Raw token streaming separated claims from citations
K81R stopped revealing prose character by character and buffered generated output into validated claim units whose evidence arrived with them.
K81R displayed the sentence before it knew whether the citation existed.
Tokens arrived into the answer pane one fragment at a time:
Z29C retries an uncertain delivery three times…
The citation field was scheduled to appear later in the generated structure. Before it did, validation failed. The interface replaced the sentence with an unsupported-claim warning.
For two seconds, the wrong claim had looked like the answer.
Time to first token was excellent. Time to first inspectable claim was not.
The stream exposed generation order as product order
Language models generate a sequence. The product needed claim, evidence, verification state, and rendering policy to arrive as one meaningful unit.
Raw streaming made model sequence visible directly. It could show:
- Half a sentence whose qualifier had not arrived.
- A numerical claim before its unit.
- A confident assertion before an uncertainty phrase.
- Markdown syntax before a closing delimiter.
- A source label before the source ID.
- A claim before deterministic policy rejected it.
The interface was reading an unfinished serialization as finished product state.
I inserted a claim buffer between model stream and reader.
The generation format used records
The model produced an ordered stream of structured claim records:
answer_start
claim_start
claim_text
evidence_ids
claim_type
uncertainty
claim_end
answer_endThe exact transport format depended on the model interface available, but the application parser required complete record boundaries. Partial fields remained internal.
A claim could contain a concise sentence or a small connected group when splitting would damage meaning. It could not contain a whole essay with one citation list.
The parser recorded raw events for short-lived diagnostics, then constructed immutable candidate claims.
At claim_end, K81R checked:
- The record parsed under the expected schema.
- Every evidence ID belonged to the selected set.
- Current requester could still access each source.
- Source revisions and spans existed.
- Claim type was allowed for the task.
- Required qualifiers and units were present where structurally checkable.
- The content passed output rendering and security policy.
Only then did the page reveal the claim, its evidence links, and validation state together.
Semantic support verification could still require a slower model or human review. The page labelled that state. Passing deterministic checks did not become a green truth badge.
The evidence set filled the wait
Buffering delayed visible prose. I did not replace it with a bigger spinner.
The page already showed the question, corpus scope, answerability result, and selected evidence. While generation ran, a reader could inspect sources. Progress reported bounded stages: drafting claim one, validating structure, checking source links.
The first visible generated unit arrived later than the first token and earlier than the complete answer. Each arrival was useful and stable enough to read.
Streaming remained progressive. The unit of progress changed from character production to reviewable meaning.
A sentence was not always a claim boundary
Sentence segmentation alone failed on lists, code, abbreviations, and multi-sentence reasoning. The generation schema asked for explicit claim records and prose blocks.
I used several block types:
- Source-supported factual claim.
- Explicit multi-source inference.
- Qualification or limitation attached to a claim.
- Quoted source span rendered by the application.
- Code suggestion labelled as proposal.
- Transition text with no factual assertion.
Transitions could render with adjacent validated claims. A qualification could not arrive in a later block after the broad assertion had already appeared.
The schema followed evidence relationships rather than punctuation alone.
Compound claims were decomposed before display
The model sometimes returned:
Z29C preserves uncertain outcomes and retries idempotent adapters three times.
The first clause and second clause required different sources and conditions. The claim normalizer split them or rejected the record for regeneration under a stricter instruction.
Deterministic conjunction detection caught obvious cases and not every semantic compound. Evaluation included examples where one clause was unsupported. Human review could challenge a displayed claim and feed the regression set.
The product preferred two source-linked sentences to one elegant sentence that laundered support across a conjunction.
The model returned evidence IDs, not Markdown links or source titles. The application looked up exact source metadata and rendered accessible citations.
This prevented invented URLs, altered titles, and links to the current revision when the evidence referenced an older one. It also kept citation style consistent across streaming states.
Quotes came from exact source spans. The model could select a span and propose surrounding prose; it could not reconstruct quotation text and wrap it in marks.
Rendering authority stayed outside the token stream.
Invalid claims had several dispositions
One generic retry would hide why validation failed. The generation workflow classified:
- Malformed structured output.
- Unknown or inaccessible evidence ID.
- Unsupported claim type for task.
- Missing required qualifier.
- Content-rendering policy violation.
- Evidence support uncertain.
- Contradicted by selected evidence.
Malformed output could receive one bounded repair attempt using the same evidence. Inaccessible evidence stopped the answer and reopened authorization/answerability. Contradiction produced a refusal or conflict presentation. Support uncertainty showed a review-required state.
The interface never flashed the invalid text as an answer before choosing.
If claim three failed after claims one and two appeared, the system kept their candidate identities. A repair request received the original task, evidence set, accepted prior claims, and failure reason. It generated a replacement candidate for the failed unit or a revised answer plan.
The final answer record stored every accepted claim and the generation attempt that produced it. Discarded invalid text remained only in short-lived restricted diagnostics unless it became an evaluation fixture.
The visible answer did not silently mutate claim one to make claim three easier. A broad revision created a new answer candidate.
Two individually supported claims could conflict when combined. One described current policy; another described historical behavior without a temporal label.
Before revealing a new claim, K81R checked entity, time, source authority, and contradiction relationships against already accepted claims. The check could identify known conflicts and could not prove global consistency.
If the historical claim was properly scoped, it appeared under a history section. If scope was missing, the block stayed buffered or moved to review.
Progressive output needed incremental answer-level validation, not only local citation checks.
Ordering followed an answer plan
The model first emitted a plan of claim slots: current rule, required capabilities, uncertainty condition, historical note, limitation. The application validated that the plan fit the task and evidence coverage before prose generation.
Claims then arrived in that order. A missing optional historical block could fail without preventing the current answer. A missing required policy block stopped completion.
The plan was not shown as chain-of-thought. It was a product-level outline of intended answer units and evidence requirements.
This reduced rambling and made progress meaningful: “2 of 4 supported claims ready” described the artifact, not the model's private process.
Character-by-character live regions were unusable. Screen readers could announce fragments repeatedly, and visual users had to chase a moving line.
K81R inserted complete claim blocks into a stable document structure. A polite status announced when a new claim became available, not every token. Focus stayed on the evidence or answer heading. The page did not auto-scroll away from a source being inspected.
Users could pause automatic claim insertion and reveal ready blocks manually. Reduced-motion preferences removed any progressive animation.
The answer unfolded like a document revision, not a typing simulation.
Raw tokens could open a code fence, link, emphasis marker, or HTML-like construct without closing it. Incremental renderers had to guess and sometimes produced unstable or unsafe DOM.
Structured claim blocks restricted allowed formatting. The application parsed complete block content, sanitized it under a strict rendering policy, and rejected unsupported constructs before insertion. Source quotations and code used typed fields rather than arbitrary Markdown where possible.
This reduced layout churn and prevented prompt-provided text from becoming executable markup.
Output rendering policy remained deterministic and versioned.
Cancellation differed before and after acceptance
Closing the page could cancel an unaccepted generation request. Once the server accepted a generation job and recorded its identity, it could continue or be cancelled through an explicit command according to policy.
Claims already committed to a draft answer remained. A client disconnect did not imply that external model work had definitely stopped. The worker recorded attempt outcome and any usage evidence.
This reused Z29C's distinction: network disappearance is not proof that an external request did not happen.
The page could resume the answer record later without replaying accepted claims.
A streaming connection could end after the provider generated output but before K81R received a complete record. The generation attempt became failed-known when the provider reported rejection, or outcome-unknown when acceptance and completion could not be established.
The job did not blindly issue another billable request under a new identity. Adapter capability determined whether status lookup or idempotent retry existed. Recovery linked any replacement attempt to the same answer intent.
The answer page showed “Drafting interrupted; checking attempt status” rather than resetting to an empty spinner.
AI streaming did not escape durable external-effect design.
The first-token metric lost priority
I kept transport measurements for diagnosis:
- Request accepted.
- First provider event.
- First parseable claim record.
- First structurally valid claim.
- First evidence-linked claim visible.
- Complete draft.
- Verification and review completion.
The product milestone was first inspectable claim. Optimizing first token could still reduce total wait, but it no longer justified revealing unstable text.
The new metric aligned performance with what a reader could safely use.
The buffer needed limits
A model could fail to close a claim record and make the interface wait indefinitely. The parser enforced size, time, nesting, and field limits. Exceeding them terminated or repaired the attempt under a bounded policy.
Large code or table output used dedicated artifact fields with separate limits. The model could not smuggle an entire answer into one claim to avoid intermediate validation.
Backpressure prevented provider events from exhausting memory if downstream validation slowed. Operational metrics tracked buffered bytes and oldest incomplete record.
The claim boundary was a protocol, not a prompt suggestion.
An answer with three validated required claims and one failed optional comparison could be useful. K81R marked it Partial draft and named the missing block. A reviewer could accept the supported subset, request repair, or return to evidence.
If a required claim failed, the answer stayed Incomplete and the page emphasized sources rather than presenting a conclusion. Completion rules came from the answer plan.
This avoided the binary choice between streaming everything and withholding the whole response until perfection.
Progressive claims enabled truthful partial results.
Static final-output scoring could not catch a wrong sentence shown briefly and later removed.
The harness recorded stream events and interface commits at deterministic checkpoints. It asserted that:
- No incomplete claim entered the visible answer.
- Citation and claim appeared together.
- Invalid or inaccessible evidence never rendered.
- Qualifications arrived in the same accepted unit.
- Live announcements occurred only at block completion.
- Final answer claims matched the immutable record.
Temporal correctness became part of AI-output evaluation.
Raw streams remained diagnostics
For synthetic evaluation and short-lived debugging, I kept raw provider events under restricted retention. They helped diagnose schema failures and latency.
They were not the public answer record. Accepted claim objects, evidence, validation, configuration, and final rendering formed the durable artifact. Sensitive raw content expired unless a reviewed failure became a minimized fixture.
The separation limited data retention and prevented transport noise from becoming product history.
The first visible prose arrived later by hundreds of milliseconds in the lab. It arrived with its source, revision, and state. Readers could inspect evidence during the wait. The answer stopped rewriting itself mid-sentence.
The experience felt less magical. It also required less vigilance to determine whether a citation was still coming or whether the qualifier had been cut off.
Raw token streaming had optimized proof that the model was doing something. Claim streaming optimized the earliest moment the product had something reviewable to say.
The model still generated tokens. K81R stopped making their transport order the order in which a person was asked to believe them.
Meaning arrived only after its supporting structure arrived with it.
The earliest visible output became slower, steadier, attributable, and far more useful than a sentence still deciding what it meant.
Source revocation could invalidate a buffered claim
A claim might finish generation while one cited source became inaccessible or superseded. Validation used current access and source status at commit time, not only when the job started.
If revocation occurred before revelation, the claim never appeared and answerability reopened with a disclosure-safe gap. If authority changed but the old source remained accessible, the claim could render as historical and no longer current. A claim already accepted into an immutable answer retained its provenance but revalidated on later viewing.
Buffering created a natural commitment point: source and claim met under one current decision before entering the visible draft.
Provider billing and token usage occurred even when a candidate claim failed validation. I recorded input, generated, buffered, discarded, repaired, and accepted token counts per attempt where the adapter exposed them.
The product did not celebrate accepted-output efficiency while hiding repeated invalid generation. Evaluation compared cost to evidence-set size, valid claims, and task consequence. A repair loop had a strict budget.
This made claim buffering economically inspectable. Safer revelation could not rely on unlimited invisible retries.
A slow verifier did not freeze the document
Deterministic checks ran synchronously before reveal. Semantic support verification could take longer. Waiting for every verifier would make progressive output collapse into a complete-answer wait.
K81R used clear states: Source-linked, Automated support check pending, Review required, and Reviewed. Low-consequence draft claims could appear after structural checks with pending status. Reference answers configured to require support verification withheld the claim until the relevant stage completed.
Task policy determined the commitment threshold. The interface never used one green appearance for several levels of assurance.
Reloading the page during generation reopened the durable answer intent, current attempt, accepted claim sequence, and any buffered record known to the server. The client did not concatenate a new raw stream onto old visible text.
Sequence numbers and claim IDs prevented duplicate insertion after reconnect. If the transport lost events, the client fetched current committed state. Uncommitted partial tokens remained implementation detail and could be discarded.
This made the stream a delivery optimization over durable state rather than the sole record of the answer.
An optional comparison claim might finish before the required policy claim. The page waited for the answer-plan slot rather than inserting it above and rearranging later.
Independent optional sections could reveal in parallel when their headings and order were already stable. Within one argument, accepted claims appeared in planned sequence. A failed slot rendered a bounded missing state rather than collapsing later claims upward unexpectedly.
The approach borrowed streaming UI's editorial lesson: preparation may be concurrent; revelation still needs a reading order.
The final renderer used the same records
After generation completed, K81R did not rebuild prose from the raw stream. The final answer page rendered the committed claim records, evidence links, review states, and deterministic transitions used during streaming.
This prevented the progressive and reloaded views from disagreeing. Export and later inspection consumed the same immutable answer revision. Any editorial smoothing created a new reviewed revision with a diff and preserved support mapping.
The stream and the document became two views of one state model.