2026-09-23 00:01:03 -07:00
import assert from "node:assert/strict" ;
import test from "node:test" ;
import {
compileCapabilityResourceSource ,
compileCapabilitySource ,
type CapabilityImportEnvironment ,
} from "../src/capability-language/parser.js" ;
import type { InterfaceRevision , PackageRevision } from "../src/capability-model/types.js" ;
function fixture ( declarations : string []) {
const interfaces = new Map < string , InterfaceRevision >();
const packages = new Map < string , PackageRevision >();
const environment : CapabilityImportEnvironment = { interfaces , packages };
for ( const sourceText of declarations ) {
const result = compileCapabilityResourceSource ( sourceText , {
source : { repository : "https://example.test/rules.git" , commit : "a" . repeat ( 40 ) },
environment ,
});
assert . ok ( result . ok , JSON . stringify ( result . diagnostics ));
if ( result . resource . kind === "interface" )
interfaces . set ( result . resource . revision . displayName , result . resource . revision );
else packages . set ( result . resource . revision . displayName , result . resource . revision );
}
return ( body : string ) =>
compileCapabilitySource (
`workspace W id "w" revision "w@1" commit " ${ "a" . repeat ( 40 ) } " {
${ [... interfaces . keys ()]. map (( name ) => `import interface ${ name } ;` ). join ( "\n" ) }
${ [... packages . keys ()]. map (( name ) => `import package ${ name } ;` ). join ( "\n" ) }
${ body }
}` ,
"rules.qx" ,
environment ,
);
}
const ok = ( result : ReturnType < ReturnType < typeof fixture >>) => {
assert . ok ( result . ok , JSON . stringify ( result . diagnostics ));
return result ;
};
const nameResources = [
'interface Person id "person" revision "person@1" {value name id "p:name" : string {get id "p:get";set id "p:set";}}' ,
'interface HasName id "name" revision "name@1" {value name id "n:name" : string {get id "n:get";set id "n:set";}}' ,
];
const person = ( name : string ) => `atom ${ name } id " ${ name } "; conform ${ name } as Person id " ${ name } :person" {
private state Name ${ name } id " ${ name } :name" on ${ name } : string policy register default "hello";
bind name.get to state Name ${ name } .read; bind name.set to state Name ${ name } .write;
}` ;
const namedRule =
'conform Person as HasName id "person-name" {bind name.get to interface Person.name.get;bind name.set to interface Person.name.set;}' ;
test ( "interface rules are order independent and preserve each original storage owner" , () => {
const compile = fixture ( nameResources );
const first = ok ( compile ( namedRule + person ( "Living" ) + person ( "Avatar" )));
const second = ok ( compile ( person ( "Avatar" ) + person ( "Living" ) + namedRule ));
const generated = ( result : typeof first ) =>
result . workspace . conformances
. filter (( c ) => c . ruleOrigin )
. map (( c ) => [ c . atomId , c . id ])
. sort ();
assert . deepEqual ( generated ( first ), generated ( second ));
for ( const atom of [ "Living" , "Avatar" ]) {
const c = first . workspace . conformances . find (( c ) => c . atomId === atom && c . interfaceRevisionId === "name@1" ) ! ;
assert ( c );
assert . equal ( c . privateAttachments . length , 0 );
assert (
c . operationBindings . every (( b ) => b . binding . kind === "interface" && b . binding . interfaceRevisionId === "person@1" ),
);
}
});
test ( "rule conflicts identify competing implementations" , () => {
const result = fixture ( nameResources )(
person ( "Living" ) + namedRule + namedRule . replace ( 'id "person-name"' , 'id "other-rule"' ),
);
assert . equal ( result . ok , false );
assert . match ( JSON . stringify ( result . diagnostics ), /duplicate-conformance/ );
});
2026-09-25 10:53:19 -07:00
test ( "rules validate unused bodies and ambiguous names" , () => {
2026-09-23 00:01:03 -07:00
const compile = fixture ( nameResources );
for ( const [ body , code ] of [
[ "conform Person as HasName { }" , "missing-rule-id" ],
[ 'conform Person as HasName id "r" {bind name.get to interface Person.missing.get;}' , "unknown-operation" ],
2026-09-25 10:53:19 -07:00
[ 'conform Person as HasName id "r" { initialize { content to state Missing; }; }' , "invalid-initialization" ],
[ 'conform Person as HasName id "r" { bind name to state Missing; }' , "invalid-state-field-binding" ],
[
'conform Person as HasName id "r" {private state Bad id "bad" on Self : Missing policy register;}' ,
"unknown-type" ,
],
2026-09-23 00:01:03 -07:00
[ 'atom Person id "p";' + namedRule , "ambiguous-conformance-source" ],
[ namedRule + namedRule , "duplicate-rule-id" ],
]) {
const result = compile ( body );
assert . equal ( result . ok , false , body );
assert . match ( JSON . stringify ( result . diagnostics ), new RegExp ( code ));
}
});
2026-09-25 10:53:19 -07:00
test ( "rule storage is scoped per application, including repeated specializations on one atom" , async () => {
const compile = fixture ([
'interface Source<value T : storable> id "source" revision "source@1" {}' ,
'interface Stored<value T : storable> id "stored" revision "stored@1" {value content id "value" : optional<T> {get id "get";set id "set";}}' ,
]);
const rule = `conform<value T : storable> Source<T> as Stored<T> id "store-rule" {
private state Value id "stored:value" on Self : optional<T> policy register default null;
bind content to state Value;
}` ;
const atoms = `atom A id "a"; atom B id "b";
conform A as Source<string> id "a-string" {}
conform A as Source<int64> id "a-number" {}
conform B as Source<string> id "b-string" {}` ;
const first = ok ( compile ( rule + atoms )). workspace ;
const second = ok ( compile ( atoms + rule )). workspace ;
const storage = ( workspace : typeof first ) =>
workspace . conformances
. filter (( c ) => c . ruleOrigin )
. map (( c ) => [ c . id , c . privateAttachments , c . operationBindings ])
. sort (( a , b ) => String ( a [ 0 ]). localeCompare ( String ( b [ 0 ])));
assert . deepEqual ( storage ( first ), storage ( second ));
const owners = first . conformances . filter (( c ) => c . ruleOrigin );
assert . equal ( owners . length , 3 );
assert . equal ( new Set ( owners . map (( c ) => c . privateAttachments [ 0 ] ! . id )). size , 3 );
for ( const owner of owners ) {
const state = owner . privateAttachments [ 0 ] ! ;
assert . equal ( state . kind , "state" );
if ( state . kind !== "state" ) throw Error ( "state expected" );
assert . equal ( state . attachedTo , owner . atomId );
assert ( owner . operationBindings . every (( b ) => b . binding . kind === "state" && b . binding . slotId === state . id ));
}
const { storageContracts , storageChangeRequiresMigration } = await import ( "../src/capability-model/evolution.js" );
const before = storageContracts ( first );
const changed = ok (
compile (
atoms . replace ( 'conform A as Source<int64> id "a-number" {}' , "" ) +
rule . replace ( "default null" , 'default "new default"' ),
),
). workspace ;
// Use the string specialization for default evolution; all nominal identities
// remain stable, and changing a default must not rewrite existing state.
const oldSlot = before . find (( s ) => s . id === owners . find (( c ) => c . atomId === "b" ) ! . privateAttachments [ 0 ] ! . id ) ! ;
const newSlot = storageContracts ( changed ). find (( s ) => s . id === oldSlot . id ) ! ;
assert . equal ( storageChangeRequiresMigration ( oldSlot , newSlot , new Set ([ "a" , "b" ])), false );
assert . equal ( storageChangeRequiresMigration ( oldSlot , undefined , new Set ([ "a" , "b" ])), true );
});
test ( "rule attachments shadow outside names without leaking into another owner" , () => {
const rule = `conform Person as HasName id "r" {
private state NameLiving id "rule:name" on Self : string policy register default "rule";
bind name to state NameLiving;
}` ;
const workspace = ok ( fixture ( nameResources )( rule + person ( "Living" ))). workspace ;
const original = workspace . conformances . find (( c ) => c . interfaceRevisionId === "person@1" ) ! ;
const derived = workspace . conformances . find (( c ) => c . interfaceRevisionId === "name@1" ) ! ;
assert . notEqual ( original . privateAttachments [ 0 ] ! . id , derived . privateAttachments [ 0 ] ! . id );
assert (
derived . operationBindings . every (
( b ) => b . binding . kind === "state" && b . binding . slotId === derived . privateAttachments [ 0 ] ! . id ,
),
);
assert (
original . operationBindings . every (
( b ) => b . binding . kind === "state" && b . binding . slotId === original . privateAttachments [ 0 ] ! . id ,
),
);
});
test ( "rule private edges substitute Self and captured endpoints with stable projection IDs" , () => {
const compile = fixture ([
'interface Linkable<object T> id "linkable" revision "linkable@1" {}' ,
'interface Links<object T> id "links" revision "links@1" {relation items id "items" : many object T {resolve id "resolve";}}' ,
]);
const source = `atom A id "a"; atom B id "b"; atom Target id "target";
conform A as Linkable<atom Target> id "a-link" {} conform B as Linkable<atom Target> id "b-link" {}
conform<object T> Linkable<T> as Links<T> id "links" {
private edge Items id "items" {
object Self projection items id "forward" many;
object T projection owners id "inverse" many;
}
bind items.resolve to edge Items.items.resolve;
}` ;
const workspace = ok ( compile ( source )). workspace ;
const edges = workspace . conformances . filter (( c ) => c . ruleOrigin ). map (( c ) => c . privateAttachments [ 0 ] ! );
assert . equal ( edges . length , 2 );
assert . notEqual ( edges [ 0 ] ! . id , edges [ 1 ] ! . id );
const projections = edges . flatMap (( edge ) => {
assert . equal ( edge . kind , "edge" );
if ( edge . kind !== "edge" ) throw Error ( "edge expected" );
assert . deepEqual ( edge . endpoints [ 1 ]. constraint , { kind : "atom" , atomId : "target" });
return edge . endpoints . map (( e ) => e . projectionId );
});
assert . equal ( new Set ( projections ). size , 4 );
});
test ( "rule creation ports close captured atom parameters and retain initialization checking" , () => {
const compile = fixture ([
'interface Factory<object T> id "factory" revision "factory@1" {operation create id "create" : unit -> ref<T> {call id "call" execution transaction targets [browser,server];}}' ,
'interface Creates<object T> id "creates" revision "creates@1" {}' ,
'package Runtime id "runtime" revision "runtime@1" {operation create<object T> id "create" : unit -> ref<T> mode call execution transaction targets [browser,server] receiver any requires {creation result id "result" : T input unit;};}' ,
]);
const rule = `conform<object T> Creates<T> as Factory<T> id "factory-rule" {
bind create.call to package Runtime.create<T> with {result to creation T with {};};
}` ;
const result = ok (
compile ( `atom Subject id "subject"; atom Product id "product";
conform Subject as Creates<atom Product> id "creates-product" {} ${ rule } ` ),
);
const owner = result . workspace . conformances . find (( c ) => c . ruleOrigin ) ! ;
const binding = owner . operationBindings [ 0 ] ! . binding ;
assert . equal ( binding . kind , "package" );
if ( binding . kind !== "package" ) throw Error ( "package expected" );
assert . deepEqual ( binding . dependencies [ 0 ] ! . binding , { kind : "creation" , atomId : "product" , owners : [] });
const invalid = compile ( `atom Subject id "subject";
conform Subject as Creates<interface Creates<atom Subject>> id "creates-interface" {} ${ rule } ` );
assert . equal ( invalid . ok , false );
assert . match ( JSON . stringify ( invalid . diagnostics ), /concrete atom/ );
});
2026-09-23 00:01:03 -07:00
const genericResources = [
'interface Placeable id "placeable" revision "placeable@1" {}' ,
'interface Eligible id "eligible" revision "eligible@1" {}' ,
'interface Factory<value Input, object Result> id "factory" revision "factory@1" {}' ,
'import interface Placeable; interface CanvasFactory<value Input, object Result implements Placeable> id "canvas-factory" revision "canvas-factory@1" {}' ,
];
const factoryRule =
'conform<value I, object R implements Placeable> Factory<I,R> as CanvasFactory<I,R> id "factory-canvas" {}' ;
test ( "generic bounds filter factories and can be supplied by later rules" , () => {
const result = ok (
fixture ( genericResources )( `
${ factoryRule }
atom Owner id "owner"; atom Product id "product"; atom Other id "other";
conform Owner as Factory<unit,atom Product> id "unit-factory" {}
conform Owner as Factory<record { title:string; },atom Product> id "record-factory" {}
conform Owner as Factory<string,atom Other> id "ineligible" {}
conform Product as Eligible id "eligible-product" {}
conform Eligible as Placeable id "eligible-placeable" {}
` ),
);
const generated = result . workspace . conformances . filter (( c ) => c . ruleOrigin ? . ruleId === "factory-canvas" );
assert . equal ( generated . length , 2 );
assert ( generated . every (( c ) => c . atomId === "owner" ));
for ( const c of generated ) {
const iface = result . workspace . interfaceImports . find (( i ) => i . revisionId === c . interfaceRevisionId ) ! ;
assert . deepEqual ( iface . application ? . arguments [ 1 ], { kind : "object" , target : { kind : "atom" , atomId : "product" } });
}
});
test ( "rules reject recursive graphs, nested capture, wrong kinds and unbound parameters" , () => {
const compile = fixture ([
'interface A<value T> id "a" revision "a@1" {}' ,
'interface B<value T> id "b" revision "b@1" {}' ,
]);
for ( const [ body , code ] of [
[ 'conform<value T> A<T> as A<list<T>> id "grow" {}' , "recursive-conformance-rule" ],
[ 'conform<value T> A<T> as B<T> id "ab" {} conform<value T> B<T> as A<T> id "ba" {}' , "recursive-conformance-rule" ],
[ 'conform<value T> A<list<T>> as B<T> id "nested" {}' , "unsupported-rule-pattern" ],
[ 'conform<value T> A<string> as B<T> id "uncaptured" {}' , "uncaptured-rule-parameter" ],
[ 'conform<object T> A<T> as B<string> id "kind" {}' , "parameter-kind" ],
]) {
const result = compile ( body );
assert . equal ( result . ok , false , body );
assert . match ( JSON . stringify ( result . diagnostics ), new RegExp ( code ));
}
});
test ( "package-backed rules retain declared interface dependencies" , () => {
const result = ok (
fixture ([
... nameResources ,
'import interface Person; package Names id "names" revision "names@1" {operation displayName id "read" : unit -> string mode call receiver any requires {interface person id "person-port" : Person using [name.get];};}' ,
])(
person ( "Living" ) +
`conform Person as HasName id "formatted" {
bind name.get to package Names.displayName with {person to interface Person;};
bind name.set to interface Person.name.set;
}` ,
),
);
const generated = result . workspace . conformances . find (( c ) => c . ruleOrigin ) ! ;
const binding = generated . operationBindings [ 0 ]. binding ;
assert . equal ( binding . kind , "package" );
if ( binding . kind === "package" )
assert . deepEqual ( binding . dependencies [ 0 ]. binding , { kind : "interface" , interfaceRevisionId : "person@1" });
});
test ( "repeated arguments, closed patterns, Self and seedless bounds remain exact" , () => {
const compile = fixture ([
'interface Pair<value A, value B> id "pair" revision "pair@1" {}' ,
'interface Same<value T, object Owner> id "same" revision "same@1" {}' ,
... genericResources ,
]);
const result = ok (
compile ( `
atom A id "atom-a";
conform A as Pair<string,string> id "equal" {}
conform A as Pair<string,int32> id "unequal" {}
conform<value T> Pair<T,T> as Same<T,Self> id "same-rule" {}
conform A as Factory<unit,atom A> id "factory" {}
${ factoryRule }
conform<object R implements Eligible> Factory<unit,R> as Placeable id "seedless" {}
conform<object R implements Placeable> Factory<unit,R> as Eligible id "seedless-other" {}
` ),
);
const generated = result . workspace . conformances . filter (( c ) => c . ruleOrigin );
assert . equal ( generated . length , 1 );
const target = result . workspace . interfaceImports . find (( i ) => i . revisionId === generated [ 0 ]. interfaceRevisionId ) ! ;
assert . deepEqual ( target . application ? . arguments [ 1 ], { kind : "object" , target : { kind : "atom" , atomId : "atom-a" } });
});
test ( "chains do not duplicate an application and explicit targets conflict" , () => {
const compile = fixture ([
'interface A id "a" revision "a@1" {}' ,
'interface B id "b" revision "b@1" {}' ,
'interface C id "c" revision "c@1" {}' ,
]);
const source = `atom Item id "item"; conform Item as A id "a-impl" {}
conform B as C id "bc" {} conform A as B id "ab" {}` ;
assert . equal ( ok ( compile ( source )). workspace . conformances . length , 3 );
const conflict = compile ( source + 'conform Item as C id "explicit-c" {}' );
assert . equal ( conflict . ok , false );
assert . match ( JSON . stringify ( conflict . diagnostics ), /explicit-c/ );
assert . match ( JSON . stringify ( conflict . diagnostics ), /rule bc/ );
});
2026-09-25 11:04:23 -07:00
test ( "rule inverse reads retain the concrete conformance ownership checks" , () => {
const compile = fixture ([
'interface Parent id "parent" revision "parent@1" {}' ,
'interface Child id "child" revision "child@1" {}' ,
'import interface Parent; interface Owned id "owned" revision "owned@1" {queryable relation parent id "parent-ref" : optional-one interface Parent {resolve id "parent-read" execution snapshot targets [browser,server];}}' ,
]);
const source = `
atom P id "p"; atom C id "c";
conform P as Parent id "parent-impl" {
private edge Membership id "membership" {
atom P projection children id "children" many-unique;
interface Child projection parent id "parent" optional-one public-traversal;
}
}
conform C as Child id "child-impl" {}
conform Child as Owned id "owned-rule" {bind parent.resolve to edge Membership.parent.resolve;}
` ;
ok ( compile ( source ));
const hidden = compile ( source . replace ( " public-traversal" , "" ));
assert . equal ( hidden . ok , false );
assert . match ( JSON . stringify ( hidden . diagnostics ), /private|public|own/i );
const missing = compile ( source . replace ( "Membership.parent.resolve" , "Missing.parent.resolve" ));
assert . equal ( missing . ok , false );
assert . match ( JSON . stringify ( missing . diagnostics ), /Unknown attachment/ );
});