@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.
Files changed (35) hide show
  1. package/LICENSE +21 -0
  2. package/PUBLISH.md +75 -0
  3. package/README.md +53 -0
  4. package/autodev/bin/autodev-tools.cjs +346 -0
  5. package/autodev/templates/config.json +20 -0
  6. package/autodev/templates/plan.md +25 -0
  7. package/autodev/templates/project.md +21 -0
  8. package/autodev/templates/requirements.md +12 -0
  9. package/autodev/templates/roadmap.md +17 -0
  10. package/autodev/templates/state.md +10 -0
  11. package/autodev/templates/summary.md +16 -0
  12. package/autodev/templates/uat.md +15 -0
  13. package/autodev/workflows/execute-phase.md +50 -0
  14. package/autodev/workflows/help.md +57 -0
  15. package/autodev/workflows/new-project.md +62 -0
  16. package/autodev/workflows/plan-phase.md +54 -0
  17. package/autodev/workflows/progress.md +15 -0
  18. package/autodev/workflows/verify-work.md +39 -0
  19. package/bin/install.js +565 -0
  20. package/commands/autodev/execute-phase.md +26 -0
  21. package/commands/autodev/help.md +18 -0
  22. package/commands/autodev/new-project.md +28 -0
  23. package/commands/autodev/plan-phase.md +25 -0
  24. package/commands/autodev/progress.md +18 -0
  25. package/commands/autodev/verify-work.md +24 -0
  26. package/hooks/autodev-context-monitor.js +66 -0
  27. package/hooks/autodev-git-guard.js +55 -0
  28. package/hooks/autodev-phase-boundary.sh +20 -0
  29. package/hooks/autodev-prompt-guard.js +55 -0
  30. package/hooks/autodev-read-guard.js +49 -0
  31. package/hooks/autodev-session-state.sh +22 -0
  32. package/hooks/autodev-statusline.js +45 -0
  33. package/hooks/autodev-workflow-guard.js +51 -0
  34. package/package.json +38 -0
  35. 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,12 @@
1
+ # Requirements
2
+
3
+ ## Must Have
4
+ 1. REQ-01: [Requirement]
5
+ Acceptance:
6
+ - [Observable outcome]
7
+
8
+ ## Nice to Have
9
+ 1. NICE-01: [Optional enhancement]
10
+
11
+ ## Non-Goals
12
+ - [Explicitly excluded work]
@@ -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,10 @@
1
+ # State
2
+
3
+ Current Phase: 1
4
+ Current Step: planning
5
+ Status: active
6
+ Next Command: /autodev-plan-phase 1
7
+ Last Updated: [ISO timestamp]
8
+
9
+ ## Notes
10
+ - Project initialized.
@@ -0,0 +1,16 @@
1
+ # Phase [N] Summary: [Name]
2
+
3
+ ## Completed
4
+ - [What shipped]
5
+
6
+ ## Files Changed
7
+ - [path]
8
+
9
+ ## Verification
10
+ - [Command and result]
11
+
12
+ ## Remaining Risks
13
+ - [Known gap]
14
+
15
+ ## Next Step
16
+ - Run `/autodev-verify-work [N]`
@@ -0,0 +1,15 @@
1
+ # Phase [N] UAT: [Name]
2
+
3
+ Status: pending
4
+
5
+ ## Test Cases
6
+ - [ ] [Behavior to verify]
7
+
8
+ ## Results
9
+ - [Pass/fail notes]
10
+
11
+ ## Bugs Or Follow-Up
12
+ - [Issue or none]
13
+
14
+ ## Recommended Next Step
15
+ - [Next command]
@@ -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>