P04-01: 同時発生の更新規約
This commit is contained in:
@@ -1,5 +1,120 @@
|
||||
# 初期監査の検証器
|
||||
|
||||
## repair6 現在値(2026-10-16)
|
||||
|
||||
旧値: C全体は `native ordering bytes` によりblocked、実applicabilityは拒否、
|
||||
whole native未確認。以下の「今回のPython確認と入力不整合」は旧bundleの履歴。
|
||||
新値: 補正済み `build_dir/audit-support/native-first-current/` に対し
|
||||
verify_native、ownership/save/ledger個別検査、applicabilityが成功した。
|
||||
checker_native_fixtures.py、checker_negative_fixtures.py、
|
||||
checker_applicability_fixtures.py --native-bundle は各1回実行しexit 0。
|
||||
旧23負例と新2負例(signature行だけのSHA、後続コメントを除いたSHA)を全て拒否。
|
||||
既存fixture14件も拒否、A/Bの登録版・production版・行移動正対照成功、3負例拒否。
|
||||
正規bundleを合成補正せず検査し、結果・旧値・新版SHAはc-native-validation.jsonに保存。
|
||||
全文rawの `old == new` および
|
||||
`sha256(new[function]) == production_body_sha256 == registered_body_sha256` が必須。
|
||||
whole gateは未実行。原15条件+EV、7領域、安全性3結果、30/88の分母、予算、
|
||||
repair上限は変更せず、formal_original_credit=0。正式受入はRunner・独立レビュー・
|
||||
オーナー判断待ち。以下の旧blocked記述を現在のC検査結果として扱わない。
|
||||
|
||||
## C段階追補(本節がrepair4以前の状態説明に優先)
|
||||
|
||||
`verify_native(base)` は供給済み `native-first-current` 形式の有限adapter。
|
||||
Rootのprobe/Reader/wrapperは起動・再実装しない。A/B、verify、coverage、
|
||||
boundary_conditions、15条件、reachable EV、7領域、3安全性結果は維持する。
|
||||
既存scalar検査は宣言の整合性検査として残すが、これだけでは成功しない。
|
||||
|
||||
whole gateのindexには追加で `native_bundle` が必要。
|
||||
`manifest` は evidence directory相対の `OWNERSHIP_RAW_PROVENANCE.json`、
|
||||
`sha256` はその実SHA。manifestの親をbundle rootとして以下を照合する。
|
||||
絶対パス・親参照・symlinkは既存safe規則で拒否する。
|
||||
native production_commitはtested HEADと一致させる。別版資料をA/Bの一致だけで
|
||||
流用しない。今回のproduction版とworker checkoutは区別したまま保持する。
|
||||
|
||||
1. SOURCE_MANIFESTの76 fileとOWNERSHIP_RAW_PROVENANCEの96 fileは、
|
||||
各bytesとSHAを実体から再計算する。由来のsource絶対パスは開かない。
|
||||
3 runのimport/parse/repro、formalのwriter/reader、合計10プロセスは
|
||||
started→process→endedのPID、owner、argv、時刻順、実終了codeを照合する。
|
||||
execution・phase receipt・actual phase・cleanupのPID集合と埋込記録も一致必須。
|
||||
stdout/stderr/native logのSHA、通常終了、cleanupのwait結果とerrors空を要求する。
|
||||
Writer/Readerは別PID・別profileで、profile receipt・環境・5 slotのパスも結合する。
|
||||
2. production_commitは3結果資料とapplicabilityで一致し、specの6登録pinと
|
||||
production Git blobから計算した6 current pinを区別する。各runのsource_beforeと
|
||||
selected_source_mapにも結合する。20関数は既存A/Bと同じ全文raw比較を行う。
|
||||
後続トップレベルdoc commentを含む抽出全文rawのSHAだけを許可する。
|
||||
signature行のみ、コメント除外prefix等の候補は許可しない。
|
||||
3. `observations.json` の5点と対応 `midnight-*.json` を結合する。
|
||||
receiptはtransaction IDを一意にし、row重複を拒否し、順序・多重度を保持した
|
||||
台帳差分との完全一致を要求する。Readerの生receipt、first/replayも同じ行に結合する。
|
||||
SERVICE_SALEにservice_idを要求しない。after snapshotの
|
||||
`/systems/runtime/economy/idempotency` の `service.payment.<service_id>` から
|
||||
transaction_idを得て、sale・guest wallet・facility revenue・cash sweepを結合する。
|
||||
固定のPID・価格・transaction番号を使わない。元価格と時間はproduction Gitの
|
||||
facility .tres、run inputのpin、初期facility/service/requestと照合する。
|
||||
PAUSEDはstateに加え `interruption_reason=RELATED_FACILITY_INACTIVE` を要求し、
|
||||
進捗・service ID・予約IDを保持、売上0、財布差分0を再計算する。
|
||||
request存在系列、予約requester/facility/ACTIVE→CONSUMED、復帰1回課金を照合する。
|
||||
最後のGuest despawn時は残存台帳から財布を再計算し、Guest辞書の存在を偽定しない。
|
||||
maintenanceは同一transaction・施設・金額のaccrual/paymentを対にする。
|
||||
発生1439と支払い1440は同分扱いせず、観測したmidnightとその直前として照合する。
|
||||
4. 正式保存は5点×4member×writer/reader=40実ファイルを照合する。
|
||||
execution.formal_before/afterの20 member map一致と実SHA/bytes一致を要求する。
|
||||
typed 14件はwriter-persisted 5、reader-loaded 5、reader-replayed 4(before以外)。
|
||||
原order-evidence .varおよびrun固定input pinと実SHAを照合する。
|
||||
.var decodeは行わず、値の判定はnative JSON receipt/stateを根拠とする。
|
||||
|
||||
このadapterが返す条件はdependency_stop/recovery_completion/paused_midnightの
|
||||
有限系列だけ。正式保存member同一性は、全save_restore条件達成を意味しない。
|
||||
whole gateは固定15条件+EVとこの結果の差集合を未収集としてfailする。
|
||||
非ゼロ給与×シフト交代×00:00、command再送、停電→閉店同Tick、退出/予約解放、
|
||||
破壊、EV等をscalar=trueで埋めることはできない。原条件の加点は常に0。
|
||||
|
||||
### 今回のPython確認と入力不整合
|
||||
|
||||
供給rawのownership/save/ledger個別検査は成功。applicability資料は
|
||||
`native ordering bytes` で拒否する。4関数のbody SHAが複数行シグネチャの
|
||||
途中までしか含まないためで、詳細はEVIDENCE_COLLECTION.mdに記録した。
|
||||
実raw全体を合格とは報告しない。
|
||||
|
||||
checker_native_fixtures.pyはallowed_paths内の一時コピーで23負例を検査する。
|
||||
通常の負例ではmanifest SHAも再計算し、hashだけを理由とする失敗を避ける。
|
||||
1byte改竄、member欠落、PID/profile同一化、ended異常、cleanup欠落、
|
||||
receipt二重化/削除、PAUSED売上、予約孤立、財布差分、idempotency誤結合、
|
||||
commit/pin不一致、typed/member変更、scalar自己申告を全て拒否する。
|
||||
PAUSED売上と予約孤立にはJSON側も同時変更する対抗例を含む。
|
||||
一時コピーのapplicabilityのみGit全文hashへ差し替えた合成正対照はあるが、
|
||||
これを正規native証拠として保存・採用しない。
|
||||
|
||||
旧synthetic_controlはnative rawを持たないため現在はexit 1が正しい。
|
||||
既存13負例も維持し、全14件を拒否。A/Bの正対照と3負例も維持する。
|
||||
本番の未収集indexに対する重複validateは行わない。
|
||||
|
||||
## repair4差分(未完成・blocked)
|
||||
|
||||
今回のA/B実装では、以下の旧説明の「6不変pin=実checkout」および
|
||||
reachabilityのstart/end/text形式を置き換えた。詳細と未供給入力は
|
||||
`EVIDENCE_COLLECTION.md` を参照。Cのowned_outer/raw台帳結合とD/Eの残項目が
|
||||
未完成のため、このcheckerを正式受入には使用しない。
|
||||
|
||||
- `registered_pins` はspec.current_source_pinsと一致し、登録Git blob SHAをcheckerが再計算する。
|
||||
- `versions` はexecution_origin(9767b0aの完全SHA)、registered(deb1bcbの完全SHA)、
|
||||
tested(HEAD)、integration(null)の4キー。candidate_commitもHEADを維持。
|
||||
- `applicability_delta` は登録版..HEADのautoload/scriptsのGD変更関数の
|
||||
path/function配列。checkerの計算順と完全一致。`delta_cases` は
|
||||
`path:function` → 条件ID → engine case ID。条件集合はchecker内固定の保守的判定。
|
||||
- 全autoload/scripts GDがsource_map必須で、実checkoutとHEADのraw一致も必須。
|
||||
- reachability.source_refsはpath/sha256/function/anchor_sha256/line_count。
|
||||
絶対行位置は使用せず、関数内のraw本文アンカーを一意に解決する。
|
||||
- 20順序関数は固定抽出規則で登録Git blobとtestedをraw比較する。
|
||||
|
||||
Python確認結果: 既存合成正対照1件exit 0、負例13件exit 1。
|
||||
別のA/B対照は登録=testedと実production Git blobの合法delta(25変更単位)の
|
||||
2件成功、両版で+7行のアンカー解決成功、delta欠落/境界case欠落/版誤表示の
|
||||
3負例を拒否した。全てengine証拠ではなくPython検証のみ。
|
||||
owned/count/restore/別候補receipt流用の新負例は未実装であり、上記に含めない。
|
||||
|
||||
以下はrepair3時点の記録。置換対象以外もC修正完了の証明として扱わない。
|
||||
|
||||
`python3 tools/check_p04_order_evidence.py --verify-only` は環境変数 `BUILD_OUTPUT_DIR` の `p04-evidence/index.json` を読み、書込み・試験・Runner操作をしない。欠落時は非0。原30/88の受入・完了を確定しない。
|
||||
|
||||
D05-P04-DEPENDENCYとD05-P04-SHIFT-1800は承認済み。固定必須条件と証拠が揃えばmachine_verified=true、formal_acceptance=false、exit 0。残るD05の帰属pendingを一括failにしない。必須authority pending・証拠欠落は非0。独立レビュー・通常統合までは正式受入0。
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
# P04-01: C段階の結合とrepair4収集契約の履歴
|
||||
|
||||
## repair6 現在値(2026-10-16、以下の旧blocked記述に優先)
|
||||
|
||||
旧値: 実applicabilityは `native ordering bytes` で拒否、C全体blocked、
|
||||
whole native未確認。新値: 補正済みbundleのverify_native成功、
|
||||
ownership/save/ledger個別検査とapplicability成功。供給bundleへの書込みは0。
|
||||
全文rawの登録版/production一致と両body SHAの全文SHA一致だけを認める。
|
||||
後続コメント除外prefixを許す暫定処理は削除した。
|
||||
|
||||
下記3本のPythonコマンドを各1回実行しexit 0を確認。
|
||||
native fixtureは既存23負例+signature行SHA/コメント除外SHAの2負例を全て拒否。
|
||||
合成補正コピーは廃止し、補正済み供給rawをそのまま正対照に使用。
|
||||
既存fixture14件拒否、A/Bの登録版・production版・行移動正対照成功、3負例拒否、
|
||||
native applicability成功。実行結果、旧検査値、新旧bundle pin、検査コードSHAは
|
||||
c-native-validation.jsonに記録。verify_nativeは有限C検査でありwhole gateは未実行。
|
||||
原未達の条件、formal_original_credit=0、15条件+EV/7領域/安全性3結果、
|
||||
30/88の分母、予算、repair上限を維持する。Root追加paid/再送は今回の範囲外。
|
||||
engine、全回帰、製品、Runner、config、DB、git書込み、他agentは全て0。
|
||||
正式検証・独立レビュー・オーナー判断待ち。以下の「今回」は旧検査履歴を指す。
|
||||
|
||||
## C段階の追補対象
|
||||
|
||||
供給rawの現在位置は `build_dir/audit-support/native-first-current/`。
|
||||
所有権、台帳・service・予約、正式保存の結合を追加する対象であり、
|
||||
この資料の存在だけでは原受入を満たさない。formal_original_creditは0を維持する。
|
||||
|
||||
## 今回のC実装と入力blocker
|
||||
|
||||
変更はchecker、Python fixtureと本ディレクトリ内のdocsだけ。
|
||||
Root helperはコピー・再実装せず、既存native成果物を読む。
|
||||
結合の正確な規則はCHECKER_PROTOCOL.mdのC追補を参照。
|
||||
新規engine/全回帰/Runner操作/git書込み/他agent起動は全て0。
|
||||
旧39rawを読了・採用した数も0。repair4-context.jsonの旧履歴は保持した。
|
||||
|
||||
供給rawでは次の個別Python検査が成功した。
|
||||
|
||||
- OWNERSHIP_RAW_PROVENANCEの96 fileのbytes/SHAと10プロセスのlifecycle/cleanup。
|
||||
- Writer/Readerの5点×4member、元20member不変、typed .var 14件の実SHA結合。
|
||||
- 生receipt 8行、service.paymentのidempotency経由での1回課金、財布差分、
|
||||
PAUSED時の進捗・予約保持、復帰後の消費、維持費発生1439→支払い1440。
|
||||
|
||||
ただし `POST_P18_CURRENT_SOURCE_APPLICABILITY.json` の4関数の
|
||||
registered_body_sha256/production_body_sha256は本文を含まない。
|
||||
実Git blobで検算すると、以下の関数先頭からのprefix SHAに一致した。
|
||||
|
||||
| path | function | hash対象のbyte数(本文を含まない) |
|
||||
|---|---|---:|
|
||||
| autoload/simulation_runtime.gd | _complete_service_transaction | 140 |
|
||||
| scripts/facility/facility_service.gd | _prepare_service_for_tick | 87 |
|
||||
| scripts/facility/facility_service.gd | _complete_service | 113 |
|
||||
| scripts/facility/facility_service.gd | _fail_service | 119 |
|
||||
|
||||
4つとも複数行引数の後の `) -> ...` より前で終わる。全文比較は別途成立するが、
|
||||
報告されたbody hashとの一致は成立しないため、実bundleは
|
||||
`native ordering bytes` でfailする。workerはこの供給資料もmanifestも変更していない。
|
||||
Root側で同じproduction Git blobの全文を対象にapplicabilityとそのmanifestを
|
||||
再生成する必要がある。engineの再起動を必要とする不整合ではない。
|
||||
旧暫定処理では後続トップレベルdoc commentの有無だけの2関数差をraw prefix一致
|
||||
として扱っていた。repair6で撤去し、現在は全文SHA一致のみ必須とする。
|
||||
|
||||
この入力不整合が残るため、C段階の実raw全体の成功は未確認(blocked)。
|
||||
これは原P04-01未達とは別のblockerであり、修正済みの合成コピーで全C検査が
|
||||
通ることを原証拠の合格へ換算しない。
|
||||
|
||||
## 有限の検証
|
||||
|
||||
実行したのは次のPython確認のみ。全て一時ファイルをallowed_paths内へ限定し削除する。
|
||||
|
||||
```sh
|
||||
python3 -B docs/plans/original-completion-2026-10-02/execution/p04-01/checker_native_fixtures.py /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/native-first-current
|
||||
python3 -B docs/plans/original-completion-2026-10-02/execution/p04-01/checker_negative_fixtures.py
|
||||
python3 -B docs/plans/original-completion-2026-10-02/execution/p04-01/checker_applicability_fixtures.py --native-bundle /Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build/audit-support/native-first-current
|
||||
```
|
||||
|
||||
Cの結果は `c-native-validation.json`。23負例を拒否し、実rawの3個別検査成功、
|
||||
実applicability拒否、修正した合成applicabilityの組合せ正対照成功を区別する。
|
||||
既存fixtureはscalarのみの旧正対照を含む14件を拒否。
|
||||
A/Bは登録版・production版の正対照と行移動の正対照、3負例、C資料の拒否を確認した。
|
||||
未収集indexに対するwhole gate/validateは再実行していない。
|
||||
|
||||
## 固定の原未達
|
||||
|
||||
非ゼロ給与のシフト交代×00:00、command再送、停電→閉店同Tick、退出/予約孤立、
|
||||
破壊、EVは未収集。正式保存のSHA同一性は全原条件のsave_restore証明とは別。
|
||||
15条件、reachable EV、7領域、安全性3結果を減らさず、未収集をfalse/pending扱いとする。
|
||||
原30/88のformal_original_credit=0、独立レビュー・通常統合未実施を維持する。
|
||||
|
||||
以下はrepair4時点の履歴であり、C追補の実装・検証状態には上記が優先する。
|
||||
|
||||
本修正は未完成であり、収集開始・machine gate・原受入の承認ではない。
|
||||
原30/88、7領域、部分点0を維持する。D05全体はpending、既存の承認2条件を
|
||||
超える規則は作らない。D-034/A01の再承認は求めない。
|
||||
|
||||
## 読取確認
|
||||
|
||||
`.review-material` はこのcheckoutには存在しない。指定された実体
|
||||
`build_dir/audit-support/p04-native-existing-sources/` のwrapper 4本とGD probe
|
||||
6本、および `tools/run_all_tests.py`、`tools/regression/owned_outer.py` を確認した。
|
||||
10本のraw SHA/sizeは配布SOURCE_MANIFEST.jsonと一致し、`repair4-context.json`
|
||||
に保存した。外部旧worktreeのartifactパスは由来としてのみ扱った。
|
||||
|
||||
実checkout HEADは `9767b0a28ca8d252520307dbbac60a1d8cfb87ab`、Runtimeは
|
||||
`d52a995ae715542bbc550f68d35889540658275d12e04ae0b21ac276f5843f39`。
|
||||
提供されたproduction資料の版は `5f6bc11d6bb6e92d22d787989b219fef3a435bc1`、
|
||||
Runtimeは `7f01b2dcdf28bc965c7588173c2dc70054633faf7204b1ac38ba0f4369331b47`。
|
||||
productionのGit objectも存在する。production資料を実checkoutのsource_mapとして
|
||||
流用しない。登録版は `deb1bcb2374eb378b840ca345db952bd8572cb6e`。
|
||||
|
||||
## A/Bの変更
|
||||
|
||||
checkerはspecのcurrent_source_pinsを登録pinとして保持し、登録Git blobのSHAを
|
||||
独立計算する。indexはregistered_pinsとversionsのexecution_origin/registered/
|
||||
tested/integrationを分離する。integrationは未統合のためnullのみ。
|
||||
testedのautoload/scripts全GDはcheckoutとHEAD blobの一致を必須にする。
|
||||
|
||||
20関数の抽出はchecker内固定。行頭func/static funcから次の行頭関数までの
|
||||
raw bytesを比較し、コメント・空白・改行を正規化しない。先頭宣言は
|
||||
`<top-level>` 単位としてdiffに含める。追加・削除関数も含む。
|
||||
`git diff --no-ext-diff --no-renames --name-only -z base..HEAD -- autoload/ scripts/`
|
||||
で変更GDを列挙し、Git blobから変更関数を計算する。applicability_deltaは
|
||||
path/function順の配列と完全一致させる。未知の変更も無影響と推定せず、
|
||||
delta_casesに保守的な全条件被覆を要求する。境界case IDの存在は後続coverageで
|
||||
検証するが、**Cの生証拠結合は未実装なので、この段階では適用可の最終判断に使えない**。
|
||||
|
||||
REACH_REFSはpath/function/anchor_sha256/line_countに変更。実tested関数内で
|
||||
本文raw bytesのアンカーを一意に解決する。旧固定範囲が隣接関数へ跨がる
|
||||
reserve/rescue箇所は関数単位に分割した。行位置が7行移動しても解決し、
|
||||
本文変更・欠落・重複アンカーは失敗する。
|
||||
|
||||
## 新collectorを作らず残す既存実行パターン
|
||||
|
||||
Root側の既存wrapper修正で保持すべき順序は、`r.source_refs(R)` →
|
||||
明示QA上書きしたrefs → `r.copy_source` によるprivate stage → bootstrap →
|
||||
cacheの `cp -c` と別inode確認 → parse-paths/contracts → `execute_phase` →
|
||||
finallyの `owned_outer.finish_captured` → fixed_guardと不変性確認。
|
||||
このworkerはwrapperを起動・変更していない。適用可能なパラメータ化patchと
|
||||
全不足probeはまだ提出できていないため、以下は実行済みの契約ではなく残作業である。
|
||||
|
||||
- R/OUT/QA/testpath/cache/input manifestは最終tested checkoutに対して固定する。
|
||||
1299件数や旧source-after.json一致をauthorityにしない。現r.source_refsがauthority。
|
||||
- checkout mapと、testpathにQAを明示上書きしたselected mapを別に記録する。
|
||||
source_map=tested、probeの元pathとSHA、QA_overrides、実stageの同SHAを結合する。
|
||||
候補製品source overrideは持ち込まない。
|
||||
- source_before/after、default_player_before/after、doc4_before/after、stage inventory、
|
||||
parse-paths、contracts、wrapper raw、phase receipt、started/ended、
|
||||
outer-owned-finally、execution.jsonを保存する。booleanだけでは不変性の代用にならない。
|
||||
- case receiptはphaseのactual_pidとexecution.actual_captured_PIDs、cleanupの全PID集合に
|
||||
結合する。cleanup_errorsが空、全childのengine_ended、終了codeを実成果物間で照合する。
|
||||
- 各条件のscalarに加え、生台帳・service/settlement ID・予約配列とのcount_eqまたは
|
||||
same_literalが必要。save_restoreはWriter保存直前と正式Reader復元直後の
|
||||
台帳・予約のsame_literal、および別PIDを要求する。nonceやログ文言では代用しない。
|
||||
|
||||
## 負履歴(起動禁止)
|
||||
|
||||
10本すべてのSHAはrepair4-context.jsonに記録した。特に以下を再実行しない。
|
||||
|
||||
- shift-end-repro-r03.gdは1080で「課金なし・予約保持」を期待し、承認済みの
|
||||
完了段階先行と矛盾する。対応native-r03.pyには旧1299 pinもある。
|
||||
- formal-boundary-reload-native-r03.pyは旧candidate sealと製品2件overrideを使う。
|
||||
SHAを書換えて別候補receiptとして使わない。
|
||||
- formal-boundary-reload-r01.gdのmanifest.source_refs==1299も旧前提。
|
||||
- midnight native-r01とpower native-r04も固定1299と旧full-run cacheに依存する。
|
||||
power readerは旧Writerの二つの正式保存slotに依存し、fresh Writerではない。
|
||||
|
||||
## 15+EVの被覆確認(未収集)
|
||||
|
||||
同一プロセス内でも条件ごとのseed、before/after、case receiptを保持する。
|
||||
以下のartifact名は既存probeが出すもの。不足欄を合格扱いにしない。
|
||||
|
||||
| 条件 | 既存probe / phase / artifact | 不足 |
|
||||
|---|---|---|
|
||||
| midnight_settlement, midnight_replay | midnight-boundary-r01 / repro / observations.json, midnight-*.var | countとraw台帳の結合、同minute再送の明示 |
|
||||
| paused_midnight | midnight-boundary-r01は開業サービスのみ | 停止した同一serviceの日跨ぎ系列 |
|
||||
| night_staff_absent | shift-end-repro-r03 / repro / 18-01観測 | 旧誤期待を除いた独立caseと非完了service |
|
||||
| power_stop, recovery_completion | power-formal-recovery-r04 / reader-a,b / recovery-*.var | fresh停止入力、台帳JSON、旧Writer依存の解消 |
|
||||
| dependency_stop | 供給6 probe内に専用系列なし | 関連施設停止・進捗/予約/service ID保持 |
|
||||
| exit_release | exit-boundary-r01 / repro / queued-*.var, observations.json | raw stateとcount結合 |
|
||||
| patience_release, closure_release | 供給6 probe内に専用系列なし | 待機解放、開始済み継続を区別したcase |
|
||||
| same_minute_replay | exit/destruction/midnightはsnapshot巻戻し再実行 | 同minuteコマンド再送の独立条件 |
|
||||
| shift_completion | shift-end-repro-r03 / repro / 18-00各phase観測 | 誤期待の修正、課金1回のraw結合 |
|
||||
| overtime_task | 供給6 probe内に専用系列なし | interrupt_level=0残業・勤務記録1回 |
|
||||
| destruction_stop | destruction-completion-boundary-r02 / repro / unfinished-*.var | raw台帳結合。completeは別帰結として維持 |
|
||||
| save_restore | formal-boundary-reload-r01 / writer,reader / *.var, writer.json, reader.json | final版の入力seal、JSON台帳/予約、owned PID結合 |
|
||||
| EV | 供給6 probe内に専用系列なし | staff予約→EV移動→停止→到着の実状態 |
|
||||
|
||||
transportはreach=falseのソース根拠のみで、別engine条件は追加しない。
|
||||
|
||||
## 再利用の有限条件と未供給資料
|
||||
|
||||
input.jsonのevidence_refsは旧証拠の参照であり、生証拠そのものではない。
|
||||
今回の供給先で確認できたのはsource、監査、適用性診断とgate失敗ログである。
|
||||
旧39件のraw receipt/state/packageを照合して採用した件数は0。
|
||||
「20関数一致」だけで39件を採用することは禁止する。
|
||||
|
||||
必要な追加のローカルraw資料:
|
||||
|
||||
1. 旧39件のexecution/phase/started/ended/outer-owned-finally/log/state一式と
|
||||
元source/config/input/environment pin。既存input.jsonのreference SHAで照合する。
|
||||
2. formal-boundary-reload-input-r02.json
|
||||
(wrapper記録SHA `195cb767e597008d1767aa0b6c8300711b83e8cf101863166e7932d9bd4ed612`)
|
||||
と、そのwhole_typed_inputs、元exact_execution、保存package全4メンバー。
|
||||
3. power original writer.json
|
||||
(wrapper記録SHA `cf3850c262012e5e52743bfb8b41af7ef5608689fb10c059c8a494216b0aff52`)
|
||||
と参照slot。旧candidateは比較用負履歴に限定する。
|
||||
|
||||
原則は最終の正確な版で再実行する。登録版証拠を再利用する有限条件は、A(i)の
|
||||
20関数raw一致、A(ii)の全delta一致、A(iii)の変更境界をtested engine caseで被覆し、
|
||||
さらに当該旧caseのsource/config/input/environmentとraw状態を独立照合できること。
|
||||
relationship restore/schema変更は正式Writer/Reader再実行、build/path/arrivalに
|
||||
関係する変更は当該経路に到達するcaseの再実行が必要。今回の資料だけでは再利用0。
|
||||
|
||||
## Rootのコマンドと残る作業
|
||||
|
||||
現在実行できるのは次のPython確認のみ(engineプロセス0)。
|
||||
|
||||
```sh
|
||||
python3 docs/plans/original-completion-2026-10-02/execution/p04-01/checker_applicability_fixtures.py
|
||||
python3 docs/plans/original-completion-2026-10-02/execution/p04-01/checker_negative_fixtures.py
|
||||
BUILD_OUTPUT_DIR=/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build python3 tools/check_p04_order_evidence.py --verify-only
|
||||
```
|
||||
|
||||
最後のコマンドはindex未収集ならexit 1が期待値。Python正対照はengine証明ではない。
|
||||
**Cのchecker強化、Dのparameter patch/不足probe、Eのowned/count/restore/他候補流用負例は未完成。**
|
||||
旧checkerのscalar/receipt自己申告を受入可能な証拠とみなしてはならない。
|
||||
現在のcheckerを正式受入に使用せず、修正全体をblockedとしてRootへ返す。
|
||||
|
||||
native収集の正確なコマンド列は、上記入力と未完成patchがないため提示できない。
|
||||
仮のコマンドを実行可能と偽って提示しない。共有stageでimport+parseを2プロセス、
|
||||
midnight/power/exit/shift/destruction/save Writer/save Reader/EVを8プロセスに
|
||||
束ねられれば計10プロセスが計画目安になるが、これは確定数・目標数ではない。
|
||||
条件ごとに必要な状態系列とguard成立を優先する。
|
||||
Rootのnative収集→validate→別セッション独立レビュー→通常統合は未実施。
|
||||
@@ -0,0 +1,576 @@
|
||||
{
|
||||
"scope": "C Python controls on supplied raw; no formal acceptance",
|
||||
"formal_original_credit": 0,
|
||||
"engine_runs": 0,
|
||||
"results": [
|
||||
{
|
||||
"control": "native_ownership_supplied_raw",
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "native_saves_supplied_raw",
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "native_ledger_supplied_raw",
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "supplied_applicability",
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "verify_native_supplied_raw",
|
||||
"result": "pass",
|
||||
"details": {
|
||||
"service_id": "service_00000001",
|
||||
"transaction_id": "ledger_00000081",
|
||||
"receipt_rows": 8,
|
||||
"formal_original_credit": 0,
|
||||
"production_commit": "5f6bc11d6bb6e92d22d787989b219fef3a435bc1",
|
||||
"owned_processes": 10,
|
||||
"verified_conditions": [
|
||||
"dependency_stop",
|
||||
"recovery_completion",
|
||||
"paused_midnight"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"control": "signature_line_sha",
|
||||
"result": "rejected",
|
||||
"error": "native ordering bytes",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "trailing_comment_excluded_sha",
|
||||
"result": "rejected",
|
||||
"error": "native ordering bytes",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "one_byte_raw",
|
||||
"result": "rejected",
|
||||
"error": "native SHA: actual-native/repro/stdout.log",
|
||||
"manifest_hashes_refreshed": false
|
||||
},
|
||||
{
|
||||
"control": "missing_member",
|
||||
"result": "rejected",
|
||||
"error": "missing/outside file: dependency-formal-native/formal-packages/reader/paused/world.bin",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "writer_reader_same_pid",
|
||||
"result": "rejected",
|
||||
"error": "native writer reader PID binding",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "writer_reader_same_profile",
|
||||
"result": "rejected",
|
||||
"error": "native writer reader profile reused",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "abnormal_ended",
|
||||
"result": "rejected",
|
||||
"error": "native process bindings",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "process_pid_changed",
|
||||
"result": "rejected",
|
||||
"error": "native PID chain",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "cleanup_missing",
|
||||
"result": "rejected",
|
||||
"error": "native owned cleanup binding",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "execution_owned_pid_deleted",
|
||||
"result": "rejected",
|
||||
"error": "native execution cleanup membership",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "reader_receipt_row_duplicated",
|
||||
"result": "rejected",
|
||||
"error": "native duplicate receipt row",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "reader_receipt_row_deleted",
|
||||
"result": "rejected",
|
||||
"error": "native reader receipt delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "observation_receipt_deleted",
|
||||
"result": "rejected",
|
||||
"error": "native ledger receipt delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "paused_sale_injected",
|
||||
"result": "rejected",
|
||||
"error": "native ledger receipt delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "paused_sale_joined_ledger_wallet",
|
||||
"result": "rejected",
|
||||
"error": "native PAUSED sale/progress/reason",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "reservation_orphaned",
|
||||
"result": "rejected",
|
||||
"error": "native reservation snapshot binding",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "reservation_orphaned_both_snapshots",
|
||||
"result": "rejected",
|
||||
"error": "native orphan reservation relation",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "wallet_wrong",
|
||||
"result": "rejected",
|
||||
"error": "native wallet delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "idempotency_wrong_transaction",
|
||||
"result": "rejected",
|
||||
"error": "native sale service join",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "production_commit_mismatch",
|
||||
"result": "rejected",
|
||||
"error": "native production commit mismatch",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "current_source_pin_mismatch",
|
||||
"result": "rejected",
|
||||
"error": "native current_source_pins mismatch",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "input_source_pin_mismatch",
|
||||
"result": "rejected",
|
||||
"error": "native input source pin mismatch",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "original_member_changed",
|
||||
"result": "rejected",
|
||||
"error": "native original members changed",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "typed_var_changed",
|
||||
"result": "rejected",
|
||||
"error": "native typed SHA mismatch",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "self_reported_scalar_true",
|
||||
"result": "rejected",
|
||||
"error": "native reader receipt delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
}
|
||||
],
|
||||
"previous_validation": {
|
||||
"scope": "C Python controls only; synthetic corrected applicability is not native proof",
|
||||
"formal_original_credit": 0,
|
||||
"engine_runs": 0,
|
||||
"results": [
|
||||
{
|
||||
"control": "native_ownership_supplied_raw",
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "native_saves_supplied_raw",
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "native_ledger_supplied_raw",
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "supplied_applicability",
|
||||
"result": "rejected",
|
||||
"error": "native ordering bytes"
|
||||
},
|
||||
{
|
||||
"control": "synthetic_corrected_applicability_composition",
|
||||
"result": "pass",
|
||||
"native_acceptance": false
|
||||
},
|
||||
{
|
||||
"control": "one_byte_raw",
|
||||
"result": "rejected",
|
||||
"error": "native SHA: actual-native/repro/stdout.log",
|
||||
"manifest_hashes_refreshed": false
|
||||
},
|
||||
{
|
||||
"control": "missing_member",
|
||||
"result": "rejected",
|
||||
"error": "missing/outside file: dependency-formal-native/formal-packages/reader/paused/world.bin",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "writer_reader_same_pid",
|
||||
"result": "rejected",
|
||||
"error": "native writer reader PID binding",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "writer_reader_same_profile",
|
||||
"result": "rejected",
|
||||
"error": "native writer reader profile reused",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "abnormal_ended",
|
||||
"result": "rejected",
|
||||
"error": "native process bindings",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "process_pid_changed",
|
||||
"result": "rejected",
|
||||
"error": "native PID chain",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "cleanup_missing",
|
||||
"result": "rejected",
|
||||
"error": "native owned cleanup binding",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "execution_owned_pid_deleted",
|
||||
"result": "rejected",
|
||||
"error": "native execution cleanup membership",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "reader_receipt_row_duplicated",
|
||||
"result": "rejected",
|
||||
"error": "native duplicate receipt row",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "reader_receipt_row_deleted",
|
||||
"result": "rejected",
|
||||
"error": "native reader receipt delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "observation_receipt_deleted",
|
||||
"result": "rejected",
|
||||
"error": "native ledger receipt delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "paused_sale_injected",
|
||||
"result": "rejected",
|
||||
"error": "native ledger receipt delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "paused_sale_joined_ledger_wallet",
|
||||
"result": "rejected",
|
||||
"error": "native PAUSED sale/progress/reason",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "reservation_orphaned",
|
||||
"result": "rejected",
|
||||
"error": "native reservation snapshot binding",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "reservation_orphaned_both_snapshots",
|
||||
"result": "rejected",
|
||||
"error": "native orphan reservation relation",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "wallet_wrong",
|
||||
"result": "rejected",
|
||||
"error": "native wallet delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "idempotency_wrong_transaction",
|
||||
"result": "rejected",
|
||||
"error": "native sale service join",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "production_commit_mismatch",
|
||||
"result": "rejected",
|
||||
"error": "native production commit mismatch",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "current_source_pin_mismatch",
|
||||
"result": "rejected",
|
||||
"error": "native current_source_pins mismatch",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "input_source_pin_mismatch",
|
||||
"result": "rejected",
|
||||
"error": "native input source pin mismatch",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "original_member_changed",
|
||||
"result": "rejected",
|
||||
"error": "native original members changed",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "typed_var_changed",
|
||||
"result": "rejected",
|
||||
"error": "native typed SHA mismatch",
|
||||
"manifest_hashes_refreshed": true
|
||||
},
|
||||
{
|
||||
"control": "self_reported_scalar_true",
|
||||
"result": "rejected",
|
||||
"error": "native reader receipt delta",
|
||||
"manifest_hashes_refreshed": true
|
||||
}
|
||||
],
|
||||
"validated_source_sha256": {
|
||||
"tools/check_p04_order_evidence.py": "98b2692c604055d7b970e6ef9e3ad1795f35823c3c19d1acad5b80ad2ec7a378",
|
||||
"docs/plans/original-completion-2026-10-02/execution/p04-01/checker_native_fixtures.py": "26bbdcee483816b8bc60c250bbc63bf0a72a194dce2ba9b690abace9b6b17bbc"
|
||||
},
|
||||
"supplied_bundle_pins": {
|
||||
"SOURCE_MANIFEST.json": "381b439fb1d4ee5f30e21243b03ad755c3ab654a9e414af5648004054d67b5f4",
|
||||
"OWNERSHIP_RAW_PROVENANCE.json": "51d746879b4197445a09cd44a88dd918c365fa98025d9cd652a740cee09a9040",
|
||||
"POST_P18_CURRENT_SOURCE_APPLICABILITY.json": "ecb92215b7bfb4368ddeb6d44dcd467d13e97d677ca2f29df3ab9684f6c757c7"
|
||||
},
|
||||
"whole_native_status": "blocked: supplied applicability body hashes exclude four function bodies",
|
||||
"whole_gate_executed": false
|
||||
},
|
||||
"whole_native_status": "pass: corrected supplied bundle; strict full raw SHA",
|
||||
"whole_gate_executed": false,
|
||||
"validation_invocations": {
|
||||
"native": 1,
|
||||
"existing_fixtures": 1,
|
||||
"applicability_ab": 1
|
||||
},
|
||||
"existing_fixtures": {
|
||||
"scope": "A/B and optional C applicability controls; no native acceptance",
|
||||
"results": [
|
||||
{
|
||||
"control": "registered_equals_tested",
|
||||
"revision": "deb1bcb2374eb378b840ca345db952bd8572cb6e",
|
||||
"changed_units": 0,
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "line_shift_resolves",
|
||||
"revision": "deb1bcb2374eb378b840ca345db952bd8572cb6e",
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "legal_delta",
|
||||
"revision": "5f6bc11d6bb6e92d22d787989b219fef3a435bc1",
|
||||
"changed_units": 25,
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "line_shift_resolves",
|
||||
"revision": "5f6bc11d6bb6e92d22d787989b219fef3a435bc1",
|
||||
"result": "pass"
|
||||
},
|
||||
{
|
||||
"control": "undeclared_delta",
|
||||
"result": "rejected",
|
||||
"error": "git diff/applicability_delta mismatch"
|
||||
},
|
||||
{
|
||||
"control": "missing_boundary_case",
|
||||
"result": "rejected",
|
||||
"error": "boundary delta coverage: autoload/simulation_runtime.gd:_build_facility_precheck"
|
||||
},
|
||||
{
|
||||
"control": "wrong_tested_revision",
|
||||
"result": "rejected",
|
||||
"error": "version roles"
|
||||
},
|
||||
{
|
||||
"control": "native_applicability",
|
||||
"result": "pass"
|
||||
}
|
||||
]
|
||||
},
|
||||
"applicability_ab": {
|
||||
"scope": "Synthetic checker checks only; no engine evidence or formal acceptance",
|
||||
"py_compile": true,
|
||||
"results": [
|
||||
{
|
||||
"fixture": "synthetic_scalar_only_rejected",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "native bundle required; self-reported scalar evidence is insufficient"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "forged_registered_pin",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "registered pin declaration"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "false_delta",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "git diff/applicability_delta mismatch"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "wrong_reach_anchor",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "unknown reachability anchor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "missing_index",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "missing/outside file: index.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "duplicate_key",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "duplicate JSON key: schema_version"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "symlink",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "symlink: stdout.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "hash_mismatch",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "artifact hash: stdout"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "stale_pin",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "stale pin: autoload/simulation_runtime.gd"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "unexecuted_receipt",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "unexecuted/incomplete receipt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "pending_authority",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "pending/missing authority"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "missing_condition",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "mandatory conditions missing/unknown"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "unsupported_reach_false",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "unsupported reach=false: transport"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fixture": "owner_hash_mismatch",
|
||||
"exit_code": 1,
|
||||
"result": {
|
||||
"task_id": "P04-01",
|
||||
"machine_verified": false,
|
||||
"formal_acceptance": false,
|
||||
"error": "owner approval hash mismatch"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"validated_source_sha256": {
|
||||
"tools/check_p04_order_evidence.py": "afe8c7cc3d3b511bacdaa1965fb06a0eefd1b204b7e9b930eb29767c4d320824",
|
||||
"docs/plans/original-completion-2026-10-02/execution/p04-01/checker_native_fixtures.py": "634b5e3a3491cdcdab549ed5d812935f73c2958d8cca008ce35c80b6ebb298e4"
|
||||
},
|
||||
"supplied_bundle_pins": {
|
||||
"SOURCE_MANIFEST.json": "dbaab3c293c191eb5f3aff34854945e2d564f824df50a92802b3a7eda55321a8",
|
||||
"OWNERSHIP_RAW_PROVENANCE.json": "51d746879b4197445a09cd44a88dd918c365fa98025d9cd652a740cee09a9040",
|
||||
"POST_P18_CURRENT_SOURCE_APPLICABILITY.json": "46e0cc35cb95496d5f26d3cab7d3a31cb29faacaa16714daab3aefdf65b420a3"
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Python-only A/B controls. Real Git blobs, synthetic case IDs; no engine proof."""
|
||||
import copy
|
||||
import argparse
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
ROOT = Path(__file__).resolve().parents[5]
|
||||
spec = importlib.util.spec_from_file_location('p04_gate', ROOT / 'tools/check_p04_order_evidence.py')
|
||||
gate = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(gate)
|
||||
PRODUCTION = '5f6bc11d6bb6e92d22d787989b219fef3a435bc1'
|
||||
|
||||
|
||||
def run(native_bundle=None):
|
||||
results = []
|
||||
registered_spec = gate.load(gate.SPEC)
|
||||
# Bind Git reads to the actual repository while testing exported raw blobs.
|
||||
# No branch/index/checkout operation and no synthetic Git command output.
|
||||
gate.git_bytes = lambda *args: subprocess.check_output(['git', *args], cwd=ROOT)
|
||||
with tempfile.TemporaryDirectory(prefix='.applicability-fixtures-', dir=Path(__file__).parent) as tmp:
|
||||
for revision in (gate.REGISTERED_COMMIT, PRODUCTION):
|
||||
base = Path(tmp) / revision
|
||||
source = {}
|
||||
for name in gate.git_bytes('ls-tree', '-r', '--name-only', '-z', revision,
|
||||
'--', 'autoload/', 'scripts/').split(b'\0'):
|
||||
if not name.endswith(b'.gd'):
|
||||
continue
|
||||
path = name.decode()
|
||||
target = base / path
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
target.write_bytes(gate.git_bytes('show', revision + ':' + path))
|
||||
source[path] = gate.sha(target)
|
||||
gate.ROOT = base
|
||||
delta = gate.source_delta(gate.REGISTERED_COMMIT, revision)
|
||||
index = dict(registered_pins=registered_spec['current_source_pins'],
|
||||
versions=dict(execution_origin=gate.EXECUTION_ORIGIN, registered=gate.REGISTERED_COMMIT,
|
||||
tested=revision, integration=None), applicability_delta=delta,
|
||||
conditions={cid: {'case_id': cid} for cid in gate.REQUIRED},
|
||||
reachability={'EV': {'case_id': 'EV'}}, delta_cases={})
|
||||
index['delta_cases'] = {r['path'] + ':' + r['function']: {
|
||||
cid: cid for cid in gate.boundary_conditions(r['path'], r['function'])} for r in delta}
|
||||
gate.applicability(index, registered_spec, source, revision)
|
||||
results.append(dict(control='registered_equals_tested' if not delta else 'legal_delta',
|
||||
revision=revision, changed_units=len(delta), result='pass'))
|
||||
for name, refs in gate.REACH_REFS.items():
|
||||
for path, function, digest, lines in refs:
|
||||
data = (base / path).read_bytes()
|
||||
gate.resolve_anchor(data, function, digest, lines)
|
||||
# Seven lines added before the function must not break reachability.
|
||||
gate.resolve_anchor(b'\n' * 7 + data, function, digest, lines)
|
||||
results.append(dict(control='line_shift_resolves', revision=revision, result='pass'))
|
||||
if delta:
|
||||
for label, mutate in (
|
||||
('undeclared_delta', lambda i: i['applicability_delta'].pop()),
|
||||
('missing_boundary_case', lambda i: i['delta_cases'][next(iter(i['delta_cases']))].clear()),
|
||||
('wrong_tested_revision', lambda i: i['versions'].update(tested=gate.REGISTERED_COMMIT)),
|
||||
):
|
||||
altered = copy.deepcopy(index)
|
||||
mutate(altered)
|
||||
try:
|
||||
gate.applicability(altered, registered_spec, source, revision)
|
||||
except ValueError as exc:
|
||||
results.append(dict(control=label, result='rejected', error=str(exc)))
|
||||
else:
|
||||
raise AssertionError('negative fixture accepted: ' + label)
|
||||
gate.ROOT = ROOT
|
||||
if native_bundle is not None:
|
||||
try:
|
||||
gate.native_applicability(native_bundle)
|
||||
except ValueError as exc:
|
||||
# A/B Git equality must not turn an inconsistent native report into
|
||||
# applicable evidence. The C mutation suite tests a corrected copy.
|
||||
assert str(exc) == 'native ordering bytes', str(exc)
|
||||
results.append(dict(control='native_report_body_hash_gap', result='rejected', error=str(exc)))
|
||||
else:
|
||||
results.append(dict(control='native_applicability', result='pass'))
|
||||
return {'scope': 'A/B and optional C applicability controls; no native acceptance', 'results': results}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--native-bundle', type=Path)
|
||||
print(json.dumps(run(parser.parse_args().native_bundle), ensure_ascii=False, indent=2))
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
#!/usr/bin/env python3
|
||||
"""C component controls and raw mutations. No engine, Runner or acceptance."""
|
||||
import argparse
|
||||
import copy
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
HERE = Path(__file__).resolve().parent
|
||||
ROOT = HERE.parents[4]
|
||||
spec = importlib.util.spec_from_file_location('p04_native_gate', ROOT / 'tools/check_p04_order_evidence.py')
|
||||
gate = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(gate)
|
||||
|
||||
|
||||
def run(source):
|
||||
results = []
|
||||
for function in (gate.native_ownership, gate.native_saves, gate.native_ledger):
|
||||
function(source)
|
||||
results.append({'control': function.__name__ + '_supplied_raw', 'result': 'pass'})
|
||||
gate.native_applicability(source)
|
||||
results.append({'control': 'supplied_applicability', 'result': 'pass'})
|
||||
native = gate.verify_native(source)
|
||||
results.append({'control': 'verify_native_supplied_raw', 'result': 'pass', 'details': native})
|
||||
with tempfile.TemporaryDirectory(prefix='.native-fixtures-', dir=HERE) as tmp:
|
||||
base = Path(tmp) / 'raw'
|
||||
shutil.copytree(source, base)
|
||||
app_path = 'POST_P18_CURRENT_SOURCE_APPLICABILITY.json'
|
||||
originals = {p.relative_to(base).as_posix(): p.read_bytes() for p in base.rglob('*') if p.is_file()}
|
||||
changed = set()
|
||||
|
||||
def edit(name, mutation):
|
||||
path = base / name
|
||||
value = gate.load(path)
|
||||
mutation(value)
|
||||
path.write_text(json.dumps(value))
|
||||
changed.add(name)
|
||||
|
||||
def refresh():
|
||||
for manifest, key, field in (('OWNERSHIP_RAW_PROVENANCE.json', 'copied', 'target'),
|
||||
('SOURCE_MANIFEST.json', 'files', 'copy')):
|
||||
def update(value):
|
||||
for row in value[key]:
|
||||
path = base / row[field]
|
||||
if path.is_file():
|
||||
row.update(bytes=path.stat().st_size, sha256=gate.sha(path))
|
||||
edit(manifest, update)
|
||||
|
||||
def check(name, function, mutation, error, rehash=True):
|
||||
for path in changed:
|
||||
(base / path).write_bytes(originals[path])
|
||||
changed.clear()
|
||||
mutation()
|
||||
if rehash:
|
||||
refresh()
|
||||
try:
|
||||
function(base)
|
||||
except (ValueError, KeyError, TypeError) as exc:
|
||||
assert error in str(exc), (name, str(exc))
|
||||
results.append({'control': name, 'result': 'rejected', 'error': str(exc),
|
||||
'manifest_hashes_refreshed': rehash})
|
||||
else:
|
||||
raise AssertionError('negative fixture accepted: ' + name)
|
||||
|
||||
def truncated_hash(kind):
|
||||
def mutate(app):
|
||||
for row in app['ordering_functions']:
|
||||
body = gate.function_bytes(gate.git_bytes(
|
||||
'show', app['production_commit'] + ':' + row['path']))[row['function']]
|
||||
if kind == 'signature':
|
||||
if row['function'] != '_complete_service_transaction':
|
||||
continue
|
||||
truncated = body.splitlines(keepends=True)[0]
|
||||
else:
|
||||
offsets = [m.start() for m in re.finditer(rb'(?m)^#', body)]
|
||||
offsets = [i for i in offsets if all(
|
||||
not line.strip() or line.startswith(b'#') for line in body[i:].splitlines())]
|
||||
if not offsets:
|
||||
continue
|
||||
truncated = body[:offsets[0]]
|
||||
assert truncated != body
|
||||
digest = hashlib.sha256(truncated).hexdigest()
|
||||
row.update(registered_body_sha256=digest, production_body_sha256=digest)
|
||||
return
|
||||
raise AssertionError('no truncation target: ' + kind)
|
||||
edit(app_path, mutate)
|
||||
check('signature_line_sha', gate.native_applicability,
|
||||
lambda: truncated_hash('signature'), 'native ordering bytes')
|
||||
check('trailing_comment_excluded_sha', gate.native_applicability,
|
||||
lambda: truncated_hash('comment'), 'native ordering bytes')
|
||||
|
||||
formal = 'dependency-formal-native/'
|
||||
obs = 'dependency-midnight-native/order-evidence/observations.json'
|
||||
reader = formal + 'restart-evidence/reader.json'
|
||||
def corrupt():
|
||||
name = 'actual-native/repro/stdout.log'
|
||||
data = bytearray((base / name).read_bytes())
|
||||
data[0] ^= 1
|
||||
(base / name).write_bytes(data)
|
||||
changed.add(name)
|
||||
check('one_byte_raw', gate.native_ownership, corrupt, 'native SHA', False)
|
||||
def remove_member():
|
||||
name = formal + 'formal-packages/reader/paused/world.bin'
|
||||
(base / name).unlink()
|
||||
changed.add(name)
|
||||
check('missing_member', gate.native_saves, remove_member, 'missing/outside')
|
||||
check('writer_reader_same_pid', gate.native_ownership,
|
||||
lambda: edit(reader, lambda d: d.update(pid=gate.load(base / (formal + 'restart-evidence/writer.json'))['pid'])),
|
||||
'PID binding')
|
||||
check('writer_reader_same_profile', gate.native_ownership,
|
||||
lambda: edit(reader, lambda d: d.update(profile=gate.load(base / (formal + 'restart-evidence/writer.json'))['profile'])),
|
||||
'profile reused')
|
||||
check('abnormal_ended', gate.native_ownership,
|
||||
lambda: edit(formal + 'reader/ended.json', lambda d: d.update(exit_code=1)), 'process bindings')
|
||||
check('process_pid_changed', gate.native_ownership,
|
||||
lambda: edit(formal + 'reader/process.json', lambda d: d.update(pid=d['pid'] + 1)), 'PID chain')
|
||||
check('cleanup_missing', gate.native_ownership,
|
||||
lambda: edit(formal + 'reader/outer-owned-finally.json', lambda d: d.update(cleanup=[])), 'cleanup binding')
|
||||
check('execution_owned_pid_deleted', gate.native_ownership,
|
||||
lambda: edit(formal + 'execution.json', lambda d: d['actual_captured_PIDs'].pop()), 'cleanup membership')
|
||||
check('reader_receipt_row_duplicated', gate.native_ledger,
|
||||
lambda: edit(reader, lambda d: d['results'][0]['receipts'][-1]['rows'].append(copy.deepcopy(d['results'][0]['receipts'][-1]['rows'][0]))),
|
||||
'duplicate receipt row')
|
||||
check('reader_receipt_row_deleted', gate.native_ledger,
|
||||
lambda: edit(reader, lambda d: d['results'][0]['receipts'][-1]['rows'].pop()), 'reader receipt delta')
|
||||
check('observation_receipt_deleted', gate.native_ledger,
|
||||
lambda: edit(obs, lambda d: d['observations'][3]['receipts'].pop()), 'ledger receipt delta')
|
||||
check('paused_sale_injected', gate.native_ledger,
|
||||
lambda: edit(obs, lambda d: d['observations'][1]['receipts'].append(copy.deepcopy(d['observations'][3]['receipts'][-1]))),
|
||||
'ledger receipt delta')
|
||||
def joined_paused_sale():
|
||||
observation = gate.load(base / obs)
|
||||
receipt = copy.deepcopy(observation['observations'][3]['receipts'][-1])
|
||||
sale = next(r for r in receipt['rows'] if r['category'] == 'SERVICE_SALE')
|
||||
def inject(d):
|
||||
paused = d['observations'][1]
|
||||
paused['receipts'].append(receipt)
|
||||
paused['wallet'] -= sale['amount']
|
||||
paused['guest']['wallet_gold'] = paused['wallet']
|
||||
edit(obs, inject)
|
||||
edit('dependency-midnight-native/order-evidence/midnight-midnight.json',
|
||||
lambda d: d['systems']['runtime']['economy']['entries'].extend(receipt['rows']))
|
||||
check('paused_sale_joined_ledger_wallet', gate.native_ledger, joined_paused_sale, 'PAUSED sale/progress/reason')
|
||||
check('reservation_orphaned', gate.native_ledger,
|
||||
lambda: edit(obs, lambda d: d['observations'][1]['reservations']['reservations'][0].update(requester_id='orphan')),
|
||||
'reservation snapshot binding')
|
||||
def joined_orphan():
|
||||
edit(obs, lambda d: d['observations'][1]['reservations']['reservations'][0].update(requester_id='orphan'))
|
||||
edit('dependency-midnight-native/order-evidence/midnight-midnight.json',
|
||||
lambda d: d['systems']['runtime']['inventory']['reservations'][0].update(requester_id='orphan'))
|
||||
check('reservation_orphaned_both_snapshots', gate.native_ledger, joined_orphan, 'orphan reservation relation')
|
||||
check('wallet_wrong', gate.native_ledger,
|
||||
lambda: edit(obs, lambda d: d['observations'][3].update(wallet=d['observations'][3]['wallet'] + 1)), 'wallet delta')
|
||||
state = 'dependency-midnight-native/order-evidence/midnight-after.json'
|
||||
check('idempotency_wrong_transaction', gate.native_ledger,
|
||||
lambda: edit(state, lambda d: next(r for r in d['systems']['runtime']['economy']['idempotency'] if r['key'].startswith('service.payment.')).update(transaction_id='wrong')),
|
||||
'sale service join')
|
||||
check('production_commit_mismatch', gate.native_applicability,
|
||||
lambda: edit('ROOT_APPROVED_DEPENDENCY_FORMAL_RESULT.json', lambda d: d.update(production_commit=gate.REGISTERED_COMMIT)),
|
||||
'production commit mismatch')
|
||||
check('current_source_pin_mismatch', gate.native_applicability,
|
||||
lambda: edit(app_path, lambda d: d['registered_source_pins'][0].update(production_sha256='0' * 64)),
|
||||
'current_source_pins mismatch')
|
||||
check('input_source_pin_mismatch', gate.native_applicability,
|
||||
lambda: edit(formal + 'runner-input.json', lambda d: d['selected_source_map'].update({'autoload/simulation_runtime.gd': '0' * 64})),
|
||||
'input source pin mismatch')
|
||||
check('original_member_changed', gate.native_saves,
|
||||
lambda: edit(formal + 'execution.json', lambda d: d['formal_after']['before']['world.bin'].update(sha256='0' * 64)),
|
||||
'original members changed')
|
||||
def typed_corrupt():
|
||||
name = formal + 'restart-evidence/reader-before-loaded.var'
|
||||
(base / name).write_bytes(b'forged typed bytes')
|
||||
changed.add(name)
|
||||
check('typed_var_changed', gate.native_saves, typed_corrupt, 'typed SHA mismatch')
|
||||
check('self_reported_scalar_true', gate.native_ledger,
|
||||
lambda: edit(reader, lambda d: d.update(results=[{'receipts': [], 'sale_count': 1}],
|
||||
passed=True, formal_save_restored=True)), 'reader receipt delta')
|
||||
return {'scope': 'C Python controls on supplied raw; no formal acceptance',
|
||||
'formal_original_credit': 0, 'engine_runs': 0, 'results': results}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('native_bundle', type=Path)
|
||||
print(json.dumps(run(parser.parse_args().native_bundle), ensure_ascii=False, indent=2))
|
||||
+16
-3
@@ -37,6 +37,8 @@ def run():
|
||||
return aid
|
||||
oldmap = gate.load(ROOT / 'docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/historical-source-map.json')
|
||||
source = {p: gate.sha(ROOT / p) for p in oldmap if p.endswith('.gd') and p.startswith(('autoload/', 'scripts/'))}
|
||||
for folder in ('autoload', 'scripts'):
|
||||
source.update({p.relative_to(ROOT).as_posix(): gate.sha(p) for p in (ROOT / folder).rglob('*.gd')})
|
||||
add('fixture_environment', b'SYNTHETIC CHECKER FIXTURE - NOT AN ENGINE')
|
||||
environment = dict(os='synthetic-checker-fixture', **{
|
||||
k: {'fixture_environment.json': artifacts['fixture_environment']['sha256']}
|
||||
@@ -94,13 +96,21 @@ def run():
|
||||
reachability = {}
|
||||
for name, refs in gate.REACH_REFS.items():
|
||||
reachability[name] = dict(reach=name == 'EV', reason='Synthetic static-chain fixture',
|
||||
source_refs=[dict(path=p, sha256=source[p], start=s, end=e,
|
||||
text='\n'.join((ROOT / p).read_text().splitlines()[s-1:e])) for p,s,e in refs])
|
||||
source_refs=[dict(path=p, sha256=source[p], function=f, anchor_sha256=h,
|
||||
line_count=n) for p,f,h,n in refs])
|
||||
reachability['EV']['case_id'] = 'ev_stop'
|
||||
index = dict(schema_version=1, task_id='P04-01', formal_acceptance=False,
|
||||
candidate_commit=subprocess.check_output(['git','rev-parse','HEAD'], cwd=ROOT, text=True).strip(),
|
||||
source_map=source, environment=environment, artifacts=artifacts, authority=authority,
|
||||
domains=domains, conditions=conditions, reachability=reachability, review_status='pending_review')
|
||||
index['registered_pins'] = gate.load(gate.SPEC)['current_source_pins']
|
||||
index['versions'] = dict(execution_origin=gate.EXECUTION_ORIGIN,
|
||||
registered=gate.REGISTERED_COMMIT, tested=index['candidate_commit'], integration=None)
|
||||
index['applicability_delta'] = gate.source_delta(gate.REGISTERED_COMMIT, index['candidate_commit'])
|
||||
index['delta_cases'] = {row['path'] + ':' + row['function']: {
|
||||
cid: ('ev_stop' if cid == 'EV' else cid)
|
||||
for cid in gate.boundary_conditions(row['path'], row['function'])}
|
||||
for row in index['applicability_delta']}
|
||||
original_files = {p.name:p.read_bytes() for p in evidence.iterdir()}
|
||||
index = copy.deepcopy(index)
|
||||
def check(name, mutate, error):
|
||||
@@ -120,7 +130,10 @@ def run():
|
||||
assert proc.returncode == (0 if error is None else 1), (name, proc.stdout, proc.stderr)
|
||||
assert error is None or error in output.get('error',''), (name, output)
|
||||
results.append(dict(fixture=name, exit_code=proc.returncode, result=output))
|
||||
check('synthetic_control', lambda i: None, None)
|
||||
check('synthetic_scalar_only_rejected', lambda i: None, 'native bundle required')
|
||||
check('forged_registered_pin', lambda i: i['registered_pins'].update({'autoload/simulation_runtime.gd':'0'*64}), 'registered pin declaration')
|
||||
check('false_delta', lambda i: i['applicability_delta'].append({'path':'autoload/simulation_runtime.gd','function':'initialize'}), 'git diff/applicability_delta mismatch')
|
||||
check('wrong_reach_anchor', lambda i: i['reachability']['EV']['source_refs'][0].update(anchor_sha256='0'*64), 'unknown reachability anchor')
|
||||
check('missing_index', lambda i: None, 'missing/outside')
|
||||
check('duplicate_key', lambda i: None, 'duplicate JSON key')
|
||||
def symlink(i):
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"supplied_sources": [
|
||||
{
|
||||
"name": "p04-01-shift-end-repro-r03.gd",
|
||||
"sha256": "97e20c3f68b85bbb85fd37e85e97dec277cca5ebc791107120b0606d1138cc0a",
|
||||
"bytes": 9518,
|
||||
"historical_only": true
|
||||
},
|
||||
{
|
||||
"name": "p04-01-shift-end-repro-native-r03.py",
|
||||
"sha256": "995a9b159533f40f79a4ef639c1338b689e8e98720eed638f8eae169d8a03e11",
|
||||
"bytes": 6268,
|
||||
"historical_only": true
|
||||
},
|
||||
{
|
||||
"name": "p04-01-midnight-boundary-r01.gd",
|
||||
"sha256": "4f587cc90a3bbd310b53c6216e54cda1deacfa87fa4312411b41288e534de527",
|
||||
"bytes": 11677,
|
||||
"historical_only": true
|
||||
},
|
||||
{
|
||||
"name": "p04-01-midnight-boundary-native-r01.py",
|
||||
"sha256": "3da084530941658ee396b05b9343f0342bf2a981962ef3361ed0f82475dd73dd",
|
||||
"bytes": 6317,
|
||||
"historical_only": true
|
||||
},
|
||||
{
|
||||
"name": "p04-01-power-formal-recovery-r04.gd",
|
||||
"sha256": "887d3097fa4178675caf253c428d56cc842b506b8c32d6f7925505f17c32e2ff",
|
||||
"bytes": 10062,
|
||||
"historical_only": true
|
||||
},
|
||||
{
|
||||
"name": "p04-01-power-formal-recovery-native-r04.py",
|
||||
"sha256": "d115a1ec5f985cfa4d7bd751eace0f2f5e93e1f4809434a0e2685c0fe0b8b23e",
|
||||
"bytes": 8425,
|
||||
"historical_only": true
|
||||
},
|
||||
{
|
||||
"name": "p04-01-formal-boundary-reload-r01.gd",
|
||||
"sha256": "56e193a2c1d44c62c83374442b61c63935a69fdc1665ffa09bb549b0dfd8d14b",
|
||||
"bytes": 7624,
|
||||
"historical_only": true
|
||||
},
|
||||
{
|
||||
"name": "p04-01-formal-boundary-reload-native-r03.py",
|
||||
"sha256": "fcd22729c9d045eb9656fae5db6c2116a27ab54fdb24f91c8125925b02a9d47a",
|
||||
"bytes": 8677,
|
||||
"historical_only": true
|
||||
},
|
||||
{
|
||||
"name": "p04-01-destruction-completion-boundary-r02.gd",
|
||||
"sha256": "a9d58e7d5fcdf4793075552ae5be1ba6f5c2d45423b245b3d4617530260df37b",
|
||||
"bytes": 12257,
|
||||
"historical_only": true
|
||||
},
|
||||
{
|
||||
"name": "p04-01-exit-boundary-r01.gd",
|
||||
"sha256": "6d7f32d801e4d8fb241a5e5695d6e31a8e7c47ad8021228ded460efcb1967254",
|
||||
"bytes": 12726,
|
||||
"historical_only": true
|
||||
}
|
||||
],
|
||||
"evidence_references": 39,
|
||||
"raw_reuse_confirmed": 0,
|
||||
"engine_runs": 0,
|
||||
"runner_operations": 0,
|
||||
"formal_acceptance": false
|
||||
}
|
||||
@@ -18,6 +18,21 @@ SPEC = ROOT / 'docs/spec/acceptance/P04-01.json'
|
||||
SPEC_HASH = '9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881'
|
||||
DOMAINS = {'閉店', '停電', '破壊', '退出', '課金', 'シフト交代', '00:00決算'}
|
||||
OWNER_HASH = '4583ee9aad45c4db183d72df4420df48aa8e0897e3b5efda13016f0b5cdbd68e'
|
||||
REGISTERED_COMMIT = 'deb1bcb2374eb378b840ca345db952bd8572cb6e'
|
||||
EXECUTION_ORIGIN = '9767b0a28ca8d252520307dbbac60a1d8cfb87ab'
|
||||
# Fixed membership, never supplied by the evidence index.
|
||||
ORDER_FUNCTIONS = {
|
||||
'scripts/core/simulation_kernel.gd': ('advance_one_minute', '_run_phase', '_handle_time_boundaries'),
|
||||
'scripts/core/command_queue.gd': ('_comes_before',),
|
||||
'autoload/simulation_runtime.gd': (
|
||||
'_process_tick_commands', '_advance_operations_time', '_run_operations_deferred_suffix',
|
||||
'_advance_mana', '_advance_facilities', '_advance_guest_vitals', '_advance_staff_ai',
|
||||
'_advance_guest_ai_decisions', '_release_closed_business_queues',
|
||||
'_release_closed_business_request', '_complete_service_transaction'),
|
||||
'scripts/facility/facility_service.gd': (
|
||||
'advance_one_minute', '_prepare_service_for_tick', '_complete_service', '_fail_service'),
|
||||
'scripts/operations/operations_coordinator.gd': ('_process_minute_boundaries',),
|
||||
}
|
||||
# Condition -> (domain, authority refs, required engine measurements).
|
||||
# Measurements describe safety/counts, not the still-pending attribution policy.
|
||||
REQUIRED = {
|
||||
@@ -38,13 +53,16 @@ REQUIRED = {
|
||||
'overtime_task': ('シフト交代', ('BASELINE:67',), {'interrupt_level': 0, 'is_overtime': True, 'duty_recorded_once': True}),
|
||||
}
|
||||
REACH_REFS = {
|
||||
'EV': [('autoload/simulation_runtime.gd', 6733, 6742),
|
||||
('scripts/staff/task_dispatcher.gd', 256, 261),
|
||||
('autoload/simulation_runtime.gd', 9141, 9170),
|
||||
('autoload/simulation_runtime.gd', 8986, 8987),
|
||||
('scripts/transport/elevator_service.gd', 279, 284)],
|
||||
'transport': [('autoload/simulation_runtime.gd', 12023, 12030),
|
||||
('autoload/simulation_runtime.gd', 12976, 13050)],
|
||||
'EV': [
|
||||
('autoload/simulation_runtime.gd', '_execute_create_staff_task', '8b83aff45ead128b70931343271dbd03a1024b90238d1f46f93e4856290aa0d8', 10),
|
||||
('scripts/staff/task_dispatcher.gd', '_reserve_pair', '48e2e593c117bd675236a165a294c9cc6233f87018010249cd8e675aff01fc3c', 6),
|
||||
('autoload/simulation_runtime.gd', '_reserve_staff_task_items', '4f2add093de47cb08abfa45e9d2285f00d906c9bceadb2d98ffa42faae9ede67', 28),
|
||||
('autoload/simulation_runtime.gd', '_advance_staff_task_travel', '53937aefeec533a5f16169bba4dd6a69b5246101d09de77ca95db7ca174c63ce', 2),
|
||||
('scripts/transport/elevator_service.gd', 'set_powered', '925f4bf2d109421956fb2958981758d7d84a1ca586a9d4eb51572b8b9677cfba', 6)],
|
||||
'transport': [
|
||||
('autoload/simulation_runtime.gd', '_on_staff_task_completed', '46daaa0197ce85c08883614112efb2d12a2cc0a02fe14ffec8314c73cbba61fc', 8),
|
||||
('autoload/simulation_runtime.gd', '_handle_rescue_arrival', '11f8d43d0c089b95006009eddfc8bd3d4375a666b29ff19f36e1fa008f3946dd', 24),
|
||||
('autoload/simulation_runtime.gd', '_advance_staff_rescue', '86bb31b40606fd624cc6b273dfdf7e3e4b3e1bc9997df825dd74136efb69a38f', 52)],
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +127,106 @@ def literal(a, b):
|
||||
return type(a) is type(b) and json.dumps(a, sort_keys=True) == json.dumps(b, sort_keys=True)
|
||||
|
||||
|
||||
def git_bytes(*args):
|
||||
return subprocess.check_output(['git', *args], cwd=ROOT)
|
||||
|
||||
|
||||
def function_bytes(data):
|
||||
"""Top-level named func through next named func, preserving every raw byte.
|
||||
|
||||
The prefix is an explicit non-function unit. Nested lambdas do not start
|
||||
a unit. Comments, whitespace, signatures and trailing declarations remain
|
||||
included; uncertain edits fail conservatively, never normalize as equal.
|
||||
"""
|
||||
matches = list(re.finditer(rb'(?m)^(?:static )?func ([A-Za-z_][A-Za-z_0-9]*)\(', data))
|
||||
result = {'<top-level>': data[:matches[0].start()] if matches else data}
|
||||
for i, match in enumerate(matches):
|
||||
name = match[1].decode('ascii')
|
||||
require(name not in result, 'ambiguous function: ' + name)
|
||||
result[name] = data[match.start():matches[i + 1].start() if i + 1 < len(matches) else len(data)]
|
||||
return result
|
||||
|
||||
|
||||
def resolve_anchor(data, function, digest, line_count):
|
||||
body = function_bytes(data).get(function)
|
||||
require(body is not None, 'reachability function missing: ' + function)
|
||||
lines = body.splitlines(keepends=True)
|
||||
hits = [b''.join(lines[i:i + line_count]) for i in range(len(lines) - line_count + 1)
|
||||
if hashlib.sha256(b''.join(lines[i:i + line_count])).hexdigest() == digest]
|
||||
require(len(hits) == 1, 'reachability anchor missing/ambiguous: ' + function)
|
||||
return hits[0]
|
||||
|
||||
|
||||
def source_delta(base, head):
|
||||
"""Compute changed function units from Git, including added/deleted files.
|
||||
|
||||
Only game autoload/scripts GDScript belongs to this applicability scope.
|
||||
The complete tested map still pins every supplied dependency separately.
|
||||
"""
|
||||
paths = git_bytes('diff', '--no-ext-diff', '--no-renames', '--name-only', '-z',
|
||||
base + '..' + head, '--', 'autoload/', 'scripts/').split(b'\0')
|
||||
base_paths = set(git_bytes('ls-tree', '-r', '--name-only', '-z', base).split(b'\0'))
|
||||
head_paths = set(git_bytes('ls-tree', '-r', '--name-only', '-z', head).split(b'\0'))
|
||||
delta = []
|
||||
for encoded in sorted(p for p in paths if p.endswith(b'.gd')):
|
||||
path = encoded.decode('utf-8')
|
||||
old = function_bytes(git_bytes('show', base + ':' + path)) if encoded in base_paths else {}
|
||||
new = function_bytes(git_bytes('show', head + ':' + path)) if encoded in head_paths else {}
|
||||
for name in sorted(old.keys() | new.keys()):
|
||||
if old.get(name) != new.get(name):
|
||||
delta.append({'path': path, 'function': name})
|
||||
return delta
|
||||
|
||||
|
||||
def boundary_conditions(path, function):
|
||||
# Conservative coverage: new/changed Runtime setup can reach every boundary.
|
||||
if path == 'autoload/simulation_runtime.gd':
|
||||
if any(word in function for word in ('relationship', 'restore', 'snapshot', 'save')):
|
||||
return {'save_restore'}
|
||||
return set(REQUIRED) | {'EV'}
|
||||
if '/relationship/' in path or '/save/' in path:
|
||||
return {'save_restore'}
|
||||
if any(part in path for part in ('/world/', '/transport/', '/staff/')):
|
||||
return {'exit_release', 'closure_release', 'shift_completion', 'EV', 'save_restore'}
|
||||
# No inferred non-impact exemption for previously unseen dependencies.
|
||||
return set(REQUIRED) | {'EV'}
|
||||
|
||||
|
||||
def applicability(index, spec, source, head):
|
||||
registered = spec['current_source_pins']
|
||||
require(index.get('registered_pins') == registered, 'registered pin declaration')
|
||||
for path, digest in registered.items():
|
||||
require(hashlib.sha256(git_bytes('show', REGISTERED_COMMIT + ':' + path)).hexdigest() == digest,
|
||||
'registered Git pin: ' + path)
|
||||
require(index.get('versions') == {'execution_origin': EXECUTION_ORIGIN,
|
||||
'registered': REGISTERED_COMMIT, 'tested': head, 'integration': None}, 'version roles')
|
||||
# Refuse uncommitted game bytes; otherwise Git diff would not describe tested.
|
||||
game_paths = git_bytes('ls-tree', '-r', '--name-only', '-z', head, '--', 'autoload/', 'scripts/').split(b'\0')
|
||||
for encoded in game_paths:
|
||||
if not encoded.endswith(b'.gd'):
|
||||
continue
|
||||
path = encoded.decode('utf-8')
|
||||
require(path in source and sha(safe(ROOT, path)) == hashlib.sha256(git_bytes('show', head + ':' + path)).hexdigest(),
|
||||
'tested game differs from Git: ' + path)
|
||||
delta = source_delta(REGISTERED_COMMIT, head)
|
||||
require(index.get('applicability_delta') == delta, 'git diff/applicability_delta mismatch')
|
||||
for path, names in ORDER_FUNCTIONS.items():
|
||||
old = function_bytes(git_bytes('show', REGISTERED_COMMIT + ':' + path))
|
||||
new = function_bytes(safe(ROOT, path).read_bytes())
|
||||
for name in names:
|
||||
require(name in old and name in new and old[name] == new[name], 'stale ordering function: ' + path + ':' + name)
|
||||
bindings = index.get('delta_cases')
|
||||
require(isinstance(bindings, dict) and set(bindings) == {r['path'] + ':' + r['function'] for r in delta}, 'delta case bindings')
|
||||
for row in delta:
|
||||
key = row['path'] + ':' + row['function']
|
||||
required = boundary_conditions(row['path'], row['function'])
|
||||
cases = bindings[key]
|
||||
require(isinstance(cases, dict) and set(cases) == required, 'boundary delta coverage: ' + key)
|
||||
for cid, case_id in cases.items():
|
||||
declaration = index['reachability']['EV'] if cid == 'EV' else index['conditions'][cid]
|
||||
require(case_id == declaration.get('case_id'), 'boundary delta engine case: ' + key)
|
||||
|
||||
|
||||
def coverage(index, raw, source):
|
||||
authority = index['authority']
|
||||
for ref in {r for _, refs, _ in REQUIRED.values() for r in refs}:
|
||||
@@ -174,11 +292,12 @@ def coverage(index, raw, source):
|
||||
and decision['reason'].strip(), 'unsupported reach=false: ' + name)
|
||||
for ref in refs:
|
||||
require(ref.get('path') in source and ref.get('sha256') == source[ref['path']], 'reachability source pin')
|
||||
lines = safe(ROOT, ref['path']).read_text().splitlines()
|
||||
start, end = ref.get('start'), ref.get('end')
|
||||
require(type(start) is int and type(end) is int and 1 <= start <= end <= len(lines), 'reachability lines')
|
||||
require(ref.get('text') == '\n'.join(lines[start - 1:end]), 'reachability source text')
|
||||
require(set(REACH_REFS[name]) <= {(r['path'], r['start'], r['end']) for r in refs}, 'missing static reachability chain: ' + name)
|
||||
identity = (ref['path'], ref.get('function'), ref.get('anchor_sha256'), ref.get('line_count'))
|
||||
require(identity in REACH_REFS[name], 'unknown reachability anchor')
|
||||
resolve_anchor(safe(ROOT, ref['path']).read_bytes(), *identity[1:])
|
||||
require(len(refs) == len(REACH_REFS[name]) and set(REACH_REFS[name]) == {
|
||||
(r['path'], r['function'], r['anchor_sha256'], r['line_count']) for r in refs},
|
||||
'missing static reachability chain: ' + name)
|
||||
# Staff dispatch reserves task items before travel. A guest-only exclusion
|
||||
# must not hide this reachable EV reservation path.
|
||||
if name == 'EV':
|
||||
@@ -197,6 +316,324 @@ def coverage(index, raw, source):
|
||||
require(decision.get('reach') is False, 'transport reservation/payment exclusion')
|
||||
|
||||
|
||||
NATIVE_RUNS = {
|
||||
'actual-native': ('import', 'parse', 'repro'),
|
||||
'dependency-midnight-native': ('import', 'parse', 'repro'),
|
||||
'dependency-formal-native': ('import', 'parse', 'writer', 'reader'),
|
||||
}
|
||||
SAVE_POINTS = ('before', 'midnight', 'paused', 'after', 'next')
|
||||
SAVE_MEMBERS = {'journal.log', 'manifest.json', 'thumbnail.png', 'world.bin'}
|
||||
|
||||
|
||||
def native_file(base, name, pin):
|
||||
path = safe(base, name)
|
||||
require(type(pin.get('bytes')) is int and path.stat().st_size == pin['bytes'], 'native bytes: ' + name)
|
||||
require(sha(path) == pin.get('sha256'), 'native SHA: ' + name)
|
||||
return path
|
||||
|
||||
|
||||
def native_cleanup(value):
|
||||
require(value.get('engine_ended') is True and value.get('errors') == []
|
||||
and literal(value.get('actual_process_exit_code'), 0), 'native cleanup failed')
|
||||
attempts = value.get('attempts')
|
||||
require(isinstance(attempts, list) and attempts, 'native cleanup attempts missing')
|
||||
for attempt in attempts:
|
||||
require(attempt.get('errors') == [] and attempt.get('kill_attempted') is False
|
||||
and attempt.get('wait_completed') is True
|
||||
and literal(attempt.get('wait_returned_code'), 0), 'native cleanup abnormal wait')
|
||||
|
||||
|
||||
def native_ownership(base):
|
||||
provenance = load(safe(base, 'OWNERSHIP_RAW_PROVENANCE.json'))['copied']
|
||||
targets = set()
|
||||
for row in provenance:
|
||||
require(row['target'] not in targets, 'duplicate native provenance target')
|
||||
targets.add(row['target'])
|
||||
native_file(base, row['target'], row)
|
||||
pids = {}
|
||||
for run, phases in NATIVE_RUNS.items():
|
||||
execution = load(safe(base, run + '/execution.json'))
|
||||
inputs = load(safe(base, run + '/runner-input.json'))
|
||||
require([p['phase'] for p in execution['phases']] == list(phases), 'native phase membership')
|
||||
run_pids = []
|
||||
cleanups = []
|
||||
for phase, phase_receipt in zip(phases, execution['phases']):
|
||||
prefix = run + '/' + phase + '/'
|
||||
names = ('started.json', 'process.json', 'ended.json', 'outer-owned-finally.json',
|
||||
'adapter-owned-cleanup.json', 'stdout.log', 'stderr.log', 'engine-native.log')
|
||||
require({prefix + n for n in names} <= targets, 'native provenance lifecycle missing')
|
||||
start, process, end, outer, cleanup = [load(safe(base, prefix + n)) for n in names[:5]]
|
||||
pid = start['actual_pid']
|
||||
require(type(pid) is int and pid > 0 and pid not in pids.values(), 'native PID reused')
|
||||
require(start['pid'] == process['pid'] == end['pid'] == end['actual_pid'] == pid,
|
||||
'native PID chain')
|
||||
require(start['event'] == 'ENGINE_STARTED' and end['event'] == 'ENGINE_ENDED'
|
||||
and start['owner_pid'] == end['owner_pid'] == inputs['owner_runner_pid']
|
||||
and start['command'] == start['argv'] == process['argv'] == end['argv'] == end['command']
|
||||
and start['monotonic_ns'] < end['monotonic_ns'], 'native lifecycle identity')
|
||||
require(process['actual_start_binding'] == start and process['actual_end_binding'] == end,
|
||||
'native process bindings')
|
||||
require(start['current_process_identity']['pid'] == pid
|
||||
and start['current_process_identity']['ppid'] == start['owner_pid'], 'native owner identity')
|
||||
require(load(safe(base, run + '/' + phase + '-receipt.json')) == phase_receipt
|
||||
== load(safe(base, run + '/' + phase + '-actual-phase.json')), 'native phase receipt binding')
|
||||
for record in (process, end, phase_receipt):
|
||||
require(literal(record.get('exit_code'), 0), 'native abnormal exit')
|
||||
require(end.get('engine_ended') is True and end.get('timed_out') is False
|
||||
and process.get('timed_out') is False and end.get('lifecycle_error') is None
|
||||
and process.get('lifecycle_error') is None and literal(end.get('actual_process_exit_code'), 0)
|
||||
and phase_receipt.get('engine_ended') is True, 'native abnormal end')
|
||||
require(phase_receipt['actual_pid'] == pid and phase_receipt['native_process'] == process,
|
||||
'native execution process binding')
|
||||
require(outer['actual_captured_pids'] == [pid] and outer['outer_cleanup_errors'] == []
|
||||
and outer.get('all_captured_ended') is True and outer.get('adapter_exception') is None
|
||||
and len(outer['cleanup']) == 1 and outer['cleanup'][0]['pid'] == pid
|
||||
and outer['cleanup'][0]['outer_cleanup_errors'] == []
|
||||
and outer['cleanup'][0]['cleanup'] == cleanup == process['adapter_owned_cleanup'],
|
||||
'native owned cleanup binding')
|
||||
native_cleanup(cleanup)
|
||||
for stream in ('stdout', 'stderr'):
|
||||
require(sha(safe(base, prefix + stream + '.log')) == process[stream + '_sha256'],
|
||||
'native stream hash')
|
||||
for field in ('stdout', 'stderr'):
|
||||
require(safe(base, prefix + field + '.log').is_file(), 'native log missing')
|
||||
native_file(base, prefix + 'engine-native.log', phase_receipt['raw_native_log'])
|
||||
pids[run + '/' + phase] = pid
|
||||
run_pids.append(pid)
|
||||
cleanups.extend(outer['cleanup'])
|
||||
require(execution['actual_captured_PIDs'] == run_pids and execution['cleanup'] == cleanups
|
||||
and execution['cleanup_errors'] == [], 'native execution cleanup membership')
|
||||
formal = 'dependency-formal-native/'
|
||||
records = [load(safe(base, formal + 'restart-evidence/' + role + '.json')) for role in ('writer', 'reader')]
|
||||
require(records[0]['profile'] != records[1]['profile'], 'native writer reader profile reused')
|
||||
for role, record in zip(('writer', 'reader'), records):
|
||||
require(record['pid'] == pids[formal + role], 'native writer reader PID binding')
|
||||
profile = load(safe(base, formal + role + '-profile.json'))
|
||||
phase = load(safe(base, formal + role + '-receipt.json'))
|
||||
require(record['profile'] == profile['actual_user_data_dir'] == profile['expected_user_data_dir']
|
||||
== phase['controlled_environment']['THE_TREE_PACK_PROFILE_EXPECTED'], 'native profile binding')
|
||||
require(record['slots'] == {p: record['profile'] + '/saves/p04_boundary/' + p for p in SAVE_POINTS},
|
||||
'native formal profile slots')
|
||||
return pids
|
||||
|
||||
|
||||
def native_applicability(base):
|
||||
"""Production evidence identity, separate from A/B checkout applicability."""
|
||||
app = load(safe(base, 'POST_P18_CURRENT_SOURCE_APPLICABILITY.json'))
|
||||
production = app['production_commit']
|
||||
require(re.fullmatch('[0-9a-f]{40}', production) is not None, 'native production commit')
|
||||
registered = load(SPEC)['current_source_pins']
|
||||
pin_rows = app['registered_source_pins']
|
||||
require(len(pin_rows) == len(registered) and {r['path'] for r in pin_rows} == set(registered),
|
||||
'native current_source_pins membership')
|
||||
current = {}
|
||||
for row in pin_rows:
|
||||
path = row['path']
|
||||
current[path] = hashlib.sha256(git_bytes('show', production + ':' + path)).hexdigest()
|
||||
require(row['registered_sha256'] == registered[path] and row['production_sha256'] == current[path],
|
||||
'native current_source_pins mismatch')
|
||||
rows = app['ordering_functions']
|
||||
require(len(rows) == sum(map(len, ORDER_FUNCTIONS.values())) and
|
||||
{(r['path'], r['function']) for r in rows} == {(p, f) for p, fs in ORDER_FUNCTIONS.items() for f in fs},
|
||||
'native ordering membership')
|
||||
for path, functions in ORDER_FUNCTIONS.items():
|
||||
old = function_bytes(git_bytes('show', REGISTERED_COMMIT + ':' + path))
|
||||
new = function_bytes(git_bytes('show', production + ':' + path))
|
||||
for function in functions:
|
||||
row = next(r for r in rows if (r['path'], r['function']) == (path, function))
|
||||
body = new[function]
|
||||
require(old[function] == body and hashlib.sha256(body).hexdigest() ==
|
||||
row['production_body_sha256'] == row['registered_body_sha256'],
|
||||
'native ordering bytes')
|
||||
for run, result in zip(NATIVE_RUNS, ('SHIFT_CURRENT', 'DEPENDENCY_MIDNIGHT', 'DEPENDENCY_FORMAL')):
|
||||
summary = load(safe(base, 'ROOT_APPROVED_' + result + '_RESULT.json'))
|
||||
require(summary['production_commit'] == production, 'native production commit mismatch')
|
||||
inputs = load(safe(base, run + '/runner-input.json'))
|
||||
for path, digest in current.items():
|
||||
require(inputs['source_before'][path]['sha256'] == digest
|
||||
== inputs['selected_source_map'][path], 'native input source pin mismatch')
|
||||
return production
|
||||
|
||||
|
||||
def native_saves(base):
|
||||
prefix = 'dependency-formal-native/'
|
||||
execution = load(safe(base, prefix + 'execution.json'))
|
||||
before, after = execution['formal_before'], execution['formal_after']
|
||||
require(set(before) == set(after) == set(SAVE_POINTS) and before == after, 'native original members changed')
|
||||
summary = load(safe(base, 'ROOT_APPROVED_DEPENDENCY_FORMAL_RESULT.json'))
|
||||
members = summary['formal_member_pins']
|
||||
require(len(members) == 20 and {(r['point'], r['member']) for r in members} ==
|
||||
{(p, m) for p in SAVE_POINTS for m in SAVE_MEMBERS}, 'native formal member membership')
|
||||
for point in SAVE_POINTS:
|
||||
require(set(before[point]) == SAVE_MEMBERS, 'native original member missing')
|
||||
for member in SAVE_MEMBERS:
|
||||
for role in ('writer', 'reader'):
|
||||
path = native_file(base, prefix + 'formal-packages/' + role + '/' + point + '/' + member, before[point][member])
|
||||
row = next(r for r in members if (r['point'], r['member']) == (point, member))
|
||||
require(sha(path) == row['sha256'], 'native formal member pin')
|
||||
typed = summary['typed_outputs_14_sha_match_original_native']
|
||||
expected = {role + '-' + p + suffix + '.var': p for p in SAVE_POINTS
|
||||
for role, suffix in (('writer', '-persisted'), ('reader', '-loaded'))}
|
||||
expected.update({'reader-replayed-' + p + '.var': p for p in SAVE_POINTS if p != 'before'})
|
||||
require(len(typed) == len(expected) and {Path(r['output']).name for r in typed} == set(expected),
|
||||
'native typed member membership')
|
||||
inputs = load(safe(base, prefix + 'runner-input.json'))['fixed_input_pins']
|
||||
for row in typed:
|
||||
name = Path(row['output']).name
|
||||
original = 'midnight-' + expected[name] + '.var'
|
||||
require(Path(row['original']).name == original, 'native typed original identity')
|
||||
source = safe(base, 'dependency-midnight-native/order-evidence/' + original)
|
||||
output = safe(base, prefix + 'restart-evidence/' + name)
|
||||
require(sha(source) == sha(output) == row['sha256'], 'native typed SHA mismatch')
|
||||
pin = [p for p in inputs if p['path'] == row['original']]
|
||||
require(len(pin) == 1, 'native typed input missing')
|
||||
native_file(base, 'dependency-midnight-native/order-evidence/' + original, pin[0])
|
||||
|
||||
|
||||
def receipt_rows(receipts):
|
||||
"""Keep multiplicity: sets must never hide duplicated ledger rows."""
|
||||
require(isinstance(receipts, list), 'native receipts missing')
|
||||
ids, rows = set(), []
|
||||
for receipt in receipts:
|
||||
require(receipt['id'] not in ids and receipt['rows'], 'native duplicate/empty receipt')
|
||||
ids.add(receipt['id'])
|
||||
for row in receipt['rows']:
|
||||
require(row['transaction_id'] == receipt['id'] and type(row['amount']) is int
|
||||
and row['amount'] >= 0, 'native receipt transaction')
|
||||
require(row not in rows, 'native duplicate receipt row')
|
||||
rows.append(row)
|
||||
return rows
|
||||
|
||||
|
||||
def native_ledger(base):
|
||||
prefix = 'dependency-midnight-native/order-evidence/'
|
||||
observations = load(safe(base, prefix + 'observations.json'))
|
||||
series = observations['observations']
|
||||
require(len(series) == len(SAVE_POINTS), 'native observation series missing')
|
||||
initial = series[0]
|
||||
service = initial['service']
|
||||
require(service['state'] == 'ACTIVE' and service['elapsed_minutes'] == service['duration_minutes'] - 1,
|
||||
'native initial service progress')
|
||||
identity = ('service_id', 'request_id', 'facility_id', 'guest_ids', 'inventory_reservations', 'price_snapshot')
|
||||
require(service['inventory_reservations'] and len(service['guest_ids']) == 1, 'native service identity missing')
|
||||
guest_id = service['guest_ids'][0]
|
||||
account = 'GUEST_WALLET:' + guest_id
|
||||
final_state = load(safe(base, prefix + 'midnight-after.json'))['systems']['runtime']
|
||||
links = [r for r in final_state['economy']['idempotency'] if r['key'] == 'service.payment.' + service['service_id']]
|
||||
require(len(links) == 1, 'native service idempotency missing/duplicate')
|
||||
transaction = links[0]['transaction_id']
|
||||
previous_rows = []
|
||||
states = []
|
||||
for position, (point, observation) in enumerate(zip(SAVE_POINTS, series)):
|
||||
snapshot = load(safe(base, prefix + 'midnight-' + point + '.json'))
|
||||
state = snapshot['systems']['runtime']
|
||||
states.append(state)
|
||||
facilities = [f for f in state['facilities']['instances'] if f['instance_id'] == service['facility_id']]
|
||||
require(len(facilities) == 1, 'native facility identity')
|
||||
facility = facilities[0]
|
||||
if position == 0:
|
||||
definition_id = facility['definition_id']
|
||||
require(re.fullmatch('[a-zA-Z0-9_]+', definition_id) is not None, 'native definition identity')
|
||||
definition_path = 'data/facilities/' + definition_id + '.tres'
|
||||
production = load(safe(base, 'POST_P18_CURRENT_SOURCE_APPLICABILITY.json'))['production_commit']
|
||||
definition = git_bytes('show', production + ':' + definition_path)
|
||||
inputs = load(safe(base, 'dependency-midnight-native/runner-input.json'))
|
||||
require(inputs['selected_source_map'][definition_path] ==
|
||||
inputs['source_before'][definition_path]['sha256'] == hashlib.sha256(definition).hexdigest(),
|
||||
'native original definition pin')
|
||||
for field, value in (('base_price', service['price_snapshot']), ('base_service_minutes', service['duration_minutes'])):
|
||||
matches = re.findall(rb'(?m)^' + field.encode() + rb' = ([0-9]+)$', definition)
|
||||
require(len(matches) == 1 and int(matches[0]) == value == facility[field], 'native original definition value')
|
||||
current = observation['service']
|
||||
require(all(current[k] == service[k] for k in identity), 'native service identity changed')
|
||||
require(observation['minute'] == initial['minute'] + position == snapshot['clock']['absolute_minute'],
|
||||
'native minute series')
|
||||
require(current in state['facilities']['service_history'] or any(
|
||||
current in f['active_services'] for f in state['facilities']['instances']), 'native service snapshot binding')
|
||||
require(observation['reservations'] == state['inventory'], 'native reservation snapshot binding')
|
||||
rows = receipt_rows(observation['receipts'])
|
||||
ledger = state['economy']['entries']
|
||||
initial_ledger = states[0]['economy']['entries']
|
||||
require(ledger[:len(initial_ledger)] == initial_ledger and ledger[len(initial_ledger):] == rows,
|
||||
'native ledger receipt delta')
|
||||
require(rows[:len(previous_rows)] == previous_rows, 'native receipt history changed')
|
||||
wallet_delta = sum(r['amount'] * ((r['debit_account'] == account) - (r['credit_account'] == account)) for r in rows)
|
||||
require(observation['wallet'] == initial['wallet'] + wallet_delta, 'native wallet delta')
|
||||
require(observation['wallet'] == sum(r['amount'] * ((r['debit_account'] == account) -
|
||||
(r['credit_account'] == account)) for r in ledger), 'native ledger wallet balance')
|
||||
if observation['guest']:
|
||||
require(observation['guest']['wallet_gold'] == observation['wallet']
|
||||
and observation['guest']['guest_id'] == guest_id, 'native guest wallet binding')
|
||||
else:
|
||||
require(point == 'next', 'native guest missing before completion')
|
||||
sales = [r for r in rows if r['category'] == 'SERVICE_SALE']
|
||||
paused = current['state'] == 'PAUSED'
|
||||
if position in (1, 2):
|
||||
require(paused and current['interruption_reason'] == 'RELATED_FACILITY_INACTIVE'
|
||||
and current['elapsed_minutes'] == service['elapsed_minutes'] and not sales,
|
||||
'native PAUSED sale/progress/reason')
|
||||
elif position >= 3:
|
||||
require(current['state'] == 'COMPLETED' and len(sales) == 1
|
||||
and current['elapsed_minutes'] == current['duration_minutes'], 'native completion sale count')
|
||||
sale = sales[0]
|
||||
require(sale['transaction_id'] == transaction and sale['credit_account'] == account
|
||||
and sale['source_entity_id'] == service['facility_id']
|
||||
and sale['debit_account'] == 'FACILITY_REVENUE:' + service['facility_id']
|
||||
and sale['amount'] == service['price_snapshot']
|
||||
and sale['absolute_minute'] == current['completed_at'], 'native sale service join')
|
||||
reservations = observation['reservations']['reservations']
|
||||
require(len(reservations) == len(service['inventory_reservations']) and
|
||||
{r['reservation_id'] for r in reservations} == set(service['inventory_reservations']),
|
||||
'native orphan reservation membership')
|
||||
requests = state['facilities']['requests']
|
||||
matching_requests = [r for r in requests if r['request_id'] == service['request_id']]
|
||||
require(len(matching_requests) == (1 if position < 3 else 0), 'native request series')
|
||||
if matching_requests:
|
||||
request = matching_requests[0]
|
||||
require(request['facility_id'] == service['facility_id'] and request['guest_ids'] == service['guest_ids']
|
||||
and request['quoted_price'] == service['price_snapshot']
|
||||
and request['reserved_inventory_ids'] == service['inventory_reservations'], 'native request service join')
|
||||
for reservation in reservations:
|
||||
require(reservation['requester_id'] == service['request_id']
|
||||
and reservation['owner_inventory_id'] == 'facility.inventory:' + service['facility_id']
|
||||
and reservation['state'] == ('ACTIVE' if position < 3 else 'CONSUMED'),
|
||||
'native orphan reservation relation')
|
||||
previous_rows = rows
|
||||
require(receipt_rows(observations['first_receipts']) == previous_rows
|
||||
== receipt_rows(observations['replay_receipts']), 'native midnight replay receipts')
|
||||
reader = load(safe(base, 'dependency-formal-native/restart-evidence/reader.json'))
|
||||
require(len(reader['results']) == 1 and receipt_rows(reader['results'][0]['receipts']) == previous_rows,
|
||||
'native reader receipt delta')
|
||||
sweep = [r for r in previous_rows if r['category'] == 'SERVICE_CASH_SWEEP']
|
||||
require(len(sweep) == 1 and sweep[0]['transaction_id'] == transaction
|
||||
and sweep[0]['amount'] == service['price_snapshot']
|
||||
and sweep[0]['credit_account'] == 'FACILITY_REVENUE:' + service['facility_id']
|
||||
and sweep[0]['debit_account'] == 'PLAYER_CASH', 'native sale cash sweep')
|
||||
maintenance = [r for r in previous_rows if r['category'].startswith('MAINTENANCE_')]
|
||||
accruals = [r for r in maintenance if r['category'] == 'MAINTENANCE_ACCRUAL']
|
||||
payments = [r for r in maintenance if r['category'] == 'MAINTENANCE_PAYMENT']
|
||||
require(accruals and len(accruals) == len(payments), 'native maintenance pairs')
|
||||
for accrual in accruals:
|
||||
matches = [r for r in payments if r['transaction_id'] == accrual['transaction_id']
|
||||
and r['source_entity_id'] == accrual['source_entity_id'] and r['amount'] == accrual['amount']
|
||||
and r['absolute_minute'] == series[1]['minute'] == accrual['absolute_minute'] + 1]
|
||||
require(len(matches) == 1, 'native maintenance accrual/payment join')
|
||||
return {'service_id': service['service_id'], 'transaction_id': transaction,
|
||||
'receipt_rows': len(previous_rows), 'formal_original_credit': 0}
|
||||
|
||||
|
||||
def verify_native(base):
|
||||
"""Finite C-layer check, never a replacement for the 15+EV whole gate."""
|
||||
for row in load(safe(base, 'SOURCE_MANIFEST.json'))['files']:
|
||||
native_file(base, row['copy'], row)
|
||||
production = native_applicability(base)
|
||||
pids = native_ownership(base)
|
||||
native_saves(base)
|
||||
result = native_ledger(base)
|
||||
return dict(result, production_commit=production, owned_processes=len(pids),
|
||||
verified_conditions=['dependency_stop', 'recovery_completion', 'paused_midnight'])
|
||||
|
||||
|
||||
def verify(directory):
|
||||
# Contract hashes the supplied spec string, while the checked-in JSON has
|
||||
# one final LF. Accept only that exact representation difference.
|
||||
@@ -213,8 +650,7 @@ def verify(directory):
|
||||
require(index.get('candidate_commit') == head, 'candidate_commit mismatch')
|
||||
source = index.get('source_map')
|
||||
pins(source, ROOT)
|
||||
for name, digest in spec['current_source_pins'].items():
|
||||
require(source.get(name) == digest, 'immutable source pin: ' + name)
|
||||
applicability(index, spec, source, head)
|
||||
oldmap = load(ROOT / 'docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/historical-source-map.json')
|
||||
required = {p for p in oldmap if p.endswith('.gd') and p.startswith(('autoload/', 'scripts/'))}
|
||||
require(required <= source.keys(), 'missing runtime/service dependency source pins')
|
||||
@@ -284,6 +720,19 @@ def verify(directory):
|
||||
require(result, name + ': predicate failed')
|
||||
require(index.get('review_status') in {'pending_review', 'approved'}, 'review status')
|
||||
coverage(index, raw, source)
|
||||
# Scalar conditions remain necessary declarations, never sufficient proof.
|
||||
binding = index.get('native_bundle')
|
||||
require(isinstance(binding, dict), 'native bundle required; self-reported scalar evidence is insufficient')
|
||||
manifest = safe(evidence, binding['manifest'])
|
||||
require(manifest.name == 'OWNERSHIP_RAW_PROVENANCE.json' and sha(manifest) == binding['sha256'],
|
||||
'native bundle provenance pin')
|
||||
native = verify_native(manifest.parent)
|
||||
require(native['production_commit'] == head, 'native production/tested mismatch; A/B reuse coverage required')
|
||||
# This adapter covers only the supplied dependency/formal series. Never
|
||||
# promote it to the missing original scenarios through scalar booleans.
|
||||
missing = (set(REQUIRED) | {'EV'}) - set(native['verified_conditions'])
|
||||
require(not missing, 'uncollected original boundaries: ' + ', '.join(sorted(missing)) +
|
||||
'; formal_original_credit=0')
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
Reference in New Issue
Block a user