diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0bf6b88..10823eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,6 +96,38 @@ jobs: run: python3 scripts/check-citations.py + # DD-045 item 0 — the DD-043 PR-3 verification harness had never run anywhere but a developer's + # shell, so several of its own assertions (jar:baked-version on a CRLF checkout, the jar stage + # grading a stale build because the compile's exit code was discarded, jvm:zero-edits passing on + # a directory it never examined) stayed broken for multiple approver rounds before anyone + # noticed. Wiring it in here turns that class of defect into a push-time failure. + # + # Scope: only `unit jar guards` — deliberately NOT `jvm` or `native`. Those two need docker and + # take 15+ minutes (native alone is a serialized ~15-minute compile); they stay manual-only, run + # by hand per the script's own header. `unit jar guards` need no docker and are what would have + # caught the findings above. + verify-dd043-pr3: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Make gradlew executable + run: chmod +x gradlew + - name: Set up Java 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + - name: Verify DD-043 PR-3 harness (unit jar guards) + run: bash scripts/verify-dd043-pr3.sh unit jar guards + - name: Upload verification run directory + if: failure() + uses: actions/upload-artifact@v4 + with: + name: verify-dd043-pr3-results + path: bench-results/verify-*/ + if-no-files-found: warn + build-and-test: runs-on: ubuntu-latest strategy: diff --git a/TODO.md b/TODO.md index 290d8be..3e8b5a1 100644 --- a/TODO.md +++ b/TODO.md @@ -1135,14 +1135,23 @@ Full rationale and the ordered item list are in `docs/ROADMAP.md`'s "Start here pointer so the debt is visible from here too. The one-line version: **PR-3 took eight approver rounds, the feature held in every one, and almost every finding was in the machinery that certifies it.** -- [ ] **0 — run the harness in CI.** No job invokes `scripts/verify-dd043-pr3.sh`; it is manual-only. - It is *not* outside the path filters any more — this PR put `'scripts/**'` in both of `ci.yml`'s - lists (`.github/workflows/ci.yml:51` push, `:79` pull_request), so a harness-only commit does - trigger the workflow; what it still does not trigger is any job that runs the harness. Being - manual-only is why `jar:baked-version` could not pass on a CRLF - checkout for three rounds and why the `jar` stage passed against a jar it never built until round - 8 ran it deliberately. `unit jar guards` needs no docker and finishes in minutes. Do this first — - the rest shorten the feedback loop; this changes when the loop closes. +- [x] **0 — run the harness in CI. Delivered.** `.github/workflows/ci.yml`'s `verify-dd043-pr3` job + (`.github/workflows/ci.yml:109`) now runs `bash scripts/verify-dd043-pr3.sh unit jar guards` on + every push and pull_request that matches the existing path filters — `jvm` and `native` stay out + of scope (docker, 15+ minutes) per a comment on the job. Both path-filter lists already covered + everything this invocation reads (`basquin-maven-injector/**`, `build.gradle`, + `basquin-init.gradle`, `gradle/**`, `gradlew`, `scripts/**`), so no filter changed. On failure the + job uploads `bench-results/verify-*/` via `actions/upload-artifact@v4` so a red run is + diagnosable from the Actions UI, not just locally. + **Proved empirically, not asserted:** an unmodified run on this branch passed 13/13 (0 failed, 0 + skipped, exit 0). The injector jar's Sisu index + (`basquin-maven-injector/src/main/resources/META-INF/sisu/javax.inject.Named`) was then changed + to name a nonexistent class, which made the built jar's index stale — the exact silent-non-discovery + shape the `jar` stage exists to catch — and re-running failed 2 rows (`unit`: 359 tests but `gradle + rc=1` from `verifyInjectorIsDiscoverable`; `jar`: `UNMEASURED: the jar build FAILED`), tallying 9 + passed / 2 failed / 0 skipped, exit 1. Restoring the file and re-running passed 13/13 again, exit 0 + — captured live via `echo "exit=$?"` immediately after the invocation. All three runs were ad hoc + (not committed as run-of-record evidence; the CI job now produces those going forward). - [x] **1 — citation-resolution CI check, whole-tree scoped. Delivered.** Built as `scripts/check-citations.py` (resolves each citation against the cited file's current text, not just the path; whole-tree, not diff-scoped — a diff-scoped version missed four dead citations in diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 467f7ce..87428bb 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -229,16 +229,21 @@ extraction; scope under "Open PRs" below). Four threads are ready to pick up, in **The pieces, in priority order:** - 0. **Run the verification harness in CI.** No job invokes `scripts/verify-dd043-pr3.sh` — it is - manual-only. (It is no longer outside the path filters: this PR added `'scripts/**'` to both of - `ci.yml`'s lists, `.github/workflows/ci.yml:51` for `push` and `:79` for `pull_request`, so a - commit touching only the harness now triggers the workflow — it just triggers no job that runs - the harness.) Manual-only is the root cause behind most of - the findings in row 1 of the table: `jar:baked-version` could not pass on a CRLF checkout for three - rounds because nothing ran it, and the `jar` stage passed against a jar it never built until round 8 - executed it deliberately. The `unit jar guards` stages need no docker and complete in minutes; wire - those into CI and the whole first row becomes a push-time failure rather than a review-round finding. - Everything below is detection; this is the one that changes when detection happens. + 0. **Run the verification harness in CI. Delivered.** The `verify-dd043-pr3` job + (`.github/workflows/ci.yml:109`) runs `bash scripts/verify-dd043-pr3.sh unit jar guards` on the + existing `push`/`pull_request` path filters — `jvm` and `native` are deliberately out of scope + (docker, 15+ minutes), stated in a comment on the job — and uploads + `bench-results/verify-*/` via `actions/upload-artifact@v4` when it fails, so a red run is + diagnosable without reproducing it locally. Manual-only was the root cause behind most of the + findings in row 1 of the table: `jar:baked-version` could not pass on a CRLF checkout for three + rounds because nothing ran it, and the `jar` stage passed against a jar it never built until + round 8 executed it deliberately. Proved this can actually fail, not merely reasoned about: an + unmodified run passed 13/13, then naming a nonexistent class in + `basquin-maven-injector/src/main/resources/META-INF/sisu/javax.inject.Named` — a stale Sisu + index, the exact silent-non-discovery shape the `jar` stage exists to catch — dropped it to 9 + passed / 2 failed / 0 skipped (exit 1: `unit` failed via `verifyInjectorIsDiscoverable`, `jar` + reported `UNMEASURED: the jar build FAILED`), and restoring the file brought it back to 13/13, + exit 0. Everything below is detection; this was the one that changed when detection happens. 1. **A citation-resolution CI check, whole-tree scoped. Built** as `scripts/check-citations.py` plus `scripts/check-citations-allowlist.txt`, wired into `.github/workflows/ci.yml` as the @@ -302,15 +307,14 @@ 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. Do **0 first**: until CI runs the harness, every other item here only shortens - the feedback loop for defects that still reach review. 1 is now built; 2-3 are the remaining - structural pieces. 4-6 are cheap once those exist. - - **Also worth noting for whoever picks this up:** `scripts/verify-dd043-pr3.sh` is now *inside* - `ci.yml`'s path filters — this PR added `'scripts/**'` to both lists - (`.github/workflows/ci.yml:51`, `:79`) so the `citation-integrity` job fires on script-only - commits. The remaining half of the gap is that no job invokes the harness, so a commit touching - only it still gets no harness run; item 0 is what closes that. + before PR-4 begins. 0 and 1 are now built; 2-3 are the remaining structural pieces. 4-6 are cheap + once those exist. + + **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 + (`.github/workflows/ci.yml:51`, `:79`) — and, since item 0, a job actually runs it: the + `verify-dd043-pr3` job (`.github/workflows/ci.yml:109`) invokes `unit jar guards` on both + `push` and `pull_request`. 2. **DD-041 — clustered exploration across replicas (the one the user asked for, for service-backed apps).** Not specced yet — so the next step is *brainstorm → spec → plan*, NOT code. DD-039 leaves