Implement v18 property projection cutover#101
Conversation
|
Warning Review limit reached
Your plan currently allows 1 review/hour. Refill in 49 minutes and 2 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR closes V18 property-projection slices 31–35: it adds runtime property write intents, extends graph-op algebra and projection emission to include content/property set ops, reworks StateReader snapshot hydration and projection helpers, updates PatchBuilder lowering and PropValue validation, expands public exports, updates tests, and parallelizes CI static gates under an aggregate type-firewall. ChangesV18 Property Projection Closeout (Slices 31–35)
Sequence Diagram(s)sequenceDiagram
participant Client as Caller
participant Reader as createStateReader
participant Hydration as createStateReaderProjectionState
participant Snapshot as SnapshotWarpState
participant Projection as NodePropertyProjection
Client->>Reader: createStateReader(source: StateReaderSource)
Reader->>Hydration: convert source to live WarpState
Hydration->>Snapshot: check if SnapshotWarpState
Snapshot->>Hydration: warpStateFromSnapshot (rebuild CRDT/frontier/props)
Hydration-->>Reader: live WarpState (hydrated or original)
Reader->>Projection: derive property records
Projection-->>Reader: visible node/edge property records
Reader-->>Client: VisibleStateReader with projection-backed props
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Release Preflight
If you tag this commit as |
Release Preflight
If you tag this commit as |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
src/domain/services/state/StateReader.ts (1)
193-207: ⚡ Quick winCache node property records once during context build.
createProjectionProps(projectionState)andcreateNodePropertyRecords(projectionState)both end up walkingNodePropertyProjection.fromState(...), so each reader build decodes/sorts the same node-property set twice. Materializing that array once here and deriving bothprojection.propsandnodePropsByIdfrom it would avoid the duplicate pass.🤖 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/state/StateReader.ts` around lines 193 - 207, Materialize node property records once: call createNodePropertyRecords(projectionState) into a local const (e.g., nodePropertyRecords) and reuse it for both building projection.props and populating nodePropsById instead of calling createNodePropertyRecords(...) twice; to do this, add or modify a helper so you can derive projection.props from the precomputed records (e.g., createProjectionPropsFromRecords(nodePropertyRecords) or adjust createProjectionProps to accept the records), then pass nodePropertyRecords into populateVisibleNodeProps(nodePropertyRecords, nodePropsById) and remove the duplicate createNodePropertyRecords(...) call.
🤖 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 @.github/workflows/ci.yml:
- Around line 36-38: Replace floating action tags by pinning the uses fields for
actions/checkout and actions/setup-node to their immutable commit SHAs (replace
uses: actions/checkout@v6 and uses: actions/setup-node@v6 with
actions/checkout@<commit-sha> and actions/setup-node@<commit-sha>, and update
every occurrence), add a top-level permissions: block with least-privilege
scopes required by the workflow, and set persist-credentials: false on each
actions/checkout step to avoid credential persistence (locate and modify the
checkout steps and the workflow header permissions in the CI yaml).
- Around line 33-48: The workflow grants excessive token scope and leaves
checkout credentials persisted; for the job type-firewall-lint (and all other
jobs using actions/checkout@v6) add a minimal job-level permissions block (e.g.,
permissions: contents: read and only the specific permissions needed) and update
each actions/checkout@v6 step to include with: persist-credentials: false so the
GITHUB_TOKEN is not left in the runner git config; apply the same changes to all
jobs named in the comment (type-firewall-types, type-firewall-lint,
type-firewall-semgrep, type-firewall-quarantine, type-firewall-surface,
type-firewall-docs, type-firewall-audit-advisory, typecheck-test-advisory,
test-node, test-bun, test-deno, coverage-threshold) to harden token scope and
disable credential persistence.
In `@src/domain/services/PatchBuilder.ts`:
- Around line 463-507: requirePatchPropertyValue currently can recurse forever
on cyclic inputs and can be polluted via prototype keys; fix by adding cycle
detection (pass a WeakSet seen through recursive calls and throw PatchError with
code 'E_PATCH_INVALID_PROPERTY_VALUE' if a non-scalar object/array is already in
seen) and by guarding against prototype-polluting keys when normalizing plain
objects (either reject keys like '__proto__' and 'constructor' with PatchError
or create records with Object.create(null) and still reject any key named
'__proto__' or 'constructor'); update requirePatchPropertyValue to accept an
internal seen: WeakSet<object> param, mark objects/arrays before recursing, and
keep isPlainPatchPropertyObject as-is for detection but ensure the object
key-check happens in requirePatchPropertyValue when building record/array to
deterministically fail on cycles and prototype-key pollution.
In `@test/unit/domain/services/PatchBuilderPropertyIntent.test.ts`:
- Around line 16-63: Add unit tests in PatchBuilderPropertyIntent.test.ts that
exercise the remaining property normalization branches: add a test that calls
createBuilder(...) and builder.setProperty('node:1','bin', new
Uint8Array([1,2,3])) then build() and assert the op value accepts Uint8Array and
patch.schema is correct; add tests that pass nested/recursive structures via
builder.setProperty (e.g., arrays and objects) to ensure they are normalized and
appended to ops by build(); and add a test that supplies a cyclic value to
builder.setProperty and asserts it throws PatchError (or the same cyclic
rejection path) and that builder.build().ops remains empty. Reference the
existing helpers and symbols used in the file (createBuilder,
builder.setProperty, setEdgeProperty, InvalidPropertyCarrier, PatchError,
requirePropSet, encodeLegacyEdgePropNode) so tests align with current test
patterns.
In `@test/unit/domain/services/StateReaderPropertyProjection.test.ts`:
- Around line 26-81: Add a parallel test that constructs a SnapshotWarpState via
warpStateFromSnapshot (or by calling StateReaderSource.snapshot path) containing
the same nodes/edges/prop entries as the existing WarpState test, then call
createStateReader with that SnapshotWarpState and assert the same results for
getNodeProps, getEdgeProps, getEdges, project().props and
getNodeContentMeta/getEdgeContentMeta as in the live-state cases; locate where
the existing tests create the live WarpState (functions addLiveNode,
addLiveEdge, encodePropKey, encodeEdgePropKey) and replicate those setup steps
but convert the final state into a SnapshotWarpState using warpStateFromSnapshot
(or the StateReaderSource API) before creating the reader so the snapshot code
path (SnapshotWarpState/StateReaderSource) is exercised and assertions remain
identical.
---
Nitpick comments:
In `@src/domain/services/state/StateReader.ts`:
- Around line 193-207: Materialize node property records once: call
createNodePropertyRecords(projectionState) into a local const (e.g.,
nodePropertyRecords) and reuse it for both building projection.props and
populating nodePropsById instead of calling createNodePropertyRecords(...)
twice; to do this, add or modify a helper so you can derive projection.props
from the precomputed records (e.g.,
createProjectionPropsFromRecords(nodePropertyRecords) or adjust
createProjectionProps to accept the records), then pass nodePropertyRecords into
populateVisibleNodeProps(nodePropertyRecords, nodePropsById) and remove the
duplicate createNodePropertyRecords(...) call.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 42937f48-5de7-4608-85e0-a36a20e15952
📒 Files selected for processing (33)
.github/workflows/ci.ymlCHANGELOG.mddocs/BEARING.mddocs/design/0179-v18-state-reader-property-projection/v18-state-reader-property-projection.mddocs/design/0180-v18-property-write-intent-nouns/v18-property-write-intent-nouns.mddocs/design/0181-v18-patchbuilder-property-intent-lowering/v18-patchbuilder-property-intent-lowering.mddocs/design/0182-v18-graph-op-projection-property-cutover/v18-graph-op-projection-property-cutover.mddocs/design/0183-v18-property-projection-closeout/v18-property-projection-closeout.mddocs/method/backlog/v18.0.0/PROTO_legacy-props-as-projection.mdsrc/domain/graph/EdgePropertyWriteIntent.tssrc/domain/graph/GraphContentAttachmentSetOp.tssrc/domain/graph/GraphEdgePropertySetOp.tssrc/domain/graph/GraphNodePropertySetOp.tssrc/domain/graph/GraphOpAlgebra.tssrc/domain/graph/GraphOperation.tssrc/domain/graph/NodePropertyWriteIntent.tssrc/domain/graph/publicGraphSubstrate.tssrc/domain/services/GraphOpAlgebraProjection.tssrc/domain/services/PatchBuilder.tssrc/domain/services/TranslationCost.tssrc/domain/services/controllers/QueryReads.tssrc/domain/services/query/StateQueryReadModel.tssrc/domain/services/state/StateReader.tssrc/domain/services/state/StateReaderContext.tstest/type-check/consumer.tstest/unit/domain/WarpGraph.coverageGaps.test.tstest/unit/domain/graph/GraphOpAlgebra.test.tstest/unit/domain/graph/PropertyWriteIntent.test.tstest/unit/domain/services/GraphOpAlgebraProjection.test.tstest/unit/domain/services/PatchBuilderPropertyIntent.test.tstest/unit/domain/services/QueryReadsPropertyProjection.test.tstest/unit/domain/services/StateReaderPropertyProjection.test.tstest/unit/domain/services/query/StateQueryReadModelPropertyProjection.test.ts
|
@codex self-review findings for confirmation.
|
|
Resolved the self-review findings in
Local verification before push:
|
Release Preflight
If you tag this commit as |
|
Resolved the unresolved review threads in
Local verification:
|
Release Preflight
If you tag this commit as |
|
@codex self-review findings for confirmation.
|
|
Resolved the P2 self-review finding in
Verification:
|
Release Preflight
If you tag this commit as |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/services/state/StateReaderContext.ts`:
- Around line 168-179: The hydration currently treats any non-null object as a
snapshot property bag; update isSnapshotPropValueObject (and validate again at
the start of propValueObjectFromSnapshot) to only accept plain objects whose
prototype is Object.prototype or null, that are not arrays or ImmutableBytes,
and whose own property descriptors (Object.getOwnPropertyDescriptors) are all
data descriptors (no getters/setters); if the input fails these checks throw
E_STATE_READER_INVALID_SNAPSHOT_PROPERTY_VALUE. Keep the existing seen handling
in propValueObjectFromSnapshot and only proceed to
Object.entries/propValueFromSnapshotWithSeen after the plain-object +
data-descriptor validation passes.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 85bb31c8-bd84-4eef-bbca-95407d8653a2
📒 Files selected for processing (3)
CHANGELOG.mdsrc/domain/services/state/StateReaderContext.tstest/unit/domain/services/StateReaderPropertyProjection.test.ts
✅ Files skipped from review due to trivial changes (1)
- CHANGELOG.md
|
Resolved the latest CodeRabbit actionable feedback in
Verification:
|
Release Preflight
If you tag this commit as |
Summary
StateQueryReadModeland property-count accounting.PatchBuilderproperty writes through those intents while preserving the existing wire shape and reserved-byte validation behavior.Verification
npm run typechecknpm run lintnpm run lint:sludgenpm run lint:quarantine-graduatenpm run test:local(488 files, 6956 tests)npx markdownlint-cli2 CHANGELOG.md docs/BEARING.md docs/method/backlog/v18.0.0/PROTO_legacy-props-as-projection.md docs/design/0183-v18-property-projection-closeout/v18-property-projection-closeout.mdgit diff --checkNotes
A follow-up commit preserves the consumer type surface after widening
createStateReaderto accept immutableSnapshotWarpStatesources in addition to liveWarpStatesources.Summary by CodeRabbit