Skip to content

Commit b44bc0a

Browse files
cleanup: tweak compaction prompt (#35220)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
1 parent 436cd39 commit b44bc0a

4 files changed

Lines changed: 39 additions & 63 deletions

File tree

packages/core/src/session/compaction.ts

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,27 @@ const TOOL_OUTPUT_MAX_CHARS = 2_000
1515
const SUMMARY_OUTPUT_TOKENS = 4_096
1616
const SUMMARY_TEMPLATE = `Output exactly the Markdown structure shown inside <template> and keep the section order unchanged. Do not include the <template> tags in your response.
1717
<template>
18-
## Goal
19-
- [single-sentence task summary]
18+
## Objective
19+
- [one or two brief sentences describing what the user is trying to accomplish]
2020
21-
## Constraints & Preferences
22-
- [user constraints, preferences, specs, or "(none)"]
21+
## Important Details
22+
- [constraints/preferences, decisions and why, important facts/assumptions, exact context needed to continue, or "(none)"]
2323
24-
## Progress
25-
### Done
26-
- [completed work or "(none)"]
24+
## Work State
25+
- Completed: [finished work, verified facts, or changes made; otherwise "(none)"]
26+
- Active: [current work, partial changes, or investigation state; otherwise "(none)"]
27+
- Blocked: [blockers, failing commands, or unknowns; otherwise "(none)"]
2728
28-
### In Progress
29-
- [current work or "(none)"]
30-
31-
### Blocked
32-
- [blockers or "(none)"]
33-
34-
## Key Decisions
35-
- [decision and why, or "(none)"]
36-
37-
## Next Steps
38-
- [ordered next actions or "(none)"]
39-
40-
## Critical Context
41-
- [important technical facts, errors, open questions, or "(none)"]
42-
43-
## Relevant Files
44-
- [file or directory path: why it matters, or "(none)"]
29+
## Next Move
30+
1. [immediate concrete action, or "(none)"]
31+
2. [next action if known, or "(none)"]
4532
</template>
4633
4734
Rules:
4835
- Keep every section, even when empty.
4936
- Use terse bullets, not prose paragraphs.
50-
- Preserve exact file paths, commands, error strings, and identifiers when known.
37+
- Preserve exact file paths, symbols, commands, error strings, URLs, and identifiers when known.
38+
- Put relevant files and symbols inside the section where they matter; do not add extra sections.
5139
- Do not mention the summary process or that context was compacted.`
5240

5341
type Entry = {

packages/core/test/session-runner.test.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ describe("SessionRunnerLLM", () => {
10971097
currentModel = compactModel
10981098
requests.length = 0
10991099
responses = [
1100-
fragmentFixture("text", "text-summary", ["## Goal\n- Preserve the task"]).completeEvents,
1100+
fragmentFixture("text", "text-summary", ["## Objective\n- Preserve the task"]).completeEvents,
11011101
fragmentFixture("text", "text-final", ["Continued"]).completeEvents,
11021102
]
11031103
yield* session.prompt({
@@ -1108,22 +1108,22 @@ describe("SessionRunnerLLM", () => {
11081108
yield* session.resume(sessionID)
11091109

11101110
expect(requests).toHaveLength(2)
1111-
expect(userTexts(requests[0])[0]).toContain("## Goal")
1111+
expect(userTexts(requests[0])[0]).toContain("## Objective")
11121112
expect(userTexts(requests[1])).toHaveLength(1)
1113-
expect(userTexts(requests[1])[0]).toContain("<summary>\n## Goal\n- Preserve the task\n</summary>")
1113+
expect(userTexts(requests[1])[0]).toContain("<summary>\n## Objective\n- Preserve the task\n</summary>")
11141114
expect(userTexts(requests[1])[0]).toContain(`[User]: ${"Recent exact request ".repeat(180)}`)
11151115

11161116
const context = yield* (yield* SessionStore.Service).context(sessionID)
11171117
expect(context.map((message) => message.type)).toEqual(["compaction", "assistant"])
11181118
expect(context[0]).toMatchObject({
11191119
type: "compaction",
1120-
summary: "## Goal\n- Preserve the task",
1120+
summary: "## Objective\n- Preserve the task",
11211121
})
11221122

11231123
requests.length = 0
11241124
executions.length = 0
11251125
responses = [
1126-
fragmentFixture("text", "text-summary-2", ["## Goal\n- Preserve the updated task"]).completeEvents,
1126+
fragmentFixture("text", "text-summary-2", ["## Objective\n- Preserve the updated task"]).completeEvents,
11271127
fragmentFixture("text", "text-final-2", ["Continued again"]).completeEvents,
11281128
]
11291129
yield* session.prompt({
@@ -1135,12 +1135,12 @@ describe("SessionRunnerLLM", () => {
11351135

11361136
expect(requests).toHaveLength(2)
11371137
expect(userTexts(requests[0])[0]).toContain(
1138-
"<previous-summary>\n## Goal\n- Preserve the task\n</previous-summary>",
1138+
"<previous-summary>\n## Objective\n- Preserve the task\n</previous-summary>",
11391139
)
11401140
expect(userTexts(requests[0])[0]).toContain("Recent exact request")
11411141
expect((yield* (yield* SessionStore.Service).context(sessionID))[0]).toMatchObject({
11421142
type: "compaction",
1143-
summary: "## Goal\n- Preserve the updated task",
1143+
summary: "## Objective\n- Preserve the updated task",
11441144
})
11451145
}),
11461146
)
@@ -1153,17 +1153,17 @@ describe("SessionRunnerLLM", () => {
11531153
LLMEvent.stepStart({ index: 0 }),
11541154
LLMEvent.providerError({ message: "prompt too long", classification: "context-overflow" }),
11551155
],
1156-
fragmentFixture("text", "text-summary", ["## Goal\n- Recover overflow"]).completeEvents,
1156+
fragmentFixture("text", "text-summary", ["## Objective\n- Recover overflow"]).completeEvents,
11571157
fragmentFixture("text", "text-final", ["Recovered"]).completeEvents,
11581158
]
11591159
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
11601160
yield* session.resume(sessionID)
11611161

11621162
expect(requests).toHaveLength(3)
1163-
expect(userTexts(requests[1])[0]).toContain("## Goal")
1164-
expect(userTexts(requests[2])[0]).toContain("<summary>\n## Goal\n- Recover overflow\n</summary>")
1163+
expect(userTexts(requests[1])[0]).toContain("## Objective")
1164+
expect(userTexts(requests[2])[0]).toContain("<summary>\n## Objective\n- Recover overflow\n</summary>")
11651165
expect(yield* session.context(sessionID)).toMatchObject([
1166-
{ type: "compaction", summary: "## Goal\n- Recover overflow" },
1166+
{ type: "compaction", summary: "## Objective\n- Recover overflow" },
11671167
{ type: "assistant", finish: "stop" },
11681168
])
11691169
yield* replaySessionProjection(sessionID)
@@ -1183,7 +1183,7 @@ describe("SessionRunnerLLM", () => {
11831183
]
11841184
responses = [
11851185
overflow(),
1186-
fragmentFixture("text", "text-summary", ["## Goal\n- Recover once"]).completeEvents,
1186+
fragmentFixture("text", "text-summary", ["## Objective\n- Recover once"]).completeEvents,
11871187
overflow(),
11881188
]
11891189
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
@@ -1211,15 +1211,15 @@ describe("SessionRunnerLLM", () => {
12111211
}),
12121212
)
12131213
responses = [
1214-
fragmentFixture("text", "text-summary", ["## Goal\n- Recover raw overflow"]).completeEvents,
1214+
fragmentFixture("text", "text-summary", ["## Objective\n- Recover raw overflow"]).completeEvents,
12151215
fragmentFixture("text", "text-final", ["Recovered"]).completeEvents,
12161216
]
12171217
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false })
12181218
yield* session.resume(sessionID)
12191219

12201220
expect(requests).toHaveLength(3)
12211221
expect(yield* session.context(sessionID)).toMatchObject([
1222-
{ type: "compaction", summary: "## Goal\n- Recover raw overflow" },
1222+
{ type: "compaction", summary: "## Objective\n- Recover raw overflow" },
12231223
{ type: "assistant", finish: "stop" },
12241224
])
12251225
}),
@@ -1250,7 +1250,7 @@ describe("SessionRunnerLLM", () => {
12501250
const session = yield* setupOverflowRecovery
12511251
responses = [
12521252
[LLMEvent.providerError({ message: "prompt too long", classification: "context-overflow" })],
1253-
fragmentFixture("text", "text-summary", ["## Goal\n- Interrupted"]).completeEvents,
1253+
fragmentFixture("text", "text-summary", ["## Objective\n- Interrupted"]).completeEvents,
12541254
]
12551255
const firstGate = yield* Deferred.make<void>()
12561256
const summaryGate = yield* Deferred.make<void>()

packages/opencode/test/server/httpapi-exercise/index.ts

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,33 +1556,21 @@ const scenarios: Scenario[] = [
15561556
const session = yield* ctx.session({ title: "Summarize session" })
15571557
yield* ctx.message(session.id, { text: "summarize this work" })
15581558
const summary = [
1559-
"## Goal",
1559+
"## Objective",
15601560
"- Exercise session summarize.",
15611561
"",
1562-
"## Constraints & Preferences",
1562+
"## Important Details",
15631563
"- Use fake LLM.",
1564-
"",
1565-
"## Progress",
1566-
"### Done",
1567-
"- Summary generated.",
1568-
"",
1569-
"### In Progress",
1570-
"- (none)",
1571-
"",
1572-
"### Blocked",
1573-
"- (none)",
1574-
"",
1575-
"## Key Decisions",
15761564
"- Keep route local.",
1565+
"- Test fixture: test/server/httpapi-exercise/index.ts.",
15771566
"",
1578-
"## Next Steps",
1579-
"- (none)",
1580-
"",
1581-
"## Critical Context",
1582-
"- Test fixture.",
1567+
"## Work State",
1568+
"- Completed: Summary generated.",
1569+
"- Active: (none)",
1570+
"- Blocked: (none)",
15831571
"",
1584-
"## Relevant Files",
1585-
"- test/server/httpapi-exercise/index.ts: scenario",
1572+
"## Next Move",
1573+
"1. (none)",
15861574
].join("\n")
15871575
yield* ctx.llmText(summary)
15881576
yield* ctx.llmText(summary)

packages/opencode/test/session/compaction.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,8 +1430,8 @@ describe("session.compaction.process", () => {
14301430
expect(captured).toContain("<previous-summary>")
14311431
expect(captured).toContain("summary one")
14321432
expect(captured.match(/summary one/g)?.length).toBe(1)
1433-
expect(captured).toContain("## Constraints & Preferences")
1434-
expect(captured).toContain("## Progress")
1433+
expect(captured).toContain("## Important Details")
1434+
expect(captured).toContain("## Work State")
14351435
}).pipe(withCompaction({ llm: stub.llmLayer }))
14361436
},
14371437
{ git: true },

0 commit comments

Comments
 (0)