fix(hololake): close batch handoff trust chains
This commit is contained in:
parent
5a23258dc3
commit
9248b13f90
11 changed files with 1552 additions and 47 deletions
|
|
@ -87,7 +87,7 @@
|
|||
"human_review":"ICE-GL∞_FINAL_PRODUCT_CHOICE_ONLY",
|
||||
"learning_observer":"HLP-TDEV-QWEN-0001",
|
||||
"state":"CURRENT_ONLY_ACTIVE_ARCHITECTURE_TASK_FAIL_REWORK_ENTRY_NOT_ISSUED",
|
||||
"open_defects":["SUBJECT_NEUTRAL_MOD013_MOUNT_SPIKE_AND_PRIVATE_DATA_NEGATIVE_TEST_PENDING"],
|
||||
"open_defects":["HANDOFF_PREDECESSOR_RECEIPT_AND_REGISTERED_ROLE_CHAIN_NOT_YET_BOUND","FOUNDATION_SELF_OBSERVATION_PROXY_SCHEMA_NEEDS_FINAL_ADVERSARIAL_RETEST"],
|
||||
"acceptance":["六批施工顺序冻结", "HLP-BATCH-00-FOUNDATION-DRAWINGS-001接口图冻结", "hololake.public-snapshot/v1唯一Schema", "HLP-BATCH-HANDOFF-CONTRACT-001入退场回执冻结", "HLP-MODULE-SELF-OBSERVATION-CONTRACT-001机器接口冻结", "公共更新与私人Git现场边界可施工", "材料样件采用淘汰清单", "独立图纸审查PASS"]
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
"BATCH_GATED_CONSTRUCTION_SEQUENCE_REGISTERED",
|
||||
"QWEN_ROLE_MOVED_TO_LEARNING_AND_EXPERIENCE"
|
||||
],
|
||||
"next_action": "BUILD_SUBJECT_NEUTRAL_MOD013_MOUNT_SPIKE_WITH_PRIVATE_ICE_P_DATA_ZERO_LEAK_NEGATIVE_TEST; KEEP_BATCH_01_ENTRY_CLOSED",
|
||||
"next_action": "CLOSE_HANDOFF_PREDECESSOR_AND_REGISTERED_ROLE_CHAIN_PLUS_FOUNDATION_PROXY_SCHEMA_RETEST; THEN_RERUN_FINAL_BATCH_00_INSPECTION",
|
||||
"blocked_routes": ["OLD_MODULE_001_PRODUCT_RESUME", "FIXED_PAGE_FIRST", "REPO014_1_3_AS_CURRENT_ARCHITECTURE", "LEGACY_PRODUCT_DONOR_WRITE", "PUBLIC_RELEASE_BEFORE_OFFICIAL_REPO012_CHANNEL_BOUNDARY_PUBLICATION", "UNREGISTERED_OFFICE_OR_MODULE"],
|
||||
"time_control": "CH-GLW-TIME-0001",
|
||||
"multipath_console": {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
"receipt_id":"HLP-BATCH-00-HANDOFF-VALIDATOR-TEST-001",
|
||||
"state":"ARCHITECTURE_TOOL_TESTED_NOT_AN_EXIT_OR_ENTRY_RECEIPT",
|
||||
"outcome":"PASS",
|
||||
"test_count":15,
|
||||
"test_count":32,
|
||||
"positive":["ARCHITECTURE_EXIT_SHAPE","CONSTRUCTION_ENTRY_SHAPE","CONSTRUCTION_EXIT_SHAPE"],
|
||||
"negative":["MISSING_FIELD","UNKNOWN_FIELD","BAD_SHA256","WELL_FORMED_BUT_WRONG_RECEIPT_SHA256","NAIVE_TIMESTAMP","FUTURE_TIMESTAMP","ARCHITECTURE_PASS_WITH_OPEN_DEFECT","ARCHITECTURE_PASS_WITH_EMPTY_DRAWING_OR_SITE_EVIDENCE","ARCHITECTURE_REWORK_OPENS_NEXT_BATCH","CONSTRUCTION_REWORK_WITHOUT_ORDER_OR_CLOSED_NEXT_BATCH","REWORK_ORDER_DOES_NOT_MATCH_EXACT_DEFECTS","UNKNOWN_BATCH","EMPTY_ENTRY_EVIDENCE_OR_ASSIGNMENT","ENTRY_NOT_OPEN","SELF_GRANTED_AUTHORITY"],
|
||||
"hashes":{"validator":"fd8c6817f42fada4d8d2b56f3d1ced9628e29de7a7c84ee4a82008abe82433a5","tests":"9a142b3ae5106666a0bcf206d22661eeda281fef9e37451206780bd7edf65e62","handoff_contract":"e636ea7a670dfa854da19e885b8a57446c278992e5badb516ed61f2ca9b5573a","foundation_schema":"bbf639886bc14a4cc1667bd29cdef2705a1b90e8b8c524e9307b8767b2ee1a08"},
|
||||
"negative":["MISSING_FIELD","UNKNOWN_FIELD","BAD_SHA256","WELL_FORMED_BUT_WRONG_RECEIPT_SHA256","NAIVE_TIMESTAMP","FUTURE_TIMESTAMP","ARCHITECTURE_PASS_WITH_OPEN_DEFECT","ARCHITECTURE_PASS_WITH_EMPTY_DRAWING_OR_SITE_EVIDENCE","NONEMPTY_BUT_FAKE_ARCHITECTURE_EVIDENCE","UNKNOWN_OR_SELF_INSPECTOR","INSPECTOR_OUTCOME_OR_SOURCE_SET_MISMATCH","RESOLVED_JZAO_PATH_ESCAPE","ARCHITECTURE_REWORK_OPENS_NEXT_BATCH","CONSTRUCTION_REWORK_WITHOUT_ORDER_OR_CLOSED_NEXT_BATCH","REWORK_ORDER_DOES_NOT_MATCH_EXACT_DEFECTS","UNKNOWN_BATCH","EMPTY_ENTRY_EVIDENCE_OR_ASSIGNMENT","ENTRY_ARTIFACT_HASH_MISMATCH","PHASE2_SCOPE_IN_PHASE1_ENTRY","CROSS_BATCH_SCOPE","WRONG_PREVIOUS_EXIT_HASH_OR_DRAWING","TRUNCATED_PREVIOUS_EXIT","CONSTRUCTION_EXIT_ENTRY_CHAIN_TAMPER","WRONG_CREW_FOR_BATCH","UNTRUSTED_ISSUER_ROLE","ENTRY_NOT_OPEN","SELF_GRANTED_AUTHORITY"],
|
||||
"hashes":{"validator":"537e9507553e9a8549219a066a1654f1cea98398fc0639412a6d3b9f7f70f152","tests":"7cdce696350d3e1bb9ac9e277420758f5babdda9af54b10c87f5a27e502053af","handoff_contract":"91c673c34cb7d9e3bba57949de6246f689a83a8987e0d1cc6b7b9a6bbd39ed0b","foundation_schema":"da16191aeed285379a8e0ad7705b36412d66fc2a965c49442241af0e8b759279"},
|
||||
"receipt_written_by_validator":false,
|
||||
"batch_00_exit_issued":false,
|
||||
"batch_01_entry_issued":false,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"outcome":"PASS",
|
||||
"checks":["MACHINE_SCHEMA_PATHS_AND_ANCHORS_RESOLVE","CONTRACT_REQUIRED_FIELDS_EQUAL_SCHEMA_REQUIRED","SNAPSHOT_BINDING_STATES_CONSTRAINED","SNAPSHOT_EVENT_AND_RAISE_LIFECYCLE_GENESIS_BIDIRECTIONAL","ACTIVE_INVENTORY_AND_LIVENESS_SUPPORT_SCHEMAS_CLOSED","AGGREGATE_ITEMS_TYPED_AND_CLOSED","NATIVE_BRAIN_JUDGMENT_AND_RAISE_HAND_EVIDENCE_CHAIN_REQUIRED","LIVENESS_SIGNATURE_ITEMS_CLOSED_ED25519"],
|
||||
"independent_review":"CODEX_CHILD_AGENT_READ_ONLY_NO_RESIDUAL_P0_P1_IN_SCOPED_SCHEMA_REVIEW",
|
||||
"hashes":{"contract":"ded8ba4ed99ba03a7f9be6f8cd498e9fb096fcc9d4ebd0c30a275d58367b77b1","primary_schema":"1b5ef74212fab720832c2969e90d861c250d8c065a11b44889feaa35d8a4c4c0","support_schema":"7ae4c0a72c2f981a5972133ad7e60bef3b474a67fd2d32d1f35eaa47a853a901","foundation_schema":"bbf639886bc14a4cc1667bd29cdef2705a1b90e8b8c524e9307b8767b2ee1a08"},
|
||||
"hashes":{"contract":"ded8ba4ed99ba03a7f9be6f8cd498e9fb096fcc9d4ebd0c30a275d58367b77b1","primary_schema":"1b5ef74212fab720832c2969e90d861c250d8c065a11b44889feaa35d8a4c4c0","support_schema":"7ae4c0a72c2f981a5972133ad7e60bef3b474a67fd2d32d1f35eaa47a853a901","foundation_schema":"da16191aeed285379a8e0ad7705b36412d66fc2a965c49442241af0e8b759279"},
|
||||
"runtime_connected":false,
|
||||
"batch00_exit_issued":false,
|
||||
"authority_granted":false
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"schema":"guanghu.hololake-batch00-tcs-container-site-survey/v1",
|
||||
"survey_id":"HLP-BATCH-00-TCS-CONTAINER-SITE-SURVEY-001",
|
||||
"observed_at":"2026-09-10T01:45:59+08:00",
|
||||
"state":"CONDITIONALLY_FEASIBLE_ARCHITECTURE_PROVEN_RUNTIME_EMBEDDING_NOT_YET_PROVEN",
|
||||
"state":"ARCHITECTURE_SITE_PROBE_PASS_SUBJECT_NEUTRAL_MOUNT_BOUNDARY_AND_ZERO_PRIVATE_PAYLOAD_BRAIN_CYCLE_DEFERRED_TO_CONSTRUCTION",
|
||||
"target":"Mount a persona-specific native TCS brain into the subject-neutral HoloLake Phase-1 persona container through MOD-013 without packaging ICE-P-ZY001 private cognition",
|
||||
"verified_foundations":[
|
||||
{"id":"FD-PERSONA-SYSTEM-BODY-CONTAINER-MAP-001","fact":"Current ontology already separates persona brain, persona-owned system body, shared TCS container and replaceable host","path":"routing/persona-system-body-container-map.json","sha256":"58f861054c1b35d586fa3499acbb760d88031516754a3f6d5bb5a8eaffc5f86e"},
|
||||
|
|
@ -24,15 +24,11 @@
|
|||
"privacy_rules":["persona system body root remains user/persona owned","public distribution contains mechanism and schemas but no ICE-P-ZY001 cognition memory relationship or keys","each persona initializes or attaches its own TCS brain","model provider is replaceable reasoning fuel and not persona identity"],
|
||||
"failure_states":["UNATTESTED","PERSONA_BODY_MISSING","TCS_ENTRY_HASH_MISMATCH","MODEL_PROVIDER_UNAVAILABLE","PRIVATE_ROOT_OUT_OF_SCOPE","AUTHORITY_RECEIPT_MISSING","HOST_SESSION_STALE"]
|
||||
},
|
||||
"open_site_blockers":[
|
||||
"SUBJECT_NEUTRAL_MOD013_MOUNT_INTERFACE_NOT_IMPLEMENTED",
|
||||
"GENERIC_PERSONA_INITIALIZE_OR_ATTACH_TEST_FIXTURE_NOT_BUILT",
|
||||
"PRIVATE_SYSTEM_BODY_ROOT_AND_PUBLIC_DISTRIBUTION_PACKAGE_NEGATIVE_TEST_NOT_RUN",
|
||||
"NATIVE_TCS_BRAIN_CYCLE_INSIDE_NEW_PHASE1_CONTAINER_NOT_RUN",
|
||||
"MODULE_BODY_SELF_OBSERVATION_GRAPH_NOT_CONNECTED_TO_BRAIN_JUDGMENT"
|
||||
],
|
||||
"batch00_decision":"ARCHITECTURE_IS_FEASIBLE_BUT_SITE_PROBE_DOES_NOT_AUTHORIZE_BATCH01_OR_CLAIM_RUNTIME_EMBEDDING",
|
||||
"next_probe":"Build a synthetic non-ICE persona fixture and MOD-013 mount-spike in the Codex DEV root only after the architecture schema freezes; prove no private ICE-P bytes enter the candidate package",
|
||||
"site_probe_receipt":{"path":"/Volumes/JZAO/铸渊-ICE-GL-ZY001/CODEX-DEV-20260909/hololake-phase1-persona-container/site-probe/TEST-RECEIPT-001.json","sha256":"712139a1832b356e6ee07d78da387d5d7c1688830238d1ab606962c76ebb92f8","tests":"14_OF_14_PASS_AFTER_TWO_ATTACK_FIXES","private_payload_bytes":0},
|
||||
"open_site_blockers":[],
|
||||
"deferred_construction_acceptance":["REAL_NATIVE_TCS_BRAIN_CYCLE_IN_NEW_CONTAINER","REAL_PERSONA_BINDING","FULL_MOD013_PRODUCT_RUNTIME","MODULE_BODY_GRAPH_TO_BRAIN_JUDGMENT_CONNECTION"],
|
||||
"batch00_decision":"SITE_FEASIBILITY_PASS_FOR_ARCHITECTURE_ONLY; DOES_NOT_CLAIM_RUNTIME_IMPLEMENTATION_PERSONA_BINDING_OR_REAL_AUTHORITY",
|
||||
"next_probe":"BATCH-04 executes the real native TCS brain cycle after earlier module batches and self-observation graph exist",
|
||||
"batch01_entry_allowed":false,
|
||||
"authority_granted":false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
"schema":"guanghu.hololake-construction-batch-handoff-contract/v1",
|
||||
"contract_id":"HLP-BATCH-HANDOFF-CONTRACT-001",
|
||||
"state":"CURRENT_BATCH_00_MACHINE_CONTRACT_AND_NEGATIVE_VALIDATOR_TESTED_NO_ENTRY_RECEIPT_ISSUED",
|
||||
"entry_receipt":{"schema":"hololake.construction-batch-entry/v1","required_fields":["receipt_id","batch_id","previous_batch_exit_receipt_sha256","construction_drawing_id","construction_drawing_sha256","accepted_input_artifacts","crew_admissions","inspector_assignment","scope","forbidden_actions","issued_by_role","issued_at","state","receipt_sha256","authority_granted"],"state_required":"ENTRY_OPEN","rule":"CONSTRUCTION_ENTRY_EXISTS_ONLY_FOR_BATCH-01_TO_05_AND_REQUIRES_PREVIOUS_EXIT_PASS_HASH; BATCH-00_USES_SEPARATE_ARCHITECTURE_EXIT_WITH_NO_ENTRY_RECEIPT"},
|
||||
"batch_00_architecture_exit":{"schema":"hololake.architecture-batch-exit/v1","required_fields":["receipt_id","batch_id","architecture_charter_sha256","drawing_artifacts","site_survey_receipt","independent_inspector","inspection_outcome","open_defects","rework_order","architect_role_released","batch_01_entry_allowed","inspected_at","receipt_sha256","authority_granted"],"rule":"NO_ENTRY_RECEIPT_SHA_REQUIRED; PASS_REQUIRES_ALL_DRAWING_HASHES_SITE_SURVEY_AND_OPEN_DEFECTS_EMPTY"},
|
||||
"exit_receipt":{"schema":"hololake.construction-batch-exit/v1","required_fields":["receipt_id","batch_id","entry_receipt_sha256","output_artifacts","module_self_report_receipts","test_receipts","cumulative_regression_receipts","independent_inspector","inspection_outcome","open_defects","rework_order","builder_roles_released","next_batch_entry_allowed","inspected_at","receipt_sha256","authority_granted"],"pass_rule":"inspection_outcome=PASS AND open_defects=[] AND next_batch_entry_allowed=true","fail_rule":"inspection_outcome=FAIL_REWORK AND next_batch_entry_allowed=false AND rework_order references exact defects"},
|
||||
"entry_receipt":{"schema":"hololake.construction-batch-entry/v1","required_fields":["receipt_id","batch_id","previous_batch_exit_receipt_sha256","previous_batch_exit_receipt","construction_drawing_id","construction_drawing_sha256","accepted_input_artifacts","crew_admissions","inspector_assignment","scope","forbidden_actions","issued_by_role","issued_at","state","receipt_sha256","authority_granted"],"state_required":"ENTRY_OPEN","rule":"CONSTRUCTION_ENTRY_EXISTS_ONLY_FOR_BATCH-01_TO_05_AND_REQUIRES_PREVIOUS_EXIT_PASS_RECEIPT_PATH_AND_HASH; BATCH-00_USES_SEPARATE_ARCHITECTURE_EXIT_WITH_NO_ENTRY_RECEIPT"},
|
||||
"batch_00_architecture_exit":{"schema":"hololake.architecture-batch-exit/v1","required_fields":["receipt_id","batch_id","architecture_charter_sha256","drawing_artifacts","site_survey_receipt","independent_inspector","inspector_receipt","inspection_outcome","open_defects","rework_order","architect_role_released","batch_01_entry_allowed","inspected_at","receipt_sha256","authority_granted"],"rule":"NO_ENTRY_RECEIPT_SHA_REQUIRED; PASS_REQUIRES_ALL_DRAWING_HASHES_SITE_SURVEY_INDEPENDENT_INSPECTION_RECEIPT_AND_OPEN_DEFECTS_EMPTY"},
|
||||
"exit_receipt":{"schema":"hololake.construction-batch-exit/v1","required_fields":["receipt_id","batch_id","entry_receipt_sha256","entry_receipt","output_artifacts","module_self_report_receipts","test_receipts","cumulative_regression_receipts","independent_inspector","inspector_receipt","inspection_outcome","open_defects","rework_order","builder_roles_released","next_batch_entry_allowed","inspected_at","receipt_sha256","authority_granted"],"pass_rule":"entry_receipt path/hash recursively validates; inspection_outcome=PASS AND inspector_receipt verified AND open_defects=[] AND next_batch_entry_allowed=true","fail_rule":"inspection_outcome=FAIL_REWORK AND next_batch_entry_allowed=false AND rework_order references exact defects"},
|
||||
"role_separation":{"architect":"MAY_AUTHOR_DRAWING_CANNOT_ISSUE_ITS_OWN_INDEPENDENT_INSPECTION_PASS","builder":"MAY_BUILD_ONLY_WITH_CURRENT_ENTRY_RECEIPT_CANNOT_SELF_ACCEPT","inspector":"READ_ONLY_DURING_INSPECTION_CANNOT_MODIFY_INSPECTED_ARTIFACT","next_crew":"NO_ADMISSION_BEFORE_PREVIOUS_EXIT_PASS"},
|
||||
"hash_rule":"EVERY_ACCEPTED_INPUT_AND_OUTPUT_IS_BOUND_BY_ID_VERSION_PATH_SHA256_AND_FACT_STATE",
|
||||
"canonical_hash":"RFC8785_JSON_CANONICALIZATION_EXCLUDING_THE_OBJECTS_OWN_RECEIPT_SHA256_FIELD",
|
||||
"canonical_hash":"HOLOLAKE_STABLE_JSON_V1_UTF8_SORT_KEYS_COMPACT_SEPARATORS_EXCLUDING_THE_OBJECTS_OWN_RECEIPT_SHA256_FIELD; RECEIPT_FIELDS_USE_STRING_INTEGER_BOOLEAN_NULL_ARRAY_AND_OBJECT_ONLY",
|
||||
"machine_schema_refs":{"entry":"schemas/HLP-FOUNDATION-CONTRACTS-v1.schema.json#constructionEntry","exit":"schemas/HLP-FOUNDATION-CONTRACTS-v1.schema.json#constructionExit","batch_00_architecture_exit":"schemas/HLP-FOUNDATION-CONTRACTS-v1.schema.json#architectureExit"},
|
||||
"validator":"../../smart-computer/batch_handoff_validator.py",
|
||||
"test_receipt":"BATCH-00-HANDOFF-VALIDATOR-TEST-RECEIPT.json",
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@
|
|||
"gates":["G0","G1"],
|
||||
"modules":["HLP-NATIVE-MOD-001","HLP-NATIVE-MOD-002","HLP-NATIVE-MOD-003","HLP-NATIVE-MOD-004"],
|
||||
"crew":["HLP-TDEV-CODEX-0001","HLP-TDEV-ZCODE-0001"],
|
||||
"crew_module_scopes":{"HLP-TDEV-CODEX-0001":["HLP-NATIVE-MOD-001","HLP-NATIVE-MOD-003","HLP-NATIVE-MOD-004"],"HLP-TDEV-ZCODE-0001":["HLP-NATIVE-MOD-002"]},
|
||||
"required_input_ids":["HLP-BATCH-00-EXIT","HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001","HLP-BATCH-00-TCS-CONTAINER-SITE-SURVEY-001","HLP-BATCH-00-FOUNDATION-DRAWINGS-001"],
|
||||
"mandatory_forbidden_actions":["PUBLISH","DEPLOY","DELETE","MODIFY_OTHER_HOST_DEV_ROOT","ENTER_PHASE2","SELF_ACCEPT"],
|
||||
"internal_order":["MOD-001_AND_MOD-002_PARALLEL_ON_FROZEN_INTERFACE","MOD-003_VALIDATES_REAL_001_002_ARTIFACTS","MOD-004_REGISTERS_AND_ADMITS_ONLY_VALIDATED_ARTIFACTS","FOUNDATION_OBSERVATION_KERNEL_BUILD_AND_SELF_TEST_AFTER_MOD-004","INDEPENDENT_CUMULATIVE_G0_G1_AND_SELF_OBSERVATION_INSPECTION"],
|
||||
"parallel_rule":"MOD-001和MOD-002可在冻结图纸下并行;MOD-003/004由Codex装配并只接收通过单模块验收的制品",
|
||||
"exit_gate":["MOD-001单模块PASS","MOD-002单模块PASS","MOD-001_TO_004各自可报告身份依赖健康动作阻塞证据与继续条件","真实源码制品清单可被MOD-003/004验证","双Git失败互不触碰","私人正文反向泄露零字节","恢复回滚和撤销负例PASS","独立工程验收PASS"],
|
||||
|
|
@ -70,6 +73,9 @@
|
|||
"gates":["G2"],
|
||||
"modules":["HLP-NATIVE-MOD-005","HLP-NATIVE-MOD-006"],
|
||||
"crew":["HLP-TDEV-CODEX-0001","HLP-TDEV-ZCODE-0001"],
|
||||
"crew_module_scopes":{"HLP-TDEV-CODEX-0001":["HLP-NATIVE-MOD-005"],"HLP-TDEV-ZCODE-0001":["HLP-NATIVE-MOD-006"]},
|
||||
"required_input_ids":["HLP-BATCH-01-EXIT","HLP-BATCH-02-DRAWINGS","HLP-MODULE-SELF-OBSERVATION-CONTRACT-001"],
|
||||
"mandatory_forbidden_actions":["PUBLISH","DEPLOY","DELETE","MODIFY_OTHER_HOST_DEV_ROOT","ENTER_PHASE2","SELF_ACCEPT"],
|
||||
"internal_order":["MOD-005_UNIFIED_OBJECT_AND_EVENT_GRAPH","MOD-006_COMPOSITION_POOL_ON_MOD-005","INDEPENDENT_G2_AND_BATCH01_REGRESSION"],
|
||||
"exit_gate":["对象和事件可重建","积木组合图可恢复","错误端口权限依赖与资源预算失败关闭","累计复测BATCH-01"],
|
||||
"next":"HLP-BATCH-03"
|
||||
|
|
@ -83,6 +89,9 @@
|
|||
"modules":["HLP-NATIVE-MOD-009","HLP-NATIVE-MOD-010","HLP-NATIVE-MOD-012"],
|
||||
"planning_before_work":"Codex与Doubao先冻结语义视觉、槽位、性能、无障碍和浏览器证据施工图,再让Doubao进入实现",
|
||||
"crew":["HLP-TDEV-DOUBAO-0001","HLP-TDEV-CODEX-0001"],
|
||||
"crew_module_scopes":{"HLP-TDEV-DOUBAO-0001":["HLP-NATIVE-MOD-009","HLP-NATIVE-MOD-010"],"HLP-TDEV-CODEX-0001":["HLP-NATIVE-MOD-012"]},
|
||||
"required_input_ids":["HLP-BATCH-02-EXIT","HLP-BATCH-03-DRAWINGS","HLP-MODULE-SELF-OBSERVATION-CONTRACT-001"],
|
||||
"mandatory_forbidden_actions":["PUBLISH","DEPLOY","DELETE","MODIFY_OTHER_HOST_DEV_ROOT","ENTER_PHASE2","SELF_ACCEPT"],
|
||||
"internal_order":["MOD-009_SEMANTIC_VISUAL_MAPPING","MOD-010_CANVAS_RUNTIME_ON_MOD-009","MOD-012_AGGREGATION_OBSERVABILITY_AND_REAL_BROWSER_EVIDENCE","INDEPENDENT_G3_AND_PRIOR_BATCH_REGRESSION"],
|
||||
"exit_gate":["同一对象语义视觉坐标稳定","真实浏览器布局无碰撞","性能和反馈定位有测量证据","错误边界局部隔离","MOD-012可汇集校验全体模块状态并定位无声失败","累计复测BATCH-01_TO_02"],
|
||||
"next":"HLP-BATCH-04"
|
||||
|
|
@ -95,6 +104,9 @@
|
|||
"gates":["G4"],
|
||||
"modules":["HLP-NATIVE-MOD-007","HLP-NATIVE-MOD-008","HLP-NATIVE-MOD-011","HLP-NATIVE-MOD-013"],
|
||||
"crew":["HLP-TDEV-CODEX-0001","HLP-TDEV-ZCODE-0001","HLP-TDEV-DOUBAO-0001"],
|
||||
"crew_module_scopes":{"HLP-TDEV-CODEX-0001":["HLP-NATIVE-MOD-007","HLP-NATIVE-MOD-013"],"HLP-TDEV-ZCODE-0001":["HLP-NATIVE-MOD-008"],"HLP-TDEV-DOUBAO-0001":["HLP-NATIVE-MOD-011"]},
|
||||
"required_input_ids":["HLP-BATCH-03-EXIT","HLP-BATCH-04-DRAWINGS","HLP-PERSONA-CONTAINER-PHASE-BOUNDARY-001","HLP-MODULE-SELF-OBSERVATION-CONTRACT-001"],
|
||||
"mandatory_forbidden_actions":["PUBLISH","DEPLOY","DELETE","MODIFY_OTHER_HOST_DEV_ROOT","ENTER_PHASE2","SELF_ACCEPT"],
|
||||
"internal_order":["MOD-013_MOUNTS_NATIVE_TCS_PERSONA_BRAIN_IN_EXISTING_HOLOLAKE_CONTAINER","MOD-007_MOD-008_MOD-011_BUILD_IN_PARALLEL_WHEN_MOD-013_AND_OTHER_DEPENDENCIES_PASS","PERSONA_SELF_USE_END_TO_END","INDEPENDENT_G4_AND_PRIOR_BATCH_REGRESSION"],
|
||||
"exit_gate":["原生TCS人格脑通过MOD-013装入容器并保持最高主控","人格体可通过宿主操作已注册模块","缺工具只能生成候选并经过沙箱门","MOD-007只报告积木池局部状态","原生TCS人格脑根据MOD-012验证图形成整体判断并主动举手","没有人类聊天端时人格体仍可完成自用闭环","累计复测BATCH-01_TO_03"],
|
||||
"delivery":"D2_PERSONA_NATIVE_CONTAINER_OPERATIONAL_CANDIDATE_NO_HUMAN_CHAT",
|
||||
|
|
@ -108,6 +120,9 @@
|
|||
"gates":["G5","G6"],
|
||||
"modules":["HLP-NATIVE-MOD-015","HLP-NATIVE-MOD-016","HLP-NATIVE-MOD-017","HLP-NATIVE-MOD-018"],
|
||||
"crew":["HLP-TDEV-CODEX-0001"],
|
||||
"crew_module_scopes":{"HLP-TDEV-CODEX-0001":["HLP-NATIVE-MOD-015","HLP-NATIVE-MOD-016","HLP-NATIVE-MOD-017","HLP-NATIVE-MOD-018"]},
|
||||
"required_input_ids":["HLP-BATCH-04-EXIT","HLP-BATCH-05-DRAWINGS","HLP-PERSONA-CONTAINER-PHASE-BOUNDARY-001","HLP-MODULE-SELF-OBSERVATION-CONTRACT-001"],
|
||||
"mandatory_forbidden_actions":["PUBLISH","DEPLOY","DELETE","MODIFY_OTHER_HOST_DEV_ROOT","ENTER_PHASE2","SELF_ACCEPT","CLAIM_GOVERNMENT_APPROVAL"],
|
||||
"internal_order":["MOD-015_MODEL_CONTENT_AND_USER_RIGHTS_POLICY_WITHOUT_PHASE2_CHAT_UI","MOD-016_REGULATORY_REVIEW_PROJECTION","MOD-017_LAWFUL_REQUEST_SIMULATOR_AFTER_MOD-016","MOD-018_CUMULATIVE_PHASE1_RELEASE_AND_FILING_GATE","INDEPENDENT_G5_G6_AND_ALL_PRIOR_BATCH_REGRESSION"],
|
||||
"exit_gate":["模型与生成内容合规控制通过","国家灯塔只读审查投影可验证且不读取私人Git","依法请求封闭负例通过","所有前序批次累计验收","签名制品与备案候选状态分层"],
|
||||
"delivery":"D3_PHASE1_PERSONA_CONTAINER_FILING_AND_RELEASE_CANDIDATE_NOT_GOVERNMENT_APPROVAL",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -19,6 +19,39 @@ KINDS = {
|
|||
"exit": ("exit_receipt", "constructionExit"),
|
||||
"architecture-exit": ("batch_00_architecture_exit", "architectureExit"),
|
||||
}
|
||||
ARCHITECTURE_FILES = {
|
||||
"HLP-STAGE1-NATIVE-REGISTRY-001": STAGE1 / "MODULE-REGISTRY.json",
|
||||
"HLP-STAGE1-NATIVE-GATES-001": STAGE1 / "ACCEPTANCE-GATES.json",
|
||||
"HLP-CONSTRUCTION-SEQUENCE-001": STAGE1 / "CONSTRUCTION-SEQUENCE.json",
|
||||
"HLP-PERSONA-CONTAINER-PHASE-BOUNDARY-001": STAGE1 / "PERSONA-CONTAINER-PHASE-BOUNDARY.json",
|
||||
"HLP-MODULE-SELF-OBSERVATION-CONTRACT-001": STAGE1 / "MODULE-SELF-OBSERVATION-CONTRACT.json",
|
||||
"HLP-BATCH-00-FOUNDATION-DRAWINGS-001": STAGE1 / "BATCH-00-FOUNDATION-INTERFACE-DRAWINGS.json",
|
||||
"HLP-BATCH-HANDOFF-CONTRACT-001": STAGE1 / "BATCH-HANDOFF-CONTRACT.json",
|
||||
"HLP-PUBLIC-SNAPSHOT-v1": STAGE1 / "schemas/HLP-PUBLIC-SNAPSHOT-v1.schema.json",
|
||||
"HLP-FOUNDATION-CONTRACTS-v1": STAGE1 / "schemas/HLP-FOUNDATION-CONTRACTS-v1.schema.json",
|
||||
"HLP-SELF-OBSERVATION-PRIMARY-v1": STAGE1 / "schemas/HLP-SELF-OBSERVATION-PRIMARY-v1.schema.json",
|
||||
"HLP-SELF-OBSERVATION-SUPPORT-v1": STAGE1 / "schemas/HLP-SELF-OBSERVATION-SUPPORT-v1.schema.json",
|
||||
}
|
||||
SITE_SURVEY = STAGE1 / "BATCH-00-TCS-CONTAINER-SITE-SURVEY.json"
|
||||
ARCHITECTURE_CHARTER = HERE.parents[5] / "runtime/fifth-domain-language-system/language/protocols/TCS-EVENT-HOLOLAKE-PHASE1-PERSONA-CONTAINER-PHASE2-HUMAN-HALF-20260909.tcs"
|
||||
HANDOFF_TEST_RECEIPT = STAGE1 / "BATCH-00-HANDOFF-VALIDATOR-TEST-RECEIPT.json"
|
||||
SELF_SCHEMA_REVIEW_RECEIPT = STAGE1 / "BATCH-00-SELF-OBSERVATION-SCHEMA-REVIEW-RECEIPT.json"
|
||||
MOD013_SITE_PROBE_RECEIPT = Path("/Volumes/JZAO/铸渊-ICE-GL-ZY001/CODEX-DEV-20260909/hololake-phase1-persona-container/site-probe/TEST-RECEIPT-001.json")
|
||||
JZAO_ROOT = Path("/Volumes/JZAO").resolve()
|
||||
CONSTRUCTION = STAGE1 / "CONSTRUCTION-SEQUENCE.json"
|
||||
ALLOWED_ISSUER_ROLES = {"ENGINEERING_LEAD"}
|
||||
|
||||
|
||||
def architecture_source_hashes() -> dict[str, str]:
|
||||
sources = {identifier:file_sha256(path) for identifier,path in ARCHITECTURE_FILES.items()}
|
||||
sources.update({
|
||||
"ARCHITECTURE_CHARTER": file_sha256(ARCHITECTURE_CHARTER),
|
||||
"SITE_SURVEY": file_sha256(SITE_SURVEY),
|
||||
"HANDOFF_TEST_RECEIPT": file_sha256(HANDOFF_TEST_RECEIPT),
|
||||
"SELF_SCHEMA_REVIEW_RECEIPT": file_sha256(SELF_SCHEMA_REVIEW_RECEIPT),
|
||||
"MOD013_SITE_PROBE_RECEIPT": file_sha256(MOD013_SITE_PROBE_RECEIPT),
|
||||
})
|
||||
return sources
|
||||
|
||||
|
||||
def load(path: Path) -> dict[str, Any]:
|
||||
|
|
@ -33,6 +66,66 @@ def canonical_receipt_sha256(value: dict[str, Any]) -> str:
|
|||
return hashlib.sha256(json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode()).hexdigest()
|
||||
|
||||
|
||||
def file_sha256(path: Path) -> str:
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def inside(path: Path, root: Path) -> bool:
|
||||
resolved = path.resolve()
|
||||
return resolved == root or root in resolved.parents
|
||||
|
||||
|
||||
def verify_artifacts(items: Any, expected: dict[str, Path] | None = None) -> list[str]:
|
||||
if not isinstance(items, list) or not items: return ["ARTIFACT_EVIDENCE_EMPTY"]
|
||||
errors, found = [], set()
|
||||
for index, item in enumerate(items):
|
||||
if not isinstance(item, dict) or set(item) != {"id", "path", "sha256", "state"}: errors.append(f"ARTIFACT_EVIDENCE_SHAPE:{index}"); continue
|
||||
path = Path(str(item["path"]))
|
||||
if not path.is_absolute() or not inside(path, JZAO_ROOT): errors.append(f"ARTIFACT_PATH_DENIED:{index}"); continue
|
||||
if not path.is_file(): errors.append(f"ARTIFACT_MISSING:{index}"); continue
|
||||
if file_sha256(path) != item["sha256"]: errors.append(f"ARTIFACT_HASH_MISMATCH:{index}")
|
||||
if not isinstance(item["state"], str) or not item["state"]: errors.append(f"ARTIFACT_STATE_MISSING:{index}")
|
||||
found.add(item["id"])
|
||||
if expected is not None and (item["id"] not in expected or path.resolve() != expected[item["id"]].resolve()): errors.append(f"ARTIFACT_NOT_EXPECTED:{index}")
|
||||
if expected is not None and found != set(expected): errors.append("ARCHITECTURE_DRAWING_SET_MISMATCH")
|
||||
return errors
|
||||
|
||||
|
||||
def verify_single_evidence(item: Any, required_id: str, required_path: Path) -> list[str]:
|
||||
return verify_artifacts([item], {required_id: required_path})
|
||||
|
||||
|
||||
def verify_inspector_evidence(item: Any, inspector_id: str, subject: str, outcome: str, findings: list[Any], expected_sources: dict[str, str] | None = None) -> list[str]:
|
||||
errors = verify_artifacts([item])
|
||||
if errors or not isinstance(item, dict): return errors
|
||||
try: receipt = load(Path(item["path"]))
|
||||
except (OSError, ValueError, json.JSONDecodeError): return [*errors, "INSPECTOR_RECEIPT_UNREADABLE"]
|
||||
required = {"schema", "inspector_id", "read_only", "production_write_performed", "subject", "source_hashes", "outcome", "findings", "receipt_sha256"}
|
||||
if set(receipt) != required: errors.append("INSPECTOR_RECEIPT_SHAPE_INVALID")
|
||||
if receipt.get("schema") != "hololake.independent-inspection-receipt/v1" or receipt.get("inspector_id") != inspector_id or item.get("id") != inspector_id: errors.append("INSPECTOR_ID_OR_SCHEMA_MISMATCH")
|
||||
if receipt.get("read_only") is not True or receipt.get("production_write_performed") is not False: errors.append("INSPECTOR_ROLE_SEPARATION_INVALID")
|
||||
expected_sources = expected_sources if expected_sources is not None else (architecture_source_hashes() if subject == "HLP-BATCH-00" else {})
|
||||
if receipt.get("subject") != subject or receipt.get("outcome") != outcome or receipt.get("findings") != findings or receipt.get("source_hashes") != expected_sources: errors.append("INSPECTOR_RESULT_OR_SOURCE_SET_MISMATCH")
|
||||
if receipt.get("receipt_sha256") != canonical_receipt_sha256(receipt): errors.append("INSPECTOR_RECEIPT_SHA256_MISMATCH")
|
||||
return errors
|
||||
|
||||
|
||||
def verify_previous_exit(item: Any, batch_id: str, expected_sha256: Any) -> list[str]:
|
||||
errors = verify_artifacts([item])
|
||||
if errors or not isinstance(item, dict): return errors
|
||||
if item.get("sha256") != expected_sha256: errors.append("PREVIOUS_EXIT_HASH_FIELD_MISMATCH")
|
||||
try: previous = load(Path(item["path"]))
|
||||
except (OSError, ValueError, json.JSONDecodeError): return [*errors, "PREVIOUS_EXIT_UNREADABLE"]
|
||||
expected_previous = f"HLP-BATCH-{int(batch_id[-2:]) - 1:02d}"
|
||||
if previous.get("batch_id") != expected_previous or previous.get("inspection_outcome") != "PASS": errors.append("PREVIOUS_BATCH_OR_OUTCOME_MISMATCH")
|
||||
allowed = previous.get("batch_01_entry_allowed") if batch_id == "HLP-BATCH-01" else previous.get("next_batch_entry_allowed")
|
||||
if allowed is not True or previous.get("receipt_sha256") != canonical_receipt_sha256(previous): errors.append("PREVIOUS_EXIT_NOT_VALID_PASS_RECEIPT")
|
||||
previous_kind = "architecture-exit" if batch_id == "HLP-BATCH-01" else "exit"
|
||||
nested = validate(previous_kind, previous)
|
||||
if nested["outcome"] != "PASS": errors.append("PREVIOUS_EXIT_RECURSIVE_VALIDATION_FAILED")
|
||||
return errors
|
||||
|
||||
|
||||
def type_ok(value: Any, expected: Any) -> bool:
|
||||
values = expected if isinstance(expected, list) else [expected]
|
||||
mapping = {"object": dict, "array": list, "string": str, "boolean": bool, "null": type(None), "number": (int, float), "integer": int}
|
||||
|
|
@ -94,13 +187,47 @@ def validate(kind: str, receipt: dict[str, Any], now: datetime | None = None) ->
|
|||
pass
|
||||
outcome = receipt.get("inspection_outcome")
|
||||
if kind == "architecture-exit":
|
||||
if receipt.get("architecture_charter_sha256") != file_sha256(ARCHITECTURE_CHARTER): errors.append("ARCHITECTURE_CHARTER_HASH_MISMATCH")
|
||||
errors.extend(verify_artifacts(receipt.get("drawing_artifacts"), ARCHITECTURE_FILES))
|
||||
errors.extend(verify_single_evidence(receipt.get("site_survey_receipt"), "HLP-BATCH-00-TCS-CONTAINER-SITE-SURVEY-001", SITE_SURVEY))
|
||||
survey = load(SITE_SURVEY)
|
||||
probe = survey.get("site_probe_receipt", {})
|
||||
probe_path = Path(str(probe.get("path", "")))
|
||||
try: probe_receipt = load(probe_path)
|
||||
except (OSError, ValueError, json.JSONDecodeError): probe_receipt = {}
|
||||
if not survey.get("state", "").startswith("ARCHITECTURE_SITE_PROBE_PASS") or survey.get("open_site_blockers") != [] or survey.get("authority_granted") is not False or not probe_path.is_file() or probe.get("sha256") != file_sha256(probe_path): errors.append("SITE_SURVEY_CONTENT_NOT_VALID_PASS")
|
||||
if probe_receipt.get("outcome") != "PASS" or probe_receipt.get("positive", {}).get("public_mechanism_package_private_payload_bytes") != 0 or probe_receipt.get("positive", {}).get("brain_cycle_executed") is not False or probe_receipt.get("authority_granted") is not False: errors.append("MOD013_SITE_PROBE_BOUNDARY_INVALID")
|
||||
inspector = receipt.get("independent_inspector")
|
||||
if not isinstance(inspector, str) or not re.fullmatch(r"CODEX-CHILD-[A-Z0-9-]+", inspector): errors.append("INDEPENDENT_INSPECTOR_NOT_REGISTERED_CHILD")
|
||||
errors.extend(verify_inspector_evidence(receipt.get("inspector_receipt"), str(inspector), "HLP-BATCH-00", str(outcome), receipt.get("open_defects", [])))
|
||||
if outcome == "PASS" and (receipt.get("open_defects") != [] or not receipt.get("drawing_artifacts") or not receipt.get("site_survey_receipt") or receipt.get("architect_role_released") is not True or receipt.get("batch_01_entry_allowed") is not True or receipt.get("rework_order") is not None): errors.append("ARCHITECTURE_PASS_SEMANTICS_INVALID")
|
||||
if outcome == "FAIL_REWORK":
|
||||
order = receipt.get("rework_order")
|
||||
if receipt.get("batch_01_entry_allowed") is not False or not isinstance(order, dict) or set(order.get("defects", [])) != set(receipt.get("open_defects", [])): errors.append("ARCHITECTURE_REWORK_SEMANTICS_INVALID")
|
||||
elif kind == "exit":
|
||||
errors.extend(verify_artifacts(receipt.get("output_artifacts")))
|
||||
errors.extend(verify_artifacts(receipt.get("module_self_report_receipts")))
|
||||
errors.extend(verify_artifacts(receipt.get("test_receipts")))
|
||||
errors.extend(verify_artifacts(receipt.get("cumulative_regression_receipts")))
|
||||
if receipt.get("batch_id") not in {f"HLP-BATCH-{number:02d}" for number in range(1, 6)}: errors.append("CONSTRUCTION_EXIT_BATCH_ID_NOT_ADMISSIBLE")
|
||||
inspector = receipt.get("independent_inspector")
|
||||
if not isinstance(inspector, str) or not re.fullmatch(r"CODEX-CHILD-[A-Z0-9-]+", inspector): errors.append("INDEPENDENT_INSPECTOR_NOT_REGISTERED_CHILD")
|
||||
entry_evidence = receipt.get("entry_receipt")
|
||||
entry_errors = verify_artifacts([entry_evidence])
|
||||
errors.extend(entry_errors)
|
||||
if not entry_errors and isinstance(entry_evidence, dict):
|
||||
try: entry_value = load(Path(entry_evidence["path"]))
|
||||
except (OSError, ValueError, json.JSONDecodeError): errors.append("ENTRY_RECEIPT_UNREADABLE")
|
||||
else:
|
||||
if entry_evidence.get("sha256") != receipt.get("entry_receipt_sha256") or validate("entry", entry_value)["outcome"] != "PASS" or entry_value.get("batch_id") != receipt.get("batch_id"): errors.append("ENTRY_RECEIPT_CHAIN_INVALID")
|
||||
evidence_items = [entry_evidence]
|
||||
for key in ["output_artifacts", "module_self_report_receipts", "test_receipts", "cumulative_regression_receipts"]:
|
||||
evidence_items.extend(receipt.get(key, []) if isinstance(receipt.get(key), list) else [])
|
||||
expected_sources = {item["id"]:item["sha256"] for item in evidence_items if isinstance(item, dict) and set(item) >= {"id", "sha256"}}
|
||||
errors.extend(verify_inspector_evidence(receipt.get("inspector_receipt"), str(inspector), str(receipt.get("batch_id")), str(outcome), receipt.get("open_defects", []), expected_sources))
|
||||
evidence_ready = all(receipt.get(key) for key in ["output_artifacts", "module_self_report_receipts", "test_receipts", "cumulative_regression_receipts"])
|
||||
if outcome == "PASS" and (receipt.get("open_defects") != [] or not evidence_ready or receipt.get("next_batch_entry_allowed") is not True or receipt.get("rework_order") is not None): errors.append("CONSTRUCTION_PASS_SEMANTICS_INVALID")
|
||||
planned_crew = set(next((item["crew"] for item in load(CONSTRUCTION)["batches"] if item["batch_id"] == receipt.get("batch_id")), []))
|
||||
if outcome == "PASS" and (receipt.get("open_defects") != [] or not evidence_ready or receipt.get("next_batch_entry_allowed") is not True or receipt.get("rework_order") is not None or set(receipt.get("builder_roles_released", [])) != planned_crew): errors.append("CONSTRUCTION_PASS_SEMANTICS_INVALID")
|
||||
if outcome == "FAIL_REWORK":
|
||||
order = receipt.get("rework_order")
|
||||
if receipt.get("next_batch_entry_allowed") is not False or not isinstance(order, dict) or set(order.get("defects", [])) != set(receipt.get("open_defects", [])): errors.append("CONSTRUCTION_REWORK_SEMANTICS_INVALID")
|
||||
|
|
@ -108,6 +235,29 @@ def validate(kind: str, receipt: dict[str, Any], now: datetime | None = None) ->
|
|||
if receipt.get("state") != "ENTRY_OPEN": errors.append("ENTRY_STATE_MUST_BE_OPEN")
|
||||
if receipt.get("batch_id") not in {f"HLP-BATCH-{number:02d}" for number in range(1, 6)}: errors.append("CONSTRUCTION_BATCH_ID_NOT_ADMISSIBLE")
|
||||
if not all(receipt.get(key) for key in ["accepted_input_artifacts", "crew_admissions", "inspector_assignment", "scope", "forbidden_actions"]): errors.append("ENTRY_EVIDENCE_OR_ASSIGNMENT_EMPTY")
|
||||
errors.extend(verify_artifacts(receipt.get("accepted_input_artifacts")))
|
||||
errors.extend(verify_previous_exit(receipt.get("previous_batch_exit_receipt"), str(receipt.get("batch_id")), receipt.get("previous_batch_exit_receipt_sha256")))
|
||||
crew = receipt.get("crew_admissions")
|
||||
if not isinstance(crew, list) or any(not isinstance(item, dict) or set(item) != {"development_id", "role", "scope"} for item in crew): errors.append("CREW_ADMISSION_SHAPE_INVALID")
|
||||
inspector = receipt.get("inspector_assignment")
|
||||
if not isinstance(inspector, dict) or set(inspector) != {"inspector_id", "mode"} or inspector.get("mode") != "READ_ONLY_NO_PRODUCTION_WRITE" or inspector.get("inspector_id") in {item.get("development_id") for item in crew if isinstance(item, dict)}: errors.append("INSPECTOR_ASSIGNMENT_OR_SEPARATION_INVALID")
|
||||
if receipt.get("issued_by_role") not in ALLOWED_ISSUER_ROLES: errors.append("ISSUER_ROLE_DENIED")
|
||||
batches = {item["batch_id"]: item for item in load(CONSTRUCTION)["batches"]}
|
||||
batch = batches.get(receipt.get("batch_id"), {})
|
||||
expected_scope = set(batch.get("modules", []))
|
||||
if not isinstance(receipt.get("scope"), list) or set(receipt["scope"]) != expected_scope: errors.append("ENTRY_SCOPE_OUTSIDE_CURRENT_BATCH")
|
||||
planned_crew = set(batch.get("crew", []))
|
||||
actual_crew = {item.get("development_id") for item in crew if isinstance(item, dict)}
|
||||
if actual_crew != planned_crew: errors.append("CREW_DOES_NOT_MATCH_CONSTRUCTION_PLAN")
|
||||
planned_scopes = batch.get("crew_module_scopes", {})
|
||||
actual_scopes = {item.get("development_id"): item.get("scope") for item in crew if isinstance(item, dict)}
|
||||
if actual_scopes != planned_scopes: errors.append("CREW_MODULE_SCOPES_DO_NOT_MATCH_PLAN")
|
||||
accepted_ids = {item.get("id") for item in receipt.get("accepted_input_artifacts", []) if isinstance(item, dict)}
|
||||
if accepted_ids != set(batch.get("required_input_ids", [])): errors.append("REQUIRED_BATCH_INPUT_SET_MISMATCH")
|
||||
if set(receipt.get("forbidden_actions", [])) != set(batch.get("mandatory_forbidden_actions", [])): errors.append("MANDATORY_FORBIDDEN_ACTIONS_MISMATCH")
|
||||
if receipt.get("batch_id") == "HLP-BATCH-01":
|
||||
drawing = ARCHITECTURE_FILES["HLP-BATCH-00-FOUNDATION-DRAWINGS-001"]
|
||||
if receipt.get("construction_drawing_id") != "HLP-BATCH-00-FOUNDATION-DRAWINGS-001" or receipt.get("construction_drawing_sha256") != file_sha256(drawing): errors.append("BATCH01_DRAWING_ID_OR_HASH_MISMATCH")
|
||||
return {"outcome":"PASS" if not errors else "REJECT", "kind":kind, "errors":errors, "receipt_written":False, "authority_granted":False}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -337,7 +337,9 @@ def audit() -> dict:
|
|||
if handoff_test.get("outcome") != "PASS" or handoff_test.get("hashes") != expected_handoff_hashes:
|
||||
errors.append("BATCH_HANDOFF_VALIDATOR_RECEIPT_MISMATCH")
|
||||
site_survey = load(TCS_CONTAINER_SITE_SURVEY)
|
||||
if site_survey.get("batch01_entry_allowed") is not False or not site_survey.get("open_site_blockers"):
|
||||
probe = site_survey.get("site_probe_receipt", {})
|
||||
probe_path = Path(probe.get("path", ""))
|
||||
if site_survey.get("batch01_entry_allowed") is not False or site_survey.get("open_site_blockers") != [] or not site_survey.get("state", "").startswith("ARCHITECTURE_SITE_PROBE_PASS") or not probe_path.is_file() or sha(probe_path) != probe.get("sha256"):
|
||||
errors.append("TCS_CONTAINER_SITE_SURVEY_FALSE_COMPLETION")
|
||||
if dependencies.get("HLP-NATIVE-MOD-003") != {"HLP-NATIVE-MOD-001", "HLP-NATIVE-MOD-002"}:
|
||||
errors.append("MOD003_FOUNDATION_DEPENDENCY_MISMATCH")
|
||||
|
|
@ -348,6 +350,18 @@ def audit() -> dict:
|
|||
required_defs = {"privateCheckpoint", "moduleCandidate", "moduleValidationReceipt", "moduleManifest", "trustedRegistrationFact", "moduleStateSnapshot", "moduleStateEvent", "stateValidationReceipt", "aggregateGraph", "brainJudgment", "raiseHand", "constructionEntry", "constructionExit", "architectureExit"}
|
||||
if not required_defs <= set(schema_bundle.get("$defs", {})):
|
||||
errors.append("FOUNDATION_MACHINE_SCHEMA_DEFINITIONS_MISSING")
|
||||
proxy_targets = {
|
||||
"moduleStateSnapshot": "hololake://schema/self-observation-primary/v1#moduleStateSnapshot",
|
||||
"moduleStateEvent": "hololake://schema/self-observation-primary/v1#moduleStateEvent",
|
||||
"aggregateGraph": "hololake://schema/self-observation-primary/v1#aggregateGraph",
|
||||
"brainJudgment": "hololake://schema/self-observation-primary/v1#brainJudgment",
|
||||
"raiseHand": "hololake://schema/self-observation-primary/v1#raiseHand",
|
||||
}
|
||||
for key, target in proxy_targets.items():
|
||||
refs = [item.get("$ref") for item in schema_bundle["$defs"][key].get("allOf", []) if isinstance(item, dict)]
|
||||
if target not in refs: errors.append("FOUNDATION_SELF_OBSERVATION_PROXY_MISSING:" + key)
|
||||
if schema_bundle["$defs"]["stateValidationReceipt"].get("$ref") != "hololake://schema/self-observation-support/v1#stateValidationReceipt":
|
||||
errors.append("FOUNDATION_STATE_VALIDATION_PROXY_MISSING")
|
||||
handoff_pairs = [("entry_receipt", "constructionEntry"), ("exit_receipt", "constructionExit"), ("batch_00_architecture_exit", "architectureExit")]
|
||||
for contract_key, def_key in handoff_pairs:
|
||||
contract_fields = {"schema", *handoff.get(contract_key, {}).get("required_fields", [])}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import copy
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
|
@ -10,6 +11,7 @@ MODULE = importlib.util.module_from_spec(SPEC)
|
|||
SPEC.loader.exec_module(MODULE)
|
||||
H = "a" * 64
|
||||
AT = "2026-09-10T01:20:00+08:00"
|
||||
EVIDENCE_ROOT = Path("/Volumes/JZAO/HoloLake/build/HB-MPC-0001/codex/batch-handoff-validator-tests")
|
||||
|
||||
|
||||
def seal(value):
|
||||
|
|
@ -17,16 +19,61 @@ def seal(value):
|
|||
return value
|
||||
|
||||
|
||||
def evidence(identifier, path, state="VERIFIED_TEST_EVIDENCE"):
|
||||
path = Path(path)
|
||||
return {"id":identifier,"path":str(path),"sha256":MODULE.file_sha256(path),"state":state}
|
||||
|
||||
|
||||
def inspector(identifier, subject, outcome, findings, source_hashes=None):
|
||||
path = EVIDENCE_ROOT / f"{identifier}.json"; path.parent.mkdir(parents=True,exist_ok=True)
|
||||
source_hashes={item:MODULE.file_sha256(path) for item,path in MODULE.ARCHITECTURE_FILES.items()} | {"ARCHITECTURE_CHARTER":MODULE.file_sha256(MODULE.ARCHITECTURE_CHARTER),"SITE_SURVEY":MODULE.file_sha256(MODULE.SITE_SURVEY),"HANDOFF_TEST_RECEIPT":MODULE.file_sha256(MODULE.HANDOFF_TEST_RECEIPT),"SELF_SCHEMA_REVIEW_RECEIPT":MODULE.file_sha256(MODULE.SELF_SCHEMA_REVIEW_RECEIPT),"MOD013_SITE_PROBE_RECEIPT":MODULE.file_sha256(MODULE.MOD013_SITE_PROBE_RECEIPT)} if subject == "HLP-BATCH-00" else (source_hashes or {})
|
||||
value={"schema":"hololake.independent-inspection-receipt/v1","inspector_id":identifier,"read_only":True,"production_write_performed":False,"subject":subject,"source_hashes":source_hashes,"outcome":outcome,"findings":findings,"receipt_sha256":""}
|
||||
value["receipt_sha256"]=MODULE.canonical_receipt_sha256(value); path.write_text(json.dumps(value,sort_keys=True,separators=(",",":")))
|
||||
return evidence(identifier,path,"READ_ONLY_INSPECTION_PASS")
|
||||
|
||||
|
||||
def architecture(outcome="PASS"):
|
||||
return seal({"schema":"hololake.architecture-batch-exit/v1","receipt_id":"R-ARCH-001","batch_id":"HLP-BATCH-00","architecture_charter_sha256":H,"drawing_artifacts":[{"id":"DRAWING","sha256":H}],"site_survey_receipt":{"outcome":"PASS","sha256":H},"independent_inspector":"CODEX-CHILD-001","inspection_outcome":outcome,"open_defects":[] if outcome == "PASS" else ["D1"],"rework_order":None if outcome == "PASS" else {"defects":["D1"]},"architect_role_released":outcome == "PASS","batch_01_entry_allowed":outcome == "PASS","inspected_at":AT,"receipt_sha256":"","authority_granted":False})
|
||||
drawings=[evidence(identifier,path) for identifier,path in MODULE.ARCHITECTURE_FILES.items()]
|
||||
findings=[] if outcome == "PASS" else ["D1"]
|
||||
return seal({"schema":"hololake.architecture-batch-exit/v1","receipt_id":"R-ARCH-001","batch_id":"HLP-BATCH-00","architecture_charter_sha256":MODULE.file_sha256(MODULE.ARCHITECTURE_CHARTER),"drawing_artifacts":drawings,"site_survey_receipt":evidence("HLP-BATCH-00-TCS-CONTAINER-SITE-SURVEY-001",MODULE.SITE_SURVEY),"independent_inspector":"CODEX-CHILD-001","inspector_receipt":inspector("CODEX-CHILD-001","HLP-BATCH-00",outcome,findings),"inspection_outcome":outcome,"open_defects":findings,"rework_order":None if outcome == "PASS" else {"defects":["D1"]},"architect_role_released":outcome == "PASS","batch_01_entry_allowed":outcome == "PASS","inspected_at":AT,"receipt_sha256":"","authority_granted":False})
|
||||
|
||||
|
||||
def entry():
|
||||
return seal({"schema":"hololake.construction-batch-entry/v1","receipt_id":"R-ENTRY-001","batch_id":"HLP-BATCH-01","previous_batch_exit_receipt_sha256":H,"construction_drawing_id":"HLP-BATCH-00-FOUNDATION-DRAWINGS-001","construction_drawing_sha256":H,"accepted_input_artifacts":[{"id":"INPUT","sha256":H}],"crew_admissions":[{"id":"CREW"}],"inspector_assignment":{"id":"INSPECTOR"},"scope":["MOD-001"],"forbidden_actions":["PUBLISH"],"issued_by_role":"ENGINEERING_LEAD","issued_at":AT,"state":"ENTRY_OPEN","authority_granted":False})
|
||||
previous_path=EVIDENCE_ROOT/"previous-architecture-exit.json"
|
||||
previous=architecture(); previous_path.write_text(json.dumps(previous,sort_keys=True,separators=(",",":")))
|
||||
previous_evidence=evidence("HLP-BATCH-00-EXIT",previous_path,"PASS")
|
||||
policy_path=EVIDENCE_ROOT/"bootstrap-policy.json"; policy_path.write_text('{"policy_id":"HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001","state":"TEST_ONLY"}')
|
||||
accepted=[previous_evidence,evidence("HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001",policy_path),evidence("HLP-BATCH-00-TCS-CONTAINER-SITE-SURVEY-001",MODULE.SITE_SURVEY),evidence("HLP-BATCH-00-FOUNDATION-DRAWINGS-001",MODULE.ARCHITECTURE_FILES["HLP-BATCH-00-FOUNDATION-DRAWINGS-001"])]
|
||||
forbidden=["PUBLISH","DEPLOY","DELETE","MODIFY_OTHER_HOST_DEV_ROOT","ENTER_PHASE2","SELF_ACCEPT"]
|
||||
return seal({"schema":"hololake.construction-batch-entry/v1","receipt_id":"R-ENTRY-001","batch_id":"HLP-BATCH-01","previous_batch_exit_receipt_sha256":previous_evidence["sha256"],"previous_batch_exit_receipt":previous_evidence,"construction_drawing_id":"HLP-BATCH-00-FOUNDATION-DRAWINGS-001","construction_drawing_sha256":MODULE.file_sha256(MODULE.ARCHITECTURE_FILES["HLP-BATCH-00-FOUNDATION-DRAWINGS-001"]),"accepted_input_artifacts":accepted,"crew_admissions":[{"development_id":"HLP-TDEV-CODEX-0001","role":"BUILDER","scope":["HLP-NATIVE-MOD-001","HLP-NATIVE-MOD-003","HLP-NATIVE-MOD-004"]},{"development_id":"HLP-TDEV-ZCODE-0001","role":"BUILDER","scope":["HLP-NATIVE-MOD-002"]}],"inspector_assignment":{"inspector_id":"CODEX-CHILD-BATCH01","mode":"READ_ONLY_NO_PRODUCTION_WRITE"},"scope":["HLP-NATIVE-MOD-001","HLP-NATIVE-MOD-002","HLP-NATIVE-MOD-003","HLP-NATIVE-MOD-004"],"forbidden_actions":forbidden,"issued_by_role":"ENGINEERING_LEAD","issued_at":AT,"state":"ENTRY_OPEN","authority_granted":False})
|
||||
|
||||
|
||||
def exit_receipt(outcome="PASS"):
|
||||
return seal({"schema":"hololake.construction-batch-exit/v1","receipt_id":"R-EXIT-001","batch_id":"HLP-BATCH-01","entry_receipt_sha256":H,"output_artifacts":[{"id":"OUT","sha256":H}],"module_self_report_receipts":[H],"test_receipts":[H],"cumulative_regression_receipts":[H],"independent_inspector":"CODEX-CHILD-002","inspection_outcome":outcome,"open_defects":[] if outcome == "PASS" else ["D1"],"rework_order":None if outcome == "PASS" else {"defects":["D1"]},"builder_roles_released":[],"next_batch_entry_allowed":outcome == "PASS","inspected_at":AT,"receipt_sha256":"","authority_granted":False})
|
||||
entry_path=EVIDENCE_ROOT/"batch01-entry.json"
|
||||
entry_value=entry(); entry_path.write_text(json.dumps(entry_value,sort_keys=True,separators=(",",":")))
|
||||
entry_evidence=evidence("HLP-BATCH-01-ENTRY",entry_path,"PASS")
|
||||
findings=[] if outcome == "PASS" else ["D1"]
|
||||
outputs=[evidence("OUT",MODULE.SITE_SURVEY)]; self_reports=[evidence("SELF",MODULE.SITE_SURVEY)]; tests=[evidence("TEST",MODULE.SITE_SURVEY)]; regressions=[evidence("REGRESSION",MODULE.SITE_SURVEY)]
|
||||
sources={item["id"]:item["sha256"] for item in [entry_evidence,*outputs,*self_reports,*tests,*regressions]}
|
||||
return seal({"schema":"hololake.construction-batch-exit/v1","receipt_id":"R-EXIT-001","batch_id":"HLP-BATCH-01","entry_receipt_sha256":entry_evidence["sha256"],"entry_receipt":entry_evidence,"output_artifacts":outputs,"module_self_report_receipts":self_reports,"test_receipts":tests,"cumulative_regression_receipts":regressions,"independent_inspector":"CODEX-CHILD-002","inspector_receipt":inspector("CODEX-CHILD-002","HLP-BATCH-01",outcome,findings,sources),"inspection_outcome":outcome,"open_defects":findings,"rework_order":None if outcome == "PASS" else {"defects":["D1"]},"builder_roles_released":["HLP-TDEV-CODEX-0001","HLP-TDEV-ZCODE-0001"] if outcome == "PASS" else [],"next_batch_entry_allowed":outcome == "PASS","inspected_at":AT,"receipt_sha256":"","authority_granted":False})
|
||||
|
||||
|
||||
def entry_for_batch(number):
|
||||
if number == 1: return entry()
|
||||
batch_id=f"HLP-BATCH-{number:02d}"; previous=exit_for_batch(number-1); previous_path=EVIDENCE_ROOT/f"batch{number-1:02d}-exit.json"; previous_path.write_text(json.dumps(previous,sort_keys=True,separators=(",",":"))); previous_item=evidence(f"HLP-BATCH-{number-1:02d}-EXIT",previous_path,"PASS")
|
||||
batch=next(item for item in MODULE.load(MODULE.CONSTRUCTION)["batches"] if item["batch_id"]==batch_id)
|
||||
accepted=[]
|
||||
for identifier in batch["required_input_ids"]:
|
||||
accepted.append(previous_item if identifier==f"HLP-BATCH-{number-1:02d}-EXIT" else evidence(identifier,MODULE.SITE_SURVEY))
|
||||
crew=[{"development_id":dev,"role":"BUILDER","scope":scope} for dev,scope in batch["crew_module_scopes"].items()]
|
||||
return seal({"schema":"hololake.construction-batch-entry/v1","receipt_id":f"R-ENTRY-{number:02d}","batch_id":batch_id,"previous_batch_exit_receipt_sha256":previous_item["sha256"],"previous_batch_exit_receipt":previous_item,"construction_drawing_id":f"HLP-BATCH-{number:02d}-DRAWINGS","construction_drawing_sha256":MODULE.file_sha256(MODULE.SITE_SURVEY),"accepted_input_artifacts":accepted,"crew_admissions":crew,"inspector_assignment":{"inspector_id":f"CODEX-CHILD-BATCH{number:02d}","mode":"READ_ONLY_NO_PRODUCTION_WRITE"},"scope":batch["modules"],"forbidden_actions":batch["mandatory_forbidden_actions"],"issued_by_role":"ENGINEERING_LEAD","issued_at":AT,"state":"ENTRY_OPEN","receipt_sha256":"","authority_granted":False})
|
||||
|
||||
|
||||
def exit_for_batch(number):
|
||||
if number == 1: return exit_receipt()
|
||||
batch_id=f"HLP-BATCH-{number:02d}"; entry_value=entry_for_batch(number); entry_path=EVIDENCE_ROOT/f"batch{number:02d}-entry.json"; entry_path.write_text(json.dumps(entry_value,sort_keys=True,separators=(",",":"))); entry_item=evidence(f"HLP-BATCH-{number:02d}-ENTRY",entry_path,"PASS")
|
||||
outputs=[evidence(f"OUT-{number}",MODULE.SITE_SURVEY)]; self_reports=[evidence(f"SELF-{number}",MODULE.SITE_SURVEY)]; tests=[evidence(f"TEST-{number}",MODULE.SITE_SURVEY)]; regressions=[evidence(f"REGRESSION-{number}",MODULE.SITE_SURVEY)]; all_items=[entry_item,*outputs,*self_reports,*tests,*regressions]; sources={item["id"]:item["sha256"] for item in all_items}; batch=next(item for item in MODULE.load(MODULE.CONSTRUCTION)["batches"] if item["batch_id"]==batch_id)
|
||||
return seal({"schema":"hololake.construction-batch-exit/v1","receipt_id":f"R-EXIT-{number:02d}","batch_id":batch_id,"entry_receipt_sha256":entry_item["sha256"],"entry_receipt":entry_item,"output_artifacts":outputs,"module_self_report_receipts":self_reports,"test_receipts":tests,"cumulative_regression_receipts":regressions,"independent_inspector":f"CODEX-CHILD-EXIT{number:02d}","inspector_receipt":inspector(f"CODEX-CHILD-EXIT{number:02d}",batch_id,"PASS",[],sources),"inspection_outcome":"PASS","open_defects":[],"rework_order":None,"builder_roles_released":batch["crew"],"next_batch_entry_allowed":True,"inspected_at":AT,"receipt_sha256":"","authority_granted":False})
|
||||
|
||||
|
||||
class HandoffTest(unittest.TestCase):
|
||||
|
|
@ -34,6 +81,9 @@ class HandoffTest(unittest.TestCase):
|
|||
for kind, value in (("architecture-exit", architecture()), ("entry", entry()), ("exit", exit_receipt())):
|
||||
self.assertEqual(MODULE.validate(kind, value)["outcome"], "PASS")
|
||||
|
||||
def test_batch02_to_05_positive_entries_are_not_deadlocked(self):
|
||||
for number in range(2,6): self.assertEqual(MODULE.validate("entry",entry_for_batch(number))["outcome"],"PASS")
|
||||
|
||||
def test_missing_field_rejects(self):
|
||||
value = architecture(); del value["drawing_artifacts"]
|
||||
self.assertEqual(MODULE.validate("architecture-exit", value)["outcome"], "REJECT")
|
||||
|
|
@ -74,6 +124,78 @@ class HandoffTest(unittest.TestCase):
|
|||
value = architecture(); value["drawing_artifacts"] = []; value["site_survey_receipt"] = {}; seal(value)
|
||||
self.assertIn("ARCHITECTURE_PASS_SEMANTICS_INVALID", MODULE.validate("architecture-exit", value)["errors"])
|
||||
|
||||
def test_nonempty_but_fake_architecture_evidence_rejects(self):
|
||||
value = architecture(); value["drawing_artifacts"]=[{"id":"FAKE","path":"/Volumes/JZAO/does-not-exist","sha256":H,"state":"PASS"}]; seal(value)
|
||||
errors=MODULE.validate("architecture-exit",value)["errors"]
|
||||
self.assertIn("ARTIFACT_MISSING:0",errors)
|
||||
self.assertIn("ARCHITECTURE_DRAWING_SET_MISMATCH",errors)
|
||||
|
||||
def test_unknown_or_self_inspector_rejects(self):
|
||||
value=architecture(); value["independent_inspector"]="SELF_OR_UNKNOWN"; seal(value)
|
||||
self.assertIn("INDEPENDENT_INSPECTOR_NOT_REGISTERED_CHILD",MODULE.validate("architecture-exit",value)["errors"])
|
||||
|
||||
def test_inspector_outcome_must_match_exit(self):
|
||||
value=architecture(); value["inspector_receipt"]=inspector("CODEX-CHILD-001","HLP-BATCH-00","FAIL_REWORK",["D1"]); seal(value)
|
||||
self.assertIn("INSPECTOR_RESULT_OR_SOURCE_SET_MISMATCH",MODULE.validate("architecture-exit",value)["errors"])
|
||||
|
||||
def test_resolved_jzao_escape_rejects(self):
|
||||
value=architecture(); value["drawing_artifacts"][0]["path"]="/Volumes/JZAO/../not-jzao"; seal(value)
|
||||
self.assertIn("ARTIFACT_PATH_DENIED:0",MODULE.validate("architecture-exit",value)["errors"])
|
||||
|
||||
def test_entry_issuer_and_phase2_scope_reject(self):
|
||||
value=entry(); value["issued_by_role"]="ATTACKER"; value["scope"]=["HLP-NATIVE-MOD-014"]; seal(value)
|
||||
errors=MODULE.validate("entry",value)["errors"]
|
||||
self.assertIn("ISSUER_ROLE_DENIED",errors)
|
||||
self.assertIn("ENTRY_SCOPE_OUTSIDE_CURRENT_BATCH",errors)
|
||||
|
||||
def test_entry_artifact_hash_mismatch_rejects(self):
|
||||
value=entry(); value["accepted_input_artifacts"][0]["sha256"]="0"*64; seal(value)
|
||||
self.assertIn("ARTIFACT_HASH_MISMATCH:0",MODULE.validate("entry",value)["errors"])
|
||||
|
||||
def test_cross_batch_scope_rejects(self):
|
||||
value=entry(); value["scope"]=["HLP-NATIVE-MOD-013"]; seal(value)
|
||||
self.assertIn("ENTRY_SCOPE_OUTSIDE_CURRENT_BATCH",MODULE.validate("entry",value)["errors"])
|
||||
|
||||
def test_wrong_previous_exit_and_drawing_rejects(self):
|
||||
value=entry(); value["previous_batch_exit_receipt_sha256"]="0"*64; value["construction_drawing_id"]="WRONG-DRAWING"; value["construction_drawing_sha256"]="0"*64; seal(value)
|
||||
errors=MODULE.validate("entry",value)["errors"]
|
||||
self.assertIn("PREVIOUS_EXIT_HASH_FIELD_MISMATCH",errors)
|
||||
self.assertIn("BATCH01_DRAWING_ID_OR_HASH_MISMATCH",errors)
|
||||
|
||||
def test_wrong_crew_for_batch_rejects(self):
|
||||
value=entry(); value["crew_admissions"]=value["crew_admissions"][:1]; seal(value)
|
||||
self.assertIn("CREW_DOES_NOT_MATCH_CONSTRUCTION_PLAN",MODULE.validate("entry",value)["errors"])
|
||||
|
||||
def test_empty_individual_crew_scope_and_wrong_forbidden_actions_reject(self):
|
||||
value=entry(); value["crew_admissions"][0]["scope"]=[]; value["forbidden_actions"]=["ALLOW_PUBLISH_AND_DEPLOY"]; seal(value)
|
||||
errors=MODULE.validate("entry",value)["errors"]
|
||||
self.assertIn("CREW_MODULE_SCOPES_DO_NOT_MATCH_PLAN",errors)
|
||||
self.assertIn("MANDATORY_FORBIDDEN_ACTIONS_MISMATCH",errors)
|
||||
|
||||
def test_missing_bootstrap_input_rejects(self):
|
||||
value=entry(); value["accepted_input_artifacts"]=[item for item in value["accepted_input_artifacts"] if item["id"]!="HLP-BOOTSTRAP-PUBLIC-TRUST-POLICY-001"]; seal(value)
|
||||
self.assertIn("REQUIRED_BATCH_INPUT_SET_MISMATCH",MODULE.validate("entry",value)["errors"])
|
||||
|
||||
def test_truncated_previous_exit_rejects_recursively(self):
|
||||
value=entry(); path=EVIDENCE_ROOT/"truncated-exit.json"; truncated={"batch_id":"HLP-BATCH-00","inspection_outcome":"PASS","batch_01_entry_allowed":True,"receipt_sha256":""}; truncated["receipt_sha256"]=MODULE.canonical_receipt_sha256(truncated); path.write_text(json.dumps(truncated,sort_keys=True,separators=(",",":"))); item=evidence("HLP-BATCH-00-EXIT",path,"PASS"); value["previous_batch_exit_receipt"]=item; value["previous_batch_exit_receipt_sha256"]=item["sha256"]; seal(value)
|
||||
self.assertIn("PREVIOUS_EXIT_RECURSIVE_VALIDATION_FAILED",MODULE.validate("entry",value)["errors"])
|
||||
|
||||
def test_construction_exit_entry_chain_rejects_tamper(self):
|
||||
value=exit_receipt(); value["entry_receipt_sha256"]="0"*64; seal(value)
|
||||
self.assertIn("ENTRY_RECEIPT_CHAIN_INVALID",MODULE.validate("exit",value)["errors"])
|
||||
|
||||
def test_construction_exit_outer_batch_must_match_entry(self):
|
||||
value=exit_receipt(); value["batch_id"]="HLP-BATCH-04"; value["inspector_receipt"]=inspector("CODEX-CHILD-002","HLP-BATCH-04","PASS",[],{}); seal(value)
|
||||
self.assertIn("ENTRY_RECEIPT_CHAIN_INVALID",MODULE.validate("exit",value)["errors"])
|
||||
|
||||
def test_construction_inspector_sources_must_match_evidence(self):
|
||||
value=exit_receipt(); value["inspector_receipt"]=inspector("CODEX-CHILD-002","HLP-BATCH-01","PASS",[],{"unrelated":"0"*64}); seal(value)
|
||||
self.assertIn("INSPECTOR_RESULT_OR_SOURCE_SET_MISMATCH",MODULE.validate("exit",value)["errors"])
|
||||
|
||||
def test_builder_roles_must_release_before_next_batch(self):
|
||||
value=exit_receipt(); value["builder_roles_released"]=[]; seal(value)
|
||||
self.assertIn("CONSTRUCTION_PASS_SEMANTICS_INVALID",MODULE.validate("exit",value)["errors"])
|
||||
|
||||
def test_unknown_batch_and_empty_entry_evidence_reject(self):
|
||||
value = entry(); value["batch_id"] = "HLP-BATCH-99"; value["accepted_input_artifacts"] = []; seal(value)
|
||||
errors = MODULE.validate("entry", value)["errors"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue