repo-memory-workflow 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 +239 -0
- package/bin/repo-memory-workflow.js +86 -0
- package/package.json +17 -0
- package/templates/ai/CONTEXT.md +39 -0
- package/templates/ai/DECISIONS.md +4 -0
- package/templates/ai/LOG.md +4 -0
- package/templates/ai/PROMPT_START.md +18 -0
- package/templates/ai/START.md +137 -0
- package/templates/ai/TASK.md +24 -0
- package/templates/ai/TASKING_GUIDE.md +29 -0
- package/templates/ai/make_context.py +194 -0
- package/templates/ai/tasks/000_retrofit_existing_work.md +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
repo-memory-workflow
|
|
2
|
+
|
|
3
|
+
A lightweight workflow template for managing AI-assisted development in a repository.
|
|
4
|
+
|
|
5
|
+
It helps you:
|
|
6
|
+
|
|
7
|
+
split requirements into tasks
|
|
8
|
+
|
|
9
|
+
keep decisions and progress recorded
|
|
10
|
+
|
|
11
|
+
generate a compact context pack for LLMs / agents
|
|
12
|
+
|
|
13
|
+
Features
|
|
14
|
+
|
|
15
|
+
Simple .ai/ folder structure
|
|
16
|
+
|
|
17
|
+
3 common scenarios supported:
|
|
18
|
+
|
|
19
|
+
New requirement (planning + task split)
|
|
20
|
+
|
|
21
|
+
Continue work (execute next actions)
|
|
22
|
+
|
|
23
|
+
Retrofit existing work (backfill docs and tasks)
|
|
24
|
+
|
|
25
|
+
One command to initialize templates in any repo
|
|
26
|
+
|
|
27
|
+
Optional context pack generator (make_context.py)
|
|
28
|
+
|
|
29
|
+
Install (Local)
|
|
30
|
+
git clone <this-repo>
|
|
31
|
+
cd repo-memory-workflow
|
|
32
|
+
npm link
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
If you see permission issues on macOS:
|
|
36
|
+
|
|
37
|
+
sudo npm link
|
|
38
|
+
|
|
39
|
+
Usage
|
|
40
|
+
1) Initialize in any project
|
|
41
|
+
|
|
42
|
+
Go to your target repo root:
|
|
43
|
+
|
|
44
|
+
repo-memory-workflow init
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
This will create:
|
|
48
|
+
|
|
49
|
+
.ai/
|
|
50
|
+
START.md
|
|
51
|
+
TASK.md
|
|
52
|
+
CONTEXT.md
|
|
53
|
+
DECISIONS.md
|
|
54
|
+
LOG.md
|
|
55
|
+
TASKING_GUIDE.md
|
|
56
|
+
make_context.py
|
|
57
|
+
tasks/
|
|
58
|
+
|
|
59
|
+
Workflow (Recommended)
|
|
60
|
+
Scenario A — New Requirement (Task Planning)
|
|
61
|
+
|
|
62
|
+
Open:
|
|
63
|
+
|
|
64
|
+
.ai/START.md
|
|
65
|
+
|
|
66
|
+
.ai/TASKING_GUIDE.md
|
|
67
|
+
|
|
68
|
+
Then:
|
|
69
|
+
|
|
70
|
+
switch to planning mode (in Cursor / ChatGPT / any agent)
|
|
71
|
+
|
|
72
|
+
split the requirement into 3~10 tasks
|
|
73
|
+
|
|
74
|
+
update .ai/TASK.md with the task list
|
|
75
|
+
|
|
76
|
+
Scenario B — Continue Work (Execute Tasks)
|
|
77
|
+
|
|
78
|
+
Open:
|
|
79
|
+
|
|
80
|
+
.ai/START.md
|
|
81
|
+
|
|
82
|
+
Then:
|
|
83
|
+
|
|
84
|
+
continue the primary active task
|
|
85
|
+
|
|
86
|
+
execute from Next actions step 1
|
|
87
|
+
|
|
88
|
+
Scenario C — Retrofit (Half Done, Need Backfill)
|
|
89
|
+
|
|
90
|
+
If the work is already half done and no workflow docs exist:
|
|
91
|
+
|
|
92
|
+
open .ai/START.md
|
|
93
|
+
|
|
94
|
+
enter retrofit mode
|
|
95
|
+
|
|
96
|
+
run Task 000 (.ai/tasks/000_retrofit_existing_work.md)
|
|
97
|
+
|
|
98
|
+
backfill decisions/log/context first
|
|
99
|
+
|
|
100
|
+
split the remaining work into tasks
|
|
101
|
+
|
|
102
|
+
Context Pack (Optional)
|
|
103
|
+
|
|
104
|
+
This repo includes a helper script:
|
|
105
|
+
|
|
106
|
+
python3 .ai/make_context.py
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
It will generate a compact file (example):
|
|
110
|
+
|
|
111
|
+
.ai/CONTEXT_PACK.md
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
This file is meant to be pasted into Cursor / ChatGPT as the working context.
|
|
115
|
+
|
|
116
|
+
Why this exists
|
|
117
|
+
|
|
118
|
+
When using LLMs to help coding, the biggest problem is usually:
|
|
119
|
+
|
|
120
|
+
requirements are unclear
|
|
121
|
+
|
|
122
|
+
context is missing
|
|
123
|
+
|
|
124
|
+
progress and decisions are not tracked
|
|
125
|
+
|
|
126
|
+
This workflow makes the process more repeatable and less chaotic.
|
|
127
|
+
|
|
128
|
+
License
|
|
129
|
+
|
|
130
|
+
MIT
|
|
131
|
+
|
|
132
|
+
中文说明
|
|
133
|
+
|
|
134
|
+
这是一个用于 AI 辅助开发 的仓库工作流模板。
|
|
135
|
+
|
|
136
|
+
它的目标是:让你在写代码时,能更稳定地让 AI 跟上进度,并且把需求、任务、决策、日志沉淀下来。
|
|
137
|
+
|
|
138
|
+
功能
|
|
139
|
+
|
|
140
|
+
提供统一的 .ai/ 目录结构
|
|
141
|
+
|
|
142
|
+
覆盖 3 个常见开发场景:
|
|
143
|
+
|
|
144
|
+
新需求:拆分任务并规划
|
|
145
|
+
|
|
146
|
+
继续开发:按 Next actions 执行
|
|
147
|
+
|
|
148
|
+
半路接入:补齐文档后继续拆分
|
|
149
|
+
|
|
150
|
+
一条命令初始化模板
|
|
151
|
+
|
|
152
|
+
可选的 make_context.py 自动生成上下文包
|
|
153
|
+
|
|
154
|
+
安装(本地)
|
|
155
|
+
git clone <this-repo>
|
|
156
|
+
cd repo-memory-workflow
|
|
157
|
+
npm link
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
如果 macOS 报权限问题:
|
|
161
|
+
|
|
162
|
+
sudo npm link
|
|
163
|
+
|
|
164
|
+
使用方法
|
|
165
|
+
1)在任意项目中初始化
|
|
166
|
+
|
|
167
|
+
进入你要使用的项目根目录:
|
|
168
|
+
|
|
169
|
+
repo-memory-workflow init
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
会生成:
|
|
173
|
+
|
|
174
|
+
.ai/
|
|
175
|
+
START.md
|
|
176
|
+
TASK.md
|
|
177
|
+
CONTEXT.md
|
|
178
|
+
DECISIONS.md
|
|
179
|
+
LOG.md
|
|
180
|
+
TASKING_GUIDE.md
|
|
181
|
+
make_context.py
|
|
182
|
+
tasks/
|
|
183
|
+
|
|
184
|
+
推荐流程
|
|
185
|
+
场景 1:新需求(拆分任务)
|
|
186
|
+
|
|
187
|
+
打开:
|
|
188
|
+
|
|
189
|
+
.ai/START.md
|
|
190
|
+
|
|
191
|
+
.ai/TASKING_GUIDE.md
|
|
192
|
+
|
|
193
|
+
然后:
|
|
194
|
+
|
|
195
|
+
进入 planning mode
|
|
196
|
+
|
|
197
|
+
把需求拆成 3~10 个 tasks
|
|
198
|
+
|
|
199
|
+
更新 .ai/TASK.md
|
|
200
|
+
|
|
201
|
+
场景 2:继续开发(执行任务)
|
|
202
|
+
|
|
203
|
+
打开:
|
|
204
|
+
|
|
205
|
+
.ai/START.md
|
|
206
|
+
|
|
207
|
+
然后:
|
|
208
|
+
|
|
209
|
+
继续 Primary active task
|
|
210
|
+
|
|
211
|
+
从 Next actions 的第 1 步开始执行
|
|
212
|
+
|
|
213
|
+
场景 3:半路接入(补档)
|
|
214
|
+
|
|
215
|
+
如果项目已经做了一半,但之前没走流程:
|
|
216
|
+
|
|
217
|
+
打开 .ai/START.md
|
|
218
|
+
|
|
219
|
+
进入 retrofit mode
|
|
220
|
+
|
|
221
|
+
执行 Task 000(.ai/tasks/000_retrofit_existing_work.md)
|
|
222
|
+
|
|
223
|
+
先补齐日志/决策/上下文
|
|
224
|
+
|
|
225
|
+
再拆分剩余任务继续推进
|
|
226
|
+
|
|
227
|
+
Context Pack(可选)
|
|
228
|
+
|
|
229
|
+
执行:
|
|
230
|
+
|
|
231
|
+
python3 .ai/make_context.py
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
会生成:
|
|
235
|
+
|
|
236
|
+
.ai/CONTEXT_PACK.md
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
这个文件可以直接贴进 Cursor / ChatGPT,当作当前任务上下文。
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
function exists(p) {
|
|
7
|
+
try { fs.accessSync(p); return true; } catch { return false; }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function mkdirp(p) {
|
|
11
|
+
fs.mkdirSync(p, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function copyDir(src, dst) {
|
|
15
|
+
mkdirp(dst);
|
|
16
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
17
|
+
for (const e of entries) {
|
|
18
|
+
const s = path.join(src, e.name);
|
|
19
|
+
const d = path.join(dst, e.name);
|
|
20
|
+
if (e.isDirectory()) copyDir(s, d);
|
|
21
|
+
else fs.copyFileSync(s, d);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function appendGitignore(root) {
|
|
26
|
+
const gi = path.join(root, ".gitignore");
|
|
27
|
+
const marker = "# repo-memory-workflow generated";
|
|
28
|
+
const rules = [marker, ".ai/CONTEXT_PACK.md", ""].join("\n");
|
|
29
|
+
|
|
30
|
+
if (!exists(gi)) {
|
|
31
|
+
fs.writeFileSync(gi, rules, "utf8");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const cur = fs.readFileSync(gi, "utf8");
|
|
35
|
+
if (cur.includes(marker) || cur.includes(".ai/CONTEXT_PACK.md")) return;
|
|
36
|
+
fs.appendFileSync(gi, "\n" + rules, "utf8");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function help() {
|
|
40
|
+
console.log(`
|
|
41
|
+
repo-memory-workflow
|
|
42
|
+
|
|
43
|
+
Usage:
|
|
44
|
+
repo-memory-workflow init # create .ai/ workflow templates in current project root
|
|
45
|
+
`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function init(root) {
|
|
49
|
+
const templatesRoot = path.join(__dirname, "..", "templates", "ai");
|
|
50
|
+
const aiDir = path.join(root, ".ai");
|
|
51
|
+
|
|
52
|
+
if (!exists(templatesRoot)) {
|
|
53
|
+
console.error("❌ Missing templates/ai in this package.");
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (exists(aiDir)) {
|
|
58
|
+
console.log("⚠️ .ai/ already exists. Skipping creation.");
|
|
59
|
+
} else {
|
|
60
|
+
copyDir(templatesRoot, aiDir);
|
|
61
|
+
console.log("✅ Created .ai/ templates");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
appendGitignore(root);
|
|
65
|
+
console.log("✅ Updated .gitignore (ignore .ai/CONTEXT_PACK.md)");
|
|
66
|
+
console.log("Next: open .ai/START.md");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function main() {
|
|
70
|
+
const args = process.argv.slice(2);
|
|
71
|
+
const sub = args[0];
|
|
72
|
+
|
|
73
|
+
if (!sub || sub === "-h" || sub === "--help" || sub === "help") {
|
|
74
|
+
return help();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (sub === "init") {
|
|
78
|
+
return init(process.cwd());
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.error(`Unknown command: ${sub}`);
|
|
82
|
+
help();
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "repo-memory-workflow",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Git-native, editor-agnostic AI workflow templates (.ai/) + context pack generator",
|
|
5
|
+
"bin": {
|
|
6
|
+
"repo-memory-workflow": "bin/repo-memory-workflow.js"
|
|
7
|
+
},
|
|
8
|
+
"type": "commonjs",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"src",
|
|
13
|
+
"templates",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Project AI Context (Editor-agnostic)
|
|
2
|
+
|
|
3
|
+
## How to continue work
|
|
4
|
+
1) Always read: .ai/TASK.md
|
|
5
|
+
2) Then read the Active task file referenced in TASK.md (under .ai/tasks/)
|
|
6
|
+
3) Follow "Next actions" strictly. If anything is unclear, write it to "Open Questions" in the Active task.
|
|
7
|
+
4) After each meaningful step:
|
|
8
|
+
- Update .ai/TASK.md (Current state + Next actions)
|
|
9
|
+
- Append key decisions to .ai/DECISIONS.md (only irreversible or important choices)
|
|
10
|
+
- Append progress logs to .ai/LOG.md (optional but recommended)
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
- Do NOT guess. If context is missing, write "Open Questions" and propose 2-3 options.
|
|
14
|
+
- Prefer minimal diffs and incremental commits.
|
|
15
|
+
- If conversation context is low, rely on files in .ai/ as the source of truth.
|
|
16
|
+
|
|
17
|
+
If the feature was already partially implemented WITHOUT this `.ai/` workflow,
|
|
18
|
+
or conversation context is lost (new editor window / new teammate),
|
|
19
|
+
you MUST create and complete:
|
|
20
|
+
|
|
21
|
+
- `.ai/tasks/000_retrofit_existing_work.md`
|
|
22
|
+
|
|
23
|
+
before continuing implementation.
|
|
24
|
+
|
|
25
|
+
Do NOT guess missing context.
|
|
26
|
+
Use repo state as source-of-truth and record unknowns in "Open questions".
|
|
27
|
+
|
|
28
|
+
## Output conventions
|
|
29
|
+
- Use checklists for TODO.
|
|
30
|
+
- Keep TASK.md short and current.
|
|
31
|
+
- Keep DECISIONS.md concise and dated.
|
|
32
|
+
|
|
33
|
+
## Logging rule (MUST)
|
|
34
|
+
After each meaningful step, append a log entry to `.ai/LOG.md`.
|
|
35
|
+
Never overwrite existing logs. Always append.
|
|
36
|
+
Each log entry must include:
|
|
37
|
+
- What was done
|
|
38
|
+
- Files changed
|
|
39
|
+
- Next step
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# AI Workflow Start Prompt (Repo Memory)
|
|
2
|
+
|
|
3
|
+
You must follow this repo workflow strictly:
|
|
4
|
+
|
|
5
|
+
1) Always read:
|
|
6
|
+
- .ai/CONTEXT.md
|
|
7
|
+
- .ai/TASK.md
|
|
8
|
+
- The Active task file referenced in TASK.md
|
|
9
|
+
|
|
10
|
+
2) Only execute the "Next actions" in the Active task.
|
|
11
|
+
- If anything is unclear, write it to "Open questions" instead of guessing.
|
|
12
|
+
|
|
13
|
+
3) After each meaningful step, you MUST update:
|
|
14
|
+
- The Active task card (.ai/tasks/xxx.md): Current state / Done / Next actions
|
|
15
|
+
- .ai/LOG.md: append a short log entry (never overwrite)
|
|
16
|
+
- .ai/DECISIONS.md: only if architecture/schema/API contract changed
|
|
17
|
+
|
|
18
|
+
4) Keep diffs minimal and incremental.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# START (Repo Memory Workflow)
|
|
2
|
+
|
|
3
|
+
This repo uses `.ai/` as the editor-agnostic source-of-truth for AI work.
|
|
4
|
+
|
|
5
|
+
Supported editors/tools:
|
|
6
|
+
- Cursor
|
|
7
|
+
- VSCode (Codex)
|
|
8
|
+
- Antigravity
|
|
9
|
+
- Any CLI AI client that can read repo files
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 0) Golden rules (MUST)
|
|
14
|
+
|
|
15
|
+
1) Always read:
|
|
16
|
+
- `.ai/CONTEXT.md`
|
|
17
|
+
- `.ai/TASK.md`
|
|
18
|
+
- The Primary active task card referenced in TASK.md
|
|
19
|
+
|
|
20
|
+
2) Do NOT guess.
|
|
21
|
+
- If context is missing, write it into "Open questions".
|
|
22
|
+
|
|
23
|
+
3) After each meaningful step, ALWAYS update:
|
|
24
|
+
- The active task card (Current state + Next actions)
|
|
25
|
+
- `.ai/LOG.md` (append only)
|
|
26
|
+
- `.ai/DECISIONS.md` (only if architecture/schema/API contract changed)
|
|
27
|
+
|
|
28
|
+
4) Keep changes minimal and incremental.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 1) Normal workflow: NEW requirement from scratch
|
|
33
|
+
|
|
34
|
+
### Step 1: Split requirement into tasks (Planning mode)
|
|
35
|
+
Ask AI:
|
|
36
|
+
|
|
37
|
+
"Read `.ai/CONTEXT.md` and `.ai/TASKING_GUIDE.md`.
|
|
38
|
+
Split the following requirement into 3~10 task cards under `.ai/tasks/`,
|
|
39
|
+
and update `.ai/TASK.md` accordingly.
|
|
40
|
+
Do NOT implement code yet."
|
|
41
|
+
|
|
42
|
+
Then paste the requirement.
|
|
43
|
+
|
|
44
|
+
### Step 2: Execute tasks (Implementation mode)
|
|
45
|
+
Ask AI:
|
|
46
|
+
|
|
47
|
+
"Read `.ai/CONTEXT.md`, `.ai/TASK.md`, and the Primary active task card.
|
|
48
|
+
Start executing ONLY the 'Next actions' in the Primary active task.
|
|
49
|
+
After each step, update task card and append `.ai/LOG.md`."
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 2) Workflow when chat context is full (Switch window safely)
|
|
54
|
+
|
|
55
|
+
When the chat is almost full, do this BEFORE switching:
|
|
56
|
+
|
|
57
|
+
1) Update the active task card:
|
|
58
|
+
- Current state: what is done
|
|
59
|
+
- Next actions: what remains (<=7 items)
|
|
60
|
+
|
|
61
|
+
2) Append one entry to `.ai/LOG.md`:
|
|
62
|
+
- What was done
|
|
63
|
+
- Which files changed
|
|
64
|
+
- What is the next step
|
|
65
|
+
|
|
66
|
+
3) Generate a context pack:
|
|
67
|
+
- Run: `python3 .ai/make_context.py`
|
|
68
|
+
- This will produce: `.ai/CONTEXT_PACK.md`
|
|
69
|
+
|
|
70
|
+
In the NEW window/chat, ask AI:
|
|
71
|
+
|
|
72
|
+
"Read `.ai/CONTEXT_PACK.md` first.
|
|
73
|
+
Continue from the Primary active task 'Next actions'.
|
|
74
|
+
After each step, update task card and append `.ai/LOG.md`."
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 3) Recovery workflow: requirement already half-done WITHOUT `.ai/` (Retrofit mode)
|
|
79
|
+
|
|
80
|
+
This is REQUIRED when:
|
|
81
|
+
- A teammate already implemented part of the feature without this workflow
|
|
82
|
+
- Chat history is lost
|
|
83
|
+
- The project is messy and needs task recovery
|
|
84
|
+
|
|
85
|
+
### Step 1: Create Task 000 (Retrofit)
|
|
86
|
+
Create this file if not present:
|
|
87
|
+
|
|
88
|
+
- `.ai/tasks/000_retrofit_existing_work.md`
|
|
89
|
+
|
|
90
|
+
Then put Task 000 into `.ai/TASK.md` -> Active as the Primary active task.
|
|
91
|
+
|
|
92
|
+
### Step 2: Run context pack
|
|
93
|
+
Run:
|
|
94
|
+
`python3 .ai/make_context.py`
|
|
95
|
+
|
|
96
|
+
### Step 3: Ask AI to recover state FIRST (do not code yet)
|
|
97
|
+
Ask AI:
|
|
98
|
+
|
|
99
|
+
"Enter retrofit mode.
|
|
100
|
+
Read `.ai/CONTEXT_PACK.md`.
|
|
101
|
+
Execute Task 000 ONLY:
|
|
102
|
+
- Summarize what is already done from repo state
|
|
103
|
+
- Append recovery summary into `.ai/LOG.md`
|
|
104
|
+
- Split remaining work into 3~10 tasks
|
|
105
|
+
- Update `.ai/TASK.md`
|
|
106
|
+
Do NOT implement remaining tasks yet."
|
|
107
|
+
|
|
108
|
+
### Step 4: After Task 000 is done
|
|
109
|
+
Move Task 000 to Done.
|
|
110
|
+
Then start implementing the remaining tasks normally.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 4) Teammate handoff workflow (Someone continues your unfinished work)
|
|
115
|
+
|
|
116
|
+
Teammate should:
|
|
117
|
+
|
|
118
|
+
1) Pull latest code
|
|
119
|
+
2) Run: `python3 .ai/make_context.py`
|
|
120
|
+
3) Ask AI:
|
|
121
|
+
|
|
122
|
+
"Read `.ai/CONTEXT_PACK.md`.
|
|
123
|
+
Continue from the Primary active task.
|
|
124
|
+
Follow Next actions strictly.
|
|
125
|
+
After each step, update task card and append `.ai/LOG.md`."
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 5) Where to put extra documents (3rd-party docs, screenshots, rules)
|
|
130
|
+
|
|
131
|
+
Store external inputs under:
|
|
132
|
+
- `.ai/resources/`
|
|
133
|
+
|
|
134
|
+
Rules:
|
|
135
|
+
- Keep original files if possible
|
|
136
|
+
- Add a short markdown summary next to it
|
|
137
|
+
- Tasks should reference resource files instead of copying large text
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# TASK
|
|
2
|
+
|
|
3
|
+
## Task board
|
|
4
|
+
- Active:
|
|
5
|
+
- .ai/tasks/000_retrofit_existing_work.md
|
|
6
|
+
- Queued:
|
|
7
|
+
- (none)
|
|
8
|
+
- Blocked:
|
|
9
|
+
- (none)
|
|
10
|
+
- Done:
|
|
11
|
+
- (none)
|
|
12
|
+
|
|
13
|
+
## Objective
|
|
14
|
+
- This repo uses `.ai/` as the editor-agnostic source-of-truth for AI work.
|
|
15
|
+
- Track active tasks, queued tasks, and completed work here.
|
|
16
|
+
|
|
17
|
+
## Current state
|
|
18
|
+
- `.ai/` workflow initialized.
|
|
19
|
+
- No project-specific tasks have been created yet.
|
|
20
|
+
|
|
21
|
+
## Next actions
|
|
22
|
+
- [ ] If this repo already has half-done work: run Retrofit (Task 000)
|
|
23
|
+
- [ ] If this is a new requirement: ask AI to split it into 3~10 tasks under `.ai/tasks/`
|
|
24
|
+
- [ ] Move tasks between Active / Queued / Done as progress is made
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# TASKING GUIDE (How to create tasks)
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
Turn a new requirement into a set of executable task cards under `.ai/tasks/`.
|
|
5
|
+
|
|
6
|
+
## Rules
|
|
7
|
+
1) Always create 3~10 tasks, do NOT create 1 giant task.
|
|
8
|
+
2) Each task must have:
|
|
9
|
+
- Objective
|
|
10
|
+
- Context / Inputs
|
|
11
|
+
- Acceptance criteria
|
|
12
|
+
- Current state
|
|
13
|
+
- Next actions (<= 7 items, ordered, executable)
|
|
14
|
+
- Open questions (if any)
|
|
15
|
+
3) Prefer tasks that can be parallelized.
|
|
16
|
+
4) Do NOT include large raw docs in tasks. Use `.ai/resources/` references.
|
|
17
|
+
5) If a task depends on another, mark it in the task as "Blocked by".
|
|
18
|
+
|
|
19
|
+
## Naming
|
|
20
|
+
- Task file name format:
|
|
21
|
+
- NNN_<short_title>.md
|
|
22
|
+
- NNN must be the next available number (monotonic increasing).
|
|
23
|
+
- Title should be short, action-oriented.
|
|
24
|
+
|
|
25
|
+
## Output
|
|
26
|
+
- Create/Update:
|
|
27
|
+
- `.ai/TASK.md` Task board
|
|
28
|
+
- New `.ai/tasks/*.md` files
|
|
29
|
+
- Do NOT modify old archived epics.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import re
|
|
5
|
+
import subprocess
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
10
|
+
AI_DIR = ROOT / ".ai"
|
|
11
|
+
TASK_FILE = AI_DIR / "TASK.md"
|
|
12
|
+
CONTEXT_FILE = AI_DIR / "CONTEXT.md"
|
|
13
|
+
DECISIONS_FILE = AI_DIR / "DECISIONS.md"
|
|
14
|
+
OUTPUT_FILE = AI_DIR / "CONTEXT_PACK.md"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def run(cmd):
|
|
18
|
+
try:
|
|
19
|
+
return subprocess.check_output(
|
|
20
|
+
cmd, cwd=str(ROOT), stderr=subprocess.STDOUT, text=True
|
|
21
|
+
).strip()
|
|
22
|
+
except Exception as e:
|
|
23
|
+
return f"(command failed: {' '.join(cmd)}; {e})"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def read_text(p: Path, max_chars=20000):
|
|
27
|
+
if not p:
|
|
28
|
+
return "(missing path)"
|
|
29
|
+
if not p.exists():
|
|
30
|
+
return f"(missing: {p})"
|
|
31
|
+
s = p.read_text(encoding="utf-8", errors="ignore")
|
|
32
|
+
if len(s) > max_chars:
|
|
33
|
+
return s[:max_chars] + "\n\n...(truncated)...\n"
|
|
34
|
+
return s
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# -----------------------------
|
|
38
|
+
# Active task parsing
|
|
39
|
+
# -----------------------------
|
|
40
|
+
|
|
41
|
+
def parse_active_task_path_legacy(task_md: str):
|
|
42
|
+
"""
|
|
43
|
+
Legacy format:
|
|
44
|
+
- Path: .ai/tasks/xxx.md
|
|
45
|
+
"""
|
|
46
|
+
m = re.search(
|
|
47
|
+
r"^-+\s*Path:\s*(\.ai\/tasks\/[^\s]+)\s*$",
|
|
48
|
+
task_md,
|
|
49
|
+
flags=re.MULTILINE,
|
|
50
|
+
)
|
|
51
|
+
if m:
|
|
52
|
+
return ROOT / m.group(1)
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def parse_task_board_active_paths(task_md: str):
|
|
57
|
+
"""
|
|
58
|
+
New format:
|
|
59
|
+
## Task board
|
|
60
|
+
- Active:
|
|
61
|
+
- .ai/tasks/011_xxx.md
|
|
62
|
+
- .ai/tasks/012_yyy.md
|
|
63
|
+
- Queued:
|
|
64
|
+
- ...
|
|
65
|
+
"""
|
|
66
|
+
lines = task_md.splitlines()
|
|
67
|
+
active_paths = []
|
|
68
|
+
in_active = False
|
|
69
|
+
|
|
70
|
+
for raw in lines:
|
|
71
|
+
line = raw.strip()
|
|
72
|
+
|
|
73
|
+
# enter Active block
|
|
74
|
+
if re.match(r"^-+\s*Active:\s*$", line):
|
|
75
|
+
in_active = True
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
# leave Active block
|
|
79
|
+
if in_active and re.match(r"^-+\s*(Queued|Blocked|Done):\s*$", line):
|
|
80
|
+
in_active = False
|
|
81
|
+
continue
|
|
82
|
+
|
|
83
|
+
if not in_active:
|
|
84
|
+
continue
|
|
85
|
+
|
|
86
|
+
# match: "- .ai/tasks/xxx.md"
|
|
87
|
+
m = re.match(r"^-+\s*(\.ai\/tasks\/\S+\.md)\s*$", line)
|
|
88
|
+
if not m:
|
|
89
|
+
# match: ".ai/tasks/xxx.md"
|
|
90
|
+
m = re.match(r"^(\.ai\/tasks\/\S+\.md)\s*$", line)
|
|
91
|
+
|
|
92
|
+
if m:
|
|
93
|
+
active_paths.append(ROOT / m.group(1))
|
|
94
|
+
|
|
95
|
+
# Deduplicate while preserving order
|
|
96
|
+
uniq = []
|
|
97
|
+
seen = set()
|
|
98
|
+
for p in active_paths:
|
|
99
|
+
s = str(p)
|
|
100
|
+
if s not in seen:
|
|
101
|
+
seen.add(s)
|
|
102
|
+
uniq.append(p)
|
|
103
|
+
|
|
104
|
+
return uniq
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def parse_active_tasks(task_md: str):
|
|
108
|
+
"""
|
|
109
|
+
Unified:
|
|
110
|
+
- Prefer Task board Active list if present
|
|
111
|
+
- Else fallback to legacy "- Path:" style
|
|
112
|
+
"""
|
|
113
|
+
active_list = parse_task_board_active_paths(task_md)
|
|
114
|
+
if active_list:
|
|
115
|
+
return active_list
|
|
116
|
+
|
|
117
|
+
legacy = parse_active_task_path_legacy(task_md)
|
|
118
|
+
return [legacy] if legacy else []
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# -----------------------------
|
|
122
|
+
# Main
|
|
123
|
+
# -----------------------------
|
|
124
|
+
|
|
125
|
+
def main():
|
|
126
|
+
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
127
|
+
|
|
128
|
+
task_md = read_text(TASK_FILE)
|
|
129
|
+
|
|
130
|
+
active_task_paths = parse_active_tasks(task_md)
|
|
131
|
+
primary_active_task = active_task_paths[0] if active_task_paths else None
|
|
132
|
+
|
|
133
|
+
primary_active_task_md = (
|
|
134
|
+
read_text(primary_active_task, max_chars=20000)
|
|
135
|
+
if primary_active_task
|
|
136
|
+
else "(No active task found in .ai/TASK.md)"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
git_status = run(["git", "status", "--porcelain"])
|
|
140
|
+
git_branch = run(["git", "rev-parse", "--abbrev-ref", "HEAD"])
|
|
141
|
+
git_diff_stat = run(["git", "diff", "--stat"])
|
|
142
|
+
recent_commits = run(["git", "log", "-5", "--oneline"])
|
|
143
|
+
|
|
144
|
+
content = []
|
|
145
|
+
content.append(f"# CONTEXT PACK\n\nGenerated: {now}\n\n")
|
|
146
|
+
|
|
147
|
+
content.append("## How to use\n")
|
|
148
|
+
content.append("- In a NEW editor window/chat, ask the AI to read this file first.\n")
|
|
149
|
+
content.append("- Then follow the Next actions in the Primary active task.\n")
|
|
150
|
+
content.append("- After changes, AI must update .ai/TASK.md and relevant task card.\n\n")
|
|
151
|
+
|
|
152
|
+
content.append("## Repo info\n")
|
|
153
|
+
content.append(f"- Branch: {git_branch}\n\n")
|
|
154
|
+
|
|
155
|
+
content.append("## Git status (porcelain)\n```text\n" + (git_status or "(clean)") + "\n```\n\n")
|
|
156
|
+
content.append("## Git diff --stat\n```text\n" + (git_diff_stat or "(no diff)") + "\n```\n\n")
|
|
157
|
+
content.append("## Recent commits\n```text\n" + (recent_commits or "(no commits)") + "\n```\n\n")
|
|
158
|
+
|
|
159
|
+
content.append("## .ai/CONTEXT.md\n")
|
|
160
|
+
content.append(read_text(CONTEXT_FILE, max_chars=12000) + "\n\n")
|
|
161
|
+
|
|
162
|
+
content.append("## .ai/TASK.md\n")
|
|
163
|
+
content.append(task_md + "\n\n")
|
|
164
|
+
|
|
165
|
+
# Active tasks list
|
|
166
|
+
content.append("## Active tasks\n")
|
|
167
|
+
if active_task_paths:
|
|
168
|
+
for p in active_task_paths:
|
|
169
|
+
content.append(f"- {p.relative_to(ROOT)}\n")
|
|
170
|
+
else:
|
|
171
|
+
content.append("- (none)\n")
|
|
172
|
+
content.append("\n")
|
|
173
|
+
|
|
174
|
+
# Primary active task
|
|
175
|
+
content.append("## Primary active task (first in Active list)\n")
|
|
176
|
+
content.append(f"- Path: {primary_active_task.relative_to(ROOT) if primary_active_task else '(none)'}\n\n")
|
|
177
|
+
content.append(primary_active_task_md + "\n\n")
|
|
178
|
+
|
|
179
|
+
# Other active tasks
|
|
180
|
+
if len(active_task_paths) > 1:
|
|
181
|
+
content.append("## Other active tasks (truncated)\n")
|
|
182
|
+
for p in active_task_paths[1:]:
|
|
183
|
+
content.append(f"### {p.relative_to(ROOT)}\n")
|
|
184
|
+
content.append(read_text(p, max_chars=8000) + "\n\n")
|
|
185
|
+
|
|
186
|
+
content.append("## .ai/DECISIONS.md (latest)\n")
|
|
187
|
+
content.append(read_text(DECISIONS_FILE, max_chars=12000) + "\n\n")
|
|
188
|
+
|
|
189
|
+
OUTPUT_FILE.write_text("".join(content), encoding="utf-8")
|
|
190
|
+
print(f"✅ Wrote: {OUTPUT_FILE}")
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
if __name__ == "__main__":
|
|
194
|
+
main()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Task 000 - Retrofit existing work (mandatory)
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
Bring a half-done repo back into the `.ai/` workflow.
|
|
5
|
+
|
|
6
|
+
## Context / Inputs
|
|
7
|
+
- This repo already contains work in progress.
|
|
8
|
+
- There may be no task cards, no log, and no clear current state.
|
|
9
|
+
|
|
10
|
+
## Acceptance criteria
|
|
11
|
+
- `.ai/TASK.md` reflects the real current work
|
|
12
|
+
- 3~10 task cards exist under `.ai/tasks/`
|
|
13
|
+
- One task is marked as Active and has executable Next actions
|
|
14
|
+
- `.ai/LOG.md` contains a short retrofit entry
|
|
15
|
+
|
|
16
|
+
## Current state
|
|
17
|
+
- Unknown / not documented yet
|
|
18
|
+
|
|
19
|
+
## Next actions
|
|
20
|
+
1. Read `.ai/START.md`, `.ai/CONTEXT.md`, `.ai/PROMPT_START.md`
|
|
21
|
+
2. Scan the repo quickly (top-level folders + README)
|
|
22
|
+
3. Summarize current progress in 5~10 bullets
|
|
23
|
+
4. Identify the current primary goal
|
|
24
|
+
5. Create 3~10 task cards under `.ai/tasks/`
|
|
25
|
+
6. Update `.ai/TASK.md` (Active / Queued / Done)
|
|
26
|
+
7. Append a retrofit entry to `.ai/LOG.md`
|