bareloop 0.15.0 → 0.16.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 +75 -0
- package/bareloop.context.md +62 -49
- package/package.json +1 -1
- package/src/authorjob.js +2 -2
- package/src/reuse.js +11 -13
- package/types/reuse.d.ts +10 -11
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,81 @@ feature lands, **patch** = docs, fixes, scaffolding.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.16.0] — 2026-08-30
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`PROMPT_COMMIT_RANGE` covers every commit of a direct push (PRD #2b, #8)**:
|
|
15
|
+
`scripts/prompt-commit-check.mjs` now honours an env var of that name (`--range` mode
|
|
16
|
+
only — a commit-msg hook's `--message-file` path is never redirected by a stray env
|
|
17
|
+
var), which supersedes `--range` and needs no `HEAD~1` fallback of its own.
|
|
18
|
+
`.github/workflows/ci.yml`'s `npm test` step sets it to `github.event.before..sha` on
|
|
19
|
+
push events, so a linear multi-commit direct push to `main` is inspected whole instead
|
|
20
|
+
of the local `HEAD~1..HEAD` fallback re-covering only the last commit. An unresolvable
|
|
21
|
+
env range (a 40-zero `github.event.before` on a brand-new branch push) is reported and
|
|
22
|
+
falls back to the `--range` arg's own path, including its existing main-push fallback.
|
|
23
|
+
Same option-shaped-value guard as `--range` (a value starting with `-` is refused before
|
|
24
|
+
it reaches `git`). Premise measured on `origin/main`'s own reflog (two 3-commit linear
|
|
25
|
+
pushes on 2026-08-24, one carrying a prompt-register change the `HEAD~1` fallback would
|
|
26
|
+
have skipped); 3 new CLI tests, each proven failing before the fix. **CI-proven
|
|
27
|
+
2026-08-30**: a branch-birth push (40-zero `before`) fell back and checked 5 commits
|
|
28
|
+
(CI run 33314883771); the next push used the real range `7e975b3..f0c3199` and checked
|
|
29
|
+
exactly 1 (run 33314899690).
|
|
30
|
+
- **Green-class runs mint a registry row, born released** (PRD open item #16,
|
|
31
|
+
`src/reuse.js`'s `writeRunGreenRow`): the fourth refusal (`credit-not-held`) is dropped —
|
|
32
|
+
a mechanical `green` run now mints its registry row at run end exactly like `soft-green`
|
|
33
|
+
does, but unheld: `greenParts` already keys the hold on `quarantinesCredit(verdictType)`
|
|
34
|
+
(`src/bridges.js:372`), so no bridge/door code changed. `door accept` on an unheld green
|
|
35
|
+
row records the disposition and releases nothing — it no longer dies `no-row-for-run`;
|
|
36
|
+
that terminal is reserved for a run that truly earned no row. `scripts/run-u.mjs`'s
|
|
37
|
+
registry line now prints `HELD`/`RELEASED` by class instead of `HELD` unconditionally,
|
|
38
|
+
and its door credit readout distinguishes a genuine release from a repeat `accept` on an
|
|
39
|
+
already-released row (`recordDoor` returns `released: false` on a same-decision repeat —
|
|
40
|
+
the wording now branches on `quarantinesCredit(spec.verdictType)` rather than claiming a
|
|
41
|
+
fresh release every time). 4 new/updated tests (2 proven failing before the fix),
|
|
42
|
+
including a soft-green regression guard (still born `HELD`) and the still-refusing
|
|
43
|
+
no-row-for-run case.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- **`bareloop.context.md` leads with the shipped design** (PRD #14): the header states the
|
|
48
|
+
v0.15.0 contract first — `green` + `soft-green`, the judged floor and calibration gate,
|
|
49
|
+
the review door (`accept`/`rerun`/`pause`) that never changes the loop's own verdict —
|
|
50
|
+
and demotes `hitl` to a LEGACY block: still admitted in code (`VERDICT_TYPES`,
|
|
51
|
+
`human-confirms`, `hitl-pause`/`hitl-decision-red`), retired by design (PRD v1.71),
|
|
52
|
+
removal a future breaking change. Six inner passages that still called `soft-green`
|
|
53
|
+
"locked" or `hitl` "the forward path" now state the shipped fact.
|
|
54
|
+
- **The authorjob no-repo refusal message** (`src/authorjob.js`) no longer says a judged or
|
|
55
|
+
human close is "declared-but-locked" — `LOCKED_CLASSES` has been empty since v0.12.0; it
|
|
56
|
+
now says what is true: this authoring flow drafts code-genre closes against a git seed
|
|
57
|
+
only.
|
|
58
|
+
- **4 `jobs/*.json` description paths repointed, docs reorg** (PRD #13): the two preregs
|
|
59
|
+
living under `docs/logs/` (`TESTGEN-PREREG.md`, `REUSE-LIFT-CONTRAST-PREREG.md`) moved to
|
|
60
|
+
`docs/product/` beside the other eight; `docs/index.md`, the one live `FINDINGS.md` link
|
|
61
|
+
and `scripts/gen-mutants-testgen.mjs`'s prereg string follow. The four job descriptions
|
|
62
|
+
that still cited the pre-reorg `docs/02-experiments/*-PREREG.md` path now cite the real
|
|
63
|
+
files — each job's signed hash flips and re-signs at its next run. `docs/archive/` and
|
|
64
|
+
CHANGELOG history left as written.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- **`--range`-only CLI tests no longer leak an ambient `PROMPT_COMMIT_RANGE`**: the six
|
|
69
|
+
tests exercising `--range` in isolation now pass `PROMPT_COMMIT_RANGE: ''` explicitly, so
|
|
70
|
+
a resolvable ambient value (as CI's own `npm test` step now sets on every push) can never
|
|
71
|
+
silently route them onto the env-range path they don't exist to prove.
|
|
72
|
+
|
|
73
|
+
### Ruled (no code change)
|
|
74
|
+
|
|
75
|
+
- **Accept's re-proof wall governance** (PRD #15, hamr, 2026-08-30): the door-accept
|
|
76
|
+
re-proof runs unclocked, on the condition it stays mechanical
|
|
77
|
+
(`mechanicalStages()` only, `src/reviewdoor.js:213`) — never a judged floor, never a
|
|
78
|
+
person. A check is never bounded (W-2); any future non-mechanical re-proof is a new
|
|
79
|
+
arbiter question.
|
|
80
|
+
- **`hitl` cleanup deferred** (PRD #21, hamr, 2026-08-30): `hitl` stays admitted in code
|
|
81
|
+
(retired by design only) until hamr decides between finishing the retirement (delete the
|
|
82
|
+
class, the stage kind, the two terminals, migrate any job using it — a breaking rung with
|
|
83
|
+
its own release) or keeping it reopenable. Unscheduled either way.
|
|
84
|
+
|
|
10
85
|
## [0.15.0] — 2026-08-27
|
|
11
86
|
|
|
12
87
|
### Added
|
package/bareloop.context.md
CHANGED
|
@@ -1,31 +1,37 @@
|
|
|
1
1
|
# bareloop — Integration Guide
|
|
2
2
|
|
|
3
|
-
> **Current
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
>
|
|
3
|
+
> **Current: v0.16.0.** The verdict classes are **`green` + `soft-green`**. `soft-green` has
|
|
4
|
+
> a real judged floor (`judged-floor`, `src/judged.js`): a pinned haiku-4.5 judge LOCATEs
|
|
5
|
+
> facts with quotes from the real artifact, an arbiter-owned `decide()` renders pass/fail from
|
|
6
|
+
> a signed rubric card, and *unsure* is a red, never a pass — bought by a signed calibration
|
|
7
|
+
> gate (ten graded truths, five resisted lies, floor 10/10, itemized reds). A soft-green pass
|
|
8
|
+
> mints its bridge row QUARANTINED: no learning credit until an `accept` releases it, forward
|
|
9
|
+
> only; a rerun records a disposition and its outcome is a NEW run's own row, born held
|
|
10
|
+
> again. Every run ends at the signer's **review door** — `accept` / `rerun` / `pause` — which
|
|
11
|
+
> records a disposition and **never changes the loop's own verdict** (`runPlan` still returns
|
|
12
|
+
> `green`/`already-green` exactly as before). The door
|
|
13
|
+
> is open **always for `soft-green`**, and **opt-in for `green`** via `reviewDoor: true` /
|
|
14
|
+
> `--review-door` (the flag wins in both directions, never inferred); `accept` re-runs the
|
|
15
|
+
> close's MECHANICAL stages only — never a judged floor, never a person. Shipped in v0.12.0
|
|
16
|
+
> (2026-08-23); see CHANGELOG `## [0.12.0]` onward for the softgreen rung and the fixes/rungs
|
|
17
|
+
> that followed through v0.15.0. **The plan shape is the ONLY shape**: the legacy
|
|
7
18
|
> operator-authored `steps[]` path, config-v1 and the draft-PR hitl step were deleted
|
|
8
19
|
> 2026-07-26 (PRD v1.32), so `interpret`, `validateConfig` and `extractRules` are gone from
|
|
9
|
-
> the public surface — a breaking change.
|
|
10
|
-
>
|
|
11
|
-
> the
|
|
12
|
-
>
|
|
13
|
-
>
|
|
14
|
-
|
|
15
|
-
>
|
|
16
|
-
> the
|
|
17
|
-
|
|
18
|
-
>
|
|
19
|
-
>
|
|
20
|
-
> `
|
|
21
|
-
>
|
|
22
|
-
>
|
|
23
|
-
>
|
|
24
|
-
> gets a `judged-floor` stage behind a signed rubric card and a signed calibration set.
|
|
25
|
-
> **Everything documented in this file describes the code as it actually is on this branch**,
|
|
26
|
-
> where `hitl` IS admitted, `human-confirms` IS live, and the three `hitl-*` terminals exist —
|
|
27
|
-
> integrate against what is written here, and expect the class-level rename when the next rung
|
|
28
|
-
> lands. Records: PRD Addendum v1.71 and
|
|
20
|
+
> the public surface — a breaking change. Runs on two worker surfaces — the API `Loop` and,
|
|
21
|
+
> for `clipipe-subscription`, the CLI's native tool channel (module 4d). API sections fill in
|
|
22
|
+
> as build-ladder rungs land (PRD §10). What is settled — the boundary, the architecture, the
|
|
23
|
+
> refusals, the constraints — is settled for good. Per LIBRARY_CONVENTIONS §3 this file ships
|
|
24
|
+
> with the package and is the complete adopter contract; the README is only the pitch.
|
|
25
|
+
|
|
26
|
+
> **LEGACY — `hitl` (retired by design, PRD Addendum v1.71, 2026-08-17).** `hitl` remains
|
|
27
|
+
> ADMITTED in code today — `VERDICT_TYPES` still lists it, the `human-confirms` stage kind is
|
|
28
|
+
> still live (never offered, at-most-once, must be last), and the two `hitl-*` terminals
|
|
29
|
+
> (`hitl-pause`, `hitl-decision-red`) still exist and still work exactly as documented
|
|
30
|
+
> wherever this file describes them below. It is retired as a *design direction*, not deleted
|
|
31
|
+
> as *code*: `LOCKED_CLASSES` is empty, so nothing refuses a `hitl` job today, but new
|
|
32
|
+
> integrations should target `green` / `soft-green` plus the review door instead — that pair
|
|
33
|
+
> is the forward path for anything needing a person's judgement, and `hitl`'s removal is a
|
|
34
|
+
> future breaking change, not yet scheduled. Records: PRD Addendum v1.71,
|
|
29
35
|
> `docs/product/2026-08-17-softgreen-review-door-design.md` (repo-only, not shipped);
|
|
30
36
|
> evidence F102–F105.
|
|
31
37
|
|
|
@@ -110,8 +116,8 @@ the step plan at run time (gated by `validatePlan`); the human signs only:
|
|
|
110
116
|
| field | shape | notes |
|
|
111
117
|
|---|---|---|
|
|
112
118
|
| `goal` | non-empty text | what the agent plans against |
|
|
113
|
-
| `verdictType` | `green` \| `soft-green` \| `hitl` | declared radio, never inferred (`VERDICT_TYPES`, frozen).
|
|
114
|
-
| `close` | **an ORDERED LIST of named stages** `[{ name, cmd, expect, judged?, gapKeep?, offer?, needs? }, ...]` (PRD v1.28), or a close object (table below)
|
|
119
|
+
| `verdictType` | `green` \| `soft-green` \| `hitl` | declared radio, never inferred (`VERDICT_TYPES`, frozen). **All three are ADMITTED today** — `LOCKED_VERDICTS` is empty, so nothing reds `request-red` on the class itself. `soft-green` has its judged floor (`judged-floor`, signed rubric card + calibration gate) and is the forward path for a job needing judgement, paired with the end-of-run review door; `hitl` is LEGACY — retired as a design direction (see the direction note at the top) but still admitted and still works exactly as documented here. Every `request-red` (e.g. for a locked TOOL verb, not a verdict class) also carries `lib` — the territory the demand lands against, stamped at the emit site (`verdictType` → `bareloop`, a locked tool verb → `bare-agent`): the ledger keys and its `suggestedAsk` seed on it, so a bareloop-catalogue refusal never files as an upstream ask |
|
|
120
|
+
| `close` | **an ORDERED LIST of named stages** `[{ name, cmd, expect, judged?, gapKeep?, offer?, needs? }, ...]` (PRD v1.28), or a close object (table below) | the destination, the only thing hand-authored; the check menu DERIVES from it (below). The plan flow executes a staged close directly and adapts a bare `predicate` object into a one-stage list; a `gold`/`rubric`/`hitl` object close still VALIDATES (`CLOSE_TYPES`) but the plan flow refuses all three at runtime as `close-unsupported` — an object close names no command to run. The modern route to a judged or human-decided close is a staged `closeDecl` (`judged-floor` / `human-confirms` stage kinds), not this object form |
|
|
115
121
|
| `closeDecl` | **the AUTHORED close** `{ genre: "TYPES", lang: "js"\|"python", stages: [{ name, kind, params }], notes? }` | the ALTERNATIVE to `close`, and the point of the close-authoring rung: the user answers an interview and an LLM composes a DECLARATION over kinds whose implementations we own — never a script, never a shell fragment, never a new kind. **`close` and `closeDecl` are alternatives**: declaring both reds `close-duplicated` (two closes are two arbiters). It is HARD-class by construction (`CLASS_BY_CLOSE.declared`), so a locked verdict on one reds `close-hierarchy` as well as `request-red`. The declaration is validated by `validateCloseDecl`; the TREE-GROUNDED half of that gate (the path rule, and the scoped-job derivation that arms the F84 one-population law) is DEFERRED at spec-validation time — a job spec is validated with no repository in hand — and the runner re-runs it GROUNDED against the real seed before any stage and before any token. It stores the counting RULE and never a number (D12): there is no seed field, and `baseline: "seed"` is measured at each run's own HEAD |
|
|
116
122
|
| `checks` | **RETIRED** (PRD v1.28/v1.32) | hand-authored checks are gone, not merely discouraged: declaring `checks` reds `checks-derived` by name. The check menu is DERIVED from the close's own stages instead — see **Staged close** below. The hazard this removes is measured, not theoretical: job #5's three hand-written checks were re-implementations of three stages the close already ran, and a hand-carved copy can drift LENIENT (the worker passes the operator's ruler and fails the real inspection) |
|
|
117
123
|
| `tools` | optional unique subset of `TOOL_MENU` (14 verbs, below) | the CEILING every plan step's grant must fit inside (omitting it means the full menu — and the hash is taken over that RESOLVED form, so a `TOOL_MENU` widening flips an omitted-`tools` spec's hash and forces a re-sign; see `jobSpecHash`, MED-1); `run` is `LOCKED_TOOLS` and reds `request-red` — locked-but-listed, and the red IS the admission evidence the ledger tallies (a typo stays `invalid-value`). A ceiling of write-class and store-class verbs ONLY reds `invalid-value`: the scout surveys read-only, so it would be handed an empty menu and survey blind |
|
|
@@ -203,14 +209,15 @@ redo it. Write the goal from the close's own stage list, in the close's own word
|
|
|
203
209
|
a few explicit requirements rather than prose. Preflight already names every stage on the
|
|
204
210
|
`check-menu` spine event — read it back and check your goal against it before you sign.
|
|
205
211
|
|
|
206
|
-
**Close types and the hierarchy — the OBJECT form, which
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
(`human-confirms` inside a `closeDecl`)
|
|
213
|
-
|
|
212
|
+
**Close types and the hierarchy — the OBJECT form, which the plan flow only partially
|
|
213
|
+
supports** (a close is data, never code; verdict-class laundering is a named red
|
|
214
|
+
`close-hierarchy`). The go-forward shape is the staged list above; a `predicate` object is
|
|
215
|
+
legal shorthand for a one-stage list and the plan flow adapts it, but `gold`/`rubric`/`hitl`
|
|
216
|
+
validate and then refuse at runtime (`close-unsupported`) regardless of verdict class — the
|
|
217
|
+
plan flow has never executed an object close beyond `predicate`. `hitl` (LEGACY) is a STAGE
|
|
218
|
+
(`human-confirms` inside a `closeDecl`) and `soft-green`'s judged floor is likewise a STAGE
|
|
219
|
+
(`judged-floor` inside a `closeDecl`) — never close TYPES — so both OBJECT forms below stay
|
|
220
|
+
refused at runtime exactly as they were:
|
|
214
221
|
|
|
215
222
|
| type | fields (exact — extras red) | legal class |
|
|
216
223
|
|---|---|---|
|
|
@@ -484,17 +491,19 @@ signed `writeScope` alone, never a free-text fallback. Menus exported: `EXIT_TYP
|
|
|
484
491
|
The one layer where a human still wrote code. A close used to be a hand-written script
|
|
485
492
|
per patient; now the user PICKS A VERDICT CLASS, answers that class's questions, and an LLM
|
|
486
493
|
composes a DECLARATION over kinds whose implementations bareloop owns. **v1 admits exactly
|
|
487
|
-
ONE genre** (`TYPES`: a type checker stops complaining without breaking the tests)
|
|
488
|
-
|
|
489
|
-
is COUNTED.
|
|
494
|
+
ONE genre** (`TYPES`: a type checker stops complaining without breaking the tests) —
|
|
495
|
+
everything else refuses honestly, and every refusal is COUNTED.
|
|
490
496
|
|
|
491
497
|
**The verdict class is the USER's answer (PRD v1.57 §1), and it DRIVES the authoring.**
|
|
492
498
|
`verdictType` is a declared radio the preflight validates, never inferred:
|
|
493
|
-
`VERDICT_CLASSES` = `green` | `soft-green` | `hitl`, with `LOCKED_CLASSES` =
|
|
494
|
-
`soft-green`
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
`
|
|
499
|
+
`VERDICT_CLASSES` = `green` | `soft-green` | `hitl`, with `LOCKED_CLASSES` = **empty** —
|
|
500
|
+
`soft-green` shipped its judged floor in v0.12.0 (2026-08-23) and is fully admitted
|
|
501
|
+
alongside `green`; `hitl` is LEGACY (retired as a class by the 2026-08-17 design, PRD
|
|
502
|
+
Addendum v1.71) but still admitted too, since removal is a future breaking change. The
|
|
503
|
+
review door (`accept`/`rerun`/`pause`) that re-homes hitl's pause machinery is shipped and
|
|
504
|
+
live — always on for `soft-green`, opt-in for `green` via `reviewDoor: true` /
|
|
505
|
+
`--review-door`. A future LOCKED_CLASSES entry would still return a counted `request-red`
|
|
506
|
+
refusal at ADMISSION — before that class's questions are ever asked. The
|
|
498
507
|
pick is also a PROMISE: every catalogue kind carries the `verdictClass` it can honestly
|
|
499
508
|
render, `closeCeiling(declaration)` reports the highest class a declaration demands, and a
|
|
500
509
|
declaration ABOVE the pick is a `class-ceiling` red naming the kind that raised it (inert
|
|
@@ -505,7 +514,7 @@ a step, or test it without a provider.
|
|
|
505
514
|
|
|
506
515
|
| step | call | what it is |
|
|
507
516
|
|---|---|---|
|
|
508
|
-
| interview | `runInterview({ verdictType, answers, repoPath })` → `{ ok, answers, verdictType, refusal, reds }` | PURE — no model, no repo, no clock. THREE frozen question sets keyed by verdict class (`QUESTION_SETS`; `questionsFor(cls)` / `requiredAnswersFor(cls)`), and the interview asks NOTHING about a genre and NOTHING about the repository. **Ask the library for the set and its numbers — never hardcode a count or a slot number**: the green set has lost two slots since it was frozen (D13's genre confirm, then the repo question, dropped 2026-08-15 because `repoPath` is mandatory structured input and asking for it again invites a second, drifting answer for a fact the machine already holds), and it renumbers CONTIGUOUSLY from 1 each time rather than leaving a gap. Today the green set is five questions, answers keyed by number; the
|
|
517
|
+
| interview | `runInterview({ verdictType, answers, repoPath })` → `{ ok, answers, verdictType, refusal, reds }` | PURE — no model, no repo, no clock. THREE frozen question sets keyed by verdict class (`QUESTION_SETS`; `questionsFor(cls)` / `requiredAnswersFor(cls)`), all three LIVE as of softgreen module 3 — nothing is locked today (`LOCKED_CLASSES` is empty) — and the interview asks NOTHING about a genre and NOTHING about the repository. **Ask the library for the set and its numbers — never hardcode a count or a slot number**: the green set has lost two slots since it was frozen (D13's genre confirm, then the repo question, dropped 2026-08-15 because `repoPath` is mandatory structured input and asking for it again invites a second, drifting answer for a fact the machine already holds), and it renumbers CONTIGUOUSLY from 1 each time rather than leaving a gap. Today the green set is five questions, answers keyed by number; the LEGACY `hitl` set is those five byte for byte plus one more (what the signer is deciding when they look at the result — `human-confirms`' `ask`), which is the spread's next number and moves with a green-side deletion; the `soft-green` set is likewise those five plus two more — Q6 the signed rubric card (what separates a pass from a fail) and Q7 the frozen calibration set (one example to pass, one to fail) — the judged floor's two required inputs. `verdictType` and `repoPath` are STRUCTURED input, never parsed out of prose. Answers are scrubbed at INGEST |
|
|
509
518
|
| survey | `runAuthorScout({ workdir, provider, attempts?, ceilingUsd? })` → `{ state, facts, reason, meta, raw, raws, calls, budgetStop }` | a bounded READ-ONLY LLM survey. Read-only by MENU CONSTRUCTION (`AUTHOR_SCOUT_VERBS` = the full menu minus write-class and store-class verbs), 8 rounds, F59's reserved toolless final round. **`state: 'ABSENT'` means the scout did not complete — never "no special facts are needed"**, and a parsed `{}` is one of its five ABSENT routes. Up to `SCOUT_ATTEMPTS` (**3**, hardcoded — PRD v1.58) attempts: `attempts` is TIGHTEN-ONLY and CLAMPS rather than throws (floor **1**, because a scout that never ran is an ABSENT nobody can act on), the direction every cap in this system runs in. **A retry fires on the typed MALFORMED class alone** (`SCOUT_RETRY_CAUSES` = `empty` \| `unparseable`); what is excluded is excluded for a reason — `call-failed` covers transport and `truncated:max_tokens`, both provider-red with NO redraft; `short` is F59's cut-off population and already has its own instrument INSIDE the attempt; `non-object` and `empty-object` are valid JSON with wrong or vacuous content, which is a SEMANTIC failure, and F38/F39 measured what re-asking one buys (the same distribution, sampled twice) — that is the self-healing line, and it is not crossed here. The re-ask is TOOLLESS over the conversation the survey already produced (the repository was already read; only the emission was unreadable) and names the mechanical parse error and nothing else. **There is no JSON repair behind it and there never will be** — a repairer decides what the model MEANT and writes it down as though the model had said it, in the one artefact whose whole job is to be honest about what a repository contains. `meta.attempts` / `meta.attemptsAllowed` record what was paid for; every attempt is metered under its own label (`author-scout`, `author-scout#2`, …) and leaves its raw behind. **`ceilingUsd` is the operator's money ceiling** (PRD v1.62) — checked BETWEEN attempts and before F59's reserved round, so no paid call escapes it; `null`/absent is UNBOUNDED, and a non-null non-finite value THROWS (the shared `capStop` seam — see `authorClose` below). When it ends the ladder, `budgetStop` names which stop (`cap-halt` \| `pricing-red`) and a survey that was never asked for carries the typed cause `not-funded` — deliberately OUTSIDE `SCOUT_RETRY_CAUSES`, because a retry is precisely what the cap forbade |
|
|
510
519
|
| listing | `buildSeedListing({ workdir, seedRef, sourcePaths, testPaths })` | mechanical, `$0`, no model. `files` is the WHOLE tree (what the validator judges paths against); `block` is scoped to the survey's own paths and capped in ANNOUNCED tiers (what the prompt carries). Handing the validator the scoped half would make a job scoped to `src/` read as whole-tree and silently disarm the one-population law |
|
|
511
520
|
| authoring | `authorClose({ workdir, seedRef, lang, verdictType, answers, scout, listing, generate, ceilingUsd? })` | the grounded loop: author → validate → run EVERY stage at the seed → feed the MEASURED results back → revise, bounded at `MAX_REVISIONS` (2) — a passed `maxRevisions` is TIGHTEN-ONLY, so a caller may LOWER that ceiling and never buy more revise rounds than the constant (floor **0**: one authoring call with no revise round is a legal ask, and unlimited revising would launder thrash as adaptation) — early-stop on an unchanged declaration. The declaration is emitted through a SCHEMA-FORCED TOOL CALL (`declare_close`), never parsed out of prose; the feedback is EXECUTION OUTPUT only — no model ever reviews another model's close. The return carries **`raws`**: what every model call actually SAID, the scout's attempts absorbed together with the declaration's, in the cost book's own order and under the same labels it meters. Each is `{ label, attempt, bytes, trimmed, text, cause, reason }` through the ONE persist helper (`scrubRaw` — redacted over the ONE `SECRET_PATTERNS` inventory, since a raw is the record most likely in this system to carry a live credential; bounded at `RAW_PERSIST_MAX` (8000) with the trim ANNOUNCING its own full size, and the cut walked back off a continuation byte so a multi-byte character is never split). `raws` is present on EVERY path **including the `$0` preflight refusals** — the path that spends nothing more is exactly the one whose evidence used to vanish with the process. `iterations` records what each turn MEANT (declaration, validation, seed read); `raws` records what it SAID, and a malformation is only ever visible in the second. **`ceilingUsd` is the same operator ceiling the survey took** — the scout's spend is ABSORBED into this loop's cost book before its first call is weighed, so spend already incurred folds in and re-entering cannot silently widen it. It is checked immediately before EVERY paid call (the author call, each revise, and each malformed-emission retry). **A MALFORMED ceiling is an ERROR, not a silent unbounded run** (v1.64 §3): the seam every ceiling read goes through (`capStop`, `src/text.js`) THROWS on a non-null non-finite value — `'2.50'`, `NaN`, `Infinity`, `true`, `{}` — before the first paid call, and the throw propagates uncaught rather than being caught into an ABSENT survey, because a caught one would hand you the very silent-unbounded run it exists to prevent. `null`/omitted is the STATED operator choice for unbounded; `0` and negatives are finite, legal, and cap-halt immediately. The advertised ceiling and the enforced ceiling can therefore never be different numbers. A `cap-halt` here can arrive with `ok:true` — a close that was already validated and measured survives the money stop, exactly as a late provider casualty does |
|
|
@@ -1640,13 +1649,17 @@ in the ledger whatever the person then does with it.
|
|
|
1640
1649
|
write}` — the terminal registry write for a runner that drives `runJob` directly** (rather
|
|
1641
1650
|
than through `runReuse`, which writes its own rows). It is what gives that runner's review
|
|
1642
1651
|
door a row to release: without one, `accept` reaches `recordDoor` and reds `no-row-for-run`.
|
|
1643
|
-
STORAGE ONLY — nothing here selects, promotes or reuses a bridge.
|
|
1644
|
-
named `reason`: no `registryDir` (`no-registry` — the registry is operator-supplied, never
|
|
1652
|
+
STORAGE ONLY — nothing here selects, promotes or reuses a bridge. Three refusals, each with
|
|
1653
|
+
a named `reason`: no `registryDir` (`no-registry` — the registry is operator-supplied, never
|
|
1645
1654
|
conjured), `outcome !== 'green'` (`green-predates-run` for already-green — accept confirms a
|
|
1646
|
-
verdict, it never mints one — else `not-green`), no executed `plan` (`no-plan-executed`,
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
row is born
|
|
1655
|
+
verdict, it never mints one — else `not-green`), and no executed `plan` (`no-plan-executed`,
|
|
1656
|
+
R1). Every green class mints (hamr's ruling 2026-08-30): a `soft-green` row is born HELD —
|
|
1657
|
+
its learning credit is quarantined until a signer accepts at the door — and a `green`-class
|
|
1658
|
+
row is born RELEASED, because a machine's own close proved it and there was never a credit
|
|
1659
|
+
to quarantine; `quarantinesCredit(verdictType)` in `greenParts` is the one predicate, read
|
|
1660
|
+
off the record's own `verdictType`, never a flag. `door-accept` on a released row records
|
|
1661
|
+
the disposition and releases nothing — not an error; a run that earned no row at all still
|
|
1662
|
+
refuses `no-row-for-run`. `name` falls back to `job.job`. A
|
|
1650
1663
|
refused underlying write returns `{minted: false, reason: 'write-refused', write}` with the
|
|
1651
1664
|
reds on `write` — never a throw. Minting goes through the same cold-leg green write `runReuse`
|
|
1652
1665
|
uses (shape-fork rule and collision refusals included), so the two runners can never spell
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bareloop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Workflows that earn their own design, with receipts — 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/authorjob.js
CHANGED
|
@@ -290,8 +290,8 @@ export function runInterview({ answers, verdictType = null, repoPath = null, que
|
|
|
290
290
|
verb: 'non-green-verdict',
|
|
291
291
|
path: 'repoPath',
|
|
292
292
|
detail: 'This job has no code repository, so there is no seed to measure against and no changed set to read — '
|
|
293
|
-
+ 'nothing deterministic can decide whether it came back done. That needs a judged or a
|
|
294
|
-
+ '
|
|
293
|
+
+ 'nothing deterministic can decide whether it came back done. That needs a judged (soft-green) or a '
|
|
294
|
+
+ 'human close; this authoring flow drafts code-genre closes against a git seed only.',
|
|
295
295
|
}),
|
|
296
296
|
});
|
|
297
297
|
}
|
package/src/reuse.js
CHANGED
|
@@ -46,7 +46,7 @@ import { existsSync } from 'node:fs';
|
|
|
46
46
|
import { join } from 'node:path';
|
|
47
47
|
import { createHash } from 'node:crypto';
|
|
48
48
|
import { createRequire } from 'node:module';
|
|
49
|
-
import { loadRegistry, loadBridge, saveBridge, appendGreen, appendRed, mintBridge, registryExists, reuseEligibility, recordDoor,
|
|
49
|
+
import { loadRegistry, loadBridge, saveBridge, appendGreen, appendRed, mintBridge, registryExists, reuseEligibility, recordDoor, QUARANTINED_CODE } from './bridges.js';
|
|
50
50
|
import { renderListing, selectionPrompt } from './selection.js';
|
|
51
51
|
import { closeStagesOf } from './plan.js';
|
|
52
52
|
import { MIN_WALL_MS, jobSpecHash } from './job.js';
|
|
@@ -2128,7 +2128,7 @@ export function writeGreenRow({ registryDir, bridge = null, meta, record }) {
|
|
|
2128
2128
|
* `no-row-for-run`. This is the row, and STORAGE IS ALL IT IS — selection, promotion
|
|
2129
2129
|
* and reuse execution stay parked (layer-3-reuse). Nothing here reads a row back.
|
|
2130
2130
|
*
|
|
2131
|
-
*
|
|
2131
|
+
* THREE REFUSALS, each one a guard that already existed somewhere and is kept:
|
|
2132
2132
|
* - NO REGISTRY, no row. The registry path is operator-supplied and never
|
|
2133
2133
|
* conjured; without one the door says, in words, that nothing was released.
|
|
2134
2134
|
* - ALREADY-GREEN mints nothing. The close was satisfied before this run did
|
|
@@ -2136,16 +2136,15 @@ export function writeGreenRow({ registryDir, bridge = null, meta, record }) {
|
|
|
2136
2136
|
* the writing side rather than the door's.
|
|
2137
2137
|
* - A GREEN WITH NO PLAN mints nothing. The artifact that inherits is the one that
|
|
2138
2138
|
* RAN, and there is none (R1).
|
|
2139
|
-
*
|
|
2140
|
-
*
|
|
2141
|
-
*
|
|
2142
|
-
*
|
|
2143
|
-
*
|
|
2144
|
-
*
|
|
2145
|
-
*
|
|
2146
|
-
*
|
|
2147
|
-
*
|
|
2148
|
-
* `verdictType` off the record. Nothing here sets the flag.
|
|
2139
|
+
*
|
|
2140
|
+
* hamr's ruling 2026-08-30 (PRD open item #16, "green-class registry hole"): a
|
|
2141
|
+
* green-class run (mechanical close) now MINTS its row too, born RELEASED — a
|
|
2142
|
+
* machine proved it, so there is no credit to quarantine. This drops the fourth
|
|
2143
|
+
* refusal this function used to carry (`credit-not-held`, main's behaviour kept
|
|
2144
|
+
* from before the ruling): every outcome that reaches this line and clears the
|
|
2145
|
+
* three refusals above now mints, held or not. Whether the minted row IS held is
|
|
2146
|
+
* decided one level down, in `greenParts`, off `quarantinesCredit(verdictType)` —
|
|
2147
|
+
* the ONE spelling of "is this class held" — never here.
|
|
2149
2148
|
* @param {{registryDir: string|null|undefined, job: any, name: string|null,
|
|
2150
2149
|
* outcome: string, plan: any, record: any}} o
|
|
2151
2150
|
* @returns {{minted: boolean, reason: string|null, write: any|null}}
|
|
@@ -2156,7 +2155,6 @@ export function writeRunGreenRow({ registryDir, job, name, outcome, plan, record
|
|
|
2156
2155
|
return { minted: false, reason: outcome === 'already-green' ? 'green-predates-run' : 'not-green', write: null };
|
|
2157
2156
|
}
|
|
2158
2157
|
if (!isObj(plan)) return { minted: false, reason: 'no-plan-executed', write: null };
|
|
2159
|
-
if (!quarantinesCredit(job?.verdictType)) return { minted: false, reason: 'credit-not-held', write: null };
|
|
2160
2158
|
|
|
2161
2159
|
const target = isNonEmptyString(name) ? name : job.job;
|
|
2162
2160
|
const meta = {
|
package/types/reuse.d.ts
CHANGED
|
@@ -470,7 +470,7 @@ export function writeGreenRow({ registryDir, bridge, meta, record }: {
|
|
|
470
470
|
* `no-row-for-run`. This is the row, and STORAGE IS ALL IT IS — selection, promotion
|
|
471
471
|
* and reuse execution stay parked (layer-3-reuse). Nothing here reads a row back.
|
|
472
472
|
*
|
|
473
|
-
*
|
|
473
|
+
* THREE REFUSALS, each one a guard that already existed somewhere and is kept:
|
|
474
474
|
* - NO REGISTRY, no row. The registry path is operator-supplied and never
|
|
475
475
|
* conjured; without one the door says, in words, that nothing was released.
|
|
476
476
|
* - ALREADY-GREEN mints nothing. The close was satisfied before this run did
|
|
@@ -478,16 +478,15 @@ export function writeGreenRow({ registryDir, bridge, meta, record }: {
|
|
|
478
478
|
* the writing side rather than the door's.
|
|
479
479
|
* - A GREEN WITH NO PLAN mints nothing. The artifact that inherits is the one that
|
|
480
480
|
* RAN, and there is none (R1).
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
*
|
|
484
|
-
*
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
* `verdictType` off the record. Nothing here sets the flag.
|
|
481
|
+
*
|
|
482
|
+
* hamr's ruling 2026-08-30 (PRD open item #16, "green-class registry hole"): a
|
|
483
|
+
* green-class run (mechanical close) now MINTS its row too, born RELEASED — a
|
|
484
|
+
* machine proved it, so there is no credit to quarantine. This drops the fourth
|
|
485
|
+
* refusal this function used to carry (`credit-not-held`, main's behaviour kept
|
|
486
|
+
* from before the ruling): every outcome that reaches this line and clears the
|
|
487
|
+
* three refusals above now mints, held or not. Whether the minted row IS held is
|
|
488
|
+
* decided one level down, in `greenParts`, off `quarantinesCredit(verdictType)` —
|
|
489
|
+
* the ONE spelling of "is this class held" — never here.
|
|
491
490
|
* @param {{registryDir: string|null|undefined, job: any, name: string|null,
|
|
492
491
|
* outcome: string, plan: any, record: any}} o
|
|
493
492
|
* @returns {{minted: boolean, reason: string|null, write: any|null}}
|