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
+213
View File
@@ -445,6 +445,8 @@ describe("Web Push worker runtime", () => {
event: "web_push_subscription_rotated",
outcome: "DEGRADED",
reason: "DEADLINE_EXCEEDED",
countBucket: expect.any(String),
truncated: expect.any(Boolean),
});
runtime.dispose();
});
@@ -489,6 +491,8 @@ describe("Web Push worker runtime", () => {
event: "web_push_subscription_rotated",
outcome: "DEGRADED",
reason: "ABORTED",
countBucket: expect.any(String),
truncated: expect.any(Boolean),
});
const throwingStore = await activeFence();
@@ -540,6 +544,8 @@ describe("Web Push worker runtime", () => {
event: "web_push_subscription_rotated",
outcome: "DEGRADED",
reason: "ABORTED",
countBucket: expect.any(String),
truncated: expect.any(Boolean),
});
throwingRuntime.dispose();
});
@@ -615,3 +621,210 @@ describe("Web Push worker runtime", () => {
expect(listeners.size).toBe(0);
});
});
/**
* WP-01. One click is one terminal record. The adapter emitted the terminal
* event from inside `process` *and* again from the `waitUntil` wrapper, so an
* ordinary click was counted twice. A late rejection also downgraded the
* certainty from `MAYBE_APPLIED` to `NOT_APPLIED`, telling operators the click
* had definitely not been applied when nobody knew that, and the late
* observation ran outside `waitUntil`, so a worker shutdown lost the evidence.
*/
describe("WP-01 the click handler has one observation authority", () => {
type Observation = Readonly<{
event: string;
outcome: string;
reason?: string;
nativeEffect?: string;
}>;
async function clickAdapterWith(
clients: Readonly<{
matchControlledWindowClients(): Promise<readonly unknown[]>;
openWindow(target: string): Promise<unknown>;
}>,
scheduler?: TimeoutScheduler,
) {
const store = await activeFence();
const observations: Observation[] = [];
const adapter = createNotificationClickAdapter({
fenceStore: store,
registry,
origin: "https://app.example.test",
now: () => now,
clients: clients as never,
observer: {
record(observation) {
observations.push(observation as Observation);
},
},
...(scheduler ? { scheduler } : {}),
});
return { adapter, observations };
}
const dispatched = (observations: readonly Observation[]) =>
observations.filter(
(observation) => observation.event === "web_push_click_dispatched",
);
it("records exactly one terminal event for an ordinary focus", async () => {
const focus = vi.fn(async () => {});
const { adapter, observations } = await clickAdapterWith({
async matchControlledWindowClients() {
return [
{
url: "https://app.example.test/current",
focus,
postMessage() {},
},
];
},
openWindow: vi.fn(async () => null),
});
let waited: Promise<void> | null = null;
const result = await adapter.handle({
notification: { data: clickData(), close() {} },
waitUntil(task) {
waited = task;
},
});
await waited;
expect(result).toEqual({ ok: true, value: undefined });
expect(dispatched(observations)).toEqual([
{
event: "web_push_click_dispatched",
outcome: "SUCCEEDED",
nativeEffect: "CONFIRMED",
},
]);
});
it("confirms NOT_APPLIED only for an explicit null window", async () => {
const { adapter, observations } = await clickAdapterWith({
async matchControlledWindowClients() {
return [];
},
openWindow: vi.fn(async () => null),
});
let waited: Promise<void> | null = null;
const result = await adapter.handle({
notification: { data: clickData(), close() {} },
waitUntil(task) {
waited = task;
},
});
await waited;
expect(result.ok).toBe(false);
expect(dispatched(observations)).toEqual([
expect.objectContaining({
outcome: "FAILED",
nativeEffect: "NOT_APPLIED",
}),
]);
});
it("keeps MAYBE_APPLIED when the native effect rejects after the deadline", async () => {
const clock = manualScheduler();
let rejectFocus: ((reason: unknown) => void) | undefined;
const { adapter, observations } = await clickAdapterWith(
{
async matchControlledWindowClients() {
return [
{
url: "https://app.example.test/current",
focus: () =>
new Promise<void>((_resolve, reject) => {
rejectFocus = reject;
}),
postMessage() {},
},
];
},
openWindow: vi.fn(async () => null),
},
clock.scheduler,
);
let waited: Promise<void> | null = null;
const handling = adapter.handle({
notification: { data: clickData(), close() {} },
waitUntil(task) {
waited = task;
},
});
await vi.waitFor(() => expect(rejectFocus).toBeDefined());
clock.expireAll();
const result = await handling;
expect(result.ok).toBe(false);
// The effect lands only now, after the terminal result.
rejectFocus?.(new Error("focus failed late"));
await waited;
const records = dispatched(observations);
expect(records).toHaveLength(2);
// The evidence record never claims the click was definitely not applied.
expect(records.at(-1)).toEqual({
event: "web_push_click_dispatched",
outcome: "DEGRADED",
reason: "ABORTED",
nativeEffect: "MAYBE_APPLIED",
});
});
it("waits for the late effect evidence inside waitUntil", async () => {
const clock = manualScheduler();
let resolveFocus: (() => void) | undefined;
const { adapter, observations } = await clickAdapterWith(
{
async matchControlledWindowClients() {
return [
{
url: "https://app.example.test/current",
focus: () =>
new Promise<void>((resolve) => {
resolveFocus = resolve;
}),
postMessage() {},
},
];
},
openWindow: vi.fn(async () => null),
},
clock.scheduler,
);
let waited: Promise<void> | null = null;
const handling = adapter.handle({
notification: { data: clickData(), close() {} },
waitUntil(task) {
waited = task;
},
});
await vi.waitFor(() => expect(resolveFocus).toBeDefined());
clock.expireAll();
await handling;
let waitUntilSettled = false;
const pendingWait = waited as Promise<void> | null;
void pendingWait?.then(() => {
waitUntilSettled = true;
});
await Promise.resolve();
await Promise.resolve();
// The handler's lifetime is still open because the effect has not landed.
expect(waitUntilSettled).toBe(false);
resolveFocus?.();
await waited;
expect(
dispatched(observations).at(-1),
).toEqual({
event: "web_push_click_dispatched",
outcome: "DEGRADED",
reason: "ABORTED",
nativeEffect: "CONFIRMED",
});
});
});