Skip to content

fix(server): use T3 sender for Claude userEmail (TEC-1031) - #128

Merged
tusharbhardwaj-bk merged 5 commits into
expbkmainfrom
linear/tec-1031-fix-the-native-bkt3-useremail-system-val-38e14c02
Aug 21, 2026
Merged

fix(server): use T3 sender for Claude userEmail (TEC-1031)#128
tusharbhardwaj-bk merged 5 commits into
expbkmainfrom
linear/tec-1031-fix-the-native-bkt3-useremail-system-val-38e14c02

Conversation

@tusharbhardwaj-bk

@tusharbhardwaj-bk tusharbhardwaj-bk commented Aug 21, 2026

Copy link
Copy Markdown

Claude's native system prompt currently reports the shared Claude subscription email, so agents can misattribute the person sending a T3 Code message.\n\nThis keeps the native Claude Code prompt and appends T3's resolved message-sender email as the authoritative userEmail. If T3 cannot resolve a sender, the prompt explicitly keeps the user unknown instead of falling back to account, OS, or Git identity. Non-T3 Claude sessions remain unchanged.\n\nValidation:\n- vp test run apps/server/src/provider/claudeSessionIdentity.expbkt3.test.ts apps/server/src/provider/Layers/ClaudeAdapter.test.ts (76 passed)\n- vp run --filter t3 typecheck (passed; existing Effect suggestions only)\n- vp fmt --check on changed files\n- vp lint on changed TypeScript files (passed; three pre-existing unused-import warnings in ClaudeAdapter.ts)\n- node scripts/check-fork-markers.ts\n\nTEC-1031\n\nImplemented with GPT-5.6 SOL in the Codex harness.


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

tusharbhardwaj-bk and others added 5 commits August 20, 2026 20:06
…and keep Codex readers alive

Three threads in four days (907d4c74 on 08-17, ed3fc9f4 and mcp:1e019f68 on
08-20) sat in "Recovering" for 45 minutes and then held every later prompt in
"Queued" until someone pressed Stop. The 5-minute cadence of their recovery
attempts was the reaper's sweep interval.

The reaper's 2h absolute cap fired on turn age, ignored that the agent had
emitted an event seconds earlier, and only rewrote the projection
(`thread.session.set interrupted`) - the provider turn kept running. Durable
recovery then inspected the provider, found the same live turn, re-adopted it
("Agent work recovered"), and the next sweep settled it again. Ten successful
recoveries later `recovery_attempts == maximum`; `observeSession` still parked
the item in `recovering`, where nothing can claim it and nothing makes it
terminal, so it blocked the thread's queue for good. The same sweep's
inactivity pass then killed the live agent mid tool call, because the cap pass
had just nulled the `activeTurnId` it relies on and `lastSeenAt` only moves on
runtime operations.

- ProviderSessionReaper: the cap measures silence (`lastActivityAt`), not age,
  and when it fires on a live session it dispatches `thread.turn.interrupt`
  first - the Stop path - so the work item is terminal and the provider is
  told to stop before the projection is settled. The inactivity pass asks the
  adapter (`inspectSession().activeProviderTurnId`) before terminating.
- DurableExecutionIntentRepository.observeSession: an interrupted/stopped
  session exhausts an item whose budget is spent (`recovery-exhausted`,
  terminal) instead of parking it in `recovering`. Retry/Dismiss work, the
  next prompt runs.

Separately, the second "continue" on mcp:1e019f68 dispatched fine and then the
server went blind: Codex kept working (rollout grew for 30 minutes) while the
provider event log stopped at sendTurn, until the inactivity reaper killed it.
CodexAdapter forked its event reader with `Effect.forkChild`, i.e. as a child
of whichever fiber called startSession. Since #124 runs each reactor command
in a detached, short-lived fiber, a `thread.session-set` command whose inline
`runDue` won the claim started the session and took the reader down with it
when the command returned.

- CodexAdapter / GrokAdapter: fork the reader into the session scope
  (`Effect.forkIn(sessionScope)`), as ClaudeAdapter already does.
- ProviderCommandReactor: `session-set` and `session-restart-requested` wake
  the durable coordinator instead of dispatching inline, so turn starts only
  ever run on the coordinator's own long-lived fiber.

Regression tests: reaper (silent turn is interrupted then settled; an old but
busy turn is left alone; adapter-reported active turn is not terminated),
repository (spent item exhausts terminally and unblocks the next prompt),
CodexAdapter (reader survives the starting fiber ending).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ents

A turn the adapter still holds but whose thread recorded no event inside the
inactivity threshold is one the server has gone blind to; terminating it is
right. One that is still emitting is alive, whatever the projection says.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ery-loop

fix(server): stop the reaper cap from looping with durable recovery; keep Codex readers alive
fix(server): rotate Claude on hard usage rejection
Claude's native prompt reports the shared account email, which misattributes the user on Beknown's shared runtime. Append the session-scoped message sender as the authoritative userEmail, and explicitly preserve unknown identity when no sender is resolved.

TEC-1031
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Aug 21, 2026
@github-actions

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 11.4 KiB 15.1 KiB
Codex Thread snapshot wire 5.7 KiB 7.3 KiB
Codex Live turn WebSocket wire 5.7 KiB 7.8 KiB
Codex Live turn WebSocket decoded 50.3 KiB 66.4 KiB
Codex Live turn messages 9 21
Claude Total thread wire 11.5 KiB 15.1 KiB
Claude Thread snapshot wire 5.7 KiB 7.3 KiB
Claude Live turn WebSocket wire 5.7 KiB 7.8 KiB
Claude Live turn WebSocket decoded 51.2 KiB 66.4 KiB
Claude Live turn messages 11 21

Baseline: unavailable · PR result: 3b4637e · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 95.6 KiB
  • Claude decoded thread snapshot: 96.3 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@tusharbhardwaj-bk
tusharbhardwaj-bk marked this pull request as ready for review August 21, 2026 07:41
@tusharbhardwaj-bk
tusharbhardwaj-bk merged commit 817b418 into expbkmain Aug 21, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant