Skip to content

Merge Store 6 main onto store6 and remove Store 5 - #52

Merged
matt-ramotar merged 53 commits into
store6from
merge-main-into-store6
Aug 16, 2026
Merged

Merge Store 6 main onto store6 and remove Store 5#52
matt-ramotar merged 53 commits into
store6from
merge-main-into-store6

Conversation

@matt-ramotar

Copy link
Copy Markdown
Owner

Summary

  • Brings the Store 6 line — all 51 commits from store6...matt-ramotar:Store6:main — onto store6 with the original SHAs preserved (merge, not rebase).
  • Merges store6 with the ours strategy. The base tip f45df778 (MobileNativeFoundation/Store#736) is a Store 5 build modernization (Gradle 9.6.1, AGP 9.3.0, Kotlin 2.3.21) that conflicts with Store 6's pinned toolchain in 10 root build files. Since this PR also removes Store 5, that modernization has no remaining scope on this branch; Store 6 stays on its CI-proven toolchain (Gradle 8.11.1, AGP 8.10.0, Kotlin 2.3.20). .editorconfig and KMMBridge-Release.yml from Build modernization: Gradle 9.5, AGP 9.2, Kotlin 2.3, and tooling updates MobileNativeFoundation/Store#736 intentionally do not carry over.
  • Removes Store 5: the store, cache, multicast, rx2, and core modules and their settings.gradle includes (166 files, −15,469 lines). No store6-* module references them (verified by sweep).
  • CI adjustments in the removal commit:
    • Drops koverXmlReport and the Codecov upload; kover was applied only in the store module.
    • Deletes create_swift_package.yml; it drives KMMBridge, which only the Store 5 convention plugin applied.
    • Adds store6 to the CI, Store6, and benchmarks workflow branch filters so PRs into store6 and pushes to it run the same gates as main.

Docs-sync note

The docs-sync guard flags this PR because the diff against store6 includes synced sources (STABILITY.md, ROADMAP.md, module READMEs) carried by the 51 commits. The docs site pins main revisions, and main is unchanged by this PR, so no re-pin is triggered by merging it; the docs-sync-ack label acknowledges the guard.

Intentionally untouched (follow-up candidates)

  • Unused Store 5 convention plugins in tooling/plugins (they compile standalone).
  • Unused version-catalog entries (kover, rxjava, kotlinx-coroutines-rx2).
  • rootProject.name = "Store5" and Store 5 mentions in README, STABILITY.md, llms.txt, and the gradle.properties POM description.

Test plan

  • All 51 compare SHAs verified as ancestors of the head via git merge-base --is-ancestor; store6..HEAD is exactly 53 commits (51 + ours-merge + removal commit).
  • Repo-wide sweep: no build or CI surface references the deleted modules.
  • ./gradlew :store6-core:compileKotlinJvm — BUILD SUCCESSFUL (settings and convention plugins configure cleanly without the v5 modules).
  • CI and Store6 workflows green on this PR.

Made with Cursor

matt-ramotar and others added 30 commits July 18, 2026 17:12
Completes the frozen Store6 core API, epoch-safe engine semantics, multiplatform ABI baselines, two-bridge Swift dump gates, and CI enforcement. All required checks passed; approved by Matt Ramotar on 2026-07-18.
…cies, typed meta (#3)

Implements the typed fetch-result surface, all five freshness policies, ordered and cancellable bookkeeping, lossless active-stream residence events, multiplatform conformance coverage, and regenerated ABI/Swift dumps. All required checks passed; approved by Matt Ramotar on 2026-07-19.
* Add readerGen and value-bound attribution to the key state machine

* Add SourceOfTruth seam with reader liveness contract and DSL default

* Rework KeyEngine onto the shared SoT reader pipeline with honest attribution

* Add store6-contract-tests module with the SoT contract kit and kit runs

* Run conformance suites against a substituted SoT

* Pin origin honesty, orphan regression, and reader liveness through the store

* Regenerate ABI and Swift dumps for the SourceOfTruth seam

* test(store6-core): harden SoT race fixtures

* test(store6-core): make dormant SoT replay causal

* test(store6-core): gate dormant replay revalidation

* test(store6-core): make grace replay barriers causal

* fix(store6-core): fence post-match write observations

* test(store6-core): make max-age seed causal

* test(store6-core): make reader barriers causal

Seed the successful SWR fixture through the shared reader pipeline before invalidation. Gate rotating-slot refetches on downstream delivery of the replacement slot snapshot so post-cutoff authority is tested deterministically.

* test(store6-core): virtualize grace races

Run zero-subscriber grace schedules on the KeyEngine test scope and advance to the last virtual millisecond before reader shutdown. Keep every fake reader collection live so one-shot hydration and shared pipeline roles are distinguished causally.

* fix(store6-core): preserve cold-start loading order

* test(store6-core): make swr refetch registration causal

* test(store6-core): gate external delete revalidation

* test(store6-core): gate orphan invalidation enrollment
…lidation (#5)

* feat(maintenance): coordinate scoped commits

* fix(maintenance): reject callback re-entry

* feat(flow): preserve lifecycle while conflating data

* fix(flow): preserve synchronous data bursts

* fix(flow): propagate terminal failures

* feat(sot): add scoped bulk deletion

* fix(sot): serialize bulk fake mutations

* fix(sot): harden bulk deletion gates

* feat(bookkeeper): add durable stale watermarks

* fix(bookkeeper): make maintenance atomic

Stage fallible maintenance updates before a single publish gate so failures leave records, watermarks, and sequence state untouched. Guard sequence exhaustion, preserve status identity semantics, and reuse the watermark-only status.

* Wire durable staleness, sidecar hydration, and discrete Revalidated through the engine

* Rebuild namespace maintenance on durable watermarks and supersede-first clears

* Add durable invalidation, revalidation, and stress conformance suites

* Regenerate ABI and Swift dumps for the grown SourceOfTruth seam

* test(maintenance): use real time for engine-tail race gates

* test(store6-core): harden emission sequence controls
* Move seam contracts into store6.core.seam and promote freshness, bookkeeping, and clock types

* Add seam Fetcher and public config install points with behavioral coverage

Route lambda sugar through internal Fetcher adapters and transport conditional ETags from the coherent reservation plan. Expose clock, bookkeeping, and freshness-validator installers and thread them through the store engine.

The restart seam test uses MaxAge to prove durable staleness forces a blocking refetch while preserving CachedOrFetch stale-while-revalidate semantics.

* Add StoreTelemetry seam with null-guarded hooks and pinned emission placement

* Add StoreRuntime capability handle with write handle and KeyEvents stream

Recognition amendments replace exactly these landed lines:
- revalidatedSatisfiesDemand: envelope.origin == Origin.FETCHER &&
- StreamDelivery.envelopeSatisfiesDemand: envelope.origin == Origin.FETCHER &&

The exact installed writer envelope now satisfies both checks.

* Add Overlay seam with a single-writer per-key projection layer

* Add seam StoreResults factory with the sanctioned exception door

* Add store6-extension-probe module with seam-only CI gates

* Stabilize replay-based binding conformance barriers

* Regenerate ABI and Swift dumps for the seam v1 surface

* Stabilize overlay reader-failure protocol assertion

* Gate overlay reader-failure proof causally

* fix(core): defer covered 304 replacement

Do not let pre-success durable status reserve a replacement while the exact revalidation owner covers the current stale epoch.

Add a gated initial-delivery regression for the disposition/outcome tail window.

Reference: Issue 008 hosted Apple verification

* test(extension-probe): gate retirement signal observers

* fix(core): preserve projection failure causes

Use an upstream Flow.catch boundary so a downstream apply failure remains the terminal cause while self-originated changes cancellation is still retained. Replace the clear-namespace counter TOCTOU with the existing causal freshness proof and add a live-subscriber regression.

* fix(core): harden seam race handling
* Add store6-testing module skeleton on the store6 convention plugin

* Absorb the SourceOfTruth and Bookkeeper contract kits into store6-testing

* Add store6-testing fakes, test clock, meta, and result factories

* Add store6-testing conformance suites and the ViewModel sample test

* Extend Store6 CI to build, test, and verify store6-testing publications

* Harden FakeStore demand-driven consumption under concurrency

* Document effective Turbine publication scopes
…pter/compose catalog, subset convention plugin (#8)
…n, close lifecycle, stress lanes (#9)

* Bound conflateLatestData with per-kind lifecycle coalescing (FS-1)

* Refcounted KeyRegistry with quiescent-only idle LRU eviction

* CI: TD-8 whitelist audit, explicit JS lock canary, macOS native stress lane

* Complete store.close() lifecycle: registry release and leak-checked teardown

* store6-testing: finalize the PROVISIONAL-PENDING-007 close-semantics pins

* AC-6 conformance: zero-config and expert-config defaults are identical

* Eviction, close-leak, and backpressure conformance and stress suites

* test(store6-core): make close waiter causal

* Refresh BCV and Swift dumps for StoreBuilder.maxIdleKeys
…and transactions (#10)

* Store v6 issue 010: store6-sqldelight module scaffold on the preflight toolchain

* Store v6 issue 010: durable meta sidecar schema, sequence algebra, and sync-transaction bridge

* Store v6 issue 010: durable SqlDelight bookkeeper passes the contract kit with restart coverage

* Store v6 issue 010: SqlDelight source of truth passes the 15-test contract kit over live drivers

* Store v6 issue 010: transactional atomicity, kill-point rollback, and TD-6 crash-window closure proofs

* Store v6 issue 010: core conformance suites green with the SqlDelight adapter substituted (AC-5)

* Store v6 issue 010: sample app and 15-minute existing-schema walkthrough with measured timings

* Store v6 issue 010: CI lanes, klib publication loop (39 artifacts), and BCV dumps for store6-sqldelight
…dent conformance suites and failure-time CI evidence (#11)

* Store v6 issue 017: adversarial reader-hop perturbation runs reproduce the scheduler race class (red)

Core perturbation lane: 3 of 10 serial repetitions red, including matrix A observing v3 instead of v2 and matrix C observing a stale terminal candidate.

SQLDelight perturbation lane: 7 of 10 serial repetitions red, including matrix C observing v1, v3, or stale data and the clear sibling starting a third fetch.

Temporary provenance probes (not committed) reproduced the same sequence in both adapters: stale SOT(v2), calls=3, then fresh FETCHER(v3). Evidence is archived under /private/tmp/store6-017-red-evidence/approved.XrR8kt.

* Store v6 issue 017: closeAndSettleForTest support seam (core joins; borrowed compilation settles with close)

* Store v6 issue 017: failure-time test-report uploads so assertion-level evidence survives red CI runs

* Store v6 issue 017: causal barriers, ratified-bound drains, and joined cleanup make conformance scenarios scheduler-independent (green under reader-hop perturbation)

* Store v6 issue 017: substitution and perturbation fixtures track and close their SQLDelight drivers

* Store v6 issue 017: settle the seed fetch before MaxAge advance

* Store v6 issue 017: fence only reader-hop seed fetches

* Store v6 issue 017: fence every cold seed on observed reader delivery

* Store v6 issue 017: fence stale reader ticket enrollment
…y the pre-clear drain (#12)

* test(store6-core): remove short wait deadlines

Preserve Default-dispatch ordering while letting a 25-second runTest bound own cancellation. This prevents nested 2-second and 5-second wall-clock timers from expiring under broad root-CI load and keeps cleanup below the JS runner's 30-second ceiling.

Post-merge evidence: root CI 30046754162

* test(store6-core): complete causal wait hardening

Remove the remaining nested physical timers from causal test waits while preserving their Default-dispatch ordering. Bound ordinary suites at 25 seconds, keep the 240-second stress watchdog, align JS Mocha at 300 seconds, and close Store before cancellation-sensitive joins.

* test: complete the wall-clock causal-wait sweep and add the ratified pre-clear drain

Remove every remaining nested wall-clock withTimeout that hops to
Dispatchers.Default across core commonTest and the sqldelight JVM lane,
preserving each cross-scheduler hop. Bound every swept suite with the
same file-private 25-second runTest shadow; StoreZeroConfigEquivalenceTest
keeps its deliberate inline 60-second bounds. Virtual-time timeouts on the
test scheduler are untouched: they are deterministic and out of the class.

Also repair the fifth same-class frame race surfaced by the serial
repetition lane: clearNamespace_activeLocalOnlyStreamObservesMissingWithoutRefetch
now drains at most one queued pre-clear Data frame, exactly asserted
(value and flags), per the fenced-clear ruling in decision 006 that a
pipeline may queue one duplicate pre-clear Data. Loading then Missing
remain strictly asserted, and the LocalOnly no-refetch bound stays exact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…lidation (#13)

Post-merge evidence at ed81900 (Store6 run 30056554434, apple-tests,
macosArm64Test, T6 artifact 8583026634): StoreRevalidationConformanceTest-
AgainstSharedFlowSot.conditionalRefetch_notModified_emitsOwnerRevalidated-
AndClearsStaleness failed with "unexpected lifecycle item Error". The engine
launched the invalidate-wake refetch while residence transiently read null,
so commitNotModified took the baseline == null branch and surfaced the
adapter-contract Missing error for a durably resident key — a public Error
frame inside a healthy 304 cycle, violating ratified C-24.

Per the T2E ruling (Matt approved option 1): a null launch baseline with
residence present at commit is an obsolete launch snapshot, classified
ObsoleteRevalidation like every other stale snapshot, which self-heals by
replanning once. Only a 304 with no value on either side remains the typed
Missing adapter-contract failure.

Red-first: coldBaselineNotModified_hydratedBeforeCommit_classifiesObsolete-
AndReplans deterministically pins the racy commit state on the virtual-time
scheduler (Failed before the fix, ObsoleteRevalidation plus exactly one
replan after); trulyColdNotModified_staysTypedMissingAdapterContractFailure
pins the preserved boundary. The three 304-cycle conformance tests legalize
the bounded self-heal (fetch call 3 answers NotModified; count bound 2..3)
while keeping every frame assertion and the staleness-clearing proof exact.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Lift Kotlin and KSP to 2.2 while preserving existing JVM-default bytecode and Swift dump output across shared convention paths.

Co-authored-by: OpenAI Codex <noreply@openai.com>
…, androidx.room3 catalog (#16)

Kotlin 2.2.21 -> 2.3.20 (room3 native KLIBs are ABI 2.3.0), KSP -> 2.3.10
(standalone versioning), AGP 8.9.3 -> 8.10.0 (room3 plugin floor),
androidx.sqlite 2.6.2 -> 2.7.0 (room3 3.0.0 POM), room 2.8.4 catalog entries
replaced by androidx.room3 3.0.0 (dormant until 011 retargets),
androidCompileSdk 33 -> 34 (room3/sqlite AAR metadata floor; no tree consumer),
renovate freeze moved to androidx.room3. Swift dumps refreshed for the
Kotlin 2.3 SubclassOptInRequired @note rendering: +30/-0, doc comments only,
no selector or type changes (shaped bounded-churn gate per the amended plan).

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…line, and demo (#17)

* Store v6 issue 012: store6-compose module skeleton and stability conf on the preflight toolchain

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: skipEqualData operator and storeResultMutationPolicy (TDD)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: Store.collectAsState and Flow.collectAsStoreState with structural skipping

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: lifecycle-aware collection on the CMP lifecycle tier

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: store6-compose-demo desktop screen, DemoUiState derivation, and stability probe

Registers the shipped stability conf as a compile input and opts the demo compilations out of
the build cache: the Compose plugin tracks neither, so a conf-only edit or a cache hit would
otherwise leave the CI gate asserting against a stale stability report.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: stability calibration ruling and consumer docs

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: CI lanes for store6-compose and the tiered compose-stability gate

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: BCV dumps for store6-compose

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: run the shared compose suites on the Android unit-test variant

Composition.dispose() traces through android.os.Trace, which is an unimplemented android.jar
stub under local unit tests and throws rather than no-ops. Returning stub defaults keeps the
Android variant executing the same 17 commonTest suites as every other target.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: ship the lifecycle entry points on all 12 targets and harden the stability gate

Review found the lifecycleMain tier rested on a false premise. lifecycle-runtime-compose 2.9.1
does publish linuxX64, mingwX64, tvosArm64 and watchosArm64 — verified against the published
Gradle module metadata and by compiling all four — so the restriction omitted the API from a
third of the published artifacts, and the README and KDoc shipped a wrong reason to consumers.
The lifecycle-gated entry points move to commonMain and the klib dump now carries them on every
target.

Two gate defects fixed:
- it asserted the ABSENCE of 'unstable' rather than the PRESENCE of 'stable', so the compiler's
  third parameter rendering — a bare, unprefixed 'value: X' emitted for unknown/runtime
  stability — passed silently. Demonstrated as a false green against a doctored report.
- Kotlin incremental compilation rewrites the stability report with only the recompiled subset,
  and the report is an undeclared output, so an incremental CI build could gate against a
  one-entry report. The step now discards the module build directory and forces a full compile.

Test gaps closed, each verified by mutation: custom valueEquivalence in the mutation policy,
origin as a discriminator, the MaxAge restart-key normalization, collectAsStoreState's initial
parameter, the collection-start close guard, collectAsStoreStateWithLifecycle, lifecycle
re-entry retention, and the demo's non-stale error banner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Store v6 issue 012: review follow-ups — commonTest lifecycle coverage, restart-token guard, demo SideEffect

Promotes the lifecycle behavior tests from jvmTest to commonTest: LifecycleRegistry.createUnsafe
and Dispatchers.setMain both work off-JVM, so the all-12-target lifecycle claim is now
behavior-verified on every runnable lane (jvm, js, wasmJs, iosSimulatorArm64, macosArm64,
androidDebug, androidRelease — 25 tests, 0 failures each) rather than compile-verified everywhere
and behavior-verified only on JVM.

Adds a guard comment on freshnessToken's else branch: it is safe only because every other landed
Freshness is a data object, and a future non-singleton subtype would silently restart collection
on every recomposition.

Replaces the demo's write-during-composition of lastData with SideEffect, so the retained-Data
write no longer lands as a backwards write to state the same composition already read.

No ABI change: api dumps are byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…fective test deadline (#18)

Turbine 1.2.0's 3-second wall-clock default nested inside every 017 25-second
runTest shadow, so a starved runner could fail a test via Turbine's deadline
instead of the ratified bound (PR #15 D0: OverlayProjectionProtocolTest red at
3.065s). No turbineTimeout override existed repo-wide.

Each of the 12 shadow files that also uses Turbine now wraps its test body in
withTurbineTimeout(30s). 30s is strictly greater than the 25s bound: equal
bounds would race, so the shadow is now provably the sole effective deadline
and starvation converts to the uniform UncompletedCoroutinesError with a full
coroutine dump, as designed.

Test-only: shim, import, and constant lines exclusively. No assertion, drain,
tolerance, or scripted-response change; no production code, workflow, toolchain,
or store6-room path touched. The 5 files borrowed byte-identically by
store6-sqldelight stay identical (Gradle Sync from core's tree).

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…r with durable bookkeeping (#15)

* Store v6 issue 011: store6-room module scaffold and Room KMP test rig

Co-authored-by: OpenAI Codex <noreply@openai.com>

* Store v6 issue 011: adapter-owned bookkeeping schema (entities, DAO, migration SQL)

* Store v6 issue 011: RoomBookkeeper — durable watermark algebra on Room

* Store v6 issue 011: RoomSourceOfTruth with generation-gated reader and transactional capability

* Store v6 issue 011: transactional atomicity and AC-5 substitution conformance suites

* fix(store6-room): keep bookkeeping scopes internal

* Store v6 issue 011: Room sample app, walkthrough, and compatibility statement

* Store v6 issue 011: CI lanes and ABI dumps for store6-room

* fix(store6-room): preserve transaction contracts

Coordinate adapters that share a database, buffer reader echoes until transaction and savepoint outcomes, and keep mutation generations monotonic.

Make the admitted commit boundary exception-atomic, fail fast on launched-child transaction mutations, and close every Room database created by the inherited contract kits.

Tests: 59/59 on JVM, iOS simulator, and macOS; module build, API checks, lint, and sample green.

* Store v6 issue 011: retarget store6-room to Room 3.0.0

The unreleased adapter moves to androidx.room3 3.0.0 before first publication
rather than shipping a known-breaking Room 2 surface: Room types are this
artifact's public ABI, so the coordinate/package/type-identity change is a
breaking change that must not land post-release.

Consumes the Kotlin 2.3.20 / AGP 8.10.0 / SQLite 2.7.0 / androidx.room3 preflight
as landed (#16, 1322eeb) on top of #17 compose (e0449fc) and #18 turbine deadline
(3db78fa). Targets drop from 9 to 8: room3 publishes no iosX64 variant, verified
directly against the resolved 3.0.0 artifacts, so the drop is inherent to the
retarget rather than a discretionary cut. js/wasmJs are Room-3-supported and
tracked as a separate follow-up; they need a suspend schema API and async SQLite.

Two API deltas the port had to absorb. Room 3's Gradle plugin registers its
extension as `room3`, not Room 2's `room`. Room 3's Migration.migrate is suspend,
while androidx.sqlite 2.7.0's execSQL is still synchronous, so
Store6RoomSchema.createTables stays non-suspend and the public surface keeps its
shape there. The connection API (useWriterConnection, useReaderConnection,
immediateTransaction, deferredTransaction) carries over unchanged.

Tests carry over semantically unchanged and pass 59/59 on jvm, iosSimulatorArm64
and macosArm64, including the 15 SourceOfTruth and 6 Bookkeeper inherited kit
tests. The three Turbine-using test files adopt PR #18's shim shape (25s runTest
shadow, 30s Turbine deadline strictly above it); the two Turbine-free files keep
the plain 25s shadow, mirroring #18's own exclusion rule.

CI: the four single-line lists become five-way unions carrying sqldelight,
compose and room without dropping any entry; #17's inserted steps are preserved
verbatim and unreordered; the klib skip-case gains iosx64 for four suffixes.
Verified publication is 61 primary artifacts (52 landed plus room's 9). BCV dumps
regenerate to name androidx.room3.RoomDatabase, and the klib dump's target header
drops iosX64. Zero drift outside store6-room, settings.gradle and store6.yml.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…irst pin (#19)

* test(core): pin cold origin cutoff race (red)

Hold a pre-write cold absence across durable write return on runTest's virtual scheduler, then assert the full C-05 contract: FETCHER origin, non-stale/non-refreshing delivery, non-null metadata, and one fetch.

The test is intentionally red on unfixed origin/main. The archived XML proves the SOT, stale, refreshing, null-metadata, two-fetch shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(core): fence queued pre-return observations

Track the active raw-reader session at the successful write boundary. When its final writer-current notification is still queued, reject preceding mismatches, preserve the committed envelope, and release the fence only on the exact writer echo.

The write-return CAS remains non-suspending, ordinary post-echo observations retain later source authority, and no public or seam API changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(core): pin concurrent cutoff mirror

Hold both cold collectors after Launch/Join reservation and gate both ticket outcomes while a shared pre-write absence crosses durable return. The unfixed engine deterministically produces SOT/stale/null-meta frames and a second fetch; the writer-current fence preserves FETCHER convergence and one call.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(core): pin successor fence overwrite (red)

Hold a committed fetcher echo across the start of a second apply write. The current fence is cleared by the successor and deterministically reproduces the full SOT, stale, refreshing, null-metadata, two-fetch failure shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(core): preserve predecessor fence across writes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(core): pin failed successor rollback (red)

Hold a committed predecessor echo unresolved, stamp and conflate a failing successor, then prove the rollback cannot strip the predecessor envelope or launch a redundant fetch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(core): retain envelope after failed successor

Discard a failed or cancelled owner's consumed tag before resuming its nonmatching row. Equal predecessor content keeps the installed envelope; different content remains source-of-truth authority.

Avoid copying the raw observation on the ordinary attribution path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(core): pin hosted fence liveness regressions (red)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(core): recover fenced reader liveness

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…lemetry overhead, non-blocking CI lane (#20)

* Store v6 issue 016: store6-benchmarks module skeleton and kotlinx-benchmark toolchain

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 016: benchmark fixtures and the harness smoke-test contract (red)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 016: METRIC-1 stream/cold/get/churn benchmarks

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(benchmarks): use JMH 1.37 Blackhole guard

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 016: telemetry overhead benchmarks and allocation probe

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 016: CI wiring — blocking build step, grep-loop union, non-blocking benchmarks lane

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 016: harness README and calibration config finalization

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(benchmarks): address final review findings

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…pp Compose inspector (#22)

* Store v6 issue 013: devtools module skeletons on the landed toolchain

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 013: devtools event model and StoreDevtoolsMonitor (TDD)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 013: structured logger sink, composite telemetry, and EVENTS.md v0 (TDD)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 013: in-app Compose inspector with pure presenter derivation (TDD)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 013: devtools demo app on Android, desktop, and iOS with the inspector overlay

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 013: CI lanes for devtools modules and BCV dumps

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 013: document devtools modules and demo runbook

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 013: keep Linux JS lock graph complete

Disable configuration on demand for the full Linux job so Kotlin JS/Wasm lock tasks see one consistent project graph across separate Gradle invocations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Store v6 issue 013: keep iOS demo launchable

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 013: keep timeline transitions visible

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…nd the public roadmap (#21)

* Store v6 issue 014: STABILITY.md — tiers, deprecation, cadence, and the mutations honesty section

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 014: README Store 6 section and llms.txt

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 014: public roadmap page

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 014: pin tests for the documented zero-config defaults

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 014: docs pages at docs/store6/, publish-time placeholders resolved

Materializes the four teaching pages as tracked files per the OQ-1 ruling (docs-site
content lives in the Store repo). Directory proposed as docs/store6/, distinct from the
untracked docs/v6 planning corpus; Matt confirms it in the voice pass.

Resolves every <PLACEHOLDER-*> token: roadmap and quickstart homes to in-repo paths,
llms.txt to repo-relative links, and <PLACEHOLDER-GRADUATION> rewritten as the named
prose reservation (no token, no dead link). Corrects store6-sqldelight/README.md's stale
"Kotlin 2.1.21" pin per the OQ-6 ruling.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 014: apply code-review and plan-ADDENDUM-3 findings

ADDENDUM 3 was appended to the plan mid-execution and carries an unruled gate on
STABILITY §3 (open item (b)). Discharging its T1 Step 4 obligation found a real error:
§3 published store6-testing as stable-track while every public declaration in that
artifact carries @ExperimentalStoreApi. The row now states the verifiable fact and the
discrepancy is routed to Matt, same disposition as the Kotlin-floor STOP-gate.

Test fixes, both of which made the pins prove more than they did:
- advanceUntilIdle() proved nothing about retries. RealStore runs the engine on
  Dispatchers.Default, which never observes runTest's virtual clock, so the assertion
  was a snapshot taken immediately after get() returned. Replaced with real-time quiet
  windows an order of magnitude above the engine's internal fixed-delay scale.
- The retry pin only covered the terminalizing get(MustBeFresh) path, which is where a
  background retry is least possible. Added a live-stream-collector leg, which is where
  one could actually hide. Green on jvm, macosArm64, and jsNode.

Documentation corrections:
- The defaults page misquoted the fetcher-requirement message it cited: a source of
  truth does not substitute for a fetcher (sot is defaulted; requireNotNull(fetcher) is
  unconditional). The third alternative is fetcher(Fetcher).
- Quickstart step 4 asserted the exact convergence issue 020 is currently stopped on.
  Re-attributed to the acknowledgement contract; active-collector convergence is
  explicitly not promised until the engine work lands.
- STABILITY and ROADMAP disagreed on the adapters; STABILITY now carries may-slip.
- §3 now tells seam implementors the seam types are @ExperimentalStoreApi today.
- Narrowed the atomicity gate to Overlay/StoreWriteHandle per the ratified RISK-2 text.
- LocalOnly line now cites evidence for both of its claims.
- Quickstart states plainly that nothing is published yet; no install block ships,
  because no ratified document sanctions a snapshot coordinate (ADDENDUM 3 item (a)).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Store v6 issue 014: apply voice-pass round 1 — cut the v5 archaeology

Matt: "it currently reads like airing dirty laundry." Both documents recited Store 5's
failures in six separate places — the 30-month alpha line, MutableStore's annotation-gated
years, the dropped FileSystem support, the stalled 4-to-5 migration, an unanswered
contribution offer, and a "trust deficit" framing. Each was defensible alone; together they
made a policy document read as an apology, which undercuts the confidence it exists to
project.

Each site now states the commitment and stops. Principles 3 and 4 gained forward-looking
clauses where a failure used to serve as the rationale. The alpha01 schedule honesty moves
to where it belongs: the confidence range.

Extended to the two closure comments, which carried the same register and are the most
public artifact here.

Nothing load-bearing was lost. AC-1's never-again statement is intact verbatim, as are the
tier markers, deprecation stages, cadence, side-by-side promise, the two-step ack obligation
in both README and STABILITY, the OVERLAY consumer guidance, and the two-stage RISK-2 text.
Re-verified: no frozen-claims, no performance numbers, no PLACEHOLDER, zero dead links, and
all five anchors the closure comments target still resolve.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* test(core): pin active confirmFresh liveness

Adopt the Issue 020 diagnostic fixture byte-for-byte and hold the exact active writer row across durable return and confirmFresh metadata advancement. The unfixed engine drops the row and strands the active projection authorization. Fresh T0 XML: 0072577630c0cd65cb2d6e5909202931b69a9ac5b1065ea3f0bcd40c66e543c6.

* fix(core): preserve confirmFresh writer-row liveness

Reuse the live metadata-advanced envelope only for the exact committed authoritative raw token, while excluding direct revalidation owners and preserving resumed attribution.

* test(core): make projection gate observation causal

* test(core): await durable mark entry causally
* test(core): pin projection auth handoff

Apply the archived two-interleaving patch unchanged at 451bb9c. The mapping-before pin fails directly while the mapping-after F-0 control passes.

Patch SHA-256: 2f819b8841c21961f87bf7de3858f7e8ff42299e760489e80f00a47cc2ae475c

Red XML SHA-256: 96770b5d1bf16d04fa611b5e7b45d2d7fe17f552f9265867139434ee056dd324

* test(core): cover projection auth matrix

Execute all 32 projection authorization handoff cells and pin consecutive metadata successors plus obsolete readiness.

* test(core): gate invalidation delivery timing

Keep the stale-epoch delivery path on the intended side of confirmFresh in every matrix cell.

* test(core): pin authorization construction race

Gate confirmFresh after coherent reader resolution and before projection authorization construction.

* fix(core): hand off projection authorization

Preserve a private causal lineage across confirmFresh metadata successors and carry the coherent projection base from reader resolution through authorization.
* store6-mutations: module scaffold, test fixtures, wiring spike (issue 020 T1)

* store6-mutations: journal boundary, mutator registry, producer-failure containment (T2)

* store6-mutations: real Overlay producer over the pending journal (T3)

* store6-mutations: non-transactional ack path (apply → confirmFresh → retire) (T4)

* store6-mutations: walking-skeleton tracer, enqueue → OVERLAY → ack → SOT (T5)

* store6-mutations: CI lanes and klib verification (T6)

* store6-mutations: harden drain and signal handoffs
Issue 021 (STORE-8): the twenty-ruling mutations API review executed against
base e3c9e6d. Presence algebra with explicit Present/Absent (null projector
result = decline only); required-input mutationStore factory (registry, server,
keyResolver, valueCodecVersion, valueCodec) over an overlay-free builder with
retained Bookkeeper/SourceOfTruth; two-method MutationServer (push + retire);
sealed present/absent acks with clear-based absent adoption; resolver-backed
drain()/drain(key) replacing drainOnce; real in-memory attempt generations with
defensively copied codec blobs; normalized failure/inspection carriers; typed
advisory event algebra; in-memory canonical alias facade with explicit
key-taking Store overrides and lost-wakeup-free revision signals; effects
capture (never execution); permanent mutations ObjC/SKIE dump lanes via the
parameterized SwiftDumpTasksPlugin (core lanes byte-identical); BCV dumps
refreshed; quickstart/STABILITY updated to the ratified surface.

Zero changes under store6-core/ and store6-testing/. Durable journal, drain
orchestration, and ack-path atomicity remain Issues 022/023/024 per the frozen
R-0/R-1 handoff.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* test(core): pin overlay authorization ordering

Add deterministic reader-first and owner-first interleavings for Issue 029. Reader-first preserves the classified legacy red; owner-first proves the equal-but-distinct target is rejected. No production code changes.

* test(core): accept authorized overlay reuse

Replace the obsolete origin-only rejection with the value- and authorization-aware C1 contract after the F-B ruling. Preserve the owner-first negative control unchanged.
* feat(mutations): add durable journal storage

Implement the public journal seam, in-memory and SQLDelight storage, restart hydration, pruning safety, and published contract kits.

Wire additive API dumps, module publication, and the required CI verification lanes for Issue 022.

* test(mutations): use durable unit codec in walking test

* test(mutations): isolate lincheck record fixtures
Implement the ruled parking, backoff, conflict, acknowledgement, effect, checkpoint, event, and restart semantics across the mutation engine and both journal adapters.

Add deterministic contract, scheduling, resumability, and API guards while preserving the public ABI and storage schema.

Reference: Issue 023
matt-ramotar and others added 23 commits August 7, 2026 07:04
* docs: add source-doc cleanup inventory baseline

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: record inventory 4-column format in plan

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: remove internal sign-off stamp from freeze-candidate KDoc

Removes the freeze-candidate/sign-off governance stamp and its variants
(personal-name references, issue-007 landing-state language) from KDoc
and comments across store6-core, store6-testing, store6-room,
store6-sqldelight, store6-compose, store6-compose-demo, store6-devtools,
store6-mutations, and store6-benchmarks. The @ExperimentalStoreApi
annotation and STABILITY.md already carry the public stability contract,
so no replacement text is added.

44 hits classified per the rewrite rubric: 33 P2 (governance/decision-
provenance stamps), 2 P1 (bare issue-007 tags), 2 P3 (speculative-intent
lifecycle-policy deferrals), and 2 FP (a test-fixture User.name string
literal that coincidentally matches "Matt", left unchanged).

Verification: root ./gradlew apiCheck ktlintCheck green; module
compileKotlinJvm green for store6-core/testing/room/sqldelight/compose/
mutations/devtools; api/ dumps unchanged; every diff hunk touches only
comment/KDoc content.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(core): remove internal issue and design-doc references from KDoc

Clears the remaining store6-core sweep hits after the cross-module
freeze-candidate stamp removal: TD-11, FS-1/FS-2/FS-5/FS-6, (D0, PR #15),
issue 006, and the T2E / fenced-clear ruling attributions. Every rewrite is
comment-only; each surviving contract clause is unchanged in meaning and its
pinning test or code site is recorded in the cleanup inventory.

Both detection sweeps now return zero for store6-core/src.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: amend plan with Sweep v2 and Task 3b (execution amendment A1)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(core): clear design-doc referents surfaced by widened sweep

Applies Sweep v2 (plan Amendment A1) to store6-core/src, clearing the
referent families the original Detection sweep does not match: design-doc
section references (engine-design §7, R3, R7), acceptance/test/criteria
tags (AC-3, AC-6, C-01..C-12, TEST-1, TEST-7), the row-7/8 design-table
reference, and bare zero-padded issue numbers (001, 004, 010/011, 016).

Hard pattern: 14 hits -> 0. Classify-only pattern: 8 hits -> 2, both
recorded as FP (internal shorthand inside executable string literals, in
SourceOfTruthHydrationRaceTest and KeyEnginePlanningTest, which are
protected content outside this pass's charter).

Notable: deletes the second KDoc paragraph of seam/TransactionalSourceOfTruth,
which prescribed an extension-side coordinated-decorator protocol on a
published @ExperimentalStoreApi interface. The interface's own contract
sentences, the confirmFresh caveat, and both @PARAM lines are kept; the
protocol remains documented where it is implemented, on
store6-extension-probe's CoordinatedTransactionalSourceOfTruth.

Every hunk is comment- or KDoc-only. Verified: root apiCheck,
:store6-core:compileKotlinJvm, :store6-core:jvmTest all BUILD SUCCESSFUL;
git diff of store6-core/api empty; Sweep v1 still zero for the module.
Inventory updated with a Task 3b section: 22 rows over 20 distinct lines,
P1 13, P3 3, P4 2, FP 2, Unverifiable 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(mutations): make KDoc contracts self-contained, drop internal issue references

Resolves all 269 Detection-sweep (v1) and Amendment A1 (v2) hits in
store6-mutations/src: 171 P1 bare provenance tags, 1 P2 governance stamp,
61 P3 speculative/stale future claims, 30 P4 rationales restated against the
components in this tree, 6 FPs recorded.

Behavioral guarantees survive verbatim in meaning. The facade's `runtime()`
returning null (pinned by MutationAckPathTest.rawWriteHandleUnreachable-
ThroughFacade) and the deliberate adopt-then-retire ordering on the ack path
(pinned by presentAck_appliesConfirmsFreshThenRetires and
absentAck_clearsThenRetires_andHasNoCanonicalKey) keep every clause; only the
labels are gone.

Several deleted sentences were not merely speculative but false in this tree,
since the journal storage, drain pipeline, conflict pipeline, tombstones and
durable parking have all landed: deadLetters() is no longer "always empty",
the conflict policy is no longer "stored, never executed", effects are
executed, and tombstones are recorded. Each was verified against code before
deletion.

Every hunk is comment/KDoc-only (mechanically checked: zero non-comment
changed lines). `git diff -- store6-mutations/api` is empty. Root apiCheck and
:store6-mutations:compileKotlinJvm pass; jvmTest runs 270 tests with one
failure, MutationJournalLincheckTest, which compiles to byte-identical
bytecode with and without this change and is a pre-existing flake.

One Sweep-v2 hard-gate hit is deliberately left: MutationRestartWalkingTest
keeps `error("The AC-4 LocalOnly scenario must not fetch")`, where the
referent sits inside a string literal in executable code.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(mutations): restate conflict-repeat bound on merge door; wrap fix

Review follow-up, three fixes.

1. The public `conflicts { merge { } }` KDoc lost its bounded-repeat contract
   under the P4 delete-fallback, but the bound is restateable from code:
   CONFLICT_UNCHANGED_BOUND = 3 (MutationEngine.kt:62) is applied at
   MutationEngine.kt:2226, where a trailing run of conflict receipts carrying
   identical server metadata (non-null conflict meta, equal etag and
   writtenAt) parks the execution with a normalized CONFLICT failure
   (detail "conflict-unchanged-bound"). Restated on the merge door, together
   with the merge-throws park (detail "merge-failed"). Pinned by
   MutationConflictTest.unchangedRepeatedConflictEventuallyParks. The
   inventory row is reclassified P3 -> P4 (it had been P3, since the first
   pass deleted rather than restated) and now records both code sites, so
   no row in this module ends on the delete-the-rationale fallback.

2. Re-wrapped MutationEngine.flushRetirementCheckpoint's KDoc: the previous
   pass left a 163-column line, the module's only comment line over 100
   columns. No formatter catches this, since ktlint and spotless are both
   no-ops for store6-* modules. Every remaining >100-column comment line in
   the module is byte-identical to its form at 1d1607a.

3. Added the inventory row for MutatorRegistry.kt:38, where the published
   MutatorRef KDoc's graduation-review waiver was deleted. No sweep pattern
   matches "R-2a", so the row is recorded as a non-sweep addition and
   excluded from the 269 measured sweep hits; the table now holds 270 rows.

Class counts are now P1 171, P2 2, P3 60, P4 31, FP 6, Unverifiable 0.

Both source hunks are comment/KDoc-only. `git diff -- store6-mutations/api`
is empty; root apiCheck and :store6-mutations:compileKotlinJvm pass; both
sweep hard patterns remain clean over store6-mutations/src apart from the
already-reported string-literal boundary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(adapters): remove internal references from room, sqldelight, compose, mutations-sqldelight

Resolves the 23 remaining unclassified Task-1-baseline hits across the four
adapter modules plus 10 additional Sweep-v2 hits enumerated fresh for this
task: 4 in store6-room, 5 in store6-compose, 1 in store6-mutations-sqldelight
(protected, FP), 0 in store6-sqldelight. 33 rows classified: P1 29, P3 1,
P4 2, FP 1.

P1: bare `TD-6`/`TD-8`/`(OQ-3)`/`(D0, PR #15)` tags and leading test-doc tags
(`FS-#`, `AC-#`, `Issue-017 convention:`, `017 residual-deadline repair:`)
deleted, sentences otherwise unchanged. The two room Turbine-deadline
comments now read as the equivalent wording already landed in store6-core's
conformance tests.

P3: RoomSourceOfTruth's nested-transaction paragraph dropped its "for the
future TD-11 mutations decorator" framing; the remaining sentence documents
withTransaction's current nested-write contract, pinned generically by
RoomTransactionalSourceOfTruthTest's nestedWrite_outerRollback_never-
PublishesEcho and nestedWrite_outerCommit_publishesEchoOnlyAfterCommit.

P4: StoreResultEquivalence's "issue-007 OQ-1 ruling" restated as
conflateLatestData's own documented contract (verified against
store6-core/internal/StoreResultFlows.kt and the quoted StoreResult.kt
Revalidated KDoc); CollectAsStateWithLifecycle's "landed issue-007 bounded
registry" restated as "the bounded key registry" (verified against
store6-core/internal/KeyRegistry.kt and StoreBuilder.maxIdleKeys).

FP: SqlDelightMutationRestartWalkingTest's error("... AC-4 ...") message is
inside an executable string literal, out of doc-pass charter.

Every hunk is comment/KDoc-only (hunk-reviewed by hand and by grep-filtering
added lines for anything not starting with `*` or `//`). Verified: root
apiCheck, module compileKotlinJvm for all four modules, jvmTest for room/
sqldelight/compose (re-run with --rerun-tasks) all BUILD SUCCESSFUL with
zero failures; git diff of */api empty; Detection sweep v1 + Amendment A1
v2 both zero across the four module trees except the recorded FP.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: clear internal references from testing, devtools, and test sources

Task 6: full Sweep v1+v2 enumeration over store6-testing,
store6-mutations-testing, store6-devtools, store6-devtools-inspector,
store6-benchmarks, store6-quickstart, store6-extension-probe,
store6-compose-demo, and store6-devtools-demo. Resolves 20 module-scope
provenance/referent hits (16 Task-1 baseline unclassified + 9 Sweep-v2
additions, minus one line already resolved as baseline) plus 3
controller-named residue items in already-cleaned store6-core files
(StoreDurableMaintenanceConformanceTest.kt, StoreConformanceTest.kt,
KeyRegistry.kt). Relabels the Task 3b StoreTelemetryTest.kt:114 inventory
row from P1 to P3 to match its P3-shaped edit.

Full-tree Sweep v1+v2 gate (store6-*/src) is now clean except previously
recorded false positives (test-fixture data literals and error(...)
string-literal referents in executable test code).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: interface KDoc audit fixes for alpha01 artifacts

Audits every public declaration in the commonMain source sets of the six
alpha01 artifacts (628 declarations) against the interface-documentation
checklist, records the findings table in the plan inventory, and applies the
recorded fixes.

Missing contracts written from code evidence: per-constant docs for
MutationFailureKind; @return and @throws for MutationStore.mutate; @throws for
the mutationStore factory; per-property docs for KeyStatus and
FreshnessContext; a class KDoc for FakeStoreInteraction and per-member docs
for FakeStore's scripting and inspection surface; a class KDoc for
FakeFetcherInvocation; the terminal/nonterminal split on
MutationExecutionPhase; the null-wallClock default on SqlDelightSourceOfTruth.

Stale and contradictory claims corrected: Freshness.LocalOnly no longer
promises fetcher-less stores in a later release; RoomBookkeeper no longer
describes RoomSourceOfTruth.withTransaction as a future capability when it
ships today.

Narration and per-declaration governance stamps removed from StoreBuilder,
TestStoreMeta, TestWallClock, and the three store6-compose entry points.

Also clears internal referents that neither detection sweep matches (FR-10,
R-0 rule 9, C8-15, Rows 3/10, T5.5, T2.2, Decision #37, phase0 item 36, and
the remaining "landed" adjectives) from the audited modules.

Comment and KDoc content only: no executable token changes, every api dump
byte-identical, apiCheck and the six JVM compilations green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: address Task 7 review findings; clear remaining known referents

Review findings:

- MutationJournalRecords: fully qualify the MutationPendingState link. The
  file's package is mutations.storage and the type lives in the parent
  package, which is not in scope for a subpackage and is not imported here,
  so Dokka rendered it as plain text.
- StoreWriteHandle.confirmFresh: split the relocated guarantee back into its
  own sentence. Joining it to the empty-residence clause with a colon had
  narrowed an unconditional guarantee to that one branch.
- MutationExecutionRecord: document the six properties whose contracts the
  init block already pins - clientSequence, currentGeneration, attempt,
  lastAttemptAt, activeFailureId, retiredAt - each written from its own
  require. The remaining 81 of 92 record properties stay deferred, now
  scoped to the fields with no init pin behind them.

Also clears the last four internal referents, in store6-mutations-testing's
contract kit, so no known referent remains outside the recorded
protected-content false positives; rewords a tautology left by an earlier
parenthetical removal; and reconciles the Task 7 inventory arithmetic, whose
row totals, class totals, and scope note disagreed. Sufficient is now 485,
computed from declarations rather than by subtracting row counts.

Comment and KDoc content only: no executable token changes, every api dump
byte-identical, apiCheck and the touched compilations and test tasks green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: source-doc cleanup completion report

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: apply final whole-branch review polish

Apply the final whole-branch review's Minor items as one comment/KDoc-only
pass, plus four inventory corrections.

Source: drop the unsupported "single custom operator" rule claim from
StoreResultEquivalence.kt (store6-core states no such rule; only the
conflateLatestData operator itself exists); drop "ratified" from
internal/FreshnessValidator.kt; fix the drainFailuresForInspection category
error and rename the codec-less path's generation comment away from the
"in-memory" sense that MutationStoreBuilder.kt uses for journal storage;
restate the emptied Iface tier clause in StabilityProbe.kt against what the
CI gate actually asserts; repair "nested inside" in three room hostTest
comments; document the FreshnessContext.status sibling; repair a
mid-sentence comment opening in MutationStoreBuilderTest.kt; reflow nine
ragged comment blocks (line breaks only); collapse six one-sentence KDoc
blocks that became three-line only because this branch removed their second
paragraph.

Inventory: remove an invented line-37 citation, correct the TestWallClock
evidence note to signature-narration grounds, add the verified parked-row
pin (publishDurablePark retires at MutationEngine.kt:2551, MutationJournal
retire filters at MutationJournal.kt:313), and record this polish pass plus
the accepted-as-is items in the completion report's residue section.

Verification: root apiCheck and the five module jvm compiles BUILD
SUCCESSFUL; :store6-room:jvmTest (the task covering the hostTest source set)
59/59 green; :store6-testing:jvmTest 54/54 green; :store6-mutations:jvmTest
270 tests, 1 failure — the pre-existing MutationJournalLincheckTest hang
already recorded as change-independent, in files this commit does not touch.
Both hard sweeps return only the recorded out-of-charter string-literal
residue. git diff over */api empty at every scope.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(core): revert two polish wraps per final review

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…CI comments (#32)

Extends the alpha01 source-doc cleanup (KDoc/comments) to the surfaces its
charter excluded: store6-*/README.md, store6-devtools/EVENTS.md, and workflow
comments. Deletes issue numbers, decision/requirement tags (FS-10, OQ-6, OQ-3,
DR-3, METRIC-1, NFR-8, TEST-7, Ruling B), sign-off and ratification stamps,
personal names, and a pointer to a private non-repo doc. Freeze-status
language is aligned with STABILITY.md ("freeze candidate, not frozen").

Workflow YAML is structurally unchanged: store6-benchmarks.yml parses
byte-identically to HEAD modulo comments; store6.yml differs only inside one
run block's shell comment plus a log-message string in an awk branch that is
dead at the shipped iface_strict=1.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The store6 convention plugin never applied org.jetbrains.dokka, so no
dokkaHtml task existed for any store6-* module and their KDoc could not
be generated or link-checked. Apply the plugin in configureStore6Module()
and reuse the existing configureDokka() helper (reportUndocumented=false,
skipDeprecated=true, jdkVersion=11), covering both the full and subset
plugin variants.

Verified: dokkaHtml builds green with real HTML output for all ten
store6 modules. Note for future link checks: Dokka 1.9.20 renders
unresolved KDoc comment links as plain text without logging a warning
(verified with a canary link at --info), so link health must be checked
by grepping build/dokka/html for data-unresolved-link, not by reading
the build log.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…utations JVM suite (#34)

Ruling: 031 remedy ruling: RD-1=3 RD-2=b RD-3=A RD-4=—. Default jvmTest excludes the Lincheck budget via a property-gated filter (census-guarded in both required lanes); the scheduled Store6 full mutations JVM suite workflow (daily + dispatch, 360m) owns the full suite. Demonstrated attempt-1 at 94b9337: CI 25m34s / Store6 25m45s green, census 33/33.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: add AGENTS.md instructing documentation discipline

Governs every documentation surface agents touch in this repo: the master
test, protected technical content, the no-internal-context rule for code
surfaces (with the durable-attribution alternative), evidence-before-claims,
byte-identical sibling comment conventions, and the three-pass review. Names
the authoring skills as the preferred entry point where available; the inline
rules stand alone otherwise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: embed the documentation skills in-repo and point AGENTS.md at them

Copies documentation-discipline (2 files) and code-documentation (13 files)
verbatim from the authoring plugin into .claude/skills/ so any agent working
in this repository gets the full rules without the plugin installed — skill
harnesses invoke them by name; anything else reads SKILL.md and references/
directly. AGENTS.md now names the embedded copies as the source of the full
rules, with its inline summary standing alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…suites (#35)

CI-green Phase 1.1. MutationEventSurfaceTest carried the plain one-line 25s
shadow and MutationOverlayReplayPropertyTest used inline runTest(timeout=25s)
at three sites while both make Turbine awaits. Under runner load Turbine's 3s
default nested inside the shadow (register class (b) exposure). Both now carry
the shim wrapper (TEST_TIMEOUT 25s / TURBINE_DEADLINE 30s) so the shadow is
the sole effective deadline. The wrapper matches the established shape; its
comment is reworded to the repository documentation discipline (AGENTS.md),
which the sibling carriers predate.

Coverage determinations recorded: MutationsTestFixtures defines no test runner
(its Turbine helper inherits the caller's deadline context). The
store6-mutations-sqldelight tree has zero Turbine files. store6-room already
carries the shim. Test-only change with no assertion, budget, or production
edits. Local proof: both suites green.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ll carriers (#37)

Comment-only sweep (36+/36-, 18 files across store6-core, store6-mutations,
store6-room). Two legacy variants of the shim comment existed; every carrier
now matches the repository documentation discipline shape with byte-identical
wording. No code, measurement, or deadline token changed; test classes of all
three modules compile.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(mutations): fence alias projection replay

* fix(mutations): snapshot projection state once

MutationEngine.kt: projectAll captures one storage-backed runtime
snapshot and one tombstone snapshot, then threads their entries and
aliases through filtering. Projector application and sequence order
remain behaviorally equivalent.

MutationEngine.kt: orderedPending and replayableEntries now accept
captured entries, aliases, and tombstones. Call-site ripples are
pendingForIdentity, pendingWrites, projectAll, pendingRows,
nextEligibleHead, and the retireAndActivateAlias legacy rehome branch.
Selection, filtering, and FIFO behavior remain equivalent.

MutationEngine.kt: pendingWrites derives storage-backed entries and
routing from the same runtime snapshot, uses one tombstone capture, and
preserves durable client-sequence ordering.

MutationJournal.kt: add only InMemoryAliasRouter.aliasesSnapshot for
the behaviorally equivalent non-storage call-site adaptations.

* refactor(mutations): require storage-backed journals

The census found 65 MutationEngine construction sites: one production and
64 commonTest. Product construction already used storage-backed journals.
The only non-storage inputs were two RetireOrderingJournal uses and one
ClearOrderingJournal use; every aliasHarness caller already supplied the
storage-backed default or a subclass.

- MutationEngine.kt narrows the constructor, removes redundant storage/null
  branches, and captures one runtime and tombstone snapshot per projection.
- MutationJournal.kt removes the unused InMemoryAliasRouter snapshot accessor.
- MutationAckPathTest.kt migrates RetireOrderingJournal and
  ClearOrderingJournal to in-memory-storage-backed subclasses.
- MutationAliasFacadeTest.kt narrows aliasHarness to the storage-backed seam.

F2 is superseded and removed: its legacy emitted-stamp bump is deleted and
no legacy trigger is added. NonCancellable ordering, alias revision and
resolution pulses, live-key cache publication, retirement accounting,
source/target emissions, ordering assertions, and projection behavior are
preserved.

* test(mutations): fence alias projection replay

Carry ProjectionRecomputeVisibilityProbeTest from a23ff03 with the approved kotlinx.coroutines.Runnable portability import; keep the probe body unchanged.

Add publicFacadeFreshAttachAfterAliasPublication_firstFrameIsCompleteOverlay through the public mutationStore factory with AliasActivationCommitGateStorage holding the post-commit activation boundary.

* test(mutations): expose active alias window

Add a deterministic fresh-attach regression at the runtime ACTIVE publication boundary. It retains the target head frame and expects the complete head+tail overlay.

* fix(mutations): close alias publication window

Serialize durable ACTIVE publication and its target fence stamp behind a narrow mutex. Capture facade resolution signals as one close-aware epoch before resolver and delegate work.

* test(core): await live reader subscription

Replace the reader-factory latch with a subscription-count barrier
before releasing the queued-absent fetch. This prevents a zero-replay
SharedFlow emission from being dropped before the KeyEngine collector
attaches.

* docs(core): make projection probe self-contained

Describe the pending recompute experiment in durable technical terms. Preserve the first-frame measurement and convergence assertion boundary.
* ci(docs): guard synchronized sources

* chore(docs): guard Room sync source (STORE-31)
* docs(store6): publish guide and mutation contracts (STORE-33, STORE-34)

* docs(quickstart): certify migration result snippet (STORE-35)

* docs(llms): publish only visible guide routes (STORE-33)

* fix(mutations-testing): specify purity key type
* docs(dokka): add Store 6 module framing (STORE-28)

* docs(dokka): restore guide escape links (STORE-28)
* feat(plugins): add store plugin with Store 6 migration skill

Store 6 is unpublished, so coding agents in consumer apps invent its API
when porting from Store 4/5. The migrating-to-store6 skill ships verified
translation tables and a worked port, with an eval recording the failing
no-skill baseline and the passing with-skill run.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(plugins): address store plugin review

Replaces the unreal store.cached(key, refresh = true) Store 4 spelling
with store.stream(StoreRequest.cached(key, refresh = true)), adds the
missing Initial row to the origins table, notes that core's experimental
overlay seam can also produce OVERLAY, and ships plugin.json plus
schemastore $schema keys for editor validation.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…tor interop over any Store (#47)

* store6-paging-androidx: TD-14 mapping, catalog pins, module scaffold, de-risk spikes (T1)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* store6-paging-androidx: StorePagingSource single-shot stream-first load + builder doors (T2)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* store6-paging-androidx: generation watcher — level-triggered invalidation wiring, KeyEvents-free (T3)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* store6-paging-androidx: MobileNativeFoundation#602 tracer — OVERLAY→SOT over MutationStore, honesty-tiered (T4)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* store6-paging-androidx: StoreRemoteMediator boundary-freshness surface (RD-2 shape) (T5)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* store6-paging-androidx: headless four-scene Paging3 sample (roadmap:53 exit) (T6)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* store6-paging-androidx: CI registration (build, sample, gates, apple, klib, JS canary) and ABI dumps (T7)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: update paging release promise

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(store6-paging-androidx): await watcher completion

Wait on the completion StateFlow instead of inferring completion from the preceding active-collector decrement. This removes the scheduler-dependent assertion ordering exposed by the Android release unit-test lane.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(paging): harden refresh and watcher lifecycle

Use the configured initial load size for mediator refresh keys, preserve Store error causes, and make generation baseline failure and cancellation bounded. Document the pager and namespace lifecycle obligations while removing internal delivery context from tracked documentation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* docs(plans): add STORE-38 data-layer skill plan

Records the RED-first plan for the building-a-store6-data-layer plugin skill.

* feat(plugins): draft building-a-store6-data-layer skill and eval scaffold (STORE-38)

Adds the greenfield Store 6 data-layer skill, Room/SQLDelight/Compose/Swift
references, and the RED-first eval fixture plus pass criteria.

* test(plugins): record data-layer skill eval runs (STORE-38)

Records the RED baseline, with-skill pass (12/12), retrieval probes, and
the two SKILL.md gaps closed after the first with-skill notes.

* chore(plugins): register data-layer skill, bump store plugin to 0.2.0 (STORE-38)

* fix(plugins): data-layer skill review pass (STORE-38)

Tighten StoreBuilder wording (DSL receiver exists; StoreBuilder.from does not)
and stamp swift.md at 6790606.
* Scaffold store6-graphql module and headless JVM sample

Full 12-target convention plugin, api(store6-core) as the only commonMain
dependency, 6.0.0-SNAPSHOT publishing coordinates, and a placeholder
sample entry point. Sample registers as :store6-graphql-sample with
projectDir store6-graphql/sample, matching the paging sample layout.

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

* Add GraphQL value model, operation key, and fetcher adapter

GraphQlValue mirrors the GraphQL input grammar with structural equality;
GraphQlOperationKey renders canonicalId as <name>(<canonical vars>) with
UTF-16-code-unit-sorted object keys, JSON string escaping, significant
list order, and explicit null distinct from absent. graphQlFetcher maps
executor outcomes onto FetcherResult: NotModified passes through, errors
follow the partial-data policy (fail by default, adopt on opt-in), null
data without errors is a protocol violation, key/operation mismatch
fails without executing, and CancellationException propagates.

Pinned by GraphQlCanonicalizationTest (17 cases) and
GraphQlFetcherMappingTest (14 cases), green on jvmTest.

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

* Add store-integration suite over real store { }

GraphQlStoreIntegrationTest exercises the adapter through the engine:
document-cache serve without re-execution (including across variable
insertion orders), concurrent readers sharing one execution, MustBeFresh
re-execution, conditional NotModified emitting Revalidated with ETags
threaded both directions (tolerating the legal cold-baseline self-heal),
and response errors surfacing as StoreError.Fetch frames and
StoreException causes carrying GraphQlOperationException. Fixtures follow
the paging ScriptedPageFetcher shape. 8 cases, green on jvmTest.

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

* Flesh out store6-graphql sample with asserted scenes

Four scenes over an in-process scripted executor, each check()-asserted:
variable-order-independent key identity, document-cache serve without
re-execution, the fail-vs-adopt partial-response policy split, and
conditional NotModified revalidation with recorded ETags. Exits nonzero
on any failed assertion so CI can gate on the run.

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

* Wire store6-graphql into store6.yml and commit BCV dumps

Build and sample-run steps after the paging steps; module added to the
core-internal access grep, the TD-8 production-source sweep, the JS and
Apple test lanes, the publish list, and the publication census (full
12-target module, so no census case exclusion). BCV dumps generated via
apiDump with klib cross-compilation enabled.

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

* Add store6-graphql README

Package promise and boundary (document cache, executor owns the wire),
Maven Local install path, first-result example, entry points, the
canonical-identity contract with the FloatValue cross-runtime caveat,
the response mapping table, conditional-request behavior, and the
asserted sample scenes. Not registered in docs-sync-sources.txt; site
registration is raised in the PR.

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>
… cancellation (#51)

cancellationAfterAliasCommit_stillPublishesRevisionAndSwitchesLiveStream
asserted provisionalObserved.isCompleted and canonicalObserved.isCompleted
immediately after joining the cancelled drain. The emissions complete inside
the NonCancellable handoff before join() returns, but the observing collector
is dispatched separately, so the asserts raced the collector by one dispatch.
Observed on the Android debug lane: canonicalObserved.isCompleted was false.
Await both observations instead; the suite-level runTest shadow owns the
deadline, matching the sibling regression tests that already await an
observation barrier before asserting.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>
* feat(store6-realtime): add transport-agnostic realtime push adapter

Map app-owned realtime frames onto Store invalidate/adopt/clear through
StoreWriteHandle, giving the freeze-candidate write seam a second real
producer without changing store6-core.

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

* fix(store6-realtime): pin etag list types and stabilize the sample

Specify String? on the conditional-fetch etag assertions so commonTest
compiles, and prove sample adoption through KeyEvents.Written rather than
a racy LocalOnly origin read.

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

* fix(store6-realtime): pin watermark stale-marking and telemetry contracts

Correct the README telemetry section so apply/confirmFresh match KeyEngine
emission. Rewrite the vacuous MustBeFresh watermark and MutationStore tests
to assert FakeBookkeeper.durablyStale and MaxAge refetch. Inline the unused
RecordingFetcher.nextValue hook.

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

* test(store6-realtime): drain the queued pre-clear replay after Deleted

deleted_emitsLoadingThenRefetch asserted Loading strictly as the next frame
after the Deleted clear, but a fenced clear may queue one duplicate pre-clear
Data frame for an already-active pipeline. Adopt the bounded drain shape that
core's StoreInvalidationConformanceTest uses for the same window. Observed on
the Android release lane: assertIs<Loading> received Data(fetched-1).

Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Matt Ramotar <matt-ramotar@users.noreply.github.com>
Records ancestry with upstream's store6 tip (f45df77, the Store 5 build
modernization) while keeping main's tree byte-for-byte. The following
commit removes the Store 5 modules from this branch, so the
modernization has no remaining scope here; Store 6 modules stay on
their pinned toolchain.
Deletes the store, cache, multicast, rx2, and core modules and their
settings.gradle includes; no store6-* module depends on them. Drops the
kover build step and Codecov upload from CI (kover was applied only in
the store module) and the KMMBridge Swift-package workflow (only the
Store 5 convention plugin applied KMMBridge). Adds store6 to the CI,
Store6, and benchmarks workflow branch filters so pull requests into
store6 and pushes to it run the same gates as main.

Co-authored-by: Cursor <cursoragent@cursor.com>
@matt-ramotar matt-ramotar added the docs-sync-ack Acknowledges that a PR changes Store Docs sync sources and requires a follow-up re-pin label Aug 16, 2026
@matt-ramotar
matt-ramotar merged commit 12cd18b into store6 Aug 16, 2026
12 of 14 checks passed
@matt-ramotar
matt-ramotar deleted the merge-main-into-store6 branch August 18, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs-sync-ack Acknowledges that a PR changes Store Docs sync sources and requires a follow-up re-pin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant