@jlongo78/agent-spaces 0.7.7 → 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 (797) 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 +1 -1
  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 +1 -1
  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 +1 -1
  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 +1 -1
  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]__eb8acb65._.js → [root-of-the-server]__c7c47529._.js} +2 -2
  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 +1 -1
  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/{69606d281c39f9b2.js → 2f9f09924ff9d447.js} +1 -1
  416. package/.next/standalone/.next/static/chunks/{84fe8d44deeeb74f.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/{9cfa0291d55d8d2a.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/e82f4414650587cf.js +7 -0
  427. package/.next/standalone/.next/static/chunks/f6464729e7aa0da0.css +3 -0
  428. package/.next/standalone/LICENSE +661 -0
  429. package/.next/standalone/NOTICE +5 -0
  430. package/.next/standalone/README.md +131 -0
  431. package/.next/standalone/bin/cortex-hook.sh +62 -62
  432. package/.next/standalone/bin/cortex-mcp.js +60 -60
  433. package/.next/standalone/bin/fix-standalone-externals.js +79 -0
  434. package/.next/standalone/bin/lib/auto-setup.js +110 -0
  435. package/.next/standalone/bin/mdns-service.js +171 -0
  436. package/.next/standalone/bin/postinstall.js +35 -0
  437. package/.next/standalone/bin/setup-admin.js +195 -0
  438. package/.next/standalone/bin/spaces-dev.js +247 -0
  439. package/.next/standalone/bin/spaces-install.js +638 -0
  440. package/.next/standalone/bin/spaces-reset-totp.js +50 -0
  441. package/.next/standalone/bin/spaces-service.js +1020 -0
  442. package/.next/standalone/bin/spaces-setup.js +253 -0
  443. package/.next/standalone/bin/spaces.js +788 -0
  444. package/.next/standalone/bin/ssh-auth-keys.sh +68 -0
  445. package/.next/standalone/bin/terminal-server.js +1807 -0
  446. package/.next/standalone/docker-compose.yml +28 -0
  447. package/.next/standalone/docs/architecture.md +387 -0
  448. package/.next/standalone/docs/cortex.md +293 -0
  449. package/.next/standalone/docs/getting-started.md +96 -0
  450. package/.next/standalone/docs/plans/2026-02-24-multi-agent-sessions-design.md +133 -0
  451. package/.next/standalone/docs/plans/2026-02-24-multi-agent-sessions-plan.md +959 -0
  452. package/.next/standalone/docs/plans/2026-03-07-service-command-design.md +146 -0
  453. package/.next/standalone/docs/plans/2026-03-07-service-command-plan.md +254 -0
  454. package/.next/standalone/docs/server-install.md +564 -0
  455. package/.next/standalone/docs/social-card.html +150 -0
  456. package/.next/standalone/docs/superpowers/plans/2026-03-12-spaces-cortex.md +5270 -0
  457. package/.next/standalone/docs/superpowers/plans/2026-03-13-cortex-wiring.md +1387 -1387
  458. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-entity-graph.md +1923 -1923
  459. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-knowledge-evolution.md +1113 -1113
  460. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-boundary-engine.md +853 -853
  461. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-context-engine.md +1274 -1274
  462. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-signal-ingestion.md +933 -933
  463. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-lobes.md +1080 -1080
  464. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-gravity-system.md +768 -768
  465. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-ui.md +1108 -1108
  466. package/.next/standalone/docs/superpowers/plans/2026-03-18-cortex-ui-integration.md +1846 -1846
  467. package/.next/standalone/docs/superpowers/plans/2026-03-19-vr-phase1-shell.md +1639 -0
  468. package/.next/standalone/docs/superpowers/specs/2026-03-11-universe-view-design.md +320 -0
  469. package/.next/standalone/docs/superpowers/specs/2026-03-12-spaces-brain-design.md +720 -0
  470. package/.next/standalone/docs/superpowers/specs/2026-03-13-cortex-wiring-design.md +268 -268
  471. package/.next/standalone/docs/superpowers/specs/2026-03-14-cortex-v2-design.md +623 -623
  472. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-lobes-design.md +263 -263
  473. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-v2-ui-design.md +240 -240
  474. package/.next/standalone/docs/superpowers/specs/2026-03-16-pane-ux-design.md +77 -0
  475. package/.next/standalone/docs/superpowers/specs/2026-03-18-cortex-ui-integration-design.md +341 -341
  476. package/.next/standalone/docs/superpowers/specs/2026-03-19-vr-phase1-shell-design.md +288 -0
  477. package/.next/standalone/docs/tiers.md +104 -0
  478. package/.next/standalone/eslint.config.mjs +18 -0
  479. package/.next/standalone/next.config.ts +20 -0
  480. package/.next/standalone/nginx.conf +53 -0
  481. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/README.md +46 -0
  482. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/glib-2.0/include/glibconfig.h +221 -0
  483. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/index.js +1 -0
  484. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  485. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/package.json +42 -0
  486. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/README.md +46 -0
  487. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/glib-2.0/include/glibconfig.h +221 -0
  488. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/index.js +1 -0
  489. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  490. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json +42 -0
  491. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/versions.json +30 -0
  492. package/.next/standalone/node_modules/@img/sharp-linux-x64/lib/sharp-linux-x64.node +0 -0
  493. package/.next/standalone/node_modules/@img/{sharp-win32-x64 → sharp-linux-x64}/package.json +46 -39
  494. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/lib/sharp-linuxmusl-x64.node +0 -0
  495. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/package.json +46 -0
  496. package/.next/standalone/package-lock.json +14154 -0
  497. package/.next/standalone/package.json +104 -104
  498. package/.next/standalone/postcss.config.mjs +7 -0
  499. package/.next/standalone/scripts/rebuild.cmd +65 -0
  500. package/.next/standalone/scripts/rebuild.sh +59 -0
  501. package/.next/standalone/server.js +1 -1
  502. package/.next/standalone/src/app/(desktop)/admin/analytics/page.tsx +266 -0
  503. package/.next/standalone/src/app/(desktop)/admin/users/page.tsx +399 -0
  504. package/.next/standalone/src/app/(desktop)/analytics/page.tsx +166 -0
  505. package/.next/standalone/src/app/(desktop)/cortex/page.tsx +81 -78
  506. package/.next/standalone/src/app/(desktop)/dashboard-client.tsx +56 -0
  507. package/.next/standalone/src/app/(desktop)/layout.tsx +18 -0
  508. package/.next/standalone/src/app/(desktop)/network/page.tsx +137 -0
  509. package/.next/standalone/src/app/(desktop)/page.tsx +17 -0
  510. package/.next/standalone/src/app/(desktop)/projects/page.tsx +68 -0
  511. package/.next/standalone/src/app/(desktop)/sessions/[id]/page.tsx +519 -0
  512. package/.next/standalone/src/app/(desktop)/sessions/page.tsx +145 -0
  513. package/.next/standalone/src/app/(desktop)/settings/page.tsx +446 -0
  514. package/.next/standalone/src/app/(desktop)/terminal/layout.tsx +7 -0
  515. package/.next/standalone/src/app/(desktop)/terminal/page.tsx +1151 -0
  516. package/.next/standalone/src/app/(desktop)/terminal/pane/[id]/page.tsx +211 -0
  517. package/.next/standalone/src/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page.tsx +192 -0
  518. package/.next/standalone/src/app/(desktop)/workspaces/page.tsx +12 -0
  519. package/.next/standalone/src/app/api/admin/analytics/route.ts +10 -0
  520. package/.next/standalone/src/app/api/admin/users/[id]/route.ts +20 -0
  521. package/.next/standalone/src/app/api/admin/users/route.ts +15 -0
  522. package/.next/standalone/src/app/api/analytics/overview/route.ts +80 -0
  523. package/.next/standalone/src/app/api/auth/login/route.ts +10 -0
  524. package/.next/standalone/src/app/api/auth/logout/route.ts +9 -0
  525. package/.next/standalone/src/app/api/auth/me/route.ts +22 -0
  526. package/.next/standalone/src/app/api/auth/totp/setup/route.ts +10 -0
  527. package/.next/standalone/src/app/api/auth/totp/status/route.ts +10 -0
  528. package/.next/standalone/src/app/api/auth/totp/verify/route.ts +10 -0
  529. package/.next/standalone/src/app/api/benchmark/lobes/route.ts +16 -0
  530. package/.next/standalone/src/app/api/benchmark/run/route.ts +92 -0
  531. package/.next/standalone/src/app/api/benchmark/runs/[id]/route.ts +26 -0
  532. package/.next/standalone/src/app/api/benchmark/runs/route.ts +16 -0
  533. package/.next/standalone/src/app/api/benchmark/status/route.ts +35 -0
  534. package/.next/standalone/src/app/api/bulk/route.ts +34 -0
  535. package/.next/standalone/src/app/api/chat/route.ts +85 -0
  536. package/.next/standalone/src/app/api/config/route.ts +30 -0
  537. package/.next/standalone/src/app/api/cortex/context/route.ts +78 -78
  538. package/.next/standalone/src/app/api/cortex/curation/assess/route.ts +27 -27
  539. package/.next/standalone/src/app/api/cortex/curation/publish/route.ts +23 -23
  540. package/.next/standalone/src/app/api/cortex/curation/refine/route.ts +23 -23
  541. package/.next/standalone/src/app/api/cortex/curation/review/route.ts +29 -29
  542. package/.next/standalone/src/app/api/cortex/curation/seed/route.ts +23 -23
  543. package/.next/standalone/src/app/api/cortex/export/route.ts +40 -40
  544. package/.next/standalone/src/app/api/cortex/federation/pending/route.ts +20 -20
  545. package/.next/standalone/src/app/api/cortex/federation/resolve/route.ts +43 -43
  546. package/.next/standalone/src/app/api/cortex/federation/search/route.ts +35 -35
  547. package/.next/standalone/src/app/api/cortex/federation/teach/route.ts +76 -76
  548. package/.next/standalone/src/app/api/cortex/graph/edges/route.ts +112 -112
  549. package/.next/standalone/src/app/api/cortex/graph/entities/[id]/route.ts +73 -73
  550. package/.next/standalone/src/app/api/cortex/graph/entities/route.ts +75 -75
  551. package/.next/standalone/src/app/api/cortex/graph/populate/route.ts +203 -203
  552. package/.next/standalone/src/app/api/cortex/import/route.ts +75 -75
  553. package/.next/standalone/src/app/api/cortex/import/status/route.ts +15 -15
  554. package/.next/standalone/src/app/api/cortex/ingest/bootstrap/route.ts +29 -29
  555. package/.next/standalone/src/app/api/cortex/ingest/status/route.ts +15 -15
  556. package/.next/standalone/src/app/api/cortex/knowledge/[id]/route.ts +91 -91
  557. package/.next/standalone/src/app/api/cortex/knowledge/route.ts +93 -93
  558. package/.next/standalone/src/app/api/cortex/lobes/[id]/route.ts +67 -67
  559. package/.next/standalone/src/app/api/cortex/lobes/route.ts +22 -22
  560. package/.next/standalone/src/app/api/cortex/lobes/share/route.ts +80 -80
  561. package/.next/standalone/src/app/api/cortex/marketplace/browse/route.ts +43 -43
  562. package/.next/standalone/src/app/api/cortex/marketplace/preview/route.ts +46 -46
  563. package/.next/standalone/src/app/api/cortex/mcp/call/route.ts +11 -11
  564. package/.next/standalone/src/app/api/cortex/mcp/tools/route.ts +6 -6
  565. package/.next/standalone/src/app/api/cortex/search/route.ts +43 -43
  566. package/.next/standalone/src/app/api/cortex/settings/route.ts +33 -33
  567. package/.next/standalone/src/app/api/cortex/status/route.ts +169 -169
  568. package/.next/standalone/src/app/api/cortex/timeline/route.ts +42 -42
  569. package/.next/standalone/src/app/api/cortex/usage/route.ts +31 -31
  570. package/.next/standalone/src/app/api/cortex/workspace/[id]/context/route.ts +41 -41
  571. package/.next/standalone/src/app/api/events/route.ts +40 -0
  572. package/.next/standalone/src/app/api/files/route.ts +187 -0
  573. package/.next/standalone/src/app/api/folders/route.ts +97 -0
  574. package/.next/standalone/src/app/api/network/connect-callback/route.ts +11 -0
  575. package/.next/standalone/src/app/api/network/connect-request/[id]/route.ts +11 -0
  576. package/.next/standalone/src/app/api/network/connect-request/route.ts +17 -0
  577. package/.next/standalone/src/app/api/network/discovered/route.ts +9 -0
  578. package/.next/standalone/src/app/api/network/handshake/route.ts +25 -0
  579. package/.next/standalone/src/app/api/network/health/route.ts +10 -0
  580. package/.next/standalone/src/app/api/network/identity/route.ts +15 -0
  581. package/.next/standalone/src/app/api/network/keys/[id]/route.ts +10 -0
  582. package/.next/standalone/src/app/api/network/keys/route.ts +15 -0
  583. package/.next/standalone/src/app/api/network/nodes/[id]/route.ts +15 -0
  584. package/.next/standalone/src/app/api/network/nodes/check/route.ts +9 -0
  585. package/.next/standalone/src/app/api/network/nodes/route.ts +15 -0
  586. package/.next/standalone/src/app/api/network/projects/route.ts +25 -0
  587. package/.next/standalone/src/app/api/network/proxy/[nodeId]/[...path]/route.ts +15 -0
  588. package/.next/standalone/src/app/api/network/search/route.ts +38 -0
  589. package/.next/standalone/src/app/api/network/sessions/[id]/messages/route.ts +36 -0
  590. package/.next/standalone/src/app/api/network/sessions/[id]/route.ts +34 -0
  591. package/.next/standalone/src/app/api/network/sessions/route.ts +43 -0
  592. package/.next/standalone/src/app/api/network/terminal/token/route.ts +10 -0
  593. package/.next/standalone/src/app/api/network/workspaces/[id]/route.ts +34 -0
  594. package/.next/standalone/src/app/api/network/workspaces/route.ts +61 -0
  595. package/.next/standalone/src/app/api/panes/[id]/route.ts +60 -0
  596. package/.next/standalone/src/app/api/panes/route.ts +39 -0
  597. package/.next/standalone/src/app/api/projects/route.ts +13 -0
  598. package/.next/standalone/src/app/api/search/route.ts +47 -0
  599. package/.next/standalone/src/app/api/sessions/[id]/chat/route.ts +120 -0
  600. package/.next/standalone/src/app/api/sessions/[id]/messages/route.ts +28 -0
  601. package/.next/standalone/src/app/api/sessions/[id]/route.ts +73 -0
  602. package/.next/standalone/src/app/api/sessions/route.ts +64 -0
  603. package/.next/standalone/src/app/api/sync/route.ts +24 -0
  604. package/.next/standalone/src/app/api/tags/route.ts +35 -0
  605. package/.next/standalone/src/app/api/tier/route.ts +16 -0
  606. package/.next/standalone/src/app/api/updates/route.ts +53 -0
  607. package/.next/standalone/src/app/api/whisper/route.ts +90 -0
  608. package/.next/standalone/src/app/api/workspaces/[id]/context/[key]/route.ts +39 -0
  609. package/.next/standalone/src/app/api/workspaces/[id]/context/route.ts +28 -0
  610. package/.next/standalone/src/app/api/workspaces/[id]/messages/[msgId]/route.ts +17 -0
  611. package/.next/standalone/src/app/api/workspaces/[id]/messages/route.ts +39 -0
  612. package/.next/standalone/src/app/api/workspaces/[id]/route.ts +47 -0
  613. package/.next/standalone/src/app/api/workspaces/[id]/sessions/route.ts +62 -0
  614. package/.next/standalone/src/app/api/workspaces/route.ts +79 -0
  615. package/.next/standalone/src/app/globals.css +85 -0
  616. package/.next/standalone/src/app/icon.png +0 -0
  617. package/.next/standalone/src/app/layout.tsx +33 -0
  618. package/.next/standalone/src/app/login/layout.tsx +7 -0
  619. package/.next/standalone/src/app/login/page.tsx +315 -0
  620. package/.next/standalone/src/app/m/layout.tsx +16 -0
  621. package/.next/standalone/src/app/m/page.tsx +118 -0
  622. package/.next/standalone/src/app/m/projects/page.tsx +64 -0
  623. package/.next/standalone/src/app/m/sessions/[id]/page.tsx +168 -0
  624. package/.next/standalone/src/app/m/sessions/page.tsx +177 -0
  625. package/.next/standalone/src/app/m/settings/page.tsx +230 -0
  626. package/.next/standalone/src/app/m/terminal/page.tsx +413 -0
  627. package/.next/standalone/src/app/vr/page.tsx +21 -0
  628. package/.next/standalone/src/app/vr/vr-app.tsx +163 -0
  629. package/.next/standalone/src/app/vr/vr-controls.tsx +139 -0
  630. package/.next/standalone/src/app/vr/vr-door.tsx +82 -0
  631. package/.next/standalone/src/app/vr/vr-environment.tsx +71 -0
  632. package/.next/standalone/src/app/vr/vr-gaze.tsx +89 -0
  633. package/.next/standalone/src/app/vr/vr-layout.ts +49 -0
  634. package/.next/standalone/src/app/vr/vr-lobby.tsx +97 -0
  635. package/.next/standalone/src/app/vr/vr-pane.tsx +195 -0
  636. package/.next/standalone/src/app/vr/vr-room.tsx +79 -0
  637. package/.next/standalone/src/app/vr/vr-terminal.tsx +303 -0
  638. package/.next/standalone/src/components/auth/totp-gate.tsx +183 -0
  639. package/.next/standalone/src/components/bus/activity-panel.tsx +261 -0
  640. package/.next/standalone/src/components/common/color-picker.tsx +35 -0
  641. package/.next/standalone/src/components/common/dev-directory-picker.tsx +339 -0
  642. package/.next/standalone/src/components/common/folder-picker.tsx +200 -0
  643. package/.next/standalone/src/components/common/tag-picker.tsx +190 -0
  644. package/.next/standalone/src/components/common/workspace-picker.tsx +113 -0
  645. package/.next/standalone/src/components/cortex/benchmark-tab.tsx +880 -0
  646. package/.next/standalone/src/components/cortex/constants.ts +29 -29
  647. package/.next/standalone/src/components/cortex/cortex-dashboard.tsx +304 -304
  648. package/.next/standalone/src/components/cortex/cortex-indicator.tsx +44 -44
  649. package/.next/standalone/src/components/cortex/cortex-panel.tsx +140 -140
  650. package/.next/standalone/src/components/cortex/cortex-settings.tsx +221 -221
  651. package/.next/standalone/src/components/cortex/curation-tab.tsx +810 -810
  652. package/.next/standalone/src/components/cortex/entity-detail.tsx +101 -101
  653. package/.next/standalone/src/components/cortex/entity-graph.tsx +382 -382
  654. package/.next/standalone/src/components/cortex/import-dialog.tsx +212 -212
  655. package/.next/standalone/src/components/cortex/injection-badge.tsx +72 -72
  656. package/.next/standalone/src/components/cortex/knowledge-card.tsx +109 -109
  657. package/.next/standalone/src/components/cortex/knowledge-tab.tsx +158 -158
  658. package/.next/standalone/src/components/cortex/lobe-settings.tsx +215 -215
  659. package/.next/standalone/src/components/cortex/marketplace-card.tsx +126 -126
  660. package/.next/standalone/src/components/cortex/marketplace-tab.tsx +113 -113
  661. package/.next/standalone/src/components/dashboard/activity-chart.tsx +41 -0
  662. package/.next/standalone/src/components/dashboard/model-usage-chart.tsx +61 -0
  663. package/.next/standalone/src/components/dashboard/recent-sessions.tsx +68 -0
  664. package/.next/standalone/src/components/dashboard/stats-cards.tsx +36 -0
  665. package/.next/standalone/src/components/files/file-explorer.tsx +703 -0
  666. package/.next/standalone/src/components/layout/providers.tsx +38 -0
  667. package/.next/standalone/src/components/layout/sidebar.tsx +170 -0
  668. package/.next/standalone/src/components/layout/tier-provider.tsx +53 -0
  669. package/.next/standalone/src/components/layout/update-banner.tsx +92 -0
  670. package/.next/standalone/src/components/mobile/bottom-nav.tsx +46 -0
  671. package/.next/standalone/src/components/mobile/mobile-chat-input.tsx +244 -0
  672. package/.next/standalone/src/components/mobile/mobile-header.tsx +44 -0
  673. package/.next/standalone/src/components/mobile/mobile-session-card.tsx +56 -0
  674. package/.next/standalone/src/components/mobile/mobile-terminal-input.tsx +71 -0
  675. package/.next/standalone/src/components/mobile/mobile-terminal-pane.tsx +300 -0
  676. package/.next/standalone/src/components/mobile/mobile-terminal-toolbar.tsx +53 -0
  677. package/.next/standalone/src/components/mobile/pull-to-refresh.tsx +82 -0
  678. package/.next/standalone/src/components/mobile/voice-input.tsx +53 -0
  679. package/.next/standalone/src/components/network/api-key-list.tsx +190 -0
  680. package/.next/standalone/src/components/network/connection-requests.tsx +94 -0
  681. package/.next/standalone/src/components/network/node-add-dialog.tsx +131 -0
  682. package/.next/standalone/src/components/network/node-badge.tsx +26 -0
  683. package/.next/standalone/src/components/network/node-list.tsx +207 -0
  684. package/.next/standalone/src/components/network/node-selector.tsx +49 -0
  685. package/.next/standalone/src/components/sessions/session-filters.tsx +116 -0
  686. package/.next/standalone/src/components/sessions/session-list.tsx +485 -0
  687. package/.next/standalone/src/components/terminal/terminal-pane.tsx +874 -0
  688. package/.next/standalone/src/components/viewer/chat-input.tsx +275 -0
  689. package/.next/standalone/src/components/viewer/message-renderer.tsx +551 -0
  690. package/.next/standalone/src/components/workspace/universe-cluster.tsx +131 -0
  691. package/.next/standalone/src/components/workspace/universe-orb.tsx +128 -0
  692. package/.next/standalone/src/components/workspace/universe-types.ts +22 -0
  693. package/.next/standalone/src/components/workspace/universe-utils.ts +11 -0
  694. package/.next/standalone/src/components/workspace/universe-view.tsx +397 -0
  695. package/.next/standalone/src/components/workspace/workspace-chooser.tsx +616 -0
  696. package/.next/standalone/src/hooks/use-benchmark.ts +71 -0
  697. package/.next/standalone/src/hooks/use-bus.ts +147 -0
  698. package/.next/standalone/src/hooks/use-idle-detection.ts +79 -0
  699. package/.next/standalone/src/hooks/use-network.ts +229 -0
  700. package/.next/standalone/src/hooks/use-sessions.ts +437 -0
  701. package/.next/standalone/src/hooks/use-speech-recognition.ts +113 -0
  702. package/.next/standalone/src/hooks/use-sse.ts +35 -0
  703. package/.next/standalone/src/hooks/use-tier.ts +39 -0
  704. package/.next/standalone/src/lib/agents.ts +70 -0
  705. package/.next/standalone/src/lib/aider/parser.ts +111 -0
  706. package/.next/standalone/src/lib/api.ts +19 -0
  707. package/.next/standalone/src/lib/auth.ts +47 -0
  708. package/.next/standalone/src/lib/claude/parser.ts +212 -0
  709. package/.next/standalone/src/lib/claude/stats.ts +204 -0
  710. package/.next/standalone/src/lib/codex/parser.ts +265 -0
  711. package/.next/standalone/src/lib/config.ts +115 -0
  712. package/.next/standalone/src/lib/cortex/benchmark.ts +67 -0
  713. package/.next/standalone/src/lib/cortex/config.ts +40 -40
  714. package/.next/standalone/src/lib/cortex/debug.ts +10 -10
  715. package/.next/standalone/src/lib/cortex/distillation/usage-store.ts +18 -18
  716. package/.next/standalone/src/lib/cortex/graph/resolver.ts +10 -10
  717. package/.next/standalone/src/lib/cortex/graph/types.ts +22 -22
  718. package/.next/standalone/src/lib/cortex/index.ts +56 -56
  719. package/.next/standalone/src/lib/cortex/ingestion/bootstrap.ts +14 -14
  720. package/.next/standalone/src/lib/cortex/knowledge/compat.ts +14 -14
  721. package/.next/standalone/src/lib/cortex/knowledge/contradiction.ts +10 -10
  722. package/.next/standalone/src/lib/cortex/knowledge/types.ts +67 -67
  723. package/.next/standalone/src/lib/cortex/lobes/config.ts +16 -16
  724. package/.next/standalone/src/lib/cortex/lobes/resolver.ts +8 -8
  725. package/.next/standalone/src/lib/cortex/lobes/shares.ts +14 -14
  726. package/.next/standalone/src/lib/cortex/mcp/server.ts +8 -8
  727. package/.next/standalone/src/lib/cortex/portability/exporter.ts +6 -6
  728. package/.next/standalone/src/lib/cortex/portability/importer.ts +10 -10
  729. package/.next/standalone/src/lib/cortex/retrieval/context-engine.ts +10 -10
  730. package/.next/standalone/src/lib/cortex/types.ts +39 -39
  731. package/.next/standalone/src/lib/cost-calculator.ts +48 -0
  732. package/.next/standalone/src/lib/db/init.ts +71 -0
  733. package/.next/standalone/src/lib/db/queries.ts +718 -0
  734. package/.next/standalone/src/lib/db/schema.ts +202 -0
  735. package/.next/standalone/src/lib/events/sse.ts +36 -0
  736. package/.next/standalone/src/lib/gemini/parser.ts +216 -0
  737. package/.next/standalone/src/lib/license.ts +56 -0
  738. package/.next/standalone/src/lib/pro.ts +31 -0
  739. package/.next/standalone/src/lib/sync/indexer.ts +429 -0
  740. package/.next/standalone/src/lib/sync/watcher.ts +64 -0
  741. package/.next/standalone/src/lib/teams.ts +31 -0
  742. package/.next/standalone/src/lib/telemetry.ts +75 -0
  743. package/.next/standalone/src/lib/terminal/server.ts +128 -0
  744. package/.next/standalone/src/lib/tier.ts +38 -0
  745. package/.next/standalone/src/lib/utils.ts +72 -0
  746. package/.next/standalone/src/middleware.ts +133 -0
  747. package/.next/standalone/src/types/claude.ts +208 -0
  748. package/.next/standalone/src/types/network.ts +61 -0
  749. package/.next/standalone/tests/setup.ts +8 -0
  750. package/.next/standalone/tsconfig.json +34 -34
  751. package/.next/standalone/vitest.config.ts +24 -0
  752. package/LICENSE +661 -661
  753. package/README.md +131 -131
  754. package/bin/cortex-hook.sh +62 -62
  755. package/bin/cortex-mcp.js +60 -60
  756. package/bin/fix-standalone-externals.js +79 -79
  757. package/bin/lib/auto-setup.js +110 -110
  758. package/bin/mdns-service.js +171 -171
  759. package/bin/postinstall.js +35 -35
  760. package/bin/setup-admin.js +195 -195
  761. package/bin/spaces-dev.js +247 -208
  762. package/bin/spaces-install.js +638 -599
  763. package/bin/spaces-reset-totp.js +50 -50
  764. package/bin/spaces-service.js +1020 -1020
  765. package/bin/spaces-setup.js +253 -253
  766. package/bin/spaces.js +788 -776
  767. package/bin/ssh-auth-keys.sh +68 -68
  768. package/bin/terminal-server.js +1807 -1683
  769. package/package.json +104 -104
  770. package/.next/standalone/.claude/settings.local.json +0 -55
  771. package/.next/standalone/.claude/spaces-env.json +0 -1
  772. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__e921fdfc._.js +0 -5
  773. package/.next/standalone/.next/server/chunks/ssr/_2230ad2d._.js +0 -3
  774. package/.next/standalone/.next/server/chunks/ssr/_5cf334fd._.js +0 -3
  775. package/.next/standalone/.next/server/chunks/ssr/_db0abd0a._.js +0 -3
  776. package/.next/standalone/.next/server/chunks/ssr/_db2fec84._.js +0 -3
  777. package/.next/standalone/.next/server/chunks/ssr/_f4e57187._.js +0 -3
  778. package/.next/standalone/.next/server/chunks/ssr/src_40fa36ce._.js +0 -7
  779. package/.next/standalone/.next/static/chunks/003e7aa1adfe577d.js +0 -1
  780. package/.next/standalone/.next/static/chunks/158b52b84e647ac1.js +0 -5
  781. package/.next/standalone/.next/static/chunks/232d8aae4fefab70.js +0 -1
  782. package/.next/standalone/.next/static/chunks/5325351ef49cb65f.js +0 -1
  783. package/.next/standalone/.next/static/chunks/559735e598ca3cbb.js +0 -1
  784. package/.next/standalone/.next/static/chunks/5d5d7b0095dd52ae.js +0 -1
  785. package/.next/standalone/.next/static/chunks/898f380eba90427a.js +0 -1
  786. package/.next/standalone/.next/static/chunks/95339e55722bb4ca.js +0 -5
  787. package/.next/standalone/.next/static/chunks/9cd594813c539df9.js +0 -1
  788. package/.next/standalone/.next/static/chunks/c1a95aebf6725f64.css +0 -3
  789. package/.next/standalone/.next/static/chunks/c515eb77d9410aa0.js +0 -5
  790. package/.next/standalone/.next/static/chunks/d9ae203a7f123546.js +0 -5
  791. package/.next/standalone/.next/static/chunks/f9f2628207848ac2.js +0 -1
  792. package/.next/standalone/.spaces/cortex-context.md +0 -70
  793. package/.next/standalone/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64.node +0 -0
  794. /package/.next/standalone/.next/static/{BEY-sql3lQLouidpurSQf → PcpzUspSK8QDdwzAJz8br}/_buildManifest.js +0 -0
  795. /package/.next/standalone/.next/static/{BEY-sql3lQLouidpurSQf → PcpzUspSK8QDdwzAJz8br}/_clientMiddlewareManifest.json +0 -0
  796. /package/.next/standalone/.next/static/{BEY-sql3lQLouidpurSQf → PcpzUspSK8QDdwzAJz8br}/_ssgManifest.js +0 -0
  797. /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)