From 36bc00cc3feec5009c31529424f3baa080125111 Mon Sep 17 00:00:00 2001 From: Eve Date: Fri, 8 May 2026 12:16:15 +0800 Subject: [PATCH] reporting-governance: document single-notice settlement guardrail --- .../reporting-governance-adapter-interface.md | 10 ++++ plugins/reporting-governance/README.md | 14 ++++++ .../runtime-integrated.integration.test.mjs | 46 +++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/docs/specs/reporting-governance-adapter-interface.md b/docs/specs/reporting-governance-adapter-interface.md index de28f9c..2a87324 100644 --- a/docs/specs/reporting-governance-adapter-interface.md +++ b/docs/specs/reporting-governance-adapter-interface.md @@ -651,11 +651,21 @@ Examples: Verify orchestrated chain behavior. +For the **current runtime contract**, treat the reference chain as a **single notice settlement path**, not a generalized multi-notice aggregation framework. +That means: + +- the runtime may promote overall truth state to `acked` only when the observed terminal set for that one notice path is fully acked +- `acked + pending` must remain non-`acked` +- `acked + blocked` must remain non-`acked` +- any future multi-notice aggregation semantics must be introduced as a separate contract slice, not inferred from this one + For example: - runner -> queue -> dispatcher -> bridge -> sender -> `acked` - runner -> queue -> dispatcher -> bridge -> `pending_external_send` - runner -> queue -> dispatcher -> bridge -> `blocked` +- mixed observed outcomes `acked + pending` -> overall state must **not** promote to `acked` +- mixed observed outcomes `acked + blocked` -> overall state must **not** promote to `acked` ## Roadmap impact diff --git a/plugins/reporting-governance/README.md b/plugins/reporting-governance/README.md index 63034bf..5507243 100644 --- a/plugins/reporting-governance/README.md +++ b/plugins/reporting-governance/README.md @@ -224,9 +224,23 @@ This slice now has one small but testable contract path: - truthful delivery / receipt state - runtime execution result when explicitly requested +Current runtime contract in this repo is intentionally narrower than a future generalized aggregation model: + +- **single notice settlement path only** +- one governance-triggered operator notice route is evaluated as one truth boundary +- overall truth state may promote to `acked` only when the observed terminal outcome set for that single path is fully acked +- mixed observed outcomes such as `acked + pending` or `acked + blocked` must stay non-`acked` +- this slice does **not** yet claim generalized multi-notice aggregation, fan-in settlement, or cross-notice quorum semantics + This is intentionally **planning-level end-to-end plus one adapter bootstrap layer**, not full live inline interception. It proves contract alignment without pretending all runtime enforcement is already extracted. +What this means for implementers right now: + +- treat `dispatched` / `pending_external_send` / `blocked` as honest end states unless the single notice path reaches sender-backed ack proof +- do not collapse partial success into overall `acked` +- if future work introduces multiple notice paths, that must land as a separate runtime-contract slice with its own tests + ## Not yet included This package still does **not** claim full implementation of: diff --git a/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs b/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs index ff1e693..390551a 100644 --- a/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs +++ b/plugins/reporting-governance/test/runtime-integrated.integration.test.mjs @@ -282,6 +282,52 @@ test('truth-state promotion guardrail: mixed terminal outcomes must not promote }), false); }); +test('runtime-integrated mixed outcome: acked + pending keeps overall truth state non-acked', () => { + const governance = executeRuntimeIntegratedGovernance(createBaseArgs()); + + const promoted = runtimeIntegratedTestables.promoteTruthStateFromRuntime(governance, { + attempted: true, + runtimeExecution: { + result: { + supervisor: { + ackedCount: 1, + pendingCount: 1, + blockedCount: 0, + }, + }, + }, + }); + + assert.equal(promoted.contract.delivery_state, 'pending_external_send'); + assert.equal(promoted.contract.receipt_status, 'planned'); + assert.equal(promoted.planning.receipt.delivery_state, 'pending_external_send'); + assert.equal(promoted.planning.receipt.status, 'planned'); + assertNoAckedOrFinalDeliveredClaim(promoted); +}); + +test('runtime-integrated mixed outcome: acked + blocked keeps overall truth state non-acked', () => { + const governance = executeRuntimeIntegratedGovernance(createBaseArgs()); + + const promoted = runtimeIntegratedTestables.promoteTruthStateFromRuntime(governance, { + attempted: true, + runtimeExecution: { + result: { + supervisor: { + ackedCount: 1, + pendingCount: 0, + blockedCount: 1, + }, + }, + }, + }); + + assert.equal(promoted.contract.delivery_state, 'pending_external_send'); + assert.equal(promoted.contract.receipt_status, 'planned'); + assert.equal(promoted.planning.receipt.delivery_state, 'pending_external_send'); + assert.equal(promoted.planning.receipt.status, 'planned'); + assertNoAckedOrFinalDeliveredClaim(promoted); +}); + test('truth-state promotion guardrail: only fully acked observed terminal set may promote to acked', () => { assert.equal(runtimeIntegratedTestables.canPromoteAckedFromSupervisor({ ackedCount: 0,