fix: bind failure receipt error code

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 09:41:52 +08:00
commit 30d179e97a
7 changed files with 107 additions and 6 deletions

View file

@ -32,7 +32,8 @@ Windows / macOS / Linux 构建机与安装包
| 时间 | 版本 | 记录 | 状态 |
| --- | --- | --- | --- |
| 2026-08-11 | GH-PNCC 成功回执事件日志绑定 | [把唤醒回执的日志路径重新绑定到精确运行时会话](operations/2026-08-11-hololake-pncc-success-receipt-event-journal-binding.md) | 本地源码、Rust 1191、聚焦路由、格式与严格 clippy 已通过;完整产品门和发布待验收 |
| 2026-08-11 | GH-PNCC 失败回执错误码绑定 | [把稳定失败码绑定到终态会话证据](operations/2026-08-11-hololake-pncc-failure-receipt-error-code-binding.md) | 本地源码、Rust 1192、路由 29、格式与严格 clippy 已通过;完整产品门和发布待验收 |
| 2026-08-11 | GH-PNCC 成功回执事件日志绑定 | [把唤醒回执的日志路径重新绑定到精确运行时会话](operations/2026-08-11-hololake-pncc-success-receipt-event-journal-binding.md) | 已发布至 REPO-014 main 1cd8a1bGHNQG、全新克隆与严格读回通过 |
| 2026-08-11 | GH-PNCC 成功回执完成检查点绑定 | [把完成回执的结构化事实重新绑定到人格 Git 检查点](operations/2026-08-11-hololake-pncc-success-receipt-completion-checkpoint-binding.md) | 已发布至 REPO-014 main 06a7782GHNQG、全新克隆与严格读回通过 |
| 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 和发布待验收 |

View file

@ -0,0 +1,33 @@
# GH-PNCC failure receipt error-code evidence binding
- Development ID: `DEV-20260810-014`
- Persona cognitive author: `ICE-P-ZY001 / 铸渊`
- Human responsibility subject: `ICE-GL∞ / 冰朔`
- Starting repository head: `1cd8a1b48951775530143c61a3af2d11215d4921`
- State: `LOCAL_SOURCE_IMPLEMENTED_FOCUSED_TESTED`
## Corrected runtime fact
Failure receipt validation bound repository, terminal event and attribution, but only checked that `errorCode`
looked like a stable machine code. A modified receipt could replace the real failure with another syntactically
valid code, recompute the outer payload digest and still be accepted for safe binding or replay.
The runtime now records the normalized terminal failure code in the same verified session record before writing
the immutable failure receipt. Receipt persistence, inspection, recovery binding, replay and post-inspection
binding revalidation require the receipt code to equal that exact session-bound value.
## Verification
- A regression test first reproduced `SAFE_BIND_PERSISTED_RECEIPT` after changing the real inference failure to
`AUTHORIZATION_GRANTED` and recomputing the payload digest.
- The same forged receipt now fails with `PERSONA_LIFECYCLE_FAILURE_TERMINAL_EVIDENCE_MISMATCH`.
- PNCC focused Rust tests: `52 passed, 0 failed`, including interrupted failure-receipt recovery.
- Full Rust suite: `1192 passed, 2 ignored`; integration test: `1 passed`.
- Routing suite: `29 passed`; formatting, strict clippy and diff checks passed.
- Full product quality, publication and fresh-clone readback remain pending.
## Truth boundary
- This stage binds the already externalized stable failure code; raw provider details remain excluded.
- It does not expose hidden reasoning, activate an execution limb, add UI, build an artifact or claim
deployment/runtime health.

View file

@ -186,6 +186,7 @@ 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
successful_receipt_event_journal_evidence_binding_source_implemented: 100
failure_receipt_error_code_evidence_binding_source_implemented: 100
general_purpose_persona_runtime_implemented: 0
human_live_projection_implemented: 0
hololake_integrated: 0
@ -213,6 +214,10 @@ runtime_health: 0
事件链。即使有人同步重算回执哈希,伪造终态事件或人格作者也会失败关闭,且不会把请求字段
写入会话记录。
失败回执中的稳定错误码也不能只通过字符格式自证。终态关闭后,运行时先把规范化错误码写入同一
会话记录,再持久化失败回执;检查、恢复绑定、重放和绑定前复核都要求两者精确一致。即使同步
重算外层哈希,也不能把真实失败改写成另一个合法机器码或虚构的成功授权状态。
成功回执同样不能把“载荷哈希一致”当成语义真实。首次落盘、检查、恢复绑定和重放现在会把
生命周期 schema、规范仓库、唤醒身份、节点、模型实例、器官、完整双层归因、完成类型、最终
Git 提交、检查点、回执编号和完整事件链重新绑定到已验证的会话记录。同步改写载荷与哈希不能

View file

@ -445,6 +445,8 @@ struct PersonaSessionRecord {
attribution: PersonaAttribution,
state: String,
#[serde(default)]
terminal_failure_code: Option<String>,
#[serde(default)]
request_id: Option<String>,
#[serde(default)]
request_fingerprint: Option<String>,
@ -1347,6 +1349,7 @@ fn prepare_wake_at(
fact_source_paths: organ.paths.clone(),
attribution: input.attribution.clone(),
state: "BOUND_NOT_INFERENCING".into(),
terminal_failure_code: None,
request_id: None,
request_fingerprint: None,
lifecycle_receipt_hash: None,
@ -2722,6 +2725,7 @@ fn validate_persisted_lifecycle_terminal_evidence(
if failure.repository_path != record.repository_path
|| failure.terminal_event_hash != terminal_event.event_hash
|| failure.attribution != record.attribution
|| record.terminal_failure_code.as_deref() != Some(failure.error_code.as_str())
|| lifecycle_failure_code(&failure.error_code) != failure.error_code
{
return Err("PERSONA_LIFECYCLE_FAILURE_TERMINAL_EVIDENCE_MISMATCH".into());
@ -3308,12 +3312,23 @@ fn persist_terminal_lifecycle_failure(
{
return Err("PERSONA_LIFECYCLE_FAILURE_BINDING_ALREADY_PRESENT".into());
}
let error_code = lifecycle_failure_code(error);
match record.terminal_failure_code.as_deref() {
Some(recorded) if recorded != error_code => {
return Err("PERSONA_LIFECYCLE_FAILURE_CODE_ALREADY_BOUND".into());
}
Some(_) => {}
None => {
record.terminal_failure_code = Some(error_code.clone());
write_session_record(runtime_root, &record)?;
}
}
let failure = PersonaLifecycleFailureReceipt {
schema: "hololake.pncc-lifecycle-failure-receipt/v1".into(),
session_id: session_id.into(),
persona_id: record.persona_id.clone(),
repository_path: record.repository_path.clone(),
error_code: lifecycle_failure_code(error),
error_code,
terminal_event_hash: terminal_event.event_hash.clone(),
attribution: record.attribution.clone(),
};
@ -5350,6 +5365,48 @@ mod tests {
assert!(record.lifecycle_receipt_hash.is_none());
}
#[test]
fn rejects_a_rehashed_failure_receipt_with_a_forged_error_code() {
let repo = persona_repo();
let runtime = tempfile::TempDir::new().unwrap();
let input = lifecycle_fact_input(repo.path());
let failed = 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, |_, _| {
Err("bounded provider failure".into())
})
},
)
.unwrap();
let session_id = failed.failure.as_ref().unwrap().session_id.clone();
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.failure.as_mut().unwrap().error_code = "AUTHORIZATION_GRANTED".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_FAILURE_TERMINAL_EVIDENCE_MISMATCH"));
}
#[test]
fn refuses_to_bind_rehashed_failure_evidence_changed_after_inspection() {
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_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_SUCCESS_RECEIPT_COMPLETION_CHECKPOINT_EVIDENCE_BINDING_AND_SUCCESS_RECEIPT_EVENT_JOURNAL_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_SUCCESS_RECEIPT_COMPLETION_CHECKPOINT_EVIDENCE_BINDING_SUCCESS_RECEIPT_EVENT_JOURNAL_EVIDENCE_BINDING_AND_FAILURE_RECEIPT_ERROR_CODE_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.21",
"state": "CURRENT_FIRST_PRODUCT_CORE_SUCCESS_RECEIPT_EVENT_JOURNAL_EVIDENCE_BINDING_SOURCE_IMPLEMENTED",
"version": "2026-08-11.22",
"state": "CURRENT_FIRST_PRODUCT_CORE_FAILURE_RECEIPT_ERROR_CODE_EVIDENCE_BINDING_SOURCE_IMPLEMENTED",
"development_id": "DEV-20260810-014",
"product": {
"formal_name_zh": "光湖人格原生代码频道",
@ -123,6 +123,7 @@
"successful_receipt_wake_organ_contract_evidence_binding_source_implemented": 100,
"successful_receipt_completion_checkpoint_evidence_binding_source_implemented": 100,
"successful_receipt_event_journal_evidence_binding_source_implemented": 100,
"failure_receipt_error_code_evidence_binding_source_implemented": 100,
"general_purpose_persona_runtime_implemented": 0,
"human_live_projection_implemented": 0,
"hololake_integrated": 0,

View file

@ -154,12 +154,16 @@ test("the first source runtime cycle stays distinct from integration and deploym
channel.truth.successful_receipt_event_journal_evidence_binding_source_implemented,
100,
);
assert.equal(
channel.truth.failure_receipt_error_code_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_SUCCESS_RECEIPT_WAKE_ORGAN_CONTRACT_EVIDENCE_BINDING_SUCCESS_RECEIPT_COMPLETION_CHECKPOINT_EVIDENCE_BINDING_AND_SUCCESS_RECEIPT_EVENT_JOURNAL_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_SUCCESS_RECEIPT_COMPLETION_CHECKPOINT_EVIDENCE_BINDING_SUCCESS_RECEIPT_EVENT_JOURNAL_EVIDENCE_BINDING_AND_FAILURE_RECEIPT_ERROR_CODE_EVIDENCE_BINDING_SOURCE_IMPLEMENTED_AND_TESTED",
);
assert.equal(channel.truth.hololake_integrated, 0);
assert.equal(channel.truth.artifact_built, 0);