Plans index¶
This page summarises every planning document in chronological order. Master plans decompose work into numbered phases, each with its own detailed plan file. Standalone plans track issues, follow-ups, or design decisions that do not require phased execution.
New plans should follow the structure in PLAN-TEMPLATE.md at the repo
root. For pre-push audits of our own work see PUSH-TEMPLATE.md (also
at the repo root).
Master plans¶
| Date | Plan | Intent | Status | Phases |
|---|---|---|---|---|
| 2026-05-08 | Distro matrix CI | Run instar's full functional test suite against installed .deb/.rpm packages on a representative matrix of Linux distributions in the GitHub merge queue, with qemu-img differential coverage |
Drafted, not started | (phases not yet written; design blocks pending) |
| 2026-05-09 | Release v0.2.0 | Cut the v0.2.0 tag and publish signed GitHub Release artifacts (tarball, .deb, .rpm) for x86_64 Linux | Complete (tagged 2026-05-09) | (no phase files; sequential gates) |
| 2026-05-10 | First public release of instar | Cargo.toml metadata, release workflow, .deb/.rpm packaging, and signing for instar's public releases (umbrella plan; v0.2.0 execution lives in PLAN-release-v0.2.md) |
In progress (phases 1-4 complete through v0.2.0; phase 5 audit mostly done; phase 6 coverage fuzzing in progress) | (phases inline) |
| 2026-05-10 | Security audit | Sweep instar for security weaknesses across the host VMM, KVM guest, call-table boundary, and format parsers, including coverage-guided fuzzing | In progress (phases 1a-5 done; phase 6 coverage fuzzing in progress) | (phases inline) |
| 2026-05-10 | Coverage-guided fuzzing | Stand up coverage-guided fuzzing across the format parsers and run sustained campaigns | In progress (steps 1-5 infrastructure merged; extended runs not yet complete) | (phases inline) |
| 2026-05-10 | Fuzz autofix workflow | Workflow that triages fuzzer-discovered crashes and proposes minimal fixes | In progress (workflow scaffolding merged; not yet exercised end-to-end) | (phases inline) |
| 2026-05-10 | Convert follow-ups | Track the deferred work from the (now-removed) convert master plan: extra qemu-img subcommands (create / map / measure / resize / snapshot / rebase / commit) and check --repair wiring |
Complete — phase 1 (all seven subcommands shipped; snapshot closed the roster) and phase 2 (check --repair, promoted to PLAN-check-repair.md, all 11 phases landed) both done |
1: subcommand parity, 2: check --repair |
| 2026-05-10 | instar measure subcommand |
Implement the measure subcommand (qemu-img parity for raw and qcow2 outputs; instar extensions for vmdk / vhd / vhdx) with cross-version baselines, integration tests, coverage-guided fuzzing, and differential fuzzing |
Complete (phases 1-10) | 1: calculators, 2: allocation scanners, 3: guest op, 4: host CLI, 5: target options, 6: baselines, 7: integration tests, 8: coverage fuzz, 9: differential fuzz, 10: docs |
| 2026-05-16 | instar create subcommand |
Implement the create subcommand (qemu-img parity for raw / qcow2 / vmdk monolithicSparse / vhd / vhdx outputs, with backing-file support, preallocation modes, cross-version info-equivalence baselines, integration tests, coverage-guided fuzzing, and differential fuzzing) |
Complete (phases 1-11) | 1: emitters, 2: guest op, 3: host CLI, 4: target options, 5: backing file, 6: preallocation, 7: baselines, 8: integration tests, 9: coverage fuzz, 10: differential fuzz, 11: docs |
| 2026-05-20 | instar resize subcommand |
Implement the resize subcommand (qemu-img parity for raw / qcow2 / vmdk monolithicSparse / vhd dynamic+fixed / vhdx dynamic, including --shrink for raw and qcow2, --preallocation modes, the [+-]SIZE syntax, a new read_output_sector call-table primitive, cross-version info-equivalence baselines, integration tests, coverage-guided fuzzing, and differential fuzzing) |
Complete (phases 1-13) | 1: skeleton, 2: qcow2 grow, 3: qcow2 shrink, 4: vhd, 5: vhdx, 6: vmdk, 7: guest op, 8: host CLI, 9: preallocation, 10: baselines, 11: integration tests, 12: fuzz, 13: docs |
| 2026-05-30 | instar rebase and instar commit subcommands |
Implement rebase (change backing-file references; both -u unsafe metadata-only mode and the default safe data-aware mode) and commit (merge overlay clusters into backing file) for qcow2 and vmdk monolithicSparse, with cross-version baselines, integration tests, coverage-guided fuzzing, and differential fuzzing. Reuses the read_output_sector call-table primitive from resize; no ABI extension required. |
Complete (phases 1-12) | 1: ABI, 2: rebase planners, 3: rebase guest, 4: rebase host, 5: rebase tests, 6: commit planners, 7: commit guest, 8: commit host, 9: commit tests, 10: fuzz, 11: diff fuzz, 12: docs |
| 2026-05-25 | resize followup-01: targeted refcount pre-pass | Lift the qcow2 grow image-size ceiling (~128 GiB at default cluster) by replacing the guest's "stage every refcount block" pre-pass with a targeted pre-pass that stages only the specific blocks the chosen grow flavour will modify. New public compute_qcow2_grow_query planner helper computes the action + required-block set; guest pre-pass dispatches on it. Bound is now "what the filesystem can hold" instead of per-cluster-size. Shrink retains its older stage-all pre-pass (separate followup). |
Complete (steps 01a-01e) | 01a: planner helper, 01b: guest pre-pass, 01c: large-image integration tests, 01d: fuzz clamp relaxation, 01e: docs |
| 2026-05-27 | Fuzzing bug backlog | Triage and fix the 44 open security-audit GitHub issues filed by coverage-guided fuzzing and differential fuzzing. Five root-cause fix phases: plan_vmdk capacity overflow, qcow2 scan_allocation out-of-bounds L2 entries, measure-calculator sum overflow, vhd/vhdx/vmdk allocated_bytes clamp, differential-fuzz external-timeout reclassification. |
Complete (phases 1-5) | 01: plan_vmdk, 02: qcow2 OOB L2, 03: measure calc overflow, 04: vhd/vhdx/vmdk clamp, 05: diff-fuzz timeouts |
| 2026-06-03 | instar map subcommand |
Implement the map subcommand (qemu-img parity for raw / qcow2 / vmdk / vhd / vhdx single-image sources, streaming per-extent emission over the guest serial channel, cross-version baselines, integration tests, coverage-guided fuzzing, and differential fuzzing). Backing-chain depth composition deferred to a follow-up. |
Complete (phases 1-9) | 1: extent iterators, 2: guest op, 3: host CLI, 4: output formatting, 5: baselines, 6: integration tests, 7: coverage fuzz, 8: differential fuzz, 9: docs |
| 2026-06-08 | instar snapshot subcommand |
Implement the snapshot subcommand (qcow2-only, mirroring qemu-img snapshot's -l/-c/-a/-d modes). List mode emits qemu-img-compatible human and JSON output; mutating modes manipulate the snapshot table, L1 copies, refcounts, and COPIED flags entirely inside the KVM guest using the existing write_input_sector primitive. Cross-version list baselines, integration tests with qemu-img check / info / compare post-op assertions, coverage-guided fuzzing of parse and refcount mutators, and differential fuzzing of random -c/-d/-a chains against qemu-img. Closes out the convert-followups subcommand roster. |
Complete (phases 1-14) | 1: ABI, 2: list planner, 3: list guest, 4: list host, 5: refcount mutators, 6: create, 7: delete, 8: apply, 9: mutate host, 10: baselines, 11: integration tests, 12: coverage fuzz, 13: differential fuzz, 14: docs |
| 2026-06-13 | June 2026 fuzzer bug backlog | Triage and fix the 10 open bug GitHub issues outstanding after the May 2026 backlog drain. Three root-cause fix phases: Fixed-VHD virtual_size overflow in plan_vhd (7 fuzz_create_emitters issues), unchecked VHDX resize sequence-number increment (2 fuzz_resize_planners issues), and qcow2 resize --shrink sub-byte refcount corruption (1 hand-filed snapshot-audit issue). |
Complete (phases 1-3: bbfdfc9, 514c52a, a54cef8) |
01: fixed-vhd overflow, 02: vhdx resize seqnum, 03: qcow2 shrink sub-byte refcount |
| 2026-06-13 | instar check --repair for QCOW2 |
Wire CheckConfig::FLAG_REPAIR (reserved but dead since the original check op) to real QCOW2 repair logic, mirroring qemu-img check -r leaks/-r all. Settles the repair safety model (tiered safe-vs-lossy repair, dry-run-by-default, in-place mutation with no mandatory backup, crash-safe write ordering guarded by the corrupt header bit, refuse-rather-than-guess) and implements leak reclamation + refcount/COPIED rebuild inside the KVM guest, reusing the src/crates/snapshot/ refcount mutators. Corrupt-fixture baselines, integration tests with post-op qemu-img check/info/compare, coverage and differential fuzzing. Promoted from convert-followups phase 2. |
Complete (all 11 phases landed) | 1: ABI + crate, 2: leak planner, 3: refcount planner, 4: guest (leaks tier), 5: guest (all tier), 6: host CLI, 7: baselines, 8: integration tests, 9: coverage fuzz, 10: differential fuzz, 11: docs |
| 2026-06-15 | instar amend subcommand |
Implement the amend subcommand (qcow2-only, mirroring qemu-img amend -o). v1 scope is the two header-only options that change no cluster/refcount data: compat=0.10\|1.1 (qcow2 v2⇔v3 version transition, with v3-only-feature downgrade blockers, refcount-width constraints, and header-extension relocation) and lazy_refcounts=on\|off (the v3 compatible-feature bit). Reuses the resize/rebase in-place-mutation idiom; new src/crates/amend/ planner crate and src/operations/amend/ guest op. Cross-version info-equivalence baselines, integration tests with post-op info/check/compare, coverage and differential fuzzing. refcount_bits, external data file, encryption, and backing-file amend deferred. Picks up the qemu-img amend sibling deferred from convert-followups. |
Complete (phases 1-9) | 1: ABI, 2: qcow2 planner, 3: guest, 4: host CLI, 5: rust tests, 6: integration tests, 7: baselines, 8: fuzz, 9: docs |
| 2026-06-21 | instar dd subcommand |
Implement the dd subcommand to upstream qemu-img dd parity (no PVE/downstream extensions). dd is convert with a windowed input: name=value operands (bs/count/skip/if/of) plus -f/-O (default output raw), a dense (non-sparse) copy, and faithful quirk replication (count shrinks-only, skip subtracts after count, skip-past-EOF ⇒ empty-but-exit-0, bs=0 rejected, short final block). Reuses convert's format writers and the run_convert lifecycle. New host name=value operand parser, guest input-windowing path, cross-version baselines, integration tests over a 14-row cross-validation matrix vs real qemu-img dd, coverage and differential fuzzing. First of the three remaining in-scope subcommands (dd, then bitmap, then bench). |
Complete | 1: ABI, 2: host operands, 3: guest raw, 4: guest formats, 5: rust tests, 6: integration tests, 7: baselines, 8: coverage fuzz, 9: differential fuzz, 10: docs |
| 2026-06-29 | instar bitmap subcommand |
Implement the bitmap subcommand (qcow2-only, mirroring qemu-img bitmap's --add/--remove/--clear/--enable/--disable/--merge actions, applied in command-line order). Manages persistent dirty bitmaps: net-new qcow2 bitmaps-extension + directory + table + data parsing in the qcow2 crate, a new src/crates/bitmap/ planner crate and src/operations/bitmap/ guest op that allocate/free clusters and maintain refcounts (reusing the snapshot/check mutators) and the autoclear-bit crash-safe ordering. Cross-validates against qemu-img bitmap via post-op qemu-img check/info, with cross-version baselines, integration tests, coverage and differential fuzzing. Leaves bench as the only unimplemented qemu-img subcommand. |
Complete (phases 1-10): instar bitmap — full qcow2 persistent-dirty-bitmap management (add/remove/clear/enable/disable/merge), qcow2-oracle integration tests + bit-for-bit merge validation, cross-version baselines, coverage + differential fuzzing, and docs; pre-existing resize bitmap-data-loss defect fixed. Leaves bench the only unimplemented qemu-img subcommand. |
1: parse ✓, 2: ABI ✓, 3: planner ✓, 4: guest ✓, 5: host CLI ✓, 6: rust tests ✓, 7: integration tests ✓, 8: baselines ✓, 9: fuzz ✓, 10: docs ✓ |
| 2026-07-06 | instar bench subcommand |
Implement the bench subcommand — the last unimplemented qemu-img subcommand, closing the 15/15 parity roster. Runs a fixed-count sequential read (or -w write) benchmark through the format layer inside the KVM guest, so the reported time measures instar's real sandboxed I/O path; instar bench vs qemu-img bench on the same image is the reproducible sandbox-overhead measurement the announcement email lacked. Byte-parity on the deterministic output surface (header line, validation, exit codes); host-Instant timing bracketed by guest markers (no guest clock exists); -d accepted but serialized in v1 (the synchronous single-buffer virtio driver has no queue depth — true depth is future work); --output json instar extension for perf-regression tracking. New pure crates/bench schedule crate, src/operations/bench/ guest op, call-table VERSION 19→20. Explicitly no cross-version baselines (timing is not comparable). |
Complete (phases 1-8): instar bench — the reframed sandboxed-path measurement (instar's own end-to-end guest→virtio→host I/O path, not qemu's block layer) with byte-parity on the deterministic surface (header line, validation, exit codes); reads on all five formats (raw, qcow2 incl. backing chains, vmdk, vhd, vhdx) and writes on raw and qcow2 incl. overlays; live-parity integration tests plus coverage and differential fuzzing, explicitly no cross-version baselines (timing is not comparable); and docs. instar now implements all 15 qemu-img subcommands — the parity roster is closed. |
1: schedule crate ✓, 2: ABI ✓, 3: guest read ✓, 4: host CLI ✓, 5: write test ✓, 6: integration tests ✓, 7: fuzz ✓, 8: docs ✓ |
| 2026-07-09 | bench qcow2 refcount growth | Let bench's qcow2 -w path grow the refcount structures (new refblocks; refcount-table relocation with a snapshot-style fsync-ordered header flip) preemptively at setup from a worst-case schedule bound, so any schedule qemu-img bench executes on the fuzzer envelope also succeeds under instar with identical virtual content and a clean qemu-img check. Retires the qcow2-write-refblock-coverage fuzzer steer-around (issues #397-#401) and restores the full cluster-size matrix to -w differential coverage. |
Complete (phases 1-4) | 01: planner, 02: guest, 03: integration, 04: fuzzer + docs |
| 2026-07-10 | qcow2 write infrastructure | Build src/crates/qcow2-write/, the missing callable "write N bytes at virtual offset X into an existing qcow2, allocating as needed" primitive: a pure planner owning cluster classification (overwrite / allocate / copy-on-write), L2 and data-cluster allocation, refcount maintenance, the shared v1 envelope gates, and the crash-safe write-ordering contract. Migrates the three existing inlined allocate-on-write compositions (commit, rebase safe mode, bench -w) onto it with byte-invisible refactor proofs, generalizes bench's refcount growth into the shared crate, and adds copy-on-write for snapshot-shared clusters (adopted per consumer as its parity oracle permits; bench lifts its internal-snapshot gate first). Phase 1 empirically pins qemu's snapshot-bearing commit/rebase behaviour — commit's blind overwrite (no nb_snapshots gate, no COPIED check) is a candidate live corruption defect that gets an interim gate if confirmed. Foundation for deferred features: amend refcount_bits, qcow2 preallocation modes, per-format write infrastructure. |
Complete (all 9 phases; 2026-07-14): phase 1 (2026-07-12) confirmed all three defects — commit silently corrupts backing snapshots, rebase corrupts snapshot-shared overlay metadata with a data-loss chain, plus an unrelated rebase 512-byte-cluster livelock; no byte-identity oracle constrains any consumer, so COW has full layout freedom. Phase 2 landed byte-idempotent refusal gates for #420, #421 and a newly-found overlay-side commit sibling defect (#423) — the corruption is unreachable pending phase-7 COW — and root-caused #422 as a guest panic (stale staged-L2 lookup slice, not a livelock, not cs=512-specific) and fixed it. Phase 3 landed src/crates/qcow2-write, the pure no_std windowed step-program planner — per-cluster classification, allocate-on-write with sub-cluster zero-fill, refcount maintenance in a single staged refblock copy, the unified envelope gates, and the crash-ordering contract as emitted data — proven by an ordering property suite (window-invariance down to a 1-step buffer, 192-run grid) and a SimDisk simulation harness that replays the step journal truncated at every Durability barrier (176 truncation points). Phase 4 (2026-07-13) migrated commit's qcow2 write path onto the crate through the new crates/qcow2-write-exec guest step executor, byte-invisibly — the new scripts/migration-proof.py before/after oracle passed 73/73 fixture combos with 0 identity failures and a 300-iteration differential-fuzz run had 0 divergences — while converting two probe-discovered silent-corruption shapes (compressed backing clusters; sparse/holed refcount tables, both stock-producible) into typed refusals and widening the backing staging caps. Phase 5 (2026-07-13) migrated rebase safe mode (including safe detach) onto the crate the same way, byte-invisibly — 69/69 proof combos with 0 identity failures and exactly 1 pre-declared beyond-EOV raw divergence with proven virtual equality, 300-iteration differential fuzz clean — converting two more probe-discovered silent-corruption shapes (holed refcount tables on the overlay, #428's sibling; extended-L2 overlays) into typed refusals, retiring the stage-everything staging caps, and identifying (not fixing) a pre-existing chain-reader zero-flag defect affecting rebase/convert/compare/bench. Phase 6 (2026-07-13) migrated bench -w onto the crate and moved bench's refcount-growth planner into the crate's new growth module; because bench's oracle is qemu-img compare + check rather than byte identity, the proof deliberately relaxes byte parity for allocating schedules — the shared planner allocates the L2 table before the data cluster, so allocating outputs are content-equivalent and check-clean but not byte-identical, while overwrite-only schedules stay byte-identical. scripts/migration-proof.py --op bench passed 56/56 combos (2 controls + 17 overwrite-only byte-identical, 34 allocating compare/check/info/flushes-issued/RT-geometry equivalent, 3 refusals) with 0 failures, 300-iteration differential fuzz clean, and the fsync census preserved exactly. A data-integrity defect the phase-6 probes found — #433, an overwrite-dominant growth schedule leaving the refcount table pointing at unmaterialized blocks past EOF — was fixed fix-first before the migration. Phase 7 (2026-07-13/14) added the crate's copy-on-write branch and adopted it in all three consumers, lifting the phase-2 interim snapshot-refusal gates and resolving #420 / #421 / #423: writes into snapshot-bearing qcow2 images now COW the shared clusters (data-cluster and L2-table COW with a net-new refcount-decrement primitive, and — a 7p correction — no child-refcount increment). commit preserves backing snapshots, rebase leaves the active view resolving through the new backing (qemu's contract), bench preserves snapshots. The proof is qemu-parity — qemu-img check clean + active-view qemu-img compare + a snapshot read-back oracle — not image-byte identity; verified across pinned qemu 6.2.0–10.2.0 and a 50-iteration soak with 0 divergences. #432 (chain-reader classic-L2 zero flag) was fixed fix-first (7z). Two follow-ups recorded: an overlay-side COW-clear primitive for full commit overlay byte-emptying, and a tighter rebase growth bound. Phase 8 (2026-07-14) fuzzed the new crate and its snapshot-bearing COW paths — two coverage-guided targets for the planner (fuzz_qcow2_write with the max_rc<3 COW invariant oracle over a Vec-backed sim harness lifted from the crate's unit tests, and fuzz_qcow2_write_growth) and the phase-7 read-back oracle scaled into the differential fuzzer's snapshot-bearing commit/rebase/bench fixtures; 0 crashes and 0 divergences, no bug found, cow-soak folded in and retired. Phase 9 (2026-07-14, docs) authored the durable docs/qcow2/qcow2-write-planner.md write-infrastructure reference, consolidated the per-op / ARCHITECTURE docs to link it, and closed out the programme (master-plan retrospective + Success Criteria confirmed all met + final acceptance gate green: make instar / lint / test-rust 1720-pass / check-binary-sizes / pre-commit clean, representative snapshot-COW smoke and a combined commit/rebase/bench differential soak with 0 divergences). All four snapshot-corruption defects (#420 / #421 / #423 / #432) are resolved. |
1: semantics pin ✓, 2: interim gates + defect handling ✓, 3: qcow2-write crate ✓, 4: migrate commit ✓, 5: migrate rebase ✓, 6: migrate bench ✓, 7: copy-on-write ✓, 8: fuzz ✓, 9: docs ✓ |
| 2026-07-17 | Format coverage expansion | Close the input-side format-coverage gap against qemu-img's real image-format roster: detection + info parity for Parallels / Bochs / cloop / DMG, convert-from read paths for VDI / Parallels / QCOW1 / DMG, a recorded decision on QED, tested refusals for the formats we choose not to read, and a qemu-img-parity axis in docs/format-coverage.md. Output formats unchanged; write/create support for new formats out of scope. |
Drafted, not started | (phase plans not yet written) 1: detection + info, 2: vdi read, 3: parallels read, 4: qcow1 read, 5: dmg read, 6: qed decision, 7: docs |