fix: audit repository scope coverage #49

Merged
andres merged 2 commits from build/48-scope-coverage into main 2026-09-01 14:16:53 +00:00

Refs #48

Summary

  • widen the existing five scope mappings to cover the repository surfaces they already describe
  • audit tracked-path coverage with an explicit residue allowlist
  • enforce two-way scope-name parity between the label configuration files

Acceptance criteria

  • Every tracked path matches at least one labeler glob except .gitignore, assets/logo-mark.svg, and the seven test/*.test.js files.
  • The same five scope:* names remain in both config files and two-way parity is machine-enforced.
  • The three rewritten label descriptions name the paths their globs match.
  • Governance fails on an uncovered tracked path while preserving its success output.
  • The rewritten coverage test fails against the pre-change labeler map.
  • CONTRIBUTING.md's scope:* section corresponds to labels.conf: the same five names
    (this issue adds and removes none), and each row's Covers cell describes the same path set
    as that row's labels.conf description — the three rewritten rows updated, scope:cli and
    scope:manifests untouched. Formatting is not a mismatch: §3 is a human-readable
    restatement, byte-equality was never #46's contract, and zero of the five rows are
    byte-equal today (measured on main; see the 13:41Z comment). npm test && npm run check:governance is green.
  • Post-merge bootstrap and live-label verification are owned by triage.

Worklog

  • Rewrite the repository mapping test as a tracked-tree coverage assertion.
  • Widen the five existing mappings and align config/documentation descriptions.
  • Add validator coverage enforcement with the ruled residue allowlist.
  • Add two-way scope-name parity enforcement and both negative cases.
  • Add the cited changelog fragment.
  • Run the complete acceptance and must-fail verification matrix.
Refs #48 ## Summary - widen the existing five scope mappings to cover the repository surfaces they already describe - audit tracked-path coverage with an explicit residue allowlist - enforce two-way scope-name parity between the label configuration files ## Acceptance criteria - [x] Every tracked path matches at least one labeler glob except `.gitignore`, `assets/logo-mark.svg`, and the seven `test/*.test.js` files. - [x] The same five `scope:*` names remain in both config files and two-way parity is machine-enforced. - [x] The three rewritten label descriptions name the paths their globs match. - [x] Governance fails on an uncovered tracked path while preserving its success output. - [x] The rewritten coverage test fails against the pre-change labeler map. - [x] `CONTRIBUTING.md`'s `scope:*` section **corresponds** to `labels.conf`: the same five names (this issue adds and removes none), and each row's *Covers* cell describes the same path set as that row's `labels.conf` description — the three rewritten rows updated, `scope:cli` and `scope:manifests` untouched. **Formatting is not a mismatch**: §3 is a human-readable restatement, byte-equality was never #46's contract, and zero of the five rows are byte-equal today (measured on `main`; see the 13:41Z comment). `npm test && npm run check:governance` is green. - [ ] Post-merge bootstrap and live-label verification are owned by triage. ## Worklog - [x] Rewrite the repository mapping test as a tracked-tree coverage assertion. - [x] Widen the five existing mappings and align config/documentation descriptions. - [x] Add validator coverage enforcement with the ruled residue allowlist. - [x] Add two-way scope-name parity enforcement and both negative cases. - [x] Add the cited changelog fragment. - [x] Run the complete acceptance and must-fail verification matrix.
codex-bot-andresmgsl added 1 commit 2026-09-01 13:40:32 +00:00
fix: cover repository scope surfaces
All checks were successful
labels / labels (pull_request) Successful in 10s
ci / test (pull_request) Successful in 16s
112f946802
forgejo-actions added the
state:addressing
label 2026-09-01 13:40:47 +00:00
codex-bot-andresmgsl changed title from fix: audit repository scope coverage to WIP: fix: audit repository scope coverage 2026-09-01 13:40:50 +00:00
forgejo-actions added
state:building
and removed
state:addressing
labels 2026-09-01 13:42:18 +00:00
codex-bot-andresmgsl added 1 commit 2026-09-01 13:42:35 +00:00
test: enforce scope coverage and parity
All checks were successful
labels / labels (pull_request) Successful in 10s
ci / test (pull_request) Successful in 15s
d84062af54
forgejo-actions added the
scope:packaging
label 2026-09-01 13:42:44 +00:00
Author
Member

📣 round answered at head d84062af54

📣 round answered at head d84062af54659f9e0acdbbb1ff3f525c4cc43441
codex-bot-andresmgsl changed title from WIP: fix: audit repository scope coverage to fix: audit repository scope coverage 2026-09-01 13:44:09 +00:00
codex-bot-andresmgsl requested review from glm-bot-andresmgsl 2026-09-01 13:48:26 +00:00
codex-bot-andresmgsl requested review from claude-bot-andresmgsl 2026-09-01 13:48:26 +00:00
codex-bot-andresmgsl requested review from kimi-bot-andresmgsl 2026-09-01 13:48:27 +00:00
codex-bot-andresmgsl added the
state:bots-reviewing
label 2026-09-01 13:48:27 +00:00
forgejo-actions added
scope:ci
scope:docs
and removed
state:building
labels 2026-09-01 13:48:45 +00:00

🔎 reviewing head d84062af54

Ran in a detached worktree at this head (npm ci first).

  • AC1 tracked-path coverage — settled: 42 tracked paths, uncovered set is exactly .gitignore, assets/logo-mark.svg, and the seven test/*.test.js files.
  • AC2 machine-enforced two-way name parity — settled: both directions fail loudly on the real repo.
  • AC3 three rewritten descriptions name their globs — settled.
  • AC4 governance fails on an uncovered tracked path, success line preserved — settled.
  • AC5 rewritten coverage test fails against the pre-change map — settled.
  • AC6 CONTRIBUTING §3 correspondence, same five names, scope:cli/scope:manifests untouched — settled.
  • AC7 post-merge bootstrap — triage's, correctly left unticked.
  • Must-pass 3 (.ceremony/ + root AGENTS.md untouched) — settled, diff empty.

Verdict next.

🔎 reviewing head d84062af54659f9e0acdbbb1ff3f525c4cc43441 Ran in a detached worktree at this head (`npm ci` first). - AC1 tracked-path coverage — **settled**: 42 tracked paths, uncovered set is exactly `.gitignore`, `assets/logo-mark.svg`, and the seven `test/*.test.js` files. - AC2 machine-enforced two-way name parity — **settled**: both directions fail loudly on the real repo. - AC3 three rewritten descriptions name their globs — **settled**. - AC4 governance fails on an uncovered tracked path, success line preserved — **settled**. - AC5 rewritten coverage test fails against the pre-change map — **settled**. - AC6 CONTRIBUTING §3 correspondence, same five names, `scope:cli`/`scope:manifests` untouched — **settled**. - AC7 post-merge bootstrap — triage's, correctly left unticked. - Must-pass 3 (`.ceremony/` + root `AGENTS.md` untouched) — **settled**, diff empty. Verdict next.

🔎 reviewing head d84062af54
progress:

  • spec + amendments read (issue #48, 13:26Z/13:41Z amendments; criterion-6 re-sync verified in PR body)
  • worktree detached at head; whole-diff review of 6 files; .ceremony/ + AGENTS.md untouched (must-pass 3)
  • npm test 133/133 green; npm run check:governance green, success line preserved
  • must-fail 5 ✓ (uncovered staged path -> exit 1, path named)
  • must-fail 6 ✓ (rewritten coverage test fails vs pre-change labeler)
  • must-fail 7 ✓ both directions (sixth labeler row; labels.conf rename -> exit 1, names named)
  • criterion 1 independently cross-checked under ceremony 0.6.3 labels-scope glob engine: 42 tracked paths, only ruled 9 residue unmatched
  • Refs #48 shape clean: no closing keyword precedes #48; criterion 7 is triage post-merge
  • CI at head: combined status success; labels job already derived scope:ci+docs+packaging from the widened map
  • verdict: approve — submitting
🔎 reviewing head d84062af54659f9e0acdbbb1ff3f525c4cc43441 progress: - spec + amendments read (issue #48, 13:26Z/13:41Z amendments; criterion-6 re-sync verified in PR body) - worktree detached at head; whole-diff review of 6 files; .ceremony/ + AGENTS.md untouched (must-pass 3) - npm test 133/133 green; npm run check:governance green, success line preserved - must-fail 5 ✓ (uncovered staged path -> exit 1, path named) - must-fail 6 ✓ (rewritten coverage test fails vs pre-change labeler) - must-fail 7 ✓ both directions (sixth labeler row; labels.conf rename -> exit 1, names named) - criterion 1 independently cross-checked under ceremony 0.6.3 labels-scope glob engine: 42 tracked paths, only ruled 9 residue unmatched - Refs #48 shape clean: no closing keyword precedes #48; criterion 7 is triage post-merge - CI at head: combined status success; labels job already derived scope:ci+docs+packaging from the widened map - verdict: approve — submitting

🔎 reviewing head d84062af54

  • Coverage: verified every tracked path matches a glob in labeler.yml except .gitignore, assets/logo-mark.svg, and the seven test/*.test.js files; used a Python glob probe because node/npm are absent from this box.
  • Scope-name parity: labels.conf and labeler.yml carry exactly the same five scope:* names; CONTRIBUTING.md §3 lists the same five.
  • Descriptions: the three rewritten labels.conf rows name the path sets their globs match, and CONTRIBUTING.md §3 restates those path sets in its own voice.
  • No changes under .ceremony/ or to root AGENTS.md.
  • Could not run npm test or npm run check:governance: node and npm are not installed in this box; relied on manual reading/probe and the existing CI expectation.
🔎 reviewing head d84062af54659f9e0acdbbb1ff3f525c4cc43441 - Coverage: verified every tracked path matches a glob in labeler.yml except .gitignore, assets/logo-mark.svg, and the seven test/*.test.js files; used a Python glob probe because node/npm are absent from this box. - Scope-name parity: labels.conf and labeler.yml carry exactly the same five scope:* names; CONTRIBUTING.md §3 lists the same five. - Descriptions: the three rewritten labels.conf rows name the path sets their globs match, and CONTRIBUTING.md §3 restates those path sets in its own voice. - No changes under .ceremony/ or to root AGENTS.md. - Could not run npm test or npm run check:governance: node and npm are not installed in this box; relied on manual reading/probe and the existing CI expectation.
claude-bot-andresmgsl approved these changes 2026-09-01 13:56:42 +00:00
claude-bot-andresmgsl left a comment
Member

Approve — head d84062af54659f9e0acdbbb1ff3f525c4cc43441.

Reviewed the whole PR at this head in a detached worktree (npm ci first, per the phantom-failure trap this repo has bitten me with before). All six pre-merge criteria of #48 are met, and I verified each by running it rather than by reading.

What I ran

check result
npm test 133/133 pass
npm run check:governance exit 0, governance: 4 identities resolved; 5 scope rows valid — success line unchanged (AC4)
independent coverage recomputation 42 tracked paths; uncovered = exactly .gitignore, assets/logo-mark.svg, and the seven test/*.test.js files (AC1)
must-fail 5: git add -N newsurface/thing.txt governance: tracked paths have no scope mapping: newsurface/thing.txt
must-fail 6: test/governance.test.js against origin/main's labeler.yml not ok 9 - repository scope mapping covers every tracked path except the ruled residue — it fails, so it tests coverage and not the old globs (AC5)
must-fail 7a: sixth row in labeler.yml only scope names only in labeler.yml: scope:extra
must-fail 7b: rename scope:manifestsscope:data in labels.conf only scope names only in labels.conf: scope:data; scope names only in labeler.yml: scope:manifests — the direction that was blind before this PR is now caught (AC2)
must-pass 3: git diff --name-only origin/main..HEAD -- .ceremony/ AGENTS.md empty — mirror and root router untouched (must-fail 8 clean)

The 7b result is the one that matters most: #48's 13:26Z amendment measured that a labels.conf-side rename was undetectable, and that replacing L123's frozen glob list would have opened the other direction too. Both directions now exit non-zero naming the offending names, and the coverage assertion replacing L123 is provably not vacuous.

AC3 — each rewritten description names its globs and nothing else: scripts/+release workflow+package manifests+changelog+fragments ↔ scripts/**, .forgejo/workflows/release.yml, package.json, package-lock.json, CHANGELOG.md, changelog.d/**; .forgejo/workflows/+.github/+.ceremony/ ↔ the same three globs; root Markdown+docs/*.md, docs/**.

AC6 — hand-checked, since #46 recorded that nothing automates the CONTRIBUTING.md leg: same five names in all three files, the three rewritten rows describe the same path sets as their labels.conf rows, and scope:cli / scope:manifests are untouched (the diff changes exactly three table rows). Correspondence, not byte-equality, as the 13:41Z amendment ruled.

AC7 correctly left unticked, and Refs #48 is the right keyword — the only other issue number in the body is #46's contract, preceded by "never", so no closing keyword precedes a number anywhere.

Glob semantics, checked against the pinned consumer

I read ceremony 0.6.3's actions/labels-scope/labels-scope.sh at its Forgejo tag (not main, and not the GitHub tree of the same name). Its contract — ** crosses /, * and ? do not, whole path must match — agrees with Node's path.matchesGlob on every path in this tree: I confirmed *.md matches AGENTS.md but not docs/DESIGN.md or .ceremony/AGENTS.md, so scope:docs really is root-prose-only, and .github/** / .ceremony/** cover their trees. path.matchesGlob landed in v22.5.0, under the >=22.12.0 engines floor.

Non-blocking nits

  1. One documented divergence from the pinned consumer: leading dots. labels-scope.sh says explicitly "a leading dot is not special"; Node's path.matchesGlob treats it as special. Measured: path.matchesGlob('.github/.keep', '.github/**') === false, likewise docs/.nojekyll under docs/**. The divergence runs in the safe direction — the validator would report such a file uncovered and fail loudly, where the real labeler would have scoped it — so it can only produce a false alarm, never a false coverage claim. No such path exists today. Worth a comment beside validateTrackedPaths so the next person to add a .nojekyll knows why the guard shouted.
  2. git ls-files without -z. With core.quotePath at its default, a non-ASCII tracked path comes back C-quoted ("caf\303\251.md") and reads as uncovered. Same in the rewritten test at L211. Safe direction again, and no such path exists; -z or -c core.quotePath=false would close it.
  3. A missing labeler.yml beside --config surfaces as a raw ENOENT rather than a governance-voiced message. Every other failure in this script names its cause.
  4. The test at L207 restates the allowlist instead of sharing UNSCOPED_PATHS with the validator, so drift between the two lists is undetected. Defensible as an independent restatement — flagging only so the choice is deliberate.
  5. test/governance.test.js requires node:child_process twice (L3, L4).
  6. validateScopeNames compares every labels.conf row against the labeler keys, where #48 wrote "the set of scope:* rows". The two readings coincide: .ceremony/LABELS.md L225 defines labels.conf as "one name|color|description row per scope", so a non-scope row there is already out of contract. No change wanted; recording that I checked rather than assumed.

What I could not verify, and what I relied on instead

  • AC7 (post-merge bootstrap, ids 272/274/275) is triage's and unrunnable here; I checked only that it is unticked and that Refs #48 matches its post-merge shape.
  • The live labelling half. I did not execute labels-scope; I read it at the 0.6.3 pin. Note for triage rather than for this PR: it reads labeler.yml at CONFIG_REF, the base ref, so the widened map governs PRs only from the merge forward — which is exactly what #48's out-of-scope section and criterion 7 already say.
  • CI. The combined status on this head reads success, but each individual entry reports state: null on this instance, so I did not treat the badge as evidence — the table above is my own run in the worktree.
  • The CI container's checkout shape. Both the validator and the rewritten test now hard-depend on git ls-files succeeding in the workspace, which is new environmental surface. I did not run the Forgejo workflow. node:22-bookworm ships git, and clone.test.js/sync.test.js already shell out to it, so the binary is proven present; what I did not prove is that actions/checkout@v4 leaves a .git directory on this runner. If a future runner ever falls back to a tarball checkout, check:governance fails closed with cannot enumerate tracked paths — loud, not silent, which is the right failure.
**Approve** — head `d84062af54659f9e0acdbbb1ff3f525c4cc43441`. Reviewed the whole PR at this head in a detached worktree (`npm ci` first, per the phantom-failure trap this repo has bitten me with before). All six pre-merge criteria of #48 are met, and I verified each by running it rather than by reading. ## What I ran | check | result | | --- | --- | | `npm test` | **133/133 pass** | | `npm run check:governance` | exit 0, `governance: 4 identities resolved; 5 scope rows valid` — success line unchanged (AC4) | | independent coverage recomputation | 42 tracked paths; uncovered = exactly `.gitignore`, `assets/logo-mark.svg`, and the seven `test/*.test.js` files (AC1) | | must-fail 5: `git add -N newsurface/thing.txt` | `governance: tracked paths have no scope mapping: newsurface/thing.txt` | | must-fail 6: `test/governance.test.js` against `origin/main`'s `labeler.yml` | `not ok 9 - repository scope mapping covers every tracked path except the ruled residue` — it fails, so it tests coverage and not the old globs (AC5) | | must-fail 7a: sixth row in `labeler.yml` only | `scope names only in labeler.yml: scope:extra` | | must-fail 7b: rename `scope:manifests` → `scope:data` in `labels.conf` only | `scope names only in labels.conf: scope:data; scope names only in labeler.yml: scope:manifests` — the direction that was blind before this PR is now caught (AC2) | | must-pass 3: `git diff --name-only origin/main..HEAD -- .ceremony/ AGENTS.md` | empty — mirror and root router untouched (must-fail 8 clean) | The 7b result is the one that matters most: #48's 13:26Z amendment measured that a `labels.conf`-side rename was undetectable, and that replacing L123's frozen glob list would have opened the other direction too. Both directions now exit non-zero naming the offending names, and the coverage assertion replacing L123 is provably not vacuous. **AC3** — each rewritten description names its globs and nothing else: `scripts/`+release workflow+package manifests+changelog+fragments ↔ `scripts/**`, `.forgejo/workflows/release.yml`, `package.json`, `package-lock.json`, `CHANGELOG.md`, `changelog.d/**`; `.forgejo/workflows/`+`.github/`+`.ceremony/` ↔ the same three globs; root Markdown+`docs/` ↔ `*.md`, `docs/**`. **AC6** — hand-checked, since #46 recorded that nothing automates the `CONTRIBUTING.md` leg: same five names in all three files, the three rewritten rows describe the same path sets as their `labels.conf` rows, and `scope:cli` / `scope:manifests` are untouched (the diff changes exactly three table rows). Correspondence, not byte-equality, as the 13:41Z amendment ruled. **AC7** correctly left unticked, and `Refs #48` is the right keyword — the only other issue number in the body is `#46's contract`, preceded by "never", so no closing keyword precedes a number anywhere. ## Glob semantics, checked against the pinned consumer I read ceremony `0.6.3`'s `actions/labels-scope/labels-scope.sh` at its Forgejo tag (not `main`, and not the GitHub tree of the same name). Its contract — `**` crosses `/`, `*` and `?` do not, whole path must match — agrees with Node's `path.matchesGlob` on every path in this tree: I confirmed `*.md` matches `AGENTS.md` but not `docs/DESIGN.md` or `.ceremony/AGENTS.md`, so `scope:docs` really is root-prose-only, and `.github/**` / `.ceremony/**` cover their trees. `path.matchesGlob` landed in v22.5.0, under the `>=22.12.0` engines floor. ## Non-blocking nits 1. **One documented divergence from the pinned consumer: leading dots.** `labels-scope.sh` says explicitly *"a leading dot is not special"*; Node's `path.matchesGlob` treats it as special. Measured: `path.matchesGlob('.github/.keep', '.github/**') === false`, likewise `docs/.nojekyll` under `docs/**`. The divergence runs in the safe direction — the validator would report such a file uncovered and fail loudly, where the real labeler would have scoped it — so it can only produce a false alarm, never a false coverage claim. No such path exists today. Worth a comment beside `validateTrackedPaths` so the next person to add a `.nojekyll` knows why the guard shouted. 2. **`git ls-files` without `-z`.** With `core.quotePath` at its default, a non-ASCII tracked path comes back C-quoted (`"caf\303\251.md"`) and reads as uncovered. Same in the rewritten test at L211. Safe direction again, and no such path exists; `-z` or `-c core.quotePath=false` would close it. 3. **A missing `labeler.yml` beside `--config` surfaces as a raw `ENOENT`** rather than a governance-voiced message. Every other failure in this script names its cause. 4. **The test at L207 restates the allowlist** instead of sharing `UNSCOPED_PATHS` with the validator, so drift between the two lists is undetected. Defensible as an independent restatement — flagging only so the choice is deliberate. 5. `test/governance.test.js` requires `node:child_process` twice (L3, L4). 6. `validateScopeNames` compares *every* `labels.conf` row against the labeler keys, where #48 wrote "the set of `scope:*` rows". The two readings coincide: `.ceremony/LABELS.md` L225 defines `labels.conf` as "one `name|color|description` row per scope", so a non-scope row there is already out of contract. No change wanted; recording that I checked rather than assumed. ## What I could not verify, and what I relied on instead - **AC7 (post-merge bootstrap, ids 272/274/275)** is triage's and unrunnable here; I checked only that it is unticked and that `Refs #48` matches its post-merge shape. - **The live labelling half.** I did not execute `labels-scope`; I read it at the `0.6.3` pin. Note for triage rather than for this PR: it reads `labeler.yml` at `CONFIG_REF`, the *base* ref, so the widened map governs PRs only from the merge forward — which is exactly what #48's out-of-scope section and criterion 7 already say. - **CI.** The combined status on this head reads `success`, but each individual entry reports `state: null` on this instance, so I did not treat the badge as evidence — the table above is my own run in the worktree. - **The CI container's checkout shape.** Both the validator and the rewritten test now hard-depend on `git ls-files` succeeding in the workspace, which is new environmental surface. I did not run the Forgejo workflow. `node:22-bookworm` ships `git`, and `clone.test.js`/`sync.test.js` already shell out to it, so the binary is proven present; what I did not prove is that `actions/checkout@v4` leaves a `.git` directory on this runner. If a future runner ever falls back to a tarball checkout, `check:governance` fails closed with `cannot enumerate tracked paths` — loud, not silent, which is the right failure.
kimi-bot-andresmgsl approved these changes 2026-09-01 13:58:08 +00:00
kimi-bot-andresmgsl left a comment
Member

Reviewed against #48 acceptance criteria and stoke's load-bearing constraints.

Verified

  • Coverage: every tracked path in the PR head matches at least one labeler glob except the explicit residue (.gitignore, assets/logo-mark.svg, and the seven test/*.test.js files). Checked with a Python glob probe because node is absent from this box.
  • Scope-name parity: .github/labels.conf and .github/labeler.yml carry exactly the same five scope:* names; CONTRIBUTING.md §3 lists the same five.
  • Descriptions: the three rewritten labels.conf rows name the path sets their globs match, and CONTRIBUTING.md §3 restates those path sets in its own voice (scope:cli and scope:manifests untouched).
  • Guard logic: scripts/check-governance.js now asserts two-way name parity and unmapped-tracked-path coverage with a three-entry commented allowlist, while preserving the existing CLI contract and success line.
  • Tests: test/governance.test.js adds failing cases for an uncovered tracked path, a scope name only in labeler.yml, and a scope name only in labels.conf; the rewritten coverage test would fail against the pre-change labeler.yml map.
  • No edits under .ceremony/ or to root AGENTS.md.
  • Changelog fragment changelog.d/48.md is present.

Could not verify

  • npm test && npm run check:governance could not be run because node and npm are not installed in this box. I relied on manual code reading and the Python coverage probe above; the existing .forgejo/workflows/ci.yml gate is expected to exercise these commands.

Approve.

Reviewed against #48 acceptance criteria and stoke's load-bearing constraints. Verified - Coverage: every tracked path in the PR head matches at least one labeler glob except the explicit residue (`.gitignore`, `assets/logo-mark.svg`, and the seven `test/*.test.js` files). Checked with a Python glob probe because node is absent from this box. - Scope-name parity: `.github/labels.conf` and `.github/labeler.yml` carry exactly the same five `scope:*` names; `CONTRIBUTING.md` §3 lists the same five. - Descriptions: the three rewritten `labels.conf` rows name the path sets their globs match, and `CONTRIBUTING.md` §3 restates those path sets in its own voice (`scope:cli` and `scope:manifests` untouched). - Guard logic: `scripts/check-governance.js` now asserts two-way name parity and unmapped-tracked-path coverage with a three-entry commented allowlist, while preserving the existing CLI contract and success line. - Tests: `test/governance.test.js` adds failing cases for an uncovered tracked path, a scope name only in `labeler.yml`, and a scope name only in `labels.conf`; the rewritten coverage test would fail against the pre-change `labeler.yml` map. - No edits under `.ceremony/` or to root `AGENTS.md`. - Changelog fragment `changelog.d/48.md` is present. Could not verify - `npm test && npm run check:governance` could not be run because node and npm are not installed in this box. I relied on manual code reading and the Python coverage probe above; the existing `.forgejo/workflows/ci.yml` gate is expected to exercise these commands. Approve.
glm-bot-andresmgsl approved these changes 2026-09-01 13:59:13 +00:00
glm-bot-andresmgsl left a comment
Member

Verdict: approve — head d84062af54659f9e0acdbbb1ff3f525c4cc43441, reviewed whole against #48 as amended (13:26Z and 13:41Z amendments; the PR body carries the amended criterion 6 verbatim, as triage's 13:43Z comment asked).

Acceptance criteria 1–6 — verified, not opined (criterion 7 is triage's post-merge item; the Refs #48 shape is correct and no closing keyword precedes #48 anywhere in the PR body):

  1. Coverage at head — run twice: (a) npm run check:governance green in a detached worktree at the head; (b) an independent cross-check sourcing ceremony 0.6.3's own parse_labeler_config + glob_to_regex from the pinned tag and matching them against git ls-files: 42 tracked paths, every one matched except exactly .gitignore, assets/logo-mark.svg, and the seven test/*.test.js files.
  2. Name parity, machine-enforced both directions — validator green on the tree; perturbation probes: a sixth scope:brand row added to labeler.yml alone → exit 1 scope names only in labeler.yml: scope:brand; scope:manifestsscope:data in labels.conf alone → exit 1 naming both offenders. No name added/removed/renamed in the diff.
  3. Three rewritten descriptions — each names exactly what its globs match ("package manifests" ↔ the two package files, "fragments" ↔ changelog.d/**, etc.); no path claimed that isn't matched.
  4. Failure + preserved contract — staged new-surface/uncovered.txt → exit 1 tracked paths have no scope mapping: new-surface/uncovered.txt; success output still ends governance: 4 identities resolved; 5 scope rows valid; --config/--api-url flags and exit behaviour unchanged.
  5. Rewritten test fails on the pre-change map — old labeler.yml swapped in at the head → not ok 1 - repository scope mapping covers every tracked path except the ruled residue, listing .ceremony/* and the other genuinely-uncovered paths. It tests coverage, not the old glob list.
  6. CONTRIBUTING §3 correspondence — same five names; the three rewritten Covers cells mirror the new labels.conf descriptions in §3's own voice; scope:cli and scope:manifests untouched (their §3 rows remain the byte-unequal restatement #46 shipped, which the amended criterion explicitly permits).

Test plan: must-pass 1–4 all run green (3: .ceremony/+AGENTS.md diff empty; 4's CONTRIBUTING.md leg is the hand-check above). Must-fail 5–7 all demonstrated above with actual non-zero exits and named offenders. Must-fail 8 n/a — no mirror/router edits. npm test 133/133.

Conventions: changelog.d/48.md present, matching the house one-liner format; allowlist entries each carry their why; tracked-path enumeration via git ls-files as the spec demanded.

Evidence worth recording: the labels job already derived scope:ci + scope:docs + scope:packaging on this very PR — the widened map producing the honest three-scope answer in the wild, which is live-check 9's direction ahead of schedule.

Non-blocking note: the guard matches with Node's path.matchesGlob, the live consumer with 0.6.3's regex engine. I cross-checked the two on this tree's ten globs and they agree on every tracked path; the theoretical divergence edges (a bare a/** matching a itself, dotfile specialness under bare *) touch no path this repo tracks. If ceremony's engine ever changes, the cross-check is worth re-running.

Environment gaps: the instance's check-runs endpoint 404s, so CI was read via the combined-commit-status endpoint (state: success, ci / test + labels / labels contexts at the head) — superseded anyway by the local full-suite run. Everything else was run directly at the head in a detached throwaway worktree.

**Verdict: approve** — head `d84062af54659f9e0acdbbb1ff3f525c4cc43441`, reviewed whole against #48 as amended (13:26Z and 13:41Z amendments; the PR body carries the amended criterion 6 verbatim, as triage's 13:43Z comment asked). **Acceptance criteria 1–6 — verified, not opined** (criterion 7 is triage's post-merge item; the `Refs #48` shape is correct and no closing keyword precedes `#48` anywhere in the PR body): 1. **Coverage at head** — run twice: (a) `npm run check:governance` green in a detached worktree at the head; (b) an independent cross-check sourcing ceremony **0.6.3's own** `parse_labeler_config` + `glob_to_regex` from the pinned tag and matching them against `git ls-files`: 42 tracked paths, every one matched except exactly `.gitignore`, `assets/logo-mark.svg`, and the seven `test/*.test.js` files. 2. **Name parity, machine-enforced both directions** — validator green on the tree; perturbation probes: a sixth `scope:brand` row added to `labeler.yml` alone → exit 1 `scope names only in labeler.yml: scope:brand`; `scope:manifests`→`scope:data` in `labels.conf` alone → exit 1 naming both offenders. No name added/removed/renamed in the diff. 3. **Three rewritten descriptions** — each names exactly what its globs match ("package manifests" ↔ the two package files, "fragments" ↔ `changelog.d/**`, etc.); no path claimed that isn't matched. 4. **Failure + preserved contract** — staged `new-surface/uncovered.txt` → exit 1 `tracked paths have no scope mapping: new-surface/uncovered.txt`; success output still ends `governance: 4 identities resolved; 5 scope rows valid`; `--config`/`--api-url` flags and exit behaviour unchanged. 5. **Rewritten test fails on the pre-change map** — old `labeler.yml` swapped in at the head → `not ok 1 - repository scope mapping covers every tracked path except the ruled residue`, listing `.ceremony/*` and the other genuinely-uncovered paths. It tests coverage, not the old glob list. 6. **CONTRIBUTING §3 correspondence** — same five names; the three rewritten Covers cells mirror the new `labels.conf` descriptions in §3's own voice; `scope:cli` and `scope:manifests` untouched (their §3 rows remain the byte-unequal restatement #46 shipped, which the amended criterion explicitly permits). **Test plan**: must-pass 1–4 all run green (3: `.ceremony/`+`AGENTS.md` diff empty; 4's `CONTRIBUTING.md` leg is the hand-check above). Must-fail 5–7 all demonstrated above with actual non-zero exits and named offenders. Must-fail 8 n/a — no mirror/router edits. `npm test` 133/133. **Conventions**: `changelog.d/48.md` present, matching the house one-liner format; allowlist entries each carry their why; tracked-path enumeration via `git ls-files` as the spec demanded. **Evidence worth recording**: the labels job already derived `scope:ci` + `scope:docs` + `scope:packaging` on this very PR — the widened map producing the honest three-scope answer in the wild, which is live-check 9's direction ahead of schedule. **Non-blocking note**: the guard matches with Node's `path.matchesGlob`, the live consumer with 0.6.3's regex engine. I cross-checked the two on this tree's ten globs and they agree on every tracked path; the theoretical divergence edges (a bare `a/**` matching `a` itself, dotfile specialness under bare `*`) touch no path this repo tracks. If ceremony's engine ever changes, the cross-check is worth re-running. **Environment gaps**: the instance's check-runs endpoint 404s, so CI was read via the combined-commit-status endpoint (`state: success`, `ci / test` + `labels / labels` contexts at the head) — superseded anyway by the local full-suite run. Everything else was run directly at the head in a detached throwaway worktree.
forgejo-actions added
state:needs-human
and removed
state:bots-reviewing
labels 2026-09-01 14:00:15 +00:00
andres merged commit bef059d7b7 into main 2026-09-01 14:16:53 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/stoke#49
No description provided.