feat(signals,diagnostics): serializable re-run records, artifact timeOrigin (v7), observe idle-cost cap - #3493
Merged
Merged
Conversation
…RVE.subjectOf), artifact timeOrigin (v7), observe idle-cost cap observe-tier-plan PR B's remainder. `RerunEvent` drops the live `node` for `nodeId` — the engine's per-node id, stable across a scope's runs and distinct between scopes — so re-run records leave the process as emitted; `OBSERVE.subjectOf` answers for them as it does for diagnostic events, keyed by the record object for as long as a consumer holds it. Clocks: every `at` stays on the `performance.now()` clock; the anchor travels once as `DiagnosticsArtifact.timeOrigin` (format v7, JSONL meta, bridge payload) rather than a second clock per record. Re-runs are stored verbatim (`RerunRecord` = `RerunEvent`). `tests/observe-idle-cost.test.ts` caps the observe artifact's idle wiring at 1.25x the prod artifact on one workload in one process (measured 1.03–1.09), re-measuring a round over the cap so contention cannot fail it. The engine diet was measured (formatters ~4% of the engine) and is written up in the plan as a decision, not taken. Co-authored-by: Claude via Cursor <noreply@cursor.com> Co-authored-by: Cursor <cursoragent@cursor.com>
🦋 Changeset detectedLatest commit: 47601b5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Coverage Report for CI Build 35086846455Coverage remained the same at 71.46%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
…ps when unbuilt Literal '../dist/...' specifiers had the build's TS pass emit TS2307 on every build (tsconfig includes tests/) and the test hard-fail on an unbuilt checkout. Same pattern as treeshake.test.ts: resolved paths, describe.skipIf(!existsSync). Also corrects the cap's framing — 1.25 trips at ~3x today's 3–9% wiring cost, not a doubling. Tests-only. Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Merging this PR will improve performance by 16.9%
|
| Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|
| ⚡ | projection derive: write one NESTED field (reference) |
2.1 ms | 1.8 ms | +16.9% |
Tip
Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.
Comparing attribution-records (47601b5) with next (8c80a67)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The remainder of
observe-tier-plan.mdPR B: the attribution engine's records become wire-shaped before the RC stabilises, and the observe tier's idle cost becomes a cap.origin— the third leg of PR B — already landed through the Sentry workstream (withOrigin,CallEvent.origin,currentOrigin()).RerunEventis serializable as emittednode(a liveComputed) is gone.nodeIdnames the scope: the engine's existing per-node id — the oneChangeOrigin.runand the relay/cycle checks already key on — stable across a scope's runs in the process and distinct between scopes, so runs of unnamed effects still fold to one scope offline.OBSERVE.subjectOf(record), which diagnostics already had, now answers for re-run records too. Keyed by the record object, so the node lives exactly as long as some consumer holds the record — the lifetime it had when the record carried it. A copy that left the process has no subject.attribution.why(target)/subscriptions(target)unchanged. Only the engine's ownrecordCosts/why()and two tests read.node;@solidjs/diagnosticswas stripping it at three sites and now stores re-runs verbatim (RerunRecordis an alias ofRerunEvent).Clocks: the anchor travels once, not a
tsper recordEvery
atthe engine and the runtimes emit is on one clock,performance.now(), and exporters (the spike) already anchor withperformance.timeOrigin. A second clock per record would cost bytes on every record and drift against the first. InsteadDiagnosticsArtifact.timeOrigin(format v7; also on the JSONL meta line and the browser bridge payload) makes everyatin an artifact absolute after the fact — re-runs, holds, records, diagnosticdata— and lines a server capture up with the browser session it served. RFC 08 documents the contract.Idle wiring is a cap
packages/signals/tests/observe-idle-cost.test.tsruns one graph-heavy workload (1000 signal→memo→memo→effect chains, 10 write passes) against the built prod and observe artifacts in one process, interleaved best-of-5, and caps observe/prod at 1.25 — measured 1.03–1.09 with no hooks installed. A round over the cap re-measures (up to three): worker-thread contention is intermittent, a regression is not. Held across four full-suite runs with the web and solid suites running in parallel.Engine diet — measured, deferred
Ranking every engine function by minified weight: the console face (
formatRerun/formatCause/logRerun) is ~0.45 KB gz of the engine's 11.7 KB — 4% — andformatOriginanother 0.15 KB, which the spike calls for span names. The plan's premise is true but small. What a record-consuming production adapter never calls is the in-process query/fold surface (costs,feedback,why,history, ~1.5 KB gz); shedding it means splittingattributioninto tree-shakable named exports — an API change for ~2 KB (17%). Written up in the plan's PR B section as a decision rather than taken here.Verification
nodekey, JSON round-trip equal,nodeIdstable/distinct,subjectOfreturns the node,why()by accessor and by node), diagnostics 34, solid 620 + 825 types, web 986 + 185 types.@solidjs/signals,@solidjs/diagnostics(patch, prerelease).Deferred to release, per direction: the vite-plugin work (C5, the SSR
componentNamesbump).