Skip to content

Expose causal entity occurrences and substrate allocation - #838

Open
flyingrobots wants to merge 56 commits into
mainfrom
feat/entity-capture-intent
Open

Expose causal entity occurrences and substrate allocation#838
flyingrobots wants to merge 56 commits into
mainfrom
feat/entity-capture-intent

Conversation

@flyingrobots

@flyingrobots flyingrobots commented Aug 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Separate semantic entity subjects from substrate-owned occurrence identity.
  • Return opaque, worldline-scoped entity occurrences with causal relation and deterministic event comparison.
  • Allocate subjects from writer-local causal machinery when applications have no semantic key.
  • Bind every occurrence to its authoritative write receipt, canonical evidence, published patch, payload, causal writer, and receipt writer.
  • Reject unsafe counters, malformed payloads, forged or transplanted occurrences, payload substitutions, conflict occurrences, and writes after commit.
  • Document the distinct CLI JSON and in-process TypeScript receipt surfaces.

Validation

  • npm run test:local - 623 files passed, 1 skipped; 7,199 tests passed, 2 skipped.
  • npm run test:integration:ci - 32 files passed; 126 tests passed.
  • npm run test:v19-acceptance - 16 files passed; 129 tests passed.
  • npm run test:coverage:ci - 651 files passed, 1 skipped; 7,403 tests passed, 2 skipped; 93.01% lines against the 92.99% floor.
  • IRONCLAD M9 link and static Gates 1-8 - passed at head 776d0b4.
  • git diff --check origin/main...HEAD - passed.

Closes #837

Creating a node with properties previously required node.add followed by
property.set: two patches, and the payload patch records a self-read
because setProperty adds its subject to the observed operands. Neither
patch can carry a complete entity, so an entity's cone was never a
singleton and its footprint was an under-approximation.

intent.entity.add({ subject, properties }) states one entity and its
complete initial payload as one fact. PatchBuilder.addEntity lowers it to
a single patch of NodeAdd + NodePropSet that reads nothing and writes
exactly one fresh id. The NodeAdd in that same patch is what brings the
node into existence, so the payload depends on nothing preceding the
patch, and the syntactic footprint is exact by construction rather than a
lower bound.

The shape is enforced, not merely offered: an id that already exists in
the patch or the graph is rejected (E_PATCH_ENTITY_EXISTS), and an entity
with no payload is rejected (E_PATCH_ENTITY_EMPTY), so the empty shell
filled by later property writes is not representable.

intentFromPatch recovers the shape from persisted operations. Any other
multi-operation patch still fails hydration rather than being
reinterpreted, including a payload naming a different node and a property
that precedes the node it belongs to.

Reference: docs/READINGS_AND_OPTICS.md sections 4, 8, and 11 (the
write-path affordances the substrate should provide).

PatchBuilder.ts sat one line under the 500 LOC source-size ceiling, so
this makes room honestly rather than relaxing the gate: node and edge
content attachment now share one staging helper instead of duplicating
the asset-storage precondition, and effect id validation moved to
PatchBuilderValidation.

Additive public API on every surface, library and CLI. Recommend a minor
version bump to 19.1.0.
Review found the implementation sound but the claims stronger than the
evidence. This tightens the evidence and retracts the overclaims.

Hydration was matching on operation shape alone. A leading NodeAdd
followed by same-subject property writes is exactly what a legacy PropSet
sequence looks like, and that sequence carries the self-read entity
capture exists to eliminate, so shape-only recognition could promote a
self-reading patch into a dependency-pure claim. Recognition now also
requires the patch to declare the footprint: no reads, and exactly one
write naming the created subject. A patch that resembles the shape
without declaring the footprint falls through and fails hydration.

Duplicate property keys were silently collapsed by last-write-wins
assignment, so re-lowering a hydrated intent would not reproduce the
patch it came from. Repeated keys now fail hydration.

Property maps are built with a null prototype at both boundaries, so a
caller- or patch-supplied `__proto__`, `constructor`, or `prototype` key
stays ordinary data. Payload keys are ordered canonically at both ends,
so two payloads differing only in construction order lower to identical
operations.

Three claims were wrong and are corrected in the API docs, the CHANGELOG,
and the CLI documentation:

- "complete payload" — the substrate enforces a non-empty payload. Which
  fields make an entity complete is an application schema concern it
  cannot know.
- "the cone is a singleton" — true of the creation. `property.set` and
  `node.remove` remain public, so an immutable-entity lifetime is a law
  an application adopts, not one a constructor imposes.
- "rejects an id that already exists in the graph" — measured false on
  the lane write path. The guard reads the builder's snapshot, which is
  the host's cached state, and that is null until something materializes.
  A new integration test records the actual behaviour: a writer with no
  materialized basis re-creates the same id without complaint, and two
  writers from the same frontier are both admitted and merged, giving
  that entity a two-patch cone. Collision-resistant ids are the
  application's responsibility, and the guard is now described as
  refusing only ids the builder can see.

Adds end-to-end coverage the unit tests could not give: write through a
real Runtime lane, close it, reopen from disk, hydrate the persisted
patch back into the intent that wrote it, and prove `patchesFor` and
`materializeSlice` return exactly the creation evidence and rebuild the
entity from it, while sibling captures stay outside the cone.

Also records measured release impact rather than asserting a version.
`entity.add` is a new member of the Intent union, and although IntentKind
is not exported by name it is structurally reachable, so an exhaustive
consumer switch stops compiling with TS2345. The version choice is left
to policy.

Brings docs/READINGS_AND_OPTICS.md onto the branch, which the code,
CHANGELOG, and CLI documentation all reference. The copy in the
fix/default-checkpoint-policy worktree is untouched and still uncommitted.
The release impact was recorded as measured but unresolved. Resolving it:
this ships as a major.

entity.add adds a member to the Intent discriminated union. IntentKind is
not exported by name, but it is structurally reachable through
Intent['kind'], so a consumer that switches exhaustively over intent kinds
stops compiling with TS2345. The runtime surface is purely additive and
this repository's own consumer contract still compiles, but a measured
compile break for a real consumer pattern is a breaking change, and the
convention here is to say so rather than to reclassify it.

Adds the migration note: take the new case, or stop treating the union as
closed.

BREAKING CHANGE: `entity.add` widens the public `Intent` discriminated
union. Consumers performing exhaustive `switch` checks over
`Intent['kind']` or `Intent['descriptor']` will fail to compile until they
handle the new `entity.add` member.
The uniqueness guard was documented as a condition a writer might fail:
"a writer that has not materialized has no basis to check." On the
Runtime lane path there is no such condition. Runtime exposes lane,
fork, strand, settle and close, none of which materialize, so the
builder's basis is always null; and one intent lowers to one patch with
validation ahead of the node add, so nothing precedes the entity in its
own patch either. Both arms of the guard are unreachable there, which
means E_PATCH_ENTITY_EXISTS never fires on the only write path the CLI,
the MCP boundary and Runtime consumers have.

docs/topics/cli.md carried the sharpest instance: it documented a
failure mode for `git warp write --lane` that cannot occur.

The concurrency test asserted the frontier case without creating it.
Both writers opened and closed sequentially, so it passed for the same
reason as the no-basis test beside it, isolating one mechanism while
naming two. It now walks reachability outwards from the tightest case:
one writer re-creating an id on one lane, two writers holding a shared
frontier open simultaneously, and a writer opening only after the first
creation is durable. All three are admitted, and the second still
proves the merge and the two-dot cone.

No behaviour changes. 7,336 unit tests pass.
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added support for creating entities with explicit or automatically allocated subjects.
    • Added entity occurrences to write receipts, including identity, subject, ordering, and causal relationships.
    • Added public API types and builders for entity creation and occurrence handling.
    • Added persisted capture recovery and concurrent entity creation support.
  • Bug Fixes

    • Improved validation, receipt authenticity, lifecycle handling, canonical payload processing, and deterministic ordering.
    • Enforced safe integer limits for counters and version vectors.
  • Documentation

    • Documented entity creation, occurrence behavior, CLI usage, provenance, and the planned 20.0.0 release.
  • Breaking Changes

    • Consumers must handle the new entity.add intent kind.

Walkthrough

This PR adds entity.add intents, automatic subject allocation, dependency-pure captures, persisted intent recovery, authenticated occurrence receipts, deterministic ordering, CRDT counter validation, CLI support, public exports, repository gates, tests, and documentation.

Changes

Entity capture and occurrence flow

Layer / File(s) Summary
Entity intent contracts and payloads
src/domain/api/Intent.ts, src/domain/api/IntentBuilders.ts, bin/cli/v19/V19DomainInput.ts, src/domain/types/*, index.ts, docs/topics/cli.md, test/unit/cli/*, test/unit/domain/Intent.entity.test.ts
Adds explicit-subject and namespace-based entity.add intents. Validates and canonicalizes entity payloads. Adds public builders, CLI conversion, exports, and tests.
Entity capture and patch integration
src/domain/services/PatchBuilder.ts, src/domain/services/PatchBuilderEntity.ts, src/domain/api/IntentRuntime.ts, src/domain/api/DraftTimelineRuntime.ts, src/domain/services/PatchBuilderPropertyRuntime.ts, src/domain/services/PatchBuilderContent.ts, src/domain/services/PatchBuilderValidation.ts, test/unit/domain/services/*, test/unit/domain/IntentRuntime.entity.test.ts, test/integration/application/Runtime.entityCapture.*.test.ts
Lowers entity intents into deterministic node captures. Allocates writer-local subjects. Reconstructs persisted captures. Centralizes property and content staging.
Occurrence receipts and substrate validation
src/domain/api/EntityOccurrence.ts, src/domain/api/EntityOccurrenceRuntime.ts, src/domain/api/WriteReceipt.ts, src/domain/api/WriteRuntime.ts, bin/presenters/V19ReadingReceipt.ts, src/domain/crdt/*, src/domain/api/EvidenceRuntime.ts, src/domain/api/RetentionEvidence.ts, test/unit/domain/*, test/integration/application/Runtime.entityOccurrence.integration.test.ts
Adds immutable occurrences with causal relations and deterministic comparison. Binds occurrences to admitted entity receipts. Enforces safe CRDT counters and canonical evidence.
Documentation and repository gates
docs/READINGS_AND_OPTICS.md, docs/topics/reference.md, CHANGELOG.md, AGENTS.md, package.json, scripts/*, .github/workflows/ci.yml, vitest.config.ts, test/unit/scripts/*, test/fixtures/generated-sdk/README.md
Documents entity capture and provenance contracts. Adds machine-local-path linting, pinned CLI installation checks, documentation ratchets, type checks, and coverage configuration updates.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Poem

A rabbit sees subjects spring from each dot,
Occurrences mark every place they are caught.
Causal hops order; concurrent hops part,
Frozen receipts hold each entity’s heart.
Tests guard the trail from the start.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The changes include unrelated machine-path linting, CI installation changes, retention and evidence refactors, and other scope beyond issue #837. Move unrelated CI, machine-path policy, retention, evidence, and general refactoring changes to separate pull requests or document their direct necessity.
Docstring Coverage ⚠️ Warning Docstring coverage is 13.02% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary changes: exposing causal entity occurrences and supporting substrate subject allocation.
Description check ✅ Passed The description includes a detailed summary, issue reference, and validation results, but omits the template's Test plan and ADR checks sections.
Linked Issues check ✅ Passed The implementation satisfies issue #837 by adding allocation, occurrence receipts, causal comparison, distinct repeated writes, and supporting documentation and tests.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

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.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Release Preflight

  • package version: 19.0.2
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v19.0.2. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer self-audit findings

# Severity File Lines Finding
1 P1 High src/domain/api/DraftTimelineRuntime.ts L327-L347, L362-L371 A live strand stores and later replays the original namespace-bearing entity.addAuto Intent, so settlement allocates a second subject. After a reopen, hydration instead stores the already allocated subject. The settled entity identity therefore depends on whether the process restarted.
2 P1 High src/domain/services/PatchBuilderEntity.ts L80-L99 Auto-allocation relies on counter + 1 without a safe-integer boundary. At Number.MAX_SAFE_INTEGER, two increments return the same counter and therefore the same allegedly unique allocated subject. Reproduced locally: both increments produced 9007199254740992.
3 P3 Medium src/domain/services/PatchBuilder.ts L155-L161 addEntity omits the builder state guard before snapshot access and payload validation. A committed builder can execute caller-visible work and report an unrelated validation error instead of the required E_PATCH_ALREADY_COMMITTED.
4 P4 Low src/domain/api/EntityOccurrenceRuntime.ts, Intent.ts, IntentRuntime.ts L44; L238; L109 New domain code introduces three as assertions despite the repository's explicit “No as assertions” rule, leaving compile-time shape trust in the causal and property-map paths.

No reviewer threads exist on this Draft PR; these are self-discovered. I am continuing the audit and will handle the queue one defect at a time with RED → GREEN → VERIFY → COMMIT.

@codex Please provide a second opinion, especially on the strand settlement identity drift and counter-exhaustion boundary.

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer self-audit addendum

# Severity File Lines Finding
5 P1 High src/domain/api/EntityOccurrenceRuntime.ts L9-L13, L24-L33, L61-L69 The occurrence coordinate omits worldline scope and treats dot equality as occurrence equality. Two writes by the same Runtime writer to different top-level lanes produced distinct occurrence.id values, the same auto-allocated subject, and relationTo(...) === "same". Writer counters are lane-local, so a bare dot is not globally unique across the comparison surface.

Local reproduction result:

{"a":{"lane":"lane-a","subject":"entry:7772697465723a31"},"b":{"lane":"lane-b","subject":"entry:7772697465723a31"},"idsDistinct":true,"relation":"same"}

The fix must scope occurrence identity and causal comparison to the worldline instead of asserting cross-worldline dot equality. @codex second opinion requested.

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer self-audit addendum

# Severity File Lines Finding
6 P3 Medium src/domain/services/PatchBuilder.ts file boundary Commit a1f456567 added the required lifecycle guard but pushed the source file to 501/500 LOC. The pre-push source-size gate rejected publication.

The committed behavioral fix will not be amended. I will restore the enforced source budget in a separate mechanical commit, then repush both commits. @codex second opinion requested.

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer self-audit addendum

# Severity File Lines Finding
7 P2 High src/domain/api/WriteReceipt.ts L51-L77 Receipt validation checks only instanceof EntityOccurrence. A directly constructed occurrence with arbitrary callbacks is accepted even though it has no substrate coordinate in EntityOccurrenceRuntime's WeakMap. The receipt invariant says admitted occurrences are authoritative, but the constructor admits forgeries.
8 P4 Low docs/topics/cli.md L80-L84 The CLI guide tells readers that the returned occurrence has relationTo and compare methods. Canonical CLI JSON emits only { id, subject }; those methods exist only on the TypeScript runtime object.

These join the already published queue. @codex second opinion requested.

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer Activity Summary

# Source Severity File Commit Outcome
1 Self P1 High src/domain/api/DraftTimelineRuntime.ts 2ce87ef42 Fixed: settlement preserves the substrate-allocated subject across live and reopened paths.
2 Self P1 High src/domain/api/EntityOccurrenceRuntime.ts, src/domain/api/WriteRuntime.ts 46de620c7 Fixed: occurrence identity and comparison are scoped by worldline.
3 Self P1 High src/domain/crdt/Dot.ts, src/domain/crdt/VersionVector.ts 7dd52ecc9 Fixed: unsafe causal counters are rejected before precision loss or duplicate allocation.
4 Self P3 Medium src/domain/services/PatchBuilder.ts a1f456567 Fixed: committed builders reject entity writes before snapshot or payload work.
5 Self P3 Medium src/domain/services/PatchBuilder.ts 28e733251 Fixed: source budget restored to the enforced 500-line ceiling without amending history.
6 Self P2 High src/domain/api/WriteReceipt.ts, src/domain/api/EntityOccurrenceRuntime.ts 1d15989d8 Fixed: receipts reject constructed occurrences lacking a substrate-issued coordinate.
7 Self P4 Low entity capture domain paths 87dfd8476 Fixed: removed all three new type assertions and added an AST ratchet.
8 Self P4 Low docs/topics/cli.md 25f605785 Fixed: CLI JSON and in-process TypeScript occurrence surfaces are distinguished.

Every item followed an isolated RED → GREEN → VERIFY → COMMIT cycle. No PR-originated review threads existed, so no thread-resolution mutation was applicable.

Local exact-head evidence:

  • npm run test:local: 621 files, 7,178 tests passed; 1 file and 2 tests skipped by design.
  • npm run test:integration:ci: 32 files, 126 tests passed.
  • npm run test:coverage:ci: passed.
  • npm run test:v19-acceptance: 16 files, 129 tests passed.
  • Pre-push IRONCLAD M9: link check and static Gates 1–8 passed; Gate 9 intentionally skipped only because the complete stable suite had already passed.
  • Published head: 25f60578566145dd805bb3f0f0813a31649a07fe.

Hosted checks are running against that exact head.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Release Preflight

  • package version: 19.0.2
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v19.0.2. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

@flyingrobots
flyingrobots marked this pull request as ready for review August 3, 2026 23:17

@coderabbitai coderabbitai 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.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/domain/api/Intent.ts`:
- Around line 196-232: Update entityIdentity to determine hasSubject and
hasNamespace from whether fields.subject and fields.namespace are not undefined,
rather than using key-presence checks. Preserve the exactly-one-identity
validation and existing non-empty string validation so an explicitly undefined
optional identity is treated as absent.

In `@src/domain/api/WriteReceipt.ts`:
- Around line 52-67: The admitted-outcome check in validateOccurrence must
explicitly accept only derived and plural, rather than treating every
non-obstruction outcome as admitted; update src/domain/api/WriteReceipt.ts lines
52-67 accordingly. Add a test in test/unit/domain/ReceiptOutcome.test.ts lines
120-133 covering an entity.add receipt with a conflict outcome, asserting the
intended behavior when the occurrence is present and absent.

In `@src/domain/api/WriteRuntime.ts`:
- Around line 192-205: Update the publication validation in the entity-write
flow around the leading NodeAdd check to hydrate the complete patch as an
entity.add capture before calling createEntityOccurrence. Reject patches that do
not hydrate as entity.add, and when a subject was supplied require the recovered
subject to match it; use WarpError code E_WRITE_ENTITY_OCCURRENCE for all
mismatches while preserving the existing occurrence creation path for valid
publications.

In `@src/domain/crdt/Dot.ts`:
- Around line 86-87: Update the validation error in Dot’s counter check to say
“counter must be a positive safe integer,” and update the corresponding message
assertions in Dot tests to match the new wording.

In `@src/domain/services/PatchBuilderEntity.ts`:
- Around line 126-135: Validate properties in the entity payload handling before
calling Object.entries: accept only plain objects or null-prototype records, and
reject strings, arrays, class instances, and other non-record values with the
existing PatchError pattern. Update the surrounding logic in PatchBuilderEntity
to perform this boundary validation while preserving the empty-record check and
deterministic key sorting for valid payloads.

In `@test/unit/cli/v19-entity-intent.test.ts`:
- Around line 10-15: Move the test named “documents the JSON and TypeScript
occurrence surfaces separately” out of the intent-parsing suite into a dedicated
documentation test file or suite. Keep its existing docs/topics/cli.md
assertions there, and leave the intentFromValue/intentFromText tests focused
only on intent parsing behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 70c61036-5767-4881-a064-392796bf1d2d

📥 Commits

Reviewing files that changed from the base of the PR and between 7ed1fd2 and 25f6057.

📒 Files selected for processing (37)
  • CHANGELOG.md
  • bin/cli/v19/V19DomainInput.ts
  • bin/presenters/V19ReadingReceipt.ts
  • docs/READINGS_AND_OPTICS.md
  • docs/topics/cli.md
  • docs/topics/reference.md
  • index.ts
  • src/domain/api/DraftTimelineRuntime.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • src/domain/api/Intent.ts
  • src/domain/api/IntentBuilders.ts
  • src/domain/api/IntentRuntime.ts
  • src/domain/api/WriteReceipt.ts
  • src/domain/api/WriteRuntime.ts
  • src/domain/crdt/Dot.ts
  • src/domain/crdt/VersionVector.ts
  • src/domain/services/PatchBuilder.ts
  • src/domain/services/PatchBuilderContent.ts
  • src/domain/services/PatchBuilderEntity.ts
  • src/domain/services/PatchBuilderValidation.ts
  • test/integration/application/Runtime.entityCapture.concurrent.test.ts
  • test/integration/application/Runtime.entityCapture.integration.test.ts
  • test/integration/application/Runtime.entityOccurrence.integration.test.ts
  • test/type-check/v19-subpaths.ts
  • test/unit/cli/v19-entity-intent.test.ts
  • test/unit/domain/EntityOccurrence.test.ts
  • test/unit/domain/Intent.entity.test.ts
  • test/unit/domain/IntentRuntime.entity.test.ts
  • test/unit/domain/ReceiptOutcome.test.ts
  • test/unit/domain/WriteRuntime.test.ts
  • test/unit/domain/crdt/Dot.test.ts
  • test/unit/domain/crdt/VersionVector.test.ts
  • test/unit/domain/services/PatchBuilder.entity.test.ts
  • test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
  • test/unit/scripts/v19-public-api-boundary.test.ts
  • vitest.config.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Do not use direct imports from src/infrastructure/** in src/domain/** or src/ports/**; depend on a port instead.
Do not use direct Node built-ins in src/domain/** or src/ports/**; use a port instead.

Files:

  • index.ts
  • test/unit/scripts/v19-public-api-boundary.test.ts
  • test/unit/domain/crdt/VersionVector.test.ts
  • test/unit/domain/crdt/Dot.test.ts
  • bin/presenters/V19ReadingReceipt.ts
  • src/domain/api/DraftTimelineRuntime.ts
  • vitest.config.ts
  • src/domain/crdt/Dot.ts
  • test/unit/domain/ReceiptOutcome.test.ts
  • src/domain/crdt/VersionVector.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • test/unit/domain/EntityOccurrence.test.ts
  • test/unit/cli/v19-entity-intent.test.ts
  • test/integration/application/Runtime.entityCapture.integration.test.ts
  • src/domain/services/PatchBuilderValidation.ts
  • src/domain/services/PatchBuilderContent.ts
  • test/unit/domain/WriteRuntime.test.ts
  • src/domain/api/WriteRuntime.ts
  • test/unit/domain/IntentRuntime.entity.test.ts
  • src/domain/api/IntentBuilders.ts
  • test/unit/domain/services/PatchBuilder.entity.test.ts
  • src/domain/services/PatchBuilderEntity.ts
  • test/type-check/v19-subpaths.ts
  • test/unit/domain/Intent.entity.test.ts
  • src/domain/services/PatchBuilder.ts
  • test/integration/application/Runtime.entityOccurrence.integration.test.ts
  • src/domain/api/IntentRuntime.ts
  • src/domain/api/Intent.ts
  • test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
  • src/domain/api/WriteReceipt.ts
  • bin/cli/v19/V19DomainInput.ts
  • test/integration/application/Runtime.entityCapture.concurrent.test.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx,js,jsx}: Do not introduce any, as any, as unknown as, unknown (outside adapters), Record<string, unknown> (outside adapters), *Like placeholder types, JSON.parse/JSON.stringify (outside adapters), fetch (outside adapters), process.env (outside adapters), @ts-ignore, or z.any() in core code; use validated boundary models and ports instead.
Use constructor-injected ports for external capabilities; do not rely on ambient dependencies for I/O, clocks, persistence, or entropy.
Do not create utils.ts, helpers.ts, misc.ts, or common.ts; name files after the actual concept they model.
Prefer one file per class, type, or object; if a file accumulates peer concepts, split it.
Keep helper corridors, fake shape trust, transitional duplication, and compile-time theater out of the codebase; runtime-honest TypeScript must reflect actual behavior.
No enum usage; prefer runtime-backed domain forms and unions.
Do not use boolean trap parameters; prefer named option objects or separate methods.
Avoid magic strings or numbers when a named constant should exist.
Keep domain bytes as Uint8Array; Buffer belongs in infrastructure adapters.

Files:

  • src/domain/api/DraftTimelineRuntime.ts
  • src/domain/crdt/Dot.ts
  • src/domain/crdt/VersionVector.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • src/domain/services/PatchBuilderValidation.ts
  • src/domain/services/PatchBuilderContent.ts
  • src/domain/api/WriteRuntime.ts
  • src/domain/api/IntentBuilders.ts
  • src/domain/services/PatchBuilderEntity.ts
  • src/domain/services/PatchBuilder.ts
  • src/domain/api/IntentRuntime.ts
  • src/domain/api/Intent.ts
  • src/domain/api/WriteReceipt.ts
src/domain/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/domain/**/*.{ts,tsx,js,jsx}: In src/domain/**, do not use Date.now(), new Date(), Date(), performance.now(), Math.random(), crypto.randomUUID(), crypto.getRandomValues(), setTimeout, setInterval, raw new Error(...)/new TypeError(...), or direct imports from Node built-ins; time, entropy, and external capabilities must enter through ports or parameters, and domain errors should extend WarpError.
Construct domain objects only in core when doing so establishes validated runtime truth; do not build infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core.
Prefer discriminated unions and explicit result types instead of boolean-flag bags, and model expected failures as return values rather than exceptions.
src/domain/ must not import host APIs or Node-specific globals; hexagonal architecture boundaries are mandatory.
Domain code must not use the wall clock directly; time must enter through a port or parameter.

Files:

  • src/domain/api/DraftTimelineRuntime.ts
  • src/domain/crdt/Dot.ts
  • src/domain/crdt/VersionVector.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • src/domain/services/PatchBuilderValidation.ts
  • src/domain/services/PatchBuilderContent.ts
  • src/domain/api/WriteRuntime.ts
  • src/domain/api/IntentBuilders.ts
  • src/domain/services/PatchBuilderEntity.ts
  • src/domain/services/PatchBuilder.ts
  • src/domain/api/IntentRuntime.ts
  • src/domain/api/Intent.ts
  • src/domain/api/WriteReceipt.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use explicit domain concepts with validated constructors, Object.freeze, and instanceof dispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.

Files:

  • src/domain/api/DraftTimelineRuntime.ts
  • src/domain/crdt/Dot.ts
  • src/domain/crdt/VersionVector.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • src/domain/services/PatchBuilderValidation.ts
  • src/domain/services/PatchBuilderContent.ts
  • src/domain/api/WriteRuntime.ts
  • src/domain/api/IntentBuilders.ts
  • src/domain/services/PatchBuilderEntity.ts
  • src/domain/services/PatchBuilder.ts
  • src/domain/api/IntentRuntime.ts
  • src/domain/api/Intent.ts
  • src/domain/api/WriteReceipt.ts
🧠 Learnings (1)
📚 Learning: 2026-03-08T19:50:17.519Z
Learnt from: flyingrobots
Repo: git-stunts/git-warp PR: 65
File: CHANGELOG.md:88-88
Timestamp: 2026-03-08T19:50:17.519Z
Learning: Follow the Keep a Changelog convention for CHANGELOG.md. Allow duplicate subheadings across versions (e.g., '### Added', '### Fixed'). Configure markdownlint MD024 with {"siblings_only": true} to avoid cross-version false positives.

Applied to files:

  • CHANGELOG.md
🪛 LanguageTool
docs/READINGS_AND_OPTICS.md

[style] ~284-~284: Consider an alternative for the overused word “exactly”.
Context: ...has no history,"_ and that ambiguity is exactly what let the Think census (§12) go unno...

(EXACTLY_PRECISELY)

🔇 Additional comments (36)
CHANGELOG.md (1)

10-110: LGTM!

src/domain/api/Intent.ts (2)

5-11: LGTM!

Also applies to: 39-45, 59-66, 103-109, 141-143


234-258: LGTM!

src/domain/api/IntentBuilders.ts (1)

2-4: LGTM!

Also applies to: 14-17, 32-35

bin/cli/v19/V19DomainInput.ts (1)

59-67: LGTM!

Also applies to: 103-131

test/unit/cli/v19-entity-intent.test.ts (1)

17-81: LGTM!

test/unit/domain/Intent.entity.test.ts (1)

1-154: LGTM!

test/type-check/v19-subpaths.ts (1)

9-10: LGTM!

Also applies to: 47-50, 62-66, 91-98

src/domain/api/EntityOccurrence.ts (1)

1-63: LGTM!

src/domain/api/EntityOccurrenceRuntime.ts (1)

1-125: LGTM!

src/domain/api/WriteReceipt.ts (1)

8-9: LGTM!

Also applies to: 18-18, 29-29, 44-49, 69-79

test/unit/domain/ReceiptOutcome.test.ts (1)

5-12: LGTM!

Also applies to: 135-204, 250-259

docs/topics/cli.md (1)

42-87: LGTM!

index.ts (1)

46-49: LGTM!

docs/topics/reference.md (1)

39-62: LGTM!

test/unit/scripts/v19-public-api-boundary.test.ts (1)

14-15: LGTM!

test/integration/application/Runtime.entityCapture.integration.test.ts (1)

1-117: LGTM!

test/integration/application/Runtime.entityCapture.concurrent.test.ts (1)

1-145: LGTM!

test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts (1)

1-40: LGTM!

vitest.config.ts (1)

33-33: LGTM!

src/domain/services/PatchBuilderEntity.ts (1)

65-99: LGTM!

src/domain/services/PatchBuilder.ts (1)

24-40: LGTM!

Also applies to: 255-259, 313-318, 347-352

src/domain/api/IntentRuntime.ts (1)

3-3: LGTM!

Also applies to: 16-16, 33-146, 232-239

src/domain/api/DraftTimelineRuntime.ts (1)

328-346: LGTM!

test/unit/domain/IntentRuntime.entity.test.ts (1)

1-198: LGTM!

test/unit/domain/services/PatchBuilder.entity.test.ts (1)

1-190: LGTM!

bin/presenters/V19ReadingReceipt.ts (1)

51-56: LGTM!

test/integration/application/Runtime.entityOccurrence.integration.test.ts (1)

1-148: LGTM!

test/unit/domain/EntityOccurrence.test.ts (1)

1-169: LGTM!

src/domain/crdt/Dot.ts (1)

69-76: LGTM!

src/domain/crdt/VersionVector.ts (1)

39-41: LGTM!

Also applies to: 95-97, 124-124

src/domain/services/PatchBuilderContent.ts (1)

6-6: LGTM!

Also applies to: 27-30, 41-56

docs/READINGS_AND_OPTICS.md (1)

1-503: LGTM!

test/unit/domain/crdt/Dot.test.ts (1)

291-294: LGTM!

test/unit/domain/crdt/VersionVector.test.ts (1)

64-72: LGTM!

Also applies to: 359-360

src/domain/services/PatchBuilderValidation.ts (1)

27-29: 🗄️ Data Integrity & Integration

No change needed: @warp/effect: is documented as the reserved node ID prefix, and existing regression coverage exercises emitEffect under that namespace.

Comment thread src/domain/api/Intent.ts
Comment thread src/domain/api/WriteReceipt.ts
Comment thread src/domain/api/WriteRuntime.ts
Comment thread src/domain/crdt/Dot.ts Outdated
Comment thread src/domain/services/PatchBuilderEntity.ts Outdated
Comment thread test/unit/cli/v19-entity-intent.test.ts Outdated
@flyingrobots

Copy link
Copy Markdown
Member Author

@codex second opinion requested on one additional closure-gate finding.

# Severity File Finding Required correction
38 P2 test/unit/scripts/v18-to-v19-finalization.test.ts#L114 The real-Git oversized-state proof passed alone under coverage in 58.63s but inherits a 60s timeout; the full coverage run timed out. That margin makes the gate scheduler-dependent. Give this explicitly heavyweight proof a bounded per-test timeout, keep its semantics unchanged, then rerun the focused covered test and the complete coverage suite.

The production path is untouched by PR #838; this is deterministic closure-test infrastructure.

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer Activity Summary — continuation

Audited and published head: c6ad3d2969adcf41b717d11d7df2b814e0a24e68

Issues 1–25 and their commits remain recorded in the first Activity Summary. This continuation closes every additional finding discovered during the renewed deep audit and closure gates.

# Severity Source Primary file Commit Outcome
26 P1 Self src/domain/api/EntityOccurrence.ts d4147d516 Occurrence authority is owned by the occurrence object; hidden WeakMap state and callback injection removed.
27 P1 Self src/domain/api/EvidenceRuntime.ts 781b0f15d Canonical evidence is recognized structurally; process-local WeakSet membership removed.
28 P3 Self src/domain/services/PatchBuilderEntity.ts 51c75fe6d False “complete payload” claims removed; non-empty substrate payload invariant retained.
29 P1 Self docs/READINGS_AND_OPTICS.md 4889004e8 Declared footprint shape is no longer misrepresented as semantic dependency completeness.
30 P1 Self src/domain/crdt/Dot.ts 3162c640f Dot decoding rejects partial/noncanonical counters instead of aliasing identities.
31 P1 Self src/domain/crdt/VersionVector.ts 79a112ea2, 9b89f5c62 Prototype-shaped writer IDs survive deterministic serialization and explicit-key access.
32 P0 Self src/domain/api/WriteRuntime.ts dc6670919 Auto-allocated publications must retain the subject derived from namespace and authoritative Dot.
33 P4 Self 35 changed TS/Markdown files a78b91feb Changed source satisfies canonical formatting; generated-reference exception corrected by #37.
34 P1 Self src/domain/services/PatchBuilder.ts d37bf014e Property/content lowering moved to a coherent collaborator; source-size gate restored.
35 P1 Self src/domain/services/PatchBuilder.ts 989c56f62 Permissive values use method generics; three detached unknown quarantines eliminated.
36 P1 Self src/domain/api/EntityOccurrence.ts 0b26f2e3c Root declarations no longer pull internal EventId/publication-hash vocabulary into the opaque occurrence surface.
37 P2 Self docs/topics/reference.md 605f22143 Owning generator restored canonical source-backed reference bytes.
38 P2 Self test/unit/scripts/v18-to-v19-finalization.test.ts c6ad3d296 Heavy real-Git coverage proof has bounded 120s headroom; full coverage no longer scheduler-dependent.

Closure evidence

  • 38 of 38 total audit items fixed; one focused commit per issue, with feat: Trust Ref Foundation (Phase A) #31’s no-amend compile correction in a follow-up commit.
  • Pre-push IRONCLAD Gates 0–9 passed at the exact published head.
  • All static gates passed: ESLint, ratchets, anti-sludge, Semgrep, contamination/quarantine, Markdown/Mermaid/code samples, docs topology/reference, type policy, consumer declarations, root surface, generated vocabulary/capability artifacts, SDK fixture byte check, and 223-link scan.
  • npm run test:local: 625 files passed, 1 skipped; 7,229 tests passed, 2 skipped.
  • npm run test:integration:ci: 32 files and 126 tests passed.
  • npm run test:v19-acceptance: 16 files and 129 tests passed.
  • BATS: 8 of 8 CLI scenarios passed.
  • Generated SDK packed-consumer smoke passed.
  • npm run test:coverage:ci: 652 files passed, 1 skipped; 7,430 tests passed, 2 skipped; 93.01% line coverage.
  • Worktree clean before push; branch advanced by a normal non-force push from 776d0b404 to c6ad3d296.

The technical queue is closed. The merge gate remains subject to a fresh exact-head CI/review/thread census and the required two approvals.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Release Preflight

  • package version: 19.0.2
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v19.0.2. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
bin/cli/v19/V19DomainInput.ts (1)

13-21: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Preserve __proto__ payloads through the CLI parser.

Zod 3.24.1 records skip an own __proto__ key while assembling object output. If the CLI accepts entity JSON with both safe and __proto__, entityIntentFrom receives only safe, and the persisted capture differs from the submitted capture. Use a boundary decoder that preserves own keys in null-prototype objects, or reject these keys before parsing. Add raw-JSON regression cases for top-level and nested __proto__ values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bin/cli/v19/V19DomainInput.ts` around lines 13 - 21, Update JSON_INPUT_SCHEMA
parsing to preserve own __proto__ keys in both top-level and nested objects,
preferably by decoding object records into null-prototype objects before
entityIntentFrom receives them; alternatively reject __proto__ keys at the CLI
boundary. Add raw-JSON regression coverage for top-level and nested __proto__
values, ensuring persisted captures match submitted JSON.
src/domain/types/PropValue.ts (1)

174-194: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the duplicated record-equality body.

propValueRecordsEqual and entityCapturePayloadsEqual in src/domain/types/EntityCapturePayload.ts (lines 16-36) contain byte-identical logic. Both define payload identity semantics that requirePublishedEntityPayload relies on for authenticity checks. If one copy changes, the two identity rules diverge silently.

Let entityCapturePayloadsEqual delegate to the record comparison exported from this module.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/domain/types/PropValue.ts` around lines 174 - 194, Export the existing
propValueRecordsEqual function from PropValue.ts so it can be reused, then
update entityCapturePayloadsEqual in EntityCapturePayload.ts to delegate to that
shared record-comparison implementation. Remove the duplicated equality logic
while preserving the current identity semantics used by
requirePublishedEntityPayload.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@bin/cli/v19/V19DomainInput.ts`:
- Line 11: Remove the duplicate JsonInput type alias in V19DomainInput.ts,
keeping exactly one declaration of JsonInput so the module type-checks
successfully.

In `@src/domain/api/EntityOccurrence.ts`:
- Around line 68-79: Remove the self-comparison `issued.subject ===
occurrence.subject` from `EntityOccurrence.requireReceiptBinding`, since
`#requireIssued` returns the same occurrence and the check cannot validate a
receipt binding. Keep the existing evidence, intent, worldline, receipt-writer,
and return behavior unchanged.

In `@src/domain/api/EvidenceRuntime.ts`:
- Around line 201-209: Update isCanonicalRetentionEvidence to validate policy,
reachability, and rootKind using the existing RetentionEvidence field-validation
logic before accepting the object, while preserving the current frozen, key-set,
and witness checks. Add a regression test covering a frozen object with
RetentionEvidence.prototype, a valid witness, and an invalid retention field,
ensuring it is rejected and normal construction/validation proceeds.

In `@test/unit/cli/v19-entity-intent.test.ts`:
- Around line 56-75: Add a test in the entity.add intent cases that calls
intentFromValue with only kind and a non-empty properties record, omitting both
subject and namespace. Assert that entityIntentFrom rejects this no-identity
descriptor, while leaving the existing empty-subject and supplied/allocated
identity tests unchanged.

---

Outside diff comments:
In `@bin/cli/v19/V19DomainInput.ts`:
- Around line 13-21: Update JSON_INPUT_SCHEMA parsing to preserve own __proto__
keys in both top-level and nested objects, preferably by decoding object records
into null-prototype objects before entityIntentFrom receives them; alternatively
reject __proto__ keys at the CLI boundary. Add raw-JSON regression coverage for
top-level and nested __proto__ values, ensuring persisted captures match
submitted JSON.

In `@src/domain/types/PropValue.ts`:
- Around line 174-194: Export the existing propValueRecordsEqual function from
PropValue.ts so it can be reused, then update entityCapturePayloadsEqual in
EntityCapturePayload.ts to delegate to that shared record-comparison
implementation. Remove the duplicated equality logic while preserving the
current identity semantics used by requirePublishedEntityPayload.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 982263ae-5c67-488a-9309-5fc7366f305c

📥 Commits

Reviewing files that changed from the base of the PR and between 45a2c01 and c6ad3d2.

📒 Files selected for processing (42)
  • CHANGELOG.md
  • bin/cli/v19/V19DomainInput.ts
  • bin/presenters/V19ReadingReceipt.ts
  • docs/READINGS_AND_OPTICS.md
  • docs/topics/cli.md
  • src/domain/api/DraftTimelineRuntime.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • src/domain/api/EvidenceRuntime.ts
  • src/domain/api/Intent.ts
  • src/domain/api/IntentRuntime.ts
  • src/domain/api/WriteReceipt.ts
  • src/domain/api/WriteRuntime.ts
  • src/domain/crdt/Dot.ts
  • src/domain/crdt/VersionVector.ts
  • src/domain/services/PatchBuilder.ts
  • src/domain/services/PatchBuilderContent.ts
  • src/domain/services/PatchBuilderEntity.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • src/domain/services/PatchBuilderValidation.ts
  • src/domain/types/EntityCapturePayload.ts
  • src/domain/types/PropValue.ts
  • test/integration/application/Runtime.entityCapture.concurrent.test.ts
  • test/type-check/v19-subpaths.ts
  • test/unit/cli/v19-entity-intent.test.ts
  • test/unit/domain/EntityOccurrence.test.ts
  • test/unit/domain/EvidenceRuntime.test.ts
  • test/unit/domain/Intent.entity.test.ts
  • test/unit/domain/IntentRuntime.entity.test.ts
  • test/unit/domain/ReceiptOutcome.test.ts
  • test/unit/domain/WriteRuntime.test.ts
  • test/unit/domain/crdt/Dot.test.ts
  • test/unit/domain/crdt/VersionVector.test.ts
  • test/unit/domain/services/PatchBuilder.commit.test.ts
  • test/unit/domain/services/PatchBuilder.entity.test.ts
  • test/unit/domain/types/EntityCapturePayload.test.ts
  • test/unit/infrastructure/adapters/WesleyDotCodecAdapter.test.ts
  • test/unit/scripts/cli-entity-documentation.test.ts
  • test/unit/scripts/entity-capture-doctrine.test.ts
  • test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
  • test/unit/scripts/v18-to-v19-finalization.test.ts
  • vitest.config.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: preflight
  • GitHub Check: v19 base/head performance
  • GitHub Check: test-node (22)
  • GitHub Check: coverage-threshold
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Do not use direct imports from src/infrastructure/** in src/domain/** or src/ports/**; depend on a port instead.
Do not use direct Node built-ins in src/domain/** or src/ports/**; use a port instead.

Files:

  • test/unit/domain/EvidenceRuntime.test.ts
  • test/integration/application/Runtime.entityCapture.concurrent.test.ts
  • test/unit/scripts/entity-capture-doctrine.test.ts
  • test/unit/infrastructure/adapters/WesleyDotCodecAdapter.test.ts
  • test/unit/cli/v19-entity-intent.test.ts
  • test/unit/domain/Intent.entity.test.ts
  • src/domain/crdt/Dot.ts
  • test/type-check/v19-subpaths.ts
  • bin/presenters/V19ReadingReceipt.ts
  • src/domain/types/PropValue.ts
  • test/unit/domain/services/PatchBuilder.commit.test.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • test/unit/domain/EntityOccurrence.test.ts
  • vitest.config.ts
  • test/unit/domain/crdt/Dot.test.ts
  • src/domain/api/WriteReceipt.ts
  • src/domain/api/IntentRuntime.ts
  • test/unit/domain/IntentRuntime.entity.test.ts
  • test/unit/domain/ReceiptOutcome.test.ts
  • test/unit/scripts/v18-to-v19-finalization.test.ts
  • src/domain/api/EvidenceRuntime.ts
  • src/domain/api/Intent.ts
  • src/domain/types/EntityCapturePayload.ts
  • src/domain/services/PatchBuilderContent.ts
  • test/unit/domain/WriteRuntime.test.ts
  • src/domain/api/DraftTimelineRuntime.ts
  • test/unit/domain/types/EntityCapturePayload.test.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/WriteRuntime.ts
  • src/domain/services/PatchBuilderEntity.ts
  • test/unit/domain/services/PatchBuilder.entity.test.ts
  • test/unit/scripts/cli-entity-documentation.test.ts
  • test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
  • src/domain/services/PatchBuilderValidation.ts
  • src/domain/crdt/VersionVector.ts
  • bin/cli/v19/V19DomainInput.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • test/unit/domain/crdt/VersionVector.test.ts
  • src/domain/services/PatchBuilder.ts
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx,js,jsx}: Do not introduce any, as any, as unknown as, unknown (outside adapters), Record<string, unknown> (outside adapters), *Like placeholder types, JSON.parse/JSON.stringify (outside adapters), fetch (outside adapters), process.env (outside adapters), @ts-ignore, or z.any() in core code; use validated boundary models and ports instead.
Use constructor-injected ports for external capabilities; do not rely on ambient dependencies for I/O, clocks, persistence, or entropy.
Do not create utils.ts, helpers.ts, misc.ts, or common.ts; name files after the actual concept they model.
Prefer one file per class, type, or object; if a file accumulates peer concepts, split it.
Keep helper corridors, fake shape trust, transitional duplication, and compile-time theater out of the codebase; runtime-honest TypeScript must reflect actual behavior.
No enum usage; prefer runtime-backed domain forms and unions.
Do not use boolean trap parameters; prefer named option objects or separate methods.
Avoid magic strings or numbers when a named constant should exist.
Keep domain bytes as Uint8Array; Buffer belongs in infrastructure adapters.

Files:

  • src/domain/crdt/Dot.ts
  • src/domain/types/PropValue.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • src/domain/api/WriteReceipt.ts
  • src/domain/api/IntentRuntime.ts
  • src/domain/api/EvidenceRuntime.ts
  • src/domain/api/Intent.ts
  • src/domain/types/EntityCapturePayload.ts
  • src/domain/services/PatchBuilderContent.ts
  • src/domain/api/DraftTimelineRuntime.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/WriteRuntime.ts
  • src/domain/services/PatchBuilderEntity.ts
  • src/domain/services/PatchBuilderValidation.ts
  • src/domain/crdt/VersionVector.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • src/domain/services/PatchBuilder.ts
src/domain/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/domain/**/*.{ts,tsx,js,jsx}: In src/domain/**, do not use Date.now(), new Date(), Date(), performance.now(), Math.random(), crypto.randomUUID(), crypto.getRandomValues(), setTimeout, setInterval, raw new Error(...)/new TypeError(...), or direct imports from Node built-ins; time, entropy, and external capabilities must enter through ports or parameters, and domain errors should extend WarpError.
Construct domain objects only in core when doing so establishes validated runtime truth; do not build infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core.
Prefer discriminated unions and explicit result types instead of boolean-flag bags, and model expected failures as return values rather than exceptions.
src/domain/ must not import host APIs or Node-specific globals; hexagonal architecture boundaries are mandatory.
Domain code must not use the wall clock directly; time must enter through a port or parameter.

Files:

  • src/domain/crdt/Dot.ts
  • src/domain/types/PropValue.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • src/domain/api/WriteReceipt.ts
  • src/domain/api/IntentRuntime.ts
  • src/domain/api/EvidenceRuntime.ts
  • src/domain/api/Intent.ts
  • src/domain/types/EntityCapturePayload.ts
  • src/domain/services/PatchBuilderContent.ts
  • src/domain/api/DraftTimelineRuntime.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/WriteRuntime.ts
  • src/domain/services/PatchBuilderEntity.ts
  • src/domain/services/PatchBuilderValidation.ts
  • src/domain/crdt/VersionVector.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • src/domain/services/PatchBuilder.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use explicit domain concepts with validated constructors, Object.freeze, and instanceof dispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.

Files:

  • src/domain/crdt/Dot.ts
  • src/domain/types/PropValue.ts
  • src/domain/api/EntityOccurrenceRuntime.ts
  • src/domain/api/WriteReceipt.ts
  • src/domain/api/IntentRuntime.ts
  • src/domain/api/EvidenceRuntime.ts
  • src/domain/api/Intent.ts
  • src/domain/types/EntityCapturePayload.ts
  • src/domain/services/PatchBuilderContent.ts
  • src/domain/api/DraftTimelineRuntime.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/WriteRuntime.ts
  • src/domain/services/PatchBuilderEntity.ts
  • src/domain/services/PatchBuilderValidation.ts
  • src/domain/crdt/VersionVector.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • src/domain/services/PatchBuilder.ts
🧠 Learnings (1)
📚 Learning: 2026-03-08T19:50:17.519Z
Learnt from: flyingrobots
Repo: git-stunts/git-warp PR: 65
File: CHANGELOG.md:88-88
Timestamp: 2026-03-08T19:50:17.519Z
Learning: Follow the Keep a Changelog convention for CHANGELOG.md. Allow duplicate subheadings across versions (e.g., '### Added', '### Fixed'). Configure markdownlint MD024 with {"siblings_only": true} to avoid cross-version false positives.

Applied to files:

  • CHANGELOG.md
🔇 Additional comments (45)
src/domain/services/PatchBuilderPropertyRuntime.ts (2)

100-144: 🩺 Stability & Availability

Verify post-commit protection after content staging.

attachNodeContent and attachEdgeContent append operations and asset handles after await stageContentAttachment(...). If PatchBuilder.commit() completes while staging is pending, these methods can mutate a committed patch. Serialize pending attachment work in commit(), or check the lifecycle again before lowering the attachment.

#!/bin/bash
set -euo pipefail

ast-grep outline src/domain/services/PatchBuilder.ts --items all
rg -n -C 12 '\b(attachContent|attachNodeContent|attachEdgeContent|commit|_assertNotCommitted|_contentAssets|_ops)\b' \
  src/domain/services/PatchBuilder.ts \
  src/domain/services/PatchBuilderPropertyRuntime.ts

1-98: LGTM!

Also applies to: 119-126, 146-222

src/domain/services/PatchBuilderContent.ts (1)

27-31: LGTM!

Also applies to: 48-58, 60-112

src/domain/services/PatchBuilderValidation.ts (1)

17-31: LGTM!

Also applies to: 66-99, 114-157

test/unit/domain/services/PatchBuilder.commit.test.ts (1)

11-11: LGTM!

Also applies to: 86-86, 112-118, 179-179

src/domain/api/EntityOccurrence.ts (1)

1-27: LGTM!

Also applies to: 37-65, 81-120, 122-178, 180-224

src/domain/api/EntityOccurrenceRuntime.ts (1)

4-7: LGTM!

Also applies to: 27-53

src/domain/api/WriteReceipt.ts (1)

49-55: LGTM!

Also applies to: 57-77, 79-90

src/domain/api/WriteRuntime.ts (1)

26-26: LGTM!

Also applies to: 190-215, 217-229, 247-254

bin/presenters/V19ReadingReceipt.ts (1)

15-17: LGTM!

Also applies to: 46-56, 70-75, 95-95, 106-125, 179-198

test/unit/domain/EntityOccurrence.test.ts (1)

83-87: LGTM!

Also applies to: 98-111, 113-176

test/unit/domain/ReceiptOutcome.test.ts (1)

9-31: LGTM!

Also applies to: 136-196, 215-215, 271-302, 353-398

test/unit/domain/WriteRuntime.test.ts (2)

345-359: 📐 Maintainability & Code Quality | 💤 Low value

Confirm the declared type of Patch.writes matches the string[] | undefined parameter.

Line 348 defaults writes to patch.writes, and line 363 assigns patch.writes?.map(...) into the same parameter type. If Patch declares writes as readonly string[] | undefined, the default assignment does not type-check. Widen the parameter to readonly string[] | undefined in that case.

#!/bin/bash
set -euo pipefail

fd -t f 'Patch.ts' src/domain/types --exec ast-grep outline {} --items all
rg -n -C 3 '\bwrites\b' src/domain/types/Patch.ts

57-98: LGTM!

Also applies to: 100-157, 159-206, 361-365, 380-385, 397-408

vitest.config.ts (1)

12-13: LGTM!

Also applies to: 25-25

test/unit/scripts/cli-entity-documentation.test.ts (1)

8-8: LGTM!

test/unit/scripts/entity-capture-doctrine.test.ts (1)

1-44: LGTM!

test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts (1)

10-11: LGTM!

Also applies to: 24-76, 78-108, 122-129

test/unit/scripts/v18-to-v19-finalization.test.ts (1)

25-25: LGTM!

Also applies to: 115-166

src/domain/crdt/Dot.ts (1)

60-60: LGTM!

Also applies to: 71-89, 127-127, 150-157

src/domain/crdt/VersionVector.ts (1)

95-97: LGTM!

Also applies to: 124-124, 141-158, 175-177, 228-230

src/domain/api/EvidenceRuntime.ts (1)

32-32: LGTM!

Also applies to: 261-303

test/unit/domain/crdt/Dot.test.ts (1)

2-3: LGTM!

Also applies to: 35-60, 187-202, 315-320

test/unit/domain/crdt/VersionVector.test.ts (1)

63-73: LGTM!

Also applies to: 324-340, 375-381

test/unit/infrastructure/adapters/WesleyDotCodecAdapter.test.ts (1)

16-28: LGTM!

Also applies to: 65-67

test/unit/domain/EvidenceRuntime.test.ts (1)

1-84: LGTM!

CHANGELOG.md (1)

10-148: LGTM!

docs/READINGS_AND_OPTICS.md (1)

75-90: LGTM!

Also applies to: 197-221, 255-270, 468-469

src/domain/api/Intent.ts (1)

24-28: LGTM!

Also applies to: 201-223, 224-241, 254-279

bin/cli/v19/V19DomainInput.ts (1)

24-65: LGTM!

Also applies to: 71-215

docs/topics/cli.md (1)

42-90: LGTM!

test/type-check/v19-subpaths.ts (1)

51-60: LGTM!

test/unit/cli/v19-entity-intent.test.ts (1)

3-54: LGTM!

Also applies to: 77-86

test/unit/domain/Intent.entity.test.ts (1)

8-8: LGTM!

Also applies to: 23-27, 47-52, 76-80, 101-150, 176-181

test/integration/application/Runtime.entityCapture.concurrent.test.ts (1)

91-91: LGTM!

Also applies to: 105-111

src/domain/types/EntityCapturePayload.ts (1)

16-36: LGTM!

src/domain/types/PropValue.ts (1)

126-130: LGTM!

Also applies to: 151-165

test/unit/domain/types/EntityCapturePayload.test.ts (1)

27-32: LGTM!

Also applies to: 57-72

src/domain/api/IntentRuntime.ts (1)

51-65: LGTM!

Also applies to: 87-117, 119-140, 142-146, 161-170, 182-182

src/domain/services/PatchBuilder.ts (1)

79-123: LGTM!

Also applies to: 134-140, 153-175, 185-232, 262-262, 272-298, 302-339, 370-373, 388-406

src/domain/services/PatchBuilderEntity.ts (1)

2-11: LGTM!

Also applies to: 105-131, 168-186

src/domain/api/DraftTimelineRuntime.ts (2)

110-110: LGTM!

Also applies to: 135-144, 161-163


304-313: 🗄️ Data Integrity & Integration

Verify the stored draft intent after the intentFromPatch round trip.

The change summary states that writeDraftIntent now derives the stored intent with intentFromPatch(publication.patch) instead of appending the submitted intent. The writeDraftIntent body is not included in this review context, so I cannot confirm the effect.

The recovery path loses the allocation mode. entityIntentFor in src/domain/api/IntentRuntime.ts always returns Intent.addEntity({ subject, properties }); there is no addEntityAuto recovery branch. A caller that submits Intent.addEntityAuto({ namespace, properties }) therefore gets an explicit-subject entity.add intent stored in the draft. The stored subject carries the original writer's dot.

If any code replays persisted draft intents, confirm that replaying a recovered addEntity reproduces the intended subject and does not reuse a foreign writer's allocated id.

#!/bin/bash
# Description: Inspect writeDraftIntent and any replay path for persisted draft intents.
set -euo pipefail

ast-grep outline src/domain/api/DraftTimelineRuntime.ts --items all

echo '--- writeDraftIntent body ---'
ast-grep run --lang typescript --pattern 'async function writeDraftIntent($$$) { $$$ }' src/domain/api/DraftTimelineRuntime.ts

echo '--- persisted draft entry shape and consumers ---'
rg -nP -C6 '\bWarpDraftPatchEntry\b' --type=ts

echo '--- consumers of persisted draft intents ---'
rg -nP -C6 '\bintentFromPatch\s*\(' --type=ts

echo '--- any addEntityAuto recovery branch ---'
rg -nP -C4 '\baddEntityAuto\b' --type=ts
test/unit/domain/IntentRuntime.entity.test.ts (1)

4-4: LGTM!

Also applies to: 13-22, 32-38, 53-61, 76-121, 123-176, 178-208, 220-228, 243-252

test/unit/domain/services/PatchBuilder.entity.test.ts (1)

19-41: LGTM!

Also applies to: 43-43, 57-102, 147-151

Comment thread bin/cli/v19/V19DomainInput.ts
Comment thread src/domain/api/EntityOccurrence.ts
Comment thread src/domain/api/EvidenceRuntime.ts
Comment thread test/unit/cli/v19-entity-intent.test.ts
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 4, 2026
@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer Activity Summary — exact-head continuation

Cumulative audit history: issues 1–25 and issues 26–38. This table closes every finding raised by the CodeRabbit review of c6ad3d296 plus its global-only observations.

# Severity Source File Commit Outcome
39 P3 PR inline bin/cli/v19/V19DomainInput.ts False positive: one JsonInput alias; source typecheck green. Replied and resolved.
40 P2 PR inline src/domain/api/EntityOccurrence.ts f8536fb54 Removed the vacuous subject equality from occurrence authority validation; structural ratchet added. Resolved.
41 P1 PR inline src/domain/api/RetentionEvidence.ts 5cc489790 Canonical evidence now revalidates policy, reachability, and root kind; forged-prototype regression added. Resolved.
42 P4 PR inline test/unit/cli/v19-entity-intent.test.ts de598b1c0 Added the missing no-identity CLI rejection proof. Resolved.
43 P1 PR global src/domain/services/PatchBuilderPropertyRuntime.ts e2d4ec90d Reproduced and fixed post-commit mutation after deferred asset staging; lifecycle is rechecked before lowering.
44 P5 PR global test/unit/domain/WriteRuntime.test.ts False positive: Patch.writes is declared `string[]
45 P2 PR global src/domain/api/DraftTimelineRuntime.ts Verified intended behavior: persisted allocation hydrates to the published explicit subject so settlement cannot remint it. Existing commit 2ce87ef42 and integration witness prove the law.

Exact-head validation

  • Published head: e2d4ec90d7f525868439a7df8996de046ebac5f3
  • Static gates: ESLint, ratchets, anti-sludge, Semgrep, contamination/quarantine, Markdown/Mermaid/code samples, docs topology/reference, source naming, all typechecks, generated capability/vocabulary checks, exact Wesley fixture, links, declaration surface — PASS
  • Generated SDK packed-consumer smoke — PASS
  • Stable unit suites: 625 files passed, 1 skipped; 7,232 tests passed, 2 skipped
  • Integration: 32 files / 126 tests — PASS
  • v19 acceptance: 16 files / 129 tests — PASS
  • BATS: 8 / 8 — PASS
  • Coverage: 652 files passed, 1 skipped; 7,433 tests passed, 2 skipped; 93.02% lines against 92.99% ratchet — PASS
  • Normal pre-push Gates 0–9 — PASS

No unresolved local defect remains. Merge eligibility is pending the exact-head hosted check and review census.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Release Preflight

  • package version: 19.0.2
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v19.0.2. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

@flyingrobots

Copy link
Copy Markdown
Member Author

Code Lawyer merge-gate closure

  • Exact head: e2d4ec90d7f525868439a7df8996de046ebac5f3
  • Hosted checks: 19/19 passed, 0 pending, 0 failed
  • Review threads: 14/14 resolved
  • Local worktree: clean; local HEAD equals published branch
  • Current approvals: 0/2
  • Current GitHub review decision: none
  • CodeRabbit: status check passed only because the exact-head review was rate limited; the bot reports an active 18-minute cooldown from 2026-08-04T11:38:32Z

MERGE GATE: LOCKED. Code and validation are clean; review authority is not. Obtain two current approvals and an exact-head CodeRabbit disposition after cooldown, then rerun the thread/review/check census. No merge was attempted.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/domain/services/PatchBuilderPropertyRuntime.ts (1)

109-115: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reject a committed builder before asset staging.

Lines 115 and 143 check mutability only after stageContentAttachment completes. A post-commit call can create an unreferenced staged asset before it receives E_PATCH_ALREADY_COMMITTED.

Call assertMutable() before staging. Keep the existing post-await check to reject a commit that occurs during staging. Add a regression test that confirms assetStorage.stage() is not called when the builder is already committed.

Also applies to: 137-143

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/domain/services/PatchBuilderPropertyRuntime.ts` around lines 109 - 115,
In the attachment-building flow of PatchBuilderPropertyRuntime, call
this.#options.assertMutable() before each stageContentAttachment invocation so
an already committed builder fails before staging; retain the existing
post-await assertions to catch commits occurring during staging. Add a
regression test verifying assetStorage.stage() is not called when the builder is
already committed.
test/unit/cli/v19-entity-intent.test.ts (1)

20-30: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the complete JSON conversion payload.

The test passes if intentFromText preserves only kind and drops subject or properties. Assert the full descriptor, including subject: 'entry:1' and properties: { count: 1 }.

Proposed assertion
-      ).kind
-    ).toBe('entity.add');
+      ).descriptor
+    ).toEqual({
+      kind: 'entity.add',
+      subject: 'entry:1',
+      properties: { count: 1 },
+    });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/unit/cli/v19-entity-intent.test.ts` around lines 20 - 30, Update the
test case “accepts the same entity capture as JSON text” to assert the complete
result returned by intentFromText, including kind, subject: 'entry:1', and
properties: { count: 1 }, rather than checking kind alone.
src/domain/services/PatchBuilder.ts (1)

273-285: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Constrain emitEffect payload type with CanonicalJsonValue.

canonicalStringify accepts arbitrary unknown, accepts shared references/diamonds, and silently omits function/symbol object values. Let callers compile unsupported payloads that silently round-trip differently or store wrong JSON. Use payload?: Readonly<CanonicalJsonValue> or the exact repository payload type.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/domain/services/PatchBuilder.ts` around lines 273 - 285, Update the
emitEffect method’s payload parameter to use Readonly<CanonicalJsonValue> (or
the repository’s equivalent canonical JSON payload type) instead of the
unconstrained generic T. Preserve the existing optional-payload handling and
canonicalStringify call while preventing unsupported values, shared references,
and non-JSON values from compiling as effect payloads.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/MachineLocalPathPolicy.ts`:
- Around line 9-13: Update WINDOWS_HOME_PATTERN so the Windows “Users” directory
segment matches case-insensitively, while preserving the existing path
boundaries and username rules. Add a regression case covering a lowercase
variant such as C:\users\alice\repo through
MachineLocalPathPolicy.containsMachineLocalPath.

In `@test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts`:
- Line 52: Replace the string-based assertion around occurrence in
entity-capture-type-assertion-ratchet with a TypeScript AST-based check that
resolves EntityOccurrence.ts and detects equality expressions comparing
issued.subject and occurrence.subject in either operand order, regardless of
whitespace or formatting. Keep the test failing whenever that semantic authority
check is present.

---

Outside diff comments:
In `@src/domain/services/PatchBuilder.ts`:
- Around line 273-285: Update the emitEffect method’s payload parameter to use
Readonly<CanonicalJsonValue> (or the repository’s equivalent canonical JSON
payload type) instead of the unconstrained generic T. Preserve the existing
optional-payload handling and canonicalStringify call while preventing
unsupported values, shared references, and non-JSON values from compiling as
effect payloads.

In `@src/domain/services/PatchBuilderPropertyRuntime.ts`:
- Around line 109-115: In the attachment-building flow of
PatchBuilderPropertyRuntime, call this.#options.assertMutable() before each
stageContentAttachment invocation so an already committed builder fails before
staging; retain the existing post-await assertions to catch commits occurring
during staging. Add a regression test verifying assetStorage.stage() is not
called when the builder is already committed.

In `@test/unit/cli/v19-entity-intent.test.ts`:
- Around line 20-30: Update the test case “accepts the same entity capture as
JSON text” to assert the complete result returned by intentFromText, including
kind, subject: 'entry:1', and properties: { count: 1 }, rather than checking
kind alone.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: acbeed80-98cc-40e9-91bd-a8b961133ac2

📥 Commits

Reviewing files that changed from the base of the PR and between c6ad3d2 and 4063ff9.

📒 Files selected for processing (18)
  • .github/workflows/ci.yml
  • AGENTS.md
  • CHANGELOG.md
  • package.json
  • scripts/MachineLocalPathPolicy.ts
  • scripts/check-machine-local-paths.ts
  • src/domain/api/EntityOccurrence.ts
  • src/domain/api/EvidenceRuntime.ts
  • src/domain/api/RetentionEvidence.ts
  • src/domain/services/PatchBuilder.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • test/fixtures/generated-sdk/README.md
  • test/unit/cli/v19-entity-intent.test.ts
  • test/unit/domain/EvidenceRuntime.test.ts
  • test/unit/domain/services/PatchBuilder.commit.test.ts
  • test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
  • test/unit/scripts/machine-local-path-policy.test.ts
  • test/unit/scripts/wesley-ci-install-source.test.ts
💤 Files with no reviewable changes (1)
  • src/domain/api/EntityOccurrence.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (6)
  • GitHub Check: test-deno
  • GitHub Check: test-node (22)
  • GitHub Check: coverage-threshold
  • GitHub Check: type-firewall-generated-sdk
  • GitHub Check: v19 base/head performance
  • GitHub Check: preflight
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: In TypeScript, reject any, as any, as unknown as, *Like placeholder types, and @ts-ignore; do not use unknown outside infrastructure adapters or type assertions generally.
Prefer discriminated unions and explicit result types over boolean-flag bags; expected failures should be returned rather than represented as exceptions.
Do not construct infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core code; use constructor-injected ports for external capabilities.
Do not use puddle-assembly object construction such as incremental property assignment with conditional fields; define explicit validated concepts instead.
When a boundary shape is unclear, define a port or transport DTO rather than inventing a fake domain model.
Prefer one file per class, type, or object; split files when peer concepts accumulate.
Validate inputs at boundaries and constructors; encoding and decoding belong in adapters, codec ports, or explicitly named boundary reader modules.
Prefer instanceof dispatch over tag switching.
Use interface only for ports; represent domain concepts as classes.
Do not use boolean trap parameters; use named option objects or separate methods.
Do not use magic strings or numbers when a named constant should exist.
Keep domain bytes as Uint8Array; keep Buffer in infrastructure adapters.
Keep source files at or below 500 LOC, test files at or below 800 LOC, and bin/scripts at or below 300 LOC.

Files:

  • scripts/MachineLocalPathPolicy.ts
  • test/unit/scripts/wesley-ci-install-source.test.ts
  • test/unit/cli/v19-entity-intent.test.ts
  • scripts/check-machine-local-paths.ts
  • test/unit/domain/EvidenceRuntime.test.ts
  • test/unit/domain/services/PatchBuilder.commit.test.ts
  • test/unit/scripts/machine-local-path-policy.test.ts
  • src/domain/api/RetentionEvidence.ts
  • src/domain/api/EvidenceRuntime.ts
  • test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • src/domain/services/PatchBuilder.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Run an SSJS scorecard for every slice; until automated, verify runtime-backed concepts, boundary validation, owning-type behavior, no message parsing for significant branching, no ambient time or entropy, and no fake shape trust or cast-cosplay.

Files:

  • scripts/MachineLocalPathPolicy.ts
  • test/unit/scripts/wesley-ci-install-source.test.ts
  • test/unit/cli/v19-entity-intent.test.ts
  • scripts/check-machine-local-paths.ts
  • test/unit/domain/EvidenceRuntime.test.ts
  • test/unit/domain/services/PatchBuilder.commit.test.ts
  • test/unit/scripts/machine-local-path-policy.test.ts
  • src/domain/api/RetentionEvidence.ts
  • src/domain/api/EvidenceRuntime.ts
  • test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • src/domain/services/PatchBuilder.ts
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Never amend, rebase, force git operations, or use destructive cleanup/history-rewrite commands; create new commits instead.
Do not publish machine-local absolute paths; use repository-relative paths, ~, $HOME, or explicit placeholders.
At the end of a turn, stage only files written in that turn and commit those edits; do not leave self-authored changes staged and uncommitted.
Use GitHub Issues as the live work tracker and prefer precise issues for discoveries; do not rely on local backlog or deleted historical planning files.
Every open issue must have exactly one label from each live axis: type, priority, status, and area; use milestones for release targeting rather than release labels.
End every turn with the specified compact progress report, including goalpost, progress, branch divergence, and pull-request status.
Read the anti-sludge policy and systems-style TypeScript documentation before design-level changes.
Do not leave helper corridors, fake shape trust, or transitional duplication at the end of a slice.
Run npm run test:local, npm run test:coverage, npm run lint, and npm run typecheck as appropriate, and fix or explicitly surface every encountered error or warning.
Follow .github/RELEASE.md and current release tooling; do not maintain a separate prose release dashboard.
Every planned versioned release must have a thesis in its GitHub Milestone description or linked tracking issue before implementation is marked active.
Releases require matching versions in package.json, package-lock.json, jsr.json, and private workspace package metadata.
Update changelog, README latest-release information, architecture posture, topic documentation, and operator documentation when a release diff changes their truth.

Files:

  • scripts/MachineLocalPathPolicy.ts
  • package.json
  • test/fixtures/generated-sdk/README.md
  • AGENTS.md
  • test/unit/scripts/wesley-ci-install-source.test.ts
  • test/unit/cli/v19-entity-intent.test.ts
  • scripts/check-machine-local-paths.ts
  • test/unit/domain/EvidenceRuntime.test.ts
  • test/unit/domain/services/PatchBuilder.commit.test.ts
  • test/unit/scripts/machine-local-path-policy.test.ts
  • src/domain/api/RetentionEvidence.ts
  • src/domain/api/EvidenceRuntime.ts
  • test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • CHANGELOG.md
  • src/domain/services/PatchBuilder.ts
**/*.{test,spec}.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

For every refactor slice, touched code must reach 100% test coverage before completion.

Files:

  • test/unit/scripts/wesley-ci-install-source.test.ts
  • test/unit/cli/v19-entity-intent.test.ts
  • test/unit/domain/EvidenceRuntime.test.ts
  • test/unit/domain/services/PatchBuilder.commit.test.ts
  • test/unit/scripts/machine-local-path-policy.test.ts
  • test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
src/domain/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/domain/**/*.ts: Domain code must not use Date.now(), date constructors, performance.now(), random or crypto entropy APIs, timers, raw Error/TypeError, host APIs, Node globals, Buffer, or infrastructure imports; inject time and capabilities through ports or parameters and extend WarpError for domain errors.
Use runtime-backed domain concepts: named classes with validated constructors, Object.freeze, and instanceof dispatch; domain objects should establish validated runtime truth.

Files:

  • src/domain/api/RetentionEvidence.ts
  • src/domain/api/EvidenceRuntime.ts
  • src/domain/services/PatchBuilderPropertyRuntime.ts
  • src/domain/services/PatchBuilder.ts
🧠 Learnings (2)
📚 Learning: 2026-03-04T12:08:30.347Z
Learnt from: flyingrobots
Repo: git-stunts/git-warp PR: 63
File: package.json:126-126
Timestamp: 2026-03-04T12:08:30.347Z
Learning: Vitest 4 removes vite-node as a dependency and rewrites its pool system. Do not flag the absence of vite-node in package.json or lockfiles as an error for Vitest 4 projects. Use this as a general guideline: if a project uses Vitest 4, missing vite-node is expected and correct; only flag issues if there is evidence the project is not using Vitest 4 or if vite-node is explicitly required by the project.

Applied to files:

  • package.json
📚 Learning: 2026-03-08T19:50:17.519Z
Learnt from: flyingrobots
Repo: git-stunts/git-warp PR: 65
File: CHANGELOG.md:88-88
Timestamp: 2026-03-08T19:50:17.519Z
Learning: Follow the Keep a Changelog convention for CHANGELOG.md. Allow duplicate subheadings across versions (e.g., '### Added', '### Fixed'). Configure markdownlint MD024 with {"siblings_only": true} to avoid cross-version false positives.

Applied to files:

  • CHANGELOG.md
🪛 ast-grep (0.45.0)
scripts/MachineLocalPathPolicy.ts

[warning] 10-13: Do not use variable for regular expressions
Context: new RegExp(
[...POSIX_HOME_PATTERN, ...DARWIN_TEMP_PATTERN, WINDOWS_HOME_PATTERN].join('|'),
'u'
)
Note: [CWE-1333] Inefficient Regular Expression Complexity. Security best practice.

(regexp-non-literal-typescript)

scripts/check-machine-local-paths.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFileSync } from 'node:child_process';
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

test/unit/scripts/machine-local-path-policy.test.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFileSync } from 'node:child_process';
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🔇 Additional comments (15)
test/unit/domain/EvidenceRuntime.test.ts (1)

85-103: LGTM!

src/domain/api/EvidenceRuntime.ts (1)

209-209: LGTM!

src/domain/api/RetentionEvidence.ts (1)

32-94: LGTM!

CHANGELOG.md (1)

10-159: LGTM!

test/unit/scripts/wesley-ci-install-source.test.ts (1)

1-34: LGTM!

test/fixtures/generated-sdk/README.md (1)

14-16: LGTM!

test/unit/domain/services/PatchBuilder.commit.test.ts (1)

157-170: 🩺 Stability & Availability

No change needed.

Promise.withResolvers is supported by the declared Node.js and TypeScript targets, and vi.waitFor is not the barrier here; the mocked stage resolves staged.promise deterministically.

			> Likely an incorrect or invalid review comment.
package.json (1)

77-77: LGTM!

Also applies to: 91-91

scripts/check-machine-local-paths.ts (1)

1-44: LGTM!

.github/workflows/ci.yml (1)

130-132: LGTM!

AGENTS.md (1)

109-112: LGTM!

test/unit/cli/v19-entity-intent.test.ts (1)

6-18: LGTM!

Also applies to: 32-44, 46-95, 96-96

src/domain/services/PatchBuilder.ts (3)

17-31: LGTM!

Also applies to: 79-96, 106-123, 137-143, 154-162, 186-193, 202-222, 231-231, 263-263, 289-297, 303-340, 389-404, 407-407


371-374: 🗄️ Data Integrity & Integration

No mutable contentAssets exposure.

PatchBuilderPropertyRuntime.contentAssets returns a copy, so commitWithEvidence does not pass the property runtime’s mutable collection into commitPatch.


163-176: 🗄️ Data Integrity & Integration

No change needed.

addEntityAuto receives the allocated dot and advances the same VersionVector once before returning it.

Comment thread scripts/MachineLocalPathPolicy.ts
expect(runtime).not.toMatch(/\bWeakMap\b/);
expect(occurrence).not.toContain('readonly #compare');
expect(occurrence).not.toContain('readonly #relationTo');
expect(occurrence).not.toContain('issued.subject === occurrence.subject');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg 'entity-capture-type-assertion-ratchet|payload|scripts' || true

echo "== target file =="
if [ -f test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts ]; then
  wc -l test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts
  cat -n test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts | sed -n '1,140p'
fi

echo "== related source names =="
fd -i 'entity|capture|assertion|ratchet|payload' . -t f | sed -n '1,120p'

echo "== search source-text checks =="
rg -n "issued\.subject \=\=|=|occurrence\.subject|not\.toContain|payload" test src --glob '*.{ts,tsx}' || true

Repository: git-stunts/git-warp

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate target file exactly =="
git ls-files | grep -F 'test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts' || true

echo "== files by basename =="
fd -a 'entity-capture' . 2>/dev/null | sed 's#^\./##' | head -120 || true
fd -a 'capture-type-assertion' . 2>/dev/null | sed 's#^\./##' | head -120 || true

echo "== exact search for substring =="
rg -n --fixed-strings 'issued.subject === occurrence.subject' . || true

echo "== exact search for occurrence subject == issued subject =="
rg -n --fixed-strings 'occurrence.subject === issued.subject' . || true

echo "== exact search for noContainedOccurrenceRatchet =="
rg -n --fixed-strings 'noContainedOccurrence' . || true

Repository: git-stunts/git-warp

Length of output: 806


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== target test first lines =="
sed -n '1,90p' test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts

echo "== repo files in test unit scripts =="
git ls-files test/unit/scripts | sed -n '1,120p'

echo "== repo files matching type assertion ratchet exactly =="
for f in $(git ls-files | grep 'entity-capture-type-assertion-ratchet'); do
  printf '\n--- %s ---\n' "$f"
  wc -l "$f"
  sed -n '1,120p' "$f"
done

echo "== all tracked files named exactly target =="
find . -path './.git' -prune -o -name 'entity-capture-type-assertion-ratchet.test.ts' -type f -print

echo "== source text around target expression in scripts =="
rg -n "not\.toContain|toContain|noContainedOccurrence|Occurrence|Type Assertion|Ratchet" test/unit/scripts -S || true

Repository: git-stunts/git-warp

Length of output: 49318


Make the occurrence authority check syntax-independent.

not.toContain('issued.subject === occurrence.subject') misses issued.subject===occurrence.subject, other whitespace variants, and the reversed operand order. Resolve EntityOccurrence.ts as a TypeScript source file and reject the equality expression between issued.subject and occurrence.subject with semantic/AST matching before merge.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/unit/scripts/entity-capture-type-assertion-ratchet.test.ts` at line 52,
Replace the string-based assertion around occurrence in
entity-capture-type-assertion-ratchet with a TypeScript AST-based check that
resolves EntityOccurrence.ts and detects equality expressions comparing
issued.subject and occurrence.subject in either operand order, regardless of
whitespace or formatting. Keep the test failing whenever that semantic authority
check is present.

Source: Coding guidelines

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Release Preflight

  • package version: 19.0.2
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v19.0.2. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

@flyingrobots

Copy link
Copy Markdown
Member Author

Path-publication guardrail self-audit

Priority Source Boundary Finding
P1 Self pre-commit The current scan reads working-tree bytes, so staged unsafe content can be masked by a different unstaged file.
P1 Self pre-push The current scan reads the checkout rather than the exact outgoing Git objects, so unsafe content introduced and later removed can still be published in branch history.
P1 Self scanner Files containing NUL bytes are skipped, allowing embedded build/debug paths to escape inspection.
P2 Self CI Path hygiene is only an indirect lint sub-step; it is not a named job wired into the required aggregate merge gate.
P2 PR policy Case-variant Windows home spellings bypass the current pattern.

The corrective slices will operate on exact Git representations, report only safe object/path identifiers, and preserve the existing working-inventory lint as defense in depth.

Cc: @codex

@flyingrobots

Copy link
Copy Markdown
Member Author

Activity Summary — path-publication guardrails

Issue Severity Boundary Commit Outcome
Case-variant Windows home paths bypassed policy P2 Policy 5f24b62 Fixed; regression green; review thread resolved
Staged unsafe bytes could be masked by working-tree bytes P1 pre-commit cc9f85e Fixed; exact changed index blobs scanned
Binary files bypassed inspection P1 Scanner 9e654c6 Fixed; text and binary bytes scanned
Clean branch tip could conceal an unsafe outgoing object P1 pre-push 181cad1 Fixed; every outgoing blob, commit, and tag object scanned
Path hygiene was not an independent required merge lane P1 CI c1efd1d Fixed; exact-tree job required by type-firewall

Published head: c1efd1d

Validation:

  • Focused guardrail suite: 24 tests green
  • Source and test type checks: green
  • Lint, documentation, surface, and policy gates: green
  • Exact staged, outgoing-object, and committed-tree scans: green
  • Full local stable suite: not executed because the repository runner blocked below its 512 MiB free-memory floor
  • GitHub CI: pending on the published head

The unrelated occurrence-authority AST ratchet remains outside this guardrail slice and unresolved.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Release Preflight

  • package version: 19.0.2
  • prerelease: false
  • npm dist-tag on release: latest
  • npm pack dry-run: passed
  • jsr publish dry-run: passed

If this PR is from a release/* branch and merges to main, Main Push Release Branch Check will run final preflight and create v19.0.2. A maintainer who is a JSR @git-stunts scope member must then dispatch the Release workflow manually.

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.

Allocate entity subjects and expose causal occurrence receipts

1 participant