diff --git a/CHANGELOG.md b/CHANGELOG.md index af91e93..a6d0759 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,11 @@ revision-guarded, atomic and replay-safe. Retained Program-execution generations cannot resurrect a causally deleted session, and Web errors now distinguish stale, absent, invalid and internal failures without exposing - database details. + database details. The private rollout additionally fixed complete-generation + dominance for occurrence equipment companions and made bounded ACK recovery + prioritize recent terminal evidence. Two correlated direct-MTP exchanges, + component restart and exact replay of a retained pre-deletion generation + preserved the single tombstone without duplication or resurrection. - Added the Program execution flow. Android schema v25 can start or resume one Program session through the existing durable singleton, preserves stable diff --git a/docs/current_state.md b/docs/current_state.md index 78b1cac..3d6c8b7 100644 --- a/docs/current_state.md +++ b/docs/current_state.md @@ -83,7 +83,7 @@ parallel implementation of its rules. | Web Sessions deletion and Programs V1 | `TRAINLOG_WEB_SESSIONS_DELETE_AND_PROGRAMS_V1=PASS` (private grouped rollout validated) | | Programs presentation, Android projection, and deletion | `TRAINLOG_PROGRAMS_PRESENTATION_ANDROID_DELETE_V1=PASS` (private coordinated deployment and restart/replay validated) | | Program execution flow | `TRAINLOG_PROGRAM_EXECUTION_FLOW_V1=PASS` (private coordinated deployment, real execution, correlated ACK, restart, replay, and deletion validated) | -| Web history deletion incident | `TRAINLOG_HISTORY_DELETE_HTTP500_FIX_V1=IMPLEMENTED` (Program-origin completed sessions use causal deletion and terminal execution provenance) | +| Web history deletion incident | `TRAINLOG_HISTORY_DELETE_HTTP500_FIX_V1=PASS` (private rollout, correlated full-generation exchanges, restart, retained-generation replay, and non-resurrection validated) | | Sync orchestrator/report V1 | `TRAINLOG_SYNC_ORCHESTRATOR_REPORT_V1=PASS/FROZEN` | | Web sync API V1 | `TRAINLOG_WEB_SYNC_API_V1=PASS/FROZEN` | | Web sync button V1 | `TRAINLOG_WEB_SYNC_BUTTON_V1=PASS/FROZEN` | diff --git a/docs/reviews/history_delete_http500_fix_v1_evidence.md b/docs/reviews/history_delete_http500_fix_v1_evidence.md index 2d5c8ed..6db0786 100644 --- a/docs/reviews/history_delete_http500_fix_v1_evidence.md +++ b/docs/reviews/history_delete_http500_fix_v1_evidence.md @@ -57,3 +57,77 @@ The recovery envelope also republishes both consumed and rejected correlated ACKs. This lets Android close an interrupted generation with the real durable desktop rejection evidence and reclaim normal bounded capacity; no generation, ACK, tombstone or archive is manually purged or synthesized. + +## Controlled private rollout + +The rollout source was advanced through bounded corrective commits to +`a8c50a9512d8754477a2491b73c0f9e0f92263bf`. The coordinated desktop archive is +`trainlog-0.1.2-a8c50a9-desktop-v28.tar.gz`, SHA-256 +`e9e08b317fb97807987b8e027a072cc8235bd9ee6dff7d393df4acb8f04c8a46`. +Android code and schema were unchanged; the installed private application +remained `com.labfytools.trainlog`, versionCode 17, versionName 0.1.2, schema +25. + +Before deployment, the real desktop v27 database was backed up as +`trainlog-desktop-v27.db`, SHA-256 +`ffa4cd5c5fc832b4054ee6543ff89b74be7148b19ffb9af718aa0dfe787ab20a`. +The real Android product backup was +`trainlog-android-v25.tlbackup.zip`, SHA-256 +`8d198dc5fb6ca5c410029342f0e3074d288dac844ce686e3a70782bdad9e8bce`. +A populated copy migration changed only `PRAGMA user_version` from 27 to 28: +all 47 business-table counts and canonical typed hashes were identical, +`integrity_check` was `ok`, and `foreign_key_check` was empty. The production +migration reached the same integrity state. + +The real deletion used the Web HTTP command with the session's current causal +revision. It removed only +`se_6bb66f59-a6fb-4759-a75d-c1a79ea107e8`, created operation +`del_af8a82de-2825-45af-9f62-ec94cc61a556`, and retained exactly one deleted +causal state. Its Program execution provenance moved from `completed` to +terminal `deleted` while preserving the original observation timestamp. The +session detail then returned the bounded absent response and reload did not +restore it. + +The first hardware exchange exposed two real recovery defects before a final +PASS. Generation `gen_42f8d681-373e-4f07-b08d-792a1e8e516d` was rejected +because the live Android snapshot reached the importer after its tombstone; +the subsequent generation `gen_c9d1fda8-8375-4d89-8c29-a5ae120c6c7d` proved +that the equipment-association companion required the same dominance rule. +Later retries reported `peer_capacity_exhausted`: a product backup showed four +older immutable Android generations still waiting for ACK. Their retained +manifests were processed by the production consumer and received genuine +correlated stale-lineage rejection ACKs. The recovery envelope then accepted +that exact terminal evidence. No ACK, tombstone, generation, archive or ledger +row was fabricated, deleted or edited manually. + +The final post-correction exchange completed as run +`sy_b343619f-a1d2-4bea-a0af-c57aa5792aca`: Android generation +`gen_b2290cad-0554-46f9-bc30-0fbd0c8190e8` was consumed with +`sqlite-commit-full`, desktop generation +`gen_21d7efa0-bd97-4843-a0d6-111e94d669b4` was acknowledged, no capability was +missing, and `sessions_reconciled` was zero. The second exchange completed as +run `sy_58b38f82-a70c-48c3-834c-81436c687c8c`, with generations +`gen_65e4833c-5383-4374-b37f-d8add8a106e8` and +`gen_76e15f8a-1258-49f1-ac0e-b04fe9e6a8a5`, again with no missing capability +and zero reconciled sessions. + +After both stores and the Web component were reopened, the Android product +backup `trainlog-android-postrestart-20260919.tlbackup.zip` had SHA-256 +`7ae8f88c60bd44355c19c89e7996d8c71ec178c75aabff0979065a5a70936ed5`, +schema 25, `integrity_check=ok`, an empty foreign-key check, no disposable +session, and exactly one matching causal state and operation. Desktop remained +schema 28 with the same integrity results and terminal provenance. Canonical +hashes for every other session, occurrence, performed set, continuous result +and body observation were identical to both pre-rollout backups. + +Finally, the retained pre-deletion generation +`gen_965fdf80-4412-41fb-9a46-28744a3e115b` was replayed through the production +consumer. It returned its byte-identical stored ACK; the before/after tuple was +unchanged (`target session=0`, `target operation=1`, `deleted provenance=1`, +`all sessions=9`). Real Firefox against the deployed C server passed at +1440x1000 and exactly 390x844 with no horizontal overflow. Evidence screenshots +are retained privately under +`~/.local/state/trainlog/history-delete-http500-fix-v1-web-evidence/`; their +SHA-256 values are respectively +`9c9fd42aa58b0818488ef9f8b3412abfb56e96ea3f9d30c8da2fcfe3da8c10f1` and +`70838305fe6d17485f3d5d80cf60e2639baf4ed87d148f4b55e4b6e8c25fdbca`. diff --git a/docs/sync_exchange.md b/docs/sync_exchange.md index c4c93dc..83ffd88 100644 --- a/docs/sync_exchange.md +++ b/docs/sync_exchange.md @@ -830,13 +830,21 @@ than fabricating an ACK or discarding evidence. Before Android captures for a negotiated `generation-archive-v1` conversation, the desktop consumer publishes `desktop-archive-acknowledgements-v1.json`. Its strictly correlated envelope -contains at most 32 exact consumed ACK documents already retained in the -desktop consumption ledger. This repairs the evidence gap left by older +contains at most 32 exact terminal consumed or rejected ACK documents already +retained in the desktop consumption ledger. The bounded window selects the +newest terminal evidence first, because older acknowledged generations are +normally already archived and must not starve interrupted recent +conversations. This repairs the evidence gap left by older Android producers that advanced generation status without retaining the received ACK. Android revalidates every document against its immutable local -generation and manifest before storing it; missing, mismatched, rejected, or -ambiguous evidence cannot make a generation archivable. The object is a -bounded coordination artifact, not a new ACK source. +generation and manifest before storing it. A consumed ACK makes its exact +generation archive-eligible; a rejected ACK closes the exact producer row but +does not make it an acknowledged archive candidate. Missing, mismatched, or +ambiguous evidence cannot advance any generation. Rejected ACKs created before +the cross-platform diagnostic canonicalization fix remain durable desktop +evidence but are omitted from the recovery envelope when Android cannot verify +their digest. The object is a bounded coordination artifact, not a new ACK +source. If Android still cannot admit a generation, it durably publishes the run-correlated `android-generation-error-v1.json` with @@ -852,6 +860,10 @@ helpers and the Android repository's outer transaction apply every business row, causal state and the consumption/ACK record together. A late semantic failure rolls back earlier writes and commits a separate bounded `rejected` ACK; missing/incomplete transport input remains retryable and produces no ACK. +Within a complete causal envelope, a history occurrence and its equipment +association companion are both dominated when their owning session already has +a durable deletion state. Standalone history and association imports remain +strict and still reject unknown sessions or occurrences. Lineage is scoped to the producer/consumer pair. Exact replay returns the stored result; an accepted successor must name the last consumed generation as diff --git a/docs/tests.md b/docs/tests.md index 67725f5..bff1776 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -170,6 +170,15 @@ npm run build Release-oriented Meson builds must use `-Dweb=enabled`; Meson never provisions or downloads npm dependencies. +The history-deletion regression suite also exercises a real Program-origin +completed session through the Core and HTTP command paths, including stale +revision, cancellation, injected transaction failure, exact request replay and +terminal execution provenance. Full-generation tests apply causal deletions +before older history and equipment-association companions, prove that +standalone imports remain strict, recover recent consumed and rejected ACKs +without letting an older bounded window starve active producer capacity, and +replay an already consumed generation without mutation. + `WEB_DASHBOARD_DATA_CONTRACT_V1` adds a standalone bounded Core test for empty history, explicit unavailable domains, two observable sessions on one local day, an unfinished session, continuous activity, MAX-only sessions, primary