forgedock 1.1.11 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/bin/cli-spawn-shared.mjs +25 -0
- package/bin/engine/phases.mjs +178 -28
- package/bin/engine/state.mjs +39 -7
- package/bin/engine-cli.mjs +85 -3
- package/bin/engine.mjs +71 -8
- package/bin/forgedock.mjs +322 -20
- package/bin/hooks/pre-tool-use.mjs +345 -10
- package/bin/init-enrich-api.mjs +12 -4
- package/bin/init-enrich-cli.mjs +328 -0
- package/bin/init-enrich.mjs +137 -0
- package/bin/journey.mjs +116 -15
- package/bin/runner.mjs +653 -10
- package/commands/adopt.md +1 -1
- package/commands/analytics.md +10 -7
- package/commands/audit-agents.md +29 -6
- package/commands/audit.md +9 -20
- package/commands/autopilot.md +52 -78
- package/commands/changelog.md +1 -1
- package/commands/ci-audit.md +19 -10
- package/commands/cleanup.md +1 -1
- package/commands/compat-audit.md +1 -1
- package/commands/deploy-info.md +1 -1
- package/commands/deploy-pr.md +1 -1
- package/commands/design-bench.md +1 -1
- package/commands/design-render-critique-loop.md +1 -1
- package/commands/diagnose.md +1 -1
- package/commands/forge-stats.md +6 -5
- package/commands/forgedock-init.md +1 -1
- package/commands/geo-audit.md +9 -6
- package/commands/incident-response.md +15 -5
- package/commands/issue.md +302 -15
- package/commands/milestone.md +45 -18
- package/commands/optimize.md +1 -1
- package/commands/orchestrate/phase-1-resolve.md +20 -5
- package/commands/orchestrate/phase-4-execution.md +8 -1
- package/commands/orchestrate/phase-5-cleanup.md +43 -2
- package/commands/orchestrate/phase-6-report.md +1 -0
- package/commands/orchestrate.md +1 -1
- package/commands/pipeline-health/phase-4-proposals.md +40 -10
- package/commands/pipeline-health/phase-5-report.md +140 -13
- package/commands/pipeline-health.md +1 -1
- package/commands/pipeline-resume.md +1 -1
- package/commands/pipeline-status.md +1 -1
- package/commands/qa-sweep.md +27 -4
- package/commands/recover-orphans.md +1 -1
- package/commands/replay.md +16 -2
- package/commands/review-pr-agents/protocols.md +4 -0
- package/commands/review-pr-agents/spec-cli.md +179 -0
- package/commands/review-pr-agents.md +7 -4
- package/commands/review-pr-staging.md +44 -15
- package/commands/review-pr.md +122 -28
- package/commands/rollback.md +15 -5
- package/commands/security-audit.md +14 -11
- package/commands/signal-planner.md +32 -12
- package/commands/spec-doctor.md +1 -1
- package/commands/sync-ecosystem.md +54 -11
- package/commands/test-gate.md +49 -11
- package/commands/upgrade-deps.md +518 -0
- package/commands/validate.md +16 -5
- package/commands/work-on/build/architect.md +1 -1
- package/commands/work-on/build/context.md +1 -1
- package/commands/work-on/build/implement.md +2 -2
- package/commands/work-on/build/validate.md +64 -2
- package/commands/work-on/build.md +10 -2
- package/commands/work-on/close.md +1 -1
- package/commands/work-on/decompose.md +35 -25
- package/commands/work-on/investigate.md +2 -2
- package/commands/work-on/remediate.md +1 -1
- package/commands/work-on/review.md +5 -3
- package/commands/work-on-monolithic.md +1 -1
- package/commands/work-on.md +28 -7
- package/docs/AIDER.md +264 -0
- package/docs/AUTOPILOT-CRON.md +130 -0
- package/docs/CI.md +18 -0
- package/docs/CONFIG.md +41 -2
- package/docs/CURSOR.md +135 -0
- package/docs/OPENCODE.md +312 -0
- package/docs/demo.gif +0 -0
- package/docs/eval/README.md +4 -4
- package/docs/launch/show-hn.md +3 -3
- package/docs/site/annotations-explained.md +2 -2
- package/docs/site/architecture.md +180 -0
- package/docs/site/command-reference.md +38 -0
- package/docs/site/configuration.md +243 -0
- package/docs/site/for-companies.md +4 -4
- package/docs/site/forge-annotation-protocol.md +1 -1
- package/docs/site/github-is-the-memory.md +2 -2
- package/docs/site/how-it-works.md +1 -1
- package/docs/site/public/llms-full.txt +380 -0
- package/docs/site/public/llms.txt +35 -0
- package/docs/spec/review-protocol.md +6 -0
- package/docs/spec-graph-schema.md +3 -3
- package/package.json +2 -2
- package/packages/protocol/README.md +75 -0
- package/packages/protocol/src/card.js +114 -0
- package/packages/protocol/src/cli.js +4 -77
- package/packages/protocol/src/emit.js +14 -3
- package/packages/protocol/src/index.js +2 -1
- package/packages/protocol/src/parse.js +17 -8
- package/packages/protocol/src/types.js +1 -1
- package/packages/protocol/src/validate.js +11 -0
- package/scripts/check-command-side-effects.sh +261 -0
- package/scripts/check-spec-markers.sh +273 -0
- package/scripts/classify-lane.sh +29 -7
- package/scripts/forge-run.sh +322 -0
- package/templates/cross-repo-trigger.yml +282 -0
- package/templates/cursor/forge.mdc +148 -0
- package/templates/github-actions/forgedock-autopilot.yml +113 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Autonomous dependency upgrade pipeline — detect outdated dependencies, create upgrade issues, and run /work-on to investigate, build, test, and merge each upgrade
|
|
3
|
+
argument-hint: [--dry-run | --ecosystem npm|pip|cargo | --allow-major | --limit N | --batch]
|
|
4
|
+
---
|
|
5
|
+
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
6
|
+
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
7
|
+
|
|
8
|
+
# /upgrade-deps — Autonomous Dependency Upgrade Pipeline
|
|
9
|
+
|
|
10
|
+
**Input**: $ARGUMENTS
|
|
11
|
+
|
|
12
|
+
You are a dependency upgrade agent. Your job is to detect outdated packages, triage them by semver risk level, create GitHub issues for eligible upgrades, and run them through the full `/work-on` pipeline — so each upgrade gets investigation, compatibility verification, quality gate, review, and merge — rather than a blind version bump PR.
|
|
13
|
+
|
|
14
|
+
**Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
|
|
15
|
+
**NEVER use plan mode (EnterPlanMode).**
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Argument Parsing
|
|
20
|
+
|
|
21
|
+
| Flag | Effect |
|
|
22
|
+
|------|--------|
|
|
23
|
+
| (none) | Detect + triage + report (no issue creation, no fixing) |
|
|
24
|
+
| `--dry-run` | Run all phases but do NOT create issues, PRs, or labels — report only |
|
|
25
|
+
| `--ecosystem npm` | Limit detection to npm only |
|
|
26
|
+
| `--ecosystem pip` | Limit detection to pip only |
|
|
27
|
+
| `--ecosystem cargo` | Limit detection to cargo only |
|
|
28
|
+
| `--allow-major` | Include major upgrades in issue creation (default: flag for human review only) |
|
|
29
|
+
| `--limit N` | Cap issue creation to at most N issues per run (default: 10) |
|
|
30
|
+
| `--batch` | Group all patch upgrades into one batch issue instead of one-per-package |
|
|
31
|
+
| `--fix` | After issue creation, also invoke `/work-on` on each created issue |
|
|
32
|
+
|
|
33
|
+
Parse `$ARGUMENTS`:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
DRY_RUN=false
|
|
37
|
+
ECOSYSTEM_FILTER=""
|
|
38
|
+
ALLOW_MAJOR=false
|
|
39
|
+
ISSUE_LIMIT=10
|
|
40
|
+
BATCH_PATCHES=false
|
|
41
|
+
DO_FIX=false
|
|
42
|
+
NEXT_IS_ECOSYSTEM=false
|
|
43
|
+
NEXT_IS_LIMIT=false
|
|
44
|
+
|
|
45
|
+
for arg in $ARGUMENTS; do
|
|
46
|
+
case "$arg" in
|
|
47
|
+
--dry-run) DRY_RUN=true ;;
|
|
48
|
+
--allow-major) ALLOW_MAJOR=true ;;
|
|
49
|
+
--batch) BATCH_PATCHES=true ;;
|
|
50
|
+
--fix) DO_FIX=true ;;
|
|
51
|
+
--ecosystem) NEXT_IS_ECOSYSTEM=true ;;
|
|
52
|
+
--limit) NEXT_IS_LIMIT=true ;;
|
|
53
|
+
*)
|
|
54
|
+
if [ "$NEXT_IS_ECOSYSTEM" = "true" ]; then
|
|
55
|
+
ECOSYSTEM_FILTER="$arg"
|
|
56
|
+
NEXT_IS_ECOSYSTEM=false
|
|
57
|
+
elif [ "$NEXT_IS_LIMIT" = "true" ]; then
|
|
58
|
+
ISSUE_LIMIT="$arg"
|
|
59
|
+
NEXT_IS_LIMIT=false
|
|
60
|
+
fi
|
|
61
|
+
;;
|
|
62
|
+
esac
|
|
63
|
+
done
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
If `DRY_RUN=true`, prefix all actions with `[DRY RUN]` and skip all `gh issue create`, `gh issue edit`, and `Skill()` invocations — report what would happen instead.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Phase 0: Config Resolution
|
|
71
|
+
|
|
72
|
+
**Config variables used by this command** (set in `forge.yaml → upgrade_deps`):
|
|
73
|
+
- `{ECOSYSTEMS}` ← `upgrade_deps.ecosystems` — list of ecosystems to check (default: `["npm"]`)
|
|
74
|
+
- `{ALLOW_MAJOR_CONFIG}` ← `upgrade_deps.allow_major` (default: `false`) — whether to create issues for major upgrades
|
|
75
|
+
- `{EXCLUDE_PACKAGES}` ← `upgrade_deps.exclude` — list of package names to skip regardless of semver level
|
|
76
|
+
- `{ISSUE_BATCH_SIZE}` ← `upgrade_deps.issue_batch_size` — how many patch packages to group per batch issue (default: 5)
|
|
77
|
+
|
|
78
|
+
Read `forge.yaml` at the project root before running any phase:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
CONFIG_FILE="${FORGE_CONFIG:-forge.yaml}"
|
|
82
|
+
if [ ! -f "$CONFIG_FILE" ]; then
|
|
83
|
+
echo "ERROR: forge.yaml not found. Run: npx forgedock init && /forgedock-init"
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
GH_REPO=$(yq '.project.owner + "/" + .project.repo' "$CONFIG_FILE")
|
|
88
|
+
GH_FLAG="-R $GH_REPO"
|
|
89
|
+
REPO_PATH=$(yq '.paths.root' "$CONFIG_FILE")
|
|
90
|
+
STAGING_BRANCH=$(yq '.branches.staging // "staging"' "$CONFIG_FILE")
|
|
91
|
+
|
|
92
|
+
# upgrade_deps section (all optional — fall back to defaults)
|
|
93
|
+
ECOSYSTEMS_CONFIG=$(yq '.upgrade_deps.ecosystems // ["npm"] | join(" ")' "$CONFIG_FILE" 2>/dev/null || echo "npm")
|
|
94
|
+
ALLOW_MAJOR_CONFIG=$(yq '.upgrade_deps.allow_major // false' "$CONFIG_FILE" 2>/dev/null || echo "false")
|
|
95
|
+
EXCLUDE_PACKAGES=$(yq '.upgrade_deps.exclude // [] | join(" ")' "$CONFIG_FILE" 2>/dev/null || echo "")
|
|
96
|
+
ISSUE_BATCH_SIZE=$(yq '.upgrade_deps.issue_batch_size // 5' "$CONFIG_FILE" 2>/dev/null || echo "5")
|
|
97
|
+
|
|
98
|
+
# CLI flags override config values
|
|
99
|
+
[ "$ECOSYSTEM_FILTER" != "" ] && ECOSYSTEMS_CONFIG="$ECOSYSTEM_FILTER"
|
|
100
|
+
[ "$ALLOW_MAJOR" = "true" ] && ALLOW_MAJOR_CONFIG="true"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Phase 1: Detect Outdated Dependencies
|
|
106
|
+
|
|
107
|
+
Run dependency detection for each configured ecosystem. Skip an ecosystem if its tool is not installed.
|
|
108
|
+
|
|
109
|
+
### 1A: npm
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
if echo "$ECOSYSTEMS_CONFIG" | grep -q "npm"; then
|
|
113
|
+
if command -v npm >/dev/null 2>&1; then
|
|
114
|
+
echo "--- npm ecosystem ---"
|
|
115
|
+
cd "$REPO_PATH"
|
|
116
|
+
NPM_OUTDATED=$(npm outdated --json 2>/dev/null || echo "{}")
|
|
117
|
+
echo "$NPM_OUTDATED" | python3 -c "
|
|
118
|
+
import json, sys
|
|
119
|
+
data = json.load(sys.stdin)
|
|
120
|
+
for pkg, info in data.items():
|
|
121
|
+
current = info.get('current', 'N/A')
|
|
122
|
+
wanted = info.get('wanted', 'N/A')
|
|
123
|
+
latest = info.get('latest', 'N/A')
|
|
124
|
+
print(f'{pkg}|{current}|{wanted}|{latest}')
|
|
125
|
+
" 2>/dev/null || true
|
|
126
|
+
else
|
|
127
|
+
echo "npm not installed — skipping npm ecosystem"
|
|
128
|
+
fi
|
|
129
|
+
fi
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 1B: pip
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
if echo "$ECOSYSTEMS_CONFIG" | grep -q "pip"; then
|
|
136
|
+
PIP_CMD=""
|
|
137
|
+
command -v pip3 >/dev/null 2>&1 && PIP_CMD="pip3"
|
|
138
|
+
command -v pip >/dev/null 2>&1 && PIP_CMD="${PIP_CMD:-pip}"
|
|
139
|
+
|
|
140
|
+
if [ -n "$PIP_CMD" ]; then
|
|
141
|
+
echo "--- pip ecosystem ---"
|
|
142
|
+
$PIP_CMD list --outdated --format=json 2>/dev/null | python3 -c "
|
|
143
|
+
import json, sys
|
|
144
|
+
data = json.load(sys.stdin)
|
|
145
|
+
for pkg in data:
|
|
146
|
+
print(f'{pkg[\"name\"]}|{pkg[\"version\"]}|{pkg[\"latest_version\"]}')
|
|
147
|
+
" 2>/dev/null || true
|
|
148
|
+
else
|
|
149
|
+
echo "pip/pip3 not installed — skipping pip ecosystem"
|
|
150
|
+
fi
|
|
151
|
+
fi
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 1C: cargo
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
if echo "$ECOSYSTEMS_CONFIG" | grep -q "cargo"; then
|
|
158
|
+
if command -v cargo >/dev/null 2>&1 && command -v cargo-outdated >/dev/null 2>&1; then
|
|
159
|
+
echo "--- cargo ecosystem ---"
|
|
160
|
+
cd "$REPO_PATH"
|
|
161
|
+
cargo outdated --format json 2>/dev/null | python3 -c "
|
|
162
|
+
import json, sys
|
|
163
|
+
try:
|
|
164
|
+
data = json.load(sys.stdin)
|
|
165
|
+
for dep in data.get('dependencies', []):
|
|
166
|
+
name = dep.get('name', '')
|
|
167
|
+
project = dep.get('project', 'N/A')
|
|
168
|
+
latest = dep.get('latest', 'N/A')
|
|
169
|
+
print(f'{name}|{project}|{latest}')
|
|
170
|
+
except: pass
|
|
171
|
+
" 2>/dev/null || true
|
|
172
|
+
else
|
|
173
|
+
command -v cargo >/dev/null 2>&1 || echo "cargo not installed — skipping cargo ecosystem"
|
|
174
|
+
command -v cargo-outdated >/dev/null 2>&1 || echo "cargo-outdated not installed — run: cargo install cargo-outdated"
|
|
175
|
+
fi
|
|
176
|
+
fi
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 1D: Aggregate results
|
|
180
|
+
|
|
181
|
+
Collect all detected outdated packages into a structured list:
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
OUTDATED_PACKAGES = [
|
|
185
|
+
{ name, current_version, latest_version, semver_level, ecosystem }
|
|
186
|
+
]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Compute `semver_level` for each package:
|
|
190
|
+
- **patch**: major and minor match (e.g., 1.2.3 → 1.2.9)
|
|
191
|
+
- **minor**: major matches, minor differs (e.g., 1.2.3 → 1.5.0)
|
|
192
|
+
- **major**: major version differs (e.g., 1.x.x → 2.x.x)
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Phase 2: Triage
|
|
197
|
+
|
|
198
|
+
**Goal**: Filter, classify, and rank the detected upgrades.
|
|
199
|
+
|
|
200
|
+
### 2A: Apply exclusions
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Filter out packages in the EXCLUDE_PACKAGES list
|
|
204
|
+
for pkg in $EXCLUDE_PACKAGES; do
|
|
205
|
+
echo "Skipping excluded package: $pkg"
|
|
206
|
+
# Remove from OUTDATED_PACKAGES
|
|
207
|
+
done
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### 2B: Apply semver gate
|
|
211
|
+
|
|
212
|
+
- **patch** and **minor**: eligible for issue creation (default behavior)
|
|
213
|
+
- **major**: eligible only if `ALLOW_MAJOR_CONFIG=true` or `--allow-major` was passed; otherwise, flag for human review
|
|
214
|
+
|
|
215
|
+
### 2C: Deduplication — skip if open issue already tracks this upgrade
|
|
216
|
+
|
|
217
|
+
Before creating any issue, check for existing open issues that already track the same package upgrade:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
for pkg in ${ELIGIBLE_PACKAGES}; do
|
|
221
|
+
# Pass $pkg to jq via the environment (env.PKG) instead of splicing it into the
|
|
222
|
+
# jq program text — avoids breaking the outer quoting if $pkg ever contained a
|
|
223
|
+
# single quote or other shell-meaningful character.
|
|
224
|
+
export PKG="$pkg"
|
|
225
|
+
EXISTING=$(gh issue list $GH_FLAG --state open \
|
|
226
|
+
--search "upgrade $pkg" --limit 5 \
|
|
227
|
+
--json number,title \
|
|
228
|
+
--jq '.[] | select(.title | test("upgrade.*" + env.PKG; "i")) | .number' 2>/dev/null | head -1)
|
|
229
|
+
|
|
230
|
+
if [ -n "$EXISTING" ]; then
|
|
231
|
+
echo "Skipping $pkg — open issue #$EXISTING already tracks this upgrade"
|
|
232
|
+
# Add $pkg to SKIPPED list with reason "existing-issue:#$EXISTING"
|
|
233
|
+
fi
|
|
234
|
+
done
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### 2D: Apply limit
|
|
238
|
+
|
|
239
|
+
Cap the final eligible list to `$ISSUE_LIMIT` packages. Prioritize by semver impact:
|
|
240
|
+
1. minor upgrades (higher value)
|
|
241
|
+
2. patch upgrades (lower value, safe to batch)
|
|
242
|
+
|
|
243
|
+
If `BATCH_PATCHES=true`, group all patch-level packages into one batch issue (up to `$ISSUE_BATCH_SIZE` per batch issue).
|
|
244
|
+
|
|
245
|
+
### 2E: Major upgrade report (human review required)
|
|
246
|
+
|
|
247
|
+
For major upgrades when `ALLOW_MAJOR_CONFIG=false`, collect them for the summary report but do NOT create issues. Print:
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
Major upgrades detected (not auto-processed — require human review):
|
|
251
|
+
{package}: {current} → {latest} [major]
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Phase 3: Issue Creation
|
|
257
|
+
|
|
258
|
+
For each eligible package (or batch), create a GitHub issue:
|
|
259
|
+
|
|
260
|
+
### 3A: Per-package issue (patch or minor, non-batched)
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
# DRY_RUN guard — must stay above the create it guards (forge#1609). In dry-run
|
|
264
|
+
# mode print the would-be issue and move on; never create it.
|
|
265
|
+
if [ "$DRY_RUN" = "true" ]; then
|
|
266
|
+
echo "[DRY RUN] Would create issue: feat(deps): upgrade {PACKAGE} from {CURRENT} to {LATEST} ({SEMVER_LEVEL})"
|
|
267
|
+
else
|
|
268
|
+
gh issue create $GH_FLAG \
|
|
269
|
+
--title "feat(deps): upgrade {PACKAGE} from {CURRENT} to {LATEST} ({SEMVER_LEVEL})" \
|
|
270
|
+
--label "enhancement" \
|
|
271
|
+
--body "$(cat <<'ISSUE_EOF'
|
|
272
|
+
## Problem
|
|
273
|
+
|
|
274
|
+
{PACKAGE} is outdated: current version {CURRENT}, latest is {LATEST} ({SEMVER_LEVEL} bump).
|
|
275
|
+
|
|
276
|
+
Dependency upgrades are repetitive, well-scoped work. This issue tracks the upgrade through the full ForgeDock pipeline: investigate compatibility, implement the upgrade, run tests, review, and merge.
|
|
277
|
+
|
|
278
|
+
## Affected Files
|
|
279
|
+
|
|
280
|
+
Files that may need changes:
|
|
281
|
+
1. `package.json` / `requirements.txt` / `Cargo.toml` — version constraint update
|
|
282
|
+
2. Lockfile (`package-lock.json` / `poetry.lock` / `Cargo.lock`) — regenerated by install command
|
|
283
|
+
|
|
284
|
+
Additional files will be identified if the new version has breaking changes requiring code updates.
|
|
285
|
+
|
|
286
|
+
## Expected Behavior
|
|
287
|
+
|
|
288
|
+
- Package is updated to {LATEST} (or the highest compatible version within {SEMVER_LEVEL} range)
|
|
289
|
+
- All existing tests pass
|
|
290
|
+
- No breaking changes introduced
|
|
291
|
+
|
|
292
|
+
## Acceptance Criteria
|
|
293
|
+
|
|
294
|
+
- [ ] `{PACKAGE}` version updated from `{CURRENT}` to `{LATEST}` in the manifest
|
|
295
|
+
- [ ] Lockfile regenerated (`npm install` / `pip install` / `cargo update`)
|
|
296
|
+
- [ ] Test suite passes (no regressions)
|
|
297
|
+
- [ ] Breaking changes identified and addressed (especially for minor upgrades)
|
|
298
|
+
- [ ] CHANGELOG or release notes consulted for deprecation notices
|
|
299
|
+
|
|
300
|
+
## Context
|
|
301
|
+
|
|
302
|
+
**Ecosystem**: {ECOSYSTEM}
|
|
303
|
+
**Semver level**: {SEMVER_LEVEL}
|
|
304
|
+
**Detected by**: `/upgrade-deps` cycle on {DATE}
|
|
305
|
+
**Release notes**: https://www.npmjs.com/package/{PACKAGE}/v/{LATEST} (adjust URL for ecosystem)
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
*Created by `/upgrade-deps`. Will be validated before any changes are applied.*
|
|
309
|
+
ISSUE_EOF
|
|
310
|
+
)"
|
|
311
|
+
fi
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### 3B: Batch patch issue (when `--batch` is set)
|
|
315
|
+
|
|
316
|
+
Group multiple patch-level packages into one issue:
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
BATCH_PACKAGE_LIST=$(printf '- `%s`: %s → %s\n' {PACKAGE} {CURRENT} {LATEST})
|
|
320
|
+
|
|
321
|
+
# DRY_RUN guard — must stay above the create it guards (forge#1609).
|
|
322
|
+
if [ "$DRY_RUN" = "true" ]; then
|
|
323
|
+
echo "[DRY RUN] Would create batch issue: feat(deps): batch patch upgrades — {COUNT} packages ({DATE})"
|
|
324
|
+
echo "[DRY RUN] Packages: $BATCH_PACKAGE_LIST"
|
|
325
|
+
else
|
|
326
|
+
gh issue create $GH_FLAG \
|
|
327
|
+
--title "feat(deps): batch patch upgrades — {COUNT} packages ({DATE})" \
|
|
328
|
+
--label "enhancement" \
|
|
329
|
+
--body "$(cat <<'BATCH_ISSUE_EOF'
|
|
330
|
+
## Problem
|
|
331
|
+
|
|
332
|
+
{COUNT} dependencies have patch-level updates available. Patch upgrades are low-risk (semver guarantees no breaking changes) and are batched here for efficiency.
|
|
333
|
+
|
|
334
|
+
## Packages in This Batch
|
|
335
|
+
|
|
336
|
+
{BATCH_PACKAGE_LIST}
|
|
337
|
+
|
|
338
|
+
## Affected Files
|
|
339
|
+
|
|
340
|
+
1. `package.json` / `requirements.txt` / `Cargo.toml` — version constraint updates
|
|
341
|
+
2. Lockfile — regenerated after all updates
|
|
342
|
+
|
|
343
|
+
## Expected Behavior
|
|
344
|
+
|
|
345
|
+
All listed packages updated to their latest patch version. Full test suite passes.
|
|
346
|
+
|
|
347
|
+
## Acceptance Criteria
|
|
348
|
+
|
|
349
|
+
- [ ] All listed packages updated in the manifest
|
|
350
|
+
- [ ] Lockfile regenerated
|
|
351
|
+
- [ ] Test suite passes with no regressions
|
|
352
|
+
|
|
353
|
+
## Context
|
|
354
|
+
|
|
355
|
+
**Ecosystem**: {ECOSYSTEM}
|
|
356
|
+
**Semver level**: patch (all)
|
|
357
|
+
**Detected by**: `/upgrade-deps` cycle on {DATE}
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
*Batch created by `/upgrade-deps`. Investigate step will verify each package's patch notes.*
|
|
361
|
+
BATCH_ISSUE_EOF
|
|
362
|
+
)"
|
|
363
|
+
fi
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**DRY_RUN check**: enforced inline in 3A and 3B above — the guard wraps each `gh issue create` rather than being stated after it, so a dry run cannot create issues even if only one section is read in isolation (forge#1609).
|
|
367
|
+
|
|
368
|
+
Store created issue numbers as `CREATED_ISSUES` (empty when `DRY_RUN=true`).
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## Phase 4: Fix (requires `--fix` flag)
|
|
373
|
+
|
|
374
|
+
**Skip unless `--fix` was passed.**
|
|
375
|
+
|
|
376
|
+
For each issue in `CREATED_ISSUES`, invoke `/work-on` via the Skill tool:
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
Skill(skill: "work-on", args: "{ISSUE_NUMBER}")
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Run **sequentially** — each `/work-on` invocation is heavyweight. If one fails, continue to the next and record the outcome.
|
|
383
|
+
|
|
384
|
+
Track outcomes:
|
|
385
|
+
|
|
386
|
+
```
|
|
387
|
+
FIX_RESULTS = [
|
|
388
|
+
{ issue: NUMBER, outcome: "merged" | "invalid" | "failed" | "needs-human", pr: PR_NUMBER | null }
|
|
389
|
+
]
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**DRY_RUN check**: If `DRY_RUN=true`, print what would be invoked but skip `Skill()` calls.
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Phase 5: Summary Report
|
|
397
|
+
|
|
398
|
+
Print a structured report at the end of every run:
|
|
399
|
+
|
|
400
|
+
```markdown
|
|
401
|
+
## /upgrade-deps Cycle Report — {DATE}
|
|
402
|
+
|
|
403
|
+
### Detection Results
|
|
404
|
+
| Ecosystem | Outdated | Eligible | Skipped (existing issue) | Skipped (excluded) | Major (human review) |
|
|
405
|
+
|-----------|----------|----------|--------------------------|-------------------|----------------------|
|
|
406
|
+
| npm | {N} | {N} | {N} | {N} | {N} |
|
|
407
|
+
| pip | {N} | {N} | {N} | {N} | {N} |
|
|
408
|
+
|
|
409
|
+
### Issues Created
|
|
410
|
+
{list with issue numbers and titles, or "None — use --fix=false dry-run or no --fix flag"}
|
|
411
|
+
|
|
412
|
+
### Major Upgrades (Human Review Required)
|
|
413
|
+
{list: package: current → latest [major], or "None detected"}
|
|
414
|
+
|
|
415
|
+
### Fix Results (only if --fix was passed)
|
|
416
|
+
| Issue | Package | Outcome | PR |
|
|
417
|
+
|-------|---------|---------|-----|
|
|
418
|
+
| #{N} | {pkg} | merged | #{PR} |
|
|
419
|
+
|
|
420
|
+
### Next Steps
|
|
421
|
+
- [ ] Review major upgrades above and create issues manually if appropriate
|
|
422
|
+
- [ ] Set `upgrade_deps.exclude` in `forge.yaml` for packages that should never auto-upgrade
|
|
423
|
+
- [ ] Run `/upgrade-deps --fix` to also execute the pipeline for created issues
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Scheduling via GitHub Actions
|
|
429
|
+
|
|
430
|
+
To run `/upgrade-deps` on a schedule, add a workflow to `.github/workflows/upgrade-deps.yml` in your project:
|
|
431
|
+
|
|
432
|
+
```yaml
|
|
433
|
+
# .github/workflows/upgrade-deps.yml
|
|
434
|
+
# Runs /upgrade-deps weekly — creates GitHub issues for outdated deps.
|
|
435
|
+
# Issues flow through the ForgeDock pipeline: investigate → build → review → merge.
|
|
436
|
+
name: Weekly Dependency Upgrade Check
|
|
437
|
+
|
|
438
|
+
on:
|
|
439
|
+
schedule:
|
|
440
|
+
- cron: '0 9 * * 1' # Every Monday at 09:00 UTC
|
|
441
|
+
workflow_dispatch: # Allow manual trigger
|
|
442
|
+
|
|
443
|
+
jobs:
|
|
444
|
+
upgrade-deps:
|
|
445
|
+
runs-on: ubuntu-latest
|
|
446
|
+
permissions:
|
|
447
|
+
contents: read
|
|
448
|
+
issues: write
|
|
449
|
+
|
|
450
|
+
steps:
|
|
451
|
+
- uses: actions/checkout@v4
|
|
452
|
+
|
|
453
|
+
- name: Set up Claude Code
|
|
454
|
+
run: npm install -g @anthropic-ai/claude-code
|
|
455
|
+
|
|
456
|
+
- name: Run /upgrade-deps
|
|
457
|
+
env:
|
|
458
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
459
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
460
|
+
run: |
|
|
461
|
+
claude -p "/upgrade-deps --limit 5" --allowedTools "Bash,Read,Write,Edit,Glob,Grep"
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
> **Note**: The workflow above creates issues only (no `--fix`). To also invoke `/work-on` from CI, add `--fix` to the claude command. Each `/work-on` run uses Anthropic API credits proportional to issue complexity. Review your budget before enabling `--fix` in scheduled workflows.
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
## forge.yaml Configuration Reference
|
|
469
|
+
|
|
470
|
+
Add an `upgrade_deps` section to your `forge.yaml` to configure the command:
|
|
471
|
+
|
|
472
|
+
```yaml
|
|
473
|
+
# upgrade_deps (OPTIONAL)
|
|
474
|
+
# Controls /upgrade-deps behavior.
|
|
475
|
+
upgrade_deps:
|
|
476
|
+
# Ecosystems to check (default: ["npm"])
|
|
477
|
+
ecosystems:
|
|
478
|
+
- npm
|
|
479
|
+
- pip
|
|
480
|
+
# - cargo # requires: cargo install cargo-outdated
|
|
481
|
+
|
|
482
|
+
# Whether to create issues for major version upgrades (default: false)
|
|
483
|
+
# Major upgrades carry breaking-change risk — enable only with human review process.
|
|
484
|
+
allow_major: false
|
|
485
|
+
|
|
486
|
+
# Packages to never auto-upgrade (excluded from issue creation and /work-on)
|
|
487
|
+
# Useful for packages with known breaking changes or intentional version pins.
|
|
488
|
+
exclude:
|
|
489
|
+
# - "some-package" # example: pinned intentionally
|
|
490
|
+
|
|
491
|
+
# How many patch packages to group per batch issue when --batch is used (default: 5)
|
|
492
|
+
issue_batch_size: 5
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## Safety Rules
|
|
498
|
+
|
|
499
|
+
1. **NEVER bump a major version without `--allow-major`** — major upgrades have breaking-change risk and require human review.
|
|
500
|
+
2. **NEVER bypass the deduplication check** — if an open issue already tracks an upgrade, skip it.
|
|
501
|
+
3. **NEVER create more than `ISSUE_LIMIT` issues per run** — prevents runaway issue flooding.
|
|
502
|
+
4. **NEVER skip `/work-on` investigation** — every upgrade goes through full pipeline (investigate compatibility, build, test, review). A blind version bump PR is not a valid outcome.
|
|
503
|
+
5. **DRY_RUN means NO side effects** — no issues created, no `/work-on` calls. Report only.
|
|
504
|
+
6. **NEVER run cargo-outdated if cargo-outdated is not installed** — detect tool availability first.
|
|
505
|
+
7. **NEVER upgrade excluded packages** — respect the `upgrade_deps.exclude` list in `forge.yaml`.
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## Integration with /autopilot
|
|
510
|
+
|
|
511
|
+
`/upgrade-deps` is a peer to `/autopilot` — both create issues and optionally invoke `/work-on`. They are complementary:
|
|
512
|
+
|
|
513
|
+
| Command | Signal source | Scope |
|
|
514
|
+
|---------|--------------|-------|
|
|
515
|
+
| `/autopilot` | Production health, CI failures, backlog | Platform operational health |
|
|
516
|
+
| `/upgrade-deps` | Package registries (npm, pip, cargo) | Dependency freshness |
|
|
517
|
+
|
|
518
|
+
`/autopilot` does NOT detect outdated dependencies. Use `/upgrade-deps` for dependency-specific work, and pair it with `/autopilot` for full-spectrum platform maintenance.
|
package/commands/validate.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Independently verify if a reported issue is actually a problem before making code changes.
|
|
3
|
-
argument-hint: [issue description or #number]
|
|
3
|
+
argument-hint: "[issue description or #number]"
|
|
4
4
|
install: extras
|
|
5
5
|
---
|
|
6
6
|
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
@@ -91,10 +91,17 @@ If CONFIRMED — recommended next step:
|
|
|
91
91
|
Root cause: [one sentence]
|
|
92
92
|
Fix approach: [one sentence]
|
|
93
93
|
Create issue:
|
|
94
|
+
Route through the `/issue` create-hook's programmatic invocation contract (see `commands/issue.md` § "Programmatic Invocation Contract") instead of calling the raw issue-creation command directly — this gets dedup (Phase 2D) and body validation (Phase 3F) for free:
|
|
95
|
+
|
|
94
96
|
```bash
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
VALIDATE_ISSUE_TITLE="fix: [concise description of the confirmed bug]"
|
|
98
|
+
# Defense-in-depth: /issue's arg tokenizer (commands/issue.md, forge#2094) uses
|
|
99
|
+
# an xargs-based tokenizer that never expands backtick/$(...) substitution, so
|
|
100
|
+
# this is no longer required for safety — but strip it anyway so the raw title
|
|
101
|
+
# stays readable if it round-trips through any other eval-based consumer.
|
|
102
|
+
VALIDATE_ISSUE_TITLE=$(printf '%s' "$VALIDATE_ISSUE_TITLE" | tr '`' "'" | sed 's/\$(/$ (/g')
|
|
103
|
+
VALIDATE_ISSUE_BODY_FILE=$(mktemp)
|
|
104
|
+
cat <<'BODY_EOF' > "$VALIDATE_ISSUE_BODY_FILE"
|
|
98
105
|
## Problem
|
|
99
106
|
|
|
100
107
|
[1-3 sentences: what the validation confirmed is wrong. Specific and concrete.]
|
|
@@ -123,7 +130,11 @@ Validated by \`/validate\` on [DATE]. Confidence: [High|Medium|Low].
|
|
|
123
130
|
- [source]: [finding]
|
|
124
131
|
- [source]: [finding]
|
|
125
132
|
BODY_EOF
|
|
126
|
-
|
|
133
|
+
|
|
134
|
+
# [priority] and [bug|enhancement] are two separate labels — passed as repeated --label flags,
|
|
135
|
+
# never comma-joined (the /issue programmatic contract's --label is repeatable, not CSV).
|
|
136
|
+
Skill(skill="issue", args="--title \"$VALIDATE_ISSUE_TITLE\" --body-file \"$VALIDATE_ISSUE_BODY_FILE\" --label \"[priority]\" --label \"[bug|enhancement]\"")
|
|
137
|
+
rm -f "$VALIDATE_ISSUE_BODY_FILE"
|
|
127
138
|
```
|
|
128
139
|
|
|
129
140
|
If NOT A PROBLEM — why the report was wrong:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Pre-implementation architecture planning — traces ALL affected code paths and produces an ordered implementation plan before any code is written
|
|
3
|
-
argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--files AFFECTED_FILES]
|
|
3
|
+
argument-hint: "[issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--files AFFECTED_FILES]"
|
|
4
4
|
---
|
|
5
5
|
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
6
6
|
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Pre-implementation context gathering — surfaces historical findings, bug patterns, and related code paths before the builder writes any code
|
|
3
|
-
argument-hint: [issue number] [affected_files...] [--functions function_names...]
|
|
3
|
+
argument-hint: "[issue number] [affected_files...] [--functions function_names...]"
|
|
4
4
|
---
|
|
5
5
|
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
6
6
|
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Implementation agent — writes code, makes commits, posts builder comment
|
|
3
|
-
argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--branch BRANCH]
|
|
3
|
+
argument-hint: "[issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--branch BRANCH]"
|
|
4
4
|
---
|
|
5
5
|
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
6
6
|
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
@@ -102,7 +102,7 @@ Extract from contract:
|
|
|
102
102
|
| Refactor / Maintenance | Implement directly following contract deliverables |
|
|
103
103
|
| Investigation | Spawn research agents, create GitHub issues for findings, skip to I5 |
|
|
104
104
|
|
|
105
|
-
**Investigation task special case**: Research deeply, create GitHub issues for each finding using the Pipeline Issue Template (see `commands/issue.md` § "Pipeline Issue Template"). Each issue MUST include `## Problem`, `## Affected Files`, and `## Acceptance Criteria`.
|
|
105
|
+
**Investigation task special case**: Research deeply, create GitHub issues for each finding using the Pipeline Issue Template (see `commands/issue.md` § "Pipeline Issue Template"). Each issue MUST include `## Problem`, `## Affected Files`, and `## Acceptance Criteria`. Create each issue via the `/issue` create-hook's programmatic invocation contract (see `commands/issue.md` § "Programmatic Invocation Contract") — `Skill(skill="issue", args="--title \"...\" --body-file <path> --label ...")` — instead of calling the raw issue-creation command directly; this gets dedup and body validation for free. Post a deliverables comment listing the created issues, close the original issue, return `IMPLEMENT_RESULT: status: INVESTIGATION_COMPLETE`.
|
|
106
106
|
|
|
107
107
|
---
|
|
108
108
|
|