Skip to content

ci(guard): enforce the committed-content self-containment guardrail + sweep breadcrumbs - #316

Merged
thejefflarson merged 4 commits into
mainfrom
thejefflarson/jef-682-enforce-the-committed-content-self-containment-guardrail-in
Aug 1, 2026
Merged

ci(guard): enforce the committed-content self-containment guardrail + sweep breadcrumbs#316
thejefflarson merged 4 commits into
mainfrom
thejefflarson/jef-682-enforce-the-committed-content-self-containment-guardrail-in

Conversation

@thejefflarson

Copy link
Copy Markdown
Owner

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-nnn breadcrumbs into Rust/JS/YAML/shell
comments. This makes it real:

  1. CI lintengine/tests/self_containment_guard.rs, a cargo nextest guard
    alongside the existing file_size_guard.rs, walking the same directories
    directly (no git invocation). It fails the build on a JEF- prefix followed by
    a digit, or a bare linear.app substring, in tracked source
    comments/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, plus CLAUDE.md, README.md, both Dockerfiles, and the
    web config/dist files).

    Boundary exemptions (per CLAUDE.md's documented scope):

    • Branch names, PR bodies, git history/commit messages never reach this
      filesystem walk — nothing to exempt, they're structurally out of scope.
    • CLAUDE.md's own guardrail text that NAMES the pattern (a `linear.app` URL)
      is allowlisted by exact substring — JEF-nnn placeholder text needs no
      allowlisting since the check requires a real digit after JEF-.
    • scripts/judge_bakeoff_cutchoice.py is excluded with a documented, narrow
      reason: 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).
    • The guard's own source file is exempted from itself (it has to name the
      literal JEF-/linear.app patterns to implement the check — the same
      self-reference CLAUDE.md's own guardrail text is allowed).
  2. Sweep — every JEF-nnn/linear.app breadcrumb the guard would have
    flagged, 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/B reference) — those got a real sentence, not just a deletion.

Testing

  • no_ticket_breadcrumbs_in_tracked_source_or_docs FAILS on a synthetic
    JEF-9999 canary added to a scoped file, and PASSES on the swept tree (verified
    both 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/.js test-description strings and dashboard.css comments, so I re-verified the web suite explicitly).
  • cargo fmt --check, cargo clippy --all-targets -- -D warnings: clean, both for the engine workspace and the separate agent workspace (protector-agent + protector-agent-common; the eBPF crate needs the nightly+bpf toolchain and isn't locally buildable here — only its doc comments/vmlinux.rs annotations were swept, no logic touched).
  • cargo nextest run --workspace: 1166 passed, 2 skipped (includes the new guard test and file_size_guard, confirming every edited file stays under the 1,000-line cap).
  • cargo test for the agent workspace's buildable crates: 45 + 7 passed.
  • helm lint charts/protector + helm template: clean (the sweep touched several chart template comments/values.yaml docs).
  • Comment/doc-prose only — no code-logic change. Caught this the hard way: an early sweep pass mechanically stripped ticket citations from strings like 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's doc_lazy_continuation lint 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 &str constant + direct .contains(). Left repo_root()/is_skipped_dir()'s duplication with file_size_guard.rs as-is — the existing test suite's own convention is per-file duplication (no shared tests/common module exists yet), and factoring one out would touch a file outside this diff's scope.

Scope notes / decisions

  • Lint mechanism: a cargo nextest Rust test (matches the ticket's stated preference and the repo's existing file_size_guard.rs pattern) rather than a standalone CI grep step — keeps the check in the same "run the test suite" gate contributors already run locally.
  • Scope beyond CLAUDE.md's literal list: I included .github/workflows/*.yml and both Dockerfiles 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.
  • DECISION NEEDED: scripts/judge_bakeoff_cutchoice.py is 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 remaining JEF-nnn breadcrumbs and delete its EXEMPT_FILES entry in the guard.

Closes JEF-682

thejefflarson and others added 3 commits August 1, 2026 15:07
… 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
@thejefflarson

Copy link
Copy Markdown
Owner Author

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 JEF-9999 + linear.app canary, passes on the swept tree), and confirmed the scope extension to .github/workflows/*.yml + both Dockerfiles is sound (tracker-blind prose in the same spirit as CLAUDE.md's list).

Found and fixed one surviving over-eager-cleanup defect the sweep left: in agent/protector-agent-ebpf/src/vmlinux.rs the trailing comments // JEF-317, ON-NODE PENDING on the two offset_of! lines inside the const _: () = { ... } compile-time guard were mangled into /, ON-NODE PENDING — invalid Rust that would have broken the ebpf cross-compile (that crate is a separate workspace, so the nextest job wouldn't have caught it; only the ebpf job would). Restored the // markers.

DECISION (stale exemption): #314 is merged, so its temporary EXEMPT_FILES entry for scripts/judge_bakeoff_cutchoice.py was stale. Folded the 3 remaining breadcrumbs there (kept the CUT TRAP / REFUTE TRAP mechanism names; ADR-0034 already cited inline) and removed the exemption, so the guard now carries a single structural exemption (its own source file) plus the one EXEMPT_LINE_SUBSTRING for CLAUDE.md's guardrail-naming line. No fast-follow needed.

Branch updated to main (fast-forward, no force). Merging on green.

@thejefflarson
thejefflarson enabled auto-merge (squash) August 1, 2026 22:17
@thejefflarson
thejefflarson merged commit 063c914 into main Aug 1, 2026
8 checks passed
@thejefflarson
thejefflarson deleted the thejefflarson/jef-682-enforce-the-committed-content-self-containment-guardrail-in branch August 1, 2026 22:27
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.

1 participant