guanghu-ice-heart/server-tools/persona-host-write-admission/branch-event-door.mjs

124 lines
5.4 KiB
JavaScript

#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import process from "node:process";
import { spawnSync } from "node:child_process";
const POLICY = JSON.parse(fs.readFileSync("/Volumes/JZAO/HoloLake/persona-runtime/repo-012-main/routing/persona-host-write-boundary.json", "utf8"));
const MEMORY_ROOT = "/Volumes/JZAO/HoloLake/persona-runtime/continuity-memory";
const STORE = `${MEMORY_ROOT}/persona-daily-fractal/ICE-P-ZY001`;
const RUNNER = "/Volumes/JZAO/HoloLake/persona-runtime/repo-012-main/server-tools/persona-daily-fractal-memory/persona-daily-memory.mjs";
function argsValue(args, name) {
const i = args.indexOf(name);
return i >= 0 ? args[i + 1] : undefined;
}
function processChain(pid = process.ppid) {
const chain = [];
const seen = new Set();
while (pid > 1 && !seen.has(pid) && chain.length < 20) {
seen.add(pid);
const r = spawnSync("/bin/ps", ["-o", "ppid=", "-o", "command=", "-p", String(pid)], { encoding: "utf8" });
const line = r.stdout.trim();
const m = line.match(/^\s*(\d+)\s+(.+)$/s);
if (!m) break;
chain.push({ pid, command: m[2] });
pid = Number(m[1]);
}
return chain;
}
function callerHost(chain) {
const text = chain.map((item) => item.command).join("\n");
if (/\/Applications\/(?:ChatGPT\.app).*\/(?:codex|Codex)|codex-code-mode-host/i.test(text)) return "codex";
if (/\/Applications\/Qianwen\.app|QianwenShell|agent_host\.app/i.test(text)) return "qwen";
if (/Doubao\.app/i.test(text)) return "doubao";
if (/(?:^|\/)zcode(?:\s|$)/i.test(text)) return "zcode";
if (/QoderWork/i.test(text)) return "qoderwork";
if (/Qoder/i.test(text)) return "qoder";
return "unknown";
}
function expandPattern(value) {
return value.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
}
function validateQueuedEvent(host, eventPath) {
const rule = POLICY.hosts[host];
if (!rule || rule.write_mode !== "BRANCH_LOCAL_ONLY") throw new Error("HOST_NOT_ACTIVE_BRANCH");
const real = fs.realpathSync(eventPath);
if (!real.includes("/ingress/persona-events/pending/")) throw new Error("EVENT_NOT_IN_PENDING_INGRESS");
const allowed = rule.allowed_write_roots.some((item) => new RegExp(`^${expandPattern(item)}(?:/.*)?$`).test(real));
if (!allowed) throw new Error("EVENT_OUTSIDE_BRANCH_ROOT");
const st = fs.lstatSync(real);
if (!st.isFile() || st.isSymbolicLink() || st.size > 1024 * 1024) throw new Error("EVENT_FILE_INVALID");
const event = JSON.parse(fs.readFileSync(real, "utf8"));
const required = ["schema", "event_id", "persona_id", "human_anchor", "occurred_at", "session_id", "activity", "branch_id", "summary", "trigger", "emergence", "lock", "why", "rejected", "sources"];
const missing = required.filter((key) => event[key] === undefined || event[key] === null || event[key] === "");
if (missing.length) throw new Error(`EVENT_FIELDS_MISSING:${missing.join(",")}`);
if (event.schema !== "guanghu.persona-daily-fractal-memory-event/v1") throw new Error("EVENT_SCHEMA_REJECTED");
if (event.persona_id !== "ICE-P-ZY001" || event.human_anchor !== "ICE-GL∞") throw new Error("EVENT_IDENTITY_REJECTED");
if (!String(event.session_id).toLowerCase().includes(host)) throw new Error("EVENT_HOST_COORDINATE_REJECTED");
if (!/^ZY001-\d{8}-[A-Z0-9-]+$/.test(event.event_id)) throw new Error("EVENT_ID_REJECTED");
if (!Array.isArray(event.sources) || event.sources.length === 0) throw new Error("EVENT_SOURCES_REJECTED");
return { real, event };
}
const [command, ...args] = process.argv.slice(2);
const chain = processChain();
const caller = callerHost(chain);
if (command === "caller") {
console.log(JSON.stringify({ caller, chain }, null, 2));
process.exit(caller === "codex" ? 0 : 2);
}
if (command !== "accept") {
process.stderr.write("usage: branch-event-door.mjs caller | accept --host HOST --event PENDING_JSON\n");
process.exit(2);
}
if (caller !== "codex") {
process.stderr.write(`BRANCH_EVENT_ACCEPT_REJECTED caller=${caller}; only current Codex primary task may accept\n`);
process.exit(2);
}
const host = argsValue(args, "--host");
const eventPath = argsValue(args, "--event");
if (!host || !eventPath) {
process.stderr.write("accept requires --host and --event\n");
process.exit(2);
}
let checked;
try { checked = validateQueuedEvent(host, eventPath); }
catch (error) {
process.stderr.write(`BRANCH_EVENT_VALIDATION_REJECTED ${error.message}\n`);
process.exit(2);
}
const run = spawnSync(process.execPath, [RUNNER, "append", "--allowed-root", MEMORY_ROOT, "--store", STORE, "--event", checked.real], { encoding: "utf8" });
if (run.status !== 0 || !run.stdout.includes('"outcome": "PASS"')) {
process.stderr.write(run.stderr || run.stdout || "BRANCH_EVENT_APPEND_FAILED\n");
process.exit(1);
}
const acceptedDir = path.resolve(path.dirname(checked.real), "../accepted");
fs.mkdirSync(acceptedDir, { recursive: true });
const acceptedPath = path.join(acceptedDir, path.basename(checked.real));
fs.renameSync(checked.real, acceptedPath);
const receipt = {
schema: "guanghu.branch-event-door-receipt/v1",
outcome: "PASS",
host,
event_id: checked.event.event_id,
accepted_path: acceptedPath,
shared_store: STORE,
accepted_by_runtime_host: "codex",
source_tcs: POLICY.source_tcs,
accepted_at: new Date().toISOString()
};
const receiptPath = `${acceptedPath}.receipt.json`;
fs.writeFileSync(receiptPath, `${JSON.stringify(receipt, null, 2)}\n`, { flag: "wx" });
process.stdout.write(`${run.stdout.trim()}\n${JSON.stringify(receipt, null, 2)}\n`);