Repository navigation
feat(crews): custom seats default to Full access and the roster flags seats that will stop - #347
Merged
Merged
Conversation
A Crew proposal now resolves exactly once, open to approved or declined, by compare-and-set under a per-proposal lock. The claimed states, reopen, and the boot sweep for lost claims are gone; migration 021 hands any leftover approving or declining row back as open. Once seats start spawning, a seat that fails does not stop the others. A seat whose thread was never created is dropped from the roster and the launch report names it on a seat_not_created line; a seat whose brief never went out reports not_started. The web launch card shows both. Closes #311 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The migration 021 test this branch adds still called NodeSqliteClient.layerMemory(), which the sync replaced with NodeSqliteClient.layer({ filename: ":memory:" }).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The upstream sync's Badge lint (shadcn/no-restyle) refuses spacing and typography classes on <Badge>; the not-created row now uses size="sm" like the roster rows beside it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The sidebar expander dropped any Crew seat whose thread was not in client state, and the Fleet page grouped a Crew only from placed participants, so a Crew could under-count or vanish while its seats were unknown. The spawned-children read now gives a Captain's row every seat on its live rosters that no parent holds, and the Fleet read emits a thread-less row for a roster seat the ledger never recorded. The sidebar keeps a seat with no thread as an unknown row, and the Fleet tree hangs an unplaced seat under its Captain, so both summaries count every seat. Closes #227 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There is never a Crew without its Captain. The Captain cascade already retired a Captain's live Crews on archive or delete; it now also brings back the Crews that retired with it when the Captain is unarchived, seat threads included, and sends a Captain's settle or unsettle to every seat of its live Crews. Unsettle reaches only seats that were settled, so a seat that never settled keeps upstream's automatic settlement. Migration 022 records whether a Crew retired with its Captain, so a Crew retired on its own through archive_crew or Archive crew stays retired. The boot sweep also settles the seats of a settled Captain and restores Crews under a Captain that is live again. A seat is still never archived on its own. Closes #312 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The upstream sync withheld the archive Undo notice whenever an archive might retire a Captain's Crews (decision #7, 2026-09-24), because unarchiving the Captain did not bring them back. With this branch it does: the Crews that retired with their Captain return with its unarchive. So the undoable plumbing is gone, useThreadActions.archiveThread is upstream's again, and the Sidebar, header menu, and LegacySidebar doors call it as upstream does. Refs #312 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…th their own ids The Captain cascade derived each seat's archive command ids from the Captain and the Crew alone, so archive, unarchive, then archive again reused the first archive's ids: the orchestrator replayed the old receipt, the seat stayed unarchived, and the Crew stayed live under an archived Captain. The retire request key now carries the occurrence, the triggering event id on the stream and the Captain's archive or delete time on the boot sweep. Each Crew step runs once and logs its failure with the cause; the two in-session retry loops are gone. The boot sweep keeps only its retire leg for Crews of an archived or gone Captain; its settle and restore legs are removed, so unarchive, settle, and unsettle have no restart recovery. A Captain's settle skips a seat with a pending runtime request, a live run, or background work, mirroring upstream's isAutoSettlementCandidate through threadShellFromProjection. Seat reads use getThreadProjectionIfPresent, so only a genuine not-found skips a seat and any other failure fails the step. Refs #312 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Crews AC18 now reads that J5 never settles a seat because its run finished, settling the Captain settles its seats, and upstream's settle rules apply to every thread; the Definition says the same. The docs no longer claim the boot sweep settles or restores Crews, say that Undo and unarchive don't restore interrupted runs or dropped Exchanges, and give the repair for an unarchive that stops partway. The retired Crew roster shows why each seat joined, since it records no approver, and the Fleet page history records the AC28 change. FORK.md's useThreadActionMenu row points at case 21, which now names the file and describes the cascade's run-once steps and retire-only sweep. Refs #312 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
FORK.md's proposal-flow paragraph still described the retry model this PR removes (the handed-back gate, converging retries, a decline that archives spawned seats) and listed migration 16's claims as current. It now says a proposal resolves once before any seat spawns and names migration 21. The agent-tools page gains its History line for the change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… seats that will stop A custom Crew seat with no runtime_mode now runs in Full access instead of inheriting the Captain's access, so a supervised Captain no longer hands approval prompts to seats in threads nobody is watching. Model, harness, and reasoning still come from the Captain; saved-persona seats keep their policy. The roster and addition card marks each seat that will stop for approvals (anything short of Full access, other than a persona on its own sandboxed policy) and counts them above the approve button. Tool descriptions, the standing Crew instructions, and the Crew and persona docs say the new default. Closes #326 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bryantderosier
requested review from
BastiHu,
Jacksondr5 and
tyler-barton-horizon
September 28, 2026 15:23
bryantderosier
added this pull request to stack #280
September 28, 2026 15:24
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Repository: Jacksondr5/j5code/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: Comment |
This was referenced Sep 28, 2026
bryantderosier
added a commit
that referenced
this pull request
Sep 29, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflicts: FORK.md takes main's proposal-flow paragraph with this branch's Full-access default for custom seats; crews.md keeps this branch's Definition sentence and adds #348's rule that seats ask their Captain, and keeps both 2026-09-26 History lines. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bryantderosier
added a commit
that referenced
this pull request
Sep 29, 2026
Conflicts: AC3 keeps #347's approval flag and adds this branch's preview-binding sentence; the personas guide keeps #301's and #347's text and adds the preview and ACP sentences, now in #344's access-mode names (Supervised, Auto-accept edits); both 2026-09-24 History lines stay. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bryantderosier
added a commit
that referenced
this pull request
Sep 29, 2026
Conflicts: agent-tools.md takes main's quoted propose_crew and request_crew_member descriptions and tables, which match the shipped strings after #347; crews.md takes main's Definition (Full access default, seats ask their Captain) with this branch's no-approver roster wording, and History keeps one date-ordered list with #301's and #307's 2026-09-24 lines. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
This PR is part of the Crews stack. Merge top to bottom, one at a time, and let each land on
j5/mainbefore the next. Everything before this PR has merged, so it can go next.fix(crews): Crew notices report only what the platform measured #292: Crew notices report only what the platform measured (adds migration 020)✅ mergedfix(crews): no seat launches into a retired Crew or under a gone Captain #271: No seat launches into a retired Crew or under a gone Captain✅ mergedfix(crews): unit stop and archive finish over a seat that was never created #279: Unit stop and archive finish over a seat that was never created✅ mergedfix(crews): a proposal launches once and reports every seat #313: A proposal launches once and reports every seat (adds migration 021)✅ mergedfix(crews): Crew groups keep seats without thread facts as unknown #300: Crew groups keep seats without thread facts as unknown✅ mergedfix(crews): J5 stream daemons start from the event store's high-water mark #352: J5 stream daemons start from the event store's real high-water mark (fixes fix(crews): J5 stream daemons replay all history on every boot (high-water reads an empty table) #349)✅ mergedfix(crews): a Crew follows its Captain through every lifecycle step #315: A Crew follows its Captain through every lifecycle step (adds migration 022)✅ mergedWhy #352 goes first: without it the finish notifier's stream starts at sequence 0 and replays every event on boot. #315's cascade also acts on
thread.unarchived,thread.settled, andthread.unsettled, so a restart would settle, unsettle, and restore Crews from history (#349).Problem
A custom Crew seat with no
runtime_modeinherited its Captain's access. A Captain you supervise in Supervised mode handed that mode to every seat it didn't configure, and those seats stopped for approvals in threads nobody watches (#326).What I changed
apps/server/src/j5/a2a/CrewLaunchService.ts→resolveSeats: an unset custom seat resolves tofull-access. Model, harness, and reasoning still come from the Captain. Saved-persona seats keep their persona's policy. The Captain-access lookup is gone.apps/web/src/j5/crew/crewSeatRuntime.ts→crewSeatStopsForApprovals: flags a seat whose resolved access isn't Full access. It skips a seat whose runtime hasn't loaded, and a saved persona left on its own policy.apps/web/src/j5/crew/CrewProposalCard.tsx: flagged seats get aStops for approvalsbadge, with a line above the buttons ("N seats will stop for approvals in their own threads"). The card serves both the roster gate and the Inbox addition card.apps/server/src/j5/a2a/mcp/tools.ts: thepropose_crew/request_crew_memberdescriptions and field descriptions now say access defaults to Full access.apps/server/src/provider/T3OrchestrationInstructions.ts(upstream, existing FORK.md case 8): the "Custom seats inherit your configuration" clause is reworded to match.crews.md(Definition, AC3, History),agent-tools.md(description copies re-synced with the shipped strings, seat tables listmodel_selectionandruntime_mode, History), anddocs/user/personas.md.Screenshots
Both use the same seeded roster proposal on an isolated copy of real data, light theme, 1440×1000. The Captain runs in Supervised.
code-reviewersets no access,docs-writerasks for Supervised, andtest-authorasks for Auto-accept edits. Before isj5/main; #315, this PR's base, doesn't change the roster card.Before:
code-reviewerinherits the Captain's Approval required, and nothing says which seats will stop.After:
code-reviewerdefaults to Full access. The two seats that will stop carry "Stops for approvals", and the footer counts them.Why this shape
This is Jackson's decision on #326. Leaving it to each Captain to set access well is a footgun, because there are several ways a seat ends up in a mode that stops. The person still picks any seat's access on the card before approving. The warning is per seat, from the same resolved runtime the preview shows, so it can't disagree with the card.
Invariants
runtime_modealways wins.Surfaces
packages/contracts)T3OrchestrationInstructions.tsunder existing case 8; FORK.md updated.Out of scope
Upgrade and data
No migration. A proposal previewed before the upgrade and approved after it gets a token mismatch, because its resolved access changed, and the card asks for a fresh preview.
Verification
apps/server,apps/web, andpackages/contractstypecheck (exit 0).vp test run apps/server/src/j5 apps/web/src/j5plus the orchestration-instructions test: 1,054 passed, 1 skipped.crewSeatStopsForApprovalscovers custom, persona, persona-default, and not-yet-loaded seats.UI evidence: before/after screenshots of the roster card are under What I changed.
Review focus
Closes #326
Claude Opus 5.5 via Claude Code in J5 Code
🤖 Generated with Claude Code