feat(gate): 熵增闸落地——repo_structure_audit.py 四查(顶层目录白名单/根文件白名单/图像白名单/退役路径守卫)+design 子目录白名单;自检探针验证抓违例能力;CLAUDE.md 交付前验收行挂闸;判据=新类别须同批改 CLAUDE.md+脚本白名单留痕
This commit is contained in:
1 parent
2f6df6c589
commit
0b7e8df1d3
2 files changed
+100
No files matched your search
@@ -23,6 +23,7 @@
|
||||
- 调参期批量工具:`--script res://smoke/adventure_monte_carlo.gd`(全冒险期望扫描)· `--script res://smoke/reward_expectation.gd`(奖励获取期望)——单关直入口口径已退役(2026-09-23 用户拍板),通关率/难度类测量一律走全冒险(原 level_monte_carlo/level_debug 已删)
|
||||
- 数值验证工具:`python tools/balance_verifier.py`(零强化冒险逐关条件通关率+止步节点归因+营地循环爬升战役——采集端 `--script res://smoke/verifier_batch.gd`,报告落 `design/qa/`;元进度换算率标定与曲线调参的自动化评判面,2026-09-22 数值验证工具批;直入口带判定随口径退役暂停,带重锚归曲线调参批)
|
||||
- 交付前验收 = smoke + 全部场景探针全绿(测试细则见 `design/dev/code-conventions.md`)
|
||||
- 结构审计闸(熵增闸):`python tools/repo_structure_audit.py`——顶层目录/根文件/图像白名单/退役路径四查,违例 FAIL;新类别 = 同批修订 CLAUDE.md Project Layout + 脚本白名单,commit 留痕(2026-09-27 立闸)
|
||||
|
||||
## Project Layout
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""仓库结构审计闸(熵增闸,2026-09-27 用户立项)。
|
||||
|
||||
收口第四闸(与 doc_link_audit / doc_term_audit / gdd_lint 同列):
|
||||
把目录三层裁定变成机器检查——任何会话乱放文件,收口时此处直接 FAIL。
|
||||
|
||||
四查:
|
||||
1. 顶层目录白名单(新增顶层目录 = FAIL,须同批改 CLAUDE.md + 本脚本白名单)
|
||||
2. 根目录文件白名单(根上只许运行文件与规则文件)
|
||||
3. 图像白名单(图只许在 artwork/ game/assets/ design/art/references/ design/dev/architecture/)
|
||||
4. 退役路径守卫(production/ docs/ tests/ qa-data/ candidates/mockups 旧路径再现 = FAIL)
|
||||
|
||||
用法: python tools/repo_structure_audit.py # 全查,FAIL 时 exit 1
|
||||
python tools/repo_structure_audit.py --json # 机器读输出
|
||||
依据: CLAUDE.md「Project Layout」节(2026-09-27 目录三层收敛终态)。
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
# 1) 顶层目录白名单(点开头目录一律忽略)
|
||||
TOP_DIRS = {"archive", "artwork", "design", "game", "sim-data", "tools"}
|
||||
# 2) 根目录文件白名单
|
||||
ROOT_FILES = {"CLAUDE.md", "active.md", "roadmap.md", "stage.txt", "review-mode.txt",
|
||||
".gitignore", ".zcodeignore"}
|
||||
# 3) 图像允许目录(相对路径前缀;archive/ 为归档 zip 不扫)
|
||||
IMAGE_EXTS = {".png", ".jpg", ".jpeg", ".webp", ".gif", ".svg", ".pxo", ".psd", ".bmp"}
|
||||
IMAGE_PREFIXES = ("artwork/", "game/assets/", "design/art/references/", "design/dev/architecture/")
|
||||
# 4) 退役路径(目录或文件任一再现即 FAIL)
|
||||
RETIRED = ["production", "docs", "tests", "qa-data",
|
||||
"design/art/candidates", "production/mockups",
|
||||
"design/ux", "game/tools"]
|
||||
# design/ 一级子目录白名单(防 ad-hoc 新目录)
|
||||
DESIGN_SUBDIRS = {"art", "dev", "gdd", "qa", "registry", "research"}
|
||||
|
||||
|
||||
def scan():
|
||||
fails, notes = [], []
|
||||
|
||||
# 1) 顶层目录
|
||||
top_dirs = {p.name for p in ROOT.iterdir() if p.is_dir() and not p.name.startswith(".")}
|
||||
extra = top_dirs - TOP_DIRS
|
||||
if extra:
|
||||
fails.append("顶层目录越界: %s(新增顶层目录须同批改 CLAUDE.md Project Layout + 本脚本 TOP_DIRS)" % sorted(extra))
|
||||
|
||||
# 2) 根目录文件(点开头忽略:.gitignore/.zcodeignore 白名单收编,.git 指针等本就不可见)
|
||||
top_files = {p.name for p in ROOT.iterdir() if p.is_file() and not p.name.startswith(".")}
|
||||
extra_f = top_files - {f for f in ROOT_FILES if not f.startswith(".")}
|
||||
if extra_f:
|
||||
fails.append("根目录文件越界: %s(运行文件与规则文件之外不放根上;新类别须同批改两处白名单)" % sorted(extra_f))
|
||||
|
||||
# 3) 图像白名单
|
||||
stray = []
|
||||
for ext in IMAGE_EXTS:
|
||||
for p in ROOT.rglob("*" + ext):
|
||||
rel = p.relative_to(ROOT).as_posix()
|
||||
if rel.startswith((".git", ".zcode", ".qoder", "archive/")):
|
||||
continue
|
||||
if not rel.startswith(IMAGE_PREFIXES):
|
||||
stray.append(rel)
|
||||
if stray:
|
||||
fails.append("图像越界 %d 个(只许 %s): %s" %
|
||||
(len(stray), "、".join(IMAGE_PREFIXES), stray[:8]))
|
||||
|
||||
# 4) 退役路径
|
||||
for rel in RETIRED:
|
||||
if (ROOT / rel).exists():
|
||||
fails.append("退役路径再现: %s/(该目录已消亡,内容按 CLAUDE.md 终态归属;此路径出现即结构回潮)" % rel)
|
||||
|
||||
# 5) design/ 一级子目录
|
||||
design_subs = {p.name for p in (ROOT / "design").iterdir() if p.is_dir()} if (ROOT / "design").is_dir() else set()
|
||||
extra_d = design_subs - DESIGN_SUBDIRS
|
||||
if extra_d:
|
||||
fails.append("design/ 子目录越界: %s(合法: %s;新分类先过用户拍板再改两处白名单)" % (sorted(extra_d), sorted(DESIGN_SUBDIRS)))
|
||||
|
||||
notes.append("顶层目录 %d 合法 · 根文件 %d 合法 · design/ 子目录 %s · 图像白名单命中 %s" %
|
||||
(len(top_dirs & TOP_DIRS), len(top_files & ROOT_FILES),
|
||||
sorted(design_subs), "、".join(IMAGE_PREFIXES)))
|
||||
return fails, notes
|
||||
|
||||
|
||||
def main():
|
||||
fails, notes = scan()
|
||||
for n in notes:
|
||||
print("✓ " + n)
|
||||
if fails:
|
||||
print("\n【结构违例】×%d" % len(fails))
|
||||
for f in fails:
|
||||
print(" ! " + f)
|
||||
print("\n处理: 文件归位到合法区;确需新类别 = 同批修订 CLAUDE.md Project Layout + 本脚本白名单,commit 留痕。")
|
||||
sys.exit(1)
|
||||
print("\n结构审计 PASS(四查全过:顶层目录/根文件/图像白名单/退役路径)")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user