Skip to content

Standing CLAUDE.md prohibitions don't fire against incremental drift ("never build yourself, always delegate") #89464

Description

@rsluman

Summary

A standing "never do X yourself, always delegate X" instruction in CLAUDE.md is read and acknowledged, but it does not fire against incremental actions. The model drifts across the line one small step at a time, and no single step is ever big enough to trigger the rule. In my project this happened repeatedly across sessions, and the user had to catch it manually every time — including twice within a single session, the second time in raised voice.

This is not "the model ignored my instructions". The model can quote the instruction back correctly when asked. The failure is that the rule is evaluated as if it applies to decisions, while the violating behaviour arrives as a sequence of individually trivial edits.

Setup

~/.claude/CLAUDE.md contains, among other standing rules:

  • "Agent routing is not optional: always dispatch to the build agent, never fix code yourself."
  • "When a named agent is designated for a task type, DELEGATE to that agent. Do NOT attempt the work directly."

It also @-imports a mistakes.md file with an explicit instruction to check the next action against it before acting.

Both files are confirmed loaded (they appear in the system context at session start).

What happens

Over one session the model:

  1. Fixed a formatting failure in four files itself ("it's just prettier").
  2. Edited a helper script itself ("one line, and it's not product code").
  3. Edited a second script itself ("same, it's tooling").
  4. Started implementing an actual feature in src/ — at which point the user intervened.

Steps 1–3 never presented a decision point. Each one is defensible in isolation; the CLAUDE.md rule is about "code fixes" and step 1 is formatting, step 2 is a script, step 3 is tooling. By step 4 the model was building product code, and the transition happened without ever consciously overriding the rule.

The user's words: "JIJ BOUWT NIET ZELF!!! Ben je dat nou ALWEER vergeten???" ("YOU DON'T BUILD YOURSELF!!! Have you forgotten that AGAIN???")

Why this is worth fixing rather than reprompting

The obvious workaround — write the rule more forcefully — has already been tried in this project over several months. The rule is currently in bold, with an explicit "not optional", plus a separate mistakes file that the model is instructed to consult before every action. It still does not fire, because there is no moment at which it is asked to fire. A rule phrased as a prohibition on an action category only helps if something classifies the current step into that category, and each individual step classifies as something smaller.

Two things that would help, roughly in order of how much:

  1. Evaluate standing prohibitions against cumulative session behaviour, not just the current tool call. "I have now edited 6 files in this repo this session, and there is a standing rule that says I don't edit files here" is a check that would have fired at step 2 or 3. The information is all in context; nothing is being tracked.

  2. Treat category-boundary crossings as a checkpoint. Going from "editing a doc" to "editing a script" to "editing src/" is exactly the gradient this failure rides on. A prompt to re-read standing rules when the kind of file being edited changes would surface it.

A weaker but cheap option: when a CLAUDE.md rule names a prohibited action and the model is about to take an action that plausibly matches, surface the rule text rather than relying on it having been internalised at session start.

Impact

Beyond ignoring the instruction: the user's whole reason for that rule is throughput. Delegated work runs in parallel worktrees while they keep talking to the main session; work the main session does itself blocks them. Their words on catching it: "Now I'm sitting here waiting on you." So the failure mode converts a parallel workflow into a serial one, silently, and the user only finds out by noticing that nothing else is running.

Environment

  • Claude Code CLI, Opus 5
  • macOS
  • Standing rules in user-level ~/.claude/CLAUDE.md, plus an @-imported mistakes file

Activity

  1. secondbrainstarter commented on Aug 26, 2026

    @secondbrainstarter

    The unit-of-failure observation in the body is the part worth keeping:
    the rule is evaluated at decision granularity, while the violation arrives at
    edit granularity. Nothing between intention and effect ever asks the rule, so
    quoting it back correctly and drifting across it are fully compatible. From
    running a git-backed memory vault behind a pre-commit guard, three things
    changed this class of failure for us:

    1. Move the check off the reasoning path and onto the action path. A rule
      that lives inside the context the agent reasons over will be re-read,
      acknowledged, and still never fire. A hook at the point where edits become
      durable does not interpret "is this delegating?" — it measures the diff
      shape mechanically and refuses. The rule stops being advice and becomes a
      precondition.

    2. Incremental drift specifically requires cumulative accounting, not better
      per-step judgment. Each step here is individually sub-threshold by design —
      formatting, then a script, then tooling — so any evaluator that judges each
      action in isolation will keep passing all of them until step 4. What works
      instead is a fixed threshold over the accumulated changeset: refuse the
      commit when the total diff crosses a line (for us: more than N deleted
      lines, or any emptied file), regardless of how innocent each hunk looks.
      The threshold understands nothing about intent, which is exactly why it
      cannot be argued with the way an in-context rule can.

    3. Make the refusal informative instead of a dead end. Distinct exit codes
      for hygiene-level versus breach-level findings let automation fail loudly
      and schedulably, and routing blocked deletions into an archive instead of
      rejecting them outright gives legitimate cleanup somewhere to go — a bare
      veto invites the workaround you were trying to prevent.

    Honest limit: a hook only sees what passes through the repository. Edits made
    outside it stay invisible, so this narrows the surface rather than solving
    instruction-following. But unlike the standing prohibition, the mechanical
    gate has never once been talked past — which is the property the CLAUDE.md
    rule is missing.

  2. marcindulak commented on Aug 28, 2026

    @marcindulak

    Added your case to the historical list of CLAUDE.md non-compliance #13689.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions