P04-01: 同時発生の更新規約

This commit is contained in:
Agent Control Runner
2026-10-15 23:15:15 +09:00
parent a19737b160
commit 9767b0a28c
6 changed files with 664 additions and 38 deletions
@@ -2,7 +2,7 @@
`python3 tools/check_p04_order_evidence.py --verify-only` は環境変数 `BUILD_OUTPUT_DIR` の `p04-evidence/index.json` を読み、書込み・試験・Runner操作をしない。欠落時は非0。原30/88の受入・完了を確定しない。
このdispatchではD05が未承認であるため、検証器は常に非0で終了する。indexのapproved/pass宣言で解除できない。これは初期監査の制限であり、全条件を機械的に検証できる完成版gateではない。承認済み原規約と生証跡が供給された後、別契約でsemantic coverageとnative provenanceの検証を追加する必要がある。
D05-P04-DEPENDENCYとD05-P04-SHIFT-1800は承認済み。固定必須条件と証拠が揃えばmachine_verified=true、formal_acceptance=false、exit 0。残るD05の帰属pendingを一括failにしない。必須authority pending・証拠欠落は非0。独立レビュー・通常統合までは正式受入0。
内部JSON形式は `P04_ORDER_EVIDENCE_PROTOCOL.json` を基に次の有限サブセットを実装した。重複JSONキー、NaN/Infinity、絶対・親参照・symlink・重複artifact pathを拒否する。全ハッシュは生バイトSHA256。indexに合格booleanや試験数があっても判定には使用しない。
@@ -12,9 +12,28 @@
- `artifacts`: ID→`path`, `bytes`(整数), `sha256`, `type`。typeは observation/state/receipt/stdout/native_log/save/authority のいずれか。
- `authority`: ref→`status`(original/approved), `artifact_id`。raw文書の存在を確認するが内容の原規約適合は独立レビューを要する。pendingは失敗。
- `domains`: 正確な7領域名→`source_refs`, `authority_refs`, `cases`, `invariants`, `applicability`。source_refは `path/function/sha256`。applicabilityはindexと同じ `source_map/environment`。
- 各caseは一意な `id` とartifact IDの `input/before/operation/after/receipt`。receipt JSONは正整数 `start_pid`、同じ `end_pid`、整数 `exit_code: 0`、`engine_ended: true`、一致する `source_map/environment`、raw `stdout/native_log` artifact IDを要求する。自己申告receiptとrawログの意味的結合、別PID保存member一致は未対応であり合格扱いしない。
- 各caseは一意な `id` とartifact IDの `input/before/operation/after/receipt`。receipt JSONは正整数 `start_pid`、同じ `end_pid`、整数 `exit_code: 0`、`engine_ended: true`、一致する `source_map/environment`、raw `stdout/native_log` artifact IDを要求する。receiptのcase_idとinput/before/operation/afterのartifact_hashesを照合する。caseにもraw_origin=engineを要求する。ログの意味と実行由来の独立確認はRoot/reviewerが行う。
- 各invariantは `artifact_id/json_pointer/operator/authority_ref/raw_origin`。raw_originはengineのみ。root derivationはformula検証未対応のため拒否する。RFC6901 pointerでraw JSONから値を読む。eqはexpectedとの型を含むliteral一致、nonnegativeはboolean以外の数値が0以上、count_eqは配列/辞書長と整数expectedの一致。same_literal/distinctは `paired_artifact_id/paired_json_pointer` の値との型を含む比較。未知operatorは失敗。
期待値の承認根拠、停止中帳簿不変、決算再送/再開一回、予約とlive targetの対応、payment identity重複なし、必須case coverageを構造チェックだけで証明しない。最後にD05とsemantic/native証明の不足を明示して失敗させる。
## 固定必須条件
Runner向け最小確認: index欠落、重複キー、symlink/traversal、hash/size不一致、stale source、未実行receipt、未知predicate、pending authority、7領域欠落が非0になること。その後、D05が未承認の完全形indexでも非0であること。正式境界試験は監査の有限計画に沿い、不適用の旧証拠だけを置き換える。workerはこれらを実行していない。
checkerのREQUIREDが唯一の必須条件定義であり、indexから条件を受け取らない。conditionsはそのIDと完全一致するmap。各値はcase_id、固定順のauthority_refs、nativeWindows: pending。各条件は指定domainのengine caseと全metricのeq invariantを必要とする。観測はcase.afterの /conditions/<condition_id>/<metric> に置き、invariantのcase_id、artifact_id、pointer、expectedを固定定義と照合する。pass booleanや試験数は使わない。測定値は実際のengine観測から出すこと。手書き合成fixtureはchecker分岐検証専用であり、受入証拠には使用不可。
- 停止課金0: power_stop / destruction_stop / dependency_stop。依存先停止は進捗差分0・予約とservice ID保持も必要。
- 完了・課金1回: shift_completion(1080、交代前)/ recovery_completion / same_minute_replay(再送・重複生成0)。
- 孤立0: closure_release / exit_release / patience_release / paused_midnight。直接休業ではD-034の開始済み継続と待機予約解放を区別。停止日跨ぎは停止中課金0と復帰完了課金各1回。
- 決算1回: midnight_settlement / midnight_replay / save_restore。売上・給与・維持費・勤務分の支払い各1回、非ゼロ給与を必須とし、帰属先は新しく決めない。
- night_staff_absent: 1081、夜番0、WAITING_FOR_STAFF。
- overtime_task: 既存interrupt_level=0の残業と勤務分記録1回(staff_service:1409-1412)。
authorityの参照名はREQUIREDに固定。BASELINE文書、D-034文書、既存A01を記録した入力草案のraw bytesをcheckoutと照合する。A01を再承認しない。承認2条件はauthority typeの同梱D05_OWNER_APPROVAL.jsonと同一SHA256(4583ee9aad45c4db183d72df4420df48aa8e0897e3b5efda13016f0b5cdbd68e)を要求する。origin=direct_user_reply、formal_acceptance=falseと承認IDも確認する。
save_restore条件にはsave_artifact(type=save)とrestore_receiptを追加する。元caseのreceiptのsaved_sha256、readerのrestored_sha256を保存raw hashと照合し、別の正整数PID・終了・exit 0・source/environment一致・stdout/native_logを要求する。保存packageの意味的完全性・正式保存APIの利用は生証拠の独立レビュー対象。
reachabilityはEV/transportのみ。各source_refはpath/sha256/start/end/textで、固定REACH_REFSの経路を全て含み、実際の行本文と一致すること。reason必須。救護搬送は課金予約reach=false。EVはスタッフ移動前予約経路があるためreach=trueとcase_idを必要とする。停電domainのengine case.afterのev.reserved_before_travel=true、power_stopped=true、orphan_reservations=0のeq invariantを要求する。客の到着後予約だけを根拠にEV全体を除外できない。
specは契約文字列hashと照合し、checkoutの末尾LF一つの表現差だけを許容する。その他のraw hashは正規化しない。
## worker確認
checker_negative_fixtures.pyはallowed_paths内の一時ディレクトリをBUILD_OUTPUT_DIRに使用し、終了後削除する。py_compile、対照用合成index(exit 0、正式受入false)、指定10負例(各exit 1、対応エラー)を確認済み。実engine試験・Runner操作は0。Runnerがp04-acceptanceを正式実行し、Rootが現版適用性、別セッションのreviewerが生証拠由来と意味を独立確認する。
@@ -0,0 +1,42 @@
{
"plan_id": "P04-01",
"decision_scope": "D05 dependency closure and 18:00 transaction order only",
"recorded_at": "2026-10-15T13:51:09.167952+00:00",
"origin": "direct_user_reply",
"question_item_ids": [
"[\"request_user_input_async\",\"call_cea3c55446014be4bde664de0ab8c381\",0]",
"[\"request_user_input_async\",\"call_cea3c55446014be4bde664de0ab8c381\",1]"
],
"approved_choices": [
{
"id": "D05-P04-DEPENDENCY",
"user_answer": "依存先の休業中は進捗・課金を停止し、予約を保持して復帰後に1回だけ完了する(Opus推奨・現状維持)",
"contract": "依存先の休業中は開始済みサービスの進捗と課金を停止し、予約とサービスIDを保持する。復帰後に残りを処理し、完了・課金は1回だけ。停止上限は新設しない。直接の休業操作はD-034を維持する。"
},
{
"id": "D05-P04-SHIFT-1800",
"user_answer": "17:59→18:00の昼番作業を先に確定し、完了・課金後に交代する(Opus推奨・現状維持)",
"contract": "[17:59,18:00)の昼番作業を先に確定し、必要時間に達したサービスを18:00に1回だけ完了・課金してから交代する。夜番は[18:00,18:01)から反映する。"
}
],
"proposal_sha256": "082c6a9e7d8d0648be261ae30e52983e10ed677eaf90ab872b7c9e19793f773c",
"required_validation": [
"停止中課金0",
"完了課金1回",
"予約の孤立0",
"同分再送",
"日跨ぎ",
"正式保存・別PID復元",
"夜番不在",
"既存残業タスク",
"7領域の現版への証拠適用性",
"必要検証・独立レビュー・通常統合"
],
"formal_acceptance": false,
"original_unit_complete": false,
"original_denominator": {
"packages": 30,
"units": 88
},
"remaining": "仕様選択は確定。条件ごとの既存証拠適用性確認と不足境界の検証、独立レビュー、通常統合は未完了。D05の他領域を一括解決したとは扱わない。"
}
@@ -1,6 +1,6 @@
# P04-01 監査状態
原単位は未完了。D05の閉店後開始済サービスと18:00最終勤務区間は未承認であり、現実装の観測を承認済み規約に置き換えない。A01の00:00保有時間按分維持費は承認済み。
原単位は未完了。D05-P04-DEPENDENCY と D05-P04-SHIFT-1800 は direct_user_reply により承認済み(同梱 D05_OWNER_APPROVAL.json、SHA256 4583ee9aad45c4db183d72df4420df48aa8e0897e3b5efda13016f0b5cdbd68e)。承認は試験合格を意味しない。A01の00:00保有時間按分維持費は承認済みで再確認しない。
正式試験はRunnerが実行する。旧証跡参照は来歴であり、現版の生証跡・ソース・設定・入力・環境の適用性確認なしに合格として再利用しない。
@@ -10,12 +10,12 @@
| 領域 | 現行呼出しと先後 | 原本・承認・不足 |
| --- | --- | --- |
| 閉店 | `_advance_facilities` の後、`_advance_guest_queues` が `_release_closed_business_queues` を実行し、patienceより先に予約解放を試みる。 | 閉店後開始済サービスはD05保留。旧business試験は部分候補。open serviceの00:00証拠を代用しない。 |
| 閉店 | `_advance_facilities` の後、`_advance_guest_queues` が `_release_closed_business_queues` を実行し、patienceより先に予約解放を試みる。 | 直接休業はD-034の開始済サービス継続。依存先休業は承認済D05の進捗・課金停止、予約・ID保持、復帰後1回完了。旧business試験は部分候補。open serviceの00:00証拠を代用しない。 |
| 停電 | `_advance_mana` → `mana_power_projection.apply` → FacilityService `_prepare_service_for_tick`。NO_POWERはpause、復電はresume。 | 草案の961停止/962復電/963不変は生証跡未確認。進捗・予約・帳簿・通知を現版で確認する必要がある。 |
| 破壊 | commandはAPPLY_COMMANDSで先行。`_advance_defense` は完了後のINCIDENTS。BROKENはサービス準備時に失敗。 | 先行破壊44と後段完了45を区別。失敗診断も保持し、原本適合と断定しない。 |
| 退出 | 公開queue leave → 完了 → INCIDENTS → queue patience解放 → AI再計画/予定退出。LEAVINGのdespawnは入状態分より後。 | 公開leave・自動patience・overdue退出の正式保存/別PID証跡は参照のみ。孤立0を現版で証明する必要がある。 |
| 課金 | `_complete_service` callback → `_complete_service_transaction` → `_apply_service_transaction`。予約消費後、service IDによるpayment keyで記帳し、通知scopeを終了。 | 原価格・時間を変えない。静的なidempotency keyの存在や試験数だけで二重課金・二重生成なしとしない。 |
| シフト交代 | 完了後の `_advance_staff_ai` 内でstaff更新・commute・staffing投影。 | 原本64/67行の18:00交代を保持。最終区間の解釈はD05保留。1080診断を承認規約に格上げしない。 |
| シフト交代 | 完了後の `_advance_staff_ai` 内でstaff更新・commute・staffing投影。 | 原本64/67行の18:00交代を保持。承認済D05により[17:59,18:00)は昼番、18:00完了・課金後に交代。夜番は[18:00,18:01)から。1080診断を承認規約に格上げしない。 |
| 00:00決算 | TIME_BOUNDARIESのweather/upkeep/operationsが完了より先。OperationsCoordinatorのdaily closeと同分service売上は別区間。 | 原本71/72行、承認済A01を保持。1440一回/1441不変の生証跡と適用性が必要。給与0fixtureを非ゼロ給与証拠に数えない。 |
## 再利用の制限
@@ -28,11 +28,25 @@
## 提出状態と有限検証計画
修正入力は内部index形式の設計を許可した。`tools/check_p04_order_evidence.py` と `CHECKER_PROTOCOL.md` を作成した。構造・pin・artifact hash・receipt項目・有限JSON比較を検証するが、native provenance、全必須境界coverage、原規約への意味的適合は未対応であり、このdispatchのD05未承認とともに必ず非0になる。初期監査をsubmittedとして提出し、machine gate利用可能・原成果完了とは扱わない。
今回の承認2条件と既存権限(BASELINE:64/67/71/72/183、D-034、A01)を分け、checker内の固定条件レジストリに対応付けた。費用時点・日跨ぎの帰属など残るD05はpendingのまま補完しないが、一括failの理由にはしない。売上・給与・維持費・勤務分の各1回、非ゼロ給与、停止の00:00またぎでも完了課金1回・予約孤立0は必須である。全条件を満たすとmachine_verified=true、formal_acceptance=false、exit 0。必須条件のauthorityがpendingなら失敗する。
1. RunnerがCHECKER_PROTOCOL.mdの負ケースでfailclosed動作を正式確認する。workerは試験未実行。
2. 生証跡・設定・入力・環境が揃う有限証拠だけ再利用する。Runtime/PathService変更に影響される到達性・勤務・退出境界を確認する。
3. D05承認後に閉店/18:00の依存境界だけ補完し、停止復電・先行後段破壊・公開/自動退出・00:00・再送/復元の不足分を絞る。A01を再確認しない。
4. semantic/native検証の不足を別契約で解消し、Runnerがp04-acceptanceと全条件の独立レビュー・統合を実施する。native Windows限定条件が必要なら個別保留とする。
承認4文書は全てバイト数とSHA256を再計算し、SOURCE_MANIFESTと一致。必要な承認JSONのみ2073 bytesを同梱した。初期空き容量約1.8GiB、旧39 artifactの複製なし。39件の原パスは来歴であり、今回のミラーは承認4文書のみ。生証拠・入力・設定・環境が不足しているので、境界の適用性合格は宣言しない。
試験・Runner操作・Git書込み・他エージェント起動は行っていない。原30パッケージ/88成果の既存1単位内の準備であり、成果追加0、正式完了0。
順序関数20本は今回個別に本文を再ハッシュし、供給されたhistorical_body_sha256と20/20一致した(詳細はJSON repair3)。旧監査の29本とは合算しない。旧Runtime rawも再ハッシュし、git diff --no-indexでは5個の@@区間(候補batchの開始・終了が別区間)、論理的な変更は記録の4箇所と確認した。関数一致は経路・候補・到着の適用性を保証しない。PathService変更を含め、停電・破壊・退出の影響ケースはRootが生証拠と設定を照合し、不適用の場合だけ新しい有限境界証拠を作る。production Runtime 4696df4aとcheckout d52a995の差も統合前にRootが確認する。
### 到達性
- 営業時間による閉店: autoload/scriptsの検索ではset_opening_hoursの定義とサービスの委譲のみ。既定[0,1440)で製品呼出しなし。直接休業と依存先休業の証拠は引き続き必須。
- 客の通常EV移動: Runtime:8898-8922の到着後にqueueを要求し、7421-7445で予約する。この移動前予約経路は対象外。
- スタッフEV: 対象外にできない。公開create_staff_task(Runtime:329、6733-6742)でrequired_itemsを渡せる。task_dispatcher:256-261、293-294、309-314が移動前に予約し、Runtime:9141-9170が在庫予約を実施、12009-12013で移動へ進み、8755-8763、8946-8987からEVを利用する。set_powered(elevator_service:279-284)による停電はこの予約保持経路に到達する。checkerはEV全体のreach=falseを拒否し、予約保持中停電のengine caseと孤立0 invariantを要求する。EV停止規則や期限は新設しない。
- 救護搬送: Runtime:12023-12030は治療状態を更新するだけ、12976-13050は救護タスク生成・移動・取消でrequired_items・課金処理を持たない。物理搬送自体でなく、課金・予約の到達性がfalse。静的根拠の行・本文・hashを必須とし、7領域の分母に加えない。
### 有限検証と残件
workerはpython3 -m py_compileとchecker_negative_fixtures.pyを実行。index欠落、重複キー、symlink、hash不一致、stale pin、未実行receipt、pending authority、必須条件欠落、根拠なしreach=false、承認hash不一致の10例が期待した理由でexit 1。合成対照のみexit 0であり、エンジン由来の製品証拠ではない。最初の対照実行はspec pinで失敗した。契約のspec文字列は末尾LFなし、checkout JSONは末尾LF一つ付きであり、その厳密な表現差のみ許容後、上記確認が通った。仕様ファイルは変更していない。
1. Runnerがp04-acceptanceを正式実行する。
2. Rootが旧証拠の適用性と不足を独立確認する。非ゼロ給与の00:00、停止の00:00またぎ、再送、正式保存→別PID復元、夜番不在18:01、既存残業タスク、予約保持中EV停電の証拠を揃える。
3. 別セッション独立レビューと通常統合のfinalまで正式受入加算0。nativeWindowsは条件ごとにpending。
エンジン実行・Runner操作・Git書込み・他エージェント起動は0。原30パッケージ/88成果の既存1単位内の準備であり、成果追加0、正式完了0。
@@ -0,0 +1,154 @@
#!/usr/bin/env python3
"""Synthetic checker fixtures only; never engine/acceptance evidence."""
import copy
import hashlib
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import sys
import tempfile
ROOT = Path(__file__).resolve().parents[5]
CHECKER = ROOT / 'tools/check_p04_order_evidence.py'
spec = importlib.util.spec_from_file_location('p04_checker', CHECKER)
gate = importlib.util.module_from_spec(spec)
sys.dont_write_bytecode = True
spec.loader.exec_module(gate)
def run():
results = []
with tempfile.TemporaryDirectory(prefix='.checker-fixtures-', dir=Path(__file__).parent) as temp:
base = Path(temp)
# Keep py_compile output inside allowed_paths; delete with the fixture.
env = dict(os.environ, PYTHONPYCACHEPREFIX=str(base / 'pycache'))
subprocess.run(['python3', '-m', 'py_compile', str(CHECKER)], env=env, check=True)
evidence = base / 'p04-evidence'
evidence.mkdir()
artifacts = {}
def add(aid, value, kind='observation'):
data = value if isinstance(value, bytes) else json.dumps(value).encode()
path = evidence / (aid + '.json')
path.write_bytes(data)
artifacts[aid] = dict(path=path.name, bytes=len(data),
sha256=hashlib.sha256(data).hexdigest(), type=kind)
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/'))}
add('fixture_environment', b'SYNTHETIC CHECKER FIXTURE - NOT AN ENGINE')
environment = dict(os='synthetic-checker-fixture', **{
k: {'fixture_environment.json': artifacts['fixture_environment']['sha256']}
for k in ('engine', 'configuration', 'inputs')})
add('baseline', (ROOT / 'docs/traceability/original/BASELINE.txt').read_bytes(), 'authority')
add('decisions', (ROOT / 'docs/DESIGN_DECISIONS.md').read_bytes(), 'authority')
add('a01', (ROOT / 'docs/plans/original-completion-2026-10-02/execution/p04-01-input-r01/ORDER_CONTRACT_DRAFT.md').read_bytes(), 'authority')
add('owner', (ROOT / 'docs/plans/original-completion-2026-10-02/execution/p04-01/D05_OWNER_APPROVAL.json').read_bytes(), 'authority')
authority = {ref: dict(status='approved', artifact_id=(
'owner' if ref.startswith('D05-P04-') else 'baseline' if ref.startswith('BASELINE:')
else 'decisions' if ref == 'D-034' else 'a01'))
for _, refs, _ in gate.REQUIRED.values() for ref in refs}
add('stdout', b'SYNTHETIC fixture log', 'stdout')
add('native_log', b'SYNTHETIC fixture log', 'native_log')
domains = {d: dict(source_refs=[dict(path='autoload/simulation_runtime.gd', function='_advance_facilities',
sha256=source['autoload/simulation_runtime.gd'])], authority_refs=[],
cases=[], invariants=[], applicability=dict(source_map=source, environment=environment))
for d in gate.DOMAINS}
conditions = {}
for cid, (d, refs, metrics) in gate.REQUIRED.items():
domain = domains[d]
domain['authority_refs'] = sorted(set(domain['authority_refs']) | set(refs))
case = dict(id=cid, raw_origin='engine')
for field in ('input', 'before', 'operation', 'after'):
case[field] = add(cid + '_' + field, {'conditions': {cid: metrics}} if field == 'after' else {'fixture': True})
receipt = dict(start_pid=101, end_pid=101, exit_code=0, engine_ended=True,
case_id=cid, source_map=source, environment=environment,
stdout='stdout', native_log='native_log',
artifact_hashes={f: artifacts[case[f]]['sha256'] for f in ('input', 'before', 'operation', 'after')})
condition = dict(case_id=cid, authority_refs=list(refs), nativeWindows='pending')
if cid == 'save_restore':
condition['save_artifact'] = add('save', b'SYNTHETIC save', 'save')
receipt['saved_sha256'] = artifacts['save']['sha256']
reader = dict(receipt, start_pid=102, end_pid=102, restored_sha256=artifacts['save']['sha256'])
condition['restore_receipt'] = add('reader', reader, 'receipt')
case['receipt'] = add(cid + '_receipt', receipt, 'receipt')
domain['cases'].append(case)
for metric, value in metrics.items():
domain['invariants'].append(dict(case_id=cid, artifact_id=case['after'],
json_pointer='/conditions/' + cid + '/' + metric, operator='eq', expected=value,
authority_ref=refs[0], raw_origin='engine'))
conditions[cid] = condition
# EV case has a separate, reachable reserved-staff scenario.
ev_case = copy.deepcopy(domains['停電']['cases'][0])
ev_case['id'] = 'ev_stop'
ev_case['after'] = add('ev_after', {'ev': dict(orphan_reservations=0, reserved_before_travel=True, power_stopped=True)})
receipt = gate.load(evidence / artifacts[ev_case['receipt']]['path'])
receipt['case_id'] = ev_case['id']
receipt['artifact_hashes']['after'] = artifacts['ev_after']['sha256']
ev_case['receipt'] = add('ev_receipt', receipt, 'receipt')
domains['停電']['cases'].append(ev_case)
domains['停電']['invariants'].append(dict(case_id='ev_stop', artifact_id='ev_after',
json_pointer='/ev/orphan_reservations', operator='eq', expected=0,
authority_ref='BASELINE:183', raw_origin='engine'))
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])
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')
original_files = {p.name:p.read_bytes() for p in evidence.iterdir()}
index = copy.deepcopy(index)
def check(name, mutate, error):
for p in evidence.iterdir():
p.unlink()
for name_, data in original_files.items():
(evidence / name_).write_bytes(data)
candidate = copy.deepcopy(index)
mutate(candidate)
if name != 'missing_index':
(evidence / 'index.json').write_text(json.dumps(candidate))
if name == 'duplicate_key':
(evidence / 'index.json').write_text('{"schema_version":1,"schema_version":1}')
proc = subprocess.run(['python3', str(CHECKER), '--verify-only'],
env=dict(os.environ, BUILD_OUTPUT_DIR=str(base)), text=True, capture_output=True)
output = json.loads(proc.stdout)
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('missing_index', lambda i: None, 'missing/outside')
check('duplicate_key', lambda i: None, 'duplicate JSON key')
def symlink(i):
(evidence / 'stdout.json').unlink()
(evidence / 'stdout.json').symlink_to(evidence / 'native_log.json')
check('symlink', symlink, 'symlink')
check('hash_mismatch', lambda i: i['artifacts']['stdout'].update(sha256='0'*64), 'artifact hash')
check('stale_pin', lambda i: i['source_map'].update({'autoload/simulation_runtime.gd':'0'*64}), 'stale pin')
def receipt_mutation(i):
aid = 'power_stop_receipt'
value = gate.load(evidence / artifacts[aid]['path'])
value['engine_ended'] = False
add(aid, value, 'receipt')
i['artifacts'][aid] = copy.deepcopy(artifacts[aid])
check('unexecuted_receipt', receipt_mutation, 'unexecuted/incomplete receipt')
check('pending_authority', lambda i: i['authority']['D05-P04-DEPENDENCY'].update(status='pending'), 'pending/missing authority')
check('missing_condition', lambda i: i['conditions'].pop('paused_midnight'), 'mandatory conditions')
check('unsupported_reach_false', lambda i: i['reachability']['transport'].update(reach=False, source_refs=[]), 'unsupported reach=false')
def owner_mutation(i):
aid = 'owner'
data = (evidence / 'owner.json').read_bytes() + b' '
add(aid, data, 'authority')
i['artifacts'][aid] = copy.deepcopy(artifacts[aid])
check('owner_hash_mismatch', owner_mutation, 'owner approval hash mismatch')
return dict(scope='Synthetic checker checks only; no engine evidence or formal acceptance',
py_compile=True, results=results)
if __name__ == '__main__':
print(json.dumps(run(), ensure_ascii=False, indent=2))
@@ -113,14 +113,29 @@
"missing_map_paths": [],
"task_id": "P04-01",
"base_commit": "deb1bcb2374eb378b840ca345db952bd8572cb6e",
"status": "blocked",
"status": "submitted",
"original_unit_complete": false,
"counted_units_added": 0,
"tests_executed": false,
"authority": {
"original": "docs/traceability/original/BASELINE.txt:64,67,71,72",
"approved": "A01: ownership-time apportioned upkeep at midnight; retained without reconfirmation",
"pending": "D05: started service after closure, final shift interval at 18:00, unresolved EV/transport stopping/cost/day crossing rules; no invented policy"
"owner_approved": {
"artifact": "D05_OWNER_APPROVAL.json",
"sha256": "4583ee9aad45c4db183d72df4420df48aa8e0897e3b5efda13016f0b5cdbd68e",
"bytes": 2073,
"origin": "direct_user_reply",
"formal_acceptance": false,
"conditions": [
"D05-P04-DEPENDENCY",
"D05-P04-SHIFT-1800"
],
"approval_is_not_test_pass": true
},
"existing": [
"BASELINE:64/67/71/72/183",
"D-034 docs/DESIGN_DECISIONS.md:252-258",
"A01 already approved; not reopened"
],
"remaining_pending": "Cost/day attribution remains pending; do not infer new policy. Required safety counts remain mandatory; no blanket D05 rejection."
},
"phase_order": "scripts/core/simulation_kernel.gd:123-153: APPLY_COMMANDS, clock increment/calendar boundary signals, TIME_BOUNDARIES, MANA, CONSTRUCTION, LOGISTICS, FACILITY_COMPLETION, VITALS_AND_ENVIRONMENT, INCIDENTS_AND_EVENTS, FACILITY_QUEUES, AI_DECISIONS, PUBLISH_SNAPSHOT. Handler IDs sorted lexically within phase at line242.",
"domains": [
@@ -132,9 +147,9 @@
"simulation_runtime._release_closed_business_queues",
"simulation_runtime._release_closed_business_request"
],
"order": "Facility completion precedes queue closure release; release occurs before patience spending. Started-service closure semantics remain D05 pending.",
"order": "Direct closure follows D-034: release waiting requests, continue started services. Dependency closure pauses progress/payment and preserves reservation/service IDs until recovery under D05-P04-DEPENDENCY.",
"old_evidence": "Historical phases 001/002: business closure/operations; midnight open-service proof cannot establish closure behavior.",
"missing": "Approved started-service closure rule and exact-version boundary raw proof."
"missing": "Exact-version direct/dependency closure evidence; approval is supplied, not a pass."
},
{
"domain": "停電",
@@ -192,9 +207,9 @@
"StaffService.advance_one_minute",
"simulation_runtime._sync_facility_staffing"
],
"order": "Facility completion precedes staff AI, commute and staffing projection. Final18:00 interval design meaning is D05 pending.",
"order": "Approved D05-P04-SHIFT-1800: [17:59,18:00) belongs to day shift, completion/payment once at 18:00 before switching; night shift begins [18:00,18:01).",
"old_evidence": "Historical phase083 hardening includes shift-end interruption; draft retains diagnostic1080 predicate failure without claiming original violation.",
"missing": "Approved final-interval rule then exact-version1080 boundary including nonzero cost where required."
"missing": "Applicable 1080 completion/replay, 1081 WAITING_FOR_STAFF with no night staff, and existing overtime task evidence."
},
{
"domain": "00:00決算",
@@ -212,23 +227,24 @@
],
"old_evidence_applicability": {
"raw_available_for_reuse": false,
"assessment": "Only local summaries/maps/draft read; original artifact paths remain provenance. No approved reuse asserted.",
"assessment": "39 references in supplied recheck retain old Runtime 2d7e2cea provenance; raw artifacts not supplied here. 20 function bodies independently rehashed in this checkout, matching supplied historical hashes, not the old 29-function count. No blanket boundary reuse.",
"source": "14 byte differences, zero missing mapped paths; six immutable current pins match.",
"config_input_environment": "Not established by raw local evidence; each required proof must pin these independently.",
"runtime_git": "Verified supplied old SHA2d7e2cea; git diff --no-index compared exact raw old/current Runtime. Four hunks affect _project_guest_candidates batching, _find_facility_access_path cost selection, _estimated_actor_path_minutes and extracted connector-credit helper. Completion/phase registration unchanged in this file; callees PathService changed, therefore reachability, choice, arrival and staff estimates require finite applicability evidence.",
"known_difference_impact": "Runtime/PathService may alter infrastructure, movement, staffing, guest selection and recovery boundary reachability; UI/main/preview and performance budget changes prevent blanket whole-full reuse. Two changed tests cannot supply old exact-version evidence. Seven additional Kenney metadata/sample byte differences require applicability classification, not product edits."
},
"blockers": [
"D05 closure service and final shift interval remain unapproved.",
"Raw historical boundary proofs/config/input/environment not supplied; summary pass claims cannot establish original acceptance.",
"Initial checker validates structural/hash predicates but intentionally rejects unsupported semantic coverage/native provenance; passing machine gate unavailable in pending-D05 dispatch."
"D05 dependency closure and 18:00 interval are approved; approval is not test success.",
"Raw 39 historical artifacts, settings/input/environment and engine receipts are not mirrored here. Their hashes in recheck are provenance, not verified current evidence.",
"Nonzero-payroll midnight, paused midnight, replay/separate-PID save restoration and reachable EV reservation safety need applicable raw evidence.",
"Root must independently assess affected power/destruction/exit paths and production Runtime 4696df4a versus checkout d52a995 before integration."
],
"validation_plan": [
"Runner supplies exact-version raw boundary evidence using CHECKER_PROTOCOL.md; no worker engine/test execution.",
"Confirm finite reachability/arrival/staff path impacts for affected Runtime and PathService; retain 14 raw differences and classify 7 metadata-only differences separately.",
"After D05 approval verify only affected closure/18:00 boundaries; retain failed diagnostics and approved A01.",
"Verify applicable stop/recovery, early/late destruction, public/patience/overdue exit, midnight/replay/reload evidence with raw hashes and source/config/input/environment pins; request fresh finite proofs only where reuse fails.",
"Runner executes p04-acceptance and independent all-condition review/integration; native Windows conditions individually pending only if applicable. No engine/all-regression run here."
"Runner runs p04-acceptance; worker only py_compile and synthetic negative fixture checks.",
"Root verifies source/config/input/environment applicability for power, destruction, exit cases affected by four Runtime hunks and PathService changes; fresh finite boundaries only if reuse fails.",
"Require nonzero payroll midnight, stop crossing midnight, same-minute resend, formal save and different PID restore, no-night-staff 18:01, existing overtime task, and reachable reserved-staff EV safety evidence.",
"Do not reopen A01 or invent cost/day attribution. Pending unrelated D05 does not fail the whole gate.",
"Root rechecks production Runtime 4696df4a against immutable checkout d52a995, then independent review in separate session and normal integration. Formal credit remains zero."
],
"repair_support": {
"hashes": {
@@ -240,5 +256,265 @@
"production_differences": 7,
"managed_differences": 14,
"additional7_classification": "Runner support reports CRLF to LF only; current raw hashes checked. Old raw metadata absent, normalization not independently reproduced; no acceptance equivalence claim."
},
"repair3": {
"space_available": "1.8 GiB before work; bounded source reads and ~small text changes, no raw archive copies needed",
"approval_material_verification": [
{
"file": "D05_OWNER_APPROVAL.json",
"bytes": 2073,
"sha256": "4583ee9aad45c4db183d72df4420df48aa8e0897e3b5efda13016f0b5cdbd68e",
"manifest_matches": true
},
{
"file": "README.md",
"bytes": 1029,
"sha256": "7b1c8992a8c5298d3ad416a5ff667a49f6e1eafea149fb6abb9e91e517e47c0f",
"manifest_matches": true
},
{
"file": "recheck.json",
"bytes": 46479,
"sha256": "44b32fa297c3c8f81691505878232756b3d63e0d5a801a6ae15173b84894bd22",
"manifest_matches": true
},
{
"file": "OPUS_D05_CANDIDATE.json",
"bytes": 6653,
"sha256": "54cd83971467744b1009e72c56e7b5d558c97073540d027640e486f7b5b5a34b",
"manifest_matches": true
}
],
"ordering_functions": [
{
"path": "scripts/core/simulation_kernel.gd",
"function": "advance_one_minute",
"line": 122,
"sha256": "b9587ef722d8c8640248025462819374ae5eca1c3d8bbe600b6bc9c328567777",
"matches_supplied_historical_body_hash": true
},
{
"path": "scripts/core/simulation_kernel.gd",
"function": "_run_phase",
"line": 236,
"sha256": "52461eeb288892a4bb4b6a99570185af08a30758ef88b0046a911baaa6f318e1",
"matches_supplied_historical_body_hash": true
},
{
"path": "scripts/core/simulation_kernel.gd",
"function": "_handle_time_boundaries",
"line": 254,
"sha256": "2ced47a2911b36def9d89de82a43afc69148ead44d19db6a2a6c7bce5a910ae9",
"matches_supplied_historical_body_hash": true
},
{
"path": "scripts/core/command_queue.gd",
"function": "_comes_before",
"line": 409,
"sha256": "21f7f9f7c0923121fd0a022a2f7546b7bb7117a9979c1ed25d0b33b96e28ab28",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_process_tick_commands",
"line": 5736,
"sha256": "9de66a4bb84b12304300d49085f44546412319bd4aee91e67b61becf97e50294",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_advance_operations_time",
"line": 1894,
"sha256": "511580d1fac3d2785072e94c2981065fa47ba18b1c97122922645dac5c0d94ab",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_run_operations_deferred_suffix",
"line": 1683,
"sha256": "12075307b12cbb66ffda47a26097194a07fad9d6467e3e557bd7269315c98982",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_advance_mana",
"line": 10633,
"sha256": "05c54626ce6e355acd92994ab80aaf2177c5cf194885e66934552139e087599e",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_advance_facilities",
"line": 8421,
"sha256": "f1efd0c23bdd60d1ef19a21879640b53b8b4d88844c0c881fe7cd724387ec274",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_advance_guest_vitals",
"line": 8427,
"sha256": "8226ca18c983ac576a74e772cc3088e9fe52b362ffba1b71255bd1d7623c1234",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_advance_staff_ai",
"line": 8597,
"sha256": "0e222987f7c5e25583dbaba8fe63784aa563715067396e8d31d10bd191e7179b",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_advance_guest_ai_decisions",
"line": 8677,
"sha256": "e33b41294e88dba840affd5cc0a5c58fe5d46f5d98a80a8d5f4e907a3b9a7b93",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_release_closed_business_queues",
"line": 12562,
"sha256": "3a05fbe94877eeb750fb0d692501954555ab6a8005448ab3b6023dab9bad816b",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_release_closed_business_request",
"line": 12580,
"sha256": "6dbde3a3d425e47a049dcc4f05eae6f01fe9784f473c0fb1019a0633c239d83b",
"matches_supplied_historical_body_hash": true
},
{
"path": "autoload/simulation_runtime.gd",
"function": "_complete_service_transaction",
"line": 11707,
"sha256": "f2b6e96a8eeef3dd3f8419b4d9d5ef4e1d13241600ce970bdd78a924428cac6c",
"matches_supplied_historical_body_hash": true
},
{
"path": "scripts/facility/facility_service.gd",
"function": "advance_one_minute",
"line": 544,
"sha256": "59c0e89b4dca291e3ec02601b3f7c5544dba7c823fc137e0e7a50e7d5319e0ed",
"matches_supplied_historical_body_hash": true
},
{
"path": "scripts/facility/facility_service.gd",
"function": "_prepare_service_for_tick",
"line": 853,
"sha256": "b35c2c0fb23a04258b71995dd7c3b6dfacbbcdf36106e2e3348acef0e18d21cc",
"matches_supplied_historical_body_hash": true
},
{
"path": "scripts/facility/facility_service.gd",
"function": "_complete_service",
"line": 895,
"sha256": "494edfd11cb3e896d73c2c6fdbe7c1193efce6d869b105e526d2f1dfd1168142",
"matches_supplied_historical_body_hash": true
},
{
"path": "scripts/facility/facility_service.gd",
"function": "_fail_service",
"line": 933,
"sha256": "56f61b255217bddb4c8a6ad3af6ed1f9edc3b6a6e928dacf2105be6698936de5",
"matches_supplied_historical_body_hash": true
},
{
"path": "scripts/operations/operations_coordinator.gd",
"function": "_process_minute_boundaries",
"line": 882,
"sha256": "1312166dc17aee0ef470069a73ff3fe6b86d11d04ca7de76f3d04f1d2d14674e",
"matches_supplied_historical_body_hash": true
}
],
"ordering_function_count": 20,
"historical_29_not_combined": true,
"nativeWindows": {
"power_stop": "pending",
"destruction_stop": "pending",
"dependency_stop": "pending",
"shift_completion": "pending",
"recovery_completion": "pending",
"same_minute_replay": "pending",
"closure_release": "pending",
"exit_release": "pending",
"patience_release": "pending",
"paused_midnight": "pending",
"midnight_settlement": "pending",
"midnight_replay": "pending",
"save_restore": "pending",
"night_staff_absent": "pending",
"overtime_task": "pending",
"EV": "pending"
},
"spec_representation": {
"raw_sha256": "d28aadb044633f7d804de5a92c8d4c4a7438dfbf44c3243dca978951f4def25f",
"contract_sha256": "9ec722e7dfb0bee178d291624a026420c08412574e238bba1fde012c7a6f7881",
"difference": "exactly one final LF; no spec edits"
},
"worker_validation": {
"py_compile": "passed",
"negative_fixture_count": 10,
"negative_results": "all exit 1 with intended error; synthetic control exit 0/formal_acceptance=false",
"engine_runs": 0,
"runner_operations": 0,
"formal_acceptance": false
},
"runtime_diff_hunks": 5,
"reachability": {
"guest_EV": {
"reach": false,
"scope": "normal guest automatic service reservation before arrival",
"source_refs": [
"Runtime:8898-8922 arrival -> queue -> create_service_request",
"Runtime:7421-7445 reserve -> create request"
]
},
"staff_EV": {
"reach": true,
"scope": "public create_staff_task required_items can reserve before EV travel",
"source_refs": [
"Runtime:329,6733-6742 public task creation",
"task_dispatcher.gd:256-261,293-294,309-314 reserve before assignment",
"Runtime:5320,9141-9170 inventory callback",
"Runtime:12009-12013 begin_moving",
"Runtime:8755-8763,8946-8987 EV travel",
"elevator_service.gd:279-284 set_powered"
],
"required": "power-stop case with reserved-before-travel items; orphan_reservations=0; nativeWindows pending"
},
"transport": {
"reach": false,
"scope": "rescue transport payment/reservation only; physical movement is reachable",
"source_refs": [
"Runtime:12023-12030 completion heals only",
"Runtime:12976-13050 rescue pickup/transport creation, no required_items/reservation/payment"
],
"counted_domain_added": false
},
"opening_hours": {
"reach": false,
"scope": "production time-of-day closure",
"source_refs": [
"facility_instance.gd default [0,1440)",
"set_opening_hours: definitions/service wrapper only; no autoload caller"
],
"direct_closure_remains_required": true
}
},
"path_applicability": {
"source_refs": [
"scripts/world/path_service.gd:1055-1101",
"scripts/world/path_service.gd:1302-1319",
"Runtime:9222-9268,9296-9300,12798-12812,12838-12848"
],
"power": "Stop/resume core unchanged, but if fixture reaches a facility through guest candidate/connector routes or staff arrival, pins/function equality alone do not prove the same stopped-service boundary. Root must inspect route and arrival observations.",
"destruction": "Command-before-completion and incident-after-completion order unchanged; infrastructure/connector destruction can alter selected/access path and arrival, so only those route-dependent cases need current applicability confirmation.",
"exit": "Release callbacks unchanged; MOVING target selection/arrival/overdue exit can use the changed paths, so confirm their raw state and arrival minute before reuse.",
"path_service": "Batch only with connectors, default layers and empty access; settled tree path/cost, fallback on unusable tree/wrapped cost. Caller estimate can affect arrival even though phase functions match.",
"verdict": "No affected case accepted from summaries alone; raw source/config/input/environment evidence remains a Root prerequisite."
},
"runtime_logical_change_groups": 4,
"runtime_diff_note": "Default git diff emits 5 textual hunks: batch begin/end split into two; four logical change groups in commander direction."
}
}