patchwarden 1.5.0 → 1.6.1
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/PatchWarden.cmd +32 -2
- package/README.en.md +194 -26
- package/README.md +160 -22
- package/dist/assessments/agentAssessor.d.ts +1 -1
- package/dist/assessments/agentAssessor.js +24 -15
- package/dist/assessments/assessmentStore.d.ts +1 -1
- package/dist/assessments/assessmentStore.js +44 -36
- package/dist/assessments/confirmCli.js +5 -4
- package/dist/config.d.ts +22 -0
- package/dist/config.js +98 -11
- package/dist/control/fileManager.d.ts +2 -0
- package/dist/control/fileManager.js +39 -0
- package/dist/control/middleware/auth.d.ts +16 -0
- package/dist/control/middleware/auth.js +17 -0
- package/dist/control/middleware/static.d.ts +3 -0
- package/dist/control/middleware/static.js +78 -0
- package/dist/control/routeTable.d.ts +24 -0
- package/dist/control/routeTable.js +263 -0
- package/dist/control/routes/audit.d.ts +15 -0
- package/dist/control/routes/audit.js +287 -0
- package/dist/control/routes/evidence.d.ts +4 -0
- package/dist/control/routes/evidence.js +96 -0
- package/dist/control/routes/lineage.d.ts +3 -0
- package/dist/control/routes/lineage.js +71 -0
- package/dist/control/routes/policy.d.ts +3 -0
- package/dist/control/routes/policy.js +81 -0
- package/dist/control/routes/process.d.ts +12 -0
- package/dist/control/routes/process.js +487 -0
- package/dist/control/routes/sessions.d.ts +30 -0
- package/dist/control/routes/sessions.js +287 -0
- package/dist/control/routes/status.d.ts +51 -0
- package/dist/control/routes/status.js +307 -0
- package/dist/control/routes/taskActions.d.ts +21 -0
- package/dist/control/routes/taskActions.js +197 -0
- package/dist/control/routes/tasks.d.ts +24 -0
- package/dist/control/routes/tasks.js +309 -0
- package/dist/control/routes/workspace.d.ts +15 -0
- package/dist/control/routes/workspace.js +220 -0
- package/dist/control/runtime.d.ts +92 -0
- package/dist/control/runtime.js +425 -0
- package/dist/control/server.d.ts +13 -0
- package/dist/control/server.js +150 -0
- package/dist/control/shared.d.ts +59 -0
- package/dist/control/shared.js +341 -0
- package/dist/controlCenter.d.ts +6 -0
- package/dist/controlCenter.js +7 -2197
- package/dist/direct/directAudit.js +234 -225
- package/dist/direct/directGuards.d.ts +2 -1
- package/dist/direct/directGuards.js +72 -37
- package/dist/direct/directPatch.d.ts +6 -1
- package/dist/direct/directPatch.js +55 -8
- package/dist/direct/directSessionStore.d.ts +16 -6
- package/dist/direct/directSessionStore.js +127 -35
- package/dist/direct/directVerification.js +8 -16
- package/dist/doctor.d.ts +18 -1
- package/dist/doctor.js +614 -373
- package/dist/goal/acceptanceEngine.d.ts +1 -1
- package/dist/goal/goalProgress.js +75 -69
- package/dist/goal/goalReport.d.ts +54 -0
- package/dist/goal/goalReport.js +197 -0
- package/dist/goal/goalStatus.d.ts +8 -0
- package/dist/goal/goalStatus.js +10 -3
- package/dist/goal/goalStore.d.ts +9 -2
- package/dist/goal/goalStore.js +152 -45
- package/dist/goal/handoffExport.js +6 -6
- package/dist/goal/specKitImport.d.ts +63 -0
- package/dist/goal/specKitImport.js +221 -0
- package/dist/goal/subgoalSync.js +13 -10
- package/dist/goal/worktreeManager.d.ts +2 -0
- package/dist/goal/worktreeManager.js +209 -136
- package/dist/httpServer.js +126 -44
- package/dist/index.js +7 -4
- package/dist/logging.d.ts +7 -1
- package/dist/logging.js +13 -3
- package/dist/policy/projectPolicy.js +5 -2
- package/dist/release/releaseGate.d.ts +1 -1
- package/dist/release/releaseGate.js +78 -25
- package/dist/runner/agentInvocation.d.ts +14 -0
- package/dist/runner/agentInvocation.js +96 -4
- package/dist/runner/changeCapture.d.ts +14 -6
- package/dist/runner/changeCapture.js +287 -81
- package/dist/runner/cli.js +7 -6
- package/dist/runner/postTaskCleanup.js +60 -7
- package/dist/runner/processSecurity.d.ts +56 -0
- package/dist/runner/processSecurity.js +373 -0
- package/dist/runner/runTask.d.ts +1 -1
- package/dist/runner/runTask.js +339 -287
- package/dist/runner/simpleProcess.d.ts +3 -0
- package/dist/runner/simpleProcess.js +52 -38
- package/dist/{taskProgress.d.ts → runner/taskProgress.d.ts} +1 -1
- package/dist/{taskProgress.js → runner/taskProgress.js} +2 -2
- package/dist/{taskRuntime.d.ts → runner/taskRuntime.d.ts} +1 -1
- package/dist/{taskRuntime.js → runner/taskRuntime.js} +3 -2
- package/dist/runner/taskStatusStore.d.ts +11 -0
- package/dist/runner/taskStatusStore.js +24 -0
- package/dist/runner/watch.d.ts +14 -1
- package/dist/runner/watch.js +265 -54
- package/dist/security/contentRedaction.d.ts +6 -0
- package/dist/security/contentRedaction.js +24 -2
- package/dist/security/discoveryTokenStore.d.ts +3 -2
- package/dist/security/discoveryTokenStore.js +17 -2
- package/dist/security/loopbackHost.d.ts +2 -0
- package/dist/security/loopbackHost.js +16 -0
- package/dist/security/pathGuard.js +32 -17
- package/dist/security/planGuard.js +2 -1
- package/dist/security/runtimeGuard.js +9 -6
- package/dist/security/secretComparison.d.ts +3 -0
- package/dist/security/secretComparison.js +11 -0
- package/dist/security/sensitiveGuard.d.ts +5 -0
- package/dist/security/sensitiveGuard.js +27 -8
- package/dist/security/toolInvocationGuard.d.ts +2 -2
- package/dist/security/toolInvocationGuard.js +1 -1
- package/dist/security/workspaceRootGuard.d.ts +8 -0
- package/dist/security/workspaceRootGuard.js +47 -0
- package/dist/smoke-test.js +280 -273
- package/dist/tools/catalog/index.d.ts +4 -0
- package/dist/tools/catalog/index.js +4 -0
- package/dist/tools/{toolCatalog.js → catalog/toolCatalog.js} +3 -12
- package/dist/tools/{toolRegistry.d.ts → catalog/toolRegistry.d.ts} +3 -3
- package/dist/tools/{toolRegistry.js → catalog/toolRegistry.js} +28 -15
- package/dist/tools/definitions/toolDefs.d.ts +18 -0
- package/dist/tools/definitions/toolDefs.js +1177 -0
- package/dist/tools/{auditSession.d.ts → diagnostics/auditSession.d.ts} +1 -1
- package/dist/tools/{auditSession.js → diagnostics/auditSession.js} +2 -2
- package/dist/tools/{auditTask.d.ts → diagnostics/auditTask.d.ts} +8 -63
- package/dist/tools/{auditTask.js → diagnostics/auditTask.js} +111 -37
- package/dist/tools/{healthCheck.d.ts → diagnostics/healthCheck.d.ts} +6 -6
- package/dist/tools/{healthCheck.js → diagnostics/healthCheck.js} +10 -10
- package/dist/tools/diagnostics/index.d.ts +6 -0
- package/dist/tools/diagnostics/index.js +6 -0
- package/dist/tools/{safeStatus.d.ts → diagnostics/safeStatus.d.ts} +3 -3
- package/dist/tools/{safeStatus.js → diagnostics/safeStatus.js} +6 -6
- package/dist/tools/{safeViews.d.ts → diagnostics/safeViews.d.ts} +14 -10
- package/dist/tools/{safeViews.js → diagnostics/safeViews.js} +25 -15
- package/dist/tools/{schemaDriftCheck.d.ts → diagnostics/schemaDriftCheck.d.ts} +1 -1
- package/dist/tools/{schemaDriftCheck.js → diagnostics/schemaDriftCheck.js} +2 -2
- package/dist/tools/{createDirectSession.d.ts → direct/createDirectSession.d.ts} +1 -1
- package/dist/tools/{createDirectSession.js → direct/createDirectSession.js} +8 -8
- package/dist/tools/{finalizeDirectSession.d.ts → direct/finalizeDirectSession.d.ts} +2 -2
- package/dist/tools/direct/finalizeDirectSession.js +86 -0
- package/dist/tools/direct/index.d.ts +3 -0
- package/dist/tools/direct/index.js +3 -0
- package/dist/tools/{runDirectVerificationBundle.js → direct/runDirectVerificationBundle.js} +2 -2
- package/dist/tools/{discoverTools.d.ts → discovery/discoverTools.d.ts} +2 -2
- package/dist/tools/{discoverTools.js → discovery/discoverTools.js} +5 -5
- package/dist/tools/{explainTool.d.ts → discovery/explainTool.d.ts} +2 -2
- package/dist/tools/{explainTool.js → discovery/explainTool.js} +2 -2
- package/dist/tools/discovery/index.d.ts +3 -0
- package/dist/tools/discovery/index.js +3 -0
- package/dist/tools/{invokeDiscoveredTool.d.ts → discovery/invokeDiscoveredTool.d.ts} +2 -2
- package/dist/tools/{invokeDiscoveredTool.js → discovery/invokeDiscoveredTool.js} +5 -5
- package/dist/tools/dispatch/coreDispatch.d.ts +9 -0
- package/dist/tools/dispatch/coreDispatch.js +283 -0
- package/dist/tools/dispatch/diagnosticDispatch.d.ts +12 -0
- package/dist/tools/dispatch/diagnosticDispatch.js +80 -0
- package/dist/tools/dispatch/directDispatch.d.ts +8 -0
- package/dist/tools/dispatch/directDispatch.js +116 -0
- package/dist/tools/dispatch/goalDispatch.d.ts +8 -0
- package/dist/tools/dispatch/goalDispatch.js +92 -0
- package/dist/tools/dispatch/releaseDispatch.d.ts +8 -0
- package/dist/tools/dispatch/releaseDispatch.js +46 -0
- package/dist/tools/dispatch/types.d.ts +23 -0
- package/dist/tools/dispatch/types.js +15 -0
- package/dist/tools/dispatch/validation.d.ts +7 -0
- package/dist/tools/dispatch/validation.js +71 -0
- package/dist/tools/{getPlan.js → goals/getPlan.js} +4 -4
- package/dist/tools/{goalSubgoalTask.d.ts → goals/goalSubgoalTask.d.ts} +2 -2
- package/dist/tools/goals/goalSubgoalTask.js +118 -0
- package/dist/tools/goals/index.d.ts +3 -0
- package/dist/tools/goals/index.js +3 -0
- package/dist/tools/{savePlan.js → goals/savePlan.js} +28 -8
- package/dist/tools/registry.d.ts +10 -14
- package/dist/tools/registry.js +47 -1651
- package/dist/tools/{checkReleaseGate.d.ts → release/checkReleaseGate.d.ts} +1 -1
- package/dist/tools/{checkReleaseGate.js → release/checkReleaseGate.js} +3 -3
- package/dist/tools/release/index.d.ts +2 -0
- package/dist/tools/release/index.js +2 -0
- package/dist/tools/{releaseMode.d.ts → release/releaseMode.d.ts} +2 -2
- package/dist/tools/{releaseMode.js → release/releaseMode.js} +46 -26
- package/dist/tools/tasks/cancelTask.d.ts +11 -0
- package/dist/tools/tasks/cancelTask.js +85 -0
- package/dist/tools/{createTask.d.ts → tasks/createTask.d.ts} +12 -4
- package/dist/tools/{createTask.js → tasks/createTask.js} +46 -31
- package/dist/tools/{diagnoseTask.d.ts → tasks/diagnoseTask.d.ts} +1 -1
- package/dist/tools/{diagnoseTask.js → tasks/diagnoseTask.js} +8 -8
- package/dist/tools/{evidencePack.d.ts → tasks/evidencePack.d.ts} +6 -0
- package/dist/tools/tasks/evidencePack.js +387 -0
- package/dist/tools/{getTaskFile.js → tasks/getTaskFile.js} +4 -4
- package/dist/tools/{getTaskStatus.d.ts → tasks/getTaskStatus.d.ts} +6 -1
- package/dist/tools/{getTaskStatus.js → tasks/getTaskStatus.js} +5 -5
- package/dist/tools/{getTaskStdoutTail.js → tasks/getTaskStdoutTail.js} +13 -11
- package/dist/tools/{getTaskSummary.js → tasks/getTaskSummary.js} +33 -26
- package/dist/tools/tasks/index.d.ts +18 -0
- package/dist/tools/tasks/index.js +18 -0
- package/dist/tools/tasks/killTask.d.ts +1 -0
- package/dist/tools/{listTasks.d.ts → tasks/listTasks.d.ts} +1 -1
- package/dist/tools/{listTasks.js → tasks/listTasks.js} +3 -3
- package/dist/tools/{reconcileTasks.d.ts → tasks/reconcileTasks.d.ts} +1 -1
- package/dist/tools/{reconcileTasks.js → tasks/reconcileTasks.js} +64 -66
- package/dist/tools/{retryTask.d.ts → tasks/retryTask.d.ts} +2 -2
- package/dist/tools/tasks/retryTask.js +60 -0
- package/dist/tools/{runTaskLoop.d.ts → tasks/runTaskLoop.d.ts} +6 -6
- package/dist/tools/{runTaskLoop.js → tasks/runTaskLoop.js} +59 -31
- package/dist/tools/tasks/runVerification.js +38 -0
- package/dist/tools/{taskLineage.js → tasks/taskLineage.js} +8 -7
- package/dist/tools/{taskOutputs.js → tasks/taskOutputs.js} +17 -16
- package/dist/tools/{androidDoctor.js → workspace/androidDoctor.js} +16 -10
- package/dist/tools/{applyPatch.d.ts → workspace/applyPatch.d.ts} +1 -1
- package/dist/tools/workspace/applyPatch.js +53 -0
- package/dist/tools/{discardWorktree.js → workspace/discardWorktree.js} +3 -3
- package/dist/tools/workspace/index.d.ts +10 -0
- package/dist/tools/workspace/index.js +10 -0
- package/dist/tools/{listAgents.d.ts → workspace/listAgents.d.ts} +5 -0
- package/dist/tools/{listAgents.js → workspace/listAgents.js} +8 -4
- package/dist/tools/{listWorkspace.js → workspace/listWorkspace.js} +3 -3
- package/dist/tools/{mergeWorktree.js → workspace/mergeWorktree.js} +3 -3
- package/dist/tools/{readWorkspaceFile.js → workspace/readWorkspaceFile.js} +8 -8
- package/dist/tools/{recommendAgentForTask.js → workspace/recommendAgentForTask.js} +3 -3
- package/dist/tools/{searchWorkspace.js → workspace/searchWorkspace.js} +5 -5
- package/dist/tools/{syncFile.d.ts → workspace/syncFile.d.ts} +1 -1
- package/dist/tools/workspace/syncFile.js +134 -0
- package/dist/utils/atomicFile.d.ts +7 -0
- package/dist/utils/atomicFile.js +48 -0
- package/dist/utils/boundedFile.d.ts +8 -0
- package/dist/utils/boundedFile.js +93 -0
- package/dist/utils/lockedJsonFile.d.ts +15 -0
- package/dist/utils/lockedJsonFile.js +224 -0
- package/dist/utils/platform.d.ts +11 -0
- package/dist/utils/platform.js +26 -0
- package/dist/utils/stableJson.d.ts +2 -0
- package/dist/utils/stableJson.js +12 -0
- package/dist/version.d.ts +3 -2
- package/dist/version.js +3 -2
- package/dist/watcherStatus.d.ts +2 -2
- package/dist/watcherStatus.js +18 -0
- package/docs/CODE_WIKI.md +1648 -0
- package/docs/agentseal-integration.md +150 -0
- package/docs/architecture.md +23 -0
- package/docs/assets/patchwarden-desktop-onboarding.png +0 -0
- package/docs/assets/patchwarden-oss-demo.gif +0 -0
- package/docs/control-center/README.md +4 -4
- package/docs/dashboard-overview.md +86 -0
- package/docs/demo.md +8 -0
- package/docs/desktop-app.md +175 -0
- package/docs/direct-session-workflow.md +98 -0
- package/docs/evidence-pack-schema.md +215 -0
- package/docs/lineage-evidence-pack-workflow.md +127 -0
- package/docs/mcp-inspector-testing.md +200 -0
- package/docs/open-source-application.md +168 -0
- package/docs/opencode-worker.md +151 -0
- package/docs/openhands-worker.md +181 -0
- package/docs/release-checklist.md +1 -1
- package/docs/release-evidence.md +82 -0
- package/docs/spec-kit-integration.md +131 -0
- package/docs/task-safe-review-workflow.md +98 -0
- package/docs/threat-model.md +97 -0
- package/docs/user-feedback.md +40 -0
- package/docs/why-patchwarden.md +110 -0
- package/examples/config.example.json +4 -2
- package/package.json +28 -11
- package/scripts/README.md +15 -6
- package/scripts/build.js +11 -0
- package/scripts/checks/brand-check.js +3 -0
- package/scripts/checks/build-output-check.js +37 -0
- package/scripts/checks/control-center-smoke.js +447 -6
- package/scripts/checks/control-smoke.js +19 -8
- package/scripts/checks/http-mcp-smoke.js +82 -4
- package/scripts/checks/lifecycle-smoke.js +39 -33
- package/scripts/checks/mcp-manifest-check.js +1 -1
- package/scripts/checks/mcp-smoke.js +30 -4
- package/scripts/checks/package-manifest-check.js +20 -7
- package/scripts/checks/unit-tests.js +3 -5
- package/scripts/checks/watcher-supervisor-smoke.js +9 -0
- package/scripts/control/get-patchwarden-health.ps1 +1 -1
- package/scripts/control/manage-patchwarden.ps1 +69 -4
- package/scripts/control/provision-patchwarden-tunnel.ps1 +127 -0
- package/scripts/control/run-background-supervisor.ps1 +41 -0
- package/scripts/control/start-patchwarden-tunnel.ps1 +126 -32
- package/scripts/generate-demo-gif.py +320 -0
- package/{PatchWarden-Control-Tray.cmd → scripts/launchers/PatchWarden-Control-Tray.cmd} +3 -3
- package/scripts/launchers/PatchWarden-Control.cmd +6 -0
- package/{PatchWarden-Desktop.cmd → scripts/launchers/PatchWarden-Desktop.cmd} +2 -2
- package/scripts/launchers/Restart-PatchWarden-Control.cmd +6 -0
- package/{Stop-PatchWarden.cmd → scripts/launchers/Stop-PatchWarden.cmd} +2 -2
- package/scripts/lib/clean-generated-output.js +11 -0
- package/scripts/lib/file-discovery.js +12 -0
- package/scripts/release/desktop-preflight.js +211 -0
- package/scripts/release/pack-clean.js +59 -14
- package/src/assessments/agentAssessor.ts +29 -15
- package/src/assessments/assessmentStore.ts +55 -43
- package/src/assessments/confirmCli.ts +5 -4
- package/src/config.ts +105 -11
- package/src/control/fileManager.ts +40 -0
- package/src/control/middleware/auth.ts +35 -0
- package/src/control/middleware/static.ts +84 -0
- package/src/control/routeTable.ts +301 -0
- package/src/control/routes/audit.ts +329 -0
- package/src/control/routes/evidence.ts +107 -0
- package/src/control/routes/lineage.ts +92 -0
- package/src/control/routes/policy.ts +81 -0
- package/src/control/routes/process.ts +505 -0
- package/src/control/routes/sessions.ts +314 -0
- package/src/control/routes/status.ts +405 -0
- package/src/control/routes/taskActions.ts +214 -0
- package/src/control/routes/tasks.ts +331 -0
- package/src/control/routes/workspace.ts +234 -0
- package/src/control/runtime.ts +508 -0
- package/src/control/server.ts +165 -0
- package/src/control/shared.ts +360 -0
- package/src/controlCenter.ts +7 -2347
- package/src/direct/directAudit.ts +17 -9
- package/src/direct/directGuards.ts +100 -51
- package/src/direct/directPatch.ts +95 -8
- package/src/direct/directSessionStore.ts +211 -55
- package/src/direct/directVerification.ts +9 -23
- package/src/doctor.ts +766 -492
- package/src/goal/acceptanceEngine.ts +1 -1
- package/src/goal/goalProgress.ts +17 -13
- package/src/goal/goalReport.ts +263 -0
- package/src/goal/goalStatus.ts +25 -3
- package/src/goal/goalStore.ts +241 -54
- package/src/goal/handoffExport.ts +6 -6
- package/src/goal/specKitImport.ts +355 -0
- package/src/goal/subgoalSync.ts +15 -10
- package/src/goal/worktreeManager.ts +139 -22
- package/src/httpServer.ts +130 -44
- package/src/index.ts +7 -4
- package/src/logging.ts +20 -4
- package/src/policy/projectPolicy.ts +5 -2
- package/src/release/releaseGate.ts +74 -27
- package/src/runner/agentInvocation.ts +126 -4
- package/src/runner/changeCapture.ts +342 -80
- package/src/runner/cli.ts +7 -6
- package/src/runner/postTaskCleanup.ts +55 -7
- package/src/runner/processSecurity.ts +433 -0
- package/src/runner/runTask.ts +441 -292
- package/src/runner/simpleProcess.ts +68 -33
- package/src/{taskProgress.ts → runner/taskProgress.ts} +3 -3
- package/src/{taskRuntime.ts → runner/taskRuntime.ts} +4 -3
- package/src/runner/taskStatusStore.ts +54 -0
- package/src/runner/watch.ts +290 -57
- package/src/security/contentRedaction.ts +31 -2
- package/src/security/discoveryTokenStore.ts +18 -4
- package/src/security/loopbackHost.ts +19 -0
- package/src/security/pathGuard.ts +35 -16
- package/src/security/planGuard.ts +2 -1
- package/src/security/runtimeGuard.ts +9 -6
- package/src/security/secretComparison.ts +13 -0
- package/src/security/sensitiveGuard.ts +27 -8
- package/src/security/toolInvocationGuard.ts +2 -2
- package/src/security/workspaceRootGuard.ts +53 -0
- package/src/smoke-test.ts +276 -273
- package/src/tools/catalog/index.ts +4 -0
- package/src/tools/{toolCatalog.ts → catalog/toolCatalog.ts} +3 -12
- package/src/tools/{toolRegistry.ts → catalog/toolRegistry.ts} +29 -16
- package/src/tools/definitions/toolDefs.ts +1264 -0
- package/src/tools/{auditSession.ts → diagnostics/auditSession.ts} +2 -2
- package/src/tools/{auditTask.ts → diagnostics/auditTask.ts} +196 -89
- package/src/tools/{healthCheck.ts → diagnostics/healthCheck.ts} +11 -11
- package/src/tools/diagnostics/index.ts +6 -0
- package/src/tools/{safeStatus.ts → diagnostics/safeStatus.ts} +7 -7
- package/src/tools/{safeViews.ts → diagnostics/safeViews.ts} +29 -19
- package/src/tools/{schemaDriftCheck.ts → diagnostics/schemaDriftCheck.ts} +3 -3
- package/src/tools/{createDirectSession.ts → direct/createDirectSession.ts} +9 -9
- package/src/tools/{finalizeDirectSession.ts → direct/finalizeDirectSession.ts} +11 -9
- package/src/tools/direct/index.ts +3 -0
- package/src/tools/{runDirectVerificationBundle.ts → direct/runDirectVerificationBundle.ts} +2 -2
- package/src/tools/{discoverTools.ts → discovery/discoverTools.ts} +6 -6
- package/src/tools/{explainTool.ts → discovery/explainTool.ts} +3 -3
- package/src/tools/discovery/index.ts +3 -0
- package/src/tools/{invokeDiscoveredTool.ts → discovery/invokeDiscoveredTool.ts} +7 -7
- package/src/tools/dispatch/coreDispatch.ts +379 -0
- package/src/tools/dispatch/diagnosticDispatch.ts +106 -0
- package/src/tools/dispatch/directDispatch.ts +168 -0
- package/src/tools/dispatch/goalDispatch.ts +128 -0
- package/src/tools/dispatch/releaseDispatch.ts +66 -0
- package/src/tools/dispatch/types.ts +24 -0
- package/src/tools/dispatch/validation.ts +78 -0
- package/src/tools/{getPlan.ts → goals/getPlan.ts} +4 -4
- package/src/tools/{goalSubgoalTask.ts → goals/goalSubgoalTask.ts} +43 -28
- package/src/tools/goals/index.ts +3 -0
- package/src/tools/{savePlan.ts → goals/savePlan.ts} +38 -8
- package/src/tools/registry.ts +54 -1858
- package/src/tools/{checkReleaseGate.ts → release/checkReleaseGate.ts} +3 -3
- package/src/tools/release/index.ts +2 -0
- package/src/tools/{releaseMode.ts → release/releaseMode.ts} +42 -24
- package/src/tools/tasks/cancelTask.ts +109 -0
- package/src/tools/{createTask.ts → tasks/createTask.ts} +56 -33
- package/src/tools/{diagnoseTask.ts → tasks/diagnoseTask.ts} +8 -8
- package/src/tools/tasks/evidencePack.ts +504 -0
- package/src/tools/{getTaskFile.ts → tasks/getTaskFile.ts} +4 -4
- package/src/tools/{getTaskStatus.ts → tasks/getTaskStatus.ts} +7 -5
- package/src/tools/{getTaskStdoutTail.ts → tasks/getTaskStdoutTail.ts} +13 -11
- package/src/tools/{getTaskSummary.ts → tasks/getTaskSummary.ts} +44 -33
- package/src/tools/tasks/index.ts +18 -0
- package/src/tools/{listTasks.ts → tasks/listTasks.ts} +4 -4
- package/src/tools/{reconcileTasks.ts → tasks/reconcileTasks.ts} +68 -66
- package/src/tools/tasks/retryTask.ts +69 -0
- package/src/tools/{runTaskLoop.ts → tasks/runTaskLoop.ts} +70 -35
- package/src/tools/{runVerification.ts → tasks/runVerification.ts} +6 -3
- package/src/tools/{taskLineage.ts → tasks/taskLineage.ts} +8 -7
- package/src/tools/{taskOutputs.ts → tasks/taskOutputs.ts} +27 -20
- package/src/tools/{androidDoctor.ts → workspace/androidDoctor.ts} +15 -10
- package/src/tools/{applyPatch.ts → workspace/applyPatch.ts} +38 -16
- package/src/tools/{discardWorktree.ts → workspace/discardWorktree.ts} +3 -3
- package/src/tools/workspace/index.ts +10 -0
- package/src/tools/{listAgents.ts → workspace/listAgents.ts} +11 -4
- package/src/tools/{listWorkspace.ts → workspace/listWorkspace.ts} +3 -3
- package/src/tools/{mergeWorktree.ts → workspace/mergeWorktree.ts} +3 -3
- package/src/tools/{readWorkspaceFile.ts → workspace/readWorkspaceFile.ts} +8 -8
- package/src/tools/{recommendAgentForTask.ts → workspace/recommendAgentForTask.ts} +3 -3
- package/src/tools/{searchWorkspace.ts → workspace/searchWorkspace.ts} +5 -5
- package/src/tools/workspace/syncFile.ts +292 -0
- package/src/utils/atomicFile.ts +58 -0
- package/src/utils/boundedFile.ts +116 -0
- package/src/utils/lockedJsonFile.ts +251 -0
- package/src/utils/platform.ts +31 -0
- package/src/utils/stableJson.ts +12 -0
- package/src/version.ts +3 -2
- package/src/watcherStatus.ts +19 -1
- package/ui/desktop-bootstrap.js +11 -0
- package/ui/desktop-bridge.js +36 -0
- package/ui/desktop.css +160 -0
- package/ui/getting-started.js +93 -0
- package/ui/i18n.js +484 -0
- package/ui/log-parser.js +30 -0
- package/ui/pages/audit.html +204 -3
- package/ui/pages/dashboard.html +937 -79
- package/ui/pages/direct-sessions.html +609 -60
- package/ui/pages/getting-started.html +43 -0
- package/ui/pages/logs.html +105 -22
- package/ui/pages/settings.html +101 -0
- package/ui/pages/task-detail.html +468 -438
- package/ui/pages/tasks.html +648 -65
- package/ui/pages/workspace.html +38 -1
- package/ui/settings.js +245 -0
- package/PatchWarden-Control.cmd +0 -6
- package/Restart-PatchWarden-Control.cmd +0 -6
- package/dist/test/unit/acceptance-engine.test.d.ts +0 -1
- package/dist/test/unit/acceptance-engine.test.js +0 -228
- package/dist/test/unit/agent-router.test.d.ts +0 -1
- package/dist/test/unit/agent-router.test.js +0 -287
- package/dist/test/unit/android-doctor.test.d.ts +0 -1
- package/dist/test/unit/android-doctor.test.js +0 -118
- package/dist/test/unit/audit-checks.test.d.ts +0 -1
- package/dist/test/unit/audit-checks.test.js +0 -350
- package/dist/test/unit/chinese-path.test.d.ts +0 -1
- package/dist/test/unit/chinese-path.test.js +0 -91
- package/dist/test/unit/command-guard.test.d.ts +0 -1
- package/dist/test/unit/command-guard.test.js +0 -160
- package/dist/test/unit/diagnose-task.test.d.ts +0 -1
- package/dist/test/unit/diagnose-task.test.js +0 -457
- package/dist/test/unit/direct-guards.test.d.ts +0 -1
- package/dist/test/unit/direct-guards.test.js +0 -213
- package/dist/test/unit/discovery-token-store.test.d.ts +0 -1
- package/dist/test/unit/discovery-token-store.test.js +0 -139
- package/dist/test/unit/evidence-pack.test.d.ts +0 -1
- package/dist/test/unit/evidence-pack.test.js +0 -130
- package/dist/test/unit/goal-graph.test.d.ts +0 -1
- package/dist/test/unit/goal-graph.test.js +0 -298
- package/dist/test/unit/goal-progress.test.d.ts +0 -1
- package/dist/test/unit/goal-progress.test.js +0 -381
- package/dist/test/unit/goal-status.test.d.ts +0 -1
- package/dist/test/unit/goal-status.test.js +0 -215
- package/dist/test/unit/goal-store.test.d.ts +0 -1
- package/dist/test/unit/goal-store.test.js +0 -253
- package/dist/test/unit/goal-subgoal-task.test.d.ts +0 -1
- package/dist/test/unit/goal-subgoal-task.test.js +0 -55
- package/dist/test/unit/goal-tools-registry.test.d.ts +0 -1
- package/dist/test/unit/goal-tools-registry.test.js +0 -190
- package/dist/test/unit/handoff-export.test.d.ts +0 -1
- package/dist/test/unit/handoff-export.test.js +0 -263
- package/dist/test/unit/invoke-discovered-tool.test.d.ts +0 -1
- package/dist/test/unit/invoke-discovered-tool.test.js +0 -167
- package/dist/test/unit/logging.test.d.ts +0 -1
- package/dist/test/unit/logging.test.js +0 -397
- package/dist/test/unit/path-guard.test.d.ts +0 -1
- package/dist/test/unit/path-guard.test.js +0 -109
- package/dist/test/unit/post-task-cleanup.test.d.ts +0 -1
- package/dist/test/unit/post-task-cleanup.test.js +0 -48
- package/dist/test/unit/project-policy-release-mode.test.d.ts +0 -1
- package/dist/test/unit/project-policy-release-mode.test.js +0 -125
- package/dist/test/unit/reconcile-tasks.test.d.ts +0 -1
- package/dist/test/unit/reconcile-tasks.test.js +0 -456
- package/dist/test/unit/release-gate.test.d.ts +0 -1
- package/dist/test/unit/release-gate.test.js +0 -242
- package/dist/test/unit/run-task-loop.test.d.ts +0 -1
- package/dist/test/unit/run-task-loop.test.js +0 -380
- package/dist/test/unit/safe-status.test.d.ts +0 -1
- package/dist/test/unit/safe-status.test.js +0 -165
- package/dist/test/unit/safe-views.test.d.ts +0 -1
- package/dist/test/unit/safe-views.test.js +0 -171
- package/dist/test/unit/schema-drift-check.test.d.ts +0 -1
- package/dist/test/unit/schema-drift-check.test.js +0 -176
- package/dist/test/unit/sensitive-guard.test.d.ts +0 -1
- package/dist/test/unit/sensitive-guard.test.js +0 -104
- package/dist/test/unit/subgoal-sync.test.d.ts +0 -1
- package/dist/test/unit/subgoal-sync.test.js +0 -183
- package/dist/test/unit/sync-file.test.d.ts +0 -1
- package/dist/test/unit/sync-file.test.js +0 -154
- package/dist/test/unit/tool-invocation-guard.test.d.ts +0 -1
- package/dist/test/unit/tool-invocation-guard.test.js +0 -432
- package/dist/test/unit/tool-usage-stats.test.d.ts +0 -1
- package/dist/test/unit/tool-usage-stats.test.js +0 -300
- package/dist/test/unit/toolSearch.test.d.ts +0 -1
- package/dist/test/unit/toolSearch.test.js +0 -571
- package/dist/test/unit/watcher-status.test.d.ts +0 -1
- package/dist/test/unit/watcher-status.test.js +0 -169
- package/dist/test/unit/worktree-manager.test.d.ts +0 -1
- package/dist/test/unit/worktree-manager.test.js +0 -176
- package/dist/tools/applyPatch.js +0 -41
- package/dist/tools/cancelTask.d.ts +0 -30
- package/dist/tools/cancelTask.js +0 -64
- package/dist/tools/evidencePack.js +0 -168
- package/dist/tools/finalizeDirectSession.js +0 -84
- package/dist/tools/goalSubgoalTask.js +0 -110
- package/dist/tools/killTask.d.ts +0 -15
- package/dist/tools/retryTask.js +0 -45
- package/dist/tools/runVerification.js +0 -36
- package/dist/tools/syncFile.js +0 -65
- package/docs/control-center/control-center-daily-driver.md +0 -211
- package/docs/control-center/control-center-mvp.md +0 -205
- package/docs/control-center/control-center-phase2.md +0 -159
- package/docs/release-v0.6.0.md +0 -71
- package/docs/release-v0.6.1.md +0 -75
- package/docs/release-v0.6.4.md +0 -45
- package/src/test/unit/acceptance-engine.test.ts +0 -261
- package/src/test/unit/agent-router.test.ts +0 -342
- package/src/test/unit/android-doctor.test.ts +0 -158
- package/src/test/unit/audit-checks.test.ts +0 -567
- package/src/test/unit/chinese-path.test.ts +0 -106
- package/src/test/unit/command-guard.test.ts +0 -221
- package/src/test/unit/diagnose-task.test.ts +0 -544
- package/src/test/unit/direct-guards.test.ts +0 -297
- package/src/test/unit/discovery-token-store.test.ts +0 -181
- package/src/test/unit/evidence-pack.test.ts +0 -142
- package/src/test/unit/goal-graph.test.ts +0 -347
- package/src/test/unit/goal-progress.test.ts +0 -538
- package/src/test/unit/goal-status.test.ts +0 -270
- package/src/test/unit/goal-store.test.ts +0 -318
- package/src/test/unit/goal-subgoal-task.test.ts +0 -72
- package/src/test/unit/goal-tools-registry.test.ts +0 -243
- package/src/test/unit/handoff-export.test.ts +0 -295
- package/src/test/unit/invoke-discovered-tool.test.ts +0 -216
- package/src/test/unit/logging.test.ts +0 -497
- package/src/test/unit/path-guard.test.ts +0 -150
- package/src/test/unit/post-task-cleanup.test.ts +0 -53
- package/src/test/unit/project-policy-release-mode.test.ts +0 -156
- package/src/test/unit/reconcile-tasks.test.ts +0 -551
- package/src/test/unit/release-gate.test.ts +0 -314
- package/src/test/unit/run-task-loop.test.ts +0 -425
- package/src/test/unit/safe-status.test.ts +0 -187
- package/src/test/unit/safe-views.test.ts +0 -184
- package/src/test/unit/schema-drift-check.test.ts +0 -260
- package/src/test/unit/sensitive-guard.test.ts +0 -124
- package/src/test/unit/subgoal-sync.test.ts +0 -236
- package/src/test/unit/sync-file.test.ts +0 -231
- package/src/test/unit/tool-invocation-guard.test.ts +0 -542
- package/src/test/unit/tool-usage-stats.test.ts +0 -384
- package/src/test/unit/toolSearch.test.ts +0 -756
- package/src/test/unit/watcher-status.test.ts +0 -190
- package/src/test/unit/worktree-manager.test.ts +0 -247
- package/src/tools/cancelTask.ts +0 -70
- package/src/tools/evidencePack.ts +0 -205
- package/src/tools/retryTask.ts +0 -53
- package/src/tools/syncFile.ts +0 -122
- /package/dist/tools/{toolCatalog.d.ts → catalog/toolCatalog.d.ts} +0 -0
- /package/dist/tools/{toolSearch.d.ts → catalog/toolSearch.d.ts} +0 -0
- /package/dist/tools/{toolSearch.js → catalog/toolSearch.js} +0 -0
- /package/dist/tools/{toolUsageStats.d.ts → catalog/toolUsageStats.d.ts} +0 -0
- /package/dist/tools/{toolUsageStats.js → catalog/toolUsageStats.js} +0 -0
- /package/dist/tools/{runDirectVerificationBundle.d.ts → direct/runDirectVerificationBundle.d.ts} +0 -0
- /package/dist/tools/{getPlan.d.ts → goals/getPlan.d.ts} +0 -0
- /package/dist/tools/{savePlan.d.ts → goals/savePlan.d.ts} +0 -0
- /package/dist/tools/{getTaskFile.d.ts → tasks/getTaskFile.d.ts} +0 -0
- /package/dist/tools/{getTaskProgress.d.ts → tasks/getTaskProgress.d.ts} +0 -0
- /package/dist/tools/{getTaskProgress.js → tasks/getTaskProgress.js} +0 -0
- /package/dist/tools/{getTaskStdoutTail.d.ts → tasks/getTaskStdoutTail.d.ts} +0 -0
- /package/dist/tools/{getTaskSummary.d.ts → tasks/getTaskSummary.d.ts} +0 -0
- /package/dist/tools/{killTask.js → tasks/killTask.js} +0 -0
- /package/dist/tools/{runVerification.d.ts → tasks/runVerification.d.ts} +0 -0
- /package/dist/tools/{taskLineage.d.ts → tasks/taskLineage.d.ts} +0 -0
- /package/dist/tools/{taskOutputs.d.ts → tasks/taskOutputs.d.ts} +0 -0
- /package/dist/tools/{waitForTask.d.ts → tasks/waitForTask.d.ts} +0 -0
- /package/dist/tools/{waitForTask.js → tasks/waitForTask.js} +0 -0
- /package/dist/tools/{androidDoctor.d.ts → workspace/androidDoctor.d.ts} +0 -0
- /package/dist/tools/{discardWorktree.d.ts → workspace/discardWorktree.d.ts} +0 -0
- /package/dist/tools/{listWorkspace.d.ts → workspace/listWorkspace.d.ts} +0 -0
- /package/dist/tools/{mergeWorktree.d.ts → workspace/mergeWorktree.d.ts} +0 -0
- /package/dist/tools/{readWorkspaceFile.d.ts → workspace/readWorkspaceFile.d.ts} +0 -0
- /package/dist/tools/{recommendAgentForTask.d.ts → workspace/recommendAgentForTask.d.ts} +0 -0
- /package/dist/tools/{searchWorkspace.d.ts → workspace/searchWorkspace.d.ts} +0 -0
- /package/src/tools/{toolSearch.ts → catalog/toolSearch.ts} +0 -0
- /package/src/tools/{toolUsageStats.ts → catalog/toolUsageStats.ts} +0 -0
- /package/src/tools/{getTaskProgress.ts → tasks/getTaskProgress.ts} +0 -0
- /package/src/tools/{killTask.ts → tasks/killTask.ts} +0 -0
- /package/src/tools/{waitForTask.ts → tasks/waitForTask.ts} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
auditDirectSession,
|
|
3
3
|
type DirectSessionAuditOutput,
|
|
4
|
-
} from "
|
|
5
|
-
import { updateDirectSession } from "
|
|
4
|
+
} from "../../direct/directAudit.js";
|
|
5
|
+
import { updateDirectSession } from "../../direct/directSessionStore.js";
|
|
6
6
|
|
|
7
7
|
// ── Types ──────────────────────────────────────────────────────────
|
|
8
8
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
|
|
3
1
|
interface AuditCheck {
|
|
4
2
|
name: string;
|
|
5
3
|
result: "pass" | "warn" | "fail";
|
|
@@ -33,13 +31,56 @@ export interface AuditTaskOutput {
|
|
|
33
31
|
manual_verification_items: string[];
|
|
34
32
|
recommended_next_actions: string[];
|
|
35
33
|
}
|
|
36
|
-
import { readFileSync, existsSync,
|
|
34
|
+
import { readFileSync, existsSync, opendirSync, statSync } from "node:fs";
|
|
37
35
|
import { join, resolve, relative, basename, sep, isAbsolute } from "node:path";
|
|
38
|
-
import { getTasksDir, getConfig } from "
|
|
39
|
-
import { guardReadPath, guardWorkspacePath } from "
|
|
40
|
-
import { guardSensitivePath, isSensitivePath } from "
|
|
41
|
-
import { evaluateAcceptance } from "
|
|
42
|
-
import { renderAcceptanceMarkdown } from "
|
|
36
|
+
import { getTasksDir, getConfig } from "../../config.js";
|
|
37
|
+
import { guardReadPath, guardWorkspacePath } from "../../security/pathGuard.js";
|
|
38
|
+
import { guardSensitivePath, isSensitivePath } from "../../security/sensitiveGuard.js";
|
|
39
|
+
import { evaluateAcceptance } from "../../goal/acceptanceEngine.js";
|
|
40
|
+
import { renderAcceptanceMarkdown } from "../../goal/acceptanceTemplate.js";
|
|
41
|
+
import type { ChangedFile } from "../../runner/changeCapture.js";
|
|
42
|
+
import { atomicWriteFileSync } from "../../utils/atomicFile.js";
|
|
43
|
+
import { mutateTaskStatus } from "../../runner/taskStatusStore.js";
|
|
44
|
+
import {
|
|
45
|
+
readTextFilePrefixSync,
|
|
46
|
+
readTextFileTailLinesSync,
|
|
47
|
+
} from "../../utils/boundedFile.js";
|
|
48
|
+
|
|
49
|
+
interface ExtractedCommand {
|
|
50
|
+
type: "npm-run" | "npm-bare" | "node" | "npx" | "python";
|
|
51
|
+
name: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface TaskStatusData {
|
|
55
|
+
status?: string;
|
|
56
|
+
resolved_repo_path?: string;
|
|
57
|
+
repo_path?: string;
|
|
58
|
+
new_out_of_scope_changes?: Array<{ path: string; change: string }>;
|
|
59
|
+
out_of_scope_changes?: Array<{ path: string; change: string }>;
|
|
60
|
+
test_command?: string;
|
|
61
|
+
verify_commands?: string[];
|
|
62
|
+
forbidden?: string[];
|
|
63
|
+
done_evidence?: string[];
|
|
64
|
+
scope?: string[];
|
|
65
|
+
verification?: string[];
|
|
66
|
+
goal?: string;
|
|
67
|
+
artifact_status?: string;
|
|
68
|
+
acceptance_status?: string;
|
|
69
|
+
updated_at?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
interface ChangedFilesEvidence {
|
|
73
|
+
changed_files?: ChangedFile[];
|
|
74
|
+
artifact_hygiene?: {
|
|
75
|
+
counts?: {
|
|
76
|
+
tracked_build_artifacts?: number | string;
|
|
77
|
+
ignored_untracked_artifacts?: number | string;
|
|
78
|
+
runtime_generated_files?: number | string;
|
|
79
|
+
suspicious_changes?: number | string;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
43
84
|
// Release claim patterns — anything that claims remote publish/release/deploy
|
|
44
85
|
const RELEASE_PATTERNS = [
|
|
45
86
|
/npm\s+package\s+version\s+published/i,
|
|
@@ -51,8 +92,12 @@ const RELEASE_PATTERNS = [
|
|
|
51
92
|
/npm\s+publish\s+completed/i,
|
|
52
93
|
/deploy(ed|ment)?\s+(to|on)\s+(npm|registry|github)/i,
|
|
53
94
|
];
|
|
54
|
-
|
|
55
|
-
|
|
95
|
+
const MAX_AUDIT_DOC_FILES = 200;
|
|
96
|
+
const MAX_AUDIT_DOC_FILE_BYTES = 512 * 1024;
|
|
97
|
+
const MAX_AUDIT_DOC_TOTAL_BYTES = 4 * 1024 * 1024;
|
|
98
|
+
const MAX_AUDIT_EVIDENCE_BYTES = 1024 * 1024;
|
|
99
|
+
function scanForReleaseClaims(text: string): string[] {
|
|
100
|
+
const found: string[] = [];
|
|
56
101
|
for (const pattern of RELEASE_PATTERNS) {
|
|
57
102
|
const match = text.match(pattern);
|
|
58
103
|
if (match)
|
|
@@ -60,24 +105,50 @@ function scanForReleaseClaims(text) {
|
|
|
60
105
|
}
|
|
61
106
|
return found;
|
|
62
107
|
}
|
|
63
|
-
function findMdFiles(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
108
|
+
function findMdFiles(
|
|
109
|
+
dir: string,
|
|
110
|
+
maxDepth = 3,
|
|
111
|
+
maxFiles = MAX_AUDIT_DOC_FILES,
|
|
112
|
+
): { files: string[]; truncated: boolean } {
|
|
113
|
+
const results: string[] = [];
|
|
114
|
+
const pending = [{ path: dir, depth: maxDepth }];
|
|
115
|
+
const maxDirectories = maxFiles * 4;
|
|
116
|
+
let visitedDirectories = 0;
|
|
117
|
+
let truncated = false;
|
|
118
|
+
while (pending.length > 0 && results.length < maxFiles && visitedDirectories < maxDirectories) {
|
|
119
|
+
const current = pending.pop()!;
|
|
120
|
+
if (!existsSync(current.path) || current.depth <= 0) continue;
|
|
121
|
+
visitedDirectories += 1;
|
|
122
|
+
let handle;
|
|
123
|
+
try {
|
|
124
|
+
handle = opendirSync(current.path);
|
|
125
|
+
while (results.length < maxFiles) {
|
|
126
|
+
const entry = handle.readSync();
|
|
127
|
+
if (!entry) break;
|
|
128
|
+
const full = join(current.path, entry.name);
|
|
129
|
+
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
130
|
+
if (pending.length < maxDirectories) pending.push({ path: full, depth: current.depth - 1 });
|
|
131
|
+
else truncated = true;
|
|
132
|
+
} else if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
|
|
133
|
+
results.push(full);
|
|
134
|
+
}
|
|
76
135
|
}
|
|
77
|
-
}
|
|
136
|
+
} catch { /* skip unreadable dirs */ }
|
|
137
|
+
finally { try { handle?.closeSync(); } catch { /* best effort */ } }
|
|
78
138
|
}
|
|
79
|
-
|
|
80
|
-
return results;
|
|
139
|
+
truncated ||= pending.length > 0 || results.length >= maxFiles || visitedDirectories >= maxDirectories;
|
|
140
|
+
return { files: results, truncated };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function readAuditEvidence(path: string): { content: string; truncated: boolean } {
|
|
144
|
+
const half = Math.floor(MAX_AUDIT_EVIDENCE_BYTES / 2);
|
|
145
|
+
const prefix = readTextFilePrefixSync(path, half);
|
|
146
|
+
if (!prefix.truncated) return { content: prefix.content, truncated: false };
|
|
147
|
+
const tail = readTextFileTailLinesSync(path, 1000, half);
|
|
148
|
+
return {
|
|
149
|
+
content: `${prefix.content}\n[...audit evidence truncated...]\n${tail}`,
|
|
150
|
+
truncated: true,
|
|
151
|
+
};
|
|
81
152
|
}
|
|
82
153
|
// ── v0.7.2: New audit checks (exported for testing) ────────────────
|
|
83
154
|
/**
|
|
@@ -86,7 +157,7 @@ function findMdFiles(dir, maxDepth = 3) {
|
|
|
86
157
|
* `*` matches a single path segment (no `/`).
|
|
87
158
|
* Path separators in the pattern are expected to be `/`.
|
|
88
159
|
*/
|
|
89
|
-
function globToRegExp(pattern) {
|
|
160
|
+
function globToRegExp(pattern: string): RegExp {
|
|
90
161
|
// Normalize backslashes to forward slashes for matching consistency.
|
|
91
162
|
const normalized = pattern.replace(/\\/g, "/");
|
|
92
163
|
let re = "^";
|
|
@@ -127,7 +198,7 @@ function globToRegExp(pattern) {
|
|
|
127
198
|
* Returns pass when changed files do not match any forbidden pattern.
|
|
128
199
|
* Returns fail when any changed file path (or old_path) matches a forbidden glob.
|
|
129
200
|
*/
|
|
130
|
-
export function checkForbiddenScope(changedFiles, forbidden) {
|
|
201
|
+
export function checkForbiddenScope(changedFiles: ChangedFile[], forbidden: string[] | null): AuditCheck | null {
|
|
131
202
|
if (!forbidden || forbidden.length === 0)
|
|
132
203
|
return null;
|
|
133
204
|
if (changedFiles.length === 0) {
|
|
@@ -161,7 +232,7 @@ export function checkForbiddenScope(changedFiles, forbidden) {
|
|
|
161
232
|
* Returns pass when all listed files exist in the task directory.
|
|
162
233
|
* Returns warn when any listed file is missing.
|
|
163
234
|
*/
|
|
164
|
-
export function checkDoneEvidenceMissing(taskDir, doneEvidence) {
|
|
235
|
+
export function checkDoneEvidenceMissing(taskDir: string, doneEvidence: string[] | null): AuditCheck | null {
|
|
165
236
|
if (!doneEvidence || doneEvidence.length === 0)
|
|
166
237
|
return null;
|
|
167
238
|
const missing = [];
|
|
@@ -189,7 +260,7 @@ const CODE_EXTENSIONS = new Set([
|
|
|
189
260
|
* Returns pass when README.md or CHANGELOG.md (basename, case-insensitive) is also changed.
|
|
190
261
|
* Returns warn when code changed but neither documentation file was updated.
|
|
191
262
|
*/
|
|
192
|
-
export function checkReadmeChangelogSync(changedFiles) {
|
|
263
|
+
export function checkReadmeChangelogSync(changedFiles: ChangedFile[]): AuditCheck | null {
|
|
193
264
|
const paths = changedFiles.map((f) => f.path);
|
|
194
265
|
const hasCodeChange = paths.some((p) => {
|
|
195
266
|
const lower = p.toLowerCase();
|
|
@@ -223,14 +294,14 @@ export function checkReadmeChangelogSync(changedFiles) {
|
|
|
223
294
|
* Returns pass when package.json parses as JSON and has non-empty name and version strings.
|
|
224
295
|
* Returns warn otherwise.
|
|
225
296
|
*/
|
|
226
|
-
export function checkPackageManifestConsistency(changedFiles, repoPathSafe) {
|
|
297
|
+
export function checkPackageManifestConsistency(changedFiles: ChangedFile[], repoPathSafe: string): AuditCheck | null {
|
|
227
298
|
const includesPackageJson = changedFiles.some((f) => basename(f.path).toLowerCase() === "package.json");
|
|
228
299
|
if (!includesPackageJson)
|
|
229
300
|
return null;
|
|
230
301
|
try {
|
|
231
302
|
const pkgPath = join(repoPathSafe, "package.json");
|
|
232
303
|
const raw = readFileSync(pkgPath, "utf-8");
|
|
233
|
-
const parsed = JSON.parse(raw);
|
|
304
|
+
const parsed = JSON.parse(raw) as { name?: unknown; version?: unknown };
|
|
234
305
|
const hasName = typeof parsed.name === "string" && parsed.name.length > 0;
|
|
235
306
|
const hasVersion = typeof parsed.version === "string" && parsed.version.length > 0;
|
|
236
307
|
if (hasName && hasVersion) {
|
|
@@ -256,7 +327,7 @@ export function checkPackageManifestConsistency(changedFiles, repoPathSafe) {
|
|
|
256
327
|
* Returns pass when no changed file path (or old_path) is sensitive.
|
|
257
328
|
* Returns fail when any changed file path is flagged by isSensitivePath.
|
|
258
329
|
*/
|
|
259
|
-
export function checkSensitivePathAccess(changedFiles) {
|
|
330
|
+
export function checkSensitivePathAccess(changedFiles: ChangedFile[]): AuditCheck | null {
|
|
260
331
|
if (changedFiles.length === 0)
|
|
261
332
|
return null;
|
|
262
333
|
const hits = [];
|
|
@@ -287,8 +358,8 @@ const HIGH_RISK_COMMAND_PATTERNS = [
|
|
|
287
358
|
/\bRemove-Item\b[\s\S]{0,80}\b-Recurse\b/i,
|
|
288
359
|
/\brm\s+-rf\b/i,
|
|
289
360
|
];
|
|
290
|
-
function extractCommands(text) {
|
|
291
|
-
const found = [];
|
|
361
|
+
function extractCommands(text: string): ExtractedCommand[] {
|
|
362
|
+
const found: ExtractedCommand[] = [];
|
|
292
363
|
const runRe = /npm(?:\.cmd)?\s+run\s+([a-zA-Z0-9:_-]+)/gi;
|
|
293
364
|
let m;
|
|
294
365
|
while ((m = runRe.exec(text)) !== null) found.push({ type: "npm-run", name: m[1] });
|
|
@@ -302,31 +373,34 @@ function extractCommands(text) {
|
|
|
302
373
|
while ((m = pythonRe.exec(text)) !== null) found.push({ type: "python", name: normalizeCommandName(m[1]) });
|
|
303
374
|
return found;
|
|
304
375
|
}
|
|
305
|
-
function normalizeCommandName(value) {
|
|
376
|
+
function normalizeCommandName(value: string): string {
|
|
306
377
|
return value.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
307
378
|
}
|
|
308
|
-
function commandKey(command) {
|
|
379
|
+
function commandKey(command: ExtractedCommand): string {
|
|
309
380
|
return command.name;
|
|
310
381
|
}
|
|
311
|
-
function readPackageScripts(repoPath) {
|
|
382
|
+
function readPackageScripts(repoPath: string | null): Record<string, string> {
|
|
312
383
|
if (!repoPath) return {};
|
|
313
384
|
const pkgJsonPath = join(repoPath, "package.json");
|
|
314
385
|
if (!existsSync(pkgJsonPath)) return {};
|
|
315
386
|
try {
|
|
316
387
|
guardSensitivePath(pkgJsonPath);
|
|
317
|
-
const parsed = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
318
|
-
|
|
319
|
-
|
|
388
|
+
const parsed = JSON.parse(readFileSync(pkgJsonPath, "utf-8")) as { scripts?: Record<string, unknown> };
|
|
389
|
+
const scripts = parsed.scripts;
|
|
390
|
+
if (!scripts || typeof scripts !== "object" || Array.isArray(scripts)) return {};
|
|
391
|
+
return Object.fromEntries(
|
|
392
|
+
Object.entries(scripts).filter(([, value]) => typeof value === "string")
|
|
393
|
+
) as Record<string, string>;
|
|
320
394
|
}
|
|
321
395
|
catch {
|
|
322
396
|
return {};
|
|
323
397
|
}
|
|
324
398
|
}
|
|
325
|
-
function buildCommandWhitelist(verifyCommands, testCommand, repoPath) {
|
|
399
|
+
function buildCommandWhitelist(verifyCommands: string[], testCommand: string | null, repoPath: string | null): { allowed: Set<string>; transitive: Set<string> } {
|
|
326
400
|
const scripts = readPackageScripts(repoPath);
|
|
327
|
-
const allowed = new Set();
|
|
328
|
-
const transitive = new Set();
|
|
329
|
-
const queue = [];
|
|
401
|
+
const allowed = new Set<string>();
|
|
402
|
+
const transitive = new Set<string>();
|
|
403
|
+
const queue: Array<{ command: ExtractedCommand; depth: number }> = [];
|
|
330
404
|
const sources = [...verifyCommands];
|
|
331
405
|
if (testCommand) sources.push(testCommand);
|
|
332
406
|
for (const src of sources) {
|
|
@@ -336,9 +410,9 @@ function buildCommandWhitelist(verifyCommands, testCommand, repoPath) {
|
|
|
336
410
|
}
|
|
337
411
|
}
|
|
338
412
|
let inspectedFiles = 0;
|
|
339
|
-
const seen = new Set();
|
|
413
|
+
const seen = new Set<string>();
|
|
340
414
|
while (queue.length > 0) {
|
|
341
|
-
const { command, depth } = queue.shift()
|
|
415
|
+
const { command, depth } = queue.shift()!;
|
|
342
416
|
if (depth > 4) continue;
|
|
343
417
|
const key = `${command.type}:${command.name}`;
|
|
344
418
|
if (seen.has(key)) continue;
|
|
@@ -365,7 +439,7 @@ function buildCommandWhitelist(verifyCommands, testCommand, repoPath) {
|
|
|
365
439
|
}
|
|
366
440
|
return { allowed, transitive };
|
|
367
441
|
}
|
|
368
|
-
function readLocalScript(repoPath, scriptPath) {
|
|
442
|
+
function readLocalScript(repoPath: string, scriptPath: string): string | null {
|
|
369
443
|
const resolvedRepo = resolve(repoPath);
|
|
370
444
|
const resolvedScript = resolve(resolvedRepo, scriptPath);
|
|
371
445
|
const rel = relative(resolvedRepo, resolvedScript);
|
|
@@ -380,17 +454,17 @@ function readLocalScript(repoPath, scriptPath) {
|
|
|
380
454
|
return null;
|
|
381
455
|
}
|
|
382
456
|
}
|
|
383
|
-
function findHighRiskCommandEvidence(text) {
|
|
384
|
-
const found = [];
|
|
457
|
+
function findHighRiskCommandEvidence(text: string): string[] {
|
|
458
|
+
const found: string[] = [];
|
|
385
459
|
for (const pattern of HIGH_RISK_COMMAND_PATTERNS) {
|
|
386
460
|
const match = text.match(pattern);
|
|
387
461
|
if (match) found.push(match[0]);
|
|
388
462
|
}
|
|
389
463
|
return [...new Set(found)];
|
|
390
464
|
}
|
|
391
|
-
export function checkUnrecordedCommandExecution(testLogContent: string | null, resultMdContent: string | null, verifyCommands: string[], testCommand: string | null, repoPath: string | null = null) {
|
|
392
|
-
const hasLog = testLogContent && testLogContent.length > 0;
|
|
393
|
-
const hasResult = resultMdContent && resultMdContent.length > 0;
|
|
465
|
+
export function checkUnrecordedCommandExecution(testLogContent: string | null, resultMdContent: string | null, verifyCommands: string[], testCommand: string | null, repoPath: string | null = null): AuditCheck | null {
|
|
466
|
+
const hasLog = !!testLogContent && testLogContent.length > 0;
|
|
467
|
+
const hasResult = !!resultMdContent && resultMdContent.length > 0;
|
|
394
468
|
if (!hasLog && !hasResult) return null;
|
|
395
469
|
const combined = `${testLogContent || ""}\n${resultMdContent || ""}`;
|
|
396
470
|
const highRisk = findHighRiskCommandEvidence(combined);
|
|
@@ -398,10 +472,10 @@ export function checkUnrecordedCommandExecution(testLogContent: string | null, r
|
|
|
398
472
|
return { name: "unrecorded_command_execution", result: "fail", detail: `High-risk command evidence: ${highRisk.join(", ")}` };
|
|
399
473
|
}
|
|
400
474
|
const whitelist = buildCommandWhitelist(verifyCommands, testCommand, repoPath);
|
|
401
|
-
const discovered = [];
|
|
402
|
-
if (hasLog) discovered.push(...extractCommands(testLogContent));
|
|
403
|
-
if (hasResult) discovered.push(...extractCommands(resultMdContent));
|
|
404
|
-
const unrecorded = new Set();
|
|
475
|
+
const discovered: ExtractedCommand[] = [];
|
|
476
|
+
if (hasLog && testLogContent) discovered.push(...extractCommands(testLogContent));
|
|
477
|
+
if (hasResult && resultMdContent) discovered.push(...extractCommands(resultMdContent));
|
|
478
|
+
const unrecorded = new Set<string>();
|
|
405
479
|
for (const cmd of discovered) {
|
|
406
480
|
if (!whitelist.allowed.has(commandKey(cmd))) unrecorded.add(commandKey(cmd));
|
|
407
481
|
}
|
|
@@ -415,7 +489,7 @@ export function checkUnrecordedCommandExecution(testLogContent: string | null, r
|
|
|
415
489
|
detail: transitive.length > 0 ? `All commands are whitelisted; transitive_verified_command: ${transitive.join(", ")}` : "All commands in whitelist.",
|
|
416
490
|
};
|
|
417
491
|
}
|
|
418
|
-
export function auditTask(taskId) {
|
|
492
|
+
export function auditTask(taskId: string): AuditTaskOutput {
|
|
419
493
|
const config = getConfig();
|
|
420
494
|
const tasksDir = getTasksDir(config);
|
|
421
495
|
const taskDir = join(tasksDir, taskId);
|
|
@@ -424,17 +498,17 @@ export function auditTask(taskId) {
|
|
|
424
498
|
if (!existsSync(statusFile)) {
|
|
425
499
|
throw new Error(`Task not found: "${taskId}"`);
|
|
426
500
|
}
|
|
427
|
-
const statusData = JSON.parse(readFileSync(statusFile, "utf-8"));
|
|
428
|
-
const checks = [];
|
|
429
|
-
const risks = [];
|
|
430
|
-
const actions = [];
|
|
431
|
-
const possibleFalsePositives = [];
|
|
432
|
-
const manualVerificationItems = [];
|
|
433
|
-
const addManualVerification = (item) => {
|
|
501
|
+
const statusData = JSON.parse(readFileSync(statusFile, "utf-8")) as TaskStatusData;
|
|
502
|
+
const checks: AuditCheck[] = [];
|
|
503
|
+
const risks: AuditRisk[] = [];
|
|
504
|
+
const actions: string[] = [];
|
|
505
|
+
const possibleFalsePositives: Array<{ check: string; reason: string }> = [];
|
|
506
|
+
const manualVerificationItems: string[] = [];
|
|
507
|
+
const addManualVerification = (item: string) => {
|
|
434
508
|
if (!manualVerificationItems.includes(item))
|
|
435
509
|
manualVerificationItems.push(item);
|
|
436
510
|
};
|
|
437
|
-
const addPossibleFalsePositive = (check, reason) => {
|
|
511
|
+
const addPossibleFalsePositive = (check: string, reason: string) => {
|
|
438
512
|
if (!possibleFalsePositives.some((item) => item.check === check && item.reason === reason)) {
|
|
439
513
|
possibleFalsePositives.push({ check, reason });
|
|
440
514
|
}
|
|
@@ -478,7 +552,7 @@ export function auditTask(taskId) {
|
|
|
478
552
|
}
|
|
479
553
|
if (existsSync(verifyJsonFile)) {
|
|
480
554
|
try {
|
|
481
|
-
const verify = JSON.parse(readFileSync(verifyJsonFile, "utf-8"));
|
|
555
|
+
const verify = JSON.parse(readFileSync(verifyJsonFile, "utf-8")) as { status?: string };
|
|
482
556
|
checks.push({
|
|
483
557
|
name: "verify_status",
|
|
484
558
|
result: verify.status === "passed" ? "pass" : verify.status === "failed" ? "fail" : "warn",
|
|
@@ -504,11 +578,11 @@ export function auditTask(taskId) {
|
|
|
504
578
|
: "No new out-of-scope changes recorded.",
|
|
505
579
|
});
|
|
506
580
|
// Extract changed_files from change evidence (used by several v0.7.2 checks).
|
|
507
|
-
let changedFiles = [];
|
|
581
|
+
let changedFiles: ChangedFile[] = [];
|
|
508
582
|
const changedFilesFile = join(taskDir, "changed-files.json");
|
|
509
583
|
if (existsSync(changedFilesFile)) {
|
|
510
584
|
try {
|
|
511
|
-
const changeEvidence = JSON.parse(readFileSync(changedFilesFile, "utf-8"));
|
|
585
|
+
const changeEvidence = JSON.parse(readFileSync(changedFilesFile, "utf-8")) as ChangedFilesEvidence;
|
|
512
586
|
if (Array.isArray(changeEvidence.changed_files)) {
|
|
513
587
|
changedFiles = changeEvidence.changed_files;
|
|
514
588
|
}
|
|
@@ -596,11 +670,11 @@ export function auditTask(taskId) {
|
|
|
596
670
|
risks.push({ severity: "high", description: "repo_path inconsistent with workspace." });
|
|
597
671
|
// ── 6. package.json scripts ──
|
|
598
672
|
const pkgJsonPath = join(repoPathSafe, "package.json");
|
|
599
|
-
let pkgScripts = [];
|
|
673
|
+
let pkgScripts: string[] = [];
|
|
600
674
|
if (existsSync(pkgJsonPath)) {
|
|
601
675
|
try {
|
|
602
676
|
guardSensitivePath(pkgJsonPath);
|
|
603
|
-
const pkgData = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
677
|
+
const pkgData = JSON.parse(readFileSync(pkgJsonPath, "utf-8")) as { scripts?: Record<string, unknown> };
|
|
604
678
|
pkgScripts = Object.keys(pkgData.scripts || {});
|
|
605
679
|
checks.push({
|
|
606
680
|
name: "package_json_scripts",
|
|
@@ -621,20 +695,35 @@ export function auditTask(taskId) {
|
|
|
621
695
|
if (existsSync(readmePath))
|
|
622
696
|
docsToScan.push(readmePath);
|
|
623
697
|
const docsDir = join(repoPathSafe, "docs");
|
|
698
|
+
let markdownEnumerationTruncated = false;
|
|
624
699
|
if (existsSync(docsDir)) {
|
|
625
|
-
|
|
700
|
+
const markdown = findMdFiles(docsDir);
|
|
701
|
+
docsToScan.push(...markdown.files);
|
|
702
|
+
markdownEnumerationTruncated = markdown.truncated;
|
|
626
703
|
}
|
|
627
704
|
// Collect all npm run references from all docs
|
|
628
|
-
const allNpmRunRefs = new Set();
|
|
629
|
-
const allReleaseClaims = [];
|
|
705
|
+
const allNpmRunRefs = new Set<string>();
|
|
706
|
+
const allReleaseClaims: string[] = [];
|
|
707
|
+
let remainingDocBytes = MAX_AUDIT_DOC_TOTAL_BYTES;
|
|
708
|
+
let documentScanTruncated = markdownEnumerationTruncated || docsToScan.length > MAX_AUDIT_DOC_FILES;
|
|
630
709
|
for (const docPath of docsToScan) {
|
|
631
|
-
|
|
710
|
+
if (remainingDocBytes <= 0) {
|
|
711
|
+
documentScanTruncated = true;
|
|
712
|
+
break;
|
|
713
|
+
}
|
|
714
|
+
let content: string;
|
|
632
715
|
try {
|
|
633
716
|
if (docPath !== resultFile) {
|
|
634
717
|
guardReadPath(docPath, config.workspaceRoot);
|
|
635
718
|
guardSensitivePath(docPath);
|
|
636
719
|
}
|
|
637
|
-
|
|
720
|
+
const bounded = readTextFilePrefixSync(
|
|
721
|
+
docPath,
|
|
722
|
+
Math.min(MAX_AUDIT_DOC_FILE_BYTES, remainingDocBytes),
|
|
723
|
+
);
|
|
724
|
+
content = bounded.content;
|
|
725
|
+
remainingDocBytes -= Buffer.byteLength(content, "utf-8");
|
|
726
|
+
documentScanTruncated ||= bounded.truncated;
|
|
638
727
|
}
|
|
639
728
|
catch {
|
|
640
729
|
continue;
|
|
@@ -651,6 +740,14 @@ export function auditTask(taskId) {
|
|
|
651
740
|
for (const c of claims)
|
|
652
741
|
allReleaseClaims.push(`[${relative(repoPathSafe, docPath) || docPath}] ${c}`);
|
|
653
742
|
}
|
|
743
|
+
if (documentScanTruncated) {
|
|
744
|
+
checks.push({
|
|
745
|
+
name: "documentation_scan_bounded",
|
|
746
|
+
result: "warn",
|
|
747
|
+
detail: `Documentation scan reached its ${MAX_AUDIT_DOC_FILES}-file or ${MAX_AUDIT_DOC_TOTAL_BYTES}-byte safety budget.`,
|
|
748
|
+
});
|
|
749
|
+
addManualVerification("Review documentation omitted by the bounded audit scan.");
|
|
750
|
+
}
|
|
654
751
|
// Cross-check npm run refs against package.json scripts
|
|
655
752
|
for (const scriptName of allNpmRunRefs) {
|
|
656
753
|
if (pkgScripts.length > 0 && !pkgScripts.includes(scriptName)) {
|
|
@@ -693,11 +790,13 @@ export function auditTask(taskId) {
|
|
|
693
790
|
addManualVerification("Verify remote npm, GitHub Release, and Git tag claims against authoritative remote services.");
|
|
694
791
|
}
|
|
695
792
|
// ── 9. test.log Exit code check ──
|
|
696
|
-
let testLogContent = null;
|
|
793
|
+
let testLogContent: string | null = null;
|
|
697
794
|
if (hasTestLog) {
|
|
698
|
-
let logContent;
|
|
795
|
+
let logContent: string;
|
|
699
796
|
try {
|
|
700
|
-
|
|
797
|
+
const evidence = readAuditEvidence(testLogFile);
|
|
798
|
+
logContent = evidence.content;
|
|
799
|
+
if (evidence.truncated) addManualVerification("test.log exceeded the audit read budget; inspect the complete local artifact.");
|
|
701
800
|
}
|
|
702
801
|
catch {
|
|
703
802
|
logContent = "";
|
|
@@ -732,10 +831,12 @@ export function auditTask(taskId) {
|
|
|
732
831
|
}
|
|
733
832
|
// ── v0.7.2: New audit checks ──
|
|
734
833
|
// Read result.md content (guarded) for the unrecorded_command_execution check.
|
|
735
|
-
let resultMdContent = null;
|
|
834
|
+
let resultMdContent: string | null = null;
|
|
736
835
|
if (hasResult) {
|
|
737
836
|
try {
|
|
738
|
-
|
|
837
|
+
const evidence = readAuditEvidence(resultFile);
|
|
838
|
+
resultMdContent = evidence.content;
|
|
839
|
+
if (evidence.truncated) addManualVerification("result.md exceeded the audit read budget; inspect the complete local artifact.");
|
|
739
840
|
}
|
|
740
841
|
catch {
|
|
741
842
|
resultMdContent = null;
|
|
@@ -803,7 +904,7 @@ export function auditTask(taskId) {
|
|
|
803
904
|
"## Recommended Actions",
|
|
804
905
|
...actions.map((a) => `- ${a}`),
|
|
805
906
|
].join("\n");
|
|
806
|
-
|
|
907
|
+
atomicWriteFileSync(join(taskDir, "independent-review.md"), reviewMd);
|
|
807
908
|
// ── v0.7.2: 集成 acceptanceEngine ──
|
|
808
909
|
const releaseClaimsUnverified = allReleaseClaims.length > 0;
|
|
809
910
|
const acceptanceEvidence = {
|
|
@@ -818,8 +919,10 @@ export function auditTask(taskId) {
|
|
|
818
919
|
if (!existsSync(verifyJsonFile))
|
|
819
920
|
return null;
|
|
820
921
|
try {
|
|
821
|
-
const v = JSON.parse(readFileSync(verifyJsonFile, "utf-8"));
|
|
822
|
-
|
|
922
|
+
const v = JSON.parse(readFileSync(verifyJsonFile, "utf-8")) as { status?: string };
|
|
923
|
+
if (v.status === "passed") return "passed" as const;
|
|
924
|
+
if (v.status === "failed") return "failed" as const;
|
|
925
|
+
return "skipped" as const;
|
|
823
926
|
}
|
|
824
927
|
catch {
|
|
825
928
|
return null;
|
|
@@ -838,16 +941,20 @@ export function auditTask(taskId) {
|
|
|
838
941
|
const acceptanceResult = evaluateAcceptance(acceptanceEvidence);
|
|
839
942
|
// 回写 status.json 的 acceptance_status(仅对 done_by_agent 有意义)
|
|
840
943
|
if (taskStatus === "done_by_agent") {
|
|
841
|
-
const
|
|
842
|
-
...statusData,
|
|
944
|
+
const statusPatch = {
|
|
843
945
|
acceptance_status: acceptanceResult.acceptance_status,
|
|
844
|
-
updated_at: new Date().toISOString(),
|
|
845
946
|
};
|
|
846
|
-
|
|
947
|
+
mutateTaskStatus(statusFile, (current) => {
|
|
948
|
+
if (current.status !== "done_by_agent") {
|
|
949
|
+
return { result: current };
|
|
950
|
+
}
|
|
951
|
+
const next = { ...current, ...statusPatch, updated_at: new Date().toISOString() };
|
|
952
|
+
return { next, result: next };
|
|
953
|
+
});
|
|
847
954
|
}
|
|
848
955
|
// 导出 ACCEPTANCE.md
|
|
849
956
|
const acceptanceMd = renderAcceptanceMarkdown(taskId, acceptanceResult, acceptanceEvidence);
|
|
850
|
-
|
|
957
|
+
atomicWriteFileSync(join(taskDir, "ACCEPTANCE.md"), acceptanceMd);
|
|
851
958
|
return {
|
|
852
959
|
task_id: taskId,
|
|
853
960
|
verdict,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { accessSync, constants, existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
-
import { getConfig, getTasksDir, getDirectSessionsDir, resolveWorkspaceRoot } from "
|
|
5
|
-
import { listAgents } from "
|
|
6
|
-
import { redactSensitiveContent, redactSensitiveValue } from "
|
|
7
|
-
import { PATCHWARDEN_VERSION, TOOL_SCHEMA_EPOCH } from "
|
|
8
|
-
import type { ToolCatalogSnapshot } from "
|
|
9
|
-
import { CHATGPT_CORE_TOOL_NAMES, CHATGPT_DIRECT_TOOL_NAMES, CHATGPT_SEARCH_TOOL_NAMES, resolveToolProfile } from "
|
|
10
|
-
import { readWatcherStatus } from "
|
|
11
|
-
import { listTasks } from "
|
|
4
|
+
import { getConfig, getTasksDir, getDirectSessionsDir, resolveWorkspaceRoot } from "../../config.js";
|
|
5
|
+
import { listAgents } from "../workspace/listAgents.js";
|
|
6
|
+
import { redactSensitiveContent, redactSensitiveValue } from "../../security/contentRedaction.js";
|
|
7
|
+
import { PATCHWARDEN_VERSION, TOOL_SCHEMA_EPOCH } from "../../version.js";
|
|
8
|
+
import type { ToolCatalogSnapshot } from "../catalog/toolCatalog.js";
|
|
9
|
+
import { CHATGPT_CORE_TOOL_NAMES, CHATGPT_DIRECT_TOOL_NAMES, CHATGPT_SEARCH_TOOL_NAMES, resolveToolProfile } from "../catalog/toolCatalog.js";
|
|
10
|
+
import { readWatcherStatus } from "../../watcherStatus.js";
|
|
11
|
+
import { listTasks } from "../tasks/listTasks.js";
|
|
12
12
|
|
|
13
13
|
const SERVER_STARTED_AT = Date.now();
|
|
14
14
|
|
|
@@ -195,14 +195,14 @@ function directoryStatus(path: string, allowCreatable: boolean, createRoot?: str
|
|
|
195
195
|
try {
|
|
196
196
|
accessSync(parent, constants.R_OK | constants.W_OK);
|
|
197
197
|
return { available: true, path, readable: false, writable: true, reason: "Directory will be created on first use." };
|
|
198
|
-
} catch {}
|
|
198
|
+
} catch {} // probe failure handled by return value
|
|
199
199
|
}
|
|
200
200
|
return { available: false, path, readable: false, writable: false, reason: "Directory does not exist." };
|
|
201
201
|
}
|
|
202
202
|
let readable = false;
|
|
203
203
|
let writable = false;
|
|
204
|
-
try { accessSync(path, constants.R_OK); readable = true; } catch {}
|
|
205
|
-
try { accessSync(path, constants.W_OK); writable = true; } catch {}
|
|
204
|
+
try { accessSync(path, constants.R_OK); readable = true; } catch {} // probe failure handled by return value
|
|
205
|
+
try { accessSync(path, constants.W_OK); writable = true; } catch {} // probe failure handled by return value
|
|
206
206
|
return {
|
|
207
207
|
available: readable && writable,
|
|
208
208
|
path,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { readFileSync, existsSync } from "node:fs";
|
|
2
2
|
import { resolve, join } from "node:path";
|
|
3
|
-
import { getTasksDir, getConfig, type PatchWardenConfig } from "
|
|
4
|
-
import { guardReadPath } from "
|
|
5
|
-
import { guardSensitivePath } from "
|
|
6
|
-
import type { TaskStatus, TaskPhase, AcceptanceStatus } from "
|
|
7
|
-
import { readTaskRuntime } from "
|
|
8
|
-
import { readWatcherStatus } from "
|
|
9
|
-
import { diagnoseTask, type DiagnosisType, type DiagnosisConfidence } from "
|
|
3
|
+
import { getTasksDir, getConfig, type PatchWardenConfig } from "../../config.js";
|
|
4
|
+
import { guardReadPath } from "../../security/pathGuard.js";
|
|
5
|
+
import { guardSensitivePath } from "../../security/sensitiveGuard.js";
|
|
6
|
+
import type { TaskStatus, TaskPhase, AcceptanceStatus } from "../tasks/createTask.js";
|
|
7
|
+
import { readTaskRuntime } from "../../runner/taskRuntime.js";
|
|
8
|
+
import { readWatcherStatus } from "../../watcherStatus.js";
|
|
9
|
+
import { diagnoseTask, type DiagnosisType, type DiagnosisConfidence } from "../tasks/diagnoseTask.js";
|
|
10
10
|
|
|
11
11
|
export interface SafeStatusOutput {
|
|
12
12
|
task_id: string;
|