-
-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathllms.txt
More file actions
401 lines (303 loc) · 26.1 KB
/
Copy pathllms.txt
File metadata and controls
401 lines (303 loc) · 26.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# Matryca Plumber - AI Agent Context & Execution Guide (v2.0.0rc1)
> **SYSTEM DIRECTIVE FOR AI AGENTS:** You operate on the user's **local Logseq OG vault** via Matryca Plumber.
> **CRITICAL RULE:** DO NOT `git clone` this repository. DO NOT `pip install`. Run the **PyPI** release with **`uvx`** so you use a real, versioned wheel — not a guessed dev tree.
Canonical copy (2026 standard path): `.well-known/llms.txt` (same content as this file).
> **v2.0.0-rc.1:** the qualified release candidate makes the external Shadow read cache default-on; `MATRYCA_SHADOW_DB_ENABLED=false` remains the emergency Markdown/BM25 opt-out, and Logseq Markdown remains authoritative. Gate A is complete; the public RC begins the separate Gate B observation required before stable `v2.0.0`. The published `v2.0.0-beta.1` / `2.0.0b1` wheel remains the historical default-off, graph-local baseline. Roadmap: `docs/roadmaps/ROADMAP_V2_PREPARATION.md`.
> **v2.0.0-alpha.5 headline:** **Shadow hardening campaign closed** ([#261](https://github.com/MarcoPorcellato/matryca-plumber/issues/261)) — CTE depth-truncation status ([#289](https://github.com/MarcoPorcellato/matryca-plumber/issues/289) / [#291](https://github.com/MarcoPorcellato/matryca-plumber/pull/291)); state API absolute-path redaction ([#293](https://github.com/MarcoPorcellato/matryca-plumber/issues/293) / [#294](https://github.com/MarcoPorcellato/matryca-plumber/pull/294)); Axes 5–7 audit probes green; `MATRYCA_SHADOW_DB_ENABLED=false` by default. **Not an RC** — post-publish soak before beta/RC. Roadmap: `docs/roadmaps/ROADMAP_V2_PREPARATION.md`.
> **v2.0.0-alpha.4 headline:** **Shadow FTS query length bound** — keywords over **512 Unicode characters** (post-`strip`) are rejected before FTS preparation or SQLite `MATCH` ([#279](https://github.com/MarcoPorcellato/matryca-plumber/issues/279) / [#286](https://github.com/MarcoPorcellato/matryca-plumber/pull/286)); Axis 4 FTS5 gate **fully green** — **52 pass, 0 xfail**.
> **v2.0.0-alpha.3 headline:** **Shadow FTS hyphenated queries** — natural compounds like `state-of-the-art` route through shadow FTS5 without spurious generational fallback ([#277](https://github.com/MarcoPorcellato/matryca-plumber/issues/277) / [#282](https://github.com/MarcoPorcellato/matryca-plumber/pull/282)).
> **v1.13.1 headline:** **Logseq Matryca Parser 1.6.0 alignment** — minimum dependency `logseq-matryca-parser>=1.6.0`; inherits **1.4.2** newline splice safety, resilient X-Ray reload, SYNAPSE cyclic-embed truncation; `_headless_append_child` mirrors parser newline normalization. Architecture: `docs/ARCHITECTURE.md`.
> **v1.13.0 headline:** **Daemon & dispatch modularization** — `maintenance_daemon` split into focused `daemon_*` modules ([#58](https://github.com/MarcoPorcellato/matryca-plumber/issues/58)); `graph_dispatch` handler registry + **`GraphReadPort`** (v2 Phase 1, [#59](https://github.com/MarcoPorcellato/matryca-plumber/issues/59)). Maintainer map: `docs/CLEAN_CODE_ARCHITECTURE.md` · `docs/ARCHITECTURE.md`.
> **v1.12.0 headline:** **Prompt Clean Architecture** — Tier-1 domain prompt builders (`src/agent/prompts/`), L0 write-safety validators before semantic commits, `SYSTEM_PROMPT.md` assembled from `docs/openspec/agent/` fragments (`make build-system-prompt`). Maintainer map: `docs/PROMPT_ARCHITECTURE.md` · `AGENTS.md`.
> **v1.11.x:** **Tana → Logseq OG** via `matryca import tana` / MCP **`import_tana`** (dry-run default). **v1.11.1** aligned **`logseq-matryca-parser` 1.4.0**. **v1.11.2** refactors the **graph layer boundary** (`post_write` port, bounded RAM LRU caches, OCC `st_mtime_ns` page writes). Spec: `docs/openspec/tana-import.md` · architecture: `docs/ARCHITECTURE.md`.
---
## 0. Graph path (REQUIRED — no `--graph` flag)
The v2.0.0-rc.1 release does **not** accept `--graph` on the CLI. You **must** point at the vault root (folder containing `pages/` and usually `journals/`) with the environment variable **`LOGSEQ_GRAPH_PATH`**.
**Set once per shell session (copy-paste):**
```bash
export LOGSEQ_GRAPH_PATH="/absolute/path/to/your/logseq/graph"
```
**One-shot (inline env for a single command):**
```bash
LOGSEQ_GRAPH_PATH="/absolute/path/to/your/logseq/graph" uvx matryca-plumber --help
```
If `LOGSEQ_GRAPH_PATH` is unset or invalid, graph commands return an error — fix the path before retrying.
---
## 1. Execution & Installation (PyPI / uvx)
Matryca Plumber is on PyPI as **`matryca-plumber`**. Use **`uvx`** (uv tool runner); no permanent install required.
**Entrypoint (console script):**
```bash
uvx matryca-plumber <subcommand> ...
```
**Discover commands:**
```bash
uvx matryca-plumber --help
uvx matryca-plumber read --help
```
**Machine-readable JSON:** Global flag **`--json`** must appear **before** the subcommand:
```bash
uvx matryca-plumber --json read page "My Project"
```
---
## 2. Core CLI (v2.0.0-rc.1)
Subcommands: `read`, `search`, `mutate`, `refactor`, `lint`, `context`, **`import`**, `service`, `plumber`.
Shorthand daemon/UI verbs (routed to `plumber`): `start`, `stop`, `status`, `ui`, `audit`, `cluster`.
### 2.0 Plumber commands — UI vs daemon (do not confuse)
| Command | Starts | Does **not** start |
|---------|--------|-------------------|
| `status` / `ui` (or `plumber status` / `plumber ui`) | Sovereign UI + API on `http://127.0.0.1:8500` | maintenance daemon |
| `plumber start` | background maintenance daemon | browser / UI server |
| `plumber start --foreground` | foreground daemon (terminal logs) | browser / UI server |
| `plumber stop` | — | stops daemon |
**Lazy UI bootstrap (v1.9.10+):** `status` / `ui` bind `:8500` in seconds; the in-memory graph index loads on the first analytics request. **v1.9.11:** settings save, graph-path save, L1 provision, and **Start Engine** also use lazy bootstrap so large vaults do not hit the 10s UI fetch timeout. Use **Start Engine** in the UI or `plumber start` to run Phase 1/2 maintenance (the daemon subprocess loads the AST eagerly).
**Common mistake:** `plumber start` alone does **not** open the dashboard — run `status` in another terminal or use **Start Engine** after opening the UI.
### 2.1 Extract graph data as JSON (DO NOT grep `.md` files)
Use **`read`** with a **positional** `target_type`, then an optional `query` string.
| `target_type` | `query` | Use when |
|---------------|---------|----------|
| `page` | Logseq page title | Full spatial page context |
| `subtree` | `Page Title\|block-uuid` or JSON | Token-efficient block extract |
| `memory` | (omit) | L1 session memory files |
| `bootstrap_status` | (omit) | Phase 1 semaphore (`bootstrap_complete`, Soft Gate) |
| `dashboard` | (omit) | Vault / daemon overview |
| `block_ast` | `Page Title\|block-uuid` | Single block AST excerpt |
| `xray_page` | Page title | X-Ray aliases `[0]`…`[n]` for mutations |
| `structural_hops` | hop query | Link/tag neighborhood report |
**Command (canonical):**
```bash
export LOGSEQ_GRAPH_PATH="/absolute/path/to/your/logseq/graph"
uvx matryca-plumber --json read page "My Project"
```
**Semantic macro (bundled context):**
```bash
uvx matryca-plumber context load "My Project"
uvx matryca-plumber context load "My Project|aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
```
**Search (examples):**
```bash
uvx matryca-plumber --json search bm25 "redis cache"
uvx matryca-plumber --json search journal_tasks "7"
```
Always **parse JSON from stdout** when using `--json`. Never hand-parse raw `pages/*.md` or `journals/*.md`.
### 2.2 MCP (FastMCP **stdio** — NOT HTTP port 8080)
MCP is a **stdio** sidecar: the host (Cursor, Claude Desktop, **Hermes Agent**, etc.) spawns `matryca-plumber` and talks JSON-RPC over stdin/stdout. There is **no** `mcp --port` flag in the v1.9 line.
**Lazy AST handshake (v1.9.6+):** MCP lifespan defers full-vault AST parsing until the **first graph tool call**. `initialize` + `tools/list` complete in seconds; `read_graph_data` / `target_type=bootstrap_status` and `target_type=memory` do **not** require the AST index.
**Requirements:**
1. `LOGSEQ_GRAPH_PATH` set to the vault root.
2. `MATRYCA_MCP_ENABLED=true` (off by default for safety).
**Host config pattern (Cursor / Claude Desktop):**
```json
{
"mcpServers": {
"matryca-logseq": {
"command": "uvx",
"args": ["matryca-plumber"],
"env": {
"LOGSEQ_GRAPH_PATH": "/absolute/path/to/your/logseq/graph",
"MATRYCA_MCP_ENABLED": "true"
}
}
}
}
```
With no CLI subcommand and MCP enabled, `uvx matryca-plumber` starts the **stdio** MCP server.
For interactive graph work without MCP, prefer the CLI in section 2.1.
#### Hermes Agent (`~/.hermes/config.yaml`)
Hermes requires the host MCP client extra: `cd ~/.hermes/hermes-agent && uv pip install -e ".[mcp]"`.
```yaml
mcp_servers:
matryca-plumber:
command: uvx
args: [matryca-plumber]
env:
MATRYCA_MCP_ENABLED: "true"
LOGSEQ_GRAPH_PATH: /absolute/path/to/vault
enabled: true
connect_timeout: 120 # handshake (initialize + tools/list) — not vault parse time
timeout: 300 # per tool call; first graph tool pays AST load on large vaults
```
| Setting | Purpose |
|---------|---------|
| `connect_timeout` | Hermes **handshake** only (`initialize`, `tools/list`). **60–120 s** is enough with lazy AST. |
| `timeout` | Each **tool invocation**. Raise for large vaults on the **first** graph read/search (AST cold start). Rule of thumb: `(pages + journals) × ~0.2 s` on slow mounts — measure once. |
Full guide: `docs/integrations/hermes-agent.md` · stderr telemetry: `AST cache bootstrap started|complete` in `~/.hermes/logs/mcp-stderr.log`.
### 2.3 AX robustness — page titles & write targets (v1.9.7+)
Local LLMs often send **wrong page title formats**. Plumber normalizes before lookup:
| You may send | Plumber accepts |
|--------------|-----------------|
| `Domain/Topic` (semantic) | Canonical Logseq title |
| `Domain___Topic` or `Domain___Topic.md` | Same (namespace encoding) |
| `pages/Domain___Topic.md` | Strips prefix/suffix |
| Wrong casing `DOMAIN/topic` | Case-insensitive match |
**Never send** path traversal (`../`, `../../etc/passwd`) — rejected with a clear error; MCP session survives.
**`mutate_graph` / `write_outline` targets:**
| `target` | When to use |
|----------|-------------|
| `parent-block-uuid` | After `xray_page` or spatial read |
| `[n]` | X-Ray alias from `.matryca_xray_state.json` |
| `Page Title\|block-uuid` or `Page Title\|[n]` | **Recommended** when the model might hallucinate UUIDs |
If the block ref is invalid but the **page exists**, Plumber **safe-appends** at page bottom and returns `warnings` (check them). Bare unknown aliases like `[42]` without a page still fail with `ok: false`.
Spec: `docs/openspec/agent-ax-robustness.md`
### 2.4 Security & Sandbox (v1.9.9+)
Graph reads and writes stay inside **`LOGSEQ_GRAPH_PATH`**. v1.9.9 adds defense-in-depth beyond MCP title normalization; **v1.9.13 (Enterprise Resilience)** hardens parsing and RAG boundaries — TOCTOU-safe bounded JSON reads, `templates_subdir` traversal rejection, namespace-aware semantic cache keys, subtree heading fences (token-efficient excerpts), and string-aware LLM JSON recovery so braces inside string values do not truncate payloads. **v1.9.14** adds journal-aware Phase 2 clustering (daily notes no longer inflate `[unclustered]` or cluster-focus prompts) and skips entity-consolidation LLM turns for journal/date wikilink pairs. **v1.9.15** bypasses Phase-2 semantic indexing and dual embeddings for `journals/` pages (Phase-1 AST cache, link registry, and OCC `mtime` ledger still run). **v1.10.0** adds flock-protected master catalog I/O (merge-on-save), atomic link registry writes, and harvest catalog/page parity on OCC abort. **v1.10.3** tightens flock sidecar file mode to `0o600`, offloads Sovereign UI config saves from the HTTP event loop, and enforces strict Pydantic LLM/outline contracts (`extra="forbid"`, recursive OpenAI strict JSON schemas). **v1.10.5** raises **`logseq-matryca-parser`** to **1.3.1** (YAML frontmatter, case-insensitive graph routing, asset extraction, root public API exports). **v1.10.6** unifies page RMW and JSON sidecar flock via `platform_lock.py` (NB acquire + backoff + reentrancy, #40) and adds OCC-safe hub page compiles for Master Index / Graph Insights (#34). **v1.11.1** pins parser **1.4.0**. **v1.11.2** inverts graph→daemon post-write coupling via `graph.post_write` port (#134), bounds generational/BM25 and block-vector RAM with LRU env caps, and uses `st_mtime_ns` OCC on page writes (#153 partial).
| Control | Operator note |
|---------|----------------|
| Path sandbox | `read_graph_file_text()` on graph paths; `../` and symlink escape → `PathTraversalSecurityError` |
| Link registry | Tampered `.matryca_link_registry.json` paths are rejected before read |
| JSON size cap | `MATRYCA_JSON_MAX_BYTES` (default 64 MiB) on catalog/registry/daemon/cache loaders |
| Memory LRU | `MATRYCA_GENERATIONAL_CACHE_MAX_GRAPHS` (default 4); `MATRYCA_BLOCK_VECTOR_STORE_MODE=ondemand` (default); `MATRYCA_BLOCK_VECTOR_STORE_MAX_GRAPHS` (default 4) — see `.env.example` Advanced section |
| UI token | Set `MATRYCA_UI_TOKEN` on shared hosts; `.env.example` templates `MATRYCA_UI_REQUIRE_EXPLICIT_TOKEN=true` |
| Debug NDJSON | `MATRYCA_LLM_DEBUG_LOG_PATH` must lie under allowed roots; secrets redacted when enabled |
**Do not** rely on raw filesystem reads of `pages/` — use Plumber tools (section 2.1). Full matrix: `SECURITY.md` · spec: `docs/openspec/security-sandbox.md`
### 2.5 Diagnostics & audit (no `doctor` command)
There is **no** `doctor` subcommand. Use these instead:
| Goal | Command |
|------|---------|
| Bootstrap / graph insights dashboard | `uvx matryca-plumber plumber audit` or `uvx matryca-plumber audit` |
| Semantic cluster neighborhoods | `uvx matryca-plumber plumber cluster` or `uvx matryca-plumber cluster` |
| Sovereign UI + pre-flight checks | `uvx matryca-plumber status` → UI on `http://127.0.0.1:8500` (no daemon until **Start Engine** or `plumber start`) |
| Block-reference lint | `uvx matryca-plumber lint block_refs` |
| Maintenance daemon (headless) | `uvx matryca-plumber plumber start` / `plumber stop` (no browser; pair with `status` for the cockpit) |
**JSON audit output:**
```bash
export LOGSEQ_GRAPH_PATH="/absolute/path/to/your/logseq/graph"
uvx matryca-plumber --json plumber audit
```
### 2.6 Shadow DB and Strict Read Only (v2.0.0-rc.1 contract)
Shadow DB is a **derived read cache outside `LOGSEQ_GRAPH_PATH`**. It does **not** replace Markdown on disk. In v2.0.0-rc.1 it is **default-on**; an explicit false value is the emergency opt-out. The published `2.0.0b1` wheel remains historically default-off and graph-local.
| Env var | Default | When `true` |
|---------|---------|-------------|
| `MATRYCA_READ_ONLY` | `false` | Blocks every Matryca write, lock, temp file, or support artifact inside the Logseq graph; reads remain available |
| `MATRYCA_SHADOW_DB_ENABLED` | `true` | Maintains the external cache; `search_graph(bm25)` prefers FTS5 and `read_graph_data(subtree)` prefers recursive CTE only while `READY`; **always falls back** to generational BM25 / parser+AST when disabled or non-ready |
| `MATRYCA_SHADOW_QUARANTINE_ENABLED` | `true` | Park over-budget pages instead of failing the whole rebuild (beta.1); `false` restores strict mode |
| `MATRYCA_SHADOW_WRITER_LOCK_TIMEOUT_S` | `10` | Cross-process advisory flock wait for incremental sync/delete (alpha.1) |
| `MATRYCA_SHADOW_REBUILD_LOCK_TIMEOUT_S` | `120` | Cross-process advisory flock wait for full rebuild (alpha.1) |
| `MATRYCA_SHADOW_DB_BUSY_TIMEOUT_MS` | `5000` | SQLite `busy_timeout` for shadow writers (clamped 0–60000 ms; alpha.1) |
**Operator health (no `doctor`):** Sovereign UI `status` → sidebar **Shadow DB** row (sourced from `GET /api/state.shadow_db`: `state`, `last_full_sync_at`, `source_page_count`, `indexed_page_count`, `lag_pages`, `last_sync_error`, `not_ready_reason`, `quarantined_page_count`).
`not_ready_reason` is a closed vocabulary of content-free codes explaining why the cache is
not accelerating reads: `not_bootstrapped`, `bootstrap_in_progress`, `database_unreadable`,
`schema_version_mismatch`, `sync_error`, `full_sync_incomplete`, `page_count_mismatch`,
`cache_unavailable`. It is
`null` when the state is `ready` or `disabled`. Treat an unrecognised code as `null` — the
vocabulary may grow. `full_sync_incomplete` is the code an agent will most often see on a
real vault; see below.
**Independent authority:** Read Only governs the vault boundary; Shadow governs only the external derived cache. Read Only + Shadow enabled is the recommended protected-reading profile. Shadow never authorizes a graph write, and a cache failure never blocks Markdown/BM25 reads.
**Over-budget pages are quarantined, not fatal.** A page whose parse exceeds `MATRYCA_PAGE_PARSE_TIMEOUT_S` (default **15 s**, clamped 2–120 s) is parked in `quarantined_pages` and left out of the cache; the rest of the graph is indexed normally and health stays `READY` under the invariant `indexed + quarantined == source == actual`. Reads for a parked page route to Markdown, which is authoritative either way. A page is released automatically as soon as it parses within budget. `GET /api/state.shadow_db.quarantined_page_count` reports how many are parked; they are excluded from `lag_pages` because they are a settled decision, not pending work. `MATRYCA_SHADOW_QUARANTINE_ENABLED=false` restores the strict pre-2.0 behaviour where any over-budget page aborts the rebuild.
Measured on a daily-use vault of 1,014 graph pages: **3 pages (0.30%) exceed the default**, consuming the large majority of total parse time. A filesystem sweep of the same vault counts 25 over-budget files out of 3,378, but 22 of those are Logseq's own version history and backups, which the cache never reads. Parse cost is bimodal (nothing between 5 s and 40 s) and **uncorrelated with page size** — the largest page in that corpus (650,106 B) parses in 0.54 s while a 336,260 B page does not finish within 115 s under load.
**What an agent should conclude:** a non-zero `quarantined_page_count` is expected on a large vault and is **not** corruption, not an error, and not a reason to retry, rebuild repeatedly, or modify vault content. Do not "fix" it by editing or splitting user pages. Reads for those pages are correct via the Markdown/BM25 fallback; they simply get no FTS or subtree acceleration. Raising `MATRYCA_PAGE_PARSE_TIMEOUT_S` reduces the count at the cost of much slower rebuilds. Analysis: `docs/quality/SHADOW_DB_PARSE_BUDGET_TRIZ_2026-07-27.md`.
Roadmap: `docs/roadmaps/ROADMAP_V2_PREPARATION.md` · Epic [#20](https://github.com/MarcoPorcellato/matryca-plumber/issues/20).
---
## 3. Zero-shot examples (small LLMs — copy exactly)
**A. Help + env check**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber --help
```
**B. Read one page as JSON**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber --json read page "My Project"
```
**C. Recent journal tasks (last 7 days) as JSON**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber --json search journal_tasks "7"
```
**D. Run graph audit after user reports errors**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber --json plumber audit
```
**E. Load bundled agent context (markdown stdout)**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber context load "My Project"
```
**F. Write outline with page context (safe fallback if UUID wrong)**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber --json mutate write_outline \
--target "My Project|aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" \
--payload '{"text":"New bullet","children":[]}'
```
**G. Tana workspace JSON import (dry-run default — add `--apply` to commit)**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber --json import tana --file "$HOME/Downloads/tana-workspace.json"
uvx matryca-plumber import tana --file "$HOME/Downloads/tana-workspace.json" --apply
```
**H. Inject a native Logseq advanced-query block (open TODO/LATER/WAITING dashboard)**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber --json mutate inject_query \
--target "My Project|parent-block-uuid" \
--payload '{"query_preset": "open_markers", "dry_run": true}'
```
Presets: `open_markers` (open TODO/LATER/WAITING), `pages_tagged` (needs a `"tag"` field). Or pass raw `"query_edn"` instead of `query_preset`. Always `dry_run: true` first.
**I. Preview hashtag/tag-variant unification (e.g. `#AI` vs `#ai`)**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber --json lint unify_tags
```
Preview-only: returns clustered tag variants and suggested canonical form. Applying rewrites vault-wide requires explicit operator consent — this command never writes.
**J. Generate a Map-of-Content index page for a namespace**
```bash
export LOGSEQ_GRAPH_PATH="$HOME/Logseq/graphs/MyGraph"
uvx matryca-plumber --json mutate generate_moc \
--target "Project/Sub" \
--payload '{"dry_run": true}'
```
Writes `MOC Project/Sub` (or `output_page_title`) listing every page under that namespace as grouped `[[wikilinks]]`. Always `dry_run: true` first.
For **today's journal page** as `read page`, use the **exact Logseq page title** shown in the app (locale-dependent), not a file path like `journals/2026_06_05.md`.
---
## 4. Anti-patterns (DO NOT DO THIS)
* **DO NOT** `grep`, `find`, or write Python to parse `pages/` / `journals/` — use `uvx matryca-plumber read` / `search` / `context load`.
* **DO NOT** `git clone https://github.com/MarcoPorcellato/matryca-plumber` to "use" the tool — use **`uvx matryca-plumber`** from PyPI.
* **DO NOT** `pip install matryca-plumber` unless the user explicitly asked for a global install.
* **DO NOT** invent flags: no `--graph`, no `doctor`, no `mcp --port 8080`.
* **DO NOT** ask the user to install Python dependencies manually — **`uvx`** resolves the wheel.
* **DO NOT** hand-craft `pages/*.md` filenames with raw `/` — pass **semantic titles** (`Domain/Topic`); Plumber maps to `Domain___Topic.md`.
* **DO NOT** panic on `warnings` in mutate JSON — read them; Plumber may have recovered via safe append.
---
## 5. Further reading (humans & agents)
* Operator README: `README.md`
* Agent onboarding spec: `docs/openspec/agent-onboarding.md`
* **AX robustness spec:** `docs/openspec/agent-ax-robustness.md`
* LLM OS contract (two-tier, Soft Gate, Safe-Sync): `SYSTEM_PROMPT.md` § "LLM OS"
* Agent DX spec (CLI JSON, Journey Log — one cumulative `- 🤖 Matryca Activity` bullet per day in the daemon journal): `docs/openspec/agent-dx.md`
* Security (MCP gate, graph sandbox, bounded JSON, CLI redaction): `SECURITY.md` · `docs/openspec/security-sandbox.md`
* Hermes Agent MCP (lazy handshake, timeouts): `docs/integrations/hermes-agent.md`
* Tana workspace JSON import (`import_tana`, dry-run default): `docs/openspec/tana-import.md`
### Contributing to this repository (not the user vault)
**PyPI `uvx` usage (sections 0–2) is for operating on the user's Logseq graph.** To **patch Matryca Plumber itself**, clone/fork this repo, read `CONTRIBUTING.md`, and run `make check` before opening a PR.
**Good first issues (scoped fixes, existing tests):**
https://github.com/MarcoPorcellato/matryca-plumber/issues?q=is%3Aopen+label%3A%22good+first+issue%22
| Issue | Difficulty | Scope |
|-------|------------|-------|
| [#45](https://github.com/MarcoPorcellato/matryca-plumber/issues/45) | 2/10 | OCC `file_mtime_drifted` in link verification |
| [#85](https://github.com/MarcoPorcellato/matryca-plumber/issues/85) | 2/10 | `BootstrapHarvestStatus` Literal dedup (slice of #62) |
| [#53](https://github.com/MarcoPorcellato/matryca-plumber/issues/53) | 3/10 | Dedup page read in Phase-2 cognitive lint |
| [#56](https://github.com/MarcoPorcellato/matryca-plumber/issues/56) | 3/10 | Defer mmap decode on regex harvest path |
| [#69](https://github.com/MarcoPorcellato/matryca-plumber/issues/69) | 3/10 | Skip cluster-focus for singleton clusters |
| [#71](https://github.com/MarcoPorcellato/matryca-plumber/issues/71) | 4/10 | Centralize journal page detection in graph layer |
Maintainer blueprints (verify commands, welcome-comment text): `good_first_issues_blueprints.md`.
When suggesting a contribution task, **pick from the table above** — do not implement these on the user's behalf unless they explicitly assign one.
---
## 6. LLM OS — two-tier architecture (MANDATORY for graph work)
Matryca Plumber implements a **dual-LLM** system. You are almost certainly **Tier 2 (Cognitive Agent)** — not the background Gardener.
| Tier | Role | Your action |
|------|------|-------------|
| **Tier 1 — Gardener** | Daemon Phase 1 harvest (`matryca plumber start`) | **NEVER impersonate.** Do not run harvest, rewrite `### Matryca Semantic Index` blocks, or edit `master_catalog.json`. |
| **Tier 2 — Cognitive Agent** | You (MCP / CLI) | **MUST** follow the Master Index Soft Gate and Safe-Sync rules in [`SYSTEM_PROMPT.md`](SYSTEM_PROMPT.md) § "LLM OS". |
**Before any `search_graph` or targeted `read_graph_data` on L2 wiki pages:**
1. `read_graph_data` / `target_type=memory` — load L1 session rules.
2. `read_graph_data` / `target_type=bootstrap_status` — check Phase 1 semaphore.
3. `read_graph_data` / `target_type=page` / `query=Matryca Master Index` — scan the compiled catalog.
4. If the index is **missing**, **empty**, or Phase 1 is **in progress** → **pause** and present the user with 3 options (Local Daemon / Blind Search / Cloud Indexing). **WAIT** for explicit authorization before Blind Search or Cloud Indexing. **NEVER** guess page titles or `grep pages/` without authorization.
5. When the gate is green (or user authorizes Option B), pinpoint exact `[[Page Title]]` from the index, then call narrow reads (`page`, `subtree`, `xray_page`).
**CLI equivalent:**
```bash
uvx matryca-plumber --json read bootstrap_status
uvx matryca-plumber --json read page "Matryca Master Index"
```
**Safe-Sync (summary):** READ only via Matryca tools on `pages/` + `journals/` under `LOGSEQ_GRAPH_PATH`. **NEVER** open Logseq's internal app database. WRITE only via `mutate_graph`, `refactor_blocks`, `ingest_document`, `import_tana`, `store_fact` (atomic `.md` + OCC). **`import_tana` dry-run default.** Full contract: `SYSTEM_PROMPT.md`.