LearnNewsExamplesServices
Frontmatter
id17440
titleFence-only completion cannot mint its materialization receipt
stateClosed
labels
bugaitestingarchitectureagent-os
assigneesneo-gpt
createdAtAug 20, 2026, 11:53 PM
updatedAtAug 21, 2026, 9:20 AM
githubUrlhttps://github.com/neomjs/neo/issues/17440
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 21, 2026, 9:20 AM

Fence-only completion cannot mint its materialization receipt

Closed Backlog/active-chunk-18 bugaitestingarchitectureagent-os
neo-gpt
neo-gpt commented on Aug 20, 2026, 11:53 PM

Context

#17139 and merged PR #17152 corrected tenant outcome classification: a summary whose error rows are all validated durable fences now completes, advances its checkpoint, and preserves per-family census visibility.

The real Ingestion composition still contradicts that completion contract on current origin/dev@b75e5d005961:

  • IngestionService.persistManifestSnapshot() at :1228 permits a positive-effect receipt only when summary.errors.length === 0.
  • A durable-fence-only summary necessarily carries validated fence rows in summary.errors.
  • TenantRepoSyncService.assertFullMaterializationEffect() at :682 rejects positive materialization without a matching receipt as KB_TENANT_REPO_SYNC_MATERIALIZATION_UNPROVEN.

PR #17152 did not touch IngestionService; its runTask composition arms used an ingestion seam. The classifier can therefore say complete while the real receipt producer withholds the proof completion requires.

Live latest-open sweep: checked the latest 20 open issues at 2026-08-20T21:53:26.487Z; no equivalent found. Recent A2A claim sweep: last 30 messages, no overlapping claim. Semantic KB search surfaced adjacent #16577 receipt precedent but no fence-only receipt ticket.

The Problem

A durable fence is an error-shaped visibility row for work that is deliberately no longer pending at the current generation. #17139 correctly prevents those rows from forcing perpetual deferral.

The materialization receipt writer still treats every error row as live failure. On a fence-only run:

  1. accepted work and/or durable fence effects are real;
  2. outcome classification says complete;
  3. receipt eligibility says false solely because the census travels in errors;
  4. the tenant composition sees positive effect without proof and throws MATERIALIZATION_UNPROVEN.

The checkpoint cannot complete through the real service even though the outcome contract says it must.

The Architectural Reality

  • #17139 owns the fail-closed durable-fence predicate: closed disposition vocabulary, coherent details.reasonCode === code, and a valid chunk ID.
  • classifyIngestionOutcome consumes that predicate.
  • persistManifestSnapshot independently decides whether a summary can mint or reuse digest-bound completion proof.
  • assertFullMaterializationEffect requires that proof before advancing a positive full-materialization attempt.

The predicate must have one service-neutral authority usable by both classifier and receipt producer. A second looser spelling would let classification and proof disagree again.

The Fix

  1. Expose the validated durable-fence predicate from an existing service-neutral helper surface, and consume the same predicate in outcome classification and receipt eligibility.
  2. Allow a non-yielded summary to mint/reuse its digest-bound receipt when it has positive effect and every error row is a validated durable fence.
  3. Keep any live, malformed, ambiguous, or mixed error as a hard receipt veto.
  4. Preserve fence rows and censuses; a receipt proves attempt completion, not absence of fenced content.
  5. Prove the contract through real IngestionService.persistManifestSnapshot() and the production tenant composition, not an ingestion stub.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
durable-fence predicate #17139 writer contract: disposition vocabulary + reason-code coherence + chunk-id gate one shared predicate used by classifier and receipt producer any malformed/unknown/incoherent row is live JSDoc per-clause mutation arms
positive-effect receipt eligibility IngestionService.persistManifestSnapshot zero errors OR all errors durable fences; yielded !== true; positive effect; valid attempt/digest any live or ambiguous row vetoes receipt JSDoc real IngestionService arms
receipt reuse existing digest + contract-version match fence-only completed retry may reuse matching proof mismatch or live error vetoes JSDoc retry arm
tenant completion assertFullMaterializationEffect fence-only summary arrives with receipt and advances checkpoint while censuses remain visible missing proof stays MATERIALIZATION_UNPROVEN real runTask composition
telemetry/census existing summary error rows and #17139 census fields receipt does not erase or relabel fences absent census remains unobserved deployment docs snapshot/checkpoint arm

Decision Record impact: none — this composes two existing completion contracts without a new protocol or persistence store.

Acceptance Criteria

  • A current-dev red proof drives a validated durable-fence-only summary through real IngestionService.persistManifestSnapshot() and observes no materialization receipt.
  • After repair, content-poison-only, undeliverable-only, and mixed durable-fence-family summaries mint or reuse digest-bound proof when non-yielded and otherwise eligible.
  • One live deferrable error beside durable fences vetoes the receipt.
  • Each malformed-fence clause independently vetoes the receipt: unknown disposition, reason-code mismatch, invalid chunk ID, or missing details.
  • A yielded summary never mints full-materialization proof, including when every error row is a durable fence.
  • Production composition through TenantRepoSyncService.runTask advances the checkpoint for a fence-only run and preserves both fence censuses.
  • Existing zero-effect and crash-after-complete receipt recovery arms remain green.
  • Classifier and receipt producer import one predicate; deleting either consumer turns its own focused arm red.

Out of Scope

  • Changing #17139's fence-only outcome or census semantics.
  • Poison-store schema, replay-clear behavior, or generation invalidation.
  • Resumed-slice settled/remaining accounting: separate follow-up.
  • Treating arbitrary errors as receipt-compatible.

Avoided Traps

  • errors.length === 0 as a semantic proxy. Durable fences are error-shaped observability, not live work.
  • Duplicating the predicate. Two definitions can classify complete and withhold proof on the same summary.
  • Erasing fence rows to obtain a receipt. That gets completion by deleting the operator signal.
  • Stub-only proof. PR #17152's classifier composition did not execute the real receipt producer.

Related

  • #17139 / PR #17152 — fence-only completion and census contract.
  • #16577 — digest-bound receipt precedent for successful materializations that previously lacked proof.
  • #17132 / PR #17299 — positive partial-progress receipt veto; distinct but adjacent.
  • #17439 — separate settled/remaining accounting lane.

Origin Session ID: 5227e910-6f64-46da-a0d1-d6fb1cdfbb9f

Retrieval Hint: query_raw_memories("durable fence only complete materialization receipt errors"); source anchors IngestionService.persistManifestSnapshot, TenantRepoSyncService.assertFullMaterializationEffect, PR #17152.

tobiu referenced in commit b8a31cd - "fix(ai): let fence-only completion retain materialization proof (#17440)" on Aug 21, 2026, 2:32 AM
tobiu referenced in commit 85143b8 - "fix(ai): share tenant chunk id authority (#17440)" on Aug 21, 2026, 2:32 AM
tobiu referenced in commit 47bbbc0 - "fix(ai): let fence-only completion retain materialization proof (#17440) (#17441) on Aug 21, 2026, 9:20 AM
tobiu closed this issue on Aug 21, 2026, 9:20 AM