@manifesto-ai/core 0.3.0 → 1.0.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 (259) hide show
  1. package/README.md +129 -499
  2. package/dist/core/apply.d.ts +16 -0
  3. package/dist/core/apply.d.ts.map +1 -0
  4. package/dist/core/apply.js +52 -0
  5. package/dist/core/apply.js.map +1 -0
  6. package/dist/core/compute.d.ts +17 -0
  7. package/dist/core/compute.d.ts.map +1 -0
  8. package/dist/core/compute.js +197 -0
  9. package/dist/core/compute.js.map +1 -0
  10. package/dist/core/compute.test.d.ts +2 -0
  11. package/dist/core/compute.test.d.ts.map +1 -0
  12. package/dist/core/compute.test.js +400 -0
  13. package/dist/core/compute.test.js.map +1 -0
  14. package/dist/core/explain.d.ts +14 -0
  15. package/dist/core/explain.d.ts.map +1 -0
  16. package/dist/core/explain.js +74 -0
  17. package/dist/core/explain.js.map +1 -0
  18. package/dist/core/index.d.ts +5 -0
  19. package/dist/core/index.d.ts.map +1 -0
  20. package/dist/core/index.js +5 -0
  21. package/dist/core/index.js.map +1 -0
  22. package/dist/core/validate.d.ts +15 -0
  23. package/dist/core/validate.d.ts.map +1 -0
  24. package/dist/core/validate.js +143 -0
  25. package/dist/core/validate.js.map +1 -0
  26. package/dist/core/validate.test.d.ts +2 -0
  27. package/dist/core/validate.test.d.ts.map +1 -0
  28. package/dist/core/validate.test.js +450 -0
  29. package/dist/core/validate.test.js.map +1 -0
  30. package/dist/errors.d.ts +30 -0
  31. package/dist/errors.d.ts.map +1 -0
  32. package/dist/errors.js +51 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/evaluator/computed.d.ts +14 -0
  35. package/dist/evaluator/computed.d.ts.map +1 -0
  36. package/dist/evaluator/computed.js +57 -0
  37. package/dist/evaluator/computed.js.map +1 -0
  38. package/dist/evaluator/context.d.ts +46 -0
  39. package/dist/evaluator/context.d.ts.map +1 -0
  40. package/dist/evaluator/context.js +35 -0
  41. package/dist/evaluator/context.js.map +1 -0
  42. package/dist/evaluator/dag.d.ts +30 -0
  43. package/dist/evaluator/dag.d.ts.map +1 -0
  44. package/dist/evaluator/dag.js +121 -0
  45. package/dist/evaluator/dag.js.map +1 -0
  46. package/dist/evaluator/expr.d.ts +11 -0
  47. package/dist/evaluator/expr.d.ts.map +1 -0
  48. package/dist/evaluator/expr.js +498 -0
  49. package/dist/evaluator/expr.js.map +1 -0
  50. package/dist/evaluator/expr.test.d.ts +2 -0
  51. package/dist/evaluator/expr.test.d.ts.map +1 -0
  52. package/dist/evaluator/expr.test.js +426 -0
  53. package/dist/evaluator/expr.test.js.map +1 -0
  54. package/dist/evaluator/flow.d.ts +35 -0
  55. package/dist/evaluator/flow.d.ts.map +1 -0
  56. package/dist/evaluator/flow.js +234 -0
  57. package/dist/evaluator/flow.js.map +1 -0
  58. package/dist/evaluator/flow.test.d.ts +2 -0
  59. package/dist/evaluator/flow.test.d.ts.map +1 -0
  60. package/dist/evaluator/flow.test.js +446 -0
  61. package/dist/evaluator/flow.test.js.map +1 -0
  62. package/dist/evaluator/index.d.ts +6 -0
  63. package/dist/evaluator/index.d.ts.map +1 -0
  64. package/dist/evaluator/index.js +6 -0
  65. package/dist/evaluator/index.js.map +1 -0
  66. package/dist/factories.d.ts +20 -0
  67. package/dist/factories.d.ts.map +1 -0
  68. package/dist/factories.js +43 -0
  69. package/dist/factories.js.map +1 -0
  70. package/dist/index.d.ts +46 -11
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +30 -45
  73. package/dist/index.js.map +1 -1
  74. package/dist/index.test.d.ts +2 -0
  75. package/dist/index.test.d.ts.map +1 -0
  76. package/dist/index.test.js +13 -0
  77. package/dist/index.test.js.map +1 -0
  78. package/dist/schema/action.d.ts +14 -0
  79. package/dist/schema/action.d.ts.map +1 -0
  80. package/dist/schema/action.js +30 -0
  81. package/dist/schema/action.js.map +1 -0
  82. package/dist/schema/common.d.ts +37 -0
  83. package/dist/schema/common.d.ts.map +1 -0
  84. package/dist/schema/common.js +20 -0
  85. package/dist/schema/common.js.map +1 -0
  86. package/dist/schema/computed.d.ts +23 -0
  87. package/dist/schema/computed.d.ts.map +1 -0
  88. package/dist/schema/computed.js +34 -0
  89. package/dist/schema/computed.js.map +1 -0
  90. package/dist/schema/domain.d.ts +46 -0
  91. package/dist/schema/domain.d.ts.map +1 -0
  92. package/dist/schema/domain.js +54 -0
  93. package/dist/schema/domain.js.map +1 -0
  94. package/dist/schema/expr.d.ts +260 -0
  95. package/dist/schema/expr.d.ts.map +1 -0
  96. package/dist/schema/expr.js +247 -0
  97. package/dist/schema/expr.js.map +1 -0
  98. package/dist/schema/field.d.ts +48 -0
  99. package/dist/schema/field.d.ts.map +1 -0
  100. package/dist/schema/field.js +31 -0
  101. package/dist/schema/field.js.map +1 -0
  102. package/dist/schema/flow.d.ts +103 -0
  103. package/dist/schema/flow.d.ts.map +1 -0
  104. package/dist/schema/flow.js +82 -0
  105. package/dist/schema/flow.js.map +1 -0
  106. package/dist/schema/index.d.ts +11 -2
  107. package/dist/schema/index.d.ts.map +1 -1
  108. package/dist/schema/index.js +22 -2
  109. package/dist/schema/index.js.map +1 -1
  110. package/dist/schema/patch.d.ts +59 -0
  111. package/dist/schema/patch.d.ts.map +1 -0
  112. package/dist/schema/patch.js +60 -0
  113. package/dist/schema/patch.js.map +1 -0
  114. package/dist/schema/result.d.ts +130 -0
  115. package/dist/schema/result.d.ts.map +1 -0
  116. package/dist/schema/result.js +90 -0
  117. package/dist/schema/result.js.map +1 -0
  118. package/dist/schema/snapshot.d.ts +151 -0
  119. package/dist/schema/snapshot.d.ts.map +1 -0
  120. package/dist/schema/snapshot.js +156 -0
  121. package/dist/schema/snapshot.js.map +1 -0
  122. package/dist/schema/trace.d.ts +87 -0
  123. package/dist/schema/trace.d.ts.map +1 -0
  124. package/dist/schema/trace.js +79 -0
  125. package/dist/schema/trace.js.map +1 -0
  126. package/dist/utils/canonical.d.ts +29 -0
  127. package/dist/utils/canonical.d.ts.map +1 -0
  128. package/dist/utils/canonical.js +56 -0
  129. package/dist/utils/canonical.js.map +1 -0
  130. package/dist/utils/canonical.test.d.ts +2 -0
  131. package/dist/utils/canonical.test.d.ts.map +1 -0
  132. package/dist/utils/canonical.test.js +153 -0
  133. package/dist/utils/canonical.test.js.map +1 -0
  134. package/dist/utils/hash.d.ts +20 -0
  135. package/dist/utils/hash.d.ts.map +1 -0
  136. package/dist/utils/hash.js +38 -0
  137. package/dist/utils/hash.js.map +1 -0
  138. package/dist/utils/hash.test.d.ts +2 -0
  139. package/dist/utils/hash.test.d.ts.map +1 -0
  140. package/dist/utils/hash.test.js +146 -0
  141. package/dist/utils/hash.test.js.map +1 -0
  142. package/dist/utils/index.d.ts +4 -0
  143. package/dist/utils/index.d.ts.map +1 -0
  144. package/dist/utils/index.js +4 -0
  145. package/dist/utils/index.js.map +1 -0
  146. package/dist/utils/path.d.ts +40 -0
  147. package/dist/utils/path.d.ts.map +1 -0
  148. package/dist/utils/path.js +132 -0
  149. package/dist/utils/path.js.map +1 -0
  150. package/dist/utils/path.test.d.ts +2 -0
  151. package/dist/utils/path.test.d.ts.map +1 -0
  152. package/dist/utils/path.test.js +191 -0
  153. package/dist/utils/path.test.js.map +1 -0
  154. package/package.json +25 -39
  155. package/LICENSE +0 -21
  156. package/dist/dag/graph.d.ts +0 -62
  157. package/dist/dag/graph.d.ts.map +0 -1
  158. package/dist/dag/graph.js +0 -244
  159. package/dist/dag/graph.js.map +0 -1
  160. package/dist/dag/index.d.ts +0 -4
  161. package/dist/dag/index.d.ts.map +0 -1
  162. package/dist/dag/index.js +0 -4
  163. package/dist/dag/index.js.map +0 -1
  164. package/dist/dag/propagation.d.ts +0 -58
  165. package/dist/dag/propagation.d.ts.map +0 -1
  166. package/dist/dag/propagation.js +0 -224
  167. package/dist/dag/propagation.js.map +0 -1
  168. package/dist/dag/topological.d.ts +0 -33
  169. package/dist/dag/topological.d.ts.map +0 -1
  170. package/dist/dag/topological.js +0 -173
  171. package/dist/dag/topological.js.map +0 -1
  172. package/dist/domain/define.d.ts +0 -82
  173. package/dist/domain/define.d.ts.map +0 -1
  174. package/dist/domain/define.js +0 -105
  175. package/dist/domain/define.js.map +0 -1
  176. package/dist/domain/index.d.ts +0 -4
  177. package/dist/domain/index.d.ts.map +0 -1
  178. package/dist/domain/index.js +0 -4
  179. package/dist/domain/index.js.map +0 -1
  180. package/dist/domain/types.d.ts +0 -203
  181. package/dist/domain/types.d.ts.map +0 -1
  182. package/dist/domain/types.js +0 -2
  183. package/dist/domain/types.js.map +0 -1
  184. package/dist/domain/validate.d.ts +0 -17
  185. package/dist/domain/validate.d.ts.map +0 -1
  186. package/dist/domain/validate.js +0 -204
  187. package/dist/domain/validate.js.map +0 -1
  188. package/dist/effect/index.d.ts +0 -4
  189. package/dist/effect/index.d.ts.map +0 -1
  190. package/dist/effect/index.js +0 -4
  191. package/dist/effect/index.js.map +0 -1
  192. package/dist/effect/result.d.ts +0 -100
  193. package/dist/effect/result.d.ts.map +0 -1
  194. package/dist/effect/result.js +0 -163
  195. package/dist/effect/result.js.map +0 -1
  196. package/dist/effect/runner.d.ts +0 -98
  197. package/dist/effect/runner.d.ts.map +0 -1
  198. package/dist/effect/runner.js +0 -321
  199. package/dist/effect/runner.js.map +0 -1
  200. package/dist/effect/types.d.ts +0 -169
  201. package/dist/effect/types.d.ts.map +0 -1
  202. package/dist/effect/types.js +0 -28
  203. package/dist/effect/types.js.map +0 -1
  204. package/dist/expression/analyzer.d.ts +0 -42
  205. package/dist/expression/analyzer.d.ts.map +0 -1
  206. package/dist/expression/analyzer.js +0 -166
  207. package/dist/expression/analyzer.js.map +0 -1
  208. package/dist/expression/evaluator.d.ts +0 -16
  209. package/dist/expression/evaluator.d.ts.map +0 -1
  210. package/dist/expression/evaluator.js +0 -382
  211. package/dist/expression/evaluator.js.map +0 -1
  212. package/dist/expression/index.d.ts +0 -5
  213. package/dist/expression/index.d.ts.map +0 -1
  214. package/dist/expression/index.js +0 -5
  215. package/dist/expression/index.js.map +0 -1
  216. package/dist/expression/parser.d.ts +0 -37
  217. package/dist/expression/parser.d.ts.map +0 -1
  218. package/dist/expression/parser.js +0 -201
  219. package/dist/expression/parser.js.map +0 -1
  220. package/dist/expression/types.d.ts +0 -123
  221. package/dist/expression/types.d.ts.map +0 -1
  222. package/dist/expression/types.js +0 -10
  223. package/dist/expression/types.js.map +0 -1
  224. package/dist/policy/field-policy.d.ts +0 -63
  225. package/dist/policy/field-policy.d.ts.map +0 -1
  226. package/dist/policy/field-policy.js +0 -138
  227. package/dist/policy/field-policy.js.map +0 -1
  228. package/dist/policy/index.d.ts +0 -3
  229. package/dist/policy/index.d.ts.map +0 -1
  230. package/dist/policy/index.js +0 -3
  231. package/dist/policy/index.js.map +0 -1
  232. package/dist/policy/precondition.d.ts +0 -58
  233. package/dist/policy/precondition.d.ts.map +0 -1
  234. package/dist/policy/precondition.js +0 -115
  235. package/dist/policy/precondition.js.map +0 -1
  236. package/dist/runtime/index.d.ts +0 -4
  237. package/dist/runtime/index.d.ts.map +0 -1
  238. package/dist/runtime/index.js +0 -4
  239. package/dist/runtime/index.js.map +0 -1
  240. package/dist/runtime/runtime.d.ts +0 -94
  241. package/dist/runtime/runtime.d.ts.map +0 -1
  242. package/dist/runtime/runtime.js +0 -294
  243. package/dist/runtime/runtime.js.map +0 -1
  244. package/dist/runtime/snapshot.d.ts +0 -39
  245. package/dist/runtime/snapshot.d.ts.map +0 -1
  246. package/dist/runtime/snapshot.js +0 -264
  247. package/dist/runtime/snapshot.js.map +0 -1
  248. package/dist/runtime/subscription.d.ts +0 -82
  249. package/dist/runtime/subscription.d.ts.map +0 -1
  250. package/dist/runtime/subscription.js +0 -222
  251. package/dist/runtime/subscription.js.map +0 -1
  252. package/dist/schema/integration.d.ts +0 -89
  253. package/dist/schema/integration.d.ts.map +0 -1
  254. package/dist/schema/integration.js +0 -171
  255. package/dist/schema/integration.js.map +0 -1
  256. package/dist/schema/validation.d.ts +0 -51
  257. package/dist/schema/validation.d.ts.map +0 -1
  258. package/dist/schema/validation.js +0 -212
  259. package/dist/schema/validation.js.map +0 -1
@@ -0,0 +1,153 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { sortKeys, toCanonical, fromCanonical, canonicalEqual } from "./canonical.js";
3
+ describe("Canonical Utilities", () => {
4
+ describe("sortKeys", () => {
5
+ it("should sort object keys alphabetically", () => {
6
+ const obj = { c: 1, a: 2, b: 3 };
7
+ const result = sortKeys(obj);
8
+ expect(Object.keys(result)).toEqual(["a", "b", "c"]);
9
+ });
10
+ it("should sort nested object keys", () => {
11
+ const obj = { z: { c: 1, a: 2 }, a: { z: 1, a: 2 } };
12
+ const result = sortKeys(obj);
13
+ expect(Object.keys(result)).toEqual(["a", "z"]);
14
+ expect(Object.keys(result.z)).toEqual(["a", "c"]);
15
+ expect(Object.keys(result.a)).toEqual(["a", "z"]);
16
+ });
17
+ it("should remove undefined values", () => {
18
+ const obj = { a: 1, b: undefined, c: 3 };
19
+ const result = sortKeys(obj);
20
+ expect(result).toEqual({ a: 1, c: 3 });
21
+ });
22
+ it("should preserve null values", () => {
23
+ const obj = { a: 1, b: null, c: 3 };
24
+ const result = sortKeys(obj);
25
+ expect(result).toEqual({ a: 1, b: null, c: 3 });
26
+ });
27
+ it("should handle arrays", () => {
28
+ const obj = [{ b: 1, a: 2 }, { d: 3, c: 4 }];
29
+ const result = sortKeys(obj);
30
+ expect(result).toHaveLength(2);
31
+ expect(Object.keys(result[0])).toEqual(["a", "b"]);
32
+ expect(Object.keys(result[1])).toEqual(["c", "d"]);
33
+ });
34
+ it("should handle arrays inside objects", () => {
35
+ const obj = { items: [{ z: 1, a: 2 }] };
36
+ const result = sortKeys(obj);
37
+ expect(Object.keys(result.items[0])).toEqual(["a", "z"]);
38
+ });
39
+ it("should return null for null input", () => {
40
+ expect(sortKeys(null)).toBeNull();
41
+ });
42
+ it("should return undefined for undefined input", () => {
43
+ expect(sortKeys(undefined)).toBeUndefined();
44
+ });
45
+ it("should return primitives unchanged", () => {
46
+ expect(sortKeys(42)).toBe(42);
47
+ expect(sortKeys("hello")).toBe("hello");
48
+ expect(sortKeys(true)).toBe(true);
49
+ });
50
+ });
51
+ describe("toCanonical", () => {
52
+ it("should produce sorted JSON string", () => {
53
+ const obj = { c: 1, a: 2, b: 3 };
54
+ expect(toCanonical(obj)).toBe('{"a":2,"b":3,"c":1}');
55
+ });
56
+ it("should produce consistent output for same data", () => {
57
+ const obj1 = { a: 1, b: 2 };
58
+ const obj2 = { b: 2, a: 1 };
59
+ expect(toCanonical(obj1)).toBe(toCanonical(obj2));
60
+ });
61
+ it("should remove undefined values", () => {
62
+ const obj = { a: 1, b: undefined };
63
+ expect(toCanonical(obj)).toBe('{"a":1}');
64
+ });
65
+ it("should preserve null values", () => {
66
+ const obj = { a: null };
67
+ expect(toCanonical(obj)).toBe('{"a":null}');
68
+ });
69
+ it("should handle nested structures", () => {
70
+ const obj = { z: { b: 1, a: 2 }, a: 3 };
71
+ expect(toCanonical(obj)).toBe('{"a":3,"z":{"a":2,"b":1}}');
72
+ });
73
+ it("should handle arrays", () => {
74
+ const obj = [3, 1, 2];
75
+ expect(toCanonical(obj)).toBe("[3,1,2]"); // Arrays preserve order
76
+ });
77
+ it("should handle primitives", () => {
78
+ expect(toCanonical(42)).toBe("42");
79
+ expect(toCanonical("hello")).toBe('"hello"');
80
+ expect(toCanonical(true)).toBe("true");
81
+ expect(toCanonical(null)).toBe("null");
82
+ });
83
+ });
84
+ describe("fromCanonical", () => {
85
+ it("should parse canonical JSON string", () => {
86
+ const canonical = '{"a":1,"b":2}';
87
+ expect(fromCanonical(canonical)).toEqual({ a: 1, b: 2 });
88
+ });
89
+ it("should handle arrays", () => {
90
+ const canonical = "[1,2,3]";
91
+ expect(fromCanonical(canonical)).toEqual([1, 2, 3]);
92
+ });
93
+ it("should handle primitives", () => {
94
+ expect(fromCanonical("42")).toBe(42);
95
+ expect(fromCanonical('"hello"')).toBe("hello");
96
+ expect(fromCanonical("true")).toBe(true);
97
+ expect(fromCanonical("null")).toBeNull();
98
+ });
99
+ });
100
+ describe("canonicalEqual", () => {
101
+ it("should return true for equal objects with different key order", () => {
102
+ const a = { x: 1, y: 2 };
103
+ const b = { y: 2, x: 1 };
104
+ expect(canonicalEqual(a, b)).toBe(true);
105
+ });
106
+ it("should return false for different objects", () => {
107
+ const a = { x: 1, y: 2 };
108
+ const b = { x: 1, y: 3 };
109
+ expect(canonicalEqual(a, b)).toBe(false);
110
+ });
111
+ it("should treat undefined as missing", () => {
112
+ const a = { x: 1 };
113
+ const b = { x: 1, y: undefined };
114
+ expect(canonicalEqual(a, b)).toBe(true);
115
+ });
116
+ it("should handle nested objects", () => {
117
+ const a = { outer: { b: 1, a: 2 } };
118
+ const b = { outer: { a: 2, b: 1 } };
119
+ expect(canonicalEqual(a, b)).toBe(true);
120
+ });
121
+ it("should distinguish null from undefined", () => {
122
+ const a = { x: null };
123
+ const b = { x: undefined };
124
+ expect(canonicalEqual(a, b)).toBe(false);
125
+ });
126
+ });
127
+ describe("Deterministic Hashing", () => {
128
+ it("should produce same canonical form regardless of property order", () => {
129
+ // Simulate objects created in different orders
130
+ const obj1 = {};
131
+ obj1.alpha = 1;
132
+ obj1.beta = 2;
133
+ obj1.gamma = 3;
134
+ const obj2 = {};
135
+ obj2.gamma = 3;
136
+ obj2.alpha = 1;
137
+ obj2.beta = 2;
138
+ expect(toCanonical(obj1)).toBe(toCanonical(obj2));
139
+ });
140
+ it("should handle deeply nested structures consistently", () => {
141
+ const obj1 = {
142
+ z: { y: { x: { w: 1 } } },
143
+ a: { b: { c: 2 } },
144
+ };
145
+ const obj2 = {
146
+ a: { b: { c: 2 } },
147
+ z: { y: { x: { w: 1 } } },
148
+ };
149
+ expect(toCanonical(obj1)).toBe(toCanonical(obj2));
150
+ });
151
+ });
152
+ });
153
+ //# sourceMappingURL=canonical.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.test.js","sourceRoot":"","sources":["../../src/utils/canonical.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { DomainSchema } from "../schema/domain.js";
2
+ /**
3
+ * SHA-256 hash using Web Crypto API
4
+ * Works in both browser and Node.js
5
+ */
6
+ export declare function sha256(message: string): Promise<string>;
7
+ /**
8
+ * Hash a schema in canonical form
9
+ */
10
+ export declare function hashSchema(schema: Omit<DomainSchema, "hash">): Promise<string>;
11
+ /**
12
+ * Generate deterministic requirement ID
13
+ * Based on: schemaHash, intentId, actionId, flowNodePath
14
+ */
15
+ export declare function generateRequirementId(schemaHash: string, intentId: string, actionId: string, flowNodePath: string): Promise<string>;
16
+ /**
17
+ * Generate a trace node ID
18
+ */
19
+ export declare function generateTraceId(): string;
20
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;GAGG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS7D;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAIpF;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
@@ -0,0 +1,38 @@
1
+ import { toCanonical } from "./canonical.js";
2
+ /**
3
+ * SHA-256 hash using Web Crypto API
4
+ * Works in both browser and Node.js
5
+ */
6
+ export async function sha256(message) {
7
+ const msgBuffer = new TextEncoder().encode(message);
8
+ // Use Web Crypto API
9
+ const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
10
+ // Convert to hex string
11
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
12
+ return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
13
+ }
14
+ /**
15
+ * Hash a schema in canonical form
16
+ */
17
+ export async function hashSchema(schema) {
18
+ // Create canonical form without the hash field
19
+ const canonical = toCanonical(schema);
20
+ return sha256(canonical);
21
+ }
22
+ /**
23
+ * Generate deterministic requirement ID
24
+ * Based on: schemaHash, intentId, actionId, flowNodePath
25
+ */
26
+ export async function generateRequirementId(schemaHash, intentId, actionId, flowNodePath) {
27
+ const input = `${schemaHash}:${intentId}:${actionId}:${flowNodePath}`;
28
+ const hash = await sha256(input);
29
+ // Return first 16 characters for brevity
30
+ return `req-${hash.slice(0, 16)}`;
31
+ }
32
+ /**
33
+ * Generate a trace node ID
34
+ */
35
+ export function generateTraceId() {
36
+ return `trace-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
37
+ }
38
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAe;IAC1C,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEpD,qBAAqB;IACrB,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAEpE,wBAAwB;IACxB,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IACzD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAkC;IACjE,+CAA+C;IAC/C,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,OAAO,MAAM,CAAC,SAAS,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,UAAkB,EAClB,QAAgB,EAChB,QAAgB,EAChB,YAAoB;IAEpB,MAAM,KAAK,GAAG,GAAG,UAAU,IAAI,QAAQ,IAAI,QAAQ,IAAI,YAAY,EAAE,CAAC;IACtE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,yCAAyC;IACzC,OAAO,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,SAAS,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACzE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hash.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.test.d.ts","sourceRoot":"","sources":["../../src/utils/hash.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,146 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { sha256, hashSchema, generateRequirementId, generateTraceId } from "./hash.js";
3
+ describe("Hash Utilities", () => {
4
+ describe("sha256", () => {
5
+ it("should produce consistent hash for same input", async () => {
6
+ const hash1 = await sha256("hello world");
7
+ const hash2 = await sha256("hello world");
8
+ expect(hash1).toBe(hash2);
9
+ });
10
+ it("should produce different hash for different input", async () => {
11
+ const hash1 = await sha256("hello");
12
+ const hash2 = await sha256("world");
13
+ expect(hash1).not.toBe(hash2);
14
+ });
15
+ it("should produce 64 character hex string", async () => {
16
+ const hash = await sha256("test");
17
+ expect(hash).toHaveLength(64);
18
+ expect(hash).toMatch(/^[a-f0-9]{64}$/);
19
+ });
20
+ it("should handle empty string", async () => {
21
+ const hash = await sha256("");
22
+ expect(hash).toHaveLength(64);
23
+ });
24
+ it("should handle unicode characters", async () => {
25
+ const hash = await sha256("안녕하세요");
26
+ expect(hash).toHaveLength(64);
27
+ });
28
+ it("should match known SHA-256 hash", async () => {
29
+ // "test" hashes to this known value
30
+ const hash = await sha256("test");
31
+ expect(hash).toBe("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08");
32
+ });
33
+ });
34
+ describe("hashSchema", () => {
35
+ it("should produce consistent hash for same schema", async () => {
36
+ const schema = {
37
+ id: "test",
38
+ version: "1.0.0",
39
+ state: { fields: {} },
40
+ computed: { fields: {} },
41
+ actions: {},
42
+ };
43
+ const hash1 = await hashSchema(schema);
44
+ const hash2 = await hashSchema(schema);
45
+ expect(hash1).toBe(hash2);
46
+ });
47
+ it("should produce same hash regardless of key order", async () => {
48
+ const schema1 = {
49
+ id: "test",
50
+ version: "1.0.0",
51
+ state: { fields: {} },
52
+ computed: { fields: {} },
53
+ actions: {},
54
+ };
55
+ const schema2 = {
56
+ actions: {},
57
+ computed: { fields: {} },
58
+ state: { fields: {} },
59
+ version: "1.0.0",
60
+ id: "test",
61
+ };
62
+ const hash1 = await hashSchema(schema1);
63
+ const hash2 = await hashSchema(schema2);
64
+ expect(hash1).toBe(hash2);
65
+ });
66
+ it("should produce different hash for different schemas", async () => {
67
+ const schema1 = {
68
+ id: "test1",
69
+ version: "1.0.0",
70
+ state: { fields: {} },
71
+ computed: { fields: {} },
72
+ actions: {},
73
+ };
74
+ const schema2 = {
75
+ id: "test2",
76
+ version: "1.0.0",
77
+ state: { fields: {} },
78
+ computed: { fields: {} },
79
+ actions: {},
80
+ };
81
+ const hash1 = await hashSchema(schema1);
82
+ const hash2 = await hashSchema(schema2);
83
+ expect(hash1).not.toBe(hash2);
84
+ });
85
+ it("should detect changes in nested structures", async () => {
86
+ const schema1 = {
87
+ id: "test",
88
+ version: "1.0.0",
89
+ state: { fields: { count: { type: "number", required: true } } },
90
+ computed: { fields: {} },
91
+ actions: {},
92
+ };
93
+ const schema2 = {
94
+ id: "test",
95
+ version: "1.0.0",
96
+ state: { fields: { count: { type: "string", required: true } } },
97
+ computed: { fields: {} },
98
+ actions: {},
99
+ };
100
+ const hash1 = await hashSchema(schema1);
101
+ const hash2 = await hashSchema(schema2);
102
+ expect(hash1).not.toBe(hash2);
103
+ });
104
+ });
105
+ describe("generateRequirementId", () => {
106
+ it("should produce consistent ID for same inputs", async () => {
107
+ const id1 = await generateRequirementId("schema-hash", "intent-1", "action", "path");
108
+ const id2 = await generateRequirementId("schema-hash", "intent-1", "action", "path");
109
+ expect(id1).toBe(id2);
110
+ });
111
+ it("should produce different ID for different inputs", async () => {
112
+ const id1 = await generateRequirementId("schema-hash", "intent-1", "action", "path");
113
+ const id2 = await generateRequirementId("schema-hash", "intent-2", "action", "path");
114
+ expect(id1).not.toBe(id2);
115
+ });
116
+ it("should produce ID with req- prefix", async () => {
117
+ const id = await generateRequirementId("hash", "intent", "action", "path");
118
+ expect(id).toMatch(/^req-[a-f0-9]{16}$/);
119
+ });
120
+ it("should produce 20 character ID (req- + 16 hex chars)", async () => {
121
+ const id = await generateRequirementId("hash", "intent", "action", "path");
122
+ expect(id).toHaveLength(20);
123
+ });
124
+ });
125
+ describe("generateTraceId", () => {
126
+ it("should produce unique IDs", () => {
127
+ const id1 = generateTraceId();
128
+ const id2 = generateTraceId();
129
+ expect(id1).not.toBe(id2);
130
+ });
131
+ it("should produce ID with trace- prefix", () => {
132
+ const id = generateTraceId();
133
+ expect(id).toMatch(/^trace-\d+-[a-z0-9]+$/);
134
+ });
135
+ it("should include timestamp", () => {
136
+ const before = Date.now();
137
+ const id = generateTraceId();
138
+ const after = Date.now();
139
+ const parts = id.split("-");
140
+ const timestamp = parseInt(parts[1], 10);
141
+ expect(timestamp).toBeGreaterThanOrEqual(before);
142
+ expect(timestamp).toBeLessThanOrEqual(after);
143
+ });
144
+ });
145
+ });
146
+ //# sourceMappingURL=hash.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.test.js","sourceRoot":"","sources":["../../src/utils/hash.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from "./path.js";
2
+ export * from "./canonical.js";
3
+ export * from "./hash.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./path.js";
2
+ export * from "./canonical.js";
3
+ export * from "./hash.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,40 @@
1
+ import type { SemanticPath } from "../schema/common.js";
2
+ /**
3
+ * Parse a dot-separated path into segments
4
+ */
5
+ export declare function parsePath(path: SemanticPath): string[];
6
+ /**
7
+ * Join path segments into a semantic path
8
+ */
9
+ export declare function joinPath(...segments: string[]): SemanticPath;
10
+ /**
11
+ * Get value at path from object
12
+ * Returns undefined for non-existent paths (never throws)
13
+ */
14
+ export declare function getByPath(obj: unknown, path: SemanticPath): unknown;
15
+ /**
16
+ * Immutably set value at path
17
+ * Creates intermediate objects as needed
18
+ */
19
+ export declare function setByPath(obj: unknown, path: SemanticPath, value: unknown): unknown;
20
+ /**
21
+ * Immutably remove value at path
22
+ */
23
+ export declare function unsetByPath(obj: unknown, path: SemanticPath): unknown;
24
+ /**
25
+ * Immutably shallow merge at path
26
+ */
27
+ export declare function mergeAtPath(obj: unknown, path: SemanticPath, value: Record<string, unknown>): unknown;
28
+ /**
29
+ * Check if a path exists in an object
30
+ */
31
+ export declare function hasPath(obj: unknown, path: SemanticPath): boolean;
32
+ /**
33
+ * Get parent path
34
+ */
35
+ export declare function parentPath(path: SemanticPath): SemanticPath;
36
+ /**
37
+ * Get last segment of path
38
+ */
39
+ export declare function lastSegment(path: SemanticPath): string;
40
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,EAAE,CAGtD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,YAAY,CAE5D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAmBnE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAKnF;AAmBD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAKrE;AAsBD;;GAEG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAQT;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAuBjE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,CAG3D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAGtD"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Parse a dot-separated path into segments
3
+ */
4
+ export function parsePath(path) {
5
+ if (!path)
6
+ return [];
7
+ return path.split(".");
8
+ }
9
+ /**
10
+ * Join path segments into a semantic path
11
+ */
12
+ export function joinPath(...segments) {
13
+ return segments.filter(Boolean).join(".");
14
+ }
15
+ /**
16
+ * Get value at path from object
17
+ * Returns undefined for non-existent paths (never throws)
18
+ */
19
+ export function getByPath(obj, path) {
20
+ if (!path)
21
+ return obj;
22
+ const segments = parsePath(path);
23
+ let current = obj;
24
+ for (const segment of segments) {
25
+ if (current === null || current === undefined) {
26
+ return undefined;
27
+ }
28
+ if (typeof current === "object") {
29
+ current = current[segment];
30
+ }
31
+ else {
32
+ return undefined;
33
+ }
34
+ }
35
+ return current;
36
+ }
37
+ /**
38
+ * Immutably set value at path
39
+ * Creates intermediate objects as needed
40
+ */
41
+ export function setByPath(obj, path, value) {
42
+ if (!path)
43
+ return value;
44
+ const segments = parsePath(path);
45
+ return setByPathSegments(obj, segments, value);
46
+ }
47
+ function setByPathSegments(obj, segments, value) {
48
+ if (segments.length === 0)
49
+ return value;
50
+ const [head, ...tail] = segments;
51
+ const current = obj !== null && typeof obj === "object" ? obj : {};
52
+ if (tail.length === 0) {
53
+ return { ...current, [head]: value };
54
+ }
55
+ const nested = current[head];
56
+ return {
57
+ ...current,
58
+ [head]: setByPathSegments(nested, tail, value),
59
+ };
60
+ }
61
+ /**
62
+ * Immutably remove value at path
63
+ */
64
+ export function unsetByPath(obj, path) {
65
+ if (!path)
66
+ return undefined;
67
+ const segments = parsePath(path);
68
+ return unsetByPathSegments(obj, segments);
69
+ }
70
+ function unsetByPathSegments(obj, segments) {
71
+ if (segments.length === 0 || obj === null || typeof obj !== "object") {
72
+ return obj;
73
+ }
74
+ const [head, ...tail] = segments;
75
+ const current = obj;
76
+ if (tail.length === 0) {
77
+ const { [head]: _, ...rest } = current;
78
+ return rest;
79
+ }
80
+ const nested = current[head];
81
+ return {
82
+ ...current,
83
+ [head]: unsetByPathSegments(nested, tail),
84
+ };
85
+ }
86
+ /**
87
+ * Immutably shallow merge at path
88
+ */
89
+ export function mergeAtPath(obj, path, value) {
90
+ const existing = getByPath(obj, path);
91
+ const merged = existing !== null && typeof existing === "object"
92
+ ? { ...existing, ...value }
93
+ : value;
94
+ return setByPath(obj, path, merged);
95
+ }
96
+ /**
97
+ * Check if a path exists in an object
98
+ */
99
+ export function hasPath(obj, path) {
100
+ if (!path)
101
+ return obj !== undefined;
102
+ const segments = parsePath(path);
103
+ let current = obj;
104
+ for (const segment of segments) {
105
+ if (current === null || current === undefined) {
106
+ return false;
107
+ }
108
+ if (typeof current !== "object") {
109
+ return false;
110
+ }
111
+ if (!(segment in current)) {
112
+ return false;
113
+ }
114
+ current = current[segment];
115
+ }
116
+ return true;
117
+ }
118
+ /**
119
+ * Get parent path
120
+ */
121
+ export function parentPath(path) {
122
+ const segments = parsePath(path);
123
+ return segments.slice(0, -1).join(".");
124
+ }
125
+ /**
126
+ * Get last segment of path
127
+ */
128
+ export function lastSegment(path) {
129
+ const segments = parsePath(path);
130
+ return segments[segments.length - 1] ?? "";
131
+ }
132
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=path.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.test.d.ts","sourceRoot":"","sources":["../../src/utils/path.test.ts"],"names":[],"mappings":""}