@giamme/forge 0.0.0-stage → 0.8.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 +181 -0
- package/LICENSE +21 -0
- package/README.md +1854 -2
- package/SKILL.md +122 -0
- package/VERSION +1 -0
- package/forge +74 -0
- package/package.json +26 -4
- package/references/dataset.md +329 -0
- package/references/decompose.md +667 -0
- package/references/fractal-dashboard.md +21 -0
- package/references/fractal.md +307 -0
- package/references/harnesses.md +353 -0
- package/references/jev.md +865 -0
- package/references/memory.md +228 -0
- package/references/planning.md +42 -0
- package/references/ripwire.md +47 -0
- package/references/runtime.md +64 -0
- package/references/solo.md +113 -0
- package/references/ui.md +112 -0
- package/registry.tsv +81 -0
- package/scripts/forge-artifact.sh +78 -0
- package/scripts/forge-contract.py +430 -0
- package/scripts/forge-dataset.py +6 -0
- package/scripts/forge-dispatch.sh +665 -0
- package/scripts/forge-fail-first.py +195 -0
- package/scripts/forge-fractal-dispatch.sh +4 -0
- package/scripts/forge-fractal-options.sh +54 -0
- package/scripts/forge-fractal.py +6 -0
- package/scripts/forge-guard.py +266 -0
- package/scripts/forge-install-fractal.sh +4 -0
- package/scripts/forge-install-ripwire.sh +52 -0
- package/scripts/forge-install.sh +135 -0
- package/scripts/forge-jev-options.sh +259 -0
- package/scripts/forge-jev.py +6 -0
- package/scripts/forge-lib-plans.sh +785 -0
- package/scripts/forge-lib-review.sh +494 -0
- package/scripts/forge-lib-task.sh +302 -0
- package/scripts/forge-lib-verify.sh +30 -0
- package/scripts/forge-memory.sh +575 -0
- package/scripts/forge-metrics.sh +39 -0
- package/scripts/forge-parallel-options.sh +76 -0
- package/scripts/forge-parallel.sh +1717 -0
- package/scripts/forge-plan-check.py +118 -0
- package/scripts/forge-prompt.py +45 -0
- package/scripts/forge-ripwire.py +136 -0
- package/scripts/forge-route.py +344 -0
- package/scripts/forge-runtime.py +533 -0
- package/scripts/forge-schedule.py +312 -0
- package/scripts/forge-shadow.py +305 -0
- package/scripts/forge-solo.sh +347 -0
- package/scripts/forge-ui-options.sh +42 -0
- package/scripts/forge-ui.py +435 -0
- package/scripts/forge-update.sh +71 -0
- package/scripts/forge-verify-coverage.py +956 -0
- package/scripts/forge-version.py +198 -0
- package/scripts/forge_dataset/__init__.py +439 -0
- package/scripts/forge_dataset/capture.py +330 -0
- package/scripts/forge_dataset/checks.py +109 -0
- package/scripts/forge_dataset/cli.py +233 -0
- package/scripts/forge_dataset/export.py +1009 -0
- package/scripts/forge_dataset/harvest.py +716 -0
- package/scripts/forge_dataset/importer.py +412 -0
- package/scripts/forge_dataset/outcomes.py +275 -0
- package/scripts/forge_dataset/routing.py +278 -0
- package/scripts/forge_fractal/__init__.py +83 -0
- package/scripts/forge_fractal/bridge.py +46 -0
- package/scripts/forge_fractal/cli.py +202 -0
- package/scripts/forge_fractal/dashboard.css +138 -0
- package/scripts/forge_fractal/dashboard.html +41 -0
- package/scripts/forge_fractal/dashboard.js +687 -0
- package/scripts/forge_fractal/decomposition.py +262 -0
- package/scripts/forge_fractal/execution.py +659 -0
- package/scripts/forge_fractal/inspection.py +261 -0
- package/scripts/forge_fractal/install.py +158 -0
- package/scripts/forge_fractal/invocation.py +94 -0
- package/scripts/forge_fractal/pipeline.py +124 -0
- package/scripts/forge_fractal/selection.py +179 -0
- package/scripts/forge_jev/__init__.py +376 -0
- package/scripts/forge_jev/backtest.py +322 -0
- package/scripts/forge_jev/cli.py +980 -0
- package/scripts/forge_jev/client.py +418 -0
- package/scripts/forge_jev/corpus.py +156 -0
- package/scripts/forge_jev/coupling.py +244 -0
- package/scripts/forge_jev/features.py +24 -0
- package/scripts/forge_jev/gates.py +100 -0
- package/scripts/forge_jev/memory.py +163 -0
- package/scripts/forge_jev/outcome.py +49 -0
- package/scripts/forge_jev/predict.py +204 -0
- package/scripts/forge_jev/questions.py +661 -0
- package/scripts/forge_jev/review.py +73 -0
- package/scripts/forge_jev/routing.py +271 -0
- package/scripts/forge_jev/subset.py +123 -0
- package/scripts/forge_jev/verify.py +453 -0
- package/scripts/forge_registry.py +140 -0
- package/ui/README.md +287 -0
- package/ui/THIRD_PARTY_NOTICES.md +69 -0
- package/ui/docs/api.md +888 -0
- package/ui/forge_ui/__init__.py +20 -0
- package/ui/forge_ui/__main__.py +135 -0
- package/ui/forge_ui/diffs.py +454 -0
- package/ui/forge_ui/executions.py +436 -0
- package/ui/forge_ui/export.py +204 -0
- package/ui/forge_ui/findings.py +132 -0
- package/ui/forge_ui/fractal.py +583 -0
- package/ui/forge_ui/models.py +216 -0
- package/ui/forge_ui/reader.py +1336 -0
- package/ui/forge_ui/server.py +303 -0
- package/ui/forge_ui/static/app.js +924 -0
- package/ui/forge_ui/static/cloud3d.js +646 -0
- package/ui/forge_ui/static/cloudmodel.js +375 -0
- package/ui/forge_ui/static/cloudui.js +394 -0
- package/ui/forge_ui/static/diffview.js +216 -0
- package/ui/forge_ui/static/favicon.svg +1 -0
- package/ui/forge_ui/static/files.js +776 -0
- package/ui/forge_ui/static/gantt.js +97 -0
- package/ui/forge_ui/static/graph.js +266 -0
- package/ui/forge_ui/static/index.html +55 -0
- package/ui/forge_ui/static/iso.js +765 -0
- package/ui/forge_ui/static/leaderboard.js +315 -0
- package/ui/forge_ui/static/map3d.js +45 -0
- package/ui/forge_ui/static/modelstats.js +249 -0
- package/ui/forge_ui/static/notify.js +179 -0
- package/ui/forge_ui/static/panel.js +526 -0
- package/ui/forge_ui/static/runmodel.js +651 -0
- package/ui/forge_ui/static/scene3d.js +996 -0
- package/ui/forge_ui/static/search.js +119 -0
- package/ui/forge_ui/static/style.css +618 -0
package/SKILL.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: forge
|
|
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]'
|
|
5
|
+
allowed-tools: [Bash, Read]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Forge
|
|
9
|
+
|
|
10
|
+
Run an implementer (**dwarf**) followed by an independent **QA** review of its actual
|
|
11
|
+
changes. Use the scripts for dispatch and capture; do not reconstruct harness commands.
|
|
12
|
+
For explanation requests, explain the workflow without spending model quota.
|
|
13
|
+
|
|
14
|
+
## Choices and boundaries
|
|
15
|
+
|
|
16
|
+
- A dwarf model must be chosen by the user. Ask when it is missing; never invent one.
|
|
17
|
+
- QA defaults to `opus`; effort defaults to `medium` for dwarf and `xhigh` for QA/planner.
|
|
18
|
+
- Specs are `alias[:effort[:harness]]`, e.g. `sol:xhigh:openclaude`. Resolve using
|
|
19
|
+
[registry.tsv](registry.tsv); report any effort clamp. Literal model IDs require a harness.
|
|
20
|
+
- Bypass flags apply only when explicitly requested for that role (`--yolo-dwarf`,
|
|
21
|
+
`--yolo-qa`). Bash access can mutate files despite disabled editing tools.
|
|
22
|
+
- Ask **“Use Fractal for this run? [y/N]”** once before an interactive run, unless
|
|
23
|
+
the user supplied `--fractal`, `--no-fractal`, or `--fractal-auto-decompose`. Pass the answer explicitly to
|
|
24
|
+
the runner. Unattended runs default off. Installation never activates Fractal.
|
|
25
|
+
Resume and explicit retry retain the recorded choice. Read [Fractal](references/fractal.md)
|
|
26
|
+
when selected; Fractal completion never substitutes for Forge QA acceptance.
|
|
27
|
+
- Ask **“Open forge-ui to watch this run? [y/N]”** once at the start of every new
|
|
28
|
+
interactive run, unless the user supplied `--ui` or `--no-ui`. Pass the answer to `plan`
|
|
29
|
+
or `forge-solo.sh` and relay the `forge-ui:` URL they print. Never ask on resume or retry;
|
|
30
|
+
unattended runs leave it off. A UI failure never changes the run. Read [forge-ui](references/ui.md).
|
|
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.
|
|
34
|
+
- `--fractal-auto-decompose` enables automatic split-or-atomic decisions before each
|
|
35
|
+
eligible node implements. Include the effective planner and bounds in the approval
|
|
36
|
+
preview; child decisions need no additional user approval inside those bounds.
|
|
37
|
+
Forward `--fractal-planner <spec>` to the runner. When omitted, forward a selected
|
|
38
|
+
top-level `--planner` as `--fractal-planner`; otherwise each task's initial root model
|
|
39
|
+
plans all its descendants. Ordinary `--fractal` keeps worker-requested decomposition.
|
|
40
|
+
- One implementer per tree. Solo edits remain uncommitted. Decomposed runs may commit
|
|
41
|
+
and merge on Forge task and integration branches. Updating the user's branch requires
|
|
42
|
+
separate authorization and `integrate --approved`. Never push automatically.
|
|
43
|
+
- Show the decomposed task/model table and wait for approval before dispatch. Retry only
|
|
44
|
+
when requested; preserve failed task branches and worktrees. `run --retry-failed N`,
|
|
45
|
+
`--infra-retries M`, `--qa-threshold Pn` and `plan --shadow-qa` (a second review of a
|
|
46
|
+
sampled share of attempts, never read, to measure reviewer agreement) are opt-in: offer
|
|
47
|
+
them, never add them unprompted. So is `--fail-first` (solo or `plan`): the change's new
|
|
48
|
+
tests also run without its non-test changes, and the reviewer is asked to report any that
|
|
49
|
+
still pass as P2; it needs `.forge/verify-subset` and never changes a result by itself. `plan` explores by default (`--explore 0.2`: now and then
|
|
50
|
+
a row left to forge gets its neighbouring tier's model from the user's pools, odds
|
|
51
|
+
recorded for `forge dataset routing`); say so with the table and pass `--explore 0` when
|
|
52
|
+
the user declines. Retries follow a policy: after three failed attempts on one model the
|
|
53
|
+
next goes a tier up in the user's pools, or the task stops with a split suggestion
|
|
54
|
+
(`--escalate-after N`, `0` = off); an explicit `retry --dwarf` overrides it. `accept`
|
|
55
|
+
overrides a reviewer, so run it (with the user's `--reason` and
|
|
56
|
+
`--approved`) only on the user's explicit instruction; never self-accept.
|
|
57
|
+
- Exit `8` / status `INFRA` is a quota, auth or network stop, not a task failure and no
|
|
58
|
+
attempt was spent: report it, say what to fix, and re-run only when told. For a multi-task
|
|
59
|
+
plan, offer the opt-in whole-run review (`review`, or `integrate --final-review <qa-spec>`);
|
|
60
|
+
it spends QA quota, so never run it unprompted.
|
|
61
|
+
- Jev is optional, off unless configured and enabled, and always advisory: it never
|
|
62
|
+
changes a task's tier, never selects a model, and never substitutes for QA acceptance
|
|
63
|
+
or repository verification (`--jev-act` is still accepted and changes nothing). Read
|
|
64
|
+
[Jev](references/jev.md) when selected.
|
|
65
|
+
|
|
66
|
+
## Common workflow
|
|
67
|
+
|
|
68
|
+
1. Inspect the repository and existing work. State the goal, selected models and any bypass
|
|
69
|
+
flags. Keep complete requirements in `prompt.md`; short titles are insufficient for QA.
|
|
70
|
+
2. Preflight every selected role before the first model call, including an optional planner:
|
|
71
|
+
`bash <skill_dir>/scripts/forge-dispatch.sh doctor --spec <spec> --role <role>`.
|
|
72
|
+
This checks resolution, executable and advertised flags without model quota. Authentication,
|
|
73
|
+
quota and live model availability remain unverified; a live probe must be explicitly requested.
|
|
74
|
+
3. Use [solo runs](references/solo.md) for one implementation. For `--decompose-level
|
|
75
|
+
low|medium|high`, read [decomposition](references/decompose.md), prepare the task table,
|
|
76
|
+
obtain approval, then use `forge-parallel.sh plan/run`. Write the user's request verbatim
|
|
77
|
+
to `request.md` in the run or plan dir, and pass `--decompose-level` to `plan` with the
|
|
78
|
+
level you actually split at, even when the user named none. Keep each task small and end
|
|
79
|
+
its `prompt.md` with an `## Acceptance criteria` section of checks the reviewer can verify;
|
|
80
|
+
`plan` names tasks over 7K characters or 9 files, where first attempts mostly fail review.
|
|
81
|
+
Pass the recorded Fractal choice and requested limits to the execution runner; tier
|
|
82
|
+
pools go to solo directly or decomposed `plan`. Fractal does not replace planner dispatch.
|
|
83
|
+
`--timeout` applies to decomposed runs too (kept in the plan).
|
|
84
|
+
4. Runners default to summary output. Read each `dwarf.last` and `qa.last` once; retrieve raw
|
|
85
|
+
logs only when needed. Report findings faithfully, and identify verification
|
|
86
|
+
limits. Source or review mutations invalidate acceptance. Missing verdicts are UNKNOWN.
|
|
87
|
+
An absent repository verification command means UNVERIFIED, even when QA passes.
|
|
88
|
+
|
|
89
|
+
For a Fractal run, report its managed run ID with the Forge result. Use
|
|
90
|
+
`<skill_dir>/forge fractal runs --repo <repo> --json` and `tree RUN_ID --json` to discover
|
|
91
|
+
run/task/node IDs; use `status`, `logs` or `open` for inspection. Run-level `resume`
|
|
92
|
+
recovers the recorded pipeline; scoped controls affect only the selected execution scope.
|
|
93
|
+
Preserve failed work and state the distinction between execution completion, QA acceptance
|
|
94
|
+
and verification. Read the Fractal reference before retrying, changing limits or exporting
|
|
95
|
+
a portable report.
|
|
96
|
+
|
|
97
|
+
Ripwire context is automatic when compatible; `--no-ripwire` or `FORGE_RIPWIRE=off`
|
|
98
|
+
disables it. Pass opt-out to every role, including a separately dispatched planner.
|
|
99
|
+
Runners offer installation once before agents; dispatch never prompts. See
|
|
100
|
+
[Ripwire](references/ripwire.md) for installation, limits and fallback behavior.
|
|
101
|
+
|
|
102
|
+
## Conditional references
|
|
103
|
+
|
|
104
|
+
- [Planning](references/planning.md): read for `--planner` or an agreed approach.
|
|
105
|
+
- [Solo](references/solo.md): command, snapshots, artifacts, exit codes and native-review limits.
|
|
106
|
+
- [Decomposition](references/decompose.md): task schema, routing, waves, retries and integration.
|
|
107
|
+
- [Harnesses](references/harnesses.md): invocation troubleshooting or adding a harness.
|
|
108
|
+
- [Fractal](references/fractal.md): opt-in nested execution, installation, limits,
|
|
109
|
+
recovery, managed run commands, read-only dashboard and portable reports.
|
|
110
|
+
- [Memory](references/memory.md): `.forge/` learning and spend records; `--no-memory` disables
|
|
111
|
+
them. Memory is written to the user's repository but excluded from implementation diffs.
|
|
112
|
+
- [forge-ui](references/ui.md): the opt-in local run viewer; `forge ui open|status|stop`,
|
|
113
|
+
`FORGE_UI=off`, one shared server, privacy.
|
|
114
|
+
- [Dataset](references/dataset.md): every run's inputs and outcomes, kept outside the repo
|
|
115
|
+
for training decision models; `forge dataset status|import|export|outcomes`, `FORGE_DATASET=off`.
|
|
116
|
+
- [Jev](references/jev.md): optional TypeSafe System One judgments for routing, test
|
|
117
|
+
selection and memory curation; off by default. Chosen sites can go to Cloudflare's hosted
|
|
118
|
+
Clef instead (`forge jev setup --provider cloudflare`, `forge jev sites`, `FORGE_CLEF=off`).
|
|
119
|
+
|
|
120
|
+
The common invocation is `/forge "<goal>" --dwarf <spec> [--qa <spec>]`. Advanced flags and
|
|
121
|
+
commands live with their mode reference. Use [offline tests and evaluation cases](tests/README.md)
|
|
122
|
+
when maintaining this skill.
|
package/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.8
|
package/forge
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -uo pipefail
|
|
3
|
+
# npm runs this file through a symlink in its bin dir, usually a relative one. Follow the
|
|
4
|
+
# links so ROOT is the package and not the bin dir; older macOS has no readlink -f.
|
|
5
|
+
SELF="${BASH_SOURCE[0]}"
|
|
6
|
+
while [ -L "$SELF" ]; do
|
|
7
|
+
LINK="$(readlink "$SELF")"
|
|
8
|
+
case "$LINK" in
|
|
9
|
+
/*) SELF="$LINK" ;;
|
|
10
|
+
*) SELF="$(dirname "$SELF")/$LINK" ;;
|
|
11
|
+
esac
|
|
12
|
+
done
|
|
13
|
+
ROOT="$(cd -P "$(dirname "$SELF")" && pwd)"
|
|
14
|
+
|
|
15
|
+
usage() {
|
|
16
|
+
printf '%s\n' \
|
|
17
|
+
'usage: forge <command> [args]' \
|
|
18
|
+
'' \
|
|
19
|
+
'commands:' \
|
|
20
|
+
' install link forge into each agent harness on this machine; --dry-run previews' \
|
|
21
|
+
' fractal opt-in Fractal execution: install, doctor, runs, status, tree, logs, open, report, ...' \
|
|
22
|
+
' jev optional Jev advice: setup, status, doctor, enable, disable, backtest' \
|
|
23
|
+
' dataset every run'"'"'s inputs and outcomes: status, dump, import, export, outcomes, ...' \
|
|
24
|
+
' ui forge-ui, the run viewer: open [DIR], status, stop' \
|
|
25
|
+
' update fast-forward this checkout and refresh every harness installation' \
|
|
26
|
+
' version the installed version, and whether a newer release is out' \
|
|
27
|
+
'' \
|
|
28
|
+
'Run `forge <command> --help` for its options.' \
|
|
29
|
+
'Runs start from your agent harness (/forge "<goal>" --dwarf <model>); see README.md.'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
case "${1:-}" in
|
|
33
|
+
install)
|
|
34
|
+
shift
|
|
35
|
+
exec /bin/bash "$ROOT/scripts/forge-install.sh" "$@"
|
|
36
|
+
;;
|
|
37
|
+
fractal)
|
|
38
|
+
shift
|
|
39
|
+
exec python3 "$ROOT/scripts/forge-fractal.py" "$@"
|
|
40
|
+
;;
|
|
41
|
+
jev)
|
|
42
|
+
shift
|
|
43
|
+
exec python3 "$ROOT/scripts/forge-jev.py" "$@"
|
|
44
|
+
;;
|
|
45
|
+
dataset)
|
|
46
|
+
shift
|
|
47
|
+
exec python3 "$ROOT/scripts/forge-dataset.py" "$@"
|
|
48
|
+
;;
|
|
49
|
+
ui)
|
|
50
|
+
shift
|
|
51
|
+
exec python3 "$ROOT/scripts/forge-ui.py" "$@"
|
|
52
|
+
;;
|
|
53
|
+
update)
|
|
54
|
+
shift
|
|
55
|
+
exec /bin/bash "$ROOT/scripts/forge-update.sh" "$@"
|
|
56
|
+
;;
|
|
57
|
+
version)
|
|
58
|
+
shift
|
|
59
|
+
exec python3 "$ROOT/scripts/forge-version.py" "$@"
|
|
60
|
+
;;
|
|
61
|
+
-h|--help|help)
|
|
62
|
+
usage
|
|
63
|
+
exit 0
|
|
64
|
+
;;
|
|
65
|
+
'')
|
|
66
|
+
usage >&2
|
|
67
|
+
exit 2
|
|
68
|
+
;;
|
|
69
|
+
*)
|
|
70
|
+
printf 'forge: unknown command: %s\n\n' "$1" >&2
|
|
71
|
+
usage >&2
|
|
72
|
+
exit 2
|
|
73
|
+
;;
|
|
74
|
+
esac
|
package/package.json
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@giamme/forge",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "One model builds it. A different model reviews what it actually built.",
|
|
5
|
+
"keywords": ["claude-code", "codex", "opencode", "agent-skill", "code-review", "multi-model"],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Giamme",
|
|
8
|
+
"repository": { "type": "git", "url": "git+https://github.com/Giamme/forge.git" },
|
|
9
|
+
"bin": { "forge": "forge" },
|
|
10
|
+
"os": ["darwin", "linux"],
|
|
11
|
+
"files": [
|
|
12
|
+
"forge",
|
|
13
|
+
"SKILL.md",
|
|
14
|
+
"VERSION",
|
|
15
|
+
"CHANGELOG.md",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE",
|
|
18
|
+
"registry.tsv",
|
|
19
|
+
"references/",
|
|
20
|
+
"scripts/",
|
|
21
|
+
"ui/forge_ui/",
|
|
22
|
+
"ui/README.md",
|
|
23
|
+
"ui/THIRD_PARTY_NOTICES.md",
|
|
24
|
+
"ui/docs/api.md",
|
|
25
|
+
"!**/__pycache__"
|
|
26
|
+
],
|
|
27
|
+
"publishConfig": { "access": "public" }
|
|
28
|
+
}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
# Run dataset
|
|
2
|
+
|
|
3
|
+
Every forge run records its inputs and outcomes in one global store outside every repo,
|
|
4
|
+
so a decision model (Jev, Laya or any other) can later be trained or calibrated on what
|
|
5
|
+
forge actually did. Run and plan dirs hold nearly all of this, but they live in `/tmp`
|
|
6
|
+
and scratchpads and get deleted. `.forge/ledger.tsv` survives, but it keeps only spec
|
|
7
|
+
strings and verdicts. It has no inputs, no resolved models, no attempt numbers and no
|
|
8
|
+
tokens.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
${FORGE_DATA_HOME:-${XDG_DATA_HOME:-~/.local/share}/forge}/dataset/
|
|
12
|
+
dataset.sqlite events (rid-keyed, append-only) and repos
|
|
13
|
+
blobs/<aa>/<sha>.gz prompts, diffs, messages, logs: capped, gzipped, deduplicated
|
|
14
|
+
errors.log capture failures
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Capture is on by default and costs a few milliseconds per execution. `FORGE_DATASET=off`
|
|
18
|
+
turns it off for one invocation.
|
|
19
|
+
|
|
20
|
+
## Raw events, not training examples
|
|
21
|
+
|
|
22
|
+
The store holds **what happened, when it happened**: the state each decision saw and the
|
|
23
|
+
outcomes that followed. It never holds (state, question, label) rows. Those are derived
|
|
24
|
+
per decision by an exporter, so a question nobody has asked yet can still be answered
|
|
25
|
+
from old runs without re-running anything. Labels come from folding a run's events in
|
|
26
|
+
time order: an attempt that PASSed, then a merge that CONFLICTed, then a human `accept`.
|
|
27
|
+
|
|
28
|
+
| kind | one per | what it holds |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `start` | execution | a receipt written by `begin()`. A start with no matching end is an execution that was killed or is still running |
|
|
31
|
+
| `dispatch` | model call | role, alias, harness, **resolved** model, effort after clamping, timeout and its source, delivery (custom or native review), phase timings, exit, timeout, infra class, tokens, parsed verdict and findings, `FORGE_LEARNING` lines. Blobs: the delivered prompt and the final message |
|
|
32
|
+
| `attempt` | task attempt or solo run | status, attempt number (with refund and resume flags), trigger (`initial`, `auto`, `human`), dwarf and qa spec, declared vs changed files, numstat, drift, guard notes, gate line, patch key, the files this execution wrote and the ones it only carried. Blobs: the diff, retry findings, memory slices, capsule, Jev task files |
|
|
33
|
+
| `verification` / `verify_run` | verify, and each command execution | command and its source (flag, `.forge/verify`, Jev), status, flaky, Jev triage. One `verify_run` per execution, each with its own log |
|
|
34
|
+
| `plan` | `plan` | goal, original request, decompose level, exploratory routing decisions (`tasks[id].route`, with their odds), author (orchestrator or planner), per-task declared vs executed difficulty and who set it, pools, waves, Jev routing and coupling. Blobs: both task tables, prompts, approaches, excerpts of the declared files at plan time, the file inventory, `memory.md` |
|
|
35
|
+
| `run_end` | `run` | results per task, the accepted integration commit, `memory.md` |
|
|
36
|
+
| `invocation` | user-facing `forge-parallel.sh` subcommand | argv, exit, duration, plus final review, accept, integrate and split/combine payloads |
|
|
37
|
+
| `event` | point event | `merge` (MERGED, CONFLICT with the files, INVALIDATED and why), `integrate_advanced`, `integrate_conflict`, `combine_conflict`, `sched_terminal`, `subset_run` (every outcome), `memory_record`, `memory_prune` |
|
|
38
|
+
| `event` `escalation` | `retry --dwarf` | the model a retry escalated from and to, recorded at the rewrite, before the retried attempt begins |
|
|
39
|
+
| `event` `shadow_review` | shadow review | how an opt-in second review ended (`done`, `invalid`, `overtime`, `orphaned`, ...), with the reviewed commit and both specs. Its dispatch is recorded with role `qa_shadow` |
|
|
40
|
+
| `jev` | Jev request | site, answers, usage, latency, mode. Blob: the **full request** (state and questions). Its original sha is `jev.jsonl`'s `key` |
|
|
41
|
+
| `fractal_step` / `fractal_node` | Fractal step, node state | decomposition decision, iteration, resolved model, cost, tokens, candidate diff |
|
|
42
|
+
| `ledger` | ledger row | imported `.forge/ledger.tsv` rows |
|
|
43
|
+
| `outcome` | integrated task, per horizon | written by `forge dataset outcomes`, never by a run: how many of the lines a task added survive N days after `integrate`, and what reverted it |
|
|
44
|
+
|
|
45
|
+
Each blob reference carries `sha` (the stored bytes), `original_sha`, `n` (the original
|
|
46
|
+
size), `kept`, and `cut`. A cut keeps the head and the tail, because a QA prompt ends with
|
|
47
|
+
the diff and a log ends with the failure. Caps: prompt 1 MiB, diff 2 MiB, message 256 KiB,
|
|
48
|
+
log 272 KiB. Transcripts (`*.log`) and `.cmd` (which some harnesses use to carry the
|
|
49
|
+
prompt in argv) are never stored. A harness without structured output has its final
|
|
50
|
+
message copied from the whole log, so for those harnesses only the tail is kept, flagged
|
|
51
|
+
`final_source: log_copy`.
|
|
52
|
+
|
|
53
|
+
## How it is captured
|
|
54
|
+
|
|
55
|
+
All capture goes through a handful of hooks. Every one of them is fail-open: errors go
|
|
56
|
+
to `errors.log`, nothing is printed, and nothing changes an exit code.
|
|
57
|
+
|
|
58
|
+
- **`forge-runtime.py begin()/finish()`.** Every dispatch, task attempt, solo run,
|
|
59
|
+
verification and parallel run already passes through these. `finish()` captures from a
|
|
60
|
+
`finally:` block, so an extraction error cannot lose the record. This is the only
|
|
61
|
+
hook that sees every exit path: an empty diff, INVALIDATED, a timeout, an infra stop
|
|
62
|
+
or a `die`.
|
|
63
|
+
- **Provenance travels with the execution.** `begin()` writes
|
|
64
|
+
`attempts/<role>-<uuid>/dataset.json` with the run id, task, starting attempt counter,
|
|
65
|
+
trigger and a signature (inode, mtime, size) of every task file. `finish()` credits a
|
|
66
|
+
file to this execution only when its signature changed. A dwarf that fails returns
|
|
67
|
+
before `changes.diff` is refreshed, and without this check it would inherit the
|
|
68
|
+
previous attempt's diff and verdict.
|
|
69
|
+
- **Point events** (`forge_dataset_event`) record facts that disappear before any EXIT
|
|
70
|
+
trap could read them: a merge that gets aborted, a combine that rolls back, a user
|
|
71
|
+
branch that moves just before a cleanup that may still fail.
|
|
72
|
+
- **An EXIT trap in `forge-parallel.sh`** records every user-facing subcommand, `die`
|
|
73
|
+
included.
|
|
74
|
+
- **`forge_jev/client.py`** keeps the canonical request bytes of every live Jev call,
|
|
75
|
+
including calls made without a run dir. It skips fixture replays, the setup probe and
|
|
76
|
+
backtests.
|
|
77
|
+
|
|
78
|
+
Run identity is a uuid in `<plan-or-run-dir>/dataset.uid`, created once (`O_EXCL`) by
|
|
79
|
+
`plan` or by the first `begin()`. Split and combine copy attempt dirs unchanged, so a
|
|
80
|
+
copied execution keeps its original identity and collapses to one event by rid.
|
|
81
|
+
|
|
82
|
+
## Which forge produced an event
|
|
83
|
+
|
|
84
|
+
Outcomes depend on the prompts, contracts and registry forge ran with, and the skill is
|
|
85
|
+
often a live dev checkout that changes between releases. So every event carries four
|
|
86
|
+
provenance columns:
|
|
87
|
+
|
|
88
|
+
| column | what it identifies |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `forge_version` | the release in `VERSION` |
|
|
91
|
+
| `registry_sha` | the effective `registry.tsv` (or `FORGE_REGISTRY`) |
|
|
92
|
+
| `code_sha` | the content of every file that shapes a run: `scripts/`, `references/`, `SKILL.md`, `VERSION`, `forge` and the effective registry. Two runs share it only if they ran the same code, uncommitted edits included |
|
|
93
|
+
| `forge_rev` | the skill checkout's `HEAD` (`git rev-parse`, read-only), or null for a copied skill dir |
|
|
94
|
+
|
|
95
|
+
An execution is stamped with what `begin()` saw, because its prompt was built then.
|
|
96
|
+
`finish()` runs in another process; if the code changed in between, the event carries
|
|
97
|
+
`code_changed: true` and can be left out of any per-regime analysis.
|
|
98
|
+
|
|
99
|
+
An imported run was produced by whatever forge ran it, so the importer stamps nothing,
|
|
100
|
+
unless a live `begin()` left its provenance in the attempt dir. Rows imported before
|
|
101
|
+
schema 2 carry the importer's version by mistake, so readers treat `forge_version` and
|
|
102
|
+
`registry_sha` on `src = 'import'` rows without a `code_sha` as unknown. The exporter
|
|
103
|
+
gives those a `forge_rev_estimate`: the last forge commit before the run started, which is a
|
|
104
|
+
guess and is labeled as one. Schema 2 added `code_sha` and `forge_rev`. The first
|
|
105
|
+
capture after an upgrade adds them in one `BEGIN IMMEDIATE` transaction, and an older
|
|
106
|
+
forge still running keeps writing.
|
|
107
|
+
|
|
108
|
+
## Commands
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
./forge dataset status [-v] [--json] # where, how much, and what looks incomplete
|
|
112
|
+
./forge dataset dump [--kind K] [--run R] [--task T] [--since UNIX] # events as JSON lines
|
|
113
|
+
./forge dataset blob <sha> # print one stored blob
|
|
114
|
+
./forge dataset import <dir|archive|legacy-dir>... [--registry] [--fractal] [--ledger REPO] [--dry-run]
|
|
115
|
+
./forge dataset export [--slice S]... [--limit N] [--seed N] [--out DIR] # labeled decision cases
|
|
116
|
+
./forge dataset outcomes [--horizon-days 14] [--repo PATH] [--dry-run] # what integrated work became
|
|
117
|
+
./forge dataset routing [--repo PATH] [--since DAYS] [--json] # pass rate and runtime per tier and model
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`status` runs a different completeness check for each mode, because each mode
|
|
121
|
+
legitimately lacks different things. A solo run has no separate verification, and a
|
|
122
|
+
final review's QA has no task attempt. The checks are:
|
|
123
|
+
|
|
124
|
+
- executions that started but never ended
|
|
125
|
+
- task QA dispatches with no task attempt
|
|
126
|
+
- parallel PASSes with no merge outcome in a finished run
|
|
127
|
+
- parallel runs with no end
|
|
128
|
+
- blob references with no stored blob
|
|
129
|
+
|
|
130
|
+
## Exporting labeled decisions
|
|
131
|
+
|
|
132
|
+
`export` folds the events into cases in the System One wire format (one JSON object per
|
|
133
|
+
line with `id`, `state`, `questions` and `expected`), the format decision-model
|
|
134
|
+
benchmarks and fine-tuning recipes take. Each case is a decision Jev makes in forge,
|
|
135
|
+
with its state built the way `forge_jev` builds it for that site and its label taken
|
|
136
|
+
from what happened afterwards:
|
|
137
|
+
|
|
138
|
+
| slice | question | label |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| `routing` | will the first attempt at this task pass review? (state adds the dwarf and reviewer models) | the final status of the first real attempt (see below) |
|
|
141
|
+
| `routing` | which difficulty tier is this task? | the tier the orchestrator or planner declared. This is agreement, not an outcome |
|
|
142
|
+
| `retry` | will this retry pass, given the review findings it was handed? (state adds the attempt number and the previous review) | the final status of that attempt (see below) |
|
|
143
|
+
| `review` | will the independent reviewer pass this diff? (state names the reviewer's model, effort and harness) | the QA verdict. A diff whose reviews disagreed is dropped |
|
|
144
|
+
| `review` | will most of the lines this diff adds stay in the code, unrewritten and unreverted? | from `outcomes`: at least 80% of the added lines still blamed to the task's commits at the horizon, and no revert. Only the review of the diff that landed gets it |
|
|
145
|
+
| `review` | what is the most severe problem the reviewer will find? (`none`, `P3` to `P0`, the contract's scale) | the worst CONFIRMED finding, only when every CONFIRMED finding carries a severity and none is UNSTATED. A review whose findings cannot be fully read gets no label rather than a wrong `none` |
|
|
146
|
+
| `drift` | is this undeclared file likely to need editing? | whether the passing attempt changed it. Negatives are undeclared files near the task, plus random ones |
|
|
147
|
+
| `citation` | do the places this review cites appear in this diff? | the review paired with its own diff, or with another task's diff from the same repo that shares no file |
|
|
148
|
+
| `memory` | is this recorded fact worth including for this task? | the fact's anchor is a file the task edited (true), or lies in an area it never touched (false). Anything in between is left out |
|
|
149
|
+
|
|
150
|
+
The reviewer is part of the review state because strictness differs by reviewer: the
|
|
151
|
+
same kind of diff passes far more often under one reviewer than another, so a label
|
|
152
|
+
means little without knowing who gave it. Routing and retry states also carry a `size`
|
|
153
|
+
block (`prompt_chars`, `declared_files`, `plan_tasks`, `deps`, `decompose_level`, from
|
|
154
|
+
`forge_jev/features.py`), since task size moves the first-pass rate more than anything
|
|
155
|
+
else in the history.
|
|
156
|
+
|
|
157
|
+
An attempt is labeled by the last execution that carries its number, because a QA-only
|
|
158
|
+
rerun keeps the number. Refunded and infra-stopped executions spent no attempt. PASS is
|
|
159
|
+
true and FAIL is false. TIMEOUT is false only when the implementer's own dispatch ran out
|
|
160
|
+
of time. Everything else says nothing about the implementer and is left out, counted
|
|
161
|
+
under `censored` in `manifest.json`:
|
|
162
|
+
- a reviewer's TIMEOUT or ERROR
|
|
163
|
+
- a harness crash
|
|
164
|
+
- forge's own failures between dispatches
|
|
165
|
+
- UNKNOWN, INVALIDATED, INTERRUPTED
|
|
166
|
+
|
|
167
|
+
A later success is never labeled as the first attempt's.
|
|
168
|
+
|
|
169
|
+
Decisions with no outcome to label them are left out rather than labeled by opinion.
|
|
170
|
+
These are QA effort sizing (recorded until 2026-10-17), the five routing rubrics, failure triage, and coupling, since
|
|
171
|
+
no merge has conflicted yet.
|
|
172
|
+
|
|
173
|
+
Routing cases of tasks routed with `plan --explore` add `route` to their metadata: the
|
|
174
|
+
candidates, the pool's own pick, the choice, its propensity, and `followed`, which says
|
|
175
|
+
whether attempt 1 really ran the chosen spec (an approval-gate edit or `retry --dwarf` can
|
|
176
|
+
replace it). `assignments.jsonl` lists every such decision with its first attempt's outcome
|
|
177
|
+
or censoring reason, including tasks no case was exported for. It is the randomized cohort,
|
|
178
|
+
free of the export's own filters.
|
|
179
|
+
|
|
180
|
+
Review cases whose attempt also had a shadow review (`plan --shadow-qa`) add `shadow` (its
|
|
181
|
+
verdict, reviewer and worst finding) and `consensus` to their metadata. Only a shadow that
|
|
182
|
+
finished on an untouched snapshot and reviewed the same commit counts. The primary
|
|
183
|
+
labels never change, because `qa_shadow` dispatches are not reviews of record.
|
|
184
|
+
`./forge dataset status` prints the agreement rate, overall and per model pair.
|
|
185
|
+
|
|
186
|
+
`meta.jsonl` records each case's slice, run, repo and label source. It also holds hosted
|
|
187
|
+
Jev's own answers where forge recorded them, as baselines that are never part of a case.
|
|
188
|
+
Routing and retry cases add:
|
|
189
|
+
- `decision_provenance` (the plan's) and `outcome_provenance` (the attempt's)
|
|
190
|
+
- `code_changed`
|
|
191
|
+
- the plan `options`
|
|
192
|
+
- `started`
|
|
193
|
+
|
|
194
|
+
Routing cases also add how the task went:
|
|
195
|
+
- `attempts_observed`
|
|
196
|
+
- `raw_verdict`
|
|
197
|
+
- `gate_pass`, a reviewer FAIL the severity gate accepted
|
|
198
|
+
- `first_raw_pass_attempt`
|
|
199
|
+
- `human_accept`
|
|
200
|
+
- `stop_reason`: `passed`, `accepted`, `noretry`, `interrupted` or `no_pass_observed`
|
|
201
|
+
|
|
202
|
+
A final FAIL is not proof a task cannot pass: the retry budget ended the observation.
|
|
203
|
+
The output defaults to `<data>/exports/forge-decisions/` (`0700`, files `0600`). It holds
|
|
204
|
+
prompts, diffs and reviews from your repos, so keep it out of public repos and pass it
|
|
205
|
+
only to local models. Builds are deterministic for a given store and `--seed`.
|
|
206
|
+
|
|
207
|
+
## Routing
|
|
208
|
+
|
|
209
|
+
`forge dataset routing` answers "which model should this tier use?" from the store, in two
|
|
210
|
+
tables kept apart because they answer different questions.
|
|
211
|
+
|
|
212
|
+
**Observational.** Every task's first attempt, by declared tier and the model and effort that
|
|
213
|
+
ran it (resolved, so `sol` and `gpt-6.1-sol:medium:codex` share a row):
|
|
214
|
+
- first-pass rate with a Wilson 95% interval
|
|
215
|
+
- the share that passed review at some attempt, or that a human accepted
|
|
216
|
+
- unfinished tasks
|
|
217
|
+
- attempts per task
|
|
218
|
+
- the implementer's median runtime
|
|
219
|
+
|
|
220
|
+
Routing chose who ran what, so a model sent the hard tasks looks worse here than it is.
|
|
221
|
+
Fractal runs are left out, since their dispatches have identities of their own.
|
|
222
|
+
|
|
223
|
+
**Randomized.** The `plan --explore` draws, one row per (tier, pool pick, neighbour) pair.
|
|
224
|
+
Round-robin pools make the pair differ between rows, and a model has no chance at all
|
|
225
|
+
outside its own pairs, so pairs are never pooled. For each arm:
|
|
226
|
+
- assigned tasks
|
|
227
|
+
- first-pass as a Hajek (self-normalized inverse-propensity) mean
|
|
228
|
+
- Kish's effective n
|
|
229
|
+
- attrition: tasks not run as assigned, and tasks with no outcome
|
|
230
|
+
- runtime
|
|
231
|
+
|
|
232
|
+
Every task stays in the arm it was *assigned* (intent to treat), whatever the approval gate
|
|
233
|
+
or a retry did afterwards. A task is bound to the last draw recorded before its first attempt
|
|
234
|
+
started, so a later re-plan never relabels it. Draws from before the two-candidate rule
|
|
235
|
+
(a pick among every spec of the plan) have no pair and are counted, not compared.
|
|
236
|
+
|
|
237
|
+
**The decision rule** is fixed in advance and only advises. A pair is judged once, at the
|
|
238
|
+
first of 30, 60 or 120 neighbour assignments it reaches, on exactly the assignments up to
|
|
239
|
+
that point. The interval is a run-cluster bootstrap, shown only with at least 10 neighbour
|
|
240
|
+
assignments across 3 runs.
|
|
241
|
+
- For a **low** pair the neighbour is the stronger model: switching is advised only when the
|
|
242
|
+
interval is above 0.
|
|
243
|
+
- For **medium** and **high** pairs it is the cheaper one: it is called non-inferior when the
|
|
244
|
+
interval's lower end is above -0.10 and its runtime is lower.
|
|
245
|
+
|
|
246
|
+
At the default `--explore 0.2` a row changes model 10% of the time, so a pair needs weeks of
|
|
247
|
+
normal use to reach its first window.
|
|
248
|
+
|
|
249
|
+
## Outcomes after merge
|
|
250
|
+
|
|
251
|
+
Every other label comes from a reviewer. `forge dataset outcomes` adds one that does not,
|
|
252
|
+
read from the repo's history after the fact. `integrate` merges the run branch with
|
|
253
|
+
`--no-ff` and fast-forwards your branch to that merge, never squashing, so each task's
|
|
254
|
+
attempt commits land as they are and `git blame` still attributes a task's lines to them.
|
|
255
|
+
For every integration, and every task it brought in, the harvester records:
|
|
256
|
+
|
|
257
|
+
- **Survival:** of the text lines the task added (`base_ref..reviewed_commit`), how many
|
|
258
|
+
are still attributed to the task's commits at the horizon, per file. A deleted file
|
|
259
|
+
counts as none surviving. Binary files are skipped, and a task that only deleted lines
|
|
260
|
+
is `no_additions`.
|
|
261
|
+
- **Reverts:** later commits whose message says `This reverts commit <sha>` for one of the
|
|
262
|
+
task's commits, its merge or the integration.
|
|
263
|
+
- **The horizon:** the last commit on your branch's first-parent chain, after the
|
|
264
|
+
integration, dated before `integrate` + N days. The branch is resolved once, and the
|
|
265
|
+
chain is walked by position, so commit dates out of order cannot skip a commit.
|
|
266
|
+
|
|
267
|
+
Two cases leave a task without a survival count:
|
|
268
|
+
- **Pending:** the horizon has not been reached and no later commit has passed it yet.
|
|
269
|
+
Nothing is written, and the next harvest tries again.
|
|
270
|
+
- **Lost:** a rebase, squash or reset took the integration off the branch. This means
|
|
271
|
+
unobservable, not failed.
|
|
272
|
+
|
|
273
|
+
The rid names the integration, the reviewed commit and the horizon, so harvesting again
|
|
274
|
+
adds nothing, and two horizons are two outcomes. Survival describes the diff that landed,
|
|
275
|
+
with every retry in it, not the first model the task was routed to. That is why the
|
|
276
|
+
exporter attaches it to that diff's review.
|
|
277
|
+
|
|
278
|
+
Each verification event also records the commit it verified (`verification.commit`, named
|
|
279
|
+
before any early return), so a FAIL or UNVERIFIED result can be joined to its code too.
|
|
280
|
+
|
|
281
|
+
## Importing old runs
|
|
282
|
+
|
|
283
|
+
`import` reads run dirs that predate live capture through the same readers. An execution
|
|
284
|
+
seen both live and imported collapses to one event. Old dirs have no begin-time snapshot,
|
|
285
|
+
so the importer will not guess which execution wrote a mutable file:
|
|
286
|
+
|
|
287
|
+
- The **newest** task attempt gets the task dir's current files, flagged `legacy`.
|
|
288
|
+
- **Earlier** attempts get only what is immutable:
|
|
289
|
+
- their own dispatch dirs
|
|
290
|
+
- the diff QA was shown (the last `` ```diff `` block of the QA prompt)
|
|
291
|
+
- the status that `attempts.tsv` logged, or failing that, the QA verdict, with
|
|
292
|
+
`status_source` saying which
|
|
293
|
+
- Unfinished executions (still running, or killed) are skipped. The first write of a rid
|
|
294
|
+
wins, so importing one now would block the real outcome that live capture records when
|
|
295
|
+
it ends. Re-import the dir afterwards to fill anything live capture missed.
|
|
296
|
+
- Repos under temp dirs (test runs) are skipped unless `--include-temp` is given.
|
|
297
|
+
- Archives are extracted to a temp dir and mapped back to their original path. The legacy
|
|
298
|
+
run id hashes that original path, so the archive and the original dir agree on it.
|
|
299
|
+
|
|
300
|
+
`~/.local/share/forge/legacy/` holds archives of run dirs taken before live capture, with a
|
|
301
|
+
`MANIFEST.tsv`. Passing that dir to `import` reads every archive, plus the ledger copies
|
|
302
|
+
listed in `ledgers/REPOS.tsv`.
|
|
303
|
+
|
|
304
|
+
## Invariants
|
|
305
|
+
|
|
306
|
+
- **Never inside the repo.** Capture refuses, silently and before any write, when the store
|
|
307
|
+
resolves inside the run's repo or a forge worktree. `integrate` refuses a dirty tree.
|
|
308
|
+
- **Never read by a prompt builder.** Memory inject, the capsule and Ripwire must not read
|
|
309
|
+
the store. A reviewer that could see earlier runs' verdicts would not be independent.
|
|
310
|
+
`tests/test_dataset.py` enforces that outside its own package, the dataset is only
|
|
311
|
+
imported for capture.
|
|
312
|
+
- **Read-only in your repos.** Capture and the harvester run only object-store git queries
|
|
313
|
+
in a repo: `rev-parse`, `rev-list`, `log`, `show`, `ls-tree`, `cat-file`, `diff` between
|
|
314
|
+
commits and `blame` at a commit. All run with `GIT_OPTIONAL_LOCKS=0`. None takes the
|
|
315
|
+
working tree or refreshes the index. `outcomes` reads the store through a read-only
|
|
316
|
+
connection and writes only what it found.
|
|
317
|
+
- **Private.** Prompts, diffs and logs can contain secrets. The dir is `0700` and its files
|
|
318
|
+
`0600`. Do not sync it. Redaction belongs to whatever exports a training set.
|
|
319
|
+
|
|
320
|
+
## Not captured
|
|
321
|
+
|
|
322
|
+
- **Token counts for openclaude, opencode and antigravity.** Those harnesses expose none.
|
|
323
|
+
They are recorded as null.
|
|
324
|
+
- **Dispatches refused before `begin()`** (an unknown alias, bad flags). No model ran.
|
|
325
|
+
- **The orchestrator's own reasoning.** Only its outputs are recorded: the task table,
|
|
326
|
+
`request.md` and the approval edits visible between the planner's message and the
|
|
327
|
+
declared table.
|
|
328
|
+
- **Counterfactuals.** Each task runs on one model, so nothing here says whether another
|
|
329
|
+
model would have done better. That needs deliberate head-to-head runs.
|