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:
1 parent
8084527b68
commit
27812167ef
14 files changed
+102
-213
No files matched your search
@@ -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())
|
||||
@@ -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 留痕)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user