PLAN-bitmap phase 08: cross-version baselines¶
Prompt¶
Before responding to questions or discussion points in this
document, explore both repos thoroughly. Read the actual code and
ground every claim in it — the baseline generator
../instar-testdata/scripts/generate-baselines.py (its
AMEND_CASES, generate_amend_baseline, the COMMANDS dict, the
per-version dispatch, and the commit block), the consumer side in
tests/test_amend.py (TestAmendBaselineMatrix,
_make_amend_baseline_test, _baseline_version_dir) and
tests/helpers/info_json.py (normalise_info_json /
assert_info_equivalent), and the amend baselines phase plan
docs/plans/PLAN-amend-phase-07-baselines.md. Do not speculate.
Flag any uncertainty explicitly.
Phase plans live in docs/plans/ as
PLAN-bitmap-phase-NN-<descriptive>.md. The master plan is
PLAN-bitmap.md; Phases 1–7 are complete —
instar bitmap runs end-to-end and passes a 35-test qemu-img
integration suite. This is the eighth of ten phases. It spans two
repos (instar + the sibling instar-testdata) and the testdata
push is operator-gated. One commit per logical change.
Situation¶
Cross-version baselines let the integration suite run green on any
CI host regardless of its installed qemu-img version, by comparing
instar's output against a version-matched stored baseline rather
than a single live oracle. This phase adds bitmap to that
machinery, mirroring amend.
The model, and why instar's missing info bitmaps don't break
it. The baseline matrix does not compare instar-info to a
stored baseline. It runs the op with instar on a
qemu-img-created image, then reads the result with the system
qemu-img info --output=json, and compares that to a stored
qemu-img info recorded from a pure-qemu pipeline at the matching
version. qemu-img is the oracle observing instar's output. Since
qemu-img info emits the bitmaps array (format-specific.data.
bitmaps, entries {name, granularity, flags}), and instar's own
info emitting no bitmaps is irrelevant here, the amend baseline
model transfers directly (this is option (a) from the phase-8
research). What it validates: bitmap directory metadata (which
bitmaps exist, their granularity, enabled/disabled/in-use flags) is
consistent across the qemu-img version matrix when instar produces
the image. (Actual dirty-bit content is invisible to info and
is validated separately by the Phase-7 NBD x-dirty-bitmap oracle —
not part of the info-json baseline, exactly as amend's data
equivalence uses qemu-img compare, not the baseline.)
Honest value assessment. The bitmaps info format (name /
granularity / flags) has been stable since ~qemu 4.1, so unlike
info/amend (where the JSON genuinely drifts across versions,
e.g. the 8.0+ "Child node" section) the bitmap baselines will be
nearly identical across versions. The value is therefore mostly
(a) parity with the other subcommands' test scaffolding, (b)
future-proofing against any qemu info-format change, and (c)
confirming instar's on-disk bitmap layout is read-consistent
across the whole qemu-img range, not just 10.0.8. Real enough to
do; modest enough not to over-engineer.
Grounding (verified against the phase-8 research, HEAD 89b0ea5):
- Baselines live in
../instar-testdata(Makefile:469TESTDATA_PATH ?= $(CURDIR)/../instar-testdata), layoutexpected-outputs/<cmd>-info-json/<target>/<version>/<case>.{stdout. txt,stderr.txt,meta.json}. amend usesexpected-outputs/amend-info-json/qcow2/<version>/. - Generator
../instar-testdata/scripts/generate-baselines.py:AMEND_CASES(:550-559, a dict of(name, create_opts, amend_opts)tuples),generate_amend_baseline(:1837-2039, per case:qemu-img create→qemu-img amend→qemu-img info --output=json, writing the three files),COMMANDS['amend']config (:172-186,output_types: {'amend-info-json': 'json'},targets: ['qcow2']), the dispatch loop buildingoutput_root / output_type / target / version(:3018-3060), and the commit block (:3510-3557, gated bycommand_name in (...)at:3515-3518;--no-commitskips it). The version matrix is 80 compiled binariesqemu-img-binaries/x86_64/<version>/(6.0.0 → 10.2.0;get_qemu_binaries:850-873) — no docker.qemu-img bitmapexists even in 6.0.0 (no version floor). make baselines-amend(instar-testdata/Makefile:210):generate-baselines.py --command amend --no-commit. Not in the umbrellabaselines:target (operator-run).- Consumer
tests/test_amend.py:TestAmendBaselineMatrix(:645) +_make_amend_baseline_test(:716-824) — create start with systemqemu-img, run instar amend, read result with systemqemu-img info,assert_info_equivalent(self, info_stdout, stored_baseline, 'qcow2', tmp_path=path);_baseline_version_dir(:126-149) picks the baseline dir matching the host qemu major.minor (else newest); skips cases the baselinemeta.jsonrecorded as failing, or inKNOWN_AMEND_DIVERGENCES.test_amend_cases_match_baselines(:684-713) is a drift tripwire (on-disk case stems ==_BASELINE_CASES). normalise_info_json(tests/helpers/info_json.py:85-123) stripsactual-size/dirty-flag/cache-hints/random-ids/nestedvirtual-sizebut does NOT touchformat-specific.data.bitmapsnor sort it — so a multi-bitmap array is compared order- sensitively (Open question 2).- No manifest entry needed: amend/resize/dd/create self-generate
ephemeral
qemu-img createfixtures; bitmap does the same. Notests/manifest.jsonchange. - Push is operator-gated: the generator commits into
instar-testdata(unless--no-commit); the agent generates on a dedicatedinstar-testdatabranch and commits locally, and does not push — pushing to protectedmainneeds the operator'sGITLAB_TESTDATA_PUSH_TOKEN(perPLAN-amend-phase-07-baselines.md:223-237).
Mission and problem statement¶
Add bitmap to the cross-version baseline machinery:
-
Generator (
instar-testdatarepo): aBITMAP_CASEStable, agenerate_bitmap_baseline()(per case:qemu-img create→ a sequence ofqemu-img bitmap …ops →qemu-img info --output=json; write<case>.{stdout.txt,stderr.txt,meta.json}), aCOMMANDS['bitmap']config (output_types: {'bitmap-info-json': 'json'},targets: ['qcow2']), the dispatch branch, inclusion in the commitcommand_nameset, and abaselines-bitmapMakefile target. Note the one shape difference from amend: a bitmap case runs a list of bitmap invocations (e.g. add then disable), not a single command. -
Normaliser (instar repo): extend
normalise_info_jsonto sortformat-specific.data.bitmapsbyname(Open question 2), so multi-bitmap cases compare order-insensitively. Small, reusable, correct; keep it targeted to that array. -
Consumer (instar repo):
TestBitmapBaselineMatrix+_make_bitmap_baseline_testintests/test_bitmap.py(mirrorTestAmendBaselineMatrix): create start with systemqemu-img, run the case's op sequence with instar bitmap (each op viarun_instar_bitmap), read the result with systemqemu-img info --output=json,assert_info_equivalentagainst the version-matched stored baseline; plus atest_bitmap_cases_match_baselinesdrift tripwire and aKNOWN_BITMAP_BASELINE_DIVERGENCESgate. -
Generate + commit the baselines (
instar-testdatarepo): runmake baselines-bitmap(generates for the full installed version matrix), review a sample, and commit locally on aninstar-testdatabranch — do not push (operator-gated). -
The baseline-matrix tests pass against the generated baselines on the host qemu-img version; the rest of the suite and harness are unaffected.
Out of scope: coverage + differential fuzzing (Phase 9); docs
(Phase 10); pushing instar-testdata to main (operator). No
instar production changes (test-helper + test only).
Open questions¶
1. Which cases to baseline (the metadata surface)¶
Propose BITMAP_CASES['qcow2'] as (name, create_opts, [op_args…])
where each op is a qemu-img bitmap arg list (the target name is
the trailing positional; the generator supplies the tmp path):
- add-default — [['--add','b0']] ⇒ b0 auto, granularity =
cluster default (65536 at the default cluster).
- add-granularity — [['--add','-g','131072','b0']] ⇒ gran 131072.
- add-disabled — [['--add','--disable','b0']] ⇒ b0 disabled
(ordered, one invocation).
- disable — [['--add','b0'],['--disable','b0']].
- enable — [['--add','b0'],['--disable','b0'],['--enable','b0']].
- clear — [['--add','b0'],['--clear','b0']] ⇒ b0 present, auto.
- two-bitmaps — [['--add','b0'],['--add','-g','131072','b1']] ⇒
two bitmaps (exercises the array sort).
- remove-last — [['--add','b0'],['--remove','b0']] ⇒ no bitmaps
(extension dropped).
Confirm the set in 8a. Keep to compat=1.1 default cluster (bitmaps
need v3); cluster-size variation is covered by Phase 7's live
matrix, not needed in the baseline set.
2. Bitmaps-array ordering¶
normalise_info_json doesn't sort the bitmaps array; instar's and
qemu's directory order should match for identical op sequences
(both append), but sort by name to be robust — the two-bitmaps
case depends on it. Extend the normaliser (Mission §2). This is the
same order-safety the Phase-7 assert_bitmaps_equivalent already
applies; unifying it in the normaliser is cleaner.
3. Generate the full 80-version matrix, or a subset?¶
The generator iterates all installed qemu-img binaries; amend has
80 version-dirs. For parity, generate the full set (it is
mechanical, ~minutes). If runtime/size is a concern, note it — but
the convention is one dir per built binary, and the consumer picks
the host-matched dir, so a partial set would fail on hosts whose
version isn't present. Recommend the full matrix. Confirm the
instar-testdata binaries are present (research found 80).
4. Cross-repo commit + operator gating¶
instar-side changes (info_json.py sort, test_bitmap.py matrix) land
on the bitmap branch (instar repo). instar-testdata-side changes
(generator, Makefile, generated expected-outputs/bitmap-info-json/)
land on an instar-testdata branch and are committed locally but
not pushed (operator holds the push token). The plan's steps
must keep the two repos' commits separate and clearly labelled.
Confirm ../instar-testdata is a writable git repo in this
environment.
5. Value vs effort¶
Bitmap metadata is version-stable, so the baselines mostly provide parity + future-proofing (Situation). Do the standard thing for consistency, but do not gold-plate: single canonical cluster size, the ~8 cases above, no manifest fixture. If generation reveals the baselines are byte-identical across all 80 versions, that's the expected (good) outcome — record it.
Step-level guidance¶
Plan at medium effort (well-trodden generator + consumer scaffolding; the one novelty is the per-case op sequence). The generation run is mechanical but heavy; the consumer test is the part that needs care.
| Step | Effort | Model | Isolation | Brief for sub-agent |
|---|---|---|---|---|
| 8a | medium | sonnet | none | In ../instar-testdata/scripts/generate-baselines.py: add BITMAP_CASES (Open question 1), generate_bitmap_baseline() (mirror generate_amend_baseline :1837-2039, but run the case's list of qemu-img bitmap ops in order — qemu-img bitmap <op_args> <tmp> <name>; the name is the trailing token of each op list, tmp inserted before it; then qemu-img info --output=json; write the three files; record all rc's + the op lists in meta.json), COMMANDS['bitmap'] (output_types: {'bitmap-info-json':'json'}, targets:['qcow2']), the dispatch branch (mirror :3018-3060), and include 'bitmap' in the commit command_name set (:3515-3518) + a manual-commit hint. Add baselines-bitmap: to ../instar-testdata/Makefile (mirror :210). Test-generate ONE version: python scripts/generate-baselines.py --command bitmap --version <host> --no-commit and inspect the produced expected-outputs/bitmap-info-json/qcow2/<host>/*.stdout.txt (confirm the bitmaps arrays look right). Report the generator diff + a sample baseline. Do NOT commit yet. |
| 8b | medium | sonnet | none | In the instar repo (bitmap branch): (1) extend tests/helpers/info_json.py normalise_info_json to sort format-specific.data.bitmaps by name (Open question 2), guarded for missing keys; keep it minimal + add a comment. (2) Add TestBitmapBaselineMatrix + _make_bitmap_baseline_test + _baseline_version_dir/_baseline_stdout/_baseline_meta helpers to tests/test_bitmap.py (mirror test_amend.py:126-149,645,716-824): pick the host-matched expected-outputs/bitmap-info-json/qcow2/<version>/ dir, skip cases the baseline meta recorded as failing or in KNOWN_BITMAP_BASELINE_DIVERGENCES = {}, run the op sequence with run_instar_bitmap, read with system qemu-img info, assert_info_equivalent vs the stored baseline; plus test_bitmap_cases_match_baselines (on-disk stems == the case list) and _require_kvm on the guest-launching matrix tests. This step CANNOT fully run until 8c generates the baselines — so gate the matrix on the baseline dir existing (skipTest if absent), and verify compile/collection via make lint + a stestr collection run. Report the test code. |
| 8c | medium | sonnet | none | Generate + verify. In ../instar-testdata: run make baselines-bitmap (full version matrix), spot-check a few versions' outputs, and commit locally on an instar-testdata branch (e.g. bitmap-baselines) — do NOT push (operator-gated; note this in the report). Back in the instar repo: make instar, then run cd tests && ../tests/.venv/bin/stestr run test_bitmap and confirm TestBitmapBaselineMatrix now runs (not skipped) and passes against the host-version baselines, and test_bitmap_cases_match_baselines passes; make lint; pre-commit run --all-files. Mark the phase-8 row complete in docs/plans/PLAN-bitmap.md + index.md (note the testdata push is operator-gated). Report: the generation summary (versions × cases, whether baselines are identical across versions), the matrix test result, and the two repos' local commit state (instar committed; instar-testdata committed-not-pushed). |
Management session review checklist¶
- The baseline model is understood correctly: qemu-info of instar output vs stored qemu pipeline (not instar-info).
-
BITMAP_CASEScovers the metadata surface; the generator runs a per-case op sequence (the amend-vs-bitmap difference). -
normalise_info_jsonsorts the bitmaps array by name (order-safe); the change is minimal + guarded. -
TestBitmapBaselineMatrixmirrors amend; skips failing/ divergent cases;_require_kvms; the drift tripwire is present. - Baselines generated for the full version matrix; the matrix test passes against the host-matched dir.
- Cross-repo hygiene: instar changes on the bitmap branch;
instar-testdatachanges committed on its own branch and NOT pushed (operator-gated) — clearly reported. - No instar production code changed (test-helper + test only);
bitmap.bin/core.binunchanged. -
make lint/make test-rust/ thetest_bitmapstestr run /pre-commit run --all-filesgreen. - Commit messages follow conventions.
Success criteria¶
- The generator produces
expected-outputs/bitmap-info-json/qcow2/ <version>/for the full installed matrix; abaselines-bitmapMakefile target exists. normalise_info_jsonsorts the bitmaps array;TestBitmapBaselineMatrixruns instar's op sequences and matches the version-matchedqemu-imgbaselines; the drift tripwire passes.- instar-side changes are committed on the bitmap branch;
instar-testdatabaselines are committed locally and left for the operator to push (gated). - All instar gates green; no production code changed.
Back brief¶
Before executing any step, the executing agent should back brief the
operator — in particular that the baseline compares qemu-img info
of instar's output against a stored pure-qemu baseline (so instar's
missing info bitmaps are irrelevant), that a bitmap case runs a
sequence of qemu-img bitmap ops (unlike amend's single
command), that the bitmaps array must be sorted by name for
order-safety, that this phase spans two repos, and that the
instar-testdata baselines are committed locally but not pushed
(operator-gated).