anchor-kb 0.2.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 (323) hide show
  1. anchor_kb-0.2.0/.gitignore +67 -0
  2. anchor_kb-0.2.0/.importlinter +67 -0
  3. anchor_kb-0.2.0/EXTENSIONS.md +283 -0
  4. anchor_kb-0.2.0/LICENSE +21 -0
  5. anchor_kb-0.2.0/OIP.md +33 -0
  6. anchor_kb-0.2.0/PKG-INFO +323 -0
  7. anchor_kb-0.2.0/README.md +286 -0
  8. anchor_kb-0.2.0/conftest.py +9 -0
  9. anchor_kb-0.2.0/docs/README.md +42 -0
  10. anchor_kb-0.2.0/docs/assets/README.md +34 -0
  11. anchor_kb-0.2.0/pyproject.toml +110 -0
  12. anchor_kb-0.2.0/scripts/dev.sh +16 -0
  13. anchor_kb-0.2.0/src/anchor/__init__.py +8 -0
  14. anchor_kb-0.2.0/src/anchor/__main__.py +5 -0
  15. anchor_kb-0.2.0/src/anchor/adapters/__init__.py +0 -0
  16. anchor_kb-0.2.0/src/anchor/adapters/cli/__init__.py +0 -0
  17. anchor_kb-0.2.0/src/anchor/adapters/cli/extensions.py +301 -0
  18. anchor_kb-0.2.0/src/anchor/adapters/cli/install.py +234 -0
  19. anchor_kb-0.2.0/src/anchor/adapters/cli/main.py +1517 -0
  20. anchor_kb-0.2.0/src/anchor/adapters/http/__init__.py +0 -0
  21. anchor_kb-0.2.0/src/anchor/adapters/http/app.py +135 -0
  22. anchor_kb-0.2.0/src/anchor/adapters/http/deps.py +25 -0
  23. anchor_kb-0.2.0/src/anchor/adapters/http/routers/__init__.py +0 -0
  24. anchor_kb-0.2.0/src/anchor/adapters/http/routers/edges.py +45 -0
  25. anchor_kb-0.2.0/src/anchor/adapters/http/routers/nodes.py +68 -0
  26. anchor_kb-0.2.0/src/anchor/adapters/http/routers/sse.py +46 -0
  27. anchor_kb-0.2.0/src/anchor/adapters/http/routers/workspaces.py +239 -0
  28. anchor_kb-0.2.0/src/anchor/adapters/http/schemas.py +111 -0
  29. anchor_kb-0.2.0/src/anchor/adapters/mcp/__init__.py +0 -0
  30. anchor_kb-0.2.0/src/anchor/adapters/mcp/handlers_canvas.py +519 -0
  31. anchor_kb-0.2.0/src/anchor/adapters/mcp/server.py +198 -0
  32. anchor_kb-0.2.0/src/anchor/adapters/mcp/stdio_main.py +106 -0
  33. anchor_kb-0.2.0/src/anchor/core/__init__.py +0 -0
  34. anchor_kb-0.2.0/src/anchor/core/clock.py +27 -0
  35. anchor_kb-0.2.0/src/anchor/core/docs/__init__.py +0 -0
  36. anchor_kb-0.2.0/src/anchor/core/docs/tags.py +67 -0
  37. anchor_kb-0.2.0/src/anchor/core/events/__init__.py +28 -0
  38. anchor_kb-0.2.0/src/anchor/core/events/canvas.py +114 -0
  39. anchor_kb-0.2.0/src/anchor/core/events/envelope.py +27 -0
  40. anchor_kb-0.2.0/src/anchor/core/ids.py +67 -0
  41. anchor_kb-0.2.0/src/anchor/core/ports/__init__.py +13 -0
  42. anchor_kb-0.2.0/src/anchor/core/ports/event_bus.py +14 -0
  43. anchor_kb-0.2.0/src/anchor/core/ports/snapshot.py +58 -0
  44. anchor_kb-0.2.0/src/anchor/core/ports/workspace_store.py +23 -0
  45. anchor_kb-0.2.0/src/anchor/core/services/__init__.py +0 -0
  46. anchor_kb-0.2.0/src/anchor/core/services/workspace_service.py +551 -0
  47. anchor_kb-0.2.0/src/anchor/core/upload_safety.py +88 -0
  48. anchor_kb-0.2.0/src/anchor/core/workspace/__init__.py +23 -0
  49. anchor_kb-0.2.0/src/anchor/core/workspace/align.py +150 -0
  50. anchor_kb-0.2.0/src/anchor/core/workspace/edges.py +31 -0
  51. anchor_kb-0.2.0/src/anchor/core/workspace/layout.py +221 -0
  52. anchor_kb-0.2.0/src/anchor/core/workspace/node_types.py +81 -0
  53. anchor_kb-0.2.0/src/anchor/core/workspace/nodes.py +47 -0
  54. anchor_kb-0.2.0/src/anchor/core/workspace/reducer.py +110 -0
  55. anchor_kb-0.2.0/src/anchor/core/workspace/workspace.py +117 -0
  56. anchor_kb-0.2.0/src/anchor/extensions/__init__.py +0 -0
  57. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/__init__.py +0 -0
  58. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/adapters/__init__.py +0 -0
  59. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/adapters/http/__init__.py +0 -0
  60. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/adapters/http/cad_routes.py +118 -0
  61. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/core/__init__.py +0 -0
  62. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/core/events.py +30 -0
  63. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/core/ports.py +34 -0
  64. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/core/schemas.py +108 -0
  65. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/core/services.py +129 -0
  66. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/extension.py +130 -0
  67. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/infra/__init__.py +0 -0
  68. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/infra/fs_store.py +80 -0
  69. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/infra/memory_store.py +37 -0
  70. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/infra/naive_inspector.py +65 -0
  71. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/infra/trimesh_inspector.py +79 -0
  72. anchor_kb-0.2.0/src/anchor/extensions/anchor_cad/mcp_handlers.py +79 -0
  73. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/__init__.py +0 -0
  74. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/adapters/__init__.py +0 -0
  75. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/adapters/http/__init__.py +0 -0
  76. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/adapters/http/fmu_routes.py +111 -0
  77. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/core/__init__.py +0 -0
  78. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/core/events.py +43 -0
  79. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/core/ports.py +54 -0
  80. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/core/schemas.py +128 -0
  81. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/core/services.py +135 -0
  82. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/extension.py +131 -0
  83. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/infra/__init__.py +0 -0
  84. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/infra/fake_runtime.py +70 -0
  85. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/infra/fmpy_runtime.py +123 -0
  86. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/infra/fs_store.py +101 -0
  87. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/infra/memory_store.py +60 -0
  88. anchor_kb-0.2.0/src/anchor/extensions/anchor_fmus/mcp_handlers.py +112 -0
  89. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/__init__.py +0 -0
  90. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/adapters/__init__.py +0 -0
  91. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/adapters/http/__init__.py +0 -0
  92. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/adapters/http/documents.py +209 -0
  93. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/adapters/http/upload.py +89 -0
  94. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/adapters/mcp/__init__.py +0 -0
  95. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/__init__.py +0 -0
  96. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/events.py +68 -0
  97. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/ingest/__init__.py +0 -0
  98. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/ports/__init__.py +0 -0
  99. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/ports/doc_store.py +58 -0
  100. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/ports/embedder.py +8 -0
  101. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/ports/md_polisher.py +16 -0
  102. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/ports/pdf_extractor.py +13 -0
  103. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/ports/pdf_renderer.py +21 -0
  104. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/ports/region_extractor.py +17 -0
  105. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/ports/synopsis_renderer.py +30 -0
  106. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/search.py +54 -0
  107. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/services.py +334 -0
  108. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/silver.py +373 -0
  109. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/core/synopsis.py +276 -0
  110. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/__init__.py +0 -0
  111. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/fs_doc_store.py +208 -0
  112. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/llm/__init__.py +0 -0
  113. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/llm/local_sentence_transformer_embedder.py +45 -0
  114. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/llm/openai_embedder.py +21 -0
  115. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/llm/openai_md_polisher.py +48 -0
  116. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/llm/openai_region_extractor.py +59 -0
  117. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/memory_doc_store.py +106 -0
  118. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/pdf/__init__.py +0 -0
  119. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/pdf/docling_extractor.py +76 -0
  120. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/pdf/pymupdf_renderer.py +56 -0
  121. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/infra/synopsis_renderers.py +179 -0
  122. anchor_kb-0.2.0/src/anchor/extensions/anchor_pdfs/mcp_handlers.py +330 -0
  123. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/README.md +58 -0
  124. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/__init__.py +0 -0
  125. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/adapters/__init__.py +0 -0
  126. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/adapters/http/__init__.py +0 -0
  127. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/adapters/http/sysml_routes.py +57 -0
  128. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/core/__init__.py +0 -0
  129. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/core/events.py +32 -0
  130. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/core/ports.py +42 -0
  131. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/core/schemas.py +195 -0
  132. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/core/services.py +187 -0
  133. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/extension.py +119 -0
  134. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/__init__.py +0 -0
  135. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/canvas_layout.py +138 -0
  136. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/canvas_mapper.py +252 -0
  137. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/canvas_resolver.py +183 -0
  138. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/lexer.py +239 -0
  139. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/lexer_tables.py +145 -0
  140. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/parser.py +153 -0
  141. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/parser_grammar.py +264 -0
  142. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/parser_helpers.py +291 -0
  143. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/infra/parser_requirements.py +125 -0
  144. anchor_kb-0.2.0/src/anchor/extensions/anchor_sysml/mcp_handlers.py +83 -0
  145. anchor_kb-0.2.0/src/anchor/infra/__init__.py +0 -0
  146. anchor_kb-0.2.0/src/anchor/infra/bus/__init__.py +0 -0
  147. anchor_kb-0.2.0/src/anchor/infra/bus/event_tailer.py +116 -0
  148. anchor_kb-0.2.0/src/anchor/infra/bus/memory_bus.py +53 -0
  149. anchor_kb-0.2.0/src/anchor/infra/bus/replay.py +67 -0
  150. anchor_kb-0.2.0/src/anchor/infra/config.py +53 -0
  151. anchor_kb-0.2.0/src/anchor/infra/locks.py +18 -0
  152. anchor_kb-0.2.0/src/anchor/infra/snapshot/__init__.py +3 -0
  153. anchor_kb-0.2.0/src/anchor/infra/snapshot/headless_chromium_snapshotter.py +120 -0
  154. anchor_kb-0.2.0/src/anchor/infra/stores/__init__.py +0 -0
  155. anchor_kb-0.2.0/src/anchor/infra/stores/fs_workspace_store.py +161 -0
  156. anchor_kb-0.2.0/src/anchor/infra/stores/memory_stores.py +9 -0
  157. anchor_kb-0.2.0/src/anchor/infra/stores/memory_workspace_store.py +63 -0
  158. anchor_kb-0.2.0/tests/__init__.py +0 -0
  159. anchor_kb-0.2.0/tests/adapters/__init__.py +0 -0
  160. anchor_kb-0.2.0/tests/adapters/test_cli_demo.py +101 -0
  161. anchor_kb-0.2.0/tests/adapters/test_cli_extensions.py +153 -0
  162. anchor_kb-0.2.0/tests/adapters/test_cli_install.py +91 -0
  163. anchor_kb-0.2.0/tests/adapters/test_http_workspace_snapshot.py +88 -0
  164. anchor_kb-0.2.0/tests/adapters/test_http_workspaces.py +339 -0
  165. anchor_kb-0.2.0/tests/adapters/test_mcp_canvas_snapshot.py +103 -0
  166. anchor_kb-0.2.0/tests/adapters/test_mcp_canvas_tools.py +367 -0
  167. anchor_kb-0.2.0/tests/core/__init__.py +0 -0
  168. anchor_kb-0.2.0/tests/core/test_align.py +156 -0
  169. anchor_kb-0.2.0/tests/core/test_ingest_service.py +88 -0
  170. anchor_kb-0.2.0/tests/core/test_layout.py +173 -0
  171. anchor_kb-0.2.0/tests/core/test_node_types_registry.py +106 -0
  172. anchor_kb-0.2.0/tests/core/test_silver_bbox_helpers.py +68 -0
  173. anchor_kb-0.2.0/tests/core/test_silver_build_index.py +78 -0
  174. anchor_kb-0.2.0/tests/core/test_silver_render.py +89 -0
  175. anchor_kb-0.2.0/tests/core/test_tags.py +64 -0
  176. anchor_kb-0.2.0/tests/core/test_workspace_align.py +137 -0
  177. anchor_kb-0.2.0/tests/core/test_workspace_apply.py +168 -0
  178. anchor_kb-0.2.0/tests/core/test_workspace_organize.py +241 -0
  179. anchor_kb-0.2.0/tests/core/test_workspace_service.py +300 -0
  180. anchor_kb-0.2.0/tests/core/test_workspace_slug_validation.py +117 -0
  181. anchor_kb-0.2.0/tests/core/test_workspace_snapshot.py +73 -0
  182. anchor_kb-0.2.0/tests/core/test_workspace_sub_canvas.py +89 -0
  183. anchor_kb-0.2.0/tests/extensions/__init__.py +0 -0
  184. anchor_kb-0.2.0/tests/extensions/anchor_cad/__init__.py +0 -0
  185. anchor_kb-0.2.0/tests/extensions/anchor_cad/test_service.py +130 -0
  186. anchor_kb-0.2.0/tests/extensions/anchor_sysml/__init__.py +0 -0
  187. anchor_kb-0.2.0/tests/extensions/anchor_sysml/fixtures/drone_base_architecture.sysml +52 -0
  188. anchor_kb-0.2.0/tests/extensions/anchor_sysml/fixtures/lkh_pump.sysml +47 -0
  189. anchor_kb-0.2.0/tests/extensions/anchor_sysml/fixtures/mining_frigate.sysml +94 -0
  190. anchor_kb-0.2.0/tests/extensions/anchor_sysml/test_canvas_mapper.py +161 -0
  191. anchor_kb-0.2.0/tests/extensions/anchor_sysml/test_lexer.py +91 -0
  192. anchor_kb-0.2.0/tests/extensions/anchor_sysml/test_parser.py +201 -0
  193. anchor_kb-0.2.0/tests/extensions/anchor_sysml/test_service.py +128 -0
  194. anchor_kb-0.2.0/tests/extensions/test_fmu_extension.py +265 -0
  195. anchor_kb-0.2.0/tests/fixtures/__init__.py +0 -0
  196. anchor_kb-0.2.0/tests/fixtures/fakes.py +121 -0
  197. anchor_kb-0.2.0/tests/fixtures/services.py +59 -0
  198. anchor_kb-0.2.0/tests/fixtures/tiny.png +0 -0
  199. anchor_kb-0.2.0/tests/infra/__init__.py +0 -0
  200. anchor_kb-0.2.0/tests/infra/test_fs_doc_store.py +114 -0
  201. anchor_kb-0.2.0/tests/infra/test_fs_workspace_store.py +108 -0
  202. anchor_kb-0.2.0/tests/infra/test_headless_chromium_snapshotter.py +93 -0
  203. anchor_kb-0.2.0/tests/infra/test_memory_bus.py +61 -0
  204. anchor_kb-0.2.0/web/.gitignore +3 -0
  205. anchor_kb-0.2.0/web/components.json +18 -0
  206. anchor_kb-0.2.0/web/dist/assets/index-Ce48iBrU.js +4457 -0
  207. anchor_kb-0.2.0/web/dist/assets/index-DlLwITRi.css +1 -0
  208. anchor_kb-0.2.0/web/dist/index.html +13 -0
  209. anchor_kb-0.2.0/web/eslint.config.js +52 -0
  210. anchor_kb-0.2.0/web/index.html +12 -0
  211. anchor_kb-0.2.0/web/package.json +62 -0
  212. anchor_kb-0.2.0/web/pnpm-lock.yaml +5537 -0
  213. anchor_kb-0.2.0/web/postcss.config.mjs +6 -0
  214. anchor_kb-0.2.0/web/src/App.tsx +22 -0
  215. anchor_kb-0.2.0/web/src/api/cad.ts +45 -0
  216. anchor_kb-0.2.0/web/src/api/canvases.ts +157 -0
  217. anchor_kb-0.2.0/web/src/api/client.ts +38 -0
  218. anchor_kb-0.2.0/web/src/api/documents.ts +46 -0
  219. anchor_kb-0.2.0/web/src/api/fmu.ts +31 -0
  220. anchor_kb-0.2.0/web/src/canvas/ActivityToast.tsx +37 -0
  221. anchor_kb-0.2.0/web/src/canvas/CanvasGraph.tsx +1167 -0
  222. anchor_kb-0.2.0/web/src/canvas/DirectionalConnectors.tsx +700 -0
  223. anchor_kb-0.2.0/web/src/canvas/EdgeContextMenu.tsx +290 -0
  224. anchor_kb-0.2.0/web/src/canvas/EdgeContextToolbar.tsx +496 -0
  225. anchor_kb-0.2.0/web/src/canvas/FillPicker.tsx +34 -0
  226. anchor_kb-0.2.0/web/src/canvas/NodeContextMenu.tsx +408 -0
  227. anchor_kb-0.2.0/web/src/canvas/NodeContextToolbar.tsx +615 -0
  228. anchor_kb-0.2.0/web/src/canvas/PaintGhost.test.tsx +153 -0
  229. anchor_kb-0.2.0/web/src/canvas/PaintGhost.tsx +147 -0
  230. anchor_kb-0.2.0/web/src/canvas/PlaceholderChip.tsx +21 -0
  231. anchor_kb-0.2.0/web/src/canvas/QuickAddPopover.tsx +301 -0
  232. anchor_kb-0.2.0/web/src/canvas/StrokePicker.tsx +33 -0
  233. anchor_kb-0.2.0/web/src/canvas/Swatches.tsx +125 -0
  234. anchor_kb-0.2.0/web/src/canvas/TextPicker.tsx +194 -0
  235. anchor_kb-0.2.0/web/src/canvas/WaypointEditor.tsx +203 -0
  236. anchor_kb-0.2.0/web/src/canvas/align.test.ts +121 -0
  237. anchor_kb-0.2.0/web/src/canvas/align.ts +150 -0
  238. anchor_kb-0.2.0/web/src/canvas/breadcrumb.ts +89 -0
  239. anchor_kb-0.2.0/web/src/canvas/colors.test.ts +121 -0
  240. anchor_kb-0.2.0/web/src/canvas/colors.ts +179 -0
  241. anchor_kb-0.2.0/web/src/canvas/edges/AnchoredEdge.tsx +133 -0
  242. anchor_kb-0.2.0/web/src/canvas/edges/EdgeMarkerDefs.tsx +144 -0
  243. anchor_kb-0.2.0/web/src/canvas/edges/FloatingEdge.tsx +151 -0
  244. anchor_kb-0.2.0/web/src/canvas/edges/RoutedEdge.tsx +213 -0
  245. anchor_kb-0.2.0/web/src/canvas/edges/edge-mode.test.ts +128 -0
  246. anchor_kb-0.2.0/web/src/canvas/edges/edge-mode.ts +108 -0
  247. anchor_kb-0.2.0/web/src/canvas/edges/edge-style.test.ts +84 -0
  248. anchor_kb-0.2.0/web/src/canvas/edges/edge-style.ts +129 -0
  249. anchor_kb-0.2.0/web/src/canvas/edges/floatingGeometry.ts +100 -0
  250. anchor_kb-0.2.0/web/src/canvas/edges/markers.test.ts +81 -0
  251. anchor_kb-0.2.0/web/src/canvas/edges/markers.ts +152 -0
  252. anchor_kb-0.2.0/web/src/canvas/icons/index.tsx +151 -0
  253. anchor_kb-0.2.0/web/src/canvas/placeholder.ts +36 -0
  254. anchor_kb-0.2.0/web/src/canvas/primitives/DocumentPrimitive.tsx +391 -0
  255. anchor_kb-0.2.0/web/src/canvas/primitives/Model3DPrimitive.tsx +152 -0
  256. anchor_kb-0.2.0/web/src/canvas/primitives/SubCanvasPrimitive.test.tsx +153 -0
  257. anchor_kb-0.2.0/web/src/canvas/primitives/SubCanvasPrimitive.tsx +173 -0
  258. anchor_kb-0.2.0/web/src/canvas/primitives/SysmlBlockPrimitive.tsx +222 -0
  259. anchor_kb-0.2.0/web/src/canvas/primitives/SysmlPackagePrimitive.tsx +70 -0
  260. anchor_kb-0.2.0/web/src/canvas/primitives/SysmlRequirementPrimitive.tsx +118 -0
  261. anchor_kb-0.2.0/web/src/canvas/primitives/TablePrimitive.test.tsx +127 -0
  262. anchor_kb-0.2.0/web/src/canvas/primitives/TablePrimitive.tsx +551 -0
  263. anchor_kb-0.2.0/web/src/canvas/primitives/_shared/Compartment.tsx +33 -0
  264. anchor_kb-0.2.0/web/src/canvas/primitives/viewers/PageWithBboxViewer.tsx +343 -0
  265. anchor_kb-0.2.0/web/src/canvas/registry.ts +335 -0
  266. anchor_kb-0.2.0/web/src/canvas/shapes/AreaNode.tsx +151 -0
  267. anchor_kb-0.2.0/web/src/canvas/shapes/ConceptNode.test.tsx +251 -0
  268. anchor_kb-0.2.0/web/src/canvas/shapes/ConceptNode.tsx +118 -0
  269. anchor_kb-0.2.0/web/src/canvas/shapes/EntityNode.tsx +100 -0
  270. anchor_kb-0.2.0/web/src/canvas/shapes/FactNode.tsx +120 -0
  271. anchor_kb-0.2.0/web/src/canvas/shapes/FunnelNode.test.tsx +118 -0
  272. anchor_kb-0.2.0/web/src/canvas/shapes/FunnelNode.tsx +152 -0
  273. anchor_kb-0.2.0/web/src/canvas/shapes/NoteNode.tsx +166 -0
  274. anchor_kb-0.2.0/web/src/canvas/useInlineField.ts +286 -0
  275. anchor_kb-0.2.0/web/src/canvas/useInlineLabel.ts +35 -0
  276. anchor_kb-0.2.0/web/src/canvas/useLiveResize.ts +70 -0
  277. anchor_kb-0.2.0/web/src/canvas/useWorkspacesList.ts +88 -0
  278. anchor_kb-0.2.0/web/src/components/ChatPanel.tsx +86 -0
  279. anchor_kb-0.2.0/web/src/components/ui/button.tsx +52 -0
  280. anchor_kb-0.2.0/web/src/components/ui/context-menu.tsx +146 -0
  281. anchor_kb-0.2.0/web/src/components/ui/dropdown-menu.tsx +101 -0
  282. anchor_kb-0.2.0/web/src/components/ui/popover.tsx +47 -0
  283. anchor_kb-0.2.0/web/src/components/ui/sheet.tsx +143 -0
  284. anchor_kb-0.2.0/web/src/components/ui/tabs.tsx +77 -0
  285. anchor_kb-0.2.0/web/src/components/ui/tooltip.tsx +40 -0
  286. anchor_kb-0.2.0/web/src/index.css +67 -0
  287. anchor_kb-0.2.0/web/src/lib/cn.ts +6 -0
  288. anchor_kb-0.2.0/web/src/main.tsx +14 -0
  289. anchor_kb-0.2.0/web/src/pages/CanvasListPage.tsx +80 -0
  290. anchor_kb-0.2.0/web/src/pages/CanvasPage.tsx +130 -0
  291. anchor_kb-0.2.0/web/src/pages/CanvasTree.test.tsx +145 -0
  292. anchor_kb-0.2.0/web/src/pages/CanvasTree.tsx +241 -0
  293. anchor_kb-0.2.0/web/src/pages/MonitorPage.tsx +41 -0
  294. anchor_kb-0.2.0/web/src/realtime/sseClient.ts +60 -0
  295. anchor_kb-0.2.0/web/src/search/embedder.test.ts +156 -0
  296. anchor_kb-0.2.0/web/src/search/embedder.ts +163 -0
  297. anchor_kb-0.2.0/web/src/search/embedder.worker.ts +95 -0
  298. anchor_kb-0.2.0/web/src/search/searchClient.ts +48 -0
  299. anchor_kb-0.2.0/web/src/shell/CanvasShell.tsx +57 -0
  300. anchor_kb-0.2.0/web/src/shell/CanvasesPanel.test.tsx +151 -0
  301. anchor_kb-0.2.0/web/src/shell/CanvasesPanel.tsx +185 -0
  302. anchor_kb-0.2.0/web/src/shell/LeftToolRail.tsx +596 -0
  303. anchor_kb-0.2.0/web/src/shell/Library.tsx +160 -0
  304. anchor_kb-0.2.0/web/src/shell/LibraryDrawer.tsx +78 -0
  305. anchor_kb-0.2.0/web/src/shell/PropertiesPanel.dispatch.test.ts +57 -0
  306. anchor_kb-0.2.0/web/src/shell/PropertiesPanel.dispatch.ts +40 -0
  307. anchor_kb-0.2.0/web/src/shell/PropertiesPanel.tsx +112 -0
  308. anchor_kb-0.2.0/web/src/shell/editors/DocumentReadonly.tsx +60 -0
  309. anchor_kb-0.2.0/web/src/shell/editors/JsonEscapeHatch.tsx +86 -0
  310. anchor_kb-0.2.0/web/src/shell/editors/LabelEditor.tsx +49 -0
  311. anchor_kb-0.2.0/web/src/shell/editors/MarkdownEditor.tsx +57 -0
  312. anchor_kb-0.2.0/web/src/shell/editors/OrganizeEditor.test.tsx +121 -0
  313. anchor_kb-0.2.0/web/src/shell/editors/OrganizeEditor.tsx +182 -0
  314. anchor_kb-0.2.0/web/src/shell/editors/SpecEditor.tsx +157 -0
  315. anchor_kb-0.2.0/web/src/shell/editors/_types.ts +20 -0
  316. anchor_kb-0.2.0/web/src/shell/editors/_usePatchNode.ts +61 -0
  317. anchor_kb-0.2.0/web/src/stores/canvasStore.test.ts +168 -0
  318. anchor_kb-0.2.0/web/src/stores/canvasStore.ts +275 -0
  319. anchor_kb-0.2.0/web/src/stores/uiStore.test.ts +178 -0
  320. anchor_kb-0.2.0/web/src/stores/uiStore.ts +226 -0
  321. anchor_kb-0.2.0/web/tsconfig.json +24 -0
  322. anchor_kb-0.2.0/web/vite.config.ts +43 -0
  323. anchor_kb-0.2.0/web/vitest.config.ts +13 -0
@@ -0,0 +1,67 @@
1
+ # Build / cache
2
+ __pycache__/
3
+ *.pyc
4
+ .pytest_cache/
5
+ .import_linter_cache/
6
+ .venv/
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ *.tsbuildinfo
11
+
12
+ # Frontend
13
+ node_modules/
14
+ web/dist/
15
+
16
+ # User data — never tracked, lives in --data-dir / ANCHOR_DATA_DIR
17
+ data/
18
+ # Note: top-level docs/ IS tracked — the architecture documentation lives
19
+ # there. User-data canvases/ live inside `data/` which is already ignored.
20
+
21
+ # Local config / env files — never commit credentials
22
+ .env
23
+ .env.local
24
+ .env.*.local
25
+
26
+ # Editor
27
+ .vscode/
28
+ .idea/
29
+
30
+ # OS
31
+ .DS_Store
32
+ .playwright-cli/
33
+ .next/
34
+
35
+ # Legacy v1 working-tree leftovers at the repo root. These directories /
36
+ # files existed before v2 was promoted; they survive locally as untracked
37
+ # entries after pulling this commit. Full history is on the
38
+ # `archive/pre-v2` branch / `pre-v2-cutoff` tag.
39
+ #
40
+ # Leading slashes restrict the patterns to the repo root so they don't
41
+ # shadow legitimate files of the same name inside `web/`.
42
+ /backend/
43
+ /backend2/
44
+ /packages/
45
+ /paperx/
46
+ /paper/
47
+ /posters/
48
+ /public/
49
+ /mydata/
50
+ /uploads/
51
+ /tmp/
52
+ /Untitled/
53
+ /v2/
54
+ /src/components/
55
+ /src/app/
56
+ /2026-*-hi.txt
57
+ /output_bboxes.txt
58
+ /metadata.json
59
+ /package.json
60
+ /package-lock.json
61
+ /pnpm-lock.yaml
62
+ /postcss.config.cjs
63
+ /tailwind.config.cjs
64
+ /tsconfig.json
65
+ /next.config.ts
66
+ /next-env.d.ts
67
+ /todos.md
@@ -0,0 +1,67 @@
1
+ [importlinter]
2
+ root_package = anchor
3
+ include_external_packages = True
4
+
5
+ [importlinter:contract:layered]
6
+ name = Hexagonal layering — adapters → infra → core
7
+ type = layers
8
+ layers =
9
+ anchor.adapters
10
+ anchor.infra
11
+ anchor.core
12
+
13
+ [importlinter:contract:core_purity]
14
+ name = Core has no I/O / framework dependencies
15
+ type = forbidden
16
+ source_modules =
17
+ anchor.core
18
+ forbidden_modules =
19
+ httpx
20
+ fastapi
21
+ openai
22
+ mcp
23
+ pymupdf
24
+ docling
25
+ uvicorn
26
+ starlette
27
+ typer
28
+ aiofiles
29
+ sse_starlette
30
+
31
+ [importlinter:contract:infra_no_transport]
32
+ name = Infra implements ports, not transport
33
+ type = forbidden
34
+ source_modules =
35
+ anchor.infra
36
+ forbidden_modules =
37
+ fastapi
38
+ mcp
39
+ uvicorn
40
+ starlette
41
+ typer
42
+ sse_starlette
43
+
44
+ [importlinter:contract:canvas_no_extensions]
45
+ name = Canvas primitive does not depend on extensions
46
+ type = forbidden
47
+ source_modules =
48
+ anchor.core
49
+ anchor.infra
50
+ forbidden_modules =
51
+ anchor.extensions
52
+
53
+ [importlinter:contract:extension_layered]
54
+ name = Extensions follow the same layering as the canvas
55
+ type = layers
56
+ layers =
57
+ anchor.extensions.anchor_pdfs.adapters
58
+ anchor.extensions.anchor_pdfs.infra
59
+ anchor.extensions.anchor_pdfs.core
60
+
61
+ [importlinter:contract:anchor_sysml_layered]
62
+ name = anchor_sysml: layered, anchor_sysml.adapters → anchor_sysml.infra → anchor_sysml.core
63
+ type = layers
64
+ layers =
65
+ anchor.extensions.anchor_sysml.adapters
66
+ anchor.extensions.anchor_sysml.infra
67
+ anchor.extensions.anchor_sysml.core
@@ -0,0 +1,283 @@
1
+ # Anchor extensions — the contract
2
+
3
+ Anchor's canvas primitive is domain-agnostic. **Extensions** layer specific
4
+ ingestion pipelines, node types, edge styles, and UI components on top of it.
5
+ Today the PDF medallion pipeline (Docling + VLM region extraction + spec
6
+ tables with page+bbox provenance) lives inside the same wheel as the canvas;
7
+ this document describes the contract every extension follows so future
8
+ extensions — transcription, code regions, web pages, your own — can ship
9
+ either in-tree or as separate `anchor-canvas-*` packages.
10
+
11
+ ---
12
+
13
+ ## What an extension provides
14
+
15
+ ```python
16
+ from anchor.canvas import CanvasCore, NodeType, ToolDef, SourceRefKind
17
+
18
+ class AnchorExtension(Protocol):
19
+ NAME: str # machine identifier, used as namespace prefix.
20
+ # e.g. "anchor_pdfs", "anchor_transcribe"
21
+ DISPLAY_NAME: str # human-friendly label for UI
22
+ VERSION: str # extension version (semver)
23
+ REQUIRES_CANVAS: str # canvas-core compat range, e.g. ">=0.2,<0.3"
24
+
25
+ def configure(self, canvas: CanvasCore) -> None:
26
+ """Called once at canvas startup. Register everything here."""
27
+ canvas.node_types.register_many([
28
+ NodeType("pdf:document", data_schema=DocumentData),
29
+ NodeType("pdf:spec_table", data_schema=SpecTableData),
30
+ ...
31
+ ])
32
+ canvas.source_ref_kinds.register(
33
+ SourceRefKind("pdf-page-bbox", schema=PdfPageBboxRef,
34
+ renderer_hint="open_pdf_at_bbox"),
35
+ )
36
+ canvas.mcp_tools.register_namespace("pdf", [
37
+ ToolDef("ingest", schema=...),
38
+ ToolDef("list_documents", schema=...),
39
+ ...
40
+ ])
41
+ canvas.http.mount_router("/api/pdfs", router)
42
+ canvas.events.register([DocBronzed, DocSilvered, DocIngested, ...])
43
+ canvas.services.provide("pdfs.ingest_service", IngestService(...))
44
+ ```
45
+
46
+ **Frontend half** (parallel contract for the React app):
47
+
48
+ ```typescript
49
+ import { registerExtension } from "@anchor/canvas/extensions";
50
+ import { SpecTableNode, DocumentNode } from "./nodes";
51
+
52
+ registerExtension({
53
+ name: "anchor_pdfs",
54
+ nodeTypes: {
55
+ "pdf:document": DocumentNode,
56
+ "pdf:spec_table": SpecTableNode,
57
+ },
58
+ edgeStyles: {
59
+ "pdf:evidence": { stroke: "#FF8E2B", dasharray: "4 4" },
60
+ },
61
+ sourceRefHandlers: {
62
+ "pdf-page-bbox": openPdfAtBbox,
63
+ },
64
+ });
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Naming convention
70
+
71
+ - **Node types:** `<extension_name_short>:<type>` (e.g. `pdf:spec_table`,
72
+ `transcribe:segment`, `code:region`). The `:` prefix prevents collisions.
73
+ - **MCP tools:** prefixed namespaces (`pdf.ingest`, `pdf.list_documents`,
74
+ `transcribe.ingest_audio`).
75
+ - **HTTP routes:** `/api/<extension_short>/...` (`/api/pdfs/...`,
76
+ `/api/transcribe/...`).
77
+ - **Source-ref kinds:** `<short>-<address-shape>` (`pdf-page-bbox`,
78
+ `audio-timestamp`, `code-line-range`).
79
+ - **On-disk substrates:** `data/<short>/...` (`data/bronze/`, `data/silver/`,
80
+ `data/gold/` for PDFs; would be `data/transcripts/` for transcription).
81
+
82
+ ---
83
+
84
+ ## What the canvas core provides
85
+
86
+ The canvas core is the **substrate**. Extensions consume:
87
+
88
+ ```
89
+ core/
90
+ workspace/ # Workspace aggregate, Node, Edge, reducer, validator
91
+ events/canvas.py # NodeAdded, NodeMoved, EdgeAdded, …
92
+ ports/ # WorkspaceStore, EventBus, AssetStore
93
+ services/ # WorkspaceService — generic CRUD over canvases
94
+
95
+ infra/
96
+ stores/fs_workspace_store.py
97
+ bus/memory_bus.py
98
+
99
+ adapters/
100
+ http/routers/{workspaces, nodes, edges, sse}.py
101
+ mcp/{server, handlers_canvas, stdio_main}.py
102
+ cli/main.py # the `anchor` binary, with extension subcommands
103
+
104
+ Built-in node types: concept, entity, fact, area, note
105
+ Built-in edge types: floating, anchored
106
+ ```
107
+
108
+ Every extension can use these without re-inventing them. Extensions only
109
+ add what's specific to their domain.
110
+
111
+ ---
112
+
113
+ ## Three ways to ship an extension
114
+
115
+ ### 1. In-tree (`extensions/` folder, recommended for the curated set)
116
+
117
+ ```
118
+ v2/extensions/
119
+ └── anchor_pdfs/
120
+ ├── pyproject.toml
121
+ ├── src/anchor_pdfs/
122
+ │ ├── extension.py # AnchorExtension implementation
123
+ │ ├── core/, infra/, adapters/ # backend code
124
+ │ └── ...
125
+ ├── web/
126
+ │ ├── package.json
127
+ │ └── src/index.ts # registerExtension(...)
128
+ └── tests/
129
+ ```
130
+
131
+ Discovery: the canvas runner walks `extensions/` at startup, imports each
132
+ `extension:Extension` class, calls `configure(canvas)`. Frontend imports each
133
+ `extensions/*/web/dist/index.js` at canvas mount.
134
+
135
+ **Status today:** PDF ingestion lives inside `src/anchor/` directly, not yet
136
+ extracted into `extensions/anchor_pdfs/`. The split lands as a refactor pass
137
+ once the API surface is stable. Use `extensions/` for genuinely new
138
+ extensions you'd contribute upstream.
139
+
140
+ ### 2. Out-of-tree pip-installable package
141
+
142
+ Anyone publishes their own `anchor-canvas-<name>` package to PyPI:
143
+
144
+ ```toml
145
+ # my-anchor-ext/pyproject.toml
146
+ [project]
147
+ name = "anchor-canvas-mermaid"
148
+ dependencies = ["anchor-canvas>=0.2"]
149
+
150
+ [project.entry-points."anchor.extensions"]
151
+ mermaid = "anchor_canvas_mermaid.extension:MermaidExtension"
152
+ ```
153
+
154
+ Discovery: the canvas runner reads Python entry points
155
+ (`importlib.metadata.entry_points(group='anchor.extensions')`) and loads each
156
+ registered class.
157
+
158
+ ```bash
159
+ uv tool install --with anchor-canvas-mermaid anchor-canvas
160
+ anchor serve --data-dir ~/anchor-data # picks up mermaid automatically
161
+ ```
162
+
163
+ ### 3. Local / editable (for extension developers)
164
+
165
+ Set `ANCHOR_EXTENSIONS_PATH` to a colon-separated list of directories
166
+ containing extension source code. Canvas runner walks each path, finds the
167
+ `extension.py` entry point, loads the extension without packaging.
168
+
169
+ ```bash
170
+ export ANCHOR_EXTENSIONS_PATH=~/dev/my-ext:~/dev/another-ext
171
+ anchor serve --data-dir ~/anchor-data
172
+ ```
173
+
174
+ Useful for iterating on a new extension without `pip install -e .` round-trips.
175
+
176
+ ---
177
+
178
+ ## Per-project extension pinning (planned)
179
+
180
+ For reproducible extension sets bound to a `--data-dir`:
181
+
182
+ ```toml
183
+ # ~/anchor-data/cooling-system/anchor.toml
184
+ [anchor]
185
+ canvas_version = ">=0.2,<0.3"
186
+
187
+ [[extensions]]
188
+ name = "anchor-canvas-pdfs"
189
+ version = ">=0.2"
190
+
191
+ [[extensions]]
192
+ git = "https://github.com/someone/anchor-canvas-mermaid"
193
+ ref = "v0.1"
194
+
195
+ [[extensions]]
196
+ path = "/Users/me/dev/my-custom-ext"
197
+ ```
198
+
199
+ `anchor serve --data-dir <dir>` reads `<dir>/anchor.toml`, ensures every
200
+ listed extension is available (or fails loudly with install instructions),
201
+ loads them, starts. Lands in v0.4.
202
+
203
+ ---
204
+
205
+ ## What lives in the canvas core vs. an extension
206
+
207
+ | Concern | Canvas core | Extension |
208
+ |---|---|---|
209
+ | Workspace, Node, Edge, reducer | ✓ | |
210
+ | Generic node types: concept, entity, fact, area, note | ✓ | |
211
+ | Generic edge types: floating, anchored | ✓ | |
212
+ | EventBus, SSE, WebSocket | ✓ | |
213
+ | Asset upload + serve | ✓ | |
214
+ | Screenshot mechanism (browser-as-screenshotter) | ✓ | |
215
+ | Viewport math (fit, visibility) | ✓ | |
216
+ | Lock state on nodes | ✓ | |
217
+ | `data.locked`, `data.visible`, `data.layer`, `data.opacity` | ✓ | |
218
+ | Domain-specific node types (pdf:spec_table, transcribe:segment, …) | | ✓ |
219
+ | Domain-specific schemas in `Node.data` | | ✓ |
220
+ | Domain-specific source-ref kinds | | ✓ |
221
+ | Ingestion pipelines (Docling, Whisper, tree-sitter, …) | | ✓ |
222
+ | Domain-specific React renderers | | ✓ |
223
+ | Domain-specific edge styling (e.g. `pdf:evidence` orange-dashed) | | ✓ |
224
+ | MCP tools for domain operations | | ✓ |
225
+
226
+ **The principle:** if the canvas core needs to know about a domain to
227
+ function, it doesn't belong in core. Canvas core only knows registries.
228
+
229
+ ---
230
+
231
+ ## Honest gotchas for extension authors
232
+
233
+ 1. **Frontend bundling is the harder problem.** Extensions need to ship JS
234
+ bundles that load into the canvas's React app. Today (in-tree) we glob
235
+ `extensions/*/web/src/index.ts` at build time. Out-of-tree extensions
236
+ eventually need Module Federation. We'll ship that path when there's
237
+ demand.
238
+
239
+ 2. **`Node.data` is not type-safe across the wire.** Validators in the
240
+ `NodeTypeRegistry` enforce schemas at command time, but anyone reading the
241
+ stored JSON has to revalidate. Keep your schemas backwards-compatible.
242
+
243
+ 3. **Source-ref kinds need to be unique.** If two extensions both register
244
+ `"page-bbox"` you'll get an error at startup. Always namespace
245
+ (`"pdf-page-bbox"`, not `"page-bbox"`).
246
+
247
+ 4. **Don't fight the layer rules.** Your extension's `core/` may not import
248
+ `httpx`/`fastapi`/`openai`/etc. Same hexagonal discipline applies. Run
249
+ `lint-imports` on your extension.
250
+
251
+ 5. **Test against the canvas's in-memory implementations.** The canvas
252
+ core ships `MemoryWorkspaceStore`, `MemoryDocStore`, `MemoryEventBus` —
253
+ use them in your unit tests so you don't need a real filesystem.
254
+
255
+ ---
256
+
257
+ ## Status of the contract
258
+
259
+ **Stable today:**
260
+ - Canvas core's domain model (Workspace, Node, Edge, reducer, events)
261
+ - `NodeTypeRegistry` for runtime node-type registration
262
+ - HTTP/MCP/CLI/SSE adapter shape
263
+
264
+ **In flux (will stabilise as we extract the canvas primitive):**
265
+ - The `AnchorExtension` Protocol class itself (today: implicit in how PDF
266
+ code is wired; tomorrow: an explicit class)
267
+ - Frontend `registerExtension(...)` API
268
+ - Source-ref kind registry
269
+ - Edge-style registry
270
+
271
+ **Not yet implemented but documented here:**
272
+ - Out-of-tree extension discovery via Python entry points
273
+ - `anchor.toml` per-project extension pinning
274
+ - `ANCHOR_EXTENSIONS_PATH` for editable-install paths
275
+ - `anchor extensions {list, install, remove}` CLI subcommand
276
+
277
+ If you're writing an extension *today*, your safest bet is to clone v2,
278
+ add it under `extensions/`, follow the patterns in the existing PDF code
279
+ (see `src/anchor/core/services/ingest_service.py`,
280
+ `src/anchor/adapters/mcp/handlers_ingest.py`,
281
+ `src/anchor/infra/llm/`). The contract above is the target shape; the
282
+ move from "implicit in v2" to "explicit Protocol" is a follow-up
283
+ refactor.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Christoffer Björkskog, Lamin Jatta, and contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
anchor_kb-0.2.0/OIP.md ADDED
@@ -0,0 +1,33 @@
1
+ # OIP — Open Ingestion Protocol
2
+
3
+ The OIP specification has moved to its own repository:
4
+
5
+ **📦 https://github.com/Novia-RDI-Seafaring/OIP**
6
+
7
+ That repo is the single source of truth for the protocol, manifest schema,
8
+ and discovery rules. It also ships a CLI (`uvx oip`) for validating
9
+ producer manifests and inspecting compliant on-disk trees.
10
+
11
+ ## What OIP is, in one paragraph
12
+
13
+ OIP is a small, governance-neutral specification for ingestion tools that
14
+ produce structured, source-grounded knowledge. Any tool that conforms to
15
+ OIP can be consumed by any OIP-aware application — the same way any
16
+ LSP-compliant language server works in any LSP-aware editor. Anchor is the
17
+ first reference consumer; Anchor's PDF medallion pipeline is the first
18
+ reference producer. Both can be replaced.
19
+
20
+ ## Anchor's relationship to OIP
21
+
22
+ - **Anchor's canvas** is an OIP **consumer**: it reads OIP-compliant gold
23
+ regions from disk and renders them as canvas nodes with row-level
24
+ provenance.
25
+ - **Anchor's bundled extensions** (`anchor_pdfs`, `anchor_fmus`,
26
+ `anchor_cad`, `anchor_sysml`) are OIP **producers**: each declares an
27
+ OIP manifest, writes to the OIP-fixed artefact tree, and exposes
28
+ ingest/list/get operations the canvas can discover.
29
+
30
+ For the manifest schema, the on-disk tree, the discovery rules, and the
31
+ list of source-kinds, **read the OIP repo's spec**. This file used to
32
+ contain a draft of that spec; the draft is now superseded by the
33
+ versioned spec in the OIP repo and is no longer maintained here.