patchwarden 0.6.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PatchWarden-Control-Tray.cmd +11 -0
- package/PatchWarden-Control.cmd +6 -0
- package/PatchWarden-Desktop.cmd +5 -0
- package/PatchWarden.cmd +1 -1
- package/README.en.md +112 -24
- package/README.md +36 -25
- package/Restart-PatchWarden-Control.cmd +6 -0
- package/Stop-PatchWarden.cmd +11 -0
- package/dist/agents/agentRouter.d.ts +40 -0
- package/dist/agents/agentRouter.js +95 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +6 -2
- package/dist/controlCenter.d.ts +14 -0
- package/dist/controlCenter.js +2015 -0
- package/dist/doctor.js +35 -4
- package/dist/goal/acceptanceEngine.d.ts +62 -0
- package/dist/goal/acceptanceEngine.js +103 -0
- package/dist/goal/acceptanceTemplate.d.ts +10 -0
- package/dist/goal/acceptanceTemplate.js +104 -0
- package/dist/goal/goalGraph.d.ts +58 -0
- package/dist/goal/goalGraph.js +189 -0
- package/dist/goal/goalProgress.d.ts +81 -0
- package/dist/goal/goalProgress.js +216 -0
- package/dist/goal/goalStatus.d.ts +60 -0
- package/dist/goal/goalStatus.js +137 -0
- package/dist/goal/goalStore.d.ts +79 -0
- package/dist/goal/goalStore.js +211 -0
- package/dist/goal/handoffExport.d.ts +34 -0
- package/dist/goal/handoffExport.js +183 -0
- package/dist/goal/subgoalSync.d.ts +40 -0
- package/dist/goal/subgoalSync.js +72 -0
- package/dist/goal/worktreeManager.d.ts +96 -0
- package/dist/goal/worktreeManager.js +292 -0
- package/dist/logging.d.ts +44 -0
- package/dist/logging.js +68 -0
- package/dist/release/releaseGate.d.ts +99 -0
- package/dist/release/releaseGate.js +475 -0
- package/dist/runner/postTaskCleanup.d.ts +13 -0
- package/dist/runner/postTaskCleanup.js +147 -0
- package/dist/runner/runTask.js +50 -10
- package/dist/security/discoveryTokenStore.d.ts +62 -0
- package/dist/security/discoveryTokenStore.js +100 -0
- package/dist/security/toolInvocationGuard.d.ts +35 -0
- package/dist/security/toolInvocationGuard.js +153 -0
- package/dist/smoke-test.js +18 -10
- package/dist/taskRuntime.d.ts +17 -0
- package/dist/test/unit/acceptance-engine.test.d.ts +1 -0
- package/dist/test/unit/acceptance-engine.test.js +228 -0
- package/dist/test/unit/agent-router.test.d.ts +1 -0
- package/dist/test/unit/agent-router.test.js +287 -0
- package/dist/test/unit/audit-checks.test.d.ts +1 -0
- package/dist/test/unit/audit-checks.test.js +350 -0
- package/dist/test/unit/diagnose-task.test.d.ts +1 -0
- package/dist/test/unit/diagnose-task.test.js +457 -0
- package/dist/test/unit/discovery-token-store.test.d.ts +1 -0
- package/dist/test/unit/discovery-token-store.test.js +139 -0
- package/dist/test/unit/goal-graph.test.d.ts +1 -0
- package/dist/test/unit/goal-graph.test.js +298 -0
- package/dist/test/unit/goal-progress.test.d.ts +1 -0
- package/dist/test/unit/goal-progress.test.js +381 -0
- package/dist/test/unit/goal-status.test.d.ts +1 -0
- package/dist/test/unit/goal-status.test.js +215 -0
- package/dist/test/unit/goal-store.test.d.ts +1 -0
- package/dist/test/unit/goal-store.test.js +253 -0
- package/dist/test/unit/goal-subgoal-task.test.d.ts +1 -0
- package/dist/test/unit/goal-subgoal-task.test.js +55 -0
- package/dist/test/unit/goal-tools-registry.test.d.ts +1 -0
- package/dist/test/unit/goal-tools-registry.test.js +190 -0
- package/dist/test/unit/handoff-export.test.d.ts +1 -0
- package/dist/test/unit/handoff-export.test.js +263 -0
- package/dist/test/unit/invoke-discovered-tool.test.d.ts +1 -0
- package/dist/test/unit/invoke-discovered-tool.test.js +167 -0
- package/dist/test/unit/logging.test.js +127 -5
- package/dist/test/unit/post-task-cleanup.test.d.ts +1 -0
- package/dist/test/unit/post-task-cleanup.test.js +48 -0
- package/dist/test/unit/reconcile-tasks.test.d.ts +1 -0
- package/dist/test/unit/reconcile-tasks.test.js +456 -0
- package/dist/test/unit/release-gate.test.d.ts +1 -0
- package/dist/test/unit/release-gate.test.js +242 -0
- package/dist/test/unit/safe-views.test.d.ts +1 -0
- package/dist/test/unit/safe-views.test.js +171 -0
- package/dist/test/unit/schema-drift-check.test.d.ts +1 -0
- package/dist/test/unit/schema-drift-check.test.js +175 -0
- package/dist/test/unit/subgoal-sync.test.d.ts +1 -0
- package/dist/test/unit/subgoal-sync.test.js +183 -0
- package/dist/test/unit/tool-invocation-guard.test.d.ts +1 -0
- package/dist/test/unit/tool-invocation-guard.test.js +432 -0
- package/dist/test/unit/tool-usage-stats.test.d.ts +1 -0
- package/dist/test/unit/tool-usage-stats.test.js +300 -0
- package/dist/test/unit/toolSearch.test.d.ts +1 -0
- package/dist/test/unit/toolSearch.test.js +571 -0
- package/dist/test/unit/worktree-manager.test.d.ts +1 -0
- package/dist/test/unit/worktree-manager.test.js +176 -0
- package/dist/tools/auditTask.d.ts +103 -1
- package/dist/tools/auditTask.js +461 -8
- package/dist/tools/cancelTask.js +1 -1
- package/dist/tools/checkReleaseGate.d.ts +21 -0
- package/dist/tools/checkReleaseGate.js +22 -0
- package/dist/tools/createTask.d.ts +18 -2
- package/dist/tools/createTask.js +29 -1
- package/dist/tools/diagnoseTask.d.ts +45 -0
- package/dist/tools/diagnoseTask.js +347 -0
- package/dist/tools/discardWorktree.d.ts +24 -0
- package/dist/tools/discardWorktree.js +27 -0
- package/dist/tools/discoverTools.d.ts +11 -0
- package/dist/tools/discoverTools.js +39 -0
- package/dist/tools/explainTool.d.ts +11 -0
- package/dist/tools/explainTool.js +21 -0
- package/dist/tools/getTaskSummary.js +2 -1
- package/dist/tools/goalSubgoalTask.d.ts +51 -0
- package/dist/tools/goalSubgoalTask.js +110 -0
- package/dist/tools/healthCheck.d.ts +1 -0
- package/dist/tools/healthCheck.js +5 -1
- package/dist/tools/invokeDiscoveredTool.d.ts +37 -0
- package/dist/tools/invokeDiscoveredTool.js +112 -0
- package/dist/tools/listTasks.d.ts +3 -1
- package/dist/tools/listTasks.js +14 -1
- package/dist/tools/mergeWorktree.d.ts +24 -0
- package/dist/tools/mergeWorktree.js +27 -0
- package/dist/tools/reconcileTasks.d.ts +41 -0
- package/dist/tools/reconcileTasks.js +352 -0
- package/dist/tools/registry.js +550 -0
- package/dist/tools/safeStatus.d.ts +31 -1
- package/dist/tools/safeStatus.js +43 -1
- package/dist/tools/safeViews.d.ts +256 -0
- package/dist/tools/safeViews.js +250 -0
- package/dist/tools/schemaDriftCheck.d.ts +46 -0
- package/dist/tools/schemaDriftCheck.js +80 -0
- package/dist/tools/toolCatalog.d.ts +4 -3
- package/dist/tools/toolCatalog.js +33 -11
- package/dist/tools/toolRegistry.d.ts +61 -0
- package/dist/tools/toolRegistry.js +724 -0
- package/dist/tools/toolSearch.d.ts +110 -0
- package/dist/tools/toolSearch.js +331 -0
- package/dist/tools/toolUsageStats.d.ts +41 -0
- package/dist/tools/toolUsageStats.js +116 -0
- package/dist/tools/waitForTask.js +1 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/watcherStatus.d.ts +29 -0
- package/dist/watcherStatus.js +92 -1
- package/docs/control-center/README.md +33 -0
- package/docs/control-center/control-center-daily-driver.md +211 -0
- package/docs/control-center/control-center-mvp.md +205 -0
- package/docs/control-center/control-center-phase2.md +159 -0
- package/docs/demo.md +3 -0
- package/docs/release-v0.6.4.md +45 -0
- package/examples/openai-tunnel/README.md +5 -5
- package/examples/openai-tunnel/tunnel-client.example.yaml +3 -3
- package/package.json +25 -16
- package/scripts/README.md +47 -0
- package/scripts/{brand-check.js → checks/brand-check.js} +2 -2
- package/scripts/checks/control-center-smoke.js +1098 -0
- package/scripts/{control-smoke.js → checks/control-smoke.js} +19 -5
- package/scripts/{doctor-smoke.js → checks/doctor-smoke.js} +2 -1
- package/scripts/{http-mcp-smoke.js → checks/http-mcp-smoke.js} +2 -2
- package/scripts/{lifecycle-smoke.js → checks/lifecycle-smoke.js} +25 -21
- package/scripts/{mcp-manifest-check.js → checks/mcp-manifest-check.js} +54 -7
- package/scripts/{mcp-smoke.js → checks/mcp-smoke.js} +40 -11
- package/scripts/{package-manifest-check.js → checks/package-manifest-check.js} +2 -1
- package/scripts/{tunnel-supervisor-smoke.js → checks/tunnel-supervisor-smoke.js} +2 -2
- package/scripts/{unit-tests.js → checks/unit-tests.js} +1 -1
- package/scripts/{watcher-supervisor-smoke.js → checks/watcher-supervisor-smoke.js} +13 -7
- package/scripts/control/control-center-tray.ps1 +281 -0
- package/scripts/{get-patchwarden-health.ps1 → control/get-patchwarden-health.ps1} +3 -3
- package/scripts/{manage-patchwarden.ps1 → control/manage-patchwarden.ps1} +30 -4
- package/scripts/control/restart-control-center.ps1 +173 -0
- package/scripts/{restart-patchwarden.ps1 → control/restart-patchwarden.ps1} +1 -1
- package/scripts/control/start-control-center.ps1 +263 -0
- package/scripts/{start-patchwarden-tunnel.ps1 → control/start-patchwarden-tunnel.ps1} +48 -6
- package/scripts/control/stop-patchwarden.ps1 +114 -0
- package/scripts/launchers/Check-PatchWarden-Health.cmd +1 -1
- package/scripts/launchers/Reset-PatchWarden-Tunnel-Key.cmd +1 -1
- package/scripts/launchers/Restart-PatchWarden.cmd +1 -1
- package/scripts/launchers/Start-PatchWarden-Direct-Tunnel.cmd +1 -1
- package/scripts/launchers/Start-PatchWarden-Tunnel.cmd +1 -1
- package/scripts/{patchwarden-mcp-direct.cmd → mcp/patchwarden-mcp-direct.cmd} +1 -1
- package/scripts/{patchwarden-mcp-stdio.cmd → mcp/patchwarden-mcp-stdio.cmd} +1 -1
- package/scripts/{pack-clean.js → release/pack-clean.js} +9 -1
- package/src/agents/agentRouter.ts +149 -0
- package/src/config.ts +9 -3
- package/src/controlCenter.ts +2166 -0
- package/src/doctor.ts +40 -5
- package/src/goal/acceptanceEngine.ts +160 -0
- package/src/goal/acceptanceTemplate.ts +121 -0
- package/src/goal/goalGraph.ts +225 -0
- package/src/goal/goalProgress.ts +301 -0
- package/src/goal/goalStatus.ts +234 -0
- package/src/goal/goalStore.ts +306 -0
- package/src/goal/handoffExport.ts +211 -0
- package/src/goal/subgoalSync.ts +82 -0
- package/src/goal/worktreeManager.ts +404 -0
- package/src/logging.ts +91 -0
- package/src/release/releaseGate.ts +567 -0
- package/src/runner/postTaskCleanup.ts +154 -0
- package/src/runner/runTask.ts +49 -10
- package/src/security/discoveryTokenStore.ts +157 -0
- package/src/security/toolInvocationGuard.ts +251 -0
- package/src/smoke-test.ts +15 -7
- package/src/taskRuntime.ts +17 -0
- package/src/test/unit/acceptance-engine.test.ts +261 -0
- package/src/test/unit/agent-router.test.ts +342 -0
- package/src/test/unit/audit-checks.test.ts +567 -0
- package/src/test/unit/diagnose-task.test.ts +544 -0
- package/src/test/unit/discovery-token-store.test.ts +181 -0
- package/src/test/unit/goal-graph.test.ts +347 -0
- package/src/test/unit/goal-progress.test.ts +538 -0
- package/src/test/unit/goal-status.test.ts +270 -0
- package/src/test/unit/goal-store.test.ts +318 -0
- package/src/test/unit/goal-subgoal-task.test.ts +72 -0
- package/src/test/unit/goal-tools-registry.test.ts +243 -0
- package/src/test/unit/handoff-export.test.ts +295 -0
- package/src/test/unit/invoke-discovered-tool.test.ts +216 -0
- package/src/test/unit/logging.test.ts +177 -5
- package/src/test/unit/post-task-cleanup.test.ts +53 -0
- package/src/test/unit/reconcile-tasks.test.ts +551 -0
- package/src/test/unit/release-gate.test.ts +314 -0
- package/src/test/unit/safe-views.test.ts +184 -0
- package/src/test/unit/schema-drift-check.test.ts +258 -0
- package/src/test/unit/subgoal-sync.test.ts +236 -0
- package/src/test/unit/tool-invocation-guard.test.ts +542 -0
- package/src/test/unit/tool-usage-stats.test.ts +384 -0
- package/src/test/unit/toolSearch.test.ts +756 -0
- package/src/test/unit/worktree-manager.test.ts +247 -0
- package/src/tools/auditTask.ts +831 -402
- package/src/tools/cancelTask.ts +1 -1
- package/src/tools/checkReleaseGate.ts +45 -0
- package/src/tools/createTask.ts +64 -6
- package/src/tools/diagnoseTask.ts +460 -0
- package/src/tools/discardWorktree.ts +42 -0
- package/src/tools/discoverTools.ts +51 -0
- package/src/tools/explainTool.ts +26 -0
- package/src/tools/getTaskSummary.ts +2 -1
- package/src/tools/goalSubgoalTask.ts +170 -0
- package/src/tools/healthCheck.ts +4 -1
- package/src/tools/invokeDiscoveredTool.ts +163 -0
- package/src/tools/listTasks.ts +16 -2
- package/src/tools/mergeWorktree.ts +42 -0
- package/src/tools/reconcileTasks.ts +464 -0
- package/src/tools/registry.ts +618 -1
- package/src/tools/safeStatus.ts +73 -2
- package/src/tools/safeViews.ts +271 -0
- package/src/tools/schemaDriftCheck.ts +120 -0
- package/src/tools/toolCatalog.ts +34 -11
- package/src/tools/toolRegistry.ts +786 -0
- package/src/tools/toolSearch.ts +464 -0
- package/src/tools/toolUsageStats.ts +151 -0
- package/src/tools/waitForTask.ts +1 -0
- package/src/version.ts +2 -2
- package/src/watcherStatus.ts +97 -1
- package/ui/colors_and_type.css +141 -0
- package/ui/pages/audit.html +743 -0
- package/ui/pages/dashboard.html +1154 -0
- package/ui/pages/direct-sessions.html +652 -0
- package/ui/pages/logs.html +502 -0
- package/ui/pages/task-detail.html +1229 -0
- package/ui/pages/tasks.html +702 -0
- package/ui/pages/workspace.html +947 -0
- package/ui/partials/project-shell.html +362 -0
- package/ui/vendor/lucide.js +12 -0
- package/ui/vendor/tailwindcss-browser.js +947 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# PatchWarden Control Center Phase 2
|
|
2
|
+
|
|
3
|
+
> v0.6.3 在 v0.6.2 MVP 基础上增强任务、工作区、Direct session 和日志体验。
|
|
4
|
+
> 不重构架构,不合并 Core/Direct MCP,不改现有 MCP 工具注册逻辑。
|
|
5
|
+
> 不发布 npm,不打 git tag。
|
|
6
|
+
|
|
7
|
+
## 概述
|
|
8
|
+
|
|
9
|
+
Phase 2 完全在 Control Center HTTP 层增强,未触动 MCP 工具注册、watcher 核心循环或
|
|
10
|
+
Direct session 写入逻辑。新增的 API 全部沿用既有 token 校验、路径围栏和脱敏机制。
|
|
11
|
+
|
|
12
|
+
- **Stale Task 管理**:4 条规则识别僵死任务,reconcile 只标注不删除
|
|
13
|
+
- **task-detail 增强**:变更文件、验证摘要、警告/错误、stale 横幅 + 4 个动作按钮
|
|
14
|
+
- **工作区按需 git 状态**:仅在用户点击时对单个 repo 执行 `git status --short`
|
|
15
|
+
- **Direct Sessions 页面**:浏览 `.patchwarden/direct-sessions` 下的会话产物
|
|
16
|
+
- **Logs 页面**:core/direct/watcher/control-center 四类日志,支持 tail 100/300/1000
|
|
17
|
+
|
|
18
|
+
## 启动方式
|
|
19
|
+
|
|
20
|
+
启动方式与 MVP 完全一致,无新增入口:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
.\PatchWarden-Control.cmd
|
|
24
|
+
# 或
|
|
25
|
+
npm.cmd run build
|
|
26
|
+
npm.cmd run start:control
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
启动后访问 `http://127.0.0.1:8090`,左侧导航新增「Direct 会话」和「日志」两项。
|
|
30
|
+
|
|
31
|
+
## 改动文件
|
|
32
|
+
|
|
33
|
+
| 文件 | 改动 |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| `src/version.ts` | `PATCHWARDEN_VERSION` 0.6.2 → 0.6.3 |
|
|
36
|
+
| `package.json` | `version` 0.6.2 → 0.6.3 |
|
|
37
|
+
| `src/controlCenter.ts` | 新增 stale/reconcile/task-detail 增强/workspace repo status/direct sessions/logs 分类等 API |
|
|
38
|
+
| `ui/pages/dashboard.html` | 侧边栏新增 Direct 会话 + 日志导航 |
|
|
39
|
+
| `ui/pages/tasks.html` | 侧边栏新增 Direct 会话 + 日志导航 |
|
|
40
|
+
| `ui/pages/task-detail.html` | 新增变更文件卡、验证摘要卡、警告/错误卡、stale 横幅、Refresh/Copy task_id/Open folder/Run audit/Reconcile 按钮 |
|
|
41
|
+
| `ui/pages/workspace.html` | 每个 repo 新增「检查」按钮,按需调用 `/api/workspace/:repo/status`,渲染 git 状态面板 |
|
|
42
|
+
| `ui/pages/audit.html` | 侧边栏新增 Direct 会话 + 日志导航 |
|
|
43
|
+
| `ui/pages/direct-sessions.html` | 新页面:会话列表 + 会话详情(summary.md / audit.md / audit.json / diff.patch / changed-files.json) |
|
|
44
|
+
| `ui/pages/logs.html` | 新页面:分类选择 + tail 选择 + 自动刷新开关 |
|
|
45
|
+
| `scripts/checks/control-center-smoke.js` | 新增 Test 11–15 覆盖 Phase 2 API |
|
|
46
|
+
| `docs/control-center/control-center-phase2.md` | 本文档 |
|
|
47
|
+
|
|
48
|
+
## 新增 API
|
|
49
|
+
|
|
50
|
+
### GET 接口(免 token)
|
|
51
|
+
|
|
52
|
+
| 路径 | 说明 |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| `GET /api/tasks/stale` | 返回当前判定为 stale 的任务列表(含 stale_reasons) |
|
|
55
|
+
| `GET /api/tasks/:taskId` | 增强详情:新增 `changed_files`、`file_stats`、`verification_summary`、`warnings`、`errors`、`stale`、`reconcile`、`task_dir`、`independent_review`、`verify_log` |
|
|
56
|
+
| `GET /api/workspace/:repo/status` | 对单个 repo 执行 `git status --short`,返回 changed_files_count/untracked_count/modified_count/is_clean/short_status |
|
|
57
|
+
| `GET /api/direct-sessions` | 列出 `.patchwarden/direct-sessions` 下所有会话摘要 |
|
|
58
|
+
| `GET /api/direct-sessions/:sessionId` | 返回会话详情:summary/session/summary_md/diff_patch/audit_json/audit_md/changed_files |
|
|
59
|
+
| `GET /api/logs/:category?tail=<100\|300\|1000>` | 四类日志(core/direct/watcher/control-center),支持 tail 行数 |
|
|
60
|
+
|
|
61
|
+
### POST 接口(必须校验 token)
|
|
62
|
+
|
|
63
|
+
| 路径 | 说明 |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `POST /api/tasks/:taskId/reconcile` | 标注 stale/archived,写入 `reconcile.json`,不删除任务 |
|
|
66
|
+
| `POST /api/tasks/:taskId/audit` | 仅当任务处于终态时委托 `auditTask` 运行独立审计 |
|
|
67
|
+
| `POST /api/tasks/:taskId/open-folder` | 通过系统命令打开任务目录 |
|
|
68
|
+
|
|
69
|
+
## Stale Task 判定规则
|
|
70
|
+
|
|
71
|
+
`classifyStaleTask` 仅对 `pending` / `running` 状态任务判定(终态任务直接返回非 stale)。
|
|
72
|
+
判定使用 `config.watcherStaleSeconds` 作为阈值,4 条规则任一命中即标记 stale:
|
|
73
|
+
|
|
74
|
+
| 规则 | 字段值 | 说明 |
|
|
75
|
+
| --- | --- | --- |
|
|
76
|
+
| `heartbeat_stale` | status=running 且 last_heartbeat_at 超过阈值 | 运行中但心跳长时间未更新 |
|
|
77
|
+
| `collecting_artifacts_stale` | phase=collecting_artifacts 且心跳超过阈值 | 卡在产物收集阶段 |
|
|
78
|
+
| `running_no_command_watcher_healthy` | status=running 且 current_command 为空且 watcher healthy | 运行中无命令但 watcher 在工作,疑似僵死 |
|
|
79
|
+
| `heartbeat_far_behind_watcher` | 任务心跳比 watcher 心跳早 2× 阈值以上且 watcher healthy | 任务明显落后于 watcher |
|
|
80
|
+
|
|
81
|
+
`/api/status` 和 `/api/tasks` 返回的任务对象均带 `is_stale: boolean` 和
|
|
82
|
+
`stale_reasons: string[]`。`/api/status.tasks` 还聚合了 `stale` 计数和
|
|
83
|
+
`stale_task_ids` 列表。
|
|
84
|
+
|
|
85
|
+
## Reconcile 行为
|
|
86
|
+
|
|
87
|
+
`POST /api/tasks/:taskId/reconcile` 的安全契约:
|
|
88
|
+
|
|
89
|
+
- **不删除任务**,不修改 `status` 枚举值
|
|
90
|
+
- 读取 `status.json` / `runtime.json` 重建 `TaskEntry`,重新调用 `classifyStaleTask`
|
|
91
|
+
- 决策(`decision` 字段):
|
|
92
|
+
- `marked_archived`:任务已处于终态 → 标注归档
|
|
93
|
+
- `marked_stale`:stale 且 watcher 未在驱动(无 current_command 或 watcher 非 healthy)→ 标注僵死
|
|
94
|
+
- `no_action`:不满足上述条件 → 仅记录,不标注
|
|
95
|
+
- 写入 `tasks/<taskId>/reconcile.json`(完整决策记录)
|
|
96
|
+
- 仅当 `safe=true` 时,在 `status.json` 追加 `reconcile_state`(`"stale"` 或 `"archived"`)和 `reconciled_at`,**原 status 字段保持不变**
|
|
97
|
+
- 返回 reconcile 记录 JSON
|
|
98
|
+
|
|
99
|
+
## 路径围栏(workspace repo status)
|
|
100
|
+
|
|
101
|
+
`GET /api/workspace/:repo/status` 的安全约束:
|
|
102
|
+
|
|
103
|
+
- `repo` 参数经 `decodeURIComponent` 后若包含 `..` 或 `\0` → 直接 400
|
|
104
|
+
- 通过 `guardWorkspacePath(repo, workspaceRoot)` 解析为绝对路径,任何逃逸 `workspaceRoot` 的路径 → 400
|
|
105
|
+
- 仅对解析后的目录执行 `git status --short`,超时 8 秒,maxBuffer 1MB
|
|
106
|
+
- 非 git 仓库或 git 不可用时返回 200 + `is_git_repo: false` + error 字段,不返回 500
|
|
107
|
+
- smoke test 用 `encodeURIComponent("../secret")` 验证穿越被拒(400)
|
|
108
|
+
|
|
109
|
+
## Direct Sessions 数据来源
|
|
110
|
+
|
|
111
|
+
- 会话目录:`getDirectSessionsDir(config)` → `<runtime>/.patchwarden/direct-sessions/`
|
|
112
|
+
- 每个会话子目录读取:`session.json`、`summary.json`、`audit.json`、`summary.md`、`diff.patch`、`audit.md`、`changed-files.json`
|
|
113
|
+
- `DirectSessionSummary` 字段:`session_id`、`repo_path`、`resolved_repo_path`、`created_at`、`expires_at`、`finalized`、`finalized_at`、`audited`、`changed_files_total`、`verification_summary`、`audit_decision`、`audit_checked_at`、`title`
|
|
114
|
+
- 目录不存在时返回 `{ sessions: [], total: 0, reason: null }`,**不返回 500**
|
|
115
|
+
- 会话按 `created_at` 降序排列
|
|
116
|
+
|
|
117
|
+
## 日志脱敏
|
|
118
|
+
|
|
119
|
+
- 所有 `/api/logs/:category` 响应均经 `redactSensitiveContent` 脱敏
|
|
120
|
+
- tail 行数限制在 `ALLOWED_LOG_TAILS = {100, 300, 1000}`,非法值回退到 100
|
|
121
|
+
- 日志文件缺失时返回 `{ stdout: "", stderr: "", reason: "log file not found" }`
|
|
122
|
+
|
|
123
|
+
## 冒烟测试
|
|
124
|
+
|
|
125
|
+
`scripts/checks/control-center-smoke.js` 在原 10 项基础上新增 5 项(共 16 项):
|
|
126
|
+
|
|
127
|
+
| # | 测试 |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| 11 | `GET /api/tasks/stale` 返回有效 JSON(`stale_tasks` 数组、`total` 数字、`stale_threshold_seconds` 数字) |
|
|
130
|
+
| 12 | `GET /api/workspace/<traversal>/status` 被拒绝(400,error 含 "traversal") |
|
|
131
|
+
| 13 | `POST /api/tasks/:taskId/reconcile` 无 token → 403 |
|
|
132
|
+
| 14 | `GET /api/direct-sessions` 目录缺失时返回空列表(200,非 500) |
|
|
133
|
+
| 15 | `GET /api/logs/core?tail=300` 响应包含 `tail: 300` |
|
|
134
|
+
|
|
135
|
+
## 测试结果
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
npm.cmd run build # tsc 编译通过
|
|
139
|
+
node scripts/checks/control-center-smoke.js
|
|
140
|
+
# Summary: 16 passed, 0 failed
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
全量 `npm test` 链路(security 139 + unit 136 + lifecycle 22 + control-center 16)
|
|
144
|
+
全部通过,0 失败。
|
|
145
|
+
|
|
146
|
+
> 注:在 TRAE IDE 沙盒内运行 `npm test` 时,control-center-smoke spawn 的子进程退出
|
|
147
|
+
> 后 Windows 会尝试更新 jump list 临时文件,被沙盒拒绝并打印
|
|
148
|
+
> "TRAE Sandbox Error: hit restricted …CustomDestinations…"。该错误与测试逻辑无关,
|
|
149
|
+
> 所有测试用例均报告 PASS。直接运行 `node scripts/checks/control-center-smoke.js` 退出码为 0。
|
|
150
|
+
|
|
151
|
+
## 已知限制
|
|
152
|
+
|
|
153
|
+
- `/api/workspace/:repo/status` 仅运行 `git status --short`,不返回 diff 或 stash 信息
|
|
154
|
+
- reconcile 不会清理任务文件,需人工后续处理或由 watcher 在下个周期自然覆盖
|
|
155
|
+
- `/api/tasks/:taskId/audit` 仅在任务处于终态(done/failed/failed_verification/
|
|
156
|
+
failed_scope_violation/failed_policy_violation/canceled/timeout)时才执行,否则返回 409
|
|
157
|
+
- Direct Sessions 页面只读,不提供 finalize 或 audit 触发入口(这些操作仍需通过 MCP 工具完成)
|
|
158
|
+
- Logs 页面的自动刷新间隔固定为 5 秒,不读取 watcher 实时事件
|
|
159
|
+
- task-detail 的「Open task folder」按钮通过 `explorer.exe` / `open` / `xdg-open` 打开,需要本地图形环境
|
package/docs/demo.md
CHANGED
|
@@ -42,7 +42,10 @@ Expected artifacts under the configured workspace:
|
|
|
42
42
|
```text
|
|
43
43
|
.patchwarden/tasks/<task_id>/status.json
|
|
44
44
|
.patchwarden/tasks/<task_id>/result.md
|
|
45
|
+
.patchwarden/tasks/<task_id>/result.json
|
|
46
|
+
.patchwarden/tasks/<task_id>/artifact_manifest.json
|
|
45
47
|
.patchwarden/tasks/<task_id>/git.diff
|
|
48
|
+
.patchwarden/tasks/<task_id>/verify.json
|
|
46
49
|
.patchwarden/tasks/<task_id>/test.log
|
|
47
50
|
```
|
|
48
51
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# PatchWarden v0.6.4 Release Notes
|
|
2
|
+
|
|
3
|
+
**Release Date**: 2026-06-26
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
PatchWarden v0.6.4 is a desktop experience release. It keeps the existing CLI and script surface, but makes the normal Windows workflow feel like a lightweight local application: start one desktop entry, control Core/Direct from the tray or Web dashboard, and shut everything down from one stop command.
|
|
8
|
+
|
|
9
|
+
## Desktop Entry
|
|
10
|
+
|
|
11
|
+
- Added `PatchWarden-Desktop.cmd` as the recommended daily entry point.
|
|
12
|
+
- The desktop entry starts the tray in a hidden PowerShell host and ensures the local Control Center is available.
|
|
13
|
+
- It does not automatically open a browser window. Use **Open Dashboard** from the tray or `PatchWarden-Control.cmd` when you want the full Web console.
|
|
14
|
+
- `PatchWarden-Control-Tray.cmd --foreground` remains available for tray debugging.
|
|
15
|
+
|
|
16
|
+
## Tray Improvements
|
|
17
|
+
|
|
18
|
+
- Added single-instance protection for the tray process.
|
|
19
|
+
- Replaced the generic system icon path with a small PatchWarden-styled shield icon drawn through WinForms/System.Drawing.
|
|
20
|
+
- Kept the tray as a lightweight switch layer: Open Dashboard, Status, Start All, Stop All, Restart All, Open Logs, and Quit Tray.
|
|
21
|
+
- Added clearer balloon/status feedback for startup and lifecycle actions.
|
|
22
|
+
- Clarified action semantics: **Stop All** stops Core/Direct and leaves tray/dashboard available; **Quit Tray** exits only the tray; `Stop-PatchWarden.cmd` performs full shutdown.
|
|
23
|
+
|
|
24
|
+
## Background Lifecycle
|
|
25
|
+
|
|
26
|
+
- Control Center now invokes `manage-patchwarden.ps1` with `-Background` and `windowsHide: true` for lifecycle API calls.
|
|
27
|
+
- The manager starts Core/Direct supervisors hidden for desktop/Web flows, while preserving visible launcher windows for explicit CLI/debug usage.
|
|
28
|
+
- Added `-NoTunnelWebUi` to `start-patchwarden-tunnel.ps1` so background starts do not open tunnel-client Web UI tabs.
|
|
29
|
+
|
|
30
|
+
## Verification
|
|
31
|
+
|
|
32
|
+
- TypeScript build: PASS
|
|
33
|
+
- Control smoke: PASS
|
|
34
|
+
- Control Center smoke: PASS (23 passed, 0 failed)
|
|
35
|
+
- Package manifest check: PASS
|
|
36
|
+
- PowerShell control script parse check: PASS
|
|
37
|
+
- Manual desktop-flow evidence: desktop entry starts only tray + Control Center; Start/Restart uses hidden supervisors; Stop-PatchWarden closes Core/Direct, Control Center, and tray.
|
|
38
|
+
|
|
39
|
+
## Migration
|
|
40
|
+
|
|
41
|
+
No breaking changes. Existing CLI commands and compatibility launchers remain available. For daily Windows use, prefer:
|
|
42
|
+
|
|
43
|
+
```powershell
|
|
44
|
+
.\PatchWarden-Desktop.cmd
|
|
45
|
+
```
|
|
@@ -15,7 +15,7 @@ or local private paths.
|
|
|
15
15
|
|
|
16
16
|
1. Configure `patchwarden.config.json`.
|
|
17
17
|
2. Run `npm.cmd run build`.
|
|
18
|
-
3. Use `scripts/patchwarden-mcp-stdio.cmd` as the tunnel MCP command.
|
|
18
|
+
3. Use `scripts/mcp/patchwarden-mcp-stdio.cmd` as the tunnel MCP command.
|
|
19
19
|
4. Start `npm.cmd run watch` in a separate terminal.
|
|
20
20
|
5. Start `tunnel-client run` or use `PatchWarden.cmd start core`.
|
|
21
21
|
6. Create a ChatGPT Connector using the tunnel channel.
|
|
@@ -25,10 +25,10 @@ or local private paths.
|
|
|
25
25
|
|
|
26
26
|
For ChatGPT Direct editing, set `enableDirectProfile: true` in the trusted
|
|
27
27
|
local config and run `PatchWarden.cmd start direct`. It uses
|
|
28
|
-
`scripts/patchwarden-mcp-direct.cmd`, the separate `patchwarden-direct` Tunnel
|
|
28
|
+
`scripts/mcp/patchwarden-mcp-direct.cmd`, the separate `patchwarden-direct` Tunnel
|
|
29
29
|
Client profile, no Watcher, and an isolated `runtime-direct` status directory.
|
|
30
|
-
Use a separate Direct Connector/Tunnel ID so the fixed
|
|
31
|
-
the
|
|
30
|
+
Use a separate Direct Connector/Tunnel ID so the fixed 17-tool Core catalog and
|
|
31
|
+
the 10-tool Direct catalog never overwrite each other's cached schema.
|
|
32
32
|
|
|
33
33
|
The Windows launcher prompts for the runtime API key once and stores only a
|
|
34
34
|
Windows DPAPI-encrypted value under `%APPDATA%\patchwarden`. Use
|
|
@@ -38,7 +38,7 @@ Before the launcher starts the tunnel it performs a real MCP stdio handshake
|
|
|
38
38
|
and requires the exact `chatgpt_core` manifest. Run
|
|
39
39
|
`PatchWarden.cmd health` to see the version, profile, tool names, schema
|
|
40
40
|
hash, process sources, and any mixed-version warnings. The check is read-only.
|
|
41
|
-
The v0.
|
|
41
|
+
The v0.6.1 core manifest contains 17 tools. A different count or schema hash
|
|
42
42
|
requires a Connector refresh and validation from a new ChatGPT conversation.
|
|
43
43
|
|
|
44
44
|
## Architecture
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
# --sample sample_mcp_stdio_local \
|
|
13
13
|
# --profile patchwarden \
|
|
14
14
|
# --tunnel-id tunnel_xxx \
|
|
15
|
-
# --mcp-command "C:/path/to/patchwarden/scripts/patchwarden-mcp-stdio.cmd"
|
|
15
|
+
# --mcp-command "C:/path/to/patchwarden/scripts/mcp/patchwarden-mcp-stdio.cmd"
|
|
16
16
|
|
|
17
17
|
# Direct mode uses a separate profile and command:
|
|
18
18
|
#
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
# --sample sample_mcp_stdio_local \
|
|
21
21
|
# --profile patchwarden-direct \
|
|
22
22
|
# --tunnel-id tunnel_xxx \
|
|
23
|
-
# --mcp-command "C:/path/to/patchwarden/scripts/patchwarden-mcp-direct.cmd"
|
|
23
|
+
# --mcp-command "C:/path/to/patchwarden/scripts/mcp/patchwarden-mcp-direct.cmd"
|
|
24
24
|
|
|
25
25
|
mcp:
|
|
26
26
|
commands:
|
|
27
27
|
- channel: main
|
|
28
|
-
command: "C:/path/to/patchwarden/scripts/patchwarden-mcp-stdio.cmd"
|
|
28
|
+
command: "C:/path/to/patchwarden/scripts/mcp/patchwarden-mcp-stdio.cmd"
|
|
29
29
|
|
|
30
30
|
# Mode B: HTTP
|
|
31
31
|
#
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "patchwarden",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Secure local MCP bridge for ChatGPT and local agents, with workspace-scoped tasks, safe summaries, audits, and Direct editing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -17,9 +17,16 @@
|
|
|
17
17
|
"src/",
|
|
18
18
|
"examples/",
|
|
19
19
|
"scripts/",
|
|
20
|
-
"!scripts/kill-patchwarden.ps1",
|
|
20
|
+
"!scripts/control/kill-patchwarden.ps1",
|
|
21
21
|
"!scripts/launchers/Kill-PatchWarden.cmd",
|
|
22
|
+
"!.local/",
|
|
23
|
+
"ui/",
|
|
22
24
|
"PatchWarden.cmd",
|
|
25
|
+
"PatchWarden-Control.cmd",
|
|
26
|
+
"PatchWarden-Control-Tray.cmd",
|
|
27
|
+
"PatchWarden-Desktop.cmd",
|
|
28
|
+
"Restart-PatchWarden-Control.cmd",
|
|
29
|
+
"Stop-PatchWarden.cmd",
|
|
23
30
|
"README.md",
|
|
24
31
|
"README.en.md",
|
|
25
32
|
"LICENSE",
|
|
@@ -29,25 +36,27 @@
|
|
|
29
36
|
"build": "node ./node_modules/typescript/bin/tsc",
|
|
30
37
|
"start": "node dist/index.js",
|
|
31
38
|
"start:http": "node dist/httpServer.js",
|
|
39
|
+
"start:control": "node dist/controlCenter.js",
|
|
32
40
|
"dev": "npm run build && node dist/index.js",
|
|
33
41
|
"runner": "node dist/runner/cli.js",
|
|
34
42
|
"watch": "node dist/runner/watch.js",
|
|
35
43
|
"doctor": "node dist/doctor.js",
|
|
36
44
|
"doctor:ci": "node dist/doctor.js --allow-default-config",
|
|
37
|
-
"test:unit": "node scripts/unit-tests.js",
|
|
38
|
-
"test": "node dist/smoke-test.js && node scripts/unit-tests.js && node scripts/lifecycle-smoke.js && node scripts/doctor-smoke.js && node scripts/tunnel-supervisor-smoke.js && node scripts/watcher-supervisor-smoke.js && node scripts/control-smoke.js && node scripts/mcp-manifest-check.js && node scripts/brand-check.js",
|
|
39
|
-
"test:lifecycle": "npm run build && node scripts/lifecycle-smoke.js",
|
|
40
|
-
"test:doctor": "npm run build && node scripts/doctor-smoke.js",
|
|
41
|
-
"test:tunnel-supervisor": "npm run build && node scripts/tunnel-supervisor-smoke.js",
|
|
42
|
-
"test:watcher-supervisor": "npm run build && node scripts/watcher-supervisor-smoke.js",
|
|
43
|
-
"check:tool-manifest": "npm run build && node scripts/mcp-manifest-check.js",
|
|
44
|
-
"check:direct-tool-manifest": "npm run build && node scripts/mcp-manifest-check.js --profile chatgpt_direct",
|
|
45
|
-
"check:
|
|
46
|
-
"
|
|
47
|
-
"test:
|
|
45
|
+
"test:unit": "node scripts/checks/unit-tests.js",
|
|
46
|
+
"test": "node dist/smoke-test.js && node scripts/checks/unit-tests.js && node scripts/checks/lifecycle-smoke.js && node scripts/checks/doctor-smoke.js && node scripts/checks/tunnel-supervisor-smoke.js && node scripts/checks/watcher-supervisor-smoke.js && node scripts/checks/control-smoke.js && node scripts/checks/mcp-manifest-check.js && node scripts/checks/brand-check.js && node scripts/checks/control-center-smoke.js",
|
|
47
|
+
"test:lifecycle": "npm run build && node scripts/checks/lifecycle-smoke.js",
|
|
48
|
+
"test:doctor": "npm run build && node scripts/checks/doctor-smoke.js",
|
|
49
|
+
"test:tunnel-supervisor": "npm run build && node scripts/checks/tunnel-supervisor-smoke.js",
|
|
50
|
+
"test:watcher-supervisor": "npm run build && node scripts/checks/watcher-supervisor-smoke.js",
|
|
51
|
+
"check:tool-manifest": "npm run build && node scripts/checks/mcp-manifest-check.js",
|
|
52
|
+
"check:direct-tool-manifest": "npm run build && node scripts/checks/mcp-manifest-check.js --profile chatgpt_direct",
|
|
53
|
+
"check:search-tool-manifest": "npm run build && node scripts/checks/mcp-manifest-check.js --profile chatgpt_search",
|
|
54
|
+
"check:brand": "node scripts/checks/brand-check.js",
|
|
55
|
+
"test:mcp": "npm run build && node scripts/checks/mcp-smoke.js",
|
|
56
|
+
"test:http-mcp": "npm run build && node scripts/checks/http-mcp-smoke.js",
|
|
48
57
|
"pretest": "npm run build",
|
|
49
|
-
"pack:clean": "npm run build && node scripts/pack-clean.js",
|
|
50
|
-
"verify:package": "npm run build && node scripts/package-manifest-check.js"
|
|
58
|
+
"pack:clean": "npm run build && node scripts/release/pack-clean.js",
|
|
59
|
+
"verify:package": "npm run build && node scripts/checks/package-manifest-check.js"
|
|
51
60
|
},
|
|
52
61
|
"dependencies": {
|
|
53
62
|
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# PatchWarden Scripts
|
|
2
|
+
|
|
3
|
+
This directory keeps implementation scripts out of the root folder. Normal
|
|
4
|
+
desktop use should start from the root entrypoints:
|
|
5
|
+
|
|
6
|
+
```powershell
|
|
7
|
+
.\PatchWarden-Desktop.cmd
|
|
8
|
+
.\PatchWarden-Control.cmd
|
|
9
|
+
.\PatchWarden-Control-Tray.cmd --foreground
|
|
10
|
+
.\Stop-PatchWarden.cmd
|
|
11
|
+
.\PatchWarden.cmd status all
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Control Scripts
|
|
15
|
+
|
|
16
|
+
- `control/manage-patchwarden.ps1`: backing implementation for `PatchWarden.cmd`.
|
|
17
|
+
- `control/start-control-center.ps1`: starts the local Web dashboard.
|
|
18
|
+
- `control/restart-control-center.ps1`: restarts the local Web dashboard.
|
|
19
|
+
- `control/control-center-tray.ps1`: Windows tray quick controls.
|
|
20
|
+
- `control/stop-patchwarden.ps1`: one-click shutdown for Core/Direct,
|
|
21
|
+
Control Center, and tray.
|
|
22
|
+
- `control/start-patchwarden-tunnel.ps1`: starts Core or Direct tunnel supervision.
|
|
23
|
+
- `control/restart-patchwarden.ps1`: compatibility restart helper.
|
|
24
|
+
|
|
25
|
+
## MCP Entrypoints
|
|
26
|
+
|
|
27
|
+
- `mcp/patchwarden-mcp-stdio.cmd`: Core stdio MCP launcher.
|
|
28
|
+
- `mcp/patchwarden-mcp-direct.cmd`: Direct stdio MCP launcher.
|
|
29
|
+
|
|
30
|
+
## Smoke Tests And Checks
|
|
31
|
+
|
|
32
|
+
- `checks/*-smoke.js`: targeted smoke tests.
|
|
33
|
+
- `checks/unit-tests.js`: Node unit test entry.
|
|
34
|
+
- `checks/mcp-manifest-check.js`: validates MCP manifest expectations.
|
|
35
|
+
- `brand-check.js`: checks public brand strings.
|
|
36
|
+
- `checks/package-manifest-check.js`: verifies package contents.
|
|
37
|
+
|
|
38
|
+
## Release Helpers
|
|
39
|
+
|
|
40
|
+
- `release/pack-clean.js`: rebuilds `release/`, `patchwarden-release.tar.gz`, and the
|
|
41
|
+
versioned `PatchWarden-v*.zip` artifact.
|
|
42
|
+
|
|
43
|
+
## Compatibility Launchers
|
|
44
|
+
|
|
45
|
+
Compatibility `.cmd` files live under `scripts/launchers/`. User-private local
|
|
46
|
+
launchers belong under `.local/` and must stay out of Git and release packages.
|
|
47
|
+
|
|
@@ -12,8 +12,8 @@ const allowedLegacyFiles = new Set([
|
|
|
12
12
|
"docs/release-v0.3.0.md",
|
|
13
13
|
"docs/release-v0.4.0.md",
|
|
14
14
|
"docs/release-v0.6.0.md",
|
|
15
|
-
"scripts/brand-check.js",
|
|
16
|
-
"scripts/pack-clean.js",
|
|
15
|
+
"scripts/checks/brand-check.js",
|
|
16
|
+
"scripts/release/pack-clean.js",
|
|
17
17
|
]);
|
|
18
18
|
const legacyPattern = /safe-bifrost|Safe-Bifrost|SAFE_BIFROST|SafeBifrost|safe_bifrost/;
|
|
19
19
|
|