ralphflow 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ralphflow.js CHANGED
@@ -231,6 +231,48 @@ function checkTrackerAllChecked(flowDir, loop) {
231
231
  const unchecked = (content.match(/- \[ \]/g) || []).length;
232
232
  return checked > 0 && unchecked === 0;
233
233
  }
234
+ function hasNewItemsInDataFile(flowDir, loop, config) {
235
+ if (!loop.entities || loop.entities.length === 0) return false;
236
+ const entityName = loop.entities[0];
237
+ const entity = config.entities?.[entityName];
238
+ if (!entity) return false;
239
+ const dataFilePath = join2(flowDir, entity.data_file);
240
+ if (!existsSync2(dataFilePath)) return false;
241
+ const trackerPath = join2(flowDir, loop.tracker);
242
+ if (!existsSync2(trackerPath)) return false;
243
+ const dataContent = readFileSync(dataFilePath, "utf-8");
244
+ const trackerContent = readFileSync(trackerPath, "utf-8");
245
+ const prefix = entity.prefix;
246
+ const itemRegex = new RegExp(`^## (${prefix}-\\d+):`, "gm");
247
+ const dataFileIds = [...dataContent.matchAll(itemRegex)].map((m) => m[1]);
248
+ if (dataFileIds.length === 0) return false;
249
+ const trackerIdRegex = new RegExp(`\\[[ x]\\]\\s*(${prefix}-\\d+)`, "gi");
250
+ const trackerIds = [...trackerContent.matchAll(trackerIdRegex)].map((m) => m[1]);
251
+ return dataFileIds.some((id) => !trackerIds.includes(id));
252
+ }
253
+ function stripStaleCompletion(flowDir, loop, config) {
254
+ if (!hasNewItemsInDataFile(flowDir, loop, config)) return false;
255
+ const trackerPath = join2(flowDir, loop.tracker);
256
+ if (!existsSync2(trackerPath)) return false;
257
+ let content = readFileSync(trackerPath, "utf-8");
258
+ const hadCompletion = content.includes(`<promise>${loop.completion}</promise>`) || content.includes(loop.completion);
259
+ if (!hadCompletion) return false;
260
+ content = content.replace(new RegExp(`<promise>${loop.completion}</promise>`, "g"), "");
261
+ content = content.replace(new RegExp(loop.completion, "g"), "");
262
+ writeFileSync(trackerPath, content);
263
+ console.log(chalk3.cyan(` \u21BB New items detected in data file \u2014 cleared stale completion for ${loop.name}`));
264
+ return true;
265
+ }
266
+ function stripCompletionString(flowDir, loop) {
267
+ const trackerPath = join2(flowDir, loop.tracker);
268
+ if (!existsSync2(trackerPath)) return;
269
+ let content = readFileSync(trackerPath, "utf-8");
270
+ const had = content.includes(`<promise>${loop.completion}</promise>`) || content.includes(loop.completion);
271
+ if (!had) return;
272
+ content = content.replace(new RegExp(`<promise>${loop.completion}</promise>`, "g"), "");
273
+ content = content.replace(new RegExp(loop.completion, "g"), "");
274
+ writeFileSync(trackerPath, content);
275
+ }
234
276
  async function runLoop(loopName, options) {
235
277
  const flowDir = resolveFlowDir(options.cwd, options.flow);
236
278
  const config = loadConfig(flowDir);
@@ -264,22 +306,25 @@ async function runLoop(loopName, options) {
264
306
  cleanup();
265
307
  process.exit(143);
266
308
  });
309
+ stripCompletionString(flowDir, loop);
267
310
  try {
268
- await iterationLoop(key, loop, flowDir, options, agentName);
311
+ await iterationLoop(key, loop, flowDir, options, agentName, void 0, void 0, true, config);
269
312
  } finally {
270
313
  cleanup();
271
314
  }
272
315
  }
273
- async function iterationLoop(configKey, loop, flowDir, options, agentName, db, flowName, forceFirstIteration) {
316
+ async function iterationLoop(configKey, loop, flowDir, options, agentName, db, flowName, forceFirstIteration, config) {
274
317
  const loopKey = loop.name;
275
318
  const appName = basename(flowDir);
319
+ if (config) stripStaleCompletion(flowDir, loop, config);
276
320
  for (let i = 1; i <= options.maxIterations; i++) {
277
321
  if (!(forceFirstIteration && i === 1)) {
278
322
  if (db && flowName && isLoopComplete(db, flowName, loopKey)) {
279
323
  console.log(chalk3.green(` \u2713 ${loop.name} \u2014 already complete`));
280
324
  return;
281
325
  }
282
- if (checkTrackerForCompletion(flowDir, loop) || checkTrackerMetadataCompletion(flowDir, loop) || checkTrackerAllChecked(flowDir, loop)) {
326
+ const newItemsExist = config ? hasNewItemsInDataFile(flowDir, loop, config) : false;
327
+ if (!newItemsExist && (checkTrackerForCompletion(flowDir, loop) || checkTrackerMetadataCompletion(flowDir, loop) || checkTrackerAllChecked(flowDir, loop))) {
283
328
  if (db && flowName) markLoopComplete(db, flowName, loopKey);
284
329
  console.log(chalk3.green(` \u2713 ${loop.name} \u2014 complete`));
285
330
  return;
@@ -301,7 +346,8 @@ async function iterationLoop(configKey, loop, flowDir, options, agentName, db, f
301
346
  skipPermissions: loop.skip_permissions
302
347
  });
303
348
  if (db && flowName) incrementIteration(db, flowName, loopKey);
304
- if (checkTrackerForCompletion(flowDir, loop) || checkTrackerMetadataCompletion(flowDir, loop) || checkTrackerAllChecked(flowDir, loop)) {
349
+ const newItemsAfter = config ? hasNewItemsInDataFile(flowDir, loop, config) : false;
350
+ if (!newItemsAfter && (checkTrackerForCompletion(flowDir, loop) || checkTrackerMetadataCompletion(flowDir, loop) || checkTrackerAllChecked(flowDir, loop))) {
305
351
  if (db && flowName) markLoopComplete(db, flowName, loopKey);
306
352
  console.log();
307
353
  console.log(chalk3.green(` Loop complete: ${loop.completion}`));
@@ -346,7 +392,8 @@ async function runE2E(options) {
346
392
  console.log(chalk3.green(` \u2713 ${loop.name} \u2014 complete, skipping`));
347
393
  continue;
348
394
  }
349
- if (checkTrackerForCompletion(flowDir, loop) || checkTrackerMetadataCompletion(flowDir, loop) || checkTrackerAllChecked(flowDir, loop)) {
395
+ const loopHasNewItems = hasNewItemsInDataFile(flowDir, loop, config);
396
+ if (!loopHasNewItems && (checkTrackerForCompletion(flowDir, loop) || checkTrackerMetadataCompletion(flowDir, loop) || checkTrackerAllChecked(flowDir, loop))) {
350
397
  markLoopComplete(db, flowName, loopKey);
351
398
  console.log(chalk3.green(` \u2713 ${loop.name} \u2014 complete, skipping`));
352
399
  continue;
@@ -362,7 +409,7 @@ async function runE2E(options) {
362
409
  agentName = acquireAgentId(agentDir, loop.multi_agent.max_agents);
363
410
  }
364
411
  try {
365
- await iterationLoop(key, loop, flowDir, options, agentName, db, flowName, isFirstLoop);
412
+ await iterationLoop(key, loop, flowDir, options, agentName, db, flowName, isFirstLoop, config);
366
413
  } finally {
367
414
  if (agentDir && agentName) releaseAgentId(agentDir, agentName);
368
415
  }
@@ -595,6 +642,39 @@ function buildPromptLoopConfig(loopDef) {
595
642
  stageConfigs
596
643
  };
597
644
  }
645
+ function generateVisualProtocol() {
646
+ let s = "";
647
+ s += `## Visual Communication Protocol
648
+
649
+ `;
650
+ s += `When communicating scope, structure, relationships, or status, render **ASCII diagrams** using Unicode box-drawing characters. These help the user see the full picture at the terminal without scrolling through prose.
651
+
652
+ `;
653
+ s += `**Character set:** \`\u250C \u2500 \u2510 \u2502 \u2514 \u2518 \u251C \u2524 \u252C \u2534 \u253C \u2550 \u25CF \u25CB \u25BC \u25B6\`
654
+
655
+ `;
656
+ s += `**Diagram types to use:**
657
+
658
+ `;
659
+ s += `- **Scope/Architecture Map** \u2014 components and their relationships in a bordered grid
660
+ `;
661
+ s += `- **Decomposition Tree** \u2014 hierarchical breakdown with \`\u251C\u2500\u2500\` and \`\u2514\u2500\u2500\` branches
662
+ `;
663
+ s += `- **Data Flow** \u2014 arrows (\`\u2500\u2500\u2192\`) showing how information moves between components
664
+ `;
665
+ s += `- **Comparison Table** \u2014 bordered table for trade-offs and design options
666
+ `;
667
+ s += `- **Status Summary** \u2014 bordered box with completion indicators (\`\u2713\` done, \`\u25CC\` pending)
668
+
669
+ `;
670
+ s += `**Rules:** Keep diagrams under 20 lines and under 70 characters wide. Populate with real data from current context. Render inside fenced code blocks. Use diagrams to supplement, not replace, prose.
671
+
672
+ `;
673
+ s += `---
674
+
675
+ `;
676
+ return s;
677
+ }
598
678
  function generatePromptFromConfig(loop, loopIndex, allLoops) {
599
679
  const loopName = loop.name || "Loop " + (loopIndex + 1);
600
680
  const inputFiles = (loop.inputFiles || "").trim();
@@ -641,6 +721,7 @@ function generatePromptFromConfig(loop, loopIndex, allLoops) {
641
721
  p += `---
642
722
 
643
723
  `;
724
+ p += generateVisualProtocol();
644
725
  if (loop.multi_agent) {
645
726
  p += `## Tracker Lock Protocol
646
727
 
@@ -800,14 +881,20 @@ function generatePromptFromConfig(loop, loopIndex, allLoops) {
800
881
  p += `---
801
882
 
802
883
  `;
803
- if (loop.multi_agent) {
804
- p += `## First-Run Handling
884
+ {
885
+ const scanFile = primaryInputFile || "input.md";
886
+ p += `## First-Run / New ${entityTitle} Detection
805
887
 
806
888
  `;
807
- const scanFile = primaryInputFile || "input.md";
808
- p += `If ${entityTitle}s Queue in tracker is empty: read \`${scanFile}\`, scan \`## ${entityKey}:\` headers, populate queue with \`{agent: -, status: pending|blocked}\` metadata (compute from Dependencies), then start.
889
+ if (loop.multi_agent) {
890
+ p += `If ${entityTitle}s Queue in tracker is empty OR all entries are \`[x]\`: read \`${scanFile}\`, scan \`## ${entityKey}:\` headers + \`**Depends on:**\` tags. For any ${entityLower} NOT already in the queue, add as \`- [ ] ${entityKey}: {title}\` with \`{agent: -, status: pending|blocked}\` metadata (compute from Dependencies), then start.
809
891
 
810
892
  `;
893
+ } else {
894
+ p += `If ${entityTitle}s Queue in tracker is empty OR all entries are \`[x]\`: read \`${scanFile}\`, scan \`## ${entityKey}:\` headers + \`**Depends on:**\` tags. For any ${entityLower} NOT already in the queue, add as \`- [ ] ${entityKey}: {title}\` and update Dependencies. If new ${entityPlural} were added, proceed to process them.
895
+
896
+ `;
897
+ }
811
898
  p += `---
812
899
 
813
900
  `;
@@ -857,6 +944,14 @@ function generatePromptFromConfig(loop, loopIndex, allLoops) {
857
944
  `;
858
945
  }
859
946
  }
947
+ if (i === 0) {
948
+ p += `${step++}. **Render a Scope Diagram** \u2014 output an ASCII architecture/scope map showing the areas this ${entityLower} touches, dependencies, and what needs to change
949
+ `;
950
+ }
951
+ if (i === stageCount - 1 && stageCount > 1) {
952
+ p += `${step++}. **Render a Completion Summary** \u2014 output an ASCII status diagram showing what was built/changed, verification results, and how this ${entityLower} fits in overall progress
953
+ `;
954
+ }
860
955
  if (loop.multi_agent) {
861
956
  p += `${step++}. Acquire lock \u2192 update tracker: stage, \`last_heartbeat\`, log entry \u2192 release lock
862
957
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralphflow",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Multi-agent AI workflow orchestration framework for Claude Code. Define pipelines as loops, coordinate parallel agents, and ship structured work.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -67,6 +67,26 @@ export function renderPromptConfigForm(loopIdx, loop, allLoops) {
67
67
  return html;
68
68
  }
69
69
 
70
+ // -----------------------------------------------------------------------
71
+ // Visual Communication Protocol for generated prompts
72
+ // -----------------------------------------------------------------------
73
+
74
+ function generateVisualProtocol() {
75
+ let s = '';
76
+ s += `## Visual Communication Protocol\n\n`;
77
+ s += `When communicating scope, structure, relationships, or status, render **ASCII diagrams** using Unicode box-drawing characters. These help the user see the full picture at the terminal without scrolling through prose.\n\n`;
78
+ s += `**Character set:** \`┌ ─ ┐ │ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ● ○ ▼ ▶\`\n\n`;
79
+ s += `**Diagram types to use:**\n\n`;
80
+ s += `- **Scope/Architecture Map** — components and their relationships in a bordered grid\n`;
81
+ s += `- **Decomposition Tree** — hierarchical breakdown with \`├──\` and \`└──\` branches\n`;
82
+ s += `- **Data Flow** — arrows (\`──→\`) showing how information moves between components\n`;
83
+ s += `- **Comparison Table** — bordered table for trade-offs and design options\n`;
84
+ s += `- **Status Summary** — bordered box with completion indicators (\`✓\` done, \`◌\` pending)\n\n`;
85
+ s += `**Rules:** Keep diagrams under 20 lines and under 70 characters wide. Populate with real data from current context. Render inside fenced code blocks. Use diagrams to supplement, not replace, prose.\n\n`;
86
+ s += `---\n\n`;
87
+ return s;
88
+ }
89
+
70
90
  // -----------------------------------------------------------------------
71
91
  // Prompt generation engine
72
92
  // -----------------------------------------------------------------------
@@ -114,6 +134,9 @@ export function generatePromptFromConfig(loop, loopIndex, allLoops) {
114
134
  p += `**Pipeline:** \`${pipelineIn} → YOU → ${pipelineOut}\`\n\n`;
115
135
  p += `---\n\n`;
116
136
 
137
+ // ── VISUAL COMMUNICATION PROTOCOL ──
138
+ p += generateVisualProtocol();
139
+
117
140
  // ── MULTI-AGENT SECTIONS (conditional) ──
118
141
  if (loop.multi_agent) {
119
142
  // Tracker Lock Protocol
@@ -199,11 +222,15 @@ export function generatePromptFromConfig(loop, loopIndex, allLoops) {
199
222
  p += `After completing ANY stage, exit: \`kill -INT $PPID\`\n\n`;
200
223
  p += `---\n\n`;
201
224
 
202
- // ── FIRST-RUN HANDLING ──
203
- if (loop.multi_agent) {
204
- p += `## First-Run Handling\n\n`;
225
+ // ── FIRST-RUN / NEW ITEM DETECTION ──
226
+ {
205
227
  const scanFile = primaryInputFile || 'input.md';
206
- p += `If ${entityTitle}s Queue in tracker is empty: read \`${scanFile}\`, scan \`## ${entityKey}:\` headers, populate queue with \`{agent: -, status: pending|blocked}\` metadata (compute from Dependencies), then start.\n\n`;
228
+ p += `## First-Run / New ${entityTitle} Detection\n\n`;
229
+ if (loop.multi_agent) {
230
+ p += `If ${entityTitle}s Queue in tracker is empty OR all entries are \`[x]\`: read \`${scanFile}\`, scan \`## ${entityKey}:\` headers + \`**Depends on:**\` tags. For any ${entityLower} NOT already in the queue, add as \`- [ ] ${entityKey}: {title}\` with \`{agent: -, status: pending|blocked}\` metadata (compute from Dependencies), then start.\n\n`;
231
+ } else {
232
+ p += `If ${entityTitle}s Queue in tracker is empty OR all entries are \`[x]\`: read \`${scanFile}\`, scan \`## ${entityKey}:\` headers + \`**Depends on:**\` tags. For any ${entityLower} NOT already in the queue, add as \`- [ ] ${entityKey}: {title}\` and update Dependencies. If new ${entityPlural} were added, proceed to process them.\n\n`;
233
+ }
207
234
  p += `---\n\n`;
208
235
  }
209
236
 
@@ -248,6 +275,14 @@ export function generatePromptFromConfig(loop, loopIndex, allLoops) {
248
275
  }
249
276
  }
250
277
 
278
+ // Visual diagram trigger
279
+ if (i === 0) {
280
+ p += `${step++}. **Render a Scope Diagram** — output an ASCII architecture/scope map showing the areas this ${entityLower} touches, dependencies, and what needs to change\n`;
281
+ }
282
+ if (i === stageCount - 1 && stageCount > 1) {
283
+ p += `${step++}. **Render a Completion Summary** — output an ASCII status diagram showing what was built/changed, verification results, and how this ${entityLower} fits in overall progress\n`;
284
+ }
285
+
251
286
  // Tracker update
252
287
  if (loop.multi_agent) {
253
288
  p += `${step++}. Acquire lock → update tracker: stage, \`last_heartbeat\`, log entry → release lock\n`;
@@ -1474,6 +1474,27 @@ body {
1474
1474
  font-weight: 600;
1475
1475
  margin-bottom: 8px;
1476
1476
  }
1477
+ .wizard-description-ref {
1478
+ border-left: 3px solid var(--accent);
1479
+ padding: 8px 12px;
1480
+ margin-bottom: 16px;
1481
+ background: rgba(99, 102, 241, 0.06);
1482
+ border-radius: 0 6px 6px 0;
1483
+ }
1484
+ .wizard-description-ref-label {
1485
+ font-size: 10px;
1486
+ text-transform: uppercase;
1487
+ letter-spacing: 0.5px;
1488
+ color: var(--accent);
1489
+ font-weight: 600;
1490
+ }
1491
+ .wizard-description-ref p {
1492
+ margin: 4px 0 0;
1493
+ font-size: 13px;
1494
+ color: var(--text-secondary);
1495
+ line-height: 1.5;
1496
+ font-style: italic;
1497
+ }
1477
1498
  .wizard-hint {
1478
1499
  font-size: 13px;
1479
1500
  color: var(--text-dim);
@@ -248,6 +248,9 @@ function renderTemplateWizard() {
248
248
  } else if (step === 1) {
249
249
  // Step 2: Define pipeline steps
250
250
  html += '<div class="wizard-step-card">';
251
+ if (wd.description) {
252
+ html += `<div class="wizard-description-ref"><span class="wizard-description-ref-label">Your description</span><p>${esc(wd.description)}</p></div>`;
253
+ }
251
254
  html += '<h3 class="wizard-question">Define your pipeline steps</h3>';
252
255
  html += '<p class="wizard-hint">Each step becomes a loop. For each, give it a name and optionally list its stages (comma-separated). Stages define what the AI agent does in each iteration cycle.</p>';
253
256
  html += '<div class="wizard-loops-list" id="wizardLoopsList">';
@@ -12,13 +12,39 @@ Read `.ralph-flow/{{APP_NAME}}/00-story-loop/tracker.md` FIRST to determine wher
12
12
 
13
13
  ---
14
14
 
15
+ ## Visual Communication Protocol
16
+
17
+ When communicating scope, structure, relationships, or status, render **ASCII diagrams** using Unicode box-drawing characters. These help the user see the full picture at the terminal without scrolling through prose.
18
+
19
+ **Character set:** `┌ ─ ┐ │ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ● ○ ▼ ▶`
20
+
21
+ **Diagram types to use:**
22
+
23
+ - **Scope/Architecture Map** — components and their relationships in a bordered grid
24
+ - **Decomposition Tree** — hierarchical breakdown with `├──` and `└──` branches
25
+ - **Data Flow** — arrows (`──→`) showing how information moves between components
26
+ - **Comparison Table** — bordered table for trade-offs and design options
27
+ - **Status Summary** — bordered box with completion indicators (`✓` done, `◌` pending)
28
+
29
+ **Rules:** Keep diagrams under 20 lines and under 70 characters wide. Populate with real data from current context. Render inside fenced code blocks. Use diagrams to supplement, not replace, prose.
30
+
31
+ ---
32
+
15
33
  ## State Machine (3 stages per story)
16
34
 
17
35
  **FIRST — Check completion.** Read the tracker. If the Stories Queue has entries
18
- AND every entry is `[x]` (no pending stories), do NOT write the completion promise yet.
19
- Instead, go to **"No Stories? Collect Them"** to ask the user for new stories.
36
+ AND every entry is `[x]` (no pending stories):
37
+ 1. **Re-scan `stories.md`** read all `## STORY-{N}:` headers and compare
38
+ against the Stories Queue in the tracker.
39
+ 2. **New stories found** (in `stories.md` but not in the queue) → add them as
40
+ `- [ ] STORY-{N}: {title}` to the Stories Queue, update the Dependency Graph
41
+ from their `**Depends on:**` tags, then proceed to process the lowest-numbered
42
+ ready story via the normal state machine.
43
+ 3. **No new stories** → go to **"No Stories? Collect Them"** to ask the user.
44
+
20
45
  Only write `<promise>ALL STORIES PROCESSED</promise>` when the user explicitly
21
- confirms they have no more stories to add.
46
+ confirms they have no more stories to add AND `stories.md` has no stories
47
+ missing from the tracker queue.
22
48
 
23
49
  Pick the lowest-numbered `ready` story. NEVER process a `blocked` story.
24
50
 
@@ -28,7 +54,8 @@ Pick the lowest-numbered `ready` story. NEVER process a `blocked` story.
28
54
 
29
55
  **Triggers when:**
30
56
  - `stories.md` has no stories at all (first run, empty queue with no entries), OR
31
- - All stories in the queue are completed (`[x]`) and there are no `pending` stories left
57
+ - All stories in the queue are completed (`[x]`), no `pending` stories remain, AND
58
+ `stories.md` has been re-scanned and contains no stories missing from the queue
32
59
 
33
60
  **Flow:**
34
61
  1. Tell the user: *"No pending stories. Tell me what you want to build — describe features, problems, or goals in your own words."*
@@ -45,9 +72,13 @@ CLARIFY → Ask user up to 20 questions (5 at a time) → stage: decompose
45
72
  DECOMPOSE → Break into TASK-GROUP(s) + tasks, append to tasks.md, mark done → kill
46
73
  ```
47
74
 
48
- ## First-Run Handling
75
+ ## First-Run / New Story Detection
49
76
 
50
- If Stories Queue in tracker is empty: read `stories.md`, scan `## STORY-{N}:` headers + `**Depends on:**` tags, populate queue as `- [ ] STORY-{N}: {title}`, build Dependency Graph.
77
+ If Stories Queue in tracker is empty OR all entries are `[x]`: read `stories.md`,
78
+ scan `## STORY-{N}:` headers + `**Depends on:**` tags. For any story NOT already
79
+ in the queue, add as `- [ ] STORY-{N}: {title}` and build/update the Dependency Graph.
80
+ If new stories were added, proceed to process them. If the queue is still empty
81
+ after scanning, go to **"No Stories? Collect Them"**.
51
82
 
52
83
  ---
53
84
 
@@ -56,23 +87,32 @@ If Stories Queue in tracker is empty: read `stories.md`, scan `## STORY-{N}:` he
56
87
  1. Read tracker → pick lowest-numbered `ready` story
57
88
  2. Read the story from `stories.md` (+ any referenced screenshots)
58
89
  3. **Explore the codebase** — read `CLAUDE.md` for project context, then **20+ key files** across the areas this story touches. Understand current behavior, patterns, conventions, and what needs to change.
59
- 4. Update tracker: `active_story: STORY-{N}`, `stage: clarify`, log entry
90
+ 4. **Render a Scope Map** output an ASCII architecture/scope diagram showing:
91
+ - The areas of the codebase this story touches (components, modules, services)
92
+ - Dependencies and data flow between affected areas
93
+ - What exists today (`●`) vs. what needs to change (`○`)
94
+ 5. Update tracker: `active_story: STORY-{N}`, `stage: clarify`, log entry
60
95
 
61
96
  ## STAGE 2: CLARIFY
62
97
 
63
98
  1. Formulate questions about scope, priorities, edge cases, design choices
64
- 2. **Ask up to 20 questions, 5 at a time** via `AskUserQuestion` (with options where possible):
99
+ 2. **Present understanding diagram first** render an ASCII scope/architecture diagram showing your understanding of the story's scope. This gives the user a visual anchor to correct misconceptions before answering questions.
100
+ 3. **Ask up to 20 questions, 5 at a time** via `AskUserQuestion` — structure each round visually:
101
+ - For multi-option decisions: numbered list with one-line descriptions
102
+ - For design trade-offs: include a **comparison table** showing trade-offs (e.g., approach vs. complexity vs. speed)
103
+ - For scope boundaries: use an in/out list format
65
104
  - Round 1: Scope, intent, must-haves
66
105
  - Round 2+: Design choices, edge cases, preferences — based on prior answers
67
106
  - Stop early if clear enough
68
- 3. Save Q&A summary in tracker log
69
- 4. Update tracker: `stage: decompose`, log entry with key decisions
107
+ 4. Save Q&A summary in tracker log
108
+ 5. Update tracker: `stage: decompose`, log entry with key decisions
70
109
 
71
110
  ## STAGE 3: DECOMPOSE
72
111
 
73
112
  1. Find next TASK-GROUP and TASK numbers (check existing in `01-tasks-loop/tasks.md`)
74
113
  2. **Read already-written tasks** — if sibling tasks exist, read them to align scope boundaries
75
- 3. Break story into TASK-GROUP(s) one per distinct functional area, 2-6 tasks each
114
+ 3. **Render a Decomposition Tree** — output an ASCII tree showing the planned TASK-GROUP(s) and their tasks, with dependency arrows between tasks that depend on each other
115
+ 4. Break story into TASK-GROUP(s) — one per distinct functional area, 2-6 tasks each
76
116
  4. For each task, ask yourself: *What does success look like? How would someone confirm? What could silently break?*
77
117
  5. **Sanity-check:** Do NOT embed specific file paths in tasks — describe *what* changes, not *where*. The tasks loop will explore the codebase itself.
78
118
  6. Append to `01-tasks-loop/tasks.md` (format below)
@@ -14,6 +14,24 @@ Read `.ralph-flow/{{APP_NAME}}/01-tasks-loop/tracker.md` FIRST to determine wher
14
14
 
15
15
  ---
16
16
 
17
+ ## Visual Communication Protocol
18
+
19
+ When communicating scope, structure, relationships, or status, render **ASCII diagrams** using Unicode box-drawing characters. These help the user see the full picture at the terminal without scrolling through prose.
20
+
21
+ **Character set:** `┌ ─ ┐ │ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ● ○ ▼ ▶`
22
+
23
+ **Diagram types to use:**
24
+
25
+ - **Scope/Architecture Map** — components and their relationships in a bordered grid
26
+ - **Decomposition Tree** — hierarchical breakdown with `├──` and `└──` branches
27
+ - **Data Flow** — arrows (`──→`) showing how information moves between components
28
+ - **Comparison Table** — bordered table for trade-offs and design options
29
+ - **Status Summary** — bordered box with completion indicators (`✓` done, `◌` pending)
30
+
31
+ **Rules:** Keep diagrams under 20 lines and under 70 characters wide. Populate with real data from current context. Render inside fenced code blocks. Use diagrams to supplement, not replace, prose.
32
+
33
+ ---
34
+
17
35
  ## Tracker Lock Protocol
18
36
 
19
37
  Before ANY write to `tracker.md`, you MUST acquire the lock:
@@ -112,7 +130,11 @@ After completing ANY stage, exit: `kill -INT $PPID`
112
130
  3. If sibling tasks are done, read their commits/diffs to align
113
131
  4. Read `CLAUDE.md` for project context
114
132
  5. Explore codebase — **40+ files:** affected areas, dependencies, patterns
115
- 6. Acquire lock update tracker: your Agent Status row `active_task: TASK-{N}`, `stage: execute`, `last_heartbeat`, log entry → release lock
133
+ 6. **Render an Implementation Map** output an ASCII diagram showing:
134
+ - Files/modules to create or modify (grouped by area)
135
+ - Data flow or control flow for the change
136
+ - How this task's changes connect to sibling tasks in the group
137
+ 7. Acquire lock → update tracker: your Agent Status row `active_task: TASK-{N}`, `stage: execute`, `last_heartbeat`, log entry → release lock
116
138
  7. Implement changes. Match existing patterns per `CLAUDE.md`.
117
139
  8. Deploy/rebuild (commands in `CLAUDE.md`)
118
140
  9. **Quick verify:** check container logs for errors, hit health endpoints, confirm no crashes
@@ -126,7 +148,11 @@ After completing ANY stage, exit: `kill -INT $PPID`
126
148
  3. **Functional verify:** test the actual change — hit new/modified endpoints, check DB state, verify expected behavior through CLI/curl/API calls
127
149
  4. **FAIL** → fix the issue, re-deploy, re-verify. If stuck, log details in tracker and move on
128
150
  5. **PASS** → continue to documentation
129
- 6. Update `CLAUDE.md` (≤150 words net). Commit separately.
151
+ 6. **Render a Completion Summary** output an ASCII status diagram showing:
152
+ - What was built/changed (files, endpoints, components)
153
+ - Verification results (pass/fail per acceptance criterion)
154
+ - How this task fits in the TASK-GROUP progress
155
+ 7. Update `CLAUDE.md` (≤150 words net). Commit separately.
130
156
  7. Create/update `.claude/skills/` if this task produced reusable knowledge. Skip if nothing reusable.
131
157
  8. **Mark done & unblock dependents:**
132
158
  - Acquire lock
@@ -12,6 +12,24 @@ Read `.ralph-flow/{{APP_NAME}}/02-delivery-loop/tracker.md` FIRST to determine w
12
12
 
13
13
  ---
14
14
 
15
+ ## Visual Communication Protocol
16
+
17
+ When communicating scope, structure, relationships, or status, render **ASCII diagrams** using Unicode box-drawing characters. These help the user see the full picture at the terminal without scrolling through prose.
18
+
19
+ **Character set:** `┌ ─ ┐ │ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ● ○ ▼ ▶`
20
+
21
+ **Diagram types to use:**
22
+
23
+ - **Scope/Architecture Map** — components and their relationships in a bordered grid
24
+ - **Decomposition Tree** — hierarchical breakdown with `├──` and `└──` branches
25
+ - **Data Flow** — arrows (`──→`) showing how information moves between components
26
+ - **Comparison Table** — bordered table for trade-offs and design options
27
+ - **Status Summary** — bordered box with completion indicators (`✓` done, `◌` pending)
28
+
29
+ **Rules:** Keep diagrams under 20 lines and under 70 characters wide. Populate with real data from current context. Render inside fenced code blocks. Use diagrams to supplement, not replace, prose.
30
+
31
+ ---
32
+
15
33
  ## First-Run Handling
16
34
 
17
35
  If Delivery Queue is empty, build it by scanning the task tracker:
@@ -47,18 +65,23 @@ Phase 1 → Phase 2 flows continuously in one iteration (no kill between them).
47
65
  2. Read phase plans from `01-tasks-loop/phases/`
48
66
  3. Read `CLAUDE.md` for project context
49
67
  4. **Review independently:** Walk through each task's verification steps. Note anything wrong, broken, or inconsistent. Build a presentation narrative.
50
- 5. For cancelled tasks/groups: note what was superseded and why
68
+ 5. **Build a Delivery Diagram** prepare an ASCII diagram for presentation showing:
69
+ - All task-groups in this story with completion status
70
+ - Per-task status (`✓` done, `✗` cancelled, `!` issues found)
71
+ - Data flow or architecture of what was built
72
+ 6. For cancelled tasks/groups: note what was superseded and why
51
73
  6. Record review notes in tracker log
52
74
  7. Update tracker: `active_story: STORY-{N}`, `stage: present-and-feedback`
53
75
  8. **Flow directly into Phase 2** (no stop)
54
76
 
55
77
  ## PHASE 2: PRESENT-AND-FEEDBACK (combined, one AskUserQuestion call)
56
78
 
57
- 1. **Present structured walkthrough** of ALL task-groups in the story:
58
- - Per task-group: what was built (plain language), how to verify it
79
+ 1. **Present structured walkthrough with diagrams:**
80
+ - Open with an ASCII **architecture/scope diagram** showing what was built (components, data flow, integrations)
81
+ - Per task-group: what was built (plain language), completion status, how to verify it
59
82
  - Any issues the agent found during Phase 1 review
60
83
  - Cancelled tasks/groups with brief explanation of what was superseded
61
- 2. **Ask 3-4 questions in ONE `AskUserQuestion` call:**
84
+ 2. **Ask 3-4 questions in ONE `AskUserQuestion` call** — use visual grouping:
62
85
  - **Q1: Working correctly?** Does everything work as expected? Note any specific issues.
63
86
  - **Q2: Behavior or appearance?** Anything to change about look, feel, or behavior?
64
87
  - **Q3: Missing or new ideas?** Anything missing, or new ideas sparked by what you see?
@@ -12,13 +12,37 @@ Read `.ralph-flow/{{APP_NAME}}/00-discovery-loop/tracker.md` FIRST to determine
12
12
 
13
13
  ---
14
14
 
15
+ ## Visual Communication Protocol
16
+
17
+ When communicating scope, structure, relationships, or status, render **ASCII diagrams** using Unicode box-drawing characters. These help the user see the full picture at the terminal without scrolling through prose.
18
+
19
+ **Character set:** `┌ ─ ┐ │ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ● ○ ▼ ▶`
20
+
21
+ **Diagram types to use:**
22
+
23
+ - **Scope/Architecture Map** — components and their relationships in a bordered grid
24
+ - **Decomposition Tree** — hierarchical breakdown with `├──` and `└──` branches
25
+ - **Data Flow** — arrows (`──→`) showing how information moves between components
26
+ - **Comparison Table** — bordered table for trade-offs and design options
27
+ - **Status Summary** — bordered box with completion indicators (`✓` done, `◌` pending)
28
+
29
+ **Rules:** Keep diagrams under 20 lines and under 70 characters wide. Populate with real data from current context. Render inside fenced code blocks. Use diagrams to supplement, not replace, prose.
30
+
31
+ ---
32
+
15
33
  ## No Brief? Collect One
16
34
 
35
+ If the tracker queue has entries and all are `[x]`:
36
+ 1. **Re-scan `topics.md`** — read all `## TOPIC-{N}:` headers and compare against
37
+ the Topics Queue in the tracker. If new topics found, add them as
38
+ `- [ ] TOPIC-{N}: {title}` with appropriate metadata and proceed to process them.
39
+ 2. **No new topics** → proceed to "No Brief? Collect One" below.
40
+
17
41
  If `topics.md` has no unprocessed topics and the tracker queue is empty/all done:
18
42
  1. Tell the user: *"No research brief found. Tell me what you want to research — describe questions, problems, or domains you want to understand."*
19
43
  2. Use `AskUserQuestion` to prompt: "What do you want to research or understand?" (open-ended)
20
44
  3. As the user narrates, capture the research brief in tracker log under `## Research Brief`
21
- 4. **Confirm scope** — present the brief back. Use `AskUserQuestion` (up to 5 questions) to validate: correct scope? right depth? any areas to include/exclude? target audience? desired output format (PDF, PPT, document)?
45
+ 4. **Confirm scope with a visual summary** — render an ASCII scope map showing the research boundaries, then use `AskUserQuestion` (up to 5 questions) to validate: correct scope? right depth? any areas to include/exclude? target audience? desired output format (PDF, PPT, document)?
22
46
  5. Apply corrections, finalize brief, proceed to normal flow
23
47
 
24
48
  ---
@@ -31,9 +55,14 @@ EXPLORE → Search broadly for sub-domains, angles, key questions → stage: de
31
55
  DECOMPOSE → Break into TOPIC entries, write to topics.md, seed research tracker → kill
32
56
  ```
33
57
 
34
- ## First-Run Handling
58
+ ## First-Run / New Topic Detection
35
59
 
36
- If Topics Queue in tracker is empty and Research Brief exists: proceed to SCOPE. If Topics Queue is populated, check for remaining unprocessed items.
60
+ If Topics Queue in tracker is empty OR all entries are `[x]`: read `topics.md`,
61
+ scan `## TOPIC-{N}:` headers + `**Depends on:**` tags. For any topic NOT already
62
+ in the queue, add as `- [ ] TOPIC-{N}: {title}` with appropriate metadata, and
63
+ update Dependencies. If new topics were added, proceed to process them.
64
+ If the queue remains empty and Research Brief exists: proceed to SCOPE.
65
+ If Topics Queue is populated with unchecked items, check for remaining unprocessed items.
37
66
 
38
67
  ---
39
68
 
@@ -46,7 +75,8 @@ If Topics Queue in tracker is empty and Research Brief exists: proceed to SCOPE.
46
75
  - What depth is needed (surface survey vs. deep dive)
47
76
  - Who is the audience (technical, executive, public)
48
77
  - What output format is expected
49
- 4. Update tracker: `stage: explore`, log entry with scope decisions
78
+ 4. **Render a Scope Map** output an ASCII diagram showing research domain boundaries (in-scope vs. out), key sub-domains identified, audience and depth indicators
79
+ 5. Update tracker: `stage: explore`, log entry with scope decisions
50
80
 
51
81
  ## STAGE 2: EXPLORE
52
82
 
@@ -61,7 +91,8 @@ If Topics Queue in tracker is empty and Research Brief exists: proceed to SCOPE.
61
91
  ## STAGE 3: DECOMPOSE
62
92
 
63
93
  1. Find next TOPIC numbers (check existing in `00-discovery-loop/topics.md`)
64
- 2. Break the research space into **5-15 specific topics**, each:
94
+ 2. **Render a Topic Tree** output an ASCII decomposition tree showing all planned topics with priority markers (H/M/L), dependency arrows between topics, and estimated depth indicators (surface/moderate/deep)
95
+ 3. Break the research space into **5-15 specific topics**, each:
65
96
  - Independently researchable by a single agent
66
97
  - Specific enough to produce focused findings (not "research everything about X")
67
98
  - Clearly scoped with guiding questions
@@ -14,6 +14,24 @@ Read `.ralph-flow/{{APP_NAME}}/01-research-loop/tracker.md` FIRST to determine w
14
14
 
15
15
  ---
16
16
 
17
+ ## Visual Communication Protocol
18
+
19
+ When communicating scope, structure, relationships, or status, render **ASCII diagrams** using Unicode box-drawing characters. These help the user see the full picture at the terminal without scrolling through prose.
20
+
21
+ **Character set:** `┌ ─ ┐ │ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ● ○ ▼ ▶`
22
+
23
+ **Diagram types to use:**
24
+
25
+ - **Scope/Architecture Map** — components and their relationships in a bordered grid
26
+ - **Decomposition Tree** — hierarchical breakdown with `├──` and `└──` branches
27
+ - **Data Flow** — arrows (`──→`) showing how information moves between components
28
+ - **Comparison Table** — bordered table for trade-offs and design options
29
+ - **Status Summary** — bordered box with completion indicators (`✓` done, `◌` pending)
30
+
31
+ **Rules:** Keep diagrams under 20 lines and under 70 characters wide. Populate with real data from current context. Render inside fenced code blocks. Use diagrams to supplement, not replace, prose.
32
+
33
+ ---
34
+
17
35
  ## Tracker Lock Protocol
18
36
 
19
37
  Before ANY write to `tracker.md`, you MUST acquire the lock:
@@ -117,7 +135,8 @@ After completing ANY stage, exit: `kill -INT $PPID`
117
135
  - Note data points, statistics, quotes, and source URLs
118
136
  - If the topic requires it, explore primary sources (government sites, official reports)
119
137
  6. **Organize raw notes** — keep structured scratch notes as you research
120
- 7. Acquire lock update tracker: `stage: synthesize`, `last_heartbeat`, log entry release lock
138
+ 7. **Render an Evidence Map** output an ASCII diagram showing key findings organized by sub-theme, source quality indicators, consensus vs. disagreement areas, and gaps that need attention
139
+ 8. Acquire lock → update tracker: `stage: synthesize`, `last_heartbeat`, log entry → release lock
121
140
  8. Exit: `kill -INT $PPID`
122
141
 
123
142
  ## STAGE 2: SYNTHESIZE
@@ -128,7 +147,8 @@ After completing ANY stage, exit: `kill -INT $PPID`
128
147
  - Include specific data points, statistics, and source citations
129
148
  - Note confidence level for each key claim
130
149
  - Flag gaps — what couldn't be found, what needs primary research
131
- 3. Acquire lock:
150
+ 3. **Render a Findings Summary** — output an ASCII status diagram showing key claims with confidence levels (H/M/L), how this topic connects to sibling topics, and gaps flagged for follow-up
151
+ 4. Acquire lock:
132
152
  - Add topic to `completed_topics` list
133
153
  - Check off topic in Topics Queue: `[x]`, set `{completed}`
134
154
  - **Unblock dependents:** for each topic in `## Dependencies` that lists the just-completed topic, check if ALL its dependencies are now in `completed_topics`. If yes, update that topic's status from `blocked` → `pending`
@@ -12,6 +12,24 @@ Read `.ralph-flow/{{APP_NAME}}/02-story-loop/tracker.md` FIRST to determine wher
12
12
 
13
13
  ---
14
14
 
15
+ ## Visual Communication Protocol
16
+
17
+ When communicating scope, structure, relationships, or status, render **ASCII diagrams** using Unicode box-drawing characters. These help the user see the full picture at the terminal without scrolling through prose.
18
+
19
+ **Character set:** `┌ ─ ┐ │ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ● ○ ▼ ▶`
20
+
21
+ **Diagram types to use:**
22
+
23
+ - **Scope/Architecture Map** — components and their relationships in a bordered grid
24
+ - **Decomposition Tree** — hierarchical breakdown with `├──` and `└──` branches
25
+ - **Data Flow** — arrows (`──→`) showing how information moves between components
26
+ - **Comparison Table** — bordered table for trade-offs and design options
27
+ - **Status Summary** — bordered box with completion indicators (`✓` done, `◌` pending)
28
+
29
+ **Rules:** Keep diagrams under 20 lines and under 70 characters wide. Populate with real data from current context. Render inside fenced code blocks. Use diagrams to supplement, not replace, prose.
30
+
31
+ ---
32
+
15
33
  ## No Findings? Wait
16
34
 
17
35
  If `findings.md` has no unprocessed findings and the tracker queue is empty/all done:
@@ -47,7 +65,8 @@ If Stories Queue in tracker is empty:
47
65
  1. Read tracker → pick next unprocessed story from queue
48
66
  2. Read ALL source findings for this story from `findings.md`
49
67
  3. Read completed stories from `stories.md` to maintain consistency and avoid repetition
50
- 4. **Draft the narrative:**
68
+ 4. **Render a Narrative Map** — output an ASCII diagram showing source findings and how they connect to this story's theme, the narrative arc (hook → evidence → implications), and how this story relates to other completed/planned stories
69
+ 5. **Draft the narrative:**
51
70
  - Open with a compelling hook or framing question
52
71
  - Build the argument/narrative logically
53
72
  - Weave in specific data points, statistics, and evidence from findings
@@ -12,6 +12,24 @@ Read `.ralph-flow/{{APP_NAME}}/03-document-loop/tracker.md` FIRST to determine w
12
12
 
13
13
  ---
14
14
 
15
+ ## Visual Communication Protocol
16
+
17
+ When communicating scope, structure, relationships, or status, render **ASCII diagrams** using Unicode box-drawing characters. These help the user see the full picture at the terminal without scrolling through prose.
18
+
19
+ **Character set:** `┌ ─ ┐ │ └ ┘ ├ ┤ ┬ ┴ ┼ ═ ● ○ ▼ ▶`
20
+
21
+ **Diagram types to use:**
22
+
23
+ - **Scope/Architecture Map** — components and their relationships in a bordered grid
24
+ - **Decomposition Tree** — hierarchical breakdown with `├──` and `└──` branches
25
+ - **Data Flow** — arrows (`──→`) showing how information moves between components
26
+ - **Comparison Table** — bordered table for trade-offs and design options
27
+ - **Status Summary** — bordered box with completion indicators (`✓` done, `◌` pending)
28
+
29
+ **Rules:** Keep diagrams under 20 lines and under 70 characters wide. Populate with real data from current context. Render inside fenced code blocks. Use diagrams to supplement, not replace, prose.
30
+
31
+ ---
32
+
15
33
  ## STAGE 1: COMPILE
16
34
 
17
35
  1. **Read context:**
@@ -24,7 +42,8 @@ Read `.ralph-flow/{{APP_NAME}}/03-document-loop/tracker.md` FIRST to determine w
24
42
  - "What format should the final document be? (markdown/pdf/ppt/html)" with options
25
43
  - Also ask: "Any specific structure, branding, or style requirements?"
26
44
 
27
- 3. **Plan document structure:**
45
+ 3. **Render a Document Blueprint** — output an ASCII diagram showing document sections in reading order with estimated word counts, story-to-section mapping, and appendix structure
46
+ 4. **Plan document structure:**
28
47
  - Executive summary / abstract
29
48
  - Table of contents
30
49
  - Arrange stories in logical reading order (not necessarily story-number order)