fix: bind successful receipt wake checkpoint

Human-Responsibility: ICE-GL∞ / 冰朔
Persona-Author: ICE-P-ZY001 / 铸渊
Execution-Runtime: Codex desktop / DEV-20260810-014
Development-ID: DEV-20260810-014
Authorization-Scope: GH-PNCC persona runtime source and tests only; no UI, deployment, or execution limb
Source-Anchor: user instruction to continue GH-PNCC from repository facts and verifiable receipts
This commit is contained in:
铸渊 / ICE-P-ZY001 2026-08-11 07:08:16 +08:00
commit 869611962e
7 changed files with 175 additions and 4 deletions

View file

@ -33,6 +33,7 @@ Windows / macOS / Linux 构建机与安装包
| 时间 | 版本 | 记录 | 状态 |
| --- | --- | --- | --- |
| 2026-08-11 | GH-PNCC 成功回执大脑入口证据绑定 | [从已验证会话重建并核对真实大脑入口](operations/2026-08-11-hololake-pncc-success-receipt-brain-entry-evidence-binding.md) | 本地源码、完整 Rust/前端/路由测试、原生权威与严格 clippy 已通过GHNQG 和发布待验收 |
| 2026-08-11 | GH-PNCC 成功回执唤醒检查点证据绑定 | [把唤醒时检查点路径绑定到不可变会话证据](operations/2026-08-11-hololake-pncc-success-receipt-wake-checkpoint-evidence-binding.md) | 本地源码、完整 Rust/前端/路由测试、原生权威与严格 clippy 已通过GHNQG 和发布待验收 |
| 2026-08-11 | GH-PNCC 安全回执绑定终态复核 | [检查后、绑定前重新验证回执与人格 Git 终态](operations/2026-08-11-hololake-pncc-safe-receipt-binding-terminal-revalidation.md) | 本地源码、完整 Rust/路由测试与严格 clippy 已通过GHNQG 和发布待验收 |
| 2026-08-11 | GH-PNCC 成功回执终态复核 | [成功回执持久化前重新验证终态证据](operations/2026-08-11-hololake-pncc-success-receipt-terminal-revalidation.md) | 本地源码、完整 Rust/路由测试与严格 clippy 已通过GHNQG 和发布待验收 |
| 2026-08-11 | GH-PNCC 重放仓库复核 | [幂等重放时重新验证人格 Git 状态](operations/2026-08-11-hololake-pncc-replay-repository-state-revalidation.md) | 本地源码、完整 Rust/路由测试与严格 clippy 已通过GHNQG 和发布待验收 |

View file

@ -0,0 +1,38 @@
# GH-PNCC successful receipt wake-checkpoint evidence binding
- Development ID: `DEV-20260810-014`
- Persona cognitive author: `ICE-P-ZY001 / 铸渊`
- Human responsibility subject: `ICE-GL∞ / 冰朔`
- Starting repository head: `56303382856de025199e75fdffa57be7507bb418`
- State: `LOCAL_SOURCE_IMPLEMENTED_FULLY_TESTED`
## Corrected runtime fact
The successful lifecycle receipt already rebound the brain entry to the verified session, but the wake
receipt's `checkpointPath` was not independently rebound. A modified receipt could therefore name another
checkpoint path after recomputing its payload digest.
New sessions now retain the exact canonical checkpoint path observed at wake as immutable session evidence.
Inspection, interrupted binding and replay require the persisted wake receipt to name that same path. Legacy
session records without the new field derive it from the persona manifest at the hash-chained wake Git head;
if that evidence cannot be reconstructed, validation fails closed.
## Verification
- A regression test first reproduced acceptance of a forged wake `checkpointPath` after recomputing the
payload digest.
- The same test passes after immutable wake-checkpoint evidence binding was added.
- A compatibility regression proves a legacy session without the new field reconstructs the same evidence from
the hash-chained wake Git head.
- PNCC focused Rust tests: `44 passed, 0 failed`.
- Full Rust suite: `1184 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 which existing checkpoint file was mounted when the persona woke.
- It does not change the promoted completion checkpoint, expose hidden reasoning, activate an execution limb,
add UI, build an artifact or claim deployment.

View file

@ -179,6 +179,7 @@ safe_receipt_binding_terminal_revalidation_source_implemented: 100
failure_receipt_terminal_evidence_binding_source_implemented: 100
successful_receipt_semantic_evidence_binding_source_implemented: 100
successful_receipt_brain_entry_evidence_binding_source_implemented: 100
successful_receipt_wake_checkpoint_evidence_binding_source_implemented: 100
general_purpose_persona_runtime_implemented: 0
human_live_projection_implemented: 0
hololake_integrated: 0

View file

@ -431,6 +431,8 @@ struct PersonaSessionRecord {
repository_path: String,
git_head: String,
brain_entry: String,
#[serde(default)]
wake_checkpoint_path: Option<String>,
checkpoint_path: String,
node_id: String,
model_provider_id: String,
@ -587,6 +589,22 @@ fn load_manifest(repository: &Path) -> Result<PersonaManifest, String> {
Ok(manifest)
}
fn load_manifest_at_git_head(repository: &Path, head: &str) -> Result<PersonaManifest, String> {
let head = validated_head(head)?;
let object = format!("{head}:{MANIFEST_PATH}");
let bytes = git_output(
repository,
&["show", &object],
"PERSONA_MANIFEST_AT_GIT_HEAD",
)?;
let manifest: PersonaManifest = serde_json::from_str(&bytes)
.map_err(|error| format!("PERSONA_MANIFEST_AT_GIT_HEAD_INVALID: {error}"))?;
if manifest.schema != "hololake.persona/v1" {
return Err("PERSONA_MANIFEST_SCHEMA_UNSUPPORTED".into());
}
Ok(manifest)
}
fn validate_attribution(
attribution: &PersonaAttribution,
manifest: &PersonaManifest,
@ -1294,6 +1312,7 @@ fn prepare_wake_at(
repository_path: repository.to_string_lossy().into_owned(),
git_head: git_head.clone(),
brain_entry: manifest.brain_entry.clone(),
wake_checkpoint_path: Some(checkpoint.to_string_lossy().into_owned()),
checkpoint_path: manifest.current_checkpoint.clone(),
node_id: node_id.clone(),
model_provider_id,
@ -2740,6 +2759,26 @@ fn validate_persisted_lifecycle_terminal_evidence(
repository_file(Path::new(&record.repository_path), &record.brain_entry)
.map_err(|_| "PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH".to_string())?;
let expected_brain_entry = expected_brain_entry.to_string_lossy();
let expected_wake_checkpoint = match record.wake_checkpoint_path.as_ref() {
Some(path) => path.clone(),
None => {
let wake_manifest = load_manifest_at_git_head(
Path::new(&record.repository_path),
&first_event.git_head,
)
.map_err(|_| "PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH".to_string())?;
if wake_manifest.persona_id != record.persona_id {
return Err("PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH".into());
}
repository_file(
Path::new(&record.repository_path),
&wake_manifest.current_checkpoint,
)
.map_err(|_| "PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH".to_string())?
.to_string_lossy()
.into_owned()
}
};
let matches = lifecycle.get("schema").and_then(serde_json::Value::as_str)
== Some("hololake.pncc-lifecycle-run-receipt/v1")
&& lifecycle
@ -2760,6 +2799,10 @@ fn validate_persisted_lifecycle_terminal_evidence(
== Some(first_event.git_head.as_str())
&& wake.get("brainEntry").and_then(serde_json::Value::as_str)
== Some(expected_brain_entry.as_ref())
&& wake
.get("checkpointPath")
.and_then(serde_json::Value::as_str)
== Some(expected_wake_checkpoint.as_str())
&& wake.get("nodeId").and_then(serde_json::Value::as_str) == Some(record.node_id.as_str())
&& wake
.get("modelInstanceId")
@ -4293,6 +4336,89 @@ mod tests {
assert!(error.contains("PERSONA_LIFECYCLE_COMPLETION_EVIDENCE_MISMATCH"));
}
#[test]
fn rejects_a_rehashed_completed_receipt_with_a_forged_wake_checkpoint_path() {
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["wakeReceipt"]["checkpointPath"] = "/forged/CURRENT.hdlp".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();
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 session_path = session_directory(runtime.path(), session_id)
.unwrap()
.join("session.json");
let mut legacy_record: serde_json::Value =
serde_json::from_slice(&fs::read(&session_path).unwrap()).unwrap();
legacy_record
.as_object_mut()
.unwrap()
.remove("wakeCheckpointPath");
legacy_record["requestId"] = serde_json::Value::Null;
legacy_record["requestFingerprint"] = serde_json::Value::Null;
legacy_record["lifecycleReceiptHash"] = serde_json::Value::Null;
fs::write(
&session_path,
serde_json::to_vec_pretty(&legacy_record).unwrap(),
)
.unwrap();
let inspection = inspect_lifecycle_request_at(runtime.path(), &input).unwrap();
assert_eq!(inspection.status, "SAFE_BIND_PERSISTED_RECEIPT");
assert!(inspection.safe_to_bind_receipt);
}
#[test]
fn rejects_a_rehashed_completed_receipt_with_a_malformed_wake_event_hash() {
let repo = persona_repo();

View file

@ -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_AND_SUCCESS_RECEIPT_BRAIN_ENTRY_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_AND_SUCCESS_RECEIPT_WAKE_CHECKPOINT_EVIDENCE_BINDING_SOURCE_IMPLEMENTED_AND_TESTED",
"desktop_integrated": false,
"development_id": "DEV-20260810-014"
},

View file

@ -1,8 +1,8 @@
{
"schema": "hololake.persona-native-code-channel/v1",
"record_id": "HLP-PERSONA-NATIVE-CODE-CHANNEL-001",
"version": "2026-08-11.14",
"state": "CURRENT_FIRST_PRODUCT_CORE_SUCCESS_RECEIPT_BRAIN_ENTRY_EVIDENCE_BINDING_SOURCE_IMPLEMENTED",
"version": "2026-08-11.15",
"state": "CURRENT_FIRST_PRODUCT_CORE_SUCCESS_RECEIPT_WAKE_CHECKPOINT_EVIDENCE_BINDING_SOURCE_IMPLEMENTED",
"development_id": "DEV-20260810-014",
"product": {
"formal_name_zh": "光湖人格原生代码频道",
@ -116,6 +116,7 @@
"failure_receipt_terminal_evidence_binding_source_implemented": 100,
"successful_receipt_semantic_evidence_binding_source_implemented": 100,
"successful_receipt_brain_entry_evidence_binding_source_implemented": 100,
"successful_receipt_wake_checkpoint_evidence_binding_source_implemented": 100,
"general_purpose_persona_runtime_implemented": 0,
"human_live_projection_implemented": 0,
"hololake_integrated": 0,

View file

@ -126,12 +126,16 @@ test("the first source runtime cycle stays distinct from integration and deploym
channel.truth.successful_receipt_brain_entry_evidence_binding_source_implemented,
100,
);
assert.equal(
channel.truth.successful_receipt_wake_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_AND_SUCCESS_RECEIPT_BRAIN_ENTRY_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_AND_SUCCESS_RECEIPT_WAKE_CHECKPOINT_EVIDENCE_BINDING_SOURCE_IMPLEMENTED_AND_TESTED",
);
assert.equal(channel.truth.hololake_integrated, 0);
assert.equal(channel.truth.artifact_built, 0);