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,110 +0,0 @@
1
- /**
2
- * flatPrdTickSweep.test.cjs — the retired flat `scheduler/prds/` dir must be
3
- * TRULY inert, not just documented as such.
4
- *
5
- * Prior to this PRD, `runPrdMigration()`'s consolidation of the flat dir into
6
- * `prds-archived/` ran ONLY at Electron boot (src/main/scheduler.cjs). But
7
- * `prdLocations.cjs`'s `resolvePrdsDirs()` unconditionally keeps scanning the
8
- * flat dir as a live PRD source, and `reconcile()` runs on every tick — so a
9
- * PRD hand-written into the flat dir *after* boot sat there live and WOULD
10
- * get reconciled into a pending job and executed (observed 2026-08-07:
11
- * 1021/1022 PRDs in social-signals-trader executed once their status was
12
- * repaired), contradicting the develop skill's documented claim that
13
- * anything landed there is "auto-consolidated ... WITHOUT being executed."
14
- *
15
- * The fix: `consolidateAllFlatPrds()` now also runs at the START of every
16
- * `reconcile()` call itself (not just one caller like tickQueue's poll — every
17
- * caller of reconcile gets the guarantee), BEFORE reconcile scans the flat
18
- * dir. A freshly hand-written PRD has no queue row yet (reconcile hasn't
19
- * seen it), so it is never in LIVE_JOB_STATUSES — this sweep archives it
20
- * before reconcile ever gets a chance to turn it into a job. This test
21
- * proves that invariant directly against `consolidateAllFlatPrds`: a file
22
- * with no matching queue job is swept into `prds-archived/` on the very next
23
- * call, which prdLocations.cjs's `resolvePrdsDirs()` never scans as a live
24
- * source — so it can never be reconciled into a job afterward.
25
- *
26
- * Run: timeout 120 npx vitest run src/main/__tests__/flatPrdTickSweep.test.cjs
27
- */
28
-
29
- 'use strict';
30
-
31
- import { test, expect, afterEach } from 'vitest';
32
- const fs = require('node:fs');
33
- const fsp = require('node:fs/promises');
34
- const os = require('node:os');
35
- const path = require('node:path');
36
- const { consolidateAllFlatPrds } = require('../scheduler.cjs');
37
- const { resolvePrdWriteDir, resolvePrdsDirs } = require('../lib/prdLocations.cjs');
38
-
39
- const tmpDirs = [];
40
- afterEach(async () => {
41
- while (tmpDirs.length) {
42
- const d = tmpDirs.pop();
43
- await fsp.rm(d, { recursive: true, force: true });
44
- }
45
- });
46
-
47
- function newProjectRoot() {
48
- const d = fs.mkdtempSync(path.join(os.tmpdir(), 'sm-flat-tick-sweep-'));
49
- tmpDirs.push(d);
50
- return d;
51
- }
52
-
53
- test('a PRD hand-written into the retired flat dir after boot is swept before it could ever be reconciled', async () => {
54
- const cwd = newProjectRoot();
55
- const flatDir = resolvePrdWriteDir(cwd);
56
- await fsp.mkdir(flatDir, { recursive: true });
57
- const filename = '999-hand-written-bypass.md';
58
- await fsp.writeFile(
59
- path.join(flatDir, filename),
60
- `---\ntitle: Hand-written bypass\ncwd: ${cwd}\nestimateMinutes: 10\n---\n\n# Goal\n\nSomething.\n`,
61
- 'utf8',
62
- );
63
- // No queue.json at all yet — this is exactly the state of a PRD dropped on
64
- // disk moments ago, before any reconcile() pass has scanned it into a job.
65
-
66
- await consolidateAllFlatPrds([cwd]);
67
-
68
- // Swept out of the live flat dir...
69
- expect(fs.existsSync(path.join(flatDir, filename))).toBe(false);
70
- // ...and into prds-archived/, which resolvePrdsDirs() never returns as a
71
- // scan source — so no future reconcile() pass can find it and queue it.
72
- const archivedPath = path.join(path.dirname(flatDir), 'prds-archived', filename);
73
- expect(fs.existsSync(archivedPath)).toBe(true);
74
-
75
- const liveDirs = resolvePrdsDirs(Infinity, { projectsDir: path.join(cwd, '.nonexistent') });
76
- expect(liveDirs.every((d) => !d.includes('prds-archived'))).toBe(true);
77
- });
78
-
79
- test('consolidateAllFlatPrds still protects a PRD that already has a live queue job (PRD 992 invariant preserved)', async () => {
80
- const cwd = newProjectRoot();
81
- const flatDir = resolvePrdWriteDir(cwd);
82
- await fsp.mkdir(flatDir, { recursive: true });
83
- const stateDir = path.join(cwd, 'session-manager-operations', 'scheduler', 'state');
84
- await fsp.mkdir(stateDir, { recursive: true });
85
- await fsp.writeFile(
86
- path.join(flatDir, '998-live.md'),
87
- `---\ntitle: Live\ncwd: ${cwd}\nestimateMinutes: 10\n---\n\n# Goal\n`,
88
- 'utf8',
89
- );
90
- await fsp.writeFile(
91
- path.join(stateDir, 'queue.json'),
92
- JSON.stringify({ jobs: [{ slug: '998-live', status: 'running' }] }),
93
- 'utf8',
94
- );
95
-
96
- await consolidateAllFlatPrds([cwd]);
97
-
98
- expect(fs.existsSync(path.join(flatDir, '998-live.md'))).toBe(true);
99
- });
100
-
101
- test('consolidateAllFlatPrds never throws when a project errors — one bad cwd does not block the sweep of the rest', async () => {
102
- const good = newProjectRoot();
103
- const flatDir = resolvePrdWriteDir(good);
104
- await fsp.mkdir(flatDir, { recursive: true });
105
- await fsp.writeFile(path.join(flatDir, '997-ok.md'), `---\ntitle: Ok\ncwd: ${good}\nestimateMinutes: 5\n---\n\n# Goal\n`, 'utf8');
106
-
107
- await expect(consolidateAllFlatPrds([null, good])).resolves.toBeUndefined();
108
-
109
- expect(fs.existsSync(path.join(flatDir, '997-ok.md'))).toBe(false);
110
- });
@@ -1,39 +0,0 @@
1
- /**
2
- * health-build-freshness.test.cjs — evaluateBuildFreshness separates
3
- * restart-needed (installed differs from running) from publish-needed
4
- * (repo HEAD differs from installed); both reported, never critical.
5
- *
6
- * Run: timeout 120 npx vitest run src/main/__tests__/health-build-freshness.test.cjs
7
- */
8
- 'use strict';
9
-
10
- import { test, expect } from 'vitest';
11
- const { evaluateBuildFreshness } = require('../health.cjs');
12
-
13
- test('all shas equal → nothing needed', () => {
14
- const r = evaluateBuildFreshness({ running: 'abc1234', installedOnDisk: 'abc1234', repoHead: 'abc1234' });
15
- expect(r).toMatchObject({ ok: true, restartNeeded: false, publishNeeded: false });
16
- });
17
-
18
- test('installed differs from running → restart needed only', () => {
19
- const r = evaluateBuildFreshness({ running: 'aaa1111', installedOnDisk: 'bbb2222', repoHead: 'bbb2222' });
20
- expect(r).toMatchObject({ ok: true, restartNeeded: true, publishNeeded: false });
21
- });
22
-
23
- test('repo HEAD differs from installed → publish needed only', () => {
24
- const r = evaluateBuildFreshness({ running: 'bbb2222', installedOnDisk: 'bbb2222', repoHead: 'ccc3333' });
25
- expect(r).toMatchObject({ ok: true, restartNeeded: false, publishNeeded: true });
26
- });
27
-
28
- test('both differ → both reported, still ok (non-critical)', () => {
29
- const r = evaluateBuildFreshness({ running: 'aaa1111', installedOnDisk: 'bbb2222', repoHead: 'ccc3333' });
30
- expect(r).toMatchObject({ ok: true, restartNeeded: true, publishNeeded: true });
31
- expect(r.note).toMatch(/restart needed/);
32
- expect(r.note).toMatch(/publish needed/);
33
- });
34
-
35
- test('unknown inputs never claim a difference; short/long sha prefixes match', () => {
36
- expect(evaluateBuildFreshness({})).toMatchObject({ restartNeeded: false, publishNeeded: false });
37
- expect(evaluateBuildFreshness({ running: null, installedOnDisk: 'abc1234', repoHead: 'abc1234567890' }))
38
- .toMatchObject({ restartNeeded: false, publishNeeded: false });
39
- });
@@ -1,57 +0,0 @@
1
- /**
2
- * health-claude-md-budget.test.cjs — CLAUDE.md SIZE BUDGET enforcement
3
- * (PRD 1039, following CLAUDE.md's growth from 3,871 to 65,768 chars between
4
- * 2026-05-09 and 2026-08-13 with zero of 359 PRDs ever pruning it). Exercises
5
- * parseClaudeMdBudget()/evaluateClaudeMdBudget() directly since they're pure —
6
- * no need to spawn the full check() to cover this.
7
- *
8
- * Run: timeout 120 npx vitest run src/main/__tests__/health-claude-md-budget.test.cjs
9
- */
10
-
11
- 'use strict';
12
-
13
- import { test, expect } from 'vitest';
14
- const { parseClaudeMdBudget, evaluateClaudeMdBudget } = require('../health.cjs');
15
-
16
- test('under budget reports ok with no issue', () => {
17
- const result = evaluateClaudeMdBudget(11873, 12000);
18
- expect(result.ok).toBe(true);
19
- expect(result.applicable).toBe(true);
20
- expect(result.message).toBeUndefined();
21
- });
22
-
23
- test('exactly at budget reports ok with no issue', () => {
24
- const result = evaluateClaudeMdBudget(12000, 12000);
25
- expect(result.ok).toBe(true);
26
- expect(result.applicable).toBe(true);
27
- });
28
-
29
- test('over budget reports one issue with actual size and budget in the message', () => {
30
- const result = evaluateClaudeMdBudget(13210, 12000);
31
- expect(result.ok).toBe(false);
32
- expect(result.overage).toBe(1210);
33
- expect(result.message).toContain('13210');
34
- expect(result.message).toContain('12000');
35
- expect(result.message).toContain('1210');
36
- });
37
-
38
- test('no SIZE BUDGET line present -> parses to null, evaluator skips silently', () => {
39
- const text = '# Some Project\n\nJust a normal CLAUDE.md with no budget declared.\n';
40
- const budget = parseClaudeMdBudget(text);
41
- expect(budget).toBeNull();
42
- const result = evaluateClaudeMdBudget(50000, budget);
43
- expect(result.ok).toBe(true);
44
- expect(result.applicable).toBe(false);
45
- });
46
-
47
- test('malformed/unparseable budget line -> null, no throw', () => {
48
- const text = '> **SIZE BUDGET — a lot of chars**, checked before every commit.';
49
- expect(() => parseClaudeMdBudget(text)).not.toThrow();
50
- const budget = parseClaudeMdBudget(text);
51
- expect(budget).toBeNull();
52
- });
53
-
54
- test('comma-separated form parses to a plain integer', () => {
55
- const text = '> **SIZE BUDGET — 12,000 chars**, checked with `wc -c CLAUDE.md` before every commit.';
56
- expect(parseClaudeMdBudget(text)).toBe(12000);
57
- });
@@ -1,81 +0,0 @@
1
- /**
2
- * health-credentials.test.cjs — the credential health component.
3
- *
4
- * An expired/absent Claude OAuth token silently voids the whole scheduler:
5
- * headless `claude -p` jobs cannot authenticate, so the queue "runs" but
6
- * nothing completes. On this machine the token expired 2026-04-04 with no
7
- * refresh token, yet `npm run health` read GREEN — no component pointed the
8
- * operator at `claude login`. evaluateCredentialHealth is the missing signal.
9
- * Pure over an injected credState (the shape refreshIfNeeded returns), so no
10
- * Keychain access here.
11
- *
12
- * Run: timeout 120 npx vitest run src/main/__tests__/health-credentials.test.cjs
13
- */
14
-
15
- 'use strict';
16
-
17
- import { test, expect } from 'vitest';
18
- const { evaluateCredentialHealth } = require('../health.cjs');
19
-
20
- const NOW = Date.parse('2026-09-23T15:00:00.000Z');
21
-
22
- test('an expired token is not ok, names claude login, and reports how long ago it lapsed', () => {
23
- const expiredAt = NOW - 90 * 60_000; // 90 min ago
24
- const { component, issues } = evaluateCredentialHealth({
25
- credState: { kind: 'auth', message: 'Credentials expired.', expiredAt },
26
- now: NOW,
27
- });
28
- expect(component.ok).toBe(false);
29
- expect(component.state).toBe('expired');
30
- expect(component.expiredAt).toBe(expiredAt);
31
- expect(component.message).toMatch(/claude login/);
32
- expect(component.message).toMatch(/90m ago/);
33
- expect(issues.length).toBe(1);
34
- expect(issues[0]).toMatch(/cannot authenticate/i);
35
- });
36
-
37
- test('an auth failure with no expiredAt still fails and still names the fix', () => {
38
- const { component, issues } = evaluateCredentialHealth({
39
- credState: { kind: 'auth', message: 'refresh rejected: HTTP 401' },
40
- now: NOW,
41
- });
42
- expect(component.ok).toBe(false);
43
- expect(component.state).toBe('expired');
44
- expect(component.message).toMatch(/claude login/);
45
- expect(component.message).not.toMatch(/NaN/);
46
- expect(issues.length).toBe(1);
47
- });
48
-
49
- test('unreadable/absent credentials (kind:config) fail with the login fix', () => {
50
- const { component, issues } = evaluateCredentialHealth({
51
- credState: { kind: 'config', message: 'credentials not found' },
52
- now: NOW,
53
- });
54
- expect(component.ok).toBe(false);
55
- expect(component.state).toBe('unreadable');
56
- expect(component.message).toMatch(/claude login/);
57
- expect(issues.length).toBe(1);
58
- });
59
-
60
- test('a fresh token is ok and raises no issue', () => {
61
- const { component, issues } = evaluateCredentialHealth({ credState: { kind: 'ok' }, now: NOW });
62
- expect(component.ok).toBe(true);
63
- expect(component.state).toBe('valid');
64
- expect(issues.length).toBe(0);
65
- });
66
-
67
- test('kind:unsupported (auto-refresh unavailable, token still valid) is ok — the token works, refresh just can not', () => {
68
- const { component, issues } = evaluateCredentialHealth({ credState: { kind: 'unsupported' }, now: NOW });
69
- expect(component.ok).toBe(true);
70
- expect(component.state).toBe('valid-no-refresh');
71
- expect(issues.length).toBe(0);
72
- });
73
-
74
- test('a missing/garbage credState never throws and never fails health (unknown, not a false alarm)', () => {
75
- for (const bad of [undefined, null, 'nope', 42]) {
76
- const { component, issues } = evaluateCredentialHealth({ credState: bad, now: NOW });
77
- expect(component.ok).toBe(true);
78
- expect(component.state).toBe('unknown');
79
- expect(issues.length).toBe(0);
80
- }
81
- });
@@ -1,124 +0,0 @@
1
- /**
2
- * health-delegation-chain.test.cjs — "can this machine actually delegate
3
- * work to the scheduler?" health section (PRD 1049), built on top of the
4
- * delegation-readiness probe (delegationReadiness.cjs, PRD 1048). Exercises
5
- * evaluateDelegationChainHealth() directly since it's pure — no need to spawn
6
- * the full check() to cover shaping/degradation — plus one end-to-end check()
7
- * run against this repo's own real config, where every check is expected to
8
- * pass (this repo registers the scheduler MCP in its own .mcp.json and wires
9
- * guard-prd-writes in .claude/settings.json).
10
- *
11
- * Run: timeout 120 npx vitest run src/main/__tests__/health-delegation-chain.test.cjs
12
- */
13
-
14
- 'use strict';
15
-
16
- import { test, expect } from 'vitest';
17
- const { evaluateDelegationChainHealth, check } = require('../health.cjs');
18
-
19
- function makeCheck(id, ok, overrides = {}) {
20
- return { id, label: `${id} label`, ok, detail: `${id} detail`, fix: ok ? null : `fix ${id}`, ...overrides };
21
- }
22
-
23
- test('all checks passing -> component ok, no issues', () => {
24
- const delegationResult = {
25
- ok: true,
26
- checks: [
27
- makeCheck('scheduler-mcp', true),
28
- makeCheck('scheduler-mcp-live', true),
29
- makeCheck('scheduler-mcp-project-duplicate', true, { warn: false }),
30
- makeCheck('dev-plugin', true),
31
- makeCheck('agent-personas', true),
32
- makeCheck('prd-write-guard', true),
33
- ],
34
- };
35
- const { component, issues } = evaluateDelegationChainHealth(delegationResult);
36
- expect(component.ok).toBe(true);
37
- expect(component.checks).toHaveLength(6);
38
- expect(issues).toEqual([]);
39
- });
40
-
41
- test('one failing check -> component not ok, one issue citing label/detail/fix', () => {
42
- const delegationResult = {
43
- ok: false,
44
- checks: [
45
- makeCheck('scheduler-mcp', false, { label: 'Scheduler MCP server registered', detail: 'no entry found', fix: 'claude mcp add ...' }),
46
- makeCheck('scheduler-mcp-live', true, { skipped: true }),
47
- makeCheck('scheduler-mcp-project-duplicate', true, { warn: false }),
48
- makeCheck('dev-plugin', true),
49
- makeCheck('agent-personas', true),
50
- makeCheck('prd-write-guard', true),
51
- ],
52
- };
53
- const { component, issues } = evaluateDelegationChainHealth(delegationResult);
54
- expect(component.ok).toBe(false);
55
- expect(issues).toHaveLength(1);
56
- expect(issues[0]).toContain('Scheduler MCP server registered');
57
- expect(issues[0]).toContain('no entry found');
58
- expect(issues[0]).toContain('claude mcp add ...');
59
- });
60
-
61
- test('multiple failing checks -> one issue per failing check, passing checks silent', () => {
62
- const delegationResult = {
63
- ok: false,
64
- checks: [
65
- makeCheck('scheduler-mcp', false),
66
- makeCheck('scheduler-mcp-live', false),
67
- makeCheck('scheduler-mcp-project-duplicate', true, { warn: false }),
68
- makeCheck('dev-plugin', false),
69
- makeCheck('agent-personas', true),
70
- makeCheck('prd-write-guard', true),
71
- ],
72
- };
73
- const { issues } = evaluateDelegationChainHealth(delegationResult);
74
- expect(issues).toHaveLength(3);
75
- });
76
-
77
- test('failing check with no fix omits the "(fix: ...)" suffix', () => {
78
- const delegationResult = {
79
- ok: false,
80
- checks: [makeCheck('scheduler-mcp', false, { fix: null })],
81
- };
82
- const { issues } = evaluateDelegationChainHealth(delegationResult);
83
- expect(issues[0]).not.toContain('(fix:');
84
- });
85
-
86
- test('end-to-end: check() reports delegation_chain for this repo, expected to pass here', async () => {
87
- // Probes THIS machine's real user-scope config (~/.claude.json MCP registration, guard
88
- // shims), so it reads the real home — not the per-run sandbox HOME. Read-only: scheduler
89
- // state stays redirected to the sandbox (SM_SCHEDULER_HOME re-pinned after the HOME swap).
90
- const sandboxHome = process.env.HOME;
91
- const sandboxSchedulerHome = process.env.SM_SCHEDULER_HOME;
92
- process.env.HOME = require('node:os').userInfo().homedir;
93
- if (sandboxSchedulerHome !== undefined) process.env.SM_SCHEDULER_HOME = sandboxSchedulerHome;
94
- process.env.SM_ALLOW_LIVE_ROOT_READS = '1';
95
- let status;
96
- try {
97
- // skipTypecheck: this test asserts on delegation_chain only; the tsc shell-out was
98
- // ~15s of the ~16s idle runtime and starved to the 90s budget under CPU load.
99
- status = await check({ skipTypecheck: true });
100
- } finally {
101
- delete process.env.SM_ALLOW_LIVE_ROOT_READS;
102
- process.env.HOME = sandboxHome;
103
- }
104
- expect(status.components.delegation_chain).toBeDefined();
105
- expect(status.components.delegation_chain.checks).toHaveLength(9);
106
- const ids = status.components.delegation_chain.checks.map((c) => c.id);
107
- expect(ids).toEqual([
108
- 'scheduler-mcp',
109
- 'scheduler-mcp-live',
110
- 'scheduler-mcp-project-duplicate',
111
- 'dev-plugin',
112
- 'agent-personas',
113
- 'prd-write-guard',
114
- 'destructive-git-guard',
115
- 'inline-implementation-guard',
116
- 'self-schedule-guard',
117
- ]);
118
- // This repo registers the scheduler MCP at user scope (~/.claude.json) and
119
- // wires guard-prd-writes in .claude/settings.json, and no longer carries a
120
- // project-scope duplicate in its own .mcp.json, so on this machine every
121
- // check is expected to pass — a failure here means the probe or the
122
- // wiring is wrong, not that the assertion should be relaxed.
123
- expect(status.components.delegation_chain.ok).toBe(true);
124
- }, 90_000);
@@ -1,84 +0,0 @@
1
- /**
2
- * health-per-project-stall.test.cjs — per-project problem-count rollup and
3
- * per-project stall-past-threshold escalation for the scheduler_queue health
4
- * check. Covers the gap where a project holding ONLY failed/needs_review/
5
- * quarantined rows (0 running, 0 pending) never tripped evaluateTickLiveness
6
- * (which requires actual pending work) — the exact way the burrow project's
7
- * four quarantined PRDs went dark.
8
- *
9
- * Run: timeout 120 npx vitest run src/main/__tests__/health-per-project-stall.test.cjs
10
- */
11
-
12
- 'use strict';
13
-
14
- // vitest, NOT node:test — see the sibling note in
15
- // scheduler-stall-per-project.test.cjs. node:assert works inside vitest.
16
- import { test } from 'vitest';
17
- const assert = require('node:assert/strict');
18
- const {
19
- computeProjectProblemCounts,
20
- evaluatePerProjectStall,
21
- TICK_STALL_THRESHOLD_MS,
22
- } = require('../health.cjs');
23
- const { computeStallSummary } = require('../scheduler.cjs');
24
-
25
- test('computeProjectProblemCounts: breaks down failed/needs_review/quarantined by project, ignores healthy statuses', () => {
26
- const jobs = [
27
- { slug: 'a', cwd: '/burrow', status: 'quarantined' },
28
- { slug: 'b', cwd: '/burrow', status: 'quarantined' },
29
- { slug: 'c', cwd: '/burrow', status: 'quarantined' },
30
- { slug: 'd', cwd: '/burrow', status: 'quarantined' },
31
- { slug: 'e', cwd: '/other', status: 'failed' },
32
- { slug: 'f', cwd: '/other', status: 'needs_review' },
33
- { slug: 'g', cwd: '/other', status: 'running' },
34
- { slug: 'h', cwd: '/other', status: 'pending' },
35
- { slug: 'i', cwd: '/other', status: 'completed' },
36
- ];
37
- const counts = computeProjectProblemCounts(jobs);
38
- assert.deepStrictEqual(counts['/burrow'], { failed: 0, needs_review: 0, quarantined: 4 });
39
- assert.deepStrictEqual(counts['/other'], { failed: 1, needs_review: 1, quarantined: 0 });
40
- });
41
-
42
- test('evaluatePerProjectStall: fully-stalled project past threshold flags pastThreshold=true', () => {
43
- const state = {
44
- lastRunAt: new Date(Date.now() - (TICK_STALL_THRESHOLD_MS + 60_000)).toISOString(),
45
- paused: null,
46
- jobs: [
47
- { slug: 'a', cwd: '/burrow', status: 'quarantined' },
48
- { slug: 'b', cwd: '/other', status: 'running' },
49
- ],
50
- invalidJobs: [],
51
- };
52
- const summary = computeStallSummary(state);
53
- const result = evaluatePerProjectStall(summary, state.lastRunAt, Date.now(), TICK_STALL_THRESHOLD_MS);
54
- assert.strictEqual(result['/burrow'].stalled, true);
55
- assert.strictEqual(result['/burrow'].pastThreshold, true);
56
- assert.strictEqual(result['/other'].stalled, false);
57
- });
58
-
59
- test('evaluatePerProjectStall: stalled but NOT yet past threshold flags pastThreshold=false', () => {
60
- const state = {
61
- lastRunAt: new Date(Date.now() - 1000).toISOString(), // just ticked
62
- paused: null,
63
- jobs: [{ slug: 'a', cwd: '/burrow', status: 'quarantined' }],
64
- invalidJobs: [],
65
- };
66
- const summary = computeStallSummary(state);
67
- const result = evaluatePerProjectStall(summary, state.lastRunAt, Date.now(), TICK_STALL_THRESHOLD_MS);
68
- assert.strictEqual(result['/burrow'].stalled, true);
69
- assert.strictEqual(result['/burrow'].pastThreshold, false);
70
- });
71
-
72
- test('evaluatePerProjectStall: no lastRunAt yet — stalled but not asserted past threshold (caveat, not a false RED)', () => {
73
- const state = {
74
- lastRunAt: null,
75
- paused: null,
76
- jobs: [{ slug: 'a', cwd: '/burrow', status: 'quarantined' }],
77
- invalidJobs: [],
78
- };
79
- const summary = computeStallSummary(state);
80
- const result = evaluatePerProjectStall(summary, state.lastRunAt, Date.now(), TICK_STALL_THRESHOLD_MS);
81
- assert.strictEqual(result['/burrow'].stalled, true);
82
- assert.strictEqual(result['/burrow'].pastThreshold, false);
83
- assert.strictEqual(result['/burrow'].caveat, 'no-lastRunAt');
84
- });
@@ -1,37 +0,0 @@
1
- /**
2
- * health-prd-migration.test.cjs — stranded-PRD-migration health signal
3
- * (behind two real 2026-07-31 incidents: a single stranded PRD causing an
4
- * instant ENOENT job failure, and 223 stranded legacy PRDs + a missing
5
- * history.jsonl resurrecting 189 completed jobs). Exercises
6
- * evaluatePrdMigrationHealth() directly since it's pure — no need to spawn
7
- * the full check() (which shells out to npm run typecheck) to cover this.
8
- *
9
- * Run: timeout 120 npx vitest run src/main/__tests__/health-prd-migration.test.cjs
10
- */
11
-
12
- 'use strict';
13
-
14
- import { test, expect } from 'vitest';
15
- const { evaluatePrdMigrationHealth } = require('../health.cjs');
16
-
17
- const LEGACY_DIR = '/home/user/.claude/session-manager/scheduled-plans/prds';
18
-
19
- test('reports ok when nothing is stranded', () => {
20
- const result = evaluatePrdMigrationHealth({ moved: 3, skipped: 0, unresolved: [] }, LEGACY_DIR);
21
- expect(result.ok).toBe(true);
22
- expect(result.strandedCount).toBe(0);
23
- expect(result.legacyDir).toBe(LEGACY_DIR);
24
- expect(result.unresolved).toBeUndefined();
25
- });
26
-
27
- test('reports RED with count and legacy dir path when files are stranded', () => {
28
- const unresolved = [
29
- { file: '01-stuck.md', reason: 'no cwd in frontmatter' },
30
- { file: '02-stuck.md', reason: 'cwd does not exist on disk' },
31
- ];
32
- const result = evaluatePrdMigrationHealth({ moved: 0, skipped: 0, unresolved }, LEGACY_DIR);
33
- expect(result.ok).toBe(false);
34
- expect(result.strandedCount).toBe(2);
35
- expect(result.legacyDir).toBe(LEGACY_DIR);
36
- expect(result.unresolved).toEqual(unresolved);
37
- });
@@ -1,135 +0,0 @@
1
- /**
2
- * health-queue-dispatch.test.cjs — `npm run health` must report non-GREEN
3
- * when there is at least one DISPATCHABLE pending job (reusing
4
- * classifyQueueStarvation's own 'starved' verdict, not merely "pending"),
5
- * nothing running, and no launch in a long time — the exact shape
6
- * of the 2026-09-11 incident (27 pending across two projects, 0 running, for
7
- * days, every other health surface reporting green). A dependsOn-blocked
8
- * queue must NOT trip this the same way: ticking can't fix a blocked chain,
9
- * so it stays GREEN (reported as 'blocked' instead, distinctly).
10
- *
11
- * Exercises evaluateQueueDispatchHealth() directly — pure, no fs — matching
12
- * every other evaluate* helper's test pattern in this file (see
13
- * health-usage-poller.test.cjs's header).
14
- *
15
- * Run: timeout 120 npx vitest run src/main/__tests__/health-queue-dispatch.test.cjs
16
- */
17
-
18
- 'use strict';
19
-
20
- import { test, expect } from 'vitest';
21
- const { evaluateQueueDispatchHealth, DISPATCH_STALL_THRESHOLD_MS, DISPATCH_WARN_THRESHOLD_MS } = require('../health.cjs');
22
-
23
- const CWD = '/home/bilko/Projects/starry-night-ships';
24
- const NOW = Date.parse('2026-09-11T12:00:00.000Z');
25
- const idleFor = (ms) => new Date(NOW - ms).toISOString();
26
-
27
- test('a dispatchable pending job, 0 running, stale past the threshold — non-GREEN, starved', () => {
28
- const state = {
29
- jobs: [{ slug: 'a', cwd: CWD, status: 'pending', dependsOn: [] }],
30
- paused: null,
31
- lastRunAt: idleFor(DISPATCH_STALL_THRESHOLD_MS + 60_000),
32
- };
33
- const result = evaluateQueueDispatchHealth(state, 0, NOW);
34
- expect(result.ok).toBe(false);
35
- expect(result.starved).toBe(true);
36
- expect(result.dispatchable).toBe(1);
37
- expect(result.message).toMatch(/dispatch appears stuck/);
38
- });
39
-
40
- test('every pending row behind a blocked dependsOn chain stays GREEN, reported as blocked', () => {
41
- const state = {
42
- jobs: [
43
- { slug: 'dead', cwd: CWD, status: 'failed', dependsOn: [] },
44
- { slug: 'blocked-child', cwd: CWD, status: 'pending', dependsOn: ['dead'] },
45
- ],
46
- paused: null,
47
- lastRunAt: idleFor(DISPATCH_STALL_THRESHOLD_MS + 60_000),
48
- };
49
- const result = evaluateQueueDispatchHealth(state, 0, NOW);
50
- expect(result.ok).toBe(true);
51
- expect(result.blocked).toBe(true);
52
- expect(result.starved).toBeUndefined();
53
- expect(result.message).toMatch(/blocked/);
54
- });
55
-
56
- test('healthy queue (recent dispatch attempt) is GREEN with no verdict', () => {
57
- const state = {
58
- jobs: [{ slug: 'a', cwd: CWD, status: 'pending', dependsOn: [] }],
59
- paused: null,
60
- lastRunAt: idleFor(60_000),
61
- };
62
- const result = evaluateQueueDispatchHealth(state, 0, NOW);
63
- expect(result).toEqual({ ok: true });
64
- });
65
-
66
- test('nothing pending is GREEN regardless of how stale the dispatch timestamp is', () => {
67
- const state = {
68
- jobs: [{ slug: 'a', cwd: CWD, status: 'completed' }],
69
- paused: null,
70
- lastRunAt: idleFor(DISPATCH_STALL_THRESHOLD_MS + 60_000),
71
- };
72
- const result = evaluateQueueDispatchHealth(state, 0, NOW);
73
- expect(result).toEqual({ ok: true });
74
- });
75
-
76
- test('work already running is GREEN — the queue is flowing', () => {
77
- const state = {
78
- jobs: [{ slug: 'a', cwd: CWD, status: 'pending', dependsOn: [] }],
79
- paused: null,
80
- lastRunAt: idleFor(DISPATCH_STALL_THRESHOLD_MS + 60_000),
81
- };
82
- const result = evaluateQueueDispatchHealth(state, 1, NOW);
83
- expect(result).toEqual({ ok: true });
84
- });
85
-
86
- test('the two tiers are exported: 15-minute warn, 2-hour cold report', () => {
87
- expect(DISPATCH_WARN_THRESHOLD_MS).toBe(15 * 60_000);
88
- expect(DISPATCH_STALL_THRESHOLD_MS).toBe(2 * 60 * 60_000);
89
- });
90
-
91
- test('starved between the warn and cold thresholds — ok:true but flagged warn', () => {
92
- const state = {
93
- jobs: [{ slug: 'a', cwd: CWD, status: 'pending', dependsOn: [] }],
94
- paused: null,
95
- lastRunAt: idleFor(DISPATCH_WARN_THRESHOLD_MS + 60_000),
96
- };
97
- const result = evaluateQueueDispatchHealth(state, 0, NOW);
98
- expect(result.ok).toBe(true);
99
- expect(result.warn).toBe(true);
100
- expect(result.starved).toBeUndefined();
101
- expect(result.dispatchable).toBe(1);
102
- });
103
-
104
- test('below the warn threshold is plain GREEN', () => {
105
- const state = {
106
- jobs: [{ slug: 'a', cwd: CWD, status: 'pending', dependsOn: [] }],
107
- paused: null,
108
- lastRunAt: idleFor(DISPATCH_WARN_THRESHOLD_MS - 60_000),
109
- };
110
- expect(evaluateQueueDispatchHealth(state, 0, NOW)).toEqual({ ok: true });
111
- });
112
-
113
- test('ticks that launch nothing (fresh lastDispatchAttemptAt, stale lastRunAt) still go non-GREEN', () => {
114
- const state = {
115
- jobs: [{ slug: 'a', cwd: CWD, status: 'pending', dependsOn: [] }],
116
- paused: null,
117
- lastDispatchAttemptAt: idleFor(5_000),
118
- lastRunAt: idleFor(DISPATCH_STALL_THRESHOLD_MS + 60_000),
119
- };
120
- const result = evaluateQueueDispatchHealth(state, 0, NOW);
121
- expect(result.ok).toBe(false);
122
- expect(result.starved).toBe(true);
123
- });
124
-
125
- test('rows held by an open launch breaker read blocked, not starved', () => {
126
- const state = {
127
- jobs: [{ slug: 'a', cwd: CWD, status: 'pending', dependsOn: [] }],
128
- paused: null,
129
- lastRunAt: idleFor(DISPATCH_STALL_THRESHOLD_MS + 60_000),
130
- launchBlocks: { default: { kind: 'auth', at: NOW - 1000 } },
131
- };
132
- const result = evaluateQueueDispatchHealth(state, 0, NOW);
133
- expect(result.ok).toBe(true);
134
- expect(result.blocked).toBe(true);
135
- });