@giamme/forge 0.11.1 → 0.12.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 +34 -0
- package/SKILL.md +4 -2
- package/VERSION +1 -1
- package/docs/artifacts.md +44 -11
- package/docs/commands.md +45 -7
- package/docs/decomposed-runs.md +43 -2
- package/docs/forge-ui.md +27 -6
- package/docs/reviews.md +31 -6
- package/package.json +1 -1
- package/references/dataset.md +3 -1
- package/references/decompose.md +159 -17
- package/references/harnesses.md +13 -1
- package/references/ui.md +14 -4
- package/scripts/forge-control.py +268 -25
- package/scripts/forge-dispatch.sh +80 -3
- package/scripts/forge-guard.py +156 -15
- package/scripts/forge-lib-plans.sh +9 -3
- package/scripts/forge-lib-review.sh +22 -3
- package/scripts/forge-lib-task.sh +51 -4
- package/scripts/forge-lib-verify.sh +137 -6
- package/scripts/forge-parallel-options.sh +59 -0
- package/scripts/forge-parallel.sh +212 -28
- package/scripts/forge-ripwire.py +1 -1
- package/scripts/forge-route.py +157 -5
- package/scripts/forge-schedule.py +687 -50
- package/scripts/forge-verify.py +878 -0
- package/scripts/forge_dataset/forecast.py +29 -4
- package/scripts/forge_dataset/harvest.py +10 -4
- package/scripts/forge_verify_reports.py +225 -0
- package/ui/README.md +18 -3
- package/ui/docs/api.md +126 -17
- package/ui/forge_ui/control.py +12 -2
- package/ui/forge_ui/export.py +20 -7
- package/ui/forge_ui/reader.py +307 -11
- package/ui/forge_ui/server.py +16 -0
- package/ui/forge_ui/static/app.js +2 -1
- package/ui/forge_ui/static/controls.js +217 -33
- package/ui/forge_ui/static/gantt.js +14 -9
- package/ui/forge_ui/static/index.html +1 -0
- package/ui/forge_ui/static/panel.js +2 -1
- package/ui/forge_ui/static/runmodel.js +92 -11
- package/ui/forge_ui/static/scene3d.js +9 -5
- package/ui/forge_ui/static/style.css +60 -0
- package/ui/forge_ui/static/verifyview.js +324 -0
package/references/decompose.md
CHANGED
|
@@ -471,6 +471,15 @@ turns it off):
|
|
|
471
471
|
- **Stop:** when nothing is above (the model is in the top tier, or in no tier pool at
|
|
472
472
|
all), the task stops with `tasks/<id>/split.suggested`: split it into smaller tasks, or
|
|
473
473
|
name a model. `run --retry-failed` does not retry it, and a plain `retry` refuses (exit 2).
|
|
474
|
+
- **Effort step** (`--escalate-effort` on `run` or `retry`, kept in the plan as `escalate_effort`;
|
|
475
|
+
`--no-escalate-effort` removes it; off by default): when no higher tier has another model, the
|
|
476
|
+
same alias and harness is tried once more at the next effort its pairing accepts
|
|
477
|
+
(`forge-dispatch.sh efforts --spec <spec>` lists them, weakest first), counted from the effort
|
|
478
|
+
the last dispatch really ran after any clamp; a spec that names no effort counts as `medium`.
|
|
479
|
+
The streak then counts per effort, so the new effort starts from zero. At the pairing's highest
|
|
480
|
+
effort the task still stops, and `split.suggested` says that effort was tried too. Turning the
|
|
481
|
+
step on (flag or `forge control set escalate-effort on`) clears the stop markers, so tasks the
|
|
482
|
+
policy already stopped are decided again at their next retry.
|
|
474
483
|
- **Overrides:** an explicit `retry --dwarf <spec>` is the human's choice and skips the policy, even
|
|
475
484
|
with the same model. The dwarf column itself cannot tell a pin from a pool pick, so it does
|
|
476
485
|
not; `--escalate-after 0` does.
|
|
@@ -488,8 +497,11 @@ changed spec passed, mostly effort bumps); the attempts this policy makes are wh
|
|
|
488
497
|
|
|
489
498
|
**Live controls.** `forge control show|set|pin|unpin <plan>` changes a run while it works:
|
|
490
499
|
`qa-threshold` (read once per attempt, so an attempt keeps the bar it started with; per task, `none`
|
|
491
|
-
exempts it and `inherit` drops the override), `timeout`, `escalate-after`, `
|
|
492
|
-
|
|
500
|
+
exempts it and `inherit` drops the override), `timeout`, `escalate-after`, `escalate-effort`
|
|
501
|
+
(`on|off`), `verify-retries`, `infra-backoff` (a shape as for `--infra-backoff`; `none` drops it,
|
|
502
|
+
read at the next infrastructure wait), and, only while a scheduler is live, `retry-budget` (plan
|
|
503
|
+
or `--task`), `infra-retries` and `max-parallel` (1 to 64, at the next dispatch decision; a lower
|
|
504
|
+
limit lets running tasks finish and never stops one). The budgets
|
|
493
505
|
keep the **per invocation** rule: the flags of `run` are not remembered, and a live scheduler only
|
|
494
506
|
mirrors them into `retry_budget`, `infra_budget` and `tasks/<id>/retry_budget` (re-read at every
|
|
495
507
|
decision, removed when it stops; `tasks/<id>/retries.used` stays), so a change dies with the
|
|
@@ -501,18 +513,55 @@ run. `pin <task> <spec>` sets the model the task's next full retry uses, once (c
|
|
|
501
513
|
the pin stays and nothing is retried. A QA-only resume leaves it for the next full retry;
|
|
502
514
|
Fractal plans never apply pins; a MERGED task refuses one.
|
|
503
515
|
The last column of `escalations.tsv` says who decided: `policy`, `retry` (an explicit
|
|
504
|
-
`--dwarf`) or `
|
|
505
|
-
`at`, `actor` `cli|ui`, `action`, `task`, `key`,
|
|
506
|
-
`control` event. Exit 2 invalid input, 3 refused (not
|
|
507
|
-
lock busy over 5 s). Report them; never set one yourself
|
|
516
|
+
`--dwarf`), `pin` or `fallback` (`--infra-fallback`, below); four-column rows read as `policy`.
|
|
517
|
+
Every change goes to `control.log` (JSON lines: `at`, `actor` `cli|ui`, `action`, `task`, `key`,
|
|
518
|
+
`value`, `previous`) and to the dataset as a `control` event. Exit 2 invalid input, 3 refused (not
|
|
519
|
+
live, MERGED, Fractal, failing doctor, lock busy over 5 s). Report them; never set one yourself
|
|
520
|
+
unless asked.
|
|
521
|
+
|
|
522
|
+
Five more commands steer a live scheduler (exit 3 when none is live):
|
|
523
|
+
|
|
524
|
+
- `drain <plan>` starts nothing new: running tasks finish, the scheduler waits (it prints
|
|
525
|
+
`drained — N task(s) waiting` once) and infrastructure waits keep counting down. `resume <plan>`
|
|
526
|
+
ends the drain. This is the supported way to pause a run; nothing has to be signalled. A drain
|
|
527
|
+
holds only tasks still to start: when none is left (or waiting on infrastructure), the run
|
|
528
|
+
ends as it would without the drain, verification included.
|
|
529
|
+
- `stop <plan>` starts nothing new and ends the run once the running tasks are done: a waiting
|
|
530
|
+
infrastructure pause ends too, unstarted tasks stay `PENDING`, verification is skipped and `run`
|
|
531
|
+
exits 130. When every task has merged by then, nothing was cut short: the run ends as usual,
|
|
532
|
+
verifies and exits 0. `stop --now` interrupts the running tasks
|
|
533
|
+
as SIGTERM would.
|
|
534
|
+
- `retry <plan> <task> [--dwarf <spec>]` and `add <plan> <task>` only queue a request, one JSON
|
|
535
|
+
file in `control.requests/`. At its next pass the scheduler applies or refuses it and appends
|
|
536
|
+
an outcome line to `control.log` with the same `request` id (`actor` `scheduler`, `outcome`
|
|
537
|
+
`applied|refused`, `reason`). `retry` takes a `FAIL`, `UNKNOWN`, `TIMEOUT`, `ERROR`,
|
|
538
|
+
`BLOCKED` or `INTERRUPTED` task that is neither running nor waiting, prepares it exactly as
|
|
539
|
+
`forge-parallel.sh retry` does (a policy stop refuses it unless `--dwarf` names a model), and
|
|
540
|
+
spends no automatic retry budget; an `INFRA` task is the
|
|
541
|
+
scheduler's own to resume. `add` takes a row the human appended to `tasks.tsv` (with its
|
|
542
|
+
`tasks/<id>/prompt.md`) whose dependencies this run already knows, and refreshes `waves.tsv`.
|
|
543
|
+
A request never outlives the scheduler that was live when it was queued; one left behind is
|
|
544
|
+
refused, and every request is refused once the run is stopping.
|
|
508
545
|
|
|
509
546
|
**Ordinary execution resume:** run `run` again. Tasks already `MERGED` are skipped. A saved PASS is fingerprint-checked and merged without
|
|
510
547
|
redispatch. PENDING, `INFRA` (paused by an infrastructure failure) and newly unblocked tasks run
|
|
511
548
|
when eligible. Failed or interrupted tasks
|
|
512
549
|
require an explicit `retry` (or `--retry-failed N`); `run` never silently pays for them again. Worktrees and pinned
|
|
513
550
|
baselines are retained. A per-plan advisory lock excludes concurrent run/retry/integrate
|
|
514
|
-
operations.
|
|
515
|
-
|
|
551
|
+
operations.
|
|
552
|
+
|
|
553
|
+
**Interrupts.** A SIGINT or SIGTERM to `run` (or to its scheduler), and `forge control stop
|
|
554
|
+
--now`, first reap the tasks that already ended (a PASS still merges), then send TERM to each
|
|
555
|
+
running task's process group, wait up to `FORGE_INTERRUPT_GRACE` seconds (default 10) for the
|
|
556
|
+
group to empty and KILL what is left. Only those live tasks become `INTERRUPTED`; their worktree
|
|
557
|
+
keeps the partial work. Each guarded dispatch records its harness in `tasks/<id>/<role>.harness`
|
|
558
|
+
(pid and start time), and `forge-guard.py stop` ends a harness that outlived its dispatch, at
|
|
559
|
+
the interrupt and again at the next scheduler start (a scheduler killed outright leaves tasks
|
|
560
|
+
`RUNNING`; the next run stops their harnesses and marks them `INTERRUPTED`). An interrupted
|
|
561
|
+
`run` skips verification and its rerun, prints `forge-parallel.sh retry <plan> <id>` for each
|
|
562
|
+
interrupted task, releases the plan lock and exits **130**. A signal that arrives during
|
|
563
|
+
verification stops the verify command's whole process tree (TERM, then KILL after a few
|
|
564
|
+
seconds) and records `verification.status` `INTERRUPTED`; that verification is not rerun.
|
|
516
565
|
|
|
517
566
|
**Fractal resume:** discover the managed ID with `<skill_dir>/forge fractal runs --repo
|
|
518
567
|
"$REPO" --json`, then use `<skill_dir>/forge fractal resume RUN_ID`. Run-level resume
|
|
@@ -527,17 +576,52 @@ Pause, stop and inspection preserve both the work and diagnostics.
|
|
|
527
576
|
Quota or usage limits, auth problems, rate limits, network errors and empty answers say nothing
|
|
528
577
|
about the work. `forge-dispatch.sh` classifies them from the dispatch log (strong phrases and
|
|
529
578
|
structured `is_error`/`turn.failed` results only; a reply that otherwise succeeded is never
|
|
530
|
-
reclassified) and exits **8**, writing `<role>.infra` (`class=`, `retry_after=`, `detail
|
|
531
|
-
`do_task` then ends the task as **`INFRA
|
|
579
|
+
reclassified) and exits **8**, writing `<role>.infra` (`class=`, `retry_after=`, `detail=`,
|
|
580
|
+
`harness=`, `model=`). `do_task` then ends the task as **`INFRA`**, copying that file to
|
|
581
|
+
`tasks/<id>/infra.txt` with `stage=dwarf|qa`:
|
|
532
582
|
|
|
533
583
|
- a **dwarf-stage** stop refunds the attempt counter;
|
|
534
584
|
- a **QA-stage** stop keeps the attempt (the dwarf's work is real and committed) and writes the
|
|
535
|
-
`resume=qa` marker, so the next entry re-reviews without running the dwarf
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
585
|
+
`resume=qa` marker, so the next entry re-reviews without running the dwarf.
|
|
586
|
+
|
|
587
|
+
The scheduler pauses only what the stop says something about. Its **scope** comes from the class:
|
|
588
|
+
|
|
589
|
+
| Class | Scope paused | Other tasks |
|
|
590
|
+
|---|---|---|
|
|
591
|
+
| `rate_limit` | that model on that harness (`model:<harness>/<model>`) | keep running, on any other model |
|
|
592
|
+
| `quota`, `auth` | that harness's account (`harness:<harness>`) | keep running on other harnesses |
|
|
593
|
+
| anything else (network, empty output, ...) | everything (`all`): running tasks drain, nothing new starts | wait with it |
|
|
594
|
+
|
|
595
|
+
A pending task whose next dispatch (its implementer and reviewer, or the reviewer alone before a
|
|
596
|
+
QA-only resume) needs a paused pair waits; the rest of the run continues. Unstarted tasks stay
|
|
597
|
+
`PENDING`, never `BLOCKED`. Without `--infra-retries`, `run` ends once nothing else can run, prints
|
|
598
|
+
what to fix and exits `8`; verification is skipped and running the same command again resumes.
|
|
599
|
+
`run --infra-retries M` waits out each scope instead, up to `M` waits **per scope** (a stop in a
|
|
600
|
+
scope already paused joins its wait and is not counted again), then resumes its tasks in the same
|
|
601
|
+
run with no attempt spent. A scope whose waits are used up stays paused while other tasks finish.
|
|
602
|
+
|
|
603
|
+
Each wait is the provider's retry-after when the log carried one (capped at 6 h), otherwise the
|
|
604
|
+
backoff shape for that wait number. `--infra-backoff <shape>` on `run` (kept in the plan as
|
|
605
|
+
`infra_backoff`, read at every wait, so `forge control set infra-backoff` applies to the next one)
|
|
606
|
+
takes `exp:<base>[,<cap>]` (base doubling, capped at `<cap>`, default the larger of the base and
|
|
607
|
+
30 min), `linear:<start>,<step>[,<cap>]`, or `list:<a>,<b>,...` (a bare `<a>,<b>,...` is a list;
|
|
608
|
+
the last value repeats), all in positive seconds. The default is `exp:60`; `FORGE_INFRA_BACKOFF`
|
|
609
|
+
changes that base. The wait message names the source, for example `waiting 120s before resuming
|
|
610
|
+
(backoff exp:60, wait 2 of 3)`. While anything is paused, `infra.paused` (JSON `{"scopes": [...]}`
|
|
611
|
+
with `scope`, `class`, `harness`, `model`, `tasks`, `cycle`, `until`, `exhausted`) says what waits
|
|
612
|
+
and until when; `forge control show` reports it as `infra_paused`, and it is removed when nothing
|
|
613
|
+
is paused.
|
|
614
|
+
|
|
615
|
+
`--infra-fallback` on `run` (kept as `infra_fallback`; `--no-infra-fallback` turns it off, the
|
|
616
|
+
default) moves a **dwarf-stage `rate_limit`** stop to the next member of the task's own tier pool,
|
|
617
|
+
in pool order, that runs another model on a pair nobody paused. No attempt is spent; the move is
|
|
618
|
+
recorded in `escalations.tsv` with source `fallback` and in `tasks.tsv`, and the task is
|
|
619
|
+
dispatched again at once. A pinned task, a Fractal plan, a QA-stage stop and a pool with no
|
|
620
|
+
healthy member keep the ordinary pause.
|
|
621
|
+
|
|
622
|
+
A planned pause (a provider maintenance window, a quota reset) is `forge control drain`, not a
|
|
623
|
+
signal: running tasks finish, nothing new starts, and `forge control resume` continues the same
|
|
624
|
+
run.
|
|
541
625
|
|
|
542
626
|
A dwarf that exits 0 with an empty final message *and* an empty diff is the same class
|
|
543
627
|
(`class=empty`): it never really ran. Under Fractal a dwarf-side stop still ends as Fractal's own
|
|
@@ -647,7 +731,9 @@ The user's own branch and working tree are untouched for the whole run.
|
|
|
647
731
|
| task status `TIMEOUT` | that role exceeded the dispatch timeout and was killed. It has usually left a partial edit in the worktree; `retry` continues from it |
|
|
648
732
|
| task status `FAIL` with "produced no changes" | the dwarf ended without editing anything — usually an ambiguous prompt it could not resolve headlessly |
|
|
649
733
|
| task status `UNKNOWN` | QA never emitted a verdict line; read `tasks/<id>/qa.last`. `retry` re-runs QA only, on the unchanged work |
|
|
650
|
-
| task status `INFRA`, `run` exits `8` | quota/auth/rate limit/network/empty output stopped a dispatch; no attempt spent. See `tasks/<id>/infra.txt`, fix the cause, run again (or `--infra-retries M`) |
|
|
734
|
+
| task status `INFRA`, `run` exits `8` | quota/auth/rate limit/network/empty output stopped a dispatch; no attempt spent. See `tasks/<id>/infra.txt`, fix the cause, run again (or `--infra-retries M`, `--infra-fallback`) |
|
|
735
|
+
| task status `INTERRUPTED`, `run` exits `130` | the run was signalled or stopped with `forge control stop --now`; verification was skipped. The summary prints `forge-parallel.sh retry <plan> <id>` for each one; a plain `run` does not dispatch them |
|
|
736
|
+
| a run that sits idle with tasks `PENDING` | `forge control drain` is in effect (`forge control show` says `drained`; `forge control resume` continues), every scope a task needs is paused on infrastructure (`infra.paused`), or `max-parallel` is lower than you think |
|
|
651
737
|
| a `FAIL` task merged anyway | an explicit `--qa-threshold` tolerated its findings; see `known_issues.md` and `qa.gate` |
|
|
652
738
|
| task status `CONFLICT` | QA passed but the merge onto the integration branch conflicted — `files` was understated somewhere |
|
|
653
739
|
| every wave has one task | `files` sets overlap across most tasks; the decomposition is not actually parallel |
|
|
@@ -688,6 +774,62 @@ in `verification.retry.log`, and prints a loud `FLAKY` line in `run`/`retry`/`in
|
|
|
688
774
|
a command that changes the tree is never retried. This runs before Jev's optional model-assisted
|
|
689
775
|
triage, which then does not.
|
|
690
776
|
|
|
777
|
+
**Verification lanes.** Instead of one command, verification can be several named **lanes**
|
|
778
|
+
that run side by side, each rerun on its own. A lane is a file whose name is the lane's name
|
|
779
|
+
(letters, digits, `_` and `-`, at most 64) and whose text is a Bash command, run from the
|
|
780
|
+
integration checkout like the single command; leading `#forge:` lines give it options. Declare
|
|
781
|
+
them in the repository as `.forge/verify.d/<name>` files, or for one plan with
|
|
782
|
+
`run --verify-lane 'name[opt,opt]=command'` (also `retry`; repeatable, written to
|
|
783
|
+
`<plan>/verify.d/`; the first one of an invocation replaces the plan's earlier lanes and its
|
|
784
|
+
`--verify`, as `--verify` replaces the plan's lanes). The first source that exists wins: the
|
|
785
|
+
plan's lanes, the plan's `--verify`, the repository's `.forge/verify.d/`, then
|
|
786
|
+
`.forge/verify` (ignored, with a note, when the repository also has lanes). `run` checks the
|
|
787
|
+
lanes before any model is paid for and exits 2 on an invalid one (an unknown or repeated
|
|
788
|
+
option, an empty command, a path outside the checkout, a missing baseline).
|
|
789
|
+
|
|
790
|
+
| Option | Means |
|
|
791
|
+
|---|---|
|
|
792
|
+
| `group=<name>` | lanes of one group never run at the same time (a shared database, a port) |
|
|
793
|
+
| `first` | runs before every other lane; if a `first` lane fails (after its reruns) or changes the tree, the rest are `skipped` |
|
|
794
|
+
| `retries=<0-9>` | reruns of this lane when it fails; otherwise `--verify-retries` (default `1`) |
|
|
795
|
+
| `reports=<dir>` | JUnit `*.xml` and TAP `*.tap` reports the lane writes under `<dir>` (inside the checkout). Only reports written during that run count; they give the lane's test counts and failing tests, and are re-read every 10 s while it runs |
|
|
796
|
+
| `baseline=<file>` | known failing test names, one per line (`#` comments), inside the checkout. A lane whose every failing test is in it ends `known`, which passes. A report that could not be read, or a failure no report names, is judged by the exit code |
|
|
797
|
+
|
|
798
|
+
Up to `--verify-parallel N` lanes run at once (`run`, `retry` and `integrate`, kept as
|
|
799
|
+
`verify_parallel`, 1 to 32, default 3), started in name order. A lane that fails is rerun alone,
|
|
800
|
+
after the round, up to its budget; a pass on a rerun makes it `flaky`, which passes but is named
|
|
801
|
+
in the run output (`FLAKY: lane <name> failed once and passed on rerun`), in
|
|
802
|
+
`verification.flaky` and in the whole-run review. Nothing reruns once the tree changed: the
|
|
803
|
+
checkout's fingerprint is compared after every round, and a change fails the verification
|
|
804
|
+
(`mutated`; with lanes in parallel it cannot be pinned to one of them). A lane's states are
|
|
805
|
+
`waiting`, `running`, `pass`, `fail`, `flaky`, `known`, `skipped` and `interrupted`. Lanes mode
|
|
806
|
+
replaces the whole-command rerun above and Jev's flake triage (a note says so when Jev's tests
|
|
807
|
+
site is on); the single-command mode is unchanged.
|
|
808
|
+
|
|
809
|
+
A lane may print `::forge step name=<step> state=start` and `::forge step name=<step>
|
|
810
|
+
state=end [exit=<n>]`, each on a line of its own, to say which step it is in; forge-ui shows the
|
|
811
|
+
open step live. A signal stops the running lanes' process groups (TERM, then KILL after 5 s),
|
|
812
|
+
marks them and the verification `INTERRUPTED`, and exits 130 like a single command.
|
|
813
|
+
|
|
814
|
+
The runner is `scripts/forge-verify.py` (`lanes` lists and checks a directory's lanes; `run`
|
|
815
|
+
runs them). In lanes mode `verification.command` holds one `<lane>: <first line>` per lane,
|
|
816
|
+
`verification.log` the runner's summary plus the last 200 lines of each lane that failed, and
|
|
817
|
+
`verification.lanes.json` the live state of every lane; each lane writes
|
|
818
|
+
`verification.lane.<name>.log` and keeps each finished run as `verification.lane.<name>.run-<k>.log`.
|
|
819
|
+
|
|
820
|
+
```
|
|
821
|
+
.forge/verify.d/lint #forge: first
|
|
822
|
+
npm run lint && npm run typecheck
|
|
823
|
+
.forge/verify.d/unit #forge: reports=reports/unit
|
|
824
|
+
npm test -- --reporter=junit --outputFile=reports/unit/junit.xml
|
|
825
|
+
.forge/verify.d/db #forge: group=postgres retries=2 reports=reports/db baseline=.forge/known-db-failures.txt
|
|
826
|
+
docker compose up -d postgres && npm run test:db
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
Here `lint` runs alone first; `unit` and `db` then run together, another lane in the
|
|
830
|
+
`postgres` group would wait for `db`, and a `db` run whose only failures are listed in the
|
|
831
|
+
baseline ends `known`.
|
|
832
|
+
|
|
691
833
|
`scripts/forge-verify-coverage.py` reads the project's own test configuration and **warns**
|
|
692
834
|
(never fails) about suites the command does not run — at `run` start before any model is paid
|
|
693
835
|
for, again in `verify_result`, and at `integrate` — recording the lines in
|
package/references/harnesses.md
CHANGED
|
@@ -53,7 +53,9 @@ looking for strong phrases (usage/session limit, quota, insufficient balance/cre
|
|
|
53
53
|
429/529, unauthorized/401/403, invalid API key, not logged in, ECONNRESET/ENOTFOUND/…). An
|
|
54
54
|
`empty` answer (exit 0, nothing said) is the fifth class. codex's non-fatal reconnect notices
|
|
55
55
|
followed by a normal reply never classify. `<role>.infra` holds `class=`, `retry_after=` (parsed
|
|
56
|
-
from "resets 3pm", "try again in 2h", `|<epoch>`, capped at 24 h), `detail=`, `rc=`, `role
|
|
56
|
+
from "resets 3pm", "try again in 2h", `|<epoch>`, capped at 24 h), `detail=`, `rc=`, `role=`,
|
|
57
|
+
`harness=`, `model=` (the scheduler pauses by them: a rate limit pauses that model on that
|
|
58
|
+
harness, a quota or auth stop that harness).
|
|
57
59
|
A dwarf that exits 0 with nothing said writes the file but still exits 0; callers consult it
|
|
58
60
|
only when the diff is empty.
|
|
59
61
|
|
|
@@ -68,6 +70,16 @@ anything still alive in it (`<role>.orphans`). This is proven offline only; veri
|
|
|
68
70
|
with one live dispatch before relying on it, and use the kill switch if a harness deliberately
|
|
69
71
|
leaves a helper running.
|
|
70
72
|
|
|
73
|
+
On an interrupt the harness leads its own session, so the TERM a decomposed run's scheduler
|
|
74
|
+
sends to a task's process group reaches the dispatch, whose exit trap stops the harness. The
|
|
75
|
+
scheduler waits up to `FORGE_INTERRUPT_GRACE` seconds (default 10) for each task's group to
|
|
76
|
+
empty before KILLing it. As a backstop, a guarded dispatch records its harness right after
|
|
77
|
+
launch in `<role>.harness` (`<pid><TAB><start time>`, from `forge-guard.py identity`; removed when
|
|
78
|
+
the dispatch ends). For a task whose dispatch could not stop its harness, and at the next
|
|
79
|
+
scheduler start for tasks a killed scheduler left `RUNNING`, `forge-guard.py stop <record>`
|
|
80
|
+
signals the recorded group (TERM, about 2 s, KILL) only when the pid still has the recorded
|
|
81
|
+
start time, so a reused pid is left alone.
|
|
82
|
+
|
|
71
83
|
Effort ladders, low to high:
|
|
72
84
|
|
|
73
85
|
- codex — `low medium high xhigh max ultra`
|
package/references/ui.md
CHANGED
|
@@ -24,9 +24,13 @@ run goes on, with the same exit code.
|
|
|
24
24
|
- **Fractal child tasks:** the tree a Fractal task was split into, in the inspector and above
|
|
25
25
|
the opened task in 3D, each node with its decision, cost, output and candidate diff.
|
|
26
26
|
- **Controls:** change a live plan from its inspector: QA threshold, timeout, escalate-after,
|
|
27
|
-
verify retries, and (while a scheduler is live)
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
the effort step, verify retries, the infrastructure backoff, and (while a scheduler is live)
|
|
28
|
+
the retry and infra-retry budgets, max parallel, Drain/Resume, Stop and Stop now; per task, a
|
|
29
|
+
threshold override (`None` exempts it), a retry budget, a one-shot model pin and, on a live run,
|
|
30
|
+
*Retry now* for a stopped or failed task (optionally on a chosen model), which shows its queued
|
|
31
|
+
request until the scheduler applies or refuses it. Each infrastructure pause gets a line: what
|
|
32
|
+
is paused, why, its tasks and the time left. Each is one `forge control` call; the change is
|
|
33
|
+
confirmed first and logged in `control.log`.
|
|
30
34
|
- **Open findings and issues:** the findings a run (or all of its repository's runs) left open,
|
|
31
35
|
filed as GitHub issues or dismissed through `forge issues`.
|
|
32
36
|
- **Delete a run:** a dry run, then `forge runs rm`: the dataset keeps the traces, an archive is
|
|
@@ -44,7 +48,13 @@ run goes on, with the same exit code.
|
|
|
44
48
|
as the run's verdict; changes on the user's own branch after an integrate are not tracked. The
|
|
45
49
|
*Execution* view shows the same run on wall-clock time, one block per attempt in the lane it
|
|
46
50
|
ran in, with projected blocks for what has not started and a strip of busy slots against
|
|
47
|
-
`--max-parallel
|
|
51
|
+
`--max-parallel`; the verification follows on rows of its own, one per verification lane
|
|
52
|
+
with each run and rerun.
|
|
53
|
+
- **Verification** (its finish node): live, the elapsed time, a lane's announced step
|
|
54
|
+
(`::forge step`), its last line, a warning after five minutes without output and the live
|
|
55
|
+
output; after a failure, the failing tests first, by lane, new or known (from JUnit/TAP
|
|
56
|
+
reports), each opening the lane's log at its line, or a reportless lane's log tail; then every
|
|
57
|
+
lane's state, time, runs and tests; a lane's name opens its output.
|
|
48
58
|
- **Opening a node** shows its attempts, dwarves and reviews, and an inspector with the prompt
|
|
49
59
|
that launched each one, the model, timings by phase, tokens, verdicts and the P0–P3 findings
|
|
50
60
|
of every review (the final review's included).
|