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.
- package/README.en.md +83 -8
- package/README.md +78 -10
- 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 -2001
- package/dist/direct/directGuards.js +30 -8
- package/dist/direct/directSessionStore.d.ts +2 -0
- package/dist/direct/directVerification.js +7 -0
- 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/policy/projectPolicy.d.ts +55 -0
- package/dist/policy/projectPolicy.js +286 -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 +261 -255
- 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.d.ts +1 -0
- package/dist/test/unit/evidence-pack.test.js +224 -0
- 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/project-policy-release-mode.test.d.ts +1 -0
- package/dist/test/unit/project-policy-release-mode.test.js +125 -0
- package/dist/test/unit/run-task-loop.test.d.ts +1 -0
- package/dist/test/unit/run-task-loop.test.js +380 -0
- package/dist/test/unit/schema-drift-check.test.js +10 -9
- 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 +45 -0
- package/dist/tools/evidencePack.js +375 -0
- 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/recommendAgentForTask.d.ts +19 -0
- package/dist/tools/recommendAgentForTask.js +56 -0
- package/dist/tools/registry.d.ts +3 -3
- package/dist/tools/registry.js +333 -402
- package/dist/tools/releaseMode.d.ts +50 -0
- package/dist/tools/releaseMode.js +370 -0
- package/dist/tools/retryTask.d.ts +2 -2
- package/dist/tools/retryTask.js +2 -2
- package/dist/tools/runDirectVerificationBundle.d.ts +26 -0
- package/dist/tools/runDirectVerificationBundle.js +64 -0
- package/dist/tools/runTaskLoop.d.ts +57 -0
- package/dist/tools/runTaskLoop.js +417 -0
- package/dist/tools/runVerification.d.ts +4 -0
- package/dist/tools/runVerification.js +4 -0
- package/dist/tools/safeViews.d.ts +8 -2
- package/dist/tools/safeViews.js +4 -2
- package/dist/tools/taskLineage.d.ts +91 -0
- package/dist/tools/taskLineage.js +175 -0
- package/dist/tools/toolCatalog.d.ts +2 -2
- package/dist/tools/toolCatalog.js +6 -0
- package/dist/tools/toolRegistry.js +132 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- 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/chatgpt-usage.md +31 -0
- package/docs/control-center/README.md +9 -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 +3 -3
- package/scripts/checks/control-center-smoke.js +443 -0
- package/scripts/checks/control-smoke.js +2 -2
- package/scripts/checks/lifecycle-smoke.js +29 -23
- package/scripts/checks/mcp-manifest-check.js +12 -0
- package/scripts/checks/mcp-smoke.js +33 -7
- package/scripts/checks/watcher-supervisor-smoke.js +1 -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 -2150
- package/src/direct/directGuards.ts +28 -7
- package/src/direct/directSessionStore.ts +2 -0
- package/src/direct/directVerification.ts +7 -0
- 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/policy/projectPolicy.ts +344 -0
- 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 +254 -252
- 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 +251 -0
- 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/project-policy-release-mode.test.ts +156 -0
- package/src/test/unit/run-task-loop.test.ts +425 -0
- package/src/test/unit/schema-drift-check.test.ts +11 -9
- 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 +490 -0
- package/src/tools/finalizeDirectSession.ts +4 -4
- package/src/tools/goalSubgoalTask.ts +2 -2
- package/src/tools/healthCheck.ts +3 -3
- package/src/tools/listWorkspace.ts +71 -71
- package/src/tools/recommendAgentForTask.ts +79 -0
- package/src/tools/registry.ts +352 -509
- package/src/tools/releaseMode.ts +450 -0
- package/src/tools/retryTask.ts +2 -2
- package/src/tools/runDirectVerificationBundle.ts +98 -0
- package/src/tools/runTaskLoop.ts +526 -0
- package/src/tools/runVerification.ts +8 -0
- package/src/tools/safeViews.ts +4 -2
- package/src/tools/taskLineage.ts +300 -0
- package/src/tools/toolCatalog.ts +6 -0
- package/src/tools/toolRegistry.ts +132 -0
- package/src/version.ts +2 -2
- package/ui/pages/audit.html +192 -3
- package/ui/pages/dashboard.html +1070 -14
- package/ui/pages/direct-sessions.html +505 -53
- package/ui/pages/task-detail.html +456 -438
- package/ui/pages/tasks.html +598 -61
|
@@ -37,13 +37,13 @@ export function runSimpleProcessSync(options) {
|
|
|
37
37
|
try {
|
|
38
38
|
writeFileSyncAppend(options.stdoutPath, stdout);
|
|
39
39
|
}
|
|
40
|
-
catch { }
|
|
40
|
+
catch { } // best-effort log write; failure doesn't affect result
|
|
41
41
|
}
|
|
42
42
|
if (options.stderrPath && stderr) {
|
|
43
43
|
try {
|
|
44
44
|
writeFileSyncAppend(options.stderrPath, stderr);
|
|
45
45
|
}
|
|
46
|
-
catch { }
|
|
46
|
+
catch { } // best-effort log write; failure doesn't affect result
|
|
47
47
|
}
|
|
48
48
|
return {
|
|
49
49
|
exitCode: result.status,
|
|
@@ -174,7 +174,7 @@ function gracefulKill(child) {
|
|
|
174
174
|
else
|
|
175
175
|
child.kill("SIGTERM");
|
|
176
176
|
}
|
|
177
|
-
catch { }
|
|
177
|
+
catch { } // cleanup failure is safe to ignore
|
|
178
178
|
}
|
|
179
179
|
function forceKill(child) {
|
|
180
180
|
if (!child.pid)
|
|
@@ -197,7 +197,7 @@ function forceKill(child) {
|
|
|
197
197
|
try {
|
|
198
198
|
child.kill("SIGKILL");
|
|
199
199
|
}
|
|
200
|
-
catch { }
|
|
200
|
+
catch { } // cleanup failure is safe to ignore
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
function writeFileSyncAppend(path, content) {
|
package/dist/runner/watch.js
CHANGED
|
@@ -24,6 +24,7 @@ import { guardAgentCommand, guardTestCommand } from "../security/commandGuard.js
|
|
|
24
24
|
import { validateAssessmentFreshness } from "../assessments/assessmentStore.js";
|
|
25
25
|
import { captureRepoSnapshot } from "./changeCapture.js";
|
|
26
26
|
import { runTask } from "./runTask.js";
|
|
27
|
+
import { logger } from "../logging.js";
|
|
27
28
|
// ── Bootstrap ─────────────────────────────────────────────────────
|
|
28
29
|
loadConfig();
|
|
29
30
|
const config = getConfig();
|
|
@@ -37,10 +38,10 @@ const WATCHER_LAUNCHER_PID = Number.isInteger(Number(process.env.PATCHWARDEN_WAT
|
|
|
37
38
|
? Number(process.env.PATCHWARDEN_WATCHER_LAUNCHER_PID)
|
|
38
39
|
: null;
|
|
39
40
|
mkdirSync(dirname(WATCHER_HEARTBEAT_FILE), { recursive: true });
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
logger.info(`[watcher] Workspace: ${wsRoot}`);
|
|
42
|
+
logger.info(`[watcher] Tasks: ${tasksDir}`);
|
|
43
|
+
logger.info(`[watcher] Polling every ${POLL_INTERVAL_MS / 1000}s`);
|
|
44
|
+
logger.info(`[watcher] Press Ctrl+C to stop`);
|
|
44
45
|
// Track executed tasks to prevent re-execution
|
|
45
46
|
const executedTasks = new Set();
|
|
46
47
|
// ── Main loop ─────────────────────────────────────────────────────
|
|
@@ -96,7 +97,7 @@ async function tick() {
|
|
|
96
97
|
}
|
|
97
98
|
// Assessment freshness revalidation
|
|
98
99
|
if (statusData.assessment_id) {
|
|
99
|
-
const preExecSnapshot = captureRepoSnapshot(resolvedRepoPath);
|
|
100
|
+
const preExecSnapshot = await captureRepoSnapshot(resolvedRepoPath);
|
|
100
101
|
const validation = validateAssessmentFreshness(String(statusData.assessment_id), preExecSnapshot);
|
|
101
102
|
if (!validation.valid) {
|
|
102
103
|
throw new Error(`assessment validation failed: ${validation.failure_reason}`);
|
|
@@ -105,7 +106,7 @@ async function tick() {
|
|
|
105
106
|
}
|
|
106
107
|
catch (err) {
|
|
107
108
|
const errMsg = `[watcher] Safety check failed for ${taskId}: ${err instanceof Error ? err.message : String(err)}`;
|
|
108
|
-
|
|
109
|
+
logger.error(errMsg);
|
|
109
110
|
// Write error and mark as failed so it doesn't get re-picked
|
|
110
111
|
try {
|
|
111
112
|
writeFileSync(join(taskDir, "error.log"), errMsg, "utf-8");
|
|
@@ -115,37 +116,39 @@ async function tick() {
|
|
|
115
116
|
data.updated_at = new Date().toISOString();
|
|
116
117
|
writeFileSync(statusFile, JSON.stringify(data, null, 2), "utf-8");
|
|
117
118
|
}
|
|
118
|
-
catch {
|
|
119
|
+
catch (err) {
|
|
120
|
+
logger.warn("watcher error-log write failed", { error: err instanceof Error ? err.message : String(err) });
|
|
121
|
+
}
|
|
119
122
|
executedTasks.add(taskId);
|
|
120
123
|
continue;
|
|
121
124
|
}
|
|
122
125
|
// ── Execute ──
|
|
123
|
-
|
|
126
|
+
logger.info(`[watcher] Executing: ${taskId}`);
|
|
124
127
|
executedTasks.add(taskId);
|
|
125
128
|
try {
|
|
126
129
|
const result = await runTask(taskId);
|
|
127
|
-
|
|
130
|
+
logger.info(`[watcher] ${taskId} → ${result.status}`);
|
|
128
131
|
}
|
|
129
132
|
catch (err) {
|
|
130
|
-
|
|
133
|
+
logger.error(`[watcher] ${taskId} → error: ${err instanceof Error ? err.message : String(err)}`);
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
136
|
}
|
|
134
137
|
catch (err) {
|
|
135
|
-
|
|
138
|
+
logger.error(`[watcher] Tick error: ${err instanceof Error ? err.message : String(err)}`);
|
|
136
139
|
}
|
|
137
140
|
}
|
|
138
141
|
// ── Start ─────────────────────────────────────────────────────────
|
|
139
|
-
|
|
142
|
+
logger.info("[watcher] Started");
|
|
140
143
|
setInterval(tick, POLL_INTERVAL_MS);
|
|
141
144
|
// Run first tick immediately
|
|
142
145
|
tick();
|
|
143
146
|
// Graceful shutdown
|
|
144
147
|
process.on("SIGINT", () => {
|
|
145
|
-
|
|
148
|
+
logger.info("[watcher] Stopped");
|
|
146
149
|
process.exit(0);
|
|
147
150
|
});
|
|
148
151
|
process.on("SIGTERM", () => {
|
|
149
|
-
|
|
152
|
+
logger.info("[watcher] Stopped");
|
|
150
153
|
process.exit(0);
|
|
151
154
|
});
|
|
@@ -8,5 +8,11 @@ export interface StructuredRedactionResult<T> {
|
|
|
8
8
|
redacted: boolean;
|
|
9
9
|
redaction_categories: string[];
|
|
10
10
|
}
|
|
11
|
+
export interface RedactionCategoryCount {
|
|
12
|
+
category: string;
|
|
13
|
+
reason: string;
|
|
14
|
+
count: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function countRedactionsByCategory(input: string): RedactionCategoryCount[];
|
|
11
17
|
export declare function redactSensitiveContent(input: string): RedactionResult;
|
|
12
18
|
export declare function redactSensitiveValue<T>(input: T): StructuredRedactionResult<T>;
|
|
@@ -1,30 +1,52 @@
|
|
|
1
1
|
const RULES = [
|
|
2
2
|
{
|
|
3
3
|
category: "private_key",
|
|
4
|
+
reason: "matched private key block",
|
|
4
5
|
pattern: /-----BEGIN [^-\r\n]*PRIVATE KEY-----[\s\S]*?-----END [^-\r\n]*PRIVATE KEY-----/gi,
|
|
5
6
|
replace: "[REDACTED PRIVATE KEY]",
|
|
6
7
|
},
|
|
7
8
|
{
|
|
8
9
|
category: "bearer_token",
|
|
10
|
+
reason: "matched bearer token",
|
|
9
11
|
pattern: /\bBearer\s+[A-Za-z0-9._~+\/-]{12,}={0,2}/gi,
|
|
10
12
|
replace: "Bearer [REDACTED]",
|
|
11
13
|
},
|
|
12
14
|
{
|
|
13
15
|
category: "npm_token",
|
|
16
|
+
reason: "matched npm auth token",
|
|
14
17
|
pattern: /(\b_?authToken\s*=\s*)[^\s\r\n]+/gi,
|
|
15
18
|
replace: "$1[REDACTED]",
|
|
16
19
|
},
|
|
17
20
|
{
|
|
18
21
|
category: "credential_assignment",
|
|
22
|
+
reason: "matched credential assignment",
|
|
19
23
|
pattern: /\b((?:access[_ -]?token|api[_ -]?key|secret|password|credential|token)\s*[:=]\s*)(["']?)([^\s,"'\]}]{8,})(["']?)/gi,
|
|
20
24
|
replace: "$1$2[REDACTED]$4",
|
|
21
25
|
},
|
|
22
26
|
{
|
|
23
27
|
category: "known_token_format",
|
|
28
|
+
reason: "matched known token format",
|
|
24
29
|
pattern: /\b(?:sk|ghp|github_pat)_[A-Za-z0-9_-]{16,}\b/g,
|
|
25
30
|
replace: "[REDACTED TOKEN]",
|
|
26
31
|
},
|
|
27
32
|
];
|
|
33
|
+
export function countRedactionsByCategory(input) {
|
|
34
|
+
const counts = new Map();
|
|
35
|
+
for (const rule of RULES) {
|
|
36
|
+
rule.pattern.lastIndex = 0;
|
|
37
|
+
const matches = input.match(rule.pattern);
|
|
38
|
+
if (matches && matches.length > 0) {
|
|
39
|
+
counts.set(rule.category, (counts.get(rule.category) || 0) + matches.length);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const result = [];
|
|
43
|
+
for (const rule of RULES) {
|
|
44
|
+
const count = counts.get(rule.category);
|
|
45
|
+
if (count)
|
|
46
|
+
result.push({ category: rule.category, reason: rule.reason, count });
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
28
50
|
export function redactSensitiveContent(input) {
|
|
29
51
|
let content = input;
|
|
30
52
|
const categories = [];
|