Skip to content

fix(server): integrate launch retry keys with current main - #22446

Open
zainmitchell wants to merge 15 commits into
pingdotgg:t3code/peer/launch-request-keyfrom
zainmitchell:contribution/21671-reviewed-conflict-fix
Open

zainmitchell wants to merge 15 commits into
pingdotgg:t3code/peer/launch-request-keyfrom
zainmitchell:contribution/21671-reviewed-conflict-fix

Conversation

@zainmitchell

@zainmitchell zainmitchell commented Oct 20, 2026 •

Copy link
Copy Markdown

Summary

Keep launch retries tied to their accepted launch while integrating the updated t3code/peer/launch-request-key base at 8a5f64e97.

same clientRequestId -> accepted launch -> resume original preparation

Preserves caller mode ceilings and checks existing-worktree membership on retries. Keeps upstream's current replay fallback, contracts and tool instructions. This updates the existing support PR; maintainer feature and workflow approval remain separate.

Evidence

  • 107 focused launch/handler/MCP tests and 2 provider instruction tests passed on candidate b81fe3355.
  • Server typecheck passed.
  • Previous two-machine evidence on 820e789c3 is historical and does not verify this updated head.

Merge Danger

Door: Two-way code integration.

Blast Radius: Server launch and replay behavior. No live app or profile changes; no new two-machine runtime pass for this head.

Original implementation: Julius Marminge. Conflict integration: Claude Opus 5.5 High through T3 Code. Independent review: GPT-6.1-Sol Medium through Codex in T3 Code.

input.files.map(async (relativePath) => {
const result = await executeAtomQuery(
appAtomRegistry,
projectEnvironment.readFile({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High lib/addProjectToMachine.ts:148

Selecting an ignored binary file always produces a failed copy: projectEnvironment.readFile rejects files containing NUL bytes, and this read failure is recorded in failed instead of transferring the file. Use a binary-safe transfer path or exclude unsupported files before offering them in the dialog.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/lib/addProjectToMachine.ts around line 148:

Selecting an ignored binary file always produces a failed copy: `projectEnvironment.readFile` rejects files containing NUL bytes, and this read failure is recorded in `failed` instead of transferring the file. Use a binary-safe transfer path or exclude unsupported files before offering them in the dialog.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is imported unchanged from main by the support merge. Git blob 367420c45e0f526f7ee6a878bb008abc59c8ee2f is identical at this PR's head ec2eba74, incorporated main f7f9e217, and main 5d4c202e (upstream source). It is outside both the launch-retry layer and the combined mode-limit/launch feature changes.

I am preserving the upstream file to keep this PR focused on integrating the existing stack. This comparison does not reproduce or dismiss the reported bug. Maintainer review of the merge remains required.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm unable to act on this request because you do not have permissions within this repository.

@@ -0,0 +1,10 @@
!macro customInstall
!ifndef DO_NOT_CREATE_START_MENU_SHORTCUT
${IfNot} ${FileExists} "$newStartMenuLink"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium resources/installer.nsh:3

When $keepShortcuts is true, this recreates a Start Menu shortcut the user deliberately deleted on every update: customInstall treats the missing link as needing repair after the installer preserves its absence. Gate shortcut creation on $keepShortcuts so the user's choice is honored.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/desktop/resources/installer.nsh around line 3:

When `$keepShortcuts` is true, this recreates a Start Menu shortcut the user deliberately deleted on every update: `customInstall` treats the missing link as needing repair after the installer preserves its absence. Gate shortcut creation on `$keepShortcuts` so the user's choice is honored.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is imported unchanged from main by the support merge. Git blob 092f641c3359fb58bf2232132e9bd4ef0491ac56 is identical at this PR's head ec2eba74, incorporated main f7f9e217, and main 5d4c202e (upstream source). It is outside both the launch-retry layer and the combined mode-limit/launch feature changes.

I am preserving the upstream file to keep this PR focused on integrating the existing stack. This comparison does not reproduce or dismiss the reported bug. Maintainer review of the merge remains required.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm unable to act on this request because you do not have permissions within this repository.

const scaledHeightDifference = previous
? (previous.height - current.height) * current.scale
: 0;
if (Math.abs(current.height - win.innerHeight / current.scale) <= 1) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High lib/softwareKeyboard.ts:48

On Firefox Android, opening the keyboard sets viewportOpen to false, so plain Enter can submit instead of preserving multiline input and the post-send keyboard blur is skipped. Firefox resizes both viewports together, making current.height equal win.innerHeight / current.scale here; navigator.virtualKeyboard is unsupported there, and the initial subscription check has the same limitation. Track keyboard visibility from a signal that does not require the layout and visual viewports to differ.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/lib/softwareKeyboard.ts around line 48:

On Firefox Android, opening the keyboard sets `viewportOpen` to `false`, so plain Enter can submit instead of preserving multiline input and the post-send keyboard blur is skipped. Firefox resizes both viewports together, making `current.height` equal `win.innerHeight / current.scale` here; `navigator.virtualKeyboard` is unsupported there, and the initial subscription check has the same limitation. Track keyboard visibility from a signal that does not require the layout and visual viewports to differ.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is imported unchanged from main by the support merge. Git blob e20d5fe00b4aa539792e0ee4a2d06658fc41c2cc is identical at this PR's head ec2eba74, incorporated main f7f9e217, and main 5d4c202e (upstream source). It is outside both the launch-retry layer and the combined mode-limit/launch feature changes.

I am preserving the upstream file to keep this PR focused on integrating the existing stack. This comparison does not reproduce or dismiss the reported bug. Maintainer review of the merge remains required.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm unable to act on this request because you do not have permissions within this repository.

@macroscopeapp

macroscopeapp Bot commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — Despite the launch-retry title, the base-to-head tree is a 1,703-file merge containing production server orchestration, authentication, desktop/mobile/web behavior, release workflows, and Macroscope/static-analysis configuration changes. The unresolved High/Medium runtime findings further support keeping this change set with human reviewers.

Needs human approval because:

  • 3 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

juliusmarminge and others added 9 commits October 20, 2026 16:06
An OAuth client on /mcp is capped by the access it was approved with.
When another environment calls on behalf of one of its agents, that agent
may run under narrower modes, and the target has no way to know.

/mcp now reads `T3-Mode-Limit: <runtimeMode>/<interactionMode>` from OAuth
clients and caps the request at the narrower of the two. The header can
only narrow: a broader one changes nothing, and a malformed one is
refused with 400. The client's interaction mode can now be capped too;
before, it was always default.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A launch had no retry key, so an agent (or another environment calling on
its behalf) that lost the response could only guess whether the thread
was created, and a retry started a second one.

t3_thread_launch now takes an optional clientRequestId. The command,
thread and message ids derive from the caller and the key, and the launch
service already replays a command it accepted, so a retry returns the
first thread. Without a key every launch is new, as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Integrates upstream main c22ace2 (v0.1.1) into the retained catch-up
merge 4fbb8de. Clean merge; the mode-limit feature delta against main is
unchanged.
The launch section said launch has no retry key, but t3_thread_launch
accepts clientRequestId and replays the first accepted launch for the
same key within the caller's MCP session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 452eb16)
@zainmitchell
zainmitchell force-pushed the contribution/21671-reviewed-conflict-fix branch from 452eb16 to 9621c64 Compare October 21, 2026 04:01
@zainmitchell zainmitchell changed the title fix(server): integrate the resolved parent into keyed launch retries fix(server): integrate launch retry keys with current main Oct 21, 2026
@zainmitchell
zainmitchell changed the base branch from takeover/ssh-relay-remote-15-launch-retry to t3code/peer/launch-request-key October 21, 2026 04:02
@zainmitchell

Copy link
Copy Markdown
Author

Additional combined-stack runtime evidence is recorded on #22448: the reviewed integration was deployed on two Windows PCs with Nightly 3486, existing peer links reconnected after both server restarts, and native agent send/wait/read completed successfully across both machines.

These results cover the combined Nightly integration, not this standalone PR head. This PR's code and target branch are unchanged. Exact source revisions, focused checks, model/harness attribution and verification limits are in the linked report. Maintainer direction/scope approval and review remain separate requirements.

@gitcafe-production
gitcafe-production Bot force-pushed the t3code/peer/launch-request-key branch from 6152622 to 88ec543 Compare October 22, 2026 04:16
An OAuth client on /mcp is capped by the access it was approved with.
When another environment calls on behalf of one of its agents, that agent
may run under narrower modes, and the target has no way to know.

/mcp now reads `T3-Mode-Limit: <runtimeMode>/<interactionMode>` from OAuth
clients and caps the request at the narrower of the two. The header can
only narrow: a broader one changes nothing, and a malformed one is
refused with 400. The client's interaction mode can now be capped too;
before, it was always default.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gitcafe-production
gitcafe-production Bot force-pushed the t3code/peer/launch-request-key branch from 88ec543 to 3b46b4c Compare October 22, 2026 04:36
A launch had no retry key, so an agent (or another environment calling on
its behalf) that lost the response could only guess whether the thread
was created, and a retry started a second one.

t3_thread_launch now takes an optional clientRequestId. The command,
thread and message ids derive from the caller and the key, and the launch
service already replays a command it accepted, so a retry returns the
first thread. Without a key every launch is new, as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gitcafe-production
gitcafe-production Bot force-pushed the t3code/peer/launch-request-key branch from 3b46b4c to 1aa278b Compare October 22, 2026 04:55
Resolve the receipt-replay conflict in Orchestrator.ts by keeping the
mode-ceiling check for replayed deferred launches and the target's
queued-run.start replay. Drop a duplicate clientRequestId replay test that
both sides added at different positions in handlers.test.ts. The target's
launched-model lookup and this branch's accepted-launch lookup both stay:
an accepted receipt still decides the replayed model first.

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

Copy link
Copy Markdown
Author

Conflict refresh: cdb82b0

Merged the current target t3code/peer/launch-request-key at 1aa278ba2891974d3f1afd8ef83e16d0b55ad5cf into this PR as cdb82b078323f080ae220384dcb5743f70935ca4. The original PR head 9621c645 remains its first parent; no history rewrite or retargeting.

The resolution retains the receipt-validated launch retry and mode-ceiling recheck, upstream's new original-model lookup and selected queued-run replay, and the new upstream regression test. One byte-identical duplicate replay test was removed.

Validation on upstream's required Node 26.12.1: 113 focused tests passed across six files; server typecheck and scoped format/lint passed, with only inherited lint warnings. Independent parent verification passed 15 launch-handler/peer-link tests on the #22447 candidate; the launch handler and orchestrator files are byte-identical between these two refreshed candidates. The parent command was vp test run apps/server/src/mcp/toolkits/project/handlers.test.ts apps/server/src/peer/PeerLinks.test.ts.

The earlier two-machine runtime evidence remains evidence for its explicitly named older commits. It was not repeated on this new head. Maintainer scope approval and CI remain separate requirements.

Resolution: Claude Opus 5.5 High through T3 Code. Independent source review and focused verification: GPT-6.1-Sol through Codex in T3 Code.

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Oct 22, 2026
A launch had no retry key, so an agent (or another environment calling on
its behalf) that lost the response could only guess whether the thread
was created, and a retry started a second one.

t3_thread_launch now takes an optional clientRequestId. The command,
thread and message ids derive from the caller and the key, and the launch
service already replays a command it accepted, so a retry returns the
first thread. Without a key every launch is new, as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gitcafe-production
gitcafe-production Bot force-pushed the t3code/peer/launch-request-key branch from 1aa278b to 071e661 Compare October 22, 2026 05:56
The target's launch commit now skips new-launch checks when a retry finds
its thread. Keep that for the worktree base ref and project defaults, and
also skip the base ref for an accepted receipt as before. Keep checking
existing-worktree membership on every launch: a retry may bind a workspace
to an idle accepted launch, and this branch's tests require the refusal.

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

Copy link
Copy Markdown
Author

Launch-retry conflict refresh: 6d84a1e

Merged the amended target 071e6616495613844a1ff062446e41b4fc586d22 into the published head as 6d84a1e536c1418ea0ff459806e4bd08a5a0b606, preserving both parents. The target changed launch-retry behavior; this was not just a rebase.

Intentional resolution: retained Julius's earlier fix a615bda90 / 1fdb652e: an existing_worktree request must still pass project membership validation on a retry. An idle accepted launch can receive its first message and bind a workspace on that retry. Restoring upstream's new skip makes the existing regression test create a preparing run for an outside path instead of refusing it. Trade-off: a removed or unregistered existing worktree can cause a retry to be refused. This differs from the target's new unconditional replay skip and remains a maintainer review point.

Upstream's new base-ref retry behavior and regression test are kept: a retry still succeeds after its original base ref disappears. Model precedence and the receipt-validated replay remain unchanged.

Node 26.12.1 validation: 114 focused tests and server typecheck passed; scoped lint/format passed with two inherited warnings. Independently, the parent ran both named behavior tests on the combined #22448 candidate: the membership guard and deleted-base replay both passed. There is no new two-machine runtime claim for these heads.

Resolution: Claude Opus 5.5 High through T3 Code. Independent source review and targeted verification: GPT-6.1-Sol through Codex in T3 Code. Maintainer scope approval and CI remain separate requirements.

@zainmitchell

zainmitchell commented Oct 25, 2026 •

Copy link
Copy Markdown
Author

Documentation/reuse cross-link for launch-retry integration: The current review note's replay/worktree-membership trade-off remains explicit; stable evidence is not substituted for this head.

The native messaging Ideas discussion and complete fork brief now bring together why/when/how, original/support PR dependencies, closed replacement history, later-layer scope, exact-head evidence and limitations. The corresponding core layer and selected fixes are represented in the version-pinned stable integration; it is not a copy of every current PR head.

The stable source/download preview has its own manifest and evidence; its results do not establish this PR head's acceptance. This temporary fork is maintained until T3 supplies the capability or a better replacement. Original upstream authorship is retained. This is a documentation cross-link, not a new feature PR or merge request.

Prepared with GPT-6.1 Sol through Codex in T3 Code. Implementation and historical model credits are stated in the linked brief.


Factory catalog cross-reference — 2026-10-26. Support lineage for included launch identity: accepted launch receipts matter when a factory reconciles an ambiguous launch. This support PR is an alternative integration route for the original layer, not an extra required cherry-pick.

Factory Ideas · Pinned fork source/guide · Source release. Version-pinned community experimental source preview; full lifecycle acceptance remains open. No upstream endorsement or current-PR-head test acceptance is claimed. Julius Marminge/T3 authorship is retained; later upstream heads are not acceptance evidence or a required cherry-pick sequence.

Prepared with GPT-6.1 Sol through Codex in T3 Code.

@gitcafe-production
gitcafe-production Bot force-pushed the t3code/peer/launch-request-key branch from 071e661 to 1c5e007 Compare October 26, 2026 01:44
@juliusmarminge
juliusmarminge force-pushed the t3code/peer/launch-request-key branch from 1c5e007 to 8a5f64e Compare October 26, 2026 02:30
The author rebased peer/launch-request-key again onto the updated
mode-limit layer and a newer main (fe585bc); the layer itself is
unchanged. This reapplies the previous resolution over that movement
(merged against the previous target), so the support delta stays the
same: replay before mutable preflights, worktree membership on every
launch, accepted preparation and dispatch limits on replay, and the
retry-key docs.

- ThreadLaunchService.test.ts: the project mock keeps the support's
  getProject override and takes main's Effect.succeedSome; the support's
  MCP launch-retry test provides DocumentText the way the target's tests
  now do, since project launches now require it.
- project/handlers.test.ts: the support's getAcceptedLaunch mock uses
  Effect.succeedNone, which the target's Effect diagnostics now require.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zainmitchell added a commit to zainmitchell/t3code that referenced this pull request Oct 26, 2026
…#22448

The author rebased peer/forwarding again onto the updated peer-links
layer and a newer main (fe585bc), adding DocumentText wiring, the
succeedNone/succeedSome refactors and diagnostics comments. This
reapplies the previous resolution over that movement (merged against the
previous target), so the support delta is unchanged: bounded internal
Stop retries with the global no-op Stop receipt sequence (Orchestrator
and EventSink), child Stops carrying both stopDelegatedTasks: false and
throughSequence, the internal thread.stop variant accepting
stopDelegatedTasks, dequeued-run Stop targeting, the remote schedule
secret-ref guard, forwarded tool validation and codecs, and the
lower-layer launch and peer fixes.

- Orchestrator.ts: main removed the unused layerUnavailable stub, so the
  support's readStoredEvents entry in it goes too.
- PeerForwarding.test.ts: the target dropped its Option import for
  Effect.succeedNone, so the support's getAcceptedLaunch mock uses
  Effect.succeedNone as well instead of a now-undefined Option.
- ThreadLaunchService.test.ts and project/handlers.test.ts: as in
  pingdotgg#22446, the support's MCP launch-retry test provides DocumentText the
  way the target's tests now do, and its getAcceptedLaunch mock uses
  Effect.succeedNone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zainmitchell added a commit to zainmitchell/t3code that referenced this pull request Oct 26, 2026
The author rebased peer/links again onto the updated launch-request-key
layer and a newer main (fe585bc), adding Effect.succeedNone in
PeerLinks and Schema.decodeEffect in PeerMcpClient. This reapplies the
previous resolution over that movement (merged against the previous
target); both refactors are kept and the support delta is unchanged:
the pingdotgg#22446 launch fixes, event-stream answers matched by request id,
sanitized link errors, and unlink removing only its own row's secret.
Migrations keep main's 068/069 with PeerLinks at 070.

ThreadLaunchService.test.ts and project/handlers.test.ts have the same
inputs as pingdotgg#22446 and reuse its resolution (DocumentText for the MCP
launch-retry test, Effect.succeedNone for the getAcceptedLaunch mock).

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

This branch has not been deployed

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

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants