================================================================================ Gate 3a — Dead Code Node: W13_gate_dead_code Ticket: #3250 (oms-bug-fixes / chips + summary) Repo: oms-web Branch: feat/3250-oms-ui-bug-fixes-chips-s Result: PASS (0 items removed — no provably-dead code found in scope) ================================================================================ SCOPE — files scanned (sides.web.feature_files, 12 files) -------------------------------------------------------------------------------- 1. app/(app)/admin/items/page.tsx 2. app/(app)/admin/projects/page.tsx 3. app/(app)/admin/suppliers/page.tsx 4. app/(app)/admin/uom/page.tsx 5. app/(app)/admin/users/page.tsx 6. app/(app)/expense-summary/[project]/page.tsx 7. app/(app)/expense-summary/page.tsx 8. app/(app)/expense-summary/ExpenseSummaryRowActions.tsx 9. app/(app)/expenses/page.tsx 10. app/(app)/orders/page.tsx 11. components/forms/ExpenseForm.tsx 12. components/forms/ResetPasswordForm.tsx METHOD -------------------------------------------------------------------------------- * Full read of all 12 files (no sampling). * eslint @typescript-eslint/no-unused-vars over all 12 files (args:all, argsIgnorePattern ^_, varsIgnorePattern ^_). * npx tsc --noEmit -p tsconfig.json (whole project). * Cross-repo grep for every exported symbol across app/, components/, lib/, tests/ — test files INCLUDED before considering any deletion. * Route-reachability grep for each App Router segment in scope (lib/nav.ts, lib/permissions/registry.ts, , router.push). * Barrel scan: find app components lib -name "index.ts*". * git diff main...HEAD -- prisma/ for schema fields added by this ticket. * Comment scan for commented-out code blocks and TODO/FIXME/XXX/HACK. -------------------------------------------------------------------------------- STEP 1 RESULTS -------------------------------------------------------------------------------- [1] UNUSED EXPORTS ......................................................... 0 Every exported symbol in scope has at least one non-test importer: ExpenseSummaryRowActions -> app/(app)/expense-summary/page.tsx:7,26 (+ tests/expense-summary-row-actions.test.tsx) ResetPasswordForm -> app/(app)/profile/reset-password/page.tsx:3,13 (+ tests/reset-password-form.test.tsx, tests/profile-reset-password-page.test.tsx) ExpenseForm -> app/(app)/expenses/new/page.tsx:2,13 app/(app)/expenses/[id]/edit/page.tsx:5,16 (+ tests/expense-form.test.tsx, tests/expenses-new-edit-pages.test.tsx) generateMetadata -> Next.js App Router convention export (app/(app)/expense-summary/[project]/page.tsx:21) metadata / default export -> Next.js App Router convention exports (all 8 page.tsx files in scope) [2] UNUSED IMPORTS / UNREFERENCED LOCALS ................................... 0 eslint no-unused-vars output over all 12 files: components/forms/ResetPasswordForm.tsx 111:5 error Definition for rule 'react-hooks/exhaustive-deps' was not found react-hooks/exhaustive-deps 1 problem (1 error, 0 warnings) NOT a finding. That is an artifact of the ad-hoc --no-eslintrc config used for this scan (the react-hooks plugin was not loaded, so the file's own inline eslint-disable comment on line 111 had no rule to resolve). Zero no-unused-vars violations were reported. The repo's real lint config already passed in W12 (docs/gate-evidence/W12_gate_lint-oms-bug-fixes.txt). `npx tsc --noEmit` over the whole project: clean, no output. [3] COMMENTED-OUT CODE BLOCKS (>3 lines) ................................... 0 Per-file count of code-shaped comment lines (^\s*//.*[;{}()=]\s*$): all 12 files: 0 All block comments in scope are prose rationale tied to a spec reference (ticket #3247/#3248/#3250 notes, TB-OMS-SRS-UP-001 §10.1, SCR-014), not disabled code. Retained deliberately. [4] DEAD BARREL ENTRIES .................................................... 0 Only one barrel exists under app/ components/ lib/: lib/permissions/index.ts export * from "./registry"; -> lib/permissions/registry.ts EXISTS export * from "./evaluate"; -> lib/permissions/evaluate.ts EXISTS export * from "./guard"; -> lib/permissions/guard.ts EXISTS No re-export points at a deleted or renamed file, so there is no dead barrel entry to remove. See OBSERVATIONS #2 below for a related, separate note about this file that is deliberately NOT actioned here. [5] ORPHANED ROUTE SEGMENTS ................................................ 0 /expense-summary reachable: lib/nav.ts:40 sidebar entry { href: "/expense-summary", label: "Expense Summary", icon: "BarChart3", permission: "expense_summary:read" } guarded: lib/permissions/registry.ts:111 /expense-summary/[project] reachable: app/(app)/expense-summary/ExpenseSummaryRowActions.tsx:9 rendered from the Actions column of the parent list (app/(app)/expense-summary/page.tsx:26) guarded: lib/permissions/registry.ts:111 (/^\/expense-summary(\/.*)?$/) /admin/items, /admin/projects, /admin/suppliers, /admin/uom, /admin/users, /expenses, /orders all pre-existing sidebar routes in lib/nav.ts; unchanged by this ticket. [6] UNUSED PRISMA SCHEMA FIELDS / MODELS ................................... 0 git diff main...HEAD -- prisma/ => empty. This ticket introduces no schema change, so there is no shipped-but-unused field to report. (Had there been one it would be reported, not deleted — dropping a field is a migration decision, not this gate's.) [7] TODO / FIXME / XXX / HACK MARKERS ...................................... 0 grep over all 12 files: none. -------------------------------------------------------------------------------- STEP 2 — REMOVALS -------------------------------------------------------------------------------- NOTHING REMOVED. No file in this checkout was modified by this gate. Every candidate examined was traced to a live reference before being ruled out. No symbol was deleted on the strength of "no importer found in app/ or components/" alone — tests/ was searched too in every case, per the gate's own rule that test-only references still count as live. -------------------------------------------------------------------------------- OBSERVATIONS — reported, deliberately NOT auto-fixed -------------------------------------------------------------------------------- #1 STALE TEST ASSERTION (pre-existing failure, NOT dead code) tests/expense-summary-page.test.tsx:29 expect(screen.getByText("View Details")).toHaveAttribute( "href", "/expense-summary/p1"); This assertion fails. Confirmed by running it: npx vitest run tests/expense-summary-page.test.tsx \ tests/expense-summary-row-actions.test.tsx Test Files 1 failed | 1 passed (2) Tests 1 failed | 4 passed (5) TestingLibraryElementError at tests/expense-summary-page.test.tsx:29:19 Cause: ticket #3250 R5 replaced the old text link with an icon-only control. ExpenseSummaryRowActions.tsx:9 renders a whose accessible name is aria-label="View Expense Summary" wrapping an icon — there is no "View Details" text node in the tree any more. The href itself is correct; only the query for the element is stale. NOT fixed here, for two reasons: (a) Rewriting a test assertion is authoring test code, which is outside this gate's whitelist (unused exports/imports, duplicate components, orphaned routes, unused schema fields, dead barrel entries). (b) It is genuinely ambiguous which side is wrong. If the icon-only treatment is the intended R5 outcome, the test should be updated to getByLabelText("View Expense Summary"). If the design actually calls for a visible "View Details" label, the component is the regression. Picking one silently would either mask a real UI regression or overwrite a deliberate design decision. Escalating instead. Owner: the test/UI gate, not this one. Flagged so it is not mistaken for a dead-code finding and not silently carried past this node. #2 UNIMPORTED BARREL (pre-existing, out of ticket scope) lib/permissions/index.ts Zero importers repo-wide — `grep -rn 'from "@/lib/permissions"'` across app/, components/, lib/, tests/ returns nothing. Consumers import the concrete modules (@/lib/permissions/ui, /registry, /guard, /evaluate) directly instead. NOT removed: * It is not a dead barrel entry in this gate's sense — all three re-export targets exist on disk (see [4] above). * It is pre-existing, not introduced by this ticket. `git cat-file -e main:lib/permissions/index.ts` succeeds; last touched by 1e617eb "Data Layer (oms-rbac-v2)". * It is not in sides.web.feature_files. Deleting a file outside this ticket's scope on a shared branch is beyond what a per-ticket dead-code gate should do unilaterally. Recommend a separate housekeeping ticket: either delete the barrel or adopt it consistently. #3 DUPLICATED CONSTANT (both copies live — a DRY issue, not dead code) EXPENSE_TYPE_OPTIONS is declared twice with identical contents: components/forms/ExpenseForm.tsx:37 (typed OptionRow[]) app/(app)/expense-summary/[project]/page.tsx:11 (untyped) Both are referenced by their own module and neither is exported: ExpenseForm.tsx:127 -> expense-summary/[project]/page.tsx:41,72 -> type-label lookup + filter NOT removed: neither copy is dead, so deleting either breaks a live reference. Collapsing them means introducing a shared module and rewiring two importers — a refactor, not a dead-code deletion, and it crosses the server/client component boundary (ExpenseForm.tsx is "use client", the summary page is a server component). Flagged for follow-up; the seven values must stay in sync with the ExpenseType enum meanwhile. -------------------------------------------------------------------------------- SUMMARY -------------------------------------------------------------------------------- files scanned .............. 12 unused exports ............. 0 unused imports ............. 0 commented-out blocks ....... 0 dead barrel entries ........ 0 orphaned routes ............ 0 unused schema fields ....... 0 TODO/FIXME markers ......... 0 ------------------------------ items removed .............. 0 files modified ............. 0 (this gate wrote only this evidence file) observations escalated ..... 3 (1 failing test, 1 unimported barrel, 1 duplicated constant) GATE STATUS: PASS PASS basis: no provably-dead code exists in the 12 files in scope, so there was nothing to remove. Observation #1 is a real, currently-failing test — it is a test-correctness defect, not a dead-code finding, and is recorded here so it is visibly owned by a downstream gate rather than lost. ================================================================================