logseq-matryca-parser 0.3.0__tar.gz → 0.3.2__tar.gz
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.
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/PKG-INFO +15 -3
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/README.md +14 -2
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/ARCHITECTURE.md +31 -9
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/pyproject.toml +1 -1
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/__init__.py +1 -1
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/agent_press.py +2 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/kinetic.py +73 -1
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/tests/test_agent_press.py +35 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/uv.lock +1 -1
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.cursorignore +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.cursorrules +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/FUNDING.yml +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/dependabot.yml +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/workflows/ci.yml +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/workflows/pypi_publish.yml +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.gitignore +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.pre-commit-config.yaml +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.repomixignore +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/CONTRIBUTING.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/LICENSE +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/Makefile +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/NOTICE +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/ROADMAP_AGENT_NATIVE_XRAY.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/ROADMAP_HEADLESS_WRITER.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/ROADMAP_OBSIDIAN_ADAPTER.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/SECURITY.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/claude-skill-logseq-read/SKILL.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/claude-skill-logseq-read/scripts/parse_logseq.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/ARCHITECTURE_BLUEPRINT.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/CODE_SCAFFOLD.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/LOGSEQ_ASSET_RESOLUTION_SPEC.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/LOGSEQ_DATASCRIPT_MAPPING.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/LOGSEQ_TEMPORAL_ONTOLOGY.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/OFFICIAL_MLDOC_SPECS.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/REFERENCE_SPEC.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/error_log.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/logseq_ast_primer.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/roadmaps/ROADMAP_CLI_HYDRATION_AND_ENRICHMENT.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/roadmaps/ROADMAP_CONTEXT_SYNTHESIS_AND_SCOPING.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/roadmaps/ROADMAP_EMBED_EXPANSION_AND_FLUENT_QUERIES.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/roadmaps/ROADMAP_GRAPH_RAG_SEMANTICS.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/roadmaps/ROADMAP_INCREMENTAL_WATCHER.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/roadmaps/ROADMAP_INLINE_SHIELD_AND_NAMESPACES.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/roadmaps/ROADMAP_ROBUSTNESS_AND_SOFT_BREAKS.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/roadmaps/ROADMAP_TOML_FIX_AND_PYPI_DISTRIBUTION.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/roadmaps/ROADMAP_UUID_AND_GRAPH_SUPERPOWERS.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/examples/demo_logseq_journal.md +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/examples/run_demo.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/legacy/local_digestor.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/lib/bindings/utils.js +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/lib/tom-select/tom-select.complete.min.js +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/lib/tom-select/tom-select.css +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/lib/vis-9.1.2/vis-network.css +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/lib/vis-9.1.2/vis-network.min.js +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/.gitignore +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/NOTICE +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/__main__.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/agent_writer.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/exceptions.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/forge.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/graph.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/lens.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/logos_core.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/logos_parser.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/pyproject.toml +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/synapse.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/tests/test_agent_writer.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/tests/test_forge.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/tests/test_graph.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/tests/test_kinetic.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/tests/test_lens.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/tests/test_logos_parser.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/tests/test_package_version.py +0 -0
- {logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/tests/test_synapse.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: logseq-matryca-parser
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: The Logos Protocol: Deterministic Logseq AST parsing for Matryca.ai.
|
|
5
5
|
Project-URL: Homepage, https://github.com/MarcoPorcellato/logseq-matryca-parser
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/MarcoPorcellato/logseq-matryca-parser/issues
|
|
@@ -136,7 +136,7 @@ Logseq Matryca Parser is a deterministic **Stack-Machine engine** that acts as t
|
|
|
136
136
|
|
|
137
137
|
---
|
|
138
138
|
|
|
139
|
-
## ⚡ Recent superpowers (Waves 4–
|
|
139
|
+
## ⚡ Recent superpowers (Waves 4–12)
|
|
140
140
|
|
|
141
141
|
### Obsidian-native export
|
|
142
142
|
Compile an entire Logseq graph into an **Obsidian vault layout**: YAML frontmatter from page properties, list body preserved, Logseq `((uuid))` links rewritten to **`[[Page#^anchor]]`**, and trailing **`^block-id`** on referenced blocks. Namespace titles become nested folders (e.g. `Projects/AI/Demo.md`).
|
|
@@ -176,6 +176,16 @@ matryca-parse agent-read /path/to/graph --query "quantum"
|
|
|
176
176
|
|
|
177
177
|
The agent reads cheap topology now; the registry resolves aliases back to sovereign UUIDs when you wire targeted writes.
|
|
178
178
|
|
|
179
|
+
### Headless Write Engine & AST Linter (Wave 12)
|
|
180
|
+
The parser is **no longer read-only**. Wave 12 adds a **headless Markdown splicer** ([`agent_writer.py`](src/logseq_matryca_parser/agent_writer.py)): `append_child_to_node` uses AST line numbers and indentation (`(indent_level + 1) × tab_size`) to insert a new bullet **atomically** into the sovereign `.md` file—via `tempfile` + `os.replace`—without Logseq’s fragile HTTP API. Pair **`agent-read`** with **`agent-write`**: X-Ray persists its alias map to **`.matryca_xray_state.json`** at the graph root so stateless CLI invocations can **read, then write** in sequence.
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
matryca-parse agent-read /path/to/graph --tag idea
|
|
184
|
+
matryca-parse agent-write /path/to/graph --alias 0 --content "Follow-up from the agent"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
For graph hygiene, **`LogseqGraph.get_broken_references()`** flags nodes whose `((uuid))` block refs point at missing registry targets—structural linting, not regex guessing.
|
|
188
|
+
|
|
179
189
|
---
|
|
180
190
|
|
|
181
191
|
## 🏗️ Core Capabilities
|
|
@@ -188,6 +198,8 @@ The agent reads cheap topology now; the registry resolves aliases back to sovere
|
|
|
188
198
|
| **FORGE** | JSON, clean Markdown, and **Obsidian** vault serialization (`ObsidianForgeVisitor`, `ForgeExporter.to_obsidian_markdown`). |
|
|
189
199
|
| **LENS Visualizer** | 60FPS interactive graph rendering (10k+ nodes) with Glassmorphism HUD. |
|
|
190
200
|
| **Agent-Native Printing Press** | [`agent_press.py`](src/logseq_matryca_parser/agent_press.py): **`SessionAliasRegistry`** maps session aliases ↔ block UUIDs; **`to_xray_markdown`** emits token-minimal outline text for autonomous agents (`matryca-parse agent-read`). |
|
|
201
|
+
| **Headless Write Engine** | [`agent_writer.py`](src/logseq_matryca_parser/agent_writer.py): **`append_child_to_node`** splices child bullets into on-disk Markdown from AST topology; **`matryca-parse agent-write`** resolves aliases via **`.matryca_xray_state.json`**. |
|
|
202
|
+
| **AST Linters** | **`LogseqGraph.get_broken_references()`** returns originating nodes when `block_refs` target UUIDs absent from the global registry. |
|
|
191
203
|
| **Sovereign AI** | 100% Local. Zero telemetry. Private by design. |
|
|
192
204
|
|
|
193
205
|
### Data model — `LogseqNode` task fields
|
|
@@ -201,7 +213,7 @@ Each AST block is a `LogseqNode`. Alongside `task_status`, the parser surfaces p
|
|
|
201
213
|
"task_priority": "A",
|
|
202
214
|
"scheduled_at": 1641600000,
|
|
203
215
|
"deadline_at": 1641772800,
|
|
204
|
-
"clean_text": "Cut v0.3.
|
|
216
|
+
"clean_text": "Cut v0.3.2 release"
|
|
205
217
|
}
|
|
206
218
|
```
|
|
207
219
|
|
|
@@ -100,7 +100,7 @@ Logseq Matryca Parser is a deterministic **Stack-Machine engine** that acts as t
|
|
|
100
100
|
|
|
101
101
|
---
|
|
102
102
|
|
|
103
|
-
## ⚡ Recent superpowers (Waves 4–
|
|
103
|
+
## ⚡ Recent superpowers (Waves 4–12)
|
|
104
104
|
|
|
105
105
|
### Obsidian-native export
|
|
106
106
|
Compile an entire Logseq graph into an **Obsidian vault layout**: YAML frontmatter from page properties, list body preserved, Logseq `((uuid))` links rewritten to **`[[Page#^anchor]]`**, and trailing **`^block-id`** on referenced blocks. Namespace titles become nested folders (e.g. `Projects/AI/Demo.md`).
|
|
@@ -140,6 +140,16 @@ matryca-parse agent-read /path/to/graph --query "quantum"
|
|
|
140
140
|
|
|
141
141
|
The agent reads cheap topology now; the registry resolves aliases back to sovereign UUIDs when you wire targeted writes.
|
|
142
142
|
|
|
143
|
+
### Headless Write Engine & AST Linter (Wave 12)
|
|
144
|
+
The parser is **no longer read-only**. Wave 12 adds a **headless Markdown splicer** ([`agent_writer.py`](src/logseq_matryca_parser/agent_writer.py)): `append_child_to_node` uses AST line numbers and indentation (`(indent_level + 1) × tab_size`) to insert a new bullet **atomically** into the sovereign `.md` file—via `tempfile` + `os.replace`—without Logseq’s fragile HTTP API. Pair **`agent-read`** with **`agent-write`**: X-Ray persists its alias map to **`.matryca_xray_state.json`** at the graph root so stateless CLI invocations can **read, then write** in sequence.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
matryca-parse agent-read /path/to/graph --tag idea
|
|
148
|
+
matryca-parse agent-write /path/to/graph --alias 0 --content "Follow-up from the agent"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
For graph hygiene, **`LogseqGraph.get_broken_references()`** flags nodes whose `((uuid))` block refs point at missing registry targets—structural linting, not regex guessing.
|
|
152
|
+
|
|
143
153
|
---
|
|
144
154
|
|
|
145
155
|
## 🏗️ Core Capabilities
|
|
@@ -152,6 +162,8 @@ The agent reads cheap topology now; the registry resolves aliases back to sovere
|
|
|
152
162
|
| **FORGE** | JSON, clean Markdown, and **Obsidian** vault serialization (`ObsidianForgeVisitor`, `ForgeExporter.to_obsidian_markdown`). |
|
|
153
163
|
| **LENS Visualizer** | 60FPS interactive graph rendering (10k+ nodes) with Glassmorphism HUD. |
|
|
154
164
|
| **Agent-Native Printing Press** | [`agent_press.py`](src/logseq_matryca_parser/agent_press.py): **`SessionAliasRegistry`** maps session aliases ↔ block UUIDs; **`to_xray_markdown`** emits token-minimal outline text for autonomous agents (`matryca-parse agent-read`). |
|
|
165
|
+
| **Headless Write Engine** | [`agent_writer.py`](src/logseq_matryca_parser/agent_writer.py): **`append_child_to_node`** splices child bullets into on-disk Markdown from AST topology; **`matryca-parse agent-write`** resolves aliases via **`.matryca_xray_state.json`**. |
|
|
166
|
+
| **AST Linters** | **`LogseqGraph.get_broken_references()`** returns originating nodes when `block_refs` target UUIDs absent from the global registry. |
|
|
155
167
|
| **Sovereign AI** | 100% Local. Zero telemetry. Private by design. |
|
|
156
168
|
|
|
157
169
|
### Data model — `LogseqNode` task fields
|
|
@@ -165,7 +177,7 @@ Each AST block is a `LogseqNode`. Alongside `task_status`, the parser surfaces p
|
|
|
165
177
|
"task_priority": "A",
|
|
166
178
|
"scheduled_at": 1641600000,
|
|
167
179
|
"deadline_at": 1641772800,
|
|
168
|
-
"clean_text": "Cut v0.3.
|
|
180
|
+
"clean_text": "Cut v0.3.2 release"
|
|
169
181
|
}
|
|
170
182
|
```
|
|
171
183
|
|
|
@@ -82,7 +82,7 @@ title Logseq Matryca Parser — C4 Level 2 (Containers)
|
|
|
82
82
|
Person(knowledgeWorker, "Knowledge Worker", "Local operator of a sovereign Logseq graph.")
|
|
83
83
|
|
|
84
84
|
System_Boundary(matrycaEcosystem, "Matryca.ai Ecosystem") {
|
|
85
|
-
Container(kinetic, "KINETIC", "Typer / Rich CLI", "CLI — export (json, markdown, langchain, langchain-enriched, obsidian), visualize, demo, graph scans, `agent-read` (
|
|
85
|
+
Container(kinetic, "KINETIC", "Typer / Rich CLI", "CLI — export (json, markdown, langchain, langchain-enriched, obsidian), visualize, demo, graph scans, `agent-read` / `agent-write` (X-Ray + headless splice), weekly append (`append`).")
|
|
86
86
|
Container(logos, "LOGOS", "Python / Pydantic", "Stack-Machine AST engine — LogseqPage and LogseqNode models.")
|
|
87
87
|
Container(synapse, "SYNAPSE", "LangChain / LlamaIndex", "Framework-native exporters with parent-child metadata.")
|
|
88
88
|
Container(lens, "LENS", "NetworkX / PyVis", "Reference-topology visualization to interactive HTML.")
|
|
@@ -258,9 +258,15 @@ The KINETIC **`export --format langchain-enriched`** path serializes these docum
|
|
|
258
258
|
|
|
259
259
|
Visualization export uses **`pyvis`** with **`force_atlas_2based`** physics, fullscreen canvas, HUD filters, glassmorphism control chrome, and stabilized layout configuration suitable for **large graphs at interactive frame rates** in the browser (product positioning targets fluid exploration of graphs on the order of **10⁴ nodes**).
|
|
260
260
|
|
|
261
|
-
### 3.4 AGENT WRITER — Append-Only Sandboxing
|
|
261
|
+
### 3.4 AGENT WRITER — Append-Only Sandboxing & Headless Splicer
|
|
262
262
|
|
|
263
|
-
In the **LLM OS** metaphor, **LOGOS** is the **read path** into the hierarchical “disk”: it materializes Spatial Markdown into a **deterministic AST** that downstream adapters trust. **`agent_writer`** ([`logseq_matryca_parser.agent_writer`](../src/logseq_matryca_parser/agent_writer.py)) is the complementary **bounded write syscall
|
|
263
|
+
In the **LLM OS** metaphor, **LOGOS** is the **read path** into the hierarchical “disk”: it materializes Spatial Markdown into a **deterministic AST** that downstream adapters trust. **`agent_writer`** ([`logseq_matryca_parser.agent_writer`](../src/logseq_matryca_parser/agent_writer.py)) is the complementary **bounded write syscall** with two surfaces:
|
|
264
|
+
|
|
265
|
+
1. **Weekly append sandbox (`logseq_agent_write`).** A **deterministic**, **configuration-aware** channel that **dynamically reads `config.edn`** (for example **`:journal/page-title-format`**) so filenames and titles align with the vault’s own conventions. Writes use **`open(..., mode="a")`** **append-only** I/O — agents **append** new block material **after** existing bytes; they do **not** rewrite, merge, or re-indent prior content. Surfaced through the **`append`** command in **KINETIC**.
|
|
266
|
+
|
|
267
|
+
2. **Headless Markdown splicer (`append_child_to_node`).** For **in-place graph mutation** under an existing parent block, the engine resolves `target_uuid` via `LogseqGraph.get_node_by_uuid`, walks to the **deepest last descendant** to obtain a **1-based `line_end` insertion index**, and computes child indentation as **`(target_node.indent_level + 1) × graph.tab_size`** spaces before the `- {content}` bullet prefix. The raw file is split into lines, the new row is inserted at that index, and the result is flushed through a **same-directory `tempfile.mkstemp` + `os.replace`** — an atomic swap that avoids torn reads during concurrent tooling. **KINETIC** exposes this as **`matryca-parse agent-write`**, resolving parent blocks by **`--alias`** (from the X-Ray state file) or **`--target-uuid`**.
|
|
268
|
+
|
|
269
|
+
Both paths keep **existing topology intact** relative to their contract: append-only journaling never truncates prior bytes; the splicer only inserts one new child line at an AST-derived coordinate so a subsequent **LOGOS** parse remains deterministic.
|
|
264
270
|
|
|
265
271
|
### 3.5 FORGE — multi-target serialization (JSON, Markdown, Obsidian)
|
|
266
272
|
|
|
@@ -293,13 +299,21 @@ This keeps **global indexes consistent** without rebuilding the entire graph.
|
|
|
293
299
|
|
|
294
300
|
**`graph.query()`** seeds a [`GraphQuery`](../src/logseq_matryca_parser/graph.py) with **all registered nodes**, then applies chainable filters: **`has_tag`**, **`with_priority`**, **`under_parent(parent_uuid)`** (ancestor chain on `path`), **`is_task_state`**, and **`execute()`** returning a materialized list. This is the **programmatic complement** to SQL-less graph inspection — ideal for **batch exporters**, **lint rules**, and **agent planners** that need a typed slice of the outline without ad-hoc traversal code.
|
|
295
301
|
|
|
302
|
+
#### AST reference linter (`get_broken_references`)
|
|
303
|
+
|
|
304
|
+
**`LogseqGraph.get_broken_references()`** scans every node in **`_node_registry`**. When **`block_refs`** contains a `((uuid))` target absent from the registry, the **originating node** is collected. Downstream apps (MCP servers, CI, pre-embed hooks) get **structural link validation** aligned with LOGOS identity rules — not brittle regex over raw Markdown.
|
|
305
|
+
|
|
296
306
|
### 3.7 AGENT PRESS — Agent-native printing press & X-Ray mode
|
|
297
307
|
|
|
298
308
|
Human-facing RAG (SYNAPSE enriched chunks, breadcrumbs, inherited properties) optimizes for **embedding geometry** and **retrieval filters**. Autonomous agents running tight **read → plan → write** loops need a different projection: **the fewest tokens per topological fact**. **`agent_press.py`** ([`logseq_matryca_parser.agent_press`](../src/logseq_matryca_parser/agent_press.py)) implements the **Printing Press** paradigm: compress the in-memory AST for machine consumption **without** sacrificing parent–child shape.
|
|
299
309
|
|
|
310
|
+
#### Stateful session registry (`.matryca_xray_state.json`)
|
|
311
|
+
|
|
312
|
+
X-Ray is designed for **stateless LLM toolchains**: each `agent-read` invocation is a fresh process, yet agents must still **write back** to blocks they only saw as `[n]` tokens. After **`generate_aliases`**, **KINETIC** persists the alias map to **`<graph_root>/.matryca_xray_state.json`** via **`SessionAliasRegistry.save_to_disk`**. A later **`matryca-parse agent-write --alias N`** loads that JSON with **`load_from_disk`**, resolves `N → uuid`, and hands off to **`append_child_to_node`**. The read/write pair therefore composes as **two independent CLI exits** without stuffing UUIDs into the model context — the filesystem holds session continuity.
|
|
313
|
+
|
|
300
314
|
#### Session alias mechanics (`SessionAliasRegistry`)
|
|
301
315
|
|
|
302
|
-
`SessionAliasRegistry` is a **session-scoped
|
|
316
|
+
`SessionAliasRegistry` is a **session-scoped translation table** (in-RAM during a single command, rehydratable from disk across commands) between lightweight aliases and sovereign block identities:
|
|
303
317
|
|
|
304
318
|
| Operation | Role |
|
|
305
319
|
| --------- | ---- |
|
|
@@ -323,18 +337,26 @@ Heavy Logseq identifiers (`id:: 64a8b0c1-d33b-4448-a261-e4dc2bbe12d3`, synthetic
|
|
|
323
337
|
|
|
324
338
|
No YAML, no JSON wrappers, no collapsed-state metadata, no blank separator lines — **pure topology + semantics** for the LLM “CPU” to load into its context window.
|
|
325
339
|
|
|
326
|
-
#### KINETIC `agent-read` — Rich bypass for machine stdout
|
|
340
|
+
#### KINETIC `agent-read` / `agent-write` — Rich bypass for machine stdout
|
|
341
|
+
|
|
342
|
+
The compound CLI commands **`agent_read`** and **`agent_write`** in [`kinetic.py`](../src/logseq_matryca_parser/kinetic.py) are the operator surfaces for the **Headless CRUD** loop:
|
|
327
343
|
|
|
328
|
-
|
|
344
|
+
**`matryca-parse agent-read`**
|
|
329
345
|
|
|
330
346
|
1. **`LogseqGraph.load_directory`** — materialize the RAM image of the vault.
|
|
331
347
|
2. **Filter** — `graph.query().has_tag(tag).execute()` when `--tag` is set; otherwise `search_content(query)` when `--query` is set; otherwise all registered nodes.
|
|
332
|
-
3. **`SessionAliasRegistry.generate_aliases`** → **`to_xray_markdown`**.
|
|
348
|
+
3. **`SessionAliasRegistry.generate_aliases`** → **`save_to_disk(.matryca_xray_state.json)`** → **`to_xray_markdown`**.
|
|
333
349
|
4. **Emit via `sys.stdout.write`** — deliberately **not** Typer’s Rich `Console`.
|
|
334
350
|
|
|
335
|
-
|
|
351
|
+
**`matryca-parse agent-write`**
|
|
352
|
+
|
|
353
|
+
1. Reload the graph (fresh AST coordinates after any external edits).
|
|
354
|
+
2. Resolve **`--alias`** through the persisted registry (or accept **`--target-uuid`** directly).
|
|
355
|
+
3. **`append_child_to_node`** — atomic Markdown splice at the parent’s AST line index.
|
|
356
|
+
|
|
357
|
+
Rich styling injects **ANSI escape sequences** that waste tokens and can cause models to **hallucinate markup** as content. `agent-read` is **stdout-pure** so shell pipelines, MCP tools, and headless agents receive **unescaped plain text** only. Human-oriented commands (`scan`, `export`, `visualize`) keep Rich; the **machine-native read/write paths** opt out where token fidelity matters.
|
|
336
358
|
|
|
337
|
-
This complements §3.4 **AGENT WRITER** (append
|
|
359
|
+
This complements §3.4 **AGENT WRITER** (weekly append + headless splice) and §3.2 **SYNAPSE** (human/RAG chunking): one stack, multiple projections — **enriched chunks for vectors**, **X-Ray + alias state for agent context**, **append / splice for durable writes**.
|
|
338
360
|
|
|
339
361
|
---
|
|
340
362
|
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/agent_press.py
RENAMED
|
@@ -10,6 +10,8 @@ from logseq_matryca_parser.logos_core import LogseqNode
|
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
13
|
+
XRAY_STATE_FILENAME = ".matryca_xray_state.json"
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
def _flatten_subtrees(nodes: list[LogseqNode]) -> list[LogseqNode]:
|
|
15
17
|
"""Depth-first list of nodes under each root, preserving outline order."""
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/kinetic.py
RENAMED
|
@@ -503,7 +503,11 @@ def agent_read(
|
|
|
503
503
|
query: str | None = typer.Option(None, "--query", help="Substring search on clean_text."),
|
|
504
504
|
) -> None:
|
|
505
505
|
"""Load a graph, filter nodes, and print ultra-dense X-Ray text to stdout (no Rich)."""
|
|
506
|
-
from logseq_matryca_parser.agent_press import
|
|
506
|
+
from logseq_matryca_parser.agent_press import (
|
|
507
|
+
SessionAliasRegistry,
|
|
508
|
+
XRAY_STATE_FILENAME,
|
|
509
|
+
to_xray_markdown,
|
|
510
|
+
)
|
|
507
511
|
from logseq_matryca_parser.graph import LogseqGraph
|
|
508
512
|
|
|
509
513
|
if not graph_path.exists() or not graph_path.is_dir():
|
|
@@ -520,6 +524,9 @@ def agent_read(
|
|
|
520
524
|
|
|
521
525
|
registry = SessionAliasRegistry()
|
|
522
526
|
registry.generate_aliases(nodes)
|
|
527
|
+
state_path = graph_path.resolve() / XRAY_STATE_FILENAME
|
|
528
|
+
registry.save_to_disk(state_path)
|
|
529
|
+
|
|
523
530
|
output = to_xray_markdown(nodes, registry)
|
|
524
531
|
if output:
|
|
525
532
|
sys.stdout.write(output)
|
|
@@ -527,5 +534,70 @@ def agent_read(
|
|
|
527
534
|
sys.stdout.write("\n")
|
|
528
535
|
|
|
529
536
|
|
|
537
|
+
@app.command("agent-write")
|
|
538
|
+
def agent_write(
|
|
539
|
+
graph_path: Path = typer.Argument(..., help="Path to the Logseq graph root."),
|
|
540
|
+
content: str = typer.Option(..., "--content", help="Markdown body for the new child bullet."),
|
|
541
|
+
alias: int | None = typer.Option(
|
|
542
|
+
None,
|
|
543
|
+
"--alias",
|
|
544
|
+
help="Session alias from a prior agent-read (resolved via .matryca_xray_state.json).",
|
|
545
|
+
),
|
|
546
|
+
target_uuid: str | None = typer.Option(
|
|
547
|
+
None,
|
|
548
|
+
"--target-uuid",
|
|
549
|
+
help="Parent block UUID (bypasses alias registry).",
|
|
550
|
+
),
|
|
551
|
+
state_file: Path | None = typer.Option(
|
|
552
|
+
None,
|
|
553
|
+
"--state-file",
|
|
554
|
+
help="Alias registry JSON (default: <graph>/.matryca_xray_state.json).",
|
|
555
|
+
),
|
|
556
|
+
) -> None:
|
|
557
|
+
"""Append a child block under a parent via headless AST markdown splicing."""
|
|
558
|
+
from logseq_matryca_parser.agent_press import SessionAliasRegistry, XRAY_STATE_FILENAME
|
|
559
|
+
from logseq_matryca_parser.agent_writer import append_child_to_node
|
|
560
|
+
from logseq_matryca_parser.graph import LogseqGraph
|
|
561
|
+
|
|
562
|
+
if alias is None and target_uuid is None:
|
|
563
|
+
print("Provide --alias or --target-uuid.", file=sys.stderr)
|
|
564
|
+
raise typer.Exit(code=1)
|
|
565
|
+
if alias is not None and target_uuid is not None:
|
|
566
|
+
print("Use only one of --alias or --target-uuid.", file=sys.stderr)
|
|
567
|
+
raise typer.Exit(code=1)
|
|
568
|
+
|
|
569
|
+
if not graph_path.exists() or not graph_path.is_dir():
|
|
570
|
+
print(f"Invalid graph path: {graph_path}", file=sys.stderr)
|
|
571
|
+
raise typer.Exit(code=1)
|
|
572
|
+
|
|
573
|
+
graph = LogseqGraph.load_directory(graph_path.resolve())
|
|
574
|
+
|
|
575
|
+
parent_uuid = target_uuid
|
|
576
|
+
if alias is not None:
|
|
577
|
+
registry_path = state_file or (graph_path.resolve() / XRAY_STATE_FILENAME)
|
|
578
|
+
if not registry_path.is_file():
|
|
579
|
+
print(f"Alias state file not found: {registry_path}", file=sys.stderr)
|
|
580
|
+
raise typer.Exit(code=1)
|
|
581
|
+
registry = SessionAliasRegistry.load_from_disk(registry_path)
|
|
582
|
+
parent_uuid = registry.resolve_alias(alias)
|
|
583
|
+
if parent_uuid is None:
|
|
584
|
+
print(f"Unknown alias: {alias}", file=sys.stderr)
|
|
585
|
+
raise typer.Exit(code=1)
|
|
586
|
+
|
|
587
|
+
assert parent_uuid is not None
|
|
588
|
+
try:
|
|
589
|
+
append_child_to_node(graph, parent_uuid, content)
|
|
590
|
+
except ValueError as exc:
|
|
591
|
+
print(str(exc), file=sys.stderr)
|
|
592
|
+
raise typer.Exit(code=1) from exc
|
|
593
|
+
|
|
594
|
+
console.print(
|
|
595
|
+
f"[bold green]Appended child under[/] {parent_uuid}",
|
|
596
|
+
no_wrap=True,
|
|
597
|
+
overflow="ignore",
|
|
598
|
+
crop=False,
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
|
|
530
602
|
if __name__ == "__main__":
|
|
531
603
|
app()
|
|
@@ -115,3 +115,38 @@ def test_agent_read_cli_plain_stdout(tmp_path: Path) -> None:
|
|
|
115
115
|
assert "\x1b[" not in result.output
|
|
116
116
|
assert "[0]" in result.output
|
|
117
117
|
assert "X-Ray target" in result.output
|
|
118
|
+
|
|
119
|
+
state_path = graph_root / ".matryca_xray_state.json"
|
|
120
|
+
assert state_path.is_file()
|
|
121
|
+
restored = SessionAliasRegistry.load_from_disk(state_path)
|
|
122
|
+
assert restored.resolve_alias(0) is not None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_agent_write_cli_splices_via_alias_state(tmp_path: Path) -> None:
|
|
126
|
+
graph_root = tmp_path / "graph"
|
|
127
|
+
pages = graph_root / "pages"
|
|
128
|
+
pages.mkdir(parents=True)
|
|
129
|
+
(graph_root / "journals").mkdir()
|
|
130
|
+
(pages / "Write.md").write_text("- Parent #parent-tag\n", encoding="utf-8")
|
|
131
|
+
|
|
132
|
+
read_result = runner.invoke(
|
|
133
|
+
app,
|
|
134
|
+
["agent-read", str(graph_root), "--tag", "parent-tag"],
|
|
135
|
+
)
|
|
136
|
+
assert read_result.exit_code == 0
|
|
137
|
+
|
|
138
|
+
write_result = runner.invoke(
|
|
139
|
+
app,
|
|
140
|
+
[
|
|
141
|
+
"agent-write",
|
|
142
|
+
str(graph_root),
|
|
143
|
+
"--alias",
|
|
144
|
+
"0",
|
|
145
|
+
"--content",
|
|
146
|
+
"Child from agent-write",
|
|
147
|
+
],
|
|
148
|
+
)
|
|
149
|
+
assert write_result.exit_code == 0
|
|
150
|
+
|
|
151
|
+
updated = (pages / "Write.md").read_text(encoding="utf-8")
|
|
152
|
+
assert "Child from agent-write" in updated
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/ISSUE_TEMPLATE/bug_report.yml
RENAMED
|
File without changes
|
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/PULL_REQUEST_TEMPLATE.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/.github/workflows/pypi_publish.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/claude-skill-logseq-read/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/CODE_SCAFFOLD.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/OFFICIAL_MLDOC_SPECS.md
RENAMED
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/docs/design-docs/REFERENCE_SPEC.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/lib/vis-9.1.2/vis-network.min.js
RENAMED
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/.gitignore
RENAMED
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/NOTICE
RENAMED
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/exceptions.py
RENAMED
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/forge.py
RENAMED
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/graph.py
RENAMED
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/lens.py
RENAMED
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/logos_core.py
RENAMED
|
File without changes
|
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/pyproject.toml
RENAMED
|
File without changes
|
{logseq_matryca_parser-0.3.0 → logseq_matryca_parser-0.3.2}/src/logseq_matryca_parser/synapse.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|