@namewta/speculo 0.7.5 → 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 (43) 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/canonical/canonical-specdev-goal-plan.md +436 -68
  23. package/template/skills/github-npm-ops/references/preflight-checklist.md +1 -1
  24. package/template/skills/source-code-zip/SKILL.md +568 -0
  25. package/template/skills/source-code-zip/scripts/zip_source_code.js +1363 -0
  26. package/template/workflows/person/runtime-contract.json +9 -0
  27. package/template/workflows/specdev/I-init-setup/I-init-setup.md +1 -1
  28. package/template/workflows/specdev/INDEX.md +7 -8
  29. package/template/workflows/specdev/common/skills/subagent-delivery/SKILL.md +88 -27
  30. package/template/workflows/specdev/common/skills/subagent-delivery/references/external-web-subagent.md +121 -9
  31. package/template/workflows/specdev/common/skills/subagent-delivery/references/native-subagent.md +10 -7
  32. package/template/workflows/specdev/common/skills/subagent-delivery/references/source-package.md +229 -9
  33. package/template/workflows/specdev/runtime-contract.json +26 -0
  34. package/dist/src/migrations.d.ts +0 -23
  35. package/dist/src/migrations.js +0 -1202
  36. package/dist/src/migrations.js.map +0 -1
  37. package/template/commands/migrate-runtime-state.md +0 -43
  38. package/template/skills/migrate-runtime-state/SKILL.md +0 -93
  39. package/template/skills/migrate-runtime-state/references/migration-contract.md +0 -64
  40. package/template/skills/migrate-runtime-state/scripts/migrate-runtime-state.mjs +0 -916
  41. package/template/skills/source-code-zip-skill/SKILL.md +0 -343
  42. package/template/skills/source-code-zip-skill/scripts/zip_source_code.py +0 -638
  43. package/template/workflows/specdev/common/skills/subagent-delivery/references/github-checkpoints.md +0 -24
@@ -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.5",
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
+ }