forgedock 1.0.1 → 1.0.2

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 (41) hide show
  1. package/README.md +19 -2
  2. package/bin/forgedock.mjs +286 -10
  3. package/commands/analytics.md +129 -52
  4. package/commands/audit-agents.md +29 -5
  5. package/commands/audit.md +55 -17
  6. package/commands/autopilot.md +11 -6
  7. package/commands/cleanup.md +44 -24
  8. package/commands/deploy-info.md +7 -3
  9. package/commands/forge-stats.md +13 -4
  10. package/commands/forgedock-init.md +534 -0
  11. package/commands/geo-audit.md +114 -26
  12. package/commands/incident-response.md +4 -1
  13. package/commands/issue.md +26 -25
  14. package/commands/milestone.md +80 -59
  15. package/commands/orchestrate.md +38 -21
  16. package/commands/pipeline-health.md +26 -15
  17. package/commands/qa-sweep.md +68 -5
  18. package/commands/quality-gate.md +18 -0
  19. package/commands/review-pr-agents.md +58 -90
  20. package/commands/review-pr.md +58 -16
  21. package/commands/rollback.md +8 -5
  22. package/commands/security-audit.md +68 -12
  23. package/commands/sync-ecosystem.md +196 -156
  24. package/commands/work-on/build/architect.md +2 -2
  25. package/commands/work-on/build/context.md +2 -2
  26. package/commands/work-on/build/implement.md +3 -3
  27. package/commands/work-on/build/validate.md +3 -3
  28. package/commands/work-on/build.md +6 -6
  29. package/commands/work-on/close.md +59 -30
  30. package/commands/work-on/decompose.md +6 -6
  31. package/commands/work-on/investigate.md +16 -20
  32. package/commands/work-on/review.md +4 -4
  33. package/commands/work-on-monolithic.md +15 -16
  34. package/commands/work-on.md +45 -33
  35. package/docs/CODEX.md +1 -1
  36. package/docs/CONFIG.md +398 -0
  37. package/docs/WORKFLOW.md +115 -72
  38. package/package.json +1 -1
  39. package/scripts/verify-host-headers.sh +14 -9
  40. package/scripts/verify-route-registration.sh +10 -10
  41. package/commands/failure-recon.md +0 -375
@@ -19,8 +19,8 @@ argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree P
19
19
 
20
20
  Parse from $ARGUMENTS:
21
21
  - `{NUMBER}` — issue number (required)
22
- - `--repo {GH_REPO}` — GitHub repo (e.g. `RapierCraft/AlterLab`)
23
- - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R RapierCraft/AlterLab`)
22
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `{owner}/{repo}` — resolved from `forge.yaml → project`)
23
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R {owner}/{repo}`)
24
24
  - `--worktree {WORKTREE_PATH}` — absolute path to the git worktree (set by caller)
25
25
  - `--branch {BRANCH}` — feature branch name (e.g. `feat/my-feature`)
26
26
 
@@ -145,7 +145,7 @@ if [ -n "$NEW_ENV_VARS" ]; then
145
145
  fi
146
146
  ```
147
147
 
148
- **If any MISSING line is printed**: add the var to the missing location before proceeding to Phase I4. If the file doesn't exist in this repo (e.g. `ENV_VARS.md` is an AlterLab file, not a Forge file), skip that check silently.
148
+ **If any MISSING line is printed**: add the var to the missing location before proceeding to Phase I4. If a file listed above doesn't exist in this repo (e.g. `ENV_VARS.md` or `env_validation.py` may not be present in all projects), skip that check silently.
149
149
 
150
150
  ### Check 2 — Deploy/infra restart risk
151
151
 
@@ -19,8 +19,8 @@ argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree P
19
19
 
20
20
  Parse from $ARGUMENTS:
21
21
  - `{NUMBER}` — issue number (required)
22
- - `--repo {GH_REPO}` — GitHub repo (e.g. `RapierCraft/AlterLab`)
23
- - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R RapierCraft/AlterLab`)
22
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `{owner}/{repo}` — resolved from `forge.yaml → project`)
23
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R {owner}/{repo}`)
24
24
  - `--worktree {WORKTREE_PATH}` — absolute path to the git worktree
25
25
  - `--files {CHANGED_FILES}` — space-separated list of changed files (from implement result)
26
26
 
@@ -99,7 +99,7 @@ python -m py_compile {PYTHON_FILES}
99
99
  ```
100
100
  Failures in `py_compile` are BLOCKING — fix before continuing.
101
101
 
102
- **TypeScript (AlterLab)**:
102
+ **TypeScript (tsc)**:
103
103
  ```bash
104
104
  cd {WORKTREE_PATH}
105
105
  prettier --write {TS_FILES}
@@ -21,8 +21,8 @@ argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--base PR_BA
21
21
 
22
22
  Parse from $ARGUMENTS:
23
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`)
24
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `{owner}/{repo}` — resolved from `forge.yaml → project`)
25
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R {owner}/{repo}`)
26
26
  - `--base {PR_BASE}` — PR target branch (e.g. `milestone/modular-pipeline-architecture` or `staging`)
27
27
 
28
28
  ---
@@ -36,16 +36,16 @@ gh issue view {NUMBER} {GH_FLAG} --json number,title,body,labels,state,milestone
36
36
 
37
37
  # Check investigation report
38
38
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
39
- --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body'
39
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body'
40
40
 
41
41
  # Check if build already completed
42
42
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
43
- --jq '.[] | select(.body | (contains("FORGE:BUILDER") or contains("ALTERLAB:BUILDER"))) | .body'
43
+ --jq '.[] | select(.body | contains("FORGE:BUILDER")) | .body'
44
44
  ```
45
45
 
46
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".
47
+ - If `<!-- FORGE:BUILDER -->` comment exists → build already complete. Return `BUILD_RESULT: status: ALREADY_DONE` to router.
48
+ - If no `<!-- FORGE:INVESTIGATOR -->` comment with `<!-- INVESTIGATION:COMPLETE -->` → EXIT with `BUILD_RESULT: status: BLOCKED`, blocker: "Investigation not complete — run investigate first".
49
49
 
50
50
  Extract from investigation report:
51
51
  - Affected files list
@@ -19,8 +19,8 @@ argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--pr PR_NUMB
19
19
 
20
20
  Parse from $ARGUMENTS:
21
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`)
22
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `{owner}/{repo}` — resolved from `forge.yaml → project`)
23
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R {owner}/{repo}`)
24
24
  - `--pr {PR_NUMBER}` — merged PR number
25
25
  - `--base {PR_BASE}` — branch the PR merged into (e.g. `milestone/modular-pipeline-architecture`)
26
26
  - `--branch {BRANCH}` — feature branch name (for worktree cleanup reference)
@@ -106,34 +106,63 @@ The `REMAINING_AFTER` variable is passed to Phase C2 to decide whether to close.
106
106
 
107
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
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
- ```
109
+ **Read project board config from `forge.yaml`**. If the `project_board` section is absent or commented out, skip this phase entirely:
115
110
 
116
- If `ITEM_ID` is found:
117
111
  ```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
112
+ # Read project board config from forge.yaml
113
+ PROJECT_BOARD_OWNER=$(yq '.project_board.owner // ""' forge.yaml 2>/dev/null || echo "")
114
+ PROJECT_ID=$(yq '.project_board.project_id // ""' forge.yaml 2>/dev/null || echo "")
115
+ PROJECT_NUMBER=$(yq '.project_board.project_number // ""' forge.yaml 2>/dev/null || echo "")
116
+ STATUS_FIELD_ID=$(yq '.project_board.field_ids.status // ""' forge.yaml 2>/dev/null || echo "")
117
+ WORKFLOW_FIELD_ID=$(yq '.project_board.field_ids.workflow // ""' forge.yaml 2>/dev/null || echo "")
118
+ STATUS_DONE_OPTION_ID=$(yq '.project_board.option_ids.status.done // ""' forge.yaml 2>/dev/null || echo "")
119
+ WORKFLOW_MERGED_OPTION_ID=$(yq '.project_board.option_ids.workflow.merged // ""' forge.yaml 2>/dev/null || echo "")
120
+
121
+ if [ -z "$PROJECT_BOARD_OWNER" ] || [ -z "$PROJECT_ID" ] || [ -z "$STATUS_FIELD_ID" ]; then
122
+ echo "INFO: project_board not configured in forge.yaml — skipping board update"
123
+ # → STOP: do not proceed to ITEM_ID fetch or board update — continue to Phase C2
124
+ else
125
+ # Project board is configured — find the item and update it
126
+
127
+ # Find the project item ID for this issue
128
+ ISSUE_URL="https://github.com/{GH_REPO}/issues/{NUMBER}"
129
+ ITEM_ID=$(gh project item-list "$PROJECT_NUMBER" --owner "$PROJECT_BOARD_OWNER" --format json --limit 200 \
130
+ --jq ".items[] | select(.content.url == \"$ISSUE_URL\") | .id" 2>/dev/null | head -1)
131
+
132
+ if [ -n "$ITEM_ID" ]; then
133
+ # Set Status=Done
134
+ if [ -n "$STATUS_FIELD_ID" ] && [ -n "$STATUS_DONE_OPTION_ID" ]; then
135
+ gh project item-edit --project-id "$PROJECT_ID" --id "$ITEM_ID" \
136
+ --field-id "$STATUS_FIELD_ID" --single-select-option-id "$STATUS_DONE_OPTION_ID" 2>/dev/null || true
137
+ fi
138
+
139
+ # Set Workflow=Merged
140
+ if [ -n "$WORKFLOW_FIELD_ID" ] && [ -n "$WORKFLOW_MERGED_OPTION_ID" ]; then
141
+ gh project item-edit --project-id "$PROJECT_ID" --id "$ITEM_ID" \
142
+ --field-id "$WORKFLOW_FIELD_ID" --single-select-option-id "$WORKFLOW_MERGED_OPTION_ID" 2>/dev/null || true
143
+ fi
144
+ else
145
+ echo "INFO: Issue #{NUMBER} not found on project board — skipping board update"
146
+ fi
147
+ fi
125
148
  ```
126
149
 
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"
150
+ **Project board field IDs are read from `forge.yaml → project_board`**. To configure:
151
+ ```yaml
152
+ project_board:
153
+ owner: "{your-github-org}"
154
+ project_number: 1
155
+ project_id: "PVT_kwHO..."
156
+ field_ids:
157
+ status: "PVTSSF_..."
158
+ workflow: "PVTSSF_..."
159
+ option_ids:
160
+ status:
161
+ done: "..."
162
+ workflow:
163
+ merged: "..."
130
164
  ```
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` |
165
+ To find your project IDs: `gh project list --owner {owner}` and `gh project field-list {number} --owner {owner}`.
137
166
 
138
167
  ---
139
168
 
@@ -220,18 +249,18 @@ gh issue edit {PARENT_REF} {GH_FLAG} --add-label "workflow:merged"
220
249
  Reconstruct the pipeline summary from GitHub state:
221
250
 
222
251
  ```bash
223
- # Get investigation verdict from FORGE:INVESTIGATOR comment (or legacy ALTERLAB:INVESTIGATOR)
252
+ # Get investigation verdict from FORGE:INVESTIGATOR comment
224
253
  VERDICT=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
225
- --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body' \
254
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body' \
226
255
  | grep -oP '(?<=\*\*Verdict\*\*: )\w+' | head -1)
227
256
 
228
257
  CONFIDENCE=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
229
- --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body' \
258
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body' \
230
259
  | grep -oP '(?<=\*\*Confidence\*\*: )\w+' | head -1)
231
260
 
232
- # Get files changed from FORGE:BUILDER comment (or legacy ALTERLAB:BUILDER)
261
+ # Get files changed from FORGE:BUILDER comment
233
262
  FILES_CHANGED=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
234
- --jq '.[] | select(.body | (contains("FORGE:BUILDER") or contains("ALTERLAB:BUILDER"))) | .body' \
263
+ --jq '.[] | select(.body | contains("FORGE:BUILDER")) | .body' \
235
264
  | grep -oP '(?<=\*\*Files changed\*\*: )\d+' | head -1)
236
265
  ```
237
266
 
@@ -19,8 +19,8 @@ argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG]
19
19
 
20
20
  Parse from $ARGUMENTS:
21
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`)
22
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `{owner}/{repo}` — resolved from `forge.yaml → project`)
23
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R {owner}/{repo}`)
24
24
 
25
25
  ---
26
26
 
@@ -33,11 +33,11 @@ gh issue view {NUMBER} {GH_FLAG} --json number,title,body,labels,state,milestone
33
33
 
34
34
  # Read investigation report (required — contains decomposition plan)
35
35
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
36
- --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body'
36
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body'
37
37
  ```
38
38
 
39
39
  **Validation**:
40
- - If FORGE:INVESTIGATOR / ALTERLAB:INVESTIGATOR comment is absent → EXIT with `DECOMPOSE_RESULT: status: BLOCKED`, blocker: "No investigation report found — run investigate first"
40
+ - If FORGE:INVESTIGATOR comment is absent → EXIT with `DECOMPOSE_RESULT: status: BLOCKED`, blocker: "No investigation report found — run investigate first"
41
41
  - If investigation report has no Decomposition Assessment section, OR the assessment does not list any sub-issues → EXIT with `DECOMPOSE_RESULT: status: BLOCKED`, blocker: "Investigation report has no decomposition plan — re-run investigate with explicit decomposition scope"
42
42
 
43
43
  Extract from investigation report:
@@ -56,10 +56,10 @@ MILESTONE_TITLE=$(gh issue view {NUMBER} {GH_FLAG} --json milestone --jq '.miles
56
56
 
57
57
  ```bash
58
58
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
59
- --jq '.[] | select(.body | (contains("FORGE:DECOMPOSED") or contains("ALTERLAB:DECOMPOSED"))) | .body'
59
+ --jq '.[] | select(.body | contains("FORGE:DECOMPOSED")) | .body'
60
60
  ```
61
61
 
62
- - If `<!-- FORGE:DECOMPOSED -->` or `<!-- ALTERLAB:DECOMPOSED -->` comment exists → decomposition already complete. EXIT with `DECOMPOSE_RESULT: status: ALREADY_DONE`.
62
+ - If `<!-- FORGE:DECOMPOSED -->` comment exists → decomposition already complete. EXIT with `DECOMPOSE_RESULT: status: ALREADY_DONE`.
63
63
 
64
64
  ---
65
65
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Investigate a GitHub issue — validate it's real, determine root cause, post findings
3
- argument-hint: [issue number] [--repo RapierCraftStudios/forge] [--gh-flag "-R RapierCraftStudios/forge"]
3
+ argument-hint: [issue number] [--repo {owner}/{repo}] [--gh-flag "-R {owner}/{repo}"]
4
4
  ---
5
5
 
6
6
  # /work-on:investigate — Issue Investigation Subcommand
@@ -18,10 +18,10 @@ Standalone investigation phase for the work-on pipeline. Validates whether an is
18
18
 
19
19
  Parse from $ARGUMENTS:
20
20
  - `{NUMBER}` — issue number (required)
21
- - `--repo {GH_REPO}` — GitHub repo (default: `RapierCraftStudios/forge` when running in Forge context; for AlterLab issues use `RapierCraft/AlterLab`)
22
- - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R RapierCraftStudios/forge`)
21
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `{owner}/{repo}` — resolved from `forge.yaml → project`)
22
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R {owner}/{repo}`)
23
23
 
24
- If called from `work-on`, these are passed through. If invoked standalone, defaults apply.
24
+ If called from `work-on`, these are passed through. If invoked standalone, `--repo` and `--gh-flag` are resolved from `forge.yaml → project`.
25
25
 
26
26
  ---
27
27
 
@@ -33,8 +33,8 @@ gh api repos/{GH_REPO}/issues/{NUMBER}/comments --jq '.[] | {id: .id, body: .bod
33
33
  ```
34
34
 
35
35
  **Resume logic**:
36
- - If `<!-- FORGE:INVESTIGATOR -->` or `<!-- ALTERLAB:INVESTIGATOR -->` comment exists AND `<!-- INVESTIGATION:COMPLETE -->` is present in the SAME comment → investigation already complete, EXIT (return existing verdict to caller)
37
- - If `<!-- FORGE:INVESTIGATOR -->` or `<!-- ALTERLAB:INVESTIGATOR -->` comment exists BUT `<!-- INVESTIGATION:COMPLETE -->` is ABSENT → investigation was interrupted, delete the partial comment and restart:
36
+ - If `<!-- FORGE:INVESTIGATOR -->` comment exists AND `<!-- INVESTIGATION:COMPLETE -->` is present in the SAME comment → investigation already complete, EXIT (return existing verdict to caller)
37
+ - If `<!-- FORGE:INVESTIGATOR -->` comment exists BUT `<!-- INVESTIGATION:COMPLETE -->` is ABSENT → investigation was interrupted, delete the partial comment and restart:
38
38
  ```bash
39
39
  gh api repos/{GH_REPO}/issues/comments/{COMMENT_ID} -X DELETE
40
40
  ```
@@ -54,20 +54,16 @@ gh issue edit {NUMBER} {GH_FLAG} --remove-label "workflow:ready-to-build,workflo
54
54
 
55
55
  ### Resolve target repo and branch
56
56
 
57
- For Forge issues (repo = `RapierCraftStudios/forge`):
58
- - Key files: `commands/work-on.md`, `commands/review-pr.md`, `commands/quality-gate.md`, `commands/orchestrate.md`, `install.sh`, `CLAUDE.md`
57
+ The target repo is `{GH_REPO}` (resolved from `forge.yaml → project`). The working directory is `{REPO_PATH}` (resolved from `forge.yaml → paths.root`).
59
58
 
60
- For AlterLab issues (repo = `RapierCraft/AlterLab`):
59
+ **Domain-to-files mapping**: The repo's domain structure depends on the project. Before investigating, read the issue body and labels to identify the affected domain. Then look at the repo's directory structure under `{REPO_PATH}` to locate relevant files. Common entry points:
60
+ - Command/prompt files: `commands/`, `.claude/commands/`
61
+ - Backend services: any `services/`, `routers/`, `core/` directories
62
+ - Frontend: any `web/`, `frontend/`, `src/` directories
63
+ - Infrastructure: `.github/workflows/`, `docker-compose*.yml`, `infra/`
64
+ - Config: `forge.yaml`, `.env.example`, any `config/` directory
61
65
 
62
- | Domain | Key files |
63
- |--------|-----------|
64
- | BILLING | `routers/billing.py`, `core/pricing.py`, `services/credit_service.py` |
65
- | SCRAPING | `unified_consumer.py`, `queues.py`, `domain_playbooks.json` |
66
- | AUTH | `core/auth.py`, `routers/auth.py`, `dependencies.py` |
67
- | DATABASE | `infra/migrations/`, `models/`, `db/` |
68
- | FRONTEND | `web/src/app/`, `web/src/components/`, `web/src/lib/` |
69
- | CORTEX | `cortex_client.py`, `routers/cortex.py` |
70
- | INFRA | `.github/workflows/`, `docker-compose.yml`, `infra/traefik/` |
66
+ If the issue specifies a **Code branch** (`**Code branch**: \`{branch}\``), check out that branch — the affected files may not be on the default branch.
71
67
 
72
68
  ### Investigation steps
73
69
 
@@ -154,7 +150,7 @@ fi
154
150
 
155
151
  ```bash
156
152
  INVESTIGATION_BODY=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
157
- --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body' | head -1)
153
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body' | head -1)
158
154
  ```
159
155
 
160
156
  ### Step 3: Generate filename and metadata
@@ -166,7 +162,7 @@ MILESTONE=$(gh issue view {NUMBER} {GH_FLAG} --json milestone --jq '.milestone.t
166
162
  # Generate slug from title: lowercase, replace non-alphanumeric with hyphens, collapse, truncate
167
163
  SLUG=$(echo "$ISSUE_TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//' | cut -c1-40)
168
164
 
169
- # Derive repo short name from GH_REPO (e.g., "RapierCraftStudios/forge" → "forge")
165
+ # Derive repo short name from GH_REPO (e.g., "acme-org/acme-platform" → "acme-platform")
170
166
  REPO_SHORT=$(echo "{GH_REPO}" | sed 's|.*/||')
171
167
 
172
168
  GIST_FILENAME="${REPO_SHORT}_${NUMBER}_${SLUG}.md"
@@ -19,8 +19,8 @@ argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree P
19
19
 
20
20
  Parse from $ARGUMENTS:
21
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`)
22
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `{owner}/{repo}` — resolved from `forge.yaml → project`)
23
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R {owner}/{repo}`)
24
24
  - `--worktree {WORKTREE_PATH}` — absolute path to the git worktree
25
25
  - `--branch {BRANCH}` — feature branch name (e.g. `feat/my-feature`)
26
26
  - `--base {PR_BASE}` — PR target branch (e.g. `milestone/modular-pipeline-architecture` or `staging`)
@@ -36,7 +36,7 @@ gh issue view {NUMBER} {GH_FLAG} --json number,title,body,labels,state,milestone
36
36
 
37
37
  # Get builder comment (for branch + commit info)
38
38
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
39
- --jq '.[] | select(.body | (contains("FORGE:BUILDER") or contains("ALTERLAB:BUILDER"))) | .body'
39
+ --jq '.[] | select(.body | contains("FORGE:BUILDER")) | .body'
40
40
 
41
41
  # Check if PR already exists for this branch
42
42
  gh pr list {GH_FLAG} --head {BRANCH} --json number,state,url 2>/dev/null
@@ -45,7 +45,7 @@ gh pr list {GH_FLAG} --head {BRANCH} --json number,state,url 2>/dev/null
45
45
  **Resume check**:
46
46
  - If PR already exists AND is OPEN → skip to Phase R3 (invoke /review-pr)
47
47
  - If PR already exists AND is MERGED → return `REVIEW_RESULT: status: ALREADY_MERGED`
48
- - If no `<!-- FORGE:BUILDER -->` or `<!-- ALTERLAB:BUILDER -->` comment exists → EXIT with `REVIEW_RESULT: status: BLOCKED`, blocker: "FORGE:BUILDER comment not found — implement phase may not have completed"
48
+ - If no `<!-- FORGE:BUILDER -->` comment exists → EXIT with `REVIEW_RESULT: status: BLOCKED`, blocker: "FORGE:BUILDER comment not found — implement phase may not have completed"
49
49
 
50
50
  ---
51
51
 
@@ -29,24 +29,23 @@ Orchestrator for the full issue lifecycle: investigate → build → review →
29
29
 
30
30
  ---
31
31
 
32
- ## Multi-Repo Support
32
+ ## Project Configuration
33
33
 
34
- | Input | Resolves To |
35
- |-------|-------------|
36
- | `123` / `#123` | AlterLab (default): `RapierCraftStudios/AlterLab` |
37
- | `mcp:5` | MCP Server: `RapierCraftStudios/alterlab-mcp-server` |
38
- | `n8n:12` | n8n Node: `RapierCraftStudios/n8n-nodes-alterlab` |
34
+ Read `forge.yaml` from the repository root. If missing, tell the user to run `npx forgedock init` and stop.
39
35
 
40
- **Context Variables** (set after resolving project):
36
+ Resolve the following variables from `forge.yaml` before running any pipeline phase:
41
37
 
42
- | Variable | AlterLab | MCP | n8n |
43
- |----------|----------|-----|-----|
44
- | `GH_REPO` | `RapierCraftStudios/AlterLab` | `RapierCraftStudios/alterlab-mcp-server` | `RapierCraftStudios/n8n-nodes-alterlab` |
45
- | `REPO_PATH` | `/home/mrdubey/projects/ScraperAPI/alterlab` | `/home/mrdubey/projects/ScraperAPI/alterlab-mcp-server` | `/home/mrdubey/projects/ScraperAPI/n8n-nodes-alterlab` |
46
- | `STAGING_BRANCH` | `staging` | `main` | `main` |
47
- | `GH_FLAG` | _(empty)_ | `-R RapierCraftStudios/alterlab-mcp-server` | `-R RapierCraftStudios/n8n-nodes-alterlab` |
38
+ | Variable | Source in forge.yaml | Description |
39
+ |----------|----------------------|-------------|
40
+ | `GH_REPO` | `project.owner` + `project.repo` | Full GitHub repo identifier (`owner/repo`) |
41
+ | `REPO_PATH` | `paths.root` | Absolute path to the local repository |
42
+ | `STAGING_BRANCH` | `branches.staging` | Branch for fast-lane PRs (no milestone) |
43
+ | `WORKTREE_BASE` | `paths.worktree_base` | Directory where git worktrees are created |
44
+ | `GH_FLAG` | _(empty for default repo; `-R owner/repo` for satellites)_ | Extra flag for `gh` CLI satellite repo calls |
48
45
 
49
- Satellite repos (MCP, n8n) have no staging — fast-lane PRs go to `main`.
46
+ **Multi-repo routing** (optional): If `forge.yaml` contains a `repos.satellites` list, build the prefix routing table from it. Each satellite entry has `prefix`, `repo`, `staging_branch`, and `local_path`. Issues without a prefix route to the default `GH_REPO`. Satellite repos have no staging — their fast-lane PRs go to their configured `staging_branch` (typically `main`).
47
+
48
+ If no `repos.satellites` section exists, only the primary repo is available — all issues route to `GH_REPO`.
50
49
 
51
50
  ---
52
51
 
@@ -189,7 +188,7 @@ Branch slug from title (lowercase, hyphenated, max 40 chars). Prefix: `fix/` (bu
189
188
  cd {REPO_PATH}
190
189
  git fetch origin
191
190
  BRANCH="fix/{slug}-{NUMBER}"
192
- git worktree add /home/mrdubey/projects/ScraperAPI/{WT_PREFIX}-worktrees/{BRANCH} -b {BRANCH} origin/{PR_BASE}
191
+ git worktree add {WORKTREE_BASE}/{BRANCH} -b {BRANCH} origin/{PR_BASE}
193
192
  ```
194
193
 
195
194
  ### 3F: Implement
@@ -204,7 +203,7 @@ Fix HIGH/MEDIUM findings. Max 2 iterations. Skip for 1-file config/docs edits.
204
203
 
205
204
  ### 3G: Format and verify
206
205
  - Python: `black` + `isort` + `py_compile`
207
- - TypeScript (AlterLab): `prettier --write` + `tsc --noEmit` (BLOCKING if fails)
206
+ - TypeScript (primary repo): `prettier --write` + `tsc --noEmit` (BLOCKING if fails)
208
207
  - TypeScript (satellite): `npm run build` + `prettier --write`
209
208
 
210
209
  ### 3H: Frontend proxy wiring check (MANDATORY)
@@ -62,15 +62,31 @@ Orchestrator for the full issue lifecycle: investigate → decompose (if needed)
62
62
 
63
63
  ---
64
64
 
65
- ## Multi-Repo Support
65
+ ## Project Configuration
66
66
 
67
- | Input | Resolves To | GH_REPO | STAGING_BRANCH |
68
- |-------|-------------|---------|----------------|
69
- | `123` / `#123` | AlterLab (default) | `RapierCraft/AlterLab` | `staging` |
70
- | `mcp:5` | MCP Server | `RapierCraft/alterlab-mcp-server` | `main` |
71
- | `n8n:12` | n8n Node | `RapierCraft/n8n-nodes-alterlab` | `main` |
67
+ Read `forge.yaml` from the repository root before processing any issue.
72
68
 
73
- Satellite repos (MCP, n8n) have no staging — fast-lane PRs go to `main`.
69
+ If `forge.yaml` is missing: stop and tell the user to run `npx forgedock init` to generate it.
70
+
71
+ **Resolve these values from `forge.yaml`**:
72
+
73
+ | Variable | Source field | Notes |
74
+ |----------|-------------|-------|
75
+ | `GH_REPO` | `project.owner` + `/` + `project.repo` | e.g. `acme-org/acme-platform` |
76
+ | `GH_FLAG` | `-R {GH_REPO}` | Passed to all `gh` commands |
77
+ | `REPO_PATH` | `paths.root` | Absolute path to repo root |
78
+ | `WORKTREE_BASE` | `paths.worktree_base` | Base dir for git worktrees |
79
+ | `STAGING_BRANCH` | `branches.staging` | Fast-lane PR target |
80
+ | `PROJECT_BOARD_OWNER` | `project_board.owner` (or `project.owner` as fallback) | For `gh project` commands |
81
+ | `PROJECT_BOARD_NUMBER` | `project_board.project_number` (or `1` as fallback) | Project number in `gh project` commands |
82
+
83
+ **Multi-repo routing** (when `forge.yaml → repos` section is present):
84
+
85
+ Parse issue input for a prefix (`<prefix>:<number>`). Look up `<prefix>` in `forge.yaml → repos.satellites[]`. Use that satellite's `repo` and `staging_branch` as `GH_REPO` and `STAGING_BRANCH`. If no prefix is given, use the default (`project.owner/project.repo`).
86
+
87
+ If `forge.yaml → repos` is absent, only the default repo is available — prefixed issue numbers are invalid.
88
+
89
+ Satellite repos (those without a `staging` branch) receive fast-lane PRs directly to `main`.
74
90
 
75
91
  ---
76
92
 
@@ -100,12 +116,12 @@ Add issue to project, set Status=In Progress, Lane, Component, Priority, Workflo
100
116
 
101
117
  ## Phase 1: Investigation
102
118
 
103
- **Skip if**: `<!-- FORGE:INVESTIGATOR -->` or `<!-- ALTERLAB:INVESTIGATOR -->` exists with `<!-- INVESTIGATION:COMPLETE -->` in the SAME comment.
119
+ **Skip if**: `<!-- FORGE:INVESTIGATOR -->` exists with `<!-- INVESTIGATION:COMPLETE -->` in the SAME comment.
104
120
 
105
121
  **Partial investigation**: If investigator comment exists BUT `<!-- INVESTIGATION:COMPLETE -->` is ABSENT → investigation was interrupted. Delete the partial comment and restart:
106
122
  ```bash
107
123
  COMMENT_ID=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
108
- --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .id')
124
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .id')
109
125
  gh api repos/{GH_REPO}/issues/comments/$COMMENT_ID -X DELETE
110
126
  ```
111
127
 
@@ -171,20 +187,14 @@ Mission: Validate whether the issue is real. Assume description is wrong until p
171
187
 
172
188
  **Resolve target repo and branch**:
173
189
 
174
- For Forge issues (repo = `RapierCraftStudios/forge`):
175
- - Key files: `commands/work-on.md`, `commands/review-pr.md`, `commands/quality-gate.md`, `commands/orchestrate.md`, `install.sh`, `CLAUDE.md`
190
+ Read `forge.yaml → review.tech_stack` and `forge.yaml → review.key_paths` (if present) to identify which files are most relevant for the affected domain. If the `review` section is absent, use the issue labels, title keywords, and the affected files listed in the issue body to determine the domain. Start with the files the issue explicitly names, then expand to callers and related modules.
191
+
192
+ **Workflow pipeline issues** (repo is a ForgeDock installation):
193
+ - Key files: `commands/work-on.md`, `commands/review-pr.md`, `commands/quality-gate.md`, `commands/orchestrate.md`, `forge.yaml`, `bin/forgedock.mjs`
176
194
 
177
- For AlterLab issues (repo = `RapierCraft/AlterLab`):
195
+ **Application issues** (all other repos):
178
196
 
179
- | Domain | Key files |
180
- |--------|-----------|
181
- | BILLING | `routers/billing.py`, `core/pricing.py`, `services/credit_service.py` |
182
- | SCRAPING | `unified_consumer.py`, `queues.py`, `domain_playbooks.json` |
183
- | AUTH | `core/auth.py`, `routers/auth.py`, `dependencies.py` |
184
- | DATABASE | `infra/migrations/`, `models/`, `db/` |
185
- | FRONTEND | `web/src/app/`, `web/src/components/`, `web/src/lib/` |
186
- | CORTEX | `cortex_client.py`, `routers/cortex.py` |
187
- | INFRA | `.github/workflows/`, `docker-compose.yml`, `infra/traefik/` |
197
+ Use `forge.yaml → review.tech_stack` and the issue domain labels to identify entry points. If `forge.yaml → review.key_paths` lists domain-to-file mappings, use that table directly. Otherwise, infer key files from the issue body's Affected Files section.
188
198
 
189
199
  **INFRA domain known footguns** (read before writing any `.github/workflows/*.yml` changes):
190
200
  - **appleboy/ssh-action Go template preprocessing**: Any `{{` in a `script:` block is interpreted as a Go template directive **before the script reaches SSH**. This means `docker ps --format '{{.Names}}'` and `docker inspect --format '{{index .RepoTags 0}}'` will crash the action with exit 1. Both function calls (`{{index .X Y}}`) AND field accessors (`{{.Names}}`, `{{.Status}}`) fail on the action's empty data context. Shell error handlers (`|| fallback`, `set -e`, `2>/dev/null`) are bypassed because the failure is client-side. Always use `docker inspect IMAGE | jq -r '.[0].RepoTags[0]'` and `docker ps --format json | jq -r '.Names'` patterns in `appleboy/ssh-action` scripts. (Ref: forge#226 — 6-day silent deploy failure masked by `continue-on-error: true`)
@@ -194,11 +204,10 @@ For AlterLab issues (repo = `RapierCraft/AlterLab`):
194
204
  2. Read domain files — start with key files for the affected domain
195
205
  2.5. **Existing system search (conditional)**: If the issue describes a gap in a functional capability — content not being distributed, notifications not sending, jobs not running, data not being synced — MUST search for an existing automated system before proposing a new one. The issue body may name a specific tool or path (e.g., `reddit-bot/`, `marketing/`) — do NOT anchor on that path alone. Expand the search to all service layers:
196
206
  ```bash
197
- # For AlterLab: check Herald, worker, and scheduler for the capability
198
- grep -rn "{capability_keyword}" services/herald/app/scheduler/ services/herald/app/content/ services/worker/
199
- grep -rn "{capability_keyword}" services/ --include="*.py" -l | head -20
207
+ # Check all service layers for the capability (adapt paths to your project structure)
208
+ grep -rn "{capability_keyword}" {REPO_PATH}/services/ --include="*.py" -l | head -20
200
209
  # Look for scheduled jobs, automated runners, existing integrations
201
- grep -rn "scheduler\|celery\|cron\|nightly\|periodic" services/ --include="*.py" -l | head -10
210
+ grep -rn "scheduler\|celery\|cron\|nightly\|periodic" {REPO_PATH}/services/ --include="*.py" -l | head -10
202
211
  ```
203
212
  If an existing system is found that already handles the capability: the fix MUST route through the existing system (fix its config, env var, or gate) — NOT create a new parallel tool. Document the existing system in the investigation report and make it the centerpiece of the recommendation. This check is especially critical when the issue references a standalone tool directory (`reddit-bot/`, `scripts/`, `tools/`) — those directories often duplicate functionality that a service already owns. (Ref: forge#279 — investigator anchored on `reddit-bot/` from issue body, never checked `services/herald/app/scheduler/`, built parallel PRAW integration alongside Herald's existing automated crosspost scheduler)
204
213
  3. Verify claims — does the code actually have the problem described?
@@ -308,13 +317,13 @@ gh issue close {NUMBER} {GH_FLAG} --comment "Closing as invalid: {reason from in
308
317
  ```bash
309
318
  gh issue view {NUMBER} {GH_FLAG} --json number,title,body,labels,state,milestone
310
319
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
311
- --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body'
320
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body'
312
321
  ```
313
322
 
314
323
  **MANDATORY — Owner override detection**: After reading the investigation comment, read ALL comments on the issue to check for owner override signals:
315
324
  ```bash
316
325
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
317
- --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR")) | not) | {author: .user.login, body: .body}'
326
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR") | not) | {author: .user.login, body: .body}'
318
327
  ```
319
328
 
320
329
  Scan non-agent comments for override signals — phrases like "do not", "do NOT", "instead", "revert", "remove this", "override", "actually", or explicit disagreement with the investigation's recommendation. If an override comment is found from a repo owner or admin (not a bot):
@@ -402,7 +411,7 @@ gh issue edit {NUMBER} {GH_FLAG} \
402
411
 
403
412
  <!-- FORGE:PHASE_COMPLETE — Entering Phase 3 (Build). See Universal Phase Dispatcher: sub-phases 3A–3M execute in sequence. No sub-phase completion is terminal. -->
404
413
 
405
- **Skip if**: `<!-- FORGE:BUILDER -->` or `<!-- ALTERLAB:BUILDER -->` exists.
414
+ **Skip if**: `<!-- FORGE:BUILDER -->` exists.
406
415
 
407
416
  **CRITICAL: You MUST execute ALL sub-phases 3A–3M in order. Do NOT skip phases 3C.5 (context) or 3C.6 (architect) — they post mandatory `FORGE:CONTEXT` and `FORGE:ARCHITECT` comments that Phase 3F reads as its primary input. Skipping them degrades build quality and causes review findings. After each sub-phase, continue to the next — no sub-phase is terminal.**
408
417
 
@@ -412,11 +421,11 @@ gh issue view {NUMBER} {GH_FLAG} --json number,title,body,labels,state,milestone
412
421
 
413
422
  # Read investigation report
414
423
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
415
- --jq '.[] | select(.body | (contains("FORGE:INVESTIGATOR") or contains("ALTERLAB:INVESTIGATOR"))) | .body'
424
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body'
416
425
 
417
426
  # Check if build already completed
418
427
  gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
419
- --jq '.[] | select(.body | (contains("FORGE:BUILDER") or contains("ALTERLAB:BUILDER"))) | .body'
428
+ --jq '.[] | select(.body | contains("FORGE:BUILDER")) | .body'
420
429
  ```
421
430
 
422
431
  If no investigation comment with `<!-- INVESTIGATION:COMPLETE -->` → STOP (investigation not complete).
@@ -745,7 +754,7 @@ black {PYTHON_FILES} && isort {PYTHON_FILES} && python -m py_compile {PYTHON_FIL
745
754
  ```
746
755
  `py_compile` failures are BLOCKING.
747
756
 
748
- **TypeScript (AlterLab)**:
757
+ **TypeScript (primary repo — has tsconfig.json)**:
749
758
  ```bash
750
759
  cd {WORKTREE_PATH}
751
760
  prettier --write {TS_FILES} && tsc --noEmit
@@ -984,13 +993,16 @@ If multi-phase (`HAS_PHASE_HEADINGS > 0` AND `REMAINING_BEFORE > 0`): do NOT che
984
993
  If single-phase or final phase: check off all `[ ]` items, add PR reference.
985
994
 
986
995
  ### 6B: Project board update (Status=Done, Workflow=Merged)
996
+
997
+ Resolve `PROJECT_BOARD_OWNER` and `PROJECT_BOARD_NUMBER` from `forge.yaml → project_board` (fields: `owner`, `project_number`). Fall back to `forge.yaml → project.owner` and project number `1` if `project_board` section is absent.
998
+
987
999
  ```bash
988
1000
  ISSUE_URL="https://github.com/{GH_REPO}/issues/{NUMBER}"
989
- ITEM_ID=$(gh project item-list 1 --owner RapierCraft --format json --limit 200 \
1001
+ ITEM_ID=$(gh project item-list {PROJECT_BOARD_NUMBER} --owner {PROJECT_BOARD_OWNER} --format json --limit 200 \
990
1002
  --jq ".items[] | select(.content.url == \"$ISSUE_URL\") | .id" 2>/dev/null | head -1)
991
1003
  ```
992
1004
 
993
- If found: set Status=Done, Workflow=Merged using project field IDs.
1005
+ If found: set Status=Done, Workflow=Merged using project field IDs from `forge.yaml → project_board.field_ids`.
994
1006
 
995
1007
  ### 6C: Ensure issue is closed
996
1008
 
package/docs/CODEX.md CHANGED
@@ -69,7 +69,7 @@ When a repo-local adapter exists under `.agents/skills/`, it becomes authoritati
69
69
  - different default GitHub repo resolution
70
70
  - Codex-native worktree roots
71
71
  - Forge-specific review heuristics
72
- - best-effort handling of project-board steps that are AlterLab-specific upstream
72
+ - best-effort handling of project-board steps that may be project-specific upstream
73
73
 
74
74
  ## Trust and Global Config
75
75