# AGENTS.md — 装配式装修技能开发

> 本文件是跨对话协作的入口锚点（核心 C1）。**它不定义规则，只告诉你规则在哪**：
> 变更定级与审批的唯一事实源是 `_专题_技能合集策划/change-governance.md`，本文件与其冲突时以该文件为准。

## 项目定位

装配式装修技能合集的**开发与治理主仓**（L1 开发源）。技能本体发布到 Qoder 运行时，本仓持有策划稿、治理文件、备份镜像与全过程记录。

- 远端：`https://github.com/eiway112/prefab-interior-skills.git`（`origin/master`）
- 2026-08-30 自 `D:\QoderWork-Files\_项目工作\` 迁入本工作区顶层，`.git` 随迁、历史完整（94 提交）

## 目录结构

```
装配式装修技能开发/
├── AGENTS.md                ← 本文件（C1）
├── .gitignore               ← C5
├── README.md / CHANGELOG.md / LICENSE
├── _专题_技能合集策划/       ← 治理文件 L1 开发源（7 份 shared 治理文件在此）
├── _专题_隔墙技能策划/ _专题_墙面技能策划/
├── _专题_吊顶技能策划/ _专题_楼地面技能策划/ _专题_ACE开发/
│                            ← 各子技能策划稿、QA 基线与红线草案
├── 技能仓备份/              ← 运行时技能的仓内镜像（sync_skill_backup.py 产物，勿手改）
├── 程序文件/                ← C2：五个校验器＋一个同步器（见下）
├── 成果/ 文档/ 记录/        ← C3：交付物 / 方案文档 / 执行记录（件数随批浮动，不钉数字）
└── 素材/                    ← 空占位
```

## 三层结构（必须理解后再动手）

| 层 | 位置 | 性质 |
|---|---|---|
| L1 开发源 | 本仓 `_专题_技能合集策划/` | 可编辑 |
| L2 运行时 SOT | `~/.qoder/skills/` | 技能实际被加载处，唯一事实源 |
| L3 只读镜像 | `~/.qoder/skills/shared/` | 治理文件镜像 |

同步流程与验收步骤见运行时技能 `prefab-governance-sync`；**定级（S/A/B/C）与审批看 `change-governance.md`，不看该技能**。

## 改任何共享治理文件前

1. 读 `change-governance.md` §一定义表 + §二流程，**先查先例再定级**（环境路径/BOM/换行类修正属 C 级，可由发起人直接执行并登记）
2. 改完必须：`技能仓备份/` 同步 → 三份 `change-governance.md` 镜像哈希一致 → 登记 CG 编号
3. 历史 CG 行与 `记录/`、`CHANGELOG.md` 中的旧路径**不改写**（属当时事实快照）

## 验收门禁（改完必须实跑，不接受"应该没问题"）

| 命令 | 当前基线 |
|---|---|
| `python -B 程序文件/validate_governance.py` | **【活基线：CG-20260919-001 起 225、CG-20260920-004 起 234，当前本体版本 v1.12.0】**总评 PASS，通过 **234** / 失败 0 / 警告 1，exit 0。**硬判据是「失败 0 + exit 0」**；通过/警告计数随本体内容浮动，不得按固定数字判回归。**225→234 系 v1.12.0 新增检查 8「技能侧索引序号引用一致性」（CG-20260920-004，B 级，承接 PL-029）产出 9 条 [OK]**（本批 clean 态实测该小节 [OK] 行恰为 9＝真值表四前置 A1—A4＋索引派生表键一致 B0＋取数面自洽 D1＋三载体各一条 ①②③，全额归因，非口径放松；判定单元现测 97＝① 含表行内 ①′ 38／② 35／③ 24，三载体各自真漂 0，NO-ANCHOR 10 值／4 位置，EXEMPT E3 4＋E2 11＋E6 1；豁免全取结构判据、零白名单、零通用编号正则、不判序号单调性）。（v1.10.0→v1.11.0 系 CG-20260919-005 把 `md_cells` 切格改为转义感知，对通过数 **no-op**——225 仍归属其设立者 CG-20260919-001，本批不增检查项故不改通过数。194→196 系 CG-20260918-001 将 SRE 静态体检块的 T-A1 名称差分 13 处清零（转「SRE 硬编码名称与索引主表名称零冲突」OK）与 T-A5Ⅱ 升档标注归入同块 [OK]，两条原 WARN 信号转 PASS，不是检测口径放松。**196→210 系 v1.9.0 新增检查 7「遗留存活性台账」（CG-20260918-005，B 级）产出 14 条 [OK]**（实测该节 OK 行恰为 14，全额归因，非口径放松）。**210→225 系 v1.10.0 检查 6 增列第三条断言 (C)「git 可见副本 ↔ `HEAD` 前像行尾形态一致」（CG-20260919-001，B 级，承接 PL-020）产出 15 条 [OK]**（本批 clean 态实测 (C) 比对 15 项＝声明表 7 件治理文件在 L1＋`技能仓备份/` 两层的 git 可见副本数，全额归因，非口径放松）。检查 7 读 §十一 的 `PL-nnn` 台账表：**结构性违法＝FAIL 档并计 `fail_count`**（台账表或必需 7 列缺失、行列数与表头不符、编号非法或重复、状态出三值枚举、日期不可解析、待处置行缺到期日、登记日期晚于到期日、已闭合／已裁定不做行缺处置依据、来源登记为空、来源与处置列引用的 CG 编号不在 §九 内＝键闭合）——同机字面比对、无外部真值依赖，故与检查 6 同理首轮即 FAIL 档；**单纯到期＝聚合一条 WARN＋逐条 INFO，不计 `fail_count`**（沿检查 3／CG-20260917-009「不因单纯到期增加失败」口径），另有 30 天内到期预警 INFO 与待处置行 TTL 超 180 天上限 WARN。**键闭合真值源＝「§九 逐行取第一列 CG 编号」，不用表级解析**：CG-20260918-005 设立检查 7 时 §九 有一历史行跨物理行断行，`iter_md_tables` 在断点处把其后各行判为「无表头块」整块丢弃（登记时点实测表级读法只见 **72** 个、止于 `CG-20260916-008`，逐行读法 **88** 个），故任何以表级解析消费 §九 的检查都会**静默漏行**；该断行登记为 **PL-016** 并自设前置「修历史行字节须另批裁定」。**该前置由 CG-20260919-002 承接**（同批另订正 PL-019 的根因与定性），订正后实测表级可见 **95** 个、与逐行读法 **95** 归一——两口径自该批起一致；逐行取数口径与合成文本守卫 `test_wrapped_history_row_does_not_hide_later_ids`（不依赖真实文件仍断行）作为**免疫性设计**保留。常量 `LEDGER_TTL_DEFAULT=90`／`LEDGER_TTL_EVENT=180`／`LEDGER_SOON_DAYS=30` 与 §11.1 散文字面由测试**双向守卫**同值（散文改了常量没改即复红）。**反向覆盖未机算**：只做「台账 → §九」方向键闭合，不反查 CG 行散文声明的遗留（散文字面无稳定形态，正则会产假信号），故「新遗留漏登记进台账」仍靠人工，§11.3 第 3 条已显式披露。警告一处：仅剩检查 3 的 38 条无有效核验日期聚合 WARN（CG-20260918-009 向 §二 官方核验记录表补登序号 68 后由 41→40，CG-20260918-010 向 §二 推荐性标准抽查核验记录表补登序号 15／18 两行后再降为 38，档内分布＝强制性国标 3／其余 35）；不计 `fail_count`，不因单纯到期增加 WARN。**T-A1 名称差分已清零（CG-20260918-001），并自 v1.8.0 起升 FAIL 档（CG-20260918-002，§6.3.3 ③(b) 代码级半步收口）**：差分非空即 FAIL 计 `fail_count`，clean 态读数不变；反向注入自证（`--runtime-dir` 临时副本注入 1 名称值）实测 T-A1 FAIL＋exit 1、检查 6 注入态保持 [OK]；其余信号 T-A2—T-A5 仍首轮 WARN，升档时点各自依其前置。**检查 3 当前口径以索引 §1.1A 为准**：按表头分类、列名读取核验日期与状态；日期到期按 92／183 天严格大于现算，显式「到期需复核」任务也须披露，二者报 INFO；无记录／无效或未来日期仍报依据链未确认 WARN，**缺日期不等于已超期或标准失效**。并列编号只按全角 `／` 切分，半角 `/` 属编号本体。运行时 `sre_reasoner.py` v1.7 的 `_verification_confirmed()` 将可复用的既有依据与维护提醒分离：已确认者仅因到期不降级，提醒写入 applicability；未确认者仍 inferred＋§1.1A degradation，补真实依据或接受降级为等价出口。已废止另有 inferred＋TA-3 提示，GB 50118 既有部分替代警告保持；自动替代／暂停能力边界见 rules §4.3。**IC-10 item 字段、枚举与适用集成员不变**，deterministic 不代表本轮重新核实最新状态或工程合规放行。v1.6.0 新增**检查 6「治理文件跨层一致性」**，**首轮即 FAIL 档且计入 `fail_count`**（与检查 5 不同：同机字面哈希比对，无外部真值依赖）——三条断言各自指向修复命令：**(A) L1→下游副本全等** 报红 → 由 `prefab-governance-sync` 按 L1→下游带平（抓 -004⑧(b)／-005(a)／-006 那类跨批落后）；**(B) 运行时↔`技能仓备份/` 同层全等** 报红 → 重跑 `程序文件/sync_skill_backup.py`（抓 sync 漏跑/半跑）；**(C) git 可见副本 ↔ `git cat-file HEAD:<path>` 前像的行尾形态一致** 报红 → 该副本工作区行尾五类形态（无行尾分隔符／纯 LF／纯 CRLF／仅 CR 无 LF／混合行尾）相对 HEAD 前像漂了，指向登记面写入脚本的换行翻译（Windows 文本模式 `Path.write_text` 把 `\n` 译作 `\r\n`）。其真值源＝HEAD 对象，在三层互等闭环之外，故抓得到「三层被同一脚本同时写坏、互等仍成立」这一 (A)(B) 结构性盲区（CG-20260918-010 ⑩ 的 `git diff --stat` 831/831 伪差异即该失效模式）。口径四条：比对集是**逐文件声明**的 7 件常量表（不 glob，故 `*_pre*` 回退件与 `.bak` 不入），基准**不读** `同步说明.md` 的哈希清单（那是被测工具自产，属自指），哈希取 `sha256(原始字节)` 不做 eol 归一（跨机 `core.autocrlf=true` 克隆会把 `技能仓备份/` 层转 CRLF 而**产假红**，本机 autocrlf=false），运行时层不可达时按检查 5 同口径**降级 WARN 且逐项列出被跳过的 (文件@层)**，而 L1／仓内属固定面缺失仍判 FAIL。(C) 三条口径：只比**形态**不比字节数与内容（故真实内容编辑不报红，而行尾形态订正会如实报红、须与所属批的改判同批入库）；HEAD 无该路径对象（新增未提交件，git 的 `does not exist in 'HEAD'` 与 `exists on disk, but not in 'HEAD'` 两式）→ INFO 不判红；git 不可达或仓无提交 → 聚合一条 WARN 且逐项列出被跳过副本，不静默放过。其不覆盖面（运行时两层无 git 面故只经 (A)(B) 字节全等传递、真值源是 HEAD 而非规范值故提交后转绿、只比形态钉不住「行尾应为 LF」这类绝对规范）由 `change-governance.md` §11.3 第 6 条**显式披露而非机算**。`platform-adapter-reference.md` 无 L1 归属，不入 (A) 链、只比同层。覆盖面**只含声明的 7 件治理文件**，技能目录内约 114 件（SKILL.md／reference.md／examples.md／scripts）与机器本地 `sre_regression_report.json` 不经本检查（F-02 遗留）。**自 v1.12.0 起须区分两件事**：其中「技能侧对索引序号／编号的引用一致性」这一子面改由**检查 8** 承担（覆盖面＝15 技能目录活 `.md` 现测 47 件，CG-20260920-004 承接 PL-029）；但**检查 6 的覆盖面并未因此扩大**——它仍只比声明表 7 件，其余约 114 件与机器本地产物（`sre_regression_report.json`）经不漏检地**不经**检查 6，故 **PL-010 不因此闭合**（其各件跨层内容一致、机器本地产物两面仍活口，见 `change-governance.md` §11.3 第 7 条）。声明集与 `sync_skill_backup.py` 的 `ROOT_FILES`＋`SHARED_FILES` 做 AST 现读**双向互查**：声明而不属脚本 → FAIL「声明表越界」；属脚本而未声明 → FAIL「漏配」 |
| `python -B 程序文件/verification_policy_test.py` | Ran 6 tests，OK；检查 3 专项：两档严格边界、到期 INFO 且 WARN/PASS 集稳定、显式复查任务、缺记录／异常日期 WARN、实际状态漂移 FAIL。改核验维护规则时与四项既有门禁一并运行。CG-20260918-010 起「到期 INFO＋全局 WARN 集稳定」那组的钟点由 `latest_verify_date()` **从索引核验记录表现读**（取最新核验日期），不再是硬编码日——硬编码钟点会把该组的跨时点全局集比对隐式耦合到索引最新日期，向核验表补录较新日期即复红（属测试件缺陷，非数据错误）。 |
| `python -B 程序文件/ace_regression_test.py` | Ran 90 tests，OK |
| `python -B ~/.qoder/skills/prefab-standards-reviewer/sre_regression_test.py` | **【活基线，更新至 CG-20260917-009】Ran 66 tests，`OK`**（既无 expected failures 亦无 unexpected successes），exit 0，缺口信号 0 条、跨轮指纹 `4f53cda18c2baa0c`（连击计数属机器本地状态，不钉数字）；IC-10 v1.9.0（零新字段、零新枚举）、reasoner v1.7、rules v1.2.6、测试模块 v1.9。59→66 为维护／依据解耦守卫：GB 55037 第 92／93 天保持完整 item 和确定性、响应内提醒、显式复查任务、缺记录／未确认／异常日期保护，以及未知／已废止／GB 50118 部分替代的独立保护；原分档边界、矩阵成员、契约及防空跑断言继续执行。已确认的确定性对称面排除未知和已废止，废止由专用断言验证。独立验收与故障注入见 CHANGELOG v1.12.15。下方为 CG-20260916-009 历史快照，其版本与计数不作当前基线。 ‖历史快照（-009 时代，不改写）‖ Ran 37 tests，`OK`（**既无 expected failures 亦无 unexpected successes**），exit 0，缺口信号 0 条、跨轮指纹 `4f53cda18c2baa0c`。全文 `^\s*@unittest\.expectedFailure` 现 **0 处**——行为组 T-B1—T-B7 七项已全部转为正向常态断言（T-B1／T-B7 随 CG-20260916-003、T-B2 全条与 T-B4 含 `conversion` 半条随 **CG-20260916-004**、T-B3／T-B5／T-B6 随 **CG-20260916-005** 摘档）。用例数 30→32 系 -005 按 §6.2「摘档须升级为有约束力断言」新增两条收紧用例：`test_TB5_empty_family_negative_path`（合成注入无映射域，因矩阵正例在数据面修净后会恒真空跑）与 `test_TB6_national_and_local_coexist`（逐地点正向期望集，期望值从 `DOMAINS` 现读）。**32→37 随 -009（A 级）**：`test_standard_item_schema` 的 `角色` 断言从「只跑 `reason("住宅","分户墙")` 一组」扩为全 34 组激活对 × 7 地点矩阵遍历（带 `visited`／`checked` 漏组与空跑判据），合法值域从 `~/.qoder/skills/shared/interface-contracts.md` 的 IC-10 `角色` 枚举**现读**；另新增 5 例（图集号命中、索引 §二 编号不降级含 `ZZ 9999-1999` 负向半条、GB 18580-2025 落 `mandatory_check`、08J931 落 `construction_guide`、M4 兜底合成注入），并按「修净后的守卫须仍能失败」做反向注入自证（逐项回退复红 1／2／2、三项合并 6）。测试侧共享 helper `_table()` 已修：数据行必须在首个非表格行截断，否则同小节第二张表（索引 §二 的「官方核验记录」）会被并入首表、其表头单元被当成编号（-009 F-02）。**运行时 `sre_reasoner.py` 版本头自本批起为 v1.3**（-005 遗留 (c) 闭合）。T-B2／T-B4 的前置仍是 IC-10 `时间状态` 枚举由四值扩为与 IC-07 同源的六值（契约 **v1.8.0**）并新增可选 `状态注记`，二者判据现从 `~/.qoder/skills/shared/interface-contracts.md` **现读枚举**，故该契约文件不得落后于运行时消费端。实跑产物 `sre_regression_report.json`（已被 `.gitignore` 收录，机器本地）。历史：7 例挂档见 CG-20260916-002、5 例见 -003、3 例见 -004 |
| `python -B ~/.qoder/skills/prefab-standards-reviewer/sr_ic07_compliance_test.py` | Ran 20 tests，OK。**计数硬编码**（`SR_REDLINE_COUNT`、`REGISTRY_TOTAL_COUNT`），红线注册类变更须回扫 |
| `python -B 程序文件/pending_ledger_test.py` | **【第六门禁，CG-20260918-005 新增】Ran 39 tests，OK**，exit 0。检查 7 专项：负向注入以**合成文本直调** `check_pending_ledger`，不落盘、不改任何治理件；覆盖 19 类结构违法**逐类**注入自证（缺节／缺表／缺表头／缺列、编号形制与非 `PL` 前缀、编号重复、状态出枚举、登记日期与到期日不可解析、非法历法日 `2026-02-30`、待处置缺到期日、登记晚于到期、已闭合／已裁定不做缺依据、来源登记为空、来源与依据列悬空 CG 编号、行列数与表头不符、§九 无真值源）、TTL 边界（到期日＝今天不超期／前一日超期／30 天预警窗口内外各一例）、**到期只 WARN 不计 `fail_count`**、已闭合行过期不计、真实治理件 clean 态断言（`test_real_repo_ledger_is_clean`）、常量↔§11.1 散文字面同值双守卫、PL-016 断行免疫守卫、§九 外 CG 编号不入真值源。**36→39 系 CG-20260919-005（B 级，闭合 PL-021）新增类 `TestEscapeAwareParsing` 三例**：`md_cells` 转义感知的正向断言（含转义竖线的单元解析为 7 列且值内含字面竖线）、台账写转义竖线形不报「行列数」、以及同单元改写未转义裸竖线仍报「行列数」不符 FAIL（证守卫非恒真）。改 TTL 口径、状态枚举、键闭合规则或 `md_cells` 切格算法时须与其余六道门禁一并运行。 |
| `python -B 程序文件/cross_layer_eol_test.py` | **【第七门禁，CG-20260919-001 新增】Ran 25 tests，OK**，exit 0。检查 6 (C) 专项：①行尾形态判据本身——五类各一例＋「单行 CRLF 注入」＋「整文件 LF→CRLF」＋**真实内容编辑不得改形态**＋「无行尾分隔符与空文件同类」＋枚举闭守卫；②`git_head_blob` 三态（ok／no_head 认 git 两式字面／git_unavailable 含零提交仓）与真实 HEAD 对象读取；③临时 git 仓端到端——核心例 `test_same_drift_across_layers_still_fails` 复现 CG-20260918-010 ⑩ 事故本体（各副本字节全等故 (A)(B) 结构上必绿、集体偏离 HEAD 时 (C) 仍逐项报红），另含部分漂移只报漂移件、无 HEAD 件只披露不判红、git 不可达走 WARN 分支；④真实仓 clean 态断言（比对项恰 15 且零 FAIL 零 WARN）＋防空跑断言（取真实 `change-governance.md` 的 HEAD 前像做 `\n`→`\r\n` 整文件翻转后必红）。临时仓建在 `D:\Qoder-Files\_tmp-scripts\`（不落 C 盘、不进运行时技能目录，免被 sync 当新增件带进镜像），跑后自清。改行尾判据、五类形态口径或 git 取物三态分类时与其余六道门禁一并运行。 |
| `python -B 程序文件/index_ref_consistency_test.py` | **【第八门禁，CG-20260920-004 新增】Ran 26 tests，OK**，exit 0。检查 8「技能侧索引序号引用一致性」专项：负向注入以**内存内直调** `check_index_ref_consistency`（合成 `FakeFile` 与 `truth_override`／`sync_text_override`），不落盘、不改任何治理件；含真实仓 clean 态基线断言（47 件活 `.md`／判定单元 97＝① 含 ①′ 38／② 35／③ 24／三载体各自真漂 0／NO-ANCHOR 10 值 4 位置／EXEMPT e3 4·e2 11·e6 1，9 条 [OK]）＋**三载体各注入 1 错号复红**（散文／表列／内联）＋**真值表四前置各破坏 1 项复红**（A1 主表空／A2 重号／A3 空号不连续／A4 非哨兵非单射）＋派生表 B0 不符复红＋取数面 D1 两侧不等报「漏配／越界」；**控制例 C1—C6 全通过**证豁免规则不恒真（C1 `(?<!原)` 只免注记形态、C2 E3 由窗口字面非行号驱动、C3 E1 只免词典零命中、C4 成员判据不因锚集扩大恒真、C5 D1 须能失败、C6 F8 多值展开有牙且 E6 刹车不误伤）。改检查 8 判据、载体提取规则、豁免结构判据或声明串展开规则时与其余七道门禁一并运行。 |
| `python -B 程序文件/sync_skill_backup.py` | 把 `~/.qoder/skills/` 运行时技能回写 `技能仓备份/` 镜像。**基线已验证**（CG-20260916-006 ④ 实跑）：清掉两层 `__pycache__` 后为「范围 122｜一致 122｜新增 0｜更新 0｜移除 0」，`同步说明.md` 哈希清单随之刷新（CG-20260829-001 ⑤ 的「失准、待重跑」已闭合）。**本行判据是「范围 122 ＋ 新增 0 ＋ 移除 0」**；一致/更新两数随批浮动（改了哪几件就更新几件），不得按固定数字判回归。**CG-20260917-009** 首跑「范围 122｜一致 116｜新增 0｜更新 6｜移除 0」，末次同步与只读检查见 CHANGELOG v1.12.15；使用 `python -B` 避免新生 `.pyc`，同步前检查范围与差异，出现未知新增／移除须停。以下为历史读数（CG-20260917-006）**首跑**为「范围 122｜一致 119｜新增 0｜更新 3｜移除 0」，更新件＝`sre_reasoner.py`／`sre_regression_test.py`／机器本地 `sre_regression_report.json`（＝本批三件运行时改动带平）；**收尾复跑**为「范围 122｜一致 121｜新增 0｜更新 1｜移除 0」，唯一更新件＝机器本地 `sre_regression_report.json`（前三件已一致，report.json 因复跑门禁被重写）——两次读数差即「本批改了哪几件」，正是本行不得钉固定数字的原因。**排除面缺口已机算收口（CG-20260919-004，C 级，闭合 PL-011）**：v1.4 起 `walk_files` 源侧收集加跳 `.pyc`／`__pycache__`，目标侧扫描故意不跳以便镜像清理删除历史遗留的孤儿 `.pyc`（自愈），故「跑前须先手工删两层 `.pyc`」这一人工步骤自此由脚本承担；`--check` 实测对 clean 态为 no-op（当前两层 0 个 `.pyc`，范围 122／新增 0／移除 0）。**反向缺口（-009 实测）**：范围是固定的「15 个技能目录 ＋ 根治理文件 ＋ shared 7 文件」，落在 `技能仓备份/` 内但不属于该范围的件会被当差异**移除**——本批放在 `技能仓备份/shared/` 的 `_pre20260916CG009` 备份首跑即被删（读数「移除 1」）。故仓内镜像侧**不是** `_pre*` 备份件的留存位置，回退判据取 `git show HEAD:<path>` 前像，运行时侧备份件仅机器本地保险 |

> **SRE 门禁转红时的正确动作（设计方案 §6.2，不是故障）**：若 `sre_regression_test.py` 报 `FAILED (unexpected successes=N)` 并 exit 1，说明对应缺陷已被真实修复——须摘掉该用例的 `@unittest.expectedFailure` 装饰器、把断言转为正向常态断言，**禁止回退或注释 `sre_reasoner.py` 的修复来让用例重新"预期失败"**。

`validate_governance.py` 从本体算数不硬编码计数；`sr_ic07_compliance_test.py` 等硬编码计数的脚本是盲区，红线注册类变更须回扫。
