stylegallery 0.1.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 (346) hide show
  1. package/AGENTS.md +156 -0
  2. package/CATALOG.md +69 -0
  3. package/DOMAINS.md +65 -0
  4. package/GOVERNANCE.md +222 -0
  5. package/GUIDE.md +59 -0
  6. package/README.md +313 -0
  7. package/consumer-reference/adapters/style-dictionary.config.mjs +36 -0
  8. package/consumer-reference/agent-native/README.md +157 -0
  9. package/consumer-reference/agent-native/registry.json +640 -0
  10. package/consumer-reference/agent-native/schema/agent-native.schema.json +848 -0
  11. package/consumer-reference/agent-native/schema/epistemic.schema.json +14 -0
  12. package/consumer-reference/agent-native/schema/execution.schema.json +12 -0
  13. package/consumer-reference/agent-native/schema/identity.schema.json +10 -0
  14. package/consumer-reference/agent-native/schema/learning.schema.json +12 -0
  15. package/consumer-reference/agent-native/schema/manifest.schema.json +6 -0
  16. package/consumer-reference/agent-native/schema/operation.schema.json +12 -0
  17. package/consumer-reference/agent-native/schema/protocol-binding.schema.json +9 -0
  18. package/consumer-reference/agent-native/schema/retrieval.schema.json +10 -0
  19. package/consumer-reference/baselines/calibration.json +260 -0
  20. package/consumer-reference/baselines/manifest.json +21 -0
  21. package/consumer-reference/contract.md +83 -0
  22. package/consumer-reference/fixtures/consumer-conformance/e2e-fixture.mjs +282 -0
  23. package/consumer-reference/fixtures/consumer-conformance/manifest.json +102 -0
  24. package/consumer-reference/fixtures/consumer-conformance/runtime-proof.mjs +32 -0
  25. package/consumer-reference/fixtures/consumer-conformance/valid-migration-result.json +18 -0
  26. package/consumer-reference/fixtures/consumer-conformance/valid-migration.json +142 -0
  27. package/consumer-reference/fixtures/invalid-stable-ended-support.json +19 -0
  28. package/consumer-reference/fixtures/promotion/invalid-blocking-evidence.json +26 -0
  29. package/consumer-reference/fixtures/promotion/invalid-count-only.json +29 -0
  30. package/consumer-reference/fixtures/promotion/invalid-missing-owner-migration.json +25 -0
  31. package/consumer-reference/fixtures/promotion/invalid-normative-bypass-no-regression.json +25 -0
  32. package/consumer-reference/fixtures/promotion/invalid-related-counted-independent.json +45 -0
  33. package/consumer-reference/fixtures/promotion/invalid-stable-ended-support.json +26 -0
  34. package/consumer-reference/fixtures/promotion/manifest.json +15 -0
  35. package/consumer-reference/fixtures/promotion/valid-deferred-example.json +67 -0
  36. package/consumer-reference/fixtures/promotion/valid-normative-bypass.json +67 -0
  37. package/consumer-reference/fixtures/token-portability/invalid-cycle.json +7 -0
  38. package/consumer-reference/fixtures/token-portability/invalid-dangling-alias.json +6 -0
  39. package/consumer-reference/fixtures/token-portability/invalid-extends.json +4 -0
  40. package/consumer-reference/fixtures/token-portability/invalid-json-pointer.json +7 -0
  41. package/consumer-reference/fixtures/token-portability/invalid-resolver.json +9 -0
  42. package/consumer-reference/fixtures/token-portability/invalid-type-mismatch.json +10 -0
  43. package/consumer-reference/fixtures/token-portability/invalid-unknown-reserved.json +6 -0
  44. package/consumer-reference/fixtures/token-portability/invalid-untested-type.json +6 -0
  45. package/consumer-reference/fixtures/token-portability/valid-border.json +14 -0
  46. package/consumer-reference/fixtures/token-portability/valid-reference.json +32 -0
  47. package/consumer-reference/fixtures/token-portability/valid-whole-alias.json +7 -0
  48. package/consumer-reference/fixtures/valid-deprecated.json +21 -0
  49. package/consumer-reference/fixtures/valid-experimental.json +19 -0
  50. package/consumer-reference/generated/manifest.json +40 -0
  51. package/consumer-reference/generated/tokens.css +12 -0
  52. package/consumer-reference/index.md +32 -0
  53. package/consumer-reference/policies/shared-experimental.json +37 -0
  54. package/consumer-reference/schema/ax-evidence.schema.json +30 -0
  55. package/consumer-reference/schema/baseline-manifest.schema.json +55 -0
  56. package/consumer-reference/schema/calibration-record.schema.json +190 -0
  57. package/consumer-reference/schema/capture-session.schema.json +161 -0
  58. package/consumer-reference/schema/component-state.schema.json +150 -0
  59. package/consumer-reference/schema/consumer-conformance-record.schema.json +365 -0
  60. package/consumer-reference/schema/dom-evidence.schema.json +38 -0
  61. package/consumer-reference/schema/evidence-record.schema.json +81 -0
  62. package/consumer-reference/schema/fixture-manifest.schema.json +32 -0
  63. package/consumer-reference/schema/item.schema.json +188 -0
  64. package/consumer-reference/schema/page-evidence-manifest.schema.json +216 -0
  65. package/consumer-reference/schema/page-evidence-session.schema.json +119 -0
  66. package/consumer-reference/schema/portable-tokens.schema.json +104 -0
  67. package/consumer-reference/schema/promotion-rfc.schema.json +219 -0
  68. package/consumer-reference/schema/runtime-evidence-manifest.schema.json +33 -0
  69. package/consumer-reference/schema/visual-evidence.schema.json +31 -0
  70. package/design-engineering/consumer-migration-readiness.md +124 -0
  71. package/design-engineering/index.md +28 -0
  72. package/design-engineering/interface-craft.md +107 -0
  73. package/design-engineering/reference-profiles/external-adaptation/index.md +12 -0
  74. package/design-engineering/reference-profiles/governed-local/editorial/components/button.component.json +125 -0
  75. package/design-engineering/reference-profiles/governed-local/editorial/evidence/button.evidence.json +3504 -0
  76. package/design-engineering/reference-profiles/governed-local/editorial/fixtures/button.fixture.json +65 -0
  77. package/design-engineering/reference-profiles/governed-local/editorial/generated/evidence-coverage.md +23 -0
  78. package/design-engineering/reference-profiles/governed-local/editorial/generated/keyboard-matrix.md +19 -0
  79. package/design-engineering/reference-profiles/governed-local/editorial/generated/state-matrix.md +21 -0
  80. package/design-engineering/reference-profiles/governed-local/editorial/local-foundations.json +12 -0
  81. package/design-engineering/reference-profiles/governed-local/editorial/profile.json +43 -0
  82. package/design-engineering/reference-profiles/governed-local/editorial/states/button.states.json +195 -0
  83. package/design-engineering/reference-profiles/governed-local/editorial/tokens.dtcg.json +17 -0
  84. package/design-engineering/reference-profiles/governed-local/index.md +26 -0
  85. package/design-engineering/reference-profiles/governed-local/terminal/components/button.component.json +125 -0
  86. package/design-engineering/reference-profiles/governed-local/terminal/evidence/button.evidence.json +3504 -0
  87. package/design-engineering/reference-profiles/governed-local/terminal/fixtures/button.fixture.json +65 -0
  88. package/design-engineering/reference-profiles/governed-local/terminal/generated/evidence-coverage.md +23 -0
  89. package/design-engineering/reference-profiles/governed-local/terminal/generated/keyboard-matrix.md +19 -0
  90. package/design-engineering/reference-profiles/governed-local/terminal/generated/state-matrix.md +21 -0
  91. package/design-engineering/reference-profiles/governed-local/terminal/local-foundations.json +12 -0
  92. package/design-engineering/reference-profiles/governed-local/terminal/profile.json +43 -0
  93. package/design-engineering/reference-profiles/governed-local/terminal/states/button.states.json +195 -0
  94. package/design-engineering/reference-profiles/governed-local/terminal/tokens.dtcg.json +17 -0
  95. package/design-engineering/reference-profiles/index.md +19 -0
  96. package/game-ui/classification.md +82 -0
  97. package/game-ui/index.md +35 -0
  98. package/game-ui/reference-record.md +62 -0
  99. package/game-ui/screen-hierarchy.md +107 -0
  100. package/game-ui/unity/architecture.md +166 -0
  101. package/game-ui/unity/cli-loop.md +84 -0
  102. package/game-ui/unity/data/unity-technologies-public-repositories.json +26654 -0
  103. package/game-ui/unity/org-wiki.md +146 -0
  104. package/game-ui/unity/repository-map.md +102 -0
  105. package/game-ui/unity/ui-systems.md +85 -0
  106. package/guides/decision-tree.md +149 -0
  107. package/guides/documentation-mode-taxonomy.md +157 -0
  108. package/guides/layout-brief.md +220 -0
  109. package/guides/vocabulary.md +148 -0
  110. package/guides/webpage-generation-workflow.md +185 -0
  111. package/index.md +36 -0
  112. package/layout/index.md +26 -0
  113. package/motion/index.md +24 -0
  114. package/motion/practice-reference.md +145 -0
  115. package/motion/review-workflow.md +86 -0
  116. package/motion/vocabulary.md +82 -0
  117. package/package.json +78 -0
  118. package/patterns/centering/center.md +87 -0
  119. package/patterns/centering/index.md +6 -0
  120. package/patterns/centering/super-center.md +89 -0
  121. package/patterns/containment/box.md +87 -0
  122. package/patterns/containment/clamped-card.md +86 -0
  123. package/patterns/containment/content-limiter.md +87 -0
  124. package/patterns/containment/fluid-styles.md +86 -0
  125. package/patterns/containment/index.md +8 -0
  126. package/patterns/grid-repetition/card-grid.md +88 -0
  127. package/patterns/grid-repetition/columns.md +87 -0
  128. package/patterns/grid-repetition/dense-grid.md +88 -0
  129. package/patterns/grid-repetition/grid-wrapper.md +89 -0
  130. package/patterns/grid-repetition/index.md +12 -0
  131. package/patterns/grid-repetition/masonry-approx.md +87 -0
  132. package/patterns/grid-repetition/page-grid.md +90 -0
  133. package/patterns/grid-repetition/ram-grid.md +88 -0
  134. package/patterns/grid-repetition/twelve-span-grid.md +92 -0
  135. package/patterns/in-line-grouping/badge-list.md +94 -0
  136. package/patterns/in-line-grouping/breadcrumb.md +89 -0
  137. package/patterns/in-line-grouping/cluster.md +89 -0
  138. package/patterns/in-line-grouping/deconstructed-pancake.md +92 -0
  139. package/patterns/in-line-grouping/index.md +13 -0
  140. package/patterns/in-line-grouping/pagination.md +89 -0
  141. package/patterns/in-line-grouping/reel.md +90 -0
  142. package/patterns/in-line-grouping/split-nav.md +97 -0
  143. package/patterns/in-line-grouping/tab-strip.md +88 -0
  144. package/patterns/in-line-grouping/wrap-row.md +89 -0
  145. package/patterns/index.md +13 -0
  146. package/patterns/media-fit/frame.md +95 -0
  147. package/patterns/media-fit/icon-frame.md +87 -0
  148. package/patterns/media-fit/index.md +6 -0
  149. package/patterns/overlay-exception/imposter.md +95 -0
  150. package/patterns/overlay-exception/index.md +6 -0
  151. package/patterns/overlay-exception/overlay-stack.md +89 -0
  152. package/patterns/split-sidebar/index.md +12 -0
  153. package/patterns/split-sidebar/list-detail.md +95 -0
  154. package/patterns/split-sidebar/main-with-rail.md +95 -0
  155. package/patterns/split-sidebar/media-object.md +102 -0
  156. package/patterns/split-sidebar/sidebar.md +101 -0
  157. package/patterns/split-sidebar/split-screen.md +92 -0
  158. package/patterns/split-sidebar/sticky-aside.md +97 -0
  159. package/patterns/split-sidebar/supporting-pane.md +95 -0
  160. package/patterns/split-sidebar/switcher.md +93 -0
  161. package/patterns/stacking/feed.md +88 -0
  162. package/patterns/stacking/index.md +8 -0
  163. package/patterns/stacking/line-up.md +95 -0
  164. package/patterns/stacking/stack.md +87 -0
  165. package/patterns/stacking/step-nav.md +88 -0
  166. package/patterns/viewport-shell/cover.md +90 -0
  167. package/patterns/viewport-shell/fixed-sidenav-shell.md +97 -0
  168. package/patterns/viewport-shell/holy-grail.md +112 -0
  169. package/patterns/viewport-shell/index.md +11 -0
  170. package/patterns/viewport-shell/panel-layout.md +95 -0
  171. package/patterns/viewport-shell/scroll-body-shell.md +93 -0
  172. package/patterns/viewport-shell/sticky-footer.md +92 -0
  173. package/patterns/viewport-shell/sticky-header.md +86 -0
  174. package/platform-guides/apple-interaction.md +89 -0
  175. package/platform-guides/index.md +26 -0
  176. package/quality/claim-records/index.md +3 -0
  177. package/quality/claim-records/samples.md +92 -0
  178. package/quality/claim-records/stylegallery-multidomain-scope.md +42 -0
  179. package/quality/claims.md +77 -0
  180. package/quality/evidence/accessibility.md +58 -0
  181. package/quality/evidence/consumer-migration.md +42 -0
  182. package/quality/evidence/design-rationale.md +34 -0
  183. package/quality/evidence/executable-evidence.md +79 -0
  184. package/quality/evidence/families.md +56 -0
  185. package/quality/evidence/hci-evaluation.md +36 -0
  186. package/quality/evidence/index.md +16 -0
  187. package/quality/evidence/pattern-contract-audit.md +96 -0
  188. package/quality/evidence/search-metadata-polyhierarchy.md +86 -0
  189. package/quality/evidence/sources.md +43 -0
  190. package/quality/evidence/tokens.md +33 -0
  191. package/quality/evidence/visual-qa.md +41 -0
  192. package/quality/gates/accessibility-evidence.md +60 -0
  193. package/quality/gates/consumer-migration-evidence.md +53 -0
  194. package/quality/gates/design-claim.md +56 -0
  195. package/quality/gates/harmony-evaluation.md +78 -0
  196. package/quality/gates/index.md +13 -0
  197. package/quality/gates/layout.md +52 -0
  198. package/quality/gates/rationale.md +53 -0
  199. package/quality/gates/visual-evidence.md +47 -0
  200. package/quality/index.md +55 -0
  201. package/quality/principles.md +58 -0
  202. package/recipes/article-page.md +52 -0
  203. package/recipes/command-surface.md +55 -0
  204. package/recipes/dashboard.md +56 -0
  205. package/recipes/form-flow.md +55 -0
  206. package/recipes/homepage.md +89 -0
  207. package/recipes/index.md +13 -0
  208. package/recipes/list-detail.md +55 -0
  209. package/recipes/primitive-to-recipe-matrix.md +83 -0
  210. package/recipes/saas-settings.md +52 -0
  211. package/scripts/agent-native/a2a-projection.mjs +248 -0
  212. package/scripts/agent-native/agui-projection.mjs +178 -0
  213. package/scripts/agent-native/canonical-json.mjs +109 -0
  214. package/scripts/agent-native/cli-adapter.mjs +68 -0
  215. package/scripts/agent-native/events.mjs +113 -0
  216. package/scripts/agent-native/execution.mjs +227 -0
  217. package/scripts/agent-native/fixture.mjs +159 -0
  218. package/scripts/agent-native/identity.mjs +184 -0
  219. package/scripts/agent-native/immutable-store.mjs +102 -0
  220. package/scripts/agent-native/knowledge.mjs +168 -0
  221. package/scripts/agent-native/learning-records.mjs +244 -0
  222. package/scripts/agent-native/learning.mjs +247 -0
  223. package/scripts/agent-native/mcp-adapter.mjs +173 -0
  224. package/scripts/agent-native/queries.mjs +173 -0
  225. package/scripts/agent-native/registry.mjs +154 -0
  226. package/scripts/agent-native/retrieval.mjs +171 -0
  227. package/scripts/agent-native/self-description.mjs +160 -0
  228. package/scripts/artifact-metadata.mjs +20 -0
  229. package/scripts/audit-evidence-freshness.mjs +308 -0
  230. package/scripts/baseline-contract.mjs +189 -0
  231. package/scripts/baseline-schema-parity.mjs +40 -0
  232. package/scripts/build-reference-artifacts.mjs +127 -0
  233. package/scripts/calibration-raw-contract.mjs +172 -0
  234. package/scripts/capture-session-contract.mjs +187 -0
  235. package/scripts/component-state-artifact-fixture.mjs +44 -0
  236. package/scripts/component-state-contract.mjs +99 -0
  237. package/scripts/component-state-semantics.mjs +128 -0
  238. package/scripts/component-state-workflow-contract.mjs +67 -0
  239. package/scripts/component-state-workflow-negative-cases.mjs +64 -0
  240. package/scripts/consumer-conformance-contract.mjs +198 -0
  241. package/scripts/consumer-evidence-governance-contract.mjs +210 -0
  242. package/scripts/consumer-reference-case-runner.mjs +93 -0
  243. package/scripts/consumer-reference-schema.mjs +155 -0
  244. package/scripts/create-component-state-session.mjs +100 -0
  245. package/scripts/create-page-evidence-session.mjs +139 -0
  246. package/scripts/domain-document-boundaries.mjs +40 -0
  247. package/scripts/domain-validation-checks.mjs +141 -0
  248. package/scripts/evidence-artifact-contract.mjs +191 -0
  249. package/scripts/finalize-component-state-evidence.mjs +165 -0
  250. package/scripts/finalize-page-evidence.mjs +197 -0
  251. package/scripts/generate-consumer-reference-evidence.mjs +154 -0
  252. package/scripts/generate-patterns.mjs +218 -0
  253. package/scripts/governance-matrix-contract.mjs +73 -0
  254. package/scripts/governance-matrix-negative-cases.mjs +114 -0
  255. package/scripts/governance-policy-contract.mjs +49 -0
  256. package/scripts/governance-test-fixture.mjs +321 -0
  257. package/scripts/governance-workflow-negative-cases.mjs +241 -0
  258. package/scripts/governed-profile-registry.mjs +125 -0
  259. package/scripts/json-schema-formats.mjs +31 -0
  260. package/scripts/markdown-structure.mjs +45 -0
  261. package/scripts/page-artifact-metadata.mjs +124 -0
  262. package/scripts/page-evidence-contract.mjs +297 -0
  263. package/scripts/page-evidence-fixture.mjs +271 -0
  264. package/scripts/pattern-data.mjs +325 -0
  265. package/scripts/profile-record-contract.mjs +140 -0
  266. package/scripts/promotion-attestation-contract.mjs +91 -0
  267. package/scripts/promotion-boundary-test-contract.mjs +92 -0
  268. package/scripts/promotion-fixture-inventory.mjs +109 -0
  269. package/scripts/promotion-governance-contract.mjs +28 -0
  270. package/scripts/reference-artifact-path-contract.mjs +28 -0
  271. package/scripts/reference-profile-contract.mjs +114 -0
  272. package/scripts/reference-token-contract.mjs +156 -0
  273. package/scripts/run-consumer-page-evidence-ci.mjs +170 -0
  274. package/scripts/sg-mcp.mjs +16 -0
  275. package/scripts/sg.mjs +27 -0
  276. package/scripts/strict-json.mjs +72 -0
  277. package/scripts/summarize-sentinel-calibration.mjs +98 -0
  278. package/scripts/test-agent-adapter-conformance.mjs +250 -0
  279. package/scripts/test-agent-conformance-receipt.mjs +106 -0
  280. package/scripts/test-agent-events.mjs +81 -0
  281. package/scripts/test-agent-execution-effects.mjs +114 -0
  282. package/scripts/test-agent-execution-fixtures.mjs +140 -0
  283. package/scripts/test-agent-execution-kernel.mjs +39 -0
  284. package/scripts/test-agent-execution-learning.mjs +130 -0
  285. package/scripts/test-agent-execution-lifecycle.mjs +143 -0
  286. package/scripts/test-agent-execution-safety.mjs +158 -0
  287. package/scripts/test-agent-execution-views.mjs +117 -0
  288. package/scripts/test-agent-identity-integrity-cases.mjs +160 -0
  289. package/scripts/test-agent-knowledge-kernel.mjs +183 -0
  290. package/scripts/test-agent-learning.mjs +246 -0
  291. package/scripts/test-agent-mcp.mjs +246 -0
  292. package/scripts/test-agent-native-schemas.mjs +215 -0
  293. package/scripts/test-agent-projections.mjs +249 -0
  294. package/scripts/test-agent-registry-mcp-integrity.mjs +215 -0
  295. package/scripts/test-agent-registry-mutations.mjs +110 -0
  296. package/scripts/test-audit-evidence-freshness.mjs +177 -0
  297. package/scripts/test-component-state-sentinel.mjs +35 -0
  298. package/scripts/test-component-state-source-contract.mjs +83 -0
  299. package/scripts/test-consumer-conformance-sentinel.mjs +165 -0
  300. package/scripts/test-consumer-reference-sentinel.mjs +31 -0
  301. package/scripts/test-generate-consumer-reference-evidence.mjs +124 -0
  302. package/scripts/test-json-cli-output.mjs +151 -0
  303. package/scripts/test-json-schema-formats.mjs +40 -0
  304. package/scripts/test-reference-adapters.mjs +199 -0
  305. package/scripts/test-renderer-purity.mjs +34 -0
  306. package/scripts/test-sg-cli.mjs +129 -0
  307. package/scripts/test-summarize-sentinel-calibration.mjs +226 -0
  308. package/scripts/test-validate-baseline-manifest.mjs +234 -0
  309. package/scripts/test-validate-component-state-artifacts.mjs +243 -0
  310. package/scripts/test-validate-component-state.mjs +106 -0
  311. package/scripts/test-validate-consumer-conformance.mjs +427 -0
  312. package/scripts/test-validate-consumer-reference-cli.mjs +69 -0
  313. package/scripts/test-validate-consumer-reference.mjs +263 -0
  314. package/scripts/test-validate-domains.mjs +357 -0
  315. package/scripts/test-validate-governance.mjs +292 -0
  316. package/scripts/test-validate-ia.mjs +262 -0
  317. package/scripts/test-validate-okf.mjs +73 -0
  318. package/scripts/test-validate-page-evidence.mjs +302 -0
  319. package/scripts/test-validate-patterns.mjs +157 -0
  320. package/scripts/test-validate-promotion-rfc.mjs +250 -0
  321. package/scripts/test-validate-reference-profiles.mjs +170 -0
  322. package/scripts/test-validate-unity-org-wiki.mjs +57 -0
  323. package/scripts/test-validate-unity-source-contracts.mjs +67 -0
  324. package/scripts/test-validate-vocabulary.mjs +174 -0
  325. package/scripts/test-validate-webpage-workflow.mjs +293 -0
  326. package/scripts/validate-baseline-manifest.mjs +44 -0
  327. package/scripts/validate-catalog.mjs +65 -0
  328. package/scripts/validate-component-state.mjs +141 -0
  329. package/scripts/validate-consumer-conformance.mjs +477 -0
  330. package/scripts/validate-consumer-reference.mjs +288 -0
  331. package/scripts/validate-domains.mjs +237 -0
  332. package/scripts/validate-governance.mjs +248 -0
  333. package/scripts/validate-ia.mjs +136 -0
  334. package/scripts/validate-links.mjs +66 -0
  335. package/scripts/validate-okf.mjs +104 -0
  336. package/scripts/validate-page-evidence.mjs +191 -0
  337. package/scripts/validate-patterns.mjs +246 -0
  338. package/scripts/validate-promotion-rfc.mjs +224 -0
  339. package/scripts/validate-reference-artifacts.mjs +125 -0
  340. package/scripts/validate-renderer-purity.mjs +56 -0
  341. package/scripts/validate-unity-org-wiki.mjs +146 -0
  342. package/scripts/validate-unity-source-contracts.mjs +107 -0
  343. package/scripts/validate-vocabulary.mjs +115 -0
  344. package/scripts/validate-webpage-workflow.mjs +254 -0
  345. package/scripts/visual-expectation-contract.mjs +20 -0
  346. package/scripts/workflow-action-contract.mjs +163 -0
@@ -0,0 +1,109 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ /**
4
+ * Errors from the identity kernel carry a stable machine-readable code. The
5
+ * callers use these errors at protocol boundaries, so do not rely on the
6
+ * wording of `message` for branching.
7
+ */
8
+ export class CanonicalJsonError extends TypeError {
9
+ constructor(code, message, path = "") {
10
+ super(message);
11
+ this.name = "CanonicalJsonError";
12
+ this.code = code;
13
+ if (path) this.path = path;
14
+ }
15
+ }
16
+
17
+ function fail(code, message, path) {
18
+ throw new CanonicalJsonError(code, message, path);
19
+ }
20
+
21
+ function isPlainObject(value) {
22
+ if (value === null || typeof value !== "object") return false;
23
+ const prototype = Object.getPrototypeOf(value);
24
+ return prototype === Object.prototype || prototype === null;
25
+ }
26
+
27
+ function encode(value, path, stack) {
28
+ if (value === null) return "null";
29
+ switch (typeof value) {
30
+ case "string": return JSON.stringify(value);
31
+ case "boolean": return value ? "true" : "false";
32
+ case "number":
33
+ if (!Number.isFinite(value)) fail("canonical_number_invalid", "numbers must be finite", path);
34
+ return Object.is(value, -0) ? "0" : JSON.stringify(value);
35
+ case "bigint": fail("canonical_type_unsupported", "bigint is not JSON data", path);
36
+ case "undefined": fail("canonical_value_undefined", "undefined is not JSON data", path);
37
+ case "function": fail("canonical_type_unsupported", "functions are not JSON data", path);
38
+ case "symbol": fail("canonical_type_unsupported", "symbols are not JSON data", path);
39
+ default: break;
40
+ }
41
+
42
+ if (stack.has(value)) fail("canonical_cycle", "cyclic values cannot be canonicalized", path);
43
+ stack.add(value);
44
+ let result;
45
+ if (Array.isArray(value)) {
46
+ for (let index = 0; index < value.length; index += 1) {
47
+ if (!Object.hasOwn(value, index)) fail("canonical_array_hole", "sparse arrays are not canonical JSON", `${path}/${index}`);
48
+ }
49
+ for (const key of Object.keys(value)) {
50
+ if (!/^(0|[1-9][0-9]*)$/.test(key) || Number(key) >= value.length) fail("canonical_array_property", "arrays may contain only indexed JSON values", `${path}/${key}`);
51
+ }
52
+ result = `[${value.map((item, index) => encode(item, `${path}/${index}`, stack)).join(",")}]`;
53
+ } else if (isPlainObject(value)) {
54
+ const keys = Reflect.ownKeys(value);
55
+ if (keys.some((key) => typeof key !== "string")) fail("canonical_symbol_key", "object keys must be strings", path);
56
+ const properties = Object.getOwnPropertyDescriptors(value);
57
+ const parts = keys.sort().map((key) => {
58
+ const descriptor = properties[key];
59
+ if (!descriptor || !Object.hasOwn(descriptor, "value")) fail("canonical_accessor", `accessor property ${key} is not canonical data`, `${path}/${key}`);
60
+ return `${JSON.stringify(key)}:${encode(descriptor.value, `${path}/${key}`, stack)}`;
61
+ });
62
+ result = `{${parts.join(",")}}`;
63
+ } else {
64
+ fail("canonical_type_unsupported", `unsupported value type ${Object.prototype.toString.call(value)}`, path);
65
+ }
66
+ stack.delete(value);
67
+ return result;
68
+ }
69
+
70
+ /** Return recursively key-sorted, whitespace-free UTF-8 JSON text. */
71
+ export function canonicalize(value) {
72
+ return encode(value, "", new WeakSet());
73
+ }
74
+
75
+ export const canonicalJson = canonicalize;
76
+ export const stringifyCanonical = canonicalize;
77
+
78
+ /** Return the SHA-256 digest of canonical JSON bytes, with an explicit suite. */
79
+ export function hashCanonical(value) {
80
+ const bytes = canonicalize(value);
81
+ return `sha256:${createHash("sha256").update(Buffer.from(bytes, "utf8")).digest("hex")}`;
82
+ }
83
+
84
+ /** Hash already-canonical UTF-8 JSON bytes when a caller has the bytes. */
85
+ export function hashCanonicalBytes(bytes) {
86
+ if (typeof bytes !== "string" && !(bytes instanceof Uint8Array)) throw new CanonicalJsonError("canonical_bytes_required", "canonical bytes must be text or Uint8Array");
87
+ return `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
88
+ }
89
+
90
+ export const sha256Canonical = hashCanonical;
91
+ export const digestCanonical = hashCanonical;
92
+
93
+ /** Deep-freeze canonical records before they cross an append-only boundary. */
94
+ export function deepFreeze(value, seen = new WeakSet()) {
95
+ if (value === null || typeof value !== "object" || seen.has(value)) return value;
96
+ seen.add(value);
97
+ for (const key of Reflect.ownKeys(value)) deepFreeze(value[key], seen);
98
+ return Object.freeze(value);
99
+ }
100
+
101
+ export function cloneAndFreeze(value) {
102
+ let clone;
103
+ try {
104
+ clone = structuredClone(value);
105
+ } catch (error) {
106
+ throw new CanonicalJsonError("canonical_clone_failed", error instanceof Error ? error.message : String(error));
107
+ }
108
+ return deepFreeze(clone);
109
+ }
@@ -0,0 +1,68 @@
1
+ import { deepFreeze } from "./canonical-json.mjs";
2
+ import { agentNativeRegistry } from "./registry.mjs";
3
+
4
+ const COMMANDS = new Set(["claims", "context", "discover", "ops", "resolve"]);
5
+ const TARGET_COMMANDS = new Set(["claims", "context", "resolve"]);
6
+
7
+ function issue(code, message, recordPath = "") {
8
+ return recordPath ? { code, message, path: recordPath } : { code, message };
9
+ }
10
+
11
+ function failed(operation, failure) {
12
+ return deepFreeze({ failures: [failure], ok: false, operation });
13
+ }
14
+
15
+ export function parseCliArguments(args) {
16
+ if (!Array.isArray(args)) return failed(null, issue("argument_list_invalid", "CLI arguments must be an array"));
17
+ let command;
18
+ let format = "json";
19
+ const operands = [];
20
+ for (let index = 0; index < args.length; index += 1) {
21
+ const argument = args[index];
22
+ if (argument === "--format") {
23
+ const value = args[index + 1];
24
+ if (value === undefined || value.startsWith("--")) {
25
+ return failed(command ?? null, issue("argument_value_required", "--format requires a value", "--format"));
26
+ }
27
+ if (value !== "json") return failed(command ?? null, issue("format_unsupported", `unsupported format ${value}`, "--format"));
28
+ format = value;
29
+ index += 1;
30
+ continue;
31
+ }
32
+ if (typeof argument !== "string" || argument.startsWith("--")) {
33
+ return failed(command ?? null, issue("argument_unknown", `unknown argument ${String(argument)}`, String(argument)));
34
+ }
35
+ if (command === undefined) command = argument;
36
+ else operands.push(argument);
37
+ }
38
+ if (command === undefined) return failed(null, issue("argument_value_required", "a command is required", "command"));
39
+ if (!COMMANDS.has(command)) return failed(command, issue("command_unknown", `unknown command ${command}`, "command"));
40
+ const required = TARGET_COMMANDS.has(command);
41
+ if (required && operands.length === 0) {
42
+ return failed(command, issue("argument_value_required", `${command} requires a StableRef or VersionID`, "reference"));
43
+ }
44
+ if ((!required && operands.length > 0) || operands.length > 1) {
45
+ return failed(command, issue("argument_unknown", `unexpected positional argument ${operands[required ? 1 : 0]}`, "argument"));
46
+ }
47
+ return deepFreeze({ command, format, input: required ? { reference: operands[0] } : {}, ok: true });
48
+ }
49
+
50
+ export function executeCli(args, registry = agentNativeRegistry) {
51
+ const parsed = parseCliArguments(args);
52
+ if (!parsed.ok) return parsed;
53
+ if (!registry || typeof registry.invoke !== "function") {
54
+ return failed(parsed.command, issue("registry_invalid", "CLI registry must expose invoke"));
55
+ }
56
+ return registry.invoke(parsed.command, parsed.input);
57
+ }
58
+
59
+ export function serializeCliReport(report) {
60
+ return `${JSON.stringify(report, null, 2)}\n`;
61
+ }
62
+
63
+ export function runCli(args, registry = agentNativeRegistry) {
64
+ const report = executeCli(args, registry);
65
+ return deepFreeze({ exitCode: report.ok ? 0 : 1, output: serializeCliReport(report), report });
66
+ }
67
+
68
+ export const invokeCli = executeCli;
@@ -0,0 +1,113 @@
1
+ import { cloneAndFreeze, canonicalize, hashCanonical } from "./canonical-json.mjs";
2
+
3
+ function sourceObject(value, name) {
4
+ if (Array.isArray(value)) return { events: value };
5
+ if (!value || typeof value !== "object") throw new TypeError(`${name} expects an object`);
6
+ return value;
7
+ }
8
+
9
+ function pick(value, ...keys) {
10
+ if (!value || typeof value !== "object") return undefined;
11
+ for (const key of keys) if (Object.hasOwn(value, key)) return value[key];
12
+ return undefined;
13
+ }
14
+
15
+ function eventId(event) {
16
+ return pick(event, "event_id", "eventId", "id", "stable_ref", "stableRef");
17
+ }
18
+
19
+ function parentIds(event) {
20
+ const parents = pick(event, "parents", "parent_ids", "parentIds");
21
+ if (parents === undefined || parents === null) return [];
22
+ if (!Array.isArray(parents)) throw new TypeError("event parents must be an array");
23
+ return [...new Set(parents.map((parent) => {
24
+ if (typeof parent !== "string" || parent.length === 0) throw new TypeError("event parent IDs must be non-empty strings");
25
+ return parent;
26
+ }))].sort();
27
+ }
28
+
29
+ function canonicalFreeze(value) {
30
+ return cloneAndFreeze(JSON.parse(canonicalize(value)));
31
+ }
32
+
33
+ function normalizeEvent(input) {
34
+ if (!input || typeof input !== "object" || Array.isArray(input)) throw new TypeError("event must be an object");
35
+ const copy = structuredClone(input);
36
+ const id = eventId(copy);
37
+ if (id !== undefined && (typeof id !== "string" || id.length === 0)) throw new TypeError("event ID must be a non-empty string");
38
+ const stableRef = pick(copy, "stable_ref", "stableRef");
39
+ const parents = parentIds(copy);
40
+ delete copy.eventId;
41
+ delete copy.event_id;
42
+ delete copy.parentIds;
43
+ delete copy.parent_ids;
44
+ delete copy.parents;
45
+ delete copy.id;
46
+ delete copy.stableRef;
47
+ delete copy.stable_ref;
48
+ const body = { ...copy, parents };
49
+ if (stableRef !== undefined) body.stable_ref = stableRef;
50
+ const stableId = typeof id === "string" && id.length > 0 ? id : `sg:event/${hashCanonical(body).slice("sha256:".length)}`;
51
+ return { event_id: stableId, parents, ...body };
52
+ }
53
+
54
+ function normalizedEvents(value) {
55
+ const source = sourceObject(value, "event collection");
56
+ const events = pick(source, "events", "items", "entries");
57
+ if (!Array.isArray(events)) throw new TypeError("events must be an array");
58
+ const result = [];
59
+ const byId = new Map();
60
+ for (const item of events) {
61
+ const normalized = normalizeEvent(item);
62
+ const id = normalized.event_id;
63
+ const previous = byId.get(id);
64
+ if (previous) {
65
+ if (canonicalize(previous) !== canonicalize(normalized)) throw new TypeError(`event ${id} is immutable`);
66
+ continue;
67
+ }
68
+ byId.set(id, normalized);
69
+ result.push(normalized);
70
+ }
71
+ const ids = new Set(result.map((item) => item.event_id));
72
+ const visiting = new Set();
73
+ const visited = new Set();
74
+ const eventById = new Map(result.map((item) => [item.event_id, item]));
75
+ const visit = (id) => {
76
+ if (visiting.has(id)) throw new TypeError(`event cycle includes ${id}`);
77
+ if (visited.has(id)) return;
78
+ visiting.add(id);
79
+ for (const parent of eventById.get(id).parents) if (eventById.has(parent)) visit(parent);
80
+ visiting.delete(id);
81
+ visited.add(id);
82
+ };
83
+ for (const id of ids) visit(id);
84
+ return result;
85
+ }
86
+
87
+ /**
88
+ * Append one event to an immutable causal event collection. Existing IDs are
89
+ * idempotent only when their canonical bytes are identical; a changed payload
90
+ * is rejected rather than silently rewriting history.
91
+ */
92
+ export function appendEvent(input) {
93
+ const source = sourceObject(input, "appendEvent");
94
+ const existing = normalizedEvents(source);
95
+ const appended = normalizeEvent(pick(source, "event") ?? source);
96
+ const existingById = new Map(existing.map((item) => [item.event_id, item]));
97
+ const previous = existingById.get(appended.event_id);
98
+ if (previous && canonicalize(previous) !== canonicalize(appended)) throw new TypeError(`event ${appended.event_id} is immutable`);
99
+ if (previous) return canonicalFreeze(existing);
100
+ return canonicalFreeze(normalizedEvents({ events: [...existing, appended] }));
101
+ }
102
+
103
+ export const appendCausalEvent = appendEvent;
104
+
105
+ /** Return the deterministic leaf IDs of an append-only causal DAG. */
106
+ export function eventHeads(input) {
107
+ const events = normalizedEvents(input);
108
+ const ids = new Set(events.map((item) => item.event_id));
109
+ const referenced = new Set(events.flatMap((item) => item.parents.filter((parent) => ids.has(parent))));
110
+ return canonicalFreeze([...ids].filter((id) => !referenced.has(id)).sort());
111
+ }
112
+
113
+ export const getEventHeads = eventHeads;
@@ -0,0 +1,227 @@
1
+ import { deepFreeze, hashCanonical } from "./canonical-json.mjs";
2
+ import { createVersionId } from "./identity.mjs";
3
+
4
+ const CONTROL = new Set(["schema_version", "record_kind", "version_id", "versionId"]);
5
+ const EFFECTS = new Set(["NONE", "LOCAL", "EXTERNAL"]);
6
+
7
+ function sourceObject(input, name) {
8
+ if (!input || typeof input !== "object" || Array.isArray(input)) throw new TypeError(`${name} expects an object parameter`);
9
+ return input;
10
+ }
11
+
12
+ function value(input, ...keys) {
13
+ if (input === null || input === undefined) return undefined;
14
+ for (const key of keys) if (Object.hasOwn(input, key) && input[key] !== undefined) return input[key];
15
+ return undefined;
16
+ }
17
+
18
+ function copy(input) {
19
+ return input === undefined ? undefined : structuredClone(input);
20
+ }
21
+
22
+ function refOf(input, prefixes, name) {
23
+ const ref = value(input, "stable_ref", "stableRef", "id", ...prefixes);
24
+ if (typeof ref !== "string" || ref.length === 0) throw new TypeError(`${name} stable reference is required`);
25
+ return ref.includes("@sha256:") ? ref.slice(0, ref.indexOf("@sha256:")) : ref;
26
+ }
27
+
28
+ function versionId(stableRef, payload) {
29
+ return createVersionId({ stableRef, payload });
30
+ }
31
+
32
+ function record(stableRef, recordKind, payload) {
33
+ const body = { schema_version: "1.0", record_kind: recordKind, stable_ref: stableRef, ...payload };
34
+ return deepFreeze({ ...body, version_id: versionId(stableRef, body) });
35
+ }
36
+
37
+ function normalizedFields(input, omit = []) {
38
+ const ignored = new Set([...CONTROL, "stable_ref", "stableRef", "id", ...omit]);
39
+ return Object.fromEntries(Object.entries(input).filter(([key, item]) => !ignored.has(key) && item !== undefined).map(([key, item]) => [key, copy(item)]));
40
+ }
41
+
42
+ function upper(input, fallback) {
43
+ return typeof input === "string" ? input.toUpperCase() : fallback;
44
+ }
45
+
46
+ function operationNames(operation) {
47
+ if (!operation || typeof operation !== "object") return [];
48
+ return [value(operation, "operation", "name"), value(operation, "stable_ref", "stableRef")].filter((item) => typeof item === "string");
49
+ }
50
+
51
+ function wildcardMatch(pattern, candidate) {
52
+ if (typeof pattern !== "string" || typeof candidate !== "string") return false;
53
+ if (pattern === "*") return true;
54
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replaceAll("*", ".*");
55
+ return new RegExp(`^${escaped}$`).test(candidate);
56
+ }
57
+
58
+ /** Define a deterministic, immutable operation specification. */
59
+ export function defineOperation(input) {
60
+ const source = sourceObject(input, "defineOperation");
61
+ const stableRef = refOf(source, ["operation"], "defineOperation");
62
+ const effectClass = upper(value(source, "effect_class", "effectClass", "effect"), "NONE");
63
+ if (!EFFECTS.has(effectClass)) throw new TypeError("defineOperation.effect_class must be NONE, LOCAL, or EXTERNAL");
64
+ const operationName = value(source, "operation", "name") ?? stableRef.slice(stableRef.lastIndexOf("/") + 1);
65
+ const payload = {
66
+ ...normalizedFields(source, ["operation", "name", "effect", "effectClass", "effect_class", "idempotent", "isIdempotent", "requiredCapability", "capability", "inputSchema", "outputSchema"]),
67
+ adapters: [...new Set((value(source, "adapters", "adapter_exposure", "adapterExposure") ?? []).filter((item) => typeof item === "string"))].sort(),
68
+ effect_class: effectClass,
69
+ idempotent: value(source, "idempotent", "isIdempotent") !== false,
70
+ input_schema: copy(value(source, "input_schema", "inputSchema") ?? { type: "object" }),
71
+ name: operationName,
72
+ operation: operationName,
73
+ output_schema: copy(value(source, "output_schema", "outputSchema") ?? { type: "object" }),
74
+ required_capability: value(source, "required_capability", "requiredCapability", "capability") ?? null,
75
+ };
76
+ return record(stableRef, "operation", payload);
77
+ }
78
+
79
+ function grantFor(input) {
80
+ return value(input, "grant", "capability");
81
+ }
82
+
83
+ function connectorReceiptId(input) {
84
+ const receipt = value(input, "connector_receipt", "connectorReceipt", "receiptId", "receipt_id");
85
+ return typeof receipt === "string" && receipt.trim().length > 0 ? receipt : null;
86
+ }
87
+
88
+ /** Evaluate capability, subject, resource, expiry, and call-limit policy. */
89
+ export function authorizeOperation(input) {
90
+ const source = sourceObject(input, "authorizeOperation");
91
+ const operation = value(source, "operation", "operationSpec");
92
+ const grant = grantFor(source);
93
+ const subject = value(source, "subject", "principal");
94
+ const resource = value(source, "resource", "resourceRef", "stable_ref", "stableRef");
95
+ const now = value(source, "now", "evaluated_at", "evaluatedAt") ?? "1970-01-01T00:00:00.000Z";
96
+ const names = operationNames(operation);
97
+ const required = value(operation ?? {}, "required_capability", "requiredCapability", "capability");
98
+ const grantedCapability = value(grant ?? {}, "capability", "name");
99
+ const operationGrant = value(grant ?? {}, "operations", "operation");
100
+ const operations = Array.isArray(operationGrant) ? operationGrant : operationGrant ? [operationGrant] : [];
101
+ const scopeGrant = value(grant ?? {}, "resource_scope", "resourceScope", "resources");
102
+ const scopes = Array.isArray(scopeGrant) ? scopeGrant : scopeGrant ? [scopeGrant] : [];
103
+ const expiresAt = value(grant ?? {}, "expires_at", "expiresAt", "expiry");
104
+ const used = Number(value(grant ?? {}, "used", "used_calls", "usedCalls", "calls_used", "callsUsed") ?? 0);
105
+ const limits = value(grant ?? {}, "limits") ?? {};
106
+ const maxCalls = Number(value(grant ?? {}, "max_calls", "maxCalls") ?? value(limits, "maxCalls", "calls") ?? Number.POSITIVE_INFINITY);
107
+ const failures = [];
108
+ if (!grant || typeof grant !== "object") failures.push("capability_missing");
109
+ if (typeof subject !== "string" || subject !== value(grant ?? {}, "subject", "principal")) failures.push("subject_denied");
110
+ if (required && grantedCapability !== required) failures.push("capability_denied");
111
+ if (operations.length === 0 || !names.some((name) => operations.includes(name))) failures.push("operation_denied");
112
+ if (scopes.length > 0 && !scopes.some((scope) => wildcardMatch(scope, resource))) failures.push("resource_denied");
113
+ if (expiresAt && String(now) >= String(expiresAt)) failures.push("grant_expired");
114
+ if (Number.isFinite(maxCalls) && used >= maxCalls) failures.push("grant_limit_exceeded");
115
+ const allowed = failures.length === 0;
116
+ const decision = {
117
+ allowed,
118
+ capability: grantedCapability ?? null,
119
+ evaluated_at: String(now),
120
+ operation: names[0] ?? null,
121
+ reason: allowed ? "allowed" : failures[0],
122
+ resource: resource ?? null,
123
+ subject: subject ?? null,
124
+ };
125
+ return deepFreeze({ allowed, decision, policy_decision: decision, failures });
126
+ }
127
+
128
+ /** Re-check policy immediately before a potentially effectful attempt. */
129
+ export function authorizeEffect(input) {
130
+ const source = sourceObject(input, "authorizeEffect");
131
+ return authorizeOperation({ ...source, operation: value(source, "operation", "operationSpec") });
132
+ }
133
+
134
+ export function createTask(input) {
135
+ const source = sourceObject(input, "createTask");
136
+ const stableRef = refOf(source, ["taskId", "task_id"], "createTask");
137
+ return record(stableRef, "task", {
138
+ ...normalizedFields(source, ["taskId", "task_id", "intent", "request", "requiredResult", "required_result", "result", "state", "status"]),
139
+ intent: copy(value(source, "intent", "request") ?? {}),
140
+ required_result: copy(value(source, "required_result", "requiredResult", "result") ?? {}),
141
+ state: upper(value(source, "state", "status"), "SUBMITTED"),
142
+ task_id: stableRef,
143
+ });
144
+ }
145
+
146
+ export function startRun(input) {
147
+ const source = sourceObject(input, "startRun");
148
+ const task = value(source, "task");
149
+ const taskId = value(task ?? {}, "task_id", "taskId", "stable_ref", "stableRef") ?? value(source, "task_id", "taskId");
150
+ if (typeof taskId !== "string" || taskId.length === 0) throw new TypeError("startRun.task_id is required");
151
+ const stableRef = refOf(source, ["runId", "run_id"], "startRun");
152
+ return record(stableRef, "run", {
153
+ ...normalizedFields(source, ["runId", "run_id", "task", "taskId", "task_id", "state", "status"]),
154
+ input: copy(value(source, "input", "arguments") ?? {}),
155
+ run_id: stableRef,
156
+ state: upper(value(source, "state", "status"), "RUNNING"),
157
+ task_id: taskId,
158
+ });
159
+ }
160
+
161
+ export function recordEffectAttempt(input) {
162
+ const source = sourceObject(input, "recordEffectAttempt");
163
+ const stableRef = refOf(source, ["effectId", "effect_id", "effect"], "recordEffectAttempt");
164
+ const effectClass = upper(value(source, "effect_class", "effectClass", "class"), "EXTERNAL");
165
+ const connectorReceipt = connectorReceiptId(source);
166
+ const suppliedState = upper(value(source, "state", "status", "effect_state", "effectState"), undefined);
167
+ const state = effectClass === "EXTERNAL"
168
+ ? (connectorReceipt ? "COMMITTED" : "UNCERTAIN")
169
+ : (suppliedState ?? "PLANNED");
170
+ return record(stableRef, "effect", {
171
+ ...normalizedFields(source, ["effectId", "effect_id", "effect", "effect_class", "effectClass", "class", "connector_receipt", "connectorReceipt", "receiptId", "receipt_id", "state", "status", "effect_state", "effectState"]),
172
+ attempt: value(source, "attempt") ?? null,
173
+ connector_receipt: connectorReceipt,
174
+ effect_class: effectClass,
175
+ effect_id: stableRef,
176
+ idempotency_key: value(source, "idempotency_key", "idempotencyKey") ?? null,
177
+ run_id: value(source, "run_id", "runId") ?? value(value(source, "run"), "run_id", "runId") ?? null,
178
+ state,
179
+ task_id: value(source, "task_id", "taskId") ?? value(value(source, "task"), "task_id", "taskId") ?? null,
180
+ });
181
+ }
182
+
183
+ export function reconcileEffect(input) {
184
+ const source = sourceObject(input, "reconcileEffect");
185
+ const effect = source.effect && typeof source.effect === "object" ? source.effect : source;
186
+ const observations = [...(Array.isArray(value(source, "observations")) ? value(source, "observations") : []), ...(value(source, "observation") ? [value(source, "observation")] : [])];
187
+ const statuses = observations.map((item) => upper(value(item ?? {}, "status", "state", "effect_state", "effectState"), "UNKNOWN"));
188
+ const positiveStatuses = new Set(["COMMITTED", "SUCCEEDED", "SUCCESS"]);
189
+ const positive = statuses.some((status) => positiveStatuses.has(status));
190
+ const negative = statuses.includes("ABSENT") || statuses.includes("FAILED") || statuses.includes("NOT_FOUND");
191
+ const strategy = upper(value(source, "strategy"), "RECONCILE");
192
+ let state = upper(value(effect, "state", "status", "effect_state", "effectState"), "UNCERTAIN");
193
+ const receiptObservation = observations.find((item) => positiveStatuses.has(upper(value(item ?? {}, "status", "state", "effect_state", "effectState"), "UNKNOWN")) && connectorReceiptId(item));
194
+ const connectorReceipt = connectorReceiptId(receiptObservation) ?? connectorReceiptId(effect);
195
+ if (positive && negative) state = "UNCERTAIN";
196
+ else if (positive) state = connectorReceipt ? "COMMITTED" : "UNCERTAIN";
197
+ else if (negative && strategy === "COMPENSATE") state = "COMPENSATED";
198
+ else if (negative) state = "FAILED";
199
+ else if (state === "COMMITTED" && !connectorReceipt) state = "UNCERTAIN";
200
+ const stableRef = refOf(effect, ["effect_id", "effectId", "effect"], "reconcileEffect");
201
+ return record(stableRef, "effect", { ...normalizedFields(effect, ["version_id", "versionId", "state", "status", "effect_state", "effectState", "connector_receipt", "connectorReceipt"]), connector_receipt: connectorReceipt, state });
202
+ }
203
+
204
+ export function createReceipt(input) {
205
+ const source = sourceObject(input, "createReceipt");
206
+ const operation = value(source, "operation", "operationSpec");
207
+ const task = value(source, "task");
208
+ const run = value(source, "run");
209
+ const effects = value(source, "effects") ?? (value(source, "effect") ? [value(source, "effect")] : []);
210
+ const inputValue = value(source, "input", "normalized_input", "normalizedInput") ?? null;
211
+ const outputValue = value(source, "output", "normalized_output", "normalizedOutput") ?? null;
212
+ const taskId = value(source, "task_id", "taskId") ?? value(task ?? {}, "task_id", "taskId", "stable_ref", "stableRef") ?? null;
213
+ const runId = value(source, "run_id", "runId") ?? value(run ?? {}, "run_id", "runId", "stable_ref", "stableRef") ?? null;
214
+ const effectIds = effects.map((effect) => value(effect ?? {}, "effect_id", "effectId", "stable_ref", "stableRef", "id")).filter((id) => typeof id === "string");
215
+ const base = { input_digest: hashCanonical(inputValue), operation: value(operation ?? {}, "operation", "name", "stable_ref", "stableRef") ?? null, output_digest: hashCanonical(outputValue), run_id: runId, task_id: taskId, effect_ids: [...new Set(effectIds)].sort() };
216
+ const stableRef = value(source, "receipt_id", "receiptId", "stable_ref", "stableRef") ?? `sg:receipt/${hashCanonical(base).slice(7, 23)}`;
217
+ return record(stableRef, "invocation_receipt", {
218
+ ...base,
219
+ causal_parents: [...new Set((value(source, "causal_parents", "causalParents", "parents") ?? []).filter((item) => typeof item === "string"))].sort(),
220
+ effects: copy(effects),
221
+ policy_decision: copy(value(source, "policy_decision", "policyDecision") ?? null),
222
+ });
223
+ }
224
+
225
+ export const defineOperationSpec = defineOperation;
226
+ export const authorizeCapability = authorizeOperation;
227
+ export const createInvocationReceipt = createReceipt;