@jlongo78/agent-spaces 0.7.5 → 0.7.7

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 (634) hide show
  1. package/.next/standalone/.claude/settings.local.json +55 -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 +2 -1
  5. package/.next/standalone/.next/build-manifest.json +5 -5
  6. package/.next/standalone/.next/prerender-manifest.json +27 -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/build-manifest.json +3 -3
  10. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/(desktop)/admin/users/page/build-manifest.json +3 -3
  12. package/.next/standalone/.next/server/app/(desktop)/admin/users/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/(desktop)/analytics/page/build-manifest.json +3 -3
  14. package/.next/standalone/.next/server/app/(desktop)/analytics/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/(desktop)/cortex/page/build-manifest.json +3 -3
  16. package/.next/standalone/.next/server/app/(desktop)/cortex/page/react-loadable-manifest.json +3 -3
  17. package/.next/standalone/.next/server/app/(desktop)/cortex/page.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/(desktop)/cortex/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/(desktop)/network/page/build-manifest.json +3 -3
  20. package/.next/standalone/.next/server/app/(desktop)/network/page_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/(desktop)/page/build-manifest.json +3 -3
  22. package/.next/standalone/.next/server/app/(desktop)/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/(desktop)/projects/page/build-manifest.json +3 -3
  24. package/.next/standalone/.next/server/app/(desktop)/projects/page_client-reference-manifest.js +1 -1
  25. package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page/build-manifest.json +3 -3
  26. package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app/(desktop)/sessions/page/build-manifest.json +3 -3
  28. package/.next/standalone/.next/server/app/(desktop)/sessions/page_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/(desktop)/settings/page/build-manifest.json +3 -3
  30. package/.next/standalone/.next/server/app/(desktop)/settings/page_client-reference-manifest.js +1 -1
  31. package/.next/standalone/.next/server/app/(desktop)/terminal/page/build-manifest.json +3 -3
  32. package/.next/standalone/.next/server/app/(desktop)/terminal/page.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/(desktop)/terminal/page_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page/build-manifest.json +3 -3
  35. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page/build-manifest.json +3 -3
  38. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/(desktop)/workspaces/page/build-manifest.json +3 -3
  41. package/.next/standalone/.next/server/app/(desktop)/workspaces/page_client-reference-manifest.js +1 -1
  42. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  43. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  44. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  45. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  46. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  47. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  48. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  49. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  50. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  51. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  53. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  54. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  55. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  56. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  57. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  58. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  59. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  60. package/.next/standalone/.next/server/app/admin/analytics.html +1 -1
  61. package/.next/standalone/.next/server/app/admin/analytics.rsc +7 -6
  62. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics/__PAGE__.segment.rsc +2 -2
  63. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics.segment.rsc +1 -1
  64. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  65. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  66. package/.next/standalone/.next/server/app/admin/analytics.segments/_full.segment.rsc +7 -6
  67. package/.next/standalone/.next/server/app/admin/analytics.segments/_head.segment.rsc +1 -1
  68. package/.next/standalone/.next/server/app/admin/analytics.segments/_index.segment.rsc +2 -2
  69. package/.next/standalone/.next/server/app/admin/analytics.segments/_tree.segment.rsc +2 -2
  70. package/.next/standalone/.next/server/app/admin/users.html +1 -1
  71. package/.next/standalone/.next/server/app/admin/users.rsc +2 -2
  72. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users/__PAGE__.segment.rsc +1 -1
  73. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users.segment.rsc +1 -1
  74. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  75. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  76. package/.next/standalone/.next/server/app/admin/users.segments/_full.segment.rsc +2 -2
  77. package/.next/standalone/.next/server/app/admin/users.segments/_head.segment.rsc +1 -1
  78. package/.next/standalone/.next/server/app/admin/users.segments/_index.segment.rsc +2 -2
  79. package/.next/standalone/.next/server/app/admin/users.segments/_tree.segment.rsc +2 -2
  80. package/.next/standalone/.next/server/app/analytics.html +1 -1
  81. package/.next/standalone/.next/server/app/analytics.rsc +3 -3
  82. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics/__PAGE__.segment.rsc +2 -2
  83. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics.segment.rsc +1 -1
  84. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  85. package/.next/standalone/.next/server/app/analytics.segments/_full.segment.rsc +3 -3
  86. package/.next/standalone/.next/server/app/analytics.segments/_head.segment.rsc +1 -1
  87. package/.next/standalone/.next/server/app/analytics.segments/_index.segment.rsc +2 -2
  88. package/.next/standalone/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
  89. package/.next/standalone/.next/server/app/api/analytics/overview/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/bulk/route.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/cortex/context/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/cortex/curation/assess/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/cortex/curation/publish/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/cortex/curation/refine/route.js.nft.json +1 -1
  96. package/.next/standalone/.next/server/app/api/cortex/curation/review/route.js.nft.json +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.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/cortex/federation/pending/route.js.nft.json +1 -1
  100. package/.next/standalone/.next/server/app/api/cortex/federation/resolve/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/cortex/federation/search/route.js.nft.json +1 -1
  102. package/.next/standalone/.next/server/app/api/cortex/federation/teach/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/cortex/graph/edges/route.js.nft.json +1 -1
  104. package/.next/standalone/.next/server/app/api/cortex/graph/entities/[id]/route.js.nft.json +1 -1
  105. package/.next/standalone/.next/server/app/api/cortex/graph/entities/route.js.nft.json +1 -1
  106. package/.next/standalone/.next/server/app/api/cortex/graph/populate/route.js.nft.json +1 -1
  107. package/.next/standalone/.next/server/app/api/cortex/import/route.js.nft.json +1 -1
  108. package/.next/standalone/.next/server/app/api/cortex/import/status/route.js.nft.json +1 -1
  109. package/.next/standalone/.next/server/app/api/cortex/ingest/bootstrap/route.js.nft.json +1 -1
  110. package/.next/standalone/.next/server/app/api/cortex/ingest/status/route.js.nft.json +1 -1
  111. package/.next/standalone/.next/server/app/api/cortex/knowledge/[id]/route.js.nft.json +1 -1
  112. package/.next/standalone/.next/server/app/api/cortex/knowledge/route.js.nft.json +1 -1
  113. package/.next/standalone/.next/server/app/api/cortex/lobes/[id]/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/cortex/lobes/route.js.nft.json +1 -1
  115. package/.next/standalone/.next/server/app/api/cortex/lobes/share/route.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/api/cortex/marketplace/browse/route.js.nft.json +1 -1
  117. package/.next/standalone/.next/server/app/api/cortex/marketplace/preview/route.js.nft.json +1 -1
  118. package/.next/standalone/.next/server/app/api/cortex/mcp/call/route.js.nft.json +1 -1
  119. package/.next/standalone/.next/server/app/api/cortex/mcp/tools/route.js.nft.json +1 -1
  120. package/.next/standalone/.next/server/app/api/cortex/search/route.js.nft.json +1 -1
  121. package/.next/standalone/.next/server/app/api/cortex/settings/route.js.nft.json +1 -1
  122. package/.next/standalone/.next/server/app/api/cortex/status/route.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/api/cortex/timeline/route.js.nft.json +1 -1
  124. package/.next/standalone/.next/server/app/api/cortex/usage/route.js.nft.json +1 -1
  125. package/.next/standalone/.next/server/app/api/cortex/workspace/[id]/context/route.js.nft.json +1 -1
  126. package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
  127. package/.next/standalone/.next/server/app/api/folders/route.js.nft.json +1 -1
  128. package/.next/standalone/.next/server/app/api/network/handshake/route.js.nft.json +1 -1
  129. package/.next/standalone/.next/server/app/api/network/projects/route.js.nft.json +1 -1
  130. package/.next/standalone/.next/server/app/api/network/search/route.js.nft.json +1 -1
  131. package/.next/standalone/.next/server/app/api/network/sessions/[id]/messages/route.js.nft.json +1 -1
  132. package/.next/standalone/.next/server/app/api/network/sessions/[id]/route.js.nft.json +1 -1
  133. package/.next/standalone/.next/server/app/api/network/sessions/route.js.nft.json +1 -1
  134. package/.next/standalone/.next/server/app/api/network/workspaces/[id]/route.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/api/network/workspaces/route.js.nft.json +1 -1
  136. package/.next/standalone/.next/server/app/api/panes/[id]/route.js.nft.json +1 -1
  137. package/.next/standalone/.next/server/app/api/panes/route.js.nft.json +1 -1
  138. package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  139. package/.next/standalone/.next/server/app/api/search/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js.nft.json +1 -1
  141. package/.next/standalone/.next/server/app/api/sessions/[id]/messages/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  143. package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/sync/route.js.nft.json +1 -1
  145. package/.next/standalone/.next/server/app/api/tags/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/tier/route.js.nft.json +1 -1
  147. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/[key]/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/route.js.nft.json +1 -1
  149. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/[msgId]/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/route.js.nft.json +1 -1
  151. package/.next/standalone/.next/server/app/api/workspaces/[id]/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/workspaces/[id]/sessions/route.js.nft.json +1 -1
  153. package/.next/standalone/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/cortex.html +1 -1
  155. package/.next/standalone/.next/server/app/cortex.rsc +3 -3
  156. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex/__PAGE__.segment.rsc +2 -2
  157. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex.segment.rsc +1 -1
  158. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  159. package/.next/standalone/.next/server/app/cortex.segments/_full.segment.rsc +3 -3
  160. package/.next/standalone/.next/server/app/cortex.segments/_head.segment.rsc +1 -1
  161. package/.next/standalone/.next/server/app/cortex.segments/_index.segment.rsc +2 -2
  162. package/.next/standalone/.next/server/app/cortex.segments/_tree.segment.rsc +2 -2
  163. package/.next/standalone/.next/server/app/login/page/build-manifest.json +3 -3
  164. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  165. package/.next/standalone/.next/server/app/login.html +1 -1
  166. package/.next/standalone/.next/server/app/login.rsc +2 -2
  167. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +2 -2
  168. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
  169. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +2 -2
  170. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  171. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  172. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
  173. package/.next/standalone/.next/server/app/m/page/build-manifest.json +3 -3
  174. package/.next/standalone/.next/server/app/m/page_client-reference-manifest.js +1 -1
  175. package/.next/standalone/.next/server/app/m/projects/page/build-manifest.json +3 -3
  176. package/.next/standalone/.next/server/app/m/projects/page_client-reference-manifest.js +1 -1
  177. package/.next/standalone/.next/server/app/m/projects.html +1 -1
  178. package/.next/standalone/.next/server/app/m/projects.rsc +2 -2
  179. package/.next/standalone/.next/server/app/m/projects.segments/_full.segment.rsc +2 -2
  180. package/.next/standalone/.next/server/app/m/projects.segments/_head.segment.rsc +1 -1
  181. package/.next/standalone/.next/server/app/m/projects.segments/_index.segment.rsc +2 -2
  182. package/.next/standalone/.next/server/app/m/projects.segments/_tree.segment.rsc +2 -2
  183. package/.next/standalone/.next/server/app/m/projects.segments/m/projects/__PAGE__.segment.rsc +1 -1
  184. package/.next/standalone/.next/server/app/m/projects.segments/m/projects.segment.rsc +1 -1
  185. package/.next/standalone/.next/server/app/m/projects.segments/m.segment.rsc +1 -1
  186. package/.next/standalone/.next/server/app/m/sessions/[id]/page/build-manifest.json +3 -3
  187. package/.next/standalone/.next/server/app/m/sessions/[id]/page_client-reference-manifest.js +1 -1
  188. package/.next/standalone/.next/server/app/m/sessions/page/build-manifest.json +3 -3
  189. package/.next/standalone/.next/server/app/m/sessions/page_client-reference-manifest.js +1 -1
  190. package/.next/standalone/.next/server/app/m/sessions.html +1 -1
  191. package/.next/standalone/.next/server/app/m/sessions.rsc +2 -2
  192. package/.next/standalone/.next/server/app/m/sessions.segments/_full.segment.rsc +2 -2
  193. package/.next/standalone/.next/server/app/m/sessions.segments/_head.segment.rsc +1 -1
  194. package/.next/standalone/.next/server/app/m/sessions.segments/_index.segment.rsc +2 -2
  195. package/.next/standalone/.next/server/app/m/sessions.segments/_tree.segment.rsc +2 -2
  196. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions/__PAGE__.segment.rsc +1 -1
  197. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions.segment.rsc +1 -1
  198. package/.next/standalone/.next/server/app/m/sessions.segments/m.segment.rsc +1 -1
  199. package/.next/standalone/.next/server/app/m/settings/page/build-manifest.json +3 -3
  200. package/.next/standalone/.next/server/app/m/settings/page_client-reference-manifest.js +1 -1
  201. package/.next/standalone/.next/server/app/m/settings.html +1 -1
  202. package/.next/standalone/.next/server/app/m/settings.rsc +2 -2
  203. package/.next/standalone/.next/server/app/m/settings.segments/_full.segment.rsc +2 -2
  204. package/.next/standalone/.next/server/app/m/settings.segments/_head.segment.rsc +1 -1
  205. package/.next/standalone/.next/server/app/m/settings.segments/_index.segment.rsc +2 -2
  206. package/.next/standalone/.next/server/app/m/settings.segments/_tree.segment.rsc +2 -2
  207. package/.next/standalone/.next/server/app/m/settings.segments/m/settings/__PAGE__.segment.rsc +1 -1
  208. package/.next/standalone/.next/server/app/m/settings.segments/m/settings.segment.rsc +1 -1
  209. package/.next/standalone/.next/server/app/m/settings.segments/m.segment.rsc +1 -1
  210. package/.next/standalone/.next/server/app/m/terminal/page/build-manifest.json +3 -3
  211. package/.next/standalone/.next/server/app/m/terminal/page_client-reference-manifest.js +1 -1
  212. package/.next/standalone/.next/server/app/m/terminal.html +1 -1
  213. package/.next/standalone/.next/server/app/m/terminal.rsc +3 -3
  214. package/.next/standalone/.next/server/app/m/terminal.segments/_full.segment.rsc +3 -3
  215. package/.next/standalone/.next/server/app/m/terminal.segments/_head.segment.rsc +1 -1
  216. package/.next/standalone/.next/server/app/m/terminal.segments/_index.segment.rsc +2 -2
  217. package/.next/standalone/.next/server/app/m/terminal.segments/_tree.segment.rsc +2 -2
  218. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal/__PAGE__.segment.rsc +2 -2
  219. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal.segment.rsc +1 -1
  220. package/.next/standalone/.next/server/app/m/terminal.segments/m.segment.rsc +1 -1
  221. package/.next/standalone/.next/server/app/m.html +1 -1
  222. package/.next/standalone/.next/server/app/m.rsc +2 -2
  223. package/.next/standalone/.next/server/app/m.segments/_full.segment.rsc +2 -2
  224. package/.next/standalone/.next/server/app/m.segments/_head.segment.rsc +1 -1
  225. package/.next/standalone/.next/server/app/m.segments/_index.segment.rsc +2 -2
  226. package/.next/standalone/.next/server/app/m.segments/_tree.segment.rsc +2 -2
  227. package/.next/standalone/.next/server/app/m.segments/m/__PAGE__.segment.rsc +1 -1
  228. package/.next/standalone/.next/server/app/m.segments/m.segment.rsc +1 -1
  229. package/.next/standalone/.next/server/app/network.html +1 -1
  230. package/.next/standalone/.next/server/app/network.rsc +2 -2
  231. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network/__PAGE__.segment.rsc +1 -1
  232. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network.segment.rsc +1 -1
  233. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  234. package/.next/standalone/.next/server/app/network.segments/_full.segment.rsc +2 -2
  235. package/.next/standalone/.next/server/app/network.segments/_head.segment.rsc +1 -1
  236. package/.next/standalone/.next/server/app/network.segments/_index.segment.rsc +2 -2
  237. package/.next/standalone/.next/server/app/network.segments/_tree.segment.rsc +2 -2
  238. package/.next/standalone/.next/server/app/projects.html +1 -1
  239. package/.next/standalone/.next/server/app/projects.rsc +2 -2
  240. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects/__PAGE__.segment.rsc +1 -1
  241. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects.segment.rsc +1 -1
  242. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  243. package/.next/standalone/.next/server/app/projects.segments/_full.segment.rsc +2 -2
  244. package/.next/standalone/.next/server/app/projects.segments/_head.segment.rsc +1 -1
  245. package/.next/standalone/.next/server/app/projects.segments/_index.segment.rsc +2 -2
  246. package/.next/standalone/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
  247. package/.next/standalone/.next/server/app/sessions.html +1 -1
  248. package/.next/standalone/.next/server/app/sessions.rsc +2 -2
  249. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions/__PAGE__.segment.rsc +1 -1
  250. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions.segment.rsc +1 -1
  251. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  252. package/.next/standalone/.next/server/app/sessions.segments/_full.segment.rsc +2 -2
  253. package/.next/standalone/.next/server/app/sessions.segments/_head.segment.rsc +1 -1
  254. package/.next/standalone/.next/server/app/sessions.segments/_index.segment.rsc +2 -2
  255. package/.next/standalone/.next/server/app/sessions.segments/_tree.segment.rsc +2 -2
  256. package/.next/standalone/.next/server/app/settings.html +1 -1
  257. package/.next/standalone/.next/server/app/settings.rsc +2 -2
  258. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings/__PAGE__.segment.rsc +1 -1
  259. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings.segment.rsc +1 -1
  260. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  261. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +2 -2
  262. package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  263. package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  264. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  265. package/.next/standalone/.next/server/app/terminal.html +1 -1
  266. package/.next/standalone/.next/server/app/terminal.rsc +3 -3
  267. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal/__PAGE__.segment.rsc +2 -2
  268. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal.segment.rsc +1 -1
  269. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  270. package/.next/standalone/.next/server/app/terminal.segments/_full.segment.rsc +3 -3
  271. package/.next/standalone/.next/server/app/terminal.segments/_head.segment.rsc +1 -1
  272. package/.next/standalone/.next/server/app/terminal.segments/_index.segment.rsc +2 -2
  273. package/.next/standalone/.next/server/app/terminal.segments/_tree.segment.rsc +2 -2
  274. package/.next/standalone/.next/server/app/vr/page/app-paths-manifest.json +3 -0
  275. package/.next/standalone/.next/server/app/vr/page/build-manifest.json +18 -0
  276. package/.next/standalone/.next/server/app/vr/page/next-font-manifest.json +11 -0
  277. package/.next/standalone/.next/server/app/vr/page/react-loadable-manifest.json +11 -0
  278. package/.next/standalone/.next/server/app/vr/page/server-reference-manifest.json +4 -0
  279. package/.next/standalone/.next/server/app/vr/page.js +17 -0
  280. package/.next/standalone/.next/server/app/vr/page.js.map +5 -0
  281. package/.next/standalone/.next/server/app/vr/page.js.nft.json +1 -0
  282. package/.next/standalone/.next/server/app/vr/page_client-reference-manifest.js +2 -0
  283. package/.next/standalone/.next/server/app/vr.html +1 -0
  284. package/.next/standalone/.next/server/app/vr.meta +15 -0
  285. package/.next/standalone/.next/server/app/vr.rsc +21 -0
  286. package/.next/standalone/.next/server/app/vr.segments/_full.segment.rsc +21 -0
  287. package/.next/standalone/.next/server/app/vr.segments/_head.segment.rsc +6 -0
  288. package/.next/standalone/.next/server/app/vr.segments/_index.segment.rsc +6 -0
  289. package/.next/standalone/.next/server/app/vr.segments/_tree.segment.rsc +4 -0
  290. package/.next/standalone/.next/server/app/vr.segments/vr/__PAGE__.segment.rsc +9 -0
  291. package/.next/standalone/.next/server/app/vr.segments/vr.segment.rsc +4 -0
  292. package/.next/standalone/.next/server/app/workspaces.html +1 -1
  293. package/.next/standalone/.next/server/app/workspaces.rsc +2 -2
  294. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces/__PAGE__.segment.rsc +1 -1
  295. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces.segment.rsc +1 -1
  296. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  297. package/.next/standalone/.next/server/app/workspaces.segments/_full.segment.rsc +2 -2
  298. package/.next/standalone/.next/server/app/workspaces.segments/_head.segment.rsc +1 -1
  299. package/.next/standalone/.next/server/app/workspaces.segments/_index.segment.rsc +2 -2
  300. package/.next/standalone/.next/server/app/workspaces.segments/_tree.segment.rsc +2 -2
  301. package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
  302. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0041efe4._.js +2 -2
  303. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00bf0ace._.js +2 -2
  304. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08a68343._.js +1 -1
  305. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0add852f._.js +1 -1
  306. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0c113ed0._.js +1 -1
  307. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e1a27e0._.js +1 -1
  308. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e71d908._.js +3 -3
  309. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e9142f3._.js +2 -2
  310. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10e47926._.js +2 -2
  311. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1194f2c1._.js +1 -1
  312. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1665dc78._.js +2 -2
  313. package/.next/standalone/.next/server/chunks/[root-of-the-server]__175cbabf._.js +2 -2
  314. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19c2d094._.js +1 -1
  315. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1adae357._.js +2 -2
  316. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1d359752._.js +2 -2
  317. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1e8fabeb._.js +3 -3
  318. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1f8deca0._.js +8 -8
  319. package/.next/standalone/.next/server/chunks/[root-of-the-server]__253fdda1._.js +2 -2
  320. package/.next/standalone/.next/server/chunks/[root-of-the-server]__28e6434f._.js +2 -2
  321. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2a386564._.js +3 -3
  322. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2acbd703._.js +1 -1
  323. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2acefabb._.js +1 -1
  324. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2c20fb38._.js +2 -2
  325. package/.next/standalone/.next/server/chunks/[root-of-the-server]__309132cd._.js +1 -1
  326. package/.next/standalone/.next/server/chunks/[root-of-the-server]__33fec964._.js +3 -3
  327. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3786d8ae._.js +2 -2
  328. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3ae92407._.js +2 -2
  329. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3beda9fe._.js +2 -2
  330. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3e3f25a1._.js +1 -1
  331. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4619e9bd._.js +1 -1
  332. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4a051043._.js +2 -2
  333. package/.next/standalone/.next/server/chunks/[root-of-the-server]__50208a5f._.js +1 -1
  334. package/.next/standalone/.next/server/chunks/[root-of-the-server]__508002e4._.js +2 -2
  335. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5086c373._.js +2 -2
  336. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5913e097._.js +2 -2
  337. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5b5f68d2._.js +2 -2
  338. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5c1f2459._.js +2 -2
  339. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5ec8c977._.js +2 -2
  340. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5f8c694a._.js +1 -1
  341. package/.next/standalone/.next/server/chunks/[root-of-the-server]__63cebc6c._.js +2 -2
  342. package/.next/standalone/.next/server/chunks/[root-of-the-server]__64d30d4d._.js +2 -2
  343. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c54fc2e._.js +2 -2
  344. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6dc1fb7e._.js +2 -2
  345. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6e568102._.js +2 -2
  346. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6faa04c0._.js +2 -2
  347. package/.next/standalone/.next/server/chunks/[root-of-the-server]__727d05f1._.js +1 -1
  348. package/.next/standalone/.next/server/chunks/[root-of-the-server]__74a34dc3._.js +2 -2
  349. package/.next/standalone/.next/server/chunks/[root-of-the-server]__75d12b32._.js +1 -1
  350. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7e7250a4._.js +2 -2
  351. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8309e0a4._.js +2 -2
  352. package/.next/standalone/.next/server/chunks/[root-of-the-server]__86cc0e2b._.js +6 -6
  353. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8915603e._.js +1 -1
  354. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89c2565a._.js +2 -2
  355. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8d178ad9._.js +2 -2
  356. package/.next/standalone/.next/server/chunks/[root-of-the-server]__93ee06f3._.js +3 -3
  357. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9e4c154a._.js +2 -2
  358. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a1fbc199._.js +1 -1
  359. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9d2e1d3._.js +2 -2
  360. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ae53d343._.js +2 -2
  361. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b3a04cef._.js +2 -2
  362. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b4270b77._.js +1 -1
  363. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b6b6ce60._.js +1 -1
  364. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b9545dd9._.js +1 -1
  365. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c200e21a._.js +1 -1
  366. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c3c74ca4._.js +1 -1
  367. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c88b63f7._.js +2 -2
  368. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cba5f007._.js +1 -1
  369. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cbf4ceb0._.js +2 -2
  370. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cefdba2f._.js +2 -2
  371. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cf9e82bb._.js +2 -2
  372. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d15515e3._.js +1 -1
  373. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d2897392._.js +2 -2
  374. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d3b2d856._.js +2 -2
  375. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d73273ca._.js +2 -2
  376. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d8417eb6._.js +2 -2
  377. package/.next/standalone/.next/server/chunks/[root-of-the-server]__db4726bc._.js +1 -1
  378. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dc2a55de._.js +2 -2
  379. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dc6e2e5f._.js +1 -1
  380. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e0d4690b._.js +3 -3
  381. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e3ecfd17._.js +3 -3
  382. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e678dd53._.js +1 -1
  383. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e9223f55._.js +2 -2
  384. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ea630076._.js +3 -3
  385. package/.next/standalone/.next/server/chunks/[root-of-the-server]__eb8acb65._.js +1 -1
  386. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f26ca49d._.js +1 -1
  387. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f33e1101._.js +2 -2
  388. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f3a4c668._.js +1 -1
  389. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f515f865._.js +2 -2
  390. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fceb5d60._.js +2 -2
  391. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fed41403._.js +2 -2
  392. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ff2e98c2._.js +2 -2
  393. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_339169c8.js +1 -1
  394. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_97dac613.js +1 -1
  395. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0d8d81ca._.js +1 -1
  396. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1425c64f._.js +1 -1
  397. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1d2ce8f1._.js +1 -1
  398. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__31137509._.js +1 -1
  399. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3633a587._.js +1 -1
  400. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3c79441b._.js +1 -1
  401. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4ca0f26b._.js +1 -1
  402. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__5b90d3ad._.js +3 -0
  403. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__62a0b363._.js +1 -1
  404. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__66aca5d4._.js +1 -1
  405. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__68205a46._.js +1 -1
  406. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__69fd2efa._.js +1 -1
  407. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__85dcf0f7._.js +1 -1
  408. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8c53a5da._.js +1 -1
  409. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__aecb1873._.js +1 -1
  410. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__b02cd143._.js +1 -1
  411. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__b9bcde11._.js +3 -0
  412. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__cac90169._.js +1 -1
  413. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__d25de2f0._.js +1 -1
  414. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__e2f86be8._.js +1 -1
  415. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__ee626b5b._.js +1 -1
  416. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__f39a9e98._.js +1 -1
  417. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__f3c566cd._.js +1 -1
  418. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__f76aa221._.js +1 -1
  419. package/.next/standalone/.next/server/chunks/ssr/_149d7fd4._.js +1 -1
  420. package/.next/standalone/.next/server/chunks/ssr/_2230ad2d._.js +1 -1
  421. package/.next/standalone/.next/server/chunks/ssr/_2e0dd6a7._.js +1 -1
  422. package/.next/standalone/.next/server/chunks/ssr/_3cd2355c._.js +1 -1
  423. package/.next/standalone/.next/server/chunks/ssr/_3d206597._.js +4 -0
  424. package/.next/standalone/.next/server/chunks/ssr/_47cc9af0._.js +1 -1
  425. package/.next/standalone/.next/server/chunks/ssr/_5cf334fd._.js +3 -0
  426. package/.next/standalone/.next/server/chunks/ssr/_7082788b._.js +1 -1
  427. package/.next/standalone/.next/server/chunks/ssr/_7154d8ae._.js +1 -1
  428. package/.next/standalone/.next/server/chunks/ssr/_75bb1b9a._.js +1 -1
  429. package/.next/standalone/.next/server/chunks/ssr/{_aeeff784._.js → _81abf587._.js} +2 -2
  430. package/.next/standalone/.next/server/chunks/ssr/_8acf81e2._.js +1 -1
  431. package/.next/standalone/.next/server/chunks/ssr/_8c36feb8._.js +1 -1
  432. package/.next/standalone/.next/server/chunks/ssr/_91e9bb86._.js +1 -1
  433. package/.next/standalone/.next/server/chunks/ssr/_ac4c1838._.js +1 -1
  434. package/.next/standalone/.next/server/chunks/ssr/_ad8515fc._.js +1 -1
  435. package/.next/standalone/.next/server/chunks/ssr/_b1f49e81._.js +1 -1
  436. package/.next/standalone/.next/server/chunks/ssr/_c0fe7614._.js +1 -1
  437. package/.next/standalone/.next/server/chunks/ssr/_d4825f5a._.js +1 -1
  438. package/.next/standalone/.next/server/chunks/ssr/_da10a9f4._.js +1 -1
  439. package/.next/standalone/.next/server/chunks/ssr/_db0abd0a._.js +3 -0
  440. package/.next/standalone/.next/server/chunks/ssr/_db2fec84._.js +1 -1
  441. package/.next/standalone/.next/server/chunks/ssr/_dee5d4a1._.js +1 -1
  442. package/.next/standalone/.next/server/chunks/ssr/_ef482c0c._.js +1 -1
  443. package/.next/standalone/.next/server/chunks/ssr/_efe43d2f._.js +1 -1
  444. package/.next/standalone/.next/server/chunks/ssr/_f4a4e116._.js +1 -1
  445. package/.next/standalone/.next/server/chunks/ssr/_f4d525d2._.js +1 -1
  446. package/.next/standalone/.next/server/chunks/ssr/_f4e57187._.js +3 -0
  447. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_vr_page_actions_3fb70d92.js +3 -0
  448. package/.next/standalone/.next/server/chunks/ssr/node_modules_32f9d62f._.js +1 -1
  449. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_02f39477.js +1 -1
  450. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_eedfc1fd._.js +1 -1
  451. package/.next/standalone/.next/server/chunks/ssr/src_40fa36ce._.js +7 -0
  452. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_cortex_page_tsx_0f33d8b3._.js +3 -0
  453. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__32a0045c._.js +1 -1
  454. package/.next/standalone/.next/server/edge/chunks/_d73df637._.js +1 -1
  455. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  456. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  457. package/.next/standalone/.next/server/next-font-manifest.js +1 -1
  458. package/.next/standalone/.next/server/next-font-manifest.json +4 -0
  459. package/.next/standalone/.next/server/pages/404.html +1 -1
  460. package/.next/standalone/.next/server/pages/500.html +2 -2
  461. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  462. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  463. package/.next/standalone/.next/static/chunks/045c83caa4d15373.js +1 -0
  464. package/.next/standalone/.next/static/chunks/07ea09e6024a523b.js +1 -0
  465. package/.next/standalone/.next/static/chunks/{aae9e0fa485bd835.js → 158b52b84e647ac1.js} +2 -2
  466. package/.next/standalone/.next/static/chunks/232d8aae4fefab70.js +1 -0
  467. package/.next/standalone/.next/static/chunks/2ad22562bb37ecad.js +1011 -0
  468. package/.next/standalone/.next/static/chunks/{a4e5c700421eaa46.js → 412140a02893327a.js} +1 -1
  469. package/.next/standalone/.next/static/chunks/481cc11ae80b08b1.js +1 -0
  470. package/.next/standalone/.next/static/chunks/5325351ef49cb65f.js +1 -0
  471. package/.next/standalone/.next/static/chunks/559735e598ca3cbb.js +1 -0
  472. package/.next/standalone/.next/static/chunks/59c63d5af5cf3daf.js +1 -0
  473. package/.next/standalone/.next/static/chunks/5d5d7b0095dd52ae.js +1 -0
  474. package/.next/standalone/.next/static/chunks/69606d281c39f9b2.js +1 -0
  475. package/.next/standalone/.next/static/chunks/6ae575967d091df4.js +1 -0
  476. package/.next/standalone/.next/static/chunks/7f8455bb855a6c84.js +1 -0
  477. package/.next/standalone/.next/static/chunks/84fe8d44deeeb74f.js +757 -0
  478. package/.next/standalone/.next/static/chunks/898f380eba90427a.js +1 -0
  479. package/.next/standalone/.next/static/chunks/95339e55722bb4ca.js +5 -0
  480. package/.next/standalone/.next/static/chunks/9cd594813c539df9.js +1 -0
  481. package/.next/standalone/.next/static/chunks/{7424664c6ffa94bd.js → 9cfa0291d55d8d2a.js} +1 -1
  482. package/.next/standalone/.next/static/chunks/ad1423eed05d129b.js +1 -0
  483. package/.next/standalone/.next/static/chunks/ae7b146884c67d2a.js +1 -0
  484. package/.next/standalone/.next/static/chunks/b84072d72aa86417.js +1 -0
  485. package/.next/standalone/.next/static/chunks/c1a95aebf6725f64.css +3 -0
  486. package/.next/standalone/.next/static/chunks/c515eb77d9410aa0.js +5 -0
  487. package/.next/standalone/.next/static/chunks/{9899cf4c2bdbe61d.js → d9ae203a7f123546.js} +2 -2
  488. package/.next/standalone/.next/static/chunks/e116953dc83d4eec.js +1 -0
  489. package/.next/standalone/.next/static/chunks/fdc09bd135846960.js +1 -0
  490. package/.next/standalone/.next/static/chunks/ff0196911449e745.js +1 -0
  491. package/.next/standalone/.next/static/chunks/{turbopack-4c21186b79fb4c10.js → turbopack-e1a0994ed4af988c.js} +1 -1
  492. package/.next/standalone/.spaces/cortex-context.md +70 -0
  493. package/.next/standalone/bin/cortex-hook.sh +62 -62
  494. package/.next/standalone/bin/cortex-mcp.js +60 -60
  495. package/.next/standalone/docs/superpowers/plans/2026-03-13-cortex-wiring.md +1387 -1387
  496. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-entity-graph.md +1923 -1923
  497. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-knowledge-evolution.md +1113 -1113
  498. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-boundary-engine.md +853 -853
  499. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-context-engine.md +1274 -1274
  500. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-signal-ingestion.md +933 -933
  501. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-lobes.md +1080 -1080
  502. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-gravity-system.md +768 -768
  503. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-ui.md +1108 -1108
  504. package/.next/standalone/docs/superpowers/plans/2026-03-18-cortex-ui-integration.md +1846 -1846
  505. package/.next/standalone/docs/superpowers/specs/2026-03-13-cortex-wiring-design.md +268 -268
  506. package/.next/standalone/docs/superpowers/specs/2026-03-14-cortex-v2-design.md +623 -623
  507. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-lobes-design.md +263 -263
  508. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-v2-ui-design.md +240 -240
  509. package/.next/standalone/docs/superpowers/specs/2026-03-18-cortex-ui-integration-design.md +341 -341
  510. package/.next/standalone/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64.node +0 -0
  511. package/.next/standalone/node_modules/@img/{sharp-linux-x64 → sharp-win32-x64}/package.json +39 -46
  512. package/.next/standalone/package.json +104 -102
  513. package/.next/standalone/server.js +1 -1
  514. package/.next/standalone/src/app/(desktop)/cortex/page.tsx +78 -78
  515. package/.next/standalone/src/app/api/cortex/context/route.ts +78 -78
  516. package/.next/standalone/src/app/api/cortex/curation/assess/route.ts +27 -27
  517. package/.next/standalone/src/app/api/cortex/curation/publish/route.ts +23 -23
  518. package/.next/standalone/src/app/api/cortex/curation/refine/route.ts +23 -23
  519. package/.next/standalone/src/app/api/cortex/curation/review/route.ts +29 -29
  520. package/.next/standalone/src/app/api/cortex/curation/seed/route.ts +23 -23
  521. package/.next/standalone/src/app/api/cortex/export/route.ts +40 -40
  522. package/.next/standalone/src/app/api/cortex/federation/pending/route.ts +20 -20
  523. package/.next/standalone/src/app/api/cortex/federation/resolve/route.ts +43 -43
  524. package/.next/standalone/src/app/api/cortex/federation/search/route.ts +35 -35
  525. package/.next/standalone/src/app/api/cortex/federation/teach/route.ts +76 -76
  526. package/.next/standalone/src/app/api/cortex/graph/edges/route.ts +112 -112
  527. package/.next/standalone/src/app/api/cortex/graph/entities/[id]/route.ts +73 -73
  528. package/.next/standalone/src/app/api/cortex/graph/entities/route.ts +75 -75
  529. package/.next/standalone/src/app/api/cortex/graph/populate/route.ts +203 -203
  530. package/.next/standalone/src/app/api/cortex/import/route.ts +75 -75
  531. package/.next/standalone/src/app/api/cortex/import/status/route.ts +15 -15
  532. package/.next/standalone/src/app/api/cortex/ingest/bootstrap/route.ts +29 -29
  533. package/.next/standalone/src/app/api/cortex/ingest/status/route.ts +15 -15
  534. package/.next/standalone/src/app/api/cortex/knowledge/[id]/route.ts +91 -91
  535. package/.next/standalone/src/app/api/cortex/knowledge/route.ts +93 -93
  536. package/.next/standalone/src/app/api/cortex/lobes/[id]/route.ts +67 -67
  537. package/.next/standalone/src/app/api/cortex/lobes/route.ts +22 -22
  538. package/.next/standalone/src/app/api/cortex/lobes/share/route.ts +80 -80
  539. package/.next/standalone/src/app/api/cortex/marketplace/browse/route.ts +43 -43
  540. package/.next/standalone/src/app/api/cortex/marketplace/preview/route.ts +46 -46
  541. package/.next/standalone/src/app/api/cortex/mcp/call/route.ts +11 -11
  542. package/.next/standalone/src/app/api/cortex/mcp/tools/route.ts +6 -6
  543. package/.next/standalone/src/app/api/cortex/search/route.ts +43 -43
  544. package/.next/standalone/src/app/api/cortex/settings/route.ts +33 -33
  545. package/.next/standalone/src/app/api/cortex/status/route.ts +169 -169
  546. package/.next/standalone/src/app/api/cortex/timeline/route.ts +42 -42
  547. package/.next/standalone/src/app/api/cortex/usage/route.ts +31 -31
  548. package/.next/standalone/src/app/api/cortex/workspace/[id]/context/route.ts +41 -41
  549. package/.next/standalone/src/components/cortex/constants.ts +29 -29
  550. package/.next/standalone/src/components/cortex/cortex-dashboard.tsx +304 -304
  551. package/.next/standalone/src/components/cortex/cortex-indicator.tsx +44 -44
  552. package/.next/standalone/src/components/cortex/cortex-panel.tsx +140 -140
  553. package/.next/standalone/src/components/cortex/cortex-settings.tsx +221 -221
  554. package/.next/standalone/src/components/cortex/curation-tab.tsx +810 -810
  555. package/.next/standalone/src/components/cortex/entity-detail.tsx +101 -101
  556. package/.next/standalone/src/components/cortex/entity-graph.tsx +382 -382
  557. package/.next/standalone/src/components/cortex/import-dialog.tsx +212 -212
  558. package/.next/standalone/src/components/cortex/injection-badge.tsx +72 -72
  559. package/.next/standalone/src/components/cortex/knowledge-card.tsx +109 -109
  560. package/.next/standalone/src/components/cortex/knowledge-tab.tsx +158 -158
  561. package/.next/standalone/src/components/cortex/lobe-settings.tsx +215 -215
  562. package/.next/standalone/src/components/cortex/marketplace-card.tsx +126 -126
  563. package/.next/standalone/src/components/cortex/marketplace-tab.tsx +113 -113
  564. package/.next/standalone/src/lib/cortex/config.ts +40 -40
  565. package/.next/standalone/src/lib/cortex/debug.ts +10 -10
  566. package/.next/standalone/src/lib/cortex/distillation/usage-store.ts +18 -18
  567. package/.next/standalone/src/lib/cortex/graph/resolver.ts +10 -10
  568. package/.next/standalone/src/lib/cortex/graph/types.ts +22 -22
  569. package/.next/standalone/src/lib/cortex/index.ts +56 -56
  570. package/.next/standalone/src/lib/cortex/ingestion/bootstrap.ts +14 -14
  571. package/.next/standalone/src/lib/cortex/knowledge/compat.ts +14 -14
  572. package/.next/standalone/src/lib/cortex/knowledge/contradiction.ts +10 -10
  573. package/.next/standalone/src/lib/cortex/knowledge/types.ts +67 -67
  574. package/.next/standalone/src/lib/cortex/lobes/config.ts +16 -16
  575. package/.next/standalone/src/lib/cortex/lobes/resolver.ts +8 -8
  576. package/.next/standalone/src/lib/cortex/lobes/shares.ts +14 -14
  577. package/.next/standalone/src/lib/cortex/mcp/server.ts +8 -8
  578. package/.next/standalone/src/lib/cortex/portability/exporter.ts +6 -6
  579. package/.next/standalone/src/lib/cortex/portability/importer.ts +10 -10
  580. package/.next/standalone/src/lib/cortex/retrieval/context-engine.ts +10 -10
  581. package/.next/standalone/src/lib/cortex/types.ts +39 -39
  582. package/.next/standalone/tsconfig.json +34 -34
  583. package/LICENSE +661 -661
  584. package/README.md +131 -131
  585. package/bin/cortex-hook.sh +62 -62
  586. package/bin/cortex-mcp.js +60 -60
  587. package/bin/fix-standalone-externals.js +79 -79
  588. package/bin/lib/auto-setup.js +110 -110
  589. package/bin/mdns-service.js +171 -171
  590. package/bin/postinstall.js +35 -35
  591. package/bin/setup-admin.js +195 -195
  592. package/bin/spaces-dev.js +208 -208
  593. package/bin/spaces-install.js +599 -599
  594. package/bin/spaces-reset-totp.js +50 -50
  595. package/bin/spaces-service.js +1020 -1020
  596. package/bin/spaces-setup.js +253 -253
  597. package/bin/spaces.js +776 -776
  598. package/bin/ssh-auth-keys.sh +68 -68
  599. package/bin/terminal-server.js +1683 -1649
  600. package/package.json +104 -102
  601. package/.next/standalone/.next/server/chunks/ssr/_078dd64d._.js +0 -3
  602. package/.next/standalone/.next/server/chunks/ssr/_701606d5._.js +0 -3
  603. package/.next/standalone/.next/server/chunks/ssr/_72b1de37._.js +0 -3
  604. package/.next/standalone/.next/server/chunks/ssr/_950142a4._.js +0 -3
  605. package/.next/standalone/.next/server/chunks/ssr/src_components_terminal_terminal-pane_tsx_803c5e2c._.js +0 -7
  606. package/.next/standalone/.next/static/chunks/18f168665aef1aab.js +0 -1
  607. package/.next/standalone/.next/static/chunks/25b7a243a404a1a7.js +0 -1
  608. package/.next/standalone/.next/static/chunks/4a50d2a3e9bc9b41.js +0 -1
  609. package/.next/standalone/.next/static/chunks/6c78a1dfa7ec2959.css +0 -3
  610. package/.next/standalone/.next/static/chunks/7e0091ab6c5ee8bd.js +0 -1
  611. package/.next/standalone/.next/static/chunks/869f562dc32e55f4.js +0 -1
  612. package/.next/standalone/.next/static/chunks/8b3f4572fec83caa.js +0 -5
  613. package/.next/standalone/.next/static/chunks/8d5419afc4b9116b.js +0 -1
  614. package/.next/standalone/.next/static/chunks/9b2c5451f0b67975.js +0 -1
  615. package/.next/standalone/.next/static/chunks/ac339e970df82fa5.js +0 -5
  616. package/.next/standalone/.next/static/chunks/e7772d64463868eb.js +0 -1
  617. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/README.md +0 -46
  618. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/glib-2.0/include/glibconfig.h +0 -221
  619. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/index.js +0 -1
  620. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  621. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/package.json +0 -42
  622. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/README.md +0 -46
  623. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/glib-2.0/include/glibconfig.h +0 -221
  624. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/index.js +0 -1
  625. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  626. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json +0 -42
  627. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/versions.json +0 -30
  628. package/.next/standalone/node_modules/@img/sharp-linux-x64/lib/sharp-linux-x64.node +0 -0
  629. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/lib/sharp-linuxmusl-x64.node +0 -0
  630. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/package.json +0 -46
  631. /package/.next/standalone/.next/static/{77VYbwIoyxFNr5xevTrCu → BEY-sql3lQLouidpurSQf}/_buildManifest.js +0 -0
  632. /package/.next/standalone/.next/static/{77VYbwIoyxFNr5xevTrCu → BEY-sql3lQLouidpurSQf}/_clientMiddlewareManifest.json +0 -0
  633. /package/.next/standalone/.next/static/{77VYbwIoyxFNr5xevTrCu → BEY-sql3lQLouidpurSQf}/_ssgManifest.js +0 -0
  634. /package/.next/standalone/node_modules/@img/{sharp-libvips-linux-x64 → sharp-win32-x64}/versions.json +0 -0
@@ -1,768 +1,768 @@
1
- # Cortex v2 — Pillar 6: Gravity System
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:** Implement bi-directional knowledge flow — evidence-based bubble-up promotion, decision trickle-down, conflict detection during ingestion, stale knowledge decay, and a background gravity scheduler that runs every 6 hours.
6
-
7
- **Architecture:** A new `src/lib/cortex/gravity/` module with four components: `promotion.ts` (bubble-up logic), `trickle.ts` (push-down logic), `contradiction.ts` (ingestion-time conflict detection), and `scheduler.ts` (background timer orchestrating all gravity operations). Uses the `gravity_state` SQLite table (created in Pillar 1) for checkpoint persistence.
8
-
9
- **Tech Stack:** TypeScript, better-sqlite3, LanceDB, vitest
10
-
11
- **Spec:** `docs/superpowers/specs/2026-03-14-cortex-v2-design.md` — Pillar 6
12
-
13
- **Depends on:** All previous pillars (1-5) — completed
14
-
15
- ---
16
-
17
- ## File Structure
18
-
19
- ```
20
- New files:
21
- ├── src/lib/cortex/gravity/promotion.ts — Bubble-up: evidence-based promotion
22
- ├── src/lib/cortex/gravity/trickle.ts — Trickle-down: decision push + visibility
23
- ├── src/lib/cortex/gravity/contradiction.ts — Ingestion-time conflict detection
24
- ├── src/lib/cortex/gravity/decay.ts — Stale knowledge decay + archival
25
- ├── src/lib/cortex/gravity/scheduler.ts — Background scheduler (setInterval)
26
- ├── src/lib/cortex/gravity/index.ts — Barrel export
27
-
28
- Modified files:
29
- ├── src/lib/cortex/index.ts — Add GravityScheduler to CortexInstance
30
-
31
- Test files:
32
- ├── tests/lib/cortex/gravity/promotion.test.ts
33
- ├── tests/lib/cortex/gravity/trickle.test.ts
34
- ├── tests/lib/cortex/gravity/contradiction.test.ts
35
- ├── tests/lib/cortex/gravity/decay.test.ts
36
- ├── tests/lib/cortex/gravity/scheduler.test.ts
37
- ```
38
-
39
- ---
40
-
41
- ## Chunk 1: Promotion and Trickle-Down
42
-
43
- ### Task 1: Bubble-up promotion logic
44
-
45
- **Files:**
46
- - Create: `src/lib/cortex/gravity/promotion.ts`
47
- - Create: `tests/lib/cortex/gravity/promotion.test.ts`
48
-
49
- - [ ] **Step 1: Write failing tests**
50
-
51
- ```typescript
52
- // tests/lib/cortex/gravity/promotion.test.ts
53
- import { describe, it, expect } from 'vitest';
54
- import {
55
- computePromotionScore,
56
- shouldPromote,
57
- PROMOTION_TYPE_WEIGHTS,
58
- } from '@/lib/cortex/gravity/promotion';
59
-
60
- describe('computePromotionScore', () => {
61
- it('computes score from evidence, type weight, and freshness', () => {
62
- const score = computePromotionScore({
63
- evidenceScore: 0.8,
64
- type: 'decision',
65
- createdDaysAgo: 10,
66
- });
67
- // 0.8 * 1.5 (decision weight) * 1.0 (< 30 days) = 1.2 → capped at 1.0
68
- expect(score).toBeLessThanOrEqual(1.0);
69
- expect(score).toBeGreaterThan(0.5);
70
- });
71
-
72
- it('applies type weights correctly', () => {
73
- const decision = computePromotionScore({ evidenceScore: 0.5, type: 'decision', createdDaysAgo: 10 });
74
- const conversation = computePromotionScore({ evidenceScore: 0.5, type: 'conversation', createdDaysAgo: 10 });
75
- expect(decision).toBeGreaterThan(conversation);
76
- });
77
-
78
- it('decays with age', () => {
79
- const recent = computePromotionScore({ evidenceScore: 0.8, type: 'pattern', createdDaysAgo: 5 });
80
- const old = computePromotionScore({ evidenceScore: 0.8, type: 'pattern', createdDaysAgo: 120 });
81
- expect(recent).toBeGreaterThan(old);
82
- });
83
- });
84
-
85
- describe('shouldPromote', () => {
86
- it('promotes personal→team when score and corroborations meet threshold', () => {
87
- expect(shouldPromote({
88
- currentLevel: 'personal',
89
- promotionScore: 0.7,
90
- corroborations: 3,
91
- sensitivity: 'internal',
92
- hasContradictions: false,
93
- })).toBe(true);
94
- });
95
-
96
- it('blocks promotion when sensitivity is restricted', () => {
97
- expect(shouldPromote({
98
- currentLevel: 'personal',
99
- promotionScore: 0.7,
100
- corroborations: 3,
101
- sensitivity: 'restricted',
102
- hasContradictions: false,
103
- })).toBe(false);
104
- });
105
-
106
- it('blocks promotion when corroborations insufficient', () => {
107
- expect(shouldPromote({
108
- currentLevel: 'personal',
109
- promotionScore: 0.7,
110
- corroborations: 1, // needs ≥ 2
111
- sensitivity: 'internal',
112
- hasContradictions: false,
113
- })).toBe(false);
114
- });
115
-
116
- it('blocks dept→org promotion when contradictions exist', () => {
117
- expect(shouldPromote({
118
- currentLevel: 'department',
119
- promotionScore: 0.95,
120
- corroborations: 6,
121
- sensitivity: 'internal',
122
- hasContradictions: true,
123
- })).toBe(false);
124
- });
125
-
126
- it('requires higher thresholds for higher promotions', () => {
127
- // Score 0.65 passes personal→team but not team→dept
128
- expect(shouldPromote({
129
- currentLevel: 'personal', promotionScore: 0.65, corroborations: 2,
130
- sensitivity: 'internal', hasContradictions: false,
131
- })).toBe(true);
132
-
133
- expect(shouldPromote({
134
- currentLevel: 'team', promotionScore: 0.65, corroborations: 3,
135
- sensitivity: 'internal', hasContradictions: false,
136
- })).toBe(false); // needs ≥ 0.75
137
- });
138
- });
139
- ```
140
-
141
- - [ ] **Step 2: Implement promotion logic**
142
-
143
- ```typescript
144
- // src/lib/cortex/gravity/promotion.ts
145
- import type { KnowledgeType, ScopeLevel, SensitivityClass } from '../knowledge/types';
146
-
147
- export const PROMOTION_TYPE_WEIGHTS: Record<string, number> = {
148
- decision: 1.5,
149
- error_fix: 1.3,
150
- pattern: 1.2,
151
- preference: 1.0,
152
- code_pattern: 1.0,
153
- command: 0.8,
154
- context: 0.7,
155
- summary: 0.7,
156
- conversation: 0.5,
157
- };
158
-
159
- const FRESHNESS_THRESHOLDS = [
160
- { maxDays: 30, multiplier: 1.0 },
161
- { maxDays: 90, multiplier: 0.8 },
162
- { maxDays: Infinity, multiplier: 0.5 },
163
- ];
164
-
165
- interface PromotionScoreInput {
166
- evidenceScore: number;
167
- type: string;
168
- createdDaysAgo: number;
169
- }
170
-
171
- export function computePromotionScore(input: PromotionScoreInput): number {
172
- const typeWeight = PROMOTION_TYPE_WEIGHTS[input.type] ?? 1.0;
173
- const freshness = FRESHNESS_THRESHOLDS.find(t => input.createdDaysAgo <= t.maxDays)?.multiplier ?? 0.5;
174
- return Math.min(1.0, input.evidenceScore * typeWeight * freshness);
175
- }
176
-
177
- interface PromotionCheck {
178
- currentLevel: ScopeLevel;
179
- promotionScore: number;
180
- corroborations: number;
181
- sensitivity: string;
182
- hasContradictions: boolean;
183
- }
184
-
185
- const PROMOTION_THRESHOLDS: Record<string, { minScore: number; minCorroborations: number; noContradictions?: boolean }> = {
186
- personal: { minScore: 0.6, minCorroborations: 2 },
187
- team: { minScore: 0.75, minCorroborations: 3 },
188
- department: { minScore: 0.9, minCorroborations: 5, noContradictions: true },
189
- };
190
-
191
- const NEXT_LEVEL: Record<string, ScopeLevel> = {
192
- personal: 'team',
193
- team: 'department',
194
- department: 'organization',
195
- };
196
-
197
- export function shouldPromote(check: PromotionCheck): boolean {
198
- const threshold = PROMOTION_THRESHOLDS[check.currentLevel];
199
- if (!threshold) return false; // organization can't promote further
200
-
201
- if (check.sensitivity === 'restricted' || check.sensitivity === 'confidential') return false;
202
- if (check.promotionScore < threshold.minScore) return false;
203
- if (check.corroborations < threshold.minCorroborations) return false;
204
- if (threshold.noContradictions && check.hasContradictions) return false;
205
-
206
- return true;
207
- }
208
-
209
- export function getNextLevel(current: ScopeLevel): ScopeLevel | null {
210
- return NEXT_LEVEL[current] ?? null;
211
- }
212
-
213
- export const HOP_DECAY = 0.85;
214
- ```
215
-
216
- - [ ] **Step 3: Run tests, commit**
217
-
218
- ```bash
219
- git commit -m "feat(cortex): add evidence-based promotion logic for gravity system"
220
- ```
221
-
222
- ---
223
-
224
- ### Task 2: Trickle-down logic
225
-
226
- **Files:**
227
- - Create: `src/lib/cortex/gravity/trickle.ts`
228
- - Create: `tests/lib/cortex/gravity/trickle.test.ts`
229
-
230
- - [ ] **Step 1: Write failing tests**
231
-
232
- ```typescript
233
- // tests/lib/cortex/gravity/trickle.test.ts
234
- import { describe, it, expect } from 'vitest';
235
- import { getTrickleMode, TRICKLE_DEFAULTS } from '@/lib/cortex/gravity/trickle';
236
-
237
- describe('getTrickleMode', () => {
238
- it('returns PUSH for org decisions', () => {
239
- expect(getTrickleMode('decision', 'organization')).toBe('push');
240
- });
241
-
242
- it('returns PUSH for security policies', () => {
243
- expect(getTrickleMode('error_fix', 'organization', ['security'])).toBe('push');
244
- });
245
-
246
- it('returns VISIBILITY for best practices', () => {
247
- expect(getTrickleMode('pattern', 'organization')).toBe('visibility');
248
- });
249
-
250
- it('returns VISIBILITY for general patterns', () => {
251
- expect(getTrickleMode('conversation', 'organization')).toBe('visibility');
252
- });
253
-
254
- it('returns null for non-org scopes', () => {
255
- expect(getTrickleMode('decision', 'team')).toBeNull();
256
- });
257
-
258
- it('exports trickle defaults table', () => {
259
- expect(TRICKLE_DEFAULTS).toBeDefined();
260
- expect(TRICKLE_DEFAULTS.decision).toBe('push');
261
- expect(TRICKLE_DEFAULTS.pattern).toBe('visibility');
262
- });
263
- });
264
- ```
265
-
266
- - [ ] **Step 2: Implement trickle-down**
267
-
268
- ```typescript
269
- // src/lib/cortex/gravity/trickle.ts
270
- import type { KnowledgeType, ScopeLevel } from '../knowledge/types';
271
-
272
- export type TrickleMode = 'push' | 'visibility';
273
-
274
- export const TRICKLE_DEFAULTS: Record<string, TrickleMode> = {
275
- decision: 'push',
276
- preference: 'push',
277
- error_fix: 'visibility',
278
- pattern: 'visibility',
279
- code_pattern: 'visibility',
280
- command: 'visibility',
281
- context: 'visibility',
282
- conversation: 'visibility',
283
- summary: 'visibility',
284
- };
285
-
286
- const SECURITY_TOPICS = ['security', 'vulnerability', 'exploit', 'cve', 'incident'];
287
-
288
- /**
289
- * Determine trickle mode for knowledge at a given scope.
290
- * Only org-level knowledge trickles down.
291
- * Returns null if knowledge shouldn't trickle (not at org scope).
292
- */
293
- export function getTrickleMode(
294
- type: string,
295
- scopeLevel: string,
296
- topics?: string[],
297
- ): TrickleMode | null {
298
- // Only org-level knowledge trickles down
299
- if (scopeLevel !== 'organization') return null;
300
-
301
- // Security topics always push
302
- if (topics?.some(t => SECURITY_TOPICS.includes(t.toLowerCase()))) {
303
- return 'push';
304
- }
305
-
306
- return TRICKLE_DEFAULTS[type] ?? 'visibility';
307
- }
308
- ```
309
-
310
- - [ ] **Step 3: Run tests, commit**
311
-
312
- ```bash
313
- git commit -m "feat(cortex): add trickle-down logic for gravity system"
314
- ```
315
-
316
- ---
317
-
318
- ## Chunk 2: Contradiction Detection and Decay
319
-
320
- ### Task 3: Ingestion-time contradiction detection
321
-
322
- **Files:**
323
- - Create: `src/lib/cortex/gravity/contradiction.ts`
324
- - Create: `tests/lib/cortex/gravity/contradiction.test.ts`
325
-
326
- - [ ] **Step 1: Write failing tests**
327
-
328
- ```typescript
329
- // tests/lib/cortex/gravity/contradiction.test.ts
330
- import { describe, it, expect } from 'vitest';
331
- import {
332
- detectSentimentConflict,
333
- CONTRADICTION_KEYWORDS,
334
- } from '@/lib/cortex/gravity/contradiction';
335
-
336
- describe('detectSentimentConflict', () => {
337
- it('detects opposing sentiments', () => {
338
- expect(detectSentimentConflict(
339
- 'increase connection pool size to 50',
340
- 'do NOT increase pool size, scale horizontally instead',
341
- )).toBe(true);
342
- });
343
-
344
- it('returns false for agreeing statements', () => {
345
- expect(detectSentimentConflict(
346
- 'use PostgreSQL for the new service',
347
- 'PostgreSQL is the right choice for reliability',
348
- )).toBe(false);
349
- });
350
-
351
- it('detects negation patterns', () => {
352
- expect(detectSentimentConflict(
353
- 'we should use Redis for caching',
354
- 'we should not use Redis for caching',
355
- )).toBe(true);
356
- });
357
-
358
- it('detects replacement/alternative patterns', () => {
359
- expect(detectSentimentConflict(
360
- 'use Express for the API',
361
- 'use Fastify instead of Express',
362
- )).toBe(true);
363
- });
364
-
365
- it('returns false for unrelated statements', () => {
366
- expect(detectSentimentConflict(
367
- 'the auth service handles JWT',
368
- 'deploy to production on Fridays',
369
- )).toBe(false);
370
- });
371
- });
372
- ```
373
-
374
- - [ ] **Step 2: Implement contradiction detection**
375
-
376
- ```typescript
377
- // src/lib/cortex/gravity/contradiction.ts
378
-
379
- export const CONTRADICTION_KEYWORDS = {
380
- negation: [/\bnot\b/i, /\bdon't\b/i, /\bdo\s+not\b/i, /\bnever\b/i, /\bavoid\b/i, /\bstop\b/i],
381
- replacement: [/\binstead\s+of\b/i, /\brather\s+than\b/i, /\breplace\b.*\bwith\b/i, /\bswitch\s+(from|to)\b/i],
382
- opposition: [/\bhowever\b/i, /\bbut\b/i, /\bcontra/i, /\boppos/i],
383
- };
384
-
385
- /**
386
- * Detect if two texts express conflicting conclusions.
387
- * Uses keyword-based sentiment analysis (no LLM needed).
388
- *
389
- * Returns true if text B appears to contradict text A.
390
- */
391
- export function detectSentimentConflict(textA: string, textB: string): boolean {
392
- const lowerB = textB.toLowerCase();
393
- const lowerA = textA.toLowerCase();
394
-
395
- // Check if B contains negation of key terms from A
396
- const aWords = extractKeyTerms(lowerA);
397
- const bWords = extractKeyTerms(lowerB);
398
-
399
- // If B negates something A asserts
400
- for (const patterns of Object.values(CONTRADICTION_KEYWORDS)) {
401
- for (const pattern of patterns) {
402
- if (pattern.test(textB)) {
403
- // B has negation/replacement language
404
- // Check if they share subject matter (at least 2 common key terms)
405
- const commonTerms = aWords.filter(w => bWords.includes(w));
406
- if (commonTerms.length >= 2) return true;
407
- }
408
- }
409
- }
410
-
411
- return false;
412
- }
413
-
414
- function extractKeyTerms(text: string): string[] {
415
- const stopWords = new Set(['the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been',
416
- 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'we', 'should', 'it',
417
- 'this', 'that', 'and', 'or', 'but', 'not', 'do', 'does', 'did', 'has', 'have', 'had']);
418
- return text.split(/\W+/).filter(w => w.length > 2 && !stopWords.has(w));
419
- }
420
-
421
- export const CONTRADICTION_COSINE_THRESHOLD = 0.80;
422
- export const DEDUP_COSINE_THRESHOLD = 0.90;
423
- ```
424
-
425
- - [ ] **Step 3: Run tests, commit**
426
-
427
- ```bash
428
- git commit -m "feat(cortex): add ingestion-time contradiction detection"
429
- ```
430
-
431
- ---
432
-
433
- ### Task 4: Stale knowledge decay
434
-
435
- **Files:**
436
- - Create: `src/lib/cortex/gravity/decay.ts`
437
- - Create: `tests/lib/cortex/gravity/decay.test.ts`
438
-
439
- - [ ] **Step 1: Write failing tests**
440
-
441
- ```typescript
442
- // tests/lib/cortex/gravity/decay.test.ts
443
- import { describe, it, expect } from 'vitest';
444
- import { computeDecay, shouldArchive, ARCHIVE_THRESHOLD } from '@/lib/cortex/gravity/decay';
445
-
446
- describe('computeDecay', () => {
447
- it('returns 0 decay for recently accessed knowledge', () => {
448
- expect(computeDecay({ daysSinceAccess: 5, currentEvidenceScore: 0.8 })).toBeCloseTo(0);
449
- });
450
-
451
- it('returns small decay for moderately old knowledge', () => {
452
- const decay = computeDecay({ daysSinceAccess: 60, currentEvidenceScore: 0.8 });
453
- expect(decay).toBeGreaterThan(0);
454
- expect(decay).toBeLessThan(0.2);
455
- });
456
-
457
- it('returns larger decay for very old knowledge', () => {
458
- const moderate = computeDecay({ daysSinceAccess: 60, currentEvidenceScore: 0.8 });
459
- const old = computeDecay({ daysSinceAccess: 180, currentEvidenceScore: 0.8 });
460
- expect(old).toBeGreaterThan(moderate);
461
- });
462
-
463
- it('never makes evidence score negative', () => {
464
- const decay = computeDecay({ daysSinceAccess: 365, currentEvidenceScore: 0.1 });
465
- expect(0.1 - decay).toBeGreaterThanOrEqual(0);
466
- });
467
- });
468
-
469
- describe('shouldArchive', () => {
470
- it('archives units with evidence below threshold after 6 months', () => {
471
- expect(shouldArchive({ evidenceScore: 0.05, daysSinceCreated: 200 })).toBe(true);
472
- });
473
-
474
- it('does not archive recent units even with low evidence', () => {
475
- expect(shouldArchive({ evidenceScore: 0.05, daysSinceCreated: 30 })).toBe(false);
476
- });
477
-
478
- it('does not archive units above threshold', () => {
479
- expect(shouldArchive({ evidenceScore: 0.5, daysSinceCreated: 200 })).toBe(false);
480
- });
481
-
482
- it('uses ARCHIVE_THRESHOLD of 0.1', () => {
483
- expect(ARCHIVE_THRESHOLD).toBe(0.1);
484
- });
485
- });
486
- ```
487
-
488
- - [ ] **Step 2: Implement decay**
489
-
490
- ```typescript
491
- // src/lib/cortex/gravity/decay.ts
492
-
493
- export const ARCHIVE_THRESHOLD = 0.1;
494
- const ARCHIVE_MIN_AGE_DAYS = 180; // 6 months
495
- const DECAY_START_DAYS = 30; // no decay within first 30 days of last access
496
-
497
- interface DecayInput {
498
- daysSinceAccess: number;
499
- currentEvidenceScore: number;
500
- }
501
-
502
- /**
503
- * Compute evidence score decay for unaccessed knowledge.
504
- * Returns the amount to SUBTRACT from evidence_score.
505
- *
506
- * Decay formula: gradual increase after 30 days of no access.
507
- * decay = max(0, (daysSinceAccess - 30) / 365) * 0.2
508
- * Capped so evidence never goes below 0.
509
- */
510
- export function computeDecay(input: DecayInput): number {
511
- const { daysSinceAccess, currentEvidenceScore } = input;
512
-
513
- if (daysSinceAccess <= DECAY_START_DAYS) return 0;
514
-
515
- const rawDecay = ((daysSinceAccess - DECAY_START_DAYS) / 365) * 0.2;
516
- return Math.min(rawDecay, currentEvidenceScore); // never go below 0
517
- }
518
-
519
- interface ArchiveCheck {
520
- evidenceScore: number;
521
- daysSinceCreated: number;
522
- }
523
-
524
- /**
525
- * Determine if a knowledge unit should be archived.
526
- * Archived when evidence < ARCHIVE_THRESHOLD and older than 6 months.
527
- */
528
- export function shouldArchive(check: ArchiveCheck): boolean {
529
- return check.evidenceScore < ARCHIVE_THRESHOLD && check.daysSinceCreated >= ARCHIVE_MIN_AGE_DAYS;
530
- }
531
- ```
532
-
533
- - [ ] **Step 3: Run tests, commit**
534
-
535
- ```bash
536
- git commit -m "feat(cortex): add knowledge decay and archival logic"
537
- ```
538
-
539
- ---
540
-
541
- ## Chunk 3: Gravity Scheduler and Integration
542
-
543
- ### Task 5: Gravity scheduler
544
-
545
- **Files:**
546
- - Create: `src/lib/cortex/gravity/scheduler.ts`
547
- - Create: `tests/lib/cortex/gravity/scheduler.test.ts`
548
-
549
- - [ ] **Step 1: Write failing tests**
550
-
551
- ```typescript
552
- // tests/lib/cortex/gravity/scheduler.test.ts
553
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
554
- import { GravityScheduler } from '@/lib/cortex/gravity/scheduler';
555
-
556
- describe('GravityScheduler', () => {
557
- let scheduler: GravityScheduler;
558
- const mockRunCycle = vi.fn().mockResolvedValue(undefined);
559
-
560
- beforeEach(() => {
561
- vi.useFakeTimers();
562
- scheduler = new GravityScheduler({
563
- intervalMs: 1000, // 1 second for testing (real: 6 hours)
564
- runCycle: mockRunCycle,
565
- });
566
- });
567
-
568
- afterEach(() => {
569
- scheduler.stop();
570
- vi.useRealTimers();
571
- });
572
-
573
- it('starts and runs the first cycle', async () => {
574
- scheduler.start();
575
- expect(scheduler.isRunning()).toBe(true);
576
- // First cycle runs immediately
577
- await vi.advanceTimersByTimeAsync(10);
578
- expect(mockRunCycle).toHaveBeenCalledTimes(1);
579
- });
580
-
581
- it('runs on interval', async () => {
582
- scheduler.start();
583
- await vi.advanceTimersByTimeAsync(10); // first immediate run
584
- await vi.advanceTimersByTimeAsync(1000); // second interval run
585
- expect(mockRunCycle).toHaveBeenCalledTimes(2);
586
- });
587
-
588
- it('stops cleanly', async () => {
589
- scheduler.start();
590
- await vi.advanceTimersByTimeAsync(10);
591
- scheduler.stop();
592
- expect(scheduler.isRunning()).toBe(false);
593
- await vi.advanceTimersByTimeAsync(2000);
594
- expect(mockRunCycle).toHaveBeenCalledTimes(1); // no more runs after stop
595
- });
596
-
597
- it('does not run concurrent cycles', async () => {
598
- let resolveFirst: () => void;
599
- const slowCycle = vi.fn().mockImplementation(() =>
600
- new Promise<void>(resolve => { resolveFirst = resolve; })
601
- );
602
- const slow = new GravityScheduler({ intervalMs: 100, runCycle: slowCycle });
603
- slow.start();
604
- await vi.advanceTimersByTimeAsync(10); // starts first cycle
605
- await vi.advanceTimersByTimeAsync(200); // interval fires but first still running
606
- expect(slowCycle).toHaveBeenCalledTimes(1);
607
- resolveFirst!();
608
- slow.stop();
609
- });
610
-
611
- it('handles cycle errors without crashing', async () => {
612
- const failingCycle = vi.fn().mockRejectedValue(new Error('cycle failed'));
613
- const failing = new GravityScheduler({ intervalMs: 1000, runCycle: failingCycle });
614
- failing.start();
615
- await vi.advanceTimersByTimeAsync(10);
616
- expect(failing.isRunning()).toBe(true); // still running despite error
617
- failing.stop();
618
- });
619
- });
620
- ```
621
-
622
- - [ ] **Step 2: Implement scheduler**
623
-
624
- ```typescript
625
- // src/lib/cortex/gravity/scheduler.ts
626
-
627
- export const GRAVITY_INTERVAL_MS = 6 * 60 * 60 * 1000; // 6 hours
628
-
629
- export interface GravitySchedulerConfig {
630
- intervalMs?: number;
631
- runCycle: () => Promise<void>;
632
- }
633
-
634
- export class GravityScheduler {
635
- private timer: ReturnType<typeof setInterval> | null = null;
636
- private running = false;
637
- private cycling = false;
638
- private config: Required<GravitySchedulerConfig>;
639
-
640
- constructor(config: GravitySchedulerConfig) {
641
- this.config = {
642
- intervalMs: config.intervalMs ?? GRAVITY_INTERVAL_MS,
643
- runCycle: config.runCycle,
644
- };
645
- }
646
-
647
- start(): void {
648
- if (this.running) return;
649
- this.running = true;
650
-
651
- // Run first cycle immediately (non-blocking)
652
- this.executeCycle();
653
-
654
- // Schedule recurring cycles
655
- this.timer = setInterval(() => this.executeCycle(), this.config.intervalMs);
656
- }
657
-
658
- stop(): void {
659
- this.running = false;
660
- if (this.timer) {
661
- clearInterval(this.timer);
662
- this.timer = null;
663
- }
664
- }
665
-
666
- isRunning(): boolean {
667
- return this.running;
668
- }
669
-
670
- private async executeCycle(): Promise<void> {
671
- if (this.cycling) return; // prevent concurrent cycles
672
- this.cycling = true;
673
- try {
674
- await this.config.runCycle();
675
- } catch {
676
- // Log but don't crash — scheduler continues
677
- } finally {
678
- this.cycling = false;
679
- }
680
- }
681
- }
682
- ```
683
-
684
- - [ ] **Step 3: Run tests, commit**
685
-
686
- ```bash
687
- git commit -m "feat(cortex): add gravity scheduler with interval execution"
688
- ```
689
-
690
- ---
691
-
692
- ### Task 6: Barrel export and CortexInstance integration
693
-
694
- **Files:**
695
- - Create: `src/lib/cortex/gravity/index.ts`
696
- - Modify: `src/lib/cortex/index.ts`
697
-
698
- - [ ] **Step 1: Create barrel export**
699
-
700
- ```typescript
701
- // src/lib/cortex/gravity/index.ts
702
- export { computePromotionScore, shouldPromote, getNextLevel, HOP_DECAY, PROMOTION_TYPE_WEIGHTS } from './promotion';
703
- export { getTrickleMode, TRICKLE_DEFAULTS } from './trickle';
704
- export type { TrickleMode } from './trickle';
705
- export { detectSentimentConflict, CONTRADICTION_COSINE_THRESHOLD, DEDUP_COSINE_THRESHOLD } from './contradiction';
706
- export { computeDecay, shouldArchive, ARCHIVE_THRESHOLD } from './decay';
707
- export { GravityScheduler, GRAVITY_INTERVAL_MS } from './scheduler';
708
- export type { GravitySchedulerConfig } from './scheduler';
709
- ```
710
-
711
- - [ ] **Step 2: Add GravityScheduler to CortexInstance**
712
-
713
- Read `src/lib/cortex/index.ts`. Add:
714
-
715
- 1. Import: `import { GravityScheduler } from './gravity/scheduler';`
716
- 2. Add `gravityScheduler?: GravityScheduler` to CortexInstance interface
717
- 3. In getCortex(), after signalPipeline initialization:
718
-
719
- ```typescript
720
- const gravityScheduler = new GravityScheduler({
721
- runCycle: async () => {
722
- // Gravity cycle placeholder — full implementation requires
723
- // scanning all knowledge units, computing promotion scores,
724
- // executing trickle-down, decaying stale knowledge, etc.
725
- // Individual functions are ready; the orchestration wiring
726
- // will be connected when the system has enough data to test.
727
- },
728
- });
729
- // Don't auto-start — let the application decide when to start
730
- ```
731
-
732
- 4. Include `gravityScheduler` in instance object
733
- 5. In `resetCortex()`, add `_instance.gravityScheduler?.stop()` before nulling
734
-
735
- - [ ] **Step 3: Run full test suite**
736
-
737
- ```bash
738
- npx vitest run tests/lib/cortex/
739
- ```
740
-
741
- - [ ] **Step 4: Commit**
742
-
743
- ```bash
744
- git commit -m "feat(cortex): add gravity module barrel export and CortexInstance integration"
745
- ```
746
-
747
- ---
748
-
749
- ## Summary
750
-
751
- | Task | Component | Tests | Status |
752
- |------|-----------|-------|--------|
753
- | 1 | Promotion (bubble-up) | 8 | |
754
- | 2 | Trickle-down | 6 | |
755
- | 3 | Contradiction detection | 5 | |
756
- | 4 | Decay + archival | 8 | |
757
- | 5 | Gravity scheduler | 5 | |
758
- | 6 | Barrel export + integration | regression | |
759
-
760
- **Total: 6 tasks, ~32 new tests, 3 chunks**
761
-
762
- **Key design decisions:**
763
- - Promotion is COPY (not move) — original stays, promoted copy gets decayed confidence (×0.85)
764
- - Trickle-down has two modes: PUSH (copies to lower scopes) and VISIBILITY (accessible via graph but not copied)
765
- - Contradiction detection uses keyword-based sentiment analysis (not LLM) — fast and deterministic
766
- - Decay is gradual — starts after 30 days of no access, increases over time, archives below 0.1 after 6 months
767
- - Scheduler uses setInterval (consistent with FederationSync pattern), prevents concurrent cycles, survives errors
768
- - The runCycle body is a placeholder — individual gravity functions are ready but the full orchestration loop connecting them to store iteration will be wired when there's enough data to test against
1
+ # Cortex v2 — Pillar 6: Gravity System
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:** Implement bi-directional knowledge flow — evidence-based bubble-up promotion, decision trickle-down, conflict detection during ingestion, stale knowledge decay, and a background gravity scheduler that runs every 6 hours.
6
+
7
+ **Architecture:** A new `src/lib/cortex/gravity/` module with four components: `promotion.ts` (bubble-up logic), `trickle.ts` (push-down logic), `contradiction.ts` (ingestion-time conflict detection), and `scheduler.ts` (background timer orchestrating all gravity operations). Uses the `gravity_state` SQLite table (created in Pillar 1) for checkpoint persistence.
8
+
9
+ **Tech Stack:** TypeScript, better-sqlite3, LanceDB, vitest
10
+
11
+ **Spec:** `docs/superpowers/specs/2026-03-14-cortex-v2-design.md` — Pillar 6
12
+
13
+ **Depends on:** All previous pillars (1-5) — completed
14
+
15
+ ---
16
+
17
+ ## File Structure
18
+
19
+ ```
20
+ New files:
21
+ ├── src/lib/cortex/gravity/promotion.ts — Bubble-up: evidence-based promotion
22
+ ├── src/lib/cortex/gravity/trickle.ts — Trickle-down: decision push + visibility
23
+ ├── src/lib/cortex/gravity/contradiction.ts — Ingestion-time conflict detection
24
+ ├── src/lib/cortex/gravity/decay.ts — Stale knowledge decay + archival
25
+ ├── src/lib/cortex/gravity/scheduler.ts — Background scheduler (setInterval)
26
+ ├── src/lib/cortex/gravity/index.ts — Barrel export
27
+
28
+ Modified files:
29
+ ├── src/lib/cortex/index.ts — Add GravityScheduler to CortexInstance
30
+
31
+ Test files:
32
+ ├── tests/lib/cortex/gravity/promotion.test.ts
33
+ ├── tests/lib/cortex/gravity/trickle.test.ts
34
+ ├── tests/lib/cortex/gravity/contradiction.test.ts
35
+ ├── tests/lib/cortex/gravity/decay.test.ts
36
+ ├── tests/lib/cortex/gravity/scheduler.test.ts
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Chunk 1: Promotion and Trickle-Down
42
+
43
+ ### Task 1: Bubble-up promotion logic
44
+
45
+ **Files:**
46
+ - Create: `src/lib/cortex/gravity/promotion.ts`
47
+ - Create: `tests/lib/cortex/gravity/promotion.test.ts`
48
+
49
+ - [ ] **Step 1: Write failing tests**
50
+
51
+ ```typescript
52
+ // tests/lib/cortex/gravity/promotion.test.ts
53
+ import { describe, it, expect } from 'vitest';
54
+ import {
55
+ computePromotionScore,
56
+ shouldPromote,
57
+ PROMOTION_TYPE_WEIGHTS,
58
+ } from '@/lib/cortex/gravity/promotion';
59
+
60
+ describe('computePromotionScore', () => {
61
+ it('computes score from evidence, type weight, and freshness', () => {
62
+ const score = computePromotionScore({
63
+ evidenceScore: 0.8,
64
+ type: 'decision',
65
+ createdDaysAgo: 10,
66
+ });
67
+ // 0.8 * 1.5 (decision weight) * 1.0 (< 30 days) = 1.2 → capped at 1.0
68
+ expect(score).toBeLessThanOrEqual(1.0);
69
+ expect(score).toBeGreaterThan(0.5);
70
+ });
71
+
72
+ it('applies type weights correctly', () => {
73
+ const decision = computePromotionScore({ evidenceScore: 0.5, type: 'decision', createdDaysAgo: 10 });
74
+ const conversation = computePromotionScore({ evidenceScore: 0.5, type: 'conversation', createdDaysAgo: 10 });
75
+ expect(decision).toBeGreaterThan(conversation);
76
+ });
77
+
78
+ it('decays with age', () => {
79
+ const recent = computePromotionScore({ evidenceScore: 0.8, type: 'pattern', createdDaysAgo: 5 });
80
+ const old = computePromotionScore({ evidenceScore: 0.8, type: 'pattern', createdDaysAgo: 120 });
81
+ expect(recent).toBeGreaterThan(old);
82
+ });
83
+ });
84
+
85
+ describe('shouldPromote', () => {
86
+ it('promotes personal→team when score and corroborations meet threshold', () => {
87
+ expect(shouldPromote({
88
+ currentLevel: 'personal',
89
+ promotionScore: 0.7,
90
+ corroborations: 3,
91
+ sensitivity: 'internal',
92
+ hasContradictions: false,
93
+ })).toBe(true);
94
+ });
95
+
96
+ it('blocks promotion when sensitivity is restricted', () => {
97
+ expect(shouldPromote({
98
+ currentLevel: 'personal',
99
+ promotionScore: 0.7,
100
+ corroborations: 3,
101
+ sensitivity: 'restricted',
102
+ hasContradictions: false,
103
+ })).toBe(false);
104
+ });
105
+
106
+ it('blocks promotion when corroborations insufficient', () => {
107
+ expect(shouldPromote({
108
+ currentLevel: 'personal',
109
+ promotionScore: 0.7,
110
+ corroborations: 1, // needs ≥ 2
111
+ sensitivity: 'internal',
112
+ hasContradictions: false,
113
+ })).toBe(false);
114
+ });
115
+
116
+ it('blocks dept→org promotion when contradictions exist', () => {
117
+ expect(shouldPromote({
118
+ currentLevel: 'department',
119
+ promotionScore: 0.95,
120
+ corroborations: 6,
121
+ sensitivity: 'internal',
122
+ hasContradictions: true,
123
+ })).toBe(false);
124
+ });
125
+
126
+ it('requires higher thresholds for higher promotions', () => {
127
+ // Score 0.65 passes personal→team but not team→dept
128
+ expect(shouldPromote({
129
+ currentLevel: 'personal', promotionScore: 0.65, corroborations: 2,
130
+ sensitivity: 'internal', hasContradictions: false,
131
+ })).toBe(true);
132
+
133
+ expect(shouldPromote({
134
+ currentLevel: 'team', promotionScore: 0.65, corroborations: 3,
135
+ sensitivity: 'internal', hasContradictions: false,
136
+ })).toBe(false); // needs ≥ 0.75
137
+ });
138
+ });
139
+ ```
140
+
141
+ - [ ] **Step 2: Implement promotion logic**
142
+
143
+ ```typescript
144
+ // src/lib/cortex/gravity/promotion.ts
145
+ import type { KnowledgeType, ScopeLevel, SensitivityClass } from '../knowledge/types';
146
+
147
+ export const PROMOTION_TYPE_WEIGHTS: Record<string, number> = {
148
+ decision: 1.5,
149
+ error_fix: 1.3,
150
+ pattern: 1.2,
151
+ preference: 1.0,
152
+ code_pattern: 1.0,
153
+ command: 0.8,
154
+ context: 0.7,
155
+ summary: 0.7,
156
+ conversation: 0.5,
157
+ };
158
+
159
+ const FRESHNESS_THRESHOLDS = [
160
+ { maxDays: 30, multiplier: 1.0 },
161
+ { maxDays: 90, multiplier: 0.8 },
162
+ { maxDays: Infinity, multiplier: 0.5 },
163
+ ];
164
+
165
+ interface PromotionScoreInput {
166
+ evidenceScore: number;
167
+ type: string;
168
+ createdDaysAgo: number;
169
+ }
170
+
171
+ export function computePromotionScore(input: PromotionScoreInput): number {
172
+ const typeWeight = PROMOTION_TYPE_WEIGHTS[input.type] ?? 1.0;
173
+ const freshness = FRESHNESS_THRESHOLDS.find(t => input.createdDaysAgo <= t.maxDays)?.multiplier ?? 0.5;
174
+ return Math.min(1.0, input.evidenceScore * typeWeight * freshness);
175
+ }
176
+
177
+ interface PromotionCheck {
178
+ currentLevel: ScopeLevel;
179
+ promotionScore: number;
180
+ corroborations: number;
181
+ sensitivity: string;
182
+ hasContradictions: boolean;
183
+ }
184
+
185
+ const PROMOTION_THRESHOLDS: Record<string, { minScore: number; minCorroborations: number; noContradictions?: boolean }> = {
186
+ personal: { minScore: 0.6, minCorroborations: 2 },
187
+ team: { minScore: 0.75, minCorroborations: 3 },
188
+ department: { minScore: 0.9, minCorroborations: 5, noContradictions: true },
189
+ };
190
+
191
+ const NEXT_LEVEL: Record<string, ScopeLevel> = {
192
+ personal: 'team',
193
+ team: 'department',
194
+ department: 'organization',
195
+ };
196
+
197
+ export function shouldPromote(check: PromotionCheck): boolean {
198
+ const threshold = PROMOTION_THRESHOLDS[check.currentLevel];
199
+ if (!threshold) return false; // organization can't promote further
200
+
201
+ if (check.sensitivity === 'restricted' || check.sensitivity === 'confidential') return false;
202
+ if (check.promotionScore < threshold.minScore) return false;
203
+ if (check.corroborations < threshold.minCorroborations) return false;
204
+ if (threshold.noContradictions && check.hasContradictions) return false;
205
+
206
+ return true;
207
+ }
208
+
209
+ export function getNextLevel(current: ScopeLevel): ScopeLevel | null {
210
+ return NEXT_LEVEL[current] ?? null;
211
+ }
212
+
213
+ export const HOP_DECAY = 0.85;
214
+ ```
215
+
216
+ - [ ] **Step 3: Run tests, commit**
217
+
218
+ ```bash
219
+ git commit -m "feat(cortex): add evidence-based promotion logic for gravity system"
220
+ ```
221
+
222
+ ---
223
+
224
+ ### Task 2: Trickle-down logic
225
+
226
+ **Files:**
227
+ - Create: `src/lib/cortex/gravity/trickle.ts`
228
+ - Create: `tests/lib/cortex/gravity/trickle.test.ts`
229
+
230
+ - [ ] **Step 1: Write failing tests**
231
+
232
+ ```typescript
233
+ // tests/lib/cortex/gravity/trickle.test.ts
234
+ import { describe, it, expect } from 'vitest';
235
+ import { getTrickleMode, TRICKLE_DEFAULTS } from '@/lib/cortex/gravity/trickle';
236
+
237
+ describe('getTrickleMode', () => {
238
+ it('returns PUSH for org decisions', () => {
239
+ expect(getTrickleMode('decision', 'organization')).toBe('push');
240
+ });
241
+
242
+ it('returns PUSH for security policies', () => {
243
+ expect(getTrickleMode('error_fix', 'organization', ['security'])).toBe('push');
244
+ });
245
+
246
+ it('returns VISIBILITY for best practices', () => {
247
+ expect(getTrickleMode('pattern', 'organization')).toBe('visibility');
248
+ });
249
+
250
+ it('returns VISIBILITY for general patterns', () => {
251
+ expect(getTrickleMode('conversation', 'organization')).toBe('visibility');
252
+ });
253
+
254
+ it('returns null for non-org scopes', () => {
255
+ expect(getTrickleMode('decision', 'team')).toBeNull();
256
+ });
257
+
258
+ it('exports trickle defaults table', () => {
259
+ expect(TRICKLE_DEFAULTS).toBeDefined();
260
+ expect(TRICKLE_DEFAULTS.decision).toBe('push');
261
+ expect(TRICKLE_DEFAULTS.pattern).toBe('visibility');
262
+ });
263
+ });
264
+ ```
265
+
266
+ - [ ] **Step 2: Implement trickle-down**
267
+
268
+ ```typescript
269
+ // src/lib/cortex/gravity/trickle.ts
270
+ import type { KnowledgeType, ScopeLevel } from '../knowledge/types';
271
+
272
+ export type TrickleMode = 'push' | 'visibility';
273
+
274
+ export const TRICKLE_DEFAULTS: Record<string, TrickleMode> = {
275
+ decision: 'push',
276
+ preference: 'push',
277
+ error_fix: 'visibility',
278
+ pattern: 'visibility',
279
+ code_pattern: 'visibility',
280
+ command: 'visibility',
281
+ context: 'visibility',
282
+ conversation: 'visibility',
283
+ summary: 'visibility',
284
+ };
285
+
286
+ const SECURITY_TOPICS = ['security', 'vulnerability', 'exploit', 'cve', 'incident'];
287
+
288
+ /**
289
+ * Determine trickle mode for knowledge at a given scope.
290
+ * Only org-level knowledge trickles down.
291
+ * Returns null if knowledge shouldn't trickle (not at org scope).
292
+ */
293
+ export function getTrickleMode(
294
+ type: string,
295
+ scopeLevel: string,
296
+ topics?: string[],
297
+ ): TrickleMode | null {
298
+ // Only org-level knowledge trickles down
299
+ if (scopeLevel !== 'organization') return null;
300
+
301
+ // Security topics always push
302
+ if (topics?.some(t => SECURITY_TOPICS.includes(t.toLowerCase()))) {
303
+ return 'push';
304
+ }
305
+
306
+ return TRICKLE_DEFAULTS[type] ?? 'visibility';
307
+ }
308
+ ```
309
+
310
+ - [ ] **Step 3: Run tests, commit**
311
+
312
+ ```bash
313
+ git commit -m "feat(cortex): add trickle-down logic for gravity system"
314
+ ```
315
+
316
+ ---
317
+
318
+ ## Chunk 2: Contradiction Detection and Decay
319
+
320
+ ### Task 3: Ingestion-time contradiction detection
321
+
322
+ **Files:**
323
+ - Create: `src/lib/cortex/gravity/contradiction.ts`
324
+ - Create: `tests/lib/cortex/gravity/contradiction.test.ts`
325
+
326
+ - [ ] **Step 1: Write failing tests**
327
+
328
+ ```typescript
329
+ // tests/lib/cortex/gravity/contradiction.test.ts
330
+ import { describe, it, expect } from 'vitest';
331
+ import {
332
+ detectSentimentConflict,
333
+ CONTRADICTION_KEYWORDS,
334
+ } from '@/lib/cortex/gravity/contradiction';
335
+
336
+ describe('detectSentimentConflict', () => {
337
+ it('detects opposing sentiments', () => {
338
+ expect(detectSentimentConflict(
339
+ 'increase connection pool size to 50',
340
+ 'do NOT increase pool size, scale horizontally instead',
341
+ )).toBe(true);
342
+ });
343
+
344
+ it('returns false for agreeing statements', () => {
345
+ expect(detectSentimentConflict(
346
+ 'use PostgreSQL for the new service',
347
+ 'PostgreSQL is the right choice for reliability',
348
+ )).toBe(false);
349
+ });
350
+
351
+ it('detects negation patterns', () => {
352
+ expect(detectSentimentConflict(
353
+ 'we should use Redis for caching',
354
+ 'we should not use Redis for caching',
355
+ )).toBe(true);
356
+ });
357
+
358
+ it('detects replacement/alternative patterns', () => {
359
+ expect(detectSentimentConflict(
360
+ 'use Express for the API',
361
+ 'use Fastify instead of Express',
362
+ )).toBe(true);
363
+ });
364
+
365
+ it('returns false for unrelated statements', () => {
366
+ expect(detectSentimentConflict(
367
+ 'the auth service handles JWT',
368
+ 'deploy to production on Fridays',
369
+ )).toBe(false);
370
+ });
371
+ });
372
+ ```
373
+
374
+ - [ ] **Step 2: Implement contradiction detection**
375
+
376
+ ```typescript
377
+ // src/lib/cortex/gravity/contradiction.ts
378
+
379
+ export const CONTRADICTION_KEYWORDS = {
380
+ negation: [/\bnot\b/i, /\bdon't\b/i, /\bdo\s+not\b/i, /\bnever\b/i, /\bavoid\b/i, /\bstop\b/i],
381
+ replacement: [/\binstead\s+of\b/i, /\brather\s+than\b/i, /\breplace\b.*\bwith\b/i, /\bswitch\s+(from|to)\b/i],
382
+ opposition: [/\bhowever\b/i, /\bbut\b/i, /\bcontra/i, /\boppos/i],
383
+ };
384
+
385
+ /**
386
+ * Detect if two texts express conflicting conclusions.
387
+ * Uses keyword-based sentiment analysis (no LLM needed).
388
+ *
389
+ * Returns true if text B appears to contradict text A.
390
+ */
391
+ export function detectSentimentConflict(textA: string, textB: string): boolean {
392
+ const lowerB = textB.toLowerCase();
393
+ const lowerA = textA.toLowerCase();
394
+
395
+ // Check if B contains negation of key terms from A
396
+ const aWords = extractKeyTerms(lowerA);
397
+ const bWords = extractKeyTerms(lowerB);
398
+
399
+ // If B negates something A asserts
400
+ for (const patterns of Object.values(CONTRADICTION_KEYWORDS)) {
401
+ for (const pattern of patterns) {
402
+ if (pattern.test(textB)) {
403
+ // B has negation/replacement language
404
+ // Check if they share subject matter (at least 2 common key terms)
405
+ const commonTerms = aWords.filter(w => bWords.includes(w));
406
+ if (commonTerms.length >= 2) return true;
407
+ }
408
+ }
409
+ }
410
+
411
+ return false;
412
+ }
413
+
414
+ function extractKeyTerms(text: string): string[] {
415
+ const stopWords = new Set(['the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been',
416
+ 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'we', 'should', 'it',
417
+ 'this', 'that', 'and', 'or', 'but', 'not', 'do', 'does', 'did', 'has', 'have', 'had']);
418
+ return text.split(/\W+/).filter(w => w.length > 2 && !stopWords.has(w));
419
+ }
420
+
421
+ export const CONTRADICTION_COSINE_THRESHOLD = 0.80;
422
+ export const DEDUP_COSINE_THRESHOLD = 0.90;
423
+ ```
424
+
425
+ - [ ] **Step 3: Run tests, commit**
426
+
427
+ ```bash
428
+ git commit -m "feat(cortex): add ingestion-time contradiction detection"
429
+ ```
430
+
431
+ ---
432
+
433
+ ### Task 4: Stale knowledge decay
434
+
435
+ **Files:**
436
+ - Create: `src/lib/cortex/gravity/decay.ts`
437
+ - Create: `tests/lib/cortex/gravity/decay.test.ts`
438
+
439
+ - [ ] **Step 1: Write failing tests**
440
+
441
+ ```typescript
442
+ // tests/lib/cortex/gravity/decay.test.ts
443
+ import { describe, it, expect } from 'vitest';
444
+ import { computeDecay, shouldArchive, ARCHIVE_THRESHOLD } from '@/lib/cortex/gravity/decay';
445
+
446
+ describe('computeDecay', () => {
447
+ it('returns 0 decay for recently accessed knowledge', () => {
448
+ expect(computeDecay({ daysSinceAccess: 5, currentEvidenceScore: 0.8 })).toBeCloseTo(0);
449
+ });
450
+
451
+ it('returns small decay for moderately old knowledge', () => {
452
+ const decay = computeDecay({ daysSinceAccess: 60, currentEvidenceScore: 0.8 });
453
+ expect(decay).toBeGreaterThan(0);
454
+ expect(decay).toBeLessThan(0.2);
455
+ });
456
+
457
+ it('returns larger decay for very old knowledge', () => {
458
+ const moderate = computeDecay({ daysSinceAccess: 60, currentEvidenceScore: 0.8 });
459
+ const old = computeDecay({ daysSinceAccess: 180, currentEvidenceScore: 0.8 });
460
+ expect(old).toBeGreaterThan(moderate);
461
+ });
462
+
463
+ it('never makes evidence score negative', () => {
464
+ const decay = computeDecay({ daysSinceAccess: 365, currentEvidenceScore: 0.1 });
465
+ expect(0.1 - decay).toBeGreaterThanOrEqual(0);
466
+ });
467
+ });
468
+
469
+ describe('shouldArchive', () => {
470
+ it('archives units with evidence below threshold after 6 months', () => {
471
+ expect(shouldArchive({ evidenceScore: 0.05, daysSinceCreated: 200 })).toBe(true);
472
+ });
473
+
474
+ it('does not archive recent units even with low evidence', () => {
475
+ expect(shouldArchive({ evidenceScore: 0.05, daysSinceCreated: 30 })).toBe(false);
476
+ });
477
+
478
+ it('does not archive units above threshold', () => {
479
+ expect(shouldArchive({ evidenceScore: 0.5, daysSinceCreated: 200 })).toBe(false);
480
+ });
481
+
482
+ it('uses ARCHIVE_THRESHOLD of 0.1', () => {
483
+ expect(ARCHIVE_THRESHOLD).toBe(0.1);
484
+ });
485
+ });
486
+ ```
487
+
488
+ - [ ] **Step 2: Implement decay**
489
+
490
+ ```typescript
491
+ // src/lib/cortex/gravity/decay.ts
492
+
493
+ export const ARCHIVE_THRESHOLD = 0.1;
494
+ const ARCHIVE_MIN_AGE_DAYS = 180; // 6 months
495
+ const DECAY_START_DAYS = 30; // no decay within first 30 days of last access
496
+
497
+ interface DecayInput {
498
+ daysSinceAccess: number;
499
+ currentEvidenceScore: number;
500
+ }
501
+
502
+ /**
503
+ * Compute evidence score decay for unaccessed knowledge.
504
+ * Returns the amount to SUBTRACT from evidence_score.
505
+ *
506
+ * Decay formula: gradual increase after 30 days of no access.
507
+ * decay = max(0, (daysSinceAccess - 30) / 365) * 0.2
508
+ * Capped so evidence never goes below 0.
509
+ */
510
+ export function computeDecay(input: DecayInput): number {
511
+ const { daysSinceAccess, currentEvidenceScore } = input;
512
+
513
+ if (daysSinceAccess <= DECAY_START_DAYS) return 0;
514
+
515
+ const rawDecay = ((daysSinceAccess - DECAY_START_DAYS) / 365) * 0.2;
516
+ return Math.min(rawDecay, currentEvidenceScore); // never go below 0
517
+ }
518
+
519
+ interface ArchiveCheck {
520
+ evidenceScore: number;
521
+ daysSinceCreated: number;
522
+ }
523
+
524
+ /**
525
+ * Determine if a knowledge unit should be archived.
526
+ * Archived when evidence < ARCHIVE_THRESHOLD and older than 6 months.
527
+ */
528
+ export function shouldArchive(check: ArchiveCheck): boolean {
529
+ return check.evidenceScore < ARCHIVE_THRESHOLD && check.daysSinceCreated >= ARCHIVE_MIN_AGE_DAYS;
530
+ }
531
+ ```
532
+
533
+ - [ ] **Step 3: Run tests, commit**
534
+
535
+ ```bash
536
+ git commit -m "feat(cortex): add knowledge decay and archival logic"
537
+ ```
538
+
539
+ ---
540
+
541
+ ## Chunk 3: Gravity Scheduler and Integration
542
+
543
+ ### Task 5: Gravity scheduler
544
+
545
+ **Files:**
546
+ - Create: `src/lib/cortex/gravity/scheduler.ts`
547
+ - Create: `tests/lib/cortex/gravity/scheduler.test.ts`
548
+
549
+ - [ ] **Step 1: Write failing tests**
550
+
551
+ ```typescript
552
+ // tests/lib/cortex/gravity/scheduler.test.ts
553
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
554
+ import { GravityScheduler } from '@/lib/cortex/gravity/scheduler';
555
+
556
+ describe('GravityScheduler', () => {
557
+ let scheduler: GravityScheduler;
558
+ const mockRunCycle = vi.fn().mockResolvedValue(undefined);
559
+
560
+ beforeEach(() => {
561
+ vi.useFakeTimers();
562
+ scheduler = new GravityScheduler({
563
+ intervalMs: 1000, // 1 second for testing (real: 6 hours)
564
+ runCycle: mockRunCycle,
565
+ });
566
+ });
567
+
568
+ afterEach(() => {
569
+ scheduler.stop();
570
+ vi.useRealTimers();
571
+ });
572
+
573
+ it('starts and runs the first cycle', async () => {
574
+ scheduler.start();
575
+ expect(scheduler.isRunning()).toBe(true);
576
+ // First cycle runs immediately
577
+ await vi.advanceTimersByTimeAsync(10);
578
+ expect(mockRunCycle).toHaveBeenCalledTimes(1);
579
+ });
580
+
581
+ it('runs on interval', async () => {
582
+ scheduler.start();
583
+ await vi.advanceTimersByTimeAsync(10); // first immediate run
584
+ await vi.advanceTimersByTimeAsync(1000); // second interval run
585
+ expect(mockRunCycle).toHaveBeenCalledTimes(2);
586
+ });
587
+
588
+ it('stops cleanly', async () => {
589
+ scheduler.start();
590
+ await vi.advanceTimersByTimeAsync(10);
591
+ scheduler.stop();
592
+ expect(scheduler.isRunning()).toBe(false);
593
+ await vi.advanceTimersByTimeAsync(2000);
594
+ expect(mockRunCycle).toHaveBeenCalledTimes(1); // no more runs after stop
595
+ });
596
+
597
+ it('does not run concurrent cycles', async () => {
598
+ let resolveFirst: () => void;
599
+ const slowCycle = vi.fn().mockImplementation(() =>
600
+ new Promise<void>(resolve => { resolveFirst = resolve; })
601
+ );
602
+ const slow = new GravityScheduler({ intervalMs: 100, runCycle: slowCycle });
603
+ slow.start();
604
+ await vi.advanceTimersByTimeAsync(10); // starts first cycle
605
+ await vi.advanceTimersByTimeAsync(200); // interval fires but first still running
606
+ expect(slowCycle).toHaveBeenCalledTimes(1);
607
+ resolveFirst!();
608
+ slow.stop();
609
+ });
610
+
611
+ it('handles cycle errors without crashing', async () => {
612
+ const failingCycle = vi.fn().mockRejectedValue(new Error('cycle failed'));
613
+ const failing = new GravityScheduler({ intervalMs: 1000, runCycle: failingCycle });
614
+ failing.start();
615
+ await vi.advanceTimersByTimeAsync(10);
616
+ expect(failing.isRunning()).toBe(true); // still running despite error
617
+ failing.stop();
618
+ });
619
+ });
620
+ ```
621
+
622
+ - [ ] **Step 2: Implement scheduler**
623
+
624
+ ```typescript
625
+ // src/lib/cortex/gravity/scheduler.ts
626
+
627
+ export const GRAVITY_INTERVAL_MS = 6 * 60 * 60 * 1000; // 6 hours
628
+
629
+ export interface GravitySchedulerConfig {
630
+ intervalMs?: number;
631
+ runCycle: () => Promise<void>;
632
+ }
633
+
634
+ export class GravityScheduler {
635
+ private timer: ReturnType<typeof setInterval> | null = null;
636
+ private running = false;
637
+ private cycling = false;
638
+ private config: Required<GravitySchedulerConfig>;
639
+
640
+ constructor(config: GravitySchedulerConfig) {
641
+ this.config = {
642
+ intervalMs: config.intervalMs ?? GRAVITY_INTERVAL_MS,
643
+ runCycle: config.runCycle,
644
+ };
645
+ }
646
+
647
+ start(): void {
648
+ if (this.running) return;
649
+ this.running = true;
650
+
651
+ // Run first cycle immediately (non-blocking)
652
+ this.executeCycle();
653
+
654
+ // Schedule recurring cycles
655
+ this.timer = setInterval(() => this.executeCycle(), this.config.intervalMs);
656
+ }
657
+
658
+ stop(): void {
659
+ this.running = false;
660
+ if (this.timer) {
661
+ clearInterval(this.timer);
662
+ this.timer = null;
663
+ }
664
+ }
665
+
666
+ isRunning(): boolean {
667
+ return this.running;
668
+ }
669
+
670
+ private async executeCycle(): Promise<void> {
671
+ if (this.cycling) return; // prevent concurrent cycles
672
+ this.cycling = true;
673
+ try {
674
+ await this.config.runCycle();
675
+ } catch {
676
+ // Log but don't crash — scheduler continues
677
+ } finally {
678
+ this.cycling = false;
679
+ }
680
+ }
681
+ }
682
+ ```
683
+
684
+ - [ ] **Step 3: Run tests, commit**
685
+
686
+ ```bash
687
+ git commit -m "feat(cortex): add gravity scheduler with interval execution"
688
+ ```
689
+
690
+ ---
691
+
692
+ ### Task 6: Barrel export and CortexInstance integration
693
+
694
+ **Files:**
695
+ - Create: `src/lib/cortex/gravity/index.ts`
696
+ - Modify: `src/lib/cortex/index.ts`
697
+
698
+ - [ ] **Step 1: Create barrel export**
699
+
700
+ ```typescript
701
+ // src/lib/cortex/gravity/index.ts
702
+ export { computePromotionScore, shouldPromote, getNextLevel, HOP_DECAY, PROMOTION_TYPE_WEIGHTS } from './promotion';
703
+ export { getTrickleMode, TRICKLE_DEFAULTS } from './trickle';
704
+ export type { TrickleMode } from './trickle';
705
+ export { detectSentimentConflict, CONTRADICTION_COSINE_THRESHOLD, DEDUP_COSINE_THRESHOLD } from './contradiction';
706
+ export { computeDecay, shouldArchive, ARCHIVE_THRESHOLD } from './decay';
707
+ export { GravityScheduler, GRAVITY_INTERVAL_MS } from './scheduler';
708
+ export type { GravitySchedulerConfig } from './scheduler';
709
+ ```
710
+
711
+ - [ ] **Step 2: Add GravityScheduler to CortexInstance**
712
+
713
+ Read `src/lib/cortex/index.ts`. Add:
714
+
715
+ 1. Import: `import { GravityScheduler } from './gravity/scheduler';`
716
+ 2. Add `gravityScheduler?: GravityScheduler` to CortexInstance interface
717
+ 3. In getCortex(), after signalPipeline initialization:
718
+
719
+ ```typescript
720
+ const gravityScheduler = new GravityScheduler({
721
+ runCycle: async () => {
722
+ // Gravity cycle placeholder — full implementation requires
723
+ // scanning all knowledge units, computing promotion scores,
724
+ // executing trickle-down, decaying stale knowledge, etc.
725
+ // Individual functions are ready; the orchestration wiring
726
+ // will be connected when the system has enough data to test.
727
+ },
728
+ });
729
+ // Don't auto-start — let the application decide when to start
730
+ ```
731
+
732
+ 4. Include `gravityScheduler` in instance object
733
+ 5. In `resetCortex()`, add `_instance.gravityScheduler?.stop()` before nulling
734
+
735
+ - [ ] **Step 3: Run full test suite**
736
+
737
+ ```bash
738
+ npx vitest run tests/lib/cortex/
739
+ ```
740
+
741
+ - [ ] **Step 4: Commit**
742
+
743
+ ```bash
744
+ git commit -m "feat(cortex): add gravity module barrel export and CortexInstance integration"
745
+ ```
746
+
747
+ ---
748
+
749
+ ## Summary
750
+
751
+ | Task | Component | Tests | Status |
752
+ |------|-----------|-------|--------|
753
+ | 1 | Promotion (bubble-up) | 8 | |
754
+ | 2 | Trickle-down | 6 | |
755
+ | 3 | Contradiction detection | 5 | |
756
+ | 4 | Decay + archival | 8 | |
757
+ | 5 | Gravity scheduler | 5 | |
758
+ | 6 | Barrel export + integration | regression | |
759
+
760
+ **Total: 6 tasks, ~32 new tests, 3 chunks**
761
+
762
+ **Key design decisions:**
763
+ - Promotion is COPY (not move) — original stays, promoted copy gets decayed confidence (×0.85)
764
+ - Trickle-down has two modes: PUSH (copies to lower scopes) and VISIBILITY (accessible via graph but not copied)
765
+ - Contradiction detection uses keyword-based sentiment analysis (not LLM) — fast and deterministic
766
+ - Decay is gradual — starts after 30 days of no access, increases over time, archives below 0.1 after 6 months
767
+ - Scheduler uses setInterval (consistent with FederationSync pattern), prevents concurrent cycles, survives errors
768
+ - The runCycle body is a placeholder — individual gravity functions are ready but the full orchestration loop connecting them to store iteration will be wired when there's enough data to test against