@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.
- package/README.md +129 -499
- package/dist/core/apply.d.ts +16 -0
- package/dist/core/apply.d.ts.map +1 -0
- package/dist/core/apply.js +52 -0
- package/dist/core/apply.js.map +1 -0
- package/dist/core/compute.d.ts +17 -0
- package/dist/core/compute.d.ts.map +1 -0
- package/dist/core/compute.js +197 -0
- package/dist/core/compute.js.map +1 -0
- package/dist/core/compute.test.d.ts +2 -0
- package/dist/core/compute.test.d.ts.map +1 -0
- package/dist/core/compute.test.js +400 -0
- package/dist/core/compute.test.js.map +1 -0
- package/dist/core/explain.d.ts +14 -0
- package/dist/core/explain.d.ts.map +1 -0
- package/dist/core/explain.js +74 -0
- package/dist/core/explain.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/validate.d.ts +15 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +143 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/core/validate.test.d.ts +2 -0
- package/dist/core/validate.test.d.ts.map +1 -0
- package/dist/core/validate.test.js +450 -0
- package/dist/core/validate.test.js.map +1 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +51 -0
- package/dist/errors.js.map +1 -0
- package/dist/evaluator/computed.d.ts +14 -0
- package/dist/evaluator/computed.d.ts.map +1 -0
- package/dist/evaluator/computed.js +57 -0
- package/dist/evaluator/computed.js.map +1 -0
- package/dist/evaluator/context.d.ts +46 -0
- package/dist/evaluator/context.d.ts.map +1 -0
- package/dist/evaluator/context.js +35 -0
- package/dist/evaluator/context.js.map +1 -0
- package/dist/evaluator/dag.d.ts +30 -0
- package/dist/evaluator/dag.d.ts.map +1 -0
- package/dist/evaluator/dag.js +121 -0
- package/dist/evaluator/dag.js.map +1 -0
- package/dist/evaluator/expr.d.ts +11 -0
- package/dist/evaluator/expr.d.ts.map +1 -0
- package/dist/evaluator/expr.js +498 -0
- package/dist/evaluator/expr.js.map +1 -0
- package/dist/evaluator/expr.test.d.ts +2 -0
- package/dist/evaluator/expr.test.d.ts.map +1 -0
- package/dist/evaluator/expr.test.js +426 -0
- package/dist/evaluator/expr.test.js.map +1 -0
- package/dist/evaluator/flow.d.ts +35 -0
- package/dist/evaluator/flow.d.ts.map +1 -0
- package/dist/evaluator/flow.js +234 -0
- package/dist/evaluator/flow.js.map +1 -0
- package/dist/evaluator/flow.test.d.ts +2 -0
- package/dist/evaluator/flow.test.d.ts.map +1 -0
- package/dist/evaluator/flow.test.js +446 -0
- package/dist/evaluator/flow.test.js.map +1 -0
- package/dist/evaluator/index.d.ts +6 -0
- package/dist/evaluator/index.d.ts.map +1 -0
- package/dist/evaluator/index.js +6 -0
- package/dist/evaluator/index.js.map +1 -0
- package/dist/factories.d.ts +20 -0
- package/dist/factories.d.ts.map +1 -0
- package/dist/factories.js +43 -0
- package/dist/factories.js.map +1 -0
- package/dist/index.d.ts +46 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -45
- package/dist/index.js.map +1 -1
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +13 -0
- package/dist/index.test.js.map +1 -0
- package/dist/schema/action.d.ts +14 -0
- package/dist/schema/action.d.ts.map +1 -0
- package/dist/schema/action.js +30 -0
- package/dist/schema/action.js.map +1 -0
- package/dist/schema/common.d.ts +37 -0
- package/dist/schema/common.d.ts.map +1 -0
- package/dist/schema/common.js +20 -0
- package/dist/schema/common.js.map +1 -0
- package/dist/schema/computed.d.ts +23 -0
- package/dist/schema/computed.d.ts.map +1 -0
- package/dist/schema/computed.js +34 -0
- package/dist/schema/computed.js.map +1 -0
- package/dist/schema/domain.d.ts +46 -0
- package/dist/schema/domain.d.ts.map +1 -0
- package/dist/schema/domain.js +54 -0
- package/dist/schema/domain.js.map +1 -0
- package/dist/schema/expr.d.ts +260 -0
- package/dist/schema/expr.d.ts.map +1 -0
- package/dist/schema/expr.js +247 -0
- package/dist/schema/expr.js.map +1 -0
- package/dist/schema/field.d.ts +48 -0
- package/dist/schema/field.d.ts.map +1 -0
- package/dist/schema/field.js +31 -0
- package/dist/schema/field.js.map +1 -0
- package/dist/schema/flow.d.ts +103 -0
- package/dist/schema/flow.d.ts.map +1 -0
- package/dist/schema/flow.js +82 -0
- package/dist/schema/flow.js.map +1 -0
- package/dist/schema/index.d.ts +11 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +22 -2
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/patch.d.ts +59 -0
- package/dist/schema/patch.d.ts.map +1 -0
- package/dist/schema/patch.js +60 -0
- package/dist/schema/patch.js.map +1 -0
- package/dist/schema/result.d.ts +130 -0
- package/dist/schema/result.d.ts.map +1 -0
- package/dist/schema/result.js +90 -0
- package/dist/schema/result.js.map +1 -0
- package/dist/schema/snapshot.d.ts +151 -0
- package/dist/schema/snapshot.d.ts.map +1 -0
- package/dist/schema/snapshot.js +156 -0
- package/dist/schema/snapshot.js.map +1 -0
- package/dist/schema/trace.d.ts +87 -0
- package/dist/schema/trace.d.ts.map +1 -0
- package/dist/schema/trace.js +79 -0
- package/dist/schema/trace.js.map +1 -0
- package/dist/utils/canonical.d.ts +29 -0
- package/dist/utils/canonical.d.ts.map +1 -0
- package/dist/utils/canonical.js +56 -0
- package/dist/utils/canonical.js.map +1 -0
- package/dist/utils/canonical.test.d.ts +2 -0
- package/dist/utils/canonical.test.d.ts.map +1 -0
- package/dist/utils/canonical.test.js +153 -0
- package/dist/utils/canonical.test.js.map +1 -0
- package/dist/utils/hash.d.ts +20 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +38 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/hash.test.d.ts +2 -0
- package/dist/utils/hash.test.d.ts.map +1 -0
- package/dist/utils/hash.test.js +146 -0
- package/dist/utils/hash.test.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/path.d.ts +40 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +132 -0
- package/dist/utils/path.js.map +1 -0
- package/dist/utils/path.test.d.ts +2 -0
- package/dist/utils/path.test.d.ts.map +1 -0
- package/dist/utils/path.test.js +191 -0
- package/dist/utils/path.test.js.map +1 -0
- package/package.json +25 -39
- package/LICENSE +0 -21
- package/dist/dag/graph.d.ts +0 -62
- package/dist/dag/graph.d.ts.map +0 -1
- package/dist/dag/graph.js +0 -244
- package/dist/dag/graph.js.map +0 -1
- package/dist/dag/index.d.ts +0 -4
- package/dist/dag/index.d.ts.map +0 -1
- package/dist/dag/index.js +0 -4
- package/dist/dag/index.js.map +0 -1
- package/dist/dag/propagation.d.ts +0 -58
- package/dist/dag/propagation.d.ts.map +0 -1
- package/dist/dag/propagation.js +0 -224
- package/dist/dag/propagation.js.map +0 -1
- package/dist/dag/topological.d.ts +0 -33
- package/dist/dag/topological.d.ts.map +0 -1
- package/dist/dag/topological.js +0 -173
- package/dist/dag/topological.js.map +0 -1
- package/dist/domain/define.d.ts +0 -82
- package/dist/domain/define.d.ts.map +0 -1
- package/dist/domain/define.js +0 -105
- package/dist/domain/define.js.map +0 -1
- package/dist/domain/index.d.ts +0 -4
- package/dist/domain/index.d.ts.map +0 -1
- package/dist/domain/index.js +0 -4
- package/dist/domain/index.js.map +0 -1
- package/dist/domain/types.d.ts +0 -203
- package/dist/domain/types.d.ts.map +0 -1
- package/dist/domain/types.js +0 -2
- package/dist/domain/types.js.map +0 -1
- package/dist/domain/validate.d.ts +0 -17
- package/dist/domain/validate.d.ts.map +0 -1
- package/dist/domain/validate.js +0 -204
- package/dist/domain/validate.js.map +0 -1
- package/dist/effect/index.d.ts +0 -4
- package/dist/effect/index.d.ts.map +0 -1
- package/dist/effect/index.js +0 -4
- package/dist/effect/index.js.map +0 -1
- package/dist/effect/result.d.ts +0 -100
- package/dist/effect/result.d.ts.map +0 -1
- package/dist/effect/result.js +0 -163
- package/dist/effect/result.js.map +0 -1
- package/dist/effect/runner.d.ts +0 -98
- package/dist/effect/runner.d.ts.map +0 -1
- package/dist/effect/runner.js +0 -321
- package/dist/effect/runner.js.map +0 -1
- package/dist/effect/types.d.ts +0 -169
- package/dist/effect/types.d.ts.map +0 -1
- package/dist/effect/types.js +0 -28
- package/dist/effect/types.js.map +0 -1
- package/dist/expression/analyzer.d.ts +0 -42
- package/dist/expression/analyzer.d.ts.map +0 -1
- package/dist/expression/analyzer.js +0 -166
- package/dist/expression/analyzer.js.map +0 -1
- package/dist/expression/evaluator.d.ts +0 -16
- package/dist/expression/evaluator.d.ts.map +0 -1
- package/dist/expression/evaluator.js +0 -382
- package/dist/expression/evaluator.js.map +0 -1
- package/dist/expression/index.d.ts +0 -5
- package/dist/expression/index.d.ts.map +0 -1
- package/dist/expression/index.js +0 -5
- package/dist/expression/index.js.map +0 -1
- package/dist/expression/parser.d.ts +0 -37
- package/dist/expression/parser.d.ts.map +0 -1
- package/dist/expression/parser.js +0 -201
- package/dist/expression/parser.js.map +0 -1
- package/dist/expression/types.d.ts +0 -123
- package/dist/expression/types.d.ts.map +0 -1
- package/dist/expression/types.js +0 -10
- package/dist/expression/types.js.map +0 -1
- package/dist/policy/field-policy.d.ts +0 -63
- package/dist/policy/field-policy.d.ts.map +0 -1
- package/dist/policy/field-policy.js +0 -138
- package/dist/policy/field-policy.js.map +0 -1
- package/dist/policy/index.d.ts +0 -3
- package/dist/policy/index.d.ts.map +0 -1
- package/dist/policy/index.js +0 -3
- package/dist/policy/index.js.map +0 -1
- package/dist/policy/precondition.d.ts +0 -58
- package/dist/policy/precondition.d.ts.map +0 -1
- package/dist/policy/precondition.js +0 -115
- package/dist/policy/precondition.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -4
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js +0 -4
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/runtime.d.ts +0 -94
- package/dist/runtime/runtime.d.ts.map +0 -1
- package/dist/runtime/runtime.js +0 -294
- package/dist/runtime/runtime.js.map +0 -1
- package/dist/runtime/snapshot.d.ts +0 -39
- package/dist/runtime/snapshot.d.ts.map +0 -1
- package/dist/runtime/snapshot.js +0 -264
- package/dist/runtime/snapshot.js.map +0 -1
- package/dist/runtime/subscription.d.ts +0 -82
- package/dist/runtime/subscription.d.ts.map +0 -1
- package/dist/runtime/subscription.js +0 -222
- package/dist/runtime/subscription.js.map +0 -1
- package/dist/schema/integration.d.ts +0 -89
- package/dist/schema/integration.d.ts.map +0 -1
- package/dist/schema/integration.js +0 -171
- package/dist/schema/integration.js.map +0 -1
- package/dist/schema/validation.d.ts +0 -51
- package/dist/schema/validation.d.ts.map +0 -1
- package/dist/schema/validation.js +0 -212
- package/dist/schema/validation.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,566 +1,196 @@
|
|
|
1
1
|
# @manifesto-ai/core
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **Core** is the pure semantic calculator of Manifesto. It computes state transitions deterministically with no side effects.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## What is Core?
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
|
|
11
|
+
In the Manifesto architecture:
|
|
16
12
|
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
20
|
+
---
|
|
110
21
|
|
|
111
|
-
|
|
22
|
+
## What Core Does
|
|
112
23
|
|
|
113
|
-
|
|
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
|
-
|
|
31
|
+
---
|
|
116
32
|
|
|
117
|
-
|
|
33
|
+
## What Core Does NOT Do
|
|
118
34
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
43
|
+
---
|
|
138
44
|
|
|
139
|
-
|
|
45
|
+
## Installation
|
|
140
46
|
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
53
|
+
---
|
|
156
54
|
|
|
157
|
-
|
|
55
|
+
## Quick Example
|
|
158
56
|
|
|
159
57
|
```typescript
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
61
|
+
// Create core instance
|
|
62
|
+
const core = createCore();
|
|
174
63
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
271
|
-
|
|
82
|
+
// Create initial snapshot
|
|
83
|
+
const snapshot = createSnapshot(schema);
|
|
272
84
|
|
|
273
|
-
//
|
|
274
|
-
const
|
|
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
|
-
|
|
88
|
+
// Compute result (pure, deterministic)
|
|
89
|
+
const result = await core.compute(schema, snapshot, intent);
|
|
314
90
|
|
|
315
|
-
|
|
316
|
-
|
|
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
|
-
|
|
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
|
-
|
|
97
|
+
---
|
|
377
98
|
|
|
378
|
-
|
|
379
|
-
['pick', object, ['key1', 'key2']] // Pick specific keys
|
|
380
|
-
['omit', object, ['key1', 'key2']] // Omit specific keys
|
|
381
|
-
```
|
|
99
|
+
## Core API
|
|
382
100
|
|
|
383
|
-
|
|
101
|
+
### Main Exports
|
|
384
102
|
|
|
385
103
|
```typescript
|
|
386
|
-
//
|
|
387
|
-
|
|
104
|
+
// Factory
|
|
105
|
+
function createCore(): ManifestoCore;
|
|
388
106
|
|
|
389
|
-
//
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
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
|
-
//
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
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
|
-
|
|
123
|
+
> See [SPEC.md](../../docs/packages/core/SPEC.md) for complete API reference.
|
|
407
124
|
|
|
408
|
-
|
|
409
|
-
```typescript
|
|
410
|
-
// ❌ This does NOT work
|
|
411
|
-
['concat', ['get', 'data.items'], [{ id: ['get', 'input.id'], name: 'New' }]]
|
|
125
|
+
---
|
|
412
126
|
|
|
413
|
-
|
|
414
|
-
['pick', '$', ['id', 'name']]
|
|
415
|
-
```
|
|
127
|
+
## Core Concepts
|
|
416
128
|
|
|
417
|
-
|
|
129
|
+
### Snapshot as Sole Medium
|
|
418
130
|
|
|
419
|
-
|
|
131
|
+
All communication between Core and Host happens through Snapshot. There is no hidden state, no suspended context, no continuation.
|
|
420
132
|
|
|
421
|
-
###
|
|
133
|
+
### Deterministic Computation
|
|
422
134
|
|
|
423
|
-
|
|
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
|
-
|
|
140
|
+
### Effects as Declarations
|
|
426
141
|
|
|
427
|
-
|
|
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
|
-
|
|
444
|
-
navigate('/success')
|
|
445
|
-
|
|
446
|
-
// Delay
|
|
447
|
-
delay(1000) // milliseconds
|
|
448
|
-
|
|
449
|
-
// Emit event
|
|
450
|
-
emitEvent('orderCreated', { orderId: '123' })
|
|
451
|
-
```
|
|
144
|
+
---
|
|
452
145
|
|
|
453
|
-
|
|
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
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
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
|
-
|
|
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
|
-
|
|
169
|
+
---
|
|
508
170
|
|
|
509
|
-
|
|
510
|
-
import { ok, err, isOk, isErr, map, flatMap, unwrapOr } from '@manifesto-ai/core';
|
|
171
|
+
## When to Use Core Directly
|
|
511
172
|
|
|
512
|
-
|
|
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
|
-
|
|
517
|
-
|
|
518
|
-
|
|
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
|
-
|
|
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
|
-
|
|
525
|
-
const result = flatMap(success, (x) =>
|
|
526
|
-
x > 0 ? ok(x) : err({ code: 'INVALID', message: 'Must be positive' })
|
|
527
|
-
);
|
|
182
|
+
---
|
|
528
183
|
|
|
529
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|