mind-palace-graph 0.3.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/INSTALL.md +387 -0
- package/README.md +602 -0
- package/dist/api.d.ts +682 -0
- package/dist/api.js +660 -0
- package/dist/api.js.map +1 -0
- package/dist/cli.d.ts +95 -0
- package/dist/cli.js +856 -0
- package/dist/cli.js.map +1 -0
- package/dist/format.d.ts +16 -0
- package/dist/format.js +199 -0
- package/dist/format.js.map +1 -0
- package/dist/fuzzy.d.ts +45 -0
- package/dist/fuzzy.js +150 -0
- package/dist/fuzzy.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +528 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +24 -0
- package/dist/mcp-server.js +187 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mind-palace.d.ts +148 -0
- package/dist/mind-palace.js +780 -0
- package/dist/mind-palace.js.map +1 -0
- package/dist/nodes.d.ts +57 -0
- package/dist/nodes.js +220 -0
- package/dist/nodes.js.map +1 -0
- package/dist/pagination.d.ts +41 -0
- package/dist/pagination.js +63 -0
- package/dist/pagination.js.map +1 -0
- package/dist/palace-format.d.ts +30 -0
- package/dist/palace-format.js +146 -0
- package/dist/palace-format.js.map +1 -0
- package/dist/rg.d.ts +34 -0
- package/dist/rg.js +288 -0
- package/dist/rg.js.map +1 -0
- package/dist/sources.d.ts +87 -0
- package/dist/sources.js +457 -0
- package/dist/sources.js.map +1 -0
- package/dist/tokens.d.ts +35 -0
- package/dist/tokens.js +95 -0
- package/dist/tokens.js.map +1 -0
- package/dist/types.d.ts +236 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -0
- package/skills/mpg-context/SKILL.md +556 -0
- package/skills/mpg-context/references/anti-patterns.md +133 -0
- package/skills/mpg-context/references/integration.md +123 -0
- package/skills/mpg-context/references/mind-palace.md +217 -0
- package/skills/mpg-context/references/multi-agent.md +147 -0
- package/skills/mpg-context/references/sources.md +120 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Anti-patterns
|
|
2
|
+
|
|
3
|
+
What NOT to do with mpg, and why.
|
|
4
|
+
|
|
5
|
+
## Search
|
|
6
|
+
|
|
7
|
+
**Don't use `deep` effort for a quick scan.**
|
|
8
|
+
`quick` is 1/10th the cost. Reserve `deep` (2000-token windows, 100
|
|
9
|
+
nodes) for the final answer-grounding pass, not initial recon.
|
|
10
|
+
|
|
11
|
+
**Don't search the same pattern twice without stashing.**
|
|
12
|
+
If you'll need a pattern more than once, `mpg_stash` it the first
|
|
13
|
+
time. Stash storage is cheap; re-running a search is not.
|
|
14
|
+
|
|
15
|
+
**Don't use mpg to read a single file.**
|
|
16
|
+
The host's `read` tool is faster and clearer. mpg is for *searching*
|
|
17
|
+
across multiple files, not retrieving one.
|
|
18
|
+
|
|
19
|
+
**Don't forget `page: 1` when paginating.**
|
|
20
|
+
Without an explicit page, mpg returns everything (up to `max_nodes`).
|
|
21
|
+
For results expected to exceed 10 hits, pass `page: 1, page_size: 5`
|
|
22
|
+
so you can decide whether to keep going.
|
|
23
|
+
|
|
24
|
+
**Don't omit `--in` for non-trivial searches.**
|
|
25
|
+
With no source, mpg reads stdin or errors out. Always be explicit
|
|
26
|
+
about where you're searching.
|
|
27
|
+
|
|
28
|
+
## Mind palace
|
|
29
|
+
|
|
30
|
+
**Don't stash and immediately drop.**
|
|
31
|
+
If you knew you weren't going to need it, you shouldn't have stashed.
|
|
32
|
+
The cost is the stash decision, not the storage.
|
|
33
|
+
|
|
34
|
+
**Don't reuse stash names across unrelated investigations.**
|
|
35
|
+
A new investigation = a new task = a new palace (`--mp-path` /
|
|
36
|
+
`MPG_MIND_PALACE`) OR a name-prefixed stash. Reusing names silently
|
|
37
|
+
overwrites or merges, which surprises the model later.
|
|
38
|
+
|
|
39
|
+
**Don't use comma-separated stash names in `compose` without quoting.**
|
|
40
|
+
The shell may split them. Prefer space-separated:
|
|
41
|
+
`--mp-compose auth-todos perf-hotspots`.
|
|
42
|
+
|
|
43
|
+
**Don't create stashes with names that look like flags.**
|
|
44
|
+
Avoid names like `--help`, `-v`, etc. mpg handles these but the LLM
|
|
45
|
+
should not have to disambiguate.
|
|
46
|
+
|
|
47
|
+
**Don't skip `--mp-prune-dry-run`.**
|
|
48
|
+
Always preview a prune before committing. Stash mistakes are
|
|
49
|
+
permanent — the JSON is overwritten in place.
|
|
50
|
+
|
|
51
|
+
**Don't pound a shared palace with hundreds of near-simultaneous writes.**
|
|
52
|
+
v0.2.4 added a `.lock` + atomic-rename write path, so concurrent
|
|
53
|
+
writers no longer lose data — but they *do* serialize. A swarm of
|
|
54
|
+
agents stashing in tight loops over one palace turns into a
|
|
55
|
+
single-writer queue. For high-write fan-out, give each agent its own
|
|
56
|
+
palace (Layout A in `multi-agent.md`) and compose at the end.
|
|
57
|
+
|
|
58
|
+
**Don't ignore a "WARNING — mind palace is corrupt" stderr line.**
|
|
59
|
+
When mpg encounters an unparseable palace it copies the file aside as
|
|
60
|
+
`<palace>.corrupt.<timestamp>`, taints the in-memory copy, and
|
|
61
|
+
**refuses to save** for the rest of that process. If you press on
|
|
62
|
+
without inspecting the backup, the next process will start from a
|
|
63
|
+
real empty palace once `MPG_FORCE_RESET=1` is set — you'll lose every
|
|
64
|
+
stash that wasn't already on disk in a parseable state. Read the
|
|
65
|
+
backup file first; recover by hand-merging or by deleting the
|
|
66
|
+
corrupt original.
|
|
67
|
+
|
|
68
|
+
**Don't ignore `result.errors[]`.**
|
|
69
|
+
When some sources error and others succeed, `status` is `"partial"`
|
|
70
|
+
and the per-source failures land in `errors: [{source, message}]`.
|
|
71
|
+
Treating a partial result as a clean "no matches" leads the agent
|
|
72
|
+
into wrong conclusions about the corpus. Always check the array;
|
|
73
|
+
if it's non-empty, decide explicitly whether to retry, fall back,
|
|
74
|
+
or surface the failure.
|
|
75
|
+
|
|
76
|
+
**Don't stash without tags.**
|
|
77
|
+
At >10 stashes, untagged ones become impossible to filter or prune.
|
|
78
|
+
Tag every stash with at least one topic word.
|
|
79
|
+
|
|
80
|
+
**Don't forget TTL on transient findings.**
|
|
81
|
+
Use `--mp-ttl 2h` (or similar) on scratch / exploratory stashes so
|
|
82
|
+
they auto-reap. Manual pruning at agent shutdown is fine too, but TTL
|
|
83
|
+
is the cheaper default. Combined with `--mp-prune-expired` at the
|
|
84
|
+
start of a session, this is how a long-running palace stays small
|
|
85
|
+
without manual gardening.
|
|
86
|
+
|
|
87
|
+
**Don't let the palace grow unbounded across a long-context task.**
|
|
88
|
+
Stash count creep is the silent killer of multi-hour agent loops:
|
|
89
|
+
`--mp-from` over a 200-stash palace gets noisy fast. Set a budget
|
|
90
|
+
(say 20–30 active stashes) and run `--mp-prune-keep 30` or
|
|
91
|
+
`--mp-prune-older-than 6h` every few major turns. Always
|
|
92
|
+
`--mp-prune-dry-run` first.
|
|
93
|
+
|
|
94
|
+
**Don't build dense relationship graphs you won't traverse.**
|
|
95
|
+
Edges are cheap, but a graph nobody walks is noise. Only `--mp-link`
|
|
96
|
+
when you actually plan to `--mp-related` or `--mp-graph` later.
|
|
97
|
+
|
|
98
|
+
## Sources
|
|
99
|
+
|
|
100
|
+
**Don't pipe gigabyte files to `--cmd` or `--stdin`.**
|
|
101
|
+
mpg buffers in memory (64 MB cap for `--cmd`). For huge corpora, use
|
|
102
|
+
`--in` with file paths so ripgrep streams.
|
|
103
|
+
|
|
104
|
+
**Don't `--url` against SPA-rendered pages.**
|
|
105
|
+
mpg fetches raw HTML — no JS execution. SPAs return empty shells.
|
|
106
|
+
Use a real HTTP client + render step upstream if you need it.
|
|
107
|
+
|
|
108
|
+
**Don't combine `--cmd` and `--stdin` for the same content.**
|
|
109
|
+
Pick one. Combining them is legal but confusing — they coexist for
|
|
110
|
+
**different** content sources, not the same one.
|
|
111
|
+
|
|
112
|
+
## Output format
|
|
113
|
+
|
|
114
|
+
**Don't parse `llm` format programmatically.**
|
|
115
|
+
It's designed for the model to read. For machine consumption use
|
|
116
|
+
`--format json`.
|
|
117
|
+
|
|
118
|
+
**Don't strip the `<mpg result ...>` wrapper before showing the
|
|
119
|
+
result to the model.**
|
|
120
|
+
The header carries the pattern, effort, status, pagination state, and
|
|
121
|
+
token budget — load-bearing for the model's reasoning. Keep it.
|
|
122
|
+
|
|
123
|
+
## Integration
|
|
124
|
+
|
|
125
|
+
**Don't register the MCP server at project scope when you want it
|
|
126
|
+
everywhere.**
|
|
127
|
+
Use `--scope user` so it's available across all projects:
|
|
128
|
+
`claude mcp add --scope user mpg -- node <path>`.
|
|
129
|
+
|
|
130
|
+
**Don't shell out from inside an MCP host for the five core tools.**
|
|
131
|
+
That's what the MCP server exists for. Shell-out only for the wider
|
|
132
|
+
mind-palace surface (relationships, prune, intersect, except) that
|
|
133
|
+
isn't exposed via MCP yet.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# mpg Integration Paths
|
|
2
|
+
|
|
3
|
+
mpg works through three different surfaces. Pick the one that matches
|
|
4
|
+
how your agent calls tools.
|
|
5
|
+
|
|
6
|
+
| Path | Best for | Cost |
|
|
7
|
+
| :--- | :--- | :--- |
|
|
8
|
+
| **MCP server** | Claude Desktop, Claude Code, Cline, Windsurf, Continue.dev | One-time config; auto-discovery of tools |
|
|
9
|
+
| **CLI shell-out** | Any agent that can `Bash`/`exec` | One-time `npm install -g`; no tool registration |
|
|
10
|
+
| **Programmatic import** | Custom Anthropic / Google SDK agents | TS/JS import; full type safety |
|
|
11
|
+
|
|
12
|
+
## MCP server
|
|
13
|
+
|
|
14
|
+
mpg ships an MCP server that exposes the five core tools over stdio.
|
|
15
|
+
No network ports, no extra config beyond the launch command.
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"mpg": {
|
|
21
|
+
"command": "node",
|
|
22
|
+
"args": ["<path-to-global-install>/dist/mcp-server.js"]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
For Claude Code, register via the CLI (recommended, user scope makes it
|
|
29
|
+
available across all projects):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
claude mcp add --scope user mpg -- node "<global-install>/dist/mcp-server.js"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The exposed tools are `mpg_search`, `mpg_stash`, `mpg_list_stashes`,
|
|
36
|
+
`mpg_get_stash`, `mpg_drop_stash`. The wider mind-palace surface
|
|
37
|
+
(relationships, prune, intersect, etc.) is **not** available through
|
|
38
|
+
MCP today — drop to CLI for those.
|
|
39
|
+
|
|
40
|
+
## CLI shell-out
|
|
41
|
+
|
|
42
|
+
Any agent that can run a shell command can use mpg directly:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
mpg "TODO" --in src/ --effort quick --format json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The `--format json` output is designed for machine consumption: it
|
|
49
|
+
includes `status`, `nodes[]`, `pagination`, `total_nodes`, etc. — feed
|
|
50
|
+
it back into the agent as the tool result.
|
|
51
|
+
|
|
52
|
+
When to prefer CLI over MCP:
|
|
53
|
+
|
|
54
|
+
- You need a flag that isn't exposed as an MCP tool (relationships,
|
|
55
|
+
prune, intersect, except, TTL).
|
|
56
|
+
- You're chaining mpg with other shell tools (e.g.
|
|
57
|
+
`mpg "errors" --cmd "git log -100" --mp-stash recent`).
|
|
58
|
+
- You want a quick recon and the MCP roundtrip is overkill.
|
|
59
|
+
|
|
60
|
+
When to prefer MCP over CLI:
|
|
61
|
+
|
|
62
|
+
- You want the tool name visible to the model in its tool list (helps
|
|
63
|
+
with tool selection).
|
|
64
|
+
- You're running in a host that doesn't auto-allow `mpg` in Bash
|
|
65
|
+
permissions (MCP bypasses Bash permission prompts).
|
|
66
|
+
|
|
67
|
+
## Programmatic import
|
|
68
|
+
|
|
69
|
+
For TS/Node agents that embed mpg directly:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import {
|
|
73
|
+
search,
|
|
74
|
+
stash,
|
|
75
|
+
listStashes,
|
|
76
|
+
getStash,
|
|
77
|
+
dropStash,
|
|
78
|
+
claudeTools,
|
|
79
|
+
geminiTools,
|
|
80
|
+
} from "mpg-cli";
|
|
81
|
+
|
|
82
|
+
// Run a search
|
|
83
|
+
const result = await search({
|
|
84
|
+
pattern: "TODO",
|
|
85
|
+
in: ["src/"],
|
|
86
|
+
effort: "quick",
|
|
87
|
+
page: 1,
|
|
88
|
+
pageSize: 5,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Stash it for later composition
|
|
92
|
+
await stash(result, {
|
|
93
|
+
name: "auth-todos",
|
|
94
|
+
note: "Auth TODOs to review",
|
|
95
|
+
tags: ["auth", "p0"],
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Register with Anthropic SDK
|
|
99
|
+
const response = await anthropic.messages.create({
|
|
100
|
+
model: "claude-sonnet-4-6",
|
|
101
|
+
tools: [...claudeTools],
|
|
102
|
+
// ...
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Or Google SDK
|
|
106
|
+
const model = genAI.getGenerativeModel({
|
|
107
|
+
model: "gemini-2.5-pro",
|
|
108
|
+
tools: [{ functionDeclarations: geminiTools }],
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Pre-built tool schemas are exported as `claudeTools` and `geminiTools`.
|
|
113
|
+
Each entry is shaped for its respective provider — no manual schema
|
|
114
|
+
authoring needed.
|
|
115
|
+
|
|
116
|
+
## Quick decision
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
Claude Desktop / Code / Cline / Windsurf / Continue? → MCP
|
|
120
|
+
Custom Anthropic / Google SDK agent in TS/Node? → import
|
|
121
|
+
Pi agent, Aider, Cursor, shell-only agent? → CLI
|
|
122
|
+
Need relationships / prune / intersect right now? → CLI (even from inside an MCP host)
|
|
123
|
+
```
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Mind Palace — full surface
|
|
2
|
+
|
|
3
|
+
The palace is a JSON file (default `./.mpg/mind-palace.json`) holding
|
|
4
|
+
named **stashes** of search results. Stashes are addressable: future
|
|
5
|
+
searches can use them as inputs, compose them, intersect them, link
|
|
6
|
+
them into a graph, and prune them by age/tag/count.
|
|
7
|
+
|
|
8
|
+
## Lifecycle
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
SEARCH → STASH → COMPOSE / FROM / INTERSECT / EXCEPT
|
|
12
|
+
↓
|
|
13
|
+
LIST ← TAG, FILTER, PAGINATE
|
|
14
|
+
↓
|
|
15
|
+
LINK → RELATED → GRAPH (traverse)
|
|
16
|
+
↓
|
|
17
|
+
PRUNE (by age / count / tag / TTL / all) → DROP
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Stash operations
|
|
21
|
+
|
|
22
|
+
| CLI flag | What it does |
|
|
23
|
+
| :--- | :--- |
|
|
24
|
+
| `--mp-stash <name> <note>` | Save current search's results. Merges into existing (dedup by file:line) unless `--mp-replace`. |
|
|
25
|
+
| `--mp-stash-note <note>` | Set note separately from the stash flag. |
|
|
26
|
+
| `--mp-stash-tag <tag>` / `--mp-tag <tag>` | Tag the stash (repeatable). |
|
|
27
|
+
| `--mp-replace` | Overwrite an existing stash outright. |
|
|
28
|
+
| `--mp-ttl <duration>` | Auto-expiry (`30m`, `2h`, `7d`). Expired stashes are reaped on next `--mp-list` / `--mp-get`. |
|
|
29
|
+
| `--mp-stash-locations` | Save only file:line pointers (no context text). Use for lean stashes when you'll re-search later. |
|
|
30
|
+
|
|
31
|
+
## Recall operations
|
|
32
|
+
|
|
33
|
+
| CLI flag | What it does |
|
|
34
|
+
| :--- | :--- |
|
|
35
|
+
| `--mp-list` | List all stashes with relative timestamps (`3m ago`, `2d ago`). |
|
|
36
|
+
| `--mp-list-tag <tag>` | Filter list by tag (repeatable). |
|
|
37
|
+
| `--mp-get <name>` | Show full contents of one stash. |
|
|
38
|
+
| `--mp-drop <name>` | Remove a stash. |
|
|
39
|
+
|
|
40
|
+
## Set operations over file lists
|
|
41
|
+
|
|
42
|
+
These all run a **fresh search**, scoped to a derived file list.
|
|
43
|
+
|
|
44
|
+
| Operation | CLI | Files searched |
|
|
45
|
+
| :--- | :--- | :--- |
|
|
46
|
+
| **Scope** | `--mp-from <name>` | Files in the named stash |
|
|
47
|
+
| **Union** | `--mp-compose <a> <b> ...` | Files in **any** of the named stashes |
|
|
48
|
+
| **Intersection** | `--mp-intersect <a> <b> ...` | Files in **all** of the named stashes |
|
|
49
|
+
| **Difference** | `--mp-except <a>` or `--mp-except <a> <b> ...` | Files **not** in the named stash(es) |
|
|
50
|
+
|
|
51
|
+
Examples:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Re-search a single stash's files
|
|
55
|
+
mpg "rate.limit" --mp-from auth-todos
|
|
56
|
+
|
|
57
|
+
# Files mentioned in any of two stashes
|
|
58
|
+
mpg "TODO" --mp-compose auth-todos perf-hotspots
|
|
59
|
+
|
|
60
|
+
# Files mentioned in BOTH stashes
|
|
61
|
+
mpg "TODO" --mp-intersect auth-todos perf-hotspots
|
|
62
|
+
|
|
63
|
+
# Files in auth-todos but NOT in deprecated
|
|
64
|
+
mpg "TODO" --mp-except deprecated
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The MCP tools today expose `from` and `compose` only — drop to CLI for
|
|
68
|
+
`intersect` and `except`.
|
|
69
|
+
|
|
70
|
+
## Relationships (the graph in mind-palace-graph)
|
|
71
|
+
|
|
72
|
+
Stashes can be linked into a directed graph. The graph is what lets
|
|
73
|
+
you **traverse the investigation by intent** instead of by remembering
|
|
74
|
+
stash names — `--mp-graph <root> 3` reconstructs an entire thread
|
|
75
|
+
topology in one CLI call, which is the lifeline when a conversation
|
|
76
|
+
gets compacted away mid-task.
|
|
77
|
+
|
|
78
|
+
| CLI flag | What it does |
|
|
79
|
+
| :--- | :--- |
|
|
80
|
+
| `--mp-link <from> <to> <type> [note]` | Create a directed edge. |
|
|
81
|
+
| `--mp-unlink <from> <to>` | Remove an edge. |
|
|
82
|
+
| `--mp-related <name>` | Show all inbound + outbound neighbors of `name`. |
|
|
83
|
+
| `--mp-graph <name> [depth]` | BFS traversal from `name` up to `[depth]` levels (default 3). |
|
|
84
|
+
|
|
85
|
+
### Edge type conventions
|
|
86
|
+
|
|
87
|
+
Edge types are unenforced strings, but consistent vocabulary makes the
|
|
88
|
+
graph readable later. Common types:
|
|
89
|
+
|
|
90
|
+
| Type | Meaning |
|
|
91
|
+
| :--- | :--- |
|
|
92
|
+
| `depends-on` | "Reading B is a prerequisite for reading A." |
|
|
93
|
+
| `supersedes` | "A is the current view; B is the old one. Ignore B." |
|
|
94
|
+
| `see-also` | "B is a related thread worth surfacing alongside A." |
|
|
95
|
+
| `parent-of` / `child-of` | Hierarchical decomposition of one investigation into subtopics. |
|
|
96
|
+
| `blocks` | "A can't ship until B is resolved." |
|
|
97
|
+
| `contradicts` | "A and B disagree — reconciliation needed." |
|
|
98
|
+
|
|
99
|
+
Pick a vocabulary at the start of an investigation and stay consistent
|
|
100
|
+
within it. Mixing `depends-on` with `requires` for the same concept
|
|
101
|
+
makes `--mp-graph` output noisy without adding signal.
|
|
102
|
+
|
|
103
|
+
### Workflow: tracking a multi-thread investigation
|
|
104
|
+
|
|
105
|
+
The pattern that pays off: build stashes as you investigate (always
|
|
106
|
+
with TTLs + tags), link them the moment you notice a relationship,
|
|
107
|
+
then traverse by intent in future sessions.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Session 1 — building the topology
|
|
111
|
+
mpg "JWT" --in src/auth/ --mp-stash auth-jwt --mp-tag rewrite --mp-ttl 24h
|
|
112
|
+
mpg "JWT" --in docs/spec/ --mp-stash spec-jwt --mp-tag rewrite --mp-ttl 24h
|
|
113
|
+
mpg "JWT" --in src/legacy/ --mp-stash legacy-jwt --mp-tag rewrite --mp-ttl 24h
|
|
114
|
+
|
|
115
|
+
mpg --mp-link auth-jwt spec-jwt see-also "implementation of the spec"
|
|
116
|
+
mpg --mp-link auth-jwt legacy-jwt supersedes "post-rewrite, legacy goes away"
|
|
117
|
+
|
|
118
|
+
# Session 2 — navigation, no need to remember names
|
|
119
|
+
mpg --mp-related auth-jwt # one-hop neighbors with edge labels
|
|
120
|
+
mpg --mp-graph auth-jwt 3 # full BFS, three hops out
|
|
121
|
+
|
|
122
|
+
# When the conversation gets compacted and you've lost the thread:
|
|
123
|
+
mpg --mp-graph <known-root> 3
|
|
124
|
+
# → reconstructs the whole investigation topology, with edge types
|
|
125
|
+
# that tell you what's current, what's superseded, what blocks what.
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### When to link (and when not to)
|
|
129
|
+
|
|
130
|
+
1. **Only link what you'll traverse.** Edges are cheap to make and
|
|
131
|
+
cheap to store, but a graph nobody walks is just noise on
|
|
132
|
+
`--mp-related`. If you wouldn't run `--mp-graph` later, skip the
|
|
133
|
+
link.
|
|
134
|
+
2. **Link when discovery is fresh.** The right moment is when you
|
|
135
|
+
notice the relationship. Three sessions later you won't remember
|
|
136
|
+
why two stashes mattered together.
|
|
137
|
+
3. **Don't link across unrelated tasks.** If you maintain one palace
|
|
138
|
+
per task (`MPG_MIND_PALACE=.mpg/<task>.json`), this is automatic —
|
|
139
|
+
cross-task links can't even be expressed.
|
|
140
|
+
4. **Relink with confidence — it's atomic.** `--mp-unlink` then
|
|
141
|
+
`--mp-link` is a no-op-loss operation; the diff-based save in
|
|
142
|
+
v0.2.5 ensures both edits land cleanly even under concurrent
|
|
143
|
+
writers.
|
|
144
|
+
|
|
145
|
+
### Quick examples by use case
|
|
146
|
+
|
|
147
|
+
| Situation | Linkage |
|
|
148
|
+
| :--- | :--- |
|
|
149
|
+
| Refactor that obsoletes an old subsystem | `--mp-link new-impl old-impl supersedes "after-rewrite"` |
|
|
150
|
+
| Implementation depends on a shared library you've already mapped | `--mp-link feature-x lib-y depends-on "uses Y's session API"` |
|
|
151
|
+
| Spec and code drift you need to reconcile | `--mp-link spec-claim impl-reality contradicts "spec says X, code does Y"` |
|
|
152
|
+
| Decomposing an epic into discrete threads | `--mp-link epic-payments stripe-webhooks child-of` then `--mp-graph epic-payments 2` to walk the whole epic |
|
|
153
|
+
| Cross-referencing parallel tracks (impl + tests + docs) | Three stashes, two `see-also` edges between them |
|
|
154
|
+
|
|
155
|
+
## Pruning
|
|
156
|
+
|
|
157
|
+
A palace grows unbounded unless pruned. Always preview first.
|
|
158
|
+
|
|
159
|
+
| CLI flag | Effect |
|
|
160
|
+
| :--- | :--- |
|
|
161
|
+
| `--mp-prune-older-than <dur>` | Stashes not updated within duration. |
|
|
162
|
+
| `--mp-prune-keep <n>` | Keep only the N most recently updated. |
|
|
163
|
+
| `--mp-prune-tag <tag>` | All stashes carrying the tag. |
|
|
164
|
+
| `--mp-prune-expired` | All TTL-expired stashes. |
|
|
165
|
+
| `--mp-prune-all` | Entire palace. Requires `--mp-prune-confirm`. |
|
|
166
|
+
| `--mp-prune-dry-run` | Preview only — do not delete. **Use this first.** |
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
mpg --mp-prune-older-than 7d --mp-prune-dry-run # preview
|
|
170
|
+
mpg --mp-prune-older-than 7d # commit
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
TTL-tagged stashes are *also* auto-reaped on every `--mp-list` or
|
|
174
|
+
`--mp-get` — no explicit prune required for the TTL case.
|
|
175
|
+
|
|
176
|
+
## Multi-palace isolation
|
|
177
|
+
|
|
178
|
+
Use a separate palace per task to avoid context bleed.
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Explicit per-invocation:
|
|
182
|
+
mpg "TODO" --in src/ --mp-stash t42 "..." --mp-path .mpg/task-42.json
|
|
183
|
+
|
|
184
|
+
# Or via env, so all subsequent calls use the same palace:
|
|
185
|
+
export MPG_MIND_PALACE=.mpg/task-42.json
|
|
186
|
+
mpg "TODO" --in src/ --mp-stash t42 "..."
|
|
187
|
+
mpg --mp-list
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The default `./.mpg/mind-palace.json` is searched walking up from CWD
|
|
191
|
+
(like `.gitignore`), so monorepo subdirs share a project palace by
|
|
192
|
+
default.
|
|
193
|
+
|
|
194
|
+
## Storage format
|
|
195
|
+
|
|
196
|
+
Each stash holds:
|
|
197
|
+
|
|
198
|
+
```jsonc
|
|
199
|
+
{
|
|
200
|
+
"name": "auth-todos",
|
|
201
|
+
"note": "Auth TODOs to review",
|
|
202
|
+
"tags": ["auth", "p0"],
|
|
203
|
+
"pattern": "TODO",
|
|
204
|
+
"effort": "quick",
|
|
205
|
+
"nodes": [ /* file:line + context */ ],
|
|
206
|
+
"sources": [ /* canonical file paths */ ],
|
|
207
|
+
"created_at": "2025-...",
|
|
208
|
+
"updated_at": "2025-...",
|
|
209
|
+
"expires_at": "2025-..." // if --mp-ttl was set
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Plus a top-level `relationships: [{from, to, type, note, created_at}]`
|
|
214
|
+
array for edges.
|
|
215
|
+
|
|
216
|
+
The file is plain JSON — safe to inspect, version-control, or hand-edit
|
|
217
|
+
for one-off corrections.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Multi-agent palace patterns
|
|
2
|
+
|
|
3
|
+
The mind palace is a single JSON file. Multiple processes / agents
|
|
4
|
+
sharing it coordinate via a per-palace `.lock` file plus an atomic
|
|
5
|
+
write path (tmp file + rename + on-disk re-read-and-merge under the
|
|
6
|
+
lock). The race conditions that earlier versions had — silently lost
|
|
7
|
+
stashes when two agents stashed in the same second — no longer apply.
|
|
8
|
+
|
|
9
|
+
You still pick a layout based on **what kind of context you want
|
|
10
|
+
agents to share**, not based on data-loss risk.
|
|
11
|
+
|
|
12
|
+
## Recommended layouts
|
|
13
|
+
|
|
14
|
+
### Layout A: per-agent isolated palaces
|
|
15
|
+
|
|
16
|
+
Each agent gets its own palace file. Use when agents are pursuing
|
|
17
|
+
genuinely independent investigations and you don't want context bleed
|
|
18
|
+
between them.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Agent A
|
|
22
|
+
MPG_MIND_PALACE=.mpg/agent-a.json mpg "TODO" --in src/ --mp-stash mine "..."
|
|
23
|
+
|
|
24
|
+
# Agent B
|
|
25
|
+
MPG_MIND_PALACE=.mpg/agent-b.json mpg "TODO" --in src/ --mp-stash mine "..."
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Pros: zero lock contention, easy to garbage-collect (just `rm` the
|
|
29
|
+
file when the agent finishes), one task = one palace = one mental model.
|
|
30
|
+
Cons: agents can't see each other's findings — you have to manually
|
|
31
|
+
copy or merge if context-sharing turns out to matter.
|
|
32
|
+
|
|
33
|
+
### Layout B: shared read-only palace + per-agent scratch
|
|
34
|
+
|
|
35
|
+
One canonical palace, populated by a coordinator agent. Worker agents
|
|
36
|
+
**read** from it (`--mp-from`, `--mp-compose`, `--mp-list`,
|
|
37
|
+
`--mp-get`) but write to their own scratch palaces.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Coordinator stashes the project's key contexts:
|
|
41
|
+
MPG_MIND_PALACE=.mpg/shared.json mpg "TODO" --in src/auth/ \
|
|
42
|
+
--mp-stash auth-overview "Auth subsystem"
|
|
43
|
+
|
|
44
|
+
# Workers read from shared, write to their own scratch:
|
|
45
|
+
MPG_MIND_PALACE=.mpg/worker-1.json \
|
|
46
|
+
mpg "rate.limit" --mp-from auth-overview --mp-stash w1-findings "..."
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Pros: shared context with a clear authorship model — coordinator
|
|
50
|
+
owns the canonical map, workers own their own findings.
|
|
51
|
+
Cons: workers can't contribute back to the shared palace without an
|
|
52
|
+
explicit merge step.
|
|
53
|
+
|
|
54
|
+
### Layout C: shared read-write palace
|
|
55
|
+
|
|
56
|
+
All agents share one palace. As of v0.2.4 this is safe under
|
|
57
|
+
concurrent writes: each save acquires a `.lock` file, re-reads the
|
|
58
|
+
on-disk palace under the lock, merges any stashes the other writer
|
|
59
|
+
added, then renames atomically into place.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# All agents
|
|
63
|
+
export MPG_MIND_PALACE=.mpg/team.json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Pros: maximum visibility — everyone sees everyone's findings as
|
|
67
|
+
soon as they're written.
|
|
68
|
+
Cons: lock contention if many agents stash in a tight loop. For
|
|
69
|
+
extreme write loads (autopilot/swarm patterns with hundreds of
|
|
70
|
+
near-simultaneous stashes), still prefer Layout A or B — the lock
|
|
71
|
+
will serialize you, and serialization at high write rates means
|
|
72
|
+
the slowest agent's stash latency becomes everyone's stash latency.
|
|
73
|
+
|
|
74
|
+
## Concurrency model (what the lock actually does)
|
|
75
|
+
|
|
76
|
+
mpg's write path is:
|
|
77
|
+
|
|
78
|
+
1. Acquire `<palace>.lock` (sibling file, `O_EXCL`). Backs off with
|
|
79
|
+
jitter for up to 2s; force-breaks a stale lock older than 30s.
|
|
80
|
+
2. Read the on-disk palace JSON (the version *some other process*
|
|
81
|
+
may have written since we last loaded).
|
|
82
|
+
3. Merge stashes the on-disk version has that our in-memory copy
|
|
83
|
+
doesn't (last-write-wins on collision by stash name).
|
|
84
|
+
4. Write to `<palace>.tmp.<pid>.<rand>` then atomically rename onto
|
|
85
|
+
the real path.
|
|
86
|
+
5. Release the lock.
|
|
87
|
+
|
|
88
|
+
Consequence for agent design:
|
|
89
|
+
|
|
90
|
+
- **Two agents stashing different stash names in parallel: both land.**
|
|
91
|
+
The merge step in (3) ensures it.
|
|
92
|
+
- **Two agents stashing the same name in parallel: last writer wins
|
|
93
|
+
for that stash.** This is intentional — `mpg_stash` with `replace`
|
|
94
|
+
semantics is supposed to overwrite. If you want a merge of two
|
|
95
|
+
parallel updates to the same stash, model them as two different
|
|
96
|
+
names and compose them later.
|
|
97
|
+
- **A crashed agent that died mid-write leaves a stale lock.** Other
|
|
98
|
+
agents will detect this (mtime > 30s) and break it. No manual
|
|
99
|
+
cleanup needed unless something is very wrong (in which case
|
|
100
|
+
`rm <palace>.lock`).
|
|
101
|
+
- **A corrupted palace file is preserved, not overwritten.** mpg
|
|
102
|
+
copies it aside as `<palace>.corrupt.<timestamp>` and **refuses
|
|
103
|
+
to save** for the rest of that process unless `MPG_FORCE_RESET=1`
|
|
104
|
+
is set. Inspect the backup before forcing.
|
|
105
|
+
|
|
106
|
+
The palace file is still plain JSON. If you suspect divergence between
|
|
107
|
+
two agents' worldviews, diff the file directly — there's no opaque
|
|
108
|
+
binary state.
|
|
109
|
+
|
|
110
|
+
## Naming conventions for shared palaces
|
|
111
|
+
|
|
112
|
+
When multiple agents share a palace, name stashes with a prefix to
|
|
113
|
+
avoid collisions and make ownership obvious:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
<agent-id>-<topic> e.g. coordinator-auth, worker1-perf
|
|
117
|
+
<task-id>-<topic> e.g. t42-auth, t42-perf
|
|
118
|
+
<phase>-<topic> e.g. grounding-auth, planning-auth
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Tag with the agent or task ID too:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
mpg "TODO" --in src/ --mp-stash w1-auth "Worker 1 auth findings" \
|
|
125
|
+
--mp-tag worker1 --mp-tag task-42
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
That makes `--mp-list-tag worker1` or `--mp-prune-tag worker1` work
|
|
129
|
+
cleanly when a worker is done.
|
|
130
|
+
|
|
131
|
+
## Lifecycle hygiene
|
|
132
|
+
|
|
133
|
+
- **Use TTL on transient findings**: `--mp-ttl 2h` on a worker's
|
|
134
|
+
exploratory stashes so the palace self-cleans.
|
|
135
|
+
- **Prune by tag on agent shutdown**: when a worker finishes, run
|
|
136
|
+
`mpg --mp-prune-tag <worker-id>` to drop its scratch.
|
|
137
|
+
- **Snapshot before destructive ops**: `cp .mpg/shared.json .mpg/shared.bak`
|
|
138
|
+
before any `--mp-prune-*`.
|
|
139
|
+
|
|
140
|
+
## Anti-patterns
|
|
141
|
+
|
|
142
|
+
- **Multiple concurrent writers to one palace with high frequency.**
|
|
143
|
+
Will lose stashes. Use Layout A or serialize writes.
|
|
144
|
+
- **Sharing a palace across unrelated tasks.** Context bleed makes
|
|
145
|
+
stashes harder to find and prune. One palace per task.
|
|
146
|
+
- **Stashing tool outputs with no TTL in a long-running agent.**
|
|
147
|
+
The palace grows unbounded.
|