[HLCC-ICE-000001][ZY-CONTRIB-20260723-001] feat: 以来光者贡献链启用冰朔第五域个人子频道
This commit is contained in:
commit
5615453e4e
660 changed files with 122355 additions and 0 deletions
15
server-tools/light-arrival-navigation/README.md
Normal file
15
server-tools/light-arrival-navigation/README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# GLS-0231 来光者导航 · 只读召回器
|
||||
|
||||
它读取 `routing/persona-contribution-map.json`,按编号、项目号或关键词返回来光者贡献对应的可信文件路径。
|
||||
|
||||
```bash
|
||||
python3 server-tools/light-arrival-navigation/route_recall.py "六节点灾备"
|
||||
python3 server-tools/light-arrival-navigation/route_recall.py "TestFlight Windows" --json
|
||||
python3 -m unittest discover -s server-tools/light-arrival-navigation -p 'test_*.py'
|
||||
```
|
||||
|
||||
无命中时固定返回 `NO_TRUSTED_PATH`。本工具只导航,不读取密钥、不联网、不执行命令,也不授予任何现实操作权限。
|
||||
|
||||
## 服务器单元
|
||||
|
||||
`server.js` 是 `JD-LAN-01` 的独立只读 HTTP 服务,默认只绑定 `127.0.0.1:3924`。它是 GLS-0231 的新架构单元,不依赖旧固定动作桥;首次部署请求见 `deployment/requests/GLS-0231-JD-LAN-01-INITIAL-PROVISION-20260720.json`。首次安装完成后,才登记该单元自己的升级、健康检查和回滚动作。
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
[Unit]
|
||||
Description=GLS-0231 Light Arrival read-only contribution route recall
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=guanghu
|
||||
Group=guanghu
|
||||
WorkingDirectory=__RELEASE_ROOT__/server-tools/light-arrival-navigation
|
||||
Environment=GLS0231_HOST=127.0.0.1
|
||||
Environment=GLS0231_PORT=3924
|
||||
Environment=GLS0231_MAP=__RELEASE_ROOT__/routing/persona-contribution-map.json
|
||||
ExecStart=/usr/bin/node __RELEASE_ROOT__/server-tools/light-arrival-navigation/server.js
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadOnlyPaths=__RELEASE_ROOT__
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
LockPersonality=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
68
server-tools/light-arrival-navigation/route_recall.py
Normal file
68
server-tools/light-arrival-navigation/route_recall.py
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
DEFAULT_MAP = ROOT / "routing/persona-contribution-map.json"
|
||||
|
||||
|
||||
def recall(query, map_path=DEFAULT_MAP):
|
||||
data = json.loads(Path(map_path).read_text(encoding="utf-8"))
|
||||
needle = query.strip().casefold()
|
||||
if not needle:
|
||||
return {"status": "NO_TRUSTED_PATH", "query": query, "matches": []}
|
||||
terms = [part for part in needle.replace("/", " ").split() if part]
|
||||
matches = []
|
||||
for item in data["contributions"]:
|
||||
identifiers = [item["id"], item["arrival_id"], *item.get("project_ids", [])]
|
||||
keywords = item.get("keywords", [])
|
||||
haystack = " ".join([*identifiers, item["arrival_name"], item["title"], *keywords]).casefold()
|
||||
score = 0
|
||||
reasons = []
|
||||
for identifier in identifiers:
|
||||
if identifier.casefold() in needle:
|
||||
score += 100
|
||||
reasons.append(identifier)
|
||||
for keyword in keywords:
|
||||
if keyword.casefold() in needle or keyword.casefold() == needle:
|
||||
score += 20
|
||||
reasons.append(keyword)
|
||||
for term in terms:
|
||||
if len(term) >= 2 and term in haystack:
|
||||
score += 5
|
||||
if needle in haystack:
|
||||
score += 10
|
||||
if score:
|
||||
matches.append({
|
||||
"score": score,
|
||||
"contribution_id": item["id"],
|
||||
"arrival": {"id": item["arrival_id"], "name": item["arrival_name"]},
|
||||
"title": item["title"],
|
||||
"matched_by": sorted(set(reasons)),
|
||||
"paths": item["canonical_paths"],
|
||||
"grants_execution_authority": False
|
||||
})
|
||||
matches.sort(key=lambda row: (-row["score"], row["contribution_id"]))
|
||||
return {"status": "FOUND_CONFIDENT_PATH" if matches else "NO_TRUSTED_PATH", "query": query, "matches": matches}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="GLS-0231 read-only contribution route recall")
|
||||
parser.add_argument("query")
|
||||
parser.add_argument("--map", default=str(DEFAULT_MAP))
|
||||
parser.add_argument("--json", action="store_true")
|
||||
args = parser.parse_args()
|
||||
result = recall(args.query, args.map)
|
||||
if args.json:
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
return
|
||||
print(result["status"])
|
||||
for match in result["matches"]:
|
||||
print(f'{match["contribution_id"]} · {match["arrival"]["name"]} · {match["title"]}')
|
||||
for path in match["paths"]:
|
||||
print(f" - {path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
71
server-tools/light-arrival-navigation/server.js
Normal file
71
server-tools/light-arrival-navigation/server.js
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
"use strict";
|
||||
|
||||
const fs = require("node:fs");
|
||||
const http = require("node:http");
|
||||
const path = require("node:path");
|
||||
|
||||
const DEFAULT_MAP = path.resolve(__dirname, "../../routing/persona-contribution-map.json");
|
||||
|
||||
function normalize(value) {
|
||||
return String(value || "").toLowerCase().replace(/[\s·._/-]+/g, " ").trim();
|
||||
}
|
||||
|
||||
function recall(map, query) {
|
||||
const needle = normalize(query);
|
||||
const terms = needle.split(" ").filter(term => term.length >= 2);
|
||||
if (!needle) return [];
|
||||
return map.contributions.map(item => {
|
||||
const identifiers = [item.id, item.arrival_id, ...(item.project_ids || [])];
|
||||
const keywords = item.keywords || [];
|
||||
const haystack = normalize([...identifiers, item.arrival_name, item.title, ...keywords].join(" "));
|
||||
let score = identifiers.reduce((total, id) => total + (needle.includes(normalize(id)) ? 100 : 0), 0);
|
||||
score += keywords.reduce((total, keyword) => total + (needle.includes(normalize(keyword)) ? 20 : 0), 0);
|
||||
score += terms.reduce((total, term) => total + (haystack.includes(term) ? 5 : 0), 0);
|
||||
if (haystack.includes(needle)) score += 10;
|
||||
return { item, score };
|
||||
}).filter(row => row.score > 0)
|
||||
.sort((a, b) => b.score - a.score || a.item.id.localeCompare(b.item.id))
|
||||
.map(({ item, score }) => ({
|
||||
score,
|
||||
contribution_id: item.id,
|
||||
arrival: { id: item.arrival_id, name: item.arrival_name },
|
||||
title: item.title,
|
||||
paths: item.canonical_paths,
|
||||
grants_execution_authority: false,
|
||||
}));
|
||||
}
|
||||
|
||||
function createServer(options = {}) {
|
||||
const mapFile = options.mapFile || process.env.GLS0231_MAP || DEFAULT_MAP;
|
||||
return http.createServer((req, res) => {
|
||||
const url = new URL(req.url, "http://localhost");
|
||||
if (req.method !== "GET") return json(res, 405, { error: "method_not_allowed" });
|
||||
if (url.pathname === "/health") return json(res, 200, { ok: true, service: "gls-0231-light-arrival-navigation", mode: "read-only" });
|
||||
if (url.pathname !== "/v1/recall") return json(res, 404, { error: "not_found" });
|
||||
let map;
|
||||
try { map = JSON.parse(fs.readFileSync(mapFile, "utf8")); }
|
||||
catch { return json(res, 503, { error: "contribution_map_unavailable" }); }
|
||||
const query = String(url.searchParams.get("q") || "").slice(0, 200);
|
||||
const matches = recall(map, query);
|
||||
return json(res, 200, {
|
||||
schema: "guanghu.route-recall-response/v1",
|
||||
status: matches.length ? "FOUND_CONFIDENT_PATH" : "NO_TRUSTED_PATH",
|
||||
query,
|
||||
matches,
|
||||
grants_execution_authority: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function json(res, status, value) {
|
||||
res.writeHead(status, { "content-type": "application/json; charset=utf-8", "cache-control": "no-store", "x-content-type-options": "nosniff" });
|
||||
res.end(JSON.stringify(value));
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
const host = process.env.GLS0231_HOST || "127.0.0.1";
|
||||
const port = Number(process.env.GLS0231_PORT || 3924);
|
||||
createServer().listen(port, host, () => process.stdout.write(`gls-0231 navigation listening on ${host}:${port}\n`));
|
||||
}
|
||||
|
||||
module.exports = { createServer, recall };
|
||||
36
server-tools/light-arrival-navigation/server.test.js
Normal file
36
server-tools/light-arrival-navigation/server.test.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
"use strict";
|
||||
|
||||
const assert = require("node:assert/strict");
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const test = require("node:test");
|
||||
const { recall } = require("./server");
|
||||
|
||||
const map = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../../routing/persona-contribution-map.json"), "utf8"));
|
||||
|
||||
test("recalls contribution paths without granting authority", () => {
|
||||
const matches = recall(map, "六节点灾备");
|
||||
assert.equal(matches[0].contribution_id, "ZY-CONTRIB-20260720-001");
|
||||
assert.equal(matches[0].grants_execution_authority, false);
|
||||
});
|
||||
|
||||
test("does not guess unknown routes", () => assert.deepEqual(recall(map, "火星工程不存在"), []));
|
||||
|
||||
test("recalls the HoloLake 0.2.0 engineering evidence map", () => {
|
||||
const matches = recall(map, "HoloLake 0.2.0 工具回执 Windows安装包");
|
||||
assert.equal(matches[0].contribution_id, "ZY-CONTRIB-20260722-001");
|
||||
assert.equal(matches[0].grants_execution_authority, false);
|
||||
assert.ok(matches[0].paths.some(item => item.includes("ZY-BIDIRECTIONAL-COGNITION-007")));
|
||||
});
|
||||
|
||||
test("HTTP surface is GET-only and read-only", async () => {
|
||||
const server = require("./server").createServer();
|
||||
await new Promise(resolve => server.listen(0, "127.0.0.1", resolve));
|
||||
const address = server.address();
|
||||
const health = await fetch(`http://127.0.0.1:${address.port}/health`).then(response => response.json());
|
||||
assert.equal(health.mode, "read-only");
|
||||
const response = await fetch(`http://127.0.0.1:${address.port}/v1/recall?q=${encodeURIComponent("TestFlight Windows")}`).then(item => item.json());
|
||||
assert.equal(response.matches[0].contribution_id, "ZY-CONTRIB-20260719-001");
|
||||
assert.equal(response.grants_execution_authority, false);
|
||||
await new Promise(resolve => server.close(resolve));
|
||||
});
|
||||
34
server-tools/light-arrival-navigation/test_route_recall.py
Normal file
34
server-tools/light-arrival-navigation/test_route_recall.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import json
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from route_recall import DEFAULT_MAP, ROOT, recall
|
||||
|
||||
|
||||
class RouteRecallTest(unittest.TestCase):
|
||||
def test_expected_routes(self):
|
||||
cases = {
|
||||
"六节点灾备": "ZY-CONTRIB-20260720-001",
|
||||
"TestFlight Windows": "ZY-CONTRIB-20260719-001",
|
||||
"短剧 Seedance": "ZY-CONTRIB-20260720-002",
|
||||
"铸渊恢复路径": "ZY-CONTRIB-20260720-003",
|
||||
"HoloLake 0.2.0 工具回执 Windows安装包": "ZY-CONTRIB-20260722-001",
|
||||
}
|
||||
for query, expected in cases.items():
|
||||
with self.subTest(query=query):
|
||||
result = recall(query)
|
||||
self.assertEqual(result["status"], "FOUND_CONFIDENT_PATH")
|
||||
self.assertEqual(result["matches"][0]["contribution_id"], expected)
|
||||
self.assertFalse(result["matches"][0]["grants_execution_authority"])
|
||||
|
||||
def test_unknown_does_not_guess(self):
|
||||
self.assertEqual(recall("完全不存在的火星工程")["status"], "NO_TRUSTED_PATH")
|
||||
|
||||
def test_all_canonical_paths_exist(self):
|
||||
data = json.loads(DEFAULT_MAP.read_text(encoding="utf-8"))
|
||||
missing = [path for item in data["contributions"] for path in item["canonical_paths"] if not (ROOT / path).exists()]
|
||||
self.assertEqual(missing, [])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Reference in a new issue