@namewta/speculo 1.0.16 → 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 +29 -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/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/scripts/validate-builder.mjs +5 -1
- 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/common/rules/path-reference-contract.md +6 -0
- 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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const EXTERNAL_NAMES: readonly [".gitignore", "AGENTS.md", "CLAUDE.md"];
|
|
2
|
+
export type ExternalName = typeof EXTERNAL_NAMES[number];
|
|
3
|
+
export type FileImage = {
|
|
4
|
+
content: string;
|
|
5
|
+
mode: number;
|
|
6
|
+
} | null;
|
|
7
|
+
export type ExternalEdit = {
|
|
8
|
+
name: ExternalName;
|
|
9
|
+
before: FileImage;
|
|
10
|
+
after: FileImage;
|
|
11
|
+
};
|
|
12
|
+
export declare function bytes(image: FileImage): Buffer;
|
|
13
|
+
export declare function image(content: string | Buffer, mode?: number): FileImage;
|
|
14
|
+
export declare function imageDigest(value: FileImage): string;
|
|
15
|
+
/** Do not treat EACCES, a dangling link, a directory or a shared inode as absence. */
|
|
16
|
+
export declare function readImage(path: string): Promise<FileImage>;
|
|
17
|
+
export declare function syncDirectory(path: string): Promise<void>;
|
|
18
|
+
export declare function writeDurableJson(path: string, value: unknown): Promise<void>;
|
|
19
|
+
export declare function assertImage(path: string, expected: FileImage): Promise<void>;
|
|
20
|
+
/** Atomic file replacement. The project directory must be trusted, not an adversarial sandbox. */
|
|
21
|
+
export declare function replaceImage(path: string, expected: FileImage, next: FileImage): Promise<void>;
|
|
22
|
+
export declare function snapshotExternalFiles(target: string): Promise<Map<ExternalName, FileImage>>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { lstat, open, rename, rm } from "node:fs/promises";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
export const EXTERNAL_NAMES = [".gitignore", "AGENTS.md", "CLAUDE.md"];
|
|
6
|
+
export function bytes(image) {
|
|
7
|
+
return image ? Buffer.from(image.content, "base64") : Buffer.alloc(0);
|
|
8
|
+
}
|
|
9
|
+
export function image(content, mode = 0o644) {
|
|
10
|
+
return { content: Buffer.from(content).toString("base64"), mode: process.platform === "win32" ? (mode & 0o200 ? 0o666 : 0o444) : mode };
|
|
11
|
+
}
|
|
12
|
+
export function imageDigest(value) {
|
|
13
|
+
return value ? createHash("sha256").update(bytes(value)).update(`\0${value.mode}`).digest("hex") : "absent";
|
|
14
|
+
}
|
|
15
|
+
/** Do not treat EACCES, a dangling link, a directory or a shared inode as absence. */
|
|
16
|
+
export async function readImage(path) {
|
|
17
|
+
let stat;
|
|
18
|
+
try {
|
|
19
|
+
stat = await lstat(path);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
if (error.code === "ENOENT")
|
|
23
|
+
return null;
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1) {
|
|
27
|
+
throw new Error(`unsafe-external-file: ${path}; preserve the link and resolve source ownership before init`);
|
|
28
|
+
}
|
|
29
|
+
const handle = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
30
|
+
try {
|
|
31
|
+
const actual = await handle.stat();
|
|
32
|
+
if (!actual.isFile() || actual.dev !== stat.dev || actual.ino !== stat.ino || actual.nlink !== 1)
|
|
33
|
+
throw new Error(`external-drift: ${path}`);
|
|
34
|
+
return image(await handle.readFile(), stat.mode & 0o777);
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
await handle.close();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export async function syncDirectory(path) {
|
|
41
|
+
// Windows does not support opening/fsyncing directories through this API.
|
|
42
|
+
if (process.platform === "win32")
|
|
43
|
+
return;
|
|
44
|
+
const handle = await open(path, "r");
|
|
45
|
+
try {
|
|
46
|
+
await handle.sync();
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
await handle.close();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export async function writeDurableJson(path, value) {
|
|
53
|
+
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
54
|
+
const handle = await open(temporary, "wx", 0o600);
|
|
55
|
+
try {
|
|
56
|
+
await handle.writeFile(JSON.stringify(value, null, 2) + "\n");
|
|
57
|
+
await handle.sync();
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
await handle.close();
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
await rename(temporary, path);
|
|
64
|
+
await syncDirectory(dirname(path));
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
await rm(temporary, { force: true });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export async function assertImage(path, expected) {
|
|
71
|
+
if (imageDigest(await readImage(path)) !== imageDigest(expected))
|
|
72
|
+
throw new Error(`external-drift: ${path}; no concurrent content was overwritten`);
|
|
73
|
+
}
|
|
74
|
+
/** Atomic file replacement. The project directory must be trusted, not an adversarial sandbox. */
|
|
75
|
+
export async function replaceImage(path, expected, next) {
|
|
76
|
+
await assertImage(path, expected);
|
|
77
|
+
if (imageDigest(expected) === imageDigest(next))
|
|
78
|
+
return;
|
|
79
|
+
if (next === null) {
|
|
80
|
+
await rm(path);
|
|
81
|
+
await syncDirectory(dirname(path));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const temporary = join(dirname(path), `.speculo-file-${randomUUID()}.tmp`);
|
|
85
|
+
const handle = await open(temporary, "wx", next.mode);
|
|
86
|
+
try {
|
|
87
|
+
await handle.writeFile(bytes(next));
|
|
88
|
+
if (process.platform !== "win32")
|
|
89
|
+
await handle.chmod(next.mode);
|
|
90
|
+
await handle.sync();
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
await handle.close();
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
await assertImage(path, expected);
|
|
97
|
+
await rename(temporary, path);
|
|
98
|
+
await syncDirectory(dirname(path));
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
await rm(temporary, { force: true });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export async function snapshotExternalFiles(target) {
|
|
105
|
+
const result = new Map();
|
|
106
|
+
for (const name of EXTERNAL_NAMES)
|
|
107
|
+
result.set(name, await readImage(join(target, name)));
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=external-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-files.js","sourceRoot":"","sources":["../../src/external-files.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type TransactionHook } from "./transaction.js";
|
|
1
2
|
import { type RefreshSummary } from "./refresh.js";
|
|
2
3
|
import { type WorkflowSelection } from "./workflows.js";
|
|
3
4
|
export type SpeculoCommandResult = {
|
|
@@ -10,5 +11,7 @@ export type SpeculoOptions = {
|
|
|
10
11
|
packageRoot?: string;
|
|
11
12
|
selection?: WorkflowSelection;
|
|
12
13
|
beforeCommit?: (installRoot: string) => Promise<void>;
|
|
14
|
+
/** Test/integration fault-injection seam; never enabled through environment variables. */
|
|
15
|
+
transactionHook?: TransactionHook;
|
|
13
16
|
};
|
|
14
17
|
export declare function initSpeculo(targetArg?: string, options?: SpeculoOptions): Promise<SpeculoCommandResult>;
|
package/dist/src/index.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import { cp, mkdir, mkdtemp,
|
|
1
|
+
import { cp, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { basename, join, resolve } from "node:path";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { hostname } from "node:os";
|
|
5
|
+
import { planExternalEdits, readPersistentKnowledge, writeDiscoveryAssets } from "./agent-files.js";
|
|
6
|
+
import { assertImage, snapshotExternalFiles, writeDurableJson } from "./external-files.js";
|
|
7
|
+
import { assertInstallDirectory, commitInstall, hasTransaction, LOCK_NAME } from "./transaction.js";
|
|
3
8
|
import { fingerprintTree } from "./manifest.js";
|
|
4
9
|
import { assertNoLegacyPending, prepareRefresh, RefreshBlockedError } from "./refresh.js";
|
|
5
10
|
import { pathExists } from "./utils.js";
|
|
6
|
-
import { discoverWorkflowCatalog, isInteractive, promptWorkflowSelection, scanInstalledWorkflows,
|
|
11
|
+
import { discoverWorkflowCatalog, isInteractive, promptWorkflowSelection, scanInstalledWorkflows, } from "./workflows.js";
|
|
7
12
|
const CORE_ASSETS = [".speculo", "commands", "skills", "config.json"];
|
|
8
13
|
const INSTALL_SUBDIR = "speculo";
|
|
9
14
|
const WORKFLOW_ENTRY = "INDEX.md";
|
|
10
15
|
const STATE_TEMPLATE_DIR = "_state";
|
|
11
|
-
const SPECDEV_WORKTREE_IGNORE = "specdev-worktree/";
|
|
12
|
-
const SPECULO_BACKUP_IGNORE = "speculo/.speculo/back/";
|
|
13
|
-
const KNOWLEDGE_START = "<!-- SPECULO-PERSISTENT-KNOWLEDGE:START -->";
|
|
14
|
-
const KNOWLEDGE_END = "<!-- SPECULO-PERSISTENT-KNOWLEDGE:END -->";
|
|
15
|
-
const LEGACY_SPECULO_BLOCK = /<SPECULO>[\s\S]*?<\/SPECULO>/g;
|
|
16
|
-
const KNOWLEDGE_BLOCK = /<!-- SPECULO-PERSISTENT-KNOWLEDGE:START -->[\s\S]*?<!-- SPECULO-PERSISTENT-KNOWLEDGE:END -->/g;
|
|
17
16
|
function assetRoot(packageRoot) {
|
|
18
17
|
return join(packageRoot, "template");
|
|
19
18
|
}
|
|
@@ -38,104 +37,6 @@ async function copyCoreAssets(packageRoot, stagedRoot) {
|
|
|
38
37
|
});
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
|
-
function hasIgnorePattern(content, expected) {
|
|
42
|
-
return content.split(/\r?\n/).some((line) => {
|
|
43
|
-
const pattern = line.trim();
|
|
44
|
-
if (!pattern || pattern.startsWith("#") || pattern.startsWith("!"))
|
|
45
|
-
return false;
|
|
46
|
-
return pattern.replace(/^\//, "").replace(/\/$/, "") === expected.replace(/^\//, "").replace(/\/$/, "");
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
async function ensureRuntimeIgnores(target, root) {
|
|
50
|
-
const patterns = [SPECULO_BACKUP_IGNORE];
|
|
51
|
-
if (await pathExists(join(root, "workflows", "specdev", WORKFLOW_ENTRY)))
|
|
52
|
-
patterns.unshift(SPECDEV_WORKTREE_IGNORE);
|
|
53
|
-
const ignorePath = join(target, ".gitignore");
|
|
54
|
-
if (!(await pathExists(ignorePath))) {
|
|
55
|
-
await writeFile(ignorePath, patterns.join("\n") + "\n", "utf8");
|
|
56
|
-
return ".gitignore (created runtime ignores)";
|
|
57
|
-
}
|
|
58
|
-
let content = await readFile(ignorePath, "utf8");
|
|
59
|
-
const newline = content.includes("\r\n") ? "\r\n" : "\n";
|
|
60
|
-
const missing = patterns.filter((pattern) => !hasIgnorePattern(content, pattern));
|
|
61
|
-
if (missing.length === 0)
|
|
62
|
-
return ".gitignore (preserved runtime ignores)";
|
|
63
|
-
const separator = content.length === 0 || content.endsWith("\n") ? "" : newline;
|
|
64
|
-
content += separator + missing.join(newline) + newline;
|
|
65
|
-
await writeFile(ignorePath, content, "utf8");
|
|
66
|
-
return ".gitignore (updated runtime ignores)";
|
|
67
|
-
}
|
|
68
|
-
async function readPersistentKnowledge(packageRoot, workflowIds) {
|
|
69
|
-
const references = [];
|
|
70
|
-
for (const workflowId of workflowIds) {
|
|
71
|
-
const manifestPath = join(assetRoot(packageRoot), "workflows", workflowId, "manifest.json");
|
|
72
|
-
let manifest;
|
|
73
|
-
try {
|
|
74
|
-
manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
75
|
-
}
|
|
76
|
-
catch (error) {
|
|
77
|
-
throw new Error("Invalid workflow manifest: " + manifestPath + " (" + String(error) + ")");
|
|
78
|
-
}
|
|
79
|
-
if (manifest === null || typeof manifest !== "object" || Array.isArray(manifest)) {
|
|
80
|
-
throw new Error("Invalid workflow manifest object: " + manifestPath);
|
|
81
|
-
}
|
|
82
|
-
const knowledge = manifest.persistent_knowledge;
|
|
83
|
-
if (knowledge === undefined)
|
|
84
|
-
continue;
|
|
85
|
-
if (!Array.isArray(knowledge) || knowledge.some((path) => typeof path !== "string")) {
|
|
86
|
-
throw new Error("workflow manifest persistent_knowledge must be a string array: " + workflowId);
|
|
87
|
-
}
|
|
88
|
-
for (const path of knowledge) {
|
|
89
|
-
if (!/^<Path>\{roots\.state\}\/[^<]+<\/Path>$/.test(path) || path.includes("workflows/") || path.includes("_state/") || path.includes("/changes/") || path.includes("/archive/")) {
|
|
90
|
-
throw new Error("Unsafe workflow manifest persistent_knowledge path: " + workflowId + " -> " + path);
|
|
91
|
-
}
|
|
92
|
-
references.push({ workflow: workflowId, path });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return references;
|
|
96
|
-
}
|
|
97
|
-
function renderKnowledgeBlock(references) {
|
|
98
|
-
if (references.length === 0)
|
|
99
|
-
return "";
|
|
100
|
-
const lines = [
|
|
101
|
-
KNOWLEDGE_START,
|
|
102
|
-
"## Speculo 永久知识",
|
|
103
|
-
"",
|
|
104
|
-
"以下路径只在当前任务相关时按需读取,不会自动激活 workflow 或 Work:",
|
|
105
|
-
"",
|
|
106
|
-
];
|
|
107
|
-
for (const reference of references)
|
|
108
|
-
lines.push("- " + reference.workflow + ":" + reference.path);
|
|
109
|
-
lines.push(KNOWLEDGE_END);
|
|
110
|
-
return lines.join("\n");
|
|
111
|
-
}
|
|
112
|
-
function updateAgentsContent(content, references) {
|
|
113
|
-
const next = content.replace(LEGACY_SPECULO_BLOCK, "").replace(KNOWLEDGE_BLOCK, "");
|
|
114
|
-
const block = renderKnowledgeBlock(references);
|
|
115
|
-
if (!block)
|
|
116
|
-
return next;
|
|
117
|
-
if (!next)
|
|
118
|
-
return block + "\n";
|
|
119
|
-
const separator = next.endsWith("\n\n") ? "" : next.endsWith("\n") ? "\n" : "\n\n";
|
|
120
|
-
return next + separator + block + "\n";
|
|
121
|
-
}
|
|
122
|
-
async function writeAgentFiles(target, references) {
|
|
123
|
-
const written = [];
|
|
124
|
-
const agentsPath = join(target, "AGENTS.md");
|
|
125
|
-
const hadAgents = await pathExists(agentsPath);
|
|
126
|
-
const beforeAgents = hadAgents ? await readFile(agentsPath, "utf8") : "";
|
|
127
|
-
const afterAgents = updateAgentsContent(hadAgents ? beforeAgents : "# AGENTS.md\n", references);
|
|
128
|
-
if (!hadAgents || afterAgents !== beforeAgents) {
|
|
129
|
-
await writeFile(agentsPath, afterAgents, "utf8");
|
|
130
|
-
written.push(hadAgents ? "AGENTS.md (updated persistent knowledge)" : "AGENTS.md (created persistent knowledge)");
|
|
131
|
-
}
|
|
132
|
-
const claudePath = join(target, "CLAUDE.md");
|
|
133
|
-
if (!(await pathExists(claudePath))) {
|
|
134
|
-
await writeFile(claudePath, "# CLAUDE.md\n\nSpeculo agent handbook: see [AGENTS.md](./AGENTS.md).\n", "utf8");
|
|
135
|
-
written.push("CLAUDE.md (created redirect)");
|
|
136
|
-
}
|
|
137
|
-
return written;
|
|
138
|
-
}
|
|
139
40
|
async function resolveSelection(packageRoot, currentRoot, options) {
|
|
140
41
|
const catalog = await discoverWorkflowCatalog(packageRoot);
|
|
141
42
|
if (options.selection) {
|
|
@@ -145,9 +46,9 @@ async function resolveSelection(packageRoot, currentRoot, options) {
|
|
|
145
46
|
throw new Error("Unknown workflow package: " + id);
|
|
146
47
|
return { workflowIds: ids };
|
|
147
48
|
}
|
|
148
|
-
if (!isInteractive())
|
|
149
|
-
return selectAllFromCatalog(catalog);
|
|
150
49
|
const installed = new Set(await scanInstalledWorkflows(currentRoot));
|
|
50
|
+
if (!isInteractive())
|
|
51
|
+
return { workflowIds: [...installed].filter((id) => catalog.has(id)).sort() };
|
|
151
52
|
return promptWorkflowSelection(catalog, {
|
|
152
53
|
preSelectedWorkflowIds: new Set([...installed].filter((workflowId) => catalog.has(workflowId))),
|
|
153
54
|
});
|
|
@@ -195,6 +96,7 @@ async function buildStagedInstall(packageRoot, target, previousRoot, catalog, se
|
|
|
195
96
|
for (const workflowId of selection.workflowIds)
|
|
196
97
|
await copySelectedWorkflow(packageRoot, stagedRoot, workflowId);
|
|
197
98
|
const unselectedWorkflowIds = await installedUnselectedWorkflowIds(catalog, selection, previousRoot);
|
|
99
|
+
await writeDiscoveryAssets(packageRoot, stagedRoot);
|
|
198
100
|
const refresh = await prepareRefresh({
|
|
199
101
|
packageRoot,
|
|
200
102
|
previousRoot,
|
|
@@ -210,72 +112,16 @@ async function buildStagedInstall(packageRoot, target, previousRoot, catalog, se
|
|
|
210
112
|
throw error;
|
|
211
113
|
}
|
|
212
114
|
}
|
|
213
|
-
async function snapshotExternalFiles(target) {
|
|
214
|
-
const snapshots = [];
|
|
215
|
-
for (const name of [".gitignore", "AGENTS.md", "CLAUDE.md"]) {
|
|
216
|
-
const path = join(target, name);
|
|
217
|
-
if (await pathExists(path))
|
|
218
|
-
snapshots.push({ path, existed: true, content: await readFile(path) });
|
|
219
|
-
else
|
|
220
|
-
snapshots.push({ path, existed: false });
|
|
221
|
-
}
|
|
222
|
-
return snapshots;
|
|
223
|
-
}
|
|
224
|
-
async function restoreExternalFiles(snapshots) {
|
|
225
|
-
for (const snapshot of snapshots) {
|
|
226
|
-
if (snapshot.existed)
|
|
227
|
-
await writeFile(snapshot.path, snapshot.content ?? Buffer.alloc(0));
|
|
228
|
-
else
|
|
229
|
-
await rm(snapshot.path, { force: true });
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
async function replaceInstall(stagedRoot, root, finalize) {
|
|
233
|
-
const expectedFingerprint = await fingerprintTree(stagedRoot);
|
|
234
|
-
if (!(await pathExists(root))) {
|
|
235
|
-
await rename(stagedRoot, root);
|
|
236
|
-
if (await fingerprintTree(root) !== expectedFingerprint) {
|
|
237
|
-
await rename(root, stagedRoot);
|
|
238
|
-
throw new Error("post-install validation failed");
|
|
239
|
-
}
|
|
240
|
-
try {
|
|
241
|
-
await finalize?.();
|
|
242
|
-
}
|
|
243
|
-
catch (error) {
|
|
244
|
-
await rm(root, { recursive: true, force: true });
|
|
245
|
-
throw error;
|
|
246
|
-
}
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
const backupRoot = stagedRoot + "-backup";
|
|
250
|
-
await rename(root, backupRoot);
|
|
251
|
-
try {
|
|
252
|
-
await rename(stagedRoot, root);
|
|
253
|
-
if (await fingerprintTree(root) !== expectedFingerprint)
|
|
254
|
-
throw new Error("post-install validation failed");
|
|
255
|
-
await finalize?.();
|
|
256
|
-
}
|
|
257
|
-
catch (error) {
|
|
258
|
-
try {
|
|
259
|
-
if (await pathExists(root))
|
|
260
|
-
await rename(root, stagedRoot);
|
|
261
|
-
await rename(backupRoot, root);
|
|
262
|
-
}
|
|
263
|
-
catch (rollbackError) {
|
|
264
|
-
throw new Error("Failed to replace Speculo installation and restore the previous installation: " + String(rollbackError));
|
|
265
|
-
}
|
|
266
|
-
throw error;
|
|
267
|
-
}
|
|
268
|
-
await rm(backupRoot, { recursive: true, force: true });
|
|
269
|
-
}
|
|
270
115
|
export async function initSpeculo(targetArg = ".", options = {}) {
|
|
271
116
|
const target = resolve(targetArg);
|
|
272
117
|
const packageRoot = resolve(options.packageRoot ?? process.cwd());
|
|
273
118
|
const root = installRoot(target);
|
|
119
|
+
await assertInstallDirectory(target);
|
|
274
120
|
const existed = await pathExists(root);
|
|
275
121
|
await mkdir(target, { recursive: true });
|
|
276
|
-
const lockRoot = join(target,
|
|
122
|
+
const lockRoot = join(target, LOCK_NAME);
|
|
277
123
|
try {
|
|
278
|
-
await mkdir(lockRoot);
|
|
124
|
+
await mkdir(lockRoot, { mode: 0o700 });
|
|
279
125
|
}
|
|
280
126
|
catch (error) {
|
|
281
127
|
if (error.code !== "EEXIST")
|
|
@@ -285,6 +131,9 @@ export async function initSpeculo(targetArg = ".", options = {}) {
|
|
|
285
131
|
let stagedRoot;
|
|
286
132
|
let refresh;
|
|
287
133
|
try {
|
|
134
|
+
await writeFile(join(lockRoot, ".gitignore"), "*\n", { mode: 0o600 });
|
|
135
|
+
await writeDurableJson(join(lockRoot, "owner.json"), { schema_version: 1, id: randomUUID(), host: hostname(), pid: process.pid, started_at: new Date().toISOString() });
|
|
136
|
+
const externalSnapshot = await snapshotExternalFiles(target);
|
|
288
137
|
if (existed)
|
|
289
138
|
await assertNoLegacyPending(root);
|
|
290
139
|
const catalog = await discoverWorkflowCatalog(packageRoot);
|
|
@@ -303,27 +152,25 @@ export async function initSpeculo(targetArg = ".", options = {}) {
|
|
|
303
152
|
}
|
|
304
153
|
const assets = [".speculo", "config.json", "commands", "skills"];
|
|
305
154
|
assets.push(...selection.workflowIds.map((workflowId) => "workflows/" + workflowId));
|
|
306
|
-
const
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
catch (error) {
|
|
314
|
-
await restoreExternalFiles(externalSnapshot);
|
|
315
|
-
throw error;
|
|
316
|
-
}
|
|
317
|
-
});
|
|
155
|
+
const installed = await scanInstalledWorkflows(stagedRoot);
|
|
156
|
+
const references = await readPersistentKnowledge(stagedRoot, installed);
|
|
157
|
+
const edits = planExternalEdits(externalSnapshot, references, installed.includes("specdev"));
|
|
158
|
+
for (const edit of edits)
|
|
159
|
+
await assertImage(join(target, edit.name), edit.before);
|
|
160
|
+
await commitInstall(target, stagedRoot, initialFingerprint, edits, options.transactionHook);
|
|
161
|
+
assets.push(...edits.map((edit) => edit.name + " (managed discovery/runtime references)"));
|
|
318
162
|
stagedRoot = undefined;
|
|
319
163
|
if (!refresh)
|
|
320
164
|
throw new Error("Speculo refresh result was not produced");
|
|
321
165
|
return { target, mode: existed ? "refresh" : "init", assets, refresh };
|
|
322
166
|
}
|
|
323
167
|
finally {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
168
|
+
// A failed rollback or killed process leaves durable evidence; never delete it in finally.
|
|
169
|
+
if (!(await hasTransaction(target))) {
|
|
170
|
+
if (stagedRoot)
|
|
171
|
+
await rm(stagedRoot, { recursive: true, force: true });
|
|
172
|
+
await rm(lockRoot, { recursive: true, force: true });
|
|
173
|
+
}
|
|
327
174
|
}
|
|
328
175
|
}
|
|
329
176
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const ROOT_NAMES: readonly ["config", "speculo", "state", "commands", "skills", "workflows"];
|
|
2
|
+
export type RootName = typeof ROOT_NAMES[number];
|
|
3
|
+
export type Workspace = {
|
|
4
|
+
schema_version: 1;
|
|
5
|
+
path_base: "project-root";
|
|
6
|
+
roots: Record<RootName, string>;
|
|
7
|
+
};
|
|
8
|
+
export declare function safeRelativePath(value: unknown): value is string;
|
|
9
|
+
export declare function validateWorkspace(value: unknown): asserts value is Workspace;
|
|
10
|
+
export declare function containedPath(projectRoot: string, portable: string): Promise<string>;
|
|
11
|
+
/** Resolve one explicit reference, not shell text. No shell is invoked or authorized. */
|
|
12
|
+
export declare function resolvePathReference(projectRoot: string, reference: string): Promise<string>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { lstat, readFile } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
3
|
+
export const ROOT_NAMES = ["config", "speculo", "state", "commands", "skills", "workflows"];
|
|
4
|
+
export function safeRelativePath(value) {
|
|
5
|
+
return typeof value === "string" && value.length > 0 && !isAbsolute(value) && !/[\\:\x00-\x1f]/.test(value) &&
|
|
6
|
+
!value.startsWith("/") && !value.split("/").some((part, index, all) => part === ".." || part === "." || (!part && index < all.length - 1));
|
|
7
|
+
}
|
|
8
|
+
export function validateWorkspace(value) {
|
|
9
|
+
const w = value;
|
|
10
|
+
if (!w || w.schema_version !== 1 || w.path_base !== "project-root" || !w.roots || Array.isArray(w.roots) ||
|
|
11
|
+
!ROOT_NAMES.every((key) => safeRelativePath(w.roots?.[key])))
|
|
12
|
+
throw new Error("invalid-workspace-roots");
|
|
13
|
+
const root = w.roots.speculo.replace(/\/$/, "");
|
|
14
|
+
for (const key of ROOT_NAMES.filter((name) => name !== "speculo")) {
|
|
15
|
+
if (!w.roots[key].startsWith(root + "/"))
|
|
16
|
+
throw new Error(`workspace-root-outside-installation: ${key}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function containedPath(projectRoot, portable) {
|
|
20
|
+
if (!safeRelativePath(portable))
|
|
21
|
+
throw new Error(`unsafe-project-path: ${portable}`);
|
|
22
|
+
const root = resolve(projectRoot), target = resolve(root, portable), rel = relative(root, target);
|
|
23
|
+
if (rel === ".." || rel.startsWith(".." + sep) || isAbsolute(rel))
|
|
24
|
+
throw new Error("path-outside-project");
|
|
25
|
+
let cursor = root;
|
|
26
|
+
for (const part of rel.split(sep)) {
|
|
27
|
+
cursor = join(cursor, part);
|
|
28
|
+
try {
|
|
29
|
+
if ((await lstat(cursor)).isSymbolicLink())
|
|
30
|
+
throw new Error(`path-symlink: ${cursor}; explicit source ownership is required`);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error.code !== "ENOENT")
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return target;
|
|
38
|
+
}
|
|
39
|
+
/** Resolve one explicit reference, not shell text. No shell is invoked or authorized. */
|
|
40
|
+
export async function resolvePathReference(projectRoot, reference) {
|
|
41
|
+
const workspacePath = await containedPath(projectRoot, "speculo/.speculo/workspace.json");
|
|
42
|
+
const workspace = JSON.parse(await readFile(workspacePath, "utf8"));
|
|
43
|
+
validateWorkspace(workspace);
|
|
44
|
+
const tagged = /^<Path>([^<>]+)<\/Path>$/.exec(reference);
|
|
45
|
+
if (reference.includes("<") && !tagged)
|
|
46
|
+
throw new Error("invalid-path-tag");
|
|
47
|
+
let portable = tagged?.[1] ?? reference;
|
|
48
|
+
portable = portable.replace(/^\{roots\.([a-z]+)\}/, (_, key) => {
|
|
49
|
+
if (!ROOT_NAMES.includes(key))
|
|
50
|
+
throw new Error(`unknown-root: ${key}`);
|
|
51
|
+
return workspace.roots[key].replace(/\/$/, "");
|
|
52
|
+
});
|
|
53
|
+
if (/[{}*?]/.test(portable))
|
|
54
|
+
throw new Error("unresolved-path-reference: substitute identifiers before execution; glob expansion is not supported");
|
|
55
|
+
return containedPath(projectRoot, portable);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type ExternalEdit } from "./external-files.js";
|
|
2
|
+
export declare const LOCK_NAME = ".speculo-init.lock";
|
|
3
|
+
export type TransactionPhase = "prepared" | "old-renamed" | "installed" | "external-finalized" | "committed" | "rolled-back";
|
|
4
|
+
export type TransactionHook = (phase: TransactionPhase) => Promise<void>;
|
|
5
|
+
type Journal = {
|
|
6
|
+
schema_version: 1;
|
|
7
|
+
id: string;
|
|
8
|
+
host: string;
|
|
9
|
+
pid: number;
|
|
10
|
+
target: string;
|
|
11
|
+
stage: string;
|
|
12
|
+
backup: string;
|
|
13
|
+
before: string;
|
|
14
|
+
after: string;
|
|
15
|
+
phase: TransactionPhase;
|
|
16
|
+
external: ExternalEdit[];
|
|
17
|
+
};
|
|
18
|
+
export declare function assertInstallDirectory(target: string): Promise<void>;
|
|
19
|
+
export declare function readTransaction(target: string): Promise<Journal>;
|
|
20
|
+
export declare function commitInstall(target: string, stagedRoot: string, before: string, external: ExternalEdit[], hook?: TransactionHook): Promise<void>;
|
|
21
|
+
/** Explicit local recovery only. Never steals a live, remote-host, or unidentified lock. */
|
|
22
|
+
export declare function recoverInstall(targetArg: string, id: string): Promise<{
|
|
23
|
+
id: string;
|
|
24
|
+
outcome: string;
|
|
25
|
+
}>;
|
|
26
|
+
export declare function hasTransaction(target: string): Promise<boolean>;
|
|
27
|
+
export {};
|