claude-code-session-manager 0.98.0 → 0.100.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.
- package/README.md +3 -3
- package/bin/cli.cjs +16 -4
- package/bin/node-floor.cjs +41 -0
- package/dist/assets/{DataModel-DCEgMTjH.js → DataModel-HdR0AxFq.js} +1 -1
- package/dist/assets/{History-Bfdoywlh.js → History-Dr4Jr_5z.js} +2 -2
- package/dist/assets/{Hooks-CKDJjTJV.js → Hooks-NhrvH3JP.js} +3 -3
- package/dist/assets/{Library-7akfgy67.js → Library-Dv_EtIMr.js} +1 -1
- package/dist/assets/{MarkdownEditor-DDesiqet.js → MarkdownEditor-DTKDWV_n.js} +1 -1
- package/dist/assets/{McpServers-D4lZtXof.js → McpServers-M034G9B3.js} +2 -2
- package/dist/assets/{Memory-CeI8G1w5.js → Memory-DzF1B4gx.js} +6 -6
- package/dist/assets/{Permissions-BGleLja4.js → Permissions-DrgbSGWl.js} +3 -3
- package/dist/assets/{Plugins-P4eCXy_S.js → Plugins-Bd3ef35w.js} +2 -2
- package/dist/assets/{ProvenanceBadge-BFczzI1B.js → ProvenanceBadge-DcBHT1Iy.js} +1 -1
- package/dist/assets/{SaveBar-l9jnEMES.js → SaveBar-rimJem-Y.js} +1 -1
- package/dist/assets/Scheduler-DjgFJl2w.js +16 -0
- package/dist/assets/{ScopeSwitcher-CjJi8ST5.js → ScopeSwitcher-CnAzTBrl.js} +1 -1
- package/dist/assets/Settings-Dc1F_sSg.js +3 -0
- package/dist/assets/{SkillReferenceGraph-CjbO01Sg.js → SkillReferenceGraph-B9aZDecM.js} +1 -1
- package/dist/assets/{Skills-BxZ9_fCR.js → Skills-DRXd18gu.js} +2 -2
- package/dist/assets/{SystemPrompt-D8vfFb8b.js → SystemPrompt-ahy5-Fwe.js} +1 -1
- package/dist/assets/{TagLibrary-2vzUo7YL.js → TagLibrary-C_tToDeL.js} +1 -1
- package/dist/assets/{TiptapBody-B8ZfbK90.js → TiptapBody-DvdefS6K.js} +1 -1
- package/dist/assets/{Toggle-BbW4nGGf.js → Toggle-6Jl5Njc6.js} +1 -1
- package/dist/assets/{index-CKH5Uxik.css → index-Bta-hwud.css} +1 -1
- package/dist/assets/{index-Cd98Q1lD.js → index-vx8O73l8.js} +497 -502
- package/dist/assets/{settingsSchema-IhUfucCF.js → settingsSchema-D6iRguNV.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +25 -29
- package/plugins/CLAUDE.md +6 -6
- package/plugins/session-manager-dev/skills/builder/4-manual/SKILL.md +21 -19
- package/plugins/session-manager-dev/skills/builder/SKILL.md +3 -3
- package/plugins/session-manager-dev/skills/develop/SKILL.md +254 -510
- package/plugins/session-manager-dev/skills/develop/standards.md +17 -22
- package/scripts/README.md +3 -11
- package/scripts/audit-ops-hygiene.cjs +3 -3
- package/scripts/hooks/lib/guard-prd-writes-policy.cjs +1 -1
- package/scripts/hooks/lib/guard-self-schedule-policy.cjs +1 -1
- package/scripts/mint-epic.cjs +2 -3
- package/scripts/scheduler-mcp-server.cjs +36 -7
- package/src/main/agentLibrary.cjs +22 -2
- package/src/main/build-info.json +4 -4
- package/src/main/config.cjs +41 -38
- package/src/main/docEdit.cjs +4 -1
- package/src/main/files.cjs +2 -5
- package/src/main/health.cjs +1 -1
- package/src/main/index.cjs +23 -10
- package/src/main/ipcSchemas.cjs +28 -35
- package/src/main/lib/agentPersonaSchema.cjs +13 -2
- package/src/main/lib/atomicFs.cjs +116 -0
- package/src/main/lib/branchSweep.cjs +13 -12
- package/src/main/lib/buildTarget.cjs +3 -3
- package/src/main/lib/claudeCliCaps.cjs +129 -0
- package/src/main/lib/credentials.cjs +2 -4
- package/src/main/lib/crossProjectFeedback.cjs +3 -3
- package/src/main/lib/cwdClassify.cjs +15 -3
- package/src/main/lib/definitionOfDone.cjs +207 -125
- package/src/main/lib/dodDrainHook.cjs +11 -5
- package/src/main/lib/epicMint.cjs +2 -4
- package/src/main/lib/epicStatusMirror.cjs +8 -10
- package/src/main/lib/epicWorktreeProjectConfig.cjs +2 -4
- package/src/main/lib/gateAuthority.cjs +96 -0
- package/src/main/lib/gitExec.cjs +69 -0
- package/src/main/lib/gitWorktree.cjs +656 -92
- package/src/main/lib/instanceLock.cjs +5 -8
- package/src/main/lib/launchFailure.cjs +2 -3
- package/src/main/lib/macroLibrary.cjs +386 -0
- package/src/main/lib/mcpToolCatalog.cjs +26 -17
- package/src/main/lib/needsReviewLedger.cjs +1 -1
- package/src/main/lib/opsErrorLog.cjs +11 -1
- package/src/main/lib/opsOwnership.cjs +0 -5
- package/src/main/lib/pidAlive.cjs +32 -0
- package/src/main/lib/prdCreate.cjs +121 -12
- package/src/main/lib/prdDisposition.cjs +2 -2
- package/src/main/lib/prdGateFiles.cjs +284 -0
- package/src/main/lib/prdLocations.cjs +61 -0
- package/src/main/lib/prdMigration.cjs +2 -3
- package/src/main/lib/prdSizing.cjs +2 -1
- package/src/main/lib/promptSessionSchema.cjs +10 -2
- package/src/main/lib/rcaReport.cjs +4 -6
- package/src/main/lib/reaperHelpers.cjs +8 -1
- package/src/main/lib/reservationExpiry.cjs +6 -1
- package/src/main/lib/reviewNotice.cjs +263 -0
- package/src/main/lib/runClaudeP.cjs +4 -1
- package/src/main/lib/schedulerPaths.cjs +22 -2
- package/src/main/lib/sessionSlots.cjs +2 -4
- package/src/main/lib/shippedPersonaSeeds.cjs +179 -0
- package/src/main/lib/timeoutShim.cjs +123 -0
- package/src/main/lib/timeoutShimScript.cjs +275 -0
- package/src/main/lib/upgradeDrain.cjs +4 -10
- package/src/main/lib/watchdogHelpers.cjs +12 -25
- package/src/main/lib/workTypeLibrary.cjs +7 -1
- package/src/main/promptSessionEvents.cjs +37 -13
- package/src/main/scheduler.cjs +910 -198
- package/src/main/seedAgentPersonas.cjs +278 -23
- package/src/main/supervisor.cjs +4 -1
- package/src/main/templates/PRD_AUTHORING.md +126 -406
- package/src/preload/__tests__/preload-surface.test.cjs +68 -0
- package/src/preload/api.d.ts +41 -94
- package/src/preload/index.cjs +14 -9
- package/src/seed/agents/architect.md +1 -0
- package/src/seed/agents/dev-lead.md +17 -18
- package/src/seed/agents/project-home-builder.md +1 -0
- package/src/seed/agents/validator.md +10 -4
- package/dist/assets/HostBilko-CDVHE0hT.js +0 -1
- package/dist/assets/Scheduler-C_phpeUS.js +0 -16
- package/dist/assets/Settings-BIwZ3FGQ.js +0 -3
- package/src/main/__tests__/activeIndexMerge.test.cjs +0 -235
- package/src/main/__tests__/agentEffortResolve.test.cjs +0 -117
- package/src/main/__tests__/agentLibrary.test.cjs +0 -276
- package/src/main/__tests__/agentModelResolve.test.cjs +0 -311
- package/src/main/__tests__/agentOverlayWrite.test.cjs +0 -95
- package/src/main/__tests__/bilkoHost-deriveSlug.test.cjs +0 -26
- package/src/main/__tests__/bilkoHost-integration.test.cjs +0 -118
- package/src/main/__tests__/bilkoHostCore.test.cjs +0 -72
- package/src/main/__tests__/broadcastCoalescer.test.cjs +0 -122
- package/src/main/__tests__/chat-cancel-terminal.test.cjs +0 -120
- package/src/main/__tests__/chat-dead-channels.test.cjs +0 -63
- package/src/main/__tests__/chat-exit-close-race.test.cjs +0 -146
- package/src/main/__tests__/chat-mcp-consent-notice.test.cjs +0 -139
- package/src/main/__tests__/chat-preamble-anchors.test.cjs +0 -100
- package/src/main/__tests__/chat-queue.test.cjs +0 -97
- package/src/main/__tests__/chat-stop-signal.test.cjs +0 -89
- package/src/main/__tests__/chatRunner-epic-worktree-execcwd.test.cjs +0 -125
- package/src/main/__tests__/chatRunner-session-flag-retry.test.cjs +0 -252
- package/src/main/__tests__/classifyPromptTicket.test.cjs +0 -101
- package/src/main/__tests__/classifyTranscriptLine.test.cjs +0 -201
- package/src/main/__tests__/computeDepHistorySatisfaction.test.cjs +0 -66
- package/src/main/__tests__/config-readText-bounded.test.cjs +0 -84
- package/src/main/__tests__/configWriteBoundaryOwners.test.cjs +0 -59
- package/src/main/__tests__/crossProjectFeedback.test.cjs +0 -334
- package/src/main/__tests__/crossProjectFeedbackRoutes.test.cjs +0 -161
- package/src/main/__tests__/dep-orphan-archive-health.test.cjs +0 -77
- package/src/main/__tests__/develop-skill-failure-modes.test.cjs +0 -70
- package/src/main/__tests__/docEdit.test.cjs +0 -244
- package/src/main/__tests__/dod-batchkey.test.cjs +0 -183
- package/src/main/__tests__/dod-drain-hook.test.cjs +0 -302
- package/src/main/__tests__/dod-report.test.cjs +0 -304
- package/src/main/__tests__/dod-reverify.test.cjs +0 -285
- package/src/main/__tests__/epicContextDigest.test.cjs +0 -174
- package/src/main/__tests__/epicMint.test.cjs +0 -332
- package/src/main/__tests__/epicMintTelemetryTap.test.cjs +0 -64
- package/src/main/__tests__/epicStatusMirror.test.cjs +0 -110
- package/src/main/__tests__/epicValidationHook.test.cjs +0 -291
- package/src/main/__tests__/exchanges.test.cjs +0 -122
- package/src/main/__tests__/exchangesPromptId.test.cjs +0 -61
- package/src/main/__tests__/extractJson.test.cjs +0 -51
- package/src/main/__tests__/files-reject-credentials.test.cjs +0 -40
- package/src/main/__tests__/fixtures/1218-fo-01-move-scripts-lib-into-src-main-lib.log +0 -556
- package/src/main/__tests__/flatPrdTickSweep.test.cjs +0 -110
- package/src/main/__tests__/health-build-freshness.test.cjs +0 -39
- package/src/main/__tests__/health-claude-md-budget.test.cjs +0 -57
- package/src/main/__tests__/health-credentials.test.cjs +0 -81
- package/src/main/__tests__/health-delegation-chain.test.cjs +0 -124
- package/src/main/__tests__/health-per-project-stall.test.cjs +0 -84
- package/src/main/__tests__/health-prd-migration.test.cjs +0 -37
- package/src/main/__tests__/health-queue-dispatch.test.cjs +0 -135
- package/src/main/__tests__/health-starve-escalation.test.cjs +0 -94
- package/src/main/__tests__/health-tick-liveness.test.cjs +0 -179
- package/src/main/__tests__/health-usage-poller.test.cjs +0 -144
- package/src/main/__tests__/health-worktree-cap-blocked.test.cjs +0 -65
- package/src/main/__tests__/heapSnapshot.test.cjs +0 -121
- package/src/main/__tests__/historyAggregatorIntraday.test.cjs +0 -313
- package/src/main/__tests__/historyDashboard.test.cjs +0 -163
- package/src/main/__tests__/historyRollup.test.cjs +0 -333
- package/src/main/__tests__/intradayRefresh.test.cjs +0 -39
- package/src/main/__tests__/ipcSchemas-dependsOn.test.cjs +0 -39
- package/src/main/__tests__/kg-augment.test.cjs +0 -195
- package/src/main/__tests__/loadGateDetailTick.test.cjs +0 -31
- package/src/main/__tests__/machineProfile.test.cjs +0 -152
- package/src/main/__tests__/mcpStatus.test.cjs +0 -61
- package/src/main/__tests__/memoryAggregate.test.cjs +0 -109
- package/src/main/__tests__/memoryStale.test.cjs +0 -88
- package/src/main/__tests__/needsReviewLedger.test.cjs +0 -162
- package/src/main/__tests__/openExternalApp-spawn-error.test.cjs +0 -25
- package/src/main/__tests__/opsErrorLog.test.cjs +0 -109
- package/src/main/__tests__/opsErrorLogTelemetryTap.test.cjs +0 -173
- package/src/main/__tests__/personaMerge.test.cjs +0 -169
- package/src/main/__tests__/planValidator.test.cjs +0 -125
- package/src/main/__tests__/pollLoop-dispatch-on-failure.test.cjs +0 -176
- package/src/main/__tests__/prd-group-allocator.test.cjs +0 -119
- package/src/main/__tests__/prdAdminRouteParity.test.cjs +0 -70
- package/src/main/__tests__/prdAdminRoutes.test.cjs +0 -718
- package/src/main/__tests__/prdAgentType.test.cjs +0 -103
- package/src/main/__tests__/prdAuthoringSeed.test.cjs +0 -39
- package/src/main/__tests__/prdCreate.test.cjs +0 -979
- package/src/main/__tests__/prdCreateAdoption.test.cjs +0 -205
- package/src/main/__tests__/prdCreateDisposition.test.cjs +0 -201
- package/src/main/__tests__/prdCreatePlanId.test.cjs +0 -132
- package/src/main/__tests__/prdFrontmatterAgentType.test.cjs +0 -117
- package/src/main/__tests__/prdFrontmatterDependsOn.test.cjs +0 -136
- package/src/main/__tests__/prdFrontmatterDisposition.test.cjs +0 -125
- package/src/main/__tests__/prdFrontmatterQuietMachine.test.cjs +0 -108
- package/src/main/__tests__/prdLocations.test.cjs +0 -195
- package/src/main/__tests__/prdLocationsArchived.test.cjs +0 -201
- package/src/main/__tests__/prdMigration.test.cjs +0 -349
- package/src/main/__tests__/prdMigrationLegacyAdopt.test.cjs +0 -91
- package/src/main/__tests__/prdParserHighWater.test.cjs +0 -74
- package/src/main/__tests__/prdParserSourcePromptId.test.cjs +0 -65
- package/src/main/__tests__/prdSetDisposition.test.cjs +0 -222
- package/src/main/__tests__/prdSizing.test.cjs +0 -106
- package/src/main/__tests__/prdSourcePromptIdBackfill.test.cjs +0 -118
- package/src/main/__tests__/prdUpdateDependsOn.test.cjs +0 -160
- package/src/main/__tests__/proc-role-env.test.cjs +0 -125
- package/src/main/__tests__/procname-claude-spawn-sites.test.cjs +0 -304
- package/src/main/__tests__/procname-sm-processes.test.cjs +0 -127
- package/src/main/__tests__/projectHomeAdminRoutes.test.cjs +0 -177
- package/src/main/__tests__/projectPages.test.cjs +0 -137
- package/src/main/__tests__/promptSessionEvents.test.cjs +0 -234
- package/src/main/__tests__/promptSessionSchema.test.cjs +0 -101
- package/src/main/__tests__/promptSessionTranscript.test.cjs +0 -0
- package/src/main/__tests__/promptSessionsCreateEpicHandler.test.cjs +0 -159
- package/src/main/__tests__/pty-epic-worktree-spawn-cwd.test.cjs +0 -282
- package/src/main/__tests__/pty-session-open-telemetry.test.cjs +0 -96
- package/src/main/__tests__/pty-write-result.test.cjs +0 -46
- package/src/main/__tests__/queue-health-verdict.test.cjs +0 -170
- package/src/main/__tests__/queue-starvation-dispatch-driver.test.cjs +0 -286
- package/src/main/__tests__/queue-starvation-per-project.test.cjs +0 -147
- package/src/main/__tests__/queueHistory.test.cjs +0 -355
- package/src/main/__tests__/queueOps-interactive-ac-lint.test.cjs +0 -65
- package/src/main/__tests__/queueOpsArchiveDestination.test.cjs +0 -65
- package/src/main/__tests__/queueOpsAutoArchive.test.cjs +0 -211
- package/src/main/__tests__/rateLimitPollerStreak.test.cjs +0 -128
- package/src/main/__tests__/rcaReport.test.cjs +0 -266
- package/src/main/__tests__/reconcileFlatPrdSweep.test.cjs +0 -119
- package/src/main/__tests__/reconcileTiming.test.cjs +0 -135
- package/src/main/__tests__/runLogRetention.test.cjs +0 -489
- package/src/main/__tests__/runVerify-atomic-verdicts.test.cjs +0 -26
- package/src/main/__tests__/runVerify-blocked-by-foreign-wip.test.cjs +0 -58
- package/src/main/__tests__/runVerify-landed-commit-outranks.test.cjs +0 -191
- package/src/main/__tests__/runVerify-policy-denial.test.cjs +0 -89
- package/src/main/__tests__/runVerify-transcript-commit-evidence.test.cjs +0 -225
- package/src/main/__tests__/runVerify.test.cjs +0 -1784
- package/src/main/__tests__/scheduleJobSchema.test.cjs +0 -127
- package/src/main/__tests__/scheduleJobStatusDrift.test.cjs +0 -65
- package/src/main/__tests__/scheduleJobTransitions.test.cjs +0 -277
- package/src/main/__tests__/scheduleJobTransitionsGrep.test.cjs +0 -59
- package/src/main/__tests__/scheduleJobTransitionsTelemetryTap.test.cjs +0 -72
- package/src/main/__tests__/scheduler-admin-routes.test.cjs +0 -199
- package/src/main/__tests__/scheduler-adopted-run-supervision.test.cjs +0 -143
- package/src/main/__tests__/scheduler-already-satisfied-on-main.test.cjs +0 -105
- package/src/main/__tests__/scheduler-archive-completed-prd.test.cjs +0 -102
- package/src/main/__tests__/scheduler-archived-twin-guard.test.cjs +0 -155
- package/src/main/__tests__/scheduler-autofix-outcome.test.cjs +0 -188
- package/src/main/__tests__/scheduler-autofix-select.test.cjs +0 -439
- package/src/main/__tests__/scheduler-autopromote.test.cjs +0 -51
- package/src/main/__tests__/scheduler-bash-timeout-env.test.cjs +0 -101
- package/src/main/__tests__/scheduler-blocked-by-foreign-wip.test.cjs +0 -107
- package/src/main/__tests__/scheduler-boot-orphans.test.cjs +0 -153
- package/src/main/__tests__/scheduler-broadcast-reconcile.test.cjs +0 -121
- package/src/main/__tests__/scheduler-clear-queue-history.test.cjs +0 -134
- package/src/main/__tests__/scheduler-commit-guard-noop.test.cjs +0 -244
- package/src/main/__tests__/scheduler-committed-in-window.test.cjs +0 -182
- package/src/main/__tests__/scheduler-cross-project-batch.test.cjs +0 -43
- package/src/main/__tests__/scheduler-default-eligible-heal.test.cjs +0 -168
- package/src/main/__tests__/scheduler-dispatch-loop.test.cjs +0 -58
- package/src/main/__tests__/scheduler-effective-concurrency.test.cjs +0 -81
- package/src/main/__tests__/scheduler-epic-digest.test.cjs +0 -227
- package/src/main/__tests__/scheduler-failed-autoreset.test.cjs +0 -121
- package/src/main/__tests__/scheduler-finalize-dispatch-guards.test.cjs +0 -229
- package/src/main/__tests__/scheduler-find-prd-dir.test.cjs +0 -75
- package/src/main/__tests__/scheduler-fix-plan-path.test.cjs +0 -119
- package/src/main/__tests__/scheduler-force-tick-outcome.test.cjs +0 -46
- package/src/main/__tests__/scheduler-foreign-wip-manifest.test.cjs +0 -78
- package/src/main/__tests__/scheduler-gate-shadow.test.cjs +0 -119
- package/src/main/__tests__/scheduler-guard-verdict-autoresolve.test.cjs +0 -390
- package/src/main/__tests__/scheduler-heal-refusal.test.cjs +0 -61
- package/src/main/__tests__/scheduler-heartbeat-payload.test.cjs +0 -80
- package/src/main/__tests__/scheduler-inplace-salvage.test.cjs +0 -323
- package/src/main/__tests__/scheduler-integration-failure-stamp.test.cjs +0 -41
- package/src/main/__tests__/scheduler-investigation-clean-skip.test.cjs +0 -63
- package/src/main/__tests__/scheduler-investigation-prompt.test.cjs +0 -123
- package/src/main/__tests__/scheduler-job-budget.test.cjs +0 -172
- package/src/main/__tests__/scheduler-job-overrun.test.cjs +0 -175
- package/src/main/__tests__/scheduler-launch-failure.test.cjs +0 -199
- package/src/main/__tests__/scheduler-leftover-fields.test.cjs +0 -52
- package/src/main/__tests__/scheduler-leftover-quarantine.test.cjs +0 -199
- package/src/main/__tests__/scheduler-looks-done.test.cjs +0 -537
- package/src/main/__tests__/scheduler-manual-pause.test.cjs +0 -118
- package/src/main/__tests__/scheduler-mechanical-recovery.test.cjs +0 -245
- package/src/main/__tests__/scheduler-meta-code-sha.test.cjs +0 -46
- package/src/main/__tests__/scheduler-mutate-reentrancy.test.cjs +0 -117
- package/src/main/__tests__/scheduler-needs-review-autoresolve.test.cjs +0 -197
- package/src/main/__tests__/scheduler-never-stop.test.cjs +0 -157
- package/src/main/__tests__/scheduler-no-dead-end-status.test.cjs +0 -152
- package/src/main/__tests__/scheduler-no-orphan-run-dir.test.cjs +0 -81
- package/src/main/__tests__/scheduler-notify-originating-tab-transcript.test.cjs +0 -87
- package/src/main/__tests__/scheduler-notify-originating-tab.test.cjs +0 -343
- package/src/main/__tests__/scheduler-periodic-reverify-guard.test.cjs +0 -217
- package/src/main/__tests__/scheduler-porcelain-rename.test.cjs +0 -164
- package/src/main/__tests__/scheduler-prd-missing-skip.test.cjs +0 -161
- package/src/main/__tests__/scheduler-prd-persona-spawn.test.cjs +0 -178
- package/src/main/__tests__/scheduler-quarantine-autoresolve.test.cjs +0 -165
- package/src/main/__tests__/scheduler-quiet-machine-lease.test.cjs +0 -257
- package/src/main/__tests__/scheduler-rate-limit-cooldown-freshness.test.cjs +0 -123
- package/src/main/__tests__/scheduler-rate-limit-pause.test.cjs +0 -152
- package/src/main/__tests__/scheduler-rate-limit-spin-guard.test.cjs +0 -156
- package/src/main/__tests__/scheduler-reap-dead-running-jobs.test.cjs +0 -754
- package/src/main/__tests__/scheduler-reaper-helpers-basics.test.cjs +0 -87
- package/src/main/__tests__/scheduler-reconcile-cwd-preserve.test.cjs +0 -100
- package/src/main/__tests__/scheduler-reconcile-history-backfill.test.cjs +0 -105
- package/src/main/__tests__/scheduler-reconcile-invalid-repair.test.cjs +0 -203
- package/src/main/__tests__/scheduler-reconcile-quarantine.test.cjs +0 -247
- package/src/main/__tests__/scheduler-reset-job-fields-guard.test.cjs +0 -77
- package/src/main/__tests__/scheduler-resume-recovery.test.cjs +0 -254
- package/src/main/__tests__/scheduler-shard-quarantine.test.cjs +0 -115
- package/src/main/__tests__/scheduler-shared-tree-guard.test.cjs +0 -380
- package/src/main/__tests__/scheduler-sigterm-commit.test.cjs +0 -43
- package/src/main/__tests__/scheduler-stall-per-project.test.cjs +0 -126
- package/src/main/__tests__/scheduler-starve-escalation.test.cjs +0 -154
- package/src/main/__tests__/scheduler-stranded-autofix-park.test.cjs +0 -252
- package/src/main/__tests__/scheduler-stranded-investigation.test.cjs +0 -185
- package/src/main/__tests__/scheduler-stuck-failed-escalation.test.cjs +0 -136
- package/src/main/__tests__/scheduler-supervisor-record.test.cjs +0 -81
- package/src/main/__tests__/scheduler-tick-cancel-token.test.cjs +0 -54
- package/src/main/__tests__/scheduler-tick-wedge.test.cjs +0 -172
- package/src/main/__tests__/scheduler-transient-failure.test.cjs +0 -141
- package/src/main/__tests__/scheduler-unreadable-queue-guard.test.cjs +0 -62
- package/src/main/__tests__/scheduler-utilization-hold.test.cjs +0 -89
- package/src/main/__tests__/scheduler-verify-prd-path.test.cjs +0 -109
- package/src/main/__tests__/scheduler-worktree-cap-defer.test.cjs +0 -234
- package/src/main/__tests__/scheduler-worktree-exec-cwd.test.cjs +0 -120
- package/src/main/__tests__/scheduler-writeprd-epic-rollback.test.cjs +0 -105
- package/src/main/__tests__/schedulerBatchRootBlocker.test.cjs +0 -117
- package/src/main/__tests__/schedulerStateSidecarRestore.test.cjs +0 -110
- package/src/main/__tests__/seedAgentPersonas.test.cjs +0 -184
- package/src/main/__tests__/seedSchedulerMcp.test.cjs +0 -211
- package/src/main/__tests__/seedStatus.test.cjs +0 -100
- package/src/main/__tests__/seedValidatorPersona.test.cjs +0 -116
- package/src/main/__tests__/stop-signal-anchor.test.cjs +0 -75
- package/src/main/__tests__/telemetryClient.test.cjs +0 -1055
- package/src/main/__tests__/telemetryContract.test.cjs +0 -930
- package/src/main/__tests__/telemetrySettings.test.cjs +0 -210
- package/src/main/__tests__/transcripts-batch-flush.test.cjs +0 -249
- package/src/main/__tests__/transcripts-doFlush-array.test.cjs +0 -124
- package/src/main/__tests__/transcripts-paged-reads.test.cjs +0 -241
- package/src/main/__tests__/transcripts-worktree-epic-path.test.cjs +0 -154
- package/src/main/__tests__/transcriptsUsageFor.test.cjs +0 -206
- package/src/main/__tests__/uniquePrdNumbers.test.cjs +0 -153
- package/src/main/__tests__/usageSingleFlight.test.cjs +0 -169
- package/src/main/__tests__/validationSentinels.test.cjs +0 -84
- package/src/main/__tests__/workTypeLibrary.test.cjs +0 -89
- package/src/main/bilkoHost.cjs +0 -314
- package/src/main/bilkoHostCore.cjs +0 -89
- package/src/main/lib/__tests__/active-sessions.test.cjs +0 -251
- package/src/main/lib/__tests__/activeIndexRebuild.test.cjs +0 -179
- package/src/main/lib/__tests__/agentPersonaSchema.test.cjs +0 -67
- package/src/main/lib/__tests__/auditLog.test.cjs +0 -38
- package/src/main/lib/__tests__/bootSelfHeal.test.cjs +0 -107
- package/src/main/lib/__tests__/branchSweep.test.cjs +0 -164
- package/src/main/lib/__tests__/buildIdentity.test.cjs +0 -121
- package/src/main/lib/__tests__/buildTarget.test.cjs +0 -52
- package/src/main/lib/__tests__/childWithLog.test.cjs +0 -321
- package/src/main/lib/__tests__/coldBootPromptSessionsWrite.test.cjs +0 -87
- package/src/main/lib/__tests__/crashTelemetry.test.cjs +0 -103
- package/src/main/lib/__tests__/credentials-futile-refresh.test.cjs +0 -115
- package/src/main/lib/__tests__/cwdClassify.test.cjs +0 -111
- package/src/main/lib/__tests__/definitionOfDoneSequence.test.cjs +0 -95
- package/src/main/lib/__tests__/delegationReadiness.test.cjs +0 -1175
- package/src/main/lib/__tests__/dispatchLoop.test.cjs +0 -63
- package/src/main/lib/__tests__/effectiveModelInfo.test.cjs +0 -244
- package/src/main/lib/__tests__/ephemeralCwd.test.cjs +0 -91
- package/src/main/lib/__tests__/epicDelegationStats.test.cjs +0 -137
- package/src/main/lib/__tests__/epicSpawnCwd.test.cjs +0 -283
- package/src/main/lib/__tests__/epicSpawnPlan.test.cjs +0 -196
- package/src/main/lib/__tests__/epicTranscriptPath.test.cjs +0 -163
- package/src/main/lib/__tests__/epicWorktreeBoot.test.cjs +0 -136
- package/src/main/lib/__tests__/epicWorktreeMerge.test.cjs +0 -130
- package/src/main/lib/__tests__/epicWorktreeMint.test.cjs +0 -117
- package/src/main/lib/__tests__/epicWorktreeProjectConfig.test.cjs +0 -137
- package/src/main/lib/__tests__/fixChainDepth.test.cjs +0 -40
- package/src/main/lib/__tests__/fixtures/204-mercury-steam-horse.log.txt +0 -13
- package/src/main/lib/__tests__/fixtures/scheduler-machine.json.corrupt-1789147548 +0 -34
- package/src/main/lib/__tests__/gateFixtures.json +0 -20
- package/src/main/lib/__tests__/gitCacheBound.test.cjs +0 -69
- package/src/main/lib/__tests__/gitWorktree.test.cjs +0 -1478
- package/src/main/lib/__tests__/gitWorktreeSalvage.test.cjs +0 -107
- package/src/main/lib/__tests__/gitWorktreeSalvageDelta.test.cjs +0 -153
- package/src/main/lib/__tests__/guardShims.test.cjs +0 -158
- package/src/main/lib/__tests__/importReferences.spec.cjs +0 -56
- package/src/main/lib/__tests__/instanceLock.test.cjs +0 -173
- package/src/main/lib/__tests__/jobSupervisorRecord.test.cjs +0 -78
- package/src/main/lib/__tests__/jobWorktree.test.cjs +0 -199
- package/src/main/lib/__tests__/jobWorktreeBootLive.test.cjs +0 -82
- package/src/main/lib/__tests__/landedSinceRun.test.cjs +0 -133
- package/src/main/lib/__tests__/launchFailure.test.cjs +0 -220
- package/src/main/lib/__tests__/loadGate.test.cjs +0 -303
- package/src/main/lib/__tests__/localAdminHttp.test.cjs +0 -214
- package/src/main/lib/__tests__/loopDelay.test.cjs +0 -68
- package/src/main/lib/__tests__/mcpToolCatalog.test.cjs +0 -107
- package/src/main/lib/__tests__/modelCatalog.test.cjs +0 -202
- package/src/main/lib/__tests__/opsOwnership.test.cjs +0 -113
- package/src/main/lib/__tests__/opsRootAbsoluteCwd.test.cjs +0 -328
- package/src/main/lib/__tests__/opsRootNestedWrite.test.cjs +0 -51
- package/src/main/lib/__tests__/opsRootResolve.test.cjs +0 -149
- package/src/main/lib/__tests__/prdDeclaredPaths.test.cjs +0 -82
- package/src/main/lib/__tests__/prdDisposition.test.cjs +0 -224
- package/src/main/lib/__tests__/procIdentity.test.cjs +0 -119
- package/src/main/lib/__tests__/procName.test.cjs +0 -92
- package/src/main/lib/__tests__/projectBriefCore.test.cjs +0 -216
- package/src/main/lib/__tests__/projectRootResolve.test.cjs +0 -148
- package/src/main/lib/__tests__/queueHealth.test.cjs +0 -58
- package/src/main/lib/__tests__/queueStoreAtomicWrite.test.cjs +0 -88
- package/src/main/lib/__tests__/queueStoreMachineStateRecovery.test.cjs +0 -190
- package/src/main/lib/__tests__/quietMachineLease.test.cjs +0 -39
- package/src/main/lib/__tests__/rateLimitWindow.test.cjs +0 -88
- package/src/main/lib/__tests__/reaperHelpers.test.cjs +0 -577
- package/src/main/lib/__tests__/schedulerBatchDepends.test.cjs +0 -312
- package/src/main/lib/__tests__/schedulerBatchFairness.test.cjs +0 -213
- package/src/main/lib/__tests__/schedulerBatchLaunchHold.test.cjs +0 -125
- package/src/main/lib/__tests__/schedulerBatchProjectCap.test.cjs +0 -127
- package/src/main/lib/__tests__/schedulerBatchQuietMachine.test.cjs +0 -109
- package/src/main/lib/__tests__/schedulerMcpServerHeadlessRefusal.test.cjs +0 -71
- package/src/main/lib/__tests__/schedulerMcpServerHelp.test.cjs +0 -216
- package/src/main/lib/__tests__/schedulerMcpServerProjectHome.test.cjs +0 -183
- package/src/main/lib/__tests__/schedulerPaths.test.cjs +0 -226
- package/src/main/lib/__tests__/schedulerPathsWorktree.test.cjs +0 -133
- package/src/main/lib/__tests__/schedulerRuntimeState.test.cjs +0 -56
- package/src/main/lib/__tests__/sessionSlots.test.cjs +0 -144
- package/src/main/lib/__tests__/telemetryBacklog.test.cjs +0 -626
- package/src/main/lib/__tests__/telemetryBoot.test.cjs +0 -134
- package/src/main/lib/__tests__/telemetryConsent.test.cjs +0 -136
- package/src/main/lib/__tests__/telemetryCounters.test.cjs +0 -57
- package/src/main/lib/__tests__/telemetryCountersMetadataColumn.test.cjs +0 -98
- package/src/main/lib/__tests__/terminalRunOutcome.test.cjs +0 -200
- package/src/main/lib/__tests__/toolUseClassify.test.cjs +0 -53
- package/src/main/lib/__tests__/updateCheck.test.cjs +0 -63
- package/src/main/lib/__tests__/upgradeDrain.test.cjs +0 -130
- package/src/main/lib/__tests__/usageCircuit.test.cjs +0 -354
- package/src/main/lib/__tests__/watchdog-helpers.test.cjs +0 -441
- package/src/main/lib/__tests__/watchdog-relaunch.test.cjs +0 -266
- package/src/main/lib/kgExchangePairing.cjs +0 -75
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* prdParserHighWater.test.cjs — regression test for allocateParallelGroup's
|
|
3
|
-
* high-water mark: once queueOps.cjs's autoArchiveCompleted starts moving
|
|
4
|
-
* old NN-*.md files out of prds/ into prds-archived/, a bare directory scan
|
|
5
|
-
* (maxParallelGroupInUse) can regress once the highest-NN files age out —
|
|
6
|
-
* letting a later allocation reissue an already-used NN and collide with an
|
|
7
|
-
* archived group. The high-water-mark sidecar (.max-allocated-group) must
|
|
8
|
-
* keep the allocator monotonic even after every file is archived away.
|
|
9
|
-
*
|
|
10
|
-
* Run: timeout 300 npx vitest run src/main/__tests__/prdParserHighWater.test.cjs
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
'use strict';
|
|
14
|
-
|
|
15
|
-
import { test, expect } from 'vitest';
|
|
16
|
-
const fsp = require('node:fs/promises');
|
|
17
|
-
const os = require('node:os');
|
|
18
|
-
const path = require('node:path');
|
|
19
|
-
|
|
20
|
-
const { allocateParallelGroup, maxParallelGroupInUse, _resetCache } = require('../scheduler/prdParser.cjs');
|
|
21
|
-
|
|
22
|
-
function mkTmpPrdsDir() {
|
|
23
|
-
return fsp.mkdtemp(path.join(os.tmpdir(), 'sm-prd-highwater-'));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
test('allocator stays monotonic after every NN-*.md file (and its reservation marker) is archived away', async () => {
|
|
27
|
-
const dir = await mkTmpPrdsDir();
|
|
28
|
-
_resetCache();
|
|
29
|
-
|
|
30
|
-
// Directly-authored legacy files (never allocated via allocateParallelGroup
|
|
31
|
-
// — e.g. /develop's deliberate-sibling path — so no .reserved-NN marker
|
|
32
|
-
// exists for them). This is the real gap: reservation markers alone would
|
|
33
|
-
// already protect any NN the allocator itself minted, so the regression
|
|
34
|
-
// this PRD guards against is specifically legacy/directly-authored NNs.
|
|
35
|
-
await fsp.writeFile(path.join(dir, '10-a.md'), '# a\n');
|
|
36
|
-
await fsp.writeFile(path.join(dir, '544-b.md'), '# b\n');
|
|
37
|
-
|
|
38
|
-
// A scan (via allocateParallelGroup) observes 544 and persists it as the
|
|
39
|
-
// high-water mark before returning the next free NN.
|
|
40
|
-
const first = await allocateParallelGroup(dir);
|
|
41
|
-
expect(first).toBe(545);
|
|
42
|
-
|
|
43
|
-
// Simulate autoArchiveCompleted moving every .md out of the live dir, and
|
|
44
|
-
// also strip the reservation marker the allocation above created — so
|
|
45
|
-
// nothing on disk still evidences 544/545 except the high-water sidecar.
|
|
46
|
-
await fsp.unlink(path.join(dir, '10-a.md'));
|
|
47
|
-
await fsp.unlink(path.join(dir, '544-b.md'));
|
|
48
|
-
await fsp.unlink(path.join(dir, '.reserved-545'));
|
|
49
|
-
|
|
50
|
-
const bareScanMax = await maxParallelGroupInUse(dir);
|
|
51
|
-
expect(bareScanMax).toBe(0);
|
|
52
|
-
|
|
53
|
-
_resetCache();
|
|
54
|
-
const second = await allocateParallelGroup(dir);
|
|
55
|
-
expect(second).toBeGreaterThan(545);
|
|
56
|
-
expect(second).toBe(546);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('high-water mark also protects against a fresh scan that is lower than a prior allocation, without any archiving involved', async () => {
|
|
60
|
-
const dir = await mkTmpPrdsDir();
|
|
61
|
-
_resetCache();
|
|
62
|
-
|
|
63
|
-
await fsp.writeFile(path.join(dir, '5-only.md'), '# x\n');
|
|
64
|
-
const nn = await allocateParallelGroup(dir);
|
|
65
|
-
expect(nn).toBe(6);
|
|
66
|
-
|
|
67
|
-
// A slow/partial directory listing (or a caller passing a differently
|
|
68
|
-
// scoped dir) must not be able to walk the allocator backwards.
|
|
69
|
-
const rescanMax = await maxParallelGroupInUse(dir);
|
|
70
|
-
expect(rescanMax).toBe(6); // the .reserved-6 marker from the allocation above still counts
|
|
71
|
-
|
|
72
|
-
const next = await allocateParallelGroup(dir);
|
|
73
|
-
expect(next).toBe(7);
|
|
74
|
-
});
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* prdParserSourcePromptId.test.cjs — parsePrdRaw() tolerates both presence
|
|
3
|
-
* and absence of the optional `sourcePromptId` frontmatter key (PRD 749).
|
|
4
|
-
* Additive-only: PRDs written before this field existed must still parse
|
|
5
|
-
* identically (no required-field regression).
|
|
6
|
-
*
|
|
7
|
-
* Run: timeout 120 npx vitest run src/main/__tests__/prdParserSourcePromptId.test.cjs
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
'use strict';
|
|
11
|
-
|
|
12
|
-
import { test, expect } from 'vitest';
|
|
13
|
-
const fsp = require('node:fs/promises');
|
|
14
|
-
const os = require('node:os');
|
|
15
|
-
const path = require('node:path');
|
|
16
|
-
|
|
17
|
-
const { parsePrdRaw, _resetCache } = require('../scheduler/prdParser.cjs');
|
|
18
|
-
|
|
19
|
-
function mkTmpPrdsDir() {
|
|
20
|
-
return fsp.mkdtemp(path.join(os.tmpdir(), 'sm-prd-sourceprompt-'));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
test('parsePrdRaw extracts sourcePromptId when present in frontmatter', async () => {
|
|
24
|
-
const dir = await mkTmpPrdsDir();
|
|
25
|
-
_resetCache();
|
|
26
|
-
const filePath = path.join(dir, '1-with-source.md');
|
|
27
|
-
await fsp.writeFile(filePath, [
|
|
28
|
-
'---',
|
|
29
|
-
'title: Has a source ticket',
|
|
30
|
-
'cwd: ~/Projects/session-manager',
|
|
31
|
-
'estimateMinutes: 10',
|
|
32
|
-
'sourcePromptId: ticket-xyz-789',
|
|
33
|
-
'---',
|
|
34
|
-
'# Goal',
|
|
35
|
-
'',
|
|
36
|
-
'Do the thing.',
|
|
37
|
-
'',
|
|
38
|
-
].join('\n'));
|
|
39
|
-
|
|
40
|
-
const parsed = await parsePrdRaw(filePath);
|
|
41
|
-
expect(parsed.sourcePromptId).toBe('ticket-xyz-789');
|
|
42
|
-
expect(parsed.title).toBe('Has a source ticket');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test('parsePrdRaw returns null sourcePromptId for a PRD authored before this field existed', async () => {
|
|
46
|
-
const dir = await mkTmpPrdsDir();
|
|
47
|
-
_resetCache();
|
|
48
|
-
const filePath = path.join(dir, '2-legacy.md');
|
|
49
|
-
await fsp.writeFile(filePath, [
|
|
50
|
-
'---',
|
|
51
|
-
'title: Legacy PRD, no sourcePromptId',
|
|
52
|
-
'cwd: ~/Projects/session-manager',
|
|
53
|
-
'estimateMinutes: 5',
|
|
54
|
-
'---',
|
|
55
|
-
'# Goal',
|
|
56
|
-
'',
|
|
57
|
-
'Do the other thing.',
|
|
58
|
-
'',
|
|
59
|
-
].join('\n'));
|
|
60
|
-
|
|
61
|
-
const parsed = await parsePrdRaw(filePath);
|
|
62
|
-
expect(parsed.sourcePromptId).toBe(null);
|
|
63
|
-
expect(parsed.title).toBe('Legacy PRD, no sourcePromptId');
|
|
64
|
-
expect(parsed.cwd).toBe(path.join(os.homedir(), 'Projects', 'session-manager'));
|
|
65
|
-
});
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* prdSetDisposition.test.cjs — scheduler wave-disposition PRD:
|
|
3
|
-
* scheduler.remote.setPrdDisposition (backing the renderer's
|
|
4
|
-
* `schedule:set-prd-disposition` IPC action) is how a human changes an
|
|
5
|
-
* already-written PRD's disposition from the Scheduler UI — promoting an
|
|
6
|
-
* appended wave to its own head, or re-attaching a head behind another
|
|
7
|
-
* chain. Validates via prdDisposition.cjs's computeDispositionRewrite
|
|
8
|
-
* (cycle-safety, running/completed rows untouched) before delegating the
|
|
9
|
-
* actual write to the SAME remote.updatePrd every other PRD edit path uses.
|
|
10
|
-
*
|
|
11
|
-
* Mirrors prdUpdateDependsOn.test.cjs's HOME-isolation fixture.
|
|
12
|
-
*
|
|
13
|
-
* Run: timeout 120 npx vitest run src/main/__tests__/prdSetDisposition.test.cjs
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
'use strict';
|
|
17
|
-
|
|
18
|
-
import { test, expect, beforeAll, afterAll } from 'vitest';
|
|
19
|
-
const fs = require('node:fs');
|
|
20
|
-
const os = require('node:os');
|
|
21
|
-
const path = require('node:path');
|
|
22
|
-
|
|
23
|
-
let tmpHome;
|
|
24
|
-
let originalHome;
|
|
25
|
-
let scheduler;
|
|
26
|
-
let queueStore;
|
|
27
|
-
let config;
|
|
28
|
-
|
|
29
|
-
beforeAll(() => {
|
|
30
|
-
originalHome = process.env.HOME;
|
|
31
|
-
tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), 'sm-set-disposition-home-'));
|
|
32
|
-
process.env.HOME = tmpHome;
|
|
33
|
-
|
|
34
|
-
scheduler = require('../scheduler.cjs');
|
|
35
|
-
queueStore = require('../lib/queueStore.cjs');
|
|
36
|
-
config = require('../config.cjs');
|
|
37
|
-
|
|
38
|
-
if (!scheduler.PRDS_DIR.startsWith(tmpHome)) {
|
|
39
|
-
throw new Error(`refusing to run: PRDS_DIR (${scheduler.PRDS_DIR}) is not under the temp HOME (${tmpHome})`);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
afterAll(() => {
|
|
44
|
-
process.env.HOME = originalHome;
|
|
45
|
-
fs.rmSync(tmpHome, { recursive: true, force: true });
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
function registerActiveProject(cwd) {
|
|
49
|
-
const projectsDir = path.join(tmpHome, '.claude', 'projects');
|
|
50
|
-
const slugDir = path.join(projectsDir, `fake-project-slug-${path.basename(cwd)}`);
|
|
51
|
-
fs.mkdirSync(slugDir, { recursive: true });
|
|
52
|
-
fs.writeFileSync(path.join(slugDir, 'transcript.jsonl'), JSON.stringify({ cwd }) + '\n');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function makeFixtureProject(prefix) {
|
|
56
|
-
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
57
|
-
registerActiveProject(cwd);
|
|
58
|
-
config.addAllowedRoot(cwd);
|
|
59
|
-
const opsRoot = path.join(cwd, 'session-manager-operations');
|
|
60
|
-
const prdsDir = path.join(opsRoot, 'scheduler', 'epics', 'test-epic-1', 'prds');
|
|
61
|
-
const stateDir = path.join(opsRoot, 'scheduler', 'state');
|
|
62
|
-
fs.mkdirSync(prdsDir, { recursive: true });
|
|
63
|
-
fs.mkdirSync(stateDir, { recursive: true });
|
|
64
|
-
fs.writeFileSync(path.join(stateDir, 'queue.json'), JSON.stringify({ jobs: [] }, null, 2), 'utf8');
|
|
65
|
-
queueStore.bustCwdCache();
|
|
66
|
-
return { cwd, prdsDir, stateDir };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function writePrd(prdsDir, filename, cwd, extraFrontmatter = '') {
|
|
70
|
-
fs.writeFileSync(
|
|
71
|
-
path.join(prdsDir, filename),
|
|
72
|
-
`---\ntitle: ${filename}\ncwd: ${cwd}\nestimateMinutes: 10\ncreatedVia: scheduler-api\n${extraFrontmatter}---\n\n# Goal\nDo the thing.\n`,
|
|
73
|
-
'utf8',
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** Seeds a queue.json row for `slug` with the given status — setPrdDisposition
|
|
78
|
-
* (like updatePrd) reads job status off the live queue, not the PRD file. */
|
|
79
|
-
function seedQueueJob(stateDir, slug, status) {
|
|
80
|
-
fs.writeFileSync(
|
|
81
|
-
path.join(stateDir, 'queue.json'),
|
|
82
|
-
JSON.stringify({ jobs: [{ slug, status, title: slug, cwd: '' }] }, null, 2),
|
|
83
|
-
'utf8',
|
|
84
|
-
);
|
|
85
|
-
queueStore.bustCwdCache();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
test('append sets the expected edges', async () => {
|
|
89
|
-
const { cwd, prdsDir } = makeFixtureProject('sm-set-disposition-append-');
|
|
90
|
-
try {
|
|
91
|
-
writePrd(prdsDir, '3-wave1-tail.md', cwd);
|
|
92
|
-
writePrd(prdsDir, '4-wave2-root.md', cwd);
|
|
93
|
-
|
|
94
|
-
const result = await scheduler.remote.setPrdDisposition({
|
|
95
|
-
slug: '4-wave2-root',
|
|
96
|
-
cwd,
|
|
97
|
-
disposition: 'append',
|
|
98
|
-
dependsOn: ['3-wave1-tail'],
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
expect(result.ok).toBe(true);
|
|
102
|
-
const written = fs.readFileSync(path.join(prdsDir, '4-wave2-root.md'), 'utf8');
|
|
103
|
-
expect(written).toMatch(/^dependsOn: \[3-wave1-tail\]$/m);
|
|
104
|
-
expect(written).toMatch(/^disposition: append$/m);
|
|
105
|
-
} finally {
|
|
106
|
-
fs.rmSync(cwd, { recursive: true, force: true });
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test('new-head sets none', async () => {
|
|
111
|
-
const { cwd, prdsDir } = makeFixtureProject('sm-set-disposition-new-head-');
|
|
112
|
-
try {
|
|
113
|
-
writePrd(prdsDir, '3-wave1-tail.md', cwd);
|
|
114
|
-
writePrd(prdsDir, '4-wave2-root.md', cwd, 'dependsOn: [wave1-tail]\ndisposition: append\n');
|
|
115
|
-
|
|
116
|
-
const result = await scheduler.remote.setPrdDisposition({
|
|
117
|
-
slug: '4-wave2-root',
|
|
118
|
-
cwd,
|
|
119
|
-
disposition: 'new-head',
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
expect(result.ok).toBe(true);
|
|
123
|
-
const written = fs.readFileSync(path.join(prdsDir, '4-wave2-root.md'), 'utf8');
|
|
124
|
-
expect(written).not.toContain('dependsOn');
|
|
125
|
-
expect(written).toMatch(/^disposition: new-head$/m);
|
|
126
|
-
} finally {
|
|
127
|
-
fs.rmSync(cwd, { recursive: true, force: true });
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
test('promoting a wave to a head removes exactly its root edges', async () => {
|
|
132
|
-
const { cwd, prdsDir } = makeFixtureProject('sm-set-disposition-promote-');
|
|
133
|
-
try {
|
|
134
|
-
writePrd(prdsDir, '3-wave1-tail.md', cwd);
|
|
135
|
-
writePrd(prdsDir, '5-other-head.md', cwd);
|
|
136
|
-
writePrd(prdsDir, '4-wave2-root.md', cwd, 'dependsOn: [wave1-tail]\ndisposition: append\n');
|
|
137
|
-
|
|
138
|
-
const result = await scheduler.remote.setPrdDisposition({
|
|
139
|
-
slug: '4-wave2-root',
|
|
140
|
-
cwd,
|
|
141
|
-
disposition: 'new-head',
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
expect(result.ok).toBe(true);
|
|
145
|
-
const promoted = fs.readFileSync(path.join(prdsDir, '4-wave2-root.md'), 'utf8');
|
|
146
|
-
expect(promoted).not.toContain('dependsOn');
|
|
147
|
-
// The unrelated sibling head is untouched by this call.
|
|
148
|
-
const other = fs.readFileSync(path.join(prdsDir, '5-other-head.md'), 'utf8');
|
|
149
|
-
expect(other).not.toContain('dependsOn');
|
|
150
|
-
} finally {
|
|
151
|
-
fs.rmSync(cwd, { recursive: true, force: true });
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
test('a change that would create a cycle is rejected, and nothing is written', async () => {
|
|
156
|
-
const { cwd, prdsDir } = makeFixtureProject('sm-set-disposition-cycle-');
|
|
157
|
-
try {
|
|
158
|
-
writePrd(prdsDir, '3-a.md', cwd, 'dependsOn: [b]\n');
|
|
159
|
-
writePrd(prdsDir, '4-b.md', cwd);
|
|
160
|
-
const before = fs.readFileSync(path.join(prdsDir, '4-b.md'), 'utf8');
|
|
161
|
-
|
|
162
|
-
const result = await scheduler.remote.setPrdDisposition({
|
|
163
|
-
slug: '4-b',
|
|
164
|
-
cwd,
|
|
165
|
-
disposition: 'append',
|
|
166
|
-
dependsOn: ['3-a'],
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
expect(result.ok).toBe(false);
|
|
170
|
-
expect(result.error).toMatch(/cycle/i);
|
|
171
|
-
const after = fs.readFileSync(path.join(prdsDir, '4-b.md'), 'utf8');
|
|
172
|
-
expect(after).toBe(before);
|
|
173
|
-
} finally {
|
|
174
|
-
fs.rmSync(cwd, { recursive: true, force: true });
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
test('running rows are untouched', async () => {
|
|
179
|
-
const { cwd, prdsDir, stateDir } = makeFixtureProject('sm-set-disposition-running-');
|
|
180
|
-
try {
|
|
181
|
-
writePrd(prdsDir, '3-wave1-tail.md', cwd);
|
|
182
|
-
writePrd(prdsDir, '4-wave2-root.md', cwd, 'dependsOn: [wave1-tail]\ndisposition: append\n');
|
|
183
|
-
seedQueueJob(stateDir, '4-wave2-root', 'running');
|
|
184
|
-
const before = fs.readFileSync(path.join(prdsDir, '4-wave2-root.md'), 'utf8');
|
|
185
|
-
|
|
186
|
-
const result = await scheduler.remote.setPrdDisposition({
|
|
187
|
-
slug: '4-wave2-root',
|
|
188
|
-
cwd,
|
|
189
|
-
disposition: 'new-head',
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
expect(result.ok).toBe(false);
|
|
193
|
-
expect(result.error).toMatch(/running/i);
|
|
194
|
-
const after = fs.readFileSync(path.join(prdsDir, '4-wave2-root.md'), 'utf8');
|
|
195
|
-
expect(after).toBe(before);
|
|
196
|
-
} finally {
|
|
197
|
-
fs.rmSync(cwd, { recursive: true, force: true });
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
test('completed rows are untouched', async () => {
|
|
202
|
-
const { cwd, prdsDir, stateDir } = makeFixtureProject('sm-set-disposition-completed-');
|
|
203
|
-
try {
|
|
204
|
-
writePrd(prdsDir, '3-wave1-tail.md', cwd);
|
|
205
|
-
writePrd(prdsDir, '4-wave2-root.md', cwd, 'dependsOn: [wave1-tail]\ndisposition: append\n');
|
|
206
|
-
seedQueueJob(stateDir, '4-wave2-root', 'completed');
|
|
207
|
-
const before = fs.readFileSync(path.join(prdsDir, '4-wave2-root.md'), 'utf8');
|
|
208
|
-
|
|
209
|
-
const result = await scheduler.remote.setPrdDisposition({
|
|
210
|
-
slug: '4-wave2-root',
|
|
211
|
-
cwd,
|
|
212
|
-
disposition: 'new-head',
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
expect(result.ok).toBe(false);
|
|
216
|
-
expect(result.error).toMatch(/completed/i);
|
|
217
|
-
const after = fs.readFileSync(path.join(prdsDir, '4-wave2-root.md'), 'utf8');
|
|
218
|
-
expect(after).toBe(before);
|
|
219
|
-
} finally {
|
|
220
|
-
fs.rmSync(cwd, { recursive: true, force: true });
|
|
221
|
-
}
|
|
222
|
-
});
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* prdSizing.test.cjs — unit tests for sizingWarnings (PRD 1403).
|
|
3
|
-
*
|
|
4
|
-
* Run: timeout 120 npx vitest run src/main/__tests__/prdSizing.test.cjs
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
'use strict';
|
|
8
|
-
|
|
9
|
-
import { test, expect } from 'vitest';
|
|
10
|
-
const { SIZING_LIMITS, sizingWarnings } = require('../lib/prdSizing.cjs');
|
|
11
|
-
|
|
12
|
-
function compliantInput(overrides = {}) {
|
|
13
|
-
return {
|
|
14
|
-
estimateMinutes: 10,
|
|
15
|
-
acceptanceCriteria: ['widget frobnicates on click', 'unit test covers the frobnication path'],
|
|
16
|
-
goal: 'Add frobnication to the widget subsystem.',
|
|
17
|
-
implementationNotes: 'See src/widget.cjs:10.',
|
|
18
|
-
...overrides,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
test('compliant PRD yields no warnings', () => {
|
|
23
|
-
expect(sizingWarnings(compliantInput())).toEqual([]);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('warns when estimateMinutes exceeds the limit', () => {
|
|
27
|
-
const warnings = sizingWarnings(compliantInput({ estimateMinutes: SIZING_LIMITS.estimateMinutes + 1 }));
|
|
28
|
-
expect(warnings.some((w) => /estimateMinutes/.test(w))).toBe(true);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test('does not warn when estimateMinutes is exactly the limit', () => {
|
|
32
|
-
const warnings = sizingWarnings(compliantInput({ estimateMinutes: SIZING_LIMITS.estimateMinutes }));
|
|
33
|
-
expect(warnings.some((w) => /estimateMinutes/.test(w))).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test('warns when acceptanceCriteria has more than the limit of lines', () => {
|
|
37
|
-
const acceptanceCriteria = Array.from({ length: SIZING_LIMITS.acLines + 1 }, (_, i) => `criterion ${i}`);
|
|
38
|
-
const warnings = sizingWarnings(compliantInput({ acceptanceCriteria }));
|
|
39
|
-
expect(warnings.some((w) => /acceptanceCriteria has/.test(w))).toBe(true);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test('does not warn when acceptanceCriteria has exactly the limit of lines', () => {
|
|
43
|
-
const acceptanceCriteria = Array.from({ length: SIZING_LIMITS.acLines }, (_, i) => `criterion ${i}`);
|
|
44
|
-
const warnings = sizingWarnings(compliantInput({ acceptanceCriteria }));
|
|
45
|
-
expect(warnings.some((w) => /acceptanceCriteria has/.test(w))).toBe(false);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('warns when an AC line exceeds the per-line character limit', () => {
|
|
49
|
-
const longLine = 'x'.repeat(SIZING_LIMITS.acLineChars + 1);
|
|
50
|
-
const warnings = sizingWarnings(compliantInput({ acceptanceCriteria: [longLine] }));
|
|
51
|
-
expect(warnings.some((w) => /exceed \d+ characters/.test(w))).toBe(true);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('does not warn when an AC line is exactly at the per-line character limit', () => {
|
|
55
|
-
const line = 'x'.repeat(SIZING_LIMITS.acLineChars);
|
|
56
|
-
const warnings = sizingWarnings(compliantInput({ acceptanceCriteria: [line] }));
|
|
57
|
-
expect(warnings.some((w) => /exceed \d+ characters/.test(w))).toBe(false);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('warns on an open-ended search-and-fix AC line', () => {
|
|
61
|
-
const warnings = sizingWarnings(compliantInput({
|
|
62
|
-
acceptanceCriteria: ['grep e2e specs and update expectations to match the new sort order'],
|
|
63
|
-
}));
|
|
64
|
-
expect(warnings.some((w) => /open-ended search-and-fix/.test(w))).toBe(true);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test('does not warn on an AC line that merely mentions grep or update in isolation', () => {
|
|
68
|
-
const warnings = sizingWarnings(compliantInput({
|
|
69
|
-
acceptanceCriteria: ['grep confirms no leftover references to the old flag'],
|
|
70
|
-
}));
|
|
71
|
-
expect(warnings.some((w) => /open-ended search-and-fix/.test(w))).toBe(false);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test('warns on an open-ended search-and-fix AC line whose "then"/"update" half is a second sentence', () => {
|
|
75
|
-
const warnings = sizingWarnings(compliantInput({
|
|
76
|
-
acceptanceCriteria: ['Grep the repo for every usage of the old flag. Then update each call site.'],
|
|
77
|
-
}));
|
|
78
|
-
expect(warnings.some((w) => /open-ended search-and-fix/.test(w))).toBe(true);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test('warns on an AC line with two or more timeout commands', () => {
|
|
82
|
-
const warnings = sizingWarnings(compliantInput({
|
|
83
|
-
acceptanceCriteria: ['timeout 120 npm run typecheck && timeout 300 npm run test:unit both pass'],
|
|
84
|
-
}));
|
|
85
|
-
expect(warnings.some((w) => /two or more `timeout/.test(w))).toBe(true);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('does not warn on an AC line with a single timeout command', () => {
|
|
89
|
-
const warnings = sizingWarnings(compliantInput({
|
|
90
|
-
acceptanceCriteria: ['timeout 120 npm run typecheck passes'],
|
|
91
|
-
}));
|
|
92
|
-
expect(warnings.some((w) => /two or more `timeout/.test(w))).toBe(false);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test('warns when goal + implementationNotes + joined AC exceeds the body character limit', () => {
|
|
96
|
-
const warnings = sizingWarnings(compliantInput({
|
|
97
|
-
goal: 'g'.repeat(SIZING_LIMITS.bodyChars + 1),
|
|
98
|
-
}));
|
|
99
|
-
expect(warnings.some((w) => /exceeding the \d+-character sizing limit/.test(w))).toBe(true);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test('does not warn when the combined body is exactly at the character limit', () => {
|
|
103
|
-
const goal = 'g'.repeat(SIZING_LIMITS.bodyChars);
|
|
104
|
-
const warnings = sizingWarnings({ estimateMinutes: 10, acceptanceCriteria: [], goal, implementationNotes: '' });
|
|
105
|
-
expect(warnings.some((w) => /exceeding the \d+-character sizing limit/.test(w))).toBe(false);
|
|
106
|
-
});
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* prdSourcePromptIdBackfill.test.cjs — PRD 830: a PRD file's location under
|
|
3
|
-
* `.../scheduler/epics/<epicId>/prds/<slug>.md` already IS its Epic
|
|
4
|
-
* membership, so ingest should stamp `sourcePromptId = <epicId>` whenever
|
|
5
|
-
* frontmatter doesn't supply one — instead of leaving it null forever.
|
|
6
|
-
*
|
|
7
|
-
* Covers:
|
|
8
|
-
* - deriveEpicIdFromPrdPath: pure path-shape extraction (prdLocations.cjs)
|
|
9
|
-
* - parsePrdRaw: dir-derived stamping + frontmatter-wins precedence
|
|
10
|
-
* - reconcileSourcePromptId: pending-only backfill (scheduler.cjs)
|
|
11
|
-
*
|
|
12
|
-
* Run: timeout 120 npx vitest run src/main/__tests__/prdSourcePromptIdBackfill.test.cjs
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
'use strict';
|
|
16
|
-
|
|
17
|
-
import { test, expect } from 'vitest';
|
|
18
|
-
const fsp = require('node:fs/promises');
|
|
19
|
-
const os = require('node:os');
|
|
20
|
-
const path = require('node:path');
|
|
21
|
-
|
|
22
|
-
const { deriveEpicIdFromPrdPath, resolveEpicPrdWriteDir } = require('../lib/prdLocations.cjs');
|
|
23
|
-
const { parsePrdRaw, _resetCache } = require('../scheduler/prdParser.cjs');
|
|
24
|
-
const { reconcileSourcePromptId } = require('../scheduler.cjs');
|
|
25
|
-
|
|
26
|
-
async function mkProjectCwd() {
|
|
27
|
-
return fsp.mkdtemp(path.join(os.tmpdir(), 'sm-prd-backfill-'));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// ---------- deriveEpicIdFromPrdPath ----------
|
|
31
|
-
|
|
32
|
-
test('deriveEpicIdFromPrdPath extracts the epic id from a well-formed epic PRD path', async () => {
|
|
33
|
-
const cwd = await mkProjectCwd();
|
|
34
|
-
const epicId = 'some-epic-abc123';
|
|
35
|
-
const dir = resolveEpicPrdWriteDir(cwd, epicId);
|
|
36
|
-
await fsp.mkdir(dir, { recursive: true });
|
|
37
|
-
const filePath = path.join(dir, '900-example.md');
|
|
38
|
-
expect(deriveEpicIdFromPrdPath(filePath)).toBe(epicId);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('deriveEpicIdFromPrdPath returns null for the retired flat prds/ layout', () => {
|
|
42
|
-
const filePath = '/home/user/Projects/foo/session-manager-operations/scheduler/prds/900-example.md';
|
|
43
|
-
expect(deriveEpicIdFromPrdPath(filePath)).toBe(null);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('deriveEpicIdFromPrdPath returns null for an unrelated path', () => {
|
|
47
|
-
expect(deriveEpicIdFromPrdPath('/tmp/whatever/900-example.md')).toBe(null);
|
|
48
|
-
expect(deriveEpicIdFromPrdPath(null)).toBe(null);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// ---------- parsePrdRaw: dir-derived stamping + frontmatter-wins ----------
|
|
52
|
-
|
|
53
|
-
test('parsePrdRaw derives sourcePromptId from the parent epic dir when frontmatter omits it', async () => {
|
|
54
|
-
_resetCache();
|
|
55
|
-
const cwd = await mkProjectCwd();
|
|
56
|
-
const epicId = 'derive-me-epic-def456';
|
|
57
|
-
const dir = resolveEpicPrdWriteDir(cwd, epicId);
|
|
58
|
-
await fsp.mkdir(dir, { recursive: true });
|
|
59
|
-
const filePath = path.join(dir, '901-hand-authored.md');
|
|
60
|
-
await fsp.writeFile(filePath, [
|
|
61
|
-
'---',
|
|
62
|
-
'title: Hand-authored, no sourcePromptId',
|
|
63
|
-
`cwd: ${cwd}`,
|
|
64
|
-
'---',
|
|
65
|
-
'# Goal',
|
|
66
|
-
'',
|
|
67
|
-
'Do the thing.',
|
|
68
|
-
'',
|
|
69
|
-
].join('\n'));
|
|
70
|
-
|
|
71
|
-
const parsed = await parsePrdRaw(filePath);
|
|
72
|
-
expect(parsed.sourcePromptId).toBe(epicId);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('parsePrdRaw: explicit frontmatter sourcePromptId wins over the dir-derived epic id', async () => {
|
|
76
|
-
_resetCache();
|
|
77
|
-
const cwd = await mkProjectCwd();
|
|
78
|
-
const epicId = 'dir-epic-ghi789';
|
|
79
|
-
const dir = resolveEpicPrdWriteDir(cwd, epicId);
|
|
80
|
-
await fsp.mkdir(dir, { recursive: true });
|
|
81
|
-
const filePath = path.join(dir, '902-explicit.md');
|
|
82
|
-
await fsp.writeFile(filePath, [
|
|
83
|
-
'---',
|
|
84
|
-
'title: Explicit sourcePromptId',
|
|
85
|
-
`cwd: ${cwd}`,
|
|
86
|
-
'sourcePromptId: ticket-explicit-999',
|
|
87
|
-
'---',
|
|
88
|
-
'# Goal',
|
|
89
|
-
'',
|
|
90
|
-
'Do the thing.',
|
|
91
|
-
'',
|
|
92
|
-
].join('\n'));
|
|
93
|
-
|
|
94
|
-
const parsed = await parsePrdRaw(filePath);
|
|
95
|
-
expect(parsed.sourcePromptId).toBe('ticket-explicit-999');
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// ---------- reconcileSourcePromptId: pending-only backfill ----------
|
|
99
|
-
|
|
100
|
-
test('reconcileSourcePromptId backfills a pending job whose sourcePromptId is null', () => {
|
|
101
|
-
const job = { slug: 'x', status: 'pending', sourcePromptId: null };
|
|
102
|
-
expect(reconcileSourcePromptId(job, 'epic-abc')).toBe('epic-abc');
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test('reconcileSourcePromptId leaves a running job untouched even if its sourcePromptId is null', () => {
|
|
106
|
-
const job = { slug: 'x', status: 'running', sourcePromptId: null };
|
|
107
|
-
expect(reconcileSourcePromptId(job, 'epic-abc')).toBe(null);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test('reconcileSourcePromptId leaves a completed job untouched even if its sourcePromptId is null', () => {
|
|
111
|
-
const job = { slug: 'x', status: 'completed', sourcePromptId: null };
|
|
112
|
-
expect(reconcileSourcePromptId(job, 'epic-abc')).toBe(null);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test('reconcileSourcePromptId keeps a pending job\'s existing value if the fresh parse yields null', () => {
|
|
116
|
-
const job = { slug: 'x', status: 'pending', sourcePromptId: 'already-set' };
|
|
117
|
-
expect(reconcileSourcePromptId(job, null)).toBe('already-set');
|
|
118
|
-
});
|