@namewta/speculo 0.7.6 → 0.8.0

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 (33) hide show
  1. package/README.md +4 -5
  2. package/dist/src/cli.js +18 -13
  3. package/dist/src/cli.js.map +1 -1
  4. package/dist/src/config.d.ts +20 -0
  5. package/dist/src/config.js +94 -0
  6. package/dist/src/config.js.map +1 -0
  7. package/dist/src/index.d.ts +3 -2
  8. package/dist/src/index.js +56 -27
  9. package/dist/src/index.js.map +1 -1
  10. package/dist/src/manifest.d.ts +20 -0
  11. package/dist/src/manifest.js +57 -0
  12. package/dist/src/manifest.js.map +1 -0
  13. package/dist/src/refresh.d.ts +30 -0
  14. package/dist/src/refresh.js +465 -0
  15. package/dist/src/refresh.js.map +1 -0
  16. package/dist/src/structured.d.ts +12 -0
  17. package/dist/src/structured.js +236 -0
  18. package/dist/src/structured.js.map +1 -0
  19. package/package.json +2 -2
  20. package/template/.speculo/README.md +12 -11
  21. package/template/.speculo/refresh-contract.json +30 -0
  22. package/template/skills/github-npm-ops/references/preflight-checklist.md +1 -1
  23. package/template/workflows/person/runtime-contract.json +9 -0
  24. package/template/workflows/specdev/I-init-setup/I-init-setup.md +1 -1
  25. package/template/workflows/specdev/INDEX.md +7 -8
  26. package/template/workflows/specdev/runtime-contract.json +26 -0
  27. package/dist/src/migrations.d.ts +0 -23
  28. package/dist/src/migrations.js +0 -1202
  29. package/dist/src/migrations.js.map +0 -1
  30. package/template/commands/migrate-runtime-state.md +0 -43
  31. package/template/skills/migrate-runtime-state/SKILL.md +0 -93
  32. package/template/skills/migrate-runtime-state/references/migration-contract.md +0 -64
  33. package/template/skills/migrate-runtime-state/scripts/migrate-runtime-state.mjs +0 -916
@@ -0,0 +1,236 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { assertJsonObject } from "./config.js";
4
+ import { pathExists } from "./utils.js";
5
+ const CHANGE_NAME = /^[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]+(?:-[a-z0-9]+)*$/;
6
+ async function readObject(path, label) {
7
+ let value;
8
+ try {
9
+ value = JSON.parse(await readFile(path, "utf8"));
10
+ }
11
+ catch (error) {
12
+ throw new Error(label + " is not valid JSON: " + String(error));
13
+ }
14
+ assertJsonObject(value, label);
15
+ return value;
16
+ }
17
+ function object(value) {
18
+ return value !== null && typeof value === "object" && !Array.isArray(value)
19
+ ? value
20
+ : {};
21
+ }
22
+ function positiveInteger(value, fallback) {
23
+ return Number.isInteger(value) && Number(value) >= 1 ? Number(value) : fallback;
24
+ }
25
+ export function migrateSpecdevConfig(local, defaults) {
26
+ const version = Number(local.schema_version);
27
+ if (version === 5)
28
+ return { value: local, migrated: false };
29
+ if (version !== 3 && version !== 4) {
30
+ throw new Error("SpecDev config supports schema v3, v4, or v5; found " + String(local.schema_version));
31
+ }
32
+ const localGit = object(local.git);
33
+ const localExecution = object(local.execution);
34
+ const defaultGit = object(defaults.git);
35
+ const defaultExecution = object(defaults.execution);
36
+ const allowedRoot = new Set([
37
+ "schema_version", "interaction_language", "artifact_language", "git",
38
+ "execution", "verification", "planning",
39
+ ]);
40
+ const unknownRoot = Object.keys(local).filter((key) => !allowedRoot.has(key));
41
+ if (unknownRoot.length > 0)
42
+ throw new Error("SpecDev config has unmapped root fields: " + unknownRoot.join(", "));
43
+ const legacyLimit = positiveInteger(localExecution.max_implementation_agents ?? localExecution.max_parallel, positiveInteger(defaultExecution.max_implementation_agents, 3));
44
+ return {
45
+ migrated: true,
46
+ value: {
47
+ schema_version: 5,
48
+ interaction_language: local.interaction_language ?? defaults.interaction_language,
49
+ artifact_language: local.artifact_language ?? defaults.artifact_language,
50
+ git: {
51
+ default_branch: typeof localGit.default_branch === "string" || localGit.default_branch === null
52
+ ? localGit.default_branch
53
+ : defaultGit.default_branch ?? null,
54
+ },
55
+ execution: {
56
+ max_implementation_agents: legacyLimit,
57
+ max_integration_attempts: positiveInteger(localExecution.max_integration_attempts, positiveInteger(defaultExecution.max_integration_attempts, 3)),
58
+ deep_ticket_human_approval: typeof localExecution.deep_ticket_human_approval === "boolean"
59
+ ? localExecution.deep_ticket_human_approval
60
+ : defaultExecution.deep_ticket_human_approval,
61
+ shared_path_owner: typeof localExecution.shared_path_owner === "string"
62
+ ? localExecution.shared_path_owner
63
+ : defaultExecution.shared_path_owner,
64
+ },
65
+ verification: Object.keys(object(local.verification)).length > 0 ? local.verification : defaults.verification,
66
+ planning: Object.keys(object(local.planning)).length > 0 ? local.planning : defaults.planning,
67
+ },
68
+ };
69
+ }
70
+ export function validateSpecdevConfig(config) {
71
+ if (config.schema_version !== 5)
72
+ throw new Error("SpecDev config schema_version must be 5");
73
+ if (typeof config.interaction_language !== "string" || typeof config.artifact_language !== "string") {
74
+ throw new Error("SpecDev config language values must be strings");
75
+ }
76
+ const git = object(config.git);
77
+ if (!(git.default_branch === null || typeof git.default_branch === "string")) {
78
+ throw new Error("SpecDev config git.default_branch must be a string or null");
79
+ }
80
+ const execution = object(config.execution);
81
+ for (const key of ["max_implementation_agents", "max_integration_attempts"]) {
82
+ if (!Number.isInteger(execution[key]) || Number(execution[key]) < 1) {
83
+ throw new Error("SpecDev config execution." + key + " must be a positive integer");
84
+ }
85
+ }
86
+ if (typeof execution.deep_ticket_human_approval !== "boolean" || typeof execution.shared_path_owner !== "string") {
87
+ throw new Error("SpecDev config execution settings are incomplete");
88
+ }
89
+ }
90
+ function authorization(scope) {
91
+ return { status: "not-authorized", source: null, granted_at: null, scope };
92
+ }
93
+ function normalizeChangeStatus(previous, globalEntry) {
94
+ const version = Number(previous.schema_version);
95
+ if (![3, 4, 5, 6].includes(version)) {
96
+ throw new Error("change status supports schema v3-v6; found " + String(previous.schema_version));
97
+ }
98
+ if (previous.artifact !== "change-status" || typeof previous.change !== "string" || !CHANGE_NAME.test(previous.change)) {
99
+ throw new Error("change status has an invalid artifact or change name");
100
+ }
101
+ const worktrees = Array.isArray(previous.worktrees) ? previous.worktrees : [];
102
+ if (version <= 3 && worktrees.length > 0) {
103
+ throw new Error("schema v3 worktree state requires an explicit migration decision");
104
+ }
105
+ if (version === 6)
106
+ return previous;
107
+ const now = typeof previous.updated_at === "string"
108
+ ? previous.updated_at
109
+ : typeof previous.created_at === "string" ? previous.created_at : new Date().toISOString();
110
+ const status = String(previous.change_status);
111
+ const change = previous.change;
112
+ const base = version === 3 ? {
113
+ schema_version: 4,
114
+ artifact: "change-status",
115
+ change,
116
+ change_status: status,
117
+ current_work: typeof previous.current_work === "string" ? previous.current_work : null,
118
+ created_at: typeof previous.created_at === "string" ? previous.created_at : now,
119
+ updated_at: now,
120
+ completed_at: typeof previous.completed_at === "string" ? previous.completed_at : null,
121
+ archived: status === "archived",
122
+ archive_path: status === "archived" ? `<Path>{roots.state}/specdev/archive/${change.slice(0, 7)}/${change}</Path>` : null,
123
+ blockers: Array.isArray(previous.blockers) ? previous.blockers : [],
124
+ deviations: Array.isArray(previous.deviations) ? previous.deviations : [],
125
+ worktrees: [],
126
+ } : previous;
127
+ const upgraded = Number(base.schema_version) === 4 ? {
128
+ ...base,
129
+ schema_version: 5,
130
+ current_work: typeof base.current_work === "string" ? base.current_work : globalEntry?.current_work ?? null,
131
+ works_run: Array.isArray(globalEntry?.works_run) ? globalEntry.works_run : [],
132
+ claimed_investigations: Array.isArray(globalEntry?.claimed_investigations) ? globalEntry.claimed_investigations : [],
133
+ execution_authorization: {
134
+ implementation_commit: authorization("Ticket implementation commits"),
135
+ local_candidate_integration: authorization("Lead-owned local integration and parent update"),
136
+ source_cleanup: authorization("Source worktree and branch cleanup"),
137
+ },
138
+ leadership: { current: "unassigned", epoch: 1, assigned_at: now, history: [] },
139
+ } : base;
140
+ return { ...upgraded, schema_version: 6 };
141
+ }
142
+ function migrateGoalPlan(text, attempts) {
143
+ if (!/^---\s*$/m.test(text))
144
+ return text;
145
+ let next = text;
146
+ if (/^schema_version:\s*4\s*$/m.test(next))
147
+ next = next.replace(/^schema_version:\s*4\s*$/m, "schema_version: 5");
148
+ if (/^schema_version:\s*5\s*$/m.test(next)) {
149
+ next = next
150
+ .replace(/^schema_version:\s*5\s*$/m, "schema_version: 6")
151
+ .replace(/^(implementation_agent_limit:\s*[^\n]+)$/m, `$1\nintegration_attempt_limit: ${attempts}`);
152
+ }
153
+ return next;
154
+ }
155
+ async function rewriteIfChanged(path, value, reason, changes) {
156
+ const before = await readFile(path);
157
+ if (before.equals(Buffer.from(value)))
158
+ return;
159
+ changes.push({ path, before, reason });
160
+ await writeFile(path, value, "utf8");
161
+ }
162
+ async function migrateSpecdevState(stagedRoot) {
163
+ const changes = [];
164
+ const stateRoot = join(stagedRoot, ".speculo", "specdev");
165
+ const statusPath = join(stateRoot, "status.json");
166
+ if (!(await pathExists(statusPath)))
167
+ return changes;
168
+ const status = await readObject(statusPath, ".speculo/specdev/status.json");
169
+ if (![4, 5].includes(Number(status.schema_version)) || status.workflow !== "specdev" || !Array.isArray(status.active) || !Array.isArray(status.archived)) {
170
+ throw new Error("SpecDev status must use schema v4/v5 with active and archived arrays");
171
+ }
172
+ const active = status.active.map((entry) => {
173
+ assertJsonObject(entry, "SpecDev active status entry");
174
+ if (typeof entry.change !== "string" || !CHANGE_NAME.test(entry.change))
175
+ throw new Error("SpecDev active change name is invalid");
176
+ return entry;
177
+ });
178
+ const archived = status.archived.map((entry) => {
179
+ if (typeof entry !== "string" || !CHANGE_NAME.test(entry))
180
+ throw new Error("SpecDev archived change name is invalid");
181
+ return entry;
182
+ });
183
+ const activeNames = new Set(active.map((entry) => String(entry.change)));
184
+ if (activeNames.size !== active.length || new Set(archived).size !== archived.length || archived.some((name) => activeNames.has(name))) {
185
+ throw new Error("SpecDev status contains duplicate or overlapping change names");
186
+ }
187
+ if (status.schema_version === 4) {
188
+ await rewriteIfChanged(statusPath, JSON.stringify({
189
+ schema_version: 5,
190
+ workflow: "specdev",
191
+ active,
192
+ archived,
193
+ }, null, 2) + "\n", "upgrade SpecDev global status schema v4 to v5", changes);
194
+ }
195
+ let attempts = 3;
196
+ const configPath = join(stateRoot, "config.json");
197
+ if (await pathExists(configPath)) {
198
+ const config = await readObject(configPath, ".speculo/specdev/config.json");
199
+ attempts = positiveInteger(object(config.execution).max_integration_attempts, 3);
200
+ }
201
+ const indexed = [
202
+ ...active.map((entry) => ({ path: join(stateRoot, "changes", String(entry.change), ".status.json"), entry })),
203
+ ...archived.map((name) => ({ path: join(stateRoot, "archive", name.slice(0, 7), name, ".status.json"), entry: null })),
204
+ ];
205
+ for (const item of indexed) {
206
+ if (!(await pathExists(item.path)))
207
+ throw new Error("indexed SpecDev change is missing " + item.path);
208
+ const previous = await readObject(item.path, item.path);
209
+ const normalized = normalizeChangeStatus(previous, item.entry);
210
+ await rewriteIfChanged(item.path, JSON.stringify(normalized, null, 2) + "\n", "upgrade SpecDev change status schema", changes);
211
+ const goalPlanPath = join(dirname(item.path), "goal-plan.md");
212
+ if (await pathExists(goalPlanPath)) {
213
+ const goalPlan = await readFile(goalPlanPath, "utf8");
214
+ await rewriteIfChanged(goalPlanPath, migrateGoalPlan(goalPlan, attempts), "upgrade Goal Plan schema", changes);
215
+ }
216
+ }
217
+ return changes;
218
+ }
219
+ async function validatePersonState(stagedRoot) {
220
+ const statusPath = join(stagedRoot, ".speculo", "person", "status.json");
221
+ if (!(await pathExists(statusPath)))
222
+ return;
223
+ const status = await readObject(statusPath, ".speculo/person/status.json");
224
+ if (status.schema_version !== 1 || status.workflow !== "person" || !Array.isArray(status.active)) {
225
+ throw new Error("Person status must use schema v1 with an active array");
226
+ }
227
+ }
228
+ export async function migrateStructuredRuntime(stagedRoot, selectedWorkflowIds) {
229
+ const changes = [];
230
+ if (selectedWorkflowIds.includes("specdev"))
231
+ changes.push(...await migrateSpecdevState(stagedRoot));
232
+ if (selectedWorkflowIds.includes("person"))
233
+ await validatePersonState(stagedRoot);
234
+ return changes;
235
+ }
236
+ //# sourceMappingURL=structured.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured.js","sourceRoot":"","sources":["../../src/structured.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namewta/speculo",
3
- "version": "0.7.6",
3
+ "version": "0.8.0",
4
4
  "description": "Workflow-packaged specification-driven development assets with state-safe refresh tooling.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,7 +13,7 @@
13
13
  "pretest": "pnpm build",
14
14
  "generate-canonical": "node scripts/generate-specdev-canonical.mjs",
15
15
  "validate-source-parity": "node scripts/check-specdev-source-parity.mjs",
16
- "validate-assets": "node scripts/check-specdev-source-parity.mjs && node scripts/generate-specdev-canonical.mjs --check && node scripts/validate-framework-assets.mjs && node scripts/check-template-links.mjs",
16
+ "validate-assets": "node scripts/check-specdev-source-parity.mjs && node scripts/generate-specdev-canonical.mjs --check && node scripts/validate-refresh-contracts.mjs && node scripts/validate-framework-assets.mjs && node scripts/check-template-links.mjs",
17
17
  "check": "pnpm test && pnpm validate-assets",
18
18
  "verify-bin": "node scripts/verify-bin.mjs",
19
19
  "prepack": "pnpm build",
@@ -4,21 +4,22 @@
4
4
 
5
5
  ## 刷新契约
6
6
 
7
- 重新运行 `speculo init` 会以当前模板刷新 commands、skills 与选中的 workflow 静态资产,并对 v0.7+ 运行时执行兼容检查。兼容时递归合并项目配置的当前默认值,并完整保留 workflow 配置、状态索引、`changes/`、`archive/`、永久知识、sidecarcommand 报告和具有当前合同的 command `state.json`。
7
+ 重新运行 `speculo init` 会以当前模板替换 commands、skills、CLI metadata 与选中的 workflow 静态资产。`.speculo/managed.json` 逐文件记录受管理路径、ownerkind、版本与 SHA-256;未选中的当前受支持 workflow 包保持原样,已移除或未知的静态包不会被带入新安装。
8
8
 
9
- 每次刷新先把旧 `config.json` 和旧 `.speculo/` 快照写入 `back/`,排除上一份 `back/` 与旧 pending marker,因此只保留最近一次刷新前备份。`install.json` 记录当前包版本和已安装 workflows;`back/manifest.json` 记录来源/目标版本及每个备份文件的 hash 和大小。
9
+ 普通 runtime 文件默认 opaque,由 CLI 按字节复制并在替换前复验 hash,不因为扩展名是 JSON 而解析。只有 workflow `runtime-contract.json` 登记的配置和结构化状态进入 schema migrator;未知结构化版本、损坏内容或符号链接会在替换前阻塞,当前安装保持不变。
10
10
 
11
- 若来源版本、核心 schema、JSON、符号链接、command state owner workflow 索引无法证明兼容,刷新安装当前干净模板状态并创建 `migration.json`,其 `status` 为 `pending`。此时所有 workflow 读取和状态写入都必须停止;只能运行 `migrate-runtime-state` command,基于只读 `back/` 逐项对账、确认并原子迁移。再次运行 `speculo init` 会在任何修改前阻塞。
11
+ 配置使用 `.speculo/baselines/` 中的上次模板默认值执行 base/local/incoming 三方合并:模板新增项自动增加,模板删除项直接删除,未被用户修改的旧默认值跟随模板更新,用户覆盖值在满足目标合同的前提下保留。只有字段删除、显式 schema 迁移或结构化文件变换时,CLI 才把原文件写入 `back/` 并生成 targeted manifest;opaque 内容不会被整包复制到备份。
12
+
13
+ `install.json` 使用 schema v2,记录包版本、已安装 workflows、managed manifest 路径和 baseline schema。初始化以项目锁、完整 staging、active fingerprint 复验、原子 rename 与失败 rollback 组成一个事务;冲突不会发布部分结果,也不会创建新的 pending marker。
12
14
 
13
15
  ## 读取顺序
14
16
 
15
17
  1. 读取 `workspace.json`,以当前打开项目为 `project_root` 解析公共 roots。
16
- 2. 检查 `migration.json`;存在 pending 时停止,仅路由到 `migrate-runtime-state` command。
17
- 3. `../workflows/<workflow>/INDEX.md` 进入 workflow,再通过 `<Path>` 指针进入具体 work 入口文件。
18
- 4. 读取 `<workflow>/status.json`,再读取 `changes/<change>/.status.json` 和当前 work 产物。
19
- 5. 历史 change 只从 `<workflow>/archive/YYYY-MM/<change>/` 读取。
20
- 6. Command 报告位于 `commands/<command>/*.md`,command state 位于 `commands/<command>/state.json`。
21
- 7. 首次 docs-sync 确认后读取 `<workflow>/docs-sync.json`;它分列该 workflow 的项目文档和私有 state 更新范围。
18
+ 2. `../workflows/<workflow>/INDEX.md` 进入 workflow,再通过 `<Path>` 指针进入具体 work 入口文件。
19
+ 3. 读取 `<workflow>/status.json`,再读取 `changes/<change>/.status.json` 和当前 work 产物。
20
+ 4. 历史 change 只从 `<workflow>/archive/YYYY-MM/<change>/` 读取。
21
+ 5. Command 报告位于 `commands/<command>/*.md`,command state 位于 `commands/<command>/state.json`。
22
+ 6. 首次 docs-sync 确认后读取 `<workflow>/docs-sync.json`;它分列该 workflow 的项目文档和私有 state 更新范围。
22
23
 
23
24
  ## 写入边界
24
25
 
@@ -26,5 +27,5 @@
26
27
  - `docs-sync.json` 是 docs-sync command 拥有的延迟 sidecar,不进入 `_state`,也不授予越过 workflow 确认规则的权限。
27
28
  - `.config` 不是标准目录;只有 workflow 声明时才可使用。
28
29
  - Command 报告命名为 `<YYYY-MM-DD>-<scope>-<topic>[-NN].md`,禁止覆盖。
29
- - `back/` 由 `speculo init` 单一写入,迁移 command 只读;workflow 和其他 commands 不得修改。
30
- - `install.json``migration.json` 由 CLI/迁移脚本拥有,workflow 不得创建、修改或删除。
30
+ - `back/` 由 `speculo init` 单一写入;workflow commands 不得修改。
31
+ - `install.json`、`managed.json`、`baselines/`refresh contract 由 CLI 拥有,workflow 不得创建、修改或删除。
@@ -0,0 +1,30 @@
1
+ {
2
+ "schema_version": 1,
3
+ "runtime_root": ".speculo",
4
+ "managed_roots": [
5
+ "commands",
6
+ "skills",
7
+ "workflows"
8
+ ],
9
+ "managed_metadata": [
10
+ ".speculo/README.md",
11
+ ".speculo/workspace.json",
12
+ ".speculo/refresh-contract.json"
13
+ ],
14
+ "reserved_runtime": [
15
+ "README.md",
16
+ "workspace.json",
17
+ "refresh-contract.json",
18
+ "install.json",
19
+ "managed.json",
20
+ "migration.json",
21
+ "baselines",
22
+ "back"
23
+ ],
24
+ "project_config": {
25
+ "path": "config.json",
26
+ "baseline": ".speculo/baselines/config.json",
27
+ "schema_version": 1,
28
+ "additional_properties": true
29
+ }
30
+ }
@@ -16,7 +16,7 @@
16
16
  | 7 | 包管理器 | `pnpm --version` (或 `npm` / `yarn`) | 版本 ≥ 仓库 lockfile 隐含版本 | 安装匹配版本;不要随意切换包管理器 |
17
17
  | 8 | release.yml 存在 | `test -f .github/workflows/release.yml` | 文件存在 | 转 `github-npm-ops` skill 的 `references/workflow-yaml-reference.md` 先落该文件 |
18
18
  | 9 | release.yml 形态 | 见 [publish-detection.md](publish-detection.md) | 输出 `PUBLISH_TO_NPM=true` 或 `false` | 见 publish-detection 文档的判定矩阵 |
19
- | 10 | docs-sync state | `test -f speculo/.speculo/commands/docs-sync/state.json && jq . speculo/.speculo/commands/docs-sync/state.json` | schema v4、scope 已确认,baseline 可解析 | 不存在/未确认 → 走 docs-sync command bootstrap;旧 schema 或损坏 → 运行 `speculo init` 建立 pending 备份,再以 `migrate-runtime-state` command 修复后确认范围 |
19
+ | 10 | docs-sync state | `test -f speculo/.speculo/commands/docs-sync/state.json && jq . speculo/.speculo/commands/docs-sync/state.json` | schema v4、scope 已确认,baseline 可解析 | 不存在/未确认 → 走 docs-sync command bootstrap;旧 schema 或损坏 → 停止发布并按 docs-sync state contract 修复,`speculo init` 不解析未登记的 command state |
20
20
  | 11 | tag 名称冲突 | `git rev-parse vX.Y.Z 2>/dev/null` | 退出码非 0(tag 不存在) | 同 tag 已存在:先确认是否真的失败需要重发;若是则 `git tag -d` + `git push origin :refs/tags/vX.Y.Z`,否则 bump 到下一版本 |
21
21
 
22
22
  ## 失败处理总策略
@@ -0,0 +1,9 @@
1
+ {
2
+ "schema_version": 1,
3
+ "workflow": "person",
4
+ "config": null,
5
+ "structured_state": [
6
+ ".speculo/person/status.json"
7
+ ],
8
+ "opaque_default": "preserve-byte-for-byte"
9
+ }
@@ -82,7 +82,7 @@ keywords: [初始化, 配置, status, tracking, 验证命令]
82
82
  - `<Path>{roots.state}/specdev/research/</Path>`
83
83
  - `<Path>{roots.state}/specdev/archive/</Path>`
84
84
 
85
- 若全局状态或 config 已存在,先检查各自 `schema_version`。版本未知、JSON 不可解析或状态与当前 workflow 契约不一致时,停止当前 Work,并提示用户运行 `speculo init` 建立备份与 pending marker,再运行 `migrate-runtime-state` command 对账修复;不得在 Work 内迁移、兼容或猜测旧状态。只有状态不存在时才从当前 schema 模板创建。
85
+ 若全局状态或 config 已存在,先检查各自 `schema_version`。版本未知、JSON 不可解析或状态与当前 workflow 契约不一致时,停止当前 Work;不得在 Work 内迁移、兼容或猜测旧状态。`speculo init` 只会对 `runtime-contract.json` 已登记且存在显式 migrator 的旧版本升级,其他冲突会保留当前安装并报告具体 blocker。只有状态不存在时才从当前 schema 模板创建。
86
86
 
87
87
  从模板生成:
88
88
 
@@ -70,7 +70,7 @@ Archive 归档历史并将经验证知识提升为当前长期知识
70
70
  - 活跃 change:`<Path>{roots.state}/specdev/changes/</Path>`
71
71
  - 历史归档:`<Path>{roots.state}/specdev/archive/</Path>`
72
72
 
73
- 刷新时 CLI `<Path>{roots.state}/back/</Path>` 保留最近一次旧配置与完整 runtime state,并对 v0.7+ 状态执行兼容迁移。若 `<Path>{roots.state}/migration.json</Path>` 存在且为 pending,所有 SpecDev Works 必须在读取 workflow state 前停止;只有 `<Path>{roots.commands}/migrate-runtime-state.md</Path>` 可以读取备份并在用户确认后修复。`<Path>{roots.state}/back/</Path>`、`<Path>{roots.state}/install.json</Path>` 与 `<Path>{roots.state}/migration.json</Path>` 均不属于 SpecDev 写入 namespace。
73
+ 刷新时 CLI 依据 `<Path>{roots.workflows}/specdev/runtime-contract.json</Path>` 处理持久化数据:配置使用 baseline 三方合并,登记的状态 schema 使用显式 migrator,其他 runtime 文件按字节保留。只有字段删除或结构迁移时才在 `<Path>{roots.state}/back/</Path>` 写入 targeted backup;冲突在替换 active 安装前阻塞。`<Path>{roots.state}/back/</Path>`、`<Path>{roots.state}/install.json</Path>`、`<Path>{roots.state}/managed.json</Path>` 与 `<Path>{roots.state}/baselines/</Path>` 均不属于 SpecDev 写入 namespace。
74
74
 
75
75
  初始化设置 work 首次运行时生成配置并创建空的永久 namespace:
76
76
 
@@ -140,12 +140,11 @@ Archive 归档历史并将经验证知识提升为当前长期知识
140
140
  ## 启动协议
141
141
 
142
142
  1. 解析 workflow 和 state roots。
143
- 2. 检查 `<Path>{roots.state}/migration.json</Path>`;存在且 `status: pending` 时停止,不读取或写入 SpecDev state,并路由到 `<Path>{roots.commands}/migrate-runtime-state.md</Path>`。
144
- 3. 读取 `<Path>{roots.state}/specdev/config.json</Path>`;不存在时运行 `<Path>{roots.workflows}/specdev/I-init-setup/I-init-setup.md</Path>`。
145
- 4. 读取 `<Path>{roots.state}/specdev/status.json</Path>`:用户指定 change 优先;唯一活跃 change 直接使用;无活跃时创建;多个候选时请求消歧。
146
- 5. 若当前 change 已有非空 `current_work`,先恢复或显式结束该 Work;否则将 `current_work` 设置为本次 work id。
147
- 6. 只加载当前步骤需要的 work 子文件和共享规则。
148
- 7. 完成后写入产物、运行适用校验、更新状态和 `works_run`。
143
+ 2. 读取 `<Path>{roots.state}/specdev/config.json</Path>`;不存在时运行 `<Path>{roots.workflows}/specdev/I-init-setup/I-init-setup.md</Path>`。
144
+ 3. 读取 `<Path>{roots.state}/specdev/status.json</Path>`:用户指定 change 优先;唯一活跃 change 直接使用;无活跃时创建;多个候选时请求消歧。
145
+ 4. 若当前 change 已有非空 `current_work`,先恢复或显式结束该 Work;否则将 `current_work` 设置为本次 work id。
146
+ 5. 只加载当前步骤需要的 work 子文件和共享规则。
147
+ 6. 完成后写入产物、运行适用校验、更新状态和 `works_run`。
149
148
 
150
149
  Change 从 active/blocked 转为 completed 时加载 `<Path>{roots.workflows}/specdev/common/rules/change-completion.md</Path>`:有 Goal Plan 时由其中唯一 Lead 拥有转换;无 Goal Plan 的 Ticket/Direct Spec 由当前 I owner 拥有;非实现型终点由最终验收工件 owner 拥有。Archive 不补造 completed。
151
150
 
@@ -216,7 +215,7 @@ Change 从 active/blocked 转为 completed 时加载 `<Path>{roots.workflows}/sp
216
215
  - **D-diagnose-bugs** — 诊断 Bug:先建立会在精确症状上变红的紧凑反馈回路,再通过最小化、排名假设和单变量探针确认根因,输出修复契约而不实施生产修复。
217
216
  - **E-engineering-cognitive-mentor** — 工程认知导师:面向 Bug、项目源码、需求技术方案、架构设计与陌生技术领域的非执行型认知指导 Work;以证据、因果 Why、候选方案对比和逐轮澄清帮助用户形成可复述理解,并将完整问答轨迹持续持久化到当前 change。
218
217
  - **G-grill-with-docs** — 设计访谈(带文档):以完整 frontier 逐轮推进设计树,直到每个决策分支都已关闭并获得用户共识,同时持续维护当前 change 的设计树、日志、领域上下文和架构决策。
219
- - **I-implement** — 实现:基于 Ready Ticket 或获批小型 Spec 执行设计检查、TDD、动态派单、双轴审查、Ticket worktree commit、候选合并验证和 Lead Evidence 回写。
218
+ - **I-implement** — 实现:基于 Ready Ticket 或获批小型 Spec 执行设计检查、TDD、动态派单、双轴审查、按 Goal Plan 选择的 current workspace 或 Ticket worktree 提交、直接父分支或候选合并验证和 Lead Evidence 回写。
220
219
  - **I-init-setup** — 初始化设置:初始化 SpecDev 的语言、配置、全局状态、本地 change 追踪、领域知识布局、验证命令和并发治理。
221
220
  - **P-goal-plan** — 目标规划:在跨 Ticket 协调复杂度需要时,以固定 Lead、动态派单、DAG/Gate 和候选合并门禁生成决策完备且可恢复的执行计划。
222
221
  - **P-prototype** — 原型:在获授权的临时 branch/worktree 中构建一次性 Logic 或 UI 原型,回答一个明确设计问题并持久化答案、资产定位和清理状态。
@@ -0,0 +1,26 @@
1
+ {
2
+ "schema_version": 1,
3
+ "workflow": "specdev",
4
+ "config": {
5
+ "path": ".speculo/specdev/config.json",
6
+ "template": "workflows/specdev/I-init-setup/config-template.json",
7
+ "baseline": ".speculo/baselines/workflows/specdev/config.json",
8
+ "schema_version": 5,
9
+ "optional": true,
10
+ "additional_properties": {
11
+ "": false,
12
+ "git": false,
13
+ "execution": false,
14
+ "verification": true,
15
+ "planning": true
16
+ }
17
+ },
18
+ "structured_state": [
19
+ ".speculo/specdev/status.json",
20
+ ".speculo/specdev/changes/*/.status.json",
21
+ ".speculo/specdev/archive/*/*/.status.json",
22
+ ".speculo/specdev/changes/*/goal-plan.md",
23
+ ".speculo/specdev/archive/*/*/goal-plan.md"
24
+ ],
25
+ "opaque_default": "preserve-byte-for-byte"
26
+ }
@@ -1,23 +0,0 @@
1
- export type MigrationStatus = "not-required" | "migrated" | "pending";
2
- export type MigrationBlocker = {
3
- code: string;
4
- path: string;
5
- message: string;
6
- };
7
- export type RuntimeMigrationResult = {
8
- status: MigrationStatus;
9
- sourceVersion: string | null;
10
- targetVersion: string;
11
- backupPath: string | null;
12
- blockers: MigrationBlocker[];
13
- };
14
- export type RuntimeMigrationOptions = {
15
- packageRoot: string;
16
- previousRoot: string;
17
- stagedRoot: string;
18
- selectedWorkflowIds: string[];
19
- unselectedWorkflowIds: string[];
20
- };
21
- export declare function assertNoPendingMigration(previousRoot: string): Promise<void>;
22
- export declare function migrateRuntimeState(options: RuntimeMigrationOptions): Promise<RuntimeMigrationResult>;
23
- export declare function initializeRuntimeManifest(packageRoot: string, stagedRoot: string, workflowIds: string[]): Promise<RuntimeMigrationResult>;