@birdie_moblie/open_spec 2.1.7
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/.agents/plugins/marketplace.json +13 -0
- package/.claude-plugin/marketplace.json +12 -0
- package/.claude-plugin/plugin.json +9 -0
- package/.codex-plugin/plugin.json +9 -0
- package/LICENSE +21 -0
- package/README.md +111 -0
- package/bin/openspec.js +3 -0
- package/dist/cli/commands/change.d.ts +3 -0
- package/dist/cli/commands/change.js +37 -0
- package/dist/cli/commands/ext.d.ts +3 -0
- package/dist/cli/commands/ext.js +196 -0
- package/dist/cli/commands/figma.d.ts +3 -0
- package/dist/cli/commands/figma.js +73 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.js +71 -0
- package/dist/cli/commands/opsx.d.ts +3 -0
- package/dist/cli/commands/opsx.js +324 -0
- package/dist/cli/commands/usage.d.ts +3 -0
- package/dist/cli/commands/usage.js +21 -0
- package/dist/cli/output.d.ts +8 -0
- package/dist/cli/output.js +17 -0
- package/dist/cli/program.d.ts +4 -0
- package/dist/cli/program.js +42 -0
- package/dist/cli/register.d.ts +3 -0
- package/dist/cli/register.js +13 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +3 -0
- package/dist/config/load.d.ts +7 -0
- package/dist/config/load.js +55 -0
- package/dist/config/presets.d.ts +129 -0
- package/dist/config/presets.js +125 -0
- package/dist/config/schema.d.ts +281 -0
- package/dist/config/schema.js +178 -0
- package/dist/core/archive.d.ts +5 -0
- package/dist/core/archive.js +33 -0
- package/dist/core/change.d.ts +12 -0
- package/dist/core/change.js +69 -0
- package/dist/core/code-changes.d.ts +9 -0
- package/dist/core/code-changes.js +31 -0
- package/dist/core/flow.d.ts +6 -0
- package/dist/core/flow.js +99 -0
- package/dist/core/gates.d.ts +5 -0
- package/dist/core/gates.js +71 -0
- package/dist/core/instructions.d.ts +21 -0
- package/dist/core/instructions.js +102 -0
- package/dist/core/source-operations.d.ts +25 -0
- package/dist/core/source-operations.js +94 -0
- package/dist/core/sources.d.ts +33 -0
- package/dist/core/sources.js +234 -0
- package/dist/core/state.d.ts +15 -0
- package/dist/core/state.js +75 -0
- package/dist/core/status.d.ts +31 -0
- package/dist/core/status.js +22 -0
- package/dist/core/tasks.d.ts +15 -0
- package/dist/core/tasks.js +143 -0
- package/dist/core/todo.d.ts +31 -0
- package/dist/core/todo.js +114 -0
- package/dist/core/types.d.ts +297 -0
- package/dist/core/types.js +227 -0
- package/dist/core/verify.d.ts +229 -0
- package/dist/core/verify.js +391 -0
- package/dist/core/worker-evidence.d.ts +71 -0
- package/dist/core/worker-evidence.js +253 -0
- package/dist/core/worker.d.ts +22 -0
- package/dist/core/worker.js +478 -0
- package/dist/delivery/claude-install.d.ts +4 -0
- package/dist/delivery/claude-install.js +44 -0
- package/dist/delivery/distribution.d.ts +3 -0
- package/dist/delivery/distribution.js +53 -0
- package/dist/delivery/skills.d.ts +36 -0
- package/dist/delivery/skills.js +178 -0
- package/dist/figma/cache.d.ts +19 -0
- package/dist/figma/cache.js +115 -0
- package/dist/figma/claude.d.ts +14 -0
- package/dist/figma/claude.js +121 -0
- package/dist/figma/collect.d.ts +3 -0
- package/dist/figma/collect.js +57 -0
- package/dist/figma/index.d.ts +35 -0
- package/dist/figma/index.js +178 -0
- package/dist/figma/media.d.ts +5 -0
- package/dist/figma/media.js +77 -0
- package/dist/figma/response.d.ts +9 -0
- package/dist/figma/response.js +27 -0
- package/dist/hooks/command-context.d.ts +19 -0
- package/dist/hooks/command-context.js +33 -0
- package/dist/hooks/engine.d.ts +61 -0
- package/dist/hooks/engine.js +314 -0
- package/dist/hooks/plugin-runtime.d.ts +188 -0
- package/dist/hooks/plugin-runtime.js +198 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.js +185 -0
- package/dist/marketplace/adapters.d.ts +202 -0
- package/dist/marketplace/adapters.js +203 -0
- package/dist/marketplace/builtin.d.ts +9 -0
- package/dist/marketplace/builtin.js +9 -0
- package/dist/marketplace/install.d.ts +38 -0
- package/dist/marketplace/install.js +108 -0
- package/dist/marketplace/registry.d.ts +71 -0
- package/dist/marketplace/registry.js +342 -0
- package/dist/marketplace/upgrade.d.ts +39 -0
- package/dist/marketplace/upgrade.js +104 -0
- package/dist/shared/command-log.d.ts +9 -0
- package/dist/shared/command-log.js +55 -0
- package/dist/shared/errors.d.ts +7 -0
- package/dist/shared/errors.js +14 -0
- package/dist/shared/exec.d.ts +16 -0
- package/dist/shared/exec.js +86 -0
- package/dist/shared/fs.d.ts +18 -0
- package/dist/shared/fs.js +93 -0
- package/dist/shared/git.d.ts +22 -0
- package/dist/shared/git.js +132 -0
- package/dist/shared/hash.d.ts +5 -0
- package/dist/shared/hash.js +29 -0
- package/dist/shared/paths.d.ts +16 -0
- package/dist/shared/paths.js +97 -0
- package/dist/shared/pkg.d.ts +3 -0
- package/dist/shared/pkg.js +23 -0
- package/dist/shared/version.d.ts +9 -0
- package/dist/shared/version.js +34 -0
- package/dist/usage/analyze.d.ts +5 -0
- package/dist/usage/analyze.js +212 -0
- package/dist/usage/claude.d.ts +9 -0
- package/dist/usage/claude.js +59 -0
- package/dist/usage/collect.d.ts +11 -0
- package/dist/usage/collect.js +71 -0
- package/dist/usage/doctor.d.ts +72 -0
- package/dist/usage/doctor.js +121 -0
- package/dist/usage/parse.d.ts +28 -0
- package/dist/usage/parse.js +345 -0
- package/dist/usage/types.d.ts +103 -0
- package/dist/usage/types.js +2 -0
- package/docs/getting-started.md +20 -0
- package/docs/guides/configuration.md +33 -0
- package/docs/guides/cost-benchmark.md +88 -0
- package/docs/guides/plugin-migration.md +65 -0
- package/docs/guides/smart-figma.md +51 -0
- package/docs/guides/source-reading.md +35 -0
- package/docs/guides/ui-conventions-template.md +39 -0
- package/docs/guides/worker-evidence.md +73 -0
- package/docs/guides/workflow.md +74 -0
- package/docs/maintainers/architecture.md +27 -0
- package/docs/maintainers/plugin-runtime-contract.md +55 -0
- package/package.json +78 -0
- package/plugin.json +9 -0
- package/presets/backend-service.yaml +19 -0
- package/presets/flutter-mobile/plugin-hooks.json +68 -0
- package/presets/flutter-mobile/ui-conventions.md +122 -0
- package/presets/flutter-mobile.yaml +205 -0
- package/presets/web-product.yaml +23 -0
- package/skills/opsx-apply/SKILL.md +35 -0
- package/skills/opsx-apply/nodes/blocked.md +7 -0
- package/skills/opsx-apply/nodes/code-task.md +29 -0
- package/skills/opsx-apply/nodes/gate-a.md +9 -0
- package/skills/opsx-apply/nodes/stop.md +5 -0
- package/skills/opsx-apply/nodes/task-build.md +50 -0
- package/skills/opsx-apply/nodes/task-repair.md +20 -0
- package/skills/opsx-apply/nodes/task-scout.md +28 -0
- package/skills/opsx-apply/nodes/task-verify.md +38 -0
- package/skills/opsx-archive/SKILL.md +24 -0
- package/skills/opsx-archive/nodes/archive.md +15 -0
- package/skills/opsx-explore/SKILL.md +20 -0
- package/skills/opsx-explore/nodes/explore.md +3 -0
- package/skills/opsx-fix-verify/SKILL.md +30 -0
- package/skills/opsx-fix-verify/nodes/repair.md +11 -0
- package/skills/opsx-fix-verify/nodes/reverify.md +3 -0
- package/skills/opsx-fix-verify/nodes/stop.md +3 -0
- package/skills/opsx-gate-decision/SKILL.md +20 -0
- package/skills/opsx-gate-decision/nodes/decide.md +15 -0
- package/skills/opsx-propose/SKILL.md +36 -0
- package/skills/opsx-propose/nodes/blocked.md +13 -0
- package/skills/opsx-propose/nodes/collect.md +35 -0
- package/skills/opsx-propose/nodes/parse.md +72 -0
- package/skills/opsx-propose/nodes/plan.md +65 -0
- package/skills/opsx-propose/nodes/stop.md +17 -0
- package/skills/opsx-propose/nodes/tech.md +77 -0
- package/skills/opsx-propose/scripts/read-json-source.mjs +22 -0
- package/skills/opsx-resume/SKILL.md +21 -0
- package/skills/opsx-resume/nodes/route.md +12 -0
- package/skills/opsx-source-update/SKILL.md +23 -0
- package/skills/opsx-source-update/nodes/update.md +14 -0
- package/skills/opsx-verify/SKILL.md +32 -0
- package/skills/opsx-verify/nodes/blocked.md +3 -0
- package/skills/opsx-verify/nodes/failed.md +3 -0
- package/skills/opsx-verify/nodes/gate-b.md +7 -0
- package/skills/opsx-verify/nodes/stop.md +5 -0
- package/skills/opsx-verify/nodes/verify.md +10 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Task verify(独立验收,UI task)
|
|
2
|
+
|
|
3
|
+
在短命上下文里一次性判定视觉与形态。**不修改业务代码,不自修页面。** 阅读以下完整验收依据,结果写入指定 review 文件:
|
|
4
|
+
|
|
5
|
+
- packet 的 `task.notes`,`initContext.hooks` 中 check 类 Hook 的 description;
|
|
6
|
+
- spec 对应页面原始要求、context.md 第 4 节设计清单及其指向的完整 Meta 元数据、样式与变量;摘要不能替代原文;
|
|
7
|
+
- 设计截图:context.md 第 4 节路径;缺失时取 designRefs 节点的图像并实际读入内容,只拿到 URL 或工具提示不算已看图;
|
|
8
|
+
- 最终页面截图:build / repair result 的 `notes` 与 context.md 第 5 节给出的路径;
|
|
9
|
+
- `packet.refs.executionEvidence` 索引里的既有 issues。
|
|
10
|
+
|
|
11
|
+
## 判定
|
|
12
|
+
|
|
13
|
+
每轮先检查完整页面原始要求,再复核历史问题,不能只检查已登记问题。以 context.md 第 4 节设计清单为核对表(与 build 用的是同一份),逐条对照最终截图与 Meta 数值:形态与区块顺序、各区块排列方向与几何(尺寸 / 间距 / 圆角)、背景与边框、按钮与导航几何、切图是否为设计源导出件且未被二次处理、字号 / 字重、颜色 token、深浅两套、可见文案与语言切换;再逐条对照 check description。宿主约定声明「以宿主为准」的项(清单中标注「按宿主约定」)按约定判定,与设计稿数值的差异不登记为问题。只判定设计与 spec 中存在的元素;参照里没有的东西不得成为问题;不新增验收规则。
|
|
14
|
+
|
|
15
|
+
只登记本 task 范围(`task.refScope` 与 build / repair 的 `changedFiles`)内可修复的问题。属于其他 task 的缺陷不写入 review 文件,在返回摘要中单列「跨任务:<task id 或文件> — <观察>」,由控制会话汇报用户。
|
|
16
|
+
|
|
17
|
+
截图字体不可读、目标页面或数据状态不对应、必要图片未加载时,登记 `evidence-unavailable` 等 open 问题及具体原因,不能输出视觉通过;证据补齐后仍须重新检查整页。行为测试结果单独检查,不用静态截图推断异步行为。
|
|
18
|
+
|
|
19
|
+
## 输出 `openspec/changes/<name>/.opsx/workers/<taskId>.review-<n>.json`
|
|
20
|
+
|
|
21
|
+
`n` 为本 task 第几次 verify。自行生成的裁剪图、对照图只能放在 `openspec/changes/<name>/.opsx/workers/<taskId>.*` 下。数组元素:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
[{"id":"hero-title-weight","status":"open",
|
|
25
|
+
"advisory":true,"evidence":"<项目内实际页面截图路径>",
|
|
26
|
+
"description":"观察:<哪张截图 / 区域 / 实际值>;期望:<设计节点或规格值 / 参照>;疑似位置:<文件或组件>"},
|
|
27
|
+
{"id":"<上轮 open 的 id>","status":"resolved",
|
|
28
|
+
"description":"复核:<哪张截图 / 区域> 已满足 <期望>","evidence":"<项目内截图路径>"}]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- 普通视觉偏差写 `advisory: true`,保留 `status: open` 和实际截图 `evidence`,可选返修并在最终报告披露。行为错误、构建失败、目标或必要图片不可用不得标 advisory;省略 advisory 的旧问题仍阻断。引擎校验记录,不代替你判断问题性质。
|
|
32
|
+
- id 用小写连字符描述位置与问题;同一问题跨轮沿用同一 id。
|
|
33
|
+
- 期望必须可观察、可核对(数值、token 名、节点 id、参照截图区域),不写「不对」「不一致」这类无法关闭的描述。
|
|
34
|
+
- 每轮覆盖索引中**全部**问题:open 项仍不满足保持 open 并更新观察,已满足写 resolved 并给证据路径;resolved / advisory 项的证据截图若本轮被重新生成,也重新复核并按实际状态再写一次 status + evidence(普通未修项保留 advisory)(引擎按证据摘要判 stale,漏写会让 accept 失败)。未提及的旧问题会保持 open。
|
|
35
|
+
- 只读整页截图或 ≥ 64×64 的裁剪区域;不要把小图标裁成十几像素的图送入模型,部分提供商会拒绝这类输入;按会话配置限制处理,原始生产资源不改。
|
|
36
|
+
- 无任何问题写 `[]`。
|
|
37
|
+
|
|
38
|
+
返回控制会话 ≤200 字:文件路径、blocking / advisory / resolved 数、跨任务条目。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opsx-archive
|
|
3
|
+
description: 批准 Gate-C 并将 change 归档。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# opsx-archive
|
|
7
|
+
|
|
8
|
+
## 项目 CLI 预检
|
|
9
|
+
|
|
10
|
+
定位项目根并校验 CLI 版本。
|
|
11
|
+
|
|
12
|
+
## 循环
|
|
13
|
+
|
|
14
|
+
1. 读 status / instructions
|
|
15
|
+
2. 读取 nodeFile
|
|
16
|
+
3. 完成后退出
|
|
17
|
+
|
|
18
|
+
## 路由表
|
|
19
|
+
|
|
20
|
+
任意已完成或 Gate-C:nodes/archive.md
|
|
21
|
+
|
|
22
|
+
## 退出条件
|
|
23
|
+
|
|
24
|
+
归档成功,或尚未 completed 时停止并说明。
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opsx-explore
|
|
3
|
+
description: 只读探索想法、代码或已有 change,不改 OPSX 状态。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# opsx-explore
|
|
7
|
+
|
|
8
|
+
只读。不要写 `.opsx/`、不要 create worker、不要改应用代码。
|
|
9
|
+
|
|
10
|
+
## 项目 CLI 预检
|
|
11
|
+
|
|
12
|
+
若已在项目中,可读 `openspec list --json`。不是项目时也可以纯讨论。
|
|
13
|
+
|
|
14
|
+
## 循环
|
|
15
|
+
|
|
16
|
+
读取 nodes/explore.md,回答用户后结束。
|
|
17
|
+
|
|
18
|
+
## 退出条件
|
|
19
|
+
|
|
20
|
+
给出观察或建议后停止。若用户要求落地,路由到 `/opsx-propose` 或 `/opsx-resume`。
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opsx-fix-verify
|
|
3
|
+
description: 对可修复的 QA 失败做一轮 code 修复后再验证。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# opsx-fix-verify
|
|
7
|
+
|
|
8
|
+
不要把修理委托给 `/opsx-apply`。本 workflow 自己跑一轮修复。
|
|
9
|
+
|
|
10
|
+
## 项目 CLI 预检
|
|
11
|
+
|
|
12
|
+
定位项目根并校验 CLI 版本。
|
|
13
|
+
|
|
14
|
+
## 循环
|
|
15
|
+
|
|
16
|
+
1. 读 `status` / `instructions opsx-fix-verify`
|
|
17
|
+
2. 读取 `nodeFile`
|
|
18
|
+
3. 回到第 1 步直到退出
|
|
19
|
+
|
|
20
|
+
## 路由表
|
|
21
|
+
|
|
22
|
+
| next.action | 读取 |
|
|
23
|
+
|---|---|
|
|
24
|
+
| fix_verify 或 code worker | nodes/repair.md |
|
|
25
|
+
| create_worker verify | nodes/reverify.md |
|
|
26
|
+
| await_gate / completed | nodes/stop.md |
|
|
27
|
+
|
|
28
|
+
## 退出条件
|
|
29
|
+
|
|
30
|
+
再次到达 Gate-C,或第二次验证仍失败时停止(不要无限循环)。
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Repair
|
|
2
|
+
|
|
3
|
+
```bash
|
|
4
|
+
openspec verify fix --change "<name>" --reason "qa failed" --json
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
然后创建返回的 `repair-verify` Worker,只修复 `packet.refs.qaReport` 所列问题(commands 失败输出、hook evidence 的 failed notes、blockingIssues),不重开原 task 列表。
|
|
8
|
+
|
|
9
|
+
repair packet 的 `initContext` 带有全部已完成 task 分类的 notes,以及匹配这些分类的 execute Hook:修复触及 UI 时仍要满足四态 / 主题 / 国际化等约束,并在 result 的 `executeHookResults` 中逐项回执(required 必须 passed 才能 completed)。
|
|
10
|
+
|
|
11
|
+
修复完成后写 `packet.expectedResult`(格式同 `opsx-apply/nodes/task-build.md`:`workerId` / `stepId: "repair-verify"` / `status` / `changedFiles` / `notes` / `executeHookResults`)并 accept;引擎会直接回到一个全新的 verify run。不要在本节点重复调用 `verify fix`。
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opsx-gate-decision
|
|
3
|
+
description: 按用户意图批准或拒绝当前等待中的 Gate。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# opsx-gate-decision
|
|
7
|
+
|
|
8
|
+
## 项目 CLI 预检
|
|
9
|
+
|
|
10
|
+
定位项目根并校验 CLI 版本。
|
|
11
|
+
|
|
12
|
+
## 循环
|
|
13
|
+
|
|
14
|
+
1. 读 status,确认 `next.action === await_gate`
|
|
15
|
+
2. 读取 nodes/decide.md
|
|
16
|
+
3. 执行后停止或交给 resume
|
|
17
|
+
|
|
18
|
+
## 退出条件
|
|
19
|
+
|
|
20
|
+
gate 决策完成。若用户意图不明,先问再执行。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 决策
|
|
2
|
+
|
|
3
|
+
批准:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
openspec gate approve <gate-A|gate-B|gate-C> --change "<name>" --comment "<why>" --json
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
拒绝(必须给原因):
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
openspec gate reject <gate> --change "<name>" --reason "<why>" --json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
拒绝 Gate-A 会回到 plan;拒绝 Gate-B/C 会重开已完成 task。
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opsx-propose
|
|
3
|
+
description: 新建 change,采集来源并完成 parse/tech/plan,停在 Gate-A。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# opsx-propose
|
|
7
|
+
|
|
8
|
+
用户参数是目标描述。先做项目 CLI 预检(见循环前规则),再进入循环。
|
|
9
|
+
|
|
10
|
+
## 项目 CLI 预检
|
|
11
|
+
|
|
12
|
+
定位含 `openspec/config.yaml` 的项目根,校验 `openspec --version` 与 `install-cli.mjs` 的 packageVersion。不一致则停止并请用户安装。
|
|
13
|
+
|
|
14
|
+
## 循环
|
|
15
|
+
|
|
16
|
+
1. 若尚无 change:`openspec new change <name>`;来源登记由 collect 节点完成。file 来源只用项目内已有文件的相对路径,外部原文先复制并校验摘要
|
|
17
|
+
2. `openspec instructions opsx-propose --change "<name>" --json`
|
|
18
|
+
3. 读取 `nodeFile` 并执行
|
|
19
|
+
4. 优先复用变更命令返回的 `next` / `nodeFile`;无此字段或外部状态变化时才重新取 instructions
|
|
20
|
+
|
|
21
|
+
## 路由表
|
|
22
|
+
|
|
23
|
+
| next.action | 读取 |
|
|
24
|
+
|---|---|
|
|
25
|
+
| add_sources / collect_sources | nodes/collect.md |
|
|
26
|
+
| create_worker parse | nodes/parse.md |
|
|
27
|
+
| create_worker tech | nodes/tech.md |
|
|
28
|
+
| create_worker plan | nodes/plan.md |
|
|
29
|
+
| await_gate gate-A | nodes/stop.md |
|
|
30
|
+
| 其他 | nodes/blocked.md |
|
|
31
|
+
|
|
32
|
+
## 退出条件
|
|
33
|
+
|
|
34
|
+
停在 Gate-A。不要写应用代码,不要批准 Gate-A(那是 apply 的职责)。
|
|
35
|
+
|
|
36
|
+
summary 中的 `packetPath` 指向完整 packet;按返回的路径读取,不回显全文。
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# 受阻
|
|
2
|
+
|
|
3
|
+
展示 blocker 与 recoveries。缺少来源或配置时停止,等待用户。
|
|
4
|
+
|
|
5
|
+
`next.questions` 非空时逐条呈现给用户并停止;不要替用户作答。用户答复后:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
openspec worker answer --change "<name>" --answer "<问题1的答复>" --answer "<问题2的答复>" --view summary --json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
答复会写入原 packet 的 `decisions`(questions / answers / answeredAt)并清除 blocked 状态;随后回到循环头,`worker create` 同一 step 会返回同一 packet,Worker 必须按 `decisions` 完成产物后重新 accept。
|
|
12
|
+
|
|
13
|
+
答复后先按具体问题定位受影响的权威内容:产品行为在 spec、技术选择在 tech、任务归属在 plan;只同步实际改变的条目及其引用,保留未受影响的有效内容。复用原 Worker 完成当前受阻步骤,不重跑已成立的阶段,也不把三个文件整份重写;不重复抄写项目通用约定。
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Collect
|
|
2
|
+
|
|
3
|
+
若没有来源账本,先把已知来源批量登记:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
openspec sources add --change "<name>" --notes "<目标>" --view summary --json
|
|
7
|
+
# 有外部材料时再追加 --source requirements=<url> 等
|
|
8
|
+
openspec sources collect --change "<name>" --view summary --json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
登记 file 来源之前,先确认文件存在于项目内,并使用项目相对路径。获授权的外部原始材料先逐字复制到项目内 `sources/frozen/`,核对摘要后再登记;不要把外部绝对路径写进账本。仅有 notes 也可以 collect。
|
|
12
|
+
|
|
13
|
+
参数、格式或可查路径校验失败时,先按错误提示修正后重试当前采集;不把可自行修正的调用错误当成用户决策。真正缺少来源权限、材料或存在未决契约时才 blocked 并结束,不能伪造来源。旧版本已经登记的无效 locator 无法用追加来源覆盖:保留失败证据并交控制会话处理,不循环派发相同失败任务。
|
|
14
|
+
|
|
15
|
+
`sources_incomplete` 列出的 `<hookId>:<sourceId>` 表示该 hook 是 `type: skill`(无 adapter):按 hook 的 purpose 用宿主工具(如 Figma MCP)人工采集,保存原始内容(放在项目内,建议 `openspec/changes/<name>/sources/manual/`)后以 `--source-file <capability>=<path>` 登记,再重新 collect;文件可为 markdown、CSV 或 JSON,不要求改写成说明文。引擎可能把同 capability 的手工来源记为 covered;必须核对它确实覆盖对应 URL,不能因分类相同就认定内容可替代。保留 URL 与全部来源身份,不删除来源。设计源从用户给定的设计组由大到小定位到业务页面/弹层的候选 frame,保留 fileKey、URL、节点 id、所在画布/section 与主题分组。明确名称或已有决定能确定的映射直接使用;通用名称保留候选,不猜用途。metadata 没有子层不表示设计为空。collect 阶段不读页面内部图层、截图、变量或视觉参数;parse 可按 [形态确认规则](parse.md) 读取候选 frame 截图或节点类型,coding 再详读目标页面。
|
|
16
|
+
|
|
17
|
+
adapter 产出的 markdown 可能保留无法展开的占位(如飞书文档里的 `<sheet>` 内嵌表格)。发现后用宿主工具补采(如 `lark-cli sheets +csv-get --spreadsheet-token <token> --sheet-id <id>`),仅保存补充表格(注明原始来源与表格位置,不再复制 PRD 全文),以 `--source-file requirements=<path>` 登记,不要让 parse 面对空占位。
|
|
18
|
+
|
|
19
|
+
资料转存优先用命令重定向或脚本保存工具原始返回;已有落盘结果直接复用,不为保存而再次请求,也不让模型逐字重写 CSV 单元格、接口 schema 或引用正文。需要聚合时由脚本把原文与来源 URL、表格/接口 ID 关联,保留全部单元格、字段、平台限定和冲突原文;不得用摘要替代原始内容。批量查询须逐项检查退出码与内容,失败不登记为成功。转存后一次核对数量、身份及完整性,再批量登记;模型只补必要的适用范围或真实缺口,不重述已保存的正文,也不在 collect 裁定冲突。只有路径而没有正文的索引不能冒充完整采集,引用的原始文件必须保存在 change 内且下游可定位读取。
|
|
20
|
+
|
|
21
|
+
聚合文件内每段正文、表格或 schema 只保存一份完整内容。不要同时保存抽取正文和含相同内容的完整原始回包;选一种完整表示,原始回包用 change 内证据路径引用。选择接口对象时保留请求头及其值、全部请求/响应字段、说明与来源,不能以去重为由删掉 `Content-Type` 等契约。登记前核对聚合内无重复全文,下游可从账本定位到唯一正文。
|
|
22
|
+
|
|
23
|
+
PRD 当前功能章节通过 `<cite>`、链接或附件引用具体行为、字段、交互规则时,引用材料也是该功能的来源依赖;先读取判断适用范围,再补齐当前需求依赖的正文与表格。不能仅因它是另一份文档、尚未单独登记,就把可访问内容列为缺口留给 parse。保留来源中的平台限制和冲突,不把某个平台的专属要求自动扩大到其他平台;无关参考链接不追踪。访问失败时保存真实错误并停在 collect,不能声明来源齐全。
|
|
24
|
+
|
|
25
|
+
采集结果只按账本 `artifact` 路径读取;同路径或已核对摘要相同的内容只读一次,不同时通读 manual 原稿和 CLI 副本。独立补采可以批量进行,完成后一次登记再 collect,不每补一项就重抓全部来源。
|
|
26
|
+
|
|
27
|
+
本次尚未完成的 collect 会复用成功且摘要匹配的采集结果;只补失败/缺失来源。明确需要重新抓取时用 `sources collect --change "<name>" --refresh --view summary --json`;已完成采集后通过 sources add 开始新修订,不能倒退阶段。
|
|
28
|
+
|
|
29
|
+
收尾复用成功的 collect 返回值:`node`、`next`、`sourcesPath`、`artifacts` 和缺口已足以路由。来源完整性在登记前核对;没有错误、外部状态变化或尚未核实的具体问题时,不为确认结束再读取 state、账本、Figma 索引或全部来源,也不重复调用 status/instructions。继续 propose 时直接按 next 进入下一节点;用户限定只做 collect 时,简述停止位置、来源路径及真实缺口即可,不生成报告文件或重新写一遍材料清单和正文。
|
|
30
|
+
|
|
31
|
+
接口总览可能只是目录。按需求定位有关接口,批量读取字段 schema、真实 path、method、分页与枚举,保存原始详情及来源;不要抓无关接口。可查的字段不能统一写成“apply 再拉详情”;确实不可访问或来源没有该定义时如实记录缺口,不猜类型或值。
|
|
32
|
+
|
|
33
|
+
已通过会话 `--settings` 启用 Smart Figma 时,`smart-figma:<sourceId>` 表示内建采集尚未完整:仅调用官方 `get_metadata` 读取登记的根节点及返回的未展开容器;工具返回页面索引路径与分页信息,按需用 `openspec sources figma show --index <path> --offset <nextOffset>` 读取下一页。不要读取 raw 目录、Claude 大响应文件或自行编写解析脚本,不重复请求已取得的子树。CLI 在下一次 `sources collect` 自动将已验证索引关联原来源,不要求手写 markdown 或再登记设计副本。`--refresh` 会使本次 Figma 缓存失效;补采后不带 refresh 重新 collect。接入未启用时仍按上述页面边界手工定位,不能声称工具结果已自动压缩。
|
|
34
|
+
|
|
35
|
+
索引中 `role=candidate` 已是页面候选,即使 `childrenObserved=false` 也不继续展开。只有明确待展开的容器才补采;`unresolvedCount=0` 且 `nextOffset=null` 表示本次页面定位已齐,不需要用额外 metadata 请求确认。
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Parse
|
|
2
|
+
|
|
3
|
+
创建 parse worker,写出 `spec.md`(产品契约:写用户可见行为与约束,不写实现细节)。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
openspec worker create --change "<name>" --step parse --view summary --json
|
|
7
|
+
# 写 spec.md 与 expectedResult
|
|
8
|
+
openspec worker accept --change "<name>" --result <path> --view summary --json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Result 文件格式
|
|
12
|
+
|
|
13
|
+
`packet.expectedResult` 是严格 JSON(未知字段会被拒收):
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"workerId": "<packet.workerId>",
|
|
18
|
+
"stepId": "parse",
|
|
19
|
+
"status": "completed | failed | blocked",
|
|
20
|
+
"notes": "可选;skipTech 为 true 时必填理由",
|
|
21
|
+
"questions": ["blocked 时每条冲突一个问题,附双方口径"],
|
|
22
|
+
"skipTech": false,
|
|
23
|
+
"executeHookResults": [{ "id": "<initContext.hooks[].id>", "status": "passed | failed | skipped", "notes": "可选" }]
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 先加载 packet.initContext
|
|
28
|
+
|
|
29
|
+
按 skill descriptor 的明确路径加载指导;有 plugin.inputDescription/input 时按其契约准备参数。command Hook 必须通过 `openspec worker check --change "<name>" --id "<hook-id>" [--input "<项目内 JSON>"]` 执行,保留真实回执;文字 passed 不能代替执行。来源、配置、输入或代码变化后重跑失效检查。
|
|
30
|
+
|
|
31
|
+
动笔前处理 `initContext.hooks`:读取 file、把 check 纳入完成自检、notes 视为硬约束。所有 hook 都在 result 的 `executeHookResults` 中按 id 回执 `passed` / `failed` / `skipped`;required file 不存在、或仍含 `openspec:fill-me` 标记(init 生成的未填写模板)时写 `blocked` 并在 questions 中请用户填写该文件,不得跳过。
|
|
32
|
+
|
|
33
|
+
## 产品事实的质量边界
|
|
34
|
+
|
|
35
|
+
以下规则适用于本阶段所有适用章节。「写明」是要求报告已知事实与未知项,不授权补齐来源未定的行为。来源未提及某项不等于否定:其它适用来源已明确给出的字段/行为可补充契约,不把表格漏列与配图出现自动当作冲突。
|
|
36
|
+
|
|
37
|
+
- 读取 packet.refs.sources 指向的完整账本;refs.design 等仅是快捷引用。必需需求不可读且无账本内等价副本时 blocked,列恢复条件,保留确定事实;不以接口/schema/changelog 或代码推演替代需求,也不要求用户重述恢复原文即可查清的内容。
|
|
38
|
+
- 完整核对当前范围的原文、被引用字段表及相关接口业务说明(markdown/desc)、字段约束、成功和各失败分支。失败可能已有业务副作用,不能一律解释为「保持原状」。需要展开大 JSON 时可用本 Skill 的 scripts/read-json-source.mjs(默认 full 无损显示),不截断规范性文字。读到了 schema 不等于读完接口语义。
|
|
39
|
+
- 引用文档只纳入明确引用的功能,不扩展邻接章节。 范围限定适用于其对应章节,不能擅自缩小到章节中的一个子项来消除范围冲突;原文没有这种限定、也无权威裁定时保留冲突。范围待裁定不等于来源缺失:该功能仍按「若纳入」保留与范围内功能相同的字段、状态、交互与条件式验收,可引用明确表格及适用行。不能只留争议摘要或「暂不验收」:选项及默认值、选择后的显示规则、操作反馈、跳转目标和参数、计算定义均属于已知契约。正文与表格中的同名字段定义、公式、单位、精度不一致时,逐项保留双方,不只摘其中一份。
|
|
40
|
+
- 仅实际答复及后续更正是决定;问题中的示例、旧推断及「未否定」不是。按项目已规定的来源优先级裁定已有证据,不能重问已裁定事项。 已确认结构中的控件数量及状态也是约束;旧来源多出的操作不能与当前结构并列为现行入口。映射到某节点不等于额外决定该节点未读的内部行为。
|
|
41
|
+
- 页面形态按项目来源优先级确定,通常以设计为准:需求明确写出且与设计一致时直接引用;需求泛称(弹窗 / 明细 / 查看详情)或只有候选节点时,读取候选 frame 的截图或节点类型**只为确认形态**并记节点 id,不读页面内部字段、文案与样式。不能从需求措辞、候选 frame 名称/尺寸或通用控件推定形态;设计中也没有对应 frame 才写「未定」及缺口。已有分享/划转等业务流程按项目权威执行,不重新选形态。
|
|
42
|
+
- 对每页及请求按钮核对状态和副作用;未知的关闭、刷新、联动、默认值、空值替代和单位应明确写「来源未定义」,不写入已定义行为或验收。尤其不要为一般成功/错误码附加未声明的刷新、关闭或重试;数值 null 不自动等于0。项目确有适用通用规则则引用该规则;实现可选择的技术机制不升格为产品承诺。
|
|
43
|
+
- 数据章节覆盖所有产品字段,包括没有接口的静态展示、本地计算和待纳入功能;不以能否找到 API 决定是否保留。来源有字段表时,可明确写「本功能的全部字段及约束按来源 X 的表 Y」,再列例外与冲突,不必重复抄表或虚构接口。只在某条冲突中提到表名,不等于采用其完整字段契约。
|
|
44
|
+
- 完成前直接在 spec 中核对:页面差异/字段/状态/条件分支均有原文或明确表格引用;正文、缺口与验收一致;所有新增产品行为有依据,未定事项没有在别处被写死。不得为通过验收编造决定或手工修改实验来源。
|
|
45
|
+
|
|
46
|
+
## spec.md 必备章节
|
|
47
|
+
|
|
48
|
+
1. **目标与范围**:范围内 / 明确排除 / 待裁定(已知条件式契约仍写入下列章节)。
|
|
49
|
+
2. **能力与入口清单**:列出本次界面、命令、API、事件或后台任务的入口、输入、输出及来源。图形 UI 每个用户可达界面一行——名称 | 形态(有依据的 page / dialog / bottom-sheet / tab 子页,或「未定」)| 进入方式 | 设计节点(可直接传给 MCP 的节点 id,含状态变体)| 来源引用。形态引用设计节点(截图或节点类型确认)、明确需求或实际答复;需求泛称而设计有对应 frame 时以设计为准并记节点 id;设计也无对应 frame 时填「未定」,不能先选再用备注否认。来源冲突保留。设计只定位到候选 frame 时注明对应范围,不能把结构候选当成已确认业务映射。
|
|
50
|
+
3. **状态与交互**:按实际界面、命令、API 或后台任务写明状态、成功/失败结果、触发和恢复条件。图形 UI 对清单中每一页核对 loading / empty / error+retry 四态、刷新时机(首屏、下拉、切 Tab 回到页面、从子页返回)、页面间联动(Tab 间刷新、共享偏好);对每个触发接口请求的按钮写明请求中状态与失败提示。需求文档里的运行时行为(默认筛选区间、防重复请求、倒计时、只请求一次)逐条保留当前有效口径;已被裁定覆盖的旧动作仅写入第 5 章差异,不在本章并列为可执行行为。
|
|
51
|
+
4. **数据与接口对照**:需求字段 ↔ 接口字段逐项对应;接口缺字段、需求无接口、字段语义不一致的条目进第 5 章缺口清单。接口对照表必须包含「wire type(schema 类型)」「真实 path」两列;注释枚举与 schema 类型冲突、标注「仅用于展示」的文档 path、未展开的 params/object 三类一律列入第 5 章,要求 tech 给出处置,不把注释或展示路径当真实契约。
|
|
52
|
+
5. **来源冲突与缺口**:需求 ↔ 设计 ↔ 接口三方不一致逐条列出(来源 id、双方口径);设计资产缺失(无法切图、无对应节点)逐条列出。没有则写「无」。
|
|
53
|
+
6. **验收要点**:按当前已裁定契约验收,包括已确认的形态、控件数量和状态;不从旧 PRD 再引入已被覆盖的动作。
|
|
54
|
+
|
|
55
|
+
入口标识、路由或事件名称有真实来源则引用;由宿主按既有约定命名时,具体字符串留 tech。命名责任及目标未知时标待确认,不从自然语言名称推导。无图形 UI 时,页面形态、设计节点和视觉资产要求不适用,不虚构页面。
|
|
56
|
+
|
|
57
|
+
## 冲突处置
|
|
58
|
+
|
|
59
|
+
- 提问前先核对适用用户决定、项目约定和具体来源;已有权威能裁定的差异直接应用并引用依据,不把可查证事实重新变成用户问题。无法裁定且影响契约的剩余冲突才提问,不能把新推断写成用户答复。
|
|
60
|
+
- 图形 UI 根据需求、接口与已采集的设计定位/证据形成契约;本阶段使用已采集页面索引,除确认形态外不展开页面内部或截图;已发现的产品冲突依据现有权威处理。尚未读取的页面内部字段、文案和视觉详情留到 UI task 编码前核对;不因尚未详读就列缺口,也不推断未读内容。已经采集或实际答复中确认的设计文案、状态和交互,当前就按项目来源优先级应用;不能以本阶段只定位页面为由,把已知设计降为纯定位、改用已被覆盖的 PRD 口径。逐条摘录原文也不改变优先级;被覆盖的旧文案仅作为来源差异保留,不写成现行行为或验收。已读到的口径、单位和时间窗按来源记录,保留节点、来源版本/摘要和产物路径供后续复用。
|
|
61
|
+
- 影响页面形态、导航结构、入口位置、字段是否存在的冲突,**不要自选口径**:result 写 `blocked`,`questions` 每条冲突一个问题并附双方口径。用户答复后再次 `worker create --step parse` 会复用同一 packet,答复在 `packet.decisions[]`(questions / answers);按答复改写 spec(第 5 章的「已裁定」保留其具体约束,包括确认的形态、控件数量与状态,不只留下节点 ID;对应正文与验收使用同一口径)后重新 accept。
|
|
62
|
+
- 其余冲突写入第 5 章,留待 stop 节点汇报。
|
|
63
|
+
|
|
64
|
+
## 是否跳过 tech
|
|
65
|
+
|
|
66
|
+
只有 packet.skipTechAllowed 不为 false 且**同时**满足三条才可在 result 设 `"skipTech": true`,并在 `notes` 写明理由(引擎拒收无理由的跳过):
|
|
67
|
+
|
|
68
|
+
1. spec「能力与入口清单」≤ 1 项;
|
|
69
|
+
2. 没有新增或改动接口;
|
|
70
|
+
3. 已有依据确认现有范式直接可用,无需新增或扩展共享模块或组件;未知不能当作无需扩展。
|
|
71
|
+
|
|
72
|
+
否则走 tech 后再 plan。
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Plan
|
|
2
|
+
|
|
3
|
+
写出 `plan/task-plan.json`。每个 task 必须有 `category`,取值来自 packet.allowedCategories(默认 ui / logic / api-codegen / test / infra)。`packet.planNotes` 是各分类的说明。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
openspec worker create --change "<name>" --step plan --view summary --json
|
|
7
|
+
openspec worker accept --change "<name>" --result <path> --view summary --json
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Result 文件格式
|
|
11
|
+
|
|
12
|
+
`packet.expectedResult` 是严格 JSON(未知字段会被拒收):
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"workerId": "<packet.workerId>",
|
|
17
|
+
"stepId": "plan",
|
|
18
|
+
"status": "completed | failed | blocked",
|
|
19
|
+
"notes": "可选",
|
|
20
|
+
"questions": ["blocked 时每条一个问题"],
|
|
21
|
+
"executeHookResults": [{ "id": "<initContext.hooks[].id>", "status": "passed | failed | skipped", "notes": "可选" }]
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`plan/task-plan.json` 形如:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"tasks": [
|
|
30
|
+
{ "id": "T-001", "title": "生成声明接口的客户端", "category": "api-codegen", "dependsOn": [],
|
|
31
|
+
"capability": "interfaces", "operation": "codegen", "provider": "<configured-provider>",
|
|
32
|
+
"sourceRefs": ["src-3"], "notes": "..." },
|
|
33
|
+
{ "id": "T-002", "title": "实现范围内列表界面", "category": "ui", "dependsOn": ["T-001"],
|
|
34
|
+
"designRefs": ["<source-node-id>"], "refScope": ["src/features/list/"], "sourceRefs": ["src-1", "src-5"], "notes": "..." }
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
示例中的 provider、路径和设计节点必须替换为宿主及来源的真实值。capability/operation/provider 是任务描述,具体实现由适用 execute Hook 指导,不自动触发生成器。
|
|
40
|
+
|
|
41
|
+
字段:`id` 只能含字母数字 `-_.`;`category: api-codegen` 的 task 必须带 `capability` / `operation` / `provider` 三个字符串;`sourceRefs` 只能引用来源账本里的 source id;`refScope` 是项目内相对路径数组;`files` / `allowedDirs` 已移除。`designRefs` 是可选节点 id 数组;可省略/空数组,非空项必须为非空字符串,引擎去重但不校验节点存在性。
|
|
42
|
+
|
|
43
|
+
## 先加载 packet.initContext
|
|
44
|
+
|
|
45
|
+
按 skill descriptor 的明确路径加载指导;有 plugin.inputDescription/input 时按其契约准备参数。command Hook 必须通过 `openspec worker check --change "<name>" --id "<hook-id>" [--input "<项目内 JSON>"]` 执行,保留真实回执;文字 passed 不能代替执行。来源、配置、输入或代码变化后重跑失效检查。
|
|
46
|
+
|
|
47
|
+
处理 `initContext.hooks`(读取 file、遵守 notes、把 check 纳入自检),并在 result 的 `executeHookResults` 中按 id 逐项回执;required file 不存在或仍含 `openspec:fill-me` 标记时写 `blocked`。同会话已完整读取、仍可用且未变化的内容可复用;压缩丢失或文件变化时补读。
|
|
48
|
+
|
|
49
|
+
Gate-A 退回时先处理退回原因。若是已有来源的解释、复用适配或任务拆分错误,最小同步 tech 中受影响决定及 plan 引用,保留有效来源、规格和预演证据;不为这类纠错重跑 collect/parse。新来源或需求变化仍走 source-update,不手改状态。
|
|
50
|
+
|
|
51
|
+
## 拆分规则
|
|
52
|
+
|
|
53
|
+
- 按实现边界拆分;`dependsOn` 只能指向更早的 id;`refScope` 可选(预计涉及的文件或目录,仅供参考,不构成边界)。
|
|
54
|
+
- **横切关注点不拆独立 task**:国际化文案、主题色、loading / empty / error 态、请求失败提示、偏好共享等,必须在产生它们的 UI / logic task 内一次完成。不得出现「补充多语言」「补齐加载态」「统一错误处理」这类尾部 task。
|
|
55
|
+
- **UI task 的 `notes` 必须引用 spec「能力与入口清单」中的条目名与形态**(page / dialog / bottom-sheet / tab 子页),并引用「状态与交互」的对应章节和共同规则;不得改写形态。用文件路径、普通章节标题与页面名定位,不复制该页正文,也不引入章节标记协议或上下文文件。
|
|
56
|
+
- `packet.refs.tech` 存在时,UI task 的 `notes` 还须引用 tech「复用清单」与「状态与数据流」中该页对应条目(条目能定位复用组件、状态容器与加载模型);只补该任务的实现边界和验证,不复写技术表。task 拆分不得与 tech 决策冲突。tech 被跳过时,在本阶段按 [Tech 的复用适配规则](tech.md) 完成必要核对,将结论写入 task `notes`;不以跳过 tech 绕过范围判断。
|
|
57
|
+
- spec 中未裁定的产品冲突不得擅自生成已确定口径的实现 task;阻塞主流程时 result 写 `blocked` + `questions`。已裁定条目按依据实施。仅页面内部设计尚未详读的事项遵循下述编码前核对要求,不因出现在缺口章节就一律删除相关任务;若确实影响当前技术选择且没有可执行依据,保留真实阻塞。
|
|
58
|
+
- 存在接口层代码(api-codegen 或手写请求)时,安排一个 `test` 类 task 覆盖路径参数拼接与 GET/POST 传参方式。涉及鉴权刷新、重试或其他异步恢复时,包含恢复后再次失败的路径,从公开调用验证结果在有限时间内成功或抛出原约定异常;不能只验证正常返回或等待固定延时。
|
|
59
|
+
- 设计资产缺失的页面,task `notes` 写明「用占位组件并标注 TODO,不得以文字替代图片」。
|
|
60
|
+
- **UI task 的范围必须一次列全**:`refScope` / `notes` 除页面文件外,还要枚举本页切图的资源目录、资源注册清单文件、经适配核对需要扩展的共享组件文件、页面所属的弹层 / 底部面板文件;逐个引用 tech 的直接复用 / 扩展后复用 / 新建结论:已有参数足够只列调用方,需要扩展则列共享文件及所属 task,不把所有引用的组件都放入修改范围。漏列会在 Gate-A 后触发边界失败与重新规划,代价远高于计划阶段多列几行。宿主精确范围文件由 plan Hook 消费,目录级放开不能代替。
|
|
61
|
+
|
|
62
|
+
- UI task 实现的页面在 spec 有设计节点时,必须把页面与状态变体节点 id 填入 `designRefs`。没有设计稿的小改、布局调整、纯文案/逻辑修补可留空,并在 notes 写「无设计稿:按 <既有页面/组件路径> 现状与需求文字实现」。设计稿存在但业务映射未确定时保留候选范围,在 notes 说明 coding 先核定目标 frame;不能伪装为无稿,也不为补定位证明提前读截图。
|
|
63
|
+
- tech 列出的接口契约缺口(经 schema 核对仍未解决的空模型类、成功码映射、枚举冲突)必须落到明确 task 或在 Gate-A 阻断,不安排"手写解析器"绕过生成结果;列表 page/size 首屏值与路由真实字符串引用 tech/spec,不自行猜测。视觉基线按已确认项目约定/决定执行,仍未裁定的缺口保留 Gate-A 决策项。
|
|
64
|
+
|
|
65
|
+
任务引用相关 spec / tech 要求,notes 只补本任务特有边界、差异与验证方式。accept 前逐项核对:产品要求都有实施与验证归属、依赖可执行、引用能定位;spec 有设计节点的每个 `ui` task `designRefs` 非空,无稿的写明「无设计稿:…」依据;路由 / 入口接线放在目标页面 task 内或 `dependsOn` 它,不在页面生成前引用不存在的页面;UI task 范围含资源目录、注册文件、需覆盖的共享组件与弹层。没有归属的要求先修正计划,不靠笼统“覆盖全部 spec”代替。完整设计详读在编码前进行;范围决定缺必要证据时定向补读并同步复用结论,不为节点去重重复调用 MCP。已有权威决定能够裁定的事项直接引用依据。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# 停止
|
|
2
|
+
|
|
3
|
+
已到达 Gate-A。Gate-A 一经批准,spec 中的口径就会按现状实现,所以此处必须让用户知情。从当前 spec / tech / plan 与返回的状态汇报;同会话中已完整可用且未变化的内容可复用,必要时定点补读。直接输出,不新建摘要文件或派助手补报告:
|
|
4
|
+
|
|
5
|
+
汇报前对照 tech 的详细决定与 task 引用;缺失值、集合完整性和 schema 开放/封闭的条件保持一致,不能在摘要里省掉前提或换成另一种处理。发现矛盾先修正对应产物,再汇报。
|
|
6
|
+
|
|
7
|
+
1. spec / tech / plan 的路径。
|
|
8
|
+
2. spec「页面与入口清单」摘要:每页一行,含形态及其依据(设计节点 id / 需求原文 / 实际答复);形态写「未定」或只有需求措辞依据的页面单独点出。
|
|
9
|
+
3. spec「来源冲突与缺口」的全部条目与所有标「待确认」项,区分已裁定及其依据、仍未决的真实问题;只对后者请求决定或明确风险接受,不重复询问已裁定事项。
|
|
10
|
+
4. tech「复用清单」中全部标「新建」的条目及其理由——自造平台件是最常见的返工来源,请用户逐条确认;tech 被跳过时给出跳过理由。
|
|
11
|
+
5. task 数量与分类分布。
|
|
12
|
+
6. tech「偏离声明」:与项目文档不同的选择、理由和影响;无偏离也明确报告。
|
|
13
|
+
7. 「接口缺口处置」:wire type/枚举冲突、真实 path、各接口成功码及映射到的宿主判定入口(逐接口,不接受"统一为 0/200")、生成预演摘要中的空模型类清单及 schema 核对结果(开放对象丢数据则阻断;明确封闭且符合使用契约的空对象记录依据后通过;语义未定保留缺口)、分页初值和服务端 routeName 的依据及未决项。
|
|
14
|
+
8. 「设计定位」:汇报已定位页面、候选范围及仍未确定的映射;页面内部视觉尚未详读不构成当前缺口。已裁定的映射方式直接引用,不重复询问。
|
|
15
|
+
9. 若最新返回没有 `uiTasksWithoutDesignRefs`,执行一次 `openspec status --change "<name>" --json`。报告 `uiTasksWithoutDesignRefs` 中每个 task 的 id、标题及无稿实现依据,区分确实无稿与已有候选但映射待定,不要求用户将未定位节点确认为无稿。该清单仅在账本存在 design 源时计算;空清单不证明设计已校验。
|
|
16
|
+
|
|
17
|
+
然后等待用户走 `/opsx-apply` 或 `/opsx-gate-decision`。
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Tech
|
|
2
|
+
|
|
3
|
+
写 `tech.md`:把 spec 的「是什么」映射到本项目的「怎么做」。横切决策写在这里,不散落到单个 task;不复述 spec.md。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
openspec worker create --change "<name>" --step tech --view summary --json
|
|
7
|
+
openspec worker accept --change "<name>" --result <path> --view summary --json
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Result 文件格式
|
|
11
|
+
|
|
12
|
+
`packet.expectedResult` 是严格 JSON(未知字段会被拒收):
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"workerId": "<packet.workerId>",
|
|
17
|
+
"stepId": "tech",
|
|
18
|
+
"status": "completed | failed | blocked",
|
|
19
|
+
"notes": "可选",
|
|
20
|
+
"questions": ["blocked 时每条一个问题"],
|
|
21
|
+
"executeHookResults": [{ "id": "<initContext.hooks[].id>", "status": "passed | failed | skipped", "notes": "可选" }]
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 先加载 packet.initContext
|
|
26
|
+
|
|
27
|
+
按 skill descriptor 的明确路径加载指导;有 plugin.inputDescription/input 时按其契约准备参数。command Hook 必须通过 `openspec worker check --change "<name>" --id "<hook-id>" [--input "<项目内 JSON>"]` 执行,保留真实回执;文字 passed 不能代替执行。来源、配置、输入或代码变化后重跑失效检查。
|
|
28
|
+
|
|
29
|
+
读取 file、遵守 notes、把 check 纳入自检,并在 result 的 `executeHookResults` 中按 id 逐项回执;required file 不存在或仍含 `openspec:fill-me` 标记时写 `blocked`。同会话中已完整读取、内容仍可用且未变化的文件可复用;压缩丢失或文件变化时补读。
|
|
30
|
+
|
|
31
|
+
从 spec 与项目约定给出的目录、路径和符号开始,批量检索后读取足以验证复用、默认行为和调用方的实现。相同能力只调查一次,证据足够即停止扩展;不要逐页面重搜全仓。来源按 packet 的账本定位 artifact,同路径或相同摘要且正文仍在上下文中时复用。
|
|
32
|
+
|
|
33
|
+
## 一次取得所需证据
|
|
34
|
+
|
|
35
|
+
按来源账本定位 artifact。直接读取原文,或使用绑定的 source adapter 定向读取;格式、字段选择和工具兼容说明由 adapter 与适用 Hook 提供,不从文件名猜测来源格式。已知字段和已读事实直接使用,不为再次确认重取目录。
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
openspec sources read --change "<name>" --source "<source-id>" --json
|
|
39
|
+
openspec sources read --change "<name>" --source "<source-id>" --input "<query.json>" --json
|
|
40
|
+
openspec worker check --change "<name>" --id "<command-hook-id>" --input "<input.json>" --json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
定向读取必须保留所选字段的原文、祖先约束和业务说明;required、nullable、未定义分别核对,不从摘要推断引用或联合类型。大查询按 adapter 给出的可读路径继续;部分提示不是完整字段清单,父对象也不等于选定子字段。原始 artifact 始终是证据来源。
|
|
44
|
+
|
|
45
|
+
项目配置了生成预演 Hook 时,按其输入说明分配相关来源与宿主入口,通过 `worker check` 执行。核对真实生成方法、参数、请求地址、模型及未保留的数据;按回执路径读取完整结果,不能用摘要替代类型、业务说明、公式和边界。预演只读来源与业务源码,不能当作编译或业务验收。工具兼容范围和临时替代项由插件明确报告,不能把空模型当作动态数据已保留。首轮插件调用不自动复用;已有完整证据足够时按路径读取,不无故重跑。
|
|
46
|
+
|
|
47
|
+
检索结果不是复用证明。**确定复用及文件范围前**,先应用宿主声明「以宿主为准」的项;对其余拟复用组件,将目标截图及必要 Meta / 样式与组件 API、默认值对照。只读会改变复用、新建或修改文件范围的设计事实;优先复用已有原始证据,缺少时定向补读目标节点,不全量展开页面、不提前下载实现资源。共享组件只核对一次,各调用记录差异。结论附设计节点/证据路径、实际参数或能力缺口:
|
|
48
|
+
|
|
49
|
+
- **直接复用**(含传已有参数):写清现有参数如何满足需要,只修改调用方。
|
|
50
|
+
- **扩展后复用**:写清缺失能力、要修改的共享文件和保留旧调用默认行为的方式。
|
|
51
|
+
- **新建**:现有实现不适用的原因与新文件位置。
|
|
52
|
+
|
|
53
|
+
不存在对应参数时不得写「按调用覆盖」。影响范围的适配尚无依据就保留 blocked,不把未知标成直接复用。完整布局、样式与切图清单仍由 scout 补齐。
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## 产品语义与接口绑定
|
|
57
|
+
|
|
58
|
+
spec 的字段关联是核对入口,不是已批准的字段绑定。选择字段前对照产品要求和接口的公式、单位、范围、时间窗及状态含义;同名或来源较新不证明语义相同。不同控件或生命周期的约束分别处理,不互相覆盖。能够从已有字段可靠组合得到产品要求时写明组合、取数完整性和边界;证据不足以实现时保留该项未决并按 blocked 处理。不能一边选用已知不符合产品口径的字段,一边只在风险章节保留冲突后完成阶段。
|
|
59
|
+
|
|
60
|
+
聚合值须写明集合是否完整、必需项缺失或不可解析时的处理;未取完分页与字段缺失不能靠跳过条目或补零变成完整总额。部分合计只有产品明确允许且界面标明时才成立;完整空集合与未知数据分别处理。用“完整项与缺失项混合”的反例核对详细算法、风险说明和任务引用是否一致,Gate 汇报保留同样前提。
|
|
61
|
+
|
|
62
|
+
对象是否开放、是否允许 null、当前样例是否为空分别判断。不能仅凭 `properties: {}` 或样例 `null` 声称封闭;先核对完整 schema 的额外属性约束(JSON Schema 缺省允许额外属性),记录依据。生成器保留 Map 与空类数为零只能证明生成结果,不能替代 schema 语义。
|
|
63
|
+
|
|
64
|
+
## tech.md 必备章节
|
|
65
|
+
|
|
66
|
+
1. **上下文**:与本 change 相关的目录约定、数据流模式(按实际状态管理和事件机制)、网络层形态、既有入口。引用权威文档及必要代码证据,只写影响本 change 的现状与新增选择,不转录通用目录和架构教程。
|
|
67
|
+
2. **复用清单**:spec「能力与入口清单」中每项能力(按实际界面、服务、存储、格式化和外部调用)→ 项目既有组件或范式的具体路径 / 类名。按上述直接复用 / 扩展后复用 / 新建结论填写,共享能力只写一项,各页面列差异;不能仅因名称不同新建同类组件。
|
|
68
|
+
3. **状态与数据流**:spec「状态与交互」中每个能力 → 状态容器或执行上下文、结果模型、失败传播、刷新或重新执行的触发方、跨模块联动契约(使用公开接口,不访问组件私有状态)。共同流定义一次,每页保留不同的事件、状态与失败恢复;引用 spec 章节,不再复制交互正文。已裁定行为直接实施;来源未定的产品口径不能通过技术选择暗自确定。
|
|
69
|
+
4. **接口接入**:从 spec 产品字段及其来源关联逐项核对接口字段、wire type 与真实 path,在本章完整记录映射及缺口处置,引用产品语义而不复写页面正文。写清生成 vs 手写、路径参数写法、GET / POST 传参方式。禁止选择文档标注仅展示的假路径;核实真实 endpoint。枚举与 wire type 冲突须列证据与处置,不猜转换。成功码、状态码等值语义以各接口 description / 示例原文为准,逐接口记录并映射到宿主既有判定入口;schema 缺 enum 不是否定 description 的理由,端点之间的差异分别映射,不统一口径,也不改共享默认。生成预演摘要中的空模型类须逐项对照 schema:开放对象被生成为空类而丢数据则 blocked,回工具项目修复;来源明确声明封闭空对象且符合使用契约,记录依据后通过;语义未定列缺口。不按空类数量一律阻断。凡接口声明 page/size 的列表,写清首屏取值及依据,未知则列缺口。
|
|
70
|
+
5. **国际化与主题**:适用时引用项目约定的路径和章节,仅记录本 change 的资源键命名、新增资源/颜色选择或例外;不重复通用调用方式、命令和整张 token 表;无相关需求注明不适用。
|
|
71
|
+
6. **视觉基线**:引用已有设计定位和项目 ui-conventions.md 的变量、字体与双主题资源章节,不转录表格;本阶段按上述复用适配规则定向读取影响决策的截图、Meta、样式或变量,记录原始证据路径供 scout 复用。尚未读取的页面字段/文案详情由 UI task 编码前核对,尚未详读本身不构成 Gate-A 阻塞;已经采集或实际答复中确认的设计事实当前就按项目来源优先级应用。表外变量按项目约定与适用决定处理,记录来源、映射和理由;影响当前决策且现有权威不能裁定的缺口才交 Gate-A。无图形 UI 时注明不适用。
|
|
72
|
+
7. **偏离声明**:逐条对照 项目实际状态管理和架构文档;偏离既有状态管理/架构惯例时写「原约定 + 本次选择 + 理由 + 影响」,供 Gate-A 明确裁定。未偏离写「无」。
|
|
73
|
+
8. **风险与迁移**:只记本 change 的具体风险、兼容影响与处理,不堆通用检查项。
|
|
74
|
+
|
|
75
|
+
每条决策写「决定 + 一句理由」;能引用项目现有文件就写路径,不写抽象原则。「新建」项会在 Gate-A 前逐条呈给用户。
|
|
76
|
+
|
|
77
|
+
完成前对照 spec:每个范围内能力均有可追溯的技术归属,接口接入、复用/新建、状态与必要的异常处理可供 plan 拆任务。不能靠把必要决定留给 code 缩短 tech;真正缺失的外部契约或实质冲突保留证据与问题,按现有 blocked/Gate 边界处理。
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Lossless original JSON display; format-specific views belong to source adapters.
|
|
3
|
+
import { readFileSync, realpathSync } from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
try {
|
|
6
|
+
const [source, ...args] = process.argv.slice(2);
|
|
7
|
+
if (source === '--help' && !args.length) {
|
|
8
|
+
console.log('Usage: node read-json-source.mjs SOURCE\nLossless JSON original text, within the current project; no writes. Format-specific selection uses openspec sources read with an explicit adapter.');
|
|
9
|
+
process.exit(0);
|
|
10
|
+
}
|
|
11
|
+
if (!source || args.length) throw new Error('Expected only SOURCE. Format-specific options use openspec sources read and its adapter input.');
|
|
12
|
+
const root = realpathSync(process.cwd());
|
|
13
|
+
const file = realpathSync(path.resolve(root, source));
|
|
14
|
+
const relative = path.relative(root, file);
|
|
15
|
+
if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) throw new Error('Source must be inside the current project');
|
|
16
|
+
const text = readFileSync(file, 'utf8');
|
|
17
|
+
JSON.parse(text); // Validate before stdout; never reserialize numbers or unknown fields.
|
|
18
|
+
process.stdout.write(text);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
21
|
+
process.exitCode = 1;
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opsx-resume
|
|
3
|
+
description: 根据 status.next 路由到正确的 workflow,不猜测进度。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# opsx-resume
|
|
7
|
+
|
|
8
|
+
## 项目 CLI 预检
|
|
9
|
+
|
|
10
|
+
定位项目根并校验 CLI 版本。
|
|
11
|
+
|
|
12
|
+
## 循环
|
|
13
|
+
|
|
14
|
+
只跑一轮路由,不执行具体 worker。
|
|
15
|
+
|
|
16
|
+
1. `openspec list --json`(必要时)
|
|
17
|
+
2. 读取 nodes/route.md
|
|
18
|
+
|
|
19
|
+
## 退出条件
|
|
20
|
+
|
|
21
|
+
给出应启动的 workflow 后停止,或转交给该 skill。
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# 路由
|
|
2
|
+
|
|
3
|
+
根据 `next.action`:
|
|
4
|
+
|
|
5
|
+
- add_sources / collect / parse / tech / plan → `/opsx-propose`
|
|
6
|
+
- sourceUpdate 活跃 → `/opsx-source-update`
|
|
7
|
+
- await_gate → `/opsx-gate-decision` 或对应 apply/verify/archive
|
|
8
|
+
- create_worker code-* → `/opsx-apply`
|
|
9
|
+
- create_worker verify / fix_verify → `/opsx-verify` 或 `/opsx-fix-verify`
|
|
10
|
+
- archive → `/opsx-archive`
|
|
11
|
+
|
|
12
|
+
不要根据文件是否存在猜测阶段。
|