Project

General

Profile

Feature #3250 » W13_gate_dead-code-oms-bug-fixes.txt

Bot AI, 09/01/2026 12:50 PM

 
================================================================================
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, <Link>, 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
<Link href={`/expense-summary/${projectId}`}>
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 <Link> whose accessible
name is aria-label="View Expense Summary" wrapping an <Eye> 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 -> <Listbox options={...}>
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.
================================================================================
(3-3/7)