修复(08-28-production-arm-backup-transfer-incident): 纠正partial停止偏移分类

这个提交包含在:
2026-08-28 19:52:59 +08:00
父节点 d6a2b85dc2
当前提交 1bb066ddb7
共修改 5 个文件,包含 75 行新增和 7 行删除
@@ -2857,11 +2857,21 @@ current shared mapping -> fine-grained stages + mutation listeners
offsets or durations indicate a deterministic limit; materially different
offsets/durations favor intermittent timeout or network interruption. Do not
infer this split from service exit `1`, which is the wrapper's generic code.
- A stopping-offset pair is `similar` only when its absolute difference is no
more than both `50000 ppm` (5% of the larger aggregate) and `67108864` bytes
(64 MiB), equivalently `difference <= min(relative_limit, absolute_limit)`.
Using `max(...)` is forbidden: it misclassifies a small nonzero partial and a
zero-byte partial as similar merely because both are below 64 MiB.
- `last-deadman.json` proves the detector decision. `deadman-alert-state.json`
proves the deduplication state. A journal allowlist line with
`evaluated sent=true` proves the helper attempted and accepted one send; it
does not prove a human noticed the message. Repeated `sent=false` for the same
failure is normal deduplication, not a monitoring blind spot.
- Keep the two JSON schemas distinct: the dead-man summary contains
`status/category/findingCount/findings`, while the alert deduplication state
contains only `schemaVersion/status/category`. A probe must not request
`findingCount` from the alert state or report its contractual absence as an
invalid remote state.
- Read-only investigation output is an allowlist of status/category/count/age
and capacity fields. Never print unit command lines, raw JSON, raw journal,
remote identities, paths, run ids, webhook data or diagnostic stderr.
@@ -2961,6 +2971,8 @@ current shared mapping -> fine-grained stages + mutation listeners
rsync codes `23/30/12/11/255`; assert the incident summary preserves code and
elapsed-time evidence separately from wrapper exit `1` and does not output
file names.
- Assert `2.68 MB` versus zero is `different`, a large pair within both 5% and
64 MiB is `similar`, and exceeding either threshold is `different`.
- Fixture one complete source batch, no complete source batch, checksum/size
corruption and malformed manifest. Assert the risk classification and
transition recommendation change without emitting paths, run ids, artifact
@@ -2987,6 +2999,7 @@ state path test returned false -> state missing
partial count > 0 -> finalize failed
off-host stale -> assume one complete backup still exists on production
service exit 1 -> call it the rsync exit code and use service duration
partial difference <= max(5% limit, 64 MiB) -> similar
```
#### Correct
@@ -3000,4 +3013,5 @@ derive unit identity from installer -> timer trigger + service Result/exit
-> safe scheduler/source/transfer/finalize/alert conclusion
-> validate the source batch first and classify single-point vs no proven point
-> bind retained diagnostics to the safe failure phase; unavailable clocks stay unavailable
-> partial difference <= min(5% limit, 64 MiB) before calling it similar
```