@nick848/sf-cli 1.0.3 → 1.0.4
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/CHANGELOG.md +15 -0
- package/dist/cli/index.js +495 -86
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +495 -86
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +495 -86
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -3314,12 +3314,20 @@ async function exitCLI(ctx, options = {}) {
|
|
|
3314
3314
|
var DEFAULT_CONFIRMATION_POINTS = [
|
|
3315
3315
|
{
|
|
3316
3316
|
type: "spec-review",
|
|
3317
|
-
name: "\u89C4\
|
|
3318
|
-
description: "\u89C4\
|
|
3317
|
+
name: "\u89C4\u683C\u786E\u8BA4",
|
|
3318
|
+
description: "\u89C4\u683C\u62C6\u5206\u5DF2\u5B8C\u6210\uFF0C\u8BF7\u786E\u8BA4\u89C4\u683C\u6587\u4EF6\u540E\u7EE7\u7EED",
|
|
3319
3319
|
triggerStep: "explore",
|
|
3320
3320
|
targetStep: "new",
|
|
3321
3321
|
required: true
|
|
3322
3322
|
},
|
|
3323
|
+
{
|
|
3324
|
+
type: "spec-review",
|
|
3325
|
+
name: "\u89C4\u683C\u786E\u8BA4",
|
|
3326
|
+
description: "\u89C4\u683C\u62C6\u5206\u5DF2\u5B8C\u6210\uFF0C\u8BF7\u786E\u8BA4\u89C4\u683C\u6587\u4EF6\u540E\u7EE7\u7EED",
|
|
3327
|
+
triggerStep: "propose",
|
|
3328
|
+
targetStep: "apply",
|
|
3329
|
+
required: true
|
|
3330
|
+
},
|
|
3323
3331
|
{
|
|
3324
3332
|
type: "architecture",
|
|
3325
3333
|
name: "\u67B6\u6784\u8C03\u6574\u786E\u8BA4",
|
|
@@ -3355,19 +3363,15 @@ var ConfirmationManager = class {
|
|
|
3355
3363
|
confirmationPoints;
|
|
3356
3364
|
confirmations = /* @__PURE__ */ new Map();
|
|
3357
3365
|
constructor(customPoints) {
|
|
3358
|
-
|
|
3359
|
-
this.confirmationPoints = new Map(points.map((p) => [p.type, p]));
|
|
3366
|
+
this.confirmationPoints = customPoints || DEFAULT_CONFIRMATION_POINTS;
|
|
3360
3367
|
}
|
|
3361
3368
|
/**
|
|
3362
3369
|
* 获取指定阶段的确认点
|
|
3363
3370
|
*/
|
|
3364
3371
|
getConfirmationPointForTransition(from, to) {
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
}
|
|
3369
|
-
}
|
|
3370
|
-
return void 0;
|
|
3372
|
+
return this.confirmationPoints.find(
|
|
3373
|
+
(point) => point.triggerStep === from && point.targetStep === to
|
|
3374
|
+
);
|
|
3371
3375
|
}
|
|
3372
3376
|
/**
|
|
3373
3377
|
* 检查是否需要确认
|
|
@@ -3380,7 +3384,7 @@ var ConfirmationManager = class {
|
|
|
3380
3384
|
* 获取确认点详情
|
|
3381
3385
|
*/
|
|
3382
3386
|
getConfirmationPoint(type) {
|
|
3383
|
-
return this.confirmationPoints.
|
|
3387
|
+
return this.confirmationPoints.find((point) => point.type === type);
|
|
3384
3388
|
}
|
|
3385
3389
|
/**
|
|
3386
3390
|
* 记录确认
|
|
@@ -3424,14 +3428,14 @@ var ConfirmationManager = class {
|
|
|
3424
3428
|
* 获取所有确认点
|
|
3425
3429
|
*/
|
|
3426
3430
|
getAllConfirmationPoints() {
|
|
3427
|
-
return
|
|
3431
|
+
return [...this.confirmationPoints];
|
|
3428
3432
|
}
|
|
3429
3433
|
/**
|
|
3430
3434
|
* 获取指定阶段需要清除的确认点
|
|
3431
3435
|
*/
|
|
3432
3436
|
getConfirmationsToClear(targetStep) {
|
|
3433
3437
|
const types = [];
|
|
3434
|
-
for (const point of this.confirmationPoints
|
|
3438
|
+
for (const point of this.confirmationPoints) {
|
|
3435
3439
|
const stepOrder = ["explore", "new", "continue", "propose", "apply", "archive"];
|
|
3436
3440
|
const targetIndex = stepOrder.indexOf(targetStep);
|
|
3437
3441
|
const triggerIndex = stepOrder.indexOf(point.triggerStep);
|
|
@@ -3554,6 +3558,26 @@ var WorkflowEngine = class {
|
|
|
3554
3558
|
devStandards: this.devStandards
|
|
3555
3559
|
};
|
|
3556
3560
|
}
|
|
3561
|
+
/**
|
|
3562
|
+
* 获取规格文件路径
|
|
3563
|
+
*/
|
|
3564
|
+
getSpecFilePath() {
|
|
3565
|
+
if (!this.state) return null;
|
|
3566
|
+
return path6__namespace.join(this.openspecPath, "changes", `${this.state.id}-spec.md`);
|
|
3567
|
+
}
|
|
3568
|
+
/**
|
|
3569
|
+
* 检查规格文件是否存在
|
|
3570
|
+
*/
|
|
3571
|
+
async hasSpecFile() {
|
|
3572
|
+
const specPath = this.getSpecFilePath();
|
|
3573
|
+
if (!specPath) return false;
|
|
3574
|
+
try {
|
|
3575
|
+
await fs6__namespace.access(specPath);
|
|
3576
|
+
return true;
|
|
3577
|
+
} catch {
|
|
3578
|
+
return false;
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3557
3581
|
/**
|
|
3558
3582
|
* 启动新工作流
|
|
3559
3583
|
*/
|
|
@@ -4015,16 +4039,23 @@ async function handleNew(args, ctx) {
|
|
|
4015
4039
|
if (workflowEngine) {
|
|
4016
4040
|
const existingState = workflowEngine.getState();
|
|
4017
4041
|
if (existingState && existingState.status === "running") {
|
|
4042
|
+
if (existingState.currentStep === "explore" || existingState.currentStep === "propose") {
|
|
4043
|
+
const specPath = path6__namespace.join(workingDir, "openspec", "changes", `${existingState.id}-spec.md`);
|
|
4044
|
+
if (fs9__namespace.existsSync(specPath)) {
|
|
4045
|
+
return {
|
|
4046
|
+
output: chalk9__default.default.yellow("\u5F53\u524D\u5DE5\u4F5C\u6D41\u6B63\u5728\u7B49\u5F85\u89C4\u683C\u786E\u8BA4") + chalk9__default.default.gray(`
|
|
4047
|
+
|
|
4048
|
+
\u5DE5\u4F5C\u6D41: ${existingState.title}`) + chalk9__default.default.gray(`
|
|
4049
|
+
\u53D8\u66F4ID: ${existingState.id}`) + chalk9__default.default.cyan("\n\n\u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210:") + chalk9__default.default.white(`
|
|
4050
|
+
${specPath}`) + chalk9__default.default.yellow("\n\n\u8BF7\u786E\u8BA4\u89C4\u683C\u540E\u7EE7\u7EED:") + chalk9__default.default.gray("\n /opsx:confirm spec-review - \u786E\u8BA4\u89C4\u683C") + chalk9__default.default.gray("\n /opsx:status - \u67E5\u770B\u8BE6\u60C5")
|
|
4051
|
+
};
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4018
4054
|
return {
|
|
4019
4055
|
output: chalk9__default.default.yellow("\u5F53\u524D\u5DF2\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.gray(`
|
|
4020
4056
|
|
|
4021
4057
|
\u5DE5\u4F5C\u6D41: ${existingState.title}`) + chalk9__default.default.gray(`
|
|
4022
|
-
\u5F53\u524D\u9636\u6BB5: ${existingState.currentStep}`) + chalk9__default.default.gray(
|
|
4023
|
-
|
|
4024
|
-
\u9009\u9879:`) + chalk9__default.default.gray(`
|
|
4025
|
-
1. \u7EE7\u7EED\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:${existingState.currentStep}`) + chalk9__default.default.gray(`
|
|
4026
|
-
2. \u53D6\u6D88\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:cancel`) + chalk9__default.default.gray(`
|
|
4027
|
-
3. \u67E5\u770B\u5DE5\u4F5C\u6D41\u72B6\u6001: /opsx:status`)
|
|
4058
|
+
\u5F53\u524D\u9636\u6BB5: ${existingState.currentStep}`) + chalk9__default.default.gray("\n\n\u9009\u9879:") + chalk9__default.default.gray("\n 1. \u7EE7\u7EED\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:status") + chalk9__default.default.gray("\n 2. \u53D6\u6D88\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:cancel")
|
|
4028
4059
|
};
|
|
4029
4060
|
}
|
|
4030
4061
|
}
|
|
@@ -4039,6 +4070,7 @@ async function handleNew(args, ctx) {
|
|
|
4039
4070
|
async function newFeature(options, workingDir, workflowEngine) {
|
|
4040
4071
|
const cwd = workingDir || process.cwd();
|
|
4041
4072
|
const { requirement, forceComplexity } = options;
|
|
4073
|
+
const lines = [];
|
|
4042
4074
|
try {
|
|
4043
4075
|
const stats = await fs6__namespace.stat(cwd);
|
|
4044
4076
|
if (!stats.isDirectory()) {
|
|
@@ -4046,51 +4078,283 @@ async function newFeature(options, workingDir, workflowEngine) {
|
|
|
4046
4078
|
output: chalk9__default.default.red(`\u9519\u8BEF: ${cwd} \u4E0D\u662F\u6709\u6548\u76EE\u5F55`)
|
|
4047
4079
|
};
|
|
4048
4080
|
}
|
|
4049
|
-
} catch
|
|
4081
|
+
} catch {
|
|
4050
4082
|
return {
|
|
4051
4083
|
output: chalk9__default.default.red(`\u9519\u8BEF: \u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6743\u9650\u8BBF\u95EE ${cwd}`)
|
|
4052
4084
|
};
|
|
4053
4085
|
}
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4086
|
+
lines.push(chalk9__default.default.cyan("\u{1F50D} \u5206\u6790\u9879\u76EE..."));
|
|
4087
|
+
const context = await readProjectContext(cwd);
|
|
4088
|
+
lines.push(chalk9__default.default.gray(` \u9879\u76EE: ${context.name}`));
|
|
4089
|
+
lines.push(chalk9__default.default.gray(` \u7C7B\u578B: ${context.type}`));
|
|
4090
|
+
lines.push(chalk9__default.default.gray(` \u6846\u67B6: ${context.framework || "\u672A\u8BC6\u522B"}`));
|
|
4091
|
+
lines.push("");
|
|
4092
|
+
lines.push(chalk9__default.default.cyan("\u{1F4CA} \u5206\u6790\u9700\u6C42\u590D\u6742\u5EA6..."));
|
|
4093
|
+
const analysis = forceComplexity ? createForcedAnalysis(forceComplexity) : analyzeComplexity(requirement, context);
|
|
4094
|
+
lines.push(chalk9__default.default.gray(` \u590D\u6742\u5EA6: ${analysis.score}/10`));
|
|
4095
|
+
lines.push(chalk9__default.default.gray(` \u6D41\u7A0B\u7C7B\u578B: ${analysis.recommendation === "complex" ? "\u590D\u6742\u6D41\u7A0B" : "\u7B80\u5355\u6D41\u7A0B"}`));
|
|
4096
|
+
for (const factor of analysis.factors) {
|
|
4097
|
+
lines.push(chalk9__default.default.gray(` - ${factor}`));
|
|
4098
|
+
}
|
|
4099
|
+
lines.push("");
|
|
4100
|
+
lines.push(chalk9__default.default.cyan("\u{1F4CB} \u521D\u59CB\u5316\u5DE5\u4F5C\u6D41..."));
|
|
4101
|
+
const workflow = workflowEngine || new WorkflowEngine();
|
|
4102
|
+
if (!workflowEngine) {
|
|
4103
|
+
await workflow.initialize(cwd);
|
|
4104
|
+
}
|
|
4105
|
+
const state = await workflow.start(requirement, analysis.score, {
|
|
4106
|
+
title: extractTitle(requirement)
|
|
4107
|
+
});
|
|
4108
|
+
lines.push(chalk9__default.default.gray(` \u53D8\u66F4ID: ${state.id}`));
|
|
4109
|
+
lines.push(chalk9__default.default.gray(` \u5DE5\u4F5C\u6D41: ${state.type}`));
|
|
4110
|
+
lines.push("");
|
|
4111
|
+
lines.push(chalk9__default.default.cyan("\u{1F4DD} \u751F\u6210\u89C4\u683C\u62C6\u5206..."));
|
|
4112
|
+
const spec = await generateSpec(requirement, context, analysis, state.id);
|
|
4113
|
+
const specPath = await saveSpecFile(cwd, spec);
|
|
4114
|
+
lines.push(chalk9__default.default.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
4115
|
+
lines.push(chalk9__default.default.gray(` \u8DEF\u5F84: ${specPath}`));
|
|
4116
|
+
lines.push("");
|
|
4117
|
+
lines.push(chalk9__default.default.cyan.bold("\u{1F4CB} \u89C4\u683C\u6982\u89C8:"));
|
|
4118
|
+
lines.push(chalk9__default.default.white(`
|
|
4119
|
+
${spec.summary}`));
|
|
4120
|
+
if (spec.items.length > 0) {
|
|
4121
|
+
lines.push("");
|
|
4122
|
+
lines.push(chalk9__default.default.cyan(" \u4EFB\u52A1\u62C6\u5206:"));
|
|
4123
|
+
for (const item of spec.items) {
|
|
4124
|
+
const priorityIcon = item.priority === "high" ? "\u{1F534}" : item.priority === "medium" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
4125
|
+
lines.push(chalk9__default.default.gray(` ${priorityIcon} [${item.id}] ${item.title}`));
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
if (spec.risks.length > 0) {
|
|
4129
|
+
lines.push("");
|
|
4130
|
+
lines.push(chalk9__default.default.yellow(" \u26A0\uFE0F \u98CE\u9669\u63D0\u793A:"));
|
|
4131
|
+
for (const risk of spec.risks) {
|
|
4132
|
+
lines.push(chalk9__default.default.gray(` - ${risk}`));
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
lines.push("");
|
|
4136
|
+
lines.push(chalk9__default.default.yellow.bold("\u23F3 \u7B49\u5F85\u89C4\u683C\u786E\u8BA4"));
|
|
4137
|
+
lines.push(chalk9__default.default.gray("\n\u8BF7\u68C0\u67E5\u751F\u6210\u7684\u89C4\u683C\u6587\u4EF6\uFF0C\u786E\u8BA4\u540E\u7EE7\u7EED:"));
|
|
4138
|
+
lines.push(chalk9__default.default.white("\n /opsx:confirm spec-review - \u786E\u8BA4\u89C4\u683C\uFF0C\u8FDB\u5165\u4E0B\u4E00\u9636\u6BB5"));
|
|
4139
|
+
lines.push(chalk9__default.default.white(" /opsx:rollback explore - \u89C4\u683C\u4E0D\u7B26\uFF0C\u91CD\u65B0\u62C6\u5206"));
|
|
4140
|
+
lines.push(chalk9__default.default.white(" /opsx:status - \u67E5\u770B\u5DE5\u4F5C\u6D41\u72B6\u6001"));
|
|
4141
|
+
return { output: lines.join("\n") };
|
|
4142
|
+
}
|
|
4143
|
+
async function generateSpec(requirement, context, analysis, changeId) {
|
|
4144
|
+
const spec = {
|
|
4145
|
+
changeId,
|
|
4146
|
+
requirement,
|
|
4147
|
+
summary: "",
|
|
4148
|
+
items: [],
|
|
4149
|
+
architectureNotes: [],
|
|
4150
|
+
risks: [],
|
|
4151
|
+
suggestions: []
|
|
4152
|
+
};
|
|
4153
|
+
spec.summary = generateSummary(requirement);
|
|
4154
|
+
if (analysis.recommendation === "complex") {
|
|
4155
|
+
spec.items = generateComplexTasks(requirement, context, analysis);
|
|
4156
|
+
spec.architectureNotes = generateArchitectureNotes(requirement, context);
|
|
4157
|
+
} else {
|
|
4158
|
+
spec.items = generateSimpleTasks(requirement);
|
|
4159
|
+
}
|
|
4160
|
+
spec.risks = generateRisks(requirement, context, analysis);
|
|
4161
|
+
spec.suggestions = generateSuggestions(requirement, context, analysis);
|
|
4162
|
+
return spec;
|
|
4163
|
+
}
|
|
4164
|
+
function generateSummary(requirement) {
|
|
4165
|
+
const firstSentence = requirement.split(/[。!?\n]/)[0];
|
|
4166
|
+
return firstSentence.length > 100 ? firstSentence.slice(0, 97) + "..." : firstSentence;
|
|
4167
|
+
}
|
|
4168
|
+
function generateComplexTasks(requirement, context, analysis) {
|
|
4169
|
+
const items = [];
|
|
4170
|
+
let itemId = 1;
|
|
4171
|
+
const featurePatterns = [
|
|
4172
|
+
{ pattern: /用户|登录|注册|认证|权限/, title: "\u7528\u6237\u8BA4\u8BC1\u6A21\u5757", priority: "high" },
|
|
4173
|
+
{ pattern: /数据|存储|缓存|数据库/, title: "\u6570\u636E\u5C42\u5B9E\u73B0", priority: "high" },
|
|
4174
|
+
{ pattern: /接口|API|请求|响应/, title: "API \u63A5\u53E3\u5F00\u53D1", priority: "high" },
|
|
4175
|
+
{ pattern: /界面|页面|组件|UI/, title: "\u754C\u9762\u5F00\u53D1", priority: "medium" },
|
|
4176
|
+
{ pattern: /测试|单测|覆盖/, title: "\u6D4B\u8BD5\u7528\u4F8B\u7F16\u5199", priority: "medium" },
|
|
4177
|
+
{ pattern: /文档|说明/, title: "\u6587\u6863\u7F16\u5199", priority: "low" },
|
|
4178
|
+
{ pattern: /配置|设置/, title: "\u914D\u7F6E\u7BA1\u7406", priority: "low" },
|
|
4179
|
+
{ pattern: /优化|性能/, title: "\u6027\u80FD\u4F18\u5316", priority: "medium" },
|
|
4180
|
+
{ pattern: /安全|加密/, title: "\u5B89\u5168\u5B9E\u73B0", priority: "high" },
|
|
4181
|
+
{ pattern: /日志|监控/, title: "\u65E5\u5FD7\u76D1\u63A7", priority: "low" }
|
|
4182
|
+
];
|
|
4183
|
+
for (const { pattern, title, priority } of featurePatterns) {
|
|
4184
|
+
if (pattern.test(requirement)) {
|
|
4185
|
+
items.push({
|
|
4186
|
+
id: `T${itemId.toString().padStart(3, "0")}`,
|
|
4187
|
+
title,
|
|
4188
|
+
description: `${title}\u76F8\u5173\u7684\u529F\u80FD\u5B9E\u73B0`,
|
|
4189
|
+
priority,
|
|
4190
|
+
dependencies: itemId > 1 ? [`T${(itemId - 1).toString().padStart(3, "0")}`] : [],
|
|
4191
|
+
estimatedComplexity: priority === "high" ? 3 : priority === "medium" ? 2 : 1
|
|
4192
|
+
});
|
|
4193
|
+
itemId++;
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
if (items.length === 0) {
|
|
4197
|
+
items.push({
|
|
4198
|
+
id: "T001",
|
|
4199
|
+
title: "\u9700\u6C42\u5206\u6790\u4E0E\u8BBE\u8BA1",
|
|
4200
|
+
description: "\u5206\u6790\u9700\u6C42\u7EC6\u8282\uFF0C\u8BBE\u8BA1\u5B9E\u73B0\u65B9\u6848",
|
|
4201
|
+
priority: "high",
|
|
4202
|
+
dependencies: [],
|
|
4203
|
+
estimatedComplexity: 2
|
|
4063
4204
|
});
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
"",
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4205
|
+
items.push({
|
|
4206
|
+
id: "T002",
|
|
4207
|
+
title: "\u6838\u5FC3\u529F\u80FD\u5B9E\u73B0",
|
|
4208
|
+
description: requirement,
|
|
4209
|
+
priority: "high",
|
|
4210
|
+
dependencies: ["T001"],
|
|
4211
|
+
estimatedComplexity: analysis.score
|
|
4212
|
+
});
|
|
4213
|
+
items.push({
|
|
4214
|
+
id: "T003",
|
|
4215
|
+
title: "\u6D4B\u8BD5\u4E0E\u9A8C\u8BC1",
|
|
4216
|
+
description: "\u7F16\u5199\u6D4B\u8BD5\u7528\u4F8B\uFF0C\u9A8C\u8BC1\u529F\u80FD\u6B63\u786E\u6027",
|
|
4217
|
+
priority: "medium",
|
|
4218
|
+
dependencies: ["T002"],
|
|
4219
|
+
estimatedComplexity: 2
|
|
4220
|
+
});
|
|
4221
|
+
}
|
|
4222
|
+
return items;
|
|
4223
|
+
}
|
|
4224
|
+
function generateSimpleTasks(requirement, context) {
|
|
4225
|
+
return [
|
|
4226
|
+
{
|
|
4227
|
+
id: "T001",
|
|
4228
|
+
title: "\u5B9E\u73B0\u53D8\u66F4",
|
|
4229
|
+
description: requirement,
|
|
4230
|
+
priority: "high",
|
|
4231
|
+
dependencies: [],
|
|
4232
|
+
estimatedComplexity: 3
|
|
4233
|
+
},
|
|
4234
|
+
{
|
|
4235
|
+
id: "T002",
|
|
4236
|
+
title: "\u6D4B\u8BD5\u9A8C\u8BC1",
|
|
4237
|
+
description: "\u9A8C\u8BC1\u53D8\u66F4\u6B63\u786E\u6027",
|
|
4238
|
+
priority: "medium",
|
|
4239
|
+
dependencies: ["T001"],
|
|
4240
|
+
estimatedComplexity: 1
|
|
4089
4241
|
}
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4242
|
+
];
|
|
4243
|
+
}
|
|
4244
|
+
function generateArchitectureNotes(requirement, context) {
|
|
4245
|
+
const notes = [];
|
|
4246
|
+
if (context.framework) {
|
|
4247
|
+
notes.push(`\u9879\u76EE\u4F7F\u7528 ${context.framework} \u6846\u67B6\uFF0C\u9700\u9075\u5FAA\u5176\u6700\u4F73\u5B9E\u8DF5`);
|
|
4248
|
+
}
|
|
4249
|
+
if (requirement.includes("\u6A21\u5757") || requirement.includes("\u7EC4\u4EF6")) {
|
|
4250
|
+
notes.push("\u5EFA\u8BAE\u91C7\u7528\u6A21\u5757\u5316\u8BBE\u8BA1\uFF0C\u4FDD\u6301\u7EC4\u4EF6\u804C\u8D23\u5355\u4E00");
|
|
4251
|
+
}
|
|
4252
|
+
if (requirement.includes("API") || requirement.includes("\u63A5\u53E3")) {
|
|
4253
|
+
notes.push("API \u8BBE\u8BA1\u9700\u8003\u8651\u7248\u672C\u63A7\u5236\u548C\u5411\u540E\u517C\u5BB9");
|
|
4254
|
+
}
|
|
4255
|
+
if (context.structure.srcStructure) {
|
|
4256
|
+
notes.push(`\u73B0\u6709\u6E90\u7801\u7ED3\u6784: ${context.structure.srcStructure}`);
|
|
4257
|
+
}
|
|
4258
|
+
return notes;
|
|
4259
|
+
}
|
|
4260
|
+
function generateRisks(requirement, context, analysis) {
|
|
4261
|
+
const risks = [];
|
|
4262
|
+
if (!context.framework) {
|
|
4263
|
+
risks.push("\u9879\u76EE\u6846\u67B6\u672A\u8BC6\u522B\uFF0C\u53EF\u80FD\u5F71\u54CD\u4EE3\u7801\u98CE\u683C\u4E00\u81F4\u6027");
|
|
4264
|
+
}
|
|
4265
|
+
if (analysis.score >= 7) {
|
|
4266
|
+
risks.push("\u9700\u6C42\u590D\u6742\u5EA6\u8F83\u9AD8\uFF0C\u5EFA\u8BAE\u5206\u9636\u6BB5\u5B9E\u73B0");
|
|
4267
|
+
}
|
|
4268
|
+
if (requirement.includes("\u8FC1\u79FB") || requirement.includes("\u91CD\u6784")) {
|
|
4269
|
+
risks.push("\u6D89\u53CA\u73B0\u6709\u4EE3\u7801\u4FEE\u6539\uFF0C\u9700\u6CE8\u610F\u56DE\u5F52\u6D4B\u8BD5");
|
|
4270
|
+
}
|
|
4271
|
+
if (requirement.includes("\u6743\u9650") || requirement.includes("\u5B89\u5168")) {
|
|
4272
|
+
risks.push("\u6D89\u53CA\u5B89\u5168\u654F\u611F\u529F\u80FD\uFF0C\u9700\u8981\u989D\u5916\u5BA1\u67E5");
|
|
4273
|
+
}
|
|
4274
|
+
return risks;
|
|
4275
|
+
}
|
|
4276
|
+
function generateSuggestions(requirement, context, analysis) {
|
|
4277
|
+
const suggestions = [];
|
|
4278
|
+
if (context.norms.devStandards) {
|
|
4279
|
+
suggestions.push("\u9879\u76EE\u5DF2\u6709\u5F00\u53D1\u89C4\u8303\uFF0C\u8BF7\u9075\u5FAA\u73B0\u6709\u89C4\u8303");
|
|
4280
|
+
}
|
|
4281
|
+
if (analysis.recommendation === "complex") {
|
|
4282
|
+
suggestions.push("\u590D\u6742\u9700\u6C42\u5EFA\u8BAE\u5148\u8FDB\u884C\u6280\u672F\u8BC4\u5BA1");
|
|
4283
|
+
suggestions.push("\u5EFA\u8BAE\u8C03\u7528 $architect \u83B7\u53D6\u67B6\u6784\u5EFA\u8BAE");
|
|
4284
|
+
}
|
|
4285
|
+
if (context.techStack.length > 0) {
|
|
4286
|
+
suggestions.push(`\u6280\u672F\u6808: ${context.techStack.join(", ")}`);
|
|
4287
|
+
}
|
|
4288
|
+
return suggestions;
|
|
4289
|
+
}
|
|
4290
|
+
async function saveSpecFile(cwd, spec) {
|
|
4291
|
+
const changesDir = path6__namespace.join(cwd, "openspec", "changes");
|
|
4292
|
+
await fs6__namespace.mkdir(changesDir, { recursive: true });
|
|
4293
|
+
const specPath = path6__namespace.join(changesDir, `${spec.changeId}-spec.md`);
|
|
4294
|
+
const content = formatSpecFile(spec);
|
|
4295
|
+
await fs6__namespace.writeFile(specPath, content, "utf-8");
|
|
4296
|
+
return specPath;
|
|
4297
|
+
}
|
|
4298
|
+
function formatSpecFile(spec) {
|
|
4299
|
+
const lines = [];
|
|
4300
|
+
lines.push(`# Spec: ${spec.summary}`);
|
|
4301
|
+
lines.push("");
|
|
4302
|
+
lines.push(`> \u53D8\u66F4ID: ${spec.changeId}`);
|
|
4303
|
+
lines.push(`> \u751F\u6210\u65F6\u95F4: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
4304
|
+
lines.push("");
|
|
4305
|
+
lines.push("---");
|
|
4306
|
+
lines.push("");
|
|
4307
|
+
lines.push("## \u9700\u6C42\u6982\u8FF0");
|
|
4308
|
+
lines.push("");
|
|
4309
|
+
lines.push(spec.requirement);
|
|
4310
|
+
lines.push("");
|
|
4311
|
+
lines.push("## \u4EFB\u52A1\u62C6\u5206");
|
|
4312
|
+
lines.push("");
|
|
4313
|
+
for (const item of spec.items) {
|
|
4314
|
+
const priorityLabel = item.priority === "high" ? "\u{1F534} \u9AD8" : item.priority === "medium" ? "\u{1F7E1} \u4E2D" : "\u{1F7E2} \u4F4E";
|
|
4315
|
+
lines.push(`### ${item.id}: ${item.title}`);
|
|
4316
|
+
lines.push("");
|
|
4317
|
+
lines.push(`- **\u4F18\u5148\u7EA7**: ${priorityLabel}`);
|
|
4318
|
+
lines.push(`- **\u63CF\u8FF0**: ${item.description}`);
|
|
4319
|
+
lines.push(`- **\u9884\u4F30\u590D\u6742\u5EA6**: ${item.estimatedComplexity}/5`);
|
|
4320
|
+
if (item.dependencies.length > 0) {
|
|
4321
|
+
lines.push(`- **\u4F9D\u8D56**: ${item.dependencies.join(", ")}`);
|
|
4322
|
+
}
|
|
4323
|
+
lines.push("");
|
|
4324
|
+
}
|
|
4325
|
+
if (spec.architectureNotes.length > 0) {
|
|
4326
|
+
lines.push("## \u67B6\u6784\u8BF4\u660E");
|
|
4327
|
+
lines.push("");
|
|
4328
|
+
for (const note of spec.architectureNotes) {
|
|
4329
|
+
lines.push(`- ${note}`);
|
|
4330
|
+
}
|
|
4331
|
+
lines.push("");
|
|
4332
|
+
}
|
|
4333
|
+
if (spec.risks.length > 0) {
|
|
4334
|
+
lines.push("## \u26A0\uFE0F \u98CE\u9669\u8BC4\u4F30");
|
|
4335
|
+
lines.push("");
|
|
4336
|
+
for (const risk of spec.risks) {
|
|
4337
|
+
lines.push(`- ${risk}`);
|
|
4338
|
+
}
|
|
4339
|
+
lines.push("");
|
|
4340
|
+
}
|
|
4341
|
+
if (spec.suggestions.length > 0) {
|
|
4342
|
+
lines.push("## \u{1F4A1} \u5EFA\u8BAE");
|
|
4343
|
+
lines.push("");
|
|
4344
|
+
for (const suggestion of spec.suggestions) {
|
|
4345
|
+
lines.push(`- ${suggestion}`);
|
|
4346
|
+
}
|
|
4347
|
+
lines.push("");
|
|
4093
4348
|
}
|
|
4349
|
+
lines.push("---");
|
|
4350
|
+
lines.push("");
|
|
4351
|
+
lines.push("## \u786E\u8BA4\u72B6\u6001");
|
|
4352
|
+
lines.push("");
|
|
4353
|
+
lines.push("- [ ] \u89C4\u683C\u5DF2\u5BA1\u9605");
|
|
4354
|
+
lines.push("- [ ] \u4EFB\u52A1\u62C6\u5206\u5DF2\u786E\u8BA4");
|
|
4355
|
+
lines.push("");
|
|
4356
|
+
lines.push("**\u786E\u8BA4\u540E\u6267\u884C**: `/opsx:confirm spec-review`");
|
|
4357
|
+
return lines.join("\n");
|
|
4094
4358
|
}
|
|
4095
4359
|
function parseArgs(args) {
|
|
4096
4360
|
let forceComplexity;
|
|
@@ -4115,42 +4379,52 @@ async function readProjectContext(cwd) {
|
|
|
4115
4379
|
type: "unknown",
|
|
4116
4380
|
framework: null,
|
|
4117
4381
|
techStack: [],
|
|
4118
|
-
description: ""
|
|
4382
|
+
description: "",
|
|
4383
|
+
structure: {
|
|
4384
|
+
directories: [],
|
|
4385
|
+
keyFiles: [],
|
|
4386
|
+
srcStructure: ""
|
|
4387
|
+
},
|
|
4388
|
+
norms: {
|
|
4389
|
+
devStandards: "",
|
|
4390
|
+
patterns: "",
|
|
4391
|
+
weights: ""
|
|
4392
|
+
}
|
|
4119
4393
|
};
|
|
4394
|
+
const [agentsContext, configContext, normsContext, structureContext] = await Promise.all([
|
|
4395
|
+
readAgentsMd(cwd),
|
|
4396
|
+
readConfigYaml(cwd),
|
|
4397
|
+
readNorms(cwd),
|
|
4398
|
+
analyzeStructure(cwd)
|
|
4399
|
+
]);
|
|
4400
|
+
return {
|
|
4401
|
+
...defaultContext,
|
|
4402
|
+
...agentsContext,
|
|
4403
|
+
...configContext,
|
|
4404
|
+
norms: normsContext,
|
|
4405
|
+
structure: structureContext
|
|
4406
|
+
};
|
|
4407
|
+
}
|
|
4408
|
+
async function readAgentsMd(cwd) {
|
|
4120
4409
|
const agentsPath = path6__namespace.join(cwd, "AGENTS.md");
|
|
4121
4410
|
try {
|
|
4122
4411
|
const stats = await fs6__namespace.stat(agentsPath);
|
|
4123
4412
|
if (stats.size > MAX_FILE_SIZE2) {
|
|
4124
4413
|
console.warn(`\u8B66\u544A: AGENTS.md \u6587\u4EF6\u8FC7\u5927 (${stats.size} bytes)\uFF0C\u8DF3\u8FC7\u8BFB\u53D6`);
|
|
4125
|
-
return
|
|
4414
|
+
return {};
|
|
4126
4415
|
}
|
|
4127
4416
|
const content = await fs6__namespace.readFile(agentsPath, "utf-8");
|
|
4128
|
-
return parseAgentsMd(content
|
|
4417
|
+
return parseAgentsMd(content);
|
|
4129
4418
|
} catch (e) {
|
|
4130
4419
|
const err = e;
|
|
4131
4420
|
if (err.code !== "ENOENT") {
|
|
4132
4421
|
console.warn(`\u8B66\u544A: \u65E0\u6CD5\u8BFB\u53D6 AGENTS.md - ${err.message}`);
|
|
4133
4422
|
}
|
|
4423
|
+
return {};
|
|
4134
4424
|
}
|
|
4135
|
-
const configPath = path6__namespace.join(cwd, "openspec", "config.yaml");
|
|
4136
|
-
try {
|
|
4137
|
-
const stats = await fs6__namespace.stat(configPath);
|
|
4138
|
-
if (stats.size > MAX_FILE_SIZE2) {
|
|
4139
|
-
console.warn(`\u8B66\u544A: config.yaml \u6587\u4EF6\u8FC7\u5927\uFF0C\u8DF3\u8FC7\u8BFB\u53D6`);
|
|
4140
|
-
return defaultContext;
|
|
4141
|
-
}
|
|
4142
|
-
const content = await fs6__namespace.readFile(configPath, "utf-8");
|
|
4143
|
-
return parseConfigYaml(content, defaultContext);
|
|
4144
|
-
} catch (e) {
|
|
4145
|
-
const err = e;
|
|
4146
|
-
if (err.code !== "ENOENT") {
|
|
4147
|
-
console.warn(`\u8B66\u544A: \u65E0\u6CD5\u8BFB\u53D6 config.yaml - ${err.message}`);
|
|
4148
|
-
}
|
|
4149
|
-
}
|
|
4150
|
-
return defaultContext;
|
|
4151
4425
|
}
|
|
4152
|
-
function parseAgentsMd(content
|
|
4153
|
-
const context = {
|
|
4426
|
+
function parseAgentsMd(content) {
|
|
4427
|
+
const context = {};
|
|
4154
4428
|
const nameMatch = content.match(/\|\s*项目名称\s*\|\s*([^\s|]+)/);
|
|
4155
4429
|
if (nameMatch) {
|
|
4156
4430
|
context.name = nameMatch[1];
|
|
@@ -4167,10 +4441,32 @@ function parseAgentsMd(content, defaults) {
|
|
|
4167
4441
|
if (descMatch) {
|
|
4168
4442
|
context.description = descMatch[1].trim();
|
|
4169
4443
|
}
|
|
4444
|
+
const techStackMatch = content.match(/技术栈[::]\s*([^\n]+)/);
|
|
4445
|
+
if (techStackMatch) {
|
|
4446
|
+
context.techStack = techStackMatch[1].split(/[,,、]/).map((s) => s.trim()).filter(Boolean);
|
|
4447
|
+
}
|
|
4170
4448
|
return context;
|
|
4171
4449
|
}
|
|
4172
|
-
function
|
|
4173
|
-
const
|
|
4450
|
+
async function readConfigYaml(cwd) {
|
|
4451
|
+
const configPath = path6__namespace.join(cwd, "openspec", "config.yaml");
|
|
4452
|
+
try {
|
|
4453
|
+
const stats = await fs6__namespace.stat(configPath);
|
|
4454
|
+
if (stats.size > MAX_FILE_SIZE2) {
|
|
4455
|
+
console.warn("\u8B66\u544A: config.yaml \u6587\u4EF6\u8FC7\u5927\uFF0C\u8DF3\u8FC7\u8BFB\u53D6");
|
|
4456
|
+
return {};
|
|
4457
|
+
}
|
|
4458
|
+
const content = await fs6__namespace.readFile(configPath, "utf-8");
|
|
4459
|
+
return parseConfigYaml(content);
|
|
4460
|
+
} catch (e) {
|
|
4461
|
+
const err = e;
|
|
4462
|
+
if (err.code !== "ENOENT") {
|
|
4463
|
+
console.warn(`\u8B66\u544A: \u65E0\u6CD5\u8BFB\u53D6 config.yaml - ${err.message}`);
|
|
4464
|
+
}
|
|
4465
|
+
return {};
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
function parseConfigYaml(content) {
|
|
4469
|
+
const context = {};
|
|
4174
4470
|
const nameMatch = content.match(/name:\s*(.+)/);
|
|
4175
4471
|
if (nameMatch) {
|
|
4176
4472
|
context.name = nameMatch[1].trim();
|
|
@@ -4185,6 +4481,67 @@ function parseConfigYaml(content, defaults) {
|
|
|
4185
4481
|
}
|
|
4186
4482
|
return context;
|
|
4187
4483
|
}
|
|
4484
|
+
async function readNorms(cwd) {
|
|
4485
|
+
const normsDir = path6__namespace.join(cwd, ".sf-cli", "norms");
|
|
4486
|
+
const norms = {
|
|
4487
|
+
devStandards: "",
|
|
4488
|
+
patterns: "",
|
|
4489
|
+
weights: ""
|
|
4490
|
+
};
|
|
4491
|
+
try {
|
|
4492
|
+
const devStandardsPath = path6__namespace.join(normsDir, "devstanded.md");
|
|
4493
|
+
norms.devStandards = await fs6__namespace.readFile(devStandardsPath, "utf-8").catch(() => "");
|
|
4494
|
+
} catch {
|
|
4495
|
+
}
|
|
4496
|
+
try {
|
|
4497
|
+
const patternsPath = path6__namespace.join(normsDir, "patterns.json");
|
|
4498
|
+
norms.patterns = await fs6__namespace.readFile(patternsPath, "utf-8").catch(() => "");
|
|
4499
|
+
} catch {
|
|
4500
|
+
}
|
|
4501
|
+
try {
|
|
4502
|
+
const weightsPath = path6__namespace.join(normsDir, "weights.json");
|
|
4503
|
+
norms.weights = await fs6__namespace.readFile(weightsPath, "utf-8").catch(() => "");
|
|
4504
|
+
} catch {
|
|
4505
|
+
}
|
|
4506
|
+
return norms;
|
|
4507
|
+
}
|
|
4508
|
+
async function analyzeStructure(cwd) {
|
|
4509
|
+
const structure = {
|
|
4510
|
+
directories: [],
|
|
4511
|
+
keyFiles: [],
|
|
4512
|
+
srcStructure: ""
|
|
4513
|
+
};
|
|
4514
|
+
try {
|
|
4515
|
+
const entries = await fs6__namespace.readdir(cwd, { withFileTypes: true });
|
|
4516
|
+
for (const entry of entries) {
|
|
4517
|
+
if (entry.isDirectory() && !["node_modules", "dist", ".git", "build"].includes(entry.name)) {
|
|
4518
|
+
structure.directories.push(entry.name);
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
const keyFiles = [
|
|
4522
|
+
"package.json",
|
|
4523
|
+
"tsconfig.json",
|
|
4524
|
+
"AGENTS.md",
|
|
4525
|
+
"README.md"
|
|
4526
|
+
];
|
|
4527
|
+
for (const file of keyFiles) {
|
|
4528
|
+
const filePath = path6__namespace.join(cwd, file);
|
|
4529
|
+
try {
|
|
4530
|
+
await fs6__namespace.access(filePath);
|
|
4531
|
+
structure.keyFiles.push(file);
|
|
4532
|
+
} catch {
|
|
4533
|
+
}
|
|
4534
|
+
}
|
|
4535
|
+
const srcDir = path6__namespace.join(cwd, "src");
|
|
4536
|
+
try {
|
|
4537
|
+
const srcEntries = await fs6__namespace.readdir(srcDir, { withFileTypes: true });
|
|
4538
|
+
structure.srcStructure = srcEntries.filter((e) => e.isDirectory()).map((e) => e.name).join("/");
|
|
4539
|
+
} catch {
|
|
4540
|
+
}
|
|
4541
|
+
} catch (e) {
|
|
4542
|
+
}
|
|
4543
|
+
return { structure };
|
|
4544
|
+
}
|
|
4188
4545
|
function analyzeComplexity(requirement, context) {
|
|
4189
4546
|
let score = 3;
|
|
4190
4547
|
const factors = [];
|
|
@@ -4990,7 +5347,7 @@ async function handleOpsx(command, args, ctx) {
|
|
|
4990
5347
|
case "rollback":
|
|
4991
5348
|
return handleRollback(workflow, args);
|
|
4992
5349
|
case "confirm":
|
|
4993
|
-
return handleConfirm(workflow, args);
|
|
5350
|
+
return handleConfirm(workflow, args, ctx);
|
|
4994
5351
|
case "next":
|
|
4995
5352
|
return handleNext(workflow);
|
|
4996
5353
|
case "auto":
|
|
@@ -5358,6 +5715,16 @@ async function handleConfirm(workflow, args, ctx) {
|
|
|
5358
5715
|
const type = args[0];
|
|
5359
5716
|
if (!type) {
|
|
5360
5717
|
const pendingPoint = workflow.getCurrentConfirmationPoint();
|
|
5718
|
+
const specPath = await checkPendingSpec(ctx.options.workingDirectory, state.id);
|
|
5719
|
+
if (specPath) {
|
|
5720
|
+
return {
|
|
5721
|
+
output: chalk9__default.default.cyan("\u{1F4CB} \u89C4\u683C\u6587\u4EF6\u5F85\u786E\u8BA4") + chalk9__default.default.gray(`
|
|
5722
|
+
|
|
5723
|
+
\u89C4\u683C\u6587\u4EF6: ${specPath}`) + chalk9__default.default.gray(`
|
|
5724
|
+
|
|
5725
|
+
\u8BF7\u68C0\u67E5\u89C4\u683C\u6587\u4EF6\u540E\u786E\u8BA4:`) + chalk9__default.default.white("\n /opsx:confirm spec-review - \u786E\u8BA4\u89C4\u683C") + chalk9__default.default.white("\n /opsx:rollback explore - \u91CD\u65B0\u62C6\u5206")
|
|
5726
|
+
};
|
|
5727
|
+
}
|
|
5361
5728
|
if (pendingPoint) {
|
|
5362
5729
|
return {
|
|
5363
5730
|
output: chalk9__default.default.cyan("\u5F85\u786E\u8BA4\u7684\u68C0\u67E5\u70B9:") + chalk9__default.default.white(`
|
|
@@ -5379,12 +5746,54 @@ ${generateConfirmationPrompt(pendingPoint)}`) + chalk9__default.default.gray(`
|
|
|
5379
5746
|
}
|
|
5380
5747
|
const comment = args.slice(1).join(" ");
|
|
5381
5748
|
workflow.confirm(type, comment);
|
|
5382
|
-
|
|
5383
|
-
|
|
5749
|
+
const lines = [];
|
|
5750
|
+
lines.push(chalk9__default.default.green("\u2713 \u5DF2\u786E\u8BA4"));
|
|
5751
|
+
lines.push(chalk9__default.default.white(`
|
|
5752
|
+
${point.name}`));
|
|
5753
|
+
if (comment) {
|
|
5754
|
+
lines.push(chalk9__default.default.gray(`
|
|
5755
|
+
\u5907\u6CE8: ${comment}`));
|
|
5756
|
+
}
|
|
5757
|
+
if (type === "spec-review") {
|
|
5758
|
+
const allowed = workflow.getAllowedTransitions();
|
|
5759
|
+
if (allowed.length > 0) {
|
|
5760
|
+
const nextStep = allowed[0];
|
|
5761
|
+
try {
|
|
5762
|
+
const transition = await workflow.transition(nextStep);
|
|
5763
|
+
lines.push("");
|
|
5764
|
+
lines.push(chalk9__default.default.cyan(`\u2713 \u5DF2\u81EA\u52A8\u8FDB\u5165 ${nextStep} \u9636\u6BB5`));
|
|
5765
|
+
lines.push(chalk9__default.default.gray(`\u8F6C\u6362: ${transition.from} \u2192 ${transition.to}`));
|
|
5766
|
+
if (nextStep === "new") {
|
|
5767
|
+
lines.push(chalk9__default.default.yellow("\n\u4E0B\u4E00\u6B65: \u8BBE\u8BA1\u65B9\u6848"));
|
|
5768
|
+
lines.push(chalk9__default.default.gray(" \u53EF\u8C03\u7528 $architect \u6216 $frontend-dev \u8FDB\u884C\u8BBE\u8BA1"));
|
|
5769
|
+
} else if (nextStep === "apply") {
|
|
5770
|
+
lines.push(chalk9__default.default.yellow("\n\u4E0B\u4E00\u6B65: \u6267\u884C\u53D8\u66F4"));
|
|
5771
|
+
lines.push(chalk9__default.default.gray(" \u53EF\u8C03\u7528 $frontend-dev \u6267\u884C\u4EE3\u7801\u4FEE\u6539"));
|
|
5772
|
+
}
|
|
5773
|
+
return { output: lines.join("\n") };
|
|
5774
|
+
} catch (e) {
|
|
5775
|
+
if (e instanceof ConfirmationRequiredError) {
|
|
5776
|
+
lines.push(chalk9__default.default.yellow("\n\u26A0 \u8FD8\u9700\u8981\u786E\u8BA4:") + chalk9__default.default.white(`
|
|
5777
|
+
${generateConfirmationPrompt(e.point)}`) + chalk9__default.default.cyan(`
|
|
5384
5778
|
|
|
5385
|
-
${point.
|
|
5386
|
-
|
|
5387
|
-
|
|
5779
|
+
\u4F7F\u7528 /opsx:confirm ${e.point.type}`));
|
|
5780
|
+
return { output: lines.join("\n") };
|
|
5781
|
+
}
|
|
5782
|
+
throw e;
|
|
5783
|
+
}
|
|
5784
|
+
}
|
|
5785
|
+
}
|
|
5786
|
+
lines.push(chalk9__default.default.yellow("\n\u4F7F\u7528 /opsx:next \u7EE7\u7EED\u4E0B\u4E00\u9636\u6BB5"));
|
|
5787
|
+
return { output: lines.join("\n") };
|
|
5788
|
+
}
|
|
5789
|
+
async function checkPendingSpec(workingDirectory, changeId) {
|
|
5790
|
+
const specPath = path6__namespace.join(workingDirectory, "openspec", "changes", `${changeId}-spec.md`);
|
|
5791
|
+
try {
|
|
5792
|
+
await fs9__namespace.promises.access(specPath);
|
|
5793
|
+
return specPath;
|
|
5794
|
+
} catch {
|
|
5795
|
+
return null;
|
|
5796
|
+
}
|
|
5388
5797
|
}
|
|
5389
5798
|
async function handleNext(workflow, args, ctx) {
|
|
5390
5799
|
const state = workflow.getState();
|