bareloop 0.38.0 → 0.40.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 (56) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/bareloop.context.md +87 -24
  3. package/package.json +3 -3
  4. package/src/authorflow.js +335 -59
  5. package/src/authoring.js +125 -3
  6. package/src/authorjob.js +93 -32
  7. package/src/authorreadout.js +498 -3
  8. package/src/authorrun.js +26 -6
  9. package/src/authorscout.js +9 -6
  10. package/src/bridges.js +1 -1
  11. package/src/calibrate.js +85 -11
  12. package/src/cardauthor.js +8 -2
  13. package/src/declaredclose.js +12 -5
  14. package/src/draftspend.js +6 -1
  15. package/src/interviewrun.js +56 -27
  16. package/src/job.js +38 -5
  17. package/src/jobblock.js +140 -0
  18. package/src/judged.js +323 -29
  19. package/src/kinds.js +13 -1
  20. package/src/ledger.js +1 -1
  21. package/src/panel/authorroutes.js +17 -11
  22. package/src/panel/authorsession.js +202 -75
  23. package/src/panel/index.html +302 -312
  24. package/src/panel/jobplan.js +107 -0
  25. package/src/panel/server.js +67 -13
  26. package/src/planrun.js +6 -5
  27. package/src/promptregisters.js +1 -1
  28. package/src/providers.js +111 -2
  29. package/src/reuse.js +1 -1
  30. package/src/root.js +1 -1
  31. package/src/run.js +3 -3
  32. package/src/selection.js +1 -1
  33. package/src/source.js +64 -1
  34. package/src/text.js +13 -0
  35. package/src/transport.js +1 -1
  36. package/src/trend.js +1 -0
  37. package/src/userrun.js +3 -3
  38. package/types/authorflow.d.ts +258 -39
  39. package/types/authoring.d.ts +30 -1
  40. package/types/authorjob.d.ts +52 -13
  41. package/types/authorreadout.d.ts +123 -1
  42. package/types/authorscout.d.ts +5 -3
  43. package/types/calibrate.d.ts +4 -1
  44. package/types/declaredclose.d.ts +5 -1
  45. package/types/draftspend.d.ts +8 -2
  46. package/types/job.d.ts +1 -1
  47. package/types/jobblock.d.ts +102 -0
  48. package/types/judged.d.ts +21 -2
  49. package/types/panel/authorsession.d.ts +57 -7
  50. package/types/panel/jobplan.d.ts +58 -0
  51. package/types/panel/server.d.ts +20 -0
  52. package/types/planrun.d.ts +1 -1
  53. package/types/providers.d.ts +52 -1
  54. package/types/run.d.ts +1 -1
  55. package/types/source.d.ts +26 -0
  56. package/types/trend.d.ts +1 -0
package/src/transport.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // hamr's ruling, verbatim: "one retry for transport layer failure and
2
- // reporting with the rest end of gate." (F115, docs/logs/FINDINGS.md.)
2
+ // reporting with the rest end of gate." (F115, docs/wiki/FINDINGS.md.)
3
3
  //
4
4
  // A transport failure is fetch THROWING — the request never produced an HTTP
5
5
  // response at all (a TLS fault mid-record, a reset socket, a DNS/network
package/src/trend.js CHANGED
@@ -272,6 +272,7 @@ export function createTrend({ stageOrder = [], limit = FIX_STRIKE_LIMIT, blindCa
272
272
  * @param {{gap?: string, stage?: string|null, value?: number|null}} o either a
273
273
  * raw gap (parsed here) or an already-read `{stage, value}` — never both
274
274
  * spellings of the same reading in one call.
275
+ * (A judged stage's value is its distinct red COUNT, supplied by the caller.)
275
276
  * @returns {{iteration: number, stage: string, value: number|null, improved: boolean,
276
277
  * comparable: boolean, noProgress: number, limit: number, stageIndex: number}}
277
278
  */
package/src/userrun.js CHANGED
@@ -111,7 +111,7 @@ const JOBS = {
111
111
  seed: '92d71a7c1253f8f2430e2d308ecfef01c826b5c2',
112
112
  },
113
113
  // Bench row G3 (the NEGATIVE row) — the planted contract contradiction
114
- // (docs/product/G3-SCOPING.md). A copy of the pulselog-u patient (patients are
114
+ // (docs/logs/G3-SCOPING.md). A copy of the pulselog-u patient (patients are
115
115
  // always copies) with one extra commit: two test/** files that pin
116
116
  // assembleEmail's subject to two different strings, unsatisfiable together
117
117
  // inside writeScope: src/**. Not frozen, not signed, no run — BUILT ON BRANCH
@@ -153,7 +153,7 @@ const JOBS = {
153
153
  // Bench row G2 (the NEGATIVE row) — TESTGEN cold start in plan-v1. The legacy
154
154
  // steps[] config went 0-of-43 (F38); this config's rate is UNKNOWN until its
155
155
  // establishing run. Same patient/seed/grader as the l2accept battery
156
- // (TESTGEN-PREREG); the spec is the cold goal. See docs/product/G2-SCOPING.md.
156
+ // (TESTGEN-PREREG); the spec is the cold goal. See docs/logs/G2-SCOPING.md.
157
157
  'aurora-testgen-cold': {
158
158
  spec: 'aurora-testgen-cold.json',
159
159
  workdir: '/home/hamr/PycharmProjects/bareloop-patients/aurora-soar',
@@ -445,7 +445,7 @@ async function execute(ctx) {
445
445
  const SHIM_TAIL = shimArg === null ? '' : ` --read-shim ${shimArg}`;
446
446
 
447
447
  // --scout picks whether the plan flow pays for the read-only survey at all
448
- // (docs/product/SCOUT-CONTRAST.md). Runner territory exactly like --read-shim
448
+ // (docs/logs/SCOUT-CONTRAST.md). Runner territory exactly like --read-shim
449
449
  // and --model: the spec names no scout, so the signed hash is unaffected. An
450
450
  // unrecognised value throws at argv, before the approval gate — the same
451
451
  // param-guard class as --read-shim above, for the same reason: a silently
@@ -1,3 +1,40 @@
1
+ /**
2
+ * Which job lines did these validation reds name? A red names a line in its text ("job line N") or through the stage it
3
+ * sits on (path `stages[i]…` → that stage's own `fromLine`; `refused[i]…` → that refusal's `line`). A red naming none (a
4
+ * missing top-level key) names no line. Sorted real line numbers.
5
+ * @param {Red[]} reds @param {any} declaration @param {number[]} lineNums
6
+ * @returns {number[]}
7
+ */
8
+ export function linesNamedByReds(reds: Red[], declaration: any, lineNums: number[]): number[];
9
+ /**
10
+ * The machine's keep-or-drop of the try-3 questions. Kept only when its line is one the previous try's reds named and its
11
+ * text is non-blank, at most {@link MAX_QUESTIONS}; every drop comes back with its reason, for the draft's log.
12
+ * @param {any} raw @param {number[]} failedLines
13
+ * @returns {{kept: {line: number, question: string}[], dropped: {reason: string, raw: any}[]}}
14
+ */
15
+ export function normalizeQuestions(raw: any, failedLines: number[]): {
16
+ kept: {
17
+ line: number;
18
+ question: string;
19
+ }[];
20
+ dropped: {
21
+ reason: string;
22
+ raw: any;
23
+ }[];
24
+ };
25
+ /**
26
+ * Did this try FAIL THE SEED READ (hamr's ruling 2026-10-10, differing from fwdloop's validation-only rule)? It did when a work
27
+ * stage instrument-stopped, or when no work stage is red on the repo as it is — the vacuous close ("nothing in the close fails
28
+ * at all": it grades nothing). The mandatory guards (`guardNames`) are green at the seed by design and never count as work.
29
+ * The job lines it names are the `fromLine`s of the stages the seed read named (the instrument-stopped ones, else every work
30
+ * stage); if none of them maps to a real line, EVERY numbered job line counts.
31
+ * @param {any[]} rows @param {any} declaration @param {string[]} guardNames @param {number[]} lineNums
32
+ * @returns {{failed: boolean, lines: number[]}}
33
+ */
34
+ export function seedReadFailure(rows: any[], declaration: any, guardNames: string[], lineNums: number[]): {
35
+ failed: boolean;
36
+ lines: number[];
37
+ };
1
38
  /** @param {boolean} isRepo @returns {typeof DESTINATION_FIELD_REPO} */
2
39
  export function destinationFieldFor(isRepo: boolean): typeof DESTINATION_FIELD_REPO;
3
40
  /** The frozen question set for a picked class. Throws on a locked or unknown
@@ -69,14 +106,34 @@ export function schemaCoverage(catalogue?: Record<string, any>): {
69
106
  * THROWS on a catalogue it cannot cover: a malformed catalogue is a bareloop bug,
70
107
  * and failing loudly beats emitting a schema that quietly cannot say something
71
108
  * the validator will then demand.
109
+ * `questions` (P7 item 5, last drafting try only) adds the optional `questions` property; absent, the schema is byte-identical.
72
110
  * @param {Record<string, any>} [catalogue]
73
- * @param {{verdictType?: string|null}} [o]
111
+ * @param {{verdictType?: string|null, questions?: boolean}} [o]
74
112
  */
75
- export function declarationSchema(catalogue?: Record<string, any>, { verdictType }?: {
113
+ export function declarationSchema(catalogue?: Record<string, any>, { verdictType, questions }?: {
76
114
  verdictType?: string | null;
115
+ questions?: boolean;
77
116
  }): {
78
117
  type: string;
79
118
  properties: {
119
+ questions?: {
120
+ type: string;
121
+ items: {
122
+ type: string;
123
+ properties: {
124
+ line: {
125
+ type: string;
126
+ minimum: number;
127
+ };
128
+ question: {
129
+ type: string;
130
+ minLength: number;
131
+ };
132
+ };
133
+ required: string[];
134
+ };
135
+ description: string;
136
+ } | undefined;
80
137
  stages: {
81
138
  type: string;
82
139
  minItems: number;
@@ -92,6 +149,16 @@ export function declarationSchema(catalogue?: Record<string, any>, { verdictType
92
149
  type: string;
93
150
  description: string;
94
151
  };
152
+ fromLine: {
153
+ type: string;
154
+ minItems: number;
155
+ uniqueItems: boolean;
156
+ items: {
157
+ type: string;
158
+ minimum: number;
159
+ };
160
+ description: string;
161
+ };
95
162
  kind: {
96
163
  const: string;
97
164
  };
@@ -115,6 +182,27 @@ export function declarationSchema(catalogue?: Record<string, any>, { verdictType
115
182
  };
116
183
  description: string;
117
184
  };
185
+ refused: {
186
+ type: string;
187
+ items: {
188
+ type: string;
189
+ properties: {
190
+ line: {
191
+ type: string;
192
+ minimum: number;
193
+ description: string;
194
+ };
195
+ reason: {
196
+ type: string;
197
+ minLength: number;
198
+ description: string;
199
+ };
200
+ };
201
+ required: string[];
202
+ additionalProperties: boolean;
203
+ };
204
+ description: string;
205
+ };
118
206
  };
119
207
  required: string[];
120
208
  additionalProperties: boolean;
@@ -123,19 +211,38 @@ export function declarationSchema(catalogue?: Record<string, any>, { verdictType
123
211
  * The output channel. It records and acknowledges; it takes no action, which is
124
212
  * why handing it to a toolless authoring call does not reopen D3.
125
213
  * @param {{calls: any[]}} box
126
- * @param {{catalogue?: Record<string, any>, verdictType?: string|null}} [o]
214
+ * @param {{catalogue?: Record<string, any>, verdictType?: string|null, questions?: boolean}} [o]
127
215
  */
128
216
  export function declarationTool(box: {
129
217
  calls: any[];
130
- }, { catalogue, verdictType }?: {
218
+ }, { catalogue, verdictType, questions }?: {
131
219
  catalogue?: Record<string, any>;
132
220
  verdictType?: string | null;
221
+ questions?: boolean;
133
222
  }): {
134
223
  name: string;
135
224
  description: string;
136
225
  parameters: {
137
226
  type: string;
138
227
  properties: {
228
+ questions?: {
229
+ type: string;
230
+ items: {
231
+ type: string;
232
+ properties: {
233
+ line: {
234
+ type: string;
235
+ minimum: number;
236
+ };
237
+ question: {
238
+ type: string;
239
+ minLength: number;
240
+ };
241
+ };
242
+ required: string[];
243
+ };
244
+ description: string;
245
+ } | undefined;
139
246
  stages: {
140
247
  type: string;
141
248
  minItems: number;
@@ -151,6 +258,16 @@ export function declarationTool(box: {
151
258
  type: string;
152
259
  description: string;
153
260
  };
261
+ fromLine: {
262
+ type: string;
263
+ minItems: number;
264
+ uniqueItems: boolean;
265
+ items: {
266
+ type: string;
267
+ minimum: number;
268
+ };
269
+ description: string;
270
+ };
154
271
  kind: {
155
272
  const: string;
156
273
  };
@@ -174,6 +291,27 @@ export function declarationTool(box: {
174
291
  };
175
292
  description: string;
176
293
  };
294
+ refused: {
295
+ type: string;
296
+ items: {
297
+ type: string;
298
+ properties: {
299
+ line: {
300
+ type: string;
301
+ minimum: number;
302
+ description: string;
303
+ };
304
+ reason: {
305
+ type: string;
306
+ minLength: number;
307
+ description: string;
308
+ };
309
+ };
310
+ required: string[];
311
+ additionalProperties: boolean;
312
+ };
313
+ description: string;
314
+ };
177
315
  };
178
316
  required: string[];
179
317
  additionalProperties: boolean;
@@ -260,16 +398,27 @@ export function writeScopeBlock(writeScope: string[]): string;
260
398
  * acceptance — BINDING, never re-decided by the composer, and a DIFFERENT
261
399
  * meaning from `openQuestions` (which means "could not resolve"): the two
262
400
  * never merge.
263
- * @param {{checks: string[], protections: string[], openQuestions?: string[], notChecked?: string[],
401
+ * @param {{checks: string[], checkItems?: {text: string, fromLine: number[]|null}[], protections: string[], openQuestions?: string[], notChecked?: string[],
264
402
  * answeredQuestions?: string[]}} confirmed
265
403
  */
266
404
  export function confirmedBlock(confirmed: {
267
405
  checks: string[];
406
+ checkItems?: {
407
+ text: string;
408
+ fromLine: number[] | null;
409
+ }[];
268
410
  protections: string[];
269
411
  openQuestions?: string[];
270
412
  notChecked?: string[];
271
413
  answeredQuestions?: string[];
272
414
  }): string;
415
+ /**
416
+ * P7: the job-line tagging order (model-facing, registered). Rule 1 of the job block: every stage the drafter writes
417
+ * names the ONE numbered job line it serves, or the line is refused with a reason; the mandatory guards serve no line.
418
+ * The $0 validator (validateDeclaration, `jobLines`) enforces it and the revise loop feeds a miss back.
419
+ * @param {number} count how many numbered job lines the person wrote
420
+ */
421
+ export function jobLineTagBlock(count: number): string;
273
422
  /**
274
423
  * The whole authoring prompt, as one string.
275
424
  *
@@ -292,9 +441,10 @@ export function confirmedBlock(confirmed: {
292
441
  * guards: {name: string, kind: string, params: Record<string, any>, fill: string[]}[],
293
442
  * ownedEnvNames?: string[], mode?: 'tool'|'text', catalogue?: Record<string, any>,
294
443
  * writeScope?: string[]|null,
295
- * confirmed?: {checks: string[], protections: string[], openQuestions?: string[], notChecked?: string[], answeredQuestions?: string[]}|null}} o
444
+ * jobLines?: {n: number}[]|null, inputs?: {n: number, label: string, value: string}[]|null,
445
+ * confirmed?: {checks: string[], checkItems?: {text: string, fromLine: number[]|null}[], protections: string[], openQuestions?: string[], notChecked?: string[], answeredQuestions?: string[]}|null}} o
296
446
  */
297
- export function authorPrompt({ answers, questions, facts, listingBlock, lang, verdictType, guards, ownedEnvNames, mode, catalogue, writeScope, confirmed, }: {
447
+ export function authorPrompt({ answers, questions, facts, listingBlock, lang, verdictType, guards, ownedEnvNames, mode, catalogue, writeScope, jobLines, inputs, confirmed, }: {
298
448
  answers: Record<string | number, string>;
299
449
  questions?: Record<string | number, string>;
300
450
  facts: any;
@@ -311,8 +461,20 @@ export function authorPrompt({ answers, questions, facts, listingBlock, lang, ve
311
461
  mode?: "tool" | "text";
312
462
  catalogue?: Record<string, any>;
313
463
  writeScope?: string[] | null;
464
+ jobLines?: {
465
+ n: number;
466
+ }[] | null;
467
+ inputs?: {
468
+ n: number;
469
+ label: string;
470
+ value: string;
471
+ }[] | null;
314
472
  confirmed?: {
315
473
  checks: string[];
474
+ checkItems?: {
475
+ text: string;
476
+ fromLine: number[] | null;
477
+ }[];
316
478
  protections: string[];
317
479
  openQuestions?: string[];
318
480
  notChecked?: string[];
@@ -457,7 +619,7 @@ export function resolveSourcePrefixes({ workdir, sourcePaths, seedFiles }: {
457
619
  */
458
620
  /**
459
621
  * @param {{ceilingUsd?: number|null,
460
- * onCall?: (call: {label: string, costUsd: number|null, unpricedRounds: number}) => void}} [o]
622
+ * onCall?: (call: {label: string, costUsd: number|null, unpricedRounds: number, thinkingApplied?: boolean|null}) => void}} [o]
461
623
  * `ceilingUsd` is the OPERATOR's ceiling; `null`/absent is UNBOUNDED.
462
624
  * `onCall` is a REPORTING seam fired as each metered call lands — the shell's
463
625
  * only chance to know what has been spent while the run is still alive. It is
@@ -473,6 +635,7 @@ export function makeCostBook({ ceilingUsd, onCall }?: {
473
635
  label: string;
474
636
  costUsd: number | null;
475
637
  unpricedRounds: number;
638
+ thinkingApplied?: boolean | null;
476
639
  }) => void;
477
640
  }): {
478
641
  /** @param {string} label @param {any} r a bare-agent run result @param {number} [attempt] */
@@ -537,16 +700,18 @@ export function makeCostBook({ ceilingUsd, onCall }?: {
537
700
  * `cacheMessages` (F18) and `maxTokens` (F30) are not optional on this stack.
538
701
  * `rates` is the customer's own price for this provider's key row (USD per 1K, `ratesFor`);
539
702
  * absent = bare-agent's built-in guess, exactly as before.
540
- * @param {any} provider @param {{system?: string, maxTokens?: number, rates?: {in: number, out: number}|null}} [o]
703
+ * `draftThinking` ('on' | 'off', operator knob; default 'off') adds the drafter's per-call thinking option via `draftCallOptions`.
704
+ * @param {any} provider @param {{system?: string, maxTokens?: number, rates?: {in: number, out: number}|null, draftThinking?: string}} [o]
541
705
  * @returns {(messages: any[], tools: any[], opts?: any) => Promise<any>}
542
706
  */
543
- export function makeLoopGenerate(provider: any, { system, maxTokens, rates }?: {
707
+ export function makeLoopGenerate(provider: any, { system, maxTokens, rates, draftThinking }?: {
544
708
  system?: string;
545
709
  maxTokens?: number;
546
710
  rates?: {
547
711
  in: number;
548
712
  out: number;
549
713
  } | null;
714
+ draftThinking?: string;
550
715
  }): (messages: any[], tools: any[], opts?: any) => Promise<any>;
551
716
  /**
552
717
  * ONE structured ask, with the malformed-emission retry bounded on its OWN axis.
@@ -564,7 +729,7 @@ export function makeLoopGenerate(provider: any, { system, maxTokens, rates }?: {
564
729
  * label: string, book: ReturnType<typeof makeCostBook>,
565
730
  * channel: {name: string, instruction: string, textPath?: string, tool: (box: {calls: any[]}) => any}}} o
566
731
  * @returns {Promise<{artifact: any, attempts: number, convo: any[], raw: string,
567
- * providerError: string|null, red: Red|null, budget: 'cap-halt'|'pricing-red'|null}>}
732
+ * providerError: string|null, red: Red|null, budget: 'cap-halt'|'pricing-red'|null, allCutOff?: boolean}>}
568
733
  */
569
734
  export function askStructured({ messages, generate, mode, retries, label, book, channel }: {
570
735
  messages: any[];
@@ -589,7 +754,18 @@ export function askStructured({ messages, generate, mode, retries, label, book,
589
754
  providerError: string | null;
590
755
  red: Red | null;
591
756
  budget: "cap-halt" | "pricing-red" | null;
757
+ allCutOff?: boolean;
592
758
  }>;
759
+ /**
760
+ * The confirm plan's checks as `{text, fromLine}` items. The schema asks for objects (P7: each check names the job line
761
+ * it is for); a bare string (a text-mode reply, an older caller) reads as a check with no line.
762
+ * @param {any} raw the plan's `checks`
763
+ * @returns {{text: string, fromLine: number[]|null}[]}
764
+ */
765
+ export function normalizeChecks(raw: any): {
766
+ text: string;
767
+ fromLine: number[] | null;
768
+ }[];
593
769
  /** The output channel. It records and acknowledges; it takes no action.
594
770
  * @param {{calls: any[]}} box */
595
771
  export function confirmTool(box: {
@@ -618,9 +794,9 @@ export function confirmTool(box: {
618
794
  * @param {{answers: Record<string|number, string>, questions: Record<string|number, string>,
619
795
  * labels?: Record<string|number, string>, facts?: any, listing?: string|null,
620
796
  * writeScope?: string[]|null, isRepo: boolean, lang: string, worseThanBefore?: string,
621
- * fixText?: string|null, protections?: string[]}} o
797
+ * fixText?: string|null, protections?: string[], inputs?: {n: number, label: string, value: string}[]|null}} o
622
798
  */
623
- export function confirmPrompt({ answers, questions, labels, facts, listing, writeScope, isRepo, lang, worseThanBefore, fixText, protections }: {
799
+ export function confirmPrompt({ answers, questions, labels, facts, listing, writeScope, isRepo, lang, worseThanBefore, fixText, protections, inputs }: {
624
800
  answers: Record<string | number, string>;
625
801
  questions: Record<string | number, string>;
626
802
  labels?: Record<string | number, string>;
@@ -632,6 +808,11 @@ export function confirmPrompt({ answers, questions, labels, facts, listing, writ
632
808
  worseThanBefore?: string;
633
809
  fixText?: string | null;
634
810
  protections?: string[];
811
+ inputs?: {
812
+ n: number;
813
+ label: string;
814
+ value: string;
815
+ }[] | null;
635
816
  }): string;
636
817
  /**
637
818
  * THE CONFIRM TURN: the $0 half (worse-than-before for a repo, a language
@@ -655,18 +836,18 @@ export function confirmPrompt({ answers, questions, labels, facts, listing, writ
655
836
  * generate: Function, book: ReturnType<typeof makeCostBook>,
656
837
  * ask: (step: {kind: string, [k: string]: any}) => Promise<string|null>,
657
838
  * onPhase?: (phase: string, data?: any) => void, mode?: 'tool'|'text',
658
- * worseThanBefore?: string}} o retired field (hamr's ruling 2026-09-28):
839
+ * worseThanBefore?: string, inputs?: {n: number, label: string, value: string}[]|null}} o retired field (hamr's ruling 2026-09-28):
659
840
  * `worseThanBefore` is never asked any more and defaults to `''` — a
660
841
  * caller may still pass a string through (kept for a future, non-ask
661
842
  * source of the same constraint), it just never comes from an ask() step.
662
843
  * @returns {Promise<{ok: boolean,
663
844
  * stop: null|'cap-halt'|'pricing-red'|'provider-red'|'artifact-red'|'confirm-abandoned'|'confirm-restart',
664
845
  * rounds: number,
665
- * accepted: {goal: string, checks: string[], protections: string[], lang: string,
846
+ * accepted: {goal: string, checks: string[], checkItems: {text: string, fromLine: number[]|null}[], protections: string[], lang: string,
666
847
  * worseThanBefore: string, openQuestions: string[], notChecked: string[], answeredQuestions?: string[]}|null,
667
848
  * reds: Red[], cost: any}>}
668
849
  */
669
- export function runConfirmTurn({ verdictType, answers, questions, labels, facts, listing, writeScope, isRepo, lang, generate, book, ask, onPhase, mode, worseThanBefore: presetWorseThanBefore, }: {
850
+ export function runConfirmTurn({ verdictType, answers, questions, labels, facts, listing, writeScope, isRepo, lang, generate, book, ask, onPhase, mode, worseThanBefore: presetWorseThanBefore, inputs, }: {
670
851
  verdictType: string;
671
852
  answers: Record<string | number, string>;
672
853
  questions: Record<string | number, string>;
@@ -689,6 +870,11 @@ export function runConfirmTurn({ verdictType, answers, questions, labels, facts,
689
870
  onPhase?: (phase: string, data?: any) => void;
690
871
  mode?: "tool" | "text";
691
872
  worseThanBefore?: string;
873
+ inputs?: {
874
+ n: number;
875
+ label: string;
876
+ value: string;
877
+ }[] | null;
692
878
  }): Promise<{
693
879
  ok: boolean;
694
880
  stop: null | "cap-halt" | "pricing-red" | "provider-red" | "artifact-red" | "confirm-abandoned" | "confirm-restart";
@@ -696,6 +882,10 @@ export function runConfirmTurn({ verdictType, answers, questions, labels, facts,
696
882
  accepted: {
697
883
  goal: string;
698
884
  checks: string[];
885
+ checkItems: {
886
+ text: string;
887
+ fromLine: number[] | null;
888
+ }[];
699
889
  protections: string[];
700
890
  lang: string;
701
891
  worseThanBefore: string;
@@ -746,14 +936,16 @@ export function runConfirmTurn({ verdictType, answers, questions, labels, facts,
746
936
  * generate: Function, seedReadFn?: Function, closeCtx?: any,
747
937
  * ceilingUsd?: number|null,
748
938
  * onPhase?: (phase: string, data?: any) => void,
749
- * onCall?: (call: {label: string, costUsd: number|null, unpricedRounds: number}) => void,
939
+ * onCall?: (call: {label: string, costUsd: number|null, unpricedRounds: number, thinkingApplied?: boolean|null}) => void,
750
940
  * maxRevisions?: number, structureRetries?: number,
751
941
  * structuredMode?: 'tool'|'text', catalogue?: Record<string, any>, writeScope?: string[]|null,
752
942
  * priorCalls?: {label: string, costUsd: number|null, unpricedRounds: number}[]|null,
753
943
  * priorRaws?: any[]|null,
754
- * confirmed?: {checks: string[], protections: string[], openQuestions?: string[], notChecked?: string[], answeredQuestions?: string[]}|null}} o
944
+ * jobLines?: {n: number, text: string}[]|null, inputs?: {n: number, label: string, value: string}[]|null,
945
+ * offerQuestions?: boolean,
946
+ * confirmed?: {checks: string[], checkItems?: {text: string, fromLine: number[]|null}[], protections: string[], openQuestions?: string[], notChecked?: string[], answeredQuestions?: string[]}|null}} o
755
947
  */
756
- export function authorClose({ workdir, seedRef, lang, verdictType, answers, questions, writeScope, scout, listing, priorCalls, priorRaws, confirmed, generate, seedReadFn, closeCtx, ceilingUsd, onPhase, onCall, maxRevisions, structureRetries, structuredMode, catalogue, }: {
948
+ export function authorClose({ workdir, seedRef, lang, verdictType, answers, questions, writeScope, scout, listing, priorCalls, priorRaws, confirmed, jobLines, inputs, generate, seedReadFn, closeCtx, ceilingUsd, onPhase, onCall, maxRevisions, structureRetries, structuredMode, catalogue, offerQuestions, }: {
757
949
  workdir: string;
758
950
  seedRef: string;
759
951
  lang: string;
@@ -784,6 +976,7 @@ export function authorClose({ workdir, seedRef, lang, verdictType, answers, ques
784
976
  label: string;
785
977
  costUsd: number | null;
786
978
  unpricedRounds: number;
979
+ thinkingApplied?: boolean | null;
787
980
  }) => void;
788
981
  maxRevisions?: number;
789
982
  structureRetries?: number;
@@ -796,8 +989,22 @@ export function authorClose({ workdir, seedRef, lang, verdictType, answers, ques
796
989
  unpricedRounds: number;
797
990
  }[] | null;
798
991
  priorRaws?: any[] | null;
992
+ jobLines?: {
993
+ n: number;
994
+ text: string;
995
+ }[] | null;
996
+ inputs?: {
997
+ n: number;
998
+ label: string;
999
+ value: string;
1000
+ }[] | null;
1001
+ offerQuestions?: boolean;
799
1002
  confirmed?: {
800
1003
  checks: string[];
1004
+ checkItems?: {
1005
+ text: string;
1006
+ fromLine: number[] | null;
1007
+ }[];
801
1008
  protections: string[];
802
1009
  openQuestions?: string[];
803
1010
  notChecked?: string[];
@@ -821,6 +1028,16 @@ export const REVISE_RED_CAP: 20;
821
1028
  export const AUTHOR_MAX_TOKENS: 32000;
822
1029
  /** the one slot the model fills on an injected guard */
823
1030
  export const FILL_MARKER: "<FILL IN>";
1031
+ /** P7 item 5 (fwdloop am24/25): the most questions the MACHINE keeps from the try-3 drafter. The drafter is never told this number. */
1032
+ export const MAX_QUESTIONS: 2;
1033
+ /**
1034
+ * The model-visible words of the optional `questions` property — offered ONLY on the last drafting try and only after the
1035
+ * two before it both failed validation (a mechanism, never a wish: the schema carries it on that one call and nowhere
1036
+ * else). It lives in the property's description, so the frozen revise turn stays measurement-only. No digit and no number
1037
+ * word anywhere in it (a test greps this): the machine, not the prompt, bounds the count.
1038
+ */
1039
+ export const QUESTIONS_DESCRIPTION: string;
1040
+ export function isOutputCutOff(r: any): boolean;
824
1041
  /**
825
1042
  * THE FROZEN REVISE INSTRUCTION — gate-2 round 3's own text, byte for byte
826
1043
  * (`scratch-gate2/author.mjs:63`, the turn that PASSED both arms). It is the only
@@ -889,6 +1106,15 @@ export const SOURCE_FIELD: Readonly<{
889
1106
  label: "Source";
890
1107
  prompt: "A local folder, subfolder or file, or one URL the machine can reach (no login, no setup).";
891
1108
  }>;
1109
+ /** P7: the Inputs box's wording (replaces Source). Line 1 is the repo; lines 2+ are tracked files inside it. */
1110
+ export const INPUTS_FIELD: Readonly<{
1111
+ id: "inputs";
1112
+ kind: "mechanical";
1113
+ label: "Inputs";
1114
+ prompt: string;
1115
+ }>;
1116
+ /** P7: how to write "The job" (printed under its question by the CLI; the panel's box shows the same in its examples). */
1117
+ export const JOB_BLOCK_HELP: readonly string[];
892
1118
  /** Destination's wording when Source resolved to a git repo: the answer IS the
893
1119
  * signed `writeScope` fence (ITEM33-BUILD.md M3 ruling 2). */
894
1120
  export const DESTINATION_FIELD_REPO: Readonly<{
@@ -907,8 +1133,11 @@ export const DESTINATION_FIELD_PLAIN: Readonly<{
907
1133
  prompt: string;
908
1134
  }>;
909
1135
  /**
910
- * THE FREE-TEXT TRIO EVERY CLASS SHARES: Goal, What success looks like,
911
- * Guardrails — numbered contiguously from 1. This is what `answers[1..3]` are
1136
+ * P7 (2026-10-10, docs/product/PANEL-BUILD.md): the old free-text trio (Goal, What success looks like, Guardrails) is ONE
1137
+ * answer now — "The job", the person's numbered lines with their `~` rules (src/jobblock.js renders it). What follows
1138
+ * is the history of the trio, kept because the numbering rule below still holds.
1139
+ *
1140
+ * THE FREE-TEXT SLOTS EVERY CLASS SHARES, numbered contiguously from 1. This is what `answers[1..3]` are
912
1141
  * filed under for every class; soft-green appends a fourth
913
1142
  * (`SOFTGREEN_QUESTIONS`) and hitl appends a different fourth
914
1143
  * (`HITL_QUESTIONS`), each its own next number rather than a fixed one, so a
@@ -918,7 +1147,7 @@ export const DESTINATION_FIELD_PLAIN: Readonly<{
918
1147
  * 2026-09-10 "The intake form (RULED)" ruling, `docs/product/PRD.md`) — not the
919
1148
  * old worded questions ("What do you want done?", "How do you check today
920
1149
  * whether it's working?", "...worse than before?"). Motivated by run `mtv8jihy`
921
- * (F159, `docs/logs/FINDINGS.md`): a rulebook this prompt commit did not touch
1150
+ * (F159, `docs/wiki/FINDINGS.md`): a rulebook this prompt commit did not touch
922
1151
  * still had to compile against a card built from a person's actual bar, and the
923
1152
  * old wording never matched what got signed — this reshape (commit 1ac4d05)
924
1153
  * trimmed the SET to three slots but left their PROSE unreconciled with the
@@ -927,9 +1156,7 @@ export const DESTINATION_FIELD_PLAIN: Readonly<{
927
1156
  * `authorPrompt`'s interview block and `scripts/run-interview.mjs`.
928
1157
  */
929
1158
  export const GREEN_QUESTIONS: Readonly<{
930
- 1: "what you want to achieve";
931
- 2: "checks a machine can count";
932
- 3: "what must not happen or change";
1159
+ 1: "the job, as numbered lines — each line may carry the rules (~) the person wrote under it";
933
1160
  }>;
934
1161
  /**
935
1162
  * The signed table's own label for each of {@link GREEN_QUESTIONS}' keys — "the
@@ -943,9 +1170,7 @@ export const GREEN_QUESTIONS: Readonly<{
943
1170
  * calls `questionsFor` — additive, nothing existing breaks.
944
1171
  */
945
1172
  export const FIELD_LABELS: Readonly<{
946
- 1: "Goal";
947
- 2: "What success looks like";
948
- 3: "Guardrails";
1173
+ 1: "The job";
949
1174
  }>;
950
1175
  /** The soft-green quartet's own key for Judge Examples — exported so
951
1176
  * `cardauthor.js` reads the SAME number this module files the answer under,
@@ -956,12 +1181,10 @@ export const SOFTGREEN_JUDGE_EXAMPLES_KEY: number;
956
1181
  * you'd pass and one you'd fail, and say why."). Exported so `cardauthor.js`'s
957
1182
  * prompt and this module's own `SOFTGREEN_QUESTIONS` render the identical
958
1183
  * string; its label ("Judge examples") lives in `SOFTGREEN_FIELD_LABELS`. */
959
- export const JUDGE_EXAMPLES_QUESTION: "one pass, one fail, and why";
1184
+ export const JUDGE_EXAMPLES_QUESTION: "the PASS: and FAIL: examples the person wrote under their job lines, each with its line number";
960
1185
  /** {@link FIELD_LABELS} plus Judge Examples' own label, for the soft-green set. */
961
1186
  export const SOFTGREEN_FIELD_LABELS: Readonly<{
962
- 1: "Goal";
963
- 2: "What success looks like";
964
- 3: "Guardrails";
1187
+ 1: "The job";
965
1188
  }>;
966
1189
  /**
967
1190
  * THE SOFTGREEN SET — the green trio plus Judge Examples. A judged close needs
@@ -973,9 +1196,7 @@ export const SOFTGREEN_FIELD_LABELS: Readonly<{
973
1196
  * nothing from it.
974
1197
  */
975
1198
  export const SOFTGREEN_QUESTIONS: Readonly<{
976
- 1: "what you want to achieve";
977
- 2: "checks a machine can count";
978
- 3: "what must not happen or change";
1199
+ 1: "the job, as numbered lines — each line may carry the rules (~) the person wrote under it";
979
1200
  }>;
980
1201
  /**
981
1202
  * THE HITL SET (N4 slice 1, kept in code only — never offered in the form or
@@ -986,9 +1207,7 @@ export const SOFTGREEN_QUESTIONS: Readonly<{
986
1207
  * set's next number, not a fixed one, so a green-side trim renumbers it too.
987
1208
  */
988
1209
  export const HITL_QUESTIONS: Readonly<{
989
- 1: "what you want to achieve";
990
- 2: "checks a machine can count";
991
- 3: "what must not happen or change";
1210
+ 1: "the job, as numbered lines — each line may carry the rules (~) the person wrote under it";
992
1211
  }>;
993
1212
  /**
994
1213
  * The three sets, all LIVE as of softgreen module 3. The locked shape stays
@@ -1039,7 +1258,7 @@ export const LANGUAGE_PICK_FIELD: Readonly<{
1039
1258
  prompt: "This repo has more than one supported language's manifest at the same level. Which one is this job about?";
1040
1259
  }>;
1041
1260
  /**
1042
- * F175's open half (docs/logs/FINDINGS.md, run mu0voeo4), hamr's ruling
1261
+ * F175's open half (docs/wiki/FINDINGS.md, run mu0voeo4), hamr's ruling
1043
1262
  * (2026-09-16): "Confirm" and "Type the goal yourself" may not bypass a
1044
1263
  * `questions` entry the model itself raised on the plan being accepted — the
1045
1264
  * person answers it inline, one question at a time, with NO extra model