@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
package/README.md CHANGED
@@ -1,566 +1,196 @@
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
7
+ ## What is Core?
8
8
 
9
- ```bash
10
- pnpm add @manifesto-ai/core
11
- # or
12
- npm install @manifesto-ai/core
13
- ```
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.
14
10
 
15
- ## Quick Start
11
+ In the Manifesto architecture:
16
12
 
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
- },
53
-
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
- ```
58
+ import { createCore, createSnapshot, createIntent } from "@manifesto-ai/core";
59
+ import type { DomainSchema } from "@manifesto-ai/core";
172
60
 
173
- #### `defineAsync(options)`
61
+ // Create core instance
62
+ const core = createCore();
174
63
 
175
- Defines an async data source with result paths.
176
-
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
+ version: "1.0.0",
67
+ state: {
68
+ count: { type: "number", default: 0 },
69
+ },
70
+ actions: {
71
+ increment: {
72
+ flow: {
73
+ kind: "patch",
74
+ op: "set",
75
+ path: "/data/count",
76
+ value: { kind: "add", left: { kind: "get", path: "/data/count" }, right: 1 },
77
+ },
189
78
  },
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
- })
79
+ },
225
80
  };
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
-
263
- // Get current snapshot
264
- const snapshot = runtime.getSnapshot();
265
-
266
- // Check action availability
267
- const canSubmit = runtime.checkAction('submit');
268
- // { available: true, reason: null }
269
81
 
270
- // Execute an action
271
- await runtime.executeAction('submit', { orderId: '123' });
82
+ // Create initial snapshot
83
+ const snapshot = createSnapshot(schema);
272
84
 
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
282
-
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
292
- ```
293
-
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
- ```
304
-
305
- #### Logical Operators
306
-
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
- ```
85
+ // Create intent
86
+ const intent = createIntent("increment");
312
87
 
313
- #### Arithmetic Operators
88
+ // Compute result (pure, deterministic)
89
+ const result = await core.compute(schema, snapshot, intent);
314
90
 
315
- ```typescript
316
- ['+', a, b] // a + b
317
- ['-', a, b] // a - b
318
- ['*', a, b] // a * b
319
- ```
320
-
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
91
+ console.log(result.status); // → "completed"
92
+ console.log(result.snapshot.data.count); // 1
328
93
  ```
329
94
 
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
- ```
95
+ > See [GUIDE.md](../../docs/packages/core/GUIDE.md) for the full tutorial.
375
96
 
376
- #### Object Operations
97
+ ---
377
98
 
378
- ```typescript
379
- ['pick', object, ['key1', 'key2']] // Pick specific keys
380
- ['omit', object, ['key1', 'key2']] // Omit specific keys
381
- ```
99
+ ## Core API
382
100
 
383
- #### Examples
101
+ ### Main Exports
384
102
 
385
103
  ```typescript
386
- // Filter active todos
387
- ['filter', ['get', 'data.items'], ['!', '$.completed']]
104
+ // Factory
105
+ function createCore(): ManifestoCore;
388
106
 
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']]
107
+ // Core interface
108
+ interface ManifestoCore {
109
+ compute(schema, snapshot, intent): Promise<ComputeResult>;
110
+ apply(schema, snapshot, patches): Snapshot;
111
+ validate(schema): ValidationResult;
112
+ explain(schema, snapshot, path): ExplainResult;
113
+ }
397
114
 
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
- ]
115
+ // Key types
116
+ type DomainSchema = { version, state, computed?, actions?, flows?, meta? };
117
+ type Snapshot = { data, computed, system, input, meta };
118
+ type Intent = { type, input?, intentId };
119
+ type Patch = { op: "set" | "unset" | "merge", path, value? };
120
+ type ComputeResult = { status, snapshot, patches, requirements, trace };
404
121
  ```
405
122
 
406
- #### Known Limitations
123
+ > See [SPEC.md](../../docs/packages/core/SPEC.md) for complete API reference.
407
124
 
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' }]]
125
+ ---
412
126
 
413
- // Use pick/omit for existing objects, or handle in effect handlers
414
- ['pick', '$', ['id', 'name']]
415
- ```
127
+ ## Core Concepts
416
128
 
417
- 2. **No empty object literal**: `{}` is not a valid expression. Use `['coalesce']` or handle in application code.
129
+ ### Snapshot as Sole Medium
418
130
 
419
- 3. **No `find` operator**: Use `['at', ['filter', array, predicate], 0]` instead.
131
+ All communication between Core and Host happens through Snapshot. There is no hidden state, no suspended context, no continuation.
420
132
 
421
- ### Effect System
133
+ ### Deterministic Computation
422
134
 
423
- Effects describe side effects as data.
135
+ Given the same (schema, snapshot, intent), Core always produces the same result. This enables:
136
+ - Reliable testing without mocks
137
+ - Time-travel debugging
138
+ - Reproducible bug reports
424
139
 
425
- #### Effect Types
140
+ ### Effects as Declarations
426
141
 
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
- })
142
+ 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
143
 
443
- // Navigation
444
- navigate('/success')
445
-
446
- // Delay
447
- delay(1000) // milliseconds
448
-
449
- // Emit event
450
- emitEvent('orderCreated', { orderId: '123' })
451
- ```
144
+ ---
452
145
 
453
- #### Effect Composition
146
+ ## Relationship with Other Packages
454
147
 
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
148
  ```
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
- }
149
+ ┌─────────────┐
150
+ │ Host │ Uses Core to compute
151
+ └──────┬──────┘
152
+
153
+
154
+ ┌─────────────┐
155
+ │ CORE │
156
+ └─────────────┘
157
+
158
+
159
+ ┌─────────────┐
160
+ │ Builder │ ← Produces DomainSchema for Core
161
+ └─────────────┘
503
162
  ```
504
163
 
505
- ### Result Type
164
+ | Relationship | Package | How |
165
+ |--------------|---------|-----|
166
+ | Used by | `@manifesto-ai/host` | Host calls compute() and apply() |
167
+ | Schema from | `@manifesto-ai/builder` | Builder produces DomainSchema |
506
168
 
507
- A functional error handling type.
169
+ ---
508
170
 
509
- ```typescript
510
- import { ok, err, isOk, isErr, map, flatMap, unwrapOr } from '@manifesto-ai/core';
171
+ ## When to Use Core Directly
511
172
 
512
- // Create results
513
- const success = ok(42);
514
- const failure = err({ code: 'NOT_FOUND', message: 'Item not found' });
173
+ **Most users don't need to use Core directly.**
515
174
 
516
- // Check type
517
- if (isOk(success)) {
518
- console.log(success.value); // 42
519
- }
175
+ Use Core directly when:
176
+ - Building a custom Host implementation
177
+ - Testing domain logic in isolation
178
+ - Building developer tools (debuggers, visualizers)
520
179
 
521
- // Transform
522
- const doubled = map(success, (x) => x * 2); // ok(84)
180
+ For typical usage, see [`@manifesto-ai/react`](../react/) or [`@manifesto-ai/host`](../host/).
523
181
 
524
- // Chain operations
525
- const result = flatMap(success, (x) =>
526
- x > 0 ? ok(x) : err({ code: 'INVALID', message: 'Must be positive' })
527
- );
182
+ ---
528
183
 
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
- ```
184
+ ## Documentation
554
185
 
555
- ## Related Packages
186
+ | Document | Purpose |
187
+ |----------|---------|
188
+ | [GUIDE.md](../../docs/packages/core/GUIDE.md) | Step-by-step usage guide |
189
+ | [SPEC.md](../../docs/packages/core/SPEC.md) | Complete specification |
190
+ | [FDR.md](../../docs/packages/core/FDR.md) | Design rationale |
556
191
 
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
192
+ ---
563
193
 
564
194
  ## License
565
195
 
566
- MIT
196
+ [MIT](../../LICENSE)