@jlongo78/agent-spaces 0.9.6 → 0.9.8

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 (917) hide show
  1. package/.next/standalone/.claude/settings.local.json +68 -0
  2. package/.next/standalone/.claude/spaces-env.json +1 -0
  3. package/.next/standalone/.next/BUILD_ID +1 -1
  4. package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
  5. package/.next/standalone/.next/build-manifest.json +2 -2
  6. package/.next/standalone/.next/prerender-manifest.json +3 -3
  7. package/.next/standalone/.next/required-server-files.json +19 -19
  8. package/.next/standalone/.next/routes-manifest.json +6 -0
  9. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/(desktop)/admin/users/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/(desktop)/analytics/page_client-reference-manifest.js +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_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page_client-reference-manifest.js +1 -1
  24. package/.next/standalone/.next/server/app/(desktop)/workspaces/page_client-reference-manifest.js +1 -1
  25. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  26. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  27. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  28. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  29. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  30. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  31. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  32. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  33. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  34. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  35. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  36. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  37. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  38. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  39. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  40. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  41. package/.next/standalone/.next/server/app/admin/analytics.html +1 -1
  42. package/.next/standalone/.next/server/app/admin/analytics.rsc +2 -2
  43. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics/__PAGE__.segment.rsc +1 -1
  44. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics.segment.rsc +1 -1
  45. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  46. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  47. package/.next/standalone/.next/server/app/admin/analytics.segments/_full.segment.rsc +2 -2
  48. package/.next/standalone/.next/server/app/admin/analytics.segments/_head.segment.rsc +1 -1
  49. package/.next/standalone/.next/server/app/admin/analytics.segments/_index.segment.rsc +2 -2
  50. package/.next/standalone/.next/server/app/admin/analytics.segments/_tree.segment.rsc +2 -2
  51. package/.next/standalone/.next/server/app/admin/users.html +1 -1
  52. package/.next/standalone/.next/server/app/admin/users.rsc +2 -2
  53. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users/__PAGE__.segment.rsc +1 -1
  54. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users.segment.rsc +1 -1
  55. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  56. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  57. package/.next/standalone/.next/server/app/admin/users.segments/_full.segment.rsc +2 -2
  58. package/.next/standalone/.next/server/app/admin/users.segments/_head.segment.rsc +1 -1
  59. package/.next/standalone/.next/server/app/admin/users.segments/_index.segment.rsc +2 -2
  60. package/.next/standalone/.next/server/app/admin/users.segments/_tree.segment.rsc +2 -2
  61. package/.next/standalone/.next/server/app/analytics.html +1 -1
  62. package/.next/standalone/.next/server/app/analytics.rsc +2 -2
  63. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics/__PAGE__.segment.rsc +1 -1
  64. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics.segment.rsc +1 -1
  65. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  66. package/.next/standalone/.next/server/app/analytics.segments/_full.segment.rsc +2 -2
  67. package/.next/standalone/.next/server/app/analytics.segments/_head.segment.rsc +1 -1
  68. package/.next/standalone/.next/server/app/analytics.segments/_index.segment.rsc +2 -2
  69. package/.next/standalone/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
  70. package/.next/standalone/.next/server/app/api/analytics/overview/route.js +1 -1
  71. package/.next/standalone/.next/server/app/api/analytics/overview/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/benchmark/lobes/route.js +1 -1
  73. package/.next/standalone/.next/server/app/api/benchmark/lobes/route.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/api/benchmark/run/route.js +1 -1
  75. package/.next/standalone/.next/server/app/api/benchmark/run/route.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/api/benchmark/runs/[id]/route.js +1 -1
  77. package/.next/standalone/.next/server/app/api/benchmark/runs/[id]/route.js.nft.json +1 -1
  78. package/.next/standalone/.next/server/app/api/benchmark/runs/route.js +1 -1
  79. package/.next/standalone/.next/server/app/api/benchmark/runs/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/benchmark/status/route.js +1 -1
  81. package/.next/standalone/.next/server/app/api/benchmark/status/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/bulk/route.js +1 -1
  83. package/.next/standalone/.next/server/app/api/bulk/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/config/route.js +1 -1
  85. package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/cortex/context/route.js +1 -1
  87. package/.next/standalone/.next/server/app/api/cortex/context/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/cortex/curation/assess/route.js +1 -1
  89. package/.next/standalone/.next/server/app/api/cortex/curation/assess/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/cortex/curation/publish/route.js +1 -1
  91. package/.next/standalone/.next/server/app/api/cortex/curation/publish/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/cortex/curation/refine/route.js +1 -1
  93. package/.next/standalone/.next/server/app/api/cortex/curation/refine/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/cortex/curation/review/route.js +1 -1
  95. package/.next/standalone/.next/server/app/api/cortex/curation/review/route.js.nft.json +1 -1
  96. package/.next/standalone/.next/server/app/api/cortex/curation/seed/route.js +1 -1
  97. package/.next/standalone/.next/server/app/api/cortex/curation/seed/route.js.nft.json +1 -1
  98. package/.next/standalone/.next/server/app/api/cortex/export/route.js +1 -1
  99. package/.next/standalone/.next/server/app/api/cortex/export/route.js.nft.json +1 -1
  100. package/.next/standalone/.next/server/app/api/cortex/federation/pending/route.js +1 -1
  101. package/.next/standalone/.next/server/app/api/cortex/federation/pending/route.js.nft.json +1 -1
  102. package/.next/standalone/.next/server/app/api/cortex/federation/resolve/route.js +1 -1
  103. package/.next/standalone/.next/server/app/api/cortex/federation/resolve/route.js.nft.json +1 -1
  104. package/.next/standalone/.next/server/app/api/cortex/federation/search/route.js +1 -1
  105. package/.next/standalone/.next/server/app/api/cortex/federation/search/route.js.nft.json +1 -1
  106. package/.next/standalone/.next/server/app/api/cortex/federation/teach/route.js +1 -1
  107. package/.next/standalone/.next/server/app/api/cortex/federation/teach/route.js.nft.json +1 -1
  108. package/.next/standalone/.next/server/app/api/cortex/graph/edges/route.js +1 -1
  109. package/.next/standalone/.next/server/app/api/cortex/graph/edges/route.js.nft.json +1 -1
  110. package/.next/standalone/.next/server/app/api/cortex/graph/entities/[id]/route.js +1 -1
  111. package/.next/standalone/.next/server/app/api/cortex/graph/entities/[id]/route.js.nft.json +1 -1
  112. package/.next/standalone/.next/server/app/api/cortex/graph/entities/route.js +1 -1
  113. package/.next/standalone/.next/server/app/api/cortex/graph/entities/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/cortex/graph/populate/route.js +1 -1
  115. package/.next/standalone/.next/server/app/api/cortex/graph/populate/route.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/api/cortex/import/route.js +1 -1
  117. package/.next/standalone/.next/server/app/api/cortex/import/route.js.nft.json +1 -1
  118. package/.next/standalone/.next/server/app/api/cortex/import/status/route.js +1 -1
  119. package/.next/standalone/.next/server/app/api/cortex/import/status/route.js.nft.json +1 -1
  120. package/.next/standalone/.next/server/app/api/cortex/ingest/bootstrap/route.js +1 -1
  121. package/.next/standalone/.next/server/app/api/cortex/ingest/bootstrap/route.js.nft.json +1 -1
  122. package/.next/standalone/.next/server/app/api/cortex/ingest/status/route.js +1 -1
  123. package/.next/standalone/.next/server/app/api/cortex/ingest/status/route.js.nft.json +1 -1
  124. package/.next/standalone/.next/server/app/api/cortex/knowledge/[id]/route.js +1 -1
  125. package/.next/standalone/.next/server/app/api/cortex/knowledge/[id]/route.js.nft.json +1 -1
  126. package/.next/standalone/.next/server/app/api/cortex/knowledge/route.js +1 -1
  127. package/.next/standalone/.next/server/app/api/cortex/knowledge/route.js.nft.json +1 -1
  128. package/.next/standalone/.next/server/app/api/cortex/lobes/[id]/route.js +1 -1
  129. package/.next/standalone/.next/server/app/api/cortex/lobes/[id]/route.js.nft.json +1 -1
  130. package/.next/standalone/.next/server/app/api/cortex/lobes/route.js +1 -1
  131. package/.next/standalone/.next/server/app/api/cortex/lobes/route.js.nft.json +1 -1
  132. package/.next/standalone/.next/server/app/api/cortex/lobes/share/route.js +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 +1 -1
  135. package/.next/standalone/.next/server/app/api/cortex/marketplace/browse/route.js.nft.json +1 -1
  136. package/.next/standalone/.next/server/app/api/cortex/marketplace/preview/route.js +1 -1
  137. package/.next/standalone/.next/server/app/api/cortex/marketplace/preview/route.js.nft.json +1 -1
  138. package/.next/standalone/.next/server/app/api/cortex/mcp/call/route.js +1 -1
  139. package/.next/standalone/.next/server/app/api/cortex/mcp/call/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/cortex/mcp/tools/route.js +1 -1
  141. package/.next/standalone/.next/server/app/api/cortex/mcp/tools/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/cortex/search/route.js +1 -1
  143. package/.next/standalone/.next/server/app/api/cortex/search/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/cortex/settings/route.js +1 -1
  145. package/.next/standalone/.next/server/app/api/cortex/settings/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/cortex/status/route.js +1 -1
  147. package/.next/standalone/.next/server/app/api/cortex/status/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/cortex/timeline/route.js +1 -1
  149. package/.next/standalone/.next/server/app/api/cortex/timeline/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/cortex/usage/route.js +1 -1
  151. package/.next/standalone/.next/server/app/api/cortex/usage/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/cortex/workspace/[id]/context/route.js +1 -1
  153. package/.next/standalone/.next/server/app/api/cortex/workspace/[id]/context/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/events/route.js +1 -1
  155. package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
  156. package/.next/standalone/.next/server/app/api/files/route.js +1 -1
  157. package/.next/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/api/folders/route.js +1 -1
  159. package/.next/standalone/.next/server/app/api/folders/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/network/handshake/route.js +1 -1
  161. package/.next/standalone/.next/server/app/api/network/handshake/route.js.nft.json +1 -1
  162. package/.next/standalone/.next/server/app/api/network/panes/[id]/route.js +1 -1
  163. package/.next/standalone/.next/server/app/api/network/panes/[id]/route.js.nft.json +1 -1
  164. package/.next/standalone/.next/server/app/api/network/panes/route.js +1 -1
  165. package/.next/standalone/.next/server/app/api/network/panes/route.js.nft.json +1 -1
  166. package/.next/standalone/.next/server/app/api/network/projects/route.js +1 -1
  167. package/.next/standalone/.next/server/app/api/network/projects/route.js.nft.json +1 -1
  168. package/.next/standalone/.next/server/app/api/network/search/route.js +1 -1
  169. package/.next/standalone/.next/server/app/api/network/search/route.js.nft.json +1 -1
  170. package/.next/standalone/.next/server/app/api/network/sessions/[id]/messages/route.js +1 -1
  171. package/.next/standalone/.next/server/app/api/network/sessions/[id]/messages/route.js.nft.json +1 -1
  172. package/.next/standalone/.next/server/app/api/network/sessions/[id]/route.js +1 -1
  173. package/.next/standalone/.next/server/app/api/network/sessions/[id]/route.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/api/network/sessions/route.js +1 -1
  175. package/.next/standalone/.next/server/app/api/network/sessions/route.js.nft.json +1 -1
  176. package/.next/standalone/.next/server/app/api/network/workspaces/[id]/route.js +1 -1
  177. package/.next/standalone/.next/server/app/api/network/workspaces/[id]/route.js.nft.json +1 -1
  178. package/.next/standalone/.next/server/app/api/network/workspaces/route.js +1 -1
  179. package/.next/standalone/.next/server/app/api/network/workspaces/route.js.nft.json +1 -1
  180. package/.next/standalone/.next/server/app/api/panes/[id]/diff/route.js +1 -1
  181. package/.next/standalone/.next/server/app/api/panes/[id]/diff/route.js.nft.json +1 -1
  182. package/.next/standalone/.next/server/app/api/panes/[id]/route.js +1 -1
  183. package/.next/standalone/.next/server/app/api/panes/[id]/route.js.nft.json +1 -1
  184. package/.next/standalone/.next/server/app/api/panes/route.js +1 -1
  185. package/.next/standalone/.next/server/app/api/panes/route.js.nft.json +1 -1
  186. package/.next/standalone/.next/server/app/api/projects/route.js +1 -1
  187. package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  188. package/.next/standalone/.next/server/app/api/proxy/models/[modelId]/[...path]/route.js +1 -1
  189. package/.next/standalone/.next/server/app/api/proxy/models/[modelId]/[...path]/route.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/api/proxy/models/[modelId]/status/route.js +1 -1
  191. package/.next/standalone/.next/server/app/api/proxy/models/[modelId]/status/route.js.nft.json +1 -1
  192. package/.next/standalone/.next/server/app/api/search/route.js +2 -2
  193. package/.next/standalone/.next/server/app/api/search/route.js.nft.json +1 -1
  194. package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js +1 -1
  195. package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js.nft.json +1 -1
  196. package/.next/standalone/.next/server/app/api/sessions/[id]/messages/route.js +1 -1
  197. package/.next/standalone/.next/server/app/api/sessions/[id]/messages/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/sessions/[id]/route.js +1 -1
  199. package/.next/standalone/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  200. package/.next/standalone/.next/server/app/api/sessions/route.js +2 -2
  201. package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
  202. package/.next/standalone/.next/server/app/api/sync/route.js +1 -1
  203. package/.next/standalone/.next/server/app/api/sync/route.js.nft.json +1 -1
  204. package/.next/standalone/.next/server/app/api/tags/route.js +1 -1
  205. package/.next/standalone/.next/server/app/api/tags/route.js.nft.json +1 -1
  206. package/.next/standalone/.next/server/app/api/tier/route.js +1 -1
  207. package/.next/standalone/.next/server/app/api/tier/route.js.nft.json +1 -1
  208. package/.next/standalone/.next/server/app/api/whisper/config/route.js +1 -1
  209. package/.next/standalone/.next/server/app/api/whisper/config/route.js.nft.json +1 -1
  210. package/.next/standalone/.next/server/app/api/whisper/route.js.nft.json +1 -1
  211. package/.next/standalone/.next/server/app/api/wizard/chart/route/app-paths-manifest.json +3 -0
  212. package/.next/standalone/.next/server/app/api/wizard/chart/route/build-manifest.json +11 -0
  213. package/.next/standalone/.next/server/app/api/wizard/chart/route/server-reference-manifest.json +4 -0
  214. package/.next/standalone/.next/server/app/api/wizard/chart/route.js +7 -0
  215. package/.next/standalone/.next/server/app/api/wizard/chart/route.js.map +5 -0
  216. package/.next/standalone/.next/server/app/api/wizard/chart/route.js.nft.json +1 -0
  217. package/.next/standalone/.next/server/app/api/wizard/chart/route_client-reference-manifest.js +2 -0
  218. package/.next/standalone/.next/server/app/api/wizard/chat/route.js +1 -1
  219. package/.next/standalone/.next/server/app/api/wizard/chat/route.js.nft.json +1 -1
  220. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/[key]/route.js +1 -1
  221. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/[key]/route.js.nft.json +1 -1
  222. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/route.js +1 -1
  223. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/route.js.nft.json +1 -1
  224. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/[msgId]/route.js +1 -1
  225. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/[msgId]/route.js.nft.json +1 -1
  226. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/route.js +1 -1
  227. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/route.js.nft.json +1 -1
  228. package/.next/standalone/.next/server/app/api/workspaces/[id]/route.js +1 -1
  229. package/.next/standalone/.next/server/app/api/workspaces/[id]/route.js.nft.json +1 -1
  230. package/.next/standalone/.next/server/app/api/workspaces/[id]/sessions/route.js +1 -1
  231. package/.next/standalone/.next/server/app/api/workspaces/[id]/sessions/route.js.nft.json +1 -1
  232. package/.next/standalone/.next/server/app/api/workspaces/route.js +2 -2
  233. package/.next/standalone/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  234. package/.next/standalone/.next/server/app/cortex.html +1 -1
  235. package/.next/standalone/.next/server/app/cortex.rsc +3 -3
  236. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex/__PAGE__.segment.rsc +2 -2
  237. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex.segment.rsc +1 -1
  238. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  239. package/.next/standalone/.next/server/app/cortex.segments/_full.segment.rsc +3 -3
  240. package/.next/standalone/.next/server/app/cortex.segments/_head.segment.rsc +1 -1
  241. package/.next/standalone/.next/server/app/cortex.segments/_index.segment.rsc +2 -2
  242. package/.next/standalone/.next/server/app/cortex.segments/_tree.segment.rsc +2 -2
  243. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  244. package/.next/standalone/.next/server/app/login.html +1 -1
  245. package/.next/standalone/.next/server/app/login.rsc +2 -2
  246. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +2 -2
  247. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
  248. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +2 -2
  249. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  250. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  251. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
  252. package/.next/standalone/.next/server/app/m/page_client-reference-manifest.js +1 -1
  253. package/.next/standalone/.next/server/app/m/projects/page_client-reference-manifest.js +1 -1
  254. package/.next/standalone/.next/server/app/m/projects.html +1 -1
  255. package/.next/standalone/.next/server/app/m/projects.rsc +2 -2
  256. package/.next/standalone/.next/server/app/m/projects.segments/_full.segment.rsc +2 -2
  257. package/.next/standalone/.next/server/app/m/projects.segments/_head.segment.rsc +1 -1
  258. package/.next/standalone/.next/server/app/m/projects.segments/_index.segment.rsc +2 -2
  259. package/.next/standalone/.next/server/app/m/projects.segments/_tree.segment.rsc +2 -2
  260. package/.next/standalone/.next/server/app/m/projects.segments/m/projects/__PAGE__.segment.rsc +1 -1
  261. package/.next/standalone/.next/server/app/m/projects.segments/m/projects.segment.rsc +1 -1
  262. package/.next/standalone/.next/server/app/m/projects.segments/m.segment.rsc +1 -1
  263. package/.next/standalone/.next/server/app/m/sessions/[id]/page.js.nft.json +1 -1
  264. package/.next/standalone/.next/server/app/m/sessions/[id]/page_client-reference-manifest.js +1 -1
  265. package/.next/standalone/.next/server/app/m/sessions/page_client-reference-manifest.js +1 -1
  266. package/.next/standalone/.next/server/app/m/sessions.html +1 -1
  267. package/.next/standalone/.next/server/app/m/sessions.rsc +2 -2
  268. package/.next/standalone/.next/server/app/m/sessions.segments/_full.segment.rsc +2 -2
  269. package/.next/standalone/.next/server/app/m/sessions.segments/_head.segment.rsc +1 -1
  270. package/.next/standalone/.next/server/app/m/sessions.segments/_index.segment.rsc +2 -2
  271. package/.next/standalone/.next/server/app/m/sessions.segments/_tree.segment.rsc +2 -2
  272. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions/__PAGE__.segment.rsc +1 -1
  273. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions.segment.rsc +1 -1
  274. package/.next/standalone/.next/server/app/m/sessions.segments/m.segment.rsc +1 -1
  275. package/.next/standalone/.next/server/app/m/settings/page_client-reference-manifest.js +1 -1
  276. package/.next/standalone/.next/server/app/m/settings.html +1 -1
  277. package/.next/standalone/.next/server/app/m/settings.rsc +2 -2
  278. package/.next/standalone/.next/server/app/m/settings.segments/_full.segment.rsc +2 -2
  279. package/.next/standalone/.next/server/app/m/settings.segments/_head.segment.rsc +1 -1
  280. package/.next/standalone/.next/server/app/m/settings.segments/_index.segment.rsc +2 -2
  281. package/.next/standalone/.next/server/app/m/settings.segments/_tree.segment.rsc +2 -2
  282. package/.next/standalone/.next/server/app/m/settings.segments/m/settings/__PAGE__.segment.rsc +1 -1
  283. package/.next/standalone/.next/server/app/m/settings.segments/m/settings.segment.rsc +1 -1
  284. package/.next/standalone/.next/server/app/m/settings.segments/m.segment.rsc +1 -1
  285. package/.next/standalone/.next/server/app/m/terminal/page_client-reference-manifest.js +1 -1
  286. package/.next/standalone/.next/server/app/m/terminal.html +1 -1
  287. package/.next/standalone/.next/server/app/m/terminal.rsc +3 -3
  288. package/.next/standalone/.next/server/app/m/terminal.segments/_full.segment.rsc +3 -3
  289. package/.next/standalone/.next/server/app/m/terminal.segments/_head.segment.rsc +1 -1
  290. package/.next/standalone/.next/server/app/m/terminal.segments/_index.segment.rsc +2 -2
  291. package/.next/standalone/.next/server/app/m/terminal.segments/_tree.segment.rsc +2 -2
  292. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal/__PAGE__.segment.rsc +2 -2
  293. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal.segment.rsc +1 -1
  294. package/.next/standalone/.next/server/app/m/terminal.segments/m.segment.rsc +1 -1
  295. package/.next/standalone/.next/server/app/m.html +1 -1
  296. package/.next/standalone/.next/server/app/m.rsc +2 -2
  297. package/.next/standalone/.next/server/app/m.segments/_full.segment.rsc +2 -2
  298. package/.next/standalone/.next/server/app/m.segments/_head.segment.rsc +1 -1
  299. package/.next/standalone/.next/server/app/m.segments/_index.segment.rsc +2 -2
  300. package/.next/standalone/.next/server/app/m.segments/_tree.segment.rsc +2 -2
  301. package/.next/standalone/.next/server/app/m.segments/m/__PAGE__.segment.rsc +1 -1
  302. package/.next/standalone/.next/server/app/m.segments/m.segment.rsc +1 -1
  303. package/.next/standalone/.next/server/app/network.html +1 -1
  304. package/.next/standalone/.next/server/app/network.rsc +2 -2
  305. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network/__PAGE__.segment.rsc +1 -1
  306. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network.segment.rsc +1 -1
  307. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  308. package/.next/standalone/.next/server/app/network.segments/_full.segment.rsc +2 -2
  309. package/.next/standalone/.next/server/app/network.segments/_head.segment.rsc +1 -1
  310. package/.next/standalone/.next/server/app/network.segments/_index.segment.rsc +2 -2
  311. package/.next/standalone/.next/server/app/network.segments/_tree.segment.rsc +2 -2
  312. package/.next/standalone/.next/server/app/projects.html +1 -1
  313. package/.next/standalone/.next/server/app/projects.rsc +2 -2
  314. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects/__PAGE__.segment.rsc +1 -1
  315. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects.segment.rsc +1 -1
  316. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  317. package/.next/standalone/.next/server/app/projects.segments/_full.segment.rsc +2 -2
  318. package/.next/standalone/.next/server/app/projects.segments/_head.segment.rsc +1 -1
  319. package/.next/standalone/.next/server/app/projects.segments/_index.segment.rsc +2 -2
  320. package/.next/standalone/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
  321. package/.next/standalone/.next/server/app/sessions.html +1 -1
  322. package/.next/standalone/.next/server/app/sessions.rsc +2 -2
  323. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions/__PAGE__.segment.rsc +1 -1
  324. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions.segment.rsc +1 -1
  325. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  326. package/.next/standalone/.next/server/app/sessions.segments/_full.segment.rsc +2 -2
  327. package/.next/standalone/.next/server/app/sessions.segments/_head.segment.rsc +1 -1
  328. package/.next/standalone/.next/server/app/sessions.segments/_index.segment.rsc +2 -2
  329. package/.next/standalone/.next/server/app/sessions.segments/_tree.segment.rsc +2 -2
  330. package/.next/standalone/.next/server/app/settings.html +1 -1
  331. package/.next/standalone/.next/server/app/settings.rsc +2 -2
  332. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings/__PAGE__.segment.rsc +1 -1
  333. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings.segment.rsc +1 -1
  334. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  335. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +2 -2
  336. package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  337. package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  338. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  339. package/.next/standalone/.next/server/app/terminal.html +1 -1
  340. package/.next/standalone/.next/server/app/terminal.rsc +3 -3
  341. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal/__PAGE__.segment.rsc +2 -2
  342. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal.segment.rsc +1 -1
  343. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  344. package/.next/standalone/.next/server/app/terminal.segments/_full.segment.rsc +3 -3
  345. package/.next/standalone/.next/server/app/terminal.segments/_head.segment.rsc +1 -1
  346. package/.next/standalone/.next/server/app/terminal.segments/_index.segment.rsc +2 -2
  347. package/.next/standalone/.next/server/app/terminal.segments/_tree.segment.rsc +2 -2
  348. package/.next/standalone/.next/server/app/vr/page/react-loadable-manifest.json +1 -1
  349. package/.next/standalone/.next/server/app/vr/page_client-reference-manifest.js +1 -1
  350. package/.next/standalone/.next/server/app/vr.html +1 -1
  351. package/.next/standalone/.next/server/app/vr.rsc +3 -3
  352. package/.next/standalone/.next/server/app/vr.segments/_full.segment.rsc +3 -3
  353. package/.next/standalone/.next/server/app/vr.segments/_head.segment.rsc +1 -1
  354. package/.next/standalone/.next/server/app/vr.segments/_index.segment.rsc +2 -2
  355. package/.next/standalone/.next/server/app/vr.segments/_tree.segment.rsc +2 -2
  356. package/.next/standalone/.next/server/app/vr.segments/vr/__PAGE__.segment.rsc +2 -2
  357. package/.next/standalone/.next/server/app/vr.segments/vr.segment.rsc +1 -1
  358. package/.next/standalone/.next/server/app/workspaces.html +1 -1
  359. package/.next/standalone/.next/server/app/workspaces.rsc +2 -2
  360. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces/__PAGE__.segment.rsc +1 -1
  361. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces.segment.rsc +1 -1
  362. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  363. package/.next/standalone/.next/server/app/workspaces.segments/_full.segment.rsc +2 -2
  364. package/.next/standalone/.next/server/app/workspaces.segments/_head.segment.rsc +1 -1
  365. package/.next/standalone/.next/server/app/workspaces.segments/_index.segment.rsc +2 -2
  366. package/.next/standalone/.next/server/app/workspaces.segments/_tree.segment.rsc +2 -2
  367. package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
  368. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00e90fc6._.js +98 -0
  369. package/.next/standalone/.next/server/chunks/[root-of-the-server]__01ab8675._.js +98 -0
  370. package/.next/standalone/.next/server/chunks/[root-of-the-server]__03974f05._.js +98 -0
  371. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__bb331da9._.js → [root-of-the-server]__046c9b91._.js} +3 -3
  372. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04ae6bf0._.js +98 -0
  373. package/.next/standalone/.next/server/chunks/[root-of-the-server]__056fa416._.js +1 -1
  374. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ac4ea3f._.js +3 -0
  375. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b8e64cb._.js +98 -0
  376. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__d95165f0._.js → [root-of-the-server]__0facd39e._.js} +3 -3
  377. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10bc76a3._.js +3 -0
  378. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__9d68157b._.js → [root-of-the-server]__115f3934._.js} +3 -3
  379. package/.next/standalone/.next/server/chunks/[root-of-the-server]__11f155f1._.js +3 -0
  380. package/.next/standalone/.next/server/chunks/[root-of-the-server]__160e7c73._.js +22 -33
  381. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__91e23c96._.js → [root-of-the-server]__17a3b966._.js} +3 -3
  382. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__277d9445._.js → [root-of-the-server]__17d3a2b2._.js} +3 -3
  383. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a86c055._.js +98 -0
  384. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20b5e9c4._.js +3 -0
  385. package/.next/standalone/.next/server/chunks/[root-of-the-server]__28d6fbd8._.js +98 -0
  386. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__04f04898._.js → [root-of-the-server]__2a3f866b._.js} +2 -2
  387. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__a95bb38b._.js → [root-of-the-server]__316617e7._.js} +2 -2
  388. package/.next/standalone/.next/server/chunks/[root-of-the-server]__32ad8f71._.js +98 -0
  389. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__6fe5e6c8._.js → [root-of-the-server]__35457394._.js} +2 -2
  390. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1f054c65._.js → [root-of-the-server]__35de78e6._.js} +3 -3
  391. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3685ffcb._.js +98 -0
  392. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__614458b7._.js → [root-of-the-server]__38954988._.js} +3 -3
  393. package/.next/standalone/.next/server/chunks/[root-of-the-server]__426ad936._.js +106 -0
  394. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4985c034._.js +98 -0
  395. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5c6ce9ed._.js +98 -0
  396. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5cebe58a._.js +98 -0
  397. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5d5e4789._.js +98 -0
  398. package/.next/standalone/.next/server/chunks/[root-of-the-server]__65676930._.js +3 -0
  399. package/.next/standalone/.next/server/chunks/[root-of-the-server]__67cab326._.js +58 -0
  400. package/.next/standalone/.next/server/chunks/[root-of-the-server]__698c6f01._.js +98 -0
  401. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c64af29._.js +131 -0
  402. package/.next/standalone/.next/server/chunks/[root-of-the-server]__73aed9f5._.js +98 -0
  403. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__ac84b704._.js → [root-of-the-server]__79b6a9bb._.js} +3 -3
  404. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__e56abacf._.js → [root-of-the-server]__7db704c6._.js} +4 -4
  405. package/.next/standalone/.next/server/chunks/[root-of-the-server]__812ca02b._.js +98 -0
  406. package/.next/standalone/.next/server/chunks/[root-of-the-server]__821f50fa._.js +98 -0
  407. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8716b86e._.js +98 -0
  408. package/.next/standalone/.next/server/chunks/[root-of-the-server]__884ef754._.js +98 -0
  409. package/.next/standalone/.next/server/chunks/[root-of-the-server]__88cdbd68._.js +98 -0
  410. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89d9aba9._.js +98 -0
  411. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8d536cb5._.js +98 -0
  412. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8df8c5d1._.js +98 -0
  413. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__2d7a454e._.js → [root-of-the-server]__8f2ccc41._.js} +3 -3
  414. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__2a2c5fc5._.js → [root-of-the-server]__95c9d682._.js} +4 -4
  415. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9e5d7774._.js +98 -0
  416. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__cc6e2885._.js → [root-of-the-server]__9edcff87._.js} +2 -2
  417. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a049dfc2._.js +98 -0
  418. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a5b4bb9a._.js +98 -0
  419. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__929ea03a._.js → [root-of-the-server]__a83262a1._.js} +2 -2
  420. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9cd1240._.js +98 -0
  421. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9d7f822._.js +98 -0
  422. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ad08c221._.js +98 -0
  423. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ad585f2f._.js +98 -0
  424. package/.next/standalone/.next/server/chunks/[root-of-the-server]__afcb8f7d._.js +98 -0
  425. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bc250d43._.js +98 -0
  426. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bce2a6e7._.js +98 -0
  427. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c011bf91._.js +98 -0
  428. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c0ac2895._.js +3 -0
  429. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c130a00c._.js +1 -1
  430. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c37d6380._.js +3 -0
  431. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cae392eb._.js +98 -0
  432. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cc2616bb._.js +3 -3
  433. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d501fa9b._.js +98 -0
  434. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d59c6c15._.js +98 -0
  435. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d5c1db32._.js +98 -0
  436. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d5d92527._.js +1 -1
  437. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dba60c86._.js +98 -0
  438. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__2384f98e._.js → [root-of-the-server]__de14b9ae._.js} +3 -3
  439. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e10643d1._.js +98 -0
  440. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__00fdfbda._.js → [root-of-the-server]__e2a996e5._.js} +2 -2
  441. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__4d903941._.js → [root-of-the-server]__e3477417._.js} +3 -3
  442. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__32dc5513._.js → [root-of-the-server]__e4db362e._.js} +2 -2
  443. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__49e42a3a._.js → [root-of-the-server]__e4e70b86._.js} +3 -3
  444. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__ac39ecc7._.js → [root-of-the-server]__e54925af._.js} +3 -3
  445. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e8edc5b0._.js +98 -0
  446. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__eafd040b._.js → [root-of-the-server]__eab4d83b._.js} +2 -2
  447. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ead29015._.js +1 -1
  448. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__194955d4._.js → [root-of-the-server]__f056fd83._.js} +3 -3
  449. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f0e99572._.js +98 -0
  450. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fe1e16d0._.js +98 -0
  451. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ff9cd277._.js +98 -0
  452. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ffaea2ce._.js +98 -0
  453. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_wizard_chart_route_actions_888e2ec1.js +3 -0
  454. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__2cffc362._.js +3 -0
  455. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__f1050870._.js → [root-of-the-server]__47c97637._.js} +2 -2
  456. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__66aca5d4._.js +1 -1
  457. package/.next/standalone/.next/server/chunks/ssr/_17b946fd._.js +3 -0
  458. package/.next/standalone/.next/server/chunks/ssr/_2a1d79e7._.js +1 -1
  459. package/.next/standalone/.next/server/chunks/ssr/_5c3c4cfa._.js +7 -5
  460. package/.next/standalone/.next/server/chunks/ssr/_ba432382._.js +7 -5
  461. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_cortex_page_tsx_0f33d8b3._.js +1 -1
  462. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_terminal_page_tsx_de5e8d85._.js +4 -4
  463. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__90eeddae._.js +1 -1
  464. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  465. package/.next/standalone/.next/server/pages/404.html +1 -1
  466. package/.next/standalone/.next/server/pages/500.html +2 -2
  467. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  468. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  469. package/.next/standalone/.next/static/chunks/0852575eb90c1e8d.js +85 -0
  470. package/.next/standalone/.next/static/chunks/{74d0ac0b1d0a1b79.js → 10b00b4f66102dcf.js} +1 -1
  471. package/.next/standalone/.next/static/chunks/{16eb77953dee9ea3.js → 19c71a8376c23c58.js} +1 -1
  472. package/.next/standalone/.next/static/chunks/2b769d1597e4fc1c.css +3 -0
  473. package/.next/standalone/.next/static/chunks/{3e91fc608659c524.js → 350271fe79509caf.js} +1 -1
  474. package/.next/standalone/.next/static/chunks/{70423c7afd8abf5f.js → 597847c22200c212.js} +1 -1
  475. package/.next/standalone/.next/static/chunks/{fb0abd1933b2b2e1.js → 7f6a14f1849fa94d.js} +1 -1
  476. package/.next/standalone/.next/static/chunks/{7ecd9bbb0ce4d68a.js → b7c8fe9b7275a84f.js} +1 -1
  477. package/.next/standalone/.next/static/chunks/{6245135a7afb8c7b.js → c9b10fc55516d142.js} +8 -6
  478. package/.next/standalone/.next/static/chunks/d0065f48eab94944.js +1 -0
  479. package/.next/standalone/.next/static/chunks/{180c1b9ff31b979f.js → f7b34c807badf95d.js} +8 -6
  480. package/.next/standalone/.spaces/cortex-context.md +50 -144
  481. package/.next/standalone/LICENSE +661 -661
  482. package/.next/standalone/NOTICE +5 -5
  483. package/.next/standalone/README.md +131 -131
  484. package/.next/standalone/bin/cortex-hook.js +79 -79
  485. package/.next/standalone/bin/cortex-hook.sh +62 -62
  486. package/.next/standalone/bin/cortex-learn-hook.js +138 -138
  487. package/.next/standalone/bin/cortex-mcp.js +60 -60
  488. package/.next/standalone/bin/cortex-pi-extension.ts +170 -170
  489. package/.next/standalone/bin/fix-standalone-externals.js +79 -79
  490. package/.next/standalone/bin/lib/auto-setup.js +110 -110
  491. package/.next/standalone/bin/mdns-service.js +171 -171
  492. package/.next/standalone/bin/postinstall.js +35 -35
  493. package/.next/standalone/bin/setup-admin.js +195 -195
  494. package/.next/standalone/bin/spaces-dev.js +247 -247
  495. package/.next/standalone/bin/spaces-install.js +660 -660
  496. package/.next/standalone/bin/spaces-postinstall.js +50 -50
  497. package/.next/standalone/bin/spaces-reset-totp.js +50 -50
  498. package/.next/standalone/bin/spaces-service.js +1046 -1046
  499. package/.next/standalone/bin/spaces-setup.js +253 -253
  500. package/.next/standalone/bin/spaces.js +808 -805
  501. package/.next/standalone/bin/ssh-auth-keys.sh +68 -68
  502. package/.next/standalone/bin/terminal-server.js +2819 -2781
  503. package/.next/standalone/cortex-hook-debug.log +57 -23
  504. package/.next/standalone/docker-compose.yml +28 -28
  505. package/.next/standalone/docs/architecture.md +387 -387
  506. package/.next/standalone/docs/cortex-integration-reference.md +268 -268
  507. package/.next/standalone/docs/cortex.md +293 -293
  508. package/.next/standalone/docs/getting-started.md +96 -96
  509. package/.next/standalone/docs/plans/2026-02-24-multi-agent-sessions-design.md +133 -133
  510. package/.next/standalone/docs/plans/2026-02-24-multi-agent-sessions-plan.md +959 -959
  511. package/.next/standalone/docs/plans/2026-03-02-security-audit.md +229 -229
  512. package/.next/standalone/docs/plans/2026-03-07-service-command-design.md +146 -146
  513. package/.next/standalone/docs/plans/2026-03-07-service-command-plan.md +254 -254
  514. package/.next/standalone/docs/server-install.md +564 -564
  515. package/.next/standalone/docs/social-card.html +150 -150
  516. package/.next/standalone/docs/superpowers/plans/2026-03-12-spaces-cortex.md +5270 -5270
  517. package/.next/standalone/docs/superpowers/plans/2026-03-13-cortex-wiring.md +1387 -1387
  518. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-entity-graph.md +1923 -1923
  519. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-knowledge-evolution.md +1113 -1113
  520. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-boundary-engine.md +853 -853
  521. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-context-engine.md +1274 -1274
  522. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-signal-ingestion.md +933 -933
  523. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-lobes.md +1080 -1080
  524. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-gravity-system.md +768 -768
  525. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-ui.md +1108 -1108
  526. package/.next/standalone/docs/superpowers/plans/2026-03-18-cortex-ui-integration.md +1846 -1846
  527. package/.next/standalone/docs/superpowers/plans/2026-03-19-vr-phase1-shell.md +1639 -1639
  528. package/.next/standalone/docs/superpowers/plans/2026-03-27-dockview-pane-layout.md +98 -98
  529. package/.next/standalone/docs/superpowers/specs/2026-03-11-universe-view-design.md +320 -320
  530. package/.next/standalone/docs/superpowers/specs/2026-03-12-spaces-brain-design.md +720 -720
  531. package/.next/standalone/docs/superpowers/specs/2026-03-13-cortex-wiring-design.md +268 -268
  532. package/.next/standalone/docs/superpowers/specs/2026-03-14-cortex-v2-design.md +623 -623
  533. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-lobes-design.md +263 -263
  534. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-v2-ui-design.md +240 -240
  535. package/.next/standalone/docs/superpowers/specs/2026-03-16-pane-ux-design.md +77 -77
  536. package/.next/standalone/docs/superpowers/specs/2026-03-18-cortex-ui-integration-design.md +341 -341
  537. package/.next/standalone/docs/superpowers/specs/2026-03-19-vr-phase1-shell-design.md +288 -288
  538. package/.next/standalone/docs/superpowers/specs/2026-03-27-pane-diff-review-and-project-wizard-design.md +322 -322
  539. package/.next/standalone/docs/tiers.md +104 -104
  540. package/.next/standalone/eslint.config.mjs +18 -18
  541. package/.next/standalone/next.config.ts +20 -20
  542. package/.next/standalone/nginx.conf +53 -53
  543. package/.next/standalone/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64.node +0 -0
  544. package/.next/standalone/node_modules/@img/{sharp-linux-x64 → sharp-win32-x64}/package.json +39 -46
  545. package/.next/standalone/package-lock.json +14985 -14986
  546. package/.next/standalone/package.json +111 -111
  547. package/.next/standalone/postcss.config.mjs +7 -7
  548. package/.next/standalone/scripts/rebuild.cmd +65 -65
  549. package/.next/standalone/scripts/rebuild.sh +59 -59
  550. package/.next/standalone/server.js +1 -1
  551. package/.next/standalone/src/app/(desktop)/admin/analytics/page.tsx +266 -266
  552. package/.next/standalone/src/app/(desktop)/admin/users/page.tsx +399 -399
  553. package/.next/standalone/src/app/(desktop)/analytics/page.tsx +166 -166
  554. package/.next/standalone/src/app/(desktop)/cortex/page.tsx +81 -81
  555. package/.next/standalone/src/app/(desktop)/dashboard-client.tsx +56 -56
  556. package/.next/standalone/src/app/(desktop)/layout.tsx +18 -18
  557. package/.next/standalone/src/app/(desktop)/network/page.tsx +137 -137
  558. package/.next/standalone/src/app/(desktop)/page.tsx +17 -17
  559. package/.next/standalone/src/app/(desktop)/projects/page.tsx +68 -68
  560. package/.next/standalone/src/app/(desktop)/sessions/[id]/page.tsx +519 -519
  561. package/.next/standalone/src/app/(desktop)/sessions/page.tsx +145 -145
  562. package/.next/standalone/src/app/(desktop)/settings/page.tsx +446 -446
  563. package/.next/standalone/src/app/(desktop)/terminal/layout.tsx +7 -7
  564. package/.next/standalone/src/app/(desktop)/terminal/page.tsx +1330 -1291
  565. package/.next/standalone/src/app/(desktop)/terminal/pane/[id]/page.tsx +211 -211
  566. package/.next/standalone/src/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page.tsx +252 -252
  567. package/.next/standalone/src/app/(desktop)/workspaces/page.tsx +12 -12
  568. package/.next/standalone/src/app/api/admin/analytics/route.ts +10 -10
  569. package/.next/standalone/src/app/api/admin/users/[id]/route.ts +20 -20
  570. package/.next/standalone/src/app/api/admin/users/route.ts +15 -15
  571. package/.next/standalone/src/app/api/analytics/overview/route.ts +80 -80
  572. package/.next/standalone/src/app/api/auth/login/route.ts +10 -10
  573. package/.next/standalone/src/app/api/auth/logout/route.ts +9 -9
  574. package/.next/standalone/src/app/api/auth/me/route.ts +22 -22
  575. package/.next/standalone/src/app/api/auth/totp/setup/route.ts +10 -10
  576. package/.next/standalone/src/app/api/auth/totp/status/route.ts +10 -10
  577. package/.next/standalone/src/app/api/auth/totp/verify/route.ts +10 -10
  578. package/.next/standalone/src/app/api/benchmark/lobes/route.ts +16 -16
  579. package/.next/standalone/src/app/api/benchmark/run/route.ts +113 -92
  580. package/.next/standalone/src/app/api/benchmark/runs/[id]/route.ts +26 -26
  581. package/.next/standalone/src/app/api/benchmark/runs/route.ts +16 -16
  582. package/.next/standalone/src/app/api/benchmark/status/route.ts +35 -35
  583. package/.next/standalone/src/app/api/bulk/route.ts +34 -34
  584. package/.next/standalone/src/app/api/chat/route.ts +85 -85
  585. package/.next/standalone/src/app/api/config/route.ts +30 -30
  586. package/.next/standalone/src/app/api/cortex/context/route.ts +78 -78
  587. package/.next/standalone/src/app/api/cortex/curation/assess/route.ts +27 -27
  588. package/.next/standalone/src/app/api/cortex/curation/publish/route.ts +23 -23
  589. package/.next/standalone/src/app/api/cortex/curation/refine/route.ts +23 -23
  590. package/.next/standalone/src/app/api/cortex/curation/review/route.ts +29 -29
  591. package/.next/standalone/src/app/api/cortex/curation/seed/route.ts +23 -23
  592. package/.next/standalone/src/app/api/cortex/export/route.ts +40 -40
  593. package/.next/standalone/src/app/api/cortex/federation/pending/route.ts +20 -20
  594. package/.next/standalone/src/app/api/cortex/federation/resolve/route.ts +43 -43
  595. package/.next/standalone/src/app/api/cortex/federation/search/route.ts +35 -35
  596. package/.next/standalone/src/app/api/cortex/federation/teach/route.ts +76 -76
  597. package/.next/standalone/src/app/api/cortex/graph/edges/route.ts +112 -112
  598. package/.next/standalone/src/app/api/cortex/graph/entities/[id]/route.ts +73 -73
  599. package/.next/standalone/src/app/api/cortex/graph/entities/route.ts +75 -75
  600. package/.next/standalone/src/app/api/cortex/graph/populate/route.ts +203 -203
  601. package/.next/standalone/src/app/api/cortex/import/route.ts +75 -75
  602. package/.next/standalone/src/app/api/cortex/import/status/route.ts +15 -15
  603. package/.next/standalone/src/app/api/cortex/ingest/bootstrap/route.ts +39 -39
  604. package/.next/standalone/src/app/api/cortex/ingest/status/route.ts +15 -15
  605. package/.next/standalone/src/app/api/cortex/knowledge/[id]/route.ts +91 -91
  606. package/.next/standalone/src/app/api/cortex/knowledge/route.ts +97 -97
  607. package/.next/standalone/src/app/api/cortex/lobes/[id]/route.ts +67 -67
  608. package/.next/standalone/src/app/api/cortex/lobes/route.ts +22 -22
  609. package/.next/standalone/src/app/api/cortex/lobes/share/route.ts +80 -80
  610. package/.next/standalone/src/app/api/cortex/marketplace/browse/route.ts +43 -43
  611. package/.next/standalone/src/app/api/cortex/marketplace/preview/route.ts +46 -46
  612. package/.next/standalone/src/app/api/cortex/mcp/call/route.ts +11 -11
  613. package/.next/standalone/src/app/api/cortex/mcp/tools/route.ts +8 -8
  614. package/.next/standalone/src/app/api/cortex/search/route.ts +57 -45
  615. package/.next/standalone/src/app/api/cortex/settings/route.ts +35 -35
  616. package/.next/standalone/src/app/api/cortex/status/route.ts +169 -169
  617. package/.next/standalone/src/app/api/cortex/timeline/route.ts +42 -42
  618. package/.next/standalone/src/app/api/cortex/usage/route.ts +31 -31
  619. package/.next/standalone/src/app/api/cortex/workspace/[id]/context/route.ts +41 -41
  620. package/.next/standalone/src/app/api/events/route.ts +40 -40
  621. package/.next/standalone/src/app/api/files/route.ts +187 -187
  622. package/.next/standalone/src/app/api/folders/route.ts +107 -97
  623. package/.next/standalone/src/app/api/network/connect-callback/route.ts +11 -11
  624. package/.next/standalone/src/app/api/network/connect-request/[id]/route.ts +11 -11
  625. package/.next/standalone/src/app/api/network/connect-request/route.ts +17 -17
  626. package/.next/standalone/src/app/api/network/discovered/route.ts +9 -9
  627. package/.next/standalone/src/app/api/network/handshake/route.ts +25 -25
  628. package/.next/standalone/src/app/api/network/health/route.ts +10 -10
  629. package/.next/standalone/src/app/api/network/identity/route.ts +15 -15
  630. package/.next/standalone/src/app/api/network/keys/[id]/route.ts +10 -10
  631. package/.next/standalone/src/app/api/network/keys/route.ts +15 -15
  632. package/.next/standalone/src/app/api/network/nodes/[id]/route.ts +15 -15
  633. package/.next/standalone/src/app/api/network/nodes/check/route.ts +9 -9
  634. package/.next/standalone/src/app/api/network/nodes/route.ts +15 -15
  635. package/.next/standalone/src/app/api/network/panes/[id]/route.ts +78 -62
  636. package/.next/standalone/src/app/api/network/panes/route.ts +61 -50
  637. package/.next/standalone/src/app/api/network/projects/route.ts +32 -25
  638. package/.next/standalone/src/app/api/network/proxy/[nodeId]/[...path]/route.ts +25 -25
  639. package/.next/standalone/src/app/api/network/search/route.ts +45 -38
  640. package/.next/standalone/src/app/api/network/sessions/[id]/messages/route.ts +43 -36
  641. package/.next/standalone/src/app/api/network/sessions/[id]/route.ts +41 -34
  642. package/.next/standalone/src/app/api/network/sessions/route.ts +50 -43
  643. package/.next/standalone/src/app/api/network/terminal/token/route.ts +10 -10
  644. package/.next/standalone/src/app/api/network/workspaces/[id]/route.ts +80 -71
  645. package/.next/standalone/src/app/api/network/workspaces/route.ts +87 -85
  646. package/.next/standalone/src/app/api/panes/[id]/diff/route.ts +121 -121
  647. package/.next/standalone/src/app/api/panes/[id]/route.ts +60 -60
  648. package/.next/standalone/src/app/api/panes/route.ts +39 -39
  649. package/.next/standalone/src/app/api/projects/route.ts +13 -13
  650. package/.next/standalone/src/app/api/proxy/models/[modelId]/[...path]/route.ts +80 -80
  651. package/.next/standalone/src/app/api/proxy/models/[modelId]/status/route.ts +33 -33
  652. package/.next/standalone/src/app/api/search/route.ts +47 -47
  653. package/.next/standalone/src/app/api/sessions/[id]/chat/route.ts +120 -120
  654. package/.next/standalone/src/app/api/sessions/[id]/messages/route.ts +34 -34
  655. package/.next/standalone/src/app/api/sessions/[id]/route.ts +73 -73
  656. package/.next/standalone/src/app/api/sessions/route.ts +64 -64
  657. package/.next/standalone/src/app/api/sync/route.ts +24 -24
  658. package/.next/standalone/src/app/api/tags/route.ts +35 -35
  659. package/.next/standalone/src/app/api/tier/route.ts +16 -16
  660. package/.next/standalone/src/app/api/updates/route.ts +65 -65
  661. package/.next/standalone/src/app/api/whisper/config/route.ts +50 -42
  662. package/.next/standalone/src/app/api/whisper/route.ts +91 -91
  663. package/.next/standalone/src/app/api/wizard/chart/route.ts +129 -0
  664. package/.next/standalone/src/app/api/wizard/chat/route.ts +113 -113
  665. package/.next/standalone/src/app/api/workspaces/[id]/context/[key]/route.ts +39 -39
  666. package/.next/standalone/src/app/api/workspaces/[id]/context/route.ts +28 -28
  667. package/.next/standalone/src/app/api/workspaces/[id]/messages/[msgId]/route.ts +17 -17
  668. package/.next/standalone/src/app/api/workspaces/[id]/messages/route.ts +39 -39
  669. package/.next/standalone/src/app/api/workspaces/[id]/route.ts +47 -47
  670. package/.next/standalone/src/app/api/workspaces/[id]/sessions/route.ts +62 -62
  671. package/.next/standalone/src/app/api/workspaces/route.ts +79 -79
  672. package/.next/standalone/src/app/globals.css +88 -88
  673. package/.next/standalone/src/app/layout.tsx +33 -33
  674. package/.next/standalone/src/app/login/layout.tsx +7 -7
  675. package/.next/standalone/src/app/login/page.tsx +315 -315
  676. package/.next/standalone/src/app/m/layout.tsx +16 -16
  677. package/.next/standalone/src/app/m/page.tsx +118 -118
  678. package/.next/standalone/src/app/m/projects/page.tsx +64 -64
  679. package/.next/standalone/src/app/m/sessions/[id]/page.tsx +168 -168
  680. package/.next/standalone/src/app/m/sessions/page.tsx +177 -177
  681. package/.next/standalone/src/app/m/settings/page.tsx +230 -230
  682. package/.next/standalone/src/app/m/terminal/page.tsx +413 -413
  683. package/.next/standalone/src/app/vr/page.tsx +21 -21
  684. package/.next/standalone/src/app/vr/vr-app.tsx +163 -163
  685. package/.next/standalone/src/app/vr/vr-controls.tsx +139 -139
  686. package/.next/standalone/src/app/vr/vr-door.tsx +82 -82
  687. package/.next/standalone/src/app/vr/vr-environment.tsx +71 -71
  688. package/.next/standalone/src/app/vr/vr-gaze.tsx +89 -89
  689. package/.next/standalone/src/app/vr/vr-layout.ts +49 -49
  690. package/.next/standalone/src/app/vr/vr-lobby.tsx +97 -97
  691. package/.next/standalone/src/app/vr/vr-pane.tsx +195 -195
  692. package/.next/standalone/src/app/vr/vr-room.tsx +79 -79
  693. package/.next/standalone/src/app/vr/vr-terminal.tsx +303 -303
  694. package/.next/standalone/src/components/auth/totp-gate.tsx +183 -183
  695. package/.next/standalone/src/components/bus/activity-panel.tsx +261 -261
  696. package/.next/standalone/src/components/common/color-picker.tsx +35 -35
  697. package/.next/standalone/src/components/common/dev-directory-picker.tsx +339 -339
  698. package/.next/standalone/src/components/common/folder-picker.tsx +200 -200
  699. package/.next/standalone/src/components/common/tag-picker.tsx +190 -190
  700. package/.next/standalone/src/components/common/workspace-picker.tsx +113 -113
  701. package/.next/standalone/src/components/cortex/benchmark-tab.tsx +894 -880
  702. package/.next/standalone/src/components/cortex/constants.ts +29 -29
  703. package/.next/standalone/src/components/cortex/cortex-dashboard.tsx +304 -304
  704. package/.next/standalone/src/components/cortex/cortex-indicator.tsx +44 -44
  705. package/.next/standalone/src/components/cortex/cortex-panel.tsx +140 -140
  706. package/.next/standalone/src/components/cortex/cortex-settings.tsx +280 -280
  707. package/.next/standalone/src/components/cortex/curation-tab.tsx +810 -810
  708. package/.next/standalone/src/components/cortex/entity-detail.tsx +101 -101
  709. package/.next/standalone/src/components/cortex/entity-graph.tsx +382 -382
  710. package/.next/standalone/src/components/cortex/import-dialog.tsx +212 -212
  711. package/.next/standalone/src/components/cortex/injection-badge.tsx +72 -72
  712. package/.next/standalone/src/components/cortex/knowledge-card.tsx +109 -109
  713. package/.next/standalone/src/components/cortex/knowledge-tab.tsx +158 -158
  714. package/.next/standalone/src/components/cortex/lobe-settings.tsx +215 -215
  715. package/.next/standalone/src/components/cortex/marketplace-card.tsx +126 -126
  716. package/.next/standalone/src/components/cortex/marketplace-tab.tsx +113 -113
  717. package/.next/standalone/src/components/dashboard/activity-chart.tsx +41 -41
  718. package/.next/standalone/src/components/dashboard/model-usage-chart.tsx +61 -61
  719. package/.next/standalone/src/components/dashboard/recent-sessions.tsx +68 -68
  720. package/.next/standalone/src/components/dashboard/stats-cards.tsx +36 -36
  721. package/.next/standalone/src/components/files/file-explorer.tsx +703 -703
  722. package/.next/standalone/src/components/layout/providers.tsx +38 -38
  723. package/.next/standalone/src/components/layout/sidebar.tsx +170 -170
  724. package/.next/standalone/src/components/layout/tier-provider.tsx +53 -53
  725. package/.next/standalone/src/components/layout/update-banner.tsx +92 -92
  726. package/.next/standalone/src/components/mobile/bottom-nav.tsx +46 -46
  727. package/.next/standalone/src/components/mobile/immersive-voice-button.tsx +123 -123
  728. package/.next/standalone/src/components/mobile/mobile-chat-input.tsx +244 -244
  729. package/.next/standalone/src/components/mobile/mobile-header.tsx +44 -44
  730. package/.next/standalone/src/components/mobile/mobile-session-card.tsx +56 -56
  731. package/.next/standalone/src/components/mobile/mobile-terminal-input.tsx +74 -74
  732. package/.next/standalone/src/components/mobile/mobile-terminal-pane.tsx +302 -302
  733. package/.next/standalone/src/components/mobile/mobile-terminal-toolbar.tsx +76 -76
  734. package/.next/standalone/src/components/mobile/pull-to-refresh.tsx +82 -82
  735. package/.next/standalone/src/components/mobile/voice-input.tsx +53 -53
  736. package/.next/standalone/src/components/network/api-key-list.tsx +190 -190
  737. package/.next/standalone/src/components/network/connection-requests.tsx +94 -94
  738. package/.next/standalone/src/components/network/node-add-dialog.tsx +131 -131
  739. package/.next/standalone/src/components/network/node-badge.tsx +26 -26
  740. package/.next/standalone/src/components/network/node-list.tsx +207 -207
  741. package/.next/standalone/src/components/network/node-selector.tsx +49 -49
  742. package/.next/standalone/src/components/sessions/session-filters.tsx +116 -116
  743. package/.next/standalone/src/components/sessions/session-list.tsx +485 -485
  744. package/.next/standalone/src/components/terminal/pane-diff-panel.tsx +179 -179
  745. package/.next/standalone/src/components/terminal/terminal-pane.tsx +1530 -1464
  746. package/.next/standalone/src/components/viewer/chat-input.tsx +275 -275
  747. package/.next/standalone/src/components/viewer/message-renderer.tsx +551 -551
  748. package/.next/standalone/src/components/wizard/chart-wizard.tsx +405 -0
  749. package/.next/standalone/src/components/wizard/project-wizard.tsx +153 -153
  750. package/.next/standalone/src/components/wizard/wizard-chat.tsx +99 -99
  751. package/.next/standalone/src/components/wizard/wizard-plan-summary.tsx +103 -103
  752. package/.next/standalone/src/components/wizard/wizard-review.tsx +225 -225
  753. package/.next/standalone/src/components/workspace/universe-cluster.tsx +131 -131
  754. package/.next/standalone/src/components/workspace/universe-orb.tsx +128 -128
  755. package/.next/standalone/src/components/workspace/universe-types.ts +22 -22
  756. package/.next/standalone/src/components/workspace/universe-utils.ts +11 -11
  757. package/.next/standalone/src/components/workspace/universe-view.tsx +397 -397
  758. package/.next/standalone/src/components/workspace/workspace-chooser.tsx +634 -634
  759. package/.next/standalone/src/hooks/use-benchmark.ts +72 -71
  760. package/.next/standalone/src/hooks/use-bus.ts +147 -147
  761. package/.next/standalone/src/hooks/use-idle-detection.ts +79 -79
  762. package/.next/standalone/src/hooks/use-network.ts +229 -229
  763. package/.next/standalone/src/hooks/use-sessions.ts +437 -437
  764. package/.next/standalone/src/hooks/use-speech-recognition.ts +114 -113
  765. package/.next/standalone/src/hooks/use-sse.ts +35 -35
  766. package/.next/standalone/src/hooks/use-tier.ts +39 -39
  767. package/.next/standalone/src/lib/agents.ts +97 -97
  768. package/.next/standalone/src/lib/aider/parser.ts +111 -111
  769. package/.next/standalone/src/lib/api.ts +19 -19
  770. package/.next/standalone/src/lib/auth.ts +47 -47
  771. package/.next/standalone/src/lib/claude/parser.ts +212 -212
  772. package/.next/standalone/src/lib/claude/stats.ts +204 -204
  773. package/.next/standalone/src/lib/codex/parser.test.ts +111 -111
  774. package/.next/standalone/src/lib/codex/parser.ts +287 -287
  775. package/.next/standalone/src/lib/config.ts +132 -132
  776. package/.next/standalone/src/lib/cortex/benchmark.ts +83 -67
  777. package/.next/standalone/src/lib/cortex/config.ts +42 -42
  778. package/.next/standalone/src/lib/cortex/debug.ts +10 -10
  779. package/.next/standalone/src/lib/cortex/distillation/usage-store.ts +18 -18
  780. package/.next/standalone/src/lib/cortex/graph/resolver.ts +10 -10
  781. package/.next/standalone/src/lib/cortex/graph/types.ts +22 -22
  782. package/.next/standalone/src/lib/cortex/index.ts +109 -56
  783. package/.next/standalone/src/lib/cortex/ingestion/bootstrap.ts +14 -14
  784. package/.next/standalone/src/lib/cortex/knowledge/compat.ts +14 -14
  785. package/.next/standalone/src/lib/cortex/knowledge/contradiction.ts +10 -10
  786. package/.next/standalone/src/lib/cortex/knowledge/types.ts +67 -67
  787. package/.next/standalone/src/lib/cortex/lobes/config.ts +16 -16
  788. package/.next/standalone/src/lib/cortex/lobes/resolver.ts +8 -8
  789. package/.next/standalone/src/lib/cortex/lobes/shares.ts +14 -14
  790. package/.next/standalone/src/lib/cortex/mcp/server.ts +12 -12
  791. package/.next/standalone/src/lib/cortex/portability/exporter.ts +6 -6
  792. package/.next/standalone/src/lib/cortex/portability/importer.ts +10 -10
  793. package/.next/standalone/src/lib/cortex/retrieval/context-engine.ts +10 -10
  794. package/.next/standalone/src/lib/cortex/types.ts +39 -39
  795. package/.next/standalone/src/lib/cost-calculator.ts +48 -48
  796. package/.next/standalone/src/lib/db/init.ts +71 -71
  797. package/.next/standalone/src/lib/db/queries.ts +740 -827
  798. package/.next/standalone/src/lib/db/schema.ts +206 -206
  799. package/.next/standalone/src/lib/events/sse.ts +36 -36
  800. package/.next/standalone/src/lib/forge/parser.ts +52 -52
  801. package/.next/standalone/src/lib/gemini/parser.ts +258 -258
  802. package/.next/standalone/src/lib/license.ts +56 -56
  803. package/.next/standalone/src/lib/pro.ts +31 -31
  804. package/.next/standalone/src/lib/shell-user.ts +101 -0
  805. package/.next/standalone/src/lib/sync/indexer.ts +504 -504
  806. package/.next/standalone/src/lib/sync/watcher.ts +64 -64
  807. package/.next/standalone/src/lib/teams.ts +31 -31
  808. package/.next/standalone/src/lib/telemetry.ts +75 -75
  809. package/.next/standalone/src/lib/terminal/server.ts +188 -188
  810. package/.next/standalone/src/lib/tier.ts +38 -38
  811. package/.next/standalone/src/lib/utils.ts +72 -72
  812. package/.next/standalone/src/lib/vms/manager.ts +121 -121
  813. package/.next/standalone/src/middleware.ts +133 -133
  814. package/.next/standalone/src/types/claude.ts +208 -208
  815. package/.next/standalone/src/types/network.ts +61 -61
  816. package/.next/standalone/tests/setup.ts +8 -8
  817. package/.next/standalone/tsconfig.json +34 -34
  818. package/.next/standalone/vitest.config.ts +24 -24
  819. package/LICENSE +661 -661
  820. package/README.md +131 -131
  821. package/bin/cortex-hook.js +79 -79
  822. package/bin/cortex-hook.sh +62 -62
  823. package/bin/cortex-learn-hook.js +138 -138
  824. package/bin/cortex-mcp.js +60 -60
  825. package/bin/cortex-pi-extension.ts +170 -170
  826. package/bin/fix-standalone-externals.js +79 -79
  827. package/bin/lib/auto-setup.js +110 -110
  828. package/bin/mdns-service.js +171 -171
  829. package/bin/postinstall.js +35 -35
  830. package/bin/setup-admin.js +195 -195
  831. package/bin/spaces-dev.js +247 -247
  832. package/bin/spaces-install.js +660 -660
  833. package/bin/spaces-postinstall.js +50 -50
  834. package/bin/spaces-reset-totp.js +50 -50
  835. package/bin/spaces-service.js +1046 -1046
  836. package/bin/spaces-setup.js +253 -253
  837. package/bin/spaces.js +808 -805
  838. package/bin/ssh-auth-keys.sh +68 -68
  839. package/bin/terminal-server.js +2819 -2781
  840. package/package.json +111 -111
  841. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0903a426._.js +0 -98
  842. package/.next/standalone/.next/server/chunks/[root-of-the-server]__09e8ccc9._.js +0 -98
  843. package/.next/standalone/.next/server/chunks/[root-of-the-server]__11c684b1._.js +0 -98
  844. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1572d4ef._.js +0 -98
  845. package/.next/standalone/.next/server/chunks/[root-of-the-server]__186cd0bb._.js +0 -3
  846. package/.next/standalone/.next/server/chunks/[root-of-the-server]__212760e6._.js +0 -98
  847. package/.next/standalone/.next/server/chunks/[root-of-the-server]__228595ec._.js +0 -98
  848. package/.next/standalone/.next/server/chunks/[root-of-the-server]__283c890f._.js +0 -3
  849. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2f300a68._.js +0 -98
  850. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2f452778._.js +0 -98
  851. package/.next/standalone/.next/server/chunks/[root-of-the-server]__35f8e77e._.js +0 -98
  852. package/.next/standalone/.next/server/chunks/[root-of-the-server]__379fc2e9._.js +0 -98
  853. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3b40d79f._.js +0 -98
  854. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3d3dca2b._.js +0 -98
  855. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4d5b78d2._.js +0 -98
  856. package/.next/standalone/.next/server/chunks/[root-of-the-server]__54163e52._.js +0 -98
  857. package/.next/standalone/.next/server/chunks/[root-of-the-server]__563c0817._.js +0 -3
  858. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5812f90a._.js +0 -98
  859. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5c5e87f5._.js +0 -98
  860. package/.next/standalone/.next/server/chunks/[root-of-the-server]__60d15b16._.js +0 -98
  861. package/.next/standalone/.next/server/chunks/[root-of-the-server]__69d315e5._.js +0 -3
  862. package/.next/standalone/.next/server/chunks/[root-of-the-server]__71f29038._.js +0 -98
  863. package/.next/standalone/.next/server/chunks/[root-of-the-server]__74084e07._.js +0 -3
  864. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7921aa80._.js +0 -98
  865. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7e077dd8._.js +0 -98
  866. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7ebc4280._.js +0 -131
  867. package/.next/standalone/.next/server/chunks/[root-of-the-server]__857c60bb._.js +0 -98
  868. package/.next/standalone/.next/server/chunks/[root-of-the-server]__874fe565._.js +0 -98
  869. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8e2171f7._.js +0 -98
  870. package/.next/standalone/.next/server/chunks/[root-of-the-server]__95659b2d._.js +0 -98
  871. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9679b91e._.js +0 -98
  872. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a90729a1._.js +0 -98
  873. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ad4346fa._.js +0 -98
  874. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b0862d69._.js +0 -98
  875. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b43306ee._.js +0 -98
  876. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b689ff5e._.js +0 -106
  877. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ba87daaa._.js +0 -98
  878. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c0461005._.js +0 -98
  879. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c1deb5f3._.js +0 -98
  880. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c8a62f42._.js +0 -98
  881. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cabaac2b._.js +0 -98
  882. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cb027619._.js +0 -98
  883. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cf608218._.js +0 -98
  884. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cfc1290d._.js +0 -98
  885. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d0109b9b._.js +0 -98
  886. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d0125483._.js +0 -3
  887. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d048ee6b._.js +0 -98
  888. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d12644e7._.js +0 -98
  889. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e3cc946c._.js +0 -98
  890. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e6fd27f8._.js +0 -98
  891. package/.next/standalone/.next/server/chunks/[root-of-the-server]__efb8251e._.js +0 -98
  892. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f44c6882._.js +0 -98
  893. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f85283de._.js +0 -98
  894. package/.next/standalone/.next/server/chunks/[root-of-the-server]__feceb3e4._.js +0 -98
  895. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__843070a6._.js +0 -3
  896. package/.next/standalone/.next/server/chunks/ssr/_e84a0c06._.js +0 -3
  897. package/.next/standalone/.next/static/chunks/470cade58d4eceeb.css +0 -3
  898. package/.next/standalone/.next/static/chunks/9d4164833c2c1fd6.js +0 -85
  899. package/.next/standalone/.next/static/chunks/f091f4bf8d80fd07.js +0 -1
  900. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/README.md +0 -46
  901. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/glib-2.0/include/glibconfig.h +0 -221
  902. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/index.js +0 -1
  903. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  904. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/package.json +0 -42
  905. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/README.md +0 -46
  906. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/glib-2.0/include/glibconfig.h +0 -221
  907. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/index.js +0 -1
  908. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  909. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json +0 -42
  910. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/versions.json +0 -30
  911. package/.next/standalone/node_modules/@img/sharp-linux-x64/lib/sharp-linux-x64.node +0 -0
  912. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/lib/sharp-linuxmusl-x64.node +0 -0
  913. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/package.json +0 -46
  914. /package/.next/standalone/.next/static/{5S4TviTCiNiTjf6KjXjBo → u1pHON3drz1mBi7owkbBP}/_buildManifest.js +0 -0
  915. /package/.next/standalone/.next/static/{5S4TviTCiNiTjf6KjXjBo → u1pHON3drz1mBi7owkbBP}/_clientMiddlewareManifest.json +0 -0
  916. /package/.next/standalone/.next/static/{5S4TviTCiNiTjf6KjXjBo → u1pHON3drz1mBi7owkbBP}/_ssgManifest.js +0 -0
  917. /package/.next/standalone/node_modules/@img/{sharp-libvips-linux-x64 → sharp-win32-x64}/versions.json +0 -0
@@ -1,1108 +1,1108 @@
1
- # Cortex v2 UI Implementation Plan
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 a dedicated `/cortex` page with interactive entity graph visualization, enhanced knowledge cards with v2 fields, and a context assembly dashboard — plus sidebar navigation and panel enhancements.
6
-
7
- **Architecture:** New `/app/(desktop)/cortex/page.tsx` with tab navigation (Graph | Knowledge | Context | Settings). Force graph rendered via `force-graph` npm package with `nodeCanvasObject` for custom shapes. Small backend tweaks to expose `listAllEdges()`, entities/conflicts/sourceWeights in context API. Existing right panel gets "Open full view" link.
8
-
9
- **Tech Stack:** React 19, Next.js 16, Tailwind CSS 4, force-graph, Lucide icons, TanStack React Query
10
-
11
- **Spec:** `docs/superpowers/specs/2026-03-16-cortex-v2-ui-design.md`
12
-
13
- ---
14
-
15
- ## File Structure
16
-
17
- ```
18
- New files:
19
- ├── src/app/(desktop)/cortex/page.tsx — Main /cortex page with tabs
20
- ├── src/components/cortex/entity-graph.tsx — Force graph canvas (dynamic, ssr:false)
21
- ├── src/components/cortex/entity-detail.tsx — Right-side entity detail panel
22
- ├── src/components/cortex/context-tab.tsx — Context assembly inspector tab
23
- ├── src/components/cortex/knowledge-tab.tsx — Knowledge list tab (reuses cards)
24
-
25
- Modified files:
26
- ├── src/components/cortex/knowledge-card.tsx — Add v2 badges + evidence bar
27
- ├── src/components/cortex/cortex-panel.tsx — Add "Open full view" link
28
- ├── src/components/layout/sidebar.tsx — Add Cortex nav item
29
- ├── src/lib/cortex/graph/entity-graph.ts — Add listAllEdges()
30
- ├── src/app/api/cortex/graph/edges/route.ts — Support all=true
31
- ├── src/lib/cortex/retrieval/context-engine.ts — Expose sourceWeights
32
- ├── src/app/api/cortex/context/route.ts — Return entities, conflicts, sourceWeights
33
- ```
34
-
35
- ---
36
-
37
- ## Chunk 1: Backend Tweaks + Enhanced Knowledge Card
38
-
39
- ### Task 1: Add listAllEdges() and edges `all=true` support
40
-
41
- **Files:**
42
- - Modify: `src/lib/cortex/graph/entity-graph.ts`
43
- - Modify: `src/app/api/cortex/graph/edges/route.ts`
44
-
45
- - [ ] **Step 1: Add listAllEdges() to EntityGraph**
46
-
47
- Read `src/lib/cortex/graph/entity-graph.ts`, find the edge methods section, add:
48
-
49
- ```typescript
50
- listAllEdges(): Edge[] {
51
- return (this.db.prepare('SELECT * FROM edges ORDER BY source_id').all() as any[])
52
- .map(r => this.rowToEdge(r));
53
- }
54
- ```
55
-
56
- - [ ] **Step 2: Update edges route GET handler**
57
-
58
- Read `src/app/api/cortex/graph/edges/route.ts`. At the top of the GET handler, before the `from`/`to` check, add:
59
-
60
- ```typescript
61
- const all = url.searchParams.get('all');
62
- if (all === 'true') {
63
- const edges = cortex.graph.listAllEdges();
64
- return NextResponse.json({ edges });
65
- }
66
- ```
67
-
68
- - [ ] **Step 3: Commit**
69
-
70
- ```bash
71
- git add src/lib/cortex/graph/entity-graph.ts src/app/api/cortex/graph/edges/route.ts
72
- git commit -m "feat(cortex): add listAllEdges() and edges all=true endpoint"
73
- ```
74
-
75
- ---
76
-
77
- ### Task 2: Expose sourceWeights in context API
78
-
79
- **Files:**
80
- - Modify: `src/lib/cortex/retrieval/context-engine.ts`
81
- - Modify: `src/app/api/cortex/context/route.ts`
82
-
83
- - [ ] **Step 1: Add sourceWeights to AssemblyResult**
84
-
85
- Read `src/lib/cortex/retrieval/context-engine.ts`. Find the `AssemblyResult` interface and add:
86
-
87
- ```typescript
88
- sourceWeights: Array<{ layerKey: string; scopeLevel: string; weight: number }>;
89
- ```
90
-
91
- Find the `assemble()` method. After `computeSourceWeights()` is called (the `sources` variable), map it into the result:
92
-
93
- ```typescript
94
- // In the return object, add:
95
- sourceWeights: sources.map(s => ({
96
- layerKey: s.layerKey,
97
- scopeLevel: s.layerKey === 'personal' ? 'personal' : s.layerKey.startsWith('workspace') ? 'team' : 'organization',
98
- weight: s.weight,
99
- })),
100
- ```
101
-
102
- - [ ] **Step 2: Update context route response**
103
-
104
- Read `src/app/api/cortex/context/route.ts`. In the `NextResponse.json()` call, change:
105
-
106
- ```typescript
107
- // From:
108
- conflicts: result.conflicts.length,
109
- // To:
110
- entities: result.entities,
111
- conflicts: result.conflicts,
112
- sourceWeights: result.sourceWeights,
113
- ```
114
-
115
- - [ ] **Step 3: Commit**
116
-
117
- ```bash
118
- git add src/lib/cortex/retrieval/context-engine.ts src/app/api/cortex/context/route.ts
119
- git commit -m "feat(cortex): expose entities, conflicts, sourceWeights in context API"
120
- ```
121
-
122
- ---
123
-
124
- ### Task 3: Enhanced knowledge card
125
-
126
- **Files:**
127
- - Modify: `src/components/cortex/knowledge-card.tsx`
128
-
129
- - [ ] **Step 1: Read the current knowledge-card.tsx**
130
-
131
- - [ ] **Step 2: Extend the props interface and add v2 display**
132
-
133
- Replace the entire file. The changes:
134
- - Extend `unit` props with optional v2 fields
135
- - Add sensitivity badge (color-coded)
136
- - Add scope badge
137
- - Add attribution row (creator, source, corroborations)
138
- - Replace confidence bar with evidence bar when available
139
- - Add conflict indicator
140
-
141
- ```typescript
142
- 'use client';
143
-
144
- import { Trash2, AlertTriangle } from 'lucide-react';
145
- import { api } from '@/lib/api';
146
-
147
- const TYPE_COLORS: Record<string, string> = {
148
- decision: 'bg-blue-500/20 text-blue-400',
149
- preference: 'bg-pink-500/20 text-pink-400',
150
- pattern: 'bg-green-500/20 text-green-400',
151
- error_fix: 'bg-amber-500/20 text-amber-400',
152
- context: 'bg-gray-500/20 text-gray-400',
153
- code_pattern: 'bg-cyan-500/20 text-cyan-400',
154
- command: 'bg-orange-500/20 text-orange-400',
155
- conversation: 'bg-slate-500/20 text-slate-400',
156
- summary: 'bg-violet-500/20 text-violet-400',
157
- };
158
-
159
- const SENSITIVITY_COLORS: Record<string, string> = {
160
- public: 'bg-green-500/20 text-green-400',
161
- internal: 'bg-indigo-500/20 text-indigo-400',
162
- restricted: 'bg-amber-500/20 text-amber-400',
163
- confidential: 'bg-red-500/20 text-red-400',
164
- };
165
-
166
- interface KnowledgeCardProps {
167
- unit: {
168
- id: string;
169
- text: string;
170
- type: string;
171
- confidence: number;
172
- created: string;
173
- session_id?: string | null;
174
- layer: string;
175
- stale_score?: number;
176
- // v2 fields
177
- scope?: { level: string; entity_id: string };
178
- sensitivity?: string;
179
- evidence_score?: number;
180
- corroborations?: number;
181
- contradiction_refs?: string[];
182
- origin?: { source_type: string; source_ref: string; creator_entity_id: string };
183
- };
184
- onDelete?: (id: string) => void;
185
- compact?: boolean;
186
- }
187
-
188
- export function KnowledgeCard({ unit, onDelete, compact }: KnowledgeCardProps) {
189
- const colorClass = TYPE_COLORS[unit.type] || TYPE_COLORS.context;
190
- const age = getRelativeAge(unit.created);
191
- const hasConflicts = (unit.contradiction_refs?.length ?? 0) > 0;
192
-
193
- // Use evidence_score if available, else confidence
194
- const score = unit.evidence_score ?? unit.confidence;
195
- const scoreLabel = unit.evidence_score != null
196
- ? `${score.toFixed(2)} evidence`
197
- : `${Math.round(score * 100)}%`;
198
-
199
- const handleDelete = async () => {
200
- await fetch(api(`/api/cortex/knowledge/${unit.id}`), { method: 'DELETE' });
201
- onDelete?.(unit.id);
202
- };
203
-
204
- return (
205
- <div className="group border border-white/5 rounded-lg p-3 hover:border-white/10 transition-colors">
206
- {/* Badge row */}
207
- <div className="flex items-start justify-between gap-2">
208
- <div className="flex items-center gap-1 flex-wrap">
209
- <span className={`text-[10px] px-1.5 py-0.5 rounded font-medium ${colorClass}`}>
210
- {unit.type.replace('_', ' ')}
211
- </span>
212
- {unit.sensitivity && (
213
- <span className={`text-[10px] px-1.5 py-0.5 rounded font-medium ${SENSITIVITY_COLORS[unit.sensitivity] || SENSITIVITY_COLORS.internal}`}>
214
- {unit.sensitivity}
215
- </span>
216
- )}
217
- {unit.scope && (
218
- <span className="text-[10px] px-1.5 py-0.5 rounded font-medium bg-purple-500/10 text-purple-400">
219
- {unit.scope.level}
220
- </span>
221
- )}
222
- {(unit.stale_score ?? 0) > 0.3 && (
223
- <span className="text-[10px] px-1.5 py-0.5 rounded font-medium bg-amber-500/20 text-amber-400">
224
- stale
225
- </span>
226
- )}
227
- {hasConflicts && (
228
- <span className="text-[10px] px-1.5 py-0.5 rounded font-medium bg-amber-500/20 text-amber-400 flex items-center gap-0.5">
229
- <AlertTriangle className="w-2.5 h-2.5" />
230
- contested
231
- </span>
232
- )}
233
- </div>
234
- <div className="flex items-center gap-2 text-[10px] text-gray-500 shrink-0">
235
- <span>{age}</span>
236
- {onDelete && (
237
- <button
238
- onClick={handleDelete}
239
- className="opacity-0 group-hover:opacity-100 transition-opacity text-red-400 hover:text-red-300"
240
- >
241
- <Trash2 className="w-3 h-3" />
242
- </button>
243
- )}
244
- </div>
245
- </div>
246
-
247
- {/* Text */}
248
- <p className="text-xs text-gray-300 mt-1.5 leading-relaxed line-clamp-3">{unit.text}</p>
249
-
250
- {/* Attribution row (v2) */}
251
- {!compact && unit.origin && (
252
- <div className="flex items-center gap-1.5 mt-1.5 text-[10px] text-gray-500 flex-wrap">
253
- <span>by {unit.origin.creator_entity_id.replace('person-', '')}</span>
254
- <span>&middot;</span>
255
- <span>via {unit.origin.source_type.replace('_', ' ')}</span>
256
- {(unit.corroborations ?? 0) > 0 && (
257
- <>
258
- <span>&middot;</span>
259
- <span className="text-green-400">{unit.corroborations} corr.</span>
260
- </>
261
- )}
262
- </div>
263
- )}
264
-
265
- {/* Evidence/confidence bar */}
266
- <div className="flex items-center gap-2 mt-2">
267
- <div className="flex-1 h-1 bg-white/5 rounded-full overflow-hidden">
268
- <div
269
- className="h-full bg-purple-500/50 rounded-full"
270
- style={{ width: `${Math.round(score * 100)}%` }}
271
- />
272
- </div>
273
- <span className="text-[10px] text-gray-500 tabular-nums">{scoreLabel}</span>
274
- </div>
275
- </div>
276
- );
277
- }
278
-
279
- function getRelativeAge(iso: string): string {
280
- const diff = Date.now() - new Date(iso).getTime();
281
- const days = Math.floor(diff / (1000 * 60 * 60 * 24));
282
- if (days === 0) return 'today';
283
- if (days === 1) return '1d ago';
284
- if (days < 30) return `${days}d ago`;
285
- if (days < 365) return `${Math.floor(days / 30)}mo ago`;
286
- return `${Math.floor(days / 365)}y ago`;
287
- }
288
- ```
289
-
290
- - [ ] **Step 3: Commit**
291
-
292
- ```bash
293
- git add src/components/cortex/knowledge-card.tsx
294
- git commit -m "feat(cortex): enhance knowledge card with v2 fields display"
295
- ```
296
-
297
- ---
298
-
299
- ## Chunk 2: Cortex Page + Sidebar
300
-
301
- ### Task 4: Sidebar navigation
302
-
303
- **Files:**
304
- - Modify: `src/components/layout/sidebar.tsx`
305
-
306
- - [ ] **Step 1: Read sidebar.tsx**
307
-
308
- - [ ] **Step 2: Add Cortex to nav array and imports**
309
-
310
- Add `Brain` to the lucide-react import. Add a Cortex entry to the `nav` array (after Network, before Settings):
311
-
312
- ```typescript
313
- // Add to imports:
314
- import { ..., Brain } from 'lucide-react';
315
-
316
- // Add to nav array (before Settings):
317
- { href: '/cortex', label: 'Cortex', icon: Brain },
318
-
319
- // Add to routeNames:
320
- '/cortex': 'cortex',
321
- ```
322
-
323
- In the nav filter, gate it like Network:
324
- ```typescript
325
- if (href === '/cortex') return hasCortex;
326
- ```
327
-
328
- - [ ] **Step 3: Commit**
329
-
330
- ```bash
331
- git add src/components/layout/sidebar.tsx
332
- git commit -m "feat(cortex): add Cortex nav item to sidebar"
333
- ```
334
-
335
- ---
336
-
337
- ### Task 5: Cortex page with tabs
338
-
339
- **Files:**
340
- - Create: `src/app/(desktop)/cortex/page.tsx`
341
-
342
- - [ ] **Step 1: Create the page**
343
-
344
- ```typescript
345
- 'use client';
346
-
347
- import { useState, useEffect } from 'react';
348
- import dynamic from 'next/dynamic';
349
- import { api } from '@/lib/api';
350
- import { KnowledgeTab } from '@/components/cortex/knowledge-tab';
351
- import { ContextTab } from '@/components/cortex/context-tab';
352
- import { CortexSettings } from '@/components/cortex/cortex-settings';
353
-
354
- const EntityGraphView = dynamic(
355
- () => import('@/components/cortex/entity-graph').then(m => ({ default: m.EntityGraphView })),
356
- { ssr: false, loading: () => <div className="flex-1 flex items-center justify-center text-gray-500 text-sm">Loading graph...</div> }
357
- );
358
-
359
- type Tab = 'graph' | 'knowledge' | 'context' | 'settings';
360
-
361
- export default function CortexPage() {
362
- const [tab, setTab] = useState<Tab>('graph');
363
- const [stats, setStats] = useState<any>(null);
364
-
365
- useEffect(() => {
366
- fetch(api('/api/cortex/status'))
367
- .then(r => r.json())
368
- .then(setStats)
369
- .catch(() => {});
370
- }, []);
371
-
372
- const tabs: { key: Tab; label: string }[] = [
373
- { key: 'graph', label: 'Graph' },
374
- { key: 'knowledge', label: 'Knowledge' },
375
- { key: 'context', label: 'Context' },
376
- { key: 'settings', label: 'Settings' },
377
- ];
378
-
379
- const totalKnowledge = stats
380
- ? Object.values(stats.layers || {}).reduce((sum: number, l: any) => sum + (l.count || 0), 0)
381
- : 0;
382
-
383
- return (
384
- <div className="flex flex-col h-screen bg-gray-950">
385
- {/* Tab bar */}
386
- <div className="flex items-center border-b border-white/5 px-4 shrink-0">
387
- <div className="flex">
388
- {tabs.map(t => (
389
- <button
390
- key={t.key}
391
- onClick={() => setTab(t.key)}
392
- className={`px-5 py-3 text-sm font-medium transition-colors border-b-2 ${
393
- tab === t.key
394
- ? 'text-purple-400 border-purple-400'
395
- : 'text-gray-500 border-transparent hover:text-gray-300'
396
- }`}
397
- >
398
- {t.label}
399
- </button>
400
- ))}
401
- </div>
402
- <div className="ml-auto text-xs text-gray-600">
403
- {totalKnowledge} knowledge units
404
- </div>
405
- </div>
406
-
407
- {/* Tab content */}
408
- <div className="flex-1 overflow-hidden">
409
- {tab === 'graph' && <EntityGraphView />}
410
- {tab === 'knowledge' && <KnowledgeTab />}
411
- {tab === 'context' && <ContextTab />}
412
- {tab === 'settings' && (
413
- <div className="p-6 max-w-2xl">
414
- <CortexSettings />
415
- </div>
416
- )}
417
- </div>
418
- </div>
419
- );
420
- }
421
- ```
422
-
423
- - [ ] **Step 2: Commit**
424
-
425
- ```bash
426
- git add src/app/(desktop)/cortex/page.tsx
427
- git commit -m "feat(cortex): add /cortex page with tab navigation"
428
- ```
429
-
430
- ---
431
-
432
- ### Task 6: Panel "Open full view" link
433
-
434
- **Files:**
435
- - Modify: `src/components/cortex/cortex-panel.tsx`
436
-
437
- - [ ] **Step 1: Add link to panel header**
438
-
439
- Read `src/components/cortex/cortex-panel.tsx`. In the header div (between the "Cortex" heading and the close button), add:
440
-
441
- ```typescript
442
- import Link from 'next/link';
443
- import { ExternalLink } from 'lucide-react';
444
-
445
- // In the header, after the h2:
446
- <Link
447
- href="/cortex"
448
- className="text-[10px] text-purple-400 hover:text-purple-300 flex items-center gap-1"
449
- onClick={onClose}
450
- >
451
- Full view <ExternalLink className="w-2.5 h-2.5" />
452
- </Link>
453
- ```
454
-
455
- - [ ] **Step 2: Commit**
456
-
457
- ```bash
458
- git add src/components/cortex/cortex-panel.tsx
459
- git commit -m "feat(cortex): add 'Full view' link to cortex panel"
460
- ```
461
-
462
- ---
463
-
464
- ## Chunk 3: Graph + Detail Components
465
-
466
- ### Task 7: Entity graph canvas component
467
-
468
- **Files:**
469
- - Create: `src/components/cortex/entity-graph.tsx`
470
-
471
- - [ ] **Step 1: Install force-graph**
472
-
473
- ```bash
474
- npm install force-graph
475
- ```
476
-
477
- - [ ] **Step 2: Create the graph component**
478
-
479
- ```typescript
480
- 'use client';
481
-
482
- import { useEffect, useRef, useState, useCallback } from 'react';
483
- import ForceGraph2D from 'force-graph';
484
- import { api } from '@/lib/api';
485
- import { EntityDetail } from './entity-detail';
486
-
487
- const NODE_COLORS: Record<string, string> = {
488
- person: '#7c3aed',
489
- team: '#10b981',
490
- project: '#10b981',
491
- department: '#3b82f6',
492
- organization: '#3b82f6',
493
- system: '#f59e0b',
494
- module: '#f59e0b',
495
- topic: '#06b6d4',
496
- };
497
-
498
- interface GraphNode {
499
- id: string;
500
- name: string;
501
- type: string;
502
- metadata: Record<string, unknown>;
503
- // force-graph adds x, y, vx, vy
504
- x?: number;
505
- y?: number;
506
- }
507
-
508
- interface GraphLink {
509
- source: string;
510
- target: string;
511
- relation: string;
512
- weight: number;
513
- }
514
-
515
- export function EntityGraphView() {
516
- const containerRef = useRef<HTMLDivElement>(null);
517
- const graphRef = useRef<any>(null);
518
- const [selectedNode, setSelectedNode] = useState<GraphNode | null>(null);
519
- const [graphData, setGraphData] = useState<{ nodes: GraphNode[]; links: GraphLink[] }>({ nodes: [], links: [] });
520
-
521
- // Fetch graph data
522
- useEffect(() => {
523
- Promise.all([
524
- fetch(api('/api/cortex/graph/entities')).then(r => r.json()),
525
- fetch(api('/api/cortex/graph/edges?all=true')).then(r => r.json()),
526
- ]).then(([entData, edgeData]) => {
527
- const nodes: GraphNode[] = (entData.entities || []).map((e: any) => ({
528
- id: e.id,
529
- name: e.name,
530
- type: e.type,
531
- metadata: e.metadata || {},
532
- }));
533
- const nodeIds = new Set(nodes.map(n => n.id));
534
- const links: GraphLink[] = (edgeData.edges || [])
535
- .filter((e: any) => nodeIds.has(e.source_id) && nodeIds.has(e.target_id))
536
- .map((e: any) => ({
537
- source: e.source_id,
538
- target: e.target_id,
539
- relation: e.relation,
540
- weight: e.weight,
541
- }));
542
- setGraphData({ nodes, links });
543
- }).catch(() => {});
544
- }, []);
545
-
546
- // Initialize force-graph
547
- useEffect(() => {
548
- if (!containerRef.current || graphData.nodes.length === 0) return;
549
-
550
- const width = containerRef.current.clientWidth;
551
- const height = containerRef.current.clientHeight;
552
-
553
- const graph = ForceGraph2D()(containerRef.current)
554
- .width(width)
555
- .height(height)
556
- .graphData(graphData)
557
- .nodeId('id')
558
- .nodeLabel((node: any) => `${node.name} (${node.type})`)
559
- .nodeCanvasObject((node: any, ctx: CanvasRenderingContext2D, globalScale: number) => {
560
- const color = NODE_COLORS[node.type] || '#666';
561
- const size = node.type === 'person' ? 8 : node.type === 'topic' ? 5 : 6;
562
- const x = node.x ?? 0;
563
- const y = node.y ?? 0;
564
-
565
- ctx.beginPath();
566
- if (node.type === 'system' || node.type === 'module') {
567
- // Diamond
568
- ctx.moveTo(x, y - size);
569
- ctx.lineTo(x + size, y);
570
- ctx.lineTo(x, y + size);
571
- ctx.lineTo(x - size, y);
572
- ctx.closePath();
573
- } else if (node.type === 'team' || node.type === 'project' || node.type === 'department' || node.type === 'organization') {
574
- // Rounded rect
575
- const w = size * 2;
576
- const h = size * 1.5;
577
- const r = 2;
578
- ctx.roundRect(x - w / 2, y - h / 2, w, h, r);
579
- } else {
580
- // Circle (person, topic)
581
- ctx.arc(x, y, size, 0, 2 * Math.PI);
582
- }
583
-
584
- ctx.fillStyle = color + '33';
585
- ctx.fill();
586
- ctx.strokeStyle = color;
587
- ctx.lineWidth = 1.5 / globalScale;
588
- ctx.stroke();
589
-
590
- // Label
591
- const fontSize = Math.max(10 / globalScale, 3);
592
- ctx.font = `${fontSize}px sans-serif`;
593
- ctx.textAlign = 'center';
594
- ctx.textBaseline = 'middle';
595
- ctx.fillStyle = color;
596
- ctx.fillText(node.name, x, y + size + fontSize);
597
- })
598
- .nodePointerAreaPaint((node: any, color: string, ctx: CanvasRenderingContext2D) => {
599
- const size = 10;
600
- ctx.fillStyle = color;
601
- ctx.beginPath();
602
- ctx.arc(node.x ?? 0, node.y ?? 0, size, 0, 2 * Math.PI);
603
- ctx.fill();
604
- })
605
- .linkColor(() => 'rgba(124, 58, 237, 0.2)')
606
- .linkWidth((link: any) => Math.max(0.5, link.weight * 2))
607
- .onNodeClick((node: any) => setSelectedNode(node))
608
- .onBackgroundClick(() => setSelectedNode(null))
609
- .backgroundColor('#06060c');
610
-
611
- graphRef.current = graph;
612
-
613
- const handleResize = () => {
614
- if (!containerRef.current) return;
615
- graph.width(containerRef.current.clientWidth);
616
- graph.height(containerRef.current.clientHeight);
617
- };
618
- window.addEventListener('resize', handleResize);
619
-
620
- return () => {
621
- window.removeEventListener('resize', handleResize);
622
- graph._destructor?.();
623
- };
624
- }, [graphData]);
625
-
626
- const handleRecenter = useCallback(() => {
627
- graphRef.current?.zoomToFit(400, 40);
628
- }, []);
629
-
630
- return (
631
- <div className="flex h-full">
632
- {/* Graph canvas */}
633
- <div className="flex-1 relative">
634
- <div ref={containerRef} className="w-full h-full" />
635
-
636
- {/* Controls overlay */}
637
- <div className="absolute bottom-3 left-3 flex gap-2">
638
- <button
639
- onClick={handleRecenter}
640
- className="px-3 py-1.5 text-xs bg-gray-900/80 border border-white/10 rounded text-gray-400 hover:text-gray-200"
641
- >
642
- Recenter
643
- </button>
644
- </div>
645
-
646
- {/* Legend overlay */}
647
- <div className="absolute top-3 right-3 bg-gray-950/90 border border-white/10 rounded-lg p-3 text-[10px] space-y-1">
648
- {Object.entries(NODE_COLORS).filter(([type]) =>
649
- ['person', 'team', 'system', 'topic'].includes(type)
650
- ).map(([type, color]) => (
651
- <div key={type} className="flex items-center gap-2">
652
- <span style={{ color }} className="text-sm">
653
- {type === 'system' ? '◆' : type === 'team' ? '■' : '●'}
654
- </span>
655
- <span className="text-gray-400 capitalize">{type}</span>
656
- </div>
657
- ))}
658
- </div>
659
-
660
- {graphData.nodes.length === 0 && (
661
- <div className="absolute inset-0 flex items-center justify-center text-gray-600 text-sm">
662
- No entities yet. Add entities via the API to see the graph.
663
- </div>
664
- )}
665
- </div>
666
-
667
- {/* Detail panel */}
668
- <div className="w-72 border-l border-white/5 bg-gray-950 overflow-y-auto">
669
- <EntityDetail
670
- node={selectedNode}
671
- onClose={() => setSelectedNode(null)}
672
- />
673
- </div>
674
- </div>
675
- );
676
- }
677
- ```
678
-
679
- - [ ] **Step 3: Commit**
680
-
681
- ```bash
682
- git add src/components/cortex/entity-graph.tsx
683
- git commit -m "feat(cortex): add force-graph entity visualization component"
684
- ```
685
-
686
- ---
687
-
688
- ### Task 8: Entity detail panel
689
-
690
- **Files:**
691
- - Create: `src/components/cortex/entity-detail.tsx`
692
-
693
- - [ ] **Step 1: Create the component**
694
-
695
- ```typescript
696
- 'use client';
697
-
698
- import { useState, useEffect } from 'react';
699
- import { api } from '@/lib/api';
700
-
701
- const RELATION_COLORS: Record<string, string> = {
702
- member_of: 'text-purple-400',
703
- expert_in: 'text-cyan-400',
704
- owns: 'text-green-400',
705
- contains: 'text-green-400',
706
- part_of: 'text-blue-400',
707
- works_on: 'text-purple-400',
708
- touches: 'text-amber-400',
709
- depends_on: 'text-red-400',
710
- relates_to: 'text-cyan-400',
711
- };
712
-
713
- interface EntityDetailProps {
714
- node: { id: string; name: string; type: string; metadata: Record<string, unknown> } | null;
715
- onClose: () => void;
716
- }
717
-
718
- export function EntityDetail({ node, onClose }: EntityDetailProps) {
719
- const [edges, setEdges] = useState<any[]>([]);
720
-
721
- useEffect(() => {
722
- if (!node) { setEdges([]); return; }
723
-
724
- Promise.all([
725
- fetch(api(`/api/cortex/graph/edges?from=${node.id}`)).then(r => r.json()),
726
- fetch(api(`/api/cortex/graph/edges?to=${node.id}`)).then(r => r.json()),
727
- ]).then(([fromData, toData]) => {
728
- const allEdges = [
729
- ...(fromData.edges || []).map((e: any) => ({ ...e, direction: 'out' })),
730
- ...(toData.edges || []).map((e: any) => ({ ...e, direction: 'in' })),
731
- ];
732
- setEdges(allEdges);
733
- }).catch(() => {});
734
- }, [node?.id]);
735
-
736
- if (!node) {
737
- return (
738
- <div className="p-4 text-center text-gray-600 text-xs mt-8">
739
- Click a node to see details
740
- </div>
741
- );
742
- }
743
-
744
- const firstLetter = node.name.charAt(0).toUpperCase();
745
- const color = node.type === 'person' ? '#7c3aed'
746
- : node.type === 'system' ? '#f59e0b'
747
- : node.type === 'topic' ? '#06b6d4'
748
- : '#10b981';
749
-
750
- return (
751
- <div className="p-4">
752
- {/* Header */}
753
- <div className="flex items-center gap-3 mb-4">
754
- <div
755
- className="w-8 h-8 rounded-full flex items-center justify-center text-sm font-bold"
756
- style={{ backgroundColor: color + '33', color, border: `2px solid ${color}` }}
757
- >
758
- {firstLetter}
759
- </div>
760
- <div>
761
- <div className="text-sm font-medium text-gray-200">{node.name}</div>
762
- <div className="text-[10px] text-gray-500">{node.type}</div>
763
- </div>
764
- </div>
765
-
766
- {/* Metadata */}
767
- {Object.keys(node.metadata).length > 0 && (
768
- <div className="mb-4">
769
- <div className="text-[10px] text-gray-600 uppercase tracking-wider mb-1">Metadata</div>
770
- {Object.entries(node.metadata).map(([k, v]) => (
771
- <div key={k} className="text-[11px] text-gray-400">
772
- <span className="text-gray-600">{k}:</span> {String(v)}
773
- </div>
774
- ))}
775
- </div>
776
- )}
777
-
778
- {/* Relationships */}
779
- <div className="text-[10px] text-gray-600 uppercase tracking-wider mb-2">
780
- Relationships ({edges.length})
781
- </div>
782
- <div className="space-y-1 mb-4">
783
- {edges.map((e, i) => {
784
- const relColor = RELATION_COLORS[e.relation] || 'text-gray-400';
785
- const target = e.direction === 'out' ? e.target_id : e.source_id;
786
- const arrow = e.direction === 'out' ? '→' : '←';
787
- return (
788
- <div key={i} className="flex items-center gap-1.5 text-[11px] bg-white/[0.02] rounded px-2 py-1.5">
789
- <span className={relColor}>{e.relation}</span>
790
- <span className="text-gray-600">{arrow}</span>
791
- <span className="text-gray-300 truncate">{target.replace(/^(person|team|system|topic|project|department|organization|module)-/, '')}</span>
792
- {e.weight < 1 && (
793
- <span className="text-gray-600 ml-auto text-[9px]">{e.weight.toFixed(2)}</span>
794
- )}
795
- </div>
796
- );
797
- })}
798
- {edges.length === 0 && (
799
- <div className="text-[11px] text-gray-600 py-2">No relationships</div>
800
- )}
801
- </div>
802
- </div>
803
- );
804
- }
805
- ```
806
-
807
- - [ ] **Step 2: Commit**
808
-
809
- ```bash
810
- git add src/components/cortex/entity-detail.tsx
811
- git commit -m "feat(cortex): add entity detail panel for graph view"
812
- ```
813
-
814
- ---
815
-
816
- ## Chunk 4: Knowledge Tab, Context Tab, Final Wiring
817
-
818
- ### Task 9: Knowledge tab component
819
-
820
- **Files:**
821
- - Create: `src/components/cortex/knowledge-tab.tsx`
822
-
823
- - [ ] **Step 1: Create the component**
824
-
825
- A search + list view that reuses `KnowledgeCard`. Fetches from `/api/cortex/search`.
826
-
827
- ```typescript
828
- 'use client';
829
-
830
- import { useState, useCallback, useEffect } from 'react';
831
- import { Search } from 'lucide-react';
832
- import { api } from '@/lib/api';
833
- import { KnowledgeCard } from './knowledge-card';
834
-
835
- export function KnowledgeTab() {
836
- const [query, setQuery] = useState('');
837
- const [results, setResults] = useState<any[]>([]);
838
- const [loading, setLoading] = useState(false);
839
-
840
- const fetchResults = useCallback(async (q?: string) => {
841
- setLoading(true);
842
- try {
843
- const params = new URLSearchParams({ limit: '30' });
844
- if (q) params.set('q', q);
845
- const res = await fetch(api(`/api/cortex/search?${params}`));
846
- if (res.ok) setResults((await res.json()).results || []);
847
- } catch {}
848
- setLoading(false);
849
- }, []);
850
-
851
- useEffect(() => { fetchResults(); }, [fetchResults]);
852
-
853
- const handleSearch = () => fetchResults(query.trim() || undefined);
854
- const handleDelete = (id: string) => setResults(prev => prev.filter(r => r.id !== id));
855
-
856
- return (
857
- <div className="flex flex-col h-full">
858
- <div className="p-4 border-b border-white/5">
859
- <div className="relative max-w-md">
860
- <Search className="absolute left-3 top-2.5 w-4 h-4 text-gray-500" />
861
- <input
862
- value={query}
863
- onChange={e => setQuery(e.target.value)}
864
- onKeyDown={e => e.key === 'Enter' && handleSearch()}
865
- placeholder="Search knowledge..."
866
- className="w-full pl-9 pr-4 py-2 text-sm bg-white/5 border border-white/10 rounded-lg text-gray-300 placeholder-gray-600 focus:outline-none focus:border-purple-500/50"
867
- />
868
- </div>
869
- </div>
870
- <div className="flex-1 overflow-y-auto p-4">
871
- <div className="max-w-2xl space-y-2">
872
- {loading && <p className="text-sm text-gray-500 text-center py-8">Loading...</p>}
873
- {!loading && results.length === 0 && (
874
- <p className="text-sm text-gray-500 text-center py-8">No knowledge found</p>
875
- )}
876
- {results.map(unit => (
877
- <KnowledgeCard key={unit.id} unit={unit} onDelete={handleDelete} />
878
- ))}
879
- </div>
880
- </div>
881
- </div>
882
- );
883
- }
884
- ```
885
-
886
- - [ ] **Step 2: Commit**
887
-
888
- ```bash
889
- git add src/components/cortex/knowledge-tab.tsx
890
- git commit -m "feat(cortex): add knowledge tab with search and v2 cards"
891
- ```
892
-
893
- ---
894
-
895
- ### Task 10: Context assembly tab
896
-
897
- **Files:**
898
- - Create: `src/components/cortex/context-tab.tsx`
899
-
900
- - [ ] **Step 1: Create the component**
901
-
902
- ```typescript
903
- 'use client';
904
-
905
- import { useState } from 'react';
906
- import { Search, ChevronDown, ChevronUp } from 'lucide-react';
907
- import { api } from '@/lib/api';
908
-
909
- const INTENT_COLORS: Record<string, string> = {
910
- debugging: 'text-red-400',
911
- architecture: 'text-blue-400',
912
- onboarding: 'text-green-400',
913
- policy: 'text-purple-400',
914
- 'how-to': 'text-amber-400',
915
- review: 'text-pink-400',
916
- security: 'text-red-500',
917
- general: 'text-gray-400',
918
- };
919
-
920
- export function ContextTab() {
921
- const [query, setQuery] = useState('');
922
- const [result, setResult] = useState<any>(null);
923
- const [loading, setLoading] = useState(false);
924
- const [showRaw, setShowRaw] = useState(false);
925
-
926
- const handleAnalyze = async () => {
927
- if (!query.trim()) return;
928
- setLoading(true);
929
- try {
930
- const res = await fetch(api(`/api/cortex/context?q=${encodeURIComponent(query)}&limit=5`));
931
- if (res.ok) setResult(await res.json());
932
- } catch {}
933
- setLoading(false);
934
- };
935
-
936
- return (
937
- <div className="p-6 max-w-3xl mx-auto">
938
- {/* Query input */}
939
- <div className="flex gap-3 mb-6">
940
- <div className="flex-1 relative">
941
- <Search className="absolute left-3 top-2.5 w-4 h-4 text-gray-500" />
942
- <input
943
- value={query}
944
- onChange={e => setQuery(e.target.value)}
945
- onKeyDown={e => e.key === 'Enter' && handleAnalyze()}
946
- placeholder="Enter a query to analyze..."
947
- className="w-full pl-9 pr-4 py-2 text-sm bg-white/5 border border-white/10 rounded-lg text-gray-300 placeholder-gray-600 focus:outline-none focus:border-purple-500/50"
948
- />
949
- </div>
950
- <button
951
- onClick={handleAnalyze}
952
- disabled={loading}
953
- className="px-5 py-2 text-sm bg-purple-600 hover:bg-purple-500 text-white rounded-lg disabled:opacity-50"
954
- >
955
- {loading ? 'Analyzing...' : 'Analyze'}
956
- </button>
957
- </div>
958
-
959
- {!result && !loading && (
960
- <p className="text-sm text-gray-600 text-center py-12">
961
- Enter a query to see how the Context Assembly Engine processes it
962
- </p>
963
- )}
964
-
965
- {result && (
966
- <>
967
- {/* Pipeline summary */}
968
- <div className="grid grid-cols-3 gap-3 mb-6">
969
- <div className="bg-white/[0.02] border border-white/5 rounded-lg p-3">
970
- <div className="text-[10px] text-gray-600 uppercase mb-1">Intent</div>
971
- <div className={`text-lg font-semibold ${INTENT_COLORS[result.intent?.intent] || 'text-gray-400'}`}>
972
- {result.intent?.intent || '?'}
973
- </div>
974
- <div className="text-[10px] text-gray-600">
975
- confidence: {(result.intent?.confidence ?? 0).toFixed(2)}
976
- </div>
977
- </div>
978
- <div className="bg-white/[0.02] border border-white/5 rounded-lg p-3">
979
- <div className="text-[10px] text-gray-600 uppercase mb-1">Entities</div>
980
- <div className="flex flex-wrap gap-1 mt-1">
981
- {(result.entities || []).map((e: any, i: number) => (
982
- <span key={i} className="text-[10px] px-1.5 py-0.5 bg-white/5 border border-white/10 rounded text-gray-300">
983
- {e.entity?.type}:{e.entity?.name}
984
- </span>
985
- ))}
986
- {(!result.entities || result.entities.length === 0) && (
987
- <span className="text-[10px] text-gray-600">none detected</span>
988
- )}
989
- </div>
990
- </div>
991
- <div className="bg-white/[0.02] border border-white/5 rounded-lg p-3">
992
- <div className="text-[10px] text-gray-600 uppercase mb-1">Timing</div>
993
- <div className="text-lg font-semibold text-green-400">
994
- {result.timing?.totalMs ?? '?'}ms
995
- </div>
996
- <div className="text-[10px] text-gray-600">
997
- intent {result.timing?.intentMs}ms · search {result.timing?.searchMs}ms
998
- </div>
999
- </div>
1000
- </div>
1001
-
1002
- {/* Source weights */}
1003
- {result.sourceWeights && (
1004
- <div className="mb-6">
1005
- <div className="text-[10px] text-gray-600 uppercase mb-2">Source Weights</div>
1006
- <div className="flex gap-3">
1007
- {result.sourceWeights.map((sw: any, i: number) => (
1008
- <div key={i} className="flex-1 bg-white/[0.02] rounded-lg p-3">
1009
- <div className="flex justify-between text-[11px] mb-1">
1010
- <span className="text-gray-300 capitalize">{sw.scopeLevel}</span>
1011
- <span className="text-gray-500">{sw.weight.toFixed(2)}</span>
1012
- </div>
1013
- <div className="h-1.5 bg-white/5 rounded-full overflow-hidden">
1014
- <div
1015
- className="h-full bg-purple-500/60 rounded-full"
1016
- style={{ width: `${Math.min(100, sw.weight * 100)}%` }}
1017
- />
1018
- </div>
1019
- </div>
1020
- ))}
1021
- </div>
1022
- </div>
1023
- )}
1024
-
1025
- {/* Results */}
1026
- <div className="mb-6">
1027
- <div className="text-[10px] text-gray-600 uppercase mb-2">
1028
- Results ({(result.results || []).length})
1029
- </div>
1030
- <div className="space-y-1">
1031
- {(result.results || []).map((r: any, i: number) => (
1032
- <div key={i} className="flex items-center gap-2 bg-white/[0.02] border border-white/5 rounded-lg px-3 py-2">
1033
- <span className={`text-[10px] px-1.5 py-0.5 rounded font-medium ${
1034
- r.type === 'error_fix' ? 'bg-amber-500/20 text-amber-400'
1035
- : r.type === 'decision' ? 'bg-blue-500/20 text-blue-400'
1036
- : 'bg-gray-500/20 text-gray-400'
1037
- }`}>{r.type?.replace('_', ' ')}</span>
1038
- <span className="text-xs text-gray-300 truncate flex-1">{r.text}</span>
1039
- <span className="text-[10px] text-gray-600 tabular-nums shrink-0">
1040
- {(r.relevance_score ?? 0).toFixed(3)}
1041
- </span>
1042
- </div>
1043
- ))}
1044
- </div>
1045
- </div>
1046
-
1047
- {/* Conflicts */}
1048
- {Array.isArray(result.conflicts) && result.conflicts.length > 0 && (
1049
- <div className="mb-6 border border-amber-500/20 bg-amber-500/5 rounded-lg p-3">
1050
- <div className="text-[10px] text-amber-400 uppercase font-medium mb-1">
1051
- Conflicts ({result.conflicts.length})
1052
- </div>
1053
- {result.conflicts.map((c: any, i: number) => (
1054
- <div key={i} className="text-xs text-gray-400 mt-1">
1055
- &ldquo;{c.unitA?.text?.slice(0, 60)}...&rdquo; vs &ldquo;{c.unitB?.text?.slice(0, 60)}...&rdquo;
1056
- </div>
1057
- ))}
1058
- </div>
1059
- )}
1060
-
1061
- {/* Raw context */}
1062
- <div>
1063
- <button
1064
- onClick={() => setShowRaw(!showRaw)}
1065
- className="flex items-center gap-1 text-[10px] text-gray-600 hover:text-gray-400 uppercase"
1066
- >
1067
- Raw context {showRaw ? <ChevronUp className="w-3 h-3" /> : <ChevronDown className="w-3 h-3" />}
1068
- </button>
1069
- {showRaw && result.context && (
1070
- <pre className="mt-2 p-3 bg-white/[0.02] border border-white/5 rounded-lg text-[11px] text-gray-400 overflow-x-auto whitespace-pre-wrap">
1071
- {result.context}
1072
- </pre>
1073
- )}
1074
- </div>
1075
- </>
1076
- )}
1077
- </div>
1078
- );
1079
- }
1080
- ```
1081
-
1082
- - [ ] **Step 2: Commit**
1083
-
1084
- ```bash
1085
- git add src/components/cortex/context-tab.tsx
1086
- git commit -m "feat(cortex): add context assembly inspector tab"
1087
- ```
1088
-
1089
- ---
1090
-
1091
- ## Summary
1092
-
1093
- | Task | Component | Status |
1094
- |------|-----------|--------|
1095
- | 1 | listAllEdges() + edges all=true | |
1096
- | 2 | Context API expansion (entities, conflicts, sourceWeights) | |
1097
- | 3 | Enhanced knowledge card (v2 fields) | |
1098
- | 4 | Sidebar Cortex nav item | |
1099
- | 5 | /cortex page with tabs | |
1100
- | 6 | Panel "Open full view" link | |
1101
- | 7 | Entity graph canvas (force-graph) | |
1102
- | 8 | Entity detail panel | |
1103
- | 9 | Knowledge tab | |
1104
- | 10 | Context assembly tab | |
1105
-
1106
- **Total: 10 tasks, 4 chunks**
1107
-
1108
- **No tests in this plan** — these are UI components that render from existing tested APIs. The backend changes (Tasks 1-2) are trivial additions to already-tested modules.
1
+ # Cortex v2 UI Implementation Plan
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 a dedicated `/cortex` page with interactive entity graph visualization, enhanced knowledge cards with v2 fields, and a context assembly dashboard — plus sidebar navigation and panel enhancements.
6
+
7
+ **Architecture:** New `/app/(desktop)/cortex/page.tsx` with tab navigation (Graph | Knowledge | Context | Settings). Force graph rendered via `force-graph` npm package with `nodeCanvasObject` for custom shapes. Small backend tweaks to expose `listAllEdges()`, entities/conflicts/sourceWeights in context API. Existing right panel gets "Open full view" link.
8
+
9
+ **Tech Stack:** React 19, Next.js 16, Tailwind CSS 4, force-graph, Lucide icons, TanStack React Query
10
+
11
+ **Spec:** `docs/superpowers/specs/2026-03-16-cortex-v2-ui-design.md`
12
+
13
+ ---
14
+
15
+ ## File Structure
16
+
17
+ ```
18
+ New files:
19
+ ├── src/app/(desktop)/cortex/page.tsx — Main /cortex page with tabs
20
+ ├── src/components/cortex/entity-graph.tsx — Force graph canvas (dynamic, ssr:false)
21
+ ├── src/components/cortex/entity-detail.tsx — Right-side entity detail panel
22
+ ├── src/components/cortex/context-tab.tsx — Context assembly inspector tab
23
+ ├── src/components/cortex/knowledge-tab.tsx — Knowledge list tab (reuses cards)
24
+
25
+ Modified files:
26
+ ├── src/components/cortex/knowledge-card.tsx — Add v2 badges + evidence bar
27
+ ├── src/components/cortex/cortex-panel.tsx — Add "Open full view" link
28
+ ├── src/components/layout/sidebar.tsx — Add Cortex nav item
29
+ ├── src/lib/cortex/graph/entity-graph.ts — Add listAllEdges()
30
+ ├── src/app/api/cortex/graph/edges/route.ts — Support all=true
31
+ ├── src/lib/cortex/retrieval/context-engine.ts — Expose sourceWeights
32
+ ├── src/app/api/cortex/context/route.ts — Return entities, conflicts, sourceWeights
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Chunk 1: Backend Tweaks + Enhanced Knowledge Card
38
+
39
+ ### Task 1: Add listAllEdges() and edges `all=true` support
40
+
41
+ **Files:**
42
+ - Modify: `src/lib/cortex/graph/entity-graph.ts`
43
+ - Modify: `src/app/api/cortex/graph/edges/route.ts`
44
+
45
+ - [ ] **Step 1: Add listAllEdges() to EntityGraph**
46
+
47
+ Read `src/lib/cortex/graph/entity-graph.ts`, find the edge methods section, add:
48
+
49
+ ```typescript
50
+ listAllEdges(): Edge[] {
51
+ return (this.db.prepare('SELECT * FROM edges ORDER BY source_id').all() as any[])
52
+ .map(r => this.rowToEdge(r));
53
+ }
54
+ ```
55
+
56
+ - [ ] **Step 2: Update edges route GET handler**
57
+
58
+ Read `src/app/api/cortex/graph/edges/route.ts`. At the top of the GET handler, before the `from`/`to` check, add:
59
+
60
+ ```typescript
61
+ const all = url.searchParams.get('all');
62
+ if (all === 'true') {
63
+ const edges = cortex.graph.listAllEdges();
64
+ return NextResponse.json({ edges });
65
+ }
66
+ ```
67
+
68
+ - [ ] **Step 3: Commit**
69
+
70
+ ```bash
71
+ git add src/lib/cortex/graph/entity-graph.ts src/app/api/cortex/graph/edges/route.ts
72
+ git commit -m "feat(cortex): add listAllEdges() and edges all=true endpoint"
73
+ ```
74
+
75
+ ---
76
+
77
+ ### Task 2: Expose sourceWeights in context API
78
+
79
+ **Files:**
80
+ - Modify: `src/lib/cortex/retrieval/context-engine.ts`
81
+ - Modify: `src/app/api/cortex/context/route.ts`
82
+
83
+ - [ ] **Step 1: Add sourceWeights to AssemblyResult**
84
+
85
+ Read `src/lib/cortex/retrieval/context-engine.ts`. Find the `AssemblyResult` interface and add:
86
+
87
+ ```typescript
88
+ sourceWeights: Array<{ layerKey: string; scopeLevel: string; weight: number }>;
89
+ ```
90
+
91
+ Find the `assemble()` method. After `computeSourceWeights()` is called (the `sources` variable), map it into the result:
92
+
93
+ ```typescript
94
+ // In the return object, add:
95
+ sourceWeights: sources.map(s => ({
96
+ layerKey: s.layerKey,
97
+ scopeLevel: s.layerKey === 'personal' ? 'personal' : s.layerKey.startsWith('workspace') ? 'team' : 'organization',
98
+ weight: s.weight,
99
+ })),
100
+ ```
101
+
102
+ - [ ] **Step 2: Update context route response**
103
+
104
+ Read `src/app/api/cortex/context/route.ts`. In the `NextResponse.json()` call, change:
105
+
106
+ ```typescript
107
+ // From:
108
+ conflicts: result.conflicts.length,
109
+ // To:
110
+ entities: result.entities,
111
+ conflicts: result.conflicts,
112
+ sourceWeights: result.sourceWeights,
113
+ ```
114
+
115
+ - [ ] **Step 3: Commit**
116
+
117
+ ```bash
118
+ git add src/lib/cortex/retrieval/context-engine.ts src/app/api/cortex/context/route.ts
119
+ git commit -m "feat(cortex): expose entities, conflicts, sourceWeights in context API"
120
+ ```
121
+
122
+ ---
123
+
124
+ ### Task 3: Enhanced knowledge card
125
+
126
+ **Files:**
127
+ - Modify: `src/components/cortex/knowledge-card.tsx`
128
+
129
+ - [ ] **Step 1: Read the current knowledge-card.tsx**
130
+
131
+ - [ ] **Step 2: Extend the props interface and add v2 display**
132
+
133
+ Replace the entire file. The changes:
134
+ - Extend `unit` props with optional v2 fields
135
+ - Add sensitivity badge (color-coded)
136
+ - Add scope badge
137
+ - Add attribution row (creator, source, corroborations)
138
+ - Replace confidence bar with evidence bar when available
139
+ - Add conflict indicator
140
+
141
+ ```typescript
142
+ 'use client';
143
+
144
+ import { Trash2, AlertTriangle } from 'lucide-react';
145
+ import { api } from '@/lib/api';
146
+
147
+ const TYPE_COLORS: Record<string, string> = {
148
+ decision: 'bg-blue-500/20 text-blue-400',
149
+ preference: 'bg-pink-500/20 text-pink-400',
150
+ pattern: 'bg-green-500/20 text-green-400',
151
+ error_fix: 'bg-amber-500/20 text-amber-400',
152
+ context: 'bg-gray-500/20 text-gray-400',
153
+ code_pattern: 'bg-cyan-500/20 text-cyan-400',
154
+ command: 'bg-orange-500/20 text-orange-400',
155
+ conversation: 'bg-slate-500/20 text-slate-400',
156
+ summary: 'bg-violet-500/20 text-violet-400',
157
+ };
158
+
159
+ const SENSITIVITY_COLORS: Record<string, string> = {
160
+ public: 'bg-green-500/20 text-green-400',
161
+ internal: 'bg-indigo-500/20 text-indigo-400',
162
+ restricted: 'bg-amber-500/20 text-amber-400',
163
+ confidential: 'bg-red-500/20 text-red-400',
164
+ };
165
+
166
+ interface KnowledgeCardProps {
167
+ unit: {
168
+ id: string;
169
+ text: string;
170
+ type: string;
171
+ confidence: number;
172
+ created: string;
173
+ session_id?: string | null;
174
+ layer: string;
175
+ stale_score?: number;
176
+ // v2 fields
177
+ scope?: { level: string; entity_id: string };
178
+ sensitivity?: string;
179
+ evidence_score?: number;
180
+ corroborations?: number;
181
+ contradiction_refs?: string[];
182
+ origin?: { source_type: string; source_ref: string; creator_entity_id: string };
183
+ };
184
+ onDelete?: (id: string) => void;
185
+ compact?: boolean;
186
+ }
187
+
188
+ export function KnowledgeCard({ unit, onDelete, compact }: KnowledgeCardProps) {
189
+ const colorClass = TYPE_COLORS[unit.type] || TYPE_COLORS.context;
190
+ const age = getRelativeAge(unit.created);
191
+ const hasConflicts = (unit.contradiction_refs?.length ?? 0) > 0;
192
+
193
+ // Use evidence_score if available, else confidence
194
+ const score = unit.evidence_score ?? unit.confidence;
195
+ const scoreLabel = unit.evidence_score != null
196
+ ? `${score.toFixed(2)} evidence`
197
+ : `${Math.round(score * 100)}%`;
198
+
199
+ const handleDelete = async () => {
200
+ await fetch(api(`/api/cortex/knowledge/${unit.id}`), { method: 'DELETE' });
201
+ onDelete?.(unit.id);
202
+ };
203
+
204
+ return (
205
+ <div className="group border border-white/5 rounded-lg p-3 hover:border-white/10 transition-colors">
206
+ {/* Badge row */}
207
+ <div className="flex items-start justify-between gap-2">
208
+ <div className="flex items-center gap-1 flex-wrap">
209
+ <span className={`text-[10px] px-1.5 py-0.5 rounded font-medium ${colorClass}`}>
210
+ {unit.type.replace('_', ' ')}
211
+ </span>
212
+ {unit.sensitivity && (
213
+ <span className={`text-[10px] px-1.5 py-0.5 rounded font-medium ${SENSITIVITY_COLORS[unit.sensitivity] || SENSITIVITY_COLORS.internal}`}>
214
+ {unit.sensitivity}
215
+ </span>
216
+ )}
217
+ {unit.scope && (
218
+ <span className="text-[10px] px-1.5 py-0.5 rounded font-medium bg-purple-500/10 text-purple-400">
219
+ {unit.scope.level}
220
+ </span>
221
+ )}
222
+ {(unit.stale_score ?? 0) > 0.3 && (
223
+ <span className="text-[10px] px-1.5 py-0.5 rounded font-medium bg-amber-500/20 text-amber-400">
224
+ stale
225
+ </span>
226
+ )}
227
+ {hasConflicts && (
228
+ <span className="text-[10px] px-1.5 py-0.5 rounded font-medium bg-amber-500/20 text-amber-400 flex items-center gap-0.5">
229
+ <AlertTriangle className="w-2.5 h-2.5" />
230
+ contested
231
+ </span>
232
+ )}
233
+ </div>
234
+ <div className="flex items-center gap-2 text-[10px] text-gray-500 shrink-0">
235
+ <span>{age}</span>
236
+ {onDelete && (
237
+ <button
238
+ onClick={handleDelete}
239
+ className="opacity-0 group-hover:opacity-100 transition-opacity text-red-400 hover:text-red-300"
240
+ >
241
+ <Trash2 className="w-3 h-3" />
242
+ </button>
243
+ )}
244
+ </div>
245
+ </div>
246
+
247
+ {/* Text */}
248
+ <p className="text-xs text-gray-300 mt-1.5 leading-relaxed line-clamp-3">{unit.text}</p>
249
+
250
+ {/* Attribution row (v2) */}
251
+ {!compact && unit.origin && (
252
+ <div className="flex items-center gap-1.5 mt-1.5 text-[10px] text-gray-500 flex-wrap">
253
+ <span>by {unit.origin.creator_entity_id.replace('person-', '')}</span>
254
+ <span>&middot;</span>
255
+ <span>via {unit.origin.source_type.replace('_', ' ')}</span>
256
+ {(unit.corroborations ?? 0) > 0 && (
257
+ <>
258
+ <span>&middot;</span>
259
+ <span className="text-green-400">{unit.corroborations} corr.</span>
260
+ </>
261
+ )}
262
+ </div>
263
+ )}
264
+
265
+ {/* Evidence/confidence bar */}
266
+ <div className="flex items-center gap-2 mt-2">
267
+ <div className="flex-1 h-1 bg-white/5 rounded-full overflow-hidden">
268
+ <div
269
+ className="h-full bg-purple-500/50 rounded-full"
270
+ style={{ width: `${Math.round(score * 100)}%` }}
271
+ />
272
+ </div>
273
+ <span className="text-[10px] text-gray-500 tabular-nums">{scoreLabel}</span>
274
+ </div>
275
+ </div>
276
+ );
277
+ }
278
+
279
+ function getRelativeAge(iso: string): string {
280
+ const diff = Date.now() - new Date(iso).getTime();
281
+ const days = Math.floor(diff / (1000 * 60 * 60 * 24));
282
+ if (days === 0) return 'today';
283
+ if (days === 1) return '1d ago';
284
+ if (days < 30) return `${days}d ago`;
285
+ if (days < 365) return `${Math.floor(days / 30)}mo ago`;
286
+ return `${Math.floor(days / 365)}y ago`;
287
+ }
288
+ ```
289
+
290
+ - [ ] **Step 3: Commit**
291
+
292
+ ```bash
293
+ git add src/components/cortex/knowledge-card.tsx
294
+ git commit -m "feat(cortex): enhance knowledge card with v2 fields display"
295
+ ```
296
+
297
+ ---
298
+
299
+ ## Chunk 2: Cortex Page + Sidebar
300
+
301
+ ### Task 4: Sidebar navigation
302
+
303
+ **Files:**
304
+ - Modify: `src/components/layout/sidebar.tsx`
305
+
306
+ - [ ] **Step 1: Read sidebar.tsx**
307
+
308
+ - [ ] **Step 2: Add Cortex to nav array and imports**
309
+
310
+ Add `Brain` to the lucide-react import. Add a Cortex entry to the `nav` array (after Network, before Settings):
311
+
312
+ ```typescript
313
+ // Add to imports:
314
+ import { ..., Brain } from 'lucide-react';
315
+
316
+ // Add to nav array (before Settings):
317
+ { href: '/cortex', label: 'Cortex', icon: Brain },
318
+
319
+ // Add to routeNames:
320
+ '/cortex': 'cortex',
321
+ ```
322
+
323
+ In the nav filter, gate it like Network:
324
+ ```typescript
325
+ if (href === '/cortex') return hasCortex;
326
+ ```
327
+
328
+ - [ ] **Step 3: Commit**
329
+
330
+ ```bash
331
+ git add src/components/layout/sidebar.tsx
332
+ git commit -m "feat(cortex): add Cortex nav item to sidebar"
333
+ ```
334
+
335
+ ---
336
+
337
+ ### Task 5: Cortex page with tabs
338
+
339
+ **Files:**
340
+ - Create: `src/app/(desktop)/cortex/page.tsx`
341
+
342
+ - [ ] **Step 1: Create the page**
343
+
344
+ ```typescript
345
+ 'use client';
346
+
347
+ import { useState, useEffect } from 'react';
348
+ import dynamic from 'next/dynamic';
349
+ import { api } from '@/lib/api';
350
+ import { KnowledgeTab } from '@/components/cortex/knowledge-tab';
351
+ import { ContextTab } from '@/components/cortex/context-tab';
352
+ import { CortexSettings } from '@/components/cortex/cortex-settings';
353
+
354
+ const EntityGraphView = dynamic(
355
+ () => import('@/components/cortex/entity-graph').then(m => ({ default: m.EntityGraphView })),
356
+ { ssr: false, loading: () => <div className="flex-1 flex items-center justify-center text-gray-500 text-sm">Loading graph...</div> }
357
+ );
358
+
359
+ type Tab = 'graph' | 'knowledge' | 'context' | 'settings';
360
+
361
+ export default function CortexPage() {
362
+ const [tab, setTab] = useState<Tab>('graph');
363
+ const [stats, setStats] = useState<any>(null);
364
+
365
+ useEffect(() => {
366
+ fetch(api('/api/cortex/status'))
367
+ .then(r => r.json())
368
+ .then(setStats)
369
+ .catch(() => {});
370
+ }, []);
371
+
372
+ const tabs: { key: Tab; label: string }[] = [
373
+ { key: 'graph', label: 'Graph' },
374
+ { key: 'knowledge', label: 'Knowledge' },
375
+ { key: 'context', label: 'Context' },
376
+ { key: 'settings', label: 'Settings' },
377
+ ];
378
+
379
+ const totalKnowledge = stats
380
+ ? Object.values(stats.layers || {}).reduce((sum: number, l: any) => sum + (l.count || 0), 0)
381
+ : 0;
382
+
383
+ return (
384
+ <div className="flex flex-col h-screen bg-gray-950">
385
+ {/* Tab bar */}
386
+ <div className="flex items-center border-b border-white/5 px-4 shrink-0">
387
+ <div className="flex">
388
+ {tabs.map(t => (
389
+ <button
390
+ key={t.key}
391
+ onClick={() => setTab(t.key)}
392
+ className={`px-5 py-3 text-sm font-medium transition-colors border-b-2 ${
393
+ tab === t.key
394
+ ? 'text-purple-400 border-purple-400'
395
+ : 'text-gray-500 border-transparent hover:text-gray-300'
396
+ }`}
397
+ >
398
+ {t.label}
399
+ </button>
400
+ ))}
401
+ </div>
402
+ <div className="ml-auto text-xs text-gray-600">
403
+ {totalKnowledge} knowledge units
404
+ </div>
405
+ </div>
406
+
407
+ {/* Tab content */}
408
+ <div className="flex-1 overflow-hidden">
409
+ {tab === 'graph' && <EntityGraphView />}
410
+ {tab === 'knowledge' && <KnowledgeTab />}
411
+ {tab === 'context' && <ContextTab />}
412
+ {tab === 'settings' && (
413
+ <div className="p-6 max-w-2xl">
414
+ <CortexSettings />
415
+ </div>
416
+ )}
417
+ </div>
418
+ </div>
419
+ );
420
+ }
421
+ ```
422
+
423
+ - [ ] **Step 2: Commit**
424
+
425
+ ```bash
426
+ git add src/app/(desktop)/cortex/page.tsx
427
+ git commit -m "feat(cortex): add /cortex page with tab navigation"
428
+ ```
429
+
430
+ ---
431
+
432
+ ### Task 6: Panel "Open full view" link
433
+
434
+ **Files:**
435
+ - Modify: `src/components/cortex/cortex-panel.tsx`
436
+
437
+ - [ ] **Step 1: Add link to panel header**
438
+
439
+ Read `src/components/cortex/cortex-panel.tsx`. In the header div (between the "Cortex" heading and the close button), add:
440
+
441
+ ```typescript
442
+ import Link from 'next/link';
443
+ import { ExternalLink } from 'lucide-react';
444
+
445
+ // In the header, after the h2:
446
+ <Link
447
+ href="/cortex"
448
+ className="text-[10px] text-purple-400 hover:text-purple-300 flex items-center gap-1"
449
+ onClick={onClose}
450
+ >
451
+ Full view <ExternalLink className="w-2.5 h-2.5" />
452
+ </Link>
453
+ ```
454
+
455
+ - [ ] **Step 2: Commit**
456
+
457
+ ```bash
458
+ git add src/components/cortex/cortex-panel.tsx
459
+ git commit -m "feat(cortex): add 'Full view' link to cortex panel"
460
+ ```
461
+
462
+ ---
463
+
464
+ ## Chunk 3: Graph + Detail Components
465
+
466
+ ### Task 7: Entity graph canvas component
467
+
468
+ **Files:**
469
+ - Create: `src/components/cortex/entity-graph.tsx`
470
+
471
+ - [ ] **Step 1: Install force-graph**
472
+
473
+ ```bash
474
+ npm install force-graph
475
+ ```
476
+
477
+ - [ ] **Step 2: Create the graph component**
478
+
479
+ ```typescript
480
+ 'use client';
481
+
482
+ import { useEffect, useRef, useState, useCallback } from 'react';
483
+ import ForceGraph2D from 'force-graph';
484
+ import { api } from '@/lib/api';
485
+ import { EntityDetail } from './entity-detail';
486
+
487
+ const NODE_COLORS: Record<string, string> = {
488
+ person: '#7c3aed',
489
+ team: '#10b981',
490
+ project: '#10b981',
491
+ department: '#3b82f6',
492
+ organization: '#3b82f6',
493
+ system: '#f59e0b',
494
+ module: '#f59e0b',
495
+ topic: '#06b6d4',
496
+ };
497
+
498
+ interface GraphNode {
499
+ id: string;
500
+ name: string;
501
+ type: string;
502
+ metadata: Record<string, unknown>;
503
+ // force-graph adds x, y, vx, vy
504
+ x?: number;
505
+ y?: number;
506
+ }
507
+
508
+ interface GraphLink {
509
+ source: string;
510
+ target: string;
511
+ relation: string;
512
+ weight: number;
513
+ }
514
+
515
+ export function EntityGraphView() {
516
+ const containerRef = useRef<HTMLDivElement>(null);
517
+ const graphRef = useRef<any>(null);
518
+ const [selectedNode, setSelectedNode] = useState<GraphNode | null>(null);
519
+ const [graphData, setGraphData] = useState<{ nodes: GraphNode[]; links: GraphLink[] }>({ nodes: [], links: [] });
520
+
521
+ // Fetch graph data
522
+ useEffect(() => {
523
+ Promise.all([
524
+ fetch(api('/api/cortex/graph/entities')).then(r => r.json()),
525
+ fetch(api('/api/cortex/graph/edges?all=true')).then(r => r.json()),
526
+ ]).then(([entData, edgeData]) => {
527
+ const nodes: GraphNode[] = (entData.entities || []).map((e: any) => ({
528
+ id: e.id,
529
+ name: e.name,
530
+ type: e.type,
531
+ metadata: e.metadata || {},
532
+ }));
533
+ const nodeIds = new Set(nodes.map(n => n.id));
534
+ const links: GraphLink[] = (edgeData.edges || [])
535
+ .filter((e: any) => nodeIds.has(e.source_id) && nodeIds.has(e.target_id))
536
+ .map((e: any) => ({
537
+ source: e.source_id,
538
+ target: e.target_id,
539
+ relation: e.relation,
540
+ weight: e.weight,
541
+ }));
542
+ setGraphData({ nodes, links });
543
+ }).catch(() => {});
544
+ }, []);
545
+
546
+ // Initialize force-graph
547
+ useEffect(() => {
548
+ if (!containerRef.current || graphData.nodes.length === 0) return;
549
+
550
+ const width = containerRef.current.clientWidth;
551
+ const height = containerRef.current.clientHeight;
552
+
553
+ const graph = ForceGraph2D()(containerRef.current)
554
+ .width(width)
555
+ .height(height)
556
+ .graphData(graphData)
557
+ .nodeId('id')
558
+ .nodeLabel((node: any) => `${node.name} (${node.type})`)
559
+ .nodeCanvasObject((node: any, ctx: CanvasRenderingContext2D, globalScale: number) => {
560
+ const color = NODE_COLORS[node.type] || '#666';
561
+ const size = node.type === 'person' ? 8 : node.type === 'topic' ? 5 : 6;
562
+ const x = node.x ?? 0;
563
+ const y = node.y ?? 0;
564
+
565
+ ctx.beginPath();
566
+ if (node.type === 'system' || node.type === 'module') {
567
+ // Diamond
568
+ ctx.moveTo(x, y - size);
569
+ ctx.lineTo(x + size, y);
570
+ ctx.lineTo(x, y + size);
571
+ ctx.lineTo(x - size, y);
572
+ ctx.closePath();
573
+ } else if (node.type === 'team' || node.type === 'project' || node.type === 'department' || node.type === 'organization') {
574
+ // Rounded rect
575
+ const w = size * 2;
576
+ const h = size * 1.5;
577
+ const r = 2;
578
+ ctx.roundRect(x - w / 2, y - h / 2, w, h, r);
579
+ } else {
580
+ // Circle (person, topic)
581
+ ctx.arc(x, y, size, 0, 2 * Math.PI);
582
+ }
583
+
584
+ ctx.fillStyle = color + '33';
585
+ ctx.fill();
586
+ ctx.strokeStyle = color;
587
+ ctx.lineWidth = 1.5 / globalScale;
588
+ ctx.stroke();
589
+
590
+ // Label
591
+ const fontSize = Math.max(10 / globalScale, 3);
592
+ ctx.font = `${fontSize}px sans-serif`;
593
+ ctx.textAlign = 'center';
594
+ ctx.textBaseline = 'middle';
595
+ ctx.fillStyle = color;
596
+ ctx.fillText(node.name, x, y + size + fontSize);
597
+ })
598
+ .nodePointerAreaPaint((node: any, color: string, ctx: CanvasRenderingContext2D) => {
599
+ const size = 10;
600
+ ctx.fillStyle = color;
601
+ ctx.beginPath();
602
+ ctx.arc(node.x ?? 0, node.y ?? 0, size, 0, 2 * Math.PI);
603
+ ctx.fill();
604
+ })
605
+ .linkColor(() => 'rgba(124, 58, 237, 0.2)')
606
+ .linkWidth((link: any) => Math.max(0.5, link.weight * 2))
607
+ .onNodeClick((node: any) => setSelectedNode(node))
608
+ .onBackgroundClick(() => setSelectedNode(null))
609
+ .backgroundColor('#06060c');
610
+
611
+ graphRef.current = graph;
612
+
613
+ const handleResize = () => {
614
+ if (!containerRef.current) return;
615
+ graph.width(containerRef.current.clientWidth);
616
+ graph.height(containerRef.current.clientHeight);
617
+ };
618
+ window.addEventListener('resize', handleResize);
619
+
620
+ return () => {
621
+ window.removeEventListener('resize', handleResize);
622
+ graph._destructor?.();
623
+ };
624
+ }, [graphData]);
625
+
626
+ const handleRecenter = useCallback(() => {
627
+ graphRef.current?.zoomToFit(400, 40);
628
+ }, []);
629
+
630
+ return (
631
+ <div className="flex h-full">
632
+ {/* Graph canvas */}
633
+ <div className="flex-1 relative">
634
+ <div ref={containerRef} className="w-full h-full" />
635
+
636
+ {/* Controls overlay */}
637
+ <div className="absolute bottom-3 left-3 flex gap-2">
638
+ <button
639
+ onClick={handleRecenter}
640
+ className="px-3 py-1.5 text-xs bg-gray-900/80 border border-white/10 rounded text-gray-400 hover:text-gray-200"
641
+ >
642
+ Recenter
643
+ </button>
644
+ </div>
645
+
646
+ {/* Legend overlay */}
647
+ <div className="absolute top-3 right-3 bg-gray-950/90 border border-white/10 rounded-lg p-3 text-[10px] space-y-1">
648
+ {Object.entries(NODE_COLORS).filter(([type]) =>
649
+ ['person', 'team', 'system', 'topic'].includes(type)
650
+ ).map(([type, color]) => (
651
+ <div key={type} className="flex items-center gap-2">
652
+ <span style={{ color }} className="text-sm">
653
+ {type === 'system' ? '◆' : type === 'team' ? '■' : '●'}
654
+ </span>
655
+ <span className="text-gray-400 capitalize">{type}</span>
656
+ </div>
657
+ ))}
658
+ </div>
659
+
660
+ {graphData.nodes.length === 0 && (
661
+ <div className="absolute inset-0 flex items-center justify-center text-gray-600 text-sm">
662
+ No entities yet. Add entities via the API to see the graph.
663
+ </div>
664
+ )}
665
+ </div>
666
+
667
+ {/* Detail panel */}
668
+ <div className="w-72 border-l border-white/5 bg-gray-950 overflow-y-auto">
669
+ <EntityDetail
670
+ node={selectedNode}
671
+ onClose={() => setSelectedNode(null)}
672
+ />
673
+ </div>
674
+ </div>
675
+ );
676
+ }
677
+ ```
678
+
679
+ - [ ] **Step 3: Commit**
680
+
681
+ ```bash
682
+ git add src/components/cortex/entity-graph.tsx
683
+ git commit -m "feat(cortex): add force-graph entity visualization component"
684
+ ```
685
+
686
+ ---
687
+
688
+ ### Task 8: Entity detail panel
689
+
690
+ **Files:**
691
+ - Create: `src/components/cortex/entity-detail.tsx`
692
+
693
+ - [ ] **Step 1: Create the component**
694
+
695
+ ```typescript
696
+ 'use client';
697
+
698
+ import { useState, useEffect } from 'react';
699
+ import { api } from '@/lib/api';
700
+
701
+ const RELATION_COLORS: Record<string, string> = {
702
+ member_of: 'text-purple-400',
703
+ expert_in: 'text-cyan-400',
704
+ owns: 'text-green-400',
705
+ contains: 'text-green-400',
706
+ part_of: 'text-blue-400',
707
+ works_on: 'text-purple-400',
708
+ touches: 'text-amber-400',
709
+ depends_on: 'text-red-400',
710
+ relates_to: 'text-cyan-400',
711
+ };
712
+
713
+ interface EntityDetailProps {
714
+ node: { id: string; name: string; type: string; metadata: Record<string, unknown> } | null;
715
+ onClose: () => void;
716
+ }
717
+
718
+ export function EntityDetail({ node, onClose }: EntityDetailProps) {
719
+ const [edges, setEdges] = useState<any[]>([]);
720
+
721
+ useEffect(() => {
722
+ if (!node) { setEdges([]); return; }
723
+
724
+ Promise.all([
725
+ fetch(api(`/api/cortex/graph/edges?from=${node.id}`)).then(r => r.json()),
726
+ fetch(api(`/api/cortex/graph/edges?to=${node.id}`)).then(r => r.json()),
727
+ ]).then(([fromData, toData]) => {
728
+ const allEdges = [
729
+ ...(fromData.edges || []).map((e: any) => ({ ...e, direction: 'out' })),
730
+ ...(toData.edges || []).map((e: any) => ({ ...e, direction: 'in' })),
731
+ ];
732
+ setEdges(allEdges);
733
+ }).catch(() => {});
734
+ }, [node?.id]);
735
+
736
+ if (!node) {
737
+ return (
738
+ <div className="p-4 text-center text-gray-600 text-xs mt-8">
739
+ Click a node to see details
740
+ </div>
741
+ );
742
+ }
743
+
744
+ const firstLetter = node.name.charAt(0).toUpperCase();
745
+ const color = node.type === 'person' ? '#7c3aed'
746
+ : node.type === 'system' ? '#f59e0b'
747
+ : node.type === 'topic' ? '#06b6d4'
748
+ : '#10b981';
749
+
750
+ return (
751
+ <div className="p-4">
752
+ {/* Header */}
753
+ <div className="flex items-center gap-3 mb-4">
754
+ <div
755
+ className="w-8 h-8 rounded-full flex items-center justify-center text-sm font-bold"
756
+ style={{ backgroundColor: color + '33', color, border: `2px solid ${color}` }}
757
+ >
758
+ {firstLetter}
759
+ </div>
760
+ <div>
761
+ <div className="text-sm font-medium text-gray-200">{node.name}</div>
762
+ <div className="text-[10px] text-gray-500">{node.type}</div>
763
+ </div>
764
+ </div>
765
+
766
+ {/* Metadata */}
767
+ {Object.keys(node.metadata).length > 0 && (
768
+ <div className="mb-4">
769
+ <div className="text-[10px] text-gray-600 uppercase tracking-wider mb-1">Metadata</div>
770
+ {Object.entries(node.metadata).map(([k, v]) => (
771
+ <div key={k} className="text-[11px] text-gray-400">
772
+ <span className="text-gray-600">{k}:</span> {String(v)}
773
+ </div>
774
+ ))}
775
+ </div>
776
+ )}
777
+
778
+ {/* Relationships */}
779
+ <div className="text-[10px] text-gray-600 uppercase tracking-wider mb-2">
780
+ Relationships ({edges.length})
781
+ </div>
782
+ <div className="space-y-1 mb-4">
783
+ {edges.map((e, i) => {
784
+ const relColor = RELATION_COLORS[e.relation] || 'text-gray-400';
785
+ const target = e.direction === 'out' ? e.target_id : e.source_id;
786
+ const arrow = e.direction === 'out' ? '→' : '←';
787
+ return (
788
+ <div key={i} className="flex items-center gap-1.5 text-[11px] bg-white/[0.02] rounded px-2 py-1.5">
789
+ <span className={relColor}>{e.relation}</span>
790
+ <span className="text-gray-600">{arrow}</span>
791
+ <span className="text-gray-300 truncate">{target.replace(/^(person|team|system|topic|project|department|organization|module)-/, '')}</span>
792
+ {e.weight < 1 && (
793
+ <span className="text-gray-600 ml-auto text-[9px]">{e.weight.toFixed(2)}</span>
794
+ )}
795
+ </div>
796
+ );
797
+ })}
798
+ {edges.length === 0 && (
799
+ <div className="text-[11px] text-gray-600 py-2">No relationships</div>
800
+ )}
801
+ </div>
802
+ </div>
803
+ );
804
+ }
805
+ ```
806
+
807
+ - [ ] **Step 2: Commit**
808
+
809
+ ```bash
810
+ git add src/components/cortex/entity-detail.tsx
811
+ git commit -m "feat(cortex): add entity detail panel for graph view"
812
+ ```
813
+
814
+ ---
815
+
816
+ ## Chunk 4: Knowledge Tab, Context Tab, Final Wiring
817
+
818
+ ### Task 9: Knowledge tab component
819
+
820
+ **Files:**
821
+ - Create: `src/components/cortex/knowledge-tab.tsx`
822
+
823
+ - [ ] **Step 1: Create the component**
824
+
825
+ A search + list view that reuses `KnowledgeCard`. Fetches from `/api/cortex/search`.
826
+
827
+ ```typescript
828
+ 'use client';
829
+
830
+ import { useState, useCallback, useEffect } from 'react';
831
+ import { Search } from 'lucide-react';
832
+ import { api } from '@/lib/api';
833
+ import { KnowledgeCard } from './knowledge-card';
834
+
835
+ export function KnowledgeTab() {
836
+ const [query, setQuery] = useState('');
837
+ const [results, setResults] = useState<any[]>([]);
838
+ const [loading, setLoading] = useState(false);
839
+
840
+ const fetchResults = useCallback(async (q?: string) => {
841
+ setLoading(true);
842
+ try {
843
+ const params = new URLSearchParams({ limit: '30' });
844
+ if (q) params.set('q', q);
845
+ const res = await fetch(api(`/api/cortex/search?${params}`));
846
+ if (res.ok) setResults((await res.json()).results || []);
847
+ } catch {}
848
+ setLoading(false);
849
+ }, []);
850
+
851
+ useEffect(() => { fetchResults(); }, [fetchResults]);
852
+
853
+ const handleSearch = () => fetchResults(query.trim() || undefined);
854
+ const handleDelete = (id: string) => setResults(prev => prev.filter(r => r.id !== id));
855
+
856
+ return (
857
+ <div className="flex flex-col h-full">
858
+ <div className="p-4 border-b border-white/5">
859
+ <div className="relative max-w-md">
860
+ <Search className="absolute left-3 top-2.5 w-4 h-4 text-gray-500" />
861
+ <input
862
+ value={query}
863
+ onChange={e => setQuery(e.target.value)}
864
+ onKeyDown={e => e.key === 'Enter' && handleSearch()}
865
+ placeholder="Search knowledge..."
866
+ className="w-full pl-9 pr-4 py-2 text-sm bg-white/5 border border-white/10 rounded-lg text-gray-300 placeholder-gray-600 focus:outline-none focus:border-purple-500/50"
867
+ />
868
+ </div>
869
+ </div>
870
+ <div className="flex-1 overflow-y-auto p-4">
871
+ <div className="max-w-2xl space-y-2">
872
+ {loading && <p className="text-sm text-gray-500 text-center py-8">Loading...</p>}
873
+ {!loading && results.length === 0 && (
874
+ <p className="text-sm text-gray-500 text-center py-8">No knowledge found</p>
875
+ )}
876
+ {results.map(unit => (
877
+ <KnowledgeCard key={unit.id} unit={unit} onDelete={handleDelete} />
878
+ ))}
879
+ </div>
880
+ </div>
881
+ </div>
882
+ );
883
+ }
884
+ ```
885
+
886
+ - [ ] **Step 2: Commit**
887
+
888
+ ```bash
889
+ git add src/components/cortex/knowledge-tab.tsx
890
+ git commit -m "feat(cortex): add knowledge tab with search and v2 cards"
891
+ ```
892
+
893
+ ---
894
+
895
+ ### Task 10: Context assembly tab
896
+
897
+ **Files:**
898
+ - Create: `src/components/cortex/context-tab.tsx`
899
+
900
+ - [ ] **Step 1: Create the component**
901
+
902
+ ```typescript
903
+ 'use client';
904
+
905
+ import { useState } from 'react';
906
+ import { Search, ChevronDown, ChevronUp } from 'lucide-react';
907
+ import { api } from '@/lib/api';
908
+
909
+ const INTENT_COLORS: Record<string, string> = {
910
+ debugging: 'text-red-400',
911
+ architecture: 'text-blue-400',
912
+ onboarding: 'text-green-400',
913
+ policy: 'text-purple-400',
914
+ 'how-to': 'text-amber-400',
915
+ review: 'text-pink-400',
916
+ security: 'text-red-500',
917
+ general: 'text-gray-400',
918
+ };
919
+
920
+ export function ContextTab() {
921
+ const [query, setQuery] = useState('');
922
+ const [result, setResult] = useState<any>(null);
923
+ const [loading, setLoading] = useState(false);
924
+ const [showRaw, setShowRaw] = useState(false);
925
+
926
+ const handleAnalyze = async () => {
927
+ if (!query.trim()) return;
928
+ setLoading(true);
929
+ try {
930
+ const res = await fetch(api(`/api/cortex/context?q=${encodeURIComponent(query)}&limit=5`));
931
+ if (res.ok) setResult(await res.json());
932
+ } catch {}
933
+ setLoading(false);
934
+ };
935
+
936
+ return (
937
+ <div className="p-6 max-w-3xl mx-auto">
938
+ {/* Query input */}
939
+ <div className="flex gap-3 mb-6">
940
+ <div className="flex-1 relative">
941
+ <Search className="absolute left-3 top-2.5 w-4 h-4 text-gray-500" />
942
+ <input
943
+ value={query}
944
+ onChange={e => setQuery(e.target.value)}
945
+ onKeyDown={e => e.key === 'Enter' && handleAnalyze()}
946
+ placeholder="Enter a query to analyze..."
947
+ className="w-full pl-9 pr-4 py-2 text-sm bg-white/5 border border-white/10 rounded-lg text-gray-300 placeholder-gray-600 focus:outline-none focus:border-purple-500/50"
948
+ />
949
+ </div>
950
+ <button
951
+ onClick={handleAnalyze}
952
+ disabled={loading}
953
+ className="px-5 py-2 text-sm bg-purple-600 hover:bg-purple-500 text-white rounded-lg disabled:opacity-50"
954
+ >
955
+ {loading ? 'Analyzing...' : 'Analyze'}
956
+ </button>
957
+ </div>
958
+
959
+ {!result && !loading && (
960
+ <p className="text-sm text-gray-600 text-center py-12">
961
+ Enter a query to see how the Context Assembly Engine processes it
962
+ </p>
963
+ )}
964
+
965
+ {result && (
966
+ <>
967
+ {/* Pipeline summary */}
968
+ <div className="grid grid-cols-3 gap-3 mb-6">
969
+ <div className="bg-white/[0.02] border border-white/5 rounded-lg p-3">
970
+ <div className="text-[10px] text-gray-600 uppercase mb-1">Intent</div>
971
+ <div className={`text-lg font-semibold ${INTENT_COLORS[result.intent?.intent] || 'text-gray-400'}`}>
972
+ {result.intent?.intent || '?'}
973
+ </div>
974
+ <div className="text-[10px] text-gray-600">
975
+ confidence: {(result.intent?.confidence ?? 0).toFixed(2)}
976
+ </div>
977
+ </div>
978
+ <div className="bg-white/[0.02] border border-white/5 rounded-lg p-3">
979
+ <div className="text-[10px] text-gray-600 uppercase mb-1">Entities</div>
980
+ <div className="flex flex-wrap gap-1 mt-1">
981
+ {(result.entities || []).map((e: any, i: number) => (
982
+ <span key={i} className="text-[10px] px-1.5 py-0.5 bg-white/5 border border-white/10 rounded text-gray-300">
983
+ {e.entity?.type}:{e.entity?.name}
984
+ </span>
985
+ ))}
986
+ {(!result.entities || result.entities.length === 0) && (
987
+ <span className="text-[10px] text-gray-600">none detected</span>
988
+ )}
989
+ </div>
990
+ </div>
991
+ <div className="bg-white/[0.02] border border-white/5 rounded-lg p-3">
992
+ <div className="text-[10px] text-gray-600 uppercase mb-1">Timing</div>
993
+ <div className="text-lg font-semibold text-green-400">
994
+ {result.timing?.totalMs ?? '?'}ms
995
+ </div>
996
+ <div className="text-[10px] text-gray-600">
997
+ intent {result.timing?.intentMs}ms · search {result.timing?.searchMs}ms
998
+ </div>
999
+ </div>
1000
+ </div>
1001
+
1002
+ {/* Source weights */}
1003
+ {result.sourceWeights && (
1004
+ <div className="mb-6">
1005
+ <div className="text-[10px] text-gray-600 uppercase mb-2">Source Weights</div>
1006
+ <div className="flex gap-3">
1007
+ {result.sourceWeights.map((sw: any, i: number) => (
1008
+ <div key={i} className="flex-1 bg-white/[0.02] rounded-lg p-3">
1009
+ <div className="flex justify-between text-[11px] mb-1">
1010
+ <span className="text-gray-300 capitalize">{sw.scopeLevel}</span>
1011
+ <span className="text-gray-500">{sw.weight.toFixed(2)}</span>
1012
+ </div>
1013
+ <div className="h-1.5 bg-white/5 rounded-full overflow-hidden">
1014
+ <div
1015
+ className="h-full bg-purple-500/60 rounded-full"
1016
+ style={{ width: `${Math.min(100, sw.weight * 100)}%` }}
1017
+ />
1018
+ </div>
1019
+ </div>
1020
+ ))}
1021
+ </div>
1022
+ </div>
1023
+ )}
1024
+
1025
+ {/* Results */}
1026
+ <div className="mb-6">
1027
+ <div className="text-[10px] text-gray-600 uppercase mb-2">
1028
+ Results ({(result.results || []).length})
1029
+ </div>
1030
+ <div className="space-y-1">
1031
+ {(result.results || []).map((r: any, i: number) => (
1032
+ <div key={i} className="flex items-center gap-2 bg-white/[0.02] border border-white/5 rounded-lg px-3 py-2">
1033
+ <span className={`text-[10px] px-1.5 py-0.5 rounded font-medium ${
1034
+ r.type === 'error_fix' ? 'bg-amber-500/20 text-amber-400'
1035
+ : r.type === 'decision' ? 'bg-blue-500/20 text-blue-400'
1036
+ : 'bg-gray-500/20 text-gray-400'
1037
+ }`}>{r.type?.replace('_', ' ')}</span>
1038
+ <span className="text-xs text-gray-300 truncate flex-1">{r.text}</span>
1039
+ <span className="text-[10px] text-gray-600 tabular-nums shrink-0">
1040
+ {(r.relevance_score ?? 0).toFixed(3)}
1041
+ </span>
1042
+ </div>
1043
+ ))}
1044
+ </div>
1045
+ </div>
1046
+
1047
+ {/* Conflicts */}
1048
+ {Array.isArray(result.conflicts) && result.conflicts.length > 0 && (
1049
+ <div className="mb-6 border border-amber-500/20 bg-amber-500/5 rounded-lg p-3">
1050
+ <div className="text-[10px] text-amber-400 uppercase font-medium mb-1">
1051
+ Conflicts ({result.conflicts.length})
1052
+ </div>
1053
+ {result.conflicts.map((c: any, i: number) => (
1054
+ <div key={i} className="text-xs text-gray-400 mt-1">
1055
+ &ldquo;{c.unitA?.text?.slice(0, 60)}...&rdquo; vs &ldquo;{c.unitB?.text?.slice(0, 60)}...&rdquo;
1056
+ </div>
1057
+ ))}
1058
+ </div>
1059
+ )}
1060
+
1061
+ {/* Raw context */}
1062
+ <div>
1063
+ <button
1064
+ onClick={() => setShowRaw(!showRaw)}
1065
+ className="flex items-center gap-1 text-[10px] text-gray-600 hover:text-gray-400 uppercase"
1066
+ >
1067
+ Raw context {showRaw ? <ChevronUp className="w-3 h-3" /> : <ChevronDown className="w-3 h-3" />}
1068
+ </button>
1069
+ {showRaw && result.context && (
1070
+ <pre className="mt-2 p-3 bg-white/[0.02] border border-white/5 rounded-lg text-[11px] text-gray-400 overflow-x-auto whitespace-pre-wrap">
1071
+ {result.context}
1072
+ </pre>
1073
+ )}
1074
+ </div>
1075
+ </>
1076
+ )}
1077
+ </div>
1078
+ );
1079
+ }
1080
+ ```
1081
+
1082
+ - [ ] **Step 2: Commit**
1083
+
1084
+ ```bash
1085
+ git add src/components/cortex/context-tab.tsx
1086
+ git commit -m "feat(cortex): add context assembly inspector tab"
1087
+ ```
1088
+
1089
+ ---
1090
+
1091
+ ## Summary
1092
+
1093
+ | Task | Component | Status |
1094
+ |------|-----------|--------|
1095
+ | 1 | listAllEdges() + edges all=true | |
1096
+ | 2 | Context API expansion (entities, conflicts, sourceWeights) | |
1097
+ | 3 | Enhanced knowledge card (v2 fields) | |
1098
+ | 4 | Sidebar Cortex nav item | |
1099
+ | 5 | /cortex page with tabs | |
1100
+ | 6 | Panel "Open full view" link | |
1101
+ | 7 | Entity graph canvas (force-graph) | |
1102
+ | 8 | Entity detail panel | |
1103
+ | 9 | Knowledge tab | |
1104
+ | 10 | Context assembly tab | |
1105
+
1106
+ **Total: 10 tasks, 4 chunks**
1107
+
1108
+ **No tests in this plan** — these are UI components that render from existing tested APIs. The backend changes (Tasks 1-2) are trivial additions to already-tested modules.