claude-code-session-manager 0.97.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-D93FoaOm.js → DataModel-HdR0AxFq.js} +1 -1
- package/dist/assets/{History-CXxxqNP1.js → History-Dr4Jr_5z.js} +2 -2
- package/dist/assets/{Hooks-CzeYFQjq.js → Hooks-NhrvH3JP.js} +3 -3
- package/dist/assets/{Library-D2zPkwOC.js → Library-Dv_EtIMr.js} +1 -1
- package/dist/assets/{MarkdownEditor-DbinP78A.js → MarkdownEditor-DTKDWV_n.js} +1 -1
- package/dist/assets/{McpServers-Bu_sVGLr.js → McpServers-M034G9B3.js} +2 -2
- package/dist/assets/{Memory-BgiI6LZ_.js → Memory-DzF1B4gx.js} +6 -6
- package/dist/assets/{Permissions-C1MMzZRm.js → Permissions-DrgbSGWl.js} +3 -3
- package/dist/assets/{Plugins-Dhu6wAZi.js → Plugins-Bd3ef35w.js} +2 -2
- package/dist/assets/{ProvenanceBadge-C3AcWKMG.js → ProvenanceBadge-DcBHT1Iy.js} +1 -1
- package/dist/assets/{SaveBar-plwYm0iO.js → SaveBar-rimJem-Y.js} +1 -1
- package/dist/assets/Scheduler-DjgFJl2w.js +16 -0
- package/dist/assets/{ScopeSwitcher-DFy0vv_o.js → ScopeSwitcher-CnAzTBrl.js} +1 -1
- package/dist/assets/Settings-Dc1F_sSg.js +3 -0
- package/dist/assets/{SkillReferenceGraph-DsI7hRPB.js → SkillReferenceGraph-B9aZDecM.js} +1 -1
- package/dist/assets/{Skills-3E748UfB.js → Skills-DRXd18gu.js} +2 -2
- package/dist/assets/{SystemPrompt-BqmfUJOd.js → SystemPrompt-ahy5-Fwe.js} +1 -1
- package/dist/assets/{TagLibrary-CPz6fO8Q.js → TagLibrary-C_tToDeL.js} +1 -1
- package/dist/assets/{TiptapBody-D9EoBQ1P.js → TiptapBody-DvdefS6K.js} +1 -1
- package/dist/assets/{Toggle-BHAmZNDn.js → Toggle-6Jl5Njc6.js} +1 -1
- package/dist/assets/{index-CKH5Uxik.css → index-Bta-hwud.css} +1 -1
- package/dist/assets/{index-tn5JIVPj.js → index-vx8O73l8.js} +497 -502
- package/dist/assets/{settingsSchema-Crqy_aNz.js → settingsSchema-D6iRguNV.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +26 -29
- package/plugins/CLAUDE.md +6 -6
- package/plugins/session-manager-dev/skills/builder/4-manual/SKILL.md +23 -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 +153 -19
- 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 +33 -30
- package/src/main/lib/workTypeLibrary.cjs +7 -1
- package/src/main/promptSessionEvents.cjs +37 -13
- package/src/main/queueOps.cjs +17 -6
- package/src/main/scheduler.cjs +975 -203
- 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-nESrTRIg.js +0 -1
- package/dist/assets/Scheduler-BVYTeh39.js +0 -16
- package/dist/assets/Settings-DIhGgdfs.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__/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 -154
- 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-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 -375
- package/src/main/lib/__tests__/watchdog-relaunch.test.cjs +0 -266
- package/src/main/lib/kgExchangePairing.cjs +0 -75
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* runVerify-landed-commit-outranks.test.cjs — ground truth (exit 0 + a commit
|
|
3
|
-
* landed THIS run + no explicit FAIL sentinel) outranks the transcript-
|
|
4
|
-
* pattern heuristics (final-20% is_error, FAIL/Traceback,
|
|
5
|
-
* ModuleNotFoundError), so a self-recovered tool error no longer parks a
|
|
6
|
-
* green, committed run.
|
|
7
|
-
*
|
|
8
|
-
* Fixture: the REAL run log for 1218-fo-01-move-scripts-lib-into-src-main-lib
|
|
9
|
-
* (session-manager-operations/reviews/2026-09-13-scheduler-stability-
|
|
10
|
-
* investigation.md), copied verbatim from
|
|
11
|
-
* ~/.claude/session-manager/scheduled-plans/runs/2026-09-13T21-52-51-192Z/ —
|
|
12
|
-
* a `git apply` "patch does not apply" tool error at event 179/209 (inside
|
|
13
|
-
* the final 20% of the transcript) that the agent retried and resolved 3
|
|
14
|
-
* events later, in a run that landed commit d1edf15 and was STILL parked
|
|
15
|
-
* needs_review (verdicts.json: verdict transcript_errors, reason
|
|
16
|
-
* "is_error=true in final 20% of transcript (event 179/209)"), spawning a
|
|
17
|
-
* $3.74 fix-plan investigation into work that needed no fix.
|
|
18
|
-
*
|
|
19
|
-
* The real run's own SCHEDULER_VERDICT sentinel is an explicit FAIL — an
|
|
20
|
-
* honest, UNRELATED report that test:unit was red for proven pre-existing/
|
|
21
|
-
* environmental reasons (shared /tmp contention), not a regression from this
|
|
22
|
-
* PRD's move. Per this PRD's own AC, an explicit FAIL sentinel must keep
|
|
23
|
-
* today's behavior byte-for-byte, so scenarios (a)/(b)/(d) below use a
|
|
24
|
-
* variant of the fixture with that trailing SCHEDULER_VERDICT line stripped
|
|
25
|
-
* (sentinel === null) — the majority real-world park shape this rule targets
|
|
26
|
-
* (the findings report measured 77 of 212 parks as transcript_errors with NO
|
|
27
|
-
* sentinel at all, vs. this one specific row's own additional, unrelated
|
|
28
|
-
* FAIL claim). Scenario (c) reuses the pristine, byte-for-byte-unmodified
|
|
29
|
-
* fixture to prove the real, still-present FAIL sentinel is honored exactly
|
|
30
|
-
* as before this change.
|
|
31
|
-
*
|
|
32
|
-
* Run standalone: timeout 120 npx vitest run src/main/__tests__/runVerify-landed-commit-outranks.test.cjs
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
import { test, beforeAll, afterAll, vi } from 'vitest';
|
|
36
|
-
const assert = require('node:assert/strict');
|
|
37
|
-
const os = require('node:os');
|
|
38
|
-
const fs = require('node:fs');
|
|
39
|
-
const path = require('node:path');
|
|
40
|
-
const { execFileSync } = require('node:child_process');
|
|
41
|
-
const { verifyRun } = require('../runVerify.cjs');
|
|
42
|
-
|
|
43
|
-
// Sidecar goes through config.writeJsonSync, whose allow-list rejects os.tmpdir() fixtures.
|
|
44
|
-
let writeSpy;
|
|
45
|
-
beforeAll(() => {
|
|
46
|
-
writeSpy = vi.spyOn(require('../config.cjs'), 'writeJsonSync').mockImplementation((abs, data) => {
|
|
47
|
-
require('node:fs').writeFileSync(abs, JSON.stringify(data, null, 2) + '\n');
|
|
48
|
-
return { ok: true, mtimeMs: 0 };
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
afterAll(() => writeSpy.mockRestore());
|
|
52
|
-
|
|
53
|
-
const SLUG = '1218-fo-01-move-scripts-lib-into-src-main-lib';
|
|
54
|
-
const FIXTURE_PATH = path.join(__dirname, 'fixtures', `${SLUG}.log`);
|
|
55
|
-
const LANDED_COMMIT = 'd1edf15be50a783f08a55e6de328780f0feb3cb0';
|
|
56
|
-
|
|
57
|
-
function makeTmpDir() {
|
|
58
|
-
return fs.mkdtempSync(path.join(os.tmpdir(), 'run-verify-landed-commit-outranks-test-'));
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function rmdir(dir) {
|
|
62
|
-
try { fs.rmSync(dir, { recursive: true, force: true }); } catch { /* */ }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function makeTmpGitRepo() {
|
|
66
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'run-verify-landed-commit-outranks-repo-'));
|
|
67
|
-
execFileSync('git', ['init', '-q'], { cwd: dir });
|
|
68
|
-
execFileSync('git', ['config', 'user.email', 'test@example.com'], { cwd: dir });
|
|
69
|
-
execFileSync('git', ['config', 'user.name', 'Test'], { cwd: dir });
|
|
70
|
-
fs.writeFileSync(path.join(dir, 'README.md'), 'init\n');
|
|
71
|
-
execFileSync('git', ['add', 'README.md'], { cwd: dir });
|
|
72
|
-
execFileSync('git', ['commit', '-q', '-m', 'init'], { cwd: dir });
|
|
73
|
-
return dir;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function writePrd(dir, slug) {
|
|
77
|
-
const text = '---\ntitle: Test PRD\ncwd: /tmp\nestimateMinutes: 30\n---\n# Move scripts/lib into src/main/lib\n';
|
|
78
|
-
fs.writeFileSync(path.join(dir, `${slug}.md`), text);
|
|
79
|
-
return path.join(dir, `${slug}.md`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Load the real fixture log, optionally stripping the trailing
|
|
84
|
-
* `SCHEDULER_VERDICT: FAIL ...` line from the final `{"type":"result",...}`
|
|
85
|
-
* event's `result` field so the sentinel scan sees no sentinel at all.
|
|
86
|
-
*/
|
|
87
|
-
function loadFixture({ stripFailSentinel }) {
|
|
88
|
-
const raw = fs.readFileSync(FIXTURE_PATH, 'utf8');
|
|
89
|
-
if (!stripFailSentinel) return raw;
|
|
90
|
-
const lines = raw.split('\n');
|
|
91
|
-
const idx = lines.findIndex((l) => l.includes('"type":"result"'));
|
|
92
|
-
assert.ok(idx !== -1, 'fixture must contain a type:result line');
|
|
93
|
-
const obj = JSON.parse(lines[idx]);
|
|
94
|
-
assert.ok(/SCHEDULER_VERDICT:\s*FAIL/.test(obj.result), 'fixture result must carry the real FAIL sentinel before stripping');
|
|
95
|
-
obj.result = obj.result.replace(/\n?SCHEDULER_VERDICT:\s*FAIL[^\n]*$/, '');
|
|
96
|
-
assert.ok(!/SCHEDULER_VERDICT/.test(obj.result), 'sentinel must be fully removed from the stripped variant');
|
|
97
|
-
lines[idx] = JSON.stringify(obj);
|
|
98
|
-
return lines.join('\n');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function writeLog(dir, slug, text) {
|
|
102
|
-
fs.writeFileSync(path.join(dir, `${slug}.log`), text);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// (a) exit 0 + commit landed THIS run + no sentinel at all → clean, demoted to annotation.
|
|
106
|
-
test('exit 0 + landed commit this run + no FAIL sentinel → clean with annotation (1218-fo-01)', async () => {
|
|
107
|
-
const tmp = makeTmpDir();
|
|
108
|
-
const repo = makeTmpGitRepo();
|
|
109
|
-
try {
|
|
110
|
-
writeLog(tmp, SLUG, loadFixture({ stripFailSentinel: true }));
|
|
111
|
-
const prdPath = writePrd(tmp, SLUG);
|
|
112
|
-
const verdict = await verifyRun({
|
|
113
|
-
runDir: tmp,
|
|
114
|
-
prdPath,
|
|
115
|
-
queueEntry: { slug: SLUG, status: 'running', cwd: repo },
|
|
116
|
-
allJobs: [],
|
|
117
|
-
committedDuringRun: false,
|
|
118
|
-
jobLandedCommitThisRun: LANDED_COMMIT,
|
|
119
|
-
exitCode: 0,
|
|
120
|
-
});
|
|
121
|
-
assert.equal(verdict.verdict, 'clean', `expected clean, got ${verdict.verdict}: ${verdict.reason}`);
|
|
122
|
-
assert.equal(verdict.downgradeTo, null);
|
|
123
|
-
const sidecar = JSON.parse(fs.readFileSync(path.join(tmp, `${SLUG}.verdicts.json`), 'utf8'));
|
|
124
|
-
assert.ok(Array.isArray(sidecar.annotations) && sidecar.annotations.length > 0, 'the demoted is_error hit must be recorded as an annotation');
|
|
125
|
-
assert.ok(sidecar.annotations.some((a) => a.verdict === 'transcript_errors'), 'annotation must carry the original transcript_errors verdict');
|
|
126
|
-
} finally { rmdir(tmp); rmdir(repo); }
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// (b) the same (stripped-sentinel) log, but exitCode !== 0 → keeps today's behavior.
|
|
130
|
-
test('non-zero exit → transcript_errors (evidence never applies to a failing run)', async () => {
|
|
131
|
-
const tmp = makeTmpDir();
|
|
132
|
-
const repo = makeTmpGitRepo();
|
|
133
|
-
try {
|
|
134
|
-
writeLog(tmp, SLUG, loadFixture({ stripFailSentinel: true }));
|
|
135
|
-
const prdPath = writePrd(tmp, SLUG);
|
|
136
|
-
const verdict = await verifyRun({
|
|
137
|
-
runDir: tmp,
|
|
138
|
-
prdPath,
|
|
139
|
-
queueEntry: { slug: SLUG, status: 'running', cwd: repo },
|
|
140
|
-
allJobs: [],
|
|
141
|
-
committedDuringRun: false,
|
|
142
|
-
jobLandedCommitThisRun: LANDED_COMMIT,
|
|
143
|
-
exitCode: 1,
|
|
144
|
-
});
|
|
145
|
-
assert.equal(verdict.verdict, 'transcript_errors', `expected transcript_errors, got ${verdict.verdict}: ${verdict.reason}`);
|
|
146
|
-
assert.equal(verdict.downgradeTo, 'needs_review');
|
|
147
|
-
} finally { rmdir(tmp); rmdir(repo); }
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
// (c) the pristine, byte-for-byte-unmodified fixture — its own real FAIL sentinel — keeps today's behavior.
|
|
151
|
-
test('explicit FAIL sentinel (the real, unmodified fixture) → transcript_errors byte-for-byte', async () => {
|
|
152
|
-
const tmp = makeTmpDir();
|
|
153
|
-
const repo = makeTmpGitRepo();
|
|
154
|
-
try {
|
|
155
|
-
writeLog(tmp, SLUG, loadFixture({ stripFailSentinel: false }));
|
|
156
|
-
const prdPath = writePrd(tmp, SLUG);
|
|
157
|
-
const verdict = await verifyRun({
|
|
158
|
-
runDir: tmp,
|
|
159
|
-
prdPath,
|
|
160
|
-
queueEntry: { slug: SLUG, status: 'running', cwd: repo },
|
|
161
|
-
allJobs: [],
|
|
162
|
-
committedDuringRun: false,
|
|
163
|
-
jobLandedCommitThisRun: LANDED_COMMIT,
|
|
164
|
-
exitCode: 0,
|
|
165
|
-
});
|
|
166
|
-
assert.equal(verdict.verdict, 'transcript_errors', `expected transcript_errors, got ${verdict.verdict}: ${verdict.reason}`);
|
|
167
|
-
assert.equal(verdict.downgradeTo, 'needs_review');
|
|
168
|
-
assert.equal(verdict.sentinel, 'fail');
|
|
169
|
-
} finally { rmdir(tmp); rmdir(repo); }
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// (d) no landed-commit evidence at all → transcript_errors (evidence gate requires attribution).
|
|
173
|
-
test('no landed commit evidence → transcript_errors (evidence gate requires attribution)', async () => {
|
|
174
|
-
const tmp = makeTmpDir();
|
|
175
|
-
const repo = makeTmpGitRepo();
|
|
176
|
-
try {
|
|
177
|
-
writeLog(tmp, SLUG, loadFixture({ stripFailSentinel: true }));
|
|
178
|
-
const prdPath = writePrd(tmp, SLUG);
|
|
179
|
-
const verdict = await verifyRun({
|
|
180
|
-
runDir: tmp,
|
|
181
|
-
prdPath,
|
|
182
|
-
queueEntry: { slug: SLUG, status: 'running', cwd: repo },
|
|
183
|
-
allJobs: [],
|
|
184
|
-
committedDuringRun: false,
|
|
185
|
-
jobLandedCommitThisRun: null,
|
|
186
|
-
exitCode: 0,
|
|
187
|
-
});
|
|
188
|
-
assert.equal(verdict.verdict, 'transcript_errors', `expected transcript_errors, got ${verdict.verdict}: ${verdict.reason}`);
|
|
189
|
-
assert.equal(verdict.downgradeTo, 'needs_review');
|
|
190
|
-
} finally { rmdir(tmp); rmdir(repo); }
|
|
191
|
-
});
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* runVerify-policy-denial.test.cjs — a PreToolUse hook denial (`Blocked: ...`
|
|
3
|
-
* tool_result) must not downgrade an otherwise-clean run, but a genuine
|
|
4
|
-
* late-run failure must still downgrade normally.
|
|
5
|
-
*
|
|
6
|
-
* Run: timeout 120 npx vitest run src/main/__tests__/runVerify-policy-denial.test.cjs
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { test } from 'vitest';
|
|
10
|
-
const assert = require('node:assert/strict');
|
|
11
|
-
const os = require('node:os');
|
|
12
|
-
const fs = require('node:fs');
|
|
13
|
-
const path = require('node:path');
|
|
14
|
-
const { verifyRun } = require('../runVerify.cjs');
|
|
15
|
-
|
|
16
|
-
function makeTmpDir() {
|
|
17
|
-
return fs.mkdtempSync(path.join(os.tmpdir(), 'run-verify-policy-denial-test-'));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function rmdir(dir) {
|
|
21
|
-
try { fs.rmSync(dir, { recursive: true, force: true }); } catch { /* */ }
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function writeLog(dir, slug, events) {
|
|
25
|
-
const lines = ['[scheduler] starting ' + slug + ' at 2026-09-02T00:00:00.000Z'];
|
|
26
|
-
for (const ev of events) lines.push(JSON.stringify(ev));
|
|
27
|
-
lines.push('[scheduler] exit code=0 (raw code=0 signal=null) duration=47s');
|
|
28
|
-
fs.writeFileSync(path.join(dir, `${slug}.log`), lines.join('\n') + '\n');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function writePrd(dir, slug, body) {
|
|
32
|
-
const text = `---\ntitle: Test PRD\ncwd: /tmp\nestimateMinutes: 30\n---\n${body}\n`;
|
|
33
|
-
fs.writeFileSync(path.join(dir, `${slug}.md`), text);
|
|
34
|
-
return path.join(dir, `${slug}.md`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
test('PreToolUse policy denial (Blocked: ...) in final 20% → clean, surfaced as annotation', async () => {
|
|
38
|
-
const tmp = makeTmpDir();
|
|
39
|
-
try {
|
|
40
|
-
const slug = '1106-policy-denial-exempt';
|
|
41
|
-
const events = [];
|
|
42
|
-
for (let k = 0; k < 8; k++) {
|
|
43
|
-
events.push({ type: 'assistant', message: { role: 'assistant', content: [
|
|
44
|
-
{ type: 'tool_use', id: `t${k}`, name: 'Read', input: { description: `read ${k}` } }] } });
|
|
45
|
-
events.push({ type: 'user', message: { role: 'user', content: [
|
|
46
|
-
{ type: 'tool_result', tool_use_id: `t${k}`, content: 'ok', is_error: false }] } });
|
|
47
|
-
}
|
|
48
|
-
events.push({ type: 'assistant', message: { role: 'assistant', content: [
|
|
49
|
-
{ type: 'tool_use', id: 'tgit', name: 'Bash', input: { command: 'git stash', description: 'stash before checkout' } }] } });
|
|
50
|
-
events.push({ type: 'user', message: { role: 'user', content: [
|
|
51
|
-
{ type: 'tool_result', tool_use_id: 'tgit',
|
|
52
|
-
content: 'Blocked: `stash` in what this hook believes is a SHARED working tree (/home/bilko/Projects/session-manager).',
|
|
53
|
-
is_error: true }] } });
|
|
54
|
-
events.push({ type: 'result', subtype: 'success', result: 'All acceptance criteria verified.\nSCHEDULER_VERDICT: PASS' });
|
|
55
|
-
|
|
56
|
-
writeLog(tmp, slug, events);
|
|
57
|
-
const prdPath = writePrd(tmp, slug, '# Policy denial exempt');
|
|
58
|
-
const verdict = await verifyRun({ runDir: tmp, prdPath, queueEntry: { slug, status: 'running' }, allJobs: [], committedDuringRun: true });
|
|
59
|
-
assert.equal(verdict.verdict, 'clean', `policy denial must not flag, got ${verdict.verdict}: ${verdict.reason}`);
|
|
60
|
-
assert.ok(
|
|
61
|
-
Array.isArray(verdict.annotations) && verdict.annotations.some((a) => a.verdict === 'policy_denial'),
|
|
62
|
-
`expected a policy_denial annotation, got ${JSON.stringify(verdict.annotations)}`,
|
|
63
|
-
);
|
|
64
|
-
} finally { rmdir(tmp); }
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test('genuine late-run failure (not a policy denial) still downgrades to transcript_errors', async () => {
|
|
68
|
-
const tmp = makeTmpDir();
|
|
69
|
-
try {
|
|
70
|
-
const slug = '1106-genuine-failure-still-flags';
|
|
71
|
-
const events = [];
|
|
72
|
-
for (let k = 0; k < 8; k++) {
|
|
73
|
-
events.push({ type: 'assistant', message: { role: 'assistant', content: [
|
|
74
|
-
{ type: 'tool_use', id: `t${k}`, name: 'Read', input: { description: `read ${k}` } }] } });
|
|
75
|
-
events.push({ type: 'user', message: { role: 'user', content: [
|
|
76
|
-
{ type: 'tool_result', tool_use_id: `t${k}`, content: 'ok', is_error: false }] } });
|
|
77
|
-
}
|
|
78
|
-
events.push({ type: 'assistant', message: { role: 'assistant', content: [
|
|
79
|
-
{ type: 'tool_use', id: 'ttest', name: 'Bash', input: { command: 'npm test', description: 'run tests' } }] } });
|
|
80
|
-
events.push({ type: 'user', message: { role: 'user', content: [
|
|
81
|
-
{ type: 'tool_result', tool_use_id: 'ttest', content: 'FAILED: 1 test failed', is_error: true }] } });
|
|
82
|
-
events.push({ type: 'result', subtype: 'success', result: 'All acceptance criteria verified.' });
|
|
83
|
-
|
|
84
|
-
writeLog(tmp, slug, events);
|
|
85
|
-
const prdPath = writePrd(tmp, slug, '# Genuine failure still flags');
|
|
86
|
-
const verdict = await verifyRun({ runDir: tmp, prdPath, queueEntry: { slug, status: 'running' }, allJobs: [], committedDuringRun: true });
|
|
87
|
-
assert.equal(verdict.verdict, 'transcript_errors', `genuine failure must still flag, got ${verdict.verdict}: ${verdict.reason}`);
|
|
88
|
-
} finally { rmdir(tmp); }
|
|
89
|
-
});
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* runVerify-transcript-commit-evidence.test.cjs — regression tests for the
|
|
3
|
-
* transcript-commit-evidence fallback added to runVerify.cjs.
|
|
4
|
-
*
|
|
5
|
-
* Root cause (99-fix-e2e-needs-review-test, 2026-08-07): a job whose cwd is
|
|
6
|
-
* not a git repo (e.g. an investigation fix-plan that inherited cwd: /tmp)
|
|
7
|
-
* can never produce committedDuringRun=true — gitHead()/committedInWindow()
|
|
8
|
-
* both fail closed there — so the PASS+commit sentinel override could never
|
|
9
|
-
* fire even when the harness's own transcript recorded a real commit. This
|
|
10
|
-
* file asserts the fallback fires ONLY when both conditions hold: the cwd is
|
|
11
|
-
* genuinely not a git repo, AND the transcript itself carries harness-emitted
|
|
12
|
-
* commit evidence (never inferred from prose the model could fabricate).
|
|
13
|
-
*
|
|
14
|
-
* Run standalone: timeout 120 npx vitest run src/main/__tests__/runVerify-transcript-commit-evidence.test.cjs
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { test, beforeAll, afterAll, vi } from 'vitest';
|
|
18
|
-
const assert = require('node:assert/strict');
|
|
19
|
-
const os = require('node:os');
|
|
20
|
-
const fs = require('node:fs');
|
|
21
|
-
const path = require('node:path');
|
|
22
|
-
const { execFileSync } = require('node:child_process');
|
|
23
|
-
const { verifyRun } = require('../runVerify.cjs');
|
|
24
|
-
|
|
25
|
-
// Sidecar goes through config.writeJsonSync, whose allow-list rejects os.tmpdir() fixtures.
|
|
26
|
-
let writeSpy;
|
|
27
|
-
beforeAll(() => {
|
|
28
|
-
writeSpy = vi.spyOn(require('../config.cjs'), 'writeJsonSync').mockImplementation((abs, data) => {
|
|
29
|
-
require('node:fs').writeFileSync(abs, JSON.stringify(data, null, 2) + '\n');
|
|
30
|
-
return { ok: true, mtimeMs: 0 };
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
afterAll(() => writeSpy.mockRestore());
|
|
34
|
-
|
|
35
|
-
// ─── helpers (mirrors runVerify.test.cjs) ─────────────────────────────────────
|
|
36
|
-
|
|
37
|
-
function makeTmpDir() {
|
|
38
|
-
return fs.mkdtempSync(path.join(os.tmpdir(), 'run-verify-commit-evidence-test-'));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function rmdir(dir) {
|
|
42
|
-
try { fs.rmSync(dir, { recursive: true, force: true }); } catch { /* */ }
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function writeLog(dir, slug, events) {
|
|
46
|
-
const lines = ['[scheduler] starting ' + slug + ' at 2026-08-07T02:25:31.453Z'];
|
|
47
|
-
for (const ev of events) lines.push(JSON.stringify(ev));
|
|
48
|
-
lines.push('[scheduler] exit code=0 (raw code=0 signal=null) duration=47s');
|
|
49
|
-
fs.writeFileSync(path.join(dir, `${slug}.log`), lines.join('\n') + '\n');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function writePrd(dir, slug, body) {
|
|
53
|
-
const text = `---\ntitle: Test PRD\ncwd: /tmp\nestimateMinutes: 30\n---\n${body}\n`;
|
|
54
|
-
fs.writeFileSync(path.join(dir, `${slug}.md`), text);
|
|
55
|
-
return path.join(dir, `${slug}.md`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function makeTmpGitRepo() {
|
|
59
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'run-verify-commit-evidence-repo-'));
|
|
60
|
-
execFileSync('git', ['init', '-q'], { cwd: dir });
|
|
61
|
-
execFileSync('git', ['config', 'user.email', 'test@example.com'], { cwd: dir });
|
|
62
|
-
execFileSync('git', ['config', 'user.name', 'Test'], { cwd: dir });
|
|
63
|
-
fs.writeFileSync(path.join(dir, 'README.md'), 'init\n');
|
|
64
|
-
execFileSync('git', ['add', 'README.md'], { cwd: dir });
|
|
65
|
-
execFileSync('git', ['commit', '-q', '-m', 'init'], { cwd: dir });
|
|
66
|
-
return dir;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Build a run log with:
|
|
71
|
-
* - padding events so a late is_error lands in the final 20%
|
|
72
|
-
* - a late is_error tool_result (main-agent, no self-recovery)
|
|
73
|
-
* - optionally a harness-emitted commit-evidence line
|
|
74
|
-
* - a SCHEDULER_VERDICT: PASS result event
|
|
75
|
-
*/
|
|
76
|
-
function buildRunEvents({ includeCommitEvidence, evidenceForm = 'vcs_state_changed' }) {
|
|
77
|
-
const events = [];
|
|
78
|
-
for (let k = 0; k < 8; k++) {
|
|
79
|
-
events.push({ type: 'assistant', message: { role: 'assistant', content: [
|
|
80
|
-
{ type: 'tool_use', id: `t${k}`, name: 'Read', input: { description: `read ${k}` } }] } });
|
|
81
|
-
events.push({ type: 'user', message: { role: 'user', content: [
|
|
82
|
-
{ type: 'tool_result', tool_use_id: `t${k}`, content: 'ok', is_error: false }] } });
|
|
83
|
-
}
|
|
84
|
-
events.push({ type: 'assistant', message: { role: 'assistant', content: [
|
|
85
|
-
{ type: 'tool_use', id: 'tbad', name: 'Agent', input: { description: 'run code review agent' } }] } });
|
|
86
|
-
events.push({ type: 'user', message: { role: 'user', content: [
|
|
87
|
-
{ type: 'tool_result', tool_use_id: 'tbad',
|
|
88
|
-
content: "Agent type 'code-reviewer' not found. Available agents: architect, …", is_error: true }] } });
|
|
89
|
-
|
|
90
|
-
if (includeCommitEvidence) {
|
|
91
|
-
if (evidenceForm === 'vcs_state_changed') {
|
|
92
|
-
events.push({ type: 'system', subtype: 'vcs_state_changed', kind: 'commit', cwd: '/tmp' });
|
|
93
|
-
} else {
|
|
94
|
-
events.push({
|
|
95
|
-
type: 'user',
|
|
96
|
-
message: { role: 'user', content: [
|
|
97
|
-
{ type: 'tool_result', tool_use_id: 'tcommit', content: 'committed', is_error: false }] },
|
|
98
|
-
tool_use_result: { gitOperation: { commit: { sha: '6ecbd40', kind: 'committed' } } },
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
events.push({ type: 'result', subtype: 'success', result: 'All acceptance criteria verified.\nSCHEDULER_VERDICT: PASS' });
|
|
104
|
-
return events;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// ─── (1) regression case: non-git cwd + transcript evidence → clean ──────────
|
|
108
|
-
|
|
109
|
-
test('PASS + late is_error + transcript commit evidence + non-git cwd → clean (fallback fires)', async () => {
|
|
110
|
-
const tmp = makeTmpDir();
|
|
111
|
-
try {
|
|
112
|
-
const slug = '99-fix-e2e-needs-review-test';
|
|
113
|
-
writeLog(tmp, slug, buildRunEvents({ includeCommitEvidence: true }));
|
|
114
|
-
const prdPath = writePrd(tmp, slug, '# Fix scheduler skip guard');
|
|
115
|
-
const nonGitCwd = fs.mkdtempSync(path.join(os.tmpdir(), 'run-verify-nongit-cwd-'));
|
|
116
|
-
try {
|
|
117
|
-
const verdict = await verifyRun({
|
|
118
|
-
runDir: tmp,
|
|
119
|
-
prdPath,
|
|
120
|
-
queueEntry: { slug, status: 'running', cwd: nonGitCwd },
|
|
121
|
-
allJobs: [],
|
|
122
|
-
committedDuringRun: false,
|
|
123
|
-
});
|
|
124
|
-
assert.equal(verdict.verdict, 'clean', `expected clean via transcript fallback, got ${verdict.verdict}: ${verdict.reason}`);
|
|
125
|
-
assert.equal(verdict.downgradeTo, null);
|
|
126
|
-
const sidecar = JSON.parse(fs.readFileSync(path.join(tmp, `${slug}.verdicts.json`), 'utf8'));
|
|
127
|
-
assert.equal(sidecar.commitEvidenceSource, 'transcript', 'sidecar should record the fallback source');
|
|
128
|
-
} finally { rmdir(nonGitCwd); }
|
|
129
|
-
} finally { rmdir(tmp); }
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test('PASS + late is_error + gitOperation.commit evidence + non-git cwd → clean (fallback fires)', async () => {
|
|
133
|
-
const tmp = makeTmpDir();
|
|
134
|
-
try {
|
|
135
|
-
const slug = '99-fix-e2e-needs-review-test-alt';
|
|
136
|
-
writeLog(tmp, slug, buildRunEvents({ includeCommitEvidence: true, evidenceForm: 'gitOperation' }));
|
|
137
|
-
const prdPath = writePrd(tmp, slug, '# Fix scheduler skip guard');
|
|
138
|
-
const nonGitCwd = fs.mkdtempSync(path.join(os.tmpdir(), 'run-verify-nongit-cwd-'));
|
|
139
|
-
try {
|
|
140
|
-
const verdict = await verifyRun({
|
|
141
|
-
runDir: tmp,
|
|
142
|
-
prdPath,
|
|
143
|
-
queueEntry: { slug, status: 'running', cwd: nonGitCwd },
|
|
144
|
-
allJobs: [],
|
|
145
|
-
committedDuringRun: false,
|
|
146
|
-
});
|
|
147
|
-
assert.equal(verdict.verdict, 'clean', `expected clean via transcript fallback, got ${verdict.verdict}: ${verdict.reason}`);
|
|
148
|
-
} finally { rmdir(nonGitCwd); }
|
|
149
|
-
} finally { rmdir(tmp); }
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// ─── (2) no evidence lines → fallback must not fire, still transcript_errors ──
|
|
153
|
-
|
|
154
|
-
test('PASS + late is_error + NO transcript evidence + non-git cwd → transcript_errors (no fallback)', async () => {
|
|
155
|
-
const tmp = makeTmpDir();
|
|
156
|
-
try {
|
|
157
|
-
const slug = '99-fix-no-evidence';
|
|
158
|
-
writeLog(tmp, slug, buildRunEvents({ includeCommitEvidence: false }));
|
|
159
|
-
const prdPath = writePrd(tmp, slug, '# Fix scheduler skip guard');
|
|
160
|
-
const nonGitCwd = fs.mkdtempSync(path.join(os.tmpdir(), 'run-verify-nongit-cwd-'));
|
|
161
|
-
try {
|
|
162
|
-
const verdict = await verifyRun({
|
|
163
|
-
runDir: tmp,
|
|
164
|
-
prdPath,
|
|
165
|
-
queueEntry: { slug, status: 'running', cwd: nonGitCwd },
|
|
166
|
-
allJobs: [],
|
|
167
|
-
committedDuringRun: false,
|
|
168
|
-
});
|
|
169
|
-
assert.equal(verdict.verdict, 'transcript_errors', `expected transcript_errors without evidence, got ${verdict.verdict}: ${verdict.reason}`);
|
|
170
|
-
assert.equal(verdict.downgradeTo, 'needs_review');
|
|
171
|
-
} finally { rmdir(nonGitCwd); }
|
|
172
|
-
} finally { rmdir(tmp); }
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
// ─── (3) git-repo cwd + evidence + committedDuringRun:false → fallback must not apply ──
|
|
176
|
-
|
|
177
|
-
test('PASS + late is_error + transcript evidence + GIT-REPO cwd + committedDuringRun:false → transcript_errors (false-PASS guard)', async () => {
|
|
178
|
-
const tmp = makeTmpDir();
|
|
179
|
-
const repo = makeTmpGitRepo();
|
|
180
|
-
try {
|
|
181
|
-
const slug = '99-fix-git-repo-cwd';
|
|
182
|
-
writeLog(tmp, slug, buildRunEvents({ includeCommitEvidence: true }));
|
|
183
|
-
const prdPath = writePrd(tmp, slug, '# Fix scheduler skip guard');
|
|
184
|
-
const verdict = await verifyRun({
|
|
185
|
-
runDir: tmp,
|
|
186
|
-
prdPath,
|
|
187
|
-
queueEntry: { slug, status: 'running', cwd: repo },
|
|
188
|
-
allJobs: [],
|
|
189
|
-
committedDuringRun: false,
|
|
190
|
-
});
|
|
191
|
-
assert.equal(verdict.verdict, 'transcript_errors', `fallback must not apply when git ancestry is observable, got ${verdict.verdict}: ${verdict.reason}`);
|
|
192
|
-
assert.equal(verdict.downgradeTo, 'needs_review');
|
|
193
|
-
} finally { rmdir(tmp); rmdir(repo); }
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
// ─── (4) PASS + transcript evidence + non-git cwd must not be pass_no_commit ──
|
|
197
|
-
|
|
198
|
-
test('PASS (no error) + transcript evidence + non-git cwd → clean, not pass_no_commit', async () => {
|
|
199
|
-
const tmp = makeTmpDir();
|
|
200
|
-
try {
|
|
201
|
-
const slug = '99-fix-clean-pass';
|
|
202
|
-
const events = [
|
|
203
|
-
{ type: 'assistant', message: { role: 'assistant', content: [
|
|
204
|
-
{ type: 'tool_use', id: 't0', name: 'Bash', input: { description: 'run tests' } }] } },
|
|
205
|
-
{ type: 'user', message: { role: 'user', content: [
|
|
206
|
-
{ type: 'tool_result', tool_use_id: 't0', content: '535 passed', is_error: false }] } },
|
|
207
|
-
{ type: 'system', subtype: 'vcs_state_changed', kind: 'commit', cwd: '/tmp' },
|
|
208
|
-
{ type: 'result', subtype: 'success', result: 'All acceptance criteria verified.\nSCHEDULER_VERDICT: PASS' },
|
|
209
|
-
];
|
|
210
|
-
writeLog(tmp, slug, events);
|
|
211
|
-
const prdPath = writePrd(tmp, slug, '# Fix scheduler skip guard');
|
|
212
|
-
const nonGitCwd = fs.mkdtempSync(path.join(os.tmpdir(), 'run-verify-nongit-cwd-'));
|
|
213
|
-
try {
|
|
214
|
-
const verdict = await verifyRun({
|
|
215
|
-
runDir: tmp,
|
|
216
|
-
prdPath,
|
|
217
|
-
queueEntry: { slug, status: 'running', cwd: nonGitCwd },
|
|
218
|
-
allJobs: [],
|
|
219
|
-
committedDuringRun: false,
|
|
220
|
-
});
|
|
221
|
-
assert.equal(verdict.verdict, 'clean', `expected clean, got ${verdict.verdict}: ${verdict.reason}`);
|
|
222
|
-
assert.notEqual(verdict.verdict, 'pass_no_commit');
|
|
223
|
-
} finally { rmdir(nonGitCwd); }
|
|
224
|
-
} finally { rmdir(tmp); }
|
|
225
|
-
});
|