@opvoid/codememory 0.1.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 +129 -0
- package/examples/basic-capture/index.ts +25 -0
- package/examples/repair-brief/index.ts +43 -0
- package/examples/runtime-observer/index.ts +33 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/Codememory-logo.png" alt="Codememory logo" width="200" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# Codememory
|
|
6
|
+
|
|
7
|
+
> AI wrote your code. Now it knows what happened.
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<video src="assets/Codememory-promo.mp4" controls width="720">
|
|
11
|
+
Your browser does not support embedded video.
|
|
12
|
+
<a href="assets/Codememory-promo.mp4">Download the Codememory promo video</a>.
|
|
13
|
+
</video>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
AI-generated code breaks. The agent doesn't remember why it wrote what it
|
|
17
|
+
wrote, what the function actually did at runtime, or what fixed the bug
|
|
18
|
+
last time the same shape of failure showed up. So you and the agent end
|
|
19
|
+
up in a loop — generate, break, guess, regenerate. Codememory is the memory
|
|
20
|
+
layer that breaks the loop. It records *behavioral* memory of your code:
|
|
21
|
+
the intent behind each generation, what executed at runtime, where it
|
|
22
|
+
failed, and what fix worked. The next time the agent touches that code,
|
|
23
|
+
it gets a repair brief instead of a blank slate.
|
|
24
|
+
|
|
25
|
+
## Why Codememory beats agentmemory
|
|
26
|
+
|
|
27
|
+
| | agentmemory | Codememory |
|
|
28
|
+
| -------------------------------------------- | -------------------- | ----------------------------------------------- |
|
|
29
|
+
| Stores | Conversation history | Code behavior history |
|
|
30
|
+
| Knows why code broke | ✗ | ✓ |
|
|
31
|
+
| Runtime awareness | ✗ | ✓ |
|
|
32
|
+
| Repair brief | ✗ | ✓ — intent + code + trace + fix approach |
|
|
33
|
+
| Works without changes to your workflow | ✓ | ✓ |
|
|
34
|
+
|
|
35
|
+
## How it works
|
|
36
|
+
|
|
37
|
+
When the agent writes code, Codememory captures the **intent** (the prompt,
|
|
38
|
+
the file, a content hash) via an MCP tool call. At runtime an
|
|
39
|
+
**observer** records what each instrumented function actually did —
|
|
40
|
+
inputs, outputs, errors, stack traces — and links those traces back to
|
|
41
|
+
the originating intent. When something fails or the agent revisits the
|
|
42
|
+
same code, Codememory returns a **repair brief** that fuses intent +
|
|
43
|
+
runtime + failure + a suggested fix approach so the next edit is
|
|
44
|
+
informed instead of speculative.
|
|
45
|
+
|
|
46
|
+
## Setup (60 seconds)
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install -g @opvoid/codememory
|
|
50
|
+
codememory init
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then add to your project's `CLAUDE.md`:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
@include CODEMEMORY.md
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
That's it. Claude Code will automatically capture intent when it writes
|
|
60
|
+
code and fetch repair briefs before fixing bugs.
|
|
61
|
+
|
|
62
|
+
## What `codememory init` creates
|
|
63
|
+
|
|
64
|
+
- `.mcp.json` — registers Codememory as a Claude Code MCP server (auto-discovered).
|
|
65
|
+
- `CODEMEMORY.md` — rules that tell Claude Code when to call which tool
|
|
66
|
+
(`capture_intent`, `record_runtime`, `log_failure`, `query_memory`,
|
|
67
|
+
`get_repair_brief`).
|
|
68
|
+
|
|
69
|
+
Existing files are preserved by default. Pass `--force` to overwrite.
|
|
70
|
+
|
|
71
|
+
## CJS vs ESM
|
|
72
|
+
|
|
73
|
+
**CJS projects:** automatic instrumentation via a `Module._load`
|
|
74
|
+
require hook. Call `hook.start()` and local `require(...)` calls are
|
|
75
|
+
auto-instrumented.
|
|
76
|
+
|
|
77
|
+
**ESM projects:** Node does not expose a comparable hook, so use the
|
|
78
|
+
manual observer API:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { RuntimeObserver } from '@opvoid/codememory'
|
|
82
|
+
const observed = observer.observe(yourFunction, 'functionName')
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## The repair brief
|
|
86
|
+
|
|
87
|
+
When something breaks, instead of asking the AI to guess, Codememory gives it:
|
|
88
|
+
|
|
89
|
+
- The original **intent** behind the code (prompt, file, content hash).
|
|
90
|
+
- What the code **actually did** at runtime (inputs, outputs, side effects).
|
|
91
|
+
- The exact **failure point** and stack trace.
|
|
92
|
+
- A suggested **fix approach** chosen by error type and prior outcomes.
|
|
93
|
+
|
|
94
|
+
That brief is fetched through one MCP tool call, before any edit, so the
|
|
95
|
+
agent stops re-deriving context that was already paid for once.
|
|
96
|
+
|
|
97
|
+
## Media
|
|
98
|
+
|
|
99
|
+
| Asset | Path |
|
|
100
|
+
| ----- | ---- |
|
|
101
|
+
| Logo | [`assets/Codememory-logo.png`](assets/Codememory-logo.png) |
|
|
102
|
+
| Promo video | [`assets/Codememory-promo.mp4`](assets/Codememory-promo.mp4) |
|
|
103
|
+
|
|
104
|
+
## Examples
|
|
105
|
+
|
|
106
|
+
See [`examples/`](./examples/) for `basic-capture`, `repair-brief`, and
|
|
107
|
+
`runtime-observer`.
|
|
108
|
+
|
|
109
|
+
## Development
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pnpm install
|
|
113
|
+
pnpm run ci # typecheck + lint + test + build
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Public source archive
|
|
117
|
+
|
|
118
|
+
To produce a clean ZIP suitable for public distribution (no `node_modules`,
|
|
119
|
+
build output, or local databases):
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
pwsh -File scripts/package-source.ps1
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Output: [`release/codememory-source.zip`](release/codememory-source.zip)
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT — byte271
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CaptureIntentTool } from '../../src/mcp/tools/capture_intent.js';
|
|
2
|
+
import { IntentQueries } from '../../src/store/queries/intent.js';
|
|
3
|
+
import { DatabaseManager } from '../../src/store/database.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Example: Capturing AI intent.
|
|
7
|
+
*/
|
|
8
|
+
async function example() {
|
|
9
|
+
const dbManager = new DatabaseManager('./example.db');
|
|
10
|
+
const queries = new IntentQueries(dbManager.getDb());
|
|
11
|
+
const tool = new CaptureIntentTool(queries);
|
|
12
|
+
|
|
13
|
+
const result = await tool.execute({
|
|
14
|
+
prompt: 'Create a function to calculate Fibonacci numbers',
|
|
15
|
+
generated_code: 'function fib(n) { return n <= 1 ? n : fib(n-1) + fib(n-2); }',
|
|
16
|
+
file_path: 'math.ts',
|
|
17
|
+
ai_tool: 'claude_code',
|
|
18
|
+
language: 'typescript'
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
console.log('Captured Intent:', result);
|
|
22
|
+
dbManager.close();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
example();
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DatabaseManager } from '../../src/store/database.js';
|
|
2
|
+
import { IntentQueries } from '../../src/store/queries/intent.js';
|
|
3
|
+
import { RuntimeQueries } from '../../src/store/queries/runtime.js';
|
|
4
|
+
import { RepairAssembler } from '../../src/engines/repair/assembler.js';
|
|
5
|
+
import { GetRepairBriefTool } from '../../src/mcp/tools/get_repair_brief.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Example: Generating a Repair Brief
|
|
9
|
+
* This script demonstrates how Codememory assembles context for AI to fix a bug.
|
|
10
|
+
*/
|
|
11
|
+
async function example() {
|
|
12
|
+
const dbManager = new DatabaseManager('./repair-example.db');
|
|
13
|
+
const db = dbManager.getDb();
|
|
14
|
+
|
|
15
|
+
const intentQueries = new IntentQueries(db);
|
|
16
|
+
const runtimeQueries = new RuntimeQueries(db);
|
|
17
|
+
const assembler = new RepairAssembler(intentQueries, runtimeQueries);
|
|
18
|
+
const tool = new GetRepairBriefTool(assembler);
|
|
19
|
+
|
|
20
|
+
// 1. Setup mock data
|
|
21
|
+
const memoryId = 'mem-123';
|
|
22
|
+
db.prepare('INSERT INTO intent_records (id, created_at, file_path, prompt, generated, ai_tool, language) VALUES (?, ?, ?, ?, ?, ?, ?)').run(
|
|
23
|
+
memoryId, Date.now(), 'api.ts', 'Fetch user data', 'function fetchUser(id) { return {id}; }', 'claude', 'ts'
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
db.prepare('INSERT INTO runtime_snapshots (id, intent_id, recorded_at, function_name, file_path, success) VALUES (?, ?, ?, ?, ?, ?)').run(
|
|
27
|
+
'snap-1', memoryId, Date.now(), 'fetchUser', 'api.ts', 1
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
db.prepare('INSERT INTO failures (id, intent_id, snapshot_id, failed_at, error_type, error_message, repair_status) VALUES (?, ?, ?, ?, ?, ?, ?)').run(
|
|
31
|
+
'fail-1', memoryId, 'snap-1', Date.now(), 'NetworkError', 'Failed to fetch', 'unresolved'
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// 2. Get the brief
|
|
35
|
+
const brief = await tool.execute({ failure_id: 'fail-1' });
|
|
36
|
+
|
|
37
|
+
console.log('--- REPAIR BRIEF FOR AI ---');
|
|
38
|
+
console.log(brief.repair_context);
|
|
39
|
+
|
|
40
|
+
dbManager.close();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
example().catch(console.error);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { RuntimeObserver } from '../../src/engines/runtime/observer.js';
|
|
2
|
+
import { logger } from '../../src/utils/logger.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example: Explicit Runtime Observation
|
|
6
|
+
* This script demonstrates how to wrap a function to record its behavior.
|
|
7
|
+
*/
|
|
8
|
+
async function example() {
|
|
9
|
+
const observer = new RuntimeObserver(
|
|
10
|
+
'memory-123',
|
|
11
|
+
async (data) => console.log('RECORDED:', data.function_name, 'Success:', data.success),
|
|
12
|
+
async (data) => console.log('FAILURE LOGGED:', data.error_message)
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const add = (a: number, b: number) => {
|
|
16
|
+
if (a < 0) throw new Error('No negatives!');
|
|
17
|
+
return a + b;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const observedAdd = observer.observe(add, 'add');
|
|
21
|
+
|
|
22
|
+
console.log('--- Case 1: Success ---');
|
|
23
|
+
observedAdd(5, 10);
|
|
24
|
+
|
|
25
|
+
console.log('\n--- Case 2: Failure ---');
|
|
26
|
+
try {
|
|
27
|
+
observedAdd(-1, 10);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
// Error is caught by observer and re-thrown
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
example().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opvoid/codememory",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A runtime behavior memory layer for AI-generated code",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"codememory": "dist/bin.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"examples"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup src/index.ts src/bin.ts --format cjs,esm --dts && pnpm run copy-templates",
|
|
17
|
+
"copy-templates": "node -e \"const fs=require('fs'),path=require('path');const src=path.resolve('src/templates'),dst=path.resolve('dist/templates');fs.mkdirSync(dst,{recursive:true});for(const f of fs.readdirSync(src))fs.copyFileSync(path.join(src,f),path.join(dst,f));console.log('Copied templates ->',dst)\"",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:watch": "vitest",
|
|
20
|
+
"lint": "eslint \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
21
|
+
"ci": "pnpm run check:brand && pnpm run typecheck && pnpm run lint && pnpm test && pnpm run build",
|
|
22
|
+
"check:brand": "node scripts/check-brand.js",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"start": "node dist/index.js",
|
|
25
|
+
"postinstall": "node -e \"try{require('better-sqlite3')}catch(e){console.log('Rebuilding better-sqlite3...');require('child_process').execSync('pnpm rebuild better-sqlite3',{stdio:'inherit'})}\""
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"mcp",
|
|
29
|
+
"ai",
|
|
30
|
+
"memory",
|
|
31
|
+
"runtime",
|
|
32
|
+
"behavior"
|
|
33
|
+
],
|
|
34
|
+
"author": "byte271",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.0.1",
|
|
38
|
+
"better-sqlite3": "^11.0.0",
|
|
39
|
+
"zod": "^3.23.8"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/better-sqlite3": "^7.6.10",
|
|
43
|
+
"@types/node": "^20.12.7",
|
|
44
|
+
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
45
|
+
"@typescript-eslint/parser": "^7.18.0",
|
|
46
|
+
"eslint": "^8.57.0",
|
|
47
|
+
"tsup": "^8.0.2",
|
|
48
|
+
"typescript": "^5.4.5",
|
|
49
|
+
"vitest": "^1.5.0"
|
|
50
|
+
},
|
|
51
|
+
"pnpm": {
|
|
52
|
+
"onlyBuiltDependencies": [
|
|
53
|
+
"better-sqlite3"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
}
|