From f3ab7cf312313f90a848fb52b7a149be6afc87bc Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Sun, 8 Feb 2026 09:35:34 -0500 Subject: [PATCH] docs(10.1): create UAT gap closure plans (08-09) --- .planning/ROADMAP.md | 8 +- .../10.1-08-PLAN.md | 153 +++++++++++++ .../10.1-09-PLAN.md | 212 ++++++++++++++++++ 3 files changed, 370 insertions(+), 3 deletions(-) create mode 100644 .planning/phases/10.1-aggressive-workflow-modularization/10.1-08-PLAN.md create mode 100644 .planning/phases/10.1-aggressive-workflow-modularization/10.1-09-PLAN.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index ee78843..3891026 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -51,7 +51,7 @@ Plans: **Requirements:** MOD-03 (new) -**Plans:** 7 plans +**Plans:** 9 plans Plans: - [x] 10.1-01-PLAN.md — Rename sub-workflows, analyze domain boundaries, get user approval @@ -61,6 +61,8 @@ Plans: - [x] 10.1-05-PLAN.md — Integration verification and UAT - [x] 10.1-06-PLAN.md — Gap closure: Extract Matching/Disambiguation sub-workflow - [x] 10.1-07-PLAN.md — Gap closure: Code node classification + contract documentation +- [ ] 10.1-08-PLAN.md — UAT gap closure: Fix action result statusCode handling (n8n-actions.json) +- [ ] 10.1-09-PLAN.md — UAT gap closure: Fix batch keyboard, cancel routing, /list command (n8n-workflow.json) **Success Criteria:** 1. Main workflow contains only: trigger, auth, keyword routing, sub-workflow dispatch @@ -162,7 +164,7 @@ Plans: | 8 | Inline Keyboard Infrastructure | v1.1 | Complete | | 9 | Batch Operations | v1.1 | Complete | | 10 | Workflow Modularization | v1.2 | Complete | -| 10.1 | Aggressive Workflow Modularization | v1.2 | Complete | +| 10.1 | Aggressive Workflow Modularization | v1.2 | In Progress (7/9 plans) | | 10.2 | Better Logging & Log Management | v1.2 | Pending (INSERTED) | | 11 | Update All & Callback Limits | v1.2 | Pending | | 12 | Polish & Audit | v1.2 | Pending | @@ -171,4 +173,4 @@ Plans: **v1.2 Coverage:** 12+ requirements mapped across 7 phases --- -*Updated: 2026-02-08 — Phase 10.1 COMPLETE (7/7 plans)* +*Updated: 2026-02-08 — Phase 10.1 UAT gap closure plans created (08-09)* diff --git a/.planning/phases/10.1-aggressive-workflow-modularization/10.1-08-PLAN.md b/.planning/phases/10.1-aggressive-workflow-modularization/10.1-08-PLAN.md new file mode 100644 index 0000000..ae16e41 --- /dev/null +++ b/.planning/phases/10.1-aggressive-workflow-modularization/10.1-08-PLAN.md @@ -0,0 +1,153 @@ +--- +phase: 10.1-aggressive-workflow-modularization +plan: 08 +type: execute +wave: 1 +depends_on: [] +files_modified: [n8n-actions.json] +autonomous: true +gap_closure: true + +must_haves: + truths: + - "Stopping an already-stopped container returns helpful 'already stopped' message" + - "Starting an already-started container returns helpful 'already started' message" + - "Container not found returns clear error message" + - "Server errors are handled gracefully with descriptive messages" + artifacts: + - path: "n8n-actions.json" + provides: "Format Stop Result, Format Start Result, Format Restart Result nodes with statusCode handling" + contains: "statusCode" + key_links: + - from: "n8n-actions.json Format Stop Result" + to: "HTTP 304/404/500 detection" + via: "response.statusCode check" + pattern: "statusCode.*304|404|500" +--- + + +Fix container action result formatting to properly handle Docker API HTTP status codes (304, 404, 500) in addition to existing message-based detection. + +Purpose: Close UAT gap where stopping an already-stopped container showed a failure message instead of "already stopped" +Output: Updated n8n-actions.json with comprehensive status code handling + + + +@/home/luc/.claude/get-shit-done/workflows/execute-plan.md +@/home/luc/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/10.1-aggressive-workflow-modularization/10.1-UAT.md +@.planning/phases/10.1-aggressive-workflow-modularization/10.1-CONTEXT.md +@n8n-actions.json + + + + + + Task 1: Add statusCode checks to Format Stop/Start/Restart Result nodes + n8n-actions.json + +Update three Code nodes in n8n-actions.json: +- **Format Stop Result** (id: code-format-stop-result) +- **Format Start Result** (id: code-format-start-result) +- **Format Restart Result** (id: code-format-restart-result) + +Each node currently checks `response.message` and `response.error` patterns. Add statusCode checks BEFORE the existing checks: + +```javascript +const response = $input.item.json; +const containerName = response.containerName; + +// Check HTTP status codes first (Docker API with onError:continueRegularOutput) +if (response.statusCode) { + if (response.statusCode === 304) { + // Already in desired state + return { + success: true, + message: `✅ ${containerName} is already {stopped|started}` + }; + } else if (response.statusCode === 404) { + return { + success: false, + message: `❌ Container ${containerName} not found` + }; + } else if (response.statusCode >= 500) { + return { + success: false, + message: `❌ Server error {stopping|starting|restarting} ${containerName}: ${response.statusMessage || 'Unknown error'}` + }; + } +} + +// Then fall through to existing message-based checks... +``` + +**Per-action text variations:** +- Stop: "already stopped", "stopping" +- Start: "already started", "starting" +- Restart: "already started" (Docker restart endpoint returns 304 for already-running containers) + +**Note:** HTTP 204 is handled by existing `!response.message && !response.error` success check. + + +1. Read n8n-actions.json and verify all three Format nodes have statusCode checks +2. Verify 304 returns success: true with "already {state}" message +3. Verify 404 returns success: false with "not found" message +4. Verify >= 500 returns success: false with "server error" message + + All three Format Result nodes check response.statusCode for 304, 404, and 500+ before falling through to existing message-based checks. Status code checks use appropriate per-action messaging. + + + + Task 2: Deploy updated sub-workflow via n8n API + n8n-actions.json + +Deploy updated n8n-actions.json to n8n instance: + +```bash +source .env.n8n-api +curl -X PUT "$N8N_HOST/api/v1/workflows/fYSZS5PkH0VSEaT5" \ + -H "X-N8N-API-KEY: $N8N_API_KEY" \ + -H "Content-Type: application/json" \ + --data @n8n-actions.json +``` + +Verify deployment success (returns 200 with workflow object). + + +curl returns 200 status code and JSON response containing workflow ID fYSZS5PkH0VSEaT5 + + Updated n8n-actions.json deployed to n8n instance successfully + + + + + +## Manual Test Cases + +After deployment, test using Telegram bot: + +1. **Already stopped:** Find a stopped container → send "stop {name}" → expect "✅ {name} is already stopped" (not failure message) +2. **Already started:** Find a running container → send "start {name}" → expect "✅ {name} is already started" +3. **Not found:** Send "stop nonexistent123" → expect "❌ Container nonexistent123 not found" + +All three should show success/error indicators instead of generic failure messages. + + + +- Format Stop/Start/Restart Result nodes check response.statusCode before message patterns +- HTTP 304 treated as success with "already {stopped|started}" message +- HTTP 404 returns clear "not found" error +- HTTP 500+ returns clear "server error" message +- Updated sub-workflow deployed via n8n API +- UAT gap "Stopping an already-stopped container returns helpful message" is closed + + + +After completion, create `.planning/phases/10.1-aggressive-workflow-modularization/10.1-08-SUMMARY.md` + diff --git a/.planning/phases/10.1-aggressive-workflow-modularization/10.1-09-PLAN.md b/.planning/phases/10.1-aggressive-workflow-modularization/10.1-09-PLAN.md new file mode 100644 index 0000000..0dbb748 --- /dev/null +++ b/.planning/phases/10.1-aggressive-workflow-modularization/10.1-09-PLAN.md @@ -0,0 +1,212 @@ +--- +phase: 10.1-aggressive-workflow-modularization +plan: 09 +type: execute +wave: 1 +depends_on: [] +files_modified: [n8n-workflow.json] +autonomous: true +gap_closure: true + +must_haves: + truths: + - "Multiple container matches show disambiguation keyboard with correct action in button text" + - "Cancel button on confirmation dialog returns to container status view" + - "/list command shows container list (or documented as /status)" + artifacts: + - path: "n8n-workflow.json" + provides: "Build Batch Keyboard with correct actionType reference" + contains: "$json.actionType" + - path: "n8n-workflow.json" + provides: "Build Cancel Return Submenu with dynamic input reference" + contains: "$input.item.json" + - path: "n8n-workflow.json" + provides: "Keyword Router with list command handling" + contains: "list" + key_links: + - from: "Build Batch Keyboard" + to: "actionType field" + via: "$json.actionType (not $json.action)" + pattern: "\\$json\\.actionType" + - from: "Build Cancel Return Submenu" + to: "dynamic predecessor data" + via: "$input.item.json (not hardcoded node reference)" + pattern: "\\$input\\.item\\.json" +--- + + +Fix three data flow bugs in main workflow: Build Batch Keyboard reading wrong field, Build Cancel Return Submenu referencing wrong predecessor, and Keyword Router missing /list command. + +Purpose: Close UAT gaps for disambiguation keyboard, confirmation cancel, and /list command +Output: Updated n8n-workflow.json with corrected node logic + + + +@/home/luc/.claude/get-shit-done/workflows/execute-plan.md +@/home/luc/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/10.1-aggressive-workflow-modularization/10.1-UAT.md +@.planning/phases/10.1-aggressive-workflow-modularization/10.1-CONTEXT.md +@.planning/phases/10.1-aggressive-workflow-modularization/10.1-02-SUMMARY.md +@.planning/phases/10.1-aggressive-workflow-modularization/10.1-04-SUMMARY.md +@n8n-workflow.json + + + + + + Task 1: Fix Build Batch Keyboard to use actionType field + n8n-workflow.json + +Update **Build Batch Keyboard** Code node (id: code-build-batch-keyboard) in n8n-workflow.json: + +**Current code reads:** +```javascript +const action = $json.action; // This is "multiple" - the routing label +``` + +**Change to:** +```javascript +const action = $json.actionType; // This contains the actual action: stop/start/restart/update +``` + +**Why:** When the matching sub-workflow returns `action: "multiple"` (indicating multiple matches found), it also includes `actionType` with the user's requested action (e.g., "stop"). The keyboard builder needs the actual action for: +1. Button callback_data: `bexec:{action}:{containerId}:all` +2. Message text: "Found multiple containers matching '{term}'. Select containers to {action}:" + +Using `$json.action` produces "multiple all?" as button text and `bexec:multiple:...` callbacks which won't be recognized. + +**Location:** Find node with `"id": "code-build-batch-keyboard"` and update its JavaScript code parameter. + + +1. Read n8n-workflow.json and find node with id "code-build-batch-keyboard" +2. Verify code contains `const action = $json.actionType;` +3. Verify no other references to `$json.action` in the action variable assignment + + Build Batch Keyboard node reads actionType field instead of action field for constructing disambiguation keyboard + + + + Task 2: Fix Build Cancel Return Submenu to use dynamic input + n8n-workflow.json + +Update **Build Cancel Return Submenu** Code node (id: code-build-cancel-return-submenu) in n8n-workflow.json: + +**Current code reads:** +```javascript +const data = $('Prepare Cancel Return').item.json; +``` + +**Change to:** +```javascript +const data = $input.item.json; +``` + +**Why:** This node has two incoming paths: +1. From "Prepare Cancel Return" (batch cancel path) +2. From "Prepare Cancel From Confirm" (confirmation dialog cancel path) + +The hardcoded node reference `$('Prepare Cancel Return')` only works for path 1. When user cancels from confirmation dialog, the data flows through "Prepare Cancel From Confirm" instead, causing the node reference to fail. + +Both predecessors output the same data structure (containerId, containerName, chatId, messageId, queryId, page), so using `$input.item.json` works for both paths. + +**Location:** Find node with `"id": "code-build-cancel-return-submenu"` and update its JavaScript code parameter. + + +1. Read n8n-workflow.json and find node with id "code-build-cancel-return-submenu" +2. Verify code contains `const data = $input.item.json;` +3. Verify the node has connections from both "Prepare Cancel Return" and "Prepare Cancel From Confirm" + + Build Cancel Return Submenu node uses dynamic $input reference instead of hardcoded predecessor, allowing it to work with both cancel paths + + + + Task 3: Add /list command to Keyword Router + n8n-workflow.json + +Update **Keyword Router** Switch node (id: switch-keyword-router) in n8n-workflow.json: + +**Current routes:** status, restart, start, stop, update, update all, logs, (default to "Show Menu") + +**Decision:** Add "list" as an alias that routes to the same output as "status". + +**Implementation:** Find the switch node rules array and add a new rule: + +```json +{ + "type": "string", + "value": "list", + "output": 0 +} +``` + +Where `output: 0` matches the same output index as the "status" rule (both should route to the same node - likely "Prepare Status Input" or similar). + +**Rationale:** The "status" command with no arguments already correctly displays the container list (per UAT note "Accessed via 'status' command (no args), not /list. Pagination works."). Adding "list" as an alias provides the user-expected command while leveraging existing functionality. + +**Alternative if routing proves complex:** Instead of adding the route, document in verification that "/status" is the correct command for listing containers, and suggest updating any user-facing help text to clarify this. + +**Location:** Find node with `"id": "switch-keyword-router"` and update its routing rules. + + +1. Read n8n-workflow.json and find node with id "switch-keyword-router" +2. Verify routing rules include "list" with same output as "status" rule +3. Check what output index "status" routes to and confirm "list" routes to same + + Keyword Router accepts "list" command as alias for "status", routing to the same container list display path + + + + Task 4: Deploy updated main workflow via n8n API + n8n-workflow.json + +Deploy updated n8n-workflow.json to n8n instance: + +```bash +source .env.n8n-api +curl -X PUT "$N8N_HOST/api/v1/workflows/HmiXBlJefBRPMS0m4iNYc" \ + -H "X-N8N-API-KEY: $N8N_API_KEY" \ + -H "Content-Type: application/json" \ + --data @n8n-workflow.json +``` + +Verify deployment success (returns 200 with workflow object). + + +curl returns 200 status code and JSON response containing workflow ID HmiXBlJefBRPMS0m4iNYc + + Updated n8n-workflow.json deployed to n8n instance successfully + + + + + +## Manual Test Cases + +After deployment, test using Telegram bot: + +1. **Disambiguation keyboard:** Send "stop plex" (assuming multiple containers match "plex") → expect keyboard showing containers with "Select containers to stop:" and buttons with correct action callbacks + +2. **Confirmation cancel:** From container status view → tap Stop → confirmation dialog appears → tap Cancel → expect return to container status view (not failure) + +3. **List command:** Send "/list" → expect container list with pagination (same as "/status" with no args) + +All three should now work correctly per UAT expectations. + + + +- Build Batch Keyboard reads $json.actionType for correct action in disambiguation keyboards +- Build Cancel Return Submenu uses $input.item.json to support both cancel paths +- Keyword Router accepts "list" command routing to status handler +- Updated main workflow deployed via n8n API +- Three UAT gaps closed: disambiguation keyboard text/callbacks, confirmation cancel, /list command + + + +After completion, create `.planning/phases/10.1-aggressive-workflow-modularization/10.1-09-SUMMARY.md` +