feat: add us-cpa review workflow
This commit is contained in:
90
skills/us-cpa/tests/test_review.py
Normal file
90
skills/us-cpa/tests/test_review.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
|
||||
from reportlab.pdfgen import canvas
|
||||
|
||||
from us_cpa.cases import CaseManager
|
||||
from us_cpa.prepare import PrepareEngine
|
||||
from us_cpa.review import ReviewEngine, render_review_memo, render_review_summary
|
||||
from us_cpa.sources import TaxYearCorpus, bootstrap_irs_catalog
|
||||
|
||||
|
||||
class ReviewEngineTests(unittest.TestCase):
|
||||
def build_prepared_case(self, temp_dir: str) -> tuple[Path, TaxYearCorpus]:
|
||||
case_dir = Path(temp_dir) / "2025-jane-doe"
|
||||
manager = CaseManager(case_dir)
|
||||
manager.create_case(case_label="Jane Doe", tax_year=2025)
|
||||
manager.intake(
|
||||
tax_year=2025,
|
||||
user_facts={
|
||||
"taxpayer.fullName": "Jane Doe",
|
||||
"filingStatus": "single",
|
||||
"wages": 50000,
|
||||
"taxableInterest": 100,
|
||||
"federalWithholding": 6000,
|
||||
},
|
||||
document_paths=[],
|
||||
)
|
||||
corpus = TaxYearCorpus(cache_root=Path(temp_dir) / "cache")
|
||||
|
||||
def fake_fetch(url: str) -> bytes:
|
||||
buffer = BytesIO()
|
||||
pdf = canvas.Canvas(buffer)
|
||||
pdf.drawString(72, 720, f"Template for {url}")
|
||||
pdf.save()
|
||||
return buffer.getvalue()
|
||||
|
||||
corpus.download_catalog(2025, bootstrap_irs_catalog(2025), fetcher=fake_fetch)
|
||||
PrepareEngine(corpus=corpus).prepare_case(case_dir)
|
||||
return case_dir, corpus
|
||||
|
||||
def test_review_detects_mismatched_return_and_missing_artifacts(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
case_dir, corpus = self.build_prepared_case(temp_dir)
|
||||
normalized_path = case_dir / "return" / "normalized-return.json"
|
||||
normalized = json.loads(normalized_path.read_text())
|
||||
normalized["totals"]["adjustedGrossIncome"] = 99999.0
|
||||
normalized_path.write_text(json.dumps(normalized, indent=2))
|
||||
|
||||
artifacts_path = case_dir / "output" / "artifacts.json"
|
||||
artifacts = json.loads(artifacts_path.read_text())
|
||||
artifacts["artifacts"] = []
|
||||
artifacts["artifactCount"] = 0
|
||||
artifacts_path.write_text(json.dumps(artifacts, indent=2))
|
||||
|
||||
review = ReviewEngine(corpus=corpus).review_case(case_dir)
|
||||
|
||||
self.assertEqual(review["status"], "reviewed")
|
||||
self.assertEqual(review["findings"][0]["severity"], "high")
|
||||
self.assertIn("adjusted gross income", review["findings"][0]["title"].lower())
|
||||
self.assertTrue(any("missing rendered artifact" in item["title"].lower() for item in review["findings"]))
|
||||
|
||||
def test_review_renderers_produce_summary_and_memo(self) -> None:
|
||||
review = {
|
||||
"status": "reviewed",
|
||||
"findings": [
|
||||
{
|
||||
"severity": "high",
|
||||
"title": "Adjusted gross income mismatch",
|
||||
"explanation": "Stored AGI does not match recomputed AGI.",
|
||||
"suggestedAction": "Update Form 1040 line 11.",
|
||||
"authorities": [{"title": "Instructions for Form 1040 and Schedules 1-3"}],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
summary = render_review_summary(review)
|
||||
memo = render_review_memo(review)
|
||||
|
||||
self.assertIn("Adjusted gross income mismatch", summary)
|
||||
self.assertIn("# Review Memo", memo)
|
||||
self.assertIn("Suggested correction", memo)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user