feat(flows-yaml): port slash commands to YAML (/hold /ready /no-ready /unassign /ready-stack) #1099
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!1099
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/flows-yaml-slash-commands"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Closes #1094.
Orphaned
handleSlashCommandOtherinevent-handlers.ts(no production caller, all five commands silently broken) replaced with four YAML flows onissue_comment.created, each gated by acomment_matchesregex andis_trusted_usertrust check.Capability + ops
SlashCommandCapabilityinflows-yaml/types.ts; live + shadow bags wire it;LiveCapabilitiesDepsextended withslashCommandis_trusted_user— wrapsevent-handlers.ts::isTrustedUser(predicate)apply_hold_command— wrapsdeps.ts::applyHoldCommand(cmd=hold|ready)apply_unassign_command— wrapsdeps.ts::applyUnassignCommandapply_ready_stack_command— wrapsevent-handlers.ts::applyReadyStackCommandcomment_matchesbuiltin extended with optionalflagsarg so flows can use'i'for case-insensitivity (legacy parsers usedbody.toLowerCase())Flows
slash-hold.yml— matches^/(?:hold|no-ready)(\s|$)→apply_hold_command(cmd=hold)slash-ready.yml— matches^/ready(\s|$)(excludes/ready-stack) →apply_hold_command(cmd=ready)slash-unassign.yml— matches^/unassign\b→apply_unassign_commandslash-ready-stack.yml— matches^/ready-stack(\s|$)→apply_ready_stack_commandCleanup
handleSlashCommandOtherfromevent-handlers.tsapplyReadyStackCommandexported — backs theapply_ready_stack_commandop (Phase 6 will move it todispatch.ts)flows.schema.json(30 ops now)Test plan
slash-commands.test.tsflow tests cover each command + untrusted-user gate/breakdownflow regression — existing tests still passCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
APPROVED — pending CI
Read the full diff (74 KB, 26 files). Code is correct. CI is still pending so merge will follow the post-CI path once it goes green.
What this does
Replaces the dead
handleSlashCommandOther(had no production caller — all five commands were silently broken) with four YAML flows backed by a cleanSlashCommandCapabilityabstraction. Good layering: trust-gating is explicit at the flow level (is_trusted_userstep +if:gate) rather than inline in a monolithic handler.Correctness checks
Return type wiring ✅
Verified
deps.tssignatures directly:applyHoldCommand→string. Adapter wraps to{ message }. Correct.applyUnassignCommand→Promise<boolean>. Adapter captures asconst cleared = await applyUnassignCommand(...)and returns{ cleared }. Correct (the old caller discarded this return value, so this is an improvement too).Regex fidelity to legacy ✅
/hold+/no-ready: legacy trimmed then checked^/(?:hold|no-ready)(?:\s|$)lowercased; new^\s*/(?:hold|no-ready)(?:\s|$)+iflag is equivalent and handles untrimmed bodies./readyvs/ready-stackdisjunction:(?:\s|$)anchor correctly excludes-stacksuffix./unassign: changed fromstartsWith('/unassign')to^\s*/unassign\b. The\bis slightly more precise (won't match/unassign_bot). Net improvement./ready-stack: straightforward, correct.comment_matchesflags extension ✅Invalid flags silently return
falsevia the existing catch block — documented in the code comment.Shadow capability ✅
isTrustedpasses through to live deps (read-only, correct). All threeapply*methods record intent and return stubs.applyUnassignreturns{ cleared: true }(optimistic shadow stub — fine).Schema sync ✅
Both
apps/server/src/domain/flows-yaml/flows.schema.jsonandapps/web/public/schemas/flows.schema.jsonupdated identically.x-opslist is alphabetically ordered and complete.Test coverage ✅
4 op unit tests (args validation + delegation), 4-flow integration suite, untrusted-user gate verified for hold + unassign.
One minor observation (non-blocking)
The
/ready-stacktest inslash-commands.test.tsis self-labelled "documentation-only":runDefaultFlowskips the file-levelif:predicate, so this test doesn't actually assert the disjunction. The regex is correct and simple enough that it's not a real risk, but a quick unit test forcomment_matches('^\\s*/ready(?:\\s|$)', 'i')against"/ready-stack"would close the gap. Worth noting for a follow-up if slash-command tests ever get extended.Deletions look clean
handleSlashCommandOtherfully removed fromevent-handlers.ts. ✅parseReadyStackCommandimport removed (was only used in the deleted function). ✅clearPrDependenciesandcleanupBranchdead-import cleanup are fine side-effects. ✅resetTriggerBus/setTriggerBusremoved from test imports — the 3271/0 test result confirms nothing else was relying on them. ✅CI pending → will squash-merge automatically once green.