bareloop 0.10.0 → 0.11.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 +351 -0
- package/README.md +17 -7
- package/bareloop.context.md +179 -16
- package/package.json +3 -3
- package/src/authorflow.js +114 -16
- package/src/authoring.js +100 -33
- package/src/authorjob.js +50 -6
- package/src/authorscout.js +13 -1
- package/src/bridges.js +1 -1
- package/src/clock.js +21 -3
- package/src/declaredclose.js +88 -11
- package/src/index.js +8 -1
- package/src/job.js +7 -2
- package/src/kinds.js +190 -9
- package/src/ledger.js +24 -1
- package/src/planrun.js +195 -5
- package/src/ralph.js +9 -0
- package/src/reuse.js +195 -7
- package/src/root.js +1 -1
- package/src/run.js +10 -4
- package/src/selection.js +1 -1
- package/types/authorflow.d.ts +86 -12
- package/types/authoring.d.ts +49 -35
- package/types/authorjob.d.ts +9 -1
- package/types/authorscout.d.ts +7 -1
- package/types/clock.d.ts +5 -2
- package/types/declaredclose.d.ts +64 -6
- package/types/index.d.ts +4 -4
- package/types/job.d.ts +5 -0
- package/types/kinds.d.ts +76 -4
- package/types/planrun.d.ts +18 -2
- package/types/reuse.d.ts +74 -0
- package/types/run.d.ts +12 -2
package/types/declaredclose.d.ts
CHANGED
|
@@ -97,7 +97,8 @@ export function guardNames(closeDecl: any, verdictType: string): string[];
|
|
|
97
97
|
* @param {any[]} stages declared stage descriptors, already validated
|
|
98
98
|
* @param {(s: string) => string} [redact] the scrub, applied at THIS boundary
|
|
99
99
|
* @param {{timeoutMs?: number, cwd?: string, seedRef?: string,
|
|
100
|
-
* seedTrees?: any, gapCap?: number, maxBuffer?: number, baselineMode?: 'auto'|'worktree'
|
|
100
|
+
* seedTrees?: any, gapCap?: number, maxBuffer?: number, baselineMode?: 'auto'|'worktree',
|
|
101
|
+
* humanRuling?: {decision: string, text?: string|null}|null}} [opts]
|
|
101
102
|
* @returns {Promise<any>}
|
|
102
103
|
*/
|
|
103
104
|
export function runDeclaredStages(stages: any[], redact?: (s: string) => string, opts?: {
|
|
@@ -108,6 +109,10 @@ export function runDeclaredStages(stages: any[], redact?: (s: string) => string,
|
|
|
108
109
|
gapCap?: number;
|
|
109
110
|
maxBuffer?: number;
|
|
110
111
|
baselineMode?: "auto" | "worktree";
|
|
112
|
+
humanRuling?: {
|
|
113
|
+
decision: string;
|
|
114
|
+
text?: string | null;
|
|
115
|
+
} | null;
|
|
111
116
|
}): Promise<any>;
|
|
112
117
|
/**
|
|
113
118
|
* The trend reader's input for ONE close verdict, whichever executor produced
|
|
@@ -160,11 +165,64 @@ export const DECLARED_GAP_PREFIX: "close: ";
|
|
|
160
165
|
* it; because every declared line carries the prefix, it designates the stage's
|
|
161
166
|
* whole judged output rather than a hand-picked slice of it. */
|
|
162
167
|
export const DECLARED_GAP_KEEP: string;
|
|
163
|
-
/**
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
+
/**
|
|
169
|
+
* The close verdict word for a run WAITING on a person (N4 §1.3/§1.4). A
|
|
170
|
+
* literal, exported, because three readers key on it — the runner's pause
|
|
171
|
+
* branch, the ledger's excluded set, and the trend reader's blind rule — and
|
|
172
|
+
* three hand-spelled copies of one terminal is how they come to disagree.
|
|
173
|
+
*
|
|
174
|
+
* It is not in `CLOSE_FAULTS` and must never be added: a fault says the close
|
|
175
|
+
* could not render a verdict, and this says the close is not FINISHED rendering
|
|
176
|
+
* one. The first escalates; the second is a checkpoint the operator returns to.
|
|
177
|
+
*/
|
|
178
|
+
export const HUMAN_PAUSE: "human-pause";
|
|
179
|
+
/**
|
|
180
|
+
* The RUN-level terminal names the hitl class mints one layer up from
|
|
181
|
+
* `HUMAN_PAUSE` (N4 §1.3–§1.5): the checkpoint, and the honest refusal of the
|
|
182
|
+
* operator's rerun input. Spelled once here, beside the close-verdict word they
|
|
183
|
+
* translate, for the same reason `HUMAN_PAUSE` is — the emitters (`planrun.js`),
|
|
184
|
+
* the ledger's excluded set, the resume reader (`reuse.js`), and the runner
|
|
185
|
+
* script all key on them, and hand-spelled copies of one terminal is how they
|
|
186
|
+
* come to disagree.
|
|
187
|
+
*
|
|
188
|
+
* There were three (2026-08-17): `hitl-cancel` was the signer's own terminal and
|
|
189
|
+
* is DELETED with the door it belonged to. A person who does not want to carry on
|
|
190
|
+
* now PAUSES — the same checkpoint, resumable, retired by the TTL if nobody comes
|
|
191
|
+
* back — so nothing in this tree mints that name any more. The ledger keeps the
|
|
192
|
+
* bare string in its excluded set so a spine written before this change still
|
|
193
|
+
* reads as governance rather than as a capability gap; that is a READER's
|
|
194
|
+
* backward compatibility, and deliberately not a constant a writer could reach.
|
|
195
|
+
*/
|
|
196
|
+
export const HITL_PAUSE: "hitl-pause";
|
|
197
|
+
export const HITL_DECISION_RED: "hitl-decision-red";
|
|
198
|
+
/**
|
|
199
|
+
* The terminals above that leave the run WAITING ON A PERSON — as a list, minted
|
|
200
|
+
* beside the names it holds so a reader keys on membership rather than on a
|
|
201
|
+
* spelling, and a rename here travels to every reader for free.
|
|
202
|
+
*
|
|
203
|
+
* It is deliberately NOT `reuse.js`'s `CHECKPOINT_OUTCOMES`, which is the wider
|
|
204
|
+
* RESUME list: every stop that left work on disk and an allowance unspent, money
|
|
205
|
+
* and time included. Those are governance stops the reuse loop is meant to try
|
|
206
|
+
* again under its remaining tries; this is the half no further attempt can
|
|
207
|
+
* change, because the allowance still unspent is a human answer. `CHECKPOINT_OUTCOMES`
|
|
208
|
+
* is composed FROM this list so the two can never disagree about which is which.
|
|
209
|
+
*
|
|
210
|
+
* `HITL_DECISION_RED` is not here: it is a verdict already rendered on the operator's
|
|
211
|
+
* own input, not a question still open.
|
|
212
|
+
*/
|
|
213
|
+
export const HUMAN_CHECKPOINTS: readonly string[];
|
|
214
|
+
/** The verdict classes a DECLARED close may claim. Named as data so the job
|
|
215
|
+
* validator reads one hierarchy table rather than hard-coding a class.
|
|
216
|
+
*
|
|
217
|
+
* `hard` is by CONSTRUCTION: every mechanical kind is a command whose measurement
|
|
218
|
+
* is the truth. `hitl` joined it at N4 slice 1, and only because `human-confirms`
|
|
219
|
+
* is genuinely LIVE — the widening and the kind go in one commit, or this table
|
|
220
|
+
* admits a class the executor cannot render. The `soft` class is still absent:
|
|
221
|
+
* `judged-floor` is locked, so no declaration can reach above hitl.
|
|
222
|
+
*
|
|
223
|
+
* The direction that matters is unchanged. This says which class a declaration
|
|
224
|
+
* MAY claim; `closeCeiling` says which class its stages actually NEED. A pick
|
|
225
|
+
* below the ceiling is still the silent upgrade `class-ceiling` refuses. */
|
|
168
226
|
export const DECLARED_CLOSE_CLASSES: readonly string[];
|
|
169
227
|
export type Red = {
|
|
170
228
|
code: string;
|
package/types/index.d.ts
CHANGED
|
@@ -8,13 +8,13 @@ export { validatePlan, stageClose, EXIT_TYPES, MAX_EXITS_PER_STEP, MAX_PLAN_STEP
|
|
|
8
8
|
export { snapshotScope, evalExits } from "./exits.js";
|
|
9
9
|
export { BRIDGE_SCHEMA, validateBridge, deriveStatus, listingRow, loadGate, mintBridge, appendGreen, appendRed, loadBridge, loadRegistry, saveBridge, makeRegistry, registryExists } from "./bridges.js";
|
|
10
10
|
export { renderListing, selectionPrompt } from "./selection.js";
|
|
11
|
-
export { validateEnvelope, resolveTrySpec, resolveReuse, reuseSpecHash, selectBridge, runReuse, REUSE_GRADED_RED, readResume, resumeTreeGate } from "./reuse.js";
|
|
11
|
+
export { validateEnvelope, resolveTrySpec, resolveReuse, reuseSpecHash, selectBridge, runReuse, REUSE_GRADED_RED, readResume, resumeTreeGate, CHECKPOINT_OUTCOMES, PAUSE_TTL_MS, checkpointAgeGate } from "./reuse.js";
|
|
12
12
|
export { classifyIncidents, foldLedger, ledgerDeltas, updateLedger, LEDGER_CLASSES } from "./ledger.js";
|
|
13
13
|
export { workBranchName, prepareWorkBranch, WORK_BRANCH_PREFIX, WORK_BRANCH_RE } from "./workbranch.js";
|
|
14
|
-
export { runDeclaredClose, runStage, seedRead, seedAtHead, seedListing, changedSet, makeSeedTrees, LIVE_KINDS, STOP_FAULTS, JUDGED_MARKER, EXIT_GREEN, EXIT_RED, EXIT_STOP } from "./kinds.js";
|
|
15
|
-
export { validateDeclaration, normalizeDeclaration, KIND_CATALOGUE, CATALOGUE_KINDS, CATALOGUE_LIVE_KINDS, LOCKED_KINDS, TYPES_GENRE, TYPES_GENRE_TEMPLATE, GENRE_LANGUAGES, genreEnv, genreOwnedEnvNames, genreInstruments, DIRECTIONS, BASELINES, MAX_STAGES, VERDICT_CLASSES, LOCKED_CLASSES, LIVE_CLASSES, CLASS_BATTERIES, classGuards, closeCeiling } from "./authoring.js";
|
|
14
|
+
export { runDeclaredClose, runStage, seedRead, seedAtHead, seedListing, changedSet, makeSeedTrees, LIVE_KINDS, STOP_FAULTS, JUDGED_MARKER, EXIT_GREEN, EXIT_RED, EXIT_STOP, HUMAN_DECISIONS, SEED_EXEMPT_KINDS, normalizeHumanRuling } from "./kinds.js";
|
|
15
|
+
export { validateDeclaration, normalizeDeclaration, KIND_CATALOGUE, CATALOGUE_KINDS, CATALOGUE_LIVE_KINDS, LOCKED_KINDS, TYPES_GENRE, TYPES_GENRE_TEMPLATE, GENRE_LANGUAGES, genreEnv, genreOwnedEnvNames, genreInstruments, DIRECTIONS, BASELINES, MAX_STAGES, VERDICT_CLASSES, LOCKED_CLASSES, LIVE_CLASSES, CLASS_BATTERIES, classGuards, closeCeiling, NEVER_OFFERED_KINDS } from "./authoring.js";
|
|
16
16
|
export { runAuthorScout, buildSeedListing, seedFileList, classifySurvey, AUTHOR_SCOUT_VERBS, SCOUT_ATTEMPTS, SURVEY_CAUSES, SCOUT_RETRY_CAUSES } from "./authorscout.js";
|
|
17
17
|
export { scrubRaw, RAW_PERSIST_MAX, RAW_TRIM_MARKER } from "./text.js";
|
|
18
18
|
export { authorClose, authorPrompt, declarationSchema, makeLoopGenerate, MAX_REVISIONS, QUESTION_SETS, GREEN_QUESTIONS, CLASS_STATEMENTS, questionsFor, requiredAnswersFor } from "./authorflow.js";
|
|
19
|
-
export { validateCloseDecl, runDeclaredStages, declaredStages, isDeclaredClose, guardNames, closeGrade, DECLARED_GENRES, DECLARED_GAP_PREFIX, DECLARED_GAP_KEEP, DECLARED_CLOSE_CLASSES, CLOSE_DECL_FIELDS } from "./declaredclose.js";
|
|
19
|
+
export { validateCloseDecl, runDeclaredStages, declaredStages, isDeclaredClose, guardNames, closeGrade, DECLARED_GENRES, DECLARED_GAP_PREFIX, DECLARED_GAP_KEEP, DECLARED_CLOSE_CLASSES, CLOSE_DECL_FIELDS, HUMAN_PAUSE, HITL_PAUSE, HITL_DECISION_RED, HUMAN_CHECKPOINTS } from "./declaredclose.js";
|
|
20
20
|
export { runInterview, authorCloseForJob, assembleSpec, prepareSigning, refusalEvents, refuseLockedKind, GENRE, REFUSAL_LIB, REFUSAL_CATEGORY, AUTHORED_SPEC_FIELDS } from "./authorjob.js";
|
package/types/job.d.ts
CHANGED
|
@@ -158,6 +158,11 @@ export const LOCKED_TOOLS: readonly string[];
|
|
|
158
158
|
* pattern: disclosure ≠ admission), so the ledger counts the demand and the
|
|
159
159
|
* non-code rung later fills a declared slot instead of reshaping the schema. */
|
|
160
160
|
export const VERDICT_TYPES: readonly string[];
|
|
161
|
+
/** N4 slice 1: `hitl` is ADMITTED — the class whose *done* needs a person runs
|
|
162
|
+
* through the same signed spec, the same agent-authored plan and the same
|
|
163
|
+
* arbiter as a green job (the nine rulings, 2026-08-07; the three-button surface,
|
|
164
|
+
* 2026-08-12). `soft-green` stays declared-but-locked until its judged floor is
|
|
165
|
+
* built and proven (slice 2): a wobbly ruler must not mint anything. */
|
|
161
166
|
export const LOCKED_VERDICTS: readonly string[];
|
|
162
167
|
export const CADENCE_UNITS: readonly string[];
|
|
163
168
|
/** SP-2: API-first; local deferred (PRD §5/§8). `clipipe-subscription` (F42,
|
package/types/kinds.d.ts
CHANGED
|
@@ -211,6 +211,30 @@ export function parseValue(output: string, terms: any[], { scope, workdir }?: {
|
|
|
211
211
|
* @returns {SeedTrees}
|
|
212
212
|
*/
|
|
213
213
|
export function makeSeedTrees(): SeedTrees;
|
|
214
|
+
/**
|
|
215
|
+
* THE SIGNER'S ANSWER, normalised at the seam that accepts it — the library half
|
|
216
|
+
* of the three-button gate (2026-08-12 §1).
|
|
217
|
+
*
|
|
218
|
+
* `null` is not a refusal: no ruling at all IS the pause path, which is how every
|
|
219
|
+
* ordinary run and every first leg of a hitl run arrives here. What is refused is
|
|
220
|
+
* an answer that is not one of the three doors, and — the case the POC's negative
|
|
221
|
+
* control measured — a `rerun` with no text. Ruling 3 makes the human's words the
|
|
222
|
+
* gap the worker converts from; an empty one launches a fix worker that re-runs
|
|
223
|
+
* as though nothing had been said, which is the failure this refusal exists for.
|
|
224
|
+
*
|
|
225
|
+
* It never throws and never repairs: a decision that cannot be read is handed
|
|
226
|
+
* back as a refusal with its reason, and the caller decides what to do about it.
|
|
227
|
+
* @param {any} ruling
|
|
228
|
+
* @returns {{ok: boolean, ruling: {decision: string, text: string|null}|null, why: string|null}}
|
|
229
|
+
*/
|
|
230
|
+
export function normalizeHumanRuling(ruling: any): {
|
|
231
|
+
ok: boolean;
|
|
232
|
+
ruling: {
|
|
233
|
+
decision: string;
|
|
234
|
+
text: string | null;
|
|
235
|
+
} | null;
|
|
236
|
+
why: string | null;
|
|
237
|
+
};
|
|
214
238
|
/**
|
|
215
239
|
* Run ONE declared stage against a workdir at a seed.
|
|
216
240
|
*
|
|
@@ -254,13 +278,14 @@ export function seedRead(declaration: any, ctx: Ctx): Promise<StageResult[]>;
|
|
|
254
278
|
* room would break a documented adopter contract for nothing; the new name says
|
|
255
279
|
* exactly what differs. `src/declaredclose.js` is what bridges the two shapes.
|
|
256
280
|
* @param {any} declaration @param {Ctx} ctx
|
|
257
|
-
* @returns {Promise<{verdict: 'green'|'red'|'instrument-stop', exitCode: number, judged: boolean, firstRed: string|null, stages: StageResult[]}>}
|
|
281
|
+
* @returns {Promise<{verdict: 'green'|'red'|'instrument-stop'|'pause', exitCode: number|null, judged: boolean, firstRed: string|null, pausedAt: string|null, stages: StageResult[]}>}
|
|
258
282
|
*/
|
|
259
283
|
export function runDeclaredClose(declaration: any, ctx: Ctx): Promise<{
|
|
260
|
-
verdict: "green" | "red" | "instrument-stop";
|
|
261
|
-
exitCode: number;
|
|
284
|
+
verdict: "green" | "red" | "instrument-stop" | "pause";
|
|
285
|
+
exitCode: number | null;
|
|
262
286
|
judged: boolean;
|
|
263
287
|
firstRed: string | null;
|
|
288
|
+
pausedAt: string | null;
|
|
264
289
|
stages: StageResult[];
|
|
265
290
|
}>;
|
|
266
291
|
/** the close's two judgment exits — a stage's verdict, in the shape the
|
|
@@ -330,6 +355,28 @@ export const SIGNS: readonly number[];
|
|
|
330
355
|
* counted demand (the request-red path), and reaching one at runtime is a
|
|
331
356
|
* stop — never a red, and never a silent pass. */
|
|
332
357
|
export const LIVE_KINDS: readonly string[];
|
|
358
|
+
/** RULING 8 — the stages the seed-verdict read (D12) must NOT run. A judged
|
|
359
|
+
* number at seed is unstable and a person at seed is an interview, not a
|
|
360
|
+
* measurement; their bar comes from calibration (soft-green) or from the person
|
|
361
|
+
* themselves (hitl), never from the seed. The skip is RECORDED by name rather
|
|
362
|
+
* than taken in silence (F59: absent is not empty), so `seedRead` still returns
|
|
363
|
+
* one row per declared stage. */
|
|
364
|
+
export const SEED_EXEMPT_KINDS: readonly string[];
|
|
365
|
+
/** the one kind a PERSON renders — named once, because the runner keys three
|
|
366
|
+
* decisions on it (is there a door to answer, which stage paused, whose ruling
|
|
367
|
+
* this is) and three literals is how they come to disagree */
|
|
368
|
+
export const HUMAN_KIND: "human-confirms";
|
|
369
|
+
/** the three doors the signer is offered at a hitl pause (2026-08-12 §1, doors
|
|
370
|
+
* re-cut 2026-08-17). No fourth door, and no free-text-only variant: a red that
|
|
371
|
+
* is not one of these two is not a ruling the run can act on.
|
|
372
|
+
*
|
|
373
|
+
* `cancel` was the third door and is DELETED as a concept (hamr: *"what's the
|
|
374
|
+
* point of cancel anyways? pause can resume — that would be more honest"*). The
|
|
375
|
+
* case it served — a person who looks and does not want to carry on — is a pause
|
|
376
|
+
* nobody returns to, which the 60-day checkpoint TTL retires on its own. Nothing
|
|
377
|
+
* here forces a forever-decision at the one moment the person has least reason
|
|
378
|
+
* to make one. */
|
|
379
|
+
export const HUMAN_DECISIONS: readonly string[];
|
|
333
380
|
/**
|
|
334
381
|
* The arbiter's book NAMES, one home. F98's mechanism was exactly this list
|
|
335
382
|
* living as independent literals: the fence deny arrays (src/planrun.js,
|
|
@@ -356,6 +403,13 @@ export type Red = {
|
|
|
356
403
|
/**
|
|
357
404
|
* The arbiter's half of a stage run. Every field here is operator/runner
|
|
358
405
|
* territory: a declaration parameterises kinds, never the contracts.
|
|
406
|
+
* `humanRuling` is the SIGNER's answer at a hitl pause, carried in from the
|
|
407
|
+
* runner — never authored, never defaulted, and absent on every ordinary run.
|
|
408
|
+
* `onStage` is a REPORTING seam and nothing else: the seed read spawns a real
|
|
409
|
+
* toolchain per stage (a suite is the slow one) and a whole read is one opaque
|
|
410
|
+
* await, so the shell gets told as each stage lands. It decides nothing, it is
|
|
411
|
+
* never consulted, and no verdict depends on it — the house pattern is
|
|
412
|
+
* `runJob`'s `emit` (the library reports, the shell prints).
|
|
359
413
|
*/
|
|
360
414
|
export type Ctx = {
|
|
361
415
|
workdir: string;
|
|
@@ -366,9 +420,27 @@ export type Ctx = {
|
|
|
366
420
|
gapCap?: number;
|
|
367
421
|
maxBuffer?: number;
|
|
368
422
|
seedTrees?: SeedTrees;
|
|
423
|
+
humanRuling?: {
|
|
424
|
+
decision: string;
|
|
425
|
+
text?: string | null;
|
|
426
|
+
} | null;
|
|
427
|
+
onStage?: (row: {
|
|
428
|
+
stage: string | null;
|
|
429
|
+
kind: string | null;
|
|
430
|
+
verdict: string;
|
|
431
|
+
durationMs: number;
|
|
432
|
+
}) => void;
|
|
369
433
|
};
|
|
434
|
+
/**
|
|
435
|
+
* Six outcomes, and only two of them are verdicts. `pause` is N4's fifth: the
|
|
436
|
+
* close reached a stage a machine cannot render and is WAITING on a person —
|
|
437
|
+
* neither green nor red, and never graded (the F17 forbidden-zone rule applied
|
|
438
|
+
* to a non-verdict). `skipped` is the sixth and says a stage was deliberately
|
|
439
|
+
* not run at THIS reading (ruling 8's seed exemption), which is a different
|
|
440
|
+
* fact from `not-reached` (an earlier stage decided first).
|
|
441
|
+
*/
|
|
370
442
|
export type StageResult = {
|
|
371
|
-
verdict: "green" | "red" | "instrument-stop" | "not-reached";
|
|
443
|
+
verdict: "green" | "red" | "instrument-stop" | "not-reached" | "pause" | "skipped";
|
|
372
444
|
exitCode: number | null;
|
|
373
445
|
value: number | null;
|
|
374
446
|
baseline: number | null;
|
package/types/planrun.d.ts
CHANGED
|
@@ -294,12 +294,24 @@ export function planPrompt(job: any, scoutBlob: string, reds: any[] | null, maxS
|
|
|
294
294
|
* it the deterministic name would collide with that very branch and the collision walk
|
|
295
295
|
* would mint a `-2` beside the progress the resume exists to keep. Absent is the cold
|
|
296
296
|
* path. A recorded branch that no longer exists is a STOP, never a fresh start.
|
|
297
|
+
* @param {{decision: string, text?: string}|null} [opts.humanRuling] N4 — the SIGNER's
|
|
298
|
+
* answer at a hitl pause (2026-08-12 §1, re-cut 2026-08-17: accept | rerun <text> | pause), carried in
|
|
299
|
+
* by the runner on the leg that RESUMES a paused run. Absent on every ordinary run and
|
|
300
|
+
* on the leg that pauses; it is never authored, never defaulted, and never inferred.
|
|
301
|
+
*
|
|
302
|
+
* It is spent ONCE, on this leg's close readings up to the moment the fix loop opens:
|
|
303
|
+
* `accept` greens the human stage on fresh evidence (OPEN-3 — the mechanical stages
|
|
304
|
+
* re-run first, because the tree can change while a run is paused), `rerun` reds it
|
|
305
|
+
* with the human's own words as the gap, and `pause` keeps the checkpoint exactly as it
|
|
306
|
+
* is, before anything is read at all. After the fix loop opens the ruling is gone, so once the mechanical
|
|
307
|
+
* stages pass again the run PAUSES for a second review rather than converting the same
|
|
308
|
+
* sentence forever.
|
|
297
309
|
* @returns {Promise<string>} 'green' | 'already-green' | 'escalated' | 'plan-red' |
|
|
298
310
|
* 'check-red' | 'close-red' | 'close-unsupported' | 'recipe-stale' | 'pricing-red' |
|
|
299
311
|
* 'branch-red' | 'cap-halt' | 'wall-halt' | 'provider-red' | 'interpreter-red' |
|
|
300
|
-
* 'step-stalled' | `step-red:<id>`
|
|
312
|
+
* 'step-stalled' | 'hitl-pause' | 'hitl-decision-red' | `step-red:<id>`
|
|
301
313
|
*/
|
|
302
|
-
export function runPlan(job: any, { workdir, provider, nativeProvider, providerFor, emit, remainingUsd, isUnpriced, spendComplete, capRuns, strikeLimit, closeTimeoutMs, maxStepRounds, layerRoot, scoutRounds, bridge, now, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch }: {
|
|
314
|
+
export function runPlan(job: any, { workdir, provider, nativeProvider, providerFor, emit, remainingUsd, isUnpriced, spendComplete, capRuns, strikeLimit, closeTimeoutMs, maxStepRounds, layerRoot, scoutRounds, bridge, now, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling }: {
|
|
303
315
|
workdir: string;
|
|
304
316
|
provider: any;
|
|
305
317
|
nativeProvider?: ((o: {
|
|
@@ -332,6 +344,10 @@ export function runPlan(job: any, { workdir, provider, nativeProvider, providerF
|
|
|
332
344
|
spendComplete?: (() => boolean) | undefined;
|
|
333
345
|
now?: (() => number) | undefined;
|
|
334
346
|
resumeBranch?: string | null | undefined;
|
|
347
|
+
humanRuling?: {
|
|
348
|
+
decision: string;
|
|
349
|
+
text?: string;
|
|
350
|
+
} | null | undefined;
|
|
335
351
|
}): Promise<string>;
|
|
336
352
|
/**
|
|
337
353
|
* The recorded bound-reason's ceiling in the WORKER-facing note. The reason is a
|
package/types/reuse.d.ts
CHANGED
|
@@ -230,6 +230,43 @@ export function readResume(events: any[], { deathAt, direct, resumableOutcomes }
|
|
|
230
230
|
direct?: boolean;
|
|
231
231
|
resumableOutcomes?: string[];
|
|
232
232
|
}): any;
|
|
233
|
+
/**
|
|
234
|
+
* The AGE gate for a paused checkpoint — the sibling of `resumeTreeGate`, and it
|
|
235
|
+
* asks the other question a 60-day-old checkpoint raises. The tree gate asks
|
|
236
|
+
* *is this still the tree the run left?*; this asks *is this still a decision
|
|
237
|
+
* anyone is waiting on?*
|
|
238
|
+
*
|
|
239
|
+
* THREE things it deliberately does NOT do:
|
|
240
|
+
*
|
|
241
|
+
* - it does not widen any other resume rule. The 2026-08-12 ruling is about a
|
|
242
|
+
* person deciding, so `applies: false` on every other terminal: a cap-halt
|
|
243
|
+
* checkpoint is a different stop under a different allowance, and quietly
|
|
244
|
+
* ageing it out would be a governance change nobody ruled.
|
|
245
|
+
* - it does not treat an unreadable stamp as young (F6). A checkpoint that
|
|
246
|
+
* cannot say WHEN it paused has an unknown age, and unknown is refused rather
|
|
247
|
+
* than rounded down to fresh — the direction that fails safe.
|
|
248
|
+
* - it does not skip silently. An expired checkpoint comes back as a refusal
|
|
249
|
+
* that NAMES the age and the TTL, because the operator's next move (start
|
|
250
|
+
* fresh) depends on knowing which of the two it hit.
|
|
251
|
+
*
|
|
252
|
+
* The clock is injected for the same reason `runPlan`'s is: a rule measured in
|
|
253
|
+
* months cannot otherwise be tested at all.
|
|
254
|
+
*
|
|
255
|
+
* @param {any[]} events the paused run's own spine, parsed, in file order
|
|
256
|
+
* @param {{now?: () => number, ttlMs?: number}} [opts]
|
|
257
|
+
* @returns {{ok: boolean, applies: boolean, ageMs: number|null, ttlMs: number, pausedAt: string|null, detail: string|null}}
|
|
258
|
+
*/
|
|
259
|
+
export function checkpointAgeGate(events: any[], { now, ttlMs }?: {
|
|
260
|
+
now?: () => number;
|
|
261
|
+
ttlMs?: number;
|
|
262
|
+
}): {
|
|
263
|
+
ok: boolean;
|
|
264
|
+
applies: boolean;
|
|
265
|
+
ageMs: number | null;
|
|
266
|
+
ttlMs: number;
|
|
267
|
+
pausedAt: string | null;
|
|
268
|
+
detail: string | null;
|
|
269
|
+
};
|
|
233
270
|
/**
|
|
234
271
|
* The PATIENT gate for a resume, which is deliberately NOT the fresh-launch one.
|
|
235
272
|
*
|
|
@@ -384,6 +421,43 @@ export function runReuse(opts: {
|
|
|
384
421
|
* started.
|
|
385
422
|
*/
|
|
386
423
|
export const REUSE_GRADED_RED: readonly string[];
|
|
424
|
+
/**
|
|
425
|
+
* WHICH TERMINALS ARE A CHECKPOINT — the list a runner hands `readResume` as
|
|
426
|
+
* `resumableOutcomes`, minted HERE rather than in whichever script happens to
|
|
427
|
+
* launch a run.
|
|
428
|
+
*
|
|
429
|
+
* `readResume` deliberately takes it as a parameter and defaults to empty, and
|
|
430
|
+
* that stays true: the reuse loop's own semantics depend on the empty default.
|
|
431
|
+
* What did not exist was a canonical ANSWER, so `scripts/run-u.mjs` kept its own
|
|
432
|
+
* copy — and the exported bundle (PRD v1.44 §2: a thin runner with bareloop as a
|
|
433
|
+
* dependency) would have had to keep a third. The same reasoning that put the
|
|
434
|
+
* pause TTL in the library (OPEN-2, hamr, 2026-08-13) puts this here.
|
|
435
|
+
*
|
|
436
|
+
* Every entry is a stop that left WORK ON DISK and an allowance unspent — money,
|
|
437
|
+
* time, a self-healed stall, and now a person who has not answered yet. A verdict
|
|
438
|
+
* already rendered is never on this list: `green`/`escalated` are graded rows, and
|
|
439
|
+
* re-buying one would pay twice for an answer already in hand. (The signer's own
|
|
440
|
+
* `hitl-cancel` terminal used to be the other example; the door was deleted on
|
|
441
|
+
* 2026-08-17 — a person who does not want to carry on pauses, and the checkpoint
|
|
442
|
+
* they keep is retired by the TTL rather than by a terminal.)
|
|
443
|
+
*
|
|
444
|
+
* The human half is SPLICED IN from `declaredclose.js` rather than spelled again,
|
|
445
|
+
* because the try loop below reads the two halves differently and a second copy is
|
|
446
|
+
* how they would come to disagree about which member is which: the first three are
|
|
447
|
+
* allowances the loop's remaining tries are meant to spend against, and the human
|
|
448
|
+
* ones are the stop no further try can change (see `hardStop`).
|
|
449
|
+
*/
|
|
450
|
+
export const CHECKPOINT_OUTCOMES: readonly string[];
|
|
451
|
+
/**
|
|
452
|
+
* THE PAUSE TTL (2026-08-12 §2): a hitl checkpoint is kept for 60 days.
|
|
453
|
+
*
|
|
454
|
+
* OPEN-2, RULED (hamr, in-turn, 2026-08-13): **the TTL lives in the LIBRARY**, so
|
|
455
|
+
* the exported bundle (a headless runner with bareloop as a dependency, PRD v1.44
|
|
456
|
+
* §2) inherits it instead of every runner re-implementing it. A script-only TTL
|
|
457
|
+
* would vanish on export — the one place the rule is most needed and least
|
|
458
|
+
* likely to be re-typed.
|
|
459
|
+
*/
|
|
460
|
+
export const PAUSE_TTL_MS: number;
|
|
387
461
|
export type Red = {
|
|
388
462
|
code: string;
|
|
389
463
|
path: string;
|
package/types/run.d.ts
CHANGED
|
@@ -97,12 +97,18 @@
|
|
|
97
97
|
* a manufactured-fixation probe). `true` is the ON/experimental arm; the
|
|
98
98
|
* default is the OFF arm. (Shell-owned seam, same doctrine as the provider
|
|
99
99
|
* binding.)
|
|
100
|
+
* @param {{decision: string, text?: string}|null} [opts.humanRuling] N4 — the SIGNER's
|
|
101
|
+
* answer at a hitl pause (accept | rerun <text> | pause), carried by the leg that
|
|
102
|
+
* RESUMES a paused run and forwarded verbatim to the plan flow. Absent on every
|
|
103
|
+
* ordinary run; never authored and never defaulted (a defaulted answer to "is this
|
|
104
|
+
* done?" is the rubber-stamp the class exists to prevent, 2026-08-12 §4).
|
|
100
105
|
* @returns {Promise<string>} outcome: 'green' | 'already-green' | 'escalated' |
|
|
101
106
|
* 'unapproved-spec' | 'job-red' | 'smoke-red' | 'plan-red' | 'check-red' |
|
|
102
107
|
* 'close-red' | 'close-unsupported' | 'recipe-stale' | 'branch-red' | 'pricing-red' | 'provider-red' |
|
|
103
|
-
* 'interpreter-red' | 'cap-halt' | 'wall-halt' | 'step-stalled' |
|
|
108
|
+
* 'interpreter-red' | 'cap-halt' | 'wall-halt' | 'step-stalled' |
|
|
109
|
+
* 'hitl-pause' | 'hitl-decision-red' | `step-red:<id>`
|
|
104
110
|
*/
|
|
105
|
-
export function runJob(rawSpec: object | string, { approvals, workdir, provider, nativeProvider, providerFor, emit, capRuns, strikeLimit, shellCapUsd, closeTimeoutMs, layerRoot, bridge, priorSpentUsd, priorSpendComplete, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch }: {
|
|
111
|
+
export function runJob(rawSpec: object | string, { approvals, workdir, provider, nativeProvider, providerFor, emit, capRuns, strikeLimit, shellCapUsd, closeTimeoutMs, layerRoot, bridge, priorSpentUsd, priorSpendComplete, priorWallMs, resumeSeed, resumeGrades, resumeReplans, resumeBranch, humanRuling }: {
|
|
106
112
|
approvals: unknown;
|
|
107
113
|
workdir: string;
|
|
108
114
|
provider: any;
|
|
@@ -133,6 +139,10 @@ export function runJob(rawSpec: object | string, { approvals, workdir, provider,
|
|
|
133
139
|
} | null | undefined;
|
|
134
140
|
resumeBranch?: string | null | undefined;
|
|
135
141
|
layerRoot?: boolean | undefined;
|
|
142
|
+
humanRuling?: {
|
|
143
|
+
decision: string;
|
|
144
|
+
text?: string;
|
|
145
|
+
} | null | undefined;
|
|
136
146
|
}): Promise<string>;
|
|
137
147
|
export type Red = {
|
|
138
148
|
code: string;
|