@peterxiaoyang/superspec 0.1.12 → 0.1.14
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/explore.toml +13 -0
- package/adapters/codex/install-map.json +10 -0
- package/dist/src/init_cli.js +6 -1
- package/dist/src/packet_render.js +9 -1
- package/dist/src/packet_schema.d.ts +2 -1
- package/dist/src/project_init.d.ts +2 -0
- package/dist/src/project_init.js +25 -1
- package/package.json +1 -1
- package/templates/workflow/prompts/explore.md +27 -0
- package/templates/workflow/skills/superspec-explore/SKILL.md +13 -1
- package/templates/workflow/skills/superspec-propose/SKILL.md +5 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# oh-my-codex agent: explore
|
|
2
|
+
name = "explore"
|
|
3
|
+
description = "Repo-local read-only factual scan for SuperSpec discovery"
|
|
4
|
+
model_reasoning_effort = "xhigh"
|
|
5
|
+
developer_instructions = """
|
|
6
|
+
Role: Explore. Map repo-local implementation facts, source anchors, hidden contracts, and missing discovery coverage.
|
|
7
|
+
|
|
8
|
+
Prompt binding: load `.codex/prompts/explore.md` first, then read the task prompt, `workflow-packet`, or `prompt_ref`. Packet refs and stop conditions override static prompt memory.
|
|
9
|
+
|
|
10
|
+
Boundary: read-only. Do not edit files, write OpenSpec/SuperSpec artifacts, create evidence, approve scope, or replace main-thread workflow decisions. Report findings upward with concrete anchors.
|
|
11
|
+
|
|
12
|
+
Output: concise Simplified Chinese. Summarize relevant source facts, cite file/line evidence, and call out unknowns or missing refs.
|
|
13
|
+
"""
|
|
@@ -52,6 +52,11 @@
|
|
|
52
52
|
"source": "templates/workflow/prompts/executor.md",
|
|
53
53
|
"target": ".codex/prompts/executor.md"
|
|
54
54
|
},
|
|
55
|
+
{
|
|
56
|
+
"kind": "prompt",
|
|
57
|
+
"source": "templates/workflow/prompts/explore.md",
|
|
58
|
+
"target": ".codex/prompts/explore.md"
|
|
59
|
+
},
|
|
55
60
|
{
|
|
56
61
|
"kind": "prompt",
|
|
57
62
|
"source": "templates/workflow/prompts/test-runner.md",
|
|
@@ -82,6 +87,11 @@
|
|
|
82
87
|
"source": "adapters/codex/agents/critic.toml",
|
|
83
88
|
"target": ".codex/agents/critic.toml"
|
|
84
89
|
},
|
|
90
|
+
{
|
|
91
|
+
"kind": "agent",
|
|
92
|
+
"source": "adapters/codex/agents/explore.toml",
|
|
93
|
+
"target": ".codex/agents/explore.toml"
|
|
94
|
+
},
|
|
85
95
|
{
|
|
86
96
|
"kind": "agent",
|
|
87
97
|
"source": "adapters/codex/agents/executor.toml",
|
package/dist/src/init_cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { block, commandExists, GuardError, printDecision, reason, runCommand, openspec_cli_probe, parseDecisionOutputFormat, REQUIRED_OPENSPEC_MIN_VERSION, } from "./core.js";
|
|
2
|
-
import { forced_openspec_install_plan, project_init, recommended_openspec_install_plan } from "./project_init.js";
|
|
2
|
+
import { ensure_openspec_chinese_context, forced_openspec_install_plan, project_init, recommended_openspec_install_plan } from "./project_init.js";
|
|
3
3
|
import { install_workflow, uninstall_workflow, update_workflow } from "./install_engine.js";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { resolve } from "node:path";
|
|
@@ -320,6 +320,11 @@ function run_init(args, scope) {
|
|
|
320
320
|
summary = engineDecision(`${gatePrefix}_update`, targetRoot, update_workflow(targetRoot, { scope }), [
|
|
321
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
|
+
if (scope === "project" && summary.allowed) {
|
|
324
|
+
const act = ensure_openspec_chinese_context(targetRoot);
|
|
325
|
+
if (Array.isArray(summary.actions))
|
|
326
|
+
summary.actions.push(act);
|
|
327
|
+
}
|
|
323
328
|
}
|
|
324
329
|
else if (scope === "user") {
|
|
325
330
|
summary = engineDecision("user_install", targetRoot, install_workflow(targetRoot, { force: args.force, scope: "user" }), [
|
|
@@ -10,7 +10,7 @@ import { final_verification_evidences, index_evidence, live_pass, live_user_conf
|
|
|
10
10
|
import { file_blob_sha, dirty_worktree_paths } from "./git.js";
|
|
11
11
|
import { preset_upgrade_reasons, preset_upgrade_required_from_context } from "./archive.js";
|
|
12
12
|
import { state_corrupt_reasons, state_stale_reasons } from "./state.js";
|
|
13
|
-
import { parse_tasks, resolve_test_contract_command, splitList, task_apply_execution_surface, task_apply_execution_surface_reasons, test_contract_invariant_refs_by_test, } from "./tasks.js";
|
|
13
|
+
import { parse_tasks, resolve_test_contract_command, splitList, task_apply_execution_surface, task_apply_execution_surface_reasons, tasks_structure_hash, test_contract_invariant_refs_by_test, } from "./tasks.js";
|
|
14
14
|
import { APPLY_CODE_REVIEW_REPORT_REQUIRED_FIELDS, APPLY_EXECUTOR_REPORT_REQUIRED_FIELDS, APPLY_TEST_RUNNER_REPORT_REQUIRED_FIELDS, APPLY_VERIFIER_REPORT_REQUIRED_FIELDS, apply_worker_implementation_fingerprint, apply_worker_executor_input_ref_digest, apply_worker_protected_path_refs, compute_apply_worker_freshness, fingerprint_digest, fingerprint_matches, pinned_artifact_ref_reasons as shared_pinned_artifact_ref_reasons, pre_edit_evidence_ref_reasons, pre_edit_worker_test_run_reasons, read_pinned_artifact_json, worker_input_ref_digest, worker_test_run_reasons, } from "./apply_worker_chain.js";
|
|
15
15
|
import { apply_worker_chain_lifecycle_state } from "./apply_worker_chain_lifecycle.js";
|
|
16
16
|
import { PACKAGE_ROOT } from "./install_engine.js";
|
|
@@ -400,6 +400,14 @@ function workflow_packet(ctx, gateRaw, taskId) {
|
|
|
400
400
|
diagnostic_command: gate_recheck_command(ctx.change, gate, taskId, true),
|
|
401
401
|
must_read_refs: workflow_gate_refs(ctx, gate),
|
|
402
402
|
};
|
|
403
|
+
// Surface tasks_structure_hash directly in the agent-facing packet so apply_isolation and
|
|
404
|
+
// scope_expansion human confirmations can be constructed without a second status/json detour
|
|
405
|
+
// or source-code inspection to find the current tasks.md structural fingerprint.
|
|
406
|
+
if (gate === "apply_ready" || gate === "task_edit" || gate === "task_complete" || gate === "task_reopen") {
|
|
407
|
+
const currentTasksStructureHash = tasks_structure_hash(ctx.changeRoot);
|
|
408
|
+
if (currentTasksStructureHash)
|
|
409
|
+
packet.tasks_structure_hash = currentTasksStructureHash;
|
|
410
|
+
}
|
|
403
411
|
const cliSurfaces = openspec_cli_surfaces_for_gate(ctx.change, gate);
|
|
404
412
|
if (cliSurfaces.length > 0)
|
|
405
413
|
packet.openspec_cli_surfaces = cliSurfaces;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type PacketOutputFormat = "agent" | "prompt";
|
|
2
2
|
export type PinnedRef = {
|
|
3
|
-
root: "repo" | "change";
|
|
3
|
+
root: "repo" | "change" | "superspec";
|
|
4
4
|
path: string;
|
|
5
5
|
blob_sha: string;
|
|
6
6
|
};
|
|
@@ -19,6 +19,7 @@ export type WorkflowPacket = {
|
|
|
19
19
|
current_gate: string;
|
|
20
20
|
task_id?: string;
|
|
21
21
|
status: "allowed" | "blocked";
|
|
22
|
+
tasks_structure_hash?: string;
|
|
22
23
|
top_blockers?: string[];
|
|
23
24
|
blocker_count?: number;
|
|
24
25
|
has_more_blockers?: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type JsonMap, type OpenspecCliProbe } from "./core.ts";
|
|
2
|
+
import { type EngineAction } from "./install_engine.ts";
|
|
2
3
|
export declare const OPENSPEC_NPM_PACKAGE = "@fission-ai/openspec";
|
|
3
4
|
export declare const OPENSPEC_INSTALL_DOC_URL = "https://github.com/Fission-AI/OpenSpec#readme";
|
|
4
5
|
export type OpenspecInstallPlan = {
|
|
@@ -26,6 +27,7 @@ export declare function openspec_cli_requirement_message(probe: OpenspecCliProbe
|
|
|
26
27
|
cwd?: string;
|
|
27
28
|
}) => boolean;
|
|
28
29
|
}): string;
|
|
30
|
+
export declare function ensure_openspec_chinese_context(repoRoot: string): EngineAction;
|
|
29
31
|
export declare function project_init(repoRootRaw?: string, opts?: {
|
|
30
32
|
force?: boolean;
|
|
31
33
|
}): JsonMap;
|
package/dist/src/project_init.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join, resolve } from "node:path";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
3
|
import { REQUIRED_SUPERSPEC_AGENT_ROLES, REQUIRED_OPENSPEC_MIN_VERSION, block, commandExists, openspec_cli_probe, reason, read_agent_toml_name, } from "./core.js";
|
|
4
4
|
import { install_workflow } from "./install_engine.js";
|
|
5
5
|
export const OPENSPEC_NPM_PACKAGE = "@fission-ai/openspec";
|
|
@@ -136,9 +136,33 @@ function ensureSuperSpecWorkflow(repoRoot, actions, force) {
|
|
|
136
136
|
}
|
|
137
137
|
return result.problems;
|
|
138
138
|
}
|
|
139
|
+
const OPENSPEC_CONFIG_REL = "openspec/config.yaml";
|
|
140
|
+
const ZH_CTX = '所有文档必须使用中文编写。需求描述应使用"应当"或"必须"等词汇。';
|
|
141
|
+
export function ensure_openspec_chinese_context(repoRoot) {
|
|
142
|
+
const p = join(repoRoot, OPENSPEC_CONFIG_REL);
|
|
143
|
+
if (existsSync(p) && statSync(p).isFile()) {
|
|
144
|
+
const t = readFileSync(p, "utf8");
|
|
145
|
+
if (/context:[\s\S]*?所有文档必须使用中文/u.test(t))
|
|
146
|
+
return { action: `configure ${OPENSPEC_CONFIG_REL}`, status: "ok", detail: "OpenSpec 中文语境已存在" };
|
|
147
|
+
if (/^context:/mu.test(t)) {
|
|
148
|
+
const u = t.replace(/^context:\s*[|>]?\s*\n(?:[ \t].*\n)*/mu, `context: |\n ${ZH_CTX}\n`);
|
|
149
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
150
|
+
writeFileSync(p, u, "utf8");
|
|
151
|
+
return { action: `configure ${OPENSPEC_CONFIG_REL}`, status: "updated", detail: "OpenSpec context 已替换为简体中文语境" };
|
|
152
|
+
}
|
|
153
|
+
const s = t.endsWith("\n") ? "\ncontext: |\n" : "\n\ncontext: |\n";
|
|
154
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
155
|
+
writeFileSync(p, `${t}${s} ${ZH_CTX}\n`, "utf8");
|
|
156
|
+
return { action: `configure ${OPENSPEC_CONFIG_REL}`, status: "updated", detail: "OpenSpec context 已追加简体中文语境" };
|
|
157
|
+
}
|
|
158
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
159
|
+
writeFileSync(p, `context: |\n ${ZH_CTX}\n`, "utf8");
|
|
160
|
+
return { action: `configure ${OPENSPEC_CONFIG_REL}`, status: "created", detail: "OpenSpec 输出语言已设为简体中文" };
|
|
161
|
+
}
|
|
139
162
|
export function project_init(repoRootRaw = process.cwd(), opts = {}) {
|
|
140
163
|
const repoRoot = resolve(repoRootRaw);
|
|
141
164
|
const actions = [];
|
|
165
|
+
actions.push(ensure_openspec_chinese_context(repoRoot));
|
|
142
166
|
const problems = [
|
|
143
167
|
...ensureOpenSpecCliSurface(repoRoot, actions),
|
|
144
168
|
...ensureSuperSpecWorkflow(repoRoot, actions, opts.force === true),
|
package/package.json
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "仓库代码事实扫描与 discovery 覆盖辅助角色"
|
|
3
|
+
argument-hint: "任务说明、workflow-packet 或 prompt_ref"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Explore
|
|
7
|
+
|
|
8
|
+
## 角色身份
|
|
9
|
+
|
|
10
|
+
你是 Explore。你负责 repo-local 只读事实扫描:定位实现入口、源码锚点、隐性合约、相邻风险和 discovery 可能遗漏的事实。你不批准范围,不写正式证据,也不替代主流程决策。
|
|
11
|
+
|
|
12
|
+
## 读写边界
|
|
13
|
+
|
|
14
|
+
- 默认只读;不要修改文件。
|
|
15
|
+
- 优先使用 repo search 和文件读取验证事实,结论必须绑定可读源码或文档锚点。
|
|
16
|
+
- 不要写 `proposal.md`/`design.md`/`tasks.md`/`specs/**`/`.superspec/**`。
|
|
17
|
+
- 不能作为 `explore_complete` 的 role evidence;需要门禁审查时交给 `critic`。
|
|
18
|
+
|
|
19
|
+
## SuperSpec Packet 规则
|
|
20
|
+
|
|
21
|
+
如果主流程提供 `workflow-packet` 或 `prompt_ref`,先读取 packet 指向的 refs。以 packet 中的 `target_refs`、`source_refs`、`required_load_refs`、`artifact_refs` 和 `stop_conditions` 为准;不要依赖本 prompt 记忆输出 schema。
|
|
22
|
+
|
|
23
|
+
## 输出风格
|
|
24
|
+
|
|
25
|
+
- 所有用户可见输出必须使用简体中文。
|
|
26
|
+
- 命令、路径、JSON/schema 字段、gate 名称、任务/测试 id、代码标识符保留原文。
|
|
27
|
+
- 结论先行;列出最相关文件/行号、已确认事实、仍缺的来源或需要主流程确认的问题。
|
|
@@ -35,10 +35,21 @@ Explore 只做需求澄清、代码事实调查、范围边界和风险记录。
|
|
|
35
35
|
superspec init --scope project --format agent
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
随后用 `openspec list --json` 查找匹配 change;若已有则复用,若没有则直接创建,不要先跑 `openspec --help` / `openspec change --help` / `openspec new --help` 探测语法(命令失败或版本报错时才查 help 诊断)。
|
|
39
39
|
|
|
40
40
|
```text
|
|
41
41
|
openspec list --json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
仅当 `openspec list --json` 没有匹配 change 时运行:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
openspec new change "<change>" --description "<用户需求摘要>"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
然后读取当前上下文:
|
|
51
|
+
|
|
52
|
+
```text
|
|
42
53
|
openspec status --change "<change>" --json
|
|
43
54
|
superspec check check-init --change "<change>" --format agent
|
|
44
55
|
superspec check workflow-packet --change "<change>" --gate explore_complete --format agent
|
|
@@ -52,6 +63,7 @@ superspec check workflow-packet --change "<change>" --gate explore_complete --fo
|
|
|
52
63
|
- 用 `openspec list --json` 和 `openspec status --change "<change>" --json` 确认 change 结构、artifactPaths 和当前状态。
|
|
53
64
|
- OpenSpec 负责 change 结构和后续 artifact 语义;本阶段只补 SuperSpec discovery 证据。
|
|
54
65
|
- 如果发现需要正式方案、规格、设计或任务,先写入 discovery,再交给 `superspec-propose`。
|
|
66
|
+
- 代码事实扫描可由主线程直接完成;若并行创建只读子代理,使用 repo-local `.codex/agents/explore.toml`。该角色只辅助 discovery 覆盖,不能替代 `critic` 审查证据。
|
|
55
67
|
|
|
56
68
|
## 专用代理边界
|
|
57
69
|
|
|
@@ -22,7 +22,7 @@ metadata:
|
|
|
22
22
|
|
|
23
23
|
## 阶段职责
|
|
24
24
|
|
|
25
|
-
Propose 把 discovery 转成 OpenSpec proposal package
|
|
25
|
+
Propose 把 discovery 转成 OpenSpec proposal package,并按阶段生成 SuperSpec 业务约束和测试契约辅助文档。负责产出 `proposal.md`、`specs/**/*.md`、`design.md`、`tasks.md`,以及在需要时新建或更新 `.superspec/artifacts/business-invariants.md`、`.superspec/artifacts/test-contract.md`。本阶段不改实现代码。
|
|
26
26
|
|
|
27
27
|
## 第一条必跑命令
|
|
28
28
|
|
|
@@ -49,7 +49,10 @@ openspec instructions <artifact-id> --change "<change>" --json
|
|
|
49
49
|
1. 运行 `openspec status --change "<change>" --json`,取 artifact 顺序、状态和 `resolvedOutputPath`。
|
|
50
50
|
2. 每个 artifact(proposal/specs/design/tasks)运行 `openspec instructions <artifact-id> --change "<change>" --json`,取回 template/rules/context/instruction/dependencies。
|
|
51
51
|
3. 先读 dependencies 列出的已完成 artifact,再按 template 写到 `resolvedOutputPath`;context/rules 是对作者的约束,不写进产出文件。
|
|
52
|
-
4.
|
|
52
|
+
4. 辅助文档(`.superspec/artifacts/business-invariants.md`、`.superspec/artifacts/test-contract.md`)如果尚不存在,就按 SuperSpec 内置模板在 change 内 `.superspec/artifacts/` 新建;已存在则基于当前阶段要求更新。
|
|
53
|
+
5. `invariants_reviewed` 的 `workflow-packet` 会下发 `business_invariants_template` 与 `business_invariants_rules`;必须按该骨架直接填写,不得改成段落/列表。
|
|
54
|
+
6. `test_contract_drafted` 的 `workflow-packet` 会下发 `test_contract_template` 与 `test_contract_rules`;必须按该骨架直接填写,不得改成段落/列表。
|
|
55
|
+
7. `business-invariants.md` 的 `## Invariants` / `## Mapping` 和 `test-contract.md` 的 `## 测试覆盖矩阵` 必须保持 Markdown 表格,列名原样保留。
|
|
53
56
|
|
|
54
57
|
## Packet 驱动的阶段门
|
|
55
58
|
|