Repository navigation
feat(playbooks): mention a playbook with @playbook: in the composer - #381
Conversation
- 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.
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>
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>
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: Jacksondr5/j5code/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (28)
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe change adds ChangesPlaybook composer
Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
actor User
participant ChatComposer
participant detectComposerTrigger
participant PlaybookLibraryQuery
participant playbookMenuItems
participant ComposerCommandMenu
User->>ChatComposer: Type a slash-playbook query
ChatComposer->>detectComposerTrigger: Detect the current composer trigger
detectComposerTrigger-->>ChatComposer: Return trigger kind and query
ChatComposer->>PlaybookLibraryQuery: Load playbooks for the selected project
ChatComposer->>playbookMenuItems: Build suggestions from query results
playbookMenuItems-->>ComposerCommandMenu: Return playbook menu items
User->>ComposerCommandMenu: Select a playbook
ComposerCommandMenu->>ChatComposer: Apply playbook selection text
Merge Risk: 🔵 Low · up to Mergeable with a bounded follow-up: drafts targeting another worktree can show the project root’s playbooks instead. Users can enter known playbook names manually. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to Existing access and ownership checks limit playbook execution. However, drafts can discover playbooks from a different worktree than the one used for execution, and the required read-first operation is unavailable in this revision. These are bounded risks; no privilege escalation was established. Retained concerns
Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
Full details: Linked Issues checkExplanation The PR implements the shared Resolution Update Full details: Docstring CoverageExplanation Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 25 files. (2 skipped: 2 unsupported.)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
⚔️ Resolve merge conflicts 💡
🧪 Generate unit tests (beta)
Comment |
Jacksondr5
left a comment
There was a problem hiding this comment.
[Review panel: Opus 5.5, Sonnet 5.5, Sol 6.1]
Three findings are inline. Reusing #314's picker through detectAgentMention is the right minimal shape, and the panel's live passes found the picker, plain @ file and thread mentions, and single-agent delivery all working.
Noted, not a finding: this PR conflicts with #380 in instructions.ts and docs/user/playbooks.md, and relies on #380 for playbook_read.
…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>
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>
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>
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>
…icker Merges origin/codex/playbook-slash-suggestions (962b7dd, aca8f4d) into j5/playbook-mention. ChatComposer.tsx takes #314's rules through one J5 check: Tab always completes, a bare /playbook sends on Enter, and an exact name sends via shouldCompleteComposerMenuSelection, while a bare @Playbook: never sends (key !== "Tab" && isBarePlaybookCommand). An exact mention sends on Enter like an exact command. FORK.md case 48 covers #314's detector delegation and #381's mention picker, chips, and keys; each ledger file is listed once with its mode and contracts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Merges origin/codex/playbook-slash-suggestions (5eb1b0c, 5b8fc4d), which brings j5/main's restructured FORK.md ledger. FORK.md takes #314's side and re-applies only #381's changes: 49 cases, the playbook-chip note on the saved-agent composer row, the combined case 48, and the ledger modes and contracts for the composer files (plus composerInlineTokens.ts). The mobile upstream-seam test gains the case 48 playbook picker seam in use-composer-command-menu.ts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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>
…ion picker Merges origin/codex/playbook-slash-suggestions (6049bac, e2f4f4f). Import lists in ChatComposer.tsx, use-composer-command-menu.ts, and playbooks.test.ts take both sides; isPlaybookSlashCommandVisible hides the built-in /playbook after earlier text while the @Playbook: rules stay in the J5 helpers. j5/main's peering case took 48, so the playbook picker is case 49: FORK.md takes #314's side and re-applies only #381's rows under 49, and the mobile seam row's record follows. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Jacksondr5
left a comment
There was a problem hiding this comment.
[Coordinator-relayed: Jackson's decisions, checked by Review panel: Opus 5.5]
Jackson ruled on the panel's two open decisions. Both remove behavior #314 brought to j5/main. This PR already rewrites those lines, so the panel recommends removing both here rather than in a follow-up.
M2: drop "bare /playbook + Enter sends the list request"
With it gone, Enter on a bare /playbook completes the first row, like every other composer menu. Remove:
packages/client-runtime/src/j5/playbooks.ts:339-343:isBarePlaybookCommand, and its test atplaybooks.test.ts:584-593.ChatComposer.tsx:- the import at line 60;
- the comment and
composerMenuAutoHighlightat 2781-2782; autoHighlight: composerMenuAutoHighlightat 2789 and 3414;- the
composerMenuAutoHighlightdeps at 2795 and 3425; - the keydown default at 4422-4426, back to upstream's
activeComposerMenuItemRef.current ?? currentItems[0].
- Upstream
apps/web/src/components/chat/composerMenuHighlight.ts:6-7,21: revert to upstream, so line 21 readsreturn input.items[0]?.id ?? null;. Also delete the"leaves nothing active without a highlight when auto-highlight is off"test atcomposerMenuHighlight.test.ts:19-35. Nothing else uses this option; theautoHighlightprops inComposerCommandMenu.tsxand elsewhere belong to upstream'sCommandcomponent. - FORK.md:
- drop the ledger rows for
composerMenuHighlight.tsandcomposerMenuHighlight.test.ts; - in case 49 "Keys", drop the
autoHighlightsentence, the bare-list clause, and theisBarePlaybookCommandsentence; - in "Rebase checks", drop
composerMenuHighlight.test.ts.
- drop the ledger rows for
- Keep
expandPlaybookPrompt's list branch. A bare/playbookis still sendable with the send button (and on mobile), or when no playbook matches, so thedocs/user/playbooks.md:50wording stays true.
M3: drop "Enter sends an exact name instead of completing"
Follow upstream: Enter and Tab always complete the highlighted item, and a second Enter sends. Remove:
packages/client-runtime/src/j5/playbooks.ts:259-274:shouldCompleteComposerMenuSelection, and its test table atplaybooks.test.ts:595-618.ChatComposer.tsx: the import at line 64, and the condition at 4435-4437, back to upstream'sif ((key === "Enter" || key === "Tab") && selectedItem) {.- FORK.md case 49 "Keys": drop the "Enter sends … an exact name (
shouldCompleteComposerMenuSelection, J5)" clause.
After both, the keydown block in ChatComposer.tsx matches upstream again, and composerMenuHighlight.ts leaves the ledger.
No change on mobile. Its popover has no Enter handling for this, and #314's slash-playbook popover visibility is unaffected.
…e 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>
…poser 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>
|
@Jacksondr5 applied both rulings in this PR:
The |
instructions.ts keeps the persona authoring line and appends #381's mention bullet. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
instructions.ts keeps #381's mention bullet and this branch's Captain delivery bullet. 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>
Problem
There was no way to name a playbook inside a message.
/playbookonly works at the start of a message and means "start it here", so "create a crew … use this playbook" had no way to say which one (#320). This PR adds@playbook:<name>anywhere in the composer on web, desktop, and mobile, and tells agents what an explicit mention means.This PR is stacked on #314, which adds the
/playbookname picker that this reuses. It merges after #314 and #380 (#319, which adds theplaybook_readtool the guidance names).What I changed
packages/shared/src/j5/playbookMention.ts→PLAYBOOK_MENTION_PREFIX,playbookMentionReplacement, anddetectPlaybookMention. The detector returns feat(playbooks): suggest registered names after slash command #314's"slash-playbook"trigger kind for any@playbook:token. The query is the raw token after the prefix, so punctuation typed after a name stays in the query.packages/shared/src/j5/agentMention.ts→detectAgentMention, already called at token level by both upstream detectors, tries the playbook mention before the persona one. NewisJ5MentionPathkeeps unquotedpersona:andplaybook:tokens out of file chips. The playbook helpers are re-exported here, so there's no new package export.packages/client-runtime/src/j5/playbooks.ts→playbookMenuItems,playbookSelectionText, andisPlaybookMention, next to feat(playbooks): suggest registered names after slash command #314'smatchPlaybookSuggestions. The/playbookform still returns feat(playbooks): suggest registered names after slash command #314's ranking exactly.apps/server/src/j5/playbooks/instructions.ts→ aPLAYBOOK_MENTION_INSTRUCTIONSbullet insidePLAYBOOK_INSTRUCTIONS. An explicit@playbook:NAMEmeans: callplaybook_read(NAME)first; unless the message asks for something else with it, start it in this thread. Mentions in quoted text, code, or file contents are references. Building a Crew from a mention is feat(crews): a crew request that mentions @playbook: builds the playbook's Crew #387's.docs/user/playbooks.md→ one paragraph after the/playbookone.ChatComposer.tsx: import, items, selection. The keydown block andcomposerMenuHighlight.tsare upstream's again (Jackson's rulings M2/M3), so Enter and Tab complete the highlighted row and a second Enter sends.use-composer-command-menu.ts: import, items, selection.packages/shared/src/composerInlineTokens.ts: one line so@playbook:xnever becomes a file chip.Before (#314's head:
@playbook:falls through to the file search):After (the playbook picker; invalid playbooks are listed after the valid ones, with their error). Since review, rows for misnamed files are left out of the picker:
Why this shape
"slash-playbook"kind through the J5 detector that both upstream detectors already call. So there's one library query, one item type, and no new upstream detector line. The alternatives were reusing the@persona:seam (it would duplicate feat(playbooks): suggest registered names after slash command #314's query and ranking) or a new trigger kind (about 12 upstream lines instead of about 6).@playbook:Release Notesisn't a valid mention and the composer menus have no disabled state; its rename hint shows in Settings. feat(playbooks): suggest registered names after slash command #314's/playbookpicker keeps hiding invalid entries.docs/user/playbooks.md. The upstreamdocs/user/composer.mddoesn't document@persona:either, so I left it alone.Invariants
/playbookcommand form keeps feat(playbooks): suggest registered names after slash command #314's items and ranking. Enter and Tab complete the highlighted row like every composer menu, including a bare/playbookor an exact name, and a second Enter sends. A bare/playbookis still sendable with the send button.@playbook:, so picking a row never removes text the user typed after it.@playbook:text is always plain editable text, never a file chip, on web and mobile./playbookshare one library query per composer, including new-thread drafts (feat(playbooks): suggest registered names after slash command #314's project and thread inputs).Surfaces
ChatComposer, mobile command menupackages/contracts)docs/user/playbooks.mdOut of scope
@playbook:from a bare@.Upgrade and data
None. No contracts, migrations, or persisted state.
Verification
vp test run packages/shared/src/j5/playbookMention.test.ts packages/shared/src/j5/agentMention.test.ts packages/client-runtime/src/j5/playbooks.test.ts apps/mobile/src/features/threads/use-composer-command-menu.test.ts apps/web/src/composer-logic.test.ts apps/web/src/components/chat/composerMenuHighlight.test.ts apps/server/src/provider/T3OrchestrationInstructions.test.ts packages/shared/src/j5/playbookTrigger.test.ts apps/mobile/src/j5/upstreamSeams.test.ts: 194 tests pass.composerMenuHighlight.tsand its test match upstream again.@persona:detection unchanged;@playbook:;@playbook:offers rows, so Enter completes the first instead of sending;/playbook debstill completing as before.vp exec tsc --noEmit -p .inpackages/shared,packages/client-runtime,apps/web,apps/mobile, andapps/server: clean.vp linton the touched files: 0 errors. The 45 warnings inChatComposer.tsxanduse-composer-command-menu.tsare the same set as on feat(playbooks): suggest registered names after slash command #314's head.Review focus
ChatComposer.tsxandresolveComposerCommandSelection. The keydown block should now match upstream exactly.Closes #320 (stacked on #314)
Claude Opus 5.5 via J5 Code (crew: planner, builder, and two reviewers on Claude and Codex)
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
/playbook, or reference one by name with@playbook:./playbookcommand to send it without selecting a suggestion.Documentation