From 8196beede8a8e82032316aaf4ca56bb958b1b58c Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sat, 22 Aug 2026 21:35:46 +0000 Subject: [PATCH 1/5] spec(GATE-ISSUE-INDEX-OWNER-KEY): key the issue index on the issue AND its owning row (#1731) `check-agent-record.py` is red on `main` at `038ff61e5` because `.agents/issue-index.md` lists #1649 twice: once under `ENG-HF-MODEL-DOWNLOAD`, the lane that found and filed the bug, and once under `GATE-WINDOWS-PORTABILITY-TARGET-SCOPE`, the lane that fixed it. Neither row is wrong and neither branch could see the other. The spec argues that the ban on a second row is a leftover. It arrived in `8dd6508da`, when the surface was a keyed, editable intake table inside `roadmap_v1.md`. `51e0cb5b1` moved it out, made it append-only and gave it `merge=union`, and uniqueness by number survived that move unexamined. In an append-only log an update IS an append, so one row per issue means one statement per issue forever. The tree already pays for that twice in prose: `bpe-quadratic-merge.md` and `serve-request-length-guard.md` each record a fact that belongs in the index, because appending it would red the gate. The design keys uniqueness on `(issue number, owning row ID)` and reports both line numbers. #1619 measured the one corruption this refusal has ever caught, where the union driver duplicated a row BYTE-IDENTICALLY at two lines; a copied line carries the same owner, so the pair key still collides and that catch is unchanged. What is given up is a mistyped owner on a second row, which no reading of the file can separate from a legitimate hand-off. Spec only, so `check-agent-record.py` and `test_agent_record` stay red at this commit with the inherited #1649 duplicate. The implementation commit clears both. `test_cpu_x86_llamacpp_floor` also reds here at loadavg 45.97 with `waiting for quiet ... exit 4`, which is #618 and is not this change. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code] --- .agents/specs/gate-issue-index-owner-key.md | 253 ++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 .agents/specs/gate-issue-index-owner-key.md diff --git a/.agents/specs/gate-issue-index-owner-key.md b/.agents/specs/gate-issue-index-owner-key.md new file mode 100644 index 000000000..b78ff25c2 --- /dev/null +++ b/.agents/specs/gate-issue-index-owner-key.md @@ -0,0 +1,253 @@ +# Spec — the issue index is keyed on the issue AND its owning row + +Issue: [#1731](https://github.com/mudler/vllm.cpp/issues/1731) +Row: `GATE-ISSUE-INDEX-OWNER-KEY` (unplaced record/gate defect; the tracked tree +is a checker, not a matrix row, the same placement +[`gate-windows-portability-target-scope.md`](gate-windows-portability-target-scope.md) +uses) +State: `ACTIVE` + +## 1. Scope + +`check_issue_index` in `scripts/check-agent-record.py` refuses a second row for +an issue number. This spec narrows the uniqueness key to the pair +`(issue number, owning row ID)`, reports both offending line numbers, and pins +that the narrowing admits a second OWNER and nothing else. + +In scope: the duplicate rule in `check_issue_index`, its message, the +[`issue-index.md`](../issue-index.md) preamble sentence that tells an appending +agent which second row is legal, and the checker's copy of that preamble. + +Out of scope, each with its reason in §4: the unowned ratchet's per-row +counting, validation of the owner ID against the row inventory, a bound on how +many rows one issue may accumulate, and every other rule in +`check-agent-record.py`. + +## 2. The defect, measured + +`python3 scripts/check-agent-record.py` exits 1 on `origin/main` at +`038ff61e5`: + +``` +ERROR: .agents/issue-index.md: issue #1649 listed twice. Under `merge=union` a duplicate is what two branches appending the same issue look like +``` + +`python3 -m unittest tests.scripts.test_agent_record` on the same tree reports +109 tests and 1 failure, `test_the_tracked_index_is_valid`, for the same +duplicate. Both are inherited by every branch that merges `main`. + +The two rows are not a bad merge and not a hand edit: + +| Line | Added by | Owning row | What it records | +|---|---|---|---| +| `:592` | `a7bb3130b` | `ENG-HF-MODEL-DOWNLOAD` | the bug, and the attribution to `a50c57d69` that introduced it | +| `:632` | `2f2a70925` | `GATE-WINDOWS-PORTABILITY-TARGET-SCOPE` | the fix, plus a second red that `:592` did not record | + +One lane found and filed the bug while repairing something else. A different +lane fixed it and recorded its own ownership. Neither branch could see the +other, and `merge=union` combines two appends silently. + +Counted directly at `038ff61e5`: 620 rows, one duplicate number (`#1649`), and +**zero** duplicate `(number, owner)` pairs. The narrowed key therefore turns +`main` green on the tree that exists, without an edit to a single row. + +## 3. Why the ban is wrong, not merely inconvenient + +**It is a leftover from a different record surface.** The rule arrived in +`8dd6508da` (2026-08-09), whose message says the checker "checks that the number +and its URL agree, that no issue is listed twice, and that the table is not +empty". At that commit the surface was a KEYED intake table inside +`.agents/roadmap_v1.md`, where a row could be edited in place and one row per +issue was the whole design. `51e0cb5b1` moved the table into +[`issue-index.md`](../issue-index.md), made it append-only, and gave it +`merge=union`. Uniqueness by number survived that move unexamined. + +**In an append-only log, an update is an append.** The preamble forbids editing +a row and deleting one. A rule that permits one row per issue therefore permits +one statement per issue for the life of the repository. Ownership that moves, +a fix that lands under a different row, and a re-scoped issue then have no +legal way to reach the index. + +**The tree already pays for this, twice, in prose.** +[`bpe-quadratic-merge.md`](bpe-quadratic-merge.md) records that `#1365` was +re-scoped in place and that its index row now under-describes its own issue: +"Both available edits are gate failures, so the reconciliation is PROSE, it +lives here, and this paragraph is it." +[`serve-request-length-guard.md`](serve-request-length-guard.md) records the +same refusal for `#1541`. Two specs carry a fact that belongs in the index +because the gate would refuse it. + +**The remedy the ban forces is the operation the file forbids.** +[#1731](https://github.com/mudler/vllm.cpp/issues/1731) proposes merging the two +`#1649` rows into one, which is an edit to an append-only record. +`scripts/check-issue-index-append-only.py` refuses exactly that against the +merge base, so the ban and the append-only rule point at each other. + +**This change has to append its own second row to land.** +[`issue-index.md`](../issue-index.md) already carries a `#1731` row owned by +`ENG-RECORD-CONFLICT-SURFACES`, the standing owner of record-surface semantics. +That row's spec, +[`retire-shared-record-surfaces.md`](retire-shared-record-surfaces.md), states +"No product source, kernel or gate semantic moves", and the `#1543` row it owns +states that a checker-semantics change "owes its own row, spec, red-before test +or mutation, and green-after evidence". So the fixing row is this one, and +`AGENTS.md` requires the index, the spec, and the pull request body to agree on +the owner. Recording that agreement means appending a second `#1731` row under +`GATE-ISSUE-INDEX-OWNER-KEY`. Under the old key that append is red. It is the +change's own first legitimate case. + +## 4. Design + +`check_issue_index` keys `seen` on the pair `(number, row_id)` and stores the +line number of the first row for each pair. A repeat reports the repeating line, +the first line, and the shared owner: + +``` +.agents/issue-index.md:640: issue #1649 is listed twice under the same owner +`ENG-HF-MODEL-DOWNLOAD`, first at .agents/issue-index.md:592. ... +``` + +The line numbers are derived at read time and stored nowhere, which is the +record shape `AGENTS.md` `## Records` admits. A line number written INTO an +append-only file would go stale on the next append; a line number computed by +the checker cannot. + +Four decisions, each of which could have gone the other way: + +**A dash and an owner are different keys, and both may stand.** A row that names +no owner is owned through a spec's `## Owed`. A later row that names an owning +row ID records adoption, and adoption can only be recorded by appending. The +opposite order loses information, and it is already gated: an added dashed row +raises the unowned count and reds the `UNOWNED_HIGH_WATER` ratchet. + +**The unowned count stays per-row.** `AGENTS.md` states the obligation per row: +"Every index row names an owning row ID, or names a spec that lists the issue +under `## Owed`." Treating an issue as owned because SOME row names an owner +would lower the count, trip the ratchet's lower arm, and change a second rule in +a change that owes one. `UNOWNED_HIGH_WATER` is therefore untouched at 33, and +the count is unchanged by this change because the row it appends names an owner. + +**No cap on rows per issue.** A cap is a shared-file budget at the scale of one +issue, which `AGENTS.md` `## Records` names as the anti-pattern: "Limit an +entry, not a shared file. A shared-file budget forces each addition to remove +another entry." The third lane to touch an issue would have to delete an earlier +row, which is the forbidden edit again. + +**The owner ID is not checked against the row inventory.** It is not checked +today, and adding that check would red `main` immediately: +`GATE-WINDOWS-PORTABILITY-TARGET-SCOPE` and this row are unplaced gate rows with +no matrix entry, and both are legitimate owners. + +## 5. Risks + +The narrowing widens what the checker accepts, so the hole is named rather than +asserted away. + +**What the gate still catches, and why that is the case it was built for.** +[#1619](https://github.com/mudler/vllm.cpp/issues/1619) measured the one +corruption this refusal has ever caught: the `merge=union` driver duplicated a +row when both sides appended before the same trailing anchor, producing 538 +lines where the correct union is 537, with `#1546` BYTE-IDENTICAL at lines 523 +and 533. `git merge-tree --write-tree` called it clean and +`check-issue-index-append-only.py` passed, because a duplicate is an addition +and that checker collects removals only. `check-agent-record.py` was the single +gate that refused it. A driver duplicate copies a LINE, so both copies carry the +same owner, so the pair key collides and the refusal is unchanged. The same +holds for a rebase or a copy-paste that appends one row twice. + +**What the gate no longer catches.** Two rows for one issue under two DIFFERENT +owners, where the second owner was a mistake rather than a hand-off. No reading +of the file can separate that from the legitimate case, because the two are the +same bytes. The bound is that the mistake is visible: the row names a row ID, a +reader can follow it, and the owner ID is a reviewed field in a reviewed diff. + +**The preamble edit carries the risk the preamble describes.** This change adds +a paragraph to the [`issue-index.md`](../issue-index.md) preamble and to +`INDEX_PREAMBLE`. Under `merge=union` two branches that edit the preamble at the +same time duplicate the lines rather than merge them. The edit inserts whole new +lines and changes no existing line, so `check-issue-index-append-only.py` sees +no removal, and the preamble drift check in `check_issue_index` reports the +duplication if a second branch edits the preamble before this lands. The +alternative, leaving the rule in the checker message alone, was rejected: an +agent reads the preamble BEFORE appending and reads the message only after +redding the gate, and the wrong repair the message costs is an edit to an +append-only record. + +## 6. Tests + +`tests/scripts/test_agent_record.py`, `IssueIntakeTable`. Four cases added, one +rescoped, one already present and now passing: + +| Case | Before | After | +|---|---|---| +| `test_a_second_row_under_a_different_owner_is_a_record` | RED (`listed twice`) | green | +| `test_a_dashed_row_and_an_owned_row_are_not_a_duplicate` | RED (`listed twice`) | green | +| `test_a_duplicate_under_one_owner_names_both_line_numbers` | RED (no line numbers in the message) | green | +| `test_a_byte_identical_duplicate_row_is_rejected` | green | green | +| `test_a_duplicated_issue_is_rejected` (rescoped) | green | green | +| `test_the_tracked_index_is_valid` | RED (`#1649`) | green | + +`test_a_duplicated_issue_is_rejected` is rescoped rather than deleted. It +appended a duplicate `#201` row under a DASH while the first `#201` row is owned +by `BACKEND-ROCM`, so it asserted the old key by accident. It now appends the +duplicate under the SAME owner, which is the guarantee the case names. The +different-owner half it used to cover is not dropped; it becomes +`test_a_second_row_under_a_different_owner_is_a_record`, with the opposite +expectation and a stated reason. + +`test_a_byte_identical_duplicate_row_is_rejected` reproduces the shape +[#1619](https://github.com/mudler/vllm.cpp/issues/1619) measured, so the one +corruption this refusal has caught in the field has a case of its own. + +The three cases that pass in both directions are the guard properties. They are +proved discriminating by mutation in §7 rather than by reading. + +## 7. Gates + +Each command is run on the real tree. The BEFORE column is measured at +`038ff61e5`. The AFTER column is filled by the implementation commit, which is +why it names the command rather than a number here. + +| Gate | Before | After | +|---|---|---| +| `python3 -m unittest tests.scripts.test_agent_record` | 109 tests, 1 failure (`test_the_tracked_index_is_valid`) | every case green, four cases more | +| `python3 scripts/check-agent-record.py` | rc 1, `issue #1649 listed twice` | rc 0 | +| `python3 scripts/check-issue-index-append-only.py --base origin/main` | `OK` | `OK`, so the preamble insert and the appended row remove no line | +| `scripts/agent-preflight.sh` | not applicable at the base | all gates green | + +`git merge-base --is-ancestor origin/main HEAD` must exit 0 before any preflight +trailer result is read. `scripts/agent-preflight.sh:452-459` takes a +`TRAILER_BEHIND` arm when the head is behind the base and then reports nothing, +so a green there would mean "not checked". + +MUTATION, recorded in the pull request body with the `git diff --stat` that +proves each mutation applied and an empty `git status --porcelain` after +restoring: forcing the key back to the number alone must red exactly the cases +the narrowing is for, and forcing the key to the owner alone must red the +duplicate cases. A mutation that fails to run reads as a passing test, so the +interpreter output is quoted for each one. + +## 8. Stop conditions + +Stop and ask before repairing the STALE index rows this change makes +repairable. `#1365` and `#1541` can now be reconciled by appending a row under +the owning row, and +[`bpe-quadratic-merge.md`](bpe-quadratic-merge.md) and +[`serve-request-length-guard.md`](serve-request-length-guard.md) then carry +prose that has a better home. Each is a record edit that belongs to its own +row, and doing them here would hide the checker change under a records sweep. + +Stop and return `NEEDS_DECISION` rather than deleting a row if any tree state +appears where the narrowed key cannot turn `main` green. Deleting a row is the +operation the index forbids, and it needs an exception argued in its own commit +message. + +## 9. Now + +The narrowed key and its cases are written. `main` is green on +`check-agent-record.py` without any row being edited or deleted, and the two +`#1649` rows both stand, each under the row that wrote it. + +## 10. Outcome + +Recorded on landing. From 3cd613041ec0c98cde9db7229b4b222d63491ef1 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sat, 22 Aug 2026 21:52:04 +0000 Subject: [PATCH 2/5] fix(GATE-ISSUE-INDEX-OWNER-KEY): key the issue index on the issue AND its owning row, so filing and fixing on two branches stops redding main (#1731) `scripts/check-agent-record.py` was red on `main` at `038ff61e5` with `.agents/issue-index.md: issue #1649 listed twice`, and every branch that merged `main` inherited it. The two rows are both correct: `ENG-HF-MODEL-DOWNLOAD` recorded the bug and the attribution to `a50c57d69`, and `GATE-WINDOWS-PORTABILITY-TARGET-SCOPE` recorded the fix and a second red the first row did not carry. Neither branch could see the other. THE BAN WAS A LEFTOVER FROM A DIFFERENT RECORD SURFACE. It arrived in `8dd6508da` (2026-08-09), when the intake table was a KEYED, editable table inside `.agents/roadmap_v1.md` and one row per issue was the whole design. `51e0cb5b1` moved it into `.agents/issue-index.md`, made it append-only and gave it `merge=union`; uniqueness by issue NUMBER survived that move unexamined. In an append-only log an update IS an append, so one row per issue permits one statement per issue for the life of the repository. The tree already pays for that twice in prose: `.agents/specs/bpe-quadratic-merge.md` records that `#1365`'s row under-describes its own re-scoped issue and that "Both available edits are gate failures, so the reconciliation is PROSE", and `.agents/specs/serve-request-length-guard.md` records the same refusal for `#1541`. The remedy the ban forces is the operation the file forbids, and `scripts/check-issue-index-append-only.py` refuses that too. `check_issue_index` now keys `seen` on `(issue number, owning row ID)` and holds the line number of the first row for each pair, so the refusal names the repeating line, the first line and the shared owner instead of only the number. The line numbers are derived at read time and stored nowhere; a line number written INTO an append-only file goes stale on the next append. THE ONE CORRUPTION THIS REFUSAL HAS CAUGHT IN THE FIELD IS UNAFFECTED, which is why the ban was narrowed rather than dropped. `#1619` measured the `merge=union` driver duplicating a row BYTE-IDENTICALLY at two lines, 538 where the correct union is 537; `git merge-tree --write-tree` called it clean and `check-issue-index-append-only.py` passed, because a duplicate is an ADDITION and that checker collects removals only. `check-agent-record.py` was the single gate that refused it. A duplicated LINE carries its owner with it, so the pair key still collides, and `test_a_byte_identical_duplicate_row_is_rejected` reproduces that shape. GIVEN UP DELIBERATELY: a mistyped owner on a second row, which no reading of this file can separate from a legitimate hand-off. REJECTED DELIBERATELY: a cap on rows per issue, which is AGENTS.md #Records' "limit an entry, not a shared file" anti-pattern at the scale of one issue and would force the third lane to delete an earlier row; and an owner-ID existence check, which would red `main` on day one because `GATE-WINDOWS-PORTABILITY-TARGET-SCOPE` and this row are unplaced gate rows with no matrix entry and both are legitimate owners. `UNOWNED_HIGH_WATER` stays at 33 and the unowned count stays PER ROW, because AGENTS.md states that obligation per row and this change owes one semantic move, not two. RED FIRST, measured on the unmodified checker: `IssueIntakeTable` ran 11 tests with 4 failures -- `test_a_second_row_under_a_different_owner_is_a_record`, `test_a_dashed_row_and_an_owned_row_are_not_a_duplicate`, `test_a_duplicate_under_one_owner_names_both_line_numbers` and `test_the_tracked_index_is_valid`. After: 113 tests OK across the module, up from 109 with 1 failure, and `scripts/check-agent-record.py` on the real tree returns rc 0. MUTATION, both directions, tree restored byte-for-byte and verified by sha256. Forcing the key back to the number alone (`key = (number, None)`, sha `710224b8`) reds exactly the three admission cases including the real tree, 3 of 113. Forcing the pair to the permissive value (`first = None`, sha `8e7cfe09`) reds exactly the three refusal cases, 3 of 113. The clean file is `7abe4aa4b3a8b0d776364207396be146e58dd9d34067b9f258c106a96e12d593` before and after. `test_a_duplicated_issue_is_rejected` is rescoped, not deleted: it appended its duplicate under a DASH while the first `#201` row is owned by `BACKEND-ROCM`, so it asserted the old key by accident. The owner now matches, which is the guarantee its name claims, and the different-owner half becomes a case of its own with the opposite expectation. The preamble gains a paragraph telling an appending agent which second row is legal, mirrored into `INDEX_PREAMBLE`, because an agent reads the preamble BEFORE appending and reads a checker message only after redding the gate. It inserts whole new lines and edits none, so `scripts/check-issue-index-append-only.py` reports `OK` and `git diff origin/main --numstat -- .agents/issue-index.md` is `8 0`. This change has to append its own second `#1731` row to land, which is its first legitimate case: the existing `#1731` row names `ENG-RECORD-CONFLICT-SURFACES`, whose spec says "No product source, kernel or gate semantic moves", so the fixing row is this one and AGENTS.md requires the index, the spec and the pull request body to agree. Two record anchors in `.agents/engine-matrix.md` moved because the test insert shifted them, and they are repaired in the same change: `tests/scripts/test_agent_record.py:1397` to `:1476` and `:1465` to `:1544`. The anchor-rot bucket returns to its baseline of 31 stale. `scripts/agent-preflight.sh --staged` is green except `test_cpu_x86_llamacpp_floor`, which is `#618`: its contended leg exits 4 `NO_QUIET_WINDOW` instead of 2 at loadavg 88.06. It failed identically on the spec-only tree at loadavg 45.97, so it is the box and not this change. `git merge-base --is-ancestor origin/main HEAD` is rc 0 and RANGE_COUNT is 1, so the trailer gates ran instead of taking the `TRAILER_BEHIND` skip. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code] --- .agents/engine-matrix.md | 2 +- .agents/issue-index.md | 8 ++ .agents/specs/gate-issue-index-owner-key.md | 57 +++++++----- scripts/check-agent-record.py | 48 ++++++++-- tests/scripts/test_agent_record.py | 98 +++++++++++++++++++-- 5 files changed, 178 insertions(+), 35 deletions(-) diff --git a/.agents/engine-matrix.md b/.agents/engine-matrix.md index 50aaab69a..be6fdee8d 100644 --- a/.agents/engine-matrix.md +++ b/.agents/engine-matrix.md @@ -225,7 +225,7 @@ claims it. | `ENG-RELEASE-WINDOWS` | Native Windows x86_64 pre-alpha release extension: one adaptive MSVC/UCRT CPU bundle with AVX2 executed in CI and one Vulkan preview bundle, both deterministic ZIPs and authenticated by the existing release handoff | T0 | vLLM has no Windows release path; runtime behavior remains pinned to vLLM `555967922`. Platform substrate reference: llama.cpp `src/llama-mmap.cpp:520-590` @ `237ad9b961f009ae19ac29dbce4cd0c1251f94b3`; Win32 API is the OS authority | W14 Win32 portability/MSVC CPU, W15 deterministic ZIP/PE packaging + Vulkan, and W16 ten-tuple prerelease workflow/version/docs implemented for one PR | Linux portability/release mutation gates are local evidence only. Native `windows-2022` MSVC `/W4 /WX`, extracted runtime/ISA smokes, merged-SHA ten-tuple dry run, `v0.0.3-pre.1` publication, attestations, and exact 32-asset audit remain pending; no Windows ZIP exists yet | [windows-binary-release.md](specs/windows-binary-release.md); [#117](https://github.com/mudler/vllm.cpp/issues/117) | `ACTIVE` | `CLAIM-ENG-RELEASE-WINDOWS` | | `ENG-RELEASE-CONTAINERS` | Published OCI container images on GHCR, built by GitHub Actions: the same staged server bundle as `ENG-RELEASE-BINARIES`, shipped from one package `ghcr.io/mudler/vllm.cpp` with the lane in the tag — `:-cuda` / `-vulkan` / `-cpu`, the moving `:latest-cuda` / `:latest-vulkan` / `:latest-cpu`, and a bare `:latest` aliasing the cpu lane, with `ENTRYPOINT vllm-server`. Lanes `cuda` (one fat image covering every supported SM), `vulkan`, `cpu` (adaptive baseline); `rocm` blocked-preview, tracking its binary channel. Version tags are immutable; every `latest-` moves. Each lane is a `linux/amd64` + `linux/arm64` multi-arch manifest built on native runners — aarch64 is first-class here because GB10 (sm_121a), Thor (sm_110) and Orin (sm_87) are all arm64. The image contains the bundle and nothing else: no weights, no Python, no PyTorch, no compiler, no build tree. BOUNDARY: the GPU driver and container runtime stay on the host and are never bundled; Metal and MLX are NOT-CONTAINERIZABLE (no macOS container runtime and no Metal passthrough exists) and remain static-binary-only lanes, recorded as a permanent boundary rather than pending work. No image, workflow, registry package or pull is claimed to exist. | T0 | release image lanes `.buildkite/release-pipeline.yaml:34-170` and the published-image dependency boundary `docker/Dockerfile.cpu:262-290` @ `555967922` | `docker/Dockerfile` (cpu/vulkan/cuda targets calling the release scripts); `docker/healthcheck.sh`; `release/container-matrix.json`; `scripts/check-container-matrix.py`; `scripts/check-container-workflow.py`; `scripts/validate-container-image.py`; `scripts/container_tags.py`; `.github/workflows/containers.yml`; SIGTERM handler `src/vllm/entrypoints/openai/server_main.cpp` (`SignalShutdown`, all three `listen()` sites); the pre-existing `docker/Dockerfile.arm64` is an unrelated CPU bench cross-check | issues `#170`, `#312`, `#394`; `tests/scripts/test_check_container_matrix.py` 31/31; `test_check_container_workflow.py` 29/29; `test_check_cuda_fat_gencode.py` 7+4 subtests. **GB10 2026-08-11 (`promaxgb10-4ad8`, `sm_121a`, CUDA 13.3): arm64 cuda image 1.71 GB, 673/673 objects, ten-SM gencode audit PASS, and a REAL GPU boot -- `/health` 200, `/version` 200, in-container healthcheck, clean SIGTERM, `--gpus all`, host driver 580.159.03 injected.** cpu amd64 783 MB gated locally; cpu+vulkan amd64 green on hosted CI **arm64 cuda lane RUNTIME-VERIFIED on GB10 2026-08-11** -- the first accelerator-hardware evidence for any lane. Four defects were removed to get there, each found by building rather than reading: the CUDA 12.9 base could not compile `sm_110`, the BuildKit cache mount outlived its toolchain (both #366), Marlin gencode had drifted from the feature table and failed the audit on 14 correctly-compiled TUs (#394, blocking BOTH cuda tuples project-wide), and the validator could only ever produce build evidence because its boot smoke never passed `--gpus`. **NOT established: nothing is published to GHCR; amd64 cuda is unbuilt; the published arm64 image is SBSA (`targets/sbsa-linux`), so Tegra -- Thor `sm_110`, Orin `sm_87` -- is untested and NOT covered** **ORIN (Tegra) 2026-08-11: the SBSA image RUNS on Jetson AGX Orin `sm_87` (L4T R36.4.3, Docker 27.5.1) -- Qwen3-0.6B (rev `c1899de2`) loads and GENERATES via `/v1/completions`, tegrastats GR3D 95-97% during decode vs 14-15% idle.** Tegra needs `--runtime nvidia --gpus all`: `--gpus` alone is refused by the hook and `--runtime` alone mounts no driver | [container-images.md](specs/container-images.md); issues [#170](https://github.com/mudler/vllm.cpp/issues/170), [#312](https://github.com/mudler/vllm.cpp/issues/312), [#394](https://github.com/mudler/vllm.cpp/issues/394) | `ACTIVE` | `CLAIM-ENG-RELEASE-CONTAINERS-W1-W7` | | `ENG-DOCS-SITE` | Publish the 11 `docs/*.md` as a browsable GitHub Pages site at `https://mudler.github.io/vllm.cpp/` WITHOUT a second copy of the prose. A Hugo site at `website/` mounts `../docs` READ-ONLY and derives everything else from what is already in the files: each page title from the file's first `# H1`, the sidebar order from `website/data/nav.yaml`, and links through a Goldmark render hook (internal `.md` → site URL; the 139 `../.agents/**` and `../AGENTS.md` escapes → GitHub blob URLs, since the protocol tree is deliberately NOT published). **No file under `docs/` is modified, moved, renamed, or given front matter**, so `check-doc-checkpoint.py` and every protocol path reference keep working and there is no second surface that can drift — the whole point of the row. Custom lean layouts, NO theme and NO submodule: off-the-shelf docs themes read titles, weights and menus out of front matter this design deliberately does not have, so each would need its title partial, menu and link hook overridden anyway, and hugo-book additionally floors at Hugo 0.158 against the 0.146.3 pin CI and the local toolchain share. Hard prerequisite inside the repo: `classify_path` in `scripts/check-pr-size.py` FAILS CLOSED on `website/**` (verified: raises `ValueError: unclassified repository path`), so the classifier must learn the path or the PR cannot pass the project's own size gate. Hard prerequisite outside it: GitHub Pages must be enabled with the source set to GitHub Actions — the workflow is inert otherwise. A marketing landing page is explicitly OUT of scope (`README.md` stays the front door), as is any restructuring of `docs/`; the custom domain is parked behind the pending vLLM trademark question | T1 | NO vLLM analogue — upstream's docs are a separate mkdocs site and nothing in this row mirrors upstream *behavior*, so it carries no parity obligation. The STRUCTURAL reference is LocalAI's `.github/workflows/gh-pages.yml` (two Hugo sites merged into one Pages artifact), reduced to the docs half | read-only mount `website/hugo.toml:29`; title-from-H1 `website/layouts/partials/title.html:10`; link rewriting `website/layouts/_default/_markup/render-link.html:27`; guard `scripts/check-site.py:70`; deploy `.github/workflows/gh-pages.yml` | `tests/scripts/test_check_site.py:51,56,66,80,89,97` (6 mutation cases: clean tree, H1 stripped, doc absent from nav, nav entry with no file, duplicated entry, missing nav file); build evidence 14 pages with `docs/bench-evidence` + `docs/superpowers` absent from `public/` and no `href` ending in `.md`; 48 protocol links rewritten in `docs/status/`. NO published page is claimed: GitHub Pages is not yet enabled on the repository, which is the recorded stop condition holding this row at `GATING` | [gh-pages-docs-site.md](specs/gh-pages-docs-site.md); issue [#224](https://github.com/mudler/vllm.cpp/issues/224) | `READY` | `CLAIM-ENG-DOCS-SITE` | -| `ENG-RECORD-ANCHOR-RATCHET` | **The record's `path:line` citations were range-checked and never reported.** `check-agent-record.py` parsed BOTH forms: markdown links, and bare `` `file.cpp:123` `` through `RAW_LOCAL_ANCHOR_RE` since `ee511ca8a`. On a missing file or an out-of-range line `local_line_anchors` runs `continue`, so the bad anchor never reaches the caller, and `is_code_anchor` then answers with **any**, so one good sibling covers the rest. There was no symbol test and no report, and **32 of the 38** offenders are IN RANGE, so range-checking could not have found them. Measured at `8daa67b39`: **832 of 867** in-scope citations (**96.0%**) were already parsed and range-checked, and the **35** new to parsing sit under `.agents/`, `docs/` and `website/`; `EVIDENCED_STATES` omits `ACTIVE`/`READY` entirely and is deliberately NOT widened, because requiring an anchor there raises 85 errors across 53 rows. Even the fraction it saw was only range-checked, never checked to CONTAIN the symbol named beside it — every stale anchor found in the 2026-08-13/14 campaign was in range. LANDED as a device-leakage-shaped ratchet over a recorded baseline, never a bulk cleanup: the backlog is fixed by whoever next touches each row | T1 | none — this is our own record surface; the discipline mirrors AGENTS.md §Records ("cite the `file:line` you ported from") | parser + classifier + ratchet in `check-agent-record.py`: `scripts/check-agent-record.py::BARE_CITATION_RE` (the bare form), `scripts/check-agent-record.py::cell_citations` (both forms, with the adjacent-symbol rule), `scripts/check-agent-record.py::classify_citation` (OK / STALE / BROKEN), `scripts/check-agent-record.py::RECORD_ANCHOR_STATES` (gap 3: `ACTIVE` and `READY` join the count), `scripts/check-agent-record.py::check_record_anchors` (the two-way gate). SYMBOL-anchored rather than line-anchored as of `SPEC-DFLASH2` W2, which added a justification paragraph to this file's `KERNEL` count and shifted all five ranges by 14 lines at once -- the rot this row exists to measure, produced by an edit to the very file the row cites; budget in `scripts/record-anchor-baseline.json` | `RecordAnchorRatchet` `tests/scripts/test_agent_record.py:1397` — 10 cases, RED-first, including `test_one_good_link_does_not_cover_a_rotted_bare_citation` `tests/scripts/test_agent_record.py:1465`, the `any()` shape the rot hid in. Five mutants red it: report-only, `EVIDENCED_STATES` restored, links-only, first-citation-only, range-only. Measured baseline **38** (32 STALE + 6 BROKEN); gate wired in `scripts/agent-preflight.sh` and the `agent-record` CI job (`--report`) | [record-anchor-ratchet.md](specs/record-anchor-ratchet.md) | `ACTIVE` | `CLAIM-ENG-RECORD-ANCHOR-RATCHET` | +| `ENG-RECORD-ANCHOR-RATCHET` | **The record's `path:line` citations were range-checked and never reported.** `check-agent-record.py` parsed BOTH forms: markdown links, and bare `` `file.cpp:123` `` through `RAW_LOCAL_ANCHOR_RE` since `ee511ca8a`. On a missing file or an out-of-range line `local_line_anchors` runs `continue`, so the bad anchor never reaches the caller, and `is_code_anchor` then answers with **any**, so one good sibling covers the rest. There was no symbol test and no report, and **32 of the 38** offenders are IN RANGE, so range-checking could not have found them. Measured at `8daa67b39`: **832 of 867** in-scope citations (**96.0%**) were already parsed and range-checked, and the **35** new to parsing sit under `.agents/`, `docs/` and `website/`; `EVIDENCED_STATES` omits `ACTIVE`/`READY` entirely and is deliberately NOT widened, because requiring an anchor there raises 85 errors across 53 rows. Even the fraction it saw was only range-checked, never checked to CONTAIN the symbol named beside it — every stale anchor found in the 2026-08-13/14 campaign was in range. LANDED as a device-leakage-shaped ratchet over a recorded baseline, never a bulk cleanup: the backlog is fixed by whoever next touches each row | T1 | none — this is our own record surface; the discipline mirrors AGENTS.md §Records ("cite the `file:line` you ported from") | parser + classifier + ratchet in `check-agent-record.py`: `scripts/check-agent-record.py::BARE_CITATION_RE` (the bare form), `scripts/check-agent-record.py::cell_citations` (both forms, with the adjacent-symbol rule), `scripts/check-agent-record.py::classify_citation` (OK / STALE / BROKEN), `scripts/check-agent-record.py::RECORD_ANCHOR_STATES` (gap 3: `ACTIVE` and `READY` join the count), `scripts/check-agent-record.py::check_record_anchors` (the two-way gate). SYMBOL-anchored rather than line-anchored as of `SPEC-DFLASH2` W2, which added a justification paragraph to this file's `KERNEL` count and shifted all five ranges by 14 lines at once -- the rot this row exists to measure, produced by an edit to the very file the row cites; budget in `scripts/record-anchor-baseline.json` | `RecordAnchorRatchet` `tests/scripts/test_agent_record.py:1476` — 10 cases, RED-first, including `test_one_good_link_does_not_cover_a_rotted_bare_citation` `tests/scripts/test_agent_record.py:1544`, the `any()` shape the rot hid in. Five mutants red it: report-only, `EVIDENCED_STATES` restored, links-only, first-citation-only, range-only. Measured baseline **38** (32 STALE + 6 BROKEN); gate wired in `scripts/agent-preflight.sh` and the `agent-record` CI job (`--report`) | [record-anchor-ratchet.md](specs/record-anchor-ratchet.md) | `ACTIVE` | `CLAIM-ENG-RECORD-ANCHOR-RATCHET` | | `ENG-RECORD-CONFLICT-SURFACES` | Retire the shared record surfaces that make concurrent PRs conflict by construction. MEASURED at `origin/main` `d928e2c3` with `git merge-tree --write-tree` over every open PR: **16 of 29 conflict (55%), and 13 of the 16 conflict in bookkeeping files ONLY**, with no product code involved — `.agents/coordination.md` in 8, `.agents/NOW.md` in 5, `.agents/roadmap_v1.md` in 4, `scripts/check-public-doc-tables.py` in 4, `docs/STATUS.md` in 4, and any `src/`/`tests/` path in just 3. Three defects, each of which GUARANTEES rather than risks a collision. (1) `.agents/NOW.md` is a fixed-size shared buffer at EXACTLY 6000/6000 chars (`check-now-current.py:31`), so adding a row requires evicting another and every PR is a read-modify-write of one global — and the conflict is the LUCKY outcome, since a clean three-way merge would apply both evictions and both additions, silently dropping live rows and blowing the very budget the checker defends. (2) `STATUS_RATCHET = {"chars": 243245}` (`check-public-doc-tables.py:557`) is a hardcoded byte count of a DIFFERENT file that may only fall, so a PR owing `docs/STATUS.md` one lifecycle line must delete unrelated prose from another row to pay for it and edit the checker too; the checker's own comment at `:331` already records the failure (*"a ratchet pinned to the byte turns every concurrently merged row's one-line status edit into a spurious failure"*) and answered it with slack instead of removing the coupling. (3) `.agents/coordination.md`'s active-claims table is insert-at-one-anchor: the six ROCm GDN PRs (#334 #336 #341 #343 #345 #348) are ONE author's sequential stack that conflicts on nothing else, each appending a ~1,500-char row — the PR description, transcribed into a file every other claim also writes. It also contradicts the protocol it serves: `AGENTS.md` holds that *"History is git"* and *"There is no state log"*, yet both claims tables ARE state logs duplicating `gh pr list`, `row/` branch names and issue state; the argument that refuses a waiver registry applies unchanged to a claims registry. Precedent twice over — `policy.csv` retired in `0f3e44ee`, per-class line budgets retired 2026-08-10 because the gate fired on ordinary work. The exonerated surfaces share ONE property, one writer per file: `.agents/specs/.md` (one file per row, **zero conflicts** in the sample), the `*-matrix.md` inventories, and the append-only `.agents/benchmark-record.md`. SCOPE: remove `STATUS_RATCHET` and the doc-gating global counters while KEEPING the per-cell/per-paragraph caps (local, so they couple nothing); remove the active-claims table and derive claims from open PRs and branch names; drop `NOW.md`'s byte budget; order the roadmap's keyed tables by ID so distinct keys stop colliding at one anchor; and record the invariant — **no surface that every PR must write** — in `AGENTS.md`. No product source, kernel or gate semantic moves | T0 | NO vLLM analogue — this is local protocol machinery, so the mirror rule does not apply and no upstream `file:line` exists to port from. Governed instead by `AGENTS.md` §"Changing the rules or a checker", which requires a spec, a red-before test or mutation, and green-after evidence | - | - (spec-before-code: the red-before suites are named in the spec's Tests section — `tests/scripts/test_check_public_doc_tables.py`, `tests/scripts/test_check_now_current.py`, a mutation case per removed rule proving the obligation survives in the retained caps and `check-doc-checkpoint.py`, and a `git merge-tree` merge-shape regression that must be RED before the `NOW.md`/roadmap work and GREEN after) | [retire-shared-record-surfaces.md](specs/retire-shared-record-surfaces.md); issue [#364](https://github.com/mudler/vllm.cpp/issues/364) | `READY` | `CLAIM-ENG-RECORD-CONFLICT-SURFACES` | | `ENG-TRAILER-MERGE-ARTIFACTS` | The trailer gate rejects CORRECT commits because of paragraph placement, and that is why `main` is red on `agent-record`. `check-commit-trailers.py` reads trailers via `git interpret-trailers --parse`, which treats ONLY the final paragraph as the block; GitHub appends `Co-authored-by:` as a SEPARATE trailing paragraph on a squash merge, so a complete correct block becomes invisible and the gate reports it missing. MEASURED: piping `git show -s --format=%B dbd0d51c` into `git interpret-trailers --parse` prints nothing but the co-author line, and 13 of the last 30 commits on `main` fail the check -- unnoticed only because those runs were cancelled (#274), which HID the defect rather than causing it. FIX: fuse consecutive trailing TRAILER-SHAPED paragraphs before parsing. Nothing is relaxed -- the block must still exist, the marker must still sit above it, each declaration must still appear exactly once, and an AI co-author is still forbidden; the block is merely FOUND where the merge tool left it. A prose paragraph still terminates it. REJECTED IN FLIGHT and recorded because it is the more instructive half: a first attempt also collapsed identical duplicate trailers to fix the multi-commit-squash shape, which relaxes the uniqueness rule an existing test already pins. Rewriting that assertion to suit the change is what AGENTS.md forbids, and the distinction is real -- a doubled block is genuinely malformed and fixable at source, whereas the co-author case is a correct commit defeated by the parser. Reverted in full. SCOPE LIMIT, stated rather than implied: this fixes ONE of five observed shapes. `f64f2b71` (bot co-author) is a REAL violation the parse had been hiding and now correctly fails; `87308dea` (GitHub's `---------` separator), `b8293c88` (squash doubled the block) and `b580452d` (merge button, no trailers) stay red by design. Closing those is a merge-method change, not a checker change | T0 | NO vLLM analogue -- local protocol machinery, so the mirror rule does not apply and there is no upstream `file:line` to port from. Governed by `AGENTS.md` §"Changing the rules or a checker" | `scripts/check-commit-trailers.py:60` (`join_trailing_trailer_paragraphs`, `_is_trailer_paragraph`, and the fused `parsed_trailers`) | `tests/scripts/test_check_commit_trailers.py:1` 21 cases -- the RED-BEFORE appended-co-author case plus four GUARDS that keep the fusion bounded (doubled block still fails, contradictory declarations still fail, a no-trailer merge message still fails, prose after the block still fails), all four green before and after; closure [parity-ledger.md#L941](parity-ledger.md#L941) | [trailer-merge-artifacts.md](specs/trailer-merge-artifacts.md); issue [#406](https://github.com/mudler/vllm.cpp/issues/406) | `DONE` | `157080c8` | | `ENG-FORGE-COAUTHOR` | The forbidden-AI-trailer rule was catching ATTRIBUTION rather than an authorship claim, which is why bot-opened PRs red `main` on merge. GitHub composes the squash message itself and appends the account that opened the PR — `Co-authored-by: localai-org-maint-bot <...@users.noreply.github.com>` — and most PRs here are opened by a bot, so nearly every squash trips the AI-identity check. Real instance `f64f2b71`, invisible until #406 repaired the parse, which is why it reads as a new failure and is not one. The rule exists so an AI cannot claim it WROTE the code, and that stays; GitHub is recording who pressed the button, and the AI-involvement claim is already carried separately by `AI-Assisted` and `Assisted-by` in the same block. FIX: accept a `Co-authored-by` at a GitHub account noreply address even when the name matches an AI identity token, keyed on the FORGE'S OWN DOMAIN rather than the name so the exemption cannot be borrowed. A hand-written `Co-authored-by: Claude ` still fails; `Signed-off-by` is excluded from the exemption entirely, because a sign-off is a legal assertion about provenance rather than attribution. `AGENTS.md` records the same distinction in the same change so prose and checker cannot drift | T0 | NO vLLM analogue -- local protocol machinery, so the mirror rule does not apply and there is no upstream `file:line` to port from. Governed by `AGENTS.md` §"Changing the rules or a checker" | `scripts/check-commit-trailers.py:38` (`FORGE_ACCOUNT_EMAIL` and the forbidden-trailer skip) | `tests/scripts/test_check_commit_trailers.py:1` 25 cases -- the RED-BEFORE forge-bot case plus THREE guards that matter more than the relaxation because this LOOSENS a rule: a hand-written AI co-author still fails, `Signed-off-by` at the same noreply address still fails, and a human co-author still passes; all three green before and after. Real commit `f64f2b71` re-verified per commit | [forge-coauthor-attribution.md](specs/forge-coauthor-attribution.md); issue [#418](https://github.com/mudler/vllm.cpp/issues/418) | `ACTIVE` | `CLAIM-ENG-FORGE-COAUTHOR` | diff --git a/.agents/issue-index.md b/.agents/issue-index.md index 5cfdde5ca..910dcecd9 100644 --- a/.agents/issue-index.md +++ b/.agents/issue-index.md @@ -14,6 +14,13 @@ append a row merge without a conflict. That driver is only safe while the rule above holds. An edited row and an edited line of this preamble are duplicated rather than merged. `scripts/check-agent-record.py` gates both. +A second row for one issue is a RECORD, not a duplicate, when it names a +DIFFERENT owning row. Filing an issue and fixing it usually happen on different +branches, and an append is the only update this file allows, so a hand-off +reaches the index this way or not at all. `scripts/check-agent-record.py` +refuses a repeat of one issue under the SAME owner, which is what one row +appended twice looks like. + | Issue | Row | Title | Kind | |---:|---|---|---| | [#168](https://github.com/mudler/vllm.cpp/issues/168) | `BACKEND-CUDA-SM110` | Jetson AGX Thor (sm_110): 32B NVFP4, Tekken tokenizer blocker | feature | @@ -636,3 +643,4 @@ rather than merged. `scripts/check-agent-record.py` gates both. | [#1721](https://github.com/mudler/vllm.cpp/issues/1721) | `ENV-GPU-LEASE-METHODOLOGY` | `git stash` is repo-global across linked worktrees, so a bare `git stash pop` in one worktree consumes whatever sits at `stash@{0}` — which on this checkout belonged to another row. `git stash` on an already-clean tree saves nothing and prints nothing, but the paired `pop` still fires: it pulled `row/ENG-PUBLIC-DOC-PROJECTIONS`'s 56-file entry into an unrelated worktree, and only survived because the conflict made git KEEP the entry. 14 entries are on the stack, some labelled recovery. Same shape as #777 and #998: a resource that looks per-worktree and is per-repository | bug | | [#1725](https://github.com/mudler/vllm.cpp/issues/1725) | `BACKEND-CUDA-SM110` | `kMatmulFp8Cutlass` and `kMatmulFp8BlockScaled` fall through to the portable CPU tier and SEGFAULT on sm_110 (`test_ops_fp8_cutlass:191`, `test_ops_matmul_fp8_block_cuda:345`, measured at `0764ded2b`). The sm_110 baseline attributed them to [#960](https://github.com/mudler/vllm.cpp/issues/960), which was CLOSED COMPLETED three days earlier by `d607fec4c` -- that fix covered `QuantFp8Static` only, while these two ops are registered from TUs `CMakeLists.txt:1790-1791` builds solely for `VT_CUTLASS_FP8_ARCHS`. `cuda_matmul_fp8_block_cutlass.cu:56-58` asserts they refuse by name instead, which the measurement contradicts; `cffe59b02` has since rewritten that dispatch, and no CI lane can see either way because `cutlass-fp8` is ENABLED on the GB10 gate host | bug | | [#1731](https://github.com/mudler/vllm.cpp/issues/1731) | `ENG-RECORD-CONFLICT-SURFACES` | `check-agent-record` is RED on `main`: `#1649` is listed twice in `.agents/issue-index.md`, at `:592` (added by `a7bb3130b`, the lane that FILED it) and `:632` (added by `2f2a70925`, the lane that FIXED it). Neither is wrong and neither could see the other -- `merge=union` combines two appends silently, so a duplicate is the ordinary outcome when filing and fixing happen on different branches, and the checker only notices once both have landed on main, where every later PR inherits the red. Not repaired in flow: the index preamble forbids editing or deleting a row, and the two bodies carry different facts (`:632` has a second red and the mutation evidence, `:592` has the attribution to `a50c57d69`), so choosing which survives is a judgement | bug | +| [#1731](https://github.com/mudler/vllm.cpp/issues/1731) | `GATE-ISSUE-INDEX-OWNER-KEY` | **The `issue #N listed twice` refusal was a leftover from a KEYED table, and it red `main` for the ordinary case of one lane filing an issue and another lane fixing it.** The rule arrived in `8dd6508da` (2026-08-09), when the intake surface was an editable keyed table inside `.agents/roadmap_v1.md` where one row per issue was the whole design. `51e0cb5b1` moved the table into this file, made it append-only and gave it `merge=union`, and uniqueness by issue NUMBER survived that move unexamined. In an append-only log an update IS an append, so one row per issue permits one statement per issue for the life of the repository. MEASURED at `038ff61e5`: 620 rows, one duplicate number ([#1649](https://github.com/mudler/vllm.cpp/issues/1649), owned by `ENG-HF-MODEL-DOWNLOAD` where the lane FILED it and by `GATE-WINDOWS-PORTABILITY-TARGET-SCOPE` where the lane FIXED it), and ZERO duplicate `(number, owner)` pairs -- so narrowing the key turns `main` green with no row edited and no row deleted. The tree already paid for the old key twice in prose: [`bpe-quadratic-merge.md`](specs/bpe-quadratic-merge.md) records that [#1365](https://github.com/mudler/vllm.cpp/issues/1365)'s row under-describes its own re-scoped issue and that "Both available edits are gate failures, so the reconciliation is PROSE", and [`serve-request-length-guard.md`](specs/serve-request-length-guard.md) records the same refusal for [#1541](https://github.com/mudler/vllm.cpp/issues/1541). What the refusal DID catch is unaffected, and it is the reason the ban was not simply dropped: [#1619](https://github.com/mudler/vllm.cpp/issues/1619) measured the `merge=union` driver duplicating a row BYTE-IDENTICALLY at two lines, which `git merge-tree` called clean and `check-issue-index-append-only.py` passed because a duplicate is an ADDITION -- `check-agent-record.py` was the only gate that refused it, and a duplicated LINE carries its owner with it, so the pair key still collides. Given up deliberately: a MISTYPED owner on a second row, which no reading of this file can separate from a legitimate hand-off. Rejected deliberately: a cap on rows per issue, which is `AGENTS.md` `## Records`' "limit an entry, not a shared file" anti-pattern at the scale of one issue, and an owner-ID existence check, which would red `main` on day one because unplaced gate rows are legitimate owners. This row is itself the change's first legitimate case: [#1731](https://github.com/mudler/vllm.cpp/issues/1731) already has a row under `ENG-RECORD-CONFLICT-SURFACES`, whose spec says "No product source, kernel or gate semantic moves", so the fixing row is a different one and recording that is an append the OLD key would have refused. Spec [`gate-issue-index-owner-key.md`](specs/gate-issue-index-owner-key.md) | bug | diff --git a/.agents/specs/gate-issue-index-owner-key.md b/.agents/specs/gate-issue-index-owner-key.md index b78ff25c2..c70291c6e 100644 --- a/.agents/specs/gate-issue-index-owner-key.md +++ b/.agents/specs/gate-issue-index-owner-key.md @@ -38,11 +38,13 @@ duplicate. Both are inherited by every branch that merges `main`. The two rows are not a bad merge and not a hand edit: -| Line | Added by | Owning row | What it records | +| Line at `038ff61e5` | Added by | Owning row | What it records | |---|---|---|---| | `:592` | `a7bb3130b` | `ENG-HF-MODEL-DOWNLOAD` | the bug, and the attribution to `a50c57d69` that introduced it | | `:632` | `2f2a70925` | `GATE-WINDOWS-PORTABILITY-TARGET-SCOPE` | the fix, plus a second red that `:592` did not record | +The line numbers are read at `038ff61e5` and move on the next append, which is why the rows are identified by their commit here. + One lane found and filed the bug while repairing something else. A different lane fixed it and recorded its own ownership. Neither branch could see the other, and `merge=union` combines two appends silently. @@ -204,28 +206,41 @@ proved discriminating by mutation in §7 rather than by reading. ## 7. Gates -Each command is run on the real tree. The BEFORE column is measured at -`038ff61e5`. The AFTER column is filled by the implementation commit, which is -why it names the command rather than a number here. +Measured on the real tree. BEFORE is `origin/main` at `038ff61e5`; AFTER is this +branch at the implementation commit. | Gate | Before | After | |---|---|---| -| `python3 -m unittest tests.scripts.test_agent_record` | 109 tests, 1 failure (`test_the_tracked_index_is_valid`) | every case green, four cases more | -| `python3 scripts/check-agent-record.py` | rc 1, `issue #1649 listed twice` | rc 0 | -| `python3 scripts/check-issue-index-append-only.py --base origin/main` | `OK` | `OK`, so the preamble insert and the appended row remove no line | -| `scripts/agent-preflight.sh` | not applicable at the base | all gates green | - -`git merge-base --is-ancestor origin/main HEAD` must exit 0 before any preflight -trailer result is read. `scripts/agent-preflight.sh:452-459` takes a +| `python3 -m unittest tests.scripts.test_agent_record` | 109 tests, 1 failure (`test_the_tracked_index_is_valid`) | 113 tests, `OK` | +| `python3 -m unittest tests.scripts.test_agent_record.IssueIntakeTable` | 11 tests, 4 failures | 11 tests, `OK` | +| `python3 scripts/check-agent-record.py` | rc 1, `issue #1649 listed twice` | rc 0, `agent record OK: ENGINE=170 MODEL=377 QUANT=84 KERNEL=57 BACKEND=85 ANCHOR-ROT=37` | +| `python3 scripts/check-issue-index-append-only.py --base origin/main` | `OK` | `OK` | +| `git diff origin/main --numstat -- .agents/issue-index.md` | n/a | `8 0`, additions only | +| `scripts/agent-preflight.sh --staged` | n/a | green except `test_cpu_x86_llamacpp_floor` | + +`test_cpu_x86_llamacpp_floor` is [#618](https://github.com/mudler/vllm.cpp/issues/618). +Its contended leg exits 4 (`NO_QUIET_WINDOW`) instead of 2 at loadavg 88.06, and +it failed the same way on the spec-only tree at loadavg 45.97. That earlier run +is the control: it holds none of this change's code. + +`git merge-base --is-ancestor origin/main HEAD` exits 0 and `RANGE_COUNT` is 1, +so the trailer gates ran. `scripts/agent-preflight.sh:452-459` takes a `TRAILER_BEHIND` arm when the head is behind the base and then reports nothing, -so a green there would mean "not checked". +so a green there without this check would mean "not checked". + +MUTATION, both directions, on the real tree. `scripts/check-agent-record.py` is +`7abe4aa4b3a8b0d776364207396be146e58dd9d34067b9f258c106a96e12d593` before and +after, verified with `sha256sum -c`. + +| Mutation | File sha256 while mutated | Result | +|---|---|---| +| `key = (number, None)`, the pre-#1731 predicate | `710224b8...` | 3 of 113 red: the two admission cases and `test_the_tracked_index_is_valid` | +| `first = None`, maximal widening | `8e7cfe09...` | 3 of 113 red: `test_a_duplicated_issue_is_rejected`, `test_a_byte_identical_duplicate_row_is_rejected`, `test_a_duplicate_under_one_owner_names_both_line_numbers` | -MUTATION, recorded in the pull request body with the `git diff --stat` that -proves each mutation applied and an empty `git status --porcelain` after -restoring: forcing the key back to the number alone must red exactly the cases -the narrowing is for, and forcing the key to the owner alone must red the -duplicate cases. A mutation that fails to run reads as a passing test, so the -interpreter output is quoted for each one. +The first mutation leaves `test_a_duplicate_under_one_owner_names_both_line_numbers` +green, correctly: that case asserts the MESSAGE, which the mutation does not +touch. Each mutated file was read back by `grep` for its marker before the run, +so neither mutation could read as passing by never having applied. ## 8. Stop conditions @@ -244,10 +259,12 @@ message. ## 9. Now -The narrowed key and its cases are written. `main` is green on +The narrowed key and its cases landed with this change. `main` is green on `check-agent-record.py` without any row being edited or deleted, and the two `#1649` rows both stand, each under the row that wrote it. ## 10. Outcome -Recorded on landing. +Recorded when the row reaches `DONE`. The measurements are in §7, and the two +decisions most likely to be revisited are in §4: no cap on rows per issue, and +no owner-ID existence check. diff --git a/scripts/check-agent-record.py b/scripts/check-agent-record.py index b06a36811..94fbec3a7 100644 --- a/scripts/check-agent-record.py +++ b/scripts/check-agent-record.py @@ -1895,6 +1895,13 @@ def check_spec_location(errors: list[str]) -> None: above holds. An edited row and an edited line of this preamble are duplicated rather than merged. `scripts/check-agent-record.py` gates both. +A second row for one issue is a RECORD, not a duplicate, when it names a +DIFFERENT owning row. Filing an issue and fixing it usually happen on different +branches, and an append is the only update this file allows, so a hand-off +reaches the index this way or not at all. `scripts/check-agent-record.py` +refuses a repeat of one issue under the SAME owner, which is what one row +appended twice looks like. + | Issue | Row | Title | Kind | |---:|---|---|---| """ @@ -1969,10 +1976,28 @@ def check_issue_index( else: errors.append(f"{label}: preamble is shorter than the checker's copy") - seen: set[str] = set() + # Keyed on the PAIR (issue, owning row), never on the issue alone (#1731). + # This file is append-only, so an UPDATE is an append: a fix that lands + # under a different row, and a row that adopts an issue owned through a + # spec's `## Owed`, can reach the index only by appending a second row. + # Keying on the number alone permitted one statement per issue for the life + # of the repository, and it red `main` on #1649 for the ordinary case of one + # lane filing and another lane fixing. + # + # The corruption this refusal was earning its keep against is unaffected. + # #1619 measured the `merge=union` driver duplicating a row BYTE-IDENTICALLY + # at two lines, which `git merge-tree` called clean and + # `check-issue-index-append-only.py` passed because a duplicate is an + # addition. A duplicated LINE carries its owner with it, so the pair still + # collides. + # + # The value is the line number of the first row for the key. It is derived + # here and stored nowhere: a line number written INTO an append-only file + # goes stale on the next append, silently. + seen: dict[tuple[str, str | None], int] = {} rows = 0 unowned: list[str] = [] - for line in text.splitlines(): + for line_no, line in enumerate(text.splitlines(), 1): # Any table line that is not the header or the separator. Matching only # `| [#` would make a row that LOST its link invisible instead of # malformed, which is the failure this loop exists to report. @@ -1989,12 +2014,23 @@ def check_issue_index( number, url, url_number, row_id = match.group(1), match.group(2), match.group(3), match.group(4) if number != url_number: errors.append(f"{label}: issue #{number} links to {url}, a different issue") - if number in seen: + key = (number, row_id) + first = seen.get(key) + if first is None: + seen[key] = line_no + else: + owner = ( + f"under the same owner `{row_id}`" + if row_id is not None + else "and neither row names an owner" + ) errors.append( - f"{label}: issue #{number} listed twice. Under `merge=union` a " - "duplicate is what two branches appending the same issue look like" + f"{label}:{line_no}: issue #{number} is listed twice {owner}, " + f"first at {label}:{first}. Under `merge=union` a duplicate is " + "what ONE row appended twice looks like. A second row for one " + "issue is a record when it names a DIFFERENT owning row, and a " + "repeat under the same owner is a duplicate" ) - seen.add(number) if row_id is None and number not in owed: unowned.append(number) diff --git a/tests/scripts/test_agent_record.py b/tests/scripts/test_agent_record.py index 7f6432464..43bb4bcd0 100644 --- a/tests/scripts/test_agent_record.py +++ b/tests/scripts/test_agent_record.py @@ -913,16 +913,95 @@ def test_a_link_pointing_at_a_different_issue_is_rejected(self): errors = self.run_check(section) self.assertTrue(any("a different issue" in e for e in errors), errors) + # The line number of the first row of the table, derived rather than + # written down. A constant here would go stale the moment the preamble + # gains a line, and it would go stale silently. + FIRST_ROW_LINE = agent_record.INDEX_PREAMBLE.count("\n") + 1 + def test_a_duplicated_issue_is_rejected(self): - """Under `merge=union` this is what two branches appending one issue - produce. The driver combines silently, so this check is the only thing - that reports it.""" + """Under `merge=union` this is what ONE row appended twice looks like. + The driver combines silently, so this check is the only thing that + reports it. + + RESCOPED for #1731. The case used to append the duplicate under a DASH + while the first `#201` row is owned by `BACKEND-ROCM`, so it asserted + the old number-only key by accident. The owner now matches, which is + the guarantee the name claims. The different-owner half it used to + cover moved to `test_a_second_row_under_a_different_owner_is_a_record`, + with the opposite expectation. + """ section = self.GOOD + ( - "| [#201](https://github.com/mudler/vllm.cpp/issues/201) | — | dup | bug |\n" + "| [#201](https://github.com/mudler/vllm.cpp/issues/201) | `BACKEND-ROCM` | dup | bug |\n" ) - errors = self.run_check(section, mark=2) + errors = self.run_check(section) + self.assertTrue(any("listed twice" in e for e in errors), errors) + + def test_a_byte_identical_duplicate_row_is_rejected(self): + """The shape #1619 MEASURED, and the only corruption this refusal has + caught in the field. + + The `merge=union` driver duplicated a row when both sides appended + before the same trailing anchor: 538 lines where the correct union is + 537, with `#1546` byte-identical at two lines. `git merge-tree` called + it clean and `check-issue-index-append-only.py` passed, because a + duplicate is an ADDITION and that checker collects removals only. A + copied line carries its owner with it, so the pair key collides. + """ + row = "| [#201](https://github.com/mudler/vllm.cpp/issues/201) | `BACKEND-ROCM` | x | bug |\n" + # The row copied is the one already in the fixture, or the case would + # be testing a row it invented rather than a duplicated one. + self.assertIn(row, self.GOOD) + errors = self.run_check(self.GOOD + row) self.assertTrue(any("listed twice" in e for e in errors), errors) + def test_a_second_row_under_a_different_owner_is_a_record(self): + """#1731. One lane files an issue, another lane fixes it and records + its own ownership. The index is append-only, so an update IS an append + and this is the only legal way to record the hand-off. + + MEASURED on `main` at `038ff61e5`: #1649 carried exactly this shape, + `ENG-HF-MODEL-DOWNLOAD` at `:592` and + `GATE-WINDOWS-PORTABILITY-TARGET-SCOPE` at `:632`, and the gate refused + the whole tree for it. + """ + section = self.GOOD + ( + "| [#201](https://github.com/mudler/vllm.cpp/issues/201) | " + "`GATE-WINDOWS-PORTABILITY-TARGET-SCOPE` | fixed under a second row | bug |\n" + ) + self.assertEqual(self.run_check(section), []) + + def test_a_dashed_row_and_an_owned_row_are_not_a_duplicate(self): + """Adoption. `#85` is owned through a spec's `## Owed` and a row later + takes it, which an append-only file can record only by appending. + + The opposite order loses information and is already gated: a dashed row + appended after an owned one raises the unowned count and reds the + `UNOWNED_HIGH_WATER` ratchet. + """ + section = self.GOOD + ( + "| [#85](https://github.com/mudler/vllm.cpp/issues/85) | `BACKEND-ROCM` | adopted | bug |\n" + ) + self.assertEqual(self.run_check(section), []) + + def test_a_duplicate_under_one_owner_names_both_line_numbers(self): + """#1731 asked for the two lines rather than only the number. Reading a + 620-row append-only file for the second copy by hand is the cost the + message used to impose. + + The numbers are derived at read time and stored nowhere, which is the + record shape AGENTS.md admits. A line number written INTO the index + would go stale on the next append. + """ + section = self.GOOD + ( + "| [#201](https://github.com/mudler/vllm.cpp/issues/201) | `BACKEND-ROCM` | dup | bug |\n" + ) + errors = self.run_check(section) + self.assertEqual(len(errors), 1, errors) + # The repeat is the third row; the first `#201` row is the first. + self.assertIn(f":{self.FIRST_ROW_LINE + 2}:", errors[0]) + self.assertIn(f":{self.FIRST_ROW_LINE}", errors[0]) + self.assertIn("BACKEND-ROCM", errors[0]) + def test_the_tracked_index_is_valid(self): errors = [] agent_record.check_issue_index(errors) @@ -1742,9 +1821,12 @@ class says that, by tying the pin to the row the matrix carries. This class asserts nothing about `.agents/issue-index.md`, where the sibling classes assert their issue number, and this change appends no row there. - #1365's row already landed in `9e1a5e573` and a second row for one issue - number is what `check-agent-record.py` reports as `issue #1365 listed - twice`. The row's TEXT is stale, because #1365 was re-scoped in place from + #1365's row already landed in `9e1a5e573`. When this class was written a + second row for one issue number was what `check-agent-record.py` reported + as `issue #1365 listed twice`; since #1731 the key is the issue AND its + owning row, so a second row under a DIFFERENT owner is admitted and the + reconciliation this paragraph goes on to describe is now available to the + row that owns the cause. The row's TEXT is stale, because #1365 was re-scoped in place from the symptom onto the cause after the row landed, so `assertIn("issues/1365)", index)` would pass here against a row describing the symptom and would measure nothing about this row's work. The staleness is recorded in the From a3605673a60d2a0b47ea62602c2a3c5659b59f44 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sun, 23 Aug 2026 00:44:01 +0000 Subject: [PATCH 3/5] evidence(GATE-ISSUE-INDEX-OWNER-KEY): re-measure the gates, name the tree each number came from, and replace two unreproducible mutation hashes (#1731) The section named ONE "before" tree and quoted two numbers taken on two different ones. `IssueIntakeTable` has SEVEN cases on `origin/main`, exactly one of which fails; the recorded "11 tests, 4 failures" needs this branch's suite to exist at all, so it described the mixed tree under `origin/main`'s name. The table now carries three named columns -- `main`, the mixed red-first tree, and this branch -- and every number in it was taken at `66f055248`. The two mutation hashes could not be reproduced from the mutation text printed beside them. Re-measured in bare, single-substitution form so a reader can reproduce each: `first = None` is `cf8eea17...` and reds 3 of 113, `key = (number, None)` is `a14213fc...` and reds a DISJOINT 3 of 113, and a third mutation dropping the line numbers from the message is `fcddaa08...` and reds the one case that asserts them. Disjoint sets are the property worth having: one mutation proves the refusal still refuses, the other proves the narrowing is what admits the hand-off, and neither alone shows both. Two instrument failures are recorded because each would have read as a pass. The import check reported `AttributeError: 'NoneType' object has no attribute '__dict__'` on the PRISTINE file -- `@dataclass` resolves `__module__` through `sys.modules` and the module was not registered there -- so every mutant would have been reported as "does not build". It is now validated in both directions before use. Separately the harness was killed by a timeout part-way through the third mutation and left the tree at `fcddaa08...`; the restoration is proved by hash, not by the harness having finished. `UNOWNED_HIGH_WATER` needs no adjustment: 33 before and after, with 33 unowned rows on the branch, because the appended row names an owner. Also records the concurrent `row/FIX-ISSUE-INDEX-1649-DUP` lane and credits its two findings, both re-measured here first. #1733 duplicates #1731 by 17 minutes and its bold claim that the repair "is NOT blocked" is false, because `check-issue-index-append-only.py:50-51` diffs a COMMIT range: the same deleted bytes give rc 0 uncommitted and rc 1 committed. If this row lands, that lane's row deletion becomes unnecessary. No checker, test or index byte changes here. The spec is the only file touched. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code] --- .agents/specs/gate-issue-index-owner-key.md | 178 ++++++++++++++++---- 1 file changed, 147 insertions(+), 31 deletions(-) diff --git a/.agents/specs/gate-issue-index-owner-key.md b/.agents/specs/gate-issue-index-owner-key.md index c70291c6e..d11e718dc 100644 --- a/.agents/specs/gate-issue-index-owner-key.md +++ b/.agents/specs/gate-issue-index-owner-key.md @@ -175,6 +175,50 @@ agent reads the preamble BEFORE appending and reads the message only after redding the gate, and the wrong repair the message costs is an edit to an append-only record. +### The other repair, and why this one makes it unnecessary + +A concurrent lane took the opposite approach on branch +`row/FIX-ISSUE-INDEX-1649-DUP`: DELETE the `:592` row as an append-only +exception argued in its own commit message. Both repairs turn `main` green. +They differ in what they cost. The deletion spends a row of the record and an +argued exception on a single instance; the narrowed key spends a checker change +and leaves both rows standing. If this row lands, the deletion is unnecessary, +and whoever reads both branches should treat this one as the live repair. If +this row is rejected, the deletion is still available and nothing here blocks +it. + +Two findings below are that lane's, credited to it. Both were re-measured here +before being written down, because relaying an unverified finding is +publishing it. + +**[#1733](https://github.com/mudler/vllm.cpp/issues/1733) is a duplicate of +[#1731](https://github.com/mudler/vllm.cpp/issues/1731), and its central claim +is false.** It was filed 17 minutes and 22 seconds after #1731 against the same +red (2026-08-22 21:08:35Z and 21:25:57Z) and closed `NOT_PLANNED`. Its body +states in bold that "**The repair is measured and it is NOT blocked**". It is +not, and the reason is an instrument artifact rather than a mistake in reading +the code. + +**`check-issue-index-append-only.py` reads COMMITS, so an uncommitted deletion +is invisible to it.** `scripts/check-issue-index-append-only.py:50-51` diffs +`merge-base(origin/main, HEAD)..HEAD`, a commit range. #1733 measured its repair +by "removing one of the two rows in a worktree and running both checkers", which +is a WORKING-TREE removal the range cannot see. Both halves were reproduced +here: + +| Deletion of `:599`, the `ENG-HF-MODEL-DOWNLOAD` `#1649` row | working tree `--numstat` | checker's own range `--numstat` | checker | +|---|---|---|---| +| uncommitted | `0 1` | `8 0` | `OK: issue index append-only`, rc 0 | +| the same bytes, committed | `0 1` | `8 1` | `FAIL: ... is append-only, and this range removes or edits lines`, rc 1 | + +The committed run was made on a throwaway branch that was deleted afterwards; +this branch's head was `c93258f49` before and after it, and the index file was +byte-identical to its pre-probe hash. #1733's own body contains the mechanism +one sentence before the wrong conclusion, noting that a removal "does red it +only when the duplicate is also reachable from the base of the branch making the +repair" — which is exactly this case, since both `#1649` rows are on `main` and +therefore reachable from any branch's merge base. + ## 6. Tests `tests/scripts/test_agent_record.py`, `IssueIntakeTable`. Four cases added, one @@ -206,41 +250,113 @@ proved discriminating by mutation in §7 rather than by reading. ## 7. Gates -Measured on the real tree. BEFORE is `origin/main` at `038ff61e5`; AFTER is this -branch at the implementation commit. +Every number below was re-measured for this section at `66f055248`, the merge of +`origin/main` `1a1d17e53` into this branch. The section previously named ONE +"before" tree and quoted two numbers that came from two different ones, so each +column now says which tree it was taken on. Three trees are involved: -| Gate | Before | After | -|---|---|---| -| `python3 -m unittest tests.scripts.test_agent_record` | 109 tests, 1 failure (`test_the_tracked_index_is_valid`) | 113 tests, `OK` | -| `python3 -m unittest tests.scripts.test_agent_record.IssueIntakeTable` | 11 tests, 4 failures | 11 tests, `OK` | -| `python3 scripts/check-agent-record.py` | rc 1, `issue #1649 listed twice` | rc 0, `agent record OK: ENGINE=170 MODEL=377 QUANT=84 KERNEL=57 BACKEND=85 ANCHOR-ROT=37` | -| `python3 scripts/check-issue-index-append-only.py --base origin/main` | `OK` | `OK` | -| `git diff origin/main --numstat -- .agents/issue-index.md` | n/a | `8 0`, additions only | -| `scripts/agent-preflight.sh --staged` | n/a | green except `test_cpu_x86_llamacpp_floor` | - -`test_cpu_x86_llamacpp_floor` is [#618](https://github.com/mudler/vllm.cpp/issues/618). -Its contended leg exits 4 (`NO_QUIET_WINDOW`) instead of 2 at loadavg 88.06, and -it failed the same way on the spec-only tree at loadavg 45.97. That earlier run -is the control: it holds none of this change's code. - -`git merge-base --is-ancestor origin/main HEAD` exits 0 and `RANGE_COUNT` is 1, -so the trailer gates ran. `scripts/agent-preflight.sh:452-459` takes a -`TRAILER_BEHIND` arm when the head is behind the base and then reports nothing, -so a green there without this check would mean "not checked". - -MUTATION, both directions, on the real tree. `scripts/check-agent-record.py` is +- **T-main**: `origin/main` at `1a1d17e53`. The checker, the suite, the index + and the engine matrix all from `main`. +- **T-mixed**: this branch's suite, index and matrix with `main`'s CHECKER in + place. The red-first tree: the new cases against the old predicate. +- **T-branch**: this branch as it stands. + +| Gate | T-main | T-mixed | T-branch | +|---|---|---|---| +| `python3 tests/scripts/test_agent_record.py` | 109 tests, 1 failure | 113 tests, 5 failures | 113 tests, `OK` | +| `python3 -m unittest tests.scripts.test_agent_record.IssueIntakeTable` | 7 tests, 1 failure | 11 tests, 4 failures | 11 tests, `OK` | +| `python3 scripts/check-agent-record.py` | rc 1, `issue #1649 listed twice` | — | rc 0, `agent record OK: ENGINE=170 MODEL=377 QUANT=84 KERNEL=57 BACKEND=85 ANCHOR-ROT=37` | +| `python3 scripts/check-issue-index-append-only.py` | `OK` | — | `OK` | +| `git diff origin/main --numstat -- .agents/issue-index.md` | n/a | n/a | `8 0`, additions only | + +The correction matters because the earlier "11 tests, 4 failures" was labelled +`origin/main`, where `IssueIntakeTable` has SEVEN cases and exactly one of them +fails. Eleven cases exist only once this branch's suite is present, so the row +described T-mixed under T-main's name. + +T-mixed is the RED-FIRST result. Its five failures are the three cases this +change adds, the real index, and the preamble consistency case: + +``` +FAIL: test_a_second_row_under_a_different_owner_is_a_record +FAIL: test_a_dashed_row_and_an_owned_row_are_not_a_duplicate +FAIL: test_a_duplicate_under_one_owner_names_both_line_numbers +FAIL: test_the_tracked_index_is_valid +FAIL: test_real_index_matches_the_checkers_preamble +``` + +`test_real_index_matches_the_checkers_preamble` is red on T-mixed by +construction and is not a defect: the index carries the new preamble paragraph +while `main`'s `INDEX_PREAMBLE` does not, which is the drift this very check +exists to report. + +The refusal each side produces, verbatim, on the same fixture — one issue, two +DIFFERENT owning rows: + +``` +old: .agents/issue-index.md: issue #201 listed twice. Under `merge=union` a + duplicate is what two branches appending the same issue look like +new: (no errors) +``` + +and on a byte-identical row appended twice under the SAME owner, which is the +[#1619](https://github.com/mudler/vllm.cpp/issues/1619) shape: + +``` +old: .agents/issue-index.md: issue #201 listed twice. Under `merge=union` a + duplicate is what two branches appending the same issue look like +new: .agents/issue-index.md:28: issue #201 is listed twice under the same owner + `BACKEND-ROCM`, first at .agents/issue-index.md:26. ... +``` + +Against the REAL index rather than a fixture, `main`'s checker reports +`issue #1649 listed twice` on `main`'s own index and this branch's checker +reports nothing on this branch's index, with both `#1649` rows byte-identical to +their `main` copies (sha256 `6dfc1fbb...` at `:599` and `74fe3230...` at `:639`, +matching `main`'s `:592` and `:632`). + +**`UNOWNED_HIGH_WATER` is unaffected and needs no adjustment.** It is 33 before +and after, and the branch's index has exactly 33 unowned rows, a delta of 0. The +appended row names `GATE-ISSUE-INDEX-OWNER-KEY` as its owner, so it never enters +that population. + +`git merge-base --is-ancestor origin/main HEAD` exits 0 at `66f055248`. +`scripts/agent-preflight.sh:452-459` takes a `TRAILER_BEHIND` arm when the head +is behind the base and then reports NOTHING, so `BASE_SHA` and `RANGE_COUNT` are +reported beside every trailer green: a count of 0 is a vacuous pass, not a pass. + +MUTATION. `scripts/check-agent-record.py` is `7abe4aa4b3a8b0d776364207396be146e58dd9d34067b9f258c106a96e12d593` before and -after, verified with `sha256sum -c`. +after every mutation. The hashes below are of the exact bytes named in the +Mutation column, so a reader can reproduce each one with a single substitution +and check the hash. The two hashes this table previously carried could NOT be +reproduced from the mutation text beside them and were replaced rather than +re-quoted. -| Mutation | File sha256 while mutated | Result | +| Mutation | sha256 while mutated | Red | |---|---|---| -| `key = (number, None)`, the pre-#1731 predicate | `710224b8...` | 3 of 113 red: the two admission cases and `test_the_tracked_index_is_valid` | -| `first = None`, maximal widening | `8e7cfe09...` | 3 of 113 red: `test_a_duplicated_issue_is_rejected`, `test_a_byte_identical_duplicate_row_is_rejected`, `test_a_duplicate_under_one_owner_names_both_line_numbers` | - -The first mutation leaves `test_a_duplicate_under_one_owner_names_both_line_numbers` -green, correctly: that case asserts the MESSAGE, which the mutation does not -touch. Each mutated file was read back by `grep` for its marker before the run, -so neither mutation could read as passing by never having applied. +| `first = seen.get(key)` → `first = None`: the refusal can never fire | `cf8eea17...` | 3 of 113 — `test_a_duplicated_issue_is_rejected`, `test_a_byte_identical_duplicate_row_is_rejected`, `test_a_duplicate_under_one_owner_names_both_line_numbers` | +| `key = (number, row_id)` → `key = (number, None)`: the pre-#1731 predicate | `a14213fc...` | 3 of 113 — `test_a_second_row_under_a_different_owner_is_a_record`, `test_a_dashed_row_and_an_owned_row_are_not_a_duplicate`, `test_the_tracked_index_is_valid` | +| the message drops both line numbers | `fcddaa08...` | 1 of 113 — `test_a_duplicate_under_one_owner_names_both_line_numbers` | + +The two predicate mutations red DISJOINT sets, which is the property worth +having: the first proves the refusal still refuses, the second proves the +narrowing is what admits the hand-off. Neither alone would show both. + +Each mutant was import-checked before its run, because a mutant that fails to +BUILD reads as a passing test. The import check itself was validated in both +directions first: it must report `IMPORT OK` on the pristine file and must exit +9 on a deliberately broken one. Its first form did neither — it reported +`AttributeError: 'NoneType' object has no attribute '__dict__'` on the PRISTINE +file, because `@dataclass` resolves `__module__` through `sys.modules` and the +module had not been registered there. Every mutant would have read as "does not +build", which is a broken instrument failing toward a code verdict. + +The mutation run also left the tree MUTATED once, when the harness was killed +by a two-minute timeout part-way through the third mutation. The tree was +`fcddaa08...` and not the pristine hash. It is restored, and `git status +--porcelain` and `git diff` are both empty at `66f055248`; the restoration is +proved by hash rather than by the harness having finished. ## 8. Stop conditions From f366a3ac61f6ceeced5d2481075b9a5a61a91041 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sun, 23 Aug 2026 00:49:56 +0000 Subject: [PATCH 4/5] record(GATE-ISSUE-INDEX-OWNER-KEY): main repaired itself by deletion, so this row is preventive and its own index is the first live case `6354755ba` (PR #1742) landed the other repair while this row was being gated: it deleted the `ENG-HF-MODEL-DOWNLOAD` `#1649` row and closed #1731. `main` is green on `check-agent-record.py` by its own deletion, verified by running main's checker against main's index. This row therefore no longer cures a red, and the spec now says so instead of claiming a green it did not produce. What it still carries is the class. The deletion is a per-instance cost that recurs every time two lanes touch one issue; the narrowed key makes the next hand-off an append. The argument is no longer hypothetical, because after the merge this branch's own index carries #1731 TWICE -- at `:644` under `ENG-RECORD-CONFLICT-SURFACES` which filed it, and at `:646` under `GATE-ISSUE-INDEX-OWNER-KEY` which fixed it -- with zero duplicate `(number, owner)` pairs. Main's checker refuses this branch's index with `issue #1731 listed twice`; this branch's checker passes it. Re-measured after the merge rather than dated, because main's change disarmed part of the proof. `test_the_tracked_index_is_valid` red under the `key = (number, None)` mutation because the real index held two `#1649` rows; that reason is gone and it reds for a new one. Both predicate mutations still red three cases each at the same hashes. A mutation table left unrechecked here would have kept a green a later commit on main had stopped earning. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code] --- .agents/specs/gate-issue-index-owner-key.md | 72 +++++++++++++++++---- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/.agents/specs/gate-issue-index-owner-key.md b/.agents/specs/gate-issue-index-owner-key.md index d11e718dc..80575bd4b 100644 --- a/.agents/specs/gate-issue-index-owner-key.md +++ b/.agents/specs/gate-issue-index-owner-key.md @@ -175,17 +175,32 @@ agent reads the preamble BEFORE appending and reads the message only after redding the gate, and the wrong repair the message costs is an edit to an append-only record. -### The other repair, and why this one makes it unnecessary +### The other repair landed first, and this row is now preventive A concurrent lane took the opposite approach on branch `row/FIX-ISSUE-INDEX-1649-DUP`: DELETE the `:592` row as an append-only -exception argued in its own commit message. Both repairs turn `main` green. -They differ in what they cost. The deletion spends a row of the record and an -argued exception on a single instance; the narrowed key spends a checker change -and leaves both rows standing. If this row lands, the deletion is unnecessary, -and whoever reads both branches should treat this one as the live repair. If -this row is rejected, the deletion is still available and nothing here blocks -it. +exception argued in its own commit message. **It landed while this row was +being gated**, as `6354755ba` (PR #1742), which removed the +`ENG-HF-MODEL-DOWNLOAD` `#1649` row, appended a `#1733` row and closed +[#1731](https://github.com/mudler/vllm.cpp/issues/1731). + +That changes what this row is for, and the change is stated rather than glossed. +`main` is GREEN on `check-agent-record.py` by its own deletion, verified here by +running `main`'s checker against `main`'s index. This row no longer CURES a red. +It removes the CLASS: the narrowed key means the next filing-and-fixing hand-off +does not have to spend a deleted row and an argued exception, and the deletion +that landed is a per-instance cost that recurs every time two lanes touch one +issue. Nothing here reverts that deletion — the merge takes `main`'s index +wholesale and the `:592` row stays gone. + +The evidence for the class is no longer hypothetical, because this branch's own +index is the first live instance. After merging `main`, +[#1731](https://github.com/mudler/vllm.cpp/issues/1731) appears twice: at `:644` +under `ENG-RECORD-CONFLICT-SURFACES`, the row that filed it, and at `:646` under +`GATE-ISSUE-INDEX-OWNER-KEY`, the row that fixed it. Duplicate `(number, owner)` +pairs: zero. `main`'s checker refuses this branch's index with `issue #1731 +listed twice`; this branch's checker passes it. The hand-off the old key could +not express is the one this change had to make about itself. Two findings below are that lane's, credited to it. Both were re-measured here before being written down, because relaying an unverified finding is @@ -358,6 +373,38 @@ by a two-minute timeout part-way through the third mutation. The tree was --porcelain` and `git diff` are both empty at `66f055248`; the restoration is proved by hash rather than by the harness having finished. +### Re-measured after merging `6354755ba` + +`main` changed under this branch while it was being gated, which disarms part of +the evidence above rather than merely dating it. Every affected number was +taken again at `0d2d69e5c`. + +| Gate | `origin/main` `6354755ba` | this branch at `0d2d69e5c` | +|---|---|---| +| `main`'s checker on `main`'s index | GREEN — the duplicate NUMBER is gone, deleted | n/a | +| `main`'s checker on THIS branch's index | n/a | RED: `issue #1731 listed twice`, plus the expected preamble drift | +| this branch's checker on this branch's index | n/a | PASS | +| `python3 scripts/check-agent-record.py` | n/a | rc 0, `agent record OK: ENGINE=170 MODEL=377 QUANT=84 KERNEL=57 BACKEND=85 ANCHOR-ROT=37` | +| `python3 scripts/check-issue-index-append-only.py` | n/a | `OK`, rc 0 | +| `python3 tests/scripts/test_agent_record.py` | n/a | 113 tests, `OK` | +| index rows | 620 | 621 | +| `UNOWNED_HIGH_WATER` vs actual | n/a | 33 vs 33, delta 0 | + +The row that had to be re-checked is `test_the_tracked_index_is_valid` under the +`key = (number, None)` mutation. Before the merge it red because the real index +carried two `#1649` rows; `main` deleted one, so that reason is gone. It reds +anyway, for a NEW reason: this branch's own index now carries two `#1731` rows +under two different owners. Re-measured post-merge, both predicate mutations red +the same three cases each, with the same hashes: + +| Mutation | sha256 | Red, post-merge | +|---|---|---| +| `first = None` | `cf8eea17...` | 3 of 113 — unchanged | +| `key = (number, None)` | `a14213fc...` | 3 of 113 — unchanged, but `test_the_tracked_index_is_valid` now reds on `#1731` rather than on `#1649` | + +Had this not been re-run, the mutation table would have kept a green that a +later commit on `main` had quietly stopped earning. + ## 8. Stop conditions Stop and ask before repairing the STALE index rows this change makes @@ -375,9 +422,12 @@ message. ## 9. Now -The narrowed key and its cases landed with this change. `main` is green on -`check-agent-record.py` without any row being edited or deleted, and the two -`#1649` rows both stand, each under the row that wrote it. +`main` was made green by `6354755ba`, the other repair, which DELETED one of the +two `#1649` rows. This row does not undo that and does not claim the green. What +it carries is the narrowed key, so the next hand-off between two lanes costs an +append rather than a deleted row and an argued exception. Its own `#1731` row, +sitting beside the one `ENG-RECORD-CONFLICT-SURFACES` already owns, is the first +case the old key would have refused. ## 10. Outcome From 1368fd5a26f406ccffbeb2d6d28e6c56c8e17fae Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sun, 23 Aug 2026 01:47:54 +0000 Subject: [PATCH 5/5] fix(GATE-ISSUE-INDEX-OWNER-KEY): the row's own issue was linked nowhere, and the ratchet it named as a guard cannot see an owed issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three findings from the fresh review of #1744. The review PASSED the narrowed key itself, so nothing here re-litigates the design. The row was in breach of the rule it is about. `AGENTS.md` requires the issue in three places that agree, and this row had it in none: the spec named #1731, which #1742 CLOSED; the index carried no row for the open issue; and the pull request body never mentioned it. #1745 is the open issue, filed against this branch by name, and it now stands in all three. #1731 stays named through the spec as the first instance and as the red that no longer stands. A guard was asserted in prose that does not exist for most of the index. §4 of the spec and the docstring of test_a_dashed_row_and_an_owned_row_are_not_a_duplicate both said the opposite order "is already gated: an added dashed row raises the unowned count and reds the UNOWNED_HIGH_WATER ratchet". It does not, whenever any spec lists the issue under `## Owed`, because check_issue_index counts a dashed row only `if row_id is None and number not in owed`. Measured on this tree: 328 owed numbers, and 226 of 621 rows carry both an owner and an owed issue. Probing the real index with a dashed #168 row leaves this branch's checker silent at rc 0 with the unowned count still 33, while the contrast row #618, an issue no spec owes, reds it with `34 rows name no owner`. The index was restored byte-for-byte. The exemption is `AGENTS.md` working as written, so the sentences are corrected and the missing ORDERING rule is #1749, owed in the spec rather than built here: it is a second checker semantic in a change that owes one. Nothing proves the CLI runs check_issue_index. Its sole production call site is unguarded inside main(); replacing it with `pass` leaves the suite at 113 tests OK and makes the command accept a byte-identical duplicate row, the exact #1619 corruption the pristine tree refuses at rc 1. Inherited rather than introduced, since `git log -S` on that call returns one commit and this change touches only the body of the function, so it is filed as #1750 and owed, not repaired here. The docstring repair moved two symbols other records cite, and the record-anchor ratchet caught it in the same run: `stale: 33 > baseline 31`. The two ENG-RECORD-ANCHOR-RATCHET citations advance to where the symbols now are, and the baseline is untouched. The three appended index rows carry no `path:line` citation at all, because the index cannot be edited and a stale anchor written into it can never be repaired; they name symbols, and the line numbers live in the spec. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [claude-code] --- .agents/engine-matrix.md | 2 +- .agents/issue-index.md | 3 + .agents/specs/gate-issue-index-owner-key.md | 152 +++++++++++++++++++- tests/scripts/test_agent_record.py | 12 +- 4 files changed, 158 insertions(+), 11 deletions(-) diff --git a/.agents/engine-matrix.md b/.agents/engine-matrix.md index be6fdee8d..e2bd81217 100644 --- a/.agents/engine-matrix.md +++ b/.agents/engine-matrix.md @@ -225,7 +225,7 @@ claims it. | `ENG-RELEASE-WINDOWS` | Native Windows x86_64 pre-alpha release extension: one adaptive MSVC/UCRT CPU bundle with AVX2 executed in CI and one Vulkan preview bundle, both deterministic ZIPs and authenticated by the existing release handoff | T0 | vLLM has no Windows release path; runtime behavior remains pinned to vLLM `555967922`. Platform substrate reference: llama.cpp `src/llama-mmap.cpp:520-590` @ `237ad9b961f009ae19ac29dbce4cd0c1251f94b3`; Win32 API is the OS authority | W14 Win32 portability/MSVC CPU, W15 deterministic ZIP/PE packaging + Vulkan, and W16 ten-tuple prerelease workflow/version/docs implemented for one PR | Linux portability/release mutation gates are local evidence only. Native `windows-2022` MSVC `/W4 /WX`, extracted runtime/ISA smokes, merged-SHA ten-tuple dry run, `v0.0.3-pre.1` publication, attestations, and exact 32-asset audit remain pending; no Windows ZIP exists yet | [windows-binary-release.md](specs/windows-binary-release.md); [#117](https://github.com/mudler/vllm.cpp/issues/117) | `ACTIVE` | `CLAIM-ENG-RELEASE-WINDOWS` | | `ENG-RELEASE-CONTAINERS` | Published OCI container images on GHCR, built by GitHub Actions: the same staged server bundle as `ENG-RELEASE-BINARIES`, shipped from one package `ghcr.io/mudler/vllm.cpp` with the lane in the tag — `:-cuda` / `-vulkan` / `-cpu`, the moving `:latest-cuda` / `:latest-vulkan` / `:latest-cpu`, and a bare `:latest` aliasing the cpu lane, with `ENTRYPOINT vllm-server`. Lanes `cuda` (one fat image covering every supported SM), `vulkan`, `cpu` (adaptive baseline); `rocm` blocked-preview, tracking its binary channel. Version tags are immutable; every `latest-` moves. Each lane is a `linux/amd64` + `linux/arm64` multi-arch manifest built on native runners — aarch64 is first-class here because GB10 (sm_121a), Thor (sm_110) and Orin (sm_87) are all arm64. The image contains the bundle and nothing else: no weights, no Python, no PyTorch, no compiler, no build tree. BOUNDARY: the GPU driver and container runtime stay on the host and are never bundled; Metal and MLX are NOT-CONTAINERIZABLE (no macOS container runtime and no Metal passthrough exists) and remain static-binary-only lanes, recorded as a permanent boundary rather than pending work. No image, workflow, registry package or pull is claimed to exist. | T0 | release image lanes `.buildkite/release-pipeline.yaml:34-170` and the published-image dependency boundary `docker/Dockerfile.cpu:262-290` @ `555967922` | `docker/Dockerfile` (cpu/vulkan/cuda targets calling the release scripts); `docker/healthcheck.sh`; `release/container-matrix.json`; `scripts/check-container-matrix.py`; `scripts/check-container-workflow.py`; `scripts/validate-container-image.py`; `scripts/container_tags.py`; `.github/workflows/containers.yml`; SIGTERM handler `src/vllm/entrypoints/openai/server_main.cpp` (`SignalShutdown`, all three `listen()` sites); the pre-existing `docker/Dockerfile.arm64` is an unrelated CPU bench cross-check | issues `#170`, `#312`, `#394`; `tests/scripts/test_check_container_matrix.py` 31/31; `test_check_container_workflow.py` 29/29; `test_check_cuda_fat_gencode.py` 7+4 subtests. **GB10 2026-08-11 (`promaxgb10-4ad8`, `sm_121a`, CUDA 13.3): arm64 cuda image 1.71 GB, 673/673 objects, ten-SM gencode audit PASS, and a REAL GPU boot -- `/health` 200, `/version` 200, in-container healthcheck, clean SIGTERM, `--gpus all`, host driver 580.159.03 injected.** cpu amd64 783 MB gated locally; cpu+vulkan amd64 green on hosted CI **arm64 cuda lane RUNTIME-VERIFIED on GB10 2026-08-11** -- the first accelerator-hardware evidence for any lane. Four defects were removed to get there, each found by building rather than reading: the CUDA 12.9 base could not compile `sm_110`, the BuildKit cache mount outlived its toolchain (both #366), Marlin gencode had drifted from the feature table and failed the audit on 14 correctly-compiled TUs (#394, blocking BOTH cuda tuples project-wide), and the validator could only ever produce build evidence because its boot smoke never passed `--gpus`. **NOT established: nothing is published to GHCR; amd64 cuda is unbuilt; the published arm64 image is SBSA (`targets/sbsa-linux`), so Tegra -- Thor `sm_110`, Orin `sm_87` -- is untested and NOT covered** **ORIN (Tegra) 2026-08-11: the SBSA image RUNS on Jetson AGX Orin `sm_87` (L4T R36.4.3, Docker 27.5.1) -- Qwen3-0.6B (rev `c1899de2`) loads and GENERATES via `/v1/completions`, tegrastats GR3D 95-97% during decode vs 14-15% idle.** Tegra needs `--runtime nvidia --gpus all`: `--gpus` alone is refused by the hook and `--runtime` alone mounts no driver | [container-images.md](specs/container-images.md); issues [#170](https://github.com/mudler/vllm.cpp/issues/170), [#312](https://github.com/mudler/vllm.cpp/issues/312), [#394](https://github.com/mudler/vllm.cpp/issues/394) | `ACTIVE` | `CLAIM-ENG-RELEASE-CONTAINERS-W1-W7` | | `ENG-DOCS-SITE` | Publish the 11 `docs/*.md` as a browsable GitHub Pages site at `https://mudler.github.io/vllm.cpp/` WITHOUT a second copy of the prose. A Hugo site at `website/` mounts `../docs` READ-ONLY and derives everything else from what is already in the files: each page title from the file's first `# H1`, the sidebar order from `website/data/nav.yaml`, and links through a Goldmark render hook (internal `.md` → site URL; the 139 `../.agents/**` and `../AGENTS.md` escapes → GitHub blob URLs, since the protocol tree is deliberately NOT published). **No file under `docs/` is modified, moved, renamed, or given front matter**, so `check-doc-checkpoint.py` and every protocol path reference keep working and there is no second surface that can drift — the whole point of the row. Custom lean layouts, NO theme and NO submodule: off-the-shelf docs themes read titles, weights and menus out of front matter this design deliberately does not have, so each would need its title partial, menu and link hook overridden anyway, and hugo-book additionally floors at Hugo 0.158 against the 0.146.3 pin CI and the local toolchain share. Hard prerequisite inside the repo: `classify_path` in `scripts/check-pr-size.py` FAILS CLOSED on `website/**` (verified: raises `ValueError: unclassified repository path`), so the classifier must learn the path or the PR cannot pass the project's own size gate. Hard prerequisite outside it: GitHub Pages must be enabled with the source set to GitHub Actions — the workflow is inert otherwise. A marketing landing page is explicitly OUT of scope (`README.md` stays the front door), as is any restructuring of `docs/`; the custom domain is parked behind the pending vLLM trademark question | T1 | NO vLLM analogue — upstream's docs are a separate mkdocs site and nothing in this row mirrors upstream *behavior*, so it carries no parity obligation. The STRUCTURAL reference is LocalAI's `.github/workflows/gh-pages.yml` (two Hugo sites merged into one Pages artifact), reduced to the docs half | read-only mount `website/hugo.toml:29`; title-from-H1 `website/layouts/partials/title.html:10`; link rewriting `website/layouts/_default/_markup/render-link.html:27`; guard `scripts/check-site.py:70`; deploy `.github/workflows/gh-pages.yml` | `tests/scripts/test_check_site.py:51,56,66,80,89,97` (6 mutation cases: clean tree, H1 stripped, doc absent from nav, nav entry with no file, duplicated entry, missing nav file); build evidence 14 pages with `docs/bench-evidence` + `docs/superpowers` absent from `public/` and no `href` ending in `.md`; 48 protocol links rewritten in `docs/status/`. NO published page is claimed: GitHub Pages is not yet enabled on the repository, which is the recorded stop condition holding this row at `GATING` | [gh-pages-docs-site.md](specs/gh-pages-docs-site.md); issue [#224](https://github.com/mudler/vllm.cpp/issues/224) | `READY` | `CLAIM-ENG-DOCS-SITE` | -| `ENG-RECORD-ANCHOR-RATCHET` | **The record's `path:line` citations were range-checked and never reported.** `check-agent-record.py` parsed BOTH forms: markdown links, and bare `` `file.cpp:123` `` through `RAW_LOCAL_ANCHOR_RE` since `ee511ca8a`. On a missing file or an out-of-range line `local_line_anchors` runs `continue`, so the bad anchor never reaches the caller, and `is_code_anchor` then answers with **any**, so one good sibling covers the rest. There was no symbol test and no report, and **32 of the 38** offenders are IN RANGE, so range-checking could not have found them. Measured at `8daa67b39`: **832 of 867** in-scope citations (**96.0%**) were already parsed and range-checked, and the **35** new to parsing sit under `.agents/`, `docs/` and `website/`; `EVIDENCED_STATES` omits `ACTIVE`/`READY` entirely and is deliberately NOT widened, because requiring an anchor there raises 85 errors across 53 rows. Even the fraction it saw was only range-checked, never checked to CONTAIN the symbol named beside it — every stale anchor found in the 2026-08-13/14 campaign was in range. LANDED as a device-leakage-shaped ratchet over a recorded baseline, never a bulk cleanup: the backlog is fixed by whoever next touches each row | T1 | none — this is our own record surface; the discipline mirrors AGENTS.md §Records ("cite the `file:line` you ported from") | parser + classifier + ratchet in `check-agent-record.py`: `scripts/check-agent-record.py::BARE_CITATION_RE` (the bare form), `scripts/check-agent-record.py::cell_citations` (both forms, with the adjacent-symbol rule), `scripts/check-agent-record.py::classify_citation` (OK / STALE / BROKEN), `scripts/check-agent-record.py::RECORD_ANCHOR_STATES` (gap 3: `ACTIVE` and `READY` join the count), `scripts/check-agent-record.py::check_record_anchors` (the two-way gate). SYMBOL-anchored rather than line-anchored as of `SPEC-DFLASH2` W2, which added a justification paragraph to this file's `KERNEL` count and shifted all five ranges by 14 lines at once -- the rot this row exists to measure, produced by an edit to the very file the row cites; budget in `scripts/record-anchor-baseline.json` | `RecordAnchorRatchet` `tests/scripts/test_agent_record.py:1476` — 10 cases, RED-first, including `test_one_good_link_does_not_cover_a_rotted_bare_citation` `tests/scripts/test_agent_record.py:1544`, the `any()` shape the rot hid in. Five mutants red it: report-only, `EVIDENCED_STATES` restored, links-only, first-citation-only, range-only. Measured baseline **38** (32 STALE + 6 BROKEN); gate wired in `scripts/agent-preflight.sh` and the `agent-record` CI job (`--report`) | [record-anchor-ratchet.md](specs/record-anchor-ratchet.md) | `ACTIVE` | `CLAIM-ENG-RECORD-ANCHOR-RATCHET` | +| `ENG-RECORD-ANCHOR-RATCHET` | **The record's `path:line` citations were range-checked and never reported.** `check-agent-record.py` parsed BOTH forms: markdown links, and bare `` `file.cpp:123` `` through `RAW_LOCAL_ANCHOR_RE` since `ee511ca8a`. On a missing file or an out-of-range line `local_line_anchors` runs `continue`, so the bad anchor never reaches the caller, and `is_code_anchor` then answers with **any**, so one good sibling covers the rest. There was no symbol test and no report, and **32 of the 38** offenders are IN RANGE, so range-checking could not have found them. Measured at `8daa67b39`: **832 of 867** in-scope citations (**96.0%**) were already parsed and range-checked, and the **35** new to parsing sit under `.agents/`, `docs/` and `website/`; `EVIDENCED_STATES` omits `ACTIVE`/`READY` entirely and is deliberately NOT widened, because requiring an anchor there raises 85 errors across 53 rows. Even the fraction it saw was only range-checked, never checked to CONTAIN the symbol named beside it — every stale anchor found in the 2026-08-13/14 campaign was in range. LANDED as a device-leakage-shaped ratchet over a recorded baseline, never a bulk cleanup: the backlog is fixed by whoever next touches each row | T1 | none — this is our own record surface; the discipline mirrors AGENTS.md §Records ("cite the `file:line` you ported from") | parser + classifier + ratchet in `check-agent-record.py`: `scripts/check-agent-record.py::BARE_CITATION_RE` (the bare form), `scripts/check-agent-record.py::cell_citations` (both forms, with the adjacent-symbol rule), `scripts/check-agent-record.py::classify_citation` (OK / STALE / BROKEN), `scripts/check-agent-record.py::RECORD_ANCHOR_STATES` (gap 3: `ACTIVE` and `READY` join the count), `scripts/check-agent-record.py::check_record_anchors` (the two-way gate). SYMBOL-anchored rather than line-anchored as of `SPEC-DFLASH2` W2, which added a justification paragraph to this file's `KERNEL` count and shifted all five ranges by 14 lines at once -- the rot this row exists to measure, produced by an edit to the very file the row cites; budget in `scripts/record-anchor-baseline.json` | `RecordAnchorRatchet` `tests/scripts/test_agent_record.py:1482` — 10 cases, RED-first, including `test_one_good_link_does_not_cover_a_rotted_bare_citation` `tests/scripts/test_agent_record.py:1550`, the `any()` shape the rot hid in. Five mutants red it: report-only, `EVIDENCED_STATES` restored, links-only, first-citation-only, range-only. Measured baseline **38** (32 STALE + 6 BROKEN); gate wired in `scripts/agent-preflight.sh` and the `agent-record` CI job (`--report`) | [record-anchor-ratchet.md](specs/record-anchor-ratchet.md) | `ACTIVE` | `CLAIM-ENG-RECORD-ANCHOR-RATCHET` | | `ENG-RECORD-CONFLICT-SURFACES` | Retire the shared record surfaces that make concurrent PRs conflict by construction. MEASURED at `origin/main` `d928e2c3` with `git merge-tree --write-tree` over every open PR: **16 of 29 conflict (55%), and 13 of the 16 conflict in bookkeeping files ONLY**, with no product code involved — `.agents/coordination.md` in 8, `.agents/NOW.md` in 5, `.agents/roadmap_v1.md` in 4, `scripts/check-public-doc-tables.py` in 4, `docs/STATUS.md` in 4, and any `src/`/`tests/` path in just 3. Three defects, each of which GUARANTEES rather than risks a collision. (1) `.agents/NOW.md` is a fixed-size shared buffer at EXACTLY 6000/6000 chars (`check-now-current.py:31`), so adding a row requires evicting another and every PR is a read-modify-write of one global — and the conflict is the LUCKY outcome, since a clean three-way merge would apply both evictions and both additions, silently dropping live rows and blowing the very budget the checker defends. (2) `STATUS_RATCHET = {"chars": 243245}` (`check-public-doc-tables.py:557`) is a hardcoded byte count of a DIFFERENT file that may only fall, so a PR owing `docs/STATUS.md` one lifecycle line must delete unrelated prose from another row to pay for it and edit the checker too; the checker's own comment at `:331` already records the failure (*"a ratchet pinned to the byte turns every concurrently merged row's one-line status edit into a spurious failure"*) and answered it with slack instead of removing the coupling. (3) `.agents/coordination.md`'s active-claims table is insert-at-one-anchor: the six ROCm GDN PRs (#334 #336 #341 #343 #345 #348) are ONE author's sequential stack that conflicts on nothing else, each appending a ~1,500-char row — the PR description, transcribed into a file every other claim also writes. It also contradicts the protocol it serves: `AGENTS.md` holds that *"History is git"* and *"There is no state log"*, yet both claims tables ARE state logs duplicating `gh pr list`, `row/` branch names and issue state; the argument that refuses a waiver registry applies unchanged to a claims registry. Precedent twice over — `policy.csv` retired in `0f3e44ee`, per-class line budgets retired 2026-08-10 because the gate fired on ordinary work. The exonerated surfaces share ONE property, one writer per file: `.agents/specs/.md` (one file per row, **zero conflicts** in the sample), the `*-matrix.md` inventories, and the append-only `.agents/benchmark-record.md`. SCOPE: remove `STATUS_RATCHET` and the doc-gating global counters while KEEPING the per-cell/per-paragraph caps (local, so they couple nothing); remove the active-claims table and derive claims from open PRs and branch names; drop `NOW.md`'s byte budget; order the roadmap's keyed tables by ID so distinct keys stop colliding at one anchor; and record the invariant — **no surface that every PR must write** — in `AGENTS.md`. No product source, kernel or gate semantic moves | T0 | NO vLLM analogue — this is local protocol machinery, so the mirror rule does not apply and no upstream `file:line` exists to port from. Governed instead by `AGENTS.md` §"Changing the rules or a checker", which requires a spec, a red-before test or mutation, and green-after evidence | - | - (spec-before-code: the red-before suites are named in the spec's Tests section — `tests/scripts/test_check_public_doc_tables.py`, `tests/scripts/test_check_now_current.py`, a mutation case per removed rule proving the obligation survives in the retained caps and `check-doc-checkpoint.py`, and a `git merge-tree` merge-shape regression that must be RED before the `NOW.md`/roadmap work and GREEN after) | [retire-shared-record-surfaces.md](specs/retire-shared-record-surfaces.md); issue [#364](https://github.com/mudler/vllm.cpp/issues/364) | `READY` | `CLAIM-ENG-RECORD-CONFLICT-SURFACES` | | `ENG-TRAILER-MERGE-ARTIFACTS` | The trailer gate rejects CORRECT commits because of paragraph placement, and that is why `main` is red on `agent-record`. `check-commit-trailers.py` reads trailers via `git interpret-trailers --parse`, which treats ONLY the final paragraph as the block; GitHub appends `Co-authored-by:` as a SEPARATE trailing paragraph on a squash merge, so a complete correct block becomes invisible and the gate reports it missing. MEASURED: piping `git show -s --format=%B dbd0d51c` into `git interpret-trailers --parse` prints nothing but the co-author line, and 13 of the last 30 commits on `main` fail the check -- unnoticed only because those runs were cancelled (#274), which HID the defect rather than causing it. FIX: fuse consecutive trailing TRAILER-SHAPED paragraphs before parsing. Nothing is relaxed -- the block must still exist, the marker must still sit above it, each declaration must still appear exactly once, and an AI co-author is still forbidden; the block is merely FOUND where the merge tool left it. A prose paragraph still terminates it. REJECTED IN FLIGHT and recorded because it is the more instructive half: a first attempt also collapsed identical duplicate trailers to fix the multi-commit-squash shape, which relaxes the uniqueness rule an existing test already pins. Rewriting that assertion to suit the change is what AGENTS.md forbids, and the distinction is real -- a doubled block is genuinely malformed and fixable at source, whereas the co-author case is a correct commit defeated by the parser. Reverted in full. SCOPE LIMIT, stated rather than implied: this fixes ONE of five observed shapes. `f64f2b71` (bot co-author) is a REAL violation the parse had been hiding and now correctly fails; `87308dea` (GitHub's `---------` separator), `b8293c88` (squash doubled the block) and `b580452d` (merge button, no trailers) stay red by design. Closing those is a merge-method change, not a checker change | T0 | NO vLLM analogue -- local protocol machinery, so the mirror rule does not apply and there is no upstream `file:line` to port from. Governed by `AGENTS.md` §"Changing the rules or a checker" | `scripts/check-commit-trailers.py:60` (`join_trailing_trailer_paragraphs`, `_is_trailer_paragraph`, and the fused `parsed_trailers`) | `tests/scripts/test_check_commit_trailers.py:1` 21 cases -- the RED-BEFORE appended-co-author case plus four GUARDS that keep the fusion bounded (doubled block still fails, contradictory declarations still fail, a no-trailer merge message still fails, prose after the block still fails), all four green before and after; closure [parity-ledger.md#L941](parity-ledger.md#L941) | [trailer-merge-artifacts.md](specs/trailer-merge-artifacts.md); issue [#406](https://github.com/mudler/vllm.cpp/issues/406) | `DONE` | `157080c8` | | `ENG-FORGE-COAUTHOR` | The forbidden-AI-trailer rule was catching ATTRIBUTION rather than an authorship claim, which is why bot-opened PRs red `main` on merge. GitHub composes the squash message itself and appends the account that opened the PR — `Co-authored-by: localai-org-maint-bot <...@users.noreply.github.com>` — and most PRs here are opened by a bot, so nearly every squash trips the AI-identity check. Real instance `f64f2b71`, invisible until #406 repaired the parse, which is why it reads as a new failure and is not one. The rule exists so an AI cannot claim it WROTE the code, and that stays; GitHub is recording who pressed the button, and the AI-involvement claim is already carried separately by `AI-Assisted` and `Assisted-by` in the same block. FIX: accept a `Co-authored-by` at a GitHub account noreply address even when the name matches an AI identity token, keyed on the FORGE'S OWN DOMAIN rather than the name so the exemption cannot be borrowed. A hand-written `Co-authored-by: Claude ` still fails; `Signed-off-by` is excluded from the exemption entirely, because a sign-off is a legal assertion about provenance rather than attribution. `AGENTS.md` records the same distinction in the same change so prose and checker cannot drift | T0 | NO vLLM analogue -- local protocol machinery, so the mirror rule does not apply and there is no upstream `file:line` to port from. Governed by `AGENTS.md` §"Changing the rules or a checker" | `scripts/check-commit-trailers.py:38` (`FORGE_ACCOUNT_EMAIL` and the forbidden-trailer skip) | `tests/scripts/test_check_commit_trailers.py:1` 25 cases -- the RED-BEFORE forge-bot case plus THREE guards that matter more than the relaxation because this LOOSENS a rule: a hand-written AI co-author still fails, `Signed-off-by` at the same noreply address still fails, and a human co-author still passes; all three green before and after. Real commit `f64f2b71` re-verified per commit | [forge-coauthor-attribution.md](specs/forge-coauthor-attribution.md); issue [#418](https://github.com/mudler/vllm.cpp/issues/418) | `ACTIVE` | `CLAIM-ENG-FORGE-COAUTHOR` | diff --git a/.agents/issue-index.md b/.agents/issue-index.md index 3f68f7112..dd43b93d0 100644 --- a/.agents/issue-index.md +++ b/.agents/issue-index.md @@ -644,3 +644,6 @@ appended twice looks like. | [#1731](https://github.com/mudler/vllm.cpp/issues/1731) | `ENG-RECORD-CONFLICT-SURFACES` | `check-agent-record` is RED on `main`: `#1649` is listed twice in `.agents/issue-index.md`, at `:592` (added by `a7bb3130b`, the lane that FILED it) and `:632` (added by `2f2a70925`, the lane that FIXED it). Neither is wrong and neither could see the other -- `merge=union` combines two appends silently, so a duplicate is the ordinary outcome when filing and fixing happen on different branches, and the checker only notices once both have landed on main, where every later PR inherits the red. Not repaired in flow: the index preamble forbids editing or deleting a row, and the two bodies carry different facts (`:632` has a second red and the mutation evidence, `:592` has the attribution to `a50c57d69`), so choosing which survives is a judgement | bug | | [#1733](https://github.com/mudler/vllm.cpp/issues/1733) | `ENG-RECORD-CONFLICT-SURFACES` | CLOSED as a duplicate of [#1731](https://github.com/mudler/vllm.cpp/issues/1731), filed seventeen minutes after it against the same red, and recorded here rather than left unindexed because its one MEASURED claim is FALSE and an append-only row cannot be corrected in place later. Both issues report that `.agents/issue-index.md` lists [#1649](https://github.com/mudler/vllm.cpp/issues/1649) twice on `main` at `038ff61e5`, at `:592` from `a7bb3130b` (the lane that FILED it) and at `:632` from `2f2a70925` (the lane that FIXED it). #1731 is the earlier filing, already carries an index row, and is the record. #1733 adds one thing #1731 does not, and it is wrong: "the repair is measured and it is NOT blocked", on the evidence that removing one of the two rows in a worktree and running both checkers gives `agent record OK: ENGINE=170 MODEL=377 ...` and `OK: issue index append-only`. The second half is an artefact of the instrument. `scripts/check-issue-index-append-only.py:50-51` diffs `merge-base(origin/main, HEAD)..HEAD`, which reads COMMITS, so an UNCOMMITTED deletion is invisible to it. Measured on `row/FIX-ISSUE-INDEX-1649-DUP` at base `038ff61e5`: deleting `:592` in the WORKING TREE alone returns `OK: issue index append-only` at rc 0 with `git diff --numstat 038ff61e5..HEAD -- .agents/issue-index.md` EMPTY, and committing the byte-identical deletion turns the same checker rc 1 with a `removed:` line naming the row. #1733's own quoted `agent record OK: ENGINE=170 MODEL=377` is the tell, because that is the working-tree reading and the committed tree cannot produce it while the duplicate stands. So the duplicate IS base-reachable, the two checkers ARE in genuine contradiction on this tree, and the repair is the argued exception #1731's row anticipated rather than the free edit #1733 reported | bug | | [#1731](https://github.com/mudler/vllm.cpp/issues/1731) | `GATE-ISSUE-INDEX-OWNER-KEY` | **The `issue #N listed twice` refusal was a leftover from a KEYED table, and it red `main` for the ordinary case of one lane filing an issue and another lane fixing it.** The rule arrived in `8dd6508da` (2026-08-09), when the intake surface was an editable keyed table inside `.agents/roadmap_v1.md` where one row per issue was the whole design. `51e0cb5b1` moved the table into this file, made it append-only and gave it `merge=union`, and uniqueness by issue NUMBER survived that move unexamined. In an append-only log an update IS an append, so one row per issue permits one statement per issue for the life of the repository. MEASURED at `038ff61e5`: 620 rows, one duplicate number ([#1649](https://github.com/mudler/vllm.cpp/issues/1649), owned by `ENG-HF-MODEL-DOWNLOAD` where the lane FILED it and by `GATE-WINDOWS-PORTABILITY-TARGET-SCOPE` where the lane FIXED it), and ZERO duplicate `(number, owner)` pairs -- so narrowing the key turns `main` green with no row edited and no row deleted. The tree already paid for the old key twice in prose: [`bpe-quadratic-merge.md`](specs/bpe-quadratic-merge.md) records that [#1365](https://github.com/mudler/vllm.cpp/issues/1365)'s row under-describes its own re-scoped issue and that "Both available edits are gate failures, so the reconciliation is PROSE", and [`serve-request-length-guard.md`](specs/serve-request-length-guard.md) records the same refusal for [#1541](https://github.com/mudler/vllm.cpp/issues/1541). What the refusal DID catch is unaffected, and it is the reason the ban was not simply dropped: [#1619](https://github.com/mudler/vllm.cpp/issues/1619) measured the `merge=union` driver duplicating a row BYTE-IDENTICALLY at two lines, which `git merge-tree` called clean and `check-issue-index-append-only.py` passed because a duplicate is an ADDITION -- `check-agent-record.py` was the only gate that refused it, and a duplicated LINE carries its owner with it, so the pair key still collides. Given up deliberately: a MISTYPED owner on a second row, which no reading of this file can separate from a legitimate hand-off. Rejected deliberately: a cap on rows per issue, which is `AGENTS.md` `## Records`' "limit an entry, not a shared file" anti-pattern at the scale of one issue, and an owner-ID existence check, which would red `main` on day one because unplaced gate rows are legitimate owners. This row is itself the change's first legitimate case: [#1731](https://github.com/mudler/vllm.cpp/issues/1731) already has a row under `ENG-RECORD-CONFLICT-SURFACES`, whose spec says "No product source, kernel or gate semantic moves", so the fixing row is a different one and recording that is an append the OLD key would have refused. Spec [`gate-issue-index-owner-key.md`](specs/gate-issue-index-owner-key.md) | bug | +| [#1745](https://github.com/mudler/vllm.cpp/issues/1745) | `GATE-ISSUE-INDEX-OWNER-KEY` | **The open issue this row answers, replacing the CLOSED [#1731](https://github.com/mudler/vllm.cpp/issues/1731).** `6354755ba` (PR #1742) cured the `#1649` red by DELETING a row as an argued append-only exception, which closed #1731 and cured the INSTANCE. The CLASS produced a new one within hours, on the very branch addressing it: on `row/GATE-ISSUE-INDEX-OWNER-KEY`, #1731 itself now sits on two rows, one under the lane that FILED it and one under the lane that FIXED it, and it is the only issue number appearing more than once there. #1745 is the record that a per-instance deletion is not a steady state, because each one has to be re-argued against the append-only rule by whoever hits it next, without the context of why the last one was granted -- `AGENTS.md` `## Records`: "A gate often creates the lock. If a checker requires every change to edit one shared file, the checker is defective. Move the obligation to a per-row surface. Do not delete the obligation." The repair is the narrowed uniqueness key in this row's spec [`gate-issue-index-owner-key.md`](specs/gate-issue-index-owner-key.md), and what it must not lose is the [#1619](https://github.com/mudler/vllm.cpp/issues/1619) corruption: a repeat under the SAME owner is what one row appended twice looks like, and that still reds | bug | +| [#1749](https://github.com/mudler/vllm.cpp/issues/1749) | — | **The `UNOWNED_HIGH_WATER` ratchet cannot see a dashed row for an issue any spec lists under `## Owed`, so the ownership-losing half of a hand-off is ungated.** `check_issue_index` in `scripts/check-agent-record.py` counts a dashed row only `if row_id is None and number not in owed`, and `owed_issues()` collects every number inside a spec's `## Owed`. MEASURED on `row/GATE-ISSUE-INDEX-OWNER-KEY` at `f366a3ac6`: 328 owed numbers, 621 rows, and 226 of those rows carry BOTH an owning row ID and an issue some spec also owes -- those 226 are exactly the rows for which appending a dashed row afterwards is silent. Of 97 dashed rows, 64 are owed, and the ratchet's real population is the remaining 33, which is the recorded high water. PROBED on the real index: a dashed `#168` row, for an issue already owned by `BACKEND-CUDA-SM110` and also owed, leaves this branch's checker at rc 0 with the unowned count still 33, while `origin/main`'s checker reds it under the OLD number-only key rather than the ratchet; the contrast row `#618`, an issue no spec owes, reds this branch's checker with `34 rows name no owner, above the recorded 33`. The index was restored byte-for-byte, sha256 `4e80b8ba...` before and after. This is NOT a defect in the pair key and is arguably an acceptable trade, because `AGENTS.md` states the obligation as an owning row ID OR a spec's `## Owed`; what is missing is an ORDERING rule over an append-only file, and a guard has to decide whether de-adoption is a regression to refuse or a record to admit. Found by the fresh review of PR #1744, whose spec and one test docstring both ASSERTED the ratchet catches it; both are corrected there, and this is owed under `## Owed` in [`gate-issue-index-owner-key.md`](specs/gate-issue-index-owner-key.md) | bug | +| [#1750](https://github.com/mudler/vllm.cpp/issues/1750) | — | **`check_issue_index` has one production call site and nothing proves the CLI runs it.** The only call is `check_issue_index(errors)`, unguarded inside `main()` in `scripts/check-agent-record.py`. MUTATED on `row/GATE-ISSUE-INDEX-OWNER-KEY` at `f366a3ac6`: replacing that call with `pass` (checker sha256 `7abe4aa4...` to `e98c80ad...`, import-checked `IMPORT OK` first, so a mutant that fails to BUILD cannot read as a pass) leaves `python3 tests/scripts/test_agent_record.py` at 113 tests `OK`, unchanged, and makes `python3 scripts/check-agent-record.py` accept a byte-identical duplicate row at rc 0 -- the exact corruption [#1619](https://github.com/mudler/vllm.cpp/issues/1619) measured, which the pristine tree refuses at rc 1. `test_the_tracked_index_is_valid` proves the FUNCTION reads the real file; nothing proves the COMMAND calls the function. INHERITED, not introduced: `git log -S'check_issue_index(errors)'` on that file returns one commit, `51e0cb5b1`, and PR #1744 touches only the body of the function. The repair pattern already exists one class over, in `paths_main_hands_the_shape_gate`, where [#1033](https://github.com/mudler/vllm.cpp/issues/1033) armed the same question for `check_table_shapes` by driving `agent_record.main([])` and capturing the REAL call instead of grepping the source, and it should cover the other unguarded calls in that block rather than this one alone. Checker and index were both restored byte-for-byte. Owed under `## Owed` in [`gate-issue-index-owner-key.md`](specs/gate-issue-index-owner-key.md) | bug | diff --git a/.agents/specs/gate-issue-index-owner-key.md b/.agents/specs/gate-issue-index-owner-key.md index 80575bd4b..16c266f4e 100644 --- a/.agents/specs/gate-issue-index-owner-key.md +++ b/.agents/specs/gate-issue-index-owner-key.md @@ -1,12 +1,22 @@ # Spec — the issue index is keyed on the issue AND its owning row -Issue: [#1731](https://github.com/mudler/vllm.cpp/issues/1731) +Issue: [#1745](https://github.com/mudler/vllm.cpp/issues/1745) +Owed: [#1749](https://github.com/mudler/vllm.cpp/issues/1749), +[#1750](https://github.com/mudler/vllm.cpp/issues/1750) (see `## Owed`) Row: `GATE-ISSUE-INDEX-OWNER-KEY` (unplaced record/gate defect; the tracked tree is a checker, not a matrix row, the same placement [`gate-windows-portability-target-scope.md`](gate-windows-portability-target-scope.md) uses) State: `ACTIVE` +This spec was opened against +[#1731](https://github.com/mudler/vllm.cpp/issues/1731), which is now CLOSED: +`6354755ba` (PR #1742) cured that red by DELETING a row. #1731 stays named +throughout §3, §5 and §7 as the first instance and as the red that no longer +stands. The open issue this row now answers is +[#1745](https://github.com/mudler/vllm.cpp/issues/1745), which records that +the class recurred on this branch within hours of that deletion. + ## 1. Scope `check_issue_index` in `scripts/check-agent-record.py` refuses a second row for @@ -119,8 +129,17 @@ Four decisions, each of which could have gone the other way: **A dash and an owner are different keys, and both may stand.** A row that names no owner is owned through a spec's `## Owed`. A later row that names an owning row ID records adoption, and adoption can only be recorded by appending. The -opposite order loses information, and it is already gated: an added dashed row -raises the unowned count and reds the `UNOWNED_HIGH_WATER` ratchet. +opposite order loses information, and NOTHING gates it. This paragraph claimed +the opposite until the fresh review of this change, and the claim was false: +`check-agent-record.py:2034` counts a dashed row only `if row_id is None and +number not in owed`, so a dashed row for an issue any spec lists under +`## Owed` never enters the unowned population and the ratchet cannot move. The +measurement, the probe and the contrast case are in §5. The exemption itself is +`AGENTS.md` working as written -- an owed issue IS owned -- so what is missing +is narrower than the count, and it is filed as +[#1749](https://github.com/mudler/vllm.cpp/issues/1749) and listed under +`## Owed` rather than repaired here: an ordering rule over an append-only file +is a second checker semantic in a change that owes one. **The unowned count stays per-row.** `AGENTS.md` states the obligation per row: "Every index row names an owning row ID, or names a spec that lists the issue @@ -158,10 +177,44 @@ same owner, so the pair key collides and the refusal is unchanged. The same holds for a rebase or a copy-paste that appends one row twice. **What the gate no longer catches.** Two rows for one issue under two DIFFERENT -owners, where the second owner was a mistake rather than a hand-off. No reading -of the file can separate that from the legitimate case, because the two are the -same bytes. The bound is that the mistake is visible: the row names a row ID, a -reader can follow it, and the owner ID is a reviewed field in a reviewed diff. +owners, where the second owner was a mistake rather than a hand-off: an invented +row ID, or one that differs from the real owner in CASE ONLY, since the ID is +compared as bytes and resolved against no inventory (§4). No reading of the file +can separate that from the legitimate case, because the two are the same bytes. +The bound is that the mistake is visible: the row names a row ID, a reader can +follow it, and the owner ID is a reviewed field in a reviewed diff. + +**What no gate catches in the other direction, measured rather than asserted.** +§4 says a dashed row appended after an owned one is ungated. That correction was +made because the sentence there previously claimed the `UNOWNED_HIGH_WATER` +ratchet catches it, and the fresh review of this change showed it does not. +Reproduced here on this branch's own tree at `f366a3ac6`, not relayed: + +| Measurement | Value | +|---|---| +| owed issue numbers, `owed_issues()` over `.agents/specs/*.md` | 328 | +| index rows | 621 | +| rows carrying BOTH an owning row ID and an issue some spec also owes | 226 | +| dashed rows | 97, of which 64 are owed | +| the ratchet's actual population | the remaining 33, which is `UNOWNED_HIGH_WATER` | + +The probe appends one dashed row for `#168` to the REAL index. #168 already has +an owner at `:26`, `BACKEND-CUDA-SM110`, and is also under a spec's `## Owed`: + +| Run | Result | +|---|---| +| this branch's `check-agent-record.py` | rc 0, `agent record OK: ENGINE=170 MODEL=377 ...` -- silent | +| unowned count with the probe row present | 33, unchanged, against `UNOWNED_HIGH_WATER` 33 | +| `origin/main`'s checker at `6354755ba`, run from inside this worktree | rc 1, `issue #168 listed twice` -- the OLD number-only key, never the ratchet | + +The contrast case is what makes the owed set, and not the dash, the +discriminator: the same probe row for `#618`, an issue no spec owes, reds this +branch's checker with `34 rows name no owner, above the recorded 33: #618`. The +index is restored byte-for-byte, sha256 +`4e80b8ba32333ac2589c9b616719f95eece6dd8a53e978e89bb09e8838fe9fbe` before and +after, with `git status --porcelain` empty. This change does not widen that +hole and does not narrow it; it stops the spec and a test docstring from +claiming a guard that is not there. **The preamble edit carries the risk the preamble describes.** This change adds a paragraph to the [`issue-index.md`](../issue-index.md) preamble and to @@ -405,6 +458,52 @@ the same three cases each, with the same hashes: Had this not been re-run, the mutation table would have kept a green that a later commit on `main` had quietly stopped earning. +### Repaired after the fresh review, and re-measured at the repair head + +The fresh review PASSED the design: 16 constructed shapes confirmed the #1619 +byte-identical-duplicate case still reds, and the two predicate mutations still +red disjoint sets. Three findings were repaired rather than argued, and each +number below was taken AFTER the last edit rather than at the parent, because a +count measured at the parent is a count of a tree nobody is merging. + +| Finding | Repair | +|---|---| +| The row's issue was linked in none of the three places: the spec named the CLOSED #1731, the index carried no row for the open issue, and the pull request body never mentioned it | The header names [#1745](https://github.com/mudler/vllm.cpp/issues/1745), the index carries a #1745 row under this row, and the body closes it | +| §4 and the `test_a_dashed_row_and_an_owned_row_are_not_a_duplicate` docstring both claimed the `UNOWNED_HIGH_WATER` ratchet gates the opposite order | Both now state the measured behaviour, the probe is in §5, and the missing guard is [#1749](https://github.com/mudler/vllm.cpp/issues/1749), owed below | +| Nothing proves the CLI runs `check_issue_index`; the sole call site can be deleted with the suite unmoved | Pre-existing and unrepaired by design, filed as [#1750](https://github.com/mudler/vllm.cpp/issues/1750) with its mutation, owed below | + +Two of those repairs moved lines that other records cite, which the record-anchor +ratchet caught in the same run and is the reason it exists. The docstring +correction added six lines above `RecordAnchorRatchet`, and +`ENG-RECORD-ANCHOR-RATCHET` in [`engine-matrix.md`](../engine-matrix.md) cited +`tests/scripts/test_agent_record.py:1476` and `:1544`. The gate red with +`RECORD ANCHOR REGRESSION in bucket 'stale': 33 > baseline 31`; the two +citations are advanced to `:1482` and `:1550`, which is where the symbols now +are, and the baseline is untouched. The `:1667-1689` citation in `## Owed` was +re-read after that same shift rather than copied from the pre-edit reading. + +The three appended index rows carry NO `path:line` citation, deliberately. The +index cannot be edited, so a line number written into it can never be repaired +when the cited file moves, and the two `#1649` anchors this row spent §2 on are +what that costs. Every one of them names a symbol instead. The line numbers live +in this spec, which can be corrected. + +| Gate | Value at the repair head | +|---|---| +| `python3 scripts/check-agent-record.py` | rc 0, `agent record OK: ENGINE=170 MODEL=377 QUANT=84 KERNEL=57 BACKEND=85 ANCHOR-ROT=37` | +| `python3 scripts/check-issue-index-append-only.py` | `OK`, rc 0 | +| `python3 tests/scripts/test_agent_record.py` | 113 tests, `OK` | +| `python3 -m unittest tests.scripts.test_agent_record.IssueIntakeTable` | 11 tests, `OK` | +| `git diff origin/main --numstat -- .agents/issue-index.md` | `11 0`, additions only | +| index rows | `origin/main` at `6354755ba` 620, this branch 624, counted on both sides because the union driver has silently dropped a tail row on a merge git called clean | +| owed numbers | 328 before, 330 after; the two added are #1749 and #1750 and nothing else | +| `UNOWNED_HIGH_WATER` vs actual | 33 vs 33, delta 0. Both appended dashed rows are owed below, which is the exemption #1749 is about | + +The `## Owed` section writes every OTHER issue number without its `#` for that +last reason. `owed_issues()` scrapes the section for any `#N`, so a normal +reference there would have claimed issues this row does not owe: the first +draft of that section raised the owed set by three instead of two. + ## 8. Stop conditions Stop and ask before repairing the STALE index rows this change makes @@ -434,3 +533,42 @@ case the old key would have refused. Recorded when the row reaches `DONE`. The measurements are in §7, and the two decisions most likely to be revisited are in §4: no cap on rows per issue, and no owner-ID existence check. + +## Owed + +Both were found by the fresh review of this change and both were reproduced here +before being written down, because relaying a finding is publishing it. Neither +is repaired in this flow: each is a checker semantic, and `AGENTS.md` routes a +checker semantic to its own row, spec, red-before test or mutation, and +green-after evidence. Filing them here rather than naming an owning row keeps +that debt visible under the row that found it. + +Every OTHER issue this section refers to is written without its `#`, and +deliberately. `owed_issues()` scrapes any `#N` and any `issues/N` out of this +section, which issue 1042 records as a defect, so a reference written normally +would silently claim an issue this row does not owe. The two numbers below are +the only ones owed. + +- [#1749](https://github.com/mudler/vllm.cpp/issues/1749). A dashed row appended + after an owned row for the same issue records ownership moving BACKWARDS, and + no gate sees it. The pair key admits the two rows as different keys, and the + `UNOWNED_HIGH_WATER` ratchet never counts the dashed row because + `check-agent-record.py:2034` exempts an issue any spec lists under `## Owed`. + Measured in §5: 328 owed numbers, and 226 of 621 rows carry both an owner and + an owed issue. A guard has to decide whether de-adoption is a regression to + refuse or a record to admit, which is why it is a row of its own and not a + line in this one. This entry sits inside the exemption it describes, and that + is the honest place for it: `AGENTS.md` admits `## Owed` as ownership, and + 1749 is about the ordering the count cannot see, not about the exemption. +- [#1750](https://github.com/mudler/vllm.cpp/issues/1750). `check_issue_index` + has one production call site, `scripts/check-agent-record.py:2125` inside + `main()`, and nothing proves the command runs it. Replacing that call with + `pass` leaves `tests/scripts/test_agent_record.py` at 113 tests `OK` and makes + the CLI accept a byte-identical duplicate row, which is the exact corruption + issue 1619 measured and the one case this refusal has ever caught in the + field. Inherited, not introduced: `git log -S'check_issue_index(errors)'` + returns one commit, `51e0cb5b1`, and this change touches only the body of the + function. The repair pattern already exists one class over at + `tests/scripts/test_agent_record.py:1667-1689`, where issue 1033 armed the + same question for `check_table_shapes` by driving `agent_record.main([])` and + capturing the real call rather than grepping the source. diff --git a/tests/scripts/test_agent_record.py b/tests/scripts/test_agent_record.py index 43bb4bcd0..97cc33acd 100644 --- a/tests/scripts/test_agent_record.py +++ b/tests/scripts/test_agent_record.py @@ -974,9 +974,15 @@ def test_a_dashed_row_and_an_owned_row_are_not_a_duplicate(self): """Adoption. `#85` is owned through a spec's `## Owed` and a row later takes it, which an append-only file can record only by appending. - The opposite order loses information and is already gated: a dashed row - appended after an owned one raises the unowned count and reds the - `UNOWNED_HIGH_WATER` ratchet. + The opposite order loses information and is NOT gated. This docstring + claimed the `UNOWNED_HIGH_WATER` ratchet catches it until #1749, which + measured otherwise: `check-agent-record.py` counts a dashed row only + `if row_id is None and number not in owed`, and an issue a row adopts is + normally the one a spec already lists under `## Owed`, so the dashed row + never enters the population and the count does not move. Measured on the + real index: 328 owed numbers, and 226 of 621 rows carry both an owner + and an owed issue. #1749 owes that guard. This case asserts only what it + is named for, that the two rows are not a duplicate. """ section = self.GOOD + ( "| [#85](https://github.com/mudler/vllm.cpp/issues/85) | `BACKEND-ROCM` | adopted | bug |\n"