2026-09-19 23:05:52 -07:00
import type {
WorkspaceRevision ,
ExecutionContract ,
ValueType ,
Binding ,
DependencyBinding ,
EdgeTraversal ,
InterfaceRevisionId ,
AtomId ,
OperationId ,
} from "../capability-model/types.js" ;
import { validateWorkspaceRevision } from "../capability-model/validation.js" ;
2026-09-22 13:16:23 -07:00
import { moduleContract } from "../capability-model/modules.js" ;
2026-09-19 23:05:52 -07:00
import { canonicalJson , contentDigest } from "../capability-model/evolution.js" ;
import { resolveForwardedBinding } from "../capability-model/forwarding.js" ;
import { linkQueries , type LinkedQuery } from "../query/link.js" ;
import { type BindingSchema } from "../bindings/index.js" ;
2026-09-20 23:50:52 -07:00
import { unsupportedQueryOperator } from "./query-operators.js" ;
2026-09-25 11:30:37 -07:00
import { moduleTypeContext } from "./module-contracts.js" ;
2026-09-19 23:05:52 -07:00
export class ExecutionPlanError extends Error {
constructor (
readonly code : string ,
readonly path : string ,
message : string ,
) {
super ( ` ${ code } ${ path } : ${ message } ` );
this . name = "ExecutionPlanError" ;
}
}
export const hexDigest = ( value : unknown ) : string => contentDigest ( value ). slice ( "sha256:" . length );
const sorted = < T >( values : readonly T [], key : ( value : T ) => string ) : T [] =>
[... values ]. sort (( a , b ) => ( key ( a ) < key ( b ) ? - 1 : key ( a ) > key ( b ) ? 1 : 0 ));
export const publicOperationKey = ( atom : string , iface : string , operation : string ) : string =>
JSON . stringify ([ atom , iface , operation ]);
export type DataDependency =
| { kind : "state" ; slot : string ; via? : EdgeTraversal }
| { kind : "edge" ; edge : string ; projection : string ; via? : EdgeTraversal }
| { kind : "operation" ; operation : string ; port : string ; via? : EdgeTraversal }
| { kind : "query" ; query : string ; port : string };
export interface PlannedOperation {
key : string ;
atomId : string ;
interfaceRevisionId : string ;
operationId : string ;
scope : "object" | "class" ;
execution : ExecutionContract ;
input : ValueType ;
output : ValueType ;
/** Concrete target after public forwarding. Never chosen by a runtime caller. */
binding : Exclude < Binding , { kind : "interface" }>;
dependencies : DataDependency [];
}
export interface PlannedQuery {
id : string ;
query : LinkedQuery ;
/** Query-selected getter entrypoints; dependency traversal supplies canonical inputs. */
operations : string [];
/** Local query roots that admission must support, in addition to selected wire outputs. */
admittedOperations : string [];
}
export interface PlanPackage {
2026-09-22 13:16:23 -07:00
modules ?: ( NonNullable < WorkspaceRevision [ "packageImports" ][ number ][ "modules" ] >[ number ] & {
contract : string ;
subject? : import ( "../capability-model/types.js" ). ObjectExpectation ;
2026-09-25 11:30:37 -07:00
typeArguments? : readonly unknown [];
requiredInterfaces? : readonly string [];
2026-09-22 13:16:23 -07:00
})[];
2026-09-21 11:23:26 -07:00
controllers? : NonNullable < WorkspaceRevision [ "packageImports" ][ number ][ "controllers" ] >;
2026-09-22 13:16:23 -07:00
components ?: { id : string ; displayName : string ; subject : InterfaceRevisionId ; runtime : "react" }[];
2026-09-19 23:05:52 -07:00
revision : string ;
source : WorkspaceRevision [ "packageImports" ][ number ][ "source" ];
sourceDigest : string ;
bindingDigest : string ;
exports : { id : string ; execution : ExecutionContract }[];
}
2026-09-22 13:16:23 -07:00
/** React consumes these module contracts; other contracts remain metadata until
* an artifact consumer exists. This does not make modules callable operations. */
function componentDeclarations ( workspace : WorkspaceRevision , pkg : WorkspaceRevision [ "packageImports" ][ number ]) {
return [
...( pkg . modules ?? []). flatMap (( module ) => {
const contract = moduleContract ( workspace . interfaceImports , module ) ! ;
if (
2026-09-25 12:26:34 -07:00
! [ "org.quixos.react.component/1" , "org.quixos.react.component/2" , "org.quixos.react.subject-only/1" ]. includes (
contract . contract ,
) ||
2026-09-22 13:16:23 -07:00
contract . subject ? . kind !== "interface"
)
return [];
return [
{
id : module.id ,
displayName : module.displayName ,
subject : contract.subject.interfaceRevisionId ,
runtime : "react" as const ,
},
];
}),
];
}
2026-09-19 23:05:52 -07:00
export interface ExecutionPlanDefinition {
2026-09-21 11:23:26 -07:00
presentations? : NonNullable < WorkspaceRevision [ "presentations" ] >;
2026-09-19 23:05:52 -07:00
codec : "camino-execution-plan-v1" ;
workspace : WorkspaceRevision ;
bindingSchema : BindingSchema ;
packages : PlanPackage [];
owners : { id : string ; atom : string ; interface : string ; initialization : unknown ; storage : unknown }[];
operations : PlannedOperation [];
queries : PlannedQuery [];
profiles : { slot : string ; profile : string }[];
versions : {
value : "camino-value-v1" ;
reference : "camino-ref-v1" ;
ports : "quixos-transaction-ports-v1" ;
crdt : "camino-automerge-3.4.1-structured-v1" ;
};
}
export interface ExecutionPlan {
definition : ExecutionPlanDefinition ;
digest : string ;
}
export const executionVersions : ExecutionPlanDefinition [ "versions" ] = {
value : "camino-value-v1" ,
reference : "camino-ref-v1" ,
ports : "quixos-transaction-ports-v1" ,
crdt : "camino-automerge-3.4.1-structured-v1" ,
};
/** Selection only: the coordinator separately verifies the caller's grant and receiver witness. */
export function resolvePlannedOperation (
plan : ExecutionPlan ,
atom : string ,
iface : string ,
operation : string ,
) : PlannedOperation {
const key = publicOperationKey ( atom , iface , operation );
const selected = plan . definition . operations . find (( entry ) => entry . key === key );
if ( ! selected ) throw new ExecutionPlanError ( "UNINSTALLED_OPERATION" , key , "No installed public operation binding" );
return selected ;
}
/** Bound argument/state codec subset. A parsed type alone does not mean a runtime implements it. */
function checkValue ( type : ValueType , path : string , allowChange = false ) : void {
switch ( type . kind ) {
case "scalar" :
case "object-ref" :
return ;
case "builtin" :
if ( type . name === "unit" ) return ;
break ;
case "optional" :
case "list" :
checkValue ( type . value , path , allowChange );
return ;
case "record" :
for ( const [ name , field ] of Object . entries ( type . fields )) checkValue ( field , ` ${ path } . ${ name } ` , allowChange );
return ;
case "change" :
if ( allowChange ) {
checkValue ( type . value , path );
return ;
}
break ;
}
throw new ExecutionPlanError ( "UNSUPPORTED_PORTABLE_CODEC" , path , `Portable execution does not support ${ type . kind } ` );
}
/** Compile declarations into a closed dispatch/dependency graph before artifact selection. */
export function compileExecutionPlan ( input : WorkspaceRevision ) : ExecutionPlan {
const workspace = structuredClone ( input );
const issues = validateWorkspaceRevision ( workspace );
if ( issues . length )
throw new ExecutionPlanError (
"INVALID_WORKSPACE" ,
workspace . id ,
issues . map (( i ) => ` ${ i . path } : ${ i . message } ` ). join ( "\n" ),
);
const interfaces = new Map ( workspace . interfaceImports . map (( i ) => [ i . revisionId , i ]));
const packages = new Map ( workspace . packageImports . map (( p ) => [ p . revisionId , p ]));
const attachments = [... workspace . sharedAttachments , ... workspace . conformances . flatMap (( c ) => c . privateAttachments )];
for ( const pkg of workspace . packageImports )
for ( const entry of pkg . exports )
if ( entry . execution && entry . execution . kind !== "remote" ) {
2026-09-20 22:57:27 -07:00
checkValue ( entry . inputType , ` ${ pkg . revisionId } / ${ entry . id } /input` , true );
checkValue ( entry . outputType , ` ${ pkg . revisionId } / ${ entry . id } /output` , true );
2026-09-19 23:05:52 -07:00
}
for ( const attachment of attachments )
if ( attachment . kind === "state" && attachment . storagePolicy . kind === "crdt-document" )
checkValue ( attachment . valueType , attachment . id );
const operationMap = new Map < string , PlannedOperation >();
const queries = linkQueries ( workspace );
const queryKey = ( pkg : string , id : string ) => JSON . stringify ([ pkg , id ]);
const queryMap = new Map ( queries . map (( q ) => [ queryKey ( q . packageRevisionId , q . checked . declaration . id ), q ]));
const declaration = ( iface : InterfaceRevisionId , operation : OperationId ) =>
interfaces
. get ( iface )
? . members . flatMap (( m ) => m . operations )
. find (( o ) => o . id === operation );
const queryOperations = ( query : LinkedQuery ) =>
query . fields . map (( f ) => publicOperationKey ( f . atomId , f . interfaceRevisionId , f . getter ));
const targetAtoms = ( binding : DependencyBinding , atom : AtomId ) : AtomId [] => {
2026-09-20 22:05:59 -07:00
if ( binding . kind === "interface" && binding . receiver === "input" )
return workspace . atoms
. filter (( candidate ) =>
workspace . conformances . some (
( conformance ) =>
conformance . atomId === candidate . id && conformance . interfaceRevisionId === binding . interfaceRevisionId ,
),
)
. map (( candidate ) => candidate . id );
2026-09-19 23:05:52 -07:00
if ( ! ( "via" in binding ) || ! binding . via ) return [ atom ];
const edge = attachments . find (( a ) => a . id === binding . via ! . edgeTypeId );
if ( ! edge || edge . kind !== "edge" ) throw new ExecutionPlanError ( "MISSING_EDGE" , atom , "Missing traversal edge" );
const endpoint = edge . endpoints . find (( e ) => e . projectionId !== binding . via ! . projectionId ) ! ;
const constraint = endpoint . constraint ;
return workspace . atoms
. filter (( a ) =>
constraint . kind === "atom"
? constraint . atomId === a.id
: workspace.conformances.some (
( c ) => c . atomId === a . id && c . interfaceRevisionId === constraint . interfaceRevisionId ,
),
)
. map (( a ) => a . id );
};
const add = ( atom : AtomId , iface : InterfaceRevisionId , operation : OperationId ) : PlannedOperation => {
const key = publicOperationKey ( atom , iface , operation ),
existing = operationMap . get ( key );
if ( existing ) return existing ;
const publicContract = declaration ( iface , operation );
if ( ! publicContract ) throw new ExecutionPlanError ( "MISSING_OPERATION" , key , "Missing public contract" );
const { binding } = resolveForwardedBinding ( workspace , atom , iface , operation );
const planned : PlannedOperation = {
key ,
atomId : atom ,
interfaceRevisionId : iface ,
operationId : operation ,
scope : publicContract.scope === "class" ? "class" : "object" ,
execution : publicContract.execution ?? { kind : "remote" },
input : publicContract.inputType ,
output : publicContract.outputType ,
binding ,
dependencies : [],
};
operationMap . set ( key , planned );
const portable = planned . execution . kind !== "remote" ;
if ( portable ) {
2026-09-20 22:57:27 -07:00
checkValue ( planned . input , ` ${ key } /input` , true );
checkValue ( planned . output , ` ${ key } /output` , true );
2026-09-19 23:05:52 -07:00
}
if ( binding . kind === "state" ) planned . dependencies . push ({ kind : "state" , slot : binding.slotId });
else if ( binding . kind === "edge" )
planned . dependencies . push ({ kind : "edge" , edge : binding.edgeTypeId , projection : binding.projectionId });
2026-09-20 22:41:51 -07:00
else if ( binding . kind === "package" ) {
2026-09-19 23:05:52 -07:00
const entry = packages . get ( binding . packageRevisionId ) ? . exports . find (( e ) => e . id === binding . exportId );
if ( ! entry ) throw new ExecutionPlanError ( "MISSING_EXPORT" , key , "Unresolved package export" );
for ( const dependency of binding . dependencies ) {
const port = entry . dependencyPorts . find (( p ) => p . id === dependency . portId ) ! ;
const target = dependency . binding ;
const via = "via" in target && target . via ? { via : target.via } : {};
if ( "via" in target && target . via )
planned . dependencies . push ({ kind : "edge" , edge : target.via.edgeTypeId , projection : target.via.projectionId });
if ( target . kind === "state" ) planned . dependencies . push ({ kind : "state" , slot : target.slotId , ... via });
else if ( target . kind === "edge" )
planned . dependencies . push ({ kind : "edge" , edge : target.edgeTypeId , projection : target.projectionId , ... via });
else if ( target . kind === "interface" && port . requirement . kind === "interface" ) {
const selected =
port . requirement . operations ??
interfaces . get ( target . interfaceRevisionId ) ! . members . flatMap (( m ) => m . operations . map (( o ) => o . id ));
for ( const targetAtom of targetAtoms ( target , atom ))
for ( const selectedOperation of selected ) {
const operation = add ( targetAtom , target . interfaceRevisionId , selectedOperation );
planned . dependencies . push ({ kind : "operation" , operation : operation.key , port : port.id , ... via });
}
} else if ( target . kind === "query" ) {
const query = queryMap . get ( queryKey ( target . packageRevisionId , target . queryId ));
if ( ! query ) throw new ExecutionPlanError ( "MISSING_QUERY" , key , `Unresolved query port ${ port . id } ` );
planned . dependencies . push ({
kind : "query" ,
query : queryKey ( target . packageRevisionId , target . queryId ),
port : port.id ,
});
}
}
}
planned . dependencies = sorted ( planned . dependencies , canonicalJson );
return planned ;
};
for ( const conformance of workspace . conformances )
for ( const entry of conformance . operationBindings )
add ( conformance . atomId , conformance . interfaceRevisionId , entry . operationId );
// Check the transitive closure, retaining a dependency path for diagnostics.
for ( const root of operationMap . values ()) {
if ( root . execution . kind === "remote" ) continue ;
const requested = root . execution ,
visited = new Set < string >();
const walk = ( key : string , path : string []) => {
if ( visited . has ( key )) return ;
visited . add ( key );
const node = operationMap . get ( key ) ! ;
if ( node . execution . kind === "remote" || ( requested . kind === "snapshot" && node . execution . kind !== "snapshot" ))
throw new ExecutionPlanError (
"NONPORTABLE_DEPENDENCY" ,
path . join ( " -> " ),
"Execution effect is not allowed by the root contract" ,
);
for ( const target of requested . targets )
if ( ! node . execution . targets . includes ( target ))
throw new ExecutionPlanError (
"MISSING_EXECUTION_TARGET" ,
path . join ( " -> " ),
`Dependency does not provide ${ target } ` ,
);
for ( const dependency of node . dependencies ) {
if ( dependency . kind === "operation" )
walk ( dependency . operation , [... path , dependency . port , dependency . operation ]);
if ( dependency . kind === "query" ) {
// An admitted presentation window is not an authoritative mutation read set.
if ( requested . kind === "transaction" )
throw new ExecutionPlanError (
"QUERY_IN_TRANSACTION" ,
[... path , dependency . port ]. join ( " -> " ),
"Capture explicit object references as mutation inputs; local presentation queries cannot define transaction membership" ,
);
const query = queryMap . get ( dependency . query ) ! ;
if ( query . checked . declaration . placement ? . kind !== "local" )
throw new ExecutionPlanError (
"REMOTE_QUERY_DEPENDENCY" ,
path . join ( " -> " ),
"Portable code requires a local query" ,
);
for ( const operation of queryOperations ( query )) walk ( operation , [... path , dependency . port , operation ]);
}
}
};
walk ( root . key , [ root . key ]);
}
const plannedQueries : PlannedQuery [] = queries . map (( query ) => ({
id : queryKey ( query . packageRevisionId , query . checked . declaration . id ),
query ,
operations : queryOperations ( query ). sort (),
admittedOperations : [],
}));
for ( const query of plannedQueries ) {
2026-09-20 23:50:52 -07:00
for ( const field of query . query . fields ) {
const operation = operationMap . get ( publicOperationKey ( field . atomId , field . interfaceRevisionId , field . getter )) ! ;
const effect = query . query . checked . effects . find (
( effect ) => effect . interfaceRevisionId === field . interfaceRevisionId && effect . memberId === field . memberId ,
);
if (
operation . execution . kind === "remote" &&
( query . query . checked . declaration . placement ? . kind === "replica" || effect ? . uses . some (( use ) => use !== "select" ))
)
throw new ExecutionPlanError (
"QUERY_REMOTE_MEMBERSHIP_UNSUPPORTED" ,
query . id ,
"Remote getters may enrich selected values after native snapshot closure; they cannot determine membership, order or canonical-input admission. Expose an accepted canonical value or split the service result into a separate query." ,
);
const member = interfaces . get ( field . interfaceRevisionId ) ? . members . find (( member ) => member . id === field . memberId );
if ( member ? . kind === "relationship" && operation . binding . kind !== "edge" )
throw new ExecutionPlanError (
"QUERY_NON_NATIVE_RELATION" ,
query . id ,
"This query runtime traverses native graph edges. Expose an edge relationship, or return a computed service value through a value getter." ,
);
}
const unsupported = unsupportedQueryOperator ( query . query . checked );
if ( unsupported )
throw new ExecutionPlanError (
"QUERY_OPERATOR_UNSUPPORTED" ,
query . id ,
`This execution world does not support ${ unsupported } . Use a bounded portable getter over admitted inputs, or a server service returning the computed value. Query placement will not change automatically.` ,
);
2026-09-19 23:05:52 -07:00
const placement = query . query . checked . declaration . placement ;
if ( placement ? . kind !== "local" ) continue ;
const source = plannedQueries . find (
( q ) => q . id === queryKey ( query . query . packageRevisionId , placement . sourceQueryId ),
);
if ( ! source || source . query . checked . declaration . placement ? . kind !== "replica" )
throw new ExecutionPlanError ( "MISSING_REPLICA_SOURCE" , query . id , "Local query source must be a replica query" );
const localRoot = query . query . checked . declaration . root ,
sourceRoot = source . query . checked . declaration . root ;
if ( localRoot . kind !== sourceRoot . kind || localRoot . interface !== sourceRoot . interface )
throw new ExecutionPlanError (
"REPLICA_ROOT_MISMATCH" ,
query . id ,
"Local and replica queries must use the same root contract" ,
);
2026-09-22 18:27:59 -07:00
if ( localRoot . kind === "workspace-interface" ) {
const sourceWindows = source . query . checked . selection
. flatMap (( root ) => root . selection )
. filter (( s ) => s . name === "objects" );
for ( const selection of query . query . checked . selection
. flatMap (( root ) => root . selection )
. filter (( s ) => s . name === "objects" )) {
if (
! sourceWindows . some (
( window ) =>
canonicalJson ({ arguments : window.arguments , conditions : window.conditions }) ===
canonicalJson ({ arguments : selection.arguments , conditions : selection.conditions }),
)
)
throw new ExecutionPlanError (
"REPLICA_WINDOW_MISMATCH" ,
query . id ,
"Local objects must observe the identical confirmed source window; use availableObjects for a local candidate view" ,
);
}
}
2026-09-19 23:05:52 -07:00
const traversals = ( linked : LinkedQuery ) => {
2026-09-22 16:48:16 -07:00
const paths = new Map < string , { complete : boolean ; requiresComplete : boolean ; windows : Set < string > }>();
const entry = ( key : string ) => {
let value = paths . get ( key );
if ( ! value ) {
value = { complete : false , requiresComplete : false , windows : new Set () };
paths . set ( key , value );
}
return value ;
};
2026-09-19 23:05:52 -07:00
const visit = ( selections : LinkedQuery [ "checked" ][ "selection" ], parents : string []) => {
for ( const selection of selections ) {
2026-09-20 23:50:52 -07:00
for ( const stage of selection . relational ? . stages ?? []) {
if ( stage . operation . kind === "source" )
2026-09-22 16:48:16 -07:00
entry ( JSON . stringify ([... parents , stage . operation . memberId ])). requiresComplete = true ;
2026-09-20 23:50:52 -07:00
}
2026-09-19 23:05:52 -07:00
const member = selection . interfaceRevisionId
? interfaces . get ( selection . interfaceRevisionId ) ? . members . find (( m ) => m . id === selection . memberId )
: undefined ;
const path = member ? . kind === "relationship" ? [... parents , member . id ] : parents ;
2026-09-20 03:44:49 -07:00
if ( member ? . kind === "relationship" ) {
const many = member . cardinality === "many" || member . cardinality === "many-unique" ;
const complete = ! selection . predicate && ( ! many || !! selection . arguments . all );
const key = JSON . stringify ( path );
2026-09-22 16:48:16 -07:00
const value = entry ( key );
value . complete ||= complete ;
if ( selection . arguments . first )
value . windows . add ( canonicalJson ({ arguments : selection.arguments , conditions : selection.conditions }));
else value . requiresComplete = true ;
2026-09-20 03:44:49 -07:00
}
2026-09-19 23:05:52 -07:00
visit ( selection . selection , path );
}
};
visit ( linked . checked . selection , []);
return paths ;
};
const admittedTraversals = traversals ( source . query );
2026-09-22 16:48:16 -07:00
for ( const [ traversal , needed ] of traversals ( query . query )) {
2026-09-19 23:05:52 -07:00
if ( ! admittedTraversals . has ( traversal ))
throw new ExecutionPlanError (
"REPLICA_TRAVERSAL_MISSING" ,
query . id ,
`Replica source does not admit relationship path ${ traversal } ` ,
);
2026-09-22 16:48:16 -07:00
if (
! admittedTraversals . get ( traversal ) ! . complete &&
( needed . requiresComplete ||
! needed . windows . size ||
[... needed . windows ]. some (( window ) => ! admittedTraversals . get ( traversal ) ! . windows . has ( window )))
)
2026-09-20 03:44:49 -07:00
throw new ExecutionPlanError (
"REPLICA_RELATION_INCOMPLETE" ,
query . id ,
2026-09-22 16:48:16 -07:00
`Local relationship ${ traversal } needs either complete source candidates or the identical confirmed first window; a window cannot supply unseen matches` ,
2026-09-20 03:44:49 -07:00
);
}
2026-09-19 23:05:52 -07:00
// The admission executor follows these canonical dependencies on the admitted roots.
// They do not change source candidate membership or make local take/filters authoritative.
source . admittedOperations . push (... query . operations );
for ( const operation of query . operations ) {
const node = operationMap . get ( operation ) ! ;
if ( node . execution . kind !== "snapshot" || ! node . execution . targets . includes ( "browser" ))
throw new ExecutionPlanError (
"NONPORTABLE_QUERY_FIELD" ,
` ${ query . id } / ${ operation } ` ,
"Local query getter must provide browser snapshot execution" ,
);
}
}
for ( const query of plannedQueries ) query . admittedOperations = [... new Set ( query . admittedOperations )]. sort ();
const schema : BindingSchema = {
format : "quixos-bindings" ,
version : 1 ,
interfaces : sorted (
workspace . interfaceImports . filter (( i ) => ! i . template ),
( i ) => i . revisionId ,
),
interfaceTemplates : sorted (
workspace . interfaceImports . filter (( i ) => i . template ),
( i ) => i . revisionId ,
),
packages : sorted ( workspace . packageImports , ( p ) => p . revisionId ),
};
const normalizedSchema = JSON . parse ( canonicalJson ( schema )) as BindingSchema ;
const definition : ExecutionPlanDefinition = {
codec : "camino-execution-plan-v1" ,
workspace ,
bindingSchema : normalizedSchema ,
2026-09-21 11:23:26 -07:00
...( workspace . presentations ? . length ? { presentations : sorted ( workspace . presentations , ( p ) => p . id ) } : {}),
2026-09-19 23:05:52 -07:00
packages : sorted ( workspace . packageImports , ( p ) => p . revisionId ). map (( p ) => ({
revision : p.revisionId ,
source : p.source ,
sourceDigest : hexDigest ({ revision : p.revisionId , source : p.source }),
bindingDigest : hexDigest ( normalizedSchema ),
2026-09-22 13:16:23 -07:00
...( p . modules ? . length
? {
modules : sorted ( p . modules , ( module ) => module . id ). map (( module ) => {
const contract = moduleContract ( workspace . interfaceImports , module ) ! ;
return {
... module ,
contract : contract.contract ,
...( contract . subject ? { subject : contract.subject } : {}),
2026-09-25 11:30:37 -07:00
... moduleTypeContext (
workspace . interfaceImports . find (( iface ) => iface . revisionId === module . interfaceRevisionId ) ! ,
),
2026-09-22 13:16:23 -07:00
};
}),
}
: {}),
2026-09-21 11:23:26 -07:00
...( p . controllers ? . length ? { controllers : sorted ( p . controllers , ( controller ) => controller . id ) } : {}),
2026-09-22 13:16:23 -07:00
...( componentDeclarations ( workspace , p ). length
? { components : sorted ( componentDeclarations ( workspace , p ), ( component ) => component . id ) }
: {}),
2026-09-19 23:05:52 -07:00
exports : sorted ( p . exports , ( e ) => e . id ). map (( e ) => ({ id : e.id , execution : e.execution ?? { kind : "remote" } })),
})),
owners : sorted ( workspace . conformances , ( c ) => c . id ?? "" ). map (( c ) => {
if ( ! c . id )
throw new ExecutionPlanError (
"OWNER_ID_REQUIRED" ,
` ${ c . atomId } / ${ c . interfaceRevisionId } ` ,
"Installed state owners require explicit stable identities" ,
);
return {
id : c.id ,
atom : c.atomId ,
interface : c . interfaceRevisionId ,
initialization : c.initialization ?? [],
storage : c.privateAttachments ,
};
}),
operations : sorted ([... operationMap . values ()], ( o ) => o . key ),
queries : sorted ( plannedQueries , ( q ) => q . id ),
profiles : sorted (
attachments . filter (( a ) => a . kind === "state" && a . storagePolicy . kind === "crdt-document" ),
( a ) => a . id ,
). map (( a ) => ({ slot : a.id , profile : "camino-automerge-3.4.1-structured-v1" })),
versions : { ... executionVersions },
};
const normalized = JSON . parse ( canonicalJson ( definition )) as ExecutionPlanDefinition ;
return { definition : normalized , digest : hexDigest ( normalized ) };
}