@polderlabs/bizar 10.2.0 → 10.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/README.md +31 -8
  2. package/bizar-dash/CONTROL_SURFACES.md +0 -1
  3. package/bizar-dash/dist/assets/{ActivityFeed-JjmOY2AQ.js → ActivityFeed-xXiUCZLB.js} +1 -1
  4. package/bizar-dash/dist/assets/{ActivityFeed-JjmOY2AQ.js.map → ActivityFeed-xXiUCZLB.js.map} +1 -1
  5. package/bizar-dash/dist/assets/{ActivityView-BIIMvGWo.js → ActivityView-nOYhCp3h.js} +1 -1
  6. package/bizar-dash/dist/assets/{ActivityView-BIIMvGWo.js.map → ActivityView-nOYhCp3h.js.map} +1 -1
  7. package/bizar-dash/dist/assets/{AdminView-DRidJtkq.js → AdminView-Coi4V3sq.js} +1 -1
  8. package/bizar-dash/dist/assets/{AdminView-DRidJtkq.js.map → AdminView-Coi4V3sq.js.map} +1 -1
  9. package/bizar-dash/dist/assets/{AgentActivity-79l4SBMC.js → AgentActivity-nEri4lbx.js} +1 -1
  10. package/bizar-dash/dist/assets/{AgentActivity-79l4SBMC.js.map → AgentActivity-nEri4lbx.js.map} +1 -1
  11. package/bizar-dash/dist/assets/{AgentsView-0vT4uPSc.js → AgentsView-ByiIJ0ej.js} +3 -3
  12. package/bizar-dash/dist/assets/{AgentsView-0vT4uPSc.js.map → AgentsView-ByiIJ0ej.js.map} +1 -1
  13. package/bizar-dash/dist/assets/{Alert-CG5q_s75.js → Alert-Dg_Vwxh5.js} +1 -1
  14. package/bizar-dash/dist/assets/{Alert-CG5q_s75.js.map → Alert-Dg_Vwxh5.js.map} +1 -1
  15. package/bizar-dash/dist/assets/{ArtifactsView-DM8ZmpR9.js → ArtifactsView-CGclRNnz.js} +1 -1
  16. package/bizar-dash/dist/assets/{ArtifactsView-DM8ZmpR9.js.map → ArtifactsView-CGclRNnz.js.map} +1 -1
  17. package/bizar-dash/dist/assets/{AuthView-BveN94MC.js → AuthView-utVm6M3D.js} +1 -1
  18. package/bizar-dash/dist/assets/{AuthView-BveN94MC.js.map → AuthView-utVm6M3D.js.map} +1 -1
  19. package/bizar-dash/dist/assets/{Avatar-ulUPIYTd.js → Avatar-CXDZdKy4.js} +1 -1
  20. package/bizar-dash/dist/assets/{Avatar-ulUPIYTd.js.map → Avatar-CXDZdKy4.js.map} +1 -1
  21. package/bizar-dash/dist/assets/{BackgroundJobsView-BWErhqFo.js → BackgroundJobsView-j603pz6o.js} +1 -1
  22. package/bizar-dash/dist/assets/{BackgroundJobsView-BWErhqFo.js.map → BackgroundJobsView-j603pz6o.js.map} +1 -1
  23. package/bizar-dash/dist/assets/{BackupView-CnBjzG9N.js → BackupView-DgvnntTE.js} +1 -1
  24. package/bizar-dash/dist/assets/{BackupView-CnBjzG9N.js.map → BackupView-DgvnntTE.js.map} +1 -1
  25. package/bizar-dash/dist/assets/{Card-B0imhxMk.js → Card-D9019JOD.js} +1 -1
  26. package/bizar-dash/dist/assets/{Card-B0imhxMk.js.map → Card-D9019JOD.js.map} +1 -1
  27. package/bizar-dash/dist/assets/{ChatView-D6zGytzx.js → ChatView-C0cTgj5d.js} +1 -1
  28. package/bizar-dash/dist/assets/{ChatView-D6zGytzx.js.map → ChatView-C0cTgj5d.js.map} +1 -1
  29. package/bizar-dash/dist/assets/{Chip-wwZSGwLE.js → Chip-DQtalZ4y.js} +1 -1
  30. package/bizar-dash/dist/assets/{Chip-wwZSGwLE.js.map → Chip-DQtalZ4y.js.map} +1 -1
  31. package/bizar-dash/dist/assets/{ClaudeSessionsView-DK1sOLhi.js → ClaudeSessionsView-H3Bqjo6b.js} +1 -1
  32. package/bizar-dash/dist/assets/{ClaudeSessionsView-DK1sOLhi.js.map → ClaudeSessionsView-H3Bqjo6b.js.map} +1 -1
  33. package/bizar-dash/dist/assets/{ClipboardView-CZ2lYPr0.js → ClipboardView-BAguaKbx.js} +1 -1
  34. package/bizar-dash/dist/assets/{ClipboardView-CZ2lYPr0.js.map → ClipboardView-BAguaKbx.js.map} +1 -1
  35. package/bizar-dash/dist/assets/{ConfigView-D-zT9eNA.js → ConfigView-DWHJgoe8.js} +1 -1
  36. package/bizar-dash/dist/assets/{ConfigView-D-zT9eNA.js.map → ConfigView-DWHJgoe8.js.map} +1 -1
  37. package/bizar-dash/dist/assets/{DiagnosticsView-BocV68Lb.js → DiagnosticsView-oCT624hk.js} +1 -1
  38. package/bizar-dash/dist/assets/{DiagnosticsView-BocV68Lb.js.map → DiagnosticsView-oCT624hk.js.map} +1 -1
  39. package/bizar-dash/dist/assets/{DialogsView-BVjPI5x7.js → DialogsView-CqHNals_.js} +1 -1
  40. package/bizar-dash/dist/assets/{DialogsView-BVjPI5x7.js.map → DialogsView-CqHNals_.js.map} +1 -1
  41. package/bizar-dash/dist/assets/{DoctorView-84gJcZwM.js → DoctorView-6kfQq_Mx.js} +1 -1
  42. package/bizar-dash/dist/assets/{DoctorView-84gJcZwM.js.map → DoctorView-6kfQq_Mx.js.map} +1 -1
  43. package/bizar-dash/dist/assets/{EmptyState-BjgVOrcO.js → EmptyState-DLmtBX_6.js} +1 -1
  44. package/bizar-dash/dist/assets/{EmptyState-BjgVOrcO.js.map → EmptyState-DLmtBX_6.js.map} +1 -1
  45. package/bizar-dash/dist/assets/{EnvVarsView-BJ2TEzF7.js → EnvVarsView-DySOXlP1.js} +2 -2
  46. package/bizar-dash/dist/assets/{EnvVarsView-BJ2TEzF7.js.map → EnvVarsView-DySOXlP1.js.map} +1 -1
  47. package/bizar-dash/dist/assets/{ErrorState-BE3WBFqF.js → ErrorState-Bump8diE.js} +1 -1
  48. package/bizar-dash/dist/assets/{ErrorState-BE3WBFqF.js.map → ErrorState-Bump8diE.js.map} +1 -1
  49. package/bizar-dash/dist/assets/{EvalView-BJJ2P-kK.js → EvalView-FnZ5d93z.js} +1 -1
  50. package/bizar-dash/dist/assets/{EvalView-BJJ2P-kK.js.map → EvalView-FnZ5d93z.js.map} +1 -1
  51. package/bizar-dash/dist/assets/{GoalsView-pwROHApi.js → GoalsView-C4m1WnVv.js} +1 -1
  52. package/bizar-dash/dist/assets/{GoalsView-pwROHApi.js.map → GoalsView-C4m1WnVv.js.map} +1 -1
  53. package/bizar-dash/dist/assets/{Grid-qcvbhx6e.js → Grid-dEnoGGws.js} +1 -1
  54. package/bizar-dash/dist/assets/{Grid-qcvbhx6e.js.map → Grid-dEnoGGws.js.map} +1 -1
  55. package/bizar-dash/dist/assets/{HistoryView-C7SSOLJA.js → HistoryView-xdRybjZ2.js} +1 -1
  56. package/bizar-dash/dist/assets/{HistoryView-C7SSOLJA.js.map → HistoryView-xdRybjZ2.js.map} +1 -1
  57. package/bizar-dash/dist/assets/{Input-Bgzxf_Hu.js → Input-BSa3lh_-.js} +1 -1
  58. package/bizar-dash/dist/assets/{Input-Bgzxf_Hu.js.map → Input-BSa3lh_-.js.map} +1 -1
  59. package/bizar-dash/dist/assets/{LibrariesView-CbFFksox.js → LibrariesView-1zR04Eci.js} +1 -1
  60. package/bizar-dash/dist/assets/{LibrariesView-CbFFksox.js.map → LibrariesView-1zR04Eci.js.map} +1 -1
  61. package/bizar-dash/dist/assets/{LightRAGView-BqDrJbRq.js → LightRAGView-PubmA9oL.js} +1 -1
  62. package/bizar-dash/dist/assets/{LightRAGView-BqDrJbRq.js.map → LightRAGView-PubmA9oL.js.map} +1 -1
  63. package/bizar-dash/dist/assets/{ListHeader-TjPJrUfY.js → ListHeader-Ak9WJd39.js} +1 -1
  64. package/bizar-dash/dist/assets/{ListHeader-TjPJrUfY.js.map → ListHeader-Ak9WJd39.js.map} +1 -1
  65. package/bizar-dash/dist/assets/{MemoryView-BlTeHLhX.js → MemoryView-DBGpuETw.js} +1 -1
  66. package/bizar-dash/dist/assets/{MemoryView-BlTeHLhX.js.map → MemoryView-DBGpuETw.js.map} +1 -1
  67. package/bizar-dash/dist/assets/MiscView-DufqBHkX.js +1 -0
  68. package/bizar-dash/dist/assets/{MiscView-B8QY82Pm.js.map → MiscView-DufqBHkX.js.map} +1 -1
  69. package/bizar-dash/dist/assets/{ModsView-CvW1OWts.js → ModsView-DcX6eVU2.js} +2 -2
  70. package/bizar-dash/dist/assets/{ModsView-CvW1OWts.js.map → ModsView-DcX6eVU2.js.map} +1 -1
  71. package/bizar-dash/dist/assets/{NotificationsView-CsBt5U7x.js → NotificationsView-B8IhHRQC.js} +1 -1
  72. package/bizar-dash/dist/assets/{NotificationsView-CsBt5U7x.js.map → NotificationsView-B8IhHRQC.js.map} +1 -1
  73. package/bizar-dash/dist/assets/ObsidianView-DEuk65zS.js +1 -0
  74. package/bizar-dash/dist/assets/{ObsidianView-BCTejEj2.js.map → ObsidianView-DEuk65zS.js.map} +1 -1
  75. package/bizar-dash/dist/assets/{OverviewView-BsuPxwnB.js → OverviewView-CTI2spTd.js} +1 -1
  76. package/bizar-dash/dist/assets/{OverviewView-BsuPxwnB.js.map → OverviewView-CTI2spTd.js.map} +1 -1
  77. package/bizar-dash/dist/assets/{ProgressBar-DlZTETEn.js → ProgressBar-D3lkz42E.js} +1 -1
  78. package/bizar-dash/dist/assets/{ProgressBar-DlZTETEn.js.map → ProgressBar-D3lkz42E.js.map} +1 -1
  79. package/bizar-dash/dist/assets/{ProjectsView-Soxtmpet.js → ProjectsView-Du0LzE7A.js} +1 -1
  80. package/bizar-dash/dist/assets/{ProjectsView-Soxtmpet.js.map → ProjectsView-Du0LzE7A.js.map} +1 -1
  81. package/bizar-dash/dist/assets/{ProvidersView-DaCEV9pM.js → ProvidersView-5bCgXwBo.js} +1 -1
  82. package/bizar-dash/dist/assets/{ProvidersView-DaCEV9pM.js.map → ProvidersView-5bCgXwBo.js.map} +1 -1
  83. package/bizar-dash/dist/assets/{SchedulesView-DY2ByBj_.js → SchedulesView-DFHdIz5P.js} +1 -1
  84. package/bizar-dash/dist/assets/{SchedulesView-DY2ByBj_.js.map → SchedulesView-DFHdIz5P.js.map} +1 -1
  85. package/bizar-dash/dist/assets/{Select-Dbd88_n8.js → Select-C8EJj4NM.js} +1 -1
  86. package/bizar-dash/dist/assets/{Select-Dbd88_n8.js.map → Select-C8EJj4NM.js.map} +1 -1
  87. package/bizar-dash/dist/assets/{SettingsRow-CLMNd434.js → SettingsRow-BdOOmYMD.js} +1 -1
  88. package/bizar-dash/dist/assets/{SettingsRow-CLMNd434.js.map → SettingsRow-BdOOmYMD.js.map} +1 -1
  89. package/bizar-dash/dist/assets/{SettingsView-b24oFq9x.js → SettingsView-CqwQ6Knv.js} +1 -1
  90. package/bizar-dash/dist/assets/{SettingsView-b24oFq9x.js.map → SettingsView-CqwQ6Knv.js.map} +1 -1
  91. package/bizar-dash/dist/assets/{Sheet-DnDid58j.js → Sheet-Cztsvgse.js} +1 -1
  92. package/bizar-dash/dist/assets/{Sheet-DnDid58j.js.map → Sheet-Cztsvgse.js.map} +1 -1
  93. package/bizar-dash/dist/assets/{Slider-BJCvKI1I.js → Slider-BexNfF6K.js} +1 -1
  94. package/bizar-dash/dist/assets/{Slider-BJCvKI1I.js.map → Slider-BexNfF6K.js.map} +1 -1
  95. package/bizar-dash/dist/assets/{Sparkline-ktqQLdyb.js → Sparkline-CLZBtvsN.js} +1 -1
  96. package/bizar-dash/dist/assets/{Sparkline-ktqQLdyb.js.map → Sparkline-CLZBtvsN.js.map} +1 -1
  97. package/bizar-dash/dist/assets/{Switch-CwXfsDii.js → Switch-B1tiRwNK.js} +1 -1
  98. package/bizar-dash/dist/assets/{Switch-CwXfsDii.js.map → Switch-B1tiRwNK.js.map} +1 -1
  99. package/bizar-dash/dist/assets/{TasksView-BHmpzFCf.js → TasksView-CT0fPlos.js} +1 -1
  100. package/bizar-dash/dist/assets/{TasksView-BHmpzFCf.js.map → TasksView-CT0fPlos.js.map} +1 -1
  101. package/bizar-dash/dist/assets/{Textarea-BzIAwSlp.js → Textarea-D_TPpVMy.js} +1 -1
  102. package/bizar-dash/dist/assets/{Textarea-BzIAwSlp.js.map → Textarea-D_TPpVMy.js.map} +1 -1
  103. package/bizar-dash/dist/assets/{UpdateView-CSmX9NN0.js → UpdateView-tD2q2OhW.js} +1 -1
  104. package/bizar-dash/dist/assets/{UpdateView-CSmX9NN0.js.map → UpdateView-tD2q2OhW.js.map} +1 -1
  105. package/bizar-dash/dist/assets/{UsageView-COyr_Gfi.js → UsageView-B4BuAFKA.js} +1 -1
  106. package/bizar-dash/dist/assets/{UsageView-COyr_Gfi.js.map → UsageView-B4BuAFKA.js.map} +1 -1
  107. package/bizar-dash/dist/assets/{ViewHeader-BzYZ3m-e.js → ViewHeader-V_SzbUpw.js} +1 -1
  108. package/bizar-dash/dist/assets/{ViewHeader-BzYZ3m-e.js.map → ViewHeader-V_SzbUpw.js.map} +1 -1
  109. package/bizar-dash/dist/assets/{VoiceView-D33_xG5t.js → VoiceView-D3vb5OM2.js} +1 -1
  110. package/bizar-dash/dist/assets/{VoiceView-D33_xG5t.js.map → VoiceView-D3vb5OM2.js.map} +1 -1
  111. package/bizar-dash/dist/assets/{brain-CM-Vls8r.js → brain-BmfWcitQ.js} +1 -1
  112. package/bizar-dash/dist/assets/{brain-CM-Vls8r.js.map → brain-BmfWcitQ.js.map} +1 -1
  113. package/bizar-dash/dist/assets/{calendar-C0lgZk69.js → calendar-VntJUzFB.js} +1 -1
  114. package/bizar-dash/dist/assets/{calendar-C0lgZk69.js.map → calendar-VntJUzFB.js.map} +1 -1
  115. package/bizar-dash/dist/assets/{circle-Bx_hQEBC.js → circle-KrQQySeK.js} +1 -1
  116. package/bizar-dash/dist/assets/{circle-Bx_hQEBC.js.map → circle-KrQQySeK.js.map} +1 -1
  117. package/bizar-dash/dist/assets/{circle-alert-DHvsqpw5.js → circle-alert-CQ9MLygI.js} +1 -1
  118. package/bizar-dash/dist/assets/{circle-alert-DHvsqpw5.js.map → circle-alert-CQ9MLygI.js.map} +1 -1
  119. package/bizar-dash/dist/assets/{circle-check-Bx8wmXR9.js → circle-check-COtVgsWw.js} +1 -1
  120. package/bizar-dash/dist/assets/{circle-check-Bx8wmXR9.js.map → circle-check-COtVgsWw.js.map} +1 -1
  121. package/bizar-dash/dist/assets/{clock-CejGoecX.js → clock-C0GlM4qp.js} +1 -1
  122. package/bizar-dash/dist/assets/{clock-CejGoecX.js.map → clock-C0GlM4qp.js.map} +1 -1
  123. package/bizar-dash/dist/assets/{download-4cEUWue1.js → download-CW4DmtRe.js} +1 -1
  124. package/bizar-dash/dist/assets/{download-4cEUWue1.js.map → download-CW4DmtRe.js.map} +1 -1
  125. package/bizar-dash/dist/assets/{external-link-0NqUhI4i.js → external-link-CAOnh_DH.js} +1 -1
  126. package/bizar-dash/dist/assets/{external-link-0NqUhI4i.js.map → external-link-CAOnh_DH.js.map} +1 -1
  127. package/bizar-dash/dist/assets/{file-text-yEMkrSoZ.js → file-text-CS1jB_oV.js} +1 -1
  128. package/bizar-dash/dist/assets/{file-text-yEMkrSoZ.js.map → file-text-CS1jB_oV.js.map} +1 -1
  129. package/bizar-dash/dist/assets/{filter-BXt60zAS.js → filter-DyQbml3L.js} +1 -1
  130. package/bizar-dash/dist/assets/{filter-BXt60zAS.js.map → filter-DyQbml3L.js.map} +1 -1
  131. package/bizar-dash/dist/assets/{git-pull-request-BjG5lNtR.js → git-pull-request-Co6gYfba.js} +1 -1
  132. package/bizar-dash/dist/assets/{git-pull-request-BjG5lNtR.js.map → git-pull-request-Co6gYfba.js.map} +1 -1
  133. package/bizar-dash/dist/assets/{main-CokHAXWM.js → main-CyAIirBB.js} +28 -33
  134. package/bizar-dash/dist/assets/main-CyAIirBB.js.map +1 -0
  135. package/bizar-dash/dist/assets/network-CDn43Gsj.js +6 -0
  136. package/bizar-dash/dist/assets/network-CDn43Gsj.js.map +1 -0
  137. package/bizar-dash/dist/assets/{pause-CAmulU0F.js → pause-CKYjSTGX.js} +1 -1
  138. package/bizar-dash/dist/assets/{pause-CAmulU0F.js.map → pause-CKYjSTGX.js.map} +1 -1
  139. package/bizar-dash/dist/assets/{pencil-eq5IqBmU.js → pencil-BUJ2DpWs.js} +1 -1
  140. package/bizar-dash/dist/assets/{pencil-eq5IqBmU.js.map → pencil-BUJ2DpWs.js.map} +1 -1
  141. package/bizar-dash/dist/assets/{play-BoLrrcBA.js → play-CGxZWqtW.js} +1 -1
  142. package/bizar-dash/dist/assets/{play-BoLrrcBA.js.map → play-CGxZWqtW.js.map} +1 -1
  143. package/bizar-dash/dist/assets/{plug-DBrVM9lK.js → plug-CQYGgGSy.js} +1 -1
  144. package/bizar-dash/dist/assets/{plug-DBrVM9lK.js.map → plug-CQYGgGSy.js.map} +1 -1
  145. package/bizar-dash/dist/assets/{plus-DENm0hqV.js → plus-fFxt-8z5.js} +1 -1
  146. package/bizar-dash/dist/assets/{plus-DENm0hqV.js.map → plus-fFxt-8z5.js.map} +1 -1
  147. package/bizar-dash/dist/assets/{power-DLjXF7zE.js → power-Cjgy2KsI.js} +1 -1
  148. package/bizar-dash/dist/assets/{power-DLjXF7zE.js.map → power-Cjgy2KsI.js.map} +1 -1
  149. package/bizar-dash/dist/assets/{power-off-D47cOnG_.js → power-off-B81hLRah.js} +1 -1
  150. package/bizar-dash/dist/assets/{power-off-D47cOnG_.js.map → power-off-B81hLRah.js.map} +1 -1
  151. package/bizar-dash/dist/assets/{refresh-ccw-DNrXX9gB.js → refresh-ccw-BCXx86xp.js} +1 -1
  152. package/bizar-dash/dist/assets/{refresh-ccw-DNrXX9gB.js.map → refresh-ccw-BCXx86xp.js.map} +1 -1
  153. package/bizar-dash/dist/assets/{refresh-cw-CoAHDpeS.js → refresh-cw-COTg1nZo.js} +1 -1
  154. package/bizar-dash/dist/assets/{refresh-cw-CoAHDpeS.js.map → refresh-cw-COTg1nZo.js.map} +1 -1
  155. package/bizar-dash/dist/assets/{rotate-ccw-ObX5awaG.js → rotate-ccw-BZrEVc0Z.js} +1 -1
  156. package/bizar-dash/dist/assets/{rotate-ccw-ObX5awaG.js.map → rotate-ccw-BZrEVc0Z.js.map} +1 -1
  157. package/bizar-dash/dist/assets/{rotate-cw-xpPJw9LP.js → rotate-cw-CsTtaLV2.js} +1 -1
  158. package/bizar-dash/dist/assets/{rotate-cw-xpPJw9LP.js.map → rotate-cw-CsTtaLV2.js.map} +1 -1
  159. package/bizar-dash/dist/assets/{save-D1iKiJJl.js → save-DtMTge1F.js} +1 -1
  160. package/bizar-dash/dist/assets/{save-D1iKiJJl.js.map → save-DtMTge1F.js.map} +1 -1
  161. package/bizar-dash/dist/assets/{send-BRcAhZUm.js → send-DyBhyk8t.js} +1 -1
  162. package/bizar-dash/dist/assets/{send-BRcAhZUm.js.map → send-DyBhyk8t.js.map} +1 -1
  163. package/bizar-dash/dist/assets/{shield-alert-C6vEcK-g.js → shield-alert-BPGJlRF8.js} +1 -1
  164. package/bizar-dash/dist/assets/{shield-alert-C6vEcK-g.js.map → shield-alert-BPGJlRF8.js.map} +1 -1
  165. package/bizar-dash/dist/assets/{trash-2-DZDjEnNh.js → trash-2-2NsyTU8c.js} +1 -1
  166. package/bizar-dash/dist/assets/{trash-2-DZDjEnNh.js.map → trash-2-2NsyTU8c.js.map} +1 -1
  167. package/bizar-dash/dist/assets/{trending-up-DMj-AJVf.js → trending-up-BXwP23VK.js} +1 -1
  168. package/bizar-dash/dist/assets/{trending-up-DMj-AJVf.js.map → trending-up-BXwP23VK.js.map} +1 -1
  169. package/bizar-dash/dist/assets/{triangle-alert-_2xe_tl4.js → triangle-alert-DFmQ_RXN.js} +1 -1
  170. package/bizar-dash/dist/assets/{triangle-alert-_2xe_tl4.js.map → triangle-alert-DFmQ_RXN.js.map} +1 -1
  171. package/bizar-dash/dist/assets/{upload-DdDljAeV.js → upload-Cj-HYRYV.js} +1 -1
  172. package/bizar-dash/dist/assets/{upload-DdDljAeV.js.map → upload-Cj-HYRYV.js.map} +1 -1
  173. package/bizar-dash/dist/assets/{zap-mHsgh0FP.js → zap-BaOiybcl.js} +1 -1
  174. package/bizar-dash/dist/assets/{zap-mHsgh0FP.js.map → zap-BaOiybcl.js.map} +1 -1
  175. package/bizar-dash/dist/index.html +1 -1
  176. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  177. package/bizar-dash/src/server/routes/update.mjs +48 -21
  178. package/bizar-dash/src/web/v8/App.tsx +0 -4
  179. package/bizar-dash/src/web/v8/__tests__/new-views.test.tsx +0 -17
  180. package/bizar-dash/src/web/v8/shell/Sidebar.tsx +0 -1
  181. package/bizar-dash/src/web/v8/views/Router.tsx +0 -5
  182. package/bizar-dash/tests/_update-test-helpers.mjs +13 -0
  183. package/bizar-dash/tests/update-check.test.mjs +18 -13
  184. package/bizar-dash/tests/update-packages.test.mjs +154 -0
  185. package/bizar-dash/tests/update-run.test.mjs +17 -80
  186. package/cli/banner.mjs +1 -1
  187. package/cli/bin.mjs +8 -1
  188. package/cli/bootstrap.mjs +1 -1
  189. package/cli/commands/claude-cmd.mjs +1 -1
  190. package/cli/commands/deploy/docker.mjs +0 -3
  191. package/cli/install/banner.mjs +67 -0
  192. package/cli/install/banner.test.mjs +39 -0
  193. package/cli/install/index.mjs +32 -0
  194. package/cli/install/index.test.mjs +61 -0
  195. package/cli/install/paths.mjs +80 -0
  196. package/cli/install/paths.test.mjs +77 -0
  197. package/cli/install/plugin.mjs +161 -0
  198. package/cli/install/postinstall.mjs +111 -0
  199. package/cli/install.mjs +13 -600
  200. package/cli/migrate.mjs +157 -0
  201. package/cli/migrate.test.mjs +85 -0
  202. package/cli/provision.mjs +615 -1918
  203. package/cli/provision.test.mjs +1 -1
  204. package/cli/service-controller.test.mjs +0 -1
  205. package/cli/service-env.mjs +0 -1
  206. package/cli/utils.mjs +0 -1
  207. package/install.sh +54 -466
  208. package/package.json +1 -1
  209. package/packages/sdk/package.json +1 -1
  210. package/scripts/install-curl.sh +17 -0
  211. package/bizar-dash/dist/assets/HeadroomView-D1UiTYbt.js +0 -11
  212. package/bizar-dash/dist/assets/HeadroomView-D1UiTYbt.js.map +0 -1
  213. package/bizar-dash/dist/assets/MiscView-B8QY82Pm.js +0 -1
  214. package/bizar-dash/dist/assets/ObsidianView-BCTejEj2.js +0 -1
  215. package/bizar-dash/dist/assets/main-CokHAXWM.js.map +0 -1
  216. package/bizar-dash/skills/headroom/SKILL.md +0 -94
  217. package/bizar-dash/src/server/headroom.mjs +0 -649
  218. package/bizar-dash/src/server/routes/headroom.mjs +0 -126
  219. package/bizar-dash/src/web/v8/views/Headroom/HeadroomView.tsx +0 -201
  220. package/bizar-dash/tests/graphify-mod-spawn.node.test.mjs +0 -90
  221. package/bizar-dash/tests/headroom-install.test.mjs +0 -173
  222. package/bizar-dash/tests/headroom-settings.test.mjs +0 -126
  223. package/bizar-dash/tests/headroom-status.test.mjs +0 -117
  224. package/bizar-dash/tests/v7-archive/mobile-overview.test.tsx +0 -214
  225. package/bizar-dash/tests/v7-archive/mobile-settings.test.tsx +0 -181
  226. package/bizar-dash/tests/v7-archive/navigation/CommandPalette.test.tsx +0 -105
  227. package/bizar-dash/tests/v7-archive/settings-nav.test.tsx +0 -128
  228. package/bizar-dash/tests/v7-archive/views/Overview.test.tsx +0 -413
  229. package/cli/commands/headroom.mjs +0 -204
  230. package/cli/provision-claude.mjs +0 -1176
@@ -8,7 +8,6 @@ import { UsageView } from '../views/Usage/UsageView.js';
8
8
  import { BackupView } from '../views/Backup/BackupView.js';
9
9
  import { NotificationsView } from '../views/Notifications/NotificationsView.js';
10
10
  import { DiagnosticsView } from '../views/Diagnostics/DiagnosticsView.js';
11
- import { HeadroomView } from '../views/Headroom/HeadroomView.js';
12
11
  import { EvalView } from '../views/Eval/EvalView.js';
13
12
 
14
13
  /**
@@ -140,22 +139,6 @@ describe('DiagnosticsView (S35)', () => {
140
139
  });
141
140
  });
142
141
 
143
- describe('HeadroomView (S35)', () => {
144
- it('shows status + controls + stats', async () => {
145
- installFetchMock([
146
- { match: (u) => u.endsWith('/api/headroom/status'), run: () => ({ status: 'not-installed' }) },
147
- { match: (u) => u.includes('/api/headroom/stats'), run: () => ({ hours: 24, requests: 142, tokensSaved: 1234, cacheHits: 12, cacheMisses: 4 }) },
148
- { match: (u) => u.endsWith('/api/headroom/install'), run: () => ({ ok: true }) },
149
- { match: () => true, run: () => ({}) },
150
- ]);
151
- render(<Providers><HeadroomView /></Providers>);
152
- expect(await screen.findByText('not-installed')).toBeTruthy();
153
- expect(screen.getByText('142')).toBeTruthy();
154
- expect(screen.getByText('1234')).toBeTruthy();
155
- expect(screen.getByTestId('headroom-install')).toBeTruthy();
156
- });
157
- });
158
-
159
142
  describe('EvalView (S35)', () => {
160
143
  it('lists runs + launches a suite via POST /api/eval/run', async () => {
161
144
  const { calls } = installFetchMock([
@@ -167,7 +167,6 @@ const DEFAULT_SECTIONS: SidebarSection[] = [
167
167
  { id: 'backup', label: 'Backups', icon: Archive },
168
168
  { id: 'notifications', label: 'Notifications', icon: Bell },
169
169
  { id: 'diagnostics', label: 'Diagnostics', icon: Terminal },
170
- { id: 'headroom', label: 'Headroom', icon: Network },
171
170
  { id: 'eval', label: 'Eval', icon: FlaskConical },
172
171
  { id: 'settings', label: 'Settings', icon: SettingsIcon },
173
172
  ],
@@ -57,9 +57,6 @@ const NotificationsView = lazy(() =>
57
57
  const DiagnosticsView = lazy(() =>
58
58
  import('./Diagnostics/DiagnosticsView.js').then((m) => ({ default: m.DiagnosticsView })),
59
59
  );
60
- const HeadroomView = lazy(() =>
61
- import('./Headroom/HeadroomView.js').then((m) => ({ default: m.HeadroomView })),
62
- );
63
60
  const EvalView = lazy(() =>
64
61
  import('./Eval/EvalView.js').then((m) => ({ default: m.EvalView })),
65
62
  );
@@ -160,8 +157,6 @@ export function useViewForId(id: string): JSX.Element {
160
157
  return <NotificationsView />;
161
158
  case 'diagnostics':
162
159
  return <DiagnosticsView />;
163
- case 'headroom':
164
- return <HeadroomView />;
165
160
  case 'eval':
166
161
  return <EvalView />;
167
162
  case 'chat':
@@ -0,0 +1,13 @@
1
+ /**
2
+ * _update-test-helpers.mjs — shared test helpers for update route tests.
3
+ *
4
+ * Exports a pre-loaded module instance so all test files share the same
5
+ * module state (important for ESM module caching in Node.js).
6
+ */
7
+ import { resolve } from 'node:path';
8
+
9
+ const REPO = resolve(import.meta.dirname, '..', '..');
10
+
11
+ export const { createUpdateRouter, resetUpdateCache, resetConcurrencyGuard } = await import(
12
+ `${REPO}/bizar-dash/src/server/routes/update.mjs`
13
+ );
@@ -16,7 +16,7 @@ import { resolve } from 'node:path';
16
16
  const REPO = resolve(import.meta.dirname, '..', '..');
17
17
 
18
18
  const { createUpdateRouter, resetUpdateCache } = await import(
19
- `${REPO}/bizar-dash/src/server/routes/update.mjs`
19
+ './_update-test-helpers.mjs'
20
20
  );
21
21
 
22
22
  let app;
@@ -64,34 +64,39 @@ describe('update.mjs — /api/updates/status', () => {
64
64
  it('returns the installed package map', async () => {
65
65
  const res = await request(app, 'GET', '/api/updates/status');
66
66
  assert.equal(res.status, 200);
67
- assert.ok(res.body.current, 'response should have current field');
68
- assert.equal(typeof res.body.current, 'object');
69
- for (const id of ['bizar', 'bizar-dash', 'bizar-plugin']) {
70
- assert.ok(id in res.body.current, `current.${id} should be a key`);
67
+ assert.ok(res.body.installed, 'response should have installed field');
68
+ assert.equal(typeof res.body.installed, 'object');
69
+ for (const id of ['bizar', 'bizar-sdk', 'claude-agent', 'claude-code']) {
70
+ assert.ok(id in res.body.installed, `installed.${id} should be a key`);
71
71
  assert.ok(
72
- res.body.current[id] === null || typeof res.body.current[id] === 'string',
73
- `current.${id} should be string or null`,
72
+ res.body.installed[id] === null || typeof res.body.installed[id] === 'string',
73
+ `installed.${id} should be string or null`,
74
74
  );
75
75
  }
76
76
  });
77
77
 
78
- it('does not include latest/hasUpdates fields', async () => {
78
+ it('does not include latest/hasUpdates/available fields', async () => {
79
79
  const res = await request(app, 'GET', '/api/updates/status');
80
80
  assert.equal(res.status, 200);
81
81
  assert.equal(res.body.latest, undefined, 'status should not include latest');
82
82
  assert.equal(res.body.hasUpdates, undefined, 'status should not include hasUpdates');
83
+ assert.equal(res.body.available, undefined, 'status should not include available');
83
84
  });
84
85
  });
85
86
 
86
87
  describe('update.mjs — /api/updates/check', () => {
87
- it('returns shape { current, latest, hasUpdates }', async () => {
88
+ it('returns shape { installed, available, hasUpdates, channel }', async () => {
88
89
  const res = await request(app, 'GET', '/api/updates/check');
89
90
  assert.equal(res.status, 200);
90
- assert.ok(res.body.current, 'should have current');
91
- assert.ok(res.body.latest, 'should have latest');
91
+ assert.ok(res.body.installed, 'should have installed');
92
+ assert.ok(res.body.available, 'should have available');
93
+ assert.equal(typeof res.body.available, 'object');
94
+ assert.ok('stable' in res.body.available, 'available should have stable key');
95
+ assert.ok('beta' in res.body.available, 'available should have beta key');
92
96
  assert.equal(typeof res.body.hasUpdates, 'boolean');
93
- for (const id of ['bizar', 'bizar-dash', 'bizar-plugin']) {
94
- assert.ok(id in res.body.latest, `latest.${id} should be a key`);
97
+ assert.equal(res.body.channel, 'stable');
98
+ for (const id of ['bizar', 'bizar-sdk', 'claude-agent', 'claude-code']) {
99
+ assert.ok(id in res.body.installed, `installed.${id} should be a key`);
95
100
  }
96
101
  });
97
102
 
@@ -0,0 +1,154 @@
1
+ /**
2
+ * update-packages.test.mjs — tests for the v10.3.0 package list and channel selection.
3
+ *
4
+ * Run with: node --test bizar-dash/tests/update-packages.test.mjs
5
+ *
6
+ * Strategy: test HTTP response shapes + response fields without needing to
7
+ * patch spawn. The channel selection is encoded in the POST response body
8
+ * (channel field) and the concurrency guard (runningSince) is checked from
9
+ * the 409 response. The actual npm spawn behavior is tested in
10
+ * update-run.test.mjs which has the proper spawn interception setup.
11
+ */
12
+ import { describe, it, beforeEach } from 'node:test';
13
+ import assert from 'node:assert/strict';
14
+ import express from 'express';
15
+ import { resolve } from 'node:path';
16
+
17
+ const REPO = resolve(import.meta.dirname, '..', '..');
18
+
19
+ const { createUpdateRouter, resetUpdateCache, resetConcurrencyGuard } = await import(
20
+ `${REPO}/bizar-dash/src/server/routes/update.mjs`
21
+ );
22
+
23
+ // ─── HTTP helper ─────────────────────────────────────────────────────────────
24
+
25
+ async function request(app, method, path, body) {
26
+ const http = await import('node:http');
27
+ return new Promise((resolveP, reject) => {
28
+ const server = app.listen(0, '127.0.0.1', () => {
29
+ const { port } = server.address();
30
+ const bodyStr = body ? JSON.stringify(body) : '';
31
+ const req = http.request({
32
+ hostname: '127.0.0.1',
33
+ port,
34
+ path,
35
+ method,
36
+ headers: bodyStr
37
+ ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(bodyStr) }
38
+ : {},
39
+ }, (res) => {
40
+ let data = '';
41
+ res.on('data', (c) => { data += c; });
42
+ res.on('end', () => {
43
+ server.close();
44
+ try {
45
+ resolveP({ status: res.statusCode, body: JSON.parse(data) });
46
+ } catch {
47
+ resolveP({ status: res.statusCode, body: data });
48
+ }
49
+ });
50
+ });
51
+ req.on('error', (err) => { server.close(); reject(err); });
52
+ if (bodyStr) req.write(bodyStr);
53
+ req.end();
54
+ });
55
+ });
56
+ }
57
+
58
+ // ─── Tests ─────────────────────────────────────────────────────────────────
59
+
60
+ describe('update.mjs — v10.3.0 package list', () => {
61
+ it('returns exactly 4 packages (bizar, bizar-sdk, claude-agent, claude-code)', async () => {
62
+ resetUpdateCache();
63
+ const app = express();
64
+ app.use(express.json());
65
+ app.use('/api', createUpdateRouter({ broadcast: () => {} }));
66
+
67
+ const res = await request(app, 'GET', '/api/updates/status');
68
+ assert.equal(res.status, 200);
69
+ assert.ok(res.body.installed, 'should have installed field');
70
+
71
+ const ids = Object.keys(res.body.installed).sort();
72
+ assert.deepEqual(ids.sort(), ['bizar', 'bizar-sdk', 'claude-agent', 'claude-code'].sort());
73
+ assert.ok(!ids.includes('bizar-dash'), 'bizar-dash should not be present');
74
+ assert.ok(!ids.includes('bizar-plugin'), 'bizar-plugin should not be present');
75
+ });
76
+ });
77
+
78
+ describe('update.mjs — channel selection', () => {
79
+ let app;
80
+
81
+ beforeEach(() => {
82
+ resetUpdateCache();
83
+ resetConcurrencyGuard();
84
+ const localApp = express();
85
+ localApp.use(express.json());
86
+ localApp.use('/api', createUpdateRouter({ broadcast: () => {} }));
87
+ app = localApp;
88
+ });
89
+
90
+ it('POST with channel=beta returns 202 and reflects channel=beta in body', async () => {
91
+ const res = await request(app, 'POST', '/api/updates/apply', {
92
+ packages: ['bizar'],
93
+ channel: 'beta',
94
+ });
95
+ // Returns 202 (npm may not be on PATH in test env, so accept 500 too)
96
+ assert.ok([202, 500].includes(res.status), `unexpected status ${res.status}`);
97
+ if (res.status === 202) {
98
+ assert.equal(res.body.channel, 'beta', 'response should reflect channel=beta');
99
+ }
100
+ });
101
+
102
+ it('POST without channel returns 202 and reflects channel=stable in body', async () => {
103
+ const res = await request(app, 'POST', '/api/updates/apply', {
104
+ packages: ['bizar'],
105
+ });
106
+ assert.ok([202, 500].includes(res.status), `unexpected status ${res.status}`);
107
+ if (res.status === 202) {
108
+ assert.equal(res.body.channel, 'stable', 'default channel should be stable');
109
+ }
110
+ });
111
+ });
112
+
113
+ describe('update.mjs — concurrency guard returns runningSince', () => {
114
+ it('second concurrent POST returns 409 with runningSince ISO8601 timestamp', async () => {
115
+ resetUpdateCache();
116
+ resetConcurrencyGuard();
117
+ const localApp = express();
118
+ localApp.use(express.json());
119
+ localApp.use('/api', createUpdateRouter({ broadcast: () => {} }));
120
+
121
+ // First request may succeed or fail depending on npm availability
122
+ const first = await request(localApp, 'POST', '/api/updates/apply', { packages: ['bizar'] });
123
+ assert.ok([202, 500].includes(first.status), `first status unexpected: ${first.status}`);
124
+
125
+ // Second concurrent request should always hit the guard (regardless of npm availability)
126
+ const second = await request(localApp, 'POST', '/api/updates/apply', { packages: ['bizar'] });
127
+ assert.equal(second.status, 409, 'second request should get 409');
128
+ assert.equal(second.body.error, 'already_running');
129
+ assert.ok('runningSince' in second.body, 'response should include runningSince');
130
+ assert.ok(second.body.runningSince !== null, 'runningSince should not be null');
131
+ assert.match(
132
+ second.body.runningSince,
133
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/,
134
+ 'runningSince should be ISO8601',
135
+ );
136
+ });
137
+ });
138
+
139
+ describe('update.mjs — /check returns stable and beta in available', () => {
140
+ it('GET /api/updates/check includes available.stable and available.beta', async () => {
141
+ resetUpdateCache();
142
+ const app = express();
143
+ app.use(express.json());
144
+ app.use('/api', createUpdateRouter({ broadcast: () => {} }));
145
+
146
+ const res = await request(app, 'GET', '/api/updates/check');
147
+ assert.equal(res.status, 200);
148
+ assert.ok(res.body.available, 'should have available field');
149
+ assert.ok('stable' in res.body.available, 'available should have stable key');
150
+ assert.ok('beta' in res.body.available, 'available should have beta key');
151
+ // Both may be null if npm registry is unreachable, but keys must be present
152
+ assert.equal(typeof res.body.available.stable, 'string');
153
+ });
154
+ });
@@ -8,7 +8,7 @@
8
8
  * exit code. Capture the broadcast channel's emitted messages and
9
9
  * assert they fire in the documented order.
10
10
  */
11
- import { describe, it, beforeEach } from 'node:test';
11
+ import { describe, it, beforeEach, afterEach } from 'node:test';
12
12
  import assert from 'node:assert/strict';
13
13
  import express from 'express';
14
14
  import { EventEmitter } from 'node:events';
@@ -17,10 +17,14 @@ import { resolve } from 'node:path';
17
17
 
18
18
  const REPO = resolve(import.meta.dirname, '..', '..');
19
19
 
20
- // ─── Spawn fake ────────────────────────────────────────────────────────────
21
- // We monkey-patch the module loader's view of `node:child_process` so
22
- // that update.mjs's `import { spawn } from 'node:child_process'` resolves
23
- // to our fake.
20
+ // ─── Dynamic import to get fresh module (bypasses ESM static-capture) ─────────
21
+
22
+ async function importUpdateModuleFresh() {
23
+ const url = `${REPO}/bizar-dash/src/server/routes/update.mjs?fresh=${Date.now()}-${Math.random()}`;
24
+ return import(url);
25
+ }
26
+
27
+ // ─── Spawn fake ─────────────────────────────────────────────────────────────
24
28
 
25
29
  class FakeChildProcess extends EventEmitter {
26
30
  constructor() {
@@ -28,7 +32,6 @@ class FakeChildProcess extends EventEmitter {
28
32
  this.stdout = new Readable({ read() {} });
29
33
  this.stderr = new Readable({ read() {} });
30
34
  }
31
- // Helpers for tests
32
35
  emitStdout(line) { this.stdout.push(line + '\n'); }
33
36
  emitStderr(line) { this.stderr.push(line + '\n'); }
34
37
  finish(code = 0) {
@@ -36,9 +39,7 @@ class FakeChildProcess extends EventEmitter {
36
39
  this.stderr.push(null);
37
40
  this.emit('close', code);
38
41
  }
39
- failWith(err) {
40
- this.emit('error', err);
41
- }
42
+ failWith(err) { this.emit('error', err); }
42
43
  }
43
44
 
44
45
  let fakeProc = null;
@@ -49,37 +50,9 @@ function makeFakeSpawn() {
49
50
  };
50
51
  }
51
52
 
52
- // Install the fake by intercepting `node:child_process`. We do this by
53
- // rewriting `Module._resolveFilename` for one test at a time.
54
53
  import { createRequire } from 'node:module';
55
54
  const require = createRequire(import.meta.url);
56
55
 
57
- let originalLoad;
58
- let patched = false;
59
- function installFakeSpawn() {
60
- if (patched) return;
61
- // Override via global require cache: pre-populate the require cache
62
- // for `node:child_process` with a stub module.
63
- const realChild = require('node:child_process');
64
- const stub = { ...realChild, spawn: makeFakeSpawn() };
65
- require.cache[require.resolve('node:child_process')] = {
66
- id: 'node:child_process',
67
- filename: 'node:child_process',
68
- loaded: true,
69
- exports: stub,
70
- };
71
- patched = true;
72
- }
73
-
74
- // Load update.mjs once after we've patched child_process. We do this
75
- // dynamically so the import picks up the stubbed `spawn` from the
76
- // require cache that ESM bridges through.
77
- //
78
- // NOTE: ESM `import` does NOT use the require cache, so the patch above
79
- // only works for CommonJS callers of `child_process`. The route imports
80
- // `spawn` from `node:child_process` directly via ESM. To make this test
81
- // work, we patch the actual child_process module's `spawn` property at
82
- // runtime instead.
83
56
  function patchSpawnDirectly() {
84
57
  const cp = require('node:child_process');
85
58
  cp.__originalSpawn = cp.__originalSpawn || cp.spawn;
@@ -94,25 +67,6 @@ function unpatchSpawn() {
94
67
  fakeProc = null;
95
68
  }
96
69
 
97
- // Now we need the route to use the patched spawn. update.mjs does:
98
- // import { spawn, execFileSync } from 'node:child_process';
99
- // In Node.js, ESM imports for built-in modules go through the loader,
100
- // which uses a private internal cache separate from the CommonJS
101
- // require cache. So patching require.cache alone won't redirect ESM.
102
- //
103
- // The reliable approach is to use a loader hook. For simplicity in
104
- // this test, we instead use module-aliasing via a wrapper: we use a
105
- // small middleware-only test that monkey-patches spawn on the imported
106
- // module instance directly. Since the same module instance is shared
107
- // across imports within a process, this works after first import.
108
-
109
- async function importUpdateModuleFresh() {
110
- // Use a query string to force re-import. ESM treats query strings as
111
- // distinct specifiers, so this gives us a fresh module instance.
112
- const url = `${REPO}/bizar-dash/src/server/routes/update.mjs?case=${Date.now()}-${Math.random()}`;
113
- return import(url);
114
- }
115
-
116
70
  // ─── App setup ─────────────────────────────────────────────────────────────
117
71
 
118
72
  function setupApp(broadcast) {
@@ -163,14 +117,8 @@ function waitFor(predicate, { timeoutMs = 4000, intervalMs = 10 } = {}) {
163
117
  return new Promise((resolveP, reject) => {
164
118
  const start = Date.now();
165
119
  const tick = () => {
166
- if (predicate()) {
167
- resolveP();
168
- return;
169
- }
170
- if (Date.now() - start > timeoutMs) {
171
- reject(new Error(`waitFor timed out after ${timeoutMs}ms`));
172
- return;
173
- }
120
+ if (predicate()) { resolveP(); return; }
121
+ if (Date.now() - start > timeoutMs) { reject(new Error(`waitFor timed out after ${timeoutMs}ms`)); return; }
174
122
  setTimeout(tick, intervalMs);
175
123
  };
176
124
  tick();
@@ -186,40 +134,37 @@ describe('update.mjs — apply run broadcasts events in order', () => {
186
134
  broadcast = [];
187
135
  });
188
136
 
137
+ afterEach(() => {
138
+ unpatchSpawn();
139
+ });
140
+
189
141
  it('emits starting → log → done → complete for a successful install', async () => {
190
142
  const { app } = await setupApp((msg) => broadcast.push(msg));
191
143
  const res = await request(app, 'POST', '/api/updates/apply', { packages: ['bizar'] });
192
144
  assert.equal(res.status, 202);
193
145
  assert.deepEqual(res.body.started, ['bizar']);
194
146
 
195
- // The first event should be a `starting` progress for `bizar`
196
147
  await waitFor(() => broadcast.length >= 1);
197
148
  assert.equal(broadcast[0].type, 'update:progress');
198
149
  assert.equal(broadcast[0].pkg, 'bizar');
199
150
  assert.equal(broadcast[0].status, 'starting');
200
151
 
201
- // Now drive the fake spawn to emit log lines + finish
202
152
  assert.ok(fakeProc, 'fakeProc should exist after request');
203
153
  fakeProc.emitStdout('npm WARN deprecated foo');
204
154
  fakeProc.emitStdout('added 1 package in 2s');
205
155
  fakeProc.finish(0);
206
156
 
207
- // Wait for the complete event
208
157
  await waitFor(() => broadcast.some((m) => m.type === 'update:complete'), { timeoutMs: 5000 });
209
158
 
210
- // Verify ordering and types
211
159
  const types = broadcast.map((m) => `${m.type}${m.pkg ? `:${m.pkg}` : ''}:${m.status ?? ''}`);
212
160
  assert.ok(types.includes('update:progress:bizar:starting'), 'should have starting progress');
213
161
  assert.ok(types.includes('update:log:bizar:'), 'should have at least one log');
214
162
  assert.ok(types.includes('update:progress:bizar:done'), 'should have done progress');
215
163
  assert.ok(types.at(-1) === 'update:complete:', 'last event should be update:complete');
216
164
 
217
- // Done event should carry newVersion
218
165
  const doneEvent = broadcast.find((m) => m.type === 'update:progress' && m.status === 'done');
219
166
  assert.ok(doneEvent, 'done event should exist');
220
167
  assert.ok('newVersion' in doneEvent, 'done event should carry newVersion field');
221
-
222
- unpatchSpawn();
223
168
  });
224
169
 
225
170
  it('emits error progress + complete when npm exits non-zero', async () => {
@@ -241,26 +186,18 @@ describe('update.mjs — apply run broadcasts events in order', () => {
241
186
 
242
187
  const lastEvent = broadcast.at(-1);
243
188
  assert.equal(lastEvent.type, 'update:complete');
244
-
245
- unpatchSpawn();
246
189
  });
247
190
 
248
191
  it('returns 409 when an apply is already running', async () => {
249
192
  const { app } = await setupApp(() => {});
250
- // First call — kicks off the run but the fake proc never closes,
251
- // so the run is "active" for the duration of the test.
252
193
  const first = await request(app, 'POST', '/api/updates/apply', { packages: ['bizar'] });
253
194
  assert.equal(first.status, 202);
254
195
 
255
- // Second call — should hit the concurrency guard
256
196
  const second = await request(app, 'POST', '/api/updates/apply', { packages: ['bizar'] });
257
197
  assert.equal(second.status, 409);
258
198
  assert.equal(second.body.error, 'already_running');
259
199
 
260
- // Cleanup: close the fake proc so the run's finally clears the guard
261
200
  if (fakeProc) fakeProc.finish(0);
262
- // Give the async run a moment to clear
263
201
  await new Promise((r) => setTimeout(r, 50));
264
- unpatchSpawn();
265
202
  });
266
- });
203
+ });
package/cli/banner.mjs CHANGED
@@ -25,7 +25,7 @@ export function showBanner() {
25
25
  console.log(chalk.hex('#6366f1').bold(RUNE_HELM));
26
26
  console.log(chalk.hex('#a855f7')(' Norse Pantheon Agent System for cline'));
27
27
  console.log();
28
- console.log(chalk.dim(' 13 agents · 4 cost tiers · Obsidian vault long-term memory · Headroom · Semble · Skills CLI · Mods'));
28
+ console.log(chalk.dim(' 13 agents · 4 cost tiers · Obsidian vault long-term memory · Semble · Skills CLI · Mods'));
29
29
  console.log();
30
30
  }
31
31
 
package/cli/bin.mjs CHANGED
@@ -90,7 +90,7 @@ if (
90
90
  !process.env.BIZAR_SKIP_BUILD
91
91
  ) {
92
92
  try {
93
- const { buildSdk, buildPlugin } = await import('./provision-claude.mjs');
93
+ const { buildSdk, buildPlugin } = await import('./provision.mjs');
94
94
  const sdkRes = await buildSdk();
95
95
  if (sdkRes.ok && !sdkRes.skipped) {
96
96
  console.error(chalk.dim(` → ${sdkRes.message}`));
@@ -124,6 +124,7 @@ function showHelp() {
124
124
 
125
125
  Commands:
126
126
  install Run the interactive installer
127
+ migrate Migrate legacy ~/.config/cline/ or ~/.config/bizar/ to ~/.claude/
127
128
  audit Run security audit on agent configuration
128
129
  init Initialize .bizar/ in current project
129
130
  export [target] Export agents/rules to another harness
@@ -293,6 +294,12 @@ async function main() {
293
294
  break;
294
295
  }
295
296
 
297
+ case 'migrate': {
298
+ const { runMigrate } = await import('./migrate.mjs');
299
+ await runMigrate(cmdArgs);
300
+ break;
301
+ }
302
+
296
303
  case 'service': {
297
304
  const mod = await importCommand('service');
298
305
  if (!mod) {
package/cli/bootstrap.mjs CHANGED
@@ -49,7 +49,7 @@ export function checkSetupStatus() {
49
49
  */
50
50
  function printSetupBanner() {
51
51
  // Use console.log directly to avoid chalk formatting issues in non-TTY
52
- console.log('\n ⚡ First-time setup — Bizar needs to install agents, plugin, Headroom, Semble, Skills CLI...\n');
52
+ console.log('\n ⚡ First-time setup — Bizar needs to install agents, plugin, Semble, Skills CLI...\n');
53
53
  }
54
54
 
55
55
  /**
@@ -49,7 +49,7 @@ const CLAUDE_BIN = process.env.CLAUDE_BIN || 'claude';
49
49
  *
50
50
  * Mirrors Claude Code's own resolver. Used so all subcommands
51
51
  * delegate to the same `~/.claude/` directory that the rest of the
52
- * Bizar harness writes to via `cli/provision-claude.mjs`.
52
+ * Bizar harness writes to via `cli/provision.mjs`.
53
53
  */
54
54
  export function resolveClaudeDir() {
55
55
  if (process.env.CLAUDE_CONFIG_DIR && process.env.CLAUDE_CONFIG_DIR.trim()) {
@@ -74,9 +74,6 @@ function generateComposeScaffold(outDir, opts) {
74
74
  '# Tailscale (optional)',
75
75
  '# TAILSCALE_AUTHKEY=tskey-auth-xxxxxxxxxxxxxxxxxxxx',
76
76
  '',
77
- '# Headroom context compression (optional)',
78
- '# HEADROOM_ENABLED=1',
79
- '',
80
77
  ].join('\n');
81
78
  writeFileSync(join(scaffoldRoot, '.env.template'), envTemplate);
82
79
 
@@ -0,0 +1,67 @@
1
+ /**
2
+ * cli/install/banner.mjs
3
+ *
4
+ * Banner, pantheon card, and section heading for the install flow.
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+
9
+ const RUNE_HELM = `
10
+ ██████╗ ██╗██╗ ██╗ █████╗ ██████╗
11
+ ██╔══██╗██║██║ ██║██╔══██╗██╔══██╗
12
+ ██████╔╝██║███████║███████║██████╔╝
13
+ ██╔══██╗██║╚════██║██╔══██║██╔══██╗
14
+ ██████╔╝██║ ██║██║ ██║██║ ██║
15
+ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
16
+ `;
17
+
18
+ const PANTHEON = `
19
+ ╔══════════════════════════════════════════╗
20
+ ║ ║
21
+ ║ ᛟ Odin ᛗ Mimir ᚹ Heimdall ║
22
+ ║ ᚱ Hermod ᚦ Thor ᛏ Tyr ║
23
+ ║ ᛉ Vidarr ᚨ Forseti ᛒ Baldr ║
24
+ ║ ║
25
+ ╚══════════════════════════════════════════╝
26
+ `;
27
+
28
+ const TAGLINE = '14 agents · 6 cost tiers · dashboard · Obsidian vault long-term memory · Mods · Skills CLI';
29
+
30
+ export const palette = {
31
+ primary: chalk.hex('#6366f1'),
32
+ success: chalk.green,
33
+ warn: chalk.yellow,
34
+ error: chalk.red,
35
+ dim: chalk.dim,
36
+ };
37
+
38
+ /**
39
+ * Print the Bizar mark + tagline.
40
+ * @param {string} [version] - Optional version string to prepend.
41
+ */
42
+ export function showBanner(version) {
43
+ if (version) {
44
+ console.log(chalk.bold.hex('#6366f1')(`\n ⚡ BizarHarness v${version}\n`));
45
+ } else {
46
+ console.log(chalk.bold.hex('#6366f1')(RUNE_HELM));
47
+ console.log(chalk.hex('#a855f7')(' Norse Pantheon Agent System for Claude Code'));
48
+ }
49
+ console.log();
50
+ console.log(chalk.dim(` ${TAGLINE}`));
51
+ console.log();
52
+ }
53
+
54
+ /** Print the Norse pantheon card. */
55
+ export function showPantheon() {
56
+ console.log(chalk.hex('#312e81')(PANTHEON));
57
+ }
58
+
59
+ /**
60
+ * Print a section header divider.
61
+ * @param {string} text - Section title.
62
+ */
63
+ export function sectionHeading(text) {
64
+ console.log();
65
+ console.log(chalk.bold.hex('#6366f1')(` ── ${text} ──`));
66
+ console.log();
67
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * cli/install/banner.test.mjs
3
+ *
4
+ * Tests for cli/install/banner.mjs
5
+ */
6
+ import { test, describe } from 'node:test';
7
+ import assert from 'node:assert/strict';
8
+ import { showBanner, showPantheon, sectionHeading, palette } from './banner.mjs';
9
+
10
+ describe('showBanner()', () => {
11
+ test('does not throw', () => {
12
+ assert.doesNotThrow(() => showBanner());
13
+ });
14
+
15
+ test('does not throw with version', () => {
16
+ assert.doesNotThrow(() => showBanner('10.0.0'));
17
+ });
18
+ });
19
+
20
+ describe('palette', () => {
21
+ test('has all 5 required keys', () => {
22
+ const required = ['primary', 'success', 'warn', 'error', 'dim'];
23
+ for (const key of required) {
24
+ assert.ok(key in palette, `missing palette key: ${key}`);
25
+ assert.ok(typeof palette[key] === 'function', `${key} should be a function`);
26
+ }
27
+ });
28
+ });
29
+
30
+ describe('sectionHeading()', () => {
31
+ let output;
32
+ const orig = console.log;
33
+
34
+ test('does not throw', () => {
35
+ assert.doesNotThrow(() => sectionHeading('Test Section'));
36
+ });
37
+ });
38
+
39
+ console.log(' banner.test.mjs loaded — run with: node --test cli/install/banner.test.mjs');