@jlongo78/agent-spaces 0.7.6 → 0.8.0

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 (800) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +6 -0
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/required-server-files.json +19 -19
  6. package/.next/standalone/.next/routes-manifest.json +38 -0
  7. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/(desktop)/admin/users/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/(desktop)/analytics/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/(desktop)/cortex/page/react-loadable-manifest.json +1 -1
  11. package/.next/standalone/.next/server/app/(desktop)/cortex/page.js.nft.json +1 -1
  12. package/.next/standalone/.next/server/app/(desktop)/cortex/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/(desktop)/network/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/(desktop)/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/(desktop)/projects/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/(desktop)/sessions/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/(desktop)/settings/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/(desktop)/terminal/page.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/(desktop)/terminal/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page_client-reference-manifest.js +1 -1
  24. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page_client-reference-manifest.js +1 -1
  26. package/.next/standalone/.next/server/app/(desktop)/workspaces/page_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  28. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  29. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  30. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  31. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  32. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  33. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  34. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  35. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  36. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  37. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  38. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  39. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  40. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  41. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  42. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  43. package/.next/standalone/.next/server/app/admin/analytics.html +1 -1
  44. package/.next/standalone/.next/server/app/admin/analytics.rsc +6 -7
  45. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics/__PAGE__.segment.rsc +2 -2
  46. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics.segment.rsc +1 -1
  47. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  48. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  49. package/.next/standalone/.next/server/app/admin/analytics.segments/_full.segment.rsc +6 -7
  50. package/.next/standalone/.next/server/app/admin/analytics.segments/_head.segment.rsc +1 -1
  51. package/.next/standalone/.next/server/app/admin/analytics.segments/_index.segment.rsc +2 -2
  52. package/.next/standalone/.next/server/app/admin/analytics.segments/_tree.segment.rsc +2 -2
  53. package/.next/standalone/.next/server/app/admin/users.html +1 -1
  54. package/.next/standalone/.next/server/app/admin/users.rsc +2 -2
  55. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users/__PAGE__.segment.rsc +1 -1
  56. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users.segment.rsc +1 -1
  57. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  58. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  59. package/.next/standalone/.next/server/app/admin/users.segments/_full.segment.rsc +2 -2
  60. package/.next/standalone/.next/server/app/admin/users.segments/_head.segment.rsc +1 -1
  61. package/.next/standalone/.next/server/app/admin/users.segments/_index.segment.rsc +2 -2
  62. package/.next/standalone/.next/server/app/admin/users.segments/_tree.segment.rsc +2 -2
  63. package/.next/standalone/.next/server/app/analytics.html +1 -1
  64. package/.next/standalone/.next/server/app/analytics.rsc +3 -3
  65. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics/__PAGE__.segment.rsc +2 -2
  66. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics.segment.rsc +1 -1
  67. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  68. package/.next/standalone/.next/server/app/analytics.segments/_full.segment.rsc +3 -3
  69. package/.next/standalone/.next/server/app/analytics.segments/_head.segment.rsc +1 -1
  70. package/.next/standalone/.next/server/app/analytics.segments/_index.segment.rsc +2 -2
  71. package/.next/standalone/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
  72. package/.next/standalone/.next/server/app/api/analytics/overview/route.js.nft.json +1 -1
  73. package/.next/standalone/.next/server/app/api/benchmark/lobes/route/app-paths-manifest.json +3 -0
  74. package/.next/standalone/.next/server/app/api/benchmark/lobes/route/build-manifest.json +11 -0
  75. package/.next/standalone/.next/server/app/api/benchmark/lobes/route/server-reference-manifest.json +4 -0
  76. package/.next/standalone/.next/server/app/api/benchmark/lobes/route.js +7 -0
  77. package/.next/standalone/.next/server/app/api/benchmark/lobes/route.js.map +5 -0
  78. package/.next/standalone/.next/server/app/api/benchmark/lobes/route.js.nft.json +1 -0
  79. package/.next/standalone/.next/server/app/api/benchmark/lobes/route_client-reference-manifest.js +2 -0
  80. package/.next/standalone/.next/server/app/api/benchmark/run/route/app-paths-manifest.json +3 -0
  81. package/.next/standalone/.next/server/app/api/benchmark/run/route/build-manifest.json +11 -0
  82. package/.next/standalone/.next/server/app/api/benchmark/run/route/server-reference-manifest.json +4 -0
  83. package/.next/standalone/.next/server/app/api/benchmark/run/route.js +7 -0
  84. package/.next/standalone/.next/server/app/api/benchmark/run/route.js.map +5 -0
  85. package/.next/standalone/.next/server/app/api/benchmark/run/route.js.nft.json +1 -0
  86. package/.next/standalone/.next/server/app/api/benchmark/run/route_client-reference-manifest.js +2 -0
  87. package/.next/standalone/.next/server/app/api/benchmark/runs/[id]/route/app-paths-manifest.json +3 -0
  88. package/.next/standalone/.next/server/app/api/benchmark/runs/[id]/route/build-manifest.json +11 -0
  89. package/.next/standalone/.next/server/app/api/benchmark/runs/[id]/route/server-reference-manifest.json +4 -0
  90. package/.next/standalone/.next/server/app/api/benchmark/runs/[id]/route.js +7 -0
  91. package/.next/standalone/.next/server/app/api/benchmark/runs/[id]/route.js.map +5 -0
  92. package/.next/standalone/.next/server/app/api/benchmark/runs/[id]/route.js.nft.json +1 -0
  93. package/.next/standalone/.next/server/app/api/benchmark/runs/[id]/route_client-reference-manifest.js +2 -0
  94. package/.next/standalone/.next/server/app/api/benchmark/runs/route/app-paths-manifest.json +3 -0
  95. package/.next/standalone/.next/server/app/api/benchmark/runs/route/build-manifest.json +11 -0
  96. package/.next/standalone/.next/server/app/api/benchmark/runs/route/server-reference-manifest.json +4 -0
  97. package/.next/standalone/.next/server/app/api/benchmark/runs/route.js +7 -0
  98. package/.next/standalone/.next/server/app/api/benchmark/runs/route.js.map +5 -0
  99. package/.next/standalone/.next/server/app/api/benchmark/runs/route.js.nft.json +1 -0
  100. package/.next/standalone/.next/server/app/api/benchmark/runs/route_client-reference-manifest.js +2 -0
  101. package/.next/standalone/.next/server/app/api/benchmark/status/route/app-paths-manifest.json +3 -0
  102. package/.next/standalone/.next/server/app/api/benchmark/status/route/build-manifest.json +11 -0
  103. package/.next/standalone/.next/server/app/api/benchmark/status/route/server-reference-manifest.json +4 -0
  104. package/.next/standalone/.next/server/app/api/benchmark/status/route.js +7 -0
  105. package/.next/standalone/.next/server/app/api/benchmark/status/route.js.map +5 -0
  106. package/.next/standalone/.next/server/app/api/benchmark/status/route.js.nft.json +1 -0
  107. package/.next/standalone/.next/server/app/api/benchmark/status/route_client-reference-manifest.js +2 -0
  108. package/.next/standalone/.next/server/app/api/bulk/route.js.nft.json +1 -1
  109. package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
  110. package/.next/standalone/.next/server/app/api/cortex/context/route.js.nft.json +1 -1
  111. package/.next/standalone/.next/server/app/api/cortex/curation/assess/route.js.nft.json +1 -1
  112. package/.next/standalone/.next/server/app/api/cortex/curation/publish/route.js.nft.json +1 -1
  113. package/.next/standalone/.next/server/app/api/cortex/curation/refine/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/cortex/curation/review/route.js.nft.json +1 -1
  115. package/.next/standalone/.next/server/app/api/cortex/curation/seed/route.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/api/cortex/export/route.js.nft.json +1 -1
  117. package/.next/standalone/.next/server/app/api/cortex/federation/pending/route.js.nft.json +1 -1
  118. package/.next/standalone/.next/server/app/api/cortex/federation/resolve/route.js.nft.json +1 -1
  119. package/.next/standalone/.next/server/app/api/cortex/federation/search/route.js.nft.json +1 -1
  120. package/.next/standalone/.next/server/app/api/cortex/federation/teach/route.js.nft.json +1 -1
  121. package/.next/standalone/.next/server/app/api/cortex/graph/edges/route.js.nft.json +1 -1
  122. package/.next/standalone/.next/server/app/api/cortex/graph/entities/[id]/route.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/api/cortex/graph/entities/route.js.nft.json +1 -1
  124. package/.next/standalone/.next/server/app/api/cortex/graph/populate/route.js.nft.json +1 -1
  125. package/.next/standalone/.next/server/app/api/cortex/import/route.js.nft.json +1 -1
  126. package/.next/standalone/.next/server/app/api/cortex/import/status/route.js.nft.json +1 -1
  127. package/.next/standalone/.next/server/app/api/cortex/ingest/bootstrap/route.js.nft.json +1 -1
  128. package/.next/standalone/.next/server/app/api/cortex/ingest/status/route.js.nft.json +1 -1
  129. package/.next/standalone/.next/server/app/api/cortex/knowledge/[id]/route.js.nft.json +1 -1
  130. package/.next/standalone/.next/server/app/api/cortex/knowledge/route.js.nft.json +1 -1
  131. package/.next/standalone/.next/server/app/api/cortex/lobes/[id]/route.js.nft.json +1 -1
  132. package/.next/standalone/.next/server/app/api/cortex/lobes/route.js.nft.json +1 -1
  133. package/.next/standalone/.next/server/app/api/cortex/lobes/share/route.js.nft.json +1 -1
  134. package/.next/standalone/.next/server/app/api/cortex/marketplace/browse/route.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/api/cortex/marketplace/preview/route.js.nft.json +1 -1
  136. package/.next/standalone/.next/server/app/api/cortex/mcp/call/route.js.nft.json +1 -1
  137. package/.next/standalone/.next/server/app/api/cortex/mcp/tools/route.js.nft.json +1 -1
  138. package/.next/standalone/.next/server/app/api/cortex/search/route.js.nft.json +1 -1
  139. package/.next/standalone/.next/server/app/api/cortex/settings/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/cortex/status/route.js.nft.json +1 -1
  141. package/.next/standalone/.next/server/app/api/cortex/timeline/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/cortex/usage/route.js.nft.json +1 -1
  143. package/.next/standalone/.next/server/app/api/cortex/workspace/[id]/context/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
  145. package/.next/standalone/.next/server/app/api/files/route.js +1 -1
  146. package/.next/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  147. package/.next/standalone/.next/server/app/api/folders/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/network/handshake/route.js.nft.json +1 -1
  149. package/.next/standalone/.next/server/app/api/network/projects/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/network/search/route.js.nft.json +1 -1
  151. package/.next/standalone/.next/server/app/api/network/sessions/[id]/messages/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/network/sessions/[id]/route.js.nft.json +1 -1
  153. package/.next/standalone/.next/server/app/api/network/sessions/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/network/workspaces/[id]/route.js.nft.json +1 -1
  155. package/.next/standalone/.next/server/app/api/network/workspaces/route.js.nft.json +1 -1
  156. package/.next/standalone/.next/server/app/api/panes/[id]/route.js.nft.json +1 -1
  157. package/.next/standalone/.next/server/app/api/panes/route.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  159. package/.next/standalone/.next/server/app/api/search/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js.nft.json +1 -1
  161. package/.next/standalone/.next/server/app/api/sessions/[id]/messages/route.js.nft.json +1 -1
  162. package/.next/standalone/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  163. package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
  164. package/.next/standalone/.next/server/app/api/sync/route.js.nft.json +1 -1
  165. package/.next/standalone/.next/server/app/api/tags/route.js.nft.json +1 -1
  166. package/.next/standalone/.next/server/app/api/tier/route.js.nft.json +1 -1
  167. package/.next/standalone/.next/server/app/api/whisper/route/app-paths-manifest.json +3 -0
  168. package/.next/standalone/.next/server/app/api/whisper/route/build-manifest.json +11 -0
  169. package/.next/standalone/.next/server/app/api/whisper/route/server-reference-manifest.json +4 -0
  170. package/.next/standalone/.next/server/app/api/whisper/route.js +7 -0
  171. package/.next/standalone/.next/server/app/api/whisper/route.js.map +5 -0
  172. package/.next/standalone/.next/server/app/api/whisper/route.js.nft.json +1 -0
  173. package/.next/standalone/.next/server/app/api/whisper/route_client-reference-manifest.js +2 -0
  174. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/[key]/route.js.nft.json +1 -1
  175. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/route.js.nft.json +1 -1
  176. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/[msgId]/route.js.nft.json +1 -1
  177. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/route.js.nft.json +1 -1
  178. package/.next/standalone/.next/server/app/api/workspaces/[id]/route.js.nft.json +1 -1
  179. package/.next/standalone/.next/server/app/api/workspaces/[id]/sessions/route.js.nft.json +1 -1
  180. package/.next/standalone/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  181. package/.next/standalone/.next/server/app/cortex.html +1 -1
  182. package/.next/standalone/.next/server/app/cortex.rsc +3 -3
  183. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex/__PAGE__.segment.rsc +2 -2
  184. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex.segment.rsc +1 -1
  185. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  186. package/.next/standalone/.next/server/app/cortex.segments/_full.segment.rsc +3 -3
  187. package/.next/standalone/.next/server/app/cortex.segments/_head.segment.rsc +1 -1
  188. package/.next/standalone/.next/server/app/cortex.segments/_index.segment.rsc +2 -2
  189. package/.next/standalone/.next/server/app/cortex.segments/_tree.segment.rsc +2 -2
  190. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  191. package/.next/standalone/.next/server/app/login.html +1 -1
  192. package/.next/standalone/.next/server/app/login.rsc +2 -2
  193. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +2 -2
  194. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
  195. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +2 -2
  196. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  197. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  198. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
  199. package/.next/standalone/.next/server/app/m/page_client-reference-manifest.js +1 -1
  200. package/.next/standalone/.next/server/app/m/projects/page_client-reference-manifest.js +1 -1
  201. package/.next/standalone/.next/server/app/m/projects.html +1 -1
  202. package/.next/standalone/.next/server/app/m/projects.rsc +2 -2
  203. package/.next/standalone/.next/server/app/m/projects.segments/_full.segment.rsc +2 -2
  204. package/.next/standalone/.next/server/app/m/projects.segments/_head.segment.rsc +1 -1
  205. package/.next/standalone/.next/server/app/m/projects.segments/_index.segment.rsc +2 -2
  206. package/.next/standalone/.next/server/app/m/projects.segments/_tree.segment.rsc +2 -2
  207. package/.next/standalone/.next/server/app/m/projects.segments/m/projects/__PAGE__.segment.rsc +1 -1
  208. package/.next/standalone/.next/server/app/m/projects.segments/m/projects.segment.rsc +1 -1
  209. package/.next/standalone/.next/server/app/m/projects.segments/m.segment.rsc +1 -1
  210. package/.next/standalone/.next/server/app/m/sessions/[id]/page.js.nft.json +1 -1
  211. package/.next/standalone/.next/server/app/m/sessions/[id]/page_client-reference-manifest.js +1 -1
  212. package/.next/standalone/.next/server/app/m/sessions/page_client-reference-manifest.js +1 -1
  213. package/.next/standalone/.next/server/app/m/sessions.html +1 -1
  214. package/.next/standalone/.next/server/app/m/sessions.rsc +2 -2
  215. package/.next/standalone/.next/server/app/m/sessions.segments/_full.segment.rsc +2 -2
  216. package/.next/standalone/.next/server/app/m/sessions.segments/_head.segment.rsc +1 -1
  217. package/.next/standalone/.next/server/app/m/sessions.segments/_index.segment.rsc +2 -2
  218. package/.next/standalone/.next/server/app/m/sessions.segments/_tree.segment.rsc +2 -2
  219. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions/__PAGE__.segment.rsc +1 -1
  220. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions.segment.rsc +1 -1
  221. package/.next/standalone/.next/server/app/m/sessions.segments/m.segment.rsc +1 -1
  222. package/.next/standalone/.next/server/app/m/settings/page_client-reference-manifest.js +1 -1
  223. package/.next/standalone/.next/server/app/m/settings.html +1 -1
  224. package/.next/standalone/.next/server/app/m/settings.rsc +2 -2
  225. package/.next/standalone/.next/server/app/m/settings.segments/_full.segment.rsc +2 -2
  226. package/.next/standalone/.next/server/app/m/settings.segments/_head.segment.rsc +1 -1
  227. package/.next/standalone/.next/server/app/m/settings.segments/_index.segment.rsc +2 -2
  228. package/.next/standalone/.next/server/app/m/settings.segments/_tree.segment.rsc +2 -2
  229. package/.next/standalone/.next/server/app/m/settings.segments/m/settings/__PAGE__.segment.rsc +1 -1
  230. package/.next/standalone/.next/server/app/m/settings.segments/m/settings.segment.rsc +1 -1
  231. package/.next/standalone/.next/server/app/m/settings.segments/m.segment.rsc +1 -1
  232. package/.next/standalone/.next/server/app/m/terminal/page.js.nft.json +1 -1
  233. package/.next/standalone/.next/server/app/m/terminal/page_client-reference-manifest.js +1 -1
  234. package/.next/standalone/.next/server/app/m/terminal.html +1 -1
  235. package/.next/standalone/.next/server/app/m/terminal.rsc +3 -3
  236. package/.next/standalone/.next/server/app/m/terminal.segments/_full.segment.rsc +3 -3
  237. package/.next/standalone/.next/server/app/m/terminal.segments/_head.segment.rsc +1 -1
  238. package/.next/standalone/.next/server/app/m/terminal.segments/_index.segment.rsc +2 -2
  239. package/.next/standalone/.next/server/app/m/terminal.segments/_tree.segment.rsc +2 -2
  240. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal/__PAGE__.segment.rsc +2 -2
  241. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal.segment.rsc +1 -1
  242. package/.next/standalone/.next/server/app/m/terminal.segments/m.segment.rsc +1 -1
  243. package/.next/standalone/.next/server/app/m.html +1 -1
  244. package/.next/standalone/.next/server/app/m.rsc +2 -2
  245. package/.next/standalone/.next/server/app/m.segments/_full.segment.rsc +2 -2
  246. package/.next/standalone/.next/server/app/m.segments/_head.segment.rsc +1 -1
  247. package/.next/standalone/.next/server/app/m.segments/_index.segment.rsc +2 -2
  248. package/.next/standalone/.next/server/app/m.segments/_tree.segment.rsc +2 -2
  249. package/.next/standalone/.next/server/app/m.segments/m/__PAGE__.segment.rsc +1 -1
  250. package/.next/standalone/.next/server/app/m.segments/m.segment.rsc +1 -1
  251. package/.next/standalone/.next/server/app/network.html +1 -1
  252. package/.next/standalone/.next/server/app/network.rsc +2 -2
  253. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network/__PAGE__.segment.rsc +1 -1
  254. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network.segment.rsc +1 -1
  255. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  256. package/.next/standalone/.next/server/app/network.segments/_full.segment.rsc +2 -2
  257. package/.next/standalone/.next/server/app/network.segments/_head.segment.rsc +1 -1
  258. package/.next/standalone/.next/server/app/network.segments/_index.segment.rsc +2 -2
  259. package/.next/standalone/.next/server/app/network.segments/_tree.segment.rsc +2 -2
  260. package/.next/standalone/.next/server/app/projects.html +1 -1
  261. package/.next/standalone/.next/server/app/projects.rsc +2 -2
  262. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects/__PAGE__.segment.rsc +1 -1
  263. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects.segment.rsc +1 -1
  264. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  265. package/.next/standalone/.next/server/app/projects.segments/_full.segment.rsc +2 -2
  266. package/.next/standalone/.next/server/app/projects.segments/_head.segment.rsc +1 -1
  267. package/.next/standalone/.next/server/app/projects.segments/_index.segment.rsc +2 -2
  268. package/.next/standalone/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
  269. package/.next/standalone/.next/server/app/sessions.html +1 -1
  270. package/.next/standalone/.next/server/app/sessions.rsc +2 -2
  271. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions/__PAGE__.segment.rsc +1 -1
  272. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions.segment.rsc +1 -1
  273. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  274. package/.next/standalone/.next/server/app/sessions.segments/_full.segment.rsc +2 -2
  275. package/.next/standalone/.next/server/app/sessions.segments/_head.segment.rsc +1 -1
  276. package/.next/standalone/.next/server/app/sessions.segments/_index.segment.rsc +2 -2
  277. package/.next/standalone/.next/server/app/sessions.segments/_tree.segment.rsc +2 -2
  278. package/.next/standalone/.next/server/app/settings.html +1 -1
  279. package/.next/standalone/.next/server/app/settings.rsc +2 -2
  280. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings/__PAGE__.segment.rsc +1 -1
  281. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings.segment.rsc +1 -1
  282. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  283. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +2 -2
  284. package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  285. package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  286. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  287. package/.next/standalone/.next/server/app/terminal.html +1 -1
  288. package/.next/standalone/.next/server/app/terminal.rsc +3 -3
  289. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal/__PAGE__.segment.rsc +2 -2
  290. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal.segment.rsc +1 -1
  291. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  292. package/.next/standalone/.next/server/app/terminal.segments/_full.segment.rsc +3 -3
  293. package/.next/standalone/.next/server/app/terminal.segments/_head.segment.rsc +1 -1
  294. package/.next/standalone/.next/server/app/terminal.segments/_index.segment.rsc +2 -2
  295. package/.next/standalone/.next/server/app/terminal.segments/_tree.segment.rsc +2 -2
  296. package/.next/standalone/.next/server/app/vr/page/react-loadable-manifest.json +3 -3
  297. package/.next/standalone/.next/server/app/vr/page_client-reference-manifest.js +1 -1
  298. package/.next/standalone/.next/server/app/vr.html +1 -1
  299. package/.next/standalone/.next/server/app/vr.rsc +3 -3
  300. package/.next/standalone/.next/server/app/vr.segments/_full.segment.rsc +3 -3
  301. package/.next/standalone/.next/server/app/vr.segments/_head.segment.rsc +1 -1
  302. package/.next/standalone/.next/server/app/vr.segments/_index.segment.rsc +2 -2
  303. package/.next/standalone/.next/server/app/vr.segments/_tree.segment.rsc +2 -2
  304. package/.next/standalone/.next/server/app/vr.segments/vr/__PAGE__.segment.rsc +2 -2
  305. package/.next/standalone/.next/server/app/vr.segments/vr.segment.rsc +1 -1
  306. package/.next/standalone/.next/server/app/workspaces.html +1 -1
  307. package/.next/standalone/.next/server/app/workspaces.rsc +2 -2
  308. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces/__PAGE__.segment.rsc +1 -1
  309. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces.segment.rsc +1 -1
  310. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  311. package/.next/standalone/.next/server/app/workspaces.segments/_full.segment.rsc +2 -2
  312. package/.next/standalone/.next/server/app/workspaces.segments/_head.segment.rsc +1 -1
  313. package/.next/standalone/.next/server/app/workspaces.segments/_index.segment.rsc +2 -2
  314. package/.next/standalone/.next/server/app/workspaces.segments/_tree.segment.rsc +2 -2
  315. package/.next/standalone/.next/server/app-paths-manifest.json +6 -0
  316. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0041efe4._.js +2 -2
  317. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00bf0ace._.js +2 -2
  318. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0a837dd9._.js +98 -0
  319. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e71d908._.js +3 -3
  320. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e9142f3._.js +2 -2
  321. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10e47926._.js +1 -1
  322. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1665dc78._.js +2 -2
  323. package/.next/standalone/.next/server/chunks/[root-of-the-server]__175cbabf._.js +2 -2
  324. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1adae357._.js +2 -2
  325. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1d359752._.js +2 -2
  326. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1e8fabeb._.js +2 -2
  327. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1f8deca0._.js +8 -8
  328. package/.next/standalone/.next/server/chunks/[root-of-the-server]__253fdda1._.js +2 -2
  329. package/.next/standalone/.next/server/chunks/[root-of-the-server]__28e6434f._.js +2 -2
  330. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2a386564._.js +3 -3
  331. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2c20fb38._.js +2 -2
  332. package/.next/standalone/.next/server/chunks/[root-of-the-server]__309132cd._.js +1 -1
  333. package/.next/standalone/.next/server/chunks/[root-of-the-server]__33fec964._.js +3 -3
  334. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3786d8ae._.js +2 -2
  335. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3ae92407._.js +2 -2
  336. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3beda9fe._.js +2 -2
  337. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4619e9bd._.js +1 -1
  338. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4a051043._.js +2 -2
  339. package/.next/standalone/.next/server/chunks/[root-of-the-server]__508002e4._.js +2 -2
  340. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5086c373._.js +2 -2
  341. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5913e097._.js +2 -2
  342. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5b5f68d2._.js +2 -2
  343. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5c1f2459._.js +2 -2
  344. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5ec8c977._.js +2 -2
  345. package/.next/standalone/.next/server/chunks/[root-of-the-server]__63cebc6c._.js +2 -2
  346. package/.next/standalone/.next/server/chunks/[root-of-the-server]__64d30d4d._.js +2 -2
  347. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c54fc2e._.js +2 -2
  348. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6dc1fb7e._.js +2 -2
  349. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6e568102._.js +2 -2
  350. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6faa04c0._.js +2 -2
  351. package/.next/standalone/.next/server/chunks/[root-of-the-server]__74a34dc3._.js +2 -2
  352. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7819e4cf._.js +98 -0
  353. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7e7250a4._.js +2 -2
  354. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8309e0a4._.js +2 -2
  355. package/.next/standalone/.next/server/chunks/[root-of-the-server]__86cc0e2b._.js +6 -6
  356. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89c2565a._.js +2 -2
  357. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8d178ad9._.js +2 -2
  358. package/.next/standalone/.next/server/chunks/[root-of-the-server]__93ee06f3._.js +2 -2
  359. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9e1f0137._.js +98 -0
  360. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9e4c154a._.js +2 -2
  361. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9d2e1d3._.js +2 -2
  362. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ae53d343._.js +2 -2
  363. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b3a04cef._.js +2 -2
  364. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b4270b77._.js +1 -1
  365. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b6b6ce60._.js +3 -3
  366. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c0757773._.js +98 -0
  367. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c24cfa91._.js +3 -0
  368. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c7c47529._.js +3 -0
  369. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c88b63f7._.js +2 -2
  370. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cba5f007._.js +1 -1
  371. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cbf4ceb0._.js +2 -2
  372. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cefdba2f._.js +2 -2
  373. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cf9e82bb._.js +2 -2
  374. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d2897392._.js +2 -2
  375. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d3b2d856._.js +2 -2
  376. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d73273ca._.js +2 -2
  377. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d8417eb6._.js +2 -2
  378. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dc2a55de._.js +2 -2
  379. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e0d4690b._.js +2 -2
  380. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e3ea8547._.js +98 -0
  381. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e678dd53._.js +1 -1
  382. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e9223f55._.js +2 -2
  383. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ea630076._.js +2 -2
  384. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f26ca49d._.js +1 -1
  385. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f33e1101._.js +2 -2
  386. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f515f865._.js +2 -2
  387. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fceb5d60._.js +2 -2
  388. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fed41403._.js +2 -2
  389. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ff2e98c2._.js +2 -2
  390. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_benchmark_lobes_route_actions_ea7beadb.js +3 -0
  391. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_benchmark_run_route_actions_9ed0ba41.js +3 -0
  392. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_benchmark_runs_[id]_route_actions_39f90307.js +3 -0
  393. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_benchmark_runs_route_actions_37cf958b.js +3 -0
  394. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_benchmark_status_route_actions_009e2cba.js +3 -0
  395. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_whisper_route_actions_be9a633d.js +3 -0
  396. package/.next/standalone/.next/server/chunks/ssr/{_c1cfdd09._.js → [root-of-the-server]__16621ac5._.js} +2 -2
  397. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__66aca5d4._.js +1 -1
  398. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__9c81bd86._.js +3 -0
  399. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__e3bf6054._.js +5 -0
  400. package/.next/standalone/.next/server/chunks/ssr/{_81abf587._.js → _31ada310._.js} +2 -2
  401. package/.next/standalone/.next/server/chunks/ssr/_648a8a2d._.js +3 -0
  402. package/.next/standalone/.next/server/chunks/ssr/_999dae61._.js +3 -0
  403. package/.next/standalone/.next/server/chunks/ssr/_c48c91e5._.js +3 -0
  404. package/.next/standalone/.next/server/chunks/ssr/_f8959434._.js +3 -0
  405. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_cortex_page_tsx_0f33d8b3._.js +1 -1
  406. package/.next/standalone/.next/server/chunks/ssr/src_components_terminal_terminal-pane_tsx_803c5e2c._.js +9 -0
  407. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__32a0045c._.js +1 -1
  408. package/.next/standalone/.next/server/edge/chunks/_d73df637._.js +1 -1
  409. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  410. package/.next/standalone/.next/server/pages/404.html +1 -1
  411. package/.next/standalone/.next/server/pages/500.html +2 -2
  412. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  413. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  414. package/.next/standalone/.next/static/chunks/157826a3253f8ccf.js +7 -0
  415. package/.next/standalone/.next/static/chunks/{396eac60f496f178.js → 2f9f09924ff9d447.js} +1 -1
  416. package/.next/standalone/.next/static/chunks/{e23f20b51a75a5bb.js → 4ced66ef12d91b38.js} +35 -12
  417. package/.next/standalone/.next/static/chunks/57d04d161b8a01b3.js +7 -0
  418. package/.next/standalone/.next/static/chunks/709c4608e5b935e8.js +1 -0
  419. package/.next/standalone/.next/static/chunks/{7424664c6ffa94bd.js → 7b14d4e609b55b9b.js} +1 -1
  420. package/.next/standalone/.next/static/chunks/7be37f4a56b8f575.js +1 -0
  421. package/.next/standalone/.next/static/chunks/8021d5a2269ff113.js +1 -0
  422. package/.next/standalone/.next/static/chunks/a3fd93a9dde3cacc.js +1 -0
  423. package/.next/standalone/.next/static/chunks/{412140a02893327a.js → afee31c7399daf2a.js} +1 -1
  424. package/.next/standalone/.next/static/chunks/b92fdbf858aeb0b3.js +1 -0
  425. package/.next/standalone/.next/static/chunks/c17274c2f95d4ba2.js +5 -0
  426. package/.next/standalone/.next/static/chunks/e116953dc83d4eec.js +1 -0
  427. package/.next/standalone/.next/static/chunks/e82f4414650587cf.js +7 -0
  428. package/.next/standalone/.next/static/chunks/f6464729e7aa0da0.css +3 -0
  429. package/.next/standalone/LICENSE +661 -0
  430. package/.next/standalone/NOTICE +5 -0
  431. package/.next/standalone/README.md +131 -0
  432. package/.next/standalone/bin/cortex-hook.sh +62 -62
  433. package/.next/standalone/bin/cortex-mcp.js +60 -60
  434. package/.next/standalone/bin/fix-standalone-externals.js +79 -0
  435. package/.next/standalone/bin/lib/auto-setup.js +110 -0
  436. package/.next/standalone/bin/mdns-service.js +171 -0
  437. package/.next/standalone/bin/postinstall.js +35 -0
  438. package/.next/standalone/bin/setup-admin.js +195 -0
  439. package/.next/standalone/bin/spaces-dev.js +247 -0
  440. package/.next/standalone/bin/spaces-install.js +638 -0
  441. package/.next/standalone/bin/spaces-reset-totp.js +50 -0
  442. package/.next/standalone/bin/spaces-service.js +1020 -0
  443. package/.next/standalone/bin/spaces-setup.js +253 -0
  444. package/.next/standalone/bin/spaces.js +788 -0
  445. package/.next/standalone/bin/ssh-auth-keys.sh +68 -0
  446. package/.next/standalone/bin/terminal-server.js +1807 -0
  447. package/.next/standalone/docker-compose.yml +28 -0
  448. package/.next/standalone/docs/architecture.md +387 -0
  449. package/.next/standalone/docs/cortex.md +293 -0
  450. package/.next/standalone/docs/getting-started.md +96 -0
  451. package/.next/standalone/docs/plans/2026-02-24-multi-agent-sessions-design.md +133 -0
  452. package/.next/standalone/docs/plans/2026-02-24-multi-agent-sessions-plan.md +959 -0
  453. package/.next/standalone/docs/plans/2026-03-07-service-command-design.md +146 -0
  454. package/.next/standalone/docs/plans/2026-03-07-service-command-plan.md +254 -0
  455. package/.next/standalone/docs/server-install.md +564 -0
  456. package/.next/standalone/docs/social-card.html +150 -0
  457. package/.next/standalone/docs/superpowers/plans/2026-03-12-spaces-cortex.md +5270 -0
  458. package/.next/standalone/docs/superpowers/plans/2026-03-13-cortex-wiring.md +1387 -1387
  459. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-entity-graph.md +1923 -1923
  460. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-knowledge-evolution.md +1113 -1113
  461. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-boundary-engine.md +853 -853
  462. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-context-engine.md +1274 -1274
  463. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-signal-ingestion.md +933 -933
  464. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-lobes.md +1080 -1080
  465. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-gravity-system.md +768 -768
  466. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-ui.md +1108 -1108
  467. package/.next/standalone/docs/superpowers/plans/2026-03-18-cortex-ui-integration.md +1846 -1846
  468. package/.next/standalone/docs/superpowers/plans/2026-03-19-vr-phase1-shell.md +1639 -0
  469. package/.next/standalone/docs/superpowers/specs/2026-03-11-universe-view-design.md +320 -0
  470. package/.next/standalone/docs/superpowers/specs/2026-03-12-spaces-brain-design.md +720 -0
  471. package/.next/standalone/docs/superpowers/specs/2026-03-13-cortex-wiring-design.md +268 -268
  472. package/.next/standalone/docs/superpowers/specs/2026-03-14-cortex-v2-design.md +623 -623
  473. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-lobes-design.md +263 -263
  474. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-v2-ui-design.md +240 -240
  475. package/.next/standalone/docs/superpowers/specs/2026-03-16-pane-ux-design.md +77 -0
  476. package/.next/standalone/docs/superpowers/specs/2026-03-18-cortex-ui-integration-design.md +341 -341
  477. package/.next/standalone/docs/superpowers/specs/2026-03-19-vr-phase1-shell-design.md +288 -0
  478. package/.next/standalone/docs/tiers.md +104 -0
  479. package/.next/standalone/eslint.config.mjs +18 -0
  480. package/.next/standalone/next.config.ts +20 -0
  481. package/.next/standalone/nginx.conf +53 -0
  482. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/README.md +46 -0
  483. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/glib-2.0/include/glibconfig.h +221 -0
  484. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/index.js +1 -0
  485. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  486. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/package.json +42 -0
  487. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/README.md +46 -0
  488. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/glib-2.0/include/glibconfig.h +221 -0
  489. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/index.js +1 -0
  490. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  491. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json +42 -0
  492. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/versions.json +30 -0
  493. package/.next/standalone/node_modules/@img/sharp-linux-x64/lib/sharp-linux-x64.node +0 -0
  494. package/.next/standalone/node_modules/@img/{sharp-win32-x64 → sharp-linux-x64}/package.json +46 -39
  495. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/lib/sharp-linuxmusl-x64.node +0 -0
  496. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/package.json +46 -0
  497. package/.next/standalone/package-lock.json +14154 -0
  498. package/.next/standalone/package.json +104 -103
  499. package/.next/standalone/postcss.config.mjs +7 -0
  500. package/.next/standalone/scripts/rebuild.cmd +65 -0
  501. package/.next/standalone/scripts/rebuild.sh +59 -0
  502. package/.next/standalone/server.js +1 -1
  503. package/.next/standalone/src/app/(desktop)/admin/analytics/page.tsx +266 -0
  504. package/.next/standalone/src/app/(desktop)/admin/users/page.tsx +399 -0
  505. package/.next/standalone/src/app/(desktop)/analytics/page.tsx +166 -0
  506. package/.next/standalone/src/app/(desktop)/cortex/page.tsx +81 -78
  507. package/.next/standalone/src/app/(desktop)/dashboard-client.tsx +56 -0
  508. package/.next/standalone/src/app/(desktop)/layout.tsx +18 -0
  509. package/.next/standalone/src/app/(desktop)/network/page.tsx +137 -0
  510. package/.next/standalone/src/app/(desktop)/page.tsx +17 -0
  511. package/.next/standalone/src/app/(desktop)/projects/page.tsx +68 -0
  512. package/.next/standalone/src/app/(desktop)/sessions/[id]/page.tsx +519 -0
  513. package/.next/standalone/src/app/(desktop)/sessions/page.tsx +145 -0
  514. package/.next/standalone/src/app/(desktop)/settings/page.tsx +446 -0
  515. package/.next/standalone/src/app/(desktop)/terminal/layout.tsx +7 -0
  516. package/.next/standalone/src/app/(desktop)/terminal/page.tsx +1151 -0
  517. package/.next/standalone/src/app/(desktop)/terminal/pane/[id]/page.tsx +211 -0
  518. package/.next/standalone/src/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page.tsx +192 -0
  519. package/.next/standalone/src/app/(desktop)/workspaces/page.tsx +12 -0
  520. package/.next/standalone/src/app/api/admin/analytics/route.ts +10 -0
  521. package/.next/standalone/src/app/api/admin/users/[id]/route.ts +20 -0
  522. package/.next/standalone/src/app/api/admin/users/route.ts +15 -0
  523. package/.next/standalone/src/app/api/analytics/overview/route.ts +80 -0
  524. package/.next/standalone/src/app/api/auth/login/route.ts +10 -0
  525. package/.next/standalone/src/app/api/auth/logout/route.ts +9 -0
  526. package/.next/standalone/src/app/api/auth/me/route.ts +22 -0
  527. package/.next/standalone/src/app/api/auth/totp/setup/route.ts +10 -0
  528. package/.next/standalone/src/app/api/auth/totp/status/route.ts +10 -0
  529. package/.next/standalone/src/app/api/auth/totp/verify/route.ts +10 -0
  530. package/.next/standalone/src/app/api/benchmark/lobes/route.ts +16 -0
  531. package/.next/standalone/src/app/api/benchmark/run/route.ts +92 -0
  532. package/.next/standalone/src/app/api/benchmark/runs/[id]/route.ts +26 -0
  533. package/.next/standalone/src/app/api/benchmark/runs/route.ts +16 -0
  534. package/.next/standalone/src/app/api/benchmark/status/route.ts +35 -0
  535. package/.next/standalone/src/app/api/bulk/route.ts +34 -0
  536. package/.next/standalone/src/app/api/chat/route.ts +85 -0
  537. package/.next/standalone/src/app/api/config/route.ts +30 -0
  538. package/.next/standalone/src/app/api/cortex/context/route.ts +78 -78
  539. package/.next/standalone/src/app/api/cortex/curation/assess/route.ts +27 -27
  540. package/.next/standalone/src/app/api/cortex/curation/publish/route.ts +23 -23
  541. package/.next/standalone/src/app/api/cortex/curation/refine/route.ts +23 -23
  542. package/.next/standalone/src/app/api/cortex/curation/review/route.ts +29 -29
  543. package/.next/standalone/src/app/api/cortex/curation/seed/route.ts +23 -23
  544. package/.next/standalone/src/app/api/cortex/export/route.ts +40 -40
  545. package/.next/standalone/src/app/api/cortex/federation/pending/route.ts +20 -20
  546. package/.next/standalone/src/app/api/cortex/federation/resolve/route.ts +43 -43
  547. package/.next/standalone/src/app/api/cortex/federation/search/route.ts +35 -35
  548. package/.next/standalone/src/app/api/cortex/federation/teach/route.ts +76 -76
  549. package/.next/standalone/src/app/api/cortex/graph/edges/route.ts +112 -112
  550. package/.next/standalone/src/app/api/cortex/graph/entities/[id]/route.ts +73 -73
  551. package/.next/standalone/src/app/api/cortex/graph/entities/route.ts +75 -75
  552. package/.next/standalone/src/app/api/cortex/graph/populate/route.ts +203 -203
  553. package/.next/standalone/src/app/api/cortex/import/route.ts +75 -75
  554. package/.next/standalone/src/app/api/cortex/import/status/route.ts +15 -15
  555. package/.next/standalone/src/app/api/cortex/ingest/bootstrap/route.ts +29 -29
  556. package/.next/standalone/src/app/api/cortex/ingest/status/route.ts +15 -15
  557. package/.next/standalone/src/app/api/cortex/knowledge/[id]/route.ts +91 -91
  558. package/.next/standalone/src/app/api/cortex/knowledge/route.ts +93 -93
  559. package/.next/standalone/src/app/api/cortex/lobes/[id]/route.ts +67 -67
  560. package/.next/standalone/src/app/api/cortex/lobes/route.ts +22 -22
  561. package/.next/standalone/src/app/api/cortex/lobes/share/route.ts +80 -80
  562. package/.next/standalone/src/app/api/cortex/marketplace/browse/route.ts +43 -43
  563. package/.next/standalone/src/app/api/cortex/marketplace/preview/route.ts +46 -46
  564. package/.next/standalone/src/app/api/cortex/mcp/call/route.ts +11 -11
  565. package/.next/standalone/src/app/api/cortex/mcp/tools/route.ts +6 -6
  566. package/.next/standalone/src/app/api/cortex/search/route.ts +43 -43
  567. package/.next/standalone/src/app/api/cortex/settings/route.ts +33 -33
  568. package/.next/standalone/src/app/api/cortex/status/route.ts +169 -169
  569. package/.next/standalone/src/app/api/cortex/timeline/route.ts +42 -42
  570. package/.next/standalone/src/app/api/cortex/usage/route.ts +31 -31
  571. package/.next/standalone/src/app/api/cortex/workspace/[id]/context/route.ts +41 -41
  572. package/.next/standalone/src/app/api/events/route.ts +40 -0
  573. package/.next/standalone/src/app/api/files/route.ts +187 -0
  574. package/.next/standalone/src/app/api/folders/route.ts +97 -0
  575. package/.next/standalone/src/app/api/network/connect-callback/route.ts +11 -0
  576. package/.next/standalone/src/app/api/network/connect-request/[id]/route.ts +11 -0
  577. package/.next/standalone/src/app/api/network/connect-request/route.ts +17 -0
  578. package/.next/standalone/src/app/api/network/discovered/route.ts +9 -0
  579. package/.next/standalone/src/app/api/network/handshake/route.ts +25 -0
  580. package/.next/standalone/src/app/api/network/health/route.ts +10 -0
  581. package/.next/standalone/src/app/api/network/identity/route.ts +15 -0
  582. package/.next/standalone/src/app/api/network/keys/[id]/route.ts +10 -0
  583. package/.next/standalone/src/app/api/network/keys/route.ts +15 -0
  584. package/.next/standalone/src/app/api/network/nodes/[id]/route.ts +15 -0
  585. package/.next/standalone/src/app/api/network/nodes/check/route.ts +9 -0
  586. package/.next/standalone/src/app/api/network/nodes/route.ts +15 -0
  587. package/.next/standalone/src/app/api/network/projects/route.ts +25 -0
  588. package/.next/standalone/src/app/api/network/proxy/[nodeId]/[...path]/route.ts +15 -0
  589. package/.next/standalone/src/app/api/network/search/route.ts +38 -0
  590. package/.next/standalone/src/app/api/network/sessions/[id]/messages/route.ts +36 -0
  591. package/.next/standalone/src/app/api/network/sessions/[id]/route.ts +34 -0
  592. package/.next/standalone/src/app/api/network/sessions/route.ts +43 -0
  593. package/.next/standalone/src/app/api/network/terminal/token/route.ts +10 -0
  594. package/.next/standalone/src/app/api/network/workspaces/[id]/route.ts +34 -0
  595. package/.next/standalone/src/app/api/network/workspaces/route.ts +61 -0
  596. package/.next/standalone/src/app/api/panes/[id]/route.ts +60 -0
  597. package/.next/standalone/src/app/api/panes/route.ts +39 -0
  598. package/.next/standalone/src/app/api/projects/route.ts +13 -0
  599. package/.next/standalone/src/app/api/search/route.ts +47 -0
  600. package/.next/standalone/src/app/api/sessions/[id]/chat/route.ts +120 -0
  601. package/.next/standalone/src/app/api/sessions/[id]/messages/route.ts +28 -0
  602. package/.next/standalone/src/app/api/sessions/[id]/route.ts +73 -0
  603. package/.next/standalone/src/app/api/sessions/route.ts +64 -0
  604. package/.next/standalone/src/app/api/sync/route.ts +24 -0
  605. package/.next/standalone/src/app/api/tags/route.ts +35 -0
  606. package/.next/standalone/src/app/api/tier/route.ts +16 -0
  607. package/.next/standalone/src/app/api/updates/route.ts +53 -0
  608. package/.next/standalone/src/app/api/whisper/route.ts +90 -0
  609. package/.next/standalone/src/app/api/workspaces/[id]/context/[key]/route.ts +39 -0
  610. package/.next/standalone/src/app/api/workspaces/[id]/context/route.ts +28 -0
  611. package/.next/standalone/src/app/api/workspaces/[id]/messages/[msgId]/route.ts +17 -0
  612. package/.next/standalone/src/app/api/workspaces/[id]/messages/route.ts +39 -0
  613. package/.next/standalone/src/app/api/workspaces/[id]/route.ts +47 -0
  614. package/.next/standalone/src/app/api/workspaces/[id]/sessions/route.ts +62 -0
  615. package/.next/standalone/src/app/api/workspaces/route.ts +79 -0
  616. package/.next/standalone/src/app/globals.css +85 -0
  617. package/.next/standalone/src/app/icon.png +0 -0
  618. package/.next/standalone/src/app/layout.tsx +33 -0
  619. package/.next/standalone/src/app/login/layout.tsx +7 -0
  620. package/.next/standalone/src/app/login/page.tsx +315 -0
  621. package/.next/standalone/src/app/m/layout.tsx +16 -0
  622. package/.next/standalone/src/app/m/page.tsx +118 -0
  623. package/.next/standalone/src/app/m/projects/page.tsx +64 -0
  624. package/.next/standalone/src/app/m/sessions/[id]/page.tsx +168 -0
  625. package/.next/standalone/src/app/m/sessions/page.tsx +177 -0
  626. package/.next/standalone/src/app/m/settings/page.tsx +230 -0
  627. package/.next/standalone/src/app/m/terminal/page.tsx +413 -0
  628. package/.next/standalone/src/app/vr/page.tsx +21 -0
  629. package/.next/standalone/src/app/vr/vr-app.tsx +163 -0
  630. package/.next/standalone/src/app/vr/vr-controls.tsx +139 -0
  631. package/.next/standalone/src/app/vr/vr-door.tsx +82 -0
  632. package/.next/standalone/src/app/vr/vr-environment.tsx +71 -0
  633. package/.next/standalone/src/app/vr/vr-gaze.tsx +89 -0
  634. package/.next/standalone/src/app/vr/vr-layout.ts +49 -0
  635. package/.next/standalone/src/app/vr/vr-lobby.tsx +97 -0
  636. package/.next/standalone/src/app/vr/vr-pane.tsx +195 -0
  637. package/.next/standalone/src/app/vr/vr-room.tsx +79 -0
  638. package/.next/standalone/src/app/vr/vr-terminal.tsx +303 -0
  639. package/.next/standalone/src/components/auth/totp-gate.tsx +183 -0
  640. package/.next/standalone/src/components/bus/activity-panel.tsx +261 -0
  641. package/.next/standalone/src/components/common/color-picker.tsx +35 -0
  642. package/.next/standalone/src/components/common/dev-directory-picker.tsx +339 -0
  643. package/.next/standalone/src/components/common/folder-picker.tsx +200 -0
  644. package/.next/standalone/src/components/common/tag-picker.tsx +190 -0
  645. package/.next/standalone/src/components/common/workspace-picker.tsx +113 -0
  646. package/.next/standalone/src/components/cortex/benchmark-tab.tsx +880 -0
  647. package/.next/standalone/src/components/cortex/constants.ts +29 -29
  648. package/.next/standalone/src/components/cortex/cortex-dashboard.tsx +304 -304
  649. package/.next/standalone/src/components/cortex/cortex-indicator.tsx +44 -44
  650. package/.next/standalone/src/components/cortex/cortex-panel.tsx +140 -140
  651. package/.next/standalone/src/components/cortex/cortex-settings.tsx +221 -221
  652. package/.next/standalone/src/components/cortex/curation-tab.tsx +810 -810
  653. package/.next/standalone/src/components/cortex/entity-detail.tsx +101 -101
  654. package/.next/standalone/src/components/cortex/entity-graph.tsx +382 -382
  655. package/.next/standalone/src/components/cortex/import-dialog.tsx +212 -212
  656. package/.next/standalone/src/components/cortex/injection-badge.tsx +72 -72
  657. package/.next/standalone/src/components/cortex/knowledge-card.tsx +109 -109
  658. package/.next/standalone/src/components/cortex/knowledge-tab.tsx +158 -158
  659. package/.next/standalone/src/components/cortex/lobe-settings.tsx +215 -215
  660. package/.next/standalone/src/components/cortex/marketplace-card.tsx +126 -126
  661. package/.next/standalone/src/components/cortex/marketplace-tab.tsx +113 -113
  662. package/.next/standalone/src/components/dashboard/activity-chart.tsx +41 -0
  663. package/.next/standalone/src/components/dashboard/model-usage-chart.tsx +61 -0
  664. package/.next/standalone/src/components/dashboard/recent-sessions.tsx +68 -0
  665. package/.next/standalone/src/components/dashboard/stats-cards.tsx +36 -0
  666. package/.next/standalone/src/components/files/file-explorer.tsx +703 -0
  667. package/.next/standalone/src/components/layout/providers.tsx +38 -0
  668. package/.next/standalone/src/components/layout/sidebar.tsx +170 -0
  669. package/.next/standalone/src/components/layout/tier-provider.tsx +53 -0
  670. package/.next/standalone/src/components/layout/update-banner.tsx +92 -0
  671. package/.next/standalone/src/components/mobile/bottom-nav.tsx +46 -0
  672. package/.next/standalone/src/components/mobile/mobile-chat-input.tsx +244 -0
  673. package/.next/standalone/src/components/mobile/mobile-header.tsx +44 -0
  674. package/.next/standalone/src/components/mobile/mobile-session-card.tsx +56 -0
  675. package/.next/standalone/src/components/mobile/mobile-terminal-input.tsx +71 -0
  676. package/.next/standalone/src/components/mobile/mobile-terminal-pane.tsx +300 -0
  677. package/.next/standalone/src/components/mobile/mobile-terminal-toolbar.tsx +53 -0
  678. package/.next/standalone/src/components/mobile/pull-to-refresh.tsx +82 -0
  679. package/.next/standalone/src/components/mobile/voice-input.tsx +53 -0
  680. package/.next/standalone/src/components/network/api-key-list.tsx +190 -0
  681. package/.next/standalone/src/components/network/connection-requests.tsx +94 -0
  682. package/.next/standalone/src/components/network/node-add-dialog.tsx +131 -0
  683. package/.next/standalone/src/components/network/node-badge.tsx +26 -0
  684. package/.next/standalone/src/components/network/node-list.tsx +207 -0
  685. package/.next/standalone/src/components/network/node-selector.tsx +49 -0
  686. package/.next/standalone/src/components/sessions/session-filters.tsx +116 -0
  687. package/.next/standalone/src/components/sessions/session-list.tsx +485 -0
  688. package/.next/standalone/src/components/terminal/terminal-pane.tsx +874 -0
  689. package/.next/standalone/src/components/viewer/chat-input.tsx +275 -0
  690. package/.next/standalone/src/components/viewer/message-renderer.tsx +551 -0
  691. package/.next/standalone/src/components/workspace/universe-cluster.tsx +131 -0
  692. package/.next/standalone/src/components/workspace/universe-orb.tsx +128 -0
  693. package/.next/standalone/src/components/workspace/universe-types.ts +22 -0
  694. package/.next/standalone/src/components/workspace/universe-utils.ts +11 -0
  695. package/.next/standalone/src/components/workspace/universe-view.tsx +397 -0
  696. package/.next/standalone/src/components/workspace/workspace-chooser.tsx +616 -0
  697. package/.next/standalone/src/hooks/use-benchmark.ts +71 -0
  698. package/.next/standalone/src/hooks/use-bus.ts +147 -0
  699. package/.next/standalone/src/hooks/use-idle-detection.ts +79 -0
  700. package/.next/standalone/src/hooks/use-network.ts +229 -0
  701. package/.next/standalone/src/hooks/use-sessions.ts +437 -0
  702. package/.next/standalone/src/hooks/use-speech-recognition.ts +113 -0
  703. package/.next/standalone/src/hooks/use-sse.ts +35 -0
  704. package/.next/standalone/src/hooks/use-tier.ts +39 -0
  705. package/.next/standalone/src/lib/agents.ts +70 -0
  706. package/.next/standalone/src/lib/aider/parser.ts +111 -0
  707. package/.next/standalone/src/lib/api.ts +19 -0
  708. package/.next/standalone/src/lib/auth.ts +47 -0
  709. package/.next/standalone/src/lib/claude/parser.ts +212 -0
  710. package/.next/standalone/src/lib/claude/stats.ts +204 -0
  711. package/.next/standalone/src/lib/codex/parser.ts +265 -0
  712. package/.next/standalone/src/lib/config.ts +115 -0
  713. package/.next/standalone/src/lib/cortex/benchmark.ts +67 -0
  714. package/.next/standalone/src/lib/cortex/config.ts +40 -40
  715. package/.next/standalone/src/lib/cortex/debug.ts +10 -10
  716. package/.next/standalone/src/lib/cortex/distillation/usage-store.ts +18 -18
  717. package/.next/standalone/src/lib/cortex/graph/resolver.ts +10 -10
  718. package/.next/standalone/src/lib/cortex/graph/types.ts +22 -22
  719. package/.next/standalone/src/lib/cortex/index.ts +56 -56
  720. package/.next/standalone/src/lib/cortex/ingestion/bootstrap.ts +14 -14
  721. package/.next/standalone/src/lib/cortex/knowledge/compat.ts +14 -14
  722. package/.next/standalone/src/lib/cortex/knowledge/contradiction.ts +10 -10
  723. package/.next/standalone/src/lib/cortex/knowledge/types.ts +67 -67
  724. package/.next/standalone/src/lib/cortex/lobes/config.ts +16 -16
  725. package/.next/standalone/src/lib/cortex/lobes/resolver.ts +8 -8
  726. package/.next/standalone/src/lib/cortex/lobes/shares.ts +14 -14
  727. package/.next/standalone/src/lib/cortex/mcp/server.ts +8 -8
  728. package/.next/standalone/src/lib/cortex/portability/exporter.ts +6 -6
  729. package/.next/standalone/src/lib/cortex/portability/importer.ts +10 -10
  730. package/.next/standalone/src/lib/cortex/retrieval/context-engine.ts +10 -10
  731. package/.next/standalone/src/lib/cortex/types.ts +39 -39
  732. package/.next/standalone/src/lib/cost-calculator.ts +48 -0
  733. package/.next/standalone/src/lib/db/init.ts +71 -0
  734. package/.next/standalone/src/lib/db/queries.ts +718 -0
  735. package/.next/standalone/src/lib/db/schema.ts +202 -0
  736. package/.next/standalone/src/lib/events/sse.ts +36 -0
  737. package/.next/standalone/src/lib/gemini/parser.ts +216 -0
  738. package/.next/standalone/src/lib/license.ts +56 -0
  739. package/.next/standalone/src/lib/pro.ts +31 -0
  740. package/.next/standalone/src/lib/sync/indexer.ts +429 -0
  741. package/.next/standalone/src/lib/sync/watcher.ts +64 -0
  742. package/.next/standalone/src/lib/teams.ts +31 -0
  743. package/.next/standalone/src/lib/telemetry.ts +75 -0
  744. package/.next/standalone/src/lib/terminal/server.ts +128 -0
  745. package/.next/standalone/src/lib/tier.ts +38 -0
  746. package/.next/standalone/src/lib/utils.ts +72 -0
  747. package/.next/standalone/src/middleware.ts +133 -0
  748. package/.next/standalone/src/types/claude.ts +208 -0
  749. package/.next/standalone/src/types/network.ts +61 -0
  750. package/.next/standalone/tests/setup.ts +8 -0
  751. package/.next/standalone/tsconfig.json +34 -34
  752. package/.next/standalone/vitest.config.ts +24 -0
  753. package/LICENSE +661 -661
  754. package/README.md +131 -131
  755. package/bin/cortex-hook.sh +62 -62
  756. package/bin/cortex-mcp.js +60 -60
  757. package/bin/fix-standalone-externals.js +79 -79
  758. package/bin/lib/auto-setup.js +110 -110
  759. package/bin/mdns-service.js +171 -171
  760. package/bin/postinstall.js +35 -35
  761. package/bin/setup-admin.js +195 -195
  762. package/bin/spaces-dev.js +247 -208
  763. package/bin/spaces-install.js +638 -599
  764. package/bin/spaces-reset-totp.js +50 -50
  765. package/bin/spaces-service.js +1020 -1020
  766. package/bin/spaces-setup.js +253 -253
  767. package/bin/spaces.js +788 -776
  768. package/bin/ssh-auth-keys.sh +68 -68
  769. package/bin/terminal-server.js +1807 -1683
  770. package/package.json +104 -103
  771. package/.next/standalone/.claude/settings.local.json +0 -55
  772. package/.next/standalone/.claude/spaces-env.json +0 -1
  773. package/.next/standalone/.next/server/chunks/[root-of-the-server]__eb8acb65._.js +0 -3
  774. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__e921fdfc._.js +0 -5
  775. package/.next/standalone/.next/server/chunks/ssr/_2230ad2d._.js +0 -3
  776. package/.next/standalone/.next/server/chunks/ssr/_5cf334fd._.js +0 -3
  777. package/.next/standalone/.next/server/chunks/ssr/_db0abd0a._.js +0 -3
  778. package/.next/standalone/.next/server/chunks/ssr/_db2fec84._.js +0 -3
  779. package/.next/standalone/.next/server/chunks/ssr/_f4e57187._.js +0 -3
  780. package/.next/standalone/.next/server/chunks/ssr/src_40fa36ce._.js +0 -7
  781. package/.next/standalone/.next/static/chunks/003e7aa1adfe577d.js +0 -1
  782. package/.next/standalone/.next/static/chunks/232d8aae4fefab70.js +0 -1
  783. package/.next/standalone/.next/static/chunks/5325351ef49cb65f.js +0 -1
  784. package/.next/standalone/.next/static/chunks/559735e598ca3cbb.js +0 -1
  785. package/.next/standalone/.next/static/chunks/5d5d7b0095dd52ae.js +0 -1
  786. package/.next/standalone/.next/static/chunks/7a7c0d9d875332a3.js +0 -1
  787. package/.next/standalone/.next/static/chunks/898f380eba90427a.js +0 -1
  788. package/.next/standalone/.next/static/chunks/95339e55722bb4ca.js +0 -5
  789. package/.next/standalone/.next/static/chunks/9cd594813c539df9.js +0 -1
  790. package/.next/standalone/.next/static/chunks/aae9e0fa485bd835.js +0 -5
  791. package/.next/standalone/.next/static/chunks/c1a95aebf6725f64.css +0 -3
  792. package/.next/standalone/.next/static/chunks/c515eb77d9410aa0.js +0 -5
  793. package/.next/standalone/.next/static/chunks/d9ae203a7f123546.js +0 -5
  794. package/.next/standalone/.next/static/chunks/f9f2628207848ac2.js +0 -1
  795. package/.next/standalone/.spaces/cortex-context.md +0 -70
  796. package/.next/standalone/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64.node +0 -0
  797. /package/.next/standalone/.next/static/{ncDe4k4gvD0788HAnq_3G → PcpzUspSK8QDdwzAJz8br}/_buildManifest.js +0 -0
  798. /package/.next/standalone/.next/static/{ncDe4k4gvD0788HAnq_3G → PcpzUspSK8QDdwzAJz8br}/_clientMiddlewareManifest.json +0 -0
  799. /package/.next/standalone/.next/static/{ncDe4k4gvD0788HAnq_3G → PcpzUspSK8QDdwzAJz8br}/_ssgManifest.js +0 -0
  800. /package/.next/standalone/node_modules/@img/{sharp-win32-x64 → sharp-libvips-linux-x64}/versions.json +0 -0
@@ -1,853 +1,853 @@
1
- # Cortex v2 — Pillar 4: Boundary Engine
2
-
3
- > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
4
-
5
- **Goal:** Add three-layer access control to Cortex: auto-classification of sensitivity, organizational policies, and creator overrides — ensuring confidential knowledge never leaks across scope boundaries.
6
-
7
- **Architecture:** A new `src/lib/cortex/boundary/` module with three components: a `Classifier` (regex-based sensitivity detection), a `PolicyEngine` (rule evaluation), and an `AccessFilter` (query-time enforcement). The AccessFilter integrates with the ContextEngine to pre-filter scopes before search. An audit log records all access decisions in the entity graph's SQLite database.
8
-
9
- **Tech Stack:** TypeScript, better-sqlite3 (existing graph DB), vitest
10
-
11
- **Spec:** `docs/superpowers/specs/2026-03-14-cortex-v2-design.md` — Pillar 4
12
-
13
- **Depends on:** Pillar 1 (Entity Graph) + Pillar 2 (Knowledge Unit Evolution) — both completed
14
-
15
- ---
16
-
17
- ## File Structure
18
-
19
- ```
20
- New files:
21
- ├── src/lib/cortex/boundary/classifier.ts — Auto-classification (Layer 1)
22
- ├── src/lib/cortex/boundary/policy.ts — Policy engine (Layer 2)
23
- ├── src/lib/cortex/boundary/access.ts — Query-time access filter (Layer 3 + enforcement)
24
- ├── src/lib/cortex/boundary/audit.ts — Audit trail logging
25
- ├── src/lib/cortex/boundary/index.ts — Barrel export
26
-
27
- Modified files:
28
- ├── src/lib/cortex/ingestion/pipeline.ts — Auto-classify on ingestion
29
- ├── src/lib/cortex/retrieval/context-engine.ts — Pre-filter with AccessFilter
30
- ├── src/lib/cortex/config.ts — Add policies to config
31
-
32
- Test files:
33
- ├── tests/lib/cortex/boundary/classifier.test.ts
34
- ├── tests/lib/cortex/boundary/policy.test.ts
35
- ├── tests/lib/cortex/boundary/access.test.ts
36
- ├── tests/lib/cortex/boundary/audit.test.ts
37
- ```
38
-
39
- ---
40
-
41
- ## Chunk 1: Auto-Classification and Policy Engine
42
-
43
- ### Task 1: Sensitivity auto-classifier
44
-
45
- **Files:**
46
- - Create: `src/lib/cortex/boundary/classifier.ts`
47
- - Create: `tests/lib/cortex/boundary/classifier.test.ts`
48
-
49
- - [ ] **Step 1: Write failing tests**
50
-
51
- ```typescript
52
- // tests/lib/cortex/boundary/classifier.test.ts
53
- import { describe, it, expect } from 'vitest';
54
- import { classifySensitivity } from '@/lib/cortex/boundary/classifier';
55
-
56
- describe('classifySensitivity', () => {
57
- it('classifies secrets as confidential', () => {
58
- expect(classifySensitivity('Set API_KEY=sk-ant-abc123 in .env')).toBe('confidential');
59
- expect(classifySensitivity('password: hunter2')).toBe('confidential');
60
- expect(classifySensitivity('DATABASE_URL=postgres://user:pass@host')).toBe('confidential');
61
- });
62
-
63
- it('classifies personnel content as confidential', () => {
64
- expect(classifySensitivity('Alice performance review: exceeds expectations')).toBe('confidential');
65
- expect(classifySensitivity('salary adjustment from 120k to 140k')).toBe('confidential');
66
- });
67
-
68
- it('classifies security content as restricted', () => {
69
- expect(classifySensitivity('Found SQL injection vulnerability in login endpoint')).toBe('restricted');
70
- expect(classifySensitivity('CVE-2024-1234 affects our auth library')).toBe('restricted');
71
- });
72
-
73
- it('classifies business content as restricted', () => {
74
- expect(classifySensitivity('Q3 revenue was $2.5M, below target')).toBe('restricted');
75
- expect(classifySensitivity('Unreleased product launch planned for April')).toBe('restricted');
76
- });
77
-
78
- it('classifies technical content as internal', () => {
79
- expect(classifySensitivity('We decided to use PostgreSQL for the new service')).toBe('internal');
80
- expect(classifySensitivity('The auth middleware handles JWT validation')).toBe('internal');
81
- });
82
-
83
- it('classifies general content as public', () => {
84
- expect(classifySensitivity('How to use git rebase')).toBe('public');
85
- expect(classifySensitivity('JavaScript array methods')).toBe('public');
86
- });
87
-
88
- it('returns most restrictive when multiple detectors match', () => {
89
- // Has both secret (confidential) and security (restricted) signals
90
- expect(classifySensitivity('API_KEY leaked in CVE-2024-1234')).toBe('confidential');
91
- });
92
- });
93
- ```
94
-
95
- - [ ] **Step 2: Implement classifier**
96
-
97
- ```typescript
98
- // src/lib/cortex/boundary/classifier.ts
99
- import type { SensitivityClass } from '../knowledge/types';
100
-
101
- interface Detector {
102
- sensitivity: SensitivityClass;
103
- patterns: RegExp[];
104
- priority: number; // higher = more restrictive
105
- }
106
-
107
- const DETECTORS: Detector[] = [
108
- {
109
- sensitivity: 'confidential',
110
- priority: 4,
111
- patterns: [
112
- // Secrets
113
- /\b(api[_-]?key|secret[_-]?key|access[_-]?token|auth[_-]?token)\s*[=:]/i,
114
- /\b(password|passwd|pwd)\s*[=:]/i,
115
- /\bsk-[a-z]{2,4}-[a-zA-Z0-9]{10,}/, // Anthropic/OpenAI key format
116
- /\b(DATABASE_URL|REDIS_URL|MONGO_URI)\s*=/i,
117
- /\bpostgres:\/\/\w+:\w+@/i,
118
- /\b(private[_-]?key|ssh[_-]?key)\b/i,
119
- // Personnel
120
- /\b(performance\s+review|annual\s+review)\b/i,
121
- /\b(salary|compensation|pay\s+raise|pay\s+cut)\b/i,
122
- /\b(hiring|termination|fired|let\s+go)\b/i,
123
- /\b(1:1\s+notes?|one[\s-]on[\s-]one)\b/i,
124
- ],
125
- },
126
- {
127
- sensitivity: 'restricted',
128
- priority: 3,
129
- patterns: [
130
- // Security
131
- /\b(vulnerab|exploit|attack\s+vector|injection|xss|csrf|ssrf)\b/i,
132
- /\bCVE-\d{4}-\d+/i,
133
- /\b(incident\s+report|security\s+breach|data\s+leak)\b/i,
134
- // Business
135
- /\b(revenue|profit|loss|earnings|ARR|MRR)\b/i,
136
- /\b(unreleased|pre-launch|confidential\s+plan|roadmap)\b/i,
137
- /\bcustomer\s+(data|records|PII)\b/i,
138
- ],
139
- },
140
- {
141
- sensitivity: 'internal',
142
- priority: 2,
143
- patterns: [
144
- /\b(we\s+decided|architecture|design\s+pattern|refactor)\b/i,
145
- /\b(middleware|service|endpoint|database|schema)\b/i,
146
- /\b(deployment|CI\/CD|pipeline|infrastructure)\b/i,
147
- /\b(bug\s+fix|pull\s+request|code\s+review)\b/i,
148
- ],
149
- },
150
- ];
151
-
152
- export function classifySensitivity(text: string): SensitivityClass {
153
- let highestPriority = 0;
154
- let result: SensitivityClass = 'public';
155
-
156
- for (const detector of DETECTORS) {
157
- if (detector.priority <= highestPriority) continue;
158
- for (const pattern of detector.patterns) {
159
- if (pattern.test(text)) {
160
- highestPriority = detector.priority;
161
- result = detector.sensitivity;
162
- break;
163
- }
164
- }
165
- }
166
-
167
- return result;
168
- }
169
- ```
170
-
171
- - [ ] **Step 3: Run tests, commit**
172
-
173
- ```bash
174
- git commit -m "feat(cortex): add sensitivity auto-classifier for boundary engine"
175
- ```
176
-
177
- ---
178
-
179
- ### Task 2: Policy engine
180
-
181
- **Files:**
182
- - Create: `src/lib/cortex/boundary/policy.ts`
183
- - Create: `tests/lib/cortex/boundary/policy.test.ts`
184
-
185
- - [ ] **Step 1: Write failing tests**
186
-
187
- ```typescript
188
- // tests/lib/cortex/boundary/policy.test.ts
189
- import { describe, it, expect } from 'vitest';
190
- import { PolicyEngine } from '@/lib/cortex/boundary/policy';
191
- import type { Policy } from '@/lib/cortex/boundary/policy';
192
-
193
- describe('PolicyEngine', () => {
194
- it('returns empty actions when no policies match', () => {
195
- const engine = new PolicyEngine([]);
196
- const actions = engine.evaluate({ type: 'decision', sensitivity: 'internal' });
197
- expect(actions).toEqual([]);
198
- });
199
-
200
- it('matches by knowledge type', () => {
201
- const policies: Policy[] = [{
202
- name: 'arch-decisions-propagate',
203
- match: { type: 'decision' },
204
- action: { propagate_to: [{ level: 'department' }] },
205
- }];
206
- const engine = new PolicyEngine(policies);
207
- const actions = engine.evaluate({ type: 'decision', sensitivity: 'internal' });
208
- expect(actions).toHaveLength(1);
209
- expect(actions[0].propagate_to).toEqual([{ level: 'department' }]);
210
- });
211
-
212
- it('matches by sensitivity', () => {
213
- const policies: Policy[] = [{
214
- name: 'lock-confidential',
215
- match: { sensitivity: 'confidential' },
216
- action: { cannot_propagate: true },
217
- }];
218
- const engine = new PolicyEngine(policies);
219
- const actions = engine.evaluate({ type: 'pattern', sensitivity: 'confidential' });
220
- expect(actions).toHaveLength(1);
221
- expect(actions[0].cannot_propagate).toBe(true);
222
- });
223
-
224
- it('matches by topics', () => {
225
- const policies: Policy[] = [{
226
- name: 'security-routing',
227
- match: { topics: ['security', 'vulnerability'] },
228
- action: { max_scope: 'department', propagate_to: [{ level: 'team', entity_id: 'team-security' }] },
229
- }];
230
- const engine = new PolicyEngine(policies);
231
- const actions = engine.evaluate({ type: 'error_fix', sensitivity: 'restricted', topics: ['security'] });
232
- expect(actions).toHaveLength(1);
233
- expect(actions[0].max_scope).toBe('department');
234
- });
235
-
236
- it('returns multiple matching policies', () => {
237
- const policies: Policy[] = [
238
- { name: 'p1', match: { type: 'decision' }, action: { trickle_down: true } },
239
- { name: 'p2', match: { sensitivity: 'internal' }, action: { max_scope: 'organization' } },
240
- ];
241
- const engine = new PolicyEngine(policies);
242
- const actions = engine.evaluate({ type: 'decision', sensitivity: 'internal' });
243
- expect(actions).toHaveLength(2);
244
- });
245
-
246
- it('does not match when criteria do not overlap', () => {
247
- const policies: Policy[] = [{
248
- name: 'security-only',
249
- match: { topics: ['security'] },
250
- action: { cannot_propagate: true },
251
- }];
252
- const engine = new PolicyEngine(policies);
253
- const actions = engine.evaluate({ type: 'decision', sensitivity: 'internal', topics: ['architecture'] });
254
- expect(actions).toHaveLength(0);
255
- });
256
- });
257
- ```
258
-
259
- - [ ] **Step 2: Implement policy engine**
260
-
261
- ```typescript
262
- // src/lib/cortex/boundary/policy.ts
263
- import type { KnowledgeType, SensitivityClass, ScopeLevel } from '../knowledge/types';
264
-
265
- export interface PropagationTarget {
266
- level: ScopeLevel;
267
- entity_id?: string;
268
- }
269
-
270
- export interface PolicyAction {
271
- max_scope?: ScopeLevel;
272
- propagate_to?: PropagationTarget[];
273
- trickle_down?: boolean;
274
- cannot_propagate?: boolean;
275
- }
276
-
277
- export interface Policy {
278
- name: string;
279
- match: {
280
- type?: KnowledgeType;
281
- topics?: string[];
282
- sensitivity?: SensitivityClass;
283
- scope_level?: ScopeLevel;
284
- };
285
- action: PolicyAction;
286
- }
287
-
288
- export interface PolicyMatchInput {
289
- type: KnowledgeType | string;
290
- sensitivity: SensitivityClass | string;
291
- topics?: string[];
292
- scope_level?: ScopeLevel | string;
293
- }
294
-
295
- export class PolicyEngine {
296
- constructor(private policies: Policy[]) {}
297
-
298
- evaluate(input: PolicyMatchInput): PolicyAction[] {
299
- const matched: PolicyAction[] = [];
300
-
301
- for (const policy of this.policies) {
302
- if (this.matches(policy, input)) {
303
- matched.push(policy.action);
304
- }
305
- }
306
-
307
- return matched;
308
- }
309
-
310
- private matches(policy: Policy, input: PolicyMatchInput): boolean {
311
- const { match } = policy;
312
-
313
- if (match.type && match.type !== input.type) return false;
314
- if (match.sensitivity && match.sensitivity !== input.sensitivity) return false;
315
- if (match.scope_level && match.scope_level !== input.scope_level) return false;
316
-
317
- if (match.topics && match.topics.length > 0) {
318
- const inputTopics = input.topics ?? [];
319
- const hasOverlap = match.topics.some(t => inputTopics.includes(t));
320
- if (!hasOverlap) return false;
321
- }
322
-
323
- return true;
324
- }
325
- }
326
- ```
327
-
328
- - [ ] **Step 3: Run tests, commit**
329
-
330
- ```bash
331
- git commit -m "feat(cortex): add policy engine for boundary enforcement"
332
- ```
333
-
334
- ---
335
-
336
- ## Chunk 2: Access Filter and Audit Trail
337
-
338
- ### Task 3: Query-time access filter
339
-
340
- **Files:**
341
- - Create: `src/lib/cortex/boundary/access.ts`
342
- - Create: `tests/lib/cortex/boundary/access.test.ts`
343
-
344
- - [ ] **Step 1: Write failing tests**
345
-
346
- ```typescript
347
- // tests/lib/cortex/boundary/access.test.ts
348
- import { describe, it, expect } from 'vitest';
349
- import { AccessFilter } from '@/lib/cortex/boundary/access';
350
- import type { ScoredKnowledge } from '@/lib/cortex/knowledge/types';
351
-
352
- function makeUnit(overrides: Partial<ScoredKnowledge> = {}): ScoredKnowledge {
353
- return {
354
- id: 'k1', vector: [], text: 'test', type: 'decision', layer: 'personal',
355
- workspace_id: null, session_id: null, agent_type: 'claude',
356
- project_path: null, file_refs: [], confidence: 0.8,
357
- created: new Date().toISOString(), source_timestamp: new Date().toISOString(),
358
- stale_score: 0, access_count: 0, last_accessed: null, metadata: {},
359
- relevance_score: 0.9, similarity: 0.9,
360
- sensitivity: 'internal',
361
- scope: { level: 'personal', entity_id: 'person-alice' },
362
- origin: { source_type: 'conversation', source_ref: '', creator_entity_id: 'person-alice' },
363
- ...overrides,
364
- };
365
- }
366
-
367
- describe('AccessFilter', () => {
368
- const filter = new AccessFilter({
369
- requesterId: 'person-alice',
370
- requesterScope: { level: 'team', entity_id: 'team-platform' },
371
- requesterOrg: 'organization-acme',
372
- });
373
-
374
- it('allows public knowledge from anywhere in org', () => {
375
- const unit = makeUnit({ sensitivity: 'public', scope: { level: 'organization', entity_id: 'org-acme' } });
376
- expect(filter.canAccess(unit)).toBe(true);
377
- });
378
-
379
- it('allows internal knowledge within org', () => {
380
- const unit = makeUnit({ sensitivity: 'internal', scope: { level: 'team', entity_id: 'team-other' } });
381
- expect(filter.canAccess(unit)).toBe(true);
382
- });
383
-
384
- it('allows restricted knowledge within same scope', () => {
385
- const unit = makeUnit({
386
- sensitivity: 'restricted',
387
- scope: { level: 'team', entity_id: 'team-platform' },
388
- });
389
- expect(filter.canAccess(unit)).toBe(true);
390
- });
391
-
392
- it('denies restricted knowledge from different department', () => {
393
- const unit = makeUnit({
394
- sensitivity: 'restricted',
395
- scope: { level: 'department', entity_id: 'department-sales' },
396
- });
397
- // Alice is in team-platform, not department-sales
398
- expect(filter.canAccess(unit)).toBe(false);
399
- });
400
-
401
- it('allows confidential knowledge from self', () => {
402
- const unit = makeUnit({
403
- sensitivity: 'confidential',
404
- scope: { level: 'personal', entity_id: 'person-alice' },
405
- origin: { source_type: 'conversation', source_ref: '', creator_entity_id: 'person-alice' },
406
- });
407
- expect(filter.canAccess(unit)).toBe(true);
408
- });
409
-
410
- it('denies confidential knowledge from others', () => {
411
- const unit = makeUnit({
412
- sensitivity: 'confidential',
413
- scope: { level: 'personal', entity_id: 'person-bob' },
414
- origin: { source_type: 'conversation', source_ref: '', creator_entity_id: 'person-bob' },
415
- });
416
- expect(filter.canAccess(unit)).toBe(false);
417
- });
418
-
419
- it('respects creator_scope override (further restriction)', () => {
420
- const unit = makeUnit({
421
- sensitivity: 'internal', // normally accessible org-wide
422
- creator_scope: { max_level: 'personal' }, // but creator restricted to personal only
423
- scope: { level: 'personal', entity_id: 'person-bob' },
424
- });
425
- // Alice can't access Bob's personal-restricted knowledge even though it's internal
426
- expect(filter.canAccess(unit)).toBe(false);
427
- });
428
-
429
- it('filters a list of results', () => {
430
- const results = [
431
- makeUnit({ id: 'a', sensitivity: 'public' }),
432
- makeUnit({ id: 'b', sensitivity: 'confidential', origin: { source_type: 'conversation', source_ref: '', creator_entity_id: 'person-bob' } }),
433
- makeUnit({ id: 'c', sensitivity: 'internal' }),
434
- ];
435
- const filtered = filter.filterResults(results);
436
- expect(filtered).toHaveLength(2); // a and c pass, b denied
437
- expect(filtered.map(r => r.id)).toEqual(['a', 'c']);
438
- });
439
- });
440
- ```
441
-
442
- - [ ] **Step 2: Implement access filter**
443
-
444
- ```typescript
445
- // src/lib/cortex/boundary/access.ts
446
- import type { ScoredKnowledge, Scope, ScopeLevel, SensitivityClass } from '../knowledge/types';
447
-
448
- const SCOPE_HIERARCHY: Record<ScopeLevel, number> = {
449
- personal: 0,
450
- team: 1,
451
- department: 2,
452
- organization: 3,
453
- };
454
-
455
- export interface AccessFilterConfig {
456
- requesterId: string;
457
- requesterScope: Scope; // requester's team scope
458
- requesterOrg: string; // requester's org entity_id
459
- grants?: Set<string>; // knowledge IDs the requester has been granted access to
460
- }
461
-
462
- export class AccessFilter {
463
- private config: AccessFilterConfig;
464
-
465
- constructor(config: AccessFilterConfig) {
466
- this.config = config;
467
- }
468
-
469
- canAccess(unit: ScoredKnowledge): boolean {
470
- const sensitivity = (unit.sensitivity ?? 'internal') as SensitivityClass;
471
- const unitScope = unit.scope ?? { level: 'personal' as ScopeLevel, entity_id: '' };
472
- const creatorId = unit.origin?.creator_entity_id ?? '';
473
-
474
- // Check creator_scope override first — most restrictive wins
475
- if (unit.creator_scope) {
476
- const maxLevel = SCOPE_HIERARCHY[unit.creator_scope.max_level] ?? 0;
477
- const requesterLevel = this.getRequesterProximityLevel(unitScope);
478
- if (requesterLevel > maxLevel) return false;
479
- }
480
-
481
- switch (sensitivity) {
482
- case 'public':
483
- return true;
484
-
485
- case 'internal':
486
- // Accessible to anyone in the same org
487
- return true;
488
-
489
- case 'restricted':
490
- // Accessible within same scope or if policy grants cross-scope access
491
- return this.isWithinScope(unitScope);
492
-
493
- case 'confidential':
494
- // Only creator or explicit grant
495
- if (this.config.requesterId === creatorId) return true;
496
- if (this.config.grants?.has(unit.id)) return true;
497
- return false;
498
-
499
- default:
500
- return false;
501
- }
502
- }
503
-
504
- filterResults(results: ScoredKnowledge[]): ScoredKnowledge[] {
505
- return results.filter(r => this.canAccess(r));
506
- }
507
-
508
- private isWithinScope(unitScope: Scope): boolean {
509
- // Same entity_id = same scope
510
- if (unitScope.entity_id === this.config.requesterScope.entity_id) return true;
511
- if (unitScope.entity_id === this.config.requesterId) return true;
512
- // Same org for org-level scopes
513
- if (unitScope.level === 'organization' && unitScope.entity_id === this.config.requesterOrg) return true;
514
- return false;
515
- }
516
-
517
- private getRequesterProximityLevel(unitScope: Scope): number {
518
- // How "far" is the requester from the unit's scope?
519
- // 0 = same entity, 1 = same scope level, 2+ = further
520
- if (unitScope.entity_id === this.config.requesterId) return 0;
521
- if (unitScope.entity_id === this.config.requesterScope.entity_id) return 0;
522
- return SCOPE_HIERARCHY[unitScope.level] ?? 3;
523
- }
524
- }
525
- ```
526
-
527
- - [ ] **Step 3: Run tests, commit**
528
-
529
- ```bash
530
- git commit -m "feat(cortex): add query-time access filter for boundary enforcement"
531
- ```
532
-
533
- ---
534
-
535
- ### Task 4: Audit trail
536
-
537
- **Files:**
538
- - Create: `src/lib/cortex/boundary/audit.ts`
539
- - Create: `tests/lib/cortex/boundary/audit.test.ts`
540
-
541
- - [ ] **Step 1: Write failing tests**
542
-
543
- ```typescript
544
- // tests/lib/cortex/boundary/audit.test.ts
545
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
546
- import fs from 'fs';
547
- import path from 'path';
548
- import os from 'os';
549
- import Database from 'better-sqlite3';
550
- import { AuditLog } from '@/lib/cortex/boundary/audit';
551
-
552
- describe('AuditLog', () => {
553
- let tmpDir: string;
554
- let audit: AuditLog;
555
-
556
- beforeEach(() => {
557
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cortex-audit-'));
558
- const db = new Database(path.join(tmpDir, 'graph.db'));
559
- audit = new AuditLog(db);
560
- });
561
-
562
- afterEach(() => {
563
- fs.rmSync(tmpDir, { recursive: true, force: true });
564
- });
565
-
566
- it('logs an access decision', () => {
567
- audit.log({
568
- requesterId: 'person-alice',
569
- knowledgeId: 'k1',
570
- action: 'allowed',
571
- reason: 'public sensitivity',
572
- });
573
- const entries = audit.query({ requesterId: 'person-alice' });
574
- expect(entries).toHaveLength(1);
575
- expect(entries[0].action).toBe('allowed');
576
- });
577
-
578
- it('logs denied access', () => {
579
- audit.log({
580
- requesterId: 'person-alice',
581
- knowledgeId: 'k2',
582
- action: 'denied',
583
- reason: 'confidential, not creator',
584
- });
585
- const entries = audit.query({ requesterId: 'person-alice' });
586
- expect(entries).toHaveLength(1);
587
- expect(entries[0].action).toBe('denied');
588
- });
589
-
590
- it('queries by time range', () => {
591
- audit.log({ requesterId: 'person-alice', knowledgeId: 'k1', action: 'allowed', reason: 'public' });
592
- const recent = audit.query({ since: new Date(Date.now() - 60000).toISOString() });
593
- expect(recent).toHaveLength(1);
594
-
595
- const future = audit.query({ since: new Date(Date.now() + 60000).toISOString() });
596
- expect(future).toHaveLength(0);
597
- });
598
-
599
- it('supports retention cleanup', () => {
600
- audit.log({ requesterId: 'person-alice', knowledgeId: 'k1', action: 'allowed', reason: 'test' });
601
- // Cleanup entries older than 0 days (everything)
602
- audit.cleanup(0);
603
- const entries = audit.query({});
604
- expect(entries).toHaveLength(0);
605
- });
606
- });
607
- ```
608
-
609
- - [ ] **Step 2: Implement audit log**
610
-
611
- ```typescript
612
- // src/lib/cortex/boundary/audit.ts
613
- import type Database from 'better-sqlite3';
614
-
615
- export interface AuditEntry {
616
- requesterId: string;
617
- knowledgeId: string;
618
- action: 'allowed' | 'denied';
619
- reason: string;
620
- }
621
-
622
- export interface AuditQueryFilter {
623
- requesterId?: string;
624
- since?: string; // ISO timestamp
625
- limit?: number;
626
- }
627
-
628
- export interface AuditRecord extends AuditEntry {
629
- timestamp: string;
630
- }
631
-
632
- export class AuditLog {
633
- private db: InstanceType<typeof Database>;
634
-
635
- constructor(db: InstanceType<typeof Database>) {
636
- this.db = db;
637
- this.db.exec(`
638
- CREATE TABLE IF NOT EXISTS audit_log (
639
- id INTEGER PRIMARY KEY AUTOINCREMENT,
640
- requester_id TEXT NOT NULL,
641
- knowledge_id TEXT NOT NULL,
642
- action TEXT NOT NULL,
643
- reason TEXT NOT NULL,
644
- timestamp TEXT NOT NULL
645
- );
646
- CREATE INDEX IF NOT EXISTS idx_audit_requester ON audit_log(requester_id);
647
- CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_log(timestamp);
648
- `);
649
- }
650
-
651
- log(entry: AuditEntry): void {
652
- this.db.prepare(`
653
- INSERT INTO audit_log (requester_id, knowledge_id, action, reason, timestamp)
654
- VALUES (?, ?, ?, ?, ?)
655
- `).run(entry.requesterId, entry.knowledgeId, entry.action, entry.reason, new Date().toISOString());
656
- }
657
-
658
- query(filter: AuditQueryFilter): AuditRecord[] {
659
- let sql = 'SELECT * FROM audit_log WHERE 1=1';
660
- const params: any[] = [];
661
-
662
- if (filter.requesterId) {
663
- sql += ' AND requester_id = ?';
664
- params.push(filter.requesterId);
665
- }
666
- if (filter.since) {
667
- sql += ' AND timestamp >= ?';
668
- params.push(filter.since);
669
- }
670
-
671
- sql += ' ORDER BY timestamp DESC';
672
-
673
- if (filter.limit) {
674
- sql += ' LIMIT ?';
675
- params.push(filter.limit);
676
- }
677
-
678
- return (this.db.prepare(sql).all(...params) as any[]).map(row => ({
679
- requesterId: row.requester_id,
680
- knowledgeId: row.knowledge_id,
681
- action: row.action,
682
- reason: row.reason,
683
- timestamp: row.timestamp,
684
- }));
685
- }
686
-
687
- cleanup(retentionDays: number): void {
688
- const cutoff = new Date(Date.now() - retentionDays * 86400000).toISOString();
689
- this.db.prepare('DELETE FROM audit_log WHERE timestamp < ?').run(cutoff);
690
- }
691
- }
692
- ```
693
-
694
- - [ ] **Step 3: Run tests, commit**
695
-
696
- ```bash
697
- git commit -m "feat(cortex): add audit trail for access decisions"
698
- ```
699
-
700
- ---
701
-
702
- ## Chunk 3: Integration
703
-
704
- ### Task 5: Integrate with ingestion pipeline
705
-
706
- **Files:**
707
- - Modify: `src/lib/cortex/ingestion/pipeline.ts`
708
-
709
- - [ ] **Step 1: Read pipeline.ts**
710
-
711
- - [ ] **Step 2: Add auto-classification during ingestion**
712
-
713
- Import the classifier:
714
- ```typescript
715
- import { classifySensitivity } from '../boundary/classifier';
716
- ```
717
-
718
- In the KnowledgeUnit construction (where v2 fields are set), replace the hardcoded `sensitivity: 'internal'` with:
719
- ```typescript
720
- sensitivity: classifySensitivity(chunk.text),
721
- ```
722
-
723
- This ensures every ingested knowledge unit gets an auto-classified sensitivity level.
724
-
725
- - [ ] **Step 3: Run pipeline tests to verify no regressions**
726
-
727
- ```bash
728
- npx vitest run tests/lib/cortex/ingestion/
729
- ```
730
-
731
- - [ ] **Step 4: Commit**
732
-
733
- ```bash
734
- git commit -m "feat(cortex): auto-classify sensitivity during ingestion"
735
- ```
736
-
737
- ---
738
-
739
- ### Task 6: Integrate AccessFilter with ContextEngine
740
-
741
- **Files:**
742
- - Modify: `src/lib/cortex/retrieval/context-engine.ts`
743
-
744
- - [ ] **Step 1: Read context-engine.ts**
745
-
746
- - [ ] **Step 2: Add AccessFilter to the pipeline**
747
-
748
- Import AccessFilter:
749
- ```typescript
750
- import { AccessFilter } from '../boundary/access';
751
- ```
752
-
753
- Add to `ContextEngineDeps`:
754
- ```typescript
755
- accessFilter?: AccessFilter;
756
- ```
757
-
758
- In the `assemble()` method, after fusion/ranking (Stage 5) but before conflict detection (Stage 6), apply the access filter:
759
-
760
- ```typescript
761
- // Stage 5.5: Access control filtering
762
- let accessible = fused;
763
- if (this.deps.accessFilter) {
764
- accessible = this.deps.accessFilter.filterResults(fused);
765
- }
766
- ```
767
-
768
- Then pass `accessible` (not `fused`) to conflict detection and formatting.
769
-
770
- - [ ] **Step 3: Run context-engine tests to verify no regressions**
771
-
772
- ```bash
773
- npx vitest run tests/lib/cortex/retrieval/context-engine.test.ts
774
- ```
775
-
776
- - [ ] **Step 4: Commit**
777
-
778
- ```bash
779
- git commit -m "feat(cortex): integrate access filter into context assembly pipeline"
780
- ```
781
-
782
- ---
783
-
784
- ### Task 7: Barrel export and config integration
785
-
786
- **Files:**
787
- - Create: `src/lib/cortex/boundary/index.ts`
788
- - Modify: `src/lib/cortex/config.ts` (add policies array to config)
789
-
790
- - [ ] **Step 1: Create barrel export**
791
-
792
- ```typescript
793
- // src/lib/cortex/boundary/index.ts
794
- export { classifySensitivity } from './classifier';
795
- export { PolicyEngine } from './policy';
796
- export type { Policy, PolicyAction, PropagationTarget } from './policy';
797
- export { AccessFilter } from './access';
798
- export type { AccessFilterConfig } from './access';
799
- export { AuditLog } from './audit';
800
- export type { AuditEntry, AuditRecord, AuditQueryFilter } from './audit';
801
- ```
802
-
803
- - [ ] **Step 2: Add policies to CortexConfig**
804
-
805
- In `src/lib/cortex/config.ts`, add to the `CortexConfig` interface:
806
- ```typescript
807
- policies?: Policy[]; // Organizational boundary policies
808
- ```
809
-
810
- And in `DEFAULT_CORTEX_CONFIG`:
811
- ```typescript
812
- policies: [],
813
- ```
814
-
815
- Import the Policy type:
816
- ```typescript
817
- import type { Policy } from './boundary/policy';
818
- ```
819
-
820
- - [ ] **Step 3: Run full test suite**
821
-
822
- ```bash
823
- npx vitest run tests/lib/cortex/
824
- ```
825
-
826
- - [ ] **Step 4: Commit**
827
-
828
- ```bash
829
- git commit -m "feat(cortex): add boundary module barrel export and config integration"
830
- ```
831
-
832
- ---
833
-
834
- ## Summary
835
-
836
- | Task | Component | Tests | Status |
837
- |------|-----------|-------|--------|
838
- | 1 | Sensitivity classifier | 7 | |
839
- | 2 | Policy engine | 6 | |
840
- | 3 | Access filter | 8 | |
841
- | 4 | Audit trail | 4 | |
842
- | 5 | Pipeline integration | regression | |
843
- | 6 | ContextEngine integration | regression | |
844
- | 7 | Barrel export + config | regression | |
845
-
846
- **Total: 7 tasks, ~25 new tests, 3 chunks**
847
-
848
- **Key design decisions:**
849
- - Auto-classification is regex-based (no LLM call) — fast, deterministic, auditable
850
- - Policies are stored in CortexConfig (admin-editable JSON) — not code
851
- - AccessFilter is a separate class that can be composed with ContextEngine or used standalone
852
- - Audit log uses the entity graph's SQLite DB (same file, new table) — no new database
853
- - Most restrictive classification always wins (confidential > restricted > internal > public)
1
+ # Cortex v2 — Pillar 4: Boundary Engine
2
+
3
+ > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Add three-layer access control to Cortex: auto-classification of sensitivity, organizational policies, and creator overrides — ensuring confidential knowledge never leaks across scope boundaries.
6
+
7
+ **Architecture:** A new `src/lib/cortex/boundary/` module with three components: a `Classifier` (regex-based sensitivity detection), a `PolicyEngine` (rule evaluation), and an `AccessFilter` (query-time enforcement). The AccessFilter integrates with the ContextEngine to pre-filter scopes before search. An audit log records all access decisions in the entity graph's SQLite database.
8
+
9
+ **Tech Stack:** TypeScript, better-sqlite3 (existing graph DB), vitest
10
+
11
+ **Spec:** `docs/superpowers/specs/2026-03-14-cortex-v2-design.md` — Pillar 4
12
+
13
+ **Depends on:** Pillar 1 (Entity Graph) + Pillar 2 (Knowledge Unit Evolution) — both completed
14
+
15
+ ---
16
+
17
+ ## File Structure
18
+
19
+ ```
20
+ New files:
21
+ ├── src/lib/cortex/boundary/classifier.ts — Auto-classification (Layer 1)
22
+ ├── src/lib/cortex/boundary/policy.ts — Policy engine (Layer 2)
23
+ ├── src/lib/cortex/boundary/access.ts — Query-time access filter (Layer 3 + enforcement)
24
+ ├── src/lib/cortex/boundary/audit.ts — Audit trail logging
25
+ ├── src/lib/cortex/boundary/index.ts — Barrel export
26
+
27
+ Modified files:
28
+ ├── src/lib/cortex/ingestion/pipeline.ts — Auto-classify on ingestion
29
+ ├── src/lib/cortex/retrieval/context-engine.ts — Pre-filter with AccessFilter
30
+ ├── src/lib/cortex/config.ts — Add policies to config
31
+
32
+ Test files:
33
+ ├── tests/lib/cortex/boundary/classifier.test.ts
34
+ ├── tests/lib/cortex/boundary/policy.test.ts
35
+ ├── tests/lib/cortex/boundary/access.test.ts
36
+ ├── tests/lib/cortex/boundary/audit.test.ts
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Chunk 1: Auto-Classification and Policy Engine
42
+
43
+ ### Task 1: Sensitivity auto-classifier
44
+
45
+ **Files:**
46
+ - Create: `src/lib/cortex/boundary/classifier.ts`
47
+ - Create: `tests/lib/cortex/boundary/classifier.test.ts`
48
+
49
+ - [ ] **Step 1: Write failing tests**
50
+
51
+ ```typescript
52
+ // tests/lib/cortex/boundary/classifier.test.ts
53
+ import { describe, it, expect } from 'vitest';
54
+ import { classifySensitivity } from '@/lib/cortex/boundary/classifier';
55
+
56
+ describe('classifySensitivity', () => {
57
+ it('classifies secrets as confidential', () => {
58
+ expect(classifySensitivity('Set API_KEY=sk-ant-abc123 in .env')).toBe('confidential');
59
+ expect(classifySensitivity('password: hunter2')).toBe('confidential');
60
+ expect(classifySensitivity('DATABASE_URL=postgres://user:pass@host')).toBe('confidential');
61
+ });
62
+
63
+ it('classifies personnel content as confidential', () => {
64
+ expect(classifySensitivity('Alice performance review: exceeds expectations')).toBe('confidential');
65
+ expect(classifySensitivity('salary adjustment from 120k to 140k')).toBe('confidential');
66
+ });
67
+
68
+ it('classifies security content as restricted', () => {
69
+ expect(classifySensitivity('Found SQL injection vulnerability in login endpoint')).toBe('restricted');
70
+ expect(classifySensitivity('CVE-2024-1234 affects our auth library')).toBe('restricted');
71
+ });
72
+
73
+ it('classifies business content as restricted', () => {
74
+ expect(classifySensitivity('Q3 revenue was $2.5M, below target')).toBe('restricted');
75
+ expect(classifySensitivity('Unreleased product launch planned for April')).toBe('restricted');
76
+ });
77
+
78
+ it('classifies technical content as internal', () => {
79
+ expect(classifySensitivity('We decided to use PostgreSQL for the new service')).toBe('internal');
80
+ expect(classifySensitivity('The auth middleware handles JWT validation')).toBe('internal');
81
+ });
82
+
83
+ it('classifies general content as public', () => {
84
+ expect(classifySensitivity('How to use git rebase')).toBe('public');
85
+ expect(classifySensitivity('JavaScript array methods')).toBe('public');
86
+ });
87
+
88
+ it('returns most restrictive when multiple detectors match', () => {
89
+ // Has both secret (confidential) and security (restricted) signals
90
+ expect(classifySensitivity('API_KEY leaked in CVE-2024-1234')).toBe('confidential');
91
+ });
92
+ });
93
+ ```
94
+
95
+ - [ ] **Step 2: Implement classifier**
96
+
97
+ ```typescript
98
+ // src/lib/cortex/boundary/classifier.ts
99
+ import type { SensitivityClass } from '../knowledge/types';
100
+
101
+ interface Detector {
102
+ sensitivity: SensitivityClass;
103
+ patterns: RegExp[];
104
+ priority: number; // higher = more restrictive
105
+ }
106
+
107
+ const DETECTORS: Detector[] = [
108
+ {
109
+ sensitivity: 'confidential',
110
+ priority: 4,
111
+ patterns: [
112
+ // Secrets
113
+ /\b(api[_-]?key|secret[_-]?key|access[_-]?token|auth[_-]?token)\s*[=:]/i,
114
+ /\b(password|passwd|pwd)\s*[=:]/i,
115
+ /\bsk-[a-z]{2,4}-[a-zA-Z0-9]{10,}/, // Anthropic/OpenAI key format
116
+ /\b(DATABASE_URL|REDIS_URL|MONGO_URI)\s*=/i,
117
+ /\bpostgres:\/\/\w+:\w+@/i,
118
+ /\b(private[_-]?key|ssh[_-]?key)\b/i,
119
+ // Personnel
120
+ /\b(performance\s+review|annual\s+review)\b/i,
121
+ /\b(salary|compensation|pay\s+raise|pay\s+cut)\b/i,
122
+ /\b(hiring|termination|fired|let\s+go)\b/i,
123
+ /\b(1:1\s+notes?|one[\s-]on[\s-]one)\b/i,
124
+ ],
125
+ },
126
+ {
127
+ sensitivity: 'restricted',
128
+ priority: 3,
129
+ patterns: [
130
+ // Security
131
+ /\b(vulnerab|exploit|attack\s+vector|injection|xss|csrf|ssrf)\b/i,
132
+ /\bCVE-\d{4}-\d+/i,
133
+ /\b(incident\s+report|security\s+breach|data\s+leak)\b/i,
134
+ // Business
135
+ /\b(revenue|profit|loss|earnings|ARR|MRR)\b/i,
136
+ /\b(unreleased|pre-launch|confidential\s+plan|roadmap)\b/i,
137
+ /\bcustomer\s+(data|records|PII)\b/i,
138
+ ],
139
+ },
140
+ {
141
+ sensitivity: 'internal',
142
+ priority: 2,
143
+ patterns: [
144
+ /\b(we\s+decided|architecture|design\s+pattern|refactor)\b/i,
145
+ /\b(middleware|service|endpoint|database|schema)\b/i,
146
+ /\b(deployment|CI\/CD|pipeline|infrastructure)\b/i,
147
+ /\b(bug\s+fix|pull\s+request|code\s+review)\b/i,
148
+ ],
149
+ },
150
+ ];
151
+
152
+ export function classifySensitivity(text: string): SensitivityClass {
153
+ let highestPriority = 0;
154
+ let result: SensitivityClass = 'public';
155
+
156
+ for (const detector of DETECTORS) {
157
+ if (detector.priority <= highestPriority) continue;
158
+ for (const pattern of detector.patterns) {
159
+ if (pattern.test(text)) {
160
+ highestPriority = detector.priority;
161
+ result = detector.sensitivity;
162
+ break;
163
+ }
164
+ }
165
+ }
166
+
167
+ return result;
168
+ }
169
+ ```
170
+
171
+ - [ ] **Step 3: Run tests, commit**
172
+
173
+ ```bash
174
+ git commit -m "feat(cortex): add sensitivity auto-classifier for boundary engine"
175
+ ```
176
+
177
+ ---
178
+
179
+ ### Task 2: Policy engine
180
+
181
+ **Files:**
182
+ - Create: `src/lib/cortex/boundary/policy.ts`
183
+ - Create: `tests/lib/cortex/boundary/policy.test.ts`
184
+
185
+ - [ ] **Step 1: Write failing tests**
186
+
187
+ ```typescript
188
+ // tests/lib/cortex/boundary/policy.test.ts
189
+ import { describe, it, expect } from 'vitest';
190
+ import { PolicyEngine } from '@/lib/cortex/boundary/policy';
191
+ import type { Policy } from '@/lib/cortex/boundary/policy';
192
+
193
+ describe('PolicyEngine', () => {
194
+ it('returns empty actions when no policies match', () => {
195
+ const engine = new PolicyEngine([]);
196
+ const actions = engine.evaluate({ type: 'decision', sensitivity: 'internal' });
197
+ expect(actions).toEqual([]);
198
+ });
199
+
200
+ it('matches by knowledge type', () => {
201
+ const policies: Policy[] = [{
202
+ name: 'arch-decisions-propagate',
203
+ match: { type: 'decision' },
204
+ action: { propagate_to: [{ level: 'department' }] },
205
+ }];
206
+ const engine = new PolicyEngine(policies);
207
+ const actions = engine.evaluate({ type: 'decision', sensitivity: 'internal' });
208
+ expect(actions).toHaveLength(1);
209
+ expect(actions[0].propagate_to).toEqual([{ level: 'department' }]);
210
+ });
211
+
212
+ it('matches by sensitivity', () => {
213
+ const policies: Policy[] = [{
214
+ name: 'lock-confidential',
215
+ match: { sensitivity: 'confidential' },
216
+ action: { cannot_propagate: true },
217
+ }];
218
+ const engine = new PolicyEngine(policies);
219
+ const actions = engine.evaluate({ type: 'pattern', sensitivity: 'confidential' });
220
+ expect(actions).toHaveLength(1);
221
+ expect(actions[0].cannot_propagate).toBe(true);
222
+ });
223
+
224
+ it('matches by topics', () => {
225
+ const policies: Policy[] = [{
226
+ name: 'security-routing',
227
+ match: { topics: ['security', 'vulnerability'] },
228
+ action: { max_scope: 'department', propagate_to: [{ level: 'team', entity_id: 'team-security' }] },
229
+ }];
230
+ const engine = new PolicyEngine(policies);
231
+ const actions = engine.evaluate({ type: 'error_fix', sensitivity: 'restricted', topics: ['security'] });
232
+ expect(actions).toHaveLength(1);
233
+ expect(actions[0].max_scope).toBe('department');
234
+ });
235
+
236
+ it('returns multiple matching policies', () => {
237
+ const policies: Policy[] = [
238
+ { name: 'p1', match: { type: 'decision' }, action: { trickle_down: true } },
239
+ { name: 'p2', match: { sensitivity: 'internal' }, action: { max_scope: 'organization' } },
240
+ ];
241
+ const engine = new PolicyEngine(policies);
242
+ const actions = engine.evaluate({ type: 'decision', sensitivity: 'internal' });
243
+ expect(actions).toHaveLength(2);
244
+ });
245
+
246
+ it('does not match when criteria do not overlap', () => {
247
+ const policies: Policy[] = [{
248
+ name: 'security-only',
249
+ match: { topics: ['security'] },
250
+ action: { cannot_propagate: true },
251
+ }];
252
+ const engine = new PolicyEngine(policies);
253
+ const actions = engine.evaluate({ type: 'decision', sensitivity: 'internal', topics: ['architecture'] });
254
+ expect(actions).toHaveLength(0);
255
+ });
256
+ });
257
+ ```
258
+
259
+ - [ ] **Step 2: Implement policy engine**
260
+
261
+ ```typescript
262
+ // src/lib/cortex/boundary/policy.ts
263
+ import type { KnowledgeType, SensitivityClass, ScopeLevel } from '../knowledge/types';
264
+
265
+ export interface PropagationTarget {
266
+ level: ScopeLevel;
267
+ entity_id?: string;
268
+ }
269
+
270
+ export interface PolicyAction {
271
+ max_scope?: ScopeLevel;
272
+ propagate_to?: PropagationTarget[];
273
+ trickle_down?: boolean;
274
+ cannot_propagate?: boolean;
275
+ }
276
+
277
+ export interface Policy {
278
+ name: string;
279
+ match: {
280
+ type?: KnowledgeType;
281
+ topics?: string[];
282
+ sensitivity?: SensitivityClass;
283
+ scope_level?: ScopeLevel;
284
+ };
285
+ action: PolicyAction;
286
+ }
287
+
288
+ export interface PolicyMatchInput {
289
+ type: KnowledgeType | string;
290
+ sensitivity: SensitivityClass | string;
291
+ topics?: string[];
292
+ scope_level?: ScopeLevel | string;
293
+ }
294
+
295
+ export class PolicyEngine {
296
+ constructor(private policies: Policy[]) {}
297
+
298
+ evaluate(input: PolicyMatchInput): PolicyAction[] {
299
+ const matched: PolicyAction[] = [];
300
+
301
+ for (const policy of this.policies) {
302
+ if (this.matches(policy, input)) {
303
+ matched.push(policy.action);
304
+ }
305
+ }
306
+
307
+ return matched;
308
+ }
309
+
310
+ private matches(policy: Policy, input: PolicyMatchInput): boolean {
311
+ const { match } = policy;
312
+
313
+ if (match.type && match.type !== input.type) return false;
314
+ if (match.sensitivity && match.sensitivity !== input.sensitivity) return false;
315
+ if (match.scope_level && match.scope_level !== input.scope_level) return false;
316
+
317
+ if (match.topics && match.topics.length > 0) {
318
+ const inputTopics = input.topics ?? [];
319
+ const hasOverlap = match.topics.some(t => inputTopics.includes(t));
320
+ if (!hasOverlap) return false;
321
+ }
322
+
323
+ return true;
324
+ }
325
+ }
326
+ ```
327
+
328
+ - [ ] **Step 3: Run tests, commit**
329
+
330
+ ```bash
331
+ git commit -m "feat(cortex): add policy engine for boundary enforcement"
332
+ ```
333
+
334
+ ---
335
+
336
+ ## Chunk 2: Access Filter and Audit Trail
337
+
338
+ ### Task 3: Query-time access filter
339
+
340
+ **Files:**
341
+ - Create: `src/lib/cortex/boundary/access.ts`
342
+ - Create: `tests/lib/cortex/boundary/access.test.ts`
343
+
344
+ - [ ] **Step 1: Write failing tests**
345
+
346
+ ```typescript
347
+ // tests/lib/cortex/boundary/access.test.ts
348
+ import { describe, it, expect } from 'vitest';
349
+ import { AccessFilter } from '@/lib/cortex/boundary/access';
350
+ import type { ScoredKnowledge } from '@/lib/cortex/knowledge/types';
351
+
352
+ function makeUnit(overrides: Partial<ScoredKnowledge> = {}): ScoredKnowledge {
353
+ return {
354
+ id: 'k1', vector: [], text: 'test', type: 'decision', layer: 'personal',
355
+ workspace_id: null, session_id: null, agent_type: 'claude',
356
+ project_path: null, file_refs: [], confidence: 0.8,
357
+ created: new Date().toISOString(), source_timestamp: new Date().toISOString(),
358
+ stale_score: 0, access_count: 0, last_accessed: null, metadata: {},
359
+ relevance_score: 0.9, similarity: 0.9,
360
+ sensitivity: 'internal',
361
+ scope: { level: 'personal', entity_id: 'person-alice' },
362
+ origin: { source_type: 'conversation', source_ref: '', creator_entity_id: 'person-alice' },
363
+ ...overrides,
364
+ };
365
+ }
366
+
367
+ describe('AccessFilter', () => {
368
+ const filter = new AccessFilter({
369
+ requesterId: 'person-alice',
370
+ requesterScope: { level: 'team', entity_id: 'team-platform' },
371
+ requesterOrg: 'organization-acme',
372
+ });
373
+
374
+ it('allows public knowledge from anywhere in org', () => {
375
+ const unit = makeUnit({ sensitivity: 'public', scope: { level: 'organization', entity_id: 'org-acme' } });
376
+ expect(filter.canAccess(unit)).toBe(true);
377
+ });
378
+
379
+ it('allows internal knowledge within org', () => {
380
+ const unit = makeUnit({ sensitivity: 'internal', scope: { level: 'team', entity_id: 'team-other' } });
381
+ expect(filter.canAccess(unit)).toBe(true);
382
+ });
383
+
384
+ it('allows restricted knowledge within same scope', () => {
385
+ const unit = makeUnit({
386
+ sensitivity: 'restricted',
387
+ scope: { level: 'team', entity_id: 'team-platform' },
388
+ });
389
+ expect(filter.canAccess(unit)).toBe(true);
390
+ });
391
+
392
+ it('denies restricted knowledge from different department', () => {
393
+ const unit = makeUnit({
394
+ sensitivity: 'restricted',
395
+ scope: { level: 'department', entity_id: 'department-sales' },
396
+ });
397
+ // Alice is in team-platform, not department-sales
398
+ expect(filter.canAccess(unit)).toBe(false);
399
+ });
400
+
401
+ it('allows confidential knowledge from self', () => {
402
+ const unit = makeUnit({
403
+ sensitivity: 'confidential',
404
+ scope: { level: 'personal', entity_id: 'person-alice' },
405
+ origin: { source_type: 'conversation', source_ref: '', creator_entity_id: 'person-alice' },
406
+ });
407
+ expect(filter.canAccess(unit)).toBe(true);
408
+ });
409
+
410
+ it('denies confidential knowledge from others', () => {
411
+ const unit = makeUnit({
412
+ sensitivity: 'confidential',
413
+ scope: { level: 'personal', entity_id: 'person-bob' },
414
+ origin: { source_type: 'conversation', source_ref: '', creator_entity_id: 'person-bob' },
415
+ });
416
+ expect(filter.canAccess(unit)).toBe(false);
417
+ });
418
+
419
+ it('respects creator_scope override (further restriction)', () => {
420
+ const unit = makeUnit({
421
+ sensitivity: 'internal', // normally accessible org-wide
422
+ creator_scope: { max_level: 'personal' }, // but creator restricted to personal only
423
+ scope: { level: 'personal', entity_id: 'person-bob' },
424
+ });
425
+ // Alice can't access Bob's personal-restricted knowledge even though it's internal
426
+ expect(filter.canAccess(unit)).toBe(false);
427
+ });
428
+
429
+ it('filters a list of results', () => {
430
+ const results = [
431
+ makeUnit({ id: 'a', sensitivity: 'public' }),
432
+ makeUnit({ id: 'b', sensitivity: 'confidential', origin: { source_type: 'conversation', source_ref: '', creator_entity_id: 'person-bob' } }),
433
+ makeUnit({ id: 'c', sensitivity: 'internal' }),
434
+ ];
435
+ const filtered = filter.filterResults(results);
436
+ expect(filtered).toHaveLength(2); // a and c pass, b denied
437
+ expect(filtered.map(r => r.id)).toEqual(['a', 'c']);
438
+ });
439
+ });
440
+ ```
441
+
442
+ - [ ] **Step 2: Implement access filter**
443
+
444
+ ```typescript
445
+ // src/lib/cortex/boundary/access.ts
446
+ import type { ScoredKnowledge, Scope, ScopeLevel, SensitivityClass } from '../knowledge/types';
447
+
448
+ const SCOPE_HIERARCHY: Record<ScopeLevel, number> = {
449
+ personal: 0,
450
+ team: 1,
451
+ department: 2,
452
+ organization: 3,
453
+ };
454
+
455
+ export interface AccessFilterConfig {
456
+ requesterId: string;
457
+ requesterScope: Scope; // requester's team scope
458
+ requesterOrg: string; // requester's org entity_id
459
+ grants?: Set<string>; // knowledge IDs the requester has been granted access to
460
+ }
461
+
462
+ export class AccessFilter {
463
+ private config: AccessFilterConfig;
464
+
465
+ constructor(config: AccessFilterConfig) {
466
+ this.config = config;
467
+ }
468
+
469
+ canAccess(unit: ScoredKnowledge): boolean {
470
+ const sensitivity = (unit.sensitivity ?? 'internal') as SensitivityClass;
471
+ const unitScope = unit.scope ?? { level: 'personal' as ScopeLevel, entity_id: '' };
472
+ const creatorId = unit.origin?.creator_entity_id ?? '';
473
+
474
+ // Check creator_scope override first — most restrictive wins
475
+ if (unit.creator_scope) {
476
+ const maxLevel = SCOPE_HIERARCHY[unit.creator_scope.max_level] ?? 0;
477
+ const requesterLevel = this.getRequesterProximityLevel(unitScope);
478
+ if (requesterLevel > maxLevel) return false;
479
+ }
480
+
481
+ switch (sensitivity) {
482
+ case 'public':
483
+ return true;
484
+
485
+ case 'internal':
486
+ // Accessible to anyone in the same org
487
+ return true;
488
+
489
+ case 'restricted':
490
+ // Accessible within same scope or if policy grants cross-scope access
491
+ return this.isWithinScope(unitScope);
492
+
493
+ case 'confidential':
494
+ // Only creator or explicit grant
495
+ if (this.config.requesterId === creatorId) return true;
496
+ if (this.config.grants?.has(unit.id)) return true;
497
+ return false;
498
+
499
+ default:
500
+ return false;
501
+ }
502
+ }
503
+
504
+ filterResults(results: ScoredKnowledge[]): ScoredKnowledge[] {
505
+ return results.filter(r => this.canAccess(r));
506
+ }
507
+
508
+ private isWithinScope(unitScope: Scope): boolean {
509
+ // Same entity_id = same scope
510
+ if (unitScope.entity_id === this.config.requesterScope.entity_id) return true;
511
+ if (unitScope.entity_id === this.config.requesterId) return true;
512
+ // Same org for org-level scopes
513
+ if (unitScope.level === 'organization' && unitScope.entity_id === this.config.requesterOrg) return true;
514
+ return false;
515
+ }
516
+
517
+ private getRequesterProximityLevel(unitScope: Scope): number {
518
+ // How "far" is the requester from the unit's scope?
519
+ // 0 = same entity, 1 = same scope level, 2+ = further
520
+ if (unitScope.entity_id === this.config.requesterId) return 0;
521
+ if (unitScope.entity_id === this.config.requesterScope.entity_id) return 0;
522
+ return SCOPE_HIERARCHY[unitScope.level] ?? 3;
523
+ }
524
+ }
525
+ ```
526
+
527
+ - [ ] **Step 3: Run tests, commit**
528
+
529
+ ```bash
530
+ git commit -m "feat(cortex): add query-time access filter for boundary enforcement"
531
+ ```
532
+
533
+ ---
534
+
535
+ ### Task 4: Audit trail
536
+
537
+ **Files:**
538
+ - Create: `src/lib/cortex/boundary/audit.ts`
539
+ - Create: `tests/lib/cortex/boundary/audit.test.ts`
540
+
541
+ - [ ] **Step 1: Write failing tests**
542
+
543
+ ```typescript
544
+ // tests/lib/cortex/boundary/audit.test.ts
545
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
546
+ import fs from 'fs';
547
+ import path from 'path';
548
+ import os from 'os';
549
+ import Database from 'better-sqlite3';
550
+ import { AuditLog } from '@/lib/cortex/boundary/audit';
551
+
552
+ describe('AuditLog', () => {
553
+ let tmpDir: string;
554
+ let audit: AuditLog;
555
+
556
+ beforeEach(() => {
557
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cortex-audit-'));
558
+ const db = new Database(path.join(tmpDir, 'graph.db'));
559
+ audit = new AuditLog(db);
560
+ });
561
+
562
+ afterEach(() => {
563
+ fs.rmSync(tmpDir, { recursive: true, force: true });
564
+ });
565
+
566
+ it('logs an access decision', () => {
567
+ audit.log({
568
+ requesterId: 'person-alice',
569
+ knowledgeId: 'k1',
570
+ action: 'allowed',
571
+ reason: 'public sensitivity',
572
+ });
573
+ const entries = audit.query({ requesterId: 'person-alice' });
574
+ expect(entries).toHaveLength(1);
575
+ expect(entries[0].action).toBe('allowed');
576
+ });
577
+
578
+ it('logs denied access', () => {
579
+ audit.log({
580
+ requesterId: 'person-alice',
581
+ knowledgeId: 'k2',
582
+ action: 'denied',
583
+ reason: 'confidential, not creator',
584
+ });
585
+ const entries = audit.query({ requesterId: 'person-alice' });
586
+ expect(entries).toHaveLength(1);
587
+ expect(entries[0].action).toBe('denied');
588
+ });
589
+
590
+ it('queries by time range', () => {
591
+ audit.log({ requesterId: 'person-alice', knowledgeId: 'k1', action: 'allowed', reason: 'public' });
592
+ const recent = audit.query({ since: new Date(Date.now() - 60000).toISOString() });
593
+ expect(recent).toHaveLength(1);
594
+
595
+ const future = audit.query({ since: new Date(Date.now() + 60000).toISOString() });
596
+ expect(future).toHaveLength(0);
597
+ });
598
+
599
+ it('supports retention cleanup', () => {
600
+ audit.log({ requesterId: 'person-alice', knowledgeId: 'k1', action: 'allowed', reason: 'test' });
601
+ // Cleanup entries older than 0 days (everything)
602
+ audit.cleanup(0);
603
+ const entries = audit.query({});
604
+ expect(entries).toHaveLength(0);
605
+ });
606
+ });
607
+ ```
608
+
609
+ - [ ] **Step 2: Implement audit log**
610
+
611
+ ```typescript
612
+ // src/lib/cortex/boundary/audit.ts
613
+ import type Database from 'better-sqlite3';
614
+
615
+ export interface AuditEntry {
616
+ requesterId: string;
617
+ knowledgeId: string;
618
+ action: 'allowed' | 'denied';
619
+ reason: string;
620
+ }
621
+
622
+ export interface AuditQueryFilter {
623
+ requesterId?: string;
624
+ since?: string; // ISO timestamp
625
+ limit?: number;
626
+ }
627
+
628
+ export interface AuditRecord extends AuditEntry {
629
+ timestamp: string;
630
+ }
631
+
632
+ export class AuditLog {
633
+ private db: InstanceType<typeof Database>;
634
+
635
+ constructor(db: InstanceType<typeof Database>) {
636
+ this.db = db;
637
+ this.db.exec(`
638
+ CREATE TABLE IF NOT EXISTS audit_log (
639
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
640
+ requester_id TEXT NOT NULL,
641
+ knowledge_id TEXT NOT NULL,
642
+ action TEXT NOT NULL,
643
+ reason TEXT NOT NULL,
644
+ timestamp TEXT NOT NULL
645
+ );
646
+ CREATE INDEX IF NOT EXISTS idx_audit_requester ON audit_log(requester_id);
647
+ CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_log(timestamp);
648
+ `);
649
+ }
650
+
651
+ log(entry: AuditEntry): void {
652
+ this.db.prepare(`
653
+ INSERT INTO audit_log (requester_id, knowledge_id, action, reason, timestamp)
654
+ VALUES (?, ?, ?, ?, ?)
655
+ `).run(entry.requesterId, entry.knowledgeId, entry.action, entry.reason, new Date().toISOString());
656
+ }
657
+
658
+ query(filter: AuditQueryFilter): AuditRecord[] {
659
+ let sql = 'SELECT * FROM audit_log WHERE 1=1';
660
+ const params: any[] = [];
661
+
662
+ if (filter.requesterId) {
663
+ sql += ' AND requester_id = ?';
664
+ params.push(filter.requesterId);
665
+ }
666
+ if (filter.since) {
667
+ sql += ' AND timestamp >= ?';
668
+ params.push(filter.since);
669
+ }
670
+
671
+ sql += ' ORDER BY timestamp DESC';
672
+
673
+ if (filter.limit) {
674
+ sql += ' LIMIT ?';
675
+ params.push(filter.limit);
676
+ }
677
+
678
+ return (this.db.prepare(sql).all(...params) as any[]).map(row => ({
679
+ requesterId: row.requester_id,
680
+ knowledgeId: row.knowledge_id,
681
+ action: row.action,
682
+ reason: row.reason,
683
+ timestamp: row.timestamp,
684
+ }));
685
+ }
686
+
687
+ cleanup(retentionDays: number): void {
688
+ const cutoff = new Date(Date.now() - retentionDays * 86400000).toISOString();
689
+ this.db.prepare('DELETE FROM audit_log WHERE timestamp < ?').run(cutoff);
690
+ }
691
+ }
692
+ ```
693
+
694
+ - [ ] **Step 3: Run tests, commit**
695
+
696
+ ```bash
697
+ git commit -m "feat(cortex): add audit trail for access decisions"
698
+ ```
699
+
700
+ ---
701
+
702
+ ## Chunk 3: Integration
703
+
704
+ ### Task 5: Integrate with ingestion pipeline
705
+
706
+ **Files:**
707
+ - Modify: `src/lib/cortex/ingestion/pipeline.ts`
708
+
709
+ - [ ] **Step 1: Read pipeline.ts**
710
+
711
+ - [ ] **Step 2: Add auto-classification during ingestion**
712
+
713
+ Import the classifier:
714
+ ```typescript
715
+ import { classifySensitivity } from '../boundary/classifier';
716
+ ```
717
+
718
+ In the KnowledgeUnit construction (where v2 fields are set), replace the hardcoded `sensitivity: 'internal'` with:
719
+ ```typescript
720
+ sensitivity: classifySensitivity(chunk.text),
721
+ ```
722
+
723
+ This ensures every ingested knowledge unit gets an auto-classified sensitivity level.
724
+
725
+ - [ ] **Step 3: Run pipeline tests to verify no regressions**
726
+
727
+ ```bash
728
+ npx vitest run tests/lib/cortex/ingestion/
729
+ ```
730
+
731
+ - [ ] **Step 4: Commit**
732
+
733
+ ```bash
734
+ git commit -m "feat(cortex): auto-classify sensitivity during ingestion"
735
+ ```
736
+
737
+ ---
738
+
739
+ ### Task 6: Integrate AccessFilter with ContextEngine
740
+
741
+ **Files:**
742
+ - Modify: `src/lib/cortex/retrieval/context-engine.ts`
743
+
744
+ - [ ] **Step 1: Read context-engine.ts**
745
+
746
+ - [ ] **Step 2: Add AccessFilter to the pipeline**
747
+
748
+ Import AccessFilter:
749
+ ```typescript
750
+ import { AccessFilter } from '../boundary/access';
751
+ ```
752
+
753
+ Add to `ContextEngineDeps`:
754
+ ```typescript
755
+ accessFilter?: AccessFilter;
756
+ ```
757
+
758
+ In the `assemble()` method, after fusion/ranking (Stage 5) but before conflict detection (Stage 6), apply the access filter:
759
+
760
+ ```typescript
761
+ // Stage 5.5: Access control filtering
762
+ let accessible = fused;
763
+ if (this.deps.accessFilter) {
764
+ accessible = this.deps.accessFilter.filterResults(fused);
765
+ }
766
+ ```
767
+
768
+ Then pass `accessible` (not `fused`) to conflict detection and formatting.
769
+
770
+ - [ ] **Step 3: Run context-engine tests to verify no regressions**
771
+
772
+ ```bash
773
+ npx vitest run tests/lib/cortex/retrieval/context-engine.test.ts
774
+ ```
775
+
776
+ - [ ] **Step 4: Commit**
777
+
778
+ ```bash
779
+ git commit -m "feat(cortex): integrate access filter into context assembly pipeline"
780
+ ```
781
+
782
+ ---
783
+
784
+ ### Task 7: Barrel export and config integration
785
+
786
+ **Files:**
787
+ - Create: `src/lib/cortex/boundary/index.ts`
788
+ - Modify: `src/lib/cortex/config.ts` (add policies array to config)
789
+
790
+ - [ ] **Step 1: Create barrel export**
791
+
792
+ ```typescript
793
+ // src/lib/cortex/boundary/index.ts
794
+ export { classifySensitivity } from './classifier';
795
+ export { PolicyEngine } from './policy';
796
+ export type { Policy, PolicyAction, PropagationTarget } from './policy';
797
+ export { AccessFilter } from './access';
798
+ export type { AccessFilterConfig } from './access';
799
+ export { AuditLog } from './audit';
800
+ export type { AuditEntry, AuditRecord, AuditQueryFilter } from './audit';
801
+ ```
802
+
803
+ - [ ] **Step 2: Add policies to CortexConfig**
804
+
805
+ In `src/lib/cortex/config.ts`, add to the `CortexConfig` interface:
806
+ ```typescript
807
+ policies?: Policy[]; // Organizational boundary policies
808
+ ```
809
+
810
+ And in `DEFAULT_CORTEX_CONFIG`:
811
+ ```typescript
812
+ policies: [],
813
+ ```
814
+
815
+ Import the Policy type:
816
+ ```typescript
817
+ import type { Policy } from './boundary/policy';
818
+ ```
819
+
820
+ - [ ] **Step 3: Run full test suite**
821
+
822
+ ```bash
823
+ npx vitest run tests/lib/cortex/
824
+ ```
825
+
826
+ - [ ] **Step 4: Commit**
827
+
828
+ ```bash
829
+ git commit -m "feat(cortex): add boundary module barrel export and config integration"
830
+ ```
831
+
832
+ ---
833
+
834
+ ## Summary
835
+
836
+ | Task | Component | Tests | Status |
837
+ |------|-----------|-------|--------|
838
+ | 1 | Sensitivity classifier | 7 | |
839
+ | 2 | Policy engine | 6 | |
840
+ | 3 | Access filter | 8 | |
841
+ | 4 | Audit trail | 4 | |
842
+ | 5 | Pipeline integration | regression | |
843
+ | 6 | ContextEngine integration | regression | |
844
+ | 7 | Barrel export + config | regression | |
845
+
846
+ **Total: 7 tasks, ~25 new tests, 3 chunks**
847
+
848
+ **Key design decisions:**
849
+ - Auto-classification is regex-based (no LLM call) — fast, deterministic, auditable
850
+ - Policies are stored in CortexConfig (admin-editable JSON) — not code
851
+ - AccessFilter is a separate class that can be composed with ContextEngine or used standalone
852
+ - Audit log uses the entity graph's SQLite DB (same file, new table) — no new database
853
+ - Most restrictive classification always wins (confidential > restricted > internal > public)