grounder 0.1.0 → 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.
- package/README.md +44 -6
- package/dist/agents/claude.d.ts +14 -0
- package/dist/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +221 -1
- package/dist/agents/claude.js.map +1 -1
- package/dist/agents/cursor-hook-input.d.ts +14 -0
- package/dist/agents/cursor-hook-input.d.ts.map +1 -0
- package/dist/agents/cursor-hook-input.js +80 -0
- package/dist/agents/cursor-hook-input.js.map +1 -0
- package/dist/agents/cursor.d.ts +10 -0
- package/dist/agents/cursor.d.ts.map +1 -1
- package/dist/agents/cursor.js +171 -1
- package/dist/agents/cursor.js.map +1 -1
- package/dist/agents/hook-runtime.d.ts +108 -0
- package/dist/agents/hook-runtime.d.ts.map +1 -0
- package/dist/agents/hook-runtime.js +260 -0
- package/dist/agents/hook-runtime.js.map +1 -0
- package/dist/agents/types.d.ts +4 -0
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/cli.js +12 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +68 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/handoff/list.d.ts +9 -0
- package/dist/commands/handoff/list.d.ts.map +1 -1
- package/dist/commands/handoff/list.js +15 -4
- package/dist/commands/handoff/list.js.map +1 -1
- package/dist/commands/handoff/peek.d.ts +38 -0
- package/dist/commands/handoff/peek.d.ts.map +1 -0
- package/dist/commands/handoff/peek.js +120 -0
- package/dist/commands/handoff/peek.js.map +1 -0
- package/dist/commands/vault/init.d.ts +2 -0
- package/dist/commands/vault/init.d.ts.map +1 -1
- package/dist/commands/vault/init.js +28 -0
- package/dist/commands/vault/init.js.map +1 -1
- package/dist/util/frontmatter.d.ts +11 -0
- package/dist/util/frontmatter.d.ts.map +1 -0
- package/dist/util/frontmatter.js +69 -0
- package/dist/util/frontmatter.js.map +1 -0
- package/dist/util/merge-json.d.ts +15 -0
- package/dist/util/merge-json.d.ts.map +1 -0
- package/dist/util/merge-json.js +40 -0
- package/dist/util/merge-json.js.map +1 -0
- package/dist/vault/find-usable-handoff.d.ts +19 -0
- package/dist/vault/find-usable-handoff.d.ts.map +1 -0
- package/dist/vault/find-usable-handoff.js +28 -0
- package/dist/vault/find-usable-handoff.js.map +1 -0
- package/package.json +1 -1
- package/templates/agents/claude/commands/grounder-task.md +4 -4
- package/templates/agents/cursor/commands/grounder-task.md +4 -4
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unescape sequences produced by {@link yamlDoubleQuoted}: `\\`, `\"`, `\r`, `\n`.
|
|
3
|
+
*/
|
|
4
|
+
function unescapeYamlDoubleQuoted(value) {
|
|
5
|
+
let result = "";
|
|
6
|
+
for (let i = 0; i < value.length; i++) {
|
|
7
|
+
if (value[i] === "\\" && i + 1 < value.length) {
|
|
8
|
+
const next = value[i + 1];
|
|
9
|
+
if (next === "\\" || next === '"') {
|
|
10
|
+
result += next;
|
|
11
|
+
i++;
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (next === "n") {
|
|
15
|
+
result += "\n";
|
|
16
|
+
i++;
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (next === "r") {
|
|
20
|
+
result += "\r";
|
|
21
|
+
i++;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
result += value[i];
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parse `title` / `created` from Grounder handoff frontmatter.
|
|
31
|
+
* Accepts the quoted `key: "value"` shape {@link writeHandoff} writes today, and
|
|
32
|
+
* unquoted `key: value` from earlier handoffs. Not a general YAML parser.
|
|
33
|
+
* Returns `{}` on anything unexpected; never throws.
|
|
34
|
+
*/
|
|
35
|
+
export function parseHandoffFrontmatter(content) {
|
|
36
|
+
try {
|
|
37
|
+
const lines = content.split(/\r?\n/);
|
|
38
|
+
if (lines[0] !== "---") {
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
const result = {};
|
|
42
|
+
for (let i = 1; i < lines.length; i++) {
|
|
43
|
+
const line = lines[i] ?? "";
|
|
44
|
+
if (line === "---") {
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
const quoted = /^(title|created):\s*"(.*)"\s*$/.exec(line);
|
|
48
|
+
if (quoted) {
|
|
49
|
+
const key = quoted[1];
|
|
50
|
+
result[key] = unescapeYamlDoubleQuoted(quoted[2] ?? "");
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// Opening quote without a closing pair — ignore rather than treat as unquoted.
|
|
54
|
+
if (/^(title|created):\s*"/.test(line)) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const unquoted = /^(title|created):\s*(.+?)\s*$/.exec(line);
|
|
58
|
+
if (unquoted) {
|
|
59
|
+
const key = unquoted[1];
|
|
60
|
+
result[key] = unquoted[2] ?? "";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return {};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=frontmatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/util/frontmatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,SAAS,wBAAwB,CAAC,KAAa;IAC7C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBAClC,MAAM,IAAI,IAAI,CAAC;gBACf,CAAC,EAAE,CAAC;gBACJ,SAAS;YACX,CAAC;YACD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjB,MAAM,IAAI,IAAI,CAAC;gBACf,CAAC,EAAE,CAAC;gBACJ,SAAS;YACX,CAAC;YACD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjB,MAAM,IAAI,IAAI,CAAC;gBACf,CAAC,EAAE,CAAC;gBACJ,SAAS;YACX,CAAC;QACH,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAe;IACrD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,MAAM,GAAyC,EAAE,CAAC;QACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACnB,MAAM;YACR,CAAC;YAED,MAAM,MAAM,GAAG,gCAAgC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3D,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAwB,CAAC;gBAC7C,MAAM,CAAC,GAAG,CAAC,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBACxD,SAAS;YACX,CAAC;YAED,+EAA+E;YAC/E,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvC,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAwB,CAAC;gBAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAClC,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type MergeJsonResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
created: boolean;
|
|
4
|
+
} | {
|
|
5
|
+
ok: false;
|
|
6
|
+
error: "unparseable";
|
|
7
|
+
message: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Read a JSON object file (default `{}` if missing), apply `merge`, write pretty-printed.
|
|
11
|
+
* On parse failure or non-object root: leaves the file untouched and returns an error
|
|
12
|
+
* so callers can warn without clobbering shared config.
|
|
13
|
+
*/
|
|
14
|
+
export declare function mergeJsonFile(filePath: string, merge: (current: Record<string, unknown>) => Record<string, unknown>): Promise<MergeJsonResult>;
|
|
15
|
+
//# sourceMappingURL=merge-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-json.d.ts","sourceRoot":"","sources":["../../src/util/merge-json.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnE,OAAO,CAAC,eAAe,CAAC,CAiC1B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileExists } from "./fs.js";
|
|
4
|
+
/**
|
|
5
|
+
* Read a JSON object file (default `{}` if missing), apply `merge`, write pretty-printed.
|
|
6
|
+
* On parse failure or non-object root: leaves the file untouched and returns an error
|
|
7
|
+
* so callers can warn without clobbering shared config.
|
|
8
|
+
*/
|
|
9
|
+
export async function mergeJsonFile(filePath, merge) {
|
|
10
|
+
const existed = await fileExists(filePath);
|
|
11
|
+
let current = {};
|
|
12
|
+
if (existed) {
|
|
13
|
+
const raw = await readFile(filePath, "utf8");
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = JSON.parse(raw);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
error: "unparseable",
|
|
23
|
+
message: `Refusing to modify ${filePath}: invalid JSON (${detail})`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
27
|
+
return {
|
|
28
|
+
ok: false,
|
|
29
|
+
error: "unparseable",
|
|
30
|
+
message: `Refusing to modify ${filePath}: root value must be a JSON object`,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
current = parsed;
|
|
34
|
+
}
|
|
35
|
+
const next = merge(current);
|
|
36
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
37
|
+
await writeFile(filePath, `${JSON.stringify(next, null, 2)}\n`, "utf8");
|
|
38
|
+
return { ok: true, created: !existed };
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=merge-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-json.js","sourceRoot":"","sources":["../../src/util/merge-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAMrC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,KAAoE;IAEpE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,OAAO,GAA4B,EAAE,CAAC;IAE1C,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC7C,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAChE,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,aAAa;gBACpB,OAAO,EAAE,sBAAsB,QAAQ,mBAAmB,MAAM,GAAG;aACpE,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3E,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,aAAa;gBACpB,OAAO,EAAE,sBAAsB,QAAQ,oCAAoC;aAC5E,CAAC;QACJ,CAAC;QAED,OAAO,GAAG,MAAiC,CAAC;IAC9C,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,SAAS,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface FindUsableHandoffOptions {
|
|
2
|
+
/** Max newest-first candidates to scan (default: 5). */
|
|
3
|
+
limit?: number;
|
|
4
|
+
}
|
|
5
|
+
export interface UsableHandoff {
|
|
6
|
+
/** Absolute path of the resolved handoff file. */
|
|
7
|
+
path: string;
|
|
8
|
+
/** Already-read file contents (avoids a second read by callers). */
|
|
9
|
+
content: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolves the newest-first handoff under `logsDir` that actually has content,
|
|
13
|
+
* skipping empty or unreadable files along the way (e.g. an interrupted write).
|
|
14
|
+
* Single source of truth for "which handoff is current" — shared by
|
|
15
|
+
* `grounder handoff peek` and `grounder handoff list --head` so both agree.
|
|
16
|
+
* Returns `undefined` when no candidate within the scan window is usable.
|
|
17
|
+
*/
|
|
18
|
+
export declare function findUsableHandoff(logsDir: string, options?: FindUsableHandoffOptions): Promise<UsableHandoff | undefined>;
|
|
19
|
+
//# sourceMappingURL=find-usable-handoff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-usable-handoff.d.ts","sourceRoot":"","sources":["../../src/vault/find-usable-handoff.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,wBAAwB;IACvC,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAcpC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { listHandoffs } from "./list-handoffs.js";
|
|
3
|
+
/** Newest-first candidates scanned for a usable handoff before giving up. */
|
|
4
|
+
const DEFAULT_SCAN_LIMIT = 5;
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the newest-first handoff under `logsDir` that actually has content,
|
|
7
|
+
* skipping empty or unreadable files along the way (e.g. an interrupted write).
|
|
8
|
+
* Single source of truth for "which handoff is current" — shared by
|
|
9
|
+
* `grounder handoff peek` and `grounder handoff list --head` so both agree.
|
|
10
|
+
* Returns `undefined` when no candidate within the scan window is usable.
|
|
11
|
+
*/
|
|
12
|
+
export async function findUsableHandoff(logsDir, options = {}) {
|
|
13
|
+
const paths = await listHandoffs(logsDir, { limit: options.limit ?? DEFAULT_SCAN_LIMIT });
|
|
14
|
+
for (const filePath of paths) {
|
|
15
|
+
let content;
|
|
16
|
+
try {
|
|
17
|
+
content = await readFile(filePath, "utf8");
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (content.trim().length > 0) {
|
|
23
|
+
return { path: filePath, content };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=find-usable-handoff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-usable-handoff.js","sourceRoot":"","sources":["../../src/vault/find-usable-handoff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,6EAA6E;AAC7E,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAc7B;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAe,EACf,UAAoC,EAAE;IAEtC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,kBAAkB,EAAE,CAAC,CAAC;IAC1F,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/package.json
CHANGED
|
@@ -4,13 +4,13 @@ Read-only — do not write to the vault. Do not invent vault paths.
|
|
|
4
4
|
|
|
5
5
|
From the linked project folder or any subdirectory beneath it:
|
|
6
6
|
|
|
7
|
-
1.
|
|
7
|
+
1. Get the current handoff (skips empty/unreadable files, same pick as the session-start teaser):
|
|
8
8
|
|
|
9
|
-
npx grounder handoff list --
|
|
9
|
+
npx grounder handoff list --head
|
|
10
10
|
|
|
11
|
-
2. If
|
|
11
|
+
2. If empty: tell the user there are no handoffs yet, then read repo `AGENTS.md` only and proceed.
|
|
12
12
|
|
|
13
|
-
3.
|
|
13
|
+
3. Otherwise, read that file. If the user names a specific session instead, run `npx grounder handoff list --limit 5` and read the path they mean.
|
|
14
14
|
|
|
15
15
|
4. Read repo `AGENTS.md` (project conventions and constraints).
|
|
16
16
|
|
|
@@ -4,13 +4,13 @@ Read-only — do not write to the vault. Do not invent vault paths.
|
|
|
4
4
|
|
|
5
5
|
From the linked project folder or any subdirectory beneath it:
|
|
6
6
|
|
|
7
|
-
1.
|
|
7
|
+
1. Get the current handoff (skips empty/unreadable files, same pick as the session-start teaser):
|
|
8
8
|
|
|
9
|
-
npx grounder handoff list --
|
|
9
|
+
npx grounder handoff list --head
|
|
10
10
|
|
|
11
|
-
2. If
|
|
11
|
+
2. If empty: tell the user there are no handoffs yet, then read repo `AGENTS.md` only and proceed.
|
|
12
12
|
|
|
13
|
-
3.
|
|
13
|
+
3. Otherwise, read that file. If the user names a specific session instead, run `npx grounder handoff list --limit 5` and read the path they mean.
|
|
14
14
|
|
|
15
15
|
4. Read repo `AGENTS.md` (project conventions and constraints).
|
|
16
16
|
|