Historical Context Injection for Weekly Analysis (#401)
Goal
Add a bounded HISTORICAL CONTEXT preamble to the weekly analysis prompt so Farnsworth can:
- maintain continuity across weeks,
- recognize multi-week patterns,
- revisit open predictions and blind spots,
- do all of that without diluting the primacy of the current week's raw JSON.
Architecture
New module
Add scripts/assemble_historical_context.py.
Responsibilities:
- Read historical source artifacts from
content/. - Extract the most analysis-relevant slices from each source.
- Compress each slice to a per-source target.
- Enforce a global historical-context budget:
- target: ~1500 words,
- hard ceiling: never more than 15% of the total prompt-token budget.
- Return one assembled markdown string ready for prompt injection.
Source inputs
The assembler reads these sources in priority order:
content/rolling/last-month.md- rolling 4-week continuity
- target: 500 words
- Previous week's summary
- derived from the prior analyzed weekly markdown already resolved by
find_previous_summary() - target: 200 words
- derived from the prior analyzed weekly markdown already resolved by
content/monthly/YYYY/MM.md- month-in-progress notes
- target: 200 words
content/yearly/YYYY.md(optional)- longer narrative arc
- target: 500 words
The module extracts focused sections instead of dumping whole files:
- previous week: frontmatter
summary+Signal & Noise+Blind Spots+The Week Ahead - monthly:
Month Overview+Trends Observed+Key Takeaways - yearly:
Year in Review+Biggest Trends+Predictions Review - rolling: whole rolling report body
Integration point
Historical context is assembled inside scripts/analyze_fallback.py during prompt rendering, before preflight budget evaluation and before any LLM invocation.
Flow:
- Load/sanitize raw weekly JSON.
- Resolve previous summary with
find_previous_summary(). - Call
assemble_historical_context(...). - Inject the returned markdown into
{{HISTORICAL_CONTEXT}}. - Run existing prompt preflight / compaction logic.
This keeps the feature inside the current weekly analysis pipeline without changing the workflow contract.
Prompt preamble format
prompts/analyze-weekly.md gains a new preamble block under ## Inputs:
### Historical context
Treat this as low-priority continuity scaffolding, not as the evidence base for this week's call. It is a bounded digest of recent rollups and prior takeaways. If it conflicts with the current raw JSON, the current raw JSON wins.
<untrusted-content>
{{HISTORICAL_CONTEXT}}
</untrusted-content>
Important prompt behavior:
- historical context is explicitly lower-weight than current data,
- it is fenced as untrusted content,
- it is continuity guidance, not permission to override present-week evidence.
Budget management
Two limits apply:
- Word target: ~1500 words total across all historical sections.
- Prompt-share cap: historical context may consume at most 15% of the configured prompt-token budget.
Implementation detail:
- each section is first compressed to its nominal word budget,
- the assembled result is then iteratively reduced until it fits both:
- the word cap,
- and the token cap derived from
prompt_token_budget * 0.15.
This makes the feature safe for both the default 90k-token preflight and smaller future prompt budgets.
Source priority and compression policy
Recency wins when over budget.
Priority retained longest:
- rolling last 4 weeks
- previous week takeaways
- current month notes
- yearly narrative
When over budget:
- compress yearly first,
- then monthly,
- then previous week,
- rolling is reduced last.
If the prompt budget is extremely tight, lower-priority sections can be dropped entirely before the rolling context is removed.
Files changed
Prompt / security
prompts/analyze-weekly.md- add
{{HISTORICAL_CONTEXT}}preamble section
- add
scripts/lint_prompts.py- classify
{{HISTORICAL_CONTEXT}}as untrusted
- classify
Pipeline
scripts/assemble_historical_context.py- new bounded historical-context assembler
scripts/analyze_fallback.py- call the assembler during prompt construction
- expose
--content-root - include the assembled context in prompt preflight components
Tests
tests/test_assemble_historical_context.pytests/test_analyze_fallback.py
Draft implementation notes
This draft intentionally avoids generating new rollups inside the assembler. It assumes:
- rolling context is produced by
scripts/generate_rollups.py --rolling, - monthly/yearly artifacts already exist when available.
If a source is missing, the assembler skips it cleanly; the weekly prompt still renders.