@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/index.js
CHANGED
|
@@ -3629,12 +3629,20 @@ function getScheduleRuleDescription(step) {
|
|
|
3629
3629
|
var DEFAULT_CONFIRMATION_POINTS = [
|
|
3630
3630
|
{
|
|
3631
3631
|
type: "spec-review",
|
|
3632
|
-
name: "\u89C4\
|
|
3633
|
-
description: "\u89C4\
|
|
3632
|
+
name: "\u89C4\u683C\u786E\u8BA4",
|
|
3633
|
+
description: "\u89C4\u683C\u62C6\u5206\u5DF2\u5B8C\u6210\uFF0C\u8BF7\u786E\u8BA4\u89C4\u683C\u6587\u4EF6\u540E\u7EE7\u7EED",
|
|
3634
3634
|
triggerStep: "explore",
|
|
3635
3635
|
targetStep: "new",
|
|
3636
3636
|
required: true
|
|
3637
3637
|
},
|
|
3638
|
+
{
|
|
3639
|
+
type: "spec-review",
|
|
3640
|
+
name: "\u89C4\u683C\u786E\u8BA4",
|
|
3641
|
+
description: "\u89C4\u683C\u62C6\u5206\u5DF2\u5B8C\u6210\uFF0C\u8BF7\u786E\u8BA4\u89C4\u683C\u6587\u4EF6\u540E\u7EE7\u7EED",
|
|
3642
|
+
triggerStep: "propose",
|
|
3643
|
+
targetStep: "apply",
|
|
3644
|
+
required: true
|
|
3645
|
+
},
|
|
3638
3646
|
{
|
|
3639
3647
|
type: "architecture",
|
|
3640
3648
|
name: "\u67B6\u6784\u8C03\u6574\u786E\u8BA4",
|
|
@@ -3670,19 +3678,15 @@ var ConfirmationManager = class {
|
|
|
3670
3678
|
confirmationPoints;
|
|
3671
3679
|
confirmations = /* @__PURE__ */ new Map();
|
|
3672
3680
|
constructor(customPoints) {
|
|
3673
|
-
|
|
3674
|
-
this.confirmationPoints = new Map(points.map((p) => [p.type, p]));
|
|
3681
|
+
this.confirmationPoints = customPoints || DEFAULT_CONFIRMATION_POINTS;
|
|
3675
3682
|
}
|
|
3676
3683
|
/**
|
|
3677
3684
|
* 获取指定阶段的确认点
|
|
3678
3685
|
*/
|
|
3679
3686
|
getConfirmationPointForTransition(from, to) {
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
}
|
|
3684
|
-
}
|
|
3685
|
-
return void 0;
|
|
3687
|
+
return this.confirmationPoints.find(
|
|
3688
|
+
(point) => point.triggerStep === from && point.targetStep === to
|
|
3689
|
+
);
|
|
3686
3690
|
}
|
|
3687
3691
|
/**
|
|
3688
3692
|
* 检查是否需要确认
|
|
@@ -3695,7 +3699,7 @@ var ConfirmationManager = class {
|
|
|
3695
3699
|
* 获取确认点详情
|
|
3696
3700
|
*/
|
|
3697
3701
|
getConfirmationPoint(type) {
|
|
3698
|
-
return this.confirmationPoints.
|
|
3702
|
+
return this.confirmationPoints.find((point) => point.type === type);
|
|
3699
3703
|
}
|
|
3700
3704
|
/**
|
|
3701
3705
|
* 记录确认
|
|
@@ -3739,14 +3743,14 @@ var ConfirmationManager = class {
|
|
|
3739
3743
|
* 获取所有确认点
|
|
3740
3744
|
*/
|
|
3741
3745
|
getAllConfirmationPoints() {
|
|
3742
|
-
return
|
|
3746
|
+
return [...this.confirmationPoints];
|
|
3743
3747
|
}
|
|
3744
3748
|
/**
|
|
3745
3749
|
* 获取指定阶段需要清除的确认点
|
|
3746
3750
|
*/
|
|
3747
3751
|
getConfirmationsToClear(targetStep) {
|
|
3748
3752
|
const types = [];
|
|
3749
|
-
for (const point of this.confirmationPoints
|
|
3753
|
+
for (const point of this.confirmationPoints) {
|
|
3750
3754
|
const stepOrder = ["explore", "new", "continue", "propose", "apply", "archive"];
|
|
3751
3755
|
const targetIndex = stepOrder.indexOf(targetStep);
|
|
3752
3756
|
const triggerIndex = stepOrder.indexOf(point.triggerStep);
|
|
@@ -3869,6 +3873,26 @@ var WorkflowEngine = class {
|
|
|
3869
3873
|
devStandards: this.devStandards
|
|
3870
3874
|
};
|
|
3871
3875
|
}
|
|
3876
|
+
/**
|
|
3877
|
+
* 获取规格文件路径
|
|
3878
|
+
*/
|
|
3879
|
+
getSpecFilePath() {
|
|
3880
|
+
if (!this.state) return null;
|
|
3881
|
+
return path4__namespace.join(this.openspecPath, "changes", `${this.state.id}-spec.md`);
|
|
3882
|
+
}
|
|
3883
|
+
/**
|
|
3884
|
+
* 检查规格文件是否存在
|
|
3885
|
+
*/
|
|
3886
|
+
async hasSpecFile() {
|
|
3887
|
+
const specPath = this.getSpecFilePath();
|
|
3888
|
+
if (!specPath) return false;
|
|
3889
|
+
try {
|
|
3890
|
+
await fs4__namespace.access(specPath);
|
|
3891
|
+
return true;
|
|
3892
|
+
} catch {
|
|
3893
|
+
return false;
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3872
3896
|
/**
|
|
3873
3897
|
* 启动新工作流
|
|
3874
3898
|
*/
|
|
@@ -6732,16 +6756,23 @@ async function handleNew(args, ctx) {
|
|
|
6732
6756
|
if (workflowEngine) {
|
|
6733
6757
|
const existingState = workflowEngine.getState();
|
|
6734
6758
|
if (existingState && existingState.status === "running") {
|
|
6759
|
+
if (existingState.currentStep === "explore" || existingState.currentStep === "propose") {
|
|
6760
|
+
const specPath = path4__namespace.join(workingDir, "openspec", "changes", `${existingState.id}-spec.md`);
|
|
6761
|
+
if (fs10__namespace.existsSync(specPath)) {
|
|
6762
|
+
return {
|
|
6763
|
+
output: chalk9__default.default.yellow("\u5F53\u524D\u5DE5\u4F5C\u6D41\u6B63\u5728\u7B49\u5F85\u89C4\u683C\u786E\u8BA4") + chalk9__default.default.gray(`
|
|
6764
|
+
|
|
6765
|
+
\u5DE5\u4F5C\u6D41: ${existingState.title}`) + chalk9__default.default.gray(`
|
|
6766
|
+
\u53D8\u66F4ID: ${existingState.id}`) + chalk9__default.default.cyan("\n\n\u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210:") + chalk9__default.default.white(`
|
|
6767
|
+
${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")
|
|
6768
|
+
};
|
|
6769
|
+
}
|
|
6770
|
+
}
|
|
6735
6771
|
return {
|
|
6736
6772
|
output: chalk9__default.default.yellow("\u5F53\u524D\u5DF2\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.gray(`
|
|
6737
6773
|
|
|
6738
6774
|
\u5DE5\u4F5C\u6D41: ${existingState.title}`) + chalk9__default.default.gray(`
|
|
6739
|
-
\u5F53\u524D\u9636\u6BB5: ${existingState.currentStep}`) + chalk9__default.default.gray(
|
|
6740
|
-
|
|
6741
|
-
\u9009\u9879:`) + chalk9__default.default.gray(`
|
|
6742
|
-
1. \u7EE7\u7EED\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:${existingState.currentStep}`) + chalk9__default.default.gray(`
|
|
6743
|
-
2. \u53D6\u6D88\u5F53\u524D\u5DE5\u4F5C\u6D41: /opsx:cancel`) + chalk9__default.default.gray(`
|
|
6744
|
-
3. \u67E5\u770B\u5DE5\u4F5C\u6D41\u72B6\u6001: /opsx:status`)
|
|
6775
|
+
\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")
|
|
6745
6776
|
};
|
|
6746
6777
|
}
|
|
6747
6778
|
}
|
|
@@ -6756,6 +6787,7 @@ async function handleNew(args, ctx) {
|
|
|
6756
6787
|
async function newFeature(options, workingDir, workflowEngine) {
|
|
6757
6788
|
const cwd = workingDir || process.cwd();
|
|
6758
6789
|
const { requirement, forceComplexity } = options;
|
|
6790
|
+
const lines = [];
|
|
6759
6791
|
try {
|
|
6760
6792
|
const stats = await fs4__namespace.stat(cwd);
|
|
6761
6793
|
if (!stats.isDirectory()) {
|
|
@@ -6763,51 +6795,283 @@ async function newFeature(options, workingDir, workflowEngine) {
|
|
|
6763
6795
|
output: chalk9__default.default.red(`\u9519\u8BEF: ${cwd} \u4E0D\u662F\u6709\u6548\u76EE\u5F55`)
|
|
6764
6796
|
};
|
|
6765
6797
|
}
|
|
6766
|
-
} catch
|
|
6798
|
+
} catch {
|
|
6767
6799
|
return {
|
|
6768
6800
|
output: chalk9__default.default.red(`\u9519\u8BEF: \u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u65E0\u6743\u9650\u8BBF\u95EE ${cwd}`)
|
|
6769
6801
|
};
|
|
6770
6802
|
}
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6803
|
+
lines.push(chalk9__default.default.cyan("\u{1F50D} \u5206\u6790\u9879\u76EE..."));
|
|
6804
|
+
const context = await readProjectContext(cwd);
|
|
6805
|
+
lines.push(chalk9__default.default.gray(` \u9879\u76EE: ${context.name}`));
|
|
6806
|
+
lines.push(chalk9__default.default.gray(` \u7C7B\u578B: ${context.type}`));
|
|
6807
|
+
lines.push(chalk9__default.default.gray(` \u6846\u67B6: ${context.framework || "\u672A\u8BC6\u522B"}`));
|
|
6808
|
+
lines.push("");
|
|
6809
|
+
lines.push(chalk9__default.default.cyan("\u{1F4CA} \u5206\u6790\u9700\u6C42\u590D\u6742\u5EA6..."));
|
|
6810
|
+
const analysis = forceComplexity ? createForcedAnalysis(forceComplexity) : analyzeComplexity(requirement, context);
|
|
6811
|
+
lines.push(chalk9__default.default.gray(` \u590D\u6742\u5EA6: ${analysis.score}/10`));
|
|
6812
|
+
lines.push(chalk9__default.default.gray(` \u6D41\u7A0B\u7C7B\u578B: ${analysis.recommendation === "complex" ? "\u590D\u6742\u6D41\u7A0B" : "\u7B80\u5355\u6D41\u7A0B"}`));
|
|
6813
|
+
for (const factor of analysis.factors) {
|
|
6814
|
+
lines.push(chalk9__default.default.gray(` - ${factor}`));
|
|
6815
|
+
}
|
|
6816
|
+
lines.push("");
|
|
6817
|
+
lines.push(chalk9__default.default.cyan("\u{1F4CB} \u521D\u59CB\u5316\u5DE5\u4F5C\u6D41..."));
|
|
6818
|
+
const workflow = workflowEngine || new WorkflowEngine();
|
|
6819
|
+
if (!workflowEngine) {
|
|
6820
|
+
await workflow.initialize(cwd);
|
|
6821
|
+
}
|
|
6822
|
+
const state = await workflow.start(requirement, analysis.score, {
|
|
6823
|
+
title: extractTitle(requirement)
|
|
6824
|
+
});
|
|
6825
|
+
lines.push(chalk9__default.default.gray(` \u53D8\u66F4ID: ${state.id}`));
|
|
6826
|
+
lines.push(chalk9__default.default.gray(` \u5DE5\u4F5C\u6D41: ${state.type}`));
|
|
6827
|
+
lines.push("");
|
|
6828
|
+
lines.push(chalk9__default.default.cyan("\u{1F4DD} \u751F\u6210\u89C4\u683C\u62C6\u5206..."));
|
|
6829
|
+
const spec = await generateSpec(requirement, context, analysis, state.id);
|
|
6830
|
+
const specPath = await saveSpecFile(cwd, spec);
|
|
6831
|
+
lines.push(chalk9__default.default.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
6832
|
+
lines.push(chalk9__default.default.gray(` \u8DEF\u5F84: ${specPath}`));
|
|
6833
|
+
lines.push("");
|
|
6834
|
+
lines.push(chalk9__default.default.cyan.bold("\u{1F4CB} \u89C4\u683C\u6982\u89C8:"));
|
|
6835
|
+
lines.push(chalk9__default.default.white(`
|
|
6836
|
+
${spec.summary}`));
|
|
6837
|
+
if (spec.items.length > 0) {
|
|
6838
|
+
lines.push("");
|
|
6839
|
+
lines.push(chalk9__default.default.cyan(" \u4EFB\u52A1\u62C6\u5206:"));
|
|
6840
|
+
for (const item of spec.items) {
|
|
6841
|
+
const priorityIcon = item.priority === "high" ? "\u{1F534}" : item.priority === "medium" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
6842
|
+
lines.push(chalk9__default.default.gray(` ${priorityIcon} [${item.id}] ${item.title}`));
|
|
6843
|
+
}
|
|
6844
|
+
}
|
|
6845
|
+
if (spec.risks.length > 0) {
|
|
6846
|
+
lines.push("");
|
|
6847
|
+
lines.push(chalk9__default.default.yellow(" \u26A0\uFE0F \u98CE\u9669\u63D0\u793A:"));
|
|
6848
|
+
for (const risk of spec.risks) {
|
|
6849
|
+
lines.push(chalk9__default.default.gray(` - ${risk}`));
|
|
6850
|
+
}
|
|
6851
|
+
}
|
|
6852
|
+
lines.push("");
|
|
6853
|
+
lines.push(chalk9__default.default.yellow.bold("\u23F3 \u7B49\u5F85\u89C4\u683C\u786E\u8BA4"));
|
|
6854
|
+
lines.push(chalk9__default.default.gray("\n\u8BF7\u68C0\u67E5\u751F\u6210\u7684\u89C4\u683C\u6587\u4EF6\uFF0C\u786E\u8BA4\u540E\u7EE7\u7EED:"));
|
|
6855
|
+
lines.push(chalk9__default.default.white("\n /opsx:confirm spec-review - \u786E\u8BA4\u89C4\u683C\uFF0C\u8FDB\u5165\u4E0B\u4E00\u9636\u6BB5"));
|
|
6856
|
+
lines.push(chalk9__default.default.white(" /opsx:rollback explore - \u89C4\u683C\u4E0D\u7B26\uFF0C\u91CD\u65B0\u62C6\u5206"));
|
|
6857
|
+
lines.push(chalk9__default.default.white(" /opsx:status - \u67E5\u770B\u5DE5\u4F5C\u6D41\u72B6\u6001"));
|
|
6858
|
+
return { output: lines.join("\n") };
|
|
6859
|
+
}
|
|
6860
|
+
async function generateSpec(requirement, context, analysis, changeId) {
|
|
6861
|
+
const spec = {
|
|
6862
|
+
changeId,
|
|
6863
|
+
requirement,
|
|
6864
|
+
summary: "",
|
|
6865
|
+
items: [],
|
|
6866
|
+
architectureNotes: [],
|
|
6867
|
+
risks: [],
|
|
6868
|
+
suggestions: []
|
|
6869
|
+
};
|
|
6870
|
+
spec.summary = generateSummary(requirement);
|
|
6871
|
+
if (analysis.recommendation === "complex") {
|
|
6872
|
+
spec.items = generateComplexTasks(requirement, context, analysis);
|
|
6873
|
+
spec.architectureNotes = generateArchitectureNotes(requirement, context);
|
|
6874
|
+
} else {
|
|
6875
|
+
spec.items = generateSimpleTasks(requirement);
|
|
6876
|
+
}
|
|
6877
|
+
spec.risks = generateRisks(requirement, context, analysis);
|
|
6878
|
+
spec.suggestions = generateSuggestions(requirement, context, analysis);
|
|
6879
|
+
return spec;
|
|
6880
|
+
}
|
|
6881
|
+
function generateSummary(requirement) {
|
|
6882
|
+
const firstSentence = requirement.split(/[。!?\n]/)[0];
|
|
6883
|
+
return firstSentence.length > 100 ? firstSentence.slice(0, 97) + "..." : firstSentence;
|
|
6884
|
+
}
|
|
6885
|
+
function generateComplexTasks(requirement, context, analysis) {
|
|
6886
|
+
const items = [];
|
|
6887
|
+
let itemId = 1;
|
|
6888
|
+
const featurePatterns = [
|
|
6889
|
+
{ pattern: /用户|登录|注册|认证|权限/, title: "\u7528\u6237\u8BA4\u8BC1\u6A21\u5757", priority: "high" },
|
|
6890
|
+
{ pattern: /数据|存储|缓存|数据库/, title: "\u6570\u636E\u5C42\u5B9E\u73B0", priority: "high" },
|
|
6891
|
+
{ pattern: /接口|API|请求|响应/, title: "API \u63A5\u53E3\u5F00\u53D1", priority: "high" },
|
|
6892
|
+
{ pattern: /界面|页面|组件|UI/, title: "\u754C\u9762\u5F00\u53D1", priority: "medium" },
|
|
6893
|
+
{ pattern: /测试|单测|覆盖/, title: "\u6D4B\u8BD5\u7528\u4F8B\u7F16\u5199", priority: "medium" },
|
|
6894
|
+
{ pattern: /文档|说明/, title: "\u6587\u6863\u7F16\u5199", priority: "low" },
|
|
6895
|
+
{ pattern: /配置|设置/, title: "\u914D\u7F6E\u7BA1\u7406", priority: "low" },
|
|
6896
|
+
{ pattern: /优化|性能/, title: "\u6027\u80FD\u4F18\u5316", priority: "medium" },
|
|
6897
|
+
{ pattern: /安全|加密/, title: "\u5B89\u5168\u5B9E\u73B0", priority: "high" },
|
|
6898
|
+
{ pattern: /日志|监控/, title: "\u65E5\u5FD7\u76D1\u63A7", priority: "low" }
|
|
6899
|
+
];
|
|
6900
|
+
for (const { pattern, title, priority } of featurePatterns) {
|
|
6901
|
+
if (pattern.test(requirement)) {
|
|
6902
|
+
items.push({
|
|
6903
|
+
id: `T${itemId.toString().padStart(3, "0")}`,
|
|
6904
|
+
title,
|
|
6905
|
+
description: `${title}\u76F8\u5173\u7684\u529F\u80FD\u5B9E\u73B0`,
|
|
6906
|
+
priority,
|
|
6907
|
+
dependencies: itemId > 1 ? [`T${(itemId - 1).toString().padStart(3, "0")}`] : [],
|
|
6908
|
+
estimatedComplexity: priority === "high" ? 3 : priority === "medium" ? 2 : 1
|
|
6909
|
+
});
|
|
6910
|
+
itemId++;
|
|
6911
|
+
}
|
|
6912
|
+
}
|
|
6913
|
+
if (items.length === 0) {
|
|
6914
|
+
items.push({
|
|
6915
|
+
id: "T001",
|
|
6916
|
+
title: "\u9700\u6C42\u5206\u6790\u4E0E\u8BBE\u8BA1",
|
|
6917
|
+
description: "\u5206\u6790\u9700\u6C42\u7EC6\u8282\uFF0C\u8BBE\u8BA1\u5B9E\u73B0\u65B9\u6848",
|
|
6918
|
+
priority: "high",
|
|
6919
|
+
dependencies: [],
|
|
6920
|
+
estimatedComplexity: 2
|
|
6780
6921
|
});
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
"",
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6922
|
+
items.push({
|
|
6923
|
+
id: "T002",
|
|
6924
|
+
title: "\u6838\u5FC3\u529F\u80FD\u5B9E\u73B0",
|
|
6925
|
+
description: requirement,
|
|
6926
|
+
priority: "high",
|
|
6927
|
+
dependencies: ["T001"],
|
|
6928
|
+
estimatedComplexity: analysis.score
|
|
6929
|
+
});
|
|
6930
|
+
items.push({
|
|
6931
|
+
id: "T003",
|
|
6932
|
+
title: "\u6D4B\u8BD5\u4E0E\u9A8C\u8BC1",
|
|
6933
|
+
description: "\u7F16\u5199\u6D4B\u8BD5\u7528\u4F8B\uFF0C\u9A8C\u8BC1\u529F\u80FD\u6B63\u786E\u6027",
|
|
6934
|
+
priority: "medium",
|
|
6935
|
+
dependencies: ["T002"],
|
|
6936
|
+
estimatedComplexity: 2
|
|
6937
|
+
});
|
|
6938
|
+
}
|
|
6939
|
+
return items;
|
|
6940
|
+
}
|
|
6941
|
+
function generateSimpleTasks(requirement, context) {
|
|
6942
|
+
return [
|
|
6943
|
+
{
|
|
6944
|
+
id: "T001",
|
|
6945
|
+
title: "\u5B9E\u73B0\u53D8\u66F4",
|
|
6946
|
+
description: requirement,
|
|
6947
|
+
priority: "high",
|
|
6948
|
+
dependencies: [],
|
|
6949
|
+
estimatedComplexity: 3
|
|
6950
|
+
},
|
|
6951
|
+
{
|
|
6952
|
+
id: "T002",
|
|
6953
|
+
title: "\u6D4B\u8BD5\u9A8C\u8BC1",
|
|
6954
|
+
description: "\u9A8C\u8BC1\u53D8\u66F4\u6B63\u786E\u6027",
|
|
6955
|
+
priority: "medium",
|
|
6956
|
+
dependencies: ["T001"],
|
|
6957
|
+
estimatedComplexity: 1
|
|
6806
6958
|
}
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6959
|
+
];
|
|
6960
|
+
}
|
|
6961
|
+
function generateArchitectureNotes(requirement, context) {
|
|
6962
|
+
const notes = [];
|
|
6963
|
+
if (context.framework) {
|
|
6964
|
+
notes.push(`\u9879\u76EE\u4F7F\u7528 ${context.framework} \u6846\u67B6\uFF0C\u9700\u9075\u5FAA\u5176\u6700\u4F73\u5B9E\u8DF5`);
|
|
6810
6965
|
}
|
|
6966
|
+
if (requirement.includes("\u6A21\u5757") || requirement.includes("\u7EC4\u4EF6")) {
|
|
6967
|
+
notes.push("\u5EFA\u8BAE\u91C7\u7528\u6A21\u5757\u5316\u8BBE\u8BA1\uFF0C\u4FDD\u6301\u7EC4\u4EF6\u804C\u8D23\u5355\u4E00");
|
|
6968
|
+
}
|
|
6969
|
+
if (requirement.includes("API") || requirement.includes("\u63A5\u53E3")) {
|
|
6970
|
+
notes.push("API \u8BBE\u8BA1\u9700\u8003\u8651\u7248\u672C\u63A7\u5236\u548C\u5411\u540E\u517C\u5BB9");
|
|
6971
|
+
}
|
|
6972
|
+
if (context.structure.srcStructure) {
|
|
6973
|
+
notes.push(`\u73B0\u6709\u6E90\u7801\u7ED3\u6784: ${context.structure.srcStructure}`);
|
|
6974
|
+
}
|
|
6975
|
+
return notes;
|
|
6976
|
+
}
|
|
6977
|
+
function generateRisks(requirement, context, analysis) {
|
|
6978
|
+
const risks = [];
|
|
6979
|
+
if (!context.framework) {
|
|
6980
|
+
risks.push("\u9879\u76EE\u6846\u67B6\u672A\u8BC6\u522B\uFF0C\u53EF\u80FD\u5F71\u54CD\u4EE3\u7801\u98CE\u683C\u4E00\u81F4\u6027");
|
|
6981
|
+
}
|
|
6982
|
+
if (analysis.score >= 7) {
|
|
6983
|
+
risks.push("\u9700\u6C42\u590D\u6742\u5EA6\u8F83\u9AD8\uFF0C\u5EFA\u8BAE\u5206\u9636\u6BB5\u5B9E\u73B0");
|
|
6984
|
+
}
|
|
6985
|
+
if (requirement.includes("\u8FC1\u79FB") || requirement.includes("\u91CD\u6784")) {
|
|
6986
|
+
risks.push("\u6D89\u53CA\u73B0\u6709\u4EE3\u7801\u4FEE\u6539\uFF0C\u9700\u6CE8\u610F\u56DE\u5F52\u6D4B\u8BD5");
|
|
6987
|
+
}
|
|
6988
|
+
if (requirement.includes("\u6743\u9650") || requirement.includes("\u5B89\u5168")) {
|
|
6989
|
+
risks.push("\u6D89\u53CA\u5B89\u5168\u654F\u611F\u529F\u80FD\uFF0C\u9700\u8981\u989D\u5916\u5BA1\u67E5");
|
|
6990
|
+
}
|
|
6991
|
+
return risks;
|
|
6992
|
+
}
|
|
6993
|
+
function generateSuggestions(requirement, context, analysis) {
|
|
6994
|
+
const suggestions = [];
|
|
6995
|
+
if (context.norms.devStandards) {
|
|
6996
|
+
suggestions.push("\u9879\u76EE\u5DF2\u6709\u5F00\u53D1\u89C4\u8303\uFF0C\u8BF7\u9075\u5FAA\u73B0\u6709\u89C4\u8303");
|
|
6997
|
+
}
|
|
6998
|
+
if (analysis.recommendation === "complex") {
|
|
6999
|
+
suggestions.push("\u590D\u6742\u9700\u6C42\u5EFA\u8BAE\u5148\u8FDB\u884C\u6280\u672F\u8BC4\u5BA1");
|
|
7000
|
+
suggestions.push("\u5EFA\u8BAE\u8C03\u7528 $architect \u83B7\u53D6\u67B6\u6784\u5EFA\u8BAE");
|
|
7001
|
+
}
|
|
7002
|
+
if (context.techStack.length > 0) {
|
|
7003
|
+
suggestions.push(`\u6280\u672F\u6808: ${context.techStack.join(", ")}`);
|
|
7004
|
+
}
|
|
7005
|
+
return suggestions;
|
|
7006
|
+
}
|
|
7007
|
+
async function saveSpecFile(cwd, spec) {
|
|
7008
|
+
const changesDir = path4__namespace.join(cwd, "openspec", "changes");
|
|
7009
|
+
await fs4__namespace.mkdir(changesDir, { recursive: true });
|
|
7010
|
+
const specPath = path4__namespace.join(changesDir, `${spec.changeId}-spec.md`);
|
|
7011
|
+
const content = formatSpecFile(spec);
|
|
7012
|
+
await fs4__namespace.writeFile(specPath, content, "utf-8");
|
|
7013
|
+
return specPath;
|
|
7014
|
+
}
|
|
7015
|
+
function formatSpecFile(spec) {
|
|
7016
|
+
const lines = [];
|
|
7017
|
+
lines.push(`# Spec: ${spec.summary}`);
|
|
7018
|
+
lines.push("");
|
|
7019
|
+
lines.push(`> \u53D8\u66F4ID: ${spec.changeId}`);
|
|
7020
|
+
lines.push(`> \u751F\u6210\u65F6\u95F4: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
7021
|
+
lines.push("");
|
|
7022
|
+
lines.push("---");
|
|
7023
|
+
lines.push("");
|
|
7024
|
+
lines.push("## \u9700\u6C42\u6982\u8FF0");
|
|
7025
|
+
lines.push("");
|
|
7026
|
+
lines.push(spec.requirement);
|
|
7027
|
+
lines.push("");
|
|
7028
|
+
lines.push("## \u4EFB\u52A1\u62C6\u5206");
|
|
7029
|
+
lines.push("");
|
|
7030
|
+
for (const item of spec.items) {
|
|
7031
|
+
const priorityLabel = item.priority === "high" ? "\u{1F534} \u9AD8" : item.priority === "medium" ? "\u{1F7E1} \u4E2D" : "\u{1F7E2} \u4F4E";
|
|
7032
|
+
lines.push(`### ${item.id}: ${item.title}`);
|
|
7033
|
+
lines.push("");
|
|
7034
|
+
lines.push(`- **\u4F18\u5148\u7EA7**: ${priorityLabel}`);
|
|
7035
|
+
lines.push(`- **\u63CF\u8FF0**: ${item.description}`);
|
|
7036
|
+
lines.push(`- **\u9884\u4F30\u590D\u6742\u5EA6**: ${item.estimatedComplexity}/5`);
|
|
7037
|
+
if (item.dependencies.length > 0) {
|
|
7038
|
+
lines.push(`- **\u4F9D\u8D56**: ${item.dependencies.join(", ")}`);
|
|
7039
|
+
}
|
|
7040
|
+
lines.push("");
|
|
7041
|
+
}
|
|
7042
|
+
if (spec.architectureNotes.length > 0) {
|
|
7043
|
+
lines.push("## \u67B6\u6784\u8BF4\u660E");
|
|
7044
|
+
lines.push("");
|
|
7045
|
+
for (const note of spec.architectureNotes) {
|
|
7046
|
+
lines.push(`- ${note}`);
|
|
7047
|
+
}
|
|
7048
|
+
lines.push("");
|
|
7049
|
+
}
|
|
7050
|
+
if (spec.risks.length > 0) {
|
|
7051
|
+
lines.push("## \u26A0\uFE0F \u98CE\u9669\u8BC4\u4F30");
|
|
7052
|
+
lines.push("");
|
|
7053
|
+
for (const risk of spec.risks) {
|
|
7054
|
+
lines.push(`- ${risk}`);
|
|
7055
|
+
}
|
|
7056
|
+
lines.push("");
|
|
7057
|
+
}
|
|
7058
|
+
if (spec.suggestions.length > 0) {
|
|
7059
|
+
lines.push("## \u{1F4A1} \u5EFA\u8BAE");
|
|
7060
|
+
lines.push("");
|
|
7061
|
+
for (const suggestion of spec.suggestions) {
|
|
7062
|
+
lines.push(`- ${suggestion}`);
|
|
7063
|
+
}
|
|
7064
|
+
lines.push("");
|
|
7065
|
+
}
|
|
7066
|
+
lines.push("---");
|
|
7067
|
+
lines.push("");
|
|
7068
|
+
lines.push("## \u786E\u8BA4\u72B6\u6001");
|
|
7069
|
+
lines.push("");
|
|
7070
|
+
lines.push("- [ ] \u89C4\u683C\u5DF2\u5BA1\u9605");
|
|
7071
|
+
lines.push("- [ ] \u4EFB\u52A1\u62C6\u5206\u5DF2\u786E\u8BA4");
|
|
7072
|
+
lines.push("");
|
|
7073
|
+
lines.push("**\u786E\u8BA4\u540E\u6267\u884C**: `/opsx:confirm spec-review`");
|
|
7074
|
+
return lines.join("\n");
|
|
6811
7075
|
}
|
|
6812
7076
|
function parseArgs(args) {
|
|
6813
7077
|
let forceComplexity;
|
|
@@ -6832,42 +7096,52 @@ async function readProjectContext(cwd) {
|
|
|
6832
7096
|
type: "unknown",
|
|
6833
7097
|
framework: null,
|
|
6834
7098
|
techStack: [],
|
|
6835
|
-
description: ""
|
|
7099
|
+
description: "",
|
|
7100
|
+
structure: {
|
|
7101
|
+
directories: [],
|
|
7102
|
+
keyFiles: [],
|
|
7103
|
+
srcStructure: ""
|
|
7104
|
+
},
|
|
7105
|
+
norms: {
|
|
7106
|
+
devStandards: "",
|
|
7107
|
+
patterns: "",
|
|
7108
|
+
weights: ""
|
|
7109
|
+
}
|
|
6836
7110
|
};
|
|
7111
|
+
const [agentsContext, configContext, normsContext, structureContext] = await Promise.all([
|
|
7112
|
+
readAgentsMd(cwd),
|
|
7113
|
+
readConfigYaml(cwd),
|
|
7114
|
+
readNorms(cwd),
|
|
7115
|
+
analyzeStructure(cwd)
|
|
7116
|
+
]);
|
|
7117
|
+
return {
|
|
7118
|
+
...defaultContext,
|
|
7119
|
+
...agentsContext,
|
|
7120
|
+
...configContext,
|
|
7121
|
+
norms: normsContext,
|
|
7122
|
+
structure: structureContext
|
|
7123
|
+
};
|
|
7124
|
+
}
|
|
7125
|
+
async function readAgentsMd(cwd) {
|
|
6837
7126
|
const agentsPath = path4__namespace.join(cwd, "AGENTS.md");
|
|
6838
7127
|
try {
|
|
6839
7128
|
const stats = await fs4__namespace.stat(agentsPath);
|
|
6840
7129
|
if (stats.size > MAX_FILE_SIZE2) {
|
|
6841
7130
|
console.warn(`\u8B66\u544A: AGENTS.md \u6587\u4EF6\u8FC7\u5927 (${stats.size} bytes)\uFF0C\u8DF3\u8FC7\u8BFB\u53D6`);
|
|
6842
|
-
return
|
|
7131
|
+
return {};
|
|
6843
7132
|
}
|
|
6844
7133
|
const content = await fs4__namespace.readFile(agentsPath, "utf-8");
|
|
6845
|
-
return parseAgentsMd(content
|
|
7134
|
+
return parseAgentsMd(content);
|
|
6846
7135
|
} catch (e) {
|
|
6847
7136
|
const err = e;
|
|
6848
7137
|
if (err.code !== "ENOENT") {
|
|
6849
7138
|
console.warn(`\u8B66\u544A: \u65E0\u6CD5\u8BFB\u53D6 AGENTS.md - ${err.message}`);
|
|
6850
7139
|
}
|
|
7140
|
+
return {};
|
|
6851
7141
|
}
|
|
6852
|
-
const configPath = path4__namespace.join(cwd, "openspec", "config.yaml");
|
|
6853
|
-
try {
|
|
6854
|
-
const stats = await fs4__namespace.stat(configPath);
|
|
6855
|
-
if (stats.size > MAX_FILE_SIZE2) {
|
|
6856
|
-
console.warn(`\u8B66\u544A: config.yaml \u6587\u4EF6\u8FC7\u5927\uFF0C\u8DF3\u8FC7\u8BFB\u53D6`);
|
|
6857
|
-
return defaultContext;
|
|
6858
|
-
}
|
|
6859
|
-
const content = await fs4__namespace.readFile(configPath, "utf-8");
|
|
6860
|
-
return parseConfigYaml(content, defaultContext);
|
|
6861
|
-
} catch (e) {
|
|
6862
|
-
const err = e;
|
|
6863
|
-
if (err.code !== "ENOENT") {
|
|
6864
|
-
console.warn(`\u8B66\u544A: \u65E0\u6CD5\u8BFB\u53D6 config.yaml - ${err.message}`);
|
|
6865
|
-
}
|
|
6866
|
-
}
|
|
6867
|
-
return defaultContext;
|
|
6868
7142
|
}
|
|
6869
|
-
function parseAgentsMd(content
|
|
6870
|
-
const context = {
|
|
7143
|
+
function parseAgentsMd(content) {
|
|
7144
|
+
const context = {};
|
|
6871
7145
|
const nameMatch = content.match(/\|\s*项目名称\s*\|\s*([^\s|]+)/);
|
|
6872
7146
|
if (nameMatch) {
|
|
6873
7147
|
context.name = nameMatch[1];
|
|
@@ -6884,10 +7158,32 @@ function parseAgentsMd(content, defaults) {
|
|
|
6884
7158
|
if (descMatch) {
|
|
6885
7159
|
context.description = descMatch[1].trim();
|
|
6886
7160
|
}
|
|
7161
|
+
const techStackMatch = content.match(/技术栈[::]\s*([^\n]+)/);
|
|
7162
|
+
if (techStackMatch) {
|
|
7163
|
+
context.techStack = techStackMatch[1].split(/[,,、]/).map((s) => s.trim()).filter(Boolean);
|
|
7164
|
+
}
|
|
6887
7165
|
return context;
|
|
6888
7166
|
}
|
|
6889
|
-
function
|
|
6890
|
-
const
|
|
7167
|
+
async function readConfigYaml(cwd) {
|
|
7168
|
+
const configPath = path4__namespace.join(cwd, "openspec", "config.yaml");
|
|
7169
|
+
try {
|
|
7170
|
+
const stats = await fs4__namespace.stat(configPath);
|
|
7171
|
+
if (stats.size > MAX_FILE_SIZE2) {
|
|
7172
|
+
console.warn("\u8B66\u544A: config.yaml \u6587\u4EF6\u8FC7\u5927\uFF0C\u8DF3\u8FC7\u8BFB\u53D6");
|
|
7173
|
+
return {};
|
|
7174
|
+
}
|
|
7175
|
+
const content = await fs4__namespace.readFile(configPath, "utf-8");
|
|
7176
|
+
return parseConfigYaml(content);
|
|
7177
|
+
} catch (e) {
|
|
7178
|
+
const err = e;
|
|
7179
|
+
if (err.code !== "ENOENT") {
|
|
7180
|
+
console.warn(`\u8B66\u544A: \u65E0\u6CD5\u8BFB\u53D6 config.yaml - ${err.message}`);
|
|
7181
|
+
}
|
|
7182
|
+
return {};
|
|
7183
|
+
}
|
|
7184
|
+
}
|
|
7185
|
+
function parseConfigYaml(content) {
|
|
7186
|
+
const context = {};
|
|
6891
7187
|
const nameMatch = content.match(/name:\s*(.+)/);
|
|
6892
7188
|
if (nameMatch) {
|
|
6893
7189
|
context.name = nameMatch[1].trim();
|
|
@@ -6902,6 +7198,67 @@ function parseConfigYaml(content, defaults) {
|
|
|
6902
7198
|
}
|
|
6903
7199
|
return context;
|
|
6904
7200
|
}
|
|
7201
|
+
async function readNorms(cwd) {
|
|
7202
|
+
const normsDir = path4__namespace.join(cwd, ".sf-cli", "norms");
|
|
7203
|
+
const norms = {
|
|
7204
|
+
devStandards: "",
|
|
7205
|
+
patterns: "",
|
|
7206
|
+
weights: ""
|
|
7207
|
+
};
|
|
7208
|
+
try {
|
|
7209
|
+
const devStandardsPath = path4__namespace.join(normsDir, "devstanded.md");
|
|
7210
|
+
norms.devStandards = await fs4__namespace.readFile(devStandardsPath, "utf-8").catch(() => "");
|
|
7211
|
+
} catch {
|
|
7212
|
+
}
|
|
7213
|
+
try {
|
|
7214
|
+
const patternsPath = path4__namespace.join(normsDir, "patterns.json");
|
|
7215
|
+
norms.patterns = await fs4__namespace.readFile(patternsPath, "utf-8").catch(() => "");
|
|
7216
|
+
} catch {
|
|
7217
|
+
}
|
|
7218
|
+
try {
|
|
7219
|
+
const weightsPath = path4__namespace.join(normsDir, "weights.json");
|
|
7220
|
+
norms.weights = await fs4__namespace.readFile(weightsPath, "utf-8").catch(() => "");
|
|
7221
|
+
} catch {
|
|
7222
|
+
}
|
|
7223
|
+
return norms;
|
|
7224
|
+
}
|
|
7225
|
+
async function analyzeStructure(cwd) {
|
|
7226
|
+
const structure = {
|
|
7227
|
+
directories: [],
|
|
7228
|
+
keyFiles: [],
|
|
7229
|
+
srcStructure: ""
|
|
7230
|
+
};
|
|
7231
|
+
try {
|
|
7232
|
+
const entries = await fs4__namespace.readdir(cwd, { withFileTypes: true });
|
|
7233
|
+
for (const entry of entries) {
|
|
7234
|
+
if (entry.isDirectory() && !["node_modules", "dist", ".git", "build"].includes(entry.name)) {
|
|
7235
|
+
structure.directories.push(entry.name);
|
|
7236
|
+
}
|
|
7237
|
+
}
|
|
7238
|
+
const keyFiles = [
|
|
7239
|
+
"package.json",
|
|
7240
|
+
"tsconfig.json",
|
|
7241
|
+
"AGENTS.md",
|
|
7242
|
+
"README.md"
|
|
7243
|
+
];
|
|
7244
|
+
for (const file of keyFiles) {
|
|
7245
|
+
const filePath = path4__namespace.join(cwd, file);
|
|
7246
|
+
try {
|
|
7247
|
+
await fs4__namespace.access(filePath);
|
|
7248
|
+
structure.keyFiles.push(file);
|
|
7249
|
+
} catch {
|
|
7250
|
+
}
|
|
7251
|
+
}
|
|
7252
|
+
const srcDir = path4__namespace.join(cwd, "src");
|
|
7253
|
+
try {
|
|
7254
|
+
const srcEntries = await fs4__namespace.readdir(srcDir, { withFileTypes: true });
|
|
7255
|
+
structure.srcStructure = srcEntries.filter((e) => e.isDirectory()).map((e) => e.name).join("/");
|
|
7256
|
+
} catch {
|
|
7257
|
+
}
|
|
7258
|
+
} catch (e) {
|
|
7259
|
+
}
|
|
7260
|
+
return { structure };
|
|
7261
|
+
}
|
|
6905
7262
|
function analyzeComplexity(requirement, context) {
|
|
6906
7263
|
let score = 3;
|
|
6907
7264
|
const factors = [];
|
|
@@ -7065,7 +7422,7 @@ async function handleOpsx(command, args, ctx) {
|
|
|
7065
7422
|
case "rollback":
|
|
7066
7423
|
return handleRollback(workflow, args);
|
|
7067
7424
|
case "confirm":
|
|
7068
|
-
return handleConfirm(workflow, args);
|
|
7425
|
+
return handleConfirm(workflow, args, ctx);
|
|
7069
7426
|
case "next":
|
|
7070
7427
|
return handleNext(workflow);
|
|
7071
7428
|
case "auto":
|
|
@@ -7433,6 +7790,16 @@ async function handleConfirm(workflow, args, ctx) {
|
|
|
7433
7790
|
const type = args[0];
|
|
7434
7791
|
if (!type) {
|
|
7435
7792
|
const pendingPoint = workflow.getCurrentConfirmationPoint();
|
|
7793
|
+
const specPath = await checkPendingSpec(ctx.options.workingDirectory, state.id);
|
|
7794
|
+
if (specPath) {
|
|
7795
|
+
return {
|
|
7796
|
+
output: chalk9__default.default.cyan("\u{1F4CB} \u89C4\u683C\u6587\u4EF6\u5F85\u786E\u8BA4") + chalk9__default.default.gray(`
|
|
7797
|
+
|
|
7798
|
+
\u89C4\u683C\u6587\u4EF6: ${specPath}`) + chalk9__default.default.gray(`
|
|
7799
|
+
|
|
7800
|
+
\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")
|
|
7801
|
+
};
|
|
7802
|
+
}
|
|
7436
7803
|
if (pendingPoint) {
|
|
7437
7804
|
return {
|
|
7438
7805
|
output: chalk9__default.default.cyan("\u5F85\u786E\u8BA4\u7684\u68C0\u67E5\u70B9:") + chalk9__default.default.white(`
|
|
@@ -7454,12 +7821,54 @@ ${generateConfirmationPrompt(pendingPoint)}`) + chalk9__default.default.gray(`
|
|
|
7454
7821
|
}
|
|
7455
7822
|
const comment = args.slice(1).join(" ");
|
|
7456
7823
|
workflow.confirm(type, comment);
|
|
7457
|
-
|
|
7458
|
-
|
|
7824
|
+
const lines = [];
|
|
7825
|
+
lines.push(chalk9__default.default.green("\u2713 \u5DF2\u786E\u8BA4"));
|
|
7826
|
+
lines.push(chalk9__default.default.white(`
|
|
7827
|
+
${point.name}`));
|
|
7828
|
+
if (comment) {
|
|
7829
|
+
lines.push(chalk9__default.default.gray(`
|
|
7830
|
+
\u5907\u6CE8: ${comment}`));
|
|
7831
|
+
}
|
|
7832
|
+
if (type === "spec-review") {
|
|
7833
|
+
const allowed = workflow.getAllowedTransitions();
|
|
7834
|
+
if (allowed.length > 0) {
|
|
7835
|
+
const nextStep = allowed[0];
|
|
7836
|
+
try {
|
|
7837
|
+
const transition = await workflow.transition(nextStep);
|
|
7838
|
+
lines.push("");
|
|
7839
|
+
lines.push(chalk9__default.default.cyan(`\u2713 \u5DF2\u81EA\u52A8\u8FDB\u5165 ${nextStep} \u9636\u6BB5`));
|
|
7840
|
+
lines.push(chalk9__default.default.gray(`\u8F6C\u6362: ${transition.from} \u2192 ${transition.to}`));
|
|
7841
|
+
if (nextStep === "new") {
|
|
7842
|
+
lines.push(chalk9__default.default.yellow("\n\u4E0B\u4E00\u6B65: \u8BBE\u8BA1\u65B9\u6848"));
|
|
7843
|
+
lines.push(chalk9__default.default.gray(" \u53EF\u8C03\u7528 $architect \u6216 $frontend-dev \u8FDB\u884C\u8BBE\u8BA1"));
|
|
7844
|
+
} else if (nextStep === "apply") {
|
|
7845
|
+
lines.push(chalk9__default.default.yellow("\n\u4E0B\u4E00\u6B65: \u6267\u884C\u53D8\u66F4"));
|
|
7846
|
+
lines.push(chalk9__default.default.gray(" \u53EF\u8C03\u7528 $frontend-dev \u6267\u884C\u4EE3\u7801\u4FEE\u6539"));
|
|
7847
|
+
}
|
|
7848
|
+
return { output: lines.join("\n") };
|
|
7849
|
+
} catch (e) {
|
|
7850
|
+
if (e instanceof ConfirmationRequiredError) {
|
|
7851
|
+
lines.push(chalk9__default.default.yellow("\n\u26A0 \u8FD8\u9700\u8981\u786E\u8BA4:") + chalk9__default.default.white(`
|
|
7852
|
+
${generateConfirmationPrompt(e.point)}`) + chalk9__default.default.cyan(`
|
|
7459
7853
|
|
|
7460
|
-
${point.
|
|
7461
|
-
|
|
7462
|
-
|
|
7854
|
+
\u4F7F\u7528 /opsx:confirm ${e.point.type}`));
|
|
7855
|
+
return { output: lines.join("\n") };
|
|
7856
|
+
}
|
|
7857
|
+
throw e;
|
|
7858
|
+
}
|
|
7859
|
+
}
|
|
7860
|
+
}
|
|
7861
|
+
lines.push(chalk9__default.default.yellow("\n\u4F7F\u7528 /opsx:next \u7EE7\u7EED\u4E0B\u4E00\u9636\u6BB5"));
|
|
7862
|
+
return { output: lines.join("\n") };
|
|
7863
|
+
}
|
|
7864
|
+
async function checkPendingSpec(workingDirectory, changeId) {
|
|
7865
|
+
const specPath = path4__namespace.join(workingDirectory, "openspec", "changes", `${changeId}-spec.md`);
|
|
7866
|
+
try {
|
|
7867
|
+
await fs10__namespace.promises.access(specPath);
|
|
7868
|
+
return specPath;
|
|
7869
|
+
} catch {
|
|
7870
|
+
return null;
|
|
7871
|
+
}
|
|
7463
7872
|
}
|
|
7464
7873
|
async function handleNext(workflow, args, ctx) {
|
|
7465
7874
|
const state = workflow.getState();
|