@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.
Files changed (31) hide show
  1. package/adapters/codex/agents/architect.toml +4 -148
  2. package/adapters/codex/agents/code-reviewer.toml +4 -166
  3. package/adapters/codex/agents/critic.toml +5 -106
  4. package/adapters/codex/agents/test-engineer.toml +4 -154
  5. package/adapters/codex/agents/verifier.toml +4 -110
  6. package/dist/src/cli.js +13 -0
  7. package/dist/src/cli_args.d.ts +5 -1
  8. package/dist/src/cli_args.js +121 -12
  9. package/dist/src/gates.d.ts +1 -1
  10. package/dist/src/gates.js +3 -19
  11. package/dist/src/i18n.js +4 -3
  12. package/dist/src/packet_measure.d.ts +43 -0
  13. package/dist/src/packet_measure.js +395 -0
  14. package/dist/src/packet_render.d.ts +4 -0
  15. package/dist/src/packet_render.js +652 -0
  16. package/dist/src/packet_schema.d.ts +55 -0
  17. package/dist/src/packet_schema.js +1 -0
  18. package/dist/src/project_init.js +7 -49
  19. package/dist/src/util.d.ts +10 -2
  20. package/dist/src/util.js +24 -6
  21. package/package.json +2 -2
  22. package/templates/workflow/prompts/architect.md +16 -109
  23. package/templates/workflow/prompts/code-reviewer.md +17 -137
  24. package/templates/workflow/prompts/critic.md +18 -75
  25. package/templates/workflow/prompts/test-engineer.md +16 -126
  26. package/templates/workflow/prompts/verifier.md +17 -80
  27. package/templates/workflow/skills/superspec-apply/SKILL.md +64 -78
  28. package/templates/workflow/skills/superspec-archive/SKILL.md +41 -37
  29. package/templates/workflow/skills/superspec-explore/SKILL.md +63 -77
  30. package/templates/workflow/skills/superspec-propose/SKILL.md +64 -85
  31. 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
- <identity>
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
- <goal>
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
- <constraints>
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
- <ask_gate>
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 });
@@ -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;
@@ -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
- "[--format {json,agent,user}]",
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
- lines.push(" --format {json,agent,user}\n");
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
- return [...requiredValueFlags(command), ...requiredBooleanFlags(command)].filter((flag) => !hasFlag(args, flag));
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
- const missing = missingRequiredFlags(command, args);
103
- if (missing.length > 0) {
104
- process.stderr.write(`${commandUsage(command)}superspec_guard ${command}:错误:缺少必填参数:${missing.join(", ")}\n`);
105
- return 2;
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
- for (const value of formatValues)
129
- parseDecisionOutputFormat(value);
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)
@@ -1,5 +1,5 @@
1
1
  import type { Decision, JsonMap, Reason } from "./util.ts";
2
- export declare function openspec_init_reasons(repoRoot: string): Reason[];
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, REQUIRED_OPENSPEC_CODEX_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";
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(repoRoot) {
334
- const reasons = [];
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
- openspec_codex_skills: "检查 OpenSpec 配套技能文件",
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 {};