bareloop 0.46.0 → 0.47.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/types/learn.d.ts CHANGED
@@ -193,7 +193,7 @@ export function foldCards(cards: Card[]): Card[][];
193
193
  * @typedef {object} Ledger
194
194
  * @property {1} version
195
195
  * @property {Row[]} rows
196
- * @property {Pending[]} pending rubric cards held until a human Accept (NOT counted, NOT readable)
196
+ * @property {Pending[]} pending holds written by v0.46.x for rubric runs, released by the human Accept (NOT counted, NOT readable); new runs never write one
197
197
  * @property {Card[]} suspect CHECK-SUSPECT cards, listed, newest last
198
198
  * @property {Record<string, {at: string, noise: string|null, cards: number, suspect: number, thin: number}>} health per run (idempotent by run id)
199
199
  */
@@ -208,8 +208,9 @@ export function lessonOf(c: Card): string;
208
208
  * Fold ONE run's cards into the ledger. Pure: returns a new ledger.
209
209
  *
210
210
  * +1 per RUN per row: the run's own cards are folded into lessons first, and a row whose `runIds` already holds the
211
- * run id is never counted twice (a resumed run, one id, never double counts). A matching lesson replaces the row's
212
- * sample, bumps the model count and appends the run id (a row last seen 56+ days ago counts +1 and is read again);
211
+ * run id is never counted twice (a resumed run, one id, never double counts) but IS refreshed: the resumed leg's card
212
+ * replaces the sample, lesson, key, lastSeen, hash and place (a leg-1 NEVER FIXED row becomes the leg-2 FIXED one). A
213
+ * matching lesson replaces the row's sample, bumps the model count and appends the run id (a row last seen 56+ days ago counts +1 and is read again);
213
214
  * otherwise it opens a new row at count 1. NEVER FIXED cards count like FIXED ones (RULING 3). A workflow row of
214
215
  * another signed hash is never matched here: the new version opens its own rows. Nothing is ever deleted or stamped.
215
216
  * @param {Ledger} ledger
@@ -234,8 +235,8 @@ export function countLedger(ledger: Ledger, { runid, cards, workflow, place, spe
234
235
  */
235
236
  export function climb(rows: Row[]): Row[];
236
237
  /**
237
- * A rubric run's cards are HELD, not counted, until a human Accept (the existing quarantine is the rule). Replaces
238
- * an earlier hold for the same run id (a resumed run re-derives its cards). Pure.
238
+ * Hold a run's cards until a human Accept. NO LONGER CALLED for new runs (v1.112: a rubric run's lessons count at run
239
+ * end); kept so a hold already in a ledger file still has a writer for tests and a reader in {@link releasePending}. Pure.
239
240
  * @param {Ledger} ledger
240
241
  * @param {{runid: string, cards: Card[], workflow: string, place: string|null, specHash: string|null, at: string}} o
241
242
  * @param {Date} now @returns {Ledger}
@@ -249,7 +250,7 @@ export function holdPending(ledger: Ledger, { runid, cards, workflow, place, spe
249
250
  at: string;
250
251
  }, now: Date): Ledger;
251
252
  /**
252
- * The human Accept releases a held rubric run: its cards count now (trust `rubric`). Only forward, only here. A hold
253
+ * The human Accept releases an OLD hold (written by v0.46.x; new runs write none): its cards count now (trust `rubric`). Only forward, only here. A hold
253
254
  * older than 60 days is dropped uncounted. Idempotent (no hold = nothing to do; run ids stop a double count).
254
255
  * @param {Ledger} ledger @param {string} runid @param {Date} now
255
256
  * @returns {{ledger: Ledger, released: number}}
@@ -510,7 +511,7 @@ export type Ledger = {
510
511
  version: 1;
511
512
  rows: Row[];
512
513
  /**
513
- * rubric cards held until a human Accept (NOT counted, NOT readable)
514
+ * holds written by v0.46.x for rubric runs, released by the human Accept (NOT counted, NOT readable); new runs never write one
514
515
  */
515
516
  pending: Pending[];
516
517
  /**
@@ -22,9 +22,8 @@ export function readLedger(home?: string): {
22
22
  */
23
23
  export function writeLedger(ledger: import("./learn.js").Ledger, home?: string): string;
24
24
  /**
25
- * Fold ONE finished run into the ledger on disk: a deterministic job's cards COUNT now; a rubric job's cards are HELD
26
- * until a human Accept (they are written to `pending`, never counted, never readable). The run's health line is recorded
27
- * either way. Never throws on a bad ledger file: it reports `problem` and writes nothing.
25
+ * Fold ONE finished run into the ledger on disk: every run's cards COUNT now, rubric jobs too (trust kept on new rows;
26
+ * v1.112). `held` is always 0 (kept in the shape for callers). The run's health line is recorded. Never throws on a bad ledger file: it reports `problem` and writes nothing.
28
27
  * @param {{home?: string, runid: string, build: import('./learn.js').CardBuild, workflow: string, place: string|null, specHash: string|null, trust: 'deterministic'|'rubric', at: string, now?: Date}} o
29
28
  * @returns {{wrote: boolean, counted: number, held: number, problem: string|null}}
30
29
  */
@@ -45,7 +44,7 @@ export function foldRunIntoLedger({ home, runid, build, workflow, place, specHas
45
44
  problem: string | null;
46
45
  };
47
46
  /**
48
- * The human Accept at the review door: release the run's held rubric cards so they count (only forward, only here).
47
+ * The human Accept at the review door: release a hold an older version wrote for the run so it counts (new runs write none; only forward, only here).
49
48
  * @param {{home?: string, runid: string, now?: Date}} o
50
49
  * @returns {{released: number, problem: string|null}}
51
50
  */
@@ -66,7 +65,7 @@ export function releaseRun({ home, runid, now }: {
66
65
  export function learningHintsOn(home?: string): boolean;
67
66
  /**
68
67
  * THE RUN-END TALLY ($0, code only, no model): turn the finished run's whole record into cards and fold them into the
69
- * ledger (a rubric job's are held until Accept). Called once from the one engine's run-end block (src/userrun.js
68
+ * ledger (a rubric job's count too, trust kept). Called once from the one engine's run-end block (src/userrun.js
70
69
  * `execute`, shared by the panel, the CLI and the bundle runner), inside its own try/catch: it is a record, never a verdict,
71
70
  * and can never change a run's outcome, exit code or spend. It runs whether the hints setting is on or off.
72
71
  * @param {{home?: string, runid: string, events: any[], auditFiles?: string[], spec: any, specHash: string|null, workdir: string|null, trust: 'deterministic'|'rubric', now?: Date}} o
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @param {string} target a folder path or a URL
3
+ * @param {{ platform?: string, spawnFn?: ((cmd: string, args: string[], o: object) => any)|null, underTest?: boolean }} [opts]
4
+ * `spawnFn: null` = no opener at all (resolves false); undefined = the real spawn, unless `underTest`, which spawns nothing
5
+ * unless a test injected one
6
+ * @returns {Promise<boolean>} true once the opener process has started
7
+ */
8
+ export function openInOs(target: string, opts?: {
9
+ platform?: string;
10
+ spawnFn?: ((cmd: string, args: string[], o: object) => any) | null;
11
+ underTest?: boolean;
12
+ }): Promise<boolean>;
@@ -87,6 +87,7 @@ export function createAuthorRoutes(opts: {
87
87
  handle: (req: import("node:http").IncomingMessage, res: import("node:http").ServerResponse, pathname: string, body: any) => boolean;
88
88
  sessions: Map<string, any>;
89
89
  headless: Map<string, any>;
90
+ openDrafts: () => number;
90
91
  startSession: (card: any, reuse: {
91
92
  spec: any;
92
93
  workflowKey: string;
@@ -1,3 +1,7 @@
1
+ /** bareloop's own version, from its package.json (read each time the page is served); 'unknown' if it cannot be read, never a guess
2
+ * @param {string} [file] test seam: another package.json
3
+ * @returns {string} */
4
+ export function packageVersion(file?: string): string;
1
5
  /**
2
6
  * `[✓]`/`[✗]`/`[■]`/`[▶]` — the ONLY vocabulary a result is ever rendered in
3
7
  * (auto-memory `ui-verdict-words.md`: never the words green/red/soft-green
@@ -288,6 +292,20 @@ export function runsListPayload(opts?: {
288
292
  needsYouDays: 7;
289
293
  }>;
290
294
  };
295
+ /**
296
+ * The runs list as the panel builds it, for a caller with no panel running (the launcher header): the same `runsListPayload` over a
297
+ * schedule door built read-only (no scheduler, no timer), so Needs you = the rows tagged `needs` + the schedules that gave up, ONE owner.
298
+ * @param {{ home?: string, now?: number, env?: Record<string, string|undefined> }} [opts]
299
+ * @returns {{ runs: any[], gaveUp: any[] }}
300
+ */
301
+ export function runsListForCount(opts?: {
302
+ home?: string;
303
+ now?: number;
304
+ env?: Record<string, string | undefined>;
305
+ }): {
306
+ runs: any[];
307
+ gaveUp: any[];
308
+ };
291
309
  /**
292
310
  * T Part 8 — what the Accept route needs: the run's row, whether its runner is alive, whether it waits at its review door
293
311
  * ({@link doorWaiting}), and the signed spec it was judged by (the file and hash `run-u --door --approve` takes).
@@ -778,6 +796,12 @@ export function handleRequest(req: import("node:http").IncomingMessage, res: imp
778
796
  importRoutes?: ReturnType<typeof createImportRoutes>;
779
797
  schedules?: ReturnType<typeof createScheduleDoor>;
780
798
  }): void;
799
+ /**
800
+ * The ONE spelling of the panel's own address (the launcher prints and opens it too).
801
+ * @param {number} boundPort
802
+ * @returns {string}
803
+ */
804
+ export function panelUrl(boundPort: number): string;
781
805
  /**
782
806
  * Start the panel server. Binds `127.0.0.1` ONLY. A taken port is a LOUD,
783
807
  * non-zero-exit failure — this never falls back to another port (see file
@@ -1,3 +1,11 @@
1
+ /**
2
+ * ONE spelling of "this run's outcome is a green that can be reused" (the Reuse picker, the Reuse start/prefill, the Ended block's
3
+ * next line). hamr 2026-10-15: an `already-green` (fixed before any work) counts. `satisfied` is a close verdict, never a run outcome.
4
+ * The SCHEDULE gate (schedules.js greenFor) deliberately stays on a real `green` only (T3).
5
+ * @param {string|null|undefined} outcome
6
+ * @returns {boolean}
7
+ */
8
+ export function isReusableGreen(outcome: string | null | undefined): boolean;
1
9
  /**
2
10
  * The status of one run.
3
11
  * @param {{outcome: string|null|undefined, died?: boolean, category?: string|null, moneyHalt?: boolean}} o
@@ -8,21 +8,6 @@
8
8
  * question.
9
9
  * @param {any} params @returns {string|null} */
10
10
  export function cmdKey(params: any): string | null;
11
- export function stageQuestionText({ kind, params, genre, suiteCmdKeys, }: {
12
- kind: any;
13
- params: any;
14
- genre: any;
15
- suiteCmdKeys: any;
16
- }): string | null;
17
- /**
18
- * Stage name to its plain question, off a signed spec's `closeDecl.stages` — the one pass that gathers every
19
- * `command-exit` stage's cmd+args FIRST (so the failing-test-count half of `suite-green`'s pair can be told from a
20
- * genuine typecheck stage) and then asks {@link stageQuestionText} per stage. `null` for a stage with no honest
21
- * question; an empty map for a spec with no declared stages.
22
- * @param {any} spec
23
- * @returns {Map<string, string|null>}
24
- */
25
- export function stageQuestionsByName(spec: any): Map<string, string | null>;
26
11
  /**
27
12
  * THE PLAIN-QUESTION OWNER (plain-checks build, 2026-09-28, hamr's ruling:
28
13
  * the "checks N/M" headline is WITHDRAWN — "confusing, reads like 6 failed
@@ -85,6 +70,22 @@ export function stageQuestionsByName(spec: any): Map<string, string | null>;
85
70
  * @param {{kind: string|null, params: any, genre: string|null, suiteCmdKeys: Set<string>}} o
86
71
  * @returns {string|null}
87
72
  */
73
+ export function stageQuestionText({ kind, params, genre, suiteCmdKeys, }: {
74
+ kind: string | null;
75
+ params: any;
76
+ genre: string | null;
77
+ suiteCmdKeys: Set<string>;
78
+ }): string | null;
79
+ /**
80
+ * Stage name to its plain question, off a signed spec's `closeDecl.stages` — the one pass that gathers every
81
+ * `command-exit` stage's cmd+args FIRST (so the failing-test-count half of `suite-green`'s pair can be told from a
82
+ * genuine typecheck stage) and then asks {@link stageQuestionText} per stage. `null` for a stage with no honest
83
+ * question; an empty map for a spec with no declared stages.
84
+ * @param {any} spec
85
+ * @returns {Map<string, string|null>}
86
+ */
87
+ export function stageQuestionsByName(spec: any): Map<string, string | null>;
88
+ /** the genre-owned noun for the count a TYPES-genre typecheck stage measures (see {@link stageQuestionText}) */
88
89
  export const GENRE_WHAT: Readonly<{
89
90
  TYPES: "type errors";
90
91
  }>;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @typedef {object} Paint
3
+ * @property {boolean} on
4
+ * @property {(s: string) => string} grey @property {(s: string) => string} green @property {(s: string) => string} yellow
5
+ * @property {(s: string) => string} red @property {(s: string) => string} cyan @property {(s: string) => string} boldCyan
6
+ */
7
+ /**
8
+ * Colour is on only for a terminal: the stream says it is a TTY, `NO_COLOR` is empty/unset, and `TERM` is not `dumb`.
9
+ * @param {{isTTY?: boolean}|undefined} stream the output stream (process.stdout)
10
+ * @param {Record<string, string|undefined>} [env]
11
+ * @returns {Paint}
12
+ */
13
+ export function makePaint(stream: {
14
+ isTTY?: boolean;
15
+ } | undefined, env?: Record<string, string | undefined>): Paint;
16
+ export namespace PLAIN {
17
+ let on: boolean;
18
+ let grey: (s: string) => string;
19
+ let green: (s: string) => string;
20
+ let yellow: (s: string) => string;
21
+ let red: (s: string) => string;
22
+ let cyan: (s: string) => string;
23
+ let boldCyan: (s: string) => string;
24
+ }
25
+ export type Paint = {
26
+ on: boolean;
27
+ grey: (s: string) => string;
28
+ green: (s: string) => string;
29
+ yellow: (s: string) => string;
30
+ red: (s: string) => string;
31
+ cyan: (s: string) => string;
32
+ boldCyan: (s: string) => string;
33
+ };