Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -1184,12 +1184,44 @@ the feature held in every one, and almost every finding was in the machinery tha
but is gitignored — the citation resolved for its author and was dead on every fresh clone
(fixed in the same pass that added this entry). Evidence for the scale that motivated building
it: `bench-results/dd043-pr3-citation-audit-2026-07-30/`.
- [ ] **2 — a stable pointer to the run of record.** Timestamped `verify-<UTC>/` names mean each new
run stales every citation to the previous one at once: **10, 10, 13 and 18** occurrences had to be
repointed by the four supersession commits, each figure read out of that commit's own message
(`16da079`, `865ba35`, `1c3ce88`, `572282a`) and counted as occurrences rather than matching lines
— `16da079` records `grep -c` reporting eight where there were ten. Add
`bench-results/RUN-OF-RECORD` and cite that.
- [x] **2 — a stable pointer to the run of record. Delivered.** Timestamped `verify-<UTC>/` names meant
each new run staled every citation to the previous one at once: **10, 10, 13 and 18** occurrences
had to be repointed by the four supersession commits, each figure read out of that commit's own
message (`16da079`, `865ba35`, `1c3ce88`, `572282a`) and counted as occurrences rather than
matching lines — `16da079` records `grep -c` reporting eight where there were ten. Added
`bench-results/RUN-OF-RECORD`, a tracked pointer **file** — not a symlink: this checkout has
`core.symlinks=false`, on which a tracked symlink materialises as a plain-text file containing its
target path rather than resolving. Format: `#`-comment and blank lines ignored, then exactly one
line naming a `bench-results/` subdirectory by name only. `scripts/check-citations.py`'s
`resolve()` substitutes a cited `bench-results/RUN-OF-RECORD/...` prefix with the directory the
pointer names before matching the tracked tree (`resolve_run_of_record()`), reusing the existing
FAILED/DEAD-PATH reporting path rather than adding a parallel one. Repointed all **14** occurrences
across the **5** files that named `verify-20260730T215842Z` (counted with `grep -o … | wc -l`, not
`grep -c`, per the lesson above) to `bench-results/RUN-OF-RECORD/`; `python3
scripts/check-citations.py`'s disposition counts are byte-identical before and after the repoint,
both runs exit 0. The three failure modes a resolver like this must never silently pass were each
proven empirically, not asserted: a pointer naming an untracked directory, a missing pointer file,
and a pointer with 0 or 2 non-comment lines each produced a `DEAD PATH` finding and `exit=1`;
restoring the pointer returned `exit=0` again every time. `scripts/verify-dd043-pr3.sh` was not
touched and does not write this file — promoting a run to run-of-record stays a deliberate, manual
edit made in the same commit that adds the new run directory, stated in the pointer file's own
comment header. **Review found a gap in that proof and it is now fixed.** The four-mode
empirical proof above only ever broke the pointer against a **sub-path** citation
(`bench-results/RUN-OF-RECORD/RESULTS.md`); it never exercised the **bare** form — this
bullet's own `bench-results/RUN-OF-RECORD/` citation two sentences up, one more citation
further down this file ("check `bench-results/RUN-OF-RECORD/` first"), and one in
`docs/ROADMAP.md` all cite the pointer that way, with nothing after the slash. In `resolve()`,
the generic `path in tracked_set` check ran BEFORE the RUN-OF-RECORD substitution, and
`bench-results/RUN-OF-RECORD` is itself a tracked file (the pointer) — so a bare citation
matched the pointer's own tracked-ness and verified clean without `resolve_run_of_record()`
ever running. All three bare citations verified clean against a pointer deliberately pointed
at a nonexistent directory. **Fixed**: the RUN-OF-RECORD branch in `resolve()` now runs first,
and a bare citation resolves to the pointer's target DIRECTORY rather than the pointer FILE
itself, so `file_cands` stays empty for it exactly as for any other directory citation instead
of accidentally matching a nearby quoted value against the pointer's own one-line text.
Re-verified against all four break modes (dangling, missing, 0-line, 2-line pointer) with all
three bare citations now each producing a `DEAD PATH` finding and `exit=1`; restoring the
pointer returns `exit=0` again.
- [ ] **3 — mutation-test the harness, not only the guards.** The script proves each of the injector's
8 guards fails when neutered; nothing proves the script's own rows do. Also: the guards stage
mutates tracked source in place, so a commit during a run is unsafe — one was observed
Expand Down Expand Up @@ -1259,7 +1291,7 @@ were recorded nowhere — the same evaporation that #95 had to go back and fix.
committed unexercised (the native mutex was held, and the `guards` stage mutates source a running
build was compiling). **Resolved 2026-07-30**: both stages ran end-to-end in the run of record,
stamped `20260730T215842Z` and made against `b980e1f` on a clean tree. All four figures come from
`bench-results/verify-20260730T215842Z/RESULTS.md`, read by label rather than by line number because
`bench-results/RUN-OF-RECORD/RESULTS.md`, read by label rather than by line number because
that header gains lines: its title line carries the stamp, its `Commit:` line the SHA and
`tree clean at run start`, its `Stages run:` line `unit jar guards jvm native`, and the line after
that **27 passed, 0 failed, 0 skipped** — including the `jvm:build`, `jvm:banner`, `native:build` and
Expand All @@ -1274,7 +1306,7 @@ were recorded nowhere — the same evaporation that #95 had to go back and fix.
`## What a pass here does and does not establish` heading, which states what a pass does and does not
establish. (Cited by heading with no line range at all: the range given here was off by one at both
ends, and a limitations list that gains a bullet invalidates any range.) Do not re-run the
native stage on the strength of this entry; check `bench-results/verify-20260730T215842Z/` first.
native stage on the strength of this entry; check `bench-results/RUN-OF-RECORD/` first.
(An earlier run, `verify-20260729T153141Z`, was **deleted** in `8cadf8a` — its B1 and B2 checks could
not fail, so it certified nothing. Do not cite it; it is not in the tree.)
- [ ] **A repo-wide line-citation audit (PR #103 round 7) found 135 wrong citations out of 547
Expand Down
14 changes: 14 additions & 0 deletions bench-results/RUN-OF-RECORD
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# bench-results/RUN-OF-RECORD — the certified run of record for DD-043 PR-3.
#
# scripts/check-citations.py resolves any cited path beginning
# `bench-results/RUN-OF-RECORD/` against the directory named on the single non-comment line
# below, so citations do not go stale every time evidence is regenerated (DD-045 item 2).
# Format: exactly one non-comment, non-blank line, naming a bench-results/ subdirectory by
# name only — no `bench-results/` prefix, no trailing slash. Zero or more than one such line
# is a malformed pointer and the checker fails loudly rather than guessing.
#
# Promoting a run to run-of-record is a DELIBERATE, MANUAL step: scripts/verify-dd043-pr3.sh
# never writes this file, so an ad hoc local run cannot silently become the cited evidence.
# Whoever certifies a new run edits the line below to name it, in the SAME COMMIT that adds
# the new bench-results/verify-<UTC>/ directory — never as a follow-up commit.
verify-20260730T215842Z
4 changes: 2 additions & 2 deletions bench-results/dd043-pr3-restvillains-2026-07-26/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ is established separately, by `scripts/verify-dd043-pr3.sh`'s `jvm` stage — di
the build (the preflight `git -C "$app" status --porcelain -- .`, whose non-zero `rc` `skip`s the whole
stage as UNMEASURED) and `jvm:zero-edits` after it
(`git status --porcelain=v2 --branch -- .` into `jvm-target-status-after.txt`), graded in
`bench-results/verify-20260730T215842Z/RESULTS.md`'s `jvm:zero-edits` row. All three are cited by
`bench-results/RUN-OF-RECORD/RESULTS.md`'s `jvm:zero-edits` row. All three are cited by
command text and row key, not by line: the script's line numbers went stale twice while this very
citation was being fixed, and any added guard row renumbers that table. The run *directory* is the part
that still has to be re-checked by hand — the previous name here was superseded and deleted while this
Expand All @@ -32,7 +32,7 @@ by the Quarkus bootstrap resolver on its own. **JVM mode only — the native cel
| 2 | Startup banner lists `basquin` under `Installed features` | `app-startup.log:25`, extracted to `banner.txt` |
| 3 | The boundary works, not just loads: driven request returns a cost line, not `miss` | `result-poll.txt`: `X-Basquin-Req: pr3-accept-1` → `/__basquin/result?id=pr3-accept-1` → `787,-684,9|0||` |
| 4 | `basquin-quarkus-deployment` fetched from the injected repo | `http-access.log` (4 GETs for it, all `200`); `build.log:31-36` (`Downloaded from basquin-injected`) |
| 5 | App tree pristine, checked once, post-hoc | `pristine-proof.txt:6,11`: a single `git status --porcelain`, empty, taken after `clean package` and after the app container ran. The before-**and**-after property (not merely after) is established by the verify run, not this artifact — in `scripts/verify-dd043-pr3.sh`, the preflight `git -C "$app" status --porcelain -- .` (before; a non-zero `rc` `skip`s the stage as UNMEASURED) and `git status --porcelain=v2 --branch -- .` into `jvm-target-status-after.txt` (after). Each is that file's only occurrence, so it is cited by command text, not by a line number that edits keep invalidating. Graded `PASS` at `bench-results/verify-20260730T215842Z/RESULTS.md`'s `jvm:zero-edits` row (row key, not line — an added guard row renumbers the table), against the same clone commit `c9b46d74…` this directory used (that run's `jvm-target-status-after.txt:1`) |
| 5 | App tree pristine, checked once, post-hoc | `pristine-proof.txt:6,11`: a single `git status --porcelain`, empty, taken after `clean package` and after the app container ran. The before-**and**-after property (not merely after) is established by the verify run, not this artifact — in `scripts/verify-dd043-pr3.sh`, the preflight `git -C "$app" status --porcelain -- .` (before; a non-zero `rc` `skip`s the stage as UNMEASURED) and `git status --porcelain=v2 --branch -- .` into `jvm-target-status-after.txt` (after). Each is that file's only occurrence, so it is cited by command text, not by a line number that edits keep invalidating. Graded `PASS` at `bench-results/RUN-OF-RECORD/RESULTS.md`'s `jvm:zero-edits` row (row key, not line — an added guard row renumbers the table), against the same clone commit `c9b46d74…` this directory used (that run's `jvm-target-status-after.txt:1`) |

Build wall time 01:03 min (`build.log`, `Total time`). On check 3's numbers: 787 ms elapsed is a
first-hit (Hibernate/Agroal warmup) figure, the −684 KB heap delta is the reactive-path GC-in-window
Expand Down
38 changes: 26 additions & 12 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ work, not cleanup of this thread.
| **DD-043** | Native + reactive targets — build-time instrumentation of a GraalVM-native Quarkus app | **Phase 0 done, gate PASSED** — **merged** as [#98](https://github.com/ianp94/basquin/pull/98) (2026-07-24). All four spikes resolved; S1 REFUTED as specified then CONFIRMED via S1b; 8 spec amendments forced, none voiding a section, plus a round-2 fix pass from the whole-branch review (spec ledger, "Round 2"). **PR-1 (#100), PR-2 (#102) merged; PR-3 open as
[#103](https://github.com/ianp94/basquin/pull/103)** — build-time injection with zero edits to the
target's tree, both halves of §5.2 passed (JVM on `rest-villains`, native on the fixture), 390 tests
(`bench-results/verify-20260730T215842Z/suite-counts.txt:1`).
(`bench-results/RUN-OF-RECORD/suite-counts.txt:1`).
§8.1 **resolved**: Apicurio's server has no native build on the 3.x line, so row 5 needs a substitute —
ranked Debezium Server (Quarkus 3.33.1.1) > Eclipse Hono HTTP adapter (3.27.4.1, reactive, heavier
infra) > Apicurio 2.6.x, the last only behind a compatibility spike since `basquin-quarkus` is pinned to
Expand Down Expand Up @@ -99,7 +99,7 @@ extraction; scope under "Open PRs" below). Four threads are ready to pick up, in
Spec §5.2's two-artifact bar passed both halves — JVM on the real `rest-villains` app
(`bench-results/dd043-pr3-restvillains-2026-07-26/`) and native on the Phase-0 fixture
(`bench-results/dd043-pr3-native-2026-07-26/`). 390 tests, 0 failures — that count comes from the
run of record, not from either acceptance directory: `bench-results/verify-20260730T215842Z/`
run of record, not from either acceptance directory: `bench-results/RUN-OF-RECORD/`
(`suite-counts.txt:1` reads `390 0`; `RESULTS.md:10`).

**Both acceptances are single-module, and no multi-module Maven reactor was ever built end-to-end
Expand All @@ -111,7 +111,7 @@ extraction; scope under "Open PRs" below). Four threads are ready to pick up, in
targets are multi-module" (`docs/superpowers/specs/2026-07-24-native-reactive-targets-design.md`,
the paragraph beginning "The injector must construct a fresh `Dependency` per `MavenProject`"). The
run of record's own "What a pass here does and does not establish" section
(`bench-results/verify-20260730T215842Z/RESULTS.md`) omits this gap; that file is fixed evidence and
(`bench-results/RUN-OF-RECORD/RESULTS.md`) omits this gap; that file is fixed evidence and
cannot be amended, so it is recorded here and in the spec instead.

**What a fresh agent most needs to know about this branch.** Two mechanisms fail *silently* if
Expand Down Expand Up @@ -166,7 +166,7 @@ extraction; scope under "Open PRs" below). Four threads are ready to pick up, in
`declaration-usability`, `sibling-scope`, `sibling-version` — seven, matching the seven
`throw new MavenExecutionException` sites in `BasquinInjector.java`), plus `skip` for the operator
opt-out, each proven able to fail when its own branch is neutered. All eight PASS in
`bench-results/verify-20260730T215842Z/RESULTS.md` as one `guards:<label>` row apiece, alongside
`bench-results/RUN-OF-RECORD/RESULTS.md` as one `guards:<label>` row apiece, alongside
`guards:restored` recording the source restored and the module suite green. Cited by **row key, not
line**: mid-table insertions in rounds 6 and 7 invalidated that line range twice, and any further
guard renumbers it again. Mind the arithmetic when restating this — eight *shapes* are closed by
Expand Down Expand Up @@ -277,10 +277,24 @@ extraction; scope under "Open PRs" below). Four threads are ready to pick up, in
not: a citation to agents.md in `docs/DESIGN-DECISIONS.md`'s DD-021 entry, a file that exists on
the authoring machine but is gitignored, so it resolved for its author and was dead on a fresh
clone (fixed in the same pass).
2. **A stable pointer to the run of record.** Timestamped directory names are why citations rot in
bulk. Add `bench-results/RUN-OF-RECORD` (a pointer file or symlink) and cite *that*, so
regenerating evidence does not invalidate every reference to it. This is the cheapest structural
fix on the list and it removes the cause rather than detecting the symptom.
2. **A stable pointer to the run of record. Delivered.** Timestamped directory names were why
citations rotted in bulk. Added `bench-results/RUN-OF-RECORD` — a tracked pointer **file**, not a
symlink (this checkout has `core.symlinks=false`, on which a tracked symlink materialises as a
plain-text file naming its target rather than resolving), holding one non-comment line naming the
run directory. `scripts/check-citations.py`'s `resolve()` substitutes a cited
`bench-results/RUN-OF-RECORD/...` prefix with the directory the pointer names before matching the
tracked tree, so a supersession now edits one file instead of repointing every citation; a
dangling, missing, or malformed (0 or 2+ non-comment-line) pointer fails the checker loudly
(`exit=1`, a `DEAD PATH` finding naming the reason) rather than passing silently — proved
empirically for all three modes. `scripts/verify-dd043-pr3.sh` never writes this file; promoting a
run is a deliberate, manual edit in the same commit that adds the new run directory. **Correction
(review found this):** that proof only ever exercised a **sub-path** citation
(`bench-results/RUN-OF-RECORD/RESULTS.md`); a **bare** `bench-results/RUN-OF-RECORD/` citation —
the exact form this file cites at `docs/ROADMAP.md:102`, and TODO.md cites twice — reached
"exact" via the generic tracked-path check before the substitution ever ran, because the pointer
is itself a tracked file, so all three bare citations verified clean against a deliberately
broken pointer. Fixed by checking the substitution first. Full account in `TODO.md`'s DD-045
item 2.
3. **Mutation-test the harness, not only the guards.** The script mutation-tests the injector's guards
(8 rows, each proven to fail when its own branch is neutered) but nothing mutation-tests the
*script's own rows*. Neuter each assertion; require its row to go red. Every entry in row 1 of the
Expand All @@ -307,8 +321,8 @@ extraction; scope under "Open PRs" below). Four threads are ready to pick up, in
it contains the pasted output of its own verification, and partial evidence is never committed.

**Entry condition:** none — this is tooling over the existing tree, and it is independently useful
before PR-4 begins. 0 and 1 are now built; 2-3 are the remaining structural pieces. 4-6 are cheap
once those exist.
before PR-4 begins. 0, 1 and 2 are now built; 3 is the remaining structural piece. 4-6 are cheap once
that exists.

**Also worth noting for whoever picks this up:** `scripts/verify-dd043-pr3.sh` is *inside*
`ci.yml`'s path filters — `'scripts/**'` is in both lists
Expand Down Expand Up @@ -350,13 +364,13 @@ time, nothing CPU-heavy during a run.

**[#103](https://github.com/ianp94/basquin/pull/103) — DD-043 PR-3, `basquin-maven-injector`.**
Build-time injection with zero edits to the target's source; both halves of spec §5.2 passed; 390 tests,
0 failures (`bench-results/verify-20260730T215842Z/suite-counts.txt:1`). Labelled `ready-for-approver`.
0 failures (`bench-results/RUN-OF-RECORD/suite-counts.txt:1`). Labelled `ready-for-approver`.
Six follow-ups are recorded in `TODO.md` under "DD-043 PR-3 follow-ups", of which **two** are now
resolved and **four** remain open — count the `- [ ]`/`- [x]` boxes in that section rather than
trusting this sentence, which has gone stale twice (round 7 added the sixth; round 9 closed the
second). The two resolved: the verify script's `jvm` and `native` stages had never been executed —
both now ran end-to-end in the run of record, stamped `20260730T215842Z`
(`bench-results/verify-20260730T215842Z/RESULTS.md`, its `Stages run:` and
(`bench-results/RUN-OF-RECORD/RESULTS.md`, its `Stages run:` and
`27 passed, 0 failed, 0 skipped` header lines — cited by label, not line number, because the header
gains lines) — and `jvm:boundary` no longer accepts an error page, since it now runs `curl -sf` and
requires `ResultStore.format`'s CSV shape.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1480,7 +1480,7 @@ two-sided property is real, but is established by `scripts/verify-dd043-pr3.sh`,
directory: dirty-tree refusal before the build (the preflight
`git -C "$app" status --porcelain -- .`) and `jvm:zero-edits` after
(`git status --porcelain=v2 --branch -- .`), surfaced in
`bench-results/verify-20260730T215842Z/RESULTS.md`'s `jvm:zero-edits` row. All three are cited by
`bench-results/RUN-OF-RECORD/RESULTS.md`'s `jvm:zero-edits` row. All three are cited by
command text and row key rather than by line, because the line numbers here were wrong once and went
stale again while being fixed. The current
`bench-results/dd043-pr3-restvillains-2026-07-26/README.md` verdict and check-5 row carry the
Expand Down
Loading
Loading