実施日:2026-10-19。契約版:p0-draft-2。状態:作成者(AI-001)の単独・内部実施の結果。独立確認前。実行契約 20 に従い、既存の handler に拡張契約の宣言を後付けし、宣言・登録・非干渉・再検証範囲の検査を実装した記録です。実装・契約の振る舞いは変えていません。追加は src/med_dsl/extensions.py、scripts/research/check-extensions.py、extensions/(宣言10件と索引)、tests/p2/(39テスト)で、P0/P1・レビュー系列とは別の分母です。
追記:本書の数値と記述は
25f6cf3時点(P2-a の直後)です。その後、拡張ホストの分離、防護例の追加(防護例のない義務 24 件 → 3 件)、宣言の固定対象への追加を行い、22 に記録しました。このため §1 の「防護例のない義務は24件」、§3-5 の内訳、§3-6 の過大な列挙(handover.pyが 1 モジュール)、§6 の「宣言・tests/p2は固定対象に含まれない」は、その時点の記述です。
1. 到達点
| 項目 | 結果 |
|---|---|
| 宣言の書式 | p2-extension-manifest-draft-1(必須18項目、未知の項目は拒否) |
| 後付けの宣言 | 10件:基底 1、host 1、R1 1(定義追加)、R2 1(有限予測)、R3 2(事象化、参考意味の恒等テンプレート)、R4 1(射影)、R5 2(欠落の診断、可用性の点検)、COMP 1(事象化+改名の鎖) |
| 義務 | 76件。防護例 95件(拒否 70・変換しない 19・境界 6)。防護例のない義務は24件(32%)で、すべて理由つき |
| 証拠の強さ(拡張ごとの最も弱い義務) | checked_native_template 7、finite_check 2(事象化・参考意味)、hand_derivation 1(鎖) |
| 登録 | 10件すべて登録。防護例95件を実際に評価し、宣言どおりの結果を確認 |
| テスト | tests/p2 39件(Python 3.14.4/3.11.17 とも通過) |
| 検査自体の検査 | extensions.py への変異 37件。最初は31件を検出、6件が生き残り(再検証範囲の列挙の規則が他の規則と重なって見えなかった)、人工の木の単体テストを足して37/37 検出 |
| 既存の系列 | 231開発テスト、レビュー系列 52、追加監査 8、P1 20条件・80 JSON・417必須パス(P0 37 JSON・221必須パス)に変化なし。固定対象は 169 → 170 ファイル(extensions.py)、共通 manifest を再固定 |
2. 受入条件の結果
| 条件 | 結果 | 補足 |
|---|---|---|
| X01 欠落の拒否 | 達成 | 必須項目18のすべてについて、欠落を拒否し、登録が変わらないことを確認。書式の不正19種も個別の理由で拒否 |
| X02 名前の衝突 | 達成 | 操作・schema・profile・回答型・述語・能力の6種別と、名前空間の重なりを検査 |
| X03 非干渉 | 達成 | 8つの拡張(予測、事象化、host、鎖、射影、参考意味、欠落の診断、点検)をそれぞれ不活性にし、131例を評価。その拡張と依存先に属さない 70〜128 例の結果は不変、属する例は変わる(無効化が効いている)。表は §3 |
| X06 クラス別の義務 | 達成 | 10拡張×クラス別の必須義務を一つずつ外して拒否を確認 |
| X07 防護例 | 一部達成(設計の文言とは異なる実現) | 設計は「各ゲートに拒否する負例が一つ以上」だった。P2-a は「防護例または理由つきの欠落」に置き換えた。防護例の結果の不一致・実在しない例・理由のない欠落・併存は拒否する。防護例のない義務は24件残る(理由は §3-5)。欠落は既知の一覧に固定し、増減はテストが検出する。24件に拒否例を作る作業は未実施 |
| X13 再検証範囲 | 達成(過大な列挙を含む) | draft-2 の変更(validation.py と P0 契約)から列挙した再生成の対象は10拡張・46ファイルと共通 manifest。git 履歴(e73d4ba→2b501c1)と比べて、(a) 三つの hash の置換だけで変わった p1-c 等の例 27件がすべて含まれる(漏れなし)。(b) 46件のうち e73d4ba に存在した 30件はすべて実際に変わっていた(27件+共通の handover.py・handover_spec.json・p1-c の manifest)。残る 16件(examples/review/ 等)は後から追加された実体で、この履歴では確かめられない。設計の「一致」ではなく、漏れなしと、確認できた範囲での過剰なしの組。再検証する拡張は10件すべてと列挙され、モジュール粒度のため過大になり得る(§3-6)。実際に再検証が要った拡張の範囲は、この履歴では測っていない |
X03 の対象と範囲
| 無効にした拡張 | 属する例(依存先を含む) | 属さない例 |
|---|---|---|
| p1-finite-forecast | 31 | 100 |
| p1-events | 61 | 70 |
| p1-handover-host | 39 | 92 |
| p1-event-chain | 22 | 109 |
| p1-projection | 8 | 123 |
| p1-reference | 6 | 125 |
| p1-absence | 3 | 128 |
| p1-replay | 10 | 121 |
方法:該当の handler を、unsupported_profile で止まる不活性な代用に差し替えて全131例(P0 37+P1 80+レビュー系列 14)を評価し、差し替えなしの結果と正規化 hash で比較する。宣言の誤りを検出できることも確認した:p1-replay が archive の意味引き継ぎで鎖の認定(run_chain)を呼ぶ読み取りを宣言から落とすと、鎖を無効にしたとき replay の例が変わり、検査が破れを報告する(test_an_undeclared_read_is_exposed_by_disabling_the_extension_that_is_read)。
3. 後付けで分かったこと
後付けの作業そのものが、契約の設計を点検した。
-
host という層が要る。 引き継ぎの5操作は、schema・profile・仕様・P0 実体の固定を共有する。操作ごとの宣言だけでは、共有する名前の所有者が決められず、
HOSTクラス(操作を持たない共有の前段)とBASE(基底)を契約に加えた。設計(19)の分類は R1〜R5+合成だった。 -
embedded_inは拡張ごとではなく、pin ごとに和で見る。 events の仕様 hash は、events 自身の宣言と host の宣言の両方で pin される。埋め込み先の漏れは、pin を宣言した拡張すべての和に対して検査する(最初の検査が、host 単独では漏れていると報告して分かった)。 -
名前を組み立てる実装は、名前空間で宣言する。 events は述語の URN を
"urn:med-dsl:events:role:" + 役割で作る。文字列として現れないため、最初はowned_name_not_foundで拒否された。末尾が:の名前を名前空間として所有する規則を加えた。 -
未宣言の読み取りがあった。 最初の宣言で、
p1-replayが鎖の認定を読むことを書き落としていた。コードを読んで気付き、上の非干渉の検査が同じ誤りを検出することを確認して、宣言を直した。宣言は作者の主張なので、検査で突き合わせる仕組みが要ることの実例。 -
防護例のない義務の分布。 24件の内訳は、共通の義務 15件(
K-RES8、K-STOP4、K-INV3)とクラス固有 9件。宣言のguard_gapに書かれた理由で分けると次のとおり。- テストで検査していて、例ファイルがない(12件):予算・上限の境界(
K-RES8、K-STOPのうち 3)と、範囲外の問いで認定が出ないこと(鎖のCOMP-2)。例を作ると境界値の構成が大きい、または乱数照合が担っている。 - 別の防護例またはテストが担う(6件):
K-INV3(認定が定義パッケージだけを読み新しい出力がない、COMP-1の防護例が担う、全例の入力保持をテストで検査)、host のK-STOP(各操作の拒否例が担う)、p0-definitionsのR1-3(R1-1・R1-2・R1-4が担う)、参考意味のR3-4(R3-1の防護例が担う)。 - 構造の性質で、拒否する入力の例がない(3件):事象化の
R3-4(新理論の範囲)、基本予測のR2-2(報告専用の固定 package しか検証に渡さない)、鎖のCOMP-3(この鎖に損失のある段がない)。 - 手作業の導出(1件):事象化の
R3-3(被覆)。反例の検査は参考意味が担い、事象化自身は有限照合だけ。宣言の上で、証拠が弱い義務として見えるようになった。 - 該当なし(2件):参考意味の
R3-5(履歴を持たない)とR3-6(恒等の翻訳で新しい名前を導入しない)。これらは「証拠がない」ではなく、義務が空になる理由を宣言に残したもの。
「別の防護例が担う」「該当なし」の判断は作成者の主張で、独立の確認は受けていない。
- テストで検査していて、例ファイルがない(12件):予算・上限の境界(
-
列挙はモジュールの粒度で過大になる。
handover.py一つに引き継ぎの全操作があるため、events・projection・reference の変更は host とその全操作に及ぶと列挙される(漏れではなく過大)。操作ごとの実装の分離で改善できるが、挙動を変えるリファクタリングなので P2-a では行わなかった。
4. 設計(19)からの変更
| 設計 | 実際 | 理由 |
|---|---|---|
| 後付けは6件(S1/S2、forecast、events、鎖、射影、参考意味) | 10件(基底、host、欠落の診断、可用性の点検を追加) | ディスパッチされる全操作に所有者を決めるため。host は §3-1 |
| 義務の「負例」 | 「防護例」(refusal/non_conversion/boundary) |
「確率1でも supported にしない」など、拒否ではなく変換しないことを守る例を含めるため |
| 拡張ホストの分離を P2-a に含める | 行わない | X03 は、handler の差し替えで実現できた。分離は挙動を変えないリファクタリングで、固定ファイルを広く変え、再固定を要する。宣言と検査を先に固定し、必要は P2-b の前に判断する |
| 証拠の強さ4段階 | 5段階(hand_derivation を finite_check と checked_native_template の間に追加) |
手作業の導出(S1/S2 のモデル拡張、事象化の被覆)を、有限照合と区別するため |
5. 再現
python3 scripts/research/check-extensions.py # 10件を登録し、防護例を評価(--strict で防護例のない義務を失敗扱い、--json で機械可読)
python3 -m unittest discover -s tests/p2 -v # 39テスト
python3 -m unittest discover -s tests -v # 231(従来)
python3 -m unittest discover -s tests/review -v # 52
python3 scripts/research/evaluate-p1-d.py --cli --output data/research/p1-d/p2a # 20条件
変異検査の script とログは data/research/review-001/(Git管理外)の mutrun_p2.py と logs/mutation-p2*.log。
6. 限界と次
- 宣言と検査は、意味の正しさを検査しない(実行契約 20 の §7)。独立の確認者は未割当で、
independent_reviewの主張は拒否される。 - 宣言・
tests/p2・check-extensions.pyは P1-d の固定対象に含まれない(固定対象は 169 → 170 ファイルで、増えたのはsrc/med_dsl/extensions.pyだけ)。宣言の改ざんや取り違えは、固定された hash では検出できない。固定対象に加えるかは P2-b の前に判断する。 - 防護例を実際に評価する登録は、今ある例が宣言どおりの結果を返すことを確かめる。ゲートを壊す実装の変更を検出できるかは別で、
extensions.py自体は変異 37件で確かめたが、既存の handler の防護例が各ゲートの変異を検出するかは、P2-a では測っていない(RV-01 の変異検査は P0/P1 の handler について実施済み。17)。 - X04・X05・X08〜X12・X14 は P2-b 以降。X05(回答型の暗黙変換がない)の機械的な検査は、回答型の宣言と結果の schema の突き合わせが要る。
- 次は P2-b:パイロット「概念の分割」(19 の §7)を、この契約に沿って設計・実装する。最初の作業は、新しい意味(候補集合と情報要求)の宣言を書き、義務を手作業で導くこと。実装に入る前に、利用者の確認を取る。