@namewta/speculo 1.0.15 → 1.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -5
- package/dist/src/agent-files.d.ts +9 -0
- package/dist/src/agent-files.js +106 -0
- package/dist/src/agent-files.js.map +1 -0
- package/dist/src/cli.js +64 -14
- package/dist/src/cli.js.map +1 -1
- package/dist/src/doctor.d.ts +2 -0
- package/dist/src/doctor.js +120 -53
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/external-files.d.ts +22 -0
- package/dist/src/external-files.js +110 -0
- package/dist/src/external-files.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +31 -182
- package/dist/src/index.js.map +1 -1
- package/dist/src/paths.d.ts +12 -0
- package/dist/src/paths.js +57 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/transaction.d.ts +27 -0
- package/dist/src/transaction.js +187 -0
- package/dist/src/transaction.js.map +1 -0
- package/dist/src/utils.js +4 -2
- package/dist/src/utils.js.map +1 -1
- package/dist/src/workflows.js +3 -4
- package/dist/src/workflows.js.map +1 -1
- package/package.json +6 -4
- package/template/.speculo/README.md +9 -3
- package/template/.speculo/refresh-contract.json +6 -2
- package/template/AGENTS.md +1 -1
- package/template/canonical/canonical-specdev-goal-plan.md +23 -12
- package/template/canonical/canonical-specdev-tickets.md +1 -1
- package/template/commands/docs-sync.md +13 -11
- package/template/skills/archive-and-consolidate/SKILL.md +2 -4
- package/template/skills/docs-sync/SKILL.md +22 -11
- package/template/skills/docs-sync/references/agents-contract.md +6 -4
- package/template/skills/docs-sync/references/document-lifecycle-contract.md +2 -0
- package/template/skills/docs-sync/references/entry-procedure.md +2 -17
- package/template/skills/docs-sync/references/git-state-contract.md +1 -1
- package/template/skills/docs-sync/references/mode-contract.md +21 -0
- package/template/skills/docs-sync/references/workflow-scope-contract.md +5 -3
- package/template/skills/engineering-standards-builder/SKILL.md +3 -1
- package/template/skills/engineering-standards-builder/examples/README.md +6 -0
- package/template/skills/engineering-standards-builder/manifest.txt +1 -0
- package/template/skills/engineering-standards-builder/scripts/self-test.mjs +1 -0
- package/template/skills/engineering-standards-builder/scripts/sync-manifest.mjs +2 -2
- package/template/skills/engineering-standards-builder/scripts/validate-builder.mjs +12 -4
- package/template/skills/git-history-squash/SKILL.md +3 -3
- package/template/skills/github-npm-ops/SKILL.md +2 -4
- package/template/skills/source-code-zip/SKILL.md +0 -1
- package/template/skills/speculo-retro/SKILL.md +2 -4
- package/template/skills/upstream-fork-sync/SKILL.md +1 -3
- package/template/skills/writing-great-skills/SKILL.md +3 -3
- package/template/workflows/learning/A-archive/A-archive.md +2 -0
- package/template/workflows/learning/A-assess-and-plan/A-assess-and-plan.md +2 -0
- package/template/workflows/learning/C-consolidate/C-consolidate.md +2 -0
- package/template/workflows/learning/G-goal/G-goal.md +6 -0
- package/template/workflows/learning/G-goal/references/external-goal-runner.md +4 -0
- package/template/workflows/learning/H-homework/H-homework.md +2 -0
- package/template/workflows/learning/L-lesson/L-lesson.md +2 -0
- package/template/workflows/learning/Q-question/Q-question.md +2 -0
- package/template/workflows/learning/R-review/R-review.md +2 -0
- package/template/workflows/learning/README.md +4 -53
- package/template/workflows/learning/common/rules/artifact-layouts.md +46 -0
- package/template/workflows/learning/common/rules/consolidation-contract.md +5 -0
- package/template/workflows/learning/common/rules/homework-contract.md +3 -0
- package/template/workflows/learning/common/rules/lesson-contract.md +7 -0
- package/template/workflows/learning/common/skills/socratic-questioning/SKILL.md +1 -0
- package/template/workflows/learning/common/skills/topic-synthesis/SKILL.md +1 -0
- package/template/workflows/ops/README.md +7 -3
- package/template/workflows/ops/_state/status.json +2 -1
- package/template/workflows/ops/common/USAGE.md +4 -0
- package/template/workflows/ops/common/rules/persistence-and-secrets.md +4 -2
- package/template/workflows/ops/common/schemas/plan.schema.json +4 -0
- package/template/workflows/ops/common/schemas/spec.schema.json +4 -0
- package/template/workflows/ops/common/schemas/status.schema.json +4 -0
- package/template/workflows/ops/common/tests/test_ops.mjs +33 -2
- package/template/workflows/ops/common/tools/opslib/core.mjs +1 -1
- package/template/workflows/ops/common/tools/opslib/docs.mjs +12 -7
- package/template/workflows/ops/common/tools/opslib/planner.mjs +7 -1
- package/template/workflows/specdev/P-goal-plan/P-goal-plan.md +4 -2
- package/template/workflows/specdev/P-goal-plan/goal-plan-template.md +2 -0
- package/template/workflows/specdev/P-goal-plan/planning-modes.md +13 -8
- package/template/workflows/specdev/P-goal-plan/references/map-control.md +1 -1
- package/template/workflows/specdev/P-goal-plan/references/single-change-plan.md +4 -2
- package/template/workflows/specdev/README.md +2 -2
- package/template/workflows/specdev/common/rules/path-reference-contract.md +6 -0
- package/template/workflows/specdev/common/rules/workflow-routing.md +2 -2
- package/template/workflows/specdev/common/skills/code-review/SKILL.md +3 -1
- package/template/workflows/specdev/common/skills/dev-worktree/SKILL.md +1 -0
- package/template/workflows/specdev/common/skills/plan-quality-review/SKILL.md +3 -1
- package/template/workflows/specdev/common/skills/research/SKILL.md +3 -1
- package/template/workflows/specdev/common/skills/subagent-delivery/SKILL.md +1 -0
- package/template/workflows/specdev/common/tools/README.md +7 -1
- package/template/workflows/specdev/common/tools/validate-specdev.mjs +19 -18
package/README.md
CHANGED
|
@@ -31,11 +31,13 @@ Requires: Node.js ≥ 22.22.3 and < 25
|
|
|
31
31
|
|---|---|
|
|
32
32
|
| `speculo` / `speculo init [target]` | Initialize or refresh a Speculo 1.0 runtime. 0.x installations are intentionally incompatible and must be removed or renamed first. |
|
|
33
33
|
| `speculo version` | Print the installed version and check npm for the latest release. |
|
|
34
|
-
| `speculo doctor [target]` | Read-only
|
|
34
|
+
| `speculo doctor [target] [--json]` | Read-only installation integrity and recovery diagnostics. |
|
|
35
|
+
| `speculo resolve [target] --path <reference>` | Read-only pointer resolution; does not execute a shell. |
|
|
36
|
+
| `speculo recover [target] --transaction <id>` | Explicit recovery of an identified interrupted refresh. |
|
|
35
37
|
|
|
36
|
-
Legacy CLI commands and 0.x migration paths
|
|
38
|
+
Legacy CLI commands and 0.x migration paths remain removed. The CLI also offers read-only `resolve` and explicit transaction-ID `recover`; doctor reports its installation-only scope.
|
|
37
39
|
|
|
38
|
-
Initialization updates
|
|
40
|
+
Initialization updates controlled passive-bootstrap and persistent-knowledge blocks in project `AGENTS.md` for all installed workflows. The block contains references to promoted knowledge paths and explicitly remains lazy: it does not activate a workflow, create a Change, or execute a Work. A missing `CLAUDE.md` is created as a fixed redirect to `AGENTS.md`; existing handbook content is preserved.
|
|
39
41
|
|
|
40
42
|
## Installed Runtime Assets
|
|
41
43
|
|
|
@@ -45,7 +47,7 @@ After initialization, the target project gains the following AI agent-callable a
|
|
|
45
47
|
|
|
46
48
|
| Command | Purpose |
|
|
47
49
|
|---|---|
|
|
48
|
-
| `docs-sync` |
|
|
50
|
+
| `docs-sync` | Audit (default), update, or explicitly commit documentation from reproducible Git ranges |
|
|
49
51
|
| `archive-and-consolidate` | Knowledge lifecycle governance: archive stale content, consolidate scattered knowledge, clean up outdated assets |
|
|
50
52
|
| `git-history-squash` | Confirmed first-parent history convergence with recoverable refs and exact remote leases |
|
|
51
53
|
| `git-repository-audit` | Read-only, reproducible audit of one or more local Git repositories |
|
|
@@ -77,7 +79,7 @@ After initialization, the target project gains the following AI agent-callable a
|
|
|
77
79
|
| **ops** | 3 | Host inventory and project deployment: initialize, host manage, and APP/shared-service deploy with dual documentation |
|
|
78
80
|
| **person** | 2 | Persona-methodology and rigorous deliberation workflows (Mao Zedong Cognitive OS; Bidirectional Steelman Deliberation) |
|
|
79
81
|
|
|
80
|
-
Every workflow ships an `INDEX.md`
|
|
82
|
+
Every workflow ships an `INDEX.md` discovery entry. SpecDev/Learning/Ops keep their generated Work catalog in the README activation contract; Person lists Works directly in INDEX. Work entries follow `<Letter>-<work_name>/<Letter>-<work_name>.md` naming with progressive-disclosure sub-files, and resolve runtime paths via `<Path>{roots.xxx}/...</Path>` pointers in `workspace.json`.
|
|
81
83
|
|
|
82
84
|
SpecDev T-triage stays the only remote boundary. Use **intake** to freeze a source, **reconcile** to close that original source Issue after local completion, **publish** to project each completed Ticket as a classified GitHub Issue (local-origin work included), and **capture** to park a not-yet-Change note as a still-open GitHub Issue. GitHub is a projection, counter, and inbox — not the development source of truth. Run both reconcile and publish when an intake Change should also count its tickets. Capture does not create a Change.
|
|
83
85
|
|
|
@@ -107,3 +109,13 @@ MIT — see [LICENSE](./LICENSE)
|
|
|
107
109
|
## SpecDev Goal migration
|
|
108
110
|
|
|
109
111
|
The unified P Goal entry, O compatibility route, Initiative exploration and Plan Ticket contracts are documented in [the migration guide](docs/specdev-goal-migration.md). Existing runtime state is not silently rewritten.
|
|
112
|
+
|
|
113
|
+
## Agent contract hardening
|
|
114
|
+
|
|
115
|
+
Unattended first installation now installs core only. Select packages explicitly with `speculo init [target] --workflows specdev,learning`; unattended refresh selects already-installed supported packages. `--core-only` refreshes core without removing existing supported workflows. Installed and selected-for-update are separate; no automatic activation or uninstall is implied.
|
|
116
|
+
|
|
117
|
+
The project AGENTS bootstrap points to `speculo/.speculo/workspace.json`, a generated read-only capability catalog and the runtime guide. Agents that do not read project instructions need an explicit user-provided entry. Public Skill metadata follows the emitted standard profile; workflow-private Skills declare their resolver requirement. `INDEX.md` is a discovery entry: SpecDev/Learning/Ops list Works in README activation contracts, while Person lists them directly in INDEX.
|
|
118
|
+
|
|
119
|
+
`speculo doctor [target] --json` checks installation integrity (not live services or agent behavior). `speculo resolve [target] --path <reference>` resolves one contained pointer without executing it. Interrupted refreshes retain transaction evidence; after verifying that the original process has stopped, `speculo recover [target] --transaction <id>` performs evidence-checked rollback or committed cleanup. Unknown locks, links and drift are never silently discarded. This is process-interruption recovery, not a universal power-loss or adversarial-filesystem guarantee.
|
|
120
|
+
|
|
121
|
+
Docs Sync defaults to read-only audit; update and commit require their corresponding user requests. New Ops controllers export credential references by default; plaintext documentation requires an explicitly approved plan. Existing active bindings, historical evidence and legacy plaintext policies are not silently migrated. See [migration and verification notes](docs/agent-contracts-upgrade.md).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ExternalEdit, type ExternalName, type FileImage } from "./external-files.js";
|
|
2
|
+
export type KnowledgeReference = {
|
|
3
|
+
workflow: string;
|
|
4
|
+
path: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function updateAgentsContent(content: string, references: KnowledgeReference[]): string;
|
|
7
|
+
export declare function readPersistentKnowledge(stagedRoot: string, workflowIds: string[]): Promise<KnowledgeReference[]>;
|
|
8
|
+
export declare function writeDiscoveryAssets(packageRoot: string, stagedRoot: string): Promise<void>;
|
|
9
|
+
export declare function planExternalEdits(snapshots: Map<ExternalName, FileImage>, references: KnowledgeReference[], specdevInstalled: boolean): ExternalEdit[];
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { cp, readFile, readdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { bytes, image } from "./external-files.js";
|
|
4
|
+
import { scanInstalledWorkflows } from "./workflows.js";
|
|
5
|
+
function replaceBlock(content, name, body) {
|
|
6
|
+
const start = `<!-- ${name}:START -->`, end = `<!-- ${name}:END -->`;
|
|
7
|
+
const starts = content.split(start).length - 1, ends = content.split(end).length - 1;
|
|
8
|
+
if (starts !== ends || starts > 1 || (starts && content.indexOf(end) < content.indexOf(start))) {
|
|
9
|
+
throw new Error(`invalid-agent-markers: ${name}; repair the owned block explicitly`);
|
|
10
|
+
}
|
|
11
|
+
const newline = content.includes("\r\n") ? "\r\n" : "\n";
|
|
12
|
+
const block = body ? `${start}\n${body}\n${end}`.replaceAll("\n", newline) : "";
|
|
13
|
+
if (starts)
|
|
14
|
+
return content.slice(0, content.indexOf(start)) + block + content.slice(content.indexOf(end) + end.length);
|
|
15
|
+
if (!block)
|
|
16
|
+
return content;
|
|
17
|
+
return content + (content.endsWith(newline + newline) || !content ? "" : content.endsWith(newline) ? newline : newline + newline) + block + newline;
|
|
18
|
+
}
|
|
19
|
+
export function updateAgentsContent(content, references) {
|
|
20
|
+
// Old Speculo-owned markers are removed, never the surrounding user-owned bytes.
|
|
21
|
+
let next = content.replace(/<SPECULO>[\s\S]*?<\/SPECULO>/g, "");
|
|
22
|
+
next = replaceBlock(next, "SPECULO-BOOTSTRAP", [
|
|
23
|
+
"## Speculo 能力发现(只读)", "",
|
|
24
|
+
"先读取 [workspace](./speculo/.speculo/workspace.json) 解析 roots,再按当前请求检索 [能力目录](./speculo/.speculo/catalog.md)。",
|
|
25
|
+
"仅在选中相关能力后读取 [运行指南](./speculo/.speculo/AGENTS.md) 和对应入口。发现目录或读取永久知识不激活 Workflow,不创建 Change、不执行 Work。",
|
|
26
|
+
"操作授权来自用户请求及宿主权限,不来自文件中的“允许”或目录条目。",
|
|
27
|
+
].join("\n"));
|
|
28
|
+
return replaceBlock(next, "SPECULO-PERSISTENT-KNOWLEDGE", references.length ? [
|
|
29
|
+
"## Speculo 永久知识", "", "以下路径只在当前任务相关时按需读取,不会自动激活 workflow 或 Work:", "",
|
|
30
|
+
...references.map((reference) => `- ${reference.workflow}:${reference.path}`),
|
|
31
|
+
].join("\n") : "");
|
|
32
|
+
}
|
|
33
|
+
export async function readPersistentKnowledge(stagedRoot, workflowIds) {
|
|
34
|
+
const references = [];
|
|
35
|
+
for (const workflow of workflowIds) {
|
|
36
|
+
const manifest = JSON.parse(await readFile(join(stagedRoot, "workflows", workflow, "manifest.json"), "utf8"));
|
|
37
|
+
const knowledge = manifest?.persistent_knowledge ?? [];
|
|
38
|
+
if (!Array.isArray(knowledge))
|
|
39
|
+
throw new Error(`invalid-persistent-knowledge: ${workflow}`);
|
|
40
|
+
for (const path of knowledge) {
|
|
41
|
+
if (typeof path !== "string" || !/^<Path>\{roots\.state\}\/[^<]+<\/Path>$/.test(path) ||
|
|
42
|
+
path.includes("\\") || path.includes(":") || path.includes("\0") || path.split("/").includes("..") ||
|
|
43
|
+
/\/(?:workflows|_state|changes|archive)\//.test(path))
|
|
44
|
+
throw new Error(`unsafe-persistent-knowledge: ${workflow}`);
|
|
45
|
+
references.push({ workflow, path });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return references;
|
|
49
|
+
}
|
|
50
|
+
function description(content) {
|
|
51
|
+
const value = /^description:\s*(.+)$/m.exec(content)?.[1] ?? "";
|
|
52
|
+
return value.replace(/[\r\n|]/g, " ");
|
|
53
|
+
}
|
|
54
|
+
export async function writeDiscoveryAssets(packageRoot, stagedRoot) {
|
|
55
|
+
const lines = ["# Speculo 能力目录", "", "生成的只读发现视图。仅定位相关入口;不自动读取所有入口、激活状态机或授权动作。", "",
|
|
56
|
+
"roots 来自 [workspace.json](workspace.json)。Workflow 激活合同由各 INDEX 声明;Person 不要求不存在的 README。", "", "## Commands"];
|
|
57
|
+
for (const name of (await readdir(join(stagedRoot, "commands"))).sort()) {
|
|
58
|
+
if (!name.endsWith(".md"))
|
|
59
|
+
continue;
|
|
60
|
+
lines.push(`- [${name.slice(0, -3)}](../commands/${name}) — ${description(await readFile(join(stagedRoot, "commands", name), "utf8"))}`);
|
|
61
|
+
}
|
|
62
|
+
lines.push("", "## Skills");
|
|
63
|
+
for (const entry of (await readdir(join(stagedRoot, "skills"), { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
64
|
+
if (!entry.isDirectory())
|
|
65
|
+
continue;
|
|
66
|
+
try {
|
|
67
|
+
lines.push(`- [${entry.name}](../skills/${entry.name}/SKILL.md) — ${description(await readFile(join(stagedRoot, "skills", entry.name, "SKILL.md"), "utf8"))}`);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (error.code !== "ENOENT")
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
lines.push("", "## Workflows");
|
|
75
|
+
for (const workflow of await scanInstalledWorkflows(stagedRoot)) {
|
|
76
|
+
lines.push(`- [${workflow}](../workflows/${workflow}/INDEX.md) — ${description(await readFile(join(stagedRoot, "workflows", workflow, "INDEX.md"), "utf8"))}`);
|
|
77
|
+
}
|
|
78
|
+
await writeFile(join(stagedRoot, ".speculo", "catalog.md"), lines.join("\n") + "\n");
|
|
79
|
+
await cp(join(packageRoot, "template", "AGENTS.md"), join(stagedRoot, ".speculo", "AGENTS.md"));
|
|
80
|
+
}
|
|
81
|
+
export function planExternalEdits(snapshots, references, specdevInstalled) {
|
|
82
|
+
const edits = [];
|
|
83
|
+
for (const [name, before] of snapshots) {
|
|
84
|
+
let text = bytes(before).toString("utf8");
|
|
85
|
+
if (before && !bytes(before).equals(Buffer.from(text)))
|
|
86
|
+
throw new Error(`external-encoding: ${name} must be UTF-8`);
|
|
87
|
+
if (name === "AGENTS.md")
|
|
88
|
+
text = updateAgentsContent(before ? text : "# AGENTS.md\n", references);
|
|
89
|
+
if (name === "CLAUDE.md" && !before)
|
|
90
|
+
text = "# CLAUDE.md\n\nSpeculo agent handbook: see [AGENTS.md](./AGENTS.md).\n";
|
|
91
|
+
if (name === ".gitignore") {
|
|
92
|
+
const newline = text.includes("\r\n") ? "\r\n" : "\n";
|
|
93
|
+
const patterns = ["speculo/.speculo/back/", ".speculo-init.lock/", ".speculo-init-stage-*/", ".speculo-file-*.tmp", ...(specdevInstalled ? ["specdev-worktree/"] : [])];
|
|
94
|
+
const existing = text.split(/\r?\n/).map((line) => line.trim().replace(/^\//, "").replace(/\/$/, ""));
|
|
95
|
+
const missing = patterns.filter((pattern) => !existing.includes(pattern.replace(/\/$/, "")));
|
|
96
|
+
if (missing.length)
|
|
97
|
+
text += (text && !text.endsWith("\n") ? newline : "") + missing.join(newline) + newline;
|
|
98
|
+
}
|
|
99
|
+
if (before && (before.mode & 0o222) === 0 && !bytes(before).equals(Buffer.from(text))) {
|
|
100
|
+
throw new Error(`read-only-external-file: ${name}; preserve permissions and obtain source-owner approval`);
|
|
101
|
+
}
|
|
102
|
+
edits.push({ name, before, after: image(text, before?.mode ?? 0o644) });
|
|
103
|
+
}
|
|
104
|
+
return edits;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=agent-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-files.js","sourceRoot":"","sources":["../../src/agent-files.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli.js
CHANGED
|
@@ -5,6 +5,8 @@ import { initSpeculo } from "./index.js";
|
|
|
5
5
|
import { RefreshBlockedError } from "./refresh.js";
|
|
6
6
|
import { checkForUpdate, formatVersionBanner } from "./version.js";
|
|
7
7
|
import { doctorSpeculo } from "./doctor.js";
|
|
8
|
+
import { recoverInstall } from "./transaction.js";
|
|
9
|
+
import { resolvePathReference } from "./paths.js";
|
|
8
10
|
const REMOVED_COMMANDS = new Set(["migrate", "mirror-skills", "update"]);
|
|
9
11
|
const REMOVED_OPTIONS = new Set(["--all", "--apply", "--dry-run"]);
|
|
10
12
|
function usage() {
|
|
@@ -12,12 +14,18 @@ function usage() {
|
|
|
12
14
|
"Usage:",
|
|
13
15
|
" speculo [init] [target]",
|
|
14
16
|
" speculo version",
|
|
15
|
-
" speculo doctor [target]",
|
|
17
|
+
" speculo doctor [target] [--json]",
|
|
18
|
+
" speculo recover [target] --transaction <id>",
|
|
19
|
+
" speculo resolve [target] --path <reference>",
|
|
20
|
+
" speculo init [target] [--workflows <id,id> | --core-only]",
|
|
16
21
|
"",
|
|
17
22
|
"Commands:",
|
|
18
23
|
" init Install or directly refresh Speculo assets and selected workflow packages.",
|
|
19
24
|
" version Print the current Speculo version and check for updates.",
|
|
20
|
-
" doctor Validate
|
|
25
|
+
" doctor Validate installation integrity and report recovery evidence (read-only).",
|
|
26
|
+
" recover Explicitly roll back an interrupted transaction, or finish committed cleanup.",
|
|
27
|
+
" resolve Resolve a Path reference to a contained local path (read-only; no shell).",
|
|
28
|
+
" Non-interactive init: core-only on first install; existing supported workflows on refresh.",
|
|
21
29
|
].join("\n");
|
|
22
30
|
}
|
|
23
31
|
function isInteractive() {
|
|
@@ -39,6 +47,30 @@ function assertNoRemovedOption(argv) {
|
|
|
39
47
|
if (option)
|
|
40
48
|
throw new Error(option + " has been removed. Run speculo init [target] to refresh Speculo.");
|
|
41
49
|
}
|
|
50
|
+
function parseArguments(argv, booleanFlags = new Set(), valueFlags = new Set()) {
|
|
51
|
+
let target;
|
|
52
|
+
const flags = new Set(), values = new Map();
|
|
53
|
+
for (let i = 0; i < argv.length; i++) {
|
|
54
|
+
const value = argv[i];
|
|
55
|
+
if (booleanFlags.has(value)) {
|
|
56
|
+
if (flags.has(value))
|
|
57
|
+
throw new Error("Duplicate option: " + value);
|
|
58
|
+
flags.add(value);
|
|
59
|
+
}
|
|
60
|
+
else if (valueFlags.has(value)) {
|
|
61
|
+
if (values.has(value) || !argv[i + 1] || argv[i + 1].startsWith("--"))
|
|
62
|
+
throw new Error("Missing or duplicate option value: " + value);
|
|
63
|
+
values.set(value, argv[++i]);
|
|
64
|
+
}
|
|
65
|
+
else if (value.startsWith("-"))
|
|
66
|
+
throw new Error("Unknown option: " + value);
|
|
67
|
+
else if (target !== undefined)
|
|
68
|
+
throw new Error("Unexpected argument: " + value);
|
|
69
|
+
else
|
|
70
|
+
target = value;
|
|
71
|
+
}
|
|
72
|
+
return { target: target ?? ".", flags, values };
|
|
73
|
+
}
|
|
42
74
|
async function main(argv) {
|
|
43
75
|
if (argv[0] === "--help" || argv[0] === "-h") {
|
|
44
76
|
console.log(usage());
|
|
@@ -60,25 +92,43 @@ async function main(argv) {
|
|
|
60
92
|
return 0;
|
|
61
93
|
}
|
|
62
94
|
if (command === "doctor") {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
95
|
+
const args = parseArguments(rest, new Set(["--json"]));
|
|
96
|
+
const result = await doctorSpeculo(args.target);
|
|
97
|
+
if (args.flags.has("--json"))
|
|
98
|
+
console.log(JSON.stringify(result, null, 2));
|
|
99
|
+
else {
|
|
100
|
+
for (const check of result.checks)
|
|
101
|
+
console.log(`${check.ok ? "ok" : "fail"} ${check.id}: ${check.message}`);
|
|
102
|
+
console.log(`scope: ${result.scope}; not checked: ${result.notChecked.join(", ")}`);
|
|
103
|
+
}
|
|
68
104
|
return result.healthy ? 0 : 2;
|
|
69
105
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
106
|
+
if (command === "recover" || command === "resolve") {
|
|
107
|
+
const flag = command === "recover" ? "--transaction" : "--path";
|
|
108
|
+
const args = parseArguments(rest, new Set(), new Set([flag]));
|
|
109
|
+
const value = args.values.get(flag);
|
|
110
|
+
if (!value)
|
|
111
|
+
throw new Error(`${command} requires ${flag}`);
|
|
112
|
+
if (command === "recover")
|
|
113
|
+
console.log(JSON.stringify(await recoverInstall(args.target, value), null, 2));
|
|
114
|
+
else
|
|
115
|
+
console.log(await resolvePathReference(args.target, value));
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
const args = parseArguments(command === "init" ? rest : argv, new Set(["--core-only"]), new Set(["--workflows"]));
|
|
119
|
+
if (args.flags.has("--core-only") && args.values.has("--workflows"))
|
|
120
|
+
throw new Error("--core-only and --workflows are mutually exclusive");
|
|
121
|
+
const requested = args.values.get("--workflows");
|
|
122
|
+
if (requested !== undefined && !/^[a-z0-9-]+(?:,[a-z0-9-]+)*$/.test(requested))
|
|
123
|
+
throw new Error("--workflows requires comma-separated workflow ids");
|
|
124
|
+
const selection = args.flags.has("--core-only") ? { workflowIds: [] } : requested === undefined ? undefined : { workflowIds: requested.split(",") };
|
|
125
|
+
const targetArg = args.target;
|
|
76
126
|
await showVersionWithCheck(packageRoot, packageName);
|
|
77
127
|
if (!(await confirmContinue())) {
|
|
78
128
|
console.log("已取消。");
|
|
79
129
|
return 0;
|
|
80
130
|
}
|
|
81
|
-
const result = await initSpeculo(targetArg
|
|
131
|
+
const result = await initSpeculo(targetArg, { packageRoot, selection });
|
|
82
132
|
console.log(result.mode === "init" ? "Speculo initialized in " + result.target : "Speculo refreshed in " + result.target);
|
|
83
133
|
console.log(" replaced " + result.refresh.managedFiles + " managed files");
|
|
84
134
|
console.log(" preserved " + result.refresh.preservedFiles + " runtime files");
|
package/dist/src/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAoB,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/src/doctor.d.ts
CHANGED
package/dist/src/doctor.js
CHANGED
|
@@ -1,70 +1,137 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
1
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { sha256File } from "./manifest.js";
|
|
4
|
+
import { containedPath, safeRelativePath, validateWorkspace } from "./paths.js";
|
|
5
|
+
import { readTransaction, LOCK_NAME } from "./transaction.js";
|
|
7
6
|
function record(value) {
|
|
8
|
-
return value
|
|
9
|
-
? value
|
|
10
|
-
: null;
|
|
11
|
-
}
|
|
12
|
-
async function checkJson(checks, root, id, predicate, message) {
|
|
13
|
-
try {
|
|
14
|
-
const value = record(await json(join(root, id)));
|
|
15
|
-
const ok = value !== null && predicate(value);
|
|
16
|
-
checks.push({ id: id + "-contract", ok, message: ok ? message : "invalid contract" });
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
checks.push({ id: id + "-contract", ok: false, message: "invalid JSON" });
|
|
20
|
-
}
|
|
7
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
21
8
|
}
|
|
9
|
+
function nonempty(value) { return typeof value === "string" && !!value.trim(); }
|
|
10
|
+
function strings(value) { return Array.isArray(value) && value.every(nonempty); }
|
|
11
|
+
function version(value) { return typeof value === "string" && /^1\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(value); }
|
|
22
12
|
export async function doctorSpeculo(targetArg = ".") {
|
|
23
|
-
const target = resolve(targetArg);
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
const required = [".speculo/workspace.json", ".speculo/install.json", ".speculo/managed.json", ".speculo/kernel.json", ".speculo/capabilities.json", "config.json"];
|
|
27
|
-
for (const item of required)
|
|
28
|
-
checks.push({ id: item, ok: await pathExists(join(root, item)), message: (await pathExists(join(root, item))) ? "present" : "missing" });
|
|
29
|
-
const installCheck = checks.find((check) => check.id === ".speculo/install.json");
|
|
30
|
-
if (installCheck?.ok) {
|
|
13
|
+
const target = resolve(targetArg), checks = [];
|
|
14
|
+
const add = (id, ok, message) => checks.push({ id, ok, message });
|
|
15
|
+
async function json(path) {
|
|
31
16
|
try {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
|
|
17
|
+
const absolute = await containedPath(target, "speculo/" + path);
|
|
18
|
+
const value = JSON.parse(await readFile(absolute, "utf8"));
|
|
19
|
+
if (!record(value))
|
|
20
|
+
throw new Error("expected JSON object");
|
|
21
|
+
return value;
|
|
35
22
|
}
|
|
36
|
-
catch {
|
|
37
|
-
|
|
23
|
+
catch (error) {
|
|
24
|
+
add(path, false, String(error));
|
|
25
|
+
return null;
|
|
38
26
|
}
|
|
39
27
|
}
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
28
|
+
const config = await json("config.json");
|
|
29
|
+
if (config) {
|
|
30
|
+
const ok = config.schema_version === 1 && nonempty(config.language) && record(config.persistence) &&
|
|
31
|
+
(config.persistence.root_override === null || safeRelativePath(config.persistence.root_override)) && record(config.defaults) &&
|
|
32
|
+
typeof config.defaults.confirm_before_external_write === "boolean" && nonempty(config.defaults.report_language);
|
|
33
|
+
add("config-contract", ok, ok ? "project config schema v1 valid" : "invalid project config fields");
|
|
34
|
+
}
|
|
35
|
+
const workspace = await json(".speculo/workspace.json");
|
|
36
|
+
if (workspace) {
|
|
42
37
|
try {
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
38
|
+
validateWorkspace(workspace);
|
|
39
|
+
for (const path of Object.values(workspace.roots))
|
|
40
|
+
await containedPath(target, path);
|
|
41
|
+
const expected = { speculo: "speculo", config: "speculo/config.json", state: "speculo/.speculo", commands: "speculo/commands", skills: "speculo/skills", workflows: "speculo/workflows" };
|
|
42
|
+
if (Object.entries(expected).some(([key, path]) => workspace.roots[key] !== path))
|
|
43
|
+
throw new Error("workspace roots differ from the installed CLI layout");
|
|
44
|
+
add("workspace-contract", true, "roots are complete, contained and match the installed layout");
|
|
46
45
|
}
|
|
47
|
-
catch {
|
|
48
|
-
|
|
46
|
+
catch (error) {
|
|
47
|
+
add("workspace-contract", false, String(error));
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
const kernel = await json(".speculo/kernel.json");
|
|
51
|
+
if (kernel) {
|
|
52
|
+
const ok = kernel.schema_version === 1 && kernel.runtime === "speculo-kernel" && strings(kernel.change_lifecycle) &&
|
|
53
|
+
["draft", "active", "blocked", "awaiting_user", "completed", "archived", "cancelled"].every((s) => kernel.change_lifecycle.includes(s)) &&
|
|
54
|
+
strings(kernel.risk_classes) && ["read-only", "local-reversible", "local-destructive", "external-mutation", "production-critical"].every((s) => kernel.risk_classes.includes(s));
|
|
55
|
+
add("kernel-contract", ok, ok ? "kernel lifecycle and risk contract valid" : "invalid kernel contract");
|
|
53
56
|
}
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
const capabilities = await json(".speculo/capabilities.json");
|
|
58
|
+
if (capabilities) {
|
|
59
|
+
const m = capabilities.model, t = capabilities.tools, e = capabilities.execution, mem = capabilities.memory;
|
|
60
|
+
const ok = capabilities.schema_version === 1 && record(m) && nonempty(m.id) &&
|
|
61
|
+
Number.isSafeInteger(m.context_window) && Number(m.context_window) >= (m.id === "unknown" ? 0 : 1) && Number.isSafeInteger(m.max_output) && Number(m.max_output) >= (m.id === "unknown" ? 0 : 1) &&
|
|
62
|
+
strings(m.modalities) && strings(m.reasoning_levels) && record(t) && strings(t.classes) && typeof t.parallel === "boolean" && typeof t.programmatic === "boolean" &&
|
|
63
|
+
record(e) && typeof e.sandbox === "boolean" && typeof e.network === "boolean" && strings(e.filesystem_roots) && ["none", "session", "persistent"].includes(String(e.data_retention)) &&
|
|
64
|
+
record(mem) && ["compaction", "persistent", "cache"].every((key) => typeof mem[key] === "boolean");
|
|
65
|
+
add("capability-contract", ok, ok ? "declared capability profile structurally valid (not a live probe)" : "invalid capability profile");
|
|
56
66
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
const install = await json(".speculo/install.json");
|
|
68
|
+
let workflows = [];
|
|
69
|
+
if (install) {
|
|
70
|
+
const ok = install.schema_version === 3 && version(install.package_version) && strings(install.workflows) &&
|
|
71
|
+
install.workflows.every((id) => /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) && new Set(install.workflows).size === install.workflows.length &&
|
|
72
|
+
install.managed_manifest === ".speculo/managed.json" && install.config_baseline_schema === 1;
|
|
73
|
+
add("install-contract", ok, ok ? "Speculo 1.x installation manifest valid" : "invalid installation manifest");
|
|
74
|
+
if (ok)
|
|
75
|
+
workflows = install.workflows;
|
|
76
|
+
}
|
|
77
|
+
const managed = await json(".speculo/managed.json");
|
|
78
|
+
if (managed) {
|
|
79
|
+
const ok = managed.schema_version === 2 && version(managed.package_version) && managed.package_version === install?.package_version && Array.isArray(managed.files) && managed.files.length > 0;
|
|
80
|
+
add("managed-contract", ok, ok ? "managed manifest schema v2 valid" : "invalid/empty managed manifest or package mismatch");
|
|
81
|
+
if (ok) {
|
|
82
|
+
const seen = new Set();
|
|
83
|
+
for (const file of managed.files) {
|
|
84
|
+
if (!record(file) || !safeRelativePath(file.path) || seen.has(file.path) || !/^[a-f0-9]{64}$/.test(String(file.sha256)) ||
|
|
85
|
+
!Number.isSafeInteger(file.bytes) || Number(file.bytes) < 0 || !nonempty(file.owner) || !["static", "baseline", "contract"].includes(String(file.kind)) || !version(file.package_version)) {
|
|
86
|
+
add("managed-entry", false, "invalid or duplicate managed file record");
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
seen.add(file.path);
|
|
90
|
+
try {
|
|
91
|
+
const actual = await sha256File(await containedPath(target, "speculo/" + file.path));
|
|
92
|
+
if (actual.bytes !== file.bytes || actual.sha256 !== file.sha256)
|
|
93
|
+
throw new Error("managed content differs from recorded digest; init replaces managed edits");
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
add("managed-file:" + file.path, false, String(error));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
for (const required of ["commands/status.md", ".speculo/workspace.json", ".speculo/kernel.json", ".speculo/AGENTS.md", ".speculo/catalog.md"]) {
|
|
100
|
+
add("managed-required:" + required, seen.has(required), seen.has(required) ? "recorded" : "missing managed entry; refresh the installation");
|
|
101
|
+
}
|
|
102
|
+
add("managed-integrity", !checks.some((c) => !c.ok && /^(managed-entry|managed-file:|managed-required:)/.test(c.id)), `verified ${seen.size} declared files; runtime evidence is not overwritten`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
for (const workflow of workflows) {
|
|
106
|
+
const manifest = await json(`workflows/${workflow}/manifest.json`), contract = await json(`workflows/${workflow}/runtime-contract.json`);
|
|
107
|
+
try {
|
|
108
|
+
await readFile(await containedPath(target, `speculo/workflows/${workflow}/INDEX.md`));
|
|
109
|
+
const ok = manifest?.schema_version === 1 && manifest.id === workflow && Array.isArray(manifest.stages) && contract?.schema_version === 1 && contract.workflow === workflow;
|
|
110
|
+
add("workflow:" + workflow, ok, ok ? "entry, manifest and runtime contract present" : "workflow contract mismatch");
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
add("workflow:" + workflow, false, String(error));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const entries = await readdir(target);
|
|
118
|
+
if (entries.includes(LOCK_NAME)) {
|
|
119
|
+
let detail = "unidentified lock; inspect owner.json, do not automatically delete it";
|
|
120
|
+
try {
|
|
121
|
+
const j = await readTransaction(target);
|
|
122
|
+
detail = `transaction ${j.id}, phase ${j.phase}; after confirming its owner stopped: speculo recover ${JSON.stringify(target)} --transaction ${j.id}`;
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
detail += "; " + String(error);
|
|
126
|
+
}
|
|
127
|
+
add("refresh-transaction", false, detail);
|
|
128
|
+
}
|
|
129
|
+
for (const name of entries.filter((name) => name.startsWith(".speculo-init-stage-") || name.startsWith(".speculo-file-")))
|
|
130
|
+
add("refresh-residue:" + name, false, "preserve residue; inspect transaction evidence before cleanup");
|
|
63
131
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
checks.push({ id: "context-checkpoints", ok: true, message: "context directory present" });
|
|
132
|
+
catch (error) {
|
|
133
|
+
add("project-directory", false, String(error));
|
|
67
134
|
}
|
|
68
|
-
return { target, healthy: checks.every((
|
|
135
|
+
return { target, healthy: checks.every((c) => c.ok), scope: "installation-integrity", notChecked: ["domain-state-transitions", "live-service-health", "agent-behavior"], checks };
|
|
69
136
|
}
|
|
70
137
|
//# sourceMappingURL=doctor.js.map
|
package/dist/src/doctor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/doctor.ts"],"names":[],"mappings":"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"}
|