@evoke-build/evoke 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/core.wasm CHANGED
Binary file
package/dist/index.d.ts CHANGED
@@ -7,4 +7,4 @@ export type { Context, Reflex, Result } from "./runtime.ts";
7
7
  export type { Adapter, Trace } from "./adapter.ts";
8
8
  export { DiagnosticError, EvokeError, FailureError, FaultError } from "./errors.ts";
9
9
  export type { Problem } from "./errors.ts";
10
- export type { Because, Binding, Bound, Cap, Choices, Contained, Contender, Diagnostic, Effect, Fault, Fix, Gate, Judgment, Limits, Missing, Needs, Prompt, Question, NonEmpty, Raw, Recognizer, Span, State, Status, Step, Text, Verdict, Weave, WeaveWhy, Why, Yield, } from "./types.ts";
10
+ export type { Answer, Because, Binding, Bound, Cap, Choices, Contained, Contender, Diagnostic, Effect, Fault, Fix, Gate, Judgment, Limits, Missing, Needs, Pinned, PinnedReflex, Prompt, Question, NonEmpty, Raw, Recognizer, Span, State, Status, Step, Text, Verdict, Weave, WeaveWhy, Why, Yield, } from "./types.ts";
package/dist/ops.d.ts CHANGED
@@ -108,6 +108,7 @@ export interface Ops {
108
108
  compile: {
109
109
  input: {
110
110
  set: T.Installed;
111
+ values?: T.Values;
111
112
  limits?: T.Limits;
112
113
  platform?: T.Platform;
113
114
  };
@@ -413,6 +414,46 @@ export interface Ops {
413
414
  };
414
415
  output: T.Running;
415
416
  };
417
+ "weave.pin": {
418
+ input: {
419
+ installed: T.Installed;
420
+ plan: T.Plan;
421
+ project: T.Project;
422
+ lock?: T.Lock;
423
+ declared: T.Declared;
424
+ input: string;
425
+ tags: T.Tag[];
426
+ weave: T.Weave;
427
+ answers: T.Answer[];
428
+ };
429
+ output: T.Pinned;
430
+ };
431
+ "weave.pinned": {
432
+ input: {
433
+ path: string;
434
+ json: T.Json;
435
+ };
436
+ output: T.Result<T.Pinned, T.Diagnostic>;
437
+ };
438
+ "weave.stale": {
439
+ input: {
440
+ path: string;
441
+ pinned: T.Pinned;
442
+ installed: T.Installed;
443
+ plan: T.Plan;
444
+ lock?: T.Lock;
445
+ declared: T.Declared;
446
+ };
447
+ output: T.Result<null, T.Diagnostic>;
448
+ };
449
+ "weave.replan": {
450
+ input: {
451
+ path: string;
452
+ pinned: T.Pinned;
453
+ plan: T.Plan;
454
+ };
455
+ output: T.Result<T.Replanned, T.Diagnostic>;
456
+ };
416
457
  "systemone.settings": {
417
458
  input: {
418
459
  door: T.Door;
package/dist/project.d.ts CHANGED
@@ -58,6 +58,15 @@ export interface WeaveOptions<R = AnyReflexes> extends DecideOptions {
58
58
  * runs the plan as it stands. Absent and reached: nothing runs. */
59
59
  proceed?: ((plan: W.Weave) => boolean | Promise<boolean>) | undefined;
60
60
  }
61
+ /** What `weave` takes for a plan read from a file — a `Pinned`, as `steps` returned it or as `JSON.parse` read it
62
+ * back — beside a step's handlers: the yes over the whole plan, asked whatever its verdict, since a file's numbers
63
+ * are whoever wrote them. Absent and reached: nothing runs, `unanswered`. The tags are the file's. */
64
+ export interface PinnedOptions<R = AnyReflexes> {
65
+ confirm?: WeaveOptions<R>["confirm"];
66
+ ask?: WeaveOptions<R>["ask"];
67
+ proceed?: ((pinned: W.Pinned) => boolean | Promise<boolean>) | undefined;
68
+ signal?: AbortSignal | undefined;
69
+ }
61
70
  /** One round of a step as it ran: the decision the loop settled, the input its body saw, what became of it. */
62
71
  export interface WovenRound<R = AnyReflexes> {
63
72
  round: number;
@@ -120,10 +129,17 @@ export interface Project<R = AnyReflexes> {
120
129
  /** The whole loop: decide; ask and fill until nothing is missing; confirm; run. */
121
130
  handle(input: string, options?: DecideOptions & Handlers<R>): Promise<Handled<R>>;
122
131
  /** One request read into its steps, each decided as `decide` decides one, ordered by the words, a result of
123
- * one threaded into a later one: the plan alone, its verdict before anything runs. Runs nothing. */
124
- steps(input: string, options?: DecideOptions): Promise<W.Weave>;
132
+ * one threaded into a later one, sealed as a plan file: the sentence, the plan with its verdict before anything
133
+ * runs, every answer the plan took and the pins they were gathered under. `JSON.stringify` writes it; `weave`
134
+ * takes it, here or on another machine with the same project. Runs nothing. */
135
+ steps(input: string, options?: DecideOptions): Promise<W.Pinned>;
125
136
  /** The steps, what the plan asks first answered, then every step run stage by stage under the same handlers. */
126
137
  weave(input: string, options?: WeaveOptions<R>): Promise<Woven<R>>;
138
+ /** A plan file run exactly: its pins checked against this project — a `DiagnosticError` names the first that
139
+ * moved and its fix — the plan made again from the file's answers under the file's gate and refused when it does
140
+ * not read the same, `proceed` asked, then every step run under the same handlers, a value bound at run time
141
+ * decided by this project's adapter. */
142
+ weave(pinned: W.Pinned, options?: PinnedOptions<R>): Promise<Woven<R>>;
127
143
  }
128
144
  /** A project from its root: its installed reflexes are what `Reflexes` from evoke.d.ts names, so R is written. */
129
145
  export declare function load<R extends object = AnyReflexes>(options: {
package/dist/project.js CHANGED
@@ -2,8 +2,10 @@
2
2
  // once; never fetched, never written. On it: `with`, the same project over a vocabulary of the call's own — a
3
3
  // tenant's words, their own plan in milliseconds; `decide`, one input asked, answered, read and gated; `fill`, an
4
4
  // ask answered and gated again; `run`, the chosen call's body; `handle`, the whole loop; `steps`, one request
5
- // read into steps, and `weave`, the steps run stage by stage under the same handlers. In: LoadOptions; inputs;
6
- // decisions. Out: a Project, decisions, results, plans.
5
+ // read into steps and sealed as a plan file — the sentence, the answers, the pins — and `weave`, the steps run
6
+ // stage by stage under the same handlers, from a sentence or from such a file, whose pins are checked and whose
7
+ // plan is made again from its answers. In: LoadOptions; inputs; decisions; plan files. Out: a Project, decisions,
8
+ // results, plans.
7
9
  import { realpathSync, statSync } from "node:fs";
8
10
  import { homedir } from "node:os";
9
11
  import { answered } from "./adapter.js";
@@ -24,6 +26,7 @@ export async function load(options) {
24
26
  const lock = files.lock === undefined ? undefined : call("lock", { doc: { file: { type: "lock" }, toml: files.lock } }, "load()");
25
27
  const adapter = options.adapter ?? (await named(project, root));
26
28
  const reflexes = {};
29
+ const values = {};
27
30
  const dirs = {};
28
31
  const bodies = {};
29
32
  const shipped = {};
@@ -39,6 +42,10 @@ export async function load(options) {
39
42
  throw refused(name, `${name} is both in evoke.toml and passed to load`, { type: "remove", reflex: name });
40
43
  }
41
44
  const configured = held(project.config[name] ?? {});
45
+ for (const [key, setting] of Object.entries(project.config[name] ?? {})) {
46
+ if (setting.type === "plain")
47
+ (values[name] ??= {})[key] = setting.value;
48
+ }
42
49
  if (location.type === "local") {
43
50
  if (root === undefined)
44
51
  throw refused(name, `${name} is a local reflex, but load has no root`, { type: "remove", reflex: name });
@@ -94,7 +101,7 @@ export async function load(options) {
94
101
  }
95
102
  const installed = { reflexes, vocab, adapter: adapter.id, evoke: call("version", {}) };
96
103
  const platform = options.platform ?? PLATFORM;
97
- return make({ installed, adapter, platform, dirs, bodies, shipped, local }, "load()");
104
+ return make({ installed, values, project, lock, adapter, platform, dirs, bodies, shipped, local }, "load()");
98
105
  }
99
106
  /** The adapter evoke.toml names, from its own subpath; a recording is never resolved by name. */
100
107
  async function named(project, root) {
@@ -134,11 +141,12 @@ function word(name, doc, overlay) {
134
141
  const effective = call("effective", { shipped: manifest, ...(yours === undefined ? {} : { yours }) });
135
142
  return { wording: { ok: effective }, manifest };
136
143
  }
137
- /** How each configured key is held: the value, or a variable and whether it is set — never a secret's value. */
144
+ /** How each configured key is held: plain, its value handed beside the set, or a variable and whether it is set —
145
+ * never a value, never a secret. */
138
146
  function held(settings) {
139
147
  const held = {};
140
148
  for (const [key, setting] of Object.entries(settings)) {
141
- held[key] = setting.type === "plain" ? setting : { type: "env", var: setting.var, set: process.env[setting.var] !== undefined };
149
+ held[key] = setting.type === "plain" ? { type: "plain" } : { type: "env", var: setting.var, set: process.env[setting.var] !== undefined };
142
150
  }
143
151
  return held;
144
152
  }
@@ -178,11 +186,14 @@ function askedFor(step, tags) {
178
186
  const own = narrowed ? step.reflex : undefined;
179
187
  return own === undefined ? { text: step.text, tags } : { text: step.text, only: own };
180
188
  }
189
+ function gathering() {
190
+ return { answers: { decided: [] }, traces: new Map(), entries: [] };
191
+ }
181
192
  /** The project over its ground: the set compiled, every reflex's status read off the plan. The implementation
182
193
  * speaks the wire's shapes; the app's R lives on the interface alone. */
183
194
  function make(ground, invoked) {
184
- const { installed, adapter, platform, dirs, bodies, shipped, local } = ground;
185
- const plan = call("compile", { set: installed, platform, ...(adapter.limits === undefined ? {} : { limits: adapter.limits }) }, invoked);
195
+ const { installed, values, project: owned, lock, adapter, platform, dirs, bodies, shipped, local } = ground;
196
+ const plan = call("compile", { set: installed, values, platform, ...(adapter.limits === undefined ? {} : { limits: adapter.limits }) }, invoked);
186
197
  if (adapter.plan !== undefined && adapter.plan !== plan.digest) {
187
198
  const message = `the recording was made against plan ${adapter.plan}, not ${plan.digest}`;
188
199
  throw new DiagnosticError([{ message, fix: { type: "rerun" }, command: "replay(file, { record: jev() })" }]);
@@ -198,6 +209,8 @@ function make(ground, invoked) {
198
209
  }
199
210
  }
200
211
  const gate = adapter.gate === undefined ? {} : { gate: adapter.gate };
212
+ const declared = { id: adapter.id, ...(adapter.limits === undefined ? {} : { limits: adapter.limits }), ...gate };
213
+ const locked = lock === undefined ? {} : { lock };
201
214
  const project = {
202
215
  reflexes,
203
216
  plan: plan.digest,
@@ -218,12 +231,7 @@ function make(ground, invoked) {
218
231
  },
219
232
  async decide(input, options = {}) {
220
233
  nonEmpty(input, "decide");
221
- const invoked = invocation(input);
222
- const request = call("request", { plan, input, tags: options.tags ?? [], ...(options.only === undefined ? {} : { only: options.only }), scope: "full" }, invoked);
223
- const { raw, trace } = await answered(adapter, request, plan.deadline, options.signal, invoked);
224
- const reading = call("read", { plan, request, raw }, invoked);
225
- const decision = call("gate", { plan, reading, ...gate });
226
- return lined(decision, { input, plan: plan.digest, trace: [trace] });
234
+ return (await decidedText(input, options)).decision;
227
235
  },
228
236
  fill(decision, given) {
229
237
  const asking = own(decision, "fill");
@@ -269,19 +277,23 @@ function make(ground, invoked) {
269
277
  },
270
278
  async steps(input, options = {}) {
271
279
  nonEmpty(input, "steps");
272
- return planned(input, options, { decided: [] }, new Map());
280
+ const gathered = gathering();
281
+ const weave = await planned(input, options, gathered);
282
+ return call("weave.pin", { installed, plan, project: owned, ...locked, declared, input, tags: options.tags ?? [], weave, answers: gathered.entries });
273
283
  },
274
284
  async weave(input, options = {}) {
285
+ if (typeof input !== "string")
286
+ return pinnedRun(input, options);
287
+ const handlers = options;
275
288
  nonEmpty(input, "weave");
276
- const traces = new Map();
277
- const answers = { decided: [] };
278
- let woven = await planned(input, options, answers, traces);
289
+ const gathered = gathering();
290
+ let woven = await planned(input, handlers, gathered);
279
291
  // What the plan asks before anything runs: a step's own question, answered, and the plan made again.
280
292
  while (woven.verdict.outcome === "ask") {
281
- const filled = await askedUpFront(woven, answers, options, traces);
293
+ const filled = await askedUpFront(woven, gathered.answers, handlers, gathered.traces);
282
294
  if (filled !== "filled")
283
295
  return { plan: woven, status: filled, steps: [] };
284
- const again = await planned(input, options, answers, traces);
296
+ const again = await planned(input, handlers, gathered);
285
297
  // A plan that asks the same again could not take the answer: unanswered, never a loop.
286
298
  if (JSON.stringify(again.verdict) === JSON.stringify(woven.verdict))
287
299
  return { plan: again, status: "unanswered", steps: [] };
@@ -290,17 +302,28 @@ function make(ground, invoked) {
290
302
  if (woven.verdict.outcome === "refuse")
291
303
  return { plan: woven, status: "refused", steps: [] };
292
304
  if (woven.verdict.outcome === "confirm") {
293
- if (options.proceed === undefined)
305
+ if (handlers.proceed === undefined)
294
306
  return { plan: woven, status: "unanswered", steps: [] };
295
- if (!(await options.proceed(woven)))
307
+ if (!(await handlers.proceed(woven)))
296
308
  return { plan: woven, status: "declined", steps: [] };
297
309
  }
298
- return executed(woven, options, traces);
310
+ return executed(woven, handlers, gathered);
299
311
  },
300
312
  };
301
- /** The plan over the answers gathered so far: the adapter asked and texts decided until it stands. */
302
- async function planned(input, options, answers, traces) {
313
+ /** One text asked, answered, read and gated, its raw answers kept beside the decision — for the plan file. */
314
+ async function decidedText(input, options) {
315
+ const invoked = invocation(input);
316
+ const request = call("request", { plan, input, tags: options.tags ?? [], ...(options.only === undefined ? {} : { only: options.only }), scope: "full" }, invoked);
317
+ const { raw, trace } = await answered(adapter, request, plan.deadline, options.signal, invoked);
318
+ const reading = call("read", { plan, request, raw }, invoked);
319
+ const decision = call("gate", { plan, reading, ...gate });
320
+ return { decision: lined(decision, { input, plan: plan.digest, trace: [trace] }), raw };
321
+ }
322
+ /** The plan over the answers gathered so far: the adapter asked and texts decided until it stands, every answer
323
+ * kept as an entry of the plan file. */
324
+ async function planned(input, options, gathered) {
303
325
  const invoked = `steps(${JSON.stringify(shown(input))})`;
326
+ const { answers, entries } = gathered;
304
327
  for (;;) {
305
328
  const planning = call("weave.plan", { plan, ...gate, input, tags: options.tags ?? [], answers }, invoked);
306
329
  if (planning.type === "done")
@@ -308,26 +331,69 @@ function make(ground, invoked) {
308
331
  const { need } = planning;
309
332
  if (need.type === "decide") {
310
333
  // Side by side: each text is its own adapter call.
311
- answers.decided.push(...(await Promise.all(need.asked.map(async (asked) => [asked, await decided(asked, options, traces)]))));
334
+ const decisions = await Promise.all(need.asked.map(async (asked) => [asked, await decided(asked, options, gathered)]));
335
+ answers.decided.push(...decisions);
312
336
  continue;
313
337
  }
314
338
  const { raw } = await answered(adapter, need.request, plan.deadline, options.signal, invoked);
339
+ entries.push({ text: need.request.state.request, raw });
315
340
  if (need.type === "judge")
316
341
  answers.judged = raw;
317
342
  else
318
343
  answers.referred = raw;
319
344
  }
320
345
  }
321
- /** One text decided as the plan asks — over the tags, or one reflex alone — its trace kept by what was asked. */
322
- async function decided(asked, options, traces) {
323
- const decision = await project.decide(asked.text, {
346
+ /** One text decided as the plan asks — over the tags, or one reflex alone — its trace kept by what was asked and
347
+ * its raw answers as an entry. */
348
+ async function decided(asked, options, gathered) {
349
+ const { decision, raw } = await decidedText(asked.text, {
324
350
  ...(asked.only === undefined ? { tags: asked.tags ?? [] } : { only: asked.only }),
325
351
  ...(options.signal === undefined ? {} : { signal: options.signal }),
326
352
  });
327
- traces.set(key(asked), decision.trace);
353
+ gathered.traces.set(key(asked), decision.trace);
354
+ gathered.entries.push({ text: asked.text, raw });
328
355
  // The whole decision crosses: the core reads its own fields and ignores the SDK's.
329
356
  return decision;
330
357
  }
358
+ /** A plan file run: read through the core, `plan = 1` required; its pins against this project, the first that
359
+ * moved refused; the plan made again from its answers under its gate, refused when it does not read the same;
360
+ * a plan that asks or refuses runs nothing, since a file holds no one's answers; then the yes over the whole
361
+ * plan, and every step under the handlers, a value bound at run time decided by this project's adapter. */
362
+ async function pinnedRun(json, options) {
363
+ const path = "plan";
364
+ const sentence = typeof json === "object" && json !== null && typeof json.input === "string" ? json.input : "<input>";
365
+ const pinned = planFile("weave.pinned", { path, json }, sentence);
366
+ planFile("weave.stale", { path, pinned, installed, plan, ...locked, declared }, pinned.input);
367
+ const replanned = planFile("weave.replan", { path, pinned, plan }, pinned.input);
368
+ const woven = replanned.weave;
369
+ if (woven.verdict.outcome === "ask")
370
+ return { plan: woven, status: "unanswered", steps: [] };
371
+ if (woven.verdict.outcome === "refuse")
372
+ return { plan: woven, status: "refused", steps: [] };
373
+ if (options.proceed === undefined)
374
+ return { plan: woven, status: "unanswered", steps: [] };
375
+ if (!(await options.proceed(pinned)))
376
+ return { plan: woven, status: "declined", steps: [] };
377
+ const handlers = {
378
+ tags: pinned.tags ?? [],
379
+ ...(options.confirm === undefined ? {} : { confirm: options.confirm }),
380
+ ...(options.ask === undefined ? {} : { ask: options.ask }),
381
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
382
+ };
383
+ return executed(woven, handlers, gathering());
384
+ }
385
+ /** One op over a plan file: its refusal a `DiagnosticError` whose save line reads as the call that makes the
386
+ * plan again here. */
387
+ function planFile(op, input, sentence) {
388
+ const answer = reply(op, input);
389
+ if ("ok" in answer)
390
+ return answer.ok;
391
+ if ("bug" in answer)
392
+ throw bug(answer.bug);
393
+ const diagnostic = answer.err;
394
+ const fixed = diagnostic.fix.type === "save" ? `steps(${JSON.stringify(shown(sentence))})` : command(diagnostic.fix);
395
+ throw new DiagnosticError([{ ...diagnostic, command: fixed }]);
396
+ }
331
397
  /** The plan's own questions before anything runs. A step's required argument no binding covers is asked as
332
398
  * `handle` asks one — the ask narrowed to what nothing binds — and the step's decision replaced for the plan
333
399
  * to stand again. Several fields, or one record of several, no handler can answer: unanswered. */
@@ -378,9 +444,10 @@ function make(ground, invoked) {
378
444
  * signal aborted mid-run is a cancel: every body's group ended, the rounds under way and every round after
379
445
  * reported `skipped · cancelled`, and the rejection — the signal's reason — carrying the record once it is
380
446
  * whole. */
381
- async function executed(woven, options, traces) {
447
+ async function executed(woven, options, gathered) {
382
448
  const invoked = `weave(${JSON.stringify(shown(woven.input))})`;
383
449
  const { signal } = options;
450
+ const { traces } = gathered;
384
451
  const progress = { decided: [], handled: [] };
385
452
  const rounds = new Map();
386
453
  const record = (handling, decision, became) => {
@@ -413,7 +480,7 @@ function make(ground, invoked) {
413
480
  const { todo } = running;
414
481
  if (todo.type === "decide") {
415
482
  try {
416
- progress.decided.push([todo.asked, await decided(todo.asked, options, traces)]);
483
+ progress.decided.push([todo.asked, await decided(todo.asked, options, gathered)]);
417
484
  }
418
485
  catch (error) {
419
486
  // The signal aborted the decision's call: the round it was for never starts.
package/dist/types.d.ts CHANGED
@@ -157,6 +157,10 @@ export type Fix = {
157
157
  type: "test";
158
158
  } | {
159
159
  type: "help";
160
+ } | {
161
+ type: "save";
162
+ file: string;
163
+ input: string;
160
164
  };
161
165
  /** A JSON value that keeps its key order: the wire form of every boundary type. */
162
166
  export type Json = unknown;
@@ -583,15 +587,16 @@ export interface Item {
583
587
  needs?: Needs;
584
588
  configured: Record<ConfigKey, Held>;
585
589
  }
586
- /** How a set config key is held: the value itself, or a variable that is set or not. Never a secret's value. */
590
+ /** How a set config key is held: plain, its value handed to `compile` beside the set and never in it, or a variable that is set or not. Never a value, never a secret. */
587
591
  export type Held = {
588
592
  type: "plain";
589
- value: string;
590
593
  } | {
591
594
  type: "env";
592
595
  var: VarName;
593
596
  set: boolean;
594
597
  };
598
+ /** The plain settings' values, per reflex and key, as `evoke.toml` holds them: handed to `compile` beside the set, so the digest holds no value. */
599
+ export type Values = Record<LocalName, Record<ConfigKey, string>>;
595
600
  /** A duration in milliseconds; the host makes it an instant. */
596
601
  export type Millis = number;
597
602
  /** The compiled set: the active reflexes, the inactive ones with a fix per problem, every input-independent question, and the digest that keys what is derived from it. */
@@ -1085,6 +1090,64 @@ export interface Executed {
1085
1090
  steps: StepOutcome[];
1086
1091
  worst: Status;
1087
1092
  }
1093
+ /** A plan file: the sentence as typed, the plan, the pins it was decided under, and every engine answer it took. What
1094
+ * `steps` returns and `weave` takes; `JSON.stringify` writes it. No time, no name, no trace. */
1095
+ export interface Pinned {
1096
+ /** Fixed text, ignored on read. */
1097
+ note: string;
1098
+ /** The format revision: `1`. */
1099
+ plan: 1;
1100
+ /** The sentence as typed: what a re-plan plans, since the request as read is not always read the same. */
1101
+ input: string;
1102
+ /** Absent when none. */
1103
+ tags?: Tag[];
1104
+ weave: Weave;
1105
+ /** The evoke that wrote it. */
1106
+ evoke: Version;
1107
+ adapter: LockedAdapter;
1108
+ /** The floors the plan was decided under; absent when the adapter declared none. */
1109
+ gate?: Gate;
1110
+ /** The plan digest of the set it was decided over. */
1111
+ set: Digest;
1112
+ /** Every active reflex, by the hash of its item and its pin. */
1113
+ reflexes: Record<LocalName, PinnedReflex>;
1114
+ /** Every vocabulary, by the hash of its words. */
1115
+ vocab: Record<VocabName, Digest>;
1116
+ /** Every engine answer the plan took, one per text and question set. */
1117
+ answers: Answer[];
1118
+ }
1119
+ /** One reflex of the plan's set: the hash of its item — wording, consent, settings — and its pin: a remote one's
1120
+ * ref as the lock writes it, its tag and `h1`; a local one's path as written; a reflex handed as code its item alone. */
1121
+ export type PinnedReflex = {
1122
+ item: Digest;
1123
+ ref: string;
1124
+ tag: Version;
1125
+ h1: Digest;
1126
+ } | {
1127
+ item: Digest;
1128
+ path: string;
1129
+ } | {
1130
+ item: Digest;
1131
+ };
1132
+ /** One engine answer the plan took: the text it was asked about and the `Raw` as the engine gave it; the weave's own
1133
+ * questions stand under the whole request's text. */
1134
+ export interface Answer {
1135
+ text: string;
1136
+ raw: Raw;
1137
+ }
1138
+ /** The plan made again from a file: the weave, and per text what a line is rendered from. */
1139
+ export interface Replanned {
1140
+ weave: Weave;
1141
+ decided: Decided[];
1142
+ }
1143
+ /** One text decided from a file's answers: what was asked, the input's candidates, the raw answers, the decision. */
1144
+ export interface Decided {
1145
+ asked: Asked;
1146
+ /** Absent when none. */
1147
+ proposed?: Proposed[];
1148
+ raw: Raw;
1149
+ decision: Decision;
1150
+ }
1088
1151
  /** What changed in the contract from one version to the next, and how much it matters. */
1089
1152
  export interface ContractDiff {
1090
1153
  level: Level;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evoke-build/evoke",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "You invoke a function; you evoke a reflex. The SDK: load a project of reflexes, decide with Jev, run.",
5
5
  "keywords": [
6
6
  "jev",