bareloop 0.31.0 → 0.33.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +151 -0
  2. package/README.md +4 -1
  3. package/bareloop.context.md +232 -85
  4. package/bin/bareloop.mjs +0 -1
  5. package/package.json +1 -1
  6. package/src/authorflow.js +5 -3
  7. package/src/authorjob.js +3 -1
  8. package/src/authorrun.js +49 -11
  9. package/src/authorscout.js +10 -6
  10. package/src/bundlerun.js +266 -0
  11. package/src/cli.js +35 -357
  12. package/src/config.js +135 -0
  13. package/src/interviewrun.js +13 -4
  14. package/src/invoke.js +22 -0
  15. package/src/judged.js +5 -3
  16. package/src/keysfile.js +156 -0
  17. package/src/ledger.js +26 -0
  18. package/src/monthly.js +422 -0
  19. package/src/panel/authorroutes.js +61 -16
  20. package/src/panel/authorsession.js +46 -28
  21. package/src/panel/index.html +287 -13
  22. package/src/panel/server.js +58 -51
  23. package/src/panel/settingsroutes.js +230 -0
  24. package/src/planrun.js +7 -3
  25. package/src/providerrows.js +301 -0
  26. package/src/providers.js +3 -1
  27. package/src/run.js +7 -2
  28. package/src/runlist.js +92 -7
  29. package/src/source.js +8 -3
  30. package/src/u-watchdog.mjs +296 -0
  31. package/src/userrun.js +230 -54
  32. package/types/authorflow.d.ts +8 -2
  33. package/types/authorjob.d.ts +6 -1
  34. package/types/authorrun.d.ts +5 -0
  35. package/types/authorscout.d.ts +11 -2
  36. package/types/bundlerun.d.ts +26 -0
  37. package/types/cli.d.ts +2 -1
  38. package/types/config.d.ts +48 -0
  39. package/types/interviewrun.d.ts +5 -0
  40. package/types/invoke.d.ts +8 -0
  41. package/types/judged.d.ts +5 -1
  42. package/types/keysfile.d.ts +90 -0
  43. package/types/ledger.d.ts +14 -0
  44. package/types/monthly.d.ts +227 -0
  45. package/types/panel/authorroutes.d.ts +4 -2
  46. package/types/panel/authorsession.d.ts +7 -15
  47. package/types/panel/server.d.ts +10 -3
  48. package/types/panel/settingsroutes.d.ts +14 -0
  49. package/types/planrun.d.ts +13 -1
  50. package/types/providerrows.d.ts +229 -0
  51. package/types/run.d.ts +14 -1
  52. package/types/runlist.d.ts +66 -3
  53. package/types/source.d.ts +8 -3
  54. package/types/userrun.d.ts +54 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,157 @@ 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.33.0] — 2026-09-30
9
+
10
+ ### Added
11
+
12
+ - **Your own price, per key row.** `config.json` `keys.<ENV NAME>.priceInPerM` / `priceOutPerM` (USD per
13
+ 1M tokens, in and out; both or neither, each a finite number 0 or more) set what the model behind a key
14
+ costs. `ratesFor(provider, baseUrl, rows, model)` (`src/providerrows.js`) is the one lookup, on the same
15
+ row `keyNameFor` picks the key from. The run doors (`run-u` / `run <bundle>` / the panel via
16
+ `src/userrun.js`, `run-author`, the panel's authoring session) resolve it once at $0 and hand it to every
17
+ model call as bare-agent's `Loop({ rates })`: worker, scout and planner rounds, the drafter and confirm
18
+ turn, and the judge (priced at the judge model's own row; falls back to the worker's price when the model
19
+ names no row on that endpoint — `judgeRatesFor`). Priced rounds read `rateSource:'caller'`. A bad
20
+ price (one field, negative, non-number) refuses the run at $0 with "Nothing spent." and never falls back
21
+ to the guess. No price = no `rates` key = the built-in guess, unchanged. The run preview and run tail print
22
+ `price yours: in $0.006 / out $1.20 per 1M tokens (DEEPSEEK_API_KEY row)` when a price is set. New:
23
+ `runJob` / `runPlan` options `rates` / `judgeRates`; `runAuthorScout`, `authorCloseForJob`,
24
+ `makeLoopGenerate` and `defaultJudgeLoop` take an optional `rates`. The Settings screen field is a later
25
+ UI part; until then edit `config.json`. Past runs are not re-priced. Not covered: native (CLI) sessions
26
+ (they report their own cost) and the reuse engine (`runReuse`), which resolves no key row.
27
+
28
+ ### Changed
29
+
30
+ - **Monthly limit: a run claims its cap at start and holds it until it is done.** The run-start seam
31
+ writes the run's row FIRST (now carrying `pid` and `capUsd`; no lock file — records only), then reads
32
+ `runs.jsonl`: only the claims above its own row count, so whoever runs first holds. A run whose pid is
33
+ a live bareloop runner stays held at its full cap however quiet its spine (no more 10-minute silence
34
+ drop); a dead run's claim is closed by whoever finds it, with an attributed `settled` note
35
+ (`process gone`, first note wins); a run that does not fit appends a `released` entry and refuses
36
+ with the exact `Max $X (monthly limit)` text. A finished run appends its own `settled` entry. Old
37
+ rows without a `pid` keep the spine-mtime rule. The `resumingSpine` special case is gone (a resumed
38
+ leg's dead process already counts at its floor). `--resume`'s "is the old process alive" check now
39
+ recognises `bareloop run-u` / `bareloop run` and shares `isLiveRunner`.
40
+ `isLiveRunner` now needs a node executable (or a runner-named argv[0]) plus a runner-named argument, so a
41
+ recycled pid running e.g. `nvim` on a bareloop path no longer holds a dead run's cap; a claimed run (or, with no monthly limit, a listed one) that
42
+ exits at $0 before its spine exists is released (`reason: 'not started'`) instead of leaving a ghost row.
43
+ - **One runner: `bareloop run <bundle>` is now a thin door to the `run-u` engine.** The exported
44
+ bundle CLI no longer carries its own `runJob` caller (`doRun`) and provider wiring
45
+ (`buildProviders`); `src/bundlerun.js` keeps only the bundle checks (integrity, deps, envelope,
46
+ blessing before any key read), the tightened spec, the fresh worktree, the history row, the
47
+ first-green blessing and the merge hints. Consequences: a bundle can name any provider whose key
48
+ is in your keys file or env (the ANTHROPIC-only refusal is gone); the **monthly $ limit now
49
+ applies to a bundle** run (exit 2, nothing spent, no worktree); a missing key is the engine's
50
+ refusal, **exit 2 naming the key** (it used to print the bundle README and exit 0 — the README now
51
+ prints on the unblessed first-run screen); the close-fix cap for a bundle is run-u's 4 (was 3 —
52
+ one number for every caller); the outside watchdog now guards a bundle run; a bundle green mints
53
+ no bridge file; the engine's job-end tail read tolerates a torn spine line (as the bundle door's
54
+ already did).
55
+ - **`bareloop run <bundle> --resume <runid> [--repo <path>]`** — a halted bundle run resumes into
56
+ its own worktree through the engine's resume gates and spend fold. Each run leg writes
57
+ `runs/<runid>/run.json`; a resume's `history.jsonl` row carries `resumedFrom`. Proven with tests against a real git worktree and a scripted
58
+ provider; not run live.
59
+
60
+ ### Fixed
61
+
62
+ - **The outside watchdog now ships in the package (F205).** `scripts/u-watchdog.mjs` moved to
63
+ `src/u-watchdog.mjs`: `package.json` `files` omits `scripts/`, so an installed run spawned a guard
64
+ whose script did not exist and it died silently at startup.
65
+ - **The bare `bareloop` menu's "2 run" now honours the monthly limit.** It handed the bundle door no keys
66
+ home, so the limit, your price and the key-row choice were all off; it now gets the same home
67
+ `bareloop run <bundle>` does.
68
+ - **A halted bundle run's printed resume command keeps your tightened `--budget` / `--wall`.** It used to drop
69
+ them, so the next leg silently reverted to the signed ceiling. The money-halt hint for a bundle no longer
70
+ says to edit `budgetUsd` (a bundle's spec is manifest-hashed and cannot be edited).
71
+ After a MONEY halt the line does not repeat the exhausted `--budget` (chain spend is folded, so pasting it
72
+ halted again at once); it prints `--budget <more than $<spent so far>, at most $<signed budgetUsd>>` for the
73
+ person to fill in, and the lever list says to choose a larger `--budget` up to the signed amount. Nothing is
74
+ filled in automatically. Other halts keep your tightened `--budget` / `--wall` as before. Printed text only.
75
+ - **Printed commands no longer name scripts the package does not ship.** Entered through `bareloop run-u` /
76
+ `interview` / `author`, the approve, resume, pause and reopen lines (and the interview's run-author line and
77
+ the author's run-u line) now read `bareloop run-u …` etc.; `node scripts/*.mjs` is printed only from the
78
+ source-tree scripts. One owner for the spelling: `commandFor` in `src/invoke.js`.
79
+ - **Printed copy-paste commands name the key variable the run reads and carry `--registry` / `--workflow`.**
80
+ The approve and resume lines from `run-u` and `run-author` used to leave these out, so a pasted line could
81
+ read a different key row or drop the run-list registration (F207 b). Printed text only.
82
+
83
+ ### Removed
84
+
85
+ - `doRun`/`buildProviders` in `src/cli.js` and the `resumable: false` wiring for bundles (F130).
86
+
87
+ ## [0.32.0] — 2026-09-29
88
+
89
+ ### Added
90
+
91
+ - **Panel Settings (P4a)** — `~/.config/bareloop/.env` keys-file loader (shell env wins; keys
92
+ never reach the page), `config.json` (monthly $ limit, chosen key variables, Anthropic balance
93
+ note), a monthly $ limit that refuses a run start with `Max $X (monthly limit)` at both
94
+ `run-u` and the panel Sign & run, and a Settings view with a Money & limits tab and a Providers
95
+ tab (read, $0 Test, key-name dropdown). Add/edit/remove providers is P4b. There is no monthly
96
+ time limit. **The monthly limit is checked by `run-u` and the panel only — `bareloop run
97
+ <bundle>` does not check it.** An unreadable `config.json` refuses a run start; a month whose
98
+ spend is incomplete reads "at least".
99
+ - **Money & limits tab** — total and this-month spend and tokens as two header tiles ($ and
100
+ tokens, month first), a monthly $ limit that saves on change, and a per-provider breakdown
101
+ table ($, wall minutes, tokens; this month and to date). Wall time is job-start to job-end
102
+ when the run ended, otherwise an "at least" floor; unknown is shown as unknown, never 0. A
103
+ spine with no recorded provider is labelled "not recorded (model X)", never guessed from the
104
+ model name.
105
+ - **`replay-live --live-audit`** (`scripts/replay-live.mjs`) — opt-in: a $0 replay keeps its
106
+ sidecar in a scratch patient dir while it paces, so the panel's live tool-log fallback can be
107
+ seen on screen. Default replay is unchanged.
108
+ - **Panel Providers tab is the keys file (P4b)** — one Settings row per key in
109
+ `~/.config/bareloop/.env` that has a value (the file is created with five empty preset lines,
110
+ `ANTHROPIC_API_KEY` / `DEEPSEEK_API_KEY` / `OPENAI_API_KEY` / `GEMINI_API_KEY` / `LOCAL_API_KEY`,
111
+ when missing; an existing file is never edited). Each row has an editable Name (the model id Chat
112
+ uses), API shape (Anthropic / OpenAI-compatible / Gemini), Base URL, a $0 Test at that shape and
113
+ URL, and a total Tokens used; changes save to `config.json` `keys.<ENV NAME>`. A key value of
114
+ `null` counts as set and means "no real key" (local servers); the provider gets a placeholder,
115
+ and local rounds price as an `estimated` guess, never a real $0. Reload keys re-merges the
116
+ keys file onto the shell environment per request, so edits and removals take effect without a
117
+ restart. Chat's Model menu is the Settings
118
+ rows, and one owner (`src/providerrows.js`) resolves model to key + shape + URL for Chat, the
119
+ author doors and the run doors.
120
+ - **Providers tab names a shell-only key** — a preset key variable exported only in the shell
121
+ (not in the keys file) gets no row and no Chat model; the tab now says so under the table, by
122
+ name only (`GET /api/settings/providers` returns `shellOnly: string[]`, never a value).
123
+
124
+ ### Changed
125
+
126
+ - **Panel: no price is displayed** — the Providers table Price column and the Chat job card's
127
+ Token price field are removed. Display only: cost recording, the `estimated` provenance, spend
128
+ sums, caps and the monthly limit are unchanged.
129
+ - The Chat cap row is two equal full-width columns (Cap $ | Time cap) at every width.
130
+ - `config.json` `providers.<row>.key` (P4a key-name dropdown) is replaced by
131
+ `keys.<ENV NAME> = { name, shape, baseUrl }`; the hardcoded `PROVIDER_ROWS` and the panel's fixed
132
+ `MODEL_OPTIONS` are gone.
133
+ - **Monthly limit counts running jobs at their full cap** — a run still in flight (no `job-end`,
134
+ spine written to within the panel's died window) is counted against the limit at its own leg
135
+ cap, not its spend so far, so two runs cannot both start against a limit only one fits. A died
136
+ run still counts its floor. The Money tab's "$ month" stays real spend.
137
+
138
+ ### Fixed
139
+
140
+ - **Monthly limit no longer double-counts a resume** — `run-u --resume` on a leg killed within
141
+ `DIED_MTIME_MS` reserved the old leg at its full cap AND asked for the remainder, so a resume
142
+ that fit was refused; the resumed leg now counts its real spend only
143
+ (`checkMonthlyRoom({ resumingSpine })`).
144
+ - **`POST /api/settings/money` no longer clears the limit on a bad body** — an empty or
145
+ unparseable body, or JSON without the `monthlyLimitUsd` key, is a 400 and leaves `config.json`
146
+ alone; only an explicit `null` or blank clears the limit.
147
+ - **A bad `monthlyLimitUsd` no longer reads as "no limit"** — a `monthlyLimitUsd` present in
148
+ `config.json` but not a number above 0 (`"50"`, `-5`, `0`, `true`, `{}`) now refuses the run
149
+ start and shows as a config problem on the Money tab, like an unparseable file. Absent or
150
+ `null` still means no limit.
151
+ - **Panel author routes: `jobsDir` and body size** — the name-collision check's `jobsDir` test
152
+ seam is now server-side only (it was readable off the client's job card, so any
153
+ `/api/author/start` body could repoint it), and POST bodies over 1 MiB get 413 and the request
154
+ is destroyed (the reader had no cap and ran before the click guard).
155
+ - **Providers Test** — a connection failure now reads "nothing answering at <URL>"; the Test
156
+ cell keeps a fixed width and wraps its result. **Tokens used** counts older model-only spines
157
+ toward the row whose Name exactly equals the model.
158
+
8
159
  ## [0.31.0] — 2026-09-29
9
160
 
10
161
  ### Added
package/README.md CHANGED
@@ -143,7 +143,10 @@ bareloop run ./my-maintainer.bareloop --repo /path/to/checkout --approve <bundle
143
143
  `export` only ships a job that has already earned a real green — it refuses to bundle an
144
144
  unproven draft. The first `run` on a new machine asks you to approve the bundle's printed
145
145
  hash; once that run goes green, later runs need no re-approval as long as the bundle stays
146
- unchanged. Every run works in its own fresh git worktree and leaves the merge to you. Full
146
+ unchanged. Every run works in its own fresh git worktree and leaves the merge to you. `bareloop
147
+ run` is a door to the same engine as `bareloop run-u`, so it uses any provider your keys file
148
+ has, honours the monthly limit, and a halted run can be continued with
149
+ `bareloop run <bundle> --resume <runid>`. Full
147
150
  contract — flags, approval/blessing rules, exit codes — in
148
151
  [`bareloop.context.md`](bareloop.context.md).
149
152