@vuau/agent-memory 0.4.0 → 0.5.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 +24 -22
- package/README.vi.md +24 -22
- package/dist/bin/cli.js +62 -68
- package/dist/index.js +38 -131
- package/docs/ARCHITECTURE.md +15 -24
- package/docs/ARCHITECTURE.vi.md +15 -23
- package/package.json +3 -2
- package/templates/AGENTS.md +11 -14
- package/templates/CUSTOM.md +18 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @vuau/agent-memory
|
|
2
2
|
|
|
3
|
-
Structured AI memory for codebases.
|
|
3
|
+
Structured AI memory for codebases. Uses `AGENTS.md` to work with OpenCode, GitHub Copilot, Cursor, Windsurf, and any AI coding assistant that reads markdown files.
|
|
4
4
|
|
|
5
5
|
**[Tiếng Việt →](./README.vi.md)**
|
|
6
6
|
|
|
@@ -19,28 +19,26 @@ AI coding assistants lose context between sessions. They can't remember:
|
|
|
19
19
|
npx @vuau/agent-memory init
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
That's it. Creates `AGENTS.md` + `.agents/` structure.
|
|
23
|
-
|
|
24
22
|
## What It Creates
|
|
25
23
|
|
|
26
24
|
```
|
|
27
25
|
/ (Project Root)
|
|
28
|
-
├── AGENTS.md
|
|
26
|
+
├── AGENTS.md # Root agent rules
|
|
29
27
|
└── .agents/
|
|
30
|
-
├── MEMORY.md
|
|
31
|
-
├── TASKS.md
|
|
32
|
-
└── spec/
|
|
28
|
+
├── MEMORY.md # Long-term memory (decisions, patterns)
|
|
29
|
+
├── TASKS.md # Working memory (current tasks)
|
|
30
|
+
└── spec/ # Detailed specs (on-demand)
|
|
33
31
|
```
|
|
34
32
|
|
|
35
33
|
## How It Works
|
|
36
34
|
|
|
37
35
|
1. **You run `init`** → Creates `AGENTS.md` + `.agents/` structure
|
|
38
|
-
2. **Agent reads
|
|
36
|
+
2. **Agent reads rules** → Finds documentation map pointing to `.agents/`
|
|
39
37
|
3. **Agent works** → Reads MEMORY.md before implementing, updates TASKS.md
|
|
40
38
|
4. **You approve decision** → Agent writes 1-line entry to MEMORY.md
|
|
41
39
|
5. **Next session** → Agent reads memory, continues where you left off
|
|
42
40
|
|
|
43
|
-
**No plugin required.** The
|
|
41
|
+
**No plugin required.** The rules in `AGENTS.md` instruct the agent what to do.
|
|
44
42
|
|
|
45
43
|
## CLI Options
|
|
46
44
|
|
|
@@ -48,8 +46,8 @@ That's it. Creates `AGENTS.md` + `.agents/` structure.
|
|
|
48
46
|
npx @vuau/agent-memory init [options]
|
|
49
47
|
|
|
50
48
|
Options:
|
|
51
|
-
--force
|
|
52
|
-
--name <n>
|
|
49
|
+
--force Overwrite existing files without asking
|
|
50
|
+
--name <n> Project name (default: from package.json)
|
|
53
51
|
|
|
54
52
|
npx @vuau/agent-memory doctor # Validate structure
|
|
55
53
|
npx @vuau/agent-memory help # Show help
|
|
@@ -57,7 +55,7 @@ npx @vuau/agent-memory help # Show help
|
|
|
57
55
|
|
|
58
56
|
## Memory Protocol
|
|
59
57
|
|
|
60
|
-
Agents follow this protocol (defined in
|
|
58
|
+
Agents follow this protocol (defined in config files):
|
|
61
59
|
|
|
62
60
|
```markdown
|
|
63
61
|
## When to write
|
|
@@ -82,11 +80,11 @@ Agents follow this protocol (defined in AGENTS.md):
|
|
|
82
80
|
|
|
83
81
|
## Architecture
|
|
84
82
|
|
|
85
|
-
###
|
|
83
|
+
### 4-Layer Design
|
|
86
84
|
|
|
87
85
|
| Layer | File | Purpose |
|
|
88
86
|
|-------|------|---------|
|
|
89
|
-
|
|
|
87
|
+
| Router | AGENTS.md | Rules + pointers (~100 lines) |
|
|
90
88
|
| Memory | .agents/MEMORY.md | Curated decisions (1-line each) |
|
|
91
89
|
| Tasks | .agents/TASKS.md | Current work, next steps |
|
|
92
90
|
| Specs | .agents/spec/*.md | Detailed docs (on-demand) |
|
|
@@ -104,17 +102,21 @@ File-based solution:
|
|
|
104
102
|
- Plain markdown (portable, git-versionable, human-readable)
|
|
105
103
|
- No dependencies (works everywhere)
|
|
106
104
|
|
|
107
|
-
##
|
|
105
|
+
## Cross-IDE Compatibility
|
|
106
|
+
|
|
107
|
+
By default, we only scaffold `AGENTS.md`, which is an emerging standard router file.
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
If your tool requires a specific file (e.g. Cursor requires `.cursorrules`, GitHub Copilot requires `.github/copilot-instructions.md`), you can simply symlink or copy `AGENTS.md`:
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
```bash
|
|
112
|
+
# For Cursor
|
|
113
|
+
ln -s AGENTS.md .cursorrules
|
|
114
|
+
|
|
115
|
+
# For GitHub Copilot
|
|
116
|
+
mkdir -p .github && ln -s ../AGENTS.md .github/copilot-instructions.md
|
|
117
|
+
```
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
All tools will read from the same underlying `.agents/` memory structure.
|
|
118
120
|
|
|
119
121
|
## Documentation
|
|
120
122
|
|
package/README.vi.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @vuau/agent-memory
|
|
2
2
|
|
|
3
|
-
Bộ nhớ AI có cấu trúc cho các codebase.
|
|
3
|
+
Bộ nhớ AI có cấu trúc cho các codebase. Sử dụng `AGENTS.md` để hoạt động với OpenCode, GitHub Copilot, Cursor, Windsurf, và bất kỳ AI coding assistant nào đọc markdown files.
|
|
4
4
|
|
|
5
5
|
## Bài toán
|
|
6
6
|
|
|
@@ -17,28 +17,26 @@ AI coding assistants mất bối cảnh giữa các phiên. Họ không thể nh
|
|
|
17
17
|
npx @vuau/agent-memory init
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Đơn giản vậy thôi. Tạo `AGENTS.md` + `.agents/` structure.
|
|
21
|
-
|
|
22
20
|
## Cấu trúc tạo ra
|
|
23
21
|
|
|
24
22
|
```
|
|
25
23
|
/ (Project Root)
|
|
26
|
-
├── AGENTS.md
|
|
24
|
+
├── AGENTS.md # Root agent rules
|
|
27
25
|
└── .agents/
|
|
28
|
-
├── MEMORY.md
|
|
29
|
-
├── TASKS.md
|
|
30
|
-
└── spec/
|
|
26
|
+
├── MEMORY.md # Long-term memory (decisions, patterns)
|
|
27
|
+
├── TASKS.md # Working memory (current tasks)
|
|
28
|
+
└── spec/ # Detailed specs (on-demand)
|
|
31
29
|
```
|
|
32
30
|
|
|
33
31
|
## Cách hoạt động
|
|
34
32
|
|
|
35
33
|
1. **Bạn chạy `init`** → Tạo `AGENTS.md` + `.agents/` structure
|
|
36
|
-
2. **Agent đọc
|
|
34
|
+
2. **Agent đọc rules** → Tìm documentation map trỏ đến `.agents/`
|
|
37
35
|
3. **Agent làm việc** → Đọc MEMORY.md trước khi implement, update TASKS.md
|
|
38
36
|
4. **Bạn approve decision** → Agent ghi 1-line entry vào MEMORY.md
|
|
39
37
|
5. **Phiên tiếp theo** → Agent đọc memory, tiếp tục từ nơi dừng lại
|
|
40
38
|
|
|
41
|
-
**Không cần plugin.**
|
|
39
|
+
**Không cần plugin.** Rules trong `AGENTS.md` hướng dẫn agent phải làm gì.
|
|
42
40
|
|
|
43
41
|
## CLI Options
|
|
44
42
|
|
|
@@ -46,8 +44,8 @@ npx @vuau/agent-memory init
|
|
|
46
44
|
npx @vuau/agent-memory init [options]
|
|
47
45
|
|
|
48
46
|
Options:
|
|
49
|
-
--force
|
|
50
|
-
--name <n>
|
|
47
|
+
--force Ghi đè files có sẵn mà không hỏi
|
|
48
|
+
--name <n> Tên project (mặc định: từ package.json)
|
|
51
49
|
|
|
52
50
|
npx @vuau/agent-memory doctor # Validate structure
|
|
53
51
|
npx @vuau/agent-memory help # Hiện help
|
|
@@ -55,7 +53,7 @@ npx @vuau/agent-memory help # Hiện help
|
|
|
55
53
|
|
|
56
54
|
## Memory Protocol
|
|
57
55
|
|
|
58
|
-
Agents follow protocol này (defined trong
|
|
56
|
+
Agents follow protocol này (defined trong config files):
|
|
59
57
|
|
|
60
58
|
```markdown
|
|
61
59
|
## Khi nào ghi
|
|
@@ -80,11 +78,11 @@ Agents follow protocol này (defined trong AGENTS.md):
|
|
|
80
78
|
|
|
81
79
|
## Kiến trúc
|
|
82
80
|
|
|
83
|
-
### Thiết kế
|
|
81
|
+
### Thiết kế 4-Layer
|
|
84
82
|
|
|
85
83
|
| Layer | File | Mục đích |
|
|
86
84
|
|-------|------|----------|
|
|
87
|
-
|
|
|
85
|
+
| Router | AGENTS.md | Rules + pointers (~100 dòng) |
|
|
88
86
|
| Memory | .agents/MEMORY.md | Curated decisions (1-line each) |
|
|
89
87
|
| Tasks | .agents/TASKS.md | Current work, next steps |
|
|
90
88
|
| Specs | .agents/spec/*.md | Detailed docs (on-demand) |
|
|
@@ -102,17 +100,21 @@ File-based solution:
|
|
|
102
100
|
- Plain markdown (portable, git-versionable, human-readable)
|
|
103
101
|
- Không dependencies (works everywhere)
|
|
104
102
|
|
|
105
|
-
##
|
|
103
|
+
## Cross-IDE Compatibility
|
|
104
|
+
|
|
105
|
+
Mặc định, công cụ chỉ scaffold `AGENTS.md`, một chuẩn router file đang phổ biến.
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
Nếu công cụ của bạn yêu cầu một file cụ thể (vd: Cursor yêu cầu `.cursorrules`, GitHub Copilot yêu cầu `.github/copilot-instructions.md`), bạn có thể đơn giản dùng symlink hoặc copy `AGENTS.md`:
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
```bash
|
|
110
|
+
# Cho Cursor
|
|
111
|
+
ln -s AGENTS.md .cursorrules
|
|
112
|
+
|
|
113
|
+
# Cho GitHub Copilot
|
|
114
|
+
mkdir -p .github && ln -s ../AGENTS.md .github/copilot-instructions.md
|
|
115
|
+
```
|
|
114
116
|
|
|
115
|
-
|
|
117
|
+
Tất cả các công cụ sẽ cùng đọc chung cấu trúc bộ nhớ bên trong thư mục `.agents/`.
|
|
116
118
|
|
|
117
119
|
## Tài liệu
|
|
118
120
|
|
package/dist/bin/cli.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// bin/cli.ts
|
|
4
|
-
import * as readline from "readline";
|
|
5
4
|
import { existsSync as existsSync3 } from "fs";
|
|
6
5
|
import { join as join3 } from "path";
|
|
7
6
|
|
|
8
|
-
// src/
|
|
7
|
+
// src/scaffold.ts
|
|
9
8
|
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
|
|
10
9
|
import { join, resolve, dirname } from "path";
|
|
11
10
|
import { fileURLToPath } from "url";
|
|
12
11
|
|
|
13
|
-
// src/
|
|
12
|
+
// src/types.ts
|
|
14
13
|
var AGENTS_DIR = ".agents";
|
|
15
14
|
var SPEC_DIR = ".agents/spec";
|
|
16
15
|
var MEMORY_FILE = ".agents/MEMORY.md";
|
|
17
16
|
var MEMORY_DETAIL_FILE = ".agents/MEMORY-DETAIL.md";
|
|
18
17
|
var TASKS_FILE = ".agents/TASKS.md";
|
|
18
|
+
var CUSTOM_FILE = ".agents/CUSTOM.md";
|
|
19
19
|
var AGENTS_MD = "AGENTS.md";
|
|
20
20
|
|
|
21
|
-
// src/
|
|
21
|
+
// src/scaffold.ts
|
|
22
22
|
function getTemplatesDir() {
|
|
23
23
|
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
24
24
|
const fromSource = resolve(thisDir, "../../templates");
|
|
@@ -56,17 +56,11 @@ function scaffold(projectDir, options = {}) {
|
|
|
56
56
|
mkdirSync(dir, { recursive: true });
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
writeFileIfNeeded(
|
|
60
|
-
join(projectDir, AGENTS_MD),
|
|
61
|
-
applyVars(readTemplate("AGENTS.md"), vars),
|
|
62
|
-
AGENTS_MD,
|
|
63
|
-
result,
|
|
64
|
-
force
|
|
65
|
-
);
|
|
66
59
|
const coreFiles = [
|
|
67
60
|
{ target: MEMORY_FILE, template: "MEMORY.md" },
|
|
68
61
|
{ target: MEMORY_DETAIL_FILE, template: "MEMORY-DETAIL.md" },
|
|
69
|
-
{ target: TASKS_FILE, template: "TASKS.md" }
|
|
62
|
+
{ target: TASKS_FILE, template: "TASKS.md" },
|
|
63
|
+
{ target: CUSTOM_FILE, template: "CUSTOM.md" }
|
|
70
64
|
];
|
|
71
65
|
for (const { target, template } of coreFiles) {
|
|
72
66
|
const targetPath = join(projectDir, target);
|
|
@@ -83,6 +77,13 @@ function scaffold(projectDir, options = {}) {
|
|
|
83
77
|
writeFileSync(specKeep, "");
|
|
84
78
|
result.created.push(`${SPEC_DIR}/.gitkeep`);
|
|
85
79
|
}
|
|
80
|
+
writeFileIfNeeded(
|
|
81
|
+
join(projectDir, AGENTS_MD),
|
|
82
|
+
applyVars(readTemplate("AGENTS.md"), vars),
|
|
83
|
+
AGENTS_MD,
|
|
84
|
+
result,
|
|
85
|
+
force
|
|
86
|
+
);
|
|
86
87
|
return result;
|
|
87
88
|
}
|
|
88
89
|
function writeFileIfNeeded(targetPath, content, displayName, result, force) {
|
|
@@ -104,14 +105,24 @@ function guessProjectName(dir) {
|
|
|
104
105
|
}
|
|
105
106
|
return dir.split("/").pop() || "Project";
|
|
106
107
|
}
|
|
108
|
+
function updateRouter(projectDir) {
|
|
109
|
+
const targetPath = join(projectDir, AGENTS_MD);
|
|
110
|
+
if (!existsSync(targetPath)) return false;
|
|
111
|
+
const projectName = guessProjectName(projectDir);
|
|
112
|
+
const vars = { PROJECT_NAME: projectName };
|
|
113
|
+
const content = applyVars(readTemplate("AGENTS.md"), vars);
|
|
114
|
+
writeFileSync(targetPath, content);
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
107
117
|
|
|
108
|
-
// src/
|
|
118
|
+
// src/doctor.ts
|
|
109
119
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
110
120
|
import { join as join2 } from "path";
|
|
111
121
|
function doctor(projectDir) {
|
|
112
122
|
const issues = [];
|
|
113
123
|
const required = [
|
|
114
|
-
{ file: AGENTS_MD, desc: "Root
|
|
124
|
+
{ file: AGENTS_MD, desc: "Root router file" },
|
|
125
|
+
{ file: CUSTOM_FILE, desc: "Project specific rules" },
|
|
115
126
|
{ file: MEMORY_FILE, desc: "Long-term memory" },
|
|
116
127
|
{ file: TASKS_FILE, desc: "Working memory" }
|
|
117
128
|
];
|
|
@@ -140,7 +151,7 @@ function doctor(projectDir) {
|
|
|
140
151
|
issues.push({
|
|
141
152
|
level: "warning",
|
|
142
153
|
file: AGENTS_MD,
|
|
143
|
-
message: "Over 150 lines \u2014 consider keeping it concise"
|
|
154
|
+
message: "Over 150 lines \u2014 consider keeping it concise as a router"
|
|
144
155
|
});
|
|
145
156
|
}
|
|
146
157
|
}
|
|
@@ -161,28 +172,13 @@ function doctor(projectDir) {
|
|
|
161
172
|
// bin/cli.ts
|
|
162
173
|
var args = process.argv.slice(2);
|
|
163
174
|
var command = args[0];
|
|
164
|
-
var rl = readline.createInterface({
|
|
165
|
-
input: process.stdin,
|
|
166
|
-
output: process.stdout
|
|
167
|
-
});
|
|
168
|
-
function ask(question) {
|
|
169
|
-
return new Promise((resolve2) => {
|
|
170
|
-
rl.question(question, (answer) => resolve2(answer.trim()));
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
function askYesNo(question, defaultYes = true) {
|
|
174
|
-
const hint = defaultYes ? "(Y/n)" : "(y/N)";
|
|
175
|
-
return ask(`${question} ${hint} `).then((answer) => {
|
|
176
|
-
if (!answer) return defaultYes;
|
|
177
|
-
return answer.toLowerCase().startsWith("y");
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
175
|
function printUsage() {
|
|
181
176
|
console.log(`
|
|
182
177
|
@vuau/agent-memory \u2014 Structured AI memory for codebases
|
|
183
178
|
|
|
184
179
|
Usage:
|
|
185
|
-
agent-memory init [options] Scaffold
|
|
180
|
+
agent-memory init [options] Scaffold .agents/ structure and AGENTS.md
|
|
181
|
+
agent-memory update Update AGENTS.md router to latest version
|
|
186
182
|
agent-memory doctor Validate .agents/ structure
|
|
187
183
|
agent-memory help Show this help
|
|
188
184
|
|
|
@@ -191,14 +187,8 @@ Options (init):
|
|
|
191
187
|
--name <name> Project name (default: from package.json)
|
|
192
188
|
|
|
193
189
|
Examples:
|
|
194
|
-
npx @vuau/agent-memory init
|
|
195
|
-
npx @vuau/agent-memory init --force
|
|
196
|
-
npx @vuau/agent-memory doctor # Check structure
|
|
197
|
-
|
|
198
|
-
AGENTS.md is the universal format supported by 25+ AI coding tools:
|
|
199
|
-
GitHub Copilot, Cursor, Windsurf, VS Code, OpenCode, Codex, Jules,
|
|
200
|
-
Junie, Gemini CLI, Devin, Aider, goose, Factory, Amp, RooCode,
|
|
201
|
-
Zed, Warp, Kilo Code, Phoenix, Semgrep, Ona, UiPath, Augment Code...
|
|
190
|
+
npx @vuau/agent-memory init
|
|
191
|
+
npx @vuau/agent-memory init --force
|
|
202
192
|
`);
|
|
203
193
|
}
|
|
204
194
|
async function runInit() {
|
|
@@ -207,31 +197,9 @@ async function runInit() {
|
|
|
207
197
|
const nameIdx = args.indexOf("--name");
|
|
208
198
|
const projectName = nameIdx !== -1 ? args[nameIdx + 1] : void 0;
|
|
209
199
|
const options = {
|
|
210
|
-
projectName
|
|
200
|
+
projectName,
|
|
201
|
+
force
|
|
211
202
|
};
|
|
212
|
-
if (!force) {
|
|
213
|
-
const filesToCheck = [
|
|
214
|
-
{ path: AGENTS_MD, name: "AGENTS.md" },
|
|
215
|
-
{ path: MEMORY_FILE, name: ".agents/MEMORY.md" },
|
|
216
|
-
{ path: TASKS_FILE, name: ".agents/TASKS.md" }
|
|
217
|
-
];
|
|
218
|
-
const existingFiles = filesToCheck.filter((f) => existsSync3(join3(cwd, f.path)));
|
|
219
|
-
if (existingFiles.length > 0) {
|
|
220
|
-
console.log("\nExisting files found:");
|
|
221
|
-
for (const f of existingFiles) {
|
|
222
|
-
console.log(` - ${f.name}`);
|
|
223
|
-
}
|
|
224
|
-
const overwrite = await askYesNo("\nOverwrite these files?", false);
|
|
225
|
-
if (!overwrite) {
|
|
226
|
-
console.log("\nAborted. Use --force to overwrite without asking.\n");
|
|
227
|
-
rl.close();
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
options.force = true;
|
|
231
|
-
}
|
|
232
|
-
} else {
|
|
233
|
-
options.force = true;
|
|
234
|
-
}
|
|
235
203
|
console.log(`
|
|
236
204
|
Initializing agent memory in ${cwd}...
|
|
237
205
|
`);
|
|
@@ -247,13 +215,35 @@ Initializing agent memory in ${cwd}...
|
|
|
247
215
|
for (const f of result.skipped) {
|
|
248
216
|
console.log(` - ${f}`);
|
|
249
217
|
}
|
|
218
|
+
if (!force) {
|
|
219
|
+
console.log("\nTip: Use --force to overwrite existing files.");
|
|
220
|
+
}
|
|
250
221
|
}
|
|
251
222
|
console.log("\nNext steps:");
|
|
252
223
|
console.log(" 1. Edit AGENTS.md \u2014 add project-specific rules");
|
|
253
224
|
console.log(" 2. Add spec files to .agents/spec/ for detailed documentation");
|
|
254
|
-
console.log(" 3.
|
|
225
|
+
console.log(" 3. Agent will read rules and write to .agents/MEMORY.md automatically");
|
|
226
|
+
console.log("");
|
|
227
|
+
}
|
|
228
|
+
async function runUpdate() {
|
|
229
|
+
const cwd = process.cwd();
|
|
230
|
+
const agentsMdPath = join3(cwd, AGENTS_MD);
|
|
231
|
+
if (!existsSync3(agentsMdPath)) {
|
|
232
|
+
console.error("\u2717 AGENTS.md not found. Please run 'agent-memory init' first.");
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
console.log(`
|
|
236
|
+
Updating ${AGENTS_MD} in ${cwd}...
|
|
237
|
+
`);
|
|
238
|
+
const updated = updateRouter(cwd);
|
|
239
|
+
if (updated) {
|
|
240
|
+
console.log(` \u2713 ${AGENTS_MD} updated to the latest template.`);
|
|
241
|
+
console.log(` (Note: Your custom rules in .agents/CUSTOM.md were not affected)`);
|
|
242
|
+
} else {
|
|
243
|
+
console.error("\u2717 Failed to update AGENTS.md");
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
255
246
|
console.log("");
|
|
256
|
-
rl.close();
|
|
257
247
|
}
|
|
258
248
|
function runDoctor() {
|
|
259
249
|
const cwd = process.cwd();
|
|
@@ -278,7 +268,12 @@ switch (command) {
|
|
|
278
268
|
case "init":
|
|
279
269
|
runInit().catch((err) => {
|
|
280
270
|
console.error("Error:", err.message);
|
|
281
|
-
|
|
271
|
+
process.exit(1);
|
|
272
|
+
});
|
|
273
|
+
break;
|
|
274
|
+
case "update":
|
|
275
|
+
runUpdate().catch((err) => {
|
|
276
|
+
console.error("Error:", err.message);
|
|
282
277
|
process.exit(1);
|
|
283
278
|
});
|
|
284
279
|
break;
|
|
@@ -293,7 +288,6 @@ switch (command) {
|
|
|
293
288
|
case void 0:
|
|
294
289
|
runInit().catch((err) => {
|
|
295
290
|
console.error("Error:", err.message);
|
|
296
|
-
rl.close();
|
|
297
291
|
process.exit(1);
|
|
298
292
|
});
|
|
299
293
|
break;
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/scaffold.ts
|
|
2
2
|
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
|
|
3
3
|
import { join, resolve, dirname } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
|
|
6
|
-
// src/
|
|
6
|
+
// src/types.ts
|
|
7
7
|
var AGENTS_DIR = ".agents";
|
|
8
8
|
var SPEC_DIR = ".agents/spec";
|
|
9
9
|
var MEMORY_FILE = ".agents/MEMORY.md";
|
|
10
10
|
var MEMORY_DETAIL_FILE = ".agents/MEMORY-DETAIL.md";
|
|
11
11
|
var TASKS_FILE = ".agents/TASKS.md";
|
|
12
|
+
var CUSTOM_FILE = ".agents/CUSTOM.md";
|
|
12
13
|
var AGENTS_MD = "AGENTS.md";
|
|
13
14
|
|
|
14
|
-
// src/
|
|
15
|
+
// src/scaffold.ts
|
|
15
16
|
function getTemplatesDir() {
|
|
16
17
|
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
17
18
|
const fromSource = resolve(thisDir, "../../templates");
|
|
@@ -49,17 +50,11 @@ function scaffold(projectDir, options = {}) {
|
|
|
49
50
|
mkdirSync(dir, { recursive: true });
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
|
-
writeFileIfNeeded(
|
|
53
|
-
join(projectDir, AGENTS_MD),
|
|
54
|
-
applyVars(readTemplate("AGENTS.md"), vars),
|
|
55
|
-
AGENTS_MD,
|
|
56
|
-
result,
|
|
57
|
-
force
|
|
58
|
-
);
|
|
59
53
|
const coreFiles = [
|
|
60
54
|
{ target: MEMORY_FILE, template: "MEMORY.md" },
|
|
61
55
|
{ target: MEMORY_DETAIL_FILE, template: "MEMORY-DETAIL.md" },
|
|
62
|
-
{ target: TASKS_FILE, template: "TASKS.md" }
|
|
56
|
+
{ target: TASKS_FILE, template: "TASKS.md" },
|
|
57
|
+
{ target: CUSTOM_FILE, template: "CUSTOM.md" }
|
|
63
58
|
];
|
|
64
59
|
for (const { target, template } of coreFiles) {
|
|
65
60
|
const targetPath = join(projectDir, target);
|
|
@@ -76,6 +71,13 @@ function scaffold(projectDir, options = {}) {
|
|
|
76
71
|
writeFileSync(specKeep, "");
|
|
77
72
|
result.created.push(`${SPEC_DIR}/.gitkeep`);
|
|
78
73
|
}
|
|
74
|
+
writeFileIfNeeded(
|
|
75
|
+
join(projectDir, AGENTS_MD),
|
|
76
|
+
applyVars(readTemplate("AGENTS.md"), vars),
|
|
77
|
+
AGENTS_MD,
|
|
78
|
+
result,
|
|
79
|
+
force
|
|
80
|
+
);
|
|
79
81
|
return result;
|
|
80
82
|
}
|
|
81
83
|
function writeFileIfNeeded(targetPath, content, displayName, result, force) {
|
|
@@ -97,134 +99,41 @@ function guessProjectName(dir) {
|
|
|
97
99
|
}
|
|
98
100
|
return dir.split("/").pop() || "Project";
|
|
99
101
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
const content = readFileSync2(filePath, "utf-8");
|
|
110
|
-
const category = entry.category || "Decisions";
|
|
111
|
-
const line = `- ${entry.date}: ${entry.content}`;
|
|
112
|
-
const categoryHeader = `## ${category}`;
|
|
113
|
-
const headerIndex = content.indexOf(categoryHeader);
|
|
114
|
-
let updated;
|
|
115
|
-
if (headerIndex === -1) {
|
|
116
|
-
updated = content.trimEnd() + `
|
|
117
|
-
|
|
118
|
-
${categoryHeader}
|
|
119
|
-
${line}
|
|
120
|
-
`;
|
|
121
|
-
} else {
|
|
122
|
-
const afterHeader = headerIndex + categoryHeader.length;
|
|
123
|
-
const nextHeaderIndex = content.indexOf("\n## ", afterHeader);
|
|
124
|
-
const insertAt = nextHeaderIndex === -1 ? content.length : nextHeaderIndex;
|
|
125
|
-
const categoryContent = content.slice(afterHeader, insertAt);
|
|
126
|
-
const lastLineEnd = afterHeader + categoryContent.trimEnd().length;
|
|
127
|
-
updated = content.slice(0, lastLineEnd) + "\n" + line + content.slice(lastLineEnd);
|
|
128
|
-
}
|
|
129
|
-
writeFileSync2(filePath, updated);
|
|
130
|
-
}
|
|
131
|
-
function readMemory(projectDir) {
|
|
132
|
-
const filePath = join2(projectDir, MEMORY_FILE);
|
|
133
|
-
if (!existsSync2(filePath)) return {};
|
|
134
|
-
const content = readFileSync2(filePath, "utf-8");
|
|
135
|
-
const categories = {};
|
|
136
|
-
let currentCategory = "_uncategorized";
|
|
137
|
-
for (const line of content.split("\n")) {
|
|
138
|
-
const headerMatch = line.match(/^## (.+)/);
|
|
139
|
-
if (headerMatch) {
|
|
140
|
-
currentCategory = headerMatch[1];
|
|
141
|
-
categories[currentCategory] = categories[currentCategory] || [];
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
if (line.startsWith("- ") && currentCategory) {
|
|
145
|
-
categories[currentCategory] = categories[currentCategory] || [];
|
|
146
|
-
categories[currentCategory].push(line.slice(2));
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return categories;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// src/core/tasks.ts
|
|
153
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
154
|
-
import { join as join3 } from "path";
|
|
155
|
-
function readTasks(projectDir) {
|
|
156
|
-
const filePath = join3(projectDir, TASKS_FILE);
|
|
157
|
-
const result = {
|
|
158
|
-
in_progress: [],
|
|
159
|
-
up_next: [],
|
|
160
|
-
completed: []
|
|
161
|
-
};
|
|
162
|
-
if (!existsSync3(filePath)) return result;
|
|
163
|
-
const content = readFileSync3(filePath, "utf-8");
|
|
164
|
-
let currentSection = null;
|
|
165
|
-
for (const line of content.split("\n")) {
|
|
166
|
-
if (line.startsWith("## In Progress")) {
|
|
167
|
-
currentSection = "in_progress";
|
|
168
|
-
continue;
|
|
169
|
-
}
|
|
170
|
-
if (line.startsWith("## Up Next")) {
|
|
171
|
-
currentSection = "up_next";
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
if (line.startsWith("## Completed")) {
|
|
175
|
-
currentSection = "completed";
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
if (currentSection && line.startsWith("- ")) {
|
|
179
|
-
result[currentSection].push(line.slice(2));
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return result;
|
|
183
|
-
}
|
|
184
|
-
function writeTasks(projectDir, tasks) {
|
|
185
|
-
const filePath = join3(projectDir, TASKS_FILE);
|
|
186
|
-
const content = `# Current Tasks
|
|
187
|
-
|
|
188
|
-
Working memory for cross-session continuity. Update before ending a session.
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
## In Progress
|
|
193
|
-
${tasks.in_progress.map((t) => `- ${t}`).join("\n") || ""}
|
|
194
|
-
|
|
195
|
-
## Up Next
|
|
196
|
-
${tasks.up_next.map((t) => `- ${t}`).join("\n") || ""}
|
|
197
|
-
|
|
198
|
-
## Completed
|
|
199
|
-
${tasks.completed.map((t) => `- ${t}`).join("\n") || ""}
|
|
200
|
-
`;
|
|
201
|
-
writeFileSync3(filePath, content);
|
|
102
|
+
function updateRouter(projectDir) {
|
|
103
|
+
const targetPath = join(projectDir, AGENTS_MD);
|
|
104
|
+
if (!existsSync(targetPath)) return false;
|
|
105
|
+
const projectName = guessProjectName(projectDir);
|
|
106
|
+
const vars = { PROJECT_NAME: projectName };
|
|
107
|
+
const content = applyVars(readTemplate("AGENTS.md"), vars);
|
|
108
|
+
writeFileSync(targetPath, content);
|
|
109
|
+
return true;
|
|
202
110
|
}
|
|
203
111
|
|
|
204
|
-
// src/
|
|
205
|
-
import { existsSync as
|
|
206
|
-
import { join as
|
|
112
|
+
// src/doctor.ts
|
|
113
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
114
|
+
import { join as join2 } from "path";
|
|
207
115
|
function doctor(projectDir) {
|
|
208
116
|
const issues = [];
|
|
209
117
|
const required = [
|
|
210
|
-
{ file: AGENTS_MD, desc: "Root
|
|
118
|
+
{ file: AGENTS_MD, desc: "Root router file" },
|
|
119
|
+
{ file: CUSTOM_FILE, desc: "Project specific rules" },
|
|
211
120
|
{ file: MEMORY_FILE, desc: "Long-term memory" },
|
|
212
121
|
{ file: TASKS_FILE, desc: "Working memory" }
|
|
213
122
|
];
|
|
214
123
|
for (const { file, desc } of required) {
|
|
215
|
-
const filePath =
|
|
216
|
-
if (!
|
|
124
|
+
const filePath = join2(projectDir, file);
|
|
125
|
+
if (!existsSync2(filePath)) {
|
|
217
126
|
issues.push({ level: "error", file, message: `Missing ${desc}` });
|
|
218
127
|
}
|
|
219
128
|
}
|
|
220
129
|
for (const dir of [AGENTS_DIR, SPEC_DIR]) {
|
|
221
|
-
if (!
|
|
130
|
+
if (!existsSync2(join2(projectDir, dir))) {
|
|
222
131
|
issues.push({ level: "error", file: dir, message: "Directory missing" });
|
|
223
132
|
}
|
|
224
133
|
}
|
|
225
|
-
const agentsPath =
|
|
226
|
-
if (
|
|
227
|
-
const content =
|
|
134
|
+
const agentsPath = join2(projectDir, AGENTS_MD);
|
|
135
|
+
if (existsSync2(agentsPath)) {
|
|
136
|
+
const content = readFileSync2(agentsPath, "utf-8");
|
|
228
137
|
if (!content.includes(".agents/")) {
|
|
229
138
|
issues.push({
|
|
230
139
|
level: "warning",
|
|
@@ -236,13 +145,13 @@ function doctor(projectDir) {
|
|
|
236
145
|
issues.push({
|
|
237
146
|
level: "warning",
|
|
238
147
|
file: AGENTS_MD,
|
|
239
|
-
message: "Over 150 lines \u2014 consider keeping it concise"
|
|
148
|
+
message: "Over 150 lines \u2014 consider keeping it concise as a router"
|
|
240
149
|
});
|
|
241
150
|
}
|
|
242
151
|
}
|
|
243
|
-
const memoryPath =
|
|
244
|
-
if (
|
|
245
|
-
const lines =
|
|
152
|
+
const memoryPath = join2(projectDir, MEMORY_FILE);
|
|
153
|
+
if (existsSync2(memoryPath)) {
|
|
154
|
+
const lines = readFileSync2(memoryPath, "utf-8").split("\n").length;
|
|
246
155
|
if (lines > 150) {
|
|
247
156
|
issues.push({
|
|
248
157
|
level: "warning",
|
|
@@ -256,14 +165,12 @@ function doctor(projectDir) {
|
|
|
256
165
|
export {
|
|
257
166
|
AGENTS_DIR,
|
|
258
167
|
AGENTS_MD,
|
|
168
|
+
CUSTOM_FILE,
|
|
259
169
|
MEMORY_DETAIL_FILE,
|
|
260
170
|
MEMORY_FILE,
|
|
261
171
|
SPEC_DIR,
|
|
262
172
|
TASKS_FILE,
|
|
263
|
-
appendMemory,
|
|
264
173
|
doctor,
|
|
265
|
-
readMemory,
|
|
266
|
-
readTasks,
|
|
267
174
|
scaffold,
|
|
268
|
-
|
|
175
|
+
updateRouter
|
|
269
176
|
};
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -168,28 +168,21 @@ This document proposes a generalizable architecture for AI memory across codebas
|
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
|
171
|
-
##
|
|
171
|
+
## Integration Points
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
- Reads: AGENTS.md (via plugin hook)
|
|
175
|
-
- Plugin auto-injects: `.agents/MEMORY.md` context on session start
|
|
176
|
-
- Plugin reminds: Update TASKS.md on session idle
|
|
177
|
-
- Writes: Agent appends to MEMORY.md/TASKS.md/spec/
|
|
173
|
+
By default, we scaffold `AGENTS.md` which acts as the root router for your AI coding assistant. This file contains rules and documentation maps that point to the `.agents/` folder.
|
|
178
174
|
|
|
179
|
-
|
|
180
|
-
- Reads: `.github/copilot-instructions.md` (GitHub convention)
|
|
181
|
-
- copilot-instructions.md = same router format as AGENTS.md
|
|
182
|
-
- Points to `.agents/MEMORY.md` + spec files
|
|
183
|
-
- Writes: User includes `@save memory: <decision>` in chat → agent appends
|
|
175
|
+
If your specific AI tool requires a different file name, you can simply symlink the `AGENTS.md` file:
|
|
184
176
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
-
|
|
188
|
-
- Writes: Agent rules instruct direct append
|
|
177
|
+
```bash
|
|
178
|
+
# Example: For Cursor
|
|
179
|
+
ln -s AGENTS.md .cursorrules
|
|
189
180
|
|
|
190
|
-
|
|
191
|
-
-
|
|
192
|
-
|
|
181
|
+
# Example: For GitHub Copilot
|
|
182
|
+
mkdir -p .github && ln -s ../AGENTS.md .github/copilot-instructions.md
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
This ensures a single source of truth (`AGENTS.md`) is maintained while providing backward compatibility with any tool.
|
|
193
186
|
|
|
194
187
|
---
|
|
195
188
|
|
|
@@ -219,12 +212,12 @@ This document proposes a generalizable architecture for AI memory across codebas
|
|
|
219
212
|
- Keep `.memsearch/memory/` as archive (1 year retention)
|
|
220
213
|
- Delete milvus.db
|
|
221
214
|
|
|
222
|
-
### From .
|
|
215
|
+
### From Monolithic Config Files (e.g. .cursorrules)
|
|
223
216
|
|
|
224
217
|
1. **Extract decisions** → `.agents/MEMORY.md`
|
|
225
218
|
2. **Extract patterns** → `.agents/spec/patterns.md`
|
|
226
219
|
3. **Extract commands** → `AGENTS.md`
|
|
227
|
-
4. **Keep router** →
|
|
220
|
+
4. **Keep router** → Create symlink from your old config file to `AGENTS.md`
|
|
228
221
|
|
|
229
222
|
---
|
|
230
223
|
|
|
@@ -254,10 +247,8 @@ This document proposes a generalizable architecture for AI memory across codebas
|
|
|
254
247
|
## Tooling Support
|
|
255
248
|
|
|
256
249
|
### CLI
|
|
257
|
-
- ✓ `npx @vuau/agent-memory init` — scaffold structure (
|
|
258
|
-
- ✓ `npx @vuau/agent-memory init --
|
|
259
|
-
- ✓ `npx @vuau/agent-memory init --copilot --cursor` — multiple IDEs
|
|
260
|
-
- ✓ `npx @vuau/agent-memory init --all` — all IDEs
|
|
250
|
+
- ✓ `npx @vuau/agent-memory init` — scaffold structure (`AGENTS.md` + `.agents/`)
|
|
251
|
+
- ✓ `npx @vuau/agent-memory init --force` — overwrite existing files
|
|
261
252
|
- ✓ `npx @vuau/agent-memory doctor` — validate structure
|
|
262
253
|
- Planned: ✗ `report` — generate memory stats, archival suggestions
|
|
263
254
|
|
package/docs/ARCHITECTURE.vi.md
CHANGED
|
@@ -168,27 +168,21 @@ Tài liệu này đề xuất kiến trúc khả năng skalabiliti cho AI memory
|
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
|
171
|
-
##
|
|
171
|
+
## Điểm Tích Hợp
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
- Reads: `AGENTS.md` (native)
|
|
175
|
-
- Agents follow rules trong AGENTS.md
|
|
176
|
-
- Writes: Agent appends đến MEMORY.md/TASKS.md/spec/
|
|
173
|
+
Mặc định, chúng tôi scaffold `AGENTS.md` hoạt động như root router cho AI coding assistant của bạn. File này chứa các rules và documentation maps trỏ đến thư mục `.agents/`.
|
|
177
174
|
|
|
178
|
-
|
|
179
|
-
- Reads: `.github/copilot-instructions.md` (GitHub convention)
|
|
180
|
-
- copilot-instructions.md = cùng router format với AGENTS.md
|
|
181
|
-
- Points đến `.agents/MEMORY.md` + spec files
|
|
182
|
-
- Writes: Agent follows rules → appends khi appropriate
|
|
175
|
+
Nếu công cụ AI cụ thể của bạn yêu cầu một tên file khác, bạn có thể dễ dàng dùng symlink file `AGENTS.md`:
|
|
183
176
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
-
|
|
187
|
-
- Writes: Agent rules instruct direct append
|
|
177
|
+
```bash
|
|
178
|
+
# Ví dụ: Cho Cursor
|
|
179
|
+
ln -s AGENTS.md .cursorrules
|
|
188
180
|
|
|
189
|
-
|
|
190
|
-
-
|
|
191
|
-
|
|
181
|
+
# Ví dụ: Cho GitHub Copilot
|
|
182
|
+
mkdir -p .github && ln -s ../AGENTS.md .github/copilot-instructions.md
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Điều này đảm bảo single source of truth (`AGENTS.md`) được duy trì trong khi cung cấp khả năng tương thích ngược với mọi công cụ.
|
|
192
186
|
|
|
193
187
|
---
|
|
194
188
|
|
|
@@ -218,12 +212,12 @@ Tài liệu này đề xuất kiến trúc khả năng skalabiliti cho AI memory
|
|
|
218
212
|
- Keep `.memsearch/memory/` như archive (1 year retention)
|
|
219
213
|
- Delete milvus.db
|
|
220
214
|
|
|
221
|
-
### Từ
|
|
215
|
+
### Từ Monolithic Config Files (vd: .cursorrules)
|
|
222
216
|
|
|
223
217
|
1. **Extract decisions** → `.agents/MEMORY.md`
|
|
224
218
|
2. **Extract patterns** → `.agents/spec/patterns.md`
|
|
225
219
|
3. **Extract commands** → `AGENTS.md`
|
|
226
|
-
4. **Keep router** →
|
|
220
|
+
4. **Keep router** → Tạo symlink từ config file cũ của bạn trỏ tới `AGENTS.md`
|
|
227
221
|
|
|
228
222
|
---
|
|
229
223
|
|
|
@@ -253,10 +247,8 @@ Tài liệu này đề xuất kiến trúc khả năng skalabiliti cho AI memory
|
|
|
253
247
|
## Công cụ Support
|
|
254
248
|
|
|
255
249
|
### CLI
|
|
256
|
-
- ✓ `npx @vuau/agent-memory init` — scaffold structure (
|
|
257
|
-
- ✓ `npx @vuau/agent-memory init --
|
|
258
|
-
- ✓ `npx @vuau/agent-memory init --copilot --cursor` — nhiều IDEs
|
|
259
|
-
- ✓ `npx @vuau/agent-memory init --all` — tất cả IDEs
|
|
250
|
+
- ✓ `npx @vuau/agent-memory init` — scaffold structure (`AGENTS.md` + `.agents/`)
|
|
251
|
+
- ✓ `npx @vuau/agent-memory init --force` — ghi đè files có sẵn
|
|
260
252
|
- ✓ `npx @vuau/agent-memory doctor` — validate structure
|
|
261
253
|
- Planned: ✗ `report` — generate memory stats, archival suggestions
|
|
262
254
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vuau/agent-memory",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Structured AI memory for codebases —
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Structured AI memory for codebases — scaffolding CLI for OpenCode, Copilot, Cursor, Windsurf",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"prepublishOnly": "npm run build"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
+
"@types/node": "^25.6.0",
|
|
24
25
|
"tsup": "^8.0.0",
|
|
25
26
|
"typescript": "^6.0.3"
|
|
26
27
|
},
|
package/templates/AGENTS.md
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
# {{PROJECT_NAME}} - AGENTS
|
|
2
2
|
|
|
3
|
-
Router file for AI agents.
|
|
3
|
+
Router file for AI agents.
|
|
4
|
+
|
|
5
|
+
> **Note**: This file is automatically managed by `@vuau/agent-memory`.
|
|
6
|
+
> Do not add project-specific rules here, as they may be overwritten by `agent-memory update`.
|
|
7
|
+
>
|
|
8
|
+
> 👉 **For project-specific rules, context, and document mapping, see `.agents/CUSTOM.md`**
|
|
4
9
|
|
|
5
10
|
## Priority
|
|
6
11
|
1. User request first.
|
|
7
|
-
2.
|
|
8
|
-
3.
|
|
9
|
-
4.
|
|
10
|
-
|
|
11
|
-
## Documentation Map
|
|
12
|
-
|
|
13
|
-
| Task | Spec File |
|
|
14
|
-
|------|-----------|
|
|
15
|
-
| Past decisions (1-line) | `.agents/MEMORY.md` |
|
|
16
|
-
| Past decisions (full context) | `.agents/MEMORY-DETAIL.md` |
|
|
17
|
-
| Current work in progress | `.agents/TASKS.md` |
|
|
18
|
-
|
|
19
|
-
> Add your own spec files to `.agents/spec/` and reference them here.
|
|
12
|
+
2. The rules in `.agents/CUSTOM.md`.
|
|
13
|
+
3. This `AGENTS.md`.
|
|
14
|
+
4. Spec files in `.agents/spec/`.
|
|
15
|
+
5. If conflict remains, choose smallest safe change and state assumption.
|
|
20
16
|
|
|
21
17
|
## Memory Protocol
|
|
22
18
|
|
|
@@ -41,5 +37,6 @@ Before ending a session with unfinished work, move items to `## In Progress` or
|
|
|
41
37
|
|
|
42
38
|
## Response Style
|
|
43
39
|
- Concise, concrete, implementation-focused.
|
|
40
|
+
- Propose the simplest solution first (KISS & YAGNI) before writing code.
|
|
44
41
|
- If uncertain, say `I don't know`, then give fastest verification step.
|
|
45
42
|
- Do not invent files, APIs, or command outputs.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Project Rules & Document Map
|
|
2
|
+
|
|
3
|
+
This file contains project-specific rules, architectural decisions, and document mappings.
|
|
4
|
+
Feel free to modify this file to suit your project's needs.
|
|
5
|
+
|
|
6
|
+
## Documentation Map
|
|
7
|
+
|
|
8
|
+
| Task | Spec File |
|
|
9
|
+
|------|-----------|
|
|
10
|
+
| Past decisions (1-line) | `.agents/MEMORY.md` |
|
|
11
|
+
| Past decisions (full context) | `.agents/MEMORY-DETAIL.md` |
|
|
12
|
+
| Current work in progress | `.agents/TASKS.md` |
|
|
13
|
+
|
|
14
|
+
> Add your own spec files to `.agents/spec/` and reference them here.
|
|
15
|
+
|
|
16
|
+
## Custom Rules
|
|
17
|
+
|
|
18
|
+
- Add your project-specific rules here.
|