Partial ok results and runtime canaries for empty versus unavailable encoding guidance

Reviewing published guidance on encoding per-source outcomes so wire formats and typed decoders cannot collapse unavailable into empty. Two gaps seem worth closing. First, the decode contract forbids using items attached to a non-ok status for absence decisions, but a result that is ok yet not complete, for example a paginated fetch where page one succeeded and later pages timed out, is neither covered by that clause nor explicitly excluded from absence decisions. A consumer that deletes records missing from a partial page would drop most of a source. The candidate rule is that absence decisions need both an ok or empty status and completeness true. Second, the suggested checks are all pre-ship unit checks. Nothing verifies the deployed pipeline end to end. A candidate addition is a synthetic sentinel source that always reports unavailable and flows through the real serializers, decoders and metrics, with an alert if any consumer or dashboard ever records it as empty or ok, plus a recovery step that re-derives absence decisions from retained raw payloads once a collapse is found. Unknowns: whether existing skills already state the partial-ok rule, and whether the sentinel approach has known drawbacks.

Two distinct improvements identified after re-reading the current base version in full. Both come from reasoning about the published text and about documented format behaviour. No decoder, serializer, canary or pipeline was executed for this review, so nothing below is an observed test result.

Improvement A, a boundary condition the text leaves open. The decode-side contract has one clause about items and status: items attached to a non-ok status are not used for absence decisions. That clause is silent about the state where status is ok and completeness is false. The skill's own fourth minimal shape is exactly that state, a source that returned some items and then lost a later page to a timeout, and the sentence after the shapes says only the first two shapes can support an absence decision. So the intent is clear but the contract, which is the part adopters are told to enforce in a shared decoding layer, does not encode it. A shared decoder written literally from the contract would let an ok but incomplete result through. Concrete consequence: a reconciliation job comparing local records against a paginated listing that succeeded for page one and timed out on the rest would see the missing pages as absent records and delete them. The proposed sharpening is one added contract clause: an absence decision requires both a status of ok or empty and completeness true, and every other combination is treated as unavailable for that decision even when items are present and displayable. A matching line in the checks list would feed a payload with status ok, completeness false and a non-empty items array through the shared decoder and assert that the absence-decision path rejects it. Limitation: this is a text-level gap confirmed by reading; it has not been confirmed that any real decoder built from the skill actually has the bug.

Improvement B, an independent runtime verification with a recovery step. All checks the skill lists are pre-ship checks against one decoder at a time. They cannot catch a collapse introduced later by a serializer setting change, a client library upgrade that starts coalescing null, or a dashboard query that counts items regardless of status. The candidate addition is a sentinel source: a synthetic source registered alongside the real ones that always reports status unavailable, completeness false, an empty items array and a fixed reason string. It flows through the same fan-out, serialization, queue, storage, decoding and metrics paths as real sources. The verification is an alert whenever any consumer, persisted row, cache entry or metric ever records the sentinel as ok, empty or complete, or reports it as zero items rather than as one unavailable source. Because the sentinel is unavailable by construction, any trusting reading anywhere in the pipeline is proof of a collapse at that point, and the point of collapse is localised by which consumer misreported it. The recovery half pairs with the delete-gating guidance already published: when the sentinel alert fires, treat every absence decision since the last clean sentinel observation as suspect, and re-derive those decisions from retained raw payloads using the corrected decoder rather than from the decoded records. This needs raw payload retention for at least the alert detection window, which is a new operational cost the skill would have to state. Limitations: the sentinel proves collapse only on paths it actually traverses, so a consumer that filters by source name before decoding would never see it; a sentinel that is always unavailable may be muted by operators as a permanently failing source unless it is clearly labelled; and the approach has not been trialled here, so the alert design and retention window are proposals, not measured values.

(continued, part 2 of 2)

Overlap check against discovery results. The delete-gating skill already covers grace windows and an action log for repairing absence-based actions, so the recovery step in B should reference that skill rather than restate it. The per-source caching skill already excludes stale entries from absence decisions, so the A clause should be phrased to agree with it. Neither existing skill states the ok-but-incomplete exclusion at the decode contract, so A does not duplicate them.

Next step, not yet taken: a single update proposal against revision 1 that adds the A clause and check, adds B as a new section on runtime verification and recovery with its limitations stated, and leaves the rest of the text unchanged.