@toclocoinc/lattice-grid 1.58.0 → 1.60.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 (113) hide show
  1. package/README.md +3 -3
  2. package/docs/API.html +1773 -73
  3. package/docs/api-detail.html +321 -5
  4. package/lattice-grid.d.ts +281 -2842
  5. package/lattice-grid.esm.min.js +879 -148
  6. package/lattice-grid.min.cjs +879 -148
  7. package/lattice-grid.min.css +1 -1
  8. package/lattice-grid.min.js +879 -148
  9. package/modules/ai.d.ts +401 -0
  10. package/modules/ai.esm.min.js +25 -6
  11. package/modules/ai.min.cjs +25 -6
  12. package/modules/ai.min.js +25 -6
  13. package/modules/angular.d.ts +31 -0
  14. package/modules/angular.esm.min.js +3 -2
  15. package/modules/angular.min.cjs +3 -2
  16. package/modules/angular.min.js +3 -2
  17. package/modules/chart-alluvial.d.ts +18 -0
  18. package/modules/chart-alluvial.esm.min.js +1 -1
  19. package/modules/chart-arc.d.ts +18 -0
  20. package/modules/chart-arc.esm.min.js +1 -1
  21. package/modules/chart-bubblemap.d.ts +18 -0
  22. package/modules/chart-bubblemap.esm.min.js +1 -1
  23. package/modules/chart-bump.d.ts +12 -0
  24. package/modules/chart-bump.esm.min.js +1 -1
  25. package/modules/chart-calendar.d.ts +12 -0
  26. package/modules/chart-calendar.esm.min.js +1 -1
  27. package/modules/chart-decomposition.d.ts +20 -0
  28. package/modules/chart-decomposition.esm.min.js +1 -1
  29. package/modules/chart-diverging.d.ts +12 -0
  30. package/modules/chart-diverging.esm.min.js +1 -1
  31. package/modules/chart-dumbbell.d.ts +18 -0
  32. package/modules/chart-dumbbell.esm.min.js +1 -1
  33. package/modules/chart-fan.d.ts +18 -0
  34. package/modules/chart-fan.esm.min.js +1 -1
  35. package/modules/chart-hexbin.d.ts +18 -0
  36. package/modules/chart-hexbin.esm.min.js +1 -1
  37. package/modules/chart-hexmap.d.ts +18 -0
  38. package/modules/chart-hexmap.esm.min.js +1 -1
  39. package/modules/chart-icicle.d.ts +12 -0
  40. package/modules/chart-icicle.esm.min.js +1 -1
  41. package/modules/chart-parallel.d.ts +19 -0
  42. package/modules/chart-parallel.esm.min.js +1 -1
  43. package/modules/chart-ridgeline.d.ts +14 -0
  44. package/modules/chart-ridgeline.esm.min.js +1 -1
  45. package/modules/chart-roc.d.ts +20 -0
  46. package/modules/chart-roc.esm.min.js +1 -1
  47. package/modules/chart-slope.d.ts +12 -0
  48. package/modules/chart-slope.esm.min.js +1 -1
  49. package/modules/chart-splom.d.ts +19 -0
  50. package/modules/chart-splom.esm.min.js +1 -1
  51. package/modules/chart-waffle.d.ts +12 -0
  52. package/modules/chart-waffle.esm.min.js +1 -1
  53. package/modules/charts.d.ts +122 -0
  54. package/modules/charts.esm.min.js +4 -4
  55. package/modules/charts.min.cjs +4 -4
  56. package/modules/charts.min.js +4 -4
  57. package/modules/data-router.d.ts +91 -0
  58. package/modules/data-router.esm.min.js +109 -17
  59. package/modules/data-router.min.cjs +109 -17
  60. package/modules/data-router.min.js +109 -17
  61. package/modules/devtools.d.ts +28 -0
  62. package/modules/devtools.esm.min.js +2 -2
  63. package/modules/devtools.min.cjs +2 -2
  64. package/modules/devtools.min.js +2 -2
  65. package/modules/dhtmlx-compat.d.ts +19 -0
  66. package/modules/dhtmlx-compat.esm.min.js +4 -4
  67. package/modules/dhtmlx-compat.min.cjs +4 -4
  68. package/modules/dhtmlx-compat.min.js +4 -4
  69. package/modules/gantt.d.ts +515 -0
  70. package/modules/gantt.esm.min.js +109 -33
  71. package/modules/gantt.min.cjs +109 -33
  72. package/modules/gantt.min.js +109 -33
  73. package/modules/htmx.d.ts +176 -0
  74. package/modules/htmx.esm.min.js +879 -148
  75. package/modules/htmx.min.cjs +879 -148
  76. package/modules/htmx.min.js +879 -148
  77. package/modules/kanban.d.ts +492 -0
  78. package/modules/kanban.esm.min.js +4 -4
  79. package/modules/kanban.min.cjs +4 -4
  80. package/modules/kanban.min.js +4 -4
  81. package/modules/kpi.d.ts +255 -0
  82. package/modules/kpi.esm.min.js +40 -7
  83. package/modules/kpi.min.cjs +40 -7
  84. package/modules/kpi.min.js +40 -7
  85. package/modules/layout.d.ts +332 -0
  86. package/modules/layout.esm.min.js +59 -6
  87. package/modules/layout.min.cjs +59 -6
  88. package/modules/layout.min.js +59 -6
  89. package/modules/mock-socket.d.ts +114 -0
  90. package/modules/mock-socket.esm.min.js +2 -2
  91. package/modules/mock-socket.min.cjs +2 -2
  92. package/modules/mock-socket.min.js +2 -2
  93. package/modules/react.d.ts +25 -0
  94. package/modules/react.esm.min.js +3 -2
  95. package/modules/react.min.cjs +3 -2
  96. package/modules/react.min.js +3 -2
  97. package/modules/svelte.d.ts +26 -0
  98. package/modules/svelte.esm.min.js +3 -2
  99. package/modules/svelte.min.cjs +3 -2
  100. package/modules/svelte.min.js +3 -2
  101. package/modules/tabs.d.ts +133 -0
  102. package/modules/tabs.esm.min.js +411 -9
  103. package/modules/tabs.min.cjs +411 -9
  104. package/modules/tabs.min.js +411 -9
  105. package/modules/vue.d.ts +24 -0
  106. package/modules/vue.esm.min.js +3 -2
  107. package/modules/vue.min.cjs +3 -2
  108. package/modules/vue.min.js +3 -2
  109. package/modules/webcomponent.d.ts +47 -0
  110. package/modules/webcomponent.esm.min.js +879 -148
  111. package/modules/webcomponent.min.cjs +879 -148
  112. package/modules/webcomponent.min.js +879 -148
  113. package/package.json +2 -2
@@ -0,0 +1,401 @@
1
+ /*!
2
+ * Lattice Grid 1.60.0, ai module type declarations
3
+ * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
+ * https://latticegrid.dev
5
+ */
6
+ /**
7
+ * The provider-agnostic model callback the host supplies (BACKLOG-0000965).
8
+ * The module never imports a provider SDK, reads a key, or makes a network
9
+ * call — it builds this payload and awaits the host's reply. A host may wrap a
10
+ * chat provider (`{ text }`), a completion (a bare string), a tool-calling turn
11
+ * (`{ toolCalls }`), or a structured provider (`{ structured }`).
12
+ */
13
+ type AIAsk = (payload: {
14
+ /** The narrate-only system instruction. */
15
+ system: string;
16
+ /** The single user message: the facts block and the ask. */
17
+ message: string;
18
+ /** System and message joined, for a completion-shaped provider. */
19
+ prompt: string;
20
+ /** The running chat, including any tool results, for a chat-shaped provider. */
21
+ messages: Array<{ role: string; content: string; [k: string]: unknown }>;
22
+ /** The read-only tool definitions, present only on the tool-use path. */
23
+ tools?: object[];
24
+ /** The grid's generated schema (no row values). */
25
+ schema?: unknown;
26
+ /** An abort signal the host should honour. */
27
+ signal?: AbortSignal;
28
+ }) => Promise<
29
+ | string
30
+ | { text?: string; content?: string; toolCalls?: object[]; structured?: unknown }
31
+ >;
32
+
33
+ /** A single computed figure a narrative is grounded on. */
34
+ interface AIFact {
35
+ id: string;
36
+ label: string;
37
+ /** The raw numeric value, or null for a context-only fact. */
38
+ value: number | null;
39
+ /** The pre-formatted display string the model is told to use verbatim. */
40
+ display: string;
41
+ kind: string;
42
+ colId?: string;
43
+ }
44
+
45
+ /**
46
+ * A narrative target. `view` narrates the current filtered view; `column`
47
+ * narrates one column's profile; `forecast` adds its projection; `kpi`/`chart`
48
+ * narrate figures the caller passes through in `facts`; `risk` assembles a
49
+ * project RISK SUMMARY from the separate Gantt / Kanban modules' public outputs
50
+ * (BACKLOG-0000979).
51
+ */
52
+ interface AITarget {
53
+ kind?: 'view' | 'column' | 'forecast' | 'kpi' | 'chart' | 'risk';
54
+ colId?: string;
55
+ /** Forecast options, for `kind: 'forecast'`. */
56
+ options?: object;
57
+ /** Caller-supplied figures for a KPI/chart Explain, grounded like the rest. */
58
+ facts?: Array<{ id?: string; label: string; value: unknown; display?: string; kind?: string; colId?: string }>;
59
+ /**
60
+ * For `kind: 'risk'`: a Gantt instance (from `createGantt`). Read duck-typed
61
+ * for `earnedValue()` (SPI/CPI/variances) and `schedule` (critical path,
62
+ * float). The AI bundle never imports the Gantt module.
63
+ */
64
+ gantt?: unknown;
65
+ /**
66
+ * For `kind: 'risk'`: a Kanban board (from `createKanban`). Read for its
67
+ * `board.sla` monitor (breach / warning counts). The AI bundle never imports
68
+ * the Kanban module.
69
+ */
70
+ board?: unknown;
71
+ /** For `kind: 'risk'`: an SLA monitor, if not reached through `board`. */
72
+ sla?: unknown;
73
+ /** For `kind: 'risk'`: a precomputed `gantt.earnedValue()` result. */
74
+ earnedValue?: object;
75
+ /** For `kind: 'risk'`: a precomputed `gantt.schedule` result. */
76
+ schedule?: object;
77
+ /** For `kind: 'risk'`: precomputed SLA breach states. */
78
+ breaches?: object[];
79
+ /** For `kind: 'risk'`: precomputed SLA warning states. */
80
+ warnings?: object[];
81
+ /** For `kind: 'risk'`: options passed to `gantt.earnedValue()`. */
82
+ evmOptions?: object;
83
+ /**
84
+ * For `kind: 'risk'`: expose the at-risk task NAMES (off by default — a risk
85
+ * summary carries aggregates only unless the host opts in).
86
+ */
87
+ includeTaskNames?: boolean;
88
+ /**
89
+ * For `kind: 'risk'`: expose the money figures BAC/PV/EV/AC (off by default).
90
+ */
91
+ includeCost?: boolean;
92
+ /** For `kind: 'risk'`: cap on named at-risk tasks (default 10). */
93
+ maxTasks?: number;
94
+ }
95
+
96
+ /** The facts packet a narrative grounds on. */
97
+ interface AIFactsPacket {
98
+ target: AITarget;
99
+ facts: AIFact[];
100
+ /** The numeric values seeding the reconciliation registry. */
101
+ groundedValues: number[];
102
+ meta: {
103
+ kind: string; filtered: boolean; factCount: number; redacted?: boolean; colId?: string;
104
+ /** For `kind: 'risk'`: which module sources resolved. */
105
+ sources?: { schedule: boolean; earnedValue: boolean; sla: boolean };
106
+ /** For `kind: 'risk'`: which opt-in exposures were honoured. */
107
+ exposed?: { taskNames: boolean; cost: boolean };
108
+ };
109
+ }
110
+
111
+ /**
112
+ * The risk facts a board / Gantt risk summary grounds on (BACKLOG-0000979),
113
+ * from {@link buildRiskFacts}: the facts plus which module sources resolved and
114
+ * which opt-in exposures (task names, cost) were honoured.
115
+ */
116
+ interface AIRiskFacts {
117
+ facts: AIFact[];
118
+ meta: {
119
+ kind: 'risk';
120
+ sources: { schedule: boolean; earnedValue: boolean; sla: boolean };
121
+ exposed: { taskNames: boolean; cost: boolean };
122
+ };
123
+ }
124
+
125
+ /** The result of a narrative: reconciled prose plus what grounded and what did not. */
126
+ interface AINarrative {
127
+ /** The narrative, with every ungrounded figure stripped (or flagged). */
128
+ text: string;
129
+ facts: AIFact[];
130
+ /** The figures that reconciled against a computed value. */
131
+ grounded: string[];
132
+ /** The figures removed as ungrounded. */
133
+ flagged: string[];
134
+ packet: AIFactsPacket;
135
+ /** How many ask() rounds ran (>1 only on the tool-use path). */
136
+ rounds: number;
137
+ mode: 'tools' | 'packet';
138
+ }
139
+
140
+ /** AI module configuration. */
141
+ interface AIConfig {
142
+ /** The host's model callback. Falls back to the grid's `ai.ask` when omitted. */
143
+ ask?: AIAsk;
144
+ /** Opt into specific features: `'narrative'`, `'insights'`, `'query'`/`'ask'`. All on when omitted. */
145
+ enable?: string[];
146
+ /**
147
+ * Ask-your-data: apply a safe (read-only) query result without a confirm
148
+ * step. Off by default — the resolved query is shown and waits for Apply.
149
+ */
150
+ autoApply?: boolean;
151
+ /**
152
+ * A Data Router instance; on applying a query the answer rows are fanned to
153
+ * its attached viewers (grid + chart + KPI together) via `load()`.
154
+ */
155
+ router?: unknown;
156
+ /** Budgets passed to the schema builder for ask-your-data. */
157
+ schemaOptions?: object;
158
+ /** Extra context passed through to `ask()`. */
159
+ context?: unknown;
160
+ /** Called with each ask-your-data result. */
161
+ onQuery?: (result: AIQueryResult) => void;
162
+ /** Called with each governed-actor proposal (Play C), before any approval. */
163
+ onProposal?: (result: AIProposal) => void;
164
+ /**
165
+ * A Kanban board (from `createKanban`) the governed actor writes moves
166
+ * through: an NL card move applies via the board's own `beforeMove` gate
167
+ * (BACKLOG-0000967), never a kanban-specific write bypass.
168
+ */
169
+ board?: unknown;
170
+ /** Cap on rows any tool result carries to `ask()`. */
171
+ maxRows?: number;
172
+ /** Columns whose values must never leave the browser. */
173
+ redact?: string | string[] | ((colId: string) => boolean);
174
+ /** Force tool-use on or off; auto-detected from how `ask` was supplied otherwise. */
175
+ tools?: boolean;
176
+ /** Locale for figure formatting. */
177
+ locale?: string;
178
+ /** Column cap for a view summary. */
179
+ maxColumns?: number;
180
+ /** What to do with an ungrounded figure: `'strip'` (default) or `'flag'`. */
181
+ reconcile?: 'strip' | 'flag';
182
+ /** An element to mount the insights panel into. */
183
+ element?: HTMLElement;
184
+ /** Called when a narrative is produced. */
185
+ onNarrative?: (result: AINarrative) => void;
186
+ /** Called when `ask()` errors; the grid stays usable. */
187
+ onError?: (error: { error: unknown; target: AITarget }) => void;
188
+ }
189
+
190
+ /** The report from applying an ask-your-data query. */
191
+ interface AIApplyReport {
192
+ ok: boolean;
193
+ /** The action types that were applied. */
194
+ applied: string[];
195
+ /** Actions that threw while applying. */
196
+ failed: Array<{ type: string; reason: string }>;
197
+ /** Actions refused by the read-only gate — a mutation is never applied. */
198
+ refused: Array<{ type: string; reason: string }>;
199
+ /** How many answer rows were fanned to a router's viewers. */
200
+ fannedOut: number;
201
+ }
202
+
203
+ /**
204
+ * The result of an ask-your-data question (BACKLOG-0000966): a validated,
205
+ * READ-ONLY query spec — never rows — that the host reviews before applying.
206
+ */
207
+ interface AIQueryResult {
208
+ /** True when the spec is safe to apply: at least one read, nothing unsafe. */
209
+ ok: boolean;
210
+ /** The user's question. */
211
+ question: string;
212
+ /** The core plan (from `grid.ai.plan`). */
213
+ plan: Record<string, unknown>;
214
+ /** The read-only actions that will run — the validated query spec. */
215
+ actions: object[];
216
+ /** Actions refused as not read-only (a mutation the model asked for). */
217
+ unsafe: Array<{ type: string; reason: string }>;
218
+ /** Parts the core validator dropped (unknown column, bad operator, …). */
219
+ rejected: Array<{ at: string; what: string; reason: string }>;
220
+ /** The model's own one-line summary, if any. */
221
+ explain: string;
222
+ /** The validated query spec as data. */
223
+ spec: { actions: object[] };
224
+ /** The apply report once applied, or null. */
225
+ applied: AIApplyReport | null;
226
+ /** The resolved query in one human sentence, from the validated spec. */
227
+ describe(): string;
228
+ /** Apply the query (re-gated), fanning the answer to a router if configured. */
229
+ apply(opts?: { router?: unknown; onResult?: (rows: object[]) => void }): AIApplyReport;
230
+ }
231
+
232
+ /** One before/after change in a governed-actor proposal (BACKLOG-0000967). */
233
+ interface AIDiffEntry {
234
+ /** The target row key. */
235
+ key: string;
236
+ /** A human label identifying the row (a name-like column, else the key). */
237
+ rowLabel: string;
238
+ /** The target column id. */
239
+ colId: string;
240
+ /** The column's title, for the diff header. */
241
+ colTitle: string;
242
+ /** The current stored value. */
243
+ oldValue: unknown;
244
+ /** The current value as shown (a lookup id mapped to its label). */
245
+ oldDisplay: string;
246
+ /** The proposed stored value (a label resolved to its option id). */
247
+ newValue: unknown;
248
+ /** The proposed value as shown. */
249
+ newDisplay: string;
250
+ }
251
+
252
+ /**
253
+ * A governed-actor proposal (Play C, BACKLOG-0000967): the model's structured
254
+ * edits, VALIDATED and resolved against the current view — never written until
255
+ * a human approves. `apply()` writes ONLY through the grid's own gate.
256
+ */
257
+ interface AIProposal {
258
+ /** True when there is at least one applicable change and nothing needs a pick first. */
259
+ ok: boolean;
260
+ /** The user's instruction. */
261
+ instruction: string;
262
+ /** `'view'` (the filtered set, the default) or `'all'` (an opted-in widen). */
263
+ scope: 'view' | 'all';
264
+ /** How many rows the scope covers. */
265
+ scopeCount: number;
266
+ /** The scope in words, always stated in the confirm/diff. */
267
+ scopeText: string;
268
+ /** Whether any proposal was a bulk (`scope:'view'`) edit. */
269
+ bulk: boolean;
270
+ /** The before/after diff — exactly what would change. Nothing is written yet. */
271
+ diff: AIDiffEntry[];
272
+ /** Proposals refused before apply (unknown column, unknown label, bad type/range, no match). */
273
+ rejected: Array<{ reason: string; [k: string]: unknown }>;
274
+ /** Matches needing a human pick (>1 row for one phrase), with candidates. */
275
+ ambiguous: Array<{ reason: string; candidates: Array<{ key: string; label: string }>; [k: string]: unknown }>;
276
+ /** Named targets found only outside the view, offered for an opt-in widen. */
277
+ outOfView: Array<{ reason: string; candidates: Array<{ key: string; label: string }>; [k: string]: unknown }>;
278
+ /** Matches whose value already equals the ask (nothing to change). */
279
+ noops: Array<{ reason: string; [k: string]: unknown }>;
280
+ /** The apply report once applied, or null. */
281
+ applied: AIProposalReport | null;
282
+ /** The proposal in one human sentence, always stating the scope. */
283
+ describe(): string;
284
+ /** Apply the approved diff through the gate (`beforeEdit`, or `beforeMove` for a board). */
285
+ apply(opts?: { board?: unknown }): Promise<AIProposalReport>;
286
+ }
287
+
288
+ /** The report from applying a governed-actor proposal. */
289
+ interface AIProposalReport {
290
+ /** True when at least one edit landed. */
291
+ ok: boolean;
292
+ /** How many edits landed through the gate. */
293
+ applied: number;
294
+ /** How many edits were attempted. */
295
+ requested: number;
296
+ /** How many were stopped by a before-handler veto. */
297
+ vetoed: number;
298
+ /** Which gated path applied them: `'setCells'`, `'board.move'`, or `'none'`. */
299
+ via: string;
300
+ }
301
+
302
+ /**
303
+ * An AI controller over a live grid. It explains the grid's computed figures
304
+ * (Play A), answers questions with validated read-only query specs (Play B),
305
+ * and PROPOSES governed edits a human approves and the grid's own gate applies
306
+ * (Play C). `grid.ai` (in core) is the complementary intent/plan skill layer
307
+ * this consumes.
308
+ */
309
+ interface AI {
310
+ /** The mounted insights panel element, or null. */
311
+ readonly el: HTMLElement | null;
312
+ /** Whether a usable `ask()` is configured. */
313
+ readonly ready: boolean;
314
+ /** Produce a grounded, reconciled narrative for a target. */
315
+ explain(target?: AITarget, opts?: object): Promise<AINarrative>;
316
+ /** An alias for {@link AI.explain}. */
317
+ narrate(target?: AITarget, opts?: object): Promise<AINarrative>;
318
+ /**
319
+ * Produce a grounded, reconciled board / Gantt RISK SUMMARY
320
+ * (BACKLOG-0000979): a plain-language reading like "3 tasks at risk on the
321
+ * critical path, SPI 0.67, 2 SLA breaches". A convenience over
322
+ * `explain({ kind: 'risk', ... })`; the module sources go in `sources`
323
+ * (`gantt`, `board`/`sla`, or precomputed outputs). Every figure runs through
324
+ * the same reconciliation guard as {@link AI.explain}.
325
+ */
326
+ riskSummary(sources?: {
327
+ gantt?: unknown; board?: unknown; sla?: unknown;
328
+ earnedValue?: object; schedule?: object; breaches?: object[]; warnings?: object[];
329
+ includeTaskNames?: boolean; includeCost?: boolean; maxTasks?: number; evmOptions?: object;
330
+ }, opts?: object): Promise<AINarrative>;
331
+ /** Mount (or re-target) the insights panel into an element. */
332
+ insights(el?: HTMLElement, opts?: object): AI;
333
+ /** Build an "Explain" button bound to a target. */
334
+ attachExplain(target: AITarget, opts?: object): HTMLElement | null;
335
+ /** Build the facts packet for a target without calling `ask()`. */
336
+ facts(target?: AITarget, opts?: object): AIFactsPacket;
337
+ /**
338
+ * Ask-your-data: turn a question into a validated, read-only query spec, run
339
+ * it in the engine, and (on apply) fan the answer to router-attached viewers.
340
+ * Returns a result the host reviews; `autoApply` applies a safe read for you.
341
+ */
342
+ query(question: string, opts?: {
343
+ autoApply?: boolean; router?: unknown; schemaOptions?: object;
344
+ context?: unknown; tools?: boolean; signal?: AbortSignal;
345
+ onResult?: (rows: object[]) => void;
346
+ }): Promise<AIQueryResult>;
347
+ /** Apply a reviewed query result (the confirm path); re-gated at the seam. */
348
+ applyQuery(result: AIQueryResult, opts?: { router?: unknown; onResult?: (rows: object[]) => void }): AIApplyReport;
349
+ /** Mount the ask-your-data bar (input, Ask, auto-apply toggle, preview, Apply/Discard). */
350
+ askBar(el?: HTMLElement, opts?: object): AI;
351
+ /**
352
+ * Governed actor (Play C): ask the model for structured edit PROPOSALS over
353
+ * the current view, validate and resolve them (label -> stored value, locate
354
+ * a named row, reject unknown columns/labels/out-of-range), and return a
355
+ * reviewable {@link AIProposal} with a before/after diff. NOTHING is written
356
+ * — the model proposes; a human approves.
357
+ */
358
+ propose(instruction: string, opts?: {
359
+ widen?: boolean; board?: unknown; schemaOptions?: object; maxRows?: number;
360
+ context?: unknown; redact?: string | string[] | ((colId: string) => boolean);
361
+ signal?: AbortSignal;
362
+ }): Promise<AIProposal>;
363
+ /**
364
+ * Apply an approved proposal — the human-approval step. Writes ONLY through
365
+ * the gate: a grid cell edit via `grid.edit.setCells({ origin: 'ai' })` (the
366
+ * `beforeEdit` veto), a kanban move via `board.move({ origin: 'ai' })` (the
367
+ * `beforeMove` veto). A vetoing host handler stops the write.
368
+ */
369
+ applyProposal(result: AIProposal, opts?: { board?: unknown }): Promise<AIProposalReport>;
370
+ /**
371
+ * Mount the governed-actor bar: an instruction input, Propose, a before/after
372
+ * diff preview stating the scope, and Approve/Discard. Approve applies
373
+ * through the gate.
374
+ */
375
+ actorBar(el?: HTMLElement, opts?: object): AI;
376
+ on(name: 'narrative' | 'query' | 'proposal' | 'error' | string, fn: (payload: object) => void): () => void;
377
+ off(name: string, fn: (payload: object) => void): void;
378
+ destroy(): void;
379
+ }
380
+
381
+ /**
382
+ * Create an AI narrative / insights controller over a live grid. The grid may
383
+ * be headless or rendered; the module grounds every figure on the grid's
384
+ * engine and calls only the host's `ask()`.
385
+ */
386
+ export function createAI(grid: unknown, config?: AIConfig): AI;
387
+
388
+ /**
389
+ * Build the RISK-SUMMARY facts packet (BACKLOG-0000979) from the separate
390
+ * Gantt / Kanban modules' public outputs — SPI/CPI and variances from
391
+ * `gantt.earnedValue()`, tasks at risk / on the critical path from
392
+ * `gantt.schedule`, and SLA breaches from `board.sla`. Reads the module
393
+ * instances (or their precomputed outputs) duck-typed off `target`; the AI
394
+ * bundle imports neither module. This is the exact grounded set
395
+ * `explain({ kind: 'risk' })` would use, exposed for preview and testing.
396
+ */
397
+ export function buildRiskFacts(target: AITarget, opts?: {
398
+ locale?: string; fmt?: (value: number) => string;
399
+ }): AIRiskFacts;
400
+
401
+ export default createAI;