Skip to content

docs: make firehose controls graph-scoped - #436

Open
aaltshuler wants to merge 1 commit into
mainfrom
codex/graph-scoped-stream-contract
Open

docs: make firehose controls graph-scoped#436
aaltshuler wants to merge 1 commit into
mainfrom
codex/graph-scoped-stream-contract

Conversation

@aaltshuler

@aaltshuler aaltshuler commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • supersede docs(rfc): amend the served stream transport to graph scope (P8) #431 from current main with the graph as the sole public firehose resource
  • remove the public prepare/bulk-enrollment contract; mixed graph ingress lazily invokes the existing private recoverable enrollment child only after bounded row validation
  • define graph-wide control-token fencing, bounded quiesce/abort ownership, immutable graph-control terminal receipts, disable cancellation, and receipt-first retry/replay in a new F6c strand without reinterpreting recovery-v13–v21
  • keep datasets, tables, lanes, bindings, lifecycle revisions, and physical object authority private across ingress, status, block/dead-letter support, and control DTOs
  • make export authority callable and explicit for ENABLED/QUIESCED, DISABLED/QUIESCED, and receipt-bound RETIRED/QUIESCED cuts while reusing the existing exact-version export substrate
  • leave F7 transport-only: it publishes the graph contract proved behind hidden seams in F6c

This directly removes #431's N-child prepare transaction and its partial-prefix recovery problem. Lance continues to own each private WAL/dataset transaction; OmniGraph coordinates only the graph-level result.

Validation

  • git diff --check
  • scripts/check-agents-md.sh
  • independent contract audits for authority/ownership/replay, historical strand integrity, graph-only surface, and callable recovery paths

Docs-only change; no Rust test surface changed.


Open in Devin Review

Greptile Summary

The PR redesigns the planned firehose surface around a single graph-scoped resource and moves semantic activation into a hidden F6c strand before transport-only F7.

  • Replaces public lane preparation and per-table controls with mixed graph ingress, private lazy enrollment, and graph-wide control-token fencing.
  • Defines graph-control coordination, immutable terminal receipts, disable adoption, redacted status and support DTOs, and receipt-first replay.
  • Extends export authority to quiesced graph cuts while preserving historical recovery-family meanings.

Confidence Score: 4/5

The PR should not merge until the terminal result and receipt behavior for a quiesce adopted by disable is made unambiguous.

The new design requires receipt-first replay by the original control ID, but simultaneously says an adopted quiesce becomes completed and must never be reported completed or cancelled, leaving no defined terminal receipt outcome.

Files Needing Attention: docs/dev/firehose-path-specs.md

Important Files Changed

Filename Overview
docs/dev/firehose-path-specs.md Adds the F6c implementation plan and graph-only F7 boundary, but gives disable-adopted quiesce occurrences contradictory terminal-result requirements.
docs/rfcs/0026-memwal-streaming-ingest.md Recasts the authoritative public contract around graph-scoped ingress, control, redaction, recovery, and export; its receipt grammar helps expose the adoption inconsistency in the implementation plan.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  Client[Graph client] -->|mixed NDJSON + graph token| Gate[Graph ingress gate]
  Gate --> Validate[Bounded row validation]
  Validate --> Enroll[Private lazy enrollment]
  Enroll --> WAL[Private lane WAL]
  Control[Graph fold / quiesce / resume] --> Coordinator[Graph control coordinator]
  Coordinator --> Children[Deterministic private child work]
  Children --> Receipt[GraphControlTerminalReceipt]
  Receipt --> Replay[Receipt-first replay]
  Coordinator --> Export[Quiesced exact-version export cut]
Loading

Fix All in Claude Code

Reviews (1): Last reviewed commit: "docs: make firehose controls graph-scope..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Comment on lines +2690 to +2692
the disable-plan ID; an adopted occurrence retains its original ID only for
eventual terminal replay and is never falsely reported `completed` or
`cancelled`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Adopted quiesce has no terminal state

When offline disable adopts an active quiesce, the specification says that quiesce becomes completed after every child is sealed but also forbids reporting it as either completed or cancelled. Because terminal receipts only cover those two results and are keyed by the original operation ID, retries cannot return the promised terminal result and instead become unreplayable or fall through to stale-authority refusal.

Fix in Claude Code

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

⚠️ 1 issue in files not directly in the diff

⚠️ Two different behaviours are specified for the same streaming situation (docs/rfcs/0026-memwal-streaming-ingest.md:2920-2922)

The rules for a graph whose underlying stream is already closed are stated twice with conflicting outcomes (stream_resume_required at docs/rfcs/0026-memwal-streaming-ingest.md:2920-2922 versus the fail-closed rule at docs/rfcs/0026-memwal-streaming-ingest.md:3711-3713), so implementers cannot tell which response is correct.
Impact: Whoever builds the feature may pick either behaviour, producing an ingest path that either quietly hands out a control handle or refuses, contrary to the other half of the specification.

Conflicting per-line result versus P2's fail-closed authority blocker

The rewritten §4.6 response union keeps a per-line stream_resume_required outcome, described as "an effect-free graph blocker under an ENABLED profile" that "carries the current graph control token needed by the separate authorized graph resume" (docs/rfcs/0026-memwal-streaming-ingest.md:2920-2922, mirrored in docs/dev/firehose-path-specs.md:1668).

The new P2 text for the same condition says the opposite: "An existing OPEN private lane may admit. DRAINING or SEALED beside ACTIVE graph control is a fail-closed authority/recovery blocker; ingest never auto-resumes it. Under the paired F6c authority, ordinary quiescing/quiesced state is already visible at the graph control boundary, so graph ingress refuses before body ownership" (docs/rfcs/0026-memwal-streaming-ingest.md:3711-3715). Under the new pairing rules, a sealed cut is exposed as ENABLED/QUIESCED, and only ACTIVE admits rows, so ingress refuses before a body byte is polled and no per-line resume-required result can be produced.

Secondarily, the retained bullet has this ingest-only path return the current graph_control_token, while P8 states an ingest actor "needs no status permission" and that any non-exact supplied token is refused "without a replacement token" — status is otherwise the only place that publishes that handle.

View 1 additional finding in Devin Review.

Open in Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant