@giamme/forge 0.8.0 → 0.10.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +106 -1766
  3. package/SKILL.md +22 -3
  4. package/VERSION +1 -1
  5. package/docs/README.md +26 -0
  6. package/docs/add-ons.md +33 -0
  7. package/docs/artifacts.md +84 -0
  8. package/docs/commands.md +365 -0
  9. package/docs/dataset.md +29 -0
  10. package/docs/decomposed-runs.md +310 -0
  11. package/docs/development.md +95 -0
  12. package/docs/forge-ui.md +128 -0
  13. package/docs/fractal.md +181 -0
  14. package/docs/install.md +160 -0
  15. package/docs/memory.md +156 -0
  16. package/docs/models.md +118 -0
  17. package/docs/reviews.md +245 -0
  18. package/docs/safety.md +55 -0
  19. package/docs/troubleshooting.md +54 -0
  20. package/forge +20 -0
  21. package/package.json +3 -2
  22. package/references/dataset.md +18 -1
  23. package/references/decompose.md +20 -2
  24. package/references/fractal.md +1 -1
  25. package/references/harnesses.md +18 -6
  26. package/references/solo.md +1 -1
  27. package/references/ui.md +27 -5
  28. package/scripts/forge-config.py +347 -0
  29. package/scripts/forge-control.py +645 -0
  30. package/scripts/forge-dispatch.sh +7 -1
  31. package/scripts/forge-issues.py +806 -0
  32. package/scripts/forge-lib-task.sh +234 -35
  33. package/scripts/forge-parallel-options.sh +3 -1
  34. package/scripts/forge-parallel.sh +3 -2
  35. package/scripts/forge-route.py +184 -27
  36. package/scripts/forge-runs-rm.py +840 -0
  37. package/scripts/forge-runs.py +139 -0
  38. package/scripts/forge-runtime.py +59 -6
  39. package/scripts/forge-schedule.py +227 -11
  40. package/scripts/forge-ui.py +85 -19
  41. package/scripts/forge-version.py +54 -12
  42. package/scripts/forge_dataset/__init__.py +77 -6
  43. package/scripts/forge_dataset/capture.py +5 -2
  44. package/scripts/forge_dataset/harvest.py +23 -1
  45. package/scripts/forge_dataset/importer.py +420 -18
  46. package/scripts/forge_fractal/__init__.py +2 -1
  47. package/scripts/forge_registry.py +168 -16
  48. package/ui/README.md +116 -23
  49. package/ui/THIRD_PARTY_NOTICES.md +108 -0
  50. package/ui/docs/api.md +283 -23
  51. package/ui/forge_ui/__main__.py +10 -2
  52. package/ui/forge_ui/control.py +575 -0
  53. package/ui/forge_ui/export.py +33 -9
  54. package/ui/forge_ui/fractal.py +1 -2
  55. package/ui/forge_ui/reader.py +121 -8
  56. package/ui/forge_ui/server.py +135 -5
  57. package/ui/forge_ui/static/D-DINCondensed-Bold.woff2 +0 -0
  58. package/ui/forge_ui/static/app.js +358 -131
  59. package/ui/forge_ui/static/cloud3d.js +3 -2
  60. package/ui/forge_ui/static/cloudui.js +8 -5
  61. package/ui/forge_ui/static/controls.js +619 -0
  62. package/ui/forge_ui/static/convo.js +295 -0
  63. package/ui/forge_ui/static/datatable.js +232 -0
  64. package/ui/forge_ui/static/diffview.js +29 -10
  65. package/ui/forge_ui/static/findings3d.js +134 -0
  66. package/ui/forge_ui/static/findingsview.js +412 -0
  67. package/ui/forge_ui/static/graph.js +3 -3
  68. package/ui/forge_ui/static/icons.js +94 -0
  69. package/ui/forge_ui/static/index.html +31 -13
  70. package/ui/forge_ui/static/iso.js +70 -19
  71. package/ui/forge_ui/static/leaderboard.js +44 -48
  72. package/ui/forge_ui/static/panel.js +92 -36
  73. package/ui/forge_ui/static/rundelete.js +388 -0
  74. package/ui/forge_ui/static/runmodel.js +17 -1
  75. package/ui/forge_ui/static/scene3d.js +518 -43
  76. package/ui/forge_ui/static/search.js +2 -1
  77. package/ui/forge_ui/static/settings.js +399 -0
  78. package/ui/forge_ui/static/shell.js +137 -0
  79. package/ui/forge_ui/static/stagectl.js +150 -0
  80. package/ui/forge_ui/static/style.css +1099 -469
  81. package/ui/forge_ui/static/theme.js +25 -0
  82. package/ui/forge_ui/static/uikit.js +161 -0
  83. package/ui/forge_ui/transcripts.py +608 -0
package/SKILL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: forge
3
3
  description: Dispatch implementation and independent diff review to user-selected models through local agent CLIs. Use for /forge or explicit requests to delegate coding or review; explanation-only questions do not authorize dispatch.
4
- argument-hint: '"<goal>" --dwarf <alias>[:effort[:harness]] [--qa <alias>] [--planner <alias>] [--yolo-dwarf] [--yolo-qa] [--decompose-level low|medium|high] [--fractal|--no-fractal|--fractal-auto-decompose] [--fractal-planner <spec>] [--jev|--no-jev] [--jev-shadow] [--no-memory] [--no-ripwire] [--ui|--no-ui] [--timeout <seconds>] [--retry-failed <n>] [--escalate-after <n>] [--qa-threshold P0|P1|P2|P3] [--shadow-qa <spec>[,<spec>]] [--shadow-rate <0..1>] [--explore <0..0.5>] [--fail-first]'
4
+ argument-hint: '"<goal>" --dwarf <alias>[:effort[:harness]] [--qa <alias>] [--planner <alias>] [--yolo-dwarf] [--yolo-qa] [--decompose-level low|medium|high] [--fractal|--no-fractal|--fractal-auto-decompose] [--fractal-planner <spec>] [--jev|--no-jev] [--jev-shadow] [--no-memory] [--no-ripwire] [--ui|--no-ui] [--timeout <seconds>] [--retry-failed <n>] [--escalate-after <n>] [--qa-threshold P0|P1|P2|P3] [--file-issues ask|auto|off] [--shadow-qa <spec>[,<spec>]] [--shadow-rate <0..1>] [--explore <0..0.5>] [--fail-first]'
5
5
  allowed-tools: [Bash, Read]
6
6
  ---
7
7
 
@@ -29,8 +29,9 @@ For explanation requests, explain the workflow without spending model quota.
29
29
  or `forge-solo.sh` and relay the `forge-ui:` URL they print. Never ask on resume or retry;
30
30
  unattended runs leave it off. A UI failure never changes the run. Read [forge-ui](references/ui.md).
31
31
  - A finished solo run, `plan` or `run` may end with one stderr line, `forge X is available
32
- (you have Y): forge update` (checked at most once a day). Relay it once; run the update only
33
- when the user asks (`forge update`, then restart the harness session). `FORGE_UPDATE_CHECK=off` silences it.
32
+ (you have Y): <command>` (checked at most once a day; the command is `forge update`, or npm's
33
+ for an npm installation). Relay it once; run the update only when the user asks (that
34
+ command, then restart the harness session). `FORGE_UPDATE_CHECK=off` silences it.
34
35
  - `--fractal-auto-decompose` enables automatic split-or-atomic decisions before each
35
36
  eligible node implements. Include the effective planner and bounds in the approval
36
37
  preview; child decisions need no additional user approval inside those bounds.
@@ -54,10 +55,28 @@ For explanation requests, explain the workflow without spending model quota.
54
55
  (`--escalate-after N`, `0` = off); an explicit `retry --dwarf` overrides it. `accept`
55
56
  overrides a reviewer, so run it (with the user's `--reason` and
56
57
  `--approved`) only on the user's explicit instruction; never self-accept.
58
+ - When you report a run, read `<plan>/control.log` and mention any human change made mid-run
59
+ (a threshold, a budget, a model pin; `forge control show <plan>` lists them). Never set a
60
+ control, pin or delete a run with `forge control` / `forge runs rm` unless the user asks.
57
61
  - Exit `8` / status `INFRA` is a quota, auth or network stop, not a task failure and no
58
62
  attempt was spent: report it, say what to fix, and re-run only when told. For a multi-task
59
63
  plan, offer the opt-in whole-run review (`review`, or `integrate --final-review <qa-spec>`);
60
64
  it spends QA quota, so never run it unprompted.
65
+ - **Leftover findings become issues.** A run can finish with review findings nobody will act on:
66
+ - CONFIRMED findings that `--qa-threshold` tolerated (`tasks/<id>/known_issues.md`);
67
+ - PLAUSIBLE findings in a passed task's `qa.last`;
68
+ - whatever a whole-run review left open.
69
+
70
+ When there are any, act on the user's `--file-issues` choice with one filer:
71
+ - **gh-proman**, only when it is installed and set up for the repository: `gh-proman -C <repo> config show` exits 0. It also puts the issues on the team's board with a priority. Run `gh-proman findings --from <plan or run dir> --include-plausible --json`, then follow the gh-proman skill's review-findings steps.
72
+ - **forge's own filer** otherwise (gh-proman missing, or not configured for this repo; never configure it yourself): `python3 <skill_dir>/scripts/forge-issues.py <plan or run dir> --include-plausible --json`, plain `gh issue create`. Pass `--lang` matching the repo's existing issues, and `--label bug` when the repo has that label. If `gh` is missing, unauthenticated or the repo has no GitHub remote, list the findings in the report and say why none were filed.
73
+
74
+ The choice:
75
+ - `ask` (the default): show the dry-run summary (count by severity, titles, anything already filed) and ask once: **"File these N findings as GitHub issues? [all / CONFIRMED only / none]"**. Then re-run with `--apply`, adding `--include-plausible` only for "all".
76
+ - `auto`: file them without asking (`--apply`, PLAUSIBLE included as "to verify" issues) and report what was created and skipped.
77
+ - `off`: never offer.
78
+
79
+ `--file-issues` is an instruction to you: never forward it to a runner. Skip INFRA, interrupted and still-failing runs. Both filers mark each issue with the same finding fingerprint and skip a finding either one already filed, so offering again after a retry only brings up new ones. A draft flagged as a possible duplicate is skipped on `--apply`: show it, and file it (`--confirm-new`) only if the user says it is different.
61
80
  - Jev is optional, off unless configured and enabled, and always advisory: it never
62
81
  changes a task's tier, never selects a model, and never substitutes for QA acceptance
63
82
  or repository verification (`--jev-act` is still accepted and changes nothing). Read
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8
1
+ 0.10
package/docs/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # forge documentation
2
+
3
+ [← README](../README.md)
4
+
5
+ The README is the short overview. These pages hold the rest, one topic each.
6
+
7
+ | Page | What's in it |
8
+ |---|---|
9
+ | [Install and update](install.md) | npm or a git checkout, the doctor, what the installer does per CLI, updating |
10
+ | [Command reference](commands.md) | every `/forge` flag with examples, the `forge` command, the runner scripts and their exit codes |
11
+ | [Models, efforts and harnesses](models.md) | the `alias:effort:harness` spec, effort ladders and clamping, yolo mode, the model registry |
12
+ | [Decomposed runs](decomposed-runs.md) | decompose levels and difficulty, routing, waves, capsules, planning, resuming, split and combine, `tasks.tsv` |
13
+ | [Reviews, retries and recovery](reviews.md) | verdicts, retries, infrastructure stops, severity thresholds, accepting, whole-run and shadow reviews, guards, verification, fail-first |
14
+ | [Fractal execution](fractal.md) | the optional nested-execution backend: install, run, inspect, bounds and recovery |
15
+ | [Project memory](memory.md) | `.forge/memory.md` and the ledger, what each role is told, whether to commit it, spend |
16
+ | [forge-ui](forge-ui.md) | the run viewer: commands, the shared server, environment variables, privacy |
17
+ | [Run dataset](dataset.md) | every run's inputs and outcomes, kept for training decision models |
18
+ | [Run artifacts](artifacts.md) | the run directory, a plan's files, worktrees and branches |
19
+ | [Safety](safety.md) | what forge never does to your branch, preconditions, execution integrity |
20
+ | [Ripwire and Jev](add-ons.md) | optional repository context and advisory judgments |
21
+ | [Troubleshooting](troubleshooting.md) | symptoms, causes and fixes |
22
+ | [Development](development.md) | repository layout, offline checks, runtime measurement |
23
+
24
+ Deeper material that the skill itself reads lives in [`references/`](../references/): the
25
+ per-harness details, the decomposition and Fractal contracts, memory internals, Jev and the
26
+ dataset schema.
@@ -0,0 +1,33 @@
1
+ # Ripwire and Jev
2
+
3
+ [← README](../README.md) · [All docs](README.md)
4
+
5
+ Two optional add-ons: Ripwire adds repository evidence to every prompt, and Jev gives advisory judgments. forge works without either.
6
+
7
+ ## Ripwire context
8
+
9
+ Forge automatically adds optional Ripwire 0.4.0 repository evidence to planner, dwarf,
10
+ and QA prompts across all six harnesses. Setup and interactive runners offer a pinned,
11
+ verified installation; headless runs continue when it is missing. Use `--no-ripwire`
12
+ or `FORGE_RIPWIRE=off` to disable it. Decomposed plans preserve opt-out across resumes
13
+ and retries. See [installation, controls and attempt artifacts](../references/ripwire.md).
14
+
15
+ ## Jev
16
+
17
+ Jev is TypeSafe's "System One" model. It answers narrow, typed questions over the state it is
18
+ given, quickly and with calibrated probabilities. forge can ask it for advice on routing, test
19
+ selection, gates and memory curation. That advice sits beside forge's own decisions and never
20
+ replaces a model choice, a test run, a review or verification.
21
+
22
+ It is **off by default**. Each enabled capability sends a narrow slice of the run to an external
23
+ API: task prompts, diff hunks, test names or memory text, and never `.forge/` or `.git`. The
24
+ installer offers setup and declines by default.
25
+
26
+ ```sh
27
+ forge jev setup # store an API key
28
+ forge jev status # resolved config and enabled capabilities
29
+ forge jev enable [--capability NAME] # turn it on, optionally for one capability
30
+ ```
31
+
32
+ Chosen sites can go to Cloudflare's hosted Clef instead (`forge jev setup --provider cloudflare`).
33
+ The [full Jev reference](../references/jev.md) covers capabilities, privacy and backtests.
@@ -0,0 +1,84 @@
1
+ # Run artifacts
2
+
3
+ [← README](../README.md) · [All docs](README.md)
4
+
5
+ What a run leaves on disk: the run directory, a decomposed plan's files, and where worktrees and branches live.
6
+
7
+ Each stage writes into the run directory, which lives **outside** the repo — anything forge
8
+ writes inside the working tree would show up in the dwarf's own diff and land in front of qa
9
+ as if the dwarf had written it.
10
+
11
+ ```
12
+ <run-dir>/
13
+ <role>.resolved what the spec resolved to (model, effort, harness, any clamp)
14
+ <role>.prompt the exact prompt sent
15
+ <role>.cmd the exact command line executed
16
+ <role>.log full transcript
17
+ <role>.last the final message — read this first
18
+ <role>.infra only after an infrastructure failure: class, retry_after, detail
19
+ <role>.orphans only when processes were left running after the harness exited
20
+ changes.diff the dwarf's real diff, which is qa's input
21
+ ```
22
+
23
+ A solo run also records, for forge-ui and for you:
24
+
25
+ ```
26
+ <run-dir>/
27
+ status RUNNING, then PASS|FAIL|UNKNOWN|NOCHANGES|INVALIDATED|TIMEOUT|INFRA|INTERRUPTED|ERROR
28
+ dwarf.spec, qa.spec the specs the run was given
29
+ attempts.tsv epoch, attempt number, status, infrastructure class, dwarf spec; one row per invocation
30
+ ```
31
+
32
+ Plus, in the repo itself and surviving the run:
33
+
34
+ ```
35
+ .forge/memory.md what forge learned here, injected into future prompts
36
+ .forge/ledger.tsv one row per dispatch, ever; never injected
37
+ ```
38
+
39
+ A decomposed run adds:
40
+
41
+ ```
42
+ <plan-dir>/
43
+ goal.txt
44
+ tasks.tsv
45
+ waves.tsv, deferrals.txt
46
+ tasks/<id>/{capsule.md,prompt.md,dwarf.*,qa.*,changes.diff,status}
47
+ tasks/<id>/attempt, attempts.tsv attempts spent; one audit row per entry (incl. refunded stops)
48
+ tasks/<id>/known_issues.md, qa.gate findings tolerated by --qa-threshold, and the gate's decision
49
+ tasks/<id>/guard.txt what forge observed about the implementer (self-commit, orphans, promises)
50
+ tasks/<id>/infra.txt, resume, noretry infrastructure stop record; QA-only resume marker; no-progress marker
51
+ tasks/<id>/qa_threshold optional per-task blocking threshold: P0-P3, or none (exempt from the plan's)
52
+ tasks/<id>/escalations.tsv epoch, attempt, from-spec, to-spec, source (policy|retry|pin); older rows have 4 columns
53
+ tasks/<id>/escalation.pin a human's one-shot model for the next full retry: one dwarf spec on one line
54
+ tasks/<id>/escalation.pin.applying the pin while a retry has claimed it; removed once the retry is recorded
55
+ tasks/<id>/retry_budget, retries.used live per-task retry budget (a number); retries spent (kept after the run)
56
+ results.tsv id status branch
57
+ timeout, qa_threshold, verify_retries options remembered from run/retry flags (also escalate_after)
58
+ control.log one JSON line per human change made with forge control
59
+ scheduler.live, control.lock only while a scheduler runs: {"pid", "started"}; the lock serialises forge control
60
+ retry_budget, infra_budget only while a scheduler runs: its live budgets (a number each)
61
+ integration.base commit the integration branch started from
62
+ verification.{status,exit,log,command,fingerprint} the combined verification
63
+ verification.{flaky,retry.log} only when a failing command passed on rerun
64
+ verification.coverage.txt suites the verify command does not run (advisory)
65
+ ```
66
+
67
+ with worktrees and branches at:
68
+
69
+ ```
70
+ <repo>/../.forge-worktrees/<run-id>/<task-id> worktree
71
+ forge/<run-id>/<task-id> task branch
72
+ forge/<run-id>-integration integration branch
73
+ ```
74
+
75
+ `control.log` lines look like
76
+ `{"at": 1761200000.5, "actor": "ui", "action": "set", "task": null, "key": "qa-threshold", "value": "P2", "previous": "P1"}`
77
+ (`actor` is `cli` or `ui`; `action` is `set`, `pin` or `unpin`; `key` is the control's name, or `pin`; `task` is null for a plan-wide
78
+ control). `scheduler.live`, `retry_budget`, `infra_budget` and the per-task `retry_budget` exist
79
+ only while the scheduler is live: it publishes the flags it was given when it starts, re-reads them
80
+ at every decision and removes them when it stops, which is why `forge control` refuses a budget
81
+ change outside a live run. See [live controls](decomposed-runs.md#changing-a-run-while-it-works).
82
+
83
+ The worktree root is a **sibling of the repo, never `TMPDIR`**. Isolated worktrees are never
84
+ pushed, so a temp root that gets cleaned takes the only copy of that work with it.
@@ -0,0 +1,365 @@
1
+ # Command reference
2
+
3
+ [← README](../README.md) · [All docs](README.md)
4
+
5
+ Every flag of the `/forge` slash command, the `forge` command, and the scripts the skill runs underneath.
6
+
7
+ ## The `forge` command
8
+
9
+ npm puts `forge` on your `PATH`; in a git checkout it is `./forge`. Runs start from your agent
10
+ harness (`/forge`); this command installs forge and drives its optional tools.
11
+
12
+ | Command | Does |
13
+ |---|---|
14
+ | `forge install [--dry-run]` | link forge into each agent harness on this machine; see [install](install.md) |
15
+ | `forge update` | fast-forward a git checkout and refresh every harness installation; on an npm install it names the npm command instead. See [updating](install.md#updating-all-harness-installations) |
16
+ | `forge version [--check]` | the installed version, and whether a newer release is out |
17
+ | `forge fractal …` | opt-in Fractal execution; see [the command group](fractal.md#forge-fractal-command-group) |
18
+ | `forge runs [--repo DIR \| --all] [--limit N] [--json]` | this repo's recent runs, newest first: run id, kind, age, task states, verification and final review, goal, and the run dir. Read-only; the same summaries forge-ui shows |
19
+ | `forge control show\|set\|pin\|unpin PLAN_DIR …` | change a live plan: `set` takes `qa-threshold`, `timeout`, `escalate-after`, `verify-retries`, `retry-budget` or `infra-retries` (the last two only while a scheduler runs; `--task ID` for `qa-threshold` and `retry-budget`, value `inherit` drops the override); `pin PLAN_DIR TASK SPEC` sets the model the task's next full retry uses once, `unpin` drops it; `--json`. Every change is logged in `control.log`. See [live controls](decomposed-runs.md#changing-a-run-while-it-works) |
20
+ | `forge config show\|set\|unset [--repo DIR] [--json]` | one view of every config source (registry, Jev, the repo's `.forge/verify`, `setup` and `verify-subset`, dataset, `FORGE_*` variables with secrets hidden); `set KEY VALUE` / `unset KEY` edit `repo.verify`, `repo.setup`, `repo.verify-subset` (must contain `{files}`) and, for `set`, `jev.enabled true\|false`. `-` as a value reads stdin. Exit 2 on invalid input |
21
+ | `forge runs rm RUN_DIR [--dry-run] [--yes] [--no-archive] [--worktrees] [--branches] [--json]` | delete a run directory but keep what it taught the dataset; see [below](#forge-runs-rm) |
22
+ | `forge issues RUN [--apply] …` | file the review findings a run left open as GitHub issues; see [below](#forge-issues) |
23
+ | `forge ui open\|status\|stop` | forge-ui, the run viewer; see [the command group](forge-ui.md#forge-ui-command-group) |
24
+ | `forge dataset …` | every run's inputs and outcomes; see [run dataset](dataset.md) |
25
+ | `forge jev …` | optional Jev advice: setup, status, doctor, enable, disable, backtest; see [Jev](add-ons.md#jev) |
26
+ | `forge --help` | list the commands; `forge <command> --help` shows each one's options |
27
+
28
+ ### `forge runs rm`
29
+
30
+ Deletes a run directory (a plan dir or a solo run dir) without losing its traces. It holds the
31
+ run's own lock from the first step to the last (`schedule.lock` of a plan, `pipeline.lock` of a
32
+ solo run), so a run started meanwhile fails to start instead of racing the delete. In order:
33
+
34
+ 1. **preserve**: a strict dataset import of the run; every event must be stored, or nothing is deleted;
35
+ 2. **archive**: a self-describing `.tar.gz` under `<data home>/archive/` (`--no-archive` skips it);
36
+ 3. **intent**: the dataset event `run_delete_started`;
37
+ 4. `--worktrees` removes the run's clean worktrees; `--branches` runs `git branch -D` on its
38
+ branches that no worktree has checked out;
39
+ 5. the run directory is removed, `run_deleted` is recorded and the run leaves the registry.
40
+
41
+ What counts as the run's is decided from the run id, not read from the run directory: a worktree
42
+ under `<repo>/../.forge-worktrees/<run id>/` on `forge/<run id>/<task>` or
43
+ `forge/<run id>-integration`. Any other worktree there is `foreign`, one with uncommitted changes
44
+ is `dirty`; neither is touched, and a dirty one keeps the run directory too. Branches are reported
45
+ `merged` or `UNMERGED`, so you see what deleting them would lose. `--dry-run` changes nothing and
46
+ reports; `--yes` skips the prompt for the run id (needed without a terminal); `--json` prints one
47
+ object, on failure too. Exit 0 ok, 2 refused input, 3 busy or the run is active, 4 failed during
48
+ deletion or the run directory was kept (the same command finishes the job).
49
+
50
+ ### `forge issues`
51
+
52
+ `forge issues <plan dir, task dir, review dir, known_issues.md or qa.last>` drafts one GitHub
53
+ issue per finding the run left open (`--group task|run` for fewer) and files them only with
54
+ `--apply`. The findings are the CONFIRMED ones `--qa-threshold` tolerated, PLAUSIBLE ones with
55
+ `--include-plausible`, and what the whole-run review left open. Each issue carries a hidden
56
+ fingerprint, so a finding is never filed twice, by this command or by gh-proman. Also:
57
+ `--min-severity`, `--repo`, `--lang`, `--label`, `--confirm-new`, `--max-issues` (default 10; pass
58
+ the size of a `--only` selection).
59
+
60
+ | Flag | Does |
61
+ |---|---|
62
+ | `--json` | machine-readable output; `findings` lists each one with its fingerprint, severity, origin, task, `filed` state and `dismissed` mark |
63
+ | `--offline` | never run `gh`: no filed state, commit publication judged from local refs |
64
+ | `--only FP` | keep only these 12-hex fingerprints (repeatable or comma-separated) |
65
+ | `--all-runs` | read `RUN` as a repository (or a plan dir naming one) and collect every run in its registry; the newest plan wins for a finding in several |
66
+ | `--dismiss FP`, `--undismiss FP`, `--reason TEXT` | mark findings as needing no work (or take it back), then exit; no network. The marks live outside the repo, in `${XDG_STATE_HOME:-~/.local/state}/forge/findings/<repo key>.json` |
67
+ | `--include-dismissed` | draft dismissed findings too |
68
+
69
+ Two filers for one repository at once would both see a finding as unfiled, so `--apply` takes a
70
+ repository lock from the issue lookup to the last `gh issue create`, and each dismissal takes it
71
+ around its write. A busy lock is retried for 10 s, then exit 3. Exit 0 ok, 2 usage or a `gh` or
72
+ dismissal-store error, 3 busy.
73
+
74
+ ## The `/forge` slash command
75
+
76
+ ```
77
+ /forge "<goal>" --dwarf <alias>[:<effort>[:<harness>]]
78
+ [--qa <alias>[:<effort>[:<harness>]]]
79
+ [--planner <alias>[:<effort>[:<harness>]]]
80
+ [--yolo-dwarf] [--yolo-qa] [--repo <dir>] [--native-review]
81
+ [--no-memory] [--timeout <seconds>] [--ui | --no-ui] [--fractal | --no-fractal]
82
+ [--fractal-auto-decompose] [--fractal-planner <spec>]
83
+ [--fractal-depth <n>] [--fractal-children <n>] [--fractal-nodes <n>]
84
+ [--fractal-iterations <n>] [--fractal-concurrency <n>] [--fractal-deadline <s>]
85
+ [--decompose-level low|medium|high] [--max-parallel <n>]
86
+ [--dwarf-high <spec>] [--dwarf-medium <spec>] [--dwarf-low <spec>]
87
+ [--qa-high <spec>] [--qa-medium <spec>] [--qa-low <spec>]
88
+ ```
89
+
90
+ | Flag | Default | Meaning |
91
+ |---|---|---|
92
+ | `--dwarf <spec>` | *asks* | the model that implements the change |
93
+ | `--qa <spec>` | `opus` at `xhigh` | the model that reviews the dwarf's diff |
94
+ | `--planner <spec>` | orchestrator plans | dispatch planning to a model; one dispatch per run, effort defaults to `xhigh` |
95
+ | `--no-memory` | memory on | write and inject nothing in `.forge/` |
96
+ | `--timeout <s>` | `2700` (45m) | kill any single dispatch that runs longer. `0` disables |
97
+ | `--yolo-dwarf` | off | drop the dwarf's sandbox and approval gates |
98
+ | `--yolo-qa` | off | drop the reviewer's sandbox |
99
+ | `--repo <dir>` | cwd | repository to work in |
100
+ | `--native-review` | off | use native Codex review against the recorded baseline instead of an inlined diff |
101
+ | `--decompose-level <l>` | off | split the goal into parallel tasks |
102
+ | `--max-parallel <n>` | `3` | concurrent task pipelines |
103
+ | `--dwarf-high/-medium/-low` | — | per-difficulty routing; comma-list pools models |
104
+ | `--qa-high/-medium/-low` | — | same, for reviewers |
105
+ | `--fractal` / `--no-fractal` | ask interactively; off unattended | mutually exclusive, per-run backend choice |
106
+ | `--fractal-auto-decompose` | off | enables Fractal with automatic recursive split-or-atomic decisions |
107
+ | `--fractal-planner <spec>` | top-level planner, then task root spec | frozen decision model; requires automatic mode |
108
+ | `--fractal-depth <n>` | `2` | nested levels below each Forge implementation node |
109
+ | `--fractal-children <n>` | `3` | unsettled direct children per node |
110
+ | `--fractal-nodes <n>` | `12` | lifetime nodes per Forge task, including implementation |
111
+ | `--fractal-iterations <n>` | `6` | per node per execution attempt |
112
+ | `--fractal-concurrency <n>` | `3` | shared model slots across nested trees and QA |
113
+ | `--fractal-deadline <s>` | `2700` | task attempt deadline, excluding explicit pauses |
114
+ | `--fractal-max-cost <amount>` | unsupported | returns an error; the bridge cannot enforce dollar caps |
115
+
116
+ Fractal's task deadline still applies when `--timeout 0` disables the ordinary
117
+ per-dispatch timeout. Child routing uses the dwarf tier flags; QA stays at the Forge
118
+ task boundary. Pools and Fractal limits are frozen for an existing run.
119
+
120
+ Before an interactive run, forge asks **“Use Fractal for this run? [y/N]”** once.
121
+ Pass `--fractal` or `--no-fractal` to answer explicitly; unattended runs default off.
122
+ It also asks **“Open forge-ui to watch this run? [y/N]”** (`--ui` / `--no-ui`); on a yes,
123
+ the [forge-ui](forge-ui.md) page opens as soon as the run exists. Resume and retry never ask.
124
+
125
+ For what `--native-review` trades away, see [native review](reviews.md#native-review).
126
+
127
+ ### Examples
128
+
129
+ ```bash
130
+ # minimum
131
+ /forge "make the cache key include the tenant id" --dwarf sol:high
132
+
133
+ # both roles named, reviewer thinking harder than the implementer
134
+ /forge "rewrite the rate limiter as a token bucket" --dwarf luna:max --qa sol:ultra
135
+
136
+ # same model, different CLI
137
+ /forge "extract the retry helper into its own module" --dwarf sol:high:openclaude
138
+
139
+ # Gemini as the dwarf, unsandboxed so it can actually run the tests it writes
140
+ /forge "add table-driven tests for the parser" --dwarf gemini:high:antigravity --yolo-dwarf
141
+
142
+ # a cheap dwarf with an expensive reviewer
143
+ /forge "update all the docstrings to match the new signatures" --dwarf haiku --qa opus:max
144
+
145
+ # work in another repo
146
+ /forge "bump the pinned deps and fix the fallout" --dwarf sol:xhigh --repo ~/dev/other-project
147
+
148
+ # large refactor, reviewed by codex's native reviewer
149
+ /forge "split the god object into three services" --dwarf sol:ultra --qa sol:ultra --native-review
150
+
151
+ # parallel, one dwarf for every task
152
+ /forge "add CRUD endpoints for projects, users and teams" \
153
+ --decompose-level medium --dwarf sol:high
154
+
155
+ # parallel, routed by difficulty, wider fan-out
156
+ /forge "migrate the whole API layer from REST to gRPC" \
157
+ --decompose-level high --max-parallel 5 \
158
+ --dwarf-high sol:ultra --dwarf-medium luna:high --dwarf-low haiku:medium \
159
+ --qa-high opus:max --qa sonnet:high
160
+
161
+ # pool two providers on the hard tier so neither quota carries it alone
162
+ /forge "implement the new billing rules across the codebase" \
163
+ --decompose-level medium \
164
+ --dwarf-high sol:xhigh,terra:xhigh --dwarf luna:high
165
+
166
+ # a model that thinks for a long time; raise the per-dispatch backstop
167
+ /forge "prove the scheduler cannot deadlock, and fix it if it can" \
168
+ --dwarf sol:ultra --timeout 7200
169
+ ```
170
+
171
+ After a decomposed run, a task that failed review can be re-run on its own — with the
172
+ findings that failed it, on a stronger model:
173
+
174
+ ```bash
175
+ bash scripts/forge-parallel.sh retry /tmp/forge-billing pricing --dwarf sol:ultra
176
+ ```
177
+
178
+ ## `scripts/forge-dispatch.sh`
179
+
180
+ Resolves a spec into a real CLI invocation and runs it. Needs only bash and coreutils, which
181
+ is the point: it behaves identically no matter which harness is orchestrating.
182
+
183
+ ```
184
+ forge-dispatch.sh doctor
185
+ forge-dispatch.sh dwarf <spec> --prompt-file <f> [--repo <dir>] [--run-dir <d>] [--yolo] [--dry-run]
186
+ forge-dispatch.sh qa <spec> --prompt-file <f> [--repo <dir>] [--run-dir <d>] [--yolo] [--dry-run]
187
+ [--native-review [--review-base <ref>]]
188
+ forge-dispatch.sh planner <spec> --prompt-file <f> [--repo <dir>] [--run-dir <d>] [--dry-run]
189
+ ```
190
+
191
+ | Option | Meaning |
192
+ |---|---|
193
+ | `--prompt-file <f>` | file holding the prompt (required for `dwarf`/`qa`) |
194
+ | `--repo <dir>` | repository the role operates in |
195
+ | `--run-dir <d>` | where prompts, logs and results are written |
196
+ | `--yolo` | bypass sandbox and approvals for this role |
197
+ | `--dry-run` | resolve and print the command; run nothing |
198
+ | `--native-review` | qa only; use codex's built-in reviewer |
199
+ | `--review-base <ref>` | qa only; base ref for the native review |
200
+ | `--agy-timeout <s>` | antigravity `--print-timeout` (long runs need this raised) |
201
+ | `--timeout <s>` | kill this dispatch after `<s>` seconds; `0` disables. See the precedence below |
202
+
203
+ **Exit codes:** `0` ok · `2` spec or usage error · `3` harness missing or unusable ·
204
+ `4` the backend ran and failed · `7` the backend hit its timeout and was killed ·
205
+ `8` an **infrastructure failure** (quota or usage limit, auth, rate limit, network, or an
206
+ empty answer) — nothing about the work was judged, so callers pause instead of counting a
207
+ failure. On `8`, `<run-dir>/<role>.infra` holds `class=`, `retry_after=`, `detail=`, `rc=`,
208
+ `role=`.
209
+
210
+ **Timeout precedence.** An explicit `--timeout`, then `FORGE_TIMEOUT` (an explicit `0` wins
211
+ and disables the watchdog), then the optional fifth `timeout` column of the model's
212
+ [registry](models.md#model-registry) row, then the built-in `2700` (45 min). A value that was *not*
213
+ explicit is scaled by the resolved (post-clamp) effort: up to `high` ×1, `xhigh` ×4/3,
214
+ `max`/`ultra`/`ultracode` ×2. QA and planner default to `xhigh`, so their built-in limit is
215
+ 3600 s; dwarves default to `medium` and keep 2700 s. `<role>.resolved` records `timeout=` and
216
+ `timeout_source=` (`explicit`, `env`, `registry` or `default`, plus `+effort-scaled`).
217
+ `forge-parallel.sh run`/`retry --timeout S` sets it for a decomposed run (kept in the plan).
218
+ `FORGE_REGISTRY` points the dispatcher at an alternative registry file.
219
+
220
+ Only antigravity bounds its own runtime, and stock macOS has no `timeout` binary to wrap the
221
+ others in — so a hung backend used to block forever, and under a decomposed run one hung task
222
+ silently stalled the others. The default is deliberately generous: this is a backstop against
223
+ a wedged process, not a budget. A role killed by it has usually left a partial edit behind, so
224
+ `7` is worth reporting as such rather than as a clean failure.
225
+
226
+ On `3` or `4`, forge shows you the actual error rather than substituting a different model —
227
+ quietly swapping backends hides the fact that the one you picked is broken.
228
+
229
+ **Process hygiene.** Unless `FORGE_ORPHAN_GUARD=off` (or the run is a Fractal one), the harness
230
+ is started in its own session, and after it exits any process still alive in that session is
231
+ listed in `<role>.orphans` and stopped, so a backgrounded measurement cannot outlive the
232
+ dispatch. The timeout watchdog and the exit trap signal the whole session too.
233
+
234
+ ```bash
235
+ # what would this actually run?
236
+ bash scripts/forge-dispatch.sh dwarf sol:ultra --prompt-file /tmp/p --dry-run
237
+
238
+ # check a clamp before committing to a long run
239
+ bash scripts/forge-dispatch.sh qa gemini-pro:medium --prompt-file /tmp/p --dry-run
240
+ # effort=low
241
+ # clamped=medium -> low (gemini-pro offers low and high, but no medium)
242
+ ```
243
+
244
+ ## `scripts/forge-solo.sh`
245
+
246
+ The whole single-task run: memory injection, prompt assembly, the dwarf dispatch, the diff
247
+ capture, the QA dispatch, and the ledger writes.
248
+
249
+ ```
250
+ forge-solo.sh <run-dir> --repo <dir> --dwarf <spec> [--qa <spec>]
251
+ [--approach <file>] [--yolo-dwarf] [--yolo-qa]
252
+ [--native-review] [--no-memory] [--timeout <s>] [--dry-run] [--ui | --no-ui]
253
+ [--fail-first]
254
+ [--fractal | --no-fractal] [--fractal-<limit> <n>]
255
+ [--dwarf-low <pool>] [--dwarf-medium <pool>] [--dwarf-high <pool>] [--retry]
256
+ ```
257
+
258
+ You write two files into the run directory; forge does the rest:
259
+
260
+ | You write | Is |
261
+ |---|---|
262
+ | `prompt.md` | the implementation instruction (required) |
263
+ | `goal.txt` | one line, what was asked — given to the reviewer as intent (optional) |
264
+
265
+ | It writes | Is |
266
+ |---|---|
267
+ | `dwarf.last` / `qa.last` | each role's final message |
268
+ | `changes.diff` | exactly what the reviewer read |
269
+ | `verdict` | `PASS`, `FAIL`, `UNKNOWN` or `NOCHANGES` |
270
+ | `<role>.{input,log,resolved,cmd}` | the prompt, the transcript, the resolution, the command |
271
+ | `fractal-selection.json` | persisted backend choice; enabled runs include their managed run ID |
272
+
273
+ With Fractal, per-step dispatch artifacts live in the managed run while the solo directory
274
+ retains the aggregate diff and Forge QA result. `--retry` starts a new Fractal attempt;
275
+ `forge fractal resume RUN_ID` continues preserved execution and pipeline checkpoints.
276
+
277
+ ```bash
278
+ RUN="$(mktemp -d /tmp/forge-XXXXXX)"
279
+ echo "add retry with backoff to the HTTP client" > "$RUN/goal.txt"
280
+ echo "Add exponential backoff to src/http.py, capped at 5 attempts." > "$RUN/prompt.md"
281
+
282
+ bash scripts/forge-solo.sh "$RUN" --repo ~/dev/api --dwarf sol:high --qa opus
283
+ ```
284
+
285
+ **Exit codes:** `0` reviewed · `2` usage · `3` not a git repository · `4` a dispatch failed ·
286
+ `5` **no changes or review invalidated** · `7` a dispatch timed out · `8` a dispatch hit an
287
+ **infrastructure failure** (quota, auth, rate limit, network, empty output): nothing was
288
+ judged, fix the cause and run again. A dwarf that exits 0 with an empty answer *and* changes
289
+ nothing is reported as `8`, not `5` — it never really ran.
290
+
291
+ The dwarf is given the same implementer rules as in a decomposed run (no commits, no
292
+ background processes, finish measurements before the last message). If it commits anyway, the
293
+ run still reviews its changes, says so, and prints the `git reset --soft <old HEAD>` that would
294
+ turn them back into uncommitted changes; forge never resets anything itself. Orphan processes
295
+ and promised-later-work notes appear under "implementer guard notes".
296
+
297
+ `5` is the one worth recognising on sight. Headless dwarves genuinely stop to ask a
298
+ clarifying question that nothing can answer; the run ends having spent the quota and changed
299
+ nothing, with the question sitting in `dwarf.last`.
300
+
301
+ Two things it gets right that are easy to get wrong by hand, and that fail *silently* rather
302
+ than loudly:
303
+
304
+ - **`.forge/` is excluded from the capture.** Forge rewrites its own memory in the working
305
+ tree at the end of every run, so left in, it reaches the reviewer as a file the dwarf
306
+ appears to have touched — which a good reviewer correctly flags as scope creep.
307
+ - **New files are diffed against `/dev/null`.** A `git status` line says only `?? calc.py`.
308
+ A dwarf whose entire task was to add a file would have had its actual code reviewed by
309
+ nobody, while the run still reported a clean QA pass.
310
+
311
+ The run directory must live outside the repository — anything forge writes inside the working
312
+ tree shows up in the dwarf's own diff. `forge-solo.sh` refuses rather than letting that happen
313
+ quietly.
314
+
315
+ ## `scripts/forge-parallel.sh`
316
+
317
+ Decomposed runs: many dwarves in isolated worktrees, per-task QA, only passing work merged.
318
+ Bash 3.2 entrypoints use a Python standard-library coordinator to schedule eligible tasks.
319
+
320
+ ```
321
+ forge-parallel.sh plan <plan-dir> --repo <dir> [routing flags] [--planner <spec>] [--no-memory]
322
+ [--decompose-level L] [--shadow-qa <spec>[,..]|none] [--shadow-rate R]
323
+ [--explore E] [--ui | --no-ui] [--fail-first | --no-fail-first]
324
+ forge-parallel.sh run <plan-dir> [--max-parallel N] [--yolo-dwarf] [--yolo-qa] [--dry-run]
325
+ [--verify <cmd>] [--setup <cmd>] [--timeout S]
326
+ [--retry-failed N] [--infra-retries M]
327
+ [--qa-threshold P0|P1|P2|P3|none] [--verify-retries N]
328
+ [--fractal | --no-fractal] [--fractal-<limit> <n>]
329
+ forge-parallel.sh retry <plan-dir> <task-id> [--dwarf <spec>] [--timeout S]
330
+ [--qa-threshold Pn|none] [--verify-retries N]
331
+ forge-parallel.sh accept <plan-dir> <task-id> --reason "<why>" --approved
332
+ forge-parallel.sh review <plan-dir> [--qa <spec>] [--yolo-qa] [--qa-threshold Pn]
333
+ forge-parallel.sh integrate <plan-dir> --approved [--final-review <qa-spec>] [--verify-retries N]
334
+ forge-parallel.sh split <plan-dir> <new-plan-dir> --tasks <id,id> [--dry-run]
335
+ forge-parallel.sh combine <new-plan-dir> <plan-dir> <plan-dir>... [--verify <cmd>] [--dry-run]
336
+ ```
337
+
338
+ | Subcommand | Does |
339
+ |---|---|
340
+ | `plan` | validate `tasks.tsv`, resolve difficulty → concrete dwarf/qa specs, compute waves, render the approval table |
341
+ | `run` | schedule ready tasks; per task: worktree → dwarf → diff → QA → status; merge passing tasks onto the integration branch |
342
+ | `retry` | re-run **one** failed task in the worktree it already has, with its reviewer's findings in the prompt |
343
+ | `integrate` | **never automatic** — merge the integration branch into your branch |
344
+ | `accept` | **only on your explicit instruction** — merge a `FAIL`/`UNKNOWN` task's reviewed work anyway, recording why |
345
+ | `review` | **opt-in, spends QA quota** — one reviewer reads the whole combined result; read-only |
346
+ | `split` / `combine` | move tasks into a plan of their own / join fully merged plans into one |
347
+
348
+ | Flag | Subcommands | Remembered in the plan | Means |
349
+ |---|---|---|---|
350
+ | `--timeout S` | run, retry | `timeout` | per-dispatch timeout in seconds (`0` disables); wins over `FORGE_TIMEOUT` |
351
+ | `--retry-failed N` | run | no — this run only | re-queue a task the reviewer rejected up to `N` more times inside the run |
352
+ | `--infra-retries M` | run | no — this run only | wait out up to `M` infrastructure stops instead of pausing |
353
+ | `--qa-threshold Pn` | run, retry | `qa_threshold` | least severe finding that still blocks; milder ones become known issues; `none` clears |
354
+ | `--verify-retries N` | run, retry, integrate | `verify_retries` | reruns of a failed verify command (default `1`, `0` = strict single run) |
355
+
356
+ **Exit codes:** `0` ok · `2` usage or validation · `3` precondition (not a git repo, …) ·
357
+ `5` some task failed QA, or the combined verification failed · `6` integration conflict ·
358
+ `8` **paused on an infrastructure failure** (quota, auth, rate limit, network): no attempt was
359
+ spent and nothing was judged — fix the cause and run the same command again.
360
+
361
+ The full plan → run → integrate walkthrough is in [decomposed runs](decomposed-runs.md#plan-run-integrate). `retry`, `accept` and `review` are covered in [reviews, retries and recovery](reviews.md); resuming, `split`/`combine`, scope drift and `tasks.tsv` in [decomposed runs](decomposed-runs.md).
362
+
363
+ ## `scripts/forge-memory.sh` and `scripts/forge-install.sh`
364
+
365
+ See [project memory](memory.md#scriptsforge-memorysh) and [install](install.md#scriptsforge-installsh).
@@ -0,0 +1,29 @@
1
+ # Run dataset
2
+
3
+ [← README](../README.md) · [All docs](README.md)
4
+
5
+ Run dirs get deleted, and the ledger keeps spec strings and verdicts but no inputs. So
6
+ every run also records its raw inputs and outcomes outside every repo, in
7
+ `~/.local/share/forge/dataset/` (`FORGE_DATA_HOME` moves it, `FORGE_DATASET=off` turns
8
+ it off). That covers resolved models, prompts, per-attempt diffs, verdicts and findings,
9
+ tokens, merge and verification outcomes, and the full request behind every Jev judgment.
10
+ It exists to train and calibrate decision models on what forge actually did.
11
+
12
+ ```sh
13
+ forge dataset status # size, counts, and anything that looks incomplete
14
+ forge dataset import ~/.local/share/forge/legacy # runs that predate live capture
15
+ forge dataset export # labeled decision cases for benchmarks and fine-tuning
16
+ forge dataset outcomes # which integrated lines survived, read from git history
17
+ ```
18
+
19
+ Deleting a run keeps what it taught the dataset. `forge runs rm <run-dir>` first imports the run
20
+ **strictly** (every event must be stored, or nothing is deleted), then writes a self-describing
21
+ archive under `<data home>/archive/`: a `.tar.gz` whose `FORGE_ARCHIVE.json` records the run
22
+ dir's original path, run id and dataset uid, so `forge dataset import` maps it back to the same
23
+ run later. It records `run_delete_started` and `run_deleted` events around the removal. The same
24
+ import also reads a plan's `escalations.tsv` (with who decided: `policy`, `retry` or `pin`) and
25
+ `control.log`, so human interventions made with `forge control` are in the dataset as
26
+ `control` events. See [forge runs rm](commands.md#forge-runs-rm).
27
+
28
+ Capture is fail-open and never read by anything that builds a prompt. See
29
+ [references/dataset.md](../references/dataset.md) for the event schema and its invariants.