feat(audit): codebase-state auditor framework + file-size probe (#156)#161
Merged
Merged
Conversation
The per-PR critic reviews diffs and never sees cumulative state. cli.py grew to 1700+ LOC, 3.4x the manifesto soft-cap for Python, one reasonable-looking 50-100 LOC commit at a time. Same boiling-frog shape as stale issues (#129) and stale branches (#146). This change adds the framework that closes that gap: * forge_loop.codebase_audit: Probe Protocol, AuditReport, audit() orchestrator with per-probe error isolation, walk_source_files() honoring vendor/build ignore dirs, and file_violations() that files one ticket per violation with idempotent dedup against the audit:probe-<name> label footer. * forge_loop.audit_probes.file_size: first probe. Per-language soft caps (Python 500, TS/JS 400, Java 600). Hard-multiplier escalates severity to P1 when a file is >= 2x its soft cap (today: cli.py). * Typed events AuditViolationFiledEvent / AuditCleanEvent registered in forge_loop.events. * forge-loop audit CLI command: dry-run by default, --apply files tickets, --json for scripts/dashboards. Dry-run path never constructs a gh client. * runner/tick._run_codebase_audit: runs on the maintenance_every_n_ticks cadence and emits audit_violation_observed / audit_clean. Side-effect- free on the runner side; operator drives --apply explicitly. * tests/test_codebase_audit.py: 23 tests covering happy path, probe crash isolation (T1 default-branch + T2 sad-path), threshold edges, language-specific caps, idempotent dedup against the footer, create_issue failure surfacing (T3), clean-event-only path, and the CLI dry-run / json / --apply variants. Manifesto compliance: every new event KIND uses the typed registry; no new os.environ.get; no new subprocess shell-out; cross-module event KIND strings live in events.py with the rest. Adversarial probes (BoomProbe) exercise the default-branch isolation per T1. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #156.
Summary
forge_loop.codebase_auditmodule:ProbeProtocol,Violation,AuditReport,audit()orchestrator with per-probe crash isolation, plusfile_violations()that files one ticket per violation with idempotent dedup against theaudit:probe-<name>label + body footer.forge_loop.audit_probes.file_size— first probe. Per-language soft caps (Py 500, TS/JS 400, Java 600); P1 escalation at ≥2× soft cap. Today it correctly flagscli.py(1700 LOC) as P1.AuditViolationFiledEventandAuditCleanEventregistered inevents.py.forge-loop auditCLI subcommand: dry-run by default,--applyfiles tickets,--jsonfor scripts. Dry-run NEVER constructs a gh client.runner/tick._run_codebase_auditwired to themaintenance_every_n_tickscadence — emitsaudit_violation_observed/audit_cleanevents so the dashboard surfaces drift. Operator runs--applyexplicitly.Acceptance (from #156)
forge_loop/codebase_audit.pywithaudit(repo, manifesto) -> AuditReportforge-loop auditCLI command (dry-run by default;--applyfiles tickets)maintenance_every_n_tickscadence by defaultmodernization-gated, rationale citing manifesto + acceptance scaffoldedaudit_violation_filed,audit_cleanManifesto compliance
The "state-based rules need a state-based gate" manifesto rule (added by #157) calls for exactly this. The framework is the unlock — follow-up sub-tickets (Any-typed-file, deprecated-pattern, cyclomatic, coverage) each ship a probe under
audit_probes/without re-touching the framework.Test plan
tests/test_codebase_audit.py— 23 tests, all green.BoomProbeexercises the probe-crash default-branch._cmd_auditend-to-end againstMockGhClientand asserts the right label set + event emission.test_events.py,test_cli.py,test_stuck_sweep.pystill green (no regressions).python -m forge_loop audit --jsonagainst this worktree correctly surfacescli.pyand other oversized files.🤖 Generated with Claude Code