bareloop 0.18.0 → 0.20.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 +62 -0
- package/bareloop.context.md +16 -2
- package/package.json +1 -1
- package/src/planrun.js +26 -1
- package/src/run.js +12 -2
- package/types/planrun.d.ts +13 -1
- package/types/run.d.ts +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,68 @@ All notable changes to bareloop are documented here. Format:
|
|
|
5
5
|
[SemVer](https://semver.org/spec/v2.0.0.html). Pre-1.0: **minor** = a ladder rung or
|
|
6
6
|
feature lands, **patch** = docs, fixes, scaffolding.
|
|
7
7
|
|
|
8
|
+
## [0.20.0] — 2026-09-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Operator-only scout OFF switch (`docs/product/SCOUT-CONTRAST.md`): `runJob`/`runPlan`
|
|
13
|
+
accept `scout` (boolean, default `true`); `false` on a fresh run skips the read-only
|
|
14
|
+
survey and records `scout-skipped { reason: 'operator-off' }` instead — the planner
|
|
15
|
+
drafts from `(no scout notes)`. `scripts/run-u.mjs --scout on|off` is the runner
|
|
16
|
+
surface, modelled on `--read-shim`; a non-boolean/unrecognised value throws/exits
|
|
17
|
+
before a token is spent. Runner territory — the signed spec hash is unaffected.
|
|
18
|
+
Measured (F126): both arms green on `aurora-u-spawner-types`, OFF cost $0.37 more
|
|
19
|
+
(inside the $0.40 noise band) — the scout is not dead weight; the switch stays as a
|
|
20
|
+
probe knob, no default flip.
|
|
21
|
+
|
|
22
|
+
### Docs
|
|
23
|
+
|
|
24
|
+
- Export scoping and lock: `docs/product/EXPORT-SCOPING.md` (tree facts, proposed
|
|
25
|
+
bundle shape) and `docs/product/EXPORT-BUILD.md` (frozen build spec — worktree,
|
|
26
|
+
no-resign-on-tighten) record hamr's interview answers ahead of the export build
|
|
27
|
+
itself; no code shipped yet.
|
|
28
|
+
- G4 counting-rule scoping (`docs/product/G4-SCOPING.md`) and the first `docs/logs/BENCH.md`
|
|
29
|
+
bench-ledger row.
|
|
30
|
+
|
|
31
|
+
## [0.19.1] — 2026-09-02
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- `tests/no-test-sniffing.test.js` no longer runs the close against the machine-local
|
|
36
|
+
`pulselog-u` patient — that test could only pass on the maintainer's machine and
|
|
37
|
+
turned CI and the v0.19.0 publish red (v0.19.0 was tagged but never published).
|
|
38
|
+
|
|
39
|
+
## [0.19.0] — 2026-09-02
|
|
40
|
+
|
|
41
|
+
_Tagged 2026-09-02, never published: `publish.yml` failed on a machine-local test; see 0.19.1._
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- **G3 bench row (the structural negative).** `scripts/u-pulselog-close.mjs`
|
|
46
|
+
gains an additive `no-test-sniffing` close stage (planted-contradiction cheat catcher,
|
|
47
|
+
modelled on `no-suppressions`) and `--workdir`/`--seed` argv flags so the same close
|
|
48
|
+
script can judge a second patient without touching `jobs/pulselog-u-types.json`'s
|
|
49
|
+
behaviour or signed hash. New spec `jobs/pulselog-g3-types.json`, registered in
|
|
50
|
+
`scripts/run-u.mjs`. Frozen 2026-09-01 (hamr: "freeze"), signed and established
|
|
51
|
+
2026-09-01 — establishing run `u-mties136` read non-green as pre-registered
|
|
52
|
+
(`step-red`, $2.98 of $4, 21.9 of 25 min) — see `docs/product/G3-SCOPING.md`, the
|
|
53
|
+
BENCH-PREREG freeze amendment, and FINDINGS F125.
|
|
54
|
+
- **`tokens` tail line in `scripts/run-u.mjs`'s run readout** (hamr's order,
|
|
55
|
+
2026-09-01). `job-end` carries dollars only; tokens existed only per round on
|
|
56
|
+
`worker-round.usage`/`judge-round.usage`, invisible in the printed tail. New
|
|
57
|
+
`tokensLine`/`fmtTokens` exports in `scripts/u-readout.mjs` sum `usage`
|
|
58
|
+
(`inputTokens`/`outputTokens`/`cacheReadTokens`/`cacheCreationTokens`) over every
|
|
59
|
+
`worker-round` and `judge-round` record of the CURRENT leg's own spine —
|
|
60
|
+
`worker-result` (an attempt-level echo of round sums) is deliberately excluded. A
|
|
61
|
+
round with no `usage` object (every `judge-round` today) counts as UNKNOWN and is
|
|
62
|
+
named in a trailing `(N round(s) unpriced/no usage)` note rather than folded into
|
|
63
|
+
the total as 0. Prints right after the `rounds` line. 5 new tests.
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- **`scripts/run-u.mjs`'s run tail pluralizes `plan N step(s)`.** A 1-step plan
|
|
68
|
+
previously printed `1 steps`; the tail now reads `1 step` / `N steps` correctly.
|
|
69
|
+
|
|
8
70
|
## [0.18.0] — 2026-08-31
|
|
9
71
|
|
|
10
72
|
### Added
|
package/bareloop.context.md
CHANGED
|
@@ -203,7 +203,7 @@ contract the single close object has always used) plus:
|
|
|
203
203
|
| stage field | shape | notes |
|
|
204
204
|
|---|---|---|
|
|
205
205
|
| `name` | unique kebab-case slug | the plan references it via `check-passes(name)`; duplicates red `duplicate-id` |
|
|
206
|
-
| `offer` | optional boolean, default offered | `offer: false` hides the stage from the derived menu — it never reaches the agent. For a stage that cannot stand alone as a ruler: a PRECONDITION (e.g. "the seed commit exists" — passes instantly, teaches nothing) or the **final grading stage** — of the
|
|
206
|
+
| `offer` | optional boolean, default offered | `offer: false` hides the stage from the derived menu — it never reaches the agent. For a stage that cannot stand alone as a ruler: a PRECONDITION (e.g. "the seed commit exists" — passes instantly, teaches nothing) or the **final grading stage** — of the fourteen specs in `jobs/`, five hide a final `verdict` stage and seven hide a `changed-from-seed` precondition instead (the remaining two use an object-form close with no staged `offer` flags) (a per-spec convention, not a schema rule — nothing stops a stage named last from being offered except the spec author remembering to set the flag; preflight's `check-menu` event always names the full menu either way, so a forgotten flag is visible in the run's own record) |
|
|
207
207
|
| `needs` | optional non-empty array of EARLIER stage names | a stage that reads what an earlier stage built (e.g. "the public API matches what an earlier stage emitted") names its prerequisite chain; picking it via `check-passes` runs the chain first, then the stage itself. Every name must be declared before this stage (`invalid-value` otherwise); `needs` + `offer: false` together is incoherent (`invalid-value`) — a stage with a chain to run must be reachable |
|
|
208
208
|
| `direction` | optional `'up'` \| `'down'`, allow-list validated (anything else is `invalid-value`) | which way this stage's numeric series is READING as progress — `'down'` (fewer is better: typecheck errors, suppressions) or `'up'` (more is better: a fault-detection rate). **Absent means `'down'`** — every close built before this field existed is a count-shaped close, so the silent default is behaviour-identical for all of them (F120). Never inferred from the goal text and never LLM-judged — prose the agent writes must never influence its own halt rule, the same reasoning that keeps every close hand-authored or declared, never judged. Consulted by `isBetter(stage,a,b)` in `src/trend.js`, the one place the close-fix governor's `countImproved` and `best`-tracking read direction; `scripts/run-u.mjs` prints each stage's direction at the close-stage banner so a silent default is never invisible |
|
|
209
209
|
|
|
@@ -958,7 +958,7 @@ Reserved spine vocabulary (V7, machinery-free until job #1 surfaces one):
|
|
|
958
958
|
`coordination-red` — a failure between units (scope contention, step order, store
|
|
959
959
|
races), never to be folded into worker/interpreter reds.
|
|
960
960
|
|
|
961
|
-
### `runJob(spec, { approvals, workdir, provider, nativeProvider?, providerFor?, emit, capRuns?, strikeLimit?, shellCapUsd?, closeTimeoutMs?, layerRoot?, readShim?, bridge?, priorSpentUsd?, priorSpendComplete?, priorWallMs?, resumeSeed?, resumeGrades?, resumeReplans?, resumeBranch?, humanRuling?, heldRuling?, reviewDoor?, doorRerun? })` → outcome — `src/run.js`
|
|
961
|
+
### `runJob(spec, { approvals, workdir, provider, nativeProvider?, providerFor?, emit, capRuns?, strikeLimit?, shellCapUsd?, closeTimeoutMs?, layerRoot?, readShim?, scout?, bridge?, priorSpentUsd?, priorSpendComplete?, priorWallMs?, resumeSeed?, resumeGrades?, resumeReplans?, resumeBranch?, humanRuling?, heldRuling?, reviewDoor?, doorRerun? })` → outcome — `src/run.js`
|
|
962
962
|
|
|
963
963
|
The last seven are the RESUME fold and are documented under *Resuming a killed run* below; they
|
|
964
964
|
default to `0` / `true` / `0` / `null` / `[]` / `null` / `null`, so a fresh run passes none of them.
|
|
@@ -1027,6 +1027,20 @@ arm replaces the CLI-display cap rather than stacking on it; a non-capping arm l
|
|
|
1027
1027
|
installed *inside* the shim, so native never loses its bound. Default-flip pending a paid contrast;
|
|
1028
1028
|
see CHANGELOG for the replay numbers behind it.
|
|
1029
1029
|
|
|
1030
|
+
**`scout` (default `true`) — the operator-only off switch** (`docs/product/SCOUT-CONTRAST.md`),
|
|
1031
|
+
threaded verbatim from `runJob` to `runPlan`. `false` on a FRESH run (no `resumeSeed`) skips the
|
|
1032
|
+
read-only survey entirely — `scout-start`/`scout-result`/`scout-empty` never fire, and a single
|
|
1033
|
+
`scout-skipped { reason: 'operator-off', meaning }` records it (a RECORD, never silence — the
|
|
1034
|
+
resume skip's own rule). The planner then drafts from `(no scout notes)` exactly as it does today
|
|
1035
|
+
when a scout returns an empty blob; nothing else observable changes. Precedence when both a
|
|
1036
|
+
resumed leg and `scout:false` are in play: the resume skip fires first and wins its own reason
|
|
1037
|
+
(`resumed`) — `operator-off` is only ever emitted on a fresh run. A non-boolean value **throws**
|
|
1038
|
+
a `TypeError` at the same door as the `readShim` arm guard, before a token is spent. It is a probe
|
|
1039
|
+
knob, not a product default — the spec names no scout, so the signed hash is unaffected — and
|
|
1040
|
+
`scripts/run-u.mjs --scout on|off` (default `on`) is its runner-territory surface, modelled on
|
|
1041
|
+
`--read-shim`: an unrecognised value exits 2 at argv, and every re-invocation the runner prints
|
|
1042
|
+
carries `--scout off` when set, so a resume never silently drops the arm.
|
|
1043
|
+
|
|
1030
1044
|
**The two hitl terminals (N4 slice 1, doors re-cut 2026-08-18)** are the class's whole surface
|
|
1031
1045
|
at this layer, and each is a CLEAN exit (`spendComplete` stays true — only the two casualties floor). `hitl-pause` is a
|
|
1032
1046
|
decision-ready CHECKPOINT: the close reached a stage no machine can render, so the run stops
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bareloop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Workflows that earn their own design, with receipts \u2014 agent-authored workflows for repeated, long, verifiable jobs that improve across runs under an un-gameable gate.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
package/src/planrun.js
CHANGED
|
@@ -642,6 +642,17 @@ ${scoutBlob || '(no scout notes)'}`;
|
|
|
642
642
|
* it.
|
|
643
643
|
* @param {number} [opts.closeTimeoutMs] close/check wall-clock cap (shell territory)
|
|
644
644
|
* @param {number} [opts.maxStepRounds] the shell's per-step rounds ceiling (validatePlan's bound)
|
|
645
|
+
* @param {boolean} [opts.scout=true] operator-only switch (docs/product/SCOUT-CONTRAST.md):
|
|
646
|
+
* `false` on a FRESH run (no `resumeSeed`) skips the survey entirely — `scoutBlob`
|
|
647
|
+
* stays `''`, no `scout-start`/`scout-result`/`scout-empty` is emitted, and a single
|
|
648
|
+
* `scout-skipped {reason:'operator-off'}` records it (a RECORD, never silence — the
|
|
649
|
+
* resume skip's own rule). The planner then drafts from `(no scout notes)`
|
|
650
|
+
* (line ~587) exactly as it does today when a scout returns an empty blob — OFF is
|
|
651
|
+
* byte-identical to today's run everywhere but the survey. Precedence: when
|
|
652
|
+
* `resumeSeed` is set the existing resume skip fires first and wins its own reason
|
|
653
|
+
* (`resumed`); `operator-off` is only ever emitted on a fresh run. A non-boolean
|
|
654
|
+
* THROWS a TypeError at entry (the `readShimArm` guard class) — a knob that
|
|
655
|
+
* silently coerced would mislabel a bench row.
|
|
645
656
|
* @param {number} [opts.scoutRounds] the read-only survey's round bound (F59: the LAST round is
|
|
646
657
|
* reserved — a scout that spends every round on tools gets one toolless round to write its
|
|
647
658
|
* survey, because the bound halts it mid-tool-use and text is its only deliverable)
|
|
@@ -805,7 +816,7 @@ ${scoutBlob || '(no scout notes)'}`;
|
|
|
805
816
|
* 'branch-red' | 'cap-halt' | 'wall-halt' | 'provider-red' | 'interpreter-red' |
|
|
806
817
|
* 'step-stalled' | 'hitl-pause' | 'hitl-decision-red' | `step-red:<id>`
|
|
807
818
|
*/
|
|
808
|
-
export async function runPlan(job, { workdir, provider, nativeProvider, providerFor, judgeProvider = null, emit, remainingUsd, isUnpriced = () => false, spendComplete = () => true, capRuns = 3, strikeLimit = STRIKE_LIMIT, closeTimeoutMs, maxStepRounds = 40, layerRoot = false, readShim = false, scoutRounds = SCOUT_ROUNDS, bridge = null, now, priorWallMs = 0, resumeSeed = null, resumeGrades = [], resumeReplans = null, resumeBranch = null, humanRuling = null, heldRuling = null, priorSpentUsd = 0, reviewDoor = null, doorRerun = null }) {
|
|
819
|
+
export async function runPlan(job, { workdir, provider, nativeProvider, providerFor, judgeProvider = null, emit, remainingUsd, isUnpriced = () => false, spendComplete = () => true, capRuns = 3, strikeLimit = STRIKE_LIMIT, closeTimeoutMs, maxStepRounds = 40, layerRoot = false, readShim = false, scout = true, scoutRounds = SCOUT_ROUNDS, bridge = null, now, priorWallMs = 0, resumeSeed = null, resumeGrades = [], resumeReplans = null, resumeBranch = null, humanRuling = null, heldRuling = null, priorSpentUsd = 0, reviewDoor = null, doorRerun = null }) {
|
|
809
820
|
// MEMORY-CACHE: what the read shim (src/readshim.js) saved THIS run, summed across
|
|
810
821
|
// every mkWorker's own shim instance (scout, drafter, each step's worker, the fix
|
|
811
822
|
// worker) — one accumulator closed over by all of them, because the shim's ledger
|
|
@@ -822,6 +833,11 @@ export async function runPlan(job, { workdir, provider, nativeProvider, provider
|
|
|
822
833
|
// would be wrong and would look fine). Only the guard runs here; the flag itself
|
|
823
834
|
// is still threaded onward as written.
|
|
824
835
|
readShimArm(readShim);
|
|
836
|
+
// The scout switch's guard, same class and same door: a mis-typed value
|
|
837
|
+
// coerced by truthiness would run the scout under an "off" label (or skip it
|
|
838
|
+
// under an "on" one) and no reading of the results afterwards could recover
|
|
839
|
+
// which arm actually ran (docs/product/SCOUT-CONTRAST.md).
|
|
840
|
+
if (typeof scout !== 'boolean') throw new TypeError(`scout: expected boolean, got ${JSON.stringify(scout)}`);
|
|
825
841
|
// G1's OTHER half, refused at the same $0 door. `validatePlan` reds `read-blind`
|
|
826
842
|
// when a step grants `read` without the retrieval pair — but a step cannot grant
|
|
827
843
|
// what the SIGNED CEILING does not offer, so against a spec whose `tools` lack
|
|
@@ -2456,6 +2472,15 @@ export async function runPlan(job, { workdir, provider, nativeProvider, provider
|
|
|
2456
2472
|
reason: 'resumed', phase: resumeSeed.phase ?? null,
|
|
2457
2473
|
meaning: 'the killed run already paid for this survey; its plan is reloaded, not re-drafted. A replan after this point drafts from an empty survey plus the failure brief.',
|
|
2458
2474
|
});
|
|
2475
|
+
} else if (scout === false) {
|
|
2476
|
+
// The operator-off arm (docs/product/SCOUT-CONTRAST.md): a fresh run whose
|
|
2477
|
+
// operator asked for no survey. Precedence already settled above — the
|
|
2478
|
+
// resume branch fires first and wins its own reason, so this arm is only
|
|
2479
|
+
// ever reached when there is nothing to resume from.
|
|
2480
|
+
emit('scout-skipped', {
|
|
2481
|
+
reason: 'operator-off',
|
|
2482
|
+
meaning: 'the operator ran with --scout off; the planner drafts from "(no scout notes)"; no survey was paid for.',
|
|
2483
|
+
});
|
|
2459
2484
|
} else {
|
|
2460
2485
|
emit('scout-start', { rounds: scoutRounds });
|
|
2461
2486
|
try {
|
package/src/run.js
CHANGED
|
@@ -171,6 +171,12 @@ async function primitiveSmoke(workdir) {
|
|
|
171
171
|
* frozen A0 baseline arm has to be exactly today, so a guard firing under a disabled
|
|
172
172
|
* shim would make the baseline a treatment arm. The default-flip belongs to a
|
|
173
173
|
* paid contrast nobody has approved yet (the `layerRoot` precedent, F41).
|
|
174
|
+
* @param {boolean} [opts.scout=true] operator-only switch (docs/product/SCOUT-CONTRAST.md),
|
|
175
|
+
* forwarded verbatim to the plan flow: `false` on a fresh run (no `resumeSeed`) skips the
|
|
176
|
+
* read-only survey and records `scout-skipped {reason:'operator-off'}` instead — the
|
|
177
|
+
* planner drafts from `(no scout notes)`. Runner territory exactly like `readShim`: the
|
|
178
|
+
* spec names no scout, so the signed hash is unaffected. A non-boolean THROWS at this
|
|
179
|
+
* entry, before the ledger, before the approval gate (the `readShim` guard class).
|
|
174
180
|
* @param {boolean} [opts.layerRoot=false] Layer R (within-run ratchet) — shell
|
|
175
181
|
* territory, threaded to the plan flow. Defaults OFF
|
|
176
182
|
* (decided 2026-07-21): fixation is extinct on every current job (F41), so
|
|
@@ -202,7 +208,7 @@ async function primitiveSmoke(workdir) {
|
|
|
202
208
|
* 'interpreter-red' | 'cap-halt' | 'wall-halt' | 'step-stalled' |
|
|
203
209
|
* 'hitl-pause' | 'hitl-decision-red' | `step-red:<id>`
|
|
204
210
|
*/
|
|
205
|
-
export async function runJob(rawSpec, { approvals, workdir, provider, nativeProvider, providerFor, judgeProvider = null, emit, capRuns = 3, strikeLimit, shellCapUsd = 2, closeTimeoutMs, layerRoot = false, readShim = false, bridge = null, priorSpentUsd = 0, priorSpendComplete = true, priorWallMs = 0, resumeSeed = null, resumeGrades = [], resumeReplans = null, resumeBranch = null, humanRuling = null, heldRuling = null, reviewDoor = null, doorRerun = null }) {
|
|
211
|
+
export async function runJob(rawSpec, { approvals, workdir, provider, nativeProvider, providerFor, judgeProvider = null, emit, capRuns = 3, strikeLimit, shellCapUsd = 2, closeTimeoutMs, layerRoot = false, readShim = false, scout = true, bridge = null, priorSpentUsd = 0, priorSpendComplete = true, priorWallMs = 0, resumeSeed = null, resumeGrades = [], resumeReplans = null, resumeBranch = null, humanRuling = null, heldRuling = null, reviewDoor = null, doorRerun = null }) {
|
|
206
212
|
// THE READ SHIM's ARM, resolved at the door — the FIRST thing this entry does,
|
|
207
213
|
// before the ledger, before the approval gate, before a byte of the spec is read.
|
|
208
214
|
// An unrecognised spelling throws here at zero cost instead of being coerced by
|
|
@@ -211,6 +217,10 @@ export async function runJob(rawSpec, { approvals, workdir, provider, nativeProv
|
|
|
211
217
|
// blind-instrument failure this programme keeps logging. Only the guard runs
|
|
212
218
|
// here; the flag itself is threaded onward to the plan flow as written.
|
|
213
219
|
readShimArm(readShim);
|
|
220
|
+
// The scout switch's guard, same class and same door (docs/product/SCOUT-CONTRAST.md):
|
|
221
|
+
// a mis-coerced value would run under the wrong label with no way to recover which arm
|
|
222
|
+
// actually fired from the results afterwards.
|
|
223
|
+
if (typeof scout !== 'boolean') throw new TypeError(`scout: expected boolean, got ${JSON.stringify(scout)}`);
|
|
214
224
|
// 0. the ledger's counters, declared FIRST so that every job-end — including
|
|
215
225
|
// the pre-token reds below — can state a real figure. An omitted `spentUsd` is
|
|
216
226
|
// not a zero: a consumer reads `undefined` and either crashes or launders it
|
|
@@ -405,7 +415,7 @@ export async function runJob(rawSpec, { approvals, workdir, provider, nativeProv
|
|
|
405
415
|
// accounts it natively (F12) and the job-end money contract is unchanged.
|
|
406
416
|
{
|
|
407
417
|
const outcome = await runPlan(job, {
|
|
408
|
-
workdir, provider, nativeProvider, providerFor, judgeProvider, emit: meter, capRuns, ...(strikeLimit !== undefined ? { strikeLimit } : {}), closeTimeoutMs, layerRoot, readShim, bridge, priorWallMs: chainWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, reviewDoor, doorRerun, priorSpentUsd: chainFoldUsd,
|
|
418
|
+
workdir, provider, nativeProvider, providerFor, judgeProvider, emit: meter, capRuns, ...(strikeLimit !== undefined ? { strikeLimit } : {}), closeTimeoutMs, layerRoot, readShim, scout, bridge, priorWallMs: chainWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, reviewDoor, doorRerun, priorSpentUsd: chainFoldUsd,
|
|
409
419
|
remainingUsd: () => Math.min(shellCapUsd, job.budgetUsd - spentUsd),
|
|
410
420
|
isUnpriced: () => unpriced, // F6: let the plan flow bail in-flight, not just after it returns
|
|
411
421
|
spendComplete, // …and let its money-halt readout say whether the remaining it quotes is exact
|
package/types/planrun.d.ts
CHANGED
|
@@ -223,6 +223,17 @@ export function planPrompt(job: any, scoutBlob: string, reds: any[] | null, maxS
|
|
|
223
223
|
* it.
|
|
224
224
|
* @param {number} [opts.closeTimeoutMs] close/check wall-clock cap (shell territory)
|
|
225
225
|
* @param {number} [opts.maxStepRounds] the shell's per-step rounds ceiling (validatePlan's bound)
|
|
226
|
+
* @param {boolean} [opts.scout=true] operator-only switch (docs/product/SCOUT-CONTRAST.md):
|
|
227
|
+
* `false` on a FRESH run (no `resumeSeed`) skips the survey entirely — `scoutBlob`
|
|
228
|
+
* stays `''`, no `scout-start`/`scout-result`/`scout-empty` is emitted, and a single
|
|
229
|
+
* `scout-skipped {reason:'operator-off'}` records it (a RECORD, never silence — the
|
|
230
|
+
* resume skip's own rule). The planner then drafts from `(no scout notes)`
|
|
231
|
+
* (line ~587) exactly as it does today when a scout returns an empty blob — OFF is
|
|
232
|
+
* byte-identical to today's run everywhere but the survey. Precedence: when
|
|
233
|
+
* `resumeSeed` is set the existing resume skip fires first and wins its own reason
|
|
234
|
+
* (`resumed`); `operator-off` is only ever emitted on a fresh run. A non-boolean
|
|
235
|
+
* THROWS a TypeError at entry (the `readShimArm` guard class) — a knob that
|
|
236
|
+
* silently coerced would mislabel a bench row.
|
|
226
237
|
* @param {number} [opts.scoutRounds] the read-only survey's round bound (F59: the LAST round is
|
|
227
238
|
* reserved — a scout that spends every round on tools gets one toolless round to write its
|
|
228
239
|
* survey, because the bound halts it mid-tool-use and text is its only deliverable)
|
|
@@ -386,7 +397,7 @@ export function planPrompt(job: any, scoutBlob: string, reds: any[] | null, maxS
|
|
|
386
397
|
* 'branch-red' | 'cap-halt' | 'wall-halt' | 'provider-red' | 'interpreter-red' |
|
|
387
398
|
* 'step-stalled' | 'hitl-pause' | 'hitl-decision-red' | `step-red:<id>`
|
|
388
399
|
*/
|
|
389
|
-
export function runPlan(job: any, { workdir, provider, nativeProvider, providerFor, judgeProvider, emit, remainingUsd, isUnpriced, spendComplete, capRuns, strikeLimit, closeTimeoutMs, maxStepRounds, layerRoot, readShim, scoutRounds, bridge, now, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, priorSpentUsd, reviewDoor, doorRerun }: {
|
|
400
|
+
export function runPlan(job: any, { workdir, provider, nativeProvider, providerFor, judgeProvider, emit, remainingUsd, isUnpriced, spendComplete, capRuns, strikeLimit, closeTimeoutMs, maxStepRounds, layerRoot, readShim, scout, scoutRounds, bridge, now, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, priorSpentUsd, reviewDoor, doorRerun }: {
|
|
390
401
|
workdir: string;
|
|
391
402
|
provider: any;
|
|
392
403
|
nativeProvider?: ((o: {
|
|
@@ -404,6 +415,7 @@ export function runPlan(job: any, { workdir, provider, nativeProvider, providerF
|
|
|
404
415
|
strikeLimit?: number | undefined;
|
|
405
416
|
closeTimeoutMs?: number | undefined;
|
|
406
417
|
maxStepRounds?: number | undefined;
|
|
418
|
+
scout?: boolean | undefined;
|
|
407
419
|
scoutRounds?: number | undefined;
|
|
408
420
|
readShim?: boolean | "cap" | "diff" | undefined;
|
|
409
421
|
layerRoot?: boolean | undefined;
|
package/types/run.d.ts
CHANGED
|
@@ -110,6 +110,12 @@
|
|
|
110
110
|
* frozen A0 baseline arm has to be exactly today, so a guard firing under a disabled
|
|
111
111
|
* shim would make the baseline a treatment arm. The default-flip belongs to a
|
|
112
112
|
* paid contrast nobody has approved yet (the `layerRoot` precedent, F41).
|
|
113
|
+
* @param {boolean} [opts.scout=true] operator-only switch (docs/product/SCOUT-CONTRAST.md),
|
|
114
|
+
* forwarded verbatim to the plan flow: `false` on a fresh run (no `resumeSeed`) skips the
|
|
115
|
+
* read-only survey and records `scout-skipped {reason:'operator-off'}` instead — the
|
|
116
|
+
* planner drafts from `(no scout notes)`. Runner territory exactly like `readShim`: the
|
|
117
|
+
* spec names no scout, so the signed hash is unaffected. A non-boolean THROWS at this
|
|
118
|
+
* entry, before the ledger, before the approval gate (the `readShim` guard class).
|
|
113
119
|
* @param {boolean} [opts.layerRoot=false] Layer R (within-run ratchet) — shell
|
|
114
120
|
* territory, threaded to the plan flow. Defaults OFF
|
|
115
121
|
* (decided 2026-07-21): fixation is extinct on every current job (F41), so
|
|
@@ -141,7 +147,7 @@
|
|
|
141
147
|
* 'interpreter-red' | 'cap-halt' | 'wall-halt' | 'step-stalled' |
|
|
142
148
|
* 'hitl-pause' | 'hitl-decision-red' | `step-red:<id>`
|
|
143
149
|
*/
|
|
144
|
-
export function runJob(rawSpec: object | string, { approvals, workdir, provider, nativeProvider, providerFor, judgeProvider, emit, capRuns, strikeLimit, shellCapUsd, closeTimeoutMs, layerRoot, readShim, bridge, priorSpentUsd, priorSpendComplete, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, reviewDoor, doorRerun }: {
|
|
150
|
+
export function runJob(rawSpec: object | string, { approvals, workdir, provider, nativeProvider, providerFor, judgeProvider, emit, capRuns, strikeLimit, shellCapUsd, closeTimeoutMs, layerRoot, readShim, scout, bridge, priorSpentUsd, priorSpendComplete, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling, heldRuling, reviewDoor, doorRerun }: {
|
|
145
151
|
approvals: unknown;
|
|
146
152
|
workdir: string;
|
|
147
153
|
provider: any;
|
|
@@ -173,6 +179,7 @@ export function runJob(rawSpec: object | string, { approvals, workdir, provider,
|
|
|
173
179
|
} | null | undefined;
|
|
174
180
|
resumeBranch?: string | null | undefined;
|
|
175
181
|
readShim?: boolean | "cap" | "diff" | undefined;
|
|
182
|
+
scout?: boolean | undefined;
|
|
176
183
|
layerRoot?: boolean | undefined;
|
|
177
184
|
humanRuling?: {
|
|
178
185
|
decision: string;
|