@contractspec/lib.surface-runtime 0.2.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 (232) hide show
  1. package/README.md +164 -0
  2. package/dist/adapters/ai-sdk-stub.d.ts +5 -0
  3. package/dist/adapters/ai-sdk-stub.js +13 -0
  4. package/dist/adapters/blocknote-stub.d.ts +6 -0
  5. package/dist/adapters/blocknote-stub.js +31 -0
  6. package/dist/adapters/dnd-kit-adapter.d.ts +13 -0
  7. package/dist/adapters/dnd-kit-adapter.js +44 -0
  8. package/dist/adapters/dnd-kit-stub.d.ts +6 -0
  9. package/dist/adapters/dnd-kit-stub.js +8 -0
  10. package/dist/adapters/floating-ui-stub.d.ts +6 -0
  11. package/dist/adapters/floating-ui-stub.js +19 -0
  12. package/dist/adapters/index.d.ts +11 -0
  13. package/dist/adapters/index.js +176 -0
  14. package/dist/adapters/interfaces.d.ts +75 -0
  15. package/dist/adapters/interfaces.js +1 -0
  16. package/dist/adapters/motion-stub.d.ts +7 -0
  17. package/dist/adapters/motion-stub.js +27 -0
  18. package/dist/adapters/motion-stub.test.d.ts +1 -0
  19. package/dist/adapters/resizable-panels-stub.d.ts +6 -0
  20. package/dist/adapters/resizable-panels-stub.js +46 -0
  21. package/dist/adapters/resizable-panels-stub.test.d.ts +1 -0
  22. package/dist/browser/adapters/ai-sdk-stub.js +12 -0
  23. package/dist/browser/adapters/blocknote-stub.js +30 -0
  24. package/dist/browser/adapters/dnd-kit-adapter.js +43 -0
  25. package/dist/browser/adapters/dnd-kit-stub.js +7 -0
  26. package/dist/browser/adapters/floating-ui-stub.js +18 -0
  27. package/dist/browser/adapters/index.js +175 -0
  28. package/dist/browser/adapters/interfaces.js +0 -0
  29. package/dist/browser/adapters/motion-stub.js +26 -0
  30. package/dist/browser/adapters/resizable-panels-stub.js +45 -0
  31. package/dist/browser/evals/golden-context.js +0 -0
  32. package/dist/browser/evals/golden-harness.js +848 -0
  33. package/dist/browser/examples/pm-workbench.bundle.js +476 -0
  34. package/dist/browser/i18n/catalogs/en.js +71 -0
  35. package/dist/browser/i18n/catalogs/es.js +32 -0
  36. package/dist/browser/i18n/catalogs/fr.js +32 -0
  37. package/dist/browser/i18n/catalogs/index.js +133 -0
  38. package/dist/browser/i18n/index.js +173 -0
  39. package/dist/browser/i18n/keys.js +19 -0
  40. package/dist/browser/i18n/messages.js +143 -0
  41. package/dist/browser/index.js +2466 -0
  42. package/dist/browser/react/BundleProvider.js +47 -0
  43. package/dist/browser/react/BundleRenderer.js +726 -0
  44. package/dist/browser/react/OverlayConflictResolver.js +255 -0
  45. package/dist/browser/react/PatchProposalCard.js +255 -0
  46. package/dist/browser/react/RegionRenderer.js +128 -0
  47. package/dist/browser/react/SlotRenderer.js +118 -0
  48. package/dist/browser/react/WidgetPalette.js +59 -0
  49. package/dist/browser/react/index.js +792 -0
  50. package/dist/browser/runtime/apply-surface-patch.js +322 -0
  51. package/dist/browser/runtime/audit-events.js +137 -0
  52. package/dist/browser/runtime/build-context.js +55 -0
  53. package/dist/browser/runtime/extension-registry.js +58 -0
  54. package/dist/browser/runtime/field-renderer-registry.js +145 -0
  55. package/dist/browser/runtime/index.js +1496 -0
  56. package/dist/browser/runtime/overlay-alignment.js +83 -0
  57. package/dist/browser/runtime/overlay-signer.js +15 -0
  58. package/dist/browser/runtime/override-store.js +52 -0
  59. package/dist/browser/runtime/planner-prompt.js +67 -0
  60. package/dist/browser/runtime/planner-tools.js +77 -0
  61. package/dist/browser/runtime/policy-eval.js +155 -0
  62. package/dist/browser/runtime/preference-adapter.js +67 -0
  63. package/dist/browser/runtime/resolve-bundle.js +767 -0
  64. package/dist/browser/runtime/resolve-preferences.js +59 -0
  65. package/dist/browser/runtime/rollback.js +347 -0
  66. package/dist/browser/runtime/widget-registry.js +36 -0
  67. package/dist/browser/spec/define-module-bundle.js +113 -0
  68. package/dist/browser/spec/index.js +319 -0
  69. package/dist/browser/spec/types.js +0 -0
  70. package/dist/browser/spec/validate-bundle.js +65 -0
  71. package/dist/browser/spec/validate-surface-patch.js +206 -0
  72. package/dist/browser/spec/verification-snapshot-types.js +0 -0
  73. package/dist/browser/telemetry/index.js +20 -0
  74. package/dist/browser/telemetry/surface-metrics.js +20 -0
  75. package/dist/evals/golden-context.d.ts +24 -0
  76. package/dist/evals/golden-context.js +1 -0
  77. package/dist/evals/golden-harness.d.ts +29 -0
  78. package/dist/evals/golden-harness.js +849 -0
  79. package/dist/evals/golden-harness.test.d.ts +1 -0
  80. package/dist/examples/pm-workbench.bundle.d.ts +177 -0
  81. package/dist/examples/pm-workbench.bundle.js +477 -0
  82. package/dist/i18n/catalogs/en.d.ts +1 -0
  83. package/dist/i18n/catalogs/en.js +72 -0
  84. package/dist/i18n/catalogs/es.d.ts +1 -0
  85. package/dist/i18n/catalogs/es.js +33 -0
  86. package/dist/i18n/catalogs/fr.d.ts +1 -0
  87. package/dist/i18n/catalogs/fr.js +33 -0
  88. package/dist/i18n/catalogs/index.d.ts +3 -0
  89. package/dist/i18n/catalogs/index.js +134 -0
  90. package/dist/i18n/index.d.ts +5 -0
  91. package/dist/i18n/index.js +174 -0
  92. package/dist/i18n/keys.d.ts +20 -0
  93. package/dist/i18n/keys.js +20 -0
  94. package/dist/i18n/messages.d.ts +5 -0
  95. package/dist/i18n/messages.js +144 -0
  96. package/dist/index.d.ts +4 -0
  97. package/dist/index.js +2467 -0
  98. package/dist/node/adapters/ai-sdk-stub.js +12 -0
  99. package/dist/node/adapters/blocknote-stub.js +30 -0
  100. package/dist/node/adapters/dnd-kit-adapter.js +43 -0
  101. package/dist/node/adapters/dnd-kit-stub.js +7 -0
  102. package/dist/node/adapters/floating-ui-stub.js +18 -0
  103. package/dist/node/adapters/index.js +175 -0
  104. package/dist/node/adapters/interfaces.js +0 -0
  105. package/dist/node/adapters/motion-stub.js +26 -0
  106. package/dist/node/adapters/resizable-panels-stub.js +45 -0
  107. package/dist/node/evals/golden-context.js +0 -0
  108. package/dist/node/evals/golden-harness.js +848 -0
  109. package/dist/node/examples/pm-workbench.bundle.js +476 -0
  110. package/dist/node/i18n/catalogs/en.js +71 -0
  111. package/dist/node/i18n/catalogs/es.js +32 -0
  112. package/dist/node/i18n/catalogs/fr.js +32 -0
  113. package/dist/node/i18n/catalogs/index.js +133 -0
  114. package/dist/node/i18n/index.js +173 -0
  115. package/dist/node/i18n/keys.js +19 -0
  116. package/dist/node/i18n/messages.js +143 -0
  117. package/dist/node/index.js +2466 -0
  118. package/dist/node/react/BundleProvider.js +47 -0
  119. package/dist/node/react/BundleRenderer.js +726 -0
  120. package/dist/node/react/OverlayConflictResolver.js +255 -0
  121. package/dist/node/react/PatchProposalCard.js +255 -0
  122. package/dist/node/react/RegionRenderer.js +128 -0
  123. package/dist/node/react/SlotRenderer.js +118 -0
  124. package/dist/node/react/WidgetPalette.js +59 -0
  125. package/dist/node/react/index.js +792 -0
  126. package/dist/node/runtime/apply-surface-patch.js +322 -0
  127. package/dist/node/runtime/audit-events.js +137 -0
  128. package/dist/node/runtime/build-context.js +55 -0
  129. package/dist/node/runtime/extension-registry.js +58 -0
  130. package/dist/node/runtime/field-renderer-registry.js +145 -0
  131. package/dist/node/runtime/index.js +1496 -0
  132. package/dist/node/runtime/overlay-alignment.js +83 -0
  133. package/dist/node/runtime/overlay-signer.js +15 -0
  134. package/dist/node/runtime/override-store.js +52 -0
  135. package/dist/node/runtime/planner-prompt.js +67 -0
  136. package/dist/node/runtime/planner-tools.js +77 -0
  137. package/dist/node/runtime/policy-eval.js +155 -0
  138. package/dist/node/runtime/preference-adapter.js +67 -0
  139. package/dist/node/runtime/resolve-bundle.js +767 -0
  140. package/dist/node/runtime/resolve-preferences.js +59 -0
  141. package/dist/node/runtime/rollback.js +347 -0
  142. package/dist/node/runtime/widget-registry.js +36 -0
  143. package/dist/node/spec/define-module-bundle.js +113 -0
  144. package/dist/node/spec/index.js +319 -0
  145. package/dist/node/spec/types.js +0 -0
  146. package/dist/node/spec/validate-bundle.js +65 -0
  147. package/dist/node/spec/validate-surface-patch.js +206 -0
  148. package/dist/node/spec/verification-snapshot-types.js +0 -0
  149. package/dist/node/telemetry/index.js +20 -0
  150. package/dist/node/telemetry/surface-metrics.js +20 -0
  151. package/dist/react/BundleProvider.d.ts +13 -0
  152. package/dist/react/BundleProvider.js +48 -0
  153. package/dist/react/BundleRenderer.d.ts +22 -0
  154. package/dist/react/BundleRenderer.js +727 -0
  155. package/dist/react/OverlayConflictResolver.d.ts +15 -0
  156. package/dist/react/OverlayConflictResolver.js +256 -0
  157. package/dist/react/PatchProposalCard.d.ts +13 -0
  158. package/dist/react/PatchProposalCard.js +256 -0
  159. package/dist/react/RegionRenderer.d.ts +13 -0
  160. package/dist/react/RegionRenderer.js +129 -0
  161. package/dist/react/SlotRenderer.d.ts +13 -0
  162. package/dist/react/SlotRenderer.js +119 -0
  163. package/dist/react/WidgetPalette.d.ts +12 -0
  164. package/dist/react/WidgetPalette.js +60 -0
  165. package/dist/react/index.d.ts +7 -0
  166. package/dist/react/index.js +793 -0
  167. package/dist/runtime/apply-surface-patch.d.ts +15 -0
  168. package/dist/runtime/apply-surface-patch.js +323 -0
  169. package/dist/runtime/apply-surface-patch.test.d.ts +1 -0
  170. package/dist/runtime/audit-events.d.ts +70 -0
  171. package/dist/runtime/audit-events.js +138 -0
  172. package/dist/runtime/audit-events.test.d.ts +1 -0
  173. package/dist/runtime/build-context.d.ts +9 -0
  174. package/dist/runtime/build-context.js +56 -0
  175. package/dist/runtime/extension-registry.d.ts +39 -0
  176. package/dist/runtime/extension-registry.js +59 -0
  177. package/dist/runtime/field-renderer-registry.d.ts +23 -0
  178. package/dist/runtime/field-renderer-registry.js +146 -0
  179. package/dist/runtime/field-renderer-registry.test.d.ts +1 -0
  180. package/dist/runtime/index.d.ts +16 -0
  181. package/dist/runtime/index.js +1497 -0
  182. package/dist/runtime/overlay-alignment.d.ts +49 -0
  183. package/dist/runtime/overlay-alignment.js +84 -0
  184. package/dist/runtime/overlay-alignment.test.d.ts +1 -0
  185. package/dist/runtime/overlay-signer.d.ts +15 -0
  186. package/dist/runtime/overlay-signer.js +16 -0
  187. package/dist/runtime/override-store.d.ts +44 -0
  188. package/dist/runtime/override-store.js +53 -0
  189. package/dist/runtime/override-store.test.d.ts +1 -0
  190. package/dist/runtime/planner-prompt.d.ts +39 -0
  191. package/dist/runtime/planner-prompt.js +68 -0
  192. package/dist/runtime/planner-prompt.test.d.ts +1 -0
  193. package/dist/runtime/planner-tools.d.ts +106 -0
  194. package/dist/runtime/planner-tools.js +78 -0
  195. package/dist/runtime/planner-tools.test.d.ts +1 -0
  196. package/dist/runtime/policy-eval.d.ts +23 -0
  197. package/dist/runtime/policy-eval.js +156 -0
  198. package/dist/runtime/preference-adapter.d.ts +6 -0
  199. package/dist/runtime/preference-adapter.js +68 -0
  200. package/dist/runtime/resolve-bundle.d.ts +68 -0
  201. package/dist/runtime/resolve-bundle.js +768 -0
  202. package/dist/runtime/resolve-bundle.test.d.ts +1 -0
  203. package/dist/runtime/resolve-preferences.d.ts +9 -0
  204. package/dist/runtime/resolve-preferences.js +60 -0
  205. package/dist/runtime/resolve-preferences.test.d.ts +1 -0
  206. package/dist/runtime/rollback.d.ts +21 -0
  207. package/dist/runtime/rollback.js +348 -0
  208. package/dist/runtime/rollback.test.d.ts +1 -0
  209. package/dist/runtime/widget-registry.d.ts +26 -0
  210. package/dist/runtime/widget-registry.js +37 -0
  211. package/dist/runtime/widget-registry.test.d.ts +1 -0
  212. package/dist/spec/define-module-bundle.d.ts +17 -0
  213. package/dist/spec/define-module-bundle.js +114 -0
  214. package/dist/spec/define-module-bundle.test.d.ts +1 -0
  215. package/dist/spec/index.d.ts +5 -0
  216. package/dist/spec/index.js +320 -0
  217. package/dist/spec/types.d.ts +494 -0
  218. package/dist/spec/types.js +1 -0
  219. package/dist/spec/validate-bundle.d.ts +23 -0
  220. package/dist/spec/validate-bundle.js +66 -0
  221. package/dist/spec/validate-bundle.test.d.ts +1 -0
  222. package/dist/spec/validate-surface-patch.d.ts +39 -0
  223. package/dist/spec/validate-surface-patch.js +207 -0
  224. package/dist/spec/validate-surface-patch.test.d.ts +1 -0
  225. package/dist/spec/verification-snapshot-types.d.ts +23 -0
  226. package/dist/spec/verification-snapshot-types.js +1 -0
  227. package/dist/spec/verification-snapshot.test.d.ts +5 -0
  228. package/dist/telemetry/index.d.ts +5 -0
  229. package/dist/telemetry/index.js +21 -0
  230. package/dist/telemetry/surface-metrics.d.ts +17 -0
  231. package/dist/telemetry/surface-metrics.js +21 -0
  232. package/package.json +920 -0
@@ -0,0 +1,83 @@
1
+ // src/runtime/overlay-alignment.ts
2
+ import { applyOverlayModifications } from "@contractspec/lib.overlay-engine/merger";
3
+ function toOverlayScopeContext(ctx) {
4
+ return {
5
+ tenantId: ctx.tenantId,
6
+ userId: ctx.actorId,
7
+ device: ctx.device,
8
+ tags: ctx.featureFlags
9
+ };
10
+ }
11
+ function toOverlayTargetRef(_ctx, target) {
12
+ return {
13
+ presentation: target.surfaceId ?? target.routeId,
14
+ bundleKey: target.bundleKey,
15
+ surfaceId: target.surfaceId,
16
+ routeId: target.routeId,
17
+ entityType: target.entityType
18
+ };
19
+ }
20
+ function toOverlayAppliesTo(ctx, target, scope) {
21
+ const scopeCtx = toOverlayScopeContext(ctx);
22
+ return {
23
+ ...scopeCtx,
24
+ ...target,
25
+ ...scope === "user" && ctx.actorId ? { userId: ctx.actorId } : {},
26
+ ...scope === "workspace" && ctx.workspaceId ? { tags: [...scopeCtx.tags ?? [], `workspace:${ctx.workspaceId}`] } : {}
27
+ };
28
+ }
29
+ function toOverlayRenderableField(field) {
30
+ return {
31
+ key: field.fieldId,
32
+ label: field.title,
33
+ visible: field.visible,
34
+ required: field.required,
35
+ order: 0
36
+ };
37
+ }
38
+ function fromOverlayRenderableField(overlay) {
39
+ return {
40
+ fieldId: overlay.key,
41
+ title: overlay.label ?? overlay.key,
42
+ visible: overlay.visible ?? true,
43
+ required: overlay.required ?? false
44
+ };
45
+ }
46
+ function toOverlayRenderable(fields) {
47
+ return {
48
+ fields: fields.map(toOverlayRenderableField)
49
+ };
50
+ }
51
+ function mergeOverlayResultIntoFields(fields, merged) {
52
+ const fieldMap = new Map(fields.map((f) => [f.fieldId, { ...f }]));
53
+ const result = [];
54
+ for (const overlay of merged.fields) {
55
+ const existing = fieldMap.get(overlay.key);
56
+ if (existing) {
57
+ result.push({
58
+ ...existing,
59
+ title: overlay.label ?? existing.title,
60
+ visible: overlay.visible ?? existing.visible,
61
+ required: overlay.required ?? existing.required
62
+ });
63
+ }
64
+ }
65
+ return result;
66
+ }
67
+ function applyEntityFieldOverlays(fields, overlays, options) {
68
+ if (!overlays.length)
69
+ return fields;
70
+ const target = toOverlayRenderable(fields);
71
+ const merged = applyOverlayModifications(target, overlays, options);
72
+ return mergeOverlayResultIntoFields(fields, merged);
73
+ }
74
+ export {
75
+ toOverlayTargetRef,
76
+ toOverlayScopeContext,
77
+ toOverlayRenderableField,
78
+ toOverlayRenderable,
79
+ toOverlayAppliesTo,
80
+ mergeOverlayResultIntoFields,
81
+ fromOverlayRenderableField,
82
+ applyEntityFieldOverlays
83
+ };
@@ -0,0 +1,15 @@
1
+ // src/runtime/overlay-signer.ts
2
+ import {
3
+ signOverlay,
4
+ verifyOverlaySignature
5
+ } from "@contractspec/lib.overlay-engine/signer";
6
+ function signWorkspaceOverlay(spec, privateKey, options) {
7
+ return signOverlay(spec, privateKey, options);
8
+ }
9
+ function verifyWorkspaceOverlay(overlay) {
10
+ return verifyOverlaySignature(overlay);
11
+ }
12
+ export {
13
+ verifyWorkspaceOverlay,
14
+ signWorkspaceOverlay
15
+ };
@@ -0,0 +1,52 @@
1
+ // src/runtime/override-store.ts
2
+ function buildOverrideTargetKey(bundleKey, surfaceId, routeId) {
3
+ return routeId ? `${bundleKey}:${routeId}:${surfaceId}` : `${bundleKey}:${surfaceId}`;
4
+ }
5
+ function createOverrideStoreWithApprovalGate(store, options) {
6
+ const { requireApprovalForWorkspacePatches = false, requestApproval } = options;
7
+ return {
8
+ list: store.list.bind(store),
9
+ async save(scope, targetKey, patch, saveOptions) {
10
+ if (requireApprovalForWorkspacePatches && scope === "workspace" && requestApproval) {
11
+ const approved = await requestApproval({ scope, targetKey, patch });
12
+ if (!approved) {
13
+ throw new Error("Workspace overlay save rejected: approval required and not granted");
14
+ }
15
+ }
16
+ return store.save(scope, targetKey, patch, saveOptions);
17
+ },
18
+ remove: store.remove.bind(store)
19
+ };
20
+ }
21
+ function createInMemoryOverrideStore() {
22
+ const overrides = new Map;
23
+ function nextId() {
24
+ return `ov_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
25
+ }
26
+ return {
27
+ async list(scope, targetKey) {
28
+ return Array.from(overrides.values()).filter((o) => o.scope === scope && o.targetKey === targetKey);
29
+ },
30
+ async save(scope, targetKey, patch, options) {
31
+ const overrideId = options?.overrideId ?? nextId();
32
+ const stored = {
33
+ overrideId,
34
+ scope,
35
+ targetKey,
36
+ patch,
37
+ createdAt: new Date().toISOString(),
38
+ createdBy: options?.createdBy
39
+ };
40
+ overrides.set(overrideId, stored);
41
+ return overrideId;
42
+ },
43
+ async remove(overrideId) {
44
+ overrides.delete(overrideId);
45
+ }
46
+ };
47
+ }
48
+ export {
49
+ createOverrideStoreWithApprovalGate,
50
+ createInMemoryOverrideStore,
51
+ buildOverrideTargetKey
52
+ };
@@ -0,0 +1,67 @@
1
+ // src/runtime/planner-prompt.ts
2
+ var SAFETY_INSTRUCTIONS = `
3
+ ## Safety instructions (mandatory)
4
+ - Do NOT emit JSX, HTML, or raw markup.
5
+ - Do NOT invent node kinds; use only the allowed kinds listed above.
6
+ - Do NOT call undeclared tools.
7
+ - Prefer fewer high-confidence patches over many speculative ones.
8
+ - Explain why a patch helps the user.
9
+ `;
10
+ function compilePlannerPrompt(input) {
11
+ const {
12
+ bundleMeta,
13
+ surfaceId,
14
+ allowedPatchOps,
15
+ allowedSlots,
16
+ allowedNodeKinds,
17
+ actions,
18
+ preferences,
19
+ basePrompt,
20
+ planSummary,
21
+ entity
22
+ } = input;
23
+ const parts = [];
24
+ parts.push(`# Bundle: ${bundleMeta.title} (${bundleMeta.key}@${bundleMeta.version})`);
25
+ parts.push(`# Surface: ${surfaceId}`);
26
+ parts.push("");
27
+ if (basePrompt) {
28
+ parts.push("## Base instructions");
29
+ parts.push(basePrompt);
30
+ parts.push("");
31
+ }
32
+ parts.push("## Allowed patch operations");
33
+ parts.push(allowedPatchOps.join(", "));
34
+ parts.push("");
35
+ parts.push("## Allowed slots");
36
+ parts.push(allowedSlots.join(", "));
37
+ parts.push("");
38
+ parts.push("## Allowed node kinds");
39
+ parts.push(allowedNodeKinds.join(", "));
40
+ parts.push("");
41
+ if (actions.length > 0) {
42
+ parts.push("## Visible actions");
43
+ for (const a of actions) {
44
+ parts.push(`- ${a.actionId}: ${a.title}`);
45
+ }
46
+ parts.push("");
47
+ }
48
+ parts.push("## Current preference profile");
49
+ parts.push(`guidance=${preferences.guidance}, density=${preferences.density}, ` + `dataDepth=${preferences.dataDepth}, control=${preferences.control}, ` + `media=${preferences.media}, pace=${preferences.pace}, narrative=${preferences.narrative}`);
50
+ parts.push("");
51
+ if (planSummary) {
52
+ parts.push("## Current plan summary");
53
+ parts.push(planSummary);
54
+ parts.push("");
55
+ }
56
+ if (entity) {
57
+ parts.push("## Entity context");
58
+ parts.push(`${entity.type}: ${entity.id}`);
59
+ parts.push("");
60
+ }
61
+ parts.push(SAFETY_INSTRUCTIONS.trim());
62
+ return parts.join(`
63
+ `);
64
+ }
65
+ export {
66
+ compilePlannerPrompt
67
+ };
@@ -0,0 +1,77 @@
1
+ // src/runtime/planner-tools.ts
2
+ var PROPOSE_PATCH_TOOL_SCHEMA = {
3
+ type: "object",
4
+ properties: {
5
+ proposalId: { type: "string", description: "Unique proposal identifier" },
6
+ ops: {
7
+ type: "array",
8
+ description: "Surface patch operations to propose",
9
+ items: {
10
+ type: "object",
11
+ required: ["op"],
12
+ properties: {
13
+ op: {
14
+ type: "string",
15
+ enum: [
16
+ "insert-node",
17
+ "replace-node",
18
+ "remove-node",
19
+ "move-node",
20
+ "resize-panel",
21
+ "set-layout",
22
+ "reveal-field",
23
+ "hide-field",
24
+ "promote-action",
25
+ "set-focus"
26
+ ]
27
+ },
28
+ slotId: { type: "string" },
29
+ nodeId: { type: "string" },
30
+ toSlotId: { type: "string" },
31
+ index: { type: "number" },
32
+ node: {
33
+ type: "object",
34
+ properties: {
35
+ nodeId: { type: "string" },
36
+ kind: { type: "string" },
37
+ title: { type: "string" },
38
+ props: { type: "object" },
39
+ children: { type: "array" }
40
+ }
41
+ },
42
+ persistKey: { type: "string" },
43
+ sizes: { type: "array", items: { type: "number" } },
44
+ layoutId: { type: "string" },
45
+ fieldId: { type: "string" },
46
+ actionId: { type: "string" },
47
+ placement: {
48
+ type: "string",
49
+ enum: ["header", "inline", "context", "assistant"]
50
+ },
51
+ targetId: { type: "string" }
52
+ }
53
+ }
54
+ }
55
+ },
56
+ required: ["proposalId", "ops"]
57
+ };
58
+ var proposePatchToolConfig = {
59
+ name: "propose-patch",
60
+ description: "Propose surface patches (layout changes, node insertions, etc.) for user approval. " + "Only use allowed ops, slots, and node kinds from the planner context.",
61
+ schema: PROPOSE_PATCH_TOOL_SCHEMA,
62
+ automationSafe: false,
63
+ requiresApproval: true
64
+ };
65
+ function buildSurfacePatchProposal(proposalId, ops) {
66
+ return {
67
+ proposalId,
68
+ source: "assistant",
69
+ ops,
70
+ approvalState: "proposed"
71
+ };
72
+ }
73
+ export {
74
+ proposePatchToolConfig,
75
+ buildSurfacePatchProposal,
76
+ PROPOSE_PATCH_TOOL_SCHEMA
77
+ };
@@ -0,0 +1,155 @@
1
+ // src/runtime/audit-events.ts
2
+ function generateEventId() {
3
+ return `evt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
4
+ }
5
+ function emitPatchProposed(audit, args) {
6
+ audit.emit({
7
+ eventId: generateEventId(),
8
+ at: new Date().toISOString(),
9
+ actorId: args.actorId,
10
+ source: args.proposal.source === "assistant" ? "assistant" : "user",
11
+ bundleKey: args.bundleKey,
12
+ surfaceId: args.surfaceId,
13
+ eventType: "patch.proposed",
14
+ payload: {
15
+ proposalId: args.proposal.proposalId,
16
+ source: args.proposal.source,
17
+ opsCount: args.proposal.ops.length
18
+ }
19
+ });
20
+ }
21
+ function emitPatchApproved(audit, args) {
22
+ audit.emit({
23
+ eventId: generateEventId(),
24
+ at: new Date().toISOString(),
25
+ actorId: args.actorId,
26
+ source: "user",
27
+ bundleKey: args.bundleKey,
28
+ surfaceId: args.surfaceId,
29
+ eventType: "patch.approved",
30
+ payload: {
31
+ proposalId: args.proposalId,
32
+ source: args.source,
33
+ opsCount: args.opsCount,
34
+ reason: args.reason
35
+ }
36
+ });
37
+ }
38
+ function emitPatchRejected(audit, args) {
39
+ audit.emit({
40
+ eventId: generateEventId(),
41
+ at: new Date().toISOString(),
42
+ actorId: args.actorId,
43
+ source: "user",
44
+ bundleKey: args.bundleKey,
45
+ surfaceId: args.surfaceId,
46
+ eventType: "patch.rejected",
47
+ payload: {
48
+ proposalId: args.proposalId,
49
+ source: args.source,
50
+ opsCount: args.opsCount,
51
+ reason: args.reason
52
+ }
53
+ });
54
+ }
55
+ function emitOverlaySaved(audit, args) {
56
+ audit.emit({
57
+ eventId: generateEventId(),
58
+ at: new Date().toISOString(),
59
+ actorId: args.actorId,
60
+ source: "user",
61
+ bundleKey: args.bundleKey,
62
+ eventType: "overlay.saved",
63
+ payload: {
64
+ overlayId: args.overlayId,
65
+ scope: args.scope,
66
+ opsCount: args.opsCount
67
+ }
68
+ });
69
+ }
70
+ function emitOverlayApplied(audit, args) {
71
+ audit.emit({
72
+ eventId: generateEventId(),
73
+ at: new Date().toISOString(),
74
+ source: "system",
75
+ bundleKey: args.bundleKey,
76
+ surfaceId: args.surfaceId,
77
+ eventType: "overlay.applied",
78
+ payload: {
79
+ overlayId: args.overlayId,
80
+ opsCount: args.opsCount
81
+ }
82
+ });
83
+ }
84
+ function emitOverlayFailed(audit, args) {
85
+ audit.emit({
86
+ eventId: generateEventId(),
87
+ at: new Date().toISOString(),
88
+ source: "system",
89
+ bundleKey: args.bundleKey,
90
+ surfaceId: args.surfaceId,
91
+ eventType: "overlay.failed",
92
+ payload: {
93
+ overlayId: args.overlayId,
94
+ error: args.error
95
+ }
96
+ });
97
+ }
98
+ function emitPolicyDenied(audit, args) {
99
+ audit.emit({
100
+ eventId: generateEventId(),
101
+ at: new Date().toISOString(),
102
+ actorId: args.actorId,
103
+ source: "policy",
104
+ bundleKey: args.bundleKey,
105
+ surfaceId: args.surfaceId,
106
+ eventType: "policy.denied",
107
+ payload: {
108
+ targetId: args.targetId,
109
+ reason: args.reason
110
+ }
111
+ });
112
+ }
113
+ function emitPolicyRedacted(audit, args) {
114
+ audit.emit({
115
+ eventId: generateEventId(),
116
+ at: new Date().toISOString(),
117
+ actorId: args.actorId,
118
+ source: "policy",
119
+ bundleKey: args.bundleKey,
120
+ surfaceId: args.surfaceId,
121
+ eventType: "policy.redacted",
122
+ payload: {
123
+ targetId: args.targetId,
124
+ redactions: args.redactions
125
+ }
126
+ });
127
+ }
128
+
129
+ // src/runtime/policy-eval.ts
130
+ function evaluatePatchProposalPolicy(ops, ctx, policy) {
131
+ const evaluate = policy?.evaluatePatchProposal;
132
+ if (!evaluate)
133
+ return "allow";
134
+ return evaluate(ops, ctx);
135
+ }
136
+ function evaluateAndEmitPatchPolicy(ops, ctx, args) {
137
+ const effect = evaluatePatchProposalPolicy(ops, ctx, args.policy);
138
+ if (effect === "deny") {
139
+ if (args.audit) {
140
+ emitPolicyDenied(args.audit, {
141
+ bundleKey: args.bundleKey,
142
+ surfaceId: args.surfaceId,
143
+ targetId: args.targetId ?? "patch-proposal",
144
+ reason: "Policy denied patch proposal",
145
+ actorId: ctx.actorId
146
+ });
147
+ }
148
+ return false;
149
+ }
150
+ return true;
151
+ }
152
+ export {
153
+ evaluatePatchProposalPolicy,
154
+ evaluateAndEmitPatchPolicy
155
+ };
@@ -0,0 +1,67 @@
1
+ // src/runtime/resolve-preferences.ts
2
+ var DIMENSION_KEYS = [
3
+ "guidance",
4
+ "density",
5
+ "dataDepth",
6
+ "control",
7
+ "media",
8
+ "pace",
9
+ "narrative"
10
+ ];
11
+ var SCOPE_ORDER = [
12
+ "user",
13
+ "workspace-user",
14
+ "bundle",
15
+ "surface",
16
+ "entity",
17
+ "session"
18
+ ];
19
+ function mergeByScope(layers, ctx) {
20
+ const merged = { ...ctx.preferences };
21
+ const sourceByDimension = {};
22
+ for (const scope of SCOPE_ORDER) {
23
+ const layer = layers[scope];
24
+ if (!layer)
25
+ continue;
26
+ for (const dim of DIMENSION_KEYS) {
27
+ const val = layer[dim];
28
+ if (val !== undefined) {
29
+ merged[dim] = val;
30
+ sourceByDimension[dim] = scope;
31
+ }
32
+ }
33
+ }
34
+ for (const dim of DIMENSION_KEYS) {
35
+ if (sourceByDimension[dim] === undefined) {
36
+ sourceByDimension[dim] = "session";
37
+ }
38
+ }
39
+ return { canonical: merged, sourceByDimension };
40
+ }
41
+ function resolveConstraints(_canonical, _ctx) {
42
+ return { constrained: {}, notes: [] };
43
+ }
44
+ function resolvePreferenceProfile(ctx) {
45
+ const layers = {
46
+ session: ctx.preferences
47
+ };
48
+ const { canonical, sourceByDimension } = mergeByScope(layers, ctx);
49
+ const { constrained, notes } = resolveConstraints(canonical, ctx);
50
+ return {
51
+ canonical,
52
+ sourceByDimension,
53
+ constrained,
54
+ notes
55
+ };
56
+ }
57
+
58
+ // src/runtime/preference-adapter.ts
59
+ var defaultPreferenceAdapter = {
60
+ async resolve(ctx) {
61
+ return resolvePreferenceProfile(ctx);
62
+ },
63
+ async savePreferencePatch(_args) {}
64
+ };
65
+ export {
66
+ defaultPreferenceAdapter
67
+ };