Skip to content

fix(measure): exempt provenance-verified full-body text from self-declaring guard - #1936

Merged
smileygames merged 1 commit into
mainfrom
1935-measurement-guard-vocabulary
Sep 10, 2026
Merged

smileygames merged 1 commit into
mainfrom
1935-measurement-guard-vocabulary

Conversation

@smileygames

Copy link
Copy Markdown
Member

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.md Containment when a file is placed の実測であり、issue もそれを覆さない)。

採った修正軸

issue コメントが第一候補とした (b) 由来による分岐 を採用した。

replace_with が編集対象パス(edit.path)にある、リポジトリ内の実在ファイルの現行内容と全文一致する場合、それは run のために書き下ろされた自己申告ではないと判定してガードを通す(_matches_existing_file)。部分一致は通らない——実在文の断片に自己申告を混ぜて忍ばせても弾かれる。load_plan / _load_editssource_root を通し、main() 側で source_root の解決を load_plan 呼び出しより前に移した。source_root を渡さない既存の直接呼び出し(tests/test_measure_rule_effect.pyPlanValidationTest など)は従来どおり語彙のみのガードで動作する(後方互換)。

(a) 文単位判定・(c) 明示フラグは issue の判断((a) は (b) で足りる、(c) は rules/model/subtractive-structural-beauty.md Spec write の二値に反する)をそのまま踏襲し、採らなかった。

(d) への判断

同一 PR で対応した。SELF_DECLARING_WORDtrial を追加した。

理由: このガードの根拠となった実測例(skills/evolution-rule-effect-measurement/SKILL.md Containment 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_itselfa copy made for a trial のケースを追加。
  • SelfDeclaringProvenanceTest: 全文一致で通る/部分一致では通らない/対象パスにファイルが無ければ語彙ガードにフォールバックする/内容が食い違えば全文一致とみなされない、の4ケース。

tests/** を変更しているため、本 PR は rules/evolution/initiator-autonomy.md Self-evolution PR definition の統治面(brake 1 が検査する対象)に含まれる。

ローカルでの実行結果: tests/test_measure_rule_effect.py 51 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

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>
@smileygames

Copy link
Copy Markdown
Member Author

Adjudicate each finding below by checking its literal against the source at the revision its path:line is given at, and adopt or drop it on that. No count enters that judgment, and no axis is exempt from it: the fixed impression-literal axis is adjudicated the same way, on the flagged phrase against the removal test its own spec fixes (skills/evolution-impression-literal-detection/SKILL.md), and it fixes no threshold.

Axis A — issue 要件との照合

指摘なし。issue #1935(本文 + コメント1件)を読み、PR #1936 の diff(scripts/measure_rule_effect.py + tests/test_measure_rule_effect.py、SHA e36df43)と突き合わせたが、両者が食い違う箇所は見つからなかった。

確認した対応関係:

  • issue 本文「(b) を第一候補とする。replace_with がリポジトリ内に実在するファイルの全文と一致するなら...ガードを通す」に対し、diff は _matches_existing_filescripts/measure_rule_effect.py:200)で全文一致判定を実装し、_reject_self_declaringscripts/measure_rule_effect.py:221)の冒頭で早期 return として適用している。部分一致は通さない仕様(_matches_existing_file docstring内 "Full match only")も一致。
  • issue コメント「SELF_DECLARING_SUBSTRINGS(日本語側)にも同じ判断を当てること」に対し、_reject_self_declaring の早期 return は正規表現チェックと SELF_DECLARING_SUBSTRINGS ループの両方より前に位置しており(scripts/measure_rule_effect.py:234-239)、日本語側にも同一の免除が及んでいる。
  • issue 本文「(c) は採らない」に対し、diff は明示的な上書きフラグ(--allow-* 等)を追加していない。
  • issue コメント「(d) は独立に確認が要る...同一 PR で扱うか別 issue に切るかを実装側で判断すること」に対し、PR は同一 PR で trial\w* を語彙に追加した(scripts/measure_rule_effect.py diff中の正規表現行)。これは issue が実装側の判断に明示的に委ねた選択の範囲内であり、issue 本文の制約(ガードを外さないこと)にも反しない。
  • issue 本文「制約: ガードそのものを外さないこと」に対し、diff は _reject_self_declaring の呼び出し自体を削除しておらず、既存の語彙チェックは exemption が成立しない限り従来どおり動く。
  • issue コメント「受入の確認方法」に列挙された3ケース(evolution-parallel-agent-eval/SKILL.md 全文で通る/evolution-rule-effect-measurement/SKILL.md 全文で通る/a copy made for a trial 相当は引き続き落ちる)を、独立にクローンした作業ワークスペースで実際に --dry-run を実行して再現した。3件とも PR の主張どおりの結果(前二者は exit 0 で run record 生成、後者は inserted text names the run itself: 'trial' で exit 2)になることを確認した。

Axis B — ルール違反

指摘なし。diff の全変更行(scripts/measure_rule_effect.py の regex 行・関数シグネチャ・docstring・_matches_existing_file_reject_self_declaringmain() 内の呼び出し順変更、および tests/test_measure_rule_effect.py の追加テストケース群)を、SHA e36df43 時点の rules/**skills/** に照らして確認した。

  • rules/evolution/initiator-autonomy.md Self-evolution PR definition(governed surface の定義): tests/** を変更しているため brake 1 の統治面に含まれる、という PR 自身の申告(PR本文末尾)と一致しており、この diff がこのルールの適用範囲判定に反する箇所はない。
  • rules/model/subtractive-structural-beauty.md Spec write(binary only: required か unnecessary か、中間の安全網を置かない): diff は (c) の明示フラグを採用せず、この二値を守っている。
  • skills/evolution-rule-effect-measurement/SKILL.md Containment when a file is placed(trial を含む実測根拠 "a copy made for a trial" の記述元): diff の trial\w* 追加は、このセクションが持つ実測文言と一致しており矛盾しない。
  • リポジトリ全体スイープ: rules/**, skills/**, docs/** に対し正規表現 measure_rule_effect|self.declar|SELF_DECLAR|source_root|_matches_existing_file(大小区別なし)でヒット数を確認。ヒット1件(rules/model/trigger-check-gate.md:38)のみで、内容は本ガードとは無関係な別概念(trigger-check-gate 側の "self-declaration trigger")であり、本 diff を拘束する規範ではない。

Fixed axis — 印象語検出

該当なし。本 diff は rules/** / skills/** を一切変更していない(変更ファイルは scripts/measure_rule_effect.pytests/test_measure_rule_effect.py のみ)。このため、AI がロードして自らの指示として実行する Li+ ソース本文の追加・修正行は 0 行であり、本軸が対象とする文言は存在しない。

@smileygames smileygames left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

親セルフレビュー(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.pytests/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 判断

patchscripts/** の内部ハーネス修正であり、アダプタが読む runtime 面の内容を変えず、user/system observable な挙動変化を持たない(rules/operations/release-version-rule.md)。semi_auto の patch は人間ゲート無しで AI 直接 merge。

merge して差し支えないと判断する。

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(measurement): self-declaring-word guard blocks inserting any L2 spec body, including its own

2 participants