diff --git a/engineering/INDEX.md b/engineering/INDEX.md index 1ff24f8..a3711a6 100644 --- a/engineering/INDEX.md +++ b/engineering/INDEX.md @@ -32,6 +32,7 @@ Windows / macOS / Linux 构建机与安装包 | 时间 | 版本 | 记录 | 状态 | | --- | --- | --- | --- | +| 2026-08-11 | GH-PNCC 成功回执完成检查点绑定 | [把完成回执的结构化事实重新绑定到人格 Git 检查点](operations/2026-08-11-hololake-pncc-success-receipt-completion-checkpoint-binding.md) | 本地源码、完整 Rust/前端/路由测试、原生权威与严格 clippy 已通过;GHNQG 和发布待验收 | | 2026-08-11 | GH-PNCC 成功回执唤醒器官合同绑定 | [成功回执唤醒器官合同证据绑定](operations/2026-08-11-hololake-pncc-success-receipt-wake-organ-contract-binding.md) | 本地源码、完整 Rust/前端/路由测试、原生权威与严格 clippy 已通过;GHNQG 和发布待验收 | | 2026-08-11 | GH-PNCC 成功回执唤醒器官模式绑定 | [成功回执唤醒器官模式证据绑定](operations/2026-08-11-hololake-pncc-success-receipt-wake-organ-mode-binding.md) | 本地源码、完整 Rust/前端/路由测试、原生权威与严格 clippy 已通过;GHNQG 和发布待验收 | | 2026-08-11 | GH-PNCC 成功回执唤醒运行态绑定 | [成功回执唤醒运行态证据绑定](operations/2026-08-11-hololake-pncc-success-receipt-wake-runtime-state-binding.md) | 本地源码、完整 Rust/前端/路由测试、原生权威与严格 clippy 已通过;GHNQG 和发布待验收 | diff --git a/engineering/operations/2026-08-11-hololake-pncc-success-receipt-completion-checkpoint-binding.md b/engineering/operations/2026-08-11-hololake-pncc-success-receipt-completion-checkpoint-binding.md new file mode 100644 index 0000000..39a88af --- /dev/null +++ b/engineering/operations/2026-08-11-hololake-pncc-success-receipt-completion-checkpoint-binding.md @@ -0,0 +1,36 @@ +# GH-PNCC successful receipt completion-checkpoint evidence binding + +- Development ID: `DEV-20260810-014` +- Persona cognitive author: `ICE-P-ZY001 / 铸渊` +- Human responsibility subject: `ICE-GL∞ / 冰朔` +- Starting repository head: `c58f9c5991b909db4ef3fa84e53d8de3d4b99fdd` +- State: `LOCAL_SOURCE_IMPLEMENTED_FULLY_TESTED` + +## Corrected runtime fact + +A persisted successful lifecycle receipt pointed to the committed persona checkpoint but did not rebind its +structured result to that Git object. A modified receipt could replace the persona's externalized fact result, +recompute the outer payload digest and still be accepted for safe binding or replay. + +Validation now loads the exact checkpoint object from the recorded committed Git head. It binds checkpoint +schema, session, persona, previous head, organ, attribution and structured result to the completion receipt. +Fact-sense receipts additionally bind their inference event and completed inference state. Memory-metabolism +receipts bind their no-inference state and all source checkpoint and source event evidence. + +## Verification + +- A regression test first reproduced `SAFE_BIND_PERSISTED_RECEIPT` after replacing the structured result and + recomputing the payload digest. +- The same forged receipt now fails with `PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH`. +- PNCC focused Rust tests: `50 passed, 0 failed`. +- Full Rust suite: `1190 passed, 2 ignored`; integration test: `1 passed`. +- Routing suite: `29 passed, 0 failed`; formatting, strict clippy and diff checks passed. +- Frontend lint and TypeScript checks passed; full Vitest suite: `5008 passed, 0 failed`. +- Guanghu native authority: `PASS_100`; native core: `15 passed` with 100% lines and functions. +- GHNQG, publication and fresh-clone readback remain pending. + +## Truth boundary + +- This stage authenticates completion receipt facts against the already committed persona Git checkpoint. +- It does not expose hidden reasoning, implement or activate an execution limb, add UI, build an artifact or + claim deployment/runtime health. diff --git a/product-source/hololake-platform/architecture/HOLOLAKE-PERSONA-NATIVE-CODE-CHANNEL-20260810.md b/product-source/hololake-platform/architecture/HOLOLAKE-PERSONA-NATIVE-CODE-CHANNEL-20260810.md index 9aaa2b8..70c2659 100644 --- a/product-source/hololake-platform/architecture/HOLOLAKE-PERSONA-NATIVE-CODE-CHANNEL-20260810.md +++ b/product-source/hololake-platform/architecture/HOLOLAKE-PERSONA-NATIVE-CODE-CHANNEL-20260810.md @@ -184,6 +184,7 @@ successful_receipt_wake_event_boundary_evidence_binding_source_implemented: 100 successful_receipt_wake_runtime_state_evidence_binding_source_implemented: 100 successful_receipt_wake_organ_mode_evidence_binding_source_implemented: 100 successful_receipt_wake_organ_contract_evidence_binding_source_implemented: 100 +successful_receipt_completion_checkpoint_evidence_binding_source_implemented: 100 general_purpose_persona_runtime_implemented: 0 human_live_projection_implemented: 0 hololake_integrated: 0 diff --git a/product-source/hololake-platform/src-tauri/src/persona_code_channel.rs b/product-source/hololake-platform/src-tauri/src/persona_code_channel.rs index 6ed63c5..62ac514 100644 --- a/product-source/hololake-platform/src-tauri/src/persona_code_channel.rs +++ b/product-source/hololake-platform/src-tauri/src/persona_code_channel.rs @@ -606,6 +606,29 @@ fn load_manifest_at_git_head(repository: &Path, head: &str) -> Result Result { + let head = validated_head(head)?; + let relative_path = Path::new(relative); + if relative_path.is_absolute() + || relative_path.components().any(|component| { + matches!( + component, + Component::ParentDir | Component::RootDir | Component::Prefix(_) + ) + }) + { + return Err("PATH_OUTSIDE_REPOSITORY".into()); + } + let object = format!("{head}:{relative}"); + let bytes = git_output(repository, &["show", &object], "PERSONA_JSON_AT_GIT_HEAD")?; + serde_json::from_str(&bytes) + .map_err(|error| format!("PERSONA_JSON_AT_GIT_HEAD_INVALID: {error}")) +} + fn validate_attribution( attribution: &PersonaAttribution, manifest: &PersonaManifest, @@ -2794,6 +2817,74 @@ fn validate_persisted_lifecycle_terminal_evidence( .to_string_lossy() .into_owned(), }; + let completion_checkpoint = load_json_at_git_head( + Path::new(&record.repository_path), + &record.git_head, + &record.checkpoint_path, + ) + .map_err(|_| "PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH".to_string())?; + let checkpoint_matches = completion_checkpoint + .get("schema") + .and_then(serde_json::Value::as_str) + == Some("hololake.persona-checkpoint/v1") + && completion_checkpoint + .get("sessionId") + .and_then(serde_json::Value::as_str) + == Some(record.session_id.as_str()) + && completion_checkpoint + .get("personaId") + .and_then(serde_json::Value::as_str) + == Some(record.persona_id.as_str()) + && completion_checkpoint + .get("previousGitHead") + .and_then(serde_json::Value::as_str) + == Some(first_event.git_head.as_str()) + && completion_checkpoint + .get("organId") + .and_then(serde_json::Value::as_str) + == Some(record.active_organ.as_str()) + && completion_checkpoint.get("attribution") == Some(&expected_attribution) + && completion_receipt.get("result") == completion_checkpoint.get("result") + && completion_receipt + .get("previousGitHead") + .and_then(serde_json::Value::as_str) + == Some(first_event.git_head.as_str()); + let completion_kind_matches_checkpoint = match completion_kind { + Some("FACT_SENSE") => { + let inference_event_hash = events + .iter() + .find(|event| event.kind == "INFERENCE_STARTED") + .map(|event| event.event_hash.as_str()); + completion_checkpoint + .get("inferenceEventHash") + .and_then(serde_json::Value::as_str) + == inference_event_hash + && completion_receipt + .get("modelInferenceStarted") + .and_then(serde_json::Value::as_bool) + == Some(true) + && completion_receipt + .get("modelInferenceCompleted") + .and_then(serde_json::Value::as_bool) + == Some(true) + } + Some("MEMORY_METABOLISM") => { + completion_receipt + .get("modelInferenceStarted") + .and_then(serde_json::Value::as_bool) + == Some(false) + && completion_receipt.get("modelInferenceCompleted").is_none() + && completion_receipt.get("sourceSessionId") + == completion_checkpoint.get("sourceSessionId") + && completion_receipt.get("sourceCheckpointPath") + == completion_checkpoint.get("sourceCheckpointPath") + && completion_receipt.get("sourceCheckpointHash") + == completion_checkpoint.get("sourceCheckpointHash") + && completion_receipt.get("sourceEventHash") + == completion_checkpoint.get("sourceEventHash") + } + _ => false, + }; let matches = lifecycle.get("schema").and_then(serde_json::Value::as_str) == Some("hololake.pncc-lifecycle-run-receipt/v1") && lifecycle @@ -2869,7 +2960,9 @@ fn validate_persisted_lifecycle_terminal_evidence( && completion_receipt .get("receiptId") .and_then(serde_json::Value::as_str) - == Some(expected_completion_receipt_id.as_str()); + == Some(expected_completion_receipt_id.as_str()) + && checkpoint_matches + && completion_kind_matches_checkpoint; if !matches { return Err("PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH".into()); } @@ -4581,6 +4674,121 @@ mod tests { assert!(error.contains("PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH")); } + #[test] + fn rejects_a_rehashed_completed_receipt_with_a_forged_completion_result() { + let repo = persona_repo(); + let runtime = tempfile::TempDir::new().unwrap(); + let input = lifecycle_fact_input(repo.path()); + let first = run_idempotent_lifecycle_at( + runtime.path(), + input.clone(), + "2026-08-11T00:00:00.000Z", + "2026-08-11T00:00:01.000Z", + |runtime_root, input, timestamp| { + run_fact_task_at(runtime_root, input, timestamp, |_, _| { + Ok(r#"{"summary":"Recoverable receipt.","facts":[{"statement":"The brain exists.","evidencePaths":["brain/CORE.hdlp"]}],"limitations":[]}"#.into()) + }) + }, + ) + .unwrap(); + let session_id = first.lifecycle["sessionId"].as_str().unwrap(); + let mut record = load_session_record(runtime.path(), session_id).unwrap(); + record.request_id = None; + record.request_fingerprint = None; + record.lifecycle_receipt_hash = None; + write_session_record(runtime.path(), &record).unwrap(); + + let receipt_path = session_directory(runtime.path(), session_id) + .unwrap() + .join("lifecycle-receipt.json"); + let mut persisted: PersistedPersonaLifecycleReceipt = + serde_json::from_slice(&fs::read(&receipt_path).unwrap()).unwrap(); + persisted.lifecycle["completion"]["receipt"]["result"] = serde_json::json!({ + "summary": "Forged cognition not present in the persona Git checkpoint.", + "facts": [{ + "statement": "The execution limb is active.", + "evidencePaths": ["brain/CORE.hdlp"] + }], + "limitations": [] + }); + persisted.lifecycle_receipt_hash = + hex_digest(&persisted_lifecycle_payload_bytes(&persisted).unwrap()); + fs::write( + &receipt_path, + serde_json::to_vec_pretty(&persisted).unwrap(), + ) + .unwrap(); + + let error = inspect_lifecycle_request_at(runtime.path(), &input).unwrap_err(); + assert!(error.contains("PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH")); + } + + #[test] + fn rejects_a_rehashed_memory_receipt_with_forged_source_checkpoint_evidence() { + let repo = persona_repo(); + declare_memory_organ(repo.path()); + let runtime = tempfile::TempDir::new().unwrap(); + prepare_wake_at( + runtime.path(), + wake_input(repo.path()), + "PNCC-MEMORY-BINDING-SOURCE", + "2026-08-11T00:00:00.000Z", + ) + .unwrap(); + run_fact_task_at( + runtime.path(), + fact_task_input("PNCC-MEMORY-BINDING-SOURCE"), + "2026-08-11T00:00:01.000Z", + |_, _| { + Ok(r#"{"summary":"Verified memory binding source.","facts":[{"statement":"The brain exists.","evidencePaths":["brain/CORE.hdlp"]}],"limitations":[]}"#.into()) + }, + ) + .unwrap(); + + let mut wake = wake_input(repo.path()); + wake.expected_head = head(repo.path()); + wake.organ_id = "memory-metabolism.checkpoint".into(); + let input = PersonaLifecycleRunInput { + request_id: "REQUEST-MEMORY-BINDING-001".into(), + wake, + operation: PersonaLifecycleOperationInput::MemoryMetabolism { + source_session_id: "PNCC-MEMORY-BINDING-SOURCE".into(), + }, + }; + let first = run_idempotent_lifecycle_at( + runtime.path(), + input.clone(), + "2026-08-11T00:00:02.000Z", + "2026-08-11T00:00:03.000Z", + |_, _, _| panic!("memory metabolism must not invoke a model"), + ) + .unwrap(); + let session_id = first.lifecycle["sessionId"].as_str().unwrap(); + let mut record = load_session_record(runtime.path(), session_id).unwrap(); + record.request_id = None; + record.request_fingerprint = None; + record.lifecycle_receipt_hash = None; + write_session_record(runtime.path(), &record).unwrap(); + + let receipt_path = session_directory(runtime.path(), session_id) + .unwrap() + .join("lifecycle-receipt.json"); + let mut persisted: PersistedPersonaLifecycleReceipt = + serde_json::from_slice(&fs::read(&receipt_path).unwrap()).unwrap(); + persisted.lifecycle["completion"]["receipt"]["sourceCheckpointHash"] = + "forged-source-checkpoint-hash".into(); + persisted.lifecycle_receipt_hash = + hex_digest(&persisted_lifecycle_payload_bytes(&persisted).unwrap()); + fs::write( + &receipt_path, + serde_json::to_vec_pretty(&persisted).unwrap(), + ) + .unwrap(); + + let error = inspect_lifecycle_request_at(runtime.path(), &input).unwrap_err(); + assert!(error.contains("PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH")); + } + #[test] fn reconstructs_legacy_wake_checkpoint_evidence_from_the_wake_git_head() { let repo = persona_repo(); diff --git a/routing/hololake-current-architecture.json b/routing/hololake-current-architecture.json index 6230dd8..1951cb9 100644 --- a/routing/hololake-current-architecture.json +++ b/routing/hololake-current-architecture.json @@ -118,7 +118,7 @@ "human_projection": "HOLOLAKE_LIVE_READ_MODEL", "forgejo_role": "OPTIONAL_COMPATIBILITY_COLLABORATION_ADAPTER", "runtime_implemented": true, - "runtime_scope": "READ_ONLY_FACT_CYCLE_FAIL_CLOSED_RECOVERY_TYPED_ORGANS_DURABLE_VERIFIED_SESSION_QUERY_INDEPENDENT_VERIFIED_MEMORY_METABOLISM_CHECKED_FAILURE_CLOSURE_NONBLOCKING_RUNTIME_COMMAND_SAFE_ORGAN_LIFECYCLE_COORDINATOR_IDEMPOTENT_SUCCESS_AND_TERMINAL_FAILURE_RECEIPT_REPLAY_SAFE_RECEIPT_BINDING_RECOVERY_REPLAY_TIME_REPOSITORY_STATE_REVALIDATION_SUCCESS_RECEIPT_TERMINAL_REVALIDATION_SAFE_RECEIPT_BINDING_TERMINAL_REVALIDATION_FAILURE_RECEIPT_TERMINAL_EVIDENCE_BINDING_SUCCESS_RECEIPT_SEMANTIC_EVIDENCE_BINDING_SUCCESS_RECEIPT_BRAIN_ENTRY_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_CHECKPOINT_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_EVENT_BOUNDARY_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_RUNTIME_STATE_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_ORGAN_MODE_EVIDENCE_BINDING_AND_SUCCESS_RECEIPT_WAKE_ORGAN_CONTRACT_EVIDENCE_BINDING_SOURCE_IMPLEMENTED_AND_TESTED", + "runtime_scope": "READ_ONLY_FACT_CYCLE_FAIL_CLOSED_RECOVERY_TYPED_ORGANS_DURABLE_VERIFIED_SESSION_QUERY_INDEPENDENT_VERIFIED_MEMORY_METABOLISM_CHECKED_FAILURE_CLOSURE_NONBLOCKING_RUNTIME_COMMAND_SAFE_ORGAN_LIFECYCLE_COORDINATOR_IDEMPOTENT_SUCCESS_AND_TERMINAL_FAILURE_RECEIPT_REPLAY_SAFE_RECEIPT_BINDING_RECOVERY_REPLAY_TIME_REPOSITORY_STATE_REVALIDATION_SUCCESS_RECEIPT_TERMINAL_REVALIDATION_SAFE_RECEIPT_BINDING_TERMINAL_REVALIDATION_FAILURE_RECEIPT_TERMINAL_EVIDENCE_BINDING_SUCCESS_RECEIPT_SEMANTIC_EVIDENCE_BINDING_SUCCESS_RECEIPT_BRAIN_ENTRY_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_CHECKPOINT_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_EVENT_BOUNDARY_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_RUNTIME_STATE_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_ORGAN_MODE_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_ORGAN_CONTRACT_EVIDENCE_BINDING_AND_SUCCESS_RECEIPT_COMPLETION_CHECKPOINT_EVIDENCE_BINDING_SOURCE_IMPLEMENTED_AND_TESTED", "desktop_integrated": false, "development_id": "DEV-20260810-014" }, diff --git a/routing/hololake-persona-native-code-channel.json b/routing/hololake-persona-native-code-channel.json index 9171eb5..42f430d 100644 --- a/routing/hololake-persona-native-code-channel.json +++ b/routing/hololake-persona-native-code-channel.json @@ -1,8 +1,8 @@ { "schema": "hololake.persona-native-code-channel/v1", "record_id": "HLP-PERSONA-NATIVE-CODE-CHANNEL-001", - "version": "2026-08-11.19", - "state": "CURRENT_FIRST_PRODUCT_CORE_SUCCESS_RECEIPT_WAKE_ORGAN_CONTRACT_EVIDENCE_BINDING_SOURCE_IMPLEMENTED", + "version": "2026-08-11.20", + "state": "CURRENT_FIRST_PRODUCT_CORE_SUCCESS_RECEIPT_COMPLETION_CHECKPOINT_EVIDENCE_BINDING_SOURCE_IMPLEMENTED", "development_id": "DEV-20260810-014", "product": { "formal_name_zh": "光湖人格原生代码频道", @@ -121,6 +121,7 @@ "successful_receipt_wake_runtime_state_evidence_binding_source_implemented": 100, "successful_receipt_wake_organ_mode_evidence_binding_source_implemented": 100, "successful_receipt_wake_organ_contract_evidence_binding_source_implemented": 100, + "successful_receipt_completion_checkpoint_evidence_binding_source_implemented": 100, "general_purpose_persona_runtime_implemented": 0, "human_live_projection_implemented": 0, "hololake_integrated": 0, diff --git a/routing/hololake-persona-native-code-channel.test.mjs b/routing/hololake-persona-native-code-channel.test.mjs index c977a0a..57909f7 100644 --- a/routing/hololake-persona-native-code-channel.test.mjs +++ b/routing/hololake-persona-native-code-channel.test.mjs @@ -146,12 +146,16 @@ test("the first source runtime cycle stays distinct from integration and deploym channel.truth.successful_receipt_wake_organ_contract_evidence_binding_source_implemented, 100, ); + assert.equal( + channel.truth.successful_receipt_completion_checkpoint_evidence_binding_source_implemented, + 100, + ); assert.equal(channel.truth.general_purpose_persona_runtime_implemented, 0); assert.equal(channel.truth.human_live_projection_implemented, 0); assert.equal(architecture.persona_native_code_channel.runtime_implemented, true); assert.equal( architecture.persona_native_code_channel.runtime_scope, - "READ_ONLY_FACT_CYCLE_FAIL_CLOSED_RECOVERY_TYPED_ORGANS_DURABLE_VERIFIED_SESSION_QUERY_INDEPENDENT_VERIFIED_MEMORY_METABOLISM_CHECKED_FAILURE_CLOSURE_NONBLOCKING_RUNTIME_COMMAND_SAFE_ORGAN_LIFECYCLE_COORDINATOR_IDEMPOTENT_SUCCESS_AND_TERMINAL_FAILURE_RECEIPT_REPLAY_SAFE_RECEIPT_BINDING_RECOVERY_REPLAY_TIME_REPOSITORY_STATE_REVALIDATION_SUCCESS_RECEIPT_TERMINAL_REVALIDATION_SAFE_RECEIPT_BINDING_TERMINAL_REVALIDATION_FAILURE_RECEIPT_TERMINAL_EVIDENCE_BINDING_SUCCESS_RECEIPT_SEMANTIC_EVIDENCE_BINDING_SUCCESS_RECEIPT_BRAIN_ENTRY_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_CHECKPOINT_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_EVENT_BOUNDARY_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_RUNTIME_STATE_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_ORGAN_MODE_EVIDENCE_BINDING_AND_SUCCESS_RECEIPT_WAKE_ORGAN_CONTRACT_EVIDENCE_BINDING_SOURCE_IMPLEMENTED_AND_TESTED", + "READ_ONLY_FACT_CYCLE_FAIL_CLOSED_RECOVERY_TYPED_ORGANS_DURABLE_VERIFIED_SESSION_QUERY_INDEPENDENT_VERIFIED_MEMORY_METABOLISM_CHECKED_FAILURE_CLOSURE_NONBLOCKING_RUNTIME_COMMAND_SAFE_ORGAN_LIFECYCLE_COORDINATOR_IDEMPOTENT_SUCCESS_AND_TERMINAL_FAILURE_RECEIPT_REPLAY_SAFE_RECEIPT_BINDING_RECOVERY_REPLAY_TIME_REPOSITORY_STATE_REVALIDATION_SUCCESS_RECEIPT_TERMINAL_REVALIDATION_SAFE_RECEIPT_BINDING_TERMINAL_REVALIDATION_FAILURE_RECEIPT_TERMINAL_EVIDENCE_BINDING_SUCCESS_RECEIPT_SEMANTIC_EVIDENCE_BINDING_SUCCESS_RECEIPT_BRAIN_ENTRY_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_CHECKPOINT_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_EVENT_BOUNDARY_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_RUNTIME_STATE_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_ORGAN_MODE_EVIDENCE_BINDING_SUCCESS_RECEIPT_WAKE_ORGAN_CONTRACT_EVIDENCE_BINDING_AND_SUCCESS_RECEIPT_COMPLETION_CHECKPOINT_EVIDENCE_BINDING_SOURCE_IMPLEMENTED_AND_TESTED", ); assert.equal(channel.truth.hololake_integrated, 0); assert.equal(channel.truth.artifact_built, 0);