Skip to content

Commit 1281801

Browse files
refactor(prompt): consolidate template context model
1 parent 04449e4 commit 1281801

23 files changed

Lines changed: 2217 additions & 641 deletions

docs/plans/2026-04-04-template-context-consolidation-design.md

Lines changed: 567 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
# Prompt Template Context Consolidation Implementation Plan
2+
3+
> **For agentic workers:** REQUIRED: Use `/skill:orchestrator-implements` (in-session, orchestrator implements), `/skill:subagent-driven-development` (in-session, subagents implement), or `/skill:executing-plans` (parallel session) to implement this plan. Steps use checkbox syntax for tracking.
4+
5+
**Goal:** Consolidate `internal/prompt` template data into a broader prompt-domain context model without changing prompt behavior, so future customizable templates are not blocked by today’s narrow `...View` structs.
6+
7+
**Architecture:** Keep git/config/storage lookups in `prompt.go`, normalize them into one universal `TemplateContext` root with prompt-family branches, and make templates plus fitting logic operate on that context and its receiver methods. Migrate incrementally through adapters so behavior stays locked to existing regression tests while the old view structs are removed.
8+
9+
**Tech Stack:** Go, `text/template`, embedded template files, testify, existing prompt regression tests in `internal/prompt`.
10+
11+
---
12+
13+
### Task 1: Introduce the consolidated prompt template context model
14+
15+
**TDD scenario:** Modifying tested code — run existing tests first
16+
17+
**Files:**
18+
- Modify: `internal/prompt/prompt.go`
19+
- Modify: `internal/prompt/prompt_body_templates.go`
20+
- Create: `internal/prompt/template_context.go`
21+
- Test: `internal/prompt/prompt_body_templates_test.go`
22+
- Test: `internal/prompt/prompt_test.go`
23+
24+
- [ ] **Step 1: Run the current prompt package tests as baseline**
25+
26+
Run: `go test ./internal/prompt -count=1`
27+
Expected: PASS
28+
29+
- [ ] **Step 2: Add the consolidated context types and clone/trim receiver methods**
30+
31+
```go
32+
type TemplateContext struct {
33+
Meta PromptMeta
34+
Review *ReviewTemplateContext
35+
Address *AddressTemplateContext
36+
System *SystemTemplateContext
37+
}
38+
39+
type ReviewTemplateContext struct {
40+
Kind ReviewKind
41+
Optional ReviewOptionalContext
42+
Subject SubjectContext
43+
Diff DiffContext
44+
Fallback FallbackContext
45+
}
46+
```
47+
48+
Include receiver helpers for:
49+
- cloning review/optional/subject context
50+
- optional trim order: previous attempts → previous reviews → additional context → project guidelines
51+
- single-message/author/subject trimming
52+
- range subject blanking and trailing entry dropping
53+
54+
- [ ] **Step 3: Rename the existing storage-backed `ReviewContext` to avoid the template-context collision**
55+
56+
```go
57+
type HistoricalReviewContext struct {
58+
SHA string
59+
Review *storage.Review
60+
Responses []storage.Response
61+
}
62+
```
63+
64+
Update helper signatures that currently take or return the old `ReviewContext` history type.
65+
66+
- [ ] **Step 4: Add focused unit coverage for the new receiver methods and naming bridge**
67+
68+
Add tests that directly assert:
69+
- optional trim order
70+
- clone isolation
71+
- range subject blanking/drop order
72+
- historical review helpers still preserve previous-review ordering
73+
74+
Run: `go test ./internal/prompt -run 'Test(TemplateContext|ReviewOptionalContext|HistoricalReviewContext|SelectRichestRangePromptView)' -count=1`
75+
Expected: PASS
76+
77+
- [ ] **Step 5: Commit Task 1**
78+
79+
```bash
80+
git add internal/prompt/template_context.go internal/prompt/prompt.go internal/prompt/prompt_body_templates.go internal/prompt/prompt_body_templates_test.go internal/prompt/prompt_test.go
81+
git commit -m "refactor(prompt): add consolidated template context model"
82+
```
83+
84+
### Task 2: Move rendering and templates onto the universal `TemplateContext`
85+
86+
**TDD scenario:** Modifying tested code — run existing tests first
87+
88+
**Files:**
89+
- Modify: `internal/prompt/prompt_body_templates.go`
90+
- Modify: `internal/prompt/templates/prompt_sections.md.gotmpl`
91+
- Modify: `internal/prompt/templates/assembled_single.md.gotmpl`
92+
- Modify: `internal/prompt/templates/assembled_range.md.gotmpl`
93+
- Modify: `internal/prompt/templates/assembled_dirty.md.gotmpl`
94+
- Modify: `internal/prompt/templates/assembled_address.md.gotmpl`
95+
- Modify: `internal/prompt/templates.go`
96+
- Test: `internal/prompt/prompt_body_templates_test.go`
97+
- Test: `internal/prompt/templates_test.go`
98+
99+
- [ ] **Step 1: Add rendering tests that exercise the new nested template field paths**
100+
101+
Cover at least:
102+
- review templates render through `.Review.Optional`, `.Review.Subject`, `.Review.Diff`, `.Review.Fallback`
103+
- address templates render through `.Address.*`
104+
- system templates render through `.System.*`
105+
106+
Run: `go test ./internal/prompt -run 'TestRender(SystemPrompt|SinglePrompt|RangePrompt|DirtyPrompt|AddressPrompt)' -count=1`
107+
Expected: FAIL where templates still expect the old root view shapes
108+
109+
- [ ] **Step 2: Update render helpers to accept the universal root context**
110+
111+
```go
112+
func renderReviewPrompt(name string, ctx TemplateContext) (string, error)
113+
func renderAddressPrompt(ctx TemplateContext) (string, error)
114+
func renderSystemPrompt(name string, ctx TemplateContext) (string, error)
115+
```
116+
117+
Keep wrappers if they improve readability, but all template execution should take `TemplateContext`.
118+
119+
- [ ] **Step 3: Rewrite built-in templates to use the new shared root contract**
120+
121+
Examples:
122+
123+
```gotmpl
124+
{{template "optional_sections" .Review.Optional}}
125+
{{template "current_commit" .Review.Subject.Single}}
126+
{{template "diff_block" .Review}}
127+
```
128+
129+
and:
130+
131+
```gotmpl
132+
{{template "address_attempts" .Address}}
133+
{{template "address_findings" .Address}}
134+
```
135+
136+
- [ ] **Step 4: Preserve the explicit fallback contract**
137+
138+
Update fallback partials so they render from structured fallback fields under `.Review.Fallback`, not duplicate ad hoc strings stored on multiple structs.
139+
140+
- [ ] **Step 5: Run rendering/system-template regression coverage**
141+
142+
Run: `go test ./internal/prompt -run 'TestRender|TestRenderSystemPrompt_AllEmbeddedAgentSpecificTemplates' -count=1`
143+
Expected: PASS
144+
145+
- [ ] **Step 6: Commit Task 2**
146+
147+
```bash
148+
git add internal/prompt/prompt_body_templates.go internal/prompt/templates/prompt_sections.md.gotmpl internal/prompt/templates/assembled_single.md.gotmpl internal/prompt/templates/assembled_range.md.gotmpl internal/prompt/templates/assembled_dirty.md.gotmpl internal/prompt/templates/assembled_address.md.gotmpl internal/prompt/templates.go internal/prompt/prompt_body_templates_test.go internal/prompt/templates_test.go
149+
git commit -m "refactor(prompt): route templates through unified context"
150+
```
151+
152+
### Task 3: Migrate builders and fitters to mutate the consolidated context
153+
154+
**TDD scenario:** Modifying tested code — run existing tests first
155+
156+
**Files:**
157+
- Modify: `internal/prompt/prompt.go`
158+
- Modify: `internal/prompt/prompt_body_templates.go`
159+
- Test: `internal/prompt/prompt_test.go`
160+
- Test: `internal/prompt/prompt_body_templates_test.go`
161+
162+
- [ ] **Step 1: Add/refresh builder-level regressions around preserved behavior**
163+
164+
Ensure coverage still explicitly checks:
165+
- single/range guidelines come from `LoadGuidelines`
166+
- dirty/address guidelines use working-tree config
167+
- address prompts still include the full original diff without current excludes
168+
- dirty truncated fallback and range fallback selection behavior remain unchanged
169+
170+
Run: `go test ./internal/prompt -run 'Test(Build|LoadGuidelines|SelectRichestRangePromptView|FitRangePrompt|BuildAddressPrompt)' -count=1`
171+
Expected: FAIL anywhere the new context migration breaks preserved behavior
172+
173+
- [ ] **Step 2: Replace old view assembly in builder code with context constructors**
174+
175+
Introduce helpers that build a `TemplateContext` from already loaded data, for example:
176+
177+
```go
178+
func buildSingleTemplateContext(...) TemplateContext
179+
func buildRangeTemplateContext(...) TemplateContext
180+
func buildDirtyTemplateContext(...) TemplateContext
181+
func buildAddressTemplateContext(...) TemplateContext
182+
func buildSystemTemplateContext(...) TemplateContext
183+
```
184+
185+
These helpers must receive already-loaded git/config/storage data and must not perform I/O themselves.
186+
187+
- [ ] **Step 3: Move fitting mutations onto context receiver methods**
188+
189+
Keep orchestration in `prompt.go`, but drive mutations through methods like:
190+
- `ctx.Review.Optional.TrimNext()`
191+
- `ctx.Review.Subject.TrimSingleMessage()`
192+
- `ctx.Review.Subject.BlankNextRangeSubject()`
193+
- `ctx.Review.Subject.DropLastRangeEntry()`
194+
195+
- [ ] **Step 4: Re-run the full prompt package suite**
196+
197+
Run: `go test ./internal/prompt -count=1`
198+
Expected: PASS
199+
200+
- [ ] **Step 5: Commit Task 3**
201+
202+
```bash
203+
git add internal/prompt/prompt.go internal/prompt/prompt_body_templates.go internal/prompt/prompt_test.go internal/prompt/prompt_body_templates_test.go
204+
git commit -m "refactor(prompt): fit prompts from consolidated context"
205+
```
206+
207+
### Task 4: Remove obsolete narrow views and run full verification
208+
209+
**TDD scenario:** Modifying tested code — run existing tests first
210+
211+
**Files:**
212+
- Modify: `internal/prompt/prompt_body_templates.go`
213+
- Modify: `internal/prompt/prompt.go`
214+
- Modify: `internal/prompt/templates_test.go`
215+
- Modify: `internal/prompt/prompt_body_templates_test.go`
216+
- Modify: `internal/prompt/prompt_test.go`
217+
218+
- [ ] **Step 1: Delete the obsolete narrow template view types and dead adapters**
219+
220+
Remove the old prompt-specific wrappers once all callers/templates use `TemplateContext`:
221+
- `singlePromptView`
222+
- `rangePromptView`
223+
- `dirtyPromptView`
224+
- `addressPromptView`
225+
- `systemPromptView`
226+
- `optionalSectionsView`
227+
- `diffSectionView`
228+
- fallback-specific one-off view structs no longer needed
229+
230+
- [ ] **Step 2: Remove any render helpers that only existed for the old shape**
231+
232+
Keep only the helpers needed by the consolidated context contract and current tests.
233+
234+
- [ ] **Step 3: Run repo verification**
235+
236+
Run:
237+
- `go fmt ./...`
238+
- `go vet ./...`
239+
- `go test ./...`
240+
241+
Expected: PASS
242+
243+
- [ ] **Step 4: Commit Task 4**
244+
245+
```bash
246+
git add internal/prompt/prompt_body_templates.go internal/prompt/prompt.go internal/prompt/templates_test.go internal/prompt/prompt_body_templates_test.go internal/prompt/prompt_test.go
247+
git commit -m "refactor(prompt): remove narrow template view wrappers"
248+
```
249+
250+
### Task 5: Final review and landing prep
251+
252+
**TDD scenario:** Trivial change — use judgment
253+
254+
**Files:**
255+
- Modify: `docs/plans/2026-04-06-template-context-consolidation.md` (only if implementation notes are required)
256+
257+
- [ ] **Step 1: Review the final diff for accidental behavior changes**
258+
259+
Run: `git diff origin/main...HEAD -- internal/prompt`
260+
Expected: only the intended context consolidation and test/template updates
261+
262+
- [ ] **Step 2: Request a code review if the subagent harness cooperates; otherwise note the timeout block in the handoff summary**
263+
264+
Run a reviewer or capture the blocker explicitly.
265+
266+
- [ ] **Step 3: Commit any final cleanups**
267+
268+
```bash
269+
git add -A
270+
git commit -m "chore(prompt): finalize template context consolidation" || true
271+
```

0 commit comments

Comments
 (0)