#!/usr/bin/env node import crypto from "node:crypto"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import process from "node:process"; import { execFileSync } from "node:child_process"; import { fileURLToPath } from "node:url"; const DEFAULT_GUARD = "/Volumes/JZAO/HoloLake/persona-runtime/continuity-guard/scripts/continuity-lane.mjs"; const DEFAULT_STORE = "/Volumes/JZAO/HoloLake/persona-runtime/continuity-memory/collaboration"; const CODE_CHANNEL_HOST = "guanghulab.com"; const CODE_CHANNEL_PREFIX = "/code/bingshuo/"; const CODE_CHANNEL_REPOSITORIES = new Set([ "guanghu-ice-heart", "hololake-system-architecture", "grok-build-upstream-mirror", ]); const SAFE_CACHE_RELATIVE = [ /^target$/u, /^coverage$/u, /^\.nyc_output$/u, /^\.pytest_cache$/u, /^\.mypy_cache$/u, /^\.ruff_cache$/u, /^\.cache$/u, /^\.next\/cache$/u, /^node_modules\/\.cache$/u, /(?:^|\/)__pycache__$/u, ]; const DEFAULT_CACHE_CANDIDATES = [ "target", "coverage", ".nyc_output", ".pytest_cache", ".mypy_cache", ".ruff_cache", ".cache", ".next/cache", "node_modules/.cache", ]; export function parseArgs(argv) { const args = { receipts: [], cleanupPaths: [] }; for (let index = 0; index < argv.length; index += 1) { const key = argv[index]; if (key === "--self-test") args.selfTest = true; else if (key === "--receipt") args.receipts.push(argv[++index]); else if (key === "--cleanup-path") args.cleanupPaths.push(argv[++index]); else if (key.startsWith("--")) { const name = key.slice(2).replaceAll(/-([a-z])/gu, (_, letter) => letter.toUpperCase(), ); args[name] = argv[++index]; } else { throw new Error(`UNKNOWN_ARGUMENT:${key}`); } } return args; } export function normalizeCodeChannelRepository(value) { let url; try { url = new URL(String(value || "").trim().replace(/^repo:\/\//u, "https://")); } catch { throw new Error("INVALID_CODE_CHANNEL_REPOSITORY"); } if (url.username || url.password) { throw new Error("CODE_CHANNEL_CREDENTIALS_FORBIDDEN"); } const pathname = url.pathname.replace(/\.git$/u, "").replace(/\/+$/u, ""); const slug = pathname.startsWith(CODE_CHANNEL_PREFIX) ? pathname.slice(CODE_CHANNEL_PREFIX.length) : ""; if ( url.protocol !== "https:" || url.hostname !== CODE_CHANNEL_HOST || !CODE_CHANNEL_REPOSITORIES.has(slug) ) { throw new Error("NON_CANONICAL_CODE_CHANNEL_REPOSITORY"); } return { identity: `repo://${CODE_CHANNEL_HOST}${CODE_CHANNEL_PREFIX}${slug}`, cloneUrl: `https://${CODE_CHANNEL_HOST}${CODE_CHANNEL_PREFIX}${slug}.git`, slug, }; } export function normalizeBranch(value) { const branch = String(value || "").trim(); if ( !branch || !/^(?!\/)(?!.*(?:\.\.|\/\/|@\{|[~^:?*\[\\]))[A-Za-z0-9._/-]+$/u.test( branch, ) || branch.endsWith("/") || branch.endsWith(".") ) { throw new Error("INVALID_TARGET_BRANCH"); } return branch; } export function normalizeReceipt(value) { const relative = String(value || "").replaceAll("\\", "/").replace(/^\.\/+/u, ""); if ( !relative.startsWith("deployment/receipts/") || relative.includes("/../") || relative.endsWith("/") || !/^[A-Za-z0-9._/-]+$/u.test(relative) ) { throw new Error("INVALID_DEPLOYMENT_RECEIPT_PATH"); } return relative; } export function safeCacheRelative(worktree, candidate) { const root = fs.realpathSync(worktree); const absolute = path.resolve(root, candidate); const relative = path.relative(root, absolute).replaceAll(path.sep, "/"); if ( !relative || relative.startsWith("../") || path.isAbsolute(relative) || !SAFE_CACHE_RELATIVE.some((pattern) => pattern.test(relative)) ) { throw new Error(`CACHE_PATH_NOT_ALLOWLISTED:${candidate}`); } return { absolute, relative }; } export function isJsonRecordName(name) { return String(name).endsWith(".json") && !String(name).startsWith("._"); } function run(file, args, options = {}) { const output = execFileSync(file, args, { cwd: options.cwd, encoding: "utf8", stdio: options.stdio || ["ignore", "pipe", "pipe"], maxBuffer: 16 * 1024 * 1024, }); return options.trim === false ? output : output.trim(); } function git(worktree, args) { return run("/usr/bin/git", ["-C", worktree, ...args]); } function gitRaw(worktree, args) { return run("/usr/bin/git", ["-C", worktree, ...args], { trim: false }); } function guard(guardScript, args) { const output = run(process.execPath, [guardScript, ...args]); return output ? JSON.parse(output) : null; } function readJson(filePath) { return JSON.parse(fs.readFileSync(filePath, "utf8")); } export function sha256(value) { return crypto.createHash("sha256").update(value).digest("hex"); } function listOwnedLeases(storeRoot, developmentId) { const directory = path.join(storeRoot, "leases"); if (!fs.existsSync(directory)) return []; return fs .readdirSync(directory) .filter(isJsonRecordName) .map((name) => readJson(path.join(directory, name))) .filter((lease) => lease.development_id === developmentId); } function ensureLane(storeRoot, developmentId, worktree) { const lanePath = path.join(storeRoot, "lanes", `${developmentId}.json`); const lane = readJson(lanePath); if (lane.status !== "active" && lane.status !== "waiting") { throw new Error(`LANE_NOT_RUNNABLE:${lane.status}`); } const owned = listOwnedLeases(storeRoot, developmentId); const resolvedWorktree = fs.realpathSync(worktree); if ( !owned.some((lease) => { if (!path.isAbsolute(lease.resource)) return false; try { const resource = fs.realpathSync(lease.resource); return ( resolvedWorktree === resource || resolvedWorktree.startsWith(`${resource}${path.sep}`) || resource.startsWith(`${resolvedWorktree}${path.sep}`) ); } catch { return false; } }) ) { throw new Error("WORKTREE_WRITE_LEASE_REQUIRED"); } return lane; } function verifyWorktree(worktree, receipts) { const root = fs.realpathSync(git(worktree, ["rev-parse", "--show-toplevel"])); if (root !== fs.realpathSync(worktree)) { throw new Error("WORKTREE_MUST_BE_GIT_ROOT"); } if (git(root, ["status", "--porcelain=v1"])) { throw new Error("WORKTREE_NOT_CLEAN"); } const head = git(root, ["rev-parse", "HEAD"]); if (!/^[0-9a-f]{40}$/u.test(head)) throw new Error("INVALID_LOCAL_HEAD"); const branch = normalizeBranch(git(root, ["branch", "--show-current"])); const receiptEvidence = receipts.map((receipt) => { const relative = normalizeReceipt(receipt); const content = gitRaw(root, ["show", `HEAD:${relative}`]); if (!content) throw new Error(`RECEIPT_NOT_COMMITTED:${relative}`); return { path: relative, sha256: sha256(Buffer.from(content)), bytes: Buffer.byteLength(content), }; }); return { root, head, branch, receiptEvidence }; } function startPublish({ guardScript, developmentId, repository, branch, }) { const requested = guard(guardScript, [ "publish-request", "--development-id", developmentId, "--repository", repository.identity, "--target", branch, "--priority", "normal", ]); guard(guardScript, ["publish-dispatch"]); guard(guardScript, [ "publish-start", "--development-id", developmentId, "--request-id", requested.request_id, ]); return requested.request_id; } function finishPublish(guardScript, developmentId, requestId, outcome, receipt) { return guard(guardScript, [ "publish-finish", "--development-id", developmentId, "--request-id", requestId, "--outcome", outcome, "--receipt", receipt, ]); } function pushAndReadBack(worktree, repository, branch, head, receipts) { run("/usr/bin/git", [ "-C", worktree, "fetch", "--quiet", "origin", `refs/heads/${branch}`, ]); const remoteBefore = git(worktree, [ "rev-parse", `refs/remotes/origin/${branch}`, ]); try { git(worktree, ["merge-base", "--is-ancestor", remoteBefore, head]); } catch { throw new Error(`NON_FAST_FORWARD_REFUSED:${remoteBefore}`); } run("/usr/bin/git", [ "-C", worktree, "push", "origin", `HEAD:refs/heads/${branch}`, ]); const remoteLine = run("/usr/bin/git", [ "ls-remote", repository.cloneUrl, `refs/heads/${branch}`, ]); const remoteHead = remoteLine.split(/\s+/u)[0] || ""; if (remoteHead !== head) { throw new Error(`REMOTE_HEAD_MISMATCH:${remoteHead || "missing"}`); } const readbackRoot = fs.mkdtempSync( path.join(os.tmpdir(), "hololake-finalize-readback-"), ); try { const clone = path.join(readbackRoot, "repo"); run("/usr/bin/git", [ "clone", "--quiet", "--depth", "1", "--branch", branch, repository.cloneUrl, clone, ]); const cloneHead = git(clone, ["rev-parse", "HEAD"]); if (cloneHead !== head) throw new Error(`FRESH_CLONE_HEAD_MISMATCH:${cloneHead}`); git(clone, ["fsck", "--full"]); for (const receipt of receipts) { const remoteContent = gitRaw(clone, ["show", `HEAD:${receipt.path}`]); if (sha256(Buffer.from(remoteContent)) !== receipt.sha256) { throw new Error(`REMOTE_RECEIPT_MISMATCH:${receipt.path}`); } } } finally { fs.rmSync(readbackRoot, { recursive: true, force: true }); } return { remoteBefore, remoteHead }; } function activeProcessFor(absolute) { const output = run("/bin/ps", ["-axo", "pid=,command="]); return output .split("\n") .map((line) => line.trim()) .filter(Boolean) .some((line) => { const match = line.match(/^(\d+)\s+(.*)$/u); if (!match) return false; const pid = Number(match[1]); return pid !== process.pid && pid !== process.ppid && match[2].includes(absolute); }); } function directoryBytes(root) { let total = 0; for (const entry of fs.readdirSync(root, { withFileTypes: true })) { const candidate = path.join(root, entry.name); const stat = fs.lstatSync(candidate); if (stat.isSymbolicLink()) continue; if (stat.isDirectory()) total += directoryBytes(candidate); else if (stat.isFile()) total += stat.size; } return total; } function collectPythonCaches(root, limit = 256) { const found = []; const walk = (directory, depth) => { if (depth > 6 || found.length >= limit) return; for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { if (found.length >= limit) return; if (!entry.isDirectory() || entry.isSymbolicLink()) continue; const candidate = path.join(directory, entry.name); if (entry.name === "__pycache__") { found.push(path.relative(root, candidate)); continue; } if ([".git", "node_modules", "target", "build", "dist"].includes(entry.name)) { continue; } walk(candidate, depth + 1); } }; walk(root, 0); return found; } function cleanupCaches(worktree, explicitPaths) { const candidates = [ ...DEFAULT_CACHE_CANDIDATES, ...collectPythonCaches(worktree), ...explicitPaths, ]; const unique = new Map(); for (const candidate of candidates) { const safe = safeCacheRelative(worktree, candidate); unique.set(safe.absolute, safe); } const results = []; for (const item of unique.values()) { if (!fs.existsSync(item.absolute)) { results.push({ path: item.relative, result: "SKIPPED_NOT_PRESENT", bytes: 0 }); continue; } const stat = fs.lstatSync(item.absolute); if (stat.isSymbolicLink() || !stat.isDirectory()) { throw new Error(`CACHE_TARGET_NOT_REAL_DIRECTORY:${item.relative}`); } if (git(worktree, ["ls-files", "--", item.relative])) { throw new Error(`TRACKED_CACHE_REFUSED:${item.relative}`); } try { git(worktree, ["check-ignore", "--no-index", "-q", "--", item.relative]); } catch { throw new Error(`UNIGNORED_CACHE_REFUSED:${item.relative}`); } if (activeProcessFor(item.absolute)) { results.push({ path: item.relative, result: "SKIPPED_ACTIVE", bytes: 0 }); continue; } const bytes = directoryBytes(item.absolute); fs.rmSync(item.absolute, { recursive: true, force: true }); results.push({ path: item.relative, result: "REMOVED", bytes }); } return results; } function writeFinalizationReceipt(storeRoot, developmentId, payload) { const directory = path.join(storeRoot, "finalization-receipts"); fs.mkdirSync(directory, { recursive: true, mode: 0o700 }); const filePath = path.join( directory, `${developmentId}-${new Date().toISOString().replaceAll(/[:.]/gu, "-")}.json`, ); const temporary = `${filePath}.tmp-${process.pid}`; fs.writeFileSync(temporary, `${JSON.stringify(payload, null, 2)}\n`, { mode: 0o600, }); fs.renameSync(temporary, filePath); return filePath; } function releaseAndComplete({ guardScript, storeRoot, developmentId, summary, }) { for (const lease of listOwnedLeases(storeRoot, developmentId)) { guard(guardScript, [ "release", "--development-id", developmentId, "--resource", lease.resource, ]); } const lane = guard(guardScript, [ "complete", "--development-id", developmentId, "--summary", summary, ]); const actions = guard(guardScript, ["completion-actions"]); const current = actions.find( (item) => item.development_id === developmentId, ); if (!current) throw new Error("COMPLETION_ACTION_MISSING"); if ((current.delete_automation_ids || []).length === 0) { guard(guardScript, [ "mark-completion-stopped", "--development-id", developmentId, ]); return { lane_status: lane.status, notification_state: "stopped" }; } return { lane_status: lane.status, notification_state: "stop_requested", delete_automation_ids: current.delete_automation_ids, }; } export async function finalize(options) { const developmentId = String(options.developmentId || ""); if (!/^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$/u.test(developmentId)) { throw new Error("INVALID_DEVELOPMENT_ID"); } const guardScript = options.guardScript || DEFAULT_GUARD; const storeRoot = options.storeRoot || DEFAULT_STORE; const worktree = fs.realpathSync(options.worktree || ""); if (!options.receipts?.length) throw new Error("AT_LEAST_ONE_RECEIPT_REQUIRED"); ensureLane(storeRoot, developmentId, worktree); const verified = verifyWorktree(worktree, options.receipts); const repository = normalizeCodeChannelRepository( options.repository || git(worktree, ["config", "--get", "remote.origin.url"]), ); const branch = normalizeBranch(options.target || verified.branch); if (branch !== verified.branch) throw new Error("CHECKED_OUT_BRANCH_MISMATCH"); let publishRequestId = null; let publishStarted = false; try { publishRequestId = startPublish({ guardScript, developmentId, repository, branch, }); publishStarted = true; const remote = pushAndReadBack( worktree, repository, branch, verified.head, verified.receiptEvidence, ); const publishReceipt = `PASS_100 remote=${repository.identity}#${branch} ` + `head=${remote.remoteHead} receipts=${verified.receiptEvidence .map((item) => `${item.path}:${item.sha256}`) .join(",")}`; finishPublish( guardScript, developmentId, publishRequestId, "completed", publishReceipt, ); publishStarted = false; const cleanup = cleanupCaches(worktree, options.cleanupPaths || []); const removedBytes = cleanup .filter((item) => item.result === "REMOVED") .reduce((total, item) => total + item.bytes, 0); const payload = { schema: "hololake.development-finalization-receipt/v1", development_id: developmentId, result: "PASS_100", code_channel: { repository: repository.identity, branch, remote_head: remote.remoteHead, fresh_clone_readback: 100, git_fsck: 100, receipts: verified.receiptEvidence, }, cleanup: { scope: "CURRENT_WORKTREE_IGNORED_ALLOWLISTED_CACHES_ONLY", removed_bytes: removedBytes, items: cleanup, }, recorded_at: new Date().toISOString(), }; const finalizationReceipt = writeFinalizationReceipt( storeRoot, developmentId, payload, ); const completion = releaseAndComplete({ guardScript, storeRoot, developmentId, summary: `自动收口PASS_100:第五域代码频道${repository.identity}#${branch}` + `远端回读${remote.remoteHead};${verified.receiptEvidence.length}份回执一致;` + `本车道安全缓存清理${removedBytes}字节;回执${finalizationReceipt}`, }); return { ...payload, finalization_receipt: finalizationReceipt, completion }; } catch (error) { if (publishStarted && publishRequestId) { try { finishPublish( guardScript, developmentId, publishRequestId, "failed", `FAIL_0 ${String(error.message || error).slice(0, 400)}`, ); } catch { // The original finalization failure remains authoritative. } } throw error; } } export function selfTest() { const canonical = normalizeCodeChannelRepository( "https://guanghulab.com/code/bingshuo/guanghu-ice-heart.git", ); if ( canonical.identity !== "repo://guanghulab.com/code/bingshuo/guanghu-ice-heart" ) { throw new Error("SELF_TEST_REPOSITORY_NORMALIZATION_FAILED"); } for (const invalid of [ "https://guanghulab.com/fifth-domain/bingshuo/fifth-domain.git", "https://user:secret@guanghulab.com/code/bingshuo/guanghu-ice-heart.git", ]) { let rejected = false; try { normalizeCodeChannelRepository(invalid); } catch { rejected = true; } if (!rejected) throw new Error("SELF_TEST_INVALID_REPOSITORY_ACCEPTED"); } if ( normalizeReceipt( "deployment/receipts/GLW-CHJH-ROUTER-CONTROLLER-JD-20260805.json", ) !== "deployment/receipts/GLW-CHJH-ROUTER-CONTROLLER-JD-20260805.json" ) { throw new Error("SELF_TEST_RECEIPT_NORMALIZATION_FAILED"); } return { result: "PASS_100" }; } async function main() { const args = parseArgs(process.argv.slice(2)); const result = args.selfTest ? selfTest() : await finalize({ developmentId: args.developmentId, worktree: args.worktree, repository: args.repository, target: args.target, receipts: args.receipts, cleanupPaths: args.cleanupPaths, guardScript: args.guardScript, storeRoot: args.storeRoot, }); process.stdout.write(`${JSON.stringify(result, null, 2)}\n`); } if (process.argv[1] === fileURLToPath(import.meta.url)) { main().catch((error) => { process.stderr.write(`FINALIZATION_FAIL_0:${String(error.message || error)}\n`); process.exitCode = 1; }); }