Skip to content

feat(server): agents can name the session owner and message sender - #116

Merged
tusharbhardwaj-bk merged 3 commits into
expbkmainfrom
t3code/tec-964-session-identity
Aug 18, 2026
Merged

tusharbhardwaj-bk merged 3 commits into
expbkmainfrom
t3code/tec-964-session-identity

Conversation

@tusharbhardwaj-bk

@tusharbhardwaj-bk tusharbhardwaj-bk commented Aug 18, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

On a shared dev machine an agent has no reliable way to tell who it is working for. It falls back to whatever the machine says — git config, a checked-in .env.user symlinked across worktrees — so one contributor's session gets attributed to another. Linear: TEC-964.

Fix

Provider sessions now spawn with three additive environment variables, read from the durable environment-user directory rather than source control:

Variable Value
BK_IDENTITY_RUNTIME Always t3-code. Marks the runtime even when nobody could be resolved.
BK_SESSION_OWNER_EMAIL Primary email of the thread owner.
BK_MESSAGE_SENDER_EMAIL Primary email of the user who actually sent the message being answered.

The sender is never manufactured from the owner — an inferred sender is the misattribution this replaces — so an absent variable means "unknown" and the agent can say so. A missing or unreadable user record leaves the runtime marker alone and the turn proceeds; identity never blocks work and never falls back to git.

A provider process reads its environment once at spawn, so ProviderCommandReactor fingerprints the identity each live session was started with and restarts on an owner transfer or a new sender, beside the existing credential-actor restart.

Source-control profile injection is unchanged and composes with the markers: mergeSourceControlEnvironment now scrubs the machine's inherited Git and GitHub credentials only when the overlay carries a source-control identity of its own, so machine-identity mode keeps its own GH_TOKEN while still carrying the markers.

Shape

Logic lives in the fork-owned apps/server/src/identity/SessionIdentityEnvironment.ts. The upstream-facing surface is four marked seams: the execution-options resolver in ProviderCommandReactor.ts, the adapter-spawn call in ProviderService.ts, one optional field on ProviderSessionExecutionOptions, and the layer in server.ts. No provider adapter changed.

Tests

vp test run src/identity/SessionIdentityEnvironment.test.ts src/sourceControl/SourceControlExecutionEnvironment.test.ts — 15 passed. Covers owner/sender resolution, sender change, owner transfer, missing and blank user records, and composition in both machine and thread-profile source-control modes. ProviderCommandReactor, ProviderService, OrchestrationReactor, GitManager, and SourceControlProfileService suites re-run green (182 tests).

Model: Claude Opus 5 in T3 Code.


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

On a shared dev machine an agent had no reliable way to tell who it was
working for, so it fell back to whatever the machine said — git config, a
checked-in dotfile — and attributed one contributor's session to another.

Provider sessions now spawn with three additive variables read from the
durable environment-user directory: BK_IDENTITY_RUNTIME (always t3-code),
BK_SESSION_OWNER_EMAIL for the thread owner, and BK_MESSAGE_SENDER_EMAIL for
the user who actually sent the message being answered — never the owner by
fallback, because an inferred sender is the misattribution this replaces. A
missing or unreadable user record leaves the runtime marker alone and the turn
proceeds, so "unknown" is expressible and nothing blocks on identity.

Because a process reads its environment once at spawn, ProviderCommandReactor
fingerprints the identity each live session was started with and restarts on an
owner transfer or a new sender, beside the existing credential-actor restart.
The markers compose with source-control profiles instead of replacing them:
mergeSourceControlEnvironment now scrubs inherited Git and GitHub credentials
only when the overlay carries a source-control identity of its own, so
machine-identity mode keeps its own GH_TOKEN and still carries the markers.

TEC-964

Model: Claude Opus 5 in T3 Code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Aug 18, 2026
tusharbhardwaj-bk and others added 2 commits August 18, 2026 12:26
The OpenCode adapter refuses to start against an external server whenever
execution options carry an environment, because it cannot inject one there.
Now that every session carries identity markers in that same field, the guard
would have failed every start against an external server.

Test the guard on what it actually protects: a source-control identity in the
overlay. The markers claim none, so they are simply not delivered to an
external server instead of failing the turn.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ctor

Proves the wiring, not just the resolver: owner and sender reach the provider
execution options, an anonymous turn reports the runtime marker alone, the
markers compose with a thread source-control profile, and an owner transfer
restarts the session while the sender stays the same.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@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.5 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.4 KiB — 66.4 KiB ✅
Codex Live turn messages — 11 — 21 ✅
Claude Total thread wire — 11.4 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: 004fc27 · 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 merged commit 3f2f1c2 into expbkmain Aug 18, 2026
14 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