Files
Lucas Berger a409671dc6 docs(09): create phase plan
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>
2026-02-03 21:01:06 -05:00

8.6 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves
phase plan type wave depends_on files_modified autonomous must_haves
09-batch-operations 01 execute 1
n8n-workflow.json
true
truths artifacts key_links
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
path provides contains
n8n-workflow.json Batch command parsing and container matching Parse Batch Command
from to via pattern
Parse Batch Command node Match Containers node Parsed action and container names array containerNames.*split
from to via pattern
Match Containers node disambiguation or execution path Switch based on match results needsDisambiguation
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.

<execution_context> @/home/luc/.claude/get-shit-done/workflows/execute-plan.md @/home/luc/.claude/get-shit-done/templates/summary.md </execution_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 Task 1: Add batch command detection and parsing n8n-workflow.json 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. 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 Batch commands detected and parsed into action + container names array; single-container commands continue to existing flow
Task 2: Add container name matching with exact-match priority n8n-workflow.json 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. 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"] Container names resolved with exact-match priority; ambiguous matches show disambiguation; not-found names reported clearly
Task 3: Wire batch routing and add "batch stop" confirmation n8n-workflow.json 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"). 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 Batch commands route correctly; batch stop shows confirmation; other batch actions proceed immediately; disambiguation allows user selection
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

<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>
After completion, create `.planning/phases/09-batch-operations/09-01-SUMMARY.md`