ci(guard): enforce the committed-content self-containment guardrail + sweep breadcrumbs - #316
Conversation
… sweep breadcrumbs Adds engine/tests/self_containment_guard.rs, a repo-wide nextest guard (alongside file_size_guard.rs) that fails the build on a JEF-nnn ticket reference or a linear.app URL in tracked source comments/docstrings and docs, with narrow, documented exemptions for the guardrail's own naming text in CLAUDE.md and for scripts/judge_bakeoff_cutchoice.py (mid-edit on a concurrent branch). Sweeps every existing JEF-nnn/linear.app breadcrumb the guard would flag out of tracked source and docs, replacing each with the ADR it records, the module it lives beside, or the inline reasoning already next to it — preserving the rationale, never the ticket number. Comment/doc-prose only; no code-logic change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VtjoJttCvBY4dzCoE4f9vP
…, drop stale exemption
The breadcrumb sweep mangled two `// JEF-317, ON-NODE PENDING` trailing
comments in agent/protector-agent-ebpf/src/vmlinux.rs into `/, ON-NODE
PENDING` inside a `const _: () = { ... }` compile-time offset guard —
invalid Rust that would break the ebpf cross-compile. Restore the `//`
markers (JEF-317 dropped per the sweep).
#314 (which was concurrently editing scripts/judge_bakeoff_cutchoice.py)
is now merged, so its temporary EXEMPT_FILES entry is stale. Sweep the 3
remaining breadcrumbs there (keep the CUT TRAP / REFUTE TRAP mechanism
names; ADR-0034 is already cited inline) and remove the exemption, leaving
the guard with a single structural exemption (its own source file).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VtjoJttCvBY4dzCoE4f9vP
|
Integration review (architect): verified this is a comment/docstring/doc-prose-only sweep with no code-logic change, re-verified the guard independently (fails on an injected Found and fixed one surviving over-eager-cleanup defect the sweep left: in DECISION (stale exemption): #314 is merged, so its temporary Branch updated to main (fast-forward, no force). Merging on green. |
Summary
CLAUDE.md's "Committed content is self-contained — no external ticket IDs" section
(added in #301) was prose-only, not CI-enforced, so it kept drifting — recent PRs
(#305–#311 and older) kept adding
JEF-nnnbreadcrumbs into Rust/JS/YAML/shellcomments. This makes it real:
CI lint —
engine/tests/self_containment_guard.rs, acargo nextestguardalongside the existing
file_size_guard.rs, walking the same directoriesdirectly (no
gitinvocation). It fails the build on aJEF-prefix followed bya digit, or a bare
linear.appsubstring, in tracked sourcecomments/docstrings + docs (Rust/JS/JSX/Python/shell/YAML/Helm-tpl/CSS/Markdown
under
docs/,scripts/,charts/,engine/src,engine/examples,engine/tests,engine/web/src,engine/web/test,behavior/src,agent/,.github/workflows, plusCLAUDE.md,README.md, bothDockerfiles, and theweb config/dist files).
Boundary exemptions (per CLAUDE.md's documented scope):
filesystem walk — nothing to exempt, they're structurally out of scope.
a `linear.app` URL)is allowlisted by exact substring —
JEF-nnnplaceholder text needs noallowlisting since the check requires a real digit after
JEF-.scripts/judge_bakeoff_cutchoice.pyis excluded with a documented, narrowreason: it's under active edit on a concurrent branch landing alongside this
one; a follow-up sweep clears it once that lands (DECISION NEEDED: flagging
for the architect — this is the one deliberately-incomplete corner of the
sweep).
literal
JEF-/linear.apppatterns to implement the check — the sameself-reference CLAUDE.md's own guardrail text is allowed).
Sweep — every
JEF-nnn/linear.appbreadcrumb the guard would haveflagged, across ~2300 occurrences in ~300 files, replaced with the ADR that
records the decision, the module/mechanism name already sitting beside it, or
the inline reasoning that was already there (the ticket number was almost
always decoration on top of prose that already carried the why). A handful of
spots needed an actual rewrite where the ticket number was structurally load
bearing (a numbered citation, a "resolves NNN" tail, a bare compound
JEF-A/Breference) — those got a real sentence, not just a deletion.Testing
no_ticket_breadcrumbs_in_tracked_source_or_docsFAILS on a syntheticJEF-9999canary added to a scoped file, and PASSES on the swept tree (verifiedboth directions before committing).
npm --prefix engine/web run build && npm run lint && npm run typecheck && npm test: clean (build, 0 eslint errors, 0 tsc errors, 122/122 vitest passing — the sweep touched.jsx/.jstest-description strings anddashboard.csscomments, so I re-verified the web suite explicitly).cargo fmt --check,cargo clippy --all-targets -- -D warnings: clean, both for theengineworkspace and the separateagentworkspace (protector-agent+protector-agent-common; the eBPF crate needs the nightly+bpf toolchain and isn't locally buildable here — only its doc comments/vmlinux.rsannotations were swept, no logic touched).cargo nextest run --workspace: 1166 passed, 2 skipped (includes the new guard test andfile_size_guard, confirming every edited file stays under the 1,000-line cap).cargo testfor theagentworkspace's buildable crates: 45 + 7 passed.helm lint charts/protector+helm template: clean (the sweep touched several chart template comments/values.yaml docs).describe("… (JEF-408)", () => {and clipped the adjacent()too, breaking 9 JS test files' syntax (eslint parse errors) and a handful of Helm template/workflow comments (dangling—/)/+-at-line-start artifacts, two of which tripped clippy'sdoc_lazy_continuationlint on accidental markdown list markers). All caught and hand-fixed before this diff; re-verified with a second full gate pass afterward.Checks
/soundcheck:pr-review: no Critical/High findings — pure comment/doc-prose sweep + one new filesystem-walking test with no untrusted input, network, shell exec, secrets, or auth/endpoint changes./simplify(single-pass, Agent tool unavailable in this context): collapsed a one-element&[&str]exemption list +.any()iteration in the new guard down to a plain&strconstant + direct.contains(). Leftrepo_root()/is_skipped_dir()'s duplication withfile_size_guard.rsas-is — the existing test suite's own convention is per-file duplication (no sharedtests/commonmodule exists yet), and factoring one out would touch a file outside this diff's scope.Scope notes / decisions
cargo nextestRust test (matches the ticket's stated preference and the repo's existingfile_size_guard.rspattern) rather than a standalone CI grep step — keeps the check in the same "run the test suite" gate contributors already run locally..github/workflows/*.ymland bothDockerfiles even though CLAUDE.md's guardrail text doesn't name them explicitly (it says "ADRs, source comments/docstrings, CLAUDE.md, VISION.md, scripts, chart templates") — they're tracked, human-authored, tracker-blind prose in the same spirit, and both had breadcrumbs. Flagging as a documented scope call rather than asking, since under-covering the lint was the actual risk here.scripts/judge_bakeoff_cutchoice.pyis still exempted (unswept) pending a concurrent branch some other in-flight work is editing — I was told to steer clear of that file. Once that branch lands, a small follow-up should sweep its 3 remainingJEF-nnnbreadcrumbs and delete itsEXEMPT_FILESentry in the guard.Closes JEF-682