forgedock 1.0.1 → 1.0.3

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 (43) hide show
  1. package/README.md +19 -2
  2. package/bin/forgedock.mjs +3084 -80
  3. package/bin/github-app-manifest.json +24 -0
  4. package/bin/tui.mjs +702 -0
  5. package/commands/analytics.md +129 -52
  6. package/commands/audit-agents.md +29 -5
  7. package/commands/audit.md +55 -17
  8. package/commands/autopilot.md +11 -6
  9. package/commands/cleanup.md +44 -24
  10. package/commands/deploy-info.md +7 -3
  11. package/commands/forge-stats.md +13 -4
  12. package/commands/forgedock-init.md +534 -0
  13. package/commands/geo-audit.md +114 -26
  14. package/commands/incident-response.md +4 -1
  15. package/commands/issue.md +26 -25
  16. package/commands/milestone.md +80 -59
  17. package/commands/orchestrate.md +38 -21
  18. package/commands/pipeline-health.md +26 -15
  19. package/commands/qa-sweep.md +68 -5
  20. package/commands/quality-gate.md +18 -0
  21. package/commands/review-pr-agents.md +58 -90
  22. package/commands/review-pr.md +58 -16
  23. package/commands/rollback.md +8 -5
  24. package/commands/security-audit.md +68 -12
  25. package/commands/sync-ecosystem.md +196 -156
  26. package/commands/work-on/build/architect.md +2 -2
  27. package/commands/work-on/build/context.md +2 -2
  28. package/commands/work-on/build/implement.md +3 -3
  29. package/commands/work-on/build/validate.md +3 -3
  30. package/commands/work-on/build.md +6 -6
  31. package/commands/work-on/close.md +59 -30
  32. package/commands/work-on/decompose.md +6 -6
  33. package/commands/work-on/investigate.md +16 -20
  34. package/commands/work-on/review.md +4 -4
  35. package/commands/work-on-monolithic.md +15 -16
  36. package/commands/work-on.md +45 -33
  37. package/docs/CODEX.md +1 -1
  38. package/docs/CONFIG.md +398 -0
  39. package/docs/WORKFLOW.md +115 -72
  40. package/package.json +1 -1
  41. package/scripts/verify-host-headers.sh +14 -9
  42. package/scripts/verify-route-registration.sh +10 -10
  43. package/commands/failure-recon.md +0 -375
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Detect API changes, sync satellite repos, and publish releases (SDKs, MCP server, n8n node)
2
+ description: Detect API changes, sync satellite repos, and publish releases
3
3
  argument-hint: [check | auto | status | publish | PR-number]
4
4
  ---
5
5
 
@@ -7,7 +7,56 @@ argument-hint: [check | auto | status | publish | PR-number]
7
7
 
8
8
  **Input**: $ARGUMENTS
9
9
 
10
- When the AlterLab API surface changes (new parameters, endpoints, modes, pricing), satellite projects (SDKs, MCP server, n8n node) need updates. This command detects what changed, creates tracking issues, checks publication status, and publishes releases.
10
+ When the `{project.name}` API surface changes (new parameters, endpoints, modes, pricing), satellite projects need updates. This command detects what changed, creates tracking issues, checks publication status, and publishes releases.
11
+
12
+ ---
13
+
14
+ ## Config Preamble
15
+
16
+ Before any phase runs, build the ecosystem registry from `forge.yaml → repos.satellites`.
17
+
18
+ ```bash
19
+ # Read satellite repos from forge.yaml
20
+ # Each entry provides: prefix, repo, staging_branch, local_path
21
+ # (Optional: package, publish_workflow — read from each satellite's package.json / workflow files)
22
+
23
+ # Gate: if repos section is absent or has no satellites, stop here
24
+ if [ -z "$(yq '.repos.satellites // empty' forge.yaml 2>/dev/null)" ]; then
25
+ echo "No satellite repos configured in forge.yaml → repos.satellites."
26
+ echo "Add entries to forge.yaml to use /sync-ecosystem:"
27
+ echo ""
28
+ echo " repos:"
29
+ echo " satellites:"
30
+ echo " - prefix: \"sdk\""
31
+ echo " repo: \"your-org/your-sdk\""
32
+ echo " staging_branch: \"main\""
33
+ echo " local_path: \"/home/youruser/projects/your-sdk\""
34
+ exit 0
35
+ fi
36
+
37
+ # For each satellite entry, resolve template variables:
38
+ # {COMPONENT} = prefix (e.g. "mcp", "sdk", "n8n")
39
+ # {GH_REPO} = repo (e.g. "your-org/your-mcp-server")
40
+ # {REPO_PATH} = local_path (e.g. "/home/youruser/projects/your-mcp-server")
41
+ # {STAGING_BRANCH} = staging_branch (e.g. "main")
42
+ # {PACKAGE} = read from {REPO_PATH}/package.json "name" field (npm)
43
+ # or {REPO_PATH}/pyproject.toml "name" field (PyPI)
44
+ # {PUBLISH_WORKFLOW} = read from {REPO_PATH}/.github/workflows/ — the workflow
45
+ # triggered by GitHub Release (look for "on: release:")
46
+
47
+ # For monorepo satellites (multiple packages in one repo):
48
+ # Use a subpath qualifier in local_path, e.g.:
49
+ # local_path: "/home/youruser/projects/myproject"
50
+ # subpaths:
51
+ # python_sdk: "sdk/python"
52
+ # node_sdk: "sdk/node"
53
+ # Then {REPO_PATH}/sdk/python and {REPO_PATH}/sdk/node are the per-SDK roots.
54
+
55
+ PROJECT_NAME=$(yq '.project.name' forge.yaml)
56
+ PROJECT_BOARD_OWNER=$(yq '.project_board.owner // .project.owner' forge.yaml)
57
+ PROJECT_BOARD_NUMBER=$(yq '.project_board.project_number // empty' forge.yaml)
58
+ PROJECT_BOARD_ID=$(yq '.project_board.project_id // empty' forge.yaml)
59
+ ```
11
60
 
12
61
  ---
13
62
 
@@ -15,17 +64,33 @@ When the AlterLab API surface changes (new parameters, endpoints, modes, pricing
15
64
 
16
65
  ### Satellite Projects
17
66
 
18
- | Component | Repo | Local Path | Package | Publish Trigger |
19
- |-----------|------|------------|---------|-----------------|
20
- | MCP Server | `RapierCraft/alterlab-mcp-server` | `/home/mrdubey/projects/ScraperAPI/alterlab-mcp-server` | `alterlab-mcp-server` (npm) | GitHub Release → `publish-npm.yml` + `publish-mcp-registry.yml` |
21
- | n8n Node | `RapierCraft/n8n-nodes-alterlab` | `/home/mrdubey/projects/ScraperAPI/n8n-nodes-alterlab` | `n8n-nodes-alterlab` (npm) | GitHub Release → `publish.yml` |
22
- | Python SDK | monorepo `sdk/python/` | `/home/mrdubey/projects/ScraperAPI/alterlab/sdk/python` | `alterlab` (PyPI) | Manual `workflow_dispatch` → `publish-sdks.yml` (input: `python` or `both`) |
23
- | Node SDK | monorepo `sdk/node/` | `/home/mrdubey/projects/ScraperAPI/alterlab/sdk/node` | `@alterlab/sdk` (npm) | Manual `workflow_dispatch` → `publish-sdks.yml` (input: `node` or `both`) |
67
+ Build the ecosystem registry from `forge.yaml → repos.satellites`. Each entry in the `satellites` array becomes one row in the registry:
68
+
69
+ | Field in `forge.yaml` | Maps to |
70
+ |-----------------------|---------|
71
+ | `satellites[].prefix` | `{COMPONENT}` — the short identifier used in issue routing (e.g. `mcp:5`) |
72
+ | `satellites[].repo` | `{GH_REPO}` — full `owner/repo` used in all `gh` commands |
73
+ | `satellites[].local_path` | `{REPO_PATH}` — absolute local path used in all `cd` commands |
74
+ | `satellites[].staging_branch` | `{STAGING_BRANCH}` — PR target branch for this satellite |
75
+ | Read from `{REPO_PATH}/package.json` | `{PACKAGE}` — npm package name |
76
+ | Read from `{REPO_PATH}/.github/workflows/` | `{PUBLISH_WORKFLOW}` — workflow file triggered on release |
77
+
78
+ **Example registry output** (what the agent constructs from your `forge.yaml`):
79
+
80
+ ```
81
+ Component: {COMPONENT}
82
+ Repo: {GH_REPO}
83
+ Local path: {REPO_PATH}
84
+ Package: {PACKAGE} ({REGISTRY: npm or PyPI})
85
+ Publish trigger: GitHub Release → {PUBLISH_WORKFLOW}
86
+ ```
87
+
88
+ Iterate over all `repos.satellites` entries before proceeding to Phase 1.
24
89
 
25
90
  ### Version Bump Rules
26
91
 
27
- - **Satellite repos** (MCP, n8n): Version lives in `package.json`. Must be bumped, committed, and pushed to `main` BEFORE creating the GitHub Release tag. The release tag must match the version (`v{VERSION}`).
28
- - **SDKs** (Python, Node): Version lives in `pyproject.toml` / `package.json` in the monorepo. Must be bumped, committed, and pushed to `main` BEFORE triggering `publish-sdks.yml`.
92
+ - **Satellite repos** (separate GitHub repos): Version lives in `package.json`. Must be bumped, committed, and pushed to `main` BEFORE creating the GitHub Release tag. The release tag must match the version (`v{VERSION}`).
93
+ - **Monorepo packages** (SDKs or tools inside a single repo): Version lives in `pyproject.toml` / `package.json` in the monorepo. Must be bumped, committed, and pushed to `main` BEFORE triggering the publish workflow.
29
94
 
30
95
  ---
31
96
 
@@ -37,7 +102,7 @@ When the AlterLab API surface changes (new parameters, endpoints, modes, pricing
37
102
  | `auto` | Same as check, but auto-create issues in satellite repos |
38
103
  | `status` | Check publication status of ALL ecosystem components (code vs published versions) |
39
104
  | `publish` | Bump versions, cut releases, and trigger publishes for all components with unpublished changes |
40
- | `publish mcp` / `publish n8n` / `publish sdks` | Publish a specific component |
105
+ | `publish {COMPONENT}` | Publish a specific component by prefix |
41
106
  | `PR-number` (e.g., `#1500`) | Analyze a specific PR for ecosystem impact |
42
107
 
43
108
  ---
@@ -58,24 +123,22 @@ gh pr view {PR_NUMBER} --json title,body,files
58
123
 
59
124
  ```bash
60
125
  # Find recent merged PRs to staging or main (last 7 days)
61
- gh pr list --state merged --base staging --limit 20 --json number,title,mergedAt,files
62
- gh pr list --state merged --base main --limit 10 --json number,title,mergedAt,files
126
+ gh pr list --state merged --base {branches.staging} --limit 20 --json number,title,mergedAt,files
127
+ gh pr list --state merged --base {branches.default} --limit 10 --json number,title,mergedAt,files
63
128
  ```
64
129
 
65
130
  ### Analyze changes for sync triggers
66
131
 
67
- Scan the changed files for API surface modifications:
132
+ Scan the changed files for API surface modifications. The file patterns below are illustrative — adapt to your project's structure:
68
133
 
69
134
  | File Pattern | Trigger Type | Satellite Impact |
70
135
  |-------------|--------------|------------------|
71
- | `services/api/app/routers/scrape*.py` | New/changed scrape parameters | SDKs, MCP, n8n |
72
- | `services/api/app/schemas/scrape*.py` | Schema changes | SDKs, MCP, n8n |
73
- | `services/api/app/routers/extract*.py` | Extraction changes | MCP, n8n |
74
- | `services/api/app/core/pricing.py` | Pricing/credit changes | MCP (estimate tool), SDK docs |
75
- | `services/api/app/routers/*.py` (new file) | New endpoint | SDKs, MCP |
76
- | `services/api/app/auth/` | Auth changes | n8n credentials, SDK auth, MCP config |
77
- | `sdk/python/` | SDK already updated | Check if n8n/MCP need matching update |
78
- | `sdk/node/` | SDK already updated | Check if n8n/MCP need matching update |
136
+ | API router files (`routers/`, `controllers/`) | New/changed parameters or endpoints | All satellites |
137
+ | Schema files (`schemas/`, `types/`) | Schema changes | All satellites |
138
+ | Pricing/billing files | Pricing/credit changes | Satellites exposing cost estimates |
139
+ | New router/controller file | New endpoint | All satellites |
140
+ | Auth files | Auth changes | All satellite credential configs |
141
+ | Existing SDK subpath | SDK already updated | Check if other satellites need matching update |
79
142
 
80
143
  **Read the actual diff** for each matched file to understand what specifically changed (new parameter, renamed field, new endpoint, etc.).
81
144
 
@@ -91,32 +154,28 @@ changes:
91
154
  - description: "Added `cookies` parameter to /api/v1/scrape"
92
155
  source_pr: "#1800"
93
156
  impacts:
94
- - repo: "RapierCraft/alterlab-mcp-server"
157
+ - repo: "{GH_REPO}" # e.g. your-org/your-mcp-server
95
158
  what: "Add `cookies` param to scrape tool schema"
96
- files: ["src/tools/scrape.ts"]
97
- - repo: "RapierCraft/n8n-nodes-alterlab"
159
+ files: ["{REPO_PATH}/src/tools/scrape.ts"]
160
+ - repo: "{GH_REPO}" # e.g. your-org/your-n8n-node
98
161
  what: "Add `cookies` field to Scrape operation"
99
- files: ["nodes/AlterLab/AlterLab.node.ts"]
100
- - repo: "sdk/python" (monorepo)
162
+ files: ["{REPO_PATH}/nodes/YourNode/YourNode.node.ts"]
163
+ - repo: "{GH_REPO} (monorepo)" # e.g. your-org/your-project
101
164
  what: "Add `cookies` kwarg to client.scrape()"
102
- files: ["sdk/python/alterlab/client.py"]
103
- - repo: "sdk/node" (monorepo)
165
+ files: ["{REPO_PATH}/sdk/python/src/client.py"]
166
+ - repo: "{GH_REPO} (monorepo)"
104
167
  what: "Add `cookies` option to scrape()"
105
- files: ["sdk/node/src/index.ts"]
168
+ files: ["{REPO_PATH}/sdk/node/src/index.ts"]
106
169
  ```
107
170
 
108
171
  **Check if sync is already done**: Before creating issues, check if the satellite repo already has the change:
109
172
 
110
173
  ```bash
111
- # For MCP server (check git main, not local disk — local may be stale):
112
- cd /home/mrdubey/projects/ScraperAPI/alterlab-mcp-server && git fetch origin main && git show origin/main:src/tools/scrape.ts | grep -n "cookies"
113
-
114
- # For n8n node:
115
- cd /home/mrdubey/projects/ScraperAPI/n8n-nodes-alterlab && git fetch origin main && git show origin/main:nodes/AlterLab/AlterLab.node.ts | grep -n "cookies"
174
+ # For each satellite repo (check git main, not local disk — local may be stale):
175
+ cd {REPO_PATH} && git fetch origin main && git show origin/main:{RELEVANT_FILE} | grep -n "{FEATURE}"
116
176
 
117
- # For SDKs (check origin/main in monorepo):
118
- cd /home/mrdubey/projects/ScraperAPI/alterlab && git show origin/main:sdk/python/alterlab/client.py | grep -n "cookies"
119
- cd /home/mrdubey/projects/ScraperAPI/alterlab && git show origin/main:sdk/node/src/index.ts | grep -n "cookies"
177
+ # For monorepo satellites with subpaths:
178
+ cd {REPO_PATH} && git show origin/main:{SUBPATH}/{RELEVANT_FILE} | grep -n "{FEATURE}"
120
179
  ```
121
180
 
122
181
  If the change already exists in a satellite's `origin/main` → skip it (code synced). Then check if it's also **published** (see Phase 5).
@@ -139,10 +198,10 @@ Report what needs syncing without creating issues:
139
198
 
140
199
  | Repo | Change Needed | Source PR | Status |
141
200
  |------|--------------|-----------|--------|
142
- | MCP Server | Add `cookies` to scrape tool | #1800 | Needs sync |
143
- | n8n Node | Add `cookies` to Scrape op | #1800 | Needs sync |
144
- | Python SDK | Already has `cookies` | #1800 | In sync |
145
- | Node SDK | Add `cookies` option | #1800 | Needs sync |
201
+ | {GH_REPO} | Add `cookies` to scrape tool | #1800 | Needs sync |
202
+ | {GH_REPO} | Add `cookies` to Scrape op | #1800 | Needs sync |
203
+ | {GH_REPO} (sdk/python) | Already has `cookies` | #1800 | In sync |
204
+ | {GH_REPO} (sdk/node) | Add `cookies` option | #1800 | Needs sync |
146
205
 
147
206
  Run `/sync-ecosystem auto` to create issues automatically.
148
207
  ```
@@ -165,7 +224,7 @@ gh issue create -R {TARGET_REPO} \
165
224
 
166
225
  ## Root Cause (if known)
167
226
 
168
- The upstream AlterLab API changed in PR #{SOURCE_PR}: {brief description of the change}. This satellite repo must be updated to stay in sync.
227
+ The upstream {project.name} API changed in PR #{SOURCE_PR}: {brief description of the change}. This satellite repo must be updated to stay in sync.
169
228
 
170
229
  ## Affected Files
171
230
 
@@ -176,14 +235,14 @@ Files that need changes:
176
235
  ## Acceptance Criteria
177
236
 
178
237
  - [ ] {Specific sync criterion — e.g., new parameter available in tool schema}
179
- - [ ] Changes passed through to AlterLab API correctly
238
+ - [ ] Changes passed through to {project.name} API correctly
180
239
  - [ ] TypeScript types / validation schemas updated
181
240
 
182
241
  ## Context
183
242
 
184
243
  **Source**: {SOURCE_REPO} PR #{SOURCE_PR}
185
244
  **Change**: {description of upstream API change}
186
- **Detected by**: \`/sync-ecosystem\`
245
+ **Detected by**: `/sync-ecosystem`
187
246
 
188
247
  ## API Reference
189
248
 
@@ -191,18 +250,18 @@ Files that need changes:
191
250
  BODY_EOF
192
251
  )"
193
252
 
194
- # For monorepo issues (SDKs, chrome extension):
253
+ # For monorepo issues (SDKs, packages inside a single repo):
195
254
  gh issue create \
196
255
  --title "feat(sync): {description of what API change needs to be reflected}" \
197
256
  --label "feature,P2" \
198
257
  --body "$(cat <<'BODY_EOF'
199
258
  ## Problem
200
259
 
201
- {1-3 sentences: what API or schema change needs to be reflected in this SDK or extension. What will be out of sync if not updated.}
260
+ {1-3 sentences: what API or schema change needs to be reflected in this SDK or package. What will be out of sync if not updated.}
202
261
 
203
262
  ## Root Cause (if known)
204
263
 
205
- The upstream AlterLab API changed in PR #{SOURCE_PR}: {brief description of the change}. This SDK must be updated to expose the new capability.
264
+ The upstream {project.name} API changed in PR #{SOURCE_PR}: {brief description of the change}. This SDK must be updated to expose the new capability.
206
265
 
207
266
  ## Affected Files
208
267
 
@@ -220,24 +279,32 @@ Files that need changes:
220
279
 
221
280
  **Source**: {SOURCE_REPO} PR #{SOURCE_PR}
222
281
  **Change**: {description of upstream API change}
223
- **Detected by**: \`/sync-ecosystem\`
282
+ **Detected by**: `/sync-ecosystem`
224
283
  BODY_EOF
225
284
  )"
226
285
  ```
227
286
 
228
287
  ### Add sync issues to Project board
229
288
 
230
- For each created issue, add it to the GitHub Project with `Lane=Sync` and the correct `Component`. Reference `~/projects/forge/docs/WORKFLOW.md` → "Project Board Integration" for field IDs.
289
+ For each created issue, add it to the GitHub Project with `Lane=Sync` and the correct `Component`. Reference `docs/WORKFLOW.md` → "Project Board Integration" for field IDs (or read them from `forge.yaml → project_board`).
231
290
 
232
291
  ```bash
233
292
  # For each created issue:
234
293
  ISSUE_URL="https://github.com/{TARGET_REPO}/issues/${ISSUE_NUM}"
235
- ITEM_ID=$(gh project item-add 1 --owner RapierCraft --url "$ISSUE_URL" --format json --jq '.id' 2>/dev/null)
294
+ ITEM_ID=$(gh project item-add {project_board.project_number} --owner {project_board.owner} --url "$ISSUE_URL" --format json --jq '.id' 2>/dev/null)
236
295
  if [ -n "$ITEM_ID" ]; then
237
- gh project item-edit --project-id PVT_kwHOCx3gR84BSK2L --id "$ITEM_ID" --field-id PVTSSF_lAHOCx3gR84BSK2Lzg_yF6E --single-select-option-id f75ad846 2>/dev/null || true # Status=Todo
238
- gh project item-edit --project-id PVT_kwHOCx3gR84BSK2L --id "$ITEM_ID" --field-id PVTSSF_lAHOCx3gR84BSK2Lzg_yF98 --single-select-option-id c0c37d33 2>/dev/null || true # Lane=Sync
239
- gh project item-edit --project-id PVT_kwHOCx3gR84BSK2L --id "$ITEM_ID" --field-id PVTSSF_lAHOCx3gR84BSK2Lzg_yF-o --single-select-option-id {COMPONENT_OPTION_ID} 2>/dev/null || true # Component (MCP Server/n8n Node/Python SDK/Node SDK)
240
- gh project item-edit --project-id PVT_kwHOCx3gR84BSK2L --id "$ITEM_ID" --field-id PVTSSF_lAHOCx3gR84BSK2Lzg_yF8o --single-select-option-id 4d95eef3 2>/dev/null || true # Priority=P2
296
+ gh project item-edit --project-id {project_board.project_id} --id "$ITEM_ID" \
297
+ --field-id {project_board.field_ids.status} \
298
+ --single-select-option-id {project_board.option_ids.status.todo} 2>/dev/null || true
299
+ gh project item-edit --project-id {project_board.project_id} --id "$ITEM_ID" \
300
+ --field-id {project_board.field_ids.lane} \
301
+ --single-select-option-id {project_board.option_ids.lane.sync} 2>/dev/null || true
302
+ gh project item-edit --project-id {project_board.project_id} --id "$ITEM_ID" \
303
+ --field-id {project_board.field_ids.component} \
304
+ --single-select-option-id {COMPONENT_OPTION_ID} 2>/dev/null || true
305
+ gh project item-edit --project-id {project_board.project_id} --id "$ITEM_ID" \
306
+ --field-id {project_board.field_ids.priority} \
307
+ --single-select-option-id {project_board.option_ids.priority.p2} 2>/dev/null || true
241
308
  fi
242
309
  ```
243
310
 
@@ -248,11 +315,9 @@ fi
248
315
 
249
316
  | # | Repo | Issue | Priority |
250
317
  |---|------|-------|----------|
251
- | mcp:#5 | alterlab-mcp-server | Add cookies to scrape tool | P2 |
252
- | n8n:#12 | n8n-nodes-alterlab | Add cookies to Scrape op | P2 |
253
- | #2100 | AlterLab (SDK) | Add cookies to Node SDK | P2 |
318
+ | {COMPONENT}:#{NUM} | {GH_REPO} | {CHANGE_DESCRIPTION} | P2 |
254
319
 
255
- Run `/orchestrate mcp:5 n8n:12 #2100` to implement all sync issues in parallel.
320
+ Run `/orchestrate {COMPONENT}:#{NUM} ...` to implement all sync issues in parallel.
256
321
  ```
257
322
 
258
323
  ---
@@ -266,10 +331,7 @@ If the API change warrants a version bump in satellite packages:
266
331
 
267
332
  | Package | Current | Suggested | Reason |
268
333
  |---------|---------|-----------|--------|
269
- | alterlab (PyPI) | 2.0.1 | 2.1.0 | New `cookies` parameter |
270
- | @alterlab/sdk (npm) | 2.0.1 | 2.1.0 | New `cookies` parameter |
271
- | alterlab-mcp-server (npm) | 1.0.0 | 1.1.0 | New scrape tool param |
272
- | n8n-nodes-alterlab (npm) | 0.5.0 | 0.6.0 | New Scrape field |
334
+ | {PACKAGE} ({REGISTRY}) | {CURRENT_VERSION} | {NEW_VERSION} | {CHANGE_DESCRIPTION} |
273
335
  ```
274
336
 
275
337
  Include version bump instructions in the created issues.
@@ -282,42 +344,38 @@ Include version bump instructions in the created issues.
282
344
 
283
345
  ### 5A: Collect current versions (code vs published)
284
346
 
347
+ For each satellite in `repos.satellites`, collect code version vs published version:
348
+
285
349
  ```bash
286
- echo "=== MCP Server ==="
350
+ # For each satellite: {COMPONENT}, {GH_REPO}, {REPO_PATH}, {PACKAGE}
351
+
352
+ echo "=== {COMPONENT} ==="
287
353
  # Version in code (on main):
288
- cd /home/mrdubey/projects/ScraperAPI/alterlab-mcp-server && git fetch origin main 2>/dev/null
289
- MCP_CODE_VERSION=$(git show origin/main:package.json | grep '"version"' | head -1 | grep -oP '\d+\.\d+\.\d+')
290
- echo "Code version: $MCP_CODE_VERSION"
354
+ cd {REPO_PATH} && git fetch origin main 2>/dev/null
355
+ CODE_VERSION=$(git show origin/main:package.json | grep '"version"' | head -1 | grep -oP '\d+\.\d+\.\d+')
356
+ # (For pyproject.toml: git show origin/main:pyproject.toml | grep '^version' | grep -oP '\d+\.\d+\.\d+')
357
+ echo "Code version: $CODE_VERSION"
358
+
291
359
  # Latest GitHub release:
292
- MCP_RELEASE=$(gh release list -R RapierCraft/alterlab-mcp-server --limit 1 --json tagName,publishedAt --jq '.[0] | "\(.tagName) (\(.publishedAt))"' 2>/dev/null)
293
- echo "Latest release: $MCP_RELEASE"
360
+ LATEST_RELEASE=$(gh release list -R {GH_REPO} --limit 1 --json tagName,publishedAt \
361
+ --jq '.[0] | "\(.tagName) (\(.publishedAt))"' 2>/dev/null)
362
+ echo "Latest release: $LATEST_RELEASE"
363
+
294
364
  # Commits since last release tag:
295
- MCP_RELEASE_TAG=$(gh release list -R RapierCraft/alterlab-mcp-server --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null)
296
- MCP_COMMITS_SINCE=$(git rev-list ${MCP_RELEASE_TAG}..origin/main --count 2>/dev/null || echo "unknown")
297
- echo "Commits since release: $MCP_COMMITS_SINCE"
298
-
299
- echo "=== n8n Node ==="
300
- cd /home/mrdubey/projects/ScraperAPI/n8n-nodes-alterlab && git fetch origin main 2>/dev/null
301
- N8N_CODE_VERSION=$(git show origin/main:package.json | grep '"version"' | head -1 | grep -oP '\d+\.\d+\.\d+')
302
- echo "Code version: $N8N_CODE_VERSION"
303
- N8N_RELEASE=$(gh release list -R RapierCraft/n8n-nodes-alterlab --limit 1 --json tagName,publishedAt --jq '.[0] | "\(.tagName) (\(.publishedAt))"' 2>/dev/null)
304
- echo "Latest release: $N8N_RELEASE"
305
- N8N_RELEASE_TAG=$(gh release list -R RapierCraft/n8n-nodes-alterlab --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null)
306
- N8N_COMMITS_SINCE=$(git rev-list ${N8N_RELEASE_TAG}..origin/main --count 2>/dev/null || echo "unknown")
307
- echo "Commits since release: $N8N_COMMITS_SINCE"
308
-
309
- echo "=== Python SDK ==="
310
- cd /home/mrdubey/projects/ScraperAPI/alterlab && git fetch origin main 2>/dev/null
311
- PY_CODE_VERSION=$(git show origin/main:sdk/python/pyproject.toml | grep '^version' | grep -oP '\d+\.\d+\.\d+')
312
- echo "Code version: $PY_CODE_VERSION"
313
- # Last publish-sdks workflow run:
314
- PY_LAST_PUBLISH=$(gh run list --workflow=publish-sdks.yml --status=success --limit 1 --json createdAt,headBranch --jq '.[0] | "\(.headBranch) (\(.createdAt))"' 2>/dev/null)
315
- echo "Last SDK publish: $PY_LAST_PUBLISH"
316
-
317
- echo "=== Node SDK ==="
318
- NODE_CODE_VERSION=$(git show origin/main:sdk/node/package.json | grep '"version"' | head -1 | grep -oP '\d+\.\d+\.\d+')
319
- echo "Code version: $NODE_CODE_VERSION"
320
- echo "Last SDK publish: $PY_LAST_PUBLISH" # Same workflow handles both
365
+ RELEASE_TAG=$(gh release list -R {GH_REPO} --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null)
366
+ COMMITS_SINCE=$(git rev-list ${RELEASE_TAG}..origin/main --count 2>/dev/null || echo "unknown")
367
+ echo "Commits since release: $COMMITS_SINCE"
368
+ ```
369
+
370
+ For monorepo packages that use `workflow_dispatch` instead of GitHub Releases:
371
+
372
+ ```bash
373
+ # Check last publish workflow run date
374
+ LAST_PUBLISH=$(gh run list --repo {GH_REPO} --workflow={PUBLISH_WORKFLOW} \
375
+ --status=success --limit 1 \
376
+ --json createdAt,headBranch \
377
+ --jq '.[0] | "\(.headBranch) (\(.createdAt))"' 2>/dev/null)
378
+ echo "Last publish: $LAST_PUBLISH"
321
379
  ```
322
380
 
323
381
  ### 5B: Determine what needs publishing
@@ -325,7 +383,7 @@ echo "Last SDK publish: $PY_LAST_PUBLISH" # Same workflow handles both
325
383
  A component needs publishing when ANY of these are true:
326
384
  - Commits exist on `main` after the last release tag (for satellite repos)
327
385
  - The version in code is newer than the last published version
328
- - The last `publish-sdks.yml` run predates commits that changed `sdk/python/` or `sdk/node/`
386
+ - The last publish workflow run predates commits that changed the package source
329
387
 
330
388
  ### 5C: Report publication status
331
389
 
@@ -334,10 +392,7 @@ A component needs publishing when ANY of these are true:
334
392
 
335
393
  | Component | Code Version | Published Version | Commits Behind | Status |
336
394
  |-----------|-------------|-------------------|----------------|--------|
337
- | MCP Server (npm) | {MCP_CODE_VERSION} | {MCP_RELEASE_TAG} | {N} commits | {PUBLISHED / STALE} |
338
- | n8n Node (npm) | {N8N_CODE_VERSION} | {N8N_RELEASE_TAG} | {N} commits | {PUBLISHED / STALE} |
339
- | Python SDK (PyPI) | {PY_CODE_VERSION} | last publish: {date} | — | {PUBLISHED / STALE} |
340
- | Node SDK (npm) | {NODE_CODE_VERSION} | last publish: {date} | — | {PUBLISHED / STALE} |
395
+ | {COMPONENT} ({REGISTRY}) | {CODE_VERSION} | {RELEASE_TAG} | {N} commits | {PUBLISHED / STALE} |
341
396
 
342
397
  {If any STALE:}
343
398
  Run `/sync-ecosystem publish` to bump versions and publish all stale components.
@@ -347,7 +402,7 @@ Run `/sync-ecosystem publish` to bump versions and publish all stale components.
347
402
 
348
403
  ## Phase 6: Publish Releases
349
404
 
350
- **Only run when input is `publish` (or `publish <component>`).** This phase bumps versions, creates releases, and triggers publish workflows.
405
+ **Only run when input is `publish` (or `publish {COMPONENT}`).** This phase bumps versions, creates releases, and triggers publish workflows.
351
406
 
352
407
  **IMPORTANT**: Always confirm with the user before publishing. Show the Phase 5 status table and ask: "These components will be published. Proceed?"
353
408
 
@@ -364,13 +419,13 @@ For each stale component, determine the appropriate semver bump:
364
419
  Read the commit log since the last release to determine the bump type:
365
420
 
366
421
  ```bash
367
- # For MCP server:
368
- cd /home/mrdubey/projects/ScraperAPI/alterlab-mcp-server
369
- git log ${MCP_RELEASE_TAG}..origin/main --oneline --no-merges
422
+ # For each satellite:
423
+ cd {REPO_PATH}
424
+ git log ${RELEASE_TAG}..origin/main --oneline --no-merges
370
425
  # Look for feat: (MINOR), fix: (PATCH), or BREAKING CHANGE (MAJOR)
371
426
  ```
372
427
 
373
- ### 6B: Publish satellite repos (MCP Server, n8n Node)
428
+ ### 6B: Publish satellite repos (separate GitHub repos)
374
429
 
375
430
  For each satellite repo that needs publishing:
376
431
 
@@ -381,7 +436,6 @@ cd {REPO_PATH}
381
436
  git checkout main && git pull origin main
382
437
 
383
438
  # 2. Bump version in package.json
384
- # Use npm version which updates package.json AND creates a git tag
385
439
  npm version {minor|patch|major} --no-git-tag-version
386
440
 
387
441
  # 3. Commit the version bump
@@ -390,7 +444,7 @@ git add package.json package-lock.json
390
444
  git commit -m "chore: bump version to ${NEW_VERSION}"
391
445
  git push origin main
392
446
 
393
- # 4. Create GitHub Release (triggers publish-npm.yml automatically)
447
+ # 4. Create GitHub Release (triggers {PUBLISH_WORKFLOW} automatically)
394
448
  gh release create "v${NEW_VERSION}" \
395
449
  --repo {GH_REPO} \
396
450
  --title "v${NEW_VERSION}" \
@@ -402,72 +456,62 @@ sleep 5
402
456
  gh run list --repo {GH_REPO} --workflow={PUBLISH_WORKFLOW} --limit 1 --json status,conclusion
403
457
  ```
404
458
 
405
- **MCP Server specific**: The `publish-mcp-registry.yml` also fires on release — it publishes to the MCP Registry alongside npm. No extra action needed.
406
-
407
- ### 6C: Publish SDKs (Python + Node)
459
+ ### 6C: Publish monorepo packages (SDKs and tools inside a shared repo)
408
460
 
409
- SDKs live in the AlterLab monorepo and use a `workflow_dispatch` workflow:
461
+ Monorepo packages use a `workflow_dispatch` workflow triggered manually (not on GitHub Release):
410
462
 
411
463
  ```bash
412
- cd /home/mrdubey/projects/ScraperAPI/alterlab
464
+ cd {REPO_PATH}
413
465
 
414
- # 1. Check if SDK versions need bumping (compare code version to last publish)
415
- PY_VERSION=$(git show origin/main:sdk/python/pyproject.toml | grep '^version' | grep -oP '\d+\.\d+\.\d+')
416
- NODE_VERSION=$(git show origin/main:sdk/node/package.json | grep '"version"' | head -1 | grep -oP '\d+\.\d+\.\d+')
466
+ # 1. Check if package versions need bumping (compare code version to last publish)
467
+ PY_VERSION=$(git show origin/main:{SUBPATH}/pyproject.toml | grep '^version' | grep -oP '\d+\.\d+\.\d+')
468
+ NODE_VERSION=$(git show origin/main:{SUBPATH}/package.json | grep '"version"' | head -1 | grep -oP '\d+\.\d+\.\d+')
417
469
 
418
470
  # 2. If versions already bumped in code, just trigger the publish
419
471
  # If versions need bumping, create a worktree, bump, commit, push, then trigger
420
472
 
421
473
  # 3. Trigger publish workflow
422
- gh workflow run publish-sdks.yml --ref main -f sdk=both
474
+ gh workflow run {PUBLISH_WORKFLOW} --repo {GH_REPO} --ref main -f sdk=both
423
475
 
424
476
  # 4. Verify workflow started
425
477
  sleep 5
426
- gh run list --workflow=publish-sdks.yml --limit 1 --json status,conclusion,createdAt
478
+ gh run list --repo {GH_REPO} --workflow={PUBLISH_WORKFLOW} --limit 1 --json status,conclusion,createdAt
427
479
  ```
428
480
 
429
- **If SDK versions need bumping** (code version matches last published version but code has changed):
481
+ **If versions need bumping** (code version matches last published version but code has changed):
430
482
 
431
483
  ```bash
432
484
  # Create worktree for version bump
433
- cd /home/mrdubey/projects/ScraperAPI/alterlab
434
- git worktree add ../alterlab-sdk-bump -b fix/sdk-version-bump origin/main
435
- cd ../alterlab-sdk-bump
436
-
437
- # Bump Python SDK version
438
- # Edit sdk/python/pyproject.toml: version = "{NEW_VERSION}"
485
+ cd {REPO_PATH}
486
+ git worktree add ../{COMPONENT}-version-bump -b fix/{COMPONENT}-version-bump origin/main
487
+ cd ../{COMPONENT}-version-bump
439
488
 
440
- # Bump Node SDK version
441
- cd sdk/node && npm version {minor|patch} --no-git-tag-version && cd ../..
489
+ # Bump version (example: pyproject.toml or package.json)
490
+ # Edit {SUBPATH}/pyproject.toml: version = "{NEW_VERSION}"
491
+ cd {SUBPATH} && npm version {minor|patch} --no-git-tag-version && cd -
442
492
 
443
493
  # Commit and push
444
- git add sdk/python/pyproject.toml sdk/node/package.json sdk/node/package-lock.json
445
- git commit -m "chore(sdk): bump Python SDK to {PY_NEW} and Node SDK to {NODE_NEW}"
446
- git push origin fix/sdk-version-bump
447
-
448
- # Create PR to staging (fast-lane), merge, then trigger publish from main after deploy
449
- gh pr create --base staging --title "chore: bump SDK versions" --body "Version bump for SDK publish"
494
+ git add {SUBPATH}/pyproject.toml {SUBPATH}/package.json {SUBPATH}/package-lock.json
495
+ git commit -m "chore({COMPONENT}): bump version to {NEW_VERSION}"
496
+ git push origin fix/{COMPONENT}-version-bump
497
+
498
+ # Create PR to {STAGING_BRANCH}, merge, then trigger publish from main
499
+ gh pr create --repo {GH_REPO} --base {STAGING_BRANCH} \
500
+ --title "chore: bump {COMPONENT} version to {NEW_VERSION}" \
501
+ --body "Version bump for {COMPONENT} publish"
450
502
  ```
451
503
 
452
504
  ### 6D: Monitor publish workflows
453
505
 
454
- After triggering publishes, monitor completion:
506
+ After triggering publishes, monitor completion for each satellite:
455
507
 
456
508
  ```bash
457
509
  echo "=== Publish Status ==="
458
510
 
459
- # MCP Server
460
- echo "MCP Server:"
461
- gh run list --repo RapierCraft/alterlab-mcp-server --workflow=publish-npm.yml --limit 1 --json status,conclusion,createdAt --jq '.[0]'
462
- gh run list --repo RapierCraft/alterlab-mcp-server --workflow=publish-mcp-registry.yml --limit 1 --json status,conclusion,createdAt --jq '.[0]'
463
-
464
- # n8n Node
465
- echo "n8n Node:"
466
- gh run list --repo RapierCraft/n8n-nodes-alterlab --workflow=publish.yml --limit 1 --json status,conclusion,createdAt --jq '.[0]'
467
-
468
- # SDKs
469
- echo "SDKs:"
470
- gh run list --workflow=publish-sdks.yml --limit 1 --json status,conclusion,createdAt --jq '.[0]'
511
+ # For each satellite: {COMPONENT}, {GH_REPO}, {PUBLISH_WORKFLOW}
512
+ echo "{COMPONENT}:"
513
+ gh run list --repo {GH_REPO} --workflow={PUBLISH_WORKFLOW} \
514
+ --limit 1 --json status,conclusion,createdAt --jq '.[0]'
471
515
  ```
472
516
 
473
517
  ### 6E: Generate changelog for releases
@@ -487,8 +531,8 @@ $CHANGES
487
531
 
488
532
  ## Ecosystem Sync
489
533
 
490
- This release brings parity with AlterLab API changes from the following PRs:
491
- {list of source AlterLab PRs that drove these changes}
534
+ This release brings parity with {project.name} API changes from the following PRs:
535
+ {list of source PRs that drove these changes}
492
536
  EOF
493
537
  ```
494
538
 
@@ -499,19 +543,14 @@ EOF
499
543
 
500
544
  | Component | Old Version | New Version | Status | Registry |
501
545
  |-----------|------------|-------------|--------|----------|
502
- | MCP Server | v1.2.0 | v1.3.0 | Published | npm + MCP Registry |
503
- | n8n Node | v0.8.0 | v0.9.0 | Published | npm |
504
- | Python SDK | 2.1.0 | 2.1.1 | Published | PyPI |
505
- | Node SDK | 2.1.0 | 2.1.1 | Published | npm |
546
+ | {COMPONENT} | {OLD_VERSION} | {NEW_VERSION} | Published | {REGISTRY} |
506
547
 
507
548
  ### Verification
508
549
 
509
550
  ```bash
510
551
  # Verify packages are live on registries:
511
- npm view alterlab-mcp-server version
512
- npm view n8n-nodes-alterlab version
513
- npm view @alterlab/sdk version
514
- pip index versions alterlab 2>/dev/null || pip install alterlab== 2>&1 | grep -oP '\d+\.\d+\.\d+'
552
+ npm view {PACKAGE} version # for npm packages
553
+ pip index versions {PACKAGE} 2>/dev/null || pip install {PACKAGE}== 2>&1 | grep -oP '\d+\.\d+\.\d+'
515
554
  ```
516
555
  ```
517
556
 
@@ -520,8 +559,9 @@ pip index versions alterlab 2>/dev/null || pip install alterlab== 2>&1 | grep -o
520
559
  ## Error Handling
521
560
 
522
561
  - **No API changes detected**: Report "No API surface changes found in recent PRs. Ecosystem is in sync." — but STILL run Phase 5 to check publication status.
523
- - **Repo not accessible**: Skip and warn (e.g., "Could not access RapierCraft/n8n-nodes-alterlab — check gh auth")
562
+ - **Repo not accessible**: Skip and warn (e.g., "Could not access {GH_REPO} — check gh auth")
524
563
  - **Duplicate issues**: Check for existing open issues with "Sync:" prefix before creating new ones
525
564
  - **Publish workflow fails**: Report the failure, link to the workflow run, suggest manual investigation. Do NOT retry automatically.
526
565
  - **Version conflict on npm/PyPI**: The version already exists on the registry. Bump to the next version and retry.
527
566
  - **OIDC publish fails**: Check that the repo has npm/PyPI trusted publishing configured. See workflow files for required permissions.
567
+ - **No repos configured**: If `forge.yaml → repos.satellites` is empty or absent, the command outputs a configuration guide and exits. No error.
@@ -23,8 +23,8 @@ Eliminate cross-path inconsistency bugs before any code is written. The single b
23
23
 
24
24
  Parse from $ARGUMENTS:
25
25
  - `{NUMBER}` — issue number (required, positional first arg)
26
- - `--repo {GH_REPO}` — GitHub repo (e.g. `RapierCraft/AlterLab`)
27
- - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R RapierCraft/AlterLab`)
26
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `{owner}/{repo}` — resolved from `forge.yaml → project`)
27
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R {owner}/{repo}`)
28
28
  - `--repo-path {REPO_PATH}` — local filesystem path to the worktree (e.g. `/path/to/.claude/worktrees/fix/issue-121`); used by Phase A1 grep commands
29
29
  - `--files {AFFECTED_FILES}` — space-separated list of files from investigation report (passed by `build.md` Phase B4)
30
30
 
@@ -23,8 +23,8 @@ Surface what went wrong in this area before the builder writes a single line of
23
23
 
24
24
  Parse from `$ARGUMENTS`:
25
25
  - `{NUMBER}` — issue number (positional, required)
26
- - `--repo {GH_REPO}` — GitHub repo (e.g. `RapierCraft/AlterLab`)
27
- - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R RapierCraft/AlterLab`)
26
+ - `--repo {GH_REPO}` — GitHub repo (e.g. `{owner}/{repo}` — resolved from `forge.yaml → project`)
27
+ - `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R {owner}/{repo}`)
28
28
  - `--repo-path {REPO_PATH}` — local filesystem path to the worktree (e.g. `/path/to/.claude/worktrees/fix/issue-121`); used by Phase C3 grep commands
29
29
  - `{AFFECTED_FILES}` — space-separated file paths (positional, after `{NUMBER}`, before any `--functions` flag)
30
30
  - `--functions {FUNCTION_NAMES}` — space-separated function/class names extracted from the Builder Contract deliverables table (optional)