Skip to content

Give two recurring prompt-conformance classes their mechanical rung - #13

Merged
dsnger merged 2 commits into
mainfrom
hardening-invariant-checks
Jul 26, 2026
Merged

Give two recurring prompt-conformance classes their mechanical rung#13
dsnger merged 2 commits into
mainfrom
hardening-invariant-checks

Conversation

@dsnger

@dsnger dsnger commented Jul 26, 2026

Copy link
Copy Markdown
Owner

PR 1 of a two-PR split from the canvas field-findings hardening round. This is
scripts/ plus the doc sites describing those checks. No plugins/** path is
touched, so invariant 12 requires no version bump here
— PR 2 carries the §5
cycle-close nudge, the optional companion files, the scaffolded-template sync and
the 0.6.0 bump.

What this resolves

Two ledger rows dated 2026-07-25 sat at rung pending, both at a third
occurrence, both naming this work as their resolution vehicle. Both are resolved
here by appended rung-2 rows; the pending rows are byte-unchanged.

check class guards, exactly
4a unverified-enforcement-claim in a *.md carrying prompt artifact and follows: exactly one column-zero Target model: line, whose value begins with a recognized token and names exactly one distinct model
4b docs-drift a prose count claim (all <digits|one..twenty>( checklist)? items) equals the checklist it counts, in both definitions, which must agree

Two design points that decided whether these are real:

  • Both halves of 4a are load-bearing. Presence alone accepts
    Target model: any capable chat model — the exact PR docs: sparring briefing for the upstream advisor chat #12 defect. Token
    anywhere accepts it too, because the real defect line named Claude as
    provenance. Measured: anywhere → 1 match, at-start → 0.
  • Word forms are in scope for 4b because the motivating occurrence was one.
    A digit-only check would have missed the very defect the row claims to harden.

The ledger is excluded from both checks. A ledger that quotes defects
self-rejects the checks that detect them — docs/hardening-log.md carries the
historical count claim as evidence, and scanning it would fail the repository
forever on rows that exist to record the fix.

Mutation evidence (documented manual run — nothing automates it)

Procedure and re-run trigger are in the checker header; the mapping is also
recorded in the test file so it travels with the code.

mutant flipped composition
delete check 4a block 20 15 4a: rejects + 4 exclusion: neighbouring … + 4a value extraction failure fires
delete check 4b block 22 16 4b: rejects + 4 4b exclusion: neighbouring … + checklist parser failure fires + 4b claim validator failure fires

Baseline exit 0, mutant exit 1 in both. No accept case moved and nothing
unrelated moved.
scan error fires and 4a/4b exclusion filter failure fires
flip in neither, because they break a stage both checks share — expected, not an
omission.

Suite

61 → 123 assertions. A shared fixture initializer landed first: without it,
25 of the 61 pre-existing assertions failed on a missing checklist before
reaching their own assertion, so accept cases turned red and reject cases started
passing for the wrong reason.

Review

Gate A: 9 passes on the plan. Gate B: 8 passes, 13 findings, final spec and
quality passes both clean against an unchanged tree.

Every Gate-B finding was one of two shapes — a claim outrunning the code, or a
path where the gate could report success without doing its work. The second
family took four passes and was closed at six depths: the recursive scan, the
post-scan exclusion filters, the claim validator, the checklist parser, the
per-file commands inside 4a, and the value-extraction pipeline, where
grep | head | sed exposed only sed's status. Each has a fixture.

AGENTS.md invariant 11 is narrowed accordingly: "nothing mechanical checks
them" stopped being true, and it now says no comprehensive checker exists and
names these two as a floor.

Summary by CodeRabbit

  • New Features

    • Added automated prompt-conformance checks for model declarations and checklist-count claims in Markdown documentation.
    • Added validation for malformed prompt artifacts and documentation drift.
  • Bug Fixes

    • Improved detection of invalid model declarations, checklist mismatches, parser failures, and scan errors.
  • Documentation

    • Updated contributor, architecture, and quality-check documentation to describe the new conformance checks.
    • Recorded the completed hardening work and validation plan.

Both classes reached a third occurrence and sat at rung `pending` in the ledger,
naming this work as their resolution vehicle. Two checks in check-invariants.sh
now guard one spelling each, and the appended rung-2 rows say exactly which.

Check 4a — a file asserting it follows docs/prompt-standards.md must carry
exactly one column-zero `Target model:` line whose value BEGINS with a
recognized token and names exactly one distinct model. Both halves are load
bearing: presence alone accepts "any capable chat model", and a token found
anywhere accepts it too, because the real PR #12 defect line mentioned Claude
as provenance. Measured: token-anywhere matched it, token-at-start did not.

Check 4b — a prose count claim must equal the checklist it counts. Word forms
one..twenty are in scope BECAUSE the motivating occurrence was one; a
digit-only check would have sailed past the very defect the row claims to
harden. Claims are recognized in two stages so a malformed `all 012 items`
fires rather than being invisible.

The ledger is excluded from both checks. A ledger that quotes defects
self-rejects the checks that detect them: docs/hardening-log.md carries the
historical count claim as evidence, and scanning it would fail the repository
forever on rows that exist to record the fix.

Also here: one shared fixture initializer, without which 25 of the 61
pre-existing assertions failed on a missing checklist before reaching their own
assertion; the docs sweep across seven locations in five files that describe
this checker; and AGENTS.md invariant 11 narrowed, since "nothing mechanical
checks them" stopped being true.

Suite 61 -> 123 assertions. Gate B: 8 passes, 13 findings, final spec and
quality passes both clean against an unchanged tree. No plugins/** path is
touched, so invariant 12 requires no version bump; the §5 nudge, the companion
files and the template sync land in PR 2 with the bump.
@cursor

cursor Bot commented Jul 26, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@dsnger, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 6 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a825cac0-98d4-47d6-9d6e-c2a503783c29

📥 Commits

Reviewing files that changed from the base of the PR and between eed589c and 92de0d2.

📒 Files selected for processing (1)
  • scripts/check-invariants.sh
📝 Walkthrough

Walkthrough

Adds two Markdown-only prompt-conformance checks for model declarations and checklist-count claims, extensive regression fixtures, CI labeling, invariant documentation, hardening records, and completion tracking.

Changes

Prompt Conformance

Layer / File(s) Summary
Checker implementation
scripts/check-invariants.sh
Adds checks for exactly one recognized Target model: declaration and matching digit or word-form checklist-count claims, with exclusions and parser-error handling.
Regression fixture coverage
scripts/check-invariants.test.sh
Initializes checklist artifacts and adds acceptance, rejection, exclusion, cleanup, and injected failure cases for both checks.
CI and invariant documentation
.github/workflows/ci.yml, AGENTS.md, README.md, docs/architecture.md
Updates CI labels and repository descriptions to include the two prompt-conformance checks.
Plan and resolution records
docs/superpowers/plans/..., docs/hardening-log.md, todos.md
Records implementation rules, scan boundaries, fixture requirements, ledger resolutions, and completed tooling work.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant CI
  participant Checker as check-invariants.sh
  participant Prompts as Markdown prompt artifacts
  participant Standards as docs/prompt-standards.md
  participant Template as workflow-init template
  CI->>Checker: Run invariant checks
  Checker->>Prompts: Scan model declarations and count claims
  Checker->>Standards: Parse checklist length
  Checker->>Template: Parse checklist length
  Checker-->>CI: Return validation status
Loading

Poem

A rabbit checks each model line,
Counts the checklist, neat and fine.
CI hops when rules agree,
Docs and tests now guard the key.
Two small checks keep prompts bright! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding mechanical checks for two prompt-conformance classes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 26, 2026

Copy link
Copy Markdown

Greptile Summary

Adds two mechanical prompt-conformance checks and integrates them into the existing invariant gate.

  • Requires Markdown files claiming prompt-standards conformance to name exactly one recognized target model.
  • Validates prose checklist-count claims against synchronized, structurally valid checklist definitions.
  • Expands regression fixtures, CI descriptions, architecture documentation, and the hardening ledger accordingly.

Confidence Score: 5/5

The pull request appears safe to merge, with no concrete correctness, security, or independently actionable quality issue identified.

The new checks fail closed on scan and parsing errors, validate the intended constrained spellings, preserve the existing invariant behavior, and are backed by targeted regression fixtures for malformed input and exclusion boundaries.

Important Files Changed

Filename Overview
scripts/check-invariants.sh Adds fail-closed model-declaration and checklist-count validation with explicit scan, filter, parser, and validator error handling.
scripts/check-invariants.test.sh Adds shared prompt fixtures and extensive accept, reject, exclusion, malformed-input, and operational-failure coverage for both checks.
.github/workflows/ci.yml Updates the existing invariant-check step description to reflect prompt-conformance enforcement without changing execution behavior.
docs/hardening-log.md Appends rung-2 resolution records for the two recurring defect classes while preserving the pending historical entries.
AGENTS.md Documents the narrow mechanical floor provided by the new checks while retaining human review as the comprehensive prompt-quality gate.
docs/superpowers/plans/2026-07-26-prompt-conformance-checks.md Records the design, scope, exclusions, fixtures, mutation evidence, and known limitations of the new checks.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Run invariant checker] --> B[Scan conforming Markdown files]
  B --> C{Exactly one recognized target model?}
  C -- No --> F[Fail invariant gate]
  C -- Yes --> D[Parse both checklist definitions]
  D --> E{Definitions valid and counts agree?}
  E -- No --> F
  E -- Yes --> G[Scan prose checklist-count claims]
  G --> H{Every claim matches checklist count?}
  H -- No --> F
  H -- Yes --> I[Invariant gate passes]
Loading

Reviews (1): Last reviewed commit: "Give two recurring prompt-conformance cl..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/check-invariants.sh (1)

441-452: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Digit-claim comparison doesn't use the same string-forcing idiom as its sibling check.

prompt_checklist_count (line 408) deliberately writes $0 "" != n "" to force a string compare and avoid awk's numeric/strnum coercion on -v-assigned n — the header comment explicitly credits this to guarding against overflow on long digit runs. The claim validator's digit branch does the equivalent comparison as a bare tok != n (line 448), without that same guard.

Under strict POSIX semantics tok (built via sub()) should already be a plain "string" type rather than a "numeric string", so tok != n likely already resolves as a string compare today — but that safety currently depends on an implicit, easy-to-regress typing distinction rather than the explicit idiom this same file uses elsewhere for exactly this reason. Given the stated design goal ("never +0, so a 40-digit claim cannot overflow its way to a wrong verdict"), the same explicit idiom should be applied here for consistency and to remove reliance on awk-implementation-specific type-inference behavior.

🛠️ Proposed fix
-          if (tok != n) print $0 "  <- checklist has " n
+          if (tok "" != n "") print $0 "  <- checklist has " n

Worth confirming across the awk implementations this script may run under (mawk, busybox awk, BSD/macOS awk) that sub()-derived values are never treated as numeric strings, since this repo already treats BSD-vs-GNU regex differences as a real, previously-bitten class of bug.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-invariants.sh` around lines 441 - 452, Update the digit
comparison in the claim validator’s awk block to use the same explicit
string-forcing comparison idiom as prompt_checklist_count, comparing tok and n
as strings without numeric coercion or arithmetic conversion. Keep the existing
canonical-number validation and mismatch reporting unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@scripts/check-invariants.sh`:
- Around line 441-452: Update the digit comparison in the claim validator’s awk
block to use the same explicit string-forcing comparison idiom as
prompt_checklist_count, comparing tok and n as strings without numeric coercion
or arithmetic conversion. Keep the existing canonical-number validation and
mismatch reporting unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9fb813ab-e333-41ae-81f8-e269a5b1343c

📥 Commits

Reviewing files that changed from the base of the PR and between 2774580 and eed589c.

📒 Files selected for processing (9)
  • .github/workflows/ci.yml
  • AGENTS.md
  • README.md
  • docs/architecture.md
  • docs/hardening-log.md
  • docs/superpowers/plans/2026-07-26-prompt-conformance-checks.md
  • scripts/check-invariants.sh
  • scripts/check-invariants.test.sh
  • todos.md

CodeRabbit nitpick on #13: `prompt_checklist_count` writes `$0 "" != n ""` to
force a string compare, and the header credits that idiom for keeping a long
digit run from overflowing into a wrong verdict — but the claim validator did the
equivalent comparison as a bare `tok != n`.

Validated by hand rather than by subagent: the PR touches AGENTS.md, so
process-pr-review's instruction-path precheck bars triage. The claim is true as a
consistency point and not a live bug — `n` arrives via `-v` (a strnum) and `tok`
comes from `sub()` (a string), so POSIX already resolves it as a string compare,
and the 40-digit fixture passes either way on BSD awk 20200816. The point stands
that it relied on type inference the rest of the file deliberately does not.

Gate B triviality skip, documented per CLAUDE.md §5: one-token, behaviour-
preserving change inside an existing awk expression, covered by the existing
`4b: 40-digit claim rejected` and `4b: non-canonical 012 rejected` fixtures.

Not hardened: no ledger class fits a style-consistency nit whose behaviour was
already correct, and minting one would dilute the recurrence signal.

(First attempt at this comment broke the script — an apostrophe in `awk's`
terminated the single-quoted awk program. The suite caught it; the comment now
says so.)
@dsnger

dsnger commented Jul 26, 2026

Copy link
Copy Markdown
Owner Author

Processed — one tracked claim, accepted and fixed in 92de0d2.

This PR touches AGENTS.md, so /dev-workflow:process-pr-review's
instruction-path precheck barred subagent triage: a subagent loads the whole
CLAUDE.md hierarchy, and a PR editing an instruction file would be rewriting
the rules its own reviewer runs under. I validated the claim myself, and this
reply says so rather than implying a triage that did not happen.

CodeRabbit — digit-claim comparison lacks the string-forcing idiom

Accept. Verified: check-invariants.sh:408 (prompt_checklist_count) uses
$0 "" != n "" and the file header credits that idiom for keeping a long digit
run from overflowing into a wrong verdict, while the claim validator at :448 did
the equivalent comparison as a bare tok != n.

Not a live bug, and the reply should be precise about that. n arrives via
-v (a strnum) and tok comes from sub() (a string), so POSIX already
resolves that comparison as a string compare. Measured on BSD awk 20200816:

tok="1234567890123456789012345678901234567890", n=12
bare   -> differ (correct)
forced -> differ (correct)

The 4b: 40-digit claim rejected fixture passes either way. Your point stands on
its own terms though: it relied on type inference that the rest of this file
deliberately refuses to rely on, and that reliance is the regressable part. Fixed
to match, with the reasoning in a comment.

Gate B triviality skip, documented in the commit per CLAUDE.md §5 — one
token, behaviour-preserving, inside an existing awk expression, covered by
existing fixtures.

Not hardened. No ledger class fits a style-consistency nit whose behaviour
was already correct, and minting one would dilute the recurrence signal that
docs/hardening-log.md exists to carry.

One thing worth recording: my first attempt at that explanatory comment wrote
awk's, and the apostrophe terminated the single-quoted awk program — the suite
went from 123 green to a wall of syntax errors immediately. The comment now
carries a note about it.

Greptile

5/5, no actionable issue — no defect claim, so nothing tracked.

@dsnger
dsnger merged commit 9ff8bcd into main Jul 26, 2026
2 checks passed
@dsnger
dsnger deleted the hardening-invariant-checks branch July 26, 2026 12:21
dsnger added a commit that referenced this pull request Jul 26, 2026
Three findings came out of a real project running this workflow. This is the
second of two PRs; #13 took the mechanical checks. Finding A was cut after five
Gate-A passes and finding B after two — both are stories now, carrying the
findings that killed them as their opening evidence.

**Companions (finding C).** The §5 protocol knew only about the findings file,
so dispositions and interrupted-cycle state lived in chat history and died with
the session. Both §5 copies now describe two advisory companions: a per-pass
dispositions file, and a cycle-stable resume note — gate-a-spec-resume.md,
gate-a-plan-resume.md, gate-b-resume.md. Cycle-stable rather than pass-named
because a note keyed to the interrupted pass is exactly the file a resuming
agent will not look for once the counter moves. Gate B gets one note even under
reviewType: full: the per-branch findings files race only because Codex's two
reviewers write them, while the resume note is written by the outer agent,
sequentially. Both are optional and nothing enforces them — the ledger row says
so rather than implying P std made context durable.

**Template sync.** The ad-hoc-briefs paragraph, deferred since #12, is now in
the scaffolded template — but not verbatim. The repo paragraph links a file
/workflow-init never scaffolds and asserts this repo's own incident count, so
downstream gets a neutral variant preserving both halves of the principle:
briefs carry the checklist's habits, and nobody reviews a brief against all 12
items. The canvas provenance line stays repo-only, per prompt-standards item 8.

**Bot completion signal.** #12 and #13 both merged heads that were never
reviewed: the check passed while the comment read "Review rate limited", and on
#13 the only CodeRabbit review record names eed589c while the merged head was
92de0d2. docs/pr-review-bots.md now separates "the check stopped pending" from
"the head was reviewed" across all three sites, with a verification command that
was found broken by running it — gh api --slurp is rejected with --jq — and is
now measured in both directions.

Gate A: 8 passes, clean. Gate B: 5 passes, final spec and quality both clean on
an unchanged tree.
dsnger added a commit that referenced this pull request Jul 26, 2026
#12 and #13 merged unreviewed heads and the miss was found afterwards. On #14 the
verification query caught it BEFORE merging: check green, comment rate-limited,
zero qualifying reviews for the head. Re-trigger produced nothing; merged on an
explicit human decision with the exception recorded.

Gate B triviality skip, documented per CLAUDE.md §5: prose-only addition to a
descriptive table's surrounding notes, no mechanism or routing changed.
dsnger added a commit that referenced this pull request Jul 26, 2026
* Ship the §5 companion files, the deferred template sync, and 0.6.0

Three findings came out of a real project running this workflow. This is the
second of two PRs; #13 took the mechanical checks. Finding A was cut after five
Gate-A passes and finding B after two — both are stories now, carrying the
findings that killed them as their opening evidence.

**Companions (finding C).** The §5 protocol knew only about the findings file,
so dispositions and interrupted-cycle state lived in chat history and died with
the session. Both §5 copies now describe two advisory companions: a per-pass
dispositions file, and a cycle-stable resume note — gate-a-spec-resume.md,
gate-a-plan-resume.md, gate-b-resume.md. Cycle-stable rather than pass-named
because a note keyed to the interrupted pass is exactly the file a resuming
agent will not look for once the counter moves. Gate B gets one note even under
reviewType: full: the per-branch findings files race only because Codex's two
reviewers write them, while the resume note is written by the outer agent,
sequentially. Both are optional and nothing enforces them — the ledger row says
so rather than implying P std made context durable.

**Template sync.** The ad-hoc-briefs paragraph, deferred since #12, is now in
the scaffolded template — but not verbatim. The repo paragraph links a file
/workflow-init never scaffolds and asserts this repo's own incident count, so
downstream gets a neutral variant preserving both halves of the principle:
briefs carry the checklist's habits, and nobody reviews a brief against all 12
items. The canvas provenance line stays repo-only, per prompt-standards item 8.

**Bot completion signal.** #12 and #13 both merged heads that were never
reviewed: the check passed while the comment read "Review rate limited", and on
#13 the only CodeRabbit review record names eed589c while the merged head was
92de0d2. docs/pr-review-bots.md now separates "the check stopped pending" from
"the head was reviewed" across all three sites, with a verification command that
was found broken by running it — gh api --slurp is rejected with --jq — and is
now measured in both directions.

Gate A: 8 passes, clean. Gate B: 5 passes, final spec and quality both clean on
an unchanged tree.

* Correct the process-pr-review step reference in the Finding A story

CodeRabbit on #14: the parked Finding A entry said the mandated ledger check
lives in `process-pr-review` step 4. It is step 5 — step 4 is the
stop-and-ask-the-user step. Verified against the command itself, which this PR
does not modify.

Validated by hand rather than by subagent: #14 touches CLAUDE.md and plugins/,
so process-pr-review's instruction-path precheck bars triage.

Left alone deliberately: docs/superpowers/specs/2026-07-18-... also says step 4.
That is a historical artifact recording what was true when written, this PR does
not touch it, and docs/superpowers/ is excluded from the conformance checks for
exactly that reason.

Gate B triviality skip, documented per CLAUDE.md §5: a one-word correction to a
backlog entry, no behaviour and no mechanism changed.

* Record the fourth completion-signal observation (#14)

#12 and #13 merged unreviewed heads and the miss was found afterwards. On #14 the
verification query caught it BEFORE merging: check green, comment rate-limited,
zero qualifying reviews for the head. Re-trigger produced nothing; merged on an
explicit human decision with the exception recorded.

Gate B triviality skip, documented per CLAUDE.md §5: prose-only addition to a
descriptive table's surrounding notes, no mechanism or routing changed.
dsnger added a commit that referenced this pull request Jul 27, 2026
…ot a hazard

Fourth occurrence (#12, #13, #15, #16 — the last observed while writing this
row): the status check passes while the comment reads "Review rate limited"
and the live head has no review record. The row now says never merge on the
check alone; the review count is the arbiter, and the verification command
runs on every merge rather than when something looks off.

Docs-only (docs/**.md), so Gate B is N/A per CLAUDE.md §5's prose exemption.
dsnger added a commit that referenced this pull request Jul 27, 2026
* harden: three classes from the profiles cycle, at the rungs that fit

Runs dev-workflow:harden-finding on the three classes that recurred through
the risk/security/validation profiles work. All three land as text; none
reaches a mechanical rung, and each ledger row says so rather than implying
otherwise.

unverified-enforcement-claim, 4th occurrence, rung P — prompt-standards
item 11 gains two rules: where the reader can reach the authoritative source,
cite it instead of restating it (with invariant 8's self-contained-template
exception named), and delete a mechanism claim that has needed a fourth
correction rather than refining it again. From a paragraph describing the
hook's path matcher that took four consecutive Gate-B corrections, each a
subtler version of the last, and closed only when the enumeration was deleted.

rewrite-drops-prior-condition, NEW class, rung 1 — a new AGENTS.md Don't:
never replace a decision procedure without listing its old conditions and
marking each kept, moved, or deliberately dropped. Ten instances in one
cycle, one of which briefly made an eligible profile sufficient for a Gate-B
skip: a gate-off path invented by the change that exists to close one.

docs-drift, 4th occurrence with a new mechanism, rung P — a standing lens on
every Gate-B call in both §5 copies: "which existing statements does this
diff falsify?" It found a shipped command that would have let a one-line fix
skip Gate B, plus two docs teaching a rule the same change had narrowed.

Two escalations deliberately refused, with the reasoning in the rows: both
lineages' latest entries are rung-2 checks guarding one spelling each
(Target-model lines; prose count claims), and both new defects fall outside
those spellings — the over-escalation those rows warn about by name.

Gate B: 7 findings at pass 1, then 1, 1, and clean on both branches at
pass 4. Three of those findings were this change committing the classes it
hardens — the item-11 fix reaching only the repo copy, the new rule
contradicting invariant 8, and the lens claiming no check could reach the
class. Verification: full battery green — shellcheck (6 files), hook tests,
check-invariants + suite (123 assertions), check-version-bump + suite
(36 assertions), claude plugin validate --strict; exit 0.

* docs(bots): the CodeRabbit rate-limit pattern is settled behaviour, not a hazard

Fourth occurrence (#12, #13, #15, #16 — the last observed while writing this
row): the status check passes while the comment reads "Review rate limited"
and the live head has no review record. The row now says never merge on the
check alone; the review count is the arbiter, and the verification command
runs on every merge rather than when something looks off.

Docs-only (docs/**.md), so Gate B is N/A per CLAUDE.md §5's prose exemption.

* docs(taxonomy): clarify the rewrite-drops-prior-condition definition

PR #16 review finding: "one the old prose carried" was ambiguous; it now
reads "one of the conditions the old prose carried".

Docs-only (docs/**.md), so Gate B is N/A per CLAUDE.md §5's prose exemption.
Validated directly rather than by a finding-triage subagent — the PR edits
instruction-bearing paths, which the command's step-0 precheck routes to
manual validation.
dsnger added a commit that referenced this pull request Jul 27, 2026
Docs-only, two files, no plugin path — no version bump.

CodeRabbit leaves Wait for after five consecutive unreviewed heads (#12, #13,
#15, #16, #17 — the last with zero review records on the PR) followed by a
genuine review on #18. Real findings source, unpredictable delivery, and a
completion signal that fires regardless of whether a review happened: the
opportunistic category by this file's own definition. Wait for is now empty.

Row additions: the status check goes green whether or not a review happened,
and `@coderabbitai review` is a no-op while automatic reviews are active
(CodeRabbit's own message on #17), which retroactively explains #14's
"re-trigger produced nothing". Plan corrected to Free; "Pro Plus" was observed
on PR #1 only.

The count rule's two facts separated: the per-head count remains the arbiter of
whether a head was reviewed, for any bot; the recorded-human-decision
requirement binds only bots under Wait for, and is dormant while that list is
empty. Every head reaching a PR has already passed Gate B, so a quiet
supplementary reviewer needs no exception.

MANIFEST.md: the bare `CLAUDE.md` row resolved to the repo root and produced a
false Major on #18. Qualified to source-files/CLAUDE.md, with the three files
distinguished, and root §6 (context canary) recorded as deliberately outside
the §1–§5 template range and never to be synced into the scaffolded template.

Pre-merge diagnostic: per-head count 1 on head 2634bf2 — reviewed. One Minor
finding (drop or explicitly optionalize the re-trigger step) collected, not
actioned, per §5's Minor/Nit rule.

Gate B: N/A — every path is explanatory documentation per §5's prose rule.
Battery green at each commit.
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