Skip to content

chore(trust): harden CI gates, adopt static analysis, unify corpus traversal [v0.7.14] - #49

Merged
tcballard merged 23 commits into
mainfrom
claude/repo-technical-audit-c4mol7
Jun 10, 2026
Merged

chore(trust): harden CI gates, adopt static analysis, unify corpus traversal [v0.7.14]#49
tcballard merged 23 commits into
mainfrom
claude/repo-technical-audit-c4mol7

Conversation

@tcballard

@tcballard tcballard commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md — the remediation release for the 2026-06-09 repository technical audit, closing every trust-infrastructure gap found before v0.8.x scoping begins.

Adds:

  • CI battery integrity: 8 orphaned test files (~1,306 lines, 21.6% of the suite — including all coverage for the only two file-mutating commands, rac new and rac migrate) restored to the matrix, with a self-guarding meta-test (tests/test_ci_batteries.py) that fails the suite on orphaned, duplicated, or stale battery entries.
  • Static quality gates: ruff (lint + format) and mypy gate CI; a new pre-merge tier (pr-checks.yml) runs the gates plus a core/golden/dogfood smoke battery on every pull request.
  • Canonical corpus traversal: walk_corpus in rac/core/corpus.py is now the single walk→parse→classify definition, consumed by all seven repository services.
  • Coverage visibility: report-only full-suite coverage job in CI (currently 97%).
  • Pre-roadmap groundwork on the same branch: the v0.7.14 roadmap artifact itself, hardened agent commit guidelines (identity + attribution rules), a root CLAUDE.md router importing the canonical session prompts, and consolidation of rac-agent-session-start.md / rac-agent-instructions.md.

Roadmap / ADR Trace

Roadmap:

  • rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md (RAC-KTQAAPF5ZDZX; identity assigned by dogfooding rac migrate metadata)

Relevant ADRs:

  • rac/decisions/adr-027-ci-test-topology.mdamended in this PR, via the mechanism its own Principle 4 prescribes
  • ADR-015 — deterministic analysis lives in core (why walk_corpus is a core module, not a service helper)
  • ADR-007 — JSON/output contract stability (why goldens were a hard constraint)

Scope

Included

  • Four new batteries (create, init, resolve, migrate) and an extended core battery; every tests/test_*.py provably maps to exactly one battery.
  • [tool.ruff] (E, F, W, I, UP, B; line-length 100; py311) and [tool.mypy] (disallow_untyped_defs for src/) in pyproject.toml; ruff, mypy, types-PyYAML, pytest-cov added to the dev extras.
  • Mechanical conformance fixes only: import sorting, formatter pass, exception chaining (raise … from), ~13 missing annotations, two variables renamed where one name held two result types, two over-length lines wrapped via implicit concatenation so string contents are byte-identical.
  • CorpusEntry carries the full Classification (not just the type string) because inspect and stats need confidence; everyone else reads the artifact_type property.
  • .DS_Store removed; coverage data files gitignored.
  • Contributor docs (CONTRIBUTING.md, docs/testing.md) updated with the new gates; CHANGELOG entries added.

Excluded (deliberately — see roadmap Non-Goals)

  • Splitting services/relationships.py (552 lines, three concerns) — deferred to v0.8.0 service-API shaping.
  • Index caching for repeated resolve/find calls — to be designed into the Explorer's long-lived runtime (v0.8.2), not retrofitted.
  • py.typed / PEP 561 marker — decided alongside v0.8.0's public service API.
  • Coverage threshold gates — visibility first, gate later.
  • cli.py restructuring — 925 lines of linear parser registration: large, not complex.
  • Full battery grid on PRs — the smoke tier is deliberately small; the grid stays merge-gated.

Product / Architecture Decisions

  • ADR-027 rule 1 amended, not superseded: pull requests now get a light pre-merge tier (lint + core/golden/dogfood smoke on py3.11, ~2 min); the full battery × version grid remains merge-gated on main. The "run tests on every PR" alternative is recorded as partially adopted.
  • The battery sync risk is now enforced, not aspirational: ADR-027's "a CI self-check could enforce it later" became tests/test_ci_batteries.py, which lives in the core battery so the guard guards itself.
  • walk_corpus lives in core (ADR-015): it composes only find_markdown_files, parse_file, and classify; iteration is lazy and ordering is the existing sorted order, so consumer output is provably unchanged. corpus.py is now the only find_markdown_files consumer outside fs.py.
  • relationships keeps two item sources: _corpus_items (directory walks) and _parsed_items (single-file paths); _build_report now takes parsed items directly.
  • CI invokes python -m mypy/python -m ruff, not bare binaries — a PATH mypy differing from the env's was observed during implementation.

User-Facing Contract

CLI

No CLI surface changes. No commands, flags, outputs, JSON fields, or exit codes were added or modified.

Human / JSON Output

All 24 golden files are byte-identical to their pre-release state — verified by git diff against the pre-implementation commit. A golden diff anywhere in this release was defined as a defect (roadmap Implementation Contract).

Exit Codes

Unchanged (0 success / 1 validation-operational / 2 usage).

Verification

Ran

python -m pytest -q                                   # 623 passed
python -m ruff check src/ tests/                      # clean
python -m ruff format --check src/ tests/             # clean
python -m mypy src/                                   # no issues in 38 files
python -m pytest -q --cov=src/rac --cov-report=term   # TOTAL 97%
rac validate rac/                                     # exit 0
rac relationships rac/ --validate                     # exit 0
rac review rac/                                       # exit 0, no P1-2 findings
git diff a74fa1c..HEAD -- tests/golden/               # empty (a74fa1c = pre-release)

Covered

  • All 163 tests in the 8 formerly-orphaned files pass unchanged (zero rot found).
  • Battery-guard mutation check: deleting the resolve battery from tests.yml fails the meta-test; restoring it passes.
  • Each of the seven service migrations was verified against its own battery plus the golden battery before its commit landed.
  • walk_corpus unit tests: sorted-order parity with find_markdown_files, classification parity with classify, unknown-type as valid outcome, recursive=False boundary, lazy iteration.
  • Smoke-battery file set executed locally as the PR job would run it (120 tests).

Review Path

  1. .github/workflows/tests.yml + tests/test_ci_batteries.py — the gap and its permanent fix
  2. rac/decisions/adr-027-ci-test-topology.md + .github/workflows/pr-checks.yml — the policy amendment and its implementation
  3. pyproject.toml — tool baselines
  4. src/rac/core/corpus.py + tests/test_corpus.py — the new seam
  5. The seven per-service consume walk_corpus refactor commits — mechanical, one service each
  6. chore(lint) commit — large but behavior-neutral (formatter + annotations); goldens prove it
  7. rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, docs, CHANGELOG

Notes For Reviewer

  • The chore(lint) commit touches 58 files; the two long-line wraps in core/artifacts.py and output/human.py use implicit string concatenation specifically to keep string contents byte-identical — worth a glance.
  • inspect_directory now reads type/confidence from the walk's Classification instead of build_inspection — identical values (both derive from the same classify call), strictly less work.
  • Deferred follow-ups are enumerated in the roadmap's Non-Goals and Follow-On Work sections; v0.8.x scoping can treat walk_corpus as its stable traversal seam.
  • Environment note: a pre-existing test_ingest.py failure in the dev container (broken cffi install, unrelated to this change) was fixed by reinstalling the package locally; CI installs fresh and is unaffected.

Implementation Process

Implemented with AI assistance under the roadmap contract. Final scope, review, and acceptance decisions were made by the maintainer.

tcballard added 23 commits June 9, 2026 23:17
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md.

Convert the 2026-06-09 repository technical audit into a pinned roadmap
artifact ahead of v0.8.x scoping: restore the eight orphaned CI test
batteries with a self-guarding meta-test, add ruff/mypy gates, extract a
canonical corpus traversal seam in core, and clean up repository hygiene.
Three agent commits today shipped with tool footers or a tool author
identity and had to be amended. Make the guideline self-sufficient for
agents: name the prohibited artifacts concretely (session links,
Co-Authored-By tool trailers, generated-by lines), require the
maintainer identity on both author and committer with a verification
command, and require the artifact path in roadmap commit bodies.
rac-agent-session-start.md and rac-agent-instructions.md had drifted:
each held rules the other lacked (attribution ban, pytest gate, branch
discipline versus the six-step contract ritual). Fold the unique rules
of instructions into session-start, add the corpus push gates, and
retire the duplicate so one artifact owns session context.
Claude Code auto-loads the root CLAUDE.md at session start. Make it a
thin router that imports rac-agent-session-start.md and
rac-agent-commit-guidelines.md from the corpus, indexes the situational
prompts by path, and points at the active roadmap series — so the
canonical artifacts reach every agent session without duplication.
…:v0.7.14]

Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 1.

Eight test files (~1,306 lines, including all coverage for the two
file-mutating commands rac new and rac migrate) were missing from the
battery matrix and never ran in CI. Adds create, init, migrate, and
resolve batteries, extends core, and adds tests/test_ci_batteries.py so
an orphaned or duplicated battery entry fails the suite instead of
relying on the matrix comment. All 163 orphaned tests pass unchanged.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 2.

Pins ruff (E, F, W, I, UP, B; line length 100; py311 target) and mypy
(disallow_untyped_defs for src/) in pyproject, adds ruff/mypy/types-PyYAML/
pytest-cov to the dev extras, and applies the mechanical fixes: import
sorting, formatter pass, exception chaining (raise ... from), thirteen
return/parameter annotations, distinct names where one variable held two
result types, and two long lines wrapped via implicit concatenation so
string contents are untouched. All 24 golden files are byte-identical;
full suite passes (618 tests).
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 2.

Adds a lint job to the reusable test workflow (ruff check, ruff format
--check, mypy src/ on py3.11), so both ci.yml and the release gate
inherit it through workflow_call.
…admap:v0.7.14]

Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 4.

Rule 1 gains a light pull-request tier (static gates plus a core/golden/
dogfood smoke battery); the full battery grid stays merge-gated. Records
that the battery-sync risk is now enforced by tests/test_ci_batteries.py
and marks the PR-trigger alternative as partially adopted.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 4.

New pr-checks workflow runs the static gates and a core/golden/dogfood
smoke battery on py3.11 for every pull request, per amended ADR-027
rule 1. The full battery grid remains merge-gated on main.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 3.

walk_corpus composes find_markdown_files, parse_file, and classify into
one lazy, deterministic iterator of CorpusEntry (path, product,
classification). Services migrate onto it in the following commits; the
v0.8.x Explorer consumes the same seam. Joins the core battery and the
PR smoke set.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 3.
Behavior unchanged; validate battery and goldens pass.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 3.
Behavior unchanged; index, resolve, and golden batteries pass.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 3.

The directory view reads type and confidence straight from the walk's
classification — identical values to build_inspection, which derives
them from the same classify call. Inspect battery and goldens pass.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 3.
Behavior unchanged; stats battery and goldens pass.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 3.
Behavior unchanged; portfolio, review, and golden batteries pass.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 3.

All three directory entrypoints share one _corpus_items helper over
walk_corpus; _build_report takes parsed items directly, and the
single-file path keeps _parsed_items. All relationship batteries,
goldens, and dogfood pass.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 3.

Discovery and classification ride the seam; the no-overwrite guards and
byte-preserving envelope write are unchanged. Migrate battery and
goldens pass.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 4.
The file was committed before .gitignore covered it; the ignore rule
prevents recurrence.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 4.

One full-suite coverage job on py3.11 with a term-missing report in the
job log. Report-only — no threshold gate this release (currently 97%).
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 4.

Adds the ruff/mypy commands to the contributor verification checklist,
notes the battery-guard rule for new test files, and shows the local
coverage view.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md.
Implements rac/roadmaps/v0.7.x-trust/v0.7.14-audit-hardening.md, Initiative 4.

pytest --cov (now in CI and the contributor docs) writes .coverage
locally; ignore it the same way other build artifacts are.
PR #49 shipped with a platform-appended 'Generated by Claude Code'
footer and session link that had to be removed by hand — the third
surface (after commit footers and commit identity) where a tool default
injected attribution the project forbids. Make the PR guideline
self-sufficient: verify the stored body after every create or edit,
strip appended footers, treat the Implementation Process section as the
only sanctioned AI disclosure, and check for sanitizer-eaten
angle-bracket placeholders.
@tcballard
tcballard merged commit 6ca28c0 into main Jun 10, 2026
2 checks passed
@tcballard
tcballard deleted the claude/repo-technical-audit-c4mol7 branch June 11, 2026 20:10
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