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
@@ -1,3 +1,11 @@
1
+ /**
2
+ * The first drafting row's words (hamr 2026-10-11) — code-owned, one owner, ALWAYS starting "thinking on" or "thinking off".
3
+ * `sent` is what the drafting calls carry (`draftThinkingFor`); `thoughtAnyway` = a call reported `thinkingApplied === false`
4
+ * after 'off' was sent (bare-agent saw reasoning in the reply).
5
+ * @param {'on'|'off'|'not-switchable'|'unverified'} sent @param {boolean} [thoughtAnyway]
6
+ * @returns {string}
7
+ */
8
+ export function thinkingRowText(sent: "on" | "off" | "not-switchable" | "unverified", thoughtAnyway?: boolean): string;
1
9
  /** @typedef {{id: string, label: string, status: 'running'|'done'|'failed', detail: string}} StepLine */
2
10
  /** @param {StepLine[]} steps @param {string} id the LATEST line carrying this id (the list is a time-ordered log; an id can repeat) */
3
11
  export function latestStep(steps: StepLine[], id: string): StepLine | undefined;
@@ -9,6 +17,37 @@ export function latestStep(steps: StepLine[], id: string): StepLine | undefined;
9
17
  * @param {StepLine[]} steps @param {string} id @param {string} [detail] (absent = keep what the line has)
10
18
  */
11
19
  export function advanceSteps(steps: StepLine[], id: string, detail?: string): void;
20
+ /**
21
+ * The confirm turn's plan as a chat message (P7): a STRUCTURED `{role:'bot', kind:'plan', plan}` the page draws with the
22
+ * same renderer the Job tab uses — each numbered job line, its `~` rule, its drafted checks folded; the AI's own "not
23
+ * checked"; the always-on guards. `questions` (what the plan still asks) ride inside the plan. One owner of the shape.
24
+ * @param {{goal?: string, checks?: string[], checkItems?: {text: string, fromLine: number[]|null}[], notChecked?: string[], questions?: string[], protections?: string[]}} p the confirm turn's plan
25
+ * @param {{n: number, text: string, rule: string}[]|null} jobLines
26
+ * @returns {{role: 'bot', kind: 'plan', text: string, plan: ReturnType<typeof planFromConfirm> & {goal: string, questions: string[]}}}
27
+ */
28
+ export function planMessage(p: {
29
+ goal?: string;
30
+ checks?: string[];
31
+ checkItems?: {
32
+ text: string;
33
+ fromLine: number[] | null;
34
+ }[];
35
+ notChecked?: string[];
36
+ questions?: string[];
37
+ protections?: string[];
38
+ }, jobLines: {
39
+ n: number;
40
+ text: string;
41
+ rule: string;
42
+ }[] | null): {
43
+ role: "bot";
44
+ kind: "plan";
45
+ text: string;
46
+ plan: ReturnType<typeof planFromConfirm> & {
47
+ goal: string;
48
+ questions: string[];
49
+ };
50
+ };
12
51
  /**
13
52
  * `true` when `jobs/<name>.json` already exists in the repo's own jobs/ dir
14
53
  * (resolved from THIS module's own on-disk location, never `process.cwd()`,
@@ -22,6 +61,13 @@ export function advanceSteps(steps: StepLine[], id: string, detail?: string): vo
22
61
  export function jobNameTaken(name: string, opts?: {
23
62
  jobsDir?: string;
24
63
  }): boolean;
64
+ /**
65
+ * The repo a card names: Inputs line 1 (P7 — the Source box is gone; the first input IS the repo). `''` when the Inputs
66
+ * box does not parse (the card validator refuses that before anything uses this).
67
+ * @param {any} card
68
+ * @returns {string}
69
+ */
70
+ export function cardSource(card: any): string;
25
71
  /**
26
72
  * Only the form's own fields, nothing else a request body might carry (`startFrom`, stray keys).
27
73
  * @param {any} card
@@ -38,12 +84,12 @@ export function cardFields(card: any): Record<string, any>;
38
84
  export function lockedFieldChanged(card: Record<string, any>, origin: Record<string, any>): string | null;
39
85
  /**
40
86
  * The spec a reuse signs: a COPY of the origin's signed spec with ONLY the open fields set from the card —
41
- * `writeScope` from Destination, `budgetUsd` from the $ cap, `maxWallMs` from the Time cap (absent when blank), and the
87
+ * `writeScope` from Destination, `inputs` from the Inputs box (P7), `budgetUsd` from the $ cap, `maxWallMs` from the Time cap (absent when blank), and the
42
88
  * worker (`provider`/`baseUrl`/`model`) from the Model Name chosen in Settings > Providers, spelled exactly as normal
43
89
  * authoring spells it (`baseUrl` only when the row has one; `model` only when the Name is not the provider's default
44
90
  * tier). A RUBRIC (soft-green) origin with no explicit `judge` first has its judge pinned to the ORIGIN's resolved judge
45
91
  * identity — the judge must not change because the worker did (`resolveJobJudge`, the one spelling); an explicit
46
- * `judge` is kept; a deterministic job has no judge to move. Source is not in a spec (it lives beside the run). The copy
92
+ * `judge` is kept; a deterministic job has no judge to move. The repo (Inputs line 1) is in a spec only as `inputs`. The copy
47
93
  * hashes to a NEW `jobSpecHash` and the SAME `workflowKey` — the caller checks the second after building.
48
94
  * @param {any} originSpec
49
95
  * @param {Record<string, any>} card
@@ -53,7 +99,7 @@ export function lockedFieldChanged(card: Record<string, any>, origin: Record<str
53
99
  export function buildReuseSpec(originSpec: any, card: Record<string, any>, rows?: readonly import("../providerrows.js").KeyRow[]): any;
54
100
  /**
55
101
  * `$0` validation for a REUSE start: the signed job carries the goal, checks and guardrails, so those boxes are not
56
- * required here — only what the new session itself needs: a Source, a Destination, a Model that is a Settings Name,
102
+ * required here — only what the new session itself needs: Inputs, a Destination, a Model that is a Settings Name,
57
103
  * and the cap. (The spec built from the open boxes is validated by the route with `validateJob`.)
58
104
  * @param {any} card
59
105
  * @param {{rows?: readonly import('../providerrows.js').KeyRow[]}} [opts]
@@ -72,7 +118,7 @@ export function validateReuseCard(card: any, opts?: {
72
118
  * relative to the repo, so an absolute path is refused — at $0, before any copy or model call. A FOLDER source (or a
73
119
  * source that does not peek as a repo) keeps today's behaviour: its Destination is an absolute output directory.
74
120
  * @param {string} destination
75
- * @param {boolean} isRepoLike `looksLikeRepoSource(card.source)`
121
+ * @param {boolean} isRepoLike `looksLikeRepoSource(cardSource(card))`
76
122
  * @returns {string|null} the plain refusal, or null when the Destination is fine
77
123
  */
78
124
  export function repoDestinationProblem(destination: string, isRepoLike: boolean): string | null;
@@ -96,12 +142,12 @@ export function validateJobCard(card: any, opts?: {
96
142
  /**
97
143
  * ONE session's engine — created already RUNNING (the caller awaits nothing;
98
144
  * the pipeline drives itself, reporting through `state`). `state.pendingAsk`
99
- * is the ONE thing a person answers next; `answer()`/`send()`/`revise()`/
145
+ * is the ONE thing a person answers next; `answer()`/`send()`/
100
146
  * `signPrepare()` are the only ways in.
101
147
  * @param {any} card the validated job card (see {@link validateJobCard})
102
148
  * @param {{env?: Record<string,string|undefined>, sessionsRoot?: string, home?: string, timeoutMs?: number,
103
149
  * scout?: any, generate?: Function, confirmGenerate?: Function, authorFn?: Function,
104
- * prepareSigningFn?: Function, npmCiFn?: Function, reuse?: {spec: any, workflowKey: string}}} [deps] `scout`..`prepareSigningFn` are
150
+ * prepareSigningFn?: Function, npmCiFn?: Function, draftThinking?: "on"|"off", reuse?: {spec: any, workflowKey: string}}} [deps] `scout`..`prepareSigningFn` are
105
151
  * TEST SEAMS ONLY — see the note just above where each is read, below. `reuse` (Reuse workflow) is NOT a seam: the
106
152
  * caller (`/api/author/start`) sets it only when the server's own same-job rule held.
107
153
  * @returns {any} the session object
@@ -117,6 +163,7 @@ export function createSession(card: any, deps?: {
117
163
  authorFn?: Function;
118
164
  prepareSigningFn?: Function;
119
165
  npmCiFn?: Function;
166
+ draftThinking?: "on" | "off";
120
167
  reuse?: {
121
168
  spec: any;
122
169
  workflowKey: string;
@@ -135,11 +182,13 @@ export const STEP_LABELS: Readonly<Record<string, string>>;
135
182
  * @type {Readonly<Record<string, keyof typeof STEP_LABELS>>}
136
183
  */
137
184
  export const PHASE_STEP: Readonly<Record<string, keyof typeof STEP_LABELS>>;
185
+ /** the line under the plan bubble, in plain words (the bubble itself is drawn by the page's one `renderJobPlan`) */
186
+ export const PLAN_FOOTER: "Sign & run to confirm this plan, or Revise to edit the boxes and draft again.";
138
187
  /** the form's fields, in card order — what `card.json` stores, verbatim (P5 item 3) */
139
188
  export const CARD_FIELDS: readonly string[];
140
189
  /**
141
190
  * REUSE WORKFLOW (hamr 2026-10-03, replaces P5 item 3's same-job rule; Model opened 2026-10-04): a reuse card has exactly
142
- * FIVE open boxes — Source, Destination, Model, $ cap, Time cap — and every other box is the signed workflow, shown greyed and never
191
+ * FIVE open boxes — Inputs, Destination, Model, $ cap, Time cap — and every other box is the signed workflow, shown greyed and never
143
192
  * editable. The page greys them; THIS is what refuses (the server never trusts the page). Changing any locked box
144
193
  * is a different job: Clear the card, which drafts.
145
194
  */
@@ -153,4 +202,5 @@ export type StepLine = {
153
202
  status: "running" | "done" | "failed";
154
203
  detail: string;
155
204
  };
205
+ import { planFromConfirm } from './jobplan.js';
156
206
  import { nonRepoSourceMessage } from '../source.js';
@@ -0,0 +1,58 @@
1
+ /** @typedef {{name: string, cls: 'machine check'|'judge'|null}} PlanCheck */
2
+ /** @typedef {{n: number, text: string, rule: string, checks: PlanCheck[], refused: string[]}} PlanLine */
3
+ /** @typedef {{lines: PlanLine[], loose: PlanCheck[], notChecked: string[], alwaysOn: string[], older: boolean, goal?: string}} JobPlan */
4
+ /**
5
+ * `machine check` for a kind a command decides, `judge` for one that needs judgement; `null` for a stage whose kind is
6
+ * unknown (a hand-written command close has no kind: it is a command, so a machine check).
7
+ * @param {unknown} kind
8
+ * @returns {'machine check'|'judge'|null}
9
+ */
10
+ export function checkClassOfKind(kind: unknown): "machine check" | "judge" | null;
11
+ /**
12
+ * The plan of a SIGNED spec. With `jobLines`, each stage lands under EACH line its `fromLine` array names (a stage with none is
13
+ * a mandatory guard: "Always on"), `closeDecl.refused` reasons land under their line, and `closeDecl.notes` are the
14
+ * drafter's own "not checked" words. Without `jobLines` (a spec that predates the job block) the signed goal sentence is
15
+ * line 1 and every stage name is a check under it — `older: true`.
16
+ * @param {any} spec
17
+ * @returns {JobPlan}
18
+ */
19
+ export function planFromSpec(spec: any): JobPlan;
20
+ /**
21
+ * The plan of the confirm turn, before anything is drafted: the person's own job lines, the model's checks under the
22
+ * line each names, its own "not checked" words, and the real protections (code-owned) as "Always on".
23
+ * @param {{n: number, text: string, rule: string}[]|null|undefined} jobLines
24
+ * @param {{checkItems?: {text: string, fromLine: number[]|null}[], checks?: string[], notChecked?: string[], protections?: string[]}} plan
25
+ * @returns {JobPlan}
26
+ */
27
+ export function planFromConfirm(jobLines: {
28
+ n: number;
29
+ text: string;
30
+ rule: string;
31
+ }[] | null | undefined, plan: {
32
+ checkItems?: {
33
+ text: string;
34
+ fromLine: number[] | null;
35
+ }[];
36
+ checks?: string[];
37
+ notChecked?: string[];
38
+ protections?: string[];
39
+ }): JobPlan;
40
+ export type PlanCheck = {
41
+ name: string;
42
+ cls: "machine check" | "judge" | null;
43
+ };
44
+ export type PlanLine = {
45
+ n: number;
46
+ text: string;
47
+ rule: string;
48
+ checks: PlanCheck[];
49
+ refused: string[];
50
+ };
51
+ export type JobPlan = {
52
+ lines: PlanLine[];
53
+ loose: PlanCheck[];
54
+ notChecked: string[];
55
+ alwaysOn: string[];
56
+ older: boolean;
57
+ goal?: string;
58
+ };
@@ -298,6 +298,26 @@ export function getRunRounds(runid: string, query?: {
298
298
  }, opts?: {
299
299
  home?: string;
300
300
  }): any | null;
301
+ /**
302
+ * The Signed row of the Job tab: `YYYY-MM-DD HH:MM · <first 6 of specHash>`, the time being the run's FIRST `job-start`
303
+ * in local time (hamr, P7). `null` when either part is not on record — never a made-up stamp.
304
+ * @param {string|null|undefined} ts an ISO stamp @param {string|null|undefined} hash
305
+ * @returns {string|null}
306
+ */
307
+ export function signedLine(ts: string | null | undefined, hash: string | null | undefined): string | null;
308
+ /**
309
+ * The Job box's text for a signed spec: the person's own numbered lines (a `~` line per entry of `rules`, or — for a spec
310
+ * signed before `rules` existed — per '; '-split piece of `rule`), or — for
311
+ * an older job that saved no job lines — the signed goal sentence as the one line.
312
+ * @param {any} spec @returns {string}
313
+ */
314
+ export function jobTextFromSpec(spec: any): string;
315
+ /**
316
+ * The Inputs box's text for a signed spec: its numbered inputs, or — for an older job — `repo: <source>` from the
317
+ * caller's best knowledge of the source (or empty).
318
+ * @param {any} spec @param {string} source @returns {string}
319
+ */
320
+ export function inputsTextFromSpec(spec: any, source: string): string;
301
321
  /**
302
322
  * `GET /api/runs/:runid/job` — the Job tab, filled from the first source
303
323
  * that actually resolves (item 2, 2026-09-25), in order:
@@ -221,7 +221,7 @@ export function planPrompt(job: any, scoutBlob: string, reds: any[] | null, maxS
221
221
  * item 27/M3 Part B), forwarded to every close invocation as
222
222
  * `BARELOOP_CLOSE_DIR`
223
223
  * @param {number} [opts.maxStepRounds] the shell's per-step rounds ceiling (validatePlan's bound)
224
- * @param {boolean} [opts.scout=true] operator-only switch (docs/product/SCOUT-CONTRAST.md):
224
+ * @param {boolean} [opts.scout=true] operator-only switch (docs/logs/SCOUT-CONTRAST.md):
225
225
  * `false` on a FRESH run (no `resumeSeed`) skips the survey entirely — `scoutBlob`
226
226
  * stays `''`, no `scout-start`/`scout-result`/`scout-empty` is emitted, and a single
227
227
  * `scout-skipped {reason:'operator-off'}` records it (a RECORD, never silence — the
@@ -1,3 +1,47 @@
1
+ /**
2
+ * The per-call options the rubric JUDGE's model calls carry for this provider instance: `{ thinkingMode: 'off' }` when
3
+ * bare-agent measures the model switchable, else `{}` (F192: judge runs thinking off; a judge on a model that cannot turn it
4
+ * off must not throw).
5
+ * @param {any} provider a constructed bare-agent provider
6
+ * @returns {Record<string, any>}
7
+ */
8
+ export function judgeCallOptions(provider: any): Record<string, any>;
9
+ /**
10
+ * Throw unless `mode` is one of {@link DRAFT_THINKING_MODES} — an operator-param guard, so a typo never silently means a mode.
11
+ * @param {unknown} mode
12
+ * @returns {'on'|'off'}
13
+ */
14
+ export function assertDraftThinking(mode: unknown): "on" | "off";
15
+ /**
16
+ * What the drafting calls on this provider ACTUALLY carry for thinking, for the draft log and the panel row: `'on'` (mode on,
17
+ * nothing sent), `'off'` (mode off and the switch is sent), `'not-switchable'` (mode off, model measured not switchable —
18
+ * nothing sent), `'unverified'` (mode off, model not measured by bare-agent — nothing sent). Never re-derives a model list.
19
+ * @param {any} provider a constructed bare-agent provider
20
+ * @param {unknown} [mode] 'on' | 'off' (default 'off')
21
+ * @returns {'on'|'off'|'not-switchable'|'unverified'}
22
+ */
23
+ export function draftThinkingSent(provider: any, mode?: unknown): "on" | "off" | "not-switchable" | "unverified";
24
+ /**
25
+ * {@link draftThinkingSent} for a model the caller has only NAMED (provider shape, model id, baseUrl) — no key, no network. For
26
+ * the panel's first drafting row, which is shown before the key is read. Constructing the provider only makes the class and
27
+ * the model id available to `thinkingSupport`; it sends nothing.
28
+ * @param {{providerName: string, model: string, baseUrl?: string|null}} o
29
+ * @param {unknown} [mode] 'on' | 'off' (default 'off')
30
+ * @returns {'on'|'off'|'not-switchable'|'unverified'}
31
+ */
32
+ export function draftThinkingFor({ providerName, model, baseUrl }: {
33
+ providerName: string;
34
+ model: string;
35
+ baseUrl?: string | null;
36
+ }, mode?: unknown): "on" | "off" | "not-switchable" | "unverified";
37
+ /**
38
+ * The ONE owner of the per-call options every DRAFTING model call carries (scout, confirm, author, revise, structure retries).
39
+ * `{ thinkingMode: 'off' }` exactly when {@link draftThinkingSent} says `'off'`, else `{}`.
40
+ * @param {any} provider a constructed bare-agent provider
41
+ * @param {unknown} [mode] 'on' | 'off' (default 'off')
42
+ * @returns {Record<string, any>}
43
+ */
44
+ export function draftCallOptions(provider: any, mode?: unknown): Record<string, any>;
1
45
  /**
2
46
  * Look up a provider's table entry. Throws a NAMED error on an unrecognized
3
47
  * provider — never a silent default (the `resolveRates`-style-substring-
@@ -11,7 +55,7 @@ export function resolveProvider(providerName: string): ProviderTableEntry;
11
55
  /**
12
56
  * Report whether a resolved API key VALUE (not its presence — every call
13
57
  * site already presence-checks separately) carries a shape an HTTP header
14
- * value cannot: F181 (`docs/logs/FINDINGS.md`) — a two-line secret-store
58
+ * value cannot: F181 (`docs/wiki/FINDINGS.md`) — a two-line secret-store
15
59
  * entry put the key plus a trailing metadata line into `OPENAI_API_KEY`
16
60
  * (`"<key>\nmeta"`), the presence-only check at every door passed, and Node
17
61
  * crashed `TypeError [ERR_INVALID_CHAR]` inside its own header-encode at the
@@ -210,6 +254,13 @@ export const PROBE_STATUS: Readonly<Record<string, {
210
254
  probed: boolean;
211
255
  evidence: string;
212
256
  }>>;
257
+ /**
258
+ * The drafter's THINKING knob — an enumerated OPERATOR param, never model output and never read from env inside the library.
259
+ * `'on'` sends nothing (the model's own thinking, byte-identical to a no-knob call); `'off'` sends `thinkingMode: 'off'` where
260
+ * bare-agent measures the model switchable. The DEFAULT is `'off'` (hamr 2026-10-11, decided by the frozen ON/OFF contrast,
261
+ * docs/logs/2026-10-10-drafter-thinking-contrast-prereg.md); `'on'` stays selectable for a later Settings checkbox.
262
+ */
263
+ export const DRAFT_THINKING_MODES: readonly string[];
213
264
  export type ProviderTableEntry = {
214
265
  /**
215
266
  * the bare-agent provider class
package/types/run.d.ts CHANGED
@@ -158,7 +158,7 @@
158
158
  * frozen A0 baseline arm has to be exactly today, so a guard firing under a disabled
159
159
  * shim would make the baseline a treatment arm. The default-flip belongs to a
160
160
  * paid contrast nobody has approved yet (the `layerRoot` precedent, F41).
161
- * @param {boolean} [opts.scout=true] operator-only switch (docs/product/SCOUT-CONTRAST.md),
161
+ * @param {boolean} [opts.scout=true] operator-only switch (docs/logs/SCOUT-CONTRAST.md),
162
162
  * forwarded verbatim to the plan flow: `false` on a fresh run (no `resumeSeed`) skips the
163
163
  * read-only survey and records `scout-skipped {reason:'operator-off'}` instead — the
164
164
  * planner drafts from `(no scout notes)`. Runner territory exactly like `readShim`: the
package/types/source.d.ts CHANGED
@@ -304,6 +304,32 @@ export function frontDoorFromManifest(read: {
304
304
  * @returns {string}
305
305
  */
306
306
  export function nonRepoSourceMessage(kind: string): string;
307
+ /**
308
+ * P7 (docs/product/PANEL-BUILD.md, "Inputs"): prove the NUMBERED INPUTS at $0, before any token. Line 1 is the repo
309
+ * (an absolute path to an existing folder); lines 2+ are files or folders INSIDE that repo, repo-relative. A line
310
+ * that is not one of those is a named red naming its line number — never a throw, never a silent skip:
311
+ * - a `search:` line or a URL, and a path that leaves the repo: "only files inside the repo for now" (search and
312
+ * outside-the-repo inputs arrive with the plain-folder piece);
313
+ * - a path that does not exist, or that git does not track (a repo job would not see it);
314
+ * - the front door's own refusals for a file: an environment file by NAME, a symlink, a non-text file, an oversize
315
+ * file. A known secret shape in its content is NOT a refusal (masked where recorded, as the P6 worktree door does).
316
+ * A folder value is checked for existence and tracking only (its files are the repo's own, which the worktree door
317
+ * already masks). Reads the tree; writes nothing.
318
+ * @param {{n: number, label: string, value: string}[]} inputs the parsed Inputs (`parseInputs`)
319
+ * @returns {Promise<{ok: true, repo: string, root: string|null}|{ok: false, error: string}>} `repo` = line 1's absolute path; `root` = the git root it sits in (null when line 1 alone was given and it is not in a git repo)
320
+ */
321
+ export function proveInputFiles(inputs: {
322
+ n: number;
323
+ label: string;
324
+ value: string;
325
+ }[]): Promise<{
326
+ ok: true;
327
+ repo: string;
328
+ root: string | null;
329
+ } | {
330
+ ok: false;
331
+ error: string;
332
+ }>;
307
333
  /**
308
334
  * a named, non-throwing stop
309
335
  */
package/types/trend.d.ts CHANGED
@@ -54,6 +54,7 @@ export function createTrend({ stageOrder, limit, blindCap, seed, directions }?:
54
54
  * @param {{gap?: string, stage?: string|null, value?: number|null}} o either a
55
55
  * raw gap (parsed here) or an already-read `{stage, value}` — never both
56
56
  * spellings of the same reading in one call.
57
+ * (A judged stage's value is its distinct red COUNT, supplied by the caller.)
57
58
  * @returns {{iteration: number, stage: string, value: number|null, improved: boolean,
58
59
  * comparable: boolean, noProgress: number, limit: number, stageIndex: number}}
59
60
  */