合并(架构审查P1余项·闸件落地): §四待执行三项做完( S8 目录域反向对账+S7/S8 清单并单点 B1_SET+文案派生; S9/S10 扫描面空转自检)+architecture v1.34 S 表同步+审计报告改判已落地; static_scan 13条规则绿退出码0; §四 P1 四条全部闭合,第五节P2与待办清单未动
ci / gates (push) Successful in 7m50s

This commit is contained in:
DKChan committed 2026-11-03 20:37:48 +08:00
commit 6640711758
5 files changed
+53 -28

No files matched your search

@@ -2,8 +2,8 @@
## 文档状态
- 版本:1.33
- 最近更新:2026-11-03(架构审查 P1 余项裁决落文——静态扫描域标题补齐至 S13 并登记 S11/S12/S13 三行、S1/S2 与 S3 行加适用域与维持 warning 的裁定注、S9/S10 缺空面自检登记为已知偏差;上一版 1.32=迭代 50 批后收尾随动(preview_reveal 只读预览口登记、天赋树 tree_rules 参数字典 API 换代);沿革查 git)
- 版本:1.34
- 最近更新:2026-11-03(架构审查 P1 余项·工程改动批随动——S8 行登记清单单点 `B1_SET` 与 settlement/ 目录域反向对账、S9/S10 空面自检查偏差清偿;沿革查 git)
- 引擎:Godot 4.7.2-stable(GDScript 单语言;2026-09-07 锁定)
- 评审模式:solo(`review-mode.txt`,2026-09-12 用户拍板——TD/LP 门禁按 solo 跳过,用户授权架构产出自主推进、迭代期回调)
- 覆盖 GDD:现行全集(根索引=`design/gdd/02-系统清单.md`,文档树构成以根索引为准)
@@ -292,11 +292,11 @@
| S5 | core/ 禁裸引用 autoload 全局标识符(`ConfigDB` / `RngService` 直接写 = --script 模式 parse error)——构造注入 only(specialist 升格) | **在位**(硬失败;形态=标识符后紧跟 `.` 的成员访问,排除注释行与字符串字面量) |
| S6 | core↔core 信号连接只许方法 Callable(禁 lambda 捕获 self);发射者禁持有订阅者反向引用 | **在位**(2026-10-25 落闸:内联 lambda 禁令机器闸——同行与跨行两形态、豁免注记 `s6-signal-exempt`、盘面零存量;「发射者禁反向引用」句静态判据不成熟,归人工评审面承接、不造弱判据) |
| S7 | B1 编排唯一性:B2/B3/B4 API 符号命中文件 ⊆ B1 文件集;A2/B3/B4 零相互直调(B1 AC-43) | **在位**(2026-10-25 落闸:符号清单×B1 域文件集,族内自调用豁免、豁免注记 `s7-b1-exempt`、缺位自检;全符号形态盘面零存量) |
| S8 | 结算路径 `await` 零命中(B1 结算/编排文件集);字面量扫描 = warning 级 + 人工三要素复核(D2 AC-14 口径) | **在位**(2026-10-25 落闸:B1 域文件集 await 零命中,文件集缺位自检、排除注释与字符串;盘面零存量。本行后半句「字面量扫描=warning 级+人工三要素复核」为独立子项、仍归人工面) |
| S8 | 结算路径 `await` 零命中(B1 结算/编排文件集);字面量扫描 = warning 级 + 人工三要素复核(D2 AC-14 口径) | **在位**(2026-10-25 落闸:B1 域文件集 await 零命中,排除注释与字符串;盘面零存量。清单单点=`static_scan.sh` 的 `B1_SET`,S7 的豁免名单由它派生(原两份 14 文件抄本已并点,2026-11-03 架构审查 P1 裁)。自检两件:①清单内文件缺位即红;②**目录域反向对账**——`game/core/settlement/` 实有 `.gd` 未登记进 `B1_SET` 即红(新段类忘登记=await 面静默失效,2026-11-03 补)。反向对账只覆盖 settlement/:装板/授予/效果端口/掷格四件结算码住 `game/core` 根下,纯目录域覆盖不住,根下新增仍由本行「模块归属」B1 登记面+写卡段申报承接。本行后半句「字面量扫描=warning 级+人工三要素复核」为独立子项、仍归人工面 |
域外扩充五件(S11/S12/S13 自 2026-09-29 起陆续落闸,本表原先只登记到 S10,2026-11-03 补齐登记面):**S9** 类型闸(`tools/audit_type_hints.py`,迭代 27 T5——产品码无类型容器/有值返回缺类型/参数缺类型;扫描面=产品码三目录);**S10** 文件头闸(`tools/audit_file_headers.py`——头注 `##` 载体+日期/变更叙事黑名单;扫描面=产品码三目录);**S11** 代码注释禁用词闸(扫描面=`game/` 全域 `.gd`/`.tres`/`.md`/`.json`/`.sh`,词表单点取 `design/gdd/术语表.md`);**S12** 效果引擎无状态化旧件零残留闸(扫描面=`game/` 全域 `.gd`/`.tres`,旧符号与旧 id 字面清单为脚本字面值);**S13** 第三方质量规则闸(`tools/gdstyle_gate.py`,钉 gdstyle v0.4.0;扫描面=产品码三目录,存量以 `tools/gdstyle_baseline.txt` 欠账簿登记,判定=基线外新键红、同键数值恶化红)。
S11/S12 扫描面覆盖全域,故 sim/probe/tests 的术语与旧件面**在册**;其余十一闸(S1–S10、S13)扫描面止于产品码,非产品码三目录不受约束——分档理由与各目录的运行期承接通道见 code-conventions §4 第 13 条。**防空转自检现行状态**(本文「三层承载与判定原则」要求扫描面为空即判红):S1–S8 与 S11/S12/S13 各自带空面或缺位自检;**S9/S10 现行缺该自检**(`tools/audit_type_hints.py` 与 `tools/audit_file_headers.py` 遇目录不存在时静默零命中并 PASS),属已知偏差,修复归工程改动批、登记在 `reports/审计-全库架构审查-2026-10-29.md` §4.2 标注处。
S11/S12 扫描面覆盖全域,故 sim/probe/tests 的术语与旧件面**在册**;其余十一闸(S1–S10、S13)扫描面止于产品码,非产品码三目录不受约束——分档理由与各目录的运行期承接通道见 code-conventions §4 第 13 条。**防空转自检现行状态**(本文「三层承载与判定原则」要求扫描面为空即判红):S1–S8 与 S11/S12/S13 各自带空面或缺位自检;**S9/S10 两件已补齐同款自检**(`tools/audit_type_hints.py` 与 `tools/audit_file_headers.py` 缺目录或扫描面零个 `.gd` 一律判红,并绿时打印扫描面件数供核;2026-11-03 架构审查 P1 余项的工程改动批落地,本表此前登记的「静默零命中即 PASS」偏差已清偿)。
### 三层承载与判定原则
+18 -5
View File
@@ -318,13 +318,15 @@ fi
# 可回放纯逻辑步骤流(同种子同输入逐位复现),await 会打断确定性——「模块归属」B1 行已写明
# 「禁 await——切片 88 冒烟实证」。本闸为防回归防线(2026-10-24 人工 grep 盘面干净)。
# 扫描面:B1 域文件集(与 architecture.md「模块归属」B1 行同口径)=battle_orchestrator.gd
# + battle_fx_host.gd + reward_grant.gd + board_installer.gd 三拆件 + settlement/ 五段段类 + damage_controller.gd,共 14 文件,显式清单见 S8_FILES。
# + battle_fx_host.gd + reward_grant.gd + board_installer.gd 三拆件 + settlement/ 五段段类 + damage_controller.gd,清单单点=B1_SET。
# 执行侧字面值豁免:脚本必须带字面值才能工作;文件集与架构文档冲突时以 B1 域文件集为准。
# 判据:文件集内出现 await 关键字即红(词边界 \bawait\b,任何形态——await 信号/协程/
# get_tree());排除注释行(行首 #/##)与字符串字面量(双引号包裹段内的 await 非代码),
# 口径仿 S1/S2 的 grep 排除手法。
# 自检:清单内文件缺位(路径写错/被改名)即判红——防扫面为空静默绿。
S8_FILES="game/core/battle_orchestrator.gd game/core/battle_fx_host.gd game/core/reward_grant.gd game/core/board_installer.gd game/core/settlement/aura_segment.gd game/core/settlement/combat_segment.gd game/core/settlement/decay_segment.gd game/core/settlement/grant_segment.gd game/core/settlement/verdict_segment.gd game/core/settlement/round_cycle.gd game/core/damage_controller.gd game/core/settlement/battle_refresh_flow.gd game/core/effect_port.gd game/core/reward_roller.gd"
# 自检:①清单内文件缺位(路径写错/被改名)即判红——防扫面为空静默绿;②settlement/ 目录域反向对账——新段类未登记即判红(见下)。
# B1 域文件集=单点清单(S8 await 禁扫面与 S7 豁免名单共用;改成员先改 architecture.md「模块归属」B1 行再改此处,2026-11-03 架构审查 P1 裁并点)
B1_SET="game/core/battle_orchestrator.gd game/core/battle_fx_host.gd game/core/reward_grant.gd game/core/board_installer.gd game/core/settlement/aura_segment.gd game/core/settlement/combat_segment.gd game/core/settlement/decay_segment.gd game/core/settlement/grant_segment.gd game/core/settlement/verdict_segment.gd game/core/settlement/round_cycle.gd game/core/damage_controller.gd game/core/settlement/battle_refresh_flow.gd game/core/effect_port.gd game/core/reward_roller.gd"
S8_FILES="$B1_SET"
S8_MISS=0
for f in $S8_FILES; do
if [ ! -f "$f" ]; then
@@ -332,6 +334,17 @@ for f in $S8_FILES; do
S8_MISS=1
fi
done
# 自检二(2026-11-03 架构审查 P1 裁):目录域反向对账——settlement/ 实有 .gd 未登记进 B1_SET=该扫的没扫,判红。
# 只反向对 settlement/ 一个目录域:装板/授予/效果端口/掷格四件结算码住 game/core 根下,纯目录域覆盖不住,
# 根下新增仍由「模块归属」B1 行+写卡段申报面承接(禁把目录判据当成全域判据)。
S8_UNREG=""
for f in $(find game/core/settlement -name '*.gd' 2>/dev/null | sort); do
case " $B1_SET " in *" $f "*) ;; *) S8_UNREG="$S8_UNREG $f" ;; esac
done
if [ -n "$S8_UNREG" ]; then
echo "[static_scan] S8 FAIL: settlement/ 有结算段类未登记进 B1 域文件集——await 禁扫面对它静默失效:$S8_UNREG(先改 architecture.md「模块归属」B1 行,再补 B1_SET)"
S8_MISS=1
fi
if [ "$S8_MISS" -eq 1 ]; then
fail=1
else
@@ -344,7 +357,7 @@ else
grep -rnE '\bawait\b' $S8_FILES 2>/dev/null | grep -vE '^[^:]+:[0-9]+:[[:space:]]*#' | grep -vE '"[^"]*\bawait\b[^"]*"'
fail=1
else
echo "[static_scan] S8 ok(扫描面 B1 文件集 10 个 .gd,await 零命中)"
echo "[static_scan] S8 ok(扫描面 B1 文件集 $(echo $S8_FILES | wc -w) 个 .gd+settlement/ 目录域已反向对账,await 零命中)"
fi
fi
@@ -368,7 +381,7 @@ fi
if require_scan_face "S7" "$DIR_CORE"; then
# B1 域文件集(迭代 46 卡A 增补 battle_refresh_flow——换图刷新流程件=C13 拆分边界的 B1 域拆件,
# 承载旧资源退役/装板编排调用;architecture.md「模块归属」BattleRefreshFlow 行随反哺点落文)
S7_B1_SET="game/core/battle_orchestrator.gd game/core/battle_fx_host.gd game/core/reward_grant.gd game/core/board_installer.gd game/core/settlement/aura_segment.gd game/core/settlement/combat_segment.gd game/core/settlement/decay_segment.gd game/core/settlement/grant_segment.gd game/core/settlement/verdict_segment.gd game/core/settlement/round_cycle.gd game/core/damage_controller.gd game/core/settlement/battle_refresh_flow.gd game/core/effect_port.gd game/core/reward_roller.gd"
S7_B1_SET="$B1_SET" # 与 S8 同一单点清单(原第二份抄本,2026-11-03 并点——两份靠人工同步必漂)
S7_MISS=0
for f in $S7_B1_SET game/core/unit_container.gd game/core/status_container.gd game/core/reward_economy.gd; do
if [ ! -f "$f" ]; then
@@ -136,10 +136,11 @@ core 内干净,绕过点全在 core 之外:
- **S9/S10/S13 不扩到三层**(裁决)。2026-11-03 只读数实跑(三个静态扫描脚本对三层,未修文件、未写基线)给出现存总量 **≈2162 处**:S9 类型 1070(sim 158/probe 130/tests 782,其中无类型容器 859)、S10 文件头 117、S13 质量 975(其中「禁调试打印」274+「循环内 await」70——这两类在测试与探针码里是功能需要,不是债)。产品码面 S9/S10 现行**归零**,扩面即把「归零」这一执法前提换成 1187 项存量红;为三层另建欠账基线会把账从 1 份变 3 份。落文=code-conventions §4 第 13 条写明适用域止于产品码并给出三目录的运行期承接通道。
- **读数是**:S8 现行 **14 文件**显式清单(`static_scan.sh:317`),非本节所记 9 文件;同口径 14 文件清单在 S7 另抄一份(`:361`),两份靠人工同步;绿文案仍报「B1 文件集 10 个 .gd」(`:337`)与头注 `:311` 的「共 14 文件」自相矛盾;S8 自检只防「清单内文件缺位」(`:319-324`)不防「该进的没进」——纯目录域方案已证伪:装板/授予/效果端口/掷格四件结算码在 `game/core` 根下而非 `settlement/` 目录内。
- **本轮新查两处**(审计未列):①S9/S10 **无扫描面空转自检**(`tools/audit_type_hints.py:82-83`、`tools/audit_file_headers.py:64-65` 目录不存在即静默 PASS),违背本文「三层承载与判定原则」的零命中自检要求与脚本前言自立的防空转纪律(`static_scan.sh:18-19`);②S3 是半闸(命中只打 WARNING、不置 fail,`static_scan.sh:110`)——**但这条不是洞**:架构文档 S 表 S3 行早已登记「warning 级——class_name 直引误报需人工复核」,属已在册状态。2026-11-03 裁**维持 warning 不升硬**(升硬前提是先有可靠的直引误报排除判据,该判据未立)。
- **待执行清单(登记处=本节;车道=工程改动批,用户发令走独立 worktree 直改+合回 CI,零需求卡片;估 <0.5 工作日)**:
1. `game/tests/static_scan.sh`:S8 新增「`game/core/settlement/` 实有文件 ⊆ 清单」反向对账(新段类未登记即红),并把 S7 的 `S7_B1_SET` 与 `S8_FILES` 两份抄本合一为单点变量,订正 `:337` 的「10 个 .gd」文案;
2. `tools/audit_type_hints.py`/`tools/audit_file_headers.py`:补扫描面空转自检(目录缺失或 `.gd` 数为零即红,口径仿 `static_scan.sh:27-36`);
3. 上述两条落地后,架构文档 S 表 S8 行与「S9/S10 缺空面自检」的偏差登记句随同批改写(禁文档跑在码前,本轮只登记现状)。
- **待执行清单(2026-11-03 同日执行完毕,凭据见下)**:
1. `game/tests/static_scan.sh`:S8 新增「`game/core/settlement/` 实有 `.gd` ⊆ 清单」反向对账(新段类未登记即红)+S7 的 `S7_B1_SET` 与 `S8_FILES` 两份 14 文件抄本合一为单点 `B1_SET`+绿文案「10 个 .gd」改为派生计数(现打「14 个 .gd+settlement/ 目录域已反向对账」)——**已落地**;
2. `tools/audit_type_hints.py`/`tools/audit_file_headers.py`:补扫描面空转自检(缺目录或零个 `.gd` 即红,绿时打印扫描面件数供核)——**已落地**(负证:把面清单改成不存在目录,两件各返回退出码 1;正证:真实面 158 个 `.gd` 归零 PASS);
3. 架构文档 S 表同步——S8 行登记单点与反向对账判据、原「S9/S10 缺自检」偏差句改判为已清偿——**已落地**(凭据=`design/engineering/architecture/architecture.md` v1.34)。
- **验证口径**:`bash game/tests/static_scan.sh` 全量 13 条规则绿、退出码 0;车道=会话内独立 worktree 直改+合回远端 CI(零需求卡片,纯闸件面属工程改动)。§四 P1 至此四条全部闭合。
### 4.3 S13 豁免常态化
+13 -9
View File
@@ -59,19 +59,23 @@ def audit_path(path):
def main():
# 扫描面空转自检:目录缺失或零个 .gd 一律判红——原实现 `if not is_dir(): continue`
# 会让路径写错静默零命中换绿,违背 test-conventions §7「零命中自检为辅证」。
missing = [d for d in SCAN_DIRS if not (ROOT / d).is_dir()]
face = [p for d in SCAN_DIRS for p in sorted((ROOT / d).rglob("*.gd"))]
if missing or not face:
print("[audit_file_headers] FAIL——扫描面为空(缺目录:%s;面清单:%s)"
% ("、".join(missing) if missing else "无", "、".join(SCAN_DIRS)))
return 1
violations = 0
for d in SCAN_DIRS:
base = ROOT / d
if not base.is_dir():
continue
for path in sorted(base.rglob("*.gd")):
for lineno, msg in audit_path(path):
print("%s:%d: %s" % (path.relative_to(ROOT), lineno, msg))
violations += 1
for path in face:
for lineno, msg in audit_path(path):
print("%s:%d: %s" % (path.relative_to(ROOT), lineno, msg))
violations += 1
if violations:
print("[audit_file_headers] FAIL: 文件头存量 %d 处(存量按 code-conventions §1.4.1 白名单清偿)" % violations)
return 1
print("[audit_file_headers] ok: 头注零黑名单命中(R0 载体/R2 日期/R3 变更叙事)")
print("[audit_file_headers] ok: 头注零黑名单命中(R0 载体/R2 日期/R3 变更叙事;扫描面 %d 个 .gd)" % len(face))
return 0
+13 -6
View File
@@ -78,16 +78,23 @@ def audit_file(path):
def main():
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
# 扫描面空转自检:目录缺失或零个 .gd 一律判红——路径写错不得静默零命中换绿
# (test-conventions §7「零命中自检为辅证」;game/tests/static_scan.sh 前言同款纪律)。
missing = [d for d in SCAN_DIRS if not (ROOT / d).is_dir()]
face = [p for d in SCAN_DIRS for p in sorted((ROOT / d).rglob("*.gd"))]
if missing or not face:
print("[audit_type_hints] FAIL——扫描面为空(缺目录:%s;面清单:%s)"
% ("、".join(missing) if missing else "无", "、".join(SCAN_DIRS)))
return 1
total = 0
for d in SCAN_DIRS:
for p in sorted((ROOT / d).rglob("*.gd")):
for line, rule, text in audit_file(p):
print("[%s] %s:%d: %s" % (rule, p.relative_to(ROOT).as_posix(), line, text))
total += 1
for p in face:
for line, rule, text in audit_file(p):
print("[%s] %s:%d: %s" % (rule, p.relative_to(ROOT).as_posix(), line, text))
total += 1
if total:
print("[audit_type_hints] FAIL——存量 %d 处(R1 无类型容器/R2 有值返回缺类型/R3 参数缺类型)" % total)
return 1
print("[audit_type_hints] PASS——产品码类型闸归零(R1/R2/R3)")
print("[audit_type_hints] PASS——产品码类型闸归零(R1/R2/R3;扫描面 %d 个 .gd)" % len(face))
return 0