grounder 0.0.2 → 0.2.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 (60) hide show
  1. package/README.md +113 -40
  2. package/dist/agents/claude.d.ts +15 -0
  3. package/dist/agents/claude.d.ts.map +1 -1
  4. package/dist/agents/claude.js +225 -1
  5. package/dist/agents/claude.js.map +1 -1
  6. package/dist/agents/cursor-hook-input.d.ts +14 -0
  7. package/dist/agents/cursor-hook-input.d.ts.map +1 -0
  8. package/dist/agents/cursor-hook-input.js +80 -0
  9. package/dist/agents/cursor-hook-input.js.map +1 -0
  10. package/dist/agents/cursor.d.ts +11 -0
  11. package/dist/agents/cursor.d.ts.map +1 -1
  12. package/dist/agents/cursor.js +175 -1
  13. package/dist/agents/cursor.js.map +1 -1
  14. package/dist/agents/hook-runtime.d.ts +108 -0
  15. package/dist/agents/hook-runtime.d.ts.map +1 -0
  16. package/dist/agents/hook-runtime.js +260 -0
  17. package/dist/agents/hook-runtime.js.map +1 -0
  18. package/dist/agents/types.d.ts +6 -0
  19. package/dist/agents/types.d.ts.map +1 -1
  20. package/dist/cli.js +25 -1
  21. package/dist/cli.js.map +1 -1
  22. package/dist/commands/check.d.ts +13 -0
  23. package/dist/commands/check.d.ts.map +1 -0
  24. package/dist/commands/check.js +21 -0
  25. package/dist/commands/check.js.map +1 -0
  26. package/dist/commands/doctor.d.ts +9 -0
  27. package/dist/commands/doctor.d.ts.map +1 -0
  28. package/dist/commands/doctor.js +270 -0
  29. package/dist/commands/doctor.js.map +1 -0
  30. package/dist/commands/handoff/list.d.ts +9 -0
  31. package/dist/commands/handoff/list.d.ts.map +1 -1
  32. package/dist/commands/handoff/list.js +15 -4
  33. package/dist/commands/handoff/list.js.map +1 -1
  34. package/dist/commands/handoff/peek.d.ts +38 -0
  35. package/dist/commands/handoff/peek.d.ts.map +1 -0
  36. package/dist/commands/handoff/peek.js +120 -0
  37. package/dist/commands/handoff/peek.js.map +1 -0
  38. package/dist/commands/status.d.ts +7 -0
  39. package/dist/commands/status.d.ts.map +1 -0
  40. package/dist/commands/status.js +101 -0
  41. package/dist/commands/status.js.map +1 -0
  42. package/dist/commands/vault/init.d.ts +2 -0
  43. package/dist/commands/vault/init.d.ts.map +1 -1
  44. package/dist/commands/vault/init.js +28 -0
  45. package/dist/commands/vault/init.js.map +1 -1
  46. package/dist/util/frontmatter.d.ts +11 -0
  47. package/dist/util/frontmatter.d.ts.map +1 -0
  48. package/dist/util/frontmatter.js +69 -0
  49. package/dist/util/frontmatter.js.map +1 -0
  50. package/dist/util/merge-json.d.ts +15 -0
  51. package/dist/util/merge-json.d.ts.map +1 -0
  52. package/dist/util/merge-json.js +40 -0
  53. package/dist/util/merge-json.js.map +1 -0
  54. package/dist/vault/find-usable-handoff.d.ts +19 -0
  55. package/dist/vault/find-usable-handoff.d.ts.map +1 -0
  56. package/dist/vault/find-usable-handoff.js +28 -0
  57. package/dist/vault/find-usable-handoff.js.map +1 -0
  58. package/package.json +1 -1
  59. package/templates/agents/claude/commands/grounder-task.md +4 -4
  60. package/templates/agents/cursor/commands/grounder-task.md +4 -4
@@ -14,7 +14,13 @@ export interface AgentAdapter {
14
14
  readonly name: string;
15
15
  /** Returns true when this agent appears to be installed on the machine. */
16
16
  isInstalled(): Promise<boolean>;
17
+ /** Absolute paths of artifacts this adapter installs (read-only inspect). */
18
+ expectedArtifacts(homeDir?: string): string[];
17
19
  /** Install all agent-specific artifacts (commands, rules, etc.). */
18
20
  install(opts: AgentInstallOptions): Promise<AgentInstallResult>;
21
+ /** Optional: install session hooks (separate from slash-command install). */
22
+ installHooks?(opts: AgentInstallOptions): Promise<AgentInstallResult>;
23
+ /** Optional: absolute path(s) of hook config this adapter would touch. */
24
+ expectedHookArtifacts?(homeDir?: string): string[];
19
25
  }
20
26
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAEnE,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,oEAAoE;IACpE,OAAO,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACjE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAEnE,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,6EAA6E;IAC7E,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC9C,oEAAoE;IACpE,OAAO,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAChE,6EAA6E;IAC7E,YAAY,CAAC,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtE,0EAA0E;IAC1E,qBAAqB,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACpD"}
package/dist/cli.js CHANGED
@@ -2,12 +2,15 @@
2
2
  import { readFileSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
+ import { runDoctor } from "./commands/doctor.js";
5
6
  import { runHandoffList } from "./commands/handoff/list.js";
7
+ import { runHandoffPeek } from "./commands/handoff/peek.js";
6
8
  import { runHandoff } from "./commands/handoff.js";
7
9
  import { runNote } from "./commands/note.js";
8
10
  import { runPathLogs } from "./commands/path/logs.js";
9
11
  import { runPathNotes } from "./commands/path/notes.js";
10
12
  import { runRepoInit } from "./commands/repo/init.js";
13
+ import { runStatus } from "./commands/status.js";
11
14
  import { runVaultInit } from "./commands/vault/init.js";
12
15
  const pkgRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
13
16
  const pkg = JSON.parse(readFileSync(path.join(pkgRoot, "package.json"), "utf8"));
@@ -19,8 +22,14 @@ Usage:
19
22
  grounder note <text> Write a note to the vault
20
23
  grounder handoff <text> Write a session handoff to vault logs/
21
24
  grounder handoff list Print recent handoff paths (newest first)
25
+ grounder handoff list --head Print only the newest usable handoff path
22
26
  grounder path notes Print resolved notes directory
23
27
  grounder path logs Print resolved logs directory
28
+ grounder status Snapshot of machine + project link + resolved paths
29
+ grounder doctor Health checks with fix hints
30
+
31
+ Hook plumbing:
32
+ grounder handoff peek One-line latest-handoff teaser (used by session hooks)
24
33
 
25
34
  Options:
26
35
  -h, --help Show this help
@@ -33,13 +42,19 @@ Init flags:
33
42
  --vault <path> Override home vault root for this run (grounder init)
34
43
  --agent <id> Install for a specific agent (repeatable; default: auto-detect)
35
44
  Supported: cursor, claude
45
+ --hooks Also install session-start teaser hooks (vault init)
46
+
47
+ Doctor flags:
48
+ --global Machine-only checks (skip project/link checks)
36
49
 
37
50
  Note / handoff flags:
38
51
  --title <slug> Short slug in filename (default: slugified first line)
39
52
  --limit <n> Max paths for handoff list (default: 5)
53
+ --head With handoff list, print only the newest usable path
54
+ (skips empty/unreadable files; same pick as handoff peek)
40
55
 
41
56
  Quickstart:
42
- grounder vault init ~/Documents/obsidian/dev
57
+ grounder vault init <path-to-your-vault>
43
58
  grounder init
44
59
  grounder note "my first note"
45
60
  grounder handoff "# Handoff\\n\\n## Next\\n1. …"
@@ -74,6 +89,9 @@ async function main() {
74
89
  if (command === "handoff" && rest[0] === "list") {
75
90
  process.exit(await runHandoffList(rest.slice(1)));
76
91
  }
92
+ if (command === "handoff" && rest[0] === "peek") {
93
+ process.exit(await runHandoffPeek(rest.slice(1)));
94
+ }
77
95
  if (command === "handoff") {
78
96
  process.exit(await runHandoff(rest));
79
97
  }
@@ -83,6 +101,12 @@ async function main() {
83
101
  if (command === "path" && rest[0] === "logs") {
84
102
  process.exit(await runPathLogs(rest.slice(1)));
85
103
  }
104
+ if (command === "status") {
105
+ process.exit(await runStatus(rest));
106
+ }
107
+ if (command === "doctor") {
108
+ process.exit(await runDoctor(rest));
109
+ }
86
110
  process.stderr.write(`Unknown command: ${args.join(" ")}\n\n`);
87
111
  printHelp();
88
112
  process.exit(1);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AACjF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAE9E,CAAC;AAEF,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Cb,CAAC;AAEF,SAAS,SAAS;IAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,YAAY;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;QAClE,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC;QAChD,YAAY,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEhC,IAAI,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/D,SAAS,EAAE,CAAC;IACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /** Shared result shape for doctor (and similar) health checks. */
2
+ export type CheckLevel = "ok" | "fail" | "warn";
3
+ export interface CheckResult {
4
+ id: string;
5
+ level: CheckLevel;
6
+ message: string;
7
+ /** Actionable fix hint when level is not `"ok"`. */
8
+ fix?: string;
9
+ }
10
+ export declare function okCheck(id: string, message: string): CheckResult;
11
+ export declare function failCheck(id: string, message: string, fix?: string): CheckResult;
12
+ export declare function warnCheck(id: string, message: string, fix?: string): CheckResult;
13
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAElE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAEhE;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAOhF;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAOhF"}
@@ -0,0 +1,21 @@
1
+ /** Shared result shape for doctor (and similar) health checks. */
2
+ export function okCheck(id, message) {
3
+ return { id, level: "ok", message };
4
+ }
5
+ export function failCheck(id, message, fix) {
6
+ return {
7
+ id,
8
+ level: "fail",
9
+ message,
10
+ ...(fix !== undefined ? { fix } : {}),
11
+ };
12
+ }
13
+ export function warnCheck(id, message, fix) {
14
+ return {
15
+ id,
16
+ level: "warn",
17
+ message,
18
+ ...(fix !== undefined ? { fix } : {}),
19
+ };
20
+ }
21
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAYlE,MAAM,UAAU,OAAO,CAAC,EAAU,EAAE,OAAe;IACjD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAU,EAAE,OAAe,EAAE,GAAY;IACjE,OAAO;QACL,EAAE;QACF,KAAK,EAAE,MAAM;QACb,OAAO;QACP,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAU,EAAE,OAAe,EAAE,GAAY;IACjE,OAAO;QACL,EAAE;QACF,KAAK,EAAE,MAAM;QACb,OAAO;QACP,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface DoctorOptions {
2
+ cwd?: string;
3
+ homeDir?: string;
4
+ /** Machine-only checks (skip project/link checks). */
5
+ global?: boolean;
6
+ }
7
+ export declare function runDoctor(argv: string[]): Promise<number>;
8
+ export declare function runDoctorWithOptions(options?: DoctorOptions): Promise<number>;
9
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAyTD,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/D;AAED,wBAAsB,oBAAoB,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBvF"}
@@ -0,0 +1,270 @@
1
+ import { readFile, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { isGrounderPeekHookCommand, isHookRuntimeStale } from "../agents/hook-runtime.js";
4
+ import { resolveAgents } from "../agents/index.js";
5
+ import { findGitRoot } from "../connector/git.js";
6
+ import { homeConfigPath, readHomeConfig, withHomeDir } from "../connector/home.js";
7
+ import { findLinkedRepoRoot, readRepoConfig } from "../connector/repo.js";
8
+ import { resolveLogsDir, resolveNotesDir, resolveVaultRoot } from "../connector/vault.js";
9
+ import { fileExists } from "../util/fs.js";
10
+ import { flagBool, parseArgs } from "../util/parse-args.js";
11
+ import { projectsParent } from "../vault/layout.js";
12
+ import { failCheck, okCheck, warnCheck } from "./check.js";
13
+ const VAULT_INIT = "grounder vault init <path>";
14
+ const VAULT_INIT_FORCE = "grounder vault init <path> --force";
15
+ const VAULT_INIT_HOOKS = "grounder vault init <path> --hooks";
16
+ const REPO_INIT = "grounder init";
17
+ async function isDirectory(dirPath) {
18
+ try {
19
+ const info = await stat(dirPath);
20
+ return info.isDirectory();
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ function formatCheck(check) {
27
+ const level = check.level.padEnd(4);
28
+ const id = check.id.padEnd(18);
29
+ const fix = check.fix ? ` → ${check.fix}` : "";
30
+ return ` ${level} ${id} ${check.message}${fix}\n`;
31
+ }
32
+ function writeSection(title, checks) {
33
+ process.stdout.write(`${title}\n`);
34
+ for (const check of checks) {
35
+ process.stdout.write(formatCheck(check));
36
+ }
37
+ }
38
+ function summarize(checks) {
39
+ const passed = checks.filter((c) => c.level === "ok").length;
40
+ const failed = checks.filter((c) => c.level === "fail").length;
41
+ const warned = checks.filter((c) => c.level === "warn").length;
42
+ return `${passed} passed, ${failed} failed, ${warned} warned\n`;
43
+ }
44
+ async function checkHomeConfig() {
45
+ const configPath = homeConfigPath();
46
+ if (!(await fileExists(configPath))) {
47
+ return {
48
+ check: failCheck("home-config", "home config missing", VAULT_INIT),
49
+ home: null,
50
+ };
51
+ }
52
+ try {
53
+ const home = await readHomeConfig();
54
+ if (!home) {
55
+ return {
56
+ check: failCheck("home-config", "home config missing", VAULT_INIT),
57
+ home: null,
58
+ };
59
+ }
60
+ return {
61
+ check: okCheck("home-config", `home config present (${configPath})`),
62
+ home,
63
+ };
64
+ }
65
+ catch (error) {
66
+ const detail = error instanceof Error ? error.message : String(error);
67
+ return {
68
+ check: failCheck("home-config", `home config invalid: ${detail}`, VAULT_INIT),
69
+ home: null,
70
+ };
71
+ }
72
+ }
73
+ async function checkVault(home) {
74
+ if (!home) {
75
+ return {
76
+ check: failCheck("vault", "cannot resolve vault (no home config)", VAULT_INIT),
77
+ vaultRoot: null,
78
+ };
79
+ }
80
+ const vaultRoot = resolveVaultRoot(home);
81
+ if (!(await isDirectory(vaultRoot))) {
82
+ return {
83
+ check: failCheck("vault", `${vaultRoot} missing or not a directory`, "Fix path or re-run vault init"),
84
+ vaultRoot: null,
85
+ };
86
+ }
87
+ return {
88
+ check: okCheck("vault", `vault reachable (${vaultRoot})`),
89
+ vaultRoot,
90
+ };
91
+ }
92
+ async function checkProjectsDir(vaultRoot) {
93
+ if (!vaultRoot) {
94
+ return failCheck("projects-dir", "cannot check 10-Projects/ (no vault)", VAULT_INIT);
95
+ }
96
+ const projectsDir = projectsParent(vaultRoot);
97
+ if (!(await isDirectory(projectsDir))) {
98
+ return failCheck("projects-dir", `${projectsDir} missing`, `${VAULT_INIT} (idempotent)`);
99
+ }
100
+ return okCheck("projects-dir", `10-Projects/ present (${projectsDir})`);
101
+ }
102
+ async function checkAgentArtifacts(homeDir) {
103
+ const agents = await resolveAgents();
104
+ const checks = [];
105
+ for (const agent of agents) {
106
+ const expected = agent.expectedArtifacts(homeDir);
107
+ const present = await Promise.all(expected.map((p) => fileExists(p)));
108
+ const presentCount = present.filter(Boolean).length;
109
+ const id = `agent-${agent.id}`;
110
+ if (presentCount === expected.length) {
111
+ checks.push(okCheck(id, `${agent.name} command files present`));
112
+ continue;
113
+ }
114
+ const fix = `${VAULT_INIT_FORCE} (or --agent=${agent.id})`;
115
+ if (presentCount === 0) {
116
+ checks.push(warnCheck(id, `${agent.name} detected but no Grounder command files`, fix));
117
+ }
118
+ else {
119
+ const missing = expected.filter((_, i) => !present[i]);
120
+ checks.push(failCheck(id, `${agent.name} missing ${missing.length} command file(s): ${missing.map((p) => path.basename(p)).join(", ")}`, fix));
121
+ }
122
+ }
123
+ return checks;
124
+ }
125
+ /** True when any nested `command` field is Grounder's peek hook (Cursor or Claude shape). */
126
+ function jsonContainsGrounderPeekCommand(value) {
127
+ if (Array.isArray(value)) {
128
+ return value.some(jsonContainsGrounderPeekCommand);
129
+ }
130
+ if (value && typeof value === "object") {
131
+ const obj = value;
132
+ if (isGrounderPeekHookCommand(obj.command)) {
133
+ return true;
134
+ }
135
+ return Object.values(obj).some(jsonContainsGrounderPeekCommand);
136
+ }
137
+ return false;
138
+ }
139
+ async function hookFileHasGrounderEntry(filePath) {
140
+ try {
141
+ if (!(await fileExists(filePath))) {
142
+ return false;
143
+ }
144
+ const parsed = JSON.parse(await readFile(filePath, "utf8"));
145
+ return jsonContainsGrounderPeekCommand(parsed);
146
+ }
147
+ catch {
148
+ return false;
149
+ }
150
+ }
151
+ /**
152
+ * Warn-only: session hooks are opt-in. Missing entry never fails doctor.
153
+ * One check per detected agent that declares `expectedHookArtifacts`.
154
+ *
155
+ * When at least one agent has a Grounder hook installed, also check the shared
156
+ * `~/.grounder/runtime` materialization — stale mainly for bare-npx copy installs
157
+ * after an upgrade (symlink installs stay current without re-init).
158
+ */
159
+ async function checkAgentHooks(homeDir) {
160
+ const agents = await resolveAgents();
161
+ const checks = [];
162
+ let anyHooksInstalled = false;
163
+ for (const agent of agents) {
164
+ if (!agent.expectedHookArtifacts) {
165
+ continue;
166
+ }
167
+ const expected = agent.expectedHookArtifacts(homeDir);
168
+ const present = await Promise.all(expected.map((p) => hookFileHasGrounderEntry(p)));
169
+ const id = `agent-${agent.id}-hooks`;
170
+ if (present.every(Boolean) && expected.length > 0) {
171
+ anyHooksInstalled = true;
172
+ checks.push(okCheck(id, `${agent.name} session hook installed`));
173
+ }
174
+ else {
175
+ checks.push(warnCheck(id, `${agent.name} detected but no Grounder session hook`, VAULT_INIT_HOOKS));
176
+ }
177
+ }
178
+ if (anyHooksInstalled) {
179
+ if (await isHookRuntimeStale(homeDir)) {
180
+ checks.push(warnCheck("hook-runtime", "hook runtime stale or missing (re-run after upgrading, especially bare npx)", VAULT_INIT_HOOKS));
181
+ }
182
+ else {
183
+ checks.push(okCheck("hook-runtime", "hook runtime current"));
184
+ }
185
+ }
186
+ return checks;
187
+ }
188
+ async function runMachineChecks(homeDir) {
189
+ const { check: homeCheck, home } = await checkHomeConfig();
190
+ const { check: vaultCheck, vaultRoot } = await checkVault(home);
191
+ const projectsCheck = await checkProjectsDir(vaultRoot);
192
+ const agentChecks = await checkAgentArtifacts(homeDir);
193
+ const hookChecks = await checkAgentHooks(homeDir);
194
+ return {
195
+ checks: [homeCheck, vaultCheck, projectsCheck, ...agentChecks, ...hookChecks],
196
+ home,
197
+ };
198
+ }
199
+ async function runProjectChecks(cwd, home) {
200
+ const checks = [];
201
+ const gitRoot = await findGitRoot(cwd);
202
+ const linkedRoot = await findLinkedRepoRoot(cwd, gitRoot);
203
+ if (!linkedRoot) {
204
+ checks.push(failCheck("repo-config", "no .grounder.json uptree", REPO_INIT));
205
+ checks.push(failCheck("repo-config-valid", "cannot validate projectId (no repo config)", REPO_INIT));
206
+ checks.push(failCheck("notes-dir", "cannot resolve notes/ (no repo config)", REPO_INIT));
207
+ checks.push(failCheck("logs-dir", "cannot resolve logs/ (no repo config)", REPO_INIT));
208
+ }
209
+ else {
210
+ checks.push(okCheck("repo-config", `repo config present (${path.join(linkedRoot, ".grounder.json")})`));
211
+ let repo = null;
212
+ try {
213
+ repo = await readRepoConfig(linkedRoot);
214
+ if (!repo) {
215
+ checks.push(failCheck("repo-config-valid", "missing or invalid projectId", `Fix or re-run ${REPO_INIT} --force`));
216
+ }
217
+ else {
218
+ checks.push(okCheck("repo-config-valid", `projectId ok (${repo.projectId})`));
219
+ }
220
+ }
221
+ catch (error) {
222
+ const detail = error instanceof Error ? error.message : String(error);
223
+ checks.push(failCheck("repo-config-valid", `invalid repo config: ${detail}`, `Fix or re-run ${REPO_INIT} --force`));
224
+ }
225
+ if (!home || !repo) {
226
+ const reason = !home ? "no home config" : "no valid repo config";
227
+ const fix = !home ? VAULT_INIT : REPO_INIT;
228
+ checks.push(failCheck("notes-dir", `cannot resolve notes/ (${reason})`, fix));
229
+ checks.push(failCheck("logs-dir", `cannot resolve logs/ (${reason})`, fix));
230
+ }
231
+ else {
232
+ const notes = resolveNotesDir(home, repo);
233
+ const logs = resolveLogsDir(home, repo);
234
+ checks.push((await isDirectory(notes))
235
+ ? okCheck("notes-dir", `notes/ present (${notes})`)
236
+ : failCheck("notes-dir", `${notes} missing`, `${REPO_INIT} (creates dirs)`));
237
+ checks.push((await isDirectory(logs))
238
+ ? okCheck("logs-dir", `logs/ present (${logs})`)
239
+ : failCheck("logs-dir", `${logs} missing`, REPO_INIT));
240
+ }
241
+ }
242
+ if (!gitRoot) {
243
+ checks.push(warnCheck("git", "no git repository found (optional)"));
244
+ }
245
+ else {
246
+ checks.push(okCheck("git", `git root (${gitRoot})`));
247
+ }
248
+ return checks;
249
+ }
250
+ export async function runDoctor(argv) {
251
+ const { flags } = parseArgs(argv);
252
+ return runDoctorWithOptions({ global: flagBool(flags, "global") });
253
+ }
254
+ export async function runDoctorWithOptions(options = {}) {
255
+ return withHomeDir(options.homeDir, async () => {
256
+ const cwd = path.resolve(options.cwd ?? process.cwd());
257
+ const { checks: machineChecks, home } = await runMachineChecks(options.homeDir);
258
+ const projectChecks = options.global ? [] : await runProjectChecks(cwd, home);
259
+ const checks = [...machineChecks, ...projectChecks];
260
+ writeSection("Machine", machineChecks);
261
+ if (!options.global) {
262
+ process.stdout.write("\n");
263
+ writeSection("Project", projectChecks);
264
+ }
265
+ process.stdout.write("\n");
266
+ process.stdout.write(summarize(checks));
267
+ return checks.some((c) => c.level === "fail") ? 1 : 0;
268
+ });
269
+ }
270
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,12 @@ export interface HandoffListOptions {
4
4
  cwd?: string;
5
5
  /** Max paths to print, newest first (default: 5). */
6
6
  limit?: number;
7
+ /**
8
+ * Print only the single newest *usable* handoff path (skips empty/unreadable
9
+ * files), same selection `grounder handoff peek` uses. Ignores `limit` for
10
+ * output count but still bounds the fallback scan.
11
+ */
12
+ head?: boolean;
7
13
  /** Override home dir / `GROUNDER_HOME` (tests). */
8
14
  homeDir?: string;
9
15
  }
@@ -17,6 +23,9 @@ export declare function runHandoffList(argv: string[]): Promise<number>;
17
23
  * Resolves the linked project, lists recent handoff paths under `logs/` (newest first).
18
24
  * Prints one absolute path per line; empty when no handoffs. Same vault/link
19
25
  * prerequisites as `grounder handoff`.
26
+ * With `head: true`, prints only the single newest *usable* handoff path — see
27
+ * {@link findUsableHandoff}. This is the selection `/grounder-task` should read,
28
+ * matching what `grounder handoff peek` teases.
20
29
  * @returns Exit code (`0` on success, `1` when vault/link is missing).
21
30
  */
22
31
  export declare function runHandoffListWithOptions(options?: HandoffListOptions): Promise<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/handoff/list.ts"],"names":[],"mappings":"AAQA,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AASD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BpE;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBjG"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/handoff/list.ts"],"names":[],"mappings":"AASA,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AASD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BpE;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BjG"}
@@ -1,10 +1,11 @@
1
1
  import { withHomeDir } from "../../connector/home.js";
2
2
  import { resolveLogsDir } from "../../connector/vault.js";
3
- import { parseArgs } from "../../util/parse-args.js";
3
+ import { flagBool, parseArgs } from "../../util/parse-args.js";
4
+ import { findUsableHandoff } from "../../vault/find-usable-handoff.js";
4
5
  import { listHandoffs } from "../../vault/list-handoffs.js";
5
6
  import { requireLinkedProject } from "../require-linked.js";
6
7
  const DEFAULT_LIMIT = 5;
7
- const USAGE = "Usage: grounder handoff list [--limit <n>]\n";
8
+ const USAGE = "Usage: grounder handoff list [--limit <n>] [--head]\n";
8
9
  function usageError() {
9
10
  process.stderr.write(USAGE);
10
11
  return 1;
@@ -20,7 +21,7 @@ export async function runHandoffList(argv) {
20
21
  return usageError();
21
22
  }
22
23
  for (const key of flags.keys()) {
23
- if (key !== "limit") {
24
+ if (key !== "limit" && key !== "head") {
24
25
  return usageError();
25
26
  }
26
27
  }
@@ -37,12 +38,15 @@ export async function runHandoffList(argv) {
37
38
  }
38
39
  limit = parsed;
39
40
  }
40
- return runHandoffListWithOptions({ limit });
41
+ return runHandoffListWithOptions({ limit, head: flagBool(flags, "head") });
41
42
  }
42
43
  /**
43
44
  * Resolves the linked project, lists recent handoff paths under `logs/` (newest first).
44
45
  * Prints one absolute path per line; empty when no handoffs. Same vault/link
45
46
  * prerequisites as `grounder handoff`.
47
+ * With `head: true`, prints only the single newest *usable* handoff path — see
48
+ * {@link findUsableHandoff}. This is the selection `/grounder-task` should read,
49
+ * matching what `grounder handoff peek` teases.
46
50
  * @returns Exit code (`0` on success, `1` when vault/link is missing).
47
51
  */
48
52
  export async function runHandoffListWithOptions(options = {}) {
@@ -52,6 +56,13 @@ export async function runHandoffListWithOptions(options = {}) {
52
56
  return 1;
53
57
  }
54
58
  const logsDir = resolveLogsDir(linked.home, linked.repo);
59
+ if (options.head) {
60
+ const usable = await findUsableHandoff(logsDir, { limit: options.limit ?? DEFAULT_LIMIT });
61
+ if (usable) {
62
+ process.stdout.write(`${usable.path}\n`);
63
+ }
64
+ return 0;
65
+ }
55
66
  const paths = await listHandoffs(logsDir, {
56
67
  limit: options.limit ?? DEFAULT_LIMIT,
57
68
  });
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/handoff/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,aAAa,GAAG,CAAC,CAAC;AAYxB,MAAM,KAAK,GAAG,8CAA8C,CAAC;AAE7D,SAAS,UAAU;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAc;IACjD,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,UAAU,EAAE,CAAC;IACtB,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/B,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACpB,OAAO,UAAU,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,KAAK,GAAG,aAAa,CAAC;IAC1B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO,UAAU,EAAE,CAAC;QACtB,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACjE,OAAO,UAAU,EAAE,CAAC;QACtB,CAAC;QACD,KAAK,GAAG,MAAM,CAAC;IACjB,CAAC;IAED,OAAO,yBAAyB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,UAA8B,EAAE;IAC9E,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE;YACxC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,aAAa;SACtC,CAAC,CAAC;QAEH,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;YAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/handoff/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,aAAa,GAAG,CAAC,CAAC;AAkBxB,MAAM,KAAK,GAAG,uDAAuD,CAAC;AAEtE,SAAS,UAAU;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5B,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAc;IACjD,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,UAAU,EAAE,CAAC;IACtB,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/B,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACtC,OAAO,UAAU,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,KAAK,GAAG,aAAa,CAAC;IAC1B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO,UAAU,EAAE,CAAC;QACtB,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACjE,OAAO,UAAU,EAAE,CAAC;QACtB,CAAC;QACD,KAAK,GAAG,MAAM,CAAC;IACjB,CAAC;IAED,OAAO,yBAAyB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,UAA8B,EAAE;IAC9E,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAEzD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,aAAa,EAAE,CAAC,CAAC;YAC3F,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;YAC3C,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE;YACxC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,aAAa;SACtC,CAAC,CAAC;QAEH,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;YAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,38 @@
1
+ /** Options for {@link runHandoffPeekWithOptions} (CLI and tests). */
2
+ export interface HandoffPeekOptions {
3
+ /** Directory used to find the linked repo (default: `process.cwd()`). */
4
+ cwd?: string;
5
+ /** Override home dir / `GROUNDER_HOME` (tests). */
6
+ homeDir?: string;
7
+ /**
8
+ * When true, always emit one JSON line for Cursor's `sessionStart` contract
9
+ * (`{ additional_context }` or `{}`). Default plain-text output is for Claude.
10
+ */
11
+ json?: boolean;
12
+ }
13
+ /**
14
+ * Derive a display label from a handoff filename when frontmatter has no title:
15
+ * strip the timestamp prefix and `.md`, replace `-` with spaces.
16
+ */
17
+ export declare function labelFromHandoffFilename(filePath: string): string;
18
+ /**
19
+ * CLI entry for `grounder handoff peek`.
20
+ * Silent by default: prints nothing and exits 0 when unlinked, empty, or on any error.
21
+ * Used by session-start hooks — must never crash or print noise.
22
+ * Reads Cursor hook stdin for `workspace_roots[0]` when present; falls back to
23
+ * `CURSOR_PROJECT_DIR` (user-level hooks often run with cwd under `~/.cursor`).
24
+ * Pass `--json` for Cursor's `additional_context` stdout contract.
25
+ * @returns Always `0`.
26
+ */
27
+ export declare function runHandoffPeek(argv: string[]): Promise<number>;
28
+ /**
29
+ * Resolves the linked project and prints a one-line teaser for the newest *usable*
30
+ * handoff, or nothing. "Usable" (via {@link findUsableHandoff}) skips empty/unreadable
31
+ * files and falls back to the next-newest — the same selection `grounder handoff list
32
+ * --head` uses, so the teaser and `/grounder-task` never disagree about which handoff
33
+ * is current.
34
+ * Uses {@link resolveLinkedProject} directly (not `requireLinkedProject`) so failures stay silent.
35
+ * @returns Always `0`.
36
+ */
37
+ export declare function runHandoffPeekWithOptions(options?: HandoffPeekOptions): Promise<number>;
38
+ //# sourceMappingURL=peek.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peek.d.ts","sourceRoot":"","sources":["../../../src/commands/handoff/peek.ts"],"names":[],"mappings":"AASA,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAKD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAWjE;AA4CD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAOpE;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BjG"}