Skip to content

Ingress: separate the causal identity recipe from plain intents (#885) - #900

Merged
flyingrobots merged 6 commits into
mainfrom
feat/causal-identity-v3
Oct 16, 2026
Merged

flyingrobots merged 6 commits into
mainfrom
feat/causal-identity-v3

Conversation

@flyingrobots

Copy link
Copy Markdown
Owner

Closes #885. Implements the owner rulings recorded on the issue: Option A, the transition rules, and the ownership split.

Stacked on #890 (base feat/strand-inherits-occurrences). The compatibility rule also governs #890's inherited-occurrence check. Retarget to main once #890 merges.

The defect: an encoding alias, not a hash collision

The original recipes hash a plain intent as "ingress:" || kind || bytes and a causal intent as "ingress:causal:v2\0" || kind || len || bytes || count || parents. The causal domain begins with the plain one, and a kind is any 32 bytes, so a plain intent can reproduce a causal intent's hash input byte for byte. The construction is direct and needs one envelope, with no search. a_plain_intent_aliases_the_original_causal_recipe_but_not_the_separated_one builds it.

What changes

  • Identity versions. Every envelope records an IngressIdentityVersion. New causal intents use SeparatedCausal: "echo.ingress.causal.v3\0" || kind || len || bytes || count || (tag || receipt_ref)*, with one-byte role tags and fixed-length refs. Plain intents are unchanged.
  • Retention. New causal requests are retained as EINGR004 (the EINGR002 layout plus an occurrence flag). The EINGR001–EINGR003 retention formats keep their bytes and identity interpretation exactly, and decode to Original, plain intents included.
  • No new original-recipe admissions. A causal request in the original recipe can only name an existing submission. As a new admission it is OriginalCausalIdentityNotAdmissible. Retained records are never rejected for that reason; historical decoding and new admission policy stay separate.
  • Transition rule. Exact legacy matches take precedence:
    • Genuine resend: the retained envelope states the same kind, bytes, parents, occurrence (both digests) and resolved head. The resend resolves to the original submission (Duplicate with its original ingress id) and is staged with its retained envelope.
    • Plain alias: not a retry, and no reservation. The request gets ordinary separated admission.
    • Legacy material missing: OriginalIngressIdentityUnverifiable.
    • Both identities exist: IngressIdentityAmbiguous.
    • Occurrence retries and strand inheritance use the same comparison.
  • Ownership. The recipe, EINGR004 and the lookup are Echo-local. Nothing here is normative for Continuum.

Witnesses (guarded worker)

Witness Variant that fails it
Alias construction and the recipe tests (codec) R1: new causal requests use the original recipe
Genuine legacy resend, staging with the retained envelope, a changed parent being a new act R2: no legacy precedence
Planted plain alias is not a resend R3: fingerprint match without semantic comparison
Both identities → ambiguity R4: no ambiguity check
Missing legacy material → obstruction R5: missing material treated as no match
Occurrence binding: the legacy resend is a retry; a different applied digest is a conflict R1/R2/R3
Restart, then resend, against a frozen WAL written by main@0512e9d2 (tests/fixtures/legacy_causal_wal, SHA-256 checked): resends resolve to the original submissions; no acceptance is written; the decided request does not run again; the pending one is staged from its retained envelope and decided once; a changed parent is a new act R1, R2

Full chain on the merged tree: featured 1878, default 1395 and workspace 981 tests pass. All six clippy configurations, fmt, rustdoc and the docs-model checks are clean.

Documentation

docs/spec/canonical-inbox-sequencing.md Decision 7 (Decision 1 marked refined), CHANGELOG, and the fixture README.

Local identity hardening only; not replica-scale conformance.

🤖 Generated with Claude Code

flyingrobots and others added 4 commits October 15, 2026 20:17
Under the original recipes a plain intent hashed "ingress:" || kind || bytes
and a causal intent "ingress:causal:v2\0" || kind || ...: the causal domain
begins with the plain one and the kind is any 32 bytes, so a plain intent can
reproduce a causal intent's hash input exactly (an encoding alias) and take its
ingress and submission IDs.

Envelopes now record an IngressIdentityVersion. New causal intents use the
separated recipe "echo.ingress.causal.v3\0" with length prefixes and one-byte
parent tags, and are retained as EINGR004. EINGR001-EINGR003 keep their bytes
and identity exactly and decode as Original, plain intents included.

Transition: a resend of a causal request accepted under the original recipe
resolves to that submission, and staging uses its retained envelope, but only
when the retained envelope states the same kind, bytes, parents, occurrence
and head; an alias neither counts nor reserves the request. Missing legacy
material obstructs (OriginalIngressIdentityUnverifiable), both identities of
one request are IngressIdentityAmbiguous, and new admission in the original
causal recipe is OriginalCausalIdentityNotAdmissible. Occurrence retries and
strand inheritance use the same comparison.

Witnesses include a frozen WAL written by main at 0512e9d (restart, then
resend) and a direct alias construction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tity-v3

# Conflicts:
#	crates/warp-core/src/coordinator.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-16T06:34:40.989931Z bb81443 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 36 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: flyingrobots/echo/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 580c8dd3-055f-49db-ae74-0314b94f76de
📥 Commits

Reviewing files that changed from the base of the PR and between f2b05e2 and bb81443.

📒 Files selected for processing: 12
  • CHANGELOG.md
  • crates/warp-core/src/contract_obstruction.rs
  • crates/warp-core/src/coordinator.rs
  • crates/warp-core/src/head_inbox.rs
  • crates/warp-core/src/lib.rs
  • crates/warp-core/src/trusted_runtime_host.rs
  • crates/warp-core/tests/fixtures/legacy_causal_wal/README.md
  • crates/warp-core/tests/fixtures/legacy_causal_wal/segments/segment-00000000000000000001.ecwal
  • crates/warp-core/tests/fixtures/legacy_causal_wal/writer-epochs.ecwal
  • crates/warp-core/tests/ingress_retention_codec_tests.rs
  • crates/warp-core/tests/trusted_runtime_host_loop_tests.rs
  • docs/spec/canonical-inbox-sequencing.md
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3999193b74

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/warp-core/src/coordinator.rs
Comment thread crates/warp-core/src/trusted_runtime_host.rs
Base automatically changed from feat/strand-inherits-occurrences to main October 16, 2026 06:13
flyingrobots and others added 2 commits October 15, 2026 23:13
…d names

Review of #900:

- An ingress id shared by two different requests (an alias under the
  original causal recipe) could be treated as a retry, or ingest could
  overwrite the retained request under the same submission. Both admission
  paths now refuse with RuntimeError::IngressIdentityAlias when the retained
  envelope states a different request, after the occurrence binding check so
  occurrence conflicts keep their own error.
- When a separated-form resend resolved to a submission accepted under the
  original recipe that the WAL had not recorded, the host persisted the
  caller's envelope under the original submission id, and recovery then
  failed. It now persists the retained envelope that matches the handle.

Witnesses a_retained_alias_is_refused_and_never_overwritten and
a_legacy_resolved_resend_records_the_retained_envelope each fail without
their fix and pass now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@flyingrobots
flyingrobots merged commit 4575b7f into main Oct 16, 2026
44 checks passed
@flyingrobots
flyingrobots deleted the feat/causal-identity-v3 branch October 16, 2026 06:32

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb81443dee

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +4045 to +4046
let Some(original) = envelope.original_identity_form() else {
return Ok(None);

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 Badge Reject exact legacy envelopes when retention is missing

When record-only replay has restored an original-recipe causal submission without its envelope, an exact EINGR002 delivery—or the plain alias sharing its ID—takes this None branch because original_identity_form() only handles separated envelopes. refuse_retained_alias also permits the missing envelope, so ingest can accept the caller-supplied material and install it under the historical submission ID. Return OriginalIngressIdentityUnverifiable for this exact-identity path before duplicate or staging logic can manufacture retained history.

AGENTS.md reference: AGENTS.md:L13-L18

Useful? React with 👍 / 👎.

Comment on lines +560 to 563
out.extend_from_slice(if separated {
RETAINED_INGRESS_ENVELOPE_MAGIC_V4
} else if self.occurrence.is_some() {
RETAINED_INGRESS_ENVELOPE_MAGIC_V3

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 Badge Correct the canonical retention-format documentation

This branch writes every newly constructed causal envelope, including one with a Continuum occurrence, as EINGR004, but the canonical spec still says occurrence envelopes use EINGR003 and envelopes without one use EINGR002 (docs/spec/canonical-inbox-sequencing.md:87-90), and docs/topics/WAL.md:109-112 repeats the EINGR003 claim. The public to_retained_bytes rustdoc at lines 546-555 is stale as well. Update these current-state claims to distinguish Original from SeparatedCausal, otherwise readers implementing or diagnosing WAL retention from the canonical owners are given the wrong wire format.

AGENTS.md reference: AGENTS.md:L146-L156

Useful? React with 👍 / 👎.

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.

Ingress: causal and local hash inputs alias, so a local intent can take a causal ingress ID

1 participant