Simplify workspace authoring and isolate managed component styles

Use imperative scaffolds without a registry/refresh lifecycle; preserve authored runtime wiring and generate checked descriptors. Consolidate binding options, embed checked TSX/CSS source, queue mutable convergence while allowing parallel immutable checks, and preload real CLI observations. Add Shadow DOM boundaries with scoped overlays and composed-event handling. Update template/toolchain pins and document VM-free authoring, browser, and stateful acceptance; no deployment or default-template selection.
This commit is contained in:
Timothy J. Aveni
2026-09-14 20:35:53 -07:00
parent 14b0ef25c3
commit 6c2f030243
13 changed files with 278 additions and 95 deletions
+5 -15
View File
@@ -17,7 +17,7 @@ export type StructuralRequest = {
source?: {repository: string; commit: string};
resourceRoot?: string;
validation?: "syntax" | "resource-graph";
files: ({file: string; edits: StructuralEdit[]} | {file: string; create: string} | {file: string; generated: string})[];
files: ({file: string; edits: StructuralEdit[]} | {file: string; create: string} | {file: string; generated: string} | {file: string; expected: string; replace: string})[];
};
type Change = {file: string; before: string | null; after: string; mode: number};
type Journal = {schemaVersion: 1; id: string; root: string; phase: "prepared" | "complete"; changes: Change[]};
@@ -70,6 +70,9 @@ export const planStructure = async (rootPath: string, request: StructuralRequest
if ("create" in input) {
if (before !== null || typeof input.create !== "string") throw new Error("Scaffold creation cannot replace an existing file");
after = input.create;
} else if ("replace" in input) {
if (before !== input.expected || typeof input.replace !== "string") throw new Error(`Stale imperative edit: ${input.file}`);
after = input.replace;
} else if ("generated" in input) {
const generated = (text: string) => text.startsWith("// Generated by qx-scaffold-v1\n") || text.startsWith("# Generated by qx-scaffold-v1\n") || (() => {try {return JSON.parse(text).generatedBy === "qx-scaffold-v1";} catch {return false;}})();
if (typeof input.generated !== "string" || !generated(input.generated) || (before !== null && !generated(before))) throw new Error("Only scaffold-owned generated files may be regenerated");
@@ -79,17 +82,6 @@ export const planStructure = async (rootPath: string, request: StructuralRequest
after = input.edits.reduce(editStructure, before);
}
if (Buffer.byteLength(after) > 1024 * 1024) throw new Error("Scaffold file exceeds 1 MiB");
if (input.file.endsWith("package.qx")) {
let registry;
try { registry = JSON.parse(await fs.readFile(path.join(root, path.dirname(input.file), "quixos.scaffold.json"), "utf8")); }
catch (error) { if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error; }
if (registry?.generatedBy === "qx-scaffold-v1") {
const declaration = parseQx(after).root.children.find(node => node.kind === "packageResourceDecl");
const literal = declaration?.children.find(node => node.kind === "stringLiteral");
if (literal && JSON.parse(after.slice(literal.start, literal.end)) !== registry.id)
throw new Error("Cannot change a scaffold-owned package identity independently of its registry; create a new managed package instead");
}
}
const mode = before === null ? 0o644 : (await fs.stat(path.join(root, input.file))).mode & 0o777;
changes.push({file: input.file, before, after, mode});
await containedParent(snapshot.directory, input.file);
@@ -109,9 +101,7 @@ export const planStructure = async (rootPath: string, request: StructuralRequest
if (request.kind === "workspace") await compileWorkspaceRepository({rootDirectory: resourceRoot, resolveResource});
else if (["package", "interface"].includes(request.kind) && request.source) {
const compiled = await compileCapabilityResourceRepository({rootDirectory: resourceRoot, kind: request.kind as "package" | "interface", source: {resolver: "git", ...request.source}, resolveResource});
let scaffoldOwned = false;
try { scaffoldOwned = JSON.parse(await fs.readFile(path.join(resourceRoot, "quixos.scaffold.json"), "utf8")).generatedBy === "qx-scaffold-v1"; } catch { /* ordinary resource, no generated package scaffolding */ }
if (scaffoldOwned && compiled.resource.kind === "package") {
if (compiled.resource.kind === "package") {
const configuration = JSON.parse(await fs.readFile(path.join(resourceRoot, "quixos.check.json"), "utf8"));
const artifacts = [
{file: configuration.bindingOutput as string, after: generateTypeScriptBindings(bindingSchema(compiled), compiled.resource.revision.revisionId, configuration.options)},