refactor(状态规矩): 废除根目录会话状态文件 active.md 与全套执法件(2026-10-18 用户裁)

判据(对 869 个 ZCode 会话与 16 个 Qoder 会话的读写统计):active.md 被整文件读 448 次、
单次中位数 14 KB、累计 6.09 MB 进上下文,311/320 个碰它的会话把它当第一个工具调用读;
但 7311 个提及它的思考片段的语境分布是——写入与编号簿记 327 个会话、并行冲突与避让 234 个、
退役与失真核对 162 个,而明确写「从它所载内容得知某事实」的只有 20 个会话。
逐条核 41 个条目:独特且现行 2 条(另 3 个子句)、别处已有权威源 14 条、陈旧或自相矛盾 7 条、
已完结批次的历史叙述 18 条;按字节约 95% 属后三类。失实样本:architecture 版本记 v1.6 实为 v1.8、
规则文件数记 7 份实为 6 份、迭代 27/28 记「位预留追加卡」而 roadmap 记已完成、三个已删 worktree
仍记「在盘待删」、同一条既宣称「文档禁列闸清单」又自行列出 01–11 全套闸。
执法件已建一轮仍拦不住:08b 体量闸只测条目数/行数/编号/死链,测不出语义失真;钩子不随仓库传播,
只有 ZCode 在跑;10-15 清到 8.6 KB、10-17 回到 40 KB,用户为「只写不删」连续三次发火。

改动面:
- 删 active.md 与 tools/audit_active_state.py;run_all_gates.sh 摘除 08b 闸件与头注、
  baseline.json 删 08b 记录(现存 12 闸)、repo_structure_audit.py 根文件白名单去 active.md
- doc-conventions §10 改写为「仓库根不设状态文件」并留裁决与判据(保持 §11/§12 编号不漂);
  §11 表两行去状态文件口径;§4 适用范围去 active.md
- process-conventions §1 第 2/3 条(合回前查尾号防撞号、豁免面)、§3 第 12 条(批次完成后的
  登记义务)、§6 分级周期口径(闸件清单不再在文档重列)四处换代
- code-conventions「实现批收尾双登记」改为单登记;CLAUDE.md 目录节、规范导航行、worktree 豁免
  行三处换代,红线新增「仓库根禁止设会话状态文件」一条
- roadmap.md 顶部新增「当前位」三行(阶段/迭代位/下一步)接替原快照职责,头注、执行纪律第 3 条、
  loop 规范第 8 条、维护纪律四处改指 06 与本文;reports/README.md 与 sim-data/README.md 两处
  现行指路改口;architecture.md 文档域闸表行去 active.md 体量闸与触发路径
- 06-待办清单迁入七条真残值(原仅载于该文件):卡片入库纪律悬空待办、req-card 两副本取齐、
  魔法道具与罕见残留(实数 23/17 处,旧记约 30/18)、通关口径统一(gdd 内 188 处,旧记 273)、
  黑话第二波待发令、数据整改批九条存疑待抽查(该批未提交面所载)、发布前删除 main.gd:196 调试
  入口写死行(工程直入·待写卡)

harness 侧另批处理(.zcode/ 与用户级技能不入 git):session-snapshot.sh 与 config.json 注册、
worktree-guard.sh 的 active.md 豁免白名单、active-closing 技能、doc-consistency-check 第 8/9 项、
iter 与 req-card 技能里的「唯一例外=active.md」与查尾号条款。
This commit is contained in:
DKChan committed 2026-10-18 07:28:48 +08:00
1 parent 8084527b68
commit 27812167ef
14 files changed
+102 -213

No files matched your search

-120
View File
@@ -1,120 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""audit_active_state.py — 根目录 active.md 体量闸(doc-conventions §10 的机械面)
状态文件只记当下:条目只增不减就是腐烂。本脚本查五条机械可判的膨胀签名——
状态记录条目数超上限、快照节行数超上限、条目编号重复、快照整行自我重复、
指向中间文档(design/qa、design/research)的死指针。
退出码:0=全绿;1=有红(逐条打印差额,供收口批据此删条目)。
用法:python tools/audit_active_state.py [--file PATH] [--quiet]
"""
import argparse
import os
import re
import sys
ENTRY_LIMIT = 30 # §10:状态记录超过 30 条必须清
SNAPSHOT_LIMIT = 10 # §10:当前状态快照 ≤10 行
INTERMEDIATE_PREFIX = ("design/qa/", "design/research/")
ENTRY_RE = re.compile(r"^- \*\*(\d+)( 续)?")
BULLET_RE = re.compile(r"^- .{20,}")
PATH_RE = re.compile(r"design/(?:qa|research)/[^\s)`,,。)]+?\.md")
def split_sections(text):
"""按二级标题切段;标题前的内容归入 '' 键(文件头元信息,本闸不判)。"""
out, key = {}, ""
for line in text.splitlines():
if line.startswith("## "):
key = line[3:].strip()
out[key] = []
continue
out.setdefault(key, []).append(line)
return out
def find_key(sections, prefix):
for name in sections:
if name.startswith(prefix):
return name
return None
def audit(path, repo):
with open(path, encoding="utf-8") as f:
sections = split_sections(f.read())
reds = []
snap_key = find_key(sections, "当前状态快照")
rec_key = find_key(sections, "状态记录")
if snap_key is None:
reds.append("A0 快照节缺失:状态文件必须含「当前状态快照」节")
if rec_key is None:
reds.append("A0 状态记录节缺失:状态文件必须含「状态记录」节")
snap = [ln for ln in sections.get(snap_key, []) if BULLET_RE.match(ln)]
if len(snap) > SNAPSHOT_LIMIT:
reds.append("A1 快照节 %d 条,超上限 %d——先删被新一轮取代的旧行,别只往顶部加"
% (len(snap), SNAPSHOT_LIMIT))
seen = {}
for ln in snap:
seen[ln] = seen.get(ln, 0) + 1
dups = [ln for ln, n in seen.items() if n > 1]
if dups:
reds.append("A2 快照节有 %d 行整行自我重复(换代不彻底的签名):%s"
% (len(dups), dups[0][:60] + " …"))
nums, conts = [], []
for ln in sections.get(rec_key, []):
m = ENTRY_RE.match(ln)
if m:
(conts if m.group(2) else nums).append(int(m.group(1)))
if len(nums) > ENTRY_LIMIT:
reds.append("A3 状态记录 %d 条,超硬上限 %d——按 §10 判据删除已完结批次条目"
% (len(nums), ENTRY_LIMIT))
repeated = sorted({n for n in nums if nums.count(n) > 1})
if repeated:
reds.append("A4 条目编号重复(并行侧写撞号):%s"
% "、".join(str(n) for n in repeated))
body = "\n".join(sections.get(snap_key, []) + sections.get(rec_key, [])
+ sections.get(find_key(sections, "未决面"), []))
dead = sorted({p for p in PATH_RE.findall(body)
if not os.path.exists(os.path.join(repo, p.replace("`", "")))})
if dead:
reds.append("A5 指向中间文档的死指针 %d 处(文件已按 §11 退役,条目却还在引):%s"
% (len(dead), "、".join(dead)))
return reds, len(nums), len(snap)
def main():
ap = argparse.ArgumentParser(description="active.md 体量闸")
ap.add_argument("--file", default=None, help="待审文件(默认为本仓库根目录 active.md)")
ap.add_argument("--quiet", action="store_true", help="只输出结论行")
args = ap.parse_args()
repo = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
path = args.file or os.path.join(repo, "active.md")
if not os.path.exists(path):
print("[active.md 体量闸] 找不到文件:%s" % path)
return 1
reds, entries, snap = audit(path, repo)
if reds:
print("[active.md 体量闸] FAIL:%d 项——状态记录 %d 条 / 快照 %d 行" % (len(reds), entries, snap))
for r in reds:
print(" " + r)
return 1
if not args.quiet:
print("[active.md 体量闸] PASS:状态记录 %d 条 / 快照 %d 行,编号唯一、指针全活" % (entries, snap))
return 0
if __name__ == "__main__":
try:
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
except Exception:
pass
sys.exit(main())
+1 -1
View File
@@ -25,7 +25,7 @@ ROOT = Path(__file__).resolve().parent.parent
# 清单的家——实现批只准往这里写,design/ 全目录对它只读。只放 .md,不放图(图像白名单不含此目录)。
TOP_DIRS = {"archive", "artwork", "design", "game", "sim-data", "tools", "reports"}
# 2) 根目录文件白名单
ROOT_FILES = {"CLAUDE.md", "active.md", "roadmap.md", "stage.txt", "review-mode.txt",
ROOT_FILES = {"CLAUDE.md", "roadmap.md", "stage.txt", "review-mode.txt",
".gitignore", ".zcodeignore"}
# 3) 图像允许目录(相对路径前缀;archive/ 为归档 zip 不扫)
# design/qa/ 收编(迭代 5 返工批 2026-09-29——U2 目检预览图/QA 呈现产物归位,commit 留痕)
+1 -3
View File
@@ -9,7 +9,7 @@
# 用法:tools/run_all_gates.sh [--code|--docs|--quick]
# --code 只跑代码域闸(01 冒烟/02 单元/03 探针 --click/04 探针 --full/05 渲染闸/09 静态扫描
# /11 回放确定性对拍+10 熵增闸)——本批改动触及 game/ 时用(游戏工程的唯一代码验收域)。
# --docs 只跑文档域闸(06 gdd_lint/07 doc_link/08 doc_term/08b active.md 体量/08c 流水线闸
# --docs 只跑文档域闸(06 gdd_lint/07 doc_link/08 doc_term/08c 流水线闸
# +10 熵增闸)
# ——本批改动不触及 game/ 时用:design/、根规则文件、tools/ 工具脚本、.zcode/ 配置等
# 一切非 game 改动的本域验收。
@@ -182,8 +182,6 @@ if in_domain docs; then
gate "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py"
gate "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict
gate "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" --strict
# ── 6b. 状态文件体量闸(active.md 只记现在:条目数/快照行数/编号/死指针四条硬上限)──
gate "08b active.md 体量" "active_state.log" "$PY" "$REPO/tools/audit_active_state.py"
# ── 8c. 流水线闸(06 条目状态机+roadmap 迭代总表+一次交叉核,判据=doc-conventions §12)──
gate "08c 流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py"
fi