patchwarden 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/Check-PatchWarden-Health.cmd +6 -0
  2. package/LICENSE +21 -0
  3. package/README.md +526 -0
  4. package/Reset-PatchWarden-Tunnel-Key.cmd +6 -0
  5. package/Restart-PatchWarden.cmd +19 -0
  6. package/Start-PatchWarden-Tunnel.cmd +7 -0
  7. package/dist/config.d.ts +24 -0
  8. package/dist/config.js +131 -0
  9. package/dist/doctor.d.ts +10 -0
  10. package/dist/doctor.js +388 -0
  11. package/dist/errors.d.ts +16 -0
  12. package/dist/errors.js +27 -0
  13. package/dist/httpServer.d.ts +17 -0
  14. package/dist/httpServer.js +255 -0
  15. package/dist/index.d.ts +9 -0
  16. package/dist/index.js +24 -0
  17. package/dist/runner/changeCapture.d.ts +43 -0
  18. package/dist/runner/changeCapture.js +245 -0
  19. package/dist/runner/cli.d.ts +9 -0
  20. package/dist/runner/cli.js +26 -0
  21. package/dist/runner/runTask.d.ts +8 -0
  22. package/dist/runner/runTask.js +821 -0
  23. package/dist/runner/watch.d.ts +19 -0
  24. package/dist/runner/watch.js +136 -0
  25. package/dist/security/commandGuard.d.ts +22 -0
  26. package/dist/security/commandGuard.js +56 -0
  27. package/dist/security/contentRedaction.d.ts +12 -0
  28. package/dist/security/contentRedaction.js +65 -0
  29. package/dist/security/pathGuard.d.ts +3 -0
  30. package/dist/security/pathGuard.js +98 -0
  31. package/dist/security/planGuard.d.ts +1 -0
  32. package/dist/security/planGuard.js +65 -0
  33. package/dist/security/sensitiveGuard.d.ts +2 -0
  34. package/dist/security/sensitiveGuard.js +60 -0
  35. package/dist/smoke-test.d.ts +15 -0
  36. package/dist/smoke-test.js +989 -0
  37. package/dist/taskProgress.d.ts +6 -0
  38. package/dist/taskProgress.js +36 -0
  39. package/dist/taskRuntime.d.ts +10 -0
  40. package/dist/taskRuntime.js +25 -0
  41. package/dist/tools/auditTask.d.ts +19 -0
  42. package/dist/tools/auditTask.js +307 -0
  43. package/dist/tools/cancelTask.d.ts +30 -0
  44. package/dist/tools/cancelTask.js +64 -0
  45. package/dist/tools/createTask.d.ts +42 -0
  46. package/dist/tools/createTask.js +188 -0
  47. package/dist/tools/getPlan.d.ts +12 -0
  48. package/dist/tools/getPlan.js +29 -0
  49. package/dist/tools/getTaskFile.d.ts +24 -0
  50. package/dist/tools/getTaskFile.js +84 -0
  51. package/dist/tools/getTaskProgress.d.ts +1 -0
  52. package/dist/tools/getTaskProgress.js +4 -0
  53. package/dist/tools/getTaskStatus.d.ts +46 -0
  54. package/dist/tools/getTaskStatus.js +36 -0
  55. package/dist/tools/getTaskStdoutTail.d.ts +9 -0
  56. package/dist/tools/getTaskStdoutTail.js +56 -0
  57. package/dist/tools/getTaskSummary.d.ts +66 -0
  58. package/dist/tools/getTaskSummary.js +237 -0
  59. package/dist/tools/healthCheck.d.ts +79 -0
  60. package/dist/tools/healthCheck.js +230 -0
  61. package/dist/tools/killTask.d.ts +15 -0
  62. package/dist/tools/killTask.js +4 -0
  63. package/dist/tools/listAgents.d.ts +12 -0
  64. package/dist/tools/listAgents.js +42 -0
  65. package/dist/tools/listTasks.d.ts +36 -0
  66. package/dist/tools/listTasks.js +94 -0
  67. package/dist/tools/listWorkspace.d.ts +10 -0
  68. package/dist/tools/listWorkspace.js +54 -0
  69. package/dist/tools/readWorkspaceFile.d.ts +8 -0
  70. package/dist/tools/readWorkspaceFile.js +26 -0
  71. package/dist/tools/registry.d.ts +24 -0
  72. package/dist/tools/registry.js +566 -0
  73. package/dist/tools/retryTask.d.ts +8 -0
  74. package/dist/tools/retryTask.js +45 -0
  75. package/dist/tools/savePlan.d.ts +10 -0
  76. package/dist/tools/savePlan.js +28 -0
  77. package/dist/tools/taskOutputs.d.ts +49 -0
  78. package/dist/tools/taskOutputs.js +136 -0
  79. package/dist/tools/taskTemplates.d.ts +15 -0
  80. package/dist/tools/taskTemplates.js +116 -0
  81. package/dist/tools/toolCatalog.d.ts +19 -0
  82. package/dist/tools/toolCatalog.js +71 -0
  83. package/dist/tools/waitForTask.d.ts +25 -0
  84. package/dist/tools/waitForTask.js +59 -0
  85. package/dist/version.d.ts +2 -0
  86. package/dist/version.js +2 -0
  87. package/dist/watcherStatus.d.ts +20 -0
  88. package/dist/watcherStatus.js +77 -0
  89. package/docs/assets/patchwarden-chatgpt-demo.svg +30 -0
  90. package/docs/demo.md +58 -0
  91. package/docs/migration-from-safe-bifrost.md +31 -0
  92. package/docs/release-v0.3.0.md +43 -0
  93. package/docs/release-v0.4.0.md +74 -0
  94. package/examples/config.example.json +40 -0
  95. package/examples/openai-tunnel/README.md +48 -0
  96. package/examples/openai-tunnel/chatgpt-test-prompt.md +53 -0
  97. package/examples/openai-tunnel/tunnel-client.example.yaml +39 -0
  98. package/package.json +73 -0
  99. package/scripts/brand-check.js +44 -0
  100. package/scripts/doctor-smoke.js +52 -0
  101. package/scripts/get-patchwarden-health.ps1 +114 -0
  102. package/scripts/http-mcp-smoke.js +351 -0
  103. package/scripts/lifecycle-smoke.js +453 -0
  104. package/scripts/mcp-manifest-check.js +120 -0
  105. package/scripts/mcp-smoke.js +336 -0
  106. package/scripts/pack-clean.js +142 -0
  107. package/scripts/patchwarden-mcp-stdio.cmd +7 -0
  108. package/scripts/restart-patchwarden.ps1 +242 -0
  109. package/scripts/start-patchwarden-tunnel.ps1 +503 -0
  110. package/scripts/tunnel-supervisor-smoke.js +77 -0
  111. package/scripts/watcher-supervisor-smoke.js +195 -0
  112. package/src/config.ts +165 -0
  113. package/src/doctor.ts +438 -0
  114. package/src/errors.ts +26 -0
  115. package/src/httpServer.ts +277 -0
  116. package/src/index.ts +34 -0
  117. package/src/runner/changeCapture.ts +304 -0
  118. package/src/runner/cli.ts +34 -0
  119. package/src/runner/runTask.ts +935 -0
  120. package/src/runner/watch.ts +152 -0
  121. package/src/security/commandGuard.ts +97 -0
  122. package/src/security/contentRedaction.ts +85 -0
  123. package/src/security/pathGuard.ts +175 -0
  124. package/src/security/planGuard.ts +93 -0
  125. package/src/security/sensitiveGuard.ts +72 -0
  126. package/src/smoke-test.ts +1078 -0
  127. package/src/taskProgress.ts +41 -0
  128. package/src/taskRuntime.ts +37 -0
  129. package/src/tools/auditTask.ts +340 -0
  130. package/src/tools/cancelTask.ts +70 -0
  131. package/src/tools/createTask.ts +337 -0
  132. package/src/tools/getPlan.ts +48 -0
  133. package/src/tools/getTaskFile.ts +111 -0
  134. package/src/tools/getTaskProgress.ts +5 -0
  135. package/src/tools/getTaskStatus.ts +85 -0
  136. package/src/tools/getTaskStdoutTail.ts +61 -0
  137. package/src/tools/getTaskSummary.ts +307 -0
  138. package/src/tools/healthCheck.ts +234 -0
  139. package/src/tools/killTask.ts +5 -0
  140. package/src/tools/listAgents.ts +54 -0
  141. package/src/tools/listTasks.ts +139 -0
  142. package/src/tools/listWorkspace.ts +71 -0
  143. package/src/tools/readWorkspaceFile.ts +41 -0
  144. package/src/tools/registry.ts +666 -0
  145. package/src/tools/retryTask.ts +53 -0
  146. package/src/tools/savePlan.ts +46 -0
  147. package/src/tools/taskOutputs.ts +155 -0
  148. package/src/tools/taskTemplates.ts +162 -0
  149. package/src/tools/toolCatalog.ts +92 -0
  150. package/src/tools/waitForTask.ts +90 -0
  151. package/src/version.ts +2 -0
  152. package/src/watcherStatus.ts +102 -0
  153. package/tsconfig.json +17 -0
@@ -0,0 +1,102 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { getConfig, getTasksDir, type PatchWardenConfig } from "./config.js";
4
+
5
+ export type WatcherState = "healthy" | "stale" | "missing" | "unreadable";
6
+ export type PendingReason =
7
+ | "queued_waiting_for_watcher"
8
+ | "queued_but_watcher_stale"
9
+ | "queued_but_watcher_missing"
10
+ | "queued_but_watcher_unreadable"
11
+ | "agent_running"
12
+ | "verification_running"
13
+ | "preparing"
14
+ | "collecting_artifacts"
15
+ | null;
16
+
17
+ export interface WatcherStatusSnapshot {
18
+ status: WatcherState;
19
+ available: boolean;
20
+ stale_after_seconds: number;
21
+ last_heartbeat_at: string | null;
22
+ heartbeat_age_seconds: number | null;
23
+ heartbeat_pid: number | null;
24
+ instance_id: string | null;
25
+ launcher_pid: number | null;
26
+ reason: string | null;
27
+ }
28
+
29
+ export function getWatcherHeartbeatPath(config: PatchWardenConfig = getConfig()): string {
30
+ return join(dirname(getTasksDir(config)), "watcher-heartbeat.json");
31
+ }
32
+
33
+ export function readWatcherStatus(
34
+ config: PatchWardenConfig = getConfig(),
35
+ nowMs = Date.now()
36
+ ): WatcherStatusSnapshot {
37
+ const staleAfterSeconds = config.watcherStaleSeconds;
38
+ const heartbeatPath = getWatcherHeartbeatPath(config);
39
+ if (!existsSync(heartbeatPath)) {
40
+ return {
41
+ status: "missing",
42
+ available: false,
43
+ stale_after_seconds: staleAfterSeconds,
44
+ last_heartbeat_at: null,
45
+ heartbeat_age_seconds: null,
46
+ heartbeat_pid: null,
47
+ instance_id: null,
48
+ launcher_pid: null,
49
+ reason: "Watcher heartbeat has not been observed. Start or restart the PatchWarden watcher.",
50
+ };
51
+ }
52
+
53
+ try {
54
+ const raw = readFileSync(heartbeatPath, "utf-8");
55
+ const data = JSON.parse(raw.charCodeAt(0) === 0xfeff ? raw.slice(1) : raw);
56
+ const heartbeatMs = Date.parse(String(data.last_heartbeat_at || ""));
57
+ if (!Number.isFinite(heartbeatMs)) throw new Error("invalid heartbeat timestamp");
58
+ const ageMs = Math.max(0, nowMs - heartbeatMs);
59
+ const ageSeconds = Math.round(ageMs / 1000);
60
+ const healthy = ageMs < staleAfterSeconds * 1000;
61
+ return {
62
+ status: healthy ? "healthy" : "stale",
63
+ available: healthy,
64
+ stale_after_seconds: staleAfterSeconds,
65
+ last_heartbeat_at: String(data.last_heartbeat_at),
66
+ heartbeat_age_seconds: ageSeconds,
67
+ heartbeat_pid: Number.isInteger(Number(data.pid)) ? Number(data.pid) : null,
68
+ instance_id: typeof data.instance_id === "string" ? data.instance_id : null,
69
+ launcher_pid: Number.isInteger(Number(data.launcher_pid)) ? Number(data.launcher_pid) : null,
70
+ reason: healthy ? null : "Watcher heartbeat is stale. Restart the PatchWarden watcher.",
71
+ };
72
+ } catch {
73
+ return {
74
+ status: "unreadable",
75
+ available: false,
76
+ stale_after_seconds: staleAfterSeconds,
77
+ last_heartbeat_at: null,
78
+ heartbeat_age_seconds: null,
79
+ heartbeat_pid: null,
80
+ instance_id: null,
81
+ launcher_pid: null,
82
+ reason: "Watcher heartbeat file is unreadable.",
83
+ };
84
+ }
85
+ }
86
+
87
+ export function derivePendingReason(
88
+ task: { status?: string; phase?: string },
89
+ watcher: WatcherStatusSnapshot
90
+ ): PendingReason {
91
+ if (task.status === "pending") {
92
+ if (watcher.status === "stale") return "queued_but_watcher_stale";
93
+ if (watcher.status === "missing") return "queued_but_watcher_missing";
94
+ if (watcher.status === "unreadable") return "queued_but_watcher_unreadable";
95
+ return "queued_waiting_for_watcher";
96
+ }
97
+ if (task.status !== "running") return null;
98
+ if (task.phase === "executing_agent") return "agent_running";
99
+ if (task.phase === "running_tests") return "verification_running";
100
+ if (task.phase === "collecting_artifacts") return "collecting_artifacts";
101
+ return "preparing";
102
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "node",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "resolveJsonModule": true,
12
+ "declaration": true,
13
+ "skipLibCheck": true
14
+ },
15
+ "include": ["src/**/*.ts"],
16
+ "exclude": ["node_modules", "dist"]
17
+ }