opencodekit 0.22.0 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +4 -25
  3. package/dist/template/.opencode/.template-manifest.json +115 -188
  4. package/dist/template/.opencode/AGENTS.md +21 -4
  5. package/dist/template/.opencode/README.md +1 -1
  6. package/dist/template/.opencode/agent/build.md +155 -13
  7. package/dist/template/.opencode/agent/plan.md +7 -16
  8. package/dist/template/.opencode/agent/scout.md +2 -2
  9. package/dist/template/.opencode/artifacts/.active +1 -0
  10. package/dist/template/.opencode/artifacts/example/plan.md +12 -0
  11. package/dist/template/.opencode/artifacts/example/progress.md +4 -0
  12. package/dist/template/.opencode/artifacts/example/research.md +4 -0
  13. package/dist/template/.opencode/artifacts/example/spec.md +16 -0
  14. package/dist/template/.opencode/artifacts/todo.md +5 -0
  15. package/dist/template/.opencode/artifacts/verify.log +4 -0
  16. package/dist/template/.opencode/command/clarify.md +6 -8
  17. package/dist/template/.opencode/command/create.md +29 -71
  18. package/dist/template/.opencode/command/design.md +1 -2
  19. package/dist/template/.opencode/command/explore.md +3 -4
  20. package/dist/template/.opencode/command/fix.md +0 -1
  21. package/dist/template/.opencode/command/init.md +1 -4
  22. package/dist/template/.opencode/command/plan.md +30 -60
  23. package/dist/template/.opencode/command/pr.md +10 -28
  24. package/dist/template/.opencode/command/refactor.md +0 -1
  25. package/dist/template/.opencode/command/research.md +7 -29
  26. package/dist/template/.opencode/command/review-codebase.md +6 -13
  27. package/dist/template/.opencode/command/ship.md +136 -78
  28. package/dist/template/.opencode/command/ui-review.md +2 -4
  29. package/dist/template/.opencode/command/verify.md +15 -23
  30. package/dist/template/.opencode/dcp-prompts/overrides/compress-range.md +89 -0
  31. package/dist/template/.opencode/dcp.jsonc +96 -96
  32. package/dist/template/.opencode/memory/README.md +1 -1
  33. package/dist/template/.opencode/memory/_templates/prd.md +1 -1
  34. package/dist/template/.opencode/memory/_templates/roadmap.md +1 -1
  35. package/dist/template/.opencode/memory/_templates/state.md +1 -1
  36. package/dist/template/.opencode/memory/project/gotchas.md +3 -3
  37. package/dist/template/.opencode/memory/project/project.md +2 -2
  38. package/dist/template/.opencode/memory/project/roadmap.md +1 -1
  39. package/dist/template/.opencode/memory/project/state.md +2 -2
  40. package/dist/template/.opencode/memory/project/tech-stack.md +2 -2
  41. package/dist/template/.opencode/opencode.json +112 -152
  42. package/dist/template/.opencode/plugin/README.md +11 -1
  43. package/dist/template/.opencode/plugin/session-summary.ts +542 -0
  44. package/dist/template/.opencode/skill/brainstorming/SKILL.md +1 -1
  45. package/dist/template/.opencode/skill/context-engineering/SKILL.md +1 -1
  46. package/dist/template/.opencode/skill/development-lifecycle/SKILL.md +26 -45
  47. package/dist/template/.opencode/skill/gemini-large-context/SKILL.md +4 -4
  48. package/dist/template/.opencode/skill/opensrc/references/example-workflow.md +1 -1
  49. package/dist/template/.opencode/skill/subagent-driven-development/SKILL.md +1 -1
  50. package/dist/template/.opencode/skill/using-git-worktrees/SKILL.md +6 -6
  51. package/dist/template/.opencode/skill/verification-before-completion/SKILL.md +6 -6
  52. package/dist/template/.opencode/skill/verification-before-completion/references/VERIFICATION_PROTOCOL.md +5 -5
  53. package/package.json +76 -76
  54. package/dist/template/.opencode/plans/1768385996691-silent-wizard.md +0 -247
  55. package/dist/template/.opencode/plans/1770006237537-mighty-otter.md +0 -418
  56. package/dist/template/.opencode/plans/1770006913647-glowing-forest.md +0 -170
  57. package/dist/template/.opencode/plans/1770013678126-witty-planet.md +0 -278
  58. package/dist/template/.opencode/plans/1770112267595-shiny-rocket.md +0 -258
  59. package/dist/template/.opencode/plans/swarm-protocol.md +0 -123
  60. package/dist/template/.opencode/skill/beads/SKILL.md +0 -182
  61. package/dist/template/.opencode/skill/beads/references/BEST_PRACTICES.md +0 -27
  62. package/dist/template/.opencode/skill/beads/references/BOUNDARIES.md +0 -219
  63. package/dist/template/.opencode/skill/beads/references/DEPENDENCIES.md +0 -124
  64. package/dist/template/.opencode/skill/beads/references/EXAMPLES.md +0 -45
  65. package/dist/template/.opencode/skill/beads/references/FILE_CLAIMING.md +0 -101
  66. package/dist/template/.opencode/skill/beads/references/GIT_SYNC.md +0 -25
  67. package/dist/template/.opencode/skill/beads/references/HIERARCHY.md +0 -71
  68. package/dist/template/.opencode/skill/beads/references/MULTI_AGENT.md +0 -40
  69. package/dist/template/.opencode/skill/beads/references/RESUMABILITY.md +0 -177
  70. package/dist/template/.opencode/skill/beads/references/SESSION_PROTOCOL.md +0 -61
  71. package/dist/template/.opencode/skill/beads/references/TASK_CREATION.md +0 -38
  72. package/dist/template/.opencode/skill/beads/references/TROUBLESHOOTING.md +0 -38
  73. package/dist/template/.opencode/skill/beads/references/WORKFLOWS.md +0 -226
@@ -1,247 +0,0 @@
1
- # Plan: Optimize Scout Agent for External Research
2
-
3
- **Goal:** Enhance Scout agent prompt with missing tool integrations and workflows for optimal external research.
4
-
5
- **Scope:** READ-ONLY external research only (no local codebase changes)
6
-
7
- ---
8
-
9
- ## Changes Required
10
-
11
- ### File: `.opencode/agent/scout.md`
12
-
13
- #### 1. Add Memory-First Protocol (after line 43, before "External research:")
14
-
15
- ````markdown
16
- ## Memory First
17
-
18
- Before hitting external APIs, check past research:
19
-
20
- ```typescript
21
- memory - search({ query: "<topic keywords>", limit: 3 });
22
- ```
23
- ````
24
-
25
- If memory returns high-confidence findings on this exact topic, synthesize and return without external calls. Only proceed to external sources if:
26
-
27
- - No relevant memory found
28
- - Memory findings are outdated or low-confidence
29
- - Question requires fresher data
30
-
31
- ````
32
-
33
- #### 2. Add Tool Priority Section (replace/enhance "## Guidelines" around line 88)
34
-
35
- ```markdown
36
- ## Tool Priority (External Sources Only)
37
-
38
- | Priority | Tool | Use Case | Speed |
39
- |----------|------|----------|-------|
40
- | 1 | memory-search | Past research findings | Instant |
41
- | Priority | Tool | Use Case | Speed |
42
- |----------|------|----------|-------|
43
- | 1 | memory-search | Past research findings | Instant |
44
- | 2 | context7_resolve-library-id | Resolve library names to IDs | Fast |
45
- | 3 | context7_query-docs | Official library docs | Fast |
46
- | 4 | codesearch | Exa Code API for SDK/library patterns | Fast |
47
- | 5 | grepsearch | Cross-repo GitHub code search | Medium |
48
- | 6 | webfetch | Specific doc URLs, READMEs, changelogs | Medium |
49
- | 7 | opensrc + LSP | Clone & analyze source code | Slow |
50
- | 8 | websearch | Tutorials, blog posts, recent news | Slow |
51
- | 3 | codesearch | Usage patterns in real code | Fast |
52
- | 4 | gh_grep | Cross-repo deep code search | Medium |
53
- | 5 | webfetch | Specific doc URLs, READMEs, changelogs | Medium |
54
- | 6 | opensrc + LSP | Clone & analyze source code | Slow |
55
- | 7 | websearch | Tutorials, blog posts, recent news | Slow |
56
-
57
- **Rule:** Exhaust faster tools before slower ones. Run tools in parallel when independent.
58
- ````
59
-
60
- #### 3. Add webfetch Section (new section after Tool Priority)
61
-
62
- ````markdown
63
- ## webfetch Usage
64
-
65
- Use `webfetch` for specific external URLs when you have a known target:
66
-
67
- ```typescript
68
- // GitHub raw files
69
- webfetch({
70
- url: "https://raw.githubusercontent.com/owner/repo/main/README.md",
71
- format: "markdown",
72
- });
73
-
74
- // Documentation pages
75
- webfetch({ url: "https://zod.dev/docs/guides/async", format: "markdown" });
76
-
77
- // Release notes
78
- webfetch({ url: "https://github.com/colinhacks/zod/releases", format: "markdown" });
79
-
80
- // API references
81
- webfetch({ url: "https://docs.example.com/api/authentication", format: "markdown" });
82
- ```
83
- ````
84
-
85
- **When to use:**
86
-
87
- - User provides a specific URL
88
- - context7_resolve-library-id returns a library ID
89
- - context7_query-docs returns a doc link worth fetching
90
- - Need CHANGELOG or release notes
91
- - GitHub README has details not in context7
92
-
93
- ````
94
-
95
- #### 4. Add Source Code Deep Dive Section (new section, expand on existing clone guidance)
96
-
97
- ```markdown
98
- ## Source Code Deep Dive
99
-
100
- When documentation is insufficient, analyze actual source code.
101
-
102
- ### Step 1: Load the Skill
103
- ```typescript
104
- skill({ name: "source-code-research" })
105
- ````
106
-
107
- ### Step 2: Clone the Package
108
-
109
- ```bash
110
- npx opensrc <package> # npm (auto-detects version)
111
- npx opensrc <package>@<version> # specific version
112
- npx opensrc pypi:<package> # Python
113
- npx opensrc <owner>/<repo> # GitHub repo
114
- ```
115
-
116
- ### Step 3: Navigate with LSP
117
-
118
- After cloning, source lands in `opensrc/repos/github.com/<owner>/<repo>/`. Use LSP:
119
-
120
- ```typescript
121
- // Get file structure
122
- lsp({
123
- operation: "documentSymbol",
124
- filePath: "opensrc/repos/.../src/index.ts",
125
- line: 1,
126
- character: 1,
127
- });
128
-
129
- // Jump to definition
130
- lsp({
131
- operation: "goToDefinition",
132
- filePath: "opensrc/repos/.../src/types.ts",
133
- line: 42,
134
- character: 10,
135
- });
136
-
137
- // Find all usages
138
- lsp({
139
- operation: "findReferences",
140
- filePath: "opensrc/repos/.../src/core.ts",
141
- line: 100,
142
- character: 5,
143
- });
144
- ```
145
-
146
- ### Step 4: Search Within Clone
147
-
148
- ```typescript
149
- // Find specific patterns
150
- grep({ pattern: "async.*refine", path: "opensrc/", include: "*.ts" });
151
-
152
- // Check tests for usage examples
153
- glob({ pattern: "opensrc/**/test/**/*.ts" });
154
- glob({ pattern: "opensrc/**/*.test.ts" });
155
- ```
156
-
157
- ### Step 5: Construct Permalinks
158
-
159
- Build GitHub permalinks from cloned code:
160
-
161
- ```
162
- https://github.com/<owner>/<repo>/blob/<sha>/path/to/file.ts#L42-L56
163
- ```
164
-
165
- Get SHA from `opensrc/sources.json` or the cloned repo.
166
-
167
- ````
168
-
169
- #### 5. Update Fallback Chain in "When Things Fail" Section (enhance existing)
170
-
171
- ```markdown
172
- ## When Things Fail
173
-
174
- ### Fallback Chain
175
- ````
176
-
177
- context7 fails → try codesearch for patterns
178
- codesearch empty → try gh_grep with broader query
179
- gh_grep empty → webfetch specific doc URLs if known
180
- still stuck → opensrc clone + LSP analysis
181
- last resort → websearch for tutorials/blogs
182
-
183
- ```
184
-
185
- ### Specific Failures
186
-
187
- **context7 doesn't find library:**
188
- 1. Try `codesearch({ query: "<library> <function> example" })`
189
- 2. Try `gh_grepsearchGitHub({ query: "import.*from.*<library>" })`
190
- 3. Clone with `npx opensrc <library>` and read source
191
-
192
- **gh_grep returns nothing:**
193
- - Broaden query: search concepts, not exact function names
194
- - Try different language filters
195
- - Search for error messages or config patterns
196
-
197
- **opensrc clone fails:**
198
- - Check if package exists on npm/pypi/crates
199
- - Try GitHub URL directly: `npx opensrc owner/repo`
200
- - Fall back to `webfetch` on raw GitHub files
201
-
202
- **API rate limits:**
203
- - Work from already-cloned repos in `opensrc/`
204
- - Use `memory-search` to find cached findings
205
- - Reduce parallel calls, go sequential
206
- ```
207
-
208
- ---
209
-
210
- ## Summary of Additions
211
-
212
- | Addition | Lines | Purpose |
213
- | ----------------------- | ----- | ----------------------------------------- |
214
- | Memory-First Protocol | ~15 | Check past research before external calls |
215
- | Tool Priority Table | ~15 | Clear hierarchy for tool selection |
216
- | webfetch Section | ~25 | Document missing tool usage |
217
- | Source Code Deep Dive | ~50 | Full opensrc + LSP workflow |
218
- | Enhanced Fallback Chain | ~30 | Clear failure recovery paths |
219
-
220
- **Total additions:** ~135 lines
221
-
222
- ---
223
-
224
- ## Files to Modify
225
-
226
- 1. `.opencode/agent/scout.md` - Add sections above
227
-
228
- ---
229
-
230
- ## Verification
231
-
232
- After implementation:
233
-
234
- 1. Test Quick Mode: `@scout how to use zod .refine()`
235
- 2. Test Deep Mode: `@scout how do production apps handle zod async validation`
236
- 3. Test Source Dive: `@scout show me zod's internal parse implementation`
237
- 4. Verify memory check appears in scout's first actions
238
- 5. Verify webfetch used when given specific URLs
239
-
240
- ---
241
-
242
- ## Out of Scope
243
-
244
- - Local codebase access (that's Explore agent)
245
- - File modifications outside `.beads/artifacts/`
246
- - Question tool (subagent constraint)
247
- - New MCP integrations (uses existing tools)
@@ -1,418 +0,0 @@
1
- # Memory System Upgrade Plan
2
-
3
- **Goal**: Upgrade OpenCodeKit memory from file-based markdown to hybrid SQLite + FTS5 with progressive disclosure.
4
-
5
- **Key Benefits**:
6
-
7
- 1. **10x token savings** via progressive disclosure (compact index → timeline → full details)
8
- 2. **Fast full-text search** via SQLite FTS5 (vs O(n) regex scan)
9
- 3. **Richer schema** with facts, narrative, files_read/modified distinction
10
- 4. **Backward compatible** - existing tools continue working, markdown remains human-readable
11
-
12
- ---
13
-
14
- ## Phase 1: Database Foundation
15
-
16
- ### 1.1 Create SQLite Module
17
-
18
- **File**: `.opencode/plugin/lib/memory-db.ts`
19
-
20
- ```typescript
21
- // Core database class using better-sqlite3
22
- import Database from "better-sqlite3";
23
-
24
- const DB_PATH = path.join(process.cwd(), ".opencode/memory.db");
25
-
26
- export function getMemoryDB(): Database {
27
- const db = new Database(DB_PATH, { create: true });
28
- db.run("PRAGMA journal_mode = WAL"); // Better concurrency
29
- db.run("PRAGMA foreign_keys = ON");
30
- initializeSchema(db);
31
- return db;
32
- }
33
- ```
34
-
35
- ### 1.2 Database Schema
36
-
37
- **File**: `.opencode/plugin/lib/memory-schema.ts`
38
-
39
- **Tables**:
40
-
41
- - `schema_versions` - Migration tracking
42
- - `observations` - Enhanced observation records
43
- - `observations_fts` - FTS5 virtual table
44
- - `memory_files` - Non-observation memory files
45
-
46
- **Schema**:
47
-
48
- ```sql
49
- CREATE TABLE IF NOT EXISTS observations (
50
- id INTEGER PRIMARY KEY AUTOINCREMENT,
51
- type TEXT NOT NULL CHECK(type IN ('decision','bugfix','feature','pattern','discovery','learning','warning')),
52
- title TEXT NOT NULL,
53
- subtitle TEXT,
54
- facts TEXT, -- JSON array
55
- narrative TEXT, -- Long-form content
56
- concepts TEXT, -- JSON array
57
- files_read TEXT, -- JSON array
58
- files_modified TEXT, -- JSON array
59
- confidence TEXT CHECK(confidence IN ('high','medium','low')) DEFAULT 'high',
60
- bead_id TEXT,
61
- supersedes INTEGER,
62
- superseded_by INTEGER,
63
- valid_until TEXT,
64
- markdown_file TEXT, -- Reference to backup markdown file
65
- created_at TEXT NOT NULL,
66
- created_at_epoch INTEGER NOT NULL,
67
- updated_at TEXT
68
- );
69
-
70
- -- FTS5 for full-text search
71
- CREATE VIRTUAL TABLE IF NOT EXISTS observations_fts USING fts5(
72
- title, subtitle, narrative, facts, concepts,
73
- content='observations', content_rowid='id'
74
- );
75
-
76
- -- Auto-sync triggers for FTS5
77
- CREATE TRIGGER observations_fts_ai AFTER INSERT ON observations BEGIN
78
- INSERT INTO observations_fts(rowid, title, subtitle, narrative, facts, concepts)
79
- VALUES (new.id, new.title, new.subtitle, new.narrative, new.facts, new.concepts);
80
- END;
81
- -- (plus UPDATE and DELETE triggers)
82
- ```
83
-
84
- ---
85
-
86
- ## Phase 2: Progressive Disclosure Tools
87
-
88
- ### 2.1 Update `memory-search.ts` - Compact Index
89
-
90
- **File**: `.opencode/tool/memory-search.ts`
91
-
92
- **Change**: Return compact index instead of full content.
93
-
94
- ```typescript
95
- // NEW: Returns compact index only (~50-100 tokens per result)
96
- interface SearchIndexResult {
97
- id: number;
98
- type: string;
99
- title: string;
100
- snippet: string; // First 100 chars of narrative
101
- created_at: string;
102
- relevance_score: number;
103
- }
104
-
105
- execute: async (args) => {
106
- const db = getMemoryDB();
107
-
108
- // Check if FTS5 available (better-sqlite3 supports it)
109
- const useFTS = checkFTS5Available(db);
110
-
111
- if (useFTS && args.query) {
112
- // Use FTS5 for text search with ranking
113
- const results = db
114
- .query(
115
- `
116
- SELECT o.id, o.type, o.title,
117
- substr(o.narrative, 1, 100) as snippet,
118
- o.created_at,
119
- bm25(observations_fts) as relevance_score
120
- FROM observations o
121
- JOIN observations_fts fts ON fts.rowid = o.id
122
- WHERE observations_fts MATCH ?
123
- ORDER BY relevance_score
124
- LIMIT ?
125
- `,
126
- )
127
- .all(args.query, args.limit || 10);
128
- return formatCompactIndex(results);
129
- }
130
-
131
- // Fallback to regex search (backward compat)
132
- return fallbackKeywordSearch(args);
133
- };
134
- ```
135
-
136
- ### 2.2 Create `memory-timeline.ts` - Chronological Context
137
-
138
- **File**: `.opencode/tool/memory-timeline.ts` (NEW)
139
-
140
- ```typescript
141
- // Get observations around an anchor point
142
- execute: async (args) => {
143
- const db = getMemoryDB();
144
- const anchor = db
145
- .query(
146
- `
147
- SELECT created_at_epoch FROM observations WHERE id = ?
148
- `,
149
- )
150
- .get(args.anchor_id);
151
-
152
- const before = db
153
- .query(
154
- `
155
- SELECT id, type, title, substr(narrative, 1, 100) as snippet
156
- FROM observations
157
- WHERE created_at_epoch < ?
158
- ORDER BY created_at_epoch DESC
159
- LIMIT ?
160
- `,
161
- )
162
- .all(anchor.created_at_epoch, args.depth_before || 5);
163
-
164
- const after = db
165
- .query(
166
- `
167
- SELECT id, type, title, substr(narrative, 1, 100) as snippet
168
- FROM observations
169
- WHERE created_at_epoch > ?
170
- ORDER BY created_at_epoch ASC
171
- LIMIT ?
172
- `,
173
- )
174
- .all(anchor.created_at_epoch, args.depth_after || 5);
175
-
176
- return { anchor: args.anchor_id, before: before.reverse(), after };
177
- };
178
- ```
179
-
180
- ### 2.3 Create `memory-get.ts` - Full Details
181
-
182
- **File**: `.opencode/tool/memory-get.ts` (NEW)
183
-
184
- ```typescript
185
- // Get full observation details by ID(s)
186
- execute: async (args) => {
187
- const db = getMemoryDB();
188
- const ids = args.ids.split(",").map(Number);
189
-
190
- const observations = db
191
- .query(
192
- `
193
- SELECT * FROM observations WHERE id IN (${ids.join(",")})
194
- `,
195
- )
196
- .all();
197
-
198
- return observations.map(formatFullObservation);
199
- };
200
- ```
201
-
202
- ---
203
-
204
- ## Phase 3: Enhanced Observation Tool
205
-
206
- ### 3.1 Update `observation.ts` - Dual Write + Enhanced Schema
207
-
208
- **File**: `.opencode/tool/observation.ts`
209
-
210
- **New Args**:
211
-
212
- ```typescript
213
- args: {
214
- type: string;
215
- title: string;
216
- subtitle?: string; // NEW
217
- facts?: string; // NEW: Comma-separated structured facts
218
- narrative?: string; // NEW: Renamed from 'content'
219
- content?: string; // DEPRECATED: Alias for narrative (backward compat)
220
- concepts?: string;
221
- files_read?: string; // NEW: Files read during task
222
- files_modified?: string; // NEW: Files changed during task
223
- files?: string; // DEPRECATED: Alias for files_modified
224
- bead_id?: string;
225
- confidence?: string;
226
- supersedes?: string;
227
- }
228
- ```
229
-
230
- **Execute**:
231
-
232
- ```typescript
233
- execute: async (args) => {
234
- const normalized = normalizeArgs(args); // Handle deprecated fields
235
-
236
- // 1. Write to SQLite
237
- const db = getMemoryDB();
238
- const result = db
239
- .query(
240
- `
241
- INSERT INTO observations (type, title, subtitle, facts, narrative, concepts,
242
- files_read, files_modified, confidence, bead_id,
243
- markdown_file, created_at, created_at_epoch)
244
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
245
- `,
246
- )
247
- .run(/* ... */);
248
-
249
- // 2. Write to markdown (backup)
250
- const markdownPath = generateMarkdownPath(normalized);
251
- await fs.writeFile(markdownPath, renderToMarkdown(normalized, result.lastInsertRowid));
252
-
253
- return `✓ Observation #${result.lastInsertRowid} saved (SQLite + markdown backup)`;
254
- };
255
- ```
256
-
257
- ---
258
-
259
- ## Phase 4: Migration Script
260
-
261
- ### 4.1 Create Migration Tool
262
-
263
- **File**: `.opencode/tool/memory-migrate.ts` (NEW)
264
-
265
- ```typescript
266
- execute: async () => {
267
- const obsDir = path.join(process.cwd(), ".opencode/memory/observations");
268
- const db = getMemoryDB();
269
-
270
- // Get all markdown files
271
- const files = await fs.readdir(obsDir);
272
- const mdFiles = files.filter((f) => f.endsWith(".md") && !f.startsWith("."));
273
-
274
- let migrated = 0,
275
- errors = [];
276
-
277
- for (const file of mdFiles) {
278
- try {
279
- const content = await fs.readFile(path.join(obsDir, file), "utf-8");
280
- const parsed = parseMarkdownObservation(content, file);
281
-
282
- // Insert into SQLite
283
- db.query(`INSERT INTO observations ...`).run(parsed);
284
- migrated++;
285
- } catch (e) {
286
- errors.push({ file, error: e.message });
287
- }
288
- }
289
-
290
- // Write migration marker
291
- await fs.writeFile(
292
- path.join(obsDir, ".migrated"),
293
- `Migrated ${migrated} observations on ${new Date().toISOString()}`,
294
- );
295
-
296
- return `✓ Migration complete: ${migrated} observations, ${errors.length} errors`;
297
- };
298
- ```
299
-
300
- ---
301
-
302
- ## Phase 5: Update Existing Tools
303
-
304
- ### 5.1 Update `memory-read.ts`
305
-
306
- Add SQLite lookup before file fallback:
307
-
308
- ```typescript
309
- execute: async (args) => {
310
- // NEW: Check for observation by ID
311
- if (args.file?.match(/^#?\d+$/)) {
312
- const db = getMemoryDB();
313
- const id = parseInt(args.file.replace("#", ""));
314
- const obs = db.query("SELECT * FROM observations WHERE id = ?").get(id);
315
- if (obs) return formatFullObservation(obs);
316
- }
317
-
318
- // Existing file-based lookup (unchanged)
319
- return readMarkdownFile(args.file);
320
- };
321
- ```
322
-
323
- ### 5.2 Update `memory-update.ts`
324
-
325
- Add dual-write to SQLite:
326
-
327
- ```typescript
328
- execute: async (args) => {
329
- const db = getMemoryDB();
330
-
331
- // Write to SQLite memory_files table
332
- db.query(
333
- `
334
- INSERT INTO memory_files (file_path, content, mode, created_at, created_at_epoch)
335
- VALUES (?, ?, ?, ?, ?)
336
- ON CONFLICT(file_path) DO UPDATE SET content = ?, updated_at = ?
337
- `,
338
- ).run(/* ... */);
339
-
340
- // Also write to markdown (unchanged)
341
- await writeMarkdownFile(args.file, args.content, args.mode);
342
-
343
- return `Updated ${args.file} (SQLite + markdown)`;
344
- };
345
- ```
346
-
347
- ---
348
-
349
- ## Implementation Order
350
-
351
- | Order | Task | Files | Effort | Depends On |
352
- | ----- | ------------------------- | --------------------------------------- | ------ | ---------- |
353
- | 1 | Create memory-db.ts | `.opencode/plugin/lib/memory-db.ts` | 3h | - |
354
- | 2 | Create memory-schema.ts | `.opencode/plugin/lib/memory-schema.ts` | 2h | 1 |
355
- | 3 | Create memory-migrate.ts | `.opencode/tool/memory-migrate.ts` | 3h | 1, 2 |
356
- | 4 | Update observation.ts | `.opencode/tool/observation.ts` | 3h | 1, 2 |
357
- | 5 | Update memory-search.ts | `.opencode/tool/memory-search.ts` | 3h | 1, 2 |
358
- | 6 | Create memory-timeline.ts | `.opencode/tool/memory-timeline.ts` | 2h | 1, 2 |
359
- | 7 | Create memory-get.ts | `.opencode/tool/memory-get.ts` | 2h | 1, 2 |
360
- | 8 | Update memory-read.ts | `.opencode/tool/memory-read.ts` | 1h | 1, 2 |
361
- | 9 | Update memory-update.ts | `.opencode/tool/memory-update.ts` | 1h | 1, 2 |
362
- | 10 | Update memory.ts plugin | `.opencode/plugin/memory.ts` | 2h | 4, 5 |
363
-
364
- **Total**: ~22 hours of implementation
365
-
366
- ---
367
-
368
- ## Files to Modify/Create
369
-
370
- **NEW FILES**:
371
-
372
- - `.opencode/plugin/lib/memory-db.ts` - SQLite database manager
373
- - `.opencode/plugin/lib/memory-schema.ts` - Schema definitions + migrations
374
- - `.opencode/tool/memory-migrate.ts` - Migration tool
375
- - `.opencode/tool/memory-timeline.ts` - Timeline context tool
376
- - `.opencode/tool/memory-get.ts` - Full observation retrieval
377
-
378
- **MODIFY**:
379
-
380
- - `.opencode/tool/observation.ts` - Dual write + enhanced schema
381
- - `.opencode/tool/memory-search.ts` - FTS5 + compact index
382
- - `.opencode/tool/memory-read.ts` - SQLite lookup + fallback
383
- - `.opencode/tool/memory-update.ts` - Dual write
384
- - `.opencode/plugin/memory.ts` - Add FTS5 optimization hook
385
-
386
- ---
387
-
388
- ## Verification
389
-
390
- ### Manual Testing
391
-
392
- 1. Run `memory-migrate` to import existing observations
393
- 2. Create new observation with `observation` tool
394
- 3. Search with `memory-search` and verify FTS5 is used
395
- 4. Use `memory-timeline` around a result
396
- 5. Use `memory-get` to fetch full details
397
- 6. Verify markdown backups are created
398
- 7. Verify existing tools still work (backward compat)
399
-
400
- ### Check Database
401
-
402
- ```bash
403
- # Verify SQLite file created
404
- ls -la .opencode/memory.db
405
-
406
- # Verify FTS5 table
407
- sqlite3 .opencode/memory.db "SELECT * FROM observations_fts LIMIT 5;"
408
-
409
- # Verify observation count matches markdown files
410
- sqlite3 .opencode/memory.db "SELECT COUNT(*) FROM observations;"
411
- ls .opencode/memory/observations/*.md | wc -l
412
- ```
413
-
414
- ### Backward Compatibility
415
-
416
- 1. `memory-read({ file: "handoffs/2024-01-01" })` still works
417
- 2. `observation({ type: "decision", title: "X", content: "Y" })` still works (deprecated `content` field)
418
- 3. `memory-search({ query: "auth" })` returns results (may be faster with FTS5)