Skip to content

tech-debt(citation-manager): pre-existing any types in citation-manager.ts block edits via smart-lint hook cascade #1

@WesleyMFrederick

Description

@WesleyMFrederick

Problem

Editing citation-manager.ts for any feature work triggers the smart-lint hook (Biome), which flags pre-existing any types throughout the file. Each edit shifts line numbers, causing Biome to discover new any usages deeper in the file. This creates a blocking cascade: fix one any → linter finds another → fix that → linter finds another → repeat ~6 times before reaching clean state.

The file has 13+ pre-existing any usages across formatForCLI(), formatAsJSON(), filterResultsByLineRange(), applyAnchorFix(), and fix() methods. These all predate the current work and are unrelated to any feature being implemented.

Reproduction Steps

  1. Open tools/citation-manager/src/citation-manager.ts
  2. Make any edit near line 50 (e.g., add a new import)
  3. Smart-lint hook runs Biome on the file
  4. Biome flags any at line ~242 (filterResultsByLineRange)
  5. Fix that any → Biome now flags any at line ~307 (formatForCLI)
  6. Fix that any → TS compiler errors on discriminated union narrowing across chained .filter().forEach() calls
  7. Revert to any with biome-ignore → Biome finds any at line ~750 (fix() method)
  8. Fix that → Biome finds any at line ~943 (applyAnchorFix)
  9. Fix that → Biome finds useOptionalChain at line ~1024
  10. Fix that → Biome finds noImplicitAnyLet at line ~1076
  11. Each round requires a Read + Edit cycle, burning context and time

Root Cause

Two compounding issues:

  1. Pre-existing any types: The file was migrated from JavaScript and retains ~13 any annotations that were never typed. These are in formatting/display methods (formatForCLI, formatAsJSON) and fix logic (applyAnchorFix, fix).

  2. Discriminated union narrowing gap: ValidationMetadata is a discriminated union ({ status: "valid" } | { status: "error"; error: string; suggestion?: string }) . The .filter(link => link.validation.status === "error").forEach(link => link.validation.error) pattern doesn't narrow the type because TypeScript doesn't propagate discriminant narrowing across chained array methods. Simply replacing any with EnrichedLinkObject causes TS2339 errors.

Expected Behavior

  • Editing citation-manager.ts should not trigger a cascade of pre-existing lint issues
  • All any types should be replaced with proper types
  • The discriminated union access pattern should use type-safe narrowing (e.g., in-callback type guards or intermediate typed variables)

Related

  • Encountered during #92 implementation (cache refactor)
  • Related to Scattered File I/O Operations tech debt (same file)
  • ValidationMetadata type defined in /WesleyMFrederick/cc-workflows/blob/main/tools/citation-manager/src/types/validationTypes.ts

Note

  • The formatForCLI method is the hardest to type because it accesses .validation.error and .validation.suggestion after filtering by status, but TS doesn't narrow across .filter().forEach() chains
  • A type guard function like isErrorLink(link): link is EnrichedLinkObject & { validation: { status: "error"; error: string } } would solve the narrowing issue
  • Alternatively, restructure to use if blocks with direct property access after narrowing
  • The applyAnchorFix method receives links that are guaranteed to be error/warning status by the caller, but the type signature doesn't reflect this — a FixableLink type alias would help
  • Workaround for now: biome-ignore comments on pre-existing any usages

Acceptance Criteria

  • All any types in citation-manager.ts replaced with proper TypeScript types
  • formatForCLI() uses type-safe discriminated union narrowing (no any callbacks)
  • formatAsJSON() typed with ValidationResult
  • filterResultsByLineRange() typed with ValidationResult (already done in current branch)
  • applyAnchorFix() uses a narrowed type (e.g., FixableLink or type predicate)
  • fix() method callbacks typed with EnrichedLinkObject
  • let result in validate action handler has explicit type annotation
  • Optional chain used where Biome suggests (useOptionalChain)
  • No biome-ignore comments for noExplicitAny remain in the file
  • All existing tests pass without modification

Definition of Done

  • Failing tests written (RED phase) — existing tests serve as regression suite
  • Implementation complete (GREEN phase)
  • All tests pass (npm test)
  • Build succeeds (npm run build -w tools/citation-manager)
  • Biome check passes (npx biome check tools/citation-manager/src/citation-manager.ts)
  • Committed with conventional commit

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions