| 1 | from __future__ import annotations |
| 2 | |
| 3 | from pathlib import Path |
| 4 | |
| 5 | from scripts.assemble_historical_context import ( |
| 6 | DEFAULT_PROMPT_BUDGET_FRACTION, |
| 7 | assemble_historical_context, |
| 8 | build_historical_context, |
| 9 | compress_to_budget, |
| 10 | estimate_tokens, |
| 11 | ) |
| 12 | |
| 13 | |
| 14 | def test_assemble_historical_context_reads_expected_sources(tmp_path: Path) -> None: |
| 15 | content_root = tmp_path / "content" |
| 16 | (content_root / "rolling").mkdir(parents=True) |
| 17 | (content_root / "monthly" / "2026").mkdir(parents=True) |
| 18 | (content_root / "yearly").mkdir(parents=True) |
| 19 | analyzed_dir = tmp_path / "analyzed" |
| 20 | analyzed_dir.mkdir() |
| 21 | |
| 22 | (content_root / "rolling" / "last-month.md").write_text( |
| 23 | "## Active Trends\n\n- Skills keep specializing.\n\n## Noise Patterns\n\n- Spam persists.\n", |
| 24 | encoding="utf-8", |
| 25 | ) |
| 26 | (content_root / "monthly" / "2026" / "06.md").write_text( |
| 27 | "---\nsummary: month\n---\n" |
| 28 | "## Month Overview\n\nJune overview.\n\n" |
| 29 | "## Trends Observed\n\nJune trends.\n\n" |
| 30 | "## Key Takeaways\n\nJune takeaways.\n", |
| 31 | encoding="utf-8", |
| 32 | ) |
| 33 | (content_root / "yearly" / "2026.md").write_text( |
| 34 | "---\nformat: narrative\n---\n" |
| 35 | "## Narrative\n\nYear review.\n\n" |
| 36 | "## Arc\n\n- agent-skills: infrastructure > economy\n", |
| 37 | encoding="utf-8", |
| 38 | ) |
| 39 | previous_summary = analyzed_dir / "2026-W24-summary.md" |
| 40 | previous_summary.write_text( |
| 41 | "---\nsummary: Prior thesis.\n---\n" |
| 42 | "## Signal & Noise\n\nSignal notes.\n\n" |
| 43 | "## Blind Spots\n\nBlind-spot notes.\n\n" |
| 44 | "## The Week Ahead\n\nWatch-list notes.\n", |
| 45 | encoding="utf-8", |
| 46 | ) |
| 47 | |
| 48 | result = assemble_historical_context( |
| 49 | current_datetime="2026-06-12T17:13:50+00:00", |
| 50 | previous_summary_path=previous_summary, |
| 51 | content_root=content_root, |
| 52 | max_words=1500, |
| 53 | prompt_token_budget=90_000, |
| 54 | ) |
| 55 | |
| 56 | assert "### Rolling Last 4 Weeks" in result |
| 57 | assert "### Previous Week Takeaways" in result |
| 58 | assert "Prior weekly thesis: Prior thesis." in result |
| 59 | assert "### Month In Progress" in result |
| 60 | assert "### Yearly Narrative" in result |
| 61 | |
| 62 | |
| 63 | def test_assemble_historical_context_yearly_falls_back_to_legacy_sections(tmp_path: Path) -> None: |
| 64 | content_root = tmp_path / "content" |
| 65 | (content_root / "yearly").mkdir(parents=True) |
| 66 | (content_root / "yearly" / "2026.md").write_text( |
| 67 | "## Year in Review\n\nLegacy review.\n\n" |
| 68 | "## Biggest Trends\n\nLegacy trends.\n\n" |
| 69 | "## Predictions Review\n\nLegacy predictions.\n", |
| 70 | encoding="utf-8", |
| 71 | ) |
| 72 | |
| 73 | result = assemble_historical_context( |
| 74 | current_datetime="2026-06-12T17:13:50+00:00", |
| 75 | previous_summary_path=None, |
| 76 | content_root=content_root, |
| 77 | max_words=1500, |
| 78 | prompt_token_budget=90_000, |
| 79 | ) |
| 80 | |
| 81 | assert "Legacy review." in result |
| 82 | assert "Legacy predictions." in result |
| 83 | |
| 84 | |
| 85 | def test_build_historical_context_respects_prompt_fraction_cap(tmp_path: Path) -> None: |
| 86 | content_root = tmp_path / "content" |
| 87 | (content_root / "rolling").mkdir(parents=True) |
| 88 | (content_root / "rolling" / "last-month.md").write_text( |
| 89 | " ".join(["rolling-context"] * 800), |
| 90 | encoding="utf-8", |
| 91 | ) |
| 92 | |
| 93 | result = build_historical_context( |
| 94 | current_datetime="2026-06-12T17:13:50+00:00", |
| 95 | previous_summary_path=None, |
| 96 | content_root=content_root, |
| 97 | max_words=1500, |
| 98 | prompt_token_budget=200, |
| 99 | ) |
| 100 | |
| 101 | assert result.token_estimate <= int(200 * DEFAULT_PROMPT_BUDGET_FRACTION) |
| 102 | assert estimate_tokens(result.markdown) == result.token_estimate |
| 103 | |
| 104 | |
| 105 | def test_compress_to_budget_preserves_line_structure() -> None: |
| 106 | text = "## Heading\n\nFirst bullet point here\nSecond bullet point\n\nThird paragraph with many words" |
| 107 | result = compress_to_budget(text, 8) |
| 108 | assert "\n" in result |