Repository navigation
refactor(web): new-thread doors and drafts go back to upstream's projects - #455
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
4ed4ca2 to
e739e67
Compare
e739e67 to
762aa66
Compare
bryantderosier
left a comment
There was a problem hiding this comment.
Reviewed this as part of the 454–457 stack. One real problem if this PR can land on its own, and a few stale FORK.md lines. I checked the higher PRs first and dropped anything they fix.
Medium: Create Squadron can leave a project unable to start threads. The web doors stop sending squadronId, but Create Squadron is still offered, and SquadronManagementService.create doesn't check whether another Squadron already references the project. Once two do, resolveProjectSquadron throws SquadronThreadCreationAmbiguousProjectError and no door can send the Squadron it asks for. Example: first send in project P auto-creates Squadron "P", then the user clicks New Squadron on folder P, and every later new thread in P fails on first send. #456 removes the Create Squadron doors, so this only bites if 455 merges without 456. Either merge them together or have create refuse a second reference to the same project. D9's repair text also undersells the fix: delete is refused while the Squadron has unarchived agents or Crews (SquadronDeleteBlockedError).
Stale FORK.md text (still wrong at the top of the stack):
- Case 11 promises the child takes its parent's home "or else its project's Squadron".
ThreadLaunchServicereturnslegacy-plan-child-nativefor a homeless parent and skips registration, so the child stays homeless. - Case 10 still says the web client refuses to send without a Squadron. This PR is the one that returns those doors.
- "Replacement scope" (around line 428) still says
DraftHeroHeadline.tsxreplaces upstream's full implementation and the palette does Registrar-derived selection. Neither is true now. - Nit:
Sidebar.logic.test.tslost upstream'sshouldCreateNewThreadInCurrentProjectimport, which is restored now.
| **Why:** agents need a home in the ledger, and the ledger is still keyed by Squadron. The server rule is a step of retiring Squadrons into projects ([#412](https://github.com/Jacksondr5/j5code/issues/412)), where a thread's home is its project. A Squadron created this way carries its project's name, so it isn't the unnamed junk drawer the first-run gate used to guard against. | ||
|
|
||
| **Consequences:** because a folder is required, a Squadron with no repository isn't possible. That rules out a real future use: non-coding work such as a support rotation. A failed read offers only a retry, never a guessed home. The web client still sends a Squadron with every launch, so the gate is what a person sees until the client's new-thread doors return to upstream. Until then the server rule is reached only by launches that send none, such as ACP session import. | ||
| **Consequences:** the person no longer creates a Squadron before the first thread; the gate is gone. Create Squadron is still offered from the sidebar and from Add Project (D8), and it still requires a folder. A project that several Squadrons reference can't start a thread until one is deleted. |
There was a problem hiding this comment.
Two things here. Create Squadron is still offered, and create doesn't refuse a second Squadron for the same project, so a project can end up with two and then every new thread in it fails with the ambiguous-project error. And the repair isn't just "delete one": delete is refused while the Squadron has unarchived agents or Crews. If this can merge without #456, either guard create or fix this text.
There was a problem hiding this comment.
I'm an AI agent (Claude) working for Jackson.
Agreed on both. No code change here: #455 and #456 merge back to back, and the description now opens with that line. #456 removes every Create Squadron door (the sidebar button, the filter's menu item and the Add Project redirect), and guards the one creating path left until #457, the welcome wizard's Squadron stage, so it uses a project's existing Squadron and never offers a second.
I fixed this text in 87c5f48 (now 5c97b18): D9 says Create Squadron does not check for an existing Squadron on the folder, and that delete is refused while the Squadron has unarchived agents or live Crews, so those have to be archived first.
| 10. SQ1's lossless launch carrier and durable attach boundary: `packages/contracts/src/orchestrationV2.ts:2322-2342` adds additive-optional unbranded `squadronId` at `:2325`; `packages/client-runtime/src/operations/commands.ts:144-167,546-612` carries it only from an explicit first-message caller into the launch RPC and loudly rejects the otherwise-silent no-bootstrap retry with the typed `SquadronLaunchRequiresBootstrapError`, directing the user to start a new thread. Bootstrap re-carry for that rare partial-failure recovery remains a queued improvement, not an invented fallback. `apps/server/src/ws.ts` forwards it only when present before the fixed `creationSource`; and `apps/server/src/orchestration-v2/ThreadLaunchService.ts:63-79,545-611` sends the carrier to J5's shared creation engine only after the thread is durable and before preparation is scheduled. The shared engine is provided once in `apps/server/src/server.ts:337-342`; the boundary honors a sent `squadronId` and rejects an invalid reference, preserves the named durable orphan on failure, and retry uses the same deterministic registration command. Since 2026-10-03 (the Squadron fold, [#412](https://github.com/Jacksondr5/j5code/issues/412)) a launch that sends no `squadronId` is no longer refused: J5-owned `SquadronThreadCreationService` registers the thread into its project's Squadron. Exactly one Squadron referencing the project is used; none creates one named after the project, in the same transaction as the lookup, so concurrent launches create one; several are refused with `SquadronThreadCreationAmbiguousProjectError`; a missing or deleted project is refused without creating anything. A replay reuses the home its first attempt registered. The service reads the project's title from upstream's `ProjectionProjectRepository`, which `makeJ5SquadronCreationLayer` provides, because `ProjectService` depends on the runtime this layer feeds. No upstream source file changed for this; the one upstream-file edit is the J5 test in `ThreadLaunchService.test.ts`, which now fails registration with the several-Squadrons error. The web client still refuses to send without a Squadron (case 9) until its doors return to upstream. This also lets ACP session import (`ws.ts`, which sends no Squadron) register instead of failing. The native cohorts in `SquadronLaunchPolicy.ts` (mobile, system bootstrap, legacy plan children) and the scheduled refusal (case 12) are unchanged. On every rebase, verify this exact client → contract → WebSocket → launch → J5-engine chain, one runtime provider, and no parallel HTTP launch door. | ||
| 11. SQ1's plan-provenance launch carrier is its own protected contract exception: `packages/contracts/src/orchestrationV2.ts:2322-2327` adds additive-optional `sourcePlanRef`; it is not an existing generic field and has no default. `packages/client-runtime/src/operations/commands.ts:152-167,590-596,624-629,669-683`, `apps/server/src/ws.ts`, and `apps/server/src/orchestration-v2/ThreadLaunchService.ts:63-79,548-592` pass it only from the plan→implementation launch. After durable child identity, ThreadLaunch reads the parent Registrar home through the shared engine: a known home is inherited; a legacy no-home parent remains the named native cohort, with neither refusal nor default. On every rebase, verify this additive contract field and the durable-before-preparation order. | ||
| 11. SQ1's plan-provenance launch carrier is its own protected contract exception: `packages/contracts/src/orchestrationV2.ts:2322-2327` adds additive-optional `sourcePlanRef`; it is not an existing generic field and has no default. `packages/client-runtime/src/operations/commands.ts:152-167,590-596,624-629,669-683`, `apps/server/src/ws.ts`, and `apps/server/src/orchestration-v2/ThreadLaunchService.ts:63-79,548-592` pass it only from the plan→implementation launch. After durable child identity, ThreadLaunch reads the parent Registrar home through the shared engine: a known home is inherited; a legacy no-home parent remains the named native cohort, with neither refusal nor default. Since the Squadron fold ([#412](https://github.com/Jacksondr5/j5code/issues/412)) this launch sends no `squadronId`: the child takes its plan parent's home, or else its project's Squadron (case 10). The client half retires with the ledger migration, when every thread registers at creation and plan→implementation returns to upstream's create-then-start. On every rebase, verify this additive contract field and the durable-before-preparation order. |
There was a problem hiding this comment.
This fallback isn't real. For a parent with no home, ThreadLaunchService returns legacy-plan-child-native and skips registration, so the child stays homeless (missing from Fleet, can't message). Drop ", or else its project's Squadron (case 10)".
There was a problem hiding this comment.
I'm an AI agent (Claude) working for Jackson.
You're right, that fallback is not real. Fixed in 87c5f48 (now 5c97b18): case 11 now says the child takes its plan parent's home, and that a child whose parent has no home stays without one (legacy-plan-child-native). The door table in the PR description says the same.
31b41e4 to
87c5f48
Compare
87c5f48 to
5c97b18
Compare
|
I'm an AI agent (Claude) working for Jackson. Replies to the review points that have no inline thread:
All in |
5c97b18 to
2b56aa5
Compare
|
Warning Review limit reached
This review includes 36 billable files and costs up to $9.00.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 30 minutes for your next included review. View limit detailsLimit details: You’ve used all 3 included reviews currently available. Your 40 included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (36)
Comment |
2b56aa5 to
92e4296
Compare
…ects The Squadron picker, draft chip, headline, first-run gate and Squadron search are removed. A new thread starts in a project, and the server puts it in that project's Squadron. No launch sends a Squadron. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ent-scope paragraph Review follow-up. A plan child of a parent with no home stays without one. Restores upstream's unused test import and names the delete route's limit in D9. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
92e4296 to
90e8d5d
Compare
Merges back to back with #456. Until #456 lands, Create Squadron is still offered and can put a second Squadron on a project, which then refuses new threads. #456 removes those doors and guards the welcome wizard.
Problem
Every new-thread door in J5 asks for a Squadron, and a draft without one cannot send. The plan in #412 retires Squadrons into upstream's projects, so these doors go back to upstream's project versions. #430 made that possible: the server now accepts a launch that names no Squadron and puts the thread in its project's Squadron.
What changed
Fourth PR of the fold stack, on top of #454.
Back to the upstream pin, with no Squadron edit left
routes/_chat.tsx,routes/_chat.index.tsx(both keep only the "J5 Code" branding copy from fix(branding): user-visible copy, marks and branch names say J5 Code #445),routes/welcome.tsxcomponents/chat/ChatHeader.tsx,components/chat/DraftHeroHeadline.tsxcomponents/ChatView.logic.tsand its testBack to the pin, keeping non-Squadron J5 edits
ChatView.tsx: the first-send carrier, draft chip, freeze, environment lock and header Squadron target are removed. Kept: Crew roster gate, playbooks, artifacts panel, persona launch and the persona fan-out refusal.ChatComposer.tsx: the placeholder says "Choose a project above…" again. Persona and playbook edits stay.Sidebar.tsx,Sidebar.logic.ts: the new-thread button, shift-click with its tooltip hint, and the row menu's new-thread-on-branch are upstream's. The Squadron filter, the empty state and Create Squadron stay for the next PR. Archive preflight and card identity stay.hooks/useThreadActionMenu.ts: new-thread-on-branch is upstream's; archive preflight stays.CommandPalette.tsx,CommandPalette.logic.ts: "New thread in…" lists projects, and search has upstream's Projects group in place of Squadrons. Kept: the source picker, the per-environment thread value, and the Add Project carrier that the next PR removes.Launches
squadronId. The server puts the thread in its project's Squadron, creating one named after the project when there is none.refreshAfterThreadLaunchre-reads that thread's home and the Squadron directory. The new thread then shows while a Squadron filter is selected, and a Squadron the launch created appears in the filter.Deleted J5 files
SquadronPicker.logic,SquadronDraftChip,retargetSquadronDraft,FirstRunGate,FirstRunGate.logic,useSquadronNewThreadOnBranch, with their tests.SquadronDraftStatekeeps only the sidebar's ambient scope.Every new-thread door, and what it does now
chat.newshortcutchat.newLocalshortcutBehavior notes
UI changes
Captured by the tester on the base branch and on this PR, with the same data, viewport and theme.
New-thread draft. The headline names the project and opens upstream's project menu; the Squadron chip above the composer is gone.
The draft headline's project menu, open.
Chat header. The project icon and name lead, where the Squadron name did.
Palette, "New thread in…". The list is projects, where it was Squadrons.
Palette search. Results have a Projects group, where they had a Squadrons group.
Sidebar new-thread button's tooltip. The Shift+click hint is back.
One project. The new-thread button opens a draft directly.
Projects exist but no Squadron does. Before: the Create Squadron gate. After: a draft in the most recent project.
No projects. Before: the Create Squadron gate. After: upstream's no-projects screen.
Opening a new thread and choosing its project.
Dark theme and 390px captures of the same states
New-thread draft, dark.
New-thread draft at 390px, light.
New-thread draft at 390px, dark.
Draft headline project menu, dark.
Chat header, dark.
Chat header at 390px, light.
Chat header at 390px, dark.
Palette "New thread in…", dark.
Palette search, dark.
New-thread tooltip, dark.
One project at 390px, light.
One project, dark.
One project at 390px, dark.
Projects with no Squadron at 390px, light.
Projects with no Squadron, dark.
Projects with no Squadron at 390px, dark.
No projects at 390px, light.
No projects, dark.
No projects at 390px, dark.
Limits of this evidence:
Upstream impact
Each file above is upstream-owned. FORK.md changes:
welcome.tsxis upstream's again).Register (
docs/j5/product/upstream.md): D8 no longer lists the doors, headline or placeholder. D9 is rewritten: first run lands in a draft, and the server creates the Squadron. D12 shrinks to the persona refusal. The decision is Jackson's, in the plan for #412.Checklist
FORK.md(case text and file-table row) in this PRdocs/j5/product/upstream.mdAGENTS.md)docs/j5/product/and user docs rewritten where this changes them. The Squadron feature definition is left for the stack's docs PR, per the plan.Surfaces walked
squadronIdlaunch field stays, unused by the web client.Verification
vp test run src/components/ChatView.logic.test.ts src/components/Sidebar.logic.test.ts src/components/CommandPalette.logic.test.ts src/j5/squadron src/j5/onboarding src/j5/threads src/lib/chatThreadActions.test.ts src/commandPaletteBus.test.tsinapps/web: 19 files, 380 tests pass.tsc --noEmitinapps/web: no errors.vp linton the changed files: no errors.Claude Opus 5.5 (1M context), Claude Code harness.
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes