logseq-matryca-parser 1.2.2__tar.gz → 1.3.1__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.
Files changed (93) hide show
  1. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/CHANGELOG.md +20 -0
  2. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/CONTRIBUTING.md +1 -1
  3. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/PKG-INFO +57 -9
  4. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/README.md +56 -8
  5. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/SECURITY.md +1 -1
  6. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/claude-skill-logseq-read/SKILL.md +1 -1
  7. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/ARCHITECTURE.md +16 -8
  8. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/CODEQL.md +1 -1
  9. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/logseq_ast_primer.md +1 -1
  10. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_INCREMENTAL_WATCHER.md +2 -0
  11. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_UUID_AND_GRAPH_SUPERPOWERS.md +2 -0
  12. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/examples/run_demo.py +4 -3
  13. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/legacy/local_digestor.py +6 -9
  14. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/pyproject.toml +22 -1
  15. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/__init__.py +26 -5
  16. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/forge.py +1 -4
  17. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/graph.py +100 -18
  18. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/kinetic.py +104 -57
  19. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/lens.py +9 -6
  20. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/logos_core.py +5 -5
  21. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/logos_parser.py +37 -8
  22. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/logseq_paths.py +17 -0
  23. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/synapse.py +134 -45
  24. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_agent_writer.py +5 -1
  25. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_graph.py +65 -1
  26. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_kinetic.py +27 -0
  27. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_lens.py +9 -1
  28. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_logos_parser.py +34 -9
  29. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_logseq_paths.py +2 -2
  30. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_package_version.py +17 -0
  31. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_synapse.py +70 -6
  32. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/uv.lock +97 -81
  33. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.cursorignore +0 -0
  34. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/CODEOWNERS +0 -0
  35. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/FUNDING.yml +0 -0
  36. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  37. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  38. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  39. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  40. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/dependabot.yml +0 -0
  41. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/workflows/ci.yml +0 -0
  42. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/workflows/daily-metrics.yml +0 -0
  43. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/workflows/github_release.yml +0 -0
  44. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.github/workflows/pypi_publish.yml +0 -0
  45. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.gitignore +0 -0
  46. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.pre-commit-config.yaml +0 -0
  47. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/.repomixignore +0 -0
  48. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/CODE_OF_CONDUCT.md +0 -0
  49. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/LICENSE +0 -0
  50. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/Makefile +0 -0
  51. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/NOTICE +0 -0
  52. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/claude-skill-logseq-read/scripts/parse_logseq.py +0 -0
  53. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/RELEASE_PROCESS.md +0 -0
  54. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/design-docs/ARCHITECTURE_BLUEPRINT.md +0 -0
  55. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/design-docs/CODE_SCAFFOLD.md +0 -0
  56. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/design-docs/LOGSEQ_ASSET_RESOLUTION_SPEC.md +0 -0
  57. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/design-docs/LOGSEQ_DATASCRIPT_MAPPING.md +0 -0
  58. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/design-docs/LOGSEQ_TEMPORAL_ONTOLOGY.md +0 -0
  59. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/design-docs/OFFICIAL_MLDOC_SPECS.md +0 -0
  60. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/design-docs/REFERENCE_SPEC.md +0 -0
  61. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/error_log.md +0 -0
  62. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_AGENT_NATIVE_XRAY.md +0 -0
  63. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_CLI_HYDRATION_AND_ENRICHMENT.md +0 -0
  64. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_CONTEXT_SYNTHESIS_AND_SCOPING.md +0 -0
  65. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_EMBED_EXPANSION_AND_FLUENT_QUERIES.md +0 -0
  66. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_GRAPH_RAG_SEMANTICS.md +0 -0
  67. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_HEADLESS_WRITER.md +0 -0
  68. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_INLINE_SHIELD_AND_NAMESPACES.md +0 -0
  69. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_OBSIDIAN_ADAPTER.md +0 -0
  70. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_ROBUSTNESS_AND_SOFT_BREAKS.md +0 -0
  71. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/docs/roadmaps/ROADMAP_TOML_FIX_AND_PYPI_DISTRIBUTION.md +0 -0
  72. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/examples/demo_logseq_journal.md +0 -0
  73. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/lib/bindings/utils.js +0 -0
  74. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/lib/tom-select/tom-select.complete.min.js +0 -0
  75. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/lib/tom-select/tom-select.css +0 -0
  76. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/lib/vis-9.1.2/vis-network.css +0 -0
  77. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/lib/vis-9.1.2/vis-network.min.js +0 -0
  78. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/metrics/history.json +0 -0
  79. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/repomix-output-parser.xml +0 -0
  80. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/scripts/debug_pre_release.py +0 -0
  81. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/scripts/extract_changelog.py +0 -0
  82. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/.gitignore +0 -0
  83. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/NOTICE +0 -0
  84. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/__main__.py +0 -0
  85. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/agent_press.py +0 -0
  86. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/agent_writer.py +0 -0
  87. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/exceptions.py +0 -0
  88. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/logseq_markdown.py +0 -0
  89. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/src/logseq_matryca_parser/pyproject.toml +0 -0
  90. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_agent_press.py +0 -0
  91. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_forge.py +0 -0
  92. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_logseq_markdown.py +0 -0
  93. {logseq_matryca_parser-1.2.2 → logseq_matryca_parser-1.3.1}/tests/test_pre_release_roundtrip.py +0 -0
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.3.1] - 2026-06-19
11
+
12
+ ### Changed
13
+
14
+ - **Documentation** — `examples/run_demo.py` and **`claude-skill-logseq-read/SKILL.md`** recommend **`uv sync --all-extras`** / **`uv pip install`** instead of legacy **`pip install`** hints.
15
+
16
+ ## [1.3.0] - 2026-06-19
17
+
18
+ ### Changed
19
+
20
+ - **Sprint 1 architectural quick wins** — **`discover_graph_files`** moved from `kinetic.py` to `logseq_paths.py` (decouples CLI from `LogseqGraph`); KINETIC optional-dependency errors now recommend **`uv sync --extra ai|viz`**; **`lens.py`** lazy-imports NetworkX/PyVis; **SYNAPSE** exports vector-store-safe metadata via **`SynapseMetadata`** / **`build_synapse_metadata`** (`task_priority`, temporal epochs, `source_uuid`, joined `path`/`refs`); explicit **`[tool.ruff]`** config in `pyproject.toml`.
21
+ - **Sprint 2 runtime robustness** — **`LogseqGraphWatcher`** debounces filesystem events (~500ms) and ignores editor temp/swap files; **`StackMachineParser(strict_refs=True)`** raises **`BlockReferenceError`** for unresolved same-page `((uuid))` refs (default off); **KINETIC** adds **`@app.callback()`** with **`--verbose`** / **`--graph`**, **`rich_markup_mode="rich"`**, and shared graph-path resolution.
22
+ - **Sprint 3 architecture** — **`LogseqGraph`** uses **`validate_assignment=True`** (no frozen/`object.__setattr__` hack); **SYNAPSE** **`LlamaIndexVisitor`** adds **`SOURCE`**, **`NEXT`**, and **`PREVIOUS`** relationships; package root **`__init__.py`** exports **`SynapseAdapter`**, **`SessionAliasRegistry`**, **`GraphVisualizer`**, and core LOGOS symbols via explicit **`__all__`**.
23
+ - **Optional AI stack** — `llama-index-core` bumped to `0.14.22` via lock refresh.
24
+ - **Documentation** — README, ARCHITECTURE, CONTRIBUTING, SECURITY, CODEQL, AST primer, and roadmaps updated for **1.3.0** (public API, watcher debounce, `strict_refs`, LlamaIndex spatial edges, `uv` install).
25
+
26
+ ### Security
27
+
28
+ - **Transitive dependency hardening** — `uv` constraints pin `aiohttp>=3.14.1` (11 Dependabot alerts); `nltk` overridden to `v3.10.0-rc1` from upstream Git until NLTK 3.10.0 ships on PyPI (GHSA-p4gq-832x-fm9v). Affects optional `[ai]` / `[all]` extras only; core install unchanged.
29
+
10
30
  ## [1.2.2] - 2026-06-18
11
31
 
12
32
  ### Fixed
@@ -15,7 +15,7 @@ User-facing behavior is documented in:
15
15
  - [`README.md`](README.md) — overview, quickstart, and feature matrix
16
16
  - [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — LOGOS, SYNAPSE, `LogseqGraph`, agents, and data flow
17
17
  - [`docs/logseq_ast_primer.md`](docs/logseq_ast_primer.md) — Logseq Spatial Markdown domain rules
18
- - [`CHANGELOG.md`](CHANGELOG.md) — shipped releases (current: **1.2.2**) and **Unreleased** changes (Keep a Changelog)
18
+ - [`CHANGELOG.md`](CHANGELOG.md) — shipped releases (current: **1.3.1**) and **Unreleased** changes (Keep a Changelog)
19
19
  - [`docs/RELEASE_PROCESS.md`](docs/RELEASE_PROCESS.md) — version bump, tag, and PyPI publish checklist
20
20
  - [`docs/CODEQL.md`](docs/CODEQL.md) — CodeQL default setup (no custom `codeql.yml`)
21
21
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logseq-matryca-parser
3
- Version: 1.2.2
3
+ Version: 1.3.1
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: Repository, https://github.com/MarcoPorcellato/logseq-matryca-parser
@@ -53,7 +53,7 @@ Description-Content-Type: text/markdown
53
53
  [![Status: Stable](https://img.shields.io/badge/Status-Stable-22c55e.svg?style=flat-square)](#)
54
54
  ![Origin: Matryca.ai](https://img.shields.io/badge/Origin-Matryca.ai-gold?style=for-the-badge)
55
55
 
56
- **v1.2.2** — CodeQL CI fix & docs (see [CHANGELOG](CHANGELOG.md)) — **234 tests**, no parser API changes; SAST via GitHub CodeQL **default setup** ([`docs/CODEQL.md`](docs/CODEQL.md)).
56
+ **v1.3.1** — Documentation patch: `uv` install hints in examples and Claude skill (see [CHANGELOG](CHANGELOG.md)) — **244 tests**, no parser or API changes.
57
57
 
58
58
  > *Turning a forest of local plain-text files into a unified semantic powerhouse.*
59
59
 
@@ -147,6 +147,34 @@ Logseq Matryca Parser is a deterministic **Stack-Machine engine** that acts as t
147
147
 
148
148
  ---
149
149
 
150
+ ## ⚡ Release highlights (v1.3.1)
151
+
152
+ Patch release — aligns example and skill install docs with the project's **`uv`** workflow. No parser or public API changes.
153
+
154
+ | Area | Change |
155
+ | :--- | :--- |
156
+ | **Examples** | `examples/run_demo.py` error hint uses **`uv sync --all-extras`**. |
157
+ | **Claude skill** | **`claude-skill-logseq-read/SKILL.md`** recommends **`uv pip install`**. |
158
+
159
+ ---
160
+
161
+ ## ⚡ Release highlights (v1.3.0)
162
+
163
+ Minor release — architectural quick wins, runtime robustness, and expanded public API. No breaking changes to default parser behavior.
164
+
165
+ | Area | Change |
166
+ | :--- | :--- |
167
+ | **Public API** | Root **`logseq_matryca_parser`** exports **`SynapseAdapter`**, **`SessionAliasRegistry`**, **`GraphVisualizer`**, **`discover_graph_files`**, and core LOGOS symbols via explicit **`__all__`**. |
168
+ | **Graph model** | **`LogseqGraph`** uses **`validate_assignment=True`** instead of frozen/`object.__setattr__` for incremental reloads. |
169
+ | **Live watcher** | **`start_watching()`** debounces filesystem events (~500ms) and ignores editor temp/swap files (`.swp`, `~`, `.tmp`, `.DS_Store`). |
170
+ | **Strict refs** | **`StackMachineParser(strict_refs=True)`** raises **`BlockReferenceError`** for unresolved same-page `((uuid))` refs (default off). |
171
+ | **SYNAPSE** | **`SynapseMetadata`** / **`build_synapse_metadata`** for vector-store-safe fields; **LlamaIndex** adds **`SOURCE`**, **`NEXT`**, **`PREVIOUS`** relationships. |
172
+ | **KINETIC CLI** | Global **`--verbose`** / **`--graph`** via **`@app.callback()`**; optional-dependency hints recommend **`uv sync --extra ai\|viz`**. |
173
+ | **LENS** | Lazy-imports NetworkX/PyVis so core installs stay lightweight. |
174
+ | **Security** | Transitive **`aiohttp`** / **`nltk`** constraints for optional **`[ai]`** extras. |
175
+
176
+ ---
177
+
150
178
  ## ⚡ Release highlights (v1.2.2)
151
179
 
152
180
  Patch release — fixes a failing CodeQL GitHub Actions workflow; **no parser or public API changes**.
@@ -236,7 +264,7 @@ matryca-parse export /path/to/logseq/graph /path/to/obsidian/vault --format obsi
236
264
  > **Note:** Wikilinks currently use the **Logseq page title** (e.g. `[[Target#^…]]`). Vault files may live under namespace folders (`Projects/AI/Demo.md`). Obsidian usually resolves unique titles; aligning link text to folder paths is a possible future refinement.
237
265
 
238
266
  ### Live incremental watcher
239
- `LogseqGraph` supports **surgical file invalidation** (optional dependency: `pip install 'logseq-matryca-parser[watch]'`). `start_watching()` runs a recursive **watchdog** observer: on `created` / `modified` under `pages/` or `journals/`, only that file is re-parsed; stale synthetic UUIDs are purged from `_node_registry` and scrubbed from `_backlink_registry`—no full-graph cold reload.
267
+ `LogseqGraph` supports **surgical file invalidation** (optional dependency: `uv sync --extra watch`). `start_watching()` runs a recursive **watchdog** observer with **~500ms debounce** and ignores editor temp/swap files: on `created` / `modified` under `pages/` or `journals/`, only that file is re-parsed; stale synthetic UUIDs are purged from `_node_registry` and scrubbed from `_backlink_registry`—no full-graph cold reload.
240
268
 
241
269
  ### Fluent topological queries
242
270
  Filter the global node registry with a **chainable** API (tags, task state, ancestry under a parent UUID):
@@ -315,12 +343,17 @@ Marker syntax (`[#A]`, `SCHEDULED: <...>`, `DEADLINE: <...>`) is stripped from `
315
343
  ## 🛠️ Quickstart
316
344
 
317
345
  ```bash
318
- # Install from PyPI (latest: v1.2.2)
319
- pip install logseq-matryca-parser
346
+ # Install from PyPI (latest: v1.3.1)
347
+ uv pip install logseq-matryca-parser
320
348
 
321
349
  # Optional: filesystem watcher for live incremental graph updates
322
- pip install 'logseq-matryca-parser[watch]'
350
+ uv pip install 'logseq-matryca-parser[watch]'
351
+
352
+ # Or clone and sync all extras locally
353
+ uv sync --all-extras
354
+ ```
323
355
 
356
+ ```bash
324
357
  # 1. Visualize your local graph (LENS)
325
358
  matryca-parse visualize /path/to/logseq/graph my-map.html
326
359
 
@@ -332,13 +365,23 @@ matryca-parse export /path/to/logseq/graph output --format langchain-enriched
332
365
 
333
366
  # 4. Obsidian vault (YAML frontmatter + ^ block ids)
334
367
  matryca-parse export /path/to/logseq/graph output --format obsidian
368
+
369
+ # Global options (all subcommands): --verbose, --graph /path/to/vault
370
+ matryca-parse --graph /path/to/logseq/graph --verbose export output --format json
335
371
  ```
336
372
 
337
373
  ### Python API
374
+
375
+ Prefer the package root for stable imports (see **`__all__`** in **`logseq_matryca_parser`**):
376
+
338
377
  ```python
339
- from logseq_matryca_parser.graph import LogseqGraph
340
- from logseq_matryca_parser.logos_parser import LogosParser
341
- from logseq_matryca_parser.synapse import SynapseAdapter
378
+ from logseq_matryca_parser import (
379
+ LogseqGraph,
380
+ LogosParser,
381
+ SynapseAdapter,
382
+ SessionAliasRegistry,
383
+ discover_graph_files,
384
+ )
342
385
 
343
386
  # Parse a single page to AST (YAML or native frontmatter; utf-8-sig BOM-safe)
344
387
  page = LogosParser().parse_page_file("page.md")
@@ -352,6 +395,11 @@ effective = graph.get_effective_properties(page_obj.root_nodes[0].uuid)
352
395
 
353
396
  # Export to LangChain with lineage metadata
354
397
  docs = SynapseAdapter.to_langchain_documents(page.root_nodes, source_name=page.title)
398
+
399
+ # Optional strict same-page block-ref validation at parse time
400
+ from logseq_matryca_parser import StackMachineParser
401
+
402
+ strict_page = StackMachineParser(strict_refs=True).parse_page_file("page.md")
355
403
  ```
356
404
 
357
405
  ### 🤖 Agentic Write Access (Append-Only)
@@ -12,7 +12,7 @@
12
12
  [![Status: Stable](https://img.shields.io/badge/Status-Stable-22c55e.svg?style=flat-square)](#)
13
13
  ![Origin: Matryca.ai](https://img.shields.io/badge/Origin-Matryca.ai-gold?style=for-the-badge)
14
14
 
15
- **v1.2.2** — CodeQL CI fix & docs (see [CHANGELOG](CHANGELOG.md)) — **234 tests**, no parser API changes; SAST via GitHub CodeQL **default setup** ([`docs/CODEQL.md`](docs/CODEQL.md)).
15
+ **v1.3.1** — Documentation patch: `uv` install hints in examples and Claude skill (see [CHANGELOG](CHANGELOG.md)) — **244 tests**, no parser or API changes.
16
16
 
17
17
  > *Turning a forest of local plain-text files into a unified semantic powerhouse.*
18
18
 
@@ -106,6 +106,34 @@ Logseq Matryca Parser is a deterministic **Stack-Machine engine** that acts as t
106
106
 
107
107
  ---
108
108
 
109
+ ## ⚡ Release highlights (v1.3.1)
110
+
111
+ Patch release — aligns example and skill install docs with the project's **`uv`** workflow. No parser or public API changes.
112
+
113
+ | Area | Change |
114
+ | :--- | :--- |
115
+ | **Examples** | `examples/run_demo.py` error hint uses **`uv sync --all-extras`**. |
116
+ | **Claude skill** | **`claude-skill-logseq-read/SKILL.md`** recommends **`uv pip install`**. |
117
+
118
+ ---
119
+
120
+ ## ⚡ Release highlights (v1.3.0)
121
+
122
+ Minor release — architectural quick wins, runtime robustness, and expanded public API. No breaking changes to default parser behavior.
123
+
124
+ | Area | Change |
125
+ | :--- | :--- |
126
+ | **Public API** | Root **`logseq_matryca_parser`** exports **`SynapseAdapter`**, **`SessionAliasRegistry`**, **`GraphVisualizer`**, **`discover_graph_files`**, and core LOGOS symbols via explicit **`__all__`**. |
127
+ | **Graph model** | **`LogseqGraph`** uses **`validate_assignment=True`** instead of frozen/`object.__setattr__` for incremental reloads. |
128
+ | **Live watcher** | **`start_watching()`** debounces filesystem events (~500ms) and ignores editor temp/swap files (`.swp`, `~`, `.tmp`, `.DS_Store`). |
129
+ | **Strict refs** | **`StackMachineParser(strict_refs=True)`** raises **`BlockReferenceError`** for unresolved same-page `((uuid))` refs (default off). |
130
+ | **SYNAPSE** | **`SynapseMetadata`** / **`build_synapse_metadata`** for vector-store-safe fields; **LlamaIndex** adds **`SOURCE`**, **`NEXT`**, **`PREVIOUS`** relationships. |
131
+ | **KINETIC CLI** | Global **`--verbose`** / **`--graph`** via **`@app.callback()`**; optional-dependency hints recommend **`uv sync --extra ai\|viz`**. |
132
+ | **LENS** | Lazy-imports NetworkX/PyVis so core installs stay lightweight. |
133
+ | **Security** | Transitive **`aiohttp`** / **`nltk`** constraints for optional **`[ai]`** extras. |
134
+
135
+ ---
136
+
109
137
  ## ⚡ Release highlights (v1.2.2)
110
138
 
111
139
  Patch release — fixes a failing CodeQL GitHub Actions workflow; **no parser or public API changes**.
@@ -195,7 +223,7 @@ matryca-parse export /path/to/logseq/graph /path/to/obsidian/vault --format obsi
195
223
  > **Note:** Wikilinks currently use the **Logseq page title** (e.g. `[[Target#^…]]`). Vault files may live under namespace folders (`Projects/AI/Demo.md`). Obsidian usually resolves unique titles; aligning link text to folder paths is a possible future refinement.
196
224
 
197
225
  ### Live incremental watcher
198
- `LogseqGraph` supports **surgical file invalidation** (optional dependency: `pip install 'logseq-matryca-parser[watch]'`). `start_watching()` runs a recursive **watchdog** observer: on `created` / `modified` under `pages/` or `journals/`, only that file is re-parsed; stale synthetic UUIDs are purged from `_node_registry` and scrubbed from `_backlink_registry`—no full-graph cold reload.
226
+ `LogseqGraph` supports **surgical file invalidation** (optional dependency: `uv sync --extra watch`). `start_watching()` runs a recursive **watchdog** observer with **~500ms debounce** and ignores editor temp/swap files: on `created` / `modified` under `pages/` or `journals/`, only that file is re-parsed; stale synthetic UUIDs are purged from `_node_registry` and scrubbed from `_backlink_registry`—no full-graph cold reload.
199
227
 
200
228
  ### Fluent topological queries
201
229
  Filter the global node registry with a **chainable** API (tags, task state, ancestry under a parent UUID):
@@ -274,12 +302,17 @@ Marker syntax (`[#A]`, `SCHEDULED: <...>`, `DEADLINE: <...>`) is stripped from `
274
302
  ## 🛠️ Quickstart
275
303
 
276
304
  ```bash
277
- # Install from PyPI (latest: v1.2.2)
278
- pip install logseq-matryca-parser
305
+ # Install from PyPI (latest: v1.3.1)
306
+ uv pip install logseq-matryca-parser
279
307
 
280
308
  # Optional: filesystem watcher for live incremental graph updates
281
- pip install 'logseq-matryca-parser[watch]'
309
+ uv pip install 'logseq-matryca-parser[watch]'
310
+
311
+ # Or clone and sync all extras locally
312
+ uv sync --all-extras
313
+ ```
282
314
 
315
+ ```bash
283
316
  # 1. Visualize your local graph (LENS)
284
317
  matryca-parse visualize /path/to/logseq/graph my-map.html
285
318
 
@@ -291,13 +324,23 @@ matryca-parse export /path/to/logseq/graph output --format langchain-enriched
291
324
 
292
325
  # 4. Obsidian vault (YAML frontmatter + ^ block ids)
293
326
  matryca-parse export /path/to/logseq/graph output --format obsidian
327
+
328
+ # Global options (all subcommands): --verbose, --graph /path/to/vault
329
+ matryca-parse --graph /path/to/logseq/graph --verbose export output --format json
294
330
  ```
295
331
 
296
332
  ### Python API
333
+
334
+ Prefer the package root for stable imports (see **`__all__`** in **`logseq_matryca_parser`**):
335
+
297
336
  ```python
298
- from logseq_matryca_parser.graph import LogseqGraph
299
- from logseq_matryca_parser.logos_parser import LogosParser
300
- from logseq_matryca_parser.synapse import SynapseAdapter
337
+ from logseq_matryca_parser import (
338
+ LogseqGraph,
339
+ LogosParser,
340
+ SynapseAdapter,
341
+ SessionAliasRegistry,
342
+ discover_graph_files,
343
+ )
301
344
 
302
345
  # Parse a single page to AST (YAML or native frontmatter; utf-8-sig BOM-safe)
303
346
  page = LogosParser().parse_page_file("page.md")
@@ -311,6 +354,11 @@ effective = graph.get_effective_properties(page_obj.root_nodes[0].uuid)
311
354
 
312
355
  # Export to LangChain with lineage metadata
313
356
  docs = SynapseAdapter.to_langchain_documents(page.root_nodes, source_name=page.title)
357
+
358
+ # Optional strict same-page block-ref validation at parse time
359
+ from logseq_matryca_parser import StackMachineParser
360
+
361
+ strict_page = StackMachineParser(strict_refs=True).parse_page_file("page.md")
314
362
  ```
315
363
 
316
364
  ### 🤖 Agentic Write Access (Append-Only)
@@ -6,7 +6,7 @@ Security fixes are provided **only for the latest released version** on [PyPI](h
6
6
 
7
7
  | Version | Supported |
8
8
  | ------- | --------- |
9
- | **1.2.2** (latest) | Yes |
9
+ | **1.3.1** (latest) | Yes |
10
10
  | Older releases | No |
11
11
 
12
12
  We recommend always running the current release and upgrading promptly when a security advisory is published.
@@ -79,5 +79,5 @@ Lo script installa `logseq-matryca-parser` automaticamente se mancante.
79
79
  In caso di errore di installazione, esegui manualmente:
80
80
 
81
81
  ```bash
82
- pip install logseq-matryca-parser
82
+ uv pip install logseq-matryca-parser
83
83
  ```
@@ -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` / `agent-write` (X-Ray + headless splice), weekly append (`append`).")
85
+ Container(kinetic, "KINETIC", "Typer / Rich CLI", "CLI — global `--verbose` / `--graph` callback; 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,7 +258,9 @@ classDiagram
258
258
 
259
259
  - **LangChain.** [`LangChainVisitor`](../src/logseq_matryca_parser/synapse.py) emits one **`Document`** per node with `page_content=node.clean_text` and metadata unioning **`node.properties`** with lineage fields (`uuid`, `parent_id`, `indent_level`, `source`, **`path`** — the UUID ancestry chain — `left_id`, `refs`, `task_status`, repeater, `created_at`). The underlying **`LogseqNode`** additionally carries **`task_priority`**, **`scheduled_at`**, and **`deadline_at`** (§3.1); adapters or custom visitors can project those into metadata when feeding **downstream graph databases** or **GraphRAG** filters. This preserves **parent context** explicitly in retrieval filters and re-ranking.
260
260
 
261
- - **LlamaIndex.** [`LlamaIndexVisitor`](../src/logseq_matryca_parser/synapse.py) constructs **`TextNode`** instances keyed by **`id_=node.uuid`**. It wires **`NodeRelationship.PARENT`** and **`CHILD`** via **`RelatedNodeInfo`**, back-linking when the parent appears earlier in preorder traversal — encoding **topology as first-class edges** beyond flat metadata dictionaries.
261
+ - **LlamaIndex.** [`LlamaIndexVisitor`](../src/logseq_matryca_parser/synapse.py) constructs **`TextNode`** instances keyed by **`id_=node.uuid`**. It wires **`NodeRelationship.PARENT`** and **`CHILD`** via **`RelatedNodeInfo`**, back-linking when the parent appears earlier in preorder traversal — encoding **topology as first-class edges** beyond flat metadata dictionaries. From **v1.3.0**, it also emits **`SOURCE`** (page-level anchor via **`page_source_node_id`**), **`NEXT`**, and **`PREVIOUS`** sibling edges for spatial traversal in vector stores.
262
+
263
+ - **Vector-store metadata.** **`SynapseMetadata`** and **`build_synapse_metadata`** project **`task_priority`**, temporal epoch fields, **`source_uuid`**, and joined **`path`** / **`refs`** strings into LangChain/LlamaIndex metadata without leaking raw Python list reprs.
262
264
 
263
265
  Together, adapters guarantee that **embedding units align with intentional block boundaries**, not splitter accidents.
264
266
 
@@ -276,7 +278,7 @@ The KINETIC **`export --format langchain-enriched`** path serializes these docum
276
278
 
277
279
  ### 3.3 LENS — NetworkX topology + PyVis interactive visualization
278
280
 
279
- **LENS** (`logseq_matryca_parser.lens.GraphVisualizer`) builds a **`networkx.Graph`** over **page ⇄ wiki/tag reference** projections using `NetworkXVisitor` during AST preorder walks. Nodes receive **degree-based sizing** (“sun” hotspots) and subgroup classification (`page`, `tag`, `journal`, etc.).
281
+ **LENS** (`logseq_matryca_parser.lens.GraphVisualizer`) builds a **`networkx.Graph`** over **page ⇄ wiki/tag reference** projections using `NetworkXVisitor` during AST preorder walks. Nodes receive **degree-based sizing** (“sun” hotspots) and subgroup classification (`page`, `tag`, `journal`, etc.). **NetworkX** and **PyVis** are **lazy-imported** (optional **`[viz]`** extra) so core installs avoid pulling visualization dependencies until `GraphVisualizer` is used.
280
282
 
281
283
  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**).
282
284
 
@@ -296,14 +298,14 @@ Both paths keep **existing topology intact** relative to their contract: append-
296
298
 
297
299
  ### 3.6 `LogseqGraph` — namespace scoping, O(1) invalidation, live watch
298
300
 
299
- The **in-memory graph** ([`graph.py`](../src/logseq_matryca_parser/graph.py)) is the runtime **RAM image** of the sovereign vault: `pages: dict[str, LogseqPage]`, a private **`_node_registry`** keyed by synthetic block UUID, and a **`_backlink_registry`** mapping normalized link targets to source node UUIDs.
301
+ The **in-memory graph** ([`graph.py`](../src/logseq_matryca_parser/graph.py)) is the runtime **RAM image** of the sovereign vault: `pages: dict[str, LogseqPage]`, a private **`_node_registry`** keyed by synthetic block UUID, and a **`_backlink_registry`** mapping normalized link targets to source node UUIDs. **`LogseqGraph`** uses **`ConfigDict(strict=True, validate_assignment=True)`** (not frozen) so **`invalidate_and_reload_page`** can mutate registries and page maps without `object.__setattr__` workarounds.
300
302
 
301
303
  #### Page title overrides and alias indexing (`_enrich_pages_index`)
302
304
 
303
305
  After every bulk or incremental parse, the graph applies a **post-parse enrichment pass** before backlink construction:
304
306
 
305
307
  1. **Filename → canonical title.** Each markdown file is first keyed by **`derive_page_title_from_source_path`** (see §3.9).
306
- 2. **`title::` override.** If page frontmatter contains a non-empty string **`title`**, the frozen `LogseqPage` is updated via **`model_copy(update={"title": custom})`**, the old filename key is removed from **`pages`**, and the page is re-inserted under the custom title (collision with another file’s title is skipped with a debug log).
308
+ 2. **`title::` override.** If page frontmatter contains a non-empty string **`title`**, the `LogseqPage` is updated via **`model_copy(update={"title": custom})`**, the old filename key is removed from **`pages`**, and the page is re-inserted under the custom title (collision with another file’s title is skipped with a debug log).
307
309
  3. **Alias injection.** For each canonical dict entry where **`dict_key == page.title`**, values from **`alias::`** and **`aliases::`** are normalized (comma-separated strings or Python lists; `[[Page]]` / `#tag` adornments stripped using the same rules as [`logseq_markdown.py`](../src/logseq_matryca_parser/logseq_markdown.py)) and registered as **additional keys** pointing at the **same `LogseqPage` instance** — e.g. `pages["Dev"]` and `pages["Development"]` share identity.
308
310
  4. **Backlinks.** **`_build_backlink_registry`** walks **unique pages** (`id(page)` deduplication) so alias keys do not double-count outgoing links. Incoming wikilinks such as **`[[Dev]]`** normalize to lowercase registry keys and resolve through **`get_backlinks("Dev")`** like any other page title.
309
311
 
@@ -341,7 +343,11 @@ This keeps **global indexes consistent** without rebuilding the entire graph —
341
343
 
342
344
  #### Live filesystem watcher (`start_watching`)
343
345
 
344
- **`LogseqGraph.start_watching(callback=None)`** (optional **`watchdog`** install) returns a **`LogseqGraphWatcher`** that schedules a recursive **`Observer`** on the graph root. **`on_modified` / `on_created`** events for tracked Markdown call **`invalidate_and_reload_page`**, then optionally invoke **`callback(path)`** — the intended hook for **vector store patch**, **re-embedding**, or UI refresh. Event routing ignores directories and non-tracked extensions so the hot path stays tight.
346
+ **`LogseqGraph.start_watching(callback=None, debounce_seconds=0.5)`** (optional **`watchdog`** install) returns a **`LogseqGraphWatcher`** that schedules a recursive **`Observer`** on the graph root. **`on_modified` / `on_created`** events for tracked Markdown call **`invalidate_and_reload_page`**, then optionally invoke **`callback(path)`** — the intended hook for **vector store patch**, **re-embedding**, or UI refresh. **`_DebouncedGraphEventRouter`** coalesces rapid save bursts (~500ms default) and ignores editor temp/swap artifacts (`.swp`, `~`, `.tmp`, `.DS_Store`). Event routing ignores directories and non-tracked extensions so the hot path stays tight.
347
+
348
+ #### Parse-time reference validation (`strict_refs`)
349
+
350
+ **`StackMachineParser(..., strict_refs=False)`** (default) resolves same-page `((uuid))` block refs leniently. When **`strict_refs=True`**, unresolved refs raise **`BlockReferenceError`** at parse time — complementary to **`LogseqGraph.get_broken_references()`**, which scans the loaded graph post-hoc.
345
351
 
346
352
  #### Fluent topological queries (`GraphQuery`)
347
353
 
@@ -404,6 +410,8 @@ The compound CLI commands **`agent_read`** and **`agent_write`** in [`kinetic.py
404
410
 
405
411
  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.
406
412
 
413
+ **Global CLI options (v1.3.0).** [`kinetic.py`](../src/logseq_matryca_parser/kinetic.py) registers **`@app.callback()`** with **`--verbose`** and **`--graph`** so every subcommand shares graph-path resolution and debug logging. Optional extras (`[ai]`, `[viz]`) print **`uv sync --extra …`** hints on import failure.
414
+
407
415
  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**.
408
416
 
409
417
  ### 3.8 Bidirectional I/O and Logseq Layouts
@@ -459,7 +467,7 @@ Logseq namespaces use **`/`** in titles (e.g. `Projects/AI`). On disk, each segm
459
467
 
460
468
  #### Graph discovery filters
461
469
 
462
- When scanning a vault root, **`is_excluded_graph_path`** drops noise directories — notably **`.recycle`**, **`.git`**, and the internal **`logseq`** config tree — so incremental watchers and bulk loaders never ingest backup blobs or VCS metadata as pages. This keeps **`LogseqGraph.load_directory`** and **`invalidate_and_reload_page`** focused on sovereign content under `pages/` and `journals/`.
470
+ When scanning a vault root, **`discover_graph_files`** (in [`logseq_paths.py`](../src/logseq_matryca_parser/logseq_paths.py), shared by **`LogseqGraph.load_directory`** and **KINETIC**) enumerates `pages/` and `journals/` markdown. **`is_excluded_graph_path`** drops noise directories — notably **`.recycle`**, **`.git`**, and the internal **`logseq`** config tree — so incremental watchers and bulk loaders never ingest backup blobs or VCS metadata as pages. This keeps **`LogseqGraph.load_directory`** and **`invalidate_and_reload_page`** focused on sovereign content under `pages/` and `journals/`.
463
471
 
464
472
  ---
465
473
 
@@ -528,4 +536,4 @@ Recursive and character-budget chunkers assume **approximately flat prose**. Log
528
536
 
529
537
  ---
530
538
 
531
- *This document reflects the implementations in `src/logseq_matryca_parser/logos_parser.py`, `synapse.py`, `graph.py`, `forge.py`, `lens.py`, `logos_core.py`, `agent_writer.py`, `agent_press.py`, `logseq_markdown.py`, and `logseq_paths.py`, and complements narrative primers such as [`logseq_ast_primer.md`](logseq_ast_primer.md).*
539
+ *This document reflects the implementations in `src/logseq_matryca_parser/logos_parser.py`, `synapse.py`, `graph.py`, `forge.py`, `lens.py`, `logos_core.py`, `agent_writer.py`, `agent_press.py`, `logseq_markdown.py`, `logseq_paths.py`, `kinetic.py`, and the public exports in `__init__.py`, and complements narrative primers such as [`logseq_ast_primer.md`](logseq_ast_primer.md).*
@@ -1,6 +1,6 @@
1
1
  # CodeQL code scanning
2
2
 
3
- **Logseq Matryca Parser** (v1.2.2+) uses **GitHub CodeQL default setup** for static analysis (SAST) on Python.
3
+ **Logseq Matryca Parser** (v1.3.1+) uses **GitHub CodeQL default setup** for static analysis (SAST) on Python.
4
4
 
5
5
  ## Why there is no `codeql.yml` workflow
6
6
 
@@ -214,4 +214,4 @@ If you feed Logseq Markdown into `RecursiveCharacterTextSplitter` (LangChain) or
214
214
 
215
215
  The **Logos Protocol** solves this by walking the AST deterministically, isolating properties, shielding dead-zone literals, and using the `SYNAPSE` adapter to export native LangChain `Document` or LlamaIndex `TextNode` objects. Every generated object retains its exact hierarchical lineage in the metadata, feeding your local LLM perfectly structured data.
216
216
 
217
- For vault-wide navigation (aliases, backlinks, namespace shadowing, assets), load the graph with **`LogseqGraph`** — see the [README](../README.md) and [CHANGELOG](../CHANGELOG.md) (graph parity from **v1.2.0**; **v1.2.1** adds CI/OSS hardening; **v1.2.2** fixes CodeQL CI and documents default setup).
217
+ For vault-wide navigation (aliases, backlinks, namespace shadowing, assets), load the graph with **`LogseqGraph`** — see the [README](../README.md) and [CHANGELOG](../CHANGELOG.md) (graph parity from **v1.2.0**; **v1.3.0** adds watcher debounce, `strict_refs`, public API exports, and LlamaIndex spatial relationships).
@@ -1,5 +1,7 @@
1
1
  # 📜 Architectural Contract: Live Incremental Invalidation & File Watcher
2
2
  **Contract Status:** Wave 7 — Implemented (incremental invalidation + lazy watchdog watcher)
3
+
4
+ > **Implementation note (v1.3.0):** `LogseqGraph` now uses `validate_assignment=True` (not `frozen=True`); the watcher debounces events (~500ms) and ignores editor temp files. Historical spec text below describes the original contract.
3
5
  **Target Stack:** Python 3.12+ | Pydantic V2 | Watchdog (Optional/Lazy Dependency)
4
6
  **Inspiration Architectures:**
5
7
  - `Microsoft/language-server-protocol` (Incremental text document synchronization and dependency invalidation)
@@ -1,5 +1,7 @@
1
1
  # 📜 Architectural Contract: Synthetic UUID Hardening & Graph Orchestration Module
2
2
  **Contract Status:** Completed (Autonomous Execution)
3
+
4
+ > **Implementation note (v1.3.0):** `discover_graph_files` lives in `logseq_paths.py` (not `kinetic.py`); `LogseqGraph` uses `validate_assignment=True` instead of `frozen=True`. Historical spec text below describes the original contract.
3
5
  **Target Stack:** Python 3.12+ | Pydantic V2 (Strict/Frozen Models) | Local-First No-DB
4
6
 
5
7
  **Execution checklist**
@@ -11,12 +11,13 @@ root_dir = Path(__file__).parent.parent
11
11
  sys.path.append(str(root_dir / "src"))
12
12
 
13
13
  try:
14
- from logseq_matryca_parser.logos_parser import LogosParser
15
- from logseq_matryca_parser.forge import ForgeExporter
16
14
  from rich.console import Console
17
15
  from rich.panel import Panel
16
+
17
+ from logseq_matryca_parser.forge import ForgeExporter
18
+ from logseq_matryca_parser.logos_parser import LogosParser
18
19
  except ImportError as e:
19
- print(f"Errore: Assicurati di aver installato le dipendenze (pip install rich typer pydantic). {e}")
20
+ print(f"Errore: Assicurati di aver installato le dipendenze (uv sync --all-extras). {e}")
20
21
  sys.exit(1)
21
22
 
22
23
  console = Console()
@@ -5,10 +5,9 @@ import re
5
5
  import shutil
6
6
  import urllib.request
7
7
  from datetime import datetime
8
- from typing import Any, Dict, Literal, TypeVar
8
+ from typing import Any, Literal, TypeVar
9
9
 
10
10
  from pydantic import BaseModel, ValidationError
11
-
12
11
  from smart_router.core.ingestion_engine import IngestionEngine
13
12
  from smart_router.core.librarian_models import (
14
13
  EntityNodeSchema,
@@ -31,7 +30,7 @@ async def emit_note_package(
31
30
  slug: str,
32
31
  content: str,
33
32
  ontology_class: NodeType,
34
- metadata: Dict[str, str],
33
+ metadata: dict[str, str],
35
34
  indentation_level: int,
36
35
  ) -> None:
37
36
  package = SovereignNotePackage(
@@ -90,9 +89,7 @@ class LogseqASTParser:
90
89
  trees.append("\n".join(current_tree))
91
90
  current_tree = [line]
92
91
  else:
93
- if current_tree:
94
- current_tree.append(line)
95
- elif line.strip():
92
+ if current_tree or line.strip():
96
93
  current_tree.append(line)
97
94
  if current_tree:
98
95
  trees.append("\n".join(current_tree))
@@ -122,7 +119,7 @@ T = TypeVar("T", bound=BaseModel)
122
119
  def call_local_llm(
123
120
  system_prompt: str, user_content: str, response_model: type[T]
124
121
  ) -> T | None:
125
- payload: Dict[str, Any] = {
122
+ payload: dict[str, Any] = {
126
123
  "model": "local-model",
127
124
  "messages": [
128
125
  {"role": "system", "content": system_prompt},
@@ -204,7 +201,7 @@ async def main() -> None:
204
201
  if filename.startswith("."):
205
202
  continue
206
203
  filepath = os.path.join(INBOX_DIR, filename)
207
- with open(filepath, "r", encoding="utf-8") as f:
204
+ with open(filepath, encoding="utf-8") as f:
208
205
  global_skeleton = f.read()
209
206
  macro_buckets = LogseqASTParser.chunk_into_buckets(
210
207
  global_skeleton, max_chars=15000
@@ -247,7 +244,7 @@ async def main() -> None:
247
244
  if not note_filename.endswith(".md"):
248
245
  note_filename += ".md"
249
246
  try:
250
- metadata: Dict[str, str] = {
247
+ metadata: dict[str, str] = {
251
248
  "source_filename": filename,
252
249
  "confidence": str(extracted_base.confidence),
253
250
  "extracted_at": datetime.now().isoformat(),
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "logseq-matryca-parser"
7
- version = "1.2.2"
7
+ version = "1.3.1"
8
8
  description = "The Logos Protocol: Deterministic Logseq AST parsing for Matryca.ai."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -76,6 +76,14 @@ dev = [
76
76
  "ruff>=0.15.12",
77
77
  ]
78
78
 
79
+ [tool.uv]
80
+ constraint-dependencies = [
81
+ "aiohttp>=3.14.1",
82
+ ]
83
+ override-dependencies = [
84
+ "nltk @ git+https://github.com/nltk/nltk@v3.10.0-rc1",
85
+ ]
86
+
79
87
  [tool.pytest.ini_options]
80
88
  testpaths = ["tests"]
81
89
 
@@ -95,3 +103,16 @@ module = [
95
103
  "watchdog.*",
96
104
  ]
97
105
  ignore_missing_imports = true
106
+
107
+ [tool.ruff]
108
+ target-version = "py312"
109
+ line-length = 100
110
+ exclude = ["legacy", "examples", "scripts"]
111
+
112
+ [tool.ruff.lint]
113
+ select = ["E", "F", "I", "UP", "B", "SIM"]
114
+ ignore = ["E501"]
115
+
116
+ [tool.ruff.lint.per-file-ignores]
117
+ "src/logseq_matryca_parser/kinetic.py" = ["B008"]
118
+ "tests/**" = ["SIM117"]
@@ -4,8 +4,9 @@ from __future__ import annotations
4
4
 
5
5
  import sys
6
6
 
7
- __version__ = "1.2.2"
7
+ __version__ = "1.3.1"
8
8
 
9
+ from .agent_press import SessionAliasRegistry
9
10
  from .agent_writer import LogseqConfigReader, logseq_agent_write
10
11
  from .exceptions import BlockReferenceError, LogseqIndentationError, LogseqParserError
11
12
  from .forge import (
@@ -16,7 +17,15 @@ from .forge import (
16
17
  ObsidianForgeVisitor,
17
18
  )
18
19
  from .graph import LogseqGraph
19
- from .logos_core import ASTVisitor, LogseqNode, LogseqPage, LogosNode, SovereignNotePackage
20
+ from .logos_core import ASTVisitor, LogosNode, LogseqNode, LogseqPage, SovereignNotePackage
21
+ from .logos_parser import (
22
+ LOGSEQ_PATTERNS,
23
+ LogosParser,
24
+ PageRegistry,
25
+ StackMachineParser,
26
+ clean_node_content,
27
+ is_system_block,
28
+ )
20
29
  from .logseq_markdown import (
21
30
  format_logseq_block_property_lines,
22
31
  format_logseq_page_properties,
@@ -26,12 +35,19 @@ from .logseq_markdown import (
26
35
  from .logseq_paths import (
27
36
  decode_page_title_segment,
28
37
  derive_page_title_from_source_path,
38
+ discover_graph_files,
29
39
  encode_page_title_segment,
30
40
  filename_to_page_title,
31
41
  is_excluded_graph_path,
32
42
  page_title_to_filename,
33
43
  page_title_to_relative_path,
34
44
  )
45
+ from .synapse import SynapseAdapter, page_source_node_id
46
+
47
+ try:
48
+ from .lens import GraphVisualizer
49
+ except ImportError: # optional [viz] extra (networkx / pyvis)
50
+ GraphVisualizer = None # type: ignore[misc, assignment]
35
51
 
36
52
 
37
53
  def ensure_aot_compatibility() -> None:
@@ -46,6 +62,7 @@ __all__ = [
46
62
  "BlockReferenceError",
47
63
  "FlatListForgeVisitor",
48
64
  "ForgeExporter",
65
+ "GraphVisualizer",
49
66
  "JSONForgeVisitor",
50
67
  "LOGSEQ_PATTERNS",
51
68
  "LogosNode",
@@ -56,22 +73,26 @@ __all__ = [
56
73
  "LogseqNode",
57
74
  "LogseqPage",
58
75
  "LogseqParserError",
76
+ "MarkdownForgeVisitor",
77
+ "ObsidianForgeVisitor",
59
78
  "PageRegistry",
79
+ "SessionAliasRegistry",
60
80
  "SovereignNotePackage",
61
81
  "StackMachineParser",
82
+ "SynapseAdapter",
62
83
  "clean_node_content",
63
- "ensure_aot_compatibility",
64
84
  "decode_page_title_segment",
65
85
  "derive_page_title_from_source_path",
86
+ "discover_graph_files",
66
87
  "encode_page_title_segment",
88
+ "ensure_aot_compatibility",
67
89
  "filename_to_page_title",
68
90
  "format_logseq_block_property_lines",
69
91
  "format_logseq_page_properties",
70
92
  "is_excluded_graph_path",
71
93
  "is_system_block",
72
94
  "logseq_agent_write",
73
- "MarkdownForgeVisitor",
74
- "ObsidianForgeVisitor",
95
+ "page_source_node_id",
75
96
  "page_title_to_filename",
76
97
  "page_title_to_relative_path",
77
98
  "serialize_logseq_page",
@@ -179,10 +179,7 @@ def _replace_block_refs_in_text(
179
179
 
180
180
  def _obsidian_line_source(node: LogseqNode) -> str:
181
181
  """Prefer the first line of ``content`` so ``((uuid))`` survives when stripped from ``clean_text``."""
182
- if node.content:
183
- first = node.content.split("\n", 1)[0]
184
- else:
185
- first = node.clean_text
182
+ first = node.content.split("\n", 1)[0] if node.content else node.clean_text
186
183
  stripped = LOGSEQ_PATTERNS["inline_uuid_prop"].sub("", first)
187
184
  return stripped.replace("\n", " ").strip()
188
185