grounder 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/README.md +150 -271
  2. package/dist/agents/claude.d.ts +4 -4
  3. package/dist/agents/claude.d.ts.map +1 -1
  4. package/dist/agents/claude.js +158 -178
  5. package/dist/agents/claude.js.map +1 -1
  6. package/dist/agents/cursor.d.ts +3 -3
  7. package/dist/agents/cursor.d.ts.map +1 -1
  8. package/dist/agents/cursor.js +97 -143
  9. package/dist/agents/cursor.js.map +1 -1
  10. package/dist/agents/home-skills.d.ts +46 -0
  11. package/dist/agents/home-skills.d.ts.map +1 -0
  12. package/dist/agents/home-skills.js +83 -0
  13. package/dist/agents/home-skills.js.map +1 -0
  14. package/dist/agents/hook-fragment.d.ts +52 -0
  15. package/dist/agents/hook-fragment.d.ts.map +1 -0
  16. package/dist/agents/hook-fragment.js +76 -0
  17. package/dist/agents/hook-fragment.js.map +1 -0
  18. package/dist/agents/hook-install.d.ts +62 -0
  19. package/dist/agents/hook-install.d.ts.map +1 -0
  20. package/dist/agents/hook-install.js +74 -0
  21. package/dist/agents/hook-install.js.map +1 -0
  22. package/dist/agents/hook-runtime.d.ts +80 -13
  23. package/dist/agents/hook-runtime.d.ts.map +1 -1
  24. package/dist/agents/hook-runtime.js +278 -74
  25. package/dist/agents/hook-runtime.js.map +1 -1
  26. package/dist/agents/index.d.ts +8 -14
  27. package/dist/agents/index.d.ts.map +1 -1
  28. package/dist/agents/index.js +13 -19
  29. package/dist/agents/index.js.map +1 -1
  30. package/dist/agents/types.d.ts +56 -16
  31. package/dist/agents/types.d.ts.map +1 -1
  32. package/dist/cli.js +15 -10
  33. package/dist/cli.js.map +1 -1
  34. package/dist/commands/apply.d.ts +69 -0
  35. package/dist/commands/apply.d.ts.map +1 -0
  36. package/dist/commands/apply.js +238 -0
  37. package/dist/commands/apply.js.map +1 -0
  38. package/dist/commands/doctor.d.ts.map +1 -1
  39. package/dist/commands/doctor.js +197 -101
  40. package/dist/commands/doctor.js.map +1 -1
  41. package/dist/commands/handoff/list.d.ts +23 -13
  42. package/dist/commands/handoff/list.d.ts.map +1 -1
  43. package/dist/commands/handoff/list.js +28 -16
  44. package/dist/commands/handoff/list.js.map +1 -1
  45. package/dist/commands/handoff/peek.d.ts +1 -1
  46. package/dist/commands/handoff/peek.d.ts.map +1 -1
  47. package/dist/commands/handoff/peek.js +28 -12
  48. package/dist/commands/handoff/peek.js.map +1 -1
  49. package/dist/commands/handoff.d.ts +2 -0
  50. package/dist/commands/handoff.d.ts.map +1 -1
  51. package/dist/commands/handoff.js +10 -1
  52. package/dist/commands/handoff.js.map +1 -1
  53. package/dist/commands/install-drift.d.ts +34 -0
  54. package/dist/commands/install-drift.d.ts.map +1 -0
  55. package/dist/commands/install-drift.js +72 -0
  56. package/dist/commands/install-drift.js.map +1 -0
  57. package/dist/commands/link.d.ts +12 -0
  58. package/dist/commands/link.d.ts.map +1 -0
  59. package/dist/commands/{repo/init.js → link.js} +35 -27
  60. package/dist/commands/link.js.map +1 -0
  61. package/dist/commands/migrate.d.ts +11 -3
  62. package/dist/commands/migrate.d.ts.map +1 -1
  63. package/dist/commands/migrate.js +66 -34
  64. package/dist/commands/migrate.js.map +1 -1
  65. package/dist/commands/note/list.d.ts +17 -9
  66. package/dist/commands/note/list.d.ts.map +1 -1
  67. package/dist/commands/note/list.js +19 -14
  68. package/dist/commands/note/list.js.map +1 -1
  69. package/dist/commands/note.d.ts +2 -0
  70. package/dist/commands/note.d.ts.map +1 -1
  71. package/dist/commands/note.js +10 -1
  72. package/dist/commands/note.js.map +1 -1
  73. package/dist/commands/output.d.ts +22 -2
  74. package/dist/commands/output.d.ts.map +1 -1
  75. package/dist/commands/output.js +18 -6
  76. package/dist/commands/output.js.map +1 -1
  77. package/dist/commands/overview.d.ts +33 -0
  78. package/dist/commands/overview.d.ts.map +1 -0
  79. package/dist/commands/overview.js +150 -0
  80. package/dist/commands/overview.js.map +1 -0
  81. package/dist/commands/plan/list.d.ts +20 -12
  82. package/dist/commands/plan/list.d.ts.map +1 -1
  83. package/dist/commands/plan/list.js +22 -17
  84. package/dist/commands/plan/list.js.map +1 -1
  85. package/dist/commands/plan.d.ts +2 -0
  86. package/dist/commands/plan.d.ts.map +1 -1
  87. package/dist/commands/plan.js +12 -2
  88. package/dist/commands/plan.js.map +1 -1
  89. package/dist/commands/render-artifact-table.d.ts +85 -0
  90. package/dist/commands/render-artifact-table.d.ts.map +1 -0
  91. package/dist/commands/render-artifact-table.js +232 -0
  92. package/dist/commands/render-artifact-table.js.map +1 -0
  93. package/dist/commands/require-linked.js +2 -2
  94. package/dist/commands/require-linked.js.map +1 -1
  95. package/dist/commands/search.d.ts +23 -0
  96. package/dist/commands/search.d.ts.map +1 -0
  97. package/dist/commands/search.js +288 -0
  98. package/dist/commands/search.js.map +1 -0
  99. package/dist/commands/{vault/init.d.ts → setup.d.ts} +5 -4
  100. package/dist/commands/setup.d.ts.map +1 -0
  101. package/dist/commands/setup.js +210 -0
  102. package/dist/commands/setup.js.map +1 -0
  103. package/dist/commands/status.d.ts +7 -0
  104. package/dist/commands/status.d.ts.map +1 -1
  105. package/dist/commands/status.js +273 -83
  106. package/dist/commands/status.js.map +1 -1
  107. package/dist/commands/upgrade-banner.d.ts +2 -2
  108. package/dist/commands/upgrade-banner.js +2 -2
  109. package/dist/connector/home.d.ts +12 -0
  110. package/dist/connector/home.d.ts.map +1 -1
  111. package/dist/connector/home.js +26 -2
  112. package/dist/connector/home.js.map +1 -1
  113. package/dist/connector/ledger-migrations.d.ts +55 -0
  114. package/dist/connector/ledger-migrations.d.ts.map +1 -0
  115. package/dist/connector/ledger-migrations.js +94 -0
  116. package/dist/connector/ledger-migrations.js.map +1 -0
  117. package/dist/connector/state.d.ts +97 -60
  118. package/dist/connector/state.d.ts.map +1 -1
  119. package/dist/connector/state.js +165 -107
  120. package/dist/connector/state.js.map +1 -1
  121. package/dist/connector/vault.d.ts +2 -0
  122. package/dist/connector/vault.d.ts.map +1 -1
  123. package/dist/connector/vault.js +6 -1
  124. package/dist/connector/vault.js.map +1 -1
  125. package/dist/help.d.ts +3 -3
  126. package/dist/help.d.ts.map +1 -1
  127. package/dist/help.js +97 -56
  128. package/dist/help.js.map +1 -1
  129. package/dist/reconcile/apply.d.ts +31 -0
  130. package/dist/reconcile/apply.d.ts.map +1 -0
  131. package/dist/reconcile/apply.js +97 -0
  132. package/dist/reconcile/apply.js.map +1 -0
  133. package/dist/reconcile/core.d.ts +82 -0
  134. package/dist/reconcile/core.d.ts.map +1 -0
  135. package/dist/reconcile/core.js +163 -0
  136. package/dist/reconcile/core.js.map +1 -0
  137. package/dist/reconcile/disk.d.ts +13 -0
  138. package/dist/reconcile/disk.d.ts.map +1 -0
  139. package/dist/reconcile/disk.js +28 -0
  140. package/dist/reconcile/disk.js.map +1 -0
  141. package/dist/util/frontmatter.d.ts +9 -7
  142. package/dist/util/frontmatter.d.ts.map +1 -1
  143. package/dist/util/frontmatter.js +29 -4
  144. package/dist/util/frontmatter.js.map +1 -1
  145. package/dist/util/fs.d.ts +14 -0
  146. package/dist/util/fs.d.ts.map +1 -1
  147. package/dist/util/fs.js +27 -1
  148. package/dist/util/fs.js.map +1 -1
  149. package/dist/util/merge-json.d.ts +13 -2
  150. package/dist/util/merge-json.d.ts.map +1 -1
  151. package/dist/util/merge-json.js +24 -10
  152. package/dist/util/merge-json.js.map +1 -1
  153. package/dist/util/path.d.ts +23 -0
  154. package/dist/util/path.d.ts.map +1 -1
  155. package/dist/util/path.js +39 -0
  156. package/dist/util/path.js.map +1 -1
  157. package/dist/vault/list-handoffs.d.ts +14 -2
  158. package/dist/vault/list-handoffs.d.ts.map +1 -1
  159. package/dist/vault/list-handoffs.js +40 -23
  160. package/dist/vault/list-handoffs.js.map +1 -1
  161. package/dist/vault/list-markdown.d.ts +8 -0
  162. package/dist/vault/list-markdown.d.ts.map +1 -0
  163. package/dist/vault/list-markdown.js +35 -0
  164. package/dist/vault/list-markdown.js.map +1 -0
  165. package/dist/vault/list-notes.d.ts +15 -6
  166. package/dist/vault/list-notes.d.ts.map +1 -1
  167. package/dist/vault/list-notes.js +23 -27
  168. package/dist/vault/list-notes.js.map +1 -1
  169. package/dist/vault/list-plans.d.ts +12 -3
  170. package/dist/vault/list-plans.d.ts.map +1 -1
  171. package/dist/vault/list-plans.js +20 -24
  172. package/dist/vault/list-plans.js.map +1 -1
  173. package/dist/vault/search.d.ts +55 -0
  174. package/dist/vault/search.d.ts.map +1 -0
  175. package/dist/vault/search.js +432 -0
  176. package/dist/vault/search.js.map +1 -0
  177. package/dist/vault/write-handoff.d.ts +2 -0
  178. package/dist/vault/write-handoff.d.ts.map +1 -1
  179. package/dist/vault/write-handoff.js +5 -0
  180. package/dist/vault/write-handoff.js.map +1 -1
  181. package/dist/vault/write-note.d.ts +2 -0
  182. package/dist/vault/write-note.d.ts.map +1 -1
  183. package/dist/vault/write-note.js +9 -1
  184. package/dist/vault/write-note.js.map +1 -1
  185. package/dist/vault/write-plan.d.ts +4 -0
  186. package/dist/vault/write-plan.d.ts.map +1 -1
  187. package/dist/vault/write-plan.js +14 -1
  188. package/dist/vault/write-plan.js.map +1 -1
  189. package/package.json +11 -4
  190. package/templates/agents/claude/skills/grounder-handoff/SKILL.md +73 -0
  191. package/templates/agents/claude/{commands/grounder-note.md → skills/grounder-note/SKILL.md} +12 -2
  192. package/templates/agents/claude/skills/grounder-overview/SKILL.md +21 -0
  193. package/templates/agents/claude/{commands/grounder-plan.md → skills/grounder-plan/SKILL.md} +13 -5
  194. package/templates/agents/claude/skills/grounder-recall/SKILL.md +34 -0
  195. package/templates/agents/claude/skills/grounder-search/SKILL.md +152 -0
  196. package/templates/agents/cursor/skills/grounder-handoff/SKILL.md +73 -0
  197. package/templates/agents/cursor/{commands/grounder-note.md → skills/grounder-note/SKILL.md} +12 -2
  198. package/templates/agents/cursor/skills/grounder-overview/SKILL.md +21 -0
  199. package/templates/agents/cursor/{commands/grounder-plan.md → skills/grounder-plan/SKILL.md} +13 -5
  200. package/templates/agents/cursor/skills/grounder-recall/SKILL.md +34 -0
  201. package/templates/agents/cursor/skills/grounder-search/SKILL.md +152 -0
  202. package/templates/vault/plan.md +1 -1
  203. package/templates/vault/session-handoff.md +2 -1
  204. package/dist/agents/install-command.d.ts +0 -35
  205. package/dist/agents/install-command.d.ts.map +0 -1
  206. package/dist/agents/install-command.js +0 -65
  207. package/dist/agents/install-command.js.map +0 -1
  208. package/dist/commands/apply-agent-installs.d.ts +0 -34
  209. package/dist/commands/apply-agent-installs.d.ts.map +0 -1
  210. package/dist/commands/apply-agent-installs.js +0 -137
  211. package/dist/commands/apply-agent-installs.js.map +0 -1
  212. package/dist/commands/repo/init.d.ts +0 -11
  213. package/dist/commands/repo/init.d.ts.map +0 -1
  214. package/dist/commands/repo/init.js.map +0 -1
  215. package/dist/commands/vault/init.d.ts.map +0 -1
  216. package/dist/commands/vault/init.js +0 -90
  217. package/dist/commands/vault/init.js.map +0 -1
  218. package/templates/agents/claude/commands/grounder-task-handoff.md +0 -54
  219. package/templates/agents/claude/commands/grounder-task.md +0 -22
  220. package/templates/agents/cursor/commands/grounder-task-handoff.md +0 -54
  221. package/templates/agents/cursor/commands/grounder-task.md +0 -22
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-fragment.js","sourceRoot":"","sources":["../../src/agents/hook-fragment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAe,EAAE,KAAa;IAC7D,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAI,MAAkC,CAAC,KAAK,CAAC;IACxD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAI,KAAiC,CAAC,KAAK,CAAC,CAAC;IAC1D,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAgC,EAChC,QAAgB;IAEhB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,iCAAiC,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,EAAE,GAAI,KAAiC,EAAE,CAAC;AACnD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,qBAAqB,CACnC,OAAqB,EACrB,OAA8B;IAE9B,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAqB,EACrB,OAA8B,EAC9B,SAAY;IAEZ,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * The I/O scaffolding both hook adapters run around their own merge functions:
3
+ * read, converge, write, and report which of created/overwritten/skipped
4
+ * happened. Kept out of `hook-fragment.ts` so that module stays pure — the
5
+ * same split `reconcile/` draws between `core.ts` and `apply.ts`.
6
+ *
7
+ * What stays adapter-specific is the fragment shape itself: the recognizer
8
+ * predicate, where a canonical entry belongs, and what "already converged"
9
+ * means (Cursor: exactly one match in a flat array; Claude Code: exactly one
10
+ * match, under the canonical matcher group). Those arrive here as callbacks.
11
+ */
12
+ import type { AgentInstallOptions, AgentInstallResult } from "./types.js";
13
+ export interface HookFragmentInstall {
14
+ /** The shared JSON config this fragment lives in. */
15
+ dest: string;
16
+ /**
17
+ * Skip the write entirely — exactly one canonical entry is already present
18
+ * *and* the shared runtime is current. Anything else converges.
19
+ */
20
+ isUpToDate(filePath: string): Promise<boolean>;
21
+ /**
22
+ * Does the file already list any Grounder entry (in any form, including a
23
+ * legacy `npx` one)? Decides whether a write reports `overwritten` rather
24
+ * than `created`. Only consulted when the file exists.
25
+ */
26
+ hasGrounderEntry(filePath: string): Promise<boolean>;
27
+ /**
28
+ * Converge the fragment into a parsed config root, returning the new root.
29
+ * `fileExisted` is passed through for the one thing that depends on it
30
+ * (Cursor stamps `version: 1` only onto a file it is creating).
31
+ */
32
+ merge(current: Record<string, unknown>, fileExisted: boolean): Record<string, unknown>;
33
+ }
34
+ /**
35
+ * Install (or converge) a hook fragment, also materializing `~/.grounder/runtime`
36
+ * on a real run if it's stale. Always converges the fragment itself — no
37
+ * `--force` gate; `force` only affects whole-file skill artifacts, never a
38
+ * shared-JSON fragment.
39
+ *
40
+ * The runtime materialization is gated on {@link isHookRuntimeStale}, not
41
+ * unconditional: an invocation running through the materialized runtime's
42
+ * own `dist/cli.js` (e.g. `{{GROUNDER_CLI}}` in a skill) has
43
+ * `defaultPackageRoot` resolve to the runtime itself, which
44
+ * {@link installHookRuntime} refuses to materialize from (see its doc
45
+ * comment) — skipping the call here when the runtime is already current
46
+ * avoids that throw.
47
+ *
48
+ * Never clobbers: an unparseable config backs off inside {@link mergeJsonFile},
49
+ * and a `merge` that refuses (see `readHooksObject`) throws before any write.
50
+ */
51
+ export declare function installHookFragment(install: HookFragmentInstall, opts: AgentInstallOptions): Promise<AgentInstallResult>;
52
+ /**
53
+ * Remove a hook fragment entirely (`--no-hooks`). Reports an artifact only
54
+ * when something actually changed, so an agent that never had the entry
55
+ * contributes no row to the install table.
56
+ *
57
+ * `remove` is expected to return its argument by reference when there is
58
+ * nothing to remove — that is what stops {@link mergeJsonFile} from
59
+ * reformatting an unrelated config file on its way to a no-op.
60
+ */
61
+ export declare function removeHookFragment(dest: string, remove: (current: Record<string, unknown>) => Record<string, unknown>, opts: AgentInstallOptions): Promise<AgentInstallResult>;
62
+ //# sourceMappingURL=hook-install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-install.d.ts","sourceRoot":"","sources":["../../src/agents/hook-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,mBAAmB,EAAE,kBAAkB,EAAkB,MAAM,YAAY,CAAC;AAE1F,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C;;;;OAIG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrD;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC,CA2B7B;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC,CAS7B"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The I/O scaffolding both hook adapters run around their own merge functions:
3
+ * read, converge, write, and report which of created/overwritten/skipped
4
+ * happened. Kept out of `hook-fragment.ts` so that module stays pure — the
5
+ * same split `reconcile/` draws between `core.ts` and `apply.ts`.
6
+ *
7
+ * What stays adapter-specific is the fragment shape itself: the recognizer
8
+ * predicate, where a canonical entry belongs, and what "already converged"
9
+ * means (Cursor: exactly one match in a flat array; Claude Code: exactly one
10
+ * match, under the canonical matcher group). Those arrive here as callbacks.
11
+ */
12
+ import { fileExists } from "../util/fs.js";
13
+ import { mergeJsonFile } from "../util/merge-json.js";
14
+ import { installHookRuntime, isHookRuntimeStale } from "./hook-runtime.js";
15
+ /**
16
+ * Install (or converge) a hook fragment, also materializing `~/.grounder/runtime`
17
+ * on a real run if it's stale. Always converges the fragment itself — no
18
+ * `--force` gate; `force` only affects whole-file skill artifacts, never a
19
+ * shared-JSON fragment.
20
+ *
21
+ * The runtime materialization is gated on {@link isHookRuntimeStale}, not
22
+ * unconditional: an invocation running through the materialized runtime's
23
+ * own `dist/cli.js` (e.g. `{{GROUNDER_CLI}}` in a skill) has
24
+ * `defaultPackageRoot` resolve to the runtime itself, which
25
+ * {@link installHookRuntime} refuses to materialize from (see its doc
26
+ * comment) — skipping the call here when the runtime is already current
27
+ * avoids that throw.
28
+ *
29
+ * Never clobbers: an unparseable config backs off inside {@link mergeJsonFile},
30
+ * and a `merge` that refuses (see `readHooksObject`) throws before any write.
31
+ */
32
+ export async function installHookFragment(install, opts) {
33
+ const dest = install.dest;
34
+ if (await install.isUpToDate(dest)) {
35
+ return { artifacts: { [dest]: "skipped" } };
36
+ }
37
+ if (!opts.dryRun && (await isHookRuntimeStale(opts.homeDir))) {
38
+ await installHookRuntime({ homeDir: opts.homeDir });
39
+ }
40
+ const fileExisted = await fileExists(dest);
41
+ const hadGrounderEntry = fileExisted && (await install.hasGrounderEntry(dest));
42
+ const result = await mergeJsonFile(dest, (current) => install.merge(current, fileExisted), {
43
+ dryRun: opts.dryRun,
44
+ });
45
+ if (!result.ok) {
46
+ throw new Error(result.message);
47
+ }
48
+ const status = !result.changed
49
+ ? "skipped"
50
+ : hadGrounderEntry
51
+ ? "overwritten"
52
+ : "created";
53
+ return { artifacts: { [dest]: status } };
54
+ }
55
+ /**
56
+ * Remove a hook fragment entirely (`--no-hooks`). Reports an artifact only
57
+ * when something actually changed, so an agent that never had the entry
58
+ * contributes no row to the install table.
59
+ *
60
+ * `remove` is expected to return its argument by reference when there is
61
+ * nothing to remove — that is what stops {@link mergeJsonFile} from
62
+ * reformatting an unrelated config file on its way to a no-op.
63
+ */
64
+ export async function removeHookFragment(dest, remove, opts) {
65
+ if (!(await fileExists(dest))) {
66
+ return { artifacts: {} };
67
+ }
68
+ const result = await mergeJsonFile(dest, remove, { dryRun: opts.dryRun });
69
+ if (!result.ok) {
70
+ throw new Error(result.message);
71
+ }
72
+ return result.changed ? { artifacts: { [dest]: "overwritten" } } : { artifacts: {} };
73
+ }
74
+ //# sourceMappingURL=hook-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-install.js","sourceRoot":"","sources":["../../src/agents/hook-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAyB3E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAA4B,EAC5B,IAAyB;IAEzB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE1B,IAAI,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC;IAC9C,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAC7D,MAAM,kBAAkB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,gBAAgB,GAAG,WAAW,IAAI,CAAC,MAAM,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/E,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE;QACzF,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,MAAM,GAAmB,CAAC,MAAM,CAAC,OAAO;QAC5C,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,gBAAgB;YAChB,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,SAAS,CAAC;IAChB,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,MAAqE,EACrE,IAAyB;IAEzB,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;IAC3B,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1E,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AACvF,CAAC"}
@@ -1,14 +1,14 @@
1
1
  /**
2
- * Home-local runtime shared by session hooks *and* slash commands (originally
2
+ * Home-local runtime shared by session hooks *and* skills (originally
3
3
  * "Issue 2 — replace `npx grounder` in session hooks"; later extended to cover
4
- * slash-command templates too, since they had the identical problem).
4
+ * skill templates too, since they had the identical problem).
5
5
  *
6
6
  * ## Why
7
7
  * Both surfaces used to shell out via `npx grounder …`. `npx <pkg>` (no
8
8
  * version specifier) matches against whatever `grounder` version exists in
9
9
  * the *current project's own dependencies*; only when the project doesn't
10
10
  * declare `grounder` as a dependency does it fall back to fetching
11
- * `grounder@latest` from the registry. Session hooks and slash commands both
11
+ * `grounder@latest` from the registry. Session hooks and skills both
12
12
  * run from arbitrary linked projects, which normally have no reason to depend
13
13
  * on `grounder` themselves, so contributors (and anyone ahead of the last
14
14
  * publish, or deliberately pinned to an older version) get the wrong binary.
@@ -16,9 +16,9 @@
16
16
  * [npm/cli#9244](https://github.com/npm/cli/issues/9244).
17
17
  *
18
18
  * ## Design
19
- * On `vault init`, materialize this package's `dist/` at
19
+ * On `setup`, materialize this package's `dist/` at
20
20
  * `~/.grounder/runtime/dist/` and point both host hook configs *and* the
21
- * commands copied into `~/.cursor/commands/` / `~/.claude/commands/` at:
21
+ * skills copied into `~/.cursor/skills/` / `~/.claude/skills/` at:
22
22
  * `process.execPath` + `~/.grounder/runtime/dist/cli.js` + `<subcommand> …`
23
23
  * No global install and no registry fetch at invocation time, for either
24
24
  * surface. This mirrors how Corepack (packageManager shims) and Husky/lint-staged
@@ -29,11 +29,13 @@
29
29
  * - **Durable source** (monorepo checkout, global install, linked devDependency) →
30
30
  * **symlink** `dist/` straight to the source. `pnpm build` / upgrading the
31
31
  * global install overwrites that same path in place, so hooks and commands
32
- * pick up new code immediately — no re-run of `vault init` ever needed.
32
+ * pick up new code immediately — no re-run of `setup` ever needed.
33
33
  * - **Ephemeral source** (bare `npx grounder …`, no install — each invocation
34
34
  * resolves to an immutable, version-keyed npx cache dir that can be evicted
35
- * or swapped out from under a symlink) → **copy** `dist/`. Re-run
36
- * `grounder vault init <vault>` after upgrading to refresh; this is an
35
+ * or swapped out from under a symlink) → **copy** `dist/`, plus
36
+ * `package.json` and `templates/` alongside it (see {@link installHookRuntime}'s
37
+ * doc comment for why those siblings are needed). Re-run
38
+ * `grounder setup <vault>` after upgrading to refresh; this is an
37
39
  * inherent limitation of using npx with no install for something that must
38
40
  * persist, not something we can engineer around.
39
41
  *
@@ -84,14 +86,14 @@ export declare function shellQuote(value: string): string;
84
86
  */
85
87
  export declare function extractRuntimeNodePath(command: unknown): string | null;
86
88
  /**
87
- * Find every baked Node interpreter path embedded in free-form text (slash-command
89
+ * Find every baked Node interpreter path embedded in free-form text (skill
88
90
  * markdown, etc.). Scans for the same `'<abs node>' '<abs …/cli.js>'` shape as
89
91
  * {@link extractRuntimeNodePath}, including mid-line / backtick-wrapped uses.
90
92
  */
91
93
  export declare function findRuntimeNodePathsInText(text: string): string[];
92
94
  /**
93
95
  * Quoted `<node> <runtime cli.js>` prefix, shared by every home-runtime
94
- * invocation (session hooks and slash-command templates alike). Append
96
+ * invocation (session hooks and skill templates alike). Append
95
97
  * subcommand args to build a full command string.
96
98
  */
97
99
  export declare function runtimeInvocation(homeDir?: string): string;
@@ -119,24 +121,89 @@ export declare function hookFileHasGrounderEntry(filePath: string): Promise<bool
119
121
  /**
120
122
  * True when the materialized runtime is missing or out of date for the given
121
123
  * source package:
124
+ * - **Self-referential** (`packageRoot` is `~/.grounder/runtime` itself —
125
+ * see {@link isSelfReferential}): never stale. There is no real source to
126
+ * compare against from inside this invocation, so the only sound answer is
127
+ * "leave it alone."
122
128
  * - **Symlink mode** (durable source): stale iff `dist/` isn't currently a
123
129
  * symlink resolving to this source's `dist/` (cheap `realpath` compare — no
124
130
  * staleness window, since a matching symlink is *always* current).
125
131
  * - **Copy mode** (ephemeral `npx` source): stale iff the manifest is
126
- * missing/unreadable or its recorded version differs from this source's.
132
+ * missing/unreadable, its recorded version differs from this source's, or
133
+ * `package.json` / `templates/` (when the source has one) are missing
134
+ * alongside `dist/` — a same-version repair case a version-only check
135
+ * would otherwise skip forever (e.g. a runtime materialized before these
136
+ * siblings were added, or one left mid-way by a partial install).
127
137
  *
128
138
  * @param packageRoot - Source package root to compare against (defaults to the
129
139
  * currently running package — override only in tests)
130
140
  */
131
141
  export declare function isHookRuntimeStale(homeDir?: string, packageRoot?: string): Promise<boolean>;
142
+ /**
143
+ * Materialization mode this source would use — symlink (durable) or copy
144
+ * (ephemeral `npx` cache) — without writing anything (read-only `realpath`
145
+ * checks only). Lets callers label a skipped/dry-run install the same way
146
+ * {@link installHookRuntime} would.
147
+ */
148
+ export declare function runtimeMode(packageRoot?: string): Promise<"symlink" | "copy">;
149
+ /**
150
+ * Materialize every artifact via `populate(stagingPath)` first — a
151
+ * populate/symlink/cp failure on any one of them leaves every `dest`
152
+ * untouched, since none have been promoted yet. Only once all of them are
153
+ * staged does promotion (backup-aside + rename-in) run for each in turn.
154
+ *
155
+ * If a promote fails partway through, every artifact already promoted in
156
+ * this call is rolled back (its backup renamed back over `dest`) before
157
+ * rethrowing — so a failure on, say, `package.json` after `dist/` has
158
+ * already promoted doesn't leave a new `dist/` sitting next to an old
159
+ * `package.json`. This isn't a true single filesystem transaction (POSIX
160
+ * has no atomic rename across independent paths), but it narrows the
161
+ * mixed-state window down to the renames themselves rather than leaving one
162
+ * as a visible end state after this function returns (successfully or not).
163
+ *
164
+ * A restore rename (`backup` back over `dest`) can itself fail — e.g. the
165
+ * same fault that broke the promote also blocks the rename back. When that
166
+ * happens `dest` is left in whatever state the failed renames put it in, but
167
+ * `backup` is deliberately *not* deleted by the cleanup below: it's the only
168
+ * remaining copy of what was there before this call, so a double failure
169
+ * degrades to "manual recovery from `<dest>.bak`" rather than silent data
170
+ * loss.
171
+ *
172
+ * `populate` decides how each artifact's staging gets filled (symlink vs.
173
+ * plain copy) — everything else (staging, backup, promote, rollback,
174
+ * cleanup) is identical for every artifact {@link installHookRuntime}
175
+ * materializes (`dist/`, and in copy mode, `package.json` / `templates/`).
176
+ */
177
+ export declare function installArtifacts(artifacts: Array<{
178
+ dest: string;
179
+ populate: (staging: string) => Promise<void>;
180
+ }>): Promise<void>;
132
181
  /**
133
182
  * Materialize this package's `dist/` at `~/.grounder/runtime/dist/` — symlinked
134
183
  * when the source is durable, copied when it's an ephemeral `npx` cache — and
135
184
  * write a manifest recording how.
136
185
  *
186
+ * Copy mode also copies `package.json` and `templates/` alongside `dist/`:
187
+ * `src/index.ts` reads `VERSION` from `<pkgRoot>/package.json` eagerly at
188
+ * import (every invocation), and `home-skills.ts` reads `<pkgRoot>/templates`
189
+ * on demand (`desiredArtifacts()` — real installs, and the drift check
190
+ * `status`/`doctor`/`peek` run). Neither exists under a copied `dist/`'s
191
+ * parent otherwise, so the materialized runtime crashed at import for every
192
+ * copy-mode (bare `npx grounder setup`) user. Symlink mode needs neither —
193
+ * Node resolves `import.meta.url` through `dist/`'s own symlink back to the
194
+ * real package root, package.json and templates included — and actively
195
+ * removes them if a previous copy-mode install left them behind, so
196
+ * `~/.grounder/runtime` never ends up with stale copy-mode siblings next to
197
+ * a symlinked `dist/`.
198
+ *
137
199
  * Callers should gate on {@link isHookRuntimeStale} (or `force`) before calling —
138
- * this always replaces whatever is currently at the destination, staging the
139
- * new materialization first so a failed symlink/cp leaves the live runtime intact.
200
+ * this always replaces whatever is currently at the destination. All
201
+ * artifacts (`dist/`, and in copy mode, `package.json` / `templates/`) are
202
+ * staged and promoted together via {@link installArtifacts}, which rolls
203
+ * back any artifact already promoted if a later one fails to promote.
204
+ * Refuses outright (see {@link isSelfReferential}) rather than attempting a
205
+ * self-symlink that would corrupt the runtime with an `ELOOP`-inducing link
206
+ * to itself.
140
207
  *
141
208
  * @param options.packageRoot - Source package root to materialize (defaults to
142
209
  * the currently running package — override only in tests)
@@ -1 +1 @@
1
- {"version":3,"file":"hook-runtime.d.ts","sourceRoot":"","sources":["../../src/agents/hook-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAkBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjD,wFAAwF;AACxF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAgCD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAyBtE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAcjE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,CAE3F;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAanE;AAED,mFAAmF;AACnF,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAqBxE;AAED,mFAAmF;AACnF,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEvE;AAED,qGAAqG;AACrG,wBAAsB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUtF;AAED,gFAAgF;AAChF,wBAAsB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEjF;AA2DD;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,GAAE,MAA2B,GACvC,OAAO,CAAC,OAAO,CAAC,CAkBlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,CAAC,CAkEjF"}
1
+ {"version":3,"file":"hook-runtime.d.ts","sourceRoot":"","sources":["../../src/agents/hook-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAkBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjD,wFAAwF;AACxF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AA+DD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAKtE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAcjE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,CAE3F;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAanE;AAED,mFAAmF;AACnF,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAqBxE;AAED,mFAAmF;AACnF,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEvE;AAED,qGAAqG;AACrG,wBAAsB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUtF;AAED,gFAAgF;AAChF,wBAAsB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEjF;AAuGD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,CAAC,EAAE,MAAM,EAChB,WAAW,GAAE,MAA2B,GACvC,OAAO,CAAC,OAAO,CAAC,CAmClB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,WAAW,GAAE,MAA2B,GACvC,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,CAE7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,GAC/E,OAAO,CAAC,IAAI,CAAC,CAqEf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,CAAC,CA0EjF"}