107 lines
5.8 KiB
Python
107 lines
5.8 KiB
Python
#!/usr/bin/env python3
|
|
import json
|
|
import pathlib
|
|
import sys
|
|
|
|
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
|
REPO = ROOT.parents[1]
|
|
errors = []
|
|
|
|
registry = json.loads((ROOT / "registries/module-registry.json").read_text())
|
|
ids = [m["module_id"] for m in registry["modules"]]
|
|
if len(ids) != len(set(ids)):
|
|
errors.append("duplicate module id")
|
|
|
|
required_sources = {
|
|
"USER_MESSAGE", "PERSONA_RESPONSE", "EXTERNAL_AI_MESSAGE", "SYSTEM_CONTEXT", "PROTOCOL_EVENT",
|
|
"AGENT_ACTION", "TOOL_RESULT", "SYSTEM_RECEIPT",
|
|
}
|
|
types = (ROOT / "src/types.ts").read_text()
|
|
missing = sorted(x for x in required_sources if f'"{x}"' not in types)
|
|
if missing:
|
|
errors.append(f"missing source kinds: {missing}")
|
|
|
|
package = json.loads((ROOT / "package.json").read_text())
|
|
for forbidden in ("openai", "anthropic", "@google/generative-ai", "langchain"):
|
|
if forbidden in package.get("dependencies", {}):
|
|
errors.append(f"internal model dependency forbidden: {forbidden}")
|
|
for required in ("marked", "dompurify"):
|
|
if required not in package.get("dependencies", {}):
|
|
errors.append(f"knowledge human renderer dependency missing: {required}")
|
|
renderer = ROOT / "src/modules/knowledge-render/index.tsx"
|
|
if not renderer.exists() or "MarkdownDocument" not in renderer.read_text():
|
|
errors.append("knowledge human visual renderer missing")
|
|
for required_file in (
|
|
"src-tauri/src/agent_executor.rs",
|
|
"src-tauri/src/persona_runtime.rs",
|
|
"src-tauri/src/realtime_bridge.rs",
|
|
"src-tauri/src/enterprise_entrance.rs",
|
|
"connectors/hololake-glp-client.py",
|
|
"contracts/public-runtime-v1.json",
|
|
"contracts/clean-v1-execution-baseline.json",
|
|
"contracts/enterprise-responsibility-entrance-v1.json",
|
|
"language/HOLOLAKE-CLEAN-V1-DIRECT-LANGUAGE-EXECUTION-BASELINE.tcs",
|
|
"server/enterprise-responsibility-gate/service.py",
|
|
"server/enterprise-responsibility-gate/test_service.py",
|
|
"server/enterprise-responsibility-gate/guanghu-hololake-enterprise-gate.service",
|
|
"server/enterprise-responsibility-gate/nginx.conf",
|
|
):
|
|
if not (ROOT / required_file).exists():
|
|
errors.append(f"public runtime file missing: {required_file}")
|
|
runtime_contract = json.loads((ROOT / "contracts/public-runtime-v1.json").read_text())
|
|
if runtime_contract["transport"]["bind"] != "127.0.0.1":
|
|
errors.append("realtime bridge is not loopback-only")
|
|
if runtime_contract["mutation_gate"] != "PENDING_HUMAN_APPROVAL_TO_EXPLICIT_UI_APPROVAL_TO_EXECUTION":
|
|
errors.append("agent human approval gate missing")
|
|
if "system_context" not in runtime_contract.get("server_messages", []):
|
|
errors.append("persona-visible system context missing from GLP contract")
|
|
realtime_source = (ROOT / "src-tauri/src/realtime_bridge.rs").read_text()
|
|
for required_context in ("sourceKinds", "pendingAgentProposals", "enterpriseEntrance", "proposalIsNotExecution"):
|
|
if required_context not in realtime_source:
|
|
errors.append(f"persona-visible system context field missing: {required_context}")
|
|
baseline = json.loads((ROOT / "contracts/clean-v1-execution-baseline.json").read_text())
|
|
if baseline.get("anchor_manifest_sha256") != "7e130de78f91a32726e22e4be7d92acf4da966c8968ec359062aa8186c4243c2":
|
|
errors.append("current direct-language anchor manifest drift")
|
|
if baseline.get("public_raw_language_embedded") is not False:
|
|
errors.append("raw private direct language embedded in public baseline")
|
|
enterprise = json.loads((ROOT / "contracts/enterprise-responsibility-entrance-v1.json").read_text())
|
|
if enterprise.get("enterprise_server_embedded") is not False:
|
|
errors.append("enterprise server embedded in HoloLake")
|
|
if enterprise.get("device_proof", {}).get("fingerprint_is_sole_credential") is not False:
|
|
errors.append("machine fingerprint incorrectly used as sole credential")
|
|
if enterprise.get("session", {}).get("scope") != "ONE_DOMAIN_ONE_REPOSITORY":
|
|
errors.append("enterprise session is not responsibility scoped")
|
|
if enterprise.get("state") != "LOCAL_DEVICE_PROOF_INSTALLED_KEYCHAIN_VERIFIED_SERVER_GATE_SOURCE_TESTED_DEPLOYMENT_PENDING":
|
|
errors.append("enterprise local device proof implementation state drift")
|
|
time_source = (ROOT / "src/time.ts").read_text()
|
|
app_source = (ROOT / "src/App.tsx").read_text()
|
|
if "legacyUnixSeconds" not in time_source or "时间待校验" not in time_source:
|
|
errors.append("legacy timestamp compatibility missing")
|
|
if "new Date(e.occurredAt)" in app_source:
|
|
errors.append("unvalidated timeline timestamp rendering remains")
|
|
|
|
tauri = json.loads((ROOT / "src-tauri/tauri.conf.json").read_text())
|
|
endpoints = tauri["plugins"]["updater"]["endpoints"]
|
|
if endpoints != ["https://guanghulab.com/hololake/releases/latest.json"]:
|
|
errors.append("update endpoint drift")
|
|
if not tauri["plugins"]["updater"].get("pubkey"):
|
|
errors.append("update signature trust missing")
|
|
|
|
architecture = json.loads((REPO / "routing/hololake-current-architecture.json").read_text())
|
|
clean = architecture.get("clean_v1_rebuild", {})
|
|
if clean.get("source") != "product-source/hololake-clean-desktop":
|
|
errors.append("current architecture does not point to clean V1")
|
|
if clean.get("enterprise_four_domains_embedded") is not False:
|
|
errors.append("enterprise domains embedded in personal product")
|
|
if clean.get("fifth_domain_private_content_embedded") is not False:
|
|
errors.append("Fifth Domain private content embedded in public product")
|
|
assessment = architecture.get("current_product_assessment", {})
|
|
if assessment.get("desktop_artifact_version") != "1.2.0":
|
|
errors.append("current product assessment version drift")
|
|
if assessment.get("canonical_public_source_repository") != "REPO-014":
|
|
errors.append("canonical public source repository unresolved")
|
|
|
|
if errors:
|
|
print(json.dumps({"result": "FAIL_0", "errors": errors}, ensure_ascii=False, indent=2))
|
|
sys.exit(1)
|
|
print(json.dumps({"result": "PASS_100", "module_ids": ids, "source_kinds": sorted(required_sources)}, ensure_ascii=False, indent=2))
|