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,161 +0,0 @@
1
- /**
2
- * crossProjectFeedbackRoutes.test.cjs — the HTTP hop for the project-to-project
3
- * conduit (lib/crossProjectFeedback.cjs's registerAdminRoute).
4
- *
5
- * Why this is its own file. crossProjectFeedback.test.cjs drives
6
- * openFeedbackSession() directly, and the MCP tool definitions live in
7
- * scripts/scheduler-mcp-server.cjs — so the ROUTE REGISTRATION between them was
8
- * the one layer nothing exercised. That layer has a real, silent failure mode:
9
- * a route registered under a path the MCP client doesn't call (or not
10
- * registered at all) surfaces only as `{"ok":false,"error":"not found"}` from a
11
- * tool that otherwise looks perfectly wired. Confirmed live 2026-08-08 against
12
- * a running app whose process predated the route being added.
13
- *
14
- * These tests boot the real transport (localAdminHttp.cjs) on a throwaway port
15
- * and speak real HTTP to it, so the method+path pair is asserted end to end
16
- * rather than assumed.
17
- *
18
- * Run: timeout 300 npx vitest run src/main/__tests__/crossProjectFeedbackRoutes.test.cjs
19
- */
20
-
21
- 'use strict';
22
-
23
- import { test, expect, beforeAll, afterAll, afterEach } from 'vitest';
24
- const http = require('node:http');
25
- const fs = require('node:fs');
26
- const fsp = require('node:fs/promises');
27
- const os = require('node:os');
28
- const path = require('node:path');
29
- const config = require('../config.cjs');
30
- const { createAdminHttp, TOKEN_PATH } = require('../lib/localAdminHttp.cjs');
31
- const crossProjectFeedback = require('../lib/crossProjectFeedback.cjs');
32
- const { readActiveIndex } = require('../lib/epicMint.cjs');
33
-
34
- // Never let start() overwrite the RUNNING app's admin-api.json — that orphans
35
- // scheduler-mcp-server.cjs until an app restart (the incident documented in
36
- // localAdminHttp.cjs's resolveTokenPath).
37
- const TEST_TOKEN_PATH = path.join(path.dirname(TOKEN_PATH), `admin-api.xproj-test-${process.pid}.json`);
38
- process.env.SM_ADMIN_TOKEN_PATH = TEST_TOKEN_PATH;
39
-
40
- let adminHttp;
41
- let port;
42
- let token;
43
-
44
- beforeAll(async () => {
45
- adminHttp = createAdminHttp();
46
- crossProjectFeedback.registerAdminRoute(adminHttp);
47
- ({ port, token } = await adminHttp.start());
48
- });
49
-
50
- afterAll(async () => {
51
- if (adminHttp) await adminHttp.stop();
52
- fs.rmSync(TEST_TOKEN_PATH, { force: true });
53
- });
54
-
55
- const tmpDirs = [];
56
- afterEach(async () => {
57
- while (tmpDirs.length) await fsp.rm(tmpDirs.pop(), { recursive: true, force: true });
58
- });
59
-
60
- async function mkProject({ managed = true } = {}) {
61
- const cwd = await fsp.mkdtemp(path.join(os.tmpdir(), 'sm-xproj-route-'));
62
- config.addAllowedRoot(cwd);
63
- tmpDirs.push(cwd);
64
- if (managed) fs.mkdirSync(path.join(cwd, 'session-manager-operations'), { recursive: true });
65
- // Project-overlay fixture for the DEFAULT_FEEDBACK_AGENT ('architect') —
66
- // ensureEpic's write-time persona-existence check (epicMint.cjs) now
67
- // requires a real persona file to mint against; this keeps these tests
68
- // hermetic instead of depending on the host's ~/.claude/agents/.
69
- const agentsDir = path.join(cwd, '.claude', 'agents');
70
- fs.mkdirSync(agentsDir, { recursive: true });
71
- fs.writeFileSync(path.join(agentsDir, 'architect.md'), '---\nname: architect\n---\nFixture persona for tests.\n');
72
- return fs.realpathSync(cwd);
73
- }
74
-
75
- function request({ method = 'GET', path: reqPath, body, auth = true }) {
76
- return new Promise((resolve, reject) => {
77
- const headers = {};
78
- if (auth) headers.Authorization = `Bearer ${token}`;
79
- let payload;
80
- if (body !== undefined) {
81
- payload = typeof body === 'string' ? body : JSON.stringify(body);
82
- headers['Content-Type'] = 'application/json';
83
- headers['Content-Length'] = Buffer.byteLength(payload);
84
- }
85
- const req = http.request({ hostname: '127.0.0.1', port, method, path: reqPath, headers }, (res) => {
86
- let data = '';
87
- res.on('data', (c) => { data += c; });
88
- res.on('end', () => {
89
- let json = null;
90
- try { json = JSON.parse(data); } catch { /* non-JSON body */ }
91
- resolve({ status: res.statusCode, json, raw: data });
92
- });
93
- });
94
- req.on('error', reject);
95
- if (payload !== undefined) req.write(payload);
96
- req.end();
97
- });
98
- }
99
-
100
- // ---------------------------------------------------------------------------
101
- // The exact method+path pairs scripts/scheduler-mcp-server.cjs calls.
102
- // If either of these two tests fails, the MCP tool is dead in the water and
103
- // reports only "not found".
104
- // ---------------------------------------------------------------------------
105
-
106
- test('GET /admin/feedback/targets is registered and answers', async () => {
107
- // Scanned against an EMPTY throwaway root, never the developer's real
108
- // ~/.claude/projects/ — the transcripts tests create and delete folders
109
- // there in their own afterEach, and scanning it made this test race their
110
- // teardown (green alone, intermittently red under the full suite).
111
- const emptyRoot = await fsp.mkdtemp(path.join(os.tmpdir(), 'sm-xproj-scan-'));
112
- tmpDirs.push(emptyRoot);
113
- const res = await request({
114
- method: 'GET',
115
- path: `/admin/feedback/targets?projectsDir=${encodeURIComponent(emptyRoot)}`,
116
- });
117
- expect(res.status).toBe(200);
118
- expect(res.json.ok).toBe(true);
119
- expect(res.json.projects).toEqual([]);
120
- });
121
-
122
- test('POST /admin/feedback/open-session is registered and delivers', async () => {
123
- const to = await mkProject();
124
- const from = await mkProject();
125
- const res = await request({
126
- method: 'POST',
127
- path: '/admin/feedback/open-session',
128
- body: { toCwd: to, fromCwd: from, title: 'Route smoke', body: 'Delivered over real HTTP.' },
129
- });
130
- expect(res.status).toBe(200);
131
- expect(res.json.ok).toBe(true);
132
- expect(res.json.status).toBe('proposed');
133
-
134
- // The write really landed in the receiving project, not just in the response.
135
- const epic = readActiveIndex(to).sessions[res.json.epicId];
136
- expect(epic.status).toBe('proposed');
137
- expect(epic.source.producer).toBe('cross-project-feedback');
138
- });
139
-
140
- test('a refusal comes back as a 400 with the reason, not a 500 or a silent 200', async () => {
141
- const p = await mkProject();
142
- const res = await request({
143
- method: 'POST',
144
- path: '/admin/feedback/open-session',
145
- body: { toCwd: p, fromCwd: p, title: 'Same project', body: 'Should be refused.' },
146
- });
147
- expect(res.status).toBe(400);
148
- expect(res.json.ok).toBe(false);
149
- expect(res.json.error).toMatch(/\/develop/);
150
- });
151
-
152
- test('a malformed JSON body is a 400, never an unhandled throw', async () => {
153
- const res = await request({ method: 'POST', path: '/admin/feedback/open-session', body: '{not json' });
154
- expect(res.status).toBe(400);
155
- expect(res.json.error).toMatch(/invalid JSON body/);
156
- });
157
-
158
- test('both routes are behind the transport\'s bearer auth', async () => {
159
- expect((await request({ method: 'GET', path: '/admin/feedback/targets', auth: false })).status).toBe(401);
160
- expect((await request({ method: 'POST', path: '/admin/feedback/open-session', body: {}, auth: false })).status).toBe(401);
161
- });
@@ -1,77 +0,0 @@
1
- /**
2
- * PRD 1286 — archiving a row must never orphan its dependents, and a fully
3
- * blocked queue must never read healthy.
4
- *
5
- * Option (b): the depends-gate (computeDepHistorySatisfaction) treats a dep
6
- * whose PRD file was archived — including the manual-archive layout
7
- * prds-archived/<ISO-ts>/<slug>.md — as satisfied. A dep with no row, no
8
- * history and no archived file still HOLDS.
9
- *
10
- * Run: timeout 120 npx vitest run src/main/__tests__/dep-orphan-archive-health.test.cjs
11
- */
12
-
13
- 'use strict';
14
-
15
- import { test, expect } from 'vitest';
16
- import fs from 'node:fs';
17
- import os from 'node:os';
18
- import path from 'node:path';
19
-
20
- const tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), 'sm-1286-home-'));
21
- process.env.HOME = tmpHome;
22
-
23
- const scheduler = require('../scheduler.cjs');
24
- const { pickNextBatch } = require('../lib/schedulerBatch.cjs');
25
- const { evaluateUnresolvableDepHealth } = require('../health.cjs');
26
-
27
- function projectWithDependent(dep) {
28
- const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'sm-1286-proj-'));
29
- const jobs = [{ slug: '902-next', status: 'pending', cwd, dependsOn: [dep] }];
30
- return { cwd, jobs };
31
- }
32
-
33
- async function eligible(jobs) {
34
- const satisfiedSlugsByCwd = await scheduler.computeDepHistorySatisfaction({ jobs });
35
- const { batch: picked } = pickNextBatch(jobs, new Set(), 3, { satisfiedSlugsByCwd });
36
- return { batch: picked.map((j) => j.slug ?? j.job?.slug ?? j), satisfiedSlugsByCwd };
37
- }
38
-
39
- test('a dep archived via the manual-archive layout (prds-archived/<ts>/) leaves its dependent eligible', async () => {
40
- const { cwd, jobs } = projectWithDependent('fo-01-base'); // bare slug, as authored
41
- const dir = path.join(cwd, 'session-manager-operations', 'scheduler', 'epics', 'e1', 'prds-archived', '2026-09-18T01-00-00-000Z');
42
- fs.mkdirSync(dir, { recursive: true });
43
- fs.writeFileSync(path.join(dir, '900-fo-01-base.md'), '# Goal\n');
44
- const { batch } = await eligible(jobs);
45
- expect(batch).toContain('902-next');
46
- });
47
-
48
- test('a dep that never ran (no row, history or archived file) keeps its dependent held', async () => {
49
- const { jobs } = projectWithDependent('fo-01-base');
50
- const { batch } = await eligible(jobs);
51
- expect(batch).not.toContain('902-next');
52
- });
53
-
54
- test('health: every pending row held behind one unresolvable root is non-GREEN and names the root', async () => {
55
- const { cwd } = projectWithDependent('fo-01-base');
56
- const jobs = [
57
- { slug: '902-a', status: 'pending', cwd, dependsOn: ['fo-01-base'] },
58
- { slug: '903-b', status: 'pending', cwd, dependsOn: ['a'] }, // transitive, bare
59
- ];
60
- const satisfied = await scheduler.computeDepHistorySatisfaction({ jobs });
61
- const res = evaluateUnresolvableDepHealth(jobs, satisfied);
62
- expect(res.ok).toBe(false);
63
- expect(res.projects[0].roots).toEqual(['fo-01-base']);
64
- expect(res.message).toContain('fo-01-base');
65
- });
66
-
67
- test('health: a project with any dispatchable pending row, or a satisfied root, stays GREEN', async () => {
68
- const { cwd } = projectWithDependent('x');
69
- const mixed = [
70
- { slug: '902-a', status: 'pending', cwd, dependsOn: ['fo-01-base'] },
71
- { slug: '903-free', status: 'pending', cwd, dependsOn: [] },
72
- ];
73
- const satisfied = await scheduler.computeDepHistorySatisfaction({ jobs: mixed });
74
- expect(evaluateUnresolvableDepHealth(mixed, satisfied).ok).toBe(true);
75
- const satisfiedRoot = new Map([[cwd, new Set(['900-fo-01-base'])]]);
76
- expect(evaluateUnresolvableDepHealth([mixed[0]], satisfiedRoot).ok).toBe(true);
77
- });
@@ -1,70 +0,0 @@
1
- /**
2
- * develop-skill-failure-modes.test.cjs — drift guard for the two
3
- * scheduler_create_prd failure-mode branches in the /develop skill.
4
- *
5
- * PRD 1024-1030 incident (2026-08-08): social-signals-trader's session
6
- * hand-wrote 7 PRDs because scheduler_create_prd was ABSENT from its tool
7
- * list (the project's .mcp.json didn't register the server yet) — not
8
- * because the tool errored as unreachable. The old wording only named the
9
- * "tool errors ... unreachable" case, which an absent tool never matches,
10
- * so an agent in that situation had no documented path except hand-writing.
11
- * This test asserts the fix (two named failure modes, with the absent-tool
12
- * case explicitly forbidding hand-writing) is present and doesn't silently
13
- * regress back to the single-case wording.
14
- *
15
- * Run: timeout 120 npx vitest run src/main/__tests__/develop-skill-failure-modes.test.cjs
16
- */
17
-
18
- 'use strict';
19
-
20
- const fs = require('fs');
21
- const path = require('path');
22
-
23
- import { test, expect } from 'vitest';
24
-
25
- const SKILL_MD = path.resolve(
26
- __dirname,
27
- '..',
28
- '..',
29
- '..',
30
- 'plugins',
31
- 'session-manager-dev',
32
- 'skills',
33
- 'develop',
34
- 'SKILL.md'
35
- );
36
-
37
- function readSkill() {
38
- return fs.readFileSync(SKILL_MD, 'utf8');
39
- }
40
-
41
- test('SKILL.md names both failure modes explicitly', () => {
42
- const text = readSkill();
43
- expect(text).toMatch(/tool PRESENT but ERRORS/i);
44
- expect(text).toMatch(/tool ABSENT from your tool list/i);
45
- });
46
-
47
- test('the absent-tool branch explicitly forbids hand-writing and says STOP', () => {
48
- const text = readSkill();
49
- const absentIdx = text.search(/tool ABSENT from your tool list/i);
50
- expect(absentIdx).toBeGreaterThan(-1);
51
- const nearby = text.slice(absentIdx, absentIdx + 1200);
52
- expect(nearby).toMatch(/STOP/);
53
- expect(nearby).toMatch(/[Dd]o not write any PRD file/);
54
- expect(nearby).toMatch(/misconfiguration/i);
55
- });
56
-
57
- test('the present-but-erroring branch is the only one pointed at the manual-write fallback', () => {
58
- const text = readSkill();
59
- expect(text).toMatch(/Fallback for case \(a\) only/);
60
- });
61
-
62
- test('the standalone preflight check appears before PRD composition begins', () => {
63
- const text = readSkill();
64
- expect(text).toMatch(/Preflight — confirm the tool is even in your tool list/);
65
- });
66
-
67
- test('a preflight-tool-registration fix is named for the human (user-scope claude mcp add)', () => {
68
- const text = readSkill();
69
- expect(text).toMatch(/claude mcp add session-manager-scheduler --scope\s*\n?\s*user/);
70
- });
@@ -1,244 +0,0 @@
1
- /**
2
- * docEdit.test.cjs — unit tests for docEdit.cjs's pure helpers (PRD 638).
3
- *
4
- * Run: timeout 300 npx vitest run src/main/__tests__/docEdit.test.cjs
5
- */
6
-
7
- 'use strict';
8
-
9
- import { test, expect, describe, beforeEach, vi } from 'vitest';
10
-
11
- // docEdit.cjs requires chatRunner.cjs at module scope and calls `chatRunner.run(...)`
12
- // as a property access, so patching `run` on the already-required (cached) module
13
- // object — before docEdit.cjs's own require resolves to the same singleton — is
14
- // enough to intercept it, mirroring the exchanges.cjs patch pattern in chatRunner.spec.ts.
15
- const chatRunnerModule = require('../chatRunner.cjs');
16
- const runCalls = [];
17
- beforeEach(() => { runCalls.length = 0; });
18
- chatRunnerModule.run = (opts) => { runCalls.push(opts); };
19
-
20
- const { parseDocEdit, editPrompt, truncateDocumentText, MAX_DOC_CONTEXT, docEditViaSession, attachWindow } = require('../docEdit.cjs');
21
- const { duplicateNameFor } = require('../files.cjs');
22
-
23
- const broadcasts = [];
24
- attachWindow({
25
- isDestroyed: () => false,
26
- webContents: { isDestroyed: () => false, send: (channel, payload) => broadcasts.push({ channel, payload }) },
27
- });
28
- beforeEach(() => { broadcasts.length = 0; });
29
-
30
- describe('parseDocEdit', () => {
31
- test('valid JSON', () => {
32
- const result = parseDocEdit('{"after":"rewritten text"}');
33
- expect(result).toEqual({ ok: true, after: 'rewritten text' });
34
- });
35
-
36
- test('JSON embedded in prose', () => {
37
- const result = parseDocEdit('Sure, here you go:\n{"after":"rewritten text"}\nHope that helps!');
38
- expect(result).toEqual({ ok: true, after: 'rewritten text' });
39
- });
40
-
41
- test('missing after', () => {
42
- const result = parseDocEdit('{"other":"value"}');
43
- expect(result.ok).toBe(false);
44
- expect(result.error).toBeTruthy();
45
- });
46
-
47
- test('empty after', () => {
48
- const result = parseDocEdit('{"after":""}');
49
- expect(result.ok).toBe(false);
50
- expect(result.error).toBeTruthy();
51
- });
52
-
53
- test('non-string after', () => {
54
- const result = parseDocEdit('{"after":42}');
55
- expect(result.ok).toBe(false);
56
- expect(result.error).toBeTruthy();
57
- });
58
-
59
- test('over-length after', () => {
60
- const result = parseDocEdit(JSON.stringify({ after: 'x'.repeat(16001) }));
61
- expect(result.ok).toBe(false);
62
- expect(result.error).toBeTruthy();
63
- });
64
-
65
- test('no JSON object in output at all', () => {
66
- const result = parseDocEdit('not json at all, just prose garbage');
67
- expect(result.ok).toBe(false);
68
- expect(result.error).toBeTruthy();
69
- });
70
-
71
- test('empty/null input', () => {
72
- expect(parseDocEdit('').ok).toBe(false);
73
- expect(parseDocEdit(null).ok).toBe(false);
74
- });
75
- });
76
-
77
- describe('editPrompt', () => {
78
- test('omits the document block when documentText is absent', () => {
79
- const prompt = editPrompt('selected text', 'make it concise');
80
- expect(prompt).not.toMatch(/<document_/);
81
- });
82
-
83
- test('includes a nonce-tagged document block when documentText is provided', () => {
84
- const prompt = editPrompt('selected text', 'make it concise', 'the whole document');
85
- expect(prompt).toMatch(/<document_[0-9a-f]+>/);
86
- expect(prompt).toContain('the whole document');
87
- });
88
-
89
- test('truncates an oversized documentText before embedding it', () => {
90
- const huge = 'x'.repeat(MAX_DOC_CONTEXT + 5000);
91
- const prompt = editPrompt('selected text', 'make it concise', huge);
92
- expect(prompt).toContain('[...document truncated for length...]');
93
- expect(prompt.length).toBeLessThan(huge.length + 2000);
94
- });
95
- });
96
-
97
- describe('truncateDocumentText', () => {
98
- test('passes short text through unchanged', () => {
99
- expect(truncateDocumentText('short')).toBe('short');
100
- });
101
-
102
- test('truncates to the documented head+tail scheme rather than dropping or erroring', () => {
103
- const head = 'H'.repeat(40000);
104
- const tail = 'T'.repeat(20000);
105
- const middle = 'M'.repeat(10000);
106
- const result = truncateDocumentText(head + middle + tail);
107
- expect(result).toBe(`${head}\n\n[...document truncated for length...]\n\n${tail}`);
108
- expect(result).not.toContain('M');
109
- });
110
- });
111
-
112
- describe('docEditViaSession', () => {
113
- test('builds its prompt via the shared editPrompt and calls chatRunner.run with resume+silent', () => {
114
- docEditViaSession({
115
- tabId: 'tab-1',
116
- sessionId: 'chat-session-1',
117
- cwd: '/home/user/project',
118
- before: 'old text',
119
- instruction: 'make it punchier',
120
- documentText: 'the whole document',
121
- requestId: 'req-1',
122
- });
123
-
124
- expect(runCalls).toHaveLength(1);
125
- const call = runCalls[0];
126
- expect(call.tabId).toBe('tab-1');
127
- expect(call.sessionId).toBe('chat-session-1');
128
- expect(call.cwd).toBe('/home/user/project');
129
- expect(call.resume).toBe(true);
130
- expect(call.silent).toBe(true);
131
- expect(typeof call.onSilentResult).toBe('function');
132
-
133
- // The prompt is the shared editPrompt's output (nonce-tagged, so compare
134
- // structurally rather than byte-for-byte) prefixed with the anti-injection
135
- // system framing — not a second, forked prompt builder.
136
- expect(call.prompt).toContain('Rewrite the SELECTION below per the INSTRUCTION');
137
- expect(call.prompt).toMatch(/<selection_[0-9a-f]+>\nold text\n<\/selection_[0-9a-f]+>/);
138
- expect(call.prompt).toContain('deterministic document-rewrite assistant');
139
- });
140
-
141
- test('onSilentResult parses the reply and broadcasts docedit:session-result', () => {
142
- docEditViaSession({
143
- tabId: 'tab-2',
144
- sessionId: 'chat-session-2',
145
- cwd: '/home/user/project',
146
- before: 'old text',
147
- instruction: 'shorten it',
148
- requestId: 'req-2',
149
- });
150
-
151
- const { onSilentResult } = runCalls[runCalls.length - 1];
152
- onSilentResult('{"after":"new text"}');
153
- expect(broadcasts).toHaveLength(1);
154
- expect(broadcasts[0]).toEqual({
155
- channel: 'docedit:session-result',
156
- payload: { tabId: 'tab-2', requestId: 'req-2', ok: true, after: 'new text' },
157
- });
158
- });
159
-
160
- test('onSilentResult reports a parse failure as ok:false', () => {
161
- docEditViaSession({
162
- tabId: 'tab-3',
163
- sessionId: 'chat-session-3',
164
- cwd: '/home/user/project',
165
- before: 'old text',
166
- instruction: 'shorten it',
167
- requestId: 'req-3',
168
- });
169
-
170
- const { onSilentResult } = runCalls[runCalls.length - 1];
171
- onSilentResult('not json at all');
172
- expect(broadcasts).toHaveLength(1);
173
- expect(broadcasts[0].payload.ok).toBe(false);
174
- expect(broadcasts[0].payload.error).toBeTruthy();
175
- });
176
-
177
- test('splits off the stop-signal protocol and reports it as a clarification request', () => {
178
- docEditViaSession({
179
- tabId: 'tab-4',
180
- sessionId: 'chat-session-4',
181
- cwd: '/home/user/project',
182
- before: 'old text',
183
- instruction: 'shorten it',
184
- requestId: 'req-4',
185
- });
186
-
187
- const { onSilentResult } = runCalls[runCalls.length - 1];
188
- onSilentResult('<<<SM_NEEDS_INPUT>>>\n{"questions":["which section?"]}');
189
- expect(broadcasts).toHaveLength(1);
190
- expect(broadcasts[0].payload.ok).toBe(false);
191
- expect(broadcasts[0].payload.error).toContain('which section?');
192
- });
193
-
194
- test('times out and broadcasts a failure if chatRunner never calls onSilentResult (error/timeout/cancel/collision on the silent lane)', () => {
195
- vi.useFakeTimers();
196
- try {
197
- docEditViaSession({
198
- tabId: 'tab-5',
199
- sessionId: 'chat-session-5',
200
- cwd: '/home/user/project',
201
- before: 'old text',
202
- instruction: 'shorten it',
203
- requestId: 'req-5',
204
- });
205
-
206
- // chatRunner.run() is a no-op stub in this test (never invokes
207
- // onSilentResult) — nothing should broadcast until the bound elapses.
208
- expect(broadcasts).toHaveLength(0);
209
-
210
- vi.advanceTimersByTime(120_000);
211
- expect(broadcasts).toHaveLength(1);
212
- expect(broadcasts[0]).toEqual({
213
- channel: 'docedit:session-result',
214
- payload: { tabId: 'tab-5', requestId: 'req-5', ok: false, error: 'timed out waiting on the background session' },
215
- });
216
- } finally {
217
- vi.useRealTimers();
218
- }
219
- });
220
- });
221
-
222
- describe('duplicateNameFor', () => {
223
- test('fresh name — no collision', () => {
224
- const result = duplicateNameFor('/tmp/dir', 'notes.txt', () => false);
225
- expect(result).toEqual({ ok: true, name: 'notes-copy.txt' });
226
- });
227
-
228
- test('collision on the first candidate falls through to -copy-2', () => {
229
- const taken = new Set(['/tmp/dir/notes-copy.txt']);
230
- const result = duplicateNameFor('/tmp/dir', 'notes.txt', (full) => taken.has(full));
231
- expect(result).toEqual({ ok: true, name: 'notes-copy-2.txt' });
232
- });
233
-
234
- test('preserves extension-less basenames', () => {
235
- const result = duplicateNameFor('/tmp/dir', 'README', () => false);
236
- expect(result).toEqual({ ok: true, name: 'README-copy' });
237
- });
238
-
239
- test('cap exhausted after 20 attempts returns an error', () => {
240
- const result = duplicateNameFor('/tmp/dir', 'notes.txt', () => true);
241
- expect(result.ok).toBe(false);
242
- expect(result.error).toBeTruthy();
243
- });
244
- });