ralphflow 0.5.0 → 0.5.1

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.
@@ -0,0 +1,115 @@
1
+ // Shared utility functions used across dashboard modules.
2
+
3
+ export function esc(s) {
4
+ if (s == null) return '';
5
+ const d = document.createElement('div');
6
+ d.textContent = String(s);
7
+ return d.innerHTML;
8
+ }
9
+
10
+ export async function fetchJson(url) {
11
+ const res = await fetch(url);
12
+ return res.json();
13
+ }
14
+
15
+ export function renderMarkdown(md) {
16
+ let html = '';
17
+ const lines = md.split('\n');
18
+ let inTable = false;
19
+ let tableHtml = '';
20
+
21
+ for (let i = 0; i < lines.length; i++) {
22
+ const line = lines[i];
23
+
24
+ // Table detection
25
+ if (line.match(/^\|.+\|$/)) {
26
+ if (!inTable) {
27
+ inTable = true;
28
+ tableHtml = '<table>';
29
+ // Header row
30
+ const cells = line.split('|').filter(Boolean).map(c => c.trim());
31
+ tableHtml += '<thead><tr>' + cells.map(c => `<th>${esc(c)}</th>`).join('') + '</tr></thead><tbody>';
32
+ continue;
33
+ }
34
+ // Separator row
35
+ if (line.match(/^\|[\s\-|]+\|$/)) continue;
36
+ // Data row
37
+ const cells = line.split('|').filter(Boolean).map(c => c.trim());
38
+ tableHtml += '<tr>' + cells.map(c => `<td>${esc(c)}</td>`).join('') + '</tr>';
39
+ continue;
40
+ } else if (inTable) {
41
+ inTable = false;
42
+ tableHtml += '</tbody></table>';
43
+ html += tableHtml;
44
+ tableHtml = '';
45
+ }
46
+
47
+ // Headers
48
+ if (line.startsWith('### ')) { html += `<h3>${esc(line.slice(4))}</h3>`; continue; }
49
+ if (line.startsWith('## ')) { html += `<h2>${esc(line.slice(3))}</h2>`; continue; }
50
+ if (line.startsWith('# ')) { html += `<h1>${esc(line.slice(2))}</h1>`; continue; }
51
+
52
+ // Checkboxes
53
+ if (line.match(/^- \[x\]/i)) {
54
+ html += `<div class="cb-done">${esc(line)}</div>`;
55
+ continue;
56
+ }
57
+ if (line.match(/^- \[ \]/)) {
58
+ html += `<div class="cb-todo">${esc(line)}</div>`;
59
+ continue;
60
+ }
61
+
62
+ // Regular lines
63
+ html += line.trim() === '' ? '<br>' : `<div>${esc(line)}</div>`;
64
+ }
65
+
66
+ if (inTable) {
67
+ tableHtml += '</tbody></table>';
68
+ html += tableHtml;
69
+ }
70
+
71
+ return html;
72
+ }
73
+
74
+ export function calculatePipelineProgress(loops) {
75
+ const perLoop = [];
76
+ let aggCompleted = 0;
77
+ let aggTotal = 0;
78
+ for (const loop of (loops || [])) {
79
+ const st = loop.status || {};
80
+ const completed = st.completed || 0;
81
+ const total = st.total || 0;
82
+ const fraction = total > 0 ? completed / total : 0;
83
+ perLoop.push({ key: loop.key, completed, total, fraction });
84
+ if (total > 0) {
85
+ aggCompleted += completed;
86
+ aggTotal += total;
87
+ }
88
+ }
89
+ const percentage = aggTotal > 0 ? Math.round(aggCompleted / aggTotal * 100) : 0;
90
+ return { perLoop, completed: aggCompleted, total: aggTotal, percentage };
91
+ }
92
+
93
+ export function formatModelName(model) {
94
+ if (!model) return null;
95
+ return model.replace(/^claude-/, '');
96
+ }
97
+
98
+ export function getLoopStatusClass(loop) {
99
+ if (!loop.status) return 'pending';
100
+ const st = loop.status;
101
+ if (st.total > 0 && st.completed === st.total) return 'complete';
102
+ if (st.agents && st.agents.length > 0) return 'running';
103
+ if (st.total > 0 && st.completed > 0 && st.completed < st.total) return 'running';
104
+ if (st.stage && st.stage !== '—' && st.stage !== 'idle') return 'running';
105
+ return 'pending';
106
+ }
107
+
108
+ export function extractNotifMessage(payload) {
109
+ if (!payload) return 'Attention needed';
110
+ if (typeof payload === 'string') return payload;
111
+ if (payload.message) return payload.message;
112
+ if (payload.type) return payload.type;
113
+ if (payload.event) return payload.event;
114
+ return 'Attention needed';
115
+ }
@@ -134,6 +134,28 @@ If Stories Queue in tracker is empty: read `stories.md`, scan `## STORY-{N}:` he
134
134
 
135
135
  ---
136
136
 
137
+ ## Decision Reporting Protocol
138
+
139
+ When you make a substantive decision a human reviewer would want to know about, report it to the dashboard:
140
+
141
+ **When to report:**
142
+ - Scope boundary decisions (included/excluded functionality from a story)
143
+ - Approach choices (why you decomposed tasks one way vs. another)
144
+ - Trade-off resolutions (prioritizing one concern over another)
145
+ - Interpretation of ambiguous requirements (how you resolved unclear user intent)
146
+ - Self-answered clarification questions (questions you could have asked but resolved yourself)
147
+
148
+ **How to report:**
149
+ ```bash
150
+ curl -s --connect-timeout 2 --max-time 5 -X POST "http://127.0.0.1:4242/api/decision?app=$RALPHFLOW_APP&loop=$RALPHFLOW_LOOP" -H 'Content-Type: application/json' -d '{"item":"STORY-{N}","agent":"story-loop","decision":"{one-line summary}","reasoning":"{why this choice}"}'
151
+ ```
152
+
153
+ **Do NOT report** routine operations: picking the next story, updating tracker, stage transitions, heartbeat updates. Only report substantive choices that affect the work product.
154
+
155
+ **Best-effort only:** If the dashboard is unreachable (curl fails), continue working normally. Decision reporting must never block or delay your work.
156
+
157
+ ---
158
+
137
159
  ## Rules
138
160
 
139
161
  - One story at a time. All 3 stages run in one iteration, one `kill` at the end.
@@ -149,6 +149,29 @@ After completing ANY stage, exit: `kill -INT $PPID`
149
149
 
150
150
  If Tasks Queue in tracker is empty: read `tasks.md`, scan `## TASK-{N}:` headers, populate queue with `{agent: -, status: pending|blocked}` metadata (compute from Dependencies), then start.
151
151
 
152
+ ## Decision Reporting Protocol
153
+
154
+ When you make a substantive decision a human reviewer would want to know about, report it to the dashboard:
155
+
156
+ **When to report:**
157
+ - Scope boundary decisions (what's included/excluded from the task)
158
+ - Approach choices (implementation strategy, library selection, architecture decisions)
159
+ - Trade-off resolutions (performance vs. readability, scope vs. complexity)
160
+ - Interpretation of ambiguous requirements (how you resolved unclear task intent)
161
+ - Self-answered clarification questions (questions you could have asked but resolved yourself)
162
+ - File overlap or conflict decisions (how you handled shared files with other agents)
163
+
164
+ **How to report:**
165
+ ```bash
166
+ curl -s --connect-timeout 2 --max-time 5 -X POST "http://127.0.0.1:4242/api/decision?app=$RALPHFLOW_APP&loop=$RALPHFLOW_LOOP" -H 'Content-Type: application/json' -d '{"item":"TASK-{N}","agent":"{{AGENT_NAME}}","decision":"{one-line summary}","reasoning":"{why this choice}"}'
167
+ ```
168
+
169
+ **Do NOT report** routine operations: claiming a task, updating heartbeat, stage transitions, waiting for blocked tasks. Only report substantive choices that affect the implementation.
170
+
171
+ **Best-effort only:** If the dashboard is unreachable (curl fails), continue working normally. Decision reporting must never block or delay your work.
172
+
173
+ ---
174
+
152
175
  ## Rules
153
176
 
154
177
  - One task at a time per agent. One stage per iteration.
@@ -92,6 +92,27 @@ After resolving all feedback:
92
92
 
93
93
  ---
94
94
 
95
+ ## Decision Reporting Protocol
96
+
97
+ When you make a substantive decision a human reviewer would want to know about, report it to the dashboard:
98
+
99
+ **When to report:**
100
+ - Feedback categorization decisions (classifying feedback as BUG vs. CHANGE)
101
+ - Scope decisions during bug fixes (what to fix now vs. defer to a new story)
102
+ - Presentation choices (how you framed or organized the walkthrough)
103
+ - Trade-off resolutions when multiple feedback items conflict
104
+
105
+ **How to report:**
106
+ ```bash
107
+ curl -s --connect-timeout 2 --max-time 5 -X POST "http://127.0.0.1:4242/api/decision?app=$RALPHFLOW_APP&loop=$RALPHFLOW_LOOP" -H 'Content-Type: application/json' -d '{"item":"STORY-{N}","agent":"delivery-loop","decision":"{one-line summary}","reasoning":"{why this choice}"}'
108
+ ```
109
+
110
+ **Do NOT report** routine operations: picking the next story, updating tracker, phase transitions. Only report substantive choices that affect the delivery outcome.
111
+
112
+ **Best-effort only:** If the dashboard is unreachable (curl fails), continue working normally. Decision reporting must never block or delay your work.
113
+
114
+ ---
115
+
95
116
  ## Rules
96
117
 
97
118
  - One STORY at a time. All 3 phases run in one iteration, one `kill` at the end.
@@ -107,6 +107,28 @@ If all topics have been discovered and queue is empty: `<promise>ALL TOPICS DISC
107
107
 
108
108
  ---
109
109
 
110
+ ## Decision Reporting Protocol
111
+
112
+ When you make a substantive decision a human reviewer would want to know about, report it to the dashboard:
113
+
114
+ **When to report:**
115
+ - Scope boundary decisions (what's in/out of the research scope)
116
+ - Topic decomposition choices (why topics were split a certain way)
117
+ - Priority assignments (why a topic is high vs. medium vs. low priority)
118
+ - Depth decisions (surface vs. deep investigation for specific areas)
119
+ - Dependency structure choices (why certain topics must precede others)
120
+
121
+ **How to report:**
122
+ ```bash
123
+ curl -s --connect-timeout 2 --max-time 5 -X POST "http://127.0.0.1:4242/api/decision?app=$RALPHFLOW_APP&loop=$RALPHFLOW_LOOP" -H 'Content-Type: application/json' -d '{"item":"TOPIC-{N}","agent":"discovery-loop","decision":"{one-line summary}","reasoning":"{why this choice}"}'
124
+ ```
125
+
126
+ **Do NOT report** routine operations: updating tracker, stage transitions. Only report substantive choices that affect the research direction.
127
+
128
+ **Best-effort only:** If the dashboard is unreachable (curl fails), continue working normally. Decision reporting must never block or delay your work.
129
+
130
+ ---
131
+
110
132
  ## Rules
111
133
 
112
134
  - One research brief at a time. All 3 stages run in one iteration, one `kill` at the end.
@@ -170,6 +170,28 @@ After completing ANY stage, exit: `kill -INT $PPID`
170
170
 
171
171
  If Topics Queue in tracker is empty: read `topics.md`, scan `## TOPIC-{N}:` headers + `**Depends on:**` tags, populate queue with `{agent: -, status: pending|blocked}` metadata, then start.
172
172
 
173
+ ## Decision Reporting Protocol
174
+
175
+ When you make a substantive decision a human reviewer would want to know about, report it to the dashboard:
176
+
177
+ **When to report:**
178
+ - Research direction choices (which angles to pursue vs. skip)
179
+ - Source credibility judgments (why you trusted or dismissed a source)
180
+ - Scope boundary decisions (what's in/out for this topic's investigation)
181
+ - Conflicting evidence resolution (how you weighed contradictory findings)
182
+ - Gap identification decisions (what couldn't be found and whether to flag it)
183
+
184
+ **How to report:**
185
+ ```bash
186
+ curl -s --connect-timeout 2 --max-time 5 -X POST "http://127.0.0.1:4242/api/decision?app=$RALPHFLOW_APP&loop=$RALPHFLOW_LOOP" -H 'Content-Type: application/json' -d '{"item":"TOPIC-{N}","agent":"{{AGENT_NAME}}","decision":"{one-line summary}","reasoning":"{why this choice}"}'
187
+ ```
188
+
189
+ **Do NOT report** routine operations: claiming a topic, updating heartbeat, stage transitions, waiting for blocked topics. Only report substantive choices that affect the research findings.
190
+
191
+ **Best-effort only:** If the dashboard is unreachable (curl fails), continue working normally. Decision reporting must never block or delay your work.
192
+
193
+ ---
194
+
173
195
  ## Rules
174
196
 
175
197
  - One topic at a time per agent. One stage per iteration.
@@ -96,6 +96,28 @@ If all stories written: `<promise>ALL STORIES WRITTEN</promise>`
96
96
 
97
97
  ---
98
98
 
99
+ ## Decision Reporting Protocol
100
+
101
+ When you make a substantive decision a human reviewer would want to know about, report it to the dashboard:
102
+
103
+ **When to report:**
104
+ - Theme grouping decisions (why findings were clustered into specific stories)
105
+ - Narrative framing choices (how you chose to frame the story's angle)
106
+ - Evidence weighting (which data points to emphasize vs. downplay)
107
+ - Audience adaptation decisions (how you adjusted tone or depth for the target audience)
108
+ - Scope decisions (what to include/exclude from a story's narrative)
109
+
110
+ **How to report:**
111
+ ```bash
112
+ curl -s --connect-timeout 2 --max-time 5 -X POST "http://127.0.0.1:4242/api/decision?app=$RALPHFLOW_APP&loop=$RALPHFLOW_LOOP" -H 'Content-Type: application/json' -d '{"item":"STORY-{N}","agent":"story-loop","decision":"{one-line summary}","reasoning":"{why this choice}"}'
113
+ ```
114
+
115
+ **Do NOT report** routine operations: picking the next story, updating tracker, stage transitions. Only report substantive choices that affect the story content.
116
+
117
+ **Best-effort only:** If the dashboard is unreachable (curl fails), continue working normally. Decision reporting must never block or delay your work.
118
+
119
+ ---
120
+
99
121
  ## Rules
100
122
 
101
123
  - One story at a time. Both stages run in one iteration, one `kill` at the end.
@@ -109,6 +109,28 @@ Read `.ralph-flow/{{APP_NAME}}/03-document-loop/tracker.md` FIRST to determine w
109
109
 
110
110
  ---
111
111
 
112
+ ## Decision Reporting Protocol
113
+
114
+ When you make a substantive decision a human reviewer would want to know about, report it to the dashboard:
115
+
116
+ **When to report:**
117
+ - Document structure decisions (how you organized the overall narrative)
118
+ - Story ordering choices (why stories were arranged in a particular sequence)
119
+ - Format decisions (how you adapted content for the chosen output format)
120
+ - Editorial choices (what to include in the executive summary, what to put in appendices)
121
+ - Audience adaptation decisions (how you adjusted tone or depth)
122
+
123
+ **How to report:**
124
+ ```bash
125
+ curl -s --connect-timeout 2 --max-time 5 -X POST "http://127.0.0.1:4242/api/decision?app=$RALPHFLOW_APP&loop=$RALPHFLOW_LOOP" -H 'Content-Type: application/json' -d '{"item":"DOCUMENT","agent":"document-loop","decision":"{one-line summary}","reasoning":"{why this choice}"}'
126
+ ```
127
+
128
+ **Do NOT report** routine operations: reading files, updating tracker. Only report substantive choices that affect the final document.
129
+
130
+ **Best-effort only:** If the dashboard is unreachable (curl fails), continue working normally. Decision reporting must never block or delay your work.
131
+
132
+ ---
133
+
112
134
  ## Rules
113
135
 
114
136
  - This runs ONCE, on-demand. It is not a recurring loop.