Skip to content

[Feature] Path based LiveObjects Implementation#1214

Draft
sacOO7 wants to merge 48 commits into
mainfrom
feature/path-based-liveobjects-implementation
Draft

[Feature] Path based LiveObjects Implementation#1214
sacOO7 wants to merge 48 commits into
mainfrom
feature/path-based-liveobjects-implementation

Conversation

@sacOO7

@sacOO7 sacOO7 commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

sacOO7 added 6 commits June 8, 2026 18:20
- PathObjectSubscriptionOptions: validate depth fail-fast per RTPO19c1a,
  throwing AblyException with ErrorInfo(400, 40003) when depth <= 0.
  Depth is now a primitive int; the "no depth / infinite depth" state is
  expressed via a new no-arg constructor (mirrors ably-js `{}` options),
  so no null handling is needed
- LiveMapValue: defensively copy binary payloads on creation and access,
  making the RTLMV3d immutability guarantee real for byte[] values
- ObjectData#getBytes: document that the returned array is the underlying
  message payload and must be treated as read-only
- JsonObjectPathObject/JsonArrayPathObject: reword "primitive resolution"
  javadoc for clarity
- LiveMapPathObject#at: fix javadoc equivalence example to compile
  (get() returns base PathObject, so chain via asLiveMap())
…al-public-api

[LiveObjects] Implement path-based LiveObjects public API
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bffd43f3-28f3-4e14-b211-fc272899f16f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/path-based-liveobjects-implementation

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 temporarily deployed to staging/pull/1214/features June 11, 2026 12:42 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc June 11, 2026 12:43 Inactive
sacOO7 and others added 3 commits June 15, 2026 19:34
…ccessor

Introduce the public, strongly-typed, path-based LiveObjects entry point on a
realtime channel, accessed via `channel.object`.

- RealtimeObject: exposes `get()` returning the root LiveMapPathObject, and
  extends ObjectStateChange to subscribe to objects sync-state events
  (on/off/offAll).
- ObjectStateChange / ObjectStateEvent: the SYNCING/SYNCED sync-state
  subscription API surface.
- ChannelBase.object: a public field providing `channel.object` access. When
  the LiveObjects plugin is not installed, the field is assigned
  RealtimeObject.Unavailable - a null-object guard whose methods fail fast with
  a clear plugin-missing error (statusCode 400, code 40019) instead of an NPE,
  keeping the `channel.object.<method>()` syntax consistent in both cases.

The plugin-present branch is intentionally left as a TODO until the LiveObjects
plugin exposes the new io.ably.lib.object.RealtimeObject type (getInstance
currently returns the legacy io.ably.lib.objects.RealtimeObjects).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ture

- Replaced ObjectsSubscription import with Subscription as per requirement
…tion-for-path-based-interfaces

[AIT-928] feat(liveobjects): add path-based RealtimeObject and channel.object accessor
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features June 16, 2026 12:01 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc June 16, 2026 12:02 Inactive
sacOO7 and others added 16 commits June 16, 2026 23:11
…mplementation' into chore/liveobjects-add-basic-implementation
- Marked PathObject#getValue as nullable when value doesn't exist at given path
- Implemented JsonSerializer annotation for better json handling
Point the JSON and MsgPack serializers in io.ably.lib.object.serialization
at the new WireObjectMessage wire model instead of the legacy
io.ably.lib.objects.ObjectMessage, so the new `object` package has no
dependency on the legacy `objects` package.

- DefaultSerialization: implement the new ObjectSerializer interface and
  (de)serialize WireObjectMessage arrays (reflectively loaded via
  ObjectSerializer.Holder).
- Json/MsgpackSerialization: bind the Wire* types; replace legacy
  objectError with the object package's objectStateError (same 500/92000).
- WireObjectMessage: restore the gson annotations required for wire-format
  fidelity - @SerializedName("object") on objectState and
  @JsonAdapter(WireObjectDataJsonSerializer) on WireObjectData.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes checkstyle AvoidStarImport violation on com.google.gson.*.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc June 24, 2026 09:53 Inactive
sacOO7 added 2 commits June 24, 2026 17:14
- Added basic helper unit/integration tests to `io.ably.lib.object`
…g `RecoveryKeyContext#channelSerials`

as a treemap
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features June 24, 2026 11:49 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc June 24, 2026 11:50 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features June 24, 2026 17:19 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc June 24, 2026 17:20 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features June 24, 2026 17:23 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc June 24, 2026 17:24 Inactive
sacOO7 and others added 12 commits June 25, 2026 14:39
Move the human-readable UTS guide and its self-contained HTML rendering
into the uts/ module as README.md and index.html. Both cover the UTS
concept, the three test tiers, the spec docs, the uts/ module layout,
mock/proxy infrastructure, the two example tests, deviations, and
appendices. Spec-doc references link to GitHub; paths are fully
qualified; the two artifacts are kept in sync.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ier Gradle tasks

Reorganise the uts module under a domain-rooted io.ably.lib.uts package that
cleanly separates infrastructure from tests, and unit from integration:

  infra/                         shared awaits (Utils.kt)
  infra/unit/                    mock transports + ConnectionDetails builder
  infra/integration/             SandboxApp
  infra/integration/proxy/       ProxyManager, ProxySession
  unit/realtime/                 ConnectionRecoveryTest        (mocked)
  integration/proxy/realtime/    AuthReauthTest                (sandbox + proxy)

- The ConnectionDetails test builder no longer sits in io.ably.lib.types, so it
  obtains the package-private constructor reflectively (as liveobjects/TestUtils.kt does).
- Add runUtsUnitTests / runUtsIntegrationTests Gradle tasks (filtered by package),
  mirroring runLiveObjectsUnitTests / runLiveObjectsIntegrationTests.
- check.yml now runs :uts:runUtsUnitTests; integration-test.yml gains a check-uts
  job running :uts:runUtsIntegrationTests.
- Bring uts/README.md and uts/index.html in sync with the new structure.
Reflect the new test-source structure in the UTS guide, website, and the
uts-to-kotlin skill:

- Add the direct-sandbox (`integration/standard/<module>/`) tier alongside
  the existing unit and proxy tiers, and document that every tier is now
  organised by module (`realtime`, `liveobjects`, …).
- Update §2 tier table, §4.2 directory tree + mental model, §7.3 SandboxApp
  (shared by both integration kinds), and §12 run commands in README.md, and
  mirror all of it in index.html (tags verified balanced, sections intact).
- Generalise the skill's spec→test path mapping to `<module>`, add a
  direct-sandbox row, and split integration specs into fault-injecting (proxy)
  vs happy-path (direct sandbox) flows.
- Correct stale "both tiers" wording now that there are three tiers.
…ckage mapping

Rework the uts-to-kotlin skill to translate a whole UTS module at once
instead of a single spec file:

- Take a UTS module directory (e.g. .../specification/uts/objects) and
  validate it sits directly under uts/ with a standard tier structure.
- Resolve the target ably-java package via uts-package-mapping.json (a new
  config file alongside the skill): a shared `testRoot` parent plus a
  `packages` table mapping each source module to its per-tier output dir
  (so objects -> liveobjects is explicit). Offer to create a mapping when
  one is missing.
- Let the user pick a tier (unit / integration / proxy) and then translate
  all specs or a selected subset, looping each through the existing
  per-spec translation steps.

Phase 1 (selection: Steps A-D) is new; Phase 2 (per-spec translation:
Steps 1-7) keeps the existing rules, with Step 1/2 adjusted to consume the
looped spec and the pre-resolved target.
…aluate mode

Make the skill's selection phase deterministic and add an explicit
translate-vs-evaluate choice:

- Add scripts/resolve_uts.py — a bundled resolver that validates the module
  directory, reads uts-package-mapping.json, and emits JSON with, per tier,
  the target dir, Kotlin package, and the candidate specs with derived class
  names. This replaces the per-run hand-work (regex validation, path joins,
  snake_case->PascalCase) that the model previously improvised, so Phase 1 is
  byte-for-byte deterministic. Exclusions are checked relative to the tier
  base (robust to the checkout location), and --create guards the target name.
- Rewrite Phase 1 (Steps A-E) around the resolver: resolve, confirm/create
  mapping, choose tier, choose specs, choose translate-only vs evaluate.
- Gate Step 6 (run/fix) behind evaluate mode per writing-derived-tests.md's
  Translation (always) vs Evaluation (only when an implementation exists)
  split; translate-only stops after compile + review.
- Make the reference fetch mandatory (WebFetch added to allowed-tools).
- Fix the file template to use the resolver's package/className (no hardcoded
  realtime, no double Test suffix) and the spec's full @uts id; correct stale
  uts/test/... proxy doc paths.
…rence

The objects UTS specs are written in ably-js-style pseudocode, but ably-java
is a typed SDK (RTTS1-10 partition). Add references/objects-mapping.md mapping
each ably-js symbol to its ably-java equivalent: entry point, async
(CompletableFuture/await), the typed PathObject/Instance hierarchies and as*
casts, the LiveMapValue write union, creation value types, subscriptions,
sync-state events, ValueType, message/operation getters, error codes, path
dot-escaping, and the internal-graph caveat for unit specs.

Wire it in deterministically: each module declares its translation reference
via a `notes` field in uts-package-mapping.json; resolve_uts.py resolves it to
`translationNotes` (absolute path, or null), and SKILL.md makes it required
reading before Phase 2 when present.
…ap them

Translate objects/helpers/standard_test_pool.md into ably-java test helpers in
uts/.../unit/liveobjects/helpers.kt: the standard object pool, the protocol- and
object-message builders (emitting the integer-coded wire JSON the SDK's Gson
expects), setupSyncedChannel/NoAck over the existing MockWebSocket, and
buildPublicObjectMessage — which reaches the internal PAOM3/PAOOP3 construction
(WireObjectMessage -> DefaultObjectMessage) by reflection, so it runs today even
though the rest of :liveobjects is unimplemented. Add testRuntimeOnly(:liveobjects)
so that reflection resolves while keeping the compile classpath decoupled.

Wire the mapping reference at it: objects-mapping.md gains a "Unit-test helpers"
section mapping each spec helper to its Kotlin name, and §11/§13 are corrected to
note public_object_message.md is translatable via buildPublicObjectMessage rather
than internal-only.
…efactor

- Add ChannelHistoryTest (RTL10d) and TokenRequestTest (RSA9/RSA9a/RSA9g)
  direct-sandbox integration tests, parameterised over json/msgpack.
- Add junit-jupiter-params dependency (@ParameterizedTest / @valuesource).
- Consolidate the sandbox host into a single SandboxApp.sandboxHost constant
  (removed from ProxyManager; ProxySession defaults both hosts to it).
- Sync uts/README.md, uts/index.html, and the uts-to-kotlin SKILL.md for the
  direct-sandbox tier: new ChannelHistoryTest walkthrough, integration-tests
  umbrella section, section renumber.
- Rename unit liveobjects helpers.kt -> Helpers.kt (case-only).
- objects-mapping.md: correct helper filename casing helpers.kt -> Helpers.kt
  (broken source-nav on case-sensitive filesystems); tag bare code fences as
  `text` to clear markdownlint MD040.
- README.md: tag bare fences as `text`; correct the msgpack rationale — ably-java
  does implement msgpack (useBinaryProtocol = true by default), the real reason
  proxy tests force JSON is that the proxy only handles text WebSocket frames.
- index.html: mirror the README msgpack correction.
- SKILL.md: label the unit-tier test scaffold as such and point integration/proxy
  flows at the SandboxApp/ProxySession section.
- resolve_uts.py: validate the module path via Path.parts instead of a
  forward-slash-only regex, so Windows paths are accepted.
- ConnectionRecoveryTest: use CopyOnWriteArrayList for the query-param capture
  list (written on the SDK transport thread, read on the coroutine dispatcher)
  to remove a visibility race / flake risk.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Translation review (SKILL.md Step 7) relied on eyeballing the spec and the
generated Kotlin side-by-side to confirm every test case, setup step, operation
and assertion was carried over — exactly the mechanical comparison the model
does inconsistently. Add a bundled extractor so the review reconciles a concrete
ledger instead.

scripts/audit_translation.py (regex-only, no semantic judgement, deterministic):
- idCoverage: spec `**Test ID**` set vs Kotlin `@UTS` tags -> missing / orphan.
- perTest[].sections: every non-comment pseudo-block line, grouped by section
  and tagged assert / await / step, so setup + operations + assertions are all
  enumerated; assertionShortfall flags likely-dropped assertions.
- Robustness: never crashes — tolerant decoding plus a top-level guard always
  emit one JSON object. Exit 0 clean / 2 missing-or-orphan / 64 couldn't-run,
  via a fail() helper matching resolve_uts.py's error shape.

SKILL.md Step 7 now runs the audit first and reconciles its output line by line
(coverage + completeness), keeping setup-fidelity and deviation-honesty as the
semantic checks; paths reference the resolver's specs[].file / targetDir.
[AIT-1081] Update liveobjects `uts-to-kotlin` skill to generate tests
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/features June 30, 2026 10:30 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/1214/javadoc June 30, 2026 10:31 Inactive
read_text()/write_text() default to the locale encoding on Windows (often
cp1252, not UTF-8) and apply newline translation, which would both mis-handle
non-ASCII content and rewrite the git-tracked uts-package-mapping.json with
CRLF. Pin the read to utf-8 and write via write_bytes (binary mode does zero
newline translation on any OS or Python version, keeping the file LF — unlike
write_text(newline=...), which needs Python 3.10+). Aligns with the utf-8 reads
already in audit_translation.py.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant