chore: initialize from frontend template 4dc033c

This commit is contained in:
DongHyeonka
2026-08-13 18:23:26 +09:00
commit 40107eec84
897 changed files with 234824 additions and 0 deletions
@@ -0,0 +1,110 @@
# Task 5 Report: Retain and reconcile uncertain optimistic mutations
## Status
Task 5 is implemented. Mutation settlement now follows explicit effect certainty, preserves unknown optimistic projections as ordered uncertain layers, and exposes one-at-a-time reconciliation bound to the original mutation record. Missing post-dispatch certainty is fail-safe `MAYBE_APPLIED`; only controller-owned pre-dispatch failures are marked `NOT_STARTED`.
## RED evidence
- Initial focused command: `corepack pnpm exec vitest run tests/unit/optimistic-layer-runtime.test.ts tests/component/application-query.test.tsx`.
- Initial result: exit `1`, 2 files, 11 failed / 28 passed. Missing lease/controller APIs failed directly; `APPLIED_CONFIRMED` and `MAYBE_APPLIED` were rolled back; effectless failures retained generic retry semantics.
- Review-driven RED: the three-file focused command including `tests/component/async-surface.test.tsx` exited `1` with 7 failed / 56 passed. It exposed applied-confirmed retry actions, active-submit reset, double reconciliation, stale-scope queue retention, overlay priority, and the incorrect refreshing copy.
- A final isolated RED proved a synchronous `NOT_APPLIED` double action could consume two FIFO records in one event turn.
- The production-form RED exited `1` with 2 failed / 8 passed: applied reconciliation left the original command dirty/retryable, while an `APPLIED_CONFIRMED` failure rendered generic unavailable.
- The final durability/lifecycle RED failed 2 / 2: an anonymous non-optimistic legacy channel did not survive remount, and render-time registry allocation exhausted the definition cap during an abandoned server render.
## Implementation
1. `OptimisticLayerLease` now supports `markUncertain()` and `reconcile("APPLIED" | "NOT_APPLIED")`. Layers are `pending | uncertain | committed`; only a committed prefix collapses into the base, while projection continues to apply every later layer in order.
2. Reconciliation is single-settlement and idempotent. `APPLIED` converts the uncertain layer to committed; `NOT_APPLIED` removes only that layer; both then collapse/reproject later committed or pending layers. Scope expiry removes stale cache instead of restoring it.
3. Legacy optimistic mutations use the same reusable always-current ordered runtime. This prevents an old manual snapshot from erasing a later successful mutation or authoritative projection. The runtime also supports optimistic entries whose base data was absent and removes them on a not-applied rollback.
4. The mutation bridge derives effect before touching optimistic state:
- `NOT_STARTED` / `NOT_APPLIED`: rollback;
- `APPLIED_CONFIRMED`: commit, then best-effort invalidate;
- `MAYBE_APPLIED`: retain as uncertain, do not invalidate, and enqueue explicit reconciliation.
5. Missing or `NOT_APPLICABLE` command effects, returned failures after dispatch, and thrown execution failures normalize to `MAYBE_APPLIED`. Unknown effects are non-retryable with `contact-support`; applied-confirmed failures are non-retryable with no resend action. Controller-owned stale scope, duplicate admission, identity/preparation, and other known pre-dispatch failures carry `NOT_STARTED`.
6. Unknown records retain their original intent, scope, layer lease, invalidation topics, and coordinator. A FIFO queue prevents parallel `ALLOW_PARALLEL` failures from overwriting each other. Reconciliation is locked through the event turn so a double action cannot consume the next intent, and it does not reset a newer active submit.
7. Scope abort discards every queued record from that scope, settles only its local stale layers, performs no invalidation, and cannot later overwrite new-generation cache data.
8. Async state adds the mutually exclusive `mutation-effect-unknown` overlay with priority `unknown > conflict > pending > stale-degraded > refreshing`. `AsyncSurface` uses dedicated safe copy and only `APPLIED` / `NOT_APPLIED` actions; it does not expose generic retry or mark the surface busy.
9. Unknown-effect admissions live in a bounded QueryClient-owned registry, so bound and legacy controllers can remount without losing reconciliation state. Channels include definition version and generation, validate the exact scope owner, count active admissions globally in O(1), release after late settlement, and preserve FIFO order even when executions finish in reverse.
10. Channel creation and scope-abort listener registration occur only in a committed React effect. An abandoned/server render performs no registry mutation and consumes no channel capacity. Non-optimistic legacy callers must provide a stable `definitionId`; optimistic legacy callers also include their query identity.
11. The reference create form blocks all generic resubmission while effect certainty is unknown. `NOT_APPLIED` preserves input and re-enables submission; `APPLIED` reconciliation and `APPLIED_CONFIRMED` settlement use the form's success-equivalent reset path so the same create command cannot be resent.
## Test coverage
- Certainty matrix for all four mutation effects, missing effect, `NOT_APPLICABLE`, thrown execution, ambiguous conflicts, and non-retry semantics.
- Applied-confirmed commit-before-invalidate ordering and retained commit when invalidation fails.
- Out-of-order later commits behind uncertain layers; both reconciliation outcomes; duplicate/reversed lease transitions; external cache projection; expired scope.
- Bound and legacy reconciliation, no-layer legacy fallback, parallel unknown queues, same-turn double actions, active newer submit preservation, scope-wide stale cleanup, and no-prior-cache rollback.
- Bound and non-optimistic legacy remount durability, unrelated legacy isolation, generation isolation, exact scope-owner collision handling, abandoned-render capacity, late empty-channel cleanup, QueryClient-global admission bounds, reverse completion, and fence-during-invalidation races.
- Production create-form coverage for the `MAYBE_APPLIED` block, `NOT_APPLIED` input preservation, and success-equivalent `APPLIED` / `APPLIED_CONFIRMED` settlement.
- Unknown overlay derivation, mutual-exclusion priority, dedicated localized copy, non-busy state, and reconciliation-only actions.
- The negative async-overlay type fixture now includes `mutationEffectUnknown: false`, so it continues to fail for the intended pending/conflict exclusivity violation.
## Files changed
- `src/presentation/adapters/query/optimistic-layer-runtime.ts`
- `src/presentation/adapters/query/application-query.ts`
- `src/application/view-models/async-state.ts`
- `src/contracts/errors.ts`
- `src/presentation/components/async-surface.tsx`
- `src/presentation/forms/form-contracts.ts`
- `src/presentation/forms/use-app-form.ts`
- `src/presentation/i18n/catalog.ts`
- `src/features/reference-feature/presentation/reference-resource-form-page.tsx`
- `tests/unit/optimistic-layer-runtime.test.ts`
- `tests/component/application-query.test.tsx`
- `tests/component/async-surface.test.tsx`
- `tests/features/reference-feature/reference-page.test.tsx`
- `tests/fixtures/typecheck/invalid-async-overlay.ts`
The AsyncSurface, catalog, UI test, and type-fixture additions are a narrow scope expansion required to avoid rendering the new indicator as a background refresh and to preserve the overlay type contract.
## Verification
- Final focused command (error classification, optimistic runtime, mutation bridge, async surface, form facade, and production reference form): 6 files / 100 tests — PASS.
- `corepack pnpm check:types` — PASS for app, node, test, recipes, web worker, and service worker.
- `corepack pnpm lint` — PASS with zero warnings.
- `corepack pnpm test:all` — PASS: runtime schema 40, unit 741, component 123, integration 23, reference feature 24, recipes 17.
- `git diff --check` — PASS.
- `corepack pnpm run check:types:fixture:async-overlay` — expected non-zero; TypeScript rejects `mutationConflict: true` when `mutationPending: true`, confirming the negative fixture still reaches its intended invariant.
## Self-review decisions
- The plan-prescribed `reconcileUnknownEffect(resolution)` API remains intact. Rather than introduce a public token incompatible with that interface, the controller retains intent-bound FIFO records and serializes reconciliation through the current event turn. A repeated action after the first promise settles is an explicit action on the next visible unknown record.
- Scope cleanup removes stale local projection without claiming or invalidating a server outcome. A stale generation cannot use its former record after the queue is discarded.
- Legacy manual snapshot restoration was removed because it could erase later successful work. Shared ordered layers are the minimal mechanism that gives legacy and bound mutations the same re-projection guarantees.
- A non-optimistic legacy mutation has no cache key from which a durable logical identity can be inferred. Its type contract therefore requires a stable caller-supplied `definitionId`; this preserves remount durability without merging unrelated controllers.
- Registry mutation was moved out of render into the committed effect lifecycle. The server-render regression fills the nominal definition count with abandoned renders, then proves a committed mutation can still acquire and execute.
- Browser/Playwright gates were not run; this task changed no browser-only integration. The jsdom component tests cover the new accessible status and actions.
## Final review
The scoped reviewer completed two fix rounds covering durable ownership, FIFO/races, global bounds, scope fences, and production form settlement. The final verdict reported no findings, independently passed 4 files / 84 tests, confirmed `git diff --check`, and assessed the change ready to merge.
## Runtime final-review fix round 3
The runtime-wide final review identified three additional Task 5 authorities. This round addresses only those findings; the provider-neutral HTTP operation port remains deferred to its separately owned remediation plans.
### RED evidence
- Composite optimistic admission: `tests/unit/optimistic-layer-runtime.test.ts` failed 2 / 8 cases because a base-valid candidate that threw only after the prior layer returned a lease and orphaned both rollback and reconciliation authority.
- Candidate replay: the isolated admission test failed with candidate updater call count `2` instead of `1`; replay through `project()` could still delete the entry after successful preflight.
- Form reconciliation: `tests/component/form-foundation.test.tsx` failed 3 / 8 cases. The hook admitted a second submit during unknown effect, settled edited value B instead of submitted snapshot A, and exposed no explicit not-applied release authority.
- Production namespace parity: the mounted reference-page regression failed because `REFERENCE_RESOURCE_QUERY_NAMESPACE` was not exported; production list/detail hooks could only duplicate its id/version literals.
### Implementation
1. `OptimisticLayerRuntime.begin()` now computes the complete ordered projection before admission. A composite failure returns pessimistic fallback `null` without changing the existing entry, cache projection, layer IDs, or earlier lease authority. The admitted candidate is written from that precomputed value, so its updater runs exactly once during admission.
2. `useAppForm` retains the exact parsed values for a `MAYBE_APPLIED` submission. The ref is the hook-level admission lock until `settleApplied`, `settleNotApplied`, or `reset` releases it; later edits preserve the unknown result and cannot trigger another command. With `resetOnSuccess: false`, APPLIED makes submitted A the baseline while edited B remains dirty. Success, applied-confirmed, validation/conflict/unavailable outcomes, reset, and explicit not-applied settlement clear the retained snapshot.
3. The reference form routes both reconciliation outcomes into the corresponding form settlement authority.
4. `REFERENCE_RESOURCE_QUERY_NAMESPACE` is exported from the governed feature contract. Both production list and detail query definitions consume its fields, while the mounted-key regression compares both real query prefixes with the installed invalidation edge.
### Verification
- Focused runtime/form/reference command: 5 files / 87 tests — PASS.
- `corepack pnpm check:types` — PASS for app, node, test, recipes, web worker, and service worker.
- `corepack pnpm lint` — PASS with zero warnings.
- `corepack pnpm test:all` — PASS: runtime schema 40, unit 744, component 126, integration 23, reference feature 25, recipes 17.
- `git diff --check` — PASS.
- Scoped re-review by the existing Task 5 reviewer: no findings, ready to merge. The reviewer independently passed the 5-file scoped suite (96 / 96), confirmed `git diff --check`, verified all three reconciliation authorities plus candidate single-invocation, and confirmed the deferred HTTP adapter remained untouched.