flight-rules 0.15.2 → 0.15.3
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/commands/ralph.js +54 -21
- package/package.json +1 -1
- package/payload/AGENTS.md +1 -1
- package/payload/prompts/ralph-discovery.md +25 -9
package/dist/commands/ralph.js
CHANGED
|
@@ -123,28 +123,29 @@ async function runClaudeWithPrompt(promptContent, verbose) {
|
|
|
123
123
|
], {
|
|
124
124
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
125
125
|
});
|
|
126
|
-
let
|
|
126
|
+
let reassembledText = ''; // Plain text reassembled from stream-json fragments
|
|
127
|
+
let resultText = ''; // Full text from the final result event (fallback)
|
|
127
128
|
let errorOutput = '';
|
|
128
129
|
let lineBuffer = ''; // Buffer for incomplete JSON lines
|
|
129
130
|
let needsTimestamp = true; // Track whether next text output needs a timestamp
|
|
130
131
|
claude.stdout?.on('data', (data) => {
|
|
131
132
|
const text = data.toString();
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (
|
|
133
|
+
// Parse stream-json lines to reassemble plain text output
|
|
134
|
+
const fullText = lineBuffer + text;
|
|
135
|
+
const lines = fullText.split('\n');
|
|
136
|
+
// Last element might be incomplete - save it for next chunk
|
|
137
|
+
lineBuffer = lines.pop() || '';
|
|
138
|
+
for (const line of lines) {
|
|
139
|
+
if (!line.trim())
|
|
140
|
+
continue;
|
|
141
|
+
try {
|
|
142
|
+
const parsed = JSON.parse(line);
|
|
143
|
+
// Handle different message types in stream-json format
|
|
144
|
+
if (parsed.type === 'assistant' && parsed.message?.content) {
|
|
145
|
+
for (const block of parsed.message.content) {
|
|
146
|
+
if (block.type === 'text' && block.text) {
|
|
147
|
+
reassembledText += block.text;
|
|
148
|
+
if (verbose) {
|
|
148
149
|
if (needsTimestamp) {
|
|
149
150
|
process.stdout.write(`${formatTimestamp()} `);
|
|
150
151
|
needsTimestamp = false;
|
|
@@ -153,23 +154,31 @@ async function runClaudeWithPrompt(promptContent, verbose) {
|
|
|
153
154
|
}
|
|
154
155
|
}
|
|
155
156
|
}
|
|
156
|
-
|
|
157
|
+
}
|
|
158
|
+
else if (parsed.type === 'content_block_delta' && parsed.delta?.text) {
|
|
159
|
+
reassembledText += parsed.delta.text;
|
|
160
|
+
if (verbose) {
|
|
157
161
|
if (needsTimestamp) {
|
|
158
162
|
process.stdout.write(`${formatTimestamp()} `);
|
|
159
163
|
needsTimestamp = false;
|
|
160
164
|
}
|
|
161
165
|
process.stdout.write(parsed.delta.text);
|
|
162
166
|
}
|
|
163
|
-
|
|
167
|
+
}
|
|
168
|
+
else if (parsed.type === 'content_block_stop') {
|
|
169
|
+
if (verbose) {
|
|
164
170
|
// Add newline + blank line after each content block ends
|
|
165
171
|
process.stdout.write('\n\n');
|
|
166
172
|
needsTimestamp = true;
|
|
167
173
|
}
|
|
168
174
|
}
|
|
169
|
-
|
|
170
|
-
|
|
175
|
+
else if (parsed.type === 'result' && typeof parsed.result === 'string') {
|
|
176
|
+
resultText = parsed.result;
|
|
171
177
|
}
|
|
172
178
|
}
|
|
179
|
+
catch {
|
|
180
|
+
// Not valid JSON, skip
|
|
181
|
+
}
|
|
173
182
|
}
|
|
174
183
|
});
|
|
175
184
|
claude.stderr?.on('data', (data) => {
|
|
@@ -180,6 +189,30 @@ async function runClaudeWithPrompt(promptContent, verbose) {
|
|
|
180
189
|
}
|
|
181
190
|
});
|
|
182
191
|
claude.on('close', (code) => {
|
|
192
|
+
// Flush any remaining data in lineBuffer
|
|
193
|
+
if (lineBuffer.trim()) {
|
|
194
|
+
try {
|
|
195
|
+
const parsed = JSON.parse(lineBuffer);
|
|
196
|
+
if (parsed.type === 'assistant' && parsed.message?.content) {
|
|
197
|
+
for (const block of parsed.message.content) {
|
|
198
|
+
if (block.type === 'text' && block.text) {
|
|
199
|
+
reassembledText += block.text;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else if (parsed.type === 'content_block_delta' && parsed.delta?.text) {
|
|
204
|
+
reassembledText += parsed.delta.text;
|
|
205
|
+
}
|
|
206
|
+
else if (parsed.type === 'result' && typeof parsed.result === 'string') {
|
|
207
|
+
resultText = parsed.result;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Not valid JSON, skip
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Prefer reassembled streaming text; fall back to result event text
|
|
215
|
+
const output = reassembledText || resultText;
|
|
183
216
|
resolve({ output, exitCode: code ?? 0 });
|
|
184
217
|
});
|
|
185
218
|
claude.on('error', (err) => {
|
package/package.json
CHANGED
package/payload/AGENTS.md
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
# Flight Rules Discovery Agent
|
|
2
2
|
|
|
3
|
-
You are a discovery agent for Flight Rules. Your ONLY job is to scan implementation docs and report which task groups have incomplete tasks. Do NOT implement anything.
|
|
3
|
+
You are a discovery agent for Flight Rules. Your ONLY job is to scan implementation docs and report which task groups have **incomplete** (not-yet-done) tasks. Do NOT implement anything.
|
|
4
4
|
|
|
5
5
|
## Instructions
|
|
6
6
|
|
|
7
7
|
1. Read `docs/implementation/overview.md` to understand the area/task-group structure
|
|
8
8
|
2. Scan each Area directory in `docs/implementation/`
|
|
9
|
-
3. For each Task Group file (.md), check every task's
|
|
10
|
-
4.
|
|
9
|
+
3. For each Task Group file (.md), check every task's `**Status**:` field
|
|
10
|
+
4. A task is **incomplete** if its status is 🔵 Planned, 🟡 In Progress, or ⏸️ Blocked
|
|
11
|
+
5. A task is **complete** only if its status is ✅ Complete
|
|
12
|
+
6. Report all task groups that contain any incomplete task
|
|
11
13
|
|
|
12
14
|
## Response Format
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
Output ONLY the `<ralph-discovery>` block below. No commentary, no summary, no interpretation before or after the tags. Your entire response must be the block and nothing else.
|
|
17
|
+
|
|
18
|
+
When incomplete tasks exist (the common case), use this format:
|
|
15
19
|
|
|
16
20
|
```
|
|
17
21
|
<ralph-discovery>
|
|
22
|
+
INCOMPLETE|{totalIncompleteTaskCount}
|
|
18
23
|
TASK_GROUP|{id}|{title}|{filePath}|{areaDir}
|
|
19
24
|
TASK|{taskId}|{taskTitle}|{status}
|
|
20
25
|
TASK|{taskId}|{taskTitle}|{status}
|
|
@@ -23,16 +28,17 @@ TASK|{taskId}|{taskTitle}|{status}
|
|
|
23
28
|
</ralph-discovery>
|
|
24
29
|
```
|
|
25
30
|
|
|
26
|
-
-
|
|
31
|
+
- First line is `INCOMPLETE|{N}` where N = total number of incomplete tasks across all task groups
|
|
32
|
+
- Each `TASK_GROUP` line is followed by its incomplete `TASK` lines
|
|
27
33
|
- `{id}` = task group ID as written in the file (e.g., "1.1", "2.3")
|
|
28
34
|
- `{title}` = task group title
|
|
29
35
|
- `{filePath}` = relative path from project root to the task group file
|
|
30
36
|
- `{areaDir}` = area directory name (e.g., "1-project-setup", "2-cli-core")
|
|
31
37
|
- `{taskId}` = individual task ID (e.g., "1.1.1", "2.3.2")
|
|
32
38
|
- `{taskTitle}` = individual task title
|
|
33
|
-
- `{status}` = one of: planned
|
|
39
|
+
- `{status}` = one of: `planned`, `in_progress`, `blocked` — all three mean the task is NOT done
|
|
34
40
|
|
|
35
|
-
|
|
41
|
+
Only if every single task in every single task group has ✅ Complete status (this is rare during active development), respond with:
|
|
36
42
|
|
|
37
43
|
```
|
|
38
44
|
<ralph-discovery>
|
|
@@ -40,11 +46,21 @@ ALL_COMPLETE
|
|
|
40
46
|
</ralph-discovery>
|
|
41
47
|
```
|
|
42
48
|
|
|
49
|
+
## Field Reference
|
|
50
|
+
|
|
51
|
+
| Status in doc | Meaning | Output value |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| 🔵 Planned | Not started, work remains | `planned` |
|
|
54
|
+
| 🟡 In Progress | Started but not finished | `in_progress` |
|
|
55
|
+
| ⏸️ Blocked | Cannot proceed, work remains | `blocked` |
|
|
56
|
+
| ✅ Complete | Done, do NOT include in output | (omit) |
|
|
57
|
+
|
|
43
58
|
## Rules
|
|
44
59
|
|
|
45
60
|
- Do NOT implement or modify any code
|
|
46
61
|
- Do NOT create or modify any files
|
|
47
62
|
- Do NOT run any scripts or quality checks
|
|
48
63
|
- ONLY read implementation files and report status
|
|
49
|
-
-
|
|
50
|
-
- List task groups in
|
|
64
|
+
- Your response must contain ONLY the `<ralph-discovery>` block — no other text
|
|
65
|
+
- List task groups in order by area number, then task group number
|
|
66
|
+
- Never output `ALL_COMPLETE` if any task has a status of planned, in_progress, or blocked
|