Skip to content

feat: 30% faster scans, enforceable AI-readiness score, and doc-truth rules#44

Merged
alxxjohn merged 13 commits into
feat/performance-categoryfrom
feat/ai-ready-and-tuning
Jul 16, 2026
Merged

feat: 30% faster scans, enforceable AI-readiness score, and doc-truth rules#44
alxxjohn merged 13 commits into
feat/performance-categoryfrom
feat/ai-ready-and-tuning

Conversation

@alxxjohn

Copy link
Copy Markdown
Contributor

Summary

Stacked on #41. Three tracks, built by parallel agents and integrated sequentially: codeguard's own scan gets measurably faster, the repo_legibility score becomes an enforceable and trended AI-readiness gate, and four new rules keep a repo's docs truthful for both AI agents and humans.

1. Scan performance (behavior-preserving, measured)

before after
Cold scan (this repo) ~0.69 s ~0.49 s (−30%)
Warm scan ~0.60 s ~0.46 s (−24%)
  • Quality's AI checks previously bypassed the shared scan corpus — 4–5 redundant full-corpus reads per scan (syscalls were 41% of warm CPU). New ListTargetFiles/ReadTargetFile corpus hooks route them all through one cached read; the redundant mode-0 re-parse now reuses the shared ParseComments AST.
  • Clone detector: tokens hashed once at tokenize time + O(1) rolling window hash, zero per-window allocations (was ~226 MB churn/scan). Hash is not behavior-bearing — every bucket pairing is still verified token-by-token.
  • One-pass dominant-style profile (test framework + error style + naming) replaces three corpus sweeps; allocation-free CountLines.
  • Proof of identical behavior: old vs new binaries produce byte-identical findings JSON on the same tree; a differential clone test captures the OLD algorithm's output verbatim and asserts the new one reproduces it. One semantic trap was found and neutralized: a fn.Doc directive exemption that never fired under the old parse mode would have silently activated — removed with a NOTE.

2. Enforceable AI-readiness score

repo_legibility (0–100, explainable components) previously could not gate a build or show a trend. Now:

  • context_rules.legibility_warn_threshold / legibility_fail_threshold — fires context.legibility-threshold when the score falls below the floor (legibility is good-high; semantics documented), message carries the component breakdown.
  • History at <cache>.legibility-history.<ext> with previous_score/delta, plus codeguard report -legibility-history.
  • Calibration fixes: an empty CLAUDE.md no longer scores the full 25 agent-docs points (substance-gated + drift-penalized); context-economy ramps linearly to zero at 25% oversized (was a cliff at 10%); doc-accuracy penalty is proportional (broken/total) instead of saturating at 5 refs; conventional basenames (index.ts, __init__.py, mod.rs, types.go, …) no longer count as ambiguous — configurable via ambiguous_symbol_ignore.
  • Dogfooded: this repo runs with legibility_warn_threshold: 85 as a live gate.

3. Doc-truth rules (Agent Context)

Rule What it catches
context.undocumented-commands high-signal Makefile targets / npm scripts (build, test, lint, fmt, …) that no agent doc or README mentions
context.oversized-agent-doc agent docs larger than max_agent_doc_lines (600) — they consume the context budget they exist to save
context.doc-link-rot markdown links in agent docs/README pointing at nonexistent files (relative + repo-absolute; no network I/O)
README drift parity context.readme-drift now gets the same full prose extraction as agent docs, not just shell fences

Dogfooding found 17 real defects in our own docs — README links baked to absolute /Users/... machine paths, references to nonexistent config filenames, and make fmt documented nowhere. All fixed, none waived.

Verification

774 tests / 9 packages, go vet, gofmt, golangci-lint 0 issues, cache-cleared self-scan 0 fail with the legibility gate active. Docs fully updated: Agent Context section rewritten (new rules, recalibrated formulas, threshold/history semantics), architecture doc gained a corpus paragraph, and three new gotchas captured in .claude/knowledge/.

🤖 Generated with Claude Code

alxxjohn and others added 13 commits July 16, 2026 12:22
Adds three Agent Context rules: context.undocumented-commands (high-signal
Makefile targets / npm scripts no agent doc or README mentions),
context.oversized-agent-doc (agent instruction files over the
max_agent_doc_lines budget, default 600), and context.doc-link-rot (markdown
links in agent docs and the root README that resolve to nothing; external
URLs and anchors exempt, no network I/O). Broadens context.readme-drift to
the same full prose extraction agent docs get, and moves markdown-link
checking out of the drift extractor so a broken link is reported once.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The broadened readme-drift and new doc-link-rot rules flagged our own README:
14 machine-absolute doc links and two search-path candidates written as
repo paths that do not exist. Repoint the links relatively, reword the
config-discovery sentence, and document make fmt in CLAUDE.md so the
undocumented-commands rule passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e components

- context_rules.legibility_warn_threshold / legibility_fail_threshold gate
  the repo_legibility score via a new context.legibility-threshold rule
  (fires when the score falls BELOW the threshold, since legibility is
  good-high; 0 disables, fail must be <= warn)
- agent_docs component now gated on substance (25 x min(non-blank,10)/10)
  and reduced -2 per unresolvable agent-doc reference (capped at 10)
- doc_accuracy penalty is proportional: round(20 x broken/total refs)
  instead of a flat -4 that saturated at 5 references
- context_economy ramps linearly to zero at 25% oversized instead of 10%
- navigability ignores conventional basenames (index.ts, __init__.py,
  mod.rs, main.go, ...) for both the score and context.ambiguous-symbol
  findings; context_rules.ambiguous_symbol_ignore replaces the default set

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- trend persisted per target at <cache>.legibility-history.<ext> following
  the slop/perf history pattern; artifacts annotated with previous_score
  and delta on subsequent scans
- context_rules.legibility_history toggles persistence (nil = enabled),
  legibility_history_limit caps retained entries (default 100)
- codeguard report -legibility-history prints the recorded trend,
  mirroring -slop-history and -perf-history

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- threshold warn/fail/disabled/pass paths plus config validation ordering
- history persistence, delta annotation, and toggle-off behavior
- calibration proofs: substance-gated agent_docs, proportional
  doc_accuracy, softened context_economy curve, conventional-basename
  ignore list and its replace semantics
- report -legibility-history CLI trend, empty-history, and mode-flag
  exclusivity
- updated artifact expectations to the recalibrated formulas

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rmulas

- rewrite the Agent Context section: new config keys, score-below-threshold
  semantics, history + report flag, recalibrated component formulas, and
  the conventional-basename ignore list with replace semantics
- dogfood: warn threshold 85 in the self-scan config (repo scores 100) and
  exclude the legibility history file from scanning

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The quality AI checks bypassed the per-scan file corpus: they re-walked
the target and re-read the full source corpus 4-5 times per scan
(dominant test framework, error style, naming convention, plus the
per-file pass), and re-parsed every Go file that the corpus had already
parsed. This made the quality section the scan's wall-clock critical
path, with syscalls at ~41% of warm CPU.

- add ListTargetFiles/ReadTargetFile hooks to checks/support.Context,
  wired to the corpus (mirroring VisitTargetFiles); nil-safe fallbacks
  for unit-test contexts live in quality_ai_corpus.go
- route every walk-enumerated AI-check read (Go/Python/script targets,
  workspace package.json discovery) through the hooks; fixed-filename
  reads (go.mod, root package.json) stay direct to preserve their
  uncapped-read semantics
- replace the redundant parser.ParseFile(..., 0) with the shared
  ParseComments corpus parse (support.ParseGoSource); drop the fn.Doc
  "go:" directive exemption that the mode-0 parse had kept latent so
  findings stay byte-identical (see NOTE in quality_ai_dead_code.go)
- collapse the three Go repo-dominant style signals into one corpus
  pass (goRepoStyleProfile); each signal is an independent per-file
  sum, so the fold is behavior-identical

Differential check: old vs new binaries scanning an identical pristine
tree produce byte-identical JSON findings (modulo generated_at).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The clone detector re-hashed every threshold-token window from scratch,
converting each token to []byte twice per window (~226 MB of
allocations per scan), and lowercased every token at tokenize time
(~175 MB more).

- cloneToken now stores the original-case source slice (no per-token
  ToLower copy; tokens are ASCII-only by the token regex) plus a
  FNV-1a hash of the ASCII-lowercased text computed once at tokenize
  time
- window grouping uses a rolling polynomial hash over the per-token
  hashes: O(1) per slide instead of O(threshold) bytes hashed, and
  zero allocations
- token equality folds ASCII case with a hash short-circuit, which is
  exactly the historical lowercased-value comparison

The hash function is not behavior-bearing: every candidate bucket is
verified token-by-token in sharedCloneLength, so equal windows always
group and colliding unequal windows are discarded. The new differential
test pins findings captured verbatim from the pre-rewrite algorithm on
a fixture covering three-way clones, case normalization,
overlapping-window merging, and below-threshold duplicates.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CountLines allocated a string copy of the file plus a split slice on
every call (~17.6 MB per scan). Count newline bytes in place instead,
preserving the exact legacy semantics (all trailing newlines trimmed,
empty input is one line). The new unit test cross-checks every edge
case against the legacy strings-based formula.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Note in the architecture doc that the per-scan file corpus memoizes
walks, reads, and parses and that the quality AI checks now share it;
record the corpus read-cap semantics, the latent fn.Doc dead-code
exemption, and the clone-hash verification invariant in the knowledge
base.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alxxjohn
alxxjohn merged commit 718dd08 into feat/performance-category Jul 16, 2026
alxxjohn added a commit that referenced this pull request Jul 16, 2026
…ns (re-land #44) (#46)

## Summary

**Re-lands #44 against main.** #44 was stacked on
`feat/performance-category` and its merge landed on that feature branch
instead of main, so none of its changes made it into main or the 1.0.0
release PR (#45). This PR carries exactly that delta (63 files; full
774-test suite green; content identical to the reviewed #44 state).

See #44 for the full description and review discussion. Highlights:
- **~30% faster cold scans / ~24% warm** — corpus-routed quality AI
checks, zero-allocation rolling clone hash, behavior proven
byte-identical
- **Enforceable AI-readiness score** — `repo_legibility` warn/fail
thresholds, history + `report -legibility-history`, honest component
calibration (dogfooded at warn-threshold 85)
- **Doc-truth rules** — `context.undocumented-commands`,
`context.oversized-agent-doc`, `context.doc-link-rot`, README drift
parity; dogfooding fixed 17 real defects in our own docs

Merging this will update release PR #45 so 1.0.0 includes these changes
— **merge this before accepting the release PR**.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
alxxjohn added a commit that referenced this pull request Jul 16, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.0.0](v0.8.3...v1.0.0)
(2026-07-16)


### ⚠ BREAKING CHANGES

* promote performance rules to their own opt-in check section
([#41](#41))
* the performance rules' ids renamed from quality.* to performance.*
(quality.n-plus-one-query -> performance.n-plus-one-query,
quality.go.alloc-in-loop -> performance.go.alloc-in-loop,
quality.sync-io-in-request-path -> performance.sync-io-in-request-path,
quality.unbounded-goroutines-in-loop ->
performance.unbounded-goroutines-in-loop, plus the typescript/javascript
mirrors and quality.python.sync-io-in-async). Their detect_* toggles
moved from quality_rules to performance_rules, and the section is
opt-in: set checks.performance: true to keep running these rules, and
update any waivers or baselines that reference the old ids.

### Features

* 30% faster scans, enforceable AI-readiness score, and doc-truth rules
([#44](#44))
([718dd08](718dd08))
* **context:** add AI-and-human-readiness rules and broaden README drift
([6caac9a](6caac9a))
* **context:** AI-readiness gate, doc-truth rules, and 30% faster scans
([1f4f130](1f4f130))
* **context:** AI-readiness gate, doc-truth rules, and 30% faster scans
(re-land [#44](#44))
([#46](#46))
([75b3f02](75b3f02))
* **context:** enforceable legibility threshold and recalibrated score
components
([604dd52](604dd52))
* **context:** persist repo_legibility score history with report flag
([e54f643](e54f643))
* **parsers:** wire the Python tree-sitter grammar and upgrade Python
N+1 detection
([07a0b24](07a0b24))
* **performance:** add AI-assisted semantic performance lens
([eabd7fe](eabd7fe))
* **performance:** add diff-only loop-nesting complexity regression rule
([2e8bcef](2e8bcef))
* **performance:** add framework-aware rules for Django, SQLAlchemy,
React, and Express
([b49ce7b](b49ce7b))
* **performance:** add loop-hygiene, concurrency, and memory-pressure
rules
([54bfca9](54bfca9))
* **performance:** add measured budgets and benchmark regression gates
([2c5e4ba](2c5e4ba))
* **performance:** publish a performance_score artifact with history and
report flag
([5c5a738](5c5a738))
* promote performance rules to their own opt-in check section
([ede8b37](ede8b37))
* promote performance rules to their own opt-in check section
([#41](#41))
([81a575b](81a575b))
* suggest enabling the performance section in scan output
([81d9d46](81d9d46))


### Performance Improvements

* **quality:** hash clone tokens once and roll the window hash
([bbf5b69](bbf5b69))
* **quality:** route AI check reads through the shared scan corpus
([b271cfb](b271cfb))
* **runner:** count lines by scanning bytes instead of allocating
([17a4593](17a4593))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
@alxxjohn
alxxjohn deleted the feat/ai-ready-and-tuning branch July 16, 2026 17:17
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