Repository navigation
fix: Remove duplicate CI view and fix Home fleet routing - #17
Conversation
Remove the project CI dashboard that duplicated the Git and PR panel, and migrate saved CI tabs on web and mobile. Return coordination results to the requesting thread instead of Home. Keep them in their own outbox lane so an offline requester cannot stall the responder, and follow restart continuations to the real answer. Let Home clone, register, and search projects in other environments. Relayed clones need source-control write on the target. Move fork migrations PeerLinkOrigin and CoordinationRequests out of upstream slots 72 and 73, which upstream uses for its own migrations. Report untrusted peer certificates as such, give forwarded clones their full time budget, refresh expired artifact URLs, and add Ctrl+N and Ctrl+P navigation to the composer menus.
[High impact] The PR changes coordination and project workflows across connected environments. Fix blocked result delivery and the remote clone deadline before merging. Findings
Fix with agent prompt### Issue 1
apps/server/src/orchestration-v2/EffectOutbox.ts:328-330
All `coordination.result` effects from one responder share the same lane. If its first requester goes offline, `EffectWorker` keeps that result pending indefinitely. The earlier pending row then blocks every later result from that responder, including answers for online requesters. Separate ordering by requester, or let unrelated results pass a delayed result.
### Issue 2
apps/server/src/home/FleetService.ts:203-206
The new remote clone route passes through `FleetBroker.invoke`, which stops waiting after 90 seconds. The clone itself allows 120 seconds, so a clone taking 90–120 seconds returns `environment_unavailable` to Home while the remote clone can still finish. Raising the timeout in `PeerMcpClient` does not cover this route. Give broker-relayed clones a deadline above the clone limit too.
### Issue 3
apps/server/src/home/HomeService.ts:333-344
`report` now waits for remote `threads.coordination` calls while holding Home's shared lock. A connected but stalled environment can take the broker's full 90-second timeout. Healthy approval and question events in the same batch wait too, as do turning Home off and starting fresh. Classify remote completions outside the lock with a short deadline, then recheck Home before delivery.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.SummaryRemoves the duplicate CI dashboard and adds Home routes for remote project creation, cloning, and thread search.
Intentional change acknowledged by Reviews (1) · Last reviewed commit: "Remove duplicate CI view and fix Home fl..." · Reviewed by Greptile |
| const effectLane = (table: "candidate" | "active") => | ||
| sql.unsafe( | ||
| `CASE WHEN ${table}.effect_type IN ('thread-title.generate', 'coordination.result') THEN ${table}.effect_type ELSE '' END`, |
There was a problem hiding this comment.
Offline requesters block other answers
All coordination.result effects from one responder share the same lane. If its first requester goes offline, EffectWorker keeps that result pending indefinitely. The earlier pending row then blocks every later result from that responder, including answers for online requesters. Separate ordering by requester, or let unrelated results pass a delayed result.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/server/src/orchestration-v2/EffectOutbox.ts
Line: 328-330
Comment:
**Offline requesters block other answers**
All `coordination.result` effects from one responder share the same lane. If its first requester goes offline, `EffectWorker` keeps that result pending indefinitely. The earlier pending row then blocks every later result from that responder, including answers for online requesters. Separate ordering by requester, or let unrelated results pass a delayed result.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Confirmed and fixed in 2176350. Each coordination.result is now its own lane in claimableCandidatePredicate, so a result waiting on an offline requester blocks neither turn work nor other results. Requester-side command ids already deduplicate results, so they need no ordering among themselves. FoundationPersistence.test.ts now claims a second requester's result while the first sits in backoff. Before the fix, only one effect was claimable.
| "projects.clone": Effect.fn("FleetService.projects.clone")((input) => | ||
| cloneProject(input).pipe( | ||
| Effect.provideService(Repositories.SourceControlRepositoryService, repositories), | ||
| ), |
There was a problem hiding this comment.
The new remote clone route passes through FleetBroker.invoke, which stops waiting after 90 seconds. The clone itself allows 120 seconds, so a clone taking 90–120 seconds returns environment_unavailable to Home while the remote clone can still finish. Raising the timeout in PeerMcpClient does not cover this route. Give broker-relayed clones a deadline above the clone limit too.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/server/src/home/FleetService.ts
Line: 203-206
Comment:
**Slow clones report failure**
The new remote clone route passes through `FleetBroker.invoke`, which stops waiting after 90 seconds. The clone itself allows 120 seconds, so a clone taking 90–120 seconds returns `environment_unavailable` to Home while the remote clone can still finish. Raising the timeout in `PeerMcpClient` does not cover this route. Give broker-relayed clones a deadline above the clone limit too.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Confirmed and fixed in 2176350. FleetBroker.invoke now waits 130 s for projects.clone, above the 120 s CLONE_TIMEOUT_MS, and 90 s for everything else.
| if (event.environmentId !== environmentId) { | ||
| const result = yield* broker | ||
| .invoke(event.environmentId, { | ||
| actor: { environmentId, threadId: homeThreadId }, | ||
| request: { | ||
| op: "threads.coordination", | ||
| input: { | ||
| threadId: event.threadId, | ||
| ...(event.runId === undefined ? {} : { runId: event.runId }), | ||
| }, | ||
| }, | ||
| }) |
There was a problem hiding this comment.
Stalled machines delay Home alerts
report now waits for remote threads.coordination calls while holding Home's shared lock. A connected but stalled environment can take the broker's full 90-second timeout. Healthy approval and question events in the same batch wait too, as do turning Home off and starting fresh. Classify remote completions outside the lock with a short deadline, then recheck Home before delivery.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/server/src/home/HomeService.ts
Line: 333-344
Comment:
**Stalled machines delay Home alerts**
`report` now waits for remote `threads.coordination` calls while holding Home's shared lock. A connected but stalled environment can take the broker's full 90-second timeout. Healthy approval and question events in the same batch wait too, as do turning Home off and starting fresh. Classify remote completions outside the lock with a short deadline, then recheck Home before delivery.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Confirmed and fixed in 2176350. report classifies watched completions before taking Home's lock, with a 10 s deadline per remote check, then reads Home again under the lock before it delivers. A failed or timed-out check still reports the run. The new test 'a stalled environment does not hold Home's lock while a report classifies it' turns Home off while a check never answers. Against the old code, the test hangs on disable.
Give each coordination result its own outbox lane, so a result waiting on an offline requester no longer holds answers for other requesters. Classify watched completions before taking Home's lock, with a 10 s deadline per remote check, so a stalled machine cannot delay other alerts or turning Home off. Let a relayed clone wait 130 s, above the 120 s clone limit.
Add a projects.update fleet operation so Home can repoint or rename a project on another machine with t3_project_update. Script changes need the same settings scopes as a direct update.
The CI dashboard from #16 duplicated the existing Git and PR panel, and the fleet work from #15 left Home unable to clone, register, update, or search projects on other machines. A review pass also found that the fork's migration 72 collides with upstream's, which would stop the server from starting after the next upstream sync.
What changes:
t3_project_clone,t3_project_create,t3_project_update, andt3_thread_searchwith another environment'senvironmentId. A relayed clone requiressource-control:writeon the target, the same as a direct clone.PeerLinkOriginandCoordinationRequestsmove toForkMigrations.ts. Databases that recorded them at upstream ids 72 or 73 are rewritten on startup.unreachablewith the TLS code, not "not a T3 environment"./and$composer menus.Checks:
vp run check:changedpasses format, lint, knip, and typecheck. Server tests pass except four that fail only on the Mac (spawn vp ENOENTand the/private/vartemp path). Browser tests for the touched web files pass (138 tests).Need help on this PR? Tag
@codesmith-botwith what you need.