344 lines
14 KiB
JavaScript
344 lines
14 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
import crypto from "node:crypto";
|
||
|
|
import fs from "node:fs";
|
||
|
|
import path from "node:path";
|
||
|
|
|
||
|
|
const CONTROL_ROOT = process.env.GH_CODEX_CONTROL_ROOT ??
|
||
|
|
"/Users/bingshuolingdianyuanhe/.codex/runtime/hldp-v1/control";
|
||
|
|
const CONTROLLER_PATH = path.join(CONTROL_ROOT, "current-controller.json");
|
||
|
|
const LEASE_SCRIPT = "/Users/bingshuolingdianyuanhe/.codex/runtime/hldp-v1/codex-write-lease.mjs";
|
||
|
|
const ANCHOR_GATE_SCRIPT = "/Users/bingshuolingdianyuanhe/.codex/runtime/hldp-v1/codex-task-anchor-gate.mjs";
|
||
|
|
const TASK_ANCHOR_ROOT = process.env.GH_CODEX_TASK_ANCHOR_ROOT ??
|
||
|
|
"/Volumes/JZAO/HoloLake/persona-runtime/task-language-anchors/codex";
|
||
|
|
|
||
|
|
function safeToken(value, fallback = "unknown") {
|
||
|
|
const token = String(value ?? "").trim().replaceAll(/[^a-zA-Z0-9._-]/gu, "-");
|
||
|
|
return token || fallback;
|
||
|
|
}
|
||
|
|
|
||
|
|
function sessionBindingPath(sessionId) {
|
||
|
|
return path.join(CONTROL_ROOT, "sessions", `${safeToken(sessionId)}.json`);
|
||
|
|
}
|
||
|
|
|
||
|
|
function channelControllerPath(channelId) {
|
||
|
|
return path.join(CONTROL_ROOT, "channels", safeToken(channelId), "controller.json");
|
||
|
|
}
|
||
|
|
|
||
|
|
function channelLeasePath(channelId) {
|
||
|
|
return path.join(CONTROL_ROOT, "channel-leases", safeToken(channelId), "write-lease.json");
|
||
|
|
}
|
||
|
|
|
||
|
|
function readInput() {
|
||
|
|
try {
|
||
|
|
const raw = fs.readFileSync(0, "utf8").trim();
|
||
|
|
return raw ? JSON.parse(raw) : {};
|
||
|
|
} catch {
|
||
|
|
return {};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function readJson(file) {
|
||
|
|
try {
|
||
|
|
return JSON.parse(fs.readFileSync(file, "utf8"));
|
||
|
|
} catch {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function atomicWriteJson(file, value) {
|
||
|
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
||
|
|
const temporary = `${file}.${process.pid}.tmp`;
|
||
|
|
fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
|
||
|
|
fs.renameSync(temporary, file);
|
||
|
|
}
|
||
|
|
|
||
|
|
function sha256(value) {
|
||
|
|
return crypto.createHash("sha256").update(value).digest("hex");
|
||
|
|
}
|
||
|
|
|
||
|
|
function allow(additionalContext = null) {
|
||
|
|
const value = additionalContext
|
||
|
|
? {
|
||
|
|
hookSpecificOutput: {
|
||
|
|
hookEventName: "PreToolUse",
|
||
|
|
additionalContext,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
: { continue: true };
|
||
|
|
process.stdout.write(JSON.stringify(value));
|
||
|
|
}
|
||
|
|
|
||
|
|
function deny(reason) {
|
||
|
|
process.stdout.write(JSON.stringify({
|
||
|
|
hookSpecificOutput: {
|
||
|
|
hookEventName: "PreToolUse",
|
||
|
|
permissionDecision: "deny",
|
||
|
|
permissionDecisionReason: reason,
|
||
|
|
},
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
|
||
|
|
function toolPayload(input) {
|
||
|
|
if (typeof input.tool_input === "string") return input.tool_input;
|
||
|
|
try {
|
||
|
|
return JSON.stringify(input.tool_input ?? {});
|
||
|
|
} catch {
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function actionPayload(input) {
|
||
|
|
const name = String(input.tool_name ?? "");
|
||
|
|
const value = input.tool_input;
|
||
|
|
if (/apply_patch/iu.test(name)) return "";
|
||
|
|
if (/(?:^|__)functions\.exec(?:$|__)/iu.test(name) || name === "functions.exec") {
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
if (typeof value === "string") return value;
|
||
|
|
if (value && typeof value === "object") {
|
||
|
|
for (const key of ["cmd", "command", "script", "query"]) {
|
||
|
|
if (typeof value[key] === "string") return value[key];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return toolPayload(input);
|
||
|
|
}
|
||
|
|
|
||
|
|
function categoryFor(input) {
|
||
|
|
const name = String(input.tool_name ?? "");
|
||
|
|
const payload = actionPayload(input);
|
||
|
|
const combined = `${name}\n${payload}`;
|
||
|
|
if (combined.includes(LEASE_SCRIPT)) return null;
|
||
|
|
|
||
|
|
if (/apply_patch/iu.test(name)) {
|
||
|
|
return /\*\*\* Delete File:/u.test(toolPayload(input))
|
||
|
|
? "destructive_cleanup"
|
||
|
|
: null;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (
|
||
|
|
/\bgit\b[\s\S]{0,900}\bpush\b/iu.test(combined) ||
|
||
|
|
/\b(?:gh\s+(?:pr\s+(?:create|merge)|release\s+create|repo\s+delete)|docker\s+push)\b/iu.test(combined)
|
||
|
|
) return "remote_git";
|
||
|
|
|
||
|
|
if (
|
||
|
|
/\b(?:npm|pnpm|yarn|cargo|twine)\s+publish\b/iu.test(combined) ||
|
||
|
|
/\b(?:vercel|flyctl|netlify)\b[\s\S]{0,300}\b(?:deploy|publish|--prod)\b/iu.test(combined) ||
|
||
|
|
/\b(?:wrangler|kubectl|helm)\b[\s\S]{0,300}\b(?:deploy|publish|apply|delete|patch|replace|upgrade)\b/iu.test(combined) ||
|
||
|
|
/\bcurl\b[\s\S]{0,500}(?:-X|--request)\s*(?:POST|PUT|PATCH|DELETE)\b/iu.test(combined) ||
|
||
|
|
/(?:deploy|publish|create_release|merge_pull_request|send_email)/iu.test(name)
|
||
|
|
) return "external_publish";
|
||
|
|
|
||
|
|
if (
|
||
|
|
/\brm\s+/iu.test(payload) ||
|
||
|
|
/\bmv\b[\s\S]{0,1200}(?:\/\.Trash(?:\/|\b)|\bTrash\b)/iu.test(payload) ||
|
||
|
|
/\bfind\b[\s\S]{0,700}\s-delete\b/iu.test(payload) ||
|
||
|
|
/\b(?:npm|pnpm|yarn)\s+cache\s+(?:clean|clear)\b/iu.test(payload) ||
|
||
|
|
/\bcargo\s+clean\b/iu.test(payload) ||
|
||
|
|
/\bxcodebuild\b[\s\S]{0,300}\bclean\b/iu.test(payload) ||
|
||
|
|
/\b(?:brew|port)\s+cleanup\b/iu.test(payload) ||
|
||
|
|
/\bgit\b[\s\S]{0,300}\b(?:clean\b|reset\s+--hard\b)/iu.test(payload) ||
|
||
|
|
/\bdiskutil\b[\s\S]{0,200}\berase/iu.test(payload) ||
|
||
|
|
/\*\*\* Delete File:/u.test(payload)
|
||
|
|
) return "destructive_cleanup";
|
||
|
|
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
function isCapabilityTool(input) {
|
||
|
|
const name = String(input.tool_name ?? "");
|
||
|
|
return (
|
||
|
|
["Bash", "exec_command", "functions.exec_command", "functions.exec", "apply_patch", "write_stdin"].includes(name) ||
|
||
|
|
/(?:^|__)(?:exec|exec_command|apply_patch|write_stdin|computer_use|control_chrome|control_in_app_browser)(?:$|__)/iu.test(name) ||
|
||
|
|
/(?:create|update|delete|remove|write|send|merge|deploy|publish|push)/iu.test(name)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function isAnchorGateVerification(input) {
|
||
|
|
const payload = toolPayload(input);
|
||
|
|
return payload.includes(ANCHOR_GATE_SCRIPT) && /(?:^|\s|["'])verify(?:\s|["']|$)/u.test(payload);
|
||
|
|
}
|
||
|
|
|
||
|
|
function isEngineeringMapBootstrap(input) {
|
||
|
|
const name = String(input.tool_name ?? "");
|
||
|
|
if (!/apply_patch/iu.test(name)) return false;
|
||
|
|
const payload = toolPayload(input);
|
||
|
|
const targets = [...payload.matchAll(/^\*\*\* (?:Add|Update|Delete) File: (.+)$/gmu)].map((match) => match[1].trim());
|
||
|
|
if (targets.length !== 1) return false;
|
||
|
|
const sessionId = safeToken(input.session_id);
|
||
|
|
const expected = path.join(
|
||
|
|
TASK_ANCHOR_ROOT,
|
||
|
|
`CODEX-TASK-${sessionId}`,
|
||
|
|
"01-自然语言到工程阶段映射",
|
||
|
|
"current.tcs",
|
||
|
|
);
|
||
|
|
return targets[0] === expected;
|
||
|
|
}
|
||
|
|
|
||
|
|
function consumeStageReceipt(input, controller, sessionBinding) {
|
||
|
|
const sessionId = safeToken(input.session_id);
|
||
|
|
const taskNumber = controller?.durable_task_number ??
|
||
|
|
sessionBinding?.durable_task_number ?? `CODEX-TASK-${sessionId}`;
|
||
|
|
const taskRoot = path.join(TASK_ANCHOR_ROOT, taskNumber);
|
||
|
|
const manifest = readJson(path.join(taskRoot, "task.json"));
|
||
|
|
const receiptPath = path.join(taskRoot, "10-阶段回读回执", "current.json");
|
||
|
|
const receipt = readJson(receiptPath);
|
||
|
|
const engineeringMapPath = path.join(taskRoot, "01-自然语言到工程阶段映射", "current.tcs");
|
||
|
|
let engineeringMapSha256 = null;
|
||
|
|
try { engineeringMapSha256 = sha256(fs.readFileSync(engineeringMapPath, "utf8")); } catch {}
|
||
|
|
let developmentTask = null;
|
||
|
|
let developmentDualHashes = [];
|
||
|
|
let developmentEngineeringMapSha256 = null;
|
||
|
|
if (controller?.development_task_number) {
|
||
|
|
developmentTask = readJson(controller.development_task_manifest);
|
||
|
|
try {
|
||
|
|
developmentDualHashes = developmentTask.dual_start_anchors.map((anchor) =>
|
||
|
|
sha256(fs.readFileSync(anchor.raw_text_path, "utf8"))
|
||
|
|
);
|
||
|
|
developmentEngineeringMapSha256 = sha256(fs.readFileSync(developmentTask.tcs_engineering_map, "utf8"));
|
||
|
|
} catch {
|
||
|
|
return { ok: false, reason: "DEVELOPMENT_DUAL_START_OR_ENGINEERING_MAP_UNREADABLE" };
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (manifest?.schema !== "guanghu.codex-task-natural-language-anchor/v1") {
|
||
|
|
return { ok: false, reason: `TASK_ANCHOR_MISSING:${taskRoot}` };
|
||
|
|
}
|
||
|
|
if (receipt?.schema !== "guanghu.codex-task-stage-anchor-read-receipt/v1") {
|
||
|
|
return { ok: false, reason: "STAGE_ANCHOR_READ_RECEIPT_MISSING" };
|
||
|
|
}
|
||
|
|
const expectedTurn = safeToken(input.turn_id, "unknown-turn");
|
||
|
|
const expectedEpoch = controller?.control_epoch;
|
||
|
|
if (
|
||
|
|
receipt.task_number !== taskNumber ||
|
||
|
|
receipt.session_id !== sessionId ||
|
||
|
|
receipt.turn_id !== expectedTurn ||
|
||
|
|
receipt.control_epoch !== expectedEpoch ||
|
||
|
|
receipt.first_event_sha256 !== manifest.first_event_sha256 ||
|
||
|
|
receipt.current_event_sha256 !== manifest.current_event_sha256 ||
|
||
|
|
receipt.engineering_map_path !== engineeringMapPath ||
|
||
|
|
receipt.engineering_map_sha256 !== engineeringMapSha256 ||
|
||
|
|
controller?.raw_text_sha256 !== manifest.current_event_sha256
|
||
|
|
) return { ok: false, reason: "STAGE_ANCHOR_READ_RECEIPT_STALE_OR_MISMATCHED" };
|
||
|
|
if (controller?.development_task_number && (
|
||
|
|
developmentTask?.schema !== "guanghu.zero-core-development-task/v1" ||
|
||
|
|
developmentTask.development_task_number !== controller.development_task_number ||
|
||
|
|
developmentTask.current_host_thread !== sessionId ||
|
||
|
|
receipt.development_task_number !== developmentTask.development_task_number ||
|
||
|
|
receipt.development_task_manifest !== controller.development_task_manifest ||
|
||
|
|
JSON.stringify(receipt.development_dual_start_sha256) !== JSON.stringify(developmentDualHashes) ||
|
||
|
|
JSON.stringify(developmentTask.dual_start_anchors.map((anchor) => anchor.raw_text_sha256)) !== JSON.stringify(developmentDualHashes) ||
|
||
|
|
receipt.development_engineering_map_path !== developmentTask.tcs_engineering_map ||
|
||
|
|
receipt.development_engineering_map_sha256 !== developmentEngineeringMapSha256
|
||
|
|
)) return { ok: false, reason: "DEVELOPMENT_DUAL_START_ANCHOR_STALE_OR_MISMATCHED" };
|
||
|
|
if (!Number.isFinite(receipt.expires_at_unix_ms) || receipt.expires_at_unix_ms < Date.now()) {
|
||
|
|
return { ok: false, reason: "STAGE_ANCHOR_READ_RECEIPT_EXPIRED_30_MINUTES" };
|
||
|
|
}
|
||
|
|
if (
|
||
|
|
!Number.isFinite(receipt.capability_calls_used) ||
|
||
|
|
receipt.capability_calls_used >= receipt.capability_calls_max
|
||
|
|
) return { ok: false, reason: "STAGE_CAPABILITY_BUDGET_EXHAUSTED_20_CALLS" };
|
||
|
|
receipt.capability_calls_used += 1;
|
||
|
|
receipt.last_capability_call_at = new Date().toISOString();
|
||
|
|
atomicWriteJson(receiptPath, receipt);
|
||
|
|
return {
|
||
|
|
ok: true,
|
||
|
|
remaining: receipt.capability_calls_max - receipt.capability_calls_used,
|
||
|
|
stage: receipt.stage,
|
||
|
|
deliverable: receipt.declared_deliverable,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
function consumeValidLease(input, controller, channel, category) {
|
||
|
|
const leasePath = channelLeasePath(channel.channel_id);
|
||
|
|
const lease = readJson(leasePath);
|
||
|
|
if (
|
||
|
|
!lease ||
|
||
|
|
lease.schema !== "guanghu.codex-one-shot-write-lease/v1" ||
|
||
|
|
lease.one_shot !== true ||
|
||
|
|
lease.channel_id !== channel.channel_id ||
|
||
|
|
lease.control_epoch !== controller.control_epoch ||
|
||
|
|
lease.session_id !== input.session_id ||
|
||
|
|
lease.turn_id !== input.turn_id ||
|
||
|
|
lease.category !== category ||
|
||
|
|
lease.cwd !== path.resolve(input.cwd ?? process.cwd()) ||
|
||
|
|
!Number.isFinite(lease.expires_at_unix_ms) ||
|
||
|
|
lease.expires_at_unix_ms < Date.now()
|
||
|
|
) return null;
|
||
|
|
try {
|
||
|
|
fs.unlinkSync(leasePath);
|
||
|
|
} catch {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return lease;
|
||
|
|
}
|
||
|
|
|
||
|
|
const input = readInput();
|
||
|
|
if ((input.hook_event_name ?? input.hookEventName) !== "PreToolUse") {
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
const sessionBinding = readJson(sessionBindingPath(input.session_id));
|
||
|
|
const channel = sessionBinding?.schema === "guanghu.codex-channel-session-binding/v1"
|
||
|
|
? readJson(channelControllerPath(sessionBinding.channel_id))
|
||
|
|
: null;
|
||
|
|
const legacyController = readJson(CONTROLLER_PATH);
|
||
|
|
const controller = channel?.schema === "guanghu.codex-channel-controller/v1"
|
||
|
|
? channel
|
||
|
|
: legacyController;
|
||
|
|
const personaExecutionActive = Boolean(
|
||
|
|
controller?.controller_phase === "PERSONA_ACTIVE_HUMAN_ANCHOR" &&
|
||
|
|
controller.active_persona_controller === "ICE-P-ZY001" &&
|
||
|
|
controller.execution_state === "CONTINUE",
|
||
|
|
);
|
||
|
|
const systemConfigurationActive = Boolean(
|
||
|
|
controller?.controller_phase === "SYSTEM_CONFIGURATION_ACTIVE" &&
|
||
|
|
controller.system_instruction_state === "ACTIVE" &&
|
||
|
|
controller.human_system_controller === "ICE-GL∞" &&
|
||
|
|
controller.active_execution_controller === "ICE-GL∞_SYSTEM_CONFIGURATION" &&
|
||
|
|
controller.execution_state === "SYSTEM_CONFIGURATION_IN_PROGRESS",
|
||
|
|
);
|
||
|
|
const currentSession = Boolean(
|
||
|
|
(
|
||
|
|
controller?.schema === "guanghu.codex-channel-controller/v1" ||
|
||
|
|
controller?.schema === "guanghu.codex-current-controller/v1"
|
||
|
|
) &&
|
||
|
|
controller.direct_bingshuo_natural_language === true &&
|
||
|
|
(controller.bound_session_id ?? controller.session_id) === input.session_id &&
|
||
|
|
(personaExecutionActive || systemConfigurationActive)
|
||
|
|
);
|
||
|
|
|
||
|
|
if (!currentSession && isCapabilityTool(input)) {
|
||
|
|
deny(`STALE_OR_UNCLAIMED_CODEX_TASK_CAPABILITY_BLOCKED; channel=${sessionBinding?.channel_id ?? "UNBOUND"}; current_session=${controller?.bound_session_id ?? controller?.session_id ?? "NONE"}; attempted_session=${input.session_id ?? "UNKNOWN"}`);
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
let stageReceipt = null;
|
||
|
|
if (
|
||
|
|
currentSession &&
|
||
|
|
isCapabilityTool(input) &&
|
||
|
|
!isAnchorGateVerification(input) &&
|
||
|
|
!isEngineeringMapBootstrap(input)
|
||
|
|
) {
|
||
|
|
stageReceipt = consumeStageReceipt(input, controller, sessionBinding);
|
||
|
|
if (!stageReceipt.ok) {
|
||
|
|
deny(`${stageReceipt.reason}; FIRST_REREAD_BINGSHUO_RAW_LANGUAGE_THEN_DECLARE_ONE_DELIVERABLE; run=node ${ANCHOR_GATE_SCRIPT} verify --session-id ${input.session_id ?? "UNKNOWN"} --turn-id ${input.turn_id ?? "UNKNOWN"} --control-epoch ${controller?.control_epoch ?? "UNKNOWN"} --stage <STAGE> --deliverable <ONE_TARGET_DELIVERABLE>`);
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const category = categoryFor(input);
|
||
|
|
if (!category) {
|
||
|
|
allow(stageReceipt ? `CODEX_TASK_STAGE_GATE_ACTIVE stage=${stageReceipt.stage}; remaining_capability_calls=${stageReceipt.remaining}; deliverable=${stageReceipt.deliverable}` : null);
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
if (!currentSession) {
|
||
|
|
deny(`STALE_OR_UNCLAIMED_CODEX_TASK_HIGH_RISK_BLOCKED; category=${category}`);
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
const effectiveChannel = channel ?? {
|
||
|
|
channel_id: controller?.channel_id ?? `LEGACY-${controller?.session_id ?? "UNKNOWN"}`,
|
||
|
|
};
|
||
|
|
const lease = consumeValidLease(input, controller, effectiveChannel, category);
|
||
|
|
if (!lease) {
|
||
|
|
deny(`CURRENT_CODEX_TASK_ONE_SHOT_LEASE_REQUIRED; category=${category}; issue_only_after_explicit_current_turn_bingshuo_authorization`);
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
allow(`GUANGHU_ONE_SHOT_WRITE_LEASE_CONSUMED lease_id=${lease.lease_id}; channel=${effectiveChannel.channel_id}; category=${category}; target=${lease.target}`);
|