@peterxiaoyang/superspec 0.1.2 → 0.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 +181 -116
- package/dist/src/cli.js +2 -2
- package/dist/src/cli_args.d.ts +2 -0
- package/dist/src/cli_args.js +28 -10
- package/dist/src/core.js +5 -5
- package/dist/src/doctor.d.ts +44 -0
- package/dist/src/doctor.js +230 -0
- package/dist/src/evidence.d.ts +1 -0
- package/dist/src/evidence.js +7 -0
- package/dist/src/gates.d.ts +1 -0
- package/dist/src/gates.js +39 -10
- package/dist/src/git.js +2 -2
- package/dist/src/init_cli.d.ts +2 -1
- package/dist/src/init_cli.js +31 -17
- package/dist/src/self_update.d.ts +14 -0
- package/dist/src/self_update.js +56 -0
- package/dist/src/util.d.ts +11 -0
- package/dist/src/util.js +218 -2
- package/dist/superspec.d.ts +2 -0
- package/dist/superspec.js +45 -5
- package/package.json +2 -2
- package/templates/workflow/skills/superspec-apply/SKILL.md +16 -6
- package/templates/workflow/skills/superspec-archive/SKILL.md +10 -2
- package/templates/workflow/skills/superspec-explore/SKILL.md +15 -4
- package/templates/workflow/skills/superspec-propose/SKILL.md +19 -9
- package/templates/workflow/skills/superspec-review/SKILL.md +15 -5
package/dist/src/util.d.ts
CHANGED
|
@@ -39,6 +39,8 @@ export type Decision = {
|
|
|
39
39
|
trust_warnings_zh?: string[];
|
|
40
40
|
workflow_terms_zh?: WorkflowTermHint[];
|
|
41
41
|
};
|
|
42
|
+
export type DecisionOutputFormat = "json" | "agent" | "user";
|
|
43
|
+
export type AgentWorkflowAction = "continue" | "fix_artifacts" | "ask_user_confirmation" | "collect_review_evidence" | "collect_test_evidence" | "repair_evidence" | "rerun_check" | "inspect_diagnostics";
|
|
42
44
|
export type TaskInfo = {
|
|
43
45
|
task_id: string;
|
|
44
46
|
checked: boolean;
|
|
@@ -82,6 +84,7 @@ export declare const GATE_ROUTE: Record<string, string>;
|
|
|
82
84
|
export declare class GuardError extends Error {
|
|
83
85
|
}
|
|
84
86
|
export declare const runtime: JsonMap;
|
|
87
|
+
export declare function parseDecisionOutputFormat(raw: string): DecisionOutputFormat;
|
|
85
88
|
export declare function reason(code: string, message: string, refs?: string[] | null): Reason;
|
|
86
89
|
export declare function pinned_ref_key(item: JsonMap): string;
|
|
87
90
|
export declare function trustWarnings(): string[];
|
|
@@ -99,8 +102,16 @@ export declare function block(change: string, gate: string, reasons: Reason[], o
|
|
|
99
102
|
export declare function decorateDecision(decision: JsonMap, opts?: {
|
|
100
103
|
command?: string;
|
|
101
104
|
}): JsonMap;
|
|
105
|
+
export declare function workflowActionForReasonCodes(reasonCodes: string[], allowed?: boolean): AgentWorkflowAction;
|
|
106
|
+
export declare function renderAgentDecision(decision: JsonMap, opts?: {
|
|
107
|
+
command?: string;
|
|
108
|
+
}): JsonMap;
|
|
109
|
+
export declare function renderUserFacingDecision(decision: JsonMap, opts?: {
|
|
110
|
+
command?: string;
|
|
111
|
+
}): string;
|
|
102
112
|
export declare function printDecision(decision: JsonMap, opts?: {
|
|
103
113
|
command?: string;
|
|
114
|
+
format?: DecisionOutputFormat;
|
|
104
115
|
}): void;
|
|
105
116
|
export declare function runCommand(cmd: string, args: string[], opts?: {
|
|
106
117
|
cwd?: string;
|
package/dist/src/util.js
CHANGED
|
@@ -78,6 +78,7 @@ export const EVIDENCE_KINDS = new Set([
|
|
|
78
78
|
// FIX-8 (audit A-5) adds the previously anchor-less human pause points:
|
|
79
79
|
// apply isolation choice, apply-phase scope expansion, and verify-failure disposition.
|
|
80
80
|
export const HUMAN_CONFIRMATION_GATES = new Set([
|
|
81
|
+
"explore_complete",
|
|
81
82
|
"design_complete",
|
|
82
83
|
"invariants_reviewed",
|
|
83
84
|
"archive_ready",
|
|
@@ -215,8 +216,8 @@ export const GATE_ALIASES = {
|
|
|
215
216
|
"propose.invariants_reviewed": "invariants_reviewed",
|
|
216
217
|
"propose.test_plan_drafted": "test_contract_drafted",
|
|
217
218
|
"propose.tasks_mapped": "tasks_complete",
|
|
218
|
-
"propose.apply_ready": "
|
|
219
|
-
apply_ready: "
|
|
219
|
+
"propose.apply_ready": "apply_ready",
|
|
220
|
+
apply_ready: "apply_ready",
|
|
220
221
|
};
|
|
221
222
|
export const GATE_ROUTE = {
|
|
222
223
|
explore_complete: "explore",
|
|
@@ -227,6 +228,7 @@ export const GATE_ROUTE = {
|
|
|
227
228
|
test_contract_honored: "propose",
|
|
228
229
|
tasks_complete: "propose",
|
|
229
230
|
propose_complete: "propose",
|
|
231
|
+
apply_ready: "propose",
|
|
230
232
|
review_complete: "review",
|
|
231
233
|
verify_complete: "review",
|
|
232
234
|
archive_ready: "archive",
|
|
@@ -234,6 +236,11 @@ export const GATE_ROUTE = {
|
|
|
234
236
|
export class GuardError extends Error {
|
|
235
237
|
}
|
|
236
238
|
export const runtime = {};
|
|
239
|
+
export function parseDecisionOutputFormat(raw) {
|
|
240
|
+
if (raw === "json" || raw === "agent" || raw === "user")
|
|
241
|
+
return raw;
|
|
242
|
+
throw new GuardError("--format 只允许 json、agent 或 user");
|
|
243
|
+
}
|
|
237
244
|
export function reason(code, message, refs = null) {
|
|
238
245
|
const zh = reason_zh(code);
|
|
239
246
|
return { code, message, refs: refs ?? [], label_zh: zh.label_zh, hint_zh: zh.hint_zh };
|
|
@@ -368,8 +375,217 @@ function sanitizeDecisionForOutput(decision) {
|
|
|
368
375
|
actions,
|
|
369
376
|
};
|
|
370
377
|
}
|
|
378
|
+
function userFacingLine(value) {
|
|
379
|
+
return String(value ?? "").replace(/\s+/gu, " ").trim();
|
|
380
|
+
}
|
|
381
|
+
const SAFE_TEXT_REPLACEMENTS = [
|
|
382
|
+
[/\bneeds_user_decision_pending\b/giu, "等待用户确认"],
|
|
383
|
+
[/\bneeds_user_decision\b/giu, "等待用户确认"],
|
|
384
|
+
[/\buser_review_decision\b/giu, "用户确认记录"],
|
|
385
|
+
[/\bmain_review_digest\b/giu, "审查问题记录"],
|
|
386
|
+
[/\breview_standing_authorization\b/giu, "长期授权记录"],
|
|
387
|
+
[/\bdecision_scope_key\b/giu, "确认范围"],
|
|
388
|
+
[/\bfinding_uid\b/giu, "问题标识"],
|
|
389
|
+
[/\bexport\s+function\s+[A-Za-z_$][\w$]*\s*\([^)]*\)/gu, "内部实现细节"],
|
|
390
|
+
[/\bfunction\s+[A-Za-z_$][\w$]*\s*\([^)]*\)/gu, "内部实现细节"],
|
|
391
|
+
[/\b[A-Za-z_$][\w$]*\s*\([^)]*\)/gu, "内部调用细节"],
|
|
392
|
+
[/裁决/gu, "确认"],
|
|
393
|
+
];
|
|
394
|
+
function safeDisplayText(value) {
|
|
395
|
+
let out = userFacingLine(value);
|
|
396
|
+
for (const [pattern, replacement] of SAFE_TEXT_REPLACEMENTS)
|
|
397
|
+
out = out.replace(pattern, replacement);
|
|
398
|
+
return out;
|
|
399
|
+
}
|
|
400
|
+
function fallbackReasonForWorkflowAction(action) {
|
|
401
|
+
const fallbacks = {
|
|
402
|
+
continue: "当前检查已通过。",
|
|
403
|
+
ask_user_confirmation: "需要用户确认后才能继续。",
|
|
404
|
+
collect_review_evidence: "需要补齐审查或验证复核记录。",
|
|
405
|
+
collect_test_evidence: "需要补齐测试或校验证据。",
|
|
406
|
+
fix_artifacts: "需要修正方案、任务或证据结构。",
|
|
407
|
+
repair_evidence: "需要修复证据记录。",
|
|
408
|
+
rerun_check: "需要重新运行当前检查。",
|
|
409
|
+
inspect_diagnostics: "需要查看诊断输出后处理。",
|
|
410
|
+
};
|
|
411
|
+
return fallbacks[action];
|
|
412
|
+
}
|
|
413
|
+
function safeReasonText(_item, action = "inspect_diagnostics") {
|
|
414
|
+
return fallbackReasonForWorkflowAction(action);
|
|
415
|
+
}
|
|
416
|
+
const WORKFLOW_ACTION_BY_REASON = [
|
|
417
|
+
[new Set([
|
|
418
|
+
"needs_user_decision_pending",
|
|
419
|
+
"user_decision_unbound",
|
|
420
|
+
"missing_review_digest",
|
|
421
|
+
"missing_human_confirmation",
|
|
422
|
+
"apply_isolation_unconfirmed",
|
|
423
|
+
"scope_expansion_unconfirmed",
|
|
424
|
+
"finding_unresolved",
|
|
425
|
+
"round_budget_exhausted",
|
|
426
|
+
]), "ask_user_confirmation"],
|
|
427
|
+
[new Set([
|
|
428
|
+
"missing_source_guidance",
|
|
429
|
+
"missing_verification_review",
|
|
430
|
+
"missing_final_verification_review",
|
|
431
|
+
"missing_roles",
|
|
432
|
+
"missing_native_subagent_evidence",
|
|
433
|
+
"missing_invariant_review",
|
|
434
|
+
"missing_test_contract_review",
|
|
435
|
+
"missing_architect_review",
|
|
436
|
+
"missing_critic_review",
|
|
437
|
+
"missing_test-engineer_review",
|
|
438
|
+
"missing_code-reviewer_review",
|
|
439
|
+
"missing_verifier_review",
|
|
440
|
+
"missing_main_adjudication",
|
|
441
|
+
"proposal_reviewed_failed",
|
|
442
|
+
"review_not_ready",
|
|
443
|
+
"missing_proposal_review",
|
|
444
|
+
]), "collect_review_evidence"],
|
|
445
|
+
[new Set([
|
|
446
|
+
"missing_red_evidence",
|
|
447
|
+
"missing_green_evidence",
|
|
448
|
+
"missing_characterization",
|
|
449
|
+
"test_contract_not_honored",
|
|
450
|
+
"validate_failed",
|
|
451
|
+
"missing_final_tests",
|
|
452
|
+
"verify_failure_unconfirmed",
|
|
453
|
+
]), "collect_test_evidence"],
|
|
454
|
+
[new Set([
|
|
455
|
+
"missing_discovery",
|
|
456
|
+
"missing_proposal",
|
|
457
|
+
"missing_design",
|
|
458
|
+
"missing_tasks",
|
|
459
|
+
"invalid_task_graph",
|
|
460
|
+
"invalid_business_invariants",
|
|
461
|
+
"review_finding_invalid",
|
|
462
|
+
"review_digest_invalid",
|
|
463
|
+
"user_decision_invalid",
|
|
464
|
+
"human_confirmation_invalid",
|
|
465
|
+
"standing_authorization_invalid",
|
|
466
|
+
"evidence_unknown_kind",
|
|
467
|
+
"evidence_missing_field",
|
|
468
|
+
"artifact_update_required",
|
|
469
|
+
"rereview_required",
|
|
470
|
+
]), "fix_artifacts"],
|
|
471
|
+
[new Set([
|
|
472
|
+
"state_concurrent_update",
|
|
473
|
+
"state_fingerprint_stale",
|
|
474
|
+
]), "rerun_check"],
|
|
475
|
+
[new Set([
|
|
476
|
+
"state_corrupt",
|
|
477
|
+
"openspec_cli_unavailable",
|
|
478
|
+
"openspec_native_surface_missing",
|
|
479
|
+
"dirty_worktree_unavailable",
|
|
480
|
+
"guard_error",
|
|
481
|
+
"guard_internal_error",
|
|
482
|
+
"unknown_gate",
|
|
483
|
+
"unknown_artifact",
|
|
484
|
+
"not_openspec_artifact",
|
|
485
|
+
]), "inspect_diagnostics"],
|
|
486
|
+
];
|
|
487
|
+
export function workflowActionForReasonCodes(reasonCodes, allowed = false) {
|
|
488
|
+
if (allowed)
|
|
489
|
+
return "continue";
|
|
490
|
+
const codes = new Set(reasonCodes);
|
|
491
|
+
for (const [matches, action] of WORKFLOW_ACTION_BY_REASON) {
|
|
492
|
+
for (const code of matches) {
|
|
493
|
+
if (codes.has(code))
|
|
494
|
+
return action;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return "inspect_diagnostics";
|
|
498
|
+
}
|
|
499
|
+
function summaryForWorkflowAction(action, allowed) {
|
|
500
|
+
if (allowed || action === "continue")
|
|
501
|
+
return "当前检查已通过,可以继续下一步。";
|
|
502
|
+
const summaries = {
|
|
503
|
+
ask_user_confirmation: "当前阶段需要用户确认一个范围或处理方式选择后才能继续。",
|
|
504
|
+
collect_review_evidence: "当前阶段缺少必要审查或验证复核记录,补齐后再继续。",
|
|
505
|
+
collect_test_evidence: "当前阶段缺少测试或校验证据,补齐后再继续。",
|
|
506
|
+
fix_artifacts: "当前阶段的方案、任务或证据结构需要修正后再继续。",
|
|
507
|
+
repair_evidence: "当前证据记录需要修复后再继续。",
|
|
508
|
+
rerun_check: "当前检查需要在输入稳定后重新运行。",
|
|
509
|
+
inspect_diagnostics: "当前检查需要查看诊断输出后处理。",
|
|
510
|
+
};
|
|
511
|
+
return summaries[action];
|
|
512
|
+
}
|
|
513
|
+
function nextStepsForWorkflowAction(action, allowed) {
|
|
514
|
+
if (allowed || action === "continue")
|
|
515
|
+
return ["继续执行下一步。"];
|
|
516
|
+
const steps = {
|
|
517
|
+
ask_user_confirmation: ["向用户展示待确认的问题与选项,记录选择后重新运行检查。"],
|
|
518
|
+
collect_review_evidence: ["补齐所需审查或验证复核记录,然后重新运行检查。"],
|
|
519
|
+
collect_test_evidence: ["补齐失败/通过测试或校验证据,然后重新运行检查。"],
|
|
520
|
+
fix_artifacts: ["修正相关方案、任务或证据结构,然后重新运行检查。"],
|
|
521
|
+
repair_evidence: ["修复证据记录中的结构或引用问题,然后重新运行检查。"],
|
|
522
|
+
rerun_check: ["等待输入稳定后重新运行当前检查。"],
|
|
523
|
+
inspect_diagnostics: ["使用诊断输出查看内部细节,再按对应问题处理。"],
|
|
524
|
+
};
|
|
525
|
+
return steps[action];
|
|
526
|
+
}
|
|
527
|
+
const DIAGNOSTIC_HINT = "需要排查内部细节时使用 --format json。";
|
|
528
|
+
export function renderAgentDecision(decision, opts = {}) {
|
|
529
|
+
const decorated = sanitizeDecisionForOutput(decorateDecision(decision, opts));
|
|
530
|
+
const reasons = Array.isArray(decorated.block_reasons) ? decorated.block_reasons : [];
|
|
531
|
+
const reasonCodes = reasons.map((item) => String(item.code ?? ""));
|
|
532
|
+
const allowed = Boolean(decorated.allowed);
|
|
533
|
+
const workflowAction = workflowActionForReasonCodes(reasonCodes, allowed);
|
|
534
|
+
const renderedReasons = reasons.map((item) => safeReasonText(item, workflowAction)).filter(Boolean);
|
|
535
|
+
return {
|
|
536
|
+
allowed,
|
|
537
|
+
status: allowed ? "allowed" : "blocked",
|
|
538
|
+
workflow_action: workflowAction,
|
|
539
|
+
stage_label_zh: safeDisplayText(decorated.gate_label_zh) || "当前阶段",
|
|
540
|
+
check_label_zh: safeDisplayText(decorated.command_label_zh) || "当前检查",
|
|
541
|
+
summary_zh: safeDisplayText(summaryForWorkflowAction(workflowAction, allowed)),
|
|
542
|
+
reasons_zh: renderedReasons.length > 0 ? renderedReasons : undefined,
|
|
543
|
+
next_steps_zh: nextStepsForWorkflowAction(workflowAction, allowed).map(safeDisplayText),
|
|
544
|
+
diagnostic_hint: DIAGNOSTIC_HINT,
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
export function renderUserFacingDecision(decision, opts = {}) {
|
|
548
|
+
const decorated = sanitizeDecisionForOutput(decorateDecision(decision, opts));
|
|
549
|
+
const agentView = renderAgentDecision(decorated, opts);
|
|
550
|
+
const gate = safeDisplayText(decorated.gate_label_zh) || "当前检查";
|
|
551
|
+
const command = safeDisplayText(decorated.command_label_zh);
|
|
552
|
+
const lines = [];
|
|
553
|
+
if (decorated.allowed) {
|
|
554
|
+
lines.push(`检查通过:${gate}。`);
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
lines.push(`暂时不能继续:${gate}。`);
|
|
558
|
+
}
|
|
559
|
+
if (command && command !== gate) {
|
|
560
|
+
lines.push(`检查项:${command}。`);
|
|
561
|
+
}
|
|
562
|
+
const reasons = Array.isArray(decorated.block_reasons) ? decorated.block_reasons : [];
|
|
563
|
+
if (!decorated.allowed && reasons.length > 0) {
|
|
564
|
+
lines.push("原因:");
|
|
565
|
+
for (const item of reasons) {
|
|
566
|
+
const reasonText = safeReasonText(item, agentView.workflow_action);
|
|
567
|
+
lines.push(`- ${reasonText}`);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
const nextActions = Array.isArray(agentView.next_steps_zh) ? agentView.next_steps_zh.map(safeDisplayText).filter(Boolean) : [];
|
|
571
|
+
if (nextActions.length > 0) {
|
|
572
|
+
lines.push("下一步:");
|
|
573
|
+
for (const action of nextActions)
|
|
574
|
+
lines.push(`- ${action}`);
|
|
575
|
+
}
|
|
576
|
+
lines.push(`诊断:${DIAGNOSTIC_HINT}`);
|
|
577
|
+
return `${lines.join("\n")}\n`;
|
|
578
|
+
}
|
|
371
579
|
export function printDecision(decision, opts = {}) {
|
|
372
580
|
const decorated = decorateDecision(decision, opts);
|
|
581
|
+
if (opts.format === "user") {
|
|
582
|
+
process.stdout.write(renderUserFacingDecision(decorated, opts));
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
if (opts.format === "agent") {
|
|
586
|
+
process.stdout.write(`${JSON.stringify(renderAgentDecision(decorated, opts), null, 2)}\n`);
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
373
589
|
process.stdout.write(`${JSON.stringify(sanitizeDecisionForOutput(decorated), null, 2)}\n`);
|
|
374
590
|
}
|
|
375
591
|
export function runCommand(cmd, args, opts = {}) {
|
package/dist/superspec.d.ts
CHANGED
package/dist/superspec.js
CHANGED
|
@@ -3,8 +3,12 @@ import { realpathSync } from "node:fs";
|
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
export * from "./src/init_cli.js";
|
|
5
5
|
export * from "./src/cli.js";
|
|
6
|
+
export * from "./src/doctor.js";
|
|
7
|
+
export * from "./src/self_update.js";
|
|
6
8
|
import { main } from "./src/cli.js";
|
|
9
|
+
import { main_doctor, superspec_package_version } from "./src/doctor.js";
|
|
7
10
|
import { main_init_async } from "./src/init_cli.js";
|
|
11
|
+
import { update_self_then_rerun } from "./src/self_update.js";
|
|
8
12
|
function realpathMaybe(filePath) {
|
|
9
13
|
try {
|
|
10
14
|
return realpathSync(filePath);
|
|
@@ -19,14 +23,35 @@ function help() {
|
|
|
19
23
|
"",
|
|
20
24
|
"commands:",
|
|
21
25
|
" init install SuperSpec Codex surfaces (asks project/user; default project)",
|
|
22
|
-
" update update manifest-managed
|
|
26
|
+
" update update SuperSpec CLI, then update manifest-managed surfaces",
|
|
23
27
|
" uninstall remove manifest-managed SuperSpec surfaces",
|
|
24
28
|
" guard run the SuperSpec guard command surface",
|
|
29
|
+
" doctor diagnose SuperSpec/OpenSpec/npm/PATH wiring",
|
|
30
|
+
" version print SuperSpec CLI version",
|
|
25
31
|
"",
|
|
26
32
|
"examples:",
|
|
27
|
-
" superspec init --scope project",
|
|
33
|
+
" superspec init --scope project --format agent",
|
|
28
34
|
" superspec init --scope user",
|
|
29
|
-
" superspec guard check-init --change <change>",
|
|
35
|
+
" superspec guard check-init --change <change> --format agent",
|
|
36
|
+
" superspec doctor",
|
|
37
|
+
"",
|
|
38
|
+
].join("\n");
|
|
39
|
+
}
|
|
40
|
+
function updateHelp() {
|
|
41
|
+
return [
|
|
42
|
+
"usage: superspec update [--scope {project,user}] [--path PATH] [--codex-home PATH] [--format {json,agent,user}] [--local-only]",
|
|
43
|
+
"",
|
|
44
|
+
"updates the global SuperSpec CLI from npm, then updates manifest-managed SuperSpec surfaces.",
|
|
45
|
+
"",
|
|
46
|
+
"options:",
|
|
47
|
+
" --scope {project,user} update project .codex surfaces or user Codex home surfaces (default: project)",
|
|
48
|
+
" --project equivalent to --scope project",
|
|
49
|
+
" --user, --global equivalent to --scope user",
|
|
50
|
+
" --path PATH project root for project scope (default: current directory)",
|
|
51
|
+
" --codex-home PATH Codex user home for user scope (default: $CODEX_HOME or ~/.codex)",
|
|
52
|
+
" --format {json,agent,user} output format; use agent for workflow consumption",
|
|
53
|
+
" --local-only skip npm self-update and use the currently installed package",
|
|
54
|
+
" -h, --help show this help",
|
|
30
55
|
"",
|
|
31
56
|
].join("\n");
|
|
32
57
|
}
|
|
@@ -36,14 +61,29 @@ export async function main_superspec(argv = process.argv.slice(2)) {
|
|
|
36
61
|
process.stdout.write(help());
|
|
37
62
|
return 0;
|
|
38
63
|
}
|
|
64
|
+
if (command === "-v" || command === "--version" || command === "version") {
|
|
65
|
+
process.stdout.write(`${superspec_package_version()}\n`);
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
39
68
|
if (command === "init")
|
|
40
69
|
return main_init_async(rest);
|
|
41
|
-
if (command === "update")
|
|
42
|
-
|
|
70
|
+
if (command === "update") {
|
|
71
|
+
if (rest.includes("-h") || rest.includes("--help")) {
|
|
72
|
+
process.stdout.write(updateHelp());
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
const localOnly = rest.includes("--local-only") || rest.includes("--skip-self-update");
|
|
76
|
+
const updateArgs = rest.filter((arg) => arg !== "--local-only" && arg !== "--skip-self-update");
|
|
77
|
+
if (!localOnly)
|
|
78
|
+
return update_self_then_rerun({ args: updateArgs });
|
|
79
|
+
return main_init_async([...updateArgs, "--update"]);
|
|
80
|
+
}
|
|
43
81
|
if (command === "uninstall")
|
|
44
82
|
return main_init_async([...rest, "--uninstall"]);
|
|
45
83
|
if (command === "guard")
|
|
46
84
|
return main(rest);
|
|
85
|
+
if (command === "doctor")
|
|
86
|
+
return main_doctor(rest);
|
|
47
87
|
// Convenience fallback: `superspec check-init ...` behaves like `superspec guard check-init ...`.
|
|
48
88
|
if (command.startsWith("check-") || command === "status" || command === "recompute" || command === "init") {
|
|
49
89
|
return main(argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peterxiaoyang/superspec",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "SuperSpec workflow package: guard runtime, generic workflow templates, and Codex adapter payload.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "node build.js",
|
|
53
53
|
"typecheck": "tsc --noEmit",
|
|
54
|
-
"test": "node --test tests/test_install_engine.test.ts tests/test_real_openspec_smoke.test.ts tests/test_superspec_guard.test.ts tests/test_superspec_skills.test.ts",
|
|
54
|
+
"test": "node --test tests/test_install_engine.test.ts tests/test_real_openspec_smoke.test.ts tests/test_superspec_cli.test.ts tests/test_superspec_guard.test.ts tests/test_superspec_skills.test.ts",
|
|
55
55
|
"prepack": "npm run build",
|
|
56
56
|
"prepublishOnly": "npm run build",
|
|
57
57
|
"pack:dry-run": "npm pack --dry-run"
|
|
@@ -16,6 +16,8 @@ metadata:
|
|
|
16
16
|
- 对话窗口里的解释、总结、提问和下一步说明必须使用中文;除命令、路径、字段名、代码标识符外,不要夹带英文说明词。
|
|
17
17
|
- 对话窗口、AskUserQuestion 文案、进度更新和最终总结不得裸露内部证据种类、字段名或 reason code;用户确认记录、审查问题记录、审查轮次编号、问题唯一标识等都只用中文业务说法。原始协议名只允许写在证据 JSON、代码、测试、精确命令输出或用户明确要求的诊断片段中。
|
|
18
18
|
- 本 skill 文档中的内部协议名只用于落盘证据或运行 guard;写给用户时必须先翻译成中文业务动作,例如“记录用户确认”“记录审查问题”“完成最终审查判断”。
|
|
19
|
+
- 用户可见文案不得使用“裁决”描述用户动作;统一说“确认”“范围取舍”“处理方式选择”或“用户确认记录”。
|
|
20
|
+
- 普通 workflow 命令使用 `--format agent` 读取 guard/init 输出;`--format json` 只用于诊断 evidence/schema/guard 内部,不得作为默认模型上下文或直接转述给用户。
|
|
19
21
|
- 向用户转述 guard / review 输出时,不要直接贴英文 `message`、`next_allowed_actions` 或英文模板标题;应改写为中文,并仅在需要定位内部协议时保留英文 code/command 于反引号中。
|
|
20
22
|
|
|
21
23
|
## 命令执行 / Shell
|
|
@@ -23,6 +25,14 @@ metadata:
|
|
|
23
25
|
- Windows PowerShell 中执行 npm 全局 bin 时,必须显式使用 `.cmd` shim:`superspec.cmd ...`、`openspec.cmd ...`;不要运行 `superspec.ps1` 或 `openspec.ps1`。
|
|
24
26
|
- macOS、Linux、Git Bash、cmd.exe 或其他不会优先拦截 `.ps1` 的 shell 中,继续使用文档中的 `superspec ...`、`openspec ...` 命令。
|
|
25
27
|
|
|
28
|
+
## 上下文读取纪律 / Context Budget
|
|
29
|
+
|
|
30
|
+
- guard 可以在本地读取完整 `.superspec/evidence/**/*.json` 并重算判定;主流程默认不要打开完整 evidence JSON,除非正在排查 guard block、修复 schema,或用户明确要求诊断原文。
|
|
31
|
+
- 主流程默认只读取 guard decision、当前 task 必要 artifact、OpenSpec instructions apply 返回的 `contextFiles`、native subagent `output_ref` 的摘要/结论段,以及 task RED/GREEN 所需的最小测试摘要。
|
|
32
|
+
- raw log、长报告和历史 superseded evidence 默认只作为引用、hash 或摘要保留;不要把全文复制进对话上下文或新的 evidence。
|
|
33
|
+
- RED/GREEN 仍按 task 的 `test_refs` 记录 gate-driving evidence;同一次命令输出可以作为共享 raw log 被引用,但不要仅凭聚合日志替代每个 task/test 所需的 RED/GREEN 证据字段。
|
|
34
|
+
- 使用按运行合并建档的 `test_ids[]` 清单时,每个 claimed id 都必须出现在引用的 raw log 中;若当前 task gate 需要单个 `test_id` 覆盖,仍要补齐对应 gate-driving evidence。
|
|
35
|
+
|
|
26
36
|
在 propose package 完成后使用本 skill 执行实现任务。**Task context、ordering 和 progress 来自 OpenSpec native apply instructions**(`openspec instructions apply`);SuperSpec 为每个 task 包上一层 RED/GREEN guard checks。
|
|
27
37
|
|
|
28
38
|
## 边界 / Boundaries
|
|
@@ -41,11 +51,11 @@ metadata:
|
|
|
41
51
|
|
|
42
52
|
## 步骤 / Steps
|
|
43
53
|
|
|
44
|
-
1. 对实现隔离(apply isolation)和执行模式(execution mode)使用 AskUserQuestion
|
|
54
|
+
1. 对实现隔离(apply isolation)和执行模式(execution mode)使用 AskUserQuestion,并等待明确选择;记录 `gate:"apply_isolation"` 的 `human_confirmation` evidence,必须包含 `confirmation_text`、`confirmed_refs` 和当前 `tasks_structure_hash`。
|
|
45
55
|
2. 当 dirty worktree、untracked files 或 branch state 需要确认时,使用 AskUserQuestion 处理分支状态。
|
|
46
56
|
3. 验证 apply readiness:
|
|
47
57
|
```text
|
|
48
|
-
superspec guard check-apply-ready --change "<change>"
|
|
58
|
+
superspec guard check-apply-ready --change "<change>" --format agent
|
|
49
59
|
```
|
|
50
60
|
4. 获取 native apply context 和 task list:
|
|
51
61
|
```text
|
|
@@ -57,21 +67,21 @@ metadata:
|
|
|
57
67
|
- 若 `request_changes_route:"reopen_tasks"`,读取 `reopen_task_ids`,逐个判断当前 task 所处阶段:
|
|
58
68
|
- 如果该 task 仍是 `[x]`,说明还处于首次回退前;先由主流程基于本轮 review 的结构化 output 写出该 task 的 `task_reopen` evidence 与配套 `status:"superseded"` evidence,形成完整 reopen package,再执行:
|
|
59
69
|
```text
|
|
60
|
-
superspec guard check-task-reopen --change "<change>" --task-id "<task-id>"
|
|
70
|
+
superspec guard check-task-reopen --change "<change>" --task-id "<task-id>" --format agent
|
|
61
71
|
```
|
|
62
72
|
只有该 guard `allow` 后,才允许把对应 task 从 `- [x]` 改为 `- [ ]`,并把它重新纳入本轮 apply。
|
|
63
73
|
- 如果该 task 已经是 `[ ]`,且当前 `tasks.md` 已匹配授权后的 `after_tasks_sha256`,说明它已经处于合法 reopened apply;此时直接续跑 `check-task-edit -> RED/GREEN -> check-task-complete`,不要重复创建 `task_reopen`,也不要再次执行 pre-revert `check-task-reopen`。
|
|
64
74
|
- 若 `request_changes_route:"change_update"`,停止 apply,回 propose / change update;不要试图通过 reopen 继续实现。
|
|
65
75
|
6. 对每个 pending task(包括刚刚合法 reopen 的 task),在任何实现编辑前执行任务编辑前检查(`check-task-edit`):
|
|
66
76
|
```text
|
|
67
|
-
superspec guard check-task-edit --change "<change>" --task-id "<task-id>"
|
|
77
|
+
superspec guard check-task-edit --change "<change>" --task-id "<task-id>" --format agent
|
|
68
78
|
```
|
|
69
79
|
7. 在 runtime/business implementation edits 前产出 RED evidence,除非有允许的 `no_tdd_reason` 或处于现状锁定测试模式(`characterization mode`)。这里的 `characterization` 指“先把当前真实行为测出来并锁住,重构后保持一致”。RED/GREEN evidence 必须引用 task 的 `test_refs`,并在 task 声明 `invariant_refs` 时同步记录 `invariant_refs`。若 task 来自 reopen,本轮 successor GREEN / alternative verification / manual verification 必须携带同一 `reopen_id`。
|
|
70
80
|
8. 按 native dynamic instruction 和 `contextFiles` 指引,实现最小 task scope。
|
|
71
|
-
9. 产出 GREEN evidence,保留 `test_id`、`invariant_refs`、命令、输出摘要和 raw log ref
|
|
81
|
+
9. 产出 GREEN evidence,保留 `test_id`、`invariant_refs`、命令、输出摘要和 raw log ref;raw log ref 指向原始输出文件,evidence 中只写必要摘要,不复制完整日志。
|
|
72
82
|
10. 勾选 task 前执行任务完成检查(`check-task-complete`):
|
|
73
83
|
```text
|
|
74
|
-
superspec guard check-task-complete --change "<change>" --task-id "<task-id>"
|
|
84
|
+
superspec guard check-task-complete --change "<change>" --task-id "<task-id>" --format agent
|
|
75
85
|
```
|
|
76
86
|
然后按 native apply semantics 将 task 从 `- [ ]` 改为 `- [x]`。
|
|
77
87
|
11. 如果该 task 来自 reopen,在重新勾回 `[x]` 后写入 `kind:"task_reopen_resolved"` evidence,关闭本轮 reopen 授权;不要复用旧 reopen 生命周期。reopen 只授权:
|
|
@@ -16,6 +16,8 @@ metadata:
|
|
|
16
16
|
- 对话窗口里的解释、确认、总结和下一步说明必须使用中文;除命令、路径、字段名、代码标识符外,不要夹带英文说明词。
|
|
17
17
|
- 对话窗口、AskUserQuestion 文案、进度更新和最终总结不得裸露内部证据种类、字段名或 reason code;用户确认记录、审查问题记录、审查轮次编号、问题唯一标识等都只用中文业务说法。原始协议名只允许写在证据 JSON、代码、测试、精确命令输出或用户明确要求的诊断片段中。
|
|
18
18
|
- 本 skill 文档中的内部协议名只用于落盘证据或运行 guard;写给用户时必须先翻译成中文业务动作,例如“记录用户确认”“记录审查问题”“完成最终审查判断”。
|
|
19
|
+
- 用户可见文案不得使用“裁决”描述用户动作;统一说“确认”“范围取舍”“处理方式选择”或“用户确认记录”。
|
|
20
|
+
- 普通 workflow 命令使用 `--format agent` 读取 guard/init 输出;`--format json` 只用于诊断 evidence/schema/guard 内部,不得作为默认模型上下文或直接转述给用户。
|
|
19
21
|
- 向用户转述 guard / archive 输出时,不要直接贴英文 `message`、`next_allowed_actions` 或英文模板标题;应改写为中文,并仅在需要定位内部协议时保留英文 code/command 于反引号中。
|
|
20
22
|
|
|
21
23
|
## 命令执行 / Shell
|
|
@@ -23,6 +25,12 @@ metadata:
|
|
|
23
25
|
- Windows PowerShell 中执行 npm 全局 bin 时,必须显式使用 `.cmd` shim:`superspec.cmd ...`、`openspec.cmd ...`;不要运行 `superspec.ps1` 或 `openspec.ps1`。
|
|
24
26
|
- macOS、Linux、Git Bash、cmd.exe 或其他不会优先拦截 `.ps1` 的 shell 中,继续使用文档中的 `superspec ...`、`openspec ...` 命令。
|
|
25
27
|
|
|
28
|
+
## 上下文读取纪律 / Context Budget
|
|
29
|
+
|
|
30
|
+
- guard 可以在本地读取完整 `.superspec/evidence/**/*.json` 并重算 archive 判定;主流程默认不要打开完整 evidence JSON,除非正在排查 guard block、修复 preservation manifest,或用户明确要求诊断原文。
|
|
31
|
+
- 主流程默认只读取 guard decision、archive preservation 摘要、OpenSpec archive 输出摘要,以及最终验证 archive 结果所需的最小 manifest 信息。
|
|
32
|
+
- raw log、长报告和历史 superseded evidence 默认只作为引用、hash 或摘要保留;不要把全文复制进对话上下文或新的 evidence。
|
|
33
|
+
|
|
26
34
|
仅在 `review_complete` passes(其中已经包含 final verification)后使用本 skill。
|
|
27
35
|
|
|
28
36
|
## 边界 / Boundaries
|
|
@@ -38,7 +46,7 @@ metadata:
|
|
|
38
46
|
1. 对 `archive_ready` 最终确认使用 AskUserQuestion,等待明确选择。记录 archive-scoped human-confirmation evidence。当前 v1 不询问也不使用 `--skip-specs`;若 change 不应同步 specs,应先回到 propose/change update 调整 OpenSpec 包,而不是在 archive 阶段跳过。
|
|
39
47
|
2. 检查 archive readiness 并生成 preservation manifest:
|
|
40
48
|
```text
|
|
41
|
-
superspec guard check-archive-ready --change "<change>"
|
|
49
|
+
superspec guard check-archive-ready --change "<change>" --format agent
|
|
42
50
|
```
|
|
43
51
|
生成的 manifest 是 archive 前证据快照,必须能追踪 business-invariants、test-contract 和对应 invariant review evidence 的 sha256。
|
|
44
52
|
3. 运行 native OpenSpec archive(移动 change、同步 delta->main specs、执行 validation):
|
|
@@ -47,7 +55,7 @@ metadata:
|
|
|
47
55
|
```
|
|
48
56
|
4. 根据 manifest 验证 archived `.superspec/` preservation:
|
|
49
57
|
```text
|
|
50
|
-
superspec guard check-archived --change "<change>"
|
|
58
|
+
superspec guard check-archived --change "<change>" --format agent
|
|
51
59
|
```
|
|
52
60
|
|
|
53
61
|
遇到任何 guard `block` 就停止。
|
|
@@ -16,6 +16,8 @@ metadata:
|
|
|
16
16
|
- 对话窗口里的解释、问题说明、总结、提问和下一步说明必须使用中文;除命令、路径、字段名、代码标识符外,不要夹带英文说明词。
|
|
17
17
|
- 对话窗口、AskUserQuestion 文案、进度更新和最终总结不得裸露内部证据种类、字段名或 reason code;用户确认记录、审查问题记录、审查轮次编号、问题唯一标识等都只用中文业务说法。原始协议名只允许写在证据 JSON、代码、测试、精确命令输出或用户明确要求的诊断片段中。
|
|
18
18
|
- 本 skill 文档中的内部协议名只用于落盘证据或运行 guard;写给用户时必须先翻译成中文业务动作,例如“记录用户确认”“记录审查问题”“完成最终审查判断”。
|
|
19
|
+
- 用户可见文案不得使用“裁决”描述用户动作;统一说“确认”“范围取舍”“处理方式选择”或“用户确认记录”。
|
|
20
|
+
- 普通 workflow 命令使用 `--format agent` 读取 guard/init 输出;`--format json` 只用于诊断 evidence/schema/guard 内部,不得作为默认模型上下文或直接转述给用户。
|
|
19
21
|
- 向用户转述 guard / review 输出时,不要直接贴英文 `message`、`next_allowed_actions` 或英文模板标题;应改写为中文,并仅在需要定位内部协议时保留英文 code/command 于反引号中。
|
|
20
22
|
|
|
21
23
|
## 命令执行 / Shell
|
|
@@ -23,6 +25,14 @@ metadata:
|
|
|
23
25
|
- Windows PowerShell 中执行 npm 全局 bin 时,必须显式使用 `.cmd` shim:`superspec.cmd ...`、`openspec.cmd ...`;不要运行 `superspec.ps1` 或 `openspec.ps1`。
|
|
24
26
|
- macOS、Linux、Git Bash、cmd.exe 或其他不会优先拦截 `.ps1` 的 shell 中,继续使用文档中的 `superspec ...`、`openspec ...` 命令。
|
|
25
27
|
|
|
28
|
+
## 上下文读取纪律 / Context Budget
|
|
29
|
+
|
|
30
|
+
- guard 可以在本地读取完整 `.superspec/evidence/**/*.json` 并重算判定;主流程默认不要打开完整 evidence JSON,除非正在排查 guard block、修复 schema,或用户明确要求诊断原文。
|
|
31
|
+
- 主流程默认只读取 guard decision、当前 gate 必要 artifact、OpenSpec instructions 返回的必要 context、native subagent `output_ref` 的摘要/结论段,以及用户确认所需的最小原文。
|
|
32
|
+
- 当前轮披露循环所需的最小结构化字段必须读取,不能只看 `output_ref` 摘要;包括 role evidence 的 `findings[]`、`finding_uid`、`decision_scope_key`、逐字 `summary`、`target_refs`,以及本轮 digest 需要引用的 evidence id。
|
|
33
|
+
- raw log、长报告和历史 superseded evidence 默认只作为引用、hash 或摘要保留;不要把全文复制进对话上下文或新的 evidence。
|
|
34
|
+
- native subagent 的 `output_ref` 应指向简洁审查报告;原始命令输出或长日志放在 raw/report 文件中被引用,不作为默认阅读材料。
|
|
35
|
+
|
|
26
36
|
在 init 之后、编写 OpenSpec proposal package 之前使用本 skill。
|
|
27
37
|
|
|
28
38
|
## 边界 / Boundaries
|
|
@@ -56,12 +66,12 @@ metadata:
|
|
|
56
66
|
|
|
57
67
|
1. 确保项目级 SuperSpec surfaces 已存在:
|
|
58
68
|
```text
|
|
59
|
-
superspec init --scope project
|
|
69
|
+
superspec init --scope project --format agent
|
|
60
70
|
```
|
|
61
71
|
2. 创建或打开 native OpenSpec change root,然后确认 change-scoped guard readiness 并拉取 native context:
|
|
62
72
|
```text
|
|
63
73
|
openspec new change "<change>" # 仅当该 change 不存在时执行
|
|
64
|
-
superspec guard check-init --change "<change>"
|
|
74
|
+
superspec guard check-init --change "<change>" --format agent
|
|
65
75
|
openspec list --json
|
|
66
76
|
openspec status --change "<change>" --json # changeRoot / artifactPaths / actionContext for grounding
|
|
67
77
|
```
|
|
@@ -74,9 +84,10 @@ metadata:
|
|
|
74
84
|
```
|
|
75
85
|
7. 在 `.superspec/evidence/discovery/` 记录 critic evidence,包含 `execution_mode:"native_subagent"`、`agent_role`、`agent_id`、`output_ref`、`source_anchors` 和 `target_refs`。
|
|
76
86
|
8. 按确认循环处理 findings:写本轮审查问题记录;存在关键问题时**停下来向用户说明并等待用户确认**,再按用户确认更新探索记录 / 重跑 critic / 写新一轮记录,直到最新轮 clean 且问题清单里没有未处理完的问题。
|
|
77
|
-
9.
|
|
87
|
+
9. 对探索结论、范围边界和进入 propose 的授权使用 AskUserQuestion,并等待明确选择;记录探索阶段人工确认 evidence(JSON 中为 `gate:"explore_complete"`、`kind:"human_confirmation"`、`created_by:"user"`),`confirmed_refs` 固定记录用户确认过的探索记录。
|
|
88
|
+
10. 运行进入阶段前检查(`check-enter`),验证 explore completion:
|
|
78
89
|
```text
|
|
79
|
-
superspec guard check-enter --change "<change>" --gate explore_complete
|
|
90
|
+
superspec guard check-enter --change "<change>" --gate explore_complete --format agent
|
|
80
91
|
```
|
|
81
92
|
|
|
82
93
|
遇到任何 guard `block` 就停止。用户确认相关阻塞原因包括:缺少审查问题记录(`missing_review_digest`)、等待用户确认(`needs_user_decision_pending`)、历史 finding 未处理完(`finding_unresolved`)、用户确认未绑定(`user_decision_unbound`)、缺少 finding 问题清单(`ledger_injection_missing`)、审查轮次已达上限(`round_budget_exhausted`)等。它们的唯一合法出路是回到确认循环或升级给用户,不允许绕过。
|
|
@@ -16,6 +16,8 @@ metadata:
|
|
|
16
16
|
- 对话窗口里的解释、问题说明、总结、提问和下一步说明必须使用中文;除命令、路径、字段名、代码标识符外,不要夹带英文说明词。
|
|
17
17
|
- 对话窗口、AskUserQuestion 文案、进度更新和最终总结不得裸露内部证据种类、字段名或 reason code;用户确认记录、审查问题记录、审查轮次编号、问题唯一标识等都只用中文业务说法。原始协议名只允许写在证据 JSON、代码、测试、精确命令输出或用户明确要求的诊断片段中。
|
|
18
18
|
- 本 skill 文档中的内部协议名只用于落盘证据或运行 guard;写给用户时必须先翻译成中文业务动作,例如“记录用户确认”“记录审查问题”“完成最终审查判断”。
|
|
19
|
+
- 用户可见文案不得使用“裁决”描述用户动作;统一说“确认”“范围取舍”“处理方式选择”或“用户确认记录”。
|
|
20
|
+
- 普通 workflow 命令使用 `--format agent` 读取 guard/init 输出;`--format json` 只用于诊断 evidence/schema/guard 内部,不得作为默认模型上下文或直接转述给用户。
|
|
19
21
|
- 向用户转述 guard / review 输出时,不要直接贴英文 `message`、`next_allowed_actions` 或英文模板标题;应改写为中文,并仅在需要定位内部协议时保留英文 code/command 于反引号中。
|
|
20
22
|
|
|
21
23
|
## 命令执行 / Shell
|
|
@@ -23,6 +25,14 @@ metadata:
|
|
|
23
25
|
- Windows PowerShell 中执行 npm 全局 bin 时,必须显式使用 `.cmd` shim:`superspec.cmd ...`、`openspec.cmd ...`;不要运行 `superspec.ps1` 或 `openspec.ps1`。
|
|
24
26
|
- macOS、Linux、Git Bash、cmd.exe 或其他不会优先拦截 `.ps1` 的 shell 中,继续使用文档中的 `superspec ...`、`openspec ...` 命令。
|
|
25
27
|
|
|
28
|
+
## 上下文读取纪律 / Context Budget
|
|
29
|
+
|
|
30
|
+
- guard 可以在本地读取完整 `.superspec/evidence/**/*.json` 并重算判定;主流程默认不要打开完整 evidence JSON,除非正在排查 guard block、修复 schema,或用户明确要求诊断原文。
|
|
31
|
+
- 主流程默认只读取 guard decision、当前 gate 必要 artifact、OpenSpec instructions 返回的必要 context、native subagent `output_ref` 的摘要/结论段,以及用户确认所需的最小原文。
|
|
32
|
+
- 当前轮披露循环所需的最小结构化字段必须读取,不能只看 `output_ref` 摘要;包括 role evidence 的 `findings[]`、`finding_uid`、`decision_scope_key`、逐字 `summary`、`target_refs`,以及本轮 digest 需要引用的 evidence id。
|
|
33
|
+
- raw log、长报告和历史 superseded evidence 默认只作为引用、hash 或摘要保留;不要把全文复制进对话上下文或新的 evidence。
|
|
34
|
+
- native subagent 的 `output_ref` 应指向简洁审查报告;原始命令输出或长日志放在 raw/report 文件中被引用,不作为默认阅读材料。
|
|
35
|
+
|
|
26
36
|
在 explore 完成后使用本 skill,用于把探索记录整理成可执行的正式方案包。OpenSpec 负责生成标准方案文件,具体写法必须通过它自带的指令(`openspec instructions`)获取;SuperSpec 负责在外层增加审查门禁(gates)、业务约束(`business-invariants.md`)、测试契约(`test-contract.md`)和任务元数据。
|
|
27
37
|
|
|
28
38
|
## 边界 / Boundaries
|
|
@@ -43,9 +53,9 @@ metadata:
|
|
|
43
53
|
|
|
44
54
|
## 步骤 / Steps
|
|
45
55
|
|
|
46
|
-
1. 运行前置门禁检查(`check-enter
|
|
56
|
+
1. 运行前置门禁检查(`check-enter`),确认探索阶段已经完成;该 gate 必须包含用户对探索结论和进入 propose 的明确确认,若 guard block 则停止并回到 explore 补确认:
|
|
47
57
|
```text
|
|
48
|
-
superspec guard check-enter --change "<change>" --gate explore_complete
|
|
58
|
+
superspec guard check-enter --change "<change>" --gate explore_complete --format agent
|
|
49
59
|
```
|
|
50
60
|
2. 从 OpenSpec 获取方案文件生成顺序:
|
|
51
61
|
```text
|
|
@@ -64,28 +74,28 @@ metadata:
|
|
|
64
74
|
- 主流程记录审查问题记录,给每个 finding 写处理结果:关键 findings(范围、非目标、验收标准、业务语义、设计边界)必须进入用户确认并停下来,用 AskUserQuestion 把原文和 A/B/C/D 选项展示给用户,拿到用户确认后才能继续;发现探索记录不完整时 route 用 `return_explore` 回 explore,不得自行补范围。
|
|
65
75
|
- 修订 `proposal.md` 后必须重跑 `critic`(新一轮 round),直到 clean round + digest 通过,然后验证:
|
|
66
76
|
```text
|
|
67
|
-
superspec guard check-enter --change "<change>" --gate propose.proposal_reviewed
|
|
77
|
+
superspec guard check-enter --change "<change>" --gate propose.proposal_reviewed --format agent
|
|
68
78
|
```
|
|
69
79
|
guard 未通过前不要开始编写 `specs/**` 或 `design.md`(两者的入口门禁都是 `proposal_reviewed`)。
|
|
70
80
|
5. 设计说明 `design.md` 编写后:获取 `architect`、`critic`、`test-engineer` 的 native-subagent review evidence(带 `review_round_id` `design_complete-r<N>` + `findings[]` + 全量 pinned target:`proposal.md` + `design.md` + `specs/**/*.md` + 探索记录)。主流程记录审查问题记录;关键问题必须停下来向用户说明并等待用户确认,按用户确认改 design/specs 后 supersede 旧轮并重审。对于设计选项选择和最终设计确认,使用 AskUserQuestion 并等待明确选择;记录 human-confirmation evidence,然后验证:
|
|
71
81
|
```text
|
|
72
|
-
superspec guard check-enter --change "<change>" --gate propose.design_reviewed
|
|
82
|
+
superspec guard check-enter --change "<change>" --gate propose.design_reviewed --format agent
|
|
73
83
|
```
|
|
74
84
|
6. 需求规格 `specs/**` 和设计说明 `design.md` 编写后、测试契约 `test-contract.md` 编写前:起草业务约束 `.superspec/artifacts/business-invariants.md`。每条 `INV-*` 必须有 statement、scope、source anchors、acceptance_refs、risk_refs、confidence、enforcement_level、test_refs_or_review_only_reason;记录 rejected candidates,防止把当前实现习惯误升格为业务真相。获取 `critic` + `test-engineer` review evidence(带 `review_round_id` `invariants_reviewed-r<N>` + `findings[]` + pinned target:business-invariants + design + specs glob)。主流程记录审查问题记录;关键业务语义问题必须进入用户确认,不得把实现习惯静默升格为 invariant 真相。然后验证:
|
|
75
85
|
```text
|
|
76
|
-
superspec guard check-enter --change "<change>" --gate propose.invariants_reviewed
|
|
86
|
+
superspec guard check-enter --change "<change>" --gate propose.invariants_reviewed --format agent
|
|
77
87
|
```
|
|
78
88
|
7. 业务约束 `business-invariants.md` 完成后、任务清单 `tasks.md` 编写前:起草测试契约 `.superspec/artifacts/test-contract.md`,覆盖 specs 中每个 `#### Scenario` 和命中本 change scope 的 hard `INV-*`,包含 TEST ids、关联 INV ids、预期 RED reasons、预期 GREEN criteria 和 commands。获取 `test-engineer` + `critic` review evidence(带 `review_round_id` `test_contract_drafted-r<N>` + `findings[]` + pinned target:test-contract + invariants + design + specs glob)。主流程记录审查问题记录;验收标准变更等关键问题必须用户确认。然后验证:
|
|
79
89
|
```text
|
|
80
|
-
superspec guard check-enter --change "<change>" --gate propose.test_plan_drafted
|
|
90
|
+
superspec guard check-enter --change "<change>" --gate propose.test_plan_drafted --format agent
|
|
81
91
|
```
|
|
82
|
-
8. 通过 `openspec instructions tasks` 编写任务清单 `tasks.md` 时:为每个 task 补充 `requirement_refs`、`invariant_refs`(必须是 business-invariants `INV-*` ids 的子集)、`test_refs`(必须是 test-contract TEST ids 的子集)、`read_scope`、`write_scope`、dependencies、TDD metadata,以及需要时的 parallel group。若 reviewer 对 task 映射提出 round-tagged findings,走 `tasks_complete-r<N>` 确认循环(pinned target:tasks + test-contract + invariants + design + specs glob);验收标准问题 route 用 `return_test_contract_drafted`,映射问题用 `stay_same_gate_fix`。对于任务审查确认,使用 AskUserQuestion
|
|
92
|
+
8. 通过 `openspec instructions tasks` 编写任务清单 `tasks.md` 时:为每个 task 补充 `requirement_refs`、`invariant_refs`(必须是 business-invariants `INV-*` ids 的子集)、`test_refs`(必须是 test-contract TEST ids 的子集)、`read_scope`、`write_scope`、dependencies、TDD metadata,以及需要时的 parallel group。若 reviewer 对 task 映射提出 round-tagged findings,走 `tasks_complete-r<N>` 确认循环(pinned target:tasks + test-contract + invariants + design + specs glob);验收标准问题 route 用 `return_test_contract_drafted`,映射问题用 `stay_same_gate_fix`。对于任务审查确认,使用 AskUserQuestion 并等待明确选择;按披露循环记录用户确认和审查问题处理结果,然后验证:
|
|
83
93
|
```text
|
|
84
|
-
superspec guard check-enter --change "<change>" --gate propose.tasks_mapped
|
|
94
|
+
superspec guard check-enter --change "<change>" --gate propose.tasks_mapped --format agent
|
|
85
95
|
```
|
|
86
96
|
9. 验证 apply readiness:
|
|
87
97
|
```text
|
|
88
|
-
superspec guard check-apply-ready --change "<change>"
|
|
98
|
+
superspec guard check-apply-ready --change "<change>" --format agent
|
|
89
99
|
```
|
|
90
100
|
|
|
91
101
|
遇到任何 guard `block` 就停止。
|