forgedock 1.0.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/LICENSE +244 -0
- package/README.md +251 -0
- package/bin/forgedock.mjs +232 -0
- package/commands/analytics.md +777 -0
- package/commands/audit-agents.md +410 -0
- package/commands/audit.md +410 -0
- package/commands/autopilot.md +432 -0
- package/commands/cleanup.md +264 -0
- package/commands/deploy-info.md +292 -0
- package/commands/failure-recon.md +375 -0
- package/commands/forge-stats.md +183 -0
- package/commands/geo-audit.md +343 -0
- package/commands/incident-response.md +384 -0
- package/commands/issue.md +506 -0
- package/commands/milestone.md +599 -0
- package/commands/orchestrate.md +1044 -0
- package/commands/pipeline-health.md +2343 -0
- package/commands/qa-sweep.md +237 -0
- package/commands/quality-gate.md +777 -0
- package/commands/review-pr-agents.md +1711 -0
- package/commands/review-pr-staging.md +325 -0
- package/commands/review-pr.md +888 -0
- package/commands/rollback.md +253 -0
- package/commands/security-audit.md +529 -0
- package/commands/sync-ecosystem.md +527 -0
- package/commands/validate.md +131 -0
- package/commands/work-on/build/architect.md +291 -0
- package/commands/work-on/build/context.md +349 -0
- package/commands/work-on/build/implement.md +280 -0
- package/commands/work-on/build/validate.md +292 -0
- package/commands/work-on/build.md +262 -0
- package/commands/work-on/close.md +350 -0
- package/commands/work-on/decompose.md +254 -0
- package/commands/work-on/investigate.md +437 -0
- package/commands/work-on/review.md +245 -0
- package/commands/work-on-monolithic.md +298 -0
- package/commands/work-on.md +1089 -0
- package/docs/CODEX.md +92 -0
- package/docs/WORKFLOW.md +104 -0
- package/package.json +45 -0
- package/scripts/verify-env-vars.sh +201 -0
- package/scripts/verify-host-headers.sh +117 -0
- package/scripts/verify-route-registration.sh +118 -0
- package/scripts/verify-sops-chain.sh +163 -0
|
@@ -0,0 +1,1044 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Orchestrate parallel work on multiple issues or an entire milestone — spawns sub-agents that each run the full /work-on pipeline
|
|
3
|
+
argument-hint: [milestone <slug> | #1 #2 #3 | next <N> | fast-lane | P0]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /orchestrate — Multi-Issue Parallel Orchestrator
|
|
7
|
+
|
|
8
|
+
**Input**: $ARGUMENTS
|
|
9
|
+
|
|
10
|
+
## HARD RULES — READ BEFORE ANYTHING ELSE
|
|
11
|
+
|
|
12
|
+
1. **Every agent MUST invoke `/work-on` via the Skill tool.** You do NOT write implementation prompts. You copy the Phase 4A template verbatim and fill in the `{VARIABLES}`. Nothing else. No custom prompts. No "just read and edit" shortcuts. The Skill tool invocation is what triggers labels, investigation comments, structured review, and trajectory tracking. Without it, the agent's work has no paper trail and is worthless.
|
|
13
|
+
|
|
14
|
+
2. **You are a dispatcher, not a builder.** You resolve issues, plan waves, spawn agents, and report results. You NEVER read code, edit files, or implement fixes yourself.
|
|
15
|
+
|
|
16
|
+
3. **After each wave, verify agents used `/work-on`.** Check that completed issues have `workflow:*` labels and structured comments. If an agent bypassed the pipeline, report it as a failure.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
You are the top-level orchestrator. Your job is to take a batch of issues, plan the execution order, spawn parallel sub-agents (each running the full `/work-on` pipeline), and report consolidated results.
|
|
21
|
+
|
|
22
|
+
**You have access to ALL tools** — Agent tool (critical), Task tool, Skill tool, Bash, everything. Use the Agent tool aggressively to parallelize work.
|
|
23
|
+
|
|
24
|
+
**Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`. User can override with `--model <name>`.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Multi-Repo Support
|
|
29
|
+
|
|
30
|
+
This orchestrator supports issues across the AlterLab ecosystem. See `/work-on` → "Multi-Repo Support" for the full project registry and context variables.
|
|
31
|
+
|
|
32
|
+
### Cross-Repo Issue References
|
|
33
|
+
|
|
34
|
+
Issues can be prefixed with a project shorthand:
|
|
35
|
+
- `#123` or `123` → AlterLab (default: `RapierCraft/AlterLab`)
|
|
36
|
+
- `mcp:5` → MCP Server (`RapierCraft/alterlab-mcp-server`)
|
|
37
|
+
- `n8n:12` → n8n Node (`RapierCraft/n8n-nodes-alterlab`)
|
|
38
|
+
- `all-repos` → Scan all ecosystem repos for open issues (combine and prioritize)
|
|
39
|
+
|
|
40
|
+
When spawning sub-agents, pass the project prefix so `/work-on` resolves to the correct repo.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Phase 1: Resolve the Issue Set
|
|
45
|
+
|
|
46
|
+
Parse `$ARGUMENTS` to determine which issues to work on:
|
|
47
|
+
|
|
48
|
+
### Input Patterns
|
|
49
|
+
|
|
50
|
+
| Input | Resolution |
|
|
51
|
+
|-------|------------|
|
|
52
|
+
| `milestone <slug>` | All open issues assigned to that GitHub milestone (default repo) |
|
|
53
|
+
| `#1 #2 #3` or `1 2 3` | Specific issue numbers, optionally repo-prefixed (e.g., `#123 mcp:5 n8n:12`) |
|
|
54
|
+
| `next <N>` | Top N priority open issues (P0 first, then P1, etc.) |
|
|
55
|
+
| `next <N> all-repos` | Top N across ALL ecosystem repos |
|
|
56
|
+
| `fast-lane` or `fast` | All open fast-lane issues (no milestone, bugs/fixes) |
|
|
57
|
+
| `P0` or `P1` | All open issues with that priority label |
|
|
58
|
+
| `mcp:fast` or `n8n:next 3` | Repo-scoped queries |
|
|
59
|
+
| `<slug>` (no keyword) | Try milestone first, then fall back to label search |
|
|
60
|
+
|
|
61
|
+
### Fetch the issues
|
|
62
|
+
|
|
63
|
+
For each resolved repo, use the appropriate `-R` flag:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# AlterLab (default — no flag needed):
|
|
67
|
+
gh issue list --milestone "{TITLE}" --state open --limit 500 --json number,title,labels,milestone --jq '.[] | {number, title, labels: [.labels[].name], milestone: .milestone.title}'
|
|
68
|
+
|
|
69
|
+
# Satellite repos — always include -R flag:
|
|
70
|
+
gh issue list -R RapierCraft/alterlab-mcp-server --milestone "{TITLE}" --state open --limit 500 --json number,title,labels,milestone
|
|
71
|
+
gh issue list -R RapierCraft/n8n-nodes-alterlab --milestone "{TITLE}" --state open --limit 500 --json number,title,labels,milestone
|
|
72
|
+
|
|
73
|
+
# For specific numbers with repo prefix:
|
|
74
|
+
gh issue view 5 -R RapierCraft/alterlab-mcp-server --json number,title,labels,state,milestone,body
|
|
75
|
+
|
|
76
|
+
# For "all-repos" — fetch from all and combine:
|
|
77
|
+
gh issue list --state open --limit {N} --json number,title,labels,milestone
|
|
78
|
+
gh issue list -R RapierCraft/alterlab-mcp-server --state open --limit 500 --json number,title,labels,milestone
|
|
79
|
+
gh issue list -R RapierCraft/n8n-nodes-alterlab --state open --limit 500 --json number,title,labels,milestone
|
|
80
|
+
# Combine, sort by priority, take top N
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Count validation**: After fetching issues, log the count returned. If a milestone query returns exactly 30 issues, warn the user: "WARNING: Exactly 30 issues returned — gh CLI default may have truncated results. Re-running with --limit 500 is recommended." (The --limit 500 above prevents this for standard runs, but verify if the count seems suspiciously low relative to milestone expectations.)
|
|
84
|
+
|
|
85
|
+
**Tag each issue with its project prefix** in your internal tracking so sub-agents receive the correct repo context.
|
|
86
|
+
|
|
87
|
+
### Filter out ineligible issues
|
|
88
|
+
|
|
89
|
+
Remove issues that should NOT be worked on:
|
|
90
|
+
- Already closed or has `workflow:merged` label
|
|
91
|
+
- Has `workflow:invalid` label
|
|
92
|
+
- Has `needs-human` label (requires manual action)
|
|
93
|
+
- Has `workflow:decomposed` label (parent tracker — its sub-issues should be picked up instead)
|
|
94
|
+
- Has `workflow:building` or `workflow:in-review` label (already in progress)
|
|
95
|
+
- Is an epic (`epic` label) — these are planning containers, not buildable
|
|
96
|
+
|
|
97
|
+
If a `workflow:decomposed` issue is found, automatically expand it to its open sub-issues instead.
|
|
98
|
+
|
|
99
|
+
### CRITICAL: No duplicate detection at orchestrator level
|
|
100
|
+
|
|
101
|
+
**The orchestrator NEVER closes, merges, or deduplicates issues.** Even if two issues look like duplicates (similar titles, same error message, same symptoms), they may target different code paths, different ORM objects, or different failure modes. Only a `/work-on` investigation agent — after reading the actual code — can determine whether an issue is truly a duplicate.
|
|
102
|
+
|
|
103
|
+
**What the orchestrator must NOT do:**
|
|
104
|
+
- Close an issue as "duplicate" based on title/symptom similarity
|
|
105
|
+
- Skip an issue because another issue "covers it"
|
|
106
|
+
- Merge two issues into one agent
|
|
107
|
+
- Make ANY judgment about issue validity
|
|
108
|
+
|
|
109
|
+
**What the orchestrator SHOULD do:**
|
|
110
|
+
- If two issues look related, add a note in the agent prompt: "Note: #{OTHER} has similar symptoms — investigate whether this is the same root cause or a different code path"
|
|
111
|
+
- Let both agents run independently — if one finds it's truly a duplicate, `/work-on`'s investigation phase will close it as invalid with evidence
|
|
112
|
+
- Flag potential overlap in the wave plan for the user's awareness, but NEVER act on it
|
|
113
|
+
|
|
114
|
+
**Why**: Surface-level similarity hides critical differences. #3842 (api_key.id lazy load) and #4039 (user.id lazy load) had identical error messages but targeted completely different ORM objects. Closing #4039 as a "duplicate" would have left a customer-impacting P0 bug unfixed.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Phase 2: Investigation-First Triage
|
|
119
|
+
|
|
120
|
+
**Purpose**: Investigation issues produce NEW GitHub issues as their output. If the batch contains investigations, they must run FIRST so their output can be folded into the execution plan.
|
|
121
|
+
|
|
122
|
+
**If no investigations are found in Step 2A, skip this entire phase and proceed directly to Phase 3.**
|
|
123
|
+
|
|
124
|
+
### Step 2A: Classify each issue
|
|
125
|
+
|
|
126
|
+
For each issue in the resolved set, read its title and body to classify it:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
for NUM in {issue_numbers}; do
|
|
130
|
+
gh issue view $NUM --json title,body,labels --jq '{title: .title, labels: [.labels[].name], body_preview: (.body[:500])}'
|
|
131
|
+
done
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Classification rules:**
|
|
135
|
+
|
|
136
|
+
| Signal | Classification |
|
|
137
|
+
|--------|---------------|
|
|
138
|
+
| Title contains "Investigate", "Audit", "Research", "Evaluate", "Assess", "Deep dive" | **Investigation** |
|
|
139
|
+
| Issue body is primarily questions (`- [ ]` checklist) with no concrete code changes | **Investigation** |
|
|
140
|
+
| Issue body says "Deliverable: execution plan" or "create issues" | **Investigation** |
|
|
141
|
+
| Issue has `enhancement` label + title starts with "Enable" + body describes toggling a feature flag | **Implementation** |
|
|
142
|
+
| Issue has `bug`, `refactor`, `dead-code`, or `feature` label | **Implementation** |
|
|
143
|
+
|
|
144
|
+
Tag each issue internally as `INVESTIGATION` or `IMPLEMENTATION`.
|
|
145
|
+
|
|
146
|
+
### Step 2B: Run investigations first (Wave 0)
|
|
147
|
+
|
|
148
|
+
If ANY issues are classified as `INVESTIGATION`:
|
|
149
|
+
|
|
150
|
+
1. **Move them to Wave 0** — they run BEFORE all implementation issues
|
|
151
|
+
2. **Spawn Wave 0 agents** using the same agent template as Phase 4A, but emphasize that `/work-on` will detect the investigation task type and produce issues (not code)
|
|
152
|
+
3. **Wait for ALL Wave 0 agents to complete** before proceeding to Phase 3
|
|
153
|
+
|
|
154
|
+
### Step 2C: Collect newly created issues
|
|
155
|
+
|
|
156
|
+
After Wave 0 completes, each investigation agent will have created new GitHub issues. Collect them:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# For each investigation issue that completed successfully:
|
|
160
|
+
# Read the FORGE:BUILDER comment to find created issue numbers
|
|
161
|
+
for INV_NUM in {investigation_numbers}; do
|
|
162
|
+
gh api repos/{GH_REPO}/issues/${INV_NUM}/comments \
|
|
163
|
+
--jq '.[] | select(.body | contains("<!-- FORGE:BUILDER -->")) | .body' \
|
|
164
|
+
| grep -oP '#\K\d+' | sort -u
|
|
165
|
+
done
|
|
166
|
+
|
|
167
|
+
# Also check: if the investigation issue had a milestone, the new issues should too
|
|
168
|
+
# Verify milestone assignment:
|
|
169
|
+
for NEW_NUM in {newly_created_numbers}; do
|
|
170
|
+
gh issue view $NEW_NUM --json milestone --jq '.milestone.title // "NO MILESTONE"'
|
|
171
|
+
done
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Step 2C.5: Collect Knowledge Gist URLs from investigations
|
|
175
|
+
|
|
176
|
+
For each completed investigation issue, query its comments for `FORGE:KNOWLEDGE_GIST` annotations. Store the mapping of investigation issue number → Gist URL(s) so the agent template in Step 4A can include prior investigation context.
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Build a map: investigation_number → gist_url(s)
|
|
180
|
+
declare -A INVESTIGATION_GISTS
|
|
181
|
+
for INV_NUM in {investigation_numbers}; do
|
|
182
|
+
GIST_URLS=$(gh api repos/{GH_REPO}/issues/${INV_NUM}/comments \
|
|
183
|
+
--jq '[.[] | select(.body | test("<!-- FORGE:KNOWLEDGE_GIST: https://")) | .body | capture("<!-- FORGE:KNOWLEDGE_GIST: (?<url>https://[^ ]+) -->").url] | unique | .[]')
|
|
184
|
+
if [ -n "$GIST_URLS" ]; then
|
|
185
|
+
INVESTIGATION_GISTS[$INV_NUM]="$GIST_URLS"
|
|
186
|
+
echo "Investigation #${INV_NUM}: found Gist URL(s)"
|
|
187
|
+
fi
|
|
188
|
+
done
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
When spawning agents for implementation issues in Step 4A, include any Gist URLs from parent/sibling investigations in the agent prompt's context block. See the `{GIST_CONTEXT}` variable in the agent template.
|
|
192
|
+
|
|
193
|
+
**Milestone index Gist**: If the milestone has a `<!-- FORGE:MILESTONE_INDEX: {url} -->` annotation in its description, read the index URL and store it for inclusion in agent context. The milestone index aggregates all investigation Gist URLs for the milestone into a single reference.
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Read milestone index URL from milestone description (if milestone exists)
|
|
197
|
+
MILESTONE_INDEX_URL=""
|
|
198
|
+
if [ -n "$MILESTONE_NUM" ]; then
|
|
199
|
+
MILESTONE_DESC=$(gh api repos/{GH_REPO}/milestones/${MILESTONE_NUM} --jq '.description // ""' 2>/dev/null)
|
|
200
|
+
MILESTONE_INDEX_URL=$(echo "$MILESTONE_DESC" | grep -oP '(?<=<!-- FORGE:MILESTONE_INDEX: )https://[^ ]+(?= -->)' | head -1)
|
|
201
|
+
if [ -n "$MILESTONE_INDEX_URL" ]; then
|
|
202
|
+
echo "Milestone index Gist found: ${MILESTONE_INDEX_URL}"
|
|
203
|
+
fi
|
|
204
|
+
fi
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Step 2D: Merge new issues into the batch
|
|
208
|
+
|
|
209
|
+
Add the newly created issues to the issue set. Re-check each one:
|
|
210
|
+
- Filter out any that are already ineligible (same rules as Phase 1)
|
|
211
|
+
- Tag them as `IMPLEMENTATION` (investigations don't spawn more investigations)
|
|
212
|
+
- They inherit the milestone from their parent investigation if applicable
|
|
213
|
+
|
|
214
|
+
**Updated issue set** = original `IMPLEMENTATION` issues + newly spawned issues from investigations.
|
|
215
|
+
|
|
216
|
+
### Step 2E: Report Wave 0 results to user
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
## Wave 0: Investigations Complete
|
|
220
|
+
|
|
221
|
+
| # | Investigation | Result | Issues Created |
|
|
222
|
+
|---|--------------|--------|---------------|
|
|
223
|
+
| #{INV1} | {title} | ✓ Closed | #{N1}, #{N2}, #{N3} |
|
|
224
|
+
| #{INV2} | {title} | ✓ Closed | #{N4}, #{N5} |
|
|
225
|
+
|
|
226
|
+
**New issues added to batch**: {count}
|
|
227
|
+
**Updated total**: {original_count} → {new_total} issues
|
|
228
|
+
|
|
229
|
+
Proceeding to dependency analysis with the expanded issue set...
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Phase 3: Dependency Analysis & Execution Plan
|
|
235
|
+
|
|
236
|
+
### Step 3A: Analyze explicit dependencies
|
|
237
|
+
|
|
238
|
+
For each issue (including newly spawned ones from Phase 2), check:
|
|
239
|
+
1. **Explicit dependencies**: Issue body contains "Depends on #X" or "Blocked by #X"
|
|
240
|
+
2. **Milestone ordering**: Issues within a milestone may have a natural order (foundation → features → UI)
|
|
241
|
+
3. **File conflicts**: If two issues modify the same files, they should be sequential (not parallel)
|
|
242
|
+
4. **Parent-child links**: If issue body contains "Parent investigation: #{X}", it was spawned by an investigation — no special ordering needed unless explicitly stated
|
|
243
|
+
|
|
244
|
+
Read each issue's body briefly to check for dependency markers:
|
|
245
|
+
```bash
|
|
246
|
+
for NUM in {issue_numbers}; do
|
|
247
|
+
gh issue view $NUM --json body --jq '.body' | grep -iE 'depends on|blocked by|after #|parent investigation' || echo "no deps"
|
|
248
|
+
done
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Step 3B: Domain estimation
|
|
252
|
+
|
|
253
|
+
For each issue, estimate which domains it touches based on title, body, and labels. This improves wave planning — issues in the same domain likely touch the same files and should be sequential.
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
for NUM in {issue_numbers}; do
|
|
257
|
+
ISSUE=$(gh issue view $NUM --json title,body,labels --jq '{title: .title, labels: [.labels[].name], body: (.body[:300])}')
|
|
258
|
+
echo "=== #$NUM ==="
|
|
259
|
+
echo "$ISSUE" | grep -qiE "credit|billing|pricing|stripe|tier.*cost|charge|refund" && echo " BILLING" || true
|
|
260
|
+
echo "$ISSUE" | grep -qiE "auth|session|jwt|login|permission|oauth" && echo " AUTH" || true
|
|
261
|
+
echo "$ISSUE" | grep -qiE "scrape|tier|proxy|playwright|playbook|worker|unified_consumer|penetrat" && echo " SCRAPING" || true
|
|
262
|
+
echo "$ISSUE" | grep -qiE "migration|\.sql|database|postgres|alembic" && echo " DATABASE" || true
|
|
263
|
+
echo "$ISSUE" | grep -qiE "component|page|layout|dashboard|ui|ux|frontend|web/src" && echo " FRONTEND" || true
|
|
264
|
+
echo "$ISSUE" | grep -qiE "docker|deploy|traefik|nginx|ci|cd|infra|github.action" && echo " INFRA" || true
|
|
265
|
+
echo "$ISSUE" | grep -qiE "cortex|llm|extract|schema|format" && echo " CORTEX" || true
|
|
266
|
+
done
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Use domain info for wave planning:**
|
|
270
|
+
- Issues in the SAME domain (especially SCRAPING, BILLING, DATABASE) are more likely to touch the same files → prefer sequential within a wave or adjacent waves
|
|
271
|
+
- Issues in DIFFERENT domains are more likely independent → safe to parallelize
|
|
272
|
+
- BILLING + AUTH issues should be prioritized early (security-critical)
|
|
273
|
+
- **DATABASE issues are ALWAYS serialized — hard rule, no exceptions.** Multiple agents writing migrations simultaneously will produce duplicate migration numbers (e.g., two `0067_*.sql` files), which breaks the migration runner. Every DATABASE issue must be in its own wave. If 3 DATABASE issues are in a batch: Wave 1 runs issue A, Wave 2 runs issue B, Wave 3 runs issue C.
|
|
274
|
+
|
|
275
|
+
**Store domain tags per issue** for use in the plan presentation (Step 3E).
|
|
276
|
+
|
|
277
|
+
### Step 3C: Multi-layer conflict detection
|
|
278
|
+
|
|
279
|
+
Domain estimation (above) catches broad category overlap but misses cases where two issues modify the exact same file without mentioning the same keywords, or where two issues touch different files that share indirect dependencies (imports, config, barrel exports). This step uses three layers of structural analysis to catch conflicts the keyword heuristic misses.
|
|
280
|
+
|
|
281
|
+
#### Layer 1: Explicit file-overlap extraction
|
|
282
|
+
|
|
283
|
+
**For issues that already have an INVESTIGATOR comment** (from Wave 0 or a prior session), extract their Affected Files list:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
for NUM in {issue_numbers}; do
|
|
287
|
+
echo "=== #$NUM ==="
|
|
288
|
+
gh api repos/{GH_REPO}/issues/${NUM}/comments \
|
|
289
|
+
--jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body' 2>/dev/null \
|
|
290
|
+
| grep -oP '`[^`]*\.(py|tsx?|jsx?|sql|json|ya?ml)`' | sort -u
|
|
291
|
+
done
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**For issues WITHOUT an investigation comment**, fall back to parsing the issue body for file paths:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
gh issue view $NUM --json body --jq '.body' | grep -oP '`[^`]*\.(py|tsx?|jsx?|sql|json|ya?ml)`' | sort -u
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Cross-reference all extracted file lists:**
|
|
301
|
+
- If two issues share ANY affected file → they MUST be in separate waves (sequential)
|
|
302
|
+
- The issue with lower issue number goes first (stable ordering), unless an explicit `Depends on #` says otherwise
|
|
303
|
+
- Add a conflict note to the wave plan: "#{A} and #{B} both modify `{file}` — serialized"
|
|
304
|
+
|
|
305
|
+
#### Layer 2: Directory-proximity detection
|
|
306
|
+
|
|
307
|
+
Two issues that modify different files in the **same leaf directory** have a high probability of conflicting through shared `__init__.py`, `index.ts`, barrel re-exports, or tightly coupled sibling modules. This layer catches indirect conflicts that Layer 1 misses.
|
|
308
|
+
|
|
309
|
+
**Extract the leaf directory for each affected file:**
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
# For each issue's file list, extract unique directories
|
|
313
|
+
for NUM in {issue_numbers}; do
|
|
314
|
+
echo "=== #$NUM directories ==="
|
|
315
|
+
# From the file list already extracted in Layer 1:
|
|
316
|
+
echo "$FILES_FOR_NUM" | xargs -I{} dirname {} | sort -u
|
|
317
|
+
done
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**Cross-reference directory lists:**
|
|
321
|
+
- If two issues share a leaf directory AND that directory is "small" (contains fewer than 10 tracked files), flag as **probable conflict** → serialize
|
|
322
|
+
- If the shared directory is a broad container (e.g., `services/api/app/routers/` with 15+ files), downgrade to **possible conflict** → serialize only if same domain tag (from Step 3B)
|
|
323
|
+
- **Known high-conflict directories** (always serialize if shared):
|
|
324
|
+
- `services/api/app/models/` (SQLAlchemy models often share Base, imports)
|
|
325
|
+
- `services/api/app/core/` (shared dependencies)
|
|
326
|
+
- `services/worker/worker/` (tightly coupled consumer modules)
|
|
327
|
+
- `web/src/lib/` (shared utilities)
|
|
328
|
+
- `shared/` (volume-mounted, affects all services)
|
|
329
|
+
- `infra/migrations/` (already covered by DATABASE hard rule, but explicit here too)
|
|
330
|
+
|
|
331
|
+
#### Layer 3: Shared-module inference
|
|
332
|
+
|
|
333
|
+
When two issues modify different files that **import from the same utility/init module**, both agents often end up modifying that shared module (adding imports, updating re-exports). This creates merge conflicts invisible to Layer 1.
|
|
334
|
+
|
|
335
|
+
**Heuristic rules (no git operations needed — pattern-based):**
|
|
336
|
+
|
|
337
|
+
| Pattern | Inference | Action |
|
|
338
|
+
|---------|-----------|--------|
|
|
339
|
+
| Issue A modifies `routers/billing.py`, Issue B modifies `routers/auth.py` | Both likely import from `routers/__init__.py` or `dependencies.py` | Flag as possible conflict if same service |
|
|
340
|
+
| Issue A modifies `models/user.py`, Issue B modifies `models/subscription.py` | Both likely modify `models/__init__.py` (SQLAlchemy model registry) | Flag as probable conflict → serialize |
|
|
341
|
+
| Issue A modifies `web/src/components/X.tsx`, Issue B modifies `web/src/components/Y.tsx` | May share `index.ts` barrel export | Flag only if same parent directory |
|
|
342
|
+
| Issue A modifies `services/api/app/main.py` | `main.py` is a high-fan-in file (router registration, middleware) | Serialize with ANY other API issue |
|
|
343
|
+
| Issue A modifies `docker-compose.yml` or `docker-compose.prod.yml` | Global config — any concurrent modification conflicts | Serialize with ALL other issues that touch infra |
|
|
344
|
+
|
|
345
|
+
**Apply inferences:**
|
|
346
|
+
```
|
|
347
|
+
# High-fan-in files — if ANY issue touches these, serialize it with all same-service issues:
|
|
348
|
+
HIGH_FAN_IN = [
|
|
349
|
+
"services/api/app/main.py",
|
|
350
|
+
"services/worker/worker/unified_consumer.py",
|
|
351
|
+
"web/src/app/layout.tsx",
|
|
352
|
+
"docker-compose.yml",
|
|
353
|
+
"docker-compose.prod.yml",
|
|
354
|
+
".env.example"
|
|
355
|
+
]
|
|
356
|
+
|
|
357
|
+
# For each issue, check if affected files include a high-fan-in file
|
|
358
|
+
# If yes: that issue cannot be parallelized with any other issue touching the same service
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### Layer 4: Conservative fallback (low-confidence cases)
|
|
362
|
+
|
|
363
|
+
When file extraction yields **fewer than 2 file paths** for an issue (common for issues without investigation comments, or issues described in prose without backtick-wrapped paths), the conflict detection has low confidence. Rather than assuming independence, apply conservative serialization.
|
|
364
|
+
|
|
365
|
+
**Rules:**
|
|
366
|
+
- If an issue has 0-1 extracted file paths AND shares a domain tag (from Step 3B) with another issue → serialize them
|
|
367
|
+
- If an issue has 0 extracted file paths AND no domain tag could be determined → serialize it with the immediately preceding wave (safest default)
|
|
368
|
+
- Add a note to the plan: "#{N} — low file-extraction confidence, serialized conservatively"
|
|
369
|
+
|
|
370
|
+
**Rationale**: The cost of a false-negative (two agents conflict → one fails with merge error, wasting the full agent run) far exceeds the cost of a false-positive (an issue waits one extra wave before starting). Always err toward serialization when uncertain.
|
|
371
|
+
|
|
372
|
+
#### Combining all layers
|
|
373
|
+
|
|
374
|
+
Build the final conflict graph by merging signals from all four layers:
|
|
375
|
+
|
|
376
|
+
| Signal | Strength | Action |
|
|
377
|
+
|--------|----------|--------|
|
|
378
|
+
| Layer 1: Same file | **Hard conflict** | Always serialize |
|
|
379
|
+
| Layer 2: Same small directory | **Probable conflict** | Serialize |
|
|
380
|
+
| Layer 2: Same broad directory + same domain | **Probable conflict** | Serialize |
|
|
381
|
+
| Layer 2: Same broad directory + different domain | **Possible conflict** | Parallelize (accept risk) |
|
|
382
|
+
| Layer 3: High-fan-in file touched | **Probable conflict** | Serialize with same-service issues |
|
|
383
|
+
| Layer 3: Shared model/init pattern | **Probable conflict** | Serialize |
|
|
384
|
+
| Layer 4: Low confidence + same domain | **Conservative** | Serialize |
|
|
385
|
+
| Layer 4: Low confidence + no domain | **Conservative** | Serialize with prior wave |
|
|
386
|
+
|
|
387
|
+
**This supplements, not replaces, the domain keyword estimation.** Domain tags still help with broad sequencing decisions. Multi-layer conflict detection catches the specific cases keywords miss (e.g., two issues that both modify files in `services/api/app/models/` where one is labeled SCRAPING and the other BILLING — Layer 2 catches this even though Layer 1 shows no direct file overlap).
|
|
388
|
+
|
|
389
|
+
### Step 3D: Build the execution plan
|
|
390
|
+
|
|
391
|
+
Organize issues into **waves** (groups that can run in parallel):
|
|
392
|
+
|
|
393
|
+
**Wave rules:**
|
|
394
|
+
- Investigation issues already ran in Wave 0 (Phase 2) — they are NOT included in these waves
|
|
395
|
+
- Issues with NO dependencies and NO file overlap → same wave (parallel)
|
|
396
|
+
- Issues that depend on other issues in the set → later wave (after dependency completes)
|
|
397
|
+
- **No artificial agent limit per wave** — spawn as many parallel agents as there are independent issues. The only constraint is file overlap and explicit dependencies.
|
|
398
|
+
- Issues that touch the **same files** must be in separate waves (sequential) to avoid merge conflicts
|
|
399
|
+
- If unsure about conflicts, err on the side of parallel — each agent works in its own worktree
|
|
400
|
+
|
|
401
|
+
**Example plan:**
|
|
402
|
+
```
|
|
403
|
+
Wave 0 (already done): #2644 (investigation) → spawned #2645, #2646, #2647
|
|
404
|
+
Wave 1 (parallel): #2633 (orphaned queues), #2636 (invalidation sub), #2645 (new finding), #2646 (new finding)
|
|
405
|
+
Wave 2 (after deps): #2634 (enable daemon — after #2633 fixes memory leak), #2647 (depends on #2645)
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Step 3E: Present the plan to the user
|
|
409
|
+
|
|
410
|
+
```
|
|
411
|
+
## Orchestration Plan
|
|
412
|
+
|
|
413
|
+
**Scope**: {milestone name / "N issues" / "fast-lane"}
|
|
414
|
+
**Total issues**: {count} ({investigation_count} investigations + {implementation_count} implementations)
|
|
415
|
+
**Estimated waves**: {wave_count} (Wave 0 = investigations, then implementation waves)
|
|
416
|
+
|
|
417
|
+
{IF investigations exist:}
|
|
418
|
+
### Wave 0 — Investigations (run first, may spawn new issues)
|
|
419
|
+
| # | Title | Expected Output |
|
|
420
|
+
|---|-------|----------------|
|
|
421
|
+
| #{INV1} | {title} | New issues → folded into subsequent waves |
|
|
422
|
+
|
|
423
|
+
### Implementation Waves (after investigations complete)
|
|
424
|
+
{END IF}
|
|
425
|
+
|
|
426
|
+
### Domain Distribution
|
|
427
|
+
| Domain | Issues | Notes |
|
|
428
|
+
|--------|--------|-------|
|
|
429
|
+
| SCRAPING | {N} | {High overlap risk / Independent targets} |
|
|
430
|
+
| FRONTEND | {N} | {Independent pages / Shared components} |
|
|
431
|
+
| BILLING | {N} | {Critical — prioritize in Wave 1} |
|
|
432
|
+
| DATABASE | {N} | {Sequential — migration order matters} |
|
|
433
|
+
| AUTH | {N} | {Critical — Wave 1} |
|
|
434
|
+
| INFRA | {N} | {Independent} |
|
|
435
|
+
| CORTEX | {N} | {Independent} |
|
|
436
|
+
|
|
437
|
+
(Omit rows with 0 issues.)
|
|
438
|
+
|
|
439
|
+
### Implementation Waves
|
|
440
|
+
|
|
441
|
+
| Wave | Issues | Strategy |
|
|
442
|
+
|------|--------|----------|
|
|
443
|
+
| 1 | #{A}, #{B}, #{C} | Parallel (no deps, different domains) |
|
|
444
|
+
| 2 | #{D} (after #{A}), #{E} | Parallel (D waits for A) |
|
|
445
|
+
| 3 | #{F} (after #{D}) | Sequential |
|
|
446
|
+
|
|
447
|
+
**Note**: Wave 0 investigations may create additional issues that will be automatically added to the implementation waves. The final wave plan will be confirmed after investigations complete.
|
|
448
|
+
|
|
449
|
+
**Excluded** (already in progress / ineligible):
|
|
450
|
+
- #{X} — {reason}
|
|
451
|
+
|
|
452
|
+
Proceed? (yes / adjust / pick specific issues)
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
**Wait for user confirmation before spawning agents.** This is the checkpoint — once agents launch, they run autonomously.
|
|
456
|
+
|
|
457
|
+
**After confirmation**: If Wave 0 exists, execute Phase 2B-E first. Then re-present the expanded plan (with newly spawned issues slotted into waves) for a quick confirmation before launching implementation waves.
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## Phase 4: Execute Waves
|
|
462
|
+
|
|
463
|
+
### Step 4A-pre: Capture staging baseline (MANDATORY before each wave)
|
|
464
|
+
|
|
465
|
+
**WHY THIS EXISTS**: Milestone-code-onto-staging contamination incidents (see issue #150) produce unexpected growth on the staging branch that is otherwise invisible until after a deploy. Capturing a line-count baseline before each wave and re-checking after allows early detection of any contamination by agents in that wave.
|
|
466
|
+
|
|
467
|
+
**When to run**: Before launching EVERY wave in batches that target `staging` (fast-lane or milestone→staging). Skip only for pure milestone-branch batches where `{PR_BASE}` is `milestone/*` and staging is not involved.
|
|
468
|
+
|
|
469
|
+
```bash
|
|
470
|
+
# Capture staging baseline before launching the wave
|
|
471
|
+
git fetch origin
|
|
472
|
+
STAGING_LINES_BEFORE=$(git diff --stat origin/main...origin/staging 2>/dev/null \
|
|
473
|
+
| tail -1 \
|
|
474
|
+
| grep -oP '\d+ insertion' \
|
|
475
|
+
| grep -oP '\d+' \
|
|
476
|
+
|| echo "0")
|
|
477
|
+
echo "Staging baseline before Wave {N}: ${STAGING_LINES_BEFORE} lines ahead of main"
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
Store `STAGING_LINES_BEFORE` per wave. After the wave completes (after Step 4C), run the integrity check:
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
# Check staging integrity after wave completes (run after Step 4C)
|
|
484
|
+
git fetch origin
|
|
485
|
+
STAGING_LINES_AFTER=$(git diff --stat origin/main...origin/staging 2>/dev/null \
|
|
486
|
+
| tail -1 \
|
|
487
|
+
| grep -oP '\d+ insertion' \
|
|
488
|
+
| grep -oP '\d+' \
|
|
489
|
+
|| echo "0")
|
|
490
|
+
STAGING_GROWTH=$((STAGING_LINES_AFTER - STAGING_LINES_BEFORE))
|
|
491
|
+
|
|
492
|
+
echo "Staging after Wave {N}: ${STAGING_LINES_AFTER} lines (+${STAGING_GROWTH} vs baseline)"
|
|
493
|
+
|
|
494
|
+
# Alert if growth exceeds expected delta
|
|
495
|
+
# Expected: only the lines from PRs merged in this wave
|
|
496
|
+
# Alert threshold: growth > 500 lines more than the sum of changed lines from wave PRs
|
|
497
|
+
# (Use 0 as threshold if no PRs merged — any growth is unexpected)
|
|
498
|
+
EXPECTED_DELTA={SUM_OF_PR_LINE_COUNTS_THIS_WAVE} # set from PR diffs collected in 4B
|
|
499
|
+
UNEXPECTED_GROWTH=$((STAGING_GROWTH - EXPECTED_DELTA))
|
|
500
|
+
if [ "$UNEXPECTED_GROWTH" -gt 500 ]; then
|
|
501
|
+
echo "ALERT: Staging grew by ${STAGING_GROWTH} lines (+${UNEXPECTED_GROWTH} beyond expected ${EXPECTED_DELTA})."
|
|
502
|
+
echo "This may indicate milestone-code contamination via agent merge commits."
|
|
503
|
+
echo "Review: git log --oneline --merges origin/main..origin/staging"
|
|
504
|
+
echo "Do NOT merge staging → main until the unexpected growth is investigated."
|
|
505
|
+
# Do NOT auto-stop — alert the user and let them decide
|
|
506
|
+
fi
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
If `UNEXPECTED_GROWTH > 500`, report the alert clearly before launching the next wave. The user confirms whether to continue.
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
### Step 4A: Launch a wave
|
|
514
|
+
|
|
515
|
+
**REMINDER: You MUST use the template below verbatim. Only fill in `{VARIABLES}`. Do NOT rewrite the agent prompt. Do NOT write custom implementation instructions. The agent MUST invoke `/work-on` via the Skill tool — this is the HARD RULE from the top of this file.**
|
|
516
|
+
|
|
517
|
+
For each issue in the current wave, spawn an Agent sub-agent that runs the full `/work-on` pipeline.
|
|
518
|
+
|
|
519
|
+
**One agent per issue.** Do NOT group multiple issues into a single agent. `/work-on` handles branching, labels, and PRs per-issue.
|
|
520
|
+
|
|
521
|
+
**Copy this template. Fill in variables. Do not modify the structure:**
|
|
522
|
+
|
|
523
|
+
```
|
|
524
|
+
Agent(
|
|
525
|
+
subagent_type="general-purpose",
|
|
526
|
+
model="sonnet",
|
|
527
|
+
description="Work on {PROJECT_PREFIX}#{NUMBER}",
|
|
528
|
+
run_in_background=true,
|
|
529
|
+
prompt="You are working on GitHub issue #{NUMBER} for the AlterLab ecosystem.
|
|
530
|
+
|
|
531
|
+
**Project**: {PROJECT_NAME}
|
|
532
|
+
**Repository**: {GH_REPO}
|
|
533
|
+
**Repo path**: {REPO_PATH}
|
|
534
|
+
|
|
535
|
+
**YOUR MISSION**: Invoke `/work-on` via the Skill tool and let it run to completion. `/work-on` is a self-contained routing loop that handles the ENTIRE pipeline: investigate → build (context → architect → implement → validate) → review (push → PR → /review-pr --auto-merge) → close (project board → trajectory log → worktree cleanup). Do NOT intervene, compensate, or manually close issues — `/work-on` handles everything including issue closure and label updates in its close phase.
|
|
536
|
+
|
|
537
|
+
**CRITICAL — DO NOT STOP EARLY**: /work-on runs as a multi-phase routing loop. Each phase (investigate, build, review, close) returns an intermediate result — these are NOT completion signals. You are NOT done until the issue reaches a terminal state: `workflow:merged`, `workflow:invalid`, or `needs-human`. If /work-on returns after only one phase (e.g., investigation), you MUST invoke it again immediately — it will re-read GitHub state and continue to the next phase. Keep invoking /work-on until it reaches a terminal state. Never output 'done' or stop after an intermediate result.
|
|
538
|
+
|
|
539
|
+
**HOW REVIEW FINDINGS WORK**: /review-pr may create GitHub issues (with `review-finding` label) for findings it discovers. These are NOT blockers — they are separate work items that will go through their own /work-on pipeline later. The original PR should ALWAYS merge after review. The only exception is build errors (code doesn't compile) — those must be fixed before merging.
|
|
540
|
+
|
|
541
|
+
**IMPORTANT RULES**:
|
|
542
|
+
- **MANDATORY**: You MUST use the Skill tool to invoke 'work-on' with args '{PROJECT_PREFIX}{NUMBER}'. Do NOT implement manually — /work-on handles the full pipeline including label state machine (workflow:investigating → workflow:building → workflow:in-review → workflow:merged), investigation reports, PR creation, and cleanup.
|
|
543
|
+
- For AlterLab issues: `Skill(skill='work-on', args='{NUMBER}')`
|
|
544
|
+
- For MCP issues: `Skill(skill='work-on', args='mcp:{NUMBER}')`
|
|
545
|
+
- For n8n issues: `Skill(skill='work-on', args='n8n:{NUMBER}')`
|
|
546
|
+
- NEVER bypass /work-on with manual git/gh commands — the label updates and structured comments are critical for tracking
|
|
547
|
+
- NEVER target `main` for AlterLab PRs. Use `staging` for fast-lane issues, or `milestone/{slug}` for milestone issues.
|
|
548
|
+
- Satellite repos (MCP, n8n) have no staging branch — fast-lane PRs go to `main` for those.
|
|
549
|
+
- If the issue is INVALID after investigation, close it with a comment explaining why
|
|
550
|
+
- If you hit merge conflicts or blockers, post a comment on the issue and STOP — do not force anything
|
|
551
|
+
- Do not interact with the user — you are running autonomously in the background
|
|
552
|
+
- **NEVER ask the user questions** — you are a background agent. If review finds issues, auto-fix simple ones and proceed. For complex findings, merge anyway and create follow-up issues.
|
|
553
|
+
|
|
554
|
+
**LABEL-STATE LOOP CONTRACT — enforce after EVERY Skill return**:
|
|
555
|
+
After EVERY `Skill(skill='work-on', ...)` call returns, immediately check the issue's current workflow label:
|
|
556
|
+
```bash
|
|
557
|
+
gh issue view {NUMBER} -R {GH_REPO} --json labels --jq '[.labels[].name | select(startswith("workflow:"))]'
|
|
558
|
+
```
|
|
559
|
+
**Terminal labels** (only these allow you to stop): `workflow:merged`, `workflow:invalid`
|
|
560
|
+
**Terminal condition also**: `needs-human` label present OR issue state is `closed`
|
|
561
|
+
If the label is NOT terminal (e.g., `workflow:investigating`, `workflow:ready-to-build`, `workflow:building`, `workflow:in-review`), invoke `Skill(skill='work-on', args='{NUMBER}')` again immediately. The `/work-on` skill will re-read GitHub state and advance to the next phase. Do NOT output a summary, do NOT pause, do NOT ask for confirmation — just invoke it again.
|
|
562
|
+
|
|
563
|
+
**CRITICAL — SOURCE BRANCH DETECTION**:
|
|
564
|
+
- If the issue has the `review-finding` label, read the issue body for `**Code branch**: \`{branch}\``
|
|
565
|
+
- If found, that is the SOURCE_BRANCH — the code ONLY exists on that branch (e.g., `staging`), NOT on `origin/main`
|
|
566
|
+
- Investigation MUST use `git show origin/{SOURCE_BRANCH}:{filepath}` to verify the code exists
|
|
567
|
+
- Worktree MUST branch from `origin/{SOURCE_BRANCH}`, NOT `origin/main`
|
|
568
|
+
- PR target is `{SOURCE_BRANCH}` (the fix goes back to where the code lives)
|
|
569
|
+
|
|
570
|
+
**LANE**: {LANE} (PR target: {PR_BASE})
|
|
571
|
+
**Issue title**: {ISSUE_TITLE}
|
|
572
|
+
{GIST_CONTEXT}
|
|
573
|
+
"
|
|
574
|
+
)
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
**`{GIST_CONTEXT}` generation**: For each issue in the wave, check if it was spawned by an investigation that has a Knowledge Gist (from Step 2C.5). If so, include the Gist URL(s) in the agent prompt:
|
|
578
|
+
|
|
579
|
+
```bash
|
|
580
|
+
# Build GIST_CONTEXT for an issue
|
|
581
|
+
GIST_CONTEXT=""
|
|
582
|
+
PARENT_INV=$(gh issue view {NUMBER} -R {GH_REPO} --json body --jq '.body' \
|
|
583
|
+
| grep -oP '(?i)parent[: ]*#\K\d+|spawned from[: ]*#\K\d+' | head -1)
|
|
584
|
+
|
|
585
|
+
if [ -n "$PARENT_INV" ] && [ -n "${INVESTIGATION_GISTS[$PARENT_INV]:-}" ]; then
|
|
586
|
+
GIST_CONTEXT="
|
|
587
|
+
**CONTEXT FROM PRIOR INVESTIGATION**: Investigation #${PARENT_INV} produced Knowledge Gist(s) with findings relevant to this issue:
|
|
588
|
+
$(echo "${INVESTIGATION_GISTS[$PARENT_INV]}" | while IFS= read -r url; do echo "- ${url}"; done)
|
|
589
|
+
Fetch the Gist content during the context-gathering phase for implementation guidance."
|
|
590
|
+
fi
|
|
591
|
+
|
|
592
|
+
# Include milestone index URL if available (from Step 2C.5)
|
|
593
|
+
if [ -n "$MILESTONE_INDEX_URL" ]; then
|
|
594
|
+
GIST_CONTEXT="${GIST_CONTEXT}
|
|
595
|
+
|
|
596
|
+
**MILESTONE KNOWLEDGE INDEX**: All investigation findings for this milestone are aggregated in a single index Gist:
|
|
597
|
+
- ${MILESTONE_INDEX_URL}
|
|
598
|
+
The context-gathering phase can fetch this index to discover all investigation Gists for the milestone."
|
|
599
|
+
fi
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
If `GIST_CONTEXT` is empty (no parent investigation or milestone index found), the variable resolves to a blank line in the template — no impact on the agent prompt. <!-- Updated: forge#341 -->
|
|
603
|
+
|
|
604
|
+
**Launch all agents in the current wave simultaneously** by putting multiple Agent tool calls in a single message. Use `run_in_background=true` so they execute in parallel.
|
|
605
|
+
|
|
606
|
+
### Step 4B: Monitor wave completion
|
|
607
|
+
|
|
608
|
+
You will be automatically notified when each background agent completes. **Do NOT use `sleep` loops to poll for completion.** Instead, wait for the automatic notification. When you receive a notification that an agent completed, immediately process it.
|
|
609
|
+
|
|
610
|
+
**CRITICAL — Stall detection and recovery**: Background agents sometimes stop mid-pipeline (`stop_reason=end_turn`) after completing a sub-phase (e.g., investigation completes but build never starts). This causes the agent to "complete" from the Agent tool's perspective even though the `/work-on` pipeline is only partially done. When you receive a completion notification:
|
|
611
|
+
|
|
612
|
+
1. **Check if the agent completed the FULL pipeline** — not just one phase:
|
|
613
|
+
```bash
|
|
614
|
+
# Check final workflow state — only workflow:merged or workflow:invalid means truly done
|
|
615
|
+
FINAL_STATE=$(gh issue view $NUM -R {GH_REPO} --json labels,state --jq '{state: .state, workflow: [.labels[].name | select(startswith("workflow:"))]}')
|
|
616
|
+
echo "#{NUM}: $FINAL_STATE"
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
2. **If the issue is NOT in a terminal state** (`workflow:merged`, `workflow:invalid`, or `needs-human`), the agent stalled mid-pipeline. **Resume it immediately**:
|
|
620
|
+
```
|
|
621
|
+
Agent(
|
|
622
|
+
resume="{AGENT_ID}",
|
|
623
|
+
description="Resume #{NUMBER} pipeline",
|
|
624
|
+
run_in_background=true,
|
|
625
|
+
prompt="The previous /work-on invocation stopped before completing the full pipeline. The issue is currently at {CURRENT_WORKFLOW_STATE}. Continue — invoke Skill(skill='work-on', args='{NUMBER}') to resume the routing loop from the current state. /work-on will re-read GitHub state and pick up where it left off."
|
|
626
|
+
)
|
|
627
|
+
```
|
|
628
|
+
**Resume ALL stalled agents in a single message** (parallel resume). Do not wait between resumes.
|
|
629
|
+
|
|
630
|
+
3. **Track resume cycles per agent.** If an agent has been resumed 3+ times and still hasn't reached a terminal state, report it as a failure — do not resume again.
|
|
631
|
+
|
|
632
|
+
4. **Record completed results**: Success (PR merged), Invalid (issue closed), Blocked (needs human), or Error
|
|
633
|
+
|
|
634
|
+
5. **Verify pipeline compliance** — for each truly completed issue, check that the agent used `/work-on`:
|
|
635
|
+
```bash
|
|
636
|
+
LABELS=$(gh issue view $NUM -R {GH_REPO} --json labels --jq '[.labels[].name | select(startswith("workflow:"))] | length')
|
|
637
|
+
COMMENTS=$(gh api repos/{GH_REPO}/issues/${NUM}/comments --jq '[.[] | select(.body | test("FORGE:INVESTIGATOR|FORGE:BUILDER"))] | length')
|
|
638
|
+
if [ "$LABELS" -eq 0 ] || [ "$COMMENTS" -eq 0 ]; then
|
|
639
|
+
echo "PIPELINE FAILURE: #{NUM} — agent bypassed /work-on (no labels or structured comments)"
|
|
640
|
+
fi
|
|
641
|
+
```
|
|
642
|
+
If an agent bypassed the pipeline, report it as a **failure** regardless of whether a PR exists.
|
|
643
|
+
|
|
644
|
+
6. **Post a brief status update** to the user after each agent reaches terminal state:
|
|
645
|
+
```
|
|
646
|
+
✓ #{NUMBER} — {title} → PR #{PR} merged to {target}
|
|
647
|
+
✗ #{NUMBER} — {title} → {reason for failure}
|
|
648
|
+
⚠ #{NUMBER} — {title} → PIPELINE BYPASS (no /work-on — PR invalid)
|
|
649
|
+
⏳ Wave 1: 2/3 complete (1 resumed after stall)...
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
**Anti-pattern — DO NOT DO THIS:**
|
|
653
|
+
- `sleep 60/120/180/300` loops to check status — you will be notified automatically
|
|
654
|
+
- Spawning separate "progress check" agents — they waste tokens and add noise
|
|
655
|
+
- Reading agent JSONL output files to check progress — use GitHub labels as the source of truth
|
|
656
|
+
- Polling the same status check repeatedly on a timer
|
|
657
|
+
|
|
658
|
+
### Step 4C: Collect review-finding issues from completed wave
|
|
659
|
+
|
|
660
|
+
When ALL agents in the current wave have completed, check if any `/work-on` runs spawned review-finding issues during their review phase. These are new work items that should be folded into the remaining waves.
|
|
661
|
+
|
|
662
|
+
```bash
|
|
663
|
+
# Method 1: Read TRAJECTORY comments from completed issues for "Finding issues" row
|
|
664
|
+
for NUM in {completed_issue_numbers_this_wave}; do
|
|
665
|
+
gh api repos/{GH_REPO}/issues/${NUM}/comments \
|
|
666
|
+
--jq '.[] | select(.body | contains("FORGE:TRAJECTORY")) | .body' 2>/dev/null \
|
|
667
|
+
| grep -oP 'Finding issues\s*\|\s*#?\K\d+[^|]*' | grep -oP '\d+' | sort -u
|
|
668
|
+
done
|
|
669
|
+
|
|
670
|
+
# Method 2 (fallback): Check for recently created review-finding issues that reference PRs from this wave
|
|
671
|
+
gh issue list -R {GH_REPO} --state open --label "review-finding" --limit 20 \
|
|
672
|
+
--json number,title,body,createdAt \
|
|
673
|
+
--jq "[.[] | select(.createdAt > \"$(date -u -d '2 hours ago' +%Y-%m-%dT%H:%M:%SZ)\")]"
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
**If review-finding issues were spawned:**
|
|
677
|
+
|
|
678
|
+
**Cascade control (MANDATORY — run before folding findings into waves):**
|
|
679
|
+
|
|
680
|
+
For each spawned finding, determine whether it should be **executed** or **deferred**:
|
|
681
|
+
|
|
682
|
+
**Evaluation order** (first matching rule wins):
|
|
683
|
+
1. **Generation ≥ 2** (always defer, even for P1/P2): Finding was spawned by an issue that was itself a review-finding. Check the source issue's labels for `review-finding` — if the source has that label, the new finding is generation 2. Always defer. Rationale: gen-2+ cascade is theoretically unbounded — cap it here.
|
|
684
|
+
2. **Priority override** (P1 or P2 → always execute): If the finding is labeled P1 or P2, skip all remaining heuristics and execute. Rationale: high-priority findings must never be suppressed by keyword matching.
|
|
685
|
+
3. **Comment/typo heuristic** (P3 and below only): Finding title contains the word "comment" or "typo" (case-insensitive). These are 1-line cosmetic fixes that do not block other work.
|
|
686
|
+
4. **P3 + same-file overlap**: Finding is labeled `P3` AND the file it targets overlaps with ANY file already in the current or remaining batch waves. Rationale: same-file P3 findings serialize the entire remaining batch — one finding per original issue doubles wall-clock time with no proportional value.
|
|
687
|
+
|
|
688
|
+
**Defer** (do NOT add to wave queue) if rules 1, 3, or 4 match.
|
|
689
|
+
|
|
690
|
+
**Execute** (add to wave queue) if:
|
|
691
|
+
- Rule 2 matches (P1 or P2)
|
|
692
|
+
- None of the defer rules matched (generation 1, P3 with no file overlap, not a keyword match)
|
|
693
|
+
|
|
694
|
+
**Before running the loop, build the batch file list (MANDATORY for Heuristic 3):**
|
|
695
|
+
|
|
696
|
+
Collect all file paths from every issue in the current batch — both completed waves and remaining queued waves. This produces `ALL_BATCH_FILES`, a newline-separated list of file paths used by Heuristic 3 to test same-file overlap.
|
|
697
|
+
|
|
698
|
+
```bash
|
|
699
|
+
# Build ALL_BATCH_FILES: collect file paths from ALL batch issues (completed + queued)
|
|
700
|
+
# Use the same extraction pattern as Step 3C Layer 1
|
|
701
|
+
ALL_BATCH_FILES=""
|
|
702
|
+
for NUM in {all_batch_issue_numbers}; do
|
|
703
|
+
# Try INVESTIGATOR comment first (most reliable source of affected files)
|
|
704
|
+
FILES=$(gh api repos/{GH_REPO}/issues/${NUM}/comments \
|
|
705
|
+
--jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body' 2>/dev/null \
|
|
706
|
+
| grep -oP '`[^`]*\.(py|tsx?|jsx?|sql|json|ya?ml|sh|md)`' | tr -d '`' | sort -u)
|
|
707
|
+
# Fall back to issue body if no investigator comment
|
|
708
|
+
if [ -z "$FILES" ]; then
|
|
709
|
+
FILES=$(gh issue view $NUM -R {GH_REPO} --json body --jq '.body' \
|
|
710
|
+
| grep -oP '`[^`]*\.(py|tsx?|jsx?|sql|json|ya?ml|sh|md)`' | tr -d '`' | sort -u)
|
|
711
|
+
fi
|
|
712
|
+
ALL_BATCH_FILES=$(printf '%s\n%s' "$ALL_BATCH_FILES" "$FILES")
|
|
713
|
+
done
|
|
714
|
+
ALL_BATCH_FILES=$(echo "$ALL_BATCH_FILES" | sort -u | grep -v '^$')
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
```bash
|
|
718
|
+
# For each finding, check its priority label and generation
|
|
719
|
+
for FINDING_NUM in {spawned_finding_numbers}; do
|
|
720
|
+
FINDING_DATA=$(gh issue view $FINDING_NUM -R {GH_REPO} --json labels,title,body \
|
|
721
|
+
--jq '{labels: [.labels[].name], title: .title, body: .body}')
|
|
722
|
+
|
|
723
|
+
PRIORITY=$(echo "$FINDING_DATA" | jq -r '.labels[] | select(startswith("P")) | .' | head -1)
|
|
724
|
+
TITLE=$(echo "$FINDING_DATA" | jq -r '.title')
|
|
725
|
+
|
|
726
|
+
# Heuristic 1: Generation check — source issue has review-finding label (always defer, even for P1/P2)
|
|
727
|
+
if SOURCE_NUM=$(echo "$FINDING_DATA" | jq -r '.body' | grep -oP '(?i)spawned from issue #\K\d+|source issue[: #]+\K\d+' | head -1) && \
|
|
728
|
+
[ -n "$SOURCE_NUM" ] && \
|
|
729
|
+
gh issue view $SOURCE_NUM -R {GH_REPO} --json labels --jq '[.labels[].name]' 2>/dev/null | grep -q "review-finding"; then
|
|
730
|
+
DEFER=true; DEFER_REASON="generation >= 2 (source #${SOURCE_NUM} is also a review-finding)"
|
|
731
|
+
# Priority override: P1 or P2 always execute — skip remaining heuristics
|
|
732
|
+
elif [ "$PRIORITY" = "P1" ] || [ "$PRIORITY" = "P2" ]; then
|
|
733
|
+
DEFER=false
|
|
734
|
+
# Heuristic 2: Comment/typo keyword (only applies to P3 and below)
|
|
735
|
+
elif echo "$TITLE" | grep -qi "comment\|typo"; then
|
|
736
|
+
DEFER=true; DEFER_REASON="comment/typo heuristic"
|
|
737
|
+
# Heuristic 3: P3 + same-file overlap
|
|
738
|
+
elif [ "$PRIORITY" = "P3" ]; then
|
|
739
|
+
# Extract file target from finding body (look for code block or backtick path)
|
|
740
|
+
FINDING_FILE=$(echo "$FINDING_DATA" | jq -r '.body' | grep -oP '`[^\`]+\.(py|ts|tsx|sh|md)`' | head -1 | tr -d '`')
|
|
741
|
+
if [ -n "$FINDING_FILE" ] && echo "$ALL_BATCH_FILES" | grep -qF "$FINDING_FILE"; then
|
|
742
|
+
DEFER=true; DEFER_REASON="P3 + same file as batch: $FINDING_FILE"
|
|
743
|
+
else
|
|
744
|
+
DEFER=false
|
|
745
|
+
fi
|
|
746
|
+
else
|
|
747
|
+
DEFER=false
|
|
748
|
+
fi
|
|
749
|
+
|
|
750
|
+
if [ "$DEFER" = "true" ]; then
|
|
751
|
+
DEFERRED_FINDINGS+=($FINDING_NUM)
|
|
752
|
+
echo "Deferred #${FINDING_NUM}: $DEFER_REASON"
|
|
753
|
+
else
|
|
754
|
+
QUEUED_FINDINGS+=($FINDING_NUM)
|
|
755
|
+
fi
|
|
756
|
+
done
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
**For queued (non-deferred) findings:**
|
|
760
|
+
|
|
761
|
+
1. **Add them to the remaining wave plan.** They are implementation issues — same as issues spawned by investigations in Phase 2.
|
|
762
|
+
2. **Respect source branch context.** Review-finding issues have `**Code branch**: \`{branch}\`` in their body — the `/work-on` agent will read this and branch from the right origin. No special handling needed from the orchestrator.
|
|
763
|
+
3. **Report to user:**
|
|
764
|
+
```
|
|
765
|
+
Wave {N} review spawned {count} new finding issues: #{A}, #{B}
|
|
766
|
+
Queued for execution: #{A}, #{B}
|
|
767
|
+
Deferred (cascade control): #{C} (P3 same-file), #{D} (comment heuristic)
|
|
768
|
+
Adding queued findings to Wave {N+1} (or new wave if no remaining waves).
|
|
769
|
+
```
|
|
770
|
+
4. **Re-run file-overlap detection** (Step 3C) on the expanded issue set — finding issues may conflict with planned issues that touch the same files.
|
|
771
|
+
|
|
772
|
+
**For deferred findings:**
|
|
773
|
+
|
|
774
|
+
They remain open in GitHub — they will be picked up by future `/orchestrate` or `/work-on` runs. Log them in the final batch summary under "deferred" so they are visible. Do NOT close or label them — leave them for the next pipeline pass.
|
|
775
|
+
|
|
776
|
+
**If no review-finding issues were spawned:** Continue to next wave normally.
|
|
777
|
+
|
|
778
|
+
### Step 4D: Milestone integration build gate (MANDATORY between waves)
|
|
779
|
+
|
|
780
|
+
**WHY THIS EXISTS**: Session Intelligence milestone shipped 116 PRs across multiple waves with zero integration testing. Each PR built in isolation — type errors from cross-PR interactions (wrong prop types, missing components, incompatible interfaces) were invisible until the milestone→staging merge broke the build with 4 distinct errors. This gate catches those failures early.
|
|
781
|
+
|
|
782
|
+
**When to run**: After each wave completes, IF the batch targets a milestone branch AND any `.tsx`/`.ts` files were changed by agents in the completed wave.
|
|
783
|
+
|
|
784
|
+
```bash
|
|
785
|
+
# Check if this is a milestone batch with TypeScript changes
|
|
786
|
+
MILESTONE_BRANCH="milestone/{milestone_slug}"
|
|
787
|
+
TS_CHANGED=$(git diff origin/{DEFAULT_BRANCH}...origin/${MILESTONE_BRANCH} --name-only | grep -E '\.(tsx?|jsx?)$' | head -1)
|
|
788
|
+
|
|
789
|
+
if [ -n "$TS_CHANGED" ]; then
|
|
790
|
+
echo "=== Integration Build Gate (TypeScript): Wave {N} ==="
|
|
791
|
+
cd {REPO_PATH}
|
|
792
|
+
git fetch origin ${MILESTONE_BRANCH}
|
|
793
|
+
git checkout origin/${MILESTONE_BRANCH} --detach 2>/dev/null
|
|
794
|
+
cd web && npx tsc --noEmit 2>&1 | head -30
|
|
795
|
+
TSC_EXIT=$?
|
|
796
|
+
if [ "$TSC_EXIT" -eq 0 ]; then
|
|
797
|
+
npx next build 2>&1 | tail -30
|
|
798
|
+
BUILD_EXIT=$?
|
|
799
|
+
fi
|
|
800
|
+
cd .. && git checkout - 2>/dev/null
|
|
801
|
+
|
|
802
|
+
if [ "$TSC_EXIT" -ne 0 ]; then
|
|
803
|
+
echo "BLOCKING: TypeScript errors on ${MILESTONE_BRANCH} after Wave {N}."
|
|
804
|
+
echo "Fix type errors before starting next wave."
|
|
805
|
+
elif [ "${BUILD_EXIT:-0}" -ne 0 ]; then
|
|
806
|
+
echo "BLOCKING: next build failed on ${MILESTONE_BRANCH} after Wave {N}."
|
|
807
|
+
echo "SSG prerender or build errors — fix before starting next wave."
|
|
808
|
+
fi
|
|
809
|
+
fi
|
|
810
|
+
|
|
811
|
+
# Python format check
|
|
812
|
+
PY_CHANGED=$(git diff origin/{DEFAULT_BRANCH}...origin/${MILESTONE_BRANCH} --name-only | grep -E '\.py$' | head -1)
|
|
813
|
+
if [ -n "$PY_CHANGED" ]; then
|
|
814
|
+
echo "=== Integration Build Gate (Python): Wave {N} ==="
|
|
815
|
+
cd {REPO_PATH}
|
|
816
|
+
git checkout origin/${MILESTONE_BRANCH} --detach 2>/dev/null
|
|
817
|
+
cd services/api && poetry run black --check app/ 2>&1 | tail -10
|
|
818
|
+
BLACK_EXIT=$?
|
|
819
|
+
poetry run isort --check app/ 2>&1 | tail -10
|
|
820
|
+
ISORT_EXIT=$?
|
|
821
|
+
cd ../.. && git checkout - 2>/dev/null
|
|
822
|
+
|
|
823
|
+
if [ "$BLACK_EXIT" -ne 0 ] || [ "$ISORT_EXIT" -ne 0 ]; then
|
|
824
|
+
echo "WARNING: Python formatting issues on ${MILESTONE_BRANCH} after Wave {N}."
|
|
825
|
+
echo "Not blocking but should be fixed before milestone→staging."
|
|
826
|
+
fi
|
|
827
|
+
fi
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
**If the gate fails**: Report the errors to the user. Do NOT proceed to the next wave. The accumulated milestone branch has integration errors that will only get worse with more PRs on top. `next build` failures are BLOCKING (not just `tsc`) — SSG prerender crashes are invisible to type checking.
|
|
831
|
+
|
|
832
|
+
### Step 4E: Advance to next wave
|
|
833
|
+
|
|
834
|
+
When wave results are processed, the integration gate passes (or is not applicable), and any new finding issues are folded in:
|
|
835
|
+
|
|
836
|
+
1. Check if any failures in the current wave block the next wave (dependency failures)
|
|
837
|
+
2. If a dependency failed, skip dependent issues in the next wave and report them as "skipped — dependency #{X} failed"
|
|
838
|
+
3. Launch the next wave (same process as Step 4A)
|
|
839
|
+
|
|
840
|
+
### Step 4F: Handle individual agent failures
|
|
841
|
+
|
|
842
|
+
If an agent reports failure or error:
|
|
843
|
+
- **Merge conflict**: Report to user, mark issue as needing human attention
|
|
844
|
+
- **Invalid issue**: Already handled by the agent (closed with comment) — just report it
|
|
845
|
+
- **Build/test failure**: Report the error, suggest manual intervention
|
|
846
|
+
- **Agent timeout**: Report which issue timed out, suggest re-running with `/work-on #{N}`
|
|
847
|
+
|
|
848
|
+
**Do NOT retry failed agents automatically.** Report the failure and let the user decide.
|
|
849
|
+
|
|
850
|
+
---
|
|
851
|
+
|
|
852
|
+
## Phase 5: Post-Batch Cleanup
|
|
853
|
+
|
|
854
|
+
**This phase is MANDATORY after every orchestration batch.** It prevents the rot that accumulates when multiple agents merge PRs in parallel — stale labels, orphaned worktrees, unclosed issues.
|
|
855
|
+
|
|
856
|
+
### Step 5A: Run cleanup sweep
|
|
857
|
+
|
|
858
|
+
Invoke the `/cleanup` skill with `all` to sweep everything:
|
|
859
|
+
|
|
860
|
+
```
|
|
861
|
+
Skill(skill="cleanup", args="all")
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
This will:
|
|
865
|
+
- Fix stale workflow labels on any issues the agents left behind
|
|
866
|
+
- Close orphaned open issues whose PRs were merged (common when merging to `staging`)
|
|
867
|
+
- Remove worktrees created by agents in this batch
|
|
868
|
+
- Delete local/remote branches for merged PRs
|
|
869
|
+
- Report milestones that hit 0 open issues — these are ready for `/milestone ship` (staging review + merge). Do NOT close them; closure happens after code reaches staging.
|
|
870
|
+
- Sync Project board state
|
|
871
|
+
|
|
872
|
+
### Step 5B: Run agent audit
|
|
873
|
+
|
|
874
|
+
Invoke `/audit-agents` on this session to measure pipeline efficiency:
|
|
875
|
+
|
|
876
|
+
```
|
|
877
|
+
Skill(skill="audit-agents", args="latest")
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
Include the audit summary in the final report (Phase 6). Key metrics to surface:
|
|
881
|
+
- **Avg idle%** — percentage of time agents spent stalled vs working
|
|
882
|
+
- **Resume cycles** — how many times agents had to be resumed
|
|
883
|
+
- **Stall boundaries** — which phase transitions cause the most stalls
|
|
884
|
+
|
|
885
|
+
### Step 5C: Report cleanup results
|
|
886
|
+
|
|
887
|
+
Include the cleanup summary in the final report (Phase 6). If cleanup found problems, call them out — they indicate agent pipeline failures that may need investigation.
|
|
888
|
+
|
|
889
|
+
---
|
|
890
|
+
|
|
891
|
+
## Phase 6: Consolidated Report
|
|
892
|
+
|
|
893
|
+
After ALL waves AND cleanup complete, present a final summary.
|
|
894
|
+
|
|
895
|
+
### Step 6A: Collect trajectory data
|
|
896
|
+
|
|
897
|
+
```bash
|
|
898
|
+
for NUM in {all_completed_issue_numbers}; do
|
|
899
|
+
gh api repos/{GH_REPO}/issues/${NUM}/comments \
|
|
900
|
+
--jq '.[] | select(.body | contains("<!-- FORGE:TRAJECTORY -->")) | .body' 2>/dev/null
|
|
901
|
+
done
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
Aggregate into the batch-level analytics for Step 6B.
|
|
905
|
+
|
|
906
|
+
### Step 6B: Present consolidated report
|
|
907
|
+
|
|
908
|
+
```
|
|
909
|
+
## Orchestration Complete
|
|
910
|
+
|
|
911
|
+
**Scope**: {milestone / issue list}
|
|
912
|
+
**Duration**: {approximate time}
|
|
913
|
+
|
|
914
|
+
### Wave 0: Investigations
|
|
915
|
+
{IF investigations ran:}
|
|
916
|
+
| # | Investigation | Issues Created | Result |
|
|
917
|
+
|---|-------------|---------------|--------|
|
|
918
|
+
| #{INV1} | {title} | #{N1}, #{N2}, #{N3} | ✓ Closed |
|
|
919
|
+
{ELSE: "No investigations in this batch."}
|
|
920
|
+
|
|
921
|
+
### Implementation Results
|
|
922
|
+
|
|
923
|
+
| # | Issue | Source | Result | PR | Target |
|
|
924
|
+
|---|-------|--------|--------|----|--------|
|
|
925
|
+
| #{A} | {title} | original | ✓ Merged | #{PR} | staging |
|
|
926
|
+
| #{B} | {title} | original | ✓ Merged | #{PR} | milestone/x |
|
|
927
|
+
| #{N1} | {title} | from #{INV1} | ✓ Merged | #{PR} | staging |
|
|
928
|
+
| #{C} | {title} | original | ✗ Invalid | — | — |
|
|
929
|
+
| #{D} | {title} | original | ⚠ Blocked | — | — |
|
|
930
|
+
| #{E} | {title} | original | ⏭ Skipped (dep) | — | — |
|
|
931
|
+
|
|
932
|
+
### Review-Spawned Issues
|
|
933
|
+
|
|
934
|
+
{IF review findings were created during any wave:}
|
|
935
|
+
| # | Finding | Source Issue | Source PR | Status |
|
|
936
|
+
|---|---------|-------------|-----------|--------|
|
|
937
|
+
| #{F1} | {title} | #{A} | PR #{PR} | ✓ Merged (wave {N}) / ⏳ Open (deferred) |
|
|
938
|
+
|
|
939
|
+
{ELSE: "No review findings created during this batch."}
|
|
940
|
+
|
|
941
|
+
### Summary
|
|
942
|
+
- **Investigations**: {N} completed, spawned {M} new issues
|
|
943
|
+
- **Review findings**: {N} spawned, {M} resolved in-batch, {K} deferred
|
|
944
|
+
- **Succeeded**: {N} issues resolved (implementation)
|
|
945
|
+
- **Failed**: {N} issues need attention
|
|
946
|
+
- **Skipped**: {N} issues (dependency failures)
|
|
947
|
+
|
|
948
|
+
### Post-Batch Cleanup
|
|
949
|
+
- Labels fixed: {N}
|
|
950
|
+
- Orphaned issues closed: {N}
|
|
951
|
+
- Worktrees removed: {N}
|
|
952
|
+
- Branches pruned: {N}
|
|
953
|
+
- Milestones closed: {N}
|
|
954
|
+
|
|
955
|
+
### Agent Efficiency (from /audit-agents)
|
|
956
|
+
|
|
957
|
+
| Agent | Issue | Total | Active | Idle% | Resumes | Stall Points |
|
|
958
|
+
|-------|-------|-------|--------|-------|---------|--------------|
|
|
959
|
+
{per-agent rows from audit}
|
|
960
|
+
|
|
961
|
+
**Wave efficiency**: {avg_idle_pct}% idle time
|
|
962
|
+
**Total resume cycles**: {sum_resumes} across {agent_count} agents
|
|
963
|
+
**Clean agents** (no stalls): {clean_count}/{agent_count}
|
|
964
|
+
|
|
965
|
+
### Batch Trajectory Analytics
|
|
966
|
+
|
|
967
|
+
| Metric | Value |
|
|
968
|
+
|--------|-------|
|
|
969
|
+
| Issues attempted | {N} |
|
|
970
|
+
| Investigation invalidation rate | {N_invalid}/{N_investigated} ({%}) |
|
|
971
|
+
| Contracts posted | {N} |
|
|
972
|
+
| Contract→code divergences | {N} (agents that updated contract mid-build) |
|
|
973
|
+
| Review findings created | {N_total} |
|
|
974
|
+
| Findings after synthesis | {N} (deduplicated/arbitrated) |
|
|
975
|
+
| Findings validated | {N} |
|
|
976
|
+
| False positives | {N} ({%}) |
|
|
977
|
+
| Anomalies flagged | {N} |
|
|
978
|
+
|
|
979
|
+
**Domain breakdown**: {N} scraping, {N} frontend, {N} billing, ...
|
|
980
|
+
**Routing**: {N} fast-lane, {N} feature-lane
|
|
981
|
+
|
|
982
|
+
**Systematic issues** (flag if detected):
|
|
983
|
+
- False positive rate > 30% → review agents may need tuning
|
|
984
|
+
- Invalidation rate < 10% or > 35% → investigation calibration off
|
|
985
|
+
- Same-domain merge conflicts in 2+ waves → domain sequencing too aggressive
|
|
986
|
+
- Contract divergences > 20% → investigation quality may need improvement
|
|
987
|
+
- **Idle% > 50%** → agents stalling at phase boundaries; check work-on routing loop
|
|
988
|
+
- **Avg resumes > 1** → orchestrator having to compensate for agent stops
|
|
989
|
+
|
|
990
|
+
### Next Steps
|
|
991
|
+
{If milestone and all issues done: "Milestone ready to ship. Run `/milestone ship {slug}` when ready. The ship command includes a pre-merge hunk-loss audit (Step 2.5) that detects staging-only hunks in milestone-modified files and rebases the milestone branch to absorb them before creating the PR — protecting against squash-merge regressions."}
|
|
992
|
+
{If some failed: "Issues #{X}, #{Y} need manual attention. Re-run with `/work-on #{X}` after resolving blockers."}
|
|
993
|
+
{If fast-lane: "All fixes merged to staging. Merge staging → main via GitHub web UI when ready to deploy."}
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
---
|
|
997
|
+
|
|
998
|
+
## Safety Rules
|
|
999
|
+
|
|
1000
|
+
1. **Every agent MUST invoke `/work-on` via the Skill tool.** No custom prompts. No manual implementation. Copy the Phase 4A template, fill in variables, done. (See HARD RULES at top of file.)
|
|
1001
|
+
2. **NEVER merge anything to `main`** — agents merge to `staging` or `milestone/{slug}` only
|
|
1002
|
+
3. **No artificial concurrency limit** — spawn as many agents as there are independent issues. Only file overlap and dependencies require sequencing.
|
|
1003
|
+
4. **Always confirm with user before launching** — Step 3E is the mandatory checkpoint
|
|
1004
|
+
5. **No retries** — if an agent fails, report it and move on
|
|
1005
|
+
6. **Respect existing work** — skip issues already being worked on (`workflow:building`, `workflow:in-review`)
|
|
1006
|
+
7. **Dependency failures cascade** — if A fails and B depends on A, B is skipped (not attempted)
|
|
1007
|
+
8. **Always run post-batch cleanup** — Phase 5 is mandatory. Never skip `/cleanup all` after orchestration.
|
|
1008
|
+
9. **NEVER close/skip issues as duplicates** — only `/work-on` investigation agents can make that call after examining the actual code. The orchestrator delegates, it does not adjudicate.
|
|
1009
|
+
10. **Post-wave verification** — after each wave, check that every completed issue has `workflow:*` labels and structured comments. If an agent bypassed `/work-on`, report it as a pipeline failure.
|
|
1010
|
+
|
|
1011
|
+
---
|
|
1012
|
+
|
|
1013
|
+
## Examples
|
|
1014
|
+
|
|
1015
|
+
### "orchestrate milestone api-expansion"
|
|
1016
|
+
→ Fetches all open issues in "API Expansion v1" milestone
|
|
1017
|
+
→ Analyzes deps (#1526 → #1527 → #1528 → #1529, #1530 independent)
|
|
1018
|
+
→ Plans 3 waves, confirms with user, executes
|
|
1019
|
+
|
|
1020
|
+
### "orchestrate #1533 #1250"
|
|
1021
|
+
→ Fetches those 2 issues, no deps between them
|
|
1022
|
+
→ Single wave, both parallel, confirms, executes
|
|
1023
|
+
|
|
1024
|
+
### "orchestrate next 5"
|
|
1025
|
+
→ Gets top 5 priority issues, checks deps
|
|
1026
|
+
→ Plans waves, confirms, executes
|
|
1027
|
+
|
|
1028
|
+
### "orchestrate P0"
|
|
1029
|
+
→ Gets all P0 issues, runs them all (presumably urgent)
|
|
1030
|
+
→ Single wave if possible, confirms, executes
|
|
1031
|
+
|
|
1032
|
+
### "orchestrate fast-lane"
|
|
1033
|
+
→ Gets all unmilestoned bugs/fixes
|
|
1034
|
+
→ Groups by independence, runs in waves
|
|
1035
|
+
|
|
1036
|
+
### "orchestrate milestone cortex-recursive-loop"
|
|
1037
|
+
→ Fetches all open issues in "Cortex Recursive Loop" milestone
|
|
1038
|
+
→ Detects #2644 is an investigation issue (title: "Investigate: Complete the autonomous recursive loop...")
|
|
1039
|
+
→ Wave 0: Runs `/work-on 2644` — investigation creates 5 new issues (#2650-#2654)
|
|
1040
|
+
→ Re-fetches milestone issues, now includes #2650-#2654
|
|
1041
|
+
→ Wave 1: #2633 (P0 orphaned queues), #2636 (invalidation), #2650, #2651 (all independent)
|
|
1042
|
+
→ Wave 2: #2634 (enable daemon, after #2633), #2652 (depends on #2650)
|
|
1043
|
+
→ Wave 3: remaining issues
|
|
1044
|
+
→ Final report shows investigation spawned issues and their results
|