Skip to content

fix(claude): preserve native requests with workload markers - #28

Merged
mergify[bot] merged 1 commit into
mainfrom
HOUSE-97-lane
Oct 30, 2026
Merged

mergify[bot] merged 1 commit into
mainfrom
HOUSE-97-lane

Conversation

@ericlitman

@ericlitman ericlitman commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Claude Code appends workload/cron to scheduled requests. The native detector rejected that valid suffix, so scheduled turns took the cloaking path and changed the cached prompt prefix.

 ordinary native request → preserve caller prompt and cache controls
-workload-marked request → cloak and rewrite prompt
+workload-marked request → preserve caller prompt and cache controls

Accept one optional final workload/[a-z0-9_-]+ segment. Existing version, entrypoint and strong-signal checks remain in place. No executor payload or routing policy changes.

Linear: HOUSE-97
Related: HOUSE-96 (deployment and observations), HOUSE-98 (explicit client cache TTL).

Introduced by: router-for-me/CLIProxyAPI#4752

Evidence

  • Before: the new TestClaudeNativeWorkloadMarkerKeepsOutboundPrefixIdentical fails in all four cases with production source restored to ed0d889f41c7a63e2545cc0b814e5c3d536b2dd7: streaming/nonstreaming × bare/explicit-one-hour cache controls. Workload-marked calls rewrite the system, messages and tools.
    After: all four cases pass on ca7a762078a3f84ebedfa29b29b008033e02edbd. Ordinary → cron → ordinary calls keep identical outbound system content and preserve incoming messages, tools, cache controls and User-Agent, using the same synthetic account/session and mocked HTTP transport.
  • Detector tables cover CLI, SDK and VS Code forms, count-tokens detection, and malformed, old-version and non-native counterexamples.
  • Rerun: go test ./internal/runtime/executor -run TestClaudeNativeWorkloadMarkerKeepsOutboundPrefixIdentical -v and go test ./internal/runtime/executor/helps -run 'TestDetectClaudeCode'.
  • Faithful local wire proof, not an Anthropic live result. The committed tests contain the complete reproduction. Full logs are retained in the HOUSE-96 batch record.

Merge Danger

Door: two-way

Revert the parser change to restore prior classification. No migration or persistent-data change.

Blast Radius: Claude

Workload-marked native Claude requests now retain their native prompt and identity. Apply explicit client main-conversation TTL settings before deployment: fixing classification removes the old cloaking path's automatic one-hour upgrade. Correct SDK identity may have different upstream quota metering; this change makes no quota-savings claim.

Device-profile stabilization is disabled in the target deployment (also the default). If enabled elsewhere, accepting a workload-marked User-Agent can make it eligible for the existing learned profile; that optional-mode interaction is recorded as an unacted advisory. client-app/ remains outside the accepted shape because the observed client does not emit it.

Acceptance criteria

Recheck the reproduction on current main and trace the native classification, detail parsing and relevant executor paths; fix the actual valid-marker handling without weakening unrelated native-client validation or altering intentional cloaking configuration.

Done: the shared plausibility regex is the failing boundary. Detail extraction already works. Streaming, nonstreaming and token-count paths use that boundary. Other signals and configured cloak behavior are unchanged.

A regression proof fails on the unchanged base and passes on the fix: ordinary and workload-marked native requests preserve the same semantic system prefix and requested cache controls, with the same account/session. Cover valid Agent SDK and CLI forms plus malformed/non-native counterexamples at the relevant decision boundary.

Done: the wire regression and detector tables described above. Explicit one-hour TTL preservation is included. Token counting is proved at the detector boundary, not through a separate executor wire test.

Run repository-required build/tests on the committed candidate; obtain required CI and Unfret review and merge through Mergify.

Local gate complete as recorded below; CI, Unfret and Mergify pending at PR creation.

Release the merged change and deploy once to studio2, preserving config/auth and previous binary for rollback. Prove deployed version/commit, successful real requests and continued normal routing; confirm scheduled/native behavior with a bounded live or faithful local wire proof and distinguish these evidence types.

Post-merge release/deployment is owned by HOUSE-96/HOUSE-97 and remains pending. Local scheduled/native proof is complete. Client TTL configuration and four-host live TTL probes are complete under HOUSE-98.

Gate results

Parent-run gate on committed ca7a762078a3f84ebedfa29b29b008033e02edbd:

  • git diff --check origin/main...HEAD: exit 0.
  • gofmt -l on all three changed Go files: empty output, exit 0.
  • go build -o test-output ./cmd/server: exit 0; temporary binary removed.
  • go test ./...: exit 0.
  • Candidate SHA and clean working tree rechecked after the gate.
  • Fresh no-comments pass: no scoped comments/suppressions, no edits, no unenforced constraints.

Not verified

  • Deployment, released binary and post-deployment Anthropic requests await merge.
  • Two one-hour workload observations await deployment and immediate testing.
  • Subscription quota savings are not established by token-cache tests.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@unfret

unfret Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

✅ Accepted risk

Accepted by ericlitman: HOUSE-97 (authority 48fa77b)

🟡 Medium · Workload-tagged UA can be pinned as the stabilized device profile

Details

Run: GET /unfret/run/panel:ca7a762078a3f84ebedfa29b29b008033e02edbd:kMFJtKoM9o5:WKHPQXyP4Ps.

@unfret review · @unfret status · @unfret help

@unfret unfret 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.

🛑 1 blocking finding
🟡 Medium · Workload-tagged UA can be pinned as the stabilized device profile
Check

@ericlitman

Copy link
Copy Markdown
Contributor Author

Confirmed finding: workload-tagged User-Agent can be retained by the optional device-profile stabilization cache and replayed on ordinary requests.

Disposition: pre-accepted, not fixed. This deployment does not enable stabilization: stabilize-device-profile is absent in the live configuration, and ClaudeDeviceProfileStabilizationEnabled returns false when its pointer is nil (internal/runtime/executor/helps/claude_device_profile.go:107-111). The default is also false. Native requests therefore keep their incoming User-Agent; the learned-profile path is not used by this installation.

The finding is valid for the enabled configuration. No claim is made that all supported configurations are unaffected. The demonstrated consequence is request workload mislabeling in that optional mode; no security, secret exposure, data loss or gate-integrity consequence was identified. The invoked run-these/babysit-pr standing reachability policy pre-accepts confirmed findings whose trigger lies outside actual usage and lacks those excluded consequences. This is the operator's application of that policy, not new approval attributed to Eric.

Exact head: ca7a762.
Finding: v1:7a31c7fe06d7cd9c31defc8bf59e3faabb263a2c1b13c124a0932bc1cc5f8927.
Related issue: HOUSE-97. No additional repair ticket is filed because no work on the disabled mode is chosen.

@mergify
mergify Bot merged commit 148e2d8 into main Oct 30, 2026
9 checks passed
@mergify

mergify Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

✅ Merged into main as 148e2d8 at 08:45 UTC

Less than a minute in the queue, with no time running CI.

So far

  • ✅ Entered the queue Fri 30 Oct, 08:45 · rule default · triggered by merge protections
  • ✅ Checks skipped · PR is already up-to-date
  • ✅ Merged 08:45 · 148e2d8
Merge conditions: 10 of 10 met

This pull request

Condition Required by
✅ github-review-approved GitHub repository ruleset rule Mergify merge protections
✅ -draft Merge Protections rule Required checks
✅ -label = hold Merge Protections rule Required checks

The batch, tested in place

Condition Required by
✅ check-success = Analyze (actions) Merge Protections rule Required checks
✅ check-success = Analyze (go) Merge Protections rule Required checks
✅ check-success = Analyze (javascript-typescript) Merge Protections rule Required checks
✅ check-success = e2e-hermetic Merge Protections rule Required checks
✅ check-success = go Merge Protections rule Required checks
✅ check-success = @unfret/Unfret Merge Protections rule Unfret on risky paths
✅ any of: check-success = @mergify/Mergify Merge Protections, check-neutral = @mergify/Mergify Merge Protections, check-skipped = @mergify/Mergify Merge Protections GitHub repository ruleset rule Mergify merge protections

Times in UTC · dashboard · how the merge queue works

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant