aodw-skill 0.7.25 → 0.7.27

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.
@@ -1,9 +1,30 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
+ import { fileURLToPath } from 'url';
3
4
  import inquirer from 'inquirer';
4
5
  import chalk from 'chalk';
5
6
  import { getProjectConfig } from '../utils/config.js';
6
7
 
8
+ const CORE_DIR = process.env.AODW_CORE_DIR || '.aodw-next';
9
+
10
+ function getTemplatePath(name) {
11
+ const local = path.join(process.cwd(), CORE_DIR, 'templates', name);
12
+ if (fs.existsSync(local)) return local;
13
+ const pkg = path.join(path.dirname(fileURLToPath(import.meta.url)), '../../.aodw-next/templates', name);
14
+ if (fs.existsSync(pkg)) return pkg;
15
+ return null;
16
+ }
17
+
18
+ function loadTemplate(name, replacements = {}) {
19
+ const templatePath = getTemplatePath(name);
20
+ if (!templatePath) return null;
21
+ let content = fs.readFileSync(templatePath, 'utf8');
22
+ for (const [key, value] of Object.entries(replacements)) {
23
+ content = content.split(key).join(value);
24
+ }
25
+ return content;
26
+ }
27
+
7
28
  function getProjectName() {
8
29
  // 1. Try .aodw/project.yaml
9
30
  const projectConfig = getProjectConfig();
@@ -45,6 +66,40 @@ function getLocalNextId() {
45
66
  return `RT-${String(maxSeq + 1).padStart(3, '0')}`;
46
67
  }
47
68
 
69
+ const EXECUTION_MODES = ['collaborative', 'autopilot'];
70
+
71
+ async function resolveExecutionMode(options) {
72
+ if (options.executionMode) {
73
+ const mode = String(options.executionMode).toLowerCase();
74
+ if (!EXECUTION_MODES.includes(mode)) {
75
+ console.error(chalk.red(`错误: execution_mode 必须是 ${EXECUTION_MODES.join(' 或 ')}`));
76
+ process.exit(1);
77
+ }
78
+ console.log(chalk.cyan(`执行模式(命令行指定): ${mode}`));
79
+ return mode;
80
+ }
81
+
82
+ console.log(chalk.yellow('\n⚠️ 创建 RT 前必须确认执行模式,未选择将无法继续。\n'));
83
+
84
+ const { executionMode } = await inquirer.prompt([{
85
+ type: 'list',
86
+ name: 'executionMode',
87
+ message: '请选择本 RT 的执行模式(必选):',
88
+ choices: [
89
+ {
90
+ name: '人工干预模式(协作)— Gate 3/4/5 需用户确认后再推进',
91
+ value: 'collaborative',
92
+ },
93
+ {
94
+ name: '全自动模式(Autopilot)— 机械验收 + 循环推进,仅熔断时请求人工',
95
+ value: 'autopilot',
96
+ },
97
+ ],
98
+ }]);
99
+
100
+ return executionMode;
101
+ }
102
+
48
103
  export async function createNewRT(options) {
49
104
  // Determine Project Name: Flag > Config/Package/Dir
50
105
  const project = options.project || getProjectName();
@@ -61,6 +116,8 @@ export async function createNewRT(options) {
61
116
  title = answers.title;
62
117
  }
63
118
 
119
+ const executionMode = await resolveExecutionMode(options);
120
+
64
121
  // 固定独立模式:始终本地生成 RT-ID
65
122
  const id = getLocalNextId();
66
123
  console.log(chalk.yellow(`Using local ID generation: ${id}`));
@@ -79,6 +136,7 @@ export async function createNewRT(options) {
79
136
  title: "${title}"
80
137
  type: Feature # Default, update after intake
81
138
  profile: Spec-Lite # Default, update after decision
139
+ execution_mode: ${executionMode} # 用户创建时已确认: collaborative | autopilot
82
140
  status: created
83
141
  created_at: "${now}"
84
142
  updated_at: "${now}"
@@ -102,9 +160,16 @@ modules: []
102
160
  `;
103
161
  fs.writeFileSync(path.join(rtPath, 'intake.md'), intakeContent);
104
162
 
163
+ const modeLabel = executionMode === 'autopilot' ? '全自动(Autopilot)' : '人工干预(协作)';
164
+
105
165
  // Create decision.md
106
166
  const decisionContent = `# Decision: ${id}
107
167
 
168
+ ## Execution Mode(用户已确认,创建时必选)
169
+ - [x] ${executionMode} — ${modeLabel}
170
+ - 确认时间: ${now}
171
+ - 说明: 创建 RT 时由用户明确选择;未经确认不得修改 execution_mode
172
+
108
173
  ## Profile Selection
109
174
  - [ ] Spec-Lite (Recommended for most tasks)
110
175
  - [ ] Spec-Full (For complex/risky tasks)
@@ -114,6 +179,56 @@ modules: []
114
179
  `;
115
180
  fs.writeFileSync(path.join(rtPath, 'decision.md'), decisionContent);
116
181
 
182
+ const replacements = {
183
+ 'RT-XXX': id,
184
+ '<任务标题>': title,
185
+ '<ISO8601>': now,
186
+ 'feature/RT-XXX': `feature/${id}`,
187
+ '{RT_ID}': id,
188
+ };
189
+
190
+ let rtLite = loadTemplate('rt-lite.template.md', replacements);
191
+ if (rtLite) {
192
+ rtLite = rtLite.replace('execution_mode: collaborative', `execution_mode: ${executionMode}`);
193
+ fs.writeFileSync(path.join(rtPath, 'rt-lite.md'), rtLite);
194
+ }
195
+
196
+ if (executionMode === 'autopilot') {
197
+ const rtPlan = loadTemplate('rt-plan.template.md', replacements);
198
+ if (rtPlan) fs.writeFileSync(path.join(rtPath, 'rt-plan.md'), rtPlan);
199
+
200
+ let stateJson = loadTemplate('rt-state.template.json', replacements);
201
+ if (stateJson) {
202
+ stateJson = stateJson.replace('"execution_mode": "autopilot"', `"execution_mode": "${executionMode}"`);
203
+ fs.writeFileSync(path.join(rtPath, 'state.json'), stateJson);
204
+ }
205
+
206
+ const loopPrompt = loadTemplate('rt-loop-prompt.template.md', {
207
+ ...replacements,
208
+ '{ITERATION}': '1',
209
+ '{MAX_ITERATIONS}': '20',
210
+ '{GOAL_SUMMARY}': title,
211
+ '{CHECKLIST_ITEMS}': '见 rt-lite.md §7',
212
+ '{STATE_JSON}': stateJson || '{}',
213
+ });
214
+ if (loopPrompt) fs.writeFileSync(path.join(rtPath, 'loop-prompt.md'), loopPrompt);
215
+
216
+ const executionLog = loadTemplate('execution-log.template.md', replacements);
217
+ if (executionLog) {
218
+ const logWithTime = executionLog.replace('**time**: \n', `**time**: ${now}\n`);
219
+ fs.writeFileSync(path.join(rtPath, 'execution-log.md'), logWithTime);
220
+ }
221
+
222
+ const preflight = loadTemplate('rt-autopilot-preflight.template.md', replacements);
223
+ if (preflight) fs.writeFileSync(path.join(rtPath, 'autopilot-preflight.md'), preflight);
224
+ }
225
+
117
226
  console.log(chalk.green(`\n✔ Created RT ${id} at ./RT/${id}`));
118
- console.log(chalk.white(`Next step: Open ./RT/${id}/intake.md and start the intake process.`));
227
+ console.log(chalk.white(`执行模式: ${executionMode}(${modeLabel})`));
228
+ console.log(chalk.white('Next step: Open ./RT/' + id + '/intake.md and complete intake/decision.'));
229
+ if (executionMode === 'autopilot') {
230
+ console.log(chalk.cyan('Autopilot: 定稿 rt-lite §7 → Goal 自检 → preflight → 见 .aodw-next/02-workflow/autopilot-protocol.md'));
231
+ } else {
232
+ console.log(chalk.cyan('协作模式: 按 spec-lite-profile.md,Gate 3/4/5 需用户确认'));
233
+ }
119
234
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aodw-skill",
3
- "version": "0.7.25",
3
+ "version": "0.7.27",
4
4
  "description": "Next-channel CLI tool to scaffold AODW in your project",
5
5
  "main": "bin/aodw.js",
6
6
  "files": [