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:
parent
1cd8a1b489
commit
30d179e97a
7 changed files with 107 additions and 6 deletions
|
|
@ -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 1cd8a1b;GHNQG、全新克隆与严格读回通过 |
|
||||
| 2026-08-11 | GH-PNCC 成功回执完成检查点绑定 | [把完成回执的结构化事实重新绑定到人格 Git 检查点](operations/2026-08-11-hololake-pncc-success-receipt-completion-checkpoint-binding.md) | 已发布至 REPO-014 main 06a7782;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 和发布待验收 |
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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 提交、检查点、回执编号和完整事件链重新绑定到已验证的会话记录。同步改写载荷与哈希不能
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue