2026-09-03 15:46:52 -07:00
import type {
AtomConstructorBinding ,
AtomId ,
AttachmentOwner ,
Binding ,
BoundDependency ,
Conformance ,
DependencyBinding ,
DependencyPort ,
EdgeCardinality ,
EdgeDefinition ,
EdgeEndpoint ,
EdgeEndpointConstraint ,
EdgePrimitive ,
EdgeProjectionId ,
EdgeTypeId ,
InterfaceMember ,
InterfaceOperation ,
InterfaceOperationMode ,
InterfaceRevision ,
InterfaceRevisionId ,
OperationId ,
OwnedAttachment ,
PackageExport ,
PackageOperationExport ,
PackageRevision ,
PackageRevisionId ,
PersistentAttachment ,
SlotId ,
SourceRevision ,
StatePrimitive ,
StateSlotDefinition ,
ValueType ,
WorkspaceRevision ,
} from "./types.js" ;
import { valueType } from "./types.js" ;
export type CapabilityValidationIssueCode =
2026-09-10 18:27:41 -07:00
| "invalid-semantic-major"
| "duplicate-conformance-id"
2026-09-03 15:46:52 -07:00
| "required-value"
| "invalid-source"
| "invalid-value-type"
| "invalid-operation"
| "duplicate-atom"
| "duplicate-attachment"
| "duplicate-projection"
| "duplicate-interface-revision"
| "duplicate-interface-member"
| "duplicate-interface-operation"
| "duplicate-package-revision"
| "duplicate-package-export"
| "duplicate-dependency-port"
| "duplicate-conformance"
| "duplicate-operation-binding"
2026-09-04 21:03:09 -07:00
| "duplicate-relationship-materialization"
2026-09-03 15:46:52 -07:00
| "duplicate-constructor"
| "unresolved-reference"
| "invalid-attachment"
| "invalid-state-binding"
| "invalid-edge-binding"
| "invalid-package-binding"
| "invalid-dependency-binding"
| "private-attachment-access"
| "incompatible-package-receiver"
2026-09-05 12:33:52 -07:00
| "unsatisfied-interface"
2026-09-03 15:46:52 -07:00
| "cyclic-conformance-requirement"
| "missing-operation-binding"
| "unknown-operation-binding"
2026-09-04 21:03:09 -07:00
| "invalid-constructor"
| "invalid-relationship-materialization" ;
2026-09-03 15:46:52 -07:00
export interface CapabilityValidationIssue {
code : CapabilityValidationIssueCode ;
path : string ;
message : string ;
}
interface InterfaceOperationEntry {
operation : InterfaceOperation ;
member : InterfaceMember ;
}
interface InterfaceIndexEntry {
revision : InterfaceRevision ;
operations : Map < OperationId , InterfaceOperationEntry >;
}
interface PackageIndexEntry {
revision : PackageRevision ;
exports : Map < string , PackageExport >;
}
interface AttachmentIndexEntry extends OwnedAttachment {
path : string ;
}
interface ValidationIndexes {
atoms : Map < string , WorkspaceRevision [ "atoms" ][ number ] >;
interfaces : Map < string , InterfaceIndexEntry >;
packages : Map < string , PackageIndexEntry >;
conformances : Map < string , Conformance >;
conformancePaths : Map < string , string >;
attachments : Map < string , AttachmentIndexEntry >;
projections : Map <
string ,
{ edge : EdgeDefinition ; endpoint : EdgeEndpoint ; endpointIndex : 0 | 1 }
> ;
constructors : Map < AtomId , AtomConstructorBinding >;
}
const hasText = ( value : string ) => value . trim (). length > 0 ;
const conformanceKey = (
atomId : AtomId ,
interfaceRevisionId : InterfaceRevisionId ,
) : string => ` ${ atomId } \ u0000 ${ interfaceRevisionId } ` ;
const attachmentKey = ( attachment : PersistentAttachment ) : string =>
` ${ attachment . kind } \ u0000 ${ attachment . id } ` ;
const issue = (
issues : CapabilityValidationIssue [],
code : CapabilityValidationIssueCode ,
path : string ,
message : string ,
) => issues . push ({ code , path , message });
const requireText = (
issues : CapabilityValidationIssue [],
value : string ,
path : string ,
label : string ,
) => {
if ( ! hasText ( value )) {
issue ( issues , "required-value" , path , ` ${ label } is required` );
}
};
const typeLabel = ( type : ValueType ) : string => {
switch ( type . kind ) {
case "builtin" :
case "scalar" :
return type . name ;
case "message" :
return `message: ${ type . descriptorId } ` ;
case "object-ref" :
return type . expectation . kind === "atom"
? `object:atom: ${ type . expectation . atomId } `
: `object:interface: ${ type . expectation . interfaceRevisionId } ` ;
case "optional" :
return `optional< ${ typeLabel ( type . value ) } >` ;
case "list" :
return `list< ${ typeLabel ( type . value ) } >` ;
}
};
export const valueTypesEqual = ( left : ValueType , right : ValueType ) : boolean => {
if ( left . kind !== right . kind ) {
return false ;
}
switch ( left . kind ) {
case "builtin" :
case "scalar" :
return left . name === ( right as typeof left ). name ;
case "message" :
return left . descriptorId === ( right as typeof left ). descriptorId ;
case "object-ref" : {
const other = ( right as typeof left ). expectation ;
if ( left . expectation . kind !== other . kind ) {
return false ;
}
return left . expectation . kind === "atom"
? left . expectation . atomId ===
( other as typeof left . expectation ). atomId
: left.expectation.interfaceRevisionId ===
( other as typeof left . expectation ). interfaceRevisionId ;
}
case "optional" :
case "list" :
return valueTypesEqual ( left . value , ( right as typeof left ). value );
}
};
const constraintsEqual = (
left : EdgeEndpointConstraint ,
right : EdgeEndpointConstraint ,
) =>
left . kind === right . kind &&
( left . kind === "atom"
? left . atomId === ( right as typeof left ). atomId
: left.interfaceRevisionId === ( right as typeof left ). interfaceRevisionId );
const sourceRequiredFields : Array < [ keyof SourceRevision , string ] > = [
[ "repository" , "repository" ],
[ "commit" , "commit" ],
];
const validateSource = (
issues : CapabilityValidationIssue [],
source : SourceRevision ,
path : string ,
) => {
for ( const [ key , label ] of sourceRequiredFields ) {
if ( ! hasText ( source [ key ])) {
issue (
issues ,
"invalid-source" ,
` ${ path } . ${ key } ` ,
`Source ${ label } is required` ,
);
}
}
};
const validateValueType = (
issues : CapabilityValidationIssue [],
type : ValueType ,
path : string ,
indexes : Pick < ValidationIndexes , "atoms" | "interfaces" >,
) => {
switch ( type . kind ) {
case "builtin" :
case "scalar" :
return ;
case "message" :
requireText (
issues ,
type . descriptorId ,
` ${ path } .descriptorId` ,
"Message descriptor identity" ,
);
return ;
case "optional" :
case "list" :
validateValueType ( issues , type . value , ` ${ path } .value` , indexes );
return ;
case "object-ref" :
if ( type . expectation . kind === "atom" ) {
if ( ! indexes . atoms . has ( type . expectation . atomId )) {
issue (
issues ,
"unresolved-reference" ,
` ${ path } .expectation.atomId` ,
`Unknown atom ${ type . expectation . atomId } ` ,
);
}
} else if (
! indexes . interfaces . has ( type . expectation . interfaceRevisionId )
) {
issue (
issues ,
"unresolved-reference" ,
` ${ path } .expectation.interfaceRevisionId` ,
`Unknown interface revision ${ type . expectation . interfaceRevisionId } ` ,
);
}
}
};
const validateConstraint = (
issues : CapabilityValidationIssue [],
constraint : EdgeEndpointConstraint ,
path : string ,
indexes : Pick < ValidationIndexes , "atoms" | "interfaces" >,
) => {
if ( constraint . kind === "atom" ) {
if ( ! indexes . atoms . has ( constraint . atomId )) {
issue (
issues ,
"unresolved-reference" ,
` ${ path } .atomId` ,
`Unknown atom ${ constraint . atomId } ` ,
);
}
} else if ( ! indexes . interfaces . has ( constraint . interfaceRevisionId )) {
issue (
issues ,
"unresolved-reference" ,
` ${ path } .interfaceRevisionId` ,
`Unknown interface revision ${ constraint . interfaceRevisionId } ` ,
);
}
};
const emitsEvents = ( mode : InterfaceOperationMode ) =>
mode === "watch-start" || mode === "subscribe" ;
const validateOperationEventShape = (
issues : CapabilityValidationIssue [],
operation : Pick < InterfaceOperation , "mode" | "eventType" >,
path : string ,
) => {
if ( emitsEvents ( operation . mode ) && operation . eventType === undefined ) {
issue (
issues ,
"invalid-operation" ,
` ${ path } .eventType` ,
` ${ operation . mode } operations require an event type` ,
);
}
if ( ! emitsEvents ( operation . mode ) && operation . eventType !== undefined ) {
issue (
issues ,
"invalid-operation" ,
` ${ path } .eventType` ,
` ${ operation . mode } operations must not declare an event type` ,
);
}
};
interface OperationSignature {
mode : InterfaceOperationMode ;
inputType : ValueType ;
outputType : ValueType ;
eventType? : ValueType ;
}
const signaturesMatch = (
operation : OperationSignature ,
implementation : OperationSignature ,
) =>
operation . mode === implementation . mode &&
valueTypesEqual ( operation . inputType , implementation . inputType ) &&
valueTypesEqual ( operation . outputType , implementation . outputType ) &&
( operation . eventType === undefined
? implementation . eventType === undefined
: implementation . eventType !== undefined &&
valueTypesEqual ( operation . eventType , implementation . eventType ));
const describeSignature = ( signature : OperationSignature ) => {
const event = signature . eventType
? ` emits ${ typeLabel ( signature . eventType ) } `
: "" ;
return ` ${ signature . mode } ${ typeLabel ( signature . inputType ) } -> ${ typeLabel ( signature . outputType ) }${ event } ` ;
};
export const statePrimitiveSignature = (
slot : StateSlotDefinition ,
primitive : StatePrimitive ,
) : OperationSignature => {
const writeType =
slot . storagePolicy . kind === "crdt-document"
? slot.storagePolicy.updateType
: slot.valueType ;
switch ( primitive ) {
case "read" :
return {
mode : "call" ,
inputType : valueType.unit ,
outputType : slot.valueType ,
};
case "write" :
return {
mode : "call" ,
inputType : writeType ,
outputType : valueType.unit ,
};
case "watch-start" :
return {
mode : "watch-start" ,
inputType : valueType.unit ,
outputType : valueType.watchHandle ,
eventType : slot.valueType ,
};
case "watch-stop" :
return {
mode : "watch-stop" ,
inputType : valueType.watchHandle ,
outputType : valueType.unit ,
};
}
};
const constraintValueType = ( constraint : EdgeEndpointConstraint ) : ValueType =>
constraint . kind === "atom"
? valueType . atomRef ( constraint . atomId )
: valueType . interfaceRef ( constraint . interfaceRevisionId );
export const cardinalityValueType = (
constraint : EdgeEndpointConstraint ,
cardinality : EdgeCardinality ,
) : ValueType => {
const target = constraintValueType ( constraint );
switch ( cardinality ) {
case "exactly-one" :
return target ;
case "optional-one" :
return valueType . optional ( target );
case "many" :
case "many-unique" :
return valueType . list ( target );
}
};
const edgeProjection = (
edge : EdgeDefinition ,
projectionId : EdgeProjectionId ,
) => {
const index = edge . endpoints . findIndex (
( endpoint ) => endpoint . projectionId === projectionId ,
);
if ( index !== 0 && index !== 1 ) {
return undefined ;
}
const endpointIndex = index as 0 | 1 ;
return {
endpoint : edge.endpoints [ endpointIndex ],
target : edge.endpoints [ endpointIndex === 0 ? 1 : 0 ],
endpointIndex ,
};
};
export const edgePrimitiveSignature = (
edge : EdgeDefinition ,
projectionId : EdgeProjectionId ,
primitive : EdgePrimitive ,
) : OperationSignature | undefined => {
const projection = edgeProjection ( edge , projectionId );
if ( ! projection ) {
return undefined ;
}
const targetType = constraintValueType ( projection . target . constraint );
const resolvedType = cardinalityValueType (
projection . target . constraint ,
projection . endpoint . cardinality ,
);
switch ( primitive ) {
case "resolve" :
return {
mode : "call" ,
inputType : valueType.unit ,
outputType : resolvedType ,
};
case "connect" :
case "disconnect" :
return {
mode : "call" ,
inputType : targetType ,
outputType : valueType.unit ,
};
case "watch-start" :
return {
mode : "watch-start" ,
inputType : valueType.unit ,
outputType : valueType.watchHandle ,
eventType : resolvedType ,
};
case "watch-stop" :
return {
mode : "watch-stop" ,
inputType : valueType.watchHandle ,
outputType : valueType.unit ,
};
}
};
const atomSatisfiesConstraint = (
atomId : AtomId ,
constraint : EdgeEndpointConstraint ,
conformances : ReadonlyMap < string , Conformance >,
) =>
constraint . kind === "atom"
? constraint . atomId === atomId
: conformances.has ( conformanceKey ( atomId , constraint . interfaceRevisionId ));
2026-09-04 21:03:09 -07:00
const constraintSatisfiesConstraint = (
actual : EdgeEndpointConstraint ,
required : EdgeEndpointConstraint ,
conformances : ReadonlyMap < string , Conformance >,
) => constraintsEqual ( actual , required ) || (
actual . kind === "atom" &&
required . kind === "interface" &&
atomSatisfiesConstraint ( actual . atomId , required , conformances )
);
2026-09-03 15:46:52 -07:00
const canAccessAttachment = (
owner : AttachmentOwner ,
conformance : Pick < Conformance , "atomId" | "interfaceRevisionId" > | undefined ,
) =>
owner . kind === "workspace" || (
conformance !== undefined &&
owner . atomId === conformance . atomId &&
owner . interfaceRevisionId === conformance . interfaceRevisionId
);
const collectIdentityIndexes = (
workspace : WorkspaceRevision ,
issues : CapabilityValidationIssue [],
) : ValidationIndexes => {
const atoms = new Map < string , WorkspaceRevision [ "atoms" ][ number ] >();
for ( const [ index , atom ] of workspace . atoms . entries ()) {
const path = `atoms[ ${ index } ]` ;
requireText ( issues , atom . id , ` ${ path } .id` , "Atom ID" );
requireText ( issues , atom . displayName , ` ${ path } .displayName` , "Atom name" );
if ( atoms . has ( atom . id )) {
issue ( issues , "duplicate-atom" , ` ${ path } .id` , `Duplicate atom ${ atom . id } ` );
} else {
atoms . set ( atom . id , atom );
}
}
const interfaces = new Map < string , InterfaceIndexEntry >();
for ( const [ interfaceIndex , revision ] of workspace . interfaceImports . entries ()) {
const path = `interfaceImports[ ${ interfaceIndex } ]` ;
requireText ( issues , revision . interfaceId , ` ${ path } .interfaceId` , "Interface ID" );
requireText (
issues ,
revision . revisionId ,
` ${ path } .revisionId` ,
"Interface revision ID" ,
);
requireText ( issues , revision . displayName , ` ${ path } .displayName` , "Interface name" );
validateSource ( issues , revision . source , ` ${ path } .source` );
const memberIds = new Set < string >();
const operations = new Map < OperationId , InterfaceOperationEntry >();
for ( const [ memberIndex , member ] of revision . members . entries ()) {
const memberPath = ` ${ path } .members[ ${ memberIndex } ]` ;
requireText ( issues , member . id , ` ${ memberPath } .id` , "Member ID" );
requireText ( issues , member . displayName , ` ${ memberPath } .displayName` , "Member name" );
if ( memberIds . has ( member . id )) {
issue (
issues ,
"duplicate-interface-member" ,
` ${ memberPath } .id` ,
`Duplicate member ${ member . id } ` ,
);
}
memberIds . add ( member . id );
for ( const [ operationIndex , operation ] of member . operations . entries ()) {
const operationPath = ` ${ memberPath } .operations[ ${ operationIndex } ]` ;
requireText ( issues , operation . id , ` ${ operationPath } .id` , "Operation ID" );
requireText (
issues ,
operation . displayName ,
` ${ operationPath } .displayName` ,
"Operation name" ,
);
validateOperationEventShape ( issues , operation , operationPath );
if ( operations . has ( operation . id )) {
issue (
issues ,
"duplicate-interface-operation" ,
` ${ operationPath } .id` ,
`Duplicate operation ${ operation . id } ` ,
);
} else {
operations . set ( operation . id , { operation , member });
}
}
}
if ( interfaces . has ( revision . revisionId )) {
issue (
issues ,
"duplicate-interface-revision" ,
` ${ path } .revisionId` ,
`Duplicate interface revision ${ revision . revisionId } ` ,
);
} else {
interfaces . set ( revision . revisionId , { revision , operations });
}
}
const packages = new Map < string , PackageIndexEntry >();
for ( const [ packageIndex , revision ] of workspace . packageImports . entries ()) {
const path = `packageImports[ ${ packageIndex } ]` ;
2026-09-10 18:27:41 -07:00
if ( revision . semanticMajor !== undefined && ( ! Number . isSafeInteger ( revision . semanticMajor ) || revision . semanticMajor < 1 )) {
issue ( issues , "invalid-semantic-major" , ` ${ path } .semanticMajor` , "Semantic major must be a positive safe integer" );
}
2026-09-03 15:46:52 -07:00
requireText ( issues , revision . packageId , ` ${ path } .packageId` , "Package ID" );
requireText (
issues ,
revision . revisionId ,
` ${ path } .revisionId` ,
"Package revision ID" ,
);
requireText ( issues , revision . displayName , ` ${ path } .displayName` , "Package name" );
validateSource ( issues , revision . source , ` ${ path } .source` );
const exports = new Map < string , PackageExport >();
for ( const [ exportIndex , entry ] of revision . exports . entries ()) {
const exportPath = ` ${ path } .exports[ ${ exportIndex } ]` ;
requireText ( issues , entry . id , ` ${ exportPath } .id` , "Package export ID" );
requireText ( issues , entry . displayName , ` ${ exportPath } .displayName` , "Package export name" );
if ( exports . has ( entry . id )) {
issue (
issues ,
"duplicate-package-export" ,
` ${ exportPath } .id` ,
`Duplicate package export ${ entry . id } ` ,
);
} else {
exports . set ( entry . id , entry );
}
const portIds = new Set < string >();
for ( const [ portIndex , port ] of entry . dependencyPorts . entries ()) {
const portPath = ` ${ exportPath } .dependencyPorts[ ${ portIndex } ]` ;
requireText ( issues , port . id , ` ${ portPath } .id` , "Dependency port ID" );
requireText ( issues , port . displayName , ` ${ portPath } .displayName` , "Dependency port name" );
if ( portIds . has ( port . id )) {
issue (
issues ,
"duplicate-dependency-port" ,
` ${ portPath } .id` ,
`Duplicate dependency port ${ port . id } ` ,
);
}
portIds . add ( port . id );
}
}
if ( packages . has ( revision . revisionId )) {
issue (
issues ,
"duplicate-package-revision" ,
` ${ path } .revisionId` ,
`Duplicate package revision ${ revision . revisionId } ` ,
);
} else {
packages . set ( revision . revisionId , { revision , exports });
}
}
const conformances = new Map < string , Conformance >();
const conformancePaths = new Map < string , string >();
2026-09-10 18:27:41 -07:00
const conformanceIds = new Set < string >();
2026-09-03 15:46:52 -07:00
for ( const [ index , conformance ] of workspace . conformances . entries ()) {
const path = `conformances[ ${ index } ]` ;
2026-09-10 18:27:41 -07:00
if ( conformance . semanticMajor !== undefined && ( ! Number . isSafeInteger ( conformance . semanticMajor ) || conformance . semanticMajor < 1 )) {
issue ( issues , "invalid-semantic-major" , ` ${ path } .semanticMajor` , "Semantic major must be a positive safe integer" );
}
if ( conformance . id !== undefined ) {
requireText ( issues , conformance . id , ` ${ path } .id` , "Conformance ID" );
if ( conformanceIds . has ( conformance . id )) issue ( issues , "duplicate-conformance-id" , ` ${ path } .id` , `Duplicate conformance ID ${ conformance . id } ` );
conformanceIds . add ( conformance . id );
}
2026-09-03 15:46:52 -07:00
const key = conformanceKey ( conformance . atomId , conformance . interfaceRevisionId );
if ( conformances . has ( key )) {
issue (
issues ,
"duplicate-conformance" ,
path ,
`Duplicate conformance for ${ conformance . atomId } as ${ conformance . interfaceRevisionId } ` ,
);
} else {
conformances . set ( key , conformance );
conformancePaths . set ( key , path );
}
}
const constructors = new Map < AtomId , AtomConstructorBinding >();
for ( const [ index , constructor ] of workspace . constructors . entries ()) {
const path = `constructors[ ${ index } ]` ;
if ( constructors . has ( constructor . atomId )) {
issue (
issues ,
"duplicate-constructor" ,
path ,
`Atom ${ constructor . atomId } has more than one constructor` ,
);
} else {
constructors . set ( constructor . atomId , constructor );
}
}
const attachments = new Map < string , AttachmentIndexEntry >();
const projections = new Map <
string ,
{ edge : EdgeDefinition ; endpoint : EdgeEndpoint ; endpointIndex : 0 | 1 }
> ();
const addAttachment = (
attachment : PersistentAttachment ,
owner : AttachmentOwner ,
path : string ,
) => {
const key = attachmentKey ( attachment );
if ( attachments . has ( key )) {
issue (
issues ,
"duplicate-attachment" ,
` ${ path } .id` ,
`Duplicate ${ attachment . kind } attachment ${ attachment . id } ` ,
);
} else {
attachments . set ( key , { attachment , owner , path });
}
if ( attachment . kind === "edge" ) {
for ( const [ endpointIndex , endpoint ] of attachment . endpoints . entries ()) {
const endpointPath = ` ${ path } .endpoints[ ${ endpointIndex } ]` ;
if ( projections . has ( endpoint . projectionId )) {
issue (
issues ,
"duplicate-projection" ,
` ${ endpointPath } .projectionId` ,
`Duplicate edge projection ${ endpoint . projectionId } ` ,
);
} else {
projections . set ( endpoint . projectionId , {
edge : attachment ,
endpoint ,
endpointIndex : endpointIndex as 0 | 1 ,
});
}
}
}
};
for ( const [ index , attachment ] of workspace . sharedAttachments . entries ()) {
addAttachment ( attachment , { kind : "workspace" }, `sharedAttachments[ ${ index } ]` );
}
for ( const [ conformanceIndex , conformance ] of workspace . conformances . entries ()) {
for ( const [ attachmentIndex , attachment ] of conformance . privateAttachments . entries ()) {
addAttachment (
attachment ,
{
kind : "conformance" ,
atomId : conformance.atomId ,
interfaceRevisionId : conformance.interfaceRevisionId ,
},
`conformances[ ${ conformanceIndex } ].privateAttachments[ ${ attachmentIndex } ]` ,
);
}
}
return {
atoms ,
interfaces ,
packages ,
conformances ,
conformancePaths ,
attachments ,
projections ,
constructors ,
};
};
const validateInterfaces = (
workspace : WorkspaceRevision ,
issues : CapabilityValidationIssue [],
indexes : ValidationIndexes ,
) => {
for ( const [ interfaceIndex , revision ] of workspace . interfaceImports . entries ()) {
const path = `interfaceImports[ ${ interfaceIndex } ]` ;
for ( const [ memberIndex , member ] of revision . members . entries ()) {
const memberPath = ` ${ path } .members[ ${ memberIndex } ]` ;
if ( member . kind === "value" ) {
validateValueType ( issues , member . valueType , ` ${ memberPath } .valueType` , indexes );
} else if ( member . kind === "relationship" ) {
validateConstraint ( issues , member . target , ` ${ memberPath } .target` , indexes );
} else {
validateValueType ( issues , member . inputType , ` ${ memberPath } .inputType` , indexes );
validateValueType ( issues , member . outputType , ` ${ memberPath } .outputType` , indexes );
}
for ( const [ operationIndex , operation ] of member . operations . entries ()) {
const operationPath = ` ${ memberPath } .operations[ ${ operationIndex } ]` ;
validateValueType ( issues , operation . inputType , ` ${ operationPath } .inputType` , indexes );
validateValueType ( issues , operation . outputType , ` ${ operationPath } .outputType` , indexes );
if ( operation . eventType ) {
validateValueType ( issues , operation . eventType , ` ${ operationPath } .eventType` , indexes );
}
}
}
}
};
const validateAttachments = (
issues : CapabilityValidationIssue [],
indexes : ValidationIndexes ,
) => {
for ( const { attachment , owner , path } of indexes . attachments . values ()) {
requireText ( issues , attachment . id , ` ${ path } .id` , ` ${ attachment . kind } attachment ID` );
requireText ( issues , attachment . displayName , ` ${ path } .displayName` , ` ${ attachment . kind } name` );
if ( attachment . kind === "state" ) {
if ( ! indexes . atoms . has ( attachment . attachedTo )) {
issue (
issues ,
"unresolved-reference" ,
` ${ path } .attachedTo` ,
`Unknown atom ${ attachment . attachedTo } ` ,
);
}
validateValueType ( issues , attachment . valueType , ` ${ path } .valueType` , indexes );
2026-09-10 18:27:41 -07:00
const containsReference = ( type : ValueType ) : boolean => type . kind === "object-ref" || (( type . kind === "optional" || type . kind === "list" ) && containsReference ( type . value ));
if ( containsReference ( attachment . valueType ) || ( attachment . storagePolicy . kind === "crdt-document" && containsReference ( attachment . storagePolicy . updateType ))) {
issue ( issues , "invalid-attachment" , ` ${ path } .valueType` , "Managed object references belong in graph relationships, not ordinary state" );
}
2026-09-03 15:46:52 -07:00
if ( attachment . storagePolicy . kind === "crdt-document" ) {
validateValueType (
issues ,
attachment . storagePolicy . updateType ,
` ${ path } .storagePolicy.updateType` ,
indexes ,
);
}
if ( owner . kind === "conformance" ) {
if ( attachment . attachedTo !== owner . atomId ) {
issue (
issues ,
"invalid-attachment" ,
` ${ path } .attachedTo` ,
`Private state must attach to its conformance atom ${ owner . atomId } ` ,
);
}
}
continue ;
}
if ( attachment . endpoints . length !== 2 ) {
issue (
issues ,
"invalid-attachment" ,
` ${ path } .endpoints` ,
`Edge ${ attachment . id } must have exactly two endpoints` ,
);
}
for ( const [ endpointIndex , endpoint ] of attachment . endpoints . entries ()) {
const endpointPath = ` ${ path } .endpoints[ ${ endpointIndex } ]` ;
2026-09-10 18:27:41 -07:00
if ( endpoint . keyType !== undefined && ( ! [ "string" , "boolean" , "int64" ]. includes ( endpoint . keyType ) || endpoint . ordered || ! [ "many" , "many-unique" ]. includes ( endpoint . cardinality ))) {
issue ( issues , "invalid-attachment" , ` ${ endpointPath } .keyType` , "Keyed projections require string/boolean/int64 keys, many cardinality, and no ordering" );
}
2026-09-03 15:46:52 -07:00
requireText ( issues , endpoint . projectionId , ` ${ endpointPath } .projectionId` , "Projection ID" );
2026-09-10 18:27:41 -07:00
if ( endpoint . onDelete !== undefined && ! [ "restrict" , "detach" , "cascade-other" ]. includes ( endpoint . onDelete )) {
issue ( issues , "invalid-attachment" , ` ${ endpointPath } .onDelete` , "Deletion policy must be restrict, detach, or cascade-other" );
}
2026-09-03 15:46:52 -07:00
requireText ( issues , endpoint . displayName , ` ${ endpointPath } .displayName` , "Projection name" );
validateConstraint ( issues , endpoint . constraint , ` ${ endpointPath } .constraint` , indexes );
}
2026-09-10 18:27:41 -07:00
if ( attachment . endpoints . every (( endpoint ) => endpoint . keyType )) issue ( issues , "invalid-attachment" , ` ${ path } .endpoints` , "A v0 map has one keyed projection and one unkeyed inverse" );
2026-09-03 15:46:52 -07:00
if ( owner . kind === "conformance" ) {
if (
! attachment . endpoints . some (( endpoint ) =>
atomSatisfiesConstraint ( owner . atomId , endpoint . constraint , indexes . conformances ),
)
) {
issue (
issues ,
"invalid-attachment" ,
` ${ path } .endpoints` ,
`Private edge has no endpoint compatible with conformance atom ${ owner . atomId } ` ,
);
}
}
}
};
const uniquePrimitiveList = (
issues : CapabilityValidationIssue [],
primitives : readonly string [],
path : string ,
) => {
if ( primitives . length === 0 ) {
issue ( issues , "invalid-dependency-binding" , path , "Dependency port requires at least one primitive" );
}
const seen = new Set < string >();
for ( const primitive of primitives ) {
if ( seen . has ( primitive )) {
issue (
issues ,
"invalid-dependency-binding" ,
path ,
`Dependency primitive ${ primitive } is listed more than once` ,
);
}
seen . add ( primitive );
}
};
const validatePackages = (
workspace : WorkspaceRevision ,
issues : CapabilityValidationIssue [],
indexes : ValidationIndexes ,
) => {
for ( const [ packageIndex , revision ] of workspace . packageImports . entries ()) {
const path = `packageImports[ ${ packageIndex } ]` ;
for ( const [ exportIndex , entry ] of revision . exports . entries ()) {
const exportPath = ` ${ path } .exports[ ${ exportIndex } ]` ;
validateValueType ( issues , entry . inputType , ` ${ exportPath } .inputType` , indexes );
validateValueType ( issues , entry . outputType , ` ${ exportPath } .outputType` , indexes );
if ( entry . kind === "operation" ) {
validateOperationEventShape ( issues , entry , exportPath );
if ( entry . eventType ) {
validateValueType ( issues , entry . eventType , ` ${ exportPath } .eventType` , indexes );
}
if ( entry . receiverRequirement . kind === "exact-atom" ) {
if ( ! indexes . atoms . has ( entry . receiverRequirement . atomId )) {
issue (
issues ,
"unresolved-reference" ,
` ${ exportPath } .receiverRequirement.atomId` ,
`Unknown atom ${ entry . receiverRequirement . atomId } ` ,
);
}
} else if ( entry . receiverRequirement . kind === "all-interfaces" ) {
const seen = new Set < string >();
for ( const [ requirementIndex , interfaceRevisionId ] of
entry . receiverRequirement . interfaceRevisionIds . entries ()) {
const requirementPath = ` ${ exportPath } .receiverRequirement.interfaceRevisionIds[ ${ requirementIndex } ]` ;
if ( ! indexes . interfaces . has ( interfaceRevisionId )) {
issue (
issues ,
"unresolved-reference" ,
requirementPath ,
`Unknown interface revision ${ interfaceRevisionId } ` ,
);
}
if ( seen . has ( interfaceRevisionId )) {
issue (
issues ,
"invalid-operation" ,
requirementPath ,
`Receiver interface ${ interfaceRevisionId } is duplicated` ,
);
}
seen . add ( interfaceRevisionId );
}
}
} else if ( entry . kind === "constructor" ) {
if ( ! indexes . atoms . has ( entry . constructsAtom )) {
issue (
issues ,
"unresolved-reference" ,
` ${ exportPath } .constructsAtom` ,
`Unknown atom ${ entry . constructsAtom } ` ,
);
}
const expected = valueType . atomRef ( entry . constructsAtom );
if ( ! valueTypesEqual ( entry . outputType , expected )) {
issue (
issues ,
"invalid-constructor" ,
` ${ exportPath } .outputType` ,
`Constructor must return ${ typeLabel ( expected ) } , not ${ typeLabel ( entry . outputType ) } ` ,
);
}
}
for ( const [ portIndex , port ] of entry . dependencyPorts . entries ()) {
const portPath = ` ${ exportPath } .dependencyPorts[ ${ portIndex } ]` ;
switch ( port . requirement . kind ) {
case "state" :
validateValueType ( issues , port . requirement . valueType , ` ${ portPath } .requirement.valueType` , indexes );
uniquePrimitiveList ( issues , port . requirement . primitives , ` ${ portPath } .requirement.primitives` );
break ;
case "edge" :
validateConstraint ( issues , port . requirement . target , ` ${ portPath } .requirement.target` , indexes );
uniquePrimitiveList ( issues , port . requirement . primitives , ` ${ portPath } .requirement.primitives` );
break ;
2026-09-05 12:33:52 -07:00
case "interface" :
2026-09-03 15:46:52 -07:00
if ( ! indexes . interfaces . has ( port . requirement . interfaceRevisionId )) {
issue (
issues ,
"unresolved-reference" ,
` ${ portPath } .requirement.interfaceRevisionId` ,
`Unknown interface revision ${ port . requirement . interfaceRevisionId } ` ,
);
}
break ;
case "constructor" :
2026-09-08 14:27:24 -07:00
if ( port . requirement . inputType ) validateValueType ( issues , port . requirement . inputType , ` ${ portPath } .requirement.inputType` , indexes );
2026-09-03 15:46:52 -07:00
if ( ! indexes . atoms . has ( port . requirement . atomId )) {
issue (
issues ,
"unresolved-reference" ,
` ${ portPath } .requirement.atomId` ,
`Unknown atom ${ port . requirement . atomId } ` ,
);
}
}
}
}
}
};
const findAttachment = < Kind extends PersistentAttachment [ "kind" ] >(
indexes : ValidationIndexes ,
kind : Kind ,
id : Kind extends "state" ? SlotId : EdgeTypeId ,
) : AttachmentIndexEntry | undefined => indexes . attachments . get ( ` ${ kind } \ u0000 ${ id } ` );
const validateAttachmentAccess = (
issues : CapabilityValidationIssue [],
entry : AttachmentIndexEntry ,
conformance : Pick < Conformance , "atomId" | "interfaceRevisionId" > | undefined ,
path : string ,
) => {
if ( ! canAccessAttachment ( entry . owner , conformance )) {
issue (
issues ,
"private-attachment-access" ,
path ,
`Attachment ${ entry . attachment . id } is private to conformance ${
entry . owner . kind === "conformance"
? ` ${ entry . owner . atomId } as ${ entry . owner . interfaceRevisionId } `
: ""
} ` ,
);
return false ;
}
return true ;
};
2026-09-04 21:03:09 -07:00
const validateTraversal = (
issues : CapabilityValidationIssue [],
indexes : ValidationIndexes ,
atomId : AtomId ,
traversal : { edgeTypeId : EdgeTypeId ; projectionId : EdgeProjectionId },
path : string ,
2026-09-05 12:33:52 -07:00
conformance? : Pick < Conformance , "atomId" | "interfaceRevisionId" >,
2026-09-04 21:03:09 -07:00
) => {
const attachment = findAttachment ( indexes , "edge" , traversal . edgeTypeId );
if ( ! attachment || attachment . attachment . kind !== "edge" ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .edgeTypeId` ,
`Unknown traversal edge ${ traversal . edgeTypeId } ` ,
);
return undefined ;
}
const projection = edgeProjection ( attachment . attachment , traversal . projectionId );
if ( ! projection ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .projectionId` ,
`Traversal projection ${ traversal . projectionId } is not on edge ${ traversal . edgeTypeId } ` ,
);
return undefined ;
}
2026-09-10 18:27:41 -07:00
if ( ! projection . endpoint . publicTraversal ) validateAttachmentAccess ( issues , attachment , conformance , ` ${ path } .edgeTypeId` );
2026-09-04 21:03:09 -07:00
if ( ! atomSatisfiesConstraint ( atomId , projection . endpoint . constraint , indexes . conformances )) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .projectionId` ,
`Traversal projection ${ traversal . projectionId } cannot originate at receiver atom ${ atomId } ` ,
);
}
if ( projection . endpoint . cardinality !== "exactly-one" ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .projectionId` ,
"Dependency traversal must select exactly one object" ,
);
}
return projection ;
};
2026-09-03 15:46:52 -07:00
const validateBoundDependencies = (
issues : CapabilityValidationIssue [],
params : {
dependencies : BoundDependency [];
dependencyPorts : DependencyPort [];
atomId : AtomId ;
conformance? : Pick < Conformance , "atomId" | "interfaceRevisionId" >;
path : string ;
indexes : ValidationIndexes ;
requirementGraph : Map < string , Set < string >>;
graphSourceKey? : string ;
},
) => {
const ports = new Map ( params . dependencyPorts . map (( port ) => [ port . id , port ]));
const bindings = new Map < string , BoundDependency >();
for ( const [ index , dependency ] of params . dependencies . entries ()) {
const path = ` ${ params . path } .dependencies[ ${ index } ]` ;
if ( bindings . has ( dependency . portId )) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .portId` ,
`Dependency port ${ dependency . portId } is bound more than once` ,
);
continue ;
}
bindings . set ( dependency . portId , dependency );
const port = ports . get ( dependency . portId );
if ( ! port ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .portId` ,
`Unknown dependency port ${ dependency . portId } ` ,
);
continue ;
}
const requirement = port . requirement ;
const binding = dependency . binding ;
if ( requirement . kind !== binding . kind ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding` ,
`Port ${ port . id } requires ${ requirement . kind } , not ${ binding . kind } ` ,
);
continue ;
}
switch ( requirement . kind ) {
case "state" : {
const stateBinding = binding as Extract < DependencyBinding , { kind : "state" }>;
const attachment = findAttachment ( params . indexes , "state" , stateBinding . slotId );
if ( ! attachment || attachment . attachment . kind !== "state" ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding.slotId` ,
`Unknown state attachment ${ stateBinding . slotId } ` ,
);
break ;
}
validateAttachmentAccess ( issues , attachment , params . conformance , ` ${ path } .binding.slotId` );
2026-09-04 21:03:09 -07:00
const traversal = stateBinding . via
? validateTraversal (
issues ,
params . indexes ,
params . atomId ,
stateBinding . via ,
` ${ path } .binding.via` ,
2026-09-05 12:33:52 -07:00
params . conformance ,
2026-09-04 21:03:09 -07:00
)
: undefined ;
if (
stateBinding . via
? traversal && ! atomSatisfiesConstraint (
attachment . attachment . attachedTo ,
traversal . target . constraint ,
params . indexes . conformances ,
)
: attachment . attachment . attachedTo !== params . atomId
) {
2026-09-03 15:46:52 -07:00
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding.slotId` ,
2026-09-04 21:03:09 -07:00
stateBinding . via
? `State ${ stateBinding . slotId } is not attached to the traversal target`
: `State ${ stateBinding . slotId } is not attached to receiver atom ${ params . atomId } ` ,
2026-09-03 15:46:52 -07:00
);
}
if ( ! valueTypesEqual ( requirement . valueType , attachment . attachment . valueType )) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding.slotId` ,
`State port expects ${ typeLabel ( requirement . valueType ) } , not ${ typeLabel ( attachment . attachment . valueType ) } ` ,
);
}
break ;
}
case "edge" : {
const edgeBinding = binding as Extract < DependencyBinding , { kind : "edge" }>;
const attachment = findAttachment ( params . indexes , "edge" , edgeBinding . edgeTypeId );
if ( ! attachment || attachment . attachment . kind !== "edge" ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding.edgeTypeId` ,
`Unknown edge attachment ${ edgeBinding . edgeTypeId } ` ,
);
break ;
}
validateAttachmentAccess ( issues , attachment , params . conformance , ` ${ path } .binding.edgeTypeId` );
const projection = edgeProjection ( attachment . attachment , edgeBinding . projectionId );
if ( ! projection ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding.projectionId` ,
`Projection ${ edgeBinding . projectionId } is not on edge ${ edgeBinding . edgeTypeId } ` ,
);
break ;
}
2026-09-04 21:03:09 -07:00
const traversal = edgeBinding . via
? validateTraversal (
issues ,
params . indexes ,
params . atomId ,
edgeBinding . via ,
` ${ path } .binding.via` ,
2026-09-05 12:33:52 -07:00
params . conformance ,
2026-09-04 21:03:09 -07:00
)
: undefined ;
const originMatches = edgeBinding . via
? traversal && (
projection . endpoint . constraint . kind === "atom"
? atomSatisfiesConstraint (
projection . endpoint . constraint . atomId ,
traversal . target . constraint ,
params . indexes . conformances ,
)
: constraintsEqual ( projection . endpoint . constraint , traversal . target . constraint )
)
: atomSatisfiesConstraint (
params . atomId ,
projection . endpoint . constraint ,
params . indexes . conformances ,
);
if ( ! originMatches ) {
2026-09-03 15:46:52 -07:00
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding.projectionId` ,
2026-09-04 21:03:09 -07:00
edgeBinding . via
? `Projection ${ edgeBinding . projectionId } cannot originate at the traversal target`
: `Projection ${ edgeBinding . projectionId } cannot originate at receiver atom ${ params . atomId } ` ,
2026-09-03 15:46:52 -07:00
);
}
if (
2026-09-04 21:03:09 -07:00
! constraintSatisfiesConstraint (
projection . target . constraint ,
requirement . target ,
params . indexes . conformances ,
) ||
2026-09-03 15:46:52 -07:00
requirement . cardinality !== projection . endpoint . cardinality
) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding` ,
`Edge port target or cardinality does not match projection ${ edgeBinding . projectionId } ` ,
);
}
break ;
}
2026-09-05 12:33:52 -07:00
case "interface" : {
2026-09-03 15:46:52 -07:00
const interfaceBinding = binding as Extract <
DependencyBinding ,
2026-09-05 12:33:52 -07:00
{ kind : "interface" }
2026-09-03 15:46:52 -07:00
> ;
if ( interfaceBinding . interfaceRevisionId !== requirement . interfaceRevisionId ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding.interfaceRevisionId` ,
`Interface port requires ${ requirement . interfaceRevisionId } ` ,
);
break ;
}
2026-09-05 12:33:52 -07:00
const traversal = interfaceBinding . via
? validateTraversal (
issues ,
params . indexes ,
params . atomId ,
interfaceBinding . via ,
` ${ path } .binding.via` ,
params . conformance ,
)
: undefined ;
const candidateAtoms = interfaceBinding . via
? traversal
? [... params . indexes . atoms . keys ()]. filter (( atomId ) =>
atomSatisfiesConstraint (
atomId as AtomId ,
traversal . target . constraint ,
params . indexes . conformances ,
)) as AtomId []
: []
: [ params . atomId ];
for ( const atomId of candidateAtoms ) {
const targetKey = conformanceKey ( atomId , requirement . interfaceRevisionId );
if ( ! params . indexes . conformances . has ( targetKey )) {
issue (
issues ,
"unsatisfied-interface" ,
` ${ path } .binding.interfaceRevisionId` ,
` ${ interfaceBinding . via ? "Related" : "Receiver" } atom ${ atomId } does not conform to ${ requirement . interfaceRevisionId } ` ,
);
} else if ( params . graphSourceKey ) {
params . requirementGraph . get ( params . graphSourceKey ) ? . add ( targetKey );
}
2026-09-03 15:46:52 -07:00
}
break ;
}
case "constructor" : {
const constructorBinding = binding as Extract < DependencyBinding , { kind : "constructor" }>;
if ( constructorBinding . atomId !== requirement . atomId ) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding.atomId` ,
`Constructor port requires atom ${ requirement . atomId } ` ,
);
}
if ( ! params . indexes . constructors . has ( requirement . atomId )) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ path } .binding.atomId` ,
`Atom ${ requirement . atomId } has no constructor binding` ,
);
}
2026-09-08 14:27:24 -07:00
if ( requirement . inputType ) {
const selected = params . indexes . constructors . get ( requirement . atomId );
const implementation = selected ? params . indexes . packages . get ( selected . packageRevisionId ) ? . exports . get ( selected . exportId ) : undefined ;
if ( implementation && ! valueTypesEqual ( requirement . inputType , implementation . inputType )) {
issue ( issues , "invalid-dependency-binding" , ` ${ path } .binding.atomId` ,
`Constructor port requires input ${ typeLabel ( requirement . inputType ) } , but selected constructor accepts ${ typeLabel ( implementation . inputType ) } ` );
}
}
2026-09-03 15:46:52 -07:00
break ;
}
}
}
for ( const port of params . dependencyPorts ) {
if ( ! bindings . has ( port . id )) {
issue (
issues ,
"invalid-dependency-binding" ,
` ${ params . path } .dependencies` ,
`Missing binding for dependency port ${ port . id } ` ,
);
}
}
};
const validatePackageReceiver = (
issues : CapabilityValidationIssue [],
params : {
entry : PackageOperationExport ;
atomId : AtomId ;
path : string ;
indexes : ValidationIndexes ;
requirementGraph : Map < string , Set < string >>;
graphSourceKey : string ;
},
) => {
const receiver = params . entry . receiverRequirement ;
if ( receiver . kind === "exact-atom" && receiver . atomId !== params . atomId ) {
issue (
issues ,
"incompatible-package-receiver" ,
params . path ,
`Package export requires atom ${ receiver . atomId } , not ${ params . atomId } ` ,
);
}
if ( receiver . kind === "all-interfaces" ) {
for ( const requiredInterface of receiver . interfaceRevisionIds ) {
const targetKey = conformanceKey ( params . atomId , requiredInterface );
if ( ! params . indexes . conformances . has ( targetKey )) {
issue (
issues ,
2026-09-05 12:33:52 -07:00
"unsatisfied-interface" ,
2026-09-03 15:46:52 -07:00
params . path ,
`Atom ${ params . atomId } does not conform to ${ requiredInterface } ` ,
);
} else {
params . requirementGraph . get ( params . graphSourceKey ) ? . add ( targetKey );
}
}
}
};
const validateConformances = (
workspace : WorkspaceRevision ,
issues : CapabilityValidationIssue [],
indexes : ValidationIndexes ,
) => {
const requirementGraph = new Map < string , Set < string >>();
for ( const key of indexes . conformances . keys ()) {
requirementGraph . set ( key , new Set ());
}
for ( const [ index , conformance ] of workspace . conformances . entries ()) {
const path = `conformances[ ${ index } ]` ;
const key = conformanceKey ( conformance . atomId , conformance . interfaceRevisionId );
if ( ! indexes . atoms . has ( conformance . atomId )) {
issue (
issues ,
"unresolved-reference" ,
` ${ path } .atomId` ,
`Unknown atom ${ conformance . atomId } ` ,
);
}
const interfaceEntry = indexes . interfaces . get ( conformance . interfaceRevisionId );
if ( ! interfaceEntry ) {
issue (
issues ,
"unresolved-reference" ,
` ${ path } .interfaceRevisionId` ,
`Unknown interface revision ${ conformance . interfaceRevisionId } ` ,
);
continue ;
}
const bindings = new Map < OperationId , Binding >();
for ( const [ bindingIndex , entry ] of conformance . operationBindings . entries ()) {
const bindingPath = ` ${ path } .operationBindings[ ${ bindingIndex } ]` ;
if ( bindings . has ( entry . operationId )) {
issue (
issues ,
"duplicate-operation-binding" ,
` ${ bindingPath } .operationId` ,
`Operation ${ entry . operationId } is bound more than once` ,
);
continue ;
}
bindings . set ( entry . operationId , entry . binding );
const operationEntry = interfaceEntry . operations . get ( entry . operationId );
if ( ! operationEntry ) {
issue (
issues ,
"unknown-operation-binding" ,
` ${ bindingPath } .operationId` ,
`Operation ${ entry . operationId } does not belong to interface ${ conformance . interfaceRevisionId } ` ,
);
continue ;
}
const operation = operationEntry . operation ;
const binding = entry . binding ;
if ( binding . kind === "state" ) {
const attachment = findAttachment ( indexes , "state" , binding . slotId );
if ( ! attachment || attachment . attachment . kind !== "state" ) {
issue (
issues ,
"invalid-state-binding" ,
` ${ bindingPath } .binding.slotId` ,
`Unknown state attachment ${ binding . slotId } ` ,
);
continue ;
}
validateAttachmentAccess ( issues , attachment , conformance , ` ${ bindingPath } .binding.slotId` );
if ( attachment . attachment . attachedTo !== conformance . atomId ) {
issue (
issues ,
"invalid-state-binding" ,
` ${ bindingPath } .binding.slotId` ,
`State ${ binding . slotId } is not attached to atom ${ conformance . atomId } ` ,
);
}
if ( operationEntry . member . kind !== "value" ) {
issue (
issues ,
"invalid-state-binding" ,
` ${ bindingPath } .binding` ,
"State primitives may only implement value members" ,
);
}
const expected = statePrimitiveSignature ( attachment . attachment , binding . primitive );
if ( ! signaturesMatch ( operation , expected )) {
issue (
issues ,
"invalid-state-binding" ,
` ${ bindingPath } .binding` ,
`State primitive provides ${ describeSignature ( expected ) } , but operation requires ${ describeSignature ( operation ) } ` ,
);
}
continue ;
}
if ( binding . kind === "edge" ) {
const attachment = findAttachment ( indexes , "edge" , binding . edgeTypeId );
if ( ! attachment || attachment . attachment . kind !== "edge" ) {
issue (
issues ,
"invalid-edge-binding" ,
` ${ bindingPath } .binding.edgeTypeId` ,
`Unknown edge attachment ${ binding . edgeTypeId } ` ,
);
continue ;
}
validateAttachmentAccess ( issues , attachment , conformance , ` ${ bindingPath } .binding.edgeTypeId` );
const projection = edgeProjection ( attachment . attachment , binding . projectionId );
2026-09-04 21:03:09 -07:00
const relationshipMember = operationEntry . member . kind === "relationship"
? operationEntry.member
: undefined ;
const operationEdge = relationshipMember
? {
... attachment . attachment ,
endpoints : attachment.attachment.endpoints.map (( endpoint , index ) =>
index === ( projection ? . endpointIndex === 0 ? 1 : 0 )
? { ... endpoint , constraint : relationshipMember.target }
: endpoint ,
) as [ EdgeEndpoint , EdgeEndpoint ],
}
: attachment . attachment ;
2026-09-03 15:46:52 -07:00
const expected = edgePrimitiveSignature (
2026-09-04 21:03:09 -07:00
operationEdge ,
2026-09-03 15:46:52 -07:00
binding . projectionId ,
binding . primitive ,
);
if ( ! projection || ! expected ) {
issue (
issues ,
"invalid-edge-binding" ,
` ${ bindingPath } .binding.projectionId` ,
`Projection ${ binding . projectionId } is not on edge ${ binding . edgeTypeId } ` ,
);
continue ;
}
if ( ! atomSatisfiesConstraint ( conformance . atomId , projection . endpoint . constraint , indexes . conformances )) {
issue (
issues ,
"invalid-edge-binding" ,
` ${ bindingPath } .binding.projectionId` ,
`Projection ${ binding . projectionId } cannot originate at atom ${ conformance . atomId } ` ,
);
}
if ( operationEntry . member . kind !== "relationship" ) {
issue (
issues ,
"invalid-edge-binding" ,
` ${ bindingPath } .binding` ,
"Edge primitives may only implement relationship members" ,
);
} else if (
2026-09-04 21:03:09 -07:00
! constraintSatisfiesConstraint (
projection . target . constraint ,
operationEntry . member . target ,
indexes . conformances ,
) ||
2026-09-03 15:46:52 -07:00
operationEntry . member . cardinality !== projection . endpoint . cardinality
) {
issue (
issues ,
"invalid-edge-binding" ,
` ${ bindingPath } .binding` ,
"Edge projection target or cardinality does not match relationship member" ,
);
}
if ( ! signaturesMatch ( operation , expected )) {
issue (
issues ,
"invalid-edge-binding" ,
` ${ bindingPath } .binding` ,
`Edge primitive provides ${ describeSignature ( expected ) } , but operation requires ${ describeSignature ( operation ) } ` ,
);
}
continue ;
}
const packageEntry = indexes . packages . get ( binding . packageRevisionId );
const packageExport = packageEntry ? . exports . get ( binding . exportId );
if ( ! packageEntry ) {
issue (
issues ,
"invalid-package-binding" ,
` ${ bindingPath } .binding.packageRevisionId` ,
`Unknown package revision ${ binding . packageRevisionId } ` ,
);
continue ;
}
if ( ! packageExport ) {
issue (
issues ,
"invalid-package-binding" ,
` ${ bindingPath } .binding.exportId` ,
`Unknown export ${ binding . exportId } in package ${ binding . packageRevisionId } ` ,
);
continue ;
}
if ( packageExport . kind !== "operation" ) {
issue (
issues ,
"invalid-package-binding" ,
` ${ bindingPath } .binding.exportId` ,
`Package export ${ binding . exportId } is ${ packageExport . kind } , not an operation` ,
);
continue ;
}
if ( ! signaturesMatch ( operation , packageExport )) {
issue (
issues ,
"invalid-package-binding" ,
` ${ bindingPath } .binding.exportId` ,
`Package export provides ${ describeSignature ( packageExport ) } , but operation requires ${ describeSignature ( operation ) } ` ,
);
}
validatePackageReceiver ( issues , {
entry : packageExport ,
atomId : conformance.atomId ,
path : ` ${ bindingPath } .binding.exportId` ,
indexes ,
requirementGraph ,
graphSourceKey : key ,
});
validateBoundDependencies ( issues , {
dependencies : binding.dependencies ,
dependencyPorts : packageExport.dependencyPorts ,
atomId : conformance.atomId ,
conformance ,
path : ` ${ bindingPath } .binding` ,
indexes ,
requirementGraph ,
graphSourceKey : key ,
});
}
2026-09-04 21:03:09 -07:00
const materializedMembers = new Set < string >();
for ( const [ materializationIndex , materialization ] of
( conformance . relationshipMaterializations ?? []). entries ()) {
const materializationPath =
` ${ path } .relationshipMaterializations[ ${ materializationIndex } ]` ;
if ( materializedMembers . has ( materialization . memberId )) {
issue (
issues ,
"duplicate-relationship-materialization" ,
materializationPath ,
`Relationship ${ materialization . memberId } has more than one materialization recipe` ,
);
continue ;
}
materializedMembers . add ( materialization . memberId );
const member = interfaceEntry . revision . members . find (( entry ) =>
entry . id === materialization . memberId );
if ( ! member || member . kind !== "relationship" ) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .memberId` ,
`Member ${ materialization . memberId } is not a relationship on ${ conformance . interfaceRevisionId } ` ,
);
continue ;
}
if ( member . cardinality !== "optional-one" ) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .memberId` ,
"A lazily constructed relationship must be optional-one before construction" ,
);
}
const resolveOperation = member . operations . find (( entry ) =>
entry . displayName === "resolve" );
const resolveBinding = resolveOperation
? bindings . get ( resolveOperation . id )
: undefined ;
if ( ! resolveBinding || resolveBinding . kind !== "edge" ) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .memberId` ,
"A materialized relationship must bind its resolve operation to an edge" ,
);
continue ;
}
if ( resolveBinding . edgeTypeId !== materialization . edgeTypeId ) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .edgeTypeId` ,
"Materialization and relationship resolution must use the same edge" ,
);
}
const attachment = findAttachment ( indexes , "edge" , materialization . edgeTypeId );
if ( ! attachment || attachment . attachment . kind !== "edge" ) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .edgeTypeId` ,
`Unknown materialization edge ${ materialization . edgeTypeId } ` ,
);
continue ;
}
validateAttachmentAccess (
issues ,
attachment ,
conformance ,
` ${ materializationPath } .edgeTypeId` ,
);
const hostProjection = edgeProjection (
attachment . attachment ,
resolveBinding . projectionId ,
);
const constructedProjection = edgeProjection (
attachment . attachment ,
materialization . constructedProjectionId ,
);
if ( ! hostProjection || ! constructedProjection ||
hostProjection . endpointIndex === constructedProjection . endpointIndex ) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .constructedProjectionId` ,
"Materialization must connect through the opposite projection of the resolved edge" ,
);
continue ;
}
if ( ! atomSatisfiesConstraint (
materialization . constructorAtomId ,
member . target ,
indexes . conformances ,
)) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .constructorAtomId` ,
`Constructed atom ${ materialization . constructorAtomId } does not satisfy the relationship target` ,
);
}
if ( ! atomSatisfiesConstraint (
materialization . constructorAtomId ,
constructedProjection . endpoint . constraint ,
indexes . conformances ,
) || ! atomSatisfiesConstraint (
conformance . atomId ,
constructedProjection . target . constraint ,
indexes . conformances ,
)) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .constructedProjectionId` ,
"Constructed projection does not connect the constructed atom back to the host atom" ,
);
}
const constructor = indexes . constructors . get ( materialization . constructorAtomId );
const constructorExport = constructor
? indexes . packages . get ( constructor . packageRevisionId ) ? . exports . get ( constructor . exportId )
: undefined ;
if ( ! constructor || ! constructorExport || constructorExport . kind !== "constructor" ) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .constructorAtomId` ,
`Constructed atom ${ materialization . constructorAtomId } has no valid constructor` ,
);
} else if ( ! valueTypesEqual (
constructorExport . inputType ,
valueType . atomRef ( conformance . atomId ),
)) {
issue (
issues ,
"invalid-relationship-materialization" ,
` ${ materializationPath } .constructorAtomId` ,
`Component constructor must accept ${ typeLabel ( valueType . atomRef ( conformance . atomId )) } ` ,
);
}
}
2026-09-03 15:46:52 -07:00
for ( const operation of interfaceEntry . operations . values ()) {
if ( ! bindings . has ( operation . operation . id )) {
issue (
issues ,
"missing-operation-binding" ,
` ${ path } .operationBindings` ,
`Missing binding for operation ${ operation . operation . id } ` ,
);
}
}
}
const visitState = new Map < string , "visiting" | "visited" >();
const visit = ( key : string , stack : string []) => {
const state = visitState . get ( key );
if ( state === "visited" ) {
return ;
}
if ( state === "visiting" ) {
const cycleStart = stack . indexOf ( key );
const cycle = [... stack . slice ( Math . max ( 0 , cycleStart )), key ];
issue (
issues ,
"cyclic-conformance-requirement" ,
indexes . conformancePaths . get ( key ) ?? "conformances" ,
`Cyclic conformance requirement: ${ cycle . join ( " -> " ) } ` ,
);
return ;
}
visitState . set ( key , "visiting" );
for ( const dependency of requirementGraph . get ( key ) ?? []) {
visit ( dependency , [... stack , key ]);
}
visitState . set ( key , "visited" );
};
for ( const key of requirementGraph . keys ()) {
visit ( key , []);
}
};
const validateConstructors = (
workspace : WorkspaceRevision ,
issues : CapabilityValidationIssue [],
indexes : ValidationIndexes ,
) => {
const noGraph = new Map < string , Set < string >>();
for ( const [ index , constructor ] of workspace . constructors . entries ()) {
const path = `constructors[ ${ index } ]` ;
if ( ! indexes . atoms . has ( constructor . atomId )) {
issue ( issues , "invalid-constructor" , ` ${ path } .atomId` , `Unknown atom ${ constructor . atomId } ` );
}
const packageEntry = indexes . packages . get ( constructor . packageRevisionId );
const packageExport = packageEntry ? . exports . get ( constructor . exportId );
if ( ! packageEntry ) {
issue (
issues ,
"invalid-constructor" ,
` ${ path } .packageRevisionId` ,
`Unknown package revision ${ constructor . packageRevisionId } ` ,
);
continue ;
}
if ( ! packageExport ) {
issue (
issues ,
"invalid-constructor" ,
` ${ path } .exportId` ,
`Unknown export ${ constructor . exportId } ` ,
);
continue ;
}
if ( packageExport . kind !== "constructor" ) {
issue (
issues ,
"invalid-constructor" ,
` ${ path } .exportId` ,
`Export ${ constructor . exportId } is ${ packageExport . kind } , not a constructor` ,
);
continue ;
}
if ( packageExport . constructsAtom !== constructor . atomId ) {
issue (
issues ,
"invalid-constructor" ,
` ${ path } .exportId` ,
`Export constructs ${ packageExport . constructsAtom } , not ${ constructor . atomId } ` ,
);
}
validateBoundDependencies ( issues , {
dependencies : constructor.dependencies ,
dependencyPorts : packageExport.dependencyPorts ,
atomId : constructor.atomId ,
path ,
indexes ,
requirementGraph : noGraph ,
});
}
};
export const validateWorkspaceRevision = (
workspace : WorkspaceRevision ,
) : CapabilityValidationIssue [] => {
const issues : CapabilityValidationIssue [] = [];
requireText ( issues , workspace . id , "id" , "Workspace revision ID" );
requireText ( issues , workspace . workspaceId , "workspaceId" , "Workspace ID" );
requireText ( issues , workspace . sourceRootCommit , "sourceRootCommit" , "Source root commit" );
const indexes = collectIdentityIndexes ( workspace , issues );
validateInterfaces ( workspace , issues , indexes );
validateAttachments ( issues , indexes );
validatePackages ( workspace , issues , indexes );
validateConformances ( workspace , issues , indexes );
validateConstructors ( workspace , issues , indexes );
return issues ;
};
export interface CompiledConformance {
source : Conformance ;
operationBindings : ReadonlyMap < OperationId , Binding >;
}
export interface CompiledWorkspaceRevision {
source : WorkspaceRevision ;
atoms : ReadonlyMap < AtomId , WorkspaceRevision [ "atoms" ][ number ] >;
interfaces : ReadonlyMap < InterfaceRevisionId , InterfaceRevision >;
packages : ReadonlyMap < PackageRevisionId , PackageRevision >;
attachments : ReadonlyMap < string , OwnedAttachment >;
conformances : ReadonlyMap < string , CompiledConformance >;
constructors : ReadonlyMap < AtomId , AtomConstructorBinding >;
}
export type CompileWorkspaceRevisionResult =
| { ok : true ; plan : CompiledWorkspaceRevision }
| { ok : false ; issues : CapabilityValidationIssue [] };
export const compileWorkspaceRevision = (
workspace : WorkspaceRevision ,
) : CompileWorkspaceRevisionResult => {
const snapshot = structuredClone ( workspace ) as WorkspaceRevision ;
const issues = validateWorkspaceRevision ( snapshot );
if ( issues . length > 0 ) {
return { ok : false , issues };
}
const attachments = new Map < string , OwnedAttachment >();
for ( const attachment of snapshot . sharedAttachments ) {
attachments . set ( attachmentKey ( attachment ), {
attachment ,
owner : { kind : "workspace" },
});
}
const conformances = new Map < string , CompiledConformance >();
for ( const conformance of snapshot . conformances ) {
for ( const attachment of conformance . privateAttachments ) {
attachments . set ( attachmentKey ( attachment ), {
attachment ,
owner : {
kind : "conformance" ,
atomId : conformance.atomId ,
interfaceRevisionId : conformance.interfaceRevisionId ,
},
});
}
conformances . set (
conformanceKey ( conformance . atomId , conformance . interfaceRevisionId ),
{
source : conformance ,
operationBindings : new Map (
conformance . operationBindings . map (( entry ) => [ entry . operationId , entry . binding ]),
),
},
);
}
return {
ok : true ,
plan : {
source : snapshot ,
atoms : new Map ( snapshot . atoms . map (( atom ) => [ atom . id , atom ])),
interfaces : new Map (
snapshot . interfaceImports . map (( revision ) => [ revision . revisionId , revision ]),
),
packages : new Map (
snapshot . packageImports . map (( revision ) => [ revision . revisionId , revision ]),
),
attachments ,
conformances ,
constructors : new Map ( snapshot . constructors . map (( entry ) => [ entry . atomId , entry ])),
},
};
};
export const resolveConformance = (
plan : CompiledWorkspaceRevision ,
atomId : AtomId ,
interfaceRevisionId : InterfaceRevisionId ,
) : CompiledConformance | undefined =>
plan . conformances . get ( conformanceKey ( atomId , interfaceRevisionId ));
export const resolveOperationBinding = (
plan : CompiledWorkspaceRevision ,
atomId : AtomId ,
interfaceRevisionId : InterfaceRevisionId ,
operationId : OperationId ,
) : Binding | undefined =>
resolveConformance ( plan , atomId , interfaceRevisionId ) ? . operationBindings . get (
operationId ,
);
export type ResolvedOperationPlan =
| {
kind : "state" ;
binding : Extract < Binding , { kind : "state" }>;
attachment : OwnedAttachment & { attachment : StateSlotDefinition };
}
| {
kind : "edge" ;
binding : Extract < Binding , { kind : "edge" }>;
attachment : OwnedAttachment & { attachment : EdgeDefinition };
}
| {
kind : "package" ;
binding : Extract < Binding , { kind : "package" }>;
packageRevision : PackageRevision ;
packageExport : PackageOperationExport ;
dependencies : Array < {
port : DependencyPort ;
binding : DependencyBinding ;
} > ;
};
export const resolveOperationPlan = (
plan : CompiledWorkspaceRevision ,
atomId : AtomId ,
interfaceRevisionId : InterfaceRevisionId ,
operationId : OperationId ,
) : ResolvedOperationPlan | undefined => {
const binding = resolveOperationBinding ( plan , atomId , interfaceRevisionId , operationId );
if ( ! binding ) {
return undefined ;
}
if ( binding . kind === "state" ) {
const owned = plan . attachments . get ( `state \ u0000 ${ binding . slotId } ` );
if ( ! owned || owned . attachment . kind !== "state" ) {
return undefined ;
}
return {
kind : "state" ,
binding ,
attachment : owned as OwnedAttachment & {
attachment : StateSlotDefinition ;
},
};
}
if ( binding . kind === "edge" ) {
const owned = plan . attachments . get ( `edge \ u0000 ${ binding . edgeTypeId } ` );
if ( ! owned || owned . attachment . kind !== "edge" ) {
return undefined ;
}
return {
kind : "edge" ,
binding ,
attachment : owned as OwnedAttachment & { attachment : EdgeDefinition },
};
}
const packageRevision = plan . packages . get ( binding . packageRevisionId );
const packageExport = packageRevision ? . exports . find (
( entry ) : entry is PackageOperationExport =>
entry . id === binding . exportId && entry . kind === "operation" ,
);
if ( ! packageRevision || ! packageExport ) {
return undefined ;
}
const bound = new Map ( binding . dependencies . map (( entry ) => [ entry . portId , entry . binding ]));
return {
kind : "package" ,
binding ,
packageRevision ,
packageExport ,
dependencies : packageExport.dependencyPorts.map (( port ) => ({
port ,
binding : bound.get ( port . id ) ! ,
})),
};
};
export interface CapabilityClosure {
conformances : Array < {
atomId : AtomId ;
interfaceRevisionId : InterfaceRevisionId ;
} > ;
packageRevisionIds : PackageRevisionId [];
attachmentIds : Array < SlotId | EdgeTypeId >;
constructorAtomIds : AtomId [];
}
export const computeCapabilityClosure = (
plan : CompiledWorkspaceRevision ,
roots : Array < { atomId : AtomId ; interfaceRevisionId : InterfaceRevisionId } > ,
) : CapabilityClosure => {
const conformances = new Map < string , {
atomId : AtomId ;
interfaceRevisionId : InterfaceRevisionId ;
}>();
const packages = new Set < PackageRevisionId >();
const attachments = new Set < SlotId | EdgeTypeId >();
const constructors = new Set < AtomId >();
const queued = [... roots ];
const visited = new Set < string >();
2026-09-05 12:33:52 -07:00
const sourceConformances = new Map (
[... plan . conformances ]. map (([ key , value ]) => [ key , value . source ]),
);
2026-09-03 15:46:52 -07:00
const includeDependencies = (
atomId : AtomId ,
dependencies : readonly BoundDependency [],
) => {
for ( const dependency of dependencies ) {
switch ( dependency . binding . kind ) {
case "state" :
attachments . add ( dependency . binding . slotId );
2026-09-04 21:03:09 -07:00
if ( dependency . binding . via ) {
attachments . add ( dependency . binding . via . edgeTypeId );
}
2026-09-03 15:46:52 -07:00
break ;
case "edge" :
attachments . add ( dependency . binding . edgeTypeId );
2026-09-04 21:03:09 -07:00
if ( dependency . binding . via ) {
attachments . add ( dependency . binding . via . edgeTypeId );
}
2026-09-03 15:46:52 -07:00
break ;
2026-09-05 12:33:52 -07:00
case "interface" : {
if ( dependency . binding . via ) {
attachments . add ( dependency . binding . via . edgeTypeId );
}
const targetAtoms = dependency . binding . via
? (() => {
const attachment = plan . attachments . get (
`edge \ u0000 ${ dependency . binding . via ! . edgeTypeId } ` ,
) ? . attachment ;
if ( ! attachment || attachment . kind !== "edge" ) return [];
const projection = edgeProjection (
attachment ,
dependency . binding . via ! . projectionId ,
);
return projection
? [... plan . atoms . keys ()]. filter (( candidate ) =>
atomSatisfiesConstraint (
candidate ,
projection . target . constraint ,
sourceConformances ,
))
: [];
})()
: [ atomId ];
for ( const targetAtom of targetAtoms ) {
queued . push ({
atomId : targetAtom ,
interfaceRevisionId : dependency.binding.interfaceRevisionId ,
});
}
2026-09-03 15:46:52 -07:00
break ;
2026-09-05 12:33:52 -07:00
}
2026-09-03 15:46:52 -07:00
case "constructor" : {
constructors . add ( dependency . binding . atomId );
const constructor = plan . constructors . get ( dependency . binding . atomId );
if ( constructor ) {
packages . add ( constructor . packageRevisionId );
includeDependencies ( dependency . binding . atomId , constructor . dependencies );
}
}
}
}
};
while ( queued . length > 0 ) {
const root = queued . shift () ! ;
const key = conformanceKey ( root . atomId , root . interfaceRevisionId );
if ( visited . has ( key )) {
continue ;
}
visited . add ( key );
const conformance = plan . conformances . get ( key );
if ( ! conformance ) {
continue ;
}
conformances . set ( key , {
atomId : conformance.source.atomId ,
interfaceRevisionId : conformance.source.interfaceRevisionId ,
});
for ( const binding of conformance . operationBindings . values ()) {
if ( binding . kind === "state" ) {
attachments . add ( binding . slotId );
} else if ( binding . kind === "edge" ) {
attachments . add ( binding . edgeTypeId );
} else {
packages . add ( binding . packageRevisionId );
includeDependencies ( root . atomId , binding . dependencies );
const packageRevision = plan . packages . get ( binding . packageRevisionId );
const operation = packageRevision ? . exports . find (
( entry ) : entry is PackageOperationExport =>
entry . id === binding . exportId && entry . kind === "operation" ,
);
if ( operation ? . receiverRequirement . kind === "all-interfaces" ) {
for ( const interfaceRevisionId of operation . receiverRequirement
. interfaceRevisionIds ) {
queued . push ({ atomId : root.atomId , interfaceRevisionId });
}
}
}
}
2026-09-04 21:03:09 -07:00
for ( const materialization of
conformance . source . relationshipMaterializations ?? []) {
attachments . add ( materialization . edgeTypeId );
constructors . add ( materialization . constructorAtomId );
const constructor = plan . constructors . get ( materialization . constructorAtomId );
if ( constructor ) {
packages . add ( constructor . packageRevisionId );
includeDependencies ( materialization . constructorAtomId , constructor . dependencies );
}
}
2026-09-03 15:46:52 -07:00
}
return {
conformances : [... conformances . entries ()]
. sort (([ left ], [ right ]) => left . localeCompare ( right ))
. map (([, conformance ]) => conformance ),
packageRevisionIds : [... packages ]. sort (),
attachmentIds : [... attachments ]. sort (),
constructorAtomIds : [... constructors ]. sort (),
};
};