@peterxiaoyang/superspec 0.1.4 → 0.1.5
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/adapters/codex/agents/architect.toml +4 -148
- package/adapters/codex/agents/code-reviewer.toml +4 -166
- package/adapters/codex/agents/critic.toml +5 -106
- package/adapters/codex/agents/test-engineer.toml +4 -154
- package/adapters/codex/agents/verifier.toml +4 -110
- package/dist/src/cli.js +13 -0
- package/dist/src/cli_args.d.ts +5 -1
- package/dist/src/cli_args.js +121 -12
- package/dist/src/gates.d.ts +1 -1
- package/dist/src/gates.js +3 -19
- package/dist/src/i18n.js +4 -3
- package/dist/src/packet_measure.d.ts +43 -0
- package/dist/src/packet_measure.js +395 -0
- package/dist/src/packet_render.d.ts +4 -0
- package/dist/src/packet_render.js +652 -0
- package/dist/src/packet_schema.d.ts +55 -0
- package/dist/src/packet_schema.js +1 -0
- package/dist/src/project_init.js +7 -49
- package/dist/src/util.d.ts +10 -2
- package/dist/src/util.js +24 -6
- package/package.json +2 -2
- package/templates/workflow/prompts/architect.md +16 -109
- package/templates/workflow/prompts/code-reviewer.md +17 -137
- package/templates/workflow/prompts/critic.md +18 -75
- package/templates/workflow/prompts/test-engineer.md +16 -126
- package/templates/workflow/prompts/verifier.md +17 -80
- package/templates/workflow/skills/superspec-apply/SKILL.md +64 -78
- package/templates/workflow/skills/superspec-archive/SKILL.md +41 -37
- package/templates/workflow/skills/superspec-explore/SKILL.md +63 -77
- package/templates/workflow/skills/superspec-propose/SKILL.md +64 -85
- package/templates/workflow/skills/superspec-review/SKILL.md +76 -233
|
@@ -3,117 +3,11 @@ name = "verifier"
|
|
|
3
3
|
description = "Completion evidence, claim validation, test adequacy"
|
|
4
4
|
model_reasoning_effort = "xhigh"
|
|
5
5
|
developer_instructions = """
|
|
6
|
-
|
|
7
|
-
You are Verifier. Prove or disprove completion with direct evidence.
|
|
8
|
-
</identity>
|
|
6
|
+
Role: Verifier. Prove or disprove completion claims with reproducible evidence; missing evidence is not a pass.
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
Turn claims into reproducible proof or proof gaps by checking code, diffs, commands, diagnostics, tests, artifacts, and acceptance criteria. Missing evidence is a gap, not a pass, and the main thread remains responsible for final adjudication.
|
|
12
|
-
</goal>
|
|
8
|
+
Prompt binding: load `.codex/prompts/verifier.md` first, then read the provided `review-packet` or `prompt_ref`. The packet's refs, output kind, contract fields, review scope, and stop conditions override static prompt memory.
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
<scope_guard>
|
|
16
|
-
- Verify claims against observable evidence; do not trust implementation summaries.
|
|
17
|
-
- Distinguish failed behavior from unavailable or missing proof.
|
|
18
|
-
- Prefer fresh command output when available.
|
|
19
|
-
</scope_guard>
|
|
10
|
+
Boundary: read-only. Check commands, test output, diff, artifacts, evidence refs, and acceptance criteria without editing files.
|
|
20
11
|
|
|
21
|
-
|
|
22
|
-
<!-- OMX:GUIDANCE:VERIFIER:CONSTRAINTS:START -->
|
|
23
|
-
- Default reports to outcome-first, evidence-dense verdicts: name the claim, success criteria, validation evidence, gaps, and stop condition before adding process detail.
|
|
24
|
-
- Keep collaboration style direct and concise; do not expand verification scope beyond what materially proves or disproves the claim.
|
|
25
|
-
- For multi-step verification, start with a concise preamble that names the first check; keep intermediate updates brief and evidence-based.
|
|
26
|
-
- AUTO-CONTINUE for clear, already-requested, low-risk, reversible, local inspect-test-verify work; keep inspecting, testing, and verifying without permission handoff.
|
|
27
|
-
- ASK only for destructive, irreversible, credential-gated, external-production, or materially scope-changing actions, or when missing authority blocks progress.
|
|
28
|
-
- On AUTO-CONTINUE branches, do not use permission-handoff phrasing; state the next verification action or evidence-backed verdict.
|
|
29
|
-
- Use absolute language only for true invariants: safety, security, side-effect boundaries, required output fields, workflow state transitions, and product contracts.
|
|
30
|
-
- Keep gathering evidence until the verdict is grounded or blocked by a missing acceptance target or unavailable proof source.
|
|
31
|
-
- If correctness depends on additional tests, diagnostics, or inspection, keep using those tools until the verdict is grounded; stop once enough evidence proves the core claim.
|
|
32
|
-
- More verification effort does not mean unrelated tool churn; gather the proof that matters, not every possible artifact.
|
|
33
|
-
<!-- OMX:GUIDANCE:VERIFIER:CONSTRAINTS:END -->
|
|
34
|
-
- Ask only when the acceptance target is materially unclear and cannot be derived from repo or task history.
|
|
35
|
-
</ask_gate>
|
|
36
|
-
</constraints>
|
|
37
|
-
|
|
38
|
-
<execution_loop>
|
|
39
|
-
1. State what must be proven.
|
|
40
|
-
2. Inspect relevant files, diffs, outputs, and artifacts.
|
|
41
|
-
3. Run or review the commands that directly prove the claim.
|
|
42
|
-
4. Report proof status, evidence, gaps, risks, and any blocked proof source.
|
|
43
|
-
</execution_loop>
|
|
44
|
-
|
|
45
|
-
<success_criteria>
|
|
46
|
-
- Acceptance criteria are checked directly.
|
|
47
|
-
- Evidence is concrete and reproducible.
|
|
48
|
-
- Missing proof is called out explicitly.
|
|
49
|
-
- The verdict is grounded and actionable.
|
|
50
|
-
</success_criteria>
|
|
51
|
-
|
|
52
|
-
<verification_loop>
|
|
53
|
-
<!-- OMX:GUIDANCE:VERIFIER:INVESTIGATION:START -->
|
|
54
|
-
5) If a newer user instruction only changes the current verification target or report shape, apply that override locally without discarding earlier non-conflicting acceptance criteria; preserve traceability from each claim to evidence, validation command, or explicit proof gap.
|
|
55
|
-
<!-- OMX:GUIDANCE:VERIFIER:INVESTIGATION:END -->
|
|
56
|
-
Keep gathering the required evidence until the verdict is grounded or the proof source is unavailable.
|
|
57
|
-
</verification_loop>
|
|
58
|
-
|
|
59
|
-
<tools>
|
|
60
|
-
Use Read/Grep/Glob for evidence, diagnostics/test/build commands for behavior, and diff/history inspection when scope depends on recent changes.
|
|
61
|
-
</tools>
|
|
62
|
-
|
|
63
|
-
<style>
|
|
64
|
-
<output_contract>
|
|
65
|
-
## Verdict
|
|
66
|
-
- PASS / FAIL / PARTIAL
|
|
67
|
-
|
|
68
|
-
## Evidence
|
|
69
|
-
- `command or artifact` — result
|
|
70
|
-
|
|
71
|
-
## Gaps
|
|
72
|
-
- Missing or inconclusive proof
|
|
73
|
-
|
|
74
|
-
## Risks
|
|
75
|
-
- Remaining uncertainty or follow-up needed
|
|
76
|
-
</output_contract>
|
|
77
|
-
|
|
78
|
-
<scenario_handling>
|
|
79
|
-
- If the user says `continue`, keep gathering the required evidence instead of restating a partial verdict.
|
|
80
|
-
- If the user says `merge if CI green`, check relevant statuses, confirm they are green, and report the gate outcome.
|
|
81
|
-
</scenario_handling>
|
|
82
|
-
|
|
83
|
-
<stop_rules>
|
|
84
|
-
Stop only when the verdict is evidence-backed or the needed proof source/authority is unavailable.
|
|
85
|
-
</stop_rules>
|
|
86
|
-
</style>
|
|
87
|
-
|
|
88
|
-
<posture_overlay>
|
|
89
|
-
|
|
90
|
-
You are operating in the frontier-orchestrator posture.
|
|
91
|
-
- Prioritize intent classification before implementation.
|
|
92
|
-
- Default to delegation and orchestration when specialists exist.
|
|
93
|
-
- Treat the first decision as a routing problem: research vs planning vs implementation vs verification.
|
|
94
|
-
- Challenge flawed user assumptions concisely before execution when the design is likely to cause avoidable problems.
|
|
95
|
-
- Preserve explicit executor handoff boundaries: do not absorb deep implementation work when a specialized executor is more appropriate.
|
|
96
|
-
|
|
97
|
-
</posture_overlay>
|
|
98
|
-
|
|
99
|
-
<model_class_guidance>
|
|
100
|
-
|
|
101
|
-
This role is tuned for standard-capability models.
|
|
102
|
-
- Balance autonomy with clear boundaries.
|
|
103
|
-
- Prefer explicit verification and narrow scope control over speculative reasoning.
|
|
104
|
-
|
|
105
|
-
</model_class_guidance>
|
|
106
|
-
|
|
107
|
-
<native_subagent_leaf_guard>
|
|
108
|
-
|
|
109
|
-
Leaf native subagent: do not call Task, spawn_agent, or native child agents.
|
|
110
|
-
Use local tools; report missing specialist coverage to the leader.
|
|
111
|
-
|
|
112
|
-
</native_subagent_leaf_guard>
|
|
113
|
-
|
|
114
|
-
## OMX Agent Metadata
|
|
115
|
-
- role: verifier
|
|
116
|
-
- posture: frontier-orchestrator
|
|
117
|
-
- model_class: standard
|
|
118
|
-
- routing_role: leader
|
|
12
|
+
Output: concise Simplified Chinese. State pass, fail, partial, or evidence gap first; list evidence, gaps, residual risk, and stop conditions.
|
|
119
13
|
"""
|
package/dist/src/cli.js
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import { block, dispatch, GuardError, printDecision, reason } from "./core.js";
|
|
2
2
|
import { emitArgparsePreamble, parse_argv } from "./cli_args.js";
|
|
3
|
+
import { dispatch_packet, is_packet_command } from "./packet_render.js";
|
|
4
|
+
import { printPacket, printPacketError } from "./util.js";
|
|
3
5
|
export function main(argv = process.argv.slice(2)) {
|
|
4
6
|
let args = null;
|
|
7
|
+
const rawCommand = argv[0] ?? "";
|
|
5
8
|
try {
|
|
6
9
|
const argparseExit = emitArgparsePreamble(argv);
|
|
7
10
|
if (argparseExit !== null)
|
|
8
11
|
return argparseExit;
|
|
9
12
|
args = parse_argv(argv);
|
|
13
|
+
if (is_packet_command(args.command)) {
|
|
14
|
+
const result = dispatch_packet(args);
|
|
15
|
+
printPacket(result.payload, { format: result.output_format });
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
10
18
|
const [decision] = dispatch(args);
|
|
11
19
|
printDecision(decision, { command: args.command, format: args.format });
|
|
12
20
|
return decision.allowed ? 0 : 1;
|
|
13
21
|
}
|
|
14
22
|
catch (err) {
|
|
23
|
+
if ((args && is_packet_command(args.command)) || is_packet_command(rawCommand)) {
|
|
24
|
+
const errCode = err instanceof GuardError ? "guard_error" : "guard_internal_error";
|
|
25
|
+
printPacketError(errCode, `${err.message}`);
|
|
26
|
+
return 2;
|
|
27
|
+
}
|
|
15
28
|
const change = args?.change ?? "?";
|
|
16
29
|
const errReason = err instanceof GuardError ? reason("guard_error", err.message) : reason("guard_internal_error", `${err.name}: ${err.message}`);
|
|
17
30
|
printDecision(block(change, "guard_error", [errReason]), { command: args?.command, format: args?.format });
|
package/dist/src/cli_args.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { type DecisionOutputFormat } from "./util.ts";
|
|
1
|
+
import { type DecisionOutputFormat, type PacketOutputFormat } from "./util.ts";
|
|
2
2
|
export type ParsedArgs = {
|
|
3
3
|
command: string;
|
|
4
4
|
change: string;
|
|
5
5
|
format?: DecisionOutputFormat;
|
|
6
|
+
packet_format?: PacketOutputFormat;
|
|
6
7
|
artifact?: string;
|
|
7
8
|
gate?: string;
|
|
8
9
|
task_id?: string;
|
|
10
|
+
role?: string;
|
|
11
|
+
evidence_kind?: string;
|
|
12
|
+
round?: number;
|
|
9
13
|
create?: boolean;
|
|
10
14
|
force_unlock?: boolean;
|
|
11
15
|
rebuild_corrupt?: boolean;
|
package/dist/src/cli_args.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { command_zh } from "./i18n.js";
|
|
2
|
-
import { GuardError, parseDecisionOutputFormat } from "./util.js";
|
|
2
|
+
import { GuardError, parseDecisionOutputFormat, parsePacketOutputFormat } from "./util.js";
|
|
3
|
+
import { normalize_gate } from "./openspec.js";
|
|
3
4
|
const SIMPLE_COMMANDS = [
|
|
4
5
|
"status",
|
|
5
6
|
"recompute",
|
|
@@ -19,9 +20,15 @@ const COMMANDS = [
|
|
|
19
20
|
"check-task-reopen",
|
|
20
21
|
"check-task-edit",
|
|
21
22
|
"check-task-complete",
|
|
23
|
+
"workflow-packet",
|
|
24
|
+
"review-packet",
|
|
25
|
+
"ledger-render",
|
|
22
26
|
];
|
|
23
27
|
const COMMAND_LIST = COMMANDS.join(",");
|
|
24
28
|
const COMMAND_CHOICES = COMMANDS.map((item) => `'${item}'`).join(", ");
|
|
29
|
+
function isPacketCommand(command) {
|
|
30
|
+
return command === "workflow-packet" || command === "review-packet" || command === "ledger-render";
|
|
31
|
+
}
|
|
25
32
|
function requiredValueFlags(command) {
|
|
26
33
|
const flags = ["--change"];
|
|
27
34
|
if (command === "check-artifact")
|
|
@@ -30,14 +37,43 @@ function requiredValueFlags(command) {
|
|
|
30
37
|
flags.push("--gate");
|
|
31
38
|
if (command === "check-task-reopen" || command === "check-task-edit" || command === "check-task-complete")
|
|
32
39
|
flags.push("--task-id");
|
|
40
|
+
if (command === "workflow-packet")
|
|
41
|
+
flags.push("--gate");
|
|
42
|
+
if (command === "review-packet")
|
|
43
|
+
flags.push("--gate", "--role", "--round");
|
|
44
|
+
if (command === "ledger-render")
|
|
45
|
+
flags.push("--gate");
|
|
33
46
|
return flags;
|
|
34
47
|
}
|
|
35
48
|
function requiredBooleanFlags(command) {
|
|
36
49
|
return command === "init" ? ["--create"] : [];
|
|
37
50
|
}
|
|
38
51
|
function optionalBooleanFlags(command) {
|
|
52
|
+
if (isPacketCommand(command))
|
|
53
|
+
return [];
|
|
39
54
|
return ["--user-facing", ...(command === "recompute" ? ["--force-unlock", "--rebuild-corrupt"] : [])];
|
|
40
55
|
}
|
|
56
|
+
function optionalValueFlags(command) {
|
|
57
|
+
if (command === "workflow-packet")
|
|
58
|
+
return ["--task-id"];
|
|
59
|
+
if (command === "review-packet")
|
|
60
|
+
return ["--kind"];
|
|
61
|
+
if (command === "ledger-render")
|
|
62
|
+
return ["--round"];
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
function formatUsage(command) {
|
|
66
|
+
if (command === "workflow-packet")
|
|
67
|
+
return "--format {agent}";
|
|
68
|
+
if (command === "review-packet")
|
|
69
|
+
return "--format {agent,prompt}";
|
|
70
|
+
if (command === "ledger-render")
|
|
71
|
+
return null;
|
|
72
|
+
return "[--format {json,agent,user}]";
|
|
73
|
+
}
|
|
74
|
+
function requiresFormat(command) {
|
|
75
|
+
return command === "workflow-packet" || command === "review-packet";
|
|
76
|
+
}
|
|
41
77
|
function rootUsage() {
|
|
42
78
|
return `usage: superspec_guard [-h]\n {${COMMAND_LIST}}\n ...\n`;
|
|
43
79
|
}
|
|
@@ -52,7 +88,8 @@ function commandUsage(command) {
|
|
|
52
88
|
const usageFlags = [
|
|
53
89
|
"[-h]",
|
|
54
90
|
...requiredValueFlags(command).map((flag) => `${flag} ${flag.slice(2).replace(/-/g, "_").toUpperCase()}`),
|
|
55
|
-
|
|
91
|
+
...(formatUsage(command) ? [formatUsage(command)] : []),
|
|
92
|
+
...optionalValueFlags(command).map((flag) => `[${flag} ${flag.slice(2).replace(/-/g, "_").toUpperCase()}]`),
|
|
56
93
|
...requiredBooleanFlags(command),
|
|
57
94
|
...optionalBooleanFlags(command),
|
|
58
95
|
];
|
|
@@ -68,7 +105,13 @@ function commandHelp(command) {
|
|
|
68
105
|
for (const flag of requiredBooleanFlags(command)) {
|
|
69
106
|
lines.push(` ${flag}\n`);
|
|
70
107
|
}
|
|
71
|
-
|
|
108
|
+
const formatToken = formatUsage(command);
|
|
109
|
+
if (formatToken)
|
|
110
|
+
lines.push(` ${formatToken}\n`);
|
|
111
|
+
for (const flag of optionalValueFlags(command)) {
|
|
112
|
+
const metavariable = flag.slice(2).replace(/-/g, "_").toUpperCase();
|
|
113
|
+
lines.push(` ${flag} ${metavariable}\n`);
|
|
114
|
+
}
|
|
72
115
|
for (const flag of optionalBooleanFlags(command)) {
|
|
73
116
|
lines.push(` ${flag}\n`);
|
|
74
117
|
}
|
|
@@ -78,7 +121,10 @@ function hasFlag(argv, flag) {
|
|
|
78
121
|
return argv.includes(flag);
|
|
79
122
|
}
|
|
80
123
|
function missingRequiredFlags(command, args) {
|
|
81
|
-
|
|
124
|
+
const missing = [...requiredValueFlags(command), ...requiredBooleanFlags(command)].filter((flag) => !hasFlag(args, flag));
|
|
125
|
+
if (requiresFormat(command) && !hasFlag(args, "--format"))
|
|
126
|
+
missing.push("--format");
|
|
127
|
+
return missing;
|
|
82
128
|
}
|
|
83
129
|
export function emitArgparsePreamble(argv) {
|
|
84
130
|
if (argv.length === 0) {
|
|
@@ -99,10 +145,12 @@ export function emitArgparsePreamble(argv) {
|
|
|
99
145
|
process.stdout.write(commandHelp(command));
|
|
100
146
|
return 0;
|
|
101
147
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
148
|
+
if (!isPacketCommand(command)) {
|
|
149
|
+
const missing = missingRequiredFlags(command, args);
|
|
150
|
+
if (missing.length > 0) {
|
|
151
|
+
process.stderr.write(`${commandUsage(command)}superspec_guard ${command}:错误:缺少必填参数:${missing.join(", ")}\n`);
|
|
152
|
+
return 2;
|
|
153
|
+
}
|
|
106
154
|
}
|
|
107
155
|
return null;
|
|
108
156
|
}
|
|
@@ -125,15 +173,26 @@ export function parse_argv(argv) {
|
|
|
125
173
|
};
|
|
126
174
|
const getValue = (flag) => getValues(flag)[0];
|
|
127
175
|
const formatValues = getValues("--format");
|
|
128
|
-
|
|
129
|
-
|
|
176
|
+
const isPacketOutputCommand = command === "workflow-packet" || command === "review-packet";
|
|
177
|
+
const isPacketCommand = isPacketOutputCommand || command === "ledger-render";
|
|
178
|
+
const selectedPacketFormat = formatValues.length > 0 ? formatValues[formatValues.length - 1] : undefined;
|
|
179
|
+
if (isPacketOutputCommand) {
|
|
180
|
+
if (!selectedPacketFormat)
|
|
181
|
+
throw new GuardError("缺少必填参数 --format");
|
|
182
|
+
for (const value of formatValues)
|
|
183
|
+
parsePacketOutputFormat(value, { allowPrompt: command === "review-packet" });
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
for (const value of formatValues)
|
|
187
|
+
parseDecisionOutputFormat(value);
|
|
188
|
+
}
|
|
130
189
|
const selectedFormat = hasFlag(args, "--user-facing")
|
|
131
190
|
? "user"
|
|
132
191
|
: (formatValues.length > 0 ? formatValues[formatValues.length - 1] : "json");
|
|
133
|
-
const format = parseDecisionOutputFormat(selectedFormat);
|
|
192
|
+
const format = isPacketCommand ? undefined : parseDecisionOutputFormat(selectedFormat);
|
|
134
193
|
const change = getValue("--change");
|
|
135
194
|
if (!change)
|
|
136
|
-
throw new Error("缺少必填参数 --change");
|
|
195
|
+
throw new (isPacketCommand ? GuardError : Error)("缺少必填参数 --change");
|
|
137
196
|
if (command === "init") {
|
|
138
197
|
if (!hasFlag(args, "--create"))
|
|
139
198
|
throw new Error("缺少必填参数 --create");
|
|
@@ -151,6 +210,56 @@ export function parse_argv(argv) {
|
|
|
151
210
|
throw new Error("缺少必填参数 --gate");
|
|
152
211
|
return { command, change, format, gate };
|
|
153
212
|
}
|
|
213
|
+
if (command === "workflow-packet") {
|
|
214
|
+
const gate = getValue("--gate");
|
|
215
|
+
if (!gate)
|
|
216
|
+
throw new GuardError("缺少必填参数 --gate");
|
|
217
|
+
const normalizedGate = normalize_gate(gate);
|
|
218
|
+
const taskId = getValue("--task-id");
|
|
219
|
+
if ((normalizedGate === "task_edit" || normalizedGate === "task_complete" || normalizedGate === "task_reopen") && !taskId) {
|
|
220
|
+
throw new GuardError("workflow-packet 缺少必填参数 --task-id");
|
|
221
|
+
}
|
|
222
|
+
return { command, change, gate, task_id: taskId, packet_format: parsePacketOutputFormat(selectedPacketFormat, { allowPrompt: false }) };
|
|
223
|
+
}
|
|
224
|
+
if (command === "review-packet") {
|
|
225
|
+
const gate = getValue("--gate");
|
|
226
|
+
const role = getValue("--role");
|
|
227
|
+
const roundValue = getValue("--round");
|
|
228
|
+
const evidenceKind = getValue("--kind");
|
|
229
|
+
if (!gate)
|
|
230
|
+
throw new GuardError("缺少必填参数 --gate");
|
|
231
|
+
if (!role)
|
|
232
|
+
throw new GuardError("缺少必填参数 --role");
|
|
233
|
+
if (!roundValue)
|
|
234
|
+
throw new GuardError("缺少必填参数 --round");
|
|
235
|
+
if (evidenceKind !== undefined && evidenceKind !== "source_guidance" && evidenceKind !== "verification_review") {
|
|
236
|
+
throw new GuardError("--kind 只允许 source_guidance 或 verification_review");
|
|
237
|
+
}
|
|
238
|
+
const round = Number.parseInt(roundValue, 10);
|
|
239
|
+
if (!Number.isInteger(round) || round < 1)
|
|
240
|
+
throw new GuardError("--round 必须是大于等于 1 的整数");
|
|
241
|
+
return {
|
|
242
|
+
command,
|
|
243
|
+
change,
|
|
244
|
+
gate,
|
|
245
|
+
role,
|
|
246
|
+
evidence_kind: evidenceKind,
|
|
247
|
+
round,
|
|
248
|
+
packet_format: parsePacketOutputFormat(selectedPacketFormat, { allowPrompt: true }),
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
if (command === "ledger-render") {
|
|
252
|
+
const gate = getValue("--gate");
|
|
253
|
+
const roundValue = getValue("--round");
|
|
254
|
+
if (!gate)
|
|
255
|
+
throw new GuardError("缺少必填参数 --gate");
|
|
256
|
+
if (roundValue === undefined)
|
|
257
|
+
return { command, change, gate };
|
|
258
|
+
const round = Number.parseInt(roundValue, 10);
|
|
259
|
+
if (!Number.isInteger(round) || round < 1)
|
|
260
|
+
throw new GuardError("--round 必须是大于等于 1 的整数");
|
|
261
|
+
return { command, change, gate, round };
|
|
262
|
+
}
|
|
154
263
|
if (command === "check-task-reopen" || command === "check-task-edit" || command === "check-task-complete") {
|
|
155
264
|
const taskId = getValue("--task-id");
|
|
156
265
|
if (!taskId)
|
package/dist/src/gates.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Decision, JsonMap, Reason } from "./util.ts";
|
|
2
|
-
export declare function openspec_init_reasons(
|
|
2
|
+
export declare function openspec_init_reasons(_repoRoot: string): Reason[];
|
|
3
3
|
export declare function superspec_workflow_skill_reasons(repoRoot: string): Reason[];
|
|
4
4
|
export declare function superspec_agent_reasons(repoRoot: string): Reason[];
|
|
5
5
|
export declare function openspec_cli_capability_reasons(): Reason[];
|
package/dist/src/gates.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { join, relative } from "node:path";
|
|
3
|
-
import { ARTIFACT_ENTER_GATE, MAIN_ADJUDICATION_DECISIONS, REQUEST_CHANGES_ROUTES, NO_TDD_REASONS, OPENSPEC_ARTIFACTS, FINAL_VERIFICATION_ROLES, REQUIRED_SUPERSPEC_AGENT_ROLES, REQUIRED_SUPERSPEC_WORKFLOW_SKILLS,
|
|
3
|
+
import { ARTIFACT_ENTER_GATE, MAIN_ADJUDICATION_DECISIONS, REQUEST_CHANGES_ROUTES, NO_TDD_REASONS, OPENSPEC_ARTIFACTS, FINAL_VERIFICATION_ROLES, REQUIRED_SUPERSPEC_AGENT_ROLES, REQUIRED_SUPERSPEC_WORKFLOW_SKILLS, REVIEW_GUIDANCE_ROLES, REVIEW_EVIDENCE_REQUIRED_FIELDS, TDD_MODES, VERIFY_EVIDENCE_REQUIRED_FIELDS, allow, block, isObject, reason, renderList, repr, pinned_ref_key, safe_within, sha256_text, runtime, toPosix, } from "./util.js";
|
|
4
4
|
import { all_done, artifact_status_map, get_repo_root, is_done, normalize_gate, openspec_cli_probe } from "./openspec.js";
|
|
5
5
|
import { read_agent_toml_name, read_skill_frontmatter_name, sidecar_business_invariants_path, sidecar_discovery_path, sidecar_test_contract_path } from "./paths.js";
|
|
6
6
|
import { business_invariant_ids, business_invariant_validation_reasons, automated_hard_business_invariant_ids, evidence_invariant_refs, evidence_invariant_ref_reasons, evidence_test_contract_invariant_reasons, human_confirmation_business_invariant_ids, invariant_matrix_coverage_reasons, post_implementation_business_invariant_ids, red_green_invariant_ids, test_contract_invariant_ids, } from "./invariants.js";
|
|
@@ -330,24 +330,8 @@ function default_gate_next_actions(gate) {
|
|
|
330
330
|
return [];
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
|
-
export function openspec_init_reasons(
|
|
334
|
-
|
|
335
|
-
reasons.push(...runtime.openspec_cli_capability_reasons());
|
|
336
|
-
const skillsRoot = join(repoRoot, ".codex", "skills");
|
|
337
|
-
const missing = REQUIRED_OPENSPEC_CODEX_SKILLS.filter((name) => !existsSync(join(skillsRoot, name, "SKILL.md")));
|
|
338
|
-
if (missing.length > 0) {
|
|
339
|
-
reasons.push(reason("openspec_init_missing", "OpenSpec native Codex skills are missing; run `openspec init --tools codex .` or `openspec update --force .` from the repository root", missing));
|
|
340
|
-
}
|
|
341
|
-
for (const name of REQUIRED_OPENSPEC_CODEX_SKILLS) {
|
|
342
|
-
const skillPath = join(skillsRoot, name, "SKILL.md");
|
|
343
|
-
if (!existsSync(skillPath))
|
|
344
|
-
continue;
|
|
345
|
-
const declared = read_skill_frontmatter_name(skillPath);
|
|
346
|
-
if (declared !== name) {
|
|
347
|
-
reasons.push(reason("openspec_native_surface_invalid", `OpenSpec native skill ${skillPath} has invalid front matter name ${repr(declared)}`, [skillPath]));
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
return reasons;
|
|
333
|
+
export function openspec_init_reasons(_repoRoot) {
|
|
334
|
+
return runtime.openspec_cli_capability_reasons();
|
|
351
335
|
}
|
|
352
336
|
// D4 (audit G-2): check-init must notice when SuperSpec's own workflow skills are missing or
|
|
353
337
|
// corrupted, otherwise a deleted .codex/skills/superspec-* surface stays invisible end to end.
|
package/dist/src/i18n.js
CHANGED
|
@@ -9,6 +9,9 @@ const COMMAND_ZH = {
|
|
|
9
9
|
"check-task-reopen": { label_zh: "任务重开检查", hint_zh: "检查被审查打回的任务是否满足重开条件。" },
|
|
10
10
|
"check-task-edit": { label_zh: "任务编辑前检查", hint_zh: "检查任务在开始实现前是否满足测试与范围前置条件。" },
|
|
11
11
|
"check-task-complete": { label_zh: "任务完成检查", hint_zh: "检查任务在勾完成前是否满足 GREEN 或替代验证要求。" },
|
|
12
|
+
"workflow-packet": { label_zh: "流程数据包", hint_zh: "只读生成当前流程 gate 的紧凑执行数据包。" },
|
|
13
|
+
"review-packet": { label_zh: "审查数据包", hint_zh: "只读生成审查角色或主线程的最小任务包。" },
|
|
14
|
+
"ledger-render": { label_zh: "问题清单渲染", hint_zh: "渲染审查轮次的确定性问题清单文本。" },
|
|
12
15
|
"check-review-ready": { label_zh: "进入审查前检查", hint_zh: "检查实现阶段是否已经处理完成,可以进入审查阶段。" },
|
|
13
16
|
"check-review-complete": { label_zh: "审查完成检查", hint_zh: "检查审查阶段证据是否齐备并允许通过。" },
|
|
14
17
|
"check-verify-ready": { label_zh: "验证完成检查", hint_zh: "检查最终验证证据是否完整。" },
|
|
@@ -583,10 +586,8 @@ export function action_status_zh(status) {
|
|
|
583
586
|
}
|
|
584
587
|
export function action_label_zh(action) {
|
|
585
588
|
const exact = {
|
|
586
|
-
|
|
589
|
+
openspec_cli_surface: "检查 OpenSpec CLI 能力",
|
|
587
590
|
superspec_repo_local_roles: "检查 SuperSpec 本地角色与提示词",
|
|
588
|
-
"openspec init --tools codex .": "运行 OpenSpec 初始化命令",
|
|
589
|
-
"openspec update --force .": "运行 OpenSpec 更新命令",
|
|
590
591
|
};
|
|
591
592
|
if (exact[action])
|
|
592
593
|
return exact[action];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type MeasuredTextFile = {
|
|
2
|
+
path: string;
|
|
3
|
+
chars: number;
|
|
4
|
+
};
|
|
5
|
+
export type SurfaceMeasure = {
|
|
6
|
+
total_chars: number;
|
|
7
|
+
files: MeasuredTextFile[];
|
|
8
|
+
};
|
|
9
|
+
export type RepresentativeScenarioMeasure = {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
total_chars: number;
|
|
13
|
+
files: MeasuredTextFile[];
|
|
14
|
+
};
|
|
15
|
+
export type MaterializedTextSample = {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
chars: number;
|
|
19
|
+
matched_markers?: string[];
|
|
20
|
+
};
|
|
21
|
+
export type MaterializedTextMeasure = {
|
|
22
|
+
total_chars: number;
|
|
23
|
+
samples: MaterializedTextSample[];
|
|
24
|
+
};
|
|
25
|
+
export type PacketMeasureReport = {
|
|
26
|
+
fixed_surface_chars_install_upper_bound: SurfaceMeasure;
|
|
27
|
+
fixed_surface_chars_runtime_required_subset: SurfaceMeasure;
|
|
28
|
+
materialized_workflow_packet_chars: MaterializedTextMeasure;
|
|
29
|
+
materialized_review_packet_chars: MaterializedTextMeasure;
|
|
30
|
+
materialized_review_prompt_chars: MaterializedTextMeasure;
|
|
31
|
+
ledger_block_chars: MaterializedTextMeasure;
|
|
32
|
+
representative_loaded_surface_chars: {
|
|
33
|
+
scenarios: RepresentativeScenarioMeasure[];
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
type ScenarioSpec = {
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
files: string[];
|
|
40
|
+
};
|
|
41
|
+
export declare function representative_scenarios(): readonly ScenarioSpec[];
|
|
42
|
+
export declare function measure_packet_surface_report(repoRoot: string): PacketMeasureReport;
|
|
43
|
+
export {};
|