test: cross-product Instant Preview's evidence-key pair with the adapter's

`evidence-key-agreement.test.ts` cross-products 144 adversarial combinations
across the mock adapter's gate and descriptor resolver, `validateWorkingCopy`
and the shared pixel resolver -- but omitted `instant-preview.tsx`'s own gate
and descriptor resolver. That pair is byte-parallel to the adapter's (it
lives in `presentation/`, which may not import `adapters/`, so it carries its
own copy of the legacy-key predicate) and it is exactly the pair three earlier
fix rounds regressed.

`instant-preview.tsx` now exports the two expressions it already used, so the
test drives the production code rather than rebuilding it. Added assertions:
gate agreement in both array orders, descriptor equality with the adapter's,
pixel/descriptor agreement, and order independence. The one sanctioned
divergence -- the legacy static key's `assetId`, a fixed literal here versus a
registry-derived one there -- is pinned to that case rather than ignored.

Mutation-checked: breaking the legacy predicate reports 96 of 144 combinations
disagreeing, breaking the legacy descriptor path reports 64 of 144.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-08-18 09:12:06 +09:00
co-authored by Claude Opus 5
parent e2a0e695dd
commit 65f8528ccc
2 changed files with 81 additions and 4 deletions
@@ -23,17 +23,29 @@ type PublicRenderModel = components["schemas"]["PublicRenderModel"];
* catalog carries a fixture `EVIDENCE` row for it, but no `Asset` record
* backs it, so `assets` never resolves it.
*/
function isLegacyStaticEvidenceKey(key: string): boolean {
export function isLegacyStaticEvidenceKey(key: string): boolean {
return key === "fetch-strategy-boundary";
}
/**
* Instant Preview's evidence-key gate. Exported so
* `tests/features/tech-log/evidence-key-agreement.test.ts` cross-products
* *this* expression against the mock adapter's byte-parallel pair rather than
* rebuilding it -- three earlier fix rounds regressed exactly this pair, each
* time by writing a second expression that agreed only on the examples that
* round happened to use.
*/
export function instantPreviewEvidenceKeyGate(assets: readonly Asset[]) {
return supportsResolvableEvidenceKey(assets, isLegacyStaticEvidenceKey);
}
/**
* Total -- never throws. Resolves through `findResolvableAsset`, the same
* function this file's key gate and `createAssetCatalogResolver` (which
* supplies the pixels) use, so the descriptor attached to a block and the
* image rendered for it always come from one Asset.
*/
function resolveAssetDescriptor(assets: readonly Asset[]) {
export function resolveInstantPreviewAssetDescriptor(assets: readonly Asset[]) {
return (key: string): ResolvedAsset => {
const asset = findResolvableAsset(assets, key);
if (asset) {
@@ -96,9 +108,9 @@ export function InstantPreview({
// key. A key this rejects fails the projection, and the error panel
// below names it -- the same key `validateDocument` reports
// `EVIDENCE_UNSUPPORTED` for.
supportsResolvableEvidenceKey(assets, isLegacyStaticEvidenceKey),
instantPreviewEvidenceKeyGate(assets),
),
resolveAssetDescriptor(assets),
resolveInstantPreviewAssetDescriptor(assets),
);
} catch (error) {
issues = error instanceof ContentFormatError