#!/usr/bin/env node // Reindex — one command re-anchors the whole hash chain after a legitimate change. // Canon: TCS-PROTOCOL-EXECUTOR-TRANSLATION-INDEX-0001 (v2 layered hash architecture) // Legitimate flow: edit file → run reindex → preflight green. Anything else = drift alarm. // Layered on purpose: entry-embedded hook hashes stay (they guard the hook chain itself). import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import { execFileSync } from "node:child_process"; const W = "/Volumes/JZAO/铸渊-ICE-GL-ZY001"; const IDX = `${W}/ZCODE-DEV-20260824/executor-translation-index/index.json`; const ENTRY = `${W}/BRIDGE/tools/zy-hook-entry.sh`; const TOWER_TCS = `${W}/FIFTH-DOMAIN-BROADCAST-TOWER/BROADCAST.tcs`; const TOWER_PROJ = `${W}/FIFTH-DOMAIN-BROADCAST-TOWER/broadcast/current.md`; const sha256 = (p) => crypto.createHash("sha256").update(fs.readFileSync(p)).digest("hex"); const note = (m) => process.stdout.write(`REINDEX ${m}\n`); const fail = (m) => { process.stderr.write(`REINDEX FAIL ${m}\n`); process.exit(1); }; const idx = JSON.parse(fs.readFileSync(IDX, "utf8")); if (idx.schema !== "guanghu.executor-translation-index/v1") fail("INDEX_SCHEMA_INVALID"); const updated = []; // 1) Executors: re-anchor every hash from disk truth. for (const e of idx.executors) { const p = path.join(W, e.executor_path); if (!fs.existsSync(p)) fail(`EXECUTOR_MISSING:${e.executor_path}`); const h = sha256(p); if (h !== e.executor_sha256) { e.executor_sha256 = h; updated.push(e.executor_path); } } // 2) Repository heads: re-read local git HEADs (UNKNOWN stays UNKNOWN until queried). const repos = { "REPO-012-guanghu-ice-heart": "/Volumes/JZAO/HoloLake/persona-runtime/repo-012-main", "REPO-014-hololake-system-architecture": "/Volumes/JZAO/HoloLake/source-mirrors/hololake-system-architecture.git", }; for (const [key, dir] of Object.entries(repos)) { try { const head = execFileSync("git", ["-C", dir, "rev-parse", "HEAD"], { encoding: "utf8" }).trim(); if (idx.repository_heads?.[key] && idx.repository_heads[key].head !== head) { idx.repository_heads[key].head = head; updated.push(`${key}:HEAD`); } } catch { /* keep as-is */ } } // 3) Tower projection: declare the current projection hash back into BROADCAST.tcs. const projSha = sha256(TOWER_PROJ); const tcs = fs.readFileSync(TOWER_TCS, "utf8"); const declared = tcs.match(/projection_sha256 = "([0-9a-f]{64})"/)?.[1]; if (declared !== projSha) { fs.writeFileSync(TOWER_TCS, tcs.replace(/projection_sha256 = "[0-9a-f]{64}"/, `projection_sha256 = "${projSha}"`), "utf8"); updated.push("BROADCAST.tcs:projection_sha256"); const tc = JSON.parse(fs.readFileSync("/Volumes/JZAO/HoloLake/persona-runtime/toolchains/tcs-persona-developer-kit-macos-arm64-v0.1.3/translator/compiler-B.gir.json", "utf8")); note("NOTE BROADCAST.tcs changed — run Stage-1 compile to refresh GIR: tcs compile-with compiler-B.gir.json BROADCAST.tcs BROADCAST.declaration.gir.json"); } // 4) Hook entry embedded hashes (they stay embedded: they guard the hook chain itself). const lw = sha256(`${W}/BRIDGE/tools/lw-link-hook.sh`); const td = sha256(`${W}/BRIDGE/tools/tcs-dynamic-entry-hook.sh`); let entry = fs.readFileSync(ENTRY, "utf8"); const before = entry; entry = entry.replace(/LW_WANT="[0-9a-f]*"/, `LW_WANT="${lw}"`).replace(/TD_WANT="[0-9a-f]*"/, `TD_WANT="${td}"`); if (entry !== before) { fs.writeFileSync(ENTRY, entry, "utf8"); updated.push("zy-hook-entry.sh:embedded"); } idx.updated_at = new Date().toISOString(); if (updated.length) { idx.update_log = idx.update_log ?? []; idx.update_log.push(`reindex ${new Date().toISOString().slice(0, 16)} → ${updated.join(", ")}`); } fs.writeFileSync(IDX, JSON.stringify(idx, null, 2) + "\n"); note(`OK updated=${updated.length}${updated.length ? " → " + updated.join(", ") : " (已一致)"}`);