@paro.io/expert-shared-components 1.14.70 → 1.14.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/lib/components/TaxAxis/TaxAxisApi.d.ts +0 -8
  2. package/lib/components/TaxAxis/TaxAxisShell.js +13 -29
  3. package/lib/tax-axis/components/clientReport/ExecutiveSummary.js +10 -6
  4. package/lib/tax-axis/components/clientReport/ImplementationRoadmap.d.ts +2 -1
  5. package/lib/tax-axis/components/clientReport/ImplementationRoadmap.js +11 -8
  6. package/lib/tax-axis/components/clientReport/ImplementationTimelineChart.d.ts +2 -1
  7. package/lib/tax-axis/components/clientReport/ImplementationTimelineChart.js +9 -3
  8. package/lib/tax-axis/components/clientReport/QuarterlyCashChart.d.ts +2 -1
  9. package/lib/tax-axis/components/clientReport/QuarterlyCashChart.js +9 -3
  10. package/lib/tax-axis/components/clientReport/TaxAxisClientReport.js +9 -2
  11. package/lib/tax-axis/components/dashboard/StrategyDetailPanel.js +3 -1
  12. package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +5 -2
  13. package/lib/tax-axis/components/intake/ClientParametersSection.js +14 -4
  14. package/lib/tax-axis/components/intake/IntakeCtaCards.d.ts +2 -8
  15. package/lib/tax-axis/components/intake/IntakeCtaCards.js +7 -70
  16. package/lib/tax-axis/components/intake/TaxAxisIntake.js +1 -1
  17. package/lib/tax-axis/components/intake/intakeSchema.js +1 -1
  18. package/lib/tax-axis/components/preparerWorkpaper/EngagementHeader.js +6 -2
  19. package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.js +3 -3
  20. package/lib/tax-axis/components/processing/TaxAxisProcessing.d.ts +1 -5
  21. package/lib/tax-axis/components/processing/TaxAxisProcessing.js +11 -27
  22. package/lib/tax-axis/components/prospectReport/ProspectNextSteps.js +1 -3
  23. package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.d.ts +1 -7
  24. package/lib/tax-axis/components/prospectReport/ProspectStrategyCard.js +6 -8
  25. package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.d.ts +1 -33
  26. package/lib/tax-axis/components/prospectReport/TaxAxisProspectReport.js +56 -57
  27. package/lib/tax-axis/lib/adapters/useEngineOutput.d.ts +42 -58
  28. package/lib/tax-axis/lib/adapters/useEngineOutput.js +99 -35
  29. package/lib/tax-axis/lib/data/nextSteps.js +13 -13
  30. package/lib/tax-axis/lib/data/sourceDescriptions.js +6 -0
  31. package/lib/tax-axis/lib/documentFieldCatalog.d.ts +10 -5
  32. package/lib/tax-axis/lib/documentFieldCatalog.js +329 -115
  33. package/lib/tax-axis/lib/types/index.d.ts +2 -0
  34. package/package.json +1 -1
  35. package/lib/tax-axis/components/prospectReport/ProspectReportSkeleton.d.ts +0 -2
  36. package/lib/tax-axis/components/prospectReport/ProspectReportSkeleton.js +0 -78
@@ -1,56 +1,120 @@
1
1
  "use strict";
2
+ // useEngineOutput — maps raw engine output + formula pre-computed results
3
+ // into the canonical Strategy[] + ComputedMap consumed by report components.
4
+ //
5
+ // Only strategies validated by the deterministic formula engine are included.
6
+ // This prevents LLM-hallucinated strategies and dollar amounts from reaching
7
+ // the Client Report or Preparer Workpaper.
2
8
  Object.defineProperty(exports, "__esModule", { value: true });
3
9
  exports.useEngineOutput = useEngineOutput;
4
10
  const react_1 = require("react");
5
- function humanize(id) {
6
- return id
7
- .replace(/[_-]/g, " ")
8
- .replace(/\b\w/g, (c) => c.toUpperCase());
11
+ const strategyNarrative_1 = require("../data/strategyNarrative");
12
+ const data_1 = require("../data");
13
+ // ---------------------------------------------------------------------------
14
+ // Helpers
15
+ // ---------------------------------------------------------------------------
16
+ /** Parse "S10" -> 10. Returns null if strategyId doesn't match the SN pattern. */
17
+ function parseStrategyNumber(strategyId) {
18
+ const match = strategyId.match(/^S(\d+)$/);
19
+ return match ? parseInt(match[1], 10) : null;
9
20
  }
10
- function mapSingleStrategy(sa, idx) {
11
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
12
- const ct = (_a = sa.calculation_trace) !== null && _a !== void 0 ? _a : {};
13
- const lo = (_d = (_b = sa.lo) !== null && _b !== void 0 ? _b : (_c = sa.estimatedSavings) === null || _c === void 0 ? void 0 : _c.min) !== null && _d !== void 0 ? _d : 0;
14
- const hi = (_g = (_e = sa.hi) !== null && _e !== void 0 ? _e : (_f = sa.estimatedSavings) === null || _f === void 0 ? void 0 : _f.max) !== null && _g !== void 0 ? _g : 0;
15
- const weightedScore = (_j = (_h = sa.weighted_score) !== null && _h !== void 0 ? _h : sa.score) !== null && _j !== void 0 ? _j : (sa.priority === "HIGH" ? 85 : sa.priority === "MEDIUM" ? 70 : 55);
16
- const timelineBucket = (_k = sa.timeline_bucket) !== null && _k !== void 0 ? _k : (sa.priority === "HIGH" ? "now" : "90d");
21
+ // Static catalog lookups keyed by original strategy rank (1-25).
22
+ const CATEGORY_BY_RANK = new Map();
23
+ const CODE_BY_RANK = new Map();
24
+ for (const s of data_1.STRATEGIES) {
25
+ CATEGORY_BY_RANK.set(s.rank, s.cat);
26
+ CODE_BY_RANK.set(s.rank, s.code);
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Core mapping — engine strategy_analysis entry -> canonical Strategy
30
+ // ---------------------------------------------------------------------------
31
+ function mapAnalysisToStrategy(sa, idx, pc) {
32
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
33
+ const ct = ((_a = sa.calculation_trace) !== null && _a !== void 0 ? _a : {});
34
+ const ci = pc === null || pc === void 0 ? void 0 : pc.confidence_interval;
35
+ // Dollar amounts: prefer preComputed CI, then calculation_trace CI
36
+ const lo = ci ? Math.round(ci.low) : Math.round((_c = (_b = ct.confidence_interval) === null || _b === void 0 ? void 0 : _b.low) !== null && _c !== void 0 ? _c : 0);
37
+ const hi = ci ? Math.round(ci.high) : Math.round((_e = (_d = ct.confidence_interval) === null || _d === void 0 ? void 0 : _d.high) !== null && _e !== void 0 ? _e : 0);
38
+ const strategyNumber = parseStrategyNumber(sa.strategy_id);
39
+ const cat = strategyNumber !== null ? ((_f = CATEGORY_BY_RANK.get(strategyNumber)) !== null && _f !== void 0 ? _f : "income") : "income";
40
+ const staticNarrative = strategyNumber !== null ? strategyNarrative_1.STRATEGY_NARRATIVE[strategyNumber] : undefined;
41
+ // Source documents from calculation_trace
42
+ const sourceDocuments = Array.isArray(ct.source_documents) ? ct.source_documents : undefined;
43
+ const specialistNote = typeof ct.specialist_note === "string" && ct.specialist_note.trim() !== ""
44
+ ? ct.specialist_note
45
+ : ((_g = staticNarrative === null || staticNarrative === void 0 ? void 0 : staticNarrative.whySpecialist) !== null && _g !== void 0 ? _g : undefined);
46
+ const positionStrength = typeof ct.position_strength === "string" ? ct.position_strength : undefined;
47
+ const authority = typeof ct.irs_cite === "string" ? ct.irs_cite : undefined;
48
+ const formsFromTrace = Array.isArray(ct.forms_required)
49
+ ? ct.forms_required.join(", ")
50
+ : undefined;
51
+ // Timeline bucket: derive from priority as a reasonable default
52
+ const priority = (sa.priority_tier || "MEDIUM").toUpperCase();
53
+ const timelineBucket = sa.quick_win ? "now" : priority === "HIGH" ? "now" : priority === "MEDIUM" ? "30d" : "90d";
17
54
  return {
18
55
  rank: idx + 1,
19
- code: (_l = sa.strategy_id) !== null && _l !== void 0 ? _l : `S${idx + 1}`,
20
- name: (_m = sa.strategy_name) !== null && _m !== void 0 ? _m : humanize((_o = sa.strategy_id) !== null && _o !== void 0 ? _o : `Strategy ${idx + 1}`),
21
- cat: "income",
22
- priority: (((_p = sa.priority) !== null && _p !== void 0 ? _p : "MEDIUM").toUpperCase()),
23
- score: Math.round(weightedScore),
56
+ strategyNumber: strategyNumber !== null && strategyNumber !== void 0 ? strategyNumber : undefined,
57
+ code: (_h = (strategyNumber !== null ? CODE_BY_RANK.get(strategyNumber) : undefined)) !== null && _h !== void 0 ? _h : sa.strategy_id,
58
+ name: sa.strategy_name,
59
+ cat,
60
+ priority,
61
+ score: sa.weighted_score != null
62
+ ? Math.min(Math.round((sa.weighted_score / 25) * 100), 100)
63
+ : (priority === "HIGH" ? 85 : priority === "MEDIUM" ? 70 : 55),
24
64
  entities: [],
25
65
  lo,
26
66
  hi,
27
67
  timeline: timelineBucket === "now" ? "Act now" : timelineBucket === "30d" ? "Within 30 days" : "Within 90 days",
28
68
  timelineBucket,
29
- clientBrief: (_q = sa.why_it_applies) !== null && _q !== void 0 ? _q : "Your preparer will review this strategy and include the analysis in your engagement report.",
30
- action: (_r = sa.next_step) !== null && _r !== void 0 ? _r : "Work with your CPA to implement this strategy.",
31
- forms: Array.isArray(ct.forms_required) ? ct.forms_required.join(", ") : undefined,
32
- abstract: sa.why_it_applies,
33
- warning: (_s = sa.risk_disclosure) !== null && _s !== void 0 ? _s : null,
34
- sources: [],
35
- trace: [],
36
- cost: undefined,
37
- sourceDocuments: Array.isArray(ct.source_documents) ? ct.source_documents : undefined,
38
- positionStrength: ct.position_strength,
39
- specialistNote: ct.specialist_note,
40
- authority: ct.irs_cite,
41
- quickWin: (_t = sa.quick_win) !== null && _t !== void 0 ? _t : false,
69
+ abstract: sa.engagement_recommendation || "",
70
+ warning: (_j = sa.risk_disclosure) !== null && _j !== void 0 ? _j : null,
71
+ forms: formsFromTrace,
72
+ authority,
73
+ sourceDocuments,
74
+ specialistNote,
75
+ positionStrength,
76
+ quickWin: sa.quick_win,
42
77
  };
43
78
  }
44
- function useEngineOutput(engineOutput) {
79
+ // ---------------------------------------------------------------------------
80
+ // Hook
81
+ // ---------------------------------------------------------------------------
82
+ function useEngineOutput(engineOutput, preComputed) {
45
83
  return (0, react_1.useMemo)(() => {
46
- const analysis = engineOutput === null || engineOutput === void 0 ? void 0 : engineOutput.strategy_analysis;
47
- if (!Array.isArray(analysis) || analysis.length === 0)
84
+ var _a;
85
+ if (!engineOutput)
86
+ return null;
87
+ const strategyAnalysis = engineOutput.strategy_analysis;
88
+ if (!Array.isArray(strategyAnalysis) || strategyAnalysis.length === 0)
89
+ return null;
90
+ const pcResults = (_a = preComputed === null || preComputed === void 0 ? void 0 : preComputed.results) !== null && _a !== void 0 ? _a : {};
91
+ // Filter: only include strategies where the formula engine returned COMPLETE
92
+ // OR the reconciler tagged _reconciledPreComputed: true.
93
+ const validated = strategyAnalysis.filter((sa) => {
94
+ const pc = pcResults[sa.strategy_id];
95
+ if ((pc === null || pc === void 0 ? void 0 : pc.status) === "COMPLETE")
96
+ return true;
97
+ if (sa._reconciledPreComputed === true)
98
+ return true;
99
+ return false;
100
+ });
101
+ if (validated.length === 0)
48
102
  return null;
49
- const strategies = analysis.map((sa, idx) => mapSingleStrategy(sa, idx));
103
+ // Map to canonical Strategy[]
104
+ const strategies = validated.map((sa, idx) => {
105
+ const pc = pcResults[sa.strategy_id];
106
+ return mapAnalysisToStrategy(sa, idx, pc);
107
+ });
108
+ // Build ComputedMap keyed by rank (1-based index matching strategies array)
50
109
  const computedMap = new Map();
51
110
  for (const s of strategies) {
52
- computedMap.set(s.rank, { lo: s.lo, hi: s.hi });
111
+ computedMap.set(s.rank, {
112
+ lo: s.lo,
113
+ hi: s.hi,
114
+ sources: s.sources,
115
+ trace: s.trace,
116
+ });
53
117
  }
54
118
  return { strategies, computedMap };
55
- }, [engineOutput]);
119
+ }, [engineOutput, preComputed]);
56
120
  }
@@ -16,20 +16,20 @@ exports.NEXT_STEPS = {
16
16
  8: "Provide your property appraisal or purchase records. A cost segregation study will identify reclassifiable assets.",
17
17
  9: "Increase your payroll HSA deduction this pay period. Your preparer will confirm your remaining contribution room.",
18
18
  10: "Start logging business meals with date, attendees, and business purpose. 50% of qualifying meals are deductible.",
19
- 11: "Review your current professional service expenses with your preparer to ensure all are properly categorized.",
20
- 12: "Photograph your dedicated workspace and collect mortgage and utility bills for the year.",
21
- 13: "Your preparer will evaluate your current employee health insurance setup for credit eligibility.",
22
- 14: "Consider bunching two years of charitable contributions into one year for maximum deduction impact.",
23
- 15: "Your preparer will file a PTE election with your state. Deadline varies by state.",
24
- 16: "Your preparer will review your business interest expense for §163(j) optimization.",
25
- 17: "Discuss year-end timing of income and expenses with your preparer before December.",
26
- 18: "Identify qualifying capital gains and potential Opportunity Zone investments with your advisor.",
27
- 19: "Have your commercial property evaluated for energy efficiency certification.",
28
- 20: "Your preparer will review your current accounting method for optimization opportunities.",
29
- 21: "Provide your POS tip reporting data. Your preparer will calculate the deduction.",
30
- 22: "Provide your payroll overtime summary. Your preparer will calculate the OBBBA deduction.",
19
+ 11: "Photograph your dedicated workspace and collect mortgage, insurance, and utility bills for the year. Your preparer will compare actual vs. simplified methods.",
20
+ 12: "Your preparer will draft an accountable plan document and board resolution for tax-free reimbursement of qualifying employee business expenses.",
21
+ 13: "Document fair market rental rates for your home and schedule qualifying business use days. Your preparer will prepare the rental agreement and FMV documentation.",
22
+ 14: "Document bona fide job duties and market-rate wages for family members working in the business. Your preparer will set up proper payroll documentation.",
23
+ 15: "Your preparer will evaluate your state's pass-through entity election and calculate the federal deduction benefit versus your current SALT position.",
24
+ 16: "Your preparer will assess qualifying energy-efficient commercial building improvements and determine applicable deduction or credit tiers.",
25
+ 17: "Your preparer will compare standard mileage rate versus actual expense methods and evaluate heavy SUV §179 eligibility for your business vehicles.",
26
+ 18: "Your preparer will review group-term life insurance, disability, and other employer-provided coverage for tax-efficient structuring under IRC employer benefit rules.",
27
+ 19: "Your preparer will evaluate qualifying real property exchanges and coordinate identification and exchange period deadlines with a qualified intermediary.",
28
+ 20: "Your preparer will verify qualified small business stock eligibility, holding period requirements, and the $10M or 10x-basis exclusion limit for capital gains.",
29
+ 21: "Your preparer will calculate the OBBBA qualified tip income deduction for eligible tipped employees and verify documentation requirements.",
30
+ 22: "Your preparer will evaluate OBBBA overtime pay deduction eligibility and calculate the incremental tax deduction for qualifying overtime wages.",
31
31
  23: "Your preparer will review prior-year R&E amortization for catch-up eligibility.",
32
- 24: "Document your employer-provided childcare facilities or referral services.",
32
+ 24: "Your preparer will evaluate employer-provided childcare facility or referral service expenditures and calculate the 25% qualified expenditure credit.",
33
33
  25: "Your preparer will evaluate Trump Account eligibility and optimal contribution levels.",
34
34
  };
35
35
  exports.INTERACTION_PAIRS = [[1, 4], [1, 7], [2, 3]];
@@ -17,7 +17,10 @@ exports.SOURCE_DESC = {
17
17
  "§223": "Health Savings Account contributions for HDHP-covered taxpayers",
18
18
  "§274": "Business meal deductions, generally limited to 50% of qualifying expenses",
19
19
  "§162": "Ordinary and necessary business expenses",
20
+ "§62": "Accountable plan reimbursements for qualifying employee business expenses under an employer-maintained plan",
20
21
  "§280A": "Home office deduction for the business use of a residence",
22
+ "§280A(g)": "Augusta Rule: exclusion of rental income for personal residence rented 14 days or fewer per year",
23
+ "§73": "Employment of family members; wage deduction and FICA/FUTA savings for qualifying family employees",
21
24
  "§45R": "Small employer health insurance credit",
22
25
  "§170": "Charitable contribution deductions",
23
26
  "OBBBA §70109": "Pass-through entity tax election workaround for the SALT cap",
@@ -26,6 +29,9 @@ exports.SOURCE_DESC = {
26
29
  "§1400Z": "Qualified Opportunity Zone capital gains deferral",
27
30
  "§179D": "Energy efficient commercial buildings deduction",
28
31
  "§446": "Permissible accounting methods and changes",
32
+ "§79, §264": "Group-term life insurance exclusion and employer-owned life insurance tax treatment",
33
+ "§1031": "Like-kind exchange deferral of recognized gain on qualifying real property dispositions",
34
+ "§1202": "Qualified Small Business Stock gain exclusion: up to $10M or 10x adjusted basis for qualifying C-Corp stock held 5+ years",
29
35
  "OBBBA": "OBBBA-introduced deductions and credits (Qualified Tips, Overtime Pay, Trump Accounts)",
30
36
  "§174A": "OBBBA-restored full expensing for domestic research and experimental expenditures",
31
37
  "§45F": "Employer-provided childcare facilities and services credit",
@@ -1,13 +1,18 @@
1
- export interface FieldDef {
2
- label: string;
1
+ export interface CatalogFieldDef {
2
+ label?: string;
3
3
  sourceRef?: string;
4
4
  }
5
5
  export interface CatalogSection {
6
6
  head: string;
7
7
  fields: string[];
8
8
  }
9
- export interface DocumentCatalogEntry {
9
+ export interface CatalogEntry {
10
10
  sections: CatalogSection[];
11
- fields: Record<string, FieldDef>;
11
+ fields: Record<string, CatalogFieldDef>;
12
12
  }
13
- export declare const DOCUMENT_FIELD_CATALOG: Record<string, DocumentCatalogEntry>;
13
+ /**
14
+ * Keyed by documentType string returned by the backend in parsedData.documentType.
15
+ * When DocumentReviewModal receives parsedData, it looks up the documentType here
16
+ * to get section groupings and field labels. Falls back to flat rendering if no entry.
17
+ */
18
+ export declare const DOCUMENT_FIELD_CATALOG: Record<string, CatalogEntry>;