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,262 @@
1
+ ---
2
+ description: Build subcommand — create worktree, post contract, sequence context/architect/implement/validate
3
+ argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--base PR_BASE]
4
+ ---
5
+
6
+ # work-on/build — Build Phase Orchestrator
7
+
8
+ **Input**: $ARGUMENTS
9
+
10
+ **Invoked by**: `work-on.md` state 8 (READY_TO_BUILD).
11
+ **Output**: Create worktree, post contract, sequence build subcommands, return result to router.
12
+
13
+ **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
14
+ **NEVER use plan mode (EnterPlanMode).**
15
+
16
+ **CRITICAL: You MUST execute ALL phases B0–B6 in order. After each Skill() call returns, you MUST continue to the next phase. Do NOT skip phases B3 (context) or B4 (architect) — they post mandatory `FORGE:CONTEXT` and `FORGE:ARCHITECT` comments that the implement phase reads as its primary input. Skipping them degrades build quality.**
17
+
18
+ ---
19
+
20
+ ## Inputs
21
+
22
+ Parse from $ARGUMENTS:
23
+ - `{NUMBER}` — issue number (required)
24
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `RapierCraftStudios/forge`)
25
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R RapierCraftStudios/forge`)
26
+ - `--base {PR_BASE}` — PR target branch (e.g. `milestone/modular-pipeline-architecture` or `staging`)
27
+
28
+ ---
29
+
30
+ ## Phase B0: Load State from GitHub (MANDATORY)
31
+
32
+ Re-read current state before doing anything:
33
+
34
+ ```bash
35
+ gh issue view {NUMBER} {GH_FLAG} --json number,title,body,labels,state,milestone
36
+
37
+ # Check investigation report
38
+ gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
39
+ --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body'
40
+
41
+ # Check if build already completed
42
+ gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
43
+ --jq '.[] | select(.body | (contains("FORGE:BUILDER") or contains("ALTERLAB:BUILDER"))) | .body'
44
+ ```
45
+
46
+ **Resume check**:
47
+ - If `<!-- FORGE:BUILDER -->` or `<!-- ALTERLAB:BUILDER -->` comment exists → build already complete. Return `BUILD_RESULT: status: ALREADY_DONE` to router.
48
+ - If no `<!-- FORGE:INVESTIGATOR -->` or `<!-- ALTERLAB:INVESTIGATOR -->` comment with `<!-- INVESTIGATION:COMPLETE -->` → EXIT with `BUILD_RESULT: status: BLOCKED`, blocker: "Investigation not complete — run investigate first".
49
+
50
+ Extract from investigation report:
51
+ - Affected files list
52
+ - Root cause
53
+ - Recommendation
54
+ - Task type (Bug Fix / Feature / Refactor / Maintenance / UI/UX / Full-Stack)
55
+
56
+ ---
57
+
58
+ ## Phase B1: Create Worktree & Branch
59
+
60
+ ### B1A: Derive branch name
61
+
62
+ From issue title: lowercase, hyphenated, max 40 chars (truncate if needed).
63
+ - Bug / fix issues → prefix `fix/`
64
+ - Feature issues → prefix `feat/`
65
+ - Refactor / maintenance → prefix `fix/` or `refactor/`
66
+
67
+ Append `-{NUMBER}` to ensure uniqueness: e.g. `fix/work-on-build-landing-file-85`.
68
+
69
+ ### B1B: Determine source branch
70
+
71
+ - Review-finding issue → parse `**Code branch**: \`{branch}\`` from issue body; branch from `origin/{branch}`
72
+ - **Milestone review-finding hybrid lane** (ONLY when Code branch matches `milestone/*`): This is a high-risk lane. The worktree will carry the full milestone history. The PR target is `staging` (or the base specified). **DANGER: Agents MUST NOT use `git merge` to resolve any conflicts in this lane.** Merge-based conflict resolution will pull the entire milestone commit tree onto staging, contaminating it with unapproved code. Use `git rebase` or `git cherry-pick` only. If conflicts cannot be resolved without a merge, post a comment on the issue, add `needs-human`, and STOP.
73
+ - Feature lane (has milestone) → branch from `origin/{PR_BASE}`
74
+ - Fast lane (no milestone) → branch from `origin/staging`
75
+
76
+ ### B1C: Create worktree
77
+
78
+ ```bash
79
+ WORKTREE_PATH="/path/to/repo/.claude/worktrees/{BRANCH_SLUG}"
80
+ git worktree add {WORKTREE_PATH} -b {BRANCH} origin/{SOURCE_BRANCH}
81
+ ```
82
+
83
+ If worktree already exists at that path:
84
+ ```bash
85
+ # Reuse existing worktree — verify it's on the correct branch
86
+ git -C {WORKTREE_PATH} branch --show-current
87
+ ```
88
+ If wrong branch, remove and recreate:
89
+ ```bash
90
+ git worktree remove {WORKTREE_PATH} --force
91
+ git worktree add {WORKTREE_PATH} -b {BRANCH} origin/{SOURCE_BRANCH}
92
+ ```
93
+
94
+ ### B1D: Set building label
95
+
96
+ ```bash
97
+ gh issue edit {NUMBER} {GH_FLAG} \
98
+ --add-label "workflow:building" \
99
+ --remove-label "workflow:ready-to-build"
100
+ ```
101
+
102
+ ---
103
+
104
+ ## Phase B2: Post Builder Contract
105
+
106
+ Post `<!-- FORGE:CONTRACT -->` comment documenting what will be built and why:
107
+
108
+ ```bash
109
+ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:CONTRACT -->
110
+ ## Builder Contract
111
+
112
+ **Task type**: {TASK_TYPE}
113
+
114
+ ### Proposed Approach
115
+
116
+ {BRIEF_APPROACH_DESCRIPTION}
117
+
118
+ ### Deliverables
119
+
120
+ | File | Change | Why |
121
+ |------|--------|-----|
122
+ {DELIVERABLES_ROWS}
123
+
124
+ ### Acceptance Criteria
125
+
126
+ {ACCEPTANCE_CRITERIA_CHECKLIST}
127
+
128
+ ### Quality Considerations
129
+
130
+ {AUTH_MODEL_NEW_ENV_VARS_SQL_SAFETY_SECURITY_SURFACE}
131
+
132
+ ### Out of Scope
133
+
134
+ {OUT_OF_SCOPE_ITEMS}"
135
+ ```
136
+
137
+ Contract must be grounded in the investigation report. Every deliverable file must appear in the affected files list from the investigator. Adversarially validate the proposed fix against adjacent system layers before posting.
138
+
139
+ ---
140
+
141
+ ## Phase B2.5: Extract FUNCTION_NAMES from Contract
142
+
143
+ After posting the Builder Contract, extract the primary function/class names from the contract's deliverables table. These are passed to the context subcommand for Phase C3 caller/importer discovery.
144
+
145
+ ```bash
146
+ FUNCTION_NAMES=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
147
+ --jq '.[] | select(.body | contains("FORGE:CONTRACT")) | .body' \
148
+ | awk '/^### Deliverables/{p=1; next} /^### /{p=0} p' \
149
+ | grep -oP '`[A-Za-z_][A-Za-z0-9_]*`' \
150
+ | tr -d '`' \
151
+ | sort -u \
152
+ | tr '\n' ' ' \
153
+ | xargs)
154
+ # Scope is limited to the ### Deliverables section to avoid false matches from FORGE markers,
155
+ # phase labels (B2, C3), and identifiers mentioned in Acceptance Criteria or Quality sections.
156
+ # Fallback: if extraction yields nothing, FUNCTION_NAMES remains empty string
157
+ # context.md Phase C3 skips gracefully when FUNCTION_NAMES is empty (for-loop produces zero iterations)
158
+ ```
159
+
160
+ If `FUNCTION_NAMES` is non-empty, it will be passed via `--functions` to the context subcommand. If empty, the `--functions` flag is omitted — Phase C3 will naturally skip with zero iterations and no error.
161
+
162
+ ---
163
+
164
+ ## Phase B3: Context Gathering (MANDATORY Subcommand)
165
+
166
+ **This phase is NOT optional.** Always invoke it regardless of issue size or complexity. Do NOT invent skip heuristics (e.g. "FAST_PATH") — the context subcommand handles trivial cases gracefully and returns quickly.
167
+
168
+ Invoke the context subcommand to surface historical review findings and bug patterns:
169
+
170
+ ```
171
+ Skill("work-on:build:context", args="{NUMBER} --repo {GH_REPO} --gh-flag {GH_FLAG} --repo-path {WORKTREE_PATH} {AFFECTED_FILES} --functions {FUNCTION_NAMES}")
172
+ ```
173
+
174
+ If `FUNCTION_NAMES` is empty, omit the `--functions` flag entirely:
175
+
176
+ ```
177
+ Skill("work-on:build:context", args="{NUMBER} --repo {GH_REPO} --gh-flag {GH_FLAG} --repo-path {WORKTREE_PATH} {AFFECTED_FILES}")
178
+ ```
179
+
180
+ **After subcommand returns**:
181
+ - Returns structured context briefing (or indicates no relevant history) → continue to B4
182
+ - If subcommand times out or errors → log warning, continue to B4 with empty context (non-blocking)
183
+ # MUST CONTINUE to Phase B4 — context result is intermediate, NOT terminal.
184
+
185
+ ---
186
+
187
+ ## Phase B4: Architecture Planning (MANDATORY Subcommand)
188
+
189
+ **This phase is NOT optional.** Always invoke it regardless of issue size or complexity. Do NOT invent skip heuristics — the architect subcommand handles simple changes gracefully and returns quickly. Even a 1-file fix benefits from cross-path consistency checks.
190
+
191
+ Invoke the architect subcommand to trace all affected code paths and produce an ordered implementation plan:
192
+
193
+ ```
194
+ Skill("work-on:build:architect", args="{NUMBER} --repo {GH_REPO} --gh-flag {GH_FLAG} --repo-path {WORKTREE_PATH} --files {AFFECTED_FILES}")
195
+ ```
196
+
197
+ **After subcommand returns**:
198
+ - Returns ordered implementation plan → continue to B5
199
+ - If subcommand returns BLOCKED → post comment, add `needs-human`, return `BUILD_RESULT: status: BLOCKED`
200
+ # MUST CONTINUE to Phase B5 — architect result is intermediate, NOT terminal.
201
+
202
+ ---
203
+
204
+ ## Phase B5: Implementation (Subcommand)
205
+
206
+ Invoke the implement subcommand to write code, stage, and post the builder comment:
207
+
208
+ ```
209
+ Skill("work-on:build:implement", args="{NUMBER} --repo {GH_REPO} --gh-flag {GH_FLAG} --worktree {WORKTREE_PATH} --branch {BRANCH}")
210
+ ```
211
+
212
+ **After subcommand returns**:
213
+ - `IMPLEMENT_RESULT: status: COMPLETE` → continue to B6
214
+ - `IMPLEMENT_RESULT: status: ALREADY_DONE` → skip to B6 (validate what's already there)
215
+ - `IMPLEMENT_RESULT: status: INVESTIGATION_COMPLETE` → issues created as deliverables; return `BUILD_RESULT: status: INVESTIGATION_COMPLETE`
216
+ - `IMPLEMENT_RESULT: status: BLOCKED` → post comment with blocker description, add `needs-human`, return `BUILD_RESULT: status: BLOCKED`
217
+ # MUST CONTINUE to Phase B6 — implement result is intermediate, NOT terminal (validation still required).
218
+
219
+ ---
220
+
221
+ ## Phase B6: Validation (Subcommand)
222
+
223
+ Invoke the validate subcommand to run the quality gate loop, formatting, and deploy checks:
224
+
225
+ ```
226
+ Skill("work-on:build:validate", args="{NUMBER} --repo {GH_REPO} --gh-flag {GH_FLAG} --worktree {WORKTREE_PATH} --files {CHANGED_FILES}")
227
+ ```
228
+
229
+ Where `{CHANGED_FILES}` is the space-separated list of files changed by the implement subcommand (read from `IMPLEMENT_RESULT` or from the `<!-- FORGE:BUILDER -->` comment).
230
+
231
+ **After subcommand returns**:
232
+ - `VALIDATE_RESULT: gate_passed: true` → build complete, return `BUILD_RESULT: status: COMPLETE`
233
+ - `VALIDATE_RESULT: gate_passed: false` → subcommand has already posted comment and added `needs-human` label; return `BUILD_RESULT: status: BLOCKED`
234
+
235
+ ---
236
+
237
+ ## Output
238
+
239
+ Output this structured block — the routing loop in `work-on.md` will read this result, re-evaluate state, and continue to the next phase. This subcommand is complete; control returns to the router's loop iteration.
240
+
241
+ ```
242
+ BUILD_RESULT:
243
+ status: COMPLETE | ALREADY_DONE | INVESTIGATION_COMPLETE | BLOCKED
244
+ branch: {BRANCH}
245
+ worktree: {WORKTREE_PATH}
246
+ blocker: {description if status=BLOCKED}
247
+ ```
248
+
249
+ ---
250
+
251
+ ## Integration Point in work-on.md
252
+
253
+ This module runs at **state 8 (READY_TO_BUILD)** in the routing loop:
254
+
255
+ ```
256
+ state 8 → [THIS MODULE] worktree + contract + context + architect + implement + validate
257
+ → BUILD_RESULT: COMPLETE
258
+ states 7, 6 → work-on:review (push + PR + /review-pr --auto-merge)
259
+ states 5, 4 → work-on:close (trajectory + parent tracker + summary)
260
+ ```
261
+
262
+ The router re-reads GitHub state after this module returns COMPLETE — it will then detect state 6 (IN_REVIEW) or 7 (BUILD_NO_PR) and invoke `work-on:review`.
@@ -0,0 +1,350 @@
1
+ ---
2
+ description: Close subcommand — update project board, final issue body, parent tracker, summary report, trajectory log
3
+ argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--pr PR_NUMBER] [--base PR_BASE] [--branch BRANCH] [--worktree WORKTREE_PATH]
4
+ ---
5
+
6
+ # work-on/close — Close & Trajectory Subcommand
7
+
8
+ **Input**: $ARGUMENTS
9
+
10
+ **Invoked by**: `work-on.md` Phase 6–7, after `review.md` returns `REVIEW_RESULT: status: COMPLETE`.
11
+ **Output**: Update project board, close issue, update parent tracker, post trajectory log. Return final summary.
12
+
13
+ **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
14
+ **NEVER use plan mode (EnterPlanMode).**
15
+
16
+ ---
17
+
18
+ ## Inputs
19
+
20
+ Parse from $ARGUMENTS:
21
+ - `{NUMBER}` — issue number (required)
22
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `RapierCraftStudios/forge`)
23
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R RapierCraftStudios/forge`)
24
+ - `--pr {PR_NUMBER}` — merged PR number
25
+ - `--base {PR_BASE}` — branch the PR merged into (e.g. `milestone/modular-pipeline-architecture`)
26
+ - `--branch {BRANCH}` — feature branch name (for worktree cleanup reference)
27
+ - `--worktree {WORKTREE_PATH}` — absolute path to the git worktree to remove (optional — skip cleanup if not provided)
28
+
29
+ ---
30
+
31
+ ## Phase C0: Load State from GitHub (MANDATORY)
32
+
33
+ Re-read current state before doing anything:
34
+
35
+ ```bash
36
+ # Issue full context
37
+ gh issue view {NUMBER} {GH_FLAG} --json number,title,body,labels,state,milestone
38
+
39
+ # PR state
40
+ gh pr view {PR_NUMBER} {GH_FLAG} --json state,mergedAt,mergeCommit
41
+
42
+ # All agent comments (to reconstruct pipeline results)
43
+ gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
44
+ --jq '.[] | {body: .body, created_at: .created_at}'
45
+ ```
46
+
47
+ Extract from agent comments:
48
+ - From FORGE:INVESTIGATOR: verdict, confidence, task type
49
+ - From FORGE:BUILDER: branch, commits, files changed
50
+ - From FORGE:TRAJECTORY (if exists): prior trajectory entries
51
+
52
+ **Resume check**:
53
+ - If `<!-- FORGE:TRAJECTORY -->` comment already exists → trajectory already posted, EXIT with `CLOSE_RESULT: status: ALREADY_DONE`
54
+ - If issue is already CLOSED and PR is MERGED → skip to C3 (just post trajectory if missing)
55
+
56
+ ---
57
+
58
+ ## Phase C1: Final Issue Body Update
59
+
60
+ **Multi-phase guard**: Before checking off items, detect whether the issue has multiple phases. Only check off items belonging to the current completed phase — not all remaining items across future phases.
61
+
62
+ ```bash
63
+ # Read current body
64
+ BODY=$(gh issue view {NUMBER} {GH_FLAG} --json body --jq '.body')
65
+
66
+ # Count remaining unchecked items BEFORE any edit
67
+ REMAINING_BEFORE=$(echo "$BODY" | grep -c '^- \[ \]' || true)
68
+ ```
69
+
70
+ **If `REMAINING_BEFORE == 0`** (no unchecked items): skip body edit — all items already checked, proceed to add PR reference only:
71
+ ```bash
72
+ UPDATED_BODY="${BODY}"$'\n\n'"**PR**: #{PR_NUMBER} → merged to \`{PR_BASE}\`"
73
+ gh issue edit {NUMBER} {GH_FLAG} --body "{UPDATED_BODY}"
74
+ REMAINING_AFTER=0
75
+ ```
76
+
77
+ **If `REMAINING_BEFORE > 0`**: check whether ANY `- [ ]` items will still remain after a full check-off — i.e., does the issue have multi-phase structure?
78
+
79
+ Multi-phase issues have checkbox groups separated by phase headings (lines starting with `##` or `###`) where at least one group has unchecked items. Detect this:
80
+ ```bash
81
+ # Conservative heuristic: if the issue body contains a phase heading (## or ###)
82
+ # AND unchecked items remain, treat as multi-phase — do NOT check off items from
83
+ # future phases; only add the PR reference and leave unchecked items intact.
84
+ HAS_PHASE_HEADINGS=$(echo "$BODY" | grep -cP '^#{2,3} ' || true)
85
+
86
+ if [ "$HAS_PHASE_HEADINGS" -gt 0 ]; then
87
+ # Multi-phase issue: do NOT check off any [ ] items
88
+ # Only add the PR reference so progress is recorded
89
+ UPDATED_BODY="${BODY}"$'\n\n'"**PR**: #{PR_NUMBER} → merged to \`{PR_BASE}\` (phase complete — remaining phases open)"
90
+ gh issue edit {NUMBER} {GH_FLAG} --body "{UPDATED_BODY}"
91
+ REMAINING_AFTER="$REMAINING_BEFORE"
92
+ else
93
+ # Single-phase issue: check off all remaining [ ] items
94
+ UPDATED_BODY=$(echo "$BODY" | sed 's/^- \[ \]/- [x]/g')
95
+ UPDATED_BODY="${UPDATED_BODY}"$'\n\n'"**PR**: #{PR_NUMBER} → merged to \`{PR_BASE}\`"
96
+ gh issue edit {NUMBER} {GH_FLAG} --body "{UPDATED_BODY}"
97
+ REMAINING_AFTER=0
98
+ fi
99
+ ```
100
+
101
+ The `REMAINING_AFTER` variable is passed to Phase C2 to decide whether to close.
102
+
103
+ ---
104
+
105
+ ## Phase C1.5: Project Board Update (Status=Done, Workflow=Merged)
106
+
107
+ Update the project board to reflect the merged state. This replaces the old Phase 5E project board update that existed before the modular refactor.
108
+
109
+ ```bash
110
+ # Find the project item ID for this issue
111
+ ISSUE_URL="https://github.com/{GH_REPO}/issues/{NUMBER}"
112
+ ITEM_ID=$(gh project item-list 1 --owner RapierCraft --format json --limit 200 \
113
+ --jq ".items[] | select(.content.url == \"$ISSUE_URL\") | .id" 2>/dev/null | head -1)
114
+ ```
115
+
116
+ If `ITEM_ID` is found:
117
+ ```bash
118
+ # Set Status=Done
119
+ gh project item-edit --project-id PVT_kwHOCx3gR84BSK2L --id "$ITEM_ID" \
120
+ --field-id PVTSSF_lAHOCx3gR84BSK2Lzg_yF6E --single-select-option-id 98236657 2>/dev/null || true # Status=Done
121
+
122
+ # Set Workflow=Merged
123
+ gh project item-edit --project-id PVT_kwHOCx3gR84BSK2L --id "$ITEM_ID" \
124
+ --field-id PVTSSF_lAHOCx3gR84BSK2Lzg_yGAA --single-select-option-id b510c537 2>/dev/null || true # Workflow=Merged
125
+ ```
126
+
127
+ If `ITEM_ID` is empty (issue not on project board) → log and skip:
128
+ ```bash
129
+ echo "INFO: Issue #{NUMBER} not found on project board — skipping board update"
130
+ ```
131
+
132
+ **Field reference** (project `PVT_kwHOCx3gR84BSK2L`):
133
+ | Field | Field ID | Option | Option ID |
134
+ |-------|----------|--------|-----------|
135
+ | Status | `PVTSSF_lAHOCx3gR84BSK2Lzg_yF6E` | Done | `98236657` |
136
+ | Workflow | `PVTSSF_lAHOCx3gR84BSK2Lzg_yGAA` | Merged | `b510c537` |
137
+
138
+ ---
139
+
140
+ ## Phase C2: Ensure Issue is Closed
141
+
142
+ **Multi-phase guard**: If `REMAINING_AFTER > 0` (set in Phase C1), uncompleted phases remain — do NOT close the issue. Instead, post a phase-complete comment and exit early so the router can pick up the next phase on the next pipeline iteration.
143
+
144
+ ```bash
145
+ ISSUE_STATE=$(gh issue view {NUMBER} {GH_FLAG} --json state --jq '.state')
146
+ ```
147
+
148
+ **If `REMAINING_AFTER > 0`** (multi-phase: uncompleted phases remain):
149
+ ```bash
150
+ # Post phase-complete marker — router state 10 (MULTI_PHASE) will re-detect this issue
151
+ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:PHASE:COMPLETE -->
152
+ Phase complete. PR #{PR_NUMBER} merged to \`{PR_BASE}\`. ${REMAINING_AFTER} phase item(s) remain — leaving issue open for next pipeline iteration."
153
+
154
+ # Update labels to reflect phase complete (not yet fully merged)
155
+ gh issue edit {NUMBER} {GH_FLAG} \
156
+ --remove-label "workflow:in-review,workflow:building,workflow:investigating" 2>/dev/null || true
157
+
158
+ # EXIT — do not close, do not post trajectory, do not run C3–C6
159
+ # Return CLOSE_RESULT: status: PHASE_COMPLETE to caller
160
+ exit 0
161
+ ```
162
+
163
+ **If `REMAINING_AFTER == 0`** (all phases complete — single-phase or final phase of multi-phase):
164
+
165
+ If state is `OPEN`:
166
+ ```bash
167
+ gh issue close {NUMBER} {GH_FLAG} \
168
+ --comment "Closed: PR #{PR_NUMBER} merged to \`{PR_BASE}\`. Closes #{NUMBER}."
169
+ ```
170
+
171
+ Add merged label:
172
+ ```bash
173
+ gh issue edit {NUMBER} {GH_FLAG} \
174
+ --add-label "workflow:merged" \
175
+ --remove-label "workflow:in-review,workflow:building,workflow:investigating" 2>/dev/null || true
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Phase C3: Parent Tracker Update (Sub-Issues Only)
181
+
182
+ **Skip if**: Issue body does NOT contain a parent issue reference (e.g. `Part of #NNN`) or the issue has no parent in its milestone tracker.
183
+
184
+ Detect parent reference:
185
+ ```bash
186
+ PARENT_REF=$(gh issue view {NUMBER} {GH_FLAG} --json body --jq '.body' \
187
+ | grep -oP '(?i)(part of|spawned from|sub-issue of|parent issue[:]?|parent[:])\s*#\K\d+' \
188
+ | head -1)
189
+ ```
190
+
191
+ If no parent reference found → log a warning and skip this phase:
192
+ ```bash
193
+ echo "WARNING: No parent reference found in issue body — skipping parent tracker update"
194
+ ```
195
+
196
+ If parent found:
197
+ ```bash
198
+ # Read parent body
199
+ PARENT_BODY=$(gh issue view {PARENT_REF} {GH_FLAG} --json body --jq '.body')
200
+
201
+ # Check off this sub-issue in parent body (replace "- [ ] #{NUMBER}" with "- [x] #{NUMBER}")
202
+ UPDATED_PARENT=$(echo "$PARENT_BODY" | sed "s/- \[ \] #${NUMBER}/- [x] #${NUMBER}/g")
203
+ gh issue edit {PARENT_REF} {GH_FLAG} --body "$UPDATED_PARENT"
204
+
205
+ # Check if all sub-issues are now closed
206
+ OPEN_SUBS=$(echo "$UPDATED_PARENT" | grep -c '\- \[ \]' || true)
207
+ ```
208
+
209
+ If `OPEN_SUBS == 0` (all sub-issues checked off):
210
+ ```bash
211
+ gh issue close {PARENT_REF} {GH_FLAG} \
212
+ --comment "All sub-issues complete. Closing parent tracker. Last completed: #{NUMBER} (PR #{PR_NUMBER})."
213
+ gh issue edit {PARENT_REF} {GH_FLAG} --add-label "workflow:merged"
214
+ ```
215
+
216
+ ---
217
+
218
+ ## Phase C4: Summary Report
219
+
220
+ Reconstruct the pipeline summary from GitHub state:
221
+
222
+ ```bash
223
+ # Get investigation verdict from FORGE:INVESTIGATOR comment (or legacy ALTERLAB:INVESTIGATOR)
224
+ VERDICT=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
225
+ --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body' \
226
+ | grep -oP '(?<=\*\*Verdict\*\*: )\w+' | head -1)
227
+
228
+ CONFIDENCE=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
229
+ --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body' \
230
+ | grep -oP '(?<=\*\*Confidence\*\*: )\w+' | head -1)
231
+
232
+ # Get files changed from FORGE:BUILDER comment (or legacy ALTERLAB:BUILDER)
233
+ FILES_CHANGED=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
234
+ --jq '.[] | select(.body | (contains("FORGE:BUILDER") or contains("ALTERLAB:BUILDER"))) | .body' \
235
+ | grep -oP '(?<=\*\*Files changed\*\*: )\d+' | head -1)
236
+ ```
237
+
238
+ Output to stdout (returned to calling agent):
239
+
240
+ ```
241
+ ## Done: #{NUMBER} — {TITLE}
242
+ - Investigation: {VERDICT} ({CONFIDENCE})
243
+ - Lane: FEATURE
244
+ - Fix: {BRANCH} → PR #{PR_NUMBER} → merged to `{PR_BASE}`
245
+ - Files changed: {FILES_CHANGED}
246
+ ```
247
+
248
+ ---
249
+
250
+ ## Phase C5: Trajectory Log (MANDATORY)
251
+
252
+ Post the `<!-- FORGE:TRAJECTORY -->` comment as the final pipeline record:
253
+
254
+ ```bash
255
+ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:TRAJECTORY -->
256
+ ## Pipeline Trajectory — #{NUMBER}
257
+
258
+ | Phase | Result | Notes |
259
+ |-------|--------|-------|
260
+ | Phase 0: Context Load | ✅ Complete | Feature lane → \`{PR_BASE}\` |
261
+ | Phase 1: Investigation | ✅ {VERDICT} ({CONFIDENCE}) | Task type: {TASK_TYPE} |
262
+ | Phase 2: Decomposition | ⏭ Skipped | Single-concern change, no decomposition needed |
263
+ | Phase 3: Build | ✅ Complete | Branch: \`{BRANCH}\` |
264
+ | Phase 3F.5: Validate | ✅ Gate passed | Quality gate: pass |
265
+ | Phase 4–5: Review + PR | ✅ Merged | PR #{PR_NUMBER} → \`{PR_BASE}\` |
266
+ | Phase 6: Parent Tracker | {PARENT_STATUS} | {PARENT_NOTES} |
267
+ | Phase C6: Cleanup | {CLEANUP_STATUS} | Worktree: {WORKTREE_PATH}, Branch: {BRANCH} |
268
+ | Phase 7: Close | ✅ Complete | Issue closed |
269
+
270
+ **Decisions**:
271
+ - Decomposition skipped: {DECOMPOSE_REASON}
272
+ - PR merged to: \`{PR_BASE}\` (feature lane, milestone branch)
273
+
274
+ **Anomalies**: None
275
+
276
+ **Pipeline completed**: {TIMESTAMP}"
277
+ ```
278
+
279
+ Where:
280
+ - `{PARENT_STATUS}` = `⏭ Skipped` (if no parent) or `✅ Complete` (if parent updated)
281
+ - `{PARENT_NOTES}` = `No parent tracker` or `Checked off in #{PARENT_REF}`
282
+ - `{CLEANUP_STATUS}` = `✅ Removed` (worktree removed + branch deleted) or `⏭ Skipped` (no path provided or path not found)
283
+ - `{TIMESTAMP}` = current date/time in ISO format
284
+
285
+ ---
286
+
287
+ ## Phase C6: Worktree & Branch Cleanup
288
+
289
+ Remove the git worktree and delete the local feature branch after the PR has merged. This prevents worktree accumulation across pipeline runs.
290
+
291
+ **Skip if**: `{WORKTREE_PATH}` is not provided OR the path does not exist.
292
+
293
+ ```bash
294
+ # Remove worktree (--force handles detached or uncommitted state)
295
+ if [ -n "{WORKTREE_PATH}" ] && [ -d "{WORKTREE_PATH}" ]; then
296
+ # Use --git-common-dir to correctly resolve REPO_ROOT for linked worktrees.
297
+ # --show-toplevel returns the worktree path itself (not the main repo root),
298
+ # so xargs dirname would give the worktree's parent dir — not the repo root.
299
+ # --git-common-dir returns the shared .git dir (e.g. /repo/.git), and
300
+ # dirname of that is always the main repo root regardless of worktree depth.
301
+ GIT_COMMON=$(git -C {WORKTREE_PATH} rev-parse --git-common-dir 2>/dev/null)
302
+ REPO_ROOT=$(dirname "$(realpath "$GIT_COMMON" 2>/dev/null || echo "$GIT_COMMON")")
303
+ git -C "$REPO_ROOT" worktree remove {WORKTREE_PATH} --force 2>/dev/null || true
304
+ echo "Worktree removed: {WORKTREE_PATH}"
305
+
306
+ # Delete local feature branch (remote branch already deleted by GitHub on merge)
307
+ if [ -n "{BRANCH}" ]; then
308
+ git -C "$REPO_ROOT" branch -D {BRANCH} 2>/dev/null || true
309
+ echo "Local branch deleted: {BRANCH}"
310
+ fi
311
+ else
312
+ echo "Worktree cleanup skipped: path not provided or does not exist"
313
+ fi
314
+ ```
315
+
316
+ Set `{CLEANUP_STATUS}` based on outcome:
317
+ - Worktree path provided and existed → `✅ Removed` (worktree removed, branch deleted)
318
+ - Worktree path not provided or path didn't exist → `⏭ Skipped`
319
+
320
+ Update the trajectory log `{CLEANUP_STATUS}` field accordingly (the trajectory was already posted in C5, so this is recorded in the output summary, not by re-editing the comment).
321
+
322
+ ---
323
+
324
+ ## Output
325
+
326
+ Return structured output to the caller:
327
+
328
+ ```
329
+ CLOSE_RESULT:
330
+ status: COMPLETE | ALREADY_DONE | PHASE_COMPLETE
331
+ issue_state: closed | open
332
+ trajectory_url: {url of FORGE:TRAJECTORY comment}
333
+ parent_updated: {true|false}
334
+ parent_closed: {true|false}
335
+ ```
336
+
337
+ Where `PHASE_COMPLETE` means the current phase was closed but uncompleted phases remain — the issue is left OPEN for the router to re-evaluate on the next pipeline iteration (state 10, MULTI_PHASE).
338
+
339
+ ---
340
+
341
+ ## Integration Point in work-on.md
342
+
343
+ This module runs at **Phases 6–7** — after review.md returns `REVIEW_RESULT: status: COMPLETE`:
344
+
345
+ ```
346
+ 4–5 → Review (by review.md) — PR created, reviewed, merged, issue closed
347
+ 6–7 → [THIS MODULE] Final body update, parent tracker, summary, trajectory
348
+ ```
349
+
350
+ This is the terminal phase — after CLOSE_RESULT returns, the pipeline is complete.