Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
8b0222b
feat: persist typed local-device run coverage verdicts
tnunamak Oct 21, 2026
7fbcb76
build: refresh connector protocol artifact metadata
tnunamak Oct 21, 2026
a643d82
chore(collector-runtime): refresh artifact metadata
tnunamak Oct 21, 2026
eb4d266
feat(coverage): reconcile terminal store evidence with host accounting
tnunamak Oct 22, 2026
d7b6e89
chore(connector-protocol): refresh artifact metadata
tnunamak Oct 22, 2026
dced79b
chore(collector-runtime): refresh artifact metadata
tnunamak Oct 22, 2026
d282784
style(coverage): align touched code with Biome
tnunamak Oct 22, 2026
a3846e8
chore(collector-runtime): refresh artifact metadata
tnunamak Oct 22, 2026
449d8f0
fix(local-device): bind terminal coverage to the server pin
tnunamak Oct 22, 2026
2194b9d
test(local-device): make restart receipt match admitted batch
tnunamak Oct 22, 2026
aead40f
fix(coverage): derive terminal verdict from runtime evidence
tnunamak Oct 22, 2026
9632375
chore(collector-runtime): refresh artifact metadata
tnunamak Oct 22, 2026
b0b78ee
Bind coverage projection to the pinned release
tnunamak Oct 22, 2026
871fca5
fix(collector-runtime): regenerate artifact metadata for the release …
tnunamak Oct 22, 2026
25c9a22
test(local-collector): pin v2 receipts to the selected release
tnunamak Oct 22, 2026
324c6b4
fix(local-collector): mark receipts for another release not current
tnunamak Oct 22, 2026
ed95576
test(local-device): run coverage end to end through the real server
tnunamak Oct 22, 2026
f80388d
test(local-collector): cover unadmitted runs and unclean accounting i…
tnunamak Oct 22, 2026
db3d295
fix(local-collector): read unadmitted runs and unclean accounting as …
tnunamak Oct 22, 2026
cfa3769
test(local-device): close the journey servers with closeTestServer
tnunamak Oct 22, 2026
d55a6ca
fix(collector-runtime): leave an open failure gap for every failed run
tnunamak Oct 22, 2026
ee4e40d
chore(collector-runtime): regenerate artifact metadata for the failur…
tnunamak Oct 22, 2026
417f11b
test(local-collector): share the live-registry transport
tnunamak Oct 22, 2026
a70f67e
test(local-device): add the install-path journey (J2-install)
tnunamak Oct 22, 2026
90d0db7
ci(managed-connector-oci): run the install-path journey in the job
tnunamak Oct 22, 2026
43f2233
fix(local-device): retire a terminal proof superseded by a later stat…
tnunamak Oct 22, 2026
2c8ee6d
test(local-device): install-path journey uses the shipped collector path
tnunamak Oct 22, 2026
c19b6c2
test(local-device): cover the legacy diagnostics proof under the stal…
tnunamak Oct 22, 2026
283f4f9
test(local-device): move the install-path packager into test helpers
tnunamak Oct 22, 2026
84e0e44
Merge branch 'fix/coverage-stale-proof' into feat/local-run-coverage-…
tnunamak Oct 22, 2026
2a1fe6f
fix(collector): refused runs open the failure barrier
tnunamak Oct 22, 2026
9048467
fix(local-device): a delivered failure gap keeps the lane unadmitted
tnunamak Oct 22, 2026
6270647
chore(collector-runtime): regenerate artifact for the local-device fixes
tnunamak Oct 22, 2026
07edf3d
test(local-device): require exact stream identities in coverage journey
tnunamak Oct 22, 2026
681291d
feat(collector): commit a terminal run record for every successful run
tnunamak Oct 22, 2026
4f25632
feat(coverage): fence local coverage proofs with a collection revision
tnunamak Oct 22, 2026
196b383
feat(console): show local coverage as of its run
tnunamak Oct 22, 2026
6a77ccf
chore(collector-runtime): regenerate artifact for the terminal run re…
tnunamak Oct 22, 2026
67db12d
fix(coverage): show positive local coverage only with run provenance
tnunamak Oct 22, 2026
d466110
fix(coverage): commit each collection revision with its event
tnunamak Oct 22, 2026
22472a8
Merge origin/main into local run coverage verdict
tnunamak Oct 22, 2026
ab3dacb
test(reference): count the new cold-required Postgres test
tnunamak Oct 22, 2026
f3d8beb
fix(coverage): close the remaining revision and snapshot gaps
tnunamak Oct 22, 2026
29f4dd9
docs(coverage): record revision guard, legacy replay and boundary sna…
tnunamak Oct 22, 2026
7ea7846
feat(collector): register runs and order device receipts by run order
tnunamak Oct 22, 2026
824007e
chore(collector-runtime): regenerate artifact for run order
tnunamak Oct 22, 2026
3f91995
feat(coverage): decide proof eligibility by run order, not commit order
tnunamak Oct 22, 2026
832d0b2
docs(coverage): record run order, the restore epoch and the contract gap
tnunamak Oct 22, 2026
06fe905
docs(coverage): map each Collection Profile MUST to its failure and test
tnunamak Oct 22, 2026
5d9554c
feat(coverage): refuse a version 1 START without a collection scope
tnunamak Oct 22, 2026
bba5dda
fix(coverage): request no evidence when START names stream resources
tnunamak Oct 22, 2026
93691c4
feat(coverage): add RUN_COVERAGE_V1 and refuse it where no evidence i…
tnunamak Oct 22, 2026
0778f34
fix(coverage): keep a store's negative status for the rest of the run
tnunamak Oct 22, 2026
0a9a7f7
test(coverage): pin the no-release and no-inventory fail-closed paths
tnunamak Oct 22, 2026
2d98c5d
chore(connector-protocol): regenerate artifact for RUN_COVERAGE_V1
tnunamak Oct 22, 2026
2c5d799
chore(collector-runtime): regenerate artifact for the run coverage gates
tnunamak Oct 22, 2026
4501d8f
docs(coverage): close the untested Collection Profile rows
tnunamak Oct 22, 2026
9769b68
test(local-collector): expect the collector to advertise RUN_COVERAGE_V1
tnunamak Oct 22, 2026
77f310a
fix(coverage): gate evidence on profile 0.3.0
tnunamak Oct 22, 2026
0709437
Re-vendor reference-contract and drop the pending-members workaround
tnunamak Oct 22, 2026
98d1673
test(manifest): accept profile 0.3.0 at registration
tnunamak Oct 22, 2026
23ae4b2
test(source-declaration): treat 0.4.0 as the unknown profile
tnunamak Oct 22, 2026
e62d1d7
test(reference): validate terminal commit responses
tnunamak Oct 23, 2026
d993b19
Negotiate store coverage as an elective extension
tnunamak Oct 23, 2026
5ee351d
Refresh connector protocol artifact metadata
tnunamak Oct 23, 2026
1a43e84
Refresh collector runtime artifact metadata
tnunamak Oct 23, 2026
3d17c84
Correct extension audit references
tnunamak Oct 23, 2026
6f7e5b9
docs(coverage): cite the extension's Section 7.1 rules
tnunamak Oct 23, 2026
02ed156
test(collector-runtime): drop capability keys the declaration overwrites
tnunamak Oct 23, 2026
547cd72
Retire device coverage on reference observations
tnunamak Oct 23, 2026
9fa5489
Gate collection observations on current-epoch device runs
tnunamak Oct 23, 2026
92438ec
Revert "Gate collection observations on current-epoch device runs"
tnunamak Oct 23, 2026
5fff3e4
Revert "Retire device coverage on reference observations"
tnunamak Oct 23, 2026
a6daef5
Gate store coverage by source kind
tnunamak Oct 23, 2026
5e6efdc
test(scheduler): stop runs leaking across tests; wait for the placeme…
tnunamak Oct 23, 2026
76b3d2a
Decide device coverage by the connection's current source kind
tnunamak Oct 23, 2026
7d99020
Treat stale fold caches as unobserved and fence folds by source kind
tnunamak Oct 23, 2026
133f73d
test(coverage): assert each behind-version mask on its own; narrow th…
tnunamak Oct 23, 2026
85432c1
Repair run_history.scheduler_managed for device runs; stop reading it…
tnunamak Oct 23, 2026
3626036
fix(reference): keep fresh SQLite schemas deterministic; register the…
tnunamak Oct 23, 2026
14d71bd
test(reference): name the Postgres skip reason in the provenance migr…
tnunamak Oct 23, 2026
45116f9
fix(coverage): accept bounded terminal scope misses
tnunamak Oct 23, 2026
2b2cafc
fix(reference): fence local-device coverage by current source kind
tnunamak Oct 23, 2026
ad27b2b
Fix SQLite collection revision migration order
tnunamak Oct 23, 2026
5a6b5ef
fix(local-collector): preserve managed profile capabilities
tnunamak Oct 23, 2026
23025d5
fix(postgres): bound run history boot migration waits
tnunamak Oct 23, 2026
14364a2
fix(reference): reconcile run-order counters with retained run sequen…
tnunamak Oct 23, 2026
1034303
test(reference): drop the post-deadline real wait from the migration …
tnunamak Oct 23, 2026
5f3f54e
test(reference): lock the table discovery reads, not the one the fold…
tnunamak Oct 23, 2026
bb5255a
Merge origin/main into local run coverage verdict
tnunamak Oct 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 79 additions & 1 deletion .github/workflows/managed-connector-oci-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ name: managed-connector OCI end-to-end (local registry; NOT GHCR, NOT Sigstore)
# fetch. (There is no cross-repo-pins.json in THIS repo; see the pin file if that surprises you.)
# The reasoning, the weakness of pinning an unmerged PR head, and why the connector stays `oura`
# while data-connectors' publish pilot moved to `ynab` are all written down in the pin file.
#
# THE INSTALL-PATH JOURNEY (J2-install, the last three steps). The live-registry test above proves an
# artifact installs and its entrypoint imports. The journey installs two releases through the shipped
# collector's own function (ensureCollectionProfileInstalled), against pins the builder writes into the job's
# temp directory. It runs each installed entrypoint and checks what the server and the device make of it. A
# replaced digest stops counting until its own run proves it. It runs against this job's registry. Its signature
# check is the same stub verifier, and its releases carry a fabricated signature bundle, so (1) and (2) above
# apply to it, and it proves nothing about signatures or ghcr.io.

on:
pull_request:
Expand All @@ -56,6 +64,13 @@ on:
- "packages/local-collector/src/managed/**"
- "packages/local-collector/test/managed-connectors.test.ts"
- "packages/local-collector/test/managed-connectors-live-registry.test.ts"
- "packages/local-collector/test/helpers/live-registry-client.ts"
# The install-path journey (J2-install) and the fixture it packages.
- "reference-implementation/test/local-device-coverage-journey.test.ts"
- "reference-implementation/test/helpers/install-path-fixture.ts"
- "reference-implementation/test/helpers/build-install-path-releases.ts"
# The shipped selection and binding the journey calls (selectedReleaseForPin, bindOptionalRunCoverageToRelease).
- "packages/local-collector/bin/pdpp-local-collector.ts"
# This job's own control files: a PR that only edits the workflow or moves the producer pin
# would otherwise not run the thing it changed. Same reasoning as consumer-drift-signal.yml's
# "Producer workflows should include their own control files in triggers".
Expand All @@ -67,6 +82,11 @@ on:
- "packages/local-collector/src/managed/**"
- "packages/local-collector/test/managed-connectors.test.ts"
- "packages/local-collector/test/managed-connectors-live-registry.test.ts"
- "packages/local-collector/test/helpers/live-registry-client.ts"
- "reference-implementation/test/local-device-coverage-journey.test.ts"
- "reference-implementation/test/helpers/install-path-fixture.ts"
- "reference-implementation/test/helpers/build-install-path-releases.ts"
- "packages/local-collector/bin/pdpp-local-collector.ts"
- ".github/workflows/managed-connector-oci-e2e.yml"
- ".github/managed-connector-e2e-pin.json"
workflow_dispatch:
Expand Down Expand Up @@ -162,7 +182,9 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: "22.23.4"
# 24.22.1 is the version the reference-implementation job runs its tests on, and the
# install-path journey below is one of those tests. The producer's engines pin node 24 too.
node-version: "24.22.1"

- name: Install this repository's dependencies
run: npm ci --ignore-scripts
Expand Down Expand Up @@ -447,3 +469,59 @@ jobs:

echo "OK: the consumer rejected blobs that did not hash to their pinned digests."
rm -f proxied.txt

- name: Build the workspace packages the reference server loads
# The reference-implementation job builds these after `npm ci` (reference-implementation.yml). The
# install-path journey imports the server, which loads their dist/ output. This job runs
# `npm ci --ignore-scripts`, so nothing has built them yet. The root postinstall is not needed here:
# it fetches connector packages, and this journey runs none.
run: |
set -euo pipefail
npm --prefix packages/connector-protocol run build
npm --prefix packages/collector-runtime run build
npm --prefix reference-implementation/vendor/read-core run build
npm --prefix reference-implementation/vendor/cli run build
npm --prefix reference-implementation/vendor/mcp-server run build

- name: Build and push the install-path releases A and B with the producer's builder
# Two releases of one connector (install-path-fixture.ts): the same manifest and different code layers,
# so different digests. The builder is the producer's own script at the pinned revision. The packaging
# tree around it is the fixture's. Both releases are pushed to this job's registry, each with a signature
# stand-in. The pins the journey checks against are written into the work directory. The journey step
# reads their path from the releases file, not from the log.
working-directory: reference-implementation
env:
PRODUCER_GIT: ${{ github.workspace }}/data-connectors
PRODUCER_SHA: ${{ steps.pin.outputs.sha }}
RELEASES_JSON: ${{ runner.temp }}/install-path-releases.json
run: |
set -euo pipefail
node --import tsx test/helpers/build-install-path-releases.ts \
--producer-git "$PRODUCER_GIT" \
--producer-sha "$PRODUCER_SHA" \
--registry localhost:5000 \
--work "${RUNNER_TEMP}/install-path" \
--modules "$PRODUCER_GIT/node_modules" > "$RELEASES_JSON"

- name: Run the install-path journey (J2-install) through the shipped collector path
working-directory: reference-implementation
env:
PDPP_TEST_OCI_REGISTRY: localhost:5000
RELEASES_JSON: ${{ runner.temp }}/install-path-releases.json
run: |
set -euo pipefail
pins_path="$(node -e 'process.stdout.write(require(process.env.RELEASES_JSON).pins)')"
test -s "$pins_path"
export PDPP_TEST_INSTALL_PATH_PINS="$pins_path"
node --test --import tsx --test-name-pattern=J2-install test/local-device-coverage-journey.test.ts | tee result.txt
# The same guard as the live-registry step above: node --test exits 0 on a skipped test, so require
# exactly one passing test and no skips. A typo in an env var name must not turn this job green.
if ! grep -qE 'pass 1$' result.txt; then
echo "::error::the install-path journey did not report exactly one passing test" >&2
exit 1
fi
if ! grep -qE 'skipped 0$' result.txt; then
echo "::error::the install-path journey SKIPPED; its env vars did not reach it" >&2
exit 1
fi
rm -f result.txt
2 changes: 1 addition & 1 deletion PG-PROFILE-51-REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ tail:

The completed profile receipt recorded 1,034 files; that historical receipt
is unchanged. The template equivalence registry is a different measure:
156 eligible plus 37 cold-required files, for **193** total. The
157 eligible plus 40 cold-required files, for **197** total. The
handle-generation, issuance-cutover, opaque-cursor and search-index repair
tests remain registered. These counts are recomputed from the merged registry arrays.

Expand Down
12 changes: 9 additions & 3 deletions apps/console/src/app/(console)/lib/collection-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
import type { AxisChip, EvidenceTone } from "@pdpp/display";
import { formatCoverageAxis } from "@pdpp/display";
import type { ForwardDispositionSummary } from "./connection-evidence.ts";
import { formatForwardDisposition } from "./connection-evidence.ts";
import { formatForwardDisposition, withCoverageAsOf } from "./connection-evidence.ts";
import { dispositionForInstallState } from "./connector-implementation.ts";
import type { RefCollectionReportEntry } from "./ref-client.ts";
import type { RefCollectionReportEntry, RefCoverageAsOf } from "./ref-client.ts";

export interface StreamCollectionFacts {
/**
Expand Down Expand Up @@ -292,9 +292,15 @@ export function formatStreamCollectionFacts(
* happen, so the reference's disposition is replaced by the install blocker.
*/
readonly connectorNotInstalled?: boolean;
/** The run the connection's local coverage describes (`coverage_as_of`). */
readonly coverageAsOf?: RefCoverageAsOf | null;
} = {}
): StreamCollectionFacts {
const coverage = formatCoverageAxis(entry.coverage_condition);
const coverage = withCoverageAsOf(
formatCoverageAxis(entry.coverage_condition),
entry.coverage_condition,
options.coverageAsOf
);
const disposition = dispositionForInstallState(
formatForwardDisposition(entry.forward_disposition),
options.connectorNotInstalled === true
Expand Down
63 changes: 63 additions & 0 deletions apps/console/src/app/(console)/lib/connection-evidence.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import assert from "node:assert/strict";
import test from "node:test";
import { formatCoverageAxis, formatFreshnessAxis, formatOutboxAxis } from "@pdpp/display";
import { formatStreamCollectionFacts } from "./collection-report.ts";
import {
deriveAutoPausedBanner,
deriveConnectionNextStep,
Expand Down Expand Up @@ -2348,3 +2349,65 @@ test("formatSourceHeartbeat reports unknown when the server derived no health",
assert.equal(chip.value, "unknown");
assert.doesNotMatch(chip.label, /starting/, "an underived status is not evidence of life");
});

// Local coverage is a fact about one run, never a present-tense claim: the
// owner sees "complete as of <time>", and the chip names the run, release and
// revision it describes.
const COVERAGE_AS_OF = {
artifact_digest: `sha256:${"a".repeat(64)}`,
collection_revision: 7,
committed_at: "2026-10-22T10:00:00.000Z",
evidence: "terminal_run",
run_id: "run-a",
run_sequence: 3,
} as const;

test("coverage chip reads 'complete as of <time>' when the reference names the run it describes", () => {
const axes = {
attention: null,
coverage: "complete",
freshness: "fresh",
outbox: "idle",
} as const;
const [coverage] = summarizeAxisChips(axes as never, {
coverageAsOf: COVERAGE_AS_OF,
isLocalDeviceBacked: true,
});
assert.equal(coverage?.label, "Coverage · complete as of 2026-10-22 10:00:00Z");
assert.equal(coverage?.value, "complete as of 2026-10-22 10:00:00Z");
assert.match(coverage?.title ?? "", /run run-a/);
assert.match(coverage?.title ?? "", /sha256:a{12}/);
assert.match(coverage?.title ?? "", /revision 7/);
});

test("coverage chip adds no as-of to unknown coverage or when the reference sends none", () => {
const unknown = {
attention: null,
coverage: "unknown",
freshness: "fresh",
outbox: "idle",
} as const;
const [unknownChip] = summarizeAxisChips(unknown as never, {
coverageAsOf: COVERAGE_AS_OF,
isLocalDeviceBacked: true,
});
assert.equal(unknownChip?.label, formatCoverageAxis("unknown").label);
const complete = {
attention: null,
coverage: "complete",
freshness: "fresh",
outbox: "idle",
} as const;
const [plain] = summarizeAxisChips(complete as never, {
coverageAsOf: null,
isLocalDeviceBacked: true,
});
assert.equal(plain?.label, formatCoverageAxis("complete").label);
});

test("per-stream coverage reads 'complete as of <time>' with the connection's as-of", () => {
const facts = formatStreamCollectionFacts({ coverage_condition: "complete", stream: "messages" } as never, {
coverageAsOf: COVERAGE_AS_OF,
});
assert.equal(facts.coverage.label, "Coverage · complete as of 2026-10-22 10:00:00Z");
});
44 changes: 42 additions & 2 deletions apps/console/src/app/(console)/lib/connection-evidence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type {
DeviceSourceInstance,
RefCollectionRateSnapshot,
RefConnectionHealthSnapshot,
RefCoverageAsOf,
RefDetailGapBacklog,
RefForwardDisposition,
RefLocalDeviceProgress,
Expand Down Expand Up @@ -87,12 +88,18 @@ export function outboxAxisIsApplicable(
*/
export function summarizeAxisChips(
axes: RefConnectionHealthSnapshot["axes"] | undefined | null,
options: { isLocalDeviceBacked?: boolean } = {}
options: {
coverageAsOf?: RefCoverageAsOf | null;
isLocalDeviceBacked?: boolean;
} = {}
): AxisChip[] {
if (!axes) {
return [];
}
const out: AxisChip[] = [formatCoverageAxis(axes.coverage), formatFreshnessAxis(axes.freshness)];
const out: AxisChip[] = [
withCoverageAsOf(formatCoverageAxis(axes.coverage), axes.coverage, options.coverageAsOf),
formatFreshnessAxis(axes.freshness),
];
const attention = formatAttentionAxis(axes.attention);
if (attention) {
out.push(attention);
Expand Down Expand Up @@ -122,6 +129,39 @@ export function summarizeAxisChips(
return out;
}

const FRACTIONAL_SECONDS = /\.\d+Z$/;

/** UTC, to the second: "2026-10-22 10:00:00Z". Empty for a missing or unparseable time. */
function formatCoverageAsOfTime(iso: string | null | undefined): string {
const parsed = iso ? Date.parse(iso) : Number.NaN;
return Number.isFinite(parsed)
? new Date(parsed).toISOString().replace("T", " ").replace(FRACTIONAL_SECONDS, "Z")
: "";
}

/**
* Coverage is a fact about one run, never a present-tense claim. When the
* reference names the run a coverage verdict describes, the chip reads
* "complete as of <time>" and its title names the run, release and collection
* revision. Unknown coverage has no run behind it, so it is left unchanged.
*/
export function withCoverageAsOf(
chip: AxisChip,
axis: string | null | undefined,
asOf: RefCoverageAsOf | null | undefined
): AxisChip {
const committedAt = formatCoverageAsOfTime(asOf?.committed_at);
if (!(asOf && committedAt) || axis === "unknown" || axis === null || axis === undefined) {
return chip;
}
return {
...chip,
label: `${chip.label} as of ${committedAt}`,
title: `${chip.title} This is a fact about run ${asOf.run_id} (release ${asOf.artifact_digest}), committed at ${committedAt} as collection revision ${asOf.collection_revision}. A later run the reference has not heard about is not reflected.`,
value: `${chip.value} as of ${committedAt}`,
};
}

/**
* Owner-facing copy for the connection-level forward disposition — the
* reference's single answer to "what is the next run expected to do?". This is
Expand Down
24 changes: 24 additions & 0 deletions apps/console/src/app/(console)/lib/ref-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,17 @@ export interface RefConnectorImplementation {
state: "built_in" | "installed" | "local_source" | "not_installed" | "unknown";
}

/** See {@link RefConnectorSummary.coverage_as_of}. */
export interface RefCoverageAsOf {
readonly artifact_digest: string;
readonly collection_revision: number;
readonly committed_at: string | null;
readonly evidence: "terminal_run";
readonly run_id: string;
/** The sequence the server issued to the run at its start; it decides which proof can be current. */
readonly run_sequence: number;
}

export interface RefConnectorSummary {
/**
* Owner/control-plane acquisition provenance for manual imports, device
Expand Down Expand Up @@ -669,6 +680,13 @@ export interface RefConnectorSummary {
* renders no horizons rather than inventing a state. Pass-through from
* `server/ref-control.ts#projectConnectorSummaryConnectionHealth`.
*/
/**
* What the local coverage on this row is a fact about (`LocalCoverageAsOf`
* in reference `server/ref-control.ts`): the run, its release digest, and the
* collection revision and time it was committed at. `null` or absent when no
* current local proof backs the coverage shown.
*/
coverage_as_of?: RefCoverageAsOf | null;
coverage_horizons?: readonly RefCoverageHorizon[];
display_name: string;
freshness: Record<string, unknown>;
Expand Down Expand Up @@ -1314,6 +1332,12 @@ export interface RefConnectionHealthSnapshot {
*/
collection_rate?: RefCollectionRateSnapshot | null;
conditions?: readonly RefConnectionHealthCondition[];
/**
* What `axes.coverage` is a fact about: the same value as the summary's
* top-level `coverage_as_of`. Optional on the mirror because a reference
* predating the field omits it.
*/
coverage_as_of?: RefCoverageAsOf | null;
/**
* Additive, nullable source-pressure detail-gap backlog rollup
* ({@link RefDetailGapBacklog}). `null` when no backlog evidence was supplied
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type {
DeviceSourceInstance,
RefActionRemediation,
RefConnectionHealthSnapshot,
RefCoverageAsOf,
RefLocalDeviceProgress,
RefRenderedVerdict,
RefSchedule,
Expand Down Expand Up @@ -71,6 +72,8 @@ export interface ConnectionDiagnosticsProps {
* coverage-derived value, matching the per-stream lines.
*/
connectorNotInstalled?: boolean;
/** The run the local coverage describes; the coverage chip reads "as of" its commit time. */
coverageAsOf?: RefCoverageAsOf | null;
/**
* Connection-summary local-device progress, including the count-backed
* `outbox_counts` rollup. Used to show the scale of stuck work in the
Expand Down Expand Up @@ -105,6 +108,7 @@ export function ConnectionDiagnostics({
connectionId,
connectorId,
connectorNotInstalled = false,
coverageAsOf = null,
localDeviceProgress,
now,
providerOrigin,
Expand Down Expand Up @@ -163,6 +167,7 @@ export function ConnectionDiagnostics({
connectionId={connectionId}
connectorId={connectorId}
connectorNotInstalled={connectorNotInstalled}
coverageAsOf={coverageAsOf}
localDeviceProgress={localDeviceProgress}
providerOrigin={providerOrigin}
renderedVerdict={renderedVerdict}
Expand Down Expand Up @@ -455,6 +460,7 @@ function ProjectedStateDiagnostics({
connectionId,
connectorId,
connectorNotInstalled,
coverageAsOf,
localDeviceProgress,
providerOrigin,
renderedVerdict,
Expand All @@ -464,6 +470,7 @@ function ProjectedStateDiagnostics({
connectionId: string | null;
connectorId: string | null;
connectorNotInstalled: boolean;
coverageAsOf: RefCoverageAsOf | null;
localDeviceProgress: RefLocalDeviceProgress | null;
providerOrigin: string | null;
renderedVerdict: RefRenderedVerdict | null;
Expand All @@ -487,6 +494,7 @@ function ProjectedStateDiagnostics({
// The diagnostics block already receives the connection's local-device
// progress, so reuse it as the local-backing signal.
const axisChips = summarizeAxisChips(connectionHealth.axes, {
coverageAsOf,
isLocalDeviceBacked: Boolean(localDeviceProgress),
});
const outboxRemediation = summarizeOutboxStallRemediation(connectionHealth, localDeviceProgress);
Expand Down
Loading
Loading