n8n $getWorkflowStaticData only reliably tracks top-level property changes.
Deep nested mutations (staticData.errorLog.debug.enabled = true) are not
persisted between executions. Fix: serialize errorLog as JSON string in
staticData._errorLog — every read does JSON.parse, every write does
JSON.stringify as a top-level assignment.
Fixed in: Process Debug Command, Log Error, Log Trace, 6 inline trace
nodes, Parse Callback Data callback routing trace.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Plan 02 executor placed correlationId outside the json object in all
Prepare Input code nodes, creating "Unexpected token '}'" syntax errors.
Moved correlationId inside the json return object in all 19 affected nodes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two bugs: (1) connection array had old fallback at index [9] shifting debug
connections off-by-one, so /errors routed to Show Menu. (2) /debug status
matched rule 1 (contains "status") before rule 11 (startsWith /debug).
Fix: move startsWith debug rules [1-4] before contains rules [5-12].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Part A - Correlation ID Generation:
- Added Generate Correlation ID node for text command path
- Added Generate Callback Correlation ID node for callback path
- Wired between authentication and routing nodes
- Uses timestamp + random string pattern (no external dependencies)
Part B - Correlation ID Propagation:
- Modified 19 Prepare Input nodes to pass correlationId to sub-workflows
- Uses $input.item.json.correlationId pattern for flexibility
- Supports both text and callback paths
Part C - Error Capture Infrastructure:
- Added 2 error detection IF nodes for high-value paths:
* Check Execute Container Action Success
* Check Execute Inline Action Success
- Error path: success === false → Log Error node
- Success path: continues to original result handling
- Log Error node receives error data from sub-workflows
- Pass-through design preserves data for downstream handlers
Main workflow: 172 → 176 nodes (+4)
- 2 correlation ID generators
- 2 error detection IF nodes
Error ring buffer now captures:
- Container action failures (Docker API errors)
- Sub-workflow errors with full diagnostic context
- Correlation IDs for request tracing
- Workflow name, node, HTTP codes, raw responses
- Create Log Error code node with ring buffer write logic
- Create Log Trace code node with debug mode check and auto-disable
- Both nodes implement ring buffer (max 50 entries) with auto-rotation
- Log Error: accepts error data, truncates large fields (stack 500, raw 1000)
- Log Error: passes through input data with _errorLogged flag
- Log Trace: checks debug.enabled before logging, passes through unchanged
- Log Trace: auto-disables debug mode after 100 executions
- Both nodes positioned at utility area (2600, -200/-400)
- Nodes are standalone (no connections) - ready for Plan 02 wiring
- Node count: 170 -> 172 (+2 utility nodes)
The list keyword rule was added to Keyword Router but its connection
pointed to Show Menu (fallback) instead of Prepare Status Input.
Added proper connection at index 8 and shifted fallback to index 9.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added 'list' route with same output as 'status'
- Both /list and /status now show paginated container list
- Provides user-expected /list command while leveraging existing functionality
- Add HTTP 304 detection for 'already in desired state' (success: true)
- Add HTTP 404 detection for 'container not found' (success: false)
- Add HTTP 500+ detection for server errors (success: false)
- Apply to Format Stop/Start/Restart Result nodes
- StatusCode checks run before existing message-based fallback logic
- Changed $('Prepare Cancel Return').item.json to $input.item.json
- Allows node to work with both cancel paths (batch cancel and confirmation cancel)
- Fixes confirmation dialog cancel button returning to container status view
- Gap 1: Format Stop/Start/Restart missing statusCode 304 check
- Gap 2: Build Batch Keyboard reads action instead of actionType
- Gap 3: /list not implemented in Keyword Router (minor)
- Gap 4: Build Cancel Return Submenu references wrong predecessor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Code Node Classification section to DEPLOY-SUBWORKFLOWS.md
- Classify each Code node into 6 categories with evidence
- 58 nodes confirmed as orchestration infrastructure (must stay)
- 2 domain-logic candidates identified but extraction is net-negative
- Summary proves no further extraction is viable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added "Prepare Batch Execution" Code node between Route Batch Match Result
and Route Batch Action to transform matching sub-workflow output:
- matchedContainers -> allMatched (field name expected by downstream nodes)
- action from Detect Batch Command (stop/start/restart) instead of
"batch_matched" routing label from sub-workflow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Text commands like "status book" should show plain text status without
inline keyboard buttons. Added "Strip Status Keyboard" Code node that
removes reply_markup before sending via Send Container Submenu Direct.
Callback-based status (with messageId) still gets the full UI with buttons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Prepare Text Action Input now reads action (stop/start/restart) from
Parse Action Command instead of matching sub-workflow's actionType field
- Added "Has Status Message ID" If node to route status_direct results:
messageId > 0 → Edit Container List (callback), messageId == 0 →
Send Container Submenu Direct (text command)
- Pre-existing bug: text "status <name>" routed to editMessageText with
messageId 0, causing Telegram API error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Updated 3 Execute Workflow nodes: Execute Action Match, Execute Update Match, Execute Batch Match
- Deployed n8n-matching.json as workflow kL4BoI8ITSP9Oxek
- Pushed main workflow to n8n API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract 12 matching/disambiguation logic nodes into sub-workflow
- 23 nodes total: trigger + router + 12 logic + 9 format-return nodes
- Three action paths: match_action, match_update, match_batch
- Every exit path returns JSON with action field per established pattern
- Adapted input references to use trigger data instead of main workflow refs
- No response nodes included (stay in main per locked decision)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 10.1 verification found 3 gaps:
- Gap 1: Node count 168 vs 115-125 target (needs user decision)
- Gap 2: Code node analysis incomplete (documentation task)
- Gap 3: Sub-workflow contracts not documented (documentation task)
Plan 10.1-06 addresses gaps with:
- Task 1: Document all 6 sub-workflow input/output contracts
- Task 2: Classify all 62 Code nodes by purpose
- Task 3: User decision checkpoint on node count approach
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Created 10.1-05-SUMMARY.md documenting verification and UAT
- Updated STATE.md to reflect phase completion (5/5 plans)
- Updated ROADMAP.md to mark phase 10.1 complete
- Updated DEPLOY-SUBWORKFLOWS.md with deployed workflow IDs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Docker logs API returns multiplexed stream with 8-byte headers per frame,
not just newline-separated text. The old code split on \n which missed
frames that weren't newline-terminated.
Now properly parses the binary stream format:
- Reads 8-byte header (stream type + frame size)
- Extracts frame data based on size
- Splits frame content by newlines
- Correctly counts and displays requested number of lines
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Text-based batch commands (e.g., /start container1 container2) were
failing because Send Batch Start Message always used editMessageText,
but you can't edit the user's message.
Fixed by:
- Conditionally use sendMessage vs editMessageText based on fromKeyboard
- Capture new message_id from sendMessage response for progress updates
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The batch action (stop/start/restart) was being lost because:
1. Parse Callback Data extracted action: "stop"
2. Prepare Batch UI Input overwrote it with action: "exec" (the UI action type)
3. Handle Exec tried to parse callbackData which was empty
Fixed by:
- Adding batchAction field to Prepare Batch UI Input
- Adding batchAction to Batch UI trigger schema
- Updating Handle Exec to use triggerData.batchAction and selectedCsv
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The n8n Telegram node's inlineKeyboard parameter doesn't work reliably
with editMessageText operation. Switched to HTTP Request node calling
Telegram API directly, which properly passes reply_markup.
Changed nodes:
- Send Confirmation Dialog
- Send Stop Result
- Send Expired Message
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The n8n Telegram node's inlineKeyboard parameter expects the keyboard
rows array directly, not the full {inline_keyboard: [...]} object.
Fixed nodes:
- Send Confirmation Dialog
- Send Stop Result
- Send Expired Message
Changed from: JSON.stringify($json.reply_markup)
Changed to: JSON.stringify($json.reply_markup.inline_keyboard)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>