@bilig/workbook 0.55.0 → 0.57.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/README.md CHANGED
@@ -1,364 +1,194 @@
1
1
  # @bilig/workbook
2
2
 
3
- Agent-first workbook model API and transport-neutral workbook operation language for bilig.
3
+ Generic workbook intent for agents and runtimes.
4
4
 
5
5
  Build `@bilig/workbook` so an agent would love using it: simple, generic,
6
6
  predictable, inspectable, verifiable, and never dependent on hardcoded business
7
7
  models or human spreadsheet UI assumptions.
8
8
 
9
- Use this package when a consumer needs to describe workbook work without taking a
10
- dependency on the engine, app server, transport, or replica-state implementation.
11
-
12
- The public surface stays generic:
13
-
14
- - `defineModel`
15
- - `buildWorkbookActionPlan`
16
- - `planWorkbookAction`
17
- - `inspectModel`
18
- - `collectWorkbookRefs`
19
- - `findTable`, `findColumn`, `findRange`, `findName`, `findRows`
20
- - `find`
21
- - `workbookRefKinds`
22
- - `isWorkbookRefKind`
23
- - `isWorkbookRef`
24
- - `workbookRowOperators`
25
- - `isWorkbookRowOperator`
26
- - `check`
27
- - `describeModel`
28
- - `describeRef`
29
- - `describePlan`
30
- - `describePlanResult`
31
- - `describeRunResult`
32
- - `describeRuntimeRequirements`
33
- - `verifyPlan`
34
- - `verifyModel`
35
- - `runWorkbookPlan`
36
- - `runWorkbookAction`
37
- - `verifyWorkbookReadbacks`
38
- - `normalizeWorkbookActionInputDescription`
39
- - `workbookActionInputDescriptionKinds`
40
- - `isWorkbookActionInputDescriptionKind`
41
- - `isWorkbookActionInputDescription`
42
- - `isWorkbookActionInput`
43
- - `builtInWorkbookCheckKinds`
44
- - `isBuiltInWorkbookCheckKind`
45
- - `workbookRunErrorCodes`
46
- - `isWorkbookRunErrorCode`
47
- - `formula`
48
- - `workbook.addOp(op, { target?, message? })` inside model actions
49
- - `WorkbookModel`
50
- - `WorkbookAction`
51
- - `WorkbookActionConfig`
52
- - `WorkbookActionDefinition`
53
- - `WorkbookActionContext`
54
- - `WorkbookCheckContext`
55
- - `WorkbookFindWorkbook`
56
- - `WorkbookCheckWorkbook`
57
- - `WorkbookActionWorkbook`
58
- - `WorkbookModelWorkbook`
59
- - `WorkbookFindNamespace`
60
- - `WorkbookRef`
61
- - `WorkbookRefKind`
62
- - `WorkbookRangeRef`
63
- - `WorkbookNameRef`
64
- - `WorkbookTableRef`
65
- - `WorkbookColumnRef`
66
- - `WorkbookRowsRef`
67
- - `WorkbookRowOperator`
68
- - `WorkbookActionInput`
69
- - `WorkbookActionInputDescription`
70
- - `WorkbookActionInputDescriptionKind`
71
- - `WorkbookActionInspection`
72
- - `WorkbookAddOpOptions`
73
- - `WorkbookActionPlanResult`
74
- - `WorkbookModelDescription`
75
- - `WorkbookRefDescription`
76
- - `WorkbookActionPlanDescription`
77
- - `WorkbookActionPlanResultDescription`
78
- - `WorkbookRunResultDescription`
79
- - `WorkbookUndoRefDescription`
80
- - `WorkbookRuntimeRequirements`
81
- - `WorkbookRuntimeRequirement`
82
- - `WorkbookRuntimeCapability`
83
- - `WorkbookPlanVerification`
84
- - `WorkbookPlanIssue`
85
- - `WorkbookModelVerification`
86
- - `WorkbookModelActionVerification`
87
- - `WorkbookModelVerificationOptions`
88
- - `WorkbookRunAdapter`
89
- - `WorkbookRunApplyResult`
90
- - `WorkbookRunReadback`
91
- - `WorkbookReadbackVerification`
92
- - `WorkbookReadbackIssue`
93
- - `WorkbookReadbackIssueCode`
94
- - `WorkbookCheckExpectation`
95
- - `WorkbookCheckExpectationDescription`
96
- - `WorkbookBuiltInCheckKind`
97
- - `WorkbookCustomCheckOptions`
98
- - `WorkbookReadbackCheckOptions`
99
- - `WorkbookRawFormulaOptions`
100
- - `WorkbookRunResult`
101
- - `WorkbookRunError`
102
- - `WorkbookRunErrorCode`
103
- - `WorkbookCheckResult`
104
-
105
- The low-level operation language remains available:
106
-
107
- - `WorkbookOp`
108
- - `WorkbookTxn`
109
- - `EngineOp`
110
- - `EngineOpBatch`
111
- - `isEngineOpBatch`
112
-
113
- Formula helpers create portable formula expressions with `@bilig/formula`.
114
- Calculation and workbook execution stay in `@bilig/core` and the app runtime.
115
- Use `planWorkbookAction` when an action name comes from an agent or user input;
116
- it returns `planned` or structured `failed` results instead of requiring
117
- exception control flow.
118
- `defineModel` returns frozen, normalized model metadata. Model and action names
119
- must be non-empty and already trimmed, while descriptions and input metadata are
120
- trimmed and frozen so the manifest an agent inspected cannot be mutated later by
121
- the caller.
122
- Actions can also accept a JSON-safe input:
9
+ Use this package when a consumer wants to define their own workbook model and
10
+ hand a runtime a portable plan. The package does not import the engine, start a
11
+ server, calculate formulas, ship revenue/quote/forecast models, or depend on
12
+ `zod`, `effect`, `@bilig/core`, `@bilig/headless`, or `@bilig/agent-api`.
13
+
14
+ ```sh
15
+ pnpm add @bilig/workbook
16
+ ```
17
+
18
+ ## The Shape
123
19
 
124
20
  ```ts
125
- import { defineModel } from '@bilig/workbook'
21
+ import {
22
+ defineModel,
23
+ describePlan,
24
+ describeRunResult,
25
+ describeRuntimeRequirements,
26
+ formula,
27
+ planWorkbookAction,
28
+ runWorkbookPlan,
29
+ verifyPlan,
30
+ } from "@bilig/workbook";
126
31
 
127
32
  export const model = defineModel({
128
- name: 'custom-writer',
33
+ name: "generic-row-calculator",
129
34
 
130
35
  find(workbook) {
36
+ const table = workbook.findTable({
37
+ headers: ["Item", "Quantity", "Rate", "Status", "Total"],
38
+ });
39
+ const rows = workbook.findRows({
40
+ table,
41
+ where: { column: "Status", op: "eq", value: "ready" },
42
+ });
43
+
131
44
  return {
132
- output: workbook.findRange({ sheetName: 'Sheet1', address: 'B2' }),
133
- }
45
+ table,
46
+ rows,
47
+ quantity: rows.column("Quantity"),
48
+ rate: rows.column("Rate"),
49
+ total: rows.column("Total"),
50
+ };
51
+ },
52
+
53
+ checks({ refs, workbook }) {
54
+ return [workbook.check.exists(refs.table), workbook.check.noFormulaErrors(refs.total)];
134
55
  },
135
56
 
136
57
  actions: {
137
- write({ refs, workbook, input }) {
138
- if (typeof input !== 'object' || input === null || Array.isArray(input)) {
139
- throw new Error('input object required')
140
- }
141
- const value = input.value
142
- if (typeof value !== 'number') {
143
- throw new Error('numeric value required')
144
- }
145
- workbook.writeValue(refs.output, value)
58
+ recompute({ refs, workbook }) {
59
+ const expected = formula.multiply(refs.quantity, refs.rate);
60
+ workbook.writeFormula(refs.total, expected);
61
+ workbook.check.formulaEquals(refs.total, expected);
146
62
  },
147
63
  },
148
- })
149
- ```
64
+ });
150
65
 
151
- `planWorkbookAction(model, "write", { value: 12 })` clones and canonicalizes
152
- that input into the plan so an agent can inspect exactly what was requested.
153
- Inputs must be plain JSON values: strings, finite numbers, booleans, `null`,
154
- arrays without holes, and plain objects. This package intentionally does not add
155
- schema dependencies; consumers own their own input validation inside actions.
156
- Use `verifyModel(model, { inputs: { write: { value: 12 } } })` when whole-model
157
- verification needs parameters for specific actions.
66
+ const planned = planWorkbookAction(model, "recompute");
67
+ if (planned.status === "failed") throw new Error(planned.errors[0]?.message);
158
68
 
159
- Actions can also be plain action objects when an agent needs a richer manifest
160
- without running workbook code:
69
+ const staticProof = verifyPlan(planned.plan);
70
+ const requirements = describeRuntimeRequirements(planned.plan);
71
+ const planForLogs = describePlan(planned.plan);
161
72
 
162
- ```ts
163
- actions: {
164
- write: {
165
- description: 'Write a consumer-provided value',
166
- input: {
167
- kind: 'object',
168
- fields: {
169
- value: { kind: 'number', required: true },
170
- },
171
- },
172
- run({ refs, workbook, input }) {
173
- if (typeof input !== 'object' || input === null || Array.isArray(input)) {
174
- throw new Error('input object required')
175
- }
176
- const value = input.value
177
- if (typeof value !== 'number') {
178
- throw new Error('numeric value required')
179
- }
180
- workbook.writeValue(refs.output, value)
181
- },
182
- },
183
- }
73
+ const result = await runWorkbookPlan(planned.plan, adapter);
74
+ const resultForLogs = describeRunResult(result);
184
75
  ```
185
76
 
186
- Input descriptions are intentionally descriptive metadata, not a schema engine.
187
- They support boring JSON kinds: `json`, `object`, `array`, `string`, `number`,
188
- `boolean`, and `null`. `object` descriptions may list sorted `fields`; `array`
189
- descriptions may list `items`. `normalizeWorkbookActionInputDescription` trims
190
- text, rejects malformed metadata, returns frozen data, and keeps the package
191
- free of `zod`, `effect`, or model-specific validators.
192
- `workbookActionInputDescriptionKinds`, `isWorkbookActionInputDescriptionKind`,
193
- `isWorkbookActionInputDescription`, and `isWorkbookActionInput` expose the same
194
- contract as stable data so generic tool builders can validate model metadata and
195
- JSON-safe payloads without ad hoc string matching.
196
-
197
- Formula expressions also keep their workbook inputs separate from their formula
198
- text. A planned `writeFormula` command includes both the parseable formula
199
- string and the generic model refs it used, so an agent can inspect what the
200
- action depends on without reverse-parsing placeholder names.
201
- For formulas outside the small helper set, use
202
- `formula.raw(source, { inputs })`; the source stays parseable while the
203
- declared refs remain inspectable and verifiable. These inputs are a declared
204
- dependency contract for agents, not parser-discovered proof that every formula
205
- reference has been mapped to a model ref.
206
- Formula operands intentionally do not accept bare strings. Use `formula.raw`
207
- for formula source and `formula.text` for spreadsheet string literals, so an
208
- agent cannot confuse a label, cell address, named range, or user-provided string
209
- with executable formula text.
210
-
211
- Known single-cell `workbook.format(ref, { numberFormat })` actions compile to
212
- concrete `setCellFormat` ops. Use `numberFormat: null` to plan an explicit
213
- format clear. Style patches remain high-level intent until the runtime resolves
214
- style ids.
215
- Use `workbook.addOp(op, { target?, message? })` inside model actions when a
216
- consumer needs the existing low-level workbook operation language directly. The
217
- op is runtime-guarded with `isWorkbookOp`, cloned into `plan.ops`, and kept in
218
- the command log so agents can inspect it without depending on `@bilig/core`.
219
- When a `target` is supplied for an address or range op, `verifyPlan` checks that
220
- the op touches the same range. For op kinds without an inferable range, `target`
221
- is still useful for logs and approvals but cannot prove the affected cells by
222
- itself.
223
-
224
- Action plans expose `refsUsed`, a flat deduped list of workbook refs found in
225
- the consumer-defined `refs` object. Use `collectWorkbookRefs` directly when an
226
- agent needs to inspect refs from any nested consumer shape.
227
- Use `findTable`, `findColumn`, `findRange`, `findName`, and `findRows` directly
228
- when an agent or test needs the same generic refs outside a model callback. The
229
- same helpers are also available as a frozen `find` namespace with short aliases
230
- such as `find.table(...)`, `find.range(...)`, and `find.rows(...)`.
231
- Use the frozen `workbookRefKinds` and `workbookRowOperators` lists, plus
232
- `isWorkbookRefKind`, `isWorkbookRef`, and `isWorkbookRowOperator`, when a
233
- generic agent tool needs to validate model refs or row predicates without
234
- copying string unions or depending on a schema package.
235
- Selector helpers trim text, canonicalize cell addresses, and reject empty table
236
- names, column names, named ranges, headers, invalid range addresses, invalid row
237
- operators, and non-finite row predicate values before a plan reaches runtime.
238
- `findRows` refs include the predicate value in their stable id so two
239
- consumer-defined row selectors do not collapse during dedupe, while labels stay
240
- human-readable for agent logs.
241
- Refs are frozen data objects. Ergonomic helpers like `table.column()` and
242
- `rows.column()` remain available, but they are non-enumerable so JSON
243
- inspection, object keys, and plan descriptions stay data-first.
244
- For table-backed rows, use `rows.column("Amount")` to target only that column in
245
- the matching rows. Runtime adapters can materialize row-filtered columns into
246
- the exact cells to read, write, format, clear, or use as row-wise formula inputs
247
- without hardcoding a business model.
248
- Use `check.exists(ref)` and `check.noFormulaErrors(ref)` directly when an agent
249
- or test needs the same generic planned checks outside a model callback.
250
- Use `check.valueEquals(ref, value)` and `check.formulaEquals(ref, formula)` when
251
- an action should carry machine-readable readback expectations for runtime
252
- verification. `formulaEquals` stores normalized formula text plus explicit model
253
- refs used by that formula, so an agent can inspect the post-action proof target
254
- without depending on a rendered spreadsheet UI.
255
- Use `check.custom({ kind, message, target, refs })` for consumer-defined
256
- invariants; the package does not need to know what the model means. `target`
257
- names the main ref, and `refs` names any supporting refs the invariant depends
258
- on so agents can describe and verify the full check contract.
259
- Custom check kinds cannot reuse built-in names. Use the frozen
260
- `builtInWorkbookCheckKinds` list or `isBuiltInWorkbookCheckKind` guard when a
261
- consumer-facing tool needs to validate check kinds before planning.
262
-
263
- Model callback phases are deliberately scoped. `find(workbook)` receives only
264
- the find API; `checks({ workbook })` receives find helpers plus `workbook.check`;
265
- actions receive find helpers, checks, and mutation planning methods. That keeps
266
- discovery and proof declaration separate from workbook mutation intent.
267
-
268
- Use `describeModel` when an agent needs a JSON-safe manifest of model name,
269
- model description, sorted action names, per-action descriptions, optional input
270
- descriptions, and whether model-level checks exist without running `find`,
271
- checks, or actions.
272
- Use `describeRef` and `describePlan` when an agent needs JSON-safe intent for
273
- logs, comparisons, approvals, or runtime handoff. Descriptions keep the same
274
- generic action input, refs, commands, checks, changes, and ops, but omit
275
- consumer-private `refs` object shape and helper functions such as
276
- `table.column()`.
277
- Use `describePlanResult` when the same JSON-safe handoff is needed for either
278
- planned or failed action planning.
279
- Use `describeRunResult` after execution when an agent needs the same JSON-safe
280
- shape for `done` or `failed` run results. It preserves changed summaries,
281
- checks, errors, and undo ops, but describes workbook refs without helper
282
- functions such as `table.column()` or `rows.column()`.
283
- Run errors use a stable `WorkbookRunErrorCode` union rather than arbitrary
284
- strings. Use the frozen `workbookRunErrorCodes` list and `isWorkbookRunErrorCode`
285
- guard when an adapter, logger, or approval layer needs to branch on known
286
- failure classes. Runtime adapters should use `apply_failed` for apply
287
- exceptions and `runtime_rejected` for intentional runtime refusal with a
288
- specific message instead of inventing new public codes.
289
- Use `describeRuntimeRequirements(plan)` before runtime handoff when an agent
290
- needs to inspect what the adapter must do. It returns a JSON-safe list of
291
- generic `apply`, `read`, and `verify` requirements with boring capabilities
292
- such as `writeFormula`, `writeValue`, `format`, `clear`, `applyOp`, `read`, and
293
- `verifyCheck`. Command-derived concrete single-cell ops are not repeated as
294
- extra `applyOp` requirements, while explicit or manually assembled ops still
295
- appear as `applyOp`. It does not execute anything and it does not import the
296
- engine.
297
-
298
- Use `verifyPlan` before runtime handoff when an agent needs to prove a planned
299
- action is internally consistent. It checks for non-JSON-safe action input,
300
- unresolved refs, unparsable formulas, duplicate resolved refs, and missing
301
- concrete ops for write, clear, and number-format commands that already target a
302
- known single cell. Custom check targets and supporting refs must also resolve
303
- through the model's `refsUsed` contract. Formula readback expectation inputs
304
- must also resolve through `refsUsed`, and expectation formulas must be parseable.
305
- Checks must start as `planned`; consumer code cannot mark a check passed or
306
- failed before runtime proof.
307
- Low-level `addOp` commands must contain valid `WorkbookOp` values, must still
308
- appear in `plan.ops`, and must match their declared `target` when the op exposes
309
- a concrete address or range.
310
- Use `verifyModel` to plan and verify every action in a consumer-defined model
311
- with one JSON-safe result. Pass `inputs` when specific actions require
312
- parameters. Each successfully planned action also includes its runtime
313
- requirements, so an agent can inspect the action manifest, planned intent,
314
- static verification result, and adapter handoff checklist from the same object.
315
-
316
- Use `runWorkbookPlan(plan, adapter)` or
317
- `runWorkbookAction(model, actionName, adapter, input)` when an agent needs a
318
- generic apply-and-prove loop. The adapter owns runtime execution and semantic
319
- readback:
77
+ That is the core flow:
78
+
79
+ 1. `defineModel` freezes a consumer-defined model.
80
+ 2. `find` returns generic refs.
81
+ 3. `checks` declares facts the runtime must prove.
82
+ 4. An action builds workbook intent.
83
+ 5. `verifyPlan` checks the plan without running an engine.
84
+ 6. `describeRuntimeRequirements` tells an adapter what it must apply, read, and prove.
85
+ 7. `runWorkbookPlan` applies the plan through a runtime-owned adapter and returns a boring result.
86
+
87
+ ## Public Contract
88
+
89
+ The main API is intentionally small:
90
+
91
+ - model: `defineModel`, `inspectModel`, `planWorkbookAction`, `buildWorkbookActionPlan`
92
+ - selectors: `findTable`, `findColumn`, `findRange`, `findName`, `findRows`, `find`
93
+ - checks: `check.exists`, `check.noFormulaErrors`, `check.valueEquals`, `check.formulaEquals`, `check.custom`
94
+ - formulas: `formula.add`, `formula.subtract`, `formula.multiply`, `formula.divide`, `formula.sum`, `formula.call`, `formula.raw`, `formula.text`
95
+ - proof: `verifyPlan`, `verifyModel`, `verifyWorkbookReadbacks`
96
+ - descriptions: `describeModel`, `describeRef`, `describePlan`, `describePlanResult`, `describeRuntimeRequirements`, `describeRunResult`
97
+ - runtime handoff: `runWorkbookPlan`, `runWorkbookAction`, `WorkbookRunAdapter`
98
+ - low-level language: `WorkbookOp`, `WorkbookTxn`, `EngineOp`, `EngineOpBatch`, `isEngineOpBatch`
99
+
100
+ Stable data helpers are exported for generic tool builders:
101
+
102
+ - `workbookRefKinds`, `isWorkbookRefKind`, `isWorkbookRef`
103
+ - `workbookRowOperators`, `workbookRowOperatorValueTypes`, `isWorkbookRowOperator`, `isWorkbookRowValueCompatible`
104
+ - `builtInWorkbookCheckKinds`, `isBuiltInWorkbookCheckKind`
105
+ - `workbookActionInputDescriptionKinds`, `isWorkbookActionInputDescriptionKind`, `isWorkbookActionInputDescription`, `isWorkbookActionInput`
106
+ - `workbookRunErrorCodes`, `isWorkbookRunErrorCode`
107
+
108
+ ## Selectors
109
+
110
+ Selectors are not a human spreadsheet UI. They are stable intent for runtimes and
111
+ agents.
112
+
113
+ - `findTable({ headers })` means "find a table with all these headers." Header
114
+ order is normalized, duplicate headers are rejected, and matching is
115
+ case-sensitive after trimming.
116
+ - `findRows({ table, where })` means "find rows in this table matching this
117
+ predicate." `eq` and `neq` accept any JSON literal; `contains` and
118
+ `startsWith` accept strings; ordered comparisons accept numbers or strings.
119
+ - `findRange` is the escape hatch for an explicit range when the consumer really
120
+ has one. It validates and canonicalizes addresses before runtime handoff.
121
+
122
+ Refs are frozen data. Helpers such as `table.column("Total")` and
123
+ `rows.column("Total")` are non-enumerable, so JSON descriptions stay data-first.
124
+
125
+ ## Formulas
126
+
127
+ `@bilig/workbook` creates formula expressions. `@bilig/formula` parses and
128
+ normalizes formula text. `@bilig/core` or an app runtime calculates it.
129
+
130
+ Formula helpers keep formula text and workbook dependencies separate. A planned
131
+ formula write includes both the formula string and the refs used to build it.
132
+ For custom formula text, use `formula.raw(source, { inputs })`. For spreadsheet
133
+ string literals, use `formula.text(value)`. Bare strings are not formula
134
+ operands because agents should not guess whether a string is code, a label, a
135
+ named range, or user text.
136
+
137
+ ## Runtime Adapter
138
+
139
+ `@bilig/workbook` does not execute plans. A runtime owns that:
320
140
 
321
141
  ```ts
322
- const result = await runWorkbookAction(model, 'write', {
142
+ const adapter = {
323
143
  apply(plan) {
324
- return runtime.apply(plan.ops)
144
+ return { status: "applied", undo: { id: "undo-1" } };
325
145
  },
326
- read(targets) {
327
- return runtime.read(targets)
146
+ read(targets, plan) {
147
+ return targets.map((target) => ({ target, value: 12 }));
328
148
  },
329
- })
149
+ verifyChecks(checks, plan) {
150
+ return checks.map((entry) => ({ ...entry, status: "passed" }));
151
+ },
152
+ };
330
153
  ```
331
154
 
332
- `runWorkbookAction` plans the action, runs `verifyPlan`, calls
333
- `adapter.apply(plan)`, then evaluates `valueEquals` and `formulaEquals` checks
334
- against `adapter.read(targets, plan)`. It never imports the engine, headless
335
- runtime, app server, or UI. If static verification fails, the apply adapter is
336
- not called. If a readback expectation is missing or mismatched, the returned
337
- `WorkbookRunResult` is `failed` with deterministic error codes such as
338
- `readback_missing`, `value_mismatch`, or `formula_mismatch`. `adapter.read`
339
- must return exactly the requested targets; extra readbacks fail with
340
- `readback_unexpected` because an agent should not accept proof for cells it did
341
- not ask the runtime to inspect.
342
- Formula readbacks are exact: adapters should return formula text in the same
343
- normalized no-leading-`=` form produced by `formula.source`.
344
- `adapter.apply` only applies the plan and may return an undo ref; it cannot
345
- drop, replace, or prove checks. An apply result with `status: "applied"` and
346
- non-empty `errors` is rejected as `runtime_rejected`.
347
- Adapters provide `verifyChecks(checks, plan)` to prove non-readback checks such
348
- as `exists`, `noFormulaErrors`, and consumer-defined `custom` invariants. The
349
- verifier must return the same checks in the same order and may only change
350
- `status` or add JSON-safe `proof`. Changing `kind`, `target`, `refs`,
351
- `expectation`, or `message` fails the run as `invalid_check_verification`.
352
- Unsupported verifier fields are stripped from accepted results. If any verified
353
- check is `failed`, the run returns `failed` with `check_failed`. If any check
354
- remains `planned` after readback and adapter verification, the run returns
355
- `failed` with `check_not_verified`; `status: "done"` means every planned check
356
- has proof.
357
-
358
- When running against Bilig's engine, use `createWorkbookRunAdapter(engine)` from
359
- `@bilig/core`. The adapter materializes generic `plan.commands` into engine
360
- operations, falls back to explicit `plan.ops` for low-level plans, reads
361
- single-cell expectation targets, and verifies generic `exists` and
362
- `noFormulaErrors` checks without adding workbook-specific business models to
363
- this package. If the engine captures undo, the run result includes `undo.ops` in
364
- the same portable operation language.
155
+ `runWorkbookPlan` refuses to call `apply` if static plan verification fails.
156
+ Readback checks attach proof to passed checks, such as
157
+ `{ source: "readback", value: 12 }` or
158
+ `{ source: "readback", formula: "(Table[Quantity])*(Table[Rate])" }`.
159
+ Generic check verifiers may only change `status` or add JSON-safe `proof`; they
160
+ cannot rewrite the check contract.
161
+
162
+ The result is deliberately plain:
163
+
164
+ ```ts
165
+ type WorkbookRunResult =
166
+ | {
167
+ status: "done";
168
+ changed: WorkbookChangeSummary[];
169
+ checks: WorkbookCheckResult[];
170
+ undo?: WorkbookUndoRef;
171
+ }
172
+ | {
173
+ status: "failed";
174
+ errors: WorkbookRunError[];
175
+ checks: WorkbookCheckResult[];
176
+ };
177
+ ```
178
+
179
+ ## Low-Level Ops
180
+
181
+ Most models should use the small action API: `writeFormula`, `writeValue`,
182
+ `format`, `clear`, and checks. If a consumer needs the existing workbook
183
+ operation language directly, call `workbook.addOp(op, { target, message })`
184
+ inside an action.
185
+
186
+ The op is guarded with `isWorkbookOp`, cloned into `plan.ops`, and kept in the
187
+ command log. If a target is supplied and the op exposes a concrete range,
188
+ `verifyPlan` checks that the target and op agree.
189
+
190
+ ## Example
191
+
192
+ See [examples/workbook-agent-model](../../examples/workbook-agent-model) for a
193
+ generic model that plans, verifies, describes, runs, and prints proof without
194
+ depending on a hardcoded business model.
package/dist/check.js CHANGED
@@ -46,14 +46,22 @@ function uniqueRefs(refs) {
46
46
  }
47
47
  function createWorkbookCheck(options) {
48
48
  const refs = uniqueRefs(options.refs);
49
- return {
49
+ const expectation = options.expectation === undefined
50
+ ? undefined
51
+ : options.expectation.kind === 'formulaEquals'
52
+ ? Object.freeze({
53
+ ...options.expectation,
54
+ inputs: Object.freeze([...options.expectation.inputs]),
55
+ })
56
+ : Object.freeze({ ...options.expectation });
57
+ return Object.freeze({
50
58
  status: 'planned',
51
59
  kind: requiredText(options.kind, 'kind'),
52
60
  ...(options.target !== undefined ? { target: options.target } : {}),
53
- ...(refs !== undefined ? { refs } : {}),
61
+ ...(refs !== undefined ? { refs: Object.freeze([...refs]) } : {}),
54
62
  message: requiredText(options.message, 'message'),
55
- ...(options.expectation !== undefined ? { expectation: options.expectation } : {}),
56
- };
63
+ ...(expectation !== undefined ? { expectation } : {}),
64
+ });
57
65
  }
58
66
  export function createWorkbookCustomCheck(options) {
59
67
  const kind = requiredText(options.kind, 'kind');
package/dist/check.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}
package/dist/find.d.ts CHANGED
@@ -27,7 +27,18 @@ export interface WorkbookColumnRef extends WorkbookBaseRef {
27
27
  readonly name: string;
28
28
  }
29
29
  export type WorkbookRowOperator = 'eq' | 'neq' | 'contains' | 'startsWith' | 'gt' | 'gte' | 'lt' | 'lte';
30
+ export type WorkbookRowValueType = 'number' | 'string' | 'boolean' | 'null';
30
31
  export declare const workbookRowOperators: readonly ["eq", "neq", "contains", "startsWith", "gt", "gte", "lt", "lte"];
32
+ export declare const workbookRowOperatorValueTypes: Readonly<{
33
+ readonly eq: readonly ("string" | "number" | "boolean" | "null")[];
34
+ readonly neq: readonly ("string" | "number" | "boolean" | "null")[];
35
+ readonly contains: readonly "string"[];
36
+ readonly startsWith: readonly "string"[];
37
+ readonly gt: readonly ("string" | "number")[];
38
+ readonly gte: readonly ("string" | "number")[];
39
+ readonly lt: readonly ("string" | "number")[];
40
+ readonly lte: readonly ("string" | "number")[];
41
+ }>;
31
42
  export interface WorkbookRowsRef extends WorkbookBaseRef {
32
43
  readonly kind: 'rows';
33
44
  readonly sheetName?: string;
@@ -88,6 +99,7 @@ export interface WorkbookFindNamespace extends WorkbookFindApi {
88
99
  readonly rows: (options: FindRowsOptions) => WorkbookRowsRef;
89
100
  }
90
101
  export declare function isWorkbookRowOperator(value: unknown): value is WorkbookRowOperator;
102
+ export declare function isWorkbookRowValueCompatible(op: WorkbookRowOperator, value: LiteralInput): boolean;
91
103
  export declare function normalizeRangeRef(input: FindRangeInput): CellRangeRef;
92
104
  export declare function createWorkbookTableRef(options: FindTableOptions): WorkbookTableRef;
93
105
  export declare function createWorkbookColumnRef(options: FindColumnOptions): WorkbookColumnRef;