Skip to content

docs: repair every ADR link from the half that still identifies it, and close four bug-ledger rows - #1522

Merged
lusoris merged 3 commits into
masterfrom
chore/state-reconcile-2026-09-23
Sep 23, 2026
Merged

lusoris merged 3 commits into
masterfrom
chore/state-reconcile-2026-09-23

Conversation

@lusoris

@lusoris lusoris commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Three things found by diffing the tracked record against master. None of them was
red in CI, which is the point: each is a record or an assertion that quietly stopped
being true.

1. 98 ADR links under docs/ resolved to no file

An ADR link carries the decision's identity twice — as a number and as a slug —
and either half can rot alone. mkdocs build --strict catches none of it: it
validates the nav and page rendering, not the target of an inline relative link.

Half that rotted Repair
63 slug — the ADR was renamed from the number
35 number — a collision sweep renumbered the file from the slug, and the [ADR-NNNN] text

Root cause of the second group, read out of the history rather than guessed:
af227b026 (PR #310) and fb14bc332 (PR #752) were ADR collision sweeps for
duplicate numbers. The second renamed 50 files, moving
0241-vmaf-tiny-v3-mlp-medium.md to 0389-vmaf-tiny-v3-mlp-medium.md and 27 others
into the 0388–0415 band. Each moved the file and its index fragment and left every
inbound citation on the old number.

Slug-before-number is the whole design, and I got it wrong first. Repairing all
98 from the number was tried, and an independent two-pass review of the result
confirmed 39 sites where that silently repointed a citation at an unrelated
decision — [ADR-0241] in a tiny-AI evaluation digest became a link to the HIP PSNR
kernel-template ADR. Those links resolve, so they read as authoritative and
nothing complains afterwards: strictly worse than the dead link they replaced. That
review is also what recovered the two sweep commits, which turned a plausible
heuristic into a verified one — the slug is the half those sweeps preserved.

One citation resolves by neither half: ADR-0846 is a number the tree skips entirely
(0845 → 0848) and no ADR carries the cpp23-wave8 slug either. It is now plain text
rather than a link to a 404.

The gate is scripts/ci/check-adr-links.py, wired as the check-adr-links
pre-commit hook on any docs/ change. It reports rather than rewrites unless asked,
refuses to guess when neither half resolves or the halves disagree, and carries 16
cases including one that proves slug beats number when both could resolve.

Out of scope on purpose: a citation whose number and slug agree and are both the
wrong decision. That needs review, not a parser — T-STALE-ADR-CITATIONS-2026-09-16.

2. Three MCP tests asserted the wrong error depending on the invocation directory

test_vmaf_score_rejects_invalid_core_params passed ref/dis as the relative path
model/vmaf_v0.6.1.json, and _validate_path resolves a relative path against the
process CWD. From the repository root that lands on an allowlisted root and the three
cases raise the invalid pixfmt / invalid bitdepth / invalid backend they assert.
Run from mcp-server/vmaf-mcp/ they resolve outside the allowlist and all three fail
on not under an allowlisted root instead — the test silently stops asserting what
it names. CI runs from the root, so this was never red.

3. Two ledger rows disagreed with master

  • T-PRAETOR-README-GOVERNANCE-BLOCK-MISSING-2026-09-22 sat under Open bugs
    although the branch that fixed it merged. Verified on master: the managed block is
    in README.md and praetorctl audit reaches [PASS] README governance block verified against the recorded baseline.
  • T-CI-DOCS-JOB-TIMEOUT-2026-09-19 claimed the docs ceiling is 20 minutes; master
    carries 25. Corrected, with the measurement that forced the second raise.
  • T-CI-MYPY-PYTHON-VERSION-STALE-2026-09-19 closed — PR fix: drive whole tree toward zero warnings and HISS #1518 raised the pin to
    3.14. Checked that the residual is a different defect: mypy still stops early,
    now on module resolution, which T-CI-MYPY-JOB-CHECKS-NO-FILES-2026-09-21 tracks.
  • T-SPDX-INVALID-IDENTIFIER-2026-09-16 re-measured: residual 92 → 66, and the
    informal BSD+Patent occurrence it names is gone.

Type

  • docs — bug-ledger reconciliation and ADR link repair
  • test — new gate coverage and a test-fixture correctness fix

Reproducer

# the link drift, and the gate that now catches it
python3 scripts/ci/check-adr-links.py            # OK; exits 1 on any broken link
python3 scripts/ci/tests/test_check_adr_links.py # 16 cases

# the MCP defect, before the fix: 3 failed from the package directory ...
cd mcp-server/vmaf-mcp && PYTHONPATH=src python3 -m pytest \
  tests/test_score_extras_adr1117.py::test_vmaf_score_rejects_invalid_core_params -q
# ... and 3 passed from the repository root, same tests, same code.
# After: passes from both. Whole package suite from the package directory:
#   before: 3 failed, 374 passed, 40 skipped
#   after:  374 passed, 43 skipped

bash scripts/ci/check-state-md-rows.sh

ADR-0108 deep-dive deliverables

  • Research digest — no digest needed: the finding is one measurement (98
    broken links, split 63/35 by which half resolves) and one history lookup
    (PR fix(go): propagate ctx through subprocess and DB boundaries (S1 sweep) #310, PR docs(nav): add 10 orphaned pages to mkdocs.yml nav #752), both recorded in the checker's docstring and in
    docs/development/adr-workflow.md where a maintainer will actually meet them.
  • Decision matrix — in the commit body and the checker docstring: repair by
    number, by slug, or slug-first. The first was tried and measured wrong for 35
    of 98 links; the third is what shipped, because the collision sweeps preserved
    the slug.
  • AGENTS.md invariant note — no rebase-sensitive invariants: no public
    surface, no upstream-mirrored file.
  • Reproducer / smoke-test command — above.
  • CHANGELOG fragment — changelog.d/fixed/adr-link-slug-drift.md,
    changelog.d/fixed/state-ledger-reconcile-20260923.md,
    changelog.d/fixed/mcp-test-relative-fixture-cwd.md.
  • Rebase note — no rebase impact: docs, one CI script and one test fixture.

Bug-status hygiene

  • docs/state.md updated — two rows corrected, three closed, one filed and
    closed in the same change per ADR-0165.

Netflix golden-data gate

  • No python/test/ assertion touched.

@github-actions github-actions Bot added the type:docs Documentation updates label Sep 23, 2026
@lusoris
lusoris force-pushed the chore/state-reconcile-2026-09-23 branch 2 times, most recently from 34aba5a to bfcbe78 Compare September 23, 2026 06:57
T-PRAETOR-README-GOVERNANCE-BLOCK-MISSING-2026-09-22 was still filed under
Open bugs although the branch that fixed it merged. Verified on master
b1f2dc7 rather than inferred: README.md carries the managed block, and
praetorctl audit on a master-based tree reaches "[PASS] README governance
block verified against the recorded baseline" next to "[PASS] HISS invariant
scan verified: 276 active violations within 276 baselined limit". Moved to
Recently closed; the row was otherwise accurate.

T-CI-DOCS-JOB-TIMEOUT-2026-09-19 claimed the docs-build ceiling is 20
minutes. Master carries 25. The row was written when 20 was the fix, and the
second raise never reached it. The corrected text records why: the 20 came
from ubuntu-24.04 timings rather than the job, two runs that actually built
the site took 10m10s and 10m03s against the 10-minute budget, and mkdocs
alone logs 562.22 seconds -- the run that looked green was a dependency bump
the ADR-1140 planner skipped, so it never ran mkdocs.

Both were found by diffing the ledger against master while reconciling
issue #1238, whose checklist had 18 of 23 unticked boxes already closed.
…root

test_vmaf_score_rejects_invalid_core_params passed ref/dis as the relative
path model/vmaf_v0.6.1.json, and _validate_path resolves a relative path
against the process CWD. From the repository root that lands on an
allowlisted root, the call reaches the parameter checks, and the three cases
raise the invalid pixfmt / invalid bitdepth / invalid backend they assert.
Run from mcp-server/vmaf-mcp/ -- the natural place to run the package's own
suite -- the same paths resolve outside the allowlist and all three fail on
"not under an allowlisted root" instead, so the test silently stops asserting
what it names.

Measured on b1f2dc7: 3 failed, 374 passed from the package directory
against 3 passed from the root. The validator is correct in both cases and
CI runs from the root, so this was never red there; the defect is that the
assertion is a function of the invocation directory.

Anchored to srv._repo_root(), which the sibling tests in the same file
already use. Verified from both directories, and the package suite is clean
from the package directory where it previously reported three failures.

Filed and closed as T-MCP-TEST-RELATIVE-FIXTURE-CWD-2026-09-23 per ADR-0165.
@lusoris lusoris changed the title docs(state): reconcile the bug ledger with master, and fix three CWD-dependent MCP tests docs: repair every ADR link from the half that still identifies it, and gate the drift Sep 23, 2026
@lusoris lusoris changed the title docs: repair every ADR link from the half that still identifies it, and gate the drift docs: repair every ADR link from the half that still identifies it, and close four bug-ledger rows Sep 23, 2026
An ADR link carries the decision's identity twice, as a number and as a slug,
and either half can rot alone. 98 links under docs/ resolved to no file;
mkdocs --strict catches none of them, because it validates the nav and page
rendering, not the target of an inline relative link.

The two halves rot for different reasons, so they need different repairs:

  63 stale slug   the ADR was renamed. The number still names the right
                  decision, so the link is repaired from the number.

  35 wrong number an ADR collision sweep renumbered the file. The slug still
                  names the right decision, so the link is repaired from the
                  slug -- and so is the [ADR-NNNN] text, which carries the
                  wrong number too.

Root cause of the second group, read out of the history rather than guessed:
af227b0 (PR #310, 2026-05-03) and fb14bc3 (PR #752, 2026-05-10) were
collision sweeps for duplicate-numbered ADRs. The second renamed 50 files,
moving 0241-vmaf-tiny-v3-mlp-medium.md to 0389-vmaf-tiny-v3-mlp-medium.md and
27 others into the 0388-0415 band. Each sweep moved the file and its index
fragment and left every inbound citation on the old number.

Slug-before-number is the whole design, and it was got wrong first. Repairing
all 98 from the number was tried, and an independent two-pass review of the
result confirmed 39 sites where that silently repointed a citation at an
unrelated decision: [ADR-0241] in a tiny-AI evaluation digest became a link to
the HIP PSNR kernel-template ADR. Those links resolve, so they read as
authoritative and nothing complains afterwards -- strictly worse than the dead
link they replaced. The review also recovered the two sweep commits above,
which is what turned a plausible heuristic into a verified one: the slug is
the half those sweeps preserved.

One citation resolves by neither half. ADR-0846 is a number the tree skips
entirely, 0845 -> 0848, and no ADR carries the cpp23-wave8 slug either, so it
is now plain text rather than a link to a 404.

The gate is scripts/ci/check-adr-links.py, wired as the check-adr-links
pre-commit hook on any docs/ change. It reports rather than rewrites unless
asked, refuses to guess when neither half resolves or the halves disagree, and
carries 16 positive/negative/boundary cases (HISS-15) including one that
proves slug beats number when both could resolve. Documented in
docs/development/adr-workflow.md.

Deliberately out of scope: a citation whose number and slug agree and are both
the wrong decision. That needs review, not a parser --
T-STALE-ADR-CITATIONS-2026-09-16.

Also in this change, from the same pass over the ledger:
T-CI-MYPY-PYTHON-VERSION-STALE-2026-09-19 is closed (PR #1518 raised the pin
to 3.14; the residual is module resolution, which
T-CI-MYPY-JOB-CHECKS-NO-FILES-2026-09-21 already tracks), and
T-SPDX-INVALID-IDENTIFIER-2026-09-16's residual is re-measured from 92 to 66
with its BSD+Patent occurrence now gone.
@lusoris
lusoris force-pushed the chore/state-reconcile-2026-09-23 branch from bfcbe78 to 693686d Compare September 23, 2026 08:08
@lusoris
lusoris merged commit 301c2b5 into master Sep 23, 2026
81 checks passed
@lusoris
lusoris deleted the chore/state-reconcile-2026-09-23 branch September 23, 2026 08:48
lusoris added a commit that referenced this pull request Sep 23, 2026
clean. It was clean only of the spelling it matched: an ADR cites a
sibling as `(0530-slug.md)`, with no `adr/` segment, and one under
`docs/adr/by-tag/` as `(../0530-slug.md)`. 237 of those resolved to no
file. Making the segment optional finds them; admitting the bare form
only for files under `docs/adr/` keeps `docs/research/`, which names its
digests `NNNN-slug.md` too, from being read as broken ADR citations.

The population inverts inside `docs/adr/`. For the qualified links the
slug was usually the surviving half; here 196 of 237 carry a slug that
names no ADR at all, leaving only the number -- and for 56 of those the
number had been reallocated by the collision sweeps. Repairing them from
the number would have pointed
`[ADR-0033](0033-hip-applicability.md)`, cited in ADR-0315 as the
precedent for fork-side GPU ports, at `codeql-config-moved-to-github`,
and `[ADR-0009](0009-batch-a-upstream-port-strategy.md)`, cited there as
the fork's demand-pull pattern, at the MCP server tool surface. That is
the failure #1522 exists to prevent, arriving from the other direction.

So a by-number repair now has to be corroborated by the target's own
title and abstract, and the corroboration weighs the words that identify
a decision over the words a family shares. The measurement that forces
that weighting: `[ADR-0138 -- PSNR-HVS SIMD bit-exactness]` cited
`0138-psnr-hvs-simd-bitexact`, and `0138-iqa-convolve-avx2-bitexact-double`
does say "simd" and "bitexact" -- it is a sibling in that family, not the
same decision, and it says nothing about PSNR-HVS. Counting shared words
admits it; ranking `hvs` (3 ADRs) above `simd` does not. A third rule
resolves a reordered slug from the slug half:
`0335-sycl-adaptivecpp-second-toolchain` is
`0407-adaptivecpp-second-sycl-toolchain` with two words swapped, and 0335
now belongs to an ADR about hardware capability priors.

181 links were repaired mechanically -- 35 by exact slug, 2 by reordered
slug, 144 by corroborated number -- and 56 by hand:

  * 26 repaired against evidence. Some from the target's own text
    (ADR-0164 discusses the EOTF and cbrt LUT the citation names; ADR-0269
    carries the barrier pattern; ADR-0161 is the only ADR that discusses
    the SSIMULACRA2 IIR blur). Some from `git log`: `0371-cambi-sycl-port.md`
    is now `0415-cambi-sycl-port.md`, and `0199-tiny-ai-netflix-training-corpus.md`
    is now `0242-...`, so those citations named the right decision before it
    moved.

  * 30 de-linked, because the cited ADR was never written under any
    number and the number now belongs to something else. The visible text
    is kept exactly, so the rendered prose is unchanged and only the
    hyperlink goes. ADR-0864, ADR-0867 and ADR-0979 are the clearest
    case: all three are cited as in-flight or proposed, and none landed.
    Two more were left de-linked rather than guessed -- ADR-0509 in
    ADR-0542, because that file already cites ADR-0514 on the next line,
    so the author meant a second ADR; and the PSNR-HVS citation in
    ADR-0918, because 0159 (AVX2) and 0160 (NEON) both carry the
    FP_CONTRACT pragma and the citation does not say which.

Tests go from 16 to 24, covering the sibling form from both `docs/adr/`
and its subdirectory, the research-digest exclusion, corroborated and
uncorroborated number repairs, the filler-word floor, and reordered
slugs beating both the number and each other.

Two pre-existing MD013 violations in `0691-vmafx-drop-legacy-build-paths.md`
and `0646-dnn-attached-multi-output.md` are wrapped: the files are touched
here, and ADR-0141 makes a touched file lint-clean.

Not fixed here, and recorded in `docs/state.md`: fifteen ADR numbers are
cited for decisions nobody wrote. Writing them, or recording them as
abandoned, is a separate job. Still unchecked by any gate: a citation
where both halves agree and both name the wrong decision.
lusoris added a commit that referenced this pull request Sep 23, 2026
)

The gate shipped in #1522 matched only `adr/NNNN-slug.md`, so the bare
`(NNNN-slug.md)` form ADRs use to cite each other was invisible to it: 237
broken sibling links under docs/adr/ while it reported the tree clean. Bare
links now count, but only for files under docs/adr/, since docs/research/ names
its digests the same way.

Repairing them by number would have been worse than leaving them dead. 196 of
the 237 carry a slug naming no ADR at all, and for 56 the number had been
reallocated by the collision sweeps -- [ADR-0033](0033-hip-applicability.md),
cited as the precedent for fork-side GPU ports, would have become a link to
codeql-config-moved-to-github. A by-number repair now has to be corroborated by
the target own title and abstract, weighing the words that identify a decision
over the words a family shares: [ADR-0138 -- PSNR-HVS SIMD bit-exactness] cited
0138-psnr-hvs-simd-bitexact, and 0138-iqa-convolve-avx2-bitexact-double does
say "simd" and "bitexact" -- it is a sibling in that family, not the same
decision.

181 links repaired mechanically, 56 by hand. Of those, 38 were repaired against
evidence and 18 de-linked. The last twelve needed the git history of the citing
commit rather than either half of the filename: the citation reading "fork PR
#60 CUDA framesync hardening" resolves because d3b6fad is both PR #60 and the
commit that created 0122-cuda-gencode-coverage-and-init-hardening.md. The
number was right all along; the slug had been minted from a docs/state.md
bug-row label, and the ADR never uses the word "framesync", which is why a
text-match check dismissed it.

Nine citations stay plain text on purpose: their decision exists only in a
commit message, a PR title or a state.md row, and linking them would invent an
authority that does not exist.

Tests go 16 -> 24.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:docs Documentation updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant