fix(measure): exempt provenance-verified full-body text from self-declaring guard - #1936
Conversation
The self-declaring-word guard in scripts/measure_rule_effect.py rejected any replace_with text carrying words like experiment/variant/test/probe/harness, which is the L2 evolution layer's own domain vocabulary. That made the harness unable to insert the body of the very skill that specifies it (skills/evolution-rule-effect-measurement/SKILL.md, 30 hits) or the brake 1 skill (skills/evolution-parallel-agent-eval/SKILL.md, 8 hits). 日本語: ガードの語彙が計測レイヤー自身の業務語彙と衝突し、ガードを持つ skill 自身の 本文すら挿入できなくなっていた問題を修正する。#1935 のコメントが絞った (b) を採用し、 replace_with がリポジトリ内の対象ファイルの全文と一致する場合はガードを通す (_matches_existing_file 経由)。全文一致のみを認めるため、一部を実在文で包んで自己 申告を通す捏造は引き続き弾かれる。 Repair axis = (b) provenance: load_plan/_load_edits now thread source_root through to _reject_self_declaring, which exempts inserted text that is byte- for-byte the current content of the file at the edit's own path. Vocabulary alone remains the guard for everything else, including a partial match. (d) taken in the same PR, not split off: the guard's own grounding example (skills/evolution-rule-effect-measurement/SKILL.md Containment when a file is placed) is "a copy made for a trial", and `trial` was absent from SELF_DECLARING_WORD - the list could not catch the example that grounds it. Low-risk, same file, same guard; splitting it out would leave that hole open. Tests: extended tests/test_measure_rule_effect.py (SelfDeclaringProvenanceTest) rather than duplicating - no prior coverage of the guard actually firing existed, so also added a case for the pre-existing vocabulary path and the new `trial` word. tests/** change, so this PR is inside brake 1's governed surface per rules/evolution/initiator-autonomy.md Self-evolution PR definition. #1935 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Axis A — issue 要件との照合指摘なし。issue #1935(本文 + コメント1件)を読み、PR #1936 の diff( 確認した対応関係:
Axis B — ルール違反指摘なし。diff の全変更行(
Fixed axis — 印象語検出該当なし。本 diff は |
smileygames
left a comment
There was a problem hiding this comment.
親セルフレビュー(brake 1 exit 後)
受入基準の照合
issue #1935 は 3 ケースを受入条件として指定していた。評価者が独立にクローンした作業ツリーで実際に --dry-run を走らせて再現しており、親の読みと一致する。
| ケース | 結果 |
|---|---|
replace_with = skills/evolution-parallel-agent-eval/SKILL.md 全文(38,596 B) |
exit 0、run record 生成 |
replace_with = skills/evolution-rule-effect-measurement/SKILL.md 全文(19,168 B) |
exit 0 |
replace_with = 捏造した a copy made for a trial 相当 |
exit 2、inserted text names the run itself: 'trial' |
三件目は (d) の修正が発火していることも同時に示している。
修正軸は指定どおり (b) 由来判定。_matches_existing_file の全文一致を _reject_self_declaring 冒頭の早期 return に置き、正規表現・SELF_DECLARING_SUBSTRINGS の両方より前に位置させている——issue コメントが求めた「日本語側にも同じ判断を当てる」を満たす配置。(c) 明示フラグは採らず、rules/model/subtractive-structural-beauty.md Spec write の二値を守っている。
(d) を同一 PR に入れた判断に同意する。 ガードの根拠になっている実測文言が a copy made for a trial であり、trial が語彙に無かった——自らの存在理由となる実例を捕まえられない語彙だった。(b) の全文一致免除は語彙の中身に依存しないため、分離しても得るものが無い。
逸脱
なし。 scope 逸脱なし、手続き逸脱なし。step 4 の clean 分岐は正しく適用し、リレーせず author も resume せず step 8 で exit している。
rule effect measurement
unmeasured。理由 = 発火条件の外。
skills/evolution-rule-effect-measurement/SKILL.md の発火条件は統治面(rules/** / skills/** / adapter/**)で削除行が追加行を上回る PR である。本 PR の当該面への変更は 0 行(変更ファイルは scripts/measure_rule_effect.py と tests/test_measure_rule_effect.py のみ)。したがって発火せず、走らせないことが正しい。
同 skill は空白を明示的に禁じているため、理由を添えてここに記入する。なお本日の #1927 / #1933 では発火条件を満たしていながらこの記入自体を落としており、両 PR には事後の訂正コメントを入れてある。
ラウンド記録
- N = 1(M = 全 3 軸 / P = 1、既定パターン)
- 往復 = 1。ラウンド 1 が三軸とも所見なしで返ったため step 8 で exit(上限 3 に未達)
- 採用 0 件 / 却下 0 件 / 追加コミットなし。却下されたまま残った所見は無い
- step 2 の運用コピーは適用していない。対象が
scripts/**とtests/**であり、いずれも subagent の常時ロード面に注入されない。評価者は名指しした SHA での直接 Read と、自前クローンでの--dry-run実行で判定している - 固定軸は構造的に空振り(対象行 0)。本 PR は Li+ ソース散文を一行も変更していないため。#1823 が名前を与えている形の再現であり、本 PR の欠陥ではない
リリース種別と merge 判断
patch。scripts/** の内部ハーネス修正であり、アダプタが読む runtime 面の内容を変えず、user/system observable な挙動変化を持たない(rules/operations/release-version-rule.md)。semi_auto の patch は人間ゲート無しで AI 直接 merge。
merge して差し支えないと判断する。
🤖 Generated with Claude Code
Closes #1935
何を直したか
scripts/measure_rule_effect.pyの自己申告ガード(SELF_DECLARING_WORD/SELF_DECLARING_SUBSTRINGS)が、測定・評価層(L2)自身の業務語彙(experiment / variant / test / probe / harness)と衝突し、replace_withに L2 の skill 本文をそのまま挿入できなくなっていた問題を修正した。ガード自体は外していない(根拠はskills/evolution-rule-effect-measurement/SKILL.mdContainment when a file is placed の実測であり、issue もそれを覆さない)。採った修正軸
issue コメントが第一候補とした (b) 由来による分岐 を採用した。
replace_withが編集対象パス(edit.path)にある、リポジトリ内の実在ファイルの現行内容と全文一致する場合、それは run のために書き下ろされた自己申告ではないと判定してガードを通す(_matches_existing_file)。部分一致は通らない——実在文の断片に自己申告を混ぜて忍ばせても弾かれる。load_plan/_load_editsにsource_rootを通し、main()側でsource_rootの解決をload_plan呼び出しより前に移した。source_rootを渡さない既存の直接呼び出し(tests/test_measure_rule_effect.pyのPlanValidationTestなど)は従来どおり語彙のみのガードで動作する(後方互換)。(a) 文単位判定・(c) 明示フラグは issue の判断((a) は (b) で足りる、(c) は
rules/model/subtractive-structural-beauty.mdSpec write の二値に反する)をそのまま踏襲し、採らなかった。(d) への判断
同一 PR で対応した。
SELF_DECLARING_WORDにtrialを追加した。理由: このガードの根拠となった実測例(
skills/evolution-rule-effect-measurement/SKILL.mdContainment when a file is placed)は文字どおりa copy made for a trialであり、trialは改修前の語彙リストに含まれていなかった——ガードの根拠となった実例そのものを、改修前の語彙は捕まえられない状態だった。同じファイル・同じガードに対する低リスクな追加であり、別 issue に切ると根拠側の穴が残ったままになるため、本 PR に含めた。(b) の全文一致は語彙の内容に左右されないため、この決定は受入確認(下記)の結果に影響しない。受入の確認結果(issue の指定どおり実施、
--dry-run)一時ワークスペース(
.claude/skills/...を本リポジトリの現行内容からコピー)を作って実測した。skills/evolution-parallel-agent-eval/SKILL.mdの全文(38,596 B)をreplace_withに置いた plan →--dry-run成功(exit 0、run record 生成)。skills/evolution-rule-effect-measurement/SKILL.mdの全文(19,168 B)をreplace_withに置いた plan →--dry-run成功(exit 0、run record 生成)。this file is a copy made for a trial相当の自己申告文(実在ファイルに一致しない捏造テキスト)を書き足した plan → 引き続き 拒否(measure_rule_effect: inserted text names the run itself: 'trial'、exit 2)。trial追加により、改修前は素通りしていたこの文言も捕まるようになったことを確認した。テスト
tests/test_measure_rule_effect.pyを拡張した(重複ではなく既存クラスへの追記 + 新規SelfDeclaringProvenanceTest)。改修前はガードが実際に発火するケースの直接カバレッジが無かったため、既存語彙経路と今回追加したtrialのケースも合わせて追加した。test_inserted_text_may_not_name_the_run_itselfにa copy made for a trialのケースを追加。SelfDeclaringProvenanceTest: 全文一致で通る/部分一致では通らない/対象パスにファイルが無ければ語彙ガードにフォールバックする/内容が食い違えば全文一致とみなされない、の4ケース。tests/**を変更しているため、本 PR はrules/evolution/initiator-autonomy.mdSelf-evolution PR definition の統治面(brake 1 が検査する対象)に含まれる。ローカルでの実行結果:
tests/test_measure_rule_effect.py51 passed / 16 subtests passed。リポジトリ全体tests/: 241 passed, 777 subtests passed(本変更と無関係な既存テストも含め全て green)。リリース種別
rules/operations/release-version-rule.mdを読んだ上で patch と判定する。根拠: 内部計測ハーネス(scripts/measure_rule_effect.py)へのバグ修正であり、ランタイムで常時ロードされる rules/skills 本文(アダプタが読み込み AI の挙動を左右する面)には触れていない。ユーザー/システムから観測可能な挙動変化はなく、release-version-rule.md の「small fix / internal rule / governance structure change with no user/system observable impact」に該当する。🤖 Generated with Claude Code