The converged admin type layer now has a regression guard
This closer verifies the end state from Stories 1693-1696 and adds a CI-enforced static check so backend wire contracts stay imported from @/gen/types, view-models stay feature-owned, and src/types remains limited to cross-cutting table UI types.
Converged state evidence
grep -rn 'from "@/types"' src returned zero rows. The command exits 1 for no matches, which is the expected clean result.
ls src/types prints only data-table.ts.
rg 'export\s+(interface|type)\s+(ActivityFeed(Item|Response)|FirmListRequest|SeatAdjustRequest|PlanChangeRequest|SubscriptionActionResponse|ReassignCSM(Request|Response))\b' src/types returned zero rows.
The generated replacements are present under src/gen/types: ActivityFeedItem, ActivityFeedResponse, AdminListFirms for the old firm-list request shape, SeatAdjustRequest, PlanChangeRequest, SubscriptionActionResponse, ReassignCSMRequest, and ReassignCSMResponse.
Guardrail behavior
scripts/frontend-drift-checks.mjs now has a hard-error type-convergence pass in addition to its existing warning-only drift checks. It parses TypeScript source and fails when:
srcimports or re-exports@/typesor any deep@/types/*path other than@/types/data-table.src/types/*.tsexports a hand-writteninterfaceortypewhose name matches a generatedsrc/gen/typesexport or one of the removed Story-1693 mirror names.src/types/*.tsimports or re-exports generated contracts from@/gen/typesor the equivalent relative../gen/typespath.
The CI wiring stays in the existing path: pnpm run check:frontend-drift is still invoked by .github/workflows/ci.yml. The step label was updated from "warnings only" because convergence violations now exit non-zero.
Regression proof
A temporary negative control added this import to src/app/(admin)/firms/firm-list-request.ts:
import type { FirmListResponse } from "@/types";
pnpm run check:frontend-drift failed with exit code 1 and the actionable message:
::error file=src/app/(admin)/firms/firm-list-request.ts,line=12,col=39::Forbidden @/types import. Story-1697 type-layer convergence: import API contracts directly from @/gen/types/*, keep view-models feature-local, and reserve @/types for data-table only.
The temporary import was removed before committing. The clean tree then passed the same guardrail with Type-layer convergence guardrail passed.
Verification proof
pnpm lintpassed with zero errors and the existing three React Compiler/TanStack warnings.pnpm exec tsc --noEmitpassed.pnpm testpassed: 91 files, 579 tests.NEXT_PUBLIC_ENV=local pnpm buildpassed.pnpm build-storybookpassed; Storybook emitted its existing package/chunk-size warnings and completed successfully.pnpm run check:frontend-driftpassed clean for the type-convergence guardrail on the restored tree.git diff --checkpassed after the walkthrough was added.
Scope boundaries
No type moves, deletions, codegen, generated contract edits, OpenAPI snapshot edits, pramaan-functions changes, pramaan-app changes, i18n work, or src/types/data-table.ts content changes were made.
pramaan-docs ADR-124: instrumentation-exempt. The new executable code is a local/CI tooling checker only. It does not add a product route, handler, workflow boundary, external call, background job, or user-visible state change.