forgedock 1.0.0 → 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.
- package/README.md +19 -2
- package/bin/forgedock.mjs +286 -10
- package/commands/analytics.md +129 -52
- package/commands/audit-agents.md +29 -5
- package/commands/audit.md +55 -17
- package/commands/autopilot.md +11 -6
- package/commands/cleanup.md +44 -24
- package/commands/deploy-info.md +7 -3
- package/commands/forge-stats.md +13 -4
- package/commands/forgedock-init.md +534 -0
- package/commands/geo-audit.md +114 -26
- package/commands/incident-response.md +4 -1
- package/commands/issue.md +26 -25
- package/commands/milestone.md +80 -59
- package/commands/orchestrate.md +38 -21
- package/commands/pipeline-health.md +26 -15
- package/commands/qa-sweep.md +68 -5
- package/commands/quality-gate.md +18 -0
- package/commands/review-pr-agents.md +58 -90
- package/commands/review-pr.md +58 -16
- package/commands/rollback.md +8 -5
- package/commands/security-audit.md +68 -12
- package/commands/sync-ecosystem.md +196 -156
- package/commands/validate.md +1 -1
- package/commands/work-on/build/architect.md +2 -2
- package/commands/work-on/build/context.md +2 -2
- package/commands/work-on/build/implement.md +3 -3
- package/commands/work-on/build/validate.md +3 -3
- package/commands/work-on/build.md +6 -6
- package/commands/work-on/close.md +59 -30
- package/commands/work-on/decompose.md +6 -6
- package/commands/work-on/investigate.md +16 -20
- package/commands/work-on/review.md +4 -4
- package/commands/work-on-monolithic.md +15 -16
- package/commands/work-on.md +45 -33
- package/docs/CODEX.md +1 -1
- package/docs/CONFIG.md +398 -0
- package/docs/WORKFLOW.md +115 -72
- package/package.json +2 -2
- package/scripts/verify-host-headers.sh +14 -9
- package/scripts/verify-route-registration.sh +10 -10
- package/commands/failure-recon.md +0 -375
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Detect API changes, sync satellite repos, and publish releases
|
|
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
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
|
21
|
-
|
|
22
|
-
|
|
|
23
|
-
|
|
|
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** (
|
|
28
|
-
- **
|
|
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
|
|
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
|
|
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
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
|
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: "
|
|
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: "
|
|
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/
|
|
100
|
-
- repo: "
|
|
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/
|
|
103
|
-
- repo: "
|
|
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
|
|
112
|
-
cd
|
|
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
|
|
118
|
-
cd
|
|
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
|
-
|
|
|
143
|
-
|
|
|
144
|
-
|
|
|
145
|
-
|
|
|
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
|
|
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
|
|
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**:
|
|
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,
|
|
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
|
|
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
|
|
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**:
|
|
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
|
|
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
|
|
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
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
gh project item-edit --project-id
|
|
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
|
-
|
|
|
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
|
|
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
|
-
|
|
|
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
|
-
|
|
350
|
+
# For each satellite: {COMPONENT}, {GH_REPO}, {REPO_PATH}, {PACKAGE}
|
|
351
|
+
|
|
352
|
+
echo "=== {COMPONENT} ==="
|
|
287
353
|
# Version in code (on main):
|
|
288
|
-
cd
|
|
289
|
-
|
|
290
|
-
|
|
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
|
-
|
|
293
|
-
|
|
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
|
-
|
|
296
|
-
|
|
297
|
-
echo "Commits since release: $
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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
|
|
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
|
-
|
|
|
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
|
|
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
|
|
368
|
-
cd
|
|
369
|
-
git log ${
|
|
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 (
|
|
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
|
|
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
|
-
|
|
406
|
-
|
|
407
|
-
### 6C: Publish SDKs (Python + Node)
|
|
459
|
+
### 6C: Publish monorepo packages (SDKs and tools inside a shared repo)
|
|
408
460
|
|
|
409
|
-
|
|
461
|
+
Monorepo packages use a `workflow_dispatch` workflow triggered manually (not on GitHub Release):
|
|
410
462
|
|
|
411
463
|
```bash
|
|
412
|
-
cd
|
|
464
|
+
cd {REPO_PATH}
|
|
413
465
|
|
|
414
|
-
# 1. Check if
|
|
415
|
-
PY_VERSION=$(git show origin/main:
|
|
416
|
-
NODE_VERSION=$(git show origin/main:
|
|
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
|
|
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=
|
|
478
|
+
gh run list --repo {GH_REPO} --workflow={PUBLISH_WORKFLOW} --limit 1 --json status,conclusion,createdAt
|
|
427
479
|
```
|
|
428
480
|
|
|
429
|
-
**If
|
|
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
|
|
434
|
-
git worktree add ../
|
|
435
|
-
cd ../
|
|
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
|
|
441
|
-
|
|
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
|
|
445
|
-
git commit -m "chore(
|
|
446
|
-
git push origin fix/
|
|
447
|
-
|
|
448
|
-
# Create PR to
|
|
449
|
-
gh pr create --
|
|
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
|
-
#
|
|
460
|
-
echo "
|
|
461
|
-
gh run list --repo
|
|
462
|
-
|
|
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
|
|
491
|
-
{list of source
|
|
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
|
-
|
|
|
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
|
|
512
|
-
|
|
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
|
|
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.
|
package/commands/validate.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Independently verify if a reported issue is actually a problem before making code changes
|
|
2
|
+
description: Independently verify if a reported issue is actually a problem before making code changes.
|
|
3
3
|
argument-hint: [issue description or #number]
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -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. `
|
|
27
|
-
- `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R
|
|
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. `
|
|
27
|
-
- `--gh-flag {GH_FLAG}` — gh CLI repo flag (e.g. `-R
|
|
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)
|