opencodekit 0.22.0 → 0.23.0
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.
- package/README.md +1 -1
- package/dist/index.js +4 -25
- package/dist/template/.opencode/.template-manifest.json +115 -188
- package/dist/template/.opencode/AGENTS.md +18 -4
- package/dist/template/.opencode/README.md +1 -1
- package/dist/template/.opencode/agent/build.md +155 -13
- package/dist/template/.opencode/agent/plan.md +7 -16
- package/dist/template/.opencode/agent/scout.md +2 -2
- package/dist/template/.opencode/artifacts/.active +1 -0
- package/dist/template/.opencode/artifacts/example/plan.md +12 -0
- package/dist/template/.opencode/artifacts/example/progress.md +4 -0
- package/dist/template/.opencode/artifacts/example/research.md +4 -0
- package/dist/template/.opencode/artifacts/example/spec.md +16 -0
- package/dist/template/.opencode/artifacts/todo.md +5 -0
- package/dist/template/.opencode/artifacts/verify.log +4 -0
- package/dist/template/.opencode/command/clarify.md +6 -8
- package/dist/template/.opencode/command/create.md +29 -71
- package/dist/template/.opencode/command/design.md +1 -2
- package/dist/template/.opencode/command/explore.md +3 -4
- package/dist/template/.opencode/command/fix.md +0 -1
- package/dist/template/.opencode/command/init.md +1 -4
- package/dist/template/.opencode/command/plan.md +30 -60
- package/dist/template/.opencode/command/pr.md +10 -28
- package/dist/template/.opencode/command/refactor.md +0 -1
- package/dist/template/.opencode/command/research.md +7 -29
- package/dist/template/.opencode/command/review-codebase.md +6 -13
- package/dist/template/.opencode/command/ship.md +136 -78
- package/dist/template/.opencode/command/ui-review.md +2 -4
- package/dist/template/.opencode/command/verify.md +15 -23
- package/dist/template/.opencode/dcp.jsonc +96 -96
- package/dist/template/.opencode/memory/README.md +1 -1
- package/dist/template/.opencode/memory/_templates/prd.md +1 -1
- package/dist/template/.opencode/memory/_templates/roadmap.md +1 -1
- package/dist/template/.opencode/memory/_templates/state.md +1 -1
- package/dist/template/.opencode/memory/project/gotchas.md +3 -3
- package/dist/template/.opencode/memory/project/project.md +2 -2
- package/dist/template/.opencode/memory/project/roadmap.md +1 -1
- package/dist/template/.opencode/memory/project/state.md +2 -2
- package/dist/template/.opencode/memory/project/tech-stack.md +2 -2
- package/dist/template/.opencode/opencode.json +14 -152
- package/dist/template/.opencode/plugin/README.md +1 -1
- package/dist/template/.opencode/skill/brainstorming/SKILL.md +1 -1
- package/dist/template/.opencode/skill/context-engineering/SKILL.md +1 -1
- package/dist/template/.opencode/skill/development-lifecycle/SKILL.md +26 -45
- package/dist/template/.opencode/skill/gemini-large-context/SKILL.md +4 -4
- package/dist/template/.opencode/skill/opensrc/references/example-workflow.md +1 -1
- package/dist/template/.opencode/skill/subagent-driven-development/SKILL.md +1 -1
- package/dist/template/.opencode/skill/using-git-worktrees/SKILL.md +6 -6
- package/dist/template/.opencode/skill/verification-before-completion/SKILL.md +6 -6
- package/dist/template/.opencode/skill/verification-before-completion/references/VERIFICATION_PROTOCOL.md +5 -5
- package/package.json +76 -76
- package/dist/template/.opencode/plans/1768385996691-silent-wizard.md +0 -247
- package/dist/template/.opencode/plans/1770006237537-mighty-otter.md +0 -418
- package/dist/template/.opencode/plans/1770006913647-glowing-forest.md +0 -170
- package/dist/template/.opencode/plans/1770013678126-witty-planet.md +0 -278
- package/dist/template/.opencode/plans/1770112267595-shiny-rocket.md +0 -258
- package/dist/template/.opencode/plans/swarm-protocol.md +0 -123
- package/dist/template/.opencode/skill/beads/SKILL.md +0 -182
- package/dist/template/.opencode/skill/beads/references/BEST_PRACTICES.md +0 -27
- package/dist/template/.opencode/skill/beads/references/BOUNDARIES.md +0 -219
- package/dist/template/.opencode/skill/beads/references/DEPENDENCIES.md +0 -124
- package/dist/template/.opencode/skill/beads/references/EXAMPLES.md +0 -45
- package/dist/template/.opencode/skill/beads/references/FILE_CLAIMING.md +0 -101
- package/dist/template/.opencode/skill/beads/references/GIT_SYNC.md +0 -25
- package/dist/template/.opencode/skill/beads/references/HIERARCHY.md +0 -71
- package/dist/template/.opencode/skill/beads/references/MULTI_AGENT.md +0 -40
- package/dist/template/.opencode/skill/beads/references/RESUMABILITY.md +0 -177
- package/dist/template/.opencode/skill/beads/references/SESSION_PROTOCOL.md +0 -61
- package/dist/template/.opencode/skill/beads/references/TASK_CREATION.md +0 -38
- package/dist/template/.opencode/skill/beads/references/TROUBLESHOOTING.md +0 -38
- 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)
|