patchwarden 1.1.0 → 1.5.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.
Files changed (258) hide show
  1. package/README.en.md +83 -8
  2. package/README.md +78 -10
  3. package/dist/assessments/agentAssessor.d.ts +1 -1
  4. package/dist/assessments/agentAssessor.js +3 -3
  5. package/dist/assessments/assessmentStore.d.ts +1 -1
  6. package/dist/assessments/assessmentStore.js +2 -2
  7. package/dist/assessments/confirmCli.js +5 -4
  8. package/dist/config.d.ts +7 -0
  9. package/dist/config.js +34 -0
  10. package/dist/control/middleware/auth.d.ts +10 -0
  11. package/dist/control/middleware/auth.js +8 -0
  12. package/dist/control/middleware/static.d.ts +3 -0
  13. package/dist/control/middleware/static.js +65 -0
  14. package/dist/control/routes/audit.d.ts +15 -0
  15. package/dist/control/routes/audit.js +277 -0
  16. package/dist/control/routes/evidence.d.ts +4 -0
  17. package/dist/control/routes/evidence.js +96 -0
  18. package/dist/control/routes/lineage.d.ts +3 -0
  19. package/dist/control/routes/lineage.js +71 -0
  20. package/dist/control/routes/policy.d.ts +3 -0
  21. package/dist/control/routes/policy.js +81 -0
  22. package/dist/control/routes/process.d.ts +5 -0
  23. package/dist/control/routes/process.js +200 -0
  24. package/dist/control/routes/sessions.d.ts +22 -0
  25. package/dist/control/routes/sessions.js +224 -0
  26. package/dist/control/routes/status.d.ts +6 -0
  27. package/dist/control/routes/status.js +250 -0
  28. package/dist/control/routes/taskActions.d.ts +21 -0
  29. package/dist/control/routes/taskActions.js +233 -0
  30. package/dist/control/routes/tasks.d.ts +20 -0
  31. package/dist/control/routes/tasks.js +310 -0
  32. package/dist/control/routes/workspace.d.ts +15 -0
  33. package/dist/control/routes/workspace.js +193 -0
  34. package/dist/control/runtime.d.ts +91 -0
  35. package/dist/control/runtime.js +392 -0
  36. package/dist/control/server.d.ts +13 -0
  37. package/dist/control/server.js +479 -0
  38. package/dist/control/shared.d.ts +35 -0
  39. package/dist/control/shared.js +288 -0
  40. package/dist/controlCenter.d.ts +6 -0
  41. package/dist/controlCenter.js +7 -2001
  42. package/dist/direct/directGuards.js +30 -8
  43. package/dist/direct/directSessionStore.d.ts +2 -0
  44. package/dist/direct/directVerification.js +7 -0
  45. package/dist/doctor.d.ts +18 -1
  46. package/dist/doctor.js +579 -348
  47. package/dist/goal/goalReport.d.ts +54 -0
  48. package/dist/goal/goalReport.js +204 -0
  49. package/dist/goal/goalStatus.d.ts +6 -0
  50. package/dist/goal/specKitImport.d.ts +63 -0
  51. package/dist/goal/specKitImport.js +220 -0
  52. package/dist/goal/subgoalSync.js +2 -1
  53. package/dist/httpServer.js +15 -12
  54. package/dist/index.js +7 -4
  55. package/dist/logging.d.ts +7 -1
  56. package/dist/logging.js +8 -0
  57. package/dist/policy/projectPolicy.d.ts +55 -0
  58. package/dist/policy/projectPolicy.js +286 -0
  59. package/dist/runner/changeCapture.d.ts +3 -3
  60. package/dist/runner/changeCapture.js +63 -39
  61. package/dist/runner/cli.js +7 -6
  62. package/dist/runner/postTaskCleanup.js +26 -2
  63. package/dist/runner/runTask.js +245 -221
  64. package/dist/runner/simpleProcess.js +4 -4
  65. package/dist/runner/watch.js +17 -14
  66. package/dist/security/contentRedaction.d.ts +6 -0
  67. package/dist/security/contentRedaction.js +22 -0
  68. package/dist/smoke-test.js +261 -255
  69. package/dist/test/unit/apply-patch.test.d.ts +1 -0
  70. package/dist/test/unit/apply-patch.test.js +225 -0
  71. package/dist/test/unit/create-task.test.d.ts +1 -0
  72. package/dist/test/unit/create-task.test.js +197 -0
  73. package/dist/test/unit/direct-guards.test.js +124 -9
  74. package/dist/test/unit/evidence-pack.test.d.ts +1 -0
  75. package/dist/test/unit/evidence-pack.test.js +224 -0
  76. package/dist/test/unit/get-task-status.test.d.ts +1 -0
  77. package/dist/test/unit/get-task-status.test.js +174 -0
  78. package/dist/test/unit/get-task-summary.test.d.ts +1 -0
  79. package/dist/test/unit/get-task-summary.test.js +146 -0
  80. package/dist/test/unit/goal-report.test.d.ts +1 -0
  81. package/dist/test/unit/goal-report.test.js +159 -0
  82. package/dist/test/unit/goal-subgoal-task.test.js +6 -6
  83. package/dist/test/unit/goal-tools-registry.test.js +6 -4
  84. package/dist/test/unit/path-guard.test.js +24 -0
  85. package/dist/test/unit/project-policy-release-mode.test.d.ts +1 -0
  86. package/dist/test/unit/project-policy-release-mode.test.js +125 -0
  87. package/dist/test/unit/run-task-loop.test.d.ts +1 -0
  88. package/dist/test/unit/run-task-loop.test.js +380 -0
  89. package/dist/test/unit/schema-drift-check.test.js +10 -9
  90. package/dist/test/unit/spec-kit-import.test.d.ts +1 -0
  91. package/dist/test/unit/spec-kit-import.test.js +341 -0
  92. package/dist/test/unit/wait-for-task.test.d.ts +1 -0
  93. package/dist/test/unit/wait-for-task.test.js +144 -0
  94. package/dist/tools/auditTask.d.ts +8 -63
  95. package/dist/tools/auditTask.js +12 -8
  96. package/dist/tools/createDirectSession.d.ts +1 -1
  97. package/dist/tools/createDirectSession.js +2 -2
  98. package/dist/tools/createTask.d.ts +2 -2
  99. package/dist/tools/createTask.js +4 -4
  100. package/dist/tools/dispatch/coreDispatch.d.ts +9 -0
  101. package/dist/tools/dispatch/coreDispatch.js +282 -0
  102. package/dist/tools/dispatch/diagnosticDispatch.d.ts +14 -0
  103. package/dist/tools/dispatch/diagnosticDispatch.js +78 -0
  104. package/dist/tools/dispatch/directDispatch.d.ts +8 -0
  105. package/dist/tools/dispatch/directDispatch.js +115 -0
  106. package/dist/tools/dispatch/goalDispatch.d.ts +8 -0
  107. package/dist/tools/dispatch/goalDispatch.js +91 -0
  108. package/dist/tools/dispatch/releaseDispatch.d.ts +8 -0
  109. package/dist/tools/dispatch/releaseDispatch.js +45 -0
  110. package/dist/tools/dispatch/types.d.ts +23 -0
  111. package/dist/tools/dispatch/types.js +15 -0
  112. package/dist/tools/evidencePack.d.ts +45 -0
  113. package/dist/tools/evidencePack.js +375 -0
  114. package/dist/tools/finalizeDirectSession.d.ts +1 -1
  115. package/dist/tools/finalizeDirectSession.js +3 -3
  116. package/dist/tools/goalSubgoalTask.d.ts +1 -1
  117. package/dist/tools/goalSubgoalTask.js +2 -2
  118. package/dist/tools/healthCheck.js +3 -3
  119. package/dist/tools/recommendAgentForTask.d.ts +19 -0
  120. package/dist/tools/recommendAgentForTask.js +56 -0
  121. package/dist/tools/registry.d.ts +3 -3
  122. package/dist/tools/registry.js +333 -402
  123. package/dist/tools/releaseMode.d.ts +50 -0
  124. package/dist/tools/releaseMode.js +370 -0
  125. package/dist/tools/retryTask.d.ts +2 -2
  126. package/dist/tools/retryTask.js +2 -2
  127. package/dist/tools/runDirectVerificationBundle.d.ts +26 -0
  128. package/dist/tools/runDirectVerificationBundle.js +64 -0
  129. package/dist/tools/runTaskLoop.d.ts +57 -0
  130. package/dist/tools/runTaskLoop.js +417 -0
  131. package/dist/tools/runVerification.d.ts +4 -0
  132. package/dist/tools/runVerification.js +4 -0
  133. package/dist/tools/safeViews.d.ts +8 -2
  134. package/dist/tools/safeViews.js +4 -2
  135. package/dist/tools/taskLineage.d.ts +91 -0
  136. package/dist/tools/taskLineage.js +175 -0
  137. package/dist/tools/toolCatalog.d.ts +2 -2
  138. package/dist/tools/toolCatalog.js +6 -0
  139. package/dist/tools/toolRegistry.js +132 -0
  140. package/dist/version.d.ts +2 -2
  141. package/dist/version.js +2 -2
  142. package/docs/CODE_WIKI.md +983 -0
  143. package/docs/agentseal-integration.md +150 -0
  144. package/docs/architecture.md +63 -0
  145. package/docs/assets/patchwarden-oss-demo.gif +0 -0
  146. package/docs/chatgpt-usage.md +31 -0
  147. package/docs/control-center/README.md +9 -0
  148. package/docs/dashboard-overview.md +86 -0
  149. package/docs/demo.md +8 -0
  150. package/docs/direct-session-workflow.md +98 -0
  151. package/docs/evidence-pack-schema.md +215 -0
  152. package/docs/execution-plan-2026-07-09.md +315 -0
  153. package/docs/lineage-evidence-pack-workflow.md +127 -0
  154. package/docs/mcp-inspector-testing.md +200 -0
  155. package/docs/open-source-application.md +162 -0
  156. package/docs/opencode-worker.md +151 -0
  157. package/docs/openhands-worker.md +181 -0
  158. package/docs/release-evidence.md +72 -0
  159. package/docs/roadmap-execution-and-acceptance.md +365 -0
  160. package/docs/spec-kit-integration.md +131 -0
  161. package/docs/task-safe-review-workflow.md +98 -0
  162. package/docs/threat-model.md +79 -0
  163. package/docs/user-feedback.md +40 -0
  164. package/docs/why-patchwarden.md +110 -0
  165. package/package.json +3 -3
  166. package/scripts/checks/control-center-smoke.js +443 -0
  167. package/scripts/checks/control-smoke.js +2 -2
  168. package/scripts/checks/lifecycle-smoke.js +29 -23
  169. package/scripts/checks/mcp-manifest-check.js +12 -0
  170. package/scripts/checks/mcp-smoke.js +33 -7
  171. package/scripts/checks/watcher-supervisor-smoke.js +1 -1
  172. package/scripts/generate-demo-gif.py +320 -0
  173. package/src/assessments/agentAssessor.ts +3 -3
  174. package/src/assessments/assessmentStore.ts +2 -2
  175. package/src/assessments/confirmCli.ts +5 -4
  176. package/src/config.ts +37 -0
  177. package/src/control/middleware/auth.ts +17 -0
  178. package/src/control/middleware/static.ts +71 -0
  179. package/src/control/routes/audit.ts +321 -0
  180. package/src/control/routes/evidence.ts +107 -0
  181. package/src/control/routes/lineage.ts +92 -0
  182. package/src/control/routes/policy.ts +81 -0
  183. package/src/control/routes/process.ts +204 -0
  184. package/src/control/routes/sessions.ts +251 -0
  185. package/src/control/routes/status.ts +325 -0
  186. package/src/control/routes/taskActions.ts +248 -0
  187. package/src/control/routes/tasks.ts +323 -0
  188. package/src/control/routes/workspace.ts +203 -0
  189. package/src/control/runtime.ts +472 -0
  190. package/src/control/server.ts +471 -0
  191. package/src/control/shared.ts +294 -0
  192. package/src/controlCenter.ts +7 -2150
  193. package/src/direct/directGuards.ts +28 -7
  194. package/src/direct/directSessionStore.ts +2 -0
  195. package/src/direct/directVerification.ts +7 -0
  196. package/src/doctor.ts +741 -481
  197. package/src/goal/goalReport.ts +271 -0
  198. package/src/goal/goalStatus.ts +6 -0
  199. package/src/goal/specKitImport.ts +355 -0
  200. package/src/goal/subgoalSync.ts +4 -2
  201. package/src/httpServer.ts +17 -14
  202. package/src/index.ts +7 -4
  203. package/src/logging.ts +10 -1
  204. package/src/policy/projectPolicy.ts +344 -0
  205. package/src/runner/changeCapture.ts +70 -42
  206. package/src/runner/cli.ts +7 -6
  207. package/src/runner/postTaskCleanup.ts +26 -2
  208. package/src/runner/runTask.ts +325 -223
  209. package/src/runner/simpleProcess.ts +4 -4
  210. package/src/runner/watch.ts +17 -14
  211. package/src/security/contentRedaction.ts +29 -0
  212. package/src/smoke-test.ts +254 -252
  213. package/src/test/unit/apply-patch.test.ts +293 -0
  214. package/src/test/unit/create-task.test.ts +255 -0
  215. package/src/test/unit/direct-guards.test.ts +178 -8
  216. package/src/test/unit/evidence-pack.test.ts +251 -0
  217. package/src/test/unit/get-task-status.test.ts +203 -0
  218. package/src/test/unit/get-task-summary.test.ts +173 -0
  219. package/src/test/unit/goal-report.test.ts +189 -0
  220. package/src/test/unit/goal-subgoal-task.test.ts +6 -6
  221. package/src/test/unit/goal-tools-registry.test.ts +7 -5
  222. package/src/test/unit/path-guard.test.ts +30 -0
  223. package/src/test/unit/project-policy-release-mode.test.ts +156 -0
  224. package/src/test/unit/run-task-loop.test.ts +425 -0
  225. package/src/test/unit/schema-drift-check.test.ts +11 -9
  226. package/src/test/unit/spec-kit-import.test.ts +429 -0
  227. package/src/test/unit/wait-for-task.test.ts +176 -0
  228. package/src/tools/auditTask.ts +99 -59
  229. package/src/tools/createDirectSession.ts +3 -3
  230. package/src/tools/createTask.ts +7 -7
  231. package/src/tools/dispatch/coreDispatch.ts +374 -0
  232. package/src/tools/dispatch/diagnosticDispatch.ts +101 -0
  233. package/src/tools/dispatch/directDispatch.ts +167 -0
  234. package/src/tools/dispatch/goalDispatch.ts +127 -0
  235. package/src/tools/dispatch/releaseDispatch.ts +65 -0
  236. package/src/tools/dispatch/types.ts +24 -0
  237. package/src/tools/evidencePack.ts +490 -0
  238. package/src/tools/finalizeDirectSession.ts +4 -4
  239. package/src/tools/goalSubgoalTask.ts +2 -2
  240. package/src/tools/healthCheck.ts +3 -3
  241. package/src/tools/listWorkspace.ts +71 -71
  242. package/src/tools/recommendAgentForTask.ts +79 -0
  243. package/src/tools/registry.ts +352 -509
  244. package/src/tools/releaseMode.ts +450 -0
  245. package/src/tools/retryTask.ts +2 -2
  246. package/src/tools/runDirectVerificationBundle.ts +98 -0
  247. package/src/tools/runTaskLoop.ts +526 -0
  248. package/src/tools/runVerification.ts +8 -0
  249. package/src/tools/safeViews.ts +4 -2
  250. package/src/tools/taskLineage.ts +300 -0
  251. package/src/tools/toolCatalog.ts +6 -0
  252. package/src/tools/toolRegistry.ts +132 -0
  253. package/src/version.ts +2 -2
  254. package/ui/pages/audit.html +192 -3
  255. package/ui/pages/dashboard.html +1070 -14
  256. package/ui/pages/direct-sessions.html +505 -53
  257. package/ui/pages/task-detail.html +456 -438
  258. package/ui/pages/tasks.html +598 -61
@@ -101,5 +101,5 @@ export interface CreateTaskOutput {
101
101
  }
102
102
  export declare function createTask(input: CreateTaskInput & {
103
103
  execution_mode: "assess_only";
104
- }): AssessOnlyOutput;
105
- export declare function createTask(input: CreateTaskInput): CreateTaskOutput;
104
+ }): Promise<AssessOnlyOutput>;
105
+ export declare function createTask(input: CreateTaskInput): Promise<CreateTaskOutput>;
@@ -18,7 +18,7 @@ import { PATCHWARDEN_VERSION } from "../version.js";
18
18
  import { getLastToolCatalogSnapshot, resolveToolProfile } from "./toolCatalog.js";
19
19
  import { derivePendingReason, readWatcherStatus, } from "../watcherStatus.js";
20
20
  import { routeAgent } from "../agents/agentRouter.js";
21
- export function createTask(input) {
21
+ export async function createTask(input) {
22
22
  const config = getConfig();
23
23
  const tasksDir = getTasksDir(config);
24
24
  const plansDir = getPlansDir(config);
@@ -151,7 +151,7 @@ export function createTask(input) {
151
151
  planBlocked = true;
152
152
  planBlockReason = e instanceof PatchWardenError ? e.reason : "plan_content_blocked";
153
153
  }
154
- const snapshot = captureRepoSnapshot(safeRepoPath);
154
+ const snapshot = await captureRepoSnapshot(safeRepoPath);
155
155
  const snapshotTruncated = snapshot.warnings.some((w) => w.includes("snapshot limited"));
156
156
  let riskResult;
157
157
  if (planBlocked) {
@@ -208,7 +208,7 @@ export function createTask(input) {
208
208
  preGeneratedAssessmentId = generateAssessmentId();
209
209
  preGeneratedAssessmentDir = createAssessmentDir(preGeneratedAssessmentId);
210
210
  const assessorAgentName = config.agentAssessmentAgentName || effectiveInput.agent;
211
- agentAssessmentSummary = runAgentAssessment({
211
+ agentAssessmentSummary = await runAgentAssessment({
212
212
  assessmentId: preGeneratedAssessmentId,
213
213
  assessmentDir: preGeneratedAssessmentDir,
214
214
  agentName: assessorAgentName,
@@ -330,7 +330,7 @@ export function createTask(input) {
330
330
  }
331
331
  // ── execute mode with assessment_id: validate freshness ──
332
332
  if (assessmentRecord) {
333
- const snapshot = captureRepoSnapshot(safeRepoPath);
333
+ const snapshot = await captureRepoSnapshot(safeRepoPath);
334
334
  const validation = validateAssessmentFreshness(input.assessment_id, snapshot);
335
335
  if (!validation.valid) {
336
336
  throw new PatchWardenError(validation.failure_reason || "assessment_validation_failed", `Assessment "${input.assessment_id}" is no longer valid: ${validation.failure_reason}`, "Re-run create_task with execution_mode=assess_only to get a fresh assessment_id.", true, { assessment_id: input.assessment_id, failure_reason: validation.failure_reason });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Dispatch handlers for core task-management tools.
3
+ *
4
+ * Each handler directly calls the existing tool function — no logic is
5
+ * rewritten. Extracted from the original handleToolCallInternal switch.
6
+ */
7
+ import type { ToolHandlerMap } from "./types.js";
8
+ export declare const coreHandlers: ToolHandlerMap;
9
+ export declare const runTaskHandler: ToolHandlerMap["run_task"];
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Dispatch handlers for core task-management tools.
3
+ *
4
+ * Each handler directly calls the existing tool function — no logic is
5
+ * rewritten. Extracted from the original handleToolCallInternal switch.
6
+ */
7
+ import { savePlan } from "../savePlan.js";
8
+ import { getPlan } from "../getPlan.js";
9
+ import { createTask } from "../createTask.js";
10
+ import { getTaskStatus } from "../getTaskStatus.js";
11
+ import { getResult, getResultJson, getDiff, getTestLog, getTaskLogTail } from "../taskOutputs.js";
12
+ import { listWorkspace } from "../listWorkspace.js";
13
+ import { readWorkspaceFile } from "../readWorkspaceFile.js";
14
+ import { listTasks } from "../listTasks.js";
15
+ import { cancelTask } from "../cancelTask.js";
16
+ import { killTask } from "../killTask.js";
17
+ import { retryTask } from "../retryTask.js";
18
+ import { getTaskStdoutTail } from "../getTaskStdoutTail.js";
19
+ import { getTaskProgress } from "../getTaskProgress.js";
20
+ import { listAgents } from "../listAgents.js";
21
+ import { healthCheck } from "../healthCheck.js";
22
+ import { getTaskSummary } from "../getTaskSummary.js";
23
+ import { waitForTask } from "../waitForTask.js";
24
+ import { runTaskLoop } from "../runTaskLoop.js";
25
+ import { getTaskLineage } from "../taskLineage.js";
26
+ import { exportTaskEvidencePack } from "../evidencePack.js";
27
+ import { recommendAgentForTask } from "../recommendAgentForTask.js";
28
+ import { auditTask } from "../auditTask.js";
29
+ import { safeStatus } from "../safeStatus.js";
30
+ import { safeAudit, safeDiffSummary, safeResult, safeTestSummary } from "../safeViews.js";
31
+ import { diagnoseTask } from "../diagnoseTask.js";
32
+ import { reconcileTasks } from "../reconcileTasks.js";
33
+ import { checkReleaseGate } from "../checkReleaseGate.js";
34
+ import { getProjectPolicyTool } from "../releaseMode.js";
35
+ import { runTask } from "../../runner/runTask.js";
36
+ import { getConfig } from "../../config.js";
37
+ import { getToolCatalogSnapshot } from "../registry.js";
38
+ import { toResult } from "./types.js";
39
+ // ── Local helpers (moved verbatim from registry.ts) ───────────────
40
+ function normalizeWaitSeconds(args) {
41
+ const legacy = args?.wait_seconds;
42
+ const preferred = args?.timeout_seconds;
43
+ if (legacy !== undefined && preferred !== undefined && Number(legacy) !== Number(preferred)) {
44
+ throw new Error("wait_seconds and timeout_seconds must match when both are supplied.");
45
+ }
46
+ const value = preferred ?? legacy;
47
+ return value === undefined ? undefined : Number(value);
48
+ }
49
+ function normalizeSummaryView(value) {
50
+ if (value === undefined)
51
+ return "standard";
52
+ if (value !== "compact" && value !== "standard") {
53
+ throw new Error('view must be "compact" or "standard".');
54
+ }
55
+ return value;
56
+ }
57
+ // ── Handler map ───────────────────────────────────────────────────
58
+ export const coreHandlers = {
59
+ save_plan: async (args) => {
60
+ return toResult(savePlan({
61
+ title: String(args?.title ?? ""),
62
+ content: args?.content !== undefined ? String(args.content) : "",
63
+ plan_ref: args?.plan_ref ? String(args.plan_ref) : undefined,
64
+ }));
65
+ },
66
+ get_plan: async (args) => {
67
+ return toResult(getPlan({ plan_id: String(args?.plan_id ?? "") }));
68
+ },
69
+ create_task: async (args) => {
70
+ return toResult(await createTask({
71
+ plan_id: args?.plan_id ? String(args.plan_id) : undefined,
72
+ inline_plan: args?.inline_plan ? String(args.inline_plan) : undefined,
73
+ plan_title: args?.plan_title ? String(args.plan_title) : undefined,
74
+ template: args?.template ? String(args.template) : undefined,
75
+ goal: args?.goal ? String(args.goal) : undefined,
76
+ source_task_id: args?.source_task_id ? String(args.source_task_id) : undefined,
77
+ agent: String(args?.agent ?? ""),
78
+ repo_path: args?.repo_path ? String(args.repo_path) : undefined,
79
+ test_command: args?.test_command ? String(args.test_command) : undefined,
80
+ verify_commands: Array.isArray(args?.verify_commands)
81
+ ? args.verify_commands.map((command) => String(command))
82
+ : undefined,
83
+ timeout_seconds: args?.timeout_seconds !== undefined ? Number(args.timeout_seconds) : undefined,
84
+ execution_mode: args?.execution_mode === "assess_only" ? "assess_only" : "execute",
85
+ assessment_id: args?.assessment_id ? String(args.assessment_id) : undefined,
86
+ }));
87
+ },
88
+ run_task_loop: async (args) => {
89
+ return toResult(await runTaskLoop({
90
+ repo_path: String(args?.repo_path ?? ""),
91
+ goal: String(args?.goal ?? ""),
92
+ verify_commands: Array.isArray(args?.verify_commands)
93
+ ? args.verify_commands.map((command) => String(command))
94
+ : [],
95
+ agent: args?.agent ? String(args.agent) : undefined,
96
+ template: args?.template === "inspect_only" || args?.template === "release_check"
97
+ ? args.template
98
+ : "feature_small",
99
+ max_iterations: args?.max_iterations !== undefined ? Number(args.max_iterations) : undefined,
100
+ task_timeout_seconds: args?.task_timeout_seconds !== undefined ? Number(args.task_timeout_seconds) : undefined,
101
+ auto_fix_tests: args?.auto_fix_tests !== undefined ? Boolean(args.auto_fix_tests) : undefined,
102
+ auto_cleanup_artifacts: args?.auto_cleanup_artifacts !== undefined
103
+ ? Boolean(args.auto_cleanup_artifacts)
104
+ : undefined,
105
+ stop_on_high_risk: args?.stop_on_high_risk !== undefined ? Boolean(args.stop_on_high_risk) : undefined,
106
+ direct_verify: args?.direct_verify !== undefined ? Boolean(args.direct_verify) : undefined,
107
+ direct_verify_commands: Array.isArray(args?.direct_verify_commands)
108
+ ? args.direct_verify_commands.map((command) => String(command))
109
+ : undefined,
110
+ direct_verify_timeout_seconds: args?.direct_verify_timeout_seconds !== undefined
111
+ ? Number(args.direct_verify_timeout_seconds)
112
+ : undefined,
113
+ scope_files: Array.isArray(args?.scope_files)
114
+ ? args.scope_files.map((entry) => String(entry))
115
+ : undefined,
116
+ isolation_mode: args?.isolation_mode === "worktree" ? "worktree" : "current_repo",
117
+ worktree_base_branch: args?.worktree_base_branch
118
+ ? String(args.worktree_base_branch)
119
+ : undefined,
120
+ worktree_cleanup: args?.worktree_cleanup === "archive" || args?.worktree_cleanup === "delete_ignored_only"
121
+ ? args.worktree_cleanup
122
+ : "keep",
123
+ }));
124
+ },
125
+ recommend_agent_for_task: async (args) => {
126
+ return toResult(recommendAgentForTask({
127
+ repo_path: String(args?.repo_path ?? ""),
128
+ goal: String(args?.goal ?? ""),
129
+ scope_files: Array.isArray(args?.scope_files)
130
+ ? args.scope_files.map((entry) => String(entry))
131
+ : undefined,
132
+ template: args?.template ? String(args.template) : undefined,
133
+ risk_hint: args?.risk_hint ? String(args.risk_hint) : undefined,
134
+ }));
135
+ },
136
+ get_task_lineage: async (args) => {
137
+ return toResult(getTaskLineage(String(args?.lineage_id ?? ""), {
138
+ max_items: args?.max_items !== undefined ? Number(args.max_items) : undefined,
139
+ }));
140
+ },
141
+ export_task_evidence_pack: async (args) => {
142
+ return toResult(exportTaskEvidencePack({
143
+ lineage_id: String(args?.lineage_id ?? ""),
144
+ max_items: args?.max_items !== undefined ? Number(args.max_items) : undefined,
145
+ }));
146
+ },
147
+ get_project_policy: async (args) => {
148
+ return toResult(getProjectPolicyTool(String(args?.repo_path ?? "")));
149
+ },
150
+ get_task_status: async (args) => {
151
+ return toResult(getTaskStatus(String(args?.task_id ?? "")));
152
+ },
153
+ get_result: async (args) => {
154
+ return toResult(getResult(String(args?.task_id ?? "")));
155
+ },
156
+ get_result_json: async (args) => {
157
+ return toResult(getResultJson(String(args?.task_id ?? "")));
158
+ },
159
+ get_diff: async (args) => {
160
+ return toResult(getDiff(String(args?.task_id ?? "")));
161
+ },
162
+ get_test_log: async (args) => {
163
+ return toResult(getTestLog(String(args?.task_id ?? "")));
164
+ },
165
+ list_workspace: async (args) => {
166
+ return toResult(listWorkspace(args?.path ? String(args.path) : undefined));
167
+ },
168
+ read_workspace_file: async (args) => {
169
+ const sessionId = args?.session_id ? String(args.session_id) : undefined;
170
+ return toResult(readWorkspaceFile({
171
+ path: String(args?.path ?? ""),
172
+ session_id: sessionId,
173
+ }));
174
+ },
175
+ list_tasks: async (args) => {
176
+ return toResult(listTasks({
177
+ status: args?.status ? String(args.status) : undefined,
178
+ repo_path: args?.repo_path ? String(args.repo_path) : undefined,
179
+ active_only: args?.active_only !== undefined ? Boolean(args.active_only) : undefined,
180
+ limit: args?.limit ? Number(args.limit) : undefined,
181
+ }));
182
+ },
183
+ list_agents: async () => {
184
+ return toResult(listAgents());
185
+ },
186
+ health_check: async (args) => {
187
+ return toResult(healthCheck(getToolCatalogSnapshot(), {
188
+ detail: args?.detail === "self_diagnostic" ? "self_diagnostic" : "standard",
189
+ }));
190
+ },
191
+ cancel_task: async (args) => {
192
+ return toResult(cancelTask(String(args?.task_id ?? "")));
193
+ },
194
+ kill_task: async (args) => {
195
+ return toResult(killTask(String(args?.task_id ?? "")));
196
+ },
197
+ retry_task: async (args) => {
198
+ return toResult(await retryTask(String(args?.task_id ?? "")));
199
+ },
200
+ get_task_stdout_tail: async (args) => {
201
+ return toResult(getTaskStdoutTail(String(args?.task_id ?? ""), args?.lines ? Number(args.lines) : undefined));
202
+ },
203
+ get_task_log_tail: async (args) => {
204
+ return toResult(getTaskLogTail(String(args?.task_id ?? ""), args?.file || "stdout", {
205
+ lines: args?.lines ? Number(args.lines) : undefined,
206
+ redact: args?.redact !== undefined ? Boolean(args.redact) : undefined,
207
+ }));
208
+ },
209
+ get_task_progress: async (args) => {
210
+ return toResult(getTaskProgress(String(args?.task_id ?? "")));
211
+ },
212
+ wait_for_task: async (args) => {
213
+ const waitSeconds = normalizeWaitSeconds(args);
214
+ return toResult(await waitForTask(String(args?.task_id ?? ""), waitSeconds));
215
+ },
216
+ get_task_summary: async (args) => {
217
+ return toResult(getTaskSummary(String(args?.task_id ?? ""), {
218
+ view: normalizeSummaryView(args?.view),
219
+ max_items: args?.max_items !== undefined ? Number(args.max_items) : undefined,
220
+ }));
221
+ },
222
+ audit_task: async (args) => {
223
+ return toResult(auditTask(String(args?.task_id ?? "")));
224
+ },
225
+ safe_status: async (args) => {
226
+ return toResult(safeStatus(String(args?.task_id ?? "")));
227
+ },
228
+ safe_result: async (args) => {
229
+ return toResult(safeResult(String(args?.task_id ?? ""), {
230
+ max_items: args?.max_items !== undefined ? Number(args.max_items) : undefined,
231
+ }));
232
+ },
233
+ safe_audit: async (args) => {
234
+ return toResult(safeAudit(String(args?.task_id ?? ""), {
235
+ max_items: args?.max_items !== undefined ? Number(args.max_items) : undefined,
236
+ }));
237
+ },
238
+ safe_test_summary: async (args) => {
239
+ return toResult(safeTestSummary(String(args?.task_id ?? "")));
240
+ },
241
+ safe_diff_summary: async (args) => {
242
+ return toResult(safeDiffSummary(String(args?.task_id ?? ""), {
243
+ max_items: args?.max_items !== undefined ? Number(args.max_items) : undefined,
244
+ }));
245
+ },
246
+ diagnose_task: async (args) => {
247
+ return toResult(diagnoseTask({
248
+ task_id: String(args?.task_id ?? ""),
249
+ include_logs: args?.include_logs !== undefined ? Boolean(args.include_logs) : undefined,
250
+ }));
251
+ },
252
+ reconcile_tasks: async (args) => {
253
+ return toResult(reconcileTasks({
254
+ mode: args?.mode === "safe_fix" ? "safe_fix" : "report_only",
255
+ max_age_minutes: args?.max_age_minutes !== undefined ? Number(args.max_age_minutes) : undefined,
256
+ include_done_candidates: args?.include_done_candidates !== undefined
257
+ ? Boolean(args.include_done_candidates)
258
+ : undefined,
259
+ }));
260
+ },
261
+ check_release_gate: async (args) => {
262
+ return toResult(await checkReleaseGate({
263
+ repo_path: String(args?.repo_path ?? ""),
264
+ target_stage: String(args?.target_stage ?? "local_ready"),
265
+ package_name: args?.package_name ? String(args.package_name) : undefined,
266
+ version: args?.version ? String(args.version) : undefined,
267
+ github_repo: args?.github_repo ? String(args.github_repo) : undefined,
268
+ branch: args?.branch ? String(args.branch) : undefined,
269
+ }));
270
+ },
271
+ };
272
+ // run_task is conditionally registered (only when enableRunTaskTool === true).
273
+ // Exported separately so registry.ts can add it conditionally to the dispatch map.
274
+ export const runTaskHandler = async (args) => {
275
+ const config = getConfig();
276
+ if (config.enableRunTaskTool !== true) {
277
+ throw new Error("run_task is disabled. Set enableRunTaskTool: true in config to enable. Prefer using the local watcher (npm run watch).");
278
+ }
279
+ const taskId = String(args?.task_id ?? "");
280
+ const result = await runTask(taskId);
281
+ return toResult(result);
282
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Dispatch handlers for diagnostic / discovery tools (v0.7.1+).
3
+ *
4
+ * discover_tools and explain_tool are read-only catalog queries.
5
+ * invoke_discovered_tool consumes a discovery token and dispatches to
6
+ * the target tool via handleToolCall.
7
+ *
8
+ * Note: This module imports getToolDefs and handleToolCall from
9
+ * registry.ts. The import is a live ESM binding resolved at runtime,
10
+ * so the circular dependency (registry → diagnosticDispatch → registry)
11
+ * is safe: neither binding is touched during module evaluation.
12
+ */
13
+ import type { ToolHandlerMap } from "./types.js";
14
+ export declare const diagnosticHandlers: ToolHandlerMap;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Dispatch handlers for diagnostic / discovery tools (v0.7.1+).
3
+ *
4
+ * discover_tools and explain_tool are read-only catalog queries.
5
+ * invoke_discovered_tool consumes a discovery token and dispatches to
6
+ * the target tool via handleToolCall.
7
+ *
8
+ * Note: This module imports getToolDefs and handleToolCall from
9
+ * registry.ts. The import is a live ESM binding resolved at runtime,
10
+ * so the circular dependency (registry → diagnosticDispatch → registry)
11
+ * is safe: neither binding is touched during module evaluation.
12
+ */
13
+ import { discoverTools } from "../discoverTools.js";
14
+ import { explainTool } from "../explainTool.js";
15
+ import { invokeDiscoveredTool } from "../invokeDiscoveredTool.js";
16
+ import { getConfig } from "../../config.js";
17
+ import { resolveToolProfile } from "../toolCatalog.js";
18
+ import { getToolDefs, handleToolCall } from "../registry.js";
19
+ import { toResult } from "./types.js";
20
+ export const diagnosticHandlers = {
21
+ discover_tools: async (args) => {
22
+ const profile = args?.profile === "full" ||
23
+ args?.profile === "chatgpt_core" ||
24
+ args?.profile === "chatgpt_direct" ||
25
+ args?.profile === "chatgpt_search"
26
+ ? args.profile
27
+ : undefined;
28
+ const mode = args?.mode === "delegate" ||
29
+ args?.mode === "direct" ||
30
+ args?.mode === "audit" ||
31
+ args?.mode === "release" ||
32
+ args?.mode === "diagnostic"
33
+ ? args.mode
34
+ : undefined;
35
+ const riskCeiling = [
36
+ "readonly",
37
+ "workspace_read_sensitive",
38
+ "workspace_write",
39
+ "command",
40
+ "release",
41
+ "credential_sensitive",
42
+ ].includes(String(args?.riskCeiling ?? ""))
43
+ ? String(args?.riskCeiling)
44
+ : undefined;
45
+ return toResult(discoverTools({
46
+ query: String(args?.query ?? ""),
47
+ profile,
48
+ mode,
49
+ maxResults: args?.maxResults !== undefined ? Number(args.maxResults) : undefined,
50
+ riskCeiling,
51
+ includeHighRisk: args?.includeHighRisk !== undefined ? Boolean(args.includeHighRisk) : undefined,
52
+ }, getToolDefs()));
53
+ },
54
+ explain_tool: async (args) => {
55
+ return toResult(explainTool({
56
+ name: String(args?.name ?? ""),
57
+ includeSchema: args?.includeSchema !== undefined ? Boolean(args.includeSchema) : undefined,
58
+ }, getToolDefs()));
59
+ },
60
+ invoke_discovered_tool: async (args) => {
61
+ const profile = resolveToolProfile(getConfig().toolProfile);
62
+ const result = await invokeDiscoveredTool({
63
+ toolName: String(args?.toolName ?? ""),
64
+ arguments: args?.arguments && typeof args.arguments === "object"
65
+ ? args.arguments
66
+ : {},
67
+ discoveryToken: String(args?.discoveryToken ?? ""),
68
+ assessmentId: args?.assessmentId ? String(args.assessmentId) : undefined,
69
+ }, {
70
+ tools: getToolDefs(),
71
+ profile,
72
+ dispatch: async (name, dispatchArgs) => {
73
+ return handleToolCall(name, dispatchArgs);
74
+ },
75
+ });
76
+ return toResult(result);
77
+ },
78
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Dispatch handlers for Direct session tools.
3
+ *
4
+ * Direct sessions allow ChatGPT to apply patches directly within a
5
+ * repo-scoped workspace. All handlers guard on enableDirectProfile.
6
+ */
7
+ import type { ToolHandlerMap } from "./types.js";
8
+ export declare const directHandlers: ToolHandlerMap;
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Dispatch handlers for Direct session tools.
3
+ *
4
+ * Direct sessions allow ChatGPT to apply patches directly within a
5
+ * repo-scoped workspace. All handlers guard on enableDirectProfile.
6
+ */
7
+ import { getConfig } from "../../config.js";
8
+ import { PatchWardenError } from "../../errors.js";
9
+ import { createDirectSession } from "../createDirectSession.js";
10
+ import { searchWorkspace } from "../searchWorkspace.js";
11
+ import { applyPatch } from "../applyPatch.js";
12
+ import { runVerification } from "../runVerification.js";
13
+ import { runDirectVerificationBundle } from "../runDirectVerificationBundle.js";
14
+ import { finalizeDirectSession } from "../finalizeDirectSession.js";
15
+ import { auditSession } from "../auditSession.js";
16
+ import { syncFile } from "../syncFile.js";
17
+ import { safeAuditDirectSession, safeDirectSummary, safeFinalizeDirectSession, } from "../safeViews.js";
18
+ import { toResult } from "./types.js";
19
+ /** Mirror of guardDirectProfileEnabled from the original registry.ts. */
20
+ function guardDirectProfileEnabled() {
21
+ const config = getConfig();
22
+ if (!config.enableDirectProfile) {
23
+ throw new PatchWardenError("direct_profile_disabled", "Direct profile is disabled by local config.", "Set enableDirectProfile: true in patchwarden.config.json to use Direct session tools.", true, { operation: "direct_tool_call" });
24
+ }
25
+ }
26
+ export const directHandlers = {
27
+ create_direct_session: async (args) => {
28
+ guardDirectProfileEnabled();
29
+ return toResult(await createDirectSession({
30
+ repo_path: String(args?.repo_path ?? ""),
31
+ title: args?.title ? String(args.title) : undefined,
32
+ }));
33
+ },
34
+ search_workspace: async (args) => {
35
+ guardDirectProfileEnabled();
36
+ return toResult(searchWorkspace({
37
+ session_id: String(args?.session_id ?? ""),
38
+ query: String(args?.query ?? ""),
39
+ max_results: args?.max_results ? Number(args.max_results) : undefined,
40
+ case_sensitive: args?.case_sensitive !== undefined ? Boolean(args.case_sensitive) : undefined,
41
+ max_preview_chars: args?.max_preview_chars ? Number(args.max_preview_chars) : undefined,
42
+ include_globs: Array.isArray(args?.include_globs)
43
+ ? args.include_globs.map(String)
44
+ : undefined,
45
+ }));
46
+ },
47
+ apply_patch: async (args) => {
48
+ guardDirectProfileEnabled();
49
+ return toResult(applyPatch({
50
+ session_id: String(args?.session_id ?? ""),
51
+ path: String(args?.path ?? ""),
52
+ expected_sha256: String(args?.expected_sha256 ?? ""),
53
+ operations: Array.isArray(args?.operations) ? args.operations : [],
54
+ }));
55
+ },
56
+ run_verification: async (args) => {
57
+ guardDirectProfileEnabled();
58
+ return toResult(await runVerification({
59
+ session_id: String(args?.session_id ?? ""),
60
+ command: String(args?.command ?? ""),
61
+ timeout_seconds: args?.timeout_seconds ? Number(args.timeout_seconds) : undefined,
62
+ }));
63
+ },
64
+ run_direct_verification_bundle: async (args) => {
65
+ guardDirectProfileEnabled();
66
+ return toResult(await runDirectVerificationBundle({
67
+ session_id: String(args?.session_id ?? ""),
68
+ commands: Array.isArray(args?.commands)
69
+ ? args.commands.map((command) => String(command))
70
+ : [],
71
+ timeout_seconds: args?.timeout_seconds ? Number(args.timeout_seconds) : undefined,
72
+ }));
73
+ },
74
+ finalize_direct_session: async (args) => {
75
+ guardDirectProfileEnabled();
76
+ return toResult(await finalizeDirectSession({
77
+ session_id: String(args?.session_id ?? ""),
78
+ }));
79
+ },
80
+ audit_session: async (args) => {
81
+ guardDirectProfileEnabled();
82
+ return toResult(auditSession({
83
+ session_id: String(args?.session_id ?? ""),
84
+ }));
85
+ },
86
+ safe_direct_summary: async (args) => {
87
+ guardDirectProfileEnabled();
88
+ return toResult(safeDirectSummary(String(args?.session_id ?? ""), {
89
+ max_items: args?.max_items !== undefined ? Number(args.max_items) : undefined,
90
+ }));
91
+ },
92
+ safe_finalize_direct_session: async (args) => {
93
+ guardDirectProfileEnabled();
94
+ return toResult(await safeFinalizeDirectSession(String(args?.session_id ?? ""), {
95
+ max_items: args?.max_items !== undefined ? Number(args.max_items) : undefined,
96
+ }));
97
+ },
98
+ safe_audit_direct_session: async (args) => {
99
+ guardDirectProfileEnabled();
100
+ return toResult(safeAuditDirectSession(String(args?.session_id ?? ""), {
101
+ max_items: args?.max_items !== undefined ? Number(args.max_items) : undefined,
102
+ }));
103
+ },
104
+ sync_file: async (args) => {
105
+ guardDirectProfileEnabled();
106
+ return toResult(syncFile(String(args?.session_id ?? ""), String(args?.source_path ?? ""), String(args?.target_path ?? ""), {
107
+ expected_source_sha256: args?.expected_source_sha256
108
+ ? String(args.expected_source_sha256)
109
+ : undefined,
110
+ expected_target_sha256: args?.expected_target_sha256
111
+ ? String(args.expected_target_sha256)
112
+ : undefined,
113
+ }));
114
+ },
115
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Dispatch handlers for Goal Session tools (v0.8.0+).
3
+ *
4
+ * Covers goal lifecycle, subgoal management, Spec Kit import,
5
+ * worktree merge/discard, and goal reporting.
6
+ */
7
+ import type { ToolHandlerMap } from "./types.js";
8
+ export declare const goalHandlers: ToolHandlerMap;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Dispatch handlers for Goal Session tools (v0.8.0+).
3
+ *
4
+ * Covers goal lifecycle, subgoal management, Spec Kit import,
5
+ * worktree merge/discard, and goal reporting.
6
+ */
7
+ import { createGoal, listGoals, readGoal, readGoalStatus } from "../../goal/goalStore.js";
8
+ import { suggestNextSubgoal } from "../../goal/goalGraph.js";
9
+ import { exportHandoff } from "../../goal/handoffExport.js";
10
+ import { acceptSubgoal, rejectSubgoal, summarizeGoalProgress } from "../../goal/goalProgress.js";
11
+ import { exportGoalReport } from "../../goal/goalReport.js";
12
+ import { importSpecKitTasks, parseSpecKitJson } from "../../goal/specKitImport.js";
13
+ import { createSubgoalTask } from "../goalSubgoalTask.js";
14
+ import { mergeWorktreeTool } from "../mergeWorktree.js";
15
+ import { discardWorktreeTool } from "../discardWorktree.js";
16
+ import { toResult } from "./types.js";
17
+ export const goalHandlers = {
18
+ create_goal: async (args) => {
19
+ return toResult(createGoal(String(args?.repo_path ?? ""), String(args?.title ?? ""), String(args?.goal_description ?? "")));
20
+ },
21
+ list_goals: async () => {
22
+ return toResult({ goals: listGoals() });
23
+ },
24
+ read_goal: async (args) => {
25
+ return toResult(readGoal(String(args?.goal_id ?? "")));
26
+ },
27
+ create_subgoal_task: async (args) => {
28
+ return toResult(await createSubgoalTask({
29
+ goal_id: String(args?.goal_id ?? ""),
30
+ subgoal_title: String(args?.subgoal_title ?? ""),
31
+ depends_on: Array.isArray(args?.depends_on) ? args.depends_on.map(String) : undefined,
32
+ plan_id: args?.plan_id ? String(args.plan_id) : undefined,
33
+ inline_plan: args?.inline_plan ? String(args.inline_plan) : undefined,
34
+ plan_title: args?.plan_title ? String(args.plan_title) : undefined,
35
+ template: args?.template ? String(args.template) : undefined,
36
+ goal: args?.goal ? String(args.goal) : undefined,
37
+ agent: args?.agent ? String(args.agent) : undefined,
38
+ repo_path: String(args?.repo_path ?? ""),
39
+ test_command: args?.test_command ? String(args.test_command) : undefined,
40
+ verify_commands: Array.isArray(args?.verify_commands)
41
+ ? args.verify_commands.map(String)
42
+ : undefined,
43
+ timeout_seconds: args?.timeout_seconds ? Number(args.timeout_seconds) : undefined,
44
+ scope: Array.isArray(args?.scope) ? args.scope.map(String) : undefined,
45
+ forbidden: Array.isArray(args?.forbidden) ? args.forbidden.map(String) : undefined,
46
+ verification: Array.isArray(args?.verification) ? args.verification.map(String) : undefined,
47
+ done_evidence: Array.isArray(args?.done_evidence) ? args.done_evidence.map(String) : undefined,
48
+ isolate_worktree: args?.isolate_worktree === undefined ? undefined : Boolean(args.isolate_worktree),
49
+ }));
50
+ },
51
+ accept_subgoal: async (args) => {
52
+ return toResult(acceptSubgoal(String(args?.goal_id ?? ""), String(args?.subgoal_id ?? "")));
53
+ },
54
+ reject_subgoal: async (args) => {
55
+ return toResult(rejectSubgoal(String(args?.goal_id ?? ""), String(args?.subgoal_id ?? ""), String(args?.reason ?? "")));
56
+ },
57
+ suggest_next_subgoal: async (args) => {
58
+ const goalStatus = readGoalStatus(String(args?.goal_id ?? ""));
59
+ return toResult(suggestNextSubgoal(goalStatus));
60
+ },
61
+ summarize_goal_progress: async (args) => {
62
+ return toResult(summarizeGoalProgress(String(args?.goal_id ?? "")));
63
+ },
64
+ export_handoff: async (args) => {
65
+ const goalId = String(args?.goal_id ?? "");
66
+ const goalStatus = readGoalStatus(goalId);
67
+ return toResult(exportHandoff(goalId, goalStatus));
68
+ },
69
+ export_goal_report: async (args) => {
70
+ const goalId = String(args?.goal_id ?? "");
71
+ return toResult(exportGoalReport(goalId));
72
+ },
73
+ import_speckit_tasks: async (args) => {
74
+ const goalId = String(args?.goal_id ?? "");
75
+ const jsonText = String(args?.spec_kit_json ?? "");
76
+ const input = parseSpecKitJson(jsonText);
77
+ return toResult(importSpecKitTasks(goalId, input));
78
+ },
79
+ merge_worktree: async (args) => {
80
+ return toResult(mergeWorktreeTool({
81
+ worktree_id: String(args?.worktree_id ?? ""),
82
+ repo_path: String(args?.repo_path ?? ""),
83
+ }));
84
+ },
85
+ discard_worktree: async (args) => {
86
+ return toResult(discardWorktreeTool({
87
+ worktree_id: String(args?.worktree_id ?? ""),
88
+ repo_path: String(args?.repo_path ?? ""),
89
+ }));
90
+ },
91
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Dispatch handlers for release-mode tools (v1.3.0+).
3
+ *
4
+ * Wraps releaseCheck, releasePrepare, releaseVerify, and releaseCleanup
5
+ * from releaseMode.ts.
6
+ */
7
+ import type { ToolHandlerMap } from "./types.js";
8
+ export declare const releaseHandlers: ToolHandlerMap;