Skip to content

Audit H6: an imperative lives in a comment, not in an expression - #6

Merged
ojassug merged 1 commit into
audit-gatewayfrom
audit-h6
Aug 10, 2026
Merged

Audit H6: an imperative lives in a comment, not in an expression#6
ojassug merged 1 commit into
audit-gatewayfrom
audit-h6

Conversation

@ojassug

@ojassug ojassug commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #5 (→ #4#3). Base is audit-gateway, so this diff shows only the H6 commit. Merge the stack bottom-up; each retargets automatically.

Closes audit H6 — the single largest cause of real code not being optimized. CONSTRAINT_DIRECTIVE_LOST accounted for 24 of 40 fallbacks on the audit's corpus.

The audit's proposed fix would have destroyed real protection

The nine-keyword scan (must, must not, never, always, only if, do not, required, except when, make sure to, critical) is written for natural-language system prompts, and was applied to raw content of every kind. In source, required and critical are ordinary identifiers.

The audit's remedy was "scope directive extraction by content type (prose/markdown/prompt kinds only, not code)". I measured where the dropped directives actually come from, over a frozen 293-file corpus at targetReductionRatio: 0.3:

bucket from comments / docstrings from code
Python 16 38 — nearly all logger.critical(...)
TypeScript 38 13readonly required?, error-message literals

So neither extreme works. Trusting the check everywhere keeps 51 false positives; the audit's version discards 54 genuine constraints — and specifically the Python docstring case that docs/phase-1d-semantic-gate-disposition.md measured this check to be the only thing catching.

What separates the two populations is not the content type but the region. An instruction to a reader lives in a comment or a docstring; it never lives in an expression.

Part 1 — extraction is scoped to prose regions

extractProseRegions returns whole content for prose content types, and for code returns line comments (//, #, --, *), block comment bodies, and Python docstrings including their interior lines.

Deliberately line-oriented and syntax-approximate rather than lexed: this is a filter on what may raise a constraint, so over-inclusion costs a false positive (the pre-existing behaviour) and under-inclusion costs a missed constraint. Requiring the comment leader at the start of a trimmed line is exactly what excludes logger.critical(exc) while keeping # never call this twice.

Part 2 — retention is checked per item

The check collected every item's directives into one list and tested each against after.items.map(i => i.content).join('\n'). Two problems:

  • A directive extracted from item A was satisfied if the string happened to appear anywhere in item B — the check could pass for content that was in fact destroyed.
  • A loss anywhere failed the whole run, with no way to say where.

Matching by item id fixes both, and the message now names the item. An item absent from after is skipped, on the same reasoning DriftTracker.findUnwitnessedItems records: selection is not elision, and failing here would make any prunable item carrying an imperative unprunable.

Measured

bucket / route before after delta
python (file) 14.98% 23.14% +8.16pp
python (stdin) 14.88% 22.66% +7.78pp
typescript (file) 23.38% 27.33% +3.95pp

20 of 586 rows changed, and none regressed — no file went from reducing to falling back. Every other bucket is byte-identical.

What deliberately remains

After the change TypeScript has zero remaining code-sourced directives. Every surviving CONSTRAINT_DIRECTIVE_LOST is a genuine imperative in a comment or docstring that an elision would drop, and those files still fall back — correctly, since the run would otherwise silently delete an instruction. That is why the category does not go to zero.

Ordering note for reviewers

This had to land after C1a (#3). The audit observed that this check was "currently the only thing preventing markdown documents from being deleted" — a document survived if its author happened to use one of nine words. Narrowing it first would have widened that data loss.

With C1a in place the drift measurement gate covers markdown on its own merits, and the corpus confirms the handoff: the prose bucket is unchanged at 28/28 fallbacks, now attributed to drift rather than to a coincidence of vocabulary.

Verification

  • npm run typecheck, npm run lint — clean
  • npx vitest run518 passing, 59 files (up from 507)
  • New tests verified to fail 9 of 11 against the unfixed code; the 2 that pass are the ones pinning behaviour H6 must preserve

Cumulative across the stack

Python 14.98% → 23.14%, TypeScript 14.00% → 27.33% — while every gate got stricter: max passing symbol loss fell 66.7% → 40% (#4), and the surviving-witness rule (#3) closed whole-document deletion.

Still open

H5 / §3.1 (multi-item ingestion — the highest structural leverage left, and what would make the knapsack reachable), C4, H4, H2, and the M-tier stragglers.

🤖 Generated with Claude Code

Closes audit H6, the largest single cause of real code not being optimized —
`CONSTRAINT_DIRECTIVE_LOST` accounted for 24 of 40 fallbacks on the audit's
corpus.

The nine-keyword scan (`must`, `must not`, `never`, `always`, `only if`,
`do not`, `required`, `except when`, `make sure to`, `critical`) is written for
natural-language system prompts, and was applied to raw content of every kind. In
source, `required` and `critical` are ordinary identifiers.

Measured over a frozen 293-file corpus at `targetReductionRatio: 0.3`,
classifying every directive a run reported as dropped by where it came from:

  Python       16 from comments/docstrings, 38 from code — nearly all
               `logger.critical(...)`
  TypeScript   38 from comments/docstrings, 13 from code — `readonly required?`,
               error-message literals

That rules out both extremes. Trusting the check everywhere keeps 51 false
positives. The audit's proposed remedy — scope extraction by content type, not
`code` — discards 54 genuine constraints, and specifically the Python docstring
case that `docs/phase-1d-semantic-gate-disposition.md` measured to be the only
thing this check actually catches. What separates the two populations is not the
content type but the region: an instruction to a reader lives in a comment or a
docstring, never in an expression.

So extraction is scoped to prose regions — line comments, block comment bodies
and Python docstrings including their interior lines, plus whole content for
prose content types. Deliberately line-oriented and syntax-approximate rather
than lexed: this is a filter on what may *raise* a constraint, so over-inclusion
costs a false positive (the pre-existing behaviour) and under-inclusion costs a
missed constraint. Requiring the comment leader at the start of a trimmed line is
what excludes `logger.critical(exc)` while keeping `# never call this twice`.

Retention is now checked per item. The check collected every item's directives
into one list and tested each against the joined content of every item, so a
directive from item A was satisfied if the string happened to appear anywhere in
item B — the check could pass for content that was in fact destroyed — and a loss
anywhere failed the whole run with no way to say where. Matching by item id fixes
both and the message names the item. An item absent from `after` is skipped, on
the same reasoning `DriftTracker.findUnwitnessedItems` records: selection is not
elision, and failing here would make any prunable item carrying an imperative
unprunable.

Measured:

  python     file    14.98% -> 23.14%   (+8.16pp)
  python     stdin   14.88% -> 22.66%   (+7.78pp)
  typescript file    23.38% -> 27.33%   (+3.95pp)

20 rows changed of 586, and none regressed — no file went from reducing to
falling back. Every other bucket is byte-identical.

TypeScript now has zero remaining code-sourced directives; every surviving
`CONSTRAINT_DIRECTIVE_LOST` is a genuine imperative in a comment or docstring
that an elision would drop. Those files still fall back, and should. That is why
the category does not go to zero.

Ordering note: this had to land after §37 (C1a). The audit observed that this
check was "currently the only thing preventing markdown documents from being
deleted" — a document survived if its author happened to use one of nine words.
Narrowing it first would have widened that data loss. With §37 in place the drift
measurement gate covers markdown on its own merits, which the corpus confirms:
the prose bucket is unchanged at 28/28 fallbacks, now attributed to drift rather
than to a coincidence of vocabulary.

New tests verified to fail 9/11 against the unfixed code; the 2 that pass are the
ones pinning behaviour H6 must preserve.

See DECISIONS §42.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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