fix: rebuild gate 1 from the resolver's own predicate, not a catalog lookup
Fix round 3 (review of 7ff9728):
Round 2's gate 1 (supportsEvidenceKeyIn(evidenceCatalogEntriesFromAssets(assets)))
still routed through evidenceCatalogEntryFor, matching on id || label ||
publicPath -- gate 2's question, asked over fewer rows, not the resolver's
actual success condition (assetKey === key && managementStatus === "READY"
&& Boolean(publicPath)). Two Asset shapes made the two predicates disagree:
a READY asset with publicPath null/"", and a READY asset whose publicPath
happens to satisfy the legacy /media/${someOtherKey}.svg convention for a
key that isn't its own assetKey. Both passed gate 1 while the resolver
could not produce real pixels, reproducing the validateDocument-VALID /
createPreview-throws-raw-Error disagreement a second time.
Rebuilt gate 1 in validate-working-copy.ts and
adapters/mock/project-public-render-model.ts directly from a new domain
function, supportsEvidenceKeyFromReadyAssets, that mirrors the resolver's
exact condition -- never through evidenceCatalogEntryFor again. Gate 2
keeps reading the merged catalog. Made the mock resolver total (returns a
placeholder instead of throwing, matching instant-preview.tsx's resolver),
removing a comment that asserted an invariant the code did not hold.
Wrapped mock-studio-gateway.ts's idempotent() so any non-StudioGatewayError
that reaches its catch is normalized before crossing the port -- closing
the class generally, not just this instance.
Reverted instant-preview.tsx's own gate 1 to the merged catalog (unlike
the mock adapters, its resolver is provably total, so a loose gate there
only ever degrades to a placeholder) -- round 2's narrowing there was a
separate regression: a CASE referencing a document-catalog-backed key
outside the editor's currently-loaded Asset list blanked the entire
preview instead of degrading one figure.
Pinned both slip-through shapes failing on both mock paths with the
thrown/rejected error's type asserted (StudioGatewayError, never a raw
Error), pinned idempotent()'s new wrapping via a validate/preview race,
pinned EVIDENCE_NOT_FOUND as reachable through validateWorkingCopy
directly, and pinned Instant Preview's graceful degradation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7ff9728a5c
commit
783e9b2cf1
@@ -9,7 +9,6 @@ import {
|
||||
projectWorkingCopy,
|
||||
resolveCaseEvidenceAssets,
|
||||
} from "../../../domain/content-format/project-public-render-model.ts";
|
||||
import type { SupportsEvidenceKey } from "../../../domain/public-render-content.ts";
|
||||
import { createAssetCatalogResolver } from "../../shared/public-render/asset-resolvers.ts";
|
||||
import { PublicRecordRenderer } from "../../shared/public-render/public-record-renderer.tsx";
|
||||
import { useStudio } from "../use-studio.ts";
|
||||
@@ -21,28 +20,12 @@ type PublicRenderModel = components["schemas"]["PublicRenderModel"];
|
||||
/**
|
||||
* The one legacy key predates the Asset gateway entirely: the document
|
||||
* catalog carries a fixture `EVIDENCE` row for it, but no `Asset` record
|
||||
* backs it, so `assets` never resolves it. This is also gate 1's "legacy"
|
||||
* half now (fix round 2) -- see `supportsEvidenceKeyForAssets` below.
|
||||
* backs it, so `assets` never resolves it.
|
||||
*/
|
||||
function isLegacyStaticEvidenceKey(key: string): boolean {
|
||||
return key === "fetch-strategy-boundary";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gate 1: "may this document reference this key at all" -- the legacy key,
|
||||
* or a `READY` Asset actually backs it. Deliberately narrower than gate 2
|
||||
* (the merged-catalog lookup `projectWorkingCopy` runs internally): fix
|
||||
* round 1 collapsed this into `supportsEvidenceKeyIn(effectiveCatalog)`,
|
||||
* which made gate 1 ask the same question as gate 2 and let any `EVIDENCE`
|
||||
* catalog row backing something other than an Asset (e.g. a QUESTION
|
||||
* resolution-target row) pass gate 1 with no Asset and no legacy key behind
|
||||
* it. See `asset-evidence-catalog.ts`'s module doc for the shared shape.
|
||||
*/
|
||||
function supportsEvidenceKeyForAssets(assets: readonly Asset[]): SupportsEvidenceKey {
|
||||
const assetOnly = supportsEvidenceKeyIn(evidenceCatalogEntriesFromAssets(assets));
|
||||
return (key: string) => isLegacyStaticEvidenceKey(key) || assetOnly(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* `resolveCaseEvidenceAssets` only needs *a* `ResolvedAsset` to turn the authoring
|
||||
* model into a genuine `PublicRenderModel` -- nothing downstream reads `block.asset`
|
||||
@@ -111,7 +94,27 @@ export function InstantPreview({
|
||||
draft,
|
||||
effectiveCatalog,
|
||||
{ mode: "PREVIEW", publishedAt: null },
|
||||
supportsEvidenceKeyForAssets(assets),
|
||||
// Gate 1 deliberately asks the SAME question gate 2 asks here
|
||||
// (`supportsEvidenceKeyIn` over the merged catalog) -- unlike
|
||||
// `validate-working-copy.ts`/`adapters/mock/project-public-render-model.ts`,
|
||||
// where reusing gate 2's question for gate 1 was the bug across fix
|
||||
// rounds 1-3 (see `asset-evidence-catalog.ts`'s module doc). The
|
||||
// difference: `resolveAssetDescriptor` below is total and cannot
|
||||
// throw, so a gate 1 that passes a key the resolver cannot fully
|
||||
// resolve only ever degrades that one figure to a placeholder --
|
||||
// never a crash, and there is no port-contract to violate here.
|
||||
// Fix round 2 narrowed this to an assets-only check (mirroring the
|
||||
// mock's gate at the time), which was itself a regression: a CASE
|
||||
// referencing an Asset the editor has not yet loaded -- outside the
|
||||
// Picker's 50-item page, or simply because `assets` is still `[]`
|
||||
// while `listAssets` is in flight on first mount -- failed gate 1
|
||||
// entirely and blanked the WHOLE preview, for every block in the
|
||||
// document, not just the one unresolved reference. Reverted to the
|
||||
// merged catalog (fix round 3): a key any part of the backend
|
||||
// already considers legitimate (document catalog OR a loaded Asset)
|
||||
// passes gate 1, and the resolver fills in real pixels when it has
|
||||
// them or a placeholder when it does not.
|
||||
supportsEvidenceKeyIn(effectiveCatalog),
|
||||
),
|
||||
resolveAssetDescriptor(assets),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user