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>
This commit is contained in:
+12
-4
@@ -66,9 +66,9 @@ Plans:
|
|||||||
**Plans:** 3 plans
|
**Plans:** 3 plans
|
||||||
|
|
||||||
Plans:
|
Plans:
|
||||||
- [ ] 08-01-PLAN.md — Container list keyboard and submenu navigation
|
- [x] 08-01-PLAN.md — Container list keyboard and submenu navigation
|
||||||
- [ ] 08-02-PLAN.md — Action execution and confirmation flow
|
- [x] 08-02-PLAN.md — Action execution and confirmation flow
|
||||||
- [ ] 08-03-PLAN.md — Progress feedback and completion messages
|
- [x] 08-03-PLAN.md — Progress feedback and completion messages
|
||||||
|
|
||||||
**Success Criteria:**
|
**Success Criteria:**
|
||||||
1. Status command returns a message with inline buttons showing available actions per container
|
1. Status command returns a message with inline buttons showing available actions per container
|
||||||
@@ -87,6 +87,14 @@ Plans:
|
|||||||
|
|
||||||
**Requirements:** BAT-01, BAT-02, BAT-03, BAT-04, BAT-05, BAT-06
|
**Requirements:** BAT-01, BAT-02, BAT-03, BAT-04, BAT-05, BAT-06
|
||||||
|
|
||||||
|
**Plans:** 4 plans
|
||||||
|
|
||||||
|
Plans:
|
||||||
|
- [ ] 09-01-PLAN.md — Batch command parsing and container matching
|
||||||
|
- [ ] 09-02-PLAN.md — Sequential batch execution with progress feedback
|
||||||
|
- [ ] 09-03-PLAN.md — "Update all" and inline multi-select
|
||||||
|
- [ ] 09-04-PLAN.md — Verification and testing
|
||||||
|
|
||||||
**Success Criteria:**
|
**Success Criteria:**
|
||||||
1. User can type "update plex sonarr radarr" and all three containers update sequentially
|
1. User can type "update plex sonarr radarr" and all three containers update sequentially
|
||||||
2. Each container shows individual progress/result as it completes (not waiting until all finish)
|
2. Each container shows individual progress/result as it completes (not waiting until all finish)
|
||||||
@@ -136,7 +144,7 @@ Plans:
|
|||||||
|-------|------|--------------|--------|
|
|-------|------|--------------|--------|
|
||||||
| 6 | n8n API Access | API-01, API-02, API-03, API-04 | Complete |
|
| 6 | n8n API Access | API-01, API-02, API-03, API-04 | Complete |
|
||||||
| 7 | Socket Security | SEC-01, SEC-02, SEC-03, SEC-04 | Complete |
|
| 7 | Socket Security | SEC-01, SEC-02, SEC-03, SEC-04 | Complete |
|
||||||
| 8 | Inline Keyboard Infrastructure | KEY-01, KEY-02, KEY-03, KEY-04, KEY-05 | Pending |
|
| 8 | Inline Keyboard Infrastructure | KEY-01, KEY-02, KEY-03, KEY-04, KEY-05 | Complete |
|
||||||
| 9 | Batch Operations | BAT-01, BAT-02, BAT-03, BAT-04, BAT-05, BAT-06 | Pending |
|
| 9 | Batch Operations | BAT-01, BAT-02, BAT-03, BAT-04, BAT-05, BAT-06 | Pending |
|
||||||
| 10 | Polish & Audit | UNR-01, ENV-01, ENV-02, WEB-01 | Pending |
|
| 10 | Polish & Audit | UNR-01, ENV-01, ENV-02, WEB-01 | Pending |
|
||||||
| 11 | Documentation Overhaul | TBD | Pending |
|
| 11 | Documentation Overhaul | TBD | Pending |
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
---
|
||||||
|
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>
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
---
|
||||||
|
phase: 09-batch-operations
|
||||||
|
plan: 02
|
||||||
|
type: execute
|
||||||
|
wave: 2
|
||||||
|
depends_on: [09-01]
|
||||||
|
files_modified: [n8n-workflow.json]
|
||||||
|
autonomous: true
|
||||||
|
|
||||||
|
must_haves:
|
||||||
|
truths:
|
||||||
|
- "Batch operations execute sequentially, not in parallel"
|
||||||
|
- "Each container shows progress as it completes"
|
||||||
|
- "One container failure does not abort remaining batch"
|
||||||
|
- "Final message shows summary with failures emphasized"
|
||||||
|
artifacts:
|
||||||
|
- path: "n8n-workflow.json"
|
||||||
|
provides: "Sequential batch execution with error handling"
|
||||||
|
contains: "Loop Over Items"
|
||||||
|
key_links:
|
||||||
|
- from: "Loop Over Items node"
|
||||||
|
to: "Execute Container Action"
|
||||||
|
via: "Single item per iteration (batch size 1)"
|
||||||
|
pattern: "batchSize.*1"
|
||||||
|
- from: "Error handler"
|
||||||
|
to: "Continue loop"
|
||||||
|
via: "Log failure, increment counter, proceed"
|
||||||
|
pattern: "failureCount"
|
||||||
|
- from: "Batch summary"
|
||||||
|
to: "Telegram editMessageText"
|
||||||
|
via: "Formatted result with failure details"
|
||||||
|
pattern: "Failed.*reason"
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Implement sequential batch execution with per-container progress, error isolation, and failure-emphasized summaries.
|
||||||
|
|
||||||
|
Purpose: Enable multi-container operations that don't fail entirely when one container has issues.
|
||||||
|
Output: Loop Over Items execution pattern with progress updates and actionable error reporting.
|
||||||
|
</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/09-batch-operations/09-01-SUMMARY.md
|
||||||
|
@n8n-workflow.json
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Add Loop Over Items for sequential batch execution</name>
|
||||||
|
<files>n8n-workflow.json</files>
|
||||||
|
<action>
|
||||||
|
Implement the sequential execution loop for batch operations.
|
||||||
|
|
||||||
|
1. After "Route Batch Action" (from Plan 01), add Code node "Initialize Batch State":
|
||||||
|
- Input: matched containers array, action type, chat_id, message_id (for editing)
|
||||||
|
- Output batch state object:
|
||||||
|
```javascript
|
||||||
|
return {
|
||||||
|
json: {
|
||||||
|
containers: $json.allMatched, // Array of container objects
|
||||||
|
action: $json.action, // 'update', 'start', 'stop', 'restart'
|
||||||
|
totalCount: $json.allMatched.length,
|
||||||
|
successCount: 0,
|
||||||
|
failureCount: 0,
|
||||||
|
warningCount: 0,
|
||||||
|
results: [], // Array of { name, status: 'success'|'error'|'warning', reason? }
|
||||||
|
chatId: $json.chatId,
|
||||||
|
messageId: $json.messageId,
|
||||||
|
currentIndex: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add HTTP node "Send Batch Start Message":
|
||||||
|
- POST to Telegram sendMessage (new message, not edit - we'll edit this one during progress)
|
||||||
|
- Text: "Starting batch {action} for {N} containers..."
|
||||||
|
- Save message_id from response for progress edits
|
||||||
|
|
||||||
|
3. Add Loop Over Items node "Batch Loop":
|
||||||
|
- Input: containers array
|
||||||
|
- Batch Size: 1 (critical - sequential execution)
|
||||||
|
- Output: Single container per iteration
|
||||||
|
|
||||||
|
4. For each iteration, the loop should:
|
||||||
|
- Edit progress message with current container name
|
||||||
|
- Execute the action (reuse existing action execution nodes where possible)
|
||||||
|
- Handle success or error
|
||||||
|
- Update counters and results array
|
||||||
|
- Continue to next item
|
||||||
|
|
||||||
|
5. Important: Use n8n's "Continue On Fail" option on HTTP Request nodes within the loop so one failure doesn't abort the whole batch.
|
||||||
|
|
||||||
|
Note from RESEARCH: n8n Loop Over Items with "Continue (using error output)" has known issues. Use HTTP Request's "Continue On Fail" and check status code in subsequent Code node instead.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
Test with mock batch of 3 containers:
|
||||||
|
- Loop executes 3 times (one per container)
|
||||||
|
- Batch state tracks progress correctly
|
||||||
|
- Initial message is sent before loop starts
|
||||||
|
</verify>
|
||||||
|
<done>Sequential loop executes containers one at a time with batch state tracking</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Add per-container progress updates and action execution</name>
|
||||||
|
<files>n8n-workflow.json</files>
|
||||||
|
<action>
|
||||||
|
Wire action execution within the loop with progress feedback.
|
||||||
|
|
||||||
|
1. Inside the loop, add Code node "Build Progress Message":
|
||||||
|
- Input: current container, batch state
|
||||||
|
- Output message text:
|
||||||
|
```
|
||||||
|
Batch {action} in progress...
|
||||||
|
|
||||||
|
Current: {containerName}
|
||||||
|
Progress: {current}/{total}
|
||||||
|
|
||||||
|
Success: {successCount}
|
||||||
|
Failed: {failureCount}
|
||||||
|
```
|
||||||
|
- Rate limit consideration: Only edit message every container (small batches <5). For larger batches, research suggests editing every 3-5 items, but since typical batch is 2-5 containers, edit every time is fine.
|
||||||
|
|
||||||
|
2. Add HTTP node "Edit Progress Message":
|
||||||
|
- POST to Telegram editMessageText
|
||||||
|
- Use saved progress_message_id from batch start
|
||||||
|
- parse_mode: HTML
|
||||||
|
|
||||||
|
3. Add Switch node "Route Batch Loop Action" (within loop):
|
||||||
|
- update: Execute full update flow (pull image, check digest, stop, remove, create, start)
|
||||||
|
- start: Execute container start
|
||||||
|
- stop: Execute container stop
|
||||||
|
- restart: Execute container restart
|
||||||
|
|
||||||
|
4. For each action type, wire to existing action execution nodes where possible:
|
||||||
|
- Start: Can reuse "Execute Immediate Action" from Phase 8 or create dedicated "Execute Batch Start"
|
||||||
|
- Stop/Restart: Similar reuse pattern
|
||||||
|
- Update: This is complex - need to execute the full update sequence per container
|
||||||
|
|
||||||
|
5. Add Code node "Handle Action Result" after each action execution:
|
||||||
|
- Check HTTP response status or exec output
|
||||||
|
- Determine success/error/warning:
|
||||||
|
- Success: Container action completed normally
|
||||||
|
- Warning: "Already stopped", "No update available", "Already running"
|
||||||
|
- Error: Network error, timeout, pull failed, etc.
|
||||||
|
- Update batch state: increment appropriate counter, add to results array
|
||||||
|
- Output updated batch state for next iteration
|
||||||
|
|
||||||
|
6. Key pattern for continue-on-error:
|
||||||
|
- HTTP nodes: Enable "Continue On Fail"
|
||||||
|
- After HTTP node, Code node checks `$json.error` or `$json.statusCode >= 400`
|
||||||
|
- Log failure to results array but don't throw - return updated state to continue loop
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
Test batch update with 2 containers where one has no update available:
|
||||||
|
- First container: pulls, updates, succeeds
|
||||||
|
- Second container: "No update available" -> warning
|
||||||
|
- Progress message updates for each container
|
||||||
|
- Both counted in results (1 success, 1 warning)
|
||||||
|
</verify>
|
||||||
|
<done>Per-container progress shown during execution; actions execute correctly; errors logged but don't abort batch</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 3: Add batch summary with failure emphasis</name>
|
||||||
|
<files>n8n-workflow.json</files>
|
||||||
|
<action>
|
||||||
|
Create the final summary message after batch completes.
|
||||||
|
|
||||||
|
1. After Loop Over Items completes, add Code node "Build Batch Summary":
|
||||||
|
- Input: final batch state with all results
|
||||||
|
- Build summary following pattern from CONTEXT: "Summary emphasizes failures over successes"
|
||||||
|
- Format:
|
||||||
|
```html
|
||||||
|
<b>Batch {action} Complete</b>
|
||||||
|
|
||||||
|
{if errors exist:}
|
||||||
|
<b>Failed ({errorCount}):</b>
|
||||||
|
- {containerName}: {reason}
|
||||||
|
- {containerName}: {reason}
|
||||||
|
|
||||||
|
{if warnings exist AND Claude's discretion to show them:}
|
||||||
|
<b>Warnings ({warningCount}):</b>
|
||||||
|
- {containerName}: {reason}
|
||||||
|
|
||||||
|
<b>Successful:</b> {successCount}/{totalCount}
|
||||||
|
```
|
||||||
|
- Per CONTEXT, Claude's discretion on warnings. Recommendation: Show warning count but not individual warnings unless there are few: `Warnings: 2 (containers already in desired state)`
|
||||||
|
|
||||||
|
2. Add HTTP node "Send Batch Summary":
|
||||||
|
- POST to Telegram editMessageText
|
||||||
|
- Edit the progress message to show final summary
|
||||||
|
- Add inline keyboard with "Back to List" button
|
||||||
|
|
||||||
|
3. Error classification in the result handler (Task 2):
|
||||||
|
- ERROR (red, show in summary):
|
||||||
|
- HTTP status 4xx/5xx from Docker API
|
||||||
|
- "image pull failed", "timeout", "permission denied"
|
||||||
|
- Container not found during execution
|
||||||
|
- WARNING (yellow, optional in summary):
|
||||||
|
- "Already stopped" (for stop action)
|
||||||
|
- "Already running" (for start action)
|
||||||
|
- "No update available" (for update action)
|
||||||
|
- HTTP 304 Not Modified
|
||||||
|
|
||||||
|
4. Summary should be actionable - if something failed, user knows what and why, not just a count.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
Test batch with mixed results:
|
||||||
|
- 2 success, 1 error, 1 warning
|
||||||
|
- Summary shows: "Failed (1): containerX: Connection timeout"
|
||||||
|
- Summary shows: "Warnings: 1"
|
||||||
|
- Summary shows: "Successful: 2/4"
|
||||||
|
- "Back to List" button works
|
||||||
|
</verify>
|
||||||
|
<done>Final summary shows after batch; failures emphasized with names and reasons; warnings handled per discretion; navigation button returns to list</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
1. Workflow imports successfully in n8n
|
||||||
|
2. "update plex sonarr radarr" executes all three sequentially
|
||||||
|
3. Progress message updates for each container
|
||||||
|
4. One failure doesn't abort remaining containers
|
||||||
|
5. Final summary shows clear failure/success breakdown
|
||||||
|
6. Errors include container name and reason
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- Batch of 3 containers executes sequentially (not parallel)
|
||||||
|
- Each container shows progress as it completes
|
||||||
|
- If container 2 fails, container 3 still attempts
|
||||||
|
- Summary: "Failed (1): sonarr: image pull timeout" + "Successful: 2/3"
|
||||||
|
- User can navigate back to container list after batch
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/09-batch-operations/09-02-SUMMARY.md`
|
||||||
|
</output>
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
---
|
||||||
|
phase: 09-batch-operations
|
||||||
|
plan: 03
|
||||||
|
type: execute
|
||||||
|
wave: 3
|
||||||
|
depends_on: [09-02]
|
||||||
|
files_modified: [n8n-workflow.json]
|
||||||
|
autonomous: true
|
||||||
|
|
||||||
|
must_haves:
|
||||||
|
truths:
|
||||||
|
- "'Update all' command updates only containers with available updates"
|
||||||
|
- "'Update all' shows confirmation with count before executing"
|
||||||
|
- "If no containers have updates, shows 'All up to date' message"
|
||||||
|
- "Inline keyboard allows selecting multiple containers for batch action"
|
||||||
|
artifacts:
|
||||||
|
- path: "n8n-workflow.json"
|
||||||
|
provides: "Update all command and inline batch selection"
|
||||||
|
contains: "Check Available Updates"
|
||||||
|
key_links:
|
||||||
|
- from: "'update all' command"
|
||||||
|
to: "Docker API image inspection"
|
||||||
|
via: "Compare current vs latest image digests"
|
||||||
|
pattern: "update.*all"
|
||||||
|
- from: "Multi-select keyboard"
|
||||||
|
to: "Batch execution"
|
||||||
|
via: "Toggle selection encoded in callback_data"
|
||||||
|
pattern: "batch:toggle"
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Add "update all" command targeting only containers with available updates, plus inline keyboard multi-select for batch operations via buttons.
|
||||||
|
|
||||||
|
Purpose: Enable convenient bulk updates and UI-based batch selection without typing container names.
|
||||||
|
Output: "Update all" flow with pre-flight check and confirmation; multi-select toggle keyboard for batch actions.
|
||||||
|
</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/09-batch-operations/09-01-SUMMARY.md
|
||||||
|
@.planning/phases/09-batch-operations/09-02-SUMMARY.md
|
||||||
|
@n8n-workflow.json
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Add "update all" command with update availability check</name>
|
||||||
|
<files>n8n-workflow.json</files>
|
||||||
|
<action>
|
||||||
|
Implement "update all" that only targets containers with updates available.
|
||||||
|
|
||||||
|
1. In command detection (early in workflow), detect "update all" as special case:
|
||||||
|
- Add to command matching: if message.toLowerCase() includes "update all" or "updateall"
|
||||||
|
- Route to dedicated "Update All" flow (not the batch parsing flow)
|
||||||
|
|
||||||
|
2. Add HTTP node "Get All Containers For Update All":
|
||||||
|
- GET from Docker API via proxy: `http://docker-socket-proxy:2375/containers/json?all=true`
|
||||||
|
- Returns all containers
|
||||||
|
|
||||||
|
3. Add Code node "Check Available Updates":
|
||||||
|
- For each container, need to check if update is available
|
||||||
|
- This requires comparing current image digest to remote latest
|
||||||
|
- Pattern from existing update flow:
|
||||||
|
a. Get container's current image ID
|
||||||
|
b. Pull :latest tag (or appropriate tag)
|
||||||
|
c. Compare digests
|
||||||
|
- This is expensive for many containers - consider approach:
|
||||||
|
- Option A: Full check for each (slow but accurate)
|
||||||
|
- Option B: Only check containers using :latest tag (faster, common case)
|
||||||
|
- Recommendation: Use Option B as default - most containers use :latest
|
||||||
|
|
||||||
|
4. For containers using :latest tag:
|
||||||
|
- Execute: `docker pull {image}:latest` (via proxy exec or curl)
|
||||||
|
- Compare pulled image digest to running container's image digest
|
||||||
|
- Mark container as "has update" if different
|
||||||
|
|
||||||
|
5. Add Code node "Build Update All Preview":
|
||||||
|
- If no containers have updates: Return "All containers are up to date!"
|
||||||
|
- If some have updates: Build list of containers with updates
|
||||||
|
- Output: `{ containersToUpdate: Container[], count: number }`
|
||||||
|
|
||||||
|
6. Add IF node "Has Updates Available":
|
||||||
|
- TRUE: Continue to confirmation
|
||||||
|
- FALSE: Send "All up to date" message and stop
|
||||||
|
|
||||||
|
7. Add Code node "Build Update All Confirmation":
|
||||||
|
- Text: "Update {N} containers?\n\n{list container names with versions if available}"
|
||||||
|
- Inline keyboard: [Confirm] [Cancel]
|
||||||
|
- Callback format: `uall:confirm:{timestamp}` and `uall:cancel`
|
||||||
|
- Store containers to update in workflow context (or encode in callback if small enough)
|
||||||
|
|
||||||
|
8. Handle callbacks:
|
||||||
|
- `uall:confirm`: Check 30-second timeout, then pass containers to batch execution flow (Plan 02)
|
||||||
|
- `uall:cancel`: Send "Update cancelled" and return to list
|
||||||
|
|
||||||
|
Note: The actual batch execution reuses Plan 02's Loop Over Items infrastructure.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
Test "update all" command:
|
||||||
|
- With containers that have updates: Shows confirmation "Update 3 containers? plex, sonarr, radarr"
|
||||||
|
- With no updates available: Shows "All containers are up to date!"
|
||||||
|
- Confirm executes batch update for listed containers
|
||||||
|
- Cancel returns to normal state
|
||||||
|
</verify>
|
||||||
|
<done>"Update all" checks for available updates, shows confirmation with count and list, executes batch for only updatable containers</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Add inline keyboard multi-select for batch operations</name>
|
||||||
|
<files>n8n-workflow.json</files>
|
||||||
|
<action>
|
||||||
|
Implement toggle-style multi-select via inline keyboard buttons.
|
||||||
|
|
||||||
|
1. Add entry point to batch selection mode:
|
||||||
|
- In container list keyboard (from Phase 8), add button row: "Select Multiple"
|
||||||
|
- Callback: `batch:mode`
|
||||||
|
|
||||||
|
2. Handle `batch:mode` callback - Add Code node "Build Batch Select Keyboard":
|
||||||
|
- Show container list with toggle checkmarks
|
||||||
|
- Each container button: text shows name with/without checkmark
|
||||||
|
- Callback format: `batch:toggle:{selected_csv}:{container_name}`
|
||||||
|
- `selected_csv`: comma-separated currently selected containers
|
||||||
|
- `container_name`: container being toggled
|
||||||
|
- Example: `batch:toggle:plex,sonarr:radarr` means "plex and sonarr selected, toggling radarr"
|
||||||
|
|
||||||
|
3. Handle `batch:toggle:*` callbacks:
|
||||||
|
- Parse callback data to get current selection and container being toggled
|
||||||
|
- Toggle the container in/out of selection
|
||||||
|
- Rebuild keyboard with updated checkmarks
|
||||||
|
- Edit message to show new keyboard
|
||||||
|
|
||||||
|
4. Add action buttons when selection exists:
|
||||||
|
- At bottom of keyboard, show: "[Update Selected] [Start Selected] [Stop Selected]"
|
||||||
|
- Only show relevant actions based on container states (or show all and handle gracefully)
|
||||||
|
- Callback format: `batch:exec:{action}:{selected_csv}`
|
||||||
|
|
||||||
|
5. Handle `batch:exec:*` callbacks:
|
||||||
|
- Parse action and selected containers
|
||||||
|
- For stop: Show confirmation (per existing batch stop rule)
|
||||||
|
- For start/restart: Execute immediately via batch loop
|
||||||
|
- For update: Execute immediately via batch loop
|
||||||
|
- Pass selected containers to batch execution infrastructure (Plan 02)
|
||||||
|
|
||||||
|
6. 64-byte callback_data limit handling (per RESEARCH):
|
||||||
|
- Average container name: 6-10 chars
|
||||||
|
- With format `batch:toggle:{csv}:{name}`, limit ~8-10 containers
|
||||||
|
- If limit approached, show warning: "Maximum selection reached. Use 'update all' for more."
|
||||||
|
- Add Code node "Check Selection Size" before toggle to enforce limit
|
||||||
|
|
||||||
|
7. Add "Clear Selection" and "Cancel" buttons:
|
||||||
|
- "Clear": `batch:clear` - reset selection, rebuild keyboard
|
||||||
|
- "Cancel": `batch:cancel` - return to normal container list
|
||||||
|
|
||||||
|
Note: This is Claude's discretion area from CONTEXT. Toggle checkmark pattern chosen for consistency with Phase 8 keyboard patterns.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
Test batch selection flow:
|
||||||
|
- Click "Select Multiple" -> Container list with toggle buttons appears
|
||||||
|
- Click container -> Checkmark appears/disappears
|
||||||
|
- With 2+ selected -> Action buttons appear at bottom
|
||||||
|
- Click "Update Selected" -> Batch update executes for selected containers
|
||||||
|
- Clear selection resets all checkmarks
|
||||||
|
- Cancel returns to normal container list
|
||||||
|
</verify>
|
||||||
|
<done>Inline keyboard multi-select works with toggle checkmarks; action buttons execute batch for selected containers; callback_data size limit enforced</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
1. Workflow imports successfully in n8n
|
||||||
|
2. "update all" shows only containers with available updates
|
||||||
|
3. "update all" with no updates shows "All up to date"
|
||||||
|
4. Multi-select keyboard allows toggling containers
|
||||||
|
5. Selected containers can be batch updated/started/stopped
|
||||||
|
6. Callback data stays within 64-byte limit
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- "Update all" scans and shows "Update 3 containers?" only for those needing updates
|
||||||
|
- When all up to date, shows "All containers are up to date!"
|
||||||
|
- Inline multi-select: checkmarks toggle on click
|
||||||
|
- "Update Selected" with 3 containers executes batch update
|
||||||
|
- Selection limit prevents callback_data overflow
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/09-batch-operations/09-03-SUMMARY.md`
|
||||||
|
</output>
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
---
|
||||||
|
phase: 09-batch-operations
|
||||||
|
plan: 04
|
||||||
|
type: execute
|
||||||
|
wave: 4
|
||||||
|
depends_on: [09-03]
|
||||||
|
files_modified: [n8n-workflow.json]
|
||||||
|
autonomous: false
|
||||||
|
|
||||||
|
must_haves:
|
||||||
|
truths:
|
||||||
|
- "All batch operation flows work correctly via text commands"
|
||||||
|
- "All batch operation flows work correctly via inline keyboard"
|
||||||
|
- "Error handling behaves correctly when containers fail"
|
||||||
|
- "Existing single-container commands still work (no regression)"
|
||||||
|
artifacts: []
|
||||||
|
key_links: []
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Verify all batch operation flows work correctly and existing functionality is preserved.
|
||||||
|
|
||||||
|
Purpose: Ensure batch operations meet requirements before marking phase complete.
|
||||||
|
Output: Verified working batch system with human confirmation.
|
||||||
|
</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-01-SUMMARY.md
|
||||||
|
@.planning/phases/09-batch-operations/09-02-SUMMARY.md
|
||||||
|
@.planning/phases/09-batch-operations/09-03-SUMMARY.md
|
||||||
|
@n8n-workflow.json
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Deploy and test batch text commands</name>
|
||||||
|
<files>n8n-workflow.json</files>
|
||||||
|
<action>
|
||||||
|
Deploy the updated workflow and test all batch text command flows.
|
||||||
|
|
||||||
|
1. Import updated workflow to n8n (via API or manual upload)
|
||||||
|
|
||||||
|
2. Test batch text commands via Telegram:
|
||||||
|
|
||||||
|
Test A: Multi-container update
|
||||||
|
- Send: "update plex sonarr" (use actual container names from your server)
|
||||||
|
- Expected: Progress shows for each container, summary shows results
|
||||||
|
|
||||||
|
Test B: Multi-container start
|
||||||
|
- First stop two containers via existing single commands
|
||||||
|
- Send: "start plex sonarr"
|
||||||
|
- Expected: Both start without confirmation, summary shows results
|
||||||
|
|
||||||
|
Test C: Multi-container stop (requires confirmation)
|
||||||
|
- Send: "stop plex sonarr"
|
||||||
|
- Expected: Confirmation prompt appears
|
||||||
|
- Tap Confirm: Both stop, summary shows
|
||||||
|
- (Test cancel in separate attempt)
|
||||||
|
|
||||||
|
Test D: Fuzzy matching
|
||||||
|
- Send: "update plex" (when jellyplex also exists, or use your actual partial matches)
|
||||||
|
- Expected: Exact match wins, no disambiguation
|
||||||
|
|
||||||
|
Test E: Disambiguation
|
||||||
|
- Send: "update jelly" (if it matches multiple containers)
|
||||||
|
- Expected: Disambiguation prompt with options
|
||||||
|
|
||||||
|
3. Test "update all" command:
|
||||||
|
- Send: "update all"
|
||||||
|
- Expected: Shows confirmation with count of containers needing updates
|
||||||
|
- If all up to date: Shows "All containers are up to date!"
|
||||||
|
- Confirm: Batch update executes for listed containers
|
||||||
|
|
||||||
|
4. Document any issues found for fixing before checkpoint.
|
||||||
|
</action>
|
||||||
|
<verify>
|
||||||
|
All text command tests pass:
|
||||||
|
- "update plex sonarr" executes sequential batch update
|
||||||
|
- "stop plex sonarr" shows confirmation first
|
||||||
|
- "update all" only targets containers with updates
|
||||||
|
- Disambiguation works for ambiguous names
|
||||||
|
</verify>
|
||||||
|
<done>All batch text commands tested and working</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="checkpoint:human-verify" gate="blocking">
|
||||||
|
<what-built>Complete batch operations system with text commands and inline keyboard multi-select</what-built>
|
||||||
|
<how-to-verify>
|
||||||
|
Test the following flows in Telegram:
|
||||||
|
|
||||||
|
**Text Command Tests:**
|
||||||
|
|
||||||
|
1. **Batch Update:**
|
||||||
|
- Send: "update {container1} {container2}" (replace with your container names)
|
||||||
|
- Verify: Progress updates for each container, final summary shows
|
||||||
|
|
||||||
|
2. **Batch Stop (confirmation required):**
|
||||||
|
- Send: "stop {container1} {container2}"
|
||||||
|
- Verify: Confirmation prompt appears
|
||||||
|
- Tap Confirm and verify both stop
|
||||||
|
|
||||||
|
3. **Update All:**
|
||||||
|
- Send: "update all"
|
||||||
|
- Verify: Shows count of containers with updates, or "All up to date"
|
||||||
|
- If updates exist, confirm and verify batch executes
|
||||||
|
|
||||||
|
**Inline Keyboard Tests:**
|
||||||
|
|
||||||
|
4. **Multi-Select Mode:**
|
||||||
|
- Send: "/status"
|
||||||
|
- Tap "Select Multiple" button
|
||||||
|
- Verify: Container list appears with toggle capability
|
||||||
|
|
||||||
|
5. **Toggle Selection:**
|
||||||
|
- Tap containers to toggle checkmarks
|
||||||
|
- Verify: Checkmarks appear/disappear on each tap
|
||||||
|
|
||||||
|
6. **Execute Batch:**
|
||||||
|
- With 2+ containers selected, tap action button (e.g., "Update Selected")
|
||||||
|
- Verify: Batch executes for selected containers with progress
|
||||||
|
|
||||||
|
**Error Handling Test:**
|
||||||
|
|
||||||
|
7. **Failure Isolation:**
|
||||||
|
- If possible, trigger a failure (e.g., update a container that doesn't exist)
|
||||||
|
- Verify: Other containers in batch still process, summary shows failure details
|
||||||
|
|
||||||
|
**Regression Tests:**
|
||||||
|
|
||||||
|
8. **Single-container commands still work:**
|
||||||
|
- "status" shows keyboard
|
||||||
|
- "start plex" starts single container
|
||||||
|
- "logs plex" shows logs
|
||||||
|
</how-to-verify>
|
||||||
|
<resume-signal>Type "approved" if all flows work, or describe any issues found</resume-signal>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
Human verified all batch flows work correctly via Telegram testing.
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- BAT-01: User can update multiple containers in one command
|
||||||
|
- BAT-02: Batch updates execute sequentially with per-container feedback
|
||||||
|
- BAT-03: "Update all" updates only containers with updates available
|
||||||
|
- BAT-04: "Update all" requires confirmation
|
||||||
|
- BAT-05: One failure doesn't abort remaining batch
|
||||||
|
- BAT-06: Final summary shows success/failure count
|
||||||
|
- Inline keyboard batch selection works
|
||||||
|
- No regression in existing commands
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/09-batch-operations/09-04-SUMMARY.md`
|
||||||
|
</output>
|
||||||
Reference in New Issue
Block a user