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,6 @@
|
||||
import childProcess from "node:child_process";
|
||||
import crypto from "node:crypto";
|
||||
import { mkdir, readFile, realpath } from "node:fs/promises";
|
||||
import { mkdir, mkdtemp, readFile, realpath, rename, rm, stat } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
import type { CapabilityRepositoryResolver } from "./assembly.js";
|
||||
@@ -61,7 +61,27 @@ export const createGitCapabilityResolver = async (options: {
|
||||
checkoutRoot,
|
||||
checkoutName(kind, source.repository, source.commit),
|
||||
);
|
||||
await execFile("git", [
|
||||
const verify = async (checkout: string) => {
|
||||
const { stdout } = await execFile("git", ["-C", checkout, "rev-parse", "HEAD"]);
|
||||
if (stdout.trim().toLowerCase() !== source.commit.toLowerCase()) {
|
||||
throw new Error(`Locked commit mismatch for ${source.repository}: wanted ${source.commit}, fetched ${stdout.trim()}`);
|
||||
}
|
||||
const { stdout: changes } = await execFile("git", ["-C", checkout, "status", "--porcelain", "--untracked-files=all"]);
|
||||
if (changes.trim()) throw new Error(`Dependency checkout was modified: ${checkout}`);
|
||||
};
|
||||
// Only complete, checked clones become visible under the deterministic name.
|
||||
// Concurrent resolvers may fetch independently, but cannot observe a partial clone.
|
||||
if (await stat(directory).then(() => true, (error: NodeJS.ErrnoException) => {
|
||||
if (error.code === "ENOENT") return false;
|
||||
throw error;
|
||||
})) {
|
||||
await verify(directory);
|
||||
return { directory };
|
||||
}
|
||||
const staging = await mkdtemp(path.join(checkoutRoot, ".fetch-"));
|
||||
const checkout = path.join(staging, "checkout");
|
||||
try {
|
||||
await execFile("git", [
|
||||
"-c",
|
||||
"advice.detachedHead=false",
|
||||
"clone",
|
||||
@@ -71,18 +91,21 @@ export const createGitCapabilityResolver = async (options: {
|
||||
"--branch",
|
||||
`quixos-reachability/${source.commit.toLowerCase()}`,
|
||||
source.repository,
|
||||
directory,
|
||||
checkout,
|
||||
]);
|
||||
const { stdout } = await execFile("git", ["-C", directory, "rev-parse", "HEAD"]);
|
||||
if (stdout.trim().toLowerCase() !== source.commit.toLowerCase()) {
|
||||
throw new Error(
|
||||
`Locked commit mismatch for ${source.repository}: ` +
|
||||
`wanted ${source.commit}, fetched ${stdout.trim()}`,
|
||||
);
|
||||
await verify(checkout);
|
||||
try { await rename(checkout, directory); }
|
||||
catch (error) {
|
||||
if (!["EEXIST", "ENOTEMPTY"].includes((error as NodeJS.ErrnoException).code ?? "")) throw error;
|
||||
await verify(directory);
|
||||
}
|
||||
} finally {
|
||||
await rm(staging, { recursive: true, force: true });
|
||||
}
|
||||
return { directory };
|
||||
})();
|
||||
checkouts.set(key, pending);
|
||||
return await pending;
|
||||
try { return await pending; }
|
||||
catch (error) { checkouts.delete(key); throw error; }
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user