lorekeep 0.2.0__tar.gz → 0.3.0__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 (126) hide show
  1. lorekeep-0.3.0/.release-please-manifest.json +3 -0
  2. {lorekeep-0.2.0 → lorekeep-0.3.0}/AGENTS.md +5 -5
  3. {lorekeep-0.2.0 → lorekeep-0.3.0}/CHANGELOG.md +20 -0
  4. {lorekeep-0.2.0 → lorekeep-0.3.0}/PKG-INFO +19 -19
  5. {lorekeep-0.2.0 → lorekeep-0.3.0}/README.md +18 -18
  6. {lorekeep-0.2.0 → lorekeep-0.3.0}/SECURITY.md +6 -4
  7. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/architecture/data-model.md +5 -5
  8. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/architecture/journal.md +0 -2
  9. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/architecture/overview.md +2 -2
  10. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/architecture/pipeline.md +2 -4
  11. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/architecture/serve-mcp.md +3 -5
  12. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/guides/compile.md +8 -10
  13. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/guides/getting-started.md +4 -2
  14. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/guides/serve.md +6 -7
  15. {lorekeep-0.2.0 → lorekeep-0.3.0}/pyproject.toml +1 -1
  16. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/__init__.py +1 -1
  17. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/cli.py +143 -55
  18. lorekeep-0.3.0/tests/test_init_chain.py +178 -0
  19. lorekeep-0.3.0/tests/test_mcp_write_tools.py +170 -0
  20. lorekeep-0.3.0/tests/test_merge_journals.py +173 -0
  21. lorekeep-0.3.0/tests/test_watch_e2e.py +202 -0
  22. {lorekeep-0.2.0 → lorekeep-0.3.0}/uv.lock +1 -1
  23. lorekeep-0.2.0/.release-please-manifest.json +0 -3
  24. {lorekeep-0.2.0 → lorekeep-0.3.0}/.commitlintrc.json +0 -0
  25. {lorekeep-0.2.0 → lorekeep-0.3.0}/.github/workflows/auto-merge-release-please.yml +0 -0
  26. {lorekeep-0.2.0 → lorekeep-0.3.0}/.github/workflows/ci.yml +0 -0
  27. {lorekeep-0.2.0 → lorekeep-0.3.0}/.github/workflows/lint-commits.yml +0 -0
  28. {lorekeep-0.2.0 → lorekeep-0.3.0}/.github/workflows/release-please.yml +0 -0
  29. {lorekeep-0.2.0 → lorekeep-0.3.0}/.gitignore +0 -0
  30. {lorekeep-0.2.0 → lorekeep-0.3.0}/.lorekeep/config.yaml.example +0 -0
  31. {lorekeep-0.2.0 → lorekeep-0.3.0}/.lorekeep/schema.json +0 -0
  32. {lorekeep-0.2.0 → lorekeep-0.3.0}/.pre-commit-config.yaml +0 -0
  33. {lorekeep-0.2.0 → lorekeep-0.3.0}/CLAUDE.md +0 -0
  34. {lorekeep-0.2.0 → lorekeep-0.3.0}/LICENSE +0 -0
  35. {lorekeep-0.2.0 → lorekeep-0.3.0}/cover.jpeg +0 -0
  36. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/README.md +0 -0
  37. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/architecture/agent.md +0 -0
  38. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/architecture/evaluation.md +0 -0
  39. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/architecture/permission.md +0 -0
  40. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/architecture/temporal.md +0 -0
  41. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/guides/backup.md +0 -0
  42. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/guides/data-home.md +0 -0
  43. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/guides/import.md +0 -0
  44. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/superpowers/plans/2026-06-26-lorekeep-dotdir-backup.md +0 -0
  45. {lorekeep-0.2.0 → lorekeep-0.3.0}/docs/superpowers/specs/2026-06-26-lorekeep-dotdir-layout-design.md +0 -0
  46. {lorekeep-0.2.0 → lorekeep-0.3.0}/release-please-config.json +0 -0
  47. {lorekeep-0.2.0 → lorekeep-0.3.0}/scripts/check-conventional-commit.py +0 -0
  48. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/agent.py +0 -0
  49. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/backup.py +0 -0
  50. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/compile/__init__.py +0 -0
  51. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/compile/extract.py +0 -0
  52. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/compile/ingest.py +0 -0
  53. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/compile/providers.py +0 -0
  54. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/compile/resolve.py +0 -0
  55. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/compile/writer.py +0 -0
  56. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/config.py +0 -0
  57. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/defaults.py +0 -0
  58. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/eval/__init__.py +0 -0
  59. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/eval/construction.py +0 -0
  60. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/eval/gold.py +0 -0
  61. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/eval/retrieval.py +0 -0
  62. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/facts_io.py +0 -0
  63. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/importer/__init__.py +0 -0
  64. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/importer/claude.py +0 -0
  65. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/importer/cursor.py +0 -0
  66. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/integrations/__init__.py +0 -0
  67. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/integrations/claude_code.py +0 -0
  68. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/integrations/codex.py +0 -0
  69. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/integrations/common.py +0 -0
  70. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/integrations/cursor.py +0 -0
  71. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/integrations/detect.py +0 -0
  72. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/integrations/opencode.py +0 -0
  73. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/journal.py +0 -0
  74. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/mcp_server.py +0 -0
  75. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/models.py +0 -0
  76. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/paths.py +0 -0
  77. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/perm/__init__.py +0 -0
  78. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/perm/ns.py +0 -0
  79. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/pipeline.py +0 -0
  80. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/schema_io.py +0 -0
  81. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/store/__init__.py +0 -0
  82. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/store/fts.py +0 -0
  83. {lorekeep-0.2.0 → lorekeep-0.3.0}/src/lorekeep/store/graph.py +0 -0
  84. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/conftest.py +0 -0
  85. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/fixtures/claude-session/memory/MEMORY.md +0 -0
  86. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/fixtures/claude-session/memory/lorekeep-design.md +0 -0
  87. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/fixtures/claude-session/memory/lorekeep-project-state.md +0 -0
  88. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/fixtures/claude-session/test.jsonl +0 -0
  89. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/fixtures/gold/payments.facts.jsonl +0 -0
  90. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/fixtures/raw/backend/payments.md +0 -0
  91. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/fixtures/retrieval/questions.json +0 -0
  92. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/fixtures/schema.json +0 -0
  93. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_agent_cli.py +0 -0
  94. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_agent_detect.py +0 -0
  95. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_backup.py +0 -0
  96. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_backup_cli.py +0 -0
  97. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_compile_cli.py +0 -0
  98. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_config.py +0 -0
  99. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_construction_eval.py +0 -0
  100. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_defaults.py +0 -0
  101. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_determinism.py +0 -0
  102. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_doctor_cli.py +0 -0
  103. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_eval_cli.py +0 -0
  104. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_extract.py +0 -0
  105. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_fts.py +0 -0
  106. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_graph_store.py +0 -0
  107. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_import_claude.py +0 -0
  108. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_import_cursor.py +0 -0
  109. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_ingest.py +0 -0
  110. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_init_cli.py +0 -0
  111. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_integrations.py +0 -0
  112. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_mcp_add_cli.py +0 -0
  113. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_mcp_reload.py +0 -0
  114. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_mcp_server.py +0 -0
  115. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_models.py +0 -0
  116. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_paths.py +0 -0
  117. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_perm.py +0 -0
  118. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_pipeline.py +0 -0
  119. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_providers.py +0 -0
  120. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_resolve.py +0 -0
  121. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_retrieval_eval.py +0 -0
  122. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_schema_io.py +0 -0
  123. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_serve_cli.py +0 -0
  124. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_smoke.py +0 -0
  125. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_watch_sessions.py +0 -0
  126. {lorekeep-0.2.0 → lorekeep-0.3.0}/tests/test_writer.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.3.0"
3
+ }
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
4
4
 
5
5
  ## What this is
6
6
 
7
- Lorekeep compiles a team's raw markdown docs into a **temporal knowledge graph** (`facts.jsonl`) and exposes it **read-only** to coding agents (Claude Code, Cursor, Codex) over MCP, with per-namespace permission. The defining constraint: **there is no runtime write path.** A curator compiles offline; agents only read. Knowledge is processed once at compile time, not re-RAG'd per query.
7
+ Lorekeep compiles a team's raw markdown docs into a **temporal knowledge graph** (`facts.jsonl`) and exposes it to coding agents (Claude Code, Cursor, Codex, opencode) over MCP, with per-namespace permission. Agents read facts through 8 read tools and propose new facts through 5 journal-based write tools (confidence-gated, merged on resolve). Knowledge is processed once at compile time, not re-RAG'd per query.
8
8
 
9
9
  ## Commands
10
10
 
@@ -28,8 +28,8 @@ uv run lorekeep <command> # run the CLI in dev mode
28
28
  | `compile` | `raw/*.md` → `graph/facts.jsonl` + `manifest.json` (runs the LLM pipeline) |
29
29
  | `check` | Validate compiled graph loads, no dangling edges (exit 1 on failure) |
30
30
  | `eval` | Tier-1 construction P/R/F1 vs gold corpus + structure metrics |
31
- | `serve [--transport stdio\|http]` | Run the read-only MCP server |
32
- | `mcp add --agent claude\|cursor\|codex --ns NS` | Write agent MCP config (`.mcp.json`) |
31
+ | `serve [--transport stdio\|http]` | Run the MCP server (8 read + 5 write tools) |
32
+ | `mcp add --agent claude\|cursor\|codex\|opencode --ns NS` | Write agent MCP config |
33
33
  | `import --from claude\|cursor` | Import agent sessions into `raw/` (claude: quick+deep; cursor: deep-only) |
34
34
  | `doctor` | Verify install: graph loads, schema valid, a tool responds |
35
35
  | `backup [--init <remote-url>]` | Commit + push `.lorekeep/` to your private backup git repo |
@@ -44,7 +44,7 @@ COMPILE (offline, curator): raw/<ns>/*.md → ingest → extract(LLM) → resol
44
44
  SERVE (runtime, per device): facts.jsonl → GraphStore → ScopedGraph(ns) → MCP → agent
45
45
  ```
46
46
 
47
- These never overlap. `compile` mutates `facts.jsonl`; `serve` reads it and lazily reloads on mtime change — there is no live write API.
47
+ `compile` mutates `facts.jsonl`; `serve` reads it and lazily reloads on mtime change. Write tools (propose_fact, link_facts, etc.) append to `pending/` journals; resolve merges them into the graph.
48
48
 
49
49
  ### Compile pipeline (`src/lorekeep/compile/`, orchestrated by `pipeline.py`)
50
50
  `ingest` chunks markdown with `path:line` provenance → `extract` calls the LLM provider for schema-constrained nodes/edges/aliases (per-chunk SHA-256 hash cache → unchanged chunks return cached output, giving byte-stable recompiles) → `resolve` collapses alias variants to canonical entities and quarantines invalid facts → `writer` emits **sorted** `facts.jsonl` + `manifest.json`. Failures are skip-and-log (partial compile is valid); errors/quarantine land in the manifest.
@@ -57,7 +57,7 @@ Pydantic, all `frozen=True`, `extra="forbid"`. `Node` / `Edge` are the two `kind
57
57
  - **`perm/ns.py` `ScopedGraph`** — the **single permission chokepoint**. Wraps a `GraphStore` and filters *every* query. Deny-by-default: `effective_ns = allowed ∪ {public}`; a node is visible iff `ns ∩ effective_ns ≠ ∅`; an edge iff **both** endpoints visible **and** `edge.ns ∩ effective_ns ≠ ∅` (an edge never leaks a neighbor the caller can't see). **Any new query path must go through `ScopedGraph`, not `GraphStore` directly.**
58
58
 
59
59
  ### Serve (`mcp_server.py`)
60
- `FastMCP` with 8 read-only tools (`search`, `get_node`, `neighbors`, `at_time`, `history`, `changes`, `list_namespaces`, `schema`). Module-global `ScopedGraph` is set by `configure()`; `_require()` lazy-reloads when `facts.jsonl` mtime changes (so `compile` is visible without reconnecting). Tools are plain functions registered with `@mcp.tool()` but stay directly callable — **tests invoke them directly, no MCP transport**. The writer uses atomic `os.replace` so lazy-reload never reads a half-written file.
60
+ `FastMCP` with 8 read tools (`search`, `get_node`, `neighbors`, `at_time`, `history`, `changes`, `list_namespaces`, `schema`) and 5 write tools (`propose_fact`, `link_facts`, `flag_contradiction`, `update_fact`, `suggest_improvement`). Module-global `ScopedGraph` is set by `configure()`; `_require()` lazy-reloads when `facts.jsonl` mtime changes (so `compile` is visible without reconnecting). Tools are plain functions registered with `@mcp.tool()` but stay directly callable — **tests invoke them directly, no MCP transport**. The writer uses atomic `os.replace` so lazy-reload never reads a half-written file.
61
61
 
62
62
  ### Path resolution (`paths.py`)
63
63
  Pure (no I/O), 4-tier precedence high→low: explicit `LOREKEEP_RAW/OUT/CACHE/SCHEMA/CONFIG` env → `LOREKEEP_HOME` → **dev mode** (`.lorekeep/` present in CWD, or `LOREKEEP_DEV=1`; auto-detected in a source checkout) — all data lives under `cwd/.lorekeep/` (`config.yaml`, `schema.json`, `raw/`, `graph/`, `cache.json`), mirroring the `LOREKEEP_HOME` layout → XDG (`platformdirs`). Running `uv run lorekeep …` from the repo uses the repo's own `.lorekeep/` data home with zero migration.
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0](https://github.com/manhhailua/lorekeep/compare/v0.2.1...v0.3.0) (2026-06-28)
4
+
5
+
6
+ ### Features
7
+
8
+ * zero-friction init — wire, import, compile, daemon in one command ([#55](https://github.com/manhhailua/lorekeep/issues/55)) ([26e27ad](https://github.com/manhhailua/lorekeep/commit/26e27ad70e9eae90d4ac490694b891eda01b563b))
9
+
10
+ ## [0.2.1](https://github.com/manhhailua/lorekeep/compare/v0.2.0...v0.2.1) (2026-06-28)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * repair daemon auto-compile provider construction and re-merge journals after standalone compile ([#48](https://github.com/manhhailua/lorekeep/issues/48)) ([fb05b29](https://github.com/manhhailua/lorekeep/commit/fb05b290c5c673cc36891790d62036b8b6f65c7e))
16
+ * resolve doc contradictions and false cadence claims ([#53](https://github.com/manhhailua/lorekeep/issues/53)) ([10fc794](https://github.com/manhhailua/lorekeep/commit/10fc79406b02d1fa5735274b3dd89c62653ed3ba))
17
+
18
+
19
+ ### Documentation
20
+
21
+ * align docs with shipped write tools, journals, resolve, and daemon ([#50](https://github.com/manhhailua/lorekeep/issues/50)) ([372e283](https://github.com/manhhailua/lorekeep/commit/372e283b475dfb6e7c8c995bf2b650dc2da02499))
22
+
3
23
  ## [0.2.0](https://github.com/manhhailua/lorekeep/compare/v0.1.13...v0.2.0) (2026-06-28)
4
24
 
5
25
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lorekeep
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Temporal knowledge graph for AI agents via MCP
5
5
  Project-URL: Homepage, https://github.com/manhhailua/lorekeep
6
6
  Project-URL: Repository, https://github.com/manhhailua/lorekeep
@@ -24,7 +24,7 @@ Description-Content-Type: text/markdown
24
24
 
25
25
  <p align="center"><img src="cover.jpeg" alt="Lorekeep" /></p>
26
26
 
27
- **A temporal knowledge graph for AI agents, over MCP — agents read at query time, contribute at compile time (runtime write planned for phase 2).**
27
+ **A temporal knowledge graph for AI agents, over MCP — agents read at query time and propose facts at runtime through journal-based write tools.**
28
28
 
29
29
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
30
30
 
@@ -59,7 +59,7 @@ knowledge.
59
59
  - **Append-and-resolve** — three write paths (raw/ compile, agent ingest,
60
60
  import sessions) converge into one resolve step. Journals are append-only;
61
61
  resolve is pure logic, zero LLM cost.
62
- - **Agent-driven knowledge** [planned] — agents propose facts at runtime via MCP write
62
+ - **Agent-driven knowledge** — agents propose facts at runtime via MCP write
63
63
  tools at **zero marginal LLM cost**. Confidence-gated: high-confidence
64
64
  auto-merge, low-confidence quarantine.
65
65
  - **File-sovereign** — `facts.jsonl` (one fact per line, sorted) is the single
@@ -69,8 +69,8 @@ knowledge.
69
69
  - **Namespace permission** — facts are tagged `ns` from the directory tree
70
70
  (`raw/<ns>/`); agents scoped to namespaces; cross-namespace edges
71
71
  hidden unless both endpoints are visible. Deny-by-default.
72
- - **MCP, stdio-first** — `lorekeep serve` exposes 8 read tools (5 write tools planned);
73
- `lorekeep mcp add` wires Claude Code / Cursor / Codex.
72
+ - **MCP, stdio-first** — `lorekeep serve` exposes 8 read + 5 write tools;
73
+ `lorekeep mcp add` wires Claude Code / Cursor / Codex / opencode.
74
74
  - **Autonomous agent daemon** — `lorekeep agent watch` keeps the graph current:
75
75
  auto-compile on raw/ change, auto-resolve pending journals, delta import of
76
76
  agent session memory. Runs in the background; MCP server lazy-reloads.
@@ -112,7 +112,7 @@ uvx lorekeep mcp add --agent claude --ns backend
112
112
  uvx lorekeep doctor
113
113
  ```
114
114
 
115
- Restart Claude Code → 8 Lorekeep read tools are available, scoped to your namespace.
115
+ Restart Claude Code → 13 Lorekeep tools are available (8 read + 5 write), scoped to your namespace.
116
116
 
117
117
  ## Lifecycle
118
118
 
@@ -140,7 +140,7 @@ The full journey from install to continuous use — see the
140
140
  | 3. Compile | `lorekeep compile` | LLM-extract facts → `facts.jsonl` (cached, deterministic) |
141
141
  | 4. Wire agent | `lorekeep mcp add --agent claude --ns <ns>` | Write `.mcp.json`, scoped to namespace |
142
142
  | 5. Verify | `lorekeep doctor` | Graph loads, schema valid, tool responds |
143
- | 6. Serve | `lorekeep serve` | MCP server (read-only, 8 tools, lazy-reload) |
143
+ | 6. Serve | `lorekeep serve` | MCP server (8 read + 5 write tools, lazy-reload) |
144
144
  | 7. Keep current | `lorekeep agent watch &` | Daemon: auto-compile, auto-resolve, delta-import sessions |
145
145
  | 8. Back up | `lorekeep backup` | Push data home to private git repo (raw/ + schema.json) |
146
146
 
@@ -154,7 +154,7 @@ updates. Step 8 syncs across machines.
154
154
  ════════════════
155
155
  raw/<ns>/*.md ──► ingest ──► extract(LLM) ──┐
156
156
  │
157
- agent propose ──► MCP write tools ──► ──────┤ [planned phase 2]
157
+ agent propose ──► MCP write tools ──► ──────┤
158
158
  (ZERO LLM cost, journal append) │
159
159
  ├──► resolve ──► writer ──► facts.jsonl
160
160
  import ──► raw/ ──► compile ────────────────┘ (pure logic, │
@@ -164,8 +164,8 @@ import ──► raw/ ──► compile ─────────────
164
164
  SERVE + QUERY (runtime, per device)
165
165
  facts.jsonl ──load──► GraphStore ──► ScopedGraph(ns) ──► MCP ──► agent
166
166
  ▲ ▲ │
167
- │ │ ◄── read queries
168
- │ └────────── write proposals (journal) [planned]
167
+ │ │ ◄── read queries
168
+ │ └────────── write proposals (journal)
169
169
  └── lazy-reload on mtime change
170
170
 
171
171
  AUTONOMOUS AGENT DAEMON
@@ -175,12 +175,12 @@ facts.jsonl ──load──► GraphStore ──► ScopedGraph(ns) ──► M
175
175
  └── watch Claude memory/ → delta import → raw/
176
176
  ```
177
177
 
178
- **Three write paths → one resolve**: markdown is compiled by an LLM (chunked + cached); agents will propose facts at runtime through MCP write tools at **zero marginal LLM cost** (the agent already ran the LLM for the conversation) — **planned for phase 2**; agent sessions are imported into raw/. All converge at `resolve` — pure Python logic that merges, deduplicates, validates, and writes byte-stable `facts.jsonl`.
178
+ **Three write paths → one resolve**: markdown is compiled by an LLM (chunked + cached); agents propose facts at runtime through MCP write tools at **zero marginal LLM cost** (the agent already ran the LLM for the conversation); agent sessions are imported into raw/. All converge at `resolve` — pure Python logic that merges, deduplicates, validates, and writes byte-stable `facts.jsonl`.
179
179
 
180
180
  **Serve**: `GraphStore` loads `facts.jsonl` into a networkx graph with temporal
181
181
  queries. `ScopedGraph` is the single permission chokepoint — every query is
182
- filtered through strict visibility rules. The FastMCP server exposes 8 read tools
183
- (5 write tools planned for phase 2) over `ScopedGraph`. It lazy-reloads when
182
+ filtered through strict visibility rules. The FastMCP server exposes 8 read
183
+ + 5 write tools over `ScopedGraph`. It lazy-reloads when
184
184
  `facts.jsonl` changes, so `compile` is instantly visible without reconnecting.
185
185
 
186
186
  ## Concepts
@@ -203,17 +203,17 @@ neighbor the caller can't see.
203
203
  `[from,to)`), `history(id)` (versions of an entity), `changes(t1,t2)` (edges
204
204
  that began/ended in the window).
205
205
 
206
- **Agent-driven knowledge** [planned] — agents will propose facts at runtime through MCP write tools (zero LLM cost). Facts land in `pending/<ns>/journal.jsonl` with agent id, confidence score, and timestamp. Resolve merges them into the graph: high-confidence (≥0.8) auto-merge, medium (0.5-0.8) merge + flag, low (<0.5) quarantine.
206
+ **Agent-driven knowledge** — agents propose facts at runtime through MCP write tools (zero LLM cost). Facts land in `pending/<ns>/journal.jsonl` with agent id, confidence score, and timestamp. Resolve merges them into the graph: high-confidence (≥0.8) auto-merge, medium (0.5-0.8) merge + flag, low (<0.5) quarantine.
207
207
 
208
208
  **Autonomous agent daemon** — `lorekeep agent watch` keeps the graph current: watches `raw/` for changes → auto-compile; monitors `pending/` → auto-resolve; delta-imports Claude session memory into `raw/`. Scheduled lint and weekly suggestions are planned. See [docs/architecture/agent.md](docs/architecture/agent.md).
209
209
 
210
- ## MCP tools (8 read, scoped; 5 write planned)
210
+ ## MCP tools (8 read + 5 write, scoped)
211
211
 
212
212
  **Read:** `search` · `get_node` · `neighbors` · `at_time` · `history` · `changes` · `list_namespaces` · `schema`.
213
213
 
214
- **Write** (journal-based, zero LLM cost, planned phase 2): `propose_fact` · `link_facts` · `flag_contradiction` · `update_fact` · `suggest_improvement`.
214
+ **Write** (journal-based, zero LLM cost): `propose_fact` · `link_facts` · `flag_contradiction` · `update_fact` · `suggest_improvement`.
215
215
 
216
- Every result is filtered to the caller's namespace. Write tools will append to `pending/` journals; facts enter the graph on the next resolve pass.
216
+ Every result is filtered to the caller's namespace. Write tools append to `pending/` journals; facts enter the graph on the next resolve pass.
217
217
 
218
218
  ## Configuration
219
219
 
@@ -268,7 +268,7 @@ src/lorekeep/
268
268
  agent.py autonomous agent: ingest, lint, suggest, status, watch
269
269
  store/{graph,fts}.py GraphStore + optional FTS cache
270
270
  perm/ns.py ScopedGraph permission chokepoint
271
- mcp_server.py FastMCP + 8 read tools (5 write planned)
271
+ mcp_server.py FastMCP + 8 read + 5 write tools
272
272
  integrations/{claude_code,cursor,codex,common}.py
273
273
  pipeline.py, cli.py
274
274
  eval/{gold,construction,retrieval}.py
@@ -280,7 +280,7 @@ docs/ README.md index, architecture/, guides/
280
280
 
281
281
  **v1 (implemented)** — compile pipeline + serve (store/permission/MCP read/integrations) + import + agent daemon (watch/ingest/lint/suggest/status) + journal + resolve + data-home + dev mode + lazy-reload + backup + eval. Published to PyPI as `lorekeep`.
282
282
 
283
- **Phase 2 (planned)** — MCP write tools (runtime fact proposals via `propose_fact`, `link_facts`, etc.) + `wiki.md` views (Obsidian-compatible markdown output), streamable-HTTP team server, OIDC/SSO, embeddings/hybrid search, scheduled nightly lint/suggest in daemon, schema evolve, full Tier-2 benchmark datasets (HotpotQA/CronQuestions) and the bespoke Tier-3 Lorekeep-Reason eval.
283
+ **Phase 2 (planned)** — `wiki.md` views (Obsidian-compatible markdown output), streamable-HTTP team server, OIDC/SSO, embeddings/hybrid search, scheduled nightly lint/suggest in daemon, schema evolve, full Tier-2 benchmark datasets (HotpotQA/CronQuestions) and the bespoke Tier-3 Lorekeep-Reason eval.
284
284
 
285
285
  ## Documentation
286
286
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  <p align="center"><img src="cover.jpeg" alt="Lorekeep" /></p>
4
4
 
5
- **A temporal knowledge graph for AI agents, over MCP — agents read at query time, contribute at compile time (runtime write planned for phase 2).**
5
+ **A temporal knowledge graph for AI agents, over MCP — agents read at query time and propose facts at runtime through journal-based write tools.**
6
6
 
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
8
 
@@ -37,7 +37,7 @@ knowledge.
37
37
  - **Append-and-resolve** — three write paths (raw/ compile, agent ingest,
38
38
  import sessions) converge into one resolve step. Journals are append-only;
39
39
  resolve is pure logic, zero LLM cost.
40
- - **Agent-driven knowledge** [planned] — agents propose facts at runtime via MCP write
40
+ - **Agent-driven knowledge** — agents propose facts at runtime via MCP write
41
41
  tools at **zero marginal LLM cost**. Confidence-gated: high-confidence
42
42
  auto-merge, low-confidence quarantine.
43
43
  - **File-sovereign** — `facts.jsonl` (one fact per line, sorted) is the single
@@ -47,8 +47,8 @@ knowledge.
47
47
  - **Namespace permission** — facts are tagged `ns` from the directory tree
48
48
  (`raw/<ns>/`); agents scoped to namespaces; cross-namespace edges
49
49
  hidden unless both endpoints are visible. Deny-by-default.
50
- - **MCP, stdio-first** — `lorekeep serve` exposes 8 read tools (5 write tools planned);
51
- `lorekeep mcp add` wires Claude Code / Cursor / Codex.
50
+ - **MCP, stdio-first** — `lorekeep serve` exposes 8 read + 5 write tools;
51
+ `lorekeep mcp add` wires Claude Code / Cursor / Codex / opencode.
52
52
  - **Autonomous agent daemon** — `lorekeep agent watch` keeps the graph current:
53
53
  auto-compile on raw/ change, auto-resolve pending journals, delta import of
54
54
  agent session memory. Runs in the background; MCP server lazy-reloads.
@@ -90,7 +90,7 @@ uvx lorekeep mcp add --agent claude --ns backend
90
90
  uvx lorekeep doctor
91
91
  ```
92
92
 
93
- Restart Claude Code → 8 Lorekeep read tools are available, scoped to your namespace.
93
+ Restart Claude Code → 13 Lorekeep tools are available (8 read + 5 write), scoped to your namespace.
94
94
 
95
95
  ## Lifecycle
96
96
 
@@ -118,7 +118,7 @@ The full journey from install to continuous use — see the
118
118
  | 3. Compile | `lorekeep compile` | LLM-extract facts → `facts.jsonl` (cached, deterministic) |
119
119
  | 4. Wire agent | `lorekeep mcp add --agent claude --ns <ns>` | Write `.mcp.json`, scoped to namespace |
120
120
  | 5. Verify | `lorekeep doctor` | Graph loads, schema valid, tool responds |
121
- | 6. Serve | `lorekeep serve` | MCP server (read-only, 8 tools, lazy-reload) |
121
+ | 6. Serve | `lorekeep serve` | MCP server (8 read + 5 write tools, lazy-reload) |
122
122
  | 7. Keep current | `lorekeep agent watch &` | Daemon: auto-compile, auto-resolve, delta-import sessions |
123
123
  | 8. Back up | `lorekeep backup` | Push data home to private git repo (raw/ + schema.json) |
124
124
 
@@ -132,7 +132,7 @@ updates. Step 8 syncs across machines.
132
132
  ════════════════
133
133
  raw/<ns>/*.md ──► ingest ──► extract(LLM) ──┐
134
134
  │
135
- agent propose ──► MCP write tools ──► ──────┤ [planned phase 2]
135
+ agent propose ──► MCP write tools ──► ──────┤
136
136
  (ZERO LLM cost, journal append) │
137
137
  ├──► resolve ──► writer ──► facts.jsonl
138
138
  import ──► raw/ ──► compile ────────────────┘ (pure logic, │
@@ -142,8 +142,8 @@ import ──► raw/ ──► compile ─────────────
142
142
  SERVE + QUERY (runtime, per device)
143
143
  facts.jsonl ──load──► GraphStore ──► ScopedGraph(ns) ──► MCP ──► agent
144
144
  ▲ ▲ │
145
- │ │ ◄── read queries
146
- │ └────────── write proposals (journal) [planned]
145
+ │ │ ◄── read queries
146
+ │ └────────── write proposals (journal)
147
147
  └── lazy-reload on mtime change
148
148
 
149
149
  AUTONOMOUS AGENT DAEMON
@@ -153,12 +153,12 @@ facts.jsonl ──load──► GraphStore ──► ScopedGraph(ns) ──► M
153
153
  └── watch Claude memory/ → delta import → raw/
154
154
  ```
155
155
 
156
- **Three write paths → one resolve**: markdown is compiled by an LLM (chunked + cached); agents will propose facts at runtime through MCP write tools at **zero marginal LLM cost** (the agent already ran the LLM for the conversation) — **planned for phase 2**; agent sessions are imported into raw/. All converge at `resolve` — pure Python logic that merges, deduplicates, validates, and writes byte-stable `facts.jsonl`.
156
+ **Three write paths → one resolve**: markdown is compiled by an LLM (chunked + cached); agents propose facts at runtime through MCP write tools at **zero marginal LLM cost** (the agent already ran the LLM for the conversation); agent sessions are imported into raw/. All converge at `resolve` — pure Python logic that merges, deduplicates, validates, and writes byte-stable `facts.jsonl`.
157
157
 
158
158
  **Serve**: `GraphStore` loads `facts.jsonl` into a networkx graph with temporal
159
159
  queries. `ScopedGraph` is the single permission chokepoint — every query is
160
- filtered through strict visibility rules. The FastMCP server exposes 8 read tools
161
- (5 write tools planned for phase 2) over `ScopedGraph`. It lazy-reloads when
160
+ filtered through strict visibility rules. The FastMCP server exposes 8 read
161
+ + 5 write tools over `ScopedGraph`. It lazy-reloads when
162
162
  `facts.jsonl` changes, so `compile` is instantly visible without reconnecting.
163
163
 
164
164
  ## Concepts
@@ -181,17 +181,17 @@ neighbor the caller can't see.
181
181
  `[from,to)`), `history(id)` (versions of an entity), `changes(t1,t2)` (edges
182
182
  that began/ended in the window).
183
183
 
184
- **Agent-driven knowledge** [planned] — agents will propose facts at runtime through MCP write tools (zero LLM cost). Facts land in `pending/<ns>/journal.jsonl` with agent id, confidence score, and timestamp. Resolve merges them into the graph: high-confidence (≥0.8) auto-merge, medium (0.5-0.8) merge + flag, low (<0.5) quarantine.
184
+ **Agent-driven knowledge** — agents propose facts at runtime through MCP write tools (zero LLM cost). Facts land in `pending/<ns>/journal.jsonl` with agent id, confidence score, and timestamp. Resolve merges them into the graph: high-confidence (≥0.8) auto-merge, medium (0.5-0.8) merge + flag, low (<0.5) quarantine.
185
185
 
186
186
  **Autonomous agent daemon** — `lorekeep agent watch` keeps the graph current: watches `raw/` for changes → auto-compile; monitors `pending/` → auto-resolve; delta-imports Claude session memory into `raw/`. Scheduled lint and weekly suggestions are planned. See [docs/architecture/agent.md](docs/architecture/agent.md).
187
187
 
188
- ## MCP tools (8 read, scoped; 5 write planned)
188
+ ## MCP tools (8 read + 5 write, scoped)
189
189
 
190
190
  **Read:** `search` · `get_node` · `neighbors` · `at_time` · `history` · `changes` · `list_namespaces` · `schema`.
191
191
 
192
- **Write** (journal-based, zero LLM cost, planned phase 2): `propose_fact` · `link_facts` · `flag_contradiction` · `update_fact` · `suggest_improvement`.
192
+ **Write** (journal-based, zero LLM cost): `propose_fact` · `link_facts` · `flag_contradiction` · `update_fact` · `suggest_improvement`.
193
193
 
194
- Every result is filtered to the caller's namespace. Write tools will append to `pending/` journals; facts enter the graph on the next resolve pass.
194
+ Every result is filtered to the caller's namespace. Write tools append to `pending/` journals; facts enter the graph on the next resolve pass.
195
195
 
196
196
  ## Configuration
197
197
 
@@ -246,7 +246,7 @@ src/lorekeep/
246
246
  agent.py autonomous agent: ingest, lint, suggest, status, watch
247
247
  store/{graph,fts}.py GraphStore + optional FTS cache
248
248
  perm/ns.py ScopedGraph permission chokepoint
249
- mcp_server.py FastMCP + 8 read tools (5 write planned)
249
+ mcp_server.py FastMCP + 8 read + 5 write tools
250
250
  integrations/{claude_code,cursor,codex,common}.py
251
251
  pipeline.py, cli.py
252
252
  eval/{gold,construction,retrieval}.py
@@ -258,7 +258,7 @@ docs/ README.md index, architecture/, guides/
258
258
 
259
259
  **v1 (implemented)** — compile pipeline + serve (store/permission/MCP read/integrations) + import + agent daemon (watch/ingest/lint/suggest/status) + journal + resolve + data-home + dev mode + lazy-reload + backup + eval. Published to PyPI as `lorekeep`.
260
260
 
261
- **Phase 2 (planned)** — MCP write tools (runtime fact proposals via `propose_fact`, `link_facts`, etc.) + `wiki.md` views (Obsidian-compatible markdown output), streamable-HTTP team server, OIDC/SSO, embeddings/hybrid search, scheduled nightly lint/suggest in daemon, schema evolve, full Tier-2 benchmark datasets (HotpotQA/CronQuestions) and the bespoke Tier-3 Lorekeep-Reason eval.
261
+ **Phase 2 (planned)** — `wiki.md` views (Obsidian-compatible markdown output), streamable-HTTP team server, OIDC/SSO, embeddings/hybrid search, scheduled nightly lint/suggest in daemon, schema evolve, full Tier-2 benchmark datasets (HotpotQA/CronQuestions) and the bespoke Tier-3 Lorekeep-Reason eval.
262
262
 
263
263
  ## Documentation
264
264
 
@@ -1,14 +1,16 @@
1
1
  # Security policy — Lorekeep
2
2
 
3
3
  Lorekeep compiles team documents into a temporal knowledge graph and serves it
4
- read-only to AI coding agents over MCP. This document describes the threat
4
+ to AI coding agents over MCP. This document describes the threat
5
5
  model and the configuration decisions that keep a deployment safe.
6
6
 
7
7
  ## Trust model
8
8
 
9
- - **Compile-only, single writer.** The graph (`graph/facts.jsonl`) is produced by
10
- `lorekeep compile` and never mutated by the server. Agents read via MCP; there is
11
- no write API. No concurrency control is needed because readers are read-only.
9
+ - **Compile + journal-based writes.** The graph (`graph/facts.jsonl`) is produced by
10
+ `lorekeep compile` and never mutated directly by the server. Agents read via MCP
11
+ and propose facts through journal-based write tools that append to `pending/` —
12
+ facts enter the graph only after a resolve pass (confidence-gated). No concurrency
13
+ control is needed on the read path because `facts.jsonl` is replaced atomically.
12
14
  - **Per-process namespace scope.** An MCP server's visible data is fixed at startup
13
15
  by `LOREKEEP_NS` (comma-separated namespaces). Visibility is enforced by a single
14
16
  chokepoint, `ScopedGraph` (`src/lorekeep/perm/ns.py`), applied to **every** query.
@@ -13,7 +13,7 @@ lorekeep/
13
13
  │ ├── facts.jsonl # THE store: nodes + edges + temporal + ns, 1 fact/line
14
14
  │ ├── manifest.json # provenance: raw→fact map, chunk hashes, run id, errors, quarantine
15
15
  │ └── schema.json # node/edge type definitions
16
- ├── pending/ # agent-proposed facts (planned phase 2)
16
+ ├── pending/ # agent-proposed facts (journals)
17
17
  │ ├── <ns>/journal.jsonl # per-namespace append-only journal
18
18
  │ └── <agent>/journal.jsonl # per-agent append-only journal
19
19
  ├── .lorekeep/ # LOCAL only (gitignored)
@@ -23,8 +23,8 @@ lorekeep/
23
23
  ├── compile/{ingest,extract,resolve,writer}.py
24
24
  ├── store/{graph,fts}.py
25
25
  ├── perm/ns.py
26
- ├── journal.py # journal append + load [planned phase 2]
27
- ├── agent.py # autonomous agent CLI [planned phase 2]
26
+ ├── journal.py # journal append + load
27
+ ├── agent.py # autonomous agent CLI
28
28
  ├── integrations/{claude_code,cursor,codex}.py
29
29
  ├── mcp_server.py
30
30
  └── cli.py
@@ -96,8 +96,8 @@ Each component has one responsibility, a clear input/output interface, and is te
96
96
  | `compile/extract` | chunk + schema | candidate facts | **The compiler.** LLM-driven, provider-pluggable. Constrained to `schema.json`. Idempotent per chunk via hash cache. |
97
97
  | `compile/resolve` | candidate facts + journals | clean facts | Entity dedup (alias → canonical id), validate edge endpoints exist, enforce ns-consistency, quarantine malformed facts. Merges from three sources (raw/ > import > agent-propose). |
98
98
  | `compile/writer` | clean facts | `facts.jsonl` + `manifest.json` | **Deterministic emit**: facts sorted by `(kind, type, id)`, sorted JSON keys, stable formatting ⇒ byte-identical output for unchanged input ⇒ clean git diffs. |
99
- | `journal` [planned] | fact + agent + confidence | append to `pending/` journal | Append-only JSONL writer. Agent-proposed facts land here before resolve. |
100
- | `agent` [planned] | — | — | Daemon: watch raw/ → auto-compile, periodic resolve, nightly lint, auto-import, suggest. CLI: `agent lint`, `agent ingest`, `agent evolve`. |
99
+ | `journal` | fact + agent + confidence | append to `pending/` journal | Append-only JSONL writer. Agent-proposed facts land here before resolve. |
100
+ | `agent` | — | — | Daemon: watch raw/ → auto-compile, periodic resolve, nightly lint, auto-import, suggest. CLI: `agent lint`, `agent ingest`, `agent evolve`. |
101
101
  | `store/graph` | `facts.jsonl` | networkx `MultiDiGraph` (temporal) | Load + query API: `get_node`, `neighbors`, `snapshot`, `history`, `changes`. Pure functions; no I/O after load. |
102
102
  | `perm/ns` | `allowed_ns` (set) | filter / guard | **Single permission chokepoint.** Every store query passes through here. |
103
103
  | `store/fts` (optional) | `facts.jsonl` | FTS cache | FTS5 over node text/props for text search. Local, gitignored, rebuilt from `facts.jsonl`. Falls back to in-memory scan if absent. |
@@ -1,7 +1,5 @@
1
1
  # Journal: agent-driven knowledge accumulation
2
2
 
3
- > **Status: planned (phase 2).** The journal system, MCP write tools, and periodic resolve described here are target architecture. Current v1 is compile-only with 8 read-only MCP tools. Implementation tracked in [#15](https://github.com/manhhailua/lorekeep/issues/15).
4
-
5
3
  The journal is the mechanism by which coding agents contribute knowledge to Lorekeep **at runtime, at zero marginal LLM cost**. Agents propose facts during conversation; the journal captures them as append-only JSONL; a periodic resolve pass merges validated facts into `facts.jsonl`.
6
4
 
7
5
  ## Why journals?
@@ -8,7 +8,7 @@ Lorekeep builds a **living temporal knowledge graph** that coding agents both **
8
8
  2. **Strictly file-based storage** (`facts.jsonl` + `pending/` journals), for privacy and portability.
9
9
  3. **Namespace-scoped permission**, for team-level use rather than a single local user.
10
10
 
11
- The system is **compile-only in v1, append-and-resolve in phase 2**: raw docs are compiled offline; agents will propose facts at runtime through a journal; a periodic resolve pass merges all sources into `facts.jsonl` without additional LLM calls. This keeps the graph continuously up-to-date while strictly controlling API cost. The target architecture is described in this document; v1 status is noted throughout.
11
+ The system has two phases: **compile** (offline, curator-side) and **serve** (runtime, per device). Raw docs are compiled offline; agents propose facts at runtime through journal-based write tools; a periodic resolve pass merges all sources into `facts.jsonl` without additional LLM calls. This keeps the graph continuously up-to-date while strictly controlling API cost.
12
12
 
13
13
  ## North star
14
14
 
@@ -57,7 +57,7 @@ Lorekeep exists to let an agent reason about a domain **systematically and with
57
57
  │ ◄── MCP write tools (journal) │
58
58
  └───────────────────────────────────────────┘
59
59
 
60
- AUTONOMOUS AGENT (daemon) [planned phase 2]
60
+ AUTONOMOUS AGENT (daemon)
61
61
  ═════════════════════════════════════════
62
62
 
63
63
  lorekeep agent watch:
@@ -42,11 +42,9 @@ raw/<ns>/*.md ──► ingest ──► extract(LLM) ──► candidate facts
42
42
 
43
43
  `raw/` is populated by hand or by `lorekeep import`, which converts a coding agent's sessions (Claude Code, Cursor) into markdown; see the [import guide](../guides/import.md).
44
44
 
45
- ## Path 2: agent propose (runtime, zero LLM cost) [planned]
45
+ ## Path 2: agent propose (runtime, zero LLM cost)
46
46
 
47
- > **Status: planned (phase 2).** MCP write tools and journal-based agent proposals are target architecture. Current v1 has no runtime write path. See [#15](https://github.com/manhhailua/lorekeep/issues/15).
48
-
49
- Coding agents will propose facts during conversation through MCP write tools. Each proposal is appended to `pending/<ns>/journal.jsonl` as a journal entry.
47
+ Coding agents propose facts during conversation through MCP write tools. Each proposal is appended to `pending/<ns>/journal.jsonl` as a journal entry.
50
48
 
51
49
  ```python
52
50
  # Agent-side (Claude Code): agent discovers checkout service during conversation
@@ -27,11 +27,9 @@ The serve chain loads `facts.jsonl` once and exposes it to coding agents over MC
27
27
 
28
28
  Every read tool is auto-scoped by `allowed_ns`. See [permission](permission.md) and [temporal](temporal.md) for the filtering these tools apply.
29
29
 
30
- ## Write tools (5 tools, journal-based) [planned]
30
+ ## Write tools (5 tools, journal-based)
31
31
 
32
- > **Status: planned (phase 2).** These 5 write tools are target architecture. Current v1 exposes only the 8 read tools above. Implementation tracked in [#15](https://github.com/manhhailua/lorekeep/issues/15).
33
-
34
- Write tools **will not mutate** `facts.jsonl` directly. They will append to `pending/<ns>/journal.jsonl`. Facts become visible after the next resolve pass (see [pipeline](pipeline.md)).
32
+ Write tools **do not mutate** `facts.jsonl` directly. They append to `pending/<ns>/journal.jsonl`. Facts become visible after the next resolve pass (see [pipeline](pipeline.md)).
35
33
 
36
34
  | Tool | Purpose | Confidence |
37
35
  |---|---|---|
@@ -86,7 +84,7 @@ MCP server lazy-reloads on next query → fact is now searchable
86
84
 
87
85
  ## Coding-agent integration
88
86
 
89
- `lorekeep mcp add --agent {claude|cursor|codex} [--scope project|user] [--ns <ns>]` writes the correct config and prints an agent-memory snippet to paste into `CLAUDE.md` / `.cursorrules` / `AGENTS.md`.
87
+ `lorekeep mcp add --agent {claude|cursor|codex|opencode} [--scope project|user] [--ns <ns>]` writes the correct config and prints an agent-memory snippet to paste into `CLAUDE.md` / `.cursorrules` / `AGENTS.md`.
90
88
 
91
89
  > **Install source.** The snippets use `uvx lorekeep`, which assumes the package is on PyPI. `mcp add` detects `install_source` from `.lorekeep/config.yaml` so the emitted config matches the deployment (PyPI `uvx`, `git+https`, or a local `uv tool install .`).
92
90
 
@@ -42,9 +42,7 @@ unchanged input yields a byte-identical file (extraction is cached under
42
42
  **What compile does not do:** compile processes only `raw/`. Agent-proposed
43
43
  facts in `pending/` journals are merged by `resolve` (see step 5).
44
44
 
45
- ## 4. Resolve pending facts (manual) [planned]
46
-
47
- > **Planned for phase 2.** Resolve and daemon commands are not yet available. See [#15](https://github.com/manhhailua/lorekeep/issues/15).
45
+ ## 4. Resolve pending facts (manual)
48
46
 
49
47
  ```bash
50
48
  uv run lorekeep resolve
@@ -54,10 +52,10 @@ Merges all pending agent-proposed facts from `pending/` journals into `facts.jso
54
52
  Facts are gated by confidence: high (≥0.8) auto-merge, medium (0.5-0.8) merge
55
53
  with review flag, low (<0.5) quarantine.
56
54
 
57
- Resolve also runs automatically: the daemon (`lorekeep agent watch`) resolves
58
- every 5 minutes or after 50 pending entries.
55
+ Resolve also runs automatically: the daemon (`lorekeep agent watch`) detects
56
+ new pending entries on every poll cycle (default 60s interval).
59
57
 
60
- ## 5. Full pipeline (compile + resolve) [planned]
58
+ ## 5. Full pipeline (compile + resolve)
61
59
 
62
60
  ```bash
63
61
  uv run lorekeep compile && uv run lorekeep resolve
@@ -66,7 +64,7 @@ uv run lorekeep compile && uv run lorekeep resolve
66
64
  Or let the daemon handle it:
67
65
 
68
66
  ```bash
69
- uv run lorekeep agent watch # watches raw/ + pending/ → auto-compile + resolve [planned]
67
+ uv run lorekeep agent watch # watches raw/ + pending/ → auto-compile + resolve
70
68
  ```
71
69
 
72
70
  ## 6. Evaluate construction quality
@@ -88,12 +86,12 @@ uv run lorekeep check
88
86
 
89
87
  Exits non-zero if the graph has dangling edges.
90
88
 
91
- ## How agents contribute knowledge [planned]
89
+ ## How agents contribute knowledge
92
90
 
93
- Agents will propose facts at runtime through MCP write tools (see [serve.md](serve.md)).
91
+ Agents propose facts at runtime through MCP write tools (see [serve.md](serve.md)).
94
92
  These are appended to `pending/<ns>/journal.jsonl` at **zero LLM cost** — the
95
93
  agent already ran the LLM for the conversation. Facts become searchable after
96
- the next resolve. **Write tools and resolve are planned for phase 2.**
94
+ the next resolve.
97
95
 
98
96
  ## Next: serve to agents
99
97
 
@@ -132,8 +132,10 @@ uvx lorekeep mcp add --agent opencode --ns backend
132
132
 
133
133
  Supported agents: `claude`, `cursor`, `codex`, `opencode`.
134
134
 
135
- Restart the agent → the 8 read-only Lorekeep tools (`search`, `get_node`,
136
- `neighbors`, `at_time`, `history`, `changes`, `list_namespaces`, `schema`) are
135
+ Restart the agent → the 13 Lorekeep tools (8 read: `search`, `get_node`,
136
+ `neighbors`, `at_time`, `history`, `changes`, `list_namespaces`, `schema`;
137
+ 5 write: `propose_fact`, `link_facts`, `flag_contradiction`, `update_fact`,
138
+ `suggest_improvement`) are
137
139
  available, scoped to `backend` (+ `public`). See
138
140
  [Serving the graph](serve.md).
139
141
 
@@ -48,12 +48,10 @@ LOREKEEP_HOME=~/kb-work uvx lorekeep compile
48
48
  `list_namespaces`, `schema`. Results are filtered to `LOREKEEP_NS`; cross-namespace
49
49
  edges are hidden unless both endpoints are visible.
50
50
 
51
- ## Write tools (5 tools, journal-based) [planned]
51
+ ## Write tools (5 tools, journal-based)
52
52
 
53
- > **Planned for phase 2.** These write tools are not yet available. Current v1 exposes 8 read tools. See [#15](https://github.com/manhhailua/lorekeep/issues/15).
54
-
55
- When implemented, agents will contribute knowledge during conversation at **zero LLM cost**. Facts
56
- will be appended to `pending/` journals and merged into the graph on the next
53
+ Agents contribute knowledge during conversation at **zero LLM cost**. Facts
54
+ are appended to `pending/` journals and merged into the graph on the next
57
55
  resolve pass.
58
56
 
59
57
  | Tool | Purpose | Confidence |
@@ -69,8 +67,9 @@ resolve pass.
69
67
  - 0.5-0.8: implied without explicit source. "Based on the architecture, X likely depends on Y."
70
68
  - < 0.5: speculation — these are quarantined, not merged.
71
69
 
72
- Facts become visible after the next resolve pass (every 5 min or 50 pending
73
- entries when daemon is running; or run `lorekeep resolve` manually). **Note: resolve and daemon are planned for phase 2.**
70
+ Facts become visible after the next resolve pass (run `lorekeep resolve`
71
+ manually; or automatically when `lorekeep agent watch` detects new pending
72
+ entries, polling every 60s).
74
73
 
75
74
  ## Keeping the graph current
76
75
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lorekeep"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  description = "Temporal knowledge graph for AI agents via MCP"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -1,3 +1,3 @@
1
1
  """Lorekeep — temporal knowledge graph for AI agents via MCP."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.3.0"