chore: sync the frontend template from 4dc033c to 8157ad4

The product was materialized from the template at `4dc033c` and has stayed
on it through 43 template commits, so it was missing all three rounds of
adapter remediation — including files it never had, such as the shared
`abortable-operation` primitive and the `exact-snapshot` decoder that
later fixes are written against. Taking only the newest round was not
possible for that reason: the delta is coherent only as a whole.

The product had not touched `src/adapters` at all since materialization,
so the 140-file delta applied with a three-way merge and no conflicts.
`package.json` was the single overlap and merged cleanly: the product owns
`name`, the template contributed `check:adapter-inventory`,
`check:remediation-ledger` and the image-resolve-signal type fixture.
All 24 product-owned files — README, index.html, CI workflow, i18n
catalog, home page, generated schemas, evidence scripts, component and
visual snapshots — are byte-identical to `main`.

`template.lock.json` now pins the synced revision and tree.

Verified in this repository, not inherited from the template: six type
projects, lint, nine gates (adapter inventory, remediation ledger,
registries, diagnostics, realtime boundaries, architecture, browser
file/storage boundaries, optional recipes, documentation), the production
build, and 2,054 of 2,073 tests. The 19 failures are all in
`tests/unit/ci-artifact-contract.test.ts` and are the same pre-existing
sandbox RLIMIT, EMFILE, umask and `/tmp` permission behaviour the template
records; four suites that failed once under parallel load pass in
isolation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-08-15 12:04:58 +09:00
co-authored by Claude Opus 5
parent 002ba3624e
commit 4bff9ca151
142 changed files with 23010 additions and 1544 deletions
@@ -0,0 +1,269 @@
/**
* BT-X-01. Shared abort and deadline mechanics.
*
* Several adapters independently reimplemented "race a promise against a
* caller signal and a deadline, then clean up listeners and timers". Only the
* mechanics are shared here; every subsystem keeps its own result taxonomy and
* recovery vocabulary, so this module deliberately imports none of them and is
* not a generic middleware layer.
*/
export type AbortTerminalReason = "CALLER_ABORT" | "DEADLINE" | "CLOSED";
/**
* TR-RR-05. A collaborator's own rejection is evidence about the work, so it is
* a distinct outcome. Forging it into `TERMINAL` erased the reason the
* operation actually failed and made `race()` disagree with `terminal()`, which
* still reported no owner.
*/
export type AbortRace<Value> =
| Readonly<{ kind: "VALUE"; value: Value }>
| Readonly<{ kind: "REJECTED"; reason: unknown }>
| Readonly<{ kind: "TERMINAL"; terminal: AbortTerminalReason }>;
export type AbortableOperation = Readonly<{
/** The composed signal: caller abort, deadline and close all feed it. */
readonly signal: AbortSignal;
/**
* The first terminal owner, or `null` while the operation is still live.
* This is a live accessor, not a snapshot.
*/
terminal(): AbortTerminalReason | null;
/**
* Resolves with the operation's value, its own rejection, or the first
* terminal owner. A terminal race never returns a bare value, and the
* `terminal` it reports is always the same owner `terminal()` reports.
*
* `compensate` is invoked at most once, and only for a value that arrived
* after the operation already ended.
*/
race<Value>(
operation: Promise<Value>,
compensate?: (value: Value) => void,
): Promise<AbortRace<Value>>;
/**
* Idempotent. Removes listeners, clears the deadline timer and marks the
* operation `CLOSED` if nothing terminal happened first.
*/
close(): void;
}>;
export type AbortableOperationInput = Readonly<{
signal?: AbortSignal;
timeoutMs?: number;
/** Scheduler seam; a throwing scheduler must not leak a listener. */
setTimer?: (callback: () => void, delayMs: number) => unknown;
clearTimer?: (handle: unknown) => void;
}>;
export type AbortTimerSnapshot = Readonly<{
setTimer: (callback: () => void, delayMs: number) => unknown;
clearTimer: (handle: unknown) => void;
}>;
/**
* X-AUDIT-02. Captures a scheduler's timer callables once, bound to their
* receiver. Consumers that kept the scheduler object and re-read `setTimeout`
* per request validated one function and executed another, so replacing a
* method after composition silently changed how work was bounded.
*/
export function snapshotAbortTimers<Handle>(
scheduler: Readonly<{
setTimeout(callback: () => void, milliseconds: number): Handle;
clearTimeout(handle: Handle): void;
}>,
): AbortTimerSnapshot {
const set = scheduler?.setTimeout;
const clear = scheduler?.clearTimeout;
if (typeof set !== "function" || typeof clear !== "function") {
throw new TypeError("Timer scheduler is invalid.");
}
return Object.freeze({
setTimer: set.bind(scheduler) as (
callback: () => void,
delayMs: number,
) => unknown,
clearTimer: clear.bind(scheduler) as (handle: unknown) => void,
});
}
export function createAbortableOperation(
input: AbortableOperationInput = {},
): AbortableOperation {
const controller = new AbortController();
// TR-RR-05. The scheduler and the caller signal are captured once, so
// replacing a method on the input object after construction cannot change how
// an operation already in flight is bounded or cleaned up.
const callerSignal = input.signal;
const setTimer =
input.setTimer ??
((callback: () => void, delayMs: number) => setTimeout(callback, delayMs));
const clearTimer =
input.clearTimer ??
((handle: unknown) => {
clearTimeout(handle as ReturnType<typeof setTimeout>);
});
let terminalReason: AbortTerminalReason | null = null;
let disposed = false;
let timer: unknown;
/** First terminal owner wins; later owners never overwrite it. */
const settle = (reason: AbortTerminalReason) => {
terminalReason ??= reason;
if (!controller.signal.aborted) controller.abort();
};
const onCallerAbort = () => {
settle("CALLER_ABORT");
dispose();
};
function dispose(): void {
if (disposed) return;
disposed = true;
try {
callerSignal?.removeEventListener("abort", onCallerAbort);
} catch {
// A hostile signal facade cannot block cleanup of the rest.
}
if (timer !== undefined) {
try {
clearTimer(timer);
} catch {
// A throwing scheduler cannot leave the operation un-disposed.
}
timer = undefined;
}
}
if (callerSignal?.aborted) {
settle("CALLER_ABORT");
disposed = true;
} else if (callerSignal) {
callerSignal.addEventListener("abort", onCallerAbort, { once: true });
}
if (
terminalReason === null &&
input.timeoutMs !== undefined &&
Number.isFinite(input.timeoutMs) &&
input.timeoutMs >= 0
) {
try {
timer = setTimer(() => {
settle("DEADLINE");
dispose();
}, input.timeoutMs);
} catch {
// TR-RR-05. A scheduler that cannot install the deadline leaves the
// operation unbounded. Removing the caller listener and leaving no
// terminal owner made a later abort invisible, so installation failure is
// itself terminal: the operation closes atomically with its resources.
timer = undefined;
settle("CLOSED");
dispose();
}
}
return Object.freeze({
signal: controller.signal,
terminal: () => terminalReason,
race<Value>(
operation: Promise<Value>,
compensate?: (value: Value) => void,
): Promise<AbortRace<Value>> {
let compensated = false;
const compensateOnce = (value: Value) => {
if (compensated || !compensate) return;
compensated = true;
try {
compensate(value);
} catch {
// Compensation is best effort and never changes the outcome.
}
};
const terminalRace = (): AbortRace<Value> =>
Object.freeze({
kind: "TERMINAL" as const,
// The owner reported here is always the owner `terminal()` reports.
terminal: terminalReason ?? ("CLOSED" as const),
});
if (terminalReason !== null) {
// Already owned before the task was ever raced: nothing it produces can
// be admitted, so a value is compensated and a rejection absorbed.
void operation.then(
(value) => compensateOnce(value),
() => undefined,
);
return Promise.resolve(terminalRace());
}
// X-AUDIT-01. Task settlement and the terminal event share one settle-once
// state machine, so the outcome is whichever callback actually ran first.
// Draining a fixed number of microtasks to guess whether a promise "had
// already settled" made the answer depend on scheduling rather than on
// observation, and let a rejection overwrite an owner that was fixed
// synchronously before it.
return new Promise<AbortRace<Value>>((resolve) => {
let claimed = false;
let onAbort: (() => void) | undefined;
const release = () => {
if (!onAbort) return;
controller.signal.removeEventListener("abort", onAbort);
onAbort = undefined;
};
const claim = (outcome: AbortRace<Value>): boolean => {
if (claimed) return false;
claimed = true;
release();
resolve(outcome);
return true;
};
operation.then(
(value) => {
if (!claim(Object.freeze({ kind: "VALUE" as const, value }))) {
// The work landed after the operation already ended.
compensateOnce(value);
}
},
(reason: unknown) => {
// A rejection that loses the claim is absorbed here, so it can never
// surface as an unhandled rejection.
claim(Object.freeze({ kind: "REJECTED" as const, reason }));
},
);
if (controller.signal.aborted) {
claim(terminalRace());
return;
}
onAbort = () => {
claim(terminalRace());
};
controller.signal.addEventListener("abort", onAbort, { once: true });
});
},
close() {
settle("CLOSED");
dispose();
},
});
}
/**
* Compensates a native handle that arrives after the operation ended. The
* compensation itself is best effort and can never change the already selected
* outcome.
*/
export function compensateLateHandle(
handle: Promise<Readonly<{ body?: { cancel(): Promise<void> } | null }> | null>,
): void {
void handle
.then(async (value) => {
await value?.body?.cancel();
})
.catch(() => undefined);
}