22
33## Goals
44
5- - Allow lifts, handlers, and recipes to return reusable node factories that can
6- be shipped across spaces or persisted and later instantiated.
5+ - Allow lifts (and thus patterns) and handlers to return reusable node factories
6+ that can be shipped across spaces or persisted and later instantiated.
77- Support partial application via a ` .curry(value, argIndex = 0) ` helper that
88 yields another shippable node factory reflecting the bound argument.
99- Use a versioned sigil format (` nodeFactory@1 ` ) that closely mirrors the graph
1515- Any node factory created by ` lift ` , ` handler ` , or builder helpers returns a
1616 callable object that also exposes ` .toJSON() ` producing the ` nodeFactory@1 `
1717 sigil.
18+ - Passing a node factory as part of the argument to ` Cell.set() ` & co, or
19+ calling another factory with it, automatically converts it into it's JSON
20+ representation.
1821- Recipes may return node factories or pass them into other lifts/recipes. When
1922 the runtime encounters a ` nodeFactory@1 ` payload (e.g., via ` Cell.get() ` or as
2023 a recipe input), it materializes a callable node factory automatically.
2629
2730Serialized form:
2831
29- ``` json
32+ ``` ts
3033{
3134 " /" : {
32- "nodeFactory@1" : {
33- "module" : ReactiveModuleDescriptor | EventHandlerDescriptor,
34- "program" : RuntimeProgram,
35- "curried" : [
36- {
37- "index" : 0 ,
38- "value" : Binding
39- }
40- ],
41- "argumentSchema" : JSONSchema,
42- "resultSchema" : JSONSchema | null,
43- "metadata" : Record<string, JSONValue> | null
44- }
35+ " nodeFactory@1" :
36+ & BoxedNodeFactory
37+ & CurriedArguments
38+ & (ReactiveNodeNarrowedSchema | HandlerNodeNarrowedSchema )
4539 }
4640}
4741```
4842
4943Notes:
5044
51- - ` module ` matches the descriptors used in ` graph-snapshot.md ` , including
52- implementation references and descriptor-level ` argumentSchema ` /` resultSchema ` .
53- - ` program ` stores the complete ` RuntimeProgram ` (as defined in
54- ` packages/runner/src/harness/types.ts ` ) so the runtime knows how to load the
55- compiled artifact and entry symbol.
56- - ` curried ` is ordered; each entry binds ` value ` to the given ` index ` (0-based by
57- default). ` Binding ` mirrors the nested binding structure from the snapshot so
58- bound values can include cell links.
59- - ` argumentSchema ` on the sigil represents the effective schema after all
60- currying. It must continue to describe array/prefix-array inputs.
61- - ` resultSchema ` is optional and may be omitted/` null ` for handlers.
62- - ` metadata ` carries optional helper information (e.g., helper names) and may be
63- omitted if unused.
45+ - ` BoxedNodeFactory ` the descriptors used in ` graph-snapshot.md ` , including
46+ implementation references and descriptor-level ` argumentSchema ` /` resultSchema `
47+ and link to implemention.
48+ - ` CurriedArguments ` contains the lists the arguments that are being supplied
49+ already, index defaulting to 0 or +1 the previous index.
50+ - For event handlers, 0 is the event stream. If it is curried, then the
51+ resulting function looks like a reactive node factory that can be called
52+ with state to bind. If it isn't curried, the result is a stream factory,
53+ just like the original, but bound to state.
54+ - ` ReactiveNodeNarrowedSchema | HandlerNodeNarrowedSchema ` are optional
55+ constraints due to currying over the original schemas in the module.
6456
6557## Runtime Behavior
6658
6759- Deserialization: When the runtime reads a value containing the ` nodeFactory@1 `
6860 sigil, it constructs a callable factory that:
6961 1 . Applies stored currying bindings before invoking the underlying module.
70- 2 . Exposes ` .curry ` to append additional entries to ` curried ` and returns a new
71- serialized-aware wrapper.
62+ 2 . Exposes ` .curry ` to append additional entries to ` curried ` and returns a
63+ new serialized-aware wrapper.
7264 3 . Implements ` .toJSON() ` to emit the sigil.
7365- Invocation: Calling the materialized factory schedules a node instantiation
7466 identical to calling the original lift/handler. Inputs are merged with stored
7567 curry bindings using positional logic (array inputs) or schema-derived names.
76- - Integration with snapshots: When a recipe instantiates a node from a serialized
77- factory, the resulting node appears in the graph snapshot exactly like a
78- regular node (same descriptor, inputs, etc.). The factory sigil itself can also
79- be stored in recipe state for later reuse.
68+ - Integration with snapshots: When a recipe instantiates a node from a
69+ serialized factory, the resulting node appears in the graph snapshot exactly
70+ like a regular node (same descriptor, inputs, etc.). The factory sigil itself
71+ can also be stored in recipe state for later reuse.
8072
8173## Builder Integration
8274
@@ -87,11 +79,10 @@ Notes:
8779 runtime keeps the sigil available so passing the factory back to storage or
8880 another recipe preserves currying metadata.
8981
90- ## Open Questions
82+ ## Rollout
9183
92- - Do we need an explicit way to specify argument names alongside indexes for
93- currying when dealing with object-shaped schemas?
94- - Should we limit the size of serialized ` RuntimeProgram ` payloads by hashing or
95- referencing a shared cache entry instead of embedding the entire program?
96- - How do we ensure backwards compatibility if the module descriptor expands? The
97- sigil version (` nodeFactory@1 ` ) gives us room to add future revisions.
84+ - This is blocked on multi-argument ` lift ` .
85+ - However, we can start with curried ` recipe ` (which later become a variant of
86+ ` lift ` ) and instead of treating it as multiple inputs merge the input object
87+ instead on call. The first use-case is for actions, so we can even do this
88+ just there.
0 commit comments