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
- Open
tools/citation-manager/src/citation-manager.ts
- Make any edit near line 50 (e.g., add a new import)
- Smart-lint hook runs Biome on the file
- Biome flags
any at line ~242 (filterResultsByLineRange)
- Fix that
any → Biome now flags any at line ~307 (formatForCLI)
- Fix that
any → TS compiler errors on discriminated union narrowing across chained .filter().forEach() calls
- Revert to
any with biome-ignore → Biome finds any at line ~750 (fix() method)
- Fix that → Biome finds
any at line ~943 (applyAnchorFix)
- Fix that → Biome finds
useOptionalChain at line ~1024
- Fix that → Biome finds
noImplicitAnyLet at line ~1076
- Each round requires a Read + Edit cycle, burning context and time
Root Cause
Two compounding issues:
-
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).
-
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
Definition of Done
Problem
Editing
citation-manager.tsfor any feature work triggers the smart-lint hook (Biome), which flags pre-existinganytypes throughout the file. Each edit shifts line numbers, causing Biome to discover newanyusages deeper in the file. This creates a blocking cascade: fix oneany→ linter finds another → fix that → linter finds another → repeat ~6 times before reaching clean state.The file has 13+ pre-existing
anyusages acrossformatForCLI(),formatAsJSON(),filterResultsByLineRange(),applyAnchorFix(), andfix()methods. These all predate the current work and are unrelated to any feature being implemented.Reproduction Steps
tools/citation-manager/src/citation-manager.tsanyat line ~242 (filterResultsByLineRange)any→ Biome now flagsanyat line ~307 (formatForCLI)any→ TS compiler errors on discriminated union narrowing across chained.filter().forEach()callsanywith biome-ignore → Biome findsanyat line ~750 (fix()method)anyat line ~943 (applyAnchorFix)useOptionalChainat line ~1024noImplicitAnyLetat line ~1076Root Cause
Two compounding issues:
Pre-existing
anytypes: The file was migrated from JavaScript and retains ~13anyannotations that were never typed. These are in formatting/display methods (formatForCLI,formatAsJSON) and fix logic (applyAnchorFix,fix).Discriminated union narrowing gap:
ValidationMetadatais 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 replacinganywithEnrichedLinkObjectcauses TS2339 errors.Expected Behavior
citation-manager.tsshould not trigger a cascade of pre-existing lint issuesanytypes should be replaced with proper typesRelated
ValidationMetadatatype defined in/WesleyMFrederick/cc-workflows/blob/main/tools/citation-manager/src/types/validationTypes.tsNote
formatForCLImethod is the hardest to type because it accesses.validation.errorand.validation.suggestionafter filtering by status, but TS doesn't narrow across.filter().forEach()chainsisErrorLink(link): link is EnrichedLinkObject & { validation: { status: "error"; error: string } }would solve the narrowing issueifblocks with direct property access after narrowingapplyAnchorFixmethod receives links that are guaranteed to be error/warning status by the caller, but the type signature doesn't reflect this — aFixableLinktype alias would helpbiome-ignorecomments on pre-existinganyusagesAcceptance Criteria
anytypes incitation-manager.tsreplaced with proper TypeScript typesformatForCLI()uses type-safe discriminated union narrowing (noanycallbacks)formatAsJSON()typed withValidationResultfilterResultsByLineRange()typed withValidationResult(already done in current branch)applyAnchorFix()uses a narrowed type (e.g.,FixableLinkor type predicate)fix()method callbacks typed withEnrichedLinkObjectlet resultin validate action handler has explicit type annotationuseOptionalChain)biome-ignorecomments fornoExplicitAnyremain in the fileDefinition of Done
npm test)npm run build -w tools/citation-manager)npx biome check tools/citation-manager/src/citation-manager.ts)