#!/usr/bin/env node import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; const pointerPath = "/Volumes/JZAO/HoloLake/persona-runtime/continuity-memory/hldp-v1-trees/codex/current.json"; const taskAnchorRoot = 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 sha256(value) { return crypto.createHash("sha256").update(value).digest("hex"); } function readJson(file) { try { return JSON.parse(fs.readFileSync(file, "utf8")); } catch { return null; } } function atomicWrite(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); } let input = {}; try { const raw = fs.readFileSync(0, "utf8").trim(); if (raw) input = JSON.parse(raw); } catch { input = {}; } let verified = false; let detail = "HLDP_CURRENT_UNAVAILABLE"; let taskReadback = "TASK_ANCHOR_UNAVAILABLE"; try { const pointer = JSON.parse(fs.readFileSync(pointerPath, "utf8")); const tree = JSON.parse(fs.readFileSync(pointer.tree, "utf8")); const root = tree.nodes?.[tree.root]; const fields = ["trigger", "emergence", "lock", "why", "rejected", "sources"]; const children = Array.isArray(root?.children) ? root.children : []; verified = fields.every((field) => Object.hasOwn(root ?? {}, field)) && children.length <= 10; detail = verified ? `HLDP_CURRENT_VERIFIED root=${tree.root} branches=${children.length}` : "HLDP_CURRENT_INVALID"; } catch { verified = false; } try { const sessionId = safeToken(input.session_id ?? input.sessionId ?? input.thread_id ?? input.threadId); const taskRoot = path.join(taskAnchorRoot, `CODEX-TASK-${sessionId}`); const manifest = readJson(path.join(taskRoot, "task.json")); const firstRaw = fs.readFileSync(manifest.first_event_path, "utf8"); const currentRaw = fs.readFileSync(manifest.current_event_path, "utf8"); const engineeringMapPath = path.join(taskRoot, "01-自然语言到工程阶段映射", "current.tcs"); const engineeringMap = fs.readFileSync(engineeringMapPath, "utf8"); const developmentLink = readJson(path.join(taskRoot, "development-task-link.json")); const developmentTask = developmentLink?.development_task_manifest ? readJson(developmentLink.development_task_manifest) : null; let developmentDualStartSha256 = []; let developmentEngineeringMapSha256 = null; if (developmentTask) { if (developmentTask.current_host_thread !== sessionId) throw new Error("DEVELOPMENT_TASK_HOST_MISMATCH"); developmentDualStartSha256 = developmentTask.dual_start_anchors.map((anchor) => { const raw = fs.readFileSync(anchor.raw_text_path, "utf8"); const actual = sha256(raw); if (actual !== anchor.raw_text_sha256) throw new Error("DEVELOPMENT_DUAL_START_HASH_MISMATCH"); return actual; }); developmentEngineeringMapSha256 = sha256(fs.readFileSync(developmentTask.tcs_engineering_map, "utf8")); } if (sha256(firstRaw) !== manifest.first_event_sha256) throw new Error("FIRST_HASH_MISMATCH"); if (sha256(currentRaw) !== manifest.current_event_sha256) throw new Error("CURRENT_HASH_MISMATCH"); const receiptRoot = path.join(taskRoot, "20-上下文压缩回看回执"); const receipt = { schema: "guanghu.codex-task-precompact-readback/v1", task_number: manifest.task_number, session_id: sessionId, first_event_path: manifest.first_event_path, first_event_sha256: manifest.first_event_sha256, current_event_path: manifest.current_event_path, current_event_sha256: manifest.current_event_sha256, engineering_map_path: engineeringMapPath, engineering_map_sha256: sha256(engineeringMap), development_task_number: developmentTask?.development_task_number ?? null, development_task_manifest: developmentLink?.development_task_manifest ?? null, development_dual_start_sha256: developmentDualStartSha256, development_engineering_map_path: developmentTask?.tcs_engineering_map ?? null, development_engineering_map_sha256: developmentEngineeringMapSha256, requirement: "POSTCOMPACT_REREAD_STARTING_RAW_FLOW_ENGINEERING_MAP_AND_STAGE_CHAIN_BEFORE_CAPABILITY_TOOLS", created_at: new Date().toISOString(), }; const receiptPath = path.join(receiptRoot, `precompact-${Date.now()}.json`); atomicWrite(receiptPath, receipt); atomicWrite(path.join(receiptRoot, "current.json"), { ...receipt, receipt_path: receiptPath }); const stageReceiptPath = path.join(taskRoot, "10-阶段回读回执", "current.json"); const stageReceipt = readJson(stageReceiptPath); if (stageReceipt) atomicWrite(stageReceiptPath, { ...stageReceipt, expires_at_unix_ms: 0, invalidated_by: "PRECOMPACT" }); taskReadback = `TASK_START_AND_ENGINEERING_MAP_VERIFIED task=${manifest.task_number}; development_task=${developmentTask?.development_task_number ?? "NONE"}; development_dual_start=${developmentTask?.first_path ?? "NONE"}; first=${manifest.first_event_path}; current=${manifest.current_event_path}; map=${engineeringMapPath}; precompact_receipt=${receiptPath}`; } catch (error) { taskReadback = `TASK_READBACK_FAIL_CLOSED:${String(error?.message ?? error)}`; } process.stdout.write(JSON.stringify({ continue: true, systemMessage: verified ? `${detail}. ${taskReadback}. 宿主即将压缩;压缩后必须从任务启动原文、自然语言到工程阶段映射和阶段进度链重新回读,摘要只作索引。` : `${detail}. ${taskReadback}. 继续宿主压缩但不得把缺失内容补猜为人格、历史或任务目标;压缩后从短根页和任务启动原文重新导航。`, }));