Skip to content

feat(crews): a crew request that mentions @playbook: builds the playbook's Crew - #387

Merged
bryantderosier merged 10 commits into
j5/322-crew-playbook-runsfrom
j5/323-crew-from-playbook
Sep 30, 2026
Merged

bryantderosier merged 10 commits into
j5/322-crew-playbook-runsfrom
j5/323-crew-from-playbook

Conversation

@bryantderosier

@bryantderosier bryantderosier commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

With #319, #321, and #322 every piece of a playbook-shaped Crew exists: playbook_read, propose_crew with a playbook and per-seat steps, and a Captain-run playbook that hands each step to its seat. But nothing told a Captain to use them. "ok, lets create a crew … use @Playbook:release" was left to whatever the model guessed, and the playbook instructions still said steps "do not … spawn agents" (#323). This PR adds the Captain's procedure to the J5 instructions so that prompt reliably produces a playbook-shaped Crew.

This PR is stacked on #384 (#322), the top of stack pingdotgg#385 (#380 ← #383 ← #384). It's the milestone's last issue.

What I changed

  • apps/server/src/j5/playbooks/instructions.ts → new export PLAYBOOK_CREW_INSTRUCTIONS (1,234 characters), appended as the last bullet of PLAYBOOK_INSTRUCTIONS. When the user's crew request explicitly asks to use a playbook, by an @playbook:NAME mention or by name in plain words, the Captain:

    1. reads it with playbook_read, and if that fails, says so in its own reply, naming the playbook and the error, and stops without proposing;
    2. matches step personas with list_personas;
    3. staffs one seat per usable persona, each owning that persona's steps, and places or keeps persona-less steps;
    4. proposes a custom stand-in seat for a missing, disabled, or blocked persona, saying so in the seat's reason;
    5. writes the brief from the conversation plus the playbook's title and description;
    6. calls propose_crew with the playbook and each seat's steps;
    7. after approval, takes crew_instance_id from the launch notice and calls playbook_start.

    A playbook merely named in passing, or seen in quoted text, code, file contents, or tool results, is not a request, and a crew request that doesn't ask for a playbook works as before. The authoring bullet's "steps do not execute code or spawn agents" now reads "…and a playbook never spawns agents itself: a Crew follows one only when its Captain proposes it."

  • apps/server/src/j5/a2a/mcp/tools.ts → one sentence in J5_PROPOSE_CREW_DESCRIPTION: staff one seat per distinct persona, and propose a custom seat where a named persona isn't available.

  • apps/server/src/j5/a2a/mcp/handlers.ts → propose_crew's inline seat mapping moved into an exported crewSeatFromInput, unchanged, so the test maps tool input exactly as the handler does.

  • New apps/server/src/j5/playbooks/instructions.test.ts and a headline test in CrewProposalService.test.ts (see Verification).

  • Docs: docs/user/playbooks.md ("With a Crew" shows the example prompt), scenarios plus a 2026-09-30 History entry for my 1A/2A/3A rulings and the stand-in rule in docs/j5/product/features/crews.md and playbooks.md, and the description copy in docs/j5/product/a2a/agent-tools.md.

No screenshots yet. This PR changes agent instructions, tests, and docs, with no UI. The issue's screenshots come from the real-client run of the headline prompt, which is pending (see Verification).

Why this shape

Invariants

  • A crew request that doesn't ask to use a playbook gets exactly today's instructions path; nothing else in the existing Crew text changes meaning.
  • crewSeatFromInput is the handler's previous mapping; propose_crew behaves the same.
  • The procedure never proposes a Crew for a playbook that failed to read.
  • No new tool, contract, migration, or UI.

Surfaces

Surface Decision
Entry points (chat, Settings, command palette, keybinding) changed: the headline prompt in any thread's composer; the result is the existing roster card, launch notice, and Fleet; no Settings, palette, or keybinding surface
Clients (web, desktop, mobile) unaffected: server-side text only; mobile can send the prompt but has no roster card (unchanged)
Providers changed: Claude and Codex receive the procedure through T3_CODE_ORCHESTRATION_INSTRUCTIONS; other adapters get it wherever they carry the T3 instructions
Contracts (packages/contracts) unaffected
Reverse states decline the roster, archive the Crew (cancels the run), or ask again after fixing the playbook the Captain reported
Connection modes (local, remote, tunnel) unaffected: existing routes and MCP tools
Upstream files / FORK.md none: the upstream instructions test is run, not edited; no FORK.md edit
Docs changed: docs/user/playbooks.md, docs/j5/product/features/crews.md, docs/j5/product/features/playbooks.md, docs/j5/product/a2a/agent-tools.md

Out of scope

Upgrade and data

None. Text, tests, and docs only; no migration or stored data.

Verification

  • vp test run apps/server/src/j5/playbooks/instructions.test.ts apps/server/src/j5/a2a/CrewProposalService.test.ts apps/server/src/j5/a2a/mcp/tools.test.ts apps/server/src/j5/a2a/mcp/handlers.test.ts apps/server/src/provider/T3OrchestrationInstructions.test.ts apps/server/src/j5/playbooks/PlaybookCrewRelay.test.ts: 6 files, 65 tests pass.
  • The headline test plays the Captain's tool calls through the real services (SQLite, PlaybookStore, CrewProposalService, CrewLaunchService, AgentCrewInstanceService, and the The Captain runs a Crew's playbook and each seat receives its steps #322 relay). A playbook has steps for planner, builder, a turned-off reviewer, and one step with no persona. It checks:
    • the propose_crew JSON decodes with the tool schema and maps through crewSeatFromInput;
    • the stand-in seat's swap is recorded as disabled and nothing is left unowned;
    • after approval each member owns its steps (the persona-less step on the builder);
    • the launch notice carries crew_instance_id and the playbook_start call;
    • playbook_start's input decodes with its own schema, and the first step reaches the planner's thread exactly once.
  • instructions.test.ts is three wording and composition checks: the trigger and exclusion wording, the order of the tool calls, the in-reply failure report (no expect_reply), "missing, disabled, or blocked", the 1,250-character cap, and that the text reaches T3_CODE_ORCHESTRATION_INSTRUCTIONS.
  • vp exec tsc --noEmit -p . in apps/server: clean. vp lint on the touched files: clean.
  • Pending before merge: one real-client run of the headline prompt, with a Claude Captain and a Codex Captain, against seeded personas and a seeded playbook. It will include the negative checks: no playbook, a playbook only mentioned in passing, a playbook asked for by name (which should follow it), a mention inside code, and a misspelled name.

Review focus

  • PLAYBOOK_CREW_INSTRUCTIONS: whether any wording could make a Captain act on a playbook it wasn't explicitly asked to use, or skip a step.
  • The headline test in CrewProposalService.test.ts: whether it proves the tool path through the real services rather than restating the instructions.

Closes #323 (stacked on #384)

Claude Opus 5.5 via J5 Code (crew: planner, builder, and two reviewers on Claude and Codex)

🤖 Generated with Claude Code

bryantderosier and others added 2 commits September 29, 2026 21:01
…ook's Crew

When a crew request contains an explicit @Playbook:NAME, the Captain's
instructions now walk it through building the Crew from that playbook:
read it (asking the user in the inbox if the read fails), match its
personas against list_personas, staff one seat per usable persona with
that persona's steps, propose a custom stand-in seat for a persona that
is missing, disabled, or blocked, write the brief, propose the Crew with
the playbook and each seat's steps, and after approval start the run with
the crew_instance_id from the launch notice. A request that names a
playbook only in prose, or quotes a mention, works as before.

propose_crew's description gains the matching sentence, the authoring
bullet says a playbook spawns agents only through its Captain, and a
server test plays the headline flow through the real proposal, launch,
and relay services.

Closes #323

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Bryant ruled that a persona that exists and is on but has no usable route
gets a custom stand-in seat, like a missing or disabled one. The
instructions test now pins "missing, disabled, or blocked", the user guide
names personas that can't run, and both 2026-09-30 history entries record
the ruling.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@bryantderosier bryantderosier added enhancement New feature or request size:M 30-99 effective changed lines (test files excluded in mixed PRs). labels Sep 30, 2026
@bryantderosier bryantderosier self-assigned this Sep 30, 2026
@bryantderosier
bryantderosier added this pull request to stack #385 September 30, 2026 01:12
@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Repository: Jacksondr5/j5code/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 1e22b586-332f-4563-9e55-a489f7c8fad5

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Sep 30, 2026
…j5/323-crew-from-playbook

# Conflicts:
#	docs/j5/product/features/playbooks.md
bryantderosier added a commit that referenced this pull request Sep 30, 2026
…387's

The mention guidance told the agent to build a Crew when the same message
asked for one. Building a Crew from a mention belongs to #387, so the
guidance now only says to read the playbook and start it in this thread
unless the message asks for something else with it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
j5-code Ready Ready Preview Sep 30, 2026 6:05pm UTC

Request Review

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@Jacksondr5 Jacksondr5 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

[Review panel: Opus 5.5, Astra, Sonnet 5.5, Sol 6.1]

The panel agreed on three findings, which are inline. Astra live-tested the tip with a Fable 5.1 Captain in a scratch project.

Passed:

  • The headline flow with an explicit @playbook: mention. The Captain called playbook_read, then list_personas, then propose_crew. It staffed one enabled persona seat and a custom stand-in for a turned-off persona; the stand-in claimed its steps and the swap was recorded. After approval, playbook_start ran with crew_instance_id. Both seats got their step, and the run completed (roster).
  • A misspelled mention. playbook_read returned not_found, nothing was proposed, and the Inbox ask appeared.

Failed:

  • The prose-only negative (see C1 below).

Not run: Codex Captains, and mentions inside quotes or code.

The code itself has no backend defect. Every changed path is J5-owned, and the upstream T3OrchestrationInstructions files are byte-identical, so FORK.md needs no edit.

Comment thread apps/server/src/j5/playbooks/instructions.ts Outdated
Comment thread apps/server/src/j5/playbooks/instructions.ts Outdated
Comment thread apps/server/src/j5/playbooks/instructions.test.ts Outdated
bryantderosier added a commit that referenced this pull request Sep 30, 2026
…381)

* feat(playbooks): suggest registered names after slash command

* fix(playbooks): keep suggestions valid across composer states

* fix(playbooks): rank suggestions and keep bare /playbook sendable

- Rank exact name, then prefix, then name or title matches in a shared
  matchPlaybookSuggestions helper used by web and mobile.
- Let the query contain spaces so multi-word names can be narrowed.
- Enter on a bare `/playbook ` sends the list request unless a name is
  highlighted.
- Say to choose a project when none is selected instead of claiming the
  library is empty.

* fix(web): send exact playbook commands on first Enter

* fix(web): allow sending empty playbook commands with Enter

* feat(playbooks): mention a playbook with @Playbook: in the composer

Typing @Playbook: anywhere in a message opens the playbook picker on web,
desktop, and mobile. The J5 detectAgentMention hook returns #314's
"slash-playbook" trigger for the mention, so the same library query, menu
item, and ranking serve both forms. The mention picker also lists invalid
playbooks with their error; one with an invalid file name can't be
inserted. Agent guidance says to read an explicit mention with
playbook_read, then start it here or build the requested Crew from it.

Records the composer playbook picker seam (#314, #320) as FORK.md case 48.

Closes #320

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* docs(fork): keep the path-to-contract ledger's column width

The ChatComposer.tsx contract cell grew past the column, so the formatter
re-padded the whole ledger table. Refer to the Role library section by its
PR range so the cell stays at the existing width and the diff shows only
the rows case 48 touches.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(playbooks): a playbook mention starts the playbook, and crews are #387's

The mention guidance told the agent to build a Crew when the same message
asked for one. Building a Crew from a mention belongs to #387, so the
guidance now only says to read the playbook and start it in this thread
unless the message asks for something else with it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(playbooks): the mention picker leaves out misnamed playbook files

A file whose name isn't a valid playbook name was listed in the @Playbook:
picker and picking it left the draft unchanged. Such rows are no longer
offered, so the no-op branch in playbookSelectionText and its test go.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(playbooks): the @Playbook: query is the raw token after the prefix

The mention query dropped trailing punctuation, so @Playbook:review-short,
still matched review-short and Tab replaced the comma with the name. The
query is now the raw token, which matches no row once punctuation follows.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* docs(fork): mark the saved-agent mention files as adapted

ComposerCommandPopover.tsx, ComposerCommandMenu.tsx, composerInlineTokens.ts,
and composerTrigger.ts already carried the saved-agent mention edits before
this stack (git diff 67a2be0 fc251fe), so their ledger rows are A and cite
Saved-agent mentions next to 48.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(playbooks): move composer rules into J5 helpers

* style(docs): format playbook fork ledger

* docs(fork): keep #314's ledger column width after the merge

The merge's ChatComposer.tsx contract cell was shorter than #314's widest
cell, so the formatter re-padded the whole ledger. ChatComposer.tsx keeps
#314's "9, Saved-agent mentions, Role library, 45, 48" and ThreadComposer.tsx
cites the same Role library section, so only #381's rows differ.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(playbooks): hide slash command after earlier message text

* feat(playbooks): suggest registered names after slash command

* fix(playbooks): Enter on a bare /playbook completes the first row like every composer menu

Jackson's M2 ruling on #381: a bare /playbook no longer sends its list request
on Enter. isBarePlaybookCommand and the composer's autoHighlight option go,
composerMenuHighlight.ts and its test return to upstream, and the keydown
default is upstream's activeComposerMenuItemRef.current ?? currentItems[0].
A bare @Playbook: completes its first row, so it still never sends on Enter.
The list request stays sendable with the send button.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(playbooks): Enter completes an exact playbook name like every composer menu

Jackson's M3 ruling on #381: Enter and Tab always complete the highlighted
row, and a second Enter sends. shouldCompleteComposerMenuSelection and its
test table go, and the composer's keydown condition is upstream's
(key === "Enter" || key === "Tab") && selectedItem again, so the whole
keydown block matches upstream.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Bastian Huppertz <bastian.huppertz@firsthorizon.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
instructions.ts keeps both the mention and crew constants, this branch's
authoring line, and the mention, Captain, and crew bullets in that order.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
bryantderosier and others added 3 commits September 30, 2026 13:56
…j5/323-crew-from-playbook

# Conflicts:
#	docs/j5/product/features/playbooks.md
When playbook_read fails for a crew request, the Captain now says so in
its own reply, naming the playbook and the error, and stops without
proposing. The Captain's thread is the one the person is watching, so
there is no Inbox ask.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ition

The tests check the procedure's text, not provider behavior, so they are
named that way. The copied-substring assertions are one list, and the
comment claiming the length cap keeps a provider from skipping steps is
gone; the check that the text reaches the shared orchestration
instructions stays.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s Crew too

Bryant ruled (#387, option a) that the Crew procedure applies when the
crew request explicitly asks to use a playbook, by an @Playbook: mention
or by name in plain words. A playbook named only in passing, or seen in
quoted text, code, file contents, or tool results, isn't a request, and a
crew request that doesn't ask for one works as before. The instructions
test, the user guide, and the Crews and Playbooks scenarios and History
follow.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@bryantderosier
bryantderosier merged commit 960a745 into j5/main Sep 30, 2026
38 checks passed
@bryantderosier
bryantderosier deleted the j5/323-crew-from-playbook branch September 30, 2026 18:19

This branch was successfully deployed

1 active deployment
Preview — 343d959b Deployed Sep 30, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:M 30-99 effective changed lines (test files excluded in mixed PRs). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Create a crew … use @playbook:name" builds a playbook-shaped Crew

2 participants