Posted by an AI agent on Jackson's behalf
Decision: deferred; use the remote URL for dogfooding
Jackson chose on 2026-09-04 to defer this initiative because the server-served remote URL already provides the main benefit: development on an always-on server. Completing the combined local-client experience would touch several J5 surfaces and distract from more urgent work. This issue preserves the research; it is not an implementation commitment or a deployment blocker for the remote-URL workflow.
Revisit when switching between local and remote clients repeatedly interrupts actual work, or when managing concurrent fleets on multiple servers becomes a concrete requirement. A small, independently justified UX fix could explain unsupported combinations before submission, without starting this whole initiative.
Problem and observed behavior
After adding a working remote J5 server under Settings → Connections → Add environment, the local client does not show that server's Squadrons in its choices. The UI also allowed an attempted remote launch that ended in an error.
Evidence collected during remote dogfooding:
- The remote server contains a real Squadron and project. Its own server-served UI successfully launched fresh Claude and Codex threads and displayed their replies live.
- Adding the remote connection to the local UI did not expose that remote Squadron to the operator.
- The subsequent remote web-created run failed before the provider started (
startedAt=null, providerTurnId=null). The exact browser error was not captured, so the source-derived registration failure below is a likely explanation, not a verified copy of that error.
- An OPTIONS request to the remote
/api/j5/squadrons endpoint from a localhost origin returned 204 and permitted the Authorization header. The inspected production server applies CORS to the J5 routes. This evidence points to J5 client routing rather than another Tailscale setup task.
Research snapshot: 5f1e56b9f3f80e40adfb427f85905c2c99d41699. No application changes or restarts were performed for this investigation.
Confirmed gaps in the current code
| Surface |
Finding |
Source |
| Squadron list/create |
Both operations use resolvePrimaryEnvironmentHttpUrl; ManagedSquadron has no environment identity. |
squadronClient.ts |
| Directory lifecycle |
One global list and status, with no subscription to connection-catalog additions/reconnections. |
SquadronDirectory.ts |
| Picker/project join |
Every Squadron's project reference is matched against primaryEnvironmentId. Fetching remote rows alone would still leave the join wrong. |
SquadronPicker.logic.ts |
| Creation |
The form explicitly refuses a non-primary project. This is a deliberate v0 limit. |
SquadronCreate.logic.ts |
| Draft/launch |
Ambient scope is a plain Squadron ID; the draft chip exposes the unscoped directory. The launch carries that ID separately from its target environment. |
SquadronDraftState.ts, ChatView.tsx |
| Thread homes and filters |
Reads go to primary; caches use raw thread IDs. Sidebar supplies IDs without their environments. A dropdown-only fix leaves remote labels/filtering incorrect. |
ThreadHomesClient.ts, Sidebar.tsx |
| Human attention |
Inbox reads, answers, and the bell count all target primary. Remote requests would remain missing from the local inbox after a picker-only fix. |
humanInboxClient.ts, humanInboxCountClient.ts |
The runtime already routes a launch through the selected environment. A local Squadron ID paired with a remote project can therefore reach the remote server, where SquadronProjectReferences checks the remote server's own table and rejects an unknown Squadron. The launch error wrapper reports that the durable thread could not receive its required Squadron home. The registration guard should remain fail-closed.
Boundaries and current workaround
Use the remote server's own HTTPS URL. That makes the remote environment primary, so its Squadron directory, thread-home reads, and inbox use the correct server. Collaborating Squadrons can be kept together on that server.
Cross-Squadron messaging on one server is distinct from cross-server messaging. This issue covers merging client views and routing user operations to their owning server. It does not add server-to-server message delivery, migrate a Squadron, or let one Squadron span machines.
The current DV5 override explicitly defers multi-environment Squadron creation. The cross-device position preserves one-server Squadron ownership (X1), supports client-side merged views (X2), and treats cross-server exchanges as separate transport work (X3).
Proposed approach when this is prioritized
- Carry a client-side
{ environmentId, squadronId } reference through the directory, ambient/draft scope, picker and launch validation. Keep project/thread/cache keys environment-scoped too.
- Read Squadrons from usable saved connections using existing prepared connections and authentication. Maintain per-environment cached/loading/error state; refresh on add/reconnect/create, discard stale results from removed connections, and avoid a new rapid polling loop.
- Show environment labels in choices. Join projects within the owning environment. Create a Squadron on the explicitly selected folder's server. Require a compatible Squadron before launching after an environment/folder change, preserving draft text.
- Batch thread-home reads by environment and update all existing web creation/filtering entry points: first-run/index, sidebar, command palette, keybindings, composer, and plan-to-implementation inheritance.
- Merge inbox rows/counts with origin identity. Answer through that connection using its returned person ID. Expose partial/offline/error state instead of presenting failed reads as empty or zero.
Reuse the environment catalog and the existing J5 prepared-connection HTTP path, including cookie/Bearer/DPoP handling. No new global registry, server transport, or database migration is expected for this client-side scope; confirm that during implementation.
Discovery/launch/home handling and inbox integration can be separate coordinated PRs. Both are needed before claiming the complete combined-client dogfood experience. Native mobile's separate v0 cohort is not implicitly included; web and desktop share this web implementation.
Upstream principle
Most changes belong under apps/web/src/j5. Limited edits to existing J5 integration points in upstream-owned Sidebar, ChatView, CommandPalette and chat route wrappers are likely necessary. Bring the concrete scope to Jackson for a ruling before implementation, reuse those integration points, and record the exceptions in FORK.md. Lift only DV5's relevant restriction. Preserve one-folder v0 behavior and server-local Squadron authority.
Moving registration validation earlier to avoid a durable failed thread is a possible separate hardening task, not a prerequisite for correct client routing.
Acceptance evidence for future implementation
Research and issue preparation: Codex harness, GPT-6; independent source review by a Codex subagent.
Posted by an AI agent on Jackson's behalf
Decision: deferred; use the remote URL for dogfooding
Jackson chose on 2026-09-04 to defer this initiative because the server-served remote URL already provides the main benefit: development on an always-on server. Completing the combined local-client experience would touch several J5 surfaces and distract from more urgent work. This issue preserves the research; it is not an implementation commitment or a deployment blocker for the remote-URL workflow.
Revisit when switching between local and remote clients repeatedly interrupts actual work, or when managing concurrent fleets on multiple servers becomes a concrete requirement. A small, independently justified UX fix could explain unsupported combinations before submission, without starting this whole initiative.
Problem and observed behavior
After adding a working remote J5 server under Settings → Connections → Add environment, the local client does not show that server's Squadrons in its choices. The UI also allowed an attempted remote launch that ended in an error.
Evidence collected during remote dogfooding:
startedAt=null,providerTurnId=null). The exact browser error was not captured, so the source-derived registration failure below is a likely explanation, not a verified copy of that error./api/j5/squadronsendpoint from a localhost origin returned 204 and permitted the Authorization header. The inspected production server applies CORS to the J5 routes. This evidence points to J5 client routing rather than another Tailscale setup task.Research snapshot:
5f1e56b9f3f80e40adfb427f85905c2c99d41699. No application changes or restarts were performed for this investigation.Confirmed gaps in the current code
resolvePrimaryEnvironmentHttpUrl;ManagedSquadronhas no environment identity.primaryEnvironmentId. Fetching remote rows alone would still leave the join wrong.The runtime already routes a launch through the selected environment. A local Squadron ID paired with a remote project can therefore reach the remote server, where SquadronProjectReferences checks the remote server's own table and rejects an unknown Squadron. The launch error wrapper reports that the durable thread could not receive its required Squadron home. The registration guard should remain fail-closed.
Boundaries and current workaround
Use the remote server's own HTTPS URL. That makes the remote environment primary, so its Squadron directory, thread-home reads, and inbox use the correct server. Collaborating Squadrons can be kept together on that server.
Cross-Squadron messaging on one server is distinct from cross-server messaging. This issue covers merging client views and routing user operations to their owning server. It does not add server-to-server message delivery, migrate a Squadron, or let one Squadron span machines.
The current DV5 override explicitly defers multi-environment Squadron creation. The cross-device position preserves one-server Squadron ownership (X1), supports client-side merged views (X2), and treats cross-server exchanges as separate transport work (X3).
Proposed approach when this is prioritized
{ environmentId, squadronId }reference through the directory, ambient/draft scope, picker and launch validation. Keep project/thread/cache keys environment-scoped too.Reuse the environment catalog and the existing J5 prepared-connection HTTP path, including cookie/Bearer/DPoP handling. No new global registry, server transport, or database migration is expected for this client-side scope; confirm that during implementation.
Discovery/launch/home handling and inbox integration can be separate coordinated PRs. Both are needed before claiming the complete combined-client dogfood experience. Native mobile's separate v0 cohort is not implicitly included; web and desktop share this web implementation.
Upstream principle
Most changes belong under
apps/web/src/j5. Limited edits to existing J5 integration points in upstream-owned Sidebar, ChatView, CommandPalette and chat route wrappers are likely necessary. Bring the concrete scope to Jackson for a ruling before implementation, reuse those integration points, and record the exceptions in FORK.md. Lift only DV5's relevant restriction. Preserve one-folder v0 behavior and server-local Squadron authority.Moving registration validation earlier to avoid a durable failed thread is a possible separate hardening task, not a prerequisite for correct client routing.
Acceptance evidence for future implementation
Research and issue preparation: Codex harness, GPT-6; independent source review by a Codex subagent.