@ai-matrx/alchemy 0.6.2 → 0.8.1

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/CHANGELOG.md +46 -0
  2. package/dist/actions.cjs +374 -0
  3. package/dist/actions.cjs.map +1 -0
  4. package/dist/actions.d.cts +773 -0
  5. package/dist/actions.d.ts +773 -0
  6. package/dist/actions.js +351 -0
  7. package/dist/actions.js.map +1 -0
  8. package/dist/checks.cjs +31 -2
  9. package/dist/checks.cjs.map +1 -1
  10. package/dist/checks.d.cts +24 -1
  11. package/dist/checks.d.ts +24 -1
  12. package/dist/checks.js +31 -2
  13. package/dist/checks.js.map +1 -1
  14. package/dist/core.cjs +1757 -2
  15. package/dist/core.cjs.map +1 -1
  16. package/dist/core.d.cts +595 -1
  17. package/dist/core.d.ts +595 -1
  18. package/dist/core.js +1749 -2
  19. package/dist/core.js.map +1 -1
  20. package/dist/declare.cjs +12 -10
  21. package/dist/declare.cjs.map +1 -1
  22. package/dist/declare.d.cts +18 -2
  23. package/dist/declare.d.ts +18 -2
  24. package/dist/declare.js +12 -10
  25. package/dist/declare.js.map +1 -1
  26. package/dist/index.cjs +1757 -2
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +595 -1
  29. package/dist/index.d.ts +595 -1
  30. package/dist/index.js +1749 -2
  31. package/dist/index.js.map +1 -1
  32. package/dist/menu.cjs +449 -0
  33. package/dist/menu.cjs.map +1 -0
  34. package/dist/menu.d.cts +828 -0
  35. package/dist/menu.d.ts +828 -0
  36. package/dist/menu.js +426 -0
  37. package/dist/menu.js.map +1 -0
  38. package/dist/operate-document.cjs +163 -0
  39. package/dist/operate-document.cjs.map +1 -0
  40. package/dist/operate-document.d.cts +132 -0
  41. package/dist/operate-document.d.ts +132 -0
  42. package/dist/operate-document.js +130 -0
  43. package/dist/operate-document.js.map +1 -0
  44. package/dist/operate-rich-html.cjs +129 -0
  45. package/dist/operate-rich-html.cjs.map +1 -0
  46. package/dist/operate-rich-html.d.cts +136 -0
  47. package/dist/operate-rich-html.d.ts +136 -0
  48. package/dist/operate-rich-html.js +96 -0
  49. package/dist/operate-rich-html.js.map +1 -0
  50. package/dist/operate-server.cjs +157 -0
  51. package/dist/operate-server.cjs.map +1 -0
  52. package/dist/operate-server.d.cts +183 -0
  53. package/dist/operate-server.d.ts +183 -0
  54. package/dist/operate-server.js +134 -0
  55. package/dist/operate-server.js.map +1 -0
  56. package/dist/operate-xlsx.cjs +248 -0
  57. package/dist/operate-xlsx.cjs.map +1 -0
  58. package/dist/operate-xlsx.d.cts +129 -0
  59. package/dist/operate-xlsx.d.ts +129 -0
  60. package/dist/operate-xlsx.js +215 -0
  61. package/dist/operate-xlsx.js.map +1 -0
  62. package/dist/operate.cjs +1774 -0
  63. package/dist/operate.cjs.map +1 -0
  64. package/dist/operate.d.cts +595 -0
  65. package/dist/operate.d.ts +595 -0
  66. package/dist/operate.js +1750 -0
  67. package/dist/operate.js.map +1 -0
  68. package/dist/ports.cjs.map +1 -1
  69. package/dist/ports.d.cts +361 -3
  70. package/dist/ports.d.ts +361 -3
  71. package/dist/react-bar.cjs +695 -0
  72. package/dist/react-bar.cjs.map +1 -0
  73. package/dist/react-bar.d.cts +379 -0
  74. package/dist/react-bar.d.ts +379 -0
  75. package/dist/react-bar.js +674 -0
  76. package/dist/react-bar.js.map +1 -0
  77. package/dist/react-host.cjs +300 -0
  78. package/dist/react-host.cjs.map +1 -0
  79. package/dist/react-host.d.cts +814 -0
  80. package/dist/react-host.d.ts +814 -0
  81. package/dist/react-host.js +268 -0
  82. package/dist/react-host.js.map +1 -0
  83. package/dist/react-menu.cjs +741 -0
  84. package/dist/react-menu.cjs.map +1 -0
  85. package/dist/react-menu.d.cts +370 -0
  86. package/dist/react-menu.d.ts +370 -0
  87. package/dist/react-menu.js +728 -0
  88. package/dist/react-menu.js.map +1 -0
  89. package/dist/react-overflow.cjs +601 -0
  90. package/dist/react-overflow.cjs.map +1 -0
  91. package/dist/react-overflow.d.cts +816 -0
  92. package/dist/react-overflow.d.ts +816 -0
  93. package/dist/react-overflow.js +580 -0
  94. package/dist/react-overflow.js.map +1 -0
  95. package/dist/react-palette.cjs +505 -0
  96. package/dist/react-palette.cjs.map +1 -0
  97. package/dist/react-palette.d.cts +359 -0
  98. package/dist/react-palette.d.ts +359 -0
  99. package/dist/react-palette.js +473 -0
  100. package/dist/react-palette.js.map +1 -0
  101. package/dist/react-selection.cjs +626 -0
  102. package/dist/react-selection.cjs.map +1 -0
  103. package/dist/react-selection.d.cts +357 -0
  104. package/dist/react-selection.d.ts +357 -0
  105. package/dist/react-selection.js +605 -0
  106. package/dist/react-selection.js.map +1 -0
  107. package/dist/react-sheet.cjs +631 -0
  108. package/dist/react-sheet.cjs.map +1 -0
  109. package/dist/react-sheet.d.cts +361 -0
  110. package/dist/react-sheet.d.ts +361 -0
  111. package/dist/react-sheet.js +610 -0
  112. package/dist/react-sheet.js.map +1 -0
  113. package/package.json +148 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,50 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.1
4
+
5
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
6
+ `git diff npm/alchemy/v0.6.2..npm/alchemy/v0.8.1 -- apps/shared/alchemy`).
7
+ No source changes intended and no consumer action required.
8
+
9
+ ## 0.8.0 — 2026-09-26
10
+
11
+ ALC-16: Operate — one engine per format (CONTRACT §1.9 / §2.3).
12
+
13
+ - `/operate` — THE transfer core, moved here from `@ai-matrx/kit/content-transfer` (capture, projection, drafts, limits, preferences, all-matching, `serialize`, `createBrowserTransport`, the AI envelope). A text payload may carry `language` (Markdown fences it; the download takes its extension). New: `FORMAT_ADAPTERS` / `eligibleFormats` / `formatAdapter` (stable ids, synchronous eligibility, lazy engines), `openPreparation` (capture → draft edits → `seal`, built once per revision/format/options), `sealArtifact` / `isSealed` / `sealDraft`, and `createDelivery` (`copy`, `copyPending` for Safari's promise ClipboardItem, `download`, `send` — each accepts ONLY a sealed artifact; `send` without the write door is refused with a remedy).
14
+ - `/operate/formats/rich-html` — "Copy formatted": print's one Markdown→HTML engine with the inline skin; Google Docs and Word are one action (profiles byte-identical, proven). Plain text of Markdown comes from the same parse (tables as TSV, TeX kept).
15
+ - `/operate/formats/document` — the HTML page (print `documentToHtml`, body allow-listed) and PDF / DOCX / EPUB (print `/document`), loaded lazily.
16
+ - `/operate/formats/xlsx` — the workbook from `rows` (SheetJS, lazy; values never formulas; secret/hidden columns dropped by the engine itself).
17
+ - `/operate/server` — `ServerOperation` registry (`registerServerOperation`, `eligibleServerOperations`); `office.generate` registered, offered only when a `ServerPort` is bound.
18
+ - `/ports` adds the ALC-16 ports `transport`, `assets`, `server`.
19
+ - The package root and `/core` re-export `/operate` instead of kit.
20
+ - New dependencies: `@ai-matrx/print` (lazy), `xlsx` (lazy). `scripts/check-operate-sizes.mjs` enforces gzip limits and that print/SheetJS are never statically bundled.
21
+
22
+ ### Consumer action
23
+
24
+ None for existing imports (`/core` keeps every function it had; the pre-contract `FormatAdapter` type and the deprecated `renderMarkdownHtml` / `serializeMarkdownRich` remain on `@ai-matrx/kit/content-transfer` until the frontend repoint). New code imports `@ai-matrx/alchemy/operate`.
25
+
26
+ ## 0.7.0 — 2026-09-26
27
+
28
+ ALC-15: Actions and the one menu engine (CONTRACT §2.4–2.5).
29
+
30
+ - `/actions` — `createActionRegistry` (duplicate provider or action ids are REFUSED with `DuplicateProviderError` / `DuplicateActionError` naming both providers; a duplicate that only appears at resolve time is dropped and captured, never overwritten), `computeEligibility` (R1: an action that does not apply is absent; only the six universal verbs, category `clipboard`, may answer `unavailable-verb` with a sentence — anything else asking to grey is absent and captured; `writes` absent on read-only targets or targets that do not declare the write target; `requiresAuth` reaches a signed-out person only when the `auth` port can sign in and resume), `createClickTarget` (value keys, writable targets and restriction from the declaration), `createProjectedReads` / `projectValues` (secret, credential, non-exportable and undeclared values never reach a provider; each removal is an omission) and `runAction` (the one run path: sign-in-then-resume, projection, failure capture + a sentence with a remedy).
31
+ - `/menu` — `buildMenuModel` (icon KEYS, translated labels, the category → group table, primary sections first, universal verbs addressed by role), the pure layouts `bar`, `overflow`, `context` (classic · tiered · command), `selectionToolbar`, `sheet`, `palette` + `filterPalette`, `leafIds` (the Lossless-Law proof: every layout's leaf set equals the model's), `withExpandedChildren` for lazy submenus, and `resolveMenuLayout` (person → organization → platform default command/comfortable).
32
+ - A named `section` is one block across categories (it sits in its first action's group and keeps its own row order); `overflow` and the bar's ⋯ fold a long named section under its OWN name ("Save as ▸"), never a coined heading.
33
+ - `/ports` adds the ALC-15 ports: `store`, `notify`, `overlay`, `icons`, `knobs`, `i18n`, `auth`, `dialogs` (all optional; absent = that capability absent).
34
+ - Per-layout React subpaths, each size-limited (`scripts/check-subpath-sizes.mjs`, gzip): `/react/host` (T0: `AlchemyActionsProvider`, `useRegisterActionProvider`, `ActionMenuTrigger` — right-click / long-press; loads `/react/menu` or `/react/sheet` by dynamic import on first open and bundles no model or renderer), `/react/bar` (`ActionBar`), `/react/overflow` (`OverflowMenu`), `/react/menu` (`ContextMenuPanel`), `/react/selection` (`SelectionToolbar`), `/react/sheet` (`ActionSheet`), `/react/palette` (`ActionPalette`).
35
+
36
+ ### Consumer action
37
+
38
+ None for existing imports. To adopt: mount `AlchemyActionsProvider` once with the host ports (bind `icons` to the host icon resolver), register each action provider with `useRegisterActionProvider`, and render a layout. Tailwind hosts add `@source "../node_modules/@ai-matrx/alchemy/dist"` so the renderers' utility classes are generated.
39
+
40
+ ## 0.6.3 — 2026-09-26
41
+
42
+ `/checks` adds `findStaleRows(plan, table, existing)` and `mirrorRowKey(row, columns)`: stale mirror rows are judged by the table's full key, so a screen value and an item value that share a name are distinct rows. `SurfaceSyncPlan.keys` names the key of every mirror table the plan owns, including tables it emits no rows for; a `DeclarationExtension` may declare `mirror: { table, conflict }` so its table is keyed even when no declaration contributes a row.
43
+
44
+ ### Consumer action
45
+
46
+ A host that deletes stale mirror rows should call `findStaleRows` and delete each row filtered by every column of `plan.keys[table]`, instead of keying on `(surface_name, name)`.
47
+
3
48
  ## 0.6.2 — 2026-09-26
4
49
 
5
50
  `/checks` adds the declaration half of the route check: `findDeadUrlPatterns(declarations, liveRoutes)`, `urlPatternMatchesRoute` and `routeSegments` (a literal pattern segment is never satisfied by a dynamic route segment; a trailing `*` is a prefix). The host supplies its route list.
@@ -177,3 +222,4 @@ Initial `@ai-matrx/alchemy` distribution package. It exports the existing kit co
177
222
 
178
223
  Wait for the initial npm publish and the required sibling package releases. Then install `@ai-matrx/alchemy` and replace multiple Alchemy package imports with the matching distribution subpath.
179
224
 
225
+
@@ -0,0 +1,374 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/actions.ts
21
+ var actions_exports = {};
22
+ __export(actions_exports, {
23
+ ACTION_CATEGORIES: () => ACTION_CATEGORIES,
24
+ DuplicateActionError: () => DuplicateActionError,
25
+ DuplicateProviderError: () => DuplicateProviderError,
26
+ UNIVERSAL_VERBS: () => UNIVERSAL_VERBS,
27
+ alwaysEligible: () => alwaysEligible,
28
+ computeEligibility: () => computeEligibility,
29
+ createActionRegistry: () => createActionRegistry,
30
+ createClickTarget: () => createClickTarget,
31
+ createProjectedReads: () => createProjectedReads,
32
+ projectValues: () => projectValues,
33
+ runAction: () => runAction,
34
+ staticActionProvider: () => staticActionProvider
35
+ });
36
+ module.exports = __toCommonJS(actions_exports);
37
+
38
+ // src/actions/click-target.ts
39
+ var UNIVERSAL_VERBS = ["copy", "cut", "paste", "undo", "redo", "find"];
40
+
41
+ // src/actions/types.ts
42
+ var ACTION_CATEGORIES = [
43
+ "feedback",
44
+ "copy",
45
+ "export",
46
+ "save",
47
+ "edit",
48
+ "share",
49
+ "creator",
50
+ "app",
51
+ "listen",
52
+ "study",
53
+ "ask",
54
+ "ai",
55
+ "admin",
56
+ "clipboard",
57
+ "history",
58
+ "surface-info"
59
+ ];
60
+
61
+ // src/actions/registry.ts
62
+ var DuplicateActionError = class extends Error {
63
+ actionId;
64
+ providers;
65
+ constructor(actionId, first, second) {
66
+ super(
67
+ first === second ? `Action "${actionId}" is yielded twice by provider "${first}". Ids are unique; the second was refused.` : `Action "${actionId}" is registered by provider "${first}" and again by "${second}". Ids are unique; "${second}"'s copy was refused.`
68
+ );
69
+ this.name = "DuplicateActionError";
70
+ this.actionId = actionId;
71
+ this.providers = [first, second];
72
+ }
73
+ };
74
+ var DuplicateProviderError = class extends Error {
75
+ providerId;
76
+ constructor(providerId) {
77
+ super(`Action provider "${providerId}" is already registered. Unregister it first; nothing was overwritten.`);
78
+ this.name = "DuplicateProviderError";
79
+ this.providerId = providerId;
80
+ }
81
+ };
82
+ var VERBS = new Set(UNIVERSAL_VERBS);
83
+ function capture(ports, error, detail) {
84
+ try {
85
+ ports.diagnostics.capture(error, { area: "actions", detail });
86
+ } catch {
87
+ }
88
+ }
89
+ function computeEligibility(action, target, options) {
90
+ const restrict = options.restrict;
91
+ if (target.excludedActionIds.has(action.id)) return { status: "absent" };
92
+ if (restrict?.exclude?.includes(action.id)) return { status: "absent" };
93
+ if (restrict?.categories && !restrict.categories.includes(action.category)) return { status: "absent" };
94
+ if (action.writes && action.writes.length > 0) {
95
+ if (target.readOnly) return { status: "absent" };
96
+ const writable = new Set(target.writable.map((w) => w.name));
97
+ if (!action.writes.some((name) => writable.has(name))) return { status: "absent" };
98
+ }
99
+ if (action.requiresAuth && !target.auth.authenticated && !options.authResumable) {
100
+ return { status: "absent" };
101
+ }
102
+ const own = action.eligible(target);
103
+ if (own.status !== "unavailable-verb") return own;
104
+ if (action.category !== "clipboard" || !VERBS.has(own.verb)) {
105
+ return {
106
+ status: "contract-break",
107
+ reason: `Action "${action.id}" answered unavailable-verb but only the six universal verbs (category "clipboard") may grey; it is absent instead.`
108
+ };
109
+ }
110
+ if (!own.sentence.trim()) {
111
+ return {
112
+ status: "contract-break",
113
+ reason: `Universal verb "${action.id}" greyed without a sentence; a greyed verb must say why.`
114
+ };
115
+ }
116
+ return own;
117
+ }
118
+ function createActionRegistry(options) {
119
+ const ports = options.ports;
120
+ const entries = /* @__PURE__ */ new Map();
121
+ const listeners = /* @__PURE__ */ new Set();
122
+ const notify = () => {
123
+ for (const l of [...listeners]) l();
124
+ };
125
+ return {
126
+ register(provider) {
127
+ if (entries.has(provider.id)) throw new DuplicateProviderError(provider.id);
128
+ const declared = provider.declaredIds?.() ?? [];
129
+ const own = /* @__PURE__ */ new Set();
130
+ for (const id of declared) {
131
+ if (own.has(id)) throw new DuplicateActionError(id, provider.id, provider.id);
132
+ own.add(id);
133
+ for (const [otherId, other] of entries) {
134
+ if (other.declared.includes(id)) throw new DuplicateActionError(id, otherId, provider.id);
135
+ }
136
+ }
137
+ const entry = { provider, declared };
138
+ entries.set(provider.id, entry);
139
+ notify();
140
+ return () => {
141
+ if (entries.get(provider.id) === entry) {
142
+ entries.delete(provider.id);
143
+ notify();
144
+ }
145
+ };
146
+ },
147
+ async resolve(target, restrict) {
148
+ const authResumable = Boolean(ports.auth);
149
+ const seen = /* @__PURE__ */ new Map();
150
+ const out = [];
151
+ for (const [providerId, { provider }] of [...entries]) {
152
+ let actions;
153
+ try {
154
+ actions = await provider.actions(target);
155
+ } catch (error) {
156
+ capture(ports, error, { providerId, stage: "actions" });
157
+ continue;
158
+ }
159
+ for (const raw of actions) {
160
+ const first = seen.get(raw.id);
161
+ if (first !== void 0) {
162
+ capture(ports, new DuplicateActionError(raw.id, first, providerId), { actionId: raw.id });
163
+ continue;
164
+ }
165
+ seen.set(raw.id, providerId);
166
+ const action = raw.provider === providerId ? raw : { ...raw, provider: providerId };
167
+ let eligibility;
168
+ try {
169
+ eligibility = computeEligibility(action, target, { restrict: restrict ?? {}, authResumable });
170
+ } catch (error) {
171
+ capture(ports, error, { actionId: action.id, stage: "eligible" });
172
+ continue;
173
+ }
174
+ if (eligibility.status === "contract-break") {
175
+ capture(ports, new Error(eligibility.reason), { actionId: action.id, stage: "eligible" });
176
+ continue;
177
+ }
178
+ if (eligibility.status === "absent") continue;
179
+ out.push({ action, eligibility });
180
+ }
181
+ }
182
+ return out;
183
+ },
184
+ providers() {
185
+ return [...entries.keys()];
186
+ },
187
+ subscribe(listener) {
188
+ listeners.add(listener);
189
+ return () => {
190
+ listeners.delete(listener);
191
+ };
192
+ }
193
+ };
194
+ }
195
+ function staticActionProvider(id, actions, tier = "T0") {
196
+ const list = actions.map((a) => a.provider === id ? a : { ...a, provider: id });
197
+ return {
198
+ id,
199
+ tier,
200
+ declaredIds: () => list.map((a) => a.id),
201
+ actions: () => list
202
+ };
203
+ }
204
+ var alwaysEligible = () => ({ status: "available" });
205
+
206
+ // src/declare/sensitivity.ts
207
+ var DEFAULT_SENSITIVITY = Object.freeze({
208
+ exportable: true,
209
+ classification: "ordinary",
210
+ includedByDefault: true
211
+ });
212
+ function resolveSensitivity(value) {
213
+ return {
214
+ exportable: value.sensitivity?.exportable ?? DEFAULT_SENSITIVITY.exportable,
215
+ classification: value.sensitivity?.classification ?? DEFAULT_SENSITIVITY.classification,
216
+ includedByDefault: value.sensitivity?.includedByDefault ?? DEFAULT_SENSITIVITY.includedByDefault
217
+ };
218
+ }
219
+
220
+ // src/actions/projection.ts
221
+ function toJson(value) {
222
+ if (value === void 0 || typeof value === "function" || typeof value === "symbol") return void 0;
223
+ if (value === null || typeof value === "string" || typeof value === "boolean") return value;
224
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
225
+ if (typeof value === "bigint") return value.toString();
226
+ if (value instanceof Date) return value.toISOString();
227
+ if (Array.isArray(value)) return value.map((v) => toJson(v) ?? null);
228
+ if (typeof value === "object") {
229
+ const out = {};
230
+ for (const [k, v] of Object.entries(value)) {
231
+ const j = toJson(v);
232
+ if (j !== void 0) out[k] = j;
233
+ }
234
+ return out;
235
+ }
236
+ return void 0;
237
+ }
238
+ function projectValues(raw, declared, pathPrefix = "") {
239
+ const byName = new Map(declared.map((d) => [d.name, d]));
240
+ const values = {};
241
+ const omissions = [];
242
+ for (const [name, value] of Object.entries(raw)) {
243
+ const path = pathPrefix ? `${pathPrefix}.${name}` : name;
244
+ const decl = byName.get(name);
245
+ if (!decl) {
246
+ omissions.push({ path, reason: "filtered" });
247
+ continue;
248
+ }
249
+ const sensitivity = resolveSensitivity(decl);
250
+ if (sensitivity.classification !== "ordinary") {
251
+ omissions.push({ path, reason: "excluded", classification: sensitivity.classification });
252
+ continue;
253
+ }
254
+ if (!sensitivity.exportable) {
255
+ omissions.push({ path, reason: "excluded" });
256
+ continue;
257
+ }
258
+ const json = toJson(value);
259
+ if (json === void 0) continue;
260
+ values[name] = json;
261
+ }
262
+ return { values, omissions };
263
+ }
264
+ function createProjectedReads(source) {
265
+ return {
266
+ async values(signal) {
267
+ if (!source.surface || !source.declaration) return { values: {}, omissions: [] };
268
+ const raw = await source.surface.readValues(signal);
269
+ const screenValues = source.declaration.values;
270
+ return projectValues(raw, screenValues);
271
+ },
272
+ async item(signal) {
273
+ const item = source.item;
274
+ if (!item || !source.declaration) return null;
275
+ const type = source.declaration.itemTypes?.find((t) => t.name === item.itemType);
276
+ if (!type) return { values: {}, omissions: [{ path: item.itemType, reason: "filtered" }] };
277
+ const raw = await item.readValues(signal);
278
+ return projectValues(raw, type.values, item.itemType);
279
+ },
280
+ async live(signal) {
281
+ if (!source.surface?.readLive) return {};
282
+ return source.surface.readLive(signal);
283
+ }
284
+ };
285
+ }
286
+
287
+ // src/declare/keys.ts
288
+ function qualifyValueKey(itemType, name) {
289
+ return itemType ? `${itemType}.${name}` : name;
290
+ }
291
+
292
+ // src/actions/target.ts
293
+ function domainOf(surfaceName) {
294
+ const slash = surfaceName.indexOf("/");
295
+ return slash > 0 ? surfaceName.slice(0, slash) : surfaceName;
296
+ }
297
+ function createClickTarget(input = {}) {
298
+ const declaration = input.declaration ?? null;
299
+ const item = input.item ?? null;
300
+ const valueKeys = /* @__PURE__ */ new Set();
301
+ let restricted = false;
302
+ const writable = [];
303
+ if (declaration) {
304
+ for (const value of declaration.values) {
305
+ valueKeys.add(value.name);
306
+ const s = resolveSensitivity(value);
307
+ if (s.classification !== "ordinary" || !s.exportable) restricted = true;
308
+ }
309
+ const itemType = item ? declaration.itemTypes?.find((t) => t.name === item.itemType) : void 0;
310
+ if (itemType) {
311
+ for (const value of itemType.values) {
312
+ valueKeys.add(qualifyValueKey(itemType.name, value.name));
313
+ const s = resolveSensitivity(value);
314
+ if (s.classification !== "ordinary" || !s.exportable) restricted = true;
315
+ }
316
+ for (const t of itemType.writeTargets ?? []) writable.push(t);
317
+ }
318
+ for (const t of declaration.writeTargets ?? []) {
319
+ if (!t.itemType || t.itemType === item?.itemType) writable.push(t);
320
+ }
321
+ }
322
+ const readOnly = input.readOnly ?? item?.readOnly ?? false;
323
+ const surfaceName = input.surface?.surfaceName ?? declaration?.surfaceName ?? null;
324
+ const scopeChain = input.scopeChain ?? (surfaceName ? ["global", domainOf(surfaceName), surfaceName] : ["global"]);
325
+ return {
326
+ surface: input.surface ?? null,
327
+ declaration,
328
+ valueKeys,
329
+ scopeChain,
330
+ excludedActionIds: new Set(input.excludedActionIds ?? []),
331
+ item,
332
+ level: input.level ?? item?.level ?? null,
333
+ selection: input.selection ?? null,
334
+ payloadKinds: input.payloadKinds ?? [],
335
+ writable: readOnly ? [] : input.writable ?? writable,
336
+ readOnly,
337
+ restricted,
338
+ organizationId: input.organizationId ?? null,
339
+ auth: {
340
+ authenticated: input.auth?.authenticated ?? false,
341
+ admin: input.auth?.admin ?? false,
342
+ creator: input.auth?.creator ?? false
343
+ },
344
+ host: input.host
345
+ };
346
+ }
347
+
348
+ // src/actions/run.ts
349
+ async function runAction(action, target, options) {
350
+ const { ports } = options;
351
+ if (action.requiresAuth && !target.auth.authenticated) {
352
+ if (!ports.auth) {
353
+ ports.diagnostics.capture(new Error(`requiresAuth action "${action.id}" ran signed out with no auth port`), {
354
+ area: "actions",
355
+ detail: { actionId: action.id }
356
+ });
357
+ return { status: "failed", error: new Error("sign-in unavailable") };
358
+ }
359
+ ports.auth.signInThenResume({ actionId: action.id, contentFingerprint: options.contentFingerprint ?? action.id });
360
+ return { status: "auth-pending" };
361
+ }
362
+ const reads = createProjectedReads(options.source ?? { surface: null, declaration: target.declaration, item: null });
363
+ const signal = options.signal ?? new AbortController().signal;
364
+ try {
365
+ const outcome = await action.run(target, { reads, ports, signal });
366
+ return { status: "ran", outcome };
367
+ } catch (error) {
368
+ ports.diagnostics.capture(error, { area: "actions", detail: { actionId: action.id, stage: "run" } });
369
+ const label = typeof action.label === "string" ? action.label : action.id;
370
+ ports.notify?.error(`${label} did not finish.`, "Try again; if it keeps failing, report it from the feedback button.");
371
+ return { status: "failed", error };
372
+ }
373
+ }
374
+ //# sourceMappingURL=actions.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/actions.ts","../src/actions/click-target.ts","../src/actions/types.ts","../src/actions/registry.ts","../src/declare/sensitivity.ts","../src/actions/projection.ts","../src/declare/keys.ts","../src/actions/target.ts","../src/actions/run.ts"],"sourcesContent":["/**\n * `@ai-matrx/alchemy/actions` — the one action registry (Matrx Alchemy CONTRACT §2.4).\n * Framework-neutral: zero React, zero `@ai-matrx/agents`.\n */\nexport {\n ACTION_CATEGORIES,\n UNIVERSAL_VERBS,\n type Action,\n type ActionCategory,\n type ActionProvider,\n type ActionRegistry,\n type ActionRunContext,\n type ActionSection,\n type ClickTarget,\n type Eligibility,\n type ProjectedReads,\n type ReadOmission,\n type ResolveRestriction,\n type ResolvedAction,\n type UniversalVerb,\n} from \"./actions/types\";\nexport {\n DuplicateActionError,\n DuplicateProviderError,\n alwaysEligible,\n computeEligibility,\n createActionRegistry,\n staticActionProvider,\n type ActionRegistryOptions,\n} from \"./actions/registry\";\nexport { createProjectedReads, projectValues, type ProjectionSource } from \"./actions/projection\";\nexport { createClickTarget, type ClickTargetInput } from \"./actions/target\";\nexport { runAction, type RunActionOptions, type RunResult } from \"./actions/run\";\n","/**\n * The click target (CONTRACT §2.4) in its own module: `/ports` references it,\n * and `/ports` must stay free of every other package (types only).\n */\nimport type { QualifiedValueKey, ResolvedItem, ResolvedSurfaceDeclaration, WriteTarget } from \"../declare/types\";\n\n/** The six universal verbs — the ONLY rows that may grey (R1 c). */\nexport const UNIVERSAL_VERBS = [\"copy\", \"cut\", \"paste\", \"undo\", \"redo\", \"find\"] as const;\nexport type UniversalVerb = (typeof UNIVERSAL_VERBS)[number];\n\n/** The transfer Payload's kinds (`actions/types.ts` asserts equality at compile time). */\nexport type PayloadKind = \"text\" | \"markdown\" | \"json\" | \"rows\" | \"registered\";\n\n/** What eligibility is computed from: everything declared at the click target. */\nexport interface ClickTarget {\n surface: { instanceId: string; surfaceName: string } | null;\n /** The resolved declaration (inheritance applied). Eligibility decides by KEY existence over it. */\n declaration: ResolvedSurfaceDeclaration | null;\n /** Declared value keys with a read path here (screen names + qualified item keys). Key existence, not population. */\n valueKeys: ReadonlySet<QualifiedValueKey>;\n /** Scope chain, most general first: [\"global\", \"<domain>\", \"<surfaceName>\"]. */\n scopeChain: readonly string[];\n /** The surface's explicit exclusions (the one override). */\n excludedActionIds: ReadonlySet<string>;\n item: ResolvedItem | null;\n level: string | null;\n /** Offsets + the live range handle, editable or not. */\n selection: {\n text: string;\n type: \"editable\" | \"non-editable\";\n start: number;\n end: number;\n /** Opaque host handle (DOM Range / element) used to restore or stream into the selection. */\n handle?: unknown;\n } | null;\n /** Payload kinds a capture of this target would produce (from declared value types/kinds). */\n payloadKinds: readonly PayloadKind[];\n /** Declared targets writable on this target right now. */\n writable: readonly WriteTarget[];\n readOnly: boolean;\n /** True when any declared value here is secret/credential or non-exportable. */\n restricted: boolean;\n organizationId: string | null;\n auth: { authenticated: boolean; admin: boolean; creator: boolean };\n /**\n * Host-owned context a provider reads to act (the rich-document source, the\n * editable field's callbacks). Opaque to the package; never crosses into the\n * model. Providers that need it narrow it themselves.\n */\n host?: unknown;\n}\n\n","/**\n * Matrx Alchemy — Actions types (CONTRACT §2.4).\n *\n * One registry of everything a person can do to a thing. Providers plug in;\n * eligibility is computed from what is declared at the click target; duplicate\n * ids are refused; an action that does not apply is ABSENT (chair ruling R1).\n *\n * Framework-neutral: zero React, zero `@ai-matrx/agents`. Icons are string KEYS\n * resolved by the host's `IconResolverPort`; labels go through `I18nPort`.\n */\nimport type { Payload, TransferOutcome } from \"@ai-matrx/kit/content-transfer\";\nimport type { Json, LiveValues } from \"../declare/types\";\nimport type { AlchemyHostPorts } from \"../ports\";\nimport type { ClickTarget, PayloadKind } from \"./click-target\";\n\nexport type { ClickTarget, PayloadKind } from \"./click-target\";\n\n/** PayloadKind is the transfer Payload's kind union, kept equal at compile time. */\ntype Equal<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;\nconst payloadKindsAgree: Equal<PayloadKind, Payload[\"kind\"]> = true;\nvoid payloadKindsAgree;\n\nexport { UNIVERSAL_VERBS, type UniversalVerb } from \"./click-target\";\nimport type { UniversalVerb } from \"./click-target\";\n\n/**\n * Chair ruling R1: an action that does not apply or cannot run now is ABSENT.\n * Only the six universal verbs may answer \"unavailable-verb\": greyed in the\n * strip/bar, the sentence as tooltip. `requiresAuth` is NOT unavailability.\n */\nexport type Eligibility =\n | { status: \"absent\" }\n | { status: \"available\" }\n | { status: \"unavailable-verb\"; verb: UniversalVerb; sentence: string };\n\n/** rich-document's ActionCategory, unchanged, plus the three the context menu groups by. */\nexport type ActionCategory =\n | \"feedback\"\n | \"copy\"\n | \"export\"\n | \"save\"\n | \"edit\"\n | \"share\"\n | \"creator\"\n | \"app\"\n | \"listen\"\n | \"study\"\n | \"ask\"\n | \"ai\"\n | \"admin\"\n | \"clipboard\"\n | \"history\"\n | \"surface-info\";\n\nexport const ACTION_CATEGORIES: readonly ActionCategory[] = [\n \"feedback\",\n \"copy\",\n \"export\",\n \"save\",\n \"edit\",\n \"share\",\n \"creator\",\n \"app\",\n \"listen\",\n \"study\",\n \"ask\",\n \"ai\",\n \"admin\",\n \"clipboard\",\n \"history\",\n \"surface-info\",\n];\n\n/**\n * An optional named section inside the action's group (a grid's cell / row /\n * column). `primary` marks the thing the person clicked: every layout renders\n * it first, inline, heading kept (context-menu-v3's primary section law).\n */\nexport interface ActionSection {\n id: string;\n label: string;\n labelKey?: string;\n icon?: string;\n primary?: boolean;\n}\n\nexport interface Action {\n /** Globally unique. A duplicate is refused (never overwritten). */\n id: string;\n /** The provider that registered it — filled by the registry. */\n provider?: string;\n /** Resolved through I18nPort.t(labelKey ?? id, label). */\n label: string | ((target: ClickTarget) => string);\n labelKey?: string;\n /** Icon KEY resolved by IconResolverPort — the model stays framework-neutral. */\n icon?: string;\n /** Host styling hint for the glyph (rich-document iconColor). Renderers may ignore it. */\n iconTone?: string;\n /** Replaces `icon` while a state holds (a spinner while speaking). */\n stateIcon?(target: ClickTarget): { icon: string; spin?: boolean } | null;\n hint?: string;\n hintKey?: string;\n description?: string;\n category: ActionCategory;\n /** Which universal verb this clipboard action is (addressed by role in every layout). */\n verb?: UniversalVerb;\n order?: number;\n /** Bar layout slot. Default \"overflow\". */\n placement?: \"primary\" | \"overflow\" | \"both\";\n section?: ActionSection;\n /** A signed-out person still sees it; running goes through AuthResumePort (sign in, then resume). */\n requiresAuth?: boolean;\n /** Declared write targets this action lands through. Absent on a read-only target. */\n writes?: readonly string[];\n destructive?: boolean;\n preserveSelection?: boolean;\n /** Link rows navigate instead of running. */\n href?: string | ((target: ClickTarget) => string);\n eligible(target: ClickTarget): Eligibility;\n /** Toggle/pressed state: a pressed button or a checked row. */\n pressed?(target: ClickTarget): boolean;\n /** Present = the row is a checkbox (pressed is its state). */\n toggle?: boolean;\n subscribe?(onChange: () => void, target: ClickTarget): () => void;\n /** Submenus whose rows load on open (agent lists). */\n expand?(target: ClickTarget, signal: AbortSignal): Promise<readonly Action[]>;\n /** Shown centred when `expand` resolves empty. */\n emptyLabel?: string;\n run(target: ClickTarget, context: ActionRunContext): Promise<TransferOutcome | void> | TransferOutcome | void;\n}\n\n/** One removed read, recorded (kit content-transfer's omission shape). */\nexport interface ReadOmission {\n path: string;\n reason: \"excluded\" | \"filtered\";\n classification?: \"secret\" | \"credential\";\n}\n\n/**\n * PROJECTION BEFORE PROVIDERS. Providers never receive a raw read. Every read\n * they can make is projected first: secret and credential values, values\n * declared `exportable: false`, and values nobody declared are removed, with an\n * omission recorded. Raw reads never leave the package.\n */\nexport interface ProjectedReads {\n values(signal: AbortSignal): Promise<{ values: Record<string, Json>; omissions: readonly ReadOmission[] }>;\n item(signal: AbortSignal): Promise<{ values: Record<string, Json>; omissions: readonly ReadOmission[] } | null>;\n live(signal: AbortSignal): Promise<LiveValues>;\n}\n\n/**\n * What a running action receives. `door` (ALC-17) and `operate` (ALC-16) join\n * with their waves; until then those capabilities are absent (N8).\n */\nexport interface ActionRunContext {\n reads: ProjectedReads;\n ports: AlchemyHostPorts;\n signal: AbortSignal;\n}\n\nexport interface ActionProvider {\n id: string;\n /** T0 providers are known at mount; T1 providers load with the menu on first open. */\n tier: \"T0\" | \"T1\";\n /**\n * The ids this provider can ever yield, when known up front. Lets the\n * registry refuse a duplicate at registration instead of at first open.\n */\n declaredIds?(): readonly string[];\n actions(target: ClickTarget): readonly Action[] | Promise<readonly Action[]>;\n}\n\nexport interface ResolvedAction {\n action: Action;\n eligibility: Exclude<Eligibility, { status: \"absent\" }>;\n}\n\nexport interface ResolveRestriction {\n exclude?: readonly string[];\n categories?: readonly ActionCategory[];\n}\n\nexport interface ActionRegistry {\n /** Throws DuplicateActionError naming both providers; nothing is overwritten. */\n register(provider: ActionProvider): () => void;\n /** restrict: a host may remove ids or categories, never add ineligible ones. */\n resolve(target: ClickTarget, restrict?: ResolveRestriction): Promise<readonly ResolvedAction[]>;\n /** Registered provider ids, in registration order. */\n providers(): readonly string[];\n /** Change notification (a provider registered or unregistered). */\n subscribe(listener: () => void): () => void;\n}\n","/**\n * The one action registry (CONTRACT §2.4).\n *\n * - Duplicate ids are REFUSED, never overwritten (rich-document's registry\n * silently overwrote — R12). A duplicate known at registration throws; one\n * that only appears when a provider yields it is dropped and captured.\n * - Eligibility is one pure pass over the resolved click target, under\n * \"restrict, never relax\": a host may remove ids or categories, never add.\n * - R1: an action that does not apply is ABSENT. Only the six universal verbs\n * (category \"clipboard\") may answer `unavailable-verb`, with a sentence; any\n * other action answering it is a contract break → absent + diagnostics.\n */\nimport type { AlchemyHostPorts, Json } from \"../ports\";\nimport {\n UNIVERSAL_VERBS,\n type Action,\n type ActionProvider,\n type ActionRegistry,\n type ClickTarget,\n type Eligibility,\n type ResolveRestriction,\n type ResolvedAction,\n} from \"./types\";\n\nexport class DuplicateActionError extends Error {\n readonly actionId: string;\n readonly providers: readonly [string, string];\n constructor(actionId: string, first: string, second: string) {\n super(\n first === second\n ? `Action \"${actionId}\" is yielded twice by provider \"${first}\". Ids are unique; the second was refused.`\n : `Action \"${actionId}\" is registered by provider \"${first}\" and again by \"${second}\". Ids are unique; \"${second}\"'s copy was refused.`,\n );\n this.name = \"DuplicateActionError\";\n this.actionId = actionId;\n this.providers = [first, second];\n }\n}\n\nexport class DuplicateProviderError extends Error {\n readonly providerId: string;\n constructor(providerId: string) {\n super(`Action provider \"${providerId}\" is already registered. Unregister it first; nothing was overwritten.`);\n this.name = \"DuplicateProviderError\";\n this.providerId = providerId;\n }\n}\n\nexport interface ActionRegistryOptions {\n /** `diagnostics` is required (nothing fails silently); `auth` decides whether requiresAuth actions reach a signed-out person. */\n ports: Pick<AlchemyHostPorts, \"diagnostics\" | \"auth\">;\n}\n\nconst VERBS = new Set<string>(UNIVERSAL_VERBS);\n\nfunction capture(ports: ActionRegistryOptions[\"ports\"], error: unknown, detail: Json): void {\n try {\n ports.diagnostics.capture(error, { area: \"actions\", detail });\n } catch {\n // A broken diagnostics port must never take the menu down with it.\n }\n}\n\n/**\n * Eligibility of one action at one target — the ONE pure pass (CONTRACT §1.6).\n * Exported for providers' tests; hosts call `registry.resolve`.\n */\nexport function computeEligibility(\n action: Action,\n target: ClickTarget,\n options: { restrict?: ResolveRestriction; authResumable: boolean },\n): Eligibility | { status: \"contract-break\"; reason: string } {\n const restrict = options.restrict;\n if (target.excludedActionIds.has(action.id)) return { status: \"absent\" };\n if (restrict?.exclude?.includes(action.id)) return { status: \"absent\" };\n if (restrict?.categories && !restrict.categories.includes(action.category)) return { status: \"absent\" };\n if (action.writes && action.writes.length > 0) {\n // A read-only target offers nothing that would change the record.\n if (target.readOnly) return { status: \"absent\" };\n const writable = new Set(target.writable.map((w) => w.name));\n if (!action.writes.some((name) => writable.has(name))) return { status: \"absent\" };\n }\n if (action.requiresAuth && !target.auth.authenticated && !options.authResumable) {\n // Sign-in-then-resume is the capability; without the auth port it is absent (N8).\n return { status: \"absent\" };\n }\n const own = action.eligible(target);\n if (own.status !== \"unavailable-verb\") return own;\n if (action.category !== \"clipboard\" || !VERBS.has(own.verb)) {\n return {\n status: \"contract-break\",\n reason: `Action \"${action.id}\" answered unavailable-verb but only the six universal verbs (category \"clipboard\") may grey; it is absent instead.`,\n };\n }\n if (!own.sentence.trim()) {\n return {\n status: \"contract-break\",\n reason: `Universal verb \"${action.id}\" greyed without a sentence; a greyed verb must say why.`,\n };\n }\n return own;\n}\n\ninterface Entry {\n provider: ActionProvider;\n declared: readonly string[];\n}\n\nexport function createActionRegistry(options: ActionRegistryOptions): ActionRegistry {\n const ports = options.ports;\n const entries = new Map<string, Entry>();\n const listeners = new Set<() => void>();\n const notify = () => {\n for (const l of [...listeners]) l();\n };\n\n return {\n register(provider) {\n if (entries.has(provider.id)) throw new DuplicateProviderError(provider.id);\n const declared = provider.declaredIds?.() ?? [];\n const own = new Set<string>();\n for (const id of declared) {\n if (own.has(id)) throw new DuplicateActionError(id, provider.id, provider.id);\n own.add(id);\n for (const [otherId, other] of entries) {\n if (other.declared.includes(id)) throw new DuplicateActionError(id, otherId, provider.id);\n }\n }\n const entry: Entry = { provider, declared };\n entries.set(provider.id, entry);\n notify();\n return () => {\n if (entries.get(provider.id) === entry) {\n entries.delete(provider.id);\n notify();\n }\n };\n },\n\n async resolve(target, restrict) {\n const authResumable = Boolean(ports.auth);\n const seen = new Map<string, string>();\n const out: ResolvedAction[] = [];\n for (const [providerId, { provider }] of [...entries]) {\n let actions: readonly Action[];\n try {\n actions = await provider.actions(target);\n } catch (error) {\n capture(ports, error, { providerId, stage: \"actions\" });\n continue;\n }\n for (const raw of actions) {\n const first = seen.get(raw.id);\n if (first !== undefined) {\n capture(ports, new DuplicateActionError(raw.id, first, providerId), { actionId: raw.id });\n continue;\n }\n seen.set(raw.id, providerId);\n const action: Action = raw.provider === providerId ? raw : { ...raw, provider: providerId };\n let eligibility: ReturnType<typeof computeEligibility>;\n try {\n eligibility = computeEligibility(action, target, { restrict: restrict ?? {}, authResumable });\n } catch (error) {\n capture(ports, error, { actionId: action.id, stage: \"eligible\" });\n continue;\n }\n if (eligibility.status === \"contract-break\") {\n capture(ports, new Error(eligibility.reason), { actionId: action.id, stage: \"eligible\" });\n continue;\n }\n if (eligibility.status === \"absent\") continue;\n out.push({ action, eligibility });\n }\n }\n return out;\n },\n\n providers() {\n return [...entries.keys()];\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\n/** A provider over a fixed list; its ids are declared up front so duplicates fail at registration. */\nexport function staticActionProvider(\n id: string,\n actions: readonly Action[],\n tier: ActionProvider[\"tier\"] = \"T0\",\n): ActionProvider {\n const list = actions.map((a) => (a.provider === id ? a : { ...a, provider: id }));\n return {\n id,\n tier,\n declaredIds: () => list.map((a) => a.id),\n actions: () => list,\n };\n}\n\n/** Always-available eligibility, for actions with no rule of their own. */\nexport const alwaysEligible = (): Eligibility => ({ status: \"available\" });\n","/**\n * Sensitivity defaults and resolution (CONTRACT §2.1). Its own module so the\n * lightweight entries (`/actions`, the T0 React host) can project without\n * pulling the declaration registry.\n */\nimport type { DeclaredValue, Sensitivity } from \"./types\";\n\nexport const DEFAULT_SENSITIVITY: Sensitivity = Object.freeze({\n exportable: true,\n classification: \"ordinary\",\n includedByDefault: true,\n});\n\nexport function resolveSensitivity(value: Pick<DeclaredValue, \"sensitivity\">): Sensitivity {\n return {\n exportable: value.sensitivity?.exportable ?? DEFAULT_SENSITIVITY.exportable,\n classification: value.sensitivity?.classification ?? DEFAULT_SENSITIVITY.classification,\n includedByDefault: value.sensitivity?.includedByDefault ?? DEFAULT_SENSITIVITY.includedByDefault,\n };\n}\n","/**\n * PROJECTION BEFORE PROVIDERS (CONTRACT §2.4).\n *\n * The only place a raw read (`MountedSurface.readValues`,\n * `InternalResolvedItem.readValues`) is consumed on behalf of an action.\n * What leaves is projected: a value is kept only when it is DECLARED, its\n * classification is \"ordinary\" and it is exportable. Everything removed is\n * recorded as an omission, so the person and the agent can see what was held\n * back. No caller can relax this.\n */\nimport { resolveSensitivity } from \"../declare/sensitivity\";\nimport type { InternalResolvedItem, MountedSurface } from \"../declare/host\";\nimport type { DeclaredValue, Json, LiveValues, ResolvedSurfaceDeclaration } from \"../declare/types\";\nimport type { ProjectedReads, ReadOmission } from \"./types\";\n\nexport interface ProjectionSource {\n surface: MountedSurface | null;\n declaration: ResolvedSurfaceDeclaration | null;\n item: InternalResolvedItem | null;\n}\n\nfunction toJson(value: unknown): Json | undefined {\n if (value === undefined || typeof value === \"function\" || typeof value === \"symbol\") return undefined;\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n if (typeof value === \"bigint\") return value.toString();\n if (value instanceof Date) return value.toISOString();\n if (Array.isArray(value)) return value.map((v) => toJson(v) ?? null);\n if (typeof value === \"object\") {\n const out: { [key: string]: Json } = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n const j = toJson(v);\n if (j !== undefined) out[k] = j;\n }\n return out;\n }\n return undefined;\n}\n\n/** Keep declared, ordinary, exportable values; record every removal. */\nexport function projectValues(\n raw: Record<string, unknown>,\n declared: readonly Pick<DeclaredValue, \"name\" | \"sensitivity\">[],\n pathPrefix = \"\",\n): { values: Record<string, Json>; omissions: ReadOmission[] } {\n const byName = new Map(declared.map((d) => [d.name, d]));\n const values: Record<string, Json> = {};\n const omissions: ReadOmission[] = [];\n for (const [name, value] of Object.entries(raw)) {\n const path = pathPrefix ? `${pathPrefix}.${name}` : name;\n const decl = byName.get(name);\n if (!decl) {\n omissions.push({ path, reason: \"filtered\" });\n continue;\n }\n const sensitivity = resolveSensitivity(decl);\n if (sensitivity.classification !== \"ordinary\") {\n omissions.push({ path, reason: \"excluded\", classification: sensitivity.classification });\n continue;\n }\n if (!sensitivity.exportable) {\n omissions.push({ path, reason: \"excluded\" });\n continue;\n }\n const json = toJson(value);\n if (json === undefined) continue;\n values[name] = json;\n }\n return { values, omissions };\n}\n\nexport function createProjectedReads(source: ProjectionSource): ProjectedReads {\n return {\n async values(signal) {\n if (!source.surface || !source.declaration) return { values: {}, omissions: [] };\n const raw = await source.surface.readValues(signal);\n const screenValues = source.declaration.values;\n return projectValues(raw, screenValues);\n },\n async item(signal) {\n const item = source.item;\n if (!item || !source.declaration) return null;\n const type = source.declaration.itemTypes?.find((t) => t.name === item.itemType);\n if (!type) return { values: {}, omissions: [{ path: item.itemType, reason: \"filtered\" }] };\n const raw = await item.readValues(signal);\n return projectValues(raw, type.values, item.itemType);\n },\n async live(signal): Promise<LiveValues> {\n if (!source.surface?.readLive) return {};\n return source.surface.readLive(signal);\n },\n };\n}\n","import type { QualifiedValueKey } from \"./types\";\n\n/** Every value, write-target, item-type and group name (the DB CHECK rule). */\nexport const DECLARATION_NAME_RE = /^[a-z][a-z0-9_]*$/;\n\n/** \"<client>/<local>\" — the surface naming convention. */\nexport const SURFACE_NAME_RE = /^[a-z][a-z0-9-]*\\/[a-z0-9-/]+$/;\n\n/** A bare screen value (`status`) or an item value (`table_row.status`). */\nexport const QUALIFIED_VALUE_KEY_RE = /^[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)?$/;\n\nexport interface ParsedValueKey {\n /** \"\" for a screen-level value. */\n itemType: string;\n name: string;\n}\n\n/** Split a qualified key; null when it is not a valid bare or qualified key. */\nexport function parseQualifiedValueKey(key: string): ParsedValueKey | null {\n if (!QUALIFIED_VALUE_KEY_RE.test(key)) return null;\n const dot = key.indexOf(\".\");\n if (dot === -1) return { itemType: \"\", name: key };\n return { itemType: key.slice(0, dot), name: key.slice(dot + 1) };\n}\n\nexport function qualifyValueKey(itemType: string, name: string): QualifiedValueKey {\n return itemType ? `${itemType}.${name}` : name;\n}\n\n/** The client that owns a surface: its name prefix. */\nexport function surfaceClientOf(surfaceName: string): string {\n return surfaceName.split(\"/\")[0] ?? \"\";\n}\n","/**\n * Building a ClickTarget from what is declared at the click (CONTRACT §2.4).\n * Key existence, never value population: a value key is present when the\n * declaration gives it a read path here.\n */\nimport { resolveSensitivity } from \"../declare/sensitivity\";\nimport { qualifyValueKey } from \"../declare/keys\";\nimport type { ResolvedItem, ResolvedSurfaceDeclaration, WriteTarget } from \"../declare/types\";\nimport type { ClickTarget } from \"./types\";\n\nexport interface ClickTargetInput {\n surface?: ClickTarget[\"surface\"];\n declaration?: ResolvedSurfaceDeclaration | null;\n item?: ResolvedItem | null;\n level?: string | null;\n selection?: ClickTarget[\"selection\"];\n payloadKinds?: ClickTarget[\"payloadKinds\"];\n /** Defaults to the item's readOnly (or false). */\n readOnly?: boolean;\n /** Extra exclusions on top of the declaration's own. */\n excludedActionIds?: Iterable<string>;\n scopeChain?: readonly string[];\n organizationId?: string | null;\n auth?: Partial<ClickTarget[\"auth\"]>;\n /** Write targets the host can serve right now; defaults to every declared target for the screen/item. */\n writable?: readonly WriteTarget[];\n host?: unknown;\n}\n\nfunction domainOf(surfaceName: string): string {\n const slash = surfaceName.indexOf(\"/\");\n return slash > 0 ? surfaceName.slice(0, slash) : surfaceName;\n}\n\nexport function createClickTarget(input: ClickTargetInput = {}): ClickTarget {\n const declaration = input.declaration ?? null;\n const item = input.item ?? null;\n const valueKeys = new Set<string>();\n let restricted = false;\n const writable: WriteTarget[] = [];\n if (declaration) {\n for (const value of declaration.values) {\n valueKeys.add(value.name);\n const s = resolveSensitivity(value);\n if (s.classification !== \"ordinary\" || !s.exportable) restricted = true;\n }\n const itemType = item ? declaration.itemTypes?.find((t) => t.name === item.itemType) : undefined;\n if (itemType) {\n for (const value of itemType.values) {\n valueKeys.add(qualifyValueKey(itemType.name, value.name));\n const s = resolveSensitivity(value);\n if (s.classification !== \"ordinary\" || !s.exportable) restricted = true;\n }\n for (const t of itemType.writeTargets ?? []) writable.push(t);\n }\n for (const t of declaration.writeTargets ?? []) {\n if (!t.itemType || t.itemType === item?.itemType) writable.push(t);\n }\n }\n const readOnly = input.readOnly ?? item?.readOnly ?? false;\n const surfaceName = input.surface?.surfaceName ?? declaration?.surfaceName ?? null;\n const scopeChain = input.scopeChain ?? (surfaceName ? [\"global\", domainOf(surfaceName), surfaceName] : [\"global\"]);\n return {\n surface: input.surface ?? null,\n declaration,\n valueKeys,\n scopeChain,\n excludedActionIds: new Set(input.excludedActionIds ?? []),\n item,\n level: input.level ?? item?.level ?? null,\n selection: input.selection ?? null,\n payloadKinds: input.payloadKinds ?? [],\n writable: readOnly ? [] : (input.writable ?? writable),\n readOnly,\n restricted,\n organizationId: input.organizationId ?? null,\n auth: {\n authenticated: input.auth?.authenticated ?? false,\n admin: input.auth?.admin ?? false,\n creator: input.auth?.creator ?? false,\n },\n host: input.host,\n };\n}\n","/**\n * The one run path (T1e). Every layout runs an action through here, so the\n * sign-in-then-resume rule, projection and failure capture live once.\n */\nimport type { TransferOutcome } from \"@ai-matrx/kit/content-transfer\";\nimport type { AlchemyHostPorts } from \"../ports\";\nimport { createProjectedReads, type ProjectionSource } from \"./projection\";\nimport type { Action, ClickTarget } from \"./types\";\n\nexport interface RunActionOptions {\n ports: AlchemyHostPorts;\n /** Raw sources; projected before the action sees them. */\n source?: ProjectionSource;\n /** Stable fingerprint of the content, for sign-in-then-resume. */\n contentFingerprint?: string;\n signal?: AbortSignal;\n}\n\nexport type RunResult =\n | { status: \"ran\"; outcome: TransferOutcome | void }\n | { status: \"auth-pending\" }\n | { status: \"failed\"; error: unknown };\n\nexport async function runAction(action: Action, target: ClickTarget, options: RunActionOptions): Promise<RunResult> {\n const { ports } = options;\n if (action.requiresAuth && !target.auth.authenticated) {\n if (!ports.auth) {\n // Unreachable through resolve (the action is absent without the port); guard direct callers.\n ports.diagnostics.capture(new Error(`requiresAuth action \"${action.id}\" ran signed out with no auth port`), {\n area: \"actions\",\n detail: { actionId: action.id },\n });\n return { status: \"failed\", error: new Error(\"sign-in unavailable\") };\n }\n ports.auth.signInThenResume({ actionId: action.id, contentFingerprint: options.contentFingerprint ?? action.id });\n return { status: \"auth-pending\" };\n }\n const reads = createProjectedReads(options.source ?? { surface: null, declaration: target.declaration, item: null });\n const signal = options.signal ?? new AbortController().signal;\n try {\n const outcome = await action.run(target, { reads, ports, signal });\n return { status: \"ran\", outcome };\n } catch (error) {\n ports.diagnostics.capture(error, { area: \"actions\", detail: { actionId: action.id, stage: \"run\" } });\n const label = typeof action.label === \"string\" ? action.label : action.id;\n ports.notify?.error(`${label} did not finish.`, \"Try again; if it keeps failing, report it from the feedback button.\");\n return { status: \"failed\", error };\n }\n}\n"],"mappings":"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","names":[]}