abstractnote 0.1.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 (200) hide show
  1. {abstractnote-0.1.0/src/abstractnote.egg-info → abstractnote-0.3.0}/PKG-INFO +24 -25
  2. {abstractnote-0.1.0 → abstractnote-0.3.0}/README.md +19 -21
  3. {abstractnote-0.1.0 → abstractnote-0.3.0}/pyproject.toml +11 -8
  4. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/__init__.py +1 -1
  5. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/cli.py +75 -1
  6. abstractnote-0.3.0/src/abstractnote/flows/build.py +2033 -0
  7. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/graph.py +14 -2
  8. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/json/note-capture.json +556 -64
  9. abstractnote-0.3.0/src/abstractnote/flows/json/note-consolidate.json +15384 -0
  10. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/json/note-drain.json +411 -17
  11. abstractnote-0.3.0/src/abstractnote/flows/json/note-file.json +1146 -0
  12. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/json/note-mine.json +43 -10
  13. abstractnote-0.3.0/src/abstractnote/flows/json/note-process.json +4325 -0
  14. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/json/note-recall.json +27 -4
  15. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/json/note-reflect.json +1198 -55
  16. abstractnote-0.3.0/src/abstractnote/flows/prompts_fallback.py +25 -0
  17. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/runner.py +66 -11
  18. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/schemas_fallback.py +14 -9
  19. abstractnote-0.3.0/src/abstractnote/gateway/consolidation.py +253 -0
  20. abstractnote-0.3.0/src/abstractnote/gateway/health.py +65 -0
  21. abstractnote-0.3.0/src/abstractnote/gateway/refile.py +141 -0
  22. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/gateway/router.py +313 -32
  23. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/gateway/tools.py +1 -0
  24. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/ids.py +34 -1
  25. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/importers/__init__.py +26 -3
  26. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/importers/agora.py +65 -17
  27. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/importers/claude_sessions.py +73 -27
  28. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/importers/cli.py +12 -3
  29. abstractnote-0.3.0/src/abstractnote/importers/dedupe.py +69 -0
  30. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/importers/files.py +13 -28
  31. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/importers/markdown.py +45 -7
  32. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/ingest/capture.py +169 -18
  33. abstractnote-0.3.0/src/abstractnote/ingest/dates.py +398 -0
  34. abstractnote-0.3.0/src/abstractnote/ingest/refile.py +171 -0
  35. abstractnote-0.3.0/src/abstractnote/ledger.py +189 -0
  36. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/model.py +14 -1
  37. abstractnote-0.3.0/src/abstractnote/process/context.py +429 -0
  38. abstractnote-0.3.0/src/abstractnote/process/demote.py +58 -0
  39. abstractnote-0.3.0/src/abstractnote/process/generic_words.txt +70 -0
  40. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/process/merge.py +20 -3
  41. abstractnote-0.3.0/src/abstractnote/process/packets.py +457 -0
  42. abstractnote-0.3.0/src/abstractnote/process/prompts/__init__.py +87 -0
  43. abstractnote-0.3.0/src/abstractnote/process/prompts/entity_summaries.md +4 -0
  44. abstractnote-0.3.0/src/abstractnote/process/prompts/entity_summaries.system.md +20 -0
  45. abstractnote-0.3.0/src/abstractnote/process/prompts/extract.md +7 -0
  46. abstractnote-0.3.0/src/abstractnote/process/prompts/extract.system.md +37 -0
  47. abstractnote-0.3.0/src/abstractnote/process/prompts/link.md +18 -0
  48. abstractnote-0.3.0/src/abstractnote/process/prompts/link.system.md +33 -0
  49. abstractnote-0.3.0/src/abstractnote/process/prompts/mine_dossier.md +5 -0
  50. abstractnote-0.1.0/src/abstractnote/process/prompts/mine_dossier.md → abstractnote-0.3.0/src/abstractnote/process/prompts/mine_dossier.system.md +3 -8
  51. abstractnote-0.3.0/src/abstractnote/process/prompts/mine_findings.md +5 -0
  52. abstractnote-0.1.0/src/abstractnote/process/prompts/mine_findings.md → abstractnote-0.3.0/src/abstractnote/process/prompts/mine_findings.system.md +3 -8
  53. abstractnote-0.3.0/src/abstractnote/process/prompts/mine_plan.md +5 -0
  54. abstractnote-0.3.0/src/abstractnote/process/prompts/mine_plan.system.md +8 -0
  55. abstractnote-0.3.0/src/abstractnote/process/prompts/quick_filing.md +9 -0
  56. abstractnote-0.3.0/src/abstractnote/process/prompts/quick_filing.system.md +18 -0
  57. abstractnote-0.3.0/src/abstractnote/process/prompts/reflect.md +4 -0
  58. abstractnote-0.3.0/src/abstractnote/process/prompts/reflect.system.md +8 -0
  59. abstractnote-0.3.0/src/abstractnote/process/prompts/synthesize.md +8 -0
  60. abstractnote-0.3.0/src/abstractnote/process/prompts/synthesize.system.md +9 -0
  61. abstractnote-0.3.0/src/abstractnote/process/resolve.py +126 -0
  62. abstractnote-0.3.0/src/abstractnote/process/revise.py +1610 -0
  63. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/process/schemas.py +176 -27
  64. abstractnote-0.3.0/src/abstractnote/process/validate.py +284 -0
  65. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/recall/changes.py +24 -10
  66. abstractnote-0.3.0/src/abstractnote/recall/communities.py +574 -0
  67. abstractnote-0.3.0/src/abstractnote/recall/consolidation.py +938 -0
  68. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/recall/expand.py +306 -66
  69. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/recall/insights.py +14 -3
  70. abstractnote-0.3.0/src/abstractnote/recall/processing.py +543 -0
  71. abstractnote-0.3.0/src/abstractnote/recall/propagation.py +712 -0
  72. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/recall/reflect.py +110 -22
  73. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/recall/review.py +2 -0
  74. abstractnote-0.3.0/src/abstractnote/recall/search.py +367 -0
  75. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/recall/shapes.py +4 -1
  76. abstractnote-0.3.0/src/abstractnote/recall/stats.py +180 -0
  77. abstractnote-0.3.0/src/abstractnote/recall/then_now.py +185 -0
  78. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/store/archive.py +116 -9
  79. abstractnote-0.3.0/src/abstractnote/store/kg.py +343 -0
  80. abstractnote-0.3.0/src/abstractnote/store/names.py +287 -0
  81. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/store/notebook.py +458 -23
  82. abstractnote-0.3.0/src/abstractnote/store/notes.py +2373 -0
  83. abstractnote-0.3.0/src/abstractnote/store/queue.py +313 -0
  84. abstractnote-0.3.0/src/abstractnote/store/schema.py +719 -0
  85. abstractnote-0.3.0/src/abstractnote/store/topics.py +55 -0
  86. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/tools/__init__.py +132 -20
  87. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/tools/capture.py +26 -3
  88. abstractnote-0.3.0/src/abstractnote/tools/consolidation.py +54 -0
  89. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/tools/context.py +4 -0
  90. abstractnote-0.3.0/src/abstractnote/tools/process.py +69 -0
  91. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/tools/queue.py +16 -2
  92. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/tools/recall.py +32 -7
  93. {abstractnote-0.1.0 → abstractnote-0.3.0/src/abstractnote.egg-info}/PKG-INFO +24 -25
  94. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote.egg-info/SOURCES.txt +77 -1
  95. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote.egg-info/requires.txt +4 -3
  96. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_capture.py +5 -3
  97. abstractnote-0.3.0/tests/test_capture_dates.py +293 -0
  98. abstractnote-0.3.0/tests/test_changes_understood.py +41 -0
  99. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_cli.py +5 -2
  100. abstractnote-0.3.0/tests/test_communities.py +436 -0
  101. abstractnote-0.3.0/tests/test_communities_flow.py +105 -0
  102. abstractnote-0.3.0/tests/test_communities_stale_first.py +27 -0
  103. abstractnote-0.3.0/tests/test_consolidation.py +302 -0
  104. abstractnote-0.3.0/tests/test_consolidation_gaps.py +187 -0
  105. abstractnote-0.3.0/tests/test_consolidation_gateway.py +136 -0
  106. abstractnote-0.3.0/tests/test_dated_views.py +418 -0
  107. abstractnote-0.3.0/tests/test_drain_stale_requeue.py +132 -0
  108. abstractnote-0.3.0/tests/test_entity_names.py +406 -0
  109. abstractnote-0.3.0/tests/test_file_dates.py +102 -0
  110. abstractnote-0.3.0/tests/test_filing_imports.py +188 -0
  111. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_flows_compile.py +1 -1
  112. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_flows_contract.py +5 -2
  113. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_flows_headless.py +61 -5
  114. abstractnote-0.3.0/tests/test_gateway_communities.py +62 -0
  115. abstractnote-0.3.0/tests/test_gateway_normalize.py +32 -0
  116. abstractnote-0.3.0/tests/test_gateway_refile.py +72 -0
  117. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_gateway_router.py +7 -3
  118. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_gateway_w10.py +1 -1
  119. abstractnote-0.3.0/tests/test_importer_dates.py +63 -0
  120. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_importers.py +98 -5
  121. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_kg_projection.py +1 -1
  122. abstractnote-0.3.0/tests/test_ledger_provenance.py +522 -0
  123. abstractnote-0.3.0/tests/test_memory_dedupe.py +91 -0
  124. abstractnote-0.3.0/tests/test_model_settings.py +146 -0
  125. abstractnote-0.3.0/tests/test_no_silent_drops.py +103 -0
  126. abstractnote-0.3.0/tests/test_packets.py +290 -0
  127. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_process.py +148 -30
  128. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_process_tools.py +2 -1
  129. abstractnote-0.3.0/tests/test_processing.py +343 -0
  130. abstractnote-0.3.0/tests/test_processor_repair.py +217 -0
  131. abstractnote-0.3.0/tests/test_prompts_kinds.py +79 -0
  132. abstractnote-0.3.0/tests/test_prompts_predicates.py +94 -0
  133. abstractnote-0.3.0/tests/test_prompts_summaries.py +122 -0
  134. abstractnote-0.3.0/tests/test_propagation.py +861 -0
  135. abstractnote-0.3.0/tests/test_queue_claims.py +136 -0
  136. abstractnote-0.3.0/tests/test_queue_errors.py +50 -0
  137. abstractnote-0.3.0/tests/test_read_paths_recovery.py +88 -0
  138. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_recall.py +141 -12
  139. abstractnote-0.3.0/tests/test_recall_eval.py +112 -0
  140. abstractnote-0.3.0/tests/test_reflect_no_repeats.py +82 -0
  141. abstractnote-0.3.0/tests/test_reinterpret.py +827 -0
  142. abstractnote-0.3.0/tests/test_retired_hidden.py +120 -0
  143. abstractnote-0.3.0/tests/test_retro.py +561 -0
  144. abstractnote-0.3.0/tests/test_retro_context.py +545 -0
  145. abstractnote-0.3.0/tests/test_retro_flow.py +56 -0
  146. abstractnote-0.3.0/tests/test_retro_router.py +63 -0
  147. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_review_and_archive.py +6 -6
  148. abstractnote-0.3.0/tests/test_search_structural_entities.py +21 -0
  149. abstractnote-0.3.0/tests/test_stats.py +135 -0
  150. abstractnote-0.3.0/tests/test_strict_schemas.py +262 -0
  151. abstractnote-0.3.0/tests/test_summary_ties.py +65 -0
  152. abstractnote-0.3.0/tests/test_topics_canonical.py +68 -0
  153. abstractnote-0.3.0/tests/test_validate.py +209 -0
  154. abstractnote-0.1.0/src/abstractnote/flows/build.py +0 -970
  155. abstractnote-0.1.0/src/abstractnote/flows/json/note-process.json +0 -1853
  156. abstractnote-0.1.0/src/abstractnote/flows/prompts_fallback.py +0 -119
  157. abstractnote-0.1.0/src/abstractnote/process/context.py +0 -218
  158. abstractnote-0.1.0/src/abstractnote/process/prompts/__init__.py +0 -39
  159. abstractnote-0.1.0/src/abstractnote/process/prompts/extract.md +0 -30
  160. abstractnote-0.1.0/src/abstractnote/process/prompts/link.md +0 -32
  161. abstractnote-0.1.0/src/abstractnote/process/prompts/mine_plan.md +0 -13
  162. abstractnote-0.1.0/src/abstractnote/process/prompts/quick_filing.md +0 -23
  163. abstractnote-0.1.0/src/abstractnote/process/prompts/reflect.md +0 -10
  164. abstractnote-0.1.0/src/abstractnote/process/prompts/synthesize.md +0 -17
  165. abstractnote-0.1.0/src/abstractnote/process/resolve.py +0 -96
  166. abstractnote-0.1.0/src/abstractnote/process/revise.py +0 -410
  167. abstractnote-0.1.0/src/abstractnote/recall/search.py +0 -205
  168. abstractnote-0.1.0/src/abstractnote/recall/then_now.py +0 -100
  169. abstractnote-0.1.0/src/abstractnote/store/kg.py +0 -219
  170. abstractnote-0.1.0/src/abstractnote/store/notes.py +0 -1190
  171. abstractnote-0.1.0/src/abstractnote/store/queue.py +0 -159
  172. abstractnote-0.1.0/src/abstractnote/store/schema.py +0 -348
  173. abstractnote-0.1.0/src/abstractnote/tools/process.py +0 -22
  174. {abstractnote-0.1.0 → abstractnote-0.3.0}/LICENSE +0 -0
  175. {abstractnote-0.1.0 → abstractnote-0.3.0}/setup.cfg +0 -0
  176. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/__init__.py +0 -0
  177. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/bundle.py +0 -0
  178. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/flows/contract.py +0 -0
  179. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/gateway/__init__.py +0 -0
  180. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/gateway/appspec.py +0 -0
  181. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/importers/__main__.py +0 -0
  182. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/ingest/__init__.py +0 -0
  183. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/ingest/blobs.py +0 -0
  184. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/ingest/extract.py +0 -0
  185. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/ingest/normalise.py +0 -0
  186. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/process/__init__.py +0 -0
  187. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/process/vocabulary.py +0 -0
  188. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/recall/__init__.py +0 -0
  189. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/store/__init__.py +0 -0
  190. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/store/embeddings.py +0 -0
  191. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote/store/vector_index.py +0 -0
  192. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote.egg-info/dependency_links.txt +0 -0
  193. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote.egg-info/entry_points.txt +0 -0
  194. {abstractnote-0.1.0 → abstractnote-0.3.0}/src/abstractnote.egg-info/top_level.txt +0 -0
  195. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_gateway_seam_guard.py +0 -0
  196. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_queue.py +0 -0
  197. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_rebuild.py +0 -0
  198. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_store.py +0 -0
  199. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_store_support.py +0 -0
  200. {abstractnote-0.1.0 → abstractnote-0.3.0}/tests/test_stub_llm.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractnote
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: AbstractNote: one endpoint for your notes; a temporal semantic knowledge graph of your life, built on AbstractGateway, AbstractRuntime and AbstractMemory
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
6
6
  License-Expression: MIT
@@ -18,13 +18,14 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
18
  Requires-Python: >=3.10
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE
21
- Requires-Dist: abstractmemory>=0.3.1
21
+ Requires-Dist: abstractmemory>=0.4.0
22
22
  Requires-Dist: abstractsemantics>=0.0.5
23
- Requires-Dist: abstractruntime>=0.10.2
23
+ Requires-Dist: abstractruntime>=0.15.0
24
24
  Requires-Dist: abstractcore>=2.26.3
25
25
  Requires-Dist: pydantic>=2.0
26
+ Requires-Dist: networkx<3.7,>=3.2
26
27
  Provides-Extra: gateway
27
- Requires-Dist: abstractgateway>=0.15.11; extra == "gateway"
28
+ Requires-Dist: abstractgateway>=0.17.0; extra == "gateway"
28
29
  Requires-Dist: fastapi>=0.110; extra == "gateway"
29
30
  Provides-Extra: dev
30
31
  Requires-Dist: pytest>=7.0; extra == "dev"
@@ -44,8 +45,12 @@ runtime and one notebook per user, app hosting), **AbstractRuntime** and **Abstr
44
45
  capture and understanding workflows), **AbstractMemory** (temporal facts) and **AbstractCore**
45
46
  (models, structured output, embeddings).
46
47
 
47
- Status: version 0.1.0, in development. It is not published on PyPI or npm yet; you install it
48
- from source (see [Install](#install)).
48
+ Status: version 0.3.0, alpha. The Python package is `abstractnote` on PyPI and the web app is
49
+ `@abstractframework/note` on npm (see [Install](#install)).
50
+
51
+ What's new in 0.3.0: the web app follows runs through the gateway's replay view and says when a run waits
52
+ for an answer, the top bar carries the shared Docs assistant and one account widget, and Capture uses the
53
+ shared composer. See [CHANGELOG.md](CHANGELOG.md#030---2026-11-02).
49
54
 
50
55
  ## What you get
51
56
 
@@ -65,29 +70,23 @@ from source (see [Install](#install)).
65
70
 
66
71
  ## Install
67
72
 
68
- AbstractNote needs Python 3.10 or later and the framework packages next to it. Until the
69
- packages are published, install everything from source checkouts:
73
+ AbstractNote needs Python 3.10 or later. Install it with the gateway integration:
70
74
 
71
75
  ```sh
72
- python3 -m venv .venv
73
- .venv/bin/pip install -e ../abstractsemantics -e ../abstractcore -e ../abstractruntime \
74
- -e ../abstractmemory # a checkout that has close_assertion, see below
75
- .venv/bin/pip install -e .
76
- .venv/bin/abstractnote --help
76
+ pip install "abstractnote[gateway]"
77
+ abstractnote --help
77
78
  ```
78
79
 
79
- Two framework changes that AbstractNote relies on are not in released packages yet:
80
-
81
- - **AbstractMemory `close_assertion`** (the `close-assertion` branch): closes a superseded fact in
82
- place. AbstractNote's first release waits for the AbstractMemory release that contains it.
83
- - **The AbstractGateway integration** (the `abstractnote-seam` branch): binds the note tools to
84
- each user's notebook, serves the note read API and lists the Note app. You need it only for the
85
- gateway path; the headless notebook works without a gateway. The gateway must carry this seam
86
- (`abstractgateway.abstractnote_seam`; the first gateway release with it is named at
87
- AbstractNote's release): the `[gateway]` extra alone does not guarantee it, and
88
- `abstractnote.gateway` refuses to import into a gateway without it, with one sentence.
80
+ This brings AbstractMemory 0.4.0 or later, AbstractRuntime 0.15.0 or later and AbstractGateway 0.17.0 or later. The
81
+ gateway carries the AbstractNote integration (`abstractgateway.abstractnote_seam`) since 0.15.11: with
82
+ `abstractnote` installed in the gateway's environment, every user gets the note tools, the note
83
+ read API under `/api/gateway/note` and the note workflows. `pip install abstractnote` alone is
84
+ enough for a headless notebook on one machine. To run models locally on Apple silicon, add
85
+ `pip install "abstractcore[apple]"` (MLX).
89
86
 
90
- To run models locally on Apple silicon, add `pip install "abstractcore[apple]"` (MLX).
87
+ The web app is the npm package `@abstractframework/note`, which the gateway's app catalog installs
88
+ and serves as the Note app. To work on AbstractNote itself, install it from a source checkout; see
89
+ [CONTRIBUTING.md](CONTRIBUTING.md) and [docs/getting-started.md](docs/getting-started.md#install-from-source).
91
90
 
92
91
  ## Quick start
93
92
 
@@ -121,7 +120,7 @@ gateway, the web app and the watch app.
121
120
 
122
121
  | Client | Where | What it does |
123
122
  |---|---|---|
124
- | Web app | [`web/`](web/) (`@abstractframework/note`) | Capture (a chat with attachments), Graph (entities and links through time), Remember (since you last looked, cue cards, ask by effort, then and now), Settings |
123
+ | Web app | [`web/`](web/) (`@abstractframework/note`) | Capture (a chat with attachments), Remember (since you last looked, cue cards, ask by effort, then and now), Explore (entities and links through time), Processing (what the notebook is doing with your notes, live: the queue and its pace, the notes being understood, failures, and the scheduled consolidation), and a Settings panel |
125
124
  | Apple Watch app | [`watch/apple/`](watch/apple/README.md) | Note, Ask, Today, Settings; watch-only, watchOS 26 or later |
126
125
  | Command line | `abstractnote` | Headless capture, search, processing, imports, rebuild, JSON output for scripts and agents |
127
126
 
@@ -11,8 +11,12 @@ runtime and one notebook per user, app hosting), **AbstractRuntime** and **Abstr
11
11
  capture and understanding workflows), **AbstractMemory** (temporal facts) and **AbstractCore**
12
12
  (models, structured output, embeddings).
13
13
 
14
- Status: version 0.1.0, in development. It is not published on PyPI or npm yet; you install it
15
- from source (see [Install](#install)).
14
+ Status: version 0.3.0, alpha. The Python package is `abstractnote` on PyPI and the web app is
15
+ `@abstractframework/note` on npm (see [Install](#install)).
16
+
17
+ What's new in 0.3.0: the web app follows runs through the gateway's replay view and says when a run waits
18
+ for an answer, the top bar carries the shared Docs assistant and one account widget, and Capture uses the
19
+ shared composer. See [CHANGELOG.md](CHANGELOG.md#030---2026-11-02).
16
20
 
17
21
  ## What you get
18
22
 
@@ -32,29 +36,23 @@ from source (see [Install](#install)).
32
36
 
33
37
  ## Install
34
38
 
35
- AbstractNote needs Python 3.10 or later and the framework packages next to it. Until the
36
- packages are published, install everything from source checkouts:
39
+ AbstractNote needs Python 3.10 or later. Install it with the gateway integration:
37
40
 
38
41
  ```sh
39
- python3 -m venv .venv
40
- .venv/bin/pip install -e ../abstractsemantics -e ../abstractcore -e ../abstractruntime \
41
- -e ../abstractmemory # a checkout that has close_assertion, see below
42
- .venv/bin/pip install -e .
43
- .venv/bin/abstractnote --help
42
+ pip install "abstractnote[gateway]"
43
+ abstractnote --help
44
44
  ```
45
45
 
46
- Two framework changes that AbstractNote relies on are not in released packages yet:
47
-
48
- - **AbstractMemory `close_assertion`** (the `close-assertion` branch): closes a superseded fact in
49
- place. AbstractNote's first release waits for the AbstractMemory release that contains it.
50
- - **The AbstractGateway integration** (the `abstractnote-seam` branch): binds the note tools to
51
- each user's notebook, serves the note read API and lists the Note app. You need it only for the
52
- gateway path; the headless notebook works without a gateway. The gateway must carry this seam
53
- (`abstractgateway.abstractnote_seam`; the first gateway release with it is named at
54
- AbstractNote's release): the `[gateway]` extra alone does not guarantee it, and
55
- `abstractnote.gateway` refuses to import into a gateway without it, with one sentence.
46
+ This brings AbstractMemory 0.4.0 or later, AbstractRuntime 0.15.0 or later and AbstractGateway 0.17.0 or later. The
47
+ gateway carries the AbstractNote integration (`abstractgateway.abstractnote_seam`) since 0.15.11: with
48
+ `abstractnote` installed in the gateway's environment, every user gets the note tools, the note
49
+ read API under `/api/gateway/note` and the note workflows. `pip install abstractnote` alone is
50
+ enough for a headless notebook on one machine. To run models locally on Apple silicon, add
51
+ `pip install "abstractcore[apple]"` (MLX).
56
52
 
57
- To run models locally on Apple silicon, add `pip install "abstractcore[apple]"` (MLX).
53
+ The web app is the npm package `@abstractframework/note`, which the gateway's app catalog installs
54
+ and serves as the Note app. To work on AbstractNote itself, install it from a source checkout; see
55
+ [CONTRIBUTING.md](CONTRIBUTING.md) and [docs/getting-started.md](docs/getting-started.md#install-from-source).
58
56
 
59
57
  ## Quick start
60
58
 
@@ -88,7 +86,7 @@ gateway, the web app and the watch app.
88
86
 
89
87
  | Client | Where | What it does |
90
88
  |---|---|---|
91
- | Web app | [`web/`](web/) (`@abstractframework/note`) | Capture (a chat with attachments), Graph (entities and links through time), Remember (since you last looked, cue cards, ask by effort, then and now), Settings |
89
+ | Web app | [`web/`](web/) (`@abstractframework/note`) | Capture (a chat with attachments), Remember (since you last looked, cue cards, ask by effort, then and now), Explore (entities and links through time), Processing (what the notebook is doing with your notes, live: the queue and its pace, the notes being understood, failures, and the scheduled consolidation), and a Settings panel |
92
90
  | Apple Watch app | [`watch/apple/`](watch/apple/README.md) | Note, Ask, Today, Settings; watch-only, watchOS 26 or later |
93
91
  | Command line | `abstractnote` | Headless capture, search, processing, imports, rebuild, JSON output for scripts and agents |
94
92
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "abstractnote"
7
- version = "0.1.0"
7
+ version = "0.3.0"
8
8
  description = "AbstractNote: one endpoint for your notes; a temporal semantic knowledge graph of your life, built on AbstractGateway, AbstractRuntime and AbstractMemory"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -21,18 +21,21 @@ classifiers = [
21
21
  "Topic :: Scientific/Engineering :: Artificial Intelligence",
22
22
  ]
23
23
  dependencies = [
24
- "abstractmemory>=0.3.1",
24
+ "abstractmemory>=0.4.0",
25
25
  "abstractsemantics>=0.0.5",
26
- "abstractruntime>=0.10.2",
26
+ "abstractruntime>=0.15.0",
27
27
  "abstractcore>=2.26.3",
28
28
  "pydantic>=2.0",
29
+ # Louvain community detection over the entity graph (backlog 0030); pure Python, no compiled parts.
30
+ # Capped below 3.7: Louvain gives other communities from one networkx release to the next (gate 04 M1), so
31
+ # only tested releases are allowed; meta.communities records the version and a change carries labels over.
32
+ "networkx>=3.2,<3.7",
29
33
  ]
30
34
 
31
35
  [project.optional-dependencies]
32
- # The gateway must carry the AbstractNote seam (abstractgateway.abstractnote_seam); no released
33
- # AbstractGateway has it yet, so this floor is raised to the first release that does when
34
- # AbstractNote is released. Until then abstractnote.gateway refuses to import without the seam.
35
- gateway = ["abstractgateway>=0.15.11", "fastapi>=0.110"]
36
+ # The gateway must carry the AbstractNote seam (abstractgateway.abstractnote_seam); 0.15.11 is
37
+ # the first AbstractGateway release that does. abstractnote.gateway refuses to import without it.
38
+ gateway = ["abstractgateway>=0.17.0", "fastapi>=0.110"]
36
39
  dev = ["pytest>=7.0", "ruff>=0.1"]
37
40
 
38
41
  [project.scripts]
@@ -51,7 +54,7 @@ where = ["src"]
51
54
  include = ["abstractnote*"]
52
55
 
53
56
  [tool.setuptools.package-data]
54
- abstractnote = ["flows/json/*.json", "process/prompts/*.md"]
57
+ abstractnote = ["flows/json/*.json", "process/prompts/*.md", "process/generic_words.txt"]
55
58
 
56
59
  [tool.ruff]
57
60
  line-length = 110
@@ -4,7 +4,7 @@
4
4
  returns the note tools for flows and agents.
5
5
  """
6
6
 
7
- __version__ = "0.1.0"
7
+ __version__ = "0.3.0"
8
8
 
9
9
 
10
10
  def __getattr__(name: str): # lazy: importing abstractnote stays cheap
@@ -6,6 +6,10 @@ gateway the notebook is ``<gateway data dir>/abstractnote``, or
6
6
  ``--gateway URL --token T`` client mode is not available yet and says so.
7
7
  Output is JSON on stdout. Exit codes: 0 done, 2 bad input, 3 a part of
8
8
  AbstractNote that is not installed or not available yet.
9
+
10
+ Read commands (search, entity, day, status, changes) never finish a half-applied revision:
11
+ another process may still be applying it. ``capture`` and ``process`` recover first, and
12
+ ``abstractnote recover`` does it on request.
9
13
  """
10
14
 
11
15
  from __future__ import annotations
@@ -59,6 +63,8 @@ def build_parser() -> argparse.ArgumentParser:
59
63
  p.add_argument("--until")
60
64
  p.add_argument("--as-of")
61
65
  p.add_argument("--limit", type=int, default=20)
66
+ p.add_argument("--order", choices=["relevance", "earliest"], default="relevance",
67
+ help="quick effort: best matches first, or the matching notes oldest first")
62
68
  p.add_argument("--provider", help="model provider for standard and deep effort")
63
69
  p.add_argument("--model", help="model for standard and deep effort")
64
70
 
@@ -80,10 +86,28 @@ def build_parser() -> argparse.ArgumentParser:
80
86
  p.add_argument("--since")
81
87
  p.add_argument("--limit", type=int, default=50)
82
88
 
89
+ p = sub.add_parser("recover", help="finish revisions a stopped process left half applied")
90
+ _common(p)
91
+
83
92
  p = sub.add_parser("rebuild", help="replay revisions into fresh index and triple stores")
84
93
  _common(p)
85
94
  p.add_argument("--reembed", action="store_true", help="recompute every vector with the given embedder")
86
95
 
96
+ p = sub.add_parser("normalize", help="merge the entities that share a canonical name (one reversible merge each)")
97
+ _common(p)
98
+ p.add_argument("--dry-run", action="store_true", help="only list the groups that would be merged")
99
+ p.add_argument("--account", help="who asked, recorded in each merge's source")
100
+
101
+ p = sub.add_parser("normalize-topics", help="give every topic one spelling (one revision)")
102
+ _common(p)
103
+ p.add_argument("--dry-run", action="store_true", help="only list the groups")
104
+ p.add_argument("--account", help="who asked, recorded in the revision's source")
105
+
106
+ p = sub.add_parser("dedupe-sources", help="archive the second copy of memory files imported by two importers")
107
+ _common(p)
108
+ p.add_argument("--dry-run", action="store_true", help="only list the pairs")
109
+ p.add_argument("--account", help="who asked, recorded in the revision's source")
110
+
87
111
  p = sub.add_parser("process", help="process queued notes now")
88
112
  _common(p)
89
113
  p.add_argument("--local", action="store_true", help="run the flows here (headless)")
@@ -92,6 +116,15 @@ def build_parser() -> argparse.ArgumentParser:
92
116
  p.add_argument("--max-items", type=int, default=20)
93
117
  p.add_argument("--budget-s", type=float, default=90.0)
94
118
 
119
+ p = sub.add_parser("refile", help="file the understood notes that have no kind (imports skipped the filing)")
120
+ _common(p)
121
+ p.add_argument("--missing", action="store_true", help="the understood notes without a kind (required)")
122
+ p.add_argument("--local", action="store_true", help="run the filing flow here (headless)")
123
+ p.add_argument("--provider")
124
+ p.add_argument("--model")
125
+ p.add_argument("--max-items", type=int, default=50)
126
+ p.add_argument("--budget-s", type=float, default=600.0)
127
+
95
128
  p = sub.add_parser("bundle", help="pack the abstractnote .flow bundle")
96
129
  p.add_argument("--out", type=Path, default=Path("."))
97
130
 
@@ -153,7 +186,8 @@ def _runner(args: argparse.Namespace) -> Any:
153
186
  def _cmd_search(args: argparse.Namespace) -> Any:
154
187
  if args.effort == "quick":
155
188
  with _open(args) as nb:
156
- return nb.search(args.query, since=args.since, until=args.until, as_of=args.as_of, limit=args.limit)
189
+ return nb.search(args.query, since=args.since, until=args.until, as_of=args.as_of, limit=args.limit,
190
+ order=args.order)
157
191
  _client_mode(args)
158
192
  if not args.notebook:
159
193
  raise ValueError("Say which notebook with --notebook DIR.")
@@ -171,6 +205,32 @@ def _cmd_process(args: argparse.Namespace) -> Any:
171
205
  return _runner(args).run_drain(max_items=args.max_items, budget_s=args.budget_s)
172
206
 
173
207
 
208
+ def _cmd_refile(args: argparse.Namespace) -> Any:
209
+ _client_mode(args)
210
+ if not args.missing:
211
+ raise ValueError("Say which notes to file: --missing (the understood notes without a kind).")
212
+ if not args.local:
213
+ raise NotImplementedError("Filing through a gateway is not available here; use --local with --provider and "
214
+ "--model.")
215
+ if not args.notebook:
216
+ raise ValueError("Say which notebook with --notebook DIR.")
217
+ from .ingest.refile import refile_missing
218
+
219
+ runner = _runner(args)
220
+ with _open(args) as nb:
221
+ nb.require_embedder()
222
+ return refile_missing(nb, lambda note_id: runner.run("note-file", {"note_id": note_id}),
223
+ max_items=args.max_items, budget_s=args.budget_s,
224
+ model=f"{args.provider}/{args.model}")
225
+
226
+
227
+ def _cmd_normalize(args: argparse.Namespace) -> Any:
228
+ # A dry run needs no embedder: a notebook pinned to a model that is not available here opens read-only for
229
+ # meaning, which is enough to list the groups; the merges themselves need the notebook's model.
230
+ with _open(args) as nb:
231
+ return nb.normalize_entities(args.account, client="cli", dry_run=args.dry_run)
232
+
233
+
174
234
  def _cmd_bundle(args: argparse.Namespace) -> Any:
175
235
  try:
176
236
  from .flows.bundle import pack
@@ -213,11 +273,25 @@ def main(argv: Optional[List[str]] = None) -> int:
213
273
  elif args.command == "changes":
214
274
  with _open(args) as nb:
215
275
  out = nb.changes(args.since, args.limit)
276
+ elif args.command == "recover":
277
+ with _open(args) as nb:
278
+ nb.require_embedder()
279
+ out = {"recovered": nb.recover()}
216
280
  elif args.command == "rebuild":
217
281
  with _open(args) as nb:
218
282
  out = nb.rebuild(reembed=args.reembed, embedder=_embedder(args))
283
+ elif args.command == "normalize":
284
+ out = _cmd_normalize(args)
285
+ elif args.command == "normalize-topics":
286
+ with _open(args) as nb:
287
+ out = nb.normalize_topics(args.account, client="cli", dry_run=args.dry_run)
288
+ elif args.command == "dedupe-sources":
289
+ with _open(args) as nb:
290
+ out = nb.dedupe_sources(args.account, client="cli", dry_run=args.dry_run)
219
291
  elif args.command == "process":
220
292
  out = _cmd_process(args)
293
+ elif args.command == "refile":
294
+ out = _cmd_refile(args)
221
295
  elif args.command == "bundle":
222
296
  out = _cmd_bundle(args)
223
297
  elif args.command == "processor":