Skip to content

Prepare version 1.0.0 - #74

Merged
cardmagic merged 4 commits into
mainfrom
release/1.0.0
Oct 13, 2026
Merged

cardmagic merged 4 commits into
mainfrom
release/1.0.0

Conversation

@cardmagic

@cardmagic cardmagic commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Summary

This pull request prepares solid-objects 1.0.0. Version 1.0 freezes the public API under semantic versioning. It makes no claim of measured scale. The Cloudflare backend stays experimental and is outside the promise.

No tag is in this pull request. The tag follows after the maintainer approves the release text. The Ruby pull request is cardmagic/solid-objects-ruby#91.

Changes

  1. Breaking: a schedule() call with no operation fails the turn. A turn that called this.schedule({ at, key }) and then called no operation on the result stored no reminder and gave no error. The turn now fails with ScheduleWithoutOperation, a NonRetryableError. The message becomes a dead letter after one attempt, and the turn commits no state and no reminder. The turn can keep the result and call the operation later. The Cloudflare backend uses the same turn code and has the same rule.
  2. Parity ledger. docs/parity.md records the schedule rule as Native. It records the Ruby json gem check as Not applicable, because Node.js has JSON built in.
  3. Status and versioning documents. docs/versioning.md is new. The README gives the status at the top and names the projects that Solid Objects is not. The package description starts with the problems that the package solves, and three keywords are new. Each "pre-1.0" statement is replaced.
  4. "No daemon" wording. Reminders, effects, and queued messages run only while a process calls runtime.run(signal). The README and the category guide now say that no separate actor service is necessary, and they name that process.
  5. Version 1.0.0, with the changelog section.

Compatibility

  • API: one breaking change, item 1. Correct code such as this.schedule({ at }).expire() does not change. ScheduleWithoutOperation is a new export.
  • Schema: no change.
  • Configuration: no change.
  • Security: no change to authorization.

What version 1.0 does not claim

The benchmarks are development measurements. Longer soak tests are open work. The project has one maintainer, and no production use by other people is known.

Validation

  • pnpm run format:check, pnpm run check: pass.
  • pnpm run test:coverage: 76 files, 673 tests pass, 32 skipped (database and Redis tests that need a server).
  • pnpm run test:cloudflare: 61 tests pass.
  • pnpm run build, pnpm run check:cloudflare, pnpm run pack:check, pnpm run test:package, pnpm run test:recovery: pass.
  • New tests failed before the code change and pass after it: test/schedule-without-operation.test.ts (7), one test in test/cloudflare/runtime.test.ts, and two tests in test/package-metadata.test.ts.

A turn that called schedule() and then called no operation on the
result stored no reminder and gave no error. The hold or the timeout
that the author intended did not exist, and nothing reported it. Three
fresh agent sessions found this mistake in a published sample.

The turn now fails with ScheduleWithoutOperation. The error is not
retryable, because a retry cannot change the actor code. The turn can
keep the result and call the operation later in the same turn. The
Cloudflare backend uses the same turn code and has the same rule.

The parity ledger records the rule, and it records the Ruby json gem
check as not applicable to Node.js.

BREAKING CHANGE: a turn with a schedule call that has no operation
after it becomes a dead letter. Correct code does not change.
Version 1.0 promises a stable public API under semantic versioning.
docs/versioning.md gives the promise and what is outside it. The
Cloudflare backend stays experimental and is outside the promise.

The README now gives the status at the top: the release date, one
maintainer, one first-party production application, and no production
use by other people. It also names the projects that Solid Objects is
not, because search results mix them. The package description starts
with the problems that the package solves.

"No daemon" was not accurate: reminders, effects, and queued messages
run only while a process calls runtime.run(signal). The text now says
that no separate actor service is necessary and names that process.
@context7

context7 Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Docs7 for cardmagic/solid-objects-js

Result Status Action
Deployment ➖ Not used —
Content review ➖ Did not run. This site has no agent runs available this month. Wait for the monthly reset or check your Docs7 plan. —

Commit 46e582b

@greptile-apps

greptile-apps Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; both previous findings are fixed and no new actionable issue remains.

Summary

Prepares version 1.0.0 with a stable public API promise, clearer release limits, and an error for unfinished schedule() calls.

  • Every scheduled reminder needs an operation in the same turn.
  • Version 1.0.0 sets a stable API promise for Solid Objects.
  • An application process runs reminders, effects, and queued messages.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Run actor operation] --> B{Unfinished schedule?}
  B -->|Yes| C[ScheduleWithoutOperation]
  B -->|No| D[Read observables]
  D --> E{State or staged work changed?}
  E -->|Yes| F[QueryMutatedState]
  E -->|No| G[Commit turn]
  C --> H[Discard staged work and restore state]
  F --> H
Loading

Reviews (2) · Last reviewed commit: "fix: catch a bare schedule call in an ob..." · Reviewed by Greptile

Comment thread src/turn.ts
Comment thread src/actor.ts Outdated
The check for a schedule call with no operation ran directly after the
operation. An observable that called schedule() only after the state
changed was read later, so the turn committed with no reminder and no
error. The open call stayed on the retained actor and made the next
turn fail, although that turn did nothing wrong.

The projection guard now counts an open schedule call as staged work.
The turn that reads the observable fails with QueryMutatedState, and
the failure path clears the open call.

The error text also kept the Date object of the caller. Code that
changed that date to an invalid value afterward made toISOString()
throw RangeError, which the runtime retried. The call now keeps the
timestamp that schedule() already checked.
@cardmagic

Copy link
Copy Markdown
Owner Author

@greptileai Please review the current head 46e582b. Finding 1: the projection guard now includes the open schedule calls, so a schedule() call with no operation in observables() fails that turn with QueryMutatedState, and the failure path clears the open call. Finding 2: the call now keeps the timestamp that schedule() already checked, not the Date object of the caller. Three tests failed before the change and pass now. pnpm run check, pnpm test (676 pass), and pnpm run test:cloudflare (61 pass) pass.

@cardmagic
cardmagic merged commit 44ca079 into main Oct 13, 2026
20 checks passed
@cardmagic
cardmagic deleted the release/1.0.0 branch October 13, 2026 23:22
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