bareloop 0.14.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 +218 -0
- package/bareloop.context.md +374 -49
- package/package.json +2 -2
- package/src/authorjob.js +2 -2
- package/src/codeversion.js +155 -0
- package/src/index.js +12 -0
- package/src/ledger.js +1 -1
- package/src/promptregisters.js +93 -0
- package/src/replay.js +1212 -0
- package/src/reuse.js +11 -13
- package/src/run.js +14 -0
- package/types/codeversion.d.ts +18 -0
- package/types/index.d.ts +2 -0
- package/types/ledger.d.ts +14 -0
- package/types/promptregisters.d.ts +31 -0
- package/types/replay.d.ts +195 -0
- package/types/reuse.d.ts +10 -11
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,224 @@ 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
|
+
|
|
85
|
+
## [0.15.0] — 2026-08-27
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- **Generic run replay** (PRD build-list #6): `replayRun`/`formatReplay` (`src/replay.js`)
|
|
90
|
+
reconstruct one run's whole story from its spine JSONL + gate-audit sidecar. The single-run
|
|
91
|
+
report is a signed layout (hamr, 2026-08-25): a header block (`goal:`/`shape:`/`signed:`/
|
|
92
|
+
`branch:`/`outcome:`/`spent:`, absent fields printing the literal `none recorded`, never
|
|
93
|
+
blank or a fabricated `0`), a `TIMELINE (steps)` or `TIMELINE (iterations — loop-shape run)`
|
|
94
|
+
section with its own column-header row and per-row time/cost (wall, `$` — a `null` `costUsd`
|
|
95
|
+
anywhere in a row's window makes that row's spend `unknown (N unpriced rounds)`, never `0` or
|
|
96
|
+
a partial sum stamped exact) and a `↳ tripped:`/`↳ close:` line under any row an escalation or
|
|
97
|
+
close fell inside, a `CLOSE` section (never omitted — `none — the run ended before any close
|
|
98
|
+
ran` when nothing ever closed; picks the run's REAL final close by seq, never by record type —
|
|
99
|
+
an early `outer-close` precheck reading red must not shadow a LATER fix-loop close-verdict that
|
|
100
|
+
went satisfied), `ENDING` (last record + 3 before it, plus an out-of-window escalation), the
|
|
101
|
+
`BEHAVIOUR` block, and a `MEMORY-CACHE` line always printed (`not armed on this run` when
|
|
102
|
+
absent — absence is never silent). Stop reason is `category — decision — detail` off the last
|
|
103
|
+
escalation, so a run's actual failure text (a TLS "bad record mac", a specific mypy error)
|
|
104
|
+
rides onto the report instead of just the generic per-category decision prose. A step id that
|
|
105
|
+
recurs after a replan is split per OCCURRENCE, never merged into one pooled row. `--all <dir>`
|
|
106
|
+
is name-agnostic (a spine is identified by a `job-start`/`run-start` record in its content,
|
|
107
|
+
never a filename convention) and prints a fixed-column, ALIGNED table (never CSV) — `id job
|
|
108
|
+
shape outcome spend wall steps reason`, `reason` built from `detail` only (never `decision`,
|
|
109
|
+
cut at 60 chars) — flagging any non-spine `.jsonl` as `<name> not-a-spine` rather than dropping
|
|
110
|
+
it. A RESUMED run's `job-end.spentUsd` is a CHAIN total (prior legs folded in) that can never
|
|
111
|
+
equal this one file's own rounds (measured: `u-msf70nei` header `$5.3389` vs its own 55 rounds
|
|
112
|
+
summing to `$1.2127`) — the header now prints both, each labelled, plus a `resumed:` line
|
|
113
|
+
(keyed on `job-start.priorSpentUsd`, never on the narrower `resume-seed` record alone — 4 real
|
|
114
|
+
archived runs carry a real fold with no resume-seed record at all). A non-resumed run's own
|
|
115
|
+
spend disagreeing with its summed rounds is a genuine finding and prints as a `MISMATCH`, never
|
|
116
|
+
hidden (measured: 0 of the archive's non-resumed runs trip it). `--all` marks a resumed row
|
|
117
|
+
with a trailing `*` and one footnote line when the listing holds any. Reuses `runBehaviour`/the
|
|
118
|
+
`memory-cache` readout rather than reimplementing either. Reads only, mints no verdict, writes
|
|
119
|
+
nothing to the spine. `job-start` (`src/run.js`) now also carries `verdictType` (the spec's
|
|
120
|
+
required verdict class) and `model` (when the shell-owned provider binding itself carries one)
|
|
121
|
+
— PRD TODO #20, blessed verbatim by hamr the same day. The header prints `class:`/`model:`
|
|
122
|
+
right after `shape:` (`not recorded (pre-F117 spine)` / `not recorded` on an older archive or
|
|
123
|
+
a provider with no `.model`), and `--all` gains `class`/`model` columns (`model` kept FULL,
|
|
124
|
+
never truncated).
|
|
125
|
+
- **Prompt-commit shape — a check, not convention** (PRD build-list #5, TODO #8, Q9 answered
|
|
126
|
+
by hamr 2026-08-25): a commit that changes a prompt register (a model-facing
|
|
127
|
+
system/strategy/instruction string a worker or judge reads) must now say, in its own
|
|
128
|
+
message, three labelled things — `Failure:` what caused the change, `Addresses:` what it
|
|
129
|
+
addresses, `Corrects:` what it corrects. `src/promptregisters.js` (`PROMPT_REGISTERS`,
|
|
130
|
+
`isPromptFile`, both exported from `bareloop`'s root) is the ONE inventory: 7 files carry
|
|
131
|
+
real prompt content (`src/authorscout.js`, `src/authorflow.js`, `src/judged.js`,
|
|
132
|
+
`src/cardauthor.js`, `src/readshim.js`, `src/tools.js`, `src/planrun.js`) — more than double
|
|
133
|
+
the 8 named consts a first grep found, once module-private consts and inline
|
|
134
|
+
template-literal prompt builders (`scoutPrompt()`, `cardCasesPrompt()`, `locatePrompt()`,
|
|
135
|
+
`strategyFor()`) are counted; the check is file-scoped precisely because a const-scoped one
|
|
136
|
+
would have silently missed those. Enforcement is LOCAL ONLY — wired into `npm test`
|
|
137
|
+
(`scripts/prompt-commit-check.mjs --range origin/main..HEAD`), never into any
|
|
138
|
+
`.github/workflows/*` file (ask-first, untouched); an unresolvable range (no `origin`, no
|
|
139
|
+
fetch) is a printed SKIP at exit 0, never a violation. Pure decision logic lives in
|
|
140
|
+
`scripts/promptcommitlib.mjs`, neither of which ships (`scripts/` is outside
|
|
141
|
+
`package.json`'s `files`). hamr's same-day addition: the `Failure:` line must also cite
|
|
142
|
+
the RUN that caused the change (`run <id>` / `run u-<id>`, `\brun\s+(u-)?[a-z0-9]{6,12}\b`
|
|
143
|
+
— alphabet/length measured against 231 real archived spine ids, every one exactly 8
|
|
144
|
+
lowercase-alnum chars), failing with a distinct message
|
|
145
|
+
(`FAILURE_NEEDS_RUN_REF`) when absent; format only, never checked against a real spine
|
|
146
|
+
file.
|
|
147
|
+
- **Run→code stamp** (F118, the parked half of the same day's prompt-commit build, closed
|
|
148
|
+
same day on hamr's go): the prompt-commit check closes commit→run; this closes run→code.
|
|
149
|
+
`src/codeversion.js`'s `codeVersion()` is a pure, $0, no-shell reader — `version` from
|
|
150
|
+
bareloop's own `package.json`, `sha` from `.git/HEAD` (loose ref, falling back to
|
|
151
|
+
`packed-refs`) ONLY when a `.git` directory exists at the package root (a dev checkout;
|
|
152
|
+
an npm install has none), `dirty` always `null` (uncommitted-changes state cannot be
|
|
153
|
+
known without a shell — reported as unknown, never faked as `false`). `job-start`
|
|
154
|
+
(`src/run.js`) now also carries `code: {version, sha}`. `replayRun`/`formatReplay`
|
|
155
|
+
(`src/replay.js`) read it: a `code:` line right after `model:` — `bareloop 0.14.0 @
|
|
156
|
+
43f2812` / `@ sha unknown` / `not recorded (pre-F118 spine)`; no new `--all` column
|
|
157
|
+
(hamr's index is already full). The library never grows a shell seam to answer this —
|
|
158
|
+
`run` stays the one locked verb.
|
|
159
|
+
- **Replay surfaces transport retries and floor reasons** (F119, live-proven the same day
|
|
160
|
+
a real run — `u-mt8yk53k` — fired the retry seam twice): `replayRun`/`formatReplay`
|
|
161
|
+
window `transport-retry` records into the step/iteration occurrence they fell inside
|
|
162
|
+
(same `seq` windowing as `worker-round`), printing `↳ transport retry ×N (recovered|not
|
|
163
|
+
recovered|partially recovered) — <error>` under that row; a retry outside every window
|
|
164
|
+
prints as `transport retries outside steps: N` under the `TIMELINE` header instead. The
|
|
165
|
+
header's `spent:` line, whenever `spendComplete:false`, now appends `· floor because:
|
|
166
|
+
<reason(s)>` — derived from the spine, never guessed: `transport retry ×N`, `unpriced
|
|
167
|
+
round(s)`, `cut mid-call`, `stall`, `prior leg floor`, every cause that shows real
|
|
168
|
+
evidence, or `floor (reason not in spine)` when none can be derived. `--all` adds no
|
|
169
|
+
column: a run carrying any retry gets ` ⟲N` appended to its outcome word (same posture
|
|
170
|
+
as the resumed `*`), with one footnote when the listing holds any. Report-only — reads
|
|
171
|
+
existing `transport-retry`/`wall-halt`/`stall`/`job-start` records, writes nothing.
|
|
172
|
+
|
|
173
|
+
### Fixed
|
|
174
|
+
|
|
175
|
+
- **Leaked tmp dirs from `npm test`** (same class that filled `/tmp` tmpfs on 2026-08-25 and
|
|
176
|
+
blocked a build): `tests/codeversion.test.js`'s real-worktree test tracked only the `wt`
|
|
177
|
+
subdirectory passed to `git worktree remove`, never the `mkdtemp`-created parent, so every run
|
|
178
|
+
left an empty `codeversion-worktree-*` dir behind; its `after()` now also prunes stale worktree
|
|
179
|
+
metadata when `remove` fails and `rmSync`s the tracked dir unconditionally, plus the mkdtemp
|
|
180
|
+
parent is now itself tracked and removed. `tests/ralph.test.js`'s cwd-threading test created a
|
|
181
|
+
`ralph-cwd-*` repo with no cleanup at all, and its cwd-relative-close test likewise leaked a
|
|
182
|
+
`close-cwd-*` and a `close-cwd-other-*` dir per run; added a per-test `after(() => rmSync(...))`
|
|
183
|
+
for each, matching the file's existing top-level cleanup pattern.
|
|
184
|
+
- **`codeversion.test.js` false-red on PR checkouts** (F118 addendum): the HEAD-sha test's own
|
|
185
|
+
precondition assumed a symbolic ref, but `actions/checkout` leaves a PR checkout's HEAD
|
|
186
|
+
DETACHED at the merge commit, so the precondition threw before the module under test ever
|
|
187
|
+
ran — `src/codeversion.js` itself already handled the detached case correctly. Test-only fix:
|
|
188
|
+
the precondition now resolves a bare 40-hex `.git/HEAD` the same way `codeVersion()` does, plus
|
|
189
|
+
a new deterministic fake-package-root test that exercises the detached case without depending
|
|
190
|
+
on the checkout's own HEAD state.
|
|
191
|
+
- **Review of PR #23 (2026-08-26), 7 items fixed**: (1) `replayRun`'s spend totals
|
|
192
|
+
(`src/replay.js`) counted only `worker-round`, silently dropping a close's own `judge-round`
|
|
193
|
+
spend and native `worker-turn` attribution out of every total — now filters on the canonical
|
|
194
|
+
`SPEND_RECORD_TYPES` (newly exported from `src/ledger.js`), including the per-step window,
|
|
195
|
+
which no longer requires a `.phase` match for records (like `judge-round`) that never carry
|
|
196
|
+
one. (2) `scripts/promptcommitlib.mjs`'s run-reference regex accepted plain prose ("run
|
|
197
|
+
failed" satisfied its `{6,12}` margin outright) — tightened to the measured exact shape
|
|
198
|
+
(`{8}`); a proposed additional per-id digit requirement was investigated and REJECTED (23 of
|
|
199
|
+
130 re-sampled real archived ids carry no digit, `msdsmkid` among them). (3)
|
|
200
|
+
`src/codeversion.js` read `sha: null` inside any real git worktree (`.git` there is a FILE,
|
|
201
|
+
`gitdir: <path>`, not a directory) — now resolves the pointer file and the worktree's
|
|
202
|
+
`commondir` to find HEAD/refs correctly. (4) `replayRun`'s `resumed` flag missed a genuine
|
|
203
|
+
$0-floor resume (`priorSpentUsd: 0` is still a real fold per `src/run.js:328`'s own doctrine)
|
|
204
|
+
— now keys on the field's presence, not `> 0`. (5) `scripts/run-replay.mjs --all` opened
|
|
205
|
+
every run's gate-audit sidecar despite never using the fields it feeds — no longer opens it
|
|
206
|
+
in `--all` mode (`--all` output on `aurora-u-bareloop` confirmed byte-identical before/after).
|
|
207
|
+
(6) the steps/iterations windowing logic in `replayRun` was duplicated inline twice — extracted
|
|
208
|
+
into one shared `buildOccurrenceMetrics` helper (replay output on `u-msdsmkid`, `u-msf70nei`,
|
|
209
|
+
`u-mt8yk53k` confirmed byte-identical before/after). (7) `npm test`'s prompt-commit check
|
|
210
|
+
(`origin/main..HEAD`) inspects NOTHING after a direct push to main, because the push itself
|
|
211
|
+
advances `origin/main` to match `HEAD` — `scripts/prompt-commit-check.mjs` now falls back to
|
|
212
|
+
`HEAD~1..HEAD` on that exact condition and prints that it did; a multi-commit direct push
|
|
213
|
+
still only re-covers the last commit (needs `github.event.before`, a `.github/` edit — out of
|
|
214
|
+
scope here, ask-first).
|
|
215
|
+
- **Release-gate findings (2026-08-27)**: `scripts/prompt-commit-check.mjs`'s `--range` value
|
|
216
|
+
was passed to `git rev-list` positionally with no way to disambiguate it from an option — an
|
|
217
|
+
option-shaped value (e.g. `--output=<path>`) was parsed by git as its own flag (verified: a
|
|
218
|
+
`--` separator does NOT fix `rev-list`, unlike `show`/`diff-tree`, since it treats everything
|
|
219
|
+
after it as a path filter, not a revision range); the script now rejects any `--range` value
|
|
220
|
+
starting with `-` up front, before any git call runs. Also corrected the fallback's printed
|
|
221
|
+
limitation and code comment: on a MERGE commit, `HEAD~1` is the first parent, so
|
|
222
|
+
`HEAD~1..HEAD` covers the merge PLUS every commit unique to the merged branch (measured on
|
|
223
|
+
this repo's own `4904d76`: 10 commits, not 1) — the prior wording ("only re-covers the last
|
|
224
|
+
commit") was only accurate for a LINEAR multi-commit push, which is now stated explicitly.
|
|
225
|
+
(`src/replay.js`'s phase-less step-window filter was also reviewed and confirmed correct by a
|
|
226
|
+
new adversarial synthetic test — no code change there.)
|
|
227
|
+
|
|
10
228
|
## [0.14.0] — 2026-08-25
|
|
11
229
|
|
|
12
230
|
### Added
|