a409671dc6
Phase 09: Batch Operations - 4 plans in 4 waves - 3 autonomous, 1 with checkpoint - Ready for execution Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
189 lines
8.6 KiB
Markdown
189 lines
8.6 KiB
Markdown
---
|
|
phase: 09-batch-operations
|
|
plan: 01
|
|
type: execute
|
|
wave: 1
|
|
depends_on: []
|
|
files_modified: [n8n-workflow.json]
|
|
autonomous: true
|
|
|
|
must_haves:
|
|
truths:
|
|
- "User can type 'update plex sonarr radarr' and bot recognizes multiple containers"
|
|
- "Fuzzy matching finds containers even with partial names"
|
|
- "Exact match gets priority (plex matches plex, not jellyplex)"
|
|
- "Ambiguous matches show disambiguation prompt"
|
|
artifacts:
|
|
- path: "n8n-workflow.json"
|
|
provides: "Batch command parsing and container matching"
|
|
contains: "Parse Batch Command"
|
|
key_links:
|
|
- from: "Parse Batch Command node"
|
|
to: "Match Containers node"
|
|
via: "Parsed action and container names array"
|
|
pattern: "containerNames.*split"
|
|
- from: "Match Containers node"
|
|
to: "disambiguation or execution path"
|
|
via: "Switch based on match results"
|
|
pattern: "needsDisambiguation"
|
|
---
|
|
|
|
<objective>
|
|
Parse multi-container batch commands and match container names with fuzzy matching and exact-match priority.
|
|
|
|
Purpose: Enable batch operations by recognizing commands like "update plex sonarr radarr" and resolving container names accurately.
|
|
Output: Workflow nodes that parse batch commands and match containers, with disambiguation for ambiguous matches.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/home/luc/.claude/get-shit-done/workflows/execute-plan.md
|
|
@/home/luc/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/PROJECT.md
|
|
@.planning/ROADMAP.md
|
|
@.planning/STATE.md
|
|
@.planning/phases/09-batch-operations/09-CONTEXT.md
|
|
@.planning/phases/09-batch-operations/09-RESEARCH.md
|
|
@.planning/phases/08-inline-keyboard-infrastructure/08-01-SUMMARY.md
|
|
@n8n-workflow.json
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Add batch command detection and parsing</name>
|
|
<files>n8n-workflow.json</files>
|
|
<action>
|
|
Add a new branch in the command routing logic to detect batch commands (multiple container names after action keyword).
|
|
|
|
1. In the existing command matching flow (after "Extract Keywords" or equivalent), add a Code node "Detect Batch Command":
|
|
- Input: message text
|
|
- Check if command matches pattern: `{action} {name1} {name2} ...` where action is update/start/stop/restart
|
|
- Parse action and container names array (split by spaces after action keyword)
|
|
- Output: `{ isBatch: boolean, action: string, containerNames: string[], originalMessage: string }`
|
|
- Single container = not batch (handled by existing flow)
|
|
- Two or more containers = batch
|
|
|
|
2. Add an IF node "Is Batch Command" that routes:
|
|
- TRUE: To new batch processing flow (Plan 01-02 nodes)
|
|
- FALSE: To existing single-container flow (preserve current behavior)
|
|
|
|
3. The batch flow should NOT trigger for:
|
|
- "status" (always shows list)
|
|
- "logs {name} {count}" (second word is line count, not container)
|
|
- Commands with only one container name
|
|
|
|
Callback format from context: Existing callbacks use colon-separated format. Batch text commands use space-separated. Keep them distinct.
|
|
</action>
|
|
<verify>
|
|
Test via n8n execution:
|
|
- "update plex sonarr" -> isBatch: true, action: "update", containerNames: ["plex", "sonarr"]
|
|
- "update plex" -> isBatch: false (single container, use existing flow)
|
|
- "logs plex 50" -> isBatch: false (logs has line count parameter)
|
|
- "status" -> Not routed to batch flow
|
|
</verify>
|
|
<done>Batch commands detected and parsed into action + container names array; single-container commands continue to existing flow</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Add container name matching with exact-match priority</name>
|
|
<files>n8n-workflow.json</files>
|
|
<action>
|
|
Add container matching logic that resolves user-provided names to actual container names.
|
|
|
|
1. Add Code node "Match Batch Containers":
|
|
- Input: `containerNames` array from batch parser, `containers` array from Docker API (reuse existing "Get All Containers" HTTP node)
|
|
- For each user-provided name:
|
|
a. Normalize: lowercase, trim whitespace
|
|
b. Check exact match first: `containers.find(c => c.Names[0].replace('/', '').toLowerCase() === normalized)`
|
|
c. If no exact match, check substring match: `containers.filter(c => c.Names[0].toLowerCase().includes(normalized))`
|
|
d. Record match result: { input: "plex", matched: "plex", type: "exact" } or { input: "plex", matches: ["plex", "jellyplex"], type: "ambiguous" }
|
|
- Aggregate results into: `{ allMatched: Container[], needsDisambiguation: { input, matches }[], notFound: string[] }`
|
|
|
|
2. Add IF node "Needs Disambiguation":
|
|
- TRUE (any ambiguous matches): Route to disambiguation message
|
|
- FALSE (all matched or some not found): Continue to batch execution or error
|
|
|
|
3. Add Code node "Build Disambiguation Message" for ambiguous matches:
|
|
- Format: "Multiple matches found:\n- 'plex' could match: plex, jellyplex\nPlease be more specific."
|
|
- Include inline keyboard with exact container names as buttons for user to select
|
|
|
|
4. Add Code node "Build Not Found Message" for completely unmatched names:
|
|
- Format: "Container not found: {name}"
|
|
- Only show if notFound array is not empty and no disambiguation needed
|
|
|
|
Decision from context: "if 'plex' matches both 'plex' and 'jellyplex', user should be able to specify they want only 'plex'" - this is why exact match has priority. If user types exact name, it wins.
|
|
</action>
|
|
<verify>
|
|
Test via n8n execution with mock container list ["plex", "jellyplex", "sonarr", "radarr"]:
|
|
- Input ["plex"] -> exact match "plex", no disambiguation
|
|
- Input ["jelly"] -> ambiguous, matches ["jellyplex"], could ask if they meant jellyplex
|
|
- Input ["plex", "sonarr"] -> both exact match, no disambiguation
|
|
- Input ["notacontainer"] -> notFound: ["notacontainer"]
|
|
</verify>
|
|
<done>Container names resolved with exact-match priority; ambiguous matches show disambiguation; not-found names reported clearly</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 3: Wire batch routing and add "batch stop" confirmation</name>
|
|
<files>n8n-workflow.json</files>
|
|
<action>
|
|
Complete the batch command routing and add confirmation for batch stop operations.
|
|
|
|
1. Wire the routing from "Is Batch Command" TRUE output:
|
|
- Connect to "Get All Containers" (reuse existing node or create duplicate for batch)
|
|
- Then to "Match Batch Containers"
|
|
- Then to "Needs Disambiguation" IF node
|
|
- Disambiguation TRUE -> "Build Disambiguation Message" -> "Send Disambiguation" (HTTP editMessageText or sendMessage)
|
|
- Disambiguation FALSE -> Check action type
|
|
|
|
2. Add Switch node "Route Batch Action":
|
|
- update: Continue to batch execution (Plan 02)
|
|
- start/restart: Continue to batch execution (Plan 02) - immediate, no confirmation
|
|
- stop: Route to confirmation flow (batch stop is dangerous per context)
|
|
|
|
3. Add confirmation flow for batch stop (per context: "Batch stop confirms due to fuzzy matching risk"):
|
|
- Code node "Build Batch Stop Confirmation": "Stop {N} containers?\n\n{list names}\n\n[Confirm] [Cancel]"
|
|
- Callback format: `bstop:confirm:{comma-separated-names}:{timestamp}` or `bstop:cancel`
|
|
- HTTP node to send confirmation message with inline keyboard
|
|
- Add to Route Callback node: handle `bstop:` prefix callbacks
|
|
- On confirm: check 30-second timeout, then continue to batch execution
|
|
- On cancel: return to container list
|
|
|
|
4. Named batch update/start/restart run immediately without confirmation (per context: "Named batches run immediately without confirmation").
|
|
</action>
|
|
<verify>
|
|
Test via n8n execution:
|
|
- "update plex sonarr" -> Matches containers, routes to batch update (output waits for Plan 02)
|
|
- "stop plex sonarr" -> Shows confirmation "Stop 2 containers? plex, sonarr [Confirm] [Cancel]"
|
|
- "start plex sonarr" -> Routes to batch start immediately (no confirmation)
|
|
- Disambiguation keyboard buttons work and re-route correctly
|
|
</verify>
|
|
<done>Batch commands route correctly; batch stop shows confirmation; other batch actions proceed immediately; disambiguation allows user selection</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
1. Workflow imports successfully in n8n
|
|
2. Batch command detection works for all action types
|
|
3. Container matching prioritizes exact matches
|
|
4. Disambiguation shows when multiple fuzzy matches exist
|
|
5. Batch stop shows confirmation dialog
|
|
6. Existing single-container commands still work unchanged
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- "update plex sonarr" parses into batch update for two containers
|
|
- "stop plex sonarr" shows confirmation before executing
|
|
- "plex" exactly matches "plex" even when "jellyplex" exists
|
|
- Ambiguous input like "jelly" prompts for clarification
|
|
- Single-container commands route to existing flow (no regression)
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/09-batch-operations/09-01-SUMMARY.md`
|
|
</output>
|