New artifacts:
arts/timr — runtime timer scheduler (singleton-per-App, never global).
Engine + Active split. Race-safe via (id, key, version) guard against
stale native callbacks, async tasks resolving after cancel/replace,
interval ticks scheduled after dispose, and ack-style timeouts. Per-
entry AbortController; intervals reuse the signal across ticks.
awaitTask:true (default, no overlap) vs awaitTask:false (fire-and-
forget cadence; failures don't stop the interval — semantic frozen).
Recursive setTimeout for intervals. scheduleAt(past) → delay 0 (no
error). Fake-clock injectable for deterministic tests. Pure
computeBackoffDelay helper. 50 server tests + 7 browser tests + full
README + DESIGN_TIMR + interactive test page at /test/timr.
arts/sess — session lifecycle with three generics
(TUser/TCredential/TData) plus optional SessionActor metadata
(kind/source/confidence — orthogonal axis to identity).
Tagged AdoptResult/RefreshResult/RevokeResult; never void.
Generation guard against stale refresh from local cancel, cross-tab
storage events, or re-adopt. onRefresh contract (null=fatal,
throw=transient). onRevoke replaces revokeUrl (consumer controls
fetch; engine just gets boolean). Default scope: 'global' when
onRevoke configured. INITIAL_SESSION sync dispatch on subscribe.
BroadcastChannel payload: {type, event, generation} only — never
tokens. SSR cookie reader validates invariants. withAutoRefresh
helper, 401-retry hook with applyAuth + loop guard, JWT exp helper.
103 tests (60 server + 5 browser + 38 actor/error/etc) + README +
DESIGN.md + test page at /test/sess.
arts/http — HTTP client with Standard Schema body validation, retry
+ Retry-After, attempt + total timeout via AbortSignal composition,
hooks (beforeRequest/beforeRetry/afterResponse/beforeError),
tagged HttpResult. Test page at /test/http.
arts/conn — DESIGN_CONN.md only (no implementation yet).
aapp:
- App.createActiveSession<TUser, TCredential, TData>(opts) factory
auto-injects App.Logger; throws SessAlreadyCreatedError on second
call. App.Sess getter exposes the active session (undefined until
first call). Auto-disposed by App.dispose().
- App.Timers integration deferred to timr Fase 3.
libs/days:
- toEpochMs(value) — permissive coercion (number | Date | string) →
epoch ms. Exposed alongside the existing day/calendar helpers.
Other:
- sium examples moved to _examples/ (excluded from public surface).
- sium-provider.svelte test removed (port pending; tracked elsewhere).
- libs/env.ts — DEV flag single source of truth.
- Various README touch-ups across artifacts.
All artifacts: 1021 server tests + 12 browser tests; svelte-check + ESLint
clean. The 9 server "errors" are pre-existing jsdom missing — unrelated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cross-cutting features added in the previous two commits were not yet
referenced from the upper-level READMEs. Sync them so the documentation
matches the code:
- aapp/README: new "Reactive keys" + "Cross-tab sync without polling"
subsections under Storage; composition order block now lists Storage
(was missing) and Frontend persist wiring.
- arts/README: stor row updated with `withBroadcast` and `dynamicEntry`;
artifact name corrected (storage → stor); /test/stor added to the
test pages list.
No code changes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the two implementables from the deferred list:
- withBroadcast(adapter, { channel? }): cross-tab synchronization wrapper
that uses BroadcastChannel — no polling, instant delivery. Wraps any
SyncStorageAdapter (especially useful for cookies, which lack a native
change event). Replaces the inner adapter's onChange to avoid duplicate
delivery; same-tab self-posts are spec-deduped. Exposes close() for
short-lived adapters; SSR-safe with a passthrough fallback.
- Storage.dynamicEntry(keyFn, defaults, options?): reactive-key entry
for cases like 'user-${userId}:profile' where the storage key tracks a
runed variable. When the key changes, the underlying entry is rebuilt,
the previous one disposed, and onChange listeners migrate across the
swap. Must run inside a Svelte component or $effect.root.
Re-exported from $aapp alongside the other adapters for ergonomic
single-import.
19 new tests: 10 for withBroadcast (with a fake BroadcastChannel that
mirrors the spec's same-context dedup), 6 for dynamicEntry (reactive
rebind, listener migration, dispose isolation, per-entry override
preservation), plus 3 audit additions (entries() introspection, refcount
registry, client cookie coverage) carried from the prior commit.
762 tests passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the three remaining items from the storage audit backlog:
- entries(): introspection snapshot of every live entry with
{ key, fullKey, adapter }. Useful for devtools panels and audit logs.
Read-only metadata — no entry handles exposed.
- registeredDefaults refcount: the conflict registry now tracks how many
live entries point at each (adapter, fullKey) and forgets the slot when
the count drops to zero. Re-creating a key with a different default
after the previous owner cleaned up no longer emits a stale warning.
When at least one owner remains, the diagnostic still fires.
- Client cookieAdapter() coverage: 8 tests with a mocked `document` (no
jsdom dependency) covering setItem/getItem/removeItem, encode/decode
defaults, custom encoder pair, Set-Cookie attribute building (path,
samesite, secure, max-age, domain), sameSite=none auto-secure and
multi-cookie parsing.
Cookie polling for onChange remains intentionally out of scope —
documented in README under "Cross-tab sync".
746 tests passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the application composition root and six new runtime artifacts. lang
and logr alone could not cover an app surface — locale propagation, format
helpers, frontend preferences, validation, persistence and DOM service all
needed independent artifacts that aapp wires together under a single
locale source of truth and a shared logger.
New artifacts:
- aapp: composition root. createActiveApp + createTestApp +
App.createSiumEngine + frontend.persist + Storage wiring.
- stor: pluggable adapters (local/session/memory/cookie + SSR via
cookieAdapter.fromCookies), envelope versioning + migrate +
TTL, validate via Standard Schema, intra-tab + cross-tab sync,
Storage.clear(), per-entry adapter/namespace overrides.
- adom: reactive DOM service. shareViewport opt-in + per-window
tracker, dispose(). breakpoints, viewport, attribute writes.
- fend: frontend preferences (theme, mode, dir, density,
reducedMotion, reducedSound) with auto/clear/isAuto pattern.
- fmts: localized formatting (numbers, currency, units, dates) with
shared LocaleSource and per-domain auto/clear pattern.
- sium: validation engine. Standard Schema interop, Lang/Logger
injection, codec/refine/transform, domain types
(color/date/time), introspection.
Existing artifacts extended:
- lang: BCP 47 SupportedLocale (LangBase | base-region), mono lang
for monolingual apps, extend() leaf-overwrite warning,
EngineLang/ActiveLang naming alignment with the rest of the
project (no Instance suffix).
- logr: EngineLogger.dispose(), failureThrottleMs anti-cascade for
transports, README sync to the per-level filter API
(minLevel removed).
Cross-cutting:
- $locale: shared LocaleSource type consumed by fmts and fend.
- arts/README.md: artifact map, dependency graph, naming conventions.
- Test pages for every artifact under /test/<artifact>.
733 tests passing; svelte-check clean except 2 pre-existing errors on
sium/svelte provider (port pending).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- logr README: restructure the Vitals + Sentry section into two clearly
separated delivery paths. Path A (via the logger → sentryTransport)
reaches Issues/breadcrumbs; Path B (via Sentry's browserTracingIntegration)
reaches the Performance/Insights product. Add a decision table covering
the five common use cases (aggregate dashboards, triage breadcrumbs,
alerts on poor ratings, non-Sentry backends, dev validation) with the
recommended path for each, and document the production combo of Path B
for analytics plus Path A at `breadcrumbLevel: TRACE` for error-context
breadcrumbs.
- Test page: enable Sentry.browserTracingIntegration() with
tracesSampleRate=1.0 so the page load emits a real transaction visible
under Insights → Browser → Web Vitals, in addition to the logger-based
vitals that already land as Issues. Promote every vital rating to ERROR
in the test page override so good/needs-improvement samples also surface
in the Issues feed — useful to validate end-to-end.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
logr:
- entry.id auto-generated (UUID v4 / hex fallback) — survives backend dedup, batched-retry, cross-transport correlation.
- Transport.levels replaces minLevel — per-level { enabled, filter? } record. More flexible: enable/disable individual levels, attach per-level filters. Helper levelsAtLeast(level) for the common min-level case; allLevels() for the permissive case.
- Transport buffering: buffer, flushIntervalMs, writeBatch on the Transport interface. Logger tracks per-transport queues, flushes on size/time/flush()/detach/beforeunload. httpTransport and lokiTransport implement writeBatch for true batched HTTP delivery.
- logger.flush() to drain all buffered transports manually.
- Web Vitals integration (src/arts/logr/vitals.ts): registerWebVitals(logger, webVitalsSDK, options?) turns LCP/INP/CLS/FCP/TTFB samples into structured log entries tagged with route/rating. Zero-deps in logr — SDK is injected.
- ConsoleTransportOptions now exposes filter so vitals can be silenced on console while still flowing to Sentry/Datadog/Loki.
- Runtime name constant: `engine_logger` (via src/arts/logr/consts.ts) replaces hardcoded 'logr' string in failure reports, console prefix and synthetic entry tags.
lang:
- README expanded with a dedicated section on ts() and the LangString type: plain strings, LangRecord, LangRef; the `message: LangString` prop pattern for generic components; when to use the isLang* guards.
Tests: 185 passing (added vitals + buffer + entry.id coverage).
Docs: logr README now documents vitals (hot-zone patterns for LogQL / Sentry Discover / Datadog), buffering, the levels config, and the helpers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>