2026-09-10 18:27:41 -07:00
import test from "node:test" ;
import assert from "node:assert/strict" ;
2026-09-14 10:26:11 -07:00
import { editStructure , scaffoldResourceSource , instantiateWorkspaceIdentity } from "../src/capability-language/structural-edits.js" ;
test ( "template identity binding changes only the workspace header and is idempotent" , () => {
const source = '// workspace fake id "do-not-touch"\nworkspace Todo id "workspace:todo" revision "workspace:todo@1" commit "' + "a" . repeat ( 40 ) + '" { atom Task id "atom:task"; }' ;
const id = "00000000-0000-0000-0000-000000000123" ;
const bound = instantiateWorkspaceIdentity ( source , id );
assert . match ( bound , /atom Task id "atom:task"/ );
assert . ok ( bound . startsWith ( '// workspace fake id "do-not-touch"' ));
assert . ok ( bound . includes ( `workspace Todo id " ${ id } "` ));
assert . equal ( instantiateWorkspaceIdentity ( bound , id ), bound );
assert . throws (() => instantiateWorkspaceIdentity ( source , "not-a-workspace" ), /UUID/ );
});
2026-09-10 18:27:41 -07:00
test ( "package scaffolding and function edits preserve surrounding source and use exact selectors" , () => {
const source = `// 🧭 resource comment \ n ${ scaffoldResourceSource ( "package" , "Chess" , "package:chess" , "package:chess@1" ) } ` ;
const functionSource = 'function evaluate id "export:evaluate" : string -> string;' ;
const appended = editStructure ( source , { operation : "append" , parent : { kind : "packageResourceDecl" , id : "package:chess" }, source : functionSource });
assert . ok ( appended . startsWith ( "// 🧭 resource comment\n" ));
assert . ok ( appended . includes ( functionSource ));
const replaced = editStructure ( appended , { operation : "replace" , target : { kind : "packageFunctionExport" , id : "export:evaluate" }, source : 'function evaluate id "export:evaluate" : unit -> string;' });
assert . ok ( replaced . includes ( ": unit -> string;" ));
assert . ok ( ! editStructure ( replaced , { operation : "remove" , target : { kind : "packageFunctionExport" , id : "export:evaluate" }}). includes ( "evaluate" ));
assert . throws (() => editStructure ( source , { operation : "remove" , target : { kind : "packageResourceDecl" , id : "package:chess@1" }}), /exactly once/ );
assert . throws (() => editStructure ( source , { operation : "append" , parent : { kind : "packageResourceDecl" }, source : "not valid QX" }), /Invalid structural/ );
2026-09-14 10:26:11 -07:00
const prefixed = `import interface Board; \ nexternal atom Game id "atom:game"; \ n ${ source } ` ;
const replacedPackage = editStructure ( prefixed , { operation : "replace" , target : { kind : "packageResourceDecl" , id : "package:chess" }, source : scaffoldResourceSource ( "package" , "Chess" , "package:chess" , "package:chess@2" )});
assert . ok ( replacedPackage . startsWith ( 'import interface Board;\nexternal atom Game id "atom:game";' ));
2026-09-10 18:27:41 -07:00
});
test ( "dependency scaffolding validates exact sources and preserves unrelated lock comments" , () => {
const source = `// 🧭 lock \ nquixos-lock version 1 { \ n quixos source { repository "https://example.test/quixos.git"; commit " ${ "a" . repeat ( 40 ) } "; } \ n // retained comment \ n} \ n` ;
const dependency = { operation : "dependency" as const , kind : "package" as const , name : "Chess" , source : { repository : "https://example.test/chess.git" , commit : "b" . repeat ( 40 )}};
const appended = editStructure ( source , dependency );
assert . ok ( appended . includes ( "// retained comment" ));
assert . ok ( appended . startsWith ( "// 🧭 lock\n" ));
assert . throws (() => editStructure ( source , {... dependency , source : {... dependency . source , commit : "main" }}), /Invalid dependency/ );
const changed = editStructure ( appended , {... dependency , source : {... dependency . source , commit : "c" . repeat ( 40 )}});
assert . ok ( ! changed . includes ( "b" . repeat ( 40 )));
assert . ok ( ! editStructure ( changed , {... dependency , source : null }). includes ( "package Chess" ));
});
test ( "conformance enrollment, major edits, imports, and private attachment removal preserve valid structure" , () => {
const source = `fragment { conform Game as Playable { private state Board id "slot:board" on Game : string policy optimistic-register; } }` ;
const selector = { kind : "conformanceDecl" , names : [ "Game" , "Playable" ]};
const enrolled = editStructure ( source , { operation : "conformance-id" , target : selector , id : "conformance:playable" });
assert . ok ( enrolled . includes ( 'as Playable id "conformance:playable"' ));
const major = editStructure ( enrolled , { operation : "semantic-major" , target : { kind : "conformanceDecl" , id : "conformance:playable" }, major : 2 });
assert . ok ( major . includes ( "semantic-major 2" ));
assert . throws (() => editStructure ( major , { operation : "conformance-id" , target : selector , id : "different" }), /Cannot change/ );
const removed = editStructure ( major , { operation : "remove" , target : { kind : "stateDecl" , id : "slot:board" }});
assert . ok ( ! removed . includes ( "private" ));
const imported = editStructure ( removed , { operation : "import" , kind : "interface" , name : "Playable" });
assert . equal ( editStructure ( imported , { operation : "import" , kind : "interface" , name : "Playable" }), imported );
});