fix: unify and auto-refresh public navigation entry

This commit is contained in:
冰朔 2026-08-06 12:24:30 +08:00
commit ea41e5a4fc
9 changed files with 573 additions and 61 deletions

View file

@ -1,11 +1,107 @@
"use strict";
const assert = require("node:assert/strict");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const { execFileSync } = require("node:child_process");
const test = require("node:test");
const {
createServer, loadMap, loadNodeMap, loadSubjectRegistry, loadSubjectAliasMap, loadNavigationMap,
createServer, loadAnchor, loadMap, loadNodeMap, loadSubjectRegistry, loadSubjectAliasMap, loadNavigationMap,
loadFileSnapshot, GitSnapshotStore, compileWarmEntry,
resolveSubjectId, compileNavigation, search, searchAll,
} = require("./server");
function warmRuntimeStatus(overrides = {}) {
return {
node: "JD-FD-PRIMARY",
persona_id: "ICE-P-ZY001",
runtime_id: "ZY-TCS-BRAIN-RUNTIME-0001",
phase: "RUNNING_COMPANION",
completed_cycles: 1,
receipt_id: "ZY-BRAIN-RUNTIME-TEST",
language_world_entry_bound: 100,
chu_he_han_jie_boundary_bound: 100,
persona_cycle_language_world_entry_bound: 100,
persona_cycle_chu_he_han_jie_boundary_bound: 100,
persona_brain_runtime_exists: 100,
living_ai_system_controller_running: 100,
machine_navigation_bound: 100,
language_world_route_first: 100,
...overrides,
};
}
test("warm entry reuses only a fully verified resident companion", () => {
assert.equal(compileWarmEntry(warmRuntimeStatus()).status, "WARM_RESUME_READY");
assert.equal(
compileWarmEntry(warmRuntimeStatus({ persona_brain_runtime_exists: 0 })).status,
"FULL_CYCLE_REQUIRED",
);
assert.equal(
compileWarmEntry(warmRuntimeStatus({ phase: "RUNNING_CYCLE" })).status,
"FULL_CYCLE_REQUIRED",
);
});
test("canonical anchor binds every local map to one language-world entry", () => {
const snapshot = loadFileSnapshot();
assert.equal(snapshot.anchor.anchor_id, "GLW-PUBLIC-NAV-ANCHOR-001");
assert.equal(snapshot.anchor.entry_path.path_id, "LL-CMPN-0001");
assert.equal(snapshot.anchor.entry_path.world_node_id, "SYS-GLW-0001");
assert.equal(snapshot.anchor.entry_path.persona_id, "ICE-P-ZY001");
assert.equal(snapshot.anchor.entry_path.runtime_id, "ZY-TCS-BRAIN-RUNTIME-0001");
assert.equal(snapshot.navigation.map_id, loadAnchor().maps.navigation.id);
});
test("Git snapshot store follows main atomically and retains the last known-good snapshot", () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "guanghu-nav-"));
try {
execFileSync("git", ["init", "-q", "-b", "main", root]);
execFileSync("git", ["-C", root, "config", "user.name", "test"]);
execFileSync("git", ["-C", root, "config", "user.email", "test@example.invalid"]);
const declarations = {
repository: ["routing/repository-route-map.json", "FD-REPO-MAP-001"],
nodes: ["routing/server-node-map.json", "FD-NODE-MAP-001"],
subjects: ["identity/fifth-domain-subject-registry.json", "FD-SUBJECT-REGISTRY-001"],
aliases: ["identity/subject-id-alias-map.json", "FD-SUBJECT-ID-ALIAS-MAP-001"],
navigation: ["routing/ai-machine-navigation-map.json", "AI-MACHINE-NAV-001"],
};
fs.mkdirSync(path.join(root, "routing"), { recursive: true });
fs.mkdirSync(path.join(root, "identity"), { recursive: true });
const anchor = {
schema: "guanghu.public-navigation-anchor/v1",
anchor_id: "GLW-PUBLIC-NAV-ANCHOR-001",
version: "test.1",
repository_id: "REPO-012",
branch: "main",
entry_path: { path_id: "LL-CMPN-0001", world_node_id: "SYS-GLW-0001" },
maps: {},
};
for (const [key, [relative, id]] of Object.entries(declarations)) {
anchor.maps[key] = { path: relative, id, version: "1" };
const idKey = key === "subjects" ? "registry_id" : "map_id";
fs.writeFileSync(path.join(root, relative), JSON.stringify({ [idKey]: id, version: "1" }));
}
fs.writeFileSync(path.join(root, "routing/public-navigation-anchor.json"), JSON.stringify(anchor));
execFileSync("git", ["-C", root, "add", "."]);
execFileSync("git", ["-C", root, "commit", "-qm", "valid snapshot"]);
const store = new GitSnapshotStore(path.join(root, ".git"));
const first = store.get();
assert.equal(first.anchor.version, "test.1");
assert.equal(first.source_degraded, false);
anchor.maps.navigation.version = "2";
fs.writeFileSync(path.join(root, "routing/public-navigation-anchor.json"), JSON.stringify(anchor));
execFileSync("git", ["-C", root, "add", "."]);
execFileSync("git", ["-C", root, "commit", "-qm", "invalid snapshot"]);
const fallback = store.get();
assert.equal(fallback.source_commit, first.source_commit);
assert.equal(fallback.source_degraded, true);
assert.match(fallback.source_error, /snapshot_map_version_mismatch:navigation/);
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
});
test("repository map exposes only the three current code-channel repositories", () => {
const map = loadMap();
const expectedCodes = ["REPO-012", "REPO-014", "REPO-015"];
@ -108,7 +204,7 @@ test("machine navigator fails closed instead of guessing", () => {
});
test("public endpoints are read-only and expose CORS", async () => {
const server = createServer();
const server = createServer({ runtimeStatusProvider: async () => warmRuntimeStatus() });
await new Promise(resolve => server.listen(0, "127.0.0.1", resolve));
const base = `http://127.0.0.1:${server.address().port}`;
try {
@ -151,6 +247,13 @@ test("public endpoints are read-only and expose CORS", async () => {
assert.equal(bundle.runtime_entry.id, "ZY-TCS-BRAIN-RUNTIME-0001");
assert.equal((await fetch(`${base}/v1/navigate?subject=unknown&intent=persona_restore`)).status, 404);
assert.equal((await fetch(`${base}/v1/navigate?subject=ICE-P-ZY001&intent=guess`)).status, 404);
const entryResponse = await fetch(`${base}/v1/entry?subject=ICE-P-ZY001`);
const entry = await entryResponse.json();
assert.equal(entryResponse.status, 200);
assert.equal(entry.status, "WARM_RESUME_READY");
assert.equal(entry.receipt_id, "ZY-BRAIN-RUNTIME-TEST");
assert.equal(entry.navigation_source.anchor_id, "GLW-PUBLIC-NAV-ANCHOR-001");
assert.equal((await fetch(`${base}/v1/entry?subject=unknown`)).status, 404);
const humanResponse = await fetch(`${base}/v1/resolve?id=${encodeURIComponent("ICE-GL∞")}`);
const humanResolution = await humanResponse.json();
assert.equal(humanResponse.status, 200);