fix(hp-2): anchor checker drops the extension allowlist (Codex P2 on #1444) (#1445)

* fix(hp-2): anchor checker drops the extension allowlist (Codex P2)

The list skipped the .sh anchor and the extensionless Server/Dockerfile:13.
Any path with a slash, or a basename with an alphabetic extension, now counts:
117 -> 119 checked, 0 unresolvable. Scorecard and plan counts updated.

* docs(b2-9,hp-2): record the #1444 squash SHA; Codex fix lands in the follow-up
This commit is contained in:
J3vb
2026-08-29 16:06:14 +02:00
committed by GitHub
parent 2bfc5e30d6
commit bf7b886df8
3 changed files with 25 additions and 8 deletions
@@ -857,7 +857,8 @@ New draft), not by CLI with the report text; their IDs are recorded in
PR bodies never name the mechanism (`docs/security.md`). PR bodies never name the mechanism (`docs/security.md`).
**Evidence, 2026-08-29** — branch `feat/b2-9-hp2` from `dev` `88c7a824`; **Evidence, 2026-08-29** — branch `feat/b2-9-hp2` from `dev` `88c7a824`;
PR to `dev` recorded below. HP-2 cites this block for exit-gate condition 7. PR #1444 to `dev`, squash-merged 2026-08-29 as `2bfc5e30`. HP-2 cites this
block for exit-gate condition 7.
- **SEC-03 verdict: B5, not B2.** Sized against the code the local report - **SEC-03 verdict: B5, not B2.** Sized against the code the local report
cites at `88c7a824` before deciding. What the register's closure line cites at `88c7a824` before deciding. What the register's closure line
@@ -920,7 +921,8 @@ readiness.
**Evidence, 2026-08-29** — the scorecard is **Evidence, 2026-08-29** — the scorecard is
[hp-2-scorecard-2026-08-29.md](hp-2-scorecard-2026-08-29.md), measured at [hp-2-scorecard-2026-08-29.md](hp-2-scorecard-2026-08-29.md), measured at
`83a535c3` on `feat/b2-9-hp2` (same PR as B2-9). `83a535c3` on `feat/b2-9-hp2` (same PR as B2-9: #1444, squash-merged
2026-08-29 as `2bfc5e30`).
- All seven questions answered with commands and their output; the B2 exit - All seven questions answered with commands and their output; the B2 exit
gate walked, nine conditions, all met (condition 1 at the slim one-epoch gate walked, nine conditions, all met (condition 1 at the slim one-epoch
@@ -933,8 +935,15 @@ readiness.
overwriting the one-per-account pin, and the holder side of OC-0316 overwriting the one-per-account pin, and the holder side of OC-0316
(resumed peer re-keyed with the rotated key). The last two were proven able (resumed peer re-keyed with the rotated key). The last two were proven able
to fail by temporary code mutation, restored with `git checkout`. to fail by temporary code mutation, restored with `git checkout`.
- `docs/plans/hp-2-trust-model-anchors.py` is the Question 3 check: 117 - `docs/plans/hp-2-trust-model-anchors.py` is the Question 3 check: 119
`path:line` anchors in `trust-model.md`, 0 unresolvable at HEAD. `path:line` anchors in `trust-model.md`, 0 unresolvable at HEAD.
- Codex review of `f3d6103d` (P2, accepted): the checker's extension
allowlist skipped the `.sh` anchor — and, found on the read-back, the
extensionless `Server/Dockerfile:13`. The allowlist is gone (any path with
a `/`, or a basename with an alphabetic extension); 117 → 119 checked, 0
unresolvable. #1444 was merged before the fix was pushed, so it lands in
a follow-up PR to `dev` (cherry-pick of `ed49426c`); no re-review
requested.
- Pre-squash SHAs: `a51e2e89` (Q4 tests), the commit carrying this block - Pre-squash SHAs: `a51e2e89` (Q4 tests), the commit carrying this block
(scorecard, this block, plan index, roadmap slice); B2-9's are in its block. (scorecard, this block, plan index, roadmap slice); B2-9's are in its block.
- **Owner lines, left blank on purpose:** the BPR-051 reader line in the B2-7 - **Owner lines, left blank on purpose:** the BPR-051 reader line in the B2-7
+5 -3
View File
@@ -147,7 +147,7 @@ one constant away (`minClientEpoch`) if a future epoch bump needs them.
## Question 3 — are the trust claims true? ## Question 3 — are the trust claims true?
`docs/trust-model.md` carries **117** `path:line` anchors and names **20** `docs/trust-model.md` carries **119** `path:line` anchors and names **20**
distinct Go tests plus the vitest cases in its E2EE table. The mechanical half distinct Go tests plus the vitest cases in its E2EE table. The mechanical half
of the question is whether every anchor still resolves on the measured tree: of the question is whether every anchor still resolves on the measured tree:
@@ -156,11 +156,13 @@ python docs/plans/hp-2-trust-model-anchors.py
``` ```
``` ```
117 path:line anchors checked (24 short-form resolved by unique basename), 0 unresolvable 119 path:line anchors checked (24 short-form resolved by unique basename), 0 unresolvable
``` ```
(The 24 short forms are the document's `file.go:NN` after a full path in the (The 24 short forms are the document's `file.go:NN` after a full path in the
same sentence; each resolves to exactly one tracked file.) Line-range drift same sentence; each resolves to exactly one tracked file. The checker has no
extension allowlist — Codex on #1444 caught the first version skipping the
`.sh` anchor, and `Server/Dockerfile:13` with it; 117 became 119.) Line-range drift
after a future edit is not caught by this check — it proves the file and the after a future edit is not caught by this check — it proves the file and the
line exist, not that the line still says what the sentence claims; the 11 line exist, not that the line still says what the sentence claims; the 11
Codex rounds on #1443 were the line-by-line read, every finding accepted and Codex rounds on #1443 were the line-by-line read, every finding accepted and
+8 -2
View File
@@ -1,7 +1,11 @@
"""Every `path:line[-line]` anchor in docs/trust-model.md must name a tracked """Every `path:line[-line]` anchor in docs/trust-model.md must name a tracked
file whose line count covers the cited line. A bare basename (the document's file whose line count covers the cited line. A bare basename (the document's
short form after a full path in the same sentence) resolves when exactly one short form after a full path in the same sentence) resolves when exactly one
tracked file has that basename. Prints the misses; exit 1 if any.""" tracked file has that basename. Prints the misses; exit 1 if any.
No extension allowlist (Codex on #1444): a path is anything with a directory
separator, or a bare name with an alphabetic extension. `Server/Dockerfile:13`
and `foo.sh:25-26` count; `8.8.8.8:80` does not."""
import os, re, subprocess, sys import os, re, subprocess, sys
doc = open("docs/trust-model.md", encoding="utf-8").read() doc = open("docs/trust-model.md", encoding="utf-8").read()
@@ -10,7 +14,9 @@ tracked_set = set(tracked)
by_base = {} by_base = {}
for p in tracked: for p in tracked:
by_base.setdefault(os.path.basename(p), []).append(p) by_base.setdefault(os.path.basename(p), []).append(p)
pat = re.compile(r"`([A-Za-z0-9_./-]+\.(?:go|ts|rs|md|json|yml|toml|sql)):(\d+)(?:-(\d+))?") pat = re.compile(
r"`((?:[A-Za-z0-9_.-]+/)+[A-Za-z0-9_.-]+|[A-Za-z0-9_-]+\.[A-Za-z][A-Za-z0-9]*):(\d+)(?:-(\d+))?"
)
seen, short, bad = 0, 0, [] seen, short, bad = 0, 0, []
for m in pat.finditer(doc): for m in pat.finditer(doc):
path, lo, hi = m.group(1), int(m.group(2)), int(m.group(3) or m.group(2)) path, lo, hi = m.group(1), int(m.group(2)), int(m.group(3) or m.group(2))