docs(11): create phase plan — bitmap batch selection + update all button
This commit is contained in:
@@ -0,0 +1,330 @@
|
||||
---
|
||||
phase: 11-update-all-callback-limits
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: ["11-01"]
|
||||
files_modified:
|
||||
- n8n-status.json
|
||||
- n8n-workflow.json
|
||||
autonomous: false
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "User can tap 'Update All :latest' button in container list inline keyboard"
|
||||
- "Tapping the button shows a confirmation dialog listing all :latest containers"
|
||||
- "User can type 'update all' to trigger the same confirmation flow"
|
||||
- "Confirming update-all triggers batch update execution for all :latest containers"
|
||||
artifacts:
|
||||
- path: "n8n-status.json"
|
||||
provides: "Container list keyboard with Update All button"
|
||||
contains: "uall:start"
|
||||
- path: "n8n-workflow.json"
|
||||
provides: "uall:start callback routing to existing update-all flow"
|
||||
contains: "isUpdateAllStart"
|
||||
key_links:
|
||||
- from: "n8n-status.json Build Container List"
|
||||
to: "Telegram inline keyboard"
|
||||
via: "uall:start callback_data button"
|
||||
pattern: "uall:start"
|
||||
- from: "n8n-workflow.json Parse Callback Data"
|
||||
to: "n8n-workflow.json Route Callback"
|
||||
via: "isUpdateAllStart flag"
|
||||
pattern: "isUpdateAllStart"
|
||||
- from: "n8n-workflow.json Route Callback"
|
||||
to: "n8n-workflow.json Get All Containers For Update All"
|
||||
via: "updateallstart route"
|
||||
pattern: "updateallstart"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add "Update All :latest" inline keyboard button to the container list and wire its callback to the existing update-all confirmation flow. Then deploy all modified workflows and verify end-to-end functionality.
|
||||
|
||||
Purpose: BATCH-05 requires inline keyboard entry point for update-all. The text command path (BATCH-04) already works. This plan adds the inline button, routes its callback to the existing confirmation flow, deploys all changes (including Plan 01's bitmap encoding), and verifies everything works.
|
||||
|
||||
Output: Modified n8n-status.json with Update All button, modified n8n-workflow.json with uall:start routing, all workflows deployed and verified.
|
||||
</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/11-update-all-callback-limits/11-01-SUMMARY.md
|
||||
@n8n-status.json
|
||||
@n8n-workflow.json
|
||||
@CLAUDE.md
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add Update All button to container list and wire callback routing</name>
|
||||
<files>n8n-status.json, n8n-workflow.json</files>
|
||||
<action>
|
||||
**1. n8n-status.json -- Build Container List node:**
|
||||
|
||||
Add an "Update All :latest" button row to the container list keyboard. Place it AFTER the navigation row and BEFORE the "Select Multiple" button. This button should appear on EVERY page of the container list.
|
||||
|
||||
In the Build Container List code node, after the navigation row block and before the "Select Multiple" button, add:
|
||||
|
||||
```javascript
|
||||
// Add Update All button
|
||||
keyboard.push([{
|
||||
text: '\u{1F504} Update All :latest',
|
||||
callback_data: 'uall:start'
|
||||
}]);
|
||||
```
|
||||
|
||||
The callback_data `uall:start` is only 10 bytes, well within the 64-byte limit.
|
||||
|
||||
Also add the same button to the Build Paginated List code node (used when paginating from an existing list view), in the same position relative to nav and Select Multiple.
|
||||
|
||||
Do NOT add to Build Container Submenu -- that is for single container actions only.
|
||||
|
||||
**2. n8n-workflow.json -- Parse Callback Data node:**
|
||||
|
||||
Add a parser for `uall:start` callback. Place it near the existing `uall:confirm` and `uall:cancel` parsers:
|
||||
|
||||
```javascript
|
||||
if (rawData === 'uall:start') {
|
||||
return {
|
||||
json: {
|
||||
queryId,
|
||||
chatId,
|
||||
messageId,
|
||||
isUpdateAllStart: true,
|
||||
isSelect: false,
|
||||
isList: false,
|
||||
isAction: false,
|
||||
isCancel: false,
|
||||
isBatch: false,
|
||||
isConfirm: false,
|
||||
expired: false
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**3. n8n-workflow.json -- Route Callback switch node:**
|
||||
|
||||
Add a new rule for `isUpdateAllStart` that routes to the update-all flow. Insert after the existing `updateallcancel` rule (index 1), before the `cancel` rule:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "is-update-all-start",
|
||||
"conditions": {
|
||||
"options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" },
|
||||
"conditions": [{
|
||||
"id": "update-all-start-true",
|
||||
"leftValue": "={{ $json.isUpdateAllStart }}",
|
||||
"rightValue": true,
|
||||
"operator": { "type": "boolean", "operation": "equals" }
|
||||
}],
|
||||
"combinator": "and"
|
||||
},
|
||||
"renameOutput": true,
|
||||
"outputKey": "updateallstart"
|
||||
}
|
||||
```
|
||||
|
||||
**4. n8n-workflow.json -- Add Answer Update All Start node:**
|
||||
|
||||
Add a new Telegram answerCallbackQuery node to acknowledge the button press before fetching containers. Use the same pattern as existing Answer nodes (e.g., Answer Batch UI Keyboard):
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Answer Update All Start",
|
||||
"type": "n8n-nodes-base.telegram",
|
||||
"typeVersion": 1.2,
|
||||
"parameters": {
|
||||
"operation": "callback",
|
||||
"callbackQueryId": "={{ $json.queryId }}",
|
||||
"additionalFields": {
|
||||
"text": "Checking for updates..."
|
||||
}
|
||||
},
|
||||
"credentials": {
|
||||
"telegramApi": {
|
||||
"id": "I0xTTiASl7C1NZhJ",
|
||||
"name": "Telegram account"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Wire: Route Callback [updateallstart output] -> Answer Update All Start -> Get All Containers For Update All
|
||||
|
||||
**5. n8n-workflow.json -- Fix Check Available Updates for dual origin:**
|
||||
|
||||
The Check Available Updates code node currently reads chatId from `$('Keyword Router').first().json.message.chat.id` which fails when coming from the callback path. Update it to handle both origins:
|
||||
|
||||
```javascript
|
||||
let chatId, messageId;
|
||||
try {
|
||||
const kwData = $('Keyword Router').first().json;
|
||||
chatId = kwData.message.chat.id;
|
||||
messageId = kwData.message.message_id;
|
||||
} catch(e) {
|
||||
// Inline keyboard origin -- data from Parse Callback Data
|
||||
const cbData = $('Parse Callback Data').first().json;
|
||||
chatId = cbData.chatId;
|
||||
messageId = cbData.messageId;
|
||||
}
|
||||
```
|
||||
|
||||
Keep the rest of the Check Available Updates logic unchanged (container filtering, :latest detection).
|
||||
|
||||
**6. Update connections in Route Callback:**
|
||||
|
||||
Add the new output connection at the correct index in the Route Callback connections array. The new `updateallstart` rule is inserted at index 2, so all existing connection indices after position 1 shift by 1. The new index 2 connection targets Answer Update All Start.
|
||||
|
||||
**Summary of changes:**
|
||||
- n8n-status.json: Add `uall:start` button to Build Container List and Build Paginated List
|
||||
- n8n-workflow.json: Add `uall:start` parser to Parse Callback Data
|
||||
- n8n-workflow.json: Add `updateallstart` rule to Route Callback (index 2, shifting existing rules)
|
||||
- n8n-workflow.json: Add "Answer Update All Start" Telegram node
|
||||
- n8n-workflow.json: Wire Route Callback [updateallstart] -> Answer Update All Start -> Get All Containers For Update All
|
||||
- n8n-workflow.json: Fix Check Available Updates to support callback origin (try/catch for Keyword Router)
|
||||
- n8n-workflow.json: Update connections array for Route Callback to include the new output
|
||||
</action>
|
||||
<verify>
|
||||
1. `python3 -c "import json; wf=json.load(open('n8n-status.json')); [print(n['name']) for n in wf['nodes']]"` shows same 11 nodes
|
||||
2. Build Container List code contains `uall:start`
|
||||
3. `python3 -c "import json; wf=json.load(open('n8n-workflow.json')); print(len(wf['nodes']), 'nodes')"` shows 172 nodes (171 from Plan 01 + 1 Answer Update All Start)
|
||||
4. Parse Callback Data contains `uall:start` parser
|
||||
5. Route Callback has `updateallstart` rule
|
||||
6. Connections exist: Route Callback -> Answer Update All Start -> Get All Containers For Update All
|
||||
</verify>
|
||||
<done>
|
||||
Container list keyboard shows "Update All :latest" button. Tapping it answers the callback, fetches containers, filters :latest, shows confirmation dialog. Existing confirmation/cancel/expired flows handle the rest. Check Available Updates works for both text and callback origins.
|
||||
</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Deploy all workflows to n8n and run smoke test</name>
|
||||
<files>n8n-batch-ui.json, n8n-status.json, n8n-workflow.json</files>
|
||||
<action>
|
||||
Push all 3 modified workflow files to n8n using the push_workflow recipe from CLAUDE.md:
|
||||
|
||||
```bash
|
||||
. .env.n8n-api
|
||||
|
||||
push_workflow() {
|
||||
local FILE=$1 WF_ID=$2 WF_NAME=$3
|
||||
python3 -c "
|
||||
import json
|
||||
with open('$FILE') as f:
|
||||
wf = json.load(f)
|
||||
payload = {'name': wf.get('name', '$WF_NAME'), 'nodes': wf['nodes'], 'connections': wf['connections'], 'settings': wf.get('settings', {})}
|
||||
if wf.get('staticData'): payload['staticData'] = wf['staticData']
|
||||
with open('/tmp/n8n-push-payload.json', 'w') as f:
|
||||
json.dump(payload, f)
|
||||
"
|
||||
local CODE=$(curl -s -o /tmp/n8n-push-result.txt -w "%{http_code}" \
|
||||
-X PUT "${N8N_HOST}/api/v1/workflows/${WF_ID}" \
|
||||
-H "X-N8N-API-KEY: ${N8N_API_KEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @/tmp/n8n-push-payload.json)
|
||||
echo " ${WF_NAME}: HTTP ${CODE}"
|
||||
}
|
||||
|
||||
push_workflow "n8n-workflow.json" "HmiXBlJefBRPMS0m4iNYc" "Main"
|
||||
push_workflow "n8n-batch-ui.json" "ZJhnGzJT26UUmW45" "Batch UI"
|
||||
push_workflow "n8n-status.json" "lqpg2CqesnKE2RJQ" "Status"
|
||||
```
|
||||
|
||||
All three should return HTTP 200.
|
||||
|
||||
After deployment, verify the main workflow is still active:
|
||||
```bash
|
||||
. .env.n8n-api; curl -s -o /tmp/n8n-result.txt -w "%{http_code}" \
|
||||
"${N8N_HOST}/api/v1/workflows/HmiXBlJefBRPMS0m4iNYc" \
|
||||
-H "X-N8N-API-KEY: ${N8N_API_KEY}" \
|
||||
&& python3 -c "
|
||||
import json
|
||||
with open('/tmp/n8n-result.txt') as f:
|
||||
wf = json.load(f)
|
||||
print(f'Active: {wf[\"active\"]}')
|
||||
print(f'Nodes: {len(wf[\"nodes\"])}')
|
||||
"
|
||||
```
|
||||
|
||||
If not active, activate:
|
||||
```bash
|
||||
. .env.n8n-api; curl -s -X POST "${N8N_HOST}/api/v1/workflows/HmiXBlJefBRPMS0m4iNYc/activate" \
|
||||
-H "X-N8N-API-KEY: ${N8N_API_KEY}"
|
||||
```
|
||||
</action>
|
||||
<verify>All three workflows deploy with HTTP 200. Main workflow is active.</verify>
|
||||
<done>All modified workflows pushed to n8n. Main workflow active and running.</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<name>Task 3: User acceptance testing of all Phase 11 features</name>
|
||||
<action>
|
||||
User verifies all four BATCH requirements via Telegram bot interaction. See verification steps below.
|
||||
</action>
|
||||
<verify>
|
||||
**Test 1 - Batch selection with 5+ containers (BATCH-06):**
|
||||
1. Send "status" to the bot
|
||||
2. Tap "Select Multiple" in the container list
|
||||
3. Select 5 or more containers by tapping them (checkmarks should appear)
|
||||
4. Verify you can navigate pages while selection is preserved
|
||||
5. Expected: All selections work, no "Maximum selection reached" errors
|
||||
|
||||
**Test 2 - Long container names (BATCH-07):**
|
||||
1. In batch selection mode, select containers with names 20+ characters
|
||||
2. Expected: Selection works without errors
|
||||
|
||||
**Test 3 - Batch execution:**
|
||||
1. Select 2-3 containers in batch mode
|
||||
2. Tap "Start (N)" or "Stop (N)"
|
||||
3. Expected: Stop shows confirmation, Start executes immediately
|
||||
4. Verify the actions complete successfully
|
||||
|
||||
**Test 4 - Update All from keyboard (BATCH-05):**
|
||||
1. Send "status" to the bot
|
||||
2. Look for "Update All :latest" button below the container list
|
||||
3. Tap the button
|
||||
4. Expected: Confirmation dialog showing :latest containers with Confirm/Cancel buttons
|
||||
5. Tap Cancel to verify cancel works
|
||||
|
||||
**Test 5 - Update All from text (BATCH-04):**
|
||||
1. Send "update all" to the bot
|
||||
2. Expected: Same confirmation dialog as Test 4
|
||||
|
||||
**Test 6 - Regression: single container actions:**
|
||||
1. Send "status", tap a container, tap Stop/Start/Restart
|
||||
2. Expected: All actions work as before
|
||||
</verify>
|
||||
<done>All six test scenarios pass. BATCH-04 through BATCH-07 requirements satisfied. No regressions in existing functionality.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. All four success criteria from ROADMAP met:
|
||||
- User can type "update all" (BATCH-04, pre-existing + verified)
|
||||
- User can tap "Update All" in keyboard (BATCH-05, new button + routing)
|
||||
- Batch selection supports 5+ containers (BATCH-06, bitmap encoding)
|
||||
- Long container names work (BATCH-07, bitmap encoding)
|
||||
2. No regression to existing functionality (single actions, batch stop/start, pagination, etc.)
|
||||
3. All workflows deployed and active in n8n
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Container list inline keyboard shows "Update All :latest" button
|
||||
- Tapping the button triggers confirmation dialog with :latest container list
|
||||
- Batch selection works with 5+ containers (no callback limit error)
|
||||
- Containers with long names selectable in batch mode
|
||||
- All existing bot functionality unaffected
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/11-update-all-callback-limits/11-02-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user