@giamme/forge 0.8.0 → 0.9.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/CHANGELOG.md +24 -0
- package/README.md +106 -1766
- package/SKILL.md +3 -2
- package/VERSION +1 -1
- package/docs/README.md +26 -0
- package/docs/add-ons.md +33 -0
- package/docs/artifacts.md +69 -0
- package/docs/commands.md +315 -0
- package/docs/dataset.md +20 -0
- package/docs/decomposed-runs.md +268 -0
- package/docs/development.md +95 -0
- package/docs/forge-ui.md +92 -0
- package/docs/fractal.md +181 -0
- package/docs/install.md +160 -0
- package/docs/memory.md +156 -0
- package/docs/models.md +118 -0
- package/docs/reviews.md +231 -0
- package/docs/safety.md +55 -0
- package/docs/troubleshooting.md +54 -0
- package/forge +5 -0
- package/package.json +3 -2
- package/references/decompose.md +1 -1
- package/references/fractal.md +1 -1
- package/references/harnesses.md +18 -6
- package/references/solo.md +1 -1
- package/scripts/forge-dispatch.sh +7 -1
- package/scripts/forge-runs.py +121 -0
- package/scripts/forge-runtime.py +59 -6
- package/scripts/forge-version.py +54 -12
- package/scripts/forge_dataset/harvest.py +1 -1
- package/scripts/forge_dataset/importer.py +1 -1
- package/scripts/forge_fractal/__init__.py +2 -1
- package/ui/README.md +80 -20
- package/ui/THIRD_PARTY_NOTICES.md +108 -0
- package/ui/docs/api.md +99 -17
- package/ui/forge_ui/export.py +16 -6
- package/ui/forge_ui/fractal.py +1 -2
- package/ui/forge_ui/reader.py +95 -7
- package/ui/forge_ui/server.py +10 -1
- package/ui/forge_ui/static/D-DINCondensed-Bold.woff2 +0 -0
- package/ui/forge_ui/static/app.js +279 -124
- package/ui/forge_ui/static/cloud3d.js +3 -2
- package/ui/forge_ui/static/cloudui.js +8 -5
- package/ui/forge_ui/static/convo.js +295 -0
- package/ui/forge_ui/static/datatable.js +232 -0
- package/ui/forge_ui/static/diffview.js +29 -10
- package/ui/forge_ui/static/findings3d.js +134 -0
- package/ui/forge_ui/static/graph.js +3 -3
- package/ui/forge_ui/static/icons.js +94 -0
- package/ui/forge_ui/static/index.html +25 -13
- package/ui/forge_ui/static/iso.js +70 -19
- package/ui/forge_ui/static/leaderboard.js +44 -48
- package/ui/forge_ui/static/panel.js +68 -32
- package/ui/forge_ui/static/runmodel.js +17 -1
- package/ui/forge_ui/static/scene3d.js +518 -43
- package/ui/forge_ui/static/search.js +2 -1
- package/ui/forge_ui/static/shell.js +137 -0
- package/ui/forge_ui/static/stagectl.js +150 -0
- package/ui/forge_ui/static/style.css +924 -469
- package/ui/forge_ui/static/theme.js +25 -0
- package/ui/forge_ui/transcripts.py +608 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Decomposed runs
|
|
2
|
+
|
|
3
|
+
[← README](../README.md) · [All docs](README.md)
|
|
4
|
+
|
|
5
|
+
Split one goal into tasks, route each to a model by difficulty, and run them in parallel in isolated worktrees, merging only the tasks that pass review.
|
|
6
|
+
|
|
7
|
+
`--decompose-level low|medium|high` turns one dwarf into many. Without the flag, nothing
|
|
8
|
+
changes — one dwarf, one QA pass.
|
|
9
|
+
|
|
10
|
+
## Two independent axes
|
|
11
|
+
|
|
12
|
+
Easy to conflate, so: **decompose-level** is how finely the *goal* is split. **difficulty**
|
|
13
|
+
is how hard each resulting *task* is.
|
|
14
|
+
|
|
15
|
+
| `--decompose-level` | Split |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `low` | only where the goal has obviously independent pieces; 2–3 coarse tasks |
|
|
18
|
+
| `medium` | one task per coherent unit (module, feature slice); typically 4–6 |
|
|
19
|
+
| `high` | finest split where each task is still independently reviewable *and* independently correct; typically 7–12 |
|
|
20
|
+
|
|
21
|
+
| `difficulty` | Means |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `low` | mechanical and local: rename, move, docs, a test for behaviour that already exists |
|
|
24
|
+
| `medium` | self-contained implementation against a clear spec; bounded blast radius |
|
|
25
|
+
| `high` | needs design judgment, cross-cutting behaviour, subtle edge cases, state or concurrency |
|
|
26
|
+
|
|
27
|
+
Difficulty is about **judgment required, not diff size**. A five-hundred-line mechanical
|
|
28
|
+
rename is `low`. A ten-line concurrency fix is `high`. Getting this backwards sends the cheap
|
|
29
|
+
model at the subtle problem and the expensive one at the boilerplate — worse than not routing
|
|
30
|
+
at all.
|
|
31
|
+
|
|
32
|
+
## Routing dwarves to tasks
|
|
33
|
+
|
|
34
|
+
Per-task assignment can't be expressed when you type the command, because the tasks don't
|
|
35
|
+
exist yet. Naming a dwarf per task would mean guessing how the goal will split. So you map
|
|
36
|
+
**model tiers to difficulty tiers**, once, in advance — three layers, each optional:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 1. one dwarf for everything
|
|
40
|
+
--dwarf sol:xhigh
|
|
41
|
+
|
|
42
|
+
# 2. per-tier routing, with plain --dwarf as the fallback for any tier not named
|
|
43
|
+
--dwarf-high sol:xhigh --dwarf-medium luna:high --dwarf-low gemini:low:antigravity
|
|
44
|
+
--dwarf sonnet:medium
|
|
45
|
+
|
|
46
|
+
# 3. pool several models within one tier — round-robined across tasks
|
|
47
|
+
--dwarf-high sol:xhigh,terra:xhigh
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`--qa`, `--qa-high`, `--qa-medium`, `--qa-low` mirror it exactly. QA has no tier rules by
|
|
51
|
+
default and falls back to `opus`.
|
|
52
|
+
|
|
53
|
+
Resolution order per task: **explicit column value → the tier's rule → plain `--dwarf` →
|
|
54
|
+
`UNASSIGNED`**. An `UNASSIGNED` task makes `plan` exit `2` and `run` refuse outright. forge
|
|
55
|
+
does not invent a model when you haven't said which one should spend your quota.
|
|
56
|
+
|
|
57
|
+
Layer three is **the approval gate**: after decomposition, before any dispatch, you get the
|
|
58
|
+
task table with each task's difficulty and resolved dwarf/qa. Retier a task ("2 is actually
|
|
59
|
+
medium") and it re-routes per your rules, or override a single row's dwarf outright. This is
|
|
60
|
+
also the cost gate — `high` on a large goal is 20+ dispatches, which should be visible before
|
|
61
|
+
it's spent.
|
|
62
|
+
|
|
63
|
+
**Exploration is on by default** (`--explore 0.2`):
|
|
64
|
+
- **Which rows:** only rows left to forge, never one whose dwarf column you filled.
|
|
65
|
+
- **What changes:** now and then such a row gets its *neighbouring* tier's spec from your own
|
|
66
|
+
pools: the next cheaper tier for medium and high rows, the next stronger for low rows.
|
|
67
|
+
Pools that differ only in effort (`--dwarf-low sol --dwarf-high sol:xhigh`) compare the
|
|
68
|
+
two efforts.
|
|
69
|
+
- **How often:** about one row in ten at the default.
|
|
70
|
+
- **What you see:** each explored row is marked `*` in the table, before anything is spent.
|
|
71
|
+
- **What it's for:** `forge dataset routing` reads the draws back as pass rates per model and
|
|
72
|
+
effort. Pass `--explore 0` to turn it off.
|
|
73
|
+
|
|
74
|
+
See [decompose.md](../references/decompose.md#exploratory-routing-on-by-default).
|
|
75
|
+
|
|
76
|
+
## Waves, and what actually bounds parallelism
|
|
77
|
+
|
|
78
|
+
A **wave** is the largest set of tasks whose dependencies are all satisfied by earlier waves
|
|
79
|
+
**and** whose declared `files` sets are pairwise disjoint.
|
|
80
|
+
|
|
81
|
+
Disjointness — not the task count — is the real bound. Two dwarves editing one file produce a
|
|
82
|
+
conflict no reviewer can untangle and no merge can resolve honestly, so they land in different
|
|
83
|
+
waves however the goal was decomposed. When that happens forge says so:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
deferrals (serialized to protect the merge):
|
|
87
|
+
wave 1: lint deferred (file overlap with a task already in this wave)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
That line matters. A decomposition that looks parallel but serializes at run time should
|
|
91
|
+
announce it, rather than leaving you wondering why eight tasks took eight rounds. When most
|
|
92
|
+
tasks overlap, the fix is a better split — not more parallelism.
|
|
93
|
+
|
|
94
|
+
Waves are a planning preview. A Python 3 standard-library coordinator starts eligible tasks
|
|
95
|
+
as prerequisites merge and capacity becomes available, while excluding overlapping active
|
|
96
|
+
paths. Merges are serialized. Each task pins the integration commit at dispatch; retries keep
|
|
97
|
+
that baseline, and QA sees only baseline membership recorded for that task.
|
|
98
|
+
|
|
99
|
+
## Fresh session per task, plus a capsule
|
|
100
|
+
|
|
101
|
+
Every dispatch is a **clean slate** — forge never passes `--continue`, `--resume`, or
|
|
102
|
+
`codex exec resume`. One task's confused turn can't poison another, and each task's context
|
|
103
|
+
stays small.
|
|
104
|
+
|
|
105
|
+
Clean slates alone would leave every dwarf blind to the wider run, so a short `capsule.md` is
|
|
106
|
+
generated from the task's pinned baseline and preserved for both implementation and QA:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
# forge run <run-id>
|
|
110
|
+
Goal: <overall goal>
|
|
111
|
+
You are doing ONE task of <N>. Do not do the others' work.
|
|
112
|
+
|
|
113
|
+
## Your task
|
|
114
|
+
tokens — Add the token model difficulty: medium
|
|
115
|
+
Files you own: src/auth/token.py
|
|
116
|
+
|
|
117
|
+
## Run status
|
|
118
|
+
id diff status files
|
|
119
|
+
middleware high MERGED src/auth/middleware.py
|
|
120
|
+
tokens medium THIS ONE src/auth/token.py
|
|
121
|
+
docs low NOT IN BASE README.md
|
|
122
|
+
|
|
123
|
+
## Ground rules
|
|
124
|
+
- Your branch already contains every MERGED task's work — do not reimplement it.
|
|
125
|
+
- Files owned by other tasks are off limits; another dwarf is editing them now.
|
|
126
|
+
- If your task truly needs a change in someone else's file, say so in your final
|
|
127
|
+
message instead of making it.
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
It's written **per task**, not once per run — tasks in a wave execute concurrently, so a
|
|
131
|
+
single shared capsule file is a race in which each task overwrites it and reads back whichever
|
|
132
|
+
sibling wrote last, handing a dwarf someone else's task description.
|
|
133
|
+
|
|
134
|
+
For QA the capsule additionally scopes the review: code from `MERGED` tasks is already in the
|
|
135
|
+
base and is not this task's bug. Without that, a wave-2 reviewer reports wave-1 code as
|
|
136
|
+
defects in the diff it was handed.
|
|
137
|
+
|
|
138
|
+
## Planning
|
|
139
|
+
|
|
140
|
+
A dwarf that is handed only an objective plans its own approach, silently, inside its own
|
|
141
|
+
run. Usually fine — but in a decomposed run the capsule prevents two dwarves editing one
|
|
142
|
+
*file* and does nothing about them inventing incompatible *interfaces* at a shared seam.
|
|
143
|
+
Both stay in their lane, both pass their own QA, and the mismatch surfaces at integration.
|
|
144
|
+
|
|
145
|
+
So forge plans before it dispatches. By default the orchestrator does it and writes the
|
|
146
|
+
approach into each task's prompt — no extra dispatch. `--planner <spec>` hands that stage to
|
|
147
|
+
a named model instead:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
/forge "migrate the API layer to gRPC" --decompose-level medium \
|
|
151
|
+
--planner sol:xhigh --dwarf-high sol:high --dwarf luna:high
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**One planner dispatch per run, never one per task.** That is the whole point: a single mind
|
|
155
|
+
designs both sides of every seam, where N independent planners would recreate the problem.
|
|
156
|
+
Effort defaults to `xhigh`, since a bad plan is executed at full price by every dwarf
|
|
157
|
+
downstream of it. The planner runs with QA's permission profile — it reads the repo and
|
|
158
|
+
writes nothing to it.
|
|
159
|
+
|
|
160
|
+
The approach shows up in the approval table under each task, which is the last moment it can
|
|
161
|
+
be changed for free, and it is handed to QA as the *intended* approach — so a review can
|
|
162
|
+
finally say "this works, but it abandons the planned shape" rather than only judging against
|
|
163
|
+
the objective.
|
|
164
|
+
|
|
165
|
+
## Plan, run, integrate
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
PLAN=/tmp/forge-auth
|
|
169
|
+
|
|
170
|
+
# 1. plan and inspect the routing
|
|
171
|
+
bash scripts/forge-parallel.sh plan "$PLAN" --repo ~/dev/api \
|
|
172
|
+
--dwarf-high sol:xhigh --dwarf-low gemini:low:antigravity --dwarf luna:high
|
|
173
|
+
|
|
174
|
+
# 2. see exactly what will be dispatched, without dispatching
|
|
175
|
+
bash scripts/forge-parallel.sh run "$PLAN" --dry-run
|
|
176
|
+
|
|
177
|
+
# 3. run it, four dwarves at a time, implementers unsandboxed
|
|
178
|
+
bash scripts/forge-parallel.sh run "$PLAN" --max-parallel 4 --yolo-dwarf
|
|
179
|
+
|
|
180
|
+
# 4. after reading the results, deliver the passing work
|
|
181
|
+
bash scripts/forge-parallel.sh integrate "$PLAN" --approved
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`integrate` refuses without `--approved`, and refuses on a dirty working tree.
|
|
185
|
+
For Fractal execution, pass tier pools to `plan` and backend/limit flags to `run`.
|
|
186
|
+
`--max-parallel` limits task pipelines; the shared `--fractal-concurrency` limit includes
|
|
187
|
+
all their child invocations and QA. See [decomposed Fractal execution](../references/decompose.md#fractal-within-decomposed-tasks).
|
|
188
|
+
|
|
189
|
+
## Resuming an interrupted run
|
|
190
|
+
|
|
191
|
+
Run `run` again to skip MERGED tasks, merge saved PASS results after fingerprint checks,
|
|
192
|
+
and dispatch eligible pending tasks. Tasks paused on an infrastructure failure (`INFRA`) are
|
|
193
|
+
dispatched again without any flag, since nothing was wrong with the work. Failed and
|
|
194
|
+
interrupted tasks need an explicit `retry` (or `run --retry-failed N` for rejected ones).
|
|
195
|
+
Their worktrees and pinned baselines remain available. Concurrent run/retry/integrate
|
|
196
|
+
operations for the same plan are excluded by an advisory lock.
|
|
197
|
+
|
|
198
|
+
For a Fractal-backed run, use `forge fractal resume RUN_ID` to recover recorded execution
|
|
199
|
+
and pipeline checkpoints. A task/subtree selector resumes only that execution scope.
|
|
200
|
+
Explicit `retry` retains the backend and frozen pools; a replacement dwarf must already
|
|
201
|
+
belong to that pool. See [recovery](../references/fractal.md#limits-and-lifecycle).
|
|
202
|
+
|
|
203
|
+
## Splitting and combining plans
|
|
204
|
+
|
|
205
|
+
`run --retry-failed N` removes most of the reason to split a plan (a failed task no longer holds
|
|
206
|
+
the rest of a run). When you still want independent work in separate plans — separate locks,
|
|
207
|
+
separate integration branches, one verified at a time — these two make it a supported operation
|
|
208
|
+
instead of hand-built git plumbing:
|
|
209
|
+
|
|
210
|
+
- `split <plan> <new-plan> --tasks a,b` moves tasks **with their saved state** (attempts,
|
|
211
|
+
findings, reviewed commit, status) into a new plan: their branches and worktrees are renamed to
|
|
212
|
+
the new run (`forge/<new>/<id>`), the new integration branch starts at the source's accepted
|
|
213
|
+
tip, dependencies on already-merged tasks are dropped, and the source forgets the moved rows
|
|
214
|
+
(`split-<new>.txt` records them). It refuses — changing nothing — for a Fractal-backed plan, a
|
|
215
|
+
MERGED or RUNNING task, a selection that leaves a dependent behind, or a dependency that is
|
|
216
|
+
neither moving nor merged. Copy first, delete last; an interrupted split rolls back.
|
|
217
|
+
- `combine <new-plan> <plan-a> <plan-b>…` joins plans whose tasks are **all `MERGED`** into one
|
|
218
|
+
plan: a new integration branch merges each source's, the per-task records are copied, and
|
|
219
|
+
`run <new-plan>` then only verifies (no model call) so `integrate` works unchanged. It refuses
|
|
220
|
+
different repositories, locked or dirty sources, duplicate task ids, and any task left behind;
|
|
221
|
+
a merge conflict exits `6` after removing everything it created. `--verify` sets the combined
|
|
222
|
+
plan's check; `--dry-run` previews and predicts conflicts. Task branches keep their original
|
|
223
|
+
names.
|
|
224
|
+
|
|
225
|
+
## Scope drift
|
|
226
|
+
|
|
227
|
+
After each dwarf, the runner compares what the task **declared** in `files` against what it
|
|
228
|
+
actually touched (a declared directory covers the paths beneath it). Undeclared paths appear
|
|
229
|
+
in the summary and in the QA prompt:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
scope drift (touched files the task did not declare):
|
|
233
|
+
auth src/db.py
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Never a failure — a dwarf that genuinely needed one more file did the right thing. What it
|
|
237
|
+
buys is that a merge `CONFLICT` two waves later arrives with its cause already named.
|
|
238
|
+
|
|
239
|
+
## `tasks.tsv`
|
|
240
|
+
|
|
241
|
+
Tab-separated, one row per task, written during decomposition:
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
# id deps difficulty files dwarf qa title
|
|
245
|
+
middleware - high src/auth/middleware.py - - Auth middleware
|
|
246
|
+
tokens - medium src/auth/token.py - - Token model
|
|
247
|
+
route middleware,tokens medium src/routes/login.py - - Login route
|
|
248
|
+
docs - low README.md - - Document the auth flow
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
| Column | Meaning |
|
|
252
|
+
|---|---|
|
|
253
|
+
| `id` | short unique slug; also the worktree and branch name |
|
|
254
|
+
| `deps` | comma-list of task ids that must land first, or `-` |
|
|
255
|
+
| `difficulty` | `low` \| `medium` \| `high` |
|
|
256
|
+
| `files` | expected touch set, comma-separated — **drives disjointness** |
|
|
257
|
+
| `dwarf` / `qa` | `-` to resolve from the routing rules; an explicit spec always wins |
|
|
258
|
+
| `title` | one line, shown in the approval table and the capsule |
|
|
259
|
+
|
|
260
|
+
Each task also needs `tasks/<id>/prompt.md`, written the same way a single-task forge goal is.
|
|
261
|
+
|
|
262
|
+
`files` is a **promise, not a prediction**: it's what the wave planner trusts when deciding
|
|
263
|
+
what may run concurrently, and what the capsule tells other dwarves not to touch. An
|
|
264
|
+
understated `files` is how two dwarves end up in the same file.
|
|
265
|
+
|
|
266
|
+
`plan` writes resolved specs back into the `dwarf`/`qa` columns, so `run` never consults the
|
|
267
|
+
routing rules — and an explicit value survives a re-plan, which is what makes a gate override
|
|
268
|
+
durable. (`UNASSIGNED` is treated as a leftover marker and re-resolved.)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
[← README](../README.md) · [All docs](README.md)
|
|
4
|
+
|
|
5
|
+
The repository layout, the offline checks, and how forge measures its own runtime cost.
|
|
6
|
+
|
|
7
|
+
## Repository layout
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
forge/
|
|
11
|
+
├── SKILL.md the skill itself — what the orchestrating model reads
|
|
12
|
+
├── registry.tsv alias → (harness, model, effort). Add a row to teach forge a model
|
|
13
|
+
├── README.md the short overview
|
|
14
|
+
├── docs/ the full documentation, one page per topic
|
|
15
|
+
├── LICENSE MIT
|
|
16
|
+
├── package.json the npm package: its name, version and the files it ships
|
|
17
|
+
├── forge launcher, on PATH from npm: `forge install`, `fractal`, `jev`, `dataset` and `ui`
|
|
18
|
+
├── scripts/
|
|
19
|
+
│ ├── forge-dispatch.sh resolve a spec → run one role on one harness
|
|
20
|
+
│ ├── forge-solo.sh the whole single-task run: dwarf → diff → qa
|
|
21
|
+
│ ├── forge-parallel.sh plan / run / retry / integrate for decomposed runs
|
|
22
|
+
│ ├── forge-parallel-options.sh flags shared by several forge-parallel.sh subcommands
|
|
23
|
+
│ ├── forge-lib-task.sh attempt log, infra stops, QA-only resume, guards, severity gate, report blocks
|
|
24
|
+
│ ├── forge-lib-verify.sh verify command lookup and the coverage report
|
|
25
|
+
│ ├── forge-lib-plans.sh accept / split / combine
|
|
26
|
+
│ ├── forge-lib-review.sh the opt-in whole-run review (review, integrate --final-review)
|
|
27
|
+
│ ├── forge-schedule.py readiness scheduler: in-run retries, infrastructure pauses
|
|
28
|
+
│ ├── forge-contract.py the shared QA/dwarf prompt contract and the severity gate
|
|
29
|
+
│ ├── forge-guard.py implementer guards: session wrapper, orphan reaping, promise scan
|
|
30
|
+
│ ├── forge-verify-coverage.py suites the project defines that the verify command skips
|
|
31
|
+
│ ├── forge-memory.sh inject / note / record / spend project memory
|
|
32
|
+
│ ├── forge-fractal.py Fractal CLI and internal adapter entrypoint
|
|
33
|
+
│ ├── forge-fractal-options.sh runner selection, limit flags and help
|
|
34
|
+
│ ├── forge-fractal-dispatch.sh bridge entrypoint for existing pipelines
|
|
35
|
+
│ ├── forge-install-fractal.sh isolated optional runtime installer
|
|
36
|
+
│ ├── forge_fractal/ nested execution, recovery, inspection and dashboard
|
|
37
|
+
│ ├── forge-ui.py `forge ui open|status|stop`: the one shared forge-ui server
|
|
38
|
+
│ ├── forge-ui-options.sh `--ui|--no-ui` and the fail-open launch, sourced by the runners
|
|
39
|
+
│ ├── forge_registry.py the run registry: where run dirs are noted, read by forge-ui
|
|
40
|
+
│ ├── forge-dataset.py `forge dataset` entry point
|
|
41
|
+
│ ├── forge_dataset/ the run dataset: capture hooks, readers, importer, status checks
|
|
42
|
+
│ └── forge-install.sh install into every harness that needs it (opencode and grok find it themselves)
|
|
43
|
+
├── ui/ forge-ui: read-only local run viewer (`forge_ui` package, tests, API contract)
|
|
44
|
+
└── references/
|
|
45
|
+
├── ui.md forge-ui: commands, env vars, shared server, state, privacy
|
|
46
|
+
├── harnesses.md per-harness invocation, ladders, failure modes
|
|
47
|
+
├── decompose.md tasks.tsv schema, difficulty criteria, wave algorithm
|
|
48
|
+
├── fractal.md opt-in backend, limits, recovery and observability
|
|
49
|
+
├── memory.md FORGE_LEARNING grammar, promotion and pruning rules
|
|
50
|
+
└── dataset.md the run dataset: what is captured, where, and its invariants
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Offline checks
|
|
54
|
+
|
|
55
|
+
Run `bash tests/check.sh` for offline regression checks. See [tests](../tests/README.md) for skill
|
|
56
|
+
invocation scenarios and verification limits. There is currently no CI workflow.
|
|
57
|
+
|
|
58
|
+
## Runtime efficiency and measurement
|
|
59
|
+
|
|
60
|
+
Shell entrypoints require Python 3 (standard library only) in addition to Bash and Git.
|
|
61
|
+
The [runtime helper decision](../references/runtime.md) records the module boundaries and tradeoffs.
|
|
62
|
+
Solo and parallel runners default to `--output summary`; use `--output full` to include raw
|
|
63
|
+
backend output. Direct dispatch keeps its full-output default. Read each `dwarf.last` and
|
|
64
|
+
`qa.last` once, and retrieve `.log` or `.out` only when investigating a problem.
|
|
65
|
+
|
|
66
|
+
QA receives complete requirements, approach, ownership, retry findings and distinct memory
|
|
67
|
+
facts once, with review instructions separate from implementation instructions. Prompts and
|
|
68
|
+
full binary diffs remain on disk. Review repositories receive self-contained tree object packs,
|
|
69
|
+
create baseline/final commits, and check out the final tree once. Exact tree comparisons and
|
|
70
|
+
all source, review and integration fingerprint checks remain acceptance boundaries.
|
|
71
|
+
|
|
72
|
+
`FORGE_CAPABILITY_CACHE` optionally selects an offline help cache. Runners share a run-local
|
|
73
|
+
`capabilities/` cache across preflights and dispatches. Keys cover the executable's resolved
|
|
74
|
+
path, device/inode, size and modification/change timestamps, help command mode, registry
|
|
75
|
+
contents and dispatch recipe. Every selected spec, effort and permission recipe is still
|
|
76
|
+
validated; cached help never proves authentication or live model availability.
|
|
77
|
+
|
|
78
|
+
Run `bash scripts/forge-dispatch.sh report <run-dir>` for JSON attempt records, including
|
|
79
|
+
failures and timeouts, with project memory enabled or disabled. `attempts/<role>-<id>/`
|
|
80
|
+
retains prompts, final responses, raw logs, resolution, command and `metrics.json` per dispatch.
|
|
81
|
+
Pipeline records capture preparation, preflight, snapshot, verification and total time;
|
|
82
|
+
dispatch records capture preparation, preflight, model and total time. Nested pipeline
|
|
83
|
+
`dispatch` time includes dispatch overhead: do not add nested totals together. Timing uses
|
|
84
|
+
monotonic seconds. A still-running or forcibly killed record has a null exit code and may
|
|
85
|
+
have incomplete timings. A dispatch that stopped on an infrastructure failure records its class
|
|
86
|
+
(`quota`, `auth`, `rate_limit`, `network`, `empty`) as `infra_class`, and keeps the `.infra` and
|
|
87
|
+
`.orphans` files beside the other attempt artifacts.
|
|
88
|
+
|
|
89
|
+
Prompt bytes are separate from native input, cached-input and output token counts. Codex
|
|
90
|
+
uses `turn.completed` usage; Claude uses result usage (input includes uncached, cache-read
|
|
91
|
+
and cache-creation tokens). Unsupported or absent usage stays null, never estimated from
|
|
92
|
+
bytes. See [measurement and live evaluation](../tests/README.md).
|
|
93
|
+
|
|
94
|
+
Measured results, including the live comparison's higher total token use and latency, are
|
|
95
|
+
recorded in [the September 7 evaluation](../tests/benchmark-2026-09-07.md).
|
package/docs/forge-ui.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# forge-ui
|
|
2
|
+
|
|
3
|
+
[← README](../README.md) · [All docs](README.md)
|
|
4
|
+
|
|
5
|
+
forge-ui is a small read-only local web page that shows runs live, as a 3D isometric map
|
|
6
|
+
ported from [archivision](https://github.com/Giamme/archivision). Its **run cloud** puts every
|
|
7
|
+
run in one full-screen view, grouped by project, in five layouts (helix, sphere, galaxy,
|
|
8
|
+
timeline, constellation), filtered down to exactly the runs you want; drag any run anywhere
|
|
9
|
+
and the cloud remembers it.
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<img src="../ui/docs/media/cloud.webp" width="880" alt="The run cloud: about seventy runs as blocks in five project spirals, orbited, then laid out as galaxies and as a timeline with one lane per project.">
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<table>
|
|
16
|
+
<tr>
|
|
17
|
+
<td width="50%" valign="top"><img src="../ui/docs/media/run.png" alt="forge-ui's window: the runs list, a run's eight tasks on a 3D plate in their planned waves with dependency cables, finding marks and the finish nodes, and the run's inspector."><br><b>A run, as planned.</b> Tasks in their waves with dependency cables, ending in integration, verification and the final review. Click a task to open its attempts, dwarves and reviews.</td>
|
|
18
|
+
<td width="50%" valign="top"><img src="../ui/docs/media/execution.png" alt="The same run on wall-clock time: one block per attempt, failed attempts in red with their finding marks, a plane marking now, the concurrency strip, and the inspector's timeline and critical path."><br><b>And as it ran.</b> One block per attempt in the lane it ran in, failed ones in red, against <code>--max-parallel</code>; the inspector names the critical path.</td>
|
|
19
|
+
</tr>
|
|
20
|
+
<tr>
|
|
21
|
+
<td valign="top"><img src="../ui/docs/media/diff.png" alt="The diff a reviewer read, with a P1 finding pinned under the line comparing token digests and a P2 finding under the revoke function."><br><b>Findings on their lines.</b> Any diff of a task, or exactly the diff one reviewer read, with each P0–P3 finding under the line it names.</td>
|
|
22
|
+
<td valign="top"><img src="../ui/docs/media/conversation.png" alt="A dwarf's conversation: its thinking, a search, the files it wrote, a test run that failed with exit 1 and the run that passed after the fix."><br><b>What each agent said and ran.</b> A dwarf's or reviewer's conversation from its CLI's log: commands with their exit and output, edits linked to the diff, its thinking; searchable, errors one key apart, live while it runs.</td>
|
|
23
|
+
</tr>
|
|
24
|
+
<tr>
|
|
25
|
+
<td valign="top"><img src="../ui/docs/media/models.png" alt="The model leaderboard: per implementer, tasks, first-attempt pass rate with a 95% interval bar, retries, escalations, timeouts, accepts, median model time and tokens."><br><b>Models, measured on your runs.</b> First-attempt pass rate with a confidence interval, retries, escalations, time and tokens; reviewers' verdicts and shadow agreement.</td>
|
|
26
|
+
<td valign="top"><img src="../ui/docs/media/files.png" alt="The files heatmap: files grouped by directory against tasks grouped by wave, with planned, touched, drift and same-wave overlap marks."><br><b>Who touched which file.</b> Planned, changed, drifted into or conflicted on, wave by wave; a cell opens that file's diff.</td>
|
|
27
|
+
</tr>
|
|
28
|
+
<tr>
|
|
29
|
+
<td colspan="2" valign="top" align="center"><img width="50%" src="../ui/docs/media/map.png" alt="The map of every run: one block per run in a district per repo, green when done, amber while running, red with failures."><br><b>Every run, by repo.</b> One block per run with a lamp per task, filtered by state, repo, model, age or review verdict.</td>
|
|
30
|
+
</tr>
|
|
31
|
+
</table>
|
|
32
|
+
|
|
33
|
+
The page reads like a signal box's desk: engraved plates for headings, push buttons with lamps
|
|
34
|
+
for switches, and lamps that keep one meaning everywhere (amber running, green merged, red failed,
|
|
35
|
+
unlit pending). Two layouts share it. *Immersive*, the default, floats the runs, the inspector and the tasks
|
|
36
|
+
over a full-window stage (on a first visit the inspector and the tasks start folded, so a run
|
|
37
|
+
opens on its plate); *Workbench* docks them beside it with splitters. `1`, `2` and
|
|
38
|
+
`3` fold each module away, the header switches layout and theme (system, light or dark), and the
|
|
39
|
+
task and model tables sort, reorder and hide columns. forge-ui remembers all of it in your browser.
|
|
40
|
+
|
|
41
|
+
On the 3D stage every review finding stands over its block as a mark shaped by its severity, and
|
|
42
|
+
a click opens the diff at that finding. A chosen task keeps its route lit, a hover shows its card
|
|
43
|
+
(attempts, time, tokens, worst finding), and merges, failed attempts and escalations play over the
|
|
44
|
+
plate as they happen or as a replay passes them. The *View* menu switches each part of the drawing
|
|
45
|
+
on or off; the keys at the stage's edge fit, zoom, switch between perspective, isometric and
|
|
46
|
+
top-down, open a legend of what is drawn, and `?` lists every key.
|
|
47
|
+
|
|
48
|
+
Each dwarf's and reviewer's conversation opens from its attempt: what it said, what it ran and
|
|
49
|
+
with what exit, what it changed (with a link into the diff), its thinking folded, and the final
|
|
50
|
+
answer with tokens and cost, searchable, with its errors one key apart and, while it runs,
|
|
51
|
+
following its log as it grows. It is read from the agent CLI's own log, whichever harness
|
|
52
|
+
wrote it (as plain text for those that log no events yet), or for an older claude run from
|
|
53
|
+
Claude's session file on this machine.
|
|
54
|
+
|
|
55
|
+
Also: replay, critical path, Fractal child-task trees, quick jump (Ctrl K, ⌘K on a Mac, or
|
|
56
|
+
`/`), a bell for runs that finish or fail, failed tasks and final-review verdicts (with opt-in
|
|
57
|
+
browser notifications), and a run exported as one HTML file that opens without forge-ui, with
|
|
58
|
+
prompts, diffs and local paths left out unless you choose them.
|
|
59
|
+
|
|
60
|
+
Offline (it loads three.js from a CDN for the 3D view) the same page works in 2D. It is opt-in.
|
|
61
|
+
The `/forge` skill asks "Open forge-ui to watch this run? [y/N]" at the start of every new
|
|
62
|
+
interactive run, or you pass it yourself:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
bash scripts/forge-solo.sh "$RUN" --repo "$REPO" --dwarf sol --ui
|
|
66
|
+
bash scripts/forge-parallel.sh plan "$PLAN" --repo "$REPO" --decompose-level medium --ui
|
|
67
|
+
forge ui open [DIR] # an existing run dir, or the run list
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
All runs share one detached server on `127.0.0.1:8765` (`FORGE_UI_PORT`) that exits after
|
|
71
|
+
four idle hours (`FORGE_UI_IDLE_S`). A UI that cannot start never fails the run. It has no
|
|
72
|
+
token: any local process can read the prompts and diffs of the runs it shows. See
|
|
73
|
+
[references/ui.md](../references/ui.md) and [ui/README.md](../ui/README.md).
|
|
74
|
+
|
|
75
|
+
To look around before your first run, point it at made-up runs (the ones in these pictures), from a git checkout:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
python3 ui/tools/demo_runs.py /tmp/forge-demo
|
|
79
|
+
(cd ui && python3 -m forge_ui --no-registry --root /tmp/forge-demo --open)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## `forge ui` command group
|
|
83
|
+
|
|
84
|
+
| Command | Purpose |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `open [DIR] [--no-browser] [--port N]` | start or reuse the shared forge-ui server; print `forge-ui: <url>` for the plan or solo run dir `DIR` (the run list without it) and open a browser the first time |
|
|
87
|
+
| `status [--json]` | exit 0 and describe the server when it runs, 1 when not |
|
|
88
|
+
| `stop` | stop the server |
|
|
89
|
+
|
|
90
|
+
`FORGE_UI=off` makes `--ui` on a runner start nothing (it does not stop a running server or block `forge ui open`; use `forge ui stop`), `FORGE_UI_BROWSER=off` never opens a browser,
|
|
91
|
+
`FORGE_UI_PORT` (8765) and `FORGE_UI_IDLE_S` (14400, `0` = never) tune the server. State and
|
|
92
|
+
`server.log` are in `${XDG_STATE_HOME:-~/.local/state}/forge/ui/`.
|
package/docs/fractal.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Fractal execution
|
|
2
|
+
|
|
3
|
+
[← README](../README.md) · [All docs](README.md)
|
|
4
|
+
|
|
5
|
+
Fractal is an optional implementation backend for both solo and decomposed runs. It uses
|
|
6
|
+
the existing Forge dispatcher for Codex, Claude, OpenClaude, OpenCode and Antigravity.
|
|
7
|
+
Each work step gets a fresh model invocation; preserved files and child results provide
|
|
8
|
+
continuity when a parent resumes. Independent QA reviews the complete Forge task diff.
|
|
9
|
+
|
|
10
|
+
`--decompose-level` plans top-level Forge tasks before execution. `--fractal` lets an
|
|
11
|
+
implementer request nested children during execution. They can be used together, and
|
|
12
|
+
solo runs can use Fractal without a top-level decomposition.
|
|
13
|
+
|
|
14
|
+
## Install the optional runtime
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
forge fractal install --dry-run
|
|
18
|
+
forge fractal install --yes --with-prerequisites
|
|
19
|
+
forge fractal doctor --spec sol --spec opus --json
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The managed runtime pins **Fractal 1.2.0** at revision
|
|
23
|
+
`18793200c0d7e8cdb2db369ea3abe5647a1e15e4`, checks the source archive checksum,
|
|
24
|
+
and includes the required `wiki` executable. It prefers an existing Python 3.12–3.14;
|
|
25
|
+
with prerequisite installation selected, it can provision uv, Python 3.13 and tmux.
|
|
26
|
+
tmux installation uses an existing Homebrew on macOS or apt on Debian/Ubuntu.
|
|
27
|
+
The [installation reference](../references/fractal.md#installation-and-provenance) covers
|
|
28
|
+
consent, supported bootstrap platforms, provenance and failure diagnostics.
|
|
29
|
+
|
|
30
|
+
Installation never enables Fractal for a run, adds no command and leaves your shell startup
|
|
31
|
+
files alone.
|
|
32
|
+
Doctor checks the runtime and advertised harness capabilities without calling a provider.
|
|
33
|
+
|
|
34
|
+
## Start and inspect a run
|
|
35
|
+
|
|
36
|
+
Through the skill:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
/forge "add retry with exponential backoff to the HTTP client" --dwarf sol:high --fractal
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Or prepare a solo run directory outside the product repository and invoke the runner:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
FORGE_RUN="$HOME/.local/state/forge/examples/http-client"
|
|
46
|
+
mkdir -p "$FORGE_RUN"
|
|
47
|
+
printf '%s\n' 'Add bounded exponential backoff to the HTTP client and run its tests.' > "$FORGE_RUN/prompt.md"
|
|
48
|
+
bash scripts/forge-solo.sh "$FORGE_RUN" --repo /absolute/path/to/product \
|
|
49
|
+
--dwarf sol:high --qa opus --fractal --fractal-concurrency 3
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Choose a new run directory for unrelated work. Backend selection, routing pools and limits
|
|
53
|
+
are stored with the run; resume and explicit retry retain them. For a prepared, approved
|
|
54
|
+
decomposed plan, select the backend on `run`:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
bash scripts/forge-parallel.sh run /absolute/path/to/plan --fractal --dry-run
|
|
58
|
+
bash scripts/forge-parallel.sh run /absolute/path/to/plan --fractal
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Dry runs show resolved model pools, limits and proposed workspaces without installation
|
|
62
|
+
or provider calls. When a selected runtime is unavailable, interactive runs offer
|
|
63
|
+
installation; unattended runs return an actionable error instead of changing backends.
|
|
64
|
+
|
|
65
|
+
Discover the managed run ID, then inspect it from another terminal:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
forge fractal runs --repo /absolute/path/to/product --json
|
|
69
|
+
forge fractal open # live runs index
|
|
70
|
+
forge fractal status RUN_ID --json
|
|
71
|
+
forge fractal tree RUN_ID --json
|
|
72
|
+
forge fractal logs RUN_ID --follow
|
|
73
|
+
forge fractal report RUN_ID --html /absolute/path/to/report.html
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`RUN_ID` is the `run-…` identifier returned by `runs`, not the solo directory or plan name.
|
|
77
|
+
The [run inspector](../references/fractal-dashboard.md) opens on progress and problems, then lets
|
|
78
|
+
readers inspect task QA/history or node decisions, logs and changes. It refreshes about every
|
|
79
|
+
two seconds without replacing the workspace; search, selection, focus and scrolling remain in
|
|
80
|
+
place. “Pause live updates” affects the browser only. Browser access is read-only, bound to
|
|
81
|
+
`127.0.0.1` with an ephemeral access token. Closing its server does not stop execution.
|
|
82
|
+
Portable HTML embeds complete captured history and logs, works offline and needs no Fractal
|
|
83
|
+
runtime to read.
|
|
84
|
+
|
|
85
|
+
## Automatic recursive decomposition
|
|
86
|
+
|
|
87
|
+
`--fractal` permits workers to request children. To require a planning decision before
|
|
88
|
+
every eligible node implements, use `--fractal-auto-decompose`:
|
|
89
|
+
|
|
90
|
+
```text
|
|
91
|
+
/forge "<goal>" --dwarf luna:high --qa sol:high --fractal-auto-decompose --fractal-planner sol:xhigh --fractal-depth 3 --fractal-nodes 24
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
After the top-level Forge approval, the planner automatically splits useful work or
|
|
95
|
+
records why it is atomic. Children repeat this decision within the approved ownership
|
|
96
|
+
and frozen limits. `--fractal-planner` selects a separate decision model; when omitted,
|
|
97
|
+
Forge reuses the configured top-level planner, then the task's initial root model.
|
|
98
|
+
Decisions use disposable snapshots, persist for resume, and appear in tree/status/HTML
|
|
99
|
+
reports. Ordinary `--fractal` and existing runs retain their current behavior. Start a
|
|
100
|
+
new run to change policy or planner. See the [full decision contract](../references/fractal.md#automatic-decomposition-decisions).
|
|
101
|
+
|
|
102
|
+
## Bounds, recovery and acceptance
|
|
103
|
+
|
|
104
|
+
Defaults per Forge task are two nesting levels below implementation, three unsettled
|
|
105
|
+
direct children per node, twelve lifetime nodes, six iterations per node per attempt,
|
|
106
|
+
and a 45-minute attempt deadline excluding explicit pauses. Three model slots are shared
|
|
107
|
+
across the whole Forge run, including QA. `--max-parallel` bounds top-level task pipelines;
|
|
108
|
+
`--fractal-concurrency` bounds model invocations across their nested trees.
|
|
109
|
+
|
|
110
|
+
Child difficulty selects a frozen `--dwarf-low`, `--dwarf-medium` or `--dwarf-high` pool,
|
|
111
|
+
falling back to the configured general dwarf, then the parent. Dependencies and owned
|
|
112
|
+
paths constrain admission; overlapping ownership is serialized. Fractal never implies
|
|
113
|
+
`--yolo-dwarf`. Costs are observational; unavailable usage stays unknown and dollar-cap
|
|
114
|
+
requests are rejected.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
forge fractal pause RUN_ID
|
|
118
|
+
forge fractal resume RUN_ID
|
|
119
|
+
forge fractal stop RUN_ID
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Pause and stop preserve work and diagnostics. Run-level resume recovers recorded execution
|
|
123
|
+
and the Forge pipeline without repeating accepted stages. Use explicit runner retry for
|
|
124
|
+
a new attempt, retaining work and the original Forge QA baseline. Controls also accept
|
|
125
|
+
`--task TASK_ID` and `--task TASK_ID --node NODE_ID`; those IDs come from `tree` output.
|
|
126
|
+
|
|
127
|
+
Managed data lives in `${XDG_STATE_HOME:-$HOME/.local/state}/forge/fractal/`. Solo execution
|
|
128
|
+
uses an isolated snapshot and imports changes only after checking source drift, preserving
|
|
129
|
+
staging and leaving changes uncommitted. Decomposed candidates return to Forge's existing
|
|
130
|
+
review/integration pipeline. **Fractal completion is not Forge acceptance**: QA, repository
|
|
131
|
+
verification and authorization to update the user's branch remain distinct.
|
|
132
|
+
|
|
133
|
+
See the [full Fractal reference](../references/fractal.md) for limits, child requests and
|
|
134
|
+
recovery details, and [verification evidence](../tests/fractal-verification.md) for the tested
|
|
135
|
+
platforms and browser checks. No paid-provider or speed/cost claim follows from fake-CLI tests.
|
|
136
|
+
|
|
137
|
+
## `forge fractal` command group
|
|
138
|
+
|
|
139
|
+
Run it as `forge fractal`, or `forge fractal` from a git checkout.
|
|
140
|
+
This group manages Fractal runs; it does not replace the `/forge` skill or runner scripts.
|
|
141
|
+
|
|
142
|
+
| Command | Purpose |
|
|
143
|
+
| --- | --- |
|
|
144
|
+
| `install [--dry-run] [--yes] [--with-prerequisites]` | preview or install the isolated pinned runtime |
|
|
145
|
+
| `doctor [--spec SPEC] [--json]` | check runtime/hooks/tmux and optional repeated harness specs without provider calls |
|
|
146
|
+
| `runs [--repo DIR] [--json] [--html PATH]` | discover managed runs, optionally filtered by repository |
|
|
147
|
+
| `status\|tree\|activity RUN_ID` | inspect progress, hierarchy and history |
|
|
148
|
+
| `logs\|costs\|messages\|config RUN_ID` | inspect diagnostics, observed accounting, radio traffic and effective settings |
|
|
149
|
+
| `pause\|resume\|stop RUN_ID` | request a control and record its observed state |
|
|
150
|
+
| `open [RUN_ID] [--port PORT]` | open the read-only live dashboard or runs index |
|
|
151
|
+
| `report RUN_ID [--html PATH]` | capture a self-contained HTML report; default filename is `RUN_ID.html` |
|
|
152
|
+
|
|
153
|
+
Inspection commands accept `--task TASK_ID`, `--node NODE_ID`, `--json`, `--html PATH`,
|
|
154
|
+
`--offset N` and `--limit N` (1–1000). They currently return a common JSON run projection;
|
|
155
|
+
the command names do not imply separate output schemas. `logs --follow` follows changes.
|
|
156
|
+
HTML exports capture full history and logs. Controls require an explicit run ID, and a
|
|
157
|
+
node control also requires its task ID; they never guess the latest run. Use each command's
|
|
158
|
+
`--help` for its accepted options. Installation is also available through
|
|
159
|
+
`bash scripts/forge-install-fractal.sh`.
|
|
160
|
+
|
|
161
|
+
Fractal adds a managed workspace alongside the runner artifacts described here:
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
${XDG_STATE_HOME:-$HOME/.local/state}/forge/fractal/
|
|
165
|
+
runtime/ isolated pinned Fractal and wiki environment
|
|
166
|
+
provenance.json installed versions and source checksum
|
|
167
|
+
installs/ installation attempts and diagnostics
|
|
168
|
+
runs/<run-id>/run.json effective routing, limits and runner binding
|
|
169
|
+
runs/<run-id>/controls/ requested controls and observed results
|
|
170
|
+
runs/<run-id>/tasks/<task-id>/
|
|
171
|
+
request.json / state.json task request and execution checkpoint
|
|
172
|
+
initialization.json control repository and Fractal ledger provenance
|
|
173
|
+
control/ Fractal metadata, separate from product changes
|
|
174
|
+
nodes/<node-id>/product/ isolated product candidate
|
|
175
|
+
nodes/<node-id>/steps/ fresh dispatcher attempts and raw logs
|
|
176
|
+
outcome.json captured Forge acceptance and verification
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The original solo/plan directory stores `fractal-selection.json`; decomposed plans also
|
|
180
|
+
store `fractal-routing.json`. Prefer `forge fractal runs`, `tree`, `logs` and `report`
|
|
181
|
+
to direct ledger access. Inspection and stop never delete managed work.
|