@nick848/fet 1.1.2 → 1.1.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/README.md +1 -1
- package/README_en.md +1 -1
- package/dist/cli/index.js +249 -21
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -104,7 +104,7 @@ fet init --lang en
|
|
|
104
104
|
| `fet fill-context` | `fet fill-context [--yes]` | 刷新 IDE 交接命令,引导 AI 替换 `AGENTS.md` 占位符。 |
|
|
105
105
|
| `fet doctor` | `fet doctor [--fix-lock]` | 诊断 OpenSpec、FET 状态、上下文文件、工具集成和锁文件。 |
|
|
106
106
|
| `fet explore` | `fet explore [...args] [--change <id>]` | 通过 FET 执行 OpenSpec 原生 explore,保留交互式需求澄清。 |
|
|
107
|
-
| `fet propose` | `fet propose <change-id>` |
|
|
107
|
+
| `fet propose` | `fet propose <change-id-or-description>` | 创建 OpenSpec change,并生成第一个 ready 规划产物;后续产物用 `continue` 逐步推进。 |
|
|
108
108
|
| `fet new` | `fet new <change-id>` | 创建新的 OpenSpec change。 |
|
|
109
109
|
| `fet continue` | `fet continue [...args] [--change <id>]` | 通过 FET 执行 OpenSpec 原生 continue。 |
|
|
110
110
|
| `fet ff` | `fet ff [...args] [--change <id>]` | 通过 FET 执行 OpenSpec 原生 ff。 |
|
package/README_en.md
CHANGED
|
@@ -106,7 +106,7 @@ fet init --lang en
|
|
|
106
106
|
| `fet fill-context` | `fet fill-context [--yes]` | Refresh IDE handoff commands that ask AI to replace `AGENTS.md` placeholders. |
|
|
107
107
|
| `fet doctor` | `fet doctor [--fix-lock]` | Diagnose OpenSpec, FET state, context files, tool integration, and lock files. |
|
|
108
108
|
| `fet explore` | `fet explore [...args] [--change <id>]` | Run native OpenSpec explore through FET so clarification prompts remain interactive. |
|
|
109
|
-
| `fet propose` | `fet propose <change-id>` | Create
|
|
109
|
+
| `fet propose` | `fet propose <change-id-or-description>` | Create an OpenSpec change and the first ready planning artifact; use `continue` for each subsequent artifact after review. |
|
|
110
110
|
| `fet new` | `fet new <change-id>` | Create a new OpenSpec change. |
|
|
111
111
|
| `fet continue` | `fet continue [...args] [--change <id>]` | Run native OpenSpec continue through FET. |
|
|
112
112
|
| `fet ff` | `fet ff [...args] [--change <id>]` | Run native OpenSpec ff through FET. |
|
package/dist/cli/index.js
CHANGED
|
@@ -2008,6 +2008,26 @@ async function proxyCommand(ctx, command, args) {
|
|
|
2008
2008
|
await artifactWorkflowCommand(ctx, command, args);
|
|
2009
2009
|
return;
|
|
2010
2010
|
}
|
|
2011
|
+
if (command === "apply") {
|
|
2012
|
+
await applyWorkflowCommand(ctx, args);
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
if (command === "explore") {
|
|
2016
|
+
await exploreWorkflowCommand(ctx, args);
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
if (command === "sync") {
|
|
2020
|
+
await syncWorkflowCommand(ctx, args);
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
2023
|
+
if (command === "bulk-archive") {
|
|
2024
|
+
await bulkArchiveWorkflowCommand(ctx, args);
|
|
2025
|
+
return;
|
|
2026
|
+
}
|
|
2027
|
+
if (command === "onboard") {
|
|
2028
|
+
await onboardWorkflowCommand(ctx);
|
|
2029
|
+
return;
|
|
2030
|
+
}
|
|
2011
2031
|
const openSpecArgs = stripFetOptions(args);
|
|
2012
2032
|
const runState = {};
|
|
2013
2033
|
await withProjectLock(ctx.projectRoot, { command, cwd: ctx.cwd, fetVersion: ctx.fetVersion }, async () => {
|
|
@@ -2082,6 +2102,161 @@ async function proxyCommand(ctx, command, args) {
|
|
|
2082
2102
|
data: graphContext ? { graphContext } : void 0
|
|
2083
2103
|
});
|
|
2084
2104
|
}
|
|
2105
|
+
async function applyWorkflowCommand(ctx, args) {
|
|
2106
|
+
const changeId = await requireChangeId(ctx);
|
|
2107
|
+
const runState = {};
|
|
2108
|
+
await withProjectLock(ctx.projectRoot, { command: "apply", cwd: ctx.cwd, fetVersion: ctx.fetVersion }, async () => {
|
|
2109
|
+
await assertOpenSpecCommandSupported(ctx, "status", "apply");
|
|
2110
|
+
await assertOpenSpecCommandSupported(ctx, "instructions", "apply");
|
|
2111
|
+
runState.graphContext = await buildWorkflowGraphContext(ctx, {
|
|
2112
|
+
command: "apply",
|
|
2113
|
+
args: ["tasks", "--change", changeId],
|
|
2114
|
+
changeId
|
|
2115
|
+
});
|
|
2116
|
+
const status = await readOpenSpecStatus(ctx, changeId);
|
|
2117
|
+
const tasks = status.artifacts?.find((artifact) => artifact.id === "tasks");
|
|
2118
|
+
const warnings = tasks && tasks.status !== "complete" && tasks.status !== "ready" ? [`OpenSpec reports tasks artifact as "${tasks.status}". Finish planning artifacts before implementation if tasks.md is missing.`] : void 0;
|
|
2119
|
+
const instructions = await runInstructions(ctx, changeId, "tasks");
|
|
2120
|
+
await syncWorkflowState(ctx, "apply", changeId, {
|
|
2121
|
+
openSpecCommand: "instructions",
|
|
2122
|
+
openSpecArgs: ["tasks", "--change", changeId],
|
|
2123
|
+
exitCode: instructions.exitCode,
|
|
2124
|
+
phaseStatus: "in_progress"
|
|
2125
|
+
});
|
|
2126
|
+
ctx.output.result({
|
|
2127
|
+
ok: true,
|
|
2128
|
+
command: "apply",
|
|
2129
|
+
summary: `fet apply prepared implementation instructions for change "${changeId}".`,
|
|
2130
|
+
warnings: [...runState.graphContext?.warnings ?? [], ...warnings ?? []],
|
|
2131
|
+
nextSteps: [
|
|
2132
|
+
`Read openspec/changes/${changeId}/tasks.md and the instructions output.`,
|
|
2133
|
+
"Implement pending tasks and update task checkboxes only after the work is done.",
|
|
2134
|
+
`Run fet verify --change ${changeId}`
|
|
2135
|
+
],
|
|
2136
|
+
data: {
|
|
2137
|
+
changeId,
|
|
2138
|
+
instructions: instructions.data,
|
|
2139
|
+
status,
|
|
2140
|
+
graphContext: runState.graphContext
|
|
2141
|
+
}
|
|
2142
|
+
});
|
|
2143
|
+
});
|
|
2144
|
+
}
|
|
2145
|
+
async function exploreWorkflowCommand(ctx, args) {
|
|
2146
|
+
const openSpecArgs = stripFetOptions(args);
|
|
2147
|
+
const changeId = ctx.changeId ?? (openSpecArgs[0] && isKebabId(openSpecArgs[0]) ? openSpecArgs[0] : null);
|
|
2148
|
+
const graphContext = await buildWorkflowGraphContext(ctx, {
|
|
2149
|
+
command: "explore",
|
|
2150
|
+
args: openSpecArgs,
|
|
2151
|
+
changeId
|
|
2152
|
+
});
|
|
2153
|
+
ctx.output.result({
|
|
2154
|
+
ok: true,
|
|
2155
|
+
command: "explore",
|
|
2156
|
+
summary: "fet explore is an IDE-guided workflow for shaping OpenSpec changes.",
|
|
2157
|
+
warnings: graphContext.warnings,
|
|
2158
|
+
nextSteps: [
|
|
2159
|
+
"Discuss the requirement, constraints, and acceptance criteria with the user.",
|
|
2160
|
+
changeId ? `Run fet continue --change ${changeId} when ready to create the next artifact.` : "Run fet propose <change-id-or-description> when ready to create a change."
|
|
2161
|
+
],
|
|
2162
|
+
data: { changeId, args: openSpecArgs, graphContext }
|
|
2163
|
+
});
|
|
2164
|
+
}
|
|
2165
|
+
async function syncWorkflowCommand(ctx, args) {
|
|
2166
|
+
const changeId = await requireChangeId(ctx);
|
|
2167
|
+
const openSpecArgs = stripFetOptions(args);
|
|
2168
|
+
await withProjectLock(ctx.projectRoot, { command: "sync", cwd: ctx.cwd, fetVersion: ctx.fetVersion }, async () => {
|
|
2169
|
+
await assertVerifiedChange(ctx, changeId);
|
|
2170
|
+
await assertOpenSpecCommandSupported(ctx, "validate", "sync");
|
|
2171
|
+
const validateArgs = [changeId, "--type", "change", ...openSpecArgs.filter((arg) => arg !== changeId)];
|
|
2172
|
+
const result = await ctx.openSpec.run("validate", validateArgs, { cwd: ctx.projectRoot, stdio: ctx.json ? "pipe" : "inherit" });
|
|
2173
|
+
if (result.exitCode !== 0) {
|
|
2174
|
+
throw new FetError({
|
|
2175
|
+
code: "OPENSPEC_COMMAND_FAILED" /* OpenSpecCommandFailed */,
|
|
2176
|
+
message: "OpenSpec validate failed during fet sync.",
|
|
2177
|
+
details: result,
|
|
2178
|
+
recoverable: true
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2181
|
+
await syncWorkflowState(ctx, "sync", changeId, {
|
|
2182
|
+
openSpecCommand: "validate",
|
|
2183
|
+
openSpecArgs: validateArgs,
|
|
2184
|
+
exitCode: result.exitCode,
|
|
2185
|
+
phaseStatus: "done"
|
|
2186
|
+
});
|
|
2187
|
+
ctx.output.result({
|
|
2188
|
+
ok: true,
|
|
2189
|
+
command: "sync",
|
|
2190
|
+
summary: `fet sync validated change "${changeId}". OpenSpec 1.3.x applies spec updates during archive.`,
|
|
2191
|
+
nextSteps: [`Run fet archive --change ${changeId} when you are ready to archive and update main specs.`],
|
|
2192
|
+
data: ctx.json ? { changeId, validate: result } : { changeId }
|
|
2193
|
+
});
|
|
2194
|
+
});
|
|
2195
|
+
}
|
|
2196
|
+
async function bulkArchiveWorkflowCommand(ctx, args) {
|
|
2197
|
+
const openSpecArgs = stripFetOptions(args);
|
|
2198
|
+
const targets = [.../* @__PURE__ */ new Set([...ctx.changeId ? [ctx.changeId] : [], ...openSpecArgs.filter((arg) => !arg.startsWith("-"))])];
|
|
2199
|
+
if (!targets.length) {
|
|
2200
|
+
throw new FetError({
|
|
2201
|
+
code: "INVALID_ARGUMENTS" /* InvalidArguments */,
|
|
2202
|
+
message: "fet bulk-archive requires explicit change ids with the current OpenSpec CLI.",
|
|
2203
|
+
suggestedCommand: "fet bulk-archive --change <change-id>"
|
|
2204
|
+
});
|
|
2205
|
+
}
|
|
2206
|
+
await withProjectLock(ctx.projectRoot, { command: "bulk-archive", cwd: ctx.cwd, fetVersion: ctx.fetVersion }, async () => {
|
|
2207
|
+
await assertOpenSpecCommandSupported(ctx, "archive", "bulk-archive");
|
|
2208
|
+
const archived = [];
|
|
2209
|
+
for (const changeId of targets) {
|
|
2210
|
+
await assertVerifiedChange(ctx, changeId);
|
|
2211
|
+
const changelogEntry = await createChangelogEntry(ctx.projectRoot, changeId);
|
|
2212
|
+
const result = await ctx.openSpec.run("archive", [changeId], { cwd: ctx.projectRoot, stdio: ctx.json ? "pipe" : "inherit" });
|
|
2213
|
+
if (result.exitCode !== 0) {
|
|
2214
|
+
throw new FetError({
|
|
2215
|
+
code: "OPENSPEC_COMMAND_FAILED" /* OpenSpecCommandFailed */,
|
|
2216
|
+
message: `OpenSpec archive failed for "${changeId}".`,
|
|
2217
|
+
details: result,
|
|
2218
|
+
recoverable: true
|
|
2219
|
+
});
|
|
2220
|
+
}
|
|
2221
|
+
await appendChangelog(ctx.projectRoot, changelogEntry);
|
|
2222
|
+
archived.push(changeId);
|
|
2223
|
+
}
|
|
2224
|
+
const inspection = await ctx.openSpec.inspectProject(ctx.projectRoot);
|
|
2225
|
+
const state = await ctx.stateStore.getOrCreateGlobal();
|
|
2226
|
+
state.openChangeIds = inspection.changes;
|
|
2227
|
+
if (state.activeChangeId && !inspection.changes.includes(state.activeChangeId)) {
|
|
2228
|
+
state.activeChangeId = null;
|
|
2229
|
+
}
|
|
2230
|
+
state.verifyAuthorization = null;
|
|
2231
|
+
await ctx.stateStore.writeGlobal(state);
|
|
2232
|
+
ctx.output.result({
|
|
2233
|
+
ok: true,
|
|
2234
|
+
command: "bulk-archive",
|
|
2235
|
+
summary: `fet bulk-archive archived ${archived.length} change(s) via OpenSpec archive.`,
|
|
2236
|
+
nextSteps: inspection.changes.length ? [`Remaining open changes: ${inspection.changes.join(", ")}`] : void 0,
|
|
2237
|
+
data: { archived, openChangeIds: inspection.changes }
|
|
2238
|
+
});
|
|
2239
|
+
});
|
|
2240
|
+
}
|
|
2241
|
+
async function onboardWorkflowCommand(ctx) {
|
|
2242
|
+
const inspection = await ctx.openSpec.inspectProject(ctx.projectRoot);
|
|
2243
|
+
const state = await ctx.stateStore.getOrCreateGlobal();
|
|
2244
|
+
state.openChangeIds = inspection.changes;
|
|
2245
|
+
if (state.activeChangeId && !inspection.changes.includes(state.activeChangeId)) {
|
|
2246
|
+
state.activeChangeId = inspection.changes.length === 1 ? inspection.changes[0] ?? null : null;
|
|
2247
|
+
}
|
|
2248
|
+
await ctx.stateStore.writeGlobal(state);
|
|
2249
|
+
ctx.output.result({
|
|
2250
|
+
ok: true,
|
|
2251
|
+
command: "onboard",
|
|
2252
|
+
summary: "fet onboard loaded local FET/OpenSpec workflow context.",
|
|
2253
|
+
nextSteps: [
|
|
2254
|
+
inspection.changes.length ? `Open changes: ${inspection.changes.join(", ")}` : "No open changes found. Run fet propose <change-id-or-description> to start one.",
|
|
2255
|
+
"Use fet continue to prepare planning artifacts, fet apply for implementation instructions, fet verify before archive."
|
|
2256
|
+
],
|
|
2257
|
+
data: { activeChangeId: state.activeChangeId, openChangeIds: inspection.changes, archivedChangeIds: inspection.archived }
|
|
2258
|
+
});
|
|
2259
|
+
}
|
|
2085
2260
|
async function artifactWorkflowCommand(ctx, command, args) {
|
|
2086
2261
|
const openSpecArgs = stripFetOptions(args);
|
|
2087
2262
|
const runState = {};
|
|
@@ -2112,8 +2287,9 @@ async function artifactWorkflowCommand(ctx, command, args) {
|
|
|
2112
2287
|
warnings: runState.graphContext?.warnings,
|
|
2113
2288
|
nextSteps: [
|
|
2114
2289
|
`Create or update openspec/changes/${changeId}/${resolveOutputPath(status, artifactId)}`,
|
|
2290
|
+
"Review the artifact with the user before generating the next planning file.",
|
|
2115
2291
|
`Run fet passthrough status --change ${changeId}`,
|
|
2116
|
-
status.isComplete ? `Run fet apply --change ${changeId}` : `Run fet continue --change ${changeId}`
|
|
2292
|
+
status.isComplete ? `Run fet apply --change ${changeId}` : `Run fet continue --change ${changeId} when ready for the next artifact`
|
|
2117
2293
|
],
|
|
2118
2294
|
data: {
|
|
2119
2295
|
changeId,
|
|
@@ -2267,9 +2443,10 @@ async function syncWorkflowState(ctx, command, changeId, lastOpenSpecCommand) {
|
|
|
2267
2443
|
}
|
|
2268
2444
|
const changeInspection = await ctx.openSpec.inspectChange(ctx.projectRoot, changeId);
|
|
2269
2445
|
const changeState = await ctx.stateStore.getOrCreateChange(changeId, phaseByCommand[command] ?? "propose");
|
|
2270
|
-
|
|
2271
|
-
changeState.
|
|
2272
|
-
|
|
2446
|
+
const phase = phaseByCommand[command] ?? "propose";
|
|
2447
|
+
changeState.currentPhase = phase;
|
|
2448
|
+
changeState.phases[phase] = {
|
|
2449
|
+
status: lastOpenSpecCommand.phaseStatus ?? "in_progress",
|
|
2273
2450
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2274
2451
|
};
|
|
2275
2452
|
changeState.lastOpenSpecCommand = {
|
|
@@ -2479,6 +2656,9 @@ async function assertVerified(ctx) {
|
|
|
2479
2656
|
suggestedCommand: "fet verify --done --change <change-id>"
|
|
2480
2657
|
});
|
|
2481
2658
|
}
|
|
2659
|
+
await assertVerifiedChange(ctx, changeId);
|
|
2660
|
+
}
|
|
2661
|
+
async function assertVerifiedChange(ctx, changeId) {
|
|
2482
2662
|
const change = await ctx.stateStore.readChange(changeId);
|
|
2483
2663
|
const inspection = await ctx.openSpec.inspectProject(ctx.projectRoot);
|
|
2484
2664
|
if (!inspection.changes.includes(changeId)) {
|
|
@@ -2969,7 +3149,7 @@ var FET_WORKFLOW_COMMANDS = [
|
|
|
2969
3149
|
"onboard"
|
|
2970
3150
|
];
|
|
2971
3151
|
var FET_GRAPH_COMMANDS = ["graph-status", "graph-setup", "graph-init", "graph-refresh", "graph-doctor", "graph-handoff"];
|
|
2972
|
-
var FET_ADAPTER_COMMANDS = [...FET_WORKFLOW_COMMANDS, "fill-context", "passthrough", ...FET_GRAPH_COMMANDS];
|
|
3152
|
+
var FET_ADAPTER_COMMANDS = [...FET_WORKFLOW_COMMANDS, "update", "fill-context", "passthrough", ...FET_GRAPH_COMMANDS];
|
|
2973
3153
|
function renderFetAdapterUsage(command, args = "[...args]") {
|
|
2974
3154
|
if (command.startsWith("graph-")) {
|
|
2975
3155
|
const subcommand = command.slice("graph-".length);
|
|
@@ -3263,12 +3443,15 @@ After the command completes, report the GitNexus state, generated handoff files,
|
|
|
3263
3443
|
`;
|
|
3264
3444
|
}
|
|
3265
3445
|
function renderSlashPrompt(command, language) {
|
|
3266
|
-
if (command === "ff"
|
|
3267
|
-
return renderFastForwardSlashPrompt(
|
|
3446
|
+
if (command === "ff") {
|
|
3447
|
+
return renderFastForwardSlashPrompt(language);
|
|
3268
3448
|
}
|
|
3269
3449
|
if (language !== "en") {
|
|
3270
3450
|
return renderSlashPromptZh(command);
|
|
3271
3451
|
}
|
|
3452
|
+
if (command === "propose") {
|
|
3453
|
+
return renderProposeSlashPrompt(language);
|
|
3454
|
+
}
|
|
3272
3455
|
if (command === "continue") {
|
|
3273
3456
|
return renderContinueSlashPrompt(language);
|
|
3274
3457
|
}
|
|
@@ -3382,12 +3565,12 @@ ${commandGoalZh(command)}
|
|
|
3382
3565
|
- \u9ED8\u8BA4\u4F7F\u7528\u4E2D\u6587\u4EA7\u51FA\u3002
|
|
3383
3566
|
- \u4E0D\u8981\u7ED5\u8FC7 FET \u76F4\u63A5\u8C03\u7528 openspec\uFF0C\u9664\u975E FET \u547D\u4EE4\u672C\u8EAB\u4E0D\u53EF\u7528\u3002
|
|
3384
3567
|
- change \u4E0D\u660E\u786E\u65F6\u5148\u8BE2\u95EE\u7528\u6237\u3002
|
|
3385
|
-
${command === "fill-context" ? "- \u66FF\u6362 AGENTS.md \u4E2D\u6BCF\u4E2A `[NEEDS LLM INPUT]` \u6216 `[NEED LLM INPUT]` \u5360\u4F4D\u7B26\uFF0C\u4FDD\u7559 FET \u6258\u7BA1\u6807\u8BB0\uFF0C\u4E0D\u8981\u4FEE\u6539\u4E1A\u52A1\u4EE3\u7801\u3002\n" : ""}${command === "continue" ? "- \u4E00\u6B21\u53EA\u521B\u5EFA\u4E00\u4E2A ready artifact\uFF0C\u5E76\u5728\u5199\u5165\u524D\u9605\u8BFB\u4F9D\u8D56\u6587\u4EF6\u3002\n" : ""}${command === "apply" ? "- \u4E0D\u8981\u5728\u672A\u5B8C\u6210\u771F\u5B9E\u5B9E\u73B0\u524D\u52FE\u9009 tasks.md\uFF1B\u4E0D\u8981\u4ECE apply \u9636\u6BB5\u76F4\u63A5 sync \u6216 archive\u3002\n" : ""}`;
|
|
3568
|
+
${command === "fill-context" ? "- \u66FF\u6362 AGENTS.md \u4E2D\u6BCF\u4E2A `[NEEDS LLM INPUT]` \u6216 `[NEED LLM INPUT]` \u5360\u4F4D\u7B26\uFF0C\u4FDD\u7559 FET \u6258\u7BA1\u6807\u8BB0\uFF0C\u4E0D\u8981\u4FEE\u6539\u4E1A\u52A1\u4EE3\u7801\u3002\n" : ""}${command === "propose" || command === "continue" ? "- \u4E00\u6B21\u53EA\u521B\u5EFA\u4E00\u4E2A ready artifact\uFF0C\u5E76\u5728\u5199\u5165\u524D\u9605\u8BFB\u4F9D\u8D56\u6587\u4EF6\u3002\n" : ""}${command === "propose" || command === "continue" ? "- \u4E0D\u8981\u5728\u7528\u6237\u5BA1\u9605\u5F53\u524D\u4EA7\u7269\u524D\u81EA\u52A8\u8FD0\u884C fet continue\u3001fet ff \u6216\u5FAA\u73AF\u751F\u6210\u540E\u7EED\u4EA7\u7269\uFF1B\u9700\u8981\u7528\u6237\u660E\u786E\u786E\u8BA4\u540E\u518D\u63A8\u8FDB\u3002\n" : ""}${command === "apply" ? "- \u4E0D\u8981\u5728\u672A\u5B8C\u6210\u771F\u5B9E\u5B9E\u73B0\u524D\u52FE\u9009 tasks.md\uFF1B\u4E0D\u8981\u4ECE apply \u9636\u6BB5\u76F4\u63A5 sync \u6216 archive\u3002\n" : ""}`;
|
|
3386
3569
|
}
|
|
3387
3570
|
function commandTitleZh(command) {
|
|
3388
3571
|
const titles = {
|
|
3389
3572
|
explore: "\u63A2\u7D22 FET/OpenSpec \u9700\u6C42",
|
|
3390
|
-
propose: "\u521B\u5EFA
|
|
3573
|
+
propose: "\u521B\u5EFA FET/OpenSpec change \u5E76\u751F\u6210\u9996\u4E2A\u89C4\u5212\u4EA7\u7269",
|
|
3391
3574
|
new: "\u521B\u5EFA\u65B0\u7684 FET/OpenSpec change \u9AA8\u67B6",
|
|
3392
3575
|
continue: "\u63A8\u8FDB\u5F53\u524D FET/OpenSpec change \u7684\u4E0B\u4E00\u4E2A\u4EA7\u7269",
|
|
3393
3576
|
ff: "\u5FEB\u901F\u751F\u6210 FET/OpenSpec \u6240\u9700\u4EA7\u7269",
|
|
@@ -3412,9 +3595,15 @@ function commandGoalZh(command) {
|
|
|
3412
3595
|
if (command === "fill-context") {
|
|
3413
3596
|
return "\u8865\u9F50 FET \u81EA\u52A8\u751F\u6210\u7684\u9879\u76EE\u4E0A\u4E0B\u6587\uFF0C\u8BA9\u540E\u7EED AI \u7F16\u7801\u548C OpenSpec \u5DE5\u4F5C\u6D41\u62E5\u6709\u7A33\u5B9A\u7684\u9879\u76EE\u4E8B\u5B9E\u3002";
|
|
3414
3597
|
}
|
|
3598
|
+
if (command === "propose") {
|
|
3599
|
+
return "\u6839\u636E change id \u6216\u63CF\u8FF0\u521B\u5EFA OpenSpec change\uFF08\u5982\u4E0D\u5B58\u5728\uFF09\uFF0C\u5E76\u53EA\u751F\u6210\u5F53\u524D\u7B2C\u4E00\u4E2A ready \u7684\u89C4\u5212\u4EA7\u7269\u3002";
|
|
3600
|
+
}
|
|
3415
3601
|
if (command === "continue") {
|
|
3416
3602
|
return "\u57FA\u4E8E active change \u6216\u7528\u6237\u6307\u5B9A\u7684 change\uFF0C\u521B\u5EFA\u4E0B\u4E00\u4E2A ready \u7684 OpenSpec \u89C4\u5212\u4EA7\u7269\u3002";
|
|
3417
3603
|
}
|
|
3604
|
+
if (command === "ff") {
|
|
3605
|
+
return "\u5728\u7528\u6237\u660E\u786E\u8981\u6C42\u5FEB\u8FDB\u65F6\uFF0C\u4E00\u6B21\u6027\u751F\u6210 change \u6240\u9700\u7684\u5168\u90E8\u89C4\u5212\u4EA7\u7269\u3002";
|
|
3606
|
+
}
|
|
3418
3607
|
if (command === "apply") {
|
|
3419
3608
|
return "\u8BFB\u53D6 OpenSpec \u4EA7\u7269\u5E76\u6309 tasks.md \u5B9E\u65BD\u4EE3\u7801\u53D8\u66F4\u3002";
|
|
3420
3609
|
}
|
|
@@ -3828,6 +4017,45 @@ Guardrails:
|
|
|
3828
4017
|
language
|
|
3829
4018
|
);
|
|
3830
4019
|
}
|
|
4020
|
+
function renderProposeSlashPrompt(language) {
|
|
4021
|
+
return renderManagedSlashPrompt(
|
|
4022
|
+
"fet propose [...args]",
|
|
4023
|
+
"Create a FET/OpenSpec change and its first ready artifact",
|
|
4024
|
+
`Start proposal planning for a FET-managed OpenSpec change by creating exactly one ready artifact.
|
|
4025
|
+
|
|
4026
|
+
Input after the slash command may be a change id or a short description of what the user wants to build. If omitted, ask the user.
|
|
4027
|
+
|
|
4028
|
+
Steps:
|
|
4029
|
+
|
|
4030
|
+
1. Load project context from AGENTS.md and openspec/config.yaml.
|
|
4031
|
+
2. Derive a kebab-case change id when the user provided a description. If ambiguous, ask the user.
|
|
4032
|
+
3. Run the native OpenSpec propose flow through FET. This creates the change when needed and returns instructions for only the next ready artifact:
|
|
4033
|
+
\`\`\`sh
|
|
4034
|
+
fet propose <change-id-or-description> --json
|
|
4035
|
+
\`\`\`
|
|
4036
|
+
4. Follow the native output. When it provides template, instruction, dependencies, and outputPath, use those fields.
|
|
4037
|
+
5. Read dependency files before writing.
|
|
4038
|
+
6. Create only that artifact file at outputPath. Do not copy context/rules wrapper text into the artifact.
|
|
4039
|
+
7. Verify the file exists, then run:
|
|
4040
|
+
\`\`\`sh
|
|
4041
|
+
fet passthrough status --change <change-id>
|
|
4042
|
+
\`\`\`
|
|
4043
|
+
|
|
4044
|
+
Output:
|
|
4045
|
+
- Change id and location.
|
|
4046
|
+
- Which single artifact was created and its file path.
|
|
4047
|
+
- Current status.
|
|
4048
|
+
- Tell the user to review the artifact and run /prompts:fet-continue <change-id> when ready for the next artifact. Mention /prompts:fet-ff <change-id> only if they explicitly want to fast-forward all remaining artifacts.
|
|
4049
|
+
|
|
4050
|
+
Guardrails:
|
|
4051
|
+
- Create one artifact per invocation. Do not run fet continue or fet ff in the same session unless the user explicitly asks after reviewing the artifact just created.
|
|
4052
|
+
- Never skip dependency order.
|
|
4053
|
+
- Do not substitute one FET/OpenSpec workflow command for another after a command-not-found or unsupported-version error.
|
|
4054
|
+
- Ask the user if instructions are ambiguous enough that a useful artifact cannot be written.`,
|
|
4055
|
+
void 0,
|
|
4056
|
+
language
|
|
4057
|
+
);
|
|
4058
|
+
}
|
|
3831
4059
|
function renderContinueSlashPrompt(language) {
|
|
3832
4060
|
return renderManagedSlashPrompt(
|
|
3833
4061
|
"fet continue [...args]",
|
|
@@ -3870,27 +4098,27 @@ Guardrails:
|
|
|
3870
4098
|
language
|
|
3871
4099
|
);
|
|
3872
4100
|
}
|
|
3873
|
-
function renderFastForwardSlashPrompt(
|
|
3874
|
-
const title = language === "en" ? command === "propose" ? "Propose a new FET/OpenSpec change" : "Fast-forward FET/OpenSpec artifact creation" : command === "propose" ? "\u521B\u5EFA\u5E76\u8865\u9F50 FET/OpenSpec \u63D0\u6848\u4EA7\u7269" : "\u5FEB\u901F\u751F\u6210 FET/OpenSpec \u6240\u9700\u4EA7\u7269";
|
|
3875
|
-
const commandLine = command === "propose" ? "fet propose <change-id-or-description>" : "fet ff --change <change-id>";
|
|
4101
|
+
function renderFastForwardSlashPrompt(language) {
|
|
3876
4102
|
return renderManagedSlashPrompt(
|
|
3877
|
-
|
|
3878
|
-
language === "en" ?
|
|
3879
|
-
`${
|
|
4103
|
+
"fet ff [...args]",
|
|
4104
|
+
language === "en" ? "Fast-forward FET/OpenSpec artifact creation" : "\u5FEB\u901F\u751F\u6210 FET/OpenSpec \u6240\u9700\u4EA7\u7269",
|
|
4105
|
+
`${language === "en" ? "Fast-forward FET/OpenSpec artifact creation" : "\u5FEB\u901F\u751F\u6210 FET/OpenSpec \u6240\u9700\u4EA7\u7269"}.
|
|
4106
|
+
|
|
4107
|
+
Use this command only when the user explicitly wants to generate all remaining planning artifacts in one session without reviewing each artifact between steps. For step-by-step review, use /prompts:fet-propose or /prompts:fet-continue instead.
|
|
3880
4108
|
|
|
3881
|
-
Input after the slash command may be a change id
|
|
4109
|
+
Input after the slash command may be a change id. It may be omitted when the active OpenSpec change is unambiguous.
|
|
3882
4110
|
|
|
3883
4111
|
Steps:
|
|
3884
4112
|
|
|
3885
4113
|
1. Load project context from AGENTS.md and openspec/config.yaml.
|
|
3886
|
-
2. Resolve the change id
|
|
3887
|
-
3. Run the native OpenSpec
|
|
4114
|
+
2. Resolve the change id. If ambiguous, ask the user.
|
|
4115
|
+
3. Run the native OpenSpec ff flow through FET:
|
|
3888
4116
|
\`\`\`sh
|
|
3889
|
-
|
|
4117
|
+
fet ff --change <change-id>
|
|
3890
4118
|
\`\`\`
|
|
3891
4119
|
4. Follow the native output. If it asks for clarification, ask the user rather than inventing details.
|
|
3892
|
-
5. If the native output includes artifact paths or templates to write, create
|
|
3893
|
-
6. If FET reports that the OpenSpec CLI does not expose the requested command, stop immediately. Do not run \`fet
|
|
4120
|
+
5. If the native output includes artifact paths or templates to write, create those files and preserve OpenSpec structure.
|
|
4121
|
+
6. If FET reports that the OpenSpec CLI does not expose the requested command, stop immediately. Do not run \`fet continue\`, \`openspec change\`, or any alternative workflow command unless the user explicitly chooses that fallback after seeing the error.
|
|
3894
4122
|
|
|
3895
4123
|
Artifact rules:
|
|
3896
4124
|
- Follow the instruction field from OpenSpec/FET for each artifact.
|