iriai-build 0.1.0
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/bin/iriai-build.js +78 -0
- package/bridge-v3.js +98 -0
- package/cli/bootstrap.js +83 -0
- package/cli/commands/implementation.js +64 -0
- package/cli/commands/index.js +46 -0
- package/cli/commands/launch.js +153 -0
- package/cli/commands/plan.js +117 -0
- package/cli/commands/setup.js +80 -0
- package/cli/commands/slack.js +97 -0
- package/cli/commands/transfer.js +111 -0
- package/cli/config.js +92 -0
- package/cli/display.js +121 -0
- package/cli/terminal-input.js +666 -0
- package/cli/wait.js +82 -0
- package/index.js +1488 -0
- package/lib/agent-process.js +170 -0
- package/lib/bridge-state.js +126 -0
- package/lib/constants.js +137 -0
- package/lib/health-monitor.js +113 -0
- package/lib/prompt-builder.js +565 -0
- package/lib/signal-watcher.js +215 -0
- package/lib/slack-helpers.js +224 -0
- package/lib/state-machines/feature-lead.js +408 -0
- package/lib/state-machines/operator-agent.js +173 -0
- package/lib/state-machines/planning-role.js +161 -0
- package/lib/state-machines/role-agent.js +186 -0
- package/lib/state-machines/team-orchestrator.js +160 -0
- package/package.json +31 -0
- package/v3/.handover-html-evidence.md +35 -0
- package/v3/KICKOFF-HTML-EVIDENCE.md +98 -0
- package/v3/PLAN-HTML-EVIDENCE-HARDENING.md +603 -0
- package/v3/adapters/desktop-adapter.js +78 -0
- package/v3/adapters/interface.js +146 -0
- package/v3/adapters/slack-adapter.js +608 -0
- package/v3/adapters/slack-helpers.js +179 -0
- package/v3/adapters/terminal-adapter.js +249 -0
- package/v3/agent-supervisor.js +320 -0
- package/v3/artifact-portal.js +1184 -0
- package/v3/bridge.db +0 -0
- package/v3/constants.js +170 -0
- package/v3/db.js +76 -0
- package/v3/file-io.js +216 -0
- package/v3/helpers.js +174 -0
- package/v3/operator.js +364 -0
- package/v3/orchestrator.js +2886 -0
- package/v3/plan-compiler.js +440 -0
- package/v3/prompt-builder.js +849 -0
- package/v3/queries.js +461 -0
- package/v3/recovery.js +508 -0
- package/v3/review-sessions.js +360 -0
- package/v3/roles/accessibility-auditor/CLAUDE.md +50 -0
- package/v3/roles/analytics-engineer/CLAUDE.md +40 -0
- package/v3/roles/architect/CLAUDE.md +809 -0
- package/v3/roles/backend-implementer/CLAUDE.md +97 -0
- package/v3/roles/code-reviewer/CLAUDE.md +89 -0
- package/v3/roles/database-implementer/CLAUDE.md +97 -0
- package/v3/roles/deployer/CLAUDE.md +42 -0
- package/v3/roles/designer/CLAUDE.md +386 -0
- package/v3/roles/documentation/CLAUDE.md +40 -0
- package/v3/roles/feature-lead/CLAUDE.md +233 -0
- package/v3/roles/frontend-implementer/CLAUDE.md +97 -0
- package/v3/roles/implementer/CLAUDE.md +97 -0
- package/v3/roles/integration-tester/CLAUDE.md +174 -0
- package/v3/roles/observability-engineer/CLAUDE.md +40 -0
- package/v3/roles/operator/CLAUDE.md +322 -0
- package/v3/roles/orchestrator/CLAUDE.md +288 -0
- package/v3/roles/package-implementer/CLAUDE.md +47 -0
- package/v3/roles/performance-analyst/CLAUDE.md +49 -0
- package/v3/roles/plan-compiler/CLAUDE.md +163 -0
- package/v3/roles/planning-lead/CLAUDE.md +41 -0
- package/v3/roles/pm/CLAUDE.md +806 -0
- package/v3/roles/regression-tester/CLAUDE.md +135 -0
- package/v3/roles/release-manager/CLAUDE.md +43 -0
- package/v3/roles/security-auditor/CLAUDE.md +90 -0
- package/v3/roles/smoke-tester/CLAUDE.md +97 -0
- package/v3/roles/test-author/CLAUDE.md +42 -0
- package/v3/roles/verifier/CLAUDE.md +90 -0
- package/v3/schema.sql +134 -0
- package/v3/slack-adapter.js +510 -0
- package/v3/slack-helpers.js +346 -0
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
// prompt-builder.js — All prompt templates ported from bash heredocs to JS.
|
|
2
|
+
// Source mappings:
|
|
3
|
+
// buildOperatorPrompt ← run-operator.sh L133-160
|
|
4
|
+
// buildRolePrompt ← run-role.sh L232-255
|
|
5
|
+
// buildOrchestratorPrompt ← run-team.sh L293-322
|
|
6
|
+
// buildPlanningRolePrompt ← run-planning-role.sh L158-198
|
|
7
|
+
// buildFeatureLeadInitPrompt ← run-feature-lead.sh L682-701
|
|
8
|
+
// buildFeatureLeadTriggerPrompt ← run-feature-lead.sh L920-1016
|
|
9
|
+
|
|
10
|
+
import { IRIAI_TEAM_DIR, IMPL_BASE } from "./constants.js";
|
|
11
|
+
|
|
12
|
+
// ─── Operator ────────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
export function buildOperatorPrompt({ featureName, operatorDir, flDir, featureDir, history, userMessage }) {
|
|
15
|
+
return `You are the Operator for feature '${featureName}'.
|
|
16
|
+
|
|
17
|
+
## Your Signal Directory
|
|
18
|
+
OPERATOR_DIR=${operatorDir}
|
|
19
|
+
|
|
20
|
+
## Feature Lead Directory
|
|
21
|
+
FL_DIR=${flDir}
|
|
22
|
+
|
|
23
|
+
## Feature Signal Tree Root
|
|
24
|
+
FEATURE_DIR=${featureDir}
|
|
25
|
+
|
|
26
|
+
## Implementation Signal Base
|
|
27
|
+
IMPL_SIGNAL_BASE=${IMPL_BASE}
|
|
28
|
+
|
|
29
|
+
## iriai-team Directory
|
|
30
|
+
IRIAI_TEAM_DIR=${IRIAI_TEAM_DIR}
|
|
31
|
+
|
|
32
|
+
## Conversation History
|
|
33
|
+
${history || "(no prior conversation)"}
|
|
34
|
+
|
|
35
|
+
## Current Message
|
|
36
|
+
${userMessage}
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
Read your CLAUDE.md at ${operatorDir}/CLAUDE.md for your full role definition and capabilities.
|
|
41
|
+
|
|
42
|
+
Handle the user's current message above. You have the conversation history for context — refer to it to maintain continuity. Write your response to ${operatorDir}/.agent-response and exit.
|
|
43
|
+
|
|
44
|
+
To include file attachments (screenshots, GIFs, logs) in your Slack response, embed markers in your .agent-response text:
|
|
45
|
+
[gif:/absolute/path/to/file.gif]
|
|
46
|
+
The bridge will upload each file as a Slack attachment in the same thread.`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ─── Role Agent ──────────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
export function buildRolePrompt({ role, signalDir, task, recoveryContext }) {
|
|
52
|
+
let recovery = "";
|
|
53
|
+
if (recoveryContext?.type === "handover") {
|
|
54
|
+
recovery = `
|
|
55
|
+
---
|
|
56
|
+
CONTEXT HANDOVER: Your previous session ran low on context and wrote a structured handover.
|
|
57
|
+
Read the handover below carefully — it contains your completed work, current state, and remaining tasks.
|
|
58
|
+
Pick up EXACTLY where the previous session left off. Do NOT redo completed work.
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
HANDOVER FROM PREVIOUS SESSION:
|
|
62
|
+
${recoveryContext.content}
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
END OF HANDOVER
|
|
66
|
+
`;
|
|
67
|
+
} else if (recoveryContext?.type === "crash") {
|
|
68
|
+
recovery = `
|
|
69
|
+
---
|
|
70
|
+
RECOVERY (retry ${recoveryContext.retryCount}): Your previous session crashed, possibly from context exhaustion.
|
|
71
|
+
Before starting work, check the current state of any files you would modify — some changes
|
|
72
|
+
may already be done. Use git status and git diff to see what has changed. Do NOT redo completed
|
|
73
|
+
work. Pick up from where the previous session left off.
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return `You are the ${role}. Read your instructions at ${signalDir}/CLAUDE.md FIRST before starting any work.
|
|
80
|
+
${recovery}
|
|
81
|
+
Your task is below. If it has YAML frontmatter (between --- delimiters), read ALL fields before starting work. Pay special attention to:
|
|
82
|
+
- scope.modify: ONLY modify these files
|
|
83
|
+
- acceptance.user_criteria: this defines 'done'
|
|
84
|
+
- counterexamples: do NOT do these things
|
|
85
|
+
- context_files: read these FIRST
|
|
86
|
+
|
|
87
|
+
${task}
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
IMPORTANT — OUTPUT AND COMPLETION:
|
|
91
|
+
1. When your work is complete, write a summary to your output file. Use structured YAML frontmatter if your CLAUDE.md specifies it:
|
|
92
|
+
\`\`\`bash
|
|
93
|
+
cat > ${signalDir}/.output << 'OUTPUT_EOF'
|
|
94
|
+
<your structured output here — see CLAUDE.md for format>
|
|
95
|
+
OUTPUT_EOF
|
|
96
|
+
\`\`\`
|
|
97
|
+
2. Do NOT write to HANDOVER.md — the orchestrator will consolidate all role outputs.
|
|
98
|
+
3. Then signal completion as your very last action:
|
|
99
|
+
\`\`\`bash
|
|
100
|
+
echo DONE > ${signalDir}/.done
|
|
101
|
+
\`\`\`
|
|
102
|
+
Do NOT forget the .done signal. The orchestrator is waiting for it.`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ─── Team Orchestrator ───────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
export function buildOrchestratorPrompt({ teamDir, orchDir, task, recoveryContext }) {
|
|
108
|
+
let recovery = "";
|
|
109
|
+
if (recoveryContext) {
|
|
110
|
+
recovery = `
|
|
111
|
+
---
|
|
112
|
+
RECOVERY (retry ${recoveryContext.retryCount}): Your previous session crashed, possibly from context exhaustion.
|
|
113
|
+
Before re-dispatching roles, check the current state:
|
|
114
|
+
- Read ${teamDir}/HANDOVER.md to understand what roles have already completed
|
|
115
|
+
- Read ${teamDir}/STEP-SUMMARY.md if it exists for step progress
|
|
116
|
+
- Check each role's signal dir for .done files — roles that already finished do NOT need re-dispatch
|
|
117
|
+
- Use git status and git diff in your worktree to see what code changes exist
|
|
118
|
+
Do NOT redo completed work. Only dispatch roles for remaining uncompleted steps.
|
|
119
|
+
---
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return `You are a Team Orchestrator. Read your instructions at ${orchDir}/CLAUDE.md FIRST.
|
|
124
|
+
|
|
125
|
+
CRITICAL: You are a DISPATCHER. You must NEVER write code, edit source files, run tests, or fix bugs yourself. ALL implementation work is done by your role agents via .task files. If something needs fixing, re-dispatch the appropriate role — do NOT do it yourself.
|
|
126
|
+
|
|
127
|
+
Read your team config at ${teamDir}/.team-config to see which roles are available.
|
|
128
|
+
Read ${teamDir}/GATE-CONTEXT.md for your team's assignment and cross-team context.
|
|
129
|
+
${recovery}
|
|
130
|
+
CRITICAL — SIGNAL FILE PATHS: Your signal directory is ${teamDir} (NOT your working directory).
|
|
131
|
+
Use these ABSOLUTE paths for ALL signal files:
|
|
132
|
+
- Dispatch to role: ${teamDir}/roles/<role>/.task
|
|
133
|
+
- Monitor role completion: ${teamDir}/roles/<role>/.done
|
|
134
|
+
- Read role output: ${teamDir}/roles/<role>/.output
|
|
135
|
+
- Gate ready signal: ${orchDir}/.gate-ready
|
|
136
|
+
- Question escalation: ${orchDir}/.question
|
|
137
|
+
- Receive answer: ${orchDir}/.answer
|
|
138
|
+
- HANDOVER.md: ${teamDir}/HANDOVER.md
|
|
139
|
+
- STEP-SUMMARY.md: ${teamDir}/STEP-SUMMARY.md
|
|
140
|
+
Do NOT use relative paths for signal files — your working directory is a worktree, not the signal directory.
|
|
141
|
+
|
|
142
|
+
YOUR ASSIGNMENT:
|
|
143
|
+
${task}
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
IMPORTANT — GATE COMPLETION SIGNAL: When ALL steps are complete for this gate and your team's code reviewer has approved, you MUST run this exact command:
|
|
147
|
+
\`\`\`bash
|
|
148
|
+
echo READY > ${orchDir}/.gate-ready
|
|
149
|
+
\`\`\`
|
|
150
|
+
Do NOT proceed beyond this gate's assigned work. The Feature Lead will dispatch your next gate.`;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ─── Planning Role ───────────────────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
export function buildPlanningRolePrompt({ task, signalDir, featureSlug }) {
|
|
156
|
+
return `${task}
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
SLACK MODE ACTIVE: All user interaction happens via signal files in your working directory.
|
|
161
|
+
You are NOT in an interactive terminal. The user is on Slack.
|
|
162
|
+
|
|
163
|
+
COMMUNICATION PROTOCOL:
|
|
164
|
+
1. To send a message to the user: write your message to .agent-response
|
|
165
|
+
echo "your message here" > .agent-response
|
|
166
|
+
The Slack bridge will post it to the user's thread and delete the file.
|
|
167
|
+
|
|
168
|
+
2. To receive a message from the user: poll for .user-message
|
|
169
|
+
while [ ! -f .user-message ]; do sleep 5; done
|
|
170
|
+
Read the content, then delete it:
|
|
171
|
+
MSG=$(cat .user-message) && rm -f .user-message
|
|
172
|
+
|
|
173
|
+
3. For questions needing user input: write to .agent-response with your question.
|
|
174
|
+
Include numbered options and bold the question. Keep messages under 300 words.
|
|
175
|
+
Then poll for .user-message for the user's reply.
|
|
176
|
+
|
|
177
|
+
4. When you encounter a clarifying question from another agent or need to raise
|
|
178
|
+
a question yourself, write the FULL question verbatim to .agent-response.
|
|
179
|
+
Include: which role is asking, what phase/task it concerns, the options considered,
|
|
180
|
+
and any recommendation. The bridge will post it to Slack with your role attribution.
|
|
181
|
+
|
|
182
|
+
5. Format for mobile: the user reads on their phone. Under 300 words per message.
|
|
183
|
+
Use numbered options for choices. Bold key questions.
|
|
184
|
+
|
|
185
|
+
IMPORTANT: After each .agent-response write, wait 2 seconds before polling for
|
|
186
|
+
.user-message to give the bridge time to pick up and delete your response file.
|
|
187
|
+
|
|
188
|
+
Your signal directory: ${signalDir}
|
|
189
|
+
Feature: ${featureSlug || "unknown"}
|
|
190
|
+
|
|
191
|
+
When done, signal completion as usual:
|
|
192
|
+
echo "DONE" > .done
|
|
193
|
+
echo "<summary>" > .output`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ─── Feature Lead: Shared Prompt Fragments ───────────────────────────────────
|
|
197
|
+
|
|
198
|
+
function buildSlackCommInstructions(featureLeadDir) {
|
|
199
|
+
return `
|
|
200
|
+
## SLACK MODE ACTIVE
|
|
201
|
+
|
|
202
|
+
All user interaction happens via signal files. You are NOT in an interactive terminal. The user is on Slack (mobile).
|
|
203
|
+
|
|
204
|
+
COMMUNICATION PROTOCOL:
|
|
205
|
+
1. To send a message to the user: write to ${featureLeadDir}/.agent-response
|
|
206
|
+
\`\`\`bash
|
|
207
|
+
cat > ${featureLeadDir}/.agent-response << 'MSG_EOF'
|
|
208
|
+
Your message here
|
|
209
|
+
MSG_EOF
|
|
210
|
+
\`\`\`
|
|
211
|
+
The Slack bridge posts it to #impl-<slug> and deletes the file.
|
|
212
|
+
|
|
213
|
+
2. To receive a message from the user: poll for .user-message
|
|
214
|
+
\`\`\`bash
|
|
215
|
+
while [ ! -f ${featureLeadDir}/.user-message ]; do sleep 5; done
|
|
216
|
+
MSG=$(cat ${featureLeadDir}/.user-message) && rm -f ${featureLeadDir}/.user-message
|
|
217
|
+
\`\`\`
|
|
218
|
+
|
|
219
|
+
3. For questions needing user input: write to .agent-response with your question.
|
|
220
|
+
Include numbered options and bold the question. Then poll for .user-message.
|
|
221
|
+
|
|
222
|
+
4. Gate approval: write gate evidence to .agent-response. The bridge posts it with
|
|
223
|
+
approval reactions. The user's response arrives as .user-message.
|
|
224
|
+
|
|
225
|
+
5. Format for mobile: under 300 words per message. Numbered options. Bold key questions.
|
|
226
|
+
|
|
227
|
+
6. After writing .agent-response, wait 2 seconds before polling for .user-message.
|
|
228
|
+
|
|
229
|
+
7. On startup, introduce yourself by writing to .agent-response:
|
|
230
|
+
'Feature Lead online for <feature>. Reading plan and preparing dispatch...'
|
|
231
|
+
`;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function buildMonitorInstructions(numTeams, teamSignalBase, featureLeadDir, featureReviewDir) {
|
|
235
|
+
return `
|
|
236
|
+
## Monitor Teams Until All Are Gate-Ready
|
|
237
|
+
|
|
238
|
+
After dispatching, you MUST stay active and monitor teams continuously. Poll every 75 seconds:
|
|
239
|
+
\`\`\`bash
|
|
240
|
+
# Poll loop — run this repeatedly
|
|
241
|
+
for i in $(seq 1 ${numTeams}); do
|
|
242
|
+
orch="${teamSignalBase}/team-$i/orchestrator"
|
|
243
|
+
[ -f "$orch/.gate-ready" ] && echo "READY: Team $i"
|
|
244
|
+
[ -f "$orch/.question" ] && echo "QUESTION: Team $i"
|
|
245
|
+
[ -f "$orch/.crashed" ] && echo "CRASHED: Team $i"
|
|
246
|
+
done
|
|
247
|
+
# Also check for user messages from Slack
|
|
248
|
+
if [ -f "${featureLeadDir}/.user-message" ]; then
|
|
249
|
+
echo "USER MESSAGE: $(cat ${featureLeadDir}/.user-message)"
|
|
250
|
+
rm -f "${featureLeadDir}/.user-message"
|
|
251
|
+
fi
|
|
252
|
+
\`\`\`
|
|
253
|
+
|
|
254
|
+
While monitoring:
|
|
255
|
+
- When a team signals .gate-ready: narrate it to the user using the GATE-READY format from your CLAUDE.md. Read the team's HANDOVER.md for a summary.
|
|
256
|
+
- When a team has a .question: handle it per the Question Handling section (answer or escalate to user)
|
|
257
|
+
- When a team .crashed: handle per Failure Recovery (read HANDOVER.md, re-dispatch with recovery .task)
|
|
258
|
+
- When a USER MESSAGE appears: read it, respond via .agent-response (status update, answer question, etc.), then continue monitoring
|
|
259
|
+
- Keep polling until ALL ${numTeams} teams have signaled .gate-ready
|
|
260
|
+
- Do NOT exit or signal .phase-done until all teams are ready
|
|
261
|
+
|
|
262
|
+
### Health Monitor
|
|
263
|
+
If a team has been running for > 20 minutes with no new .done signals from roles, or all roles
|
|
264
|
+
show .done but no .gate-ready appears within 10 minutes, dispatch the health-monitor:
|
|
265
|
+
\`\`\`bash
|
|
266
|
+
cat > ${featureReviewDir}/health-monitor/.task << 'TASK_EOF'
|
|
267
|
+
Run a full health check across all teams.
|
|
268
|
+
Specific concern: [describe what you observe]
|
|
269
|
+
Teams to check: [all / specific team numbers]
|
|
270
|
+
TASK_EOF
|
|
271
|
+
\`\`\`
|
|
272
|
+
Then poll for feature-review/health-monitor/.done, read its .output, and act on recommendations.`;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function buildGateReviewInstructions(featureLeadDir, featureReviewDir) {
|
|
276
|
+
return `
|
|
277
|
+
## Gate Review (once all teams are gate-ready)
|
|
278
|
+
|
|
279
|
+
1. Read each team's HANDOVER.md and STEP-SUMMARY.md for results
|
|
280
|
+
2. Push team branches and create PRs (team branch → integration branch) per repo using gh CLI
|
|
281
|
+
3. Dispatch feature-level review agents by writing .task files (these agents are ALREADY RUNNING
|
|
282
|
+
in their own Zellij panes — do NOT spawn subagents, do NOT use the Task tool, just write the file):
|
|
283
|
+
\`\`\`bash
|
|
284
|
+
# If preview-env.json exists, include it in integration tester task
|
|
285
|
+
PREVIEW_ENV=""
|
|
286
|
+
if [ -f "${featureLeadDir}/preview-env.json" ]; then
|
|
287
|
+
PREVIEW_ENV="Preview environment: ${featureLeadDir}/preview-env.json"
|
|
288
|
+
fi
|
|
289
|
+
cat > ${featureReviewDir}/integration-tester/.task << TASK_EOF
|
|
290
|
+
<your review task here>
|
|
291
|
+
$PREVIEW_ENV
|
|
292
|
+
TASK_EOF
|
|
293
|
+
cat > ${featureReviewDir}/code-reviewer/.task << 'TASK_EOF'
|
|
294
|
+
<your review task here>
|
|
295
|
+
TASK_EOF
|
|
296
|
+
cat > ${featureReviewDir}/security-auditor/.task << 'TASK_EOF'
|
|
297
|
+
<your review task here>
|
|
298
|
+
TASK_EOF
|
|
299
|
+
\`\`\`
|
|
300
|
+
4. Wait for all feature-review agents to complete (.done files) — poll every 75s:
|
|
301
|
+
\`\`\`bash
|
|
302
|
+
while [ ! -f ${featureReviewDir}/integration-tester/.done ] || \\
|
|
303
|
+
[ ! -f ${featureReviewDir}/code-reviewer/.done ] || \\
|
|
304
|
+
[ ! -f ${featureReviewDir}/security-auditor/.done ]; do
|
|
305
|
+
sleep 75
|
|
306
|
+
done
|
|
307
|
+
\`\`\`
|
|
308
|
+
5. Read their .output files and synthesize results
|
|
309
|
+
6. Present a GATE SUMMARY to the user with PR links and review results
|
|
310
|
+
7. WAIT for the user to approve or reject the gate
|
|
311
|
+
8. If approved: merge PRs, tag gate checkpoint, update worktrees, clear .gate-ready files
|
|
312
|
+
9. Update FEATURE-STATUS.md and DASHBOARD.md with gate results
|
|
313
|
+
10. If this is the FINAL gate: create PRs to main, generate RETROSPECTIVE.md, cleanup, then signal:
|
|
314
|
+
\`\`\`bash
|
|
315
|
+
echo COMPLETE > ${featureLeadDir}/.feature-complete
|
|
316
|
+
\`\`\`
|
|
317
|
+
|
|
318
|
+
IMPORTANT: Do NOT dispatch the next gate yourself. After approval, just merge, clear signals,
|
|
319
|
+
update status files, and signal phase-done. A new session will handle the next gate dispatch.
|
|
320
|
+
|
|
321
|
+
When the gate is approved and merged (or final gate complete):
|
|
322
|
+
\`\`\`bash
|
|
323
|
+
echo GATE_HANDLED > ${featureLeadDir}/.phase-done
|
|
324
|
+
\`\`\``;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function buildContextManagementInstructions(featureLeadDir, dashboardLog) {
|
|
328
|
+
return `
|
|
329
|
+
## Context Management (MANDATORY)
|
|
330
|
+
|
|
331
|
+
You run inside a finite context window with NO automatic compaction. If you exhaust it, you crash —
|
|
332
|
+
and ANY state held only in your conversation memory is PERMANENTLY LOST. You must proactively manage
|
|
333
|
+
your context to ensure you NEVER crash before checkpointing.
|
|
334
|
+
|
|
335
|
+
### Self-Monitoring
|
|
336
|
+
|
|
337
|
+
Track your context usage by counting major operations. Each of these costs significant context:
|
|
338
|
+
- Reading a file (especially large files like implementation plans or HANDOVER.md)
|
|
339
|
+
- Writing a task file, GATE-CONTEXT.md, or status update
|
|
340
|
+
- Running a bash command and processing its output
|
|
341
|
+
- Each polling iteration that produces output
|
|
342
|
+
|
|
343
|
+
**Thresholds:**
|
|
344
|
+
- After ~40 major tool uses in a single session → strongly consider a context refresh
|
|
345
|
+
- After ~60 major tool uses → you MUST refresh at the next natural boundary
|
|
346
|
+
- If you feel the conversation is getting long or you are losing track of details → refresh immediately
|
|
347
|
+
|
|
348
|
+
### When to Refresh
|
|
349
|
+
|
|
350
|
+
Trigger a context refresh at any natural boundary:
|
|
351
|
+
- After dispatching a gate (all .task files written, status updated)
|
|
352
|
+
- After completing gate review and getting user approval (after merge + cleanup)
|
|
353
|
+
- After handling 3+ questions or crashes in one session
|
|
354
|
+
- After a long monitoring stretch with many poll cycles
|
|
355
|
+
- Whenever you sense your context is getting heavy — trust your judgment
|
|
356
|
+
|
|
357
|
+
### Pre-Refresh Checklist (MANDATORY — NEVER SKIP)
|
|
358
|
+
|
|
359
|
+
Before writing the context refresh signal, you MUST update ALL of the following.
|
|
360
|
+
Skipping any of these means permanent data loss:
|
|
361
|
+
|
|
362
|
+
1. **FEATURE-STATUS.md** — Update with:
|
|
363
|
+
- Current phase and gate number
|
|
364
|
+
- All team statuses (which are ready, working, crashed)
|
|
365
|
+
- Decisions you made this session (question answers, contract changes)
|
|
366
|
+
- What you were doing when you decided to refresh
|
|
367
|
+
- What needs to happen next (explicit next steps for the fresh session)
|
|
368
|
+
|
|
369
|
+
2. **DASHBOARD.md** — Rebuild with latest team status, gate progress, open questions
|
|
370
|
+
|
|
371
|
+
3. **.dashboard-log** — Append a refresh event:
|
|
372
|
+
\`\`\`bash
|
|
373
|
+
echo "$(date +%H:%M:%S) | feature-lead | context-refresh" >> ${dashboardLog}
|
|
374
|
+
\`\`\`
|
|
375
|
+
|
|
376
|
+
4. **GATE-CONTEXT.md (all teams)** — Complete or note which teams still need context
|
|
377
|
+
|
|
378
|
+
5. **Cross-team contracts** — Record any established/modified contracts in FEATURE-STATUS.md
|
|
379
|
+
|
|
380
|
+
6. **Open questions** — Verify .answer files written, log decision rationale
|
|
381
|
+
|
|
382
|
+
### How to Refresh
|
|
383
|
+
|
|
384
|
+
After completing the full checklist above:
|
|
385
|
+
\`\`\`bash
|
|
386
|
+
echo REFRESH > ${featureLeadDir}/.context-refresh
|
|
387
|
+
\`\`\`
|
|
388
|
+
|
|
389
|
+
### Emergency Refresh
|
|
390
|
+
|
|
391
|
+
If context is critically low:
|
|
392
|
+
1. Write MINIMAL but complete FEATURE-STATUS.md update
|
|
393
|
+
2. Signal immediately:
|
|
394
|
+
\`\`\`bash
|
|
395
|
+
echo REFRESH > ${featureLeadDir}/.context-refresh
|
|
396
|
+
\`\`\``;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// ─── Feature Lead: Init Prompt ───────────────────────────────────────────────
|
|
400
|
+
|
|
401
|
+
export function buildFeatureLeadInitPrompt({
|
|
402
|
+
featureName, numTeams, teamType, teamSignalBase,
|
|
403
|
+
planReadInstruction, featureLeadDir, featureReviewDir, dashboardLog,
|
|
404
|
+
}) {
|
|
405
|
+
const monitor = buildMonitorInstructions(numTeams, teamSignalBase, featureLeadDir, featureReviewDir);
|
|
406
|
+
const gateReview = buildGateReviewInstructions(featureLeadDir, featureReviewDir);
|
|
407
|
+
const contextMgmt = buildContextManagementInstructions(featureLeadDir, dashboardLog);
|
|
408
|
+
const slackComm = buildSlackCommInstructions(featureLeadDir);
|
|
409
|
+
|
|
410
|
+
return `You are the Feature Lead for '${featureName}' with ${numTeams} teams (type: ${teamType}).
|
|
411
|
+
|
|
412
|
+
Read your instructions at ~/src/iriai/iriai-team/roles-v2/feature-lead/CLAUDE.md.
|
|
413
|
+
Read the feature status at ~/src/iriai/iriai-team/FEATURE-STATUS.md.
|
|
414
|
+
${planReadInstruction}
|
|
415
|
+
|
|
416
|
+
## Dispatch Gate 1
|
|
417
|
+
|
|
418
|
+
1. Read and understand the full implementation plan
|
|
419
|
+
2. Identify the gate boundaries in the plan
|
|
420
|
+
3. Partition Gate 1 work across ${numTeams} teams
|
|
421
|
+
4. Write GATE-CONTEXT.md for each team (at ${teamSignalBase}/team-N/GATE-CONTEXT.md)
|
|
422
|
+
5. Write team manifests if not present (at ${teamSignalBase}/team-N/manifest.yaml)
|
|
423
|
+
6. Dispatch to each team orchestrator by writing .task files (at ${teamSignalBase}/team-N/orchestrator/.task)
|
|
424
|
+
7. Update FEATURE-STATUS.md with gate 1 status
|
|
425
|
+
8. Update DASHBOARD.md
|
|
426
|
+
${monitor}
|
|
427
|
+
${gateReview}
|
|
428
|
+
${contextMgmt}
|
|
429
|
+
${slackComm}`;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// ─── Feature Lead: Refresh/Continue Prompt ───────────────────────────────────
|
|
433
|
+
|
|
434
|
+
export function buildFeatureLeadRefreshPrompt({
|
|
435
|
+
featureName, numTeams, teamSignalBase,
|
|
436
|
+
planReadInstruction, featureLeadDir, featureReviewDir, dashboardLog,
|
|
437
|
+
gateEvidenceTs,
|
|
438
|
+
}) {
|
|
439
|
+
const monitor = buildMonitorInstructions(numTeams, teamSignalBase, featureLeadDir, featureReviewDir);
|
|
440
|
+
const gateReview = buildGateReviewInstructions(featureLeadDir, featureReviewDir);
|
|
441
|
+
const contextMgmt = buildContextManagementInstructions(featureLeadDir, dashboardLog);
|
|
442
|
+
const slackComm = buildSlackCommInstructions(featureLeadDir);
|
|
443
|
+
|
|
444
|
+
const gateDedup = gateEvidenceTs
|
|
445
|
+
? `\nIMPORTANT: Gate evidence was ALREADY posted to Slack at timestamp ${gateEvidenceTs}.\nDo NOT re-post gate evidence. You are waiting for the user's GATE APPROVED / GATE REJECTED response\nin the impl channel. Poll for .user-message, do not repost.\n`
|
|
446
|
+
: "";
|
|
447
|
+
|
|
448
|
+
return `You are the Feature Lead for '${featureName}' with ${numTeams} teams.
|
|
449
|
+
|
|
450
|
+
Read your instructions at ~/src/iriai/iriai-team/roles-v2/feature-lead/CLAUDE.md.
|
|
451
|
+
|
|
452
|
+
CONTEXT REFRESH: Your previous session requested a context refresh. All state has been
|
|
453
|
+
persisted to disk. Read these files to restore your state:
|
|
454
|
+
|
|
455
|
+
1. ~/src/iriai/iriai-team/FEATURE-STATUS.md — your persistent memory (source of truth)
|
|
456
|
+
2. ~/src/iriai/iriai-team/DASHBOARD.md — current team status
|
|
457
|
+
3. Each team's GATE-CONTEXT.md at ${teamSignalBase}/team-N/GATE-CONTEXT.md
|
|
458
|
+
|
|
459
|
+
Check FEATURE-STATUS.md for 'what was in progress' and 'next steps' to understand
|
|
460
|
+
exactly where to resume. Do not re-do completed work.
|
|
461
|
+
${gateDedup}
|
|
462
|
+
${planReadInstruction}
|
|
463
|
+
${monitor}
|
|
464
|
+
${gateReview}
|
|
465
|
+
${contextMgmt}
|
|
466
|
+
${slackComm}`;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// ─── Feature Lead: Trigger-Based Phase Prompt ────────────────────────────────
|
|
470
|
+
|
|
471
|
+
export function buildFeatureLeadTriggerPrompt({
|
|
472
|
+
featureName, numTeams, trigger, teamSignalBase,
|
|
473
|
+
featureLeadDir, featureReviewDir, dashboardLog,
|
|
474
|
+
questionTeams, crashedTeams, recoveryContext,
|
|
475
|
+
}) {
|
|
476
|
+
const monitor = buildMonitorInstructions(numTeams, teamSignalBase, featureLeadDir, featureReviewDir);
|
|
477
|
+
const gateReview = buildGateReviewInstructions(featureLeadDir, featureReviewDir);
|
|
478
|
+
const contextMgmt = buildContextManagementInstructions(featureLeadDir, dashboardLog);
|
|
479
|
+
const slackComm = buildSlackCommInstructions(featureLeadDir);
|
|
480
|
+
|
|
481
|
+
let base = `You are the Feature Lead for '${featureName}' with ${numTeams} teams.
|
|
482
|
+
|
|
483
|
+
Read your instructions at ~/src/iriai/iriai-team/roles-v2/feature-lead/CLAUDE.md.
|
|
484
|
+
Read the feature status at ~/src/iriai/iriai-team/FEATURE-STATUS.md.
|
|
485
|
+
Read ~/src/iriai/iriai-team/DASHBOARD.md for current state.
|
|
486
|
+
`;
|
|
487
|
+
|
|
488
|
+
if (recoveryContext) {
|
|
489
|
+
base = `RECOVERY: Your prior session crashed during this phase. Resume from where you left off.
|
|
490
|
+
Read ~/src/iriai/iriai-team/FEATURE-STATUS.md for current state.
|
|
491
|
+
Read ~/src/iriai/iriai-team/DASHBOARD.md for team status.
|
|
492
|
+
|
|
493
|
+
${base}`;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
switch (trigger) {
|
|
497
|
+
case "gate-ready":
|
|
498
|
+
base += `
|
|
499
|
+
TRIGGER: All ${numTeams} teams have signaled .gate-ready.
|
|
500
|
+
${gateReview}`;
|
|
501
|
+
break;
|
|
502
|
+
|
|
503
|
+
case "question":
|
|
504
|
+
base += `
|
|
505
|
+
TRIGGER: Teams ${questionTeams.join(", ")} have questions that need resolution.
|
|
506
|
+
|
|
507
|
+
You must:
|
|
508
|
+
1. Read each questioning team's .question file at ${teamSignalBase}/team-N/orchestrator/.question
|
|
509
|
+
2. Read FEATURE-STATUS.md for cross-team context
|
|
510
|
+
3. If you can resolve the question with your cross-team knowledge:
|
|
511
|
+
- Write the answer to ${teamSignalBase}/team-N/orchestrator/.answer
|
|
512
|
+
- Remove the .question file
|
|
513
|
+
4. If you cannot resolve it: surface it to the user and wait for their response
|
|
514
|
+
- Then write the user's answer to ${teamSignalBase}/team-N/orchestrator/.answer
|
|
515
|
+
- Remove the .question file
|
|
516
|
+
5. Update FEATURE-STATUS.md and DASHBOARD.md
|
|
517
|
+
|
|
518
|
+
After handling questions, continue monitoring teams:
|
|
519
|
+
${monitor}
|
|
520
|
+
${gateReview}`;
|
|
521
|
+
break;
|
|
522
|
+
|
|
523
|
+
case "crash":
|
|
524
|
+
base += `
|
|
525
|
+
TRIGGER: Teams ${crashedTeams.join(", ")} have crashed orchestrators.
|
|
526
|
+
|
|
527
|
+
You must:
|
|
528
|
+
1. Read the crashed team's HANDOVER.md to understand progress
|
|
529
|
+
2. Determine what work was completed and what remains
|
|
530
|
+
3. Write a recovery .task to ${teamSignalBase}/team-N/orchestrator/.task that:
|
|
531
|
+
- References HANDOVER.md for completed work
|
|
532
|
+
- Assigns only the remaining work
|
|
533
|
+
4. Remove the .crashed file (run-team.sh will detect the new .task)
|
|
534
|
+
5. If recovery isn't possible, surface the issue to the user
|
|
535
|
+
6. Update FEATURE-STATUS.md and DASHBOARD.md
|
|
536
|
+
|
|
537
|
+
After handling crashes, continue monitoring teams:
|
|
538
|
+
${monitor}
|
|
539
|
+
${gateReview}`;
|
|
540
|
+
break;
|
|
541
|
+
|
|
542
|
+
case "idle-redispatch":
|
|
543
|
+
base += `
|
|
544
|
+
TRIGGER: All ${numTeams} teams are idle — they have no active .task files.
|
|
545
|
+
This typically happens after a session restart (launch.sh continue).
|
|
546
|
+
|
|
547
|
+
## Re-dispatch Teams
|
|
548
|
+
|
|
549
|
+
1. Read FEATURE-STATUS.md to understand the current gate and what was dispatched
|
|
550
|
+
2. Read each team's GATE-CONTEXT.md and HANDOVER.md to understand their assignment and progress
|
|
551
|
+
3. For each team, write a new .task file to ${teamSignalBase}/team-N/orchestrator/.task
|
|
552
|
+
- If the team has made progress (check HANDOVER.md), assign only remaining work
|
|
553
|
+
- If no progress, re-dispatch the full gate assignment from GATE-CONTEXT.md
|
|
554
|
+
4. Update FEATURE-STATUS.md and DASHBOARD.md
|
|
555
|
+
${monitor}
|
|
556
|
+
${gateReview}`;
|
|
557
|
+
break;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
base += `
|
|
561
|
+
${contextMgmt}
|
|
562
|
+
${slackComm}`;
|
|
563
|
+
|
|
564
|
+
return base;
|
|
565
|
+
}
|