YONAPO RESEARCH
研究記録
MedDSL(仮称)

RESEARCH / RECORD

P2-p:出力先の構造への写像の可否の診断(FHIR R5 Observation への接地)の実装と内部評価

原文 docs/research/69-p2-p-results.md

19 KB

GitHubで見る

版 be280c0

この文書の目次 7項目

作成日:2026-10-21。状態:P2-o の臨床ライブラリを一度だけ実行し、満たされた exchange の行が出力先の構造で、丸めず・閉じず・補わずに表せるかを診断する合成の専用 R5 を実装し、両 Python 版の全体回帰を通過。設計67、手指定期待68、接地の監査66 に従いました(利用者の承認:2026-10-21「推奨案で進めてください」。U1〜U3 は設計67の推奨どおり)。67・68 の「未実装」という記載は設計時点の記録として保持します。独立確認・評価用正解の凍結は未実施で、independent_review / evaluation_frozen は false のままです。数値・単位・property・識別子はすべて架空です。構造の事実だけ、取得した FHIR R5 v5.0.0 のページ(台帳に記録、Git 管理外)の読み取りです。FHIR への適合は主張しません。

1. 行ったこと

項目 内容
実装 structure_grounding.py と native 仕様 structure_grounding_spec.json。P2-o の run_library を子として一度だけ呼び(子の予算は P2-o の全体の料金 M_lib を先払いし、使い切りを照合)、satisfied の exchange の行に、値・期間・文脈の3つの写像の可否を判定する。それ以外の行は P2-o の行のまま通す。構造の事実は仕様の表(出典のページ id・SHA-256・目印の語)に持つ
実行例 examples/p2-grounding/:97 JSON・1,998必須パス(G27・P5・C6・R4・D4・N12・B3条件)。生成器は native を import せず、射影・流れ・料金を手指定する
宣言 p2-structure-grounding.json:R5、17義務(共通4+R5の3+GR-1〜10)、防護例17。証拠は checked_native_template 9・finite_check 8。依存:P2-o。継承は宣言しない
別計算 grounding_oracle.py:基の行は P2-o の別計算を再利用し、有限小数の判定と表記は Decimal の除算が正確に終わるか(モジュールの整数の掛け算とは別の道)、桁数は文字列の長さ、期間の端は datetime、流れの表は手書きで持つ
検査 test_grounding.py 14テスト(手指定・値の格子の全数・期間と文脈の列挙・基の行との差分・丸めず閉じず足さない・出典の結び付き・料金・予算の掃引・子の失敗の原子性・静的検査・型破損・順序と不変性・検査器・変異)
検査器 共通部品 p2_checks.py の未完了行の値の検査に、新しい欄2つ(grounding・base_status)を足した。変異の表に B19 を足し、B17・B18 の対象文字列を更新した(検査器の変異は73件と対照)
台帳 追加で取得した FHIR のページ7件を 台帳 に記録済み(66)。仕様の事実の出典のハッシュは、この台帳と一致する
登録の入口 既存の実装・仕様・宣言・旧実行例は変更していない。変更したのは登録の入口と、手で保つ期待の一覧(W1)

2. 予測の結果(設計67の W1〜W10)

ID 予測 結果
W1 既存の実装・仕様・宣言・旧実行例を一つも変えずに実装できる 成立。既存の src/med_dsl で変更したのは host.py の2行。既存の examples/p2-* と宣言は0件変更(索引に1行追加)。P2-o の実装・仕様・宣言・例は無変更
W2 値の判定は手導出の規則に一致する(分母1〜40の格子の全数) 成立。分子−24〜24・分母1〜40の1,187点×2つの対象と、端の開閉4通りの120区間×2つの対象(計2,614要求)が、別計算(Decimal)と一致。小数で書ける分母は素因数が2・5だけ(独立な素因数分解の判定と一致)
W3 通す行は P2-o の行と一致し、表せる行の P2-o の欄は同一 成立。乱数300要求で、P2-o 単独の実行と比べ、通す行は全欄が同じ。表せる行・表せない行は選択・要素が同じ。表せる行の出力は同じ
W4 規約を宣言しないと半開区間は全て表せない。宣言すると端が1秒戻り、仮定が added に出る 成立。期間の規約3通りの列挙と、すべての半開区間 [day s, day e)(44通り)で確認
W5 区別の損失の数は、運ぶ欄のうち known でない欄の数に等しい。確認と出自は常に失う 成立。method・specimen の3状態×運ぶ欄の5通り×期間の規約3通りの135通りの全数
W6 料金 M = 2 + M_lib + 3N が全要求で成り立つ。P2-o の実費は M_lib 成立。固定例5件の呼び出しの追跡(M=37・42・65・93・108)と、乱数60要求で別計算と一致。実費の不一致は拒否、子の資源停止は全行を原子的に止める
W7 呼び出し側が構造の事実を変えられない。出典の目印が手元のページに存在する 成立。要求に事実の欄がなく(追加すると unknown_field)、仕様の6事実が台帳のハッシュと一致し、手元のページに全ての目印がある
W8 義務は R5 と必須欄で足りる。クラスも書式も増えない。GR-9 は既存の主題に収まらない 成立。クラスも書式も増えなかった。GR-9(外部の資料に結んだ事実)は、A〜H のどれにも置けず、意味固有に置いた(F18)
W9 affected():P2-o の変更が、依存によってこの拡張を列挙する 成立。P2-i・P2-f・P2-j・P2-m・P2-o の変更が及ぶ全ての場合に、この拡張も列挙される(例:measurement.py の変更が及ぶ拡張は6件から7件)。この拡張の変更は他に及ばない
W10 「18桁」の境界の例は、保守側の解釈に依る。例に明記される 成立。G33(先頭の 0 を数えて18桁)と G34(19桁)。ページの記述だけでは数え方を決められないことを例に明記した

3. 反例の結果(設計67の Z1〜Z9)

ID 内容 結果
Z1 2/3 を range へ 小数に丸めず not_decimal_representable(G03・G08・G25)。失うのは exact_value
Z2 半開区間を range へ 端を閉じず open_boundary_not_representable(G22〜G24・G26)。失うのは interval_bounds
Z3 区間を quantity へ 中点に潰さず interval_not_representable_as_quantity(G10・G12・G13)。失うのは interval_width
Z4 桁数 18桁は表せ(G30・G32)、19桁は digits_exceed_limit(G31)。境界(G33・G34)は解釈に依ると明記
Z5 期間の規約 宣言なしは表せず(P01)、宣言すると end を1秒戻し、仮定を added に出す(P02・P06)。表せない行は仮定を足さない(P05)
Z6 unknown と unspecified どちらも不在として運び、区別が落ちたと lost に出す(C01・C02)
Z7 対象のない出力先 not_declared(P2-o の行のまま。D01〜D03)
Z8 line・trend の出力先に対象 静的に拒否(unsupported_grounding_output_kind。N11)
Z9 P2-o が needs_information の行 そのまま通し not_evaluated(依頼は変わらない。R01・R04)。表せない行・評価不能の行も同じ(R02・R03)

4. 分かったこと

  1. 構造の事実を仕様の表に出典のハッシュ付きで持つと、どの事実がどのページの記述に由来するかを辿れる。 ただし、事実の正しさ(ページの記述を私が正しく読んだか)は、同じ作成者の目の検査に限られる。目印の語がページに存在することの検査は、取り違えを防ぐだけで、意味の検証ではない。
  2. 表せない理由を区別して返すと、失う区別を行ごとに残せる。 丸め・閉じる・潰す・補うのどれもせず、理由ごとに exact_value・interval_bounds・interval_width・validity_end を失うものとして返す。
  3. 仮定を足す規約は、呼び出し側が宣言したときだけ使い、足したことを流れに残す。 期間の端の規約(exclusive_end_as_last_second)は秒の粒度の上でだけ正確で、FHIR の dateTime の精度の意味づけは検証していない。
  4. 合成は既存を変えずに足せた。 P2-m の閉包の問題(前段の出力を後段の入力にする不整合)は、この拡張では起きない(出力を入力に戻さない)。
  5. 運べない区別は、ライブラリの出力でなく、出力先の構造の側に原因がある。 確認・出自・文脈の三状態は、取得した Observation のページの要素では運べない(Provenance・拡張は別)。この拡張はそれを lost に残すだけで、運ぶ方法は決めない。

新しい発見

ID 発見 根拠 限界
F17 設計の矛盾を、手指定の期待を書く段階で見つけた。 設計67は「表せる行の流れは P2-o の exchange の流れに差分を足す」としたが、P2-o の流れは quantity_kind と context:property を「保持」とする。この拡張の射影は運ばないので矛盾する。手指定で、射影が運ぶものから作り直す規則(S1)と、流れの項目名の統一(S2)に直した 68 の§0(S1〜S8の8決定) 実装前の決定なので、実行結果に合わせた変更ではない。手指定の段階で見つかったのは、期待を実行の前に書いたことによる
F18 外部の資料に結んだ事実を持つ義務(GR-9)は、A〜H のどれにも収まらない。 三つの拡張で、それぞれ一つの義務が主題の外に出た:P2-m の接続面の閉包(LC-12)、P2-o の要求を宣言として持つこと(CL-9)、P2-p の外部資料に結んだ事実(GR-9)。いずれも意味固有(I)に置いた 各設計の予測(H2)と実装後の割り当て。n=3 主題の分類は作成者による。新しい主題を立てるかは判断(外部の資料・宣言・接続面の三つはまとまらない)
F19 合成の拡張の宣言は、入れ子の要求が埋め込む他の仕様の hash の pin も持つ。 子(P2-o)の要求を包むので、例が P2-i・P2-f の仕様の hash を含む。既存の契約の検査(embedded_in の網羅)が初回に失敗して気づいた。pin を二つ足して解消 test_embedded_in_covers_every_artifact_that_embeds_a_pinned_hash の失敗 手で書く宣言の項目。入れ子が深くなると増える
F20 判定の誤りで無限に回る箇所が、変異を選ぶ段階で見つかった。 有限小数の判定が誤ると、小数の表記の生成が止まらない。入力の上限(256bit)から導いた境界(256桁)で、資源停止にした 変異(素因数3を許す)の設計。注入の検査 境界は入力の上限からの導出で、通常の入力では届かない
F21 新しい拡張を足す手で保つ一覧が、また約11ファイル。 P2-o と同程度(F15)。今回は、継承を宣言しない拡張でも、affected() の列挙の期待(約7箇所)と独立な組の数が変わった 変更したファイルの一覧 一覧は検査が漏れを教える。作業は残る

実装の最中に直した誤り

  • 実装の誤り:0件。97例の手指定の期待は、初回の実行ですべて満たされた。14テストも初回に通過した。
  • 検査側の調整:(1)静的検査のテストの予算の置換に、予算欄そのものの不正を含めていた。範囲外として除いた。(2)C06 を、手指定の段階(実行前)で、変異(順序依存)を検出できる記録に強めた。実行結果を見ての変更ではない。(3)宣言の embedded_in の網羅(F19)。
  • 同値な変更:なし。

5. 検査の強さ

  • 別計算との比較:値の格子(1,187点×2、120区間×2)の全2,614要求、期間の規約と文脈の135通り、36の半開区間、乱数300要求、固定例。別計算は Decimal の除算を使うので、モジュールの整数の掛け算と別の道だが、P2-o の別計算は再利用しており、P2-o と同じ読み違いは共有する。
  • 差分:P2-o 単独の実行との差分(乱数300要求)。丸めず・閉じず・補わないことの性質検査(表せる行の小数を有理数に戻すと元の端と一致する)。
  • 変異:20件。関数の差し替え19件(開いた端の受理、区間を数量へ、桁数の検査の削除、符号を桁に数える、先頭の 0 を数えない、素因数3を許す、規約の黙った使用、仮定の欠落、端を戻さない、区別の損失の欠落、確認・出自の損失の欠落、運ぶ欄の順序依存、low/high の入れ替え、not_declared を表せると言う、不足の行を判定する、先払いの削除、完成料金の削除、推測で補った情報、認定の誤り)と、定数1件(自前の料金)。全件検出(例外で壊れるものも検出に数える)。
  • 検査器の変異:B09・B15・B17・B18・B19 を実行(結果は§6)。
  • 子の呼び出しの注入:P2-o の資源停止(全行を原子的に止める)、実費の不一致、2行目の資源停止(先に完成した行は保持)。いずれも期待どおり。
  • 型破損:要求の全ノード×6種の値で、状態は ok/invalid_input/unsupported_profile/resource_limit のいずれかで例外なし。入力不正は予算に依らず同じ結果。
  • 出典:仕様の6事実が台帳のハッシュと一致。手元のページがあれば、ハッシュと目印の語を照合する(なければ台帳との照合だけ)。

6. 検証

Python 3.14.4 と 3.11.17 で、全テスト系列と統合評価を実行しました。

系列 件数 Python 3.14.4 Python 3.11.17
開発 231 通過 通過
追加レビュー系列 52 通過 通過
保存監査 8 通過 通過
P2 418(P2-oの404に、構造への写像の可否14を追加) 通過 通過
統合評価 P1/P0・拡張・全P2・予算・版比較(2記録) 通過 通過
P1-d の CLI 照合・保存監査・登録検査 P1 20条件・80 JSON・417必須パス、別枠 P0 の37 JSON・221必須パス、監査600+256+32+1 通過 通過
統合評価の対象 P2-p 追加後の分母
登録・義務・防護例 22宣言・295義務・477防護例参照(P2-oの21宣言・278義務・460から、17義務と防護例17を追加)
証拠の強さ checked_native_template 190、finite_check 97、hand_derivation 8
防護例のない義務 既存の3件のまま
独立な拡張の組 175/210(P2-oは158/190)。この拡張は基底を除く他の20件と20組をつくり、依存(推移)で結ばれる3件(P2-o・数量・期間つき数量)を除く17組が独立(手で数えた値と一致)
継承 12項目・証人46・理由つきの欠落2(変更なし。この拡張は継承を宣言しない)
構造への写像の可否の系列 97 JSON・1,998必須パス。他の系列の分母は変更なし
予算 1,347要求・掃引28,345回、違反0(P2-oは1,251要求・24,895回)。掃引の回数は実測で、予測ではない

予測した分母(宣言・義務・防護例・独立な組・継承・要求の数)は、実行の前に手で導いた値が全て一致しました(掃引の回数だけは実測)。旧い22,052件の挙動 digest と、生成器による全例・宣言のバイト一致(追加した生成器を含む)も通過しました。検査器の変異 Z0(対照、失敗0)・B09・B15・B17・B18・B19 は、いずれも検出されました。固定対象に、設計67・期待68・構造への写像の可否の例・検査・別計算・生成器を加えました。作成者 snapshot で、independent_review / evaluation_frozen は false です。

  • 新 native 仕様 hash:構造への写像の可否 cec41a2d…(先頭8桁)。既存の仕様(P2-o 9f9c6363…、数量 f52ea526… ほか)は変更なし
  • 追加前(9e01802、P2-pの設計の追加後):1,510ファイル、manifest d8376bfc…、束 defeef15…
  • 追加後:1,617ファイル、manifest 28e6495c…、束 47191fe4…(この文書の追加で固定対象は変わらない)

7. 限界と次

  • 構造は一つだけ(fhir-r5-observation)で、判定は値・期間・文脈の運び方に限ります。status・code(必須の要素)、値のない記録(dataAbsentReason)、検体の状態、Quantity の comparator、コード化した単位、Provenance への出力、Timing・instant、他の資源は範囲外です。FHIR の資源の生成も、適合の検査もしません。
  • 「18桁」の数え方は、ページの記述だけでは決まらず、保守側の解釈(先頭の 0 を数える)を採りました。FHIR が許す境界とは主張しません。
  • 期間の規約は、ライブラリの時刻が秒の粒度であることに依ります。FHIR の dateTime の精度の意味づけは検証していません。
  • ページを読んだのは作成者一人です。事実の読み違いは、同じ作成者の目の検査(目印の語、台帳のハッシュ)では見つかりません。別計算も P2-o の別計算を再利用しています。独立確認はありません。
  • 医療者の負担が減ることの証明ではありません。 構造への写像の可否を診断する一つの断片です。
  • 次の候補は、status・code の写像と Provenance への出力(取得済みのページで読めるが、判断が要る)、CPC の版の監査、複数の出力先への射影の拡張です。着手前に利用者の確認を取ります。独立確認は将来の英語の別リポジトリで行います。

P2-p

同じ区分の文書