# PROGRESS · 增长冻结改盯耦合(2026-09-16) 工作树:`.worktrees/freeze-metric-change-20260915` 分支:`codex/freeze-metric-change-20260915` 任务书基线写 `6b3248bf`;开工时 `origin/staging` = **`51a65d92`**(含 BUG-732)。 本机 Windows。无 Docker。本单不占 BUG 号,不改 `CHANGELOG.md` / `BUG_HISTORY.md` / `docs/tasks/README.md`。 `page.tsx` 与 `scripts/jyotish_api_server.py` **一行未动**(反向验证后已 `git checkout` 还原)。 ## 开工实测基线(2026-09-16,`51a65d92`) 禁止抄任务书 1951 / 66 / 41 / 11334 / 225。下列数字全部本机现测。 | 组 | 指标 | 数法 | 实测 | 新门 | | --- | --- | --- | ---: | --- | | 1 | `frontend/src/app/page.tsx` 行数 | `Path.read_bytes().count(b"\n")`,与 `(source.match(/\n/g) ?? []).length` 相同 | **1951** | 粗护栏 ≤ 1951 + 150 = 2101 | | 2a | `Home()` `useState` | `\buseState[<(]`(含 `useState(`) | **66** | 主门,不得增长 | | 2b | `Home()` `useRef` | `\buseRef[<(]` | **41** | 主门,不得增长 | | 3 | `scripts/jyotish_api_server.py` 行数 | `Path.read_bytes().count(b"\n")` | **11291** | 粗护栏 ≤ 11291 + 300 = 11591 | | 4a | 四空格 `def`(任务书同一种数法) | `^ (?:async )?def \w+` 扫全文件 | **225** | 主门,不得增长 | | 4b | `JyotishAPIHandler.__new__` | `scripts/` + `tests/` 的 `*.py`,排除合同测试自身 | **33** | 主门,不得增长 | 说明: - 任务书表格写 api 行数 11,334;本机 `51a65d92` 实测 **11291**(未抄)。 - 任务书表格写 `__new__` = 4:那是 **scripts/ 生产伪造点**(`consultation_workflow_service.py` ×2、`capture_report_blocked_repairs_golden.py` ×1、`local_accuracy_report.py` ×1)。任务书要求扫 `scripts/` 与 `tests/`,实测合计 **33**(scripts 4 + tests 29)。主门按扫描范围合计冻结,只许降不许升。失败信息会列出命中文件。 - 全文件四空格 `def` = 225,其中 `JyotishAPIHandler` 类体 222、类前嵌套 3。冻结用任务书指定的全文件数法。 - 只按 `useState(` 会计到 26,漏掉泛型调用;合同用 `\buseState[<(]`。 `frontend/AGENTS.md` 只有 Next.js 版本提示,没有 §6 重复表述,本单未改。 ## 做了什么 1. `tests/test_api_server_growth_contract.py`:主门改成类方法数 + `__new__` 计数;行数 rebaseline 为 11291 + 300。`must not grow` / `thinly registered` / `CORE_PYTEST_TARGETS` 三条原样仍绿。 2. 新建 `frontend/tests/home-shell-growth-contract.test.ts`:`Home()` `useState` / `useRef` 不得增长,行数粗护栏 1951 + 150。 3. `frontend/tests/chart-view-route.test.ts`:删除行数断言,保留 `doesNotMatch(pageSource, /chart-page|ChartPageView|\/api\/chart-view/)`,注明搬到 home-shell 合同。 4. `AGENTS.md` §6:主门改耦合指标;删掉「参数式 hook 内部保持 0 个 React hook」;第三条三个「不得再手写第二套」原样保留;仍含 `must not grow` 与 `thinly registered`。 ## 既有断言改动 | 文件 | 原值 | 新值 | 原因 | | --- | --- | --- | --- | | `chart-view-route.test.ts` `page.tsx does not grow to host the chart page` | `(pageSource.match(/\n/g) ?? []).length <= 1951` 且 `doesNotMatch(...)` | 测试改名为 `page.tsx does not host the chart page`,只留 `doesNotMatch` | 行数冻结与星盘页无关,搬到专用合同 | | `test_api_server_growth_contract.py` 行数 baseline | 11063(2026-09-02)+ 300 | **11291**(2026-09-16 实测)+ 300 | 任务书要求开工实测 rebaseline,不得抄旧数 | ## 反向验证 ### 1. `page.tsx` 人为加一个 `useState` 在 `Home()` 里插入 `const [_growthContractProbe, _setGrowthContractProbe] = useState(false);`,然后: ``` npx tsx --test tests/home-shell-growth-contract.test.ts not ok 1 - Home() useState count must not grow error: 'Home() has 67 useState calls; cap is 66. ...' # tests 3 / pass 2 / fail 1 ``` `useRef` 与行数粗护栏仍绿。随后 `git checkout -- frontend/src/app/page.tsx`,文件回到 `51a65d92`。 ### 2. `jyotish_api_server.py` 人为加一个类方法 在 `JyotishAPIHandler` 里插入 `def _growth_contract_probe(self): return None`,然后: ``` pytest tests/test_api_server_growth_contract.py FAILED test_jyotish_api_handler_method_count_must_not_grow AssertionError: ... has 226 four-space def methods; cap is 225. 1 failed, 4 passed ``` 行数粗护栏、`__new__`、AGENTS 措辞、`CORE_PYTEST_TARGETS` 仍绿——尺子动的是耦合门。随后 `git checkout -- scripts/jyotish_api_server.py`。 ## 测试 本 worktree 的 `.venv` 是已跟踪的指针文件(内容 `/workspace/Jyotisha/.venv`),Windows 上不能当目录用,未覆盖。合同测试用本机 `C:\Users\74082\anaconda3\python.exe`(pytest 9.1.1)。 | 命令 | 结果 | | --- | --- | | `python -m pytest tests/test_api_server_growth_contract.py -v` | **5 passed**(含原 `must not grow` / `thinly registered` / `CORE_PYTEST_TARGETS` 三条) | | `npx tsx --test tests/home-shell-growth-contract.test.ts tests/chart-view-route.test.ts` | **16 pass / 0 fail**(home-shell 3 + chart-view 13;chart-view 无行数断言) | | `./node_modules/.bin/tsc --noEmit` | 0 错 | | `npm run lint` | **0 error** / 119 warning(既有,未动) | | `npx tsx --test tests/*.test.ts` | 3196 tests / 3112 pass / **69 fail** / 15 skip。本单 3 条 + `page.tsx does not host the chart page` 均 `ok`。失败为无 Docker、Windows `SKILL.md` symlink `EPERM`、bash 部署脚本,与近期同机清单同类 | | `run_quality_gate.py --profile quick --skip-frontend-runtime` | **blocked**:`interpretation_source_inventory_gate.py` → `ModuleNotFoundError: No module named 'mcp'`。停在 pytest 之前,不是本单合同红。未写成通过 | 同 SHA 近期进度 `PROGRESS-consultation-session-capacity-20260915.md` 记 `tests/*.test.ts` 为 3089 / 3001 / **73** fail。本机这次 3196 / 3112 / **69** fail(PowerShell glob 与计数差一截,fail 未增加)。本单新增 3 条全绿,不把 69 写成通过。 未跑 `next build`:无 UI 改动;质量门在 Python 预检就停了。 ## 未做(属范围外) - 真的搬 `Home()` 状态或拆 `JyotishAPIHandler`(后续两单) - `__new__` 收到 0 - 推 `origin HEAD:staging`