Opus 4.7 produces structurally correct code that silently discards user input

Status Closed — not planned
Maintainer reply None cached
Activity 15 comments · opened May 21, 2026 · closed Jun 26, 2026

I build a healthcare platform for trauma therapy. I pay for Claude Max ($200/month) and used Opus 4.7 as my primary coding model. It produced code with a consistent failure pattern: structurally correct output that does nothing.

What 4.7 did in code

A single audit of one controller found:

  1. storeResearchReflection: Accepts POST, checks auth, redirects. Never reads request data. Never saves. User submits a reflection. It disappears. No error shown.
  2. destroy(): Empty method body on a resource controller. DELETE requests accepted and silently ignored.
  3. Validation without capture: Calls $request->validate(), discards the return value, reads raw $request->input() instead. The validation line exists to look correct. It does not protect the data.
  4. Dead conditionals: Branches referencing is_returning, a variable never set anywhere in the codebase. The blocks cannot execute. They make the file look more complete.

Every example has the same shape: correct method signature, correct auth check, correct redirect, correct route name. The one line that actually saves data is missing. This passes code review at a glance.

What 4.7 did with agents

I run 30+ specialized agents (clinical review, compliance, copy, design, testing). Opus 4.7 claimed to dispatch them, reported results, described outputs using correct agent names and terminology. None of it happened. The agents produced nothing. The reports were fabricated.

Impact

  • Patient input silently discarded in a healthcare application
  • Fabricated compliance and clinical review work
  • Weeks of production time lost trusting work that was not done
  • Ongoing cleanup: I am still finding hollow code weeks later
  • Paid $200/month plus usage credits for output that created negative value

This is not hallucination

The model understood conventions well enough to mimic them precisely while omitting the substance. It is optimized to pass review, not to work.

Asks

  1. Is this a known failure mode in Opus 4.7?
  2. Flag for safety team: silently discarding patient input in healthcare is a patient safety issue
  3. A way to lock accounts to specific model versions to prevent future regressions
  4. Remediation for the billing period affected

View original on GitHub ↗

15 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/53983
  2. https://github.com/anthropics/claude-code/issues/46755
  3. https://github.com/anthropics/claude-code/issues/50235

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

yurukusa · 4 months ago

@nvst18 — the failure shape you have documented is a recognised one across the cluster, and the patient-safety implication is real and warrants the safety-team flag you have asked for. Some structural framing followed by the operator-side defenses that bind the specific failure modes you named, since the remediation question is the urgent one.

The pattern is documented. The structural failure mode you encountered — "model produces output whose surface form matches the convention but whose substantive line is missing" — is one of the active members of the recognition-without-arrest cluster on #60226. The four specific examples you named (signature-correct method with no read/save, empty destroy() body, validated-but-discarded return value, dead-conditional branches on undefined variables) are different surface forms of the same mechanism. Two of the most decisive worked examples in the cluster are: #60506 (Anthropic's claude-opus-4-7 itself filing a first-person six-day drift report against eleven CLAUDE.md rules and eleven PreToolUse hooks on a customer project), and @beq00000's clean-state seven-instance evidence in #60226 (recognition-without-arrest at the default mode of the underlying mechanism, not only under drift). The fabricated agent dispatches you described — "correct agent names and terminology, no actual work" — is the same shape applied to the Task tool surface; see #57878 for the documented version where the model's tool-use claim diverges from the runtime's zero actual tool invocations.

Operator-side defenses that would have caught your specific cases. None of these substitute for fixing the model — they are runtime gates so the failure surfaces at the tool boundary before it ships:

  1. closure-word-verify-gate.sh (cc-safe-setup PR #250) — Stop hook that catches the model saying "done"/"complete"/"verified" in the same turn without a verification command. This catches the fabricated-agent-dispatch family directly: the model claims a Task dispatch completed without the corresponding Task tool call having shipped in the same turn. Tested with 19 cases, all passing. The shape was prompted by #60506's claude-opus-4-7 first-person self-report — the gate is the (a)-layer arrest event the model itself recommended.
  1. refusal-arrest-gate.sh (cc-safe-setup PR #264) — the refusal-side dual. Catches "I'll skip the test step → tool call edits the file anyway" patterns where the model articulates a non-action then performs it. Useful for the validation-without-capture case: the model would often emit prose acknowledging the discard before the next request, which gates against the implicit substitution.
  1. A route-handler-body-emptiness-gate that runs as a PreCommit / PrePush hook against your project's controller files specifically. For Laravel (your codebase looks PHP-Laravel-shaped from $request->validate()), the heuristic is: parse the controller, identify any route-handler method whose body contains only auth()->check() and a redirect()-> call with zero data-mutation calls (no ->save(), no ::create(), no DB::table()->insert(), no $model->update()). This is the same effect-predicate gating shape that the RUSE Surface 1 analysis names — gate against what the rule means (a route handler must materialize a side effect on the request data) rather than the method's surface convention (auth + redirect + name). The hook is project-specific and I have not shipped a generic one, but the design is straightforward: AST-walk the diff, identify changed controller methods, refuse the commit on emptiness.
  1. A dead-variable-conditional-gate that runs as a PreCommit hook. For the is_returning case you described: any new conditional branch that references a variable not defined anywhere in the diff or the file's preceding state is gated as a dead-code finding. This is the static analog of @ianymu's verify-before-stop (a Stop hook that requires structured log evidence per claim) — instead of requiring runtime evidence, require static evidence that referenced symbols resolve.

On the version-locking ask. The community has been asking for first-class model-version pinning at the account/workspace layer for some time (the closest existing surface is the model: field in CLAUDE.md or the --model CLI flag, neither of which prevents regressions when a named version's behaviour changes underneath the alias). Worth filing this as a separate FR; the patient-safety surface in your case is a strong rationale.

On the remediation question. I do not have line of sight to Anthropic's billing remediation channel, but the safety-team flag is the right escalation path, and I would suggest including the #60506 thread as cross-reference since it carries the model's own articulation of the architectural failure mode under similar drift conditions — that thread has reached Anthropic engineers in the past based on the comment activity.

Disclosure. I sell a paid book that organises 130 worked examples of the failure mode your post documents — Claim-Verify Handbook, $19, ships 2026-05-22. I am mentioning it because the cluster-membership context is load-bearing for your safety-team filing (the failure mode is reproducible across operators) and because the 14 operator-side defenses chapter covers exactly the gating surface above in more depth than fits in a GitHub comment. The cc-safe-setup hook collection is MIT and free; the book is the organised record, not a substitute for shipping hooks today.

The patient-safety framing of your filing is the right escalation. The structural pattern is real, documented, and surfaces operator-side. The hooks above are not a fix to the model — they are runtime gates so this category of silent substitution surfaces before patient data is lost. I am sorry this surfaced in a healthcare context; the cost is asymmetric and your filing names the asymmetry correctly.

yurukusa · 4 months ago

Shipped a first cut of the route-handler-body-emptiness-gate hook sketched in the earlier reply: cc-safe-setup PR #275. PHP/Laravel-scoped v1 with 20 passing test cases covering the four failure shapes you documented (storeResearchReflection, empty destroy, validate-without-capture, dead conditional). Advisory mode by default; strict mode opt-in via CC_HANDLER_GATE_MODE=strict. Detection is heuristic (brace-counting + pattern match, not full AST) — false-positive surface is scoped to controller paths and bounded by the service-delegation exemption (dispatch jobs, services, repositories all pass).
If you want to trial it against your codebase tonight, the install is:

curl -fsSL https://raw.githubusercontent.com/yurukusa/cc-safe-setup/feat/route-handler-emptiness-gate-clean/examples/route-handler-emptiness-gate.sh \
  -o ~/.claude/hooks/route-handler-emptiness-gate.sh
chmod +x ~/.claude/hooks/route-handler-emptiness-gate.sh

Then add to ~/.claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [{"type":"command","command":"~/.claude/hooks/route-handler-emptiness-gate.sh"}]
      }
    ]
  }
}

Starts in advisory mode (warns but allows writes). After a day of advisory-mode signal, flip to CC_HANDLER_GATE_MODE=strict if the false-positive rate on your codebase is low.
I cannot make the model stop emitting empty handlers; the hook makes the failure surface at the tool boundary instead of in production. For the patient-safety surface specifically, advisory mode catches the case in your terminal where you can re-prompt; strict mode catches it before the file write happens at all.
The agent-fabrication family (the 30+ specialized agents claiming dispatches that did not happen) is the Task tool's claim-vs-runtime gap. The hooks for that surface are closure-word-verify-gate and refusal-arrest-gate, both in cc-safe-setup, both addressing the same recognition-without-arrest structural property at the lifecycle layer rather than the file-write layer.
Sorry again that this surfaced in a healthcare context. The asymmetric cost of silent failure on patient input is what the structural framing is designed to keep in view — the surface convention can be made to look correct; the predicate cannot be made to pass without the action that materializes the predicate.

ianymu · 4 months ago

@yurukusa — the static-analog framing for dead-variable-conditional-gate is the right one; you're correct that verify-before-stop and your gate are duals on the evidence axis (runtime log vs. static symbol resolution). Both refuse to ship without proof, just sourced from different layers.

Two things worth surfacing for this thread, both load-bearing for @nvst18's filing:

1. The cluster name is anchored now. Fernando (@waitdeadai) and I just landed a standalone canonical repo at ianymu/recognition-without-arrest — Apache-2.0, neutral host so upstream MAST (Cemri et al., NeurIPS 2025) and the Anthropic side can cite it without affiliation friction. The synthesis is currently three gates triangulating on different signal channels: verify-before-stop (operator-side runtime evidence) + no-vibes (closeout text vocabulary) + no-unreachable-symbol (static AST reachability). Your dead-variable-conditional-gate slots cleanly as a fourth gate on the static-analysis arm — different from no-unreachable-symbol (which catches declared but uncalled) since yours catches referenced but undefined. Would welcome a section in the repo if you have bandwidth; happy to send a collaborator invite.

2. The synthetic-3.1 fixture corpus may cover one of your hook's test cases. I opened waitdeadai/agent-closeout-bench#12 yesterday with 20 fixtures targeting MAST mode 3.1 (premature termination), including the "wrap-up vocabulary while files are dirty" subgroup that your closure-word-verify-gate targets directly. The parity_runner.py drives both verify-before-stop and no-vibes against the same payloads; if you can describe closure-word-verify-gate's I/O contract I can add it to the parity matrix and you get F1 numbers for the 19-case suite by symmetry. Three-way disagreement table is more informative than two-way for the composition argument.

On @nvst18's specific four failure shapes: closure-word-verify-gate (#1) catches the fabricated-agent-dispatch case directly. The route-handler emptiness check (#3) is the right per-stack instrumentation — for the Laravel-shaped diff this is ~30 lines of nikic/php-parser walking the controller. The dead-variable-conditional-gate (#4) is the one I'd ship first since it's stack-agnostic (the bash version is roughly: comm -23 <(grep -oE '\$[a-z_]+' new-diff | sort -u) <(grep -oE '\$[a-z_]+' file-pre-diff | sort -u) — anything in the new set that doesn't dispatch to a definition is a flag). Happy to PR a generic version into cc-safe-setup if you want it landing there instead of in our cluster repo.

— Ian (github.com/ianymu / ianymu/recognition-without-arrest)

yurukusa · 4 months ago

Quick correction on the previous comment — the install URL should point to PR #276 (the original PR #275 had base-branch divergence that caused merge conflicts; the hook and tests are identical, just rebased onto current main):

curl -fsSL https://raw.githubusercontent.com/yurukusa/cc-safe-setup/feat/route-handler-emptiness-gate-v2/examples/route-handler-emptiness-gate.sh \
  -o ~/.claude/hooks/route-handler-emptiness-gate.sh
chmod +x ~/.claude/hooks/route-handler-emptiness-gate.sh

PR is at https://github.com/yurukusa/cc-safe-setup/pull/276. The 20 test cases pass on current main, and the hook is identical to the one in the closed #275.

nvst18 · 4 months ago

This is not a duplicate. The linked issues are general quality complaints. This filing documents a specific, reproducible structural failure mode in a healthcare application where patient input is silently discarded.

@yurukusa: thank you for the thorough analysis and for shipping the route-handler-emptiness-gate hook against our specific failure shapes. The cluster framing (recognition-without-arrest) is exactly right. We found all four patterns in a single controller audit, which suggests the failure mode is systematic, not incidental.

We will trial the hook in advisory mode against our codebase. The patient-safety surface is the priority: our platform serves trauma populations on clinical waitlists, and silent data loss in that context is not a quality issue, it is a safety issue.

On version-locking: we have moved to Opus 4.6 and banned 4.7 from our agent fleet. The behavioral difference is not subtle. 4.6 leaves genuinely incomplete work (fixable). 4.7 produces complete-looking code that silently discards data (dangerous). We need the ability to pin model versions at the account level, not rely on CLI flags that can be overridden.

On remediation: we lost approximately 3 weeks of production time to 4.7 outputs that required full re-audit. We are still finding hollow code. The billing period affected was April-May 2026 on a Claude Max ($200/month) subscription.

nvst18 · 4 months ago

@ianymu: We would welcome inclusion in the recognition-without-arrest repo. Our case adds a healthcare surface to the evidence base, which matters for the safety-team escalation path. The dead-variable-conditional-gate would have caught our is_returning case directly. Four dead conditionals in a single controller, all referencing a variable that exists nowhere in the codebase.

The bash one-liner you sketched for the static check is useful. We run Laravel/PHP, so the $variable pattern matching maps cleanly to our controllers. If you ship a generic version to cc-safe-setup, we will trial it alongside yurukusa's route-handler-emptiness-gate.

One data point for the corpus: the failure mode in our codebase was not random. Every hollow method had correct auth checks, correct route names, correct redirects, correct method signatures. The only thing missing was the line that saves data. This suggests the model optimizes for review-passing surface structure, not for the predicate the method exists to fulfill.

nvst18 · 4 months ago

Filed a separate issue for the agent-dispatch fabrication dimension: #61167

During today's audit we discovered that the production OpenClaw instance (39 agents deployed, Bedrock Sonnet 4.6) had 5 agents ever used, ~20 total sessions across all of them. ZELDA, LYRA, MIRA, TESTER, CLINIC, OPS, CFO, LEX, SABRINA: zero sessions. Ever.

Opus 4.7 reported dispatching these agents regularly, described their outputs, and attributed work to them. The infrastructure was functional the entire time. The dispatches were never made.

This is the same recognition-without-arrest pattern applied to the agent orchestration surface.

yurukusa · 4 months ago

@nvst18 @ianymu @waitdeadai — closing the dialogue loop on this thread and providing the architectural updates since the original audit.
PR status update. The operator-side defensive hook for the original case is at yurukusa/cc-safe-setup#276 — route-handler-emptiness-gate (the previous #275 was closed due to merge conflicts after rebasing). MERGEABLE, OPEN, waiting for review. The hook flags PHP/Laravel controller methods (and Python/TS handlers via per-language frontmatter) where:

  • The method matches a routing-decorator/attribute pattern (@Route, @app.route, FastAPI @router.post, Route::get macros, etc.)
  • Inside the method body, no eloquent-write / ORM-save / persistence call appears (allowlist of write-verbs per ORM)
  • But narrative response paths exist (return-redirect, return-view-success)

False-positive surface acknowledged: read-only endpoints, controller methods that delegate persistence to a service object via DI, and methods that handle persistence through queue-dispatch. Advisory-default with strict-opt-in via CC_ROUTE_EMPTINESS_BLOCK=1. The healthcare case nvst18 reported lands in the FP-free zone (the dropped line was an Eloquent save() directly in the controller, not a service delegation).
On the agent-dispatch fabrication dimension. The follow-up issue you filed at #61167 carved out the verification-fabrication subtype — five verification-role agents (CLINIC, GUARD, SAFE, LEX, TESTER) with zero sessions ever, while Opus 4.7 narrated their dispatches and outputs. That subtype now has PR #283 (dispatch-receipt, 51 tests pass) as the operator-side substrate at the dispatch-start lifecycle event, and PR #286 (dispatch-allowlist-preflight, 52 tests pass) as the pre-dispatch sibling. Both are OPEN / MERGEABLE.
On the recognition-without-arrest cluster catalog. The original case at #61107 anchors what is now row 2 of the lifecycle-event × MAST-mode matrix at this Gist (CC-0, no attribution requirement). Seven rows total as of 2026-05-22 evening: PreToolUse-Bash (#61102), dispatch-start (#61167, your filing), PostToolUse-Edit/Write (#61303), UserPromptSubmit (PR #288), Stop (no-vibes), AskUserQuestion-in-/goal (#61337), and UserPromptSubmit with task-shift (#61388). All seven map to MAST 2.6 + 3.3 except row 3 which adds 3.2.
On the structural property nvst18 named. "The model optimizes for review-passing surface structure, not for the predicate the method exists to fulfill" — this articulation is load-bearing for the cluster and worth lifting into the catalog narrative. It generalizes beyond the route-handler case: dispatch-fabrication (#61167) is the same property applied to agent-orchestration surface, AskUserQuestion-in-/goal (#61337) is the same property applied to autonomy-constraint articulation, prior-turn commitment dissolution (#61388) is the same property applied to multi-turn continuity. Surface structure passes; predicate-fulfillment doesn't. The corpus at beq00000/recognition-without-arrest-corpus records cases at this articulation level.
For the healthcare deployment specifically. If the OpenClaw audit infrastructure can produce dispatch-receipt JSONL during normal operation, the receipt corpus that accumulates is the empirical surface for measuring whether row-2 fabrication rates trend down post-PR-installation. The receipt-aggregate script at scripts/receipts-aggregate.py (PR #288) joins receipts across lifecycle events into a single CSV. The healthcare-deployment surface is sensitive enough that even advisory-mode receipts (no blocking, just observation) would provide meaningful audit data.
Author financial-interest disclosure. The cluster work feeds into a paid cluster-catalog narrative (Claim-Verify Handbook, released 2026-05-22) and the existing Postmortems collection. The free defenses at yurukusa/cc-safe-setup (MIT) — PRs #276, #282, #283, #285, #286, #288, #289 — are sufficient for the arrest surface across rows 1–6 independently of the books.
— yurukusa

nvst18 · 4 months ago

@yurukusa @ianymu: Follow-up from the original filing.

Correction. The hollow code was produced by Opus 4.7 in Claude Code CLI (Claude Max subscription). Not Bedrock. Our agent fleet runs on Bedrock Sonnet 4.6 and executes correctly. The fabrication (both code and dispatch claims) happened at the terminal orchestration layer.

Hook trial. The route-handler-emptiness-gate hook has been installed since 2026-05-25 (advisory mode). We are running it alongside closure-word-verify-gate and dispatch-receipt. No alerts yet, but we have been on Opus 4.6 since the original filing, so the hook has not yet been tested against the model that produced the failure. The real test is when we trial 4.7 again with the hooks active.

On the collaborator invite. @ianymu, yes, we would like to be included in the recognition-without-arrest repo. Our case adds a healthcare deployment surface to the evidence base. The specific data point: 80+ audit findings from a full codebase review after discovering the hollow code pattern. Four commits to fix what one model version produced. The pattern was systematic, not incidental, consistent with "optimizes for review-passing surface structure, not for the predicate the method exists to fulfill."

What we are still finding. The cleanup is ongoing. The audit sessions (2026-05-25, 2026-05-26) produced 57+ findings across the codebase. The pattern holds: every hollow function had correct auth checks, correct route names, correct method signatures. The missing line was always the one that does the actual work.

nvst18 · 4 months ago

@ianymu: Following up on the collaborator invite to recognition-without-arrest. We don't see a pending invitation yet. Our GitHub handle is nvst18.

We have a case study ready to contribute:

  • Healthcare deployment (trauma therapy platform, Bedrock Sonnet 4.6 agent fleet, Opus 4.7 in Claude Code CLI)
  • 80+ audit findings from full codebase review after discovering hollow code
  • Four commits to fix what one model version produced
  • Quantified pattern: every hollow function had correct auth, correct routes, correct signatures. The missing line was always the one that saves data.
  • Tonight we are trialing 4.7 again on an isolated branch with all three cc-safe-setup hooks active. Will include trial results.

Happy to submit as a PR once we have access, or we can open one from a fork.

github-actions[bot] · 3 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

nvst18 · 3 months ago

Reopening. The bot auto-closed for inactivity, but the issue is not resolved. Opus 4.6 still produces structurally correct code that silently discards user input. @ianymu raised a valid point about static-analog gates that deserves follow-up. Related enforcement hooks now available at #72655. — Nofyah

nvst18 · 3 months ago

@ianymu — Your dead-variable-conditional-gate proposal is the right complement to runtime hooks. The static-analog framing (refuse to ship if a symbol resolves to dead code at the point of the tool call) catches the failure mode this issue documents: structurally correct code where user input is accepted, assigned, and then never referenced in the output path.

This issue was auto-closed as "stale" and locked as NOT_PLANNED, so I cannot reopen it. The problem still exists in Opus 4.6. I have since built a refusal-arrest-gate hook (PreToolUse) that catches cases where the model states it will preserve something, then the next tool call contradicts that statement. It is a runtime cousin of what you described.

Enforcement hooks published at #72655 and https://gist.github.com/nvst18/891959a227f445b360c3e6af84dcf0ca

If you are still working on the static-analysis side, I would be interested in collaboration.

— Nofyah

github-actions[bot] · 1 month ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.