@runcore-sh/runcore 0.4.0 → 0.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/dictionary.json +2 -2
- package/dist/activity/log.js +2 -2
- package/dist/activity/log.js.map +1 -1
- package/dist/agents/governed-spawn.d.ts.map +1 -1
- package/dist/cli.js +101 -11
- package/dist/cli.js.map +1 -1
- package/dist/extensions/cache.d.ts +57 -0
- package/dist/extensions/cache.d.ts.map +1 -0
- package/dist/extensions/cache.js +173 -0
- package/dist/extensions/cache.js.map +1 -0
- package/dist/extensions/client.d.ts +55 -0
- package/dist/extensions/client.d.ts.map +1 -0
- package/dist/extensions/client.js +120 -0
- package/dist/extensions/client.js.map +1 -0
- package/dist/extensions/index.d.ts +13 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +12 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +50 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +166 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/manifest.d.ts +38 -0
- package/dist/extensions/manifest.d.ts.map +1 -0
- package/dist/extensions/manifest.js +17 -0
- package/dist/extensions/manifest.js.map +1 -0
- package/dist/extensions/stubs.d.ts +27 -0
- package/dist/extensions/stubs.d.ts.map +1 -0
- package/dist/extensions/stubs.js +45 -0
- package/dist/extensions/stubs.js.map +1 -0
- package/dist/lib/audit.js +2 -2
- package/dist/lib/audit.js.map +1 -1
- package/dist/lib/brain-migrate.d.ts +21 -0
- package/dist/lib/brain-migrate.d.ts.map +1 -0
- package/dist/lib/brain-migrate.js +137 -0
- package/dist/lib/brain-migrate.js.map +1 -0
- package/dist/lib/paths.d.ts +27 -0
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +65 -0
- package/dist/lib/paths.js.map +1 -1
- package/dist/llm/call-log.d.ts +40 -0
- package/dist/llm/call-log.d.ts.map +1 -0
- package/dist/llm/call-log.js +35 -0
- package/dist/llm/call-log.js.map +1 -0
- package/dist/llm/complete.d.ts +6 -0
- package/dist/llm/complete.d.ts.map +1 -1
- package/dist/llm/complete.js +27 -0
- package/dist/llm/complete.js.map +1 -1
- package/dist/mcp-server.js +118 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/memory/file-backed.d.ts +4 -0
- package/dist/memory/file-backed.d.ts.map +1 -1
- package/dist/memory/file-backed.js +4 -0
- package/dist/memory/file-backed.js.map +1 -1
- package/dist/memory/vector-index.d.ts +4 -12
- package/dist/memory/vector-index.d.ts.map +1 -1
- package/dist/memory/vector-index.js +11 -93
- package/dist/memory/vector-index.js.map +1 -1
- package/dist/search/brain-docs.d.ts +17 -7
- package/dist/search/brain-docs.d.ts.map +1 -1
- package/dist/search/brain-docs.js +170 -52
- package/dist/search/brain-docs.js.map +1 -1
- package/dist/search/brain-rag.d.ts +45 -0
- package/dist/search/brain-rag.d.ts.map +1 -0
- package/dist/search/brain-rag.js +275 -0
- package/dist/search/brain-rag.js.map +1 -0
- package/dist/search/chunker.d.ts +24 -0
- package/dist/search/chunker.d.ts.map +1 -0
- package/dist/search/chunker.js +95 -0
- package/dist/search/chunker.js.map +1 -0
- package/dist/search/embedder.d.ts +16 -0
- package/dist/search/embedder.d.ts.map +1 -0
- package/dist/search/embedder.js +108 -0
- package/dist/search/embedder.js.map +1 -0
- package/dist/search/file-watcher.d.ts +11 -0
- package/dist/search/file-watcher.d.ts.map +1 -0
- package/dist/search/file-watcher.js +86 -0
- package/dist/search/file-watcher.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +814 -472
- package/dist/server.js.map +1 -1
- package/dist/sessions/store.d.ts +9 -0
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js.map +1 -1
- package/dist/settings.d.ts +26 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +78 -2
- package/dist/settings.js.map +1 -1
- package/dist/tracing/init.d.ts +1 -1
- package/dist/tracing/init.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -2
- package/dist/utils/logger.js.map +1 -1
- package/module-tiers.json +164 -0
- package/package.json +9 -13
- package/public/avatar/cache/1184385ec5522b57.mp4 +0 -0
- package/public/avatar/cache/1f15f6a1ebd7e439.mp4 +0 -0
- package/public/avatar/cache/2c7e47ff0bdeb8d1.mp4 +0 -0
- package/public/avatar/cache/5f308566f7abb8f2.mp4 +0 -0
- package/public/avatar/cache/62f9cfba848d724e.mp4 +0 -0
- package/public/avatar/cache/6d64e657e6bf2aab.mp4 +0 -0
- package/public/avatar/cache/763ad0349e0b6f26.mp4 +0 -0
- package/public/avatar/cache/81a516cfd461b2b9.mp4 +0 -0
- package/public/avatar/cache/9366de15fd6910ca.mp4 +0 -0
- package/public/avatar/cache/ade41a846b283895.mp4 +0 -0
- package/public/avatar/cache/b6066e5c65383eec.mp4 +0 -0
- package/public/avatar/cache/edadb75d37891fc7.mp4 +0 -0
- package/public/avatar/cache/f0ae159640621dd9.mp4 +0 -0
- package/public/avatar/cache/fc2e5419adf29d96.mp4 +0 -0
- package/public/index.html +379 -59
- package/dist/agents/autonomous.js +0 -749
- package/dist/agents/autonomous.js.map +0 -1
- package/dist/agents/commit.js +0 -113
- package/dist/agents/commit.js.map +0 -1
- package/dist/agents/continue.js +0 -158
- package/dist/agents/continue.js.map +0 -1
- package/dist/agents/cooldown.js +0 -397
- package/dist/agents/cooldown.js.map +0 -1
- package/dist/agents/dedup-guard.js +0 -131
- package/dist/agents/dedup-guard.js.map +0 -1
- package/dist/agents/feed.js +0 -176
- package/dist/agents/feed.js.map +0 -1
- package/dist/agents/governance.js +0 -292
- package/dist/agents/governance.js.map +0 -1
- package/dist/agents/governed-spawn.js +0 -192
- package/dist/agents/governed-spawn.js.map +0 -1
- package/dist/agents/heartbeat.js +0 -324
- package/dist/agents/heartbeat.js.map +0 -1
- package/dist/agents/instance-manager.js +0 -850
- package/dist/agents/instance-manager.js.map +0 -1
- package/dist/agents/issue-reporter.js +0 -123
- package/dist/agents/issue-reporter.js.map +0 -1
- package/dist/agents/issues.js +0 -141
- package/dist/agents/issues.js.map +0 -1
- package/dist/agents/locks.js +0 -234
- package/dist/agents/locks.js.map +0 -1
- package/dist/agents/memory.js +0 -93
- package/dist/agents/memory.js.map +0 -1
- package/dist/agents/monitor.js +0 -235
- package/dist/agents/monitor.js.map +0 -1
- package/dist/agents/orchestration.js +0 -715
- package/dist/agents/orchestration.js.map +0 -1
- package/dist/agents/recover.js +0 -166
- package/dist/agents/recover.js.map +0 -1
- package/dist/agents/reflection.js +0 -199
- package/dist/agents/reflection.js.map +0 -1
- package/dist/agents/runtime/bus.js +0 -174
- package/dist/agents/runtime/bus.js.map +0 -1
- package/dist/agents/runtime/config.js +0 -101
- package/dist/agents/runtime/config.js.map +0 -1
- package/dist/agents/runtime/driver.js +0 -214
- package/dist/agents/runtime/driver.js.map +0 -1
- package/dist/agents/runtime/errors.js +0 -40
- package/dist/agents/runtime/errors.js.map +0 -1
- package/dist/agents/runtime/index.js +0 -54
- package/dist/agents/runtime/index.js.map +0 -1
- package/dist/agents/runtime/lifecycle.js +0 -116
- package/dist/agents/runtime/lifecycle.js.map +0 -1
- package/dist/agents/runtime/manager.js +0 -948
- package/dist/agents/runtime/manager.js.map +0 -1
- package/dist/agents/runtime/registry.js +0 -195
- package/dist/agents/runtime/registry.js.map +0 -1
- package/dist/agents/runtime/resources.js +0 -146
- package/dist/agents/runtime/resources.js.map +0 -1
- package/dist/agents/runtime/types.js +0 -24
- package/dist/agents/runtime/types.js.map +0 -1
- package/dist/agents/spawn-policy.js +0 -202
- package/dist/agents/spawn-policy.js.map +0 -1
- package/dist/agents/spawn.js +0 -970
- package/dist/agents/spawn.js.map +0 -1
- package/dist/agents/triage.js +0 -81
- package/dist/agents/triage.js.map +0 -1
- package/dist/agents/workflow.js +0 -543
- package/dist/agents/workflow.js.map +0 -1
- package/dist/avatar/client.js +0 -172
- package/dist/avatar/client.js.map +0 -1
- package/dist/avatar/sidecar.js +0 -125
- package/dist/avatar/sidecar.js.map +0 -1
- package/dist/browser/sessions.js +0 -122
- package/dist/browser/sessions.js.map +0 -1
- package/dist/capabilities/definitions/browser.js +0 -242
- package/dist/capabilities/definitions/browser.js.map +0 -1
- package/dist/channels/whatsapp.js +0 -200
- package/dist/channels/whatsapp.js.map +0 -1
- package/dist/credentials/store.js +0 -189
- package/dist/credentials/store.js.map +0 -1
- package/dist/files/deep-index.js +0 -337
- package/dist/files/deep-index.js.map +0 -1
- package/dist/files/extract.js +0 -33
- package/dist/files/extract.js.map +0 -1
- package/dist/files/gdrive.js +0 -246
- package/dist/files/gdrive.js.map +0 -1
- package/dist/github/client.js +0 -408
- package/dist/github/client.js.map +0 -1
- package/dist/github/commit-analysis.js +0 -276
- package/dist/github/commit-analysis.js.map +0 -1
- package/dist/github/contributor-stats.js +0 -119
- package/dist/github/contributor-stats.js.map +0 -1
- package/dist/github/issue-sla.js +0 -220
- package/dist/github/issue-sla.js.map +0 -1
- package/dist/github/issue-triage.js +0 -286
- package/dist/github/issue-triage.js.map +0 -1
- package/dist/github/pr-readiness.js +0 -197
- package/dist/github/pr-readiness.js.map +0 -1
- package/dist/github/pr-review.js +0 -410
- package/dist/github/pr-review.js.map +0 -1
- package/dist/github/release-notes.js +0 -227
- package/dist/github/release-notes.js.map +0 -1
- package/dist/github/repo-health.js +0 -303
- package/dist/github/repo-health.js.map +0 -1
- package/dist/github/retry.js +0 -117
- package/dist/github/retry.js.map +0 -1
- package/dist/github/types.js +0 -8
- package/dist/github/types.js.map +0 -1
- package/dist/github/webhooks.js +0 -153
- package/dist/github/webhooks.js.map +0 -1
- package/dist/google/auth.js +0 -325
- package/dist/google/auth.js.map +0 -1
- package/dist/google/calendar-timer.js +0 -91
- package/dist/google/calendar-timer.js.map +0 -1
- package/dist/google/calendar.js +0 -270
- package/dist/google/calendar.js.map +0 -1
- package/dist/google/docs.js +0 -309
- package/dist/google/docs.js.map +0 -1
- package/dist/google/gmail-send.js +0 -219
- package/dist/google/gmail-send.js.map +0 -1
- package/dist/google/gmail-timer.js +0 -223
- package/dist/google/gmail-timer.js.map +0 -1
- package/dist/google/gmail.js +0 -470
- package/dist/google/gmail.js.map +0 -1
- package/dist/google/plugin.js +0 -169
- package/dist/google/plugin.js.map +0 -1
- package/dist/google/tasks-timer.js +0 -107
- package/dist/google/tasks-timer.js.map +0 -1
- package/dist/google/tasks.js +0 -331
- package/dist/google/tasks.js.map +0 -1
- package/dist/google/temporal.js +0 -176
- package/dist/google/temporal.js.map +0 -1
- package/dist/integrations/gate.js +0 -100
- package/dist/integrations/gate.js.map +0 -1
- package/dist/integrations/github.js +0 -331
- package/dist/integrations/github.js.map +0 -1
- package/dist/integrations/google-tasks.js +0 -432
- package/dist/integrations/google-tasks.js.map +0 -1
- package/dist/mdns.js +0 -110
- package/dist/mdns.js.map +0 -1
- package/dist/notifications/channel.js +0 -83
- package/dist/notifications/channel.js.map +0 -1
- package/dist/notifications/channels/adapter.js +0 -55
- package/dist/notifications/channels/adapter.js.map +0 -1
- package/dist/notifications/channels/index.js +0 -6
- package/dist/notifications/channels/index.js.map +0 -1
- package/dist/notifications/channels/log.js +0 -29
- package/dist/notifications/channels/log.js.map +0 -1
- package/dist/notifications/email.js +0 -72
- package/dist/notifications/email.js.map +0 -1
- package/dist/notifications/engine.js +0 -198
- package/dist/notifications/engine.js.map +0 -1
- package/dist/notifications/index.js +0 -24
- package/dist/notifications/index.js.map +0 -1
- package/dist/notifications/phone.js +0 -48
- package/dist/notifications/phone.js.map +0 -1
- package/dist/notifications/sms.js +0 -65
- package/dist/notifications/sms.js.map +0 -1
- package/dist/notifications/types.js +0 -14
- package/dist/notifications/types.js.map +0 -1
- package/dist/notifications/webhook.js +0 -65
- package/dist/notifications/webhook.js.map +0 -1
- package/dist/resend/inbox.js +0 -199
- package/dist/resend/inbox.js.map +0 -1
- package/dist/resend/webhooks.js +0 -244
- package/dist/resend/webhooks.js.map +0 -1
- package/dist/search/browse.js +0 -225
- package/dist/search/browse.js.map +0 -1
- package/dist/search/perplexity.js +0 -41
- package/dist/search/perplexity.js.map +0 -1
- package/dist/slack/channels.js +0 -277
- package/dist/slack/channels.js.map +0 -1
- package/dist/slack/client.js +0 -468
- package/dist/slack/client.js.map +0 -1
- package/dist/slack/retry.js +0 -100
- package/dist/slack/retry.js.map +0 -1
- package/dist/slack/types.js +0 -52
- package/dist/slack/types.js.map +0 -1
- package/dist/slack/webhooks.js +0 -285
- package/dist/slack/webhooks.js.map +0 -1
- package/dist/stt/client.js +0 -66
- package/dist/stt/client.js.map +0 -1
- package/dist/stt/sidecar.js +0 -115
- package/dist/stt/sidecar.js.map +0 -1
- package/dist/tracing/bridge.js +0 -70
- package/dist/tracing/bridge.js.map +0 -1
- package/dist/tracing/correlation.js +0 -49
- package/dist/tracing/correlation.js.map +0 -1
- package/dist/tracing/index.js +0 -18
- package/dist/tracing/index.js.map +0 -1
- package/dist/tracing/init.js +0 -81
- package/dist/tracing/init.js.map +0 -1
- package/dist/tracing/instrument.js +0 -145
- package/dist/tracing/instrument.js.map +0 -1
- package/dist/tracing/middleware.js +0 -69
- package/dist/tracing/middleware.js.map +0 -1
- package/dist/tracing/tracer.js +0 -327
- package/dist/tracing/tracer.js.map +0 -1
- package/dist/tts/client.js +0 -48
- package/dist/tts/client.js.map +0 -1
- package/dist/tts/sidecar.js +0 -148
- package/dist/tts/sidecar.js.map +0 -1
- package/dist/twilio/call.js +0 -79
- package/dist/twilio/call.js.map +0 -1
- package/dist/vault/matcher.js +0 -197
- package/dist/vault/matcher.js.map +0 -1
- package/dist/vault/personal.js +0 -163
- package/dist/vault/personal.js.map +0 -1
- package/dist/vault/policy.js +0 -159
- package/dist/vault/policy.js.map +0 -1
- package/dist/vault/store.js +0 -122
- package/dist/vault/store.js.map +0 -1
- package/dist/vault/transfer.js +0 -188
- package/dist/vault/transfer.js.map +0 -1
- package/dist/volumes/index.js +0 -2
- package/dist/volumes/index.js.map +0 -1
- package/dist/volumes/manager.js +0 -462
- package/dist/volumes/manager.js.map +0 -1
- package/dist/volumes/types.js +0 -8
- package/dist/volumes/types.js.map +0 -1
- package/dist/webhooks/config.js +0 -214
- package/dist/webhooks/config.js.map +0 -1
- package/dist/webhooks/event-log.js +0 -132
- package/dist/webhooks/event-log.js.map +0 -1
- package/dist/webhooks/handler.js +0 -103
- package/dist/webhooks/handler.js.map +0 -1
- package/dist/webhooks/handlers.js +0 -231
- package/dist/webhooks/handlers.js.map +0 -1
- package/dist/webhooks/index.js +0 -33
- package/dist/webhooks/index.js.map +0 -1
- package/dist/webhooks/mount.js +0 -400
- package/dist/webhooks/mount.js.map +0 -1
- package/dist/webhooks/registry.js +0 -143
- package/dist/webhooks/registry.js.map +0 -1
- package/dist/webhooks/relay.js +0 -53
- package/dist/webhooks/relay.js.map +0 -1
- package/dist/webhooks/retry.js +0 -270
- package/dist/webhooks/retry.js.map +0 -1
- package/dist/webhooks/router.js +0 -290
- package/dist/webhooks/router.js.map +0 -1
- package/dist/webhooks/twilio.js +0 -129
- package/dist/webhooks/twilio.js.map +0 -1
- package/dist/webhooks/types.js +0 -8
- package/dist/webhooks/types.js.map +0 -1
- package/dist/webhooks/verify.js +0 -154
- package/dist/webhooks/verify.js.map +0 -1
package/dist/agents/cooldown.js
DELETED
|
@@ -1,397 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Task Cooldown Manager — prevents repeatedly-failing tasks from being
|
|
3
|
-
* retried too aggressively, reducing GC pressure from excessive agent spawns.
|
|
4
|
-
*
|
|
5
|
-
* Tracks failure counts per board task ID with exponential backoff cooldowns.
|
|
6
|
-
* Persists state to disk so cooldowns survive process restarts.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* const cooldown = TaskCooldownManager.getInstance();
|
|
10
|
-
* await cooldown.init();
|
|
11
|
-
* cooldown.recordFailure("task-123", "Build feature X", "TypeError: ...");
|
|
12
|
-
* if (cooldown.isOnCooldown("task-123")) { skip task }
|
|
13
|
-
*/
|
|
14
|
-
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
15
|
-
import { join, dirname } from "node:path";
|
|
16
|
-
import { createLogger } from "../utils/logger.js";
|
|
17
|
-
import { logActivity } from "../activity/log.js";
|
|
18
|
-
import { recordCooldownActivation, recordCooldownSkip } from "../metrics/firewall-metrics.js";
|
|
19
|
-
import { BRAIN_DIR } from "../lib/paths.js";
|
|
20
|
-
const log = createLogger("cooldown");
|
|
21
|
-
const DEFAULT_CONFIG = {
|
|
22
|
-
baseCooldownMs: 30 * 60 * 1000, // 30 min
|
|
23
|
-
maxCooldownMs: 4 * 60 * 60 * 1000, // 4 hours
|
|
24
|
-
backoffMultiplier: 2,
|
|
25
|
-
persistPath: join(BRAIN_DIR, "agents", "cooldowns.json"),
|
|
26
|
-
maxEntries: 200,
|
|
27
|
-
maxTotalFailures: 6,
|
|
28
|
-
};
|
|
29
|
-
// ─── Singleton ──────────────────────────────────────────────────────────────
|
|
30
|
-
let instance = null;
|
|
31
|
-
// ─── Manager ────────────────────────────────────────────────────────────────
|
|
32
|
-
export class TaskCooldownManager {
|
|
33
|
-
config;
|
|
34
|
-
entries = new Map();
|
|
35
|
-
dirty = false;
|
|
36
|
-
persistTimer = null;
|
|
37
|
-
constructor(config) {
|
|
38
|
-
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
39
|
-
}
|
|
40
|
-
/** Get or create the singleton instance. */
|
|
41
|
-
static getInstance(config) {
|
|
42
|
-
if (!instance) {
|
|
43
|
-
instance = new TaskCooldownManager(config);
|
|
44
|
-
}
|
|
45
|
-
return instance;
|
|
46
|
-
}
|
|
47
|
-
/** Reset singleton (for testing). */
|
|
48
|
-
static resetInstance() {
|
|
49
|
-
if (instance) {
|
|
50
|
-
instance.shutdown();
|
|
51
|
-
instance = null;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
|
55
|
-
/** Load persisted cooldown state from disk. */
|
|
56
|
-
async init() {
|
|
57
|
-
try {
|
|
58
|
-
const raw = await readFile(this.config.persistPath, "utf-8");
|
|
59
|
-
const data = JSON.parse(raw);
|
|
60
|
-
for (const entry of data) {
|
|
61
|
-
this.entries.set(entry.taskId, entry);
|
|
62
|
-
}
|
|
63
|
-
// Prune expired entries on load
|
|
64
|
-
this.pruneExpired();
|
|
65
|
-
log.info(`Loaded ${this.entries.size} cooldown entries from disk`);
|
|
66
|
-
}
|
|
67
|
-
catch (err) {
|
|
68
|
-
const code = err.code;
|
|
69
|
-
if (code === "ENOENT") {
|
|
70
|
-
log.info("No cooldown state on disk, starting fresh");
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
log.warn(`Failed to load cooldown state: ${err.message}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
/** Flush pending changes and stop the persist timer. */
|
|
78
|
-
shutdown() {
|
|
79
|
-
if (this.persistTimer) {
|
|
80
|
-
clearTimeout(this.persistTimer);
|
|
81
|
-
this.persistTimer = null;
|
|
82
|
-
}
|
|
83
|
-
if (this.dirty) {
|
|
84
|
-
this.persistSync();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
// ── Core API ──────────────────────────────────────────────────────────────
|
|
88
|
-
/**
|
|
89
|
-
* Record a task failure. Increments the failure count and resets the
|
|
90
|
-
* cooldown timer. Schedules a debounced persist to disk.
|
|
91
|
-
*/
|
|
92
|
-
recordFailure(taskId, label, error) {
|
|
93
|
-
const existing = this.entries.get(taskId);
|
|
94
|
-
// DASH-143: Dedup burst — if the same task was recorded within 30s,
|
|
95
|
-
// skip to prevent double-counting from multiple recording paths
|
|
96
|
-
// (immediate failure handler + batch completion handler).
|
|
97
|
-
if (existing) {
|
|
98
|
-
const sinceLast = Date.now() - new Date(existing.lastFailedAt).getTime();
|
|
99
|
-
if (sinceLast < 30_000) {
|
|
100
|
-
log.debug(`Skipping duplicate failure record for ${taskId} (${sinceLast}ms since last)`);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
const failureCount = (existing?.failureCount ?? 0) + 1;
|
|
105
|
-
const entry = {
|
|
106
|
-
taskId,
|
|
107
|
-
lastFailedAt: new Date().toISOString(),
|
|
108
|
-
failureCount,
|
|
109
|
-
lastError: error?.slice(0, 300),
|
|
110
|
-
label: label ?? existing?.label,
|
|
111
|
-
};
|
|
112
|
-
this.entries.set(taskId, entry);
|
|
113
|
-
this.dirty = true;
|
|
114
|
-
this.schedulePersist();
|
|
115
|
-
recordCooldownActivation();
|
|
116
|
-
// Check if task is now permanently blocked
|
|
117
|
-
if (failureCount >= this.config.maxTotalFailures) {
|
|
118
|
-
log.warn(`Task ${taskId} BLOCKED after ${failureCount} failures — needs manual clearCooldown()`, {
|
|
119
|
-
taskId,
|
|
120
|
-
failureCount,
|
|
121
|
-
label,
|
|
122
|
-
});
|
|
123
|
-
logActivity({
|
|
124
|
-
source: "agent",
|
|
125
|
-
summary: `BLOCKED: ${label ?? taskId} permanently blocked after ${failureCount} failures — needs human intervention`,
|
|
126
|
-
detail: error?.slice(0, 200),
|
|
127
|
-
actionLabel: "AUTONOMOUS",
|
|
128
|
-
reason: "task permanently blocked (DASH-143 hard cap)",
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
const cooldownMs = this.calculateCooldown(failureCount);
|
|
133
|
-
const cooldownMin = Math.round(cooldownMs / 60_000);
|
|
134
|
-
log.info(`Task ${taskId} failed ${failureCount} time(s), cooldown ${cooldownMin}min`, {
|
|
135
|
-
taskId,
|
|
136
|
-
failureCount,
|
|
137
|
-
cooldownMin,
|
|
138
|
-
label,
|
|
139
|
-
});
|
|
140
|
-
logActivity({
|
|
141
|
-
source: "agent",
|
|
142
|
-
summary: `Cooldown: ${label ?? taskId} failed ${failureCount}x, backing off ${cooldownMin}min`,
|
|
143
|
-
detail: error?.slice(0, 200),
|
|
144
|
-
actionLabel: "AUTONOMOUS",
|
|
145
|
-
reason: "task cooldown escalation",
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Check if a task is currently on cooldown (or permanently blocked).
|
|
151
|
-
*
|
|
152
|
-
* DASH-143 fix: cooldown expiration no longer deletes the entry. Failure
|
|
153
|
-
* history is preserved so the hard cap (maxTotalFailures) works across
|
|
154
|
-
* cooldown cycles. Only clearCooldown() resets failure history.
|
|
155
|
-
*/
|
|
156
|
-
isOnCooldown(taskId) {
|
|
157
|
-
const entry = this.entries.get(taskId);
|
|
158
|
-
if (!entry)
|
|
159
|
-
return false;
|
|
160
|
-
// Hard cap: permanently blocked until manual clearCooldown()
|
|
161
|
-
if (entry.failureCount >= this.config.maxTotalFailures)
|
|
162
|
-
return true;
|
|
163
|
-
const cooldownMs = this.calculateCooldown(entry.failureCount);
|
|
164
|
-
const elapsed = Date.now() - new Date(entry.lastFailedAt).getTime();
|
|
165
|
-
// Cooldown expired — task is retryable, but keep the entry so
|
|
166
|
-
// failureCount accumulates across cycles (DASH-143)
|
|
167
|
-
if (elapsed >= cooldownMs)
|
|
168
|
-
return false;
|
|
169
|
-
return true;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Check if a task has been permanently blocked (exceeded maxTotalFailures).
|
|
173
|
-
* These tasks will never be retried until manually cleared.
|
|
174
|
-
*/
|
|
175
|
-
isBlocked(taskId) {
|
|
176
|
-
const entry = this.entries.get(taskId);
|
|
177
|
-
return entry != null && entry.failureCount >= this.config.maxTotalFailures;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Check cooldown and log a skip message if the task is on cooldown.
|
|
181
|
-
* Returns true if the task should be skipped.
|
|
182
|
-
*/
|
|
183
|
-
shouldSkip(taskId) {
|
|
184
|
-
if (!this.isOnCooldown(taskId))
|
|
185
|
-
return false;
|
|
186
|
-
recordCooldownSkip();
|
|
187
|
-
if (this.isBlocked(taskId)) {
|
|
188
|
-
const entry = this.entries.get(taskId);
|
|
189
|
-
log.info(`Skipping task ${taskId} — permanently blocked after ${entry?.failureCount} failures (needs manual clear)`, {
|
|
190
|
-
taskId,
|
|
191
|
-
failureCount: entry?.failureCount,
|
|
192
|
-
label: entry?.label,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
const status = this.getStatus(taskId);
|
|
197
|
-
if (status) {
|
|
198
|
-
const remainMin = Math.round(status.remainingMs / 60_000);
|
|
199
|
-
log.info(`Skipping task ${taskId} — on cooldown for ${remainMin} more min (${status.failureCount} failures)`, {
|
|
200
|
-
taskId,
|
|
201
|
-
remainingMin: remainMin,
|
|
202
|
-
failureCount: status.failureCount,
|
|
203
|
-
label: status.label,
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return true;
|
|
208
|
-
}
|
|
209
|
-
/** Get detailed status for a single task's cooldown. */
|
|
210
|
-
getStatus(taskId) {
|
|
211
|
-
const entry = this.entries.get(taskId);
|
|
212
|
-
if (!entry)
|
|
213
|
-
return null;
|
|
214
|
-
// Blocked tasks: report as permanently on cooldown
|
|
215
|
-
if (entry.failureCount >= this.config.maxTotalFailures) {
|
|
216
|
-
return {
|
|
217
|
-
taskId,
|
|
218
|
-
label: entry.label,
|
|
219
|
-
failureCount: entry.failureCount,
|
|
220
|
-
cooldownMs: Infinity,
|
|
221
|
-
remainingMs: Infinity,
|
|
222
|
-
expiresAt: "blocked",
|
|
223
|
-
lastFailedAt: entry.lastFailedAt,
|
|
224
|
-
lastError: entry.lastError,
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
const cooldownMs = this.calculateCooldown(entry.failureCount);
|
|
228
|
-
const elapsed = Date.now() - new Date(entry.lastFailedAt).getTime();
|
|
229
|
-
const remainingMs = Math.max(0, cooldownMs - elapsed);
|
|
230
|
-
if (remainingMs === 0)
|
|
231
|
-
return null;
|
|
232
|
-
return {
|
|
233
|
-
taskId,
|
|
234
|
-
label: entry.label,
|
|
235
|
-
failureCount: entry.failureCount,
|
|
236
|
-
cooldownMs,
|
|
237
|
-
remainingMs,
|
|
238
|
-
expiresAt: new Date(new Date(entry.lastFailedAt).getTime() + cooldownMs).toISOString(),
|
|
239
|
-
lastFailedAt: entry.lastFailedAt,
|
|
240
|
-
lastError: entry.lastError,
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
/** Clear cooldown for a specific task (e.g., after manual intervention). */
|
|
244
|
-
clearCooldown(taskId) {
|
|
245
|
-
if (this.entries.delete(taskId)) {
|
|
246
|
-
this.dirty = true;
|
|
247
|
-
this.schedulePersist();
|
|
248
|
-
log.info(`Cooldown cleared for task ${taskId}`);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
/** Clear all cooldowns. */
|
|
252
|
-
clearAll() {
|
|
253
|
-
if (this.entries.size > 0) {
|
|
254
|
-
this.entries.clear();
|
|
255
|
-
this.dirty = true;
|
|
256
|
-
this.schedulePersist();
|
|
257
|
-
log.info("All cooldowns cleared");
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Remove expired cooldown entries that are safe to prune.
|
|
262
|
-
* Entries at or above the hard failure cap are NEVER pruned — they
|
|
263
|
-
* represent permanently blocked tasks that need manual clearCooldown().
|
|
264
|
-
* Entries with failure history but expired cooldowns are pruned after
|
|
265
|
-
* 24 hours of inactivity (enough time that if the task succeeds on
|
|
266
|
-
* the next retry, the entry is no longer needed).
|
|
267
|
-
*/
|
|
268
|
-
pruneExpired() {
|
|
269
|
-
const now = Date.now();
|
|
270
|
-
const STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
271
|
-
let pruned = 0;
|
|
272
|
-
for (const [taskId, entry] of this.entries) {
|
|
273
|
-
// Never prune permanently blocked entries
|
|
274
|
-
if (entry.failureCount >= this.config.maxTotalFailures)
|
|
275
|
-
continue;
|
|
276
|
-
const cooldownMs = this.calculateCooldown(entry.failureCount);
|
|
277
|
-
const elapsed = now - new Date(entry.lastFailedAt).getTime();
|
|
278
|
-
// Only prune if cooldown expired AND entry is stale (24h inactive)
|
|
279
|
-
if (elapsed >= cooldownMs + STALE_THRESHOLD_MS) {
|
|
280
|
-
this.entries.delete(taskId);
|
|
281
|
-
pruned++;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
if (pruned > 0) {
|
|
285
|
-
this.dirty = true;
|
|
286
|
-
this.schedulePersist();
|
|
287
|
-
log.info(`Pruned ${pruned} stale cooldown entries`);
|
|
288
|
-
}
|
|
289
|
-
return pruned;
|
|
290
|
-
}
|
|
291
|
-
/** List all active cooldowns and blocked tasks with status details. */
|
|
292
|
-
listActiveCooldowns() {
|
|
293
|
-
this.pruneExpired();
|
|
294
|
-
const results = [];
|
|
295
|
-
for (const [taskId] of this.entries) {
|
|
296
|
-
const status = this.getStatus(taskId);
|
|
297
|
-
if (status)
|
|
298
|
-
results.push(status);
|
|
299
|
-
}
|
|
300
|
-
// Blocked tasks (Infinity) sort last, then by remaining time
|
|
301
|
-
results.sort((a, b) => {
|
|
302
|
-
if (a.remainingMs === Infinity && b.remainingMs === Infinity)
|
|
303
|
-
return 0;
|
|
304
|
-
if (a.remainingMs === Infinity)
|
|
305
|
-
return 1;
|
|
306
|
-
if (b.remainingMs === Infinity)
|
|
307
|
-
return -1;
|
|
308
|
-
return a.remainingMs - b.remainingMs;
|
|
309
|
-
});
|
|
310
|
-
return results;
|
|
311
|
-
}
|
|
312
|
-
/** Get summary for planner context (what tasks are on cooldown or blocked). */
|
|
313
|
-
getCooldownContext() {
|
|
314
|
-
const active = this.listActiveCooldowns();
|
|
315
|
-
if (active.length === 0)
|
|
316
|
-
return null;
|
|
317
|
-
const lines = active.map((s) => {
|
|
318
|
-
if (s.expiresAt === "blocked") {
|
|
319
|
-
return `- ${s.label ?? s.taskId}: BLOCKED (${s.failureCount} failures, needs human intervention)`;
|
|
320
|
-
}
|
|
321
|
-
const remainMin = Math.round(s.remainingMs / 60_000);
|
|
322
|
-
return `- ${s.label ?? s.taskId}: failed ${s.failureCount}x, ${remainMin}min remaining`;
|
|
323
|
-
});
|
|
324
|
-
return lines.join("\n");
|
|
325
|
-
}
|
|
326
|
-
/** Get the failure count for a task (0 if not tracked). */
|
|
327
|
-
getFailureCount(taskId) {
|
|
328
|
-
return this.entries.get(taskId)?.failureCount ?? 0;
|
|
329
|
-
}
|
|
330
|
-
/** Get total number of tracked entries (active + expired pending prune). */
|
|
331
|
-
get size() {
|
|
332
|
-
return this.entries.size;
|
|
333
|
-
}
|
|
334
|
-
// ── Internals ─────────────────────────────────────────────────────────────
|
|
335
|
-
/**
|
|
336
|
-
* Calculate exponential backoff cooldown.
|
|
337
|
-
* Formula: base × multiplier^(failureCount - 1), capped at max.
|
|
338
|
-
*
|
|
339
|
-
* Failures → Cooldown (with defaults):
|
|
340
|
-
* 1 → 30min
|
|
341
|
-
* 2 → 60min
|
|
342
|
-
* 3 → 120min
|
|
343
|
-
* 4 → 240min (capped at 4hr)
|
|
344
|
-
* 5+ → 240min (capped at 4hr)
|
|
345
|
-
*/
|
|
346
|
-
calculateCooldown(failureCount) {
|
|
347
|
-
const { baseCooldownMs, maxCooldownMs, backoffMultiplier } = this.config;
|
|
348
|
-
return Math.min(baseCooldownMs * Math.pow(backoffMultiplier, Math.max(0, failureCount - 1)), maxCooldownMs);
|
|
349
|
-
}
|
|
350
|
-
/** Debounced persist — waits 5s after last change before writing to disk. */
|
|
351
|
-
schedulePersist() {
|
|
352
|
-
if (this.persistTimer)
|
|
353
|
-
return;
|
|
354
|
-
this.persistTimer = setTimeout(() => {
|
|
355
|
-
this.persistTimer = null;
|
|
356
|
-
this.persistAsync().catch((err) => {
|
|
357
|
-
log.warn(`Failed to persist cooldowns: ${err.message}`);
|
|
358
|
-
});
|
|
359
|
-
}, 5_000);
|
|
360
|
-
}
|
|
361
|
-
async persistAsync() {
|
|
362
|
-
if (!this.dirty)
|
|
363
|
-
return;
|
|
364
|
-
// Prune before persisting
|
|
365
|
-
this.pruneExpired();
|
|
366
|
-
// Enforce max entries: keep the most recent
|
|
367
|
-
if (this.entries.size > this.config.maxEntries) {
|
|
368
|
-
const sorted = [...this.entries.entries()]
|
|
369
|
-
.sort((a, b) => new Date(b[1].lastFailedAt).getTime() - new Date(a[1].lastFailedAt).getTime());
|
|
370
|
-
this.entries = new Map(sorted.slice(0, this.config.maxEntries));
|
|
371
|
-
}
|
|
372
|
-
const data = [...this.entries.values()];
|
|
373
|
-
try {
|
|
374
|
-
await mkdir(dirname(this.config.persistPath), { recursive: true });
|
|
375
|
-
await writeFile(this.config.persistPath, JSON.stringify(data, null, 2), "utf-8");
|
|
376
|
-
this.dirty = false;
|
|
377
|
-
log.debug(`Persisted ${data.length} cooldown entries to disk`);
|
|
378
|
-
}
|
|
379
|
-
catch (err) {
|
|
380
|
-
log.warn(`Failed to write cooldown file: ${err.message}`);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
/** Synchronous persist for shutdown path (best-effort). */
|
|
384
|
-
persistSync() {
|
|
385
|
-
try {
|
|
386
|
-
const { writeFileSync, mkdirSync } = require("node:fs");
|
|
387
|
-
const data = [...this.entries.values()];
|
|
388
|
-
mkdirSync(dirname(this.config.persistPath), { recursive: true });
|
|
389
|
-
writeFileSync(this.config.persistPath, JSON.stringify(data, null, 2), "utf-8");
|
|
390
|
-
this.dirty = false;
|
|
391
|
-
}
|
|
392
|
-
catch {
|
|
393
|
-
// Best effort on shutdown
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
//# sourceMappingURL=cooldown.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cooldown.js","sourceRoot":"","sources":["../../src/agents/cooldown.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dedup Guard — prevents the autonomous planner from spawning agents
|
|
3
|
-
* that duplicate work already in progress or recently completed.
|
|
4
|
-
*
|
|
5
|
-
* Three checks, cheapest first:
|
|
6
|
-
* 1. Active agent with same label (~0ms, in-memory)
|
|
7
|
-
* 2. Recent task with same label (~5ms, reads task JSON files)
|
|
8
|
-
* 3. Recent git commits touching related files (~50ms, shell out to git)
|
|
9
|
-
*/
|
|
10
|
-
import { activeProcesses } from "./spawn.js";
|
|
11
|
-
import { listTasks } from "./store.js";
|
|
12
|
-
import { createLogger } from "../utils/logger.js";
|
|
13
|
-
import { gitAvailable } from "../utils/git.js";
|
|
14
|
-
const log = createLogger("dedup-guard");
|
|
15
|
-
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
16
|
-
const DEDUP_RECENT_WINDOW_MS = 2 * 60 * 60 * 1000; // 2 hours
|
|
17
|
-
/** Shorter window for failed tasks — blocks immediate re-planning while
|
|
18
|
-
* cooldown manager handles longer-term backoff (DASH-143). */
|
|
19
|
-
const DEDUP_FAILED_WINDOW_MS = 5 * 60 * 1000; // 5 minutes
|
|
20
|
-
const GIT_LOOKBACK_MINUTES = 30;
|
|
21
|
-
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
22
|
-
/** Normalize a label for fuzzy matching: lowercase, trim whitespace. */
|
|
23
|
-
function normalize(label) {
|
|
24
|
-
return label.toLowerCase().trim();
|
|
25
|
-
}
|
|
26
|
-
/** Fuzzy match: either label contains the other (after normalization). */
|
|
27
|
-
function fuzzyMatch(a, b) {
|
|
28
|
-
const na = normalize(a);
|
|
29
|
-
const nb = normalize(b);
|
|
30
|
-
return na.includes(nb) || nb.includes(na);
|
|
31
|
-
}
|
|
32
|
-
/** Extract file paths from a prompt string. */
|
|
33
|
-
function extractFilePaths(prompt) {
|
|
34
|
-
const regex = /(?:src\/|brain\/|public\/)[^\s"'`,)}\]]+(?:\.ts|\.js|\.md|\.json|\.yaml|\.yml)?/g;
|
|
35
|
-
const matches = prompt.match(regex) ?? [];
|
|
36
|
-
// Deduplicate
|
|
37
|
-
return [...new Set(matches)];
|
|
38
|
-
}
|
|
39
|
-
// ─── Main ───────────────────────────────────────────────────────────────────
|
|
40
|
-
export async function checkDedup(label, prompt) {
|
|
41
|
-
// Check 1: Active agent with same label (~0ms)
|
|
42
|
-
for (const [, proc] of activeProcesses) {
|
|
43
|
-
// activeProcesses is Map<taskId, ChildProcess> — we need labels from tasks
|
|
44
|
-
// Skip this map-based check; we'll rely on the task list check below
|
|
45
|
-
void proc;
|
|
46
|
-
}
|
|
47
|
-
// Better: check running tasks via store (covers both pool and direct spawns)
|
|
48
|
-
try {
|
|
49
|
-
const tasks = await listTasks();
|
|
50
|
-
for (const t of tasks) {
|
|
51
|
-
if (t.status === "running" && fuzzyMatch(t.label, label)) {
|
|
52
|
-
return {
|
|
53
|
-
blocked: true,
|
|
54
|
-
reason: `Active agent already running: "${t.label}"`,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
catch (err) {
|
|
60
|
-
log.debug(`Check 1 (active agents) failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
61
|
-
}
|
|
62
|
-
// Check 2: Recent task with same label (~5ms)
|
|
63
|
-
try {
|
|
64
|
-
const tasks = await listTasks();
|
|
65
|
-
const cutoff = Date.now() - DEDUP_RECENT_WINDOW_MS;
|
|
66
|
-
const failedCutoff = Date.now() - DEDUP_FAILED_WINDOW_MS;
|
|
67
|
-
for (const t of tasks) {
|
|
68
|
-
const ts = t.finishedAt || t.createdAt;
|
|
69
|
-
if (!ts)
|
|
70
|
-
continue;
|
|
71
|
-
const taskTime = new Date(ts).getTime();
|
|
72
|
-
if (t.status === "running" || t.status === "completed") {
|
|
73
|
-
if (taskTime < cutoff)
|
|
74
|
-
continue;
|
|
75
|
-
if (fuzzyMatch(t.label, label)) {
|
|
76
|
-
return {
|
|
77
|
-
blocked: true,
|
|
78
|
-
reason: `Recent task (${t.status}) with same label: "${t.label}"`,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
else if (t.status === "failed") {
|
|
83
|
-
// DASH-143: Block re-spawning recently-failed tasks — prevents
|
|
84
|
-
// rapid retry loops before cooldown manager kicks in.
|
|
85
|
-
if (taskTime < failedCutoff)
|
|
86
|
-
continue;
|
|
87
|
-
if (fuzzyMatch(t.label, label)) {
|
|
88
|
-
return {
|
|
89
|
-
blocked: true,
|
|
90
|
-
reason: `Recently failed task (cooldown active): "${t.label}"`,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (err) {
|
|
97
|
-
log.debug(`Check 2 (recent tasks) failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
98
|
-
}
|
|
99
|
-
// Check 3: Recent agent git commits touching related files (~50ms)
|
|
100
|
-
// Only blocks on commits made by autonomous agents (contains "Auto-committed"
|
|
101
|
-
// in the git log). Human/manual commits should not prevent agents from working.
|
|
102
|
-
// Git is an optional signal source — skip silently if unavailable.
|
|
103
|
-
if (gitAvailable())
|
|
104
|
-
try {
|
|
105
|
-
const { execSync } = await import("node:child_process");
|
|
106
|
-
const paths = extractFilePaths(prompt);
|
|
107
|
-
if (paths.length > 0) {
|
|
108
|
-
const pathArgs = paths.map((p) => `"${p}"`).join(" ");
|
|
109
|
-
const cmd = `git log --oneline --since="${GIT_LOOKBACK_MINUTES} minutes ago" --grep="Auto-committed" -- ${pathArgs}`;
|
|
110
|
-
const result = execSync(cmd, {
|
|
111
|
-
encoding: "utf-8",
|
|
112
|
-
timeout: 5000,
|
|
113
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
114
|
-
}).trim();
|
|
115
|
-
if (result.length > 0) {
|
|
116
|
-
const commitCount = result.split("\n").length;
|
|
117
|
-
const firstCommit = result.split("\n")[0];
|
|
118
|
-
return {
|
|
119
|
-
blocked: true,
|
|
120
|
-
reason: `${commitCount} recent agent commit(s) touching related files: ${firstCommit}`,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
catch {
|
|
126
|
-
// Git command failed — fail open (don't block)
|
|
127
|
-
log.debug("Check 3 (git commits) failed or no git — skipping");
|
|
128
|
-
}
|
|
129
|
-
return { blocked: false };
|
|
130
|
-
}
|
|
131
|
-
//# sourceMappingURL=dedup-guard.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dedup-guard.js","sourceRoot":"","sources":["../../src/agents/dedup-guard.ts"],"names":[],"mappings":"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"}
|