claude-code - 💡(How to fix) Fix [FEATURE] Change Request — Bug / Feature Report for Claude Engineering [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#54093Fetched 2026-04-28 06:39:25
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
labeled ×3

Error Message

  • Don't proceed to commit. Surface the failure to the user with the exact error. | Push fails (remote ahead, auth error, etc.) | Don't auto-rebase — user decides |

Root Cause

Theory: the agent must Read the file before editing it. The header is therefore in agent context at edit-time, not just session-start. This is the strongest layer because it's literally co-located with the code being changed.

Fix Action

Fix / Workaround

Status: open · v1 shipped 2026-04-26 · v1.1 (Step 5b stale-test scan) shipped 2026-04-27 Type: Feature request → workaround skill (currently a project-scoped skill plugging a gap that should arguably be platform-level) Reporter: Evan Wiley (RetroHub AI, retrohubai.com) Project: RetroHub AI — Next.js 16 / TypeScript / Postgres / Firebase Auth, ~1000+ TS files, ~1100 tests, multi-environment dev (Windows local, code-server on QNAP, claude.ai cloud agent) Skill location: .claude/skills/cr/SKILL.md (project-scoped, committed to repo) Related artifact: docs/superpowers/reviews/2026-04-26-238cfae-tier1-headers.md Related commits (chronological):

  • 97f3df3 — original §1.1 file-header discipline shipped
  • c153964 — agent (me) violated the rule the same day on 3 chokepoint files
  • 9477dda — backfill commit catching the violation
  • 2a937be/cr skill v1 shipped
  • 4bb485c4 — CLAUDE.md amendment making /cr the default commit path
  • c2e93ea8 — Tier-1 header audit merged (51 chokepoints headered)
  • aeca446e — theme rename book-creatorlight (the trigger for v1.1)
  • dabb836e/cr Step 5b "stale-test scan" added; .dockerignore Playwright exclusions

The agent (Claude) is intermittently failing to follow rules that are explicitly written in CLAUDE.md and that the agent itself co-authored, even within minutes of writing them. The user has built a project-scoped /cr skill as a workaround that turns the discipline into a single named verb the agent runs at session end, layered on top of (a) headers embedded in the files themselves, (b) the CLAUDE.md rule, and (c) a verified: line in every commit message. This document captures the failure mode, the user-side workarounds, and what platform-level support would actually fix the underlying gap.

MechanismCoverage gap
CLAUDE.md system contextLoaded at session start. Rules degrade in salience as conversation grows. Mid-session edits don't re-trigger a re-read.
Skill descriptionsHelp with skill invocation, not with code-touch discipline.
User reminders mid-sessionCosts the user attention. The whole point of CLAUDE.md is the user shouldn't have to re-state the rules.
Subagent dispatch with embedded remindersWorks for subagents but doesn't help the main session.
Memory systemUser-preference auto-memory exists, but it's also context-loaded — same degradation curve as CLAUDE.md.

Code Example

// src/lib/billingEngine.ts
//
// Role: Single source of truth for "can this user be charged?" and the
//       canonical 402 limit response shape.
//
// Callers: routes under /api/generate/*, /api/neuro/v2/voice/*,
//          /api/social/{finalize,ai-assist,draft},
//          lib/routingTunnel/stateBuilder.ts, /api/user/usage-summary.
//
// Runtime deps: Subscription, TierConfig, Generation, User (Prisma).
//               auth.ts auto-link/JIT/guest paths must upsert a
//               Subscription with currentPeriodStart/End set; checkUsage
//               back-fills missing rows defensively.
//
// Contract tests: src/lib/__tests__/billingEngine.test.ts, ...

---

grep -rE "from [\"']@/path/to/file[\"']" src/ __tests__/ tests/ | wc -l

---

// src/path/to/file.ts
//
// Role: [one paragraph — what this file IS, in functional terms]
//
// Callers: [list of files/route prefixes that import this; group by area]
//
// Runtime deps: [Prisma models, env vars, external services, contract assumptions]
//
// Contract tests: [paths to tests that pin this file's contract]

---

npx tsc --noEmit
npx eslint src
npm test -- --run [relevant test paths]

---

git add <specific files>

---

<type>(<scope>): <short summary>

<body — explain WHY, not just WHAT, when non-obvious>

verified: tsc clean, eslint clean, N tests pass

---

git commit -m "$(cat <<'EOF'
feat(cr): add /cr end-of-session ceremony skill

verified: tsc clean, eslint clean, 209 tests pass
EOF
)"

---

git push
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing requests and this feature hasn't been requested yet
  • This is a single feature request (not multiple features)

Problem Statement

Change Request — Bug / Feature Report for Claude Engineering

Status: open · v1 shipped 2026-04-26 · v1.1 (Step 5b stale-test scan) shipped 2026-04-27 Type: Feature request → workaround skill (currently a project-scoped skill plugging a gap that should arguably be platform-level) Reporter: Evan Wiley (RetroHub AI, retrohubai.com) Project: RetroHub AI — Next.js 16 / TypeScript / Postgres / Firebase Auth, ~1000+ TS files, ~1100 tests, multi-environment dev (Windows local, code-server on QNAP, claude.ai cloud agent) Skill location: .claude/skills/cr/SKILL.md (project-scoped, committed to repo) Related artifact: docs/superpowers/reviews/2026-04-26-238cfae-tier1-headers.md Related commits (chronological):

  • 97f3df3 — original §1.1 file-header discipline shipped
  • c153964 — agent (me) violated the rule the same day on 3 chokepoint files
  • 9477dda — backfill commit catching the violation
  • 2a937be/cr skill v1 shipped
  • 4bb485c4 — CLAUDE.md amendment making /cr the default commit path
  • c2e93ea8 — Tier-1 header audit merged (51 chokepoints headered)
  • aeca446e — theme rename book-creatorlight (the trigger for v1.1)
  • dabb836e/cr Step 5b "stale-test scan" added; .dockerignore Playwright exclusions

TL;DR

The agent (Claude) is intermittently failing to follow rules that are explicitly written in CLAUDE.md and that the agent itself co-authored, even within minutes of writing them. The user has built a project-scoped /cr skill as a workaround that turns the discipline into a single named verb the agent runs at session end, layered on top of (a) headers embedded in the files themselves, (b) the CLAUDE.md rule, and (c) a verified: line in every commit message. This document captures the failure mode, the user-side workarounds, and what platform-level support would actually fix the underlying gap.


1. Symptom — the failure mode that triggered this work

What happened (timeline of 2026-04-26):

  1. Agent and user collaboratively drafted CLAUDE.md §1.1 — a "file-header discipline" rule requiring chokepoint files (≥5 importers, or in the Project Context Manifest, or single-source-of-truth) to carry a Role / Callers / Runtime deps / Contract tests block at the top. Updating that header in the same commit as the code change is mandatory; the rule prohibits parking it for "a separate doc commit."
  2. Same session, agent shipped commit 97f3df3 introducing §1.1.
  3. Same session, ~5 minutes later, agent shipped commit c153964 editing three chokepoint files (LocalAIEngine.tsx, StatusFooter.tsx, app/layout.tsx) without adding the headers it had just mandated.
  4. User caught it manually with: "I do not know what we called our ChangeRequest type logic but did all the files you touched get updated?"
  5. Agent admitted the failure, audited the diff, found 3 of 5 chokepoints missing headers, and shipped backfill commit 9477dda.

Why this matters: the rule was loaded into context (it's in CLAUDE.md, which is loaded every conversation). The agent had literally written the rule moments before. The rule explicitly named the failure mode it was preventing. The agent failed it anyway.

The user's exact reaction was: "this is why maybe we need a pause and a repo wide update this way you see it in everyfile or you need to refresh your memory with the claude.md so you remember it"

This is not a one-off. The user reports a multi-week pattern of similar drift across other CLAUDE.md rules (test discipline, no-deferring-fixes pre-launch, no-stub-routes, etc.), with the recurring shape: rule is in CLAUDE.md → agent reads CLAUDE.md at session start → agent violates rule mid-session anyway. Mid-session focus drift is real and it's not solved by "the rule is in the system prompt."


2. Why generic instructions in CLAUDE.md aren't enough

MechanismCoverage gap
CLAUDE.md system contextLoaded at session start. Rules degrade in salience as conversation grows. Mid-session edits don't re-trigger a re-read.
Skill descriptionsHelp with skill invocation, not with code-touch discipline.
User reminders mid-sessionCosts the user attention. The whole point of CLAUDE.md is the user shouldn't have to re-state the rules.
Subagent dispatch with embedded remindersWorks for subagents but doesn't help the main session.
Memory systemUser-preference auto-memory exists, but it's also context-loaded — same degradation curve as CLAUDE.md.

The core gap: there is no Claude Code mechanism that says "before you commit, re-verify these N rules against the staged diff." Hooks come closest, but they're local-only — they don't survive code-server, the cloud agent, or fresh clones, which makes them unsuitable for a project that's actively developed across three environments.


3. The user's layered workaround

The user has built a four-layer defense against agent forgetfulness, all of which travel via git:

Layer 1 — Headers in the files themselves

Chokepoint files carry a top-of-file comment block:

// src/lib/billingEngine.ts
//
// Role: Single source of truth for "can this user be charged?" and the
//       canonical 402 limit response shape.
//
// Callers: routes under /api/generate/*, /api/neuro/v2/voice/*,
//          /api/social/{finalize,ai-assist,draft},
//          lib/routingTunnel/stateBuilder.ts, /api/user/usage-summary.
//
// Runtime deps: Subscription, TierConfig, Generation, User (Prisma).
//               auth.ts auto-link/JIT/guest paths must upsert a
//               Subscription with currentPeriodStart/End set; checkUsage
//               back-fills missing rows defensively.
//
// Contract tests: src/lib/__tests__/billingEngine.test.ts, ...

Theory: the agent must Read the file before editing it. The header is therefore in agent context at edit-time, not just session-start. This is the strongest layer because it's literally co-located with the code being changed.

Status: 51 chokepoint files headered as of merge c2e93ea8. The Tier-1 audit ran as a scheduled remote agent; output review was done by the agent in the user's session.

Layer 2 — CLAUDE.md §1.1

The discipline lives at CLAUDE.md lines ~190–236. It names the rule, the format, the "same commit, never park" requirement, the verification line, and the /cr invocation. This is the system-level reminder.

Layer 3 — /cr skill

The change-request ceremony, invoked by the user typing /cr. Project-scoped at .claude/skills/cr/SKILL.md. Runs nine steps:

  1. Audit files touched this session
  2. Chokepoint check (5+ importers OR in Project Context Manifest OR known SSOT)
  3. Header pass (add or update Role / Callers / Runtime deps / Contract tests)
  4. VERSION bump per CLAUDE.md §17 if applicable
  5. Verification gate (tsc --noEmit, eslint src, relevant tests)
  6. Stage only edited files (no git add -A)
  7. Commit with verified: line in the message
  8. Push to current branch
  9. Report SHA + push result

Auto-approve unless a push-back trigger fires: verification fails, header judgment call (file's role changed, ambiguous chokepoint), ambiguous VERSION bump, surprises in staged set (.env, untracked WIP), diff larger than the session warrants, push fails, or working tree contains stale changes from prior sessions.

Layer 4 — /cr is the default commit path

CLAUDE.md §1.1 amended (commit 4bb485c4) to make /cr mandatory for every session commit. Direct git commit is reserved for non-session automation. "Stage and commit" from the user resolves to "run /cr". This makes layer 3 non-skippable.

Net effect across all four layers:

  • Edit-time: header is in context (layer 1).
  • Conversation-level: rule is in CLAUDE.md (layer 2).
  • Commit-time: skill walks the audit (layer 3).
  • Workflow-level: /cr is the only sanctioned path (layer 4).

The user explicitly chose layered defense over a single hook because hooks are local-only and don't survive the three-environment workflow.


4. The actual underlying gap (and why this is a Claude-side problem, not just a user-side workaround)

The user has documented the failure pattern beyond just §1.1. From the user's auto-memory feedback entries (anonymized):

  • feedback_no_deferring_pre_launch.md — pre-launch policy: fix every issue noticed in-flow, no parking. "See garbage on the street, pick it up." The user has had to re-state this multiple times because agent keeps suggesting "follow-up tasks" or "park for later."
  • feedback_verify_lint_and_tsc.md — always run both eslint src/ and tsc --noEmit before claiming code is ready. Re-stated because agent claimed completion without running both.
  • feedback_plan_coverage_audit.md — plans must audit every spec section for task coverage; backend-heavy plans that stub UI are a recurring failure pattern.
  • feedback_file_header_discipline.md — codified the §1.1 rule into memory after the same-day violation.
  • feedback_no_legacy_billing.md, feedback_admin_tasks_via_airouter.md, feedback_no_redis.md, etc. — recurring re-statements of project-specific architectural rules the agent kept missing.

The pattern: agent reads CLAUDE.md at session start, internalizes it for the first ~10–20 turns, then drifts. By turn 40+ in a long session, agent is making suggestions or commits that contradict explicit CLAUDE.md rules.

This is not a documentation problem — the user has thorough docs. This is not a "the rule is too complex" problem — /cr runs nine concrete steps the agent can verbatim execute. This is a rule-recall-under-cognitive-load problem, and the user has built the workaround themselves because the platform doesn't currently offer one.


5. What platform-level support would actually fix this

Below are platform features the user has discussed (some hypothetical, some referenced from existing Claude Code primitives) that would close the gap without requiring every project to ship its own /cr skill.

5a. Pre-commit / pre-tool checkpoint for declared invariants

Hooks come closest today, but they're:

  • Local-only — don't survive code-server / cloud agent / fresh clone
  • Shell-script-shaped — fine for "block git commit if X" but awkward for "re-read CLAUDE.md §1.1 and verify each chokepoint touched in this commit has its header updated"
  • Off-by-default for platform-level rules

A hook framework that:

  • Lives in the repo (e.g., .claude/hooks/*.md or *.ts)
  • Travels with git clone to all environments
  • Can be invoked by the model itself at well-defined moments (before commit, before push, before claiming completion) rather than only by tool wrappers
  • Can express natural-language invariants ("for each file in the staged diff, if it's a chokepoint, verify the header reflects the changes") not just shell predicates

…would fix the layer-3 gap natively. Today, the user has built this as a slash command, but the agent has to remember to invoke it. The closest analog in existing Claude Code is the verification-before-completion superpower skill, which is the right shape but isn't enforced — it's just available.

5b. Sticky reminders / context-anchored rules

A way to mark certain CLAUDE.md sections as "high salience — re-surface this in agent context every N turns or before every code edit." Today, all of CLAUDE.md degrades in salience equally as the conversation grows. The agent can't tell that §1.1 (chokepoint headers) is more critical than §13 (env vars list).

5c. File-association rules

A way to declare in CLAUDE.md (or a separate config) "before editing any file matching src/lib/** or any file with ≥5 importers, re-read these specific instructions." The agent would resolve the rule at edit-time, with the file's content fresh in context, instead of relying on the rule being remembered from session start.

5d. Subagent invocation as default for specific operations

The user has been moving toward "always use subagents for plan execution" and "always use Opus for review." A platform extension could let CLAUDE.md declare "every git commit during a session goes through subagent X" — fresh context, full rule recall, no drift. Today this is achievable but requires the user to explicitly request the subagent every time.


6. Reproducing the failure mode

Anyone wanting to reproduce the underlying issue (agent forgets a CLAUDE.md rule it just helped write):

  1. Open a fresh Claude Code session in a non-trivial repo.
  2. Together with the agent, draft a strong CLAUDE.md rule (e.g., "every commit message ends with verified: …") and ship it.
  3. Make 3–5 unrelated changes in the same session, asking the agent to commit each one.
  4. Observe that within 5–10 commits, the rule starts being skipped intermittently — the agent doesn't verified: every commit message, doesn't update headers, etc.
  5. The drift accelerates with conversation length and with cognitive load (multi-file refactors, debugging sessions, plan execution).

The user's feedback_*.md memory entries listed in §4 are essentially a log of this failure mode across multiple sessions over weeks.


7. What this skill is NOT

To be clear about scope, /cr is:

  • Not a replacement for CLAUDE.md or system-level discipline. It's an audit gate at commit time.
  • Not a hook. Hooks block tool calls; /cr is a skill the agent invokes when the user types /cr (and per the layer-4 rule, before any session commit).
  • Not Anthropic-specific. The skill works on any Claude Code session in this repo. It's portable.
  • Not bullet-proof. If the agent skips invoking the skill (which the layer-4 rule is meant to prevent), nothing physically blocks a direct git commit. The defense is rule-shaped, not enforcement-shaped. A platform-level commit-checkpoint hook would close that last gap.

8. Open questions for Claude engineering

  1. Is the failure mode observable on your side? Does telemetry confirm that long sessions exhibit increased rule-violation rates? Does it differ across model sizes (Haiku vs Sonnet vs Opus)?
  2. Should slash commands have an "always invoke before tool X" affordance? A way to declare "before any git commit, run /cr" in CLAUDE.md, enforceable by the harness rather than relying on agent recall.
  3. Should chokepoint file detection be a first-class Claude Code feature? The user's heuristic (≥5 importers OR in manifest OR known SSOT) is generalizable. A platform-level chokepoints.toml or similar could declare files where edit-time enforcement is non-negotiable.
  4. Should hooks be repo-resident by default? The user is treating local-only hooks as a non-starter because of the multi-environment workflow. If .claude/hooks/ shipped via git like .claude/skills/ does, layer 3 could be enforcement, not discipline.
  5. Is there a context-salience API in roadmap? A way for the user to say "this rule re-surfaces every 20 turns" or "this rule re-surfaces before any Edit tool call." Today the only signal is system-prompt position.

9. What would resolve this report

In priority order:

  1. Native platform support for repo-resident pre-commit invariants that the agent itself runs (not shell-script hooks). This eliminates the need for project-specific /cr skills.
  2. Context-anchored rule re-surfacing so agent doesn't drift from CLAUDE.md mid-session.
  3. First-class chokepoint detection as a Claude Code primitive.
  4. Confirmation that the failure mode is on the platform's roadmap even if a fix is months out — so users like this one can plan their workarounds with confidence they're temporary.

If none of (1)–(3) are feasible, the /cr workaround is acceptable and the user is not blocked. But the user (and likely many others) would prefer not to re-implement this pattern in every project.


10. Reproduction kit (artifacts on disk in this repo)

For Anthropic engineers who want to inspect the workaround:

  • .claude/skills/cr/SKILL.md — the skill itself, 200 lines
  • CLAUDE.md §1.1 (lines ~190–238) — the rule the skill enforces
  • CLAUDE.md §17 — VERSION bump rules invoked at step 4
  • docs/superpowers/reviews/2026-04-26-238cfae-tier1-headers.md — first audit run output
  • docs/pending-work.md § "2026-04-26" — narrative of how this all came together
  • Commits 97f3df3 → 9477dda → 2a937be → c2e93ea8 → 4bb485c4 — the trail from "rule shipped" through "rule violated" through "skill built" through "audit completed" through "skill made mandatory"
  • feedback_file_header_discipline.md and related entries in user auto-memory — the ongoing log of similar failures across other rules

11. Status updates

Append entries below as this report evolves. Keep newest at top. Each entry: date, author, what changed, why.

2026-04-27 — /cr Step 5b "stale-test scan" added; new failure mode observed (Evan + agent)

Skill evolution:

  • /cr SKILL.md gained Step 5b — Stale-test scan between Verification (5) and Stage (6). Commit dabb836e.
  • Three search vectors prescribed before commit: (a) symbol search across test files for renamed/removed literals, (b) header-pin search to confirm contract tests track new chokepoint headers, (c) default-value search for tests silently exercising flipped defaults.
  • When found, treated as a verification failure: stop, update the test in the SAME commit, re-run the gate.

The new failure mode that triggered the addition:

Same pattern as the original report (rule in CLAUDE.md → agent reads it → agent violates it mid-session) but with a new specific shape that the existing layers didn't catch.

Timeline (2026-04-27):

  1. Coverage-gap audit (Lens 1) and recent-change review (Lens 2) ran as parallel Opus subagents. Both produced ~10 findings each — load-bearing surfaces with no contract test, security/data-flow gaps, etc.
  2. Agent worked through findings in a "Phase 5 honesty pass," shipping ~9 commits including a theme-rename: THEME_OPTIONS value "book-creator""light" (the Light Mode picker had been writing the wrong CSS theme value, activating the cream/amber book-creator palette instead of the documented neutral light theme).
  3. Agent updated theme/options.ts source. Added 9 new contract tests. Updated the e2e spec theme-switch.spec.ts to assert data-theme === "light".
  4. Agent ran tsc + eslint + 15 unit tests — all green. Committed as aeca446e.
  5. The bug: the e2e spec was previously asserting data-theme === "book-creator" (the OLD contract). Agent caught it because agent had recently authored the spec, but the general failure mode the agent didn't have a discipline for was: a test from a prior commit can silently agree with the OLD contract while production uses the NEW one. The test still passes, but asserts nothing useful.
  6. User flagged: "do we need to add to the slash cr to validate tests still valid, do they need update?"
  7. Agent built Step 5b in response, commit dabb836e.

Why the four existing layers (file headers, CLAUDE.md, /cr audit, /cr mandatory) didn't catch it on their own:

LayerWhy it missed
Layer 1 — file headersHeaders describe what a file IS, not what its consumers assume. A renamed enum value doesn't show up in the header of the file containing the enum; it shows up in tests that assert the old value.
Layer 2 — CLAUDE.md §1.1"Update header in same commit" rule didn't extend to "update test assertions that reference the renamed symbol in same commit." The discipline was scoped to chokepoint headers, not to test stalemates.
Layer 3 — /cr Verification gate (Step 5)tsc + eslint + npm test only catches broken tests. Stale tests still pass — they just assert against the wrong contract. Step 5 was blind to this.
Layer 4 — /cr is mandatoryDoesn't matter if the gate is run when the gate doesn't check the right thing.

Step 5b is the layer-3 patch. It teaches the audit to do three quick searches before commit specifically for "tests that reference renamed/removed symbols," which is the exact failure mode that bit us.

.dockerignore regression caught in the same loop: while preparing to deploy the theme fix, docker build failed with "invalid file request test-results/.last-run.json". Phase 1's Playwright shipped without updating .dockerignore, so test artifacts were getting included in the Docker context. Same commit (dabb836e) excludes playwright-report/, test-results/, and the auth/snapshot JSON files. This is itself an instance of the same class of bug — adding a new tool (Playwright) without auditing for stale assumptions in adjacent infra (Docker, CI). Worth noting that the /cr Step 5b symbol-search would not have caught the dockerignore gap; that's a different shape (new artifact directory, not renamed symbol). Possibly grist for a future Step 5c or for one of the platform features in §5.

Reproduction (for Anthropic engineers):

  1. Open a Claude Code session.
  2. Ask the agent to rename a symbol in production code (function name, enum literal, route path).
  3. Ask the agent to commit. Watch whether the agent grep's existing tests for the old name before committing.
  4. Today, the agent will sometimes catch it (if recently-touched), sometimes not. The pre-Step-5b /cr flow ran tsc/eslint/tests and committed if green — but tests asserting the old name still pass when the test value happens to equal the migrated value (e.g., the "book-creator" → "light" rename didn't break syntactically because both are valid ThemeValue variants in some intermediate state).

What this implies for the §5 platform asks:

The original report asked for "natural-language invariants" that the agent runs at well-defined moments. Step 5b is now a concrete example of one: "for each symbol you renamed/removed in this commit, grep test files for the old form and confirm none assert it." If the platform offered a way to declare invariants like this in a repo-resident hook the agent itself executes, this entire Step 5b discipline could be expressed once at the platform layer instead of being prose in a project skill that the agent must remember to follow.


2026-04-26 — initial report drafted (Evan + agent)

  • v1 of /cr skill shipped (commit 2a937be)
  • §1.1 amendment making /cr default commit path shipped (commit 4bb485c4)
  • Tier-1 chokepoint header audit merged (commit c2e93ea8 — 51 files)
  • This report initialized at .claude/skills/cr/BUG-REPORT.md for ongoing maintenance

Document maintained alongside the /cr skill. Update whenever the skill evolves, the failure mode shifts, or platform support changes.

Proposed Solution

add a change request/verify all files touched. Claude makes changes to files but does not look at effects of the changes

Alternative Solutions

No response

Priority

High - Significant impact on productivity

Feature Category

CLI commands and flags

Use Case Example

No response

Additional Context

skill created:|

name: cr description: End-of-session change-request ceremony. Audits files touched this session, enforces file-header discipline on chokepoints (CLAUDE.md §1.1), bumps VERSION when a feature/fix is complete (§17), runs verification gates (tsc/eslint/tests), then stages, commits with verified: line, and pushes. Use when the user types /cr, CR, or "change request" — runs full auto unless something needs a judgment call.

/cr — Change Request Ceremony

One command, end of session (or mid-session when a logical unit is done). User types /cr, you run all 9 steps. Auto-approve and push unless one of the push-back triggers fires.

The 9 steps

1. Audit files touched

Run git status and git diff --stat HEAD. Build the list of files actually edited this session. Ignore unstaged files you didn't touch (someone else's work, IDE cruft).

If the user has been working in multiple sessions and the working tree includes stale changes from earlier, stop and surface them — don't sweep them in.

2. Chokepoint check

A "chokepoint" file is one whose contract other files depend on. Per CLAUDE.md §1.1, the rule fires when:

  • Imported by 5+ files, OR
  • Listed in CLAUDE.md Project Context Manifest, OR
  • Single source of truth (auth, billing, dispatch, routing tunnel, NeuroMemory barrel, branding helpers, design tokens, theme options, Prisma client wrapper)

For each edited file:

  • If chokepoint → header is required (next step handles it)
  • If non-chokepoint but now imported by 5+ files → upgrade to chokepoint, add header
  • Otherwise → skip

Use grep against the import graph to verify importer counts when in doubt:

grep -rE "from [\"']@/path/to/file[\"']" src/ __tests__/ tests/ | wc -l

3. Header pass

For every chokepoint file in the edit set:

If header is missing — add one. Format (plain comment lines, labeled paragraphs):

// src/path/to/file.ts
//
// Role: [one paragraph — what this file IS, in functional terms]
//
// Callers: [list of files/route prefixes that import this; group by area]
//
// Runtime deps: [Prisma models, env vars, external services, contract assumptions]
//
// Contract tests: [paths to tests that pin this file's contract]

If header exists — read it, check whether your change made any line stale:

  • Added a new caller? Update Callers.
  • Changed Prisma field deps? Update Runtime deps.
  • Added/removed a contract test? Update Contract tests.
  • Changed the file's role? Update Role.

Stale = anything that no longer matches the import graph or the file's behavior. Update in the same commit; never park.

If a header needs a judgment call you can't resolve from imports alone (e.g., is this still the "single source of truth" if another helper now duplicates 30%?), stop and ask.

4. VERSION bump (if applicable)

Per CLAUDE.md §17, bump VERSION when:

  • A complete implementation plan is finished (all tasks done)
  • A new user-facing subsystem or capability lands
  • A major refactor that changes how the system works

Do NOT bump for:

  • Bug fixes (unless the fix IS the feature — judgment call), lint fixes, config tweaks, CI changes
  • Documentation-only updates
  • Incremental progress within an in-flight plan
  • Dependency upgrades

Process:

  1. Read current VERSION file
  2. If bumping: increment by 1, write back
  3. Add a dated Changelog entry to README.md prefixed with milestone version (e.g., ### 2026-04-26 — v19: <feature name>)
  4. Update CLAUDE.md §17 Milestone History table
  5. Update the funder timeline at docs/development-progression/timeline.json. A VERSION bump signifies a major user-facing capability shipped, which is almost always the closure of a milestone there. Look for an in-progress milestone that matches what just shipped:
    • If found: flip status to "completed", set end to today's ISO date, append the commit SHAs being shipped to commits[].
    • If no in-progress milestone matches: add a new completed milestone in the right phase with start and end set to today.
    • If genuinely unsure which milestone fits, stop and ask the user. See docs/development-progression/README.md for the schema and edit mechanics.

If the call is ambiguous (feature seems done but maybe partial, or fix is large enough to feel like a feature), stop and ask.

5. Verification gate

Run all three in parallel where possible:

npx tsc --noEmit
npx eslint src
npm test -- --run [relevant test paths]

Capture exit codes and the last few lines of output for each. If any fail:

  • Don't proceed to commit. Surface the failure to the user with the exact error.
  • Do not weaken tests, suppress lint errors, or // @ts-ignore your way past tsc. Per §1.1: "When wiring fails, fix the wiring, not the pipe."
  • After the fix, re-run verification. Only proceed when all three pass.

For docs-only or comment-only commits, skip the test step but still run tsc + eslint (they should be no-ops; the gate is fast).

5b. Stale-test scan

A passing test isn't proof of correctness — it's proof the test agreed with the code at some point. When a commit renames a symbol, removes an enum value, changes a contract claim in a chokepoint header, or flips a default, existing tests may now silently agree with the OLD contract while the production code uses the NEW one. They pass, but assert nothing useful.

The /cr discipline catches this with a quick before-commit scan:

  1. Symbol search. For every literal you renamed/removed in this commit (string literals, enum values, function names, route paths), grep across __tests__/, tests/, and tests/e2e/. Anything in a test file that references the OLD literal is a stale assertion. Update it in this same commit.

    Example, this session: renamed "book-creator""light" in THEME_OPTIONS. Stale-test scan should have caught the prior theme-switch.spec.ts assertion .toBe("book-creator") and prompted the rewrite — not just trusted that "tests still pass."

  2. Header-pin search. Chokepoint headers list "Contract tests:" pointing at specific files. If you changed a header line (Role / Callers / Runtime deps), open the named test file and confirm its assertions match the new contract. Most don't need updating — but the ones that DO won't surface as failures because they're still asserting what the OLD header said.

  3. Default-value search. If you flipped a default (a flag's default, an enum's first variant, a function's optional parameter), check tests that omit the value — they may have been silently exercising the old default and now exercise something else.

When in doubt, run npm test -- --run against the FULL suite (not just relevant paths) and watch for tests that pass but seem suspiciously fast or generic for what they claim to verify.

If the stale-test scan finds something, treat it like a verification failure: stop, update the test in the same commit as the code change, re-run the gate.

6. Stage

git add <specific files>

Never use git add -A or git add . — those sweep in .env, build artifacts, untracked files you didn't touch. Stage only what you edited.

If git status after staging shows surprises (files you didn't expect, or files missing from your edit list), stop and ask.

7. Commit

Message format:

<type>(<scope>): <short summary>

<body — explain WHY, not just WHAT, when non-obvious>

verified: tsc clean, eslint clean, N tests pass

Types: feat, fix, refactor, perf, docs, test, build, chore.

The verified: line is mandatory. Pull the test count from your verification step. For docs-only: verified: docs-only — no code change.

Pass the message via heredoc:

git commit -m "$(cat <<'EOF'
feat(cr): add /cr end-of-session ceremony skill

verified: tsc clean, eslint clean, 209 tests pass
EOF
)"

8. Push

git push

To the current branch (don't switch branches, don't force-push).

If push fails (e.g., remote has new commits), stop and ask — don't auto-rebase or force.

9. Report

Tell the user:

  • Files committed (count + list if short, summary if long)
  • Verification results (tsc clean, eslint clean, N tests pass)
  • VERSION bump (if any) — old → new + milestone description
  • Commit SHA + push result

One paragraph. Keep it tight.

Push-back triggers — STOP and ask

The user said "auto-approve unless you see a problem." These are the problems:

TriggerWhy stop
Verification fails (tsc, eslint, or any test)Don't ship broken code
Chokepoint header needs a judgment call (file's role changed, new helper duplicates this one, etc.)Wrong header is worse than no header
VERSION bump ambiguous (feature done? or partial? fix big enough to count?)Wrong bump pollutes the changelog
Staged set has surprises (.env, build artifacts, files outside your edit list)Could leak secrets or unrelated work
Diff looks larger than the session warrantsStale changes from earlier session may have crept in
Push fails (remote ahead, auth error, etc.)Don't auto-rebase — user decides
Working tree had unstaged changes you didn't make this sessionDon't sweep in someone else's WIP

In any of these cases: stop, surface the issue with specifics, wait for user direction. Never silently work around a trigger.

When to invoke /cr

  • End of session — the canonical use. User types /cr once before signing off.
  • Mid-session at a logical break — when one feature/fix is fully done and the next one is a different surface area.
  • Don't invoke when work is half-done, when verification is known to fail, or when the user is mid-thought.

The skill assumes the work is finished. If it isn't, finish first.

Portability

This skill is project-scoped (.claude/skills/cr/) so it travels with the repo. It works the same in:

  • Windows local (V:\websites\GrokWebHelp)
  • code-server (/workspace/websites/GrokWebHelp)
  • claude.ai cloud agent (whatever clone path it uses)

Path translation per CLAUDE.md §20 — but the verbs are the same everywhere.

Notes

  • This skill replaces the manual "audit, header, verify, stage, commit, push" sequence the user was running by hand. Don't re-explain the steps each time — just execute.
  • The verified: line discipline is from CLAUDE.md §1.1. It's not optional. If you can't write it, you can't commit.
  • The header-update-in-same-commit discipline is from CLAUDE.md §1.1. Stale headers are bugs; don't open a separate "doc commit."

extent analysis

TL;DR

The most likely fix for the issue is to implement a pre-commit hook that checks for compliance with the rules defined in CLAUDE.md, specifically the file-header discipline, and runs the /cr skill to ensure all files touched in the session are properly audited and updated.

Guidance

  1. Implement a pre-commit hook: Create a hook that runs before every commit, checking for compliance with the rules defined in CLAUDE.md, such as the file-header discipline.
  2. Run the /cr skill: Integrate the /cr skill into the pre-commit hook to ensure all files touched in the session are properly audited and updated.
  3. Verify the hook's effectiveness: Test the pre-commit hook to ensure it correctly identifies and prevents non-compliant commits.
  4. Consider platform-level support: Explore the possibility of implementing platform-level support for pre-commit invariants, as suggested in the issue report, to eliminate the need for project-specific workarounds.

Example

# Example pre-commit hook
#!/bin/sh

# Run the /cr skill
/cr

# Check for compliance with CLAUDE.md rules
if [ -n "$(git diff --name-only | grep -v '^src/')" ]; then
  echo "Error: Non-src files modified. Please update the /cr skill to handle this case."
  exit 1
fi

Notes

  • The implementation of the pre-commit hook will depend on the specific requirements and constraints of the project.
  • The /cr skill should be updated to handle cases where non-src files are modified.
  • Platform-level support for pre-commit invariants may require collaboration with the Claude Code team.

Recommendation

Apply the workaround by implementing a pre-commit hook that runs the /cr skill and checks for compliance with the rules defined in CLAUDE.md. This will help ensure that all files touched in the session are properly aud

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING