Make workspace authoring converge through immutable Nix candidates
Coordinate registered resource edits bottom-up into retained exact remote sources. Use one Nix-owned source graph for provisional checking, template publication, explicit baseline upgrades and host activation; retain independent runtime pins. Add scoped contract inspection, historical recovery, derived worklists, crash-safe locks, named dependency adoption and plain-QX structural editing. Repair TODO ownership and template instantiation, and document the supported agent workflow. Validated with protocol and command suites, real jj/Nix convergence and cache checks, TS/React installed-command acceptance, and fresh TODO first-edit acceptance. No live deployment or public publication performed. Props projection generation and a one-command rich feature generator remain explicitly outside this delivery.
This commit is contained in:
@@ -1,6 +1,17 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { editStructure, scaffoldResourceSource } from "../src/capability-language/structural-edits.js";
|
||||
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/);
|
||||
});
|
||||
|
||||
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")}`;
|
||||
@@ -13,6 +24,9 @@ test("package scaffolding and function edits preserve surrounding source and use
|
||||
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/);
|
||||
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";'));
|
||||
});
|
||||
|
||||
test("dependency scaffolding validates exact sources and preserves unrelated lock comments", () => {
|
||||
|
||||
Reference in New Issue
Block a user