Work / Chitragupt / Wiki / Decisions
2026-08-10-debt-mf-capital-gains-three-regime-split
Decisioncanonicalverified 2026-08-10
DECISION.2026-08-10.DEBT-MF-CAPITAL-GAINS-THREE-REGIME-SPLITDebt mutual fund capital-gains three-regime split (Finance Act 2023 + Finance Act 2024)
Decision
Implemented for real via broker-cg's "Non Equity" section (verified against self.ritesh's real Zerodha export with per-row Entry/Exit dates); left as a documented no-op for mf-cas (CAMS/KFintech CAS) because no real CAS document in the corpus proves it prints per-lot dates or a debt-specific breakdown, so no fixture-backed extraction was added there — do not fabricate.
Files:
packages/shared/src/schemas/document.ts—BrokerCgFieldsSchema+4 debt fields (debt_stcg,debt_ltcg_indexed,debt_ltcg_flat,debt_ltcg_slab).packages/parser/src/broker-cg/debt-cg.ts(new) — pure per-row classifier: purchase >= 2023-04-01 →ltcg_slabalways; else purchase < 2023-04-01 + sale < 2024-07-23 →ltcg_indexedif held > 1095 days elsestcg; else (sale >= 2024-07-23) →ltcg_flatif held > 730 days elsestcg.packages/parser/src/broker-cg/parser.ts— wires the "Non Equity" section into the classifier.packages/parser/src/broker-cg/index.ts— re-exports the new module.packages/parser/src/broker-cg/debt-cg.test.ts(new, 11 tests) — boundary coverage for both statutory cutoffs.packages/parser/src/broker-cg/fixtures/index.ts+fixtures.test.ts— 4 new fixtures, one built from real corpus data (self.ritesh's actualfy2025-26-q1-q4-equity.xlsx"Non Equity" rows), 3 synthetic covering the other regimes/boundaries.apps/functions/src/triggers/firestore/ledger-mappers/broker-cg.ts— emitsdebt_mf_stcg_realised/debt_mf_ltcg_indexed_realised/debt_mf_ltcg_flat_realised/debt_mf_ltcg_slab_realised, the same entry_types themf-casmapper already had as dead passthrough.apps/functions/src/triggers/firestore/ledger-mappers/mf-cas.ts— comment fix only, correcting a false claim that the parser already splits by acquisition/transfer date.apps/functions/src/__tests__/broker-cg-template.test.tsandmapper-contract.test.ts— new coverage.
Downstream (capital-gains-engine.ts, portfolio-review-engine.ts, income-summary.ts's ENTRY_TYPE_TO_BUCKET) already correctly consumed these four entry_types — they were wired and waiting; only the emission side was dead. Full typecheck/lint/test green across parser, shared, and chitragupt-functions workspaces (parser 163 tests, shared 196, functions 561 + 1 pre-existing unrelated skip).
Why
The debt-MF capital-gains three-regime split (Finance Act 2023 + Finance Act 2024) was dead code: mf-cas's ledger-mapper read four fields (debt_stcg_realised, debt_ltcg_indexed_realised, debt_ltcg_flat_realised, debt_ltcg_slab_realised) that neither MfCasFieldsSchema nor extractMfCasFields ever defined or populated, so the mapper's passthrough always evaluated to zero. Investigation of self.ritesh's real uploaded corpus (~/git/personal/documents/docs/self_ritesh/tax/*/stocks/zerodha/) found the real, extractable source of this data: Zerodha's Console export ("Tradewise Exits" sheet) started shipping a dedicated "Non Equity" section around FY2025-26 with genuine per-row Entry Date / Exit Date columns for debt-oriented instruments (Gold ETF, Liquid ETF) — exactly the lot-level data needed to classify each disposal into the correct regime. No real CAS (CAMS/KFintech "Consolidated Account Statement") document exists in the corpus, and the existing mf-cas-template.test.ts file already documents this gap ("the user's corpus has no CAMS / KFintech CAS PDFs to fixture against yet") — so per the task's explicit instruction not to fabricate data, mf-cas was left as an honestly-commented no-op rather than guessing at label wording never verified against a real document.
Impact
- pillar-portfolio — Portfolio Review's debt-MF STCG/LTCG-indexed/LTCG-flat/LTCG-slab tax buckets (
portfolio-review-engine.ts) now receive real, non-zero data for any user who uploads a Zerodha "Tradewise Exits" export containing a "Non Equity" section, instead of always reading zero. capital_gains/{ay}documents gain realrealised_debt_mf_*_paisevalues wherever a real debt-fund disposal exists in the source statement.- No schema drift introduced against
.context/wiki/entities/*— this is a bug fix against already-canonical tax rules (Finance Act 2023 + Finance Act 2024), not a new product decision about rates or thresholds. mf-cas(CAMS/KFintech CAS) remains unable to produce this split until a real CAS document proves what label/format it would use — flagged, not silently defaulted.
Status
Active.
Sources
~/git/personal/documents/docs/self_ritesh/tax/fy2025-26/stocks/zerodha/fy2025-26-q1-q4-equity.xlsx— real Zerodha Console export, "Tradewise Exits from 2025-04-01 to 2026-03-31" sheet, "Non Equity" section (GOLDBEES + LIQUIDCASE rows with real Entry/Exit dates).~/git/personal/documents/docs/self_ritesh/tax/fy2023-24/stocks/zerodha/tax-pnl-q1-q4.xlsxand~/git/personal/documents/docs/self_ritesh/tax/fy2024-25/stocks/zerodha/zerodha-profit-loss.xlsx— real "Taxpnl Statement for Mutual Funds" sheets confirming the industry convention of a 3-way debt bucket split ("Short Term profit Debt" / "Long Term profit Debt" / "Debt - Purchases post 2023-04-01").apps/functions/src/__tests__/mf-cas-template.test.ts— existing code comment confirming no real CAS document exists in the corpus.packages/parser/src/broker-cg/debt-cg.ts,packages/parser/src/broker-cg/parser.ts,apps/functions/src/triggers/firestore/ledger-mappers/broker-cg.ts,apps/functions/src/triggers/firestore/ledger-mappers/mf-cas.ts.
Every project of mine is written down like this.
Read the résumé