forgedock 1.2.0 → 1.4.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 +8 -2
- package/bin/batch-runner.mjs +31 -2
- package/bin/engine/admission.mjs +294 -0
- package/bin/engine/admission.test.mjs +265 -0
- package/bin/engine/invariants.mjs +17 -4
- package/bin/engine/phases.mjs +358 -42
- package/bin/engine/resolve.mjs +256 -0
- package/bin/engine/resolve.test.mjs +149 -0
- package/bin/engine/state.mjs +31 -7
- package/bin/engine-cli.mjs +138 -2
- package/bin/engine.mjs +414 -21
- package/bin/forgedock.mjs +552 -44
- package/bin/hooks/interactive-engine.mjs +50 -24
- package/bin/hooks/pre-tool-use.mjs +189 -19
- package/bin/journey.mjs +109 -11
- package/bin/labels.json +5 -0
- package/bin/runner.mjs +321 -10
- package/bin/watch-utils.mjs +255 -0
- package/commands/cleanup.md +7 -3
- package/commands/forge-stats.md +5 -4
- package/commands/issue.md +5 -1
- package/commands/orchestrate/config.md +41 -1
- package/commands/orchestrate/phase-1-resolve.md +234 -8
- package/commands/orchestrate/phase-3-dependency.md +27 -18
- package/commands/orchestrate/phase-4-execution.md +223 -22
- package/commands/qa-sweep.md +17 -0
- package/commands/quality-gate.md +6 -6
- package/commands/replay.md +16 -2
- package/commands/review-pr-agents/spec-cli.md +179 -0
- package/commands/review-pr.md +65 -0
- package/commands/upgrade-deps.md +523 -0
- package/commands/work-on/build/validate.md +61 -1
- package/commands/work-on/build.md +9 -1
- package/commands/work-on/decompose.md +10 -1
- package/commands/work-on/investigate.md +22 -4
- package/commands/work-on/remediate.md +2 -0
- package/commands/work-on/review.md +40 -1
- package/commands/work-on.md +19 -4
- package/docs/AIDER.md +264 -0
- package/docs/AUTOPILOT-CRON.md +130 -0
- package/docs/CONFIG.md +156 -0
- 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/architecture.md +180 -0
- package/docs/site/command-reference.md +17 -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/eval-run-result.md +8 -4
- package/docs/spec/label-state-machine.md +9 -0
- package/docs/spec-graph-schema.md +3 -3
- package/package.json +3 -3
- 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 +5 -11
- package/packages/protocol/src/html-comment-escape.js +68 -0
- package/packages/protocol/src/index.js +3 -1
- package/packages/protocol/src/parse.js +19 -11
- package/packages/protocol/src/phases.js +105 -0
- package/packages/protocol/src/types.js +18 -1
- package/packages/protocol/src/validate.js +11 -0
- package/scripts/check-admission-parity.mjs +167 -0
- package/scripts/check-command-side-effects.sh +376 -0
- package/scripts/check-phase-registry-drift.mjs +96 -0
- package/scripts/check-spec-markers.sh +274 -0
- package/scripts/classify-lane.sh +29 -7
- package/scripts/forge-run.sh +353 -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
package/docs/CONFIG.md
CHANGED
|
@@ -48,6 +48,8 @@ If you have both a local `claude` CLI and `ANTHROPIC_API_KEY` set and want to pi
|
|
|
48
48
|
| [`agents`](#agents-optional) | No | Default model for pipeline agents |
|
|
49
49
|
| [`repos`](#repos-optional) | No | Multi-repository routing |
|
|
50
50
|
| [`project_board`](#project_board-optional) | No | GitHub Projects v2 integration |
|
|
51
|
+
| [`orchestration`](#orchestration-optional) | No | `/orchestrate` concurrency and cascade admission policy |
|
|
52
|
+
| [`pipeline`](#pipeline-optional) | No | `/orchestrate` batch-engine tuning (stall detection, token budget, narration) |
|
|
51
53
|
| [`services`](#services-optional) | No | External service URLs and IDs |
|
|
52
54
|
| [`review`](#review-optional) | No | Context injected into review agents |
|
|
53
55
|
| [`devdocs`](#devdocs-optional) | No | Devdocs knowledge tree path |
|
|
@@ -210,6 +212,9 @@ repos:
|
|
|
210
212
|
| `satellites[].local_path` | string | No | Absolute local path to the satellite repo's checkout |
|
|
211
213
|
| `satellites[].subpaths` | map(string→string) | No | Named sub-directory paths within `local_path`, for monorepo satellites that publish multiple packages. Each key is a logical name; the value is the relative path to that package's root. Used by `/sync-ecosystem` to locate per-package version files and publish workflows. |
|
|
212
214
|
| `satellites[].billing_enabled` | boolean | No | Set to `true` to run Phase 4 (Financial Integrity) of `/security-audit` against this satellite repo. Mirrors the top-level [`billing.enabled`](#billing-optional) flag but scoped per-satellite. Defaults to `false` when absent. |
|
|
215
|
+
| `satellites[].trigger_on_merge` | boolean | No | When `true`, fires a cross-repo trigger when a PR merges in the parent repo and touches paths matching `trigger_paths`. Set to `false` to disable triggering for this satellite. Defaults to `true` when `trigger_paths` is present; otherwise has no effect until runtime trigger support is configured. |
|
|
216
|
+
| `satellites[].trigger_paths` | list of strings | No | Path glob patterns that constrain when the trigger fires. Uses GitHub Actions glob syntax (same as `on: push: paths:`). The trigger fires only when at least one changed file matches a pattern in this list. When omitted, the trigger fires on every merge (if `trigger_on_merge: true`). |
|
|
217
|
+
| `satellites[].auto_run` | boolean | No | When `true`, automatically invokes `/work-on` on the satellite issue when the cross-repo trigger fires. Requires a running Claude Code session with ForgeDock installed in the satellite repo. Advanced opt-in — defaults to `false`. Do not set to `true` unless a persistent Claude Code session is available in the satellite repo. |
|
|
213
218
|
|
|
214
219
|
**Routing syntax in commands**: `<prefix>:<issue_number>` — e.g., `mcp:5`, `sdk:12`
|
|
215
220
|
|
|
@@ -287,6 +292,124 @@ gh project field-list <project_number> --owner <owner> --format json \
|
|
|
287
292
|
|
|
288
293
|
---
|
|
289
294
|
|
|
295
|
+
## `orchestration` (OPTIONAL)
|
|
296
|
+
|
|
297
|
+
Concurrency limits and cascade admission policy for `/orchestrate`'s batch engine. Previously read at runtime (`orchestration.max_concurrent`) but undocumented; this section is the first place it — and the newer `cascade` sub-section (forge#2234) — are formally specified.
|
|
298
|
+
|
|
299
|
+
```yaml
|
|
300
|
+
orchestration:
|
|
301
|
+
# Maximum number of /work-on sub-agents dispatched concurrently. Guards against
|
|
302
|
+
# saturating the Anthropic API rate limit in one burst on a large ready set.
|
|
303
|
+
# Default: 12.
|
|
304
|
+
max_concurrent: 12
|
|
305
|
+
|
|
306
|
+
cascade:
|
|
307
|
+
# Named preset expanding to the granular keys below. Any granular key set
|
|
308
|
+
# explicitly overrides just that field — the preset supplies defaults, not
|
|
309
|
+
# hard values. Default: "balanced".
|
|
310
|
+
# all — admit everything: no generation cap, no token cap, every
|
|
311
|
+
# heuristic-based defer disabled. For a maintainer draining
|
|
312
|
+
# a backlog who wants /orchestrate to "pick up everything."
|
|
313
|
+
# balanced — the pre-#2234 hardcoded behavior, unchanged: generation
|
|
314
|
+
# cap at 1 (i.e. cascade-spawned findings deferred),
|
|
315
|
+
# 900000-token per-batch ceiling, idle/keyword/same-file
|
|
316
|
+
# heuristics all active.
|
|
317
|
+
# conservative — same admission shape as balanced, with a lower
|
|
318
|
+
# (450000) token ceiling for cost-sensitive or noisy repos.
|
|
319
|
+
policy: "balanced"
|
|
320
|
+
|
|
321
|
+
# Maximum cascade generation depth admitted. Generation 1 = an original
|
|
322
|
+
# issue (not spawned from a review-finding). Generation 2 = spawned from a
|
|
323
|
+
# review-finding. Generation 3 = spawned from a finding that was itself
|
|
324
|
+
# spawned from a review-finding. Accepts a positive integer or the literal
|
|
325
|
+
# string "unlimited". Governs Phase 1 resolve-time admission only (the
|
|
326
|
+
# `cascade`/`review-findings`/`findings` resolution in phase-1-resolve.md)
|
|
327
|
+
# — it does NOT relax Step 4C's absolute autonomous-cascade defer, which
|
|
328
|
+
# stays hardcoded regardless of this value (see phase-4-execution.md Step
|
|
329
|
+
# 4C rule 1). This is what makes "admit gen-2, stop at gen-3" expressible,
|
|
330
|
+
# which the pre-#2234 --allow-gen2 flag (all-or-nothing) could not say.
|
|
331
|
+
# Default: 1 (from the "balanced" preset); "unlimited" under "all".
|
|
332
|
+
max_generation: 1
|
|
333
|
+
|
|
334
|
+
# Per-batch token ceiling for Step 4C's review-finding cascade dispatch.
|
|
335
|
+
# New home for the same lever previously read only as
|
|
336
|
+
# `pipeline.token_budget_per_batch` (kept working as a deprecated alias —
|
|
337
|
+
# see the `pipeline` section below). Accepts a positive integer or
|
|
338
|
+
# "unlimited". Default: 900000 (from "balanced"); 450000 under
|
|
339
|
+
# "conservative"; "unlimited" under "all".
|
|
340
|
+
token_budget: 900000
|
|
341
|
+
|
|
342
|
+
# Whether a fully human-gated original batch (forge#1814's
|
|
343
|
+
# BATCH_FULLY_GATED — every original-batch issue DONE/FAILED/GATED with at
|
|
344
|
+
# least one GATED) suppresses further cascade-finding dispatch. Default:
|
|
345
|
+
# true (from "balanced"); false under "all".
|
|
346
|
+
defer_on_batch_gated: true
|
|
347
|
+
|
|
348
|
+
# Whether the comment/typo title-keyword heuristic defers P3-and-below
|
|
349
|
+
# cascade findings. Default: true (from "balanced"); false under "all".
|
|
350
|
+
keyword_heuristic: true
|
|
351
|
+
|
|
352
|
+
# Whether a P3 finding sharing a file with the active batch is deferred
|
|
353
|
+
# (avoids serializing agents on same-file predecessor edges). Default:
|
|
354
|
+
# true (from "balanced"); false under "all".
|
|
355
|
+
p3_same_file_defer: true
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
| Field | Type | Required | Description |
|
|
359
|
+
|-------|------|----------|-------------|
|
|
360
|
+
| `max_concurrent` | integer | No | Max concurrent `/work-on` sub-agent dispatch. Default: 12 |
|
|
361
|
+
| `cascade.policy` | string | No | `all` \| `balanced` \| `conservative`. Default: `balanced` |
|
|
362
|
+
| `cascade.max_generation` | integer or `"unlimited"` | No | Max cascade generation admitted at Phase 1 resolve time. Default: 1 |
|
|
363
|
+
| `cascade.token_budget` | integer or `"unlimited"` | No | Per-batch token ceiling for Step 4C cascade dispatch. Default: 900000 (deprecated alias: `pipeline.token_budget_per_batch`) |
|
|
364
|
+
| `cascade.defer_on_batch_gated` | boolean | No | Suppress cascade dispatch when the original batch is fully human-gated. Default: `true` |
|
|
365
|
+
| `cascade.keyword_heuristic` | boolean | No | Defer P3-and-below comment/typo-titled findings. Default: `true` |
|
|
366
|
+
| `cascade.p3_same_file_defer` | boolean | No | Defer P3 findings sharing a file with the active batch. Default: `true` |
|
|
367
|
+
|
|
368
|
+
**Hard invariant — not configurable**: safety exclusions (findings whose `## Problem` section indicates security/billing/anti-bot/auth concerns) are never batched and never auto-admitted by any `cascade.policy`, including `all`. That exclusion is enforced upstream of this section (the P3 batching eligibility check) and has no corresponding key here by design.
|
|
369
|
+
|
|
370
|
+
**CLI overrides**: `--policy`, `--max-generation`, `--token-budget` on `/orchestrate` take precedence over these keys for a single invocation — see `commands/orchestrate/config.md` → "Cascade Policy CLI Flags".
|
|
371
|
+
|
|
372
|
+
**Commands that use this section**: `orchestrate`
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## `pipeline` (OPTIONAL)
|
|
377
|
+
|
|
378
|
+
Tuning knobs for `/orchestrate`'s batch engine — stall detection, narration verbosity, and (deprecated alias only, see `orchestration.cascade` above) the review-finding cascade token budget. All keys optional; sane defaults apply when omitted.
|
|
379
|
+
|
|
380
|
+
```yaml
|
|
381
|
+
pipeline:
|
|
382
|
+
# Minutes an agent may sit idle (no FORGE:HEARTBEAT / label change) before
|
|
383
|
+
# /orchestrate's stall detector treats it as stuck and attempts an
|
|
384
|
+
# auto-resume. Default: 15.
|
|
385
|
+
stall_timeout_minutes: 15
|
|
386
|
+
|
|
387
|
+
# Deprecated alias for orchestration.cascade.token_budget (forge#2234) — kept
|
|
388
|
+
# working so existing configs are unaffected. When both are set,
|
|
389
|
+
# orchestration.cascade.token_budget wins. Default: 900000.
|
|
390
|
+
token_budget_per_batch: 900000
|
|
391
|
+
|
|
392
|
+
# Estimated token cost of a single P3-or-lower review-finding /work-on
|
|
393
|
+
# pipeline, used to decrement the token budget above. Default: 150000.
|
|
394
|
+
token_estimate_per_finding: 150000
|
|
395
|
+
|
|
396
|
+
# Narration verbosity for /orchestrate's per-completion status updates.
|
|
397
|
+
# "terse" (default): one line per completion. "verbose": adds a running
|
|
398
|
+
# per-completion recap table. Cosmetic only — never changes which phases run.
|
|
399
|
+
narration: "terse"
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
| Field | Type | Required | Description |
|
|
403
|
+
|-------|------|----------|-------------|
|
|
404
|
+
| `stall_timeout_minutes` | integer | No | Idle minutes before the stall detector attempts auto-resume. Default: 15 |
|
|
405
|
+
| `token_budget_per_batch` | integer | No | **Deprecated** — use `orchestration.cascade.token_budget`. Default: 900000 |
|
|
406
|
+
| `token_estimate_per_finding` | integer | No | Estimated tokens per P3-or-lower cascade finding. Default: 150000 |
|
|
407
|
+
| `narration` | string | No | `terse` \| `verbose`. Default: `terse` |
|
|
408
|
+
|
|
409
|
+
**Commands that use this section**: `orchestrate`
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
290
413
|
## `services` (OPTIONAL)
|
|
291
414
|
|
|
292
415
|
External service endpoints and identifiers. Used by analytics and monitoring commands.
|
|
@@ -609,6 +732,39 @@ Colors are grouped by semantic meaning:
|
|
|
609
732
|
|
|
610
733
|
---
|
|
611
734
|
|
|
735
|
+
## `branding` (OPTIONAL)
|
|
736
|
+
|
|
737
|
+
Controls attribution in FORGE annotation comments posted to GitHub issues and PRs by pipeline commands.
|
|
738
|
+
|
|
739
|
+
When `show_attribution` is `true` (the default), every annotation comment (`FORGE:INVESTIGATOR`, `FORGE:CONTRACT`, `FORGE:BUILDER`, `FORGE:TRAJECTORY`, `FORGE:DECOMPOSED`, etc.) ends with a one-line footer:
|
|
740
|
+
|
|
741
|
+
```
|
|
742
|
+
> Pipeline powered by [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock)
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
This follows the pattern established by Dependabot, Renovate, and similar tools. It helps new users discover the tooling when they encounter FORGE: annotations in a public thread. Set to `false` to suppress the attribution entirely.
|
|
746
|
+
|
|
747
|
+
```yaml
|
|
748
|
+
branding:
|
|
749
|
+
show_attribution: true
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
| Field | Type | Required | Default | Description |
|
|
753
|
+
|-------|------|----------|---------|-------------|
|
|
754
|
+
| `show_attribution` | boolean | No | `true` | When `true`, annotation comments posted by the pipeline include a one-line attribution footer. Set to `false` to suppress it entirely. Opt-out model — attribution is on by default. |
|
|
755
|
+
|
|
756
|
+
**Commands that use this section**: `work-on` (all phases that post FORGE: annotation comments)
|
|
757
|
+
|
|
758
|
+
**Config read pattern** (yq, with default-true fallback):
|
|
759
|
+
|
|
760
|
+
```bash
|
|
761
|
+
SHOW_ATTRIBUTION=$(yq '.branding.show_attribution // "true"' forge.yaml 2>/dev/null || echo "true")
|
|
762
|
+
[ "$SHOW_ATTRIBUTION" = "false" ] && ATTRIBUTION_LINE="" || ATTRIBUTION_LINE="
|
|
763
|
+
> Pipeline powered by [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock)"
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
---
|
|
767
|
+
|
|
612
768
|
## GitHub App Install
|
|
613
769
|
|
|
614
770
|
During `npx forgedock`, the installer prompts you to install the ForgeDock GitHub App (`rapiercraft-forgedock`) on your account or org.
|
package/docs/CURSOR.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Cursor Support
|
|
2
|
+
|
|
3
|
+
ForgeDock has a Cursor adapter that lets Cursor Agent mode run the ForgeDock pipeline via shell commands and the `gh` CLI.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
Shared source:
|
|
8
|
+
- `commands/**/*.md` remains the canonical workflow spec for all runtimes
|
|
9
|
+
|
|
10
|
+
Cursor wrapper:
|
|
11
|
+
- `templates/cursor/forge.mdc` — a static Cursor rules file that instructs Cursor Agent to execute pipeline phases using shell commands, `gh` CLI, and `git`
|
|
12
|
+
- Users install this file into their repo's `.cursor/rules/forge.mdc`
|
|
13
|
+
|
|
14
|
+
This is a static injection model, not a dynamic skill-loading mechanism. The adapter cannot replicate Claude Code's `Skill()` invocation or Codex's installed skill wrappers. Instead, it instructs the agent to read command specs directly from `commands/` and execute them using available terminal tools.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
### Automatic (via `npx forgedock`)
|
|
19
|
+
|
|
20
|
+
If your project already has a `.cursor/` directory, `npx forgedock` will detect it and automatically write `templates/cursor/forge.mdc` to `.cursor/rules/forge.mdc`:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx forgedock
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The installer skips this step if `.cursor/rules/forge.mdc` already exists (idempotent — never overwrites customizations).
|
|
27
|
+
|
|
28
|
+
### Manual
|
|
29
|
+
|
|
30
|
+
Copy the template directly:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
mkdir -p .cursor/rules
|
|
34
|
+
cp node_modules/forgedock/templates/cursor/forge.mdc .cursor/rules/forge.mdc
|
|
35
|
+
# or, if installed globally:
|
|
36
|
+
cp "$(npx forgedock which-dir)/templates/cursor/forge.mdc" .cursor/rules/forge.mdc
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Commit the file to version control so all team members get it:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git add .cursor/rules/forge.mdc
|
|
43
|
+
git commit -m "chore: add ForgeDock Cursor rules adapter"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
### Running the Pipeline
|
|
49
|
+
|
|
50
|
+
Open a Cursor Agent session and describe the pipeline task:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
Work on GitHub issue #123 using the ForgeDock pipeline.
|
|
54
|
+
Read commands/work-on.md and follow all phases.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The rules file will instruct Cursor Agent to:
|
|
58
|
+
|
|
59
|
+
1. Load issue context from GitHub using `gh issue view`
|
|
60
|
+
2. Follow the Universal Phase Dispatcher in `commands/work-on.md`
|
|
61
|
+
3. Write FORGE annotations (HTML comments) to issue comments after each phase
|
|
62
|
+
4. Transition `workflow:*` labels as phases complete
|
|
63
|
+
5. Continue until a terminal label is set
|
|
64
|
+
|
|
65
|
+
### Checking Pipeline State
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# See current workflow state
|
|
69
|
+
gh issue view NUMBER --json labels --jq '[.labels[].name]'
|
|
70
|
+
|
|
71
|
+
# Read existing pipeline annotations
|
|
72
|
+
gh api repos/OWNER/REPO/issues/NUMBER/comments \
|
|
73
|
+
--jq '.[] | select(.body | contains("FORGE:")) | {body: .body[:200]}'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Continuing After a Phase
|
|
77
|
+
|
|
78
|
+
Because Cursor Agent mode does not persist between invocations, start a new session and describe the resume:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Resume the ForgeDock pipeline for GitHub issue #123.
|
|
82
|
+
Read commands/work-on.md — it will re-read GitHub state and pick up from the current label.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The pipeline is designed for compaction resilience — every phase re-reads GitHub state at the start, so a new Cursor Agent session picks up exactly where the previous session left off.
|
|
86
|
+
|
|
87
|
+
## Limitations
|
|
88
|
+
|
|
89
|
+
| Capability | Claude Code | Cursor (this adapter) |
|
|
90
|
+
|------------|-------------|----------------------|
|
|
91
|
+
| Skill loading | Dynamic (`~/.claude/commands/`) | Static (this rules file) |
|
|
92
|
+
| Multi-phase pipeline | Automatic (single continuous session) | Manual (re-invoke agent per phase) |
|
|
93
|
+
| Sub-skill invocation | `Skill("review-pr")` | Read `commands/review-pr.md` directly |
|
|
94
|
+
| Session continuity | Native compaction resilience | Re-read GitHub state each invocation |
|
|
95
|
+
| Tool set | Claude-native (`Bash`, `Read`, `Grep`, `Glob`, `WebFetch`) | Cursor Agent terminal tools |
|
|
96
|
+
|
|
97
|
+
### Multi-Phase Pipeline
|
|
98
|
+
|
|
99
|
+
The ForgeDock pipeline has 7 phases (investigate → build → review → merge → close → trajectory). Cursor Agent mode does not automatically advance through all phases in a single session. After each phase completes, you will need to start a new agent invocation and ask it to continue.
|
|
100
|
+
|
|
101
|
+
The pipeline's compaction resilience handles this correctly: each invocation re-reads the issue's labels and comments, determines the current phase, and continues from there. No context is lost between sessions.
|
|
102
|
+
|
|
103
|
+
### Sub-Skill Invocation
|
|
104
|
+
|
|
105
|
+
When the pipeline spec calls `Skill("review-pr")` or `Skill("quality-gate")`, Cursor Agent should read the referenced command spec file directly:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cat commands/review-pr.md # Then execute that spec
|
|
109
|
+
cat commands/quality-gate.md
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Project Board Steps
|
|
113
|
+
|
|
114
|
+
Some pipeline phases (0C: Sync to Project board) call GitHub Projects API operations. These work via `gh` CLI but require the project number and field IDs from `forge.yaml`. Verify your `forge.yaml` has the correct project configuration before running the pipeline.
|
|
115
|
+
|
|
116
|
+
## Configuration
|
|
117
|
+
|
|
118
|
+
ForgeDock reads `forge.yaml` for project-specific settings:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
cat forge.yaml # Review before running the pipeline
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Key fields used by the pipeline:
|
|
125
|
+
- `project.github.owner` / `project.github.repo` — GitHub repo coordinates
|
|
126
|
+
- `branches.staging` — target branch for fast-lane PRs
|
|
127
|
+
- `branches.main` — default branch
|
|
128
|
+
|
|
129
|
+
## Reference
|
|
130
|
+
|
|
131
|
+
- `commands/work-on.md` — Full pipeline spec (all phases)
|
|
132
|
+
- `commands/review-pr.md` — PR review spec
|
|
133
|
+
- `commands/quality-gate.md` — Pre-commit quality checks (14+ domains)
|
|
134
|
+
- `docs/FORGE-PROTOCOL.md` — FORGE annotation protocol specification
|
|
135
|
+
- `docs/CODEX.md` — Codex CLI adapter (dynamic skill model)
|
package/docs/OPENCODE.md
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# OpenCode Support
|
|
2
|
+
|
|
3
|
+
ForgeDock has an OpenCode adapter that lets OpenCode run the ForgeDock pipeline
|
|
4
|
+
using its native bash tool and the `gh` CLI.
|
|
5
|
+
|
|
6
|
+
## Architecture
|
|
7
|
+
|
|
8
|
+
Shared source:
|
|
9
|
+
- `commands/**/*.md` remains the workflow spec for all runtimes
|
|
10
|
+
|
|
11
|
+
Claude Code wrapper:
|
|
12
|
+
- `install.sh` (or `npx forgedock`) symlinks command files into `~/.claude/commands/`
|
|
13
|
+
|
|
14
|
+
Codex wrapper:
|
|
15
|
+
- `install-codex.sh` generates namespaced skills in `~/.codex/skills/`
|
|
16
|
+
|
|
17
|
+
Aider wrapper:
|
|
18
|
+
- `install-aider.sh` writes `~/.aider-forge.md` loaded via `--read`
|
|
19
|
+
|
|
20
|
+
**OpenCode wrapper** (this document):
|
|
21
|
+
- `install-opencode.sh` writes `~/.opencode-forge.md` — a conventions file
|
|
22
|
+
OpenCode loads via the `instructions` field in `opencode.json`
|
|
23
|
+
- `install-opencode.sh` also patches `~/.config/opencode/opencode.json` to
|
|
24
|
+
register ForgeDock pipeline commands as native OpenCode slash commands
|
|
25
|
+
(`/work-on`, `/review-pr`, `/quality-gate`, `/orchestrate`)
|
|
26
|
+
|
|
27
|
+
This is a conventions-file + command-registration architecture. The shared
|
|
28
|
+
`commands/` directory remains the single source of truth — the adapter
|
|
29
|
+
registers entry points that read from it.
|
|
30
|
+
|
|
31
|
+
## Feasibility
|
|
32
|
+
|
|
33
|
+
OpenCode is the **highest-fidelity** non-Claude Code adapter because:
|
|
34
|
+
|
|
35
|
+
| Capability | Requirement | OpenCode support |
|
|
36
|
+
|-----------|-------------|-----------------|
|
|
37
|
+
| Load instruction files | `instructions` field in `opencode.json` | Native |
|
|
38
|
+
| Execute shell commands | `gh`, `git`, standard tools | Native `Bash` tool |
|
|
39
|
+
| Read/write files | File editing | Native `Read`/`Write`/`Edit` tools |
|
|
40
|
+
| GitHub API | `gh` CLI | Via `Bash("gh ...")` |
|
|
41
|
+
| Multi-step workflows | Follow sequential instructions | Supported |
|
|
42
|
+
| Compaction resilience | Re-read GitHub state at phase start | Supported (via `Bash("gh ...")`) |
|
|
43
|
+
| Native slash commands | `/work-on 967` in TUI | Via `command` config |
|
|
44
|
+
| Tool name parity | Same tool names as Claude Code | Direct — no translation needed |
|
|
45
|
+
|
|
46
|
+
**Key advantage over Aider and Cursor**: OpenCode shares Claude Code's tool
|
|
47
|
+
names (`Bash`, `Read`, `Write`, `Edit`, `Glob`, `Grep`, `WebFetch`) — no
|
|
48
|
+
translation table required for most operations. Pipeline command specs run
|
|
49
|
+
nearly unmodified.
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
### Option A — standalone bash installer
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd /path/to/forgedock
|
|
57
|
+
./install-opencode.sh
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This writes `~/.opencode-forge.md` with ForgeDock conventions and patches
|
|
61
|
+
`~/.config/opencode/opencode.json` with:
|
|
62
|
+
- `instructions`: adds `~/.opencode-forge.md` to OpenCode's system prompt
|
|
63
|
+
- `command`: registers `/work-on`, `/review-pr`, `/quality-gate`, `/orchestrate`
|
|
64
|
+
|
|
65
|
+
### Option B — via npx forgedock
|
|
66
|
+
|
|
67
|
+
When `opencode` is detected on your PATH, `npx forgedock` writes
|
|
68
|
+
`~/.opencode-forge.md` and patches `opencode.json` as an additional install
|
|
69
|
+
step. No existing Claude Code files are affected.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx forgedock
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Usage
|
|
76
|
+
|
|
77
|
+
### Native slash commands (recommended)
|
|
78
|
+
|
|
79
|
+
After running `install-opencode.sh`, use ForgeDock commands in the OpenCode
|
|
80
|
+
TUI:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
/work-on 967
|
|
84
|
+
/review-pr 123
|
|
85
|
+
/quality-gate
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Or headlessly via `opencode run`:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
opencode run --command work-on "967"
|
|
92
|
+
opencode run --command review-pr "123"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Manual pipeline loading
|
|
96
|
+
|
|
97
|
+
Read a pipeline command spec directly and follow it:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Read the file /path/to/forgedock/commands/work-on.md and run the pipeline for issue 967.
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
OpenCode will load the spec and execute each phase using its native tools.
|
|
104
|
+
|
|
105
|
+
### Phase routing with forge-run.sh
|
|
106
|
+
|
|
107
|
+
`forge-run.sh` emits JSON phase state for the current issue without invoking
|
|
108
|
+
an LLM. Use it to determine the current pipeline phase:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
Bash("/path/to/forgedock/scripts/forge-run.sh work-on 967 -R OWNER/REPO")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Output (NDJSON):
|
|
115
|
+
```json
|
|
116
|
+
{"event":"phase_detected","command":"work-on","issue":967,"phase":"no-comments","ts":"..."}
|
|
117
|
+
{"event":"phase_detail","phase":"no-comments","lane":"feature","branch":"milestone/dev-exp","labels":[]}
|
|
118
|
+
{"event":"action_required","phase":"no-comments","action":"No pipeline activity detected. Invoke /work-on 967 to start investigation.","ts":"..."}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Tool Translation
|
|
122
|
+
|
|
123
|
+
OpenCode and Claude Code share the same tool names. Most pipeline operations
|
|
124
|
+
run without modification:
|
|
125
|
+
|
|
126
|
+
| Claude Code | OpenCode | Notes |
|
|
127
|
+
|-------------|----------|-------|
|
|
128
|
+
| `Bash("git status")` | `Bash("git status")` | Direct |
|
|
129
|
+
| `Read("path/to/file")` | `Read("path/to/file")` | Direct |
|
|
130
|
+
| `Write("path", content)` | `Write("path", content)` | Direct |
|
|
131
|
+
| `Edit("path", ...)` | `Edit("path", ...)` | Direct |
|
|
132
|
+
| `Glob("**/*.md")` | `Glob("**/*.md")` | Direct |
|
|
133
|
+
| `Grep(pattern, path)` | `Grep(pattern, path)` | Direct |
|
|
134
|
+
| `WebFetch(url)` | `WebFetch(url)` | Direct |
|
|
135
|
+
| `Skill("work-on", args="123")` | Read `commands/work-on.md` | No skill loader — read spec directly |
|
|
136
|
+
| `Skill("review-pr", args="456")` | Read `commands/review-pr.md` | No skill loader — read spec directly |
|
|
137
|
+
| `Agent(...)` / `Task(...)` | Continue the sub-task inline | No sub-agent model; inline it |
|
|
138
|
+
|
|
139
|
+
### Nested Skill references
|
|
140
|
+
|
|
141
|
+
When a command spec calls `Skill("x")` or references another command, read
|
|
142
|
+
the referenced command spec directly:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
# Load the referenced command spec:
|
|
146
|
+
Read("/path/to/forgedock/commands/quality-gate.md")
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Map command names to file paths:
|
|
150
|
+
- `Skill("work-on")` → `commands/work-on.md`
|
|
151
|
+
- `Skill("review-pr")` → `commands/review-pr.md`
|
|
152
|
+
- `Skill("quality-gate")` → `commands/quality-gate.md`
|
|
153
|
+
- `Skill("orchestrate")` → `commands/orchestrate.md`
|
|
154
|
+
|
|
155
|
+
## GitHub Operations
|
|
156
|
+
|
|
157
|
+
All FORGE annotations are written to GitHub issue/PR comments via the `gh`
|
|
158
|
+
CLI. Use `Bash()` for every GitHub operation.
|
|
159
|
+
|
|
160
|
+
### Label management
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
Bash("gh issue edit 123 -R OWNER/REPO --add-label 'workflow:investigating'")
|
|
164
|
+
Bash("gh issue edit 123 -R OWNER/REPO --remove-label 'workflow:investigating'")
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Reading existing annotations
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
Bash("gh api repos/OWNER/REPO/issues/123/comments \
|
|
171
|
+
--jq '.[] | select(.body | contains(\"FORGE:INVESTIGATOR\")) | .body'")
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Writing a FORGE annotation comment
|
|
175
|
+
|
|
176
|
+
For multi-line comment bodies, write the content to a temp file first:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Write comment body to temp file (avoids shell quoting issues)
|
|
180
|
+
Write("/tmp/forge_comment.md", """<!-- FORGE:INVESTIGATOR -->
|
|
181
|
+
## Investigation Report
|
|
182
|
+
|
|
183
|
+
**Verdict**: CONFIRMED
|
|
184
|
+
...
|
|
185
|
+
<!-- INVESTIGATION:COMPLETE -->""")
|
|
186
|
+
|
|
187
|
+
Bash("gh issue comment 123 -R OWNER/REPO --body \"$(cat /tmp/forge_comment.md)\"")
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Creating a PR
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
Write("/tmp/pr_body.md", """## Summary
|
|
194
|
+
...
|
|
195
|
+
|
|
196
|
+
Closes #967""")
|
|
197
|
+
|
|
198
|
+
Bash("gh pr create -R OWNER/REPO \
|
|
199
|
+
--base milestone/developer-experience-distribution \
|
|
200
|
+
--head feat/opencode-adapter-967 \
|
|
201
|
+
--title 'feat: OpenCode adapter (#967)' \
|
|
202
|
+
--body \"$(cat /tmp/pr_body.md)\"")
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Worktrees
|
|
206
|
+
|
|
207
|
+
ForgeDock uses git worktrees to isolate branch work. Create one with:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
Bash("git fetch origin")
|
|
211
|
+
Bash("git worktree add .claude/worktrees/feat-my-feature-123 \
|
|
212
|
+
-b feat/my-feature-123 origin/staging")
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Work inside the worktree for all file edits and commits:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
Read("/path/to/repo/.claude/worktrees/feat-my-feature-123/file.py")
|
|
219
|
+
Edit("/path/to/repo/.claude/worktrees/feat-my-feature-123/file.py", ...)
|
|
220
|
+
Bash("git -C /path/to/repo/.claude/worktrees/feat-my-feature-123 status")
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## FORGE Annotation Protocol
|
|
224
|
+
|
|
225
|
+
Every pipeline stage writes a structured annotation to GitHub. Key rules:
|
|
226
|
+
|
|
227
|
+
1. **Idempotency**: Check for existing annotations BEFORE starting a phase.
|
|
228
|
+
Do not re-run a completed phase.
|
|
229
|
+
2. **Compaction resilience**: Write annotations AFTER completing each
|
|
230
|
+
significant step. GitHub is the persistent state layer.
|
|
231
|
+
3. **Restart partial annotations**: If an annotation exists without its
|
|
232
|
+
`:COMPLETE` sentinel, delete it and restart the phase.
|
|
233
|
+
4. **Respect label state**: Labels track workflow state. Read and set them
|
|
234
|
+
at each phase boundary.
|
|
235
|
+
|
|
236
|
+
### Label state machine
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
workflow:investigating
|
|
240
|
+
→ workflow:ready-to-build (investigation complete)
|
|
241
|
+
→ workflow:building (build started)
|
|
242
|
+
→ workflow:in-review (PR created)
|
|
243
|
+
→ workflow:merged (PR merged) [TERMINAL]
|
|
244
|
+
|
|
245
|
+
workflow:invalid [TERMINAL]
|
|
246
|
+
workflow:decomposed [TERMINAL]
|
|
247
|
+
needs-human [TERMINAL]
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Stop the pipeline when any terminal label is set.
|
|
251
|
+
|
|
252
|
+
## Limitations
|
|
253
|
+
|
|
254
|
+
| Capability | Claude Code | OpenCode (this adapter) |
|
|
255
|
+
|------------|-------------|------------------------|
|
|
256
|
+
| Skill loading | Dynamic (`~/.claude/commands/`) | Read `commands/*.md` directly |
|
|
257
|
+
| Native slash commands | `/work-on 967` | `/work-on 967` (via `command` config) |
|
|
258
|
+
| Tool name parity | Native | Direct (same names) |
|
|
259
|
+
| Sub-agent invocation | `Skill("review-pr")` | Read `commands/review-pr.md` directly |
|
|
260
|
+
| Session continuity | Native compaction resilience | Re-read GitHub state each session |
|
|
261
|
+
| Multi-phase pipeline | Automatic (single continuous session) | Supported (GitHub state is persistent) |
|
|
262
|
+
|
|
263
|
+
**Sub-skill invocation**: When a command spec calls `Skill("x")`, OpenCode
|
|
264
|
+
has no native skill loader. Read the referenced command spec file directly
|
|
265
|
+
instead.
|
|
266
|
+
|
|
267
|
+
**Parallel tasks**: When a command spec calls `Agent(...)` or `Task(...)` for
|
|
268
|
+
parallelism (e.g., multi-agent review in `review-pr-agents.md`), execute the
|
|
269
|
+
sub-tasks sequentially. OpenCode runs one agent context at a time.
|
|
270
|
+
|
|
271
|
+
## Configuration
|
|
272
|
+
|
|
273
|
+
`install-opencode.sh` patches `~/.config/opencode/opencode.json`. Example
|
|
274
|
+
of what is added:
|
|
275
|
+
|
|
276
|
+
```json
|
|
277
|
+
{
|
|
278
|
+
"instructions": [
|
|
279
|
+
"~/.opencode-forge.md"
|
|
280
|
+
],
|
|
281
|
+
"command": {
|
|
282
|
+
"work-on": {
|
|
283
|
+
"description": "Run the ForgeDock full issue pipeline (investigate → build → review → merge)",
|
|
284
|
+
"template": "Read /path/to/forgedock/commands/work-on.md and execute the pipeline for issue {{args}}."
|
|
285
|
+
},
|
|
286
|
+
"review-pr": {
|
|
287
|
+
"description": "Run the ForgeDock PR review pipeline",
|
|
288
|
+
"template": "Read /path/to/forgedock/commands/review-pr.md and execute the PR review for PR {{args}}."
|
|
289
|
+
},
|
|
290
|
+
"quality-gate": {
|
|
291
|
+
"description": "Run ForgeDock pre-commit quality checks",
|
|
292
|
+
"template": "Read /path/to/forgedock/commands/quality-gate.md and run all quality gate checks."
|
|
293
|
+
},
|
|
294
|
+
"orchestrate": {
|
|
295
|
+
"description": "Run ForgeDock parallel multi-issue orchestration",
|
|
296
|
+
"template": "Read /path/to/forgedock/commands/orchestrate.md and orchestrate the issues: {{args}}."
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Existing config keys (provider, model, etc.) are preserved. ForgeDock only
|
|
303
|
+
adds to the `instructions` array and `command` object — never overwrites.
|
|
304
|
+
|
|
305
|
+
## Reference
|
|
306
|
+
|
|
307
|
+
- [FORGE Protocol spec](FORGE-PROTOCOL.md) — annotation format, label state machine
|
|
308
|
+
- [Aider adapter](AIDER.md) — parallel adapter reference (Aider uses `/run` translation)
|
|
309
|
+
- [Codex adapter](CODEX.md) — parallel adapter reference (Codex skill model)
|
|
310
|
+
- [Pipeline commands](../commands/) — shared workflow specs (authoritative for all runtimes)
|
|
311
|
+
- [`install-opencode.sh`](../install-opencode.sh) — installer script
|
|
312
|
+
- [`scripts/forge-run.sh`](../scripts/forge-run.sh) — universal shell phase router
|
package/docs/demo.gif
CHANGED
|
Binary file
|
package/docs/eval/README.md
CHANGED
|
@@ -8,8 +8,8 @@ Per-release pipeline evaluation results for ForgeDock. Every scorecard here was
|
|
|
8
8
|
|
|
9
9
|
| Field | Value |
|
|
10
10
|
|-------|-------|
|
|
11
|
-
| Scorecard | [claude-sonnet-
|
|
12
|
-
| Model | claude-sonnet-
|
|
11
|
+
| Scorecard | [claude-sonnet-4-6-2026-07-04.json](published/claude-sonnet-4-6-2026-07-04.json) |
|
|
12
|
+
| Model | claude-sonnet-4-6 |
|
|
13
13
|
| Corpus | seed-v1 |
|
|
14
14
|
| Run date | 2026-07-04 |
|
|
15
15
|
| One-shot success rate | — (pending harness) |
|
|
@@ -17,7 +17,7 @@ Per-release pipeline evaluation results for ForgeDock. Every scorecard here was
|
|
|
17
17
|
|
|
18
18
|
> **Note**: The baseline above is a format placeholder. The harness (#1285) and CI gate (#1286) must be operational before real scorecard values can be populated. When the first real run completes, update this table and remove this note.
|
|
19
19
|
>
|
|
20
|
-
> **Model upgrade**: Default model was updated from `claude-sonnet-4-5` to `claude-sonnet-5` in PR #1441 (issue #1248, committed 2026-07-04). The `--model` flag and `FORGEDOCK_MODEL` env var override the default at runtime.
|
|
20
|
+
> **Model upgrade**: Default model was updated from `claude-sonnet-4-5` to `claude-sonnet-5` in PR #1441 (issue #1248, committed 2026-07-04). The `--model` flag and `FORGEDOCK_MODEL` env var override the default at runtime. No `claude-sonnet-5` scorecard has been published yet — see the Published results table below.
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -25,7 +25,7 @@ Per-release pipeline evaluation results for ForgeDock. Every scorecard here was
|
|
|
25
25
|
|
|
26
26
|
| Run ID | Model | Corpus | Date | One-shot success | Human interventions/issue | Scorecard |
|
|
27
27
|
|--------|-------|--------|------|-----------------|--------------------------|-----------|
|
|
28
|
-
| claude-sonnet-5-2026-07-04 | claude-sonnet-5 | seed-v1 | 2026-07-04 | pending | pending |
|
|
28
|
+
| claude-sonnet-5-2026-07-04 | claude-sonnet-5 | seed-v1 | 2026-07-04 | pending | pending | not yet published |
|
|
29
29
|
| claude-sonnet-4-6-2026-07-04 | claude-sonnet-4-6 | seed-v1 | 2026-07-04 | pending | pending | [scorecard](published/claude-sonnet-4-6-2026-07-04.json) |
|
|
30
30
|
|
|
31
31
|
---
|