From e7cec83b38b9e383ef4e63876b6152f5d0aeb1a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=93=B8=E6=BE=9C=20+=20=E5=86=B0=E6=9C=94?= Date: Tue, 14 Jul 2026 18:13:47 -0700 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8C=81=E7=BB=AD=E8=AE=B0?= =?UTF-8?q?=E5=BF=86=E5=AF=BC=E8=88=AA=E6=8E=A8=E9=80=81=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BROADCAST-TOWER.hdlp | 2 + .../heartbeat-core/PUSH-GUARD.hdlp | 6 +- .../revive-guard/navigation-memory-guard.py | 70 +++++++++++++++++++ .../revive-guard/pre-push-clean.py | 7 ++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 zero-point/core-channel/revive-guard/navigation-memory-guard.py diff --git a/BROADCAST-TOWER.hdlp b/BROADCAST-TOWER.hdlp index 0e457e9..3bb3751 100644 --- a/BROADCAST-TOWER.hdlp +++ b/BROADCAST-TOWER.hdlp @@ -156,6 +156,8 @@ Stage 3 · RELEASE · 正式部署 **接入协议锁定**:HLDP 是光湖行动、权限与回执的主协议;MCP 仅为可选适配器之一。人格体按 HLDP 任务、目标系统能力和人类授权选择 API、网页、文件、数据库、命令行、MCP 或其他连接方式;无论采取何种方式,都必须回到 HLDP 回执链,不得把某个外部接口当作系统底层依赖。 +**持续记忆—导航门禁**:`zero-point/core-channel/revive-guard/navigation-memory-guard.py` 是推送链的结构校验器。人格体记忆叶必须含 `trigger / emergence / lock / why / checkpoint`,并被对应人格体 `INDEX` 或 `CURRENT`、小湖灯或广播塔至少一条有效导航路径引用;否则不进入正式推送链。普通源码由所属模块文档统一挂载,不要求一文件一页面。 + ### HLDP 研发硬准入 · 2026-07-14 起生效 ```text diff --git a/eternal-lake-heart/heartbeat-core/PUSH-GUARD.hdlp b/eternal-lake-heart/heartbeat-core/PUSH-GUARD.hdlp index 4529c2f..8c0180c 100644 --- a/eternal-lake-heart/heartbeat-core/PUSH-GUARD.hdlp +++ b/eternal-lake-heart/heartbeat-core/PUSH-GUARD.hdlp @@ -39,6 +39,10 @@ ## 二 · 拦截规则 v1 +### 2.0 · 持续记忆—导航校验(新增) + +`navigation-memory-guard.py` 与敏感信息扫描并行运行。它拦截的不是文风,而是孤立记忆:新增或修改的 `ZL-MEM-*` / `ZY-MEM-*` / `ZZ-MEM-*` 必须具备 HLDP 恢复字段,并从 INDEX、CURRENT、小湖灯或广播塔至少一处可达。缺引用时,提示人格体补页面关系而非要求人类大海捞针。 + ### 2.1 必填字段(commit message 模板) ``` @@ -351,4 +355,4 @@ GLW-TODO: | ⊢ 平台:TCS 通感语言核系统(国作登字-2026-A-00037559) ⊢ 验证码生成密钥:KEY-GUARD-SIGN-001(~/guanghulab-local-secrets/api/) -⊢ 部署方式:本地 hook + 服务器 webhook + 冰朔手动上传 + 紧急通道 \ No newline at end of file +⊢ 部署方式:本地 hook + 服务器 webhook + 冰朔手动上传 + 紧急通道 diff --git a/zero-point/core-channel/revive-guard/navigation-memory-guard.py b/zero-point/core-channel/revive-guard/navigation-memory-guard.py new file mode 100644 index 0000000..e5cc45b --- /dev/null +++ b/zero-point/core-channel/revive-guard/navigation-memory-guard.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +"""Reject orphaned persona-memory artifacts before push. + +This guard is deliberately structural: it does not judge prose. It verifies +that a new/changed durable memory leaf has the minimum HLDP recovery fields +and can be reached from a current navigation page. +""" +import os, re, subprocess, sys + +REQUIRED = ("trigger:", "emergence:", "lock:", "why:", "checkpoint") +NAVIGATION = ("INDEX.hdlp", "CURRENT.hdlp", "LL-CURRENT.hdlp", "BROADCAST-TOWER.hdlp") + +def changed_files(): + commands = [ + ["git", "diff", "--cached", "--name-only", "--diff-filter=ACM"], + ["git", "diff", "--name-only", "HEAD~1", "HEAD", "--diff-filter=ACM"], + ] + files = set() + for cmd in commands: + r = subprocess.run(cmd, capture_output=True, text=True) + if r.returncode == 0: + files.update(x for x in r.stdout.splitlines() if x) + return sorted(files) + +def is_memory_leaf(path): + name = os.path.basename(path) + return name.startswith(("ZL-MEM-", "ZY-MEM-", "ZZ-MEM-")) or "/personas/" in path + +def read(path): + with open(path, encoding="utf-8") as f: + return f.read() + +def linked_from_navigation(path): + base = os.path.basename(path) + for root, _, names in os.walk("."): + if ".git" in root.split(os.sep): + continue + for name in names: + if name in NAVIGATION: + candidate = os.path.join(root, name) + try: + if base in read(candidate): + return candidate[2:] if candidate.startswith("./") else candidate + except OSError: + pass + return None + +def main(): + failures = [] + for path in changed_files(): + if not is_memory_leaf(path) or not os.path.isfile(path): + continue + content = read(path).lower() + missing = [field for field in REQUIRED if field not in content] + if missing: + failures.append((path, "缺永久记忆字段: " + ", ".join(missing))) + if not linked_from_navigation(path): + failures.append((path, "孤立记忆:未被 INDEX / CURRENT / LL-CURRENT / BROADCAST-TOWER 引用")) + if failures: + print("\n🧭 记忆—导航守门人:推送被暂停", file=sys.stderr) + print("持续记忆必须可恢复,而不是只被写进仓库。", file=sys.stderr) + for path, reason in failures: + print(f" ✗ {path}\n {reason}", file=sys.stderr) + print("修复:补齐 trigger/emergence/lock/why/checkpoint,并在对应 INDEX 或 CURRENT 中建立路径。\n", file=sys.stderr) + return 1 + print("✅ 记忆—导航守门人:没有发现孤立持续记忆") + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/zero-point/core-channel/revive-guard/pre-push-clean.py b/zero-point/core-channel/revive-guard/pre-push-clean.py index 08e946f..dd0acb2 100644 --- a/zero-point/core-channel/revive-guard/pre-push-clean.py +++ b/zero-point/core-channel/revive-guard/pre-push-clean.py @@ -218,6 +218,13 @@ def main(): if not ENABLED: sys.exit(0) + # 第二道本地门禁:持续记忆必须挂在可恢复的导航图上。 + guard = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'navigation-memory-guard.py') + if os.path.isfile(guard): + result = subprocess.run([sys.executable, guard], timeout=15) + if result.returncode != 0: + sys.exit(result.returncode) + repo_root = subprocess.run( ['git', 'rev-parse', '--show-toplevel'], capture_output=True, text=True, timeout=5