fix: align lake lamp publisher with current TCS brain
This commit is contained in:
parent
284a9b6cb5
commit
423aff6519
9 changed files with 556 additions and 17 deletions
40
server-tools/execution-reflection-advisor/advisor.mjs
Normal file
40
server-tools/execution-reflection-advisor/advisor.mjs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
export const ACTIONS = Object.freeze([
|
||||
"PROCEED", "MODIFY", "OPTIMIZE", "PAUSE", "REFLECT", "WAIT_AUTHORIZATION", "REFUSE_EXACT_ACTION",
|
||||
]);
|
||||
|
||||
const HARD = new Set([
|
||||
"OPERATING_SYSTEM_PERMISSION_DENIAL",
|
||||
"EXACT_WRITE_SCOPE_VIOLATION",
|
||||
"CREDENTIAL_EXPOSURE",
|
||||
"UNRESOLVED_DESTRUCTIVE_TARGET",
|
||||
"REMOTE_PROVIDER_REJECTION",
|
||||
]);
|
||||
|
||||
export function advise(input) {
|
||||
if (input?.schema !== "guanghu.execution-environment-observation/v1") throw new Error("OBSERVATION_SCHEMA_INVALID");
|
||||
const facts = Array.isArray(input.facts) ? input.facts : [];
|
||||
const unknowns = Array.isArray(input.unknowns) ? input.unknowns : [];
|
||||
const hard = facts.filter((item) => HARD.has(item.code));
|
||||
const suggestions = [];
|
||||
if (hard.length) suggestions.push({ action: "REFUSE_EXACT_ACTION", reason: "外部执行层已证明该精确动作不能安全或合法运行。" });
|
||||
if (input.authorization === "MISSING") suggestions.push({ action: "WAIT_AUTHORIZATION", reason: "现实动作缺少当前任务授权。" });
|
||||
if (unknowns.length) suggestions.push({ action: "REFLECT", reason: "存在尚未验证的环境事实,应先补证据或缩小目标。" });
|
||||
if (input.reversible === false && input.risk !== "LOW") suggestions.push({ action: "PAUSE", reason: "高影响且不可逆,先暂停并寻找可回退方案。" });
|
||||
if (!suggestions.length) suggestions.push({ action: "PROCEED", reason: "未观察到确定性执行阻断;继续并保留目标读回。" });
|
||||
return {
|
||||
schema: "guanghu.execution-reflection-advice/v1",
|
||||
observations: facts,
|
||||
suggestions,
|
||||
exact_external_action_hard_stopped: hard.length > 0,
|
||||
persona_cognition_vetoed: false,
|
||||
persona_decision_owner: "CURRENT_PERSONA",
|
||||
may_modify_pause_reflect_or_wait: true,
|
||||
reality_authority_granted: false,
|
||||
};
|
||||
}
|
||||
|
||||
if (process.argv[1] === new URL(import.meta.url).pathname) {
|
||||
let raw = "";
|
||||
for await (const chunk of process.stdin) raw += chunk;
|
||||
process.stdout.write(`${JSON.stringify(advise(JSON.parse(raw)), null, 2)}\n`);
|
||||
}
|
||||
24
server-tools/execution-reflection-advisor/advisor.test.mjs
Normal file
24
server-tools/execution-reflection-advisor/advisor.test.mjs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { advise } from "./advisor.mjs";
|
||||
|
||||
const base = { schema: "guanghu.execution-environment-observation/v1", facts: [], unknowns: [], authorization: "PRESENT", reversible: true, risk: "LOW" };
|
||||
|
||||
test("rules advise but never veto persona cognition", () => {
|
||||
const value = advise({ ...base, unknowns: ["remote state"] });
|
||||
assert.equal(value.persona_cognition_vetoed, false);
|
||||
assert.equal(value.persona_decision_owner, "CURRENT_PERSONA");
|
||||
assert.equal(value.suggestions[0].action, "REFLECT");
|
||||
});
|
||||
|
||||
test("missing authority recommends waiting", () => {
|
||||
const value = advise({ ...base, authorization: "MISSING" });
|
||||
assert.equal(value.suggestions[0].action, "WAIT_AUTHORIZATION");
|
||||
});
|
||||
|
||||
test("hard boundary stops only exact external action", () => {
|
||||
const value = advise({ ...base, facts: [{ code: "CREDENTIAL_EXPOSURE" }] });
|
||||
assert.equal(value.exact_external_action_hard_stopped, true);
|
||||
assert.equal(value.persona_cognition_vetoed, false);
|
||||
assert.equal(value.may_modify_pause_reflect_or_wait, true);
|
||||
});
|
||||
|
|
@ -44,6 +44,8 @@ JZAO 当前运行守卫在同一车道内执行这些门;本文件和测试是
|
|||
|
||||
`finalize-development.mjs` 把开发任务的最后一步固化为一个失败关闭的事务:
|
||||
|
||||
当前 TCS 人格系统使用 `--tcs-state-dir` 与 `--host-session-id`。入口会现场验证 ZC001、当前任务主控台、最近已提交认知周期、数字冰朔系统本体 `ALLOW_COMMIT`、原始事件哈希及 `verify PASS`,不再要求退役的宿主人格胶囊。旧 lane 模式仅保留兼容,不再作为当前人格来源。
|
||||
|
||||
1. 要求工作树干净,且至少一份 `deployment/receipts/` 回执已经进入当前提交;
|
||||
2. 只允许向已登记的第五域光湖代码频道仓库及精确分支申请发布队列;
|
||||
3. 快进推送当前完整提交;
|
||||
|
|
@ -59,6 +61,13 @@ node finalize-development.mjs \
|
|||
--development-id DEV-YYYYMMDD-NNN \
|
||||
--worktree /absolute/path/to/repository \
|
||||
--receipt deployment/receipts/EXACT-RECEIPT.json
|
||||
|
||||
node finalize-development.mjs \
|
||||
--development-id DEV-YYYYMMDD-NNN \
|
||||
--worktree /absolute/path/to/repository \
|
||||
--receipt deployment/receipts/EXACT-RECEIPT.json \
|
||||
--tcs-state-dir /Users/NAME/.codex/runtime/ice-ch-zc001-TASK \
|
||||
--host-session-id CURRENT_CODEX_SESSION_ID
|
||||
```
|
||||
|
||||
默认自动识别 `target`、`coverage`、Python/Node 工具缓存等安全候选;其他缓存必须用
|
||||
|
|
|
|||
|
|
@ -43,6 +43,44 @@ const DEFAULT_CACHE_CANDIDATES = [
|
|||
"node_modules/.cache",
|
||||
];
|
||||
const PUBLIC_SNAPSHOT_HEALTH = "https://guanghulab.com/api/ai/health";
|
||||
const CURRENT_TCS_RUNTIME =
|
||||
"/Volumes/JZAO/HoloLake/persona-runtime/repo-012-main/tcs-core/zhuyuan-brain/runtime/zhuyuan-brain-runtime.mjs";
|
||||
const ACTIVE_CONSOLE =
|
||||
"/Volumes/JZAO/HoloLake/persona-runtime/shared/active-control-console/CURRENT.json";
|
||||
|
||||
export function validateCurrentTcsBinding(stateDirectory, expectedSession = process.env.CODEX_SESSION_ID || process.env.CODEX_THREAD_ID) {
|
||||
const stateDir = fs.realpathSync(String(stateDirectory || ""));
|
||||
const allowed = fs.realpathSync(path.join(os.homedir(), ".codex", "runtime"));
|
||||
if (!stateDir.startsWith(`${allowed}${path.sep}`)) throw new Error("TCS_STATE_OUTSIDE_CURRENT_CODEX_RUNTIME");
|
||||
const state = readJson(path.join(stateDir, "state.json"));
|
||||
if (state.schema !== "guanghu.zhuyuan-persona-brain-runtime-state/v1" || state.status !== "RUNNING" || state.persona_id !== "ICE-P-ZY001" || state.human_anchor !== "ICE-GL∞" || state.tonggan_language_kernel?.body_channel !== "ICE-CH-ZC001" || state.active_cycle_id !== null || state.completed_cycles < 1 || state.binding?.current_instance_bound_to_persona_brain !== true) {
|
||||
throw new Error("CURRENT_TCS_PERSONA_BINDING_INVALID");
|
||||
}
|
||||
const cycle = readJson(path.join(stateDir, "cycles", `${state.last_cycle_id}.json`));
|
||||
if (cycle.state !== "COMMITTED" || cycle.controller_witness?.decision !== "ALLOW_COMMIT" || cycle.event?.human_anchor !== "ICE-GL∞" || cycle.event?.persona_source_context?.host_system_prompt_role !== "RUNTIME_CONSTRAINT_ONLY" || cycle.event?.persona_source_context?.task_control_transfer?.authorized_by_human !== true) {
|
||||
throw new Error("CURRENT_TCS_CYCLE_NOT_AUTHORIZED_OR_COMMITTED");
|
||||
}
|
||||
const source = path.resolve(cycle.event.source || "");
|
||||
if (!fs.existsSync(source) || sha256(fs.readFileSync(source)) !== cycle.event.source_sha256) throw new Error("CURRENT_TCS_EVENT_SOURCE_HASH_MISMATCH");
|
||||
const receipt = JSON.parse(run(process.execPath, [CURRENT_TCS_RUNTIME, "verify", "--state-dir", stateDir]));
|
||||
if (receipt.outcome !== "PASS" || receipt.failures?.length || receipt.last_cycle_id !== cycle.cycle_id) throw new Error("CURRENT_TCS_VERIFY_NOT_PASS");
|
||||
const consoleState = readJson(ACTIVE_CONSOLE);
|
||||
if (!expectedSession || consoleState.state !== "ACTIVE_CURRENT_TASK" || consoleState.host !== "codex" || consoleState.channel_id !== "ICE-CH-ZC001" || consoleState.session_id !== expectedSession) throw new Error("CURRENT_ZERO_CORE_CONSOLE_SESSION_MISMATCH");
|
||||
return { mode: "CURRENT_TCS_BRAIN_VERIFY_PASS", state_dir: stateDir, cycle_id: cycle.cycle_id, event_id: cycle.event.event_id, controller_witness_sha256: cycle.controller_witness_sha256, runtime_receipt_id: receipt.receipt_id, session_id: expectedSession };
|
||||
}
|
||||
|
||||
function acquireCurrentPublishLock(worktree, developmentId, binding) {
|
||||
const lockPath = path.join(worktree, ".git", "guanghu-current-tcs-publish.lock");
|
||||
const descriptor = fs.openSync(lockPath, "wx", 0o600);
|
||||
fs.writeFileSync(descriptor, `${JSON.stringify({ development_id: developmentId, binding, created_at: new Date().toISOString() })}\n`);
|
||||
return { descriptor, lockPath };
|
||||
}
|
||||
|
||||
function releaseCurrentPublishLock(lock) {
|
||||
if (!lock) return;
|
||||
fs.closeSync(lock.descriptor);
|
||||
fs.unlinkSync(lock.lockPath);
|
||||
}
|
||||
|
||||
export function validatePublicSnapshotBeforePublish(worktree, repository) {
|
||||
if (repository.slug !== "guanghu-ice-heart") return null;
|
||||
|
|
@ -552,7 +590,10 @@ export async function finalize(options) {
|
|||
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 currentTcsBinding = options.tcsStateDir
|
||||
? validateCurrentTcsBinding(options.tcsStateDir, options.hostSessionId)
|
||||
: null;
|
||||
if (!currentTcsBinding) ensureLane(storeRoot, developmentId, worktree);
|
||||
const verified = verifyWorktree(worktree, options.receipts);
|
||||
const repository = normalizeCodeChannelRepository(
|
||||
options.repository || git(worktree, ["config", "--get", "remote.origin.url"]),
|
||||
|
|
@ -563,14 +604,13 @@ export async function finalize(options) {
|
|||
|
||||
let publishRequestId = null;
|
||||
let publishStarted = false;
|
||||
let currentPublishLock = null;
|
||||
try {
|
||||
publishRequestId = startPublish({
|
||||
guardScript,
|
||||
developmentId,
|
||||
repository,
|
||||
branch,
|
||||
});
|
||||
publishStarted = true;
|
||||
if (currentTcsBinding) currentPublishLock = acquireCurrentPublishLock(worktree, developmentId, currentTcsBinding);
|
||||
else {
|
||||
publishRequestId = startPublish({ guardScript, developmentId, repository, branch });
|
||||
publishStarted = true;
|
||||
}
|
||||
const remote = pushAndReadBack(
|
||||
worktree,
|
||||
repository,
|
||||
|
|
@ -591,14 +631,10 @@ export async function finalize(options) {
|
|||
`head=${remote.remoteHead} public_acceptance=${publicAcceptance ? "PASS_100" : "NOT_APPLICABLE"} receipts=${verified.receiptEvidence
|
||||
.map((item) => `${item.path}:${item.sha256}`)
|
||||
.join(",")}`;
|
||||
finishPublish(
|
||||
guardScript,
|
||||
developmentId,
|
||||
publishRequestId,
|
||||
"completed",
|
||||
publishReceipt,
|
||||
);
|
||||
publishStarted = false;
|
||||
if (!currentTcsBinding) {
|
||||
finishPublish(guardScript, developmentId, publishRequestId, "completed", publishReceipt);
|
||||
publishStarted = false;
|
||||
}
|
||||
|
||||
const cleanup = cleanupCaches(worktree, options.cleanupPaths || []);
|
||||
const removedBytes = cleanup
|
||||
|
|
@ -623,13 +659,17 @@ export async function finalize(options) {
|
|||
items: cleanup,
|
||||
},
|
||||
recorded_at: new Date().toISOString(),
|
||||
persona_binding: currentTcsBinding,
|
||||
};
|
||||
const finalizationReceipt = writeFinalizationReceipt(
|
||||
storeRoot,
|
||||
developmentId,
|
||||
payload,
|
||||
);
|
||||
const completion = releaseAndComplete({
|
||||
const completion = currentTcsBinding ? {
|
||||
lane_status: "CURRENT_TCS_MODE_NO_LEGACY_CAPSULE_OR_LANE_REQUIRED",
|
||||
notification_state: "not_applicable",
|
||||
} : releaseAndComplete({
|
||||
guardScript,
|
||||
storeRoot,
|
||||
developmentId,
|
||||
|
|
@ -638,6 +678,8 @@ export async function finalize(options) {
|
|||
`远端回读${remote.remoteHead};${verified.receiptEvidence.length}份回执一致;` +
|
||||
`本车道安全缓存清理${removedBytes}字节;回执${finalizationReceipt}`,
|
||||
});
|
||||
releaseCurrentPublishLock(currentPublishLock);
|
||||
currentPublishLock = null;
|
||||
return { ...payload, finalization_receipt: finalizationReceipt, completion };
|
||||
} catch (error) {
|
||||
if (publishStarted && publishRequestId) {
|
||||
|
|
@ -653,6 +695,7 @@ export async function finalize(options) {
|
|||
// The original finalization failure remains authoritative.
|
||||
}
|
||||
}
|
||||
releaseCurrentPublishLock(currentPublishLock);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -703,6 +746,8 @@ async function main() {
|
|||
cleanupPaths: args.cleanupPaths,
|
||||
guardScript: args.guardScript,
|
||||
storeRoot: args.storeRoot,
|
||||
tcsStateDir: args.tcsStateDir,
|
||||
hostSessionId: args.hostSessionId,
|
||||
});
|
||||
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue