docs: record D6a and the guard-scope fix - #120
Merged
Merged
Conversation
D6a switched phase0/phase2 to the factor service and proved it a no-op cell by cell: 16,388 cells at max_abs_diff 0.0, every headline metric bit-identical at full precision, and the phase0 anchor untouched, which R10 requires until D6d. Everything that would have made a later number move ambiguous - the isinstance dispatch, the missing cache argument - was registered rather than smuggled in. The finding that matters more than the switch is that pytest had been writing fabricated values into the shared factor store. The demo config uses real tickers and real dates, the store key carries no data-source dimension, and D6b's runners are CSI300 over exactly those years; the two configs derive the same key, verified independently by three parties. The fix is not a stronger key. Demo prices are a function of data.start, which the key cannot see, so those values are not a function of their own key - they are not storable at all, and the code now refuses to store them rather than trying to name them. Two guards were rewritten to derive rather than enumerate. The caller census replaced a hand-typed list after a mutation showed the real failure shape: a third unregistered caller plus a signature change plus dutifully updating everything visible left the suite entirely green. The retired-invocation guard was walking the filesystem, so it read git archive exports of pre-retirement revisions under tmp/ and turned main red while every worktree stayed green - and every gate for C6, D5 and D6a had been run inside a worktree, which structurally lacks the directories that break it. Three rules came out of the round. Claiming a property is covered requires naming which test covers it; "that path is covered" is the shape of the mistake, and it fooled its author before it fooled the lead through his report. A red test means either the code broke or the test went blind, and only looking at the colour cannot tell them apart - the lead's instruction to preserve one such red was wrong, because that red was a guard failing to see a call while reporting that the call no longer existed. And node-ID diffs count tests, not properties, so they cannot see a test that grew an assertion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
进度文档 PR,对应 #118(D6a) 与 #119(守卫射程修复)。docs-only:
docs/progress/07_factor_layer_refactor.md追加 D6a 条目、pr_ledger.md补 #118–#120、CLAUDE.md只动三处(状态表 / 主线段 / 路线图)+cp到AGENTS.md并cmp验证逐字节相同。三个重点
① 切换被证明是 no-op(16,388 cells
max_abs_diff=0.0、headline 全精度逐位相同、锚未动),而为保住这个性质所拒绝的东西(isinstance分派、漏传的cache)全部登记而不夹带。② 比切换更要紧的发现:
pytest一直在把编造值写进共享 store。修法不是加固 key —— demo 值是data.start的函数而 key 看不见它 ⇒ 那些值不是它们自己 key 的函数 ⇒ 根本不可存储;代码现在拒绝存储,而不是试图给它们命名。③ 两个守卫从枚举改为派生:caller census 换掉手敲清单(真实失效形态经 mutation 证明是"第三个未登记调用者 + 改签名 + 尽职更新一切可见处 ⇒ 全绿");retired-invocation 守卫走文件系统 ⇒ 读进
tmp/下的退役前副本 ⇒main红而每个 worktree 绿——而 C6/D5/D6a 的每次 gate 都跑在 worktree 里,它结构性地缺少会打破那个守卫的目录。三条方法论
判断"某性质已被覆盖"必须指出是哪一条测试——"那条路径被覆盖了"是犯错的形状,它先骗了作者、再通过作者的报告骗了 lead。一条测试变红有两种可能:代码坏了,或测试瞎了——lead 要求保住的那个红,是守卫看不见一个调用、却报告该调用不存在。node-ID 差分数的是测试个数不是性质,看不见"同一 node ID、断言变多"。