patchwarden 1.5.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.
- package/README.en.md +43 -2
- package/README.md +43 -2
- package/dist/assessments/agentAssessor.d.ts +1 -1
- package/dist/assessments/agentAssessor.js +3 -3
- package/dist/assessments/assessmentStore.d.ts +1 -1
- package/dist/assessments/assessmentStore.js +2 -2
- package/dist/assessments/confirmCli.js +5 -4
- package/dist/config.d.ts +7 -0
- package/dist/config.js +34 -0
- package/dist/control/middleware/auth.d.ts +10 -0
- package/dist/control/middleware/auth.js +8 -0
- package/dist/control/middleware/static.d.ts +3 -0
- package/dist/control/middleware/static.js +65 -0
- package/dist/control/routes/audit.d.ts +15 -0
- package/dist/control/routes/audit.js +277 -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 +5 -0
- package/dist/control/routes/process.js +200 -0
- package/dist/control/routes/sessions.d.ts +22 -0
- package/dist/control/routes/sessions.js +224 -0
- package/dist/control/routes/status.d.ts +6 -0
- package/dist/control/routes/status.js +250 -0
- package/dist/control/routes/taskActions.d.ts +21 -0
- package/dist/control/routes/taskActions.js +233 -0
- package/dist/control/routes/tasks.d.ts +20 -0
- package/dist/control/routes/tasks.js +310 -0
- package/dist/control/routes/workspace.d.ts +15 -0
- package/dist/control/routes/workspace.js +193 -0
- package/dist/control/runtime.d.ts +91 -0
- package/dist/control/runtime.js +392 -0
- package/dist/control/server.d.ts +13 -0
- package/dist/control/server.js +479 -0
- package/dist/control/shared.d.ts +35 -0
- package/dist/control/shared.js +288 -0
- package/dist/controlCenter.d.ts +6 -0
- package/dist/controlCenter.js +7 -2197
- package/dist/direct/directGuards.js +30 -8
- package/dist/doctor.d.ts +18 -1
- package/dist/doctor.js +579 -348
- package/dist/goal/goalReport.d.ts +54 -0
- package/dist/goal/goalReport.js +204 -0
- package/dist/goal/goalStatus.d.ts +6 -0
- package/dist/goal/specKitImport.d.ts +63 -0
- package/dist/goal/specKitImport.js +220 -0
- package/dist/goal/subgoalSync.js +2 -1
- package/dist/httpServer.js +15 -12
- package/dist/index.js +7 -4
- package/dist/logging.d.ts +7 -1
- package/dist/logging.js +8 -0
- package/dist/runner/changeCapture.d.ts +3 -3
- package/dist/runner/changeCapture.js +63 -39
- package/dist/runner/cli.js +7 -6
- package/dist/runner/postTaskCleanup.js +26 -2
- package/dist/runner/runTask.js +245 -221
- package/dist/runner/simpleProcess.js +4 -4
- package/dist/runner/watch.js +17 -14
- package/dist/security/contentRedaction.d.ts +6 -0
- package/dist/security/contentRedaction.js +22 -0
- package/dist/smoke-test.js +257 -251
- package/dist/test/unit/apply-patch.test.d.ts +1 -0
- package/dist/test/unit/apply-patch.test.js +225 -0
- package/dist/test/unit/create-task.test.d.ts +1 -0
- package/dist/test/unit/create-task.test.js +197 -0
- package/dist/test/unit/direct-guards.test.js +124 -9
- package/dist/test/unit/evidence-pack.test.js +95 -1
- package/dist/test/unit/get-task-status.test.d.ts +1 -0
- package/dist/test/unit/get-task-status.test.js +174 -0
- package/dist/test/unit/get-task-summary.test.d.ts +1 -0
- package/dist/test/unit/get-task-summary.test.js +146 -0
- package/dist/test/unit/goal-report.test.d.ts +1 -0
- package/dist/test/unit/goal-report.test.js +159 -0
- package/dist/test/unit/goal-subgoal-task.test.js +6 -6
- package/dist/test/unit/goal-tools-registry.test.js +6 -4
- package/dist/test/unit/path-guard.test.js +24 -0
- package/dist/test/unit/spec-kit-import.test.d.ts +1 -0
- package/dist/test/unit/spec-kit-import.test.js +341 -0
- package/dist/test/unit/wait-for-task.test.d.ts +1 -0
- package/dist/test/unit/wait-for-task.test.js +144 -0
- package/dist/tools/auditTask.d.ts +8 -63
- package/dist/tools/auditTask.js +12 -8
- package/dist/tools/createDirectSession.d.ts +1 -1
- package/dist/tools/createDirectSession.js +2 -2
- package/dist/tools/createTask.d.ts +2 -2
- package/dist/tools/createTask.js +4 -4
- package/dist/tools/dispatch/coreDispatch.d.ts +9 -0
- package/dist/tools/dispatch/coreDispatch.js +282 -0
- package/dist/tools/dispatch/diagnosticDispatch.d.ts +14 -0
- package/dist/tools/dispatch/diagnosticDispatch.js +78 -0
- package/dist/tools/dispatch/directDispatch.d.ts +8 -0
- package/dist/tools/dispatch/directDispatch.js +115 -0
- package/dist/tools/dispatch/goalDispatch.d.ts +8 -0
- package/dist/tools/dispatch/goalDispatch.js +91 -0
- package/dist/tools/dispatch/releaseDispatch.d.ts +8 -0
- package/dist/tools/dispatch/releaseDispatch.js +45 -0
- package/dist/tools/dispatch/types.d.ts +23 -0
- package/dist/tools/dispatch/types.js +15 -0
- package/dist/tools/evidencePack.d.ts +6 -0
- package/dist/tools/evidencePack.js +213 -6
- package/dist/tools/finalizeDirectSession.d.ts +1 -1
- package/dist/tools/finalizeDirectSession.js +3 -3
- package/dist/tools/goalSubgoalTask.d.ts +1 -1
- package/dist/tools/goalSubgoalTask.js +2 -2
- package/dist/tools/healthCheck.js +3 -3
- package/dist/tools/registry.d.ts +3 -3
- package/dist/tools/registry.js +60 -503
- package/dist/tools/retryTask.d.ts +2 -2
- package/dist/tools/retryTask.js +2 -2
- package/dist/tools/runTaskLoop.js +4 -4
- package/dist/tools/safeViews.d.ts +2 -2
- package/dist/tools/safeViews.js +2 -2
- package/dist/tools/toolRegistry.js +22 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/CODE_WIKI.md +983 -0
- package/docs/agentseal-integration.md +150 -0
- package/docs/architecture.md +63 -0
- package/docs/assets/patchwarden-oss-demo.gif +0 -0
- package/docs/dashboard-overview.md +86 -0
- package/docs/demo.md +8 -0
- package/docs/direct-session-workflow.md +98 -0
- package/docs/evidence-pack-schema.md +215 -0
- package/docs/execution-plan-2026-07-09.md +315 -0
- package/docs/lineage-evidence-pack-workflow.md +127 -0
- package/docs/mcp-inspector-testing.md +200 -0
- package/docs/open-source-application.md +162 -0
- package/docs/opencode-worker.md +151 -0
- package/docs/openhands-worker.md +181 -0
- package/docs/release-evidence.md +72 -0
- package/docs/roadmap-execution-and-acceptance.md +365 -0
- package/docs/spec-kit-integration.md +131 -0
- package/docs/task-safe-review-workflow.md +98 -0
- package/docs/threat-model.md +79 -0
- package/docs/user-feedback.md +40 -0
- package/docs/why-patchwarden.md +110 -0
- package/package.json +2 -2
- package/scripts/checks/control-center-smoke.js +356 -0
- package/scripts/checks/lifecycle-smoke.js +29 -23
- package/scripts/checks/mcp-smoke.js +3 -1
- package/scripts/generate-demo-gif.py +320 -0
- package/src/assessments/agentAssessor.ts +3 -3
- package/src/assessments/assessmentStore.ts +2 -2
- package/src/assessments/confirmCli.ts +5 -4
- package/src/config.ts +37 -0
- package/src/control/middleware/auth.ts +17 -0
- package/src/control/middleware/static.ts +71 -0
- package/src/control/routes/audit.ts +321 -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 +204 -0
- package/src/control/routes/sessions.ts +251 -0
- package/src/control/routes/status.ts +325 -0
- package/src/control/routes/taskActions.ts +248 -0
- package/src/control/routes/tasks.ts +323 -0
- package/src/control/routes/workspace.ts +203 -0
- package/src/control/runtime.ts +472 -0
- package/src/control/server.ts +471 -0
- package/src/control/shared.ts +294 -0
- package/src/controlCenter.ts +7 -2347
- package/src/direct/directGuards.ts +28 -7
- package/src/doctor.ts +741 -481
- package/src/goal/goalReport.ts +271 -0
- package/src/goal/goalStatus.ts +6 -0
- package/src/goal/specKitImport.ts +355 -0
- package/src/goal/subgoalSync.ts +4 -2
- package/src/httpServer.ts +17 -14
- package/src/index.ts +7 -4
- package/src/logging.ts +10 -1
- package/src/runner/changeCapture.ts +70 -42
- package/src/runner/cli.ts +7 -6
- package/src/runner/postTaskCleanup.ts +26 -2
- package/src/runner/runTask.ts +325 -223
- package/src/runner/simpleProcess.ts +4 -4
- package/src/runner/watch.ts +17 -14
- package/src/security/contentRedaction.ts +29 -0
- package/src/smoke-test.ts +252 -250
- package/src/test/unit/apply-patch.test.ts +293 -0
- package/src/test/unit/create-task.test.ts +255 -0
- package/src/test/unit/direct-guards.test.ts +178 -8
- package/src/test/unit/evidence-pack.test.ts +110 -1
- package/src/test/unit/get-task-status.test.ts +203 -0
- package/src/test/unit/get-task-summary.test.ts +173 -0
- package/src/test/unit/goal-report.test.ts +189 -0
- package/src/test/unit/goal-subgoal-task.test.ts +6 -6
- package/src/test/unit/goal-tools-registry.test.ts +7 -5
- package/src/test/unit/path-guard.test.ts +30 -0
- package/src/test/unit/spec-kit-import.test.ts +429 -0
- package/src/test/unit/wait-for-task.test.ts +176 -0
- package/src/tools/auditTask.ts +99 -59
- package/src/tools/createDirectSession.ts +3 -3
- package/src/tools/createTask.ts +7 -7
- package/src/tools/dispatch/coreDispatch.ts +374 -0
- package/src/tools/dispatch/diagnosticDispatch.ts +101 -0
- package/src/tools/dispatch/directDispatch.ts +167 -0
- package/src/tools/dispatch/goalDispatch.ts +127 -0
- package/src/tools/dispatch/releaseDispatch.ts +65 -0
- package/src/tools/dispatch/types.ts +24 -0
- package/src/tools/evidencePack.ts +291 -6
- package/src/tools/finalizeDirectSession.ts +4 -4
- package/src/tools/goalSubgoalTask.ts +2 -2
- package/src/tools/healthCheck.ts +3 -3
- package/src/tools/registry.ts +68 -628
- package/src/tools/retryTask.ts +2 -2
- package/src/tools/runTaskLoop.ts +4 -4
- package/src/tools/safeViews.ts +2 -2
- package/src/tools/toolRegistry.ts +22 -0
- package/src/version.ts +1 -1
- package/ui/pages/audit.html +192 -3
- package/ui/pages/dashboard.html +959 -44
- package/ui/pages/direct-sessions.html +505 -53
- package/ui/pages/task-detail.html +456 -438
- package/ui/pages/tasks.html +598 -61
package/src/tools/retryTask.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { getTasksDir, getConfig } from "../config.js";
|
|
|
4
4
|
import { guardReadPath } from "../security/pathGuard.js";
|
|
5
5
|
import { createTask } from "./createTask.js";
|
|
6
6
|
|
|
7
|
-
export function retryTask(taskId: string) {
|
|
7
|
+
export async function retryTask(taskId: string) {
|
|
8
8
|
const config = getConfig();
|
|
9
9
|
const tasksDir = getTasksDir(config);
|
|
10
10
|
const taskDir = join(tasksDir, taskId);
|
|
@@ -23,7 +23,7 @@ export function retryTask(taskId: string) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// Create a new task with the same parameters
|
|
26
|
-
const newTask = createTask({
|
|
26
|
+
const newTask = await createTask({
|
|
27
27
|
plan_id: data.plan_id,
|
|
28
28
|
agent: data.agent,
|
|
29
29
|
repo_path: data.repo_path,
|
package/src/tools/runTaskLoop.ts
CHANGED
|
@@ -202,7 +202,7 @@ export async function runTaskLoopWithDeps(
|
|
|
202
202
|
timeout_seconds: normalized.task_timeout_seconds,
|
|
203
203
|
execution_mode: "assess_only",
|
|
204
204
|
};
|
|
205
|
-
const assessment = deps.createTask(assessmentInput as CreateTaskInput & { execution_mode: "assess_only" }) as any;
|
|
205
|
+
const assessment = await deps.createTask(assessmentInput as CreateTaskInput & { execution_mode: "assess_only" }) as any;
|
|
206
206
|
if (assessment.decision === "blocked") {
|
|
207
207
|
return finalize("blocked", "high_risk_blocked", "Risk assessment blocked task execution.", assessment.reason_codes?.join(", "));
|
|
208
208
|
}
|
|
@@ -210,7 +210,7 @@ export async function runTaskLoopWithDeps(
|
|
|
210
210
|
return finalize("blocked", "user_confirmation_required", "Ask the user to confirm the assessment before executing the loop.");
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
const created = deps.createTask({
|
|
213
|
+
const created = await deps.createTask({
|
|
214
214
|
execution_mode: "execute",
|
|
215
215
|
assessment_id: String(assessment.assessment_id || ""),
|
|
216
216
|
}) as any;
|
|
@@ -403,7 +403,7 @@ async function runDirectVerification(
|
|
|
403
403
|
|
|
404
404
|
let sessionId = "";
|
|
405
405
|
try {
|
|
406
|
-
const session = deps.createDirectSession({
|
|
406
|
+
const session = await deps.createDirectSession({
|
|
407
407
|
repo_path: repoPath,
|
|
408
408
|
title: `Direct verification for ${lineageId}`,
|
|
409
409
|
});
|
|
@@ -413,7 +413,7 @@ async function runDirectVerification(
|
|
|
413
413
|
commands: normalized.direct_verify_commands,
|
|
414
414
|
timeout_seconds: normalized.direct_verify_timeout_seconds,
|
|
415
415
|
});
|
|
416
|
-
const finalized = deps.safeFinalizeDirectSession(sessionId, { max_items: 8 }) as any;
|
|
416
|
+
const finalized = await deps.safeFinalizeDirectSession(sessionId, { max_items: 8 }) as any;
|
|
417
417
|
const audit = deps.safeAuditDirectSession(sessionId, { max_items: 8 }) as any;
|
|
418
418
|
const evidence: TaskLineageDirectSession = {
|
|
419
419
|
session_id: sessionId,
|
package/src/tools/safeViews.ts
CHANGED
|
@@ -103,9 +103,9 @@ export function safeDirectSummary(sessionId: string, options: SafeViewOptions =
|
|
|
103
103
|
return directSessionToSafe(session, maxItems, "summary");
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
export function safeFinalizeDirectSession(sessionId: string, options: SafeViewOptions = {}) {
|
|
106
|
+
export async function safeFinalizeDirectSession(sessionId: string, options: SafeViewOptions = {}) {
|
|
107
107
|
const maxItems = normalizeMaxItems(options.max_items);
|
|
108
|
-
const finalized = finalizeDirectSession({ session_id: sessionId });
|
|
108
|
+
const finalized = await finalizeDirectSession({ session_id: sessionId });
|
|
109
109
|
const session = readDirectSession(sessionId);
|
|
110
110
|
return redact({
|
|
111
111
|
...directSessionToSafe(session, maxItems, "finalize"),
|
|
@@ -728,6 +728,28 @@ const STATIC_TOOL_META: Record<string, StaticToolMeta> = {
|
|
|
728
728
|
requiresConfirmation: false,
|
|
729
729
|
relatedTools: ["summarize_goal_progress", "read_goal"],
|
|
730
730
|
},
|
|
731
|
+
export_goal_report: {
|
|
732
|
+
title: "Export Goal Report",
|
|
733
|
+
summary: "Export a structured final report for a Goal session",
|
|
734
|
+
profiles: ["full"],
|
|
735
|
+
modes: ["delegate", "audit"],
|
|
736
|
+
tags: ["goal", "report", "export", "summary", "final"],
|
|
737
|
+
aliases: ["goal_report", "report"],
|
|
738
|
+
risk: "workspace_write",
|
|
739
|
+
requiresConfirmation: false,
|
|
740
|
+
relatedTools: ["summarize_goal_progress", "export_handoff"],
|
|
741
|
+
},
|
|
742
|
+
import_speckit_tasks: {
|
|
743
|
+
title: "Import Spec Kit Tasks",
|
|
744
|
+
summary: "Import Spec Kit tasks into a Goal session as subgoals",
|
|
745
|
+
profiles: ["full"],
|
|
746
|
+
modes: ["delegate", "audit"],
|
|
747
|
+
tags: ["goal", "speckit", "import", "tasks", "subgoal"],
|
|
748
|
+
aliases: ["speckit_import", "import_tasks"],
|
|
749
|
+
risk: "workspace_write",
|
|
750
|
+
requiresConfirmation: false,
|
|
751
|
+
relatedTools: ["create_subgoal_task", "export_goal_report"],
|
|
752
|
+
},
|
|
731
753
|
invoke_discovered_tool: {
|
|
732
754
|
title: "Invoke Discovered Tool",
|
|
733
755
|
summary: "v0.8.1: 通过 token 调用 discover_tools 发现的动态工具",
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const PATCHWARDEN_VERSION = "1.5.
|
|
1
|
+
export const PATCHWARDEN_VERSION = "1.5.1";
|
|
2
2
|
export const TOOL_SCHEMA_EPOCH = "2026-07-05-v13";
|
package/ui/pages/audit.html
CHANGED
|
@@ -293,6 +293,55 @@ html.dark {
|
|
|
293
293
|
</div>
|
|
294
294
|
</section>
|
|
295
295
|
|
|
296
|
+
<!-- ===== 1b. Warnings Aggregation ===== -->
|
|
297
|
+
<section class="rounded-lg overflow-hidden mb-6" style="background-color: var(--pw-bg-surface); border: 1px solid var(--pw-border); border-left: 3px solid var(--pw-state-warning);">
|
|
298
|
+
<div class="flex items-center justify-between px-5 py-4" style="border-bottom: 1px solid var(--pw-border-subtle);">
|
|
299
|
+
<div class="flex items-center gap-2 flex-wrap">
|
|
300
|
+
<i data-lucide="alert-triangle" class="w-4 h-4 shrink-0" style="color: var(--pw-state-warning);"></i>
|
|
301
|
+
<h2 class="text-sm font-semibold" style="color: var(--pw-text-primary);" data-zh="警告聚合" data-en="Warnings Aggregation">警告聚合</h2>
|
|
302
|
+
<span id="warnings-count" class="text-xs px-2 py-0.5 rounded-md whitespace-nowrap" style="font-family: var(--pw-font-mono); color: var(--pw-text-tertiary); background-color: var(--pw-bg-hover);">—</span>
|
|
303
|
+
</div>
|
|
304
|
+
</div>
|
|
305
|
+
|
|
306
|
+
<!-- Warnings Loading State -->
|
|
307
|
+
<div id="warningsLoadingState" class="py-10 text-center">
|
|
308
|
+
<svg class="pw-spin inline-block mb-2" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="var(--pw-text-tertiary)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
309
|
+
<line x1="12" y1="2" x2="12" y2="6"/>
|
|
310
|
+
<line x1="12" y1="18" x2="12" y2="22"/>
|
|
311
|
+
<line x1="4.93" y1="4.93" x2="7.76" y2="7.76"/>
|
|
312
|
+
<line x1="16.24" y1="16.24" x2="19.07" y2="19.07"/>
|
|
313
|
+
<line x1="2" y1="12" x2="6" y2="12"/>
|
|
314
|
+
<line x1="18" y1="12" x2="22" y2="12"/>
|
|
315
|
+
<line x1="4.93" y1="19.07" x2="7.76" y2="16.24"/>
|
|
316
|
+
<line x1="16.24" y1="7.76" x2="19.07" y2="4.93"/>
|
|
317
|
+
</svg>
|
|
318
|
+
<p class="text-xs" style="color: var(--pw-text-tertiary);" data-zh="加载警告中..." data-en="Loading warnings...">加载警告中...</p>
|
|
319
|
+
</div>
|
|
320
|
+
|
|
321
|
+
<!-- Warnings Error State -->
|
|
322
|
+
<div id="warningsErrorState" class="hidden py-10 text-center">
|
|
323
|
+
<svg class="inline-block mb-2" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="var(--pw-state-error)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
324
|
+
<circle cx="12" cy="12" r="10"/>
|
|
325
|
+
<line x1="12" y1="8" x2="12" y2="12"/>
|
|
326
|
+
<line x1="12" y1="16" x2="12.01" y2="16"/>
|
|
327
|
+
</svg>
|
|
328
|
+
<p class="text-xs font-medium" style="color: var(--pw-state-error);" data-zh="警告加载失败" data-en="Warnings Load Failed">警告加载失败</p>
|
|
329
|
+
<p id="warningsErrorMessage" class="text-xs mt-2 px-6 break-words" style="color: var(--pw-text-tertiary); font-family: var(--pw-font-mono);"></p>
|
|
330
|
+
</div>
|
|
331
|
+
|
|
332
|
+
<!-- Warnings Empty State -->
|
|
333
|
+
<div id="warningsEmptyState" class="hidden py-10 text-center">
|
|
334
|
+
<svg class="inline-block mb-2" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="var(--pw-state-success)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
335
|
+
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
|
|
336
|
+
<polyline points="22 4 12 14.01 9 11.01"/>
|
|
337
|
+
</svg>
|
|
338
|
+
<p class="text-xs" style="color: var(--pw-text-tertiary);" data-zh="暂无警告" data-en="No Warnings">暂无警告</p>
|
|
339
|
+
</div>
|
|
340
|
+
|
|
341
|
+
<!-- Warnings Cards Container -->
|
|
342
|
+
<div id="warningsBody" class="hidden px-5 py-4 space-y-3"></div>
|
|
343
|
+
</section>
|
|
344
|
+
|
|
296
345
|
<!-- ===== 2. Audit Log Table ===== -->
|
|
297
346
|
<section class="rounded-lg overflow-hidden mb-6" style="background-color: var(--pw-bg-surface); border: 1px solid var(--pw-border); border-left: 3px solid var(--pw-accent);">
|
|
298
347
|
|
|
@@ -438,8 +487,10 @@ html.dark {
|
|
|
438
487
|
'use strict';
|
|
439
488
|
|
|
440
489
|
var API_URL = '/api/audit';
|
|
490
|
+
var WARNINGS_URL = '/api/warnings';
|
|
441
491
|
|
|
442
492
|
var allAudits = [];
|
|
493
|
+
var allWarnings = [];
|
|
443
494
|
var selectedTaskId = null;
|
|
444
495
|
|
|
445
496
|
// ---- DOM helpers ----
|
|
@@ -724,16 +775,154 @@ html.dark {
|
|
|
724
775
|
});
|
|
725
776
|
}
|
|
726
777
|
|
|
778
|
+
// ---- Warnings aggregation ----
|
|
779
|
+
function showWarningsLoading() {
|
|
780
|
+
show($('warningsLoadingState'));
|
|
781
|
+
hide($('warningsErrorState'));
|
|
782
|
+
hide($('warningsEmptyState'));
|
|
783
|
+
hide($('warningsBody'));
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
function showWarningsError(msg) {
|
|
787
|
+
hide($('warningsLoadingState'));
|
|
788
|
+
show($('warningsErrorState'));
|
|
789
|
+
hide($('warningsEmptyState'));
|
|
790
|
+
hide($('warningsBody'));
|
|
791
|
+
var errEl = $('warningsErrorMessage');
|
|
792
|
+
if (errEl) errEl.textContent = msg || '未知错误';
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
function showWarningsEmpty() {
|
|
796
|
+
hide($('warningsLoadingState'));
|
|
797
|
+
hide($('warningsErrorState'));
|
|
798
|
+
show($('warningsEmptyState'));
|
|
799
|
+
hide($('warningsBody'));
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function showWarningsBody() {
|
|
803
|
+
hide($('warningsLoadingState'));
|
|
804
|
+
hide($('warningsErrorState'));
|
|
805
|
+
hide($('warningsEmptyState'));
|
|
806
|
+
show($('warningsBody'));
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Map a warning type to a display label + icon + accent color.
|
|
810
|
+
function warningTypeMeta(type) {
|
|
811
|
+
var map = {
|
|
812
|
+
failed_verification: { label: 'Failed verification', color: 'var(--pw-state-error)' },
|
|
813
|
+
stale_task: { label: 'Stale task', color: 'var(--pw-state-warning)' },
|
|
814
|
+
manual_verification_required: { label: 'Manual verification required', color: 'var(--pw-state-warning)' },
|
|
815
|
+
unrecorded_command_execution: { label: 'Unrecorded command execution', color: 'var(--pw-state-info)' },
|
|
816
|
+
release_publish_claim: { label: 'Release/publish claim', color: 'var(--pw-state-error)' },
|
|
817
|
+
artifact_hygiene: { label: 'Artifact hygiene', color: 'var(--pw-state-info)' },
|
|
818
|
+
scope_changes: { label: 'Scope changes', color: 'var(--pw-state-info)' }
|
|
819
|
+
};
|
|
820
|
+
return map[type] || { label: type || 'Unknown', color: 'var(--pw-text-tertiary)' };
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function severityBadge(severity) {
|
|
824
|
+
var v = String(severity || '').toLowerCase();
|
|
825
|
+
var bg, color;
|
|
826
|
+
if (v === 'error') {
|
|
827
|
+
bg = 'var(--pw-state-error-bg)';
|
|
828
|
+
color = 'var(--pw-state-error)';
|
|
829
|
+
} else if (v === 'warning') {
|
|
830
|
+
bg = 'var(--pw-state-warning-bg)';
|
|
831
|
+
color = 'var(--pw-state-warning)';
|
|
832
|
+
} else {
|
|
833
|
+
bg = 'var(--pw-state-info-bg)';
|
|
834
|
+
color = 'var(--pw-state-info)';
|
|
835
|
+
}
|
|
836
|
+
return '<span class="inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium whitespace-nowrap" style="background-color: ' + bg + '; color: ' + color + ';">' + escapeHtml(v || 'info') + '</span>';
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
function flagLabel(active, label, activeColor) {
|
|
840
|
+
if (!active) return '';
|
|
841
|
+
return '<span class="inline-flex items-center px-1.5 py-0.5 rounded text-xs whitespace-nowrap" style="background-color: ' + activeColor + '_bg; color: ' + activeColor + '; border-left: 2px solid ' + activeColor + ';">' + escapeHtml(label) + '</span>';
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
function renderWarnings() {
|
|
845
|
+
var countEl = $('warnings-count');
|
|
846
|
+
if (allWarnings.length === 0) {
|
|
847
|
+
if (countEl) countEl.textContent = '0';
|
|
848
|
+
showWarningsEmpty();
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
if (countEl) countEl.textContent = String(allWarnings.length);
|
|
852
|
+
var html = '';
|
|
853
|
+
for (var i = 0; i < allWarnings.length; i++) {
|
|
854
|
+
var w = allWarnings[i];
|
|
855
|
+
var meta = warningTypeMeta(w.type);
|
|
856
|
+
var tasks = Array.isArray(w.affected_tasks) ? w.affected_tasks : [];
|
|
857
|
+
var taskLinksHtml = '';
|
|
858
|
+
for (var j = 0; j < tasks.length; j++) {
|
|
859
|
+
var tid = tasks[j];
|
|
860
|
+
var href = '/pages/task-detail.html?id=' + encodeURIComponent(tid);
|
|
861
|
+
taskLinksHtml += '<a href="' + href + '" class="inline-block hover:underline px-1.5 py-0.5 rounded text-xs" style="font-family: var(--pw-font-mono); color: var(--pw-text-accent); background-color: var(--pw-accent-subtle);" title="' + escapeAttr(tid) + '">' + escapeHtml(truncate(tid, 18)) + '</a>';
|
|
862
|
+
}
|
|
863
|
+
var flagsHtml = ''
|
|
864
|
+
+ flagLabel(w.likely_false_positive === true, 'likely false positive', 'var(--pw-state-warning)')
|
|
865
|
+
+ flagLabel(w.needs_fix === true, 'needs fix', 'var(--pw-state-error)')
|
|
866
|
+
+ flagLabel(w.blocked === true, 'blocked', 'var(--pw-state-error)');
|
|
867
|
+
html += ''
|
|
868
|
+
+ '<div class="rounded-md p-3" style="background-color: var(--pw-bg-hover); border-left: 3px solid ' + meta.color + ';">'
|
|
869
|
+
+ '<div class="flex items-center gap-2 mb-2 flex-wrap">'
|
|
870
|
+
+ '<span class="text-sm font-semibold truncate" style="color: var(--pw-text-primary);">' + escapeHtml(meta.label) + '</span>'
|
|
871
|
+
+ severityBadge(w.severity)
|
|
872
|
+
+ '<span class="text-xs whitespace-nowrap" style="color: var(--pw-text-tertiary); font-family: var(--pw-font-mono);">' + escapeHtml(String(w.affected_tasks_count || 0)) + ' task' + (w.affected_tasks_count === 1 ? '' : 's') + '</span>'
|
|
873
|
+
+ (flagsHtml ? '<span class="flex items-center gap-1 flex-wrap">' + flagsHtml + '</span>' : '')
|
|
874
|
+
+ '</div>'
|
|
875
|
+
+ (w.recommended_action ? '<div class="text-xs mb-2" style="color: var(--pw-text-secondary);">' + escapeHtml(w.recommended_action) + '</div>' : '')
|
|
876
|
+
+ (taskLinksHtml ? '<div class="flex flex-wrap gap-1.5">' + taskLinksHtml + '</div>' : '')
|
|
877
|
+
+ '</div>';
|
|
878
|
+
}
|
|
879
|
+
$('warningsBody').innerHTML = html;
|
|
880
|
+
showWarningsBody();
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
function fetchWarnings() {
|
|
884
|
+
showWarningsLoading();
|
|
885
|
+
fetch(WARNINGS_URL, {
|
|
886
|
+
method: 'GET',
|
|
887
|
+
headers: { 'Accept': 'application/json' },
|
|
888
|
+
cache: 'no-store'
|
|
889
|
+
})
|
|
890
|
+
.then(function (res) {
|
|
891
|
+
if (!res.ok) {
|
|
892
|
+
return res.text().then(function (body) {
|
|
893
|
+
throw new Error('HTTP ' + res.status + (body ? (': ' + body.slice(0, 200)) : ''));
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
return res.json();
|
|
897
|
+
})
|
|
898
|
+
.then(function (data) {
|
|
899
|
+
allWarnings = (data && Array.isArray(data.warnings)) ? data.warnings : [];
|
|
900
|
+
renderWarnings();
|
|
901
|
+
})
|
|
902
|
+
.catch(function (err) {
|
|
903
|
+
var msg = (err && err.message) ? err.message : '未知错误';
|
|
904
|
+
if (err && err.name === 'TypeError' && /fetch/i.test(msg)) {
|
|
905
|
+
msg = '无法连接到 ' + WARNINGS_URL + '(请确认 PatchWarden 服务正在运行)';
|
|
906
|
+
}
|
|
907
|
+
showWarningsError(msg);
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
function refreshAll() {
|
|
912
|
+
fetchWarnings();
|
|
913
|
+
fetchAudits();
|
|
914
|
+
}
|
|
915
|
+
|
|
727
916
|
// ---- Event wiring ----
|
|
728
|
-
$('refreshBtn').addEventListener('click',
|
|
917
|
+
$('refreshBtn').addEventListener('click', refreshAll);
|
|
729
918
|
|
|
730
919
|
var retryBtn = $('retryBtn');
|
|
731
920
|
if (retryBtn) {
|
|
732
|
-
retryBtn.addEventListener('click',
|
|
921
|
+
retryBtn.addEventListener('click', refreshAll);
|
|
733
922
|
}
|
|
734
923
|
|
|
735
924
|
// Initial load
|
|
736
|
-
|
|
925
|
+
refreshAll();
|
|
737
926
|
})();
|
|
738
927
|
</script>
|
|
739
928
|
|