grounder 0.4.0 → 0.5.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 +148 -270
- package/dist/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +2 -1
- package/dist/agents/claude.js.map +1 -1
- package/dist/agents/cursor.d.ts.map +1 -1
- package/dist/agents/cursor.js +2 -1
- package/dist/agents/cursor.js.map +1 -1
- package/dist/agents/hook-runtime.d.ts +3 -3
- package/dist/agents/hook-runtime.js +4 -4
- package/dist/agents/hook-runtime.js.map +1 -1
- package/dist/cli.js +11 -10
- package/dist/cli.js.map +1 -1
- package/dist/commands/apply-agent-installs.d.ts +2 -2
- package/dist/commands/apply-agent-installs.d.ts.map +1 -1
- package/dist/commands/apply-agent-installs.js +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +7 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/handoff/list.d.ts +23 -13
- package/dist/commands/handoff/list.d.ts.map +1 -1
- package/dist/commands/handoff/list.js +28 -16
- package/dist/commands/handoff/list.js.map +1 -1
- package/dist/commands/handoff.d.ts +2 -0
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +10 -1
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/link.d.ts +12 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/{repo/init.js → link.js} +35 -27
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/migrate.js +3 -5
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/note/list.d.ts +17 -9
- package/dist/commands/note/list.d.ts.map +1 -1
- package/dist/commands/note/list.js +19 -14
- package/dist/commands/note/list.js.map +1 -1
- package/dist/commands/note.d.ts +2 -0
- package/dist/commands/note.d.ts.map +1 -1
- package/dist/commands/note.js +10 -1
- package/dist/commands/note.js.map +1 -1
- package/dist/commands/output.d.ts +22 -2
- package/dist/commands/output.d.ts.map +1 -1
- package/dist/commands/output.js +18 -6
- package/dist/commands/output.js.map +1 -1
- package/dist/commands/plan/list.d.ts +20 -12
- package/dist/commands/plan/list.d.ts.map +1 -1
- package/dist/commands/plan/list.js +22 -17
- package/dist/commands/plan/list.js.map +1 -1
- package/dist/commands/plan.d.ts +2 -0
- package/dist/commands/plan.d.ts.map +1 -1
- package/dist/commands/plan.js +12 -2
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/require-linked.js +2 -2
- package/dist/commands/require-linked.js.map +1 -1
- package/dist/commands/search.d.ts +23 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +277 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/{vault/init.d.ts → setup.d.ts} +5 -4
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +137 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +24 -15
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade-banner.d.ts +2 -2
- package/dist/commands/upgrade-banner.js +2 -2
- package/dist/connector/home.d.ts +12 -0
- package/dist/connector/home.d.ts.map +1 -1
- package/dist/connector/home.js +26 -2
- package/dist/connector/home.js.map +1 -1
- package/dist/connector/state.d.ts +1 -1
- package/dist/connector/state.d.ts.map +1 -1
- package/dist/connector/vault.d.ts +2 -0
- package/dist/connector/vault.d.ts.map +1 -1
- package/dist/connector/vault.js +6 -1
- package/dist/connector/vault.js.map +1 -1
- package/dist/help.d.ts +3 -3
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +70 -51
- package/dist/help.js.map +1 -1
- package/dist/util/frontmatter.d.ts +9 -7
- package/dist/util/frontmatter.d.ts.map +1 -1
- package/dist/util/frontmatter.js +29 -4
- package/dist/util/frontmatter.js.map +1 -1
- package/dist/util/path.d.ts +23 -0
- package/dist/util/path.d.ts.map +1 -1
- package/dist/util/path.js +39 -0
- package/dist/util/path.js.map +1 -1
- package/dist/vault/list-handoffs.d.ts +3 -1
- package/dist/vault/list-handoffs.d.ts.map +1 -1
- package/dist/vault/list-handoffs.js +17 -15
- package/dist/vault/list-handoffs.js.map +1 -1
- package/dist/vault/list-markdown.d.ts +8 -0
- package/dist/vault/list-markdown.d.ts.map +1 -0
- package/dist/vault/list-markdown.js +35 -0
- package/dist/vault/list-markdown.js.map +1 -0
- package/dist/vault/list-notes.d.ts +5 -5
- package/dist/vault/list-notes.d.ts.map +1 -1
- package/dist/vault/list-notes.js +12 -22
- package/dist/vault/list-notes.js.map +1 -1
- package/dist/vault/list-plans.d.ts +2 -2
- package/dist/vault/list-plans.d.ts.map +1 -1
- package/dist/vault/list-plans.js +9 -19
- package/dist/vault/list-plans.js.map +1 -1
- package/dist/vault/search.d.ts +55 -0
- package/dist/vault/search.d.ts.map +1 -0
- package/dist/vault/search.js +328 -0
- package/dist/vault/search.js.map +1 -0
- package/dist/vault/write-handoff.d.ts +2 -0
- package/dist/vault/write-handoff.d.ts.map +1 -1
- package/dist/vault/write-handoff.js +5 -0
- package/dist/vault/write-handoff.js.map +1 -1
- package/dist/vault/write-note.d.ts +2 -0
- package/dist/vault/write-note.d.ts.map +1 -1
- package/dist/vault/write-note.js +9 -1
- package/dist/vault/write-note.js.map +1 -1
- package/dist/vault/write-plan.d.ts +4 -0
- package/dist/vault/write-plan.d.ts.map +1 -1
- package/dist/vault/write-plan.js +14 -1
- package/dist/vault/write-plan.js.map +1 -1
- package/package.json +10 -3
- package/templates/agents/claude/commands/grounder-note.md +6 -2
- package/templates/agents/claude/commands/grounder-plan.md +7 -5
- package/templates/agents/claude/commands/grounder-search.md +144 -0
- package/templates/agents/claude/commands/grounder-task-handoff.md +5 -1
- package/templates/agents/claude/commands/grounder-task.md +2 -2
- package/templates/agents/cursor/commands/grounder-note.md +6 -2
- package/templates/agents/cursor/commands/grounder-plan.md +7 -5
- package/templates/agents/cursor/commands/grounder-search.md +144 -0
- package/templates/agents/cursor/commands/grounder-task-handoff.md +5 -1
- package/templates/agents/cursor/commands/grounder-task.md +2 -2
- package/dist/commands/repo/init.d.ts +0 -11
- package/dist/commands/repo/init.d.ts.map +0 -1
- package/dist/commands/repo/init.js.map +0 -1
- package/dist/commands/vault/init.d.ts.map +0 -1
- package/dist/commands/vault/init.js +0 -90
- package/dist/commands/vault/init.js.map +0 -1
|
@@ -4,6 +4,8 @@ export interface WritePlanOptions {
|
|
|
4
4
|
projectId: string;
|
|
5
5
|
/** When true, overwrite an existing plan (preserving original `created`). */
|
|
6
6
|
force?: boolean;
|
|
7
|
+
/** 3-5 topic keywords for search (flat list, omitted when empty/unset). */
|
|
8
|
+
topics?: string[];
|
|
7
9
|
/** Timestamp for `created` / `updated` (default: now). */
|
|
8
10
|
now?: Date;
|
|
9
11
|
}
|
|
@@ -15,6 +17,7 @@ export interface WritePlanResult {
|
|
|
15
17
|
/**
|
|
16
18
|
* Overwrites an existing plan at an absolute path.
|
|
17
19
|
* Preserves original `created` (falls back to `now` if missing) and sets `updated`.
|
|
20
|
+
* Omitting `topics` keeps existing frontmatter topics; passing `topics` replaces them.
|
|
18
21
|
* Caller must validate the path (e.g. inside this project's `plans/` dir).
|
|
19
22
|
*/
|
|
20
23
|
export declare function updatePlanAtPath(filePath: string, body: string, options: Omit<WritePlanOptions, "force">): Promise<WritePlanResult>;
|
|
@@ -23,6 +26,7 @@ export declare function updatePlanAtPath(filePath: string, body: string, options
|
|
|
23
26
|
* Target is always `plansDir/<name>.md` — no collision suffixes.
|
|
24
27
|
* Without `force`, an existing file is left untouched and status `"exists"` is returned.
|
|
25
28
|
* With `force`, overwrites the body, preserves original `created`, and sets `updated`.
|
|
29
|
+
* Omitting `topics` on overwrite keeps existing frontmatter topics.
|
|
26
30
|
*/
|
|
27
31
|
export declare function writePlan(plansDir: string, name: string, body: string, options: WritePlanOptions): Promise<WritePlanResult>;
|
|
28
32
|
//# sourceMappingURL=write-plan.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-plan.d.ts","sourceRoot":"","sources":["../../src/vault/write-plan.ts"],"names":[],"mappings":"AAMA,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"write-plan.d.ts","sourceRoot":"","sources":["../../src/vault/write-plan.ts"],"names":[],"mappings":"AAMA,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;CACzB;AAwBD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GACvC,OAAO,CAAC,eAAe,CAAC,CAkB1B;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CA4B1B"}
|
package/dist/vault/write-plan.js
CHANGED
|
@@ -12,12 +12,17 @@ function buildFrontmatter(options) {
|
|
|
12
12
|
if (options.updated) {
|
|
13
13
|
lines.push(`updated: ${yamlDoubleQuoted(options.updated)}`);
|
|
14
14
|
}
|
|
15
|
+
if (options.topics && options.topics.length > 0) {
|
|
16
|
+
const items = options.topics.map((t) => yamlDoubleQuoted(t)).join(", ");
|
|
17
|
+
lines.push(`topics: [${items}]`);
|
|
18
|
+
}
|
|
15
19
|
lines.push("---");
|
|
16
20
|
return `${lines.join("\n")}\n\n`;
|
|
17
21
|
}
|
|
18
22
|
/**
|
|
19
23
|
* Overwrites an existing plan at an absolute path.
|
|
20
24
|
* Preserves original `created` (falls back to `now` if missing) and sets `updated`.
|
|
25
|
+
* Omitting `topics` keeps existing frontmatter topics; passing `topics` replaces them.
|
|
21
26
|
* Caller must validate the path (e.g. inside this project's `plans/` dir).
|
|
22
27
|
*/
|
|
23
28
|
export async function updatePlanAtPath(filePath, body, options) {
|
|
@@ -26,10 +31,12 @@ export async function updatePlanAtPath(filePath, body, options) {
|
|
|
26
31
|
const fm = parseHandoffFrontmatter(existing);
|
|
27
32
|
const created = fm.created ?? now.toISOString();
|
|
28
33
|
const updated = now.toISOString();
|
|
34
|
+
const topics = options.topics ?? fm.topics;
|
|
29
35
|
const content = buildFrontmatter({
|
|
30
36
|
projectId: options.projectId,
|
|
31
37
|
created,
|
|
32
38
|
updated,
|
|
39
|
+
topics,
|
|
33
40
|
}) + body;
|
|
34
41
|
await writeFile(filePath, content, "utf8");
|
|
35
42
|
return { path: filePath, status: "overwritten" };
|
|
@@ -39,6 +46,7 @@ export async function updatePlanAtPath(filePath, body, options) {
|
|
|
39
46
|
* Target is always `plansDir/<name>.md` — no collision suffixes.
|
|
40
47
|
* Without `force`, an existing file is left untouched and status `"exists"` is returned.
|
|
41
48
|
* With `force`, overwrites the body, preserves original `created`, and sets `updated`.
|
|
49
|
+
* Omitting `topics` on overwrite keeps existing frontmatter topics.
|
|
42
50
|
*/
|
|
43
51
|
export async function writePlan(plansDir, name, body, options) {
|
|
44
52
|
const now = options.now ?? new Date();
|
|
@@ -49,11 +57,16 @@ export async function writePlan(plansDir, name, body, options) {
|
|
|
49
57
|
return { path: filePath, status: "exists" };
|
|
50
58
|
}
|
|
51
59
|
if (exists && options.force) {
|
|
52
|
-
return updatePlanAtPath(filePath, body, {
|
|
60
|
+
return updatePlanAtPath(filePath, body, {
|
|
61
|
+
projectId: options.projectId,
|
|
62
|
+
topics: options.topics,
|
|
63
|
+
now,
|
|
64
|
+
});
|
|
53
65
|
}
|
|
54
66
|
const content = buildFrontmatter({
|
|
55
67
|
projectId: options.projectId,
|
|
56
68
|
created: now.toISOString(),
|
|
69
|
+
topics: options.topics,
|
|
57
70
|
}) + body;
|
|
58
71
|
await writeFile(filePath, content, "utf8");
|
|
59
72
|
return { path: filePath, status: "created" };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-plan.js","sourceRoot":"","sources":["../../src/vault/write-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"write-plan.js","sourceRoot":"","sources":["../../src/vault/write-plan.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grounder",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Connect projects to an Obsidian vault (or any markdown folder) for AI agent memory — session handoffs, plans, and notes in files you own",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"grounder": "./dist/cli.js"
|
|
@@ -20,7 +20,14 @@
|
|
|
20
20
|
"handoff",
|
|
21
21
|
"developer-tools",
|
|
22
22
|
"ai",
|
|
23
|
-
"cli"
|
|
23
|
+
"cli",
|
|
24
|
+
"agent-memory",
|
|
25
|
+
"local-first",
|
|
26
|
+
"vault",
|
|
27
|
+
"session-handoff",
|
|
28
|
+
"context-management",
|
|
29
|
+
"second-brain",
|
|
30
|
+
"pkm"
|
|
24
31
|
],
|
|
25
32
|
"license": "MIT",
|
|
26
33
|
"repository": {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Save a note to the
|
|
1
|
+
Save a note to the markdown vault for this project.
|
|
2
2
|
|
|
3
3
|
Distill the instruction after `/grounder-note` into a clean note body — not a chat transcript.
|
|
4
4
|
Do not dump tool traces, full conversation, or false starts.
|
|
5
5
|
|
|
6
|
-
**Special case: the instruction asks to view existing notes, not write one** (`list`, `list 3 oldest`, `show notes`, etc.) → run `{{GROUNDER_CLI}} note list --limit <N
|
|
6
|
+
**Special case: the instruction asks to view existing notes, not write one** (`list`, `list 3 oldest`, `show notes`, etc.) → run `{{GROUNDER_CLI}} note list --limit <N> --markdown` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no note write. Relay the CLI stdout as-is (it already includes the count header; title lines are clickable `[relativePath](fileUri)` links).
|
|
7
7
|
|
|
8
8
|
Rules:
|
|
9
9
|
- Default → distill the args into a clean note body
|
|
@@ -18,6 +18,10 @@ Optional short title slug (filename):
|
|
|
18
18
|
|
|
19
19
|
{{GROUNDER_CLI}} note --title <slug> "<body>"
|
|
20
20
|
|
|
21
|
+
Always include `--topics` with 3-5 comma-separated lowercase keywords that capture the note's core concepts (e.g. `--topics "schema,migration,postgres"`). Pick terms a future search would use — concrete nouns and technical terms, not verbs or filler:
|
|
22
|
+
|
|
23
|
+
{{GROUNDER_CLI}} note --topics "keyword1,keyword2,keyword3" "<body>"
|
|
24
|
+
|
|
21
25
|
For multi-line bodies, prefer a shell heredoc so quoting does not break:
|
|
22
26
|
|
|
23
27
|
```bash
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Write a named, updatable plan document to the
|
|
1
|
+
Write a named, updatable plan document to the markdown vault for this project.
|
|
2
2
|
|
|
3
3
|
Distill the instruction after `/grounder-plan` into a structured plan — not a chat transcript.
|
|
4
4
|
Do not dump tool traces, full conversation, or false starts.
|
|
@@ -22,7 +22,7 @@ Build a markdown body with these sections:
|
|
|
22
22
|
…
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
**Special case: the instruction asks to view existing plans, not name a new topic** (`list`, `list 3 oldest`, `show plans`, etc.) → run `{{GROUNDER_CLI}} plan list --limit <N
|
|
25
|
+
**Special case: the instruction asks to view existing plans, not name a new topic** (`list`, `list 3 oldest`, `show plans`, etc.) → run `{{GROUNDER_CLI}} plan list --limit <N> --markdown` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no plan write, no title. Relay the CLI stdout as-is (it already includes the count header; title lines are clickable `[relativePath](fileUri)` links).
|
|
26
26
|
|
|
27
27
|
Otherwise, resolve the target, then **state it plainly before writing** — `Updating plan at <path>.` or `Creating new plan titled <title>.` This is a visible record, not a blocking confirmation — updates overwrite with no `--force`, so get the match right.
|
|
28
28
|
|
|
@@ -31,12 +31,12 @@ Otherwise, resolve the target, then **state it plainly before writing** — `Upd
|
|
|
31
31
|
**2. No path, but update intent** (e.g. "update/continue/revise the plan", or a name that sounds like an existing one) → look it up first:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
{{GROUNDER_CLI}} plan list --limit 5
|
|
34
|
+
{{GROUNDER_CLI}} plan list --limit 5 --markdown
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
CLI output starts with a count header, then each result as a numbered two-line block — `N. ` +
|
|
37
|
+
CLI output starts with a count header, then each result as a numbered two-line block — `N. ` + `[relativePath](fileUri)` on the first line, the absolute path indented beneath it (use that absolute path for `--path`).
|
|
38
38
|
|
|
39
|
-
A match counts only if
|
|
39
|
+
A match counts only if the filename stem / relative path actually corresponds to what the user named — not just "it's the only plan in the project." No name given and exactly one plan exists → that counts too. If the user refers to a plan by the number shown in *this* listing (e.g. "update plan 2"), that counts as a match too — resolve it to the indented absolute path from this same output, don't reuse a number from an earlier listing in the conversation (it's positional, not a stable id, and can shift if plans changed since). Otherwise (no match, several matches, or a name/number that doesn't correspond to any existing plan) → ask; never guess.
|
|
40
40
|
|
|
41
41
|
Cases 1 and 2 (update) — run:
|
|
42
42
|
|
|
@@ -62,6 +62,8 @@ EOF
|
|
|
62
62
|
|
|
63
63
|
If `--title` collides with an existing plan (non-zero exit; stderr names the conflict), ask: overwrite (`--force`) or a different name. `--force` only resolves that collision — **never** use it to update a plan you meant to target with `--path`.
|
|
64
64
|
|
|
65
|
+
Always include `--topics` with 3-5 comma-separated lowercase keywords that capture the plan's core concepts (e.g. `--topics "caching,redis,performance,api"`). Pick terms a future search would use — concrete nouns and technical terms, not verbs or filler.
|
|
66
|
+
|
|
65
67
|
Run from the linked project folder or any subdirectory beneath it.
|
|
66
68
|
The vault is outside the workspace — grant shell permissions if Claude Code prompts you.
|
|
67
69
|
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Search this project's vault content for relevant context.
|
|
2
|
+
|
|
3
|
+
**Silence:** write **no assistant text** until step 3. Rounds 1–2 are tool calls with an empty/absent text part — not “I’ll search…”, not “I’ll read…”, not “**Analyzing…**”, not query/terms narration.
|
|
4
|
+
|
|
5
|
+
Use this when the user asks to find prior project-vault context by topic, keyword, concept, or phrase.
|
|
6
|
+
|
|
7
|
+
Scope is this linked project only — the CLI resolves and searches under the linked project vault root. Do not search outside it.
|
|
8
|
+
|
|
9
|
+
## Turn budget (speed)
|
|
10
|
+
|
|
11
|
+
**Rounds 1–2: tool calls only — no text part in those messages.** Not even one sentence.
|
|
12
|
+
|
|
13
|
+
Exactly **two** assistant turns with tools, then the answer. Allowed tools, nothing else:
|
|
14
|
+
|
|
15
|
+
1. Round 1 — Shell only: one `search … --json` (optional second search in the *same* round only per the broaden rule below). Message = that tool call, nothing else.
|
|
16
|
+
2. Round 2 — Read only: **one** parallel batch of full-file reads (hits 1–4). Message = those Read calls, nothing else.
|
|
17
|
+
3. Final answer to the user (first and only chat text).
|
|
18
|
+
|
|
19
|
+
**Do not** Glob, Grep, extra Shell, or status/UI tools (`UpdateCurrentStep`, `TodoWrite`, and similar). Do not add a third tool turn. Do not explore the repo.
|
|
20
|
+
|
|
21
|
+
## Output contract (default — hybrid)
|
|
22
|
+
|
|
23
|
+
- Do not echo commands or shell output.
|
|
24
|
+
- **Never paste CLI JSON, snippets, or raw stdout into chat** — parse `--json` internally only.
|
|
25
|
+
- One final synthesized response only.
|
|
26
|
+
|
|
27
|
+
**Path links (mandatory for every listed file):**
|
|
28
|
+
- Visible title = `hits[].relativePath` from JSON **exactly** (project-vault-relative; the folder that contains `notes/`, `logs/`, and `plans/`). Example: `plans/archive/0.2.0 and older/doc.md`.
|
|
29
|
+
- **Do not** derive the title from `hits[].file`, path segments, or parent-vault prefixes.
|
|
30
|
+
- **Wrong titles:** `10-Projects/grounder/plans/…`, `%20` in the visible title, or any path above the project vault root.
|
|
31
|
+
- Link href = `hits[].fileUri` from JSON (spaces already percent-encoded).
|
|
32
|
+
- Markdown form: `[hits[i].relativePath](hits[i].fileUri)`
|
|
33
|
+
|
|
34
|
+
**Numbering (mandatory):**
|
|
35
|
+
- Number every listed file, continuing across sections (`1…` in **Read these**, then `5…` in **Also matched`).
|
|
36
|
+
- Do not restart at 1 in **Also matched**. Do not use bullet-only lists without numbers.
|
|
37
|
+
|
|
38
|
+
Structure:
|
|
39
|
+
|
|
40
|
+
1. **Opening** — one sentence of what the vault says (not a search recap). Never start with “I have searched…”, “I found…”, or similar.
|
|
41
|
+
2. **Read these** — hits 1–4 only; numbered linked paths + optional role + short bullets under each. You may list a design/archive authority first *among those four*.
|
|
42
|
+
3. **Also matched** — leftover top-10 **in CLI order** (do not reshuffle); numbered linked paths + one short phrase each (`hits[].alsoMatchedHint` or `matches[].term`). Every line must end with ` — phrase`; bare links are invalid. Omit if empty.
|
|
43
|
+
|
|
44
|
+
Example shape (`##` headings required — not bold-only, not `###`):
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
Vault notes discuss …
|
|
48
|
+
|
|
49
|
+
## Read these
|
|
50
|
+
1. [plans/archive/0.3.0/schema_….md](file:///…/schema_….md) — design authority
|
|
51
|
+
- …
|
|
52
|
+
2. [plans/…](file:///…) — …
|
|
53
|
+
## Also matched
|
|
54
|
+
3. [plans/archive/0.2.0 and older/doc.md](file:///…/0.2.0%20and%20older/doc.md) — one phrase
|
|
55
|
+
4. [plans/…](file:///…) — one phrase
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Lookup mode:** explicit lookup wording (`exact phrase`, `this line`, `the wording`) **or** the entire input after stripping retrieval wrappers is a bare `"quoted span"` → relay CLI `--markdown` as-is (one search, no `--terms`, no full reads).
|
|
59
|
+
|
|
60
|
+
## Steps
|
|
61
|
+
|
|
62
|
+
1. **Query and terms (private)** — classify, then build argv. Classification is silent (no chat text). The CLI always line-scans `query` plus `--terms`. Multi-word queries only match lines that contain that phrase verbatim. Rank is dominated by how many distinct terms hit the **same** file — complementary vault words beat extra English synonyms and source module names.
|
|
63
|
+
|
|
64
|
+
**Classify** after stripping retrieval wrappers (`find`, `search for`, `documents discussing`, `notes about`, `look up`). Then pick one:
|
|
65
|
+
|
|
66
|
+
- **Lookup** — explicit lookup wording (`exact phrase`, `this line`, `the wording`), **or** leftover is a bare `"quoted span"`. `query` = the quoted text, unmodified. Relay CLI `--markdown` as-is; no `--terms`, no full reads.
|
|
67
|
+
- **Request** — leftover still has request syntax (any of): `that mention` / `that discuss` / `that talk about`; leftover starts with `plans that` / `notes that` / `docs that` / `documents that`; trailing scope `both in` / `either in` / `in CLI and`. Do **not** pass that leftover as `query`. `query` = one primary noun or named command from the topic (tight phrase; do not prefix a product name). Extra nouns go in `--terms`.
|
|
68
|
+
- **Topic leftover** — leftover is already a topic noun-phrase. `query` = leftover, same words, same order. Do not paraphrase, shorten, or coin a new phrase.
|
|
69
|
+
|
|
70
|
+
Strip only retrieval wrappers. Do not pass the whole utterance. Do not recycle the query as a `--terms` item.
|
|
71
|
+
|
|
72
|
+
Examples below are a **fictional** domain. Copy the shape; invent tokens for *this* topic. Do not reuse these strings as `--terms`.
|
|
73
|
+
|
|
74
|
+
Example — lookup. User: `find "retry of expired jobs"`
|
|
75
|
+
- class: lookup
|
|
76
|
+
- argv: {{GROUNDER_CLI}} search "retry of expired jobs" --markdown
|
|
77
|
+
|
|
78
|
+
Example — topic leftover. User: `find documents discussing retry of expired jobs`
|
|
79
|
+
- class: topic leftover
|
|
80
|
+
- query: `retry of expired jobs` (leftover after stripping the wrapper)
|
|
81
|
+
- wrong query: `expired job retries` (rewritten)
|
|
82
|
+
- wrong class: request (`documents discussing` is a wrapper)
|
|
83
|
+
|
|
84
|
+
Example — request. User: `find plans that mention updating the charge or refund command, both in worker and API`
|
|
85
|
+
- class: request (`plans that mention` / `both in` stay leftover — not the topic)
|
|
86
|
+
- query: `charge` (one named command from leftover; not `billing charge`)
|
|
87
|
+
- terms: `refund,settlement,invoices.json,RefundPolicy`
|
|
88
|
+
- from leftover: `refund` (the other named command)
|
|
89
|
+
- invented: `settlement` (domain), `invoices.json` (file), `RefundPolicy` (schema) — guess this project's equivalents
|
|
90
|
+
- wrong query: `plans that mention updating the charge or refund command, both in worker and API`
|
|
91
|
+
- wrong query: `charge refund command` (joined nouns)
|
|
92
|
+
- not as terms: `plan`, `command`, `api`
|
|
93
|
+
|
|
94
|
+
**Terms** — invent 3–5 complementary vault tokens for *this* topic, then stop. They need not appear in the utterance:
|
|
95
|
+
1. Domain noun/phrase from the topic (skip if it would duplicate the query)
|
|
96
|
+
2. Named command or product verb if the topic has one — never a lone generic verb (`migrate`, `install`)
|
|
97
|
+
3. One on-disk identifier (filename, config key, schema field) guessed for this project
|
|
98
|
+
4–5. Only another vault/product token. No paraphrase of the query.
|
|
99
|
+
|
|
100
|
+
**Never as terms** (unless the user asked about code layout): repo paths, `packages/…`, source module / file stems. Lone high-df words (`plan`, `command`, `cli`) flatten rank. Prefer words that appear in vault notes (named commands, config files, domain identifiers).
|
|
101
|
+
|
|
102
|
+
Example — user: `look up why the retry queue must skip expired jobs`
|
|
103
|
+
- class: topic leftover
|
|
104
|
+
- query: `why the retry queue must skip expired jobs`
|
|
105
|
+
- terms: `retry queue,dead letter,jobs.json,RetryPolicy,ttl` (`retry queue` from leftover; others invented)
|
|
106
|
+
- not: `queue-worker`, `process-jobs`, `skip`, `look up`
|
|
107
|
+
|
|
108
|
+
2. **Search (tool round 1):**
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
{{GROUNDER_CLI}} search "<query>" --terms "<csv>" --context 2 --json
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Always quote `--terms`.** Unquoted CSV with spaces corrupts argv.
|
|
115
|
+
|
|
116
|
+
Parse JSON privately. Take hits in CLI order (`hits[0]` …). For links use `relativePath` + `fileUri`; for Also matched gloss use `alsoMatchedHint` or `matches[].term` — do not quote snippets.
|
|
117
|
+
|
|
118
|
+
**Broaden once (silent)** only if: `totalFileCount` is 0; or ≤2 and every hit is meta (`discussions/search/`, or snippet only quotes the query); or any term in `termHitCounts` has a count of 0 (that term produced no files — it was a bad guess and must be replaced). Otherwise do not re-search.
|
|
119
|
+
|
|
120
|
+
Broaden call (use `--context 3` — weaker matches need more context):
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
{{GROUNDER_CLI}} search "<query>" --terms "<csv-with-replacement>" --context 3 --json
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Broaden strategy (deterministic):** check `termHitCounts` first — if any term has count 0, replace **that term** (not slot-3) with a different product/vault token. If no zero-hit term, drop slot-3 (the on-disk identifier). Keep slots 1–2 (product noun/verb) unchanged. Do not invent new terms or rewrite existing ones.
|
|
127
|
+
|
|
128
|
+
3. **Read (tool round 2)** — mandatory unless lookup:
|
|
129
|
+
- Full-read CLI hits **1–4** in rank order, **all in one parallel batch**.
|
|
130
|
+
- Read path = `hits[i].file` (absolute). Link title/href = `hits[i].relativePath` + `hits[i].fileUri`.
|
|
131
|
+
- **No skips, no substitutions, no “maybe also hit 5.”** Trust CLI order; judge relevance only when writing the answer.
|
|
132
|
+
- Grant read permissions for vault paths outside the workspace when needed.
|
|
133
|
+
|
|
134
|
+
4. **Answer** — synthesize immediately after reads:
|
|
135
|
+
- Claims only from files you full-read. Unread hits must not grow new facts.
|
|
136
|
+
- **Read these:** useful full-reads (those 1–4 only). Thin/off-topic reads get one blunt numbered line there or move to **Also matched**.
|
|
137
|
+
- **Also matched:** remaining top-10 you did not deep-summarize, **in CLI leftover order**. Copy `alsoMatchedHint` or phrase from `matches[].term`; every line ends with ` — phrase`.
|
|
138
|
+
- Every file line: `[relativePath](fileUri)` from JSON; continue numbering across sections.
|
|
139
|
+
- Prefer design/archive docs when they are the authority among the files you read.
|
|
140
|
+
|
|
141
|
+
Run from the linked project folder or any subdirectory beneath it.
|
|
142
|
+
The vault is outside the workspace — grant shell permissions if Claude Code prompts you.
|
|
143
|
+
Do not write to vault files during search.
|
|
144
|
+
Do not grep the vault yourself — the CLI ranks; you read and synthesize.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Write a session handoff checkpoint to the
|
|
1
|
+
Write a session handoff checkpoint to the markdown vault for this project.
|
|
2
2
|
|
|
3
3
|
Summarize the session into a structured handoff — not a chat transcript.
|
|
4
4
|
Do not dump tool traces, full conversation, or false starts.
|
|
@@ -38,6 +38,10 @@ Optional short title slug (filename + frontmatter):
|
|
|
38
38
|
|
|
39
39
|
{{GROUNDER_CLI}} handoff --title <slug> "<body>"
|
|
40
40
|
|
|
41
|
+
Always include `--topics` with 3-5 comma-separated lowercase keywords that capture the session's core concepts (e.g. `--topics "auth,middleware,jwt,session"`). Pick terms a future search would use — concrete nouns and technical terms, not verbs or filler:
|
|
42
|
+
|
|
43
|
+
{{GROUNDER_CLI}} handoff --topics "keyword1,keyword2,keyword3" "<body>"
|
|
44
|
+
|
|
41
45
|
For multi-line bodies, prefer a shell heredoc so quoting does not break:
|
|
42
46
|
|
|
43
47
|
```bash
|
|
@@ -2,7 +2,7 @@ Hydrate this session from the latest vault handoff and repo truth.
|
|
|
2
2
|
|
|
3
3
|
Read-only — do not write to the vault. Do not invent vault paths.
|
|
4
4
|
|
|
5
|
-
**Special case: the instruction asks to view existing handoffs, not hydrate** (`list`, `list 3 oldest`, `show handoffs`, etc.) → run `{{GROUNDER_CLI}} handoff list --limit <N
|
|
5
|
+
**Special case: the instruction asks to view existing handoffs, not hydrate** (`list`, `list 3 oldest`, `show handoffs`, etc.) → run `{{GROUNDER_CLI}} handoff list --limit <N> --markdown` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no hydrate, no `AGENTS.md`, no “start work.” Relay the CLI stdout as-is (it already includes the count header; title lines are clickable `[relativePath](fileUri)` links).
|
|
6
6
|
|
|
7
7
|
Otherwise, from the linked project folder or any subdirectory beneath it:
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ Otherwise, from the linked project folder or any subdirectory beneath it:
|
|
|
12
12
|
|
|
13
13
|
2. If empty: tell the user there are no handoffs yet, then read repo `AGENTS.md` only and proceed.
|
|
14
14
|
|
|
15
|
-
3. Otherwise, read that file. If the user names a specific session instead: `{{GROUNDER_CLI}} handoff list --limit 5` → match name/index to the indented path in *this* listing (positional, not a stable id). Miss → once with `--limit 50` (*that* listing only). Still miss → tell the user and stop — no guessed hydrate.
|
|
15
|
+
3. Otherwise, read that file. If the user names a specific session instead: `{{GROUNDER_CLI}} handoff list --limit 5 --markdown` → match name/index to the indented absolute path in *this* listing (positional, not a stable id). Miss → once with `--limit 50 --markdown` (*that* listing only). Still miss → tell the user and stop — no guessed hydrate.
|
|
16
16
|
|
|
17
17
|
4. Read repo `AGENTS.md` (project conventions and constraints).
|
|
18
18
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Save a note to the
|
|
1
|
+
Save a note to the markdown vault for this project.
|
|
2
2
|
|
|
3
3
|
Distill the instruction after `/grounder-note` into a clean note body — not a chat transcript.
|
|
4
4
|
Do not dump tool traces, full conversation, or false starts.
|
|
5
5
|
|
|
6
|
-
**Special case: the instruction asks to view existing notes, not write one** (`list`, `list 3 oldest`, `show notes`, etc.) → run `{{GROUNDER_CLI}} note list --limit <N
|
|
6
|
+
**Special case: the instruction asks to view existing notes, not write one** (`list`, `list 3 oldest`, `show notes`, etc.) → run `{{GROUNDER_CLI}} note list --limit <N> --markdown` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no note write. Relay the CLI stdout as-is (it already includes the count header; title lines are clickable `[relativePath](fileUri)` links).
|
|
7
7
|
|
|
8
8
|
Rules:
|
|
9
9
|
- Default → distill the args into a clean note body
|
|
@@ -18,6 +18,10 @@ Optional short title slug (filename):
|
|
|
18
18
|
|
|
19
19
|
{{GROUNDER_CLI}} note --title <slug> "<body>"
|
|
20
20
|
|
|
21
|
+
Always include `--topics` with 3-5 comma-separated lowercase keywords that capture the note's core concepts (e.g. `--topics "schema,migration,postgres"`). Pick terms a future search would use — concrete nouns and technical terms, not verbs or filler:
|
|
22
|
+
|
|
23
|
+
{{GROUNDER_CLI}} note --topics "keyword1,keyword2,keyword3" "<body>"
|
|
24
|
+
|
|
21
25
|
For multi-line bodies, prefer a shell heredoc so quoting does not break:
|
|
22
26
|
|
|
23
27
|
```bash
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Write a named, updatable plan document to the
|
|
1
|
+
Write a named, updatable plan document to the markdown vault for this project.
|
|
2
2
|
|
|
3
3
|
Distill the instruction after `/grounder-plan` into a structured plan — not a chat transcript.
|
|
4
4
|
Do not dump tool traces, full conversation, or false starts.
|
|
@@ -22,7 +22,7 @@ Build a markdown body with these sections:
|
|
|
22
22
|
…
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
**Special case: the instruction asks to view existing plans, not name a new topic** (`list`, `list 3 oldest`, `show plans`, etc.) → run `{{GROUNDER_CLI}} plan list --limit <N
|
|
25
|
+
**Special case: the instruction asks to view existing plans, not name a new topic** (`list`, `list 3 oldest`, `show plans`, etc.) → run `{{GROUNDER_CLI}} plan list --limit <N> --markdown` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no plan write, no title. Relay the CLI stdout as-is (it already includes the count header; title lines are clickable `[relativePath](fileUri)` links).
|
|
26
26
|
|
|
27
27
|
Otherwise, resolve the target, then **state it plainly before writing** — `Updating plan at <path>.` or `Creating new plan titled <title>.` This is a visible record, not a blocking confirmation — updates overwrite with no `--force`, so get the match right.
|
|
28
28
|
|
|
@@ -31,12 +31,12 @@ Otherwise, resolve the target, then **state it plainly before writing** — `Upd
|
|
|
31
31
|
**2. No path, but update intent** (e.g. "update/continue/revise the plan", or a name that sounds like an existing one) → look it up first:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
{{GROUNDER_CLI}} plan list --limit 5
|
|
34
|
+
{{GROUNDER_CLI}} plan list --limit 5 --markdown
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
CLI output starts with a count header, then each result as a numbered two-line block — `N. ` +
|
|
37
|
+
CLI output starts with a count header, then each result as a numbered two-line block — `N. ` + `[relativePath](fileUri)` on the first line, the absolute path indented beneath it (use that absolute path for `--path`).
|
|
38
38
|
|
|
39
|
-
A match counts only if
|
|
39
|
+
A match counts only if the filename stem / relative path actually corresponds to what the user named — not just "it's the only plan in the project." No name given and exactly one plan exists → that counts too. If the user refers to a plan by the number shown in *this* listing (e.g. "update plan 2"), that counts as a match too — resolve it to the indented absolute path from this same output, don't reuse a number from an earlier listing in the conversation (it's positional, not a stable id, and can shift if plans changed since). Otherwise (no match, several matches, or a name/number that doesn't correspond to any existing plan) → ask; never guess.
|
|
40
40
|
|
|
41
41
|
Cases 1 and 2 (update) — run:
|
|
42
42
|
|
|
@@ -62,6 +62,8 @@ EOF
|
|
|
62
62
|
|
|
63
63
|
If `--title` collides with an existing plan (non-zero exit; stderr names the conflict), ask: overwrite (`--force`) or a different name. `--force` only resolves that collision — **never** use it to update a plan you meant to target with `--path`.
|
|
64
64
|
|
|
65
|
+
Always include `--topics` with 3-5 comma-separated lowercase keywords that capture the plan's core concepts (e.g. `--topics "caching,redis,performance,api"`). Pick terms a future search would use — concrete nouns and technical terms, not verbs or filler.
|
|
66
|
+
|
|
65
67
|
Run from the linked project folder or any subdirectory beneath it.
|
|
66
68
|
Run {{GROUNDER_CLI}} with `required_permissions: ["all"]` (vault is outside the workspace).
|
|
67
69
|
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Search this project's vault content for relevant context.
|
|
2
|
+
|
|
3
|
+
**Silence:** write **no assistant text** until step 3. Rounds 1–2 are tool calls with an empty/absent text part — not “I’ll search…”, not “I’ll read…”, not “**Analyzing…**”, not query/terms narration.
|
|
4
|
+
|
|
5
|
+
Use this when the user asks to find prior project-vault context by topic, keyword, concept, or phrase.
|
|
6
|
+
|
|
7
|
+
Scope is this linked project only — the CLI resolves and searches under the linked project vault root. Do not search outside it.
|
|
8
|
+
|
|
9
|
+
## Turn budget (speed)
|
|
10
|
+
|
|
11
|
+
**Rounds 1–2: tool calls only — no text part in those messages.** Not even one sentence.
|
|
12
|
+
|
|
13
|
+
Exactly **two** assistant turns with tools, then the answer. Allowed tools, nothing else:
|
|
14
|
+
|
|
15
|
+
1. Round 1 — Shell only: one `search … --json` (optional second search in the *same* round only per the broaden rule below). Message = that tool call, nothing else.
|
|
16
|
+
2. Round 2 — Read only: **one** parallel batch of full-file reads (hits 1–4). Message = those Read calls, nothing else.
|
|
17
|
+
3. Final answer to the user (first and only chat text).
|
|
18
|
+
|
|
19
|
+
**Do not** Glob, Grep, extra Shell, or status/UI tools (`UpdateCurrentStep`, `TodoWrite`, and similar). Do not add a third tool turn. Do not explore the repo.
|
|
20
|
+
|
|
21
|
+
## Output contract (default — hybrid)
|
|
22
|
+
|
|
23
|
+
- Do not echo commands or shell output.
|
|
24
|
+
- **Never paste CLI JSON, snippets, or raw stdout into chat** — parse `--json` internally only.
|
|
25
|
+
- One final synthesized response only.
|
|
26
|
+
|
|
27
|
+
**Path links (mandatory for every listed file):**
|
|
28
|
+
- Visible title = `hits[].relativePath` from JSON **exactly** (project-vault-relative; the folder that contains `notes/`, `logs/`, and `plans/`). Example: `plans/archive/0.2.0 and older/doc.md`.
|
|
29
|
+
- **Do not** derive the title from `hits[].file`, path segments, or parent-vault prefixes.
|
|
30
|
+
- **Wrong titles:** `10-Projects/grounder/plans/…`, `%20` in the visible title, or any path above the project vault root.
|
|
31
|
+
- Link href = `hits[].fileUri` from JSON (spaces already percent-encoded).
|
|
32
|
+
- Markdown form: `[hits[i].relativePath](hits[i].fileUri)`
|
|
33
|
+
|
|
34
|
+
**Numbering (mandatory):**
|
|
35
|
+
- Number every listed file, continuing across sections (`1…` in **Read these**, then `5…` in **Also matched`).
|
|
36
|
+
- Do not restart at 1 in **Also matched**. Do not use bullet-only lists without numbers.
|
|
37
|
+
|
|
38
|
+
Structure:
|
|
39
|
+
|
|
40
|
+
1. **Opening** — one sentence of what the vault says (not a search recap). Never start with “I have searched…”, “I found…”, or similar.
|
|
41
|
+
2. **Read these** — hits 1–4 only; numbered linked paths + optional role + short bullets under each. You may list a design/archive authority first *among those four*.
|
|
42
|
+
3. **Also matched** — leftover top-10 **in CLI order** (do not reshuffle); numbered linked paths + one short phrase each (`hits[].alsoMatchedHint` or `matches[].term`). Every line must end with ` — phrase`; bare links are invalid. Omit if empty.
|
|
43
|
+
|
|
44
|
+
Example shape (`##` headings required — not bold-only, not `###`):
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
Vault notes discuss …
|
|
48
|
+
|
|
49
|
+
## Read these
|
|
50
|
+
1. [plans/archive/0.3.0/schema_….md](file:///…/schema_….md) — design authority
|
|
51
|
+
- …
|
|
52
|
+
2. [plans/…](file:///…) — …
|
|
53
|
+
## Also matched
|
|
54
|
+
3. [plans/archive/0.2.0 and older/doc.md](file:///…/0.2.0%20and%20older/doc.md) — one phrase
|
|
55
|
+
4. [plans/…](file:///…) — one phrase
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Lookup mode:** explicit lookup wording (`exact phrase`, `this line`, `the wording`) **or** the entire input after stripping retrieval wrappers is a bare `"quoted span"` → relay CLI `--markdown` as-is (one search, no `--terms`, no full reads).
|
|
59
|
+
|
|
60
|
+
## Steps
|
|
61
|
+
|
|
62
|
+
1. **Query and terms (private)** — classify, then build argv. Classification is silent (no chat text). The CLI always line-scans `query` plus `--terms`. Multi-word queries only match lines that contain that phrase verbatim. Rank is dominated by how many distinct terms hit the **same** file — complementary vault words beat extra English synonyms and source module names.
|
|
63
|
+
|
|
64
|
+
**Classify** after stripping retrieval wrappers (`find`, `search for`, `documents discussing`, `notes about`, `look up`). Then pick one:
|
|
65
|
+
|
|
66
|
+
- **Lookup** — explicit lookup wording (`exact phrase`, `this line`, `the wording`), **or** leftover is a bare `"quoted span"`. `query` = the quoted text, unmodified. Relay CLI `--markdown` as-is; no `--terms`, no full reads.
|
|
67
|
+
- **Request** — leftover still has request syntax (any of): `that mention` / `that discuss` / `that talk about`; leftover starts with `plans that` / `notes that` / `docs that` / `documents that`; trailing scope `both in` / `either in` / `in CLI and`. Do **not** pass that leftover as `query`. `query` = one primary noun or named command from the topic (tight phrase; do not prefix a product name). Extra nouns go in `--terms`.
|
|
68
|
+
- **Topic leftover** — leftover is already a topic noun-phrase. `query` = leftover, same words, same order. Do not paraphrase, shorten, or coin a new phrase.
|
|
69
|
+
|
|
70
|
+
Strip only retrieval wrappers. Do not pass the whole utterance. Do not recycle the query as a `--terms` item.
|
|
71
|
+
|
|
72
|
+
Examples below are a **fictional** domain. Copy the shape; invent tokens for *this* topic. Do not reuse these strings as `--terms`.
|
|
73
|
+
|
|
74
|
+
Example — lookup. User: `find "retry of expired jobs"`
|
|
75
|
+
- class: lookup
|
|
76
|
+
- argv: {{GROUNDER_CLI}} search "retry of expired jobs" --markdown
|
|
77
|
+
|
|
78
|
+
Example — topic leftover. User: `find documents discussing retry of expired jobs`
|
|
79
|
+
- class: topic leftover
|
|
80
|
+
- query: `retry of expired jobs` (leftover after stripping the wrapper)
|
|
81
|
+
- wrong query: `expired job retries` (rewritten)
|
|
82
|
+
- wrong class: request (`documents discussing` is a wrapper)
|
|
83
|
+
|
|
84
|
+
Example — request. User: `find plans that mention updating the charge or refund command, both in worker and API`
|
|
85
|
+
- class: request (`plans that mention` / `both in` stay leftover — not the topic)
|
|
86
|
+
- query: `charge` (one named command from leftover; not `billing charge`)
|
|
87
|
+
- terms: `refund,settlement,invoices.json,RefundPolicy`
|
|
88
|
+
- from leftover: `refund` (the other named command)
|
|
89
|
+
- invented: `settlement` (domain), `invoices.json` (file), `RefundPolicy` (schema) — guess this project's equivalents
|
|
90
|
+
- wrong query: `plans that mention updating the charge or refund command, both in worker and API`
|
|
91
|
+
- wrong query: `charge refund command` (joined nouns)
|
|
92
|
+
- not as terms: `plan`, `command`, `api`
|
|
93
|
+
|
|
94
|
+
**Terms** — invent 3–5 complementary vault tokens for *this* topic, then stop. They need not appear in the utterance:
|
|
95
|
+
1. Domain noun/phrase from the topic (skip if it would duplicate the query)
|
|
96
|
+
2. Named command or product verb if the topic has one — never a lone generic verb (`migrate`, `install`)
|
|
97
|
+
3. One on-disk identifier (filename, config key, schema field) guessed for this project
|
|
98
|
+
4–5. Only another vault/product token. No paraphrase of the query.
|
|
99
|
+
|
|
100
|
+
**Never as terms** (unless the user asked about code layout): repo paths, `packages/…`, source module / file stems. Lone high-df words (`plan`, `command`, `cli`) flatten rank. Prefer words that appear in vault notes (named commands, config files, domain identifiers).
|
|
101
|
+
|
|
102
|
+
Example — user: `look up why the retry queue must skip expired jobs`
|
|
103
|
+
- class: topic leftover
|
|
104
|
+
- query: `why the retry queue must skip expired jobs`
|
|
105
|
+
- terms: `retry queue,dead letter,jobs.json,RetryPolicy,ttl` (`retry queue` from leftover; others invented)
|
|
106
|
+
- not: `queue-worker`, `process-jobs`, `skip`, `look up`
|
|
107
|
+
|
|
108
|
+
2. **Search (tool round 1):**
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
{{GROUNDER_CLI}} search "<query>" --terms "<csv>" --context 2 --json
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Always quote `--terms`.** Unquoted CSV with spaces corrupts argv.
|
|
115
|
+
|
|
116
|
+
Parse JSON privately. Take hits in CLI order (`hits[0]` …). For links use `relativePath` + `fileUri`; for Also matched gloss use `alsoMatchedHint` or `matches[].term` — do not quote snippets.
|
|
117
|
+
|
|
118
|
+
**Broaden once (silent)** only if: `totalFileCount` is 0; or ≤2 and every hit is meta (`discussions/search/`, or snippet only quotes the query); or any term in `termHitCounts` has a count of 0 (that term produced no files — it was a bad guess and must be replaced). Otherwise do not re-search.
|
|
119
|
+
|
|
120
|
+
Broaden call (use `--context 3` — weaker matches need more context):
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
{{GROUNDER_CLI}} search "<query>" --terms "<csv-with-replacement>" --context 3 --json
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Broaden strategy (deterministic):** check `termHitCounts` first — if any term has count 0, replace **that term** (not slot-3) with a different product/vault token. If no zero-hit term, drop slot-3 (the on-disk identifier). Keep slots 1–2 (product noun/verb) unchanged. Do not invent new terms or rewrite existing ones.
|
|
127
|
+
|
|
128
|
+
3. **Read (tool round 2)** — mandatory unless lookup:
|
|
129
|
+
- Full-read CLI hits **1–4** in rank order, **all in one parallel batch**.
|
|
130
|
+
- Read path = `hits[i].file` (absolute). Link title/href = `hits[i].relativePath` + `hits[i].fileUri`.
|
|
131
|
+
- **No skips, no substitutions, no “maybe also hit 5.”** Trust CLI order; judge relevance only when writing the answer.
|
|
132
|
+
- Request vault read permissions as needed.
|
|
133
|
+
|
|
134
|
+
4. **Answer** — synthesize immediately after reads:
|
|
135
|
+
- Claims only from files you full-read. Unread hits must not grow new facts.
|
|
136
|
+
- **Read these:** useful full-reads (those 1–4 only). Thin/off-topic reads get one blunt numbered line there or move to **Also matched**.
|
|
137
|
+
- **Also matched:** remaining top-10 you did not deep-summarize, **in CLI leftover order**. Copy `alsoMatchedHint` or phrase from `matches[].term`; every line ends with ` — phrase`.
|
|
138
|
+
- Every file line: `[relativePath](fileUri)` from JSON; continue numbering across sections.
|
|
139
|
+
- Prefer design/archive docs when they are the authority among the files you read.
|
|
140
|
+
|
|
141
|
+
Run from the linked project folder or any subdirectory beneath it.
|
|
142
|
+
Run {{GROUNDER_CLI}} with `required_permissions: ["all"]` (vault is outside the workspace).
|
|
143
|
+
Do not write to vault files during search.
|
|
144
|
+
Do not grep the vault yourself — the CLI ranks; you read and synthesize.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Write a session handoff checkpoint to the
|
|
1
|
+
Write a session handoff checkpoint to the markdown vault for this project.
|
|
2
2
|
|
|
3
3
|
Summarize the session into a structured handoff — not a chat transcript.
|
|
4
4
|
Do not dump tool traces, full conversation, or false starts.
|
|
@@ -38,6 +38,10 @@ Optional short title slug (filename + frontmatter):
|
|
|
38
38
|
|
|
39
39
|
{{GROUNDER_CLI}} handoff --title <slug> "<body>"
|
|
40
40
|
|
|
41
|
+
Always include `--topics` with 3-5 comma-separated lowercase keywords that capture the session's core concepts (e.g. `--topics "auth,middleware,jwt,session"`). Pick terms a future search would use — concrete nouns and technical terms, not verbs or filler:
|
|
42
|
+
|
|
43
|
+
{{GROUNDER_CLI}} handoff --topics "keyword1,keyword2,keyword3" "<body>"
|
|
44
|
+
|
|
41
45
|
For multi-line bodies, prefer a shell heredoc so quoting does not break:
|
|
42
46
|
|
|
43
47
|
```bash
|
|
@@ -2,7 +2,7 @@ Hydrate this session from the latest vault handoff and repo truth.
|
|
|
2
2
|
|
|
3
3
|
Read-only — do not write to the vault. Do not invent vault paths.
|
|
4
4
|
|
|
5
|
-
**Special case: the instruction asks to view existing handoffs, not hydrate** (`list`, `list 3 oldest`, `show handoffs`, etc.) → run `{{GROUNDER_CLI}} handoff list --limit <N
|
|
5
|
+
**Special case: the instruction asks to view existing handoffs, not hydrate** (`list`, `list 3 oldest`, `show handoffs`, etc.) → run `{{GROUNDER_CLI}} handoff list --limit <N> --markdown` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no hydrate, no `AGENTS.md`, no “start work.” Relay the CLI stdout as-is (it already includes the count header; title lines are clickable `[relativePath](fileUri)` links).
|
|
6
6
|
|
|
7
7
|
Otherwise, from the linked project folder or any subdirectory beneath it:
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ Otherwise, from the linked project folder or any subdirectory beneath it:
|
|
|
12
12
|
|
|
13
13
|
2. If empty: tell the user there are no handoffs yet, then read repo `AGENTS.md` only and proceed.
|
|
14
14
|
|
|
15
|
-
3. Otherwise, read that file. If the user names a specific session instead: `{{GROUNDER_CLI}} handoff list --limit 5` → match name/index to the indented path in *this* listing (positional, not a stable id). Miss → once with `--limit 50` (*that* listing only). Still miss → tell the user and stop — no guessed hydrate.
|
|
15
|
+
3. Otherwise, read that file. If the user names a specific session instead: `{{GROUNDER_CLI}} handoff list --limit 5 --markdown` → match name/index to the indented absolute path in *this* listing (positional, not a stable id). Miss → once with `--limit 50 --markdown` (*that* listing only). Still miss → tell the user and stop — no guessed hydrate.
|
|
16
16
|
|
|
17
17
|
4. Read repo `AGENTS.md` (project conventions and constraints).
|
|
18
18
|
|