Feature 125 taught four components to recover what stands from the coverage store rather than only from a live announcement. backend/lib/standing-run.ts names the analyst among them and the analyst was not reached.
Its own docstring:
run_published is the only statement that a forecast stands, and four components hold nothing but what it told them: the scheduler its remaining validity, the offload packager the run it would stage, the analyst the spread field its next background covariance is built from, and telemetry the run its skill is scored against. Each learns it once, from the model runner, and keeps it in memory — so any component that was not listening when the run was published has no way back to it.
Against main at b13a22a:
| component |
references to standing-run.ts |
scheduler/scheduler.ts |
2 |
telemetry/telemetry.ts |
2 |
model-runner/runner.ts |
1 |
offload/packager.ts |
1 |
analyst/analyst.ts |
0 |
The analyst learns its spread holding in one place, from a live announcement:
// analyst.ts:152
if (published.current) this.spreadHoldingId = published.collections.uncertainty;
and reads it in one place:
// analyst.ts:199
const spread = this.spreadHoldingId ? this.store.holding(this.spreadHoldingId) : undefined;
What it costs
The situation standing-run.ts was written for: a start condition's artefact carries the forecast eras, so the model runner is held back for the whole pre-roll while the snapshot source replays the holdings it would have authored, and the announcement is never made. A reader who opens the console then gets an analyst with spreadHoldingId undefined, so the next cycle's background covariance is built without the spread that travels with the standing run. The same happens after a component restart from the Operator tab.
It is not visible on any surface, which is why it has outlived the feature that fixed its four siblings — the analysis still publishes, it is just built on a weaker B than the store could support.
What it is not
The reading side of this — the centre region showing no provenance at all on a snapshot-seeded visit — was reported against a running instance and is fixed in #111. That fix deliberately did not touch the analyst: an AnalysisPublished carries observations (assimilated, clamped, worst displacement) which are facts about a cycle that ran and sit on no descriptor, so an analyst rebuilding its own announcement would have to invent them, which ADR-0041 forbids in as many words. The region needed three collection names and now reads those from the holdings inventory instead.
This issue is the other half, and it is genuinely the analyst's: the spread holding is recoverable from the store's descriptors, by the same standingRunFacts / spreadHoldingIdFor route the other four use. Nothing is recomputed and no forecast is re-run.
Suggested shape
Adopt on the same cadence the siblings do — telemetry calls adoptStandingRun() on its cadence tick, idempotent and a no-op once adopted — so a restarted or replay-fed analyst recovers without a new announcement, and a live announcement still supersedes it.
Worth a test that the adopted id equals the one a live run_published would have supplied, since "the store's spread" and "the announcement's spread" agreeing is the whole claim.
Found while auditing outstanding work after #111 merged; raised rather than folded into that PR because it is a backend change and 125's territory.
Feature 125 taught four components to recover what stands from the coverage store rather than only from a live announcement.
backend/lib/standing-run.tsnames the analyst among them and the analyst was not reached.Its own docstring:
Against
mainatb13a22a:standing-run.tsscheduler/scheduler.tstelemetry/telemetry.tsmodel-runner/runner.tsoffload/packager.tsanalyst/analyst.tsThe analyst learns its spread holding in one place, from a live announcement:
and reads it in one place:
What it costs
The situation
standing-run.tswas written for: a start condition's artefact carries the forecast eras, so the model runner is held back for the whole pre-roll while the snapshot source replays the holdings it would have authored, and the announcement is never made. A reader who opens the console then gets an analyst withspreadHoldingIdundefined, so the next cycle's background covariance is built without the spread that travels with the standing run. The same happens after a component restart from the Operator tab.It is not visible on any surface, which is why it has outlived the feature that fixed its four siblings — the analysis still publishes, it is just built on a weaker B than the store could support.
What it is not
The reading side of this — the centre region showing no provenance at all on a snapshot-seeded visit — was reported against a running instance and is fixed in #111. That fix deliberately did not touch the analyst: an
AnalysisPublishedcarriesobservations(assimilated, clamped, worst displacement) which are facts about a cycle that ran and sit on no descriptor, so an analyst rebuilding its own announcement would have to invent them, which ADR-0041 forbids in as many words. The region needed three collection names and now reads those from the holdings inventory instead.This issue is the other half, and it is genuinely the analyst's: the spread holding is recoverable from the store's descriptors, by the same
standingRunFacts/spreadHoldingIdForroute the other four use. Nothing is recomputed and no forecast is re-run.Suggested shape
Adopt on the same cadence the siblings do — telemetry calls
adoptStandingRun()on its cadence tick, idempotent and a no-op once adopted — so a restarted or replay-fed analyst recovers without a new announcement, and a live announcement still supersedes it.Worth a test that the adopted id equals the one a live
run_publishedwould have supplied, since "the store's spread" and "the announcement's spread" agreeing is the whole claim.Found while auditing outstanding work after #111 merged; raised rather than folded into that PR because it is a backend change and 125's territory.