Skip to content

feat(binding): add lifecycle primitives#92

Open
flyingrobots wants to merge 5 commits into
mainfrom
cycle/dx-034e-binding-lifecycle-primitives
Open

feat(binding): add lifecycle primitives#92
flyingrobots wants to merge 5 commits into
mainfrom
cycle/dx-034e-binding-lifecycle-primitives

Conversation

@flyingrobots
Copy link
Copy Markdown
Owner

@flyingrobots flyingrobots commented May 19, 2026

Summary

Adds DX-034E binding lifecycle primitives to @flyingrobots/bijou.

This introduces immutable transition-algebra value objects for binding lifecycle ownership:

  • BindingLifecycleOwner
  • BindingLifecycleRecord
  • BindingLifecycleState
  • BindingLifecycleTransition
  • BindingInvalidation
  • lifecycle constructors/checkers
  • active/suspended/disposed transitions
  • invalidation records

This is a pure contract/value-object slice. Lifecycle records are immutable facts, not runtime managers.

Provider updates are represented as invalidation facts; assembling the next BindingFrame remains a later runtime integration concern.

Non-goals

  • no provider subscriptions
  • no active hierarchy traversal
  • no command dispatch
  • no rendered AppShell
  • no schema binding
  • no cache retention policy
  • no DOGFOOD integration

Validation

  • npm test -- --run packages/bijou/src/core/binding-lifecycle.test.ts tests/cycles/DX-034/binding-lifecycle-primitives.test.ts
  • npm test -- --run packages/bijou/src/core/binding.test.ts packages/bijou/src/core/binding-lifecycle.test.ts packages/bijou/src/core/app-shell-composition.test.ts tests/cycles/DX-034/binding-frame-primitives.test.ts tests/cycles/DX-034/provider-scope-contracts.test.ts tests/cycles/DX-034/app-shell-composition-contract.test.ts tests/cycles/DX-034/active-binding-lifecycle.test.ts tests/cycles/DX-034/binding-lifecycle-primitives.test.ts
  • npm run typecheck:test
  • npm run docs:inventory
  • git diff --check
  • npm run lint
  • npm test
  • pre-push hook reran npm run typecheck:test, npm test, and npm run verify:interactive-examples

Full suite: 288 test files passed, 3342 tests passed.

Summary by CodeRabbit

  • New Features

    • Binding lifecycle primitives: lifecycle owners and immutable value-object records
    • Deterministic state transitions (active, suspended, disposed)
    • Lifecycle invalidation tracking and transition history
  • Documentation

    • Added binding lifecycle primitives to changelog and design documentation
  • Tests

    • Added comprehensive binding lifecycle and integration test coverage

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Warning

Rate limit exceeded

@flyingrobots has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 44 minutes and 40 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cb2302d3-39be-4226-8fe0-7d41e4f78b7e

📥 Commits

Reviewing files that changed from the base of the PR and between 3e205e4 and 24bd65f.

📒 Files selected for processing (3)
  • docs/CHANGELOG.md
  • packages/bijou/src/core/binding-lifecycle.test.ts
  • packages/bijou/src/core/binding-lifecycle.ts
📝 Walkthrough

Walkthrough

This pull request implements DX-034E "Binding Lifecycle Primitives" for the @flyingrobots/bijou library. It introduces immutable, frozen lifecycle records modeling deterministic state transitions (active → suspended → disposed) with invalidation facts, replacing mutable lifecycle managers with pure transition-algebra value objects that produce no side effects.

Changes

Binding Lifecycle Primitives Implementation

Layer / File(s) Summary
Design Specification and Requirements
docs/design/DX-034-declarative-view-data-binding.md, docs/CHANGELOG.md
DX-034E design section defines lifecycle as transition-algebra facts with owner/record/state/transition/invalidation vocabulary, enumerated allowed transitions, provider-generated invalidation facts without side effects on frames, test requirements for immutability, and implementation status. CHANGELOG entry documents exported primitives and follow-on integration work.
Lifecycle Type System and Contracts
packages/bijou/src/core/binding-lifecycle.ts (lines 1–108)
Exports enumerated types (BindingLifecycleState, BindingLifecycleOwnerKind, BindingInvalidationReason, BindingLifecycleTransitionReason) and branded interfaces (BindingLifecycleOwner, BindingLifecycleRecord, BindingInvalidation, BindingLifecycleTransition) defining the immutable data shapes and state-machine vocabulary.
Lifecycle Owner and Record Construction
packages/bijou/src/core/binding-lifecycle.ts (lines 110–500)
Constructors (defineBindingLifecycleOwner, bindingLifecycleRecord) validate inputs, normalize text fields, default state/version, and produce fully immutable frozen objects with branded type symbols. Supporting functions include cycle-safe deepFreeze, text normalization, and runtime validation predicates. Type guards enable runtime narrowing.
Lifecycle State Transitions and Mutations
packages/bijou/src/core/binding-lifecycle.ts (lines 199–447)
Mutation functions (activateBinding, suspendBinding, disposeBinding, invalidateBinding) enforce state-machine rules via transition-reason matrix, prevent operations on disposed records, increment version, and append immutable transition history. Transition validation ensures only allowed state paths (active↔suspended, →invalidated, →disposed) with matching reason semantics.
Core Unit Tests
packages/bijou/src/core/binding-lifecycle.test.ts
Comprehensive test suite covering owner/record creation with normalized/frozen structures, state transitions with history tracking, invalidation snapshots and immutability, defensive validation of empty IDs/unsupported states/version constraints/transition inconsistencies, field exposure constraints, and command intent separation.
Public API Export and Acceptance Tests
packages/bijou/src/index.ts, tests/cycles/DX-034/binding-lifecycle-primitives.test.ts
Barrel re-exports lifecycle functions and types; integration tests verify state transition flow and invalidation through public API, confirm design documentation describes transition-algebra semantics, validate changelog consistency, and assert command intent metadata isolation.

Sequence Diagram

sequenceDiagram
  participant Client as Client Code
  participant Owner as defineBindingLifecycleOwner
  participant Constructor as bindingLifecycleRecord
  participant Mutate as activateBinding
  participant Freeze as deepFreeze
  participant Record as BindingLifecycleRecord
  
  Client->>Owner: kind, id, label
  Owner->>Owner: validate and normalize
  Owner->>Record: branded immutable owner
  
  Client->>Constructor: owner, requirementId, state
  Constructor->>Constructor: validate owner brand
  Constructor->>Freeze: recursively freeze invalidations
  Constructor->>Record: branded immutable record v1
  
  Client->>Mutate: record (suspended)
  Mutate->>Mutate: assert record, not disposed
  Mutate->>Mutate: check suspended→active allowed
  Mutate->>Record: new record v2, transition appended
  
  Client->>Record: inspect state, transitions, version
Loading

🎯 4 (Complex) | ⏱️ ~45 minutes

🐰 A binding lifecycle blooms,
Frozen states in transition rooms—
No side effects intrude,
Pure facts, immutably viewed! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(binding): add lifecycle primitives' is a clear, concise summary that directly reflects the main change—introduction of immutable binding lifecycle primitives to the @flyingrobots/bijou package.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cycle/dx-034e-binding-lifecycle-primitives

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 and usage tips.

Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e205e44e0

ℹ️ About Codex in GitHub

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

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

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

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

Comment thread packages/bijou/src/core/binding-lifecycle.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@packages/bijou/src/core/binding-lifecycle.ts`:
- Around line 136-141: isBindingLifecycleOwner and isBindingLifecycleRecord
currently accept brands inherited via the prototype chain; change their checks
to ensure the brand is an own property (not inherited) and value is a non-null
object. Specifically, in isBindingLifecycleOwner replace the prototype-accepting
test with: confirm typeof value === 'object' && value !== null and use
Object.prototype.hasOwnProperty.call(value, BINDING_LIFECYCLE_OWNER_BRAND) and
strict equality against true on (value as
BindingLifecycleOwnerBrandCarrier)[BINDING_LIFECYCLE_OWNER_BRAND]; apply the
same pattern to isBindingLifecycleRecord using its
BINDING_LIFECYCLE_RECORD_BRAND and corresponding BrandCarrier type so only
objects with an own-brand property pass.
- Around line 367-385: The function freezeTransitions currently only checks the
final transition matches expectedState but does not ensure the chain is
continuous; modify freezeTransitions (and use the already-mapped
frozenTransitions) to validate that for every index i > 0
frozenTransitions[i].from === frozenTransitions[i-1].to and throw an Error if
any adjacent pair is discontinuous, preserving the existing final-state check
against expectedState and returning Object.freeze(frozenTransitions) as before;
reference the freezeTransitions function and the freezeTransition-produced
frozenTransitions array when implementing this adjacency validation.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0904de9e-6b76-445d-9286-145cd855b5ec

📥 Commits

Reviewing files that changed from the base of the PR and between 4f8d23b and 3e205e4.

📒 Files selected for processing (6)
  • docs/CHANGELOG.md
  • docs/design/DX-034-declarative-view-data-binding.md
  • packages/bijou/src/core/binding-lifecycle.test.ts
  • packages/bijou/src/core/binding-lifecycle.ts
  • packages/bijou/src/index.ts
  • tests/cycles/DX-034/binding-lifecycle-primitives.test.ts

Comment thread packages/bijou/src/core/binding-lifecycle.ts
Comment thread packages/bijou/src/core/binding-lifecycle.ts
@flyingrobots
Copy link
Copy Markdown
Owner Author

@codex PR feedback resolution summary:

Severity File Issue Outcome Commit SHA Regression Test
P2 packages/bijou/src/core/binding-lifecycle.ts Lifecycle brand guards accepted inherited prototype brands. Own-property brand checks now reject prototype-chain spoofing. a716d0b npm test -- --run packages/bijou/src/core/binding-lifecycle.test.ts
P2 packages/bijou/src/core/binding-lifecycle.ts Rehydrated transition histories could be discontinuous. Transition history adjacency is validated before records are accepted. 9493046 npm test -- --run packages/bijou/src/core/binding-lifecycle.test.ts
P5 docs/CHANGELOG.md Public invariant hardening needed release-note truth. Unreleased changelog records own-brand and contiguous-history invariants. 91f27be npm run docs:inventory; git diff --check
P5 docs/CHANGELOG.md Changelog rewrap broke the DX-034E cycle proof phrase. Restored the contiguous provider subscriptions non-goal phrase. 24bd65f npm test -- --run tests/cycles/DX-034/binding-lifecycle-primitives.test.ts

Validation after fixes:

  • npm test -- --run packages/bijou/src/core/binding-lifecycle.test.ts tests/cycles/DX-034/binding-lifecycle-primitives.test.ts
  • npm run typecheck:test
  • npm run docs:inventory
  • git diff --check
  • npm run lint
  • npm test
  • pre-push reran npm run typecheck:test, npm test, and npm run verify:interactive-examples

@flyingrobots
Copy link
Copy Markdown
Owner Author

@coderabbitai review please 🥕

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

@flyingrobots Appreciated the detailed resolution summary — the P2 fixes for brand spoofing and discontinuous transition histories look like solid hardening. Kicking off a fresh review now! 🥕

( ´・ω・`) 🐇

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant