oh-my-claudecode 0.2.3 → 0.2.4

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 (64) hide show
  1. package/README.md +48 -1
  2. package/dist/cli/bind-cron.d.ts +86 -0
  3. package/dist/cli/bind-cron.d.ts.map +1 -0
  4. package/dist/cli/bind-cron.js +161 -0
  5. package/dist/cli/bind-cron.js.map +1 -0
  6. package/dist/cli/bind.d.ts +78 -0
  7. package/dist/cli/bind.d.ts.map +1 -0
  8. package/dist/cli/bind.js +417 -0
  9. package/dist/cli/bind.js.map +1 -0
  10. package/dist/cli/index.js +61 -0
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/cli/project-scan.d.ts +94 -0
  13. package/dist/cli/project-scan.d.ts.map +1 -0
  14. package/dist/cli/project-scan.js +387 -0
  15. package/dist/cli/project-scan.js.map +1 -0
  16. package/dist/cli/sisyphus-migrate.d.ts +50 -0
  17. package/dist/cli/sisyphus-migrate.d.ts.map +1 -0
  18. package/dist/cli/sisyphus-migrate.js +226 -0
  19. package/dist/cli/sisyphus-migrate.js.map +1 -0
  20. package/dist/cli/tui.d.ts +94 -0
  21. package/dist/cli/tui.d.ts.map +1 -0
  22. package/dist/cli/tui.js +180 -0
  23. package/dist/cli/tui.js.map +1 -0
  24. package/dist/features/yith-archive/functions/backfill.d.ts +43 -0
  25. package/dist/features/yith-archive/functions/backfill.d.ts.map +1 -1
  26. package/dist/features/yith-archive/functions/backfill.js +303 -145
  27. package/dist/features/yith-archive/functions/backfill.js.map +1 -1
  28. package/dist/features/yith-archive/functions/compress-batch.d.ts +4 -0
  29. package/dist/features/yith-archive/functions/compress-batch.d.ts.map +1 -0
  30. package/dist/features/yith-archive/functions/compress-batch.js +290 -0
  31. package/dist/features/yith-archive/functions/compress-batch.js.map +1 -0
  32. package/dist/features/yith-archive/functions/compress.d.ts +2 -1
  33. package/dist/features/yith-archive/functions/compress.d.ts.map +1 -1
  34. package/dist/features/yith-archive/functions/compress.js +1 -1
  35. package/dist/features/yith-archive/functions/compress.js.map +1 -1
  36. package/dist/features/yith-archive/functions/opencode-import.d.ts +67 -0
  37. package/dist/features/yith-archive/functions/opencode-import.d.ts.map +1 -0
  38. package/dist/features/yith-archive/functions/opencode-import.js +272 -0
  39. package/dist/features/yith-archive/functions/opencode-import.js.map +1 -0
  40. package/dist/features/yith-archive/index.d.ts.map +1 -1
  41. package/dist/features/yith-archive/index.js +4 -0
  42. package/dist/features/yith-archive/index.js.map +1 -1
  43. package/dist/features/yith-archive/providers/embedding/local.d.ts +22 -0
  44. package/dist/features/yith-archive/providers/embedding/local.d.ts.map +1 -1
  45. package/dist/features/yith-archive/providers/embedding/local.js +56 -2
  46. package/dist/features/yith-archive/providers/embedding/local.js.map +1 -1
  47. package/dist/features/yith-archive/state/bind-state.d.ts +84 -0
  48. package/dist/features/yith-archive/state/bind-state.d.ts.map +1 -0
  49. package/dist/features/yith-archive/state/bind-state.js +120 -0
  50. package/dist/features/yith-archive/state/bind-state.js.map +1 -0
  51. package/dist/features/yith-archive/state/schema.d.ts +14 -0
  52. package/dist/features/yith-archive/state/schema.d.ts.map +1 -1
  53. package/dist/features/yith-archive/state/schema.js +14 -0
  54. package/dist/features/yith-archive/state/schema.js.map +1 -1
  55. package/dist/hooks/cthulhu-auto.d.ts +1 -1
  56. package/dist/hooks/cthulhu-auto.d.ts.map +1 -1
  57. package/dist/hooks/cthulhu-auto.js +75 -11
  58. package/dist/hooks/cthulhu-auto.js.map +1 -1
  59. package/dist/hooks/cthulhu-preflight.d.ts +45 -0
  60. package/dist/hooks/cthulhu-preflight.d.ts.map +1 -0
  61. package/dist/hooks/cthulhu-preflight.js +91 -0
  62. package/dist/hooks/cthulhu-preflight.js.map +1 -0
  63. package/package.json +5 -2
  64. /package/commands/{bind-necronomicon.md → necronomicon-bind.md} +0 -0
@@ -0,0 +1,387 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
2
+ import { extname, join, relative } from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ // ============================================================================
5
+ // Gitignore
6
+ // ============================================================================
7
+ /**
8
+ * Parse a .gitignore body into a flat list of patterns. Drops
9
+ * comment lines (# prefix) and empty lines. Trailing slashes on
10
+ * directory patterns are preserved so `isIgnored` can match them.
11
+ */
12
+ export function parseGitignore(body) {
13
+ const out = [];
14
+ for (const line of body.split("\n")) {
15
+ const trimmed = line.trim();
16
+ if (!trimmed || trimmed.startsWith("#"))
17
+ continue;
18
+ out.push(trimmed);
19
+ }
20
+ return out;
21
+ }
22
+ /**
23
+ * Check whether a relative path matches any gitignore pattern.
24
+ * Supports literal names, `*.ext` globs, and trailing-slash
25
+ * directory patterns.
26
+ */
27
+ export function isIgnored(relPath, patterns) {
28
+ const firstSegment = relPath.split("/")[0];
29
+ for (const p of patterns) {
30
+ const pattern = p.endsWith("/") ? p.slice(0, -1) : p;
31
+ // Literal match anywhere in the path.
32
+ if (firstSegment === pattern)
33
+ return true;
34
+ if (relPath === pattern)
35
+ return true;
36
+ // Glob: *.ext
37
+ if (pattern.startsWith("*.")) {
38
+ const ext = pattern.slice(1); // ".ext"
39
+ if (relPath.endsWith(ext))
40
+ return true;
41
+ }
42
+ // Directory glob: dir or dir/
43
+ if (relPath.startsWith(`${pattern}/`))
44
+ return true;
45
+ }
46
+ return false;
47
+ }
48
+ // ============================================================================
49
+ // Language stats
50
+ // ============================================================================
51
+ /**
52
+ * Count file paths by extension and return the most-common one as
53
+ * the primary language indicator. Extensions include the leading dot
54
+ * so callers can distinguish `.ts` / `.tsx` / `.js` etc.
55
+ */
56
+ export function summarizeLanguages(files) {
57
+ const byExt = {};
58
+ for (const f of files) {
59
+ const ext = extname(f).toLowerCase();
60
+ if (!ext)
61
+ continue;
62
+ byExt[ext] = (byExt[ext] ?? 0) + 1;
63
+ }
64
+ // Pick primary: max by count. Tie goes to whichever iterates first.
65
+ let primary = "";
66
+ let max = 0;
67
+ for (const [ext, n] of Object.entries(byExt)) {
68
+ if (n > max) {
69
+ max = n;
70
+ primary = ext;
71
+ }
72
+ }
73
+ return { byExt, primary, total: files.length };
74
+ }
75
+ // ============================================================================
76
+ // README extraction
77
+ // ============================================================================
78
+ /**
79
+ * Extract the top-level title, first paragraph, and H2 headings from
80
+ * a README markdown body. Used for the project-summary observation
81
+ * so downstream search has something to match against even when the
82
+ * README is the only source of truth about what the project does.
83
+ */
84
+ export function extractReadmeSections(body) {
85
+ // Title: first `# <title>`
86
+ const titleMatch = body.match(/^#\s+(.+?)\s*$/m);
87
+ const title = titleMatch ? titleMatch[1].trim() : null;
88
+ // First paragraph: first non-empty block after the title.
89
+ let firstParagraph = null;
90
+ if (titleMatch) {
91
+ const afterTitle = body.slice(titleMatch.index + titleMatch[0].length);
92
+ const paras = afterTitle.split(/\n\s*\n/).map((p) => p.trim());
93
+ firstParagraph = paras.find((p) => p && !p.startsWith("#")) ?? null;
94
+ }
95
+ // H2 headings.
96
+ const headings = [];
97
+ for (const m of body.matchAll(/^##\s+(.+?)\s*$/gm)) {
98
+ headings.push(m[1].trim());
99
+ }
100
+ return { title, firstParagraph, headings };
101
+ }
102
+ // ============================================================================
103
+ // package.json parser
104
+ // ============================================================================
105
+ /**
106
+ * Parse a package.json body into a simplified PackageInfo summary.
107
+ * Returns null on malformed JSON — callers should handle the null
108
+ * case (e.g., emit a "malformed package.json" observation).
109
+ */
110
+ export function parsePackageJson(body) {
111
+ let data;
112
+ try {
113
+ data = JSON.parse(body);
114
+ }
115
+ catch {
116
+ return null;
117
+ }
118
+ const name = typeof data.name === "string" ? data.name : undefined;
119
+ const version = typeof data.version === "string" ? data.version : undefined;
120
+ const description = typeof data.description === "string" ? data.description : undefined;
121
+ const entryPoint = typeof data.main === "string" ? data.main : undefined;
122
+ const runtime = (data.dependencies ?? {});
123
+ const dev = (data.devDependencies ?? {});
124
+ const scripts = (data.scripts ?? {});
125
+ return {
126
+ name,
127
+ version,
128
+ description,
129
+ entryPoint,
130
+ runtimeDependencies: Object.keys(runtime),
131
+ devDependencies: Object.keys(dev),
132
+ scripts: Object.fromEntries(Object.entries(scripts).filter(([, v]) => typeof v === "string")),
133
+ };
134
+ }
135
+ // ============================================================================
136
+ // Directory walk
137
+ // ============================================================================
138
+ const MAX_WALK_DEPTH = 6;
139
+ const MAX_FILES = 2000;
140
+ /** Recursively walk a project tree, honoring a gitignore patterns
141
+ * list. Returns relative paths (relative to `root`). */
142
+ function walkProject(root, patterns, current, depth, accum) {
143
+ if (depth > MAX_WALK_DEPTH)
144
+ return;
145
+ if (accum.length >= MAX_FILES)
146
+ return;
147
+ let entries;
148
+ try {
149
+ entries = readdirSync(current);
150
+ }
151
+ catch {
152
+ return;
153
+ }
154
+ for (const entry of entries) {
155
+ if (accum.length >= MAX_FILES)
156
+ return;
157
+ // Hard skip for well-known heavy dirs regardless of gitignore.
158
+ if (entry === ".git" ||
159
+ entry === "node_modules" ||
160
+ entry === ".next" ||
161
+ entry === "dist") {
162
+ continue;
163
+ }
164
+ const abs = join(current, entry);
165
+ const rel = relative(root, abs);
166
+ if (isIgnored(rel, patterns))
167
+ continue;
168
+ let s;
169
+ try {
170
+ s = statSync(abs);
171
+ }
172
+ catch {
173
+ continue;
174
+ }
175
+ if (s.isDirectory()) {
176
+ walkProject(root, patterns, abs, depth + 1, accum);
177
+ }
178
+ else if (s.isFile()) {
179
+ accum.push(rel);
180
+ }
181
+ }
182
+ }
183
+ // ============================================================================
184
+ // Top-level scan
185
+ // ============================================================================
186
+ const KNOWN_CONFIG_FILES = [
187
+ "package.json",
188
+ "tsconfig.json",
189
+ "jsconfig.json",
190
+ "Cargo.toml",
191
+ "pyproject.toml",
192
+ "go.mod",
193
+ "composer.json",
194
+ "Gemfile",
195
+ "shard.yml",
196
+ "build.gradle",
197
+ "pom.xml",
198
+ "Makefile",
199
+ "CMakeLists.txt",
200
+ "Dockerfile",
201
+ "docker-compose.yml",
202
+ ".prettierrc",
203
+ ".eslintrc.json",
204
+ ];
205
+ export async function scanProject(root) {
206
+ if (!existsSync(root)) {
207
+ return {
208
+ path: root,
209
+ files: [],
210
+ languages: { byExt: {}, primary: "", total: 0 },
211
+ packageInfo: null,
212
+ readme: null,
213
+ configFiles: [],
214
+ directoryTree: "",
215
+ };
216
+ }
217
+ // Load top-level .gitignore.
218
+ const gitignorePath = join(root, ".gitignore");
219
+ const patterns = existsSync(gitignorePath)
220
+ ? parseGitignore(readFileSync(gitignorePath, "utf-8"))
221
+ : [];
222
+ // Walk.
223
+ const files = [];
224
+ walkProject(root, patterns, root, 0, files);
225
+ // Config files discovered by name at top level.
226
+ const configFiles = KNOWN_CONFIG_FILES.filter((name) => existsSync(join(root, name)));
227
+ // Language stats.
228
+ const languages = summarizeLanguages(files);
229
+ // package.json.
230
+ let packageInfo = null;
231
+ const pkgPath = join(root, "package.json");
232
+ if (existsSync(pkgPath)) {
233
+ try {
234
+ packageInfo = parsePackageJson(readFileSync(pkgPath, "utf-8"));
235
+ }
236
+ catch {
237
+ /* malformed — leave null */
238
+ }
239
+ }
240
+ // README.
241
+ let readme = null;
242
+ for (const name of ["README.md", "readme.md", "Readme.md", "README"]) {
243
+ const p = join(root, name);
244
+ if (existsSync(p)) {
245
+ try {
246
+ readme = extractReadmeSections(readFileSync(p, "utf-8"));
247
+ break;
248
+ }
249
+ catch {
250
+ /* ignore */
251
+ }
252
+ }
253
+ }
254
+ // Directory tree: flatten to depth-2 string.
255
+ const directoryTree = buildDirectoryTree(root, patterns);
256
+ return {
257
+ path: root,
258
+ files,
259
+ languages,
260
+ packageInfo,
261
+ readme,
262
+ configFiles,
263
+ directoryTree,
264
+ };
265
+ }
266
+ function buildDirectoryTree(root, patterns) {
267
+ const lines = [];
268
+ try {
269
+ const entries = readdirSync(root);
270
+ for (const entry of entries) {
271
+ if (entry === ".git" ||
272
+ entry === "node_modules" ||
273
+ entry === ".next" ||
274
+ entry === "dist")
275
+ continue;
276
+ if (isIgnored(entry, patterns))
277
+ continue;
278
+ let s;
279
+ try {
280
+ s = statSync(join(root, entry));
281
+ }
282
+ catch {
283
+ continue;
284
+ }
285
+ lines.push(`${entry}${s.isDirectory() ? "/" : ""}`);
286
+ }
287
+ }
288
+ catch {
289
+ /* unreadable root */
290
+ }
291
+ return lines.sort().join("\n");
292
+ }
293
+ // ============================================================================
294
+ // Summary → observations
295
+ // ============================================================================
296
+ /**
297
+ * Emit a set of RawObservations synthesized from the scan results.
298
+ * Every observation gets a stable ID derived from the project path
299
+ * plus the observation kind, so re-running the scan produces the
300
+ * same IDs and the idempotent-upsert path in the write layer
301
+ * dedupes automatically.
302
+ */
303
+ export function projectSummaryToObservations(summary) {
304
+ const obs = [];
305
+ const now = new Date().toISOString();
306
+ const sessionId = `proj:${hash(summary.path)}`;
307
+ const mkId = (kind) => `proj:${hash(summary.path)}:${kind}`;
308
+ // 1. Language summary.
309
+ if (summary.languages.total > 0) {
310
+ const topExts = Object.entries(summary.languages.byExt)
311
+ .sort((a, b) => b[1] - a[1])
312
+ .slice(0, 5)
313
+ .map(([ext, n]) => `${ext} (${n})`)
314
+ .join(", ");
315
+ obs.push({
316
+ id: mkId("languages"),
317
+ sessionId,
318
+ timestamp: now,
319
+ hookType: "session_start",
320
+ userPrompt: `Project at ${summary.path} has ${summary.languages.total} source files. ` +
321
+ `Top languages: ${topExts}. Primary: ${summary.languages.primary || "mixed"}.`,
322
+ raw: { kind: "project-languages", languages: summary.languages },
323
+ });
324
+ }
325
+ // 2. Package info.
326
+ if (summary.packageInfo) {
327
+ const pkg = summary.packageInfo;
328
+ const deps = pkg.runtimeDependencies.slice(0, 10).join(", ");
329
+ const devDeps = pkg.devDependencies.slice(0, 10).join(", ");
330
+ obs.push({
331
+ id: mkId("package"),
332
+ sessionId,
333
+ timestamp: now,
334
+ hookType: "session_start",
335
+ userPrompt: `Package ${pkg.name ?? "(unnamed)"} v${pkg.version ?? "0"}: ` +
336
+ `${pkg.description ?? ""}. ` +
337
+ (pkg.entryPoint ? `Entry: ${pkg.entryPoint}. ` : "") +
338
+ (deps ? `Runtime deps: ${deps}. ` : "") +
339
+ (devDeps ? `Dev deps: ${devDeps}.` : ""),
340
+ raw: { kind: "project-package", package: pkg },
341
+ });
342
+ }
343
+ // 3. README summary.
344
+ if (summary.readme?.title || summary.readme?.firstParagraph) {
345
+ obs.push({
346
+ id: mkId("readme"),
347
+ sessionId,
348
+ timestamp: now,
349
+ hookType: "session_start",
350
+ userPrompt: `README for project ${summary.path}: ` +
351
+ (summary.readme.title ? `"${summary.readme.title}". ` : "") +
352
+ (summary.readme.firstParagraph ?? "") +
353
+ (summary.readme.headings.length > 0
354
+ ? ` Sections: ${summary.readme.headings.join(", ")}.`
355
+ : ""),
356
+ raw: { kind: "project-readme", readme: summary.readme },
357
+ });
358
+ }
359
+ // 4. Directory structure.
360
+ if (summary.directoryTree) {
361
+ obs.push({
362
+ id: mkId("tree"),
363
+ sessionId,
364
+ timestamp: now,
365
+ hookType: "session_start",
366
+ userPrompt: `Top-level structure of ${summary.path}:\n` + summary.directoryTree,
367
+ raw: { kind: "project-tree", tree: summary.directoryTree },
368
+ });
369
+ }
370
+ // 5. Config files.
371
+ if (summary.configFiles.length > 0) {
372
+ obs.push({
373
+ id: mkId("configs"),
374
+ sessionId,
375
+ timestamp: now,
376
+ hookType: "session_start",
377
+ userPrompt: `Config files detected in ${summary.path}: ${summary.configFiles.join(", ")}.`,
378
+ raw: { kind: "project-configs", configs: summary.configFiles },
379
+ });
380
+ }
381
+ return obs;
382
+ }
383
+ /** Short stable hash of a string, used for generating observation IDs. */
384
+ function hash(s) {
385
+ return createHash("sha256").update(s).digest("hex").slice(0, 12);
386
+ }
387
+ //# sourceMappingURL=project-scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-scan.js","sourceRoot":"","sources":["../../src/cli/project-scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * .sisyphus/ → .elder-gods/ filesystem migrator.
3
+ *
4
+ * oh-my-opencode used per-project `.sisyphus/` dirs to hold
5
+ * operational state: plans, handoffs, evidence, and a `boulder.json`
6
+ * tracking the active task. oh-my-claudecode uses the analogous
7
+ * `.elder-gods/` layout. This function walks a single project's
8
+ * `.sisyphus/` and copies / translates contents into the project's
9
+ * new `.elder-gods/` home.
10
+ *
11
+ * Non-destructive: the source directory is left fully intact. Users
12
+ * can delete it manually after verifying the migration. No in-place
13
+ * rename, no recycle bin — the migrator only reads the source.
14
+ *
15
+ * Idempotent: a second run detects files that already exist at the
16
+ * destination (by name) and skips them. Zero-copy counts are the
17
+ * expected steady state.
18
+ *
19
+ * Mapping:
20
+ *
21
+ * .sisyphus/plans/*.md → .elder-gods/plans/*.md (1:1)
22
+ * .sisyphus/handoff.md → .elder-gods/handoffs/YYYY-MM-DD-<slug>.md
23
+ * .sisyphus/evidence/ → .elder-gods/evidence/ (recursive copy)
24
+ * .sisyphus/notepads/ → .elder-gods/legacy/notepads/
25
+ * .sisyphus/drafts/ → .elder-gods/legacy/drafts/
26
+ * .sisyphus/run-continuation/ → .elder-gods/legacy/run-continuation/
27
+ * .sisyphus/boulder.json → .elder-gods/plans/legacy-boulder.md
28
+ * (translated to markdown — see
29
+ * `boulderToMarkdown` below)
30
+ *
31
+ * The legacy/ subdir is a catch-all for state we don't have a first-
32
+ * class equivalent for. Users can grep it, migrate it further, or
33
+ * delete it.
34
+ */
35
+ export interface MigrateSisyphusOptions {
36
+ source: string;
37
+ dest: string;
38
+ }
39
+ export interface MigrateSisyphusResult {
40
+ /** True when source doesn't exist — nothing to do. */
41
+ skipped: boolean;
42
+ plansCopied: number;
43
+ handoffsCopied: number;
44
+ evidenceCopied: number;
45
+ legacyCopied: number;
46
+ boulderImported: boolean;
47
+ errors: string[];
48
+ }
49
+ export declare function migrateSisyphusDir(opts: MigrateSisyphusOptions): MigrateSisyphusResult;
50
+ //# sourceMappingURL=sisyphus-migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sisyphus-migrate.d.ts","sourceRoot":"","sources":["../../src/cli/sisyphus-migrate.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,qBAAqB;IACpC,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,OAAO,CAAA;IACxB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,sBAAsB,GAC3B,qBAAqB,CA6HvB"}
@@ -0,0 +1,226 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, copyFileSync, statSync, } from "node:fs";
2
+ import { join, basename, extname } from "node:path";
3
+ export function migrateSisyphusDir(opts) {
4
+ const { source, dest } = opts;
5
+ const result = {
6
+ skipped: false,
7
+ plansCopied: 0,
8
+ handoffsCopied: 0,
9
+ evidenceCopied: 0,
10
+ legacyCopied: 0,
11
+ boulderImported: false,
12
+ errors: [],
13
+ };
14
+ if (!existsSync(source)) {
15
+ result.skipped = true;
16
+ return result;
17
+ }
18
+ mkdirSync(dest, { recursive: true });
19
+ // ---- Plans ----
20
+ const plansSrc = join(source, "plans");
21
+ if (existsSync(plansSrc)) {
22
+ const plansDest = join(dest, "plans");
23
+ mkdirSync(plansDest, { recursive: true });
24
+ for (const entry of readdirSafe(plansSrc)) {
25
+ if (!entry.endsWith(".md"))
26
+ continue;
27
+ const destFile = join(plansDest, entry);
28
+ if (existsSync(destFile))
29
+ continue; // idempotent
30
+ try {
31
+ copyFileSync(join(plansSrc, entry), destFile);
32
+ result.plansCopied++;
33
+ }
34
+ catch (err) {
35
+ result.errors.push(`plans/${entry}: ${err instanceof Error ? err.message : String(err)}`);
36
+ }
37
+ }
38
+ }
39
+ // ---- Handoff ----
40
+ const handoffSrc = join(source, "handoff.md");
41
+ if (existsSync(handoffSrc)) {
42
+ const handoffsDest = join(dest, "handoffs");
43
+ mkdirSync(handoffsDest, { recursive: true });
44
+ const stamp = formatDateStamp(statSync(handoffSrc).mtimeMs);
45
+ const slug = slugify(extractHandoffTitle(handoffSrc) ?? "sisyphus-handoff");
46
+ const targetName = `${stamp}-${slug}.md`;
47
+ const target = join(handoffsDest, targetName);
48
+ if (!existsSync(target)) {
49
+ try {
50
+ copyFileSync(handoffSrc, target);
51
+ result.handoffsCopied++;
52
+ }
53
+ catch (err) {
54
+ result.errors.push(`handoff.md: ${err instanceof Error ? err.message : String(err)}`);
55
+ }
56
+ }
57
+ }
58
+ // ---- Evidence ----
59
+ const evidenceSrc = join(source, "evidence");
60
+ if (existsSync(evidenceSrc)) {
61
+ const evidenceDest = join(dest, "evidence");
62
+ mkdirSync(evidenceDest, { recursive: true });
63
+ for (const entry of readdirSafe(evidenceSrc)) {
64
+ const src = join(evidenceSrc, entry);
65
+ const dst = join(evidenceDest, entry);
66
+ if (existsSync(dst))
67
+ continue;
68
+ try {
69
+ const s = statSync(src);
70
+ if (s.isDirectory()) {
71
+ copyDirRecursive(src, dst);
72
+ result.evidenceCopied++;
73
+ }
74
+ else {
75
+ copyFileSync(src, dst);
76
+ result.evidenceCopied++;
77
+ }
78
+ }
79
+ catch (err) {
80
+ result.errors.push(`evidence/${entry}: ${err instanceof Error ? err.message : String(err)}`);
81
+ }
82
+ }
83
+ }
84
+ // ---- Legacy (notepads, drafts, run-continuation) ----
85
+ const legacyNames = ["notepads", "drafts", "run-continuation"];
86
+ for (const name of legacyNames) {
87
+ const src = join(source, name);
88
+ if (!existsSync(src))
89
+ continue;
90
+ const dst = join(dest, "legacy", name);
91
+ if (existsSync(dst))
92
+ continue;
93
+ try {
94
+ copyDirRecursive(src, dst);
95
+ result.legacyCopied++;
96
+ }
97
+ catch (err) {
98
+ result.errors.push(`legacy/${name}: ${err instanceof Error ? err.message : String(err)}`);
99
+ }
100
+ }
101
+ // ---- Boulder ----
102
+ const boulderSrc = join(source, "boulder.json");
103
+ if (existsSync(boulderSrc)) {
104
+ const plansDest = join(dest, "plans");
105
+ mkdirSync(plansDest, { recursive: true });
106
+ const target = join(plansDest, "legacy-boulder.md");
107
+ if (!existsSync(target)) {
108
+ try {
109
+ const body = boulderToMarkdown(boulderSrc);
110
+ writeFileSync(target, body, "utf-8");
111
+ result.boulderImported = true;
112
+ }
113
+ catch (err) {
114
+ result.errors.push(`boulder.json: ${err instanceof Error ? err.message : String(err)}`);
115
+ }
116
+ }
117
+ }
118
+ return result;
119
+ }
120
+ // ============================================================================
121
+ // Helpers
122
+ // ============================================================================
123
+ function readdirSafe(dir) {
124
+ try {
125
+ return readdirSync(dir);
126
+ }
127
+ catch {
128
+ return [];
129
+ }
130
+ }
131
+ /**
132
+ * Recursively copy every file in src into dst. Creates parent
133
+ * directories as needed. Skips entries that already exist at dst
134
+ * (so idempotent re-runs don't clobber user edits).
135
+ */
136
+ function copyDirRecursive(src, dst) {
137
+ mkdirSync(dst, { recursive: true });
138
+ for (const entry of readdirSafe(src)) {
139
+ const sp = join(src, entry);
140
+ const dp = join(dst, entry);
141
+ const s = statSync(sp);
142
+ if (s.isDirectory()) {
143
+ copyDirRecursive(sp, dp);
144
+ }
145
+ else if (s.isFile()) {
146
+ if (!existsSync(dp)) {
147
+ copyFileSync(sp, dp);
148
+ }
149
+ }
150
+ }
151
+ }
152
+ function formatDateStamp(ms) {
153
+ const d = new Date(ms);
154
+ const y = d.getFullYear();
155
+ const m = String(d.getMonth() + 1).padStart(2, "0");
156
+ const day = String(d.getDate()).padStart(2, "0");
157
+ return `${y}-${m}-${day}`;
158
+ }
159
+ function slugify(s) {
160
+ return s
161
+ .toLowerCase()
162
+ .replace(/[^a-z0-9]+/g, "-")
163
+ .replace(/^-+|-+$/g, "")
164
+ .slice(0, 50) || "handoff";
165
+ }
166
+ /**
167
+ * Best-effort title extraction from a handoff markdown file. Looks
168
+ * for the first `# Title` heading; falls back to the filename without
169
+ * extension.
170
+ */
171
+ function extractHandoffTitle(path) {
172
+ try {
173
+ const body = readFileSync(path, "utf-8");
174
+ const m = body.match(/^#\s+(.+?)\s*$/m);
175
+ if (m) {
176
+ const title = m[1].trim();
177
+ // Strip common suffix noise like "— sisyphus handoff".
178
+ return title.replace(/^sisyphus\s+handoff\b.*$/i, "sisyphus-handoff");
179
+ }
180
+ return basename(path, extname(path));
181
+ }
182
+ catch {
183
+ return null;
184
+ }
185
+ }
186
+ /**
187
+ * Render a legacy boulder.json as a markdown plan note so the data
188
+ * isn't lost in the migration. The resulting file lives at
189
+ * `.elder-gods/plans/legacy-boulder.md` and describes what the last
190
+ * active task was — useful for users resuming where they left off.
191
+ */
192
+ function boulderToMarkdown(path) {
193
+ let data = {};
194
+ try {
195
+ data = JSON.parse(readFileSync(path, "utf-8"));
196
+ }
197
+ catch {
198
+ return "# Legacy boulder\n\n(failed to parse source boulder.json)\n";
199
+ }
200
+ const lines = [];
201
+ lines.push("# Legacy Boulder State (imported from .sisyphus/boulder.json)");
202
+ lines.push("");
203
+ lines.push("This file captures the final state of the oh-my-opencode sisyphus " +
204
+ "boulder at migration time. Use it to remember what you were " +
205
+ "working on before the switch.");
206
+ lines.push("");
207
+ if (data.plan_name)
208
+ lines.push(`**Plan:** ${String(data.plan_name)}`);
209
+ if (data.active_plan)
210
+ lines.push(`**Active plan path:** \`${String(data.active_plan)}\``);
211
+ if (data.started_at)
212
+ lines.push(`**Started:** ${String(data.started_at)}`);
213
+ if (Array.isArray(data.session_ids)) {
214
+ lines.push(`**Session IDs:**`);
215
+ for (const sid of data.session_ids) {
216
+ lines.push(`- ${String(sid)}`);
217
+ }
218
+ }
219
+ lines.push("");
220
+ lines.push("## Raw JSON");
221
+ lines.push("```json");
222
+ lines.push(JSON.stringify(data, null, 2));
223
+ lines.push("```");
224
+ return lines.join("\n") + "\n";
225
+ }
226
+ //# sourceMappingURL=sisyphus-migrate.js.map