main
md 152 lines 4.66 KB
Rendered Raw
1 # Historical Context Injection for Weekly Analysis (#401)
2
3 ## Goal
4
5 Add a bounded `HISTORICAL CONTEXT` preamble to the weekly analysis prompt so Farnsworth can:
6
7 - maintain continuity across weeks,
8 - recognize multi-week patterns,
9 - revisit open predictions and blind spots,
10 - do all of that without diluting the primacy of the current week's raw JSON.
11
12 ## Architecture
13
14 ### New module
15
16 Add `scripts/assemble_historical_context.py`.
17
18 Responsibilities:
19
20 1. Read historical source artifacts from `content/`.
21 2. Extract the most analysis-relevant slices from each source.
22 3. Compress each slice to a per-source target.
23 4. Enforce a global historical-context budget:
24 - target: ~1500 words,
25 - hard ceiling: never more than 15% of the total prompt-token budget.
26 5. Return one assembled markdown string ready for prompt injection.
27
28 ### Source inputs
29
30 The assembler reads these sources in priority order:
31
32 1. `content/rolling/last-month.md`
33 - rolling 4-week continuity
34 - target: 500 words
35 2. Previous week's summary
36 - derived from the prior analyzed weekly markdown already resolved by `find_previous_summary()`
37 - target: 200 words
38 3. `content/monthly/YYYY/MM.md`
39 - month-in-progress notes
40 - target: 200 words
41 4. `content/yearly/YYYY.md` (optional)
42 - longer narrative arc
43 - target: 500 words
44
45 The module extracts focused sections instead of dumping whole files:
46
47 - previous week: frontmatter `summary` + `Signal & Noise` + `Blind Spots` + `The Week Ahead`
48 - monthly: `Month Overview` + `Trends Observed` + `Key Takeaways`
49 - yearly: `Year in Review` + `Biggest Trends` + `Predictions Review`
50 - rolling: whole rolling report body
51
52 ## Integration point
53
54 Historical context is assembled inside `scripts/analyze_fallback.py` during prompt rendering, before preflight budget evaluation and before any LLM invocation.
55
56 Flow:
57
58 1. Load/sanitize raw weekly JSON.
59 2. Resolve previous summary with `find_previous_summary()`.
60 3. Call `assemble_historical_context(...)`.
61 4. Inject the returned markdown into `{{HISTORICAL_CONTEXT}}`.
62 5. Run existing prompt preflight / compaction logic.
63
64 This keeps the feature inside the current weekly analysis pipeline without changing the workflow contract.
65
66 ## Prompt preamble format
67
68 `prompts/analyze-weekly.md` gains a new preamble block under `## Inputs`:
69
70 ```md
71 ### Historical context
72
73 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.
74
75 <untrusted-content>
76 {{HISTORICAL_CONTEXT}}
77 </untrusted-content>
78 ```
79
80 Important prompt behavior:
81
82 - historical context is explicitly lower-weight than current data,
83 - it is fenced as untrusted content,
84 - it is continuity guidance, not permission to override present-week evidence.
85
86 ## Budget management
87
88 Two limits apply:
89
90 1. **Word target:** ~1500 words total across all historical sections.
91 2. **Prompt-share cap:** historical context may consume at most **15%** of the configured prompt-token budget.
92
93 Implementation detail:
94
95 - each section is first compressed to its nominal word budget,
96 - the assembled result is then iteratively reduced until it fits both:
97 - the word cap,
98 - and the token cap derived from `prompt_token_budget * 0.15`.
99
100 This makes the feature safe for both the default 90k-token preflight and smaller future prompt budgets.
101
102 ## Source priority and compression policy
103
104 Recency wins when over budget.
105
106 Priority retained longest:
107
108 1. rolling last 4 weeks
109 2. previous week takeaways
110 3. current month notes
111 4. yearly narrative
112
113 When over budget:
114
115 1. compress yearly first,
116 2. then monthly,
117 3. then previous week,
118 4. rolling is reduced last.
119
120 If the prompt budget is extremely tight, lower-priority sections can be dropped entirely before the rolling context is removed.
121
122 ## Files changed
123
124 ### Prompt / security
125
126 - `prompts/analyze-weekly.md`
127 - add `{{HISTORICAL_CONTEXT}}` preamble section
128 - `scripts/lint_prompts.py`
129 - classify `{{HISTORICAL_CONTEXT}}` as untrusted
130
131 ### Pipeline
132
133 - `scripts/assemble_historical_context.py`
134 - new bounded historical-context assembler
135 - `scripts/analyze_fallback.py`
136 - call the assembler during prompt construction
137 - expose `--content-root`
138 - include the assembled context in prompt preflight components
139
140 ### Tests
141
142 - `tests/test_assemble_historical_context.py`
143 - `tests/test_analyze_fallback.py`
144
145 ## Draft implementation notes
146
147 This draft intentionally avoids generating new rollups inside the assembler. It assumes:
148
149 - rolling context is produced by `scripts/generate_rollups.py --rolling`,
150 - monthly/yearly artifacts already exist when available.
151
152 If a source is missing, the assembler skips it cleanly; the weekly prompt still renders.