claude-code-session-manager 0.98.0 → 0.101.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 (441) hide show
  1. package/README.md +3 -3
  2. package/bin/cli.cjs +16 -4
  3. package/bin/node-floor.cjs +41 -0
  4. package/dist/assets/DataModel-CXaH2GED.js +1 -0
  5. package/dist/assets/{History-Bfdoywlh.js → History-Cerii-HA.js} +2 -2
  6. package/dist/assets/{Hooks-CKDJjTJV.js → Hooks-aXMb5LDy.js} +3 -3
  7. package/dist/assets/{Library-7akfgy67.js → Library-WrJFKEOJ.js} +1 -1
  8. package/dist/assets/{MarkdownEditor-DDesiqet.js → MarkdownEditor-D1BMCXS7.js} +1 -1
  9. package/dist/assets/{McpServers-D4lZtXof.js → McpServers-Cf0davLd.js} +2 -2
  10. package/dist/assets/{Memory-CeI8G1w5.js → Memory-Dn6NHWPe.js} +6 -6
  11. package/dist/assets/Permissions-CTVuFPjg.js +3 -0
  12. package/dist/assets/{Plugins-P4eCXy_S.js → Plugins-C2TyF8Mn.js} +2 -2
  13. package/dist/assets/ProvenanceBadge-F_jwHSwE.js +1 -0
  14. package/dist/assets/{SaveBar-l9jnEMES.js → SaveBar-DA1KVJST.js} +1 -1
  15. package/dist/assets/Scheduler-Bm6Q_hlu.js +16 -0
  16. package/dist/assets/{ScopeSwitcher-CjJi8ST5.js → ScopeSwitcher-BygZlJca.js} +1 -1
  17. package/dist/assets/Settings-BYCiv5KV.js +3 -0
  18. package/dist/assets/{SkillReferenceGraph-CjbO01Sg.js → SkillReferenceGraph-CcLnl9np.js} +1 -1
  19. package/dist/assets/{Skills-BxZ9_fCR.js → Skills-ChffsdTD.js} +2 -2
  20. package/dist/assets/{SystemPrompt-D8vfFb8b.js → SystemPrompt-dNkfHE_M.js} +1 -1
  21. package/dist/assets/{TagLibrary-2vzUo7YL.js → TagLibrary-jVlEuB0m.js} +1 -1
  22. package/dist/assets/{TiptapBody-B8ZfbK90.js → TiptapBody-6_cdwcP0.js} +1 -1
  23. package/dist/assets/{Toggle-BbW4nGGf.js → Toggle-CVXqGpAP.js} +1 -1
  24. package/dist/assets/ViewTabs-DO1YVbpc.js +1 -0
  25. package/dist/assets/{index-CKH5Uxik.css → index-D89EUizB.css} +1 -1
  26. package/dist/assets/{index-Cd98Q1lD.js → index-DbCQPWWY.js} +747 -752
  27. package/dist/assets/{settingsSchema-IhUfucCF.js → settingsSchema-Wrvn-Yz1.js} +1 -1
  28. package/dist/index.html +2 -2
  29. package/package.json +25 -29
  30. package/plugins/CLAUDE.md +6 -6
  31. package/plugins/session-manager-dev/skills/builder/4-manual/SKILL.md +21 -19
  32. package/plugins/session-manager-dev/skills/builder/SKILL.md +3 -3
  33. package/plugins/session-manager-dev/skills/develop/SKILL.md +254 -510
  34. package/plugins/session-manager-dev/skills/develop/standards.md +17 -22
  35. package/scripts/README.md +3 -11
  36. package/scripts/audit-ops-hygiene.cjs +3 -3
  37. package/scripts/hooks/lib/guard-prd-writes-policy.cjs +1 -1
  38. package/scripts/hooks/lib/guard-self-schedule-policy.cjs +1 -1
  39. package/scripts/mint-epic.cjs +2 -3
  40. package/scripts/scheduler-mcp-server.cjs +64 -7
  41. package/src/main/agentLibrary.cjs +22 -2
  42. package/src/main/build-info.json +4 -4
  43. package/src/main/chatRunner.cjs +4 -3
  44. package/src/main/config.cjs +41 -38
  45. package/src/main/docEdit.cjs +4 -1
  46. package/src/main/files.cjs +2 -5
  47. package/src/main/health.cjs +1 -1
  48. package/src/main/index.cjs +40 -11
  49. package/src/main/ipcSchemas.cjs +35 -34
  50. package/src/main/lib/agentPersonaSchema.cjs +13 -2
  51. package/src/main/lib/atomicFs.cjs +116 -0
  52. package/src/main/lib/branchSweep.cjs +13 -12
  53. package/src/main/lib/buildTarget.cjs +3 -3
  54. package/src/main/lib/builtinMacros.cjs +39 -0
  55. package/src/main/lib/claudeCliCaps.cjs +129 -0
  56. package/src/main/lib/credentials.cjs +2 -4
  57. package/src/main/lib/crossProjectFeedback.cjs +3 -3
  58. package/src/main/lib/cwdClassify.cjs +15 -3
  59. package/src/main/lib/definitionOfDone.cjs +207 -125
  60. package/src/main/lib/dodDrainHook.cjs +11 -5
  61. package/src/main/lib/epicMint.cjs +2 -4
  62. package/src/main/lib/epicStatusMirror.cjs +8 -10
  63. package/src/main/lib/epicWorktreeProjectConfig.cjs +2 -4
  64. package/src/main/lib/gateAuthority.cjs +96 -0
  65. package/src/main/lib/gitExec.cjs +69 -0
  66. package/src/main/lib/gitWorktree.cjs +656 -92
  67. package/src/main/lib/instanceLock.cjs +5 -8
  68. package/src/main/lib/launchFailure.cjs +2 -3
  69. package/src/main/lib/macroLibrary.cjs +480 -0
  70. package/src/main/lib/mcpToolCatalog.cjs +49 -17
  71. package/src/main/lib/needsReviewLedger.cjs +1 -1
  72. package/src/main/lib/opsErrorLog.cjs +11 -1
  73. package/src/main/lib/opsOwnership.cjs +5 -9
  74. package/src/main/lib/pidAlive.cjs +32 -0
  75. package/src/main/lib/prdCreate.cjs +121 -12
  76. package/src/main/lib/prdDisposition.cjs +2 -2
  77. package/src/main/lib/prdGateFiles.cjs +284 -0
  78. package/src/main/lib/prdLocations.cjs +61 -0
  79. package/src/main/lib/prdMigration.cjs +2 -3
  80. package/src/main/lib/prdSizing.cjs +2 -1
  81. package/src/main/lib/projectHomeAdminRoutes.cjs +136 -21
  82. package/src/main/lib/promptSessionSchema.cjs +10 -2
  83. package/src/main/lib/rcaReport.cjs +4 -6
  84. package/src/main/lib/reaperHelpers.cjs +8 -1
  85. package/src/main/lib/reservationExpiry.cjs +6 -1
  86. package/src/main/lib/reviewNotice.cjs +263 -0
  87. package/src/main/lib/runClaudeP.cjs +4 -1
  88. package/src/main/lib/schedulerPaths.cjs +22 -2
  89. package/src/main/lib/sessionSlots.cjs +2 -4
  90. package/src/main/lib/shippedPersonaSeeds.cjs +226 -0
  91. package/src/main/lib/smfileHeaders.cjs +66 -0
  92. package/src/main/lib/timeoutShim.cjs +123 -0
  93. package/src/main/lib/timeoutShimScript.cjs +275 -0
  94. package/src/main/lib/upgradeDrain.cjs +4 -10
  95. package/src/main/lib/watchdogHelpers.cjs +12 -25
  96. package/src/main/lib/workTypeLibrary.cjs +7 -1
  97. package/src/main/projectPages.cjs +43 -13
  98. package/src/main/promptSessionEvents.cjs +37 -13
  99. package/src/main/scheduler.cjs +910 -198
  100. package/src/main/seedAgentPersonas.cjs +279 -24
  101. package/src/main/supervisor.cjs +4 -1
  102. package/src/main/templates/PRD_AUTHORING.md +126 -406
  103. package/src/preload/__tests__/preload-surface.test.cjs +68 -0
  104. package/src/preload/api.d.ts +53 -94
  105. package/src/preload/index.cjs +14 -9
  106. package/src/seed/agents/architect.md +2 -0
  107. package/src/seed/agents/demo-video-builder.md +84 -0
  108. package/src/seed/agents/dev-lead.md +18 -18
  109. package/src/seed/agents/project-home-builder.md +66 -35
  110. package/src/seed/agents/validator.md +10 -4
  111. package/dist/assets/DataModel-DCEgMTjH.js +0 -1
  112. package/dist/assets/HostBilko-CDVHE0hT.js +0 -1
  113. package/dist/assets/Permissions-BGleLja4.js +0 -3
  114. package/dist/assets/ProvenanceBadge-BFczzI1B.js +0 -1
  115. package/dist/assets/Scheduler-C_phpeUS.js +0 -16
  116. package/dist/assets/Settings-BIwZ3FGQ.js +0 -3
  117. package/src/main/__tests__/activeIndexMerge.test.cjs +0 -235
  118. package/src/main/__tests__/agentEffortResolve.test.cjs +0 -117
  119. package/src/main/__tests__/agentLibrary.test.cjs +0 -276
  120. package/src/main/__tests__/agentModelResolve.test.cjs +0 -311
  121. package/src/main/__tests__/agentOverlayWrite.test.cjs +0 -95
  122. package/src/main/__tests__/bilkoHost-deriveSlug.test.cjs +0 -26
  123. package/src/main/__tests__/bilkoHost-integration.test.cjs +0 -118
  124. package/src/main/__tests__/bilkoHostCore.test.cjs +0 -72
  125. package/src/main/__tests__/broadcastCoalescer.test.cjs +0 -122
  126. package/src/main/__tests__/chat-cancel-terminal.test.cjs +0 -120
  127. package/src/main/__tests__/chat-dead-channels.test.cjs +0 -63
  128. package/src/main/__tests__/chat-exit-close-race.test.cjs +0 -146
  129. package/src/main/__tests__/chat-mcp-consent-notice.test.cjs +0 -139
  130. package/src/main/__tests__/chat-preamble-anchors.test.cjs +0 -100
  131. package/src/main/__tests__/chat-queue.test.cjs +0 -97
  132. package/src/main/__tests__/chat-stop-signal.test.cjs +0 -89
  133. package/src/main/__tests__/chatRunner-epic-worktree-execcwd.test.cjs +0 -125
  134. package/src/main/__tests__/chatRunner-session-flag-retry.test.cjs +0 -252
  135. package/src/main/__tests__/classifyPromptTicket.test.cjs +0 -101
  136. package/src/main/__tests__/classifyTranscriptLine.test.cjs +0 -201
  137. package/src/main/__tests__/computeDepHistorySatisfaction.test.cjs +0 -66
  138. package/src/main/__tests__/config-readText-bounded.test.cjs +0 -84
  139. package/src/main/__tests__/configWriteBoundaryOwners.test.cjs +0 -59
  140. package/src/main/__tests__/crossProjectFeedback.test.cjs +0 -334
  141. package/src/main/__tests__/crossProjectFeedbackRoutes.test.cjs +0 -161
  142. package/src/main/__tests__/dep-orphan-archive-health.test.cjs +0 -77
  143. package/src/main/__tests__/develop-skill-failure-modes.test.cjs +0 -70
  144. package/src/main/__tests__/docEdit.test.cjs +0 -244
  145. package/src/main/__tests__/dod-batchkey.test.cjs +0 -183
  146. package/src/main/__tests__/dod-drain-hook.test.cjs +0 -302
  147. package/src/main/__tests__/dod-report.test.cjs +0 -304
  148. package/src/main/__tests__/dod-reverify.test.cjs +0 -285
  149. package/src/main/__tests__/epicContextDigest.test.cjs +0 -174
  150. package/src/main/__tests__/epicMint.test.cjs +0 -332
  151. package/src/main/__tests__/epicMintTelemetryTap.test.cjs +0 -64
  152. package/src/main/__tests__/epicStatusMirror.test.cjs +0 -110
  153. package/src/main/__tests__/epicValidationHook.test.cjs +0 -291
  154. package/src/main/__tests__/exchanges.test.cjs +0 -122
  155. package/src/main/__tests__/exchangesPromptId.test.cjs +0 -61
  156. package/src/main/__tests__/extractJson.test.cjs +0 -51
  157. package/src/main/__tests__/files-reject-credentials.test.cjs +0 -40
  158. package/src/main/__tests__/fixtures/1218-fo-01-move-scripts-lib-into-src-main-lib.log +0 -556
  159. package/src/main/__tests__/flatPrdTickSweep.test.cjs +0 -110
  160. package/src/main/__tests__/health-build-freshness.test.cjs +0 -39
  161. package/src/main/__tests__/health-claude-md-budget.test.cjs +0 -57
  162. package/src/main/__tests__/health-credentials.test.cjs +0 -81
  163. package/src/main/__tests__/health-delegation-chain.test.cjs +0 -124
  164. package/src/main/__tests__/health-per-project-stall.test.cjs +0 -84
  165. package/src/main/__tests__/health-prd-migration.test.cjs +0 -37
  166. package/src/main/__tests__/health-queue-dispatch.test.cjs +0 -135
  167. package/src/main/__tests__/health-starve-escalation.test.cjs +0 -94
  168. package/src/main/__tests__/health-tick-liveness.test.cjs +0 -179
  169. package/src/main/__tests__/health-usage-poller.test.cjs +0 -144
  170. package/src/main/__tests__/health-worktree-cap-blocked.test.cjs +0 -65
  171. package/src/main/__tests__/heapSnapshot.test.cjs +0 -121
  172. package/src/main/__tests__/historyAggregatorIntraday.test.cjs +0 -313
  173. package/src/main/__tests__/historyDashboard.test.cjs +0 -163
  174. package/src/main/__tests__/historyRollup.test.cjs +0 -333
  175. package/src/main/__tests__/intradayRefresh.test.cjs +0 -39
  176. package/src/main/__tests__/ipcSchemas-dependsOn.test.cjs +0 -39
  177. package/src/main/__tests__/kg-augment.test.cjs +0 -195
  178. package/src/main/__tests__/loadGateDetailTick.test.cjs +0 -31
  179. package/src/main/__tests__/machineProfile.test.cjs +0 -152
  180. package/src/main/__tests__/mcpStatus.test.cjs +0 -61
  181. package/src/main/__tests__/memoryAggregate.test.cjs +0 -109
  182. package/src/main/__tests__/memoryStale.test.cjs +0 -88
  183. package/src/main/__tests__/needsReviewLedger.test.cjs +0 -162
  184. package/src/main/__tests__/openExternalApp-spawn-error.test.cjs +0 -25
  185. package/src/main/__tests__/opsErrorLog.test.cjs +0 -109
  186. package/src/main/__tests__/opsErrorLogTelemetryTap.test.cjs +0 -173
  187. package/src/main/__tests__/personaMerge.test.cjs +0 -169
  188. package/src/main/__tests__/planValidator.test.cjs +0 -125
  189. package/src/main/__tests__/pollLoop-dispatch-on-failure.test.cjs +0 -176
  190. package/src/main/__tests__/prd-group-allocator.test.cjs +0 -119
  191. package/src/main/__tests__/prdAdminRouteParity.test.cjs +0 -70
  192. package/src/main/__tests__/prdAdminRoutes.test.cjs +0 -718
  193. package/src/main/__tests__/prdAgentType.test.cjs +0 -103
  194. package/src/main/__tests__/prdAuthoringSeed.test.cjs +0 -39
  195. package/src/main/__tests__/prdCreate.test.cjs +0 -979
  196. package/src/main/__tests__/prdCreateAdoption.test.cjs +0 -205
  197. package/src/main/__tests__/prdCreateDisposition.test.cjs +0 -201
  198. package/src/main/__tests__/prdCreatePlanId.test.cjs +0 -132
  199. package/src/main/__tests__/prdFrontmatterAgentType.test.cjs +0 -117
  200. package/src/main/__tests__/prdFrontmatterDependsOn.test.cjs +0 -136
  201. package/src/main/__tests__/prdFrontmatterDisposition.test.cjs +0 -125
  202. package/src/main/__tests__/prdFrontmatterQuietMachine.test.cjs +0 -108
  203. package/src/main/__tests__/prdLocations.test.cjs +0 -195
  204. package/src/main/__tests__/prdLocationsArchived.test.cjs +0 -201
  205. package/src/main/__tests__/prdMigration.test.cjs +0 -349
  206. package/src/main/__tests__/prdMigrationLegacyAdopt.test.cjs +0 -91
  207. package/src/main/__tests__/prdParserHighWater.test.cjs +0 -74
  208. package/src/main/__tests__/prdParserSourcePromptId.test.cjs +0 -65
  209. package/src/main/__tests__/prdSetDisposition.test.cjs +0 -222
  210. package/src/main/__tests__/prdSizing.test.cjs +0 -106
  211. package/src/main/__tests__/prdSourcePromptIdBackfill.test.cjs +0 -118
  212. package/src/main/__tests__/prdUpdateDependsOn.test.cjs +0 -160
  213. package/src/main/__tests__/proc-role-env.test.cjs +0 -125
  214. package/src/main/__tests__/procname-claude-spawn-sites.test.cjs +0 -304
  215. package/src/main/__tests__/procname-sm-processes.test.cjs +0 -127
  216. package/src/main/__tests__/projectHomeAdminRoutes.test.cjs +0 -177
  217. package/src/main/__tests__/projectPages.test.cjs +0 -137
  218. package/src/main/__tests__/promptSessionEvents.test.cjs +0 -234
  219. package/src/main/__tests__/promptSessionSchema.test.cjs +0 -101
  220. package/src/main/__tests__/promptSessionTranscript.test.cjs +0 -0
  221. package/src/main/__tests__/promptSessionsCreateEpicHandler.test.cjs +0 -159
  222. package/src/main/__tests__/pty-epic-worktree-spawn-cwd.test.cjs +0 -282
  223. package/src/main/__tests__/pty-session-open-telemetry.test.cjs +0 -96
  224. package/src/main/__tests__/pty-write-result.test.cjs +0 -46
  225. package/src/main/__tests__/queue-health-verdict.test.cjs +0 -170
  226. package/src/main/__tests__/queue-starvation-dispatch-driver.test.cjs +0 -286
  227. package/src/main/__tests__/queue-starvation-per-project.test.cjs +0 -147
  228. package/src/main/__tests__/queueHistory.test.cjs +0 -355
  229. package/src/main/__tests__/queueOps-interactive-ac-lint.test.cjs +0 -65
  230. package/src/main/__tests__/queueOpsArchiveDestination.test.cjs +0 -65
  231. package/src/main/__tests__/queueOpsAutoArchive.test.cjs +0 -211
  232. package/src/main/__tests__/rateLimitPollerStreak.test.cjs +0 -128
  233. package/src/main/__tests__/rcaReport.test.cjs +0 -266
  234. package/src/main/__tests__/reconcileFlatPrdSweep.test.cjs +0 -119
  235. package/src/main/__tests__/reconcileTiming.test.cjs +0 -135
  236. package/src/main/__tests__/runLogRetention.test.cjs +0 -489
  237. package/src/main/__tests__/runVerify-atomic-verdicts.test.cjs +0 -26
  238. package/src/main/__tests__/runVerify-blocked-by-foreign-wip.test.cjs +0 -58
  239. package/src/main/__tests__/runVerify-landed-commit-outranks.test.cjs +0 -191
  240. package/src/main/__tests__/runVerify-policy-denial.test.cjs +0 -89
  241. package/src/main/__tests__/runVerify-transcript-commit-evidence.test.cjs +0 -225
  242. package/src/main/__tests__/runVerify.test.cjs +0 -1784
  243. package/src/main/__tests__/scheduleJobSchema.test.cjs +0 -127
  244. package/src/main/__tests__/scheduleJobStatusDrift.test.cjs +0 -65
  245. package/src/main/__tests__/scheduleJobTransitions.test.cjs +0 -277
  246. package/src/main/__tests__/scheduleJobTransitionsGrep.test.cjs +0 -59
  247. package/src/main/__tests__/scheduleJobTransitionsTelemetryTap.test.cjs +0 -72
  248. package/src/main/__tests__/scheduler-admin-routes.test.cjs +0 -199
  249. package/src/main/__tests__/scheduler-adopted-run-supervision.test.cjs +0 -143
  250. package/src/main/__tests__/scheduler-already-satisfied-on-main.test.cjs +0 -105
  251. package/src/main/__tests__/scheduler-archive-completed-prd.test.cjs +0 -102
  252. package/src/main/__tests__/scheduler-archived-twin-guard.test.cjs +0 -155
  253. package/src/main/__tests__/scheduler-autofix-outcome.test.cjs +0 -188
  254. package/src/main/__tests__/scheduler-autofix-select.test.cjs +0 -439
  255. package/src/main/__tests__/scheduler-autopromote.test.cjs +0 -51
  256. package/src/main/__tests__/scheduler-bash-timeout-env.test.cjs +0 -101
  257. package/src/main/__tests__/scheduler-blocked-by-foreign-wip.test.cjs +0 -107
  258. package/src/main/__tests__/scheduler-boot-orphans.test.cjs +0 -153
  259. package/src/main/__tests__/scheduler-broadcast-reconcile.test.cjs +0 -121
  260. package/src/main/__tests__/scheduler-clear-queue-history.test.cjs +0 -134
  261. package/src/main/__tests__/scheduler-commit-guard-noop.test.cjs +0 -244
  262. package/src/main/__tests__/scheduler-committed-in-window.test.cjs +0 -182
  263. package/src/main/__tests__/scheduler-cross-project-batch.test.cjs +0 -43
  264. package/src/main/__tests__/scheduler-default-eligible-heal.test.cjs +0 -168
  265. package/src/main/__tests__/scheduler-dispatch-loop.test.cjs +0 -58
  266. package/src/main/__tests__/scheduler-effective-concurrency.test.cjs +0 -81
  267. package/src/main/__tests__/scheduler-epic-digest.test.cjs +0 -227
  268. package/src/main/__tests__/scheduler-failed-autoreset.test.cjs +0 -121
  269. package/src/main/__tests__/scheduler-finalize-dispatch-guards.test.cjs +0 -229
  270. package/src/main/__tests__/scheduler-find-prd-dir.test.cjs +0 -75
  271. package/src/main/__tests__/scheduler-fix-plan-path.test.cjs +0 -119
  272. package/src/main/__tests__/scheduler-force-tick-outcome.test.cjs +0 -46
  273. package/src/main/__tests__/scheduler-foreign-wip-manifest.test.cjs +0 -78
  274. package/src/main/__tests__/scheduler-gate-shadow.test.cjs +0 -119
  275. package/src/main/__tests__/scheduler-guard-verdict-autoresolve.test.cjs +0 -390
  276. package/src/main/__tests__/scheduler-heal-refusal.test.cjs +0 -61
  277. package/src/main/__tests__/scheduler-heartbeat-payload.test.cjs +0 -80
  278. package/src/main/__tests__/scheduler-inplace-salvage.test.cjs +0 -323
  279. package/src/main/__tests__/scheduler-integration-failure-stamp.test.cjs +0 -41
  280. package/src/main/__tests__/scheduler-investigation-clean-skip.test.cjs +0 -63
  281. package/src/main/__tests__/scheduler-investigation-prompt.test.cjs +0 -123
  282. package/src/main/__tests__/scheduler-job-budget.test.cjs +0 -172
  283. package/src/main/__tests__/scheduler-job-overrun.test.cjs +0 -175
  284. package/src/main/__tests__/scheduler-launch-failure.test.cjs +0 -199
  285. package/src/main/__tests__/scheduler-leftover-fields.test.cjs +0 -52
  286. package/src/main/__tests__/scheduler-leftover-quarantine.test.cjs +0 -199
  287. package/src/main/__tests__/scheduler-looks-done.test.cjs +0 -537
  288. package/src/main/__tests__/scheduler-manual-pause.test.cjs +0 -118
  289. package/src/main/__tests__/scheduler-mechanical-recovery.test.cjs +0 -245
  290. package/src/main/__tests__/scheduler-meta-code-sha.test.cjs +0 -46
  291. package/src/main/__tests__/scheduler-mutate-reentrancy.test.cjs +0 -117
  292. package/src/main/__tests__/scheduler-needs-review-autoresolve.test.cjs +0 -197
  293. package/src/main/__tests__/scheduler-never-stop.test.cjs +0 -157
  294. package/src/main/__tests__/scheduler-no-dead-end-status.test.cjs +0 -152
  295. package/src/main/__tests__/scheduler-no-orphan-run-dir.test.cjs +0 -81
  296. package/src/main/__tests__/scheduler-notify-originating-tab-transcript.test.cjs +0 -87
  297. package/src/main/__tests__/scheduler-notify-originating-tab.test.cjs +0 -343
  298. package/src/main/__tests__/scheduler-periodic-reverify-guard.test.cjs +0 -217
  299. package/src/main/__tests__/scheduler-porcelain-rename.test.cjs +0 -164
  300. package/src/main/__tests__/scheduler-prd-missing-skip.test.cjs +0 -161
  301. package/src/main/__tests__/scheduler-prd-persona-spawn.test.cjs +0 -178
  302. package/src/main/__tests__/scheduler-quarantine-autoresolve.test.cjs +0 -165
  303. package/src/main/__tests__/scheduler-quiet-machine-lease.test.cjs +0 -257
  304. package/src/main/__tests__/scheduler-rate-limit-cooldown-freshness.test.cjs +0 -123
  305. package/src/main/__tests__/scheduler-rate-limit-pause.test.cjs +0 -152
  306. package/src/main/__tests__/scheduler-rate-limit-spin-guard.test.cjs +0 -156
  307. package/src/main/__tests__/scheduler-reap-dead-running-jobs.test.cjs +0 -754
  308. package/src/main/__tests__/scheduler-reaper-helpers-basics.test.cjs +0 -87
  309. package/src/main/__tests__/scheduler-reconcile-cwd-preserve.test.cjs +0 -100
  310. package/src/main/__tests__/scheduler-reconcile-history-backfill.test.cjs +0 -105
  311. package/src/main/__tests__/scheduler-reconcile-invalid-repair.test.cjs +0 -203
  312. package/src/main/__tests__/scheduler-reconcile-quarantine.test.cjs +0 -247
  313. package/src/main/__tests__/scheduler-reset-job-fields-guard.test.cjs +0 -77
  314. package/src/main/__tests__/scheduler-resume-recovery.test.cjs +0 -254
  315. package/src/main/__tests__/scheduler-shard-quarantine.test.cjs +0 -115
  316. package/src/main/__tests__/scheduler-shared-tree-guard.test.cjs +0 -380
  317. package/src/main/__tests__/scheduler-sigterm-commit.test.cjs +0 -43
  318. package/src/main/__tests__/scheduler-stall-per-project.test.cjs +0 -126
  319. package/src/main/__tests__/scheduler-starve-escalation.test.cjs +0 -154
  320. package/src/main/__tests__/scheduler-stranded-autofix-park.test.cjs +0 -252
  321. package/src/main/__tests__/scheduler-stranded-investigation.test.cjs +0 -185
  322. package/src/main/__tests__/scheduler-stuck-failed-escalation.test.cjs +0 -136
  323. package/src/main/__tests__/scheduler-supervisor-record.test.cjs +0 -81
  324. package/src/main/__tests__/scheduler-tick-cancel-token.test.cjs +0 -54
  325. package/src/main/__tests__/scheduler-tick-wedge.test.cjs +0 -172
  326. package/src/main/__tests__/scheduler-transient-failure.test.cjs +0 -141
  327. package/src/main/__tests__/scheduler-unreadable-queue-guard.test.cjs +0 -62
  328. package/src/main/__tests__/scheduler-utilization-hold.test.cjs +0 -89
  329. package/src/main/__tests__/scheduler-verify-prd-path.test.cjs +0 -109
  330. package/src/main/__tests__/scheduler-worktree-cap-defer.test.cjs +0 -234
  331. package/src/main/__tests__/scheduler-worktree-exec-cwd.test.cjs +0 -120
  332. package/src/main/__tests__/scheduler-writeprd-epic-rollback.test.cjs +0 -105
  333. package/src/main/__tests__/schedulerBatchRootBlocker.test.cjs +0 -117
  334. package/src/main/__tests__/schedulerStateSidecarRestore.test.cjs +0 -110
  335. package/src/main/__tests__/seedAgentPersonas.test.cjs +0 -184
  336. package/src/main/__tests__/seedSchedulerMcp.test.cjs +0 -211
  337. package/src/main/__tests__/seedStatus.test.cjs +0 -100
  338. package/src/main/__tests__/seedValidatorPersona.test.cjs +0 -116
  339. package/src/main/__tests__/stop-signal-anchor.test.cjs +0 -75
  340. package/src/main/__tests__/telemetryClient.test.cjs +0 -1055
  341. package/src/main/__tests__/telemetryContract.test.cjs +0 -930
  342. package/src/main/__tests__/telemetrySettings.test.cjs +0 -210
  343. package/src/main/__tests__/transcripts-batch-flush.test.cjs +0 -249
  344. package/src/main/__tests__/transcripts-doFlush-array.test.cjs +0 -124
  345. package/src/main/__tests__/transcripts-paged-reads.test.cjs +0 -241
  346. package/src/main/__tests__/transcripts-worktree-epic-path.test.cjs +0 -154
  347. package/src/main/__tests__/transcriptsUsageFor.test.cjs +0 -206
  348. package/src/main/__tests__/uniquePrdNumbers.test.cjs +0 -153
  349. package/src/main/__tests__/usageSingleFlight.test.cjs +0 -169
  350. package/src/main/__tests__/validationSentinels.test.cjs +0 -84
  351. package/src/main/__tests__/workTypeLibrary.test.cjs +0 -89
  352. package/src/main/bilkoHost.cjs +0 -314
  353. package/src/main/bilkoHostCore.cjs +0 -89
  354. package/src/main/lib/__tests__/active-sessions.test.cjs +0 -251
  355. package/src/main/lib/__tests__/activeIndexRebuild.test.cjs +0 -179
  356. package/src/main/lib/__tests__/agentPersonaSchema.test.cjs +0 -67
  357. package/src/main/lib/__tests__/auditLog.test.cjs +0 -38
  358. package/src/main/lib/__tests__/bootSelfHeal.test.cjs +0 -107
  359. package/src/main/lib/__tests__/branchSweep.test.cjs +0 -164
  360. package/src/main/lib/__tests__/buildIdentity.test.cjs +0 -121
  361. package/src/main/lib/__tests__/buildTarget.test.cjs +0 -52
  362. package/src/main/lib/__tests__/childWithLog.test.cjs +0 -321
  363. package/src/main/lib/__tests__/coldBootPromptSessionsWrite.test.cjs +0 -87
  364. package/src/main/lib/__tests__/crashTelemetry.test.cjs +0 -103
  365. package/src/main/lib/__tests__/credentials-futile-refresh.test.cjs +0 -115
  366. package/src/main/lib/__tests__/cwdClassify.test.cjs +0 -111
  367. package/src/main/lib/__tests__/definitionOfDoneSequence.test.cjs +0 -95
  368. package/src/main/lib/__tests__/delegationReadiness.test.cjs +0 -1175
  369. package/src/main/lib/__tests__/dispatchLoop.test.cjs +0 -63
  370. package/src/main/lib/__tests__/effectiveModelInfo.test.cjs +0 -244
  371. package/src/main/lib/__tests__/ephemeralCwd.test.cjs +0 -91
  372. package/src/main/lib/__tests__/epicDelegationStats.test.cjs +0 -137
  373. package/src/main/lib/__tests__/epicSpawnCwd.test.cjs +0 -283
  374. package/src/main/lib/__tests__/epicSpawnPlan.test.cjs +0 -196
  375. package/src/main/lib/__tests__/epicTranscriptPath.test.cjs +0 -163
  376. package/src/main/lib/__tests__/epicWorktreeBoot.test.cjs +0 -136
  377. package/src/main/lib/__tests__/epicWorktreeMerge.test.cjs +0 -130
  378. package/src/main/lib/__tests__/epicWorktreeMint.test.cjs +0 -117
  379. package/src/main/lib/__tests__/epicWorktreeProjectConfig.test.cjs +0 -137
  380. package/src/main/lib/__tests__/fixChainDepth.test.cjs +0 -40
  381. package/src/main/lib/__tests__/fixtures/204-mercury-steam-horse.log.txt +0 -13
  382. package/src/main/lib/__tests__/fixtures/scheduler-machine.json.corrupt-1789147548 +0 -34
  383. package/src/main/lib/__tests__/gateFixtures.json +0 -20
  384. package/src/main/lib/__tests__/gitCacheBound.test.cjs +0 -69
  385. package/src/main/lib/__tests__/gitWorktree.test.cjs +0 -1478
  386. package/src/main/lib/__tests__/gitWorktreeSalvage.test.cjs +0 -107
  387. package/src/main/lib/__tests__/gitWorktreeSalvageDelta.test.cjs +0 -153
  388. package/src/main/lib/__tests__/guardShims.test.cjs +0 -158
  389. package/src/main/lib/__tests__/importReferences.spec.cjs +0 -56
  390. package/src/main/lib/__tests__/instanceLock.test.cjs +0 -173
  391. package/src/main/lib/__tests__/jobSupervisorRecord.test.cjs +0 -78
  392. package/src/main/lib/__tests__/jobWorktree.test.cjs +0 -199
  393. package/src/main/lib/__tests__/jobWorktreeBootLive.test.cjs +0 -82
  394. package/src/main/lib/__tests__/landedSinceRun.test.cjs +0 -133
  395. package/src/main/lib/__tests__/launchFailure.test.cjs +0 -220
  396. package/src/main/lib/__tests__/loadGate.test.cjs +0 -303
  397. package/src/main/lib/__tests__/localAdminHttp.test.cjs +0 -214
  398. package/src/main/lib/__tests__/loopDelay.test.cjs +0 -68
  399. package/src/main/lib/__tests__/mcpToolCatalog.test.cjs +0 -107
  400. package/src/main/lib/__tests__/modelCatalog.test.cjs +0 -202
  401. package/src/main/lib/__tests__/opsOwnership.test.cjs +0 -113
  402. package/src/main/lib/__tests__/opsRootAbsoluteCwd.test.cjs +0 -328
  403. package/src/main/lib/__tests__/opsRootNestedWrite.test.cjs +0 -51
  404. package/src/main/lib/__tests__/opsRootResolve.test.cjs +0 -149
  405. package/src/main/lib/__tests__/prdDeclaredPaths.test.cjs +0 -82
  406. package/src/main/lib/__tests__/prdDisposition.test.cjs +0 -224
  407. package/src/main/lib/__tests__/procIdentity.test.cjs +0 -119
  408. package/src/main/lib/__tests__/procName.test.cjs +0 -92
  409. package/src/main/lib/__tests__/projectBriefCore.test.cjs +0 -216
  410. package/src/main/lib/__tests__/projectRootResolve.test.cjs +0 -148
  411. package/src/main/lib/__tests__/queueHealth.test.cjs +0 -58
  412. package/src/main/lib/__tests__/queueStoreAtomicWrite.test.cjs +0 -88
  413. package/src/main/lib/__tests__/queueStoreMachineStateRecovery.test.cjs +0 -190
  414. package/src/main/lib/__tests__/quietMachineLease.test.cjs +0 -39
  415. package/src/main/lib/__tests__/rateLimitWindow.test.cjs +0 -88
  416. package/src/main/lib/__tests__/reaperHelpers.test.cjs +0 -577
  417. package/src/main/lib/__tests__/schedulerBatchDepends.test.cjs +0 -312
  418. package/src/main/lib/__tests__/schedulerBatchFairness.test.cjs +0 -213
  419. package/src/main/lib/__tests__/schedulerBatchLaunchHold.test.cjs +0 -125
  420. package/src/main/lib/__tests__/schedulerBatchProjectCap.test.cjs +0 -127
  421. package/src/main/lib/__tests__/schedulerBatchQuietMachine.test.cjs +0 -109
  422. package/src/main/lib/__tests__/schedulerMcpServerHeadlessRefusal.test.cjs +0 -71
  423. package/src/main/lib/__tests__/schedulerMcpServerHelp.test.cjs +0 -216
  424. package/src/main/lib/__tests__/schedulerMcpServerProjectHome.test.cjs +0 -183
  425. package/src/main/lib/__tests__/schedulerPaths.test.cjs +0 -226
  426. package/src/main/lib/__tests__/schedulerPathsWorktree.test.cjs +0 -133
  427. package/src/main/lib/__tests__/schedulerRuntimeState.test.cjs +0 -56
  428. package/src/main/lib/__tests__/sessionSlots.test.cjs +0 -144
  429. package/src/main/lib/__tests__/telemetryBacklog.test.cjs +0 -626
  430. package/src/main/lib/__tests__/telemetryBoot.test.cjs +0 -134
  431. package/src/main/lib/__tests__/telemetryConsent.test.cjs +0 -136
  432. package/src/main/lib/__tests__/telemetryCounters.test.cjs +0 -57
  433. package/src/main/lib/__tests__/telemetryCountersMetadataColumn.test.cjs +0 -98
  434. package/src/main/lib/__tests__/terminalRunOutcome.test.cjs +0 -200
  435. package/src/main/lib/__tests__/toolUseClassify.test.cjs +0 -53
  436. package/src/main/lib/__tests__/updateCheck.test.cjs +0 -63
  437. package/src/main/lib/__tests__/upgradeDrain.test.cjs +0 -130
  438. package/src/main/lib/__tests__/usageCircuit.test.cjs +0 -354
  439. package/src/main/lib/__tests__/watchdog-helpers.test.cjs +0 -441
  440. package/src/main/lib/__tests__/watchdog-relaunch.test.cjs +0 -266
  441. package/src/main/lib/kgExchangePairing.cjs +0 -75
@@ -1,314 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * bilkoHost.cjs — Stage A (deterministic bundle prep) for the "Host on
5
- * Bilko.run" tab. See session-manager-operations/architecture/
6
- * bilko-host-integration.md for the full design.
7
- *
8
- * Model: ONE Bilko project (slug) hosts a LIST of documents — a root
9
- * document (subpath '', dist/index.html — "the project itself") plus any
10
- * number of sub-path documents (subpath 'special-doc/01',
11
- * dist/special-doc/01/index.html → bilko.run/projects/<slug>/special-doc/01/).
12
- * `documents.json` is the list; `dist/` is always rebuilt wholesale from it
13
- * (rm + rewrite) so it can never drift from the list — the same "full
14
- * replace" semantics Bilko's own publish_static_project already uses, which
15
- * is exactly what makes local deletion reliably propagate live (see
16
- * bilkoHostCore.cjs's header comment).
17
- *
18
- * This module owns `session-manager-operations/bilko-host/documents.json` +
19
- * `dist/{**,manifest.json}` (writer id `bilko-host`, OWNERS-enforced via
20
- * config.cjs's write helpers). It never talks to the bilko-host MCP itself
21
- * and never writes publish-state.json — that's Stage B, run by the
22
- * bilko-host-publisher Epic's own session with its own Write tool
23
- * (agent-authored artifact, same as project-pages/output/*.html; not
24
- * enforceable by OWNERS). Directory removal (rm -rf of dist/ before a
25
- * rebuild) uses raw fs directly, same precedent as epicMint.cjs/
26
- * queueStore.cjs using raw fs for their own owned namespace — this module
27
- * IS the declared owner of `bilko-host`, so there is no foreign-writer risk
28
- * to guard against here.
29
- */
30
-
31
- const { ipcMain } = require('electron');
32
- const { opsPath } = require('./lib/opsOwnership.cjs');
33
- const fsp = require('node:fs/promises');
34
- const path = require('node:path');
35
- const crypto = require('node:crypto');
36
- const { execFileSync } = require('node:child_process');
37
- const { gzipSync } = require('node:zlib');
38
- const config = require('./config.cjs');
39
- const {
40
- validateSubpath,
41
- validateDocumentSet,
42
- documentDistRelPath,
43
- documentUrl,
44
- } = require('./bilkoHostCore.cjs');
45
-
46
- const WRITER = 'bilko-host';
47
- const PROJECT_PAGE_LENSES = new Set(['home', 'marketing', 'feature', 'architecture']);
48
-
49
- function homePagePath(cwd) {
50
- return opsPath(cwd, 'project-pages', 'home.html');
51
- }
52
-
53
- function bilkoHostDir(cwd) {
54
- return opsPath(cwd, 'bilko-host');
55
- }
56
-
57
- function distDir(cwd) {
58
- return path.join(bilkoHostDir(cwd), 'dist');
59
- }
60
-
61
- function documentsPath(cwd) {
62
- return path.join(bilkoHostDir(cwd), 'documents.json');
63
- }
64
-
65
- /** Kebab-case a project name into a slug candidate. Pure. */
66
- function deriveSlug(projectDirName) {
67
- return String(projectDirName)
68
- .trim()
69
- .toLowerCase()
70
- .replace(/[^a-z0-9]+/g, '-')
71
- .replace(/^-+|-+$/g, '')
72
- .slice(0, 64) || 'project';
73
- }
74
-
75
- function gitInfo(cwd) {
76
- const run = (args, fallback) => {
77
- try {
78
- return execFileSync('git', args, { cwd, stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
79
- } catch {
80
- return fallback;
81
- }
82
- };
83
- return {
84
- gitSha: run(['rev-parse', '--short', 'HEAD'], '0000000'),
85
- gitBranch: run(['rev-parse', '--abbrev-ref', 'HEAD'], 'main'),
86
- };
87
- }
88
-
89
- async function readDocuments(cwd) {
90
- const result = await config.readJson(documentsPath(cwd));
91
- if (result.exists && !result.parseError && Array.isArray(result.data?.documents)) {
92
- return result.data.documents;
93
- }
94
- return null;
95
- }
96
-
97
- async function writeDocuments(cwd, documents) {
98
- await config.writeJson(documentsPath(cwd), { documents }, { writer: WRITER });
99
- }
100
-
101
- /**
102
- * Reads everything the tab needs to render its status card: whether a
103
- * Project Page exists to seed a root document from, the project's
104
- * package.json (for the compatibility gate + default slug/version), the
105
- * current document list, and any bundle/publish state already on disk.
106
- */
107
- async function get({ cwd }) {
108
- const realCwd = config.validatePath(cwd);
109
-
110
- // The single Project Home page (project-pages/home.html) seeds the root
111
- // document. `hasMarketingPage` is the renderer's legacy field name for
112
- // "a root-document source page exists".
113
- const marketingResult = await config.readText(homePagePath(realCwd));
114
- const pkgResult = await config.readJson(path.join(realCwd, 'package.json'));
115
- const pkg = pkgResult.exists && !pkgResult.parseError ? pkgResult.data : null;
116
-
117
- const documents = (await readDocuments(realCwd)) ?? [];
118
-
119
- const bundleManifestResult = await config.readJson(path.join(distDir(realCwd), 'manifest.json'));
120
- const bundleManifest = bundleManifestResult.exists && !bundleManifestResult.parseError
121
- ? bundleManifestResult.data
122
- : null;
123
-
124
- const publishStateResult = await config.readJson(path.join(bilkoHostDir(realCwd), 'publish-state.json'));
125
- const publishState = publishStateResult.exists && !publishStateResult.parseError
126
- ? publishStateResult.data
127
- : null;
128
-
129
- const slug = bundleManifest?.slug
130
- ?? deriveSlug(pkg && typeof pkg.name === 'string' ? pkg.name : path.basename(realCwd));
131
-
132
- return {
133
- hasMarketingPage: marketingResult.exists,
134
- projectName: pkg && typeof pkg.name === 'string' ? pkg.name : path.basename(realCwd),
135
- packagePrivate: pkg ? pkg.private === true : false,
136
- packageHomepage: pkg && typeof pkg.homepage === 'string' ? pkg.homepage : null,
137
- packageVersion: pkg && typeof pkg.version === 'string' ? pkg.version : '0.0.0',
138
- defaultSlug: deriveSlug(pkg && typeof pkg.name === 'string' ? pkg.name : path.basename(realCwd)),
139
- documents: documents.map((d) => ({ ...d, url: documentUrl(slug, d.subpath) })),
140
- // A rebuild is owed whenever the bundle on disk doesn't reflect the
141
- // current document list — the tab uses this to gray out "up to date"
142
- // vs. prompt "Prepare Bundle" again, and (post-publish) to warn that a
143
- // removed document is still live until the next Publish.
144
- bundleStale: bundleManifest ? bundleManifest.documentCount !== documents.length : documents.length > 0,
145
- bundleManifest,
146
- publishState,
147
- };
148
- }
149
-
150
- /** Seeds documents.json with a single root document (the Project Home page, home.html) if it doesn't exist yet. */
151
- async function ensureSeededDocuments(cwd) {
152
- const existing = await readDocuments(cwd);
153
- if (existing) return existing;
154
- const seeded = [{
155
- id: crypto.randomUUID(),
156
- subpath: '',
157
- title: 'Project (Home)',
158
- source: { kind: 'project-page-lens', lens: 'home' },
159
- addedAt: new Date().toISOString(),
160
- }];
161
- await writeDocuments(cwd, seeded);
162
- return seeded;
163
- }
164
-
165
- /**
166
- * Add a hosted document. `source` is either
167
- * `{ kind: 'project-page-lens', lens: 'home'|'marketing'|'feature'|'architecture' }`
168
- * (reuses an already-generated Project Page lens) or
169
- * `{ kind: 'file', path: <repo-relative path> }` (any other local HTML —
170
- * e.g. a HUMAN_LEARN page or a hand-authored explainer).
171
- */
172
- async function addDocument({ cwd, subpath, title, source }) {
173
- const realCwd = config.validatePath(cwd);
174
- const subpathCheck = validateSubpath(subpath);
175
- if (!subpathCheck.ok) throw new Error(subpathCheck.error);
176
- if (source.kind === 'project-page-lens' && !PROJECT_PAGE_LENSES.has(source.lens)) {
177
- throw new Error(`unknown Project Page lens: ${source.lens}`);
178
- }
179
-
180
- const documents = (await readDocuments(realCwd)) ?? await ensureSeededDocuments(realCwd);
181
- if (subpath === '') {
182
- throw new Error('the root document (subpath "") always exists — edit it instead of adding a second one');
183
- }
184
- if (documents.some((d) => d.subpath === subpath)) {
185
- throw new Error(`a document already uses subpath "${subpath}"`);
186
- }
187
-
188
- const next = [...documents, {
189
- id: crypto.randomUUID(),
190
- subpath,
191
- title,
192
- source,
193
- addedAt: new Date().toISOString(),
194
- }];
195
- const setCheck = validateDocumentSet(next);
196
- if (!setCheck.ok) throw new Error(setCheck.error);
197
-
198
- await writeDocuments(realCwd, next);
199
- return { documents: next };
200
- }
201
-
202
- /**
203
- * Remove a hosted document (never the root). This only updates
204
- * documents.json — the file stays in `dist/` (and, if already published,
205
- * live on bilko.run) until the next Prepare Bundle + Publish, which is the
206
- * confirmed mechanism that actually removes it (Bilko's publish tool
207
- * rm -rf's + rebuilds the whole slug directory every publish).
208
- */
209
- async function removeDocument({ cwd, id }) {
210
- const realCwd = config.validatePath(cwd);
211
- const documents = (await readDocuments(realCwd)) ?? [];
212
- const target = documents.find((d) => d.id === id);
213
- if (!target) throw new Error(`no document with id ${id}`);
214
- if (target.subpath === '') throw new Error('cannot remove the root document');
215
-
216
- const next = documents.filter((d) => d.id !== id);
217
- await writeDocuments(realCwd, next);
218
- return { documents: next };
219
- }
220
-
221
- async function resolveDocumentHtml(cwd, doc) {
222
- if (doc.source.kind === 'project-page-lens') {
223
- // Only `home` is generated now (one home.html); other lens names are
224
- // retired and have no output anywhere — fail loudly rather than fall back.
225
- if (doc.source.lens !== 'home') {
226
- throw new Error(`document "${doc.title}" points at the retired "${doc.source.lens}" Project Page lens; only the single home.html page is generated now`);
227
- }
228
- const result = await config.readText(homePagePath(cwd));
229
- if (!result.exists) {
230
- throw new Error(`document "${doc.title}" points at the ${doc.source.lens} Project Page, but it hasn't been generated yet`);
231
- }
232
- return result.text;
233
- }
234
- if (doc.source.kind === 'file') {
235
- const abs = config.validatePath(path.join(cwd, doc.source.path));
236
- const result = await config.readText(abs);
237
- if (!result.exists) throw new Error(`document "${doc.title}"'s source file is missing: ${doc.source.path}`);
238
- return result.text;
239
- }
240
- throw new Error(`unknown document source kind: ${doc.source.kind}`);
241
- }
242
-
243
- /**
244
- * Stage A: rebuild the ENTIRE dist/ tree from documents.json (rm + rewrite,
245
- * mirroring Bilko's own full-replace publish semantics so local state can
246
- * never lag the document list) + dist/manifest.json (host-contract manifest
247
- * schema, one per bundle — golden.path/expect always point at the root
248
- * document). Idempotent.
249
- */
250
- async function prepareBundle({ cwd, slug }) {
251
- const realCwd = config.validatePath(cwd);
252
- const documents = await ensureSeededDocuments(realCwd);
253
-
254
- const setCheck = validateDocumentSet(documents);
255
- if (!setCheck.ok) throw new Error(setCheck.error);
256
-
257
- const pkgResult = await config.readJson(path.join(realCwd, 'package.json'));
258
- const pkg = pkgResult.exists && !pkgResult.parseError ? pkgResult.data : {};
259
- const version = typeof pkg.version === 'string' ? pkg.version : '0.0.0';
260
-
261
- const dist = distDir(realCwd);
262
- await fsp.rm(dist, { recursive: true, force: true });
263
-
264
- let totalGz = 0;
265
- for (const doc of documents) {
266
- const html = await resolveDocumentHtml(realCwd, doc);
267
- const relPath = documentDistRelPath(doc.subpath);
268
- await config.writeTextAtomic(path.join(dist, relPath), html, { writer: WRITER });
269
- totalGz += gzipSync(Buffer.from(html, 'utf8')).length;
270
- }
271
-
272
- const { gitSha, gitBranch } = gitInfo(realCwd);
273
- const goldenExpect = pkg && typeof pkg.name === 'string' ? pkg.name : slug;
274
-
275
- const manifest = {
276
- schemaVersion: 1,
277
- slug,
278
- version,
279
- builtAt: new Date().toISOString(),
280
- gitSha,
281
- gitBranch,
282
- hostKit: { version: '0.0.0' },
283
- golden: { path: `/projects/${slug}/`, expect: goldenExpect },
284
- health: {},
285
- bundle: { sizeBytesGz: totalGz, fileCount: documents.length },
286
- // Not part of the host-contract schema itself — this app's own staleness
287
- // check (get()'s bundleStale) compares this against documents.length.
288
- documentCount: documents.length,
289
- documents: documents.map((d) => ({ subpath: d.subpath, title: d.title })),
290
- };
291
-
292
- await config.writeJson(path.join(dist, 'manifest.json'), manifest, { writer: WRITER });
293
-
294
- return { distPath: dist, manifest };
295
- }
296
-
297
- function registerBilkoHostIpc() {
298
- const { schemas: s, validated: v } = require('./ipcSchemas.cjs');
299
- ipcMain.handle('bilko-host:get', v(s.bilkoHostCwd, get));
300
- ipcMain.handle('bilko-host:prepare-bundle', v(s.bilkoHostPrepareBundle, prepareBundle));
301
- ipcMain.handle('bilko-host:add-document', v(s.bilkoHostAddDocument, addDocument));
302
- ipcMain.handle('bilko-host:remove-document', v(s.bilkoHostRemoveDocument, removeDocument));
303
- }
304
-
305
- module.exports = {
306
- registerBilkoHostIpc,
307
- get,
308
- prepareBundle,
309
- addDocument,
310
- removeDocument,
311
- deriveSlug,
312
- bilkoHostDir,
313
- distDir,
314
- };
@@ -1,89 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * bilkoHostCore.cjs — pure logic for the "Host on Bilko.run" tab's
5
- * multi-document bundle model. No fs/IPC here (that's bilkoHost.cjs) so
6
- * this stays unit-testable without a real project directory.
7
- *
8
- * Model: ONE Bilko project (one registry slug, one `dist/` tree) can host
9
- * MANY documents — exactly one root document (subpath `''`, becomes
10
- * dist/index.html — "the project itself") plus any number of sub-path
11
- * documents (subpath 'special-doc/01', becomes dist/special-doc/01/
12
- * index.html → bilko.run/projects/<slug>/special-doc/01/). This mirrors how
13
- * Bilko's own publish_static_project already works: it `rm -rf`s then
14
- * `cp -r`s the WHOLE public/projects/<slug>/ tree on every publish, so
15
- * removing a document locally and re-publishing is guaranteed to remove it
16
- * live too — no separate per-document delete API needed on Bilko's side.
17
- */
18
-
19
- const SUBPATH_SEGMENT = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
20
- const MAX_SEGMENTS = 6;
21
- const MAX_SUBPATH_LENGTH = 200;
22
-
23
- /**
24
- * Validates a document's subpath. `''` (root) is always valid. Otherwise
25
- * every '/'-separated segment must be lowercase kebab-case, no '.'/'..',
26
- * no leading/trailing/double slashes, bounded depth and length.
27
- */
28
- function validateSubpath(subpath) {
29
- if (typeof subpath !== 'string') return { ok: false, error: 'subpath must be a string' };
30
- if (subpath === '') return { ok: true, error: null };
31
- if (subpath.length > MAX_SUBPATH_LENGTH) return { ok: false, error: 'subpath is too long' };
32
- if (subpath.startsWith('/') || subpath.endsWith('/')) {
33
- return { ok: false, error: 'subpath must not start or end with /' };
34
- }
35
- const segments = subpath.split('/');
36
- if (segments.length > MAX_SEGMENTS) return { ok: false, error: `subpath has more than ${MAX_SEGMENTS} segments` };
37
- for (const seg of segments) {
38
- if (!SUBPATH_SEGMENT.test(seg)) {
39
- return { ok: false, error: `invalid subpath segment "${seg}" — use lowercase kebab-case` };
40
- }
41
- }
42
- return { ok: true, error: null };
43
- }
44
-
45
- /**
46
- * Validates a full document list: subpaths individually valid, exactly one
47
- * root document, no duplicate subpaths. Pure — takes the array shape
48
- * documents.json stores, `[{ id, subpath, ... }]`.
49
- */
50
- function validateDocumentSet(documents) {
51
- if (!Array.isArray(documents) || documents.length === 0) {
52
- return { ok: false, error: 'at least one document (the root) is required' };
53
- }
54
- const seen = new Set();
55
- let rootCount = 0;
56
- for (const doc of documents) {
57
- const v = validateSubpath(doc.subpath);
58
- if (!v.ok) return { ok: false, error: `document "${doc.id}": ${v.error}` };
59
- if (seen.has(doc.subpath)) return { ok: false, error: `duplicate subpath "${doc.subpath}"` };
60
- seen.add(doc.subpath);
61
- if (doc.subpath === '') rootCount += 1;
62
- }
63
- if (rootCount !== 1) return { ok: false, error: 'exactly one document must have subpath "" (the project root)' };
64
- return { ok: true, error: null };
65
- }
66
-
67
- /** Where a document's rendered HTML lands inside dist/. Pure path math. */
68
- function documentDistRelPath(subpath) {
69
- return subpath === '' ? 'index.html' : `${subpath}/index.html`;
70
- }
71
-
72
- /**
73
- * The bilko.run URL a document resolves to once published, given the
74
- * project's slug. Pure — used by the tab to render "will be live at" links
75
- * before anything is actually published.
76
- */
77
- function documentUrl(slug, subpath) {
78
- return subpath === '' ? `https://bilko.run/projects/${slug}/` : `https://bilko.run/projects/${slug}/${subpath}/`;
79
- }
80
-
81
- module.exports = {
82
- SUBPATH_SEGMENT,
83
- MAX_SEGMENTS,
84
- MAX_SUBPATH_LENGTH,
85
- validateSubpath,
86
- validateDocumentSet,
87
- documentDistRelPath,
88
- documentUrl,
89
- };
@@ -1,251 +0,0 @@
1
- 'use strict';
2
-
3
- // Run: timeout 120 npx vitest run src/main/lib/__tests__/active-sessions.test.cjs
4
-
5
- import { vi } from 'vitest';
6
- const assert = require('node:assert/strict');
7
- const fs = require('node:fs');
8
- const os = require('node:os');
9
- const path = require('node:path');
10
- const { activeProjectCwds, allProjectCwds, bustProjectCwdCache } = require('../activeSessions.cjs');
11
-
12
- function tmpDir() {
13
- return fs.mkdtempSync(path.join(os.tmpdir(), 'active-sessions-test-'));
14
- }
15
-
16
- function writeTranscript(projectsDir, slug, fileName, cwd, mtimeMsAgo) {
17
- const projDir = path.join(projectsDir, slug);
18
- fs.mkdirSync(projDir, { recursive: true });
19
- const fp = path.join(projDir, fileName);
20
- fs.writeFileSync(fp, JSON.stringify({ cwd }) + '\n');
21
- const mtime = new Date(Date.now() - mtimeMsAgo);
22
- fs.utimesSync(fp, mtime, mtime);
23
- return fp;
24
- }
25
-
26
- test('two recent + one stale + one nonexistent → returns exactly the two recent existing cwds', () => {
27
- const base = tmpDir();
28
- try {
29
- const projectsDir = path.join(base, 'projects');
30
- const cwdA = path.join(base, 'proj-a');
31
- const cwdB = path.join(base, 'proj-b');
32
- const cwdC = path.join(base, 'proj-c'); // stale — exists on disk
33
- const cwdMissing = path.join(base, 'proj-missing'); // never created
34
- fs.mkdirSync(cwdA);
35
- fs.mkdirSync(cwdB);
36
- fs.mkdirSync(cwdC);
37
-
38
- const MAX_AGE_MIN = 90;
39
- writeTranscript(projectsDir, 'slug-a', 'a.jsonl', cwdA, 10 * 60 * 1000);
40
- writeTranscript(projectsDir, 'slug-b', 'b.jsonl', cwdB, 10 * 60 * 1000);
41
- writeTranscript(projectsDir, 'slug-c', 'c.jsonl', cwdC, 120 * 60 * 1000);
42
- writeTranscript(projectsDir, 'slug-missing', 'm.jsonl', cwdMissing, 10 * 60 * 1000);
43
-
44
- const result = activeProjectCwds(MAX_AGE_MIN, { projectsDir });
45
-
46
- assert.equal(
47
- result.length, 2,
48
- `expected 2 cwds, got ${result.length}: ${JSON.stringify(result)}`,
49
- );
50
- assert.ok(result.includes(cwdA), `cwdA must be in result`);
51
- assert.ok(result.includes(cwdB), `cwdB must be in result`);
52
- assert.ok(!result.includes(cwdC), 'stale cwdC must not appear');
53
- assert.ok(!result.includes(cwdMissing), 'nonexistent path must not appear');
54
- } finally {
55
- fs.rmSync(base, { recursive: true, force: true });
56
- }
57
- });
58
-
59
- test('duplicate cwd across two project dirs → deduped to one entry', () => {
60
- const base = tmpDir();
61
- try {
62
- const projectsDir = path.join(base, 'projects');
63
- const cwdA = path.join(base, 'proj-a');
64
- fs.mkdirSync(cwdA);
65
-
66
- writeTranscript(projectsDir, 'slug-1', 'a.jsonl', cwdA, 5 * 60 * 1000);
67
- writeTranscript(projectsDir, 'slug-2', 'b.jsonl', cwdA, 5 * 60 * 1000);
68
-
69
- const result = activeProjectCwds(90, { projectsDir });
70
- assert.equal(result.length, 1, 'duplicate cwd must be deduped');
71
- assert.equal(result[0], cwdA);
72
- } finally {
73
- fs.rmSync(base, { recursive: true, force: true });
74
- }
75
- });
76
-
77
- test('missing projects dir → empty result', () => {
78
- const base = tmpDir();
79
- try {
80
- const result = activeProjectCwds(90, { projectsDir: path.join(base, 'no-such-dir') });
81
- assert.deepEqual(result, []);
82
- } finally {
83
- fs.rmSync(base, { recursive: true, force: true });
84
- }
85
- });
86
-
87
- test('prompts.jsonl absent → transcripts still detected (sole detection path)', () => {
88
- const base = tmpDir();
89
- try {
90
- // No knowledge-log / prompts.jsonl anywhere in this tmp tree — the
91
- // function must not need it. logPath, if passed, is a harmless no-op.
92
- const projectsDir = path.join(base, 'projects');
93
- const cwdA = path.join(base, 'proj-a');
94
- fs.mkdirSync(cwdA);
95
-
96
- writeTranscript(projectsDir, 'slug-a', 'a.jsonl', cwdA, 5 * 60 * 1000);
97
-
98
- const missingLogPath = path.join(base, 'knowledge-log', 'prompts.jsonl');
99
- assert.ok(!fs.existsSync(missingLogPath), 'sanity: log path must not exist');
100
-
101
- const result = activeProjectCwds(90, { projectsDir, logPath: missingLogPath });
102
- assert.deepEqual(result, [cwdA]);
103
- } finally {
104
- fs.rmSync(base, { recursive: true, force: true });
105
- }
106
- });
107
-
108
- test('fresh transcript mtime with no prompt log present → cwd is returned', () => {
109
- const base = tmpDir();
110
- try {
111
- const projectsDir = path.join(base, 'projects');
112
- const cwdA = path.join(base, 'proj-fresh');
113
- fs.mkdirSync(cwdA);
114
-
115
- writeTranscript(projectsDir, 'slug-fresh', 'fresh.jsonl', cwdA, 60 * 1000); // 1 min ago
116
-
117
- const result = activeProjectCwds(90, { projectsDir });
118
- assert.equal(result.length, 1);
119
- assert.equal(result[0], cwdA);
120
- } finally {
121
- fs.rmSync(base, { recursive: true, force: true });
122
- }
123
- });
124
-
125
- test('garbage lines in transcript are skipped, cwd read from last parseable line', () => {
126
- const base = tmpDir();
127
- try {
128
- const projectsDir = path.join(base, 'projects');
129
- const cwdA = path.join(base, 'proj-a');
130
- fs.mkdirSync(cwdA);
131
-
132
- const projDir = path.join(projectsDir, 'slug-a');
133
- fs.mkdirSync(projDir, { recursive: true });
134
- const fp = path.join(projDir, 'a.jsonl');
135
- fs.writeFileSync(fp, [
136
- JSON.stringify({ cwd: cwdA }),
137
- 'not json at all!!!',
138
- '{ broken',
139
- ].join('\n') + '\n');
140
- const mtime = new Date(Date.now() - 5 * 60 * 1000);
141
- fs.utimesSync(fp, mtime, mtime);
142
-
143
- const result = activeProjectCwds(90, { projectsDir });
144
- assert.equal(result.length, 1);
145
- assert.equal(result[0], cwdA);
146
- } finally {
147
- fs.rmSync(base, { recursive: true, force: true });
148
- }
149
- });
150
-
151
- test('5 consecutive allProjectCwds() calls with the same args perform ONE directory scan', () => {
152
- const base = tmpDir();
153
- try {
154
- const projectsDir = path.join(base, 'projects');
155
- const cwdA = path.join(base, 'proj-a');
156
- fs.mkdirSync(cwdA);
157
- writeTranscript(projectsDir, 'slug-a', 'a.jsonl', cwdA, 5 * 60 * 1000);
158
-
159
- bustProjectCwdCache();
160
- const readdirSpy = vi.spyOn(fs, 'readdirSync');
161
-
162
- const first = allProjectCwds({ projectsDir });
163
- const callsAfterFirst = readdirSpy.mock.calls.length;
164
- assert.ok(callsAfterFirst > 0, 'first call must actually scan');
165
-
166
- for (let i = 0; i < 4; i++) {
167
- const again = allProjectCwds({ projectsDir });
168
- assert.deepEqual(again, first);
169
- }
170
-
171
- assert.equal(
172
- readdirSpy.mock.calls.length, callsAfterFirst,
173
- 'the 4 repeat calls must not perform any additional directory scan',
174
- );
175
- } finally {
176
- vi.restoreAllMocks();
177
- fs.rmSync(base, { recursive: true, force: true });
178
- }
179
- });
180
-
181
- test('bustProjectCwdCache() forces the very next call to rescan', () => {
182
- const base = tmpDir();
183
- try {
184
- const projectsDir = path.join(base, 'projects');
185
- const cwdA = path.join(base, 'proj-a');
186
- fs.mkdirSync(cwdA);
187
- writeTranscript(projectsDir, 'slug-a', 'a.jsonl', cwdA, 5 * 60 * 1000);
188
-
189
- bustProjectCwdCache();
190
- allProjectCwds({ projectsDir }); // warm the cache
191
-
192
- const readdirSpy = vi.spyOn(fs, 'readdirSync');
193
- allProjectCwds({ projectsDir });
194
- assert.equal(readdirSpy.mock.calls.length, 0, 'a cache hit must not scan');
195
-
196
- bustProjectCwdCache();
197
- allProjectCwds({ projectsDir });
198
- assert.ok(readdirSpy.mock.calls.length > 0, 'a bust must force a rescan on the next call');
199
- } finally {
200
- vi.restoreAllMocks();
201
- fs.rmSync(base, { recursive: true, force: true });
202
- }
203
- });
204
-
205
- test('allProjectCwds() and activeProjectCwds(90) do not share a cache entry', () => {
206
- const base = tmpDir();
207
- try {
208
- const projectsDir = path.join(base, 'projects');
209
- const cwdFresh = path.join(base, 'proj-fresh');
210
- const cwdStale = path.join(base, 'proj-stale');
211
- fs.mkdirSync(cwdFresh);
212
- fs.mkdirSync(cwdStale);
213
- writeTranscript(projectsDir, 'slug-fresh', 'fresh.jsonl', cwdFresh, 5 * 60 * 1000);
214
- writeTranscript(projectsDir, 'slug-stale', 'stale.jsonl', cwdStale, 120 * 60 * 1000);
215
-
216
- bustProjectCwdCache();
217
- // allProjectCwds (maxAgeMin Infinity, maxCwds 500) sees both — cached
218
- // first under its own key.
219
- const all = allProjectCwds({ projectsDir });
220
- assert.ok(all.includes(cwdFresh) && all.includes(cwdStale));
221
-
222
- // activeProjectCwds(90) must recompute under its OWN key, not return
223
- // allProjectCwds' cached (Infinity, 500) result — proving the cache key
224
- // includes maxAgeMin/maxCwds, not just projectsDir.
225
- const active = activeProjectCwds(90, { projectsDir });
226
- assert.ok(active.includes(cwdFresh), 'fresh cwd must be present');
227
- assert.ok(!active.includes(cwdStale), 'stale cwd must be excluded by the 90-min filter');
228
- } finally {
229
- fs.rmSync(base, { recursive: true, force: true });
230
- }
231
- });
232
-
233
- test('missing projectsDir returns [] and does not poison the cache once the dir appears', () => {
234
- const base = tmpDir();
235
- try {
236
- const projectsDir = path.join(base, 'projects');
237
- bustProjectCwdCache();
238
-
239
- assert.deepEqual(activeProjectCwds(90, { projectsDir }), []);
240
- assert.deepEqual(activeProjectCwds(90, { projectsDir }), []);
241
-
242
- const cwdA = path.join(base, 'proj-a');
243
- fs.mkdirSync(cwdA);
244
- writeTranscript(projectsDir, 'slug-a', 'a.jsonl', cwdA, 5 * 60 * 1000);
245
-
246
- const result = activeProjectCwds(90, { projectsDir });
247
- assert.deepEqual(result, [cwdA], 'the dir appearing later must be visible, not stuck on a cached []');
248
- } finally {
249
- fs.rmSync(base, { recursive: true, force: true });
250
- }
251
- });