@peterxiaoyang/superspec 0.1.53 → 0.1.55
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 +7 -6
- package/dist/cli.js +71 -10
- package/dist/install.d.ts +11 -0
- package/dist/install.js +68 -13
- package/dist/record.js +3 -3
- package/dist/transition.js +21 -1
- package/dist/workflow_config.d.ts +10 -0
- package/dist/workflow_config.js +78 -20
- package/package.json +1 -1
- package/templates/workflow/AGENTS.md +1 -1
- package/templates/workflow/agents-md/architect.md +13 -0
- package/templates/workflow/agents-md/code-reviewer.md +13 -0
- package/templates/workflow/agents-md/critic.md +13 -0
- package/templates/workflow/agents-md/executor.md +13 -0
- package/templates/workflow/agents-md/explore.md +13 -0
- package/templates/workflow/agents-md/test-engineer.md +13 -0
- package/templates/workflow/agents-md/test-runner.md +13 -0
- package/templates/workflow/agents-md/verifier.md +13 -0
- package/templates/workflow/skills/superspec-apply/SKILL.md +1 -1
- package/templates/workflow/skills/superspec-explore/SKILL.md +1 -1
- package/templates/workflow/skills/superspec-propose/SKILL.md +1 -1
- package/templates/workflow/skills/superspec-review/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -33,14 +33,14 @@ superspec status
|
|
|
33
33
|
|
|
34
34
|
## 工作流入口
|
|
35
35
|
|
|
36
|
-
在 Codex 中显式调用对应 Skill。新需求通常从
|
|
36
|
+
在 Codex 中显式调用对应 Skill。新需求通常从 `superspec-explore` 开始;已有 change 则从当前阶段继续。
|
|
37
37
|
|
|
38
38
|
| Skill | 作用 |
|
|
39
39
|
| --- | --- |
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
40
|
+
| `superspec-explore` | 调查现状,确认事实和待决策事项 |
|
|
41
|
+
| `superspec-propose` | 生成规格、设计和可执行任务 |
|
|
42
|
+
| `superspec-apply` | 按已批准任务修改代码并验证 |
|
|
43
|
+
| `superspec-review` | 审查实现并完成最终验证 |
|
|
44
44
|
|
|
45
45
|
工作流会根据问题性质留在当前阶段修复,或回到计划阶段重新确认需求、验收和技术取舍。
|
|
46
46
|
|
|
@@ -51,7 +51,8 @@ superspec status
|
|
|
51
51
|
```json
|
|
52
52
|
{
|
|
53
53
|
"workflow": {
|
|
54
|
-
"mode": "normal"
|
|
54
|
+
"mode": "normal",
|
|
55
|
+
"hosts": ["codex"]
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
```
|
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ import { recordTestRun, recordTestRunContent } from "./task.js";
|
|
|
13
13
|
import { RecordInputDecodingError, decodeRecordInput } from "./record_input.js";
|
|
14
14
|
import { probeOpenSpec, openspecStatus, changeRoot } from "./openspec.js";
|
|
15
15
|
import { SUPERSPEC_VERSION } from "./version.js";
|
|
16
|
-
import { WorkflowConfigError, workflowRiskForProject } from "./workflow_config.js";
|
|
16
|
+
import { DEFAULT_WORKFLOW_HOSTS, parseWorkflowHostsFlag, WorkflowConfigError, workflowHostsDeclared, workflowHostsForProject, workflowRiskForProject, } from "./workflow_config.js";
|
|
17
17
|
const PACKAGE_NAME = "@peterxiaoyang/superspec";
|
|
18
18
|
const OPENSPEC_PACKAGE_NAME = "@fission-ai/openspec";
|
|
19
19
|
const OPENSPEC_REQUIRED_VERSION = "1.4.1";
|
|
@@ -490,6 +490,55 @@ async function askToUpdateSelfIfNeeded(projectRoot, rerunArgs) {
|
|
|
490
490
|
throw attachSelfUpdateLatest(err, "rerun", latest);
|
|
491
491
|
}
|
|
492
492
|
}
|
|
493
|
+
function parseSelectedHosts(raw) {
|
|
494
|
+
if (!raw)
|
|
495
|
+
return DEFAULT_WORKFLOW_HOSTS;
|
|
496
|
+
return parseWorkflowHostsFlag(raw);
|
|
497
|
+
}
|
|
498
|
+
function parseHostPromptAnswer(raw) {
|
|
499
|
+
const tokens = raw.toLowerCase().split(/[,\s]+/).filter(Boolean);
|
|
500
|
+
if (tokens.length === 0)
|
|
501
|
+
return DEFAULT_WORKFLOW_HOSTS;
|
|
502
|
+
const selected = [];
|
|
503
|
+
for (const token of tokens) {
|
|
504
|
+
if (token === "1" || token === "codex")
|
|
505
|
+
selected.push("codex");
|
|
506
|
+
else if (token === "2" || token === "omp")
|
|
507
|
+
selected.push("omp");
|
|
508
|
+
else if (token === "both" || token === "all")
|
|
509
|
+
selected.push("codex", "omp");
|
|
510
|
+
else
|
|
511
|
+
throw new WorkflowConfigError(`无法识别的宿主选项:${token}。可用 1/codex、2/omp,或 both`);
|
|
512
|
+
}
|
|
513
|
+
return parseWorkflowHostsFlag(selected.join(","));
|
|
514
|
+
}
|
|
515
|
+
async function resolveInstallHosts(projectRoot, opts, mode) {
|
|
516
|
+
if (opts.hosts)
|
|
517
|
+
return parseSelectedHosts(opts.hosts);
|
|
518
|
+
if (mode === "update" || workflowHostsDeclared(projectRoot))
|
|
519
|
+
return workflowHostsForProject(projectRoot);
|
|
520
|
+
const assumeTty = testEnv("SUPERSPEC_TEST_ASSUME_TTY") === "1";
|
|
521
|
+
if (!assumeTty && (!process.stdin.isTTY || !process.stdout.isTTY))
|
|
522
|
+
return DEFAULT_WORKFLOW_HOSTS;
|
|
523
|
+
const testAnswer = testEnv("SUPERSPEC_TEST_HOSTS_ANSWER");
|
|
524
|
+
if (testAnswer !== undefined)
|
|
525
|
+
return parseHostPromptAnswer(testAnswer);
|
|
526
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
527
|
+
try {
|
|
528
|
+
const answer = await rl.question("选择 SuperSpec 入口宿主:1) Codex 2) OMP。可多选,例如 1,2;直接回车默认 Codex。 ");
|
|
529
|
+
return parseHostPromptAnswer(answer);
|
|
530
|
+
}
|
|
531
|
+
finally {
|
|
532
|
+
rl.close();
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function installOptionsFromCli(opts, hosts, allowLegacyState = false) {
|
|
536
|
+
return {
|
|
537
|
+
hosts,
|
|
538
|
+
allowLegacyState,
|
|
539
|
+
...(opts["omp-home"] ? { ompHome: opts["omp-home"] } : {}),
|
|
540
|
+
};
|
|
541
|
+
}
|
|
493
542
|
// ===== 初始化 transition init =====
|
|
494
543
|
// ===== init/explore 现在在 transition.ts 中(走统一锁内路径)=====
|
|
495
544
|
// ===== 主分发 =====
|
|
@@ -503,9 +552,9 @@ function topLevelHelp() {
|
|
|
503
552
|
transition <子命令> --change <C> 状态流转(见下)
|
|
504
553
|
record <子命令> --change <C> 登记证据(见下)
|
|
505
554
|
jobs <子命令> --change <C> 工作项管理(见下)
|
|
506
|
-
install
|
|
555
|
+
install [--hosts codex,omp] 安装项目工作流入口
|
|
507
556
|
init --scope project install 的兼容别名
|
|
508
|
-
update
|
|
557
|
+
update [--hosts codex,omp] 升级 CLI 到 npm latest 并同步已选宿主入口
|
|
509
558
|
version 版本号
|
|
510
559
|
|
|
511
560
|
transition 子命令:
|
|
@@ -589,10 +638,14 @@ async function main(argv) {
|
|
|
589
638
|
return 1;
|
|
590
639
|
}
|
|
591
640
|
try {
|
|
641
|
+
const hosts = await resolveInstallHosts(projectRoot, opts, "install");
|
|
592
642
|
if (opts["skip-self-update"] !== "true") {
|
|
643
|
+
const hostArgs = ["--hosts", hosts.join(",")];
|
|
644
|
+
if (opts["omp-home"])
|
|
645
|
+
hostArgs.push("--omp-home", opts["omp-home"]);
|
|
593
646
|
const rerunArgs = command === "init"
|
|
594
|
-
? ["init", "--scope", "project", "--skip-self-update"]
|
|
595
|
-
: ["install", "--skip-self-update"];
|
|
647
|
+
? ["init", "--scope", "project", "--skip-self-update", ...hostArgs]
|
|
648
|
+
: ["install", "--skip-self-update", ...hostArgs];
|
|
596
649
|
const selfUpdate = await askToUpdateSelfIfNeeded(projectRoot, rerunArgs);
|
|
597
650
|
if (selfUpdate.updated) {
|
|
598
651
|
const rerun = updatedCliOutput(selfUpdate.output, selfUpdate.latest);
|
|
@@ -602,7 +655,7 @@ async function main(argv) {
|
|
|
602
655
|
}
|
|
603
656
|
const openspec = ensureOpenSpecCli();
|
|
604
657
|
console.log(JSON.stringify({
|
|
605
|
-
...installProject(projectRoot),
|
|
658
|
+
...installProject(projectRoot, installOptionsFromCli(opts, hosts)),
|
|
606
659
|
openspec,
|
|
607
660
|
}));
|
|
608
661
|
return 0;
|
|
@@ -612,14 +665,20 @@ async function main(argv) {
|
|
|
612
665
|
? selfUpdateFailurePayload(err)
|
|
613
666
|
: err instanceof OpenSpecDependencyError
|
|
614
667
|
? openSpecDependencyFailurePayload(err)
|
|
615
|
-
:
|
|
668
|
+
: err instanceof WorkflowConfigError
|
|
669
|
+
? { ok: false, message: err.message }
|
|
670
|
+
: { ok: false, message: commandErrorMessage(err) }));
|
|
616
671
|
return 1;
|
|
617
672
|
}
|
|
618
673
|
}
|
|
619
674
|
if (command === "update") {
|
|
620
675
|
try {
|
|
676
|
+
const hosts = await resolveInstallHosts(projectRoot, opts, "update");
|
|
621
677
|
if (opts["skip-self-update"] !== "true") {
|
|
622
|
-
const
|
|
678
|
+
const hostArgs = ["--hosts", hosts.join(",")];
|
|
679
|
+
if (opts["omp-home"])
|
|
680
|
+
hostArgs.push("--omp-home", opts["omp-home"]);
|
|
681
|
+
const selfUpdate = updateSelfIfNeeded(projectRoot, ["update", "--skip-self-update", ...hostArgs]);
|
|
623
682
|
if (selfUpdate.updated) {
|
|
624
683
|
const rerun = updatedCliOutput(selfUpdate.output, selfUpdate.latest);
|
|
625
684
|
console.log(rerun.text);
|
|
@@ -627,7 +686,7 @@ async function main(argv) {
|
|
|
627
686
|
}
|
|
628
687
|
}
|
|
629
688
|
const openspec = ensureOpenSpecCli();
|
|
630
|
-
const result = installProject(projectRoot,
|
|
689
|
+
const result = installProject(projectRoot, installOptionsFromCli(opts, hosts, true));
|
|
631
690
|
console.log(JSON.stringify({
|
|
632
691
|
...result,
|
|
633
692
|
openspec,
|
|
@@ -640,7 +699,9 @@ async function main(argv) {
|
|
|
640
699
|
? selfUpdateFailurePayload(err)
|
|
641
700
|
: err instanceof OpenSpecDependencyError
|
|
642
701
|
? openSpecDependencyFailurePayload(err)
|
|
643
|
-
:
|
|
702
|
+
: err instanceof WorkflowConfigError
|
|
703
|
+
? { ok: false, message: err.message }
|
|
704
|
+
: { ok: false, message: commandErrorMessage(err) }));
|
|
644
705
|
return 1;
|
|
645
706
|
}
|
|
646
707
|
}
|
package/dist/install.d.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
|
+
import { type WorkflowHost } from "./workflow_config.ts";
|
|
1
2
|
export declare const WORKFLOW_SKILLS: readonly ["superspec-explore", "superspec-propose", "superspec-apply", "superspec-review"];
|
|
2
3
|
export declare const WORKFLOW_PROMPTS: readonly ["architect.md", "code-reviewer.md", "critic.md", "executor.md", "explore.md", "test-engineer.md", "test-runner.md", "verifier.md"];
|
|
3
4
|
export declare const WORKFLOW_AGENTS: readonly ["architect.toml", "code-reviewer.toml", "critic.toml", "executor.toml", "explore.toml", "test-engineer.toml", "test-runner.toml", "verifier.toml"];
|
|
5
|
+
export declare const WORKFLOW_MARKDOWN_AGENTS: readonly ["architect.md", "code-reviewer.md", "critic.md", "executor.md", "explore.md", "test-engineer.md", "test-runner.md", "verifier.md"];
|
|
6
|
+
export interface OmpInstallResult {
|
|
7
|
+
dest: string | null;
|
|
8
|
+
agents: string[];
|
|
9
|
+
skipped: string | null;
|
|
10
|
+
}
|
|
4
11
|
export interface InstallResult {
|
|
5
12
|
ok: boolean;
|
|
6
13
|
message: string;
|
|
7
14
|
installed: {
|
|
8
15
|
engine_dir: string;
|
|
16
|
+
hosts: WorkflowHost[];
|
|
9
17
|
skills: string[];
|
|
10
18
|
prompts: string[];
|
|
11
19
|
agents: string[];
|
|
20
|
+
omp: OmpInstallResult;
|
|
12
21
|
config: string;
|
|
13
22
|
workflow_config: string;
|
|
14
23
|
agents_md: string;
|
|
@@ -18,5 +27,7 @@ export interface InstallResult {
|
|
|
18
27
|
export interface InstallOptions {
|
|
19
28
|
templateRoot?: string;
|
|
20
29
|
allowLegacyState?: boolean;
|
|
30
|
+
hosts?: WorkflowHost[];
|
|
31
|
+
ompHome?: string;
|
|
21
32
|
}
|
|
22
33
|
export declare function installProject(projectRoot: string, options?: InstallOptions): InstallResult;
|
package/dist/install.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
2
3
|
import { dirname, join } from "node:path";
|
|
3
4
|
import { SUPERSPEC_VERSION } from "./version.js";
|
|
4
|
-
import {
|
|
5
|
+
import { DEFAULT_WORKFLOW_HOSTS, persistWorkflowHosts, workflowHostsDeclared, workflowHostsForProject, } from "./workflow_config.js";
|
|
5
6
|
export const WORKFLOW_SKILLS = [
|
|
6
7
|
"superspec-explore",
|
|
7
8
|
"superspec-propose",
|
|
@@ -29,6 +30,16 @@ export const WORKFLOW_AGENTS = [
|
|
|
29
30
|
"test-runner.toml",
|
|
30
31
|
"verifier.toml",
|
|
31
32
|
];
|
|
33
|
+
export const WORKFLOW_MARKDOWN_AGENTS = [
|
|
34
|
+
"architect.md",
|
|
35
|
+
"code-reviewer.md",
|
|
36
|
+
"critic.md",
|
|
37
|
+
"executor.md",
|
|
38
|
+
"explore.md",
|
|
39
|
+
"test-engineer.md",
|
|
40
|
+
"test-runner.md",
|
|
41
|
+
"verifier.md",
|
|
42
|
+
];
|
|
32
43
|
function defaultTemplateRoot() {
|
|
33
44
|
return join(import.meta.dirname, "..", "templates", "workflow");
|
|
34
45
|
}
|
|
@@ -56,6 +67,11 @@ function assertWorkflowTemplates(templateRoot) {
|
|
|
56
67
|
if (!existsSync(file))
|
|
57
68
|
missing.push(file);
|
|
58
69
|
}
|
|
70
|
+
for (const agent of WORKFLOW_MARKDOWN_AGENTS) {
|
|
71
|
+
const file = join(templateRoot, "agents-md", agent);
|
|
72
|
+
if (!existsSync(file))
|
|
73
|
+
missing.push(file);
|
|
74
|
+
}
|
|
59
75
|
const agentsMdTemplate = join(templateRoot, "AGENTS.md");
|
|
60
76
|
if (!existsSync(agentsMdTemplate))
|
|
61
77
|
missing.push(agentsMdTemplate);
|
|
@@ -248,14 +264,44 @@ function ensureOpenSpecChineseContext(projectRoot) {
|
|
|
248
264
|
writeFileSync(configPath, next);
|
|
249
265
|
return OPENSPEC_CONFIG_PATH;
|
|
250
266
|
}
|
|
251
|
-
function
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
267
|
+
function copyOmpAgents(templateRoot, dest) {
|
|
268
|
+
const agentsDest = join(dest, "agents");
|
|
269
|
+
const installedAgents = [];
|
|
270
|
+
for (const agent of WORKFLOW_MARKDOWN_AGENTS) {
|
|
271
|
+
const src = join(templateRoot, "agents-md", agent);
|
|
272
|
+
writeBundledFile(src, join(agentsDest, agent));
|
|
273
|
+
installedAgents.push(agent);
|
|
257
274
|
}
|
|
258
|
-
return
|
|
275
|
+
return installedAgents;
|
|
276
|
+
}
|
|
277
|
+
function existingDirectory(path) {
|
|
278
|
+
try {
|
|
279
|
+
return statSync(path).isDirectory();
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function resolveOmpAgentHome(explicitHome) {
|
|
286
|
+
if (explicitHome) {
|
|
287
|
+
return existingDirectory(explicitHome)
|
|
288
|
+
? { dest: explicitHome, skipped: null }
|
|
289
|
+
: { dest: null, skipped: `OMP 用户目录不存在:${explicitHome}` };
|
|
290
|
+
}
|
|
291
|
+
const profile = (process.env.OMP_PROFILE ?? process.env.PI_PROFILE ?? "").trim();
|
|
292
|
+
const dest = profile && profile !== "default"
|
|
293
|
+
? join(homedir(), ".omp", "profiles", profile, "agent")
|
|
294
|
+
: join(homedir(), ".omp", "agent");
|
|
295
|
+
if (!existingDirectory(dest)) {
|
|
296
|
+
return { dest: null, skipped: `OMP 用户目录不存在:${dest}。先启动一次 omp,或用 --omp-home 指定已有目录。` };
|
|
297
|
+
}
|
|
298
|
+
return { dest, skipped: null };
|
|
299
|
+
}
|
|
300
|
+
function installOmpAgents(templateRoot, ompHome) {
|
|
301
|
+
const resolved = resolveOmpAgentHome(ompHome);
|
|
302
|
+
if (!resolved.dest)
|
|
303
|
+
return { dest: null, agents: [], skipped: resolved.skipped };
|
|
304
|
+
return { dest: resolved.dest, agents: copyOmpAgents(templateRoot, resolved.dest), skipped: null };
|
|
259
305
|
}
|
|
260
306
|
const AGENTS_MD_PATH = "AGENTS.md";
|
|
261
307
|
const SUPERSPEC_AGENTS_START = "<!-- SUPERSPEC:AGENTS:START -->";
|
|
@@ -299,22 +345,31 @@ export function installProject(projectRoot, options = {}) {
|
|
|
299
345
|
const templateRoot = options.templateRoot ?? defaultTemplateRoot();
|
|
300
346
|
assertWorkflowTemplates(templateRoot);
|
|
301
347
|
const agentsMdTemplate = readAgentsMdTemplate(templateRoot);
|
|
348
|
+
const hosts = options.hosts
|
|
349
|
+
?? (workflowHostsDeclared(projectRoot) ? workflowHostsForProject(projectRoot) : DEFAULT_WORKFLOW_HOSTS);
|
|
350
|
+
const wantsCodex = hosts.includes("codex");
|
|
351
|
+
const wantsOmp = hosts.includes("omp");
|
|
302
352
|
const engineDir = join(projectRoot, ".superspec");
|
|
303
353
|
mkdirSync(join(engineDir, "changes"), { recursive: true });
|
|
304
354
|
const gitignorePath = join(engineDir, ".gitignore");
|
|
305
355
|
if (!existsSync(gitignorePath))
|
|
306
356
|
writeFileSync(gitignorePath, "changes/\n*.log\n*.tmp\n");
|
|
307
357
|
migrateLegacyManagedHooks(projectRoot);
|
|
358
|
+
const omp = wantsOmp
|
|
359
|
+
? installOmpAgents(templateRoot, options.ompHome)
|
|
360
|
+
: { dest: null, agents: [], skipped: null };
|
|
308
361
|
return {
|
|
309
362
|
ok: true,
|
|
310
363
|
message: `SuperSpec ${SUPERSPEC_VERSION} 已安装`,
|
|
311
364
|
installed: {
|
|
312
365
|
engine_dir: ".superspec/",
|
|
366
|
+
hosts,
|
|
313
367
|
skills: copySkills(templateRoot, projectRoot),
|
|
314
|
-
prompts: copyPrompts(templateRoot, projectRoot),
|
|
315
|
-
agents: copyAgents(templateRoot, projectRoot),
|
|
316
|
-
|
|
317
|
-
|
|
368
|
+
prompts: wantsCodex ? copyPrompts(templateRoot, projectRoot) : [],
|
|
369
|
+
agents: wantsCodex ? copyAgents(templateRoot, projectRoot) : [],
|
|
370
|
+
omp,
|
|
371
|
+
config: wantsCodex ? ensureCodexConfig(projectRoot) : "",
|
|
372
|
+
workflow_config: persistWorkflowHosts(projectRoot, hosts),
|
|
318
373
|
agents_md: ensureAgentsMd(projectRoot, agentsMdTemplate),
|
|
319
374
|
openspec_config: ensureOpenSpecChineseContext(projectRoot),
|
|
320
375
|
},
|
package/dist/record.js
CHANGED
|
@@ -16,7 +16,7 @@ import { currentProposeOpenQuestion, currentProposeQuestionContent, currentPropo
|
|
|
16
16
|
import { discoveryOpenQuestionDisplayText, discoveryQuestionContextFingerprint, discoveryQuestionDecisionBasisDigest, discoveryOpenQuestionScope, legacyDiscoveryOpenQuestionScope, EXPLORE_OPEN_QUESTION_SCOPE_PREFIX, parseDiscoveryOpenQuestions, proposeOpenQuestionDisplayText, proposeOpenQuestionScope, proposeQuestionContextFingerprint, proposeQuestionDecisionBasisDigest, legacyProposeOpenQuestionScope, PROPOSE_OPEN_QUESTION_SCOPE_PREFIX, } from "./format.js";
|
|
17
17
|
const REVIEW_REPORT_REQUIRED_FIELDS = ["role", "verdict", "findings"];
|
|
18
18
|
const REVIEW_REPORT_OPTIONAL_FIELDS = ["summary", "evidence_refs", "risks", "open_questions"];
|
|
19
|
-
const REVIEWER_KINDS = new Set(["codex-subagent", "human", "external-agent"]);
|
|
19
|
+
const REVIEWER_KINDS = new Set(["subagent", "codex-subagent", "human", "external-agent"]);
|
|
20
20
|
const CODE_REVIEW_FINDING_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/;
|
|
21
21
|
function isReviewRole(role) {
|
|
22
22
|
return role === "critic" || role === "architect" || role === "test-engineer" || role === "code-reviewer" || role === "verifier";
|
|
@@ -1234,7 +1234,7 @@ export function jobsPacket(projectRoot, change, jobId) {
|
|
|
1234
1234
|
(requiresReviewer(job.role) ? `必须由独立 ${recommendedAgentForRole(job.role)} 审查角色执行,并在审查者来源字段(reviewer.kind/id)中记录来源,` : "") +
|
|
1235
1235
|
`产出 JSON 报告内容并优先通过 --report - 从 stdin 登记;文件路径模式仅作备用。${recordInputInstruction(job)}协议字段含义见 packet 顶层“字段说明”,普通对话不要原样复述 JSON。` +
|
|
1236
1236
|
(isCodeReviewer
|
|
1237
|
-
? `格式骨架:{"role":"code-reviewer","verdict":"pass","review_scope":{"job_id":"${job.job_id}","packet_digest":"${job.packet_digest}","checked_paths":[],"checked_docs":[],"unchecked":[]},"findings":[],"reviewer":{"kind":"
|
|
1237
|
+
? `格式骨架:{"role":"code-reviewer","verdict":"pass","review_scope":{"job_id":"${job.job_id}","packet_digest":"${job.packet_digest}","checked_paths":[],"checked_docs":[],"unchecked":[]},"findings":[],"reviewer":{"kind":"subagent","id":"<thread-or-agent-id>"}}。提交前按真实审查结果填写数组;不得从 boundFiles 自动复制 checked_paths。verdict 只能为 pass 或 fail;审查覆盖范围(review_scope)用来说明本次审查覆盖了哪些文件和文档,已检查路径(checked_paths)与未检查项(unchecked)必须合起来覆盖全部绑定文件(boundFiles),unchecked 条目格式为 {"path":"<path>","reason":"<reason>"};pass 不允许仍有未检查的绑定文件。`
|
|
1238
1238
|
+ `报告结论为 fail 时,问题列表(findings)至少包含一个可处理、可追溯的阻塞问题,字段为 {"id":"<stable-id>","blocking":true,"type":"implementation|spec|mixed","description":"<what>","evidence":"<why>","source_refs":["<path:line>"],"impact":"<impact>","suggested_action":"apply|propose"}。问题类型(type)中 implementation 表示纯代码实现问题,spec 表示方案/需求文档问题,mixed 表示需要使用者判断的混合问题。`
|
|
1239
1239
|
+ (packetContext?.task_execution_index
|
|
1240
1240
|
? `本工作项带任务执行索引(task_execution_index):按 task 对照其执行依据快照(contract)审查——实现路线对照 design 引用原文、累计 diff 对照 guard 边界、测试断言对照 tests 声明的 scenario;每项的 required_evidence 是 task-start 冻结的证据口径,red_required/green_required 分别说明是否需要 RED/GREEN;fix 非空表示状态机创建的实现修复,source、parent_task_id 和 reason 说明其归属,code_review 来源还需核对 review_finding;scope_note 既可能解释必要的范围扩大,也可能说明代码审查修复为何保留原实现,均需结合 Diff、调用链和验证证据独立判断;changed_paths 是归属线索不是结论(null 表示未知);unattributed_paths 中的无主改动逐个判断合理性;coverage_exemption_refs 解释未绑定 task 的 TEST 豁免。当前 packet 的 boundFiles 是本轮冻结的审查范围;若它来自前一轮审查后的增量,只复核本轮变化及其直接影响链路,不要求重复审查未变化文件,但仍要判断批准行为是否完整闭合。`
|
|
@@ -1245,7 +1245,7 @@ export function jobsPacket(projectRoot, change, jobId) {
|
|
|
1245
1245
|
? `本工作项带代码状态检查(code_state_check),它是创建 packet 时的快照:验证期间若代码状态已变化,不要提交该报告;主流程会通过 next 创建携带最新事实的验证工作项。`
|
|
1246
1246
|
: "")
|
|
1247
1247
|
: isReviewer
|
|
1248
|
-
? `最小格式:{"role":"${job.role}","verdict":"pass","findings":[]${hasReviewScope ? `,"review_scope":{"checked_paths":${JSON.stringify(job.boundFiles.map(file => file.path))}}` : ""},"reviewer":{"kind":"
|
|
1248
|
+
? `最小格式:{"role":"${job.role}","verdict":"pass","findings":[]${hasReviewScope ? `,"review_scope":{"checked_paths":${JSON.stringify(job.boundFiles.map(file => file.path))}}` : ""},"reviewer":{"kind":"subagent","id":"<thread-or-agent-id>"}}。verdict 只能为 pass 或 fail。`
|
|
1249
1249
|
: `最小格式:{"role":"${job.role}","verdict":"pass","findings":[]}。verdict 只能为 pass 或 fail。`),
|
|
1250
1250
|
stop_conditions: isReviewer
|
|
1251
1251
|
? ["完成审查后提交报告,不要修改文档"]
|
package/dist/transition.js
CHANGED
|
@@ -1016,6 +1016,24 @@ function applyPlanningMaterialsChanged(changeRoot, events) {
|
|
|
1016
1016
|
const baseline = latestApplyPlanningBaseline(events);
|
|
1017
1017
|
return baseline != null && applyPlanningDocsChangedSinceBaseline(changeRoot, baseline);
|
|
1018
1018
|
}
|
|
1019
|
+
/**
|
|
1020
|
+
* self-test-fix 由使用者明确指定已完成的父 task;它可以修复早于当前
|
|
1021
|
+
* Apply round 的实现问题。普通 Apply 仍只消费当前轮完成事件,这个查询
|
|
1022
|
+
* 只用于自测修复的人工关联,不改变任务完成判定。
|
|
1023
|
+
*/
|
|
1024
|
+
function hasHistoricalTaskCompletion(events, taskId) {
|
|
1025
|
+
return events.some(event => {
|
|
1026
|
+
if (event.event_type !== "task_completed")
|
|
1027
|
+
return false;
|
|
1028
|
+
const payload = event.payload;
|
|
1029
|
+
if (payload.task_id !== taskId || typeof payload.attempt_id !== "string")
|
|
1030
|
+
return false;
|
|
1031
|
+
const checkboxUpdate = payload.checkbox_update;
|
|
1032
|
+
if (!checkboxUpdate || typeof checkboxUpdate !== "object" || Array.isArray(checkboxUpdate))
|
|
1033
|
+
return true;
|
|
1034
|
+
return checkboxUpdate.status !== "failed";
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1019
1037
|
function proposalReopenBaseline(changeRoot, events, source) {
|
|
1020
1038
|
const applyBaseline = ["apply", "apply_done", "review"].includes(source)
|
|
1021
1039
|
? latestApplyPlanningBaseline(events)
|
|
@@ -1154,7 +1172,9 @@ export function reopen(projectRoot, change, changeRoot, to, reason, opts = {}) {
|
|
|
1154
1172
|
if (pendingStatus.pending.length > 0 || snapshot.active_task_attempts.some(attempt => attempt.state === "active")) {
|
|
1155
1173
|
return { skip: true, message: "自测修复只允许在当前 task 全部完成且没有活跃执行尝试后创建" };
|
|
1156
1174
|
}
|
|
1157
|
-
if (pendingStatus.mode === "contract" &&
|
|
1175
|
+
if (pendingStatus.mode === "contract" &&
|
|
1176
|
+
!pendingStatus.completedByEvent.includes(parentTaskId) &&
|
|
1177
|
+
!hasHistoricalTaskCompletion(events, parentTaskId)) {
|
|
1158
1178
|
return { skip: true, message: `自测修复关联的 task ${parentTaskId} 缺少完成事件,不能只依赖 checkbox` };
|
|
1159
1179
|
}
|
|
1160
1180
|
if (pendingStatus.mode === "legacy" && !parentTask.done) {
|
|
@@ -3,9 +3,19 @@ import type { Event, State } from "./types.ts";
|
|
|
3
3
|
export declare const WORKFLOW_CONFIG_PATH = ".superspec/config.json";
|
|
4
4
|
/** 项目未声明 workflow.mode 时采用的默认档位。 */
|
|
5
5
|
export declare const DEFAULT_WORKFLOW_RISK: ReviewRisk;
|
|
6
|
+
export declare const WORKFLOW_HOSTS: readonly ["codex", "omp"];
|
|
7
|
+
export type WorkflowHost = (typeof WORKFLOW_HOSTS)[number];
|
|
8
|
+
/** 未声明 hosts 的旧项目按 Codex 入口处理。 */
|
|
9
|
+
export declare const DEFAULT_WORKFLOW_HOSTS: WorkflowHost[];
|
|
6
10
|
export declare class WorkflowConfigError extends Error {
|
|
7
11
|
constructor(message: string);
|
|
8
12
|
}
|
|
13
|
+
export declare function normalizeWorkflowHosts(values: readonly string[]): WorkflowHost[];
|
|
14
|
+
export declare function parseWorkflowHostsFlag(raw: string): WorkflowHost[];
|
|
15
|
+
/** 读取项目已选宿主。缺少配置或缺少 workflow.hosts 时默认 Codex。 */
|
|
16
|
+
export declare function workflowHostsForProject(projectRoot: string): WorkflowHost[];
|
|
17
|
+
export declare function persistWorkflowHosts(projectRoot: string, hosts: WorkflowHost[]): string;
|
|
18
|
+
export declare function workflowHostsDeclared(projectRoot: string): boolean;
|
|
9
19
|
/**
|
|
10
20
|
* Propose-ready 是一个 planning round 的冻结点。配置只影响尚未冻结的计划;
|
|
11
21
|
* 已就绪计划必须沿用当时的 mode,直到 reopen 回到 propose 后创建新 round。
|
package/dist/workflow_config.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
// SuperSpec 项目级工作流配置。所有阶段从同一位置解析默认 mode,
|
|
2
2
|
// 避免 CLI、Explore、Propose、Review 各自保留不同默认值。
|
|
3
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
-
import { join } from "node:path";
|
|
3
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
5
|
export const WORKFLOW_CONFIG_PATH = ".superspec/config.json";
|
|
6
6
|
/** 项目未声明 workflow.mode 时采用的默认档位。 */
|
|
7
7
|
export const DEFAULT_WORKFLOW_RISK = "normal";
|
|
8
|
+
export const WORKFLOW_HOSTS = ["codex", "omp"];
|
|
9
|
+
/** 未声明 hosts 的旧项目按 Codex 入口处理。 */
|
|
10
|
+
export const DEFAULT_WORKFLOW_HOSTS = ["codex"];
|
|
8
11
|
export class WorkflowConfigError extends Error {
|
|
9
12
|
constructor(message) {
|
|
10
13
|
super(message);
|
|
@@ -14,6 +17,77 @@ export class WorkflowConfigError extends Error {
|
|
|
14
17
|
function isReviewRisk(value) {
|
|
15
18
|
return value === "minimal" || value === "normal" || value === "strict";
|
|
16
19
|
}
|
|
20
|
+
function isWorkflowHost(value) {
|
|
21
|
+
return value === "codex" || value === "omp";
|
|
22
|
+
}
|
|
23
|
+
export function normalizeWorkflowHosts(values) {
|
|
24
|
+
const hosts = [...new Set(values.filter(isWorkflowHost))];
|
|
25
|
+
hosts.sort((left, right) => WORKFLOW_HOSTS.indexOf(left) - WORKFLOW_HOSTS.indexOf(right));
|
|
26
|
+
return hosts;
|
|
27
|
+
}
|
|
28
|
+
export function parseWorkflowHostsFlag(raw) {
|
|
29
|
+
const hosts = normalizeWorkflowHosts(raw.split(/[,\s]+/).filter(Boolean));
|
|
30
|
+
if (hosts.length === 0) {
|
|
31
|
+
throw new WorkflowConfigError(`hosts 只能是 ${WORKFLOW_HOSTS.join("、")},至少选一个`);
|
|
32
|
+
}
|
|
33
|
+
return hosts;
|
|
34
|
+
}
|
|
35
|
+
function readWorkflowConfigObject(projectRoot) {
|
|
36
|
+
const configPath = join(projectRoot, WORKFLOW_CONFIG_PATH);
|
|
37
|
+
if (!existsSync(configPath))
|
|
38
|
+
return null;
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(readFileSync(configPath, "utf8"));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new WorkflowConfigError(`${WORKFLOW_CONFIG_PATH} 必须是有效 JSON`);
|
|
45
|
+
}
|
|
46
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
47
|
+
throw new WorkflowConfigError(`${WORKFLOW_CONFIG_PATH} 顶层必须是 JSON object`);
|
|
48
|
+
}
|
|
49
|
+
return parsed;
|
|
50
|
+
}
|
|
51
|
+
function workflowObject(parsed) {
|
|
52
|
+
if (!parsed || parsed.workflow === undefined)
|
|
53
|
+
return undefined;
|
|
54
|
+
if (parsed.workflow === null || typeof parsed.workflow !== "object" || Array.isArray(parsed.workflow)) {
|
|
55
|
+
throw new WorkflowConfigError(`${WORKFLOW_CONFIG_PATH} 的 workflow 必须是 object`);
|
|
56
|
+
}
|
|
57
|
+
return parsed.workflow;
|
|
58
|
+
}
|
|
59
|
+
function hostsFromWorkflow(workflow) {
|
|
60
|
+
if (!workflow || workflow.hosts === undefined)
|
|
61
|
+
return DEFAULT_WORKFLOW_HOSTS;
|
|
62
|
+
if (!Array.isArray(workflow.hosts)) {
|
|
63
|
+
throw new WorkflowConfigError(`${WORKFLOW_CONFIG_PATH} 的 workflow.hosts 必须是字符串数组`);
|
|
64
|
+
}
|
|
65
|
+
const hosts = normalizeWorkflowHosts(workflow.hosts.filter((item) => typeof item === "string"));
|
|
66
|
+
if (hosts.length === 0) {
|
|
67
|
+
throw new WorkflowConfigError(`${WORKFLOW_CONFIG_PATH} 的 workflow.hosts 只能包含 ${WORKFLOW_HOSTS.join("、")},至少一项`);
|
|
68
|
+
}
|
|
69
|
+
return hosts;
|
|
70
|
+
}
|
|
71
|
+
/** 读取项目已选宿主。缺少配置或缺少 workflow.hosts 时默认 Codex。 */
|
|
72
|
+
export function workflowHostsForProject(projectRoot) {
|
|
73
|
+
return hostsFromWorkflow(workflowObject(readWorkflowConfigObject(projectRoot)));
|
|
74
|
+
}
|
|
75
|
+
export function persistWorkflowHosts(projectRoot, hosts) {
|
|
76
|
+
const configPath = join(projectRoot, WORKFLOW_CONFIG_PATH);
|
|
77
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
78
|
+
const parsed = readWorkflowConfigObject(projectRoot) ?? {};
|
|
79
|
+
const workflow = workflowObject(parsed) ?? {};
|
|
80
|
+
if (workflow.mode === undefined)
|
|
81
|
+
workflow.mode = DEFAULT_WORKFLOW_RISK;
|
|
82
|
+
workflow.hosts = normalizeWorkflowHosts(hosts);
|
|
83
|
+
parsed.workflow = workflow;
|
|
84
|
+
writeFileSync(configPath, `${JSON.stringify(parsed, null, 2)}\n`);
|
|
85
|
+
return WORKFLOW_CONFIG_PATH;
|
|
86
|
+
}
|
|
87
|
+
export function workflowHostsDeclared(projectRoot) {
|
|
88
|
+
const workflow = workflowObject(readWorkflowConfigObject(projectRoot));
|
|
89
|
+
return workflow !== undefined && workflow.hosts !== undefined;
|
|
90
|
+
}
|
|
17
91
|
function workflowModeFromPayload(payload) {
|
|
18
92
|
return isReviewRisk(payload.workflow_mode) ? payload.workflow_mode : null;
|
|
19
93
|
}
|
|
@@ -96,25 +170,9 @@ export function workflowRiskForState(events, state, fallback) {
|
|
|
96
170
|
* 配置格式:{ "workflow": { "mode": "normal" } }
|
|
97
171
|
*/
|
|
98
172
|
export function workflowRiskForProject(projectRoot) {
|
|
99
|
-
const
|
|
100
|
-
if (!
|
|
101
|
-
return DEFAULT_WORKFLOW_RISK;
|
|
102
|
-
let parsed;
|
|
103
|
-
try {
|
|
104
|
-
parsed = JSON.parse(readFileSync(configPath, "utf8"));
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
throw new WorkflowConfigError(`${WORKFLOW_CONFIG_PATH} 必须是有效 JSON`);
|
|
108
|
-
}
|
|
109
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
110
|
-
throw new WorkflowConfigError(`${WORKFLOW_CONFIG_PATH} 顶层必须是 JSON object`);
|
|
111
|
-
}
|
|
112
|
-
const workflow = parsed.workflow;
|
|
113
|
-
if (workflow === undefined)
|
|
173
|
+
const workflow = workflowObject(readWorkflowConfigObject(projectRoot));
|
|
174
|
+
if (!workflow)
|
|
114
175
|
return DEFAULT_WORKFLOW_RISK;
|
|
115
|
-
if (!workflow || typeof workflow !== "object" || Array.isArray(workflow)) {
|
|
116
|
-
throw new WorkflowConfigError(`${WORKFLOW_CONFIG_PATH} 的 workflow 必须是 object`);
|
|
117
|
-
}
|
|
118
176
|
const mode = workflow.mode;
|
|
119
177
|
if (mode === undefined)
|
|
120
178
|
return DEFAULT_WORKFLOW_RISK;
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
工作流要求用户决定时,只能登记当前对话中用户针对当前问题作出的明确答复。启动工作流、要求推进到某阶段、允许自动执行或表达一般偏好,不等于回答后续具体业务问题或阶段确认;主流程、Skill、subagent 和审查角色都不得根据目标、建议、历史偏好或推断代替用户作答。答复与当前问题不对应或仍有实质歧义时,保持待确认,不得登记为用户决定。
|
|
11
11
|
|
|
12
|
-
当用户显式调用
|
|
12
|
+
当用户显式调用 `superspec-explore`,或明确要求继续处于 Explore 的已有 change 时,视为已明确授权启动 `explore` subagent 做只读深扫;其他 `superspec-*` 阶段仅在工作流引擎创建独立工作项时,视为授权启动对应 subagent。
|
|
13
13
|
|
|
14
14
|
Explore 中需要用户决定业务、验收、范围或关键取舍时,先简要说明当前理解、影响和建议,再一次只请用户决定一件事;收到明确答复后,更新相关 discovery 结论,再继续工作流。其他阶段要求用户确认、选择处理方向或补齐材料时,按当前工作流返回的要求登记结论或更新相应材料;不得把这类答复默认写入 discovery。
|
|
15
15
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architect
|
|
3
|
+
description: System design, boundaries, interfaces, long-horizon tradeoffs
|
|
4
|
+
tools: read, grep, glob, bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Role: Architect. Review system boundaries, interface contracts, data flow, maintenance risk, rollback risk, and design tradeoffs.
|
|
8
|
+
|
|
9
|
+
Task binding: read the current SuperSpec job packet and task instructions first. The job packet is the runtime contract; follow it over this prompt, including any previous rejection it asks you to correct.
|
|
10
|
+
|
|
11
|
+
Boundary: read-only. Do not edit files or judge materials you have not opened. Report missing context upward instead of guessing.
|
|
12
|
+
|
|
13
|
+
Output: concise Simplified Chinese. For JSON reports, follow the packet's report contract exactly. Otherwise put the conclusion first, cite file:line evidence, and write `无阻塞问题` when no blocking issue is found.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-reviewer
|
|
3
|
+
description: Code-level review for spec fit, bugs, safety, and test gaps
|
|
4
|
+
tools: read, grep, glob, bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Role: Code Reviewer. Check spec fit, correctness, security, test adequacy, code quality, performance, and maintainability without making the workflow heavy.
|
|
8
|
+
|
|
9
|
+
Task binding: read the current SuperSpec job packet and task instructions first. The job packet is the runtime contract; follow it over this prompt, including any previous rejection it asks you to correct.
|
|
10
|
+
|
|
11
|
+
Boundary: read-only. Do not implement fixes, write evidence, mark tasks complete, decide GREEN, reopen, accept, or replace main-thread workflow decisions. Start from packet-provided materials and report missing context upward instead of guessing.
|
|
12
|
+
|
|
13
|
+
Output: concise Simplified Chinese. For JSON reports, follow the packet's report contract exactly. Blocking issues must be traceable and actionable. Write `无阻塞问题` when no blocking issue is found.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: critic
|
|
3
|
+
description: Plan/design critical challenge and review
|
|
4
|
+
tools: read, grep, glob, bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Role: Critic. Challenge demand clarification, plans, designs, implementations, and verification claims with source-backed skepticism.
|
|
8
|
+
|
|
9
|
+
Task binding: read the current SuperSpec job packet and task instructions first. The job packet is the runtime contract; follow it over this prompt, including any previous rejection it asks you to correct.
|
|
10
|
+
|
|
11
|
+
Boundary: read-only by default. Do not edit files, invent issues, or widen scope silently. Report missing source refs or claim gaps upward.
|
|
12
|
+
|
|
13
|
+
Output: concise Simplified Chinese. For JSON reports, follow the packet's report contract exactly. Otherwise state pass or reject first, distinguish defects from proof gaps and residual risk, and cite concrete evidence.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: executor
|
|
3
|
+
description: Bounded SuperSpec apply implementation worker
|
|
4
|
+
tools: read, grep, glob, bash, edit, write
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Role: Executor. Implement exactly one SuperSpec apply task from the current task instructions.
|
|
8
|
+
|
|
9
|
+
Task binding: read the current SuperSpec task instructions first. Their task id, declared write scope, guard fingerprint, worker chain id, stop conditions, and report policy override this prompt.
|
|
10
|
+
|
|
11
|
+
Boundary: mutating but bounded. Edit only paths listed in `declared_task_write_scope`; do not edit OpenSpec artifacts, `.superspec/**`, task checkboxes, evidence, review reports, or archives. Stop and report blockers when scope or context is insufficient.
|
|
12
|
+
|
|
13
|
+
Output: concise Simplified Chinese implementation report with changed files, task/test mapping, suggested GREEN checks, artifact refs, and residual risk.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: explore
|
|
3
|
+
description: Repo-local read-only factual scan for SuperSpec discovery
|
|
4
|
+
tools: read, grep, glob, bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Role: Explore. Map repo-local implementation facts, source anchors, hidden contracts, and missing discovery coverage.
|
|
8
|
+
|
|
9
|
+
Task binding: read the current SuperSpec task instructions first. Their refs and stop conditions override this prompt.
|
|
10
|
+
|
|
11
|
+
Boundary: read-only. Do not edit files, write OpenSpec/SuperSpec artifacts, create evidence, approve scope, or replace main-thread workflow decisions. Strict explore review belongs to `critic`; report findings upward with concrete anchors.
|
|
12
|
+
|
|
13
|
+
Output: concise Simplified Chinese. Summarize relevant source facts, cite short anchors like ClassName.java:123 or file.ts:45 instead of absolute or long project-relative paths, and call out unknowns or missing refs.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-engineer
|
|
3
|
+
description: Test strategy, coverage, flaky-test hardening
|
|
4
|
+
tools: read, grep, glob, bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Role: Test Engineer. Review test strategy, coverage, RED/GREEN credibility, flaky-test risk, and acceptance mapping.
|
|
8
|
+
|
|
9
|
+
Task binding: read the current SuperSpec job packet and task instructions first. The job packet is the runtime contract; follow it over this prompt, including any previous rejection it asks you to correct.
|
|
10
|
+
|
|
11
|
+
Boundary: review jobs are read-only. In ordinary testing tasks, write tests only and report implementation needs upward.
|
|
12
|
+
|
|
13
|
+
Output: concise Simplified Chinese. For JSON reports, follow the packet's report contract exactly. Otherwise list coverage gaps, suggested tests, fresh validation commands, unverifiable items, and residual risk.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-runner
|
|
3
|
+
description: Bounded SuperSpec apply test execution worker
|
|
4
|
+
tools: read, grep, glob, bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Role: Test Runner. Execute exactly one SuperSpec apply test phase from the current task instructions and report an evidence candidate.
|
|
8
|
+
|
|
9
|
+
Task binding: read the current SuperSpec task instructions first. Their task id, test id, phase, allowed command, expected semantic status, guard fingerprint, report policy, and stop conditions override this prompt.
|
|
10
|
+
|
|
11
|
+
Boundary: read-only by default. Do not edit production code, OpenSpec artifacts, `.superspec/**`, task checkboxes, evidence, review reports, or archives. Run only the allowed command from current task instructions and report blockers for missing command, unsafe side effects, or incomplete raw transcript refs.
|
|
12
|
+
|
|
13
|
+
Output: concise Simplified Chinese test report with command, cwd, phase, task/test id, exit status, semantic status candidate, result summary, raw transcript ref, repo head, dirty-state summary, guard fingerprint, and unverified items.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: verifier
|
|
3
|
+
description: Completion evidence, claim validation, test adequacy
|
|
4
|
+
tools: read, grep, glob, bash
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Role: Verifier. Prove or disprove completion claims with reproducible evidence; missing evidence is not a pass.
|
|
8
|
+
|
|
9
|
+
Task binding: read the current SuperSpec job packet and task instructions first. The job packet is the runtime contract; follow it over this prompt, including any previous rejection it asks you to correct.
|
|
10
|
+
|
|
11
|
+
Boundary: read-only. Check commands, test output, artifacts, evidence refs, acceptance criteria, code-reviewer closure, and whether the verifier job still matches the packet-provided evidence version. Use diffs only as evidence references when the packet requires them. Do not edit files, write evidence, mark tasks complete, or add an extra code-diff blocker outside the packet contract.
|
|
12
|
+
|
|
13
|
+
Output: concise Simplified Chinese. For JSON reports, follow the packet's report contract exactly. For other verification paths, state pass, fail, partial, or evidence gap first; list evidence, gaps, residual risk, and stop conditions.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: superspec-apply
|
|
3
|
-
description: "仅在用户显式调用
|
|
3
|
+
description: "仅在用户显式调用 superspec-apply 入口,或明确要求继续某个 SuperSpec change 的 Apply 阶段时使用;普通开发、修复或测试请求不得自动触发。"
|
|
4
4
|
metadata:
|
|
5
5
|
author: SuperSpec
|
|
6
6
|
source: SuperSpec
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: superspec-explore
|
|
3
|
-
description: "仅在用户显式调用
|
|
3
|
+
description: "仅在用户显式调用 superspec-explore 入口,或明确要求继续某个 SuperSpec change 的 Explore 阶段时使用;普通分析、排查或修复请求不得自动触发。"
|
|
4
4
|
metadata:
|
|
5
5
|
author: SuperSpec
|
|
6
6
|
source: SuperSpec
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: superspec-propose
|
|
3
|
-
description: "仅在用户显式调用
|
|
3
|
+
description: "仅在用户显式调用 superspec-propose 入口,或明确要求继续某个 SuperSpec change 的 Propose 阶段时使用;普通需求讨论、方案或设计请求不得自动触发。"
|
|
4
4
|
metadata:
|
|
5
5
|
author: SuperSpec
|
|
6
6
|
source: SuperSpec
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: superspec-review
|
|
3
|
-
description: "仅在用户显式调用
|
|
3
|
+
description: "仅在用户显式调用 superspec-review 入口,或明确要求继续某个 SuperSpec change 的 Review 阶段时使用;普通代码审查、验证或修复请求不得自动触发。"
|
|
4
4
|
metadata:
|
|
5
5
|
author: SuperSpec
|
|
6
6
|
source: SuperSpec
|