@monoes/monomindcli 2.16.6 → 2.16.8

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 (193) hide show
  1. package/.claude/agents/github/monoswarm-multi-repo.md +2 -2
  2. package/.claude/agents/github/sync-coordinator.md +1 -1
  3. package/.claude/commands/agents/agent-capabilities.md +2 -5
  4. package/.claude/commands/coordination/task-orchestrate.md +0 -1
  5. package/.claude/commands/hooks/post-edit.md +1 -1
  6. package/.claude/commands/hooks/post-task.md +2 -3
  7. package/.claude/commands/hooks/pre-edit.md +0 -2
  8. package/.claude/commands/hooks/session-end.md +4 -4
  9. package/.claude/commands/monoswarm/consensus.md +1 -1
  10. package/.claude/commands/monoswarm/memory.md +1 -1
  11. package/.claude/commands/monoswarm/monoswarm.md +1 -1
  12. package/.claude/commands/monoswarm/spawn.md +1 -1
  13. package/.claude/commands/optimization/auto-topology.md +6 -9
  14. package/.claude/commands/optimization/performance-optimize.md +23 -39
  15. package/.claude/helpers/build-skill-registry.cjs +4 -3
  16. package/.claude/helpers/pick-rank.cjs +118 -9
  17. package/dist/src/catalog/projection.d.ts.map +1 -1
  18. package/dist/src/catalog/projection.js +2 -1
  19. package/dist/src/catalog/projection.js.map +1 -1
  20. package/dist/src/commands/agent-exec.d.ts.map +1 -1
  21. package/dist/src/commands/agent-exec.js +10 -1
  22. package/dist/src/commands/agent-exec.js.map +1 -1
  23. package/dist/src/commands/cleanup-plan.js +1 -1
  24. package/dist/src/commands/cleanup-plan.js.map +1 -1
  25. package/dist/src/commands/doctor.js +1 -1
  26. package/dist/src/commands/doctor.js.map +1 -1
  27. package/dist/src/commands/hooks-core-commands.d.ts.map +1 -1
  28. package/dist/src/commands/hooks-core-commands.js +10 -42
  29. package/dist/src/commands/hooks-core-commands.js.map +1 -1
  30. package/dist/src/commands/hooks-extended-commands.d.ts.map +1 -1
  31. package/dist/src/commands/hooks-extended-commands.js +9 -5
  32. package/dist/src/commands/hooks-extended-commands.js.map +1 -1
  33. package/dist/src/commands/hooks-routing-commands.d.ts.map +1 -1
  34. package/dist/src/commands/hooks-routing-commands.js +13 -24
  35. package/dist/src/commands/hooks-routing-commands.js.map +1 -1
  36. package/dist/src/commands/hooks-workers.d.ts.map +1 -1
  37. package/dist/src/commands/hooks-workers.js +8 -8
  38. package/dist/src/commands/hooks-workers.js.map +1 -1
  39. package/dist/src/commands/hooks.d.ts.map +1 -1
  40. package/dist/src/commands/hooks.js +9 -16
  41. package/dist/src/commands/hooks.js.map +1 -1
  42. package/dist/src/commands/monograph.d.ts.map +1 -1
  43. package/dist/src/commands/monograph.js +24 -2
  44. package/dist/src/commands/monograph.js.map +1 -1
  45. package/dist/src/commands/org.d.ts.map +1 -1
  46. package/dist/src/commands/org.js +29 -1
  47. package/dist/src/commands/org.js.map +1 -1
  48. package/dist/src/commands/platforms.js +2 -1
  49. package/dist/src/commands/platforms.js.map +1 -1
  50. package/dist/src/init/asset-maps.d.ts +46 -0
  51. package/dist/src/init/asset-maps.d.ts.map +1 -0
  52. package/dist/src/init/asset-maps.js +177 -0
  53. package/dist/src/init/asset-maps.js.map +1 -0
  54. package/dist/src/init/copy-assets.d.ts.map +1 -1
  55. package/dist/src/init/copy-assets.js +4 -1
  56. package/dist/src/init/copy-assets.js.map +1 -1
  57. package/dist/src/init/executor.d.ts.map +1 -1
  58. package/dist/src/init/executor.js +5 -3
  59. package/dist/src/init/executor.js.map +1 -1
  60. package/dist/src/init/file-guard.d.ts +6 -0
  61. package/dist/src/init/file-guard.d.ts.map +1 -1
  62. package/dist/src/init/file-guard.js +22 -8
  63. package/dist/src/init/file-guard.js.map +1 -1
  64. package/dist/src/init/fs-helpers.d.ts +63 -0
  65. package/dist/src/init/fs-helpers.d.ts.map +1 -0
  66. package/dist/src/init/fs-helpers.js +198 -0
  67. package/dist/src/init/fs-helpers.js.map +1 -0
  68. package/dist/src/init/init-manifest.d.ts +106 -0
  69. package/dist/src/init/init-manifest.d.ts.map +1 -0
  70. package/dist/src/init/init-manifest.js +222 -0
  71. package/dist/src/init/init-manifest.js.map +1 -0
  72. package/dist/src/init/shared.d.ts +3 -201
  73. package/dist/src/init/shared.d.ts.map +1 -1
  74. package/dist/src/init/shared.js +7 -573
  75. package/dist/src/init/shared.js.map +1 -1
  76. package/dist/src/init/upgrade.d.ts.map +1 -1
  77. package/dist/src/init/upgrade.js +3 -1
  78. package/dist/src/init/upgrade.js.map +1 -1
  79. package/dist/src/init/write-antigravity.d.ts.map +1 -1
  80. package/dist/src/init/write-antigravity.js +2 -1
  81. package/dist/src/init/write-antigravity.js.map +1 -1
  82. package/dist/src/init/write-capabilities.js +2 -1
  83. package/dist/src/init/write-capabilities.js.map +1 -1
  84. package/dist/src/init/write-claude.d.ts +3 -5
  85. package/dist/src/init/write-claude.d.ts.map +1 -1
  86. package/dist/src/init/write-claude.js +6 -210
  87. package/dist/src/init/write-claude.js.map +1 -1
  88. package/dist/src/init/write-codex.js +1 -1
  89. package/dist/src/init/write-codex.js.map +1 -1
  90. package/dist/src/init/write-kimicode.d.ts.map +1 -1
  91. package/dist/src/init/write-kimicode.js +6 -2
  92. package/dist/src/init/write-kimicode.js.map +1 -1
  93. package/dist/src/init/write-opencode.d.ts.map +1 -1
  94. package/dist/src/init/write-opencode.js +5 -4
  95. package/dist/src/init/write-opencode.js.map +1 -1
  96. package/dist/src/init/write-runtime-config.d.ts.map +1 -1
  97. package/dist/src/init/write-runtime-config.js +2 -1
  98. package/dist/src/init/write-runtime-config.js.map +1 -1
  99. package/dist/src/init/write-settings.d.ts +9 -0
  100. package/dist/src/init/write-settings.d.ts.map +1 -0
  101. package/dist/src/init/write-settings.js +217 -0
  102. package/dist/src/init/write-settings.js.map +1 -0
  103. package/dist/src/mcp-tools/hooks-embedding.d.ts +2 -1
  104. package/dist/src/mcp-tools/hooks-embedding.d.ts.map +1 -1
  105. package/dist/src/mcp-tools/hooks-embedding.js +3 -0
  106. package/dist/src/mcp-tools/hooks-embedding.js.map +1 -1
  107. package/dist/src/mcp-tools/hooks-intelligence.d.ts.map +1 -1
  108. package/dist/src/mcp-tools/hooks-intelligence.js +11 -8
  109. package/dist/src/mcp-tools/hooks-intelligence.js.map +1 -1
  110. package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
  111. package/dist/src/mcp-tools/hooks-routing.js +31 -38
  112. package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
  113. package/dist/src/mcp-tools/platforms-tools.js +1 -1
  114. package/dist/src/mcp-tools/platforms-tools.js.map +1 -1
  115. package/dist/src/memory/memory-bridge.d.ts +13 -0
  116. package/dist/src/memory/memory-bridge.d.ts.map +1 -1
  117. package/dist/src/memory/memory-bridge.js +68 -20
  118. package/dist/src/memory/memory-bridge.js.map +1 -1
  119. package/dist/src/monovector/command-outcomes.d.ts +2 -1
  120. package/dist/src/monovector/command-outcomes.d.ts.map +1 -1
  121. package/dist/src/monovector/command-outcomes.js +2 -2
  122. package/dist/src/monovector/command-outcomes.js.map +1 -1
  123. package/dist/src/monovector/model-outcomes.d.ts +4 -2
  124. package/dist/src/monovector/model-outcomes.d.ts.map +1 -1
  125. package/dist/src/monovector/model-outcomes.js +11 -3
  126. package/dist/src/monovector/model-outcomes.js.map +1 -1
  127. package/dist/src/orgrt/approvals.d.ts +25 -0
  128. package/dist/src/orgrt/approvals.d.ts.map +1 -1
  129. package/dist/src/orgrt/approvals.js +51 -2
  130. package/dist/src/orgrt/approvals.js.map +1 -1
  131. package/dist/src/orgrt/budget-closure.d.ts +39 -0
  132. package/dist/src/orgrt/budget-closure.d.ts.map +1 -0
  133. package/dist/src/orgrt/budget-closure.js +380 -0
  134. package/dist/src/orgrt/budget-closure.js.map +1 -0
  135. package/dist/src/orgrt/daemon.d.ts +21 -2
  136. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  137. package/dist/src/orgrt/daemon.js +39 -45
  138. package/dist/src/orgrt/daemon.js.map +1 -1
  139. package/dist/src/orgrt/decisions.d.ts +8 -0
  140. package/dist/src/orgrt/decisions.d.ts.map +1 -1
  141. package/dist/src/orgrt/decisions.js +7 -1
  142. package/dist/src/orgrt/decisions.js.map +1 -1
  143. package/dist/src/orgrt/policy.d.ts +6 -0
  144. package/dist/src/orgrt/policy.d.ts.map +1 -1
  145. package/dist/src/orgrt/policy.js +5 -0
  146. package/dist/src/orgrt/policy.js.map +1 -1
  147. package/dist/src/orgrt/runner-registry.d.ts +11 -2
  148. package/dist/src/orgrt/runner-registry.d.ts.map +1 -1
  149. package/dist/src/orgrt/runner-registry.js +11 -34
  150. package/dist/src/orgrt/runner-registry.js.map +1 -1
  151. package/dist/src/orgrt/task-dag.d.ts +13 -0
  152. package/dist/src/orgrt/task-dag.d.ts.map +1 -1
  153. package/dist/src/orgrt/task-dag.js +29 -0
  154. package/dist/src/orgrt/task-dag.js.map +1 -1
  155. package/dist/src/orgrt/version-probe.d.ts +43 -0
  156. package/dist/src/orgrt/version-probe.d.ts.map +1 -0
  157. package/dist/src/orgrt/version-probe.js +136 -0
  158. package/dist/src/orgrt/version-probe.js.map +1 -0
  159. package/dist/src/platform-adapters/locations.d.ts +12 -0
  160. package/dist/src/platform-adapters/locations.d.ts.map +1 -0
  161. package/dist/src/platform-adapters/locations.js +57 -0
  162. package/dist/src/platform-adapters/locations.js.map +1 -0
  163. package/dist/src/platform-adapters/merge.d.ts +2 -0
  164. package/dist/src/platform-adapters/merge.d.ts.map +1 -1
  165. package/dist/src/platform-adapters/merge.js +7 -0
  166. package/dist/src/platform-adapters/merge.js.map +1 -1
  167. package/dist/src/platform-adapters/migration.js +1 -1
  168. package/dist/src/platform-adapters/migration.js.map +1 -1
  169. package/dist/src/platform-adapters/mutation.js +1 -1
  170. package/dist/src/platform-adapters/mutation.js.map +1 -1
  171. package/dist/src/platform-adapters/operations.d.ts +3 -16
  172. package/dist/src/platform-adapters/operations.d.ts.map +1 -1
  173. package/dist/src/platform-adapters/operations.js +25 -168
  174. package/dist/src/platform-adapters/operations.js.map +1 -1
  175. package/dist/src/platform-adapters/owned-files.js +1 -1
  176. package/dist/src/platform-adapters/owned-files.js.map +1 -1
  177. package/dist/src/platform-adapters/platform-doctor.d.ts +9 -0
  178. package/dist/src/platform-adapters/platform-doctor.d.ts.map +1 -0
  179. package/dist/src/platform-adapters/platform-doctor.js +117 -0
  180. package/dist/src/platform-adapters/platform-doctor.js.map +1 -0
  181. package/dist/src/platform-adapters/shared-surface.d.ts.map +1 -1
  182. package/dist/src/platform-adapters/shared-surface.js +2 -1
  183. package/dist/src/platform-adapters/shared-surface.js.map +1 -1
  184. package/dist/src/platform-adapters/types.d.ts +14 -1
  185. package/dist/src/platform-adapters/types.d.ts.map +1 -1
  186. package/dist/src/protocol-capabilities.d.ts +4 -1
  187. package/dist/src/protocol-capabilities.d.ts.map +1 -1
  188. package/dist/src/protocol-capabilities.js +4 -0
  189. package/dist/src/protocol-capabilities.js.map +1 -1
  190. package/dist/tsconfig.tsbuildinfo +1 -1
  191. package/org-skills/api-designer/SKILL.md +1 -1
  192. package/org-skills/code-documenter/SKILL.md +1 -1
  193. package/package.json +3 -3
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Filesystem helpers shared by the init write-* modules: atomic and
3
+ * timestamp-stable writes, the conversion-target guard, and tree walkers.
4
+ */
5
+ import type { InitResult } from './types.js';
6
+ /**
7
+ * Atomic write helper — writes to a sibling .tmp file then renames into place.
8
+ * SIGINT or crash during a partial write would otherwise corrupt user-critical
9
+ * files (.claude/settings.json, .mcp.json, helper scripts that Claude Code
10
+ * executes on every hook). Without atomicity a half-written settings.json or
11
+ * a zero-byte hook-handler.cjs disables Claude Code's protections silently.
12
+ */
13
+ export declare function atomicWriteFile(target: string, content: string | Buffer, encoding?: BufferEncoding): void;
14
+ /**
15
+ * Write a generated file that embeds a `Generated: <ISO timestamp>` line,
16
+ * skipping the write entirely when that stamp is the only thing that would
17
+ * change. Otherwise every `init --force` rewrote these files with a fresh
18
+ * timestamp and left the repository dirty by exactly two files, for
19
+ * information nobody can act on. Skipping the write (rather than reusing the
20
+ * old stamp) keeps the mtime stable too, and the stamp keeps its meaning:
21
+ * when this content was generated.
22
+ */
23
+ export declare function writeGeneratedFile(target: string, content: string): void;
24
+ /**
25
+ * Guard for the write-opencode.ts / write-kimicode.ts converters, which read
26
+ * `.claude/{agents,commands,skills}` and write the converted result into what
27
+ * is expected to be a separate platform directory (`.opencode/...`,
28
+ * `.kimi-code/...`). If that destination has been symlinked back into
29
+ * `.claude/` (observed live: a committed `.opencode/command -> ../.claude/commands`
30
+ * symlink), the atomic write-then-rename in `atomicWriteFile` resolves through
31
+ * the symlink and lands the converted, flattened, field-injected output
32
+ * straight back in the Claude source tree it was just read from — silently
33
+ * corrupting hand-authored agent/skill/command files and resurrecting
34
+ * "deleted" flattened command duplicates on every `--force` run.
35
+ *
36
+ * Checked once per destination directory (not per file) before its copy loop.
37
+ * Returns false and records one `result.errors` entry when `destDir` resolves
38
+ * inside `claudeDir`; the caller should skip the whole loop rather than write
39
+ * file-by-file into the wrong place. A `destDir` that is itself a symlink to
40
+ * `claudeDir/<mirrorOf>` is a deliberate mirror (this repo links
41
+ * `.opencode/agent -> ../.claude/agents`), so it is skipped without the error.
42
+ */
43
+ export declare function isSafeConversionTarget(destDir: string, claudeDir: string, result: InitResult, label: string, mirrorOf?: string): boolean;
44
+ /** Relative file paths under `dir` (files only). Used by every o-38 mirror
45
+ * sweep (copySkills's `.gemini`/`.agents`, writeOpencodeFiles's
46
+ * `.opencode/skills`) to tell "content the source regenerated" from "a file
47
+ * someone added directly inside the mirror" (o-38 §2·0b). */
48
+ export declare function listFilesRecursive(dir: string): Set<string>;
49
+ /**
50
+ * Copy directory recursively
51
+ */
52
+ export declare function copyDirRecursive(src: string, dest: string): void;
53
+ /**
54
+ * Count files with extension in directory
55
+ */
56
+ export declare function countFiles(dir: string, ext: string): number;
57
+ /** Recursively collect .md files under dir, returned relative to dir. */
58
+ export declare function walkMdFiles(dir: string): string[];
59
+ /** Skip READMEs and other non-definition markdown. */
60
+ export declare function isLikelyUserFile(rel: string): boolean;
61
+ /** Pull the `name:` scalar from a frontmatter block (best-effort). */
62
+ export declare function extractFmName(md: string): string | null;
63
+ //# sourceMappingURL=fs-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-helpers.d.ts","sourceRoot":"","sources":["../../../src/init/fs-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,IAAI,CAUN;AAaD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAQxE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CA4BT;AAED;;;8DAG8D;AAC9D,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAY3D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAmBhE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAgB3D;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBjD;AAED,sDAAsD;AACtD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAIrD;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMvD"}
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Filesystem helpers shared by the init write-* modules: atomic and
3
+ * timestamp-stable writes, the conversion-target guard, and tree walkers.
4
+ */
5
+ import * as fs from 'node:fs';
6
+ import * as path from 'node:path';
7
+ /**
8
+ * Atomic write helper — writes to a sibling .tmp file then renames into place.
9
+ * SIGINT or crash during a partial write would otherwise corrupt user-critical
10
+ * files (.claude/settings.json, .mcp.json, helper scripts that Claude Code
11
+ * executes on every hook). Without atomicity a half-written settings.json or
12
+ * a zero-byte hook-handler.cjs disables Claude Code's protections silently.
13
+ */
14
+ export function atomicWriteFile(target, content, encoding) {
15
+ const tmp = `${target}.${process.pid}.tmp`;
16
+ if (encoding && typeof content === 'string') {
17
+ fs.writeFileSync(tmp, content, encoding);
18
+ }
19
+ else if (typeof content === 'string') {
20
+ fs.writeFileSync(tmp, content, 'utf-8');
21
+ }
22
+ else {
23
+ fs.writeFileSync(tmp, content);
24
+ }
25
+ fs.renameSync(tmp, target);
26
+ }
27
+ /**
28
+ * The `Generated: <ISO timestamp>` stamp that .monomind/config.yaml and
29
+ * .monomind/CAPABILITIES.md carry, in whatever comment syntax their format
30
+ * uses (`# Generated: …`, `> Generated: …`).
31
+ */
32
+ const GENERATED_TIMESTAMP = /(Generated:[^\S\r\n]*)\d{4}-\d{2}-\d{2}T[\d:.]+Z/g;
33
+ function withoutGeneratedTimestamp(content) {
34
+ return content.replace(GENERATED_TIMESTAMP, '$1<generated>');
35
+ }
36
+ /**
37
+ * Write a generated file that embeds a `Generated: <ISO timestamp>` line,
38
+ * skipping the write entirely when that stamp is the only thing that would
39
+ * change. Otherwise every `init --force` rewrote these files with a fresh
40
+ * timestamp and left the repository dirty by exactly two files, for
41
+ * information nobody can act on. Skipping the write (rather than reusing the
42
+ * old stamp) keeps the mtime stable too, and the stamp keeps its meaning:
43
+ * when this content was generated.
44
+ */
45
+ export function writeGeneratedFile(target, content) {
46
+ try {
47
+ const existing = fs.readFileSync(target, 'utf-8');
48
+ if (withoutGeneratedTimestamp(existing) === withoutGeneratedTimestamp(content))
49
+ return;
50
+ }
51
+ catch {
52
+ // No readable file on disk — fall through and write it.
53
+ }
54
+ atomicWriteFile(target, content);
55
+ }
56
+ /**
57
+ * Guard for the write-opencode.ts / write-kimicode.ts converters, which read
58
+ * `.claude/{agents,commands,skills}` and write the converted result into what
59
+ * is expected to be a separate platform directory (`.opencode/...`,
60
+ * `.kimi-code/...`). If that destination has been symlinked back into
61
+ * `.claude/` (observed live: a committed `.opencode/command -> ../.claude/commands`
62
+ * symlink), the atomic write-then-rename in `atomicWriteFile` resolves through
63
+ * the symlink and lands the converted, flattened, field-injected output
64
+ * straight back in the Claude source tree it was just read from — silently
65
+ * corrupting hand-authored agent/skill/command files and resurrecting
66
+ * "deleted" flattened command duplicates on every `--force` run.
67
+ *
68
+ * Checked once per destination directory (not per file) before its copy loop.
69
+ * Returns false and records one `result.errors` entry when `destDir` resolves
70
+ * inside `claudeDir`; the caller should skip the whole loop rather than write
71
+ * file-by-file into the wrong place. A `destDir` that is itself a symlink to
72
+ * `claudeDir/<mirrorOf>` is a deliberate mirror (this repo links
73
+ * `.opencode/agent -> ../.claude/agents`), so it is skipped without the error.
74
+ */
75
+ export function isSafeConversionTarget(destDir, claudeDir, result, label, mirrorOf) {
76
+ let realDest;
77
+ try {
78
+ realDest = fs.realpathSync(destDir);
79
+ }
80
+ catch {
81
+ return true; // doesn't exist yet — mkdirSync will create a real directory
82
+ }
83
+ let realClaude;
84
+ try {
85
+ realClaude = fs.realpathSync(claudeDir);
86
+ }
87
+ catch {
88
+ return true; // no .claude/ to collide with
89
+ }
90
+ if (realDest === realClaude || realDest.startsWith(`${realClaude}${path.sep}`)) {
91
+ if (mirrorOf !== undefined &&
92
+ fs.lstatSync(destDir).isSymbolicLink() &&
93
+ realDest === path.join(realClaude, mirrorOf)) {
94
+ result.skipped.push(`${label} (symlink to .claude/${mirrorOf})`);
95
+ return false;
96
+ }
97
+ result.errors.push(`${label} resolves inside .claude/ (likely a symlink) — skipping to avoid writing converted files back into the Claude source tree. Remove or repoint the symlink and re-run.`);
98
+ return false;
99
+ }
100
+ return true;
101
+ }
102
+ /** Relative file paths under `dir` (files only). Used by every o-38 mirror
103
+ * sweep (copySkills's `.gemini`/`.agents`, writeOpencodeFiles's
104
+ * `.opencode/skills`) to tell "content the source regenerated" from "a file
105
+ * someone added directly inside the mirror" (o-38 §2·0b). */
106
+ export function listFilesRecursive(dir) {
107
+ const out = new Set();
108
+ if (!fs.existsSync(dir))
109
+ return out;
110
+ const walk = (d) => {
111
+ for (const entry of fs.readdirSync(d, { withFileTypes: true })) {
112
+ const full = path.join(d, entry.name);
113
+ if (entry.isDirectory())
114
+ walk(full);
115
+ else
116
+ out.add(path.relative(dir, full));
117
+ }
118
+ };
119
+ walk(dir);
120
+ return out;
121
+ }
122
+ /**
123
+ * Copy directory recursively
124
+ */
125
+ export function copyDirRecursive(src, dest) {
126
+ fs.mkdirSync(dest, { recursive: true });
127
+ const entries = fs.readdirSync(src, { withFileTypes: true });
128
+ for (const entry of entries) {
129
+ // Skip exFAT/macOS AppleDouble junk files (e.g. "._foo.js") so they don't
130
+ // get perpetuated into every newly-initialized project.
131
+ if (entry.name.startsWith('._'))
132
+ continue;
133
+ const srcPath = path.join(src, entry.name);
134
+ const destPath = path.join(dest, entry.name);
135
+ if (entry.isDirectory()) {
136
+ copyDirRecursive(srcPath, destPath);
137
+ }
138
+ else {
139
+ fs.copyFileSync(srcPath, destPath);
140
+ }
141
+ }
142
+ }
143
+ /**
144
+ * Count files with extension in directory
145
+ */
146
+ export function countFiles(dir, ext) {
147
+ let count = 0;
148
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
149
+ for (const entry of entries) {
150
+ const fullPath = path.join(dir, entry.name);
151
+ if (entry.isDirectory()) {
152
+ count += countFiles(fullPath, ext);
153
+ }
154
+ else if (entry.name.endsWith(ext)) {
155
+ count++;
156
+ }
157
+ }
158
+ return count;
159
+ }
160
+ /** Recursively collect .md files under dir, returned relative to dir. */
161
+ export function walkMdFiles(dir) {
162
+ const out = [];
163
+ const visit = (d, prefix) => {
164
+ let entries;
165
+ try {
166
+ entries = fs.readdirSync(d, { withFileTypes: true });
167
+ }
168
+ catch {
169
+ return;
170
+ }
171
+ for (const e of entries) {
172
+ const rel = prefix ? `${prefix}${path.sep}${e.name}` : e.name;
173
+ if (e.isDirectory())
174
+ visit(path.join(d, e.name), rel);
175
+ else if (e.isFile() && /\.md$/i.test(e.name))
176
+ out.push(rel);
177
+ }
178
+ };
179
+ visit(dir, '');
180
+ return out;
181
+ }
182
+ /** Skip READMEs and other non-definition markdown. */
183
+ export function isLikelyUserFile(rel) {
184
+ const base = path.basename(rel).toLowerCase();
185
+ if (base === 'readme.md' || base === 'readme')
186
+ return false;
187
+ return true;
188
+ }
189
+ /** Pull the `name:` scalar from a frontmatter block (best-effort). */
190
+ export function extractFmName(md) {
191
+ const m = md.match(/^---\r?\n[\s\S]*?\r?\n---/);
192
+ if (!m)
193
+ return null;
194
+ const fm = m[0];
195
+ const nm = fm.match(/^name\s*:\s*(.+?)\s*$/m);
196
+ return nm ? nm[1].replace(/^["']|["']$/g, '') : null;
197
+ }
198
+ //# sourceMappingURL=fs-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-helpers.js","sourceRoot":"","sources":["../../../src/init/fs-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,OAAwB,EACxB,QAAyB;IAEzB,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;IAC3C,IAAI,QAAQ,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;SAAM,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACvC,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IACD,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,mDAAmD,CAAC;AAEhF,SAAS,yBAAyB,CAAC,OAAe;IAChD,OAAO,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,OAAe;IAChE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClD,IAAI,yBAAyB,CAAC,QAAQ,CAAC,KAAK,yBAAyB,CAAC,OAAO,CAAC;YAAE,OAAO;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,wDAAwD;IAC1D,CAAC;IACD,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAe,EACf,SAAiB,EACjB,MAAkB,EAClB,KAAa,EACb,QAAiB;IAEjB,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,6DAA6D;IAC5E,CAAC;IACD,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,8BAA8B;IAC7C,CAAC;IACD,IAAI,QAAQ,KAAK,UAAU,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QAC/E,IACE,QAAQ,KAAK,SAAS;YACtB,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE;YACtC,QAAQ,KAAK,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,EAC5C,CAAC;YACD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,wBAAwB,QAAQ,GAAG,CAAC,CAAC;YACjE,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,IAAI,CAChB,GAAG,KAAK,sKAAsK,CAC/K,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;8DAG8D;AAC9D,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IACpC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE;QACzB,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,KAAK,CAAC,WAAW,EAAE;gBAAE,IAAI,CAAC,IAAI,CAAC,CAAC;;gBAC/B,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,IAAY;IACxD,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAExC,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,0EAA0E;QAC1E,wDAAwD;QACxD,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAE1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE7C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACtC,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,GAAW;IACjD,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,KAAK,IAAI,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACrC,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,MAAc,EAAE,EAAE;QAC1C,IAAI,OAAoB,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC9D,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;iBACjD,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACf,OAAO,GAAG,CAAC;AACb,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9C,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAChD,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChB,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC9C,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC"}
@@ -0,0 +1,106 @@
1
+ import type { InitResult } from './types.js';
2
+ /**
3
+ * Provenance manifest for generated .claude content.
4
+ *
5
+ * init used to "clean stale" entries by deleting every name under
6
+ * .claude/{skills,commands,agents} that was absent from the current version's
7
+ * SKILLS_MAP/COMMANDS_MAP/AGENTS_MAP. Every user-authored command and skill is
8
+ * absent from those maps, so that pass deleted user content on the very first
9
+ * run — unrecoverable data loss.
10
+ *
11
+ * The manifest records exactly which entries *this tool* wrote, so the stale
12
+ * sweep can be restricted to those. Anything init did not write is never
13
+ * removed. Projects initialised by an older version have no manifest, so their
14
+ * first run under the fix deletes nothing and seeds the manifest instead;
15
+ * stale generated content may survive one extra run, which is the correct
16
+ * trade (preserving stale generated content is recoverable, deleting user
17
+ * content is not).
18
+ */
19
+ export declare const INIT_MANIFEST_REL: string;
20
+ /**
21
+ * One retired entry's provenance (o-38): a name the manifest recorded that
22
+ * this version no longer ships, moved to `movedTo` instead of deleted.
23
+ * Appended-only — a later run's `recordGenerated` never drops this array, so
24
+ * the run after next can still tell a user what was retired and where it went.
25
+ */
26
+ export interface RetiredEntry {
27
+ /** The manifest section for a `.claude`/`.kimi-code` entry (an
28
+ * `InitManifestSection` value), or a descriptive label for a mirror
29
+ * retirement (e.g. `gemini-skills`) — mirrors have no manifest section
30
+ * of their own, so this is an audit-trail label, not a lookup key. */
31
+ section: string;
32
+ name: string;
33
+ /** Path (relative to targetDir) the entry was moved to. */
34
+ movedTo: string;
35
+ /** ISO timestamp of the retirement. */
36
+ at: string;
37
+ }
38
+ export interface InitManifest {
39
+ version: number;
40
+ /** Entry names directly under .claude/skills that init generated. */
41
+ skills: string[];
42
+ /** Entry names directly under .claude/commands that init generated. */
43
+ commands: string[];
44
+ /** Entry names (category dirs) directly under .claude/agents that init generated. */
45
+ agents: string[];
46
+ /** Directory names directly under .kimi-code/skills that init generated. */
47
+ kimiSkills: string[];
48
+ /** File names directly under .kimi-code/plugin/commands that init generated. */
49
+ kimiPluginCommands: string[];
50
+ /** Directory names directly under .opencode/skills that init generated.
51
+ * Absent in manifests written before this field existed; normalised to
52
+ * an empty list on read, which the sweep treats as "delete nothing". */
53
+ opencodeSkills: string[];
54
+ /** Every entry ever retired (o-38) — see `RetiredEntry`. Absent on a
55
+ * manifest written before this field existed; treated as empty. */
56
+ retired?: RetiredEntry[];
57
+ /** sha256 of each shipped file as init last left it, keyed by its
58
+ * project-relative path — how a later run tells a user edit from an
59
+ * untouched install (see file-guard.ts). */
60
+ files?: Record<string, string>;
61
+ /** sha256 of each managed block's body as init last wrote it, keyed
62
+ * `<file>#<marker>` (see file-guard.ts). */
63
+ blocks?: Record<string, string>;
64
+ }
65
+ export type InitManifestSection = 'skills' | 'commands' | 'agents' | 'kimiSkills' | 'kimiPluginCommands' | 'opencodeSkills';
66
+ /**
67
+ * Read the provenance manifest. Returns null when absent or unreadable —
68
+ * callers must treat that as "provenance unknown", i.e. delete nothing.
69
+ */
70
+ export declare function readInitManifest(targetDir: string): InitManifest | null;
71
+ /** Replace the manifest's `files` or `blocks` hash map, keeping every other
72
+ * field (see file-guard.ts). */
73
+ export declare function recordManifestHashes(targetDir: string, field: 'files' | 'blocks', hashes: Record<string, string>): void;
74
+ /**
75
+ * Names init previously generated in one section. Empty set when no manifest
76
+ * exists — which makes the stale sweep a no-op rather than a delete-everything.
77
+ */
78
+ export declare function previouslyGenerated(targetDir: string, section: InitManifestSection): Set<string>;
79
+ /**
80
+ * Record the entries init just wrote for one section, merging into any
81
+ * existing manifest so a partial run (e.g. --only-claude, or a section whose
82
+ * source dir was missing) never drops provenance for the other sections.
83
+ */
84
+ export declare function recordGenerated(targetDir: string, section: InitManifestSection, entries: string[]): void;
85
+ /**
86
+ * Retire a generated entry instead of deleting it (o-38): a name the
87
+ * manifest recorded that this version no longer ships anywhere is moved to
88
+ * `.monomind/backups/<run-timestamp>-<pid>/retired/<label>/` rather than
89
+ * `rmSync`-ed. The manifest's granularity is per-top-level-entry — "did init
90
+ * ever generate this name" — not per-file, so a stale-sweep candidate can
91
+ * still hold user files added since (a note beside a retired skill, e.g.)
92
+ * that must survive byte-identical.
93
+ *
94
+ * `label` doubles as the retirement's section plus display name, e.g.
95
+ * `skills/my-retired-skill` — the first path segment is an
96
+ * `InitManifestSection` value for the five real call sites, or a
97
+ * descriptive mirror label (`gemini-skills`, `agents-skills`,
98
+ * `opencode-skills`) for a mirror copy that turned out to hold user-added
99
+ * content (see `copySkills` / `writeOpencodeFiles`).
100
+ *
101
+ * On any failure, the entry is LEFT IN PLACE and a warning is recorded in
102
+ * `result.errors` — this must never fall back to deleting; a fix that
103
+ * deletes when the move fails is the original bug with extra steps.
104
+ */
105
+ export declare function retireGeneratedEntry(targetDir: string, label: string, stalePath: string, result: InitResult): void;
106
+ //# sourceMappingURL=init-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-manifest.d.ts","sourceRoot":"","sources":["../../../src/init/init-manifest.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,QAA+C,CAAC;AAE9E;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;;;2EAGuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,qFAAqF;IACrF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,gFAAgF;IAChF,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B;;6EAEyE;IACzE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;wEACoE;IACpE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB;;iDAE6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;iDAC6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,MAAM,mBAAmB,GAC3B,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,YAAY,GACZ,oBAAoB,GACpB,gBAAgB,CAAC;AAErB;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CA2CvE;AAWD;iCACiC;AACjC,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,GAAG,QAAQ,EACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,IAAI,CAoBN;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,GAAG,CAAC,MAAM,CAAC,CAEhG;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,MAAM,EAAE,GAChB,IAAI,CAoBN;AAmDD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,GACjB,IAAI,CAsBN"}
@@ -0,0 +1,222 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { atomicWriteFile } from './fs-helpers.js';
4
+ /**
5
+ * Provenance manifest for generated .claude content.
6
+ *
7
+ * init used to "clean stale" entries by deleting every name under
8
+ * .claude/{skills,commands,agents} that was absent from the current version's
9
+ * SKILLS_MAP/COMMANDS_MAP/AGENTS_MAP. Every user-authored command and skill is
10
+ * absent from those maps, so that pass deleted user content on the very first
11
+ * run — unrecoverable data loss.
12
+ *
13
+ * The manifest records exactly which entries *this tool* wrote, so the stale
14
+ * sweep can be restricted to those. Anything init did not write is never
15
+ * removed. Projects initialised by an older version have no manifest, so their
16
+ * first run under the fix deletes nothing and seeds the manifest instead;
17
+ * stale generated content may survive one extra run, which is the correct
18
+ * trade (preserving stale generated content is recoverable, deleting user
19
+ * content is not).
20
+ */
21
+ export const INIT_MANIFEST_REL = path.join('.monomind', 'init-manifest.json');
22
+ /**
23
+ * Read the provenance manifest. Returns null when absent or unreadable —
24
+ * callers must treat that as "provenance unknown", i.e. delete nothing.
25
+ */
26
+ export function readInitManifest(targetDir) {
27
+ const manifestPath = path.join(targetDir, INIT_MANIFEST_REL);
28
+ try {
29
+ if (!fs.existsSync(manifestPath))
30
+ return null;
31
+ const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
32
+ if (!parsed || typeof parsed !== 'object')
33
+ return null;
34
+ return {
35
+ version: typeof parsed.version === 'number' ? parsed.version : 1,
36
+ skills: Array.isArray(parsed.skills)
37
+ ? parsed.skills.filter((s) => typeof s === 'string')
38
+ : [],
39
+ commands: Array.isArray(parsed.commands)
40
+ ? parsed.commands.filter((s) => typeof s === 'string')
41
+ : [],
42
+ agents: Array.isArray(parsed.agents)
43
+ ? parsed.agents.filter((s) => typeof s === 'string')
44
+ : [],
45
+ kimiSkills: Array.isArray(parsed.kimiSkills)
46
+ ? parsed.kimiSkills.filter((s) => typeof s === 'string')
47
+ : [],
48
+ kimiPluginCommands: Array.isArray(parsed.kimiPluginCommands)
49
+ ? parsed.kimiPluginCommands.filter((s) => typeof s === 'string')
50
+ : [],
51
+ opencodeSkills: Array.isArray(parsed.opencodeSkills)
52
+ ? parsed.opencodeSkills.filter((s) => typeof s === 'string')
53
+ : [],
54
+ retired: Array.isArray(parsed.retired)
55
+ ? parsed.retired.filter((r) => !!r &&
56
+ typeof r === 'object' &&
57
+ typeof r.section === 'string' &&
58
+ typeof r.name === 'string' &&
59
+ typeof r.movedTo === 'string' &&
60
+ typeof r.at === 'string')
61
+ : [],
62
+ files: stringRecord(parsed.files),
63
+ blocks: stringRecord(parsed.blocks),
64
+ };
65
+ }
66
+ catch {
67
+ return null;
68
+ }
69
+ }
70
+ function stringRecord(value) {
71
+ if (!value || typeof value !== 'object' || Array.isArray(value))
72
+ return {};
73
+ return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === 'string'));
74
+ }
75
+ /** Replace the manifest's `files` or `blocks` hash map, keeping every other
76
+ * field (see file-guard.ts). */
77
+ export function recordManifestHashes(targetDir, field, hashes) {
78
+ const manifestPath = path.join(targetDir, INIT_MANIFEST_REL);
79
+ const manifest = readInitManifest(targetDir) ?? {
80
+ version: 1,
81
+ skills: [],
82
+ commands: [],
83
+ agents: [],
84
+ kimiSkills: [],
85
+ kimiPluginCommands: [],
86
+ opencodeSkills: [],
87
+ };
88
+ manifest[field] = Object.fromEntries(Object.entries(hashes).sort(([a], [b]) => a.localeCompare(b)));
89
+ try {
90
+ fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
91
+ atomicWriteFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
92
+ }
93
+ catch {
94
+ // Non-fatal: without hashes the next run treats these files as unrecorded.
95
+ }
96
+ }
97
+ /**
98
+ * Names init previously generated in one section. Empty set when no manifest
99
+ * exists — which makes the stale sweep a no-op rather than a delete-everything.
100
+ */
101
+ export function previouslyGenerated(targetDir, section) {
102
+ return new Set(readInitManifest(targetDir)?.[section] ?? []);
103
+ }
104
+ /**
105
+ * Record the entries init just wrote for one section, merging into any
106
+ * existing manifest so a partial run (e.g. --only-claude, or a section whose
107
+ * source dir was missing) never drops provenance for the other sections.
108
+ */
109
+ export function recordGenerated(targetDir, section, entries) {
110
+ const manifestPath = path.join(targetDir, INIT_MANIFEST_REL);
111
+ const existing = readInitManifest(targetDir);
112
+ const manifest = existing ?? {
113
+ version: 1,
114
+ skills: [],
115
+ commands: [],
116
+ agents: [],
117
+ kimiSkills: [],
118
+ kimiPluginCommands: [],
119
+ opencodeSkills: [],
120
+ };
121
+ manifest.version = 1;
122
+ manifest[section] = [...new Set(entries)].sort();
123
+ try {
124
+ fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
125
+ atomicWriteFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
126
+ }
127
+ catch {
128
+ // Non-fatal: without a manifest the next run simply deletes nothing.
129
+ }
130
+ }
131
+ /**
132
+ * Append one retirement to the manifest's `retired` array (o-38). A separate
133
+ * read-modify-write from `recordGenerated`'s, deliberately: `recordGenerated`
134
+ * REPLACES one section's active-entry list, and calling it after every single
135
+ * retirement (the stale-sweep loop can retire several names) would be wrong.
136
+ * This only ever appends, and appending here happens before the sweep's
137
+ * `recordGenerated` call, so `retired` survives that call's read of the
138
+ * manifest — `recordGenerated` never touches this field.
139
+ */
140
+ function appendRetiredProvenance(targetDir, entry) {
141
+ const manifestPath = path.join(targetDir, INIT_MANIFEST_REL);
142
+ const existing = readInitManifest(targetDir);
143
+ const manifest = existing ?? {
144
+ version: 1,
145
+ skills: [],
146
+ commands: [],
147
+ agents: [],
148
+ kimiSkills: [],
149
+ kimiPluginCommands: [],
150
+ opencodeSkills: [],
151
+ retired: [],
152
+ };
153
+ manifest.retired = [...(manifest.retired ?? []), entry];
154
+ try {
155
+ fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
156
+ atomicWriteFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
157
+ }
158
+ catch {
159
+ // Non-fatal, same as recordGenerated: the retire itself already
160
+ // succeeded (the file is safe); only the audit trail entry is lost.
161
+ }
162
+ }
163
+ // One shared retire-destination root per init run, keyed by the run's own
164
+ // InitResult object (created once per `executeInit` call) rather than
165
+ // targetDir — safe under concurrent/sequential runs against different
166
+ // targetDirs in the same process (e.g. a test suite), and lets every
167
+ // retirement in a run land under one timestamped directory instead of a
168
+ // different one per call.
169
+ const retireRoots = new WeakMap();
170
+ function getRetireRoot(targetDir, result) {
171
+ let root = retireRoots.get(result);
172
+ if (!root) {
173
+ root = path.join(targetDir, '.monomind', 'backups', `${Date.now()}-${process.pid}`, 'retired');
174
+ retireRoots.set(result, root);
175
+ }
176
+ return root;
177
+ }
178
+ /**
179
+ * Retire a generated entry instead of deleting it (o-38): a name the
180
+ * manifest recorded that this version no longer ships anywhere is moved to
181
+ * `.monomind/backups/<run-timestamp>-<pid>/retired/<label>/` rather than
182
+ * `rmSync`-ed. The manifest's granularity is per-top-level-entry — "did init
183
+ * ever generate this name" — not per-file, so a stale-sweep candidate can
184
+ * still hold user files added since (a note beside a retired skill, e.g.)
185
+ * that must survive byte-identical.
186
+ *
187
+ * `label` doubles as the retirement's section plus display name, e.g.
188
+ * `skills/my-retired-skill` — the first path segment is an
189
+ * `InitManifestSection` value for the five real call sites, or a
190
+ * descriptive mirror label (`gemini-skills`, `agents-skills`,
191
+ * `opencode-skills`) for a mirror copy that turned out to hold user-added
192
+ * content (see `copySkills` / `writeOpencodeFiles`).
193
+ *
194
+ * On any failure, the entry is LEFT IN PLACE and a warning is recorded in
195
+ * `result.errors` — this must never fall back to deleting; a fix that
196
+ * deletes when the move fails is the original bug with extra steps.
197
+ */
198
+ export function retireGeneratedEntry(targetDir, label, stalePath, result) {
199
+ const sepIndex = label.indexOf('/');
200
+ const section = sepIndex === -1 ? label : label.slice(0, sepIndex);
201
+ const name = sepIndex === -1 ? label : label.slice(sepIndex + 1);
202
+ const dest = path.join(getRetireRoot(targetDir, result), label);
203
+ try {
204
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
205
+ try {
206
+ fs.renameSync(stalePath, dest);
207
+ }
208
+ catch (error) {
209
+ if (error.code !== 'EXDEV')
210
+ throw error;
211
+ fs.cpSync(stalePath, dest, { recursive: true });
212
+ fs.rmSync(stalePath, { recursive: true, force: true });
213
+ }
214
+ const movedTo = path.relative(targetDir, dest);
215
+ result.removed.push(`[retired] ${label} → ${movedTo}`);
216
+ appendRetiredProvenance(targetDir, { section, name, movedTo, at: new Date().toISOString() });
217
+ }
218
+ catch (error) {
219
+ result.errors.push(`Could not retire ${label} (left in place): ${error instanceof Error ? error.message : String(error)}`);
220
+ }
221
+ }
222
+ //# sourceMappingURL=init-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-manifest.js","sourceRoot":"","sources":["../../../src/init/init-manifest.ts"],"names":[],"mappings":"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"}