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.
Files changed (44) hide show
  1. package/LICENSE +244 -0
  2. package/README.md +251 -0
  3. package/bin/forgedock.mjs +232 -0
  4. package/commands/analytics.md +777 -0
  5. package/commands/audit-agents.md +410 -0
  6. package/commands/audit.md +410 -0
  7. package/commands/autopilot.md +432 -0
  8. package/commands/cleanup.md +264 -0
  9. package/commands/deploy-info.md +292 -0
  10. package/commands/failure-recon.md +375 -0
  11. package/commands/forge-stats.md +183 -0
  12. package/commands/geo-audit.md +343 -0
  13. package/commands/incident-response.md +384 -0
  14. package/commands/issue.md +506 -0
  15. package/commands/milestone.md +599 -0
  16. package/commands/orchestrate.md +1044 -0
  17. package/commands/pipeline-health.md +2343 -0
  18. package/commands/qa-sweep.md +237 -0
  19. package/commands/quality-gate.md +777 -0
  20. package/commands/review-pr-agents.md +1711 -0
  21. package/commands/review-pr-staging.md +325 -0
  22. package/commands/review-pr.md +888 -0
  23. package/commands/rollback.md +253 -0
  24. package/commands/security-audit.md +529 -0
  25. package/commands/sync-ecosystem.md +527 -0
  26. package/commands/validate.md +131 -0
  27. package/commands/work-on/build/architect.md +291 -0
  28. package/commands/work-on/build/context.md +349 -0
  29. package/commands/work-on/build/implement.md +280 -0
  30. package/commands/work-on/build/validate.md +292 -0
  31. package/commands/work-on/build.md +262 -0
  32. package/commands/work-on/close.md +350 -0
  33. package/commands/work-on/decompose.md +254 -0
  34. package/commands/work-on/investigate.md +437 -0
  35. package/commands/work-on/review.md +245 -0
  36. package/commands/work-on-monolithic.md +298 -0
  37. package/commands/work-on.md +1089 -0
  38. package/docs/CODEX.md +92 -0
  39. package/docs/WORKFLOW.md +104 -0
  40. package/package.json +45 -0
  41. package/scripts/verify-env-vars.sh +201 -0
  42. package/scripts/verify-host-headers.sh +117 -0
  43. package/scripts/verify-route-registration.sh +118 -0
  44. package/scripts/verify-sops-chain.sh +163 -0
@@ -0,0 +1,432 @@
1
+ ---
2
+ description: Autonomous platform improvement cycle — recon, triage, fix, report. Runs recon+triage by default; pass --fix to also pick up and fix top issues. Human gates all deploys.
3
+ argument-hint: [--fix | --recon-only | --fix --limit 5 | --dry-run]
4
+ ---
5
+
6
+ # /autopilot — Recursive Platform Improvement Cycle
7
+
8
+ **Input**: $ARGUMENTS (default: recon + triage + report, no fixing)
9
+
10
+ You are AlterLab's autonomous improvement engine. Your job is to **find what's wrong, create trackable issues, and optionally fix the highest-impact ones** — all in a single cycle. Every cycle leaves the platform measurably better than before.
11
+
12
+ **This is designed to run repeatedly.** Each cycle builds on the last — issues created in cycle N get fixed in cycle N+1. The platform compounds improvements over time.
13
+
14
+ **NEVER use plan mode (EnterPlanMode)** — it breaks execution context.
15
+
16
+ **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`. User can override with `--model <name>`. Pass the resolved model in every `Agent`/`Task` tool call. Each agent prompt is scoped to a specific data source or issue — the model executes the explicit steps without needing broad inference.
17
+
18
+ ---
19
+
20
+ ## Argument Parsing
21
+
22
+ | Flag | Effect |
23
+ |------|--------|
24
+ | (none) | Phases 1-3 only (recon, triage, report) |
25
+ | `--fix` | Also run Phase 4 (pick top issues, fix via /work-on) |
26
+ | `--fix --limit N` | Fix at most N issues (default: 3) |
27
+ | `--recon-only` | Phase 1 only (data collection, no issue creation) |
28
+ | `--dry-run` | Run everything but don't create issues or PRs — just report what would happen |
29
+
30
+ Parse `$ARGUMENTS` and set these variables:
31
+ ```
32
+ MODE = "full" | "recon-only" | "fix" # derived from flags
33
+ DO_FIX = true if --fix present
34
+ FIX_LIMIT = N from --limit N, default 3
35
+ DRY_RUN = true if --dry-run present
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Phase 0: Cycle Context
41
+
42
+ **Goal**: Understand what happened since the last cycle.
43
+
44
+ ### 0A: Timestamp & baseline
45
+
46
+ ```bash
47
+ echo "=== Autopilot Cycle: $(date -u +%Y-%m-%dT%H:%M:%SZ) ==="
48
+
49
+ # Recent closed issues (last 3 days) — what was fixed recently?
50
+ gh issue list --state closed --json number,title,labels,closedAt \
51
+ --jq '[.[] | select(.closedAt > "'$(date -u -d '3 days ago' +%Y-%m-%dT%H:%M:%SZ)'")] | length' 2>/dev/null || echo "0"
52
+
53
+ # Open issue count by priority
54
+ gh issue list --state open --label P0 --json number --jq 'length'
55
+ gh issue list --state open --label P1 --json number --jq 'length'
56
+ gh issue list --state open --label P2 --json number --jq 'length'
57
+
58
+ # Stale issues (open, no workflow label, older than 7 days)
59
+ gh issue list --state open --limit 200 --json number,title,labels,createdAt \
60
+ --jq '[.[] | select(
61
+ (.labels | map(.name) | any(startswith("workflow:")) | not) and
62
+ (.createdAt < "'$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)'")
63
+ )] | length'
64
+
65
+ # Failed CI runs in last 24h
66
+ gh run list --limit 30 --json conclusion,createdAt \
67
+ --jq '[.[] | select(.conclusion == "failure" and .createdAt > "'$(date -u -d '1 day ago' +%Y-%m-%dT%H:%M:%SZ)'")] | length'
68
+ ```
69
+
70
+ Store these as `BASELINE` metrics for the cycle report.
71
+
72
+ ### 0B: Check for open P0s
73
+
74
+ ```bash
75
+ gh issue list --state open --label P0 --json number,title --jq '.[] | "#\(.number) \(.title)"'
76
+ ```
77
+
78
+ If any P0 issues exist:
79
+ - **STOP the normal cycle**
80
+ - Print: `P0 issue(s) open — autopilot prioritizing these above all else`
81
+ - Set `FIX_TARGETS` to the P0 issue numbers
82
+ - Skip to Phase 4 (fix mode, regardless of flags)
83
+
84
+ ---
85
+
86
+ ## Phase 1: Recon (Parallel Data Collection)
87
+
88
+ **Goal**: Pull signals from every available source. Launch ALL collectors simultaneously.
89
+
90
+ ### 1A: Launch parallel recon agents
91
+
92
+ Spawn these as **background agents** (all `run_in_background=true`, all `model="sonnet"`):
93
+
94
+ **Agent: Production Health**
95
+ ```
96
+ Check production system health:
97
+ 1. SSH to check for open eMemos: ssh ubuntu@51.195.40.172 "ls /opt/alterlab/app/infra/ememos/*-open-* 2>/dev/null"
98
+ 2. If any exist, cat each one and summarize
99
+ 3. Check container health via MCP: get_production_status, run_production_health_check
100
+ 4. Check recent error logs: get_production_logs for api and worker (last 100 lines), grep for ERROR/CRITICAL
101
+ 5. Return: memo summaries, unhealthy containers, error patterns with counts
102
+ ```
103
+
104
+ **Agent: Scraping Intelligence**
105
+ ```
106
+ Pull scraping performance data:
107
+ 1. Read scrape_diagnostics summary from admin API or production logs
108
+ 2. Check Redis for tier feedback stats: tier success/fail rates across domains
109
+ 3. Look for patterns: domains with >50% failure rate, tiers with degraded performance
110
+ 4. Return: top failing domains (count + tier), tier pass rates, any new anti-bot patterns
111
+ ```
112
+
113
+ **Agent: CI/CD Health**
114
+ ```
115
+ Check CI pipeline health:
116
+ 1. gh run list --limit 30 — count failures by workflow name
117
+ 2. For each failed run: gh run view {id} --json jobs — identify which job failed
118
+ 3. Check if ecosystem-sync is consistently failing (known issue vs new)
119
+ 4. Return: failure rate, recurring failures, new failures
120
+ ```
121
+
122
+ **Agent: Issue Backlog Health**
123
+ ```
124
+ Analyze GitHub issue backlog:
125
+ 1. gh issue list --state open --limit 200 — full list with labels, milestones, dates
126
+ 2. Count by: priority (P0-P3), type (bug/feature/etc), milestone, age
127
+ 3. Find stale issues: open > 14 days, no workflow label, no recent comments
128
+ 4. Find orphaned issues: workflow:in-review but no open PR
129
+ 5. Find blocked issues: depends on another open issue
130
+ 6. Return: backlog summary, stale issues list, orphans, blockers
131
+ ```
132
+
133
+ **Agent: Analytics Snapshot** (lightweight — not the full /analytics audit)
134
+ ```
135
+ Quick analytics pulse — just the key metrics, not a full audit:
136
+ 1. Read credentials from /home/mrdubey/projects/ScraperAPI/credentials.yaml
137
+ 2. GSC: mcp__gsc__search_analytics for last 7 days — total clicks, impressions, avg position
138
+ 3. Stripe: mcp__stripe__retrieve_balance — current balance
139
+ 4. Return: clicks trend (up/down), any revenue, notable changes
140
+ ```
141
+
142
+ ### 1B: Collect results
143
+
144
+ Wait for all agents to complete. Aggregate into a `RECON_DATA` object:
145
+ ```
146
+ RECON_DATA = {
147
+ production: { memos, unhealthy_containers, error_patterns },
148
+ scraping: { failing_domains, tier_rates, new_patterns },
149
+ ci: { failure_rate, recurring_failures, new_failures },
150
+ backlog: { summary, stale_issues, orphans, blockers },
151
+ analytics: { clicks_trend, revenue, notable_changes }
152
+ }
153
+ ```
154
+
155
+ If `MODE == "recon-only"`, print RECON_DATA as a formatted report and **stop here**.
156
+
157
+ ---
158
+
159
+ ## Phase 2: Triage & Issue Creation
160
+
161
+ **Goal**: Convert recon signals into actionable, deduplicated GitHub issues.
162
+
163
+ ### 2A: Deduplication check
164
+
165
+ Before creating ANY issue, search for existing open issues that cover the same problem:
166
+
167
+ ```bash
168
+ # For each finding, search existing issues
169
+ gh issue list --state open --limit 200 --json number,title,labels \
170
+ --jq '.[] | "\(.number) \(.title)"'
171
+ ```
172
+
173
+ **Rule**: If an existing open issue covers the finding (even partially), DO NOT create a duplicate. Instead, add a comment to the existing issue with the new data point.
174
+
175
+ ### 2B: Classify and prioritize findings
176
+
177
+ For each finding from RECON_DATA, assign:
178
+
179
+ | Signal | Priority | Type |
180
+ |--------|----------|------|
181
+ | Production eMemo (open) | P1 | bug |
182
+ | Container unhealthy | P0 | bug |
183
+ | Error spike (>5x normal) | P1 | bug |
184
+ | Tier degradation (>20% drop) | P2 | bug |
185
+ | CI consistently failing | P2 | bug |
186
+ | Stale issue (>14 days) | — | (comment, don't create new issue) |
187
+ | Orphaned workflow state | — | (fix via /cleanup, not new issue) |
188
+ | Analytics decline (>20% week-over-week) | P2 | improvement |
189
+ | New anti-bot pattern detected | P2 | feature |
190
+
191
+ ### 2C: Create issues
192
+
193
+ For each finding that passes dedup check, create a GitHub issue:
194
+
195
+ ```bash
196
+ gh issue create \
197
+ --title "{fix|feat|refactor}: {concise description}" \
198
+ --label "{priority},{type}" \
199
+ --body "$(cat <<'ISSUE_EOF'
200
+ ## Problem
201
+
202
+ {Description of the finding with specific data points. What's wrong or what's missing.}
203
+
204
+ ## Root Cause (if known)
205
+
206
+ {What's causing the issue — specific code path, config gap, or behavior. If unknown: "Root cause unknown — investigation needed."}
207
+
208
+ ## Affected Files
209
+
210
+ Files that need changes:
211
+ 1. `{filepath}` — {what needs to change}
212
+ 2. `{filepath}` — {what needs to change}
213
+
214
+ ## Acceptance Criteria
215
+
216
+ - [ ] {Specific, testable criterion}
217
+ - [ ] No regression in {related feature}
218
+
219
+ ## Context
220
+
221
+ Found by \`/autopilot\` cycle on {DATE}.
222
+
223
+ ## Evidence
224
+
225
+ {Logs, metrics, error messages — concrete data, not speculation}
226
+
227
+ ## Suggested Approach
228
+
229
+ {Brief suggestion — the /work-on investigation will validate this}
230
+
231
+ ---
232
+ *Created by autopilot recon cycle. Will be validated before any fix is applied.*
233
+ ISSUE_EOF
234
+ )"
235
+ ```
236
+
237
+ **DRY_RUN check**: If `DRY_RUN == true`, print what would be created but don't actually create issues.
238
+
239
+ ### 2D: Quick hygiene (inline, no separate /cleanup invocation)
240
+
241
+ While we have the backlog data, fix obvious hygiene issues directly:
242
+
243
+ ```bash
244
+ # Close orphaned issues (merged PR but still open)
245
+ for orphan in {ORPHAN_LIST}; do
246
+ gh issue close $orphan --comment "Auto-closed by autopilot: linked PR was already merged."
247
+ done
248
+
249
+ # Fix stale labels on closed issues
250
+ for stale in {STALE_LABEL_LIST}; do
251
+ gh issue edit $stale --add-label "workflow:merged" --remove-label "workflow:in-review,workflow:building" 2>/dev/null || true
252
+ done
253
+ ```
254
+
255
+ Store list of created issues as `CREATED_ISSUES`.
256
+
257
+ ---
258
+
259
+ ## Phase 3: Cycle Report
260
+
261
+ **Goal**: Present findings and actions taken to the user.
262
+
263
+ Print a structured report:
264
+
265
+ ```markdown
266
+ ## Autopilot Cycle Report — {DATE}
267
+
268
+ ### Production Health
269
+ - Containers: {all healthy / N unhealthy}
270
+ - Open eMemos: {count}
271
+ - Error patterns: {summary or "none"}
272
+
273
+ ### Scraping Performance
274
+ - Tier pass rates: T1 {X}%, T2 {X}%, T3 {X}%, T4 {X}%
275
+ - Top failing domains: {list or "all healthy"}
276
+ - New patterns: {any or "none detected"}
277
+
278
+ ### CI/CD
279
+ - Failure rate (24h): {X}/{Y} runs
280
+ - Recurring failures: {list or "none"}
281
+
282
+ ### Issue Backlog
283
+ - Open: {P0: N, P1: N, P2: N, P3: N}
284
+ - Stale (>14d): {count}
285
+ - Orphaned: {count fixed}
286
+
287
+ ### Analytics Pulse
288
+ - Clicks (7d): {N} ({trend})
289
+ - Revenue: ${N}
290
+
291
+ ### Actions Taken
292
+ - Issues created: {count} ({list with numbers})
293
+ - Issues commented: {count}
294
+ - Orphans closed: {count}
295
+ - Stale labels fixed: {count}
296
+
297
+ ### Recommended Next Steps
298
+ {Prioritized list of what the user should look at or deploy}
299
+ ```
300
+
301
+ If `DO_FIX == false`, **stop here**. Print:
302
+ ```
303
+ Run `/autopilot --fix` to also pick up and fix the top {FIX_LIMIT} issues.
304
+ ```
305
+
306
+ ---
307
+
308
+ ## Phase 4: Fix (Optional, requires --fix flag)
309
+
310
+ **Goal**: Pick the highest-impact fixable issues and run them through `/work-on`.
311
+
312
+ ### 4A: Select fix targets
313
+
314
+ If `FIX_TARGETS` was set by Phase 0 (P0 issues), use those. Otherwise:
315
+
316
+ Pick the top `FIX_LIMIT` issues by this priority:
317
+ 1. P0 issues (always first)
318
+ 2. P1 bugs (production-impacting)
319
+ 3. Issues created by THIS cycle (freshest signal)
320
+ 4. P2 bugs with `validated` or `needs-validation` label
321
+ 5. Oldest P1 issues (prevent aging)
322
+
323
+ **Exclude** from fix targets:
324
+ - Issues with `needs-human` label
325
+ - Issues in milestones (feature lane — don't autopilot feature work)
326
+ - Issues already in `workflow:building` or `workflow:in-review`
327
+ - Issues with open dependencies
328
+
329
+ ```bash
330
+ # Get candidates
331
+ gh issue list --state open --label "bug" --limit 50 --json number,title,labels,createdAt \
332
+ --jq 'sort_by(.labels | map(select(.name | startswith("P"))) | .[0].name) | .[:{FIX_LIMIT}] | .[] | "#\(.number) \(.title)"'
333
+ ```
334
+
335
+ ### 4B: Present fix plan to user
336
+
337
+ **MANDATORY CHECKPOINT — do NOT proceed without user confirmation.**
338
+
339
+ ```markdown
340
+ ## Autopilot Fix Plan
341
+
342
+ I'll run `/work-on` for these {N} issues:
343
+
344
+ | # | Title | Priority | Estimated Scope |
345
+ |---|-------|----------|-----------------|
346
+ | {number} | {title} | {priority} | {small/medium/large} |
347
+
348
+ Each issue goes through: investigate → validate → build → review → merge to staging.
349
+ Nothing merges to `main` — you deploy when ready.
350
+
351
+ **Proceed?** (yes / adjust / skip)
352
+ ```
353
+
354
+ Wait for user response. If they adjust, re-select. If they skip, end the cycle.
355
+
356
+ ### 4C: Execute fixes
357
+
358
+ For each approved fix target, invoke `/work-on` via the Skill tool:
359
+
360
+ ```
361
+ Skill(skill: "work-on", args: "{ISSUE_NUMBER}")
362
+ ```
363
+
364
+ Run them **sequentially** (not parallel) — each `/work-on` invocation is heavyweight and benefits from full context. If one fails, continue to the next.
365
+
366
+ After each `/work-on` completes, record the result:
367
+ ```
368
+ FIX_RESULTS.push({
369
+ issue: NUMBER,
370
+ outcome: "merged" | "invalid" | "failed" | "needs-human",
371
+ pr: PR_NUMBER or null,
372
+ branch: BRANCH_NAME
373
+ })
374
+ ```
375
+
376
+ ### 4D: Fix summary
377
+
378
+ ```markdown
379
+ ## Fix Results
380
+
381
+ | Issue | Outcome | PR |
382
+ |-------|---------|-----|
383
+ | #{N} | {outcome} | #{PR} |
384
+
385
+ **Merged to staging**: {count}
386
+ **Needs attention**: {list}
387
+
388
+ When ready to deploy, merge `staging` → `main` via GitHub.
389
+ ```
390
+
391
+ ---
392
+
393
+ ## Safety Rules
394
+
395
+ 1. **NEVER merge to `main`** — all fixes go to `staging`. User deploys manually.
396
+ 2. **NEVER skip investigation** — every fix goes through full `/work-on` (investigate → validate → build → review → merge).
397
+ 3. **NEVER fix `needs-human` issues** — these require human judgment (legal, external services, etc.).
398
+ 4. **NEVER fix milestone issues** — feature work is scoped to milestones, not autopilot.
399
+ 5. **NEVER create duplicate issues** — always dedup against existing open issues first.
400
+ 6. **NEVER run more than FIX_LIMIT fixes per cycle** — prevent runaway resource consumption.
401
+ 7. **If a fix fails, move on** — don't retry. Log it and let the next cycle or human handle it.
402
+ 8. **DRY_RUN means NO side effects** — no issues created, no PRs, no label changes. Report only.
403
+ 9. **P0 overrides everything** — if P0 exists, skip normal recon and fix P0 immediately.
404
+ 10. **Always gate fixes on user approval** — Phase 4B checkpoint is non-negotiable.
405
+
406
+ ---
407
+
408
+ ## Recursion: How Cycles Compound
409
+
410
+ Each cycle feeds the next:
411
+ ```
412
+ Cycle N: /failure-recon finds tier 3 headers broken → creates issue #X
413
+ Cycle N+1: autopilot picks up #X → /work-on fixes it → merged to staging
414
+ Cycle N+2: /failure-recon shows tier 3 pass rate improved 30% → no new issue needed
415
+ ```
416
+
417
+ ```
418
+ Cycle N: /analytics finds CTR dropped on /pricing → creates issue #Y
419
+ Cycle N+1: autopilot picks up #Y → /work-on rewrites SERP snippet → merged
420
+ Cycle N+2: /analytics shows CTR recovered → improvement confirmed
421
+ ```
422
+
423
+ The platform gets better every cycle. Issues that aren't picked up age and rise in priority. Issues that keep recurring indicate a deeper structural problem — autopilot will eventually create a "meta" issue about the pattern.
424
+
425
+ ---
426
+
427
+ ## Operational Notes
428
+
429
+ - **Runtime**: Recon-only ~3-5 min. Full cycle with fixes ~15-45 min depending on issue count.
430
+ - **Token budget**: Recon is cheap (mostly MCP + API calls). Fixes are expensive (full /work-on per issue).
431
+ - **Idempotent**: Safe to run multiple times — dedup prevents duplicate issues, /work-on resumes from checkpoints.
432
+ - **Pairs with /loop**: Run `/loop 4h /autopilot` for continuous improvement, or `/loop 4h /autopilot --fix --limit 2` for autonomous fixing with a human checkpoint every cycle.
@@ -0,0 +1,264 @@
1
+ ---
2
+ description: Sweep closed issues for stale labels, missing workflow state, and Project board gaps — plus prune worktrees, branches, and milestones
3
+ argument-hint: [labels | branches | milestones | board | orphans | all]
4
+ ---
5
+
6
+ # /cleanup — Full Hygiene Sweep
7
+
8
+ **Input**: $ARGUMENTS
9
+
10
+ Scan the entire development environment for rot and fix it. This is a maintenance command — run periodically or after large orchestration batches. It covers 6 domains: stale labels, orphaned issues, worktree/branch pruning, milestone hygiene, and Project board sync.
11
+
12
+ **NEVER use plan mode (EnterPlanMode)** — it breaks execution context.
13
+
14
+ ---
15
+
16
+ ## Command Router
17
+
18
+ | Input | Action |
19
+ |-------|--------|
20
+ | `labels` or empty | Fix stale/missing workflow labels on closed issues |
21
+ | `orphans` | Close open issues whose PRs are already merged |
22
+ | `branches` | Prune worktrees and remote branches for merged PRs |
23
+ | `milestones` | Close milestones with 0 open issues |
24
+ | `board` | Sync closed issues to Project board with correct terminal state |
25
+ | `all` | All of the above, in order |
26
+
27
+ ---
28
+
29
+ ## Phase 1: Stale Labels
30
+
31
+ ### 1A: Detect stale intermediate labels on closed issues
32
+
33
+ These labels should only exist on OPEN issues. If a closed issue has them, the pipeline crashed mid-flight.
34
+
35
+ ```bash
36
+ echo "=== Stale workflow:in-review ==="
37
+ gh issue list -R RapierCraft/AlterLab --state closed --label "workflow:in-review" --limit 100 --json number,title --jq '.[] | "#\(.number) — \(.title)"'
38
+
39
+ echo "=== Stale workflow:building ==="
40
+ gh issue list -R RapierCraft/AlterLab --state closed --label "workflow:building" --limit 100 --json number,title --jq '.[] | "#\(.number) — \(.title)"'
41
+
42
+ echo "=== Stale workflow:investigating ==="
43
+ gh issue list -R RapierCraft/AlterLab --state closed --label "workflow:investigating" --limit 100 --json number,title --jq '.[] | "#\(.number) — \(.title)"'
44
+
45
+ echo "=== Stale needs-validation ==="
46
+ gh issue list -R RapierCraft/AlterLab --state closed --label "needs-validation" --limit 100 --json number,title --jq '.[] | "#\(.number) — \(.title)"'
47
+ ```
48
+
49
+ ### 1B: Fix stale labels
50
+
51
+ For each closed issue with a stale intermediate label:
52
+
53
+ **Stale `workflow:in-review`, `workflow:building`** — these were merged but label wasn't updated:
54
+ ```bash
55
+ for NUM in {stale_issue_numbers}; do
56
+ gh issue edit $NUM -R RapierCraft/AlterLab --add-label "workflow:merged"
57
+ gh issue edit $NUM -R RapierCraft/AlterLab --remove-label "workflow:in-review,workflow:building,needs-validation" 2>/dev/null || true
58
+ done
59
+ ```
60
+
61
+ **Stale `workflow:investigating`** — check if closed as invalid or completed:
62
+ - If it has `workflow:invalid` already → just remove `workflow:investigating`
63
+ - If closed normally → add `workflow:merged`, remove `workflow:investigating`
64
+
65
+ **Stale `needs-validation`** — remove from all closed issues:
66
+ ```bash
67
+ for NUM in {needs_validation_numbers}; do
68
+ gh issue edit $NUM -R RapierCraft/AlterLab --remove-label "needs-validation" 2>/dev/null || true
69
+ done
70
+ ```
71
+
72
+ ### 1C: Report closed issues with NO workflow label
73
+
74
+ ```bash
75
+ gh issue list -R RapierCraft/AlterLab --state closed --limit 200 --json number,title,labels \
76
+ --jq '.[] | select([.labels[].name] | any(startswith("workflow:")) | not) | "#\(.number) — \(.title)"'
77
+ ```
78
+
79
+ These were closed outside the pipeline. Report count but don't fix (not necessarily wrong).
80
+
81
+ ---
82
+
83
+ ## Phase 2: Orphaned Issues (open issues with merged PRs)
84
+
85
+ Find open issues whose fix PRs have already been merged — these slipped through because `Closes #N` doesn't auto-close when merging to `staging` (only works for default branch `main`).
86
+
87
+ ### 2A: Detect orphans
88
+
89
+ For each open issue with `workflow:in-review` label, check if it has a merged PR:
90
+
91
+ ```bash
92
+ # Get all open issues with workflow:in-review
93
+ OPEN_IN_REVIEW=$(gh issue list -R RapierCraft/AlterLab --state open --label "workflow:in-review" --limit 100 --json number --jq '.[].number')
94
+
95
+ for NUM in $OPEN_IN_REVIEW; do
96
+ # Search for merged PRs that reference this issue
97
+ MERGED_PR=$(gh pr list -R RapierCraft/AlterLab --search "Closes #$NUM" --state merged --json number --jq '.[0].number' 2>/dev/null)
98
+ if [ -n "$MERGED_PR" ]; then
99
+ echo "ORPHAN: #$NUM has merged PR #$MERGED_PR"
100
+ fi
101
+ done
102
+ ```
103
+
104
+ ### 2B: Close orphans
105
+
106
+ For each orphaned issue found:
107
+ ```bash
108
+ gh issue close $NUM -R RapierCraft/AlterLab --comment "Closed by cleanup — PR #$MERGED_PR was already merged."
109
+ gh issue edit $NUM -R RapierCraft/AlterLab --add-label "workflow:merged"
110
+ gh issue edit $NUM -R RapierCraft/AlterLab --remove-label "workflow:in-review" 2>/dev/null || true
111
+ ```
112
+
113
+ Also check open issues with `workflow:building` — same pattern (search for merged PRs referencing them).
114
+
115
+ ---
116
+
117
+ ## Phase 3: Worktree & Branch Pruning
118
+
119
+ ### 3A: Identify worktrees with merged PRs
120
+
121
+ ```bash
122
+ cd /home/mrdubey/projects/ScraperAPI/alterlab
123
+
124
+ # For each worktree (excluding the main one), check if its branch has a merged PR
125
+ git worktree list --porcelain | grep "^worktree " | grep -v "/alterlab$" | sed 's/^worktree //' | while read wt; do
126
+ branch=$(git -C "$wt" branch --show-current 2>/dev/null)
127
+ if [ -n "$branch" ]; then
128
+ merged_pr=$(gh pr list --head "$branch" --state merged --json number --jq '.[0].number' 2>/dev/null)
129
+ if [ -n "$merged_pr" ]; then
130
+ echo "STALE_WT|$wt|$branch|PR#$merged_pr"
131
+ fi
132
+ fi
133
+ done
134
+ ```
135
+
136
+ ### 3B: Remove stale worktrees and local branches
137
+
138
+ For each worktree with a merged PR:
139
+ ```bash
140
+ git worktree remove "$WORKTREE_PATH" --force
141
+ git branch -D "$BRANCH_NAME" 2>/dev/null || true
142
+ echo "Removed: $WORKTREE_PATH ($BRANCH_NAME)"
143
+ ```
144
+
145
+ ### 3C: Prune merged remote branches
146
+
147
+ Delete remote `fix/` and `feat/` branches that are fully merged into `staging`:
148
+
149
+ ```bash
150
+ cd /home/mrdubey/projects/ScraperAPI/alterlab
151
+ git fetch --prune origin
152
+
153
+ # Count first
154
+ MERGED_COUNT=$(git branch -r --merged origin/staging | grep -E "origin/(fix|feat)/" | wc -l)
155
+ echo "Found $MERGED_COUNT merged remote branches to delete"
156
+
157
+ # Delete them
158
+ if [ "$MERGED_COUNT" -gt 0 ]; then
159
+ git branch -r --merged origin/staging | grep -E "origin/(fix|feat)/" | sed 's|origin/||' | xargs -I{} git push origin --delete {} 2>&1
160
+ fi
161
+ ```
162
+
163
+ **Note**: This can take a while for large batches (1 network call per branch). Run in background if > 20 branches.
164
+
165
+ ---
166
+
167
+ ## Phase 4: Milestone Hygiene
168
+
169
+ ### 4A: Find completed milestones
170
+
171
+ ```bash
172
+ # List open milestones with 0 remaining issues
173
+ gh api repos/:owner/:repo/milestones --jq '.[] | select(.state == "open" and .open_issues == 0) | "\(.number) | \(.title) | open:\(.open_issues) closed:\(.closed_issues)"'
174
+ ```
175
+
176
+ ### 4B: Close completed milestones (shipping-verified only)
177
+
178
+ For each milestone with 0 open issues, verify the milestone branch has been merged to staging or main before closing:
179
+
180
+ ```bash
181
+ # Derive slug from milestone title (lowercase, spaces→hyphens, strip non-alphanumeric except hyphens)
182
+ SLUG=$(echo "$MILESTONE_TITLE" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
183
+
184
+ # Check if milestone branch was merged to staging or main
185
+ SHIPPED_STAGING=$(gh pr list --base staging --head "milestone/$SLUG" --state merged --json number --jq '.[0].number' 2>/dev/null)
186
+ SHIPPED_MAIN=$(gh pr list --base main --head "milestone/$SLUG" --state merged --json number --jq '.[0].number' 2>/dev/null)
187
+
188
+ if [ -n "$SHIPPED_STAGING" ] || [ -n "$SHIPPED_MAIN" ]; then
189
+ # Safe to close — code has been shipped to staging or main
190
+ gh api repos/:owner/:repo/milestones/$MILESTONE_NUMBER -X PATCH -f state=closed
191
+ echo "CLOSED milestone: $MILESTONE_TITLE (shipped via PR #${SHIPPED_STAGING:-$SHIPPED_MAIN})"
192
+ else
193
+ # DO NOT close — code is only on the milestone branch, not yet shipped
194
+ echo "SKIPPED: $MILESTONE_TITLE — issues done but milestone branch not merged to staging or main"
195
+ fi
196
+ ```
197
+
198
+ **Exception**: Don't close milestones that are intentionally kept open for future work (check if the milestone description says "ongoing" or "rolling"). If unsure, **SKIP it** — milestones are only closed by `/milestone ship` after code reaches staging. Incorrect closure destroys milestone state that cannot be trivially recovered.
199
+
200
+ ---
201
+
202
+ ## Phase 5: Sync Project Board (if `board` or `all`)
203
+
204
+ For closed issues that are on the Project board but have stale fields:
205
+
206
+ ```bash
207
+ gh project item-list 1 --owner RapierCraft --format json --limit 200
208
+ ```
209
+
210
+ For each item where `content.state == "CLOSED"` but `status != "Done"` or `workflow` is not a terminal state:
211
+
212
+ ```bash
213
+ gh project item-edit --project-id PVT_kwHOCx3gR84BSK2L --id "$ITEM_ID" \
214
+ --field-id PVTSSF_lAHOCx3gR84BSK2Lzg_yF6E --single-select-option-id 98236657 2>/dev/null || true # Status=Done
215
+ gh project item-edit --project-id PVT_kwHOCx3gR84BSK2L --id "$ITEM_ID" \
216
+ --field-id PVTSSF_lAHOCx3gR84BSK2Lzg_yGAA --single-select-option-id b510c537 2>/dev/null || true # Workflow=Merged
217
+ ```
218
+
219
+ ---
220
+
221
+ ## Phase 6: Report
222
+
223
+ ```
224
+ ## Cleanup Report
225
+
226
+ ### Labels Fixed
227
+ | Action | Count |
228
+ |--------|-------|
229
+ | workflow:in-review → workflow:merged | {N} |
230
+ | workflow:building → workflow:merged | {N} |
231
+ | workflow:investigating → cleaned | {N} |
232
+ | needs-validation removed | {N} |
233
+
234
+ ### Orphaned Issues Closed
235
+ | Issue | Merged PR | Action |
236
+ |-------|-----------|--------|
237
+ | #{N} | PR #{M} | Closed |
238
+
239
+ ### Worktrees & Branches Pruned
240
+ | Type | Count |
241
+ |------|-------|
242
+ | Worktrees removed | {N} |
243
+ | Local branches deleted | {N} |
244
+ | Remote branches deleted | {N} |
245
+
246
+ ### Milestones Closed
247
+ | Milestone | Issues (closed) | Shipped via |
248
+ |-----------|-----------------|-------------|
249
+ | {title} | {N} | PR #{M} → staging/main |
250
+
251
+ ### Milestones Skipped (unshipped)
252
+ | Milestone | Issues (closed) | Reason |
253
+ |-----------|-----------------|--------|
254
+ | {title} | {N} | No merged PR from milestone/{slug} → staging or main |
255
+
256
+ ### Board Synced
257
+ | Action | Count |
258
+ |--------|-------|
259
+ | Status → Done | {N} |
260
+ | Workflow → Merged | {N} |
261
+
262
+ ### Still Missing Workflow Label
263
+ {N} closed issues have no workflow label (closed outside pipeline — no action needed)
264
+ ```