feat(cml): context-window-scaled CLAUDE.md char budget (mirrors CC 40.0k warning)
Add a char-based CML finding that mirrors Claude Code's own startup warning
("Large CLAUDE.md will impact performance (X chars > 40.0k)"). CC 2.1.169 scales
that threshold with the model's context window, so the finding anchors on the
conservative 200k window (we cannot observe the user's window; the anchor fires
earliest) and discloses the relaxed ~200,000-char figure at 1M context. MEDIUM
severity (token cost, not an adherence cliff — consistent with the v5.2.0 reframe).
Keyed on chars, not lines, so it is complementary to the existing 200/500-line
checks (which stay untouched): a file can be long by lines yet under budget (short
lines, e.g. large-cascade at 37k chars / 1024 lines), or short by lines yet over it.
Extract the shared 200k/1M context-window constants to scanners/lib/context-window.mjs
(single source of truth; skill-listing-budget.mjs now imports + re-exports them).
40.0k figure and context-window scaling verified against the CC changelog (2.1.169,
2026-06-08) and the live startup-warning text. +6 tests, new fixture large-claude-chars
(48,531 chars / 100 lines). Suite 918/918, self-audit PASS configGrade A 97.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ter3E2JSi1Khgmuf2kady8
This commit is contained in:
parent
03949c6c98
commit
b0bf8c5817
7 changed files with 253 additions and 8 deletions
22
CLAUDE.md
22
CLAUDE.md
|
|
@ -109,7 +109,27 @@ Default: auto-detects scope from git context. Override with `/config-audit full|
|
|||
node --test 'tests/**/*.test.mjs'
|
||||
```
|
||||
|
||||
912 tests across 56 test files (17 lib + 29 scanner + 1 hook + 1 agent + 3 commands + 1 knowledge + 4 top-level). Test fixtures in `tests/fixtures/`. Top-level humanizer tests: `json-backcompat.test.mjs`, `raw-backcompat.test.mjs`, `scenario-read-test.test.mjs`, `snapshot-default-output.test.mjs`.
|
||||
918 tests across 56 test files (17 lib + 29 scanner + 1 hook + 1 agent + 3 commands + 1 knowledge + 4 top-level). Test fixtures in `tests/fixtures/`. Top-level humanizer tests: `json-backcompat.test.mjs`, `raw-backcompat.test.mjs`, `scenario-read-test.test.mjs`, `snapshot-default-output.test.mjs`.
|
||||
|
||||
### CML scanner — context-window-scaled char budget
|
||||
|
||||
Beyond the line-count checks (200/500 lines, both MEDIUM), the CML scanner mirrors
|
||||
Claude Code's own startup warning — *"Large CLAUDE.md will impact performance
|
||||
(X chars > 40.0k)"* — as a `char`-based finding:
|
||||
|
||||
- **Char budget** — flags a CLAUDE.md over **~40.0k chars** (CC's startup-warning
|
||||
figure at a 200k-context model). CC 2.1.169 scales that threshold with the model's
|
||||
context window, so the finding anchors on the conservative 200k window (we cannot
|
||||
observe the user's window; the anchor fires earliest) and discloses the relaxed
|
||||
~200,000-char figure at 1M context. Severity MEDIUM (token cost, not an adherence
|
||||
cliff). New `CA-CML` finding.
|
||||
|
||||
It keys on chars, not lines, so it is complementary to the line checks: a file can be
|
||||
long by lines yet under budget (short lines), or short by lines yet over it (long lines).
|
||||
The 200k/1M window constants live in the shared `scanners/lib/context-window.mjs`
|
||||
(single source of truth, also re-exported by `skill-listing-budget.mjs`). The 40.0k
|
||||
figure and context-window scaling are verified against the CC changelog (2.1.169) and
|
||||
the live startup-warning text.
|
||||
|
||||
### DIS scanner — permission-rule hygiene
|
||||
|
||||
|
|
|
|||
13
README.md
13
README.md
|
|
@ -12,7 +12,7 @@
|
|||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
A Claude Code plugin that checks configuration health, suggests context-aware improvements, and auto-fixes issues — `CLAUDE.md`, `settings.json`, hooks, rules, MCP servers, `@imports`, and plugins. 13 deterministic scanners across 10 quality areas, context-aware feature recommendations, auto-fix with backup/rollback, a prompt-cache-aware Token Hotspots scanner with optional API-calibrated `--accurate-tokens` mode, plus cache-prefix stability, dead-tool, and cross-plugin collision detection. Zero external dependencies.
|
||||
|
|
@ -299,7 +299,7 @@ By default, `/config-audit` auto-detects scope from your git context. Override w
|
|||
|
||||
| Scanner | Prefix | What It Catches |
|
||||
|---------|--------|-----------------|
|
||||
| `claude-md-linter.mjs` | CML | Oversized files, missing sections, broken @imports, duplicates, stale TODOs |
|
||||
| `claude-md-linter.mjs` | CML | Oversized files (line count **plus** a context-window-scaled char budget mirroring Claude Code's ~40.0k-char startup warning), missing sections, broken @imports, duplicates, stale TODOs |
|
||||
| `settings-validator.mjs` | SET | Schema violations, unknown/deprecated keys, type mismatches, permission issues |
|
||||
| `hook-validator.mjs` | HKV | Invalid format, missing scripts, wrong event names, timeout risks |
|
||||
| `rules-validator.mjs` | RUL | Bad glob patterns, orphaned rules, deprecated fields, unscoped rules |
|
||||
|
|
@ -321,6 +321,15 @@ By default, `/config-audit` auto-detects scope from your git context. Override w
|
|||
> It fires only under measured pressure, so it stays an opportunity rather than noise. Both
|
||||
> scanners share one budget definition (`scanners/lib/skill-listing-budget.mjs`).
|
||||
|
||||
> **CLAUDE.md size — two complementary signals.** CML checks line count (200/500, for
|
||||
> readability) **and** a character budget that mirrors Claude Code's own startup warning
|
||||
> — *"Large CLAUDE.md will impact performance (X chars > 40.0k)."* CC 2.1.169 scales that
|
||||
> threshold with the model's context window, so the char finding anchors on a conservative
|
||||
> 200k window and discloses the relaxed ~200,000-char figure at 1M context. A file can be
|
||||
> long by lines yet under the char budget (short lines), or short by lines yet over it — so
|
||||
> both signals earn their place. The 200k/1M window constants live in the shared
|
||||
> `scanners/lib/context-window.mjs` (single source of truth with the skill-listing budget).
|
||||
|
||||
### CLI Tools
|
||||
|
||||
All tools work standalone — no Claude Code session needed:
|
||||
|
|
|
|||
|
|
@ -9,11 +9,21 @@ import { finding, scannerResult, resetCounter } from './lib/output.mjs';
|
|||
import { SEVERITY } from './lib/severity.mjs';
|
||||
import { parseFrontmatter, extractSections, findImports } from './lib/yaml-parser.mjs';
|
||||
import { lineCount, truncate } from './lib/string-utils.mjs';
|
||||
import { LARGE_CONTEXT_WINDOW, LARGE_CONTEXT_SCALE, withCommas } from './lib/context-window.mjs';
|
||||
|
||||
const SCANNER = 'CML';
|
||||
const MAX_RECOMMENDED_LINES = 200;
|
||||
const MAX_ABSOLUTE_LINES = 500;
|
||||
|
||||
// Claude Code's own startup warning ("Large CLAUDE.md will impact performance
|
||||
// (X chars > 40.0k)") fires once a CLAUDE.md passes ~40.0k chars on a
|
||||
// 200k-context model. CC 2.1.169 made that threshold scale with the model's
|
||||
// context window. We mirror it in the same unit CC uses (chars, not lines):
|
||||
// anchor on the conservative 200k window (we cannot observe the user's window,
|
||||
// and the anchor fires earliest) and disclose the relaxed 1M figure.
|
||||
const CLAUDE_MD_CHAR_WARN_ANCHOR = 40_000; // chars @ 200k context (CC startup warning)
|
||||
const CLAUDE_MD_CHAR_WARN_LARGE = CLAUDE_MD_CHAR_WARN_ANCHOR * LARGE_CONTEXT_SCALE; // 200,000 @ 1M
|
||||
|
||||
/** Recommended sections for a project CLAUDE.md */
|
||||
const RECOMMENDED_SECTIONS = [
|
||||
{ pattern: /project|overview|description|what/i, label: 'Project overview' },
|
||||
|
|
@ -87,6 +97,26 @@ export async function scan(targetPath, discovery) {
|
|||
}));
|
||||
}
|
||||
|
||||
// --- Char budget (mirrors Claude Code's own startup warning) ---
|
||||
// Keyed on chars, not lines: CC's "Large CLAUDE.md will impact performance"
|
||||
// warning is char-based (~40.0k @ 200k context) and CC 2.1.169 scales that
|
||||
// threshold with the context window. A file can be long by lines yet under
|
||||
// this budget (short lines), or short by lines yet over it (long lines), so
|
||||
// this is complementary to the line-count checks above.
|
||||
const chars = content.length;
|
||||
if (chars > CLAUDE_MD_CHAR_WARN_ANCHOR) {
|
||||
findings.push(finding({
|
||||
scanner: SCANNER,
|
||||
severity: SEVERITY.medium,
|
||||
title: 'CLAUDE.md exceeds Claude Code\'s performance-warning threshold',
|
||||
description: `${file.relPath} is ${withCommas(chars)} chars. Claude Code shows a startup warning ("Large CLAUDE.md will impact performance ... chars > 40.0k") once a CLAUDE.md passes ~40.0k chars on a 200k-context model — it loads in full on every turn. CC 2.1.169 scales that threshold with the context window, so on a ${withCommas(LARGE_CONTEXT_WINDOW)}-token model it relaxes to ~${withCommas(CLAUDE_MD_CHAR_WARN_LARGE)} chars and you are likely within it.`,
|
||||
file: file.absPath,
|
||||
evidence: `${withCommas(chars)} chars > 40.0k (200k-context anchor; ~${withCommas(CLAUDE_MD_CHAR_WARN_LARGE)} at ${withCommas(LARGE_CONTEXT_WINDOW)} context). This is an estimate, not measured telemetry.`,
|
||||
recommendation: 'Split detail into @imports and .claude/rules/ files so only the relevant rules load, and keep the top of CLAUDE.md byte-stable for cache hits.',
|
||||
autoFixable: false,
|
||||
}));
|
||||
}
|
||||
|
||||
// --- Empty file ---
|
||||
if (lines < 3) {
|
||||
findings.push(finding({
|
||||
|
|
|
|||
28
scanners/lib/context-window.mjs
Normal file
28
scanners/lib/context-window.mjs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Context-window constants — single source of truth.
|
||||
*
|
||||
* Several Claude Code budgets scale with the model's context window:
|
||||
* - the skill listing is allotted ~2% of context (CC 2.1.32, changelog L2860);
|
||||
* - the "CLAUDE.md is too long" warning threshold scales with it (CC 2.1.169).
|
||||
*
|
||||
* We cannot observe the user's actual context window, so scanners anchor on a
|
||||
* conservative 200k window (the smallest common size — it fires earliest, the
|
||||
* safe default when the window is unknown) and disclose the relaxed 1M figure.
|
||||
*
|
||||
* Zero external dependencies.
|
||||
*/
|
||||
|
||||
// Conservative anchor: the smallest common context window. Budgets anchored
|
||||
// here fire earliest, which is the safe default when the window is unknown.
|
||||
export const CONTEXT_WINDOW_ANCHOR = 200_000;
|
||||
|
||||
// Large context window (Opus/Sonnet 1M tier). Used to disclose how a budget
|
||||
// relaxes on large-context models.
|
||||
export const LARGE_CONTEXT_WINDOW = 1_000_000;
|
||||
|
||||
// How much larger the 1M window is than the 200k anchor (= 5). A budget that
|
||||
// scales linearly with the window relaxes by this factor at 1M.
|
||||
export const LARGE_CONTEXT_SCALE = LARGE_CONTEXT_WINDOW / CONTEXT_WINDOW_ANCHOR;
|
||||
|
||||
// Dependency-free thousands separator (repo invariant: zero external deps).
|
||||
export const withCommas = (n) => String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
|
|
@ -23,6 +23,7 @@ import { join } from 'node:path';
|
|||
import { estimateTokens, enumeratePlugins, enumerateSkills } from './active-config-reader.mjs';
|
||||
import { readTextFile } from './file-discovery.mjs';
|
||||
import { parseFrontmatter, parseJson } from './yaml-parser.mjs';
|
||||
import { CONTEXT_WINDOW_ANCHOR, LARGE_CONTEXT_WINDOW, withCommas } from './context-window.mjs';
|
||||
|
||||
// Verified per-description skill-listing cap (CC 2.1.105, changelog L1502).
|
||||
// Descriptions longer than this are truncated in the listing the model sees.
|
||||
|
|
@ -32,14 +33,13 @@ export const DESCRIPTION_CAP = 1536;
|
|||
// model reads is allotted ~2% of the context window. The context window is
|
||||
// unknown, so we anchor on a conservative 200k window — the smallest common
|
||||
// size, which fires earliest — and disclose the assumption in the evidence.
|
||||
// The 200k/1M window constants live in context-window.mjs (single source of
|
||||
// truth, shared with the CML CLAUDE.md char-budget check); re-exported here so
|
||||
// existing importers of this module keep working.
|
||||
export const BUDGET_FRACTION = 0.02;
|
||||
export const CONTEXT_WINDOW_ANCHOR = 200_000;
|
||||
export const AGGREGATE_BUDGET_TOKENS = Math.round(BUDGET_FRACTION * CONTEXT_WINDOW_ANCHOR); // 4000
|
||||
export const LARGE_CONTEXT_WINDOW = 1_000_000;
|
||||
export const LARGE_CONTEXT_BUDGET_TOKENS = Math.round(BUDGET_FRACTION * LARGE_CONTEXT_WINDOW); // 20000
|
||||
|
||||
// Dependency-free thousands separator (repo invariant: zero external deps).
|
||||
export const withCommas = (n) => String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
export { CONTEXT_WINDOW_ANCHOR, LARGE_CONTEXT_WINDOW, withCommas };
|
||||
|
||||
// The honest framing required because the budget depends on a context window we
|
||||
// cannot observe (jf. TOK CALIBRATION_NOTE). Appended to budget-overflow evidence.
|
||||
|
|
|
|||
100
tests/fixtures/large-claude-chars/CLAUDE.md
vendored
Normal file
100
tests/fixtures/large-claude-chars/CLAUDE.md
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# Large CLAUDE.md fixture — chars over 40k, lines under 200
|
||||
|
||||
## Project overview
|
||||
|
||||
This fixture exercises the CML char-budget check (CA-CML char-budget): it
|
||||
crosses Claude Code's ~40.0k-char startup-warning threshold while staying well
|
||||
under 200 lines, so it isolates the char check from the line-count check.
|
||||
|
||||
## Commands and workflow
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 00.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 01.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 02.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 03.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 04.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 05.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 06.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 07.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 08.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 09.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 10.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 11.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 12.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 13.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 14.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 15.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 16.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 17.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 18.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 19.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 20.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 21.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 22.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 23.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 24.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 25.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 26.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 27.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 28.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 29.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 30.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 31.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 32.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 33.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 34.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 35.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 36.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 37.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 38.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 39.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 40.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 41.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 42.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 43.
|
||||
|
||||
The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. The conventions for this project are written out at length in flowing prose rather than being split into @imports or .claude/rules files, which is the exact shape that drives a CLAUDE.md past its character budget while the line count stays small and unremarkable. Paragraph 44.
|
||||
|
||||
|
|
@ -129,6 +129,64 @@ describe('CML scanner — large cascade (>500 lines): reframed, not absolute-adh
|
|||
});
|
||||
});
|
||||
|
||||
describe('CML scanner — char budget mirrors CC startup warning (CC 2.1.169)', () => {
|
||||
// large-claude-chars/CLAUDE.md is 48,531 chars across 100 lines: it crosses
|
||||
// Claude Code's ~40.0k-char startup-warning threshold while staying under the
|
||||
// 200-line count, so it isolates the char-budget check from the line check.
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
resetCounter();
|
||||
const discovery = await discoverConfigFiles(resolve(FIXTURES, 'large-claude-chars'));
|
||||
result = await scan(resolve(FIXTURES, 'large-claude-chars'), discovery);
|
||||
});
|
||||
|
||||
const charFinding = (r) =>
|
||||
r.findings.find((f) => /performance-warning threshold/i.test(f.title || ''));
|
||||
|
||||
it('flags a CLAUDE.md over ~40k chars', () => {
|
||||
assert.ok(charFinding(result), 'expected a char-budget finding for a >40k-char CLAUDE.md');
|
||||
});
|
||||
|
||||
it('the char-budget finding is MEDIUM (token cost, not an adherence cliff)', () => {
|
||||
assert.strictEqual(charFinding(result)?.severity, 'medium');
|
||||
});
|
||||
|
||||
it('anchors on CC\'s 40.0k figure and discloses context-window scaling', () => {
|
||||
const f = charFinding(result);
|
||||
const text = `${f?.description || ''} ${f?.evidence || ''}`;
|
||||
assert.match(text, /40\.0k/, 'should mirror CC\'s 40.0k startup-warning figure');
|
||||
assert.match(text, /context window|scales|1,000,000/i, 'should disclose context-window scaling');
|
||||
// Lock the scaling arithmetic: 40.0k anchor x (1M / 200k) = 200,000 chars @ 1M.
|
||||
assert.match(text, /200,000/, 'should disclose the ~200,000-char relaxed threshold at 1M context');
|
||||
});
|
||||
|
||||
it('does NOT fire the line-count findings (chars high, lines under 200)', () => {
|
||||
const lineFinding = result.findings.find((f) => /exceeds (recommended 200|500)/.test(f.title || ''));
|
||||
assert.ok(!lineFinding, `char fixture should not trip a line finding: ${lineFinding?.title || ''}`);
|
||||
});
|
||||
|
||||
it('the char-budget finding ID matches CA-CML-NNN', () => {
|
||||
assert.match(charFinding(result)?.id || '', /^CA-CML-\d{3}$/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CML scanner — large-by-lines but under the char budget (no false char finding)', () => {
|
||||
// large-cascade/CLAUDE.md is 1024 lines but only 37,393 chars (short lines):
|
||||
// under CC's 40.0k char threshold, so the char-budget finding must NOT fire —
|
||||
// proving the check keys on chars, not raw size or line count.
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
resetCounter();
|
||||
const discovery = await discoverConfigFiles(resolve(FIXTURES, 'large-cascade'));
|
||||
result = await scan(resolve(FIXTURES, 'large-cascade'), discovery);
|
||||
});
|
||||
|
||||
it('does not emit a char-budget finding under 40k chars', () => {
|
||||
const f = result.findings.find((x) => /performance-warning threshold/i.test(x.title || ''));
|
||||
assert.ok(!f, 'a 37k-char file (under 40.0k) must not trip the char-budget finding');
|
||||
});
|
||||
});
|
||||
|
||||
describe('CML scanner — empty project', () => {
|
||||
let result;
|
||||
beforeEach(async () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue