作成日:2026-10-21。状態:期間つき数量(P2-i)の記録の observer を必須にして、不明は明示の値 {kind: unknown} で書かせ、依存する5拡張を再固定・採用し、版の記録と履歴の検査を追加。両 Python 版の全体回帰を通過。設計76・手指定期待77 に従いました(利用者の指示:2026-10-21「項目を必須にする版の更新(旧入力を拒否する)」。設計の確認事項 U1〜U3 は推奨どおり)。76・77 の「実装・版の記録は未作成」という記載は設計時点の記録として保持します。独立確認・評価用正解の凍結は未実施で、independent_review / evaluation_frozen は false のままです。数値・識別子はすべて架空です。外部資料は新たに参照していません。
1. 行ったこと
| 項目 |
内容 |
| P2-i(draft-4) |
temporal_measurement.py↗ と 仕様↗:記録の observer を必須にした。形は `{kind: human |
| P2-o(draft-3) |
操作 record・correct の observer を必須にして台帳へそのまま渡す。ライブラリは欠落を unknown で補わない。確認の操作は観察者を持たない(変更なし) |
| P2-q(draft-3) |
観察者が unknown のとき、観察者を持たない記録と同じに扱う(agent も依頼も流れの変化もなし) |
| 再固定のみ |
P2-j(draft-4)、P2-m・P2-p(draft-3)。根拠をそのまま写す P2-j・P2-m は結果の中に record_observer が現れる |
| 移行 |
生成器の既定の変更:全ての例の記録・操作に observer: {kind: unknown} を足す。手編集なし。期待を個別に変えたのは P2-i の O04(訂正が既定の unknown、元は人)だけ |
| 実行例 |
新しい入力7件:P2-i に O20〜O23(欠落・明示 unknown・unknown に ref・既定)、P2-o に O73・N03-observer-missing・N03-observer-unknown-ref。P2-i 166 JSON・1,796必須パス、P2-o 150 JSON・2,559必須パス |
| 宣言 |
義務を2つ足した(TM-14:観察者は必須で欠落は拒否、CL-14:ライブラリは欠落を補わない)。TM-13・CL-13 は「あるときだけ」から「常に」へ読み替えた。宣言の数は変わらない(23)。6宣言の版と依存の版を更新 |
| 検査 |
P2-i・P2-o・P2-q のテスト(観察者の全数、unknown の扱い、補完しないこと)、変異、別計算(P2-q)の更新。版の記録の履歴の検査(test_required_observer_version.py↗:比較器の単位テスト5、履歴の検査9) |
| 版の記録 |
p2-temporal-measurement-draft-3-to-draft-4.json↗(p2-version-record-draft-2)。生成は make_required_observer_version_record.py↗ |
| 比較器 |
p2_checks.py↗ に宣言の種類 required_field(request_leaf・result_leaf・substitution_refusal)を足した。変更は26行の追加と5行の削除。書式 p2-version-record-draft-2 は変えていない |
旧版は、変更前のコミット ab4c358(P2-r の結果の追加後)として履歴に残ります。新版の実装は fe420cb、実装の誤りの修正は c586272(§4)、版の記録は b3c7e45(記録は自身を含む木のコミットを指せないため、別のコミット)。
2. 予測の結果(設計76の S1〜S10)
| ID |
予測 |
結果 |
| S1 |
旧版 ab4c358 は旧コミットの木で再現できる(23宣言・316義務・498防護例) |
成立。旧コミットの木で統合評価が合格し、23宣言・316義務・498防護例、manifest 4aa13b97…・束 4861a082… を再現 |
| S2 |
旧入力を新版へそのまま渡すと、pin を持つ入力は profile_spec_mismatch で拒否され、他は同一。黙った再解釈は 0 |
成立。旧入力762件のうち、拒否703・同一59・変更0。拒否の状態と理由は全て unsupported_profile/profile_spec_mismatch |
| S3 |
旧い pin を新しい値へ置換した入力は、全て missing_field で拒否され、受理は 0(P2-r で置換だけで再固定できた3系列も) |
成立。6系列×先頭3件の18件が全て invalid_input/missing_field。受理 0 |
| S4 |
移行した入力は、旧入力と hash の値・宣言した observer の追加を除いて同一。期待は record_observer を確かめる少数の例を除いて同一。料金は変わらない |
成立。要求が変わった入力733件は全て observer の追加(と hash の値)だけ。期待が変わった102件は observer を含む写しと、個別に決めた O04 だけ。料金が変わった入力 0。追加は宣言した7件(旧762、新769) |
| S5 |
旧入力の結果と移行した入力の結果の違いは、根拠の record_observer の追加だけ |
一部成立(初回は外れ、直して成立)。(1) 初回の測定で、O12(人の観察者に ref がない)の error_path が record.observer から record.observer.ref に変わっていた(実装の副作用。§4)。入れ物のパスに直して、この違いは 0。(2) 予測外:結果の違いは record_observer だけでなく、結果が要求の原情報を写す retained_source の observer にもある。違う405件の内訳は、record_observer だけ129・写しの observer だけ83・両方193 |
| S6 |
要求の側の変更は P2-r の比較器では宣言できず、宣言の種類 required_field と小さな拡張が要る |
成立。required_field の宣言がない記録では、移行が宣言にない要求の変更として報告される(test_a_record_without_the_declaration_keeps_the_stricter_old_behaviour)。拡張は p2_checks.py の26行の追加と5行の削除で、書式は不変 |
| S7 |
書き換わるファイルは800〜860 |
成立。820ファイル(P2-r は813、P2-l は739) |
| S8 |
affected() は6拡張を過不足なく列挙する。過小は P2-r と同じ9件。過大は100〜130件 |
成立(過大は下限)。6拡張は過不足なし。過小は予測と完全に一致(宣言6件とモジュール3件)。過大は100件(P2-r は118) |
| S9 |
unknown を含む入力は、旧版の木で invalid_observer により拒否される。人・機器の観察者だけの入力は、旧い pin に替えれば旧版が受理する |
一部成立(拒否の理由が外れ)。新版の入力765件を旧い pin で旧版へ渡すと、unknown を含む734件は受理 0(未知の値を黙って受理しない)。だが拒否の理由は invalid_observer が2件だけで、585件は missing_field、147件は観察者の検査より前の理由(pin・形・予算など)。旧版は ref の有無を kind の値より先に検査するため。受理は8件:人・機器の観察者だけの入力7件と、新版が拒否する N03-observer-missing(旧版は受理) |
| S10 |
P2-q の unknown は依頼・agent・流れを変えない:移行後の P2-q の結果は selection.record_observer を除いて同じ |
成立。P2-q の例の結果の違いは record_observer と写しの observer だけ(§2 の S5 の内訳)。別計算の全数(観察者〔既定の unknown・human・device〕×出自×型の宣言×Provenance の宣言)と一致し、別計算は unknown を観察者のない場合と同じに扱う |
3. 反例の結果(設計76の W1〜W8)
| ID |
内容 |
結果 |
| W1 |
記録に observer がない(台帳) |
invalid_input/missing_field(P2-i の O20)。補完しない |
| W2 |
操作に observer がない(ライブラリ) |
invalid_input/missing_field(P2-o の N03-observer-missing)。補完しない |
| W3 |
unknown に ref/human に ref がない |
前者は unknown_field(O22、N03-observer-unknown-ref)、後者は missing_field(O12) |
| W4 |
P2-r の時点で有効だった入力を、pin だけ新しくして渡す |
18件全て missing_field で拒否。受理 0(S3) |
| W5 |
unknown の記録の確認 |
確認は有効。unknown も内容の一部として hash に含まれ、観察者を書き換えると確認は合わない(P2-i の全数と O05) |
| W6 |
訂正が unknown、元の記録は人 |
選ばれた訂正の record_observer は unknown。元の観察者を継がない(O04) |
| W7 |
P2-q:unknown の観察者で Provenance を宣言 |
生成の agent は AI の1件だけ(観察者の agent を足さない)。依頼も流れの変化もなし |
| W8 |
新版の入力を旧版へ |
unknown を含む734件は拒否、受理されるのは unknown を含まない8件(S9) |
4. 実装の最中に見つかった誤りと直し方
- 版の記録の作成が止まった(実装の副作用):版の記録の作成器が、宣言にない結果の差として
p2-temporal-measurement/o12.json の error_path を報告した。ref を条件つきの必須にした新しい検査が、欠落を record.observer.ref と報告していたが、旧版と他の検査(fields())は入れ物の record.observer を報告する。理由と状態は同じ(invalid_input/missing_field)で、期待は経路を固定していなかったため、テストでは見つからなかった。比較器が設計の宣言(observer の必須化)と無関係な診断の変化を見つけた例。新しい検査の報告を入れ物のパスに直した(c586272)。経路を宣言に足して許容する選択もあったが、意図した変更でなく、旧版との一致を保つほうが小さい変更だったため、実装の側を直した。この直しの後で版の記録を作った。
- 履歴の検査の期待の誤り:S9 の「拒否は
invalid_observer、拒否が受理より多い」を履歴の検査に書いていたため、測定(invalid_observer 2件)と合わなかった。検査を、予測でなく成り立つ性質(unknown を含む入力の受理 0、受理は unknown を含まない入力だけ、unknown を含む入力は受理より多い)に直し、理由の分布を版の記録の測定値に加えた(unknown_observer_first_reason)。予測の外れは §2 に残した。
- 実装の誤り:上の1件のみ。設計77の手指定の期待(O20〜O23、O73、N03 の2件、O04 の変更)は、最終の例の期待と一致している(文書の値と例の期待を突き合わせた)。ただし 76・77 は実装と同じコミット(
fe420cb)で履歴に入れたため、「実装前に固定した」ことは履歴からは示せない。
5. 分かったこと
- 任意の項目を必須にする更新でも、意味の局所性は保たれた。 旧入力762件は黙って再解釈されず(拒否703・同一59・変更0)、旧い pin を置換しただけの入力は18件全て欠落した必須項目で拒否された。移行は「欠落に明示の
unknown を足す」だけで、期待を個別に変えたのは1例(O04)だった。一方、書き換わったファイルは820件と、任意の項目を足したとき(P2-r の813件)とほぼ同じ規模だった。
- 必須にすることは、答えの強制でなく、「聞いたが分からない」と「聞いていない」を分けることだった。
unknown は観察者を推測せず、Provenance の agent・依頼・流れを変えない。ただし unknown の細分(聞いていない/聞いたが分からない)は扱っていない。
- 比較器は、要求の側の変更を小さな拡張で宣言でき、宣言にない差も見つけた。 宣言の種類
required_field の追加は26行で、書式は不変。移行の差を許す一方で、宣言にない error_path の変化を失敗にした(§4)。
新しい発見
| ID |
発見 |
根拠 |
限界 |
| F31 |
意味の変更を宣言する比較器は、意図しない診断の変化も見つける。 宣言した項目(observer・record_observer)以外の結果の差を失敗にするので、必須化の副作用の error_path の変化(理由・状態は同じ)が見つかった。手指定の期待が経路を固定していなければ、テストでは見つからない種類の変化 |
p2-temporal-measurement/o12.json の /error_path。c586272 |
宣言した名前の項目は、経路を問わず許容する(F32) |
| F32 |
宣言の照合は項目の名前(経路の末尾)で行うので粗い。 結果が要求の原情報を写す retained_source の observer も、根拠の record_observer も、同じ宣言で許される。無関係な場所に同名の項目が増えても許容される |
比較器の only_declared_leaves。405件の内訳(写しだけ83・根拠だけ129・両方193) |
経路全体の宣言は書いていない。写しと根拠を分けて宣言する拡張は未実施 |
| F33 |
確認は仕様の版に結ばれるので、新旧の互換の部分集合は小さい。 台帳を直接持つ入力(P2-i・P2-j・P2-m)の確認は、記録の hash に仕様の hash を含むため、観察者の項目と無関係でも別の版では review_record_hash_mismatch で拒否される。旧版へ渡した765件のうち、旧版が受理するのは8件だけ。操作から台帳を組み立てる P2-o の入力は hash を持たないので、この拒否を受けない |
前方の測定(受理8、unknown を含む入力の受理 0)。P2-i の O01 など4件が観察者以外の理由(確認の hash)で拒否 |
互換は、確認を使わない入力に限る。確認を版をまたいで引き継ぐ規則はない(既存の規則どおり) |
| F34 |
旧版の拒否の理由は、旧版の検査の順序で決まる。 旧版は ref の有無(missing_field)を kind の値の検査より先に行うため、新しい値 unknown は invalid_observer でなく missing_field で拒否された。値の追加が旧版でどの理由になるかは、旧版の実装を見ないと予測できない |
S9 の外れ(invalid_observer 2件、missing_field 585件) |
拒否されること自体(受理 0)は旧版の検査の順序によらず成り立つか、は別の問い(旧版の別の実装では確かめていない) |
6. 検査の強さ
- 観察者の必須化:P2-i の全数(観察者 欠落/
unknown/human/device × 訂正の鎖の2記録、記録の hash が観察者ごとに異なること)、不正な観察者の全数、確認の後の書き換え。P2-o の受け渡しの全数(操作の観察者 欠落/unknown/human/device × 確認の操作の観察者)。P2-q の全数。いずれも別計算または独立な計算と比べた。
- 変異(テストに組み込んだもの):P2-i は、観察者の種類の検査の削除、
record_observer を出さない、unknown に ref を許す、の3件(種類の検査は unknown を含む形に更新)。P2-o は、台帳へ渡さず unknown で置き換える(補完に当たる)、根拠に出さない、の2件。全件検出。
- 変異(設計77の§6のうち、テストには組み込んでいないもの):使い捨ての作業木で一度だけ試した。(1) 欠落を
unknown で補う(P2-i)、(2) unknown を ref が必要な種類と同じに扱う(P2-i)、(3) P2-q が unknown を観察者のない場合として正規化する行の削除、(4) 確認の操作が任意の observer を受理する(P2-o)。いずれも既存のテストが失敗して検出した((3) は多くのテストが ref の参照で異常終了するという粗い検出)。コミットした検査ではないので、再現するには変異を手で当てる。設計の「unknown で依頼を出す」変異は試していない。
- 版の手順:V1〜V8 を履歴の検査9テストで確認した。比較器の単位テスト5は、宣言どおりの報告が通ること、宣言外の要求・期待・結果の差と、置換の拒否の理由の食い違いが報告されること、宣言のない記録が従来どおり厳しいことを確かめる。
- 比較器の変異:G01〜G05・G10・G15・G16 と対照 Z0 を再実行(比較器を変えたため)。全件検出、対照は失敗0。
7. 検証
Python 3.14.4 と 3.11.17 で、全テスト系列と統合評価を実行しました(版の記録を加えた木 b3c7e45 で実行)。
| 系列 |
件数 |
Python 3.14.4 |
Python 3.11.17 |
| 開発 |
231 |
通過 |
通過 |
| 追加レビュー系列 |
52 |
通過 |
通過 |
| 保存監査 |
8 |
通過 |
通過 |
| P2 |
460(P2-r の444に、P2-s のテストと版の履歴の検査〔比較器の単位テスト5、履歴9〕などを追加)。スキップなし |
通過 |
通過 |
| 統合評価 |
P1/P0・拡張・全P2・予算・版比較(3記録)。版の記録を加えた後の履歴の検査も通過 |
通過 |
通過 |
| P1-d の CLI 照合・保存監査・登録検査 |
P1 20条件・80 JSON・417必須パス、別枠 P0 の37 JSON・221必須パス、監査600+256+32+1、登録23/拒否0 |
通過 |
通過 |
| 統合評価の対象 |
P2-s 追加後の分母 |
| 登録・義務・防護例 |
23宣言・318義務・500防護例参照(P2-r の316・498から、2義務と防護例2を追加)。宣言の数は変わらない。防護例のない義務は3(変更なし) |
| 証拠の強さ |
checked_native_template 201、finite_check 109、hand_derivation 8 |
| 独立な拡張の組 |
192/231(変更なし) |
| 実行例の系列 |
P2-i 166 JSON・1,796必須パス(+4、+39)、P2-o 150・2,559(+3、+32)。他は変更なし |
| 予算 |
1,453要求・掃引31,198回、違反0(P2-r は1,446要求・31,113回)。掃引の回数は実測で、予測ではない。両 Python 版で一致 |
予測した分母(義務・防護例・要求の数)は、実行の前に手で導いた値が一致しました(掃引の回数だけは実測)。旧い挙動 digest の回帰と、生成器による全例・宣言のバイト一致の検査は P2 系列に含まれ、通過しました。固定対象に、設計76・期待77・版の記録・検査・道具を加えました。作成者 snapshot で、independent_review / evaluation_frozen は false です。
- 新 native 仕様 hash(先頭8桁):P2-i
5de7893a…(draft-3 は 168e9f87…)、P2-j 65550ac5…(旧 d1673a14…)、P2-m bd782f9c…(旧 8e84f905…)、P2-o 58abe63f…(旧 bb87cc22…)、P2-p 34f88aa6…(旧 3f8527fb…)、P2-q 062efe75…(旧 422285b0…)。数量の仕様 f52ea526… は変更なし
- 追加前(
ab4c358、P2-r の結果の追加後):1,732ファイル、manifest 4aa13b97…、束 4861a082…
- 追加後:実装の木(
fe420cb)は1,743ファイル、manifest e0aaae42…、束 9094f15b…。誤りの修正の木(c586272)は1,743ファイル、manifest e458292b…、束 2c368451…。版の記録を加えた木(b3c7e45)は1,744ファイル、manifest 0bbefd61…、束 4b4b83d4…(完全な値は各コミットの examples/p1-evaluation/manifest.json)。この文書と概要文書の更新で固定対象は変わらない(再スナップしても同じ manifest)
8. 限界と次
- 必須にする更新は、1つの項目(
observer)の1回の実演です。項目の意味の変更、削除、複数の項目の同時の更新は試していません。
- 移行は有限の旧入力(762件)と生成器の既定の変更に基づきます。旧入力が行使しない新版の変更は旧入力の比較では見えません。一般の移行の正しさの証明ではありません。
unknown は「観察者が分からない」の一つの値で、聞いていない・聞いたが分からない、の細分、観察者の同一性・資格・履歴は扱いません。補完の層(画面など)も範囲外です。
- 比較器の宣言の照合は項目の名前で行い、粗い(F32)。
- 設計者・実装者・検査の作成者が同一で、独立確認はありません。
- 次の候補は、revision の entity と activity の符号、CPC の版の監査、複数の出力先への射影の拡張です。着手前に利用者の確認を取ります。独立確認は将来の英語の別リポジトリで行います。