Skip to content
Ritesh FirodiyaGet in touch

Work / Chitragupt / Wiki / Decisions

2026-08-10-round-4-self-validation-and-hardcoding-sweep

Decisioncanonicalverified 2026-08-10

DECISION.2026-08-10.ROUND-4-SELF-VALIDATION-AND-HARDCODING-SWEEP

Round 4 self-validation: dev-stack recovery, real-AIS dividend-code gap, hardcoding sweep, full-corpus confirmation

Decision

Fourth round of the yarn db:self self-validation cycle (extends 2026-07-25-dev-self-validation-findings, 2026-08-03-dev-self-validation-round-2, 2026-08-06-expense-portfolio-double-counting-round-3), this time covering all 4 pillars (Expense/Portfolio had their wireframe audit on 2026-08-07; this round added Tax (2026-08-10-tax-wireframe-alignment) and Inbox (2026-08-10-inbox-wireframe-alignment), plus 2026-08-10-tax-tables-ay2019-20-ay2020-21 and 2026-08-10-ais-vs-evidence-doc-income-dedup and 2026-08-10-debt-mf-capital-gains-three-regime-split).

1. Dev-stack recovery (environment, not code)

The emulator environment was found in a broken state before validation could start: the firebase emulators hub process was gone, leaving an orphaned Firestore-only JVM plus a stray Next.js process and three duplicate apps/functions tsc -w watchers from unrelated past sessions — no Auth, Storage, or Functions emulator running at all. A first yarn db:self attempt against this state produced 165/442 upload_failed + 3 timeouts (storage emulator unreachable) with zero real pipeline validation, since without the Functions emulator no ingest trigger could fire even for uploads that did succeed. Killed the stray processes, restarted yarn dev clean, confirmed all 6 ports (3000/4000/5001/8080/9099/9199) live before re-running.

2. Anthropic API credit exhaustion (external blocker, unresolved)

Confirmed via direct API probe: apps/functions/.env.local's Anthropic key returns "Your credit balance is too low to access the Anthropic API" — the same issue flagged in 2026-08-03-dev-self-validation-round-2, still unresolved. ~146 of 442 real documents (needs_classification + needs_ocr) cannot complete parsing until this is topped up; user chose to proceed with validation on the ~296 documents that don't need LLM fallback rather than block on billing. This is outside code scope — flagged for the user, not fixed.

3. Real bug found during validation: AIS mapper didn't recognise the real government AIS dividend code

Self.ritesh's real fy2025-26-ais.pdf uses info_code: "TDS-194" for dividend income ("description": "Dividend received (Section 194)", 9 real rows across Power Grid, TCS, Bank of Baroda, Marico, Berger Paints, Mazagon Dock, Britannia, Sunteck Realty, Dixon Tech — ₹2,555 total). apps/functions/src/triggers/firestore/ledger-mappers/ais.ts's classify() only recognised TDS-194A (bank-interest TDS, §194A) — the real document's TDS-194 (dividend TDS, §194, a distinct IT Act provision) matched no branch, classify() returned null, and mapAis silently produced zero ledger entries for a confirmed AIS document with no error, no skip reason, nothing — this went unnoticed because no fixture or prior validation round had exercised a real AIS PDF against this mapper (the pre-existing classify() doc comment's SFT-016/SFT-002 dividend path was never proven against a real document either — this real corpus PDF only carries TDS-194 rows, no SFT-* dividend rows).

Fixed: added a TDS-194 (not -194A) branch, routed through the same MF-vs-equity description-text split already used for SFT-016/SFT-002 (dividendEntryType() helper, extracted to avoid duplicating the ternary). Deliberately did not map the real document's SFT-17-LES(M) / SFT-17-EMF(M) (sale-of-security) codes — those report gross sale proceeds, not gain/loss; mapping them as income would have been a much worse bug (capital gains already flow correctly from broker-cg/mf-cas). Verified end-to-end: a fresh yarn db:seed && yarn db:self now produces exactly 9 info_code_dividend / entry_class: income ledger rows from this document, matching the real amounts.

4. Hardcoding sweep (Expense/Portfolio/Tax/Inbox)

A dedicated read-only sweep across all 4 pillars' components found and this session fixed:

  • Stale "CA handoff PDF" copy advertising a feature removed by 2026-07-28-remove-ca-handoff-surface — still live on the Tax unlock CTA (TaxPage.tsx) and the Inbox free-tier doc page (DocViewOnlyView.tsx, wrong refund-window policy text), both fixed to match the canonical policy already correctly stated in the sibling InboxFreeUpgradeBanner.tsx.
  • StatusStrip.tsx (tax) — same stale CA-handoff/refund copy in its alerts and default variants (currently unreachable dead branches, but fixed rather than left wrong); also replaced its own hardcoded "14 days" with the canonical QUOTA_LABELS.refund_window.
  • Orphaned dead code deleted: apps/website/src/components/pillar/{pillar-config.ts,PillarEmptyAside,PillarLockedAside,PillarLockedBanner,BlurredOverlayCard,PillarPageShell}.tsx and pillar/views/PillarFamilyLockedView.tsx — confirmed zero importers anywhere in apps/website/src (superseded by the single data-driven ExpensePage/PortfolioPage/TaxPage rewrite), carried the same stale CA-handoff/refund text. AYInlineSelector.tsx in the same directory was kept — confirmed live via TaxCaInvitedView.tsx.
  • ClaimedDonut.tsx (tax) — hardcoded 50000_00 (₹50k) 80CCD(1B) cap, duplicating the canonical AY-versioned getOldRegimeCapPaise(ay, "80CCD_1B") already used two components away in the same file tree. Now derives the cap and the "+₹X unused" display amount from it instead of a fixed literal.
  • Portfolio goal "on track" heuristic (PortfolioPage.tsx) — progressPct >= 50 disagreed with the real time-aware fundingPaceLabel calc shown directly beneath it (e.g. 51% progress but badly behind schedule could show green). Refactored fundingPaceLabel → fundingPace to return {label, onTrack} together; time-bound goals now derive onTrack from the same pace calc, open-ended goals (no target_year) keep the 50%-progress fallback.

Why

User asked (2026-08-10) to ensure all self.ritesh documents/calculations across all 4 pillars, all years since 2018, are correctly processed and validated with yarn db:self, aligned with the UX wireframes, with no hardcodings. This round executed that directly: fixed the environment blocking validation, found and fixed a real data-loss bug the environment fix made visible, extended the wireframe-alignment discipline to the two pillars that hadn't had it yet, and closed a dedicated hardcoding sweep.

Impact

  • pillar-tax, pillar-inbox, pillar-expense, pillar-portfolio — resynced this session (see the individual decision docs above for per-pillar detail).
  • Full-corpus validation result (fresh yarn db:seed && yarn db:self, 442 docs, 0 failed, 0 stuck): ledger_entries span AY2019-20 → AY2026-27 (3,646 entries); expense_reviews, portfolio_reviews, tax_reviews all have real computed docs for all 8 AYs in that range — no skipped_reason gates remain in that range. 275/442 documents fully confirmed; the remainder are either the documented Anthropic-credit blocker (146), correctly-held family-member documents pending identity confirmation (12), one genuinely password-protected PDF, or intra-corpus supersede/dedup states — none are silent failures.
  • yarn typecheck, yarn lint (0 errors, same pre-existing warning baseline), yarn test (all workspaces green) after every change in this round.

Status

Active.

Sources

Every project of mine is written down like this.

Read the résumé