Skip to content

feat: delegation results reach a waiting human, one claude per conversation, live GitHub tokens, draft/read-only mode, /handoff, per-turn speaker (v0.465.0) - #888

Merged
vikasprogrammer merged 6 commits into
mainfrom
feat/session-trust
Oct 26, 2026
Merged

vikasprogrammer merged 6 commits into
mainfrom
feat/session-trust

Conversation

@vikasprogrammer

Copy link
Copy Markdown
Owner

This PR implements the follow-ups from the 30-day fleet chat mining (#887), as directed.

1. Results of delegated work reach the person waiting

Root cause: the wake-up deliverer treated any run that had ever called report as finished, and wouldn't inject good news into it. A long human-driven session reports early and keeps going.

Evidence: on one tenant, one engineer conversation handed QA off 28 times and 26 results were dropped (done-no-own-pane). Meanwhile the human typed "did QA complete?" 75 times. Across the fleet that was 206 dropped completions in 30 days, all with an interactive session as the caller.

Fix: a run counts as finished only if it reported after dispatching the hand-off, and never while a person is attached to it.

UI: a "Waiting on" strip above the live terminal lists each open hand-off with its delegate and state: queued / working Nm / blocked / came back.

2. One claude per conversation (the session clash)

An agent's own schedule resumed its transcript while the interactive session was still open. That happened 16 times on one conversation, and the agent started leaving itself 00-READ-ME-TWO-SESSIONS.txt.

createSession now types the request into the live pane instead of starting a second claude (session.resume.redirected). This is a single guard at the point every resume passes through.

3. GitHub token cross-fire

gh (a session PATH shim) and git (the credential helper) now fetch the member's current token from POST /api/agent/github/token on every call.

  • The token is refreshed once, single-flight, when it is near expiry.
  • If the fetch fails, they fall back to the token the session launched with.
  • github_refresh no longer rotates a token that another session refreshed in the last hour.
  • The brief now tells agents to stop pasting literal tokens into commands.

4. Draft-only / read-only sessions

These are under Operations → Working mode, or passed as mode at spawn. Both are enforced at the gate (src/governance/session-mode.ts) and combined with the other guards so the stricter decision wins (stricterDecision). The live agent is told in its pane, and the change is audited as session.mode.set.

  • Draft-only: no email, chat posts or DMs, ticket or PR comments, new PRs or issues, git push, or write calls to external APIs. Replying in the conversation itself is still allowed.
  • Read-only: everything draft-only blocks, plus file edits outside the temp dir, commits, deletes, installs, service restarts and SQL writes.

5. /handoff and "Hand off to a fresh session"

The agent writes a note, and the OS opens a new session for the same agent, acting as the same person. The new session is seeded with the note, the original request and a link back, and keeps the working mode.

  • New always-on MCP tool: handoff.
  • New slash command for claude-code agents: .claude/commands/handoff.md.
  • From the menu: a live agent is asked to run /handoff itself. A session that isn't running gets a server-side summary of its transcript as the note.

6. Who is speaking in a shared session

  • Attribution: the console terminal reports which member pressed Enter, and the composer and inject box attribute their own sends. Each human turn is audited as turn.speaker and the speaker is named in the conversation view.
  • A poke that the server types right after someone presses Enter is not attributed to that person.
  • Agent context: when the speaker isn't the run-as member, claude gets one line naming who it is acting for, via UserPromptSubmit additionalContext. I verified with the real CLI that the model sees it.
  • GitHub: gh and git act as the speaker when that person has linked GitHub.
  • Not in this PR: Composio connections are still bound to the run-as member when the session launches. Switching them per speaker needs the MCP server re-minted, which is the next step.

Also in this PR

I scrubbed real tenant names that had leaked back into older CHANGELOG entries and replaced them with placeholders, per the public-repo rule.

Validation

  • npm run typecheck and web build pass. npm run test:governance passes: 3,351 checks, 0 failures.
  • New scripts/session-trust-test.cjs (67 checks) runs the generated gh shim and git helper for real against a fake server, plus the hook under /bin/bash.
  • wakeup-queue-test.cjs now has 65 checks.
  • npm run demo runs clean.

🤖 Generated with Claude Code

vikasprogrammer and others added 6 commits October 26, 2026 12:44
…e completion

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…b token

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sation, live GitHub tokens, draft/read-only mode, /handoff, per-turn speaker (v0.465.0)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vikasprogrammer
vikasprogrammer merged commit 4b357a0 into main Oct 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant