← opencode report

T12 — Structured compaction template

Template 5-section yêu cầu LLM sinh summary theo cấu trúc cố định khi compact — đảm bảo agent mới biết mục tiêu, rules, codebase facts, việc đã làm, và file liên quan.
Nhóm: B — Context ManagementFile: session/compaction.tsLines: 277–299Status: Stable

Tổng quan Context

Tại sao quan trọng. Khi LLM tóm tắt free-form, nó thường tập trung vào "câu chuyện" của conversation nhưng bỏ sót thông tin kỹ thuật thiết yếu: file paths, function names, error messages, rules người dùng đã đặt ra. Agent mới sau compact sẽ "mất trí nhớ" về codebase — dẫn đến đặt câu hỏi lại, làm lại việc đã làm, vi phạm rules đã thỏa thuận.

opencode giải quyết bằng template 5-section bắt buộc LLM phân loại thông tin vào đúng bucket, không tự do diễn giải:

  • Goal — 1 câu mục tiêu user muốn đạt được
  • Instructions — bullet list rules/constraints user đã đặt ra
  • Discoveries — facts kỹ thuật về codebase (file paths, patterns, symbols)
  • Accomplished — list hành động đã thực hiện (edits, commands, changes)
  • Relevant files — list file với 1-line description mỗi file

Plugin có thể override template bằng plugins.compactionTemplate?.() — cho phép domain-specific summary (ví dụ: thêm section "Test results", "API endpoints").

5 sections = 5 memory types. Mỗi section ánh xạ đến một loại "trí nhớ" khác nhau: Goal = working memory, Instructions = rule memory, Discoveries = semantic memory, Accomplished = episodic memory, Relevant files = spatial memory. Đây là thiết kế cognitive-informed.

Phân tích code chi tiết Anatomy

Template gốc — DEFAULT_COMPACTION_TEMPLATE

Template là một user message prompt yêu cầu LLM sinh summary với 5 markdown headers. Thứ tự sections quan trọng: Goal đứng đầu để model hiểu ngữ cảnh khi đọc các section sau.

session/compaction.ts:277-299 — default template

TS
{`
export const DEFAULT_COMPACTION_TEMPLATE = \`
Your task is to create a detailed summary of our conversation so far.
This summary will be used to restore context after compaction.

Please structure your summary with these EXACT 5 sections:

## Goal
One sentence: what is the user ultimately trying to accomplish?

## Instructions
Bullet list of rules, constraints, or preferences the user has stated.
Include coding style preferences, naming conventions, forbidden approaches.

## Discoveries
Technical facts learned about the codebase:
- File paths and their purpose
- Key functions/classes/symbols and what they do
- Patterns, conventions, or architecture decisions
- Environment details (language versions, dependencies, config)

## Accomplished
Chronological list of actions taken:
- Files created, edited, or deleted (with brief reason)
- Commands run and their outcome
- Decisions made and why

## Relevant files
List of files relevant to the current task:
- \`path/to/file.ts\` — one-line description of relevance

Keep each section focused and factual. Avoid narrative prose.
\`
`}

Plugin override mechanism

Plugin có thể thay thế hoàn toàn template bằng domain-specific prompt. Ví dụ: plugin cho Android development có thể thêm section "Gradle config" và "Device targets".

session/compaction.ts — plugin override

TS
{`
export function getCompactionTemplate(
  plugins: Plugin[]
): string {
  // Plugin override: lấy template từ plugin đầu tiên có implement
  for (const plugin of plugins) {
    const customTemplate = plugin.compactionTemplate?.()
    if (customTemplate) return customTemplate
  }

  return DEFAULT_COMPACTION_TEMPLATE
}

// Trong T8 compact call:
const template  = getCompactionTemplate(session.plugins)
const summaryLLM = await llm.complete({
  messages: [...head, { role: 'user', content: template }],
})
`}

Output validation (optional enhancement)

opencode hiện không validate output của LLM — tin tưởng model tuân theo template. Một số harness implement section detection để fallback nếu output thiếu section.

Enhancement — section validation

TS
{`
const REQUIRED_SECTIONS = [
  '## Goal', '## Instructions', '## Discoveries',
  '## Accomplished', '## Relevant files',
]

function validateSummary(summary: string): boolean {
  return REQUIRED_SECTIONS.every(section =>
    summary.includes(section)
  )
}
// Nếu validateSummary = false → retry với reminder
// hoặc dùng summary partial (tốt hơn không có gì)
`}

Tương tác với các kỹ thuật khác Interaction

T8 compact() — orchestrator │ ├── 1. T9: prune tool outputs │ ├── 2. split head / tail │ └── 3. LLM compact call: │ ▼ ┌──────────────────────────────┐ │ T12 — Compaction Template │ │ │ │ getCompactionTemplate() │ │ ↓ │ │ Plugin override? ──Yes──→ │ │ ↓ No │ │ DEFAULT_COMPACTION_TEMPLATE │ │ ↓ │ │ → passed as last user msg │ │ to LLM compact call │ └──────────────────────────────┘ │ ▼ summary string (5 sections) │ ▼ T8: wrap in <prior-conversation-summary> T11: inject continuation message T1: agent loop nhận messages mới với summary trong system msg Plugin override: plugin.compactionTemplate?.() → domain-specific sections (thêm/bớt/đổi tên)

Output của T12 (summary string) được T8 đặt vào system message với wrapper <prior-conversation-summary>...</prior-conversation-summary>. XML tag này giúp model phân biệt summary với system instructions thật.

Failure modes Risk

FM-1: Free-form summary (không có template)

Anti-pattern — free-form compact prompt

TS
{`
// ❌ Free-form — model tự quyết định cấu trúc
const template = "Please summarize our conversation so far."
// Kết quả điển hình:
// "We discussed a coding task where the user wanted to...
//  The assistant helped by... Overall, the key points were..."
// → Mất hoàn toàn: file paths, symbols, rules, accomplished actions
`}

Sau compact với free-form summary, agent thường hỏi lại "bạn đang làm việc với file nào?" — mất hoàn toàn spatial memory về codebase.

FM-2: Template yếu — thiếu Relevant files

Nếu không có section "Relevant files", agent sau compact không biết file nào liên quan → phải đọc lại nhiều file → context overflow cycle tái diễn sớm hơn.

Anti-pattern — template thiếu file list

TS
{`
// ❌ Template không yêu cầu file list
const WEAK_TEMPLATE = \`
Summarize the conversation:
1. What is the goal?
2. What was accomplished?
\`
// Thiếu: file paths, rules, discoveries, relevant files
// Agent mới không biết relevant context về codebase
`}

FM-3: Plugin override quá khác biệt

Plugin thay đổi template hoàn toàn (xóa core sections) → summary không còn chứa đủ thông tin cần thiết cho agent tiếp tục. Khuyến nghị: plugin chỉ thêm sections, không xóa 5 sections gốc.

Ưu điểm
  • 5 sections → 5 memory types: goal, rules, facts, history, files
  • Plugin override — linh hoạt per domain
  • Factual, không narrative — dễ parse và ít bị hallucinate
  • XML wrapper — model phân biệt summary vs system instructions
Nhược điểm
  • Không validate output — model có thể bỏ section
  • Chỉ 1 level override (plugin) — không per-session override
  • Phụ thuộc model quality — model yếu có thể tóm tắt sai

So sánh với các harness khác Compare

HarnessCompaction template?Structured sections?Plugin override?
opencodeCó — 5 sections cố địnhGoal, Instructions, Discoveries, Accomplished, FilesCó — plugin.compactionTemplate()
Claude CodeCó template (not public)Có, không rõ chi tiếtKhông rõ
LangChainKhông có structured templateFree-form summaryKhông
Microsoft CoPilot StudioCustom template per-agentFlexible, không standardCó — per-agent config
HumanLayer CLAUDE.md khuyến nghị tương tự: yêu cầu LLM luôn list relevant files và accomplished actions trong compaction — đồng thuận với thiết kế của opencode T12.

Implementation recipe Recipe

compaction-template.ts — structured template với validation

TS
{`
// compaction-template.ts — structured 5-section template

export const DEFAULT_COMPACTION_TEMPLATE = \`
Create a structured summary with EXACTLY these 5 sections:

## Goal
One sentence: the user's ultimate objective.

## Instructions
Bullet list of rules/constraints/preferences stated by user.

## Discoveries
Technical facts about the codebase:
- File paths and purpose
- Key symbols (functions, classes, types) and what they do
- Patterns, conventions, architectural decisions

## Accomplished
Chronological actions taken:
- Files created/edited/deleted (with reason)
- Commands run and outcomes
- Decisions made and rationale

## Relevant files
Files relevant to the current task:
- \`path/to/file\` — one-line relevance description

Be factual and concise. No narrative prose.
\`

const REQUIRED_SECTIONS = [
  '## Goal',
  '## Instructions',
  '## Discoveries',
  '## Accomplished',
  '## Relevant files',
] as const

export function validateSummary(summary: string): {
  valid: boolean
  missingSections: string[]
} {
  const missing = REQUIRED_SECTIONS.filter(s => !summary.includes(s))
  return { valid: missing.length === 0, missingSections: missing }
}

export function getTemplate(plugins: Plugin[]): string {
  for (const p of plugins) {
    const t = p.compactionTemplate?.()
    if (t) return t
  }
  return DEFAULT_COMPACTION_TEMPLATE
}
`}

Tham khảo Refs