@mthanhlm/autodev 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/LICENSE +21 -0
- package/PUBLISH.md +75 -0
- package/README.md +53 -0
- package/autodev/bin/autodev-tools.cjs +346 -0
- package/autodev/templates/config.json +20 -0
- package/autodev/templates/plan.md +25 -0
- package/autodev/templates/project.md +21 -0
- package/autodev/templates/requirements.md +12 -0
- package/autodev/templates/roadmap.md +17 -0
- package/autodev/templates/state.md +10 -0
- package/autodev/templates/summary.md +16 -0
- package/autodev/templates/uat.md +15 -0
- package/autodev/workflows/execute-phase.md +50 -0
- package/autodev/workflows/help.md +57 -0
- package/autodev/workflows/new-project.md +62 -0
- package/autodev/workflows/plan-phase.md +54 -0
- package/autodev/workflows/progress.md +15 -0
- package/autodev/workflows/verify-work.md +39 -0
- package/bin/install.js +565 -0
- package/commands/autodev/execute-phase.md +26 -0
- package/commands/autodev/help.md +18 -0
- package/commands/autodev/new-project.md +28 -0
- package/commands/autodev/plan-phase.md +25 -0
- package/commands/autodev/progress.md +18 -0
- package/commands/autodev/verify-work.md +24 -0
- package/hooks/autodev-context-monitor.js +66 -0
- package/hooks/autodev-git-guard.js +55 -0
- package/hooks/autodev-phase-boundary.sh +20 -0
- package/hooks/autodev-prompt-guard.js +55 -0
- package/hooks/autodev-read-guard.js +49 -0
- package/hooks/autodev-session-state.sh +22 -0
- package/hooks/autodev-statusline.js +45 -0
- package/hooks/autodev-workflow-guard.js +51 -0
- package/package.json +38 -0
- package/scripts/run-tests.cjs +23 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mthanhlm
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/PUBLISH.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Publishing `@mthanhlm/autodev`
|
|
2
|
+
|
|
3
|
+
## One-Time Setup
|
|
4
|
+
|
|
5
|
+
1. Make sure the npm account `mthanhlm` has access to the `@mthanhlm` scope.
|
|
6
|
+
2. Log in:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm login
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
3. Verify the active account:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm whoami
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Pre-Publish Checklist
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
cd autodev
|
|
22
|
+
npm test
|
|
23
|
+
npm pack
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Check the tarball contents:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
tar -tf mthanhlm-autodev-0.1.0.tgz
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## First Public Publish
|
|
33
|
+
|
|
34
|
+
Scoped packages are private by default. The first public release must include `--access public`.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm publish --access public
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Later Releases
|
|
41
|
+
|
|
42
|
+
1. Bump the version in `package.json`.
|
|
43
|
+
2. Regenerate the tarball:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm pack
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
3. Publish:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm publish
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Post-Publish Smoke Check
|
|
56
|
+
|
|
57
|
+
Verify npm sees the release:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm view @mthanhlm/autodev version
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then install from npm in a scratch directory:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
mkdir -p /tmp/autodev-smoke
|
|
67
|
+
cd /tmp/autodev-smoke
|
|
68
|
+
npx @mthanhlm/autodev@latest --local
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Open Claude Code in that directory and run:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
/autodev-help
|
|
75
|
+
```
|
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# autodev
|
|
2
|
+
|
|
3
|
+
`autodev` is a Claude Code workflow package built for one thing: get from idea to shipped code without the slow, over-engineered, git-writing behavior that made GSD painful.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
- Installs a small Claude Code workflow under `~/.claude/` or `./.claude/`
|
|
8
|
+
- Keeps project state in `.autodev/`
|
|
9
|
+
- Ships six commands:
|
|
10
|
+
- `/autodev-help`
|
|
11
|
+
- `/autodev-new-project`
|
|
12
|
+
- `/autodev-plan-phase`
|
|
13
|
+
- `/autodev-execute-phase`
|
|
14
|
+
- `/autodev-verify-work`
|
|
15
|
+
- `/autodev-progress`
|
|
16
|
+
- Treats git as read-only inside the workflow
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @mthanhlm/autodev@latest --global
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Local install for one repo:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx @mthanhlm/autodev@latest --local
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Uninstall:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx @mthanhlm/autodev@latest --global --uninstall
|
|
34
|
+
npx @mthanhlm/autodev@latest --local --uninstall
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Default Flow
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
/autodev-new-project
|
|
41
|
+
/autodev-plan-phase 1
|
|
42
|
+
/autodev-execute-phase 1
|
|
43
|
+
/autodev-verify-work 1
|
|
44
|
+
/autodev-progress
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Git Policy
|
|
48
|
+
|
|
49
|
+
`autodev` does not stage, commit, branch, merge, worktree, pull, push, or initialize git repositories. Read-only git commands like `git status`, `git diff`, and `git log` remain allowed.
|
|
50
|
+
|
|
51
|
+
## Publish
|
|
52
|
+
|
|
53
|
+
Release steps are in [PUBLISH.md](PUBLISH.md).
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const DEFAULT_CONFIG = {
|
|
7
|
+
workflow: {
|
|
8
|
+
research: false
|
|
9
|
+
},
|
|
10
|
+
execution: {
|
|
11
|
+
parallel: false
|
|
12
|
+
},
|
|
13
|
+
git: {
|
|
14
|
+
mode: 'read-only'
|
|
15
|
+
},
|
|
16
|
+
hooks: {
|
|
17
|
+
context_warnings: true,
|
|
18
|
+
read_guard: true,
|
|
19
|
+
workflow_guard: true,
|
|
20
|
+
prompt_guard: true,
|
|
21
|
+
git_guard: true,
|
|
22
|
+
session_state: true,
|
|
23
|
+
phase_boundary: true
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function autodevDir(cwd) {
|
|
28
|
+
return path.join(cwd, '.autodev');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function readText(filePath) {
|
|
32
|
+
try {
|
|
33
|
+
return fs.readFileSync(filePath, 'utf8');
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readJson(filePath, fallback = null) {
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
42
|
+
} catch {
|
|
43
|
+
return fallback;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function slugify(value) {
|
|
48
|
+
return String(value)
|
|
49
|
+
.toLowerCase()
|
|
50
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
51
|
+
.replace(/^-+|-+$/g, '')
|
|
52
|
+
.replace(/-+/g, '-') || 'phase';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function padPhase(number) {
|
|
56
|
+
return String(number).padStart(2, '0');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function parseRoadmap(content) {
|
|
60
|
+
const phases = [];
|
|
61
|
+
if (!content) {
|
|
62
|
+
return phases;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const matcher = /^##\s+Phase\s+(\d+)\s*:\s*(.+)$/gm;
|
|
66
|
+
let match;
|
|
67
|
+
while ((match = matcher.exec(content)) !== null) {
|
|
68
|
+
phases.push({
|
|
69
|
+
number: Number(match[1]),
|
|
70
|
+
name: match[2].trim()
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return phases;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function phasePaths(cwd, phase) {
|
|
77
|
+
const dirName = `${padPhase(phase.number)}-${slugify(phase.name)}`;
|
|
78
|
+
const dir = path.join(autodevDir(cwd), 'phases', dirName);
|
|
79
|
+
const prefix = padPhase(phase.number);
|
|
80
|
+
return {
|
|
81
|
+
...phase,
|
|
82
|
+
padded: prefix,
|
|
83
|
+
dir,
|
|
84
|
+
planPath: path.join(dir, `${prefix}-PLAN.md`),
|
|
85
|
+
summaryPath: path.join(dir, `${prefix}-SUMMARY.md`),
|
|
86
|
+
uatPath: path.join(dir, `${prefix}-UAT.md`)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function loadConfig(cwd) {
|
|
91
|
+
const config = readJson(path.join(autodevDir(cwd), 'config.json'), {});
|
|
92
|
+
return {
|
|
93
|
+
workflow: {
|
|
94
|
+
...DEFAULT_CONFIG.workflow,
|
|
95
|
+
...(config.workflow || {})
|
|
96
|
+
},
|
|
97
|
+
execution: {
|
|
98
|
+
...DEFAULT_CONFIG.execution,
|
|
99
|
+
...(config.execution || {})
|
|
100
|
+
},
|
|
101
|
+
git: {
|
|
102
|
+
...DEFAULT_CONFIG.git,
|
|
103
|
+
...(config.git || {})
|
|
104
|
+
},
|
|
105
|
+
hooks: {
|
|
106
|
+
...DEFAULT_CONFIG.hooks,
|
|
107
|
+
...(config.hooks || {})
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function listPhases(cwd) {
|
|
113
|
+
const roadmap = readText(path.join(autodevDir(cwd), 'ROADMAP.md'));
|
|
114
|
+
return parseRoadmap(roadmap).map(phase => {
|
|
115
|
+
const details = phasePaths(cwd, phase);
|
|
116
|
+
const planExists = fs.existsSync(details.planPath);
|
|
117
|
+
const summaryExists = fs.existsSync(details.summaryPath);
|
|
118
|
+
const uatExists = fs.existsSync(details.uatPath);
|
|
119
|
+
const status = uatExists
|
|
120
|
+
? 'verified'
|
|
121
|
+
: summaryExists
|
|
122
|
+
? 'executed'
|
|
123
|
+
: planExists
|
|
124
|
+
? 'planned'
|
|
125
|
+
: 'pending';
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
...details,
|
|
129
|
+
planExists,
|
|
130
|
+
summaryExists,
|
|
131
|
+
uatExists,
|
|
132
|
+
status
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function resolvePhase(cwd, requestedPhase, mode) {
|
|
138
|
+
const phases = listPhases(cwd);
|
|
139
|
+
if (phases.length === 0) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (requestedPhase) {
|
|
144
|
+
const numeric = Number(requestedPhase);
|
|
145
|
+
return phases.find(phase => phase.number === numeric) || null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (mode === 'plan') {
|
|
149
|
+
return phases.find(phase => !phase.planExists) || phases[0];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (mode === 'execute') {
|
|
153
|
+
return phases.find(phase => phase.planExists && !phase.summaryExists) || null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (mode === 'verify') {
|
|
157
|
+
return phases.find(phase => phase.summaryExists && !phase.uatExists)
|
|
158
|
+
|| [...phases].reverse().find(phase => phase.summaryExists)
|
|
159
|
+
|| null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return phases[0];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function nextCommand(progress) {
|
|
166
|
+
if (!progress.initialized) {
|
|
167
|
+
return '/autodev-new-project';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const nextVerify = progress.phases.find(phase => phase.summaryExists && !phase.uatExists);
|
|
171
|
+
if (nextVerify) {
|
|
172
|
+
return `/autodev-verify-work ${nextVerify.number}`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const nextExecute = progress.phases.find(phase => phase.planExists && !phase.summaryExists);
|
|
176
|
+
if (nextExecute) {
|
|
177
|
+
return `/autodev-execute-phase ${nextExecute.number}`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const nextPlan = progress.phases.find(phase => !phase.planExists);
|
|
181
|
+
if (nextPlan) {
|
|
182
|
+
return `/autodev-plan-phase ${nextPlan.number}`;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return '/autodev-progress';
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function buildProgress(cwd) {
|
|
189
|
+
const root = autodevDir(cwd);
|
|
190
|
+
const initialized = fs.existsSync(root);
|
|
191
|
+
if (!initialized) {
|
|
192
|
+
return {
|
|
193
|
+
initialized: false,
|
|
194
|
+
phases: [],
|
|
195
|
+
counts: {
|
|
196
|
+
total: 0,
|
|
197
|
+
planned: 0,
|
|
198
|
+
executed: 0,
|
|
199
|
+
verified: 0
|
|
200
|
+
},
|
|
201
|
+
nextCommand: '/autodev-new-project'
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const phases = listPhases(cwd);
|
|
206
|
+
return {
|
|
207
|
+
initialized: true,
|
|
208
|
+
phases,
|
|
209
|
+
counts: {
|
|
210
|
+
total: phases.length,
|
|
211
|
+
planned: phases.filter(phase => phase.planExists).length,
|
|
212
|
+
executed: phases.filter(phase => phase.summaryExists).length,
|
|
213
|
+
verified: phases.filter(phase => phase.uatExists).length
|
|
214
|
+
},
|
|
215
|
+
nextCommand: nextCommand({ initialized: true, phases })
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function renderProgressTable(progress) {
|
|
220
|
+
if (!progress.initialized) {
|
|
221
|
+
return 'No .autodev project found.\nNext: /autodev-new-project';
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const lines = [
|
|
225
|
+
'Autodev Progress',
|
|
226
|
+
'',
|
|
227
|
+
`Phases: ${progress.counts.total}`,
|
|
228
|
+
`Planned: ${progress.counts.planned}`,
|
|
229
|
+
`Executed: ${progress.counts.executed}`,
|
|
230
|
+
`Verified: ${progress.counts.verified}`,
|
|
231
|
+
`Next: ${progress.nextCommand}`,
|
|
232
|
+
'',
|
|
233
|
+
'| Phase | Name | Plan | Summary | UAT | Status |',
|
|
234
|
+
'| --- | --- | --- | --- | --- | --- |'
|
|
235
|
+
];
|
|
236
|
+
|
|
237
|
+
for (const phase of progress.phases) {
|
|
238
|
+
lines.push(
|
|
239
|
+
`| ${phase.number} | ${phase.name} | ${phase.planExists ? 'yes' : 'no'} | ${phase.summaryExists ? 'yes' : 'no'} | ${phase.uatExists ? 'yes' : 'no'} | ${phase.status} |`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return lines.join('\n');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function dotGet(object, key) {
|
|
247
|
+
return key.split('.').reduce((current, part) => (
|
|
248
|
+
current && Object.prototype.hasOwnProperty.call(current, part) ? current[part] : undefined
|
|
249
|
+
), object);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function initPayload(cwd, mode, requestedPhase) {
|
|
253
|
+
const root = autodevDir(cwd);
|
|
254
|
+
const config = loadConfig(cwd);
|
|
255
|
+
const phase = mode === 'new-project' ? null : resolvePhase(cwd, requestedPhase, mode);
|
|
256
|
+
return {
|
|
257
|
+
cwd,
|
|
258
|
+
autodev_exists: fs.existsSync(root),
|
|
259
|
+
config_path: path.join(root, 'config.json'),
|
|
260
|
+
project_path: path.join(root, 'PROJECT.md'),
|
|
261
|
+
requirements_path: path.join(root, 'REQUIREMENTS.md'),
|
|
262
|
+
roadmap_path: path.join(root, 'ROADMAP.md'),
|
|
263
|
+
state_path: path.join(root, 'STATE.md'),
|
|
264
|
+
research_enabled: config.workflow.research,
|
|
265
|
+
git_mode: config.git.mode,
|
|
266
|
+
phase_found: Boolean(phase),
|
|
267
|
+
phase_number: phase ? phase.number : null,
|
|
268
|
+
phase_name: phase ? phase.name : null,
|
|
269
|
+
phase_dir: phase ? phase.dir : null,
|
|
270
|
+
plan_path: phase ? phase.planPath : null,
|
|
271
|
+
summary_path: phase ? phase.summaryPath : null,
|
|
272
|
+
uat_path: phase ? phase.uatPath : null,
|
|
273
|
+
plan_exists: phase ? phase.planExists : false,
|
|
274
|
+
summary_exists: phase ? phase.summaryExists : false,
|
|
275
|
+
uat_exists: phase ? phase.uatExists : false
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function printJson(value) {
|
|
280
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function main() {
|
|
284
|
+
const args = process.argv.slice(2);
|
|
285
|
+
const cwd = process.cwd();
|
|
286
|
+
|
|
287
|
+
if (args.length === 0) {
|
|
288
|
+
process.stderr.write('autodev-tools: command required\n');
|
|
289
|
+
process.exit(1);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const [command, ...rest] = args;
|
|
293
|
+
|
|
294
|
+
if (command === 'progress') {
|
|
295
|
+
const mode = rest[0] || 'table';
|
|
296
|
+
const progress = buildProgress(cwd);
|
|
297
|
+
if (mode === 'json') {
|
|
298
|
+
printJson(progress);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
process.stdout.write(`${renderProgressTable(progress)}\n`);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (command === 'config-get') {
|
|
306
|
+
const key = rest[0];
|
|
307
|
+
if (!key) {
|
|
308
|
+
process.stderr.write('autodev-tools: config key required\n');
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
const value = dotGet(loadConfig(cwd), key);
|
|
312
|
+
if (typeof value === 'object') {
|
|
313
|
+
printJson(value);
|
|
314
|
+
} else if (value !== undefined) {
|
|
315
|
+
process.stdout.write(`${String(value)}\n`);
|
|
316
|
+
}
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (command === 'init') {
|
|
321
|
+
const mode = rest[0];
|
|
322
|
+
const phase = rest[1];
|
|
323
|
+
if (!mode) {
|
|
324
|
+
process.stderr.write('autodev-tools: init mode required\n');
|
|
325
|
+
process.exit(1);
|
|
326
|
+
}
|
|
327
|
+
printJson(initPayload(cwd, mode, phase));
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
process.stderr.write(`autodev-tools: unknown command "${command}"\n`);
|
|
332
|
+
process.exit(1);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (require.main === module) {
|
|
336
|
+
main();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
module.exports = {
|
|
340
|
+
autodevDir,
|
|
341
|
+
buildProgress,
|
|
342
|
+
loadConfig,
|
|
343
|
+
parseRoadmap,
|
|
344
|
+
renderProgressTable,
|
|
345
|
+
resolvePhase
|
|
346
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"workflow": {
|
|
3
|
+
"research": false
|
|
4
|
+
},
|
|
5
|
+
"execution": {
|
|
6
|
+
"parallel": false
|
|
7
|
+
},
|
|
8
|
+
"git": {
|
|
9
|
+
"mode": "read-only"
|
|
10
|
+
},
|
|
11
|
+
"hooks": {
|
|
12
|
+
"context_warnings": true,
|
|
13
|
+
"read_guard": true,
|
|
14
|
+
"workflow_guard": true,
|
|
15
|
+
"prompt_guard": true,
|
|
16
|
+
"git_guard": true,
|
|
17
|
+
"session_state": true,
|
|
18
|
+
"phase_boundary": true
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Phase [N] Plan: [Name]
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
[Phase goal]
|
|
5
|
+
|
|
6
|
+
## Inputs
|
|
7
|
+
- PROJECT.md
|
|
8
|
+
- REQUIREMENTS.md
|
|
9
|
+
- ROADMAP.md
|
|
10
|
+
- Current codebase state
|
|
11
|
+
|
|
12
|
+
## Steps
|
|
13
|
+
1. [Concrete task]
|
|
14
|
+
2. [Concrete task]
|
|
15
|
+
|
|
16
|
+
## Files Likely To Change
|
|
17
|
+
- [path]
|
|
18
|
+
|
|
19
|
+
## Verification
|
|
20
|
+
- [Command]
|
|
21
|
+
- [Manual check]
|
|
22
|
+
|
|
23
|
+
## Git Policy
|
|
24
|
+
- Read-only only.
|
|
25
|
+
- Allowed: `git status`, `git diff`, `git log`, `git show`, `git rev-parse`, `git ls-files`, `git branch --show-current`.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Project
|
|
2
|
+
|
|
3
|
+
## One-Line Summary
|
|
4
|
+
[Describe the product in one sentence.]
|
|
5
|
+
|
|
6
|
+
## Problem
|
|
7
|
+
[What pain are you solving?]
|
|
8
|
+
|
|
9
|
+
## Users
|
|
10
|
+
[Who is this for?]
|
|
11
|
+
|
|
12
|
+
## Success Criteria
|
|
13
|
+
- [Primary outcome]
|
|
14
|
+
- [Primary quality bar]
|
|
15
|
+
|
|
16
|
+
## Constraints
|
|
17
|
+
- [Technical constraints]
|
|
18
|
+
- [Business or time constraints]
|
|
19
|
+
|
|
20
|
+
## Non-Goals
|
|
21
|
+
- [Out of scope]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
## Phase 1: [Name]
|
|
4
|
+
Status: pending
|
|
5
|
+
Goal: [What this phase achieves]
|
|
6
|
+
Deliverables:
|
|
7
|
+
- [Deliverable]
|
|
8
|
+
Risks:
|
|
9
|
+
- [Risk]
|
|
10
|
+
|
|
11
|
+
## Phase 2: [Name]
|
|
12
|
+
Status: pending
|
|
13
|
+
Goal: [What this phase achieves]
|
|
14
|
+
Deliverables:
|
|
15
|
+
- [Deliverable]
|
|
16
|
+
Risks:
|
|
17
|
+
- [Risk]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<purpose>
|
|
2
|
+
Execute a phase plan sequentially, keep the edits pragmatic, and capture the real outcome in a summary.
|
|
3
|
+
</purpose>
|
|
4
|
+
|
|
5
|
+
<rules>
|
|
6
|
+
- Never run git write commands.
|
|
7
|
+
- Do not create commits, branches, merges, or worktrees.
|
|
8
|
+
- Stay within the current phase. Do not silently expand scope.
|
|
9
|
+
- Execute sequentially by default. Do not create parallel sub-work unless the user explicitly asks for it.
|
|
10
|
+
</rules>
|
|
11
|
+
|
|
12
|
+
<process>
|
|
13
|
+
1. Run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
node "$HOME/.claude/autodev/bin/autodev-tools.cjs" init execute-phase "$ARGUMENTS"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
2. If no phase is found or the plan file is missing, stop and direct the user to `/autodev-plan-phase`.
|
|
20
|
+
|
|
21
|
+
3. Read:
|
|
22
|
+
- `.autodev/STATE.md`
|
|
23
|
+
- the target `NN-PLAN.md`
|
|
24
|
+
- the source files needed for the current phase
|
|
25
|
+
|
|
26
|
+
4. Execute the plan directly in the repository. Use normal coding tools, tests, and read-only git inspection if useful.
|
|
27
|
+
|
|
28
|
+
5. Keep a short running note of:
|
|
29
|
+
- files changed
|
|
30
|
+
- commands run
|
|
31
|
+
- tests passed or failed
|
|
32
|
+
- any scope adjustments the user explicitly approved
|
|
33
|
+
|
|
34
|
+
6. Write or update `NN-SUMMARY.md` from the template with:
|
|
35
|
+
- completed work
|
|
36
|
+
- files changed
|
|
37
|
+
- verification results
|
|
38
|
+
- remaining risks
|
|
39
|
+
- next step
|
|
40
|
+
|
|
41
|
+
7. Update `.autodev/STATE.md` so it points to:
|
|
42
|
+
- `Current Phase: N`
|
|
43
|
+
- `Current Step: executed`
|
|
44
|
+
- `Next Command: /autodev-verify-work N`
|
|
45
|
+
- current ISO timestamp
|
|
46
|
+
|
|
47
|
+
8. If the phase is blocked or incomplete, say so clearly in the summary and set the next command back to `/autodev-execute-phase N`.
|
|
48
|
+
|
|
49
|
+
9. End with a short outcome summary and the next recommended command.
|
|
50
|
+
</process>
|