Skip to content

Commit df67fd6

Browse files
anandgupta42claude
andcommitted
feat: merge training into memory with context-aware relevance scoring
Replace two parallel injection systems (memory 8KB + training 16KB) with a single unified injection that scores blocks by relevance to the current agent. How it works: - All blocks (memory + training) loaded in one pass - Each block scored: agent tag match (+10), training kind relevance per agent (+1-5), applied count bonus (+0-3), recency (+0-2), non-training base (+5) - Builder sees rules/patterns first; analyst sees glossary/context first - Budget is 20KB unified, filled greedily by score - Training blocks still tracked with applied counts (fire-and-forget) Architecture: - memory/prompt.ts: new scoreBlock(), unified inject() with InjectionContext - memory/types.ts: UNIFIED_INJECTION_BUDGET, AGENT_TRAINING_RELEVANCE weights - session/prompt.ts: single inject call with agent context (was 2 separate) - training/prompt.ts: deprecated, delegates to MemoryPrompt (backward compat) No changes to: MemoryStore, TrainingStore, training tools, memory tools. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4a10913 commit df67fd6

File tree

5 files changed

+287
-106
lines changed

5 files changed

+287
-106
lines changed

packages/opencode/src/altimate/training/prompt.ts

Lines changed: 10 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,24 @@
1-
// altimate_change - Training prompt injection for AI Teammate learned knowledge
2-
import { TrainingStore, type TrainingEntry } from "./store"
3-
import { TRAINING_BUDGET, type TrainingKind } from "./types"
4-
5-
const KIND_HEADERS: Record<TrainingKind, { header: string; instruction: string }> = {
6-
pattern: {
7-
header: "Learned Patterns",
8-
instruction: "Follow these patterns when creating similar artifacts. They were learned from the user's codebase.",
9-
},
10-
rule: {
11-
header: "Learned Rules",
12-
instruction: "Always follow these rules. They were taught by the user through corrections and explicit instruction.",
13-
},
14-
glossary: {
15-
header: "Domain Glossary",
16-
instruction: "Use these definitions when discussing business concepts. They are specific to the user's domain.",
17-
},
18-
standard: {
19-
header: "Team Standards",
20-
instruction: "Enforce these standards in code reviews and when writing new code. They were loaded from team documentation.",
21-
},
22-
context: {
23-
header: "Domain Context",
24-
instruction: "Use this background knowledge to inform your reasoning. Not directly enforceable, but critical for understanding 'why'.",
25-
},
26-
playbook: {
27-
header: "Playbooks",
28-
instruction: "Follow these step-by-step procedures when handling the described scenarios.",
29-
},
30-
}
31-
32-
// Track which entries have been applied this session to avoid double-counting
33-
const appliedThisSession = new Set<string>()
1+
// altimate_change - Training prompt (deprecated — delegates to unified MemoryPrompt.inject)
2+
// Kept for backward compatibility with training tools (budgetUsage) and tests.
3+
import { MemoryPrompt } from "../../memory/prompt"
4+
import { TRAINING_BUDGET } from "./types"
5+
import type { TrainingEntry } from "./store"
346

357
export namespace TrainingPrompt {
8+
/** Format a training entry for display. */
369
export function formatEntry(entry: TrainingEntry): string {
3710
const meta = entry.meta.applied > 0 ? ` (applied ${entry.meta.applied}x)` : ""
3811
return `#### ${entry.name}${meta}\n${entry.content}`
3912
}
4013

41-
/** Reset session tracking (call at session start) */
14+
/** @deprecated — Use MemoryPrompt.resetSession(). Kept for backward compat. */
4215
export function resetSession(): void {
43-
appliedThisSession.clear()
16+
MemoryPrompt.resetSession()
4417
}
4518

19+
/** @deprecated — Use MemoryPrompt.inject() with context. Kept for training tool compat. */
4620
export async function inject(budget: number = TRAINING_BUDGET): Promise<string> {
47-
const entries = await TrainingStore.list()
48-
if (entries.length === 0) return ""
49-
50-
const grouped = new Map<TrainingKind, TrainingEntry[]>()
51-
for (const entry of entries) {
52-
const list = grouped.get(entry.kind) ?? []
53-
list.push(entry)
54-
grouped.set(entry.kind, list)
55-
}
56-
57-
const header =
58-
"## Teammate Training\n\nYou have been trained on the following knowledge by your team. Apply it consistently.\n"
59-
let result = header
60-
let used = header.length
61-
const injected: TrainingEntry[] = []
62-
63-
for (const kind of ["rule", "pattern", "standard", "glossary", "context", "playbook"] as TrainingKind[]) {
64-
const items = grouped.get(kind)
65-
if (!items || items.length === 0) continue
66-
67-
const section = KIND_HEADERS[kind]
68-
const sectionHeader = `\n### ${section.header}\n_${section.instruction}_\n`
69-
if (used + sectionHeader.length > budget) break
70-
result += sectionHeader
71-
used += sectionHeader.length
72-
73-
// Sort by applied count descending so most-used entries get priority in budget
74-
const sorted = [...items].sort((a, b) => b.meta.applied - a.meta.applied)
75-
for (const entry of sorted) {
76-
const formatted = formatEntry(entry)
77-
const needed = formatted.length + 2
78-
if (used + needed > budget) break
79-
result += "\n" + formatted + "\n"
80-
used += needed
81-
injected.push(entry)
82-
}
83-
}
84-
85-
// Increment applied count once per session per entry (fire-and-forget)
86-
for (const entry of injected) {
87-
if (!appliedThisSession.has(entry.id)) {
88-
appliedThisSession.add(entry.id)
89-
TrainingStore.incrementApplied(entry.scope, entry.kind, entry.name).catch(() => {})
90-
}
91-
}
92-
93-
return result
21+
return MemoryPrompt.injectTrainingOnly(budget)
9422
}
9523

9624
export async function budgetUsage(budget: number = TRAINING_BUDGET): Promise<{

packages/opencode/src/memory/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ export { MemoryWriteTool } from "./tools/memory-write"
55
export { MemoryDeleteTool } from "./tools/memory-delete"
66
export { MemoryAuditTool } from "./tools/memory-audit"
77
export { MemoryExtractTool } from "./tools/memory-extract"
8-
export { MEMORY_MAX_BLOCK_SIZE, MEMORY_MAX_BLOCKS_PER_SCOPE, MEMORY_MAX_CITATIONS, MEMORY_DEFAULT_INJECTION_BUDGET } from "./types"
9-
export type { MemoryBlock, Citation } from "./types"
8+
export { MEMORY_MAX_BLOCK_SIZE, MEMORY_MAX_BLOCKS_PER_SCOPE, MEMORY_MAX_CITATIONS, MEMORY_DEFAULT_INJECTION_BUDGET, UNIFIED_INJECTION_BUDGET, AGENT_TRAINING_RELEVANCE } from "./types"
9+
export type { MemoryBlock, Citation, InjectionContext } from "./types"

0 commit comments

Comments
 (0)