@manifesto-ai/core 0.3.0 → 1.3.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 (279) hide show
  1. package/README.md +148 -498
  2. package/dist/__tests__/apply.test.d.ts +2 -0
  3. package/dist/__tests__/apply.test.d.ts.map +1 -0
  4. package/dist/__tests__/apply.test.js +144 -0
  5. package/dist/__tests__/apply.test.js.map +1 -0
  6. package/dist/__tests__/jcs.test.d.ts +2 -0
  7. package/dist/__tests__/jcs.test.d.ts.map +1 -0
  8. package/dist/__tests__/jcs.test.js +45 -0
  9. package/dist/__tests__/jcs.test.js.map +1 -0
  10. package/dist/core/apply.d.ts +17 -0
  11. package/dist/core/apply.d.ts.map +1 -0
  12. package/dist/core/apply.js +130 -0
  13. package/dist/core/apply.js.map +1 -0
  14. package/dist/core/compute.d.ts +17 -0
  15. package/dist/core/compute.d.ts.map +1 -0
  16. package/dist/core/compute.js +287 -0
  17. package/dist/core/compute.js.map +1 -0
  18. package/dist/core/compute.test.d.ts +2 -0
  19. package/dist/core/compute.test.d.ts.map +1 -0
  20. package/dist/core/compute.test.js +633 -0
  21. package/dist/core/compute.test.js.map +1 -0
  22. package/dist/core/explain.d.ts +14 -0
  23. package/dist/core/explain.d.ts.map +1 -0
  24. package/dist/core/explain.js +78 -0
  25. package/dist/core/explain.js.map +1 -0
  26. package/dist/core/index.d.ts +5 -0
  27. package/dist/core/index.d.ts.map +1 -0
  28. package/dist/core/index.js +5 -0
  29. package/dist/core/index.js.map +1 -0
  30. package/dist/core/validate.d.ts +16 -0
  31. package/dist/core/validate.d.ts.map +1 -0
  32. package/dist/core/validate.js +361 -0
  33. package/dist/core/validate.js.map +1 -0
  34. package/dist/core/validate.test.d.ts +2 -0
  35. package/dist/core/validate.test.d.ts.map +1 -0
  36. package/dist/core/validate.test.js +638 -0
  37. package/dist/core/validate.test.js.map +1 -0
  38. package/dist/core/validation-utils.d.ts +20 -0
  39. package/dist/core/validation-utils.d.ts.map +1 -0
  40. package/dist/core/validation-utils.js +289 -0
  41. package/dist/core/validation-utils.js.map +1 -0
  42. package/dist/errors.d.ts +30 -0
  43. package/dist/errors.d.ts.map +1 -0
  44. package/dist/errors.js +51 -0
  45. package/dist/errors.js.map +1 -0
  46. package/dist/evaluator/computed.d.ts +14 -0
  47. package/dist/evaluator/computed.d.ts.map +1 -0
  48. package/dist/evaluator/computed.js +60 -0
  49. package/dist/evaluator/computed.js.map +1 -0
  50. package/dist/evaluator/context.d.ts +59 -0
  51. package/dist/evaluator/context.d.ts.map +1 -0
  52. package/dist/evaluator/context.js +41 -0
  53. package/dist/evaluator/context.js.map +1 -0
  54. package/dist/evaluator/dag.d.ts +30 -0
  55. package/dist/evaluator/dag.d.ts.map +1 -0
  56. package/dist/evaluator/dag.js +121 -0
  57. package/dist/evaluator/dag.js.map +1 -0
  58. package/dist/evaluator/expr.d.ts +11 -0
  59. package/dist/evaluator/expr.d.ts.map +1 -0
  60. package/dist/evaluator/expr.js +649 -0
  61. package/dist/evaluator/expr.js.map +1 -0
  62. package/dist/evaluator/expr.test.d.ts +2 -0
  63. package/dist/evaluator/expr.test.d.ts.map +1 -0
  64. package/dist/evaluator/expr.test.js +449 -0
  65. package/dist/evaluator/expr.test.js.map +1 -0
  66. package/dist/evaluator/flow.d.ts +35 -0
  67. package/dist/evaluator/flow.d.ts.map +1 -0
  68. package/dist/evaluator/flow.js +387 -0
  69. package/dist/evaluator/flow.js.map +1 -0
  70. package/dist/evaluator/flow.test.d.ts +2 -0
  71. package/dist/evaluator/flow.test.d.ts.map +1 -0
  72. package/dist/evaluator/flow.test.js +499 -0
  73. package/dist/evaluator/flow.test.js.map +1 -0
  74. package/dist/evaluator/index.d.ts +6 -0
  75. package/dist/evaluator/index.d.ts.map +1 -0
  76. package/dist/evaluator/index.js +6 -0
  77. package/dist/evaluator/index.js.map +1 -0
  78. package/dist/factories.d.ts +22 -0
  79. package/dist/factories.d.ts.map +1 -0
  80. package/dist/factories.js +44 -0
  81. package/dist/factories.js.map +1 -0
  82. package/dist/index.d.ts +47 -11
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +30 -45
  85. package/dist/index.js.map +1 -1
  86. package/dist/index.test.d.ts +2 -0
  87. package/dist/index.test.d.ts.map +1 -0
  88. package/dist/index.test.js +13 -0
  89. package/dist/index.test.js.map +1 -0
  90. package/dist/schema/action.d.ts +14 -0
  91. package/dist/schema/action.d.ts.map +1 -0
  92. package/dist/schema/action.js +30 -0
  93. package/dist/schema/action.js.map +1 -0
  94. package/dist/schema/common.d.ts +37 -0
  95. package/dist/schema/common.d.ts.map +1 -0
  96. package/dist/schema/common.js +20 -0
  97. package/dist/schema/common.js.map +1 -0
  98. package/dist/schema/computed.d.ts +23 -0
  99. package/dist/schema/computed.d.ts.map +1 -0
  100. package/dist/schema/computed.js +34 -0
  101. package/dist/schema/computed.js.map +1 -0
  102. package/dist/schema/domain.d.ts +50 -0
  103. package/dist/schema/domain.d.ts.map +1 -0
  104. package/dist/schema/domain.js +60 -0
  105. package/dist/schema/domain.js.map +1 -0
  106. package/dist/schema/expr.d.ts +303 -0
  107. package/dist/schema/expr.d.ts.map +1 -0
  108. package/dist/schema/expr.js +283 -0
  109. package/dist/schema/expr.js.map +1 -0
  110. package/dist/schema/field.d.ts +48 -0
  111. package/dist/schema/field.d.ts.map +1 -0
  112. package/dist/schema/field.js +31 -0
  113. package/dist/schema/field.js.map +1 -0
  114. package/dist/schema/flow.d.ts +103 -0
  115. package/dist/schema/flow.d.ts.map +1 -0
  116. package/dist/schema/flow.js +82 -0
  117. package/dist/schema/flow.js.map +1 -0
  118. package/dist/schema/host-context.d.ts +12 -0
  119. package/dist/schema/host-context.d.ts.map +1 -0
  120. package/dist/schema/host-context.js +23 -0
  121. package/dist/schema/host-context.js.map +1 -0
  122. package/dist/schema/index.d.ts +13 -2
  123. package/dist/schema/index.d.ts.map +1 -1
  124. package/dist/schema/index.js +25 -2
  125. package/dist/schema/index.js.map +1 -1
  126. package/dist/schema/patch.d.ts +59 -0
  127. package/dist/schema/patch.d.ts.map +1 -0
  128. package/dist/schema/patch.js +60 -0
  129. package/dist/schema/patch.js.map +1 -0
  130. package/dist/schema/result.d.ts +142 -0
  131. package/dist/schema/result.d.ts.map +1 -0
  132. package/dist/schema/result.js +94 -0
  133. package/dist/schema/result.js.map +1 -0
  134. package/dist/schema/snapshot.d.ts +153 -0
  135. package/dist/schema/snapshot.d.ts.map +1 -0
  136. package/dist/schema/snapshot.js +160 -0
  137. package/dist/schema/snapshot.js.map +1 -0
  138. package/dist/schema/trace.d.ts +98 -0
  139. package/dist/schema/trace.d.ts.map +1 -0
  140. package/dist/schema/trace.js +90 -0
  141. package/dist/schema/trace.js.map +1 -0
  142. package/dist/schema/type-spec.d.ts +34 -0
  143. package/dist/schema/type-spec.d.ts.map +1 -0
  144. package/dist/schema/type-spec.js +40 -0
  145. package/dist/schema/type-spec.js.map +1 -0
  146. package/dist/utils/canonical.d.ts +37 -0
  147. package/dist/utils/canonical.d.ts.map +1 -0
  148. package/dist/utils/canonical.js +122 -0
  149. package/dist/utils/canonical.js.map +1 -0
  150. package/dist/utils/canonical.test.d.ts +2 -0
  151. package/dist/utils/canonical.test.d.ts.map +1 -0
  152. package/dist/utils/canonical.test.js +183 -0
  153. package/dist/utils/canonical.test.js.map +1 -0
  154. package/dist/utils/hash.d.ts +28 -0
  155. package/dist/utils/hash.d.ts.map +1 -0
  156. package/dist/utils/hash.js +152 -0
  157. package/dist/utils/hash.js.map +1 -0
  158. package/dist/utils/hash.test.d.ts +2 -0
  159. package/dist/utils/hash.test.d.ts.map +1 -0
  160. package/dist/utils/hash.test.js +170 -0
  161. package/dist/utils/hash.test.js.map +1 -0
  162. package/dist/utils/index.d.ts +4 -0
  163. package/dist/utils/index.d.ts.map +1 -0
  164. package/dist/utils/index.js +4 -0
  165. package/dist/utils/index.js.map +1 -0
  166. package/dist/utils/path.d.ts +40 -0
  167. package/dist/utils/path.d.ts.map +1 -0
  168. package/dist/utils/path.js +132 -0
  169. package/dist/utils/path.js.map +1 -0
  170. package/dist/utils/path.test.d.ts +2 -0
  171. package/dist/utils/path.test.d.ts.map +1 -0
  172. package/dist/utils/path.test.js +191 -0
  173. package/dist/utils/path.test.js.map +1 -0
  174. package/package.json +28 -41
  175. package/LICENSE +0 -21
  176. package/dist/dag/graph.d.ts +0 -62
  177. package/dist/dag/graph.d.ts.map +0 -1
  178. package/dist/dag/graph.js +0 -244
  179. package/dist/dag/graph.js.map +0 -1
  180. package/dist/dag/index.d.ts +0 -4
  181. package/dist/dag/index.d.ts.map +0 -1
  182. package/dist/dag/index.js +0 -4
  183. package/dist/dag/index.js.map +0 -1
  184. package/dist/dag/propagation.d.ts +0 -58
  185. package/dist/dag/propagation.d.ts.map +0 -1
  186. package/dist/dag/propagation.js +0 -224
  187. package/dist/dag/propagation.js.map +0 -1
  188. package/dist/dag/topological.d.ts +0 -33
  189. package/dist/dag/topological.d.ts.map +0 -1
  190. package/dist/dag/topological.js +0 -173
  191. package/dist/dag/topological.js.map +0 -1
  192. package/dist/domain/define.d.ts +0 -82
  193. package/dist/domain/define.d.ts.map +0 -1
  194. package/dist/domain/define.js +0 -105
  195. package/dist/domain/define.js.map +0 -1
  196. package/dist/domain/index.d.ts +0 -4
  197. package/dist/domain/index.d.ts.map +0 -1
  198. package/dist/domain/index.js +0 -4
  199. package/dist/domain/index.js.map +0 -1
  200. package/dist/domain/types.d.ts +0 -203
  201. package/dist/domain/types.d.ts.map +0 -1
  202. package/dist/domain/types.js +0 -2
  203. package/dist/domain/types.js.map +0 -1
  204. package/dist/domain/validate.d.ts +0 -17
  205. package/dist/domain/validate.d.ts.map +0 -1
  206. package/dist/domain/validate.js +0 -204
  207. package/dist/domain/validate.js.map +0 -1
  208. package/dist/effect/index.d.ts +0 -4
  209. package/dist/effect/index.d.ts.map +0 -1
  210. package/dist/effect/index.js +0 -4
  211. package/dist/effect/index.js.map +0 -1
  212. package/dist/effect/result.d.ts +0 -100
  213. package/dist/effect/result.d.ts.map +0 -1
  214. package/dist/effect/result.js +0 -163
  215. package/dist/effect/result.js.map +0 -1
  216. package/dist/effect/runner.d.ts +0 -98
  217. package/dist/effect/runner.d.ts.map +0 -1
  218. package/dist/effect/runner.js +0 -321
  219. package/dist/effect/runner.js.map +0 -1
  220. package/dist/effect/types.d.ts +0 -169
  221. package/dist/effect/types.d.ts.map +0 -1
  222. package/dist/effect/types.js +0 -28
  223. package/dist/effect/types.js.map +0 -1
  224. package/dist/expression/analyzer.d.ts +0 -42
  225. package/dist/expression/analyzer.d.ts.map +0 -1
  226. package/dist/expression/analyzer.js +0 -166
  227. package/dist/expression/analyzer.js.map +0 -1
  228. package/dist/expression/evaluator.d.ts +0 -16
  229. package/dist/expression/evaluator.d.ts.map +0 -1
  230. package/dist/expression/evaluator.js +0 -382
  231. package/dist/expression/evaluator.js.map +0 -1
  232. package/dist/expression/index.d.ts +0 -5
  233. package/dist/expression/index.d.ts.map +0 -1
  234. package/dist/expression/index.js +0 -5
  235. package/dist/expression/index.js.map +0 -1
  236. package/dist/expression/parser.d.ts +0 -37
  237. package/dist/expression/parser.d.ts.map +0 -1
  238. package/dist/expression/parser.js +0 -201
  239. package/dist/expression/parser.js.map +0 -1
  240. package/dist/expression/types.d.ts +0 -123
  241. package/dist/expression/types.d.ts.map +0 -1
  242. package/dist/expression/types.js +0 -10
  243. package/dist/expression/types.js.map +0 -1
  244. package/dist/policy/field-policy.d.ts +0 -63
  245. package/dist/policy/field-policy.d.ts.map +0 -1
  246. package/dist/policy/field-policy.js +0 -138
  247. package/dist/policy/field-policy.js.map +0 -1
  248. package/dist/policy/index.d.ts +0 -3
  249. package/dist/policy/index.d.ts.map +0 -1
  250. package/dist/policy/index.js +0 -3
  251. package/dist/policy/index.js.map +0 -1
  252. package/dist/policy/precondition.d.ts +0 -58
  253. package/dist/policy/precondition.d.ts.map +0 -1
  254. package/dist/policy/precondition.js +0 -115
  255. package/dist/policy/precondition.js.map +0 -1
  256. package/dist/runtime/index.d.ts +0 -4
  257. package/dist/runtime/index.d.ts.map +0 -1
  258. package/dist/runtime/index.js +0 -4
  259. package/dist/runtime/index.js.map +0 -1
  260. package/dist/runtime/runtime.d.ts +0 -94
  261. package/dist/runtime/runtime.d.ts.map +0 -1
  262. package/dist/runtime/runtime.js +0 -294
  263. package/dist/runtime/runtime.js.map +0 -1
  264. package/dist/runtime/snapshot.d.ts +0 -39
  265. package/dist/runtime/snapshot.d.ts.map +0 -1
  266. package/dist/runtime/snapshot.js +0 -264
  267. package/dist/runtime/snapshot.js.map +0 -1
  268. package/dist/runtime/subscription.d.ts +0 -82
  269. package/dist/runtime/subscription.d.ts.map +0 -1
  270. package/dist/runtime/subscription.js +0 -222
  271. package/dist/runtime/subscription.js.map +0 -1
  272. package/dist/schema/integration.d.ts +0 -89
  273. package/dist/schema/integration.d.ts.map +0 -1
  274. package/dist/schema/integration.js +0 -171
  275. package/dist/schema/integration.js.map +0 -1
  276. package/dist/schema/validation.d.ts +0 -51
  277. package/dist/schema/validation.d.ts.map +0 -1
  278. package/dist/schema/validation.js +0 -212
  279. package/dist/schema/validation.js.map +0 -1
package/README.md CHANGED
@@ -1,566 +1,216 @@
1
1
  # @manifesto-ai/core
2
2
 
3
- > AI Native Semantic Layer for SaaS Business Logic
3
+ > **Core** is the pure semantic calculator of Manifesto. It computes state transitions deterministically with no side effects.
4
4
 
5
- The core package provides domain definition, runtime execution, expression evaluation, and effect system for Manifesto AI.
5
+ ---
6
6
 
7
- ## Installation
8
-
9
- ```bash
10
- pnpm add @manifesto-ai/core
11
- # or
12
- npm install @manifesto-ai/core
13
- ```
7
+ ## What is Core?
14
8
 
15
- ## Quick Start
9
+ Core is responsible for evaluating domain semantics. Given a schema, snapshot, and intent, it computes what patches and effects should result—but never executes them.
16
10
 
17
- ```typescript
18
- import {
19
- defineDomain,
20
- createRuntime,
21
- defineDerived,
22
- defineAction,
23
- defineSource,
24
- sequence,
25
- setState,
26
- setValue,
27
- z
28
- } from '@manifesto-ai/core';
29
-
30
- // Define a domain
31
- const todosDomain = defineDomain({
32
- id: 'todos',
33
- name: 'Todos',
34
- description: 'Todo list management domain',
35
-
36
- dataSchema: z.object({
37
- items: z.array(z.object({
38
- id: z.string(),
39
- title: z.string(),
40
- completed: z.boolean()
41
- }))
42
- }),
43
-
44
- stateSchema: z.object({
45
- filter: z.enum(['all', 'active', 'completed']),
46
- isLoading: z.boolean()
47
- }),
48
-
49
- initialState: {
50
- filter: 'all',
51
- isLoading: false
52
- },
11
+ In the Manifesto architecture:
53
12
 
54
- paths: {
55
- sources: {
56
- // Auto-prefixed: 'items' becomes 'data.items'
57
- items: defineSource({
58
- schema: z.array(z.object({
59
- id: z.string(),
60
- title: z.string(),
61
- completed: z.boolean()
62
- })),
63
- defaultValue: [],
64
- semantic: { type: 'list', description: 'Todo items' }
65
- })
66
- },
67
- derived: {
68
- // Auto-prefixed: 'activeCount' becomes 'derived.activeCount'
69
- activeCount: defineDerived({
70
- deps: ['data.items'],
71
- expr: ['length', ['filter', ['get', 'data.items'], ['!', '$.completed']]],
72
- semantic: { type: 'count', description: 'Number of active todos' }
73
- })
74
- }
75
- },
76
-
77
- actions: {
78
- // Set filter action
79
- setFilter: defineAction({
80
- deps: ['state.filter'],
81
- input: z.object({ filter: z.enum(['all', 'active', 'completed']) }),
82
- effect: setState('state.filter', ['get', 'input.filter'], 'Set filter'),
83
- semantic: { type: 'action', verb: 'set', description: 'Set todo filter' }
84
- }),
85
-
86
- // Clear completed todos
87
- clearCompleted: defineAction({
88
- deps: ['data.items'],
89
- effect: setValue('data.items',
90
- ['filter', ['get', 'data.items'], ['!', '$.completed']],
91
- 'Clear completed todos'
92
- ),
93
- semantic: { type: 'action', verb: 'clear', description: 'Remove completed todos' }
94
- })
95
- }
96
- });
97
-
98
- // Create runtime
99
- const runtime = createRuntime({ domain: todosDomain });
100
-
101
- // Use the runtime
102
- runtime.set('data.items', [
103
- { id: '1', title: 'Learn Manifesto', completed: false }
104
- ]);
105
-
106
- console.log(runtime.get('derived.activeCount')); // 1
13
+ ```
14
+ Host ──→ CORE ──→ ComputeResult
15
+
16
+ Computes patches & effects
17
+ (pure, no IO, deterministic)
107
18
  ```
108
19
 
109
- ## API Reference
20
+ ---
110
21
 
111
- ### Domain Definition
22
+ ## What Core Does
112
23
 
113
- > **Note:** Keys in `sources`, `derived`, and `async` are auto-prefixed (`data.`, `derived.`, `async.` respectively). Keys with existing prefixes are preserved for backward compatibility. Both `activeCount` and `'derived.activeCount'` are valid.
24
+ | Responsibility | Description |
25
+ |----------------|-------------|
26
+ | Compute state transitions | Given (schema, snapshot, intent), produce patches and effects |
27
+ | Apply patches | Transform snapshots by applying patch operations |
28
+ | Validate schemas | Check DomainSchema structure for correctness |
29
+ | Explain values | Trace why a computed value has its current result |
114
30
 
115
- #### `defineDomain(options)`
31
+ ---
116
32
 
117
- Creates a domain definition.
33
+ ## What Core Does NOT Do
118
34
 
119
- ```typescript
120
- const domain = defineDomain({
121
- id: 'myDomain',
122
- name: 'My Domain',
123
- description: 'Domain description for AI understanding',
124
- dataSchema: z.object({ ... }), // Required: Source data schema
125
- stateSchema: z.object({ ... }), // Required: UI state schema
126
- initialState: { ... }, // Required: Initial state values
127
- paths: {
128
- sources: { ... }, // Optional: Source definitions
129
- derived: { ... }, // Optional: Computed values
130
- async: { ... }, // Optional: Async data sources
131
- },
132
- actions: { ... }, // Optional: Domain actions
133
- meta: { ... } // Optional: Domain metadata
134
- });
135
- ```
35
+ | NOT Responsible For | Who Is |
36
+ |--------------------|--------|
37
+ | Execute effects | Host |
38
+ | Perform IO (network, filesystem) | Host |
39
+ | Persist snapshots | Host |
40
+ | Govern authority/proposals | World |
41
+ | Handle UI bindings | Bridge / React |
136
42
 
137
- #### `defineSource(options)`
43
+ ---
138
44
 
139
- Defines a source field with semantic metadata.
45
+ ## Installation
140
46
 
141
- ```typescript
142
- const sources = {
143
- // Auto-prefixed: 'user' becomes 'data.user'
144
- user: defineSource({
145
- schema: z.object({ name: z.string(), email: z.string() }),
146
- defaultValue: { name: '', email: '' },
147
- semantic: {
148
- type: 'entity',
149
- description: 'Current user information'
150
- }
151
- })
152
- };
47
+ ```bash
48
+ npm install @manifesto-ai/core
49
+ # or
50
+ pnpm add @manifesto-ai/core
153
51
  ```
154
52
 
155
- #### `defineDerived(options)`
53
+ ---
156
54
 
157
- Defines a computed value with explicit dependencies.
55
+ ## Quick Example
158
56
 
159
57
  ```typescript
160
- const derived = {
161
- // Auto-prefixed: 'fullName' becomes 'derived.fullName'
162
- fullName: defineDerived({
163
- deps: ['data.firstName', 'data.lastName'],
164
- expr: ['concat', ['get', 'data.firstName'], ' ', ['get', 'data.lastName']],
165
- semantic: {
166
- type: 'computed',
167
- description: 'User full name'
168
- }
169
- })
170
- };
171
- ```
172
-
173
- #### `defineAsync(options)`
58
+ import { createCore, createSnapshot, createIntent } from "@manifesto-ai/core";
59
+ import type { DomainSchema } from "@manifesto-ai/core";
174
60
 
175
- Defines an async data source with result paths.
61
+ // Create core instance
62
+ const core = createCore();
176
63
 
177
- ```typescript
178
- const async = {
179
- // Auto-prefixed: 'userData' becomes 'async.userData'
180
- userData: defineAsync({
181
- deps: ['data.userId'],
182
- condition: ['!=', ['get', 'data.userId'], null],
183
- debounce: 300,
184
- effect: {
185
- _tag: 'ApiCall',
186
- method: 'GET',
187
- endpoint: '/api/user',
188
- description: 'Fetch user data'
64
+ // Define a simple schema (usually from @manifesto-ai/builder)
65
+ const schema: DomainSchema = {
66
+ id: "example:counter",
67
+ version: "1.0.0",
68
+ hash: "example-hash",
69
+ types: {},
70
+ state: {
71
+ fields: {
72
+ count: { type: "number", required: true, default: 0 },
189
73
  },
190
- resultPath: 'state.userData',
191
- loadingPath: 'state.userLoading',
192
- errorPath: 'state.userError',
193
- semantic: {
194
- type: 'async',
195
- description: 'User data from API'
196
- }
197
- })
198
- };
199
- ```
200
-
201
- #### `defineAction(options)`
202
-
203
- Defines a domain action with preconditions and effects.
204
-
205
- ```typescript
206
- const actions = {
207
- submit: defineAction({
208
- deps: ['derived.total', 'state.isSubmitting'],
209
- preconditions: [
210
- { path: 'derived.hasItems', expect: 'true', reason: 'Cart must have items' },
211
- { path: 'state.isSubmitting', expect: 'false', reason: 'Already submitting' }
212
- ],
213
- effect: sequence([
214
- setState('state.isSubmitting', true),
215
- apiCall({ method: 'POST', url: '/api/submit' }),
216
- setState('state.isSubmitting', false)
217
- ]),
218
- semantic: {
219
- type: 'action',
220
- verb: 'submit',
221
- description: 'Submit the order',
222
- risk: 'medium'
223
- }
224
- })
74
+ },
75
+ computed: {
76
+ fields: {
77
+ "computed.count": {
78
+ deps: ["count"],
79
+ expr: { kind: "get", path: "count" },
80
+ },
81
+ },
82
+ },
83
+ actions: {
84
+ increment: {
85
+ flow: {
86
+ kind: "patch",
87
+ op: "set",
88
+ path: "count",
89
+ value: {
90
+ kind: "add",
91
+ left: { kind: "get", path: "count" },
92
+ right: { kind: "lit", value: 1 },
93
+ },
94
+ },
95
+ },
96
+ },
225
97
  };
226
- ```
227
-
228
- ### Runtime
229
-
230
- #### `createRuntime(options)`
231
-
232
- Creates a runtime instance for a domain.
233
-
234
- ```typescript
235
- const runtime = createRuntime({
236
- domain: myDomain,
237
- initialData: { count: 0 },
238
- initialState: { isLoading: false }
239
- });
240
- ```
241
-
242
- #### Runtime Methods
243
-
244
- ```typescript
245
- // Get a value by path
246
- runtime.get('data.user.name'); // Returns the value
247
- runtime.get('derived.fullName'); // Computes and returns
248
-
249
- // Set a value
250
- runtime.set('data.count', 10);
251
- runtime.set('state.isLoading', true);
252
-
253
- // Subscribe to changes
254
- const unsubscribe = runtime.subscribe('data.count', (value) => {
255
- console.log('Count:', value);
256
- });
257
-
258
- // Subscribe to all changes
259
- runtime.subscribeAll((snapshot) => {
260
- console.log('Snapshot changed:', snapshot);
261
- });
262
98
 
263
- // Get current snapshot
264
- const snapshot = runtime.getSnapshot();
99
+ // Create host context (deterministic inputs)
100
+ const context = { now: 0, randomSeed: "seed" };
265
101
 
266
- // Check action availability
267
- const canSubmit = runtime.checkAction('submit');
268
- // { available: true, reason: null }
102
+ // Create initial snapshot
103
+ const snapshot = createSnapshot({ count: 0 }, schema.hash, context);
269
104
 
270
- // Execute an action
271
- await runtime.executeAction('submit', { orderId: '123' });
105
+ // Create intent
106
+ const intent = createIntent("increment", "intent-1");
272
107
 
273
- // Explain why a value is what it is
274
- const explanation = runtime.explain('derived.total');
275
- ```
276
-
277
- ### Expression DSL
278
-
279
- Manifesto uses a JSON-based DSL for declarative expressions. All expressions use **array format**: `['operator', ...args]`.
280
-
281
- #### Path Reference
108
+ // Compute result (pure, deterministic)
109
+ const result = await core.compute(schema, snapshot, intent, context);
282
110
 
283
- ```typescript
284
- ['get', 'data.user.name'] // Get value at path
285
- ['get', 'state.isLoading'] // Get state value
286
- ['get', 'derived.total'] // Get derived value
287
-
288
- // In predicates (filter, map, etc.)
289
- '$.price' // Current item's price field
290
- '$.completed' // Current item's completed field
291
- '$' // Current item itself
111
+ console.log(result.status); // → "complete"
112
+ console.log(result.snapshot.data.count); // 1
292
113
  ```
293
114
 
294
- #### Comparison Operators
295
-
296
- ```typescript
297
- ['==', a, b] // a === b
298
- ['!=', a, b] // a !== b
299
- ['>', a, b] // a > b
300
- ['>=', a, b] // a >= b
301
- ['<', a, b] // a < b
302
- ['<=', a, b] // a <= b
303
- ```
115
+ > See [GUIDE.md](../../docs/packages/core/GUIDE.md) for the full tutorial.
304
116
 
305
- #### Logical Operators
117
+ ---
306
118
 
307
- ```typescript
308
- ['all', expr1, expr2, ...] // All expressions must be true (AND)
309
- ['any', expr1, expr2, ...] // Any expression is true (OR)
310
- ['!', expr] // Negation (NOT)
311
- ```
119
+ ## Core API
312
120
 
313
- #### Arithmetic Operators
121
+ ### Main Exports
314
122
 
315
123
  ```typescript
316
- ['+', a, b] // a + b
317
- ['-', a, b] // a - b
318
- ['*', a, b] // a * b
319
- ```
124
+ // Factory
125
+ function createCore(): ManifestoCore;
320
126
 
321
- #### String Functions
322
-
323
- ```typescript
324
- ['concat', str1, str2, ...] // Concatenate strings
325
- ['join', array, delimiter] // Join array elements
326
- ['includes', str, search] // Contains substring
327
- ['slice', str, start, end] // Substring
328
- ```
329
-
330
- #### Array Functions
331
-
332
- ```typescript
333
- ['length', array] // Array length
334
- ['at', array, index] // Element at index (0 = first, -1 = last)
335
- ['filter', array, predicate] // Filter elements
336
- ['map', array, transform] // Transform elements
337
- ['some', array, predicate] // Any element matches
338
- ['every', array, predicate] // All elements match
339
- ['concat', array1, array2] // Concatenate arrays
340
- ['includes', array, element] // Array contains element
341
- ['sort', array, key] // Sort by key
342
- ['slice', array, start, end] // Slice array
343
- ['indexOf', array, element] // Find index of element
344
- ```
345
-
346
- > **Note:** There is no `find` operator. Use `['at', ['filter', array, predicate], 0]` instead.
347
-
348
- #### Conditional
349
-
350
- ```typescript
351
- // Case expression (if-else chain) - each condition-value pair is a tuple
352
- ['case',
353
- [condition1, value1],
354
- [condition2, value2],
355
- defaultValue
356
- ]
357
-
358
- // Example: return 'large', 'medium', or 'small' based on total
359
- ['case',
360
- [['>', ['get', 'derived.total'], 100], 'large'],
361
- [['>', ['get', 'derived.total'], 50], 'medium'],
362
- 'small'
363
- ]
364
-
365
- // Match expression (pattern matching)
366
- ['match', value,
367
- [pattern1, result1],
368
- [pattern2, result2],
369
- defaultResult
370
- ]
371
-
372
- // Coalesce (first non-null value)
373
- ['coalesce', value1, value2, value3]
374
- ```
375
-
376
- #### Object Operations
377
-
378
- ```typescript
379
- ['pick', object, ['key1', 'key2']] // Pick specific keys
380
- ['omit', object, ['key1', 'key2']] // Omit specific keys
381
- ```
382
-
383
- #### Examples
384
-
385
- ```typescript
386
- // Filter active todos
387
- ['filter', ['get', 'data.items'], ['!', '$.completed']]
388
-
389
- // Count completed items
390
- ['length', ['filter', ['get', 'data.items'], '$.completed']]
391
-
392
- // Find first item by id (no find operator, use filter + at)
393
- ['at', ['filter', ['get', 'data.items'], ['==', '$.id', ['get', 'input.id']]], 0]
394
-
395
- // Concatenate first and last name
396
- ['concat', ['get', 'data.firstName'], ' ', ['get', 'data.lastName']]
127
+ // Core interface
128
+ interface ManifestoCore {
129
+ compute(schema, snapshot, intent, context): Promise<ComputeResult>;
130
+ apply(schema, snapshot, patches, context): Snapshot;
131
+ validate(schema): ValidationResult;
132
+ explain(schema, snapshot, path): ExplainResult;
133
+ }
397
134
 
398
- // Conditional value (each condition-value pair is a tuple)
399
- ['case',
400
- [['>', ['get', 'derived.total'], 100], 'large'],
401
- [['>', ['get', 'derived.total'], 50], 'medium'],
402
- 'small'
403
- ]
135
+ // Key types
136
+ type DomainSchema = { id, version, hash, types, state, computed, actions, meta? };
137
+ type Snapshot = { data, computed, system, input, meta };
138
+ type Intent = { type, input?, intentId };
139
+ type Patch = { op: "set" | "unset" | "merge", path, value? };
140
+ type ComputeResult = { status, snapshot, requirements, trace };
404
141
  ```
405
142
 
406
- #### Known Limitations
143
+ > See [SPEC.md](../../docs/packages/core/SPEC.md) for complete API reference.
407
144
 
408
- 1. **No object literal construction**: You cannot create new objects with dynamic values directly in expressions.
409
- ```typescript
410
- // ❌ This does NOT work
411
- ['concat', ['get', 'data.items'], [{ id: ['get', 'input.id'], name: 'New' }]]
145
+ ---
412
146
 
413
- // Use pick/omit for existing objects, or handle in effect handlers
414
- ['pick', '$', ['id', 'name']]
415
- ```
147
+ ## Core Concepts
416
148
 
417
- 2. **No empty object literal**: `{}` is not a valid expression. Use `['coalesce']` or handle in application code.
149
+ ### Snapshot as Sole Medium
418
150
 
419
- 3. **No `find` operator**: Use `['at', ['filter', array, predicate], 0]` instead.
151
+ All communication between Core and Host happens through Snapshot. There is no hidden state, no suspended context, no continuation.
420
152
 
421
- ### Effect System
153
+ ### Deterministic Computation
422
154
 
423
- Effects describe side effects as data.
155
+ Given the same (schema, snapshot, intent), Core always produces the same result. This enables:
156
+ - Reliable testing without mocks
157
+ - Time-travel debugging
158
+ - Reproducible bug reports
424
159
 
425
- #### Effect Types
160
+ ### Effects as Declarations
426
161
 
427
- ```typescript
428
- // Set a value
429
- setValue('data.count', 10)
430
- setValue('data.count', ['+', ['get', 'data.count'], 1])
431
-
432
- // Set state
433
- setState('state.isLoading', true)
434
-
435
- // API call
436
- apiCall({
437
- method: 'POST',
438
- url: '/api/orders',
439
- body: ['get', 'data.order'],
440
- headers: { 'Content-Type': 'application/json' }
441
- })
162
+ When an action needs IO (API call, timer, etc.), Core doesn't execute it. Instead, it records an Effect as a Requirement in the snapshot. Host reads these and executes them.
442
163
 
443
- // Navigation
444
- navigate('/success')
445
-
446
- // Delay
447
- delay(1000) // milliseconds
448
-
449
- // Emit event
450
- emitEvent('orderCreated', { orderId: '123' })
451
- ```
164
+ ---
452
165
 
453
- #### Effect Composition
166
+ ## Relationship with Other Packages
454
167
 
455
- ```typescript
456
- // Sequential execution
457
- sequence([
458
- setState('state.isLoading', true),
459
- apiCall({ method: 'GET', url: '/api/data' }),
460
- setState('state.isLoading', false)
461
- ])
462
-
463
- // Parallel execution
464
- parallel([
465
- apiCall({ method: 'GET', url: '/api/user' }),
466
- apiCall({ method: 'GET', url: '/api/settings' })
467
- ])
468
-
469
- // Conditional execution
470
- conditional(
471
- ['get', 'state.isPremium'],
472
- apiCall({ method: 'GET', url: '/api/premium' }),
473
- apiCall({ method: 'GET', url: '/api/basic' })
474
- )
475
-
476
- // Error handling
477
- catchEffect(
478
- apiCall({ method: 'POST', url: '/api/submit' }),
479
- setState('state.error', ['get', 'error.message'])
480
- )
481
168
  ```
482
-
483
- #### Running Effects
484
-
485
- ```typescript
486
- import { runEffect } from '@manifesto-ai/core';
487
-
488
- const result = await runEffect(effect, runtime, {
489
- apiHandler: async (config) => {
490
- const response = await fetch(config.url, {
491
- method: config.method,
492
- body: JSON.stringify(config.body)
493
- });
494
- return response.json();
495
- }
496
- });
497
-
498
- if (isOk(result)) {
499
- console.log('Success:', result.value);
500
- } else {
501
- console.log('Error:', result.error);
502
- }
169
+ ┌─────────────┐
170
+ │ Host │ Uses Core to compute
171
+ └──────┬──────┘
172
+
173
+
174
+ ┌─────────────┐
175
+ │ CORE │
176
+ └─────────────┘
177
+
178
+
179
+ ┌─────────────┐
180
+ │ Builder │ ← Produces DomainSchema for Core
181
+ └─────────────┘
503
182
  ```
504
183
 
505
- ### Result Type
184
+ | Relationship | Package | How |
185
+ |--------------|---------|-----|
186
+ | Used by | `@manifesto-ai/host` | Host calls compute() and apply() |
187
+ | Schema from | `@manifesto-ai/builder` | Builder produces DomainSchema |
506
188
 
507
- A functional error handling type.
189
+ ---
508
190
 
509
- ```typescript
510
- import { ok, err, isOk, isErr, map, flatMap, unwrapOr } from '@manifesto-ai/core';
191
+ ## When to Use Core Directly
511
192
 
512
- // Create results
513
- const success = ok(42);
514
- const failure = err({ code: 'NOT_FOUND', message: 'Item not found' });
193
+ **Most users don't need to use Core directly.**
515
194
 
516
- // Check type
517
- if (isOk(success)) {
518
- console.log(success.value); // 42
519
- }
195
+ Use Core directly when:
196
+ - Building a custom Host implementation
197
+ - Testing domain logic in isolation
198
+ - Building developer tools (debuggers, visualizers)
520
199
 
521
- // Transform
522
- const doubled = map(success, (x) => x * 2); // ok(84)
200
+ For typical usage, see [`@manifesto-ai/react`](../react/) or [`@manifesto-ai/host`](../host/).
523
201
 
524
- // Chain operations
525
- const result = flatMap(success, (x) =>
526
- x > 0 ? ok(x) : err({ code: 'INVALID', message: 'Must be positive' })
527
- );
202
+ ---
528
203
 
529
- // Get with default
530
- const value = unwrapOr(failure, 0); // 0
531
- ```
532
-
533
- ### Schema Utilities
534
-
535
- ```typescript
536
- import {
537
- schemaToSource,
538
- validateValue,
539
- zodErrorToValidationResult,
540
- CommonSchemas
541
- } from '@manifesto-ai/core';
542
-
543
- // Common schemas
544
- CommonSchemas.email // z.string().email()
545
- CommonSchemas.phone // Phone number pattern
546
- CommonSchemas.money // Positive number with 2 decimals
547
-
548
- // Validate values
549
- const result = validateValue(userSchema, inputData);
550
- if (!result.valid) {
551
- console.log(result.issues);
552
- }
553
- ```
204
+ ## Documentation
554
205
 
555
- ## Related Packages
206
+ | Document | Purpose |
207
+ |----------|---------|
208
+ | [GUIDE.md](../../docs/packages/core/GUIDE.md) | Step-by-step usage guide |
209
+ | [SPEC.md](docs/SPEC.md) | Complete specification |
210
+ | [FDR.md](docs/FDR.md) | Design rationale |
556
211
 
557
- - [@manifesto-ai/bridge](../bridge) - Framework adapters
558
- - [@manifesto-ai/bridge-zustand](../bridge-zustand) - Zustand integration
559
- - [@manifesto-ai/bridge-react-hook-form](../bridge-react-hook-form) - React Hook Form integration
560
- - [@manifesto-ai/projection-ui](../projection-ui) - UI state projection
561
- - [@manifesto-ai/projection-agent](../projection-agent) - AI agent context
562
- - [@manifesto-ai/projection-graphql](../projection-graphql) - GraphQL schema generation
212
+ ---
563
213
 
564
214
  ## License
565
215
 
566
- MIT
216
+ [MIT](../../LICENSE)