fix: unify and auto-refresh public navigation entry
This commit is contained in:
parent
2ba64391ea
commit
ea41e5a4fc
9 changed files with 573 additions and 61 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue