memtrace-skills 1.2.5 → 1.2.7
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/dist/transformers/cursor.js +1 -1
- package/package.json +1 -1
- package/plugins/memtrace-skills/references/mcp-parameters.md +43 -3
- package/plugins/memtrace-skills/skills/memtrace-codebase-exploration/SKILL.md +17 -0
- package/plugins/memtrace-skills/skills/memtrace-first/SKILL.md +113 -17
- package/plugins/memtrace-skills/skills/memtrace-graph/SKILL.md +12 -0
- package/plugins/memtrace-skills/skills/memtrace-index/SKILL.md +19 -2
- package/plugins/memtrace-skills/skills/memtrace-search/SKILL.md +22 -4
- package/skills/commands/memtrace-graph.md +12 -0
- package/skills/commands/memtrace-index.md +19 -2
- package/skills/commands/memtrace-search.md +22 -4
- package/skills/workflows/memtrace-codebase-exploration.md +17 -0
- package/skills/workflows/memtrace-first.md +113 -17
|
@@ -60,7 +60,7 @@ function cursorWorkspaceBoundaryWarnings(ctx) {
|
|
|
60
60
|
if (fs.existsSync(path.join(ctx.cwd, '.memtrace-workspace')))
|
|
61
61
|
return [];
|
|
62
62
|
return [
|
|
63
|
-
`Cursor install target ${ctx.cwd} contains multiple sibling git repos but is not a blessed Memtrace workspace. For separate MemDBs, install/open each repo root. To intentionally share one MemDB, run 'memtrace start --bless-workspace' from ${ctx.cwd}, then verify with 'memtrace workspace status ${ctx.cwd}'.`,
|
|
63
|
+
`Cursor install target ${ctx.cwd} contains multiple sibling git repos but is not a blessed Memtrace workspace. For separate MemDBs, install/open each repo root. To intentionally share one MemDB, declare the members in a workspace manifest and run 'memtrace start --workspace-file <manifest>', or use the legacy Folder Group flow: 'memtrace start --bless-workspace' from ${ctx.cwd}, then verify with 'memtrace workspace status ${ctx.cwd}'. Once a store's membership is declared, a Memtrace MCP session can never widen it — adding a repo means editing the manifest and restarting that store's daemon with 'memtrace start --workspace-file <manifest>'.`,
|
|
64
64
|
];
|
|
65
65
|
}
|
|
66
66
|
export function registerCursorMcpAt(mcpFile, binary) {
|
package/package.json
CHANGED
|
@@ -31,20 +31,60 @@ arrays as arrays. No quoting numbers, no `"true"` for booleans.
|
|
|
31
31
|
|
|
32
32
|
| Param | Type | Meaning |
|
|
33
33
|
|---|---|---|
|
|
34
|
-
| `repo_id` | string | Repository identifier from `list_indexed_repositories` (usually the repo folder name, e.g. `"memtrace"`) |
|
|
34
|
+
| `repo_id` | string | Repository identifier from `list_indexed_repositories` (usually the repo folder name, e.g. `"memtrace"`). That list covers this session's store only — see "A `repo_id` this session's store does not hold" below |
|
|
35
35
|
| `branch` *or* `branch_name` | string | Git branch. Default `"main"` across every tool. Both spellings occur historically — use whichever the specific tool's schema says |
|
|
36
36
|
| `limit` | integer | Cap on returned results. Always a JSON number, never a string |
|
|
37
37
|
| `depth` | integer | Graph traversal hops. 1–5 is reasonable; >8 explodes on wide graphs |
|
|
38
38
|
| `target` / `symbol` | string | Symbol **name** for graph tools — `get_impact`/`analyze_relationships` use `target`; `get_symbol_context` uses `symbol` |
|
|
39
39
|
| `from` / `to` / `since` / `until` | string | e.g. `"90d ago"`, `"2026-04-17T13:00:00Z"`, `"yesterday"` — relative strings work for temporal tools. **Never `days` on `get_evolution`.** |
|
|
40
40
|
|
|
41
|
+
|
|
42
|
+
## A `repo_id` this session's store does not hold
|
|
43
|
+
|
|
44
|
+
Ten tools check the requested `repo_id` against this store's declared members
|
|
45
|
+
before they answer: `find_code`, `find_symbol`, `get_codebase_briefing`,
|
|
46
|
+
`find_central_symbols`, `find_dependency_path`, `find_bridge_symbols`,
|
|
47
|
+
`list_processes`, `get_process_flow`, `list_communities` and
|
|
48
|
+
`get_repository_stats`. On those, a wrong `repo_id` is never a success-shaped
|
|
49
|
+
zero.
|
|
50
|
+
|
|
51
|
+
- If a live runtime's store declares the repository, the read is forwarded to
|
|
52
|
+
it and the answer carries `_meta.answered_by: "store_owner_daemon"`,
|
|
53
|
+
`_meta.owner_pid`, `_meta.owner_http` and `_meta.store`.
|
|
54
|
+
- Otherwise the call is refused: `repo_in_store: false`,
|
|
55
|
+
`error_code: "repo_not_in_store"`, `count: 0`, and a `diagnostic` naming the
|
|
56
|
+
store that answered, its `members`, `reason` and `repo_lives_in` when a
|
|
57
|
+
runtime declares the repository elsewhere. Nothing was searched. A `reason`
|
|
58
|
+
of `ambiguous_repo_id` is the opposite case: the id matches more than one
|
|
59
|
+
repository in this store, so pass the exact id.
|
|
60
|
+
|
|
61
|
+
The remaining `repo_id` tools do not check membership: the relationship tools
|
|
62
|
+
(`get_symbol_context`, `get_impact`, `analyze_relationships`), the temporal
|
|
63
|
+
tools (`get_evolution`, `get_timeline`, `get_changes_since`), the topology
|
|
64
|
+
tools (`get_api_topology`, `find_api_endpoints`, `find_api_calls`,
|
|
65
|
+
`get_service_diagram`) and `get_source_window`. They read this session's store
|
|
66
|
+
whatever id you pass, set no `repo_in_store` key, and return an ordinary empty
|
|
67
|
+
result for a repository this store does not hold. A zero from one of them is
|
|
68
|
+
not an absence — confirm the repository is a member with one of the ten above
|
|
69
|
+
first.
|
|
70
|
+
|
|
71
|
+
`repo_in_store: true` means membership was proven. `repo_in_store: null` means
|
|
72
|
+
the session discovered no workspace, so membership was assumed rather than
|
|
73
|
+
proven.
|
|
74
|
+
|
|
75
|
+
Tools that change a store, a runtime, or anything outside the process
|
|
76
|
+
(`index_directory`, `delete_repository`, `watch_directory`, `link_*`,
|
|
77
|
+
`cleanup_*`, `replay_history`, the mutating `fleet_*` calls, and the rest) are
|
|
78
|
+
never forwarded. Run them from the session attached to the store that holds
|
|
79
|
+
the repository.
|
|
80
|
+
|
|
41
81
|
## Search & discovery
|
|
42
82
|
|
|
43
83
|
### `find_code`
|
|
44
84
|
| Field | Type | Required | Default | Notes |
|
|
45
85
|
|---|---|---|---|---|
|
|
46
86
|
| `query` | string | yes | — | Natural-language text |
|
|
47
|
-
| `repo_id` | string | no |
|
|
87
|
+
| `repo_id` | string | no | this store's members | Scope to one repo. Omitted, an unambiguous session resolves to its own repository and a multi-repo store fans out across its discovered members |
|
|
48
88
|
| `file_path` | string | no | — | Path substring filter |
|
|
49
89
|
| `limit` | integer | no | `20` | Max 100 |
|
|
50
90
|
| `as_of` | string | no | now | Time-travel search |
|
|
@@ -58,7 +98,7 @@ No `kind` param — use `find_symbol(kind=...)` instead.
|
|
|
58
98
|
| `name` | string | yes | — | Exact or partial identifier |
|
|
59
99
|
| `fuzzy` | boolean | no | `false` | Exact-match today; field kept for API parity |
|
|
60
100
|
| `edit_distance` | integer | no | `2` | Max 2. Only used when `fuzzy: true` |
|
|
61
|
-
| `repo_id` | string | no |
|
|
101
|
+
| `repo_id` | string | no | inferred | One repository is inferred only when that is unambiguous; otherwise the call returns `repo_scope_required` |
|
|
62
102
|
| `kind` | string | no | — | Same enum as `find_code` |
|
|
63
103
|
| `file_path` | string | no | — | |
|
|
64
104
|
| `limit` | integer | no | `10` | Capped at `50` |
|
|
@@ -15,6 +15,11 @@ Call `list_indexed_repositories` first. If the repo is already indexed, skip to
|
|
|
15
15
|
|
|
16
16
|
Otherwise, call `index_directory` with the project path, then poll `check_job_status` until completion.
|
|
17
17
|
|
|
18
|
+
`list_indexed_repositories` covers this session's store only. If a later call
|
|
19
|
+
answers `error_code: "repo_not_in_store"`, the repository is indexed in the
|
|
20
|
+
store named in `diagnostic.repo_lives_in` — route the question there instead
|
|
21
|
+
of indexing a second copy here.
|
|
22
|
+
|
|
18
23
|
**Success criteria:** Repo appears in `list_indexed_repositories` with non-zero node/edge counts.
|
|
19
24
|
|
|
20
25
|
### 2. Get the lay of the land
|
|
@@ -116,6 +121,18 @@ The deliverable is the 7-part overview above. Skeleton (one headline per part):
|
|
|
116
121
|
6. Recent Activity — 31 episodes in 30d; hottest file per `top_changed_files`
|
|
117
122
|
7. Technical Debt — top-10 complex functions, highest complexity first
|
|
118
123
|
|
|
124
|
+
## A `busy` answer is a wait, not an absence
|
|
125
|
+
|
|
126
|
+
Heavy graph work runs one repository-sized fold at a time, because holding
|
|
127
|
+
two in memory is what the bound protects against. When the lane is already
|
|
128
|
+
held, a caller is not queued indefinitely: after a bounded wait it gets a
|
|
129
|
+
successful answer carrying `"busy": true`, `"lane": "graph_materialization"`,
|
|
130
|
+
`"retryable": true`, and a `holder` block naming the operation that holds the
|
|
131
|
+
lane and how long it has held it. Report it as a wait, retry once the holder
|
|
132
|
+
is likely done, or narrow the call (one `repo_id`, a smaller `limit`, a
|
|
133
|
+
shorter window) so it does not need the lane. Do not read it as an empty
|
|
134
|
+
graph and do not fall back to file search.
|
|
135
|
+
|
|
119
136
|
## Common Mistakes
|
|
120
137
|
|
|
121
138
|
| Mistake | Reality |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: memtrace-first
|
|
3
|
-
description: "Route code discovery, debugging, flow tracing, how-code-works questions, and pre-edit rationale checks in indexed source-code repos to Memtrace graph plus Cortex decision tools. Use first before searching/reading code, and before editing, refactoring, deleting, or re-picking an approach that may have a recorded decision, ban, convention, or contract. Do not use Grep, Glob, rg, find, or manual file browsing for code discovery when Memtrace is indexed. Zero results are not permission to grep; diagnose/reindex with Memtrace."
|
|
3
|
+
description: "Route code discovery, debugging, flow tracing, how-code-works questions, and pre-edit rationale checks in indexed source-code repos to Memtrace graph plus Cortex decision tools. Use first before searching/reading code, and before editing, refactoring, deleting, or re-picking an approach that may have a recorded decision, ban, convention, or contract. Do not use Grep, Glob, rg, find, or manual file browsing for code discovery when Memtrace is indexed. Zero results are not permission to grep; diagnose/reindex with Memtrace. A `repo_not_in_store` refusal means a different store holds the repository: route to that store, never grep and never re-index here."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Memtrace First
|
|
@@ -37,19 +37,93 @@ Memtrace's hybrid search = **BM25 over symbol metadata** (name, signature, file_
|
|
|
37
37
|
|
|
38
38
|
The semantic side means **string literals, error messages, magic constants, log strings, and any text inside an indexed symbol's body are findable through `find_code`**. The body got embedded; the embedding catches it. You do NOT need `Grep` to hunt for `STRIPE_KEY_FOO_BAR` if it lives inside a function in your indexed codebase.
|
|
39
39
|
|
|
40
|
-
##
|
|
40
|
+
## Read the envelope before you diagnose anything
|
|
41
|
+
|
|
42
|
+
An empty-looking answer has three different causes and they need different
|
|
43
|
+
responses: the tool refused because another store holds the repository, the
|
|
44
|
+
tool never checked membership at all, or this store genuinely holds nothing
|
|
45
|
+
for the query. Before diagnosing, check which tool you called and what
|
|
46
|
+
`repo_in_store` and `error_code` say.
|
|
47
|
+
|
|
48
|
+
### Only some tools check membership
|
|
49
|
+
|
|
50
|
+
Ten tools check the requested `repo_id` against this store's declared members
|
|
51
|
+
before they answer, and they are the only ones that set the top-level
|
|
52
|
+
`repo_in_store` key: `find_code`, `find_symbol`, `get_codebase_briefing`,
|
|
53
|
+
`find_central_symbols`, `find_dependency_path`, `find_bridge_symbols`,
|
|
54
|
+
`list_processes`, `get_process_flow`, `list_communities` and
|
|
55
|
+
`get_repository_stats`.
|
|
56
|
+
|
|
57
|
+
Every other tool that takes a `repo_id` — `get_symbol_context`, `get_impact`,
|
|
58
|
+
`analyze_relationships`, `get_evolution`, `get_timeline`, `get_source_window`,
|
|
59
|
+
`get_api_topology` and the rest — reads this session's store whatever id you
|
|
60
|
+
pass. Their answers carry no `repo_in_store` key at all, so a zero from one of
|
|
61
|
+
them is not evidence about membership and not evidence that the repository is
|
|
62
|
+
unindexed. When membership is in doubt, establish it with one of the ten above
|
|
63
|
+
before you conclude anything. `repo_in_store: null` is a third case:
|
|
64
|
+
membership was assumed rather than proven, because the session discovered no
|
|
65
|
+
workspace.
|
|
66
|
+
|
|
67
|
+
### `repo_not_in_store` — wrong store, not a missing index
|
|
68
|
+
|
|
69
|
+
One of the ten, asked for a `repo_id` this session's store does not hold,
|
|
70
|
+
answers `repo_in_store: false` with `error_code: "repo_not_in_store"`. It
|
|
71
|
+
searched nothing. The `diagnostic` block names the store that answered, its
|
|
72
|
+
`members`, the `reason`, and — when a live runtime declares the repository —
|
|
73
|
+
`repo_lives_in` with that store, its path, `owner_pid`, `ui_port`,
|
|
74
|
+
`control_port` and `endpoint`.
|
|
75
|
+
|
|
76
|
+
1. Read `diagnostic.reason` first. `ambiguous_repo_id` is not a routing
|
|
77
|
+
problem: the id matches more than one repository in *this* store, and the
|
|
78
|
+
message says to pass the exact id. Do that and stop here. Everything below
|
|
79
|
+
applies to the `not_in_store` reason.
|
|
80
|
+
2. Do not fall back to file search. The refusal says so itself, in `_note`:
|
|
81
|
+
"Wrong store for this repo_id; do not fall back to filesystem search, ask
|
|
82
|
+
the session attached to the store named in diagnostic.repo_lives_in."
|
|
83
|
+
3. Do not call `index_directory`. The repository is already indexed in the
|
|
84
|
+
store `repo_lives_in` names. Indexing it here would build a second copy in
|
|
85
|
+
the wrong store — writes are never routed to another store, so the call
|
|
86
|
+
lands locally.
|
|
87
|
+
4. Tell the user which store holds it, and route the question to the session
|
|
88
|
+
or daemon attached to that store. A session cannot ask an owner to add a
|
|
89
|
+
repository: changing the members of a store that already has them means
|
|
90
|
+
running `memtrace start` for that store, with `--workspace-file <manifest>`
|
|
91
|
+
or `--workspace <name>` when a manifest or a Named Workspace owns its
|
|
92
|
+
scope.
|
|
93
|
+
5. If `repo_lives_in` is absent, no live Memtrace runtime declares the
|
|
94
|
+
repository. Running `memtrace start` in its own workspace is the fix.
|
|
95
|
+
|
|
96
|
+
A refusal is not the only outcome. When the runtime whose store declares the
|
|
97
|
+
repository is live and publishes a reachable control port, the same read is
|
|
98
|
+
forwarded to it and you get the real answer, marked
|
|
99
|
+
`_meta.answered_by: "store_owner_daemon"` alongside `_meta.owner_pid`,
|
|
100
|
+
`_meta.owner_http` and `_meta.store`. That answer is authoritative; say which
|
|
101
|
+
store produced it.
|
|
102
|
+
|
|
103
|
+
A forwarded read can also come back as a bounded `busy` answer with
|
|
104
|
+
`"lane": "graph_materialization"` and `retryable: true`, naming what holds
|
|
105
|
+
the graph lane and for how long. That is a wait, not an absence — retry, or
|
|
106
|
+
narrow the call.
|
|
41
107
|
|
|
42
|
-
|
|
43
|
-
infer that a source subdirectory is outside the index. Diagnose through
|
|
44
|
-
Memtrace:
|
|
108
|
+
## Zero results are not a grep license
|
|
45
109
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
110
|
+
A genuine zero — `count: 0` from a tool that reported `repo_in_store: true` —
|
|
111
|
+
is a coverage question. Do **not** infer that a source subdirectory is outside
|
|
112
|
+
the index. Diagnose through Memtrace:
|
|
113
|
+
|
|
114
|
+
1. Call `list_indexed_repositories` and identify the repo root/repo_id. It
|
|
115
|
+
lists this session's store only, so a repository missing from it may still
|
|
116
|
+
be indexed and live in another store.
|
|
117
|
+
2. If the zero came from a tool that sets no `repo_in_store` key, re-ask about
|
|
118
|
+
the same repository through `find_code` or `find_symbol` before reading
|
|
119
|
+
anything into it. Those check membership; the first tool did not.
|
|
120
|
+
3. If the path is under that indexed repo root, keep using Memtrace.
|
|
121
|
+
4. Retry with broader `find_code` terms and, when available, `file_path` filters
|
|
49
122
|
such as `ui/`, `memtrace-ui/`, `src/`, or the framework directory.
|
|
50
|
-
|
|
51
|
-
root with `incremental: true` (or ask before `clear_existing: true`).
|
|
52
|
-
|
|
123
|
+
5. If the language/path still appears missing, run `index_directory` on the repo
|
|
124
|
+
root with `incremental: true` (or ask before `clear_existing: true`). Do
|
|
125
|
+
this only after steps 1 and 2 show the repository is a member of this store.
|
|
126
|
+
6. Report the indexing coverage problem instead of silently switching to grep.
|
|
53
127
|
|
|
54
128
|
### Workspace Boundary Check
|
|
55
129
|
|
|
@@ -61,9 +135,22 @@ answer from stale repos.
|
|
|
61
135
|
|
|
62
136
|
- For separate repos: use the actual git repo root as the `index_directory`
|
|
63
137
|
path, or ask the user to open/run the agent from that repo root.
|
|
64
|
-
- For an intentional shared workspace:
|
|
65
|
-
`memtrace start --
|
|
138
|
+
- For an intentional shared workspace: a portable manifest is the durable
|
|
139
|
+
form — `memtrace start --workspace-file <manifest>` declares the members and
|
|
140
|
+
records the manifest as the owner of the store's membership. The Folder
|
|
141
|
+
Group flow still works and the CLI now calls it legacy: the user blesses the
|
|
142
|
+
parent with `memtrace start --bless-workspace`, then verifies it with
|
|
66
143
|
`memtrace workspace status <path>`; the workspace marker should be present.
|
|
144
|
+
- A store whose membership is already owned by a manifest or a Named Workspace
|
|
145
|
+
cannot be widened by a plain `memtrace start` from a parent folder. That
|
|
146
|
+
start is refused with "a folder-walked start cannot widen it. Run
|
|
147
|
+
`<command>`", and the refusal names the exact command to run instead. Run
|
|
148
|
+
it. Do not route around the refusal by indexing elsewhere. A folder-sourced
|
|
149
|
+
store has no owning definition, so that refusal does not apply to it. A
|
|
150
|
+
`memtrace mcp` session can never widen an existing store under any flag,
|
|
151
|
+
including `--workspace-file`: adding a repository is always a `memtrace
|
|
152
|
+
start` for that store, carrying the manifest or the workspace name when one
|
|
153
|
+
owns its members.
|
|
67
154
|
- If `list_indexed_repositories` returns empty or its metadata says the MCP
|
|
68
155
|
child resolved a data dir from cwd because no workspace marker/git root was
|
|
69
156
|
found, surface the workspace mismatch. Do not "fix" it by indexing the broad
|
|
@@ -79,8 +166,11 @@ These are the ONLY cases where file tools beat memtrace:
|
|
|
79
166
|
|
|
80
167
|
- **Files outside every indexed repo root.** Confirm this with
|
|
81
168
|
`list_indexed_repositories`; 0 search results or missing language stats do not
|
|
82
|
-
prove it
|
|
83
|
-
|
|
169
|
+
prove it, and neither does a `repo_not_in_store` refusal — that list covers
|
|
170
|
+
this session's store only, and the refusal's `diagnostic.repo_lives_in`
|
|
171
|
+
names the store that does hold the repository. Vendored deps, system
|
|
172
|
+
headers, and excluded dirs (`.git`, `node_modules`, `target`, `dist`) are
|
|
173
|
+
examples Memtrace cannot see.
|
|
84
174
|
- **Non-source artifacts.** `.env`, `package.json`, build scripts, top-level `README.md`, raw config files. Memtrace indexes parseable code, not configuration text.
|
|
85
175
|
- **Pure file-inventory questions.** "How many `*.test.ts` files exist", "list every Markdown file in `docs/`". You're asking for a file count, not a symbol search.
|
|
86
176
|
- **Reading at a known path outside Memtrace.** For configs, docs, or non-source artifacts that Memtrace cannot index, file `Read` is fine. For source-code spans returned by Memtrace, read the precise line range (your harness's `Read` with offset/limit, or `get_source_window` if your harness lacks bounded reads). Do not whole-file Read when you have a span.
|
|
@@ -101,6 +191,8 @@ For everything else inside the indexed repo, memtrace is the right tool.
|
|
|
101
191
|
| "Should I change/delete/refactor `foo`?" | `find_symbol`/`get_symbol_context` → `recall_decision("foo / subsystem / approach")`; if a symbol id is available, `why_is_this_here` + `governing_contracts`; then `get_impact`. |
|
|
102
192
|
| "Can I use/switch to pattern or library X?" | `recall_decision("X")` FIRST; bans and conventions are decisions. Verify a matching decision with `verify_intent(decision_id)` before relying on it. |
|
|
103
193
|
| "What changed in `auth.ts` last week?" | `get_evolution(repo_id, from="7d ago", mode="recent", file_path="auth.ts")`. |
|
|
194
|
+
| The answer carries `error_code: "repo_not_in_store"` | Read `diagnostic.reason`. On `ambiguous_repo_id`, pass the exact id. Otherwise read `diagnostic.repo_lives_in` and route the question to the session attached to that store. Never grep, never `index_directory`. |
|
|
195
|
+
| A `repo_id` tool answered zero with no `repo_in_store` key | It never checked membership. Re-ask through `find_code` or `find_symbol` before treating the zero as an absence. |
|
|
104
196
|
| "List all `*.test.ts` files." | `Glob` (file inventory, not symbol search). |
|
|
105
197
|
| "Find this string in my `.env`." | `Grep` (non-source artifact). |
|
|
106
198
|
| "I'm about to edit `foo` — show me its source." | Bounded `Read(file_path, offset=start_line, limit=end_line-start_line+8)`, or `get_source_window` if your harness lacks bounded reads. Never whole-file. |
|
|
@@ -203,7 +295,9 @@ You are violating this skill if you think:
|
|
|
203
295
|
| "I'll just switch to library/pattern X" | `recall_decision("X")` first — you may be reintroducing a banned approach. |
|
|
204
296
|
| "It's just a quick search" | Grep has no understanding of call graphs, communities, or time |
|
|
205
297
|
| "I don't know if it's indexed" | Check with `list_indexed_repositories` first — takes 1 second |
|
|
206
|
-
| "Memtrace returned 0 results" |
|
|
298
|
+
| "Memtrace returned 0 results" | Check `repo_in_store` first. If it is true, broaden the query, check repo_id/path coverage, then reindex if needed |
|
|
299
|
+
| "The zero had no `repo_in_store`, so the repo is not indexed" | Only ten tools set that key. A zero from the others says nothing about membership — re-ask through `find_code` or `find_symbol` |
|
|
300
|
+
| "It said `repo_not_in_store`, so I'll index it here" | The repository is already indexed in the store `diagnostic.repo_lives_in` names. Indexing here makes a second copy in the wrong store |
|
|
207
301
|
| "Stats only show Rust, but I need `ui/` or `memtrace-ui/`" | That is a coverage diagnostic. Reindex the repo root; do not grep source code. |
|
|
208
302
|
| "The user didn't say to use Memtrace" | User asked about the code. Repo is indexed. Use Memtrace. |
|
|
209
303
|
| "This is a simple question" | Simple questions benefit most — one `find_symbol` vs 20 file reads |
|
|
@@ -253,5 +347,7 @@ When this skill applies, it overrides default file-search behavior. Use the spec
|
|
|
253
347
|
|
|
254
348
|
- The answer is grounded in Memtrace graph results (search hit → `get_symbol_context` / `get_impact`), not file-tool discovery.
|
|
255
349
|
- Grep/Glob/Read appear only via the documented narrow exceptions (non-source artifacts, paths outside every indexed root, file inventory, bounded span reads).
|
|
256
|
-
-
|
|
350
|
+
- A `repo_not_in_store` refusal was routed on `diagnostic.repo_lives_in`, not answered by grep and not answered by indexing the repository into this store.
|
|
351
|
+
- Genuine zero-result queries (`repo_in_store: true`) were diagnosed (`list_indexed_repositories` → broaden → reindex), not bypassed to grep.
|
|
352
|
+
- A zero from a tool that sets no `repo_in_store` key was re-checked through a membership-checking tool before it was called an absence.
|
|
257
353
|
- Any source read was bounded to the span Memtrace returned.
|
|
@@ -73,6 +73,18 @@ Params are **`source`** and **`target`** (symbol names) — not `from`/`to`.
|
|
|
73
73
|
|
|
74
74
|
`find_dependency_path` returns the ordered symbol chain from `source` to `target`; `list_communities` returns module partitions with their member symbols.
|
|
75
75
|
|
|
76
|
+
## A `busy` answer is a wait, not an absence
|
|
77
|
+
|
|
78
|
+
Heavy graph work runs one repository-sized fold at a time, because holding
|
|
79
|
+
two in memory is what the bound protects against. When the lane is already
|
|
80
|
+
held, a caller is not queued indefinitely: after a bounded wait it gets a
|
|
81
|
+
successful answer carrying `"busy": true`, `"lane": "graph_materialization"`,
|
|
82
|
+
`"retryable": true`, and a `holder` block naming the operation that holds the
|
|
83
|
+
lane and how long it has held it. Report it as a wait, retry once the holder
|
|
84
|
+
is likely done, or narrow the call (one `repo_id`, a smaller `limit`, a
|
|
85
|
+
shorter window) so it does not need the lane. Do not read it as an empty
|
|
86
|
+
graph and do not fall back to file search.
|
|
87
|
+
|
|
76
88
|
## Common Mistakes
|
|
77
89
|
|
|
78
90
|
| Mistake | Reality |
|
|
@@ -33,6 +33,13 @@ root (for example `ui/`, `memtrace-ui/`, `web/`, `frontend/`, or `src/`), treat
|
|
|
33
33
|
that as a stale/partial index. Do not use grep as a workaround. Run incremental
|
|
34
34
|
indexing on the repo root, then retry the Memtrace query.
|
|
35
35
|
|
|
36
|
+
If a search instead came back with `error_code: "repo_not_in_store"`, stop.
|
|
37
|
+
That repository is not missing from the index; it is indexed in a different
|
|
38
|
+
store, named in `diagnostic.repo_lives_in`. `list_indexed_repositories` lists
|
|
39
|
+
this session's store only, so its absence there proves nothing. Indexing it
|
|
40
|
+
here would build a second copy in the wrong store. Report the store that holds
|
|
41
|
+
it and route the question to the session or daemon attached to that store.
|
|
42
|
+
|
|
36
43
|
### 2. Index the directory
|
|
37
44
|
|
|
38
45
|
Use the `index_directory` MCP tool:
|
|
@@ -44,10 +51,20 @@ Use the `index_directory` MCP tool:
|
|
|
44
51
|
If the selected path is just a folder containing multiple independent git repos,
|
|
45
52
|
do not index that parent folder unless the user explicitly wants a shared
|
|
46
53
|
workspace. For separate repos, index each repo root separately. For intentional
|
|
47
|
-
sharing,
|
|
48
|
-
`memtrace start --
|
|
54
|
+
sharing, the durable form is a portable manifest started with
|
|
55
|
+
`memtrace start --workspace-file <manifest>`; the legacy Folder Group flow is
|
|
56
|
+
`memtrace start --bless-workspace` from the parent, verified with
|
|
49
57
|
`memtrace workspace status <path>`.
|
|
50
58
|
|
|
59
|
+
A store whose membership is already owned by a manifest or a Named Workspace
|
|
60
|
+
cannot be widened from an MCP session, nor by a plain `memtrace start` from a
|
|
61
|
+
parent folder. Adding a repository means restarting that store's daemon with
|
|
62
|
+
the definition that owns it — `memtrace start --workspace-file <manifest>` or
|
|
63
|
+
`memtrace start --workspace <name>`, editing the manifest first when it is a
|
|
64
|
+
manifest. If a start is refused with "a folder-walked start cannot widen it",
|
|
65
|
+
run the command the refusal names. No MCP session can widen an existing store
|
|
66
|
+
under any flag, whatever declared it.
|
|
67
|
+
|
|
51
68
|
**Success criteria:** You receive a `job_id` immediately.
|
|
52
69
|
|
|
53
70
|
### 3. Poll for completion
|
|
@@ -22,7 +22,7 @@ Find code using hybrid BM25 + semantic search (RRF). Primary discovery tool —
|
|
|
22
22
|
| Param | Required | Default | Notes |
|
|
23
23
|
|---|---|---|---|
|
|
24
24
|
| `query` | yes | — | Natural language or symbol text |
|
|
25
|
-
| `repo_id` | no |
|
|
25
|
+
| `repo_id` | no | this store's members | Omitted, an unambiguous session resolves to its own repository; a multi-repo store fans out across its discovered members |
|
|
26
26
|
| `limit` | no | 20 | Max 100 |
|
|
27
27
|
| `file_path` | no | — | Path/directory substring filter |
|
|
28
28
|
| `as_of` | no | now | ISO-8601 time-travel |
|
|
@@ -39,7 +39,7 @@ Find code using hybrid BM25 + semantic search (RRF). Primary discovery tool —
|
|
|
39
39
|
| Param | Required | Default | Notes |
|
|
40
40
|
|---|---|---|---|
|
|
41
41
|
| `name` | yes | — | Symbol name to search |
|
|
42
|
-
| `repo_id` | no |
|
|
42
|
+
| `repo_id` | no | inferred | One repository is inferred only when that is unambiguous; otherwise the call returns `repo_scope_required` |
|
|
43
43
|
| `fuzzy` | no | false | API field exists; currently exact-match in backend |
|
|
44
44
|
| `edit_distance` | no | 2 | Only when fuzzy enabled |
|
|
45
45
|
| `kind` | no | — | `Function`, `Class`, `Method`, etc. |
|
|
@@ -58,7 +58,7 @@ Full parameter spec for every Memtrace tool: `references/mcp-parameters.md` (bun
|
|
|
58
58
|
|
|
59
59
|
- Exact name → `find_symbol`
|
|
60
60
|
- Behaviour description → `find_code`
|
|
61
|
-
-
|
|
61
|
+
- Every member of this store → omit `repo_id` on `find_code`. `find_symbol` needs one repository and infers it only when that is unambiguous.
|
|
62
62
|
|
|
63
63
|
### 2. Execute search
|
|
64
64
|
|
|
@@ -98,6 +98,23 @@ One `find_code` / `find_symbol` result entry:
|
|
|
98
98
|
|
|
99
99
|
`score` (and `id`) appear only with `include_diagnostics: true`.
|
|
100
100
|
|
|
101
|
+
## A `repo_id` this store does not hold
|
|
102
|
+
|
|
103
|
+
`find_code` and `find_symbol` check membership before they search. If the
|
|
104
|
+
`repo_id` you passed is not a member of this session's store, the call is
|
|
105
|
+
handed to the live runtime whose store declares it, and the answer comes back
|
|
106
|
+
marked `_meta.answered_by: "store_owner_daemon"` with `_meta.owner_pid`,
|
|
107
|
+
`_meta.owner_http` and `_meta.store`. Use that answer and say which store
|
|
108
|
+
produced it.
|
|
109
|
+
|
|
110
|
+
If no live runtime holds the repository, or its owner cannot answer, you get
|
|
111
|
+
a refusal instead: `repo_in_store: false`, `error_code: "repo_not_in_store"`,
|
|
112
|
+
`count: 0`, and a `diagnostic` naming this store, its `members` and — when it
|
|
113
|
+
is known — `repo_lives_in`. Nothing was searched. Do not read that as an
|
|
114
|
+
empty index, do not switch to grep, and do not index the repository into this
|
|
115
|
+
store. Route the question to the session attached to the store the diagnostic
|
|
116
|
+
names.
|
|
117
|
+
|
|
101
118
|
## Common Mistakes
|
|
102
119
|
|
|
103
120
|
| Mistake | Reality |
|
|
@@ -105,4 +122,5 @@ One `find_code` / `find_symbol` result entry:
|
|
|
105
122
|
| `find_code(kind=...)` | **`kind` only on `find_symbol`** |
|
|
106
123
|
| Passing symbol `id` to graph tools | Use **`name`** as `symbol` / `target` |
|
|
107
124
|
| Assuming `fuzzy: true` always works | Backend is exact-match today — try spelling variants |
|
|
108
|
-
| Skipping `list_indexed_repositories` | Verify repo is indexed first |
|
|
125
|
+
| Skipping `list_indexed_repositories` | Verify repo is indexed first — it lists this session's store only |
|
|
126
|
+
| Reading `repo_not_in_store` as an empty index | Nothing was searched; the repository lives in the store `diagnostic.repo_lives_in` names |
|
|
@@ -85,6 +85,18 @@ Params are **`source`** and **`target`** (symbol names) — not `from`/`to`.
|
|
|
85
85
|
|
|
86
86
|
`find_dependency_path` returns the ordered symbol chain from `source` to `target`; `list_communities` returns module partitions with their member symbols.
|
|
87
87
|
|
|
88
|
+
## A `busy` answer is a wait, not an absence
|
|
89
|
+
|
|
90
|
+
Heavy graph work runs one repository-sized fold at a time, because holding
|
|
91
|
+
two in memory is what the bound protects against. When the lane is already
|
|
92
|
+
held, a caller is not queued indefinitely: after a bounded wait it gets a
|
|
93
|
+
successful answer carrying `"busy": true`, `"lane": "graph_materialization"`,
|
|
94
|
+
`"retryable": true`, and a `holder` block naming the operation that holds the
|
|
95
|
+
lane and how long it has held it. Report it as a wait, retry once the holder
|
|
96
|
+
is likely done, or narrow the call (one `repo_id`, a smaller `limit`, a
|
|
97
|
+
shorter window) so it does not need the lane. Do not read it as an empty
|
|
98
|
+
graph and do not fall back to file search.
|
|
99
|
+
|
|
88
100
|
## Common Mistakes
|
|
89
101
|
|
|
90
102
|
| Mistake | Reality |
|
|
@@ -43,6 +43,13 @@ root (for example `ui/`, `memtrace-ui/`, `web/`, `frontend/`, or `src/`), treat
|
|
|
43
43
|
that as a stale/partial index. Do not use grep as a workaround. Run incremental
|
|
44
44
|
indexing on the repo root, then retry the Memtrace query.
|
|
45
45
|
|
|
46
|
+
If a search instead came back with `error_code: "repo_not_in_store"`, stop.
|
|
47
|
+
That repository is not missing from the index; it is indexed in a different
|
|
48
|
+
store, named in `diagnostic.repo_lives_in`. `list_indexed_repositories` lists
|
|
49
|
+
this session's store only, so its absence there proves nothing. Indexing it
|
|
50
|
+
here would build a second copy in the wrong store. Report the store that holds
|
|
51
|
+
it and route the question to the session or daemon attached to that store.
|
|
52
|
+
|
|
46
53
|
### 2. Index the directory
|
|
47
54
|
|
|
48
55
|
Use the `index_directory` MCP tool:
|
|
@@ -54,10 +61,20 @@ Use the `index_directory` MCP tool:
|
|
|
54
61
|
If the selected path is just a folder containing multiple independent git repos,
|
|
55
62
|
do not index that parent folder unless the user explicitly wants a shared
|
|
56
63
|
workspace. For separate repos, index each repo root separately. For intentional
|
|
57
|
-
sharing,
|
|
58
|
-
`memtrace start --
|
|
64
|
+
sharing, the durable form is a portable manifest started with
|
|
65
|
+
`memtrace start --workspace-file <manifest>`; the legacy Folder Group flow is
|
|
66
|
+
`memtrace start --bless-workspace` from the parent, verified with
|
|
59
67
|
`memtrace workspace status <path>`.
|
|
60
68
|
|
|
69
|
+
A store whose membership is already owned by a manifest or a Named Workspace
|
|
70
|
+
cannot be widened from an MCP session, nor by a plain `memtrace start` from a
|
|
71
|
+
parent folder. Adding a repository means restarting that store's daemon with
|
|
72
|
+
the definition that owns it — `memtrace start --workspace-file <manifest>` or
|
|
73
|
+
`memtrace start --workspace <name>`, editing the manifest first when it is a
|
|
74
|
+
manifest. If a start is refused with "a folder-walked start cannot widen it",
|
|
75
|
+
run the command the refusal names. No MCP session can widen an existing store
|
|
76
|
+
under any flag, whatever declared it.
|
|
77
|
+
|
|
61
78
|
**Success criteria:** You receive a `job_id` immediately.
|
|
62
79
|
|
|
63
80
|
### 3. Poll for completion
|
|
@@ -32,7 +32,7 @@ Find code using hybrid BM25 + semantic search (RRF). Primary discovery tool —
|
|
|
32
32
|
| Param | Required | Default | Notes |
|
|
33
33
|
|---|---|---|---|
|
|
34
34
|
| `query` | yes | — | Natural language or symbol text |
|
|
35
|
-
| `repo_id` | no |
|
|
35
|
+
| `repo_id` | no | this store's members | Omitted, an unambiguous session resolves to its own repository; a multi-repo store fans out across its discovered members |
|
|
36
36
|
| `limit` | no | 20 | Max 100 |
|
|
37
37
|
| `file_path` | no | — | Path/directory substring filter |
|
|
38
38
|
| `as_of` | no | now | ISO-8601 time-travel |
|
|
@@ -49,7 +49,7 @@ Find code using hybrid BM25 + semantic search (RRF). Primary discovery tool —
|
|
|
49
49
|
| Param | Required | Default | Notes |
|
|
50
50
|
|---|---|---|---|
|
|
51
51
|
| `name` | yes | — | Symbol name to search |
|
|
52
|
-
| `repo_id` | no |
|
|
52
|
+
| `repo_id` | no | inferred | One repository is inferred only when that is unambiguous; otherwise the call returns `repo_scope_required` |
|
|
53
53
|
| `fuzzy` | no | false | API field exists; currently exact-match in backend |
|
|
54
54
|
| `edit_distance` | no | 2 | Only when fuzzy enabled |
|
|
55
55
|
| `kind` | no | — | `Function`, `Class`, `Method`, etc. |
|
|
@@ -68,7 +68,7 @@ Full parameter spec for every Memtrace tool: `references/mcp-parameters.md` (bun
|
|
|
68
68
|
|
|
69
69
|
- Exact name → `find_symbol`
|
|
70
70
|
- Behaviour description → `find_code`
|
|
71
|
-
-
|
|
71
|
+
- Every member of this store → omit `repo_id` on `find_code`. `find_symbol` needs one repository and infers it only when that is unambiguous.
|
|
72
72
|
|
|
73
73
|
### 2. Execute search
|
|
74
74
|
|
|
@@ -108,6 +108,23 @@ One `find_code` / `find_symbol` result entry:
|
|
|
108
108
|
|
|
109
109
|
`score` (and `id`) appear only with `include_diagnostics: true`.
|
|
110
110
|
|
|
111
|
+
## A `repo_id` this store does not hold
|
|
112
|
+
|
|
113
|
+
`find_code` and `find_symbol` check membership before they search. If the
|
|
114
|
+
`repo_id` you passed is not a member of this session's store, the call is
|
|
115
|
+
handed to the live runtime whose store declares it, and the answer comes back
|
|
116
|
+
marked `_meta.answered_by: "store_owner_daemon"` with `_meta.owner_pid`,
|
|
117
|
+
`_meta.owner_http` and `_meta.store`. Use that answer and say which store
|
|
118
|
+
produced it.
|
|
119
|
+
|
|
120
|
+
If no live runtime holds the repository, or its owner cannot answer, you get
|
|
121
|
+
a refusal instead: `repo_in_store: false`, `error_code: "repo_not_in_store"`,
|
|
122
|
+
`count: 0`, and a `diagnostic` naming this store, its `members` and — when it
|
|
123
|
+
is known — `repo_lives_in`. Nothing was searched. Do not read that as an
|
|
124
|
+
empty index, do not switch to grep, and do not index the repository into this
|
|
125
|
+
store. Route the question to the session attached to the store the diagnostic
|
|
126
|
+
names.
|
|
127
|
+
|
|
111
128
|
## Common Mistakes
|
|
112
129
|
|
|
113
130
|
| Mistake | Reality |
|
|
@@ -115,4 +132,5 @@ One `find_code` / `find_symbol` result entry:
|
|
|
115
132
|
| `find_code(kind=...)` | **`kind` only on `find_symbol`** |
|
|
116
133
|
| Passing symbol `id` to graph tools | Use **`name`** as `symbol` / `target` |
|
|
117
134
|
| Assuming `fuzzy: true` always works | Backend is exact-match today — try spelling variants |
|
|
118
|
-
| Skipping `list_indexed_repositories` | Verify repo is indexed first |
|
|
135
|
+
| Skipping `list_indexed_repositories` | Verify repo is indexed first — it lists this session's store only |
|
|
136
|
+
| Reading `repo_not_in_store` as an empty index | Nothing was searched; the repository lives in the store `diagnostic.repo_lives_in` names |
|
|
@@ -33,6 +33,11 @@ Call `list_indexed_repositories` first. If the repo is already indexed, skip to
|
|
|
33
33
|
|
|
34
34
|
Otherwise, call `index_directory` with the project path, then poll `check_job_status` until completion.
|
|
35
35
|
|
|
36
|
+
`list_indexed_repositories` covers this session's store only. If a later call
|
|
37
|
+
answers `error_code: "repo_not_in_store"`, the repository is indexed in the
|
|
38
|
+
store named in `diagnostic.repo_lives_in` — route the question there instead
|
|
39
|
+
of indexing a second copy here.
|
|
40
|
+
|
|
36
41
|
**Success criteria:** Repo appears in `list_indexed_repositories` with non-zero node/edge counts.
|
|
37
42
|
|
|
38
43
|
### 2. Get the lay of the land
|
|
@@ -134,6 +139,18 @@ The deliverable is the 7-part overview above. Skeleton (one headline per part):
|
|
|
134
139
|
6. Recent Activity — 31 episodes in 30d; hottest file per `top_changed_files`
|
|
135
140
|
7. Technical Debt — top-10 complex functions, highest complexity first
|
|
136
141
|
|
|
142
|
+
## A `busy` answer is a wait, not an absence
|
|
143
|
+
|
|
144
|
+
Heavy graph work runs one repository-sized fold at a time, because holding
|
|
145
|
+
two in memory is what the bound protects against. When the lane is already
|
|
146
|
+
held, a caller is not queued indefinitely: after a bounded wait it gets a
|
|
147
|
+
successful answer carrying `"busy": true`, `"lane": "graph_materialization"`,
|
|
148
|
+
`"retryable": true`, and a `holder` block naming the operation that holds the
|
|
149
|
+
lane and how long it has held it. Report it as a wait, retry once the holder
|
|
150
|
+
is likely done, or narrow the call (one `repo_id`, a smaller `limit`, a
|
|
151
|
+
shorter window) so it does not need the lane. Do not read it as an empty
|
|
152
|
+
graph and do not fall back to file search.
|
|
153
|
+
|
|
137
154
|
## Common Mistakes
|
|
138
155
|
|
|
139
156
|
| Mistake | Reality |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: memtrace-first
|
|
3
|
-
description: "Route code discovery, debugging, flow tracing, how-code-works questions, and pre-edit rationale checks in indexed source-code repos to Memtrace graph plus Cortex decision tools. Use first before searching/reading code, and before editing, refactoring, deleting, or re-picking an approach that may have a recorded decision, ban, convention, or contract. Do not use Grep, Glob, rg, find, or manual file browsing for code discovery when Memtrace is indexed. Zero results are not permission to grep; diagnose/reindex with Memtrace."
|
|
3
|
+
description: "Route code discovery, debugging, flow tracing, how-code-works questions, and pre-edit rationale checks in indexed source-code repos to Memtrace graph plus Cortex decision tools. Use first before searching/reading code, and before editing, refactoring, deleting, or re-picking an approach that may have a recorded decision, ban, convention, or contract. Do not use Grep, Glob, rg, find, or manual file browsing for code discovery when Memtrace is indexed. Zero results are not permission to grep; diagnose/reindex with Memtrace. A `repo_not_in_store` refusal means a different store holds the repository: route to that store, never grep and never re-index here."
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- mcp__memtrace__list_indexed_repositories
|
|
6
6
|
- mcp__memtrace__index_directory
|
|
@@ -70,19 +70,93 @@ Memtrace's hybrid search = **BM25 over symbol metadata** (name, signature, file_
|
|
|
70
70
|
|
|
71
71
|
The semantic side means **string literals, error messages, magic constants, log strings, and any text inside an indexed symbol's body are findable through `find_code`**. The body got embedded; the embedding catches it. You do NOT need `Grep` to hunt for `STRIPE_KEY_FOO_BAR` if it lives inside a function in your indexed codebase.
|
|
72
72
|
|
|
73
|
-
##
|
|
73
|
+
## Read the envelope before you diagnose anything
|
|
74
|
+
|
|
75
|
+
An empty-looking answer has three different causes and they need different
|
|
76
|
+
responses: the tool refused because another store holds the repository, the
|
|
77
|
+
tool never checked membership at all, or this store genuinely holds nothing
|
|
78
|
+
for the query. Before diagnosing, check which tool you called and what
|
|
79
|
+
`repo_in_store` and `error_code` say.
|
|
80
|
+
|
|
81
|
+
### Only some tools check membership
|
|
82
|
+
|
|
83
|
+
Ten tools check the requested `repo_id` against this store's declared members
|
|
84
|
+
before they answer, and they are the only ones that set the top-level
|
|
85
|
+
`repo_in_store` key: `find_code`, `find_symbol`, `get_codebase_briefing`,
|
|
86
|
+
`find_central_symbols`, `find_dependency_path`, `find_bridge_symbols`,
|
|
87
|
+
`list_processes`, `get_process_flow`, `list_communities` and
|
|
88
|
+
`get_repository_stats`.
|
|
89
|
+
|
|
90
|
+
Every other tool that takes a `repo_id` — `get_symbol_context`, `get_impact`,
|
|
91
|
+
`analyze_relationships`, `get_evolution`, `get_timeline`, `get_source_window`,
|
|
92
|
+
`get_api_topology` and the rest — reads this session's store whatever id you
|
|
93
|
+
pass. Their answers carry no `repo_in_store` key at all, so a zero from one of
|
|
94
|
+
them is not evidence about membership and not evidence that the repository is
|
|
95
|
+
unindexed. When membership is in doubt, establish it with one of the ten above
|
|
96
|
+
before you conclude anything. `repo_in_store: null` is a third case:
|
|
97
|
+
membership was assumed rather than proven, because the session discovered no
|
|
98
|
+
workspace.
|
|
99
|
+
|
|
100
|
+
### `repo_not_in_store` — wrong store, not a missing index
|
|
101
|
+
|
|
102
|
+
One of the ten, asked for a `repo_id` this session's store does not hold,
|
|
103
|
+
answers `repo_in_store: false` with `error_code: "repo_not_in_store"`. It
|
|
104
|
+
searched nothing. The `diagnostic` block names the store that answered, its
|
|
105
|
+
`members`, the `reason`, and — when a live runtime declares the repository —
|
|
106
|
+
`repo_lives_in` with that store, its path, `owner_pid`, `ui_port`,
|
|
107
|
+
`control_port` and `endpoint`.
|
|
108
|
+
|
|
109
|
+
1. Read `diagnostic.reason` first. `ambiguous_repo_id` is not a routing
|
|
110
|
+
problem: the id matches more than one repository in *this* store, and the
|
|
111
|
+
message says to pass the exact id. Do that and stop here. Everything below
|
|
112
|
+
applies to the `not_in_store` reason.
|
|
113
|
+
2. Do not fall back to file search. The refusal says so itself, in `_note`:
|
|
114
|
+
"Wrong store for this repo_id; do not fall back to filesystem search, ask
|
|
115
|
+
the session attached to the store named in diagnostic.repo_lives_in."
|
|
116
|
+
3. Do not call `index_directory`. The repository is already indexed in the
|
|
117
|
+
store `repo_lives_in` names. Indexing it here would build a second copy in
|
|
118
|
+
the wrong store — writes are never routed to another store, so the call
|
|
119
|
+
lands locally.
|
|
120
|
+
4. Tell the user which store holds it, and route the question to the session
|
|
121
|
+
or daemon attached to that store. A session cannot ask an owner to add a
|
|
122
|
+
repository: changing the members of a store that already has them means
|
|
123
|
+
running `memtrace start` for that store, with `--workspace-file <manifest>`
|
|
124
|
+
or `--workspace <name>` when a manifest or a Named Workspace owns its
|
|
125
|
+
scope.
|
|
126
|
+
5. If `repo_lives_in` is absent, no live Memtrace runtime declares the
|
|
127
|
+
repository. Running `memtrace start` in its own workspace is the fix.
|
|
128
|
+
|
|
129
|
+
A refusal is not the only outcome. When the runtime whose store declares the
|
|
130
|
+
repository is live and publishes a reachable control port, the same read is
|
|
131
|
+
forwarded to it and you get the real answer, marked
|
|
132
|
+
`_meta.answered_by: "store_owner_daemon"` alongside `_meta.owner_pid`,
|
|
133
|
+
`_meta.owner_http` and `_meta.store`. That answer is authoritative; say which
|
|
134
|
+
store produced it.
|
|
135
|
+
|
|
136
|
+
A forwarded read can also come back as a bounded `busy` answer with
|
|
137
|
+
`"lane": "graph_materialization"` and `retryable: true`, naming what holds
|
|
138
|
+
the graph lane and for how long. That is a wait, not an absence — retry, or
|
|
139
|
+
narrow the call.
|
|
74
140
|
|
|
75
|
-
|
|
76
|
-
infer that a source subdirectory is outside the index. Diagnose through
|
|
77
|
-
Memtrace:
|
|
141
|
+
## Zero results are not a grep license
|
|
78
142
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
143
|
+
A genuine zero — `count: 0` from a tool that reported `repo_in_store: true` —
|
|
144
|
+
is a coverage question. Do **not** infer that a source subdirectory is outside
|
|
145
|
+
the index. Diagnose through Memtrace:
|
|
146
|
+
|
|
147
|
+
1. Call `list_indexed_repositories` and identify the repo root/repo_id. It
|
|
148
|
+
lists this session's store only, so a repository missing from it may still
|
|
149
|
+
be indexed and live in another store.
|
|
150
|
+
2. If the zero came from a tool that sets no `repo_in_store` key, re-ask about
|
|
151
|
+
the same repository through `find_code` or `find_symbol` before reading
|
|
152
|
+
anything into it. Those check membership; the first tool did not.
|
|
153
|
+
3. If the path is under that indexed repo root, keep using Memtrace.
|
|
154
|
+
4. Retry with broader `find_code` terms and, when available, `file_path` filters
|
|
82
155
|
such as `ui/`, `memtrace-ui/`, `src/`, or the framework directory.
|
|
83
|
-
|
|
84
|
-
root with `incremental: true` (or ask before `clear_existing: true`).
|
|
85
|
-
|
|
156
|
+
5. If the language/path still appears missing, run `index_directory` on the repo
|
|
157
|
+
root with `incremental: true` (or ask before `clear_existing: true`). Do
|
|
158
|
+
this only after steps 1 and 2 show the repository is a member of this store.
|
|
159
|
+
6. Report the indexing coverage problem instead of silently switching to grep.
|
|
86
160
|
|
|
87
161
|
### Workspace Boundary Check
|
|
88
162
|
|
|
@@ -94,9 +168,22 @@ answer from stale repos.
|
|
|
94
168
|
|
|
95
169
|
- For separate repos: use the actual git repo root as the `index_directory`
|
|
96
170
|
path, or ask the user to open/run the agent from that repo root.
|
|
97
|
-
- For an intentional shared workspace:
|
|
98
|
-
`memtrace start --
|
|
171
|
+
- For an intentional shared workspace: a portable manifest is the durable
|
|
172
|
+
form — `memtrace start --workspace-file <manifest>` declares the members and
|
|
173
|
+
records the manifest as the owner of the store's membership. The Folder
|
|
174
|
+
Group flow still works and the CLI now calls it legacy: the user blesses the
|
|
175
|
+
parent with `memtrace start --bless-workspace`, then verifies it with
|
|
99
176
|
`memtrace workspace status <path>`; the workspace marker should be present.
|
|
177
|
+
- A store whose membership is already owned by a manifest or a Named Workspace
|
|
178
|
+
cannot be widened by a plain `memtrace start` from a parent folder. That
|
|
179
|
+
start is refused with "a folder-walked start cannot widen it. Run
|
|
180
|
+
`<command>`", and the refusal names the exact command to run instead. Run
|
|
181
|
+
it. Do not route around the refusal by indexing elsewhere. A folder-sourced
|
|
182
|
+
store has no owning definition, so that refusal does not apply to it. A
|
|
183
|
+
`memtrace mcp` session can never widen an existing store under any flag,
|
|
184
|
+
including `--workspace-file`: adding a repository is always a `memtrace
|
|
185
|
+
start` for that store, carrying the manifest or the workspace name when one
|
|
186
|
+
owns its members.
|
|
100
187
|
- If `list_indexed_repositories` returns empty or its metadata says the MCP
|
|
101
188
|
child resolved a data dir from cwd because no workspace marker/git root was
|
|
102
189
|
found, surface the workspace mismatch. Do not "fix" it by indexing the broad
|
|
@@ -112,8 +199,11 @@ These are the ONLY cases where file tools beat memtrace:
|
|
|
112
199
|
|
|
113
200
|
- **Files outside every indexed repo root.** Confirm this with
|
|
114
201
|
`list_indexed_repositories`; 0 search results or missing language stats do not
|
|
115
|
-
prove it
|
|
116
|
-
|
|
202
|
+
prove it, and neither does a `repo_not_in_store` refusal — that list covers
|
|
203
|
+
this session's store only, and the refusal's `diagnostic.repo_lives_in`
|
|
204
|
+
names the store that does hold the repository. Vendored deps, system
|
|
205
|
+
headers, and excluded dirs (`.git`, `node_modules`, `target`, `dist`) are
|
|
206
|
+
examples Memtrace cannot see.
|
|
117
207
|
- **Non-source artifacts.** `.env`, `package.json`, build scripts, top-level `README.md`, raw config files. Memtrace indexes parseable code, not configuration text.
|
|
118
208
|
- **Pure file-inventory questions.** "How many `*.test.ts` files exist", "list every Markdown file in `docs/`". You're asking for a file count, not a symbol search.
|
|
119
209
|
- **Reading at a known path outside Memtrace.** For configs, docs, or non-source artifacts that Memtrace cannot index, file `Read` is fine. For source-code spans returned by Memtrace, read the precise line range (your harness's `Read` with offset/limit, or `get_source_window` if your harness lacks bounded reads). Do not whole-file Read when you have a span.
|
|
@@ -134,6 +224,8 @@ For everything else inside the indexed repo, memtrace is the right tool.
|
|
|
134
224
|
| "Should I change/delete/refactor `foo`?" | `find_symbol`/`get_symbol_context` → `recall_decision("foo / subsystem / approach")`; if a symbol id is available, `why_is_this_here` + `governing_contracts`; then `get_impact`. |
|
|
135
225
|
| "Can I use/switch to pattern or library X?" | `recall_decision("X")` FIRST; bans and conventions are decisions. Verify a matching decision with `verify_intent(decision_id)` before relying on it. |
|
|
136
226
|
| "What changed in `auth.ts` last week?" | `get_evolution(repo_id, from="7d ago", mode="recent", file_path="auth.ts")`. |
|
|
227
|
+
| The answer carries `error_code: "repo_not_in_store"` | Read `diagnostic.reason`. On `ambiguous_repo_id`, pass the exact id. Otherwise read `diagnostic.repo_lives_in` and route the question to the session attached to that store. Never grep, never `index_directory`. |
|
|
228
|
+
| A `repo_id` tool answered zero with no `repo_in_store` key | It never checked membership. Re-ask through `find_code` or `find_symbol` before treating the zero as an absence. |
|
|
137
229
|
| "List all `*.test.ts` files." | `Glob` (file inventory, not symbol search). |
|
|
138
230
|
| "Find this string in my `.env`." | `Grep` (non-source artifact). |
|
|
139
231
|
| "I'm about to edit `foo` — show me its source." | Bounded `Read(file_path, offset=start_line, limit=end_line-start_line+8)`, or `get_source_window` if your harness lacks bounded reads. Never whole-file. |
|
|
@@ -236,7 +328,9 @@ You are violating this skill if you think:
|
|
|
236
328
|
| "I'll just switch to library/pattern X" | `recall_decision("X")` first — you may be reintroducing a banned approach. |
|
|
237
329
|
| "It's just a quick search" | Grep has no understanding of call graphs, communities, or time |
|
|
238
330
|
| "I don't know if it's indexed" | Check with `list_indexed_repositories` first — takes 1 second |
|
|
239
|
-
| "Memtrace returned 0 results" |
|
|
331
|
+
| "Memtrace returned 0 results" | Check `repo_in_store` first. If it is true, broaden the query, check repo_id/path coverage, then reindex if needed |
|
|
332
|
+
| "The zero had no `repo_in_store`, so the repo is not indexed" | Only ten tools set that key. A zero from the others says nothing about membership — re-ask through `find_code` or `find_symbol` |
|
|
333
|
+
| "It said `repo_not_in_store`, so I'll index it here" | The repository is already indexed in the store `diagnostic.repo_lives_in` names. Indexing here makes a second copy in the wrong store |
|
|
240
334
|
| "Stats only show Rust, but I need `ui/` or `memtrace-ui/`" | That is a coverage diagnostic. Reindex the repo root; do not grep source code. |
|
|
241
335
|
| "The user didn't say to use Memtrace" | User asked about the code. Repo is indexed. Use Memtrace. |
|
|
242
336
|
| "This is a simple question" | Simple questions benefit most — one `find_symbol` vs 20 file reads |
|
|
@@ -286,5 +380,7 @@ When this skill applies, it overrides default file-search behavior. Use the spec
|
|
|
286
380
|
|
|
287
381
|
- The answer is grounded in Memtrace graph results (search hit → `get_symbol_context` / `get_impact`), not file-tool discovery.
|
|
288
382
|
- Grep/Glob/Read appear only via the documented narrow exceptions (non-source artifacts, paths outside every indexed root, file inventory, bounded span reads).
|
|
289
|
-
-
|
|
383
|
+
- A `repo_not_in_store` refusal was routed on `diagnostic.repo_lives_in`, not answered by grep and not answered by indexing the repository into this store.
|
|
384
|
+
- Genuine zero-result queries (`repo_in_store: true`) were diagnosed (`list_indexed_repositories` → broaden → reindex), not bypassed to grep.
|
|
385
|
+
- A zero from a tool that sets no `repo_in_store` key was re-checked through a membership-checking tool before it was called an absence.
|
|
290
386
|
- Any source read was bounded to the span Memtrace returned.
|