@manifesto-ai/sdk 1.2.0 → 2.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 (46) hide show
  1. package/README.md +60 -34
  2. package/dist/index.d.ts +413 -20
  3. package/dist/index.js +587 -48
  4. package/dist/index.js.map +1 -1
  5. package/package.json +10 -9
  6. package/dist/__tests__/bootstrap.test.d.ts +0 -2
  7. package/dist/__tests__/bootstrap.test.d.ts.map +0 -1
  8. package/dist/__tests__/bootstrap.test.js +0 -33
  9. package/dist/__tests__/bootstrap.test.js.map +0 -1
  10. package/dist/__tests__/public-exports.test.d.ts +0 -2
  11. package/dist/__tests__/public-exports.test.d.ts.map +0 -1
  12. package/dist/__tests__/public-exports.test.js +0 -58
  13. package/dist/__tests__/public-exports.test.js.map +0 -1
  14. package/dist/app.d.ts +0 -51
  15. package/dist/app.d.ts.map +0 -1
  16. package/dist/app.js +0 -170
  17. package/dist/app.js.map +0 -1
  18. package/dist/create-app.d.ts +0 -52
  19. package/dist/create-app.d.ts.map +0 -1
  20. package/dist/create-app.js +0 -94
  21. package/dist/create-app.js.map +0 -1
  22. package/dist/hooks/app-ref.d.ts +0 -71
  23. package/dist/hooks/app-ref.d.ts.map +0 -1
  24. package/dist/hooks/app-ref.js +0 -82
  25. package/dist/hooks/app-ref.js.map +0 -1
  26. package/dist/hooks/context.d.ts +0 -22
  27. package/dist/hooks/context.d.ts.map +0 -1
  28. package/dist/hooks/context.js +0 -26
  29. package/dist/hooks/context.js.map +0 -1
  30. package/dist/hooks/hookable.d.ts +0 -79
  31. package/dist/hooks/hookable.d.ts.map +0 -1
  32. package/dist/hooks/hookable.js +0 -137
  33. package/dist/hooks/hookable.js.map +0 -1
  34. package/dist/hooks/index.d.ts +0 -14
  35. package/dist/hooks/index.d.ts.map +0 -1
  36. package/dist/hooks/index.js +0 -13
  37. package/dist/hooks/index.js.map +0 -1
  38. package/dist/hooks/queue.d.ts +0 -57
  39. package/dist/hooks/queue.d.ts.map +0 -1
  40. package/dist/hooks/queue.js +0 -141
  41. package/dist/hooks/queue.js.map +0 -1
  42. package/dist/index.d.ts.map +0 -1
  43. package/dist/manifest.d.ts +0 -10
  44. package/dist/manifest.d.ts.map +0 -1
  45. package/dist/manifest.js +0 -2
  46. package/dist/manifest.js.map +0 -1
package/README.md CHANGED
@@ -1,27 +1,27 @@
1
1
  # @manifesto-ai/sdk
2
2
 
3
- > **SDK** is the canonical public developer API for Manifesto applications.
3
+ > Thin public composition layer for the Manifesto protocol stack.
4
4
 
5
5
  ---
6
6
 
7
7
  ## Overview
8
8
 
9
- SDK owns the public contract for app creation and interaction.
10
- It provides `createApp()`, `createTestApp()`, `ManifestoApp`, and the hook primitives while delegating orchestration to Runtime.
9
+ `@manifesto-ai/sdk` is the canonical entry point for new Manifesto integrations.
11
10
 
12
11
  ```text
13
12
  Application Code
14
13
  |
15
14
  v
16
- SDK (createApp, App, Hooks)
15
+ SDK (createManifesto, defineOps, re-exports)
17
16
  |
18
17
  v
19
- Runtime (orchestration)
20
- |
21
- v
22
- Core / Host / World
18
+ Compiler / Host / Core
19
+ +
20
+ optional World integration
23
21
  ```
24
22
 
23
+ The SDK owns exactly one concept: `createManifesto()`. Everything else is either a small SDK utility (`defineOps`) or a re-export from protocol packages. Legacy app-package facade APIs are retired in v1.0.0. Governance and lineage remain explicit integrations through `@manifesto-ai/world`.
24
+
25
25
  ---
26
26
 
27
27
  ## Installation
@@ -35,42 +35,61 @@ pnpm add @manifesto-ai/sdk
35
35
  ## Quick Example
36
36
 
37
37
  ```typescript
38
- import { createApp } from "@manifesto-ai/sdk";
38
+ import { createManifesto, createIntent } from "@manifesto-ai/sdk";
39
39
 
40
- const app = createApp({
40
+ const manifesto = createManifesto({
41
41
  schema: counterSchema,
42
- effects: {
43
- "api.save": async (params) => [
44
- { op: "set", path: "data.savedAt", value: params.timestamp },
45
- ],
46
- },
42
+ effects: {},
47
43
  });
48
44
 
49
- await app.ready();
50
- await app.act("increment").done();
51
- console.log(app.getState().data.count);
45
+ manifesto.on("dispatch:completed", ({ snapshot }) => {
46
+ console.log(snapshot?.data.count);
47
+ });
48
+
49
+ manifesto.dispatch(createIntent("increment", "intent-1"));
52
50
  ```
53
51
 
54
52
  ---
55
53
 
56
54
  ## Main Exports
57
55
 
58
- ### Factory
56
+ ### SDK-Owned
57
+
58
+ ```typescript
59
+ function createManifesto(config: ManifestoConfig): ManifestoInstance;
60
+ function defineOps<TData>(): TypedOps<TData>;
61
+ ```
62
+
63
+ ### ManifestoInstance
59
64
 
60
65
  ```typescript
61
- function createApp(config: AppConfig): App;
62
- function createTestApp(domain: DomainSchema | string, opts?: Partial<AppConfig>): App;
66
+ interface ManifestoInstance {
67
+ dispatch(intent: Intent): void;
68
+ subscribe(selector, listener): Unsubscribe;
69
+ on(event, handler): Unsubscribe;
70
+ getSnapshot(): Snapshot;
71
+ dispose(): void;
72
+ }
63
73
  ```
64
74
 
65
- ### Class
75
+ ### Event Channel
66
76
 
67
77
  ```typescript
68
- class ManifestoApp implements App { /* ... */ }
78
+ type ManifestoEvent =
79
+ | "dispatch:completed"
80
+ | "dispatch:rejected"
81
+ | "dispatch:failed";
69
82
  ```
70
83
 
71
- ### Runtime-Reexported Public Types/Errors
84
+ `dispatch()` is enqueue-only. Observe results through `subscribe()` for state changes or `on()` for per-intent telemetry.
72
85
 
73
- SDK re-exports public contract types and errors (for example `AppConfig`, `AppState`, `ActionHandle`, `AppNotReadyError`).
86
+ ### Re-Exported Protocol Surface
87
+
88
+ SDK re-exports selected protocol types and factories from:
89
+
90
+ - `@manifesto-ai/core`
91
+ - `@manifesto-ai/world`
92
+ - `@manifesto-ai/host` (types)
74
93
 
75
94
  ---
76
95
 
@@ -78,27 +97,34 @@ SDK re-exports public contract types and errors (for example `AppConfig`, `AppSt
78
97
 
79
98
  | Relationship | Package | How |
80
99
  |--------------|---------|-----|
81
- | Delegates to | `@manifesto-ai/runtime` | All orchestration via runtime pipeline |
82
100
  | Uses | `@manifesto-ai/core` | Schema and expression types |
83
- | Uses | `@manifesto-ai/world` | World protocol types |
84
- | Legacy predecessor | App facade package | Removed in R2 (see API retirement record) |
101
+ | Uses | `@manifesto-ai/host` | Effect execution and compute loop |
102
+ | Re-exports | `@manifesto-ai/world` | World protocol types and store factory for explicit governance integration |
103
+ | Uses | `@manifesto-ai/compiler` | MEL → DomainSchema compilation |
104
+ | Retired predecessor | `@manifesto-ai/runtime` | Absorbed into `createManifesto()` per ADR-010 |
85
105
 
86
106
  ---
87
107
 
88
- ## Migration from Legacy App Facade
108
+ ## Migration Notes
109
+
110
+ Older app-package code usually maps to three current patterns:
89
111
 
90
- Legacy app-facade imports should be replaced with `@manifesto-ai/sdk`.
112
+ - use `createManifesto({ schema, effects })` as the public entry point
113
+ - create intents explicitly with `createIntent(...)`
114
+ - treat `dispatch()` as enqueue-only and observe completion through `dispatch:*` events or a small `dispatchAsync()` helper
91
115
 
92
- For automated rewrite guidance, see:
93
- - [docs/guides/migrate-app-to-sdk.md](../../docs/guides/migrate-app-to-sdk.md)
116
+ For migration details, see:
117
+ - [Migrate App to SDK](../../docs/guides/migrate-app-to-sdk.md)
118
+ - [sdk-SPEC-v1.0.0.md](docs/sdk-SPEC-v1.0.0.md)
119
+ - [ADR-010](../../docs/internals/adr/010-major-hard-cut.md)
94
120
 
95
121
  ---
96
122
 
97
123
  ## Documentation
98
124
 
99
- - [sdk-SPEC-v0.1.0.md](docs/sdk-SPEC-v0.1.0.md)
125
+ - [sdk-SPEC-v1.0.0.md](docs/sdk-SPEC-v1.0.0.md)
100
126
  - [VERSION-INDEX.md](docs/VERSION-INDEX.md)
101
- - [ADR-008](../../docs/internals/adr/008-sdk-first-transition-and-app-retirement.md)
127
+ - [ADR-010](../../docs/internals/adr/010-major-hard-cut.md)
102
128
 
103
129
  ---
104
130
 
package/dist/index.d.ts CHANGED
@@ -1,21 +1,414 @@
1
+ import { DomainSchema, Snapshot as Snapshot$1, Patch, Intent, SetPatch, UnsetPatch, MergePatch } from '@manifesto-ai/core';
2
+ export { ComputeResult, Snapshot as CoreSnapshot, DomainSchema, ErrorValue, Intent, MergePatch, Patch, Requirement, SetPatch, TraceGraph, UnsetPatch, createCore, createIntent, createSnapshot } from '@manifesto-ai/core';
3
+ export { HostOptions, HostResult } from '@manifesto-ai/host';
4
+ export { WorldStore, createMemoryWorldStore } from '@manifesto-ai/world';
5
+
1
6
  /**
2
- * @manifesto-ai/sdk v1.0.0
3
- *
4
- * Public developer API layer for the Manifesto protocol stack.
5
- * Canonical entry point since Phase 2 (ADR-008).
6
- *
7
- * @see sdk-SPEC-v0.1.0.md
8
- * @packageDocumentation
9
- */
10
- export type { SdkManifest } from './manifest.js';
11
- export type { AppStatus, RuntimeKind, Unsubscribe, ActionPhase, ActionResult, CompletedActionResult, RejectedActionResult, FailedActionResult, PreparationFailedActionResult, ExecutionStats, ActionUpdate, ActionUpdateDetail, ActorPolicyConfig, SystemActionsConfig, DisposeOptions, DoneOptions, ActOptions, ForkOptions, SessionOptions, SubscribeOptions, LineageOptions, AppState, SystemState, SnapshotMeta, MemoryHubConfig, BackfillConfig, RecallRequest, RecallResult, MemoryMaintenanceOptions, MigrationLink, MigrationContext, MigrationFn, App, ActionHandle, Branch, Session, MemoryFacade, SystemFacade, SystemMemoryFacade, Hookable, HookContext, EnqueueOptions, AppPlugin, AppHooks, MemoryProvider, MemoryVerifier, MemoryIngestEntry, MemorySelectionView, ProveResult, Requirement, AppConfig, AppRef, Proposal, ProposalResult, ExecutionKey, ExecutionKeyPolicy, ProposalId, ActorId, BranchId, ApprovedScope, AuthorityDecision, PolicyService, ArtifactRef, Intent, SchemaCompatibilityResult, MemoryStore, StoredMemoryRecord, MemoryRecordInput, MemoryFilter, World, WorldId, Snapshot, Patch, WorldHead, Effects, AppEffectContext, EffectHandler, ErrorValue, MelText, } from '@manifesto-ai/runtime';
12
- export { ManifestoAppError, AppNotReadyError, AppDisposedError, ActionRejectedError, ActionFailedError, ActionPreparationError, ActionTimeoutError, ActionNotFoundError, HandleDetachedError, HookMutationError, ReservedEffectTypeError, SystemActionDisabledError, SystemActionRoutingError, MemoryDisabledError, BranchNotFoundError, WorldNotFoundError, WorldSchemaHashMismatchError, WorldNotInLineageError, ReservedNamespaceError, MissingDefaultActorError, DomainCompileError, PluginInitError, SchemaMismatchOnResumeError, BranchHeadNotFoundError, } from '@manifesto-ai/runtime';
13
- export { createApp, createTestApp } from './create-app.js';
14
- export { ManifestoApp } from './app.js';
15
- export { AppRefImpl, createAppRef } from './hooks/index.js';
16
- export type { AppRefCallbacks } from './hooks/index.js';
17
- export { HookableImpl } from './hooks/index.js';
18
- export type { HookState } from './hooks/index.js';
19
- export { JobQueue } from './hooks/index.js';
20
- export { HookContextImpl, createHookContext } from './hooks/index.js';
21
- //# sourceMappingURL=index.d.ts.map
7
+ * SDK package identity and SPEC version metadata.
8
+ * Used for phase tracking and compatibility verification.
9
+ */
10
+ type SdkManifest = {
11
+ readonly name: '@manifesto-ai/sdk';
12
+ readonly specVersion: '1.0.0';
13
+ readonly phase: 'released';
14
+ };
15
+
16
+ /**
17
+ * SDK v1.0.0 Public Types
18
+ *
19
+ * Defines ManifestoInstance, ManifestoConfig, event types, and supporting types.
20
+ *
21
+ * @see SDK SPEC v1.0.0 §6–8
22
+ * @module
23
+ */
24
+
25
+ /**
26
+ * Typed Snapshot with generic data shape.
27
+ *
28
+ * Core's Snapshot uses `data: unknown`. This overlay provides type-safe
29
+ * access to domain data via the generic parameter T.
30
+ *
31
+ * @see SDK SPEC v1.0.0 §6.1
32
+ */
33
+ type Snapshot<T = unknown> = Omit<Snapshot$1, "data"> & {
34
+ data: T;
35
+ };
36
+ /**
37
+ * Context provided to effect handlers.
38
+ *
39
+ * Simplified from Host's EffectContext (2-param contract).
40
+ */
41
+ type EffectContext<T = unknown> = {
42
+ /** Current snapshot (read-only). */
43
+ readonly snapshot: Readonly<Snapshot<T>>;
44
+ };
45
+ /**
46
+ * SDK-level effect handler.
47
+ *
48
+ * Users provide this simplified 2-param handler; SDK adapts it
49
+ * to Host's 3-param EffectHandler internally.
50
+ */
51
+ type EffectHandler = (params: unknown, ctx: EffectContext) => Promise<readonly Patch[]>;
52
+ /**
53
+ * Configuration for createManifesto().
54
+ *
55
+ * @see SDK SPEC v1.0.0 §7
56
+ */
57
+ interface ManifestoConfig<T = unknown> {
58
+ /**
59
+ * Required: Domain schema defining state, computed, actions.
60
+ * Accepts either a compiled DomainSchema or MEL text string.
61
+ *
62
+ * @see SDK-CONFIG-1
63
+ */
64
+ schema: DomainSchema | string;
65
+ /**
66
+ * Required: Effect handlers keyed by effect type.
67
+ *
68
+ * @see SDK-CONFIG-2
69
+ */
70
+ effects: Record<string, EffectHandler>;
71
+ /**
72
+ * Optional: Guard function for intent validation.
73
+ */
74
+ guard?: (intent: Intent, snapshot: Snapshot<T>) => boolean;
75
+ /**
76
+ * Optional: Restore from persisted snapshot.
77
+ */
78
+ snapshot?: Snapshot<T>;
79
+ }
80
+ /**
81
+ * Selector function — projects a value from the typed snapshot.
82
+ */
83
+ type Selector<T, R> = (snapshot: Snapshot<T>) => R;
84
+ /**
85
+ * Unsubscribe function returned by subscribe() and on().
86
+ */
87
+ type Unsubscribe = () => void;
88
+ /**
89
+ * ManifestoInstance — the sole runtime handle returned by createManifesto().
90
+ *
91
+ * 5 methods, no more.
92
+ *
93
+ * @see SDK SPEC v1.0.0 §6
94
+ */
95
+ interface ManifestoInstance<T = unknown> {
96
+ /**
97
+ * Fire-and-forget intent dispatch.
98
+ *
99
+ * Enqueues the intent for serial processing. Returns immediately.
100
+ *
101
+ * @throws DisposedError if instance is disposed (SDK-DISPATCH-4)
102
+ * @see SDK-DISPATCH-1, SDK-DISPATCH-2, SDK-DISPATCH-3
103
+ */
104
+ dispatch(intent: Intent): void;
105
+ /**
106
+ * Subscribe to state changes via selector.
107
+ *
108
+ * Fires only at terminal snapshot, at most once per intent.
109
+ *
110
+ * @see SDK-SUB-1, SDK-SUB-2, SDK-SUB-3, SDK-SUB-4
111
+ */
112
+ subscribe<R>(selector: Selector<T, R>, listener: (value: R) => void): Unsubscribe;
113
+ /**
114
+ * Listen to intent lifecycle events (telemetry channel).
115
+ *
116
+ * Payload type is narrowed by event name.
117
+ *
118
+ * @see SDK-EVENT-1, SDK-EVENT-2, SDK-EVENT-3
119
+ */
120
+ on<K extends ManifestoEvent>(event: K, handler: (payload: ManifestoEventMap<T>[K]) => void): Unsubscribe;
121
+ /**
122
+ * Get the current snapshot synchronously.
123
+ *
124
+ * @see SDK-SNAP-1
125
+ */
126
+ getSnapshot(): Snapshot<T>;
127
+ /**
128
+ * Dispose the instance and release resources.
129
+ *
130
+ * @see SDK-DISPOSE-1, SDK-DISPOSE-2, SDK-DISPOSE-3
131
+ */
132
+ dispose(): void;
133
+ }
134
+ /**
135
+ * Typed event map — payload narrowed by event name.
136
+ *
137
+ * @see SDK SPEC v1.0.0 §8
138
+ */
139
+ interface ManifestoEventMap<T = unknown> {
140
+ "dispatch:completed": {
141
+ intentId: string;
142
+ intent: Intent;
143
+ snapshot: Snapshot<T>;
144
+ };
145
+ "dispatch:rejected": {
146
+ intentId: string;
147
+ intent: Intent;
148
+ reason: string;
149
+ };
150
+ "dispatch:failed": {
151
+ intentId: string;
152
+ intent: Intent;
153
+ error: Error;
154
+ };
155
+ }
156
+ /**
157
+ * Telemetry event types for the `on()` channel.
158
+ *
159
+ * @see SDK SPEC v1.0.0 §8
160
+ */
161
+ type ManifestoEvent = keyof ManifestoEventMap;
162
+ /**
163
+ * Union of all event payloads (for backward compatibility).
164
+ *
165
+ * Prefer using `ManifestoEventMap<T>[K]` with typed `on()` instead.
166
+ *
167
+ * @see SDK-INV-6 — intentId is always present
168
+ */
169
+ type ManifestoEventPayload<T = unknown> = ManifestoEventMap<T>[ManifestoEvent];
170
+
171
+ /**
172
+ * createManifesto() Factory
173
+ *
174
+ * The sole SDK-owned concept. Creates a ManifestoInstance that composes
175
+ * the four protocol axes (Core, Host, World, Compiler) into a single handle.
176
+ *
177
+ * @see SDK SPEC v1.0.0 §5
178
+ * @see ADR-010
179
+ * @module
180
+ */
181
+
182
+ /**
183
+ * Create a ManifestoInstance.
184
+ *
185
+ * This is the sole entry point for SDK consumers. It composes the protocol
186
+ * axes (Core via Host, Host, World, Compiler) into a single handle with
187
+ * 5 methods: dispatch, subscribe, on, getSnapshot, dispose.
188
+ *
189
+ * @see SDK-FACTORY-1 through SDK-FACTORY-5
190
+ * @see SDK-INV-1 through SDK-INV-6
191
+ */
192
+ declare function createManifesto<T = unknown>(config: ManifestoConfig<T>): ManifestoInstance<T>;
193
+
194
+ /**
195
+ * dispatchAsync() — Non-normative convenience utility
196
+ *
197
+ * Promise-based wrapper around dispatch() + on().
198
+ * Resolves when the intent reaches a terminal state.
199
+ *
200
+ * @see SDK SPEC v1.0.0 §14.3
201
+ * @module
202
+ */
203
+
204
+ /**
205
+ * Error thrown when an intent is rejected by a guard.
206
+ */
207
+ declare class DispatchRejectedError extends Error {
208
+ readonly code = "DISPATCH_REJECTED";
209
+ readonly intentId: string;
210
+ constructor(intentId: string, reason?: string);
211
+ }
212
+ /**
213
+ * Dispatch an intent and wait for it to complete.
214
+ *
215
+ * - Resolves with the terminal Snapshot on `dispatch:completed`
216
+ * - Rejects with the error on `dispatch:failed`
217
+ * - Rejects with DispatchRejectedError on `dispatch:rejected`
218
+ *
219
+ * This is a convenience utility derived entirely from `dispatch` + `on`.
220
+ * It does NOT violate the "one owned concept" rule.
221
+ *
222
+ * @see SDK SPEC v1.0.0 §14.3
223
+ */
224
+ declare function dispatchAsync<T = unknown>(instance: ManifestoInstance<T>, intent: Intent): Promise<Snapshot<T>>;
225
+
226
+ /**
227
+ * SDK v1.0.0 Error Types
228
+ *
229
+ * @see SDK SPEC v1.0.0 §12
230
+ * @see SDK-ERR-1, SDK-ERR-2, SDK-ERR-3
231
+ * @module
232
+ */
233
+ /**
234
+ * Base error for all SDK errors.
235
+ *
236
+ * @see SDK-ERR-1
237
+ */
238
+ declare class ManifestoError extends Error {
239
+ readonly code: string;
240
+ constructor(code: string, message: string, options?: ErrorOptions);
241
+ }
242
+ /**
243
+ * Thrown when user effects attempt to override reserved effect types (e.g. system.get).
244
+ *
245
+ * @see SDK-ERR-2, SDK-INV-4
246
+ */
247
+ declare class ReservedEffectError extends ManifestoError {
248
+ readonly effectType: string;
249
+ constructor(effectType: string);
250
+ }
251
+ /**
252
+ * Thrown when MEL compilation fails. Exposes full diagnostic info.
253
+ *
254
+ * @see SDK-ERR-4
255
+ */
256
+ declare class CompileError extends ManifestoError {
257
+ readonly diagnostics: readonly CompileDiagnostic[];
258
+ constructor(diagnostics: readonly CompileDiagnostic[], formattedMessage: string);
259
+ }
260
+ /**
261
+ * Minimal diagnostic shape exposed by SDK.
262
+ * Matches @manifesto-ai/compiler Diagnostic but avoids hard dependency.
263
+ */
264
+ interface CompileDiagnostic {
265
+ readonly severity: "error" | "warning" | "info";
266
+ readonly code: string;
267
+ readonly message: string;
268
+ readonly location: {
269
+ readonly start: {
270
+ readonly line: number;
271
+ readonly column: number;
272
+ readonly offset: number;
273
+ };
274
+ readonly end: {
275
+ readonly line: number;
276
+ readonly column: number;
277
+ readonly offset: number;
278
+ };
279
+ };
280
+ readonly source?: string;
281
+ readonly suggestion?: string;
282
+ }
283
+ /**
284
+ * Thrown when dispatch is called on a disposed instance.
285
+ *
286
+ * @see SDK-ERR-3, SDK-DISPATCH-4
287
+ */
288
+ declare class DisposedError extends ManifestoError {
289
+ constructor();
290
+ }
291
+
292
+ /**
293
+ * Depth counter for recursive type operations.
294
+ * Prevents infinite recursion in TypeScript's type system.
295
+ *
296
+ * Usage: Prev[4] = 3, Prev[3] = 2, ... Prev[0] = never
297
+ */
298
+ type Prev = [never, 0, 1, 2, 3, 4];
299
+ /**
300
+ * Extract all valid dot-separated paths from a data type.
301
+ *
302
+ * - Object keys become path segments
303
+ * - Nested objects generate dot-separated paths (e.g. "user.name")
304
+ * - Arrays, primitives, and Record<string, T> are leaf nodes
305
+ * (Record sub-paths are not supported by Core's path resolution)
306
+ * - Limited to 3 levels of nesting to avoid TS recursion limits
307
+ * (root key + 3 nested levels = max 4 path segments)
308
+ *
309
+ * @example
310
+ * type State = { user: { name: string; age: number }; count: number };
311
+ * type P = DataPaths<State>;
312
+ * // "user" | "user.name" | "user.age" | "count"
313
+ */
314
+ type DataPaths<T, D extends number = 3> = [D] extends [never] ? never : T extends Record<string, unknown> ? T extends unknown[] ? never : {
315
+ [K in keyof T & string]: K | (NonNullable<T[K]> extends Record<string, unknown> ? NonNullable<T[K]> extends unknown[] ? never : string extends keyof NonNullable<T[K]> ? never : `${K}.${DataPaths<NonNullable<T[K]>, Prev[D]>}` : never);
316
+ }[keyof T & string] : never;
317
+ /**
318
+ * Resolve the value type at a dot-separated path.
319
+ *
320
+ * @example
321
+ * type State = { user: { name: string } };
322
+ * type V = ValueAt<State, "user.name">; // string
323
+ * type U = ValueAt<State, "user">; // { name: string }
324
+ */
325
+ type ValueAt<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? ValueAt<NonNullable<T[K]>, Rest> : never : P extends keyof T ? T[P] : never;
326
+ /**
327
+ * Paths that resolve to plain object types (valid targets for merge).
328
+ * Arrays and primitives are excluded since merge performs shallow object merge.
329
+ *
330
+ * @example
331
+ * type State = { user: { name: string }; tags: string[]; count: number };
332
+ * type M = ObjectPaths<State>;
333
+ * // "user" (tags and count excluded - not plain objects)
334
+ */
335
+ type ObjectPaths<T, D extends number = 3> = [D] extends [never] ? never : T extends Record<string, unknown> ? T extends unknown[] ? never : {
336
+ [K in keyof T & string]: (NonNullable<T[K]> extends Record<string, unknown> ? NonNullable<T[K]> extends unknown[] ? never : K : never) | (NonNullable<T[K]> extends Record<string, unknown> ? NonNullable<T[K]> extends unknown[] ? never : string extends keyof NonNullable<T[K]> ? never : `${K}.${ObjectPaths<NonNullable<T[K]>, Prev[D]>}` : never);
337
+ }[keyof T & string] : never;
338
+ /**
339
+ * Type-safe patch operations builder.
340
+ *
341
+ * Provides IDE autocomplete for state paths and compile-time type checking
342
+ * for patch values. All methods return standard Patch objects compatible
343
+ * with Core's apply() function.
344
+ * System mutation convenience APIs are intentionally excluded.
345
+ *
346
+ * @typeParam TData - The shape of domain state (snapshot.data)
347
+ */
348
+ interface TypedOps<TData extends Record<string, unknown>> {
349
+ /**
350
+ * Create a set patch — replace value at path (create if missing).
351
+ *
352
+ * @example
353
+ * ops.set('count', 5);
354
+ * ops.set('user.name', 'Alice');
355
+ */
356
+ set<P extends DataPaths<TData>>(path: P, value: Exclude<ValueAt<TData, P>, undefined>): SetPatch;
357
+ /**
358
+ * Create an unset patch — remove property at path.
359
+ *
360
+ * @example
361
+ * ops.unset('temporaryField');
362
+ */
363
+ unset<P extends DataPaths<TData>>(path: P): UnsetPatch;
364
+ /**
365
+ * Create a merge patch — shallow merge at object path.
366
+ * Only valid for paths that resolve to plain object types.
367
+ *
368
+ * @example
369
+ * ops.merge('user', { name: 'Bob' });
370
+ */
371
+ merge<P extends ObjectPaths<TData>>(path: P, value: {
372
+ [K in keyof ValueAt<TData, P>]?: Exclude<ValueAt<TData, P>[K], undefined>;
373
+ }): MergePatch;
374
+ /**
375
+ * Raw (untyped) patch creation — escape hatch for dynamic paths
376
+ * or platform namespace ($*) targets.
377
+ */
378
+ raw: {
379
+ set(path: string, value: unknown): SetPatch;
380
+ unset(path: string): UnsetPatch;
381
+ merge(path: string, value: Record<string, unknown>): MergePatch;
382
+ };
383
+ }
384
+ /**
385
+ * Create a type-safe patch operations builder.
386
+ *
387
+ * Injects the domain state type to enable:
388
+ * - IDE autocomplete on all valid state paths
389
+ * - Compile-time type checking of patch values
390
+ * - Merge restricted to object-typed paths
391
+ *
392
+ * @typeParam TData - The shape of domain state (snapshot.data)
393
+ *
394
+ * @example
395
+ * type State = {
396
+ * count: number;
397
+ * user: { name: string; age: number };
398
+ * tags: string[];
399
+ * };
400
+ *
401
+ * const ops = defineOps<State>();
402
+ *
403
+ * ops.set('count', 5); // OK — value: number
404
+ * ops.set('user.name', 'Alice'); // OK — value: string
405
+ * ops.set('count', 'hello'); // TS error — expected number
406
+ * ops.merge('user', { name: 'B' }); // OK — partial object merge
407
+ * ops.unset('tags'); // OK
408
+ *
409
+ * // Escape hatch for dynamic / platform paths
410
+ * ops.raw.set('$host.custom', { key: 'value' });
411
+ */
412
+ declare function defineOps<TData extends Record<string, unknown>>(): TypedOps<TData>;
413
+
414
+ export { type CompileDiagnostic, CompileError, type DataPaths, DispatchRejectedError, DisposedError, type EffectContext, type EffectHandler, type ManifestoConfig, ManifestoError, type ManifestoEvent, type ManifestoEventMap, type ManifestoEventPayload, type ManifestoInstance, type ObjectPaths, ReservedEffectError, type SdkManifest, type Selector, type Snapshot, type TypedOps, type Unsubscribe, type ValueAt, createManifesto, defineOps, dispatchAsync };