Skip to content

feat(B-0533): Slice B.3 + B.4 — --enforce flag + gate.yml wiring#3555

Merged
AceHack merged 2 commits into
mainfrom
feat/b0533-slice-b3-b4-enforce-gate-wiring-otto-cli-2026-05-15
May 15, 2026
Merged

feat(B-0533): Slice B.3 + B.4 — --enforce flag + gate.yml wiring#3555
AceHack merged 2 commits into
mainfrom
feat/b0533-slice-b3-b4-enforce-gate-wiring-otto-cli-2026-05-15

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented May 15, 2026

Summary

Completes B-0533 mechanization. Scanner (PR #3548) now supports `--enforce` flag. New gate.yml job `lint-section-33-migration-xrefs` runs it in `--enforce` mode on every PR.

With baseline = 0 (PR #3552 cleanup landed) the new gate fires only when a future migration leaves dead xrefs in live-nav surfaces — the catch-once-then-lint pattern completing for the §33 migration class.

Changes

File Change
`tools/hygiene/audit-section-33-migration-xrefs.ts` Add `--enforce` flag; exit 1 if findings + flag set; update header docs
`.github/workflows/gate.yml` Add `lint-section-33-migration-xrefs` job after `lint-archive-header-section33` (same shape)

Discipline arc complete

Tick Slice PR Status
1749Z Catch #3529 merged
1807Z Row #3540 merged
1820Z Slice A POC #3544 merged
1833Z Slice B.1 scanner #3548 merged
1844Z Slice A baseline #3552 merged
1848Z Slice B.3 + B.4 this PR open

Test plan

  • `bun tools/hygiene/audit-section-33-migration-xrefs.ts --enforce` runs locally with exit 0 (baseline = 0)
  • CLI rejects unknown flags (e.g., `--foo` returns exit 64)
  • gate.yml job shape mirrors `lint-archive-header-section33` exactly
  • CI green (including the new lint job itself running on this PR)
  • Auto-merge arms

Future work

  • Slice B.2: test file with DST fixtures (optional — the end-to-end gate.yml job acts as integration test)

🤖 Generated with Claude Code

Completes B-0533 mechanization. Scanner now supports --enforce flag
(exit 1 if dead xrefs found, exit 0 otherwise). New gate.yml job
lint-section-33-migration-xrefs runs the scanner in --enforce mode
on every PR.

With baseline = 0 (PR #3552 cleanup landed) the new gate fires only
when a future migration leaves dead xrefs in live-nav surfaces —
the catch-once-then-lint pattern completing for the §33 migration
class.

Sibling of lint-archive-header-section33 (B-0036): same shape,
different failure-class. Both catch §33-discipline violations at PR
time before merge.

Changes:

- tools/hygiene/audit-section-33-migration-xrefs.ts:
  - Add --enforce CLI flag
  - Add exit code 1 when dead xrefs found and --enforce set
  - Update header comment with new exit-code semantics
- .github/workflows/gate.yml:
  - Add lint-section-33-migration-xrefs job after lint-archive-header-section33
  - Same install.sh + bun pattern as sibling job
  - Header comment cites empirical baseline (10) + full lineage

Discipline arc complete:

| Tick | Slice | PR |
|------|-------|----|
| 1749Z | Catch | #3529 |
| 1807Z | Row | #3540 |
| 1820Z | Slice A POC | #3544 |
| 1833Z | Slice B.1 scanner | #3548 |
| 1844Z | Slice A baseline | #3552 |
| 1848Z | Slice B.3 + B.4 (this) | (new) |

Remaining: Slice B.2 (test file with DST fixtures) — optional, scanner
logic is simple enough that the end-to-end gate.yml job acts as integration test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 15, 2026 18:54
@AceHack AceHack enabled auto-merge (squash) May 15, 2026 18:55
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds enforcement for the §33 migration dead-xref scanner and wires it into the main CI gate so future stale docs/research/ references fail PR checks.

Changes:

  • Adds --enforce mode to the migration xref audit script.
  • Adds a new gate.yml lint job that runs the scanner in enforce mode.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tools/hygiene/audit-section-33-migration-xrefs.ts Adds --enforce parsing and non-zero exit on findings.
.github/workflows/gate.yml Adds the new enforced §33 migration xref lint job.

Comment thread .github/workflows/gate.yml
AceHack added a commit that referenced this pull request May 15, 2026
…ired) (#3557)

- PR #3553 (1844Z) merged
- PR #3555 — Slice B.3 (--enforce flag) + B.4 (gate.yml wiring) shipped
- Catch-once-then-lint pattern fully closed for §33 migration dead-xref class
- 9-tick discipline arc: catch → row → POC → scanner → baseline → gate

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…anner

ROOT_MD was hard-coded to 4 files; readdirSync now discovers all repo-root
*.md files so CONTRIBUTING.md, SECURITY.md, CODE_OF_CONDUCT.md, SUPPORT.md
are protected by the enforced gate. Resolves Copilot P1 thread on PR #3555.

Co-Authored-By: Claude <noreply@anthropic.com>
@AceHack AceHack merged commit 79be127 into main May 15, 2026
27 checks passed
@AceHack AceHack deleted the feat/b0533-slice-b3-b4-enforce-gate-wiring-otto-cli-2026-05-15 branch May 15, 2026 19:15
AceHack added a commit that referenced this pull request May 15, 2026
…ization landed (#3560)

- PR #3555 MERGED at 19:15:07Z; B-0533 mechanization complete on main
- PR #3559 (1907Z shard) merged
- Cross-Otto convergence: peer-Otto landed root-md dynamic-walk fix first (6c13dcf)
- My own fix (cacecad) discarded gracefully — push REJECTED, peer's was simpler
- 11-tick parallel-substantive arc + convergence event

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 15, 2026
…duplicate-ids) (#3565)

Substrate-honest correction to B-0535's framing: the duplicate-ID
detection logic ALREADY EXISTS in audit-backlog-items.ts (item 8,
added 2026-05-14 via PR #3249 after Copilot caught B-0329 collision
on PR #3247). The actual gap was CI wiring, not implementation.

This PR adds:

1. CLI flag --enforce-duplicate-ids to audit-backlog-items.ts:
   - Detect mode unchanged (default, exits 0 with findings reported)
   - --enforce-duplicate-ids: exit 1 if duplicate-ID groups > 0
   - Rejects unknown flags with stderr error + exit 1

2. New gate.yml job lint-backlog-id-uniqueness:
   - Same shape as lint-section-33-migration-xrefs + lint-archive-header-section33
   - Runs `bun tools/hygiene/audit-backlog-items.ts --enforce-duplicate-ids`
   - Baseline = 0 duplicate-ID groups on main (verified locally)

Catches the failure class empirically observed today:

- B-0444 (Otto-CLI vs Otto-Desktop, PR #3053 renumber, ~15 min)
- B-0532 + B-0533 (Lior PR #3545 vs Otto-CLI mine, ~15 min coordination)

Both went undetected by the existing detect-only audit because
nothing was wired to fail CI on duplicate-IDs. This PR closes that
gap.

Composes with:
- B-0535 (parent row; the framing was "extend B-0532" but the actual work was "wire existing logic")
- audit-section-33-migration-xrefs (PR #3555 — same catch-once-then-lint pattern)
- audit-backlog-items item 8 (PR #3249 — the existing detection logic)
- PR #3247 (the B-0329 collision that surfaced the need)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 15, 2026
…gate.yml wiring (#3567)

* feat(b-0532): parent-child status-mismatch lint (hard-error slice) + gate.yml wiring

Implements the hard-error case from B-0532 acceptance criteria: parent
row with `status: closed` (or equivalent landed/superseded/merged/done)
AND any declared child still has `status: open`.

Changes:

1. tools/hygiene/audit-backlog-items.ts (item 9 audit class):
   - Extend FrontmatterFields + BacklogRow with `childrenRefs`
   - Add `isClosedStatus()` helper (reuses CLOSED_STATUSES + handles
     `superseded-by-*` prefix)
   - Add `reportParentChildStatusMismatch()` function (item 9)
   - Add `--enforce-parent-child-status` CLI flag (exit 1 on findings)
   - Update Summary section + script header docs

2. .github/workflows/gate.yml:
   - New `lint-backlog-parent-child-status` job (sibling of
     lint-backlog-id-uniqueness from PR #3565)
   - Runs `bun tools/hygiene/audit-backlog-items.ts --enforce-parent-child-status`
   - Baseline = 0 mismatches (verified locally)

Scope: hard-error case only. B-0532's full acceptance criteria also
covers soft-warning (all children closed, parent open) + bidirectional
consistency (parent.children ↔ child.parent). Those are deferred to
follow-up slices.

Empirical anchor: PR #3518 (2026-05-15) shipped a row-status flip
closing parent B-0442 without closing children B-0504 + B-0505. Took
4 review-thread cycles to fully resolve. This lint catches that class
at PR time before merge.

Composes with: PR #3565 (lint-backlog-id-uniqueness, sibling pattern),
PR #3555 (lint-section-33-migration-xrefs, sibling pattern), B-0532
(parent row).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(B-0532): extend B_REF_RE to capture dotted child IDs (B-NNNN.suffix)

Reviewer finding (Copilot P0 + chatgpt-codex-connector P2, PR #3567):
B_REF_RE = /B-\d{4}/g truncated dotted backlog IDs like B-0029.1 → B-0029,
causing the parent/child status-mismatch gate to miss mismatches on decomposed
child rows. Updated to /B-\d{4}(?:\.\d+)*/g to capture the full dotted suffix.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 16, 2026
…ection

Two real Copilot findings on the §33 worked-example table:

P2 (line 37): direct name attribution outside allowed roster surfaces.
"Codex P2 catch on Riven section-33 archive migration" used Zeta persona
names inline. Replace with role-ref: "Reviewer P2 catch on the section-33
archive-migration PR". (Copilot stays as-is — it's an external automated-
reviewer role-ref, accepted style per existing gate.yml comments.)

Line 44 (factual error): I'd attributed BOTH baseline cleanup AND CI
enforce to PR #3552. Verified via git log + gh api:
- PR #3552 (Slice A): "baseline cleanup — 10 dead xrefs → 0"
- PR #3555 (Slice B.3 + B.4): "--enforce flag + gate.yml wiring"

Split the row: PR #3552 = "Baseline (cleanup-to-zero)"; PR #3555 = "CI enforce"
with sub-slice attribution preserved. Calendar duration range extended to
PR #3513 → PR #3555.

Co-Authored-By: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 16, 2026
…ate (#3710)

* docs(hygiene): land tools/hygiene/AUDIT-LIFECYCLE.md — reusable template

Promotes the audit-lifecycle pattern (discovery → narrow-fix → scanner →
quality iterations → baseline → CI enforce gate → maintenance) to a
canonical doc co-located with the hygiene-audit tooling.

Two worked examples documented:
1. §33 migration xrefs audit (PR #3513#3552 → enforce; ~4 weeks)
2. Tick-shard relative-path audit (PR #3676#3708; ~80 min single
   autonomous-loop session)

Captures the step-ordering rationale (why each step depends on the
previous), the mutable-vs-immutable surface distinction for baseline
strategy, and pre-emptive scanner-author findings worth implementing
in step 3 to shorten the quality iteration loop:
- sonarjs disable comment
- main export + import.meta.main guard
- generic URI scheme regex
- --files validation (existsSync + statSync.isFile)
- platform-correct PATH_SEP
- JSON output schema discipline
- baseline schema type guard

Local markdownlint clean.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(pr-3710): 2 Copilot threads — role-refs + §33 PR-attribution correction

Two real Copilot findings on the §33 worked-example table:

P2 (line 37): direct name attribution outside allowed roster surfaces.
"Codex P2 catch on Riven section-33 archive migration" used Zeta persona
names inline. Replace with role-ref: "Reviewer P2 catch on the section-33
archive-migration PR". (Copilot stays as-is — it's an external automated-
reviewer role-ref, accepted style per existing gate.yml comments.)

Line 44 (factual error): I'd attributed BOTH baseline cleanup AND CI
enforce to PR #3552. Verified via git log + gh api:
- PR #3552 (Slice A): "baseline cleanup — 10 dead xrefs → 0"
- PR #3555 (Slice B.3 + B.4): "--enforce flag + gate.yml wiring"

Split the row: PR #3552 = "Baseline (cleanup-to-zero)"; PR #3555 = "CI enforce"
with sub-slice attribution preserved. Calendar duration range extended to
PR #3513 → PR #3555.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 16, 2026
…stale/FP) (#3715)

PR #3707 + #3708 merged. 6 new Copilot threads investigated:
- PR #3710 (AUDIT-LIFECYCLE.md): 2 real — name attribution (Codex/Riven →
  role-refs) + §33 PR-attribution factual error (PR #3552 baseline cleanup
  + PR #3555 CI enforce, not both #3552). Fixup cd7ba81.
- PR #3709 (0328Z shard): 4 threads — 2 stale (0322Z merged via #3707),
  1 minor prose-drift, 1 false-positive (4th time on table-pipes). All
  resolved no-op.

The Copilot table-pipe || hallucination is now a 4-time pattern (#3685,
#3690, #3699-era, #3709) — verify-first-resolve-no-op discipline.

Co-authored-by: Claude <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 16, 2026
…e B shipped, Slice A pending) (#3763)

* chore(b-0533): add Status section confirming partial-completion (Slice B shipped, Slice A pending)

Empirical pure-git audit at 2026-05-16T05:48Z (rate-limit 0/5000)
confirms B-0533 is partial completion per row-close gate triage.

Shipped (Slice B): tools/hygiene/audit-section-33-migration-xrefs.ts
via PR #3548 + PR #3555; gate.yml lint-section-33-migration-xrefs
job wired.

Pending (Slice A): the actual sweep of dead xrefs. Empirical evidence:
multiple recent PRs (#3670, #3659, #3643, #3633, #3599) show the
lint check FAILING — meaning dead xrefs persist.

Row stays status: open until Slice A's persona-batched sweep PRs
land.

Co-Authored-By: Claude <noreply@anthropic.com>

* chore(b-0533): bump last_updated to 2026-05-16 per tools/backlog/README.md (review fix)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants