@peterxiaoyang/superspec 0.1.11 → 0.1.12
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 +4 -4
- package/dist/src/apply_worker_chain.d.ts +6 -3
- package/dist/src/apply_worker_chain.js +125 -30
- package/dist/src/apply_worker_chain_lifecycle.d.ts +7 -5
- package/dist/src/apply_worker_chain_lifecycle.js +153 -22
- package/dist/src/cli_args.d.ts +1 -0
- package/dist/src/cli_args.js +33 -15
- package/dist/src/disclosure.js +2 -2
- package/dist/src/evidence.js +104 -8
- package/dist/src/gates.d.ts +1 -0
- package/dist/src/gates.js +160 -27
- package/dist/src/hooks/guard_api.js +2 -2
- package/dist/src/hooks/policy_event.js +11 -1
- package/dist/src/i18n.js +63 -3
- package/dist/src/init_cli.js +1 -1
- package/dist/src/openspec.d.ts +2 -0
- package/dist/src/openspec.js +31 -0
- package/dist/src/packet_render.d.ts +1 -0
- package/dist/src/packet_render.js +248 -31
- package/dist/src/packet_schema.d.ts +2 -0
- package/dist/src/tasks.d.ts +5 -0
- package/dist/src/tasks.js +62 -0
- package/dist/src/util.d.ts +4 -0
- package/dist/src/util.js +13 -0
- package/dist/superspec.js +4 -4
- package/package.json +3 -3
- package/templates/sidecar/discovery.md +9 -0
- package/templates/sidecar/test-contract.md +2 -1
- package/templates/workflow/prompts/code-reviewer.md +1 -1
- package/templates/workflow/prompts/executor.md +1 -1
- package/templates/workflow/prompts/test-engineer.md +1 -0
- package/templates/workflow/prompts/test-runner.md +3 -1
- package/templates/workflow/prompts/verifier.md +9 -9
- package/templates/workflow/skills/superspec-apply/SKILL.md +58 -33
- package/templates/workflow/skills/superspec-archive/SKILL.md +5 -5
- package/templates/workflow/skills/superspec-explore/SKILL.md +18 -12
- package/templates/workflow/skills/superspec-propose/SKILL.md +26 -15
- package/templates/workflow/skills/superspec-review/SKILL.md +17 -17
- package/dist/src/packet_measure.d.ts +0 -43
- package/dist/src/packet_measure.js +0 -382
- /package/bin/{superspec-guard.js → superspec-check.js} +0 -0
|
@@ -457,7 +457,7 @@ export function hookCheckWrite(change, eventRef) {
|
|
|
457
457
|
block_reasons: blockReasons,
|
|
458
458
|
audit_only_reasons: auditOnlyReasons,
|
|
459
459
|
target_paths: intent.target_paths,
|
|
460
|
-
next_allowed_actions: ["rerun the relevant superspec
|
|
460
|
+
next_allowed_actions: ["rerun the relevant superspec check and use the expected workflow command surface"],
|
|
461
461
|
});
|
|
462
462
|
}
|
|
463
463
|
return hookDecision(ctx, "hook_check_write", true, {
|
|
@@ -510,7 +510,7 @@ export function hookCheckWrite(change, eventRef) {
|
|
|
510
510
|
block_reasons: blockReasons,
|
|
511
511
|
audit_only_reasons: auditOnlyReasons,
|
|
512
512
|
target_paths: intent.target_paths,
|
|
513
|
-
next_allowed_actions: ["rerun the relevant superspec
|
|
513
|
+
next_allowed_actions: ["rerun the relevant superspec check and use the expected workflow command surface"],
|
|
514
514
|
});
|
|
515
515
|
}
|
|
516
516
|
return hookDecision(ctx, "hook_check_write", true, {
|
|
@@ -2340,7 +2340,9 @@ function tokenAtSameCommand(tokens, idx) {
|
|
|
2340
2340
|
return tokens[idx];
|
|
2341
2341
|
}
|
|
2342
2342
|
function isHookEntrypointName(name) {
|
|
2343
|
-
return name === "superspec-
|
|
2343
|
+
return name === "superspec-check"
|
|
2344
|
+
|| name === "superspec-check.js"
|
|
2345
|
+
|| name === "superspec-guard"
|
|
2344
2346
|
|| name === "superspec-guard.js"
|
|
2345
2347
|
|| name === "superspec-hook"
|
|
2346
2348
|
|| name === "superspec-hook.js";
|
|
@@ -2392,9 +2394,13 @@ function commandLooksLikeInternalHookWriter(command, depth = 0) {
|
|
|
2392
2394
|
return true;
|
|
2393
2395
|
if (next === "guard" && afterNext?.startsWith("hook-record-"))
|
|
2394
2396
|
return true;
|
|
2397
|
+
if (next === "check" && afterNext?.startsWith("hook-record-"))
|
|
2398
|
+
return true;
|
|
2395
2399
|
}
|
|
2396
2400
|
if (name === "superspec-guard" && tokenAtSameCommand(tokens, commandIdx + 1)?.startsWith("hook-record-"))
|
|
2397
2401
|
return true;
|
|
2402
|
+
if (name === "superspec-check" && tokenAtSameCommand(tokens, commandIdx + 1)?.startsWith("hook-record-"))
|
|
2403
|
+
return true;
|
|
2398
2404
|
if (isHookAdapterEntrypointName(name))
|
|
2399
2405
|
return true;
|
|
2400
2406
|
if (isHookEntrypointName(name) && tokenAtSameCommand(tokens, commandIdx + 1)?.startsWith("hook-record-"))
|
|
@@ -2442,6 +2448,10 @@ function commandLooksLikeUnsafeLifecycleTermination(command, depth = 0) {
|
|
|
2442
2448
|
if (segmentHasDangerousReason(commandIdx + 3, segmentEnd))
|
|
2443
2449
|
return true;
|
|
2444
2450
|
}
|
|
2451
|
+
if (token === "superspec" && tokens[commandIdx + 1] === "check" && tokens[commandIdx + 2] === "hook-session-end") {
|
|
2452
|
+
if (segmentHasDangerousReason(commandIdx + 3, segmentEnd))
|
|
2453
|
+
return true;
|
|
2454
|
+
}
|
|
2445
2455
|
if (token === "superspec" && tokens[commandIdx + 1] === "hook-session-end") {
|
|
2446
2456
|
if (segmentHasDangerousReason(commandIdx + 2, segmentEnd))
|
|
2447
2457
|
return true;
|
package/dist/src/i18n.js
CHANGED
|
@@ -73,6 +73,7 @@ const REASON_ZH = {
|
|
|
73
73
|
invalid_tdd_mode: { label_zh: "TDD 模式无效", hint_zh: "task 上声明的 tdd_mode 不在允许枚举里。" },
|
|
74
74
|
invalid_no_tdd_reason: { label_zh: "免 TDD 理由无效", hint_zh: "task 上声明的 no_tdd_reason 不在允许枚举里。" },
|
|
75
75
|
missing_discovery: { label_zh: "缺少探索记录", hint_zh: "探索阶段缺少 discovery.md,或者该文件内容为空。" },
|
|
76
|
+
explore_open_questions_unresolved: { label_zh: "探索待确认问题未清空", hint_zh: "discovery.md 的待确认问题还有未勾选或「仍需确认」的项,需要逐条与用户确认并改成已确认后才能进入 propose。" },
|
|
76
77
|
missing_proposal: { label_zh: "缺少提案工件", hint_zh: "提案工件还没有完成。" },
|
|
77
78
|
missing_proposal_review: { label_zh: "缺少提案审查", hint_zh: "提案审查阶段还没有收集到严格审查证据。" },
|
|
78
79
|
explore_complete_failed: { label_zh: "探索阶段未通过", hint_zh: "后续阶段依赖的探索完成检查还没有通过。" },
|
|
@@ -95,6 +96,65 @@ const REASON_ZH = {
|
|
|
95
96
|
user_uninstall_failed: { label_zh: "用户级卸载失败", hint_zh: "用户级 SuperSpec 卸载失败。" },
|
|
96
97
|
guard_error: { label_zh: "检查执行失败", hint_zh: "guard 命令执行过程中发生了可报告错误。" },
|
|
97
98
|
guard_internal_error: { label_zh: "检查器内部错误", hint_zh: "guard 内部抛出了异常,需要查看错误信息排查。" },
|
|
99
|
+
"apply_worker_chain_active": { label_zh: "活跃工作链存在", hint_zh: "当前任务已有活跃的 apply worker chain。" },
|
|
100
|
+
"apply_worker_chain_active_conflict": { label_zh: "活跃工作链冲突", hint_zh: "存在多条活跃 apply worker chain,需要先收敛到一条。" },
|
|
101
|
+
"apply_worker_chain_missing_active": { label_zh: "缺少活跃工作链", hint_zh: "当前任务没有活跃的 apply worker chain,需要先启动。" },
|
|
102
|
+
"apply_worker_chain_terminal_conflict": { label_zh: "工作链终态冲突", hint_zh: "存在多条终态 apply worker chain,需要先收敛。" },
|
|
103
|
+
"archive_not_found": { label_zh: "归档未找到", hint_zh: "没有找到已归档的 change,确认归档是否完成。" },
|
|
104
|
+
"bash_write_target_unknown": { label_zh: "Bash 写入目标未知", hint_zh: "Bash 命令的写入目标无法识别,需要明确目标路径。" },
|
|
105
|
+
"curl_config_write_target_unknown": { label_zh: "curl 配置写入目标未知", hint_zh: "curl 配置类命令的写入目标无法识别。" },
|
|
106
|
+
"curl_write_target_unknown": { label_zh: "curl 写入目标未知", hint_zh: "curl 命令的写入目标无法识别。" },
|
|
107
|
+
"custom_superspec_schema_present": { label_zh: "自定义 schema 存在", hint_zh: "检测到自定义 OpenSpec schema,SuperSpec 只支持默认 spec-driven。" },
|
|
108
|
+
"dangling_evidence_ref": { label_zh: "证据引用悬空", hint_zh: "evidence 引用的 evidence_id 不存在,检查引用或恢复被删证据。" },
|
|
109
|
+
"dirty_worktree_unattributed": { label_zh: "脏工作区未归属", hint_zh: "工作区有改动但无法归因到当前 change,需要先确认归属。" },
|
|
110
|
+
"duplicate_test_command": { label_zh: "测试命令重复", hint_zh: "检测到重复的测试命令声明。" },
|
|
111
|
+
"evidence_bad_status": { label_zh: "证据状态非法", hint_zh: "evidence 的 status 字段不在合法枚举内。" },
|
|
112
|
+
"evidence_forbidden_field": { label_zh: "证据含禁止字段", hint_zh: "evidence 包含当前 kind 不允许的字段。" },
|
|
113
|
+
"evidence_missing_field": { label_zh: "证据缺字段", hint_zh: "evidence 缺少必需字段。" },
|
|
114
|
+
"evidence_unknown_kind": { label_zh: "证据 kind 未知", hint_zh: "evidence 的 kind 不在白名单内。" },
|
|
115
|
+
"evidence_unparsable": { label_zh: "证据不可解析", hint_zh: "evidence 文件不是合法 JSON。" },
|
|
116
|
+
"evidence_unsafe_ref": { label_zh: "证据引用不安全", hint_zh: "evidence 的引用路径逃逸了允许范围。" },
|
|
117
|
+
"forbidden_alias_path": { label_zh: "禁用别名路径", hint_zh: "使用了被禁用的配置或状态文件别名。" },
|
|
118
|
+
"hook_internal_writer_invocation": { label_zh: "内部写入命令被调用", hint_zh: "模型控制的工具调用不得触发 SuperSpec hook 写入命令。" },
|
|
119
|
+
"hook_manifest_missing_or_unmanaged": { label_zh: "hook manifest 缺失或不受管", hint_zh: ".codex/hooks.json 缺失或不是 SuperSpec 受管版本。" },
|
|
120
|
+
"hook_manifest_unmanaged": { label_zh: "hook manifest 不受管", hint_zh: ".codex/hooks.json 不是 SuperSpec 受管版本。" },
|
|
121
|
+
"hook_session_audit_only": { label_zh: "hook 会话仅审计", hint_zh: "当前 hook 会话是 audit-only,不能作为可信强制来源。" },
|
|
122
|
+
"hook_session_corrupt": { label_zh: "hook 会话损坏", hint_zh: "活跃 hook 会话记录损坏,需要重建。" },
|
|
123
|
+
"hook_session_expired": { label_zh: "hook 会话过期", hint_zh: "活跃 hook 会话已过期。" },
|
|
124
|
+
"hook_session_termination_untrusted": { label_zh: "hook 会话终止不可信", hint_zh: "会话终止来源不可信,不能关闭 lease。" },
|
|
125
|
+
"invariants_not_reviewed": { label_zh: "业务约束未审查", hint_zh: "business-invariants 尚未通过审查。" },
|
|
126
|
+
"mixed_request_changes_route": { label_zh: "混合返工路由", hint_zh: "request_changes 同时包含不一致的 route。" },
|
|
127
|
+
"openspec_canonical_direct_edit": { label_zh: "直接编辑 OpenSpec 正本", hint_zh: "不允许绕过 openspec instructions 直接编辑正本 artifact。" },
|
|
128
|
+
"openspec_status_incompatible": { label_zh: "OpenSpec 状态不兼容", hint_zh: "openspec status 输出与预期结构不一致。" },
|
|
129
|
+
"openspec_tasks_direct_edit": { label_zh: "直接编辑 tasks", hint_zh: "不允许绕过流程直接编辑 tasks.md。" },
|
|
130
|
+
"post_implementation_invariant_backfill": { label_zh: "实现后补不变量", hint_zh: "不允许在实现后才补业务不变量。" },
|
|
131
|
+
"protected_path_dirty": { label_zh: "受保护路径被改动", hint_zh: "受保护路径处于脏状态。" },
|
|
132
|
+
"protected_trust_root_link_source": { label_zh: "信任根符号链接", hint_zh: "信任根路径通过符号链接指向外部来源。" },
|
|
133
|
+
"protected_trust_root_write": { label_zh: "写入信任根", hint_zh: "不允许写入 SuperSpec 信任根路径。" },
|
|
134
|
+
"ref_empty": { label_zh: "引用为空", hint_zh: "引用字段为空字符串。" },
|
|
135
|
+
"ref_not_readable": { label_zh: "引用不可读", hint_zh: "引用指向的文件不可读。" },
|
|
136
|
+
"ref_path_unsafe": { label_zh: "引用路径不安全", hint_zh: "引用路径逃逸了允许的根。" },
|
|
137
|
+
"reopen_lifecycle_exhausted": { label_zh: "重开次数耗尽", hint_zh: "task reopen 的生命周期次数已用尽。" },
|
|
138
|
+
"required_claim_unadjudicated": { label_zh: "必需 claim 未裁决", hint_zh: "存在尚未裁决的必需 claim。" },
|
|
139
|
+
"review_diff_not_covered": { label_zh: "review 未覆盖 diff", hint_zh: "review 未覆盖当前 diff。" },
|
|
140
|
+
"runtime_evidence_missing_command_fingerprint": { label_zh: "运行时证据缺命令指纹", hint_zh: "runtime evidence 缺少 command fingerprint。" },
|
|
141
|
+
"runtime_evidence_missing_exit_code": { label_zh: "运行时证据缺退出码", hint_zh: "runtime evidence 缺少 exit code。" },
|
|
142
|
+
"runtime_evidence_missing_hook_event": { label_zh: "运行时证据缺 hook 事件", hint_zh: "runtime evidence 缺少可信 hook 事件。" },
|
|
143
|
+
"runtime_evidence_missing_raw_log_pin": { label_zh: "运行时证据缺日志锚定", hint_zh: "runtime evidence 缺少 raw log pinned refs。" },
|
|
144
|
+
"runtime_evidence_missing_token": { label_zh: "运行时证据缺 token", hint_zh: "runtime evidence 缺少绑定 token。" },
|
|
145
|
+
"runtime_evidence_untrusted_provenance": { label_zh: "运行时证据来源不可信", hint_zh: "runtime evidence 缺少可信 provenance。" },
|
|
146
|
+
"scope_expansion_requires_propose": { label_zh: "范围扩大需回 propose", hint_zh: "任务范围扩大需要回 propose 重新确认。" },
|
|
147
|
+
"self_review_not_allowed": { label_zh: "不允许自审", hint_zh: "主线程不能充当审查角色。" },
|
|
148
|
+
"shell_path_may_touch_trust_root": { label_zh: "shell 路径可能触及信任根", hint_zh: "shell 展开的路径可能触及 SuperSpec 信任根。" },
|
|
149
|
+
"superspec_not_preserved": { label_zh: "SuperSpec 记录未保全", hint_zh: "归档后 .superspec 记录未能从 preservation manifest 追溯。" },
|
|
150
|
+
"target_path_outside_repo": { label_zh: "写入目标在仓库外", hint_zh: "写入目标路径逃逸了仓库根。" },
|
|
151
|
+
"task_already_done": { label_zh: "任务已完成", hint_zh: "目标 task 已经勾选完成。" },
|
|
152
|
+
"test_id_not_in_log": { label_zh: "测试 id 不在日志中", hint_zh: "声称的 test_id 未出现在引用日志里。" },
|
|
153
|
+
"test_not_declared_for_task": { label_zh: "测试未为任务声明", hint_zh: "测试未在任务的 test_refs 中声明。" },
|
|
154
|
+
"untrusted_test_command_ref": { label_zh: "测试命令引用不可信", hint_zh: "测试命令引用来源不可信。" },
|
|
155
|
+
"unsafe_write_scope": { label_zh: "写范围不安全", hint_zh: "任务的 write_scope 包含不安全路径。" },
|
|
156
|
+
"unsupported_write_surface": { label_zh: "不支持的写入面", hint_zh: "当前面不支持该写入操作。" },
|
|
157
|
+
"write_scope_conflict": { label_zh: "写范围冲突", hint_zh: "多个任务的 write_scope 存在冲突。" },
|
|
98
158
|
};
|
|
99
159
|
const WORKFLOW_TERMS_ZH = {
|
|
100
160
|
"check-enter": { term: "check-enter", label_zh: "进入阶段前检查", hint_zh: "进入某个流程阶段前先运行的检查命令。" },
|
|
@@ -110,9 +170,9 @@ const TRUST_WARNING_ZH = {
|
|
|
110
170
|
"project init installs project surfaces only; change sidecars are created lazily by later superspec phases": "project init 只安装项目级内容;change sidecar 会在后续 superspec 阶段按需创建。",
|
|
111
171
|
};
|
|
112
172
|
const ACTION_ZH_EXACT = {
|
|
113
|
-
"continue with superspec-explore/propose/apply
|
|
114
|
-
"create/select a change during superspec-explore, then run change-scoped
|
|
115
|
-
"review *.new files for user-modified surfaces, then rerun superspec
|
|
173
|
+
"continue with superspec-explore/propose/apply check checks": "继续执行探索、提案和实现阶段的前置检查。",
|
|
174
|
+
"create/select a change during superspec-explore, then run change-scoped check checks": "先在探索阶段创建或选择一个变更,然后运行该变更范围内的前置检查。",
|
|
175
|
+
"review *.new files for user-modified surfaces, then rerun superspec check check-init": "先检查因用户改动而生成的 *.new 文件,然后重新运行初始化前置检查;Windows PowerShell 中使用 superspec.cmd check check-init。",
|
|
116
176
|
"review *.new files for user-modified user-level surfaces": "先检查用户级内容对应的 *.new 文件。",
|
|
117
177
|
"user-level SuperSpec Codex surfaces installed; use superspec init --scope project inside a repo when project-local surfaces are needed": "用户级 SuperSpec 配套内容已安装;如果仓库里还需要项目级内容,请在仓库内运行 superspec init --scope project;Windows PowerShell 中使用 superspec.cmd init --scope project。",
|
|
118
178
|
"finish remaining unchecked tasks and mark them complete only after check-task-complete passes": "先完成剩余未勾选任务,并且仅在任务完成检查通过后再标记完成。",
|
package/dist/src/init_cli.js
CHANGED
|
@@ -318,7 +318,7 @@ function run_init(args, scope) {
|
|
|
318
318
|
}
|
|
319
319
|
else if (args.mode === "update") {
|
|
320
320
|
summary = engineDecision(`${gatePrefix}_update`, targetRoot, update_workflow(targetRoot, { scope }), [
|
|
321
|
-
scope === "project" ? "review *.new files for user-modified surfaces, then rerun superspec
|
|
321
|
+
scope === "project" ? "review *.new files for user-modified surfaces, then rerun superspec check check-init" : "review *.new files for user-modified user-level surfaces",
|
|
322
322
|
]);
|
|
323
323
|
}
|
|
324
324
|
else if (scope === "user") {
|
package/dist/src/openspec.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export declare function all_done(status: JsonMap): boolean;
|
|
|
27
27
|
export declare function openspec_floor_route(status: JsonMap): string;
|
|
28
28
|
export declare function normalize_route_phase(route: string): string;
|
|
29
29
|
export declare function normalize_gate(gate: string): string;
|
|
30
|
+
export declare function authorized_supersede_target_ids(evidences: JsonMap[]): Set<string>;
|
|
31
|
+
export declare function effective_superseded_ids(evidences: JsonMap[]): Set<string>;
|
|
30
32
|
export declare function gate_route_phase(gate: string): string;
|
|
31
33
|
export declare function effective_route_phase(status: JsonMap, requestedRoute: string, decision: JsonMap): string;
|
|
32
34
|
export declare function status_fingerprint(status: JsonMap): string;
|
package/dist/src/openspec.js
CHANGED
|
@@ -188,6 +188,37 @@ export function normalize_route_phase(route) {
|
|
|
188
188
|
export function normalize_gate(gate) {
|
|
189
189
|
return GATE_ALIASES[gate] ?? gate;
|
|
190
190
|
}
|
|
191
|
+
export function authorized_supersede_target_ids(evidences) {
|
|
192
|
+
const byId = new Map();
|
|
193
|
+
for (const ev of evidences) {
|
|
194
|
+
if (!isObject(ev) || ev._invalid)
|
|
195
|
+
continue;
|
|
196
|
+
const id = typeof ev.evidence_id === "string" ? ev.evidence_id : "";
|
|
197
|
+
if (id && !byId.has(id))
|
|
198
|
+
byId.set(id, ev);
|
|
199
|
+
}
|
|
200
|
+
const out = new Set();
|
|
201
|
+
for (const ev of evidences) {
|
|
202
|
+
if (!isObject(ev) || ev._invalid || ev.status !== "superseded")
|
|
203
|
+
continue;
|
|
204
|
+
const targetId = typeof ev.supersedes === "string" ? ev.supersedes : "";
|
|
205
|
+
if (!targetId)
|
|
206
|
+
continue;
|
|
207
|
+
const target = byId.get(targetId);
|
|
208
|
+
if (!target)
|
|
209
|
+
continue;
|
|
210
|
+
if (target.status !== "pass")
|
|
211
|
+
continue;
|
|
212
|
+
const sameGate = normalize_gate(String(ev.gate ?? "")) === normalize_gate(String(target.gate ?? ""));
|
|
213
|
+
const supersedeReason = typeof ev.supersede_reason === "string" ? ev.supersede_reason.trim() : "";
|
|
214
|
+
if (sameGate || supersedeReason)
|
|
215
|
+
out.add(targetId);
|
|
216
|
+
}
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
219
|
+
export function effective_superseded_ids(evidences) {
|
|
220
|
+
return authorized_supersede_target_ids(evidences);
|
|
221
|
+
}
|
|
191
222
|
export function gate_route_phase(gate) {
|
|
192
223
|
return GATE_ROUTE[normalize_gate(gate)] ?? "propose";
|
|
193
224
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ParsedArgs } from "./cli_args.ts";
|
|
2
2
|
import type { PacketDispatchResult } from "./packet_schema.ts";
|
|
3
|
+
export declare function read_discovery_template(packageRoot?: string): string | null;
|
|
3
4
|
export declare function dispatch_packet(args: ParsedArgs): PacketDispatchResult;
|
|
4
5
|
export declare function is_packet_command(command: string): boolean;
|