@cat-factory/worker 0.137.2 → 0.138.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/app.d.ts.map +1 -1
  2. package/dist/app.js +33 -0
  3. package/dist/app.js.map +1 -1
  4. package/dist/index.d.ts +2 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +111 -118
  7. package/dist/index.js.map +1 -1
  8. package/dist/infrastructure/config/index.d.ts.map +1 -1
  9. package/dist/infrastructure/config/index.js +4 -0
  10. package/dist/infrastructure/config/index.js.map +1 -1
  11. package/dist/infrastructure/container-account-settings.d.ts +13 -0
  12. package/dist/infrastructure/container-account-settings.d.ts.map +1 -0
  13. package/dist/infrastructure/container-account-settings.js +34 -0
  14. package/dist/infrastructure/container-account-settings.js.map +1 -0
  15. package/dist/infrastructure/container-artifact-storage.d.ts +16 -0
  16. package/dist/infrastructure/container-artifact-storage.d.ts.map +1 -0
  17. package/dist/infrastructure/container-artifact-storage.js +40 -0
  18. package/dist/infrastructure/container-artifact-storage.js.map +1 -0
  19. package/dist/infrastructure/container-assembly.d.ts.map +1 -1
  20. package/dist/infrastructure/container-assembly.js +5 -1
  21. package/dist/infrastructure/container-assembly.js.map +1 -1
  22. package/dist/infrastructure/container-executor-deps.d.ts.map +1 -1
  23. package/dist/infrastructure/container-executor-deps.js +4 -1
  24. package/dist/infrastructure/container-executor-deps.js.map +1 -1
  25. package/dist/infrastructure/container-shared-services.d.ts +1 -1
  26. package/dist/infrastructure/container-shared-services.d.ts.map +1 -1
  27. package/dist/infrastructure/container-shared-services.js +3 -1
  28. package/dist/infrastructure/container-shared-services.js.map +1 -1
  29. package/dist/infrastructure/container.d.ts +5 -21
  30. package/dist/infrastructure/container.d.ts.map +1 -1
  31. package/dist/infrastructure/container.js +12 -57
  32. package/dist/infrastructure/container.js.map +1 -1
  33. package/dist/infrastructure/env.d.ts +4 -0
  34. package/dist/infrastructure/env.d.ts.map +1 -1
  35. package/dist/infrastructure/env.js.map +1 -1
  36. package/dist/infrastructure/observability/cronSweep.d.ts +33 -0
  37. package/dist/infrastructure/observability/cronSweep.d.ts.map +1 -0
  38. package/dist/infrastructure/observability/cronSweep.js +41 -0
  39. package/dist/infrastructure/observability/cronSweep.js.map +1 -0
  40. package/dist/infrastructure/observability/operationalFlush.d.ts +15 -0
  41. package/dist/infrastructure/observability/operationalFlush.d.ts.map +1 -0
  42. package/dist/infrastructure/observability/operationalFlush.js +64 -0
  43. package/dist/infrastructure/observability/operationalFlush.js.map +1 -0
  44. package/dist/infrastructure/repositories/D1AgentRunRepository.d.ts +1 -0
  45. package/dist/infrastructure/repositories/D1AgentRunRepository.d.ts.map +1 -1
  46. package/dist/infrastructure/repositories/D1AgentRunRepository.js +14 -1
  47. package/dist/infrastructure/repositories/D1AgentRunRepository.js.map +1 -1
  48. package/dist/infrastructure/workflows/retention.d.ts +18 -4
  49. package/dist/infrastructure/workflows/retention.d.ts.map +1 -1
  50. package/dist/infrastructure/workflows/retention.js +22 -19
  51. package/dist/infrastructure/workflows/retention.js.map +1 -1
  52. package/dist/infrastructure/workflows/sweeper.d.ts +11 -2
  53. package/dist/infrastructure/workflows/sweeper.d.ts.map +1 -1
  54. package/dist/infrastructure/workflows/sweeper.js +11 -1
  55. package/dist/infrastructure/workflows/sweeper.js.map +1 -1
  56. package/migrations/0076_agent_runs_redrive_count.sql +20 -0
  57. package/package.json +18 -18
@@ -1,4 +1,4 @@
1
- import type { AgentContextSnapshotRepository, AgentSearchQueryRepository, Clock, CommitProjectionRepository, LlmCallMetricRepository, NotificationRepository, PasswordResetTokenRepository, PipelineScheduleRepository, ProvisioningLogRepository, RateLimitRepository, SubscriptionQuotaCycleRepository, TokenUsageRepository } from '@cat-factory/kernel';
1
+ import type { AgentContextSnapshotRepository, AgentSearchQueryRepository, Clock, CommitProjectionRepository, LlmCallMetricRepository, NotificationRepository, PasswordResetTokenRepository, PipelineScheduleRepository, ProvisioningLogRepository, RateLimitRepository, SubscriptionQuotaCycleRepository, TokenUsageRepository, Logger } from '@cat-factory/kernel';
2
2
  /** Per-table retention ages in milliseconds; 0 (or less) disables that table's pass. */
3
3
  interface RetentionPolicy {
4
4
  tokenUsageMs: number;
@@ -36,8 +36,10 @@ export interface RetentionDeps {
36
36
  notificationRepository: NotificationRepository;
37
37
  clock: Clock;
38
38
  policy: RetentionPolicy;
39
+ /** Names the table behind each isolated prune failure. Absent ⇒ the failures are silent. */
40
+ logger?: Logger;
39
41
  }
40
- /** Rows reclaimed from each table, for logging. */
42
+ /** Rows reclaimed from each table, plus the tables the pass could not prune. */
41
43
  export interface RetentionResult {
42
44
  tokenUsage: number;
43
45
  rateLimits: number;
@@ -50,12 +52,24 @@ export interface RetentionResult {
50
52
  provisioningLog: number;
51
53
  passwordResetTokens: number;
52
54
  notifications: number;
55
+ /**
56
+ * The tables whose prune threw this pass. EMPTY on a clean pass. Reported separately from
57
+ * the counts because a failed prune and an empty table both reclaim 0 rows, and only one of
58
+ * them means the table is still growing.
59
+ */
60
+ failedTables: string[];
53
61
  }
54
62
  /**
55
63
  * Prune each unbounded table to its retention window. The deletes are
56
64
  * range-scans on indexed columns and usually reclaim nothing, so this is cheap
57
- * to run on the every-2-min cron. Returns the counts removed per table.
65
+ * to run on the every-2-min cron. Returns the counts removed per table plus the tables that
66
+ * failed.
67
+ *
68
+ * Every table is pruned in ISOLATION (slice 4.4): the passes used to be a chain of bare
69
+ * `await`s, so the first failing `deleteOlderThan` aborted every later one — indefinitely,
70
+ * since the same table failed on every subsequent pass too. Shared with the Node twin via
71
+ * `createRetentionPass`, so the two facades cannot drift on it.
58
72
  */
59
- export declare function sweepRetention({ tokenUsageRepository, rateLimitRepository, commitRepository, llmCallMetricRepository, agentContextSnapshotRepository, agentSearchQueryRepository, subscriptionQuotaCycleRepository, pipelineScheduleRepository, provisioningLogRepository, passwordResetTokenRepository, notificationRepository, clock, policy, }: RetentionDeps): Promise<RetentionResult>;
73
+ export declare function sweepRetention({ tokenUsageRepository, rateLimitRepository, commitRepository, llmCallMetricRepository, agentContextSnapshotRepository, agentSearchQueryRepository, subscriptionQuotaCycleRepository, pipelineScheduleRepository, provisioningLogRepository, passwordResetTokenRepository, notificationRepository, clock, policy, logger, }: RetentionDeps): Promise<RetentionResult>;
60
74
  export {};
61
75
  //# sourceMappingURL=retention.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/workflows/retention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC1B,KAAK,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,gCAAgC,EAChC,oBAAoB,EACrB,MAAM,qBAAqB,CAAA;AAoB5B,wFAAwF;AACxF,UAAU,eAAe;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,MAAM,CAAA;IACxB;;;;;OAKG;IACH,iBAAiB,EAAE,MAAM,CAAA;IACzB,6EAA6E;IAC7E,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,oBAAoB,EAAE,oBAAoB,CAAA;IAC1C,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,gBAAgB,EAAE,0BAA0B,CAAA;IAC5C,uBAAuB,EAAE,uBAAuB,CAAA;IAChD,oFAAoF;IACpF,8BAA8B,EAAE,8BAA8B,CAAA;IAC9D,iFAAiF;IACjF,0BAA0B,EAAE,0BAA0B,CAAA;IACtD,uFAAuF;IACvF,gCAAgC,EAAE,gCAAgC,CAAA;IAClE,4FAA4F;IAC5F,0BAA0B,CAAC,EAAE,0BAA0B,CAAA;IACvD,+FAA+F;IAC/F,yBAAyB,CAAC,EAAE,yBAAyB,CAAA;IACrD,mFAAmF;IACnF,4BAA4B,CAAC,EAAE,4BAA4B,CAAA;IAC3D,sFAAsF;IACtF,sBAAsB,EAAE,sBAAsB,CAAA;IAC9C,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,eAAe,CAAA;CACxB;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,uBAAuB,EAAE,MAAM,CAAA;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,aAAa,EAAE,MAAM,CAAA;CACtB;AAYD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,EACnC,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,gCAAgC,EAChC,0BAA0B,EAC1B,yBAAyB,EACzB,4BAA4B,EAC5B,sBAAsB,EACtB,KAAK,EACL,MAAM,GACP,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CA0C1C"}
1
+ {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/workflows/retention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,0BAA0B,EAC1B,KAAK,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,sBAAsB,EACtB,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,gCAAgC,EAChC,oBAAoB,EACpB,MAAM,EACP,MAAM,qBAAqB,CAAA;AAqB5B,wFAAwF;AACxF,UAAU,eAAe;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,MAAM,CAAA;IACxB;;;;;OAKG;IACH,iBAAiB,EAAE,MAAM,CAAA;IACzB,6EAA6E;IAC7E,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,oBAAoB,EAAE,oBAAoB,CAAA;IAC1C,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,gBAAgB,EAAE,0BAA0B,CAAA;IAC5C,uBAAuB,EAAE,uBAAuB,CAAA;IAChD,oFAAoF;IACpF,8BAA8B,EAAE,8BAA8B,CAAA;IAC9D,iFAAiF;IACjF,0BAA0B,EAAE,0BAA0B,CAAA;IACtD,uFAAuF;IACvF,gCAAgC,EAAE,gCAAgC,CAAA;IAClE,4FAA4F;IAC5F,0BAA0B,CAAC,EAAE,0BAA0B,CAAA;IACvD,+FAA+F;IAC/F,yBAAyB,CAAC,EAAE,yBAAyB,CAAA;IACrD,mFAAmF;IACnF,4BAA4B,CAAC,EAAE,4BAA4B,CAAA;IAC3D,sFAAsF;IACtF,sBAAsB,EAAE,sBAAsB,CAAA;IAC9C,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,eAAe,CAAA;IACvB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,uBAAuB,EAAE,MAAM,CAAA;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,aAAa,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,EACnC,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,gCAAgC,EAChC,0BAA0B,EAC1B,yBAAyB,EACzB,4BAA4B,EAC5B,sBAAsB,EACtB,KAAK,EACL,MAAM,EACN,MAAM,GACP,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CA2D1C"}
@@ -1,3 +1,4 @@
1
+ import { createRetentionPass } from '@cat-factory/orchestration';
1
2
  /** Recurring-pipeline run history is kept ~1 week (the inspector's window). */
2
3
  const SCHEDULE_RUN_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
3
4
  /**
@@ -7,42 +8,44 @@ const SCHEDULE_RUN_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
7
8
  * 30 days has long since reset and only holds stale counters.
8
9
  */
9
10
  const SUBSCRIPTION_QUOTA_CYCLE_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
10
- /** Delete rows older than `now - windowMs`, treating a non-positive window as "disabled". */
11
- async function prune(windowMs, now, del) {
12
- if (windowMs <= 0)
13
- return 0;
14
- return del(now - windowMs);
15
- }
16
11
  /**
17
12
  * Prune each unbounded table to its retention window. The deletes are
18
13
  * range-scans on indexed columns and usually reclaim nothing, so this is cheap
19
- * to run on the every-2-min cron. Returns the counts removed per table.
14
+ * to run on the every-2-min cron. Returns the counts removed per table plus the tables that
15
+ * failed.
16
+ *
17
+ * Every table is pruned in ISOLATION (slice 4.4): the passes used to be a chain of bare
18
+ * `await`s, so the first failing `deleteOlderThan` aborted every later one — indefinitely,
19
+ * since the same table failed on every subsequent pass too. Shared with the Node twin via
20
+ * `createRetentionPass`, so the two facades cannot drift on it.
20
21
  */
21
- export async function sweepRetention({ tokenUsageRepository, rateLimitRepository, commitRepository, llmCallMetricRepository, agentContextSnapshotRepository, agentSearchQueryRepository, subscriptionQuotaCycleRepository, pipelineScheduleRepository, provisioningLogRepository, passwordResetTokenRepository, notificationRepository, clock, policy, }) {
22
+ export async function sweepRetention({ tokenUsageRepository, rateLimitRepository, commitRepository, llmCallMetricRepository, agentContextSnapshotRepository, agentSearchQueryRepository, subscriptionQuotaCycleRepository, pipelineScheduleRepository, provisioningLogRepository, passwordResetTokenRepository, notificationRepository, clock, policy, logger, }) {
22
23
  const now = clock.now();
24
+ const pass = createRetentionPass(logger);
23
25
  return {
24
- tokenUsage: await prune(policy.tokenUsageMs, now, (c) => tokenUsageRepository.deleteOlderThan(c)),
25
- rateLimits: await prune(policy.rateLimitMs, now, (c) => rateLimitRepository.deleteOlderThan(c)),
26
- commits: await prune(policy.commitMs, now, (c) => commitRepository.deleteOlderThan(c)),
27
- llmCallMetrics: await prune(policy.llmCallMetricsMs, now, (c) => llmCallMetricRepository.deleteOlderThan(c)),
26
+ tokenUsage: await pass.prune('token_usage', policy.tokenUsageMs, now, (c) => tokenUsageRepository.deleteOlderThan(c)),
27
+ rateLimits: await pass.prune('github_rate_limits', policy.rateLimitMs, now, (c) => rateLimitRepository.deleteOlderThan(c)),
28
+ commits: await pass.prune('github_commits', policy.commitMs, now, (c) => commitRepository.deleteOlderThan(c)),
29
+ llmCallMetrics: await pass.prune('llm_call_metrics', policy.llmCallMetricsMs, now, (c) => llmCallMetricRepository.deleteOlderThan(c)),
28
30
  // Same window as the LLM call telemetry (heavy prompt + injected-file bodies).
29
- agentContextSnapshots: await prune(policy.llmCallMetricsMs, now, (c) => agentContextSnapshotRepository.deleteOlderThan(c)),
31
+ agentContextSnapshots: await pass.prune('agent_context_snapshots', policy.llmCallMetricsMs, now, (c) => agentContextSnapshotRepository.deleteOlderThan(c)),
30
32
  // Same window as the LLM call telemetry (performed web-search queries).
31
- agentSearchQueries: await prune(policy.llmCallMetricsMs, now, (c) => agentSearchQueryRepository.deleteOlderThan(c)),
33
+ agentSearchQueries: await pass.prune('agent_search_queries', policy.llmCallMetricsMs, now, (c) => agentSearchQueryRepository.deleteOlderThan(c)),
32
34
  // Idle quota cycles past the fixed 30-day window (well beyond the weekly one).
33
- subscriptionQuotaCycles: await prune(SUBSCRIPTION_QUOTA_CYCLE_RETENTION_MS, now, (c) => subscriptionQuotaCycleRepository.deleteOlderThan(c)),
35
+ subscriptionQuotaCycles: await pass.prune('subscription_quota_cycles', SUBSCRIPTION_QUOTA_CYCLE_RETENTION_MS, now, (c) => subscriptionQuotaCycleRepository.deleteOlderThan(c)),
34
36
  scheduleRuns: pipelineScheduleRepository
35
- ? await prune(SCHEDULE_RUN_RETENTION_MS, now, (c) => pipelineScheduleRepository.pruneRunsBefore(c))
37
+ ? await pass.prune('pipeline_schedule_runs', SCHEDULE_RUN_RETENTION_MS, now, (c) => pipelineScheduleRepository.pruneRunsBefore(c))
36
38
  : 0,
37
39
  provisioningLog: provisioningLogRepository
38
- ? await prune(policy.provisioningLogMs, now, (c) => provisioningLogRepository.deleteOlderThan(c))
40
+ ? await pass.prune('provisioning_log', policy.provisioningLogMs, now, (c) => provisioningLogRepository.deleteOlderThan(c))
39
41
  : 0,
40
42
  // Reset tokens past their own expiry — `now`, not a window.
41
43
  passwordResetTokens: passwordResetTokenRepository
42
- ? await passwordResetTokenRepository.deleteExpired(now)
44
+ ? await pass.expire('password_reset_tokens', () => passwordResetTokenRepository.deleteExpired(now))
43
45
  : 0,
44
46
  // Resolved (acted/dismissed) notifications past the window; open cards untouched.
45
- notifications: await prune(policy.notificationsMs, now, (c) => notificationRepository.deleteResolvedOlderThan(c)),
47
+ notifications: await pass.prune('notifications', policy.notificationsMs, now, (c) => notificationRepository.deleteResolvedOlderThan(c)),
48
+ failedTables: pass.failed,
46
49
  };
47
50
  }
48
51
  //# sourceMappingURL=retention.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"retention.js","sourceRoot":"","sources":["../../../src/infrastructure/workflows/retention.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"retention.js","sourceRoot":"","sources":["../../../src/infrastructure/workflows/retention.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { AgentRunRef, AgentRunRepository, Clock, EnvironmentTestRunRecord } from '@cat-factory/kernel';
1
+ import type { AgentRunRef, AgentRunRepository, Clock, EnvironmentTestRunRecord, Logger, OperationalMetrics } from '@cat-factory/kernel';
2
2
  import type { Workflow } from '@cloudflare/workers-types';
3
3
  /**
4
4
  * A run's durable instance, as the sweeper needs to classify it:
@@ -54,6 +54,15 @@ export interface SweepDeps {
54
54
  * (the degenerate unit-test case), never wrongly on a first observation.
55
55
  */
56
56
  orphanedSince?: Map<string, number>;
57
+ /**
58
+ * Counts each disposition (re-drive / finalize / stall). The per-sweep RESULT below already
59
+ * carries these numbers, but only for this tick's log line: nothing accumulates them, so
60
+ * "has the re-drive rate tripled since the deploy" was unanswerable except by grepping.
61
+ * Absent ⇒ uncounted (a unit test).
62
+ */
63
+ metrics?: OperationalMetrics;
64
+ /** Reports the best-effort re-drive bookkeeping below. Absent ⇒ silent (a unit test). */
65
+ logger?: Logger;
57
66
  }
58
67
  /** What a sweep did, for logging. */
59
68
  export interface SweepResult {
@@ -75,7 +84,7 @@ export interface SweepResult {
75
84
  * - `alive` → leave it.
76
85
  * Pure orchestration over its ports so it is unit-testable with fakes.
77
86
  */
78
- export declare function sweepStuckRuns({ agentRunRepository, instanceState, redrive, finalizeOrphan, failStalled, clock, leaseMs, hardStallMs, orphanedSince, }: SweepDeps): Promise<SweepResult>;
87
+ export declare function sweepStuckRuns({ agentRunRepository, instanceState, redrive, finalizeOrphan, failStalled, clock, leaseMs, hardStallMs, orphanedSince, metrics, logger, }: SweepDeps): Promise<SweepResult>;
79
88
  export interface EnvTestSweepDeps {
80
89
  repository: {
81
90
  listStale(cutoffMs: number): Promise<EnvironmentTestRunRecord[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"sweeper.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/workflows/sweeper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,KAAK,EACL,wBAAwB,EACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAEzD;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAA;AAE5D,+DAA+D;AAC/D,UAAU,cAAc;IACtB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;CACrD;AAED,0DAA0D;AAC1D,qBAAa,eAAgB,YAAW,cAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAArC,YAA6B,QAAQ,EAAE,QAAQ,EAAI;IAE7C,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAqBzD;CACF;AAED,MAAM,WAAW,SAAS;IACxB,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,gEAAgE;IAChE,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACvD,4EAA4E;IAC5E,OAAO,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC;;;;OAIG;IACH,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/C;;;;OAIG;IACH,WAAW,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,KAAK,EAAE,KAAK,CAAA;IACZ,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAA;IACf,6FAA6F;IAC7F,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACpC;AAED,qCAAqC;AACrC,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAA;IACjB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,EACnC,kBAAkB,EAClB,aAAa,EACb,OAAO,EACP,cAAc,EACd,WAAW,EACX,KAAK,EACL,OAAO,EACP,WAAW,EACX,aAAyC,GAC1C,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAiDlC;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE;QAAE,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAAA;KAAE,CAAA;IAChF,2DAA2D;IAC3D,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACpD,4EAA4E;IAC5E,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1D;;;OAGG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE,KAAK,EAAE,KAAK,CAAA;IACZ,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,UAAU,EACV,aAAa,EACb,OAAO,EACP,cAAc,EACd,KAAK,EACL,OAAO,GACR,EAAE,gBAAgB,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBrE"}
1
+ {"version":3,"file":"sweeper.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/workflows/sweeper.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { noopLogger, noopOperationalMetrics, runBestEffort } from '@cat-factory/kernel';
1
2
  /** WorkflowLookup over a Cloudflare Workflows binding. */
2
3
  export class WorkflowsLookup {
3
4
  workflow;
@@ -40,7 +41,7 @@ export class WorkflowsLookup {
40
41
  * - `alive` → leave it.
41
42
  * Pure orchestration over its ports so it is unit-testable with fakes.
42
43
  */
43
- export async function sweepStuckRuns({ agentRunRepository, instanceState, redrive, finalizeOrphan, failStalled, clock, leaseMs, hardStallMs, orphanedSince = new Map(), }) {
44
+ export async function sweepStuckRuns({ agentRunRepository, instanceState, redrive, finalizeOrphan, failStalled, clock, leaseMs, hardStallMs, orphanedSince = new Map(), metrics = noopOperationalMetrics, logger = noopLogger, }) {
44
45
  const now = clock.now();
45
46
  const stale = await agentRunRepository.listStale(now - leaseMs);
46
47
  let redriven = 0;
@@ -60,6 +61,9 @@ export async function sweepStuckRuns({ agentRunRepository, instanceState, redriv
60
61
  orphanedSince.delete(ref.id);
61
62
  await finalizeOrphan(ref);
62
63
  finalized++;
64
+ // The run KIND is a bounded enum and the split that matters: bootstrap runs and
65
+ // execution runs are lost for different reasons and fixed in different places.
66
+ metrics.increment('sweep.run_finalized', { kind: ref.kind });
63
67
  continue;
64
68
  }
65
69
  // `missing`: the instance was lost (eviction, a missed event) and can be re-created.
@@ -76,12 +80,18 @@ export async function sweepStuckRuns({ agentRunRepository, instanceState, redriv
76
80
  if (ref.kind === 'execution' && now - firstSeenOrphaned > hardStallMs) {
77
81
  await failStalled(ref);
78
82
  stalled++;
83
+ metrics.increment('sweep.run_stalled', { kind: ref.kind });
79
84
  orphanedSince.delete(ref.id);
80
85
  stillOrphaned.delete(ref.id);
81
86
  continue;
82
87
  }
83
88
  await redrive(ref);
84
89
  redriven++;
90
+ metrics.increment('sweep.run_redriven', { kind: ref.kind });
91
+ // Persist the per-run count AFTER the re-drive and best-effort: this is bookkeeping about
92
+ // the recovery, so it must never be able to fail one. Ordered after for the same reason —
93
+ // a counter claiming a run was re-driven when it was not is worse than one that missed.
94
+ await runBestEffort(logger, 'sweep.recordRedrive', () => agentRunRepository.recordRedrive(ref.workspaceId, ref.id));
85
95
  }
86
96
  // Forget runs that recovered (bumped their lease → left the stale set) or went terminal, so
87
97
  // their per-process orphaned clock restarts if they ever stall again.
@@ -1 +1 @@
1
- {"version":3,"file":"sweeper.js","sourceRoot":"","sources":["../../../src/infrastructure/workflows/sweeper.ts"],"names":[],"mappings":"AAuBA,0DAA0D;AAC1D,MAAM,OAAO,eAAe;IACG,QAAQ;IAArC,YAA6B,QAAkB;wBAAlB,QAAQ;IAAa,CAAC;IAEnD,KAAK,CAAC,aAAa,CAAC,KAAa;QAC/B,IAAI,QAAQ,CAAA;QACZ,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;YAClE,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAA;YAC1C,OAAO,MAAM,KAAK,SAAS;gBACzB,MAAM,KAAK,QAAQ;gBACnB,MAAM,KAAK,SAAS;gBACpB,MAAM,KAAK,QAAQ;gBACnB,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,UAAU,CAAA;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,8EAA8E;YAC9E,8EAA8E;YAC9E,OAAO,SAAS,CAAA;QAClB,CAAC;IACH,CAAC;CACF;AAiDD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EACnC,kBAAkB,EAClB,aAAa,EACb,OAAO,EACP,cAAc,EACd,WAAW,EACX,KAAK,EACL,OAAO,EACP,WAAW,EACX,aAAa,GAAG,IAAI,GAAG,EAAkB,GAC/B;IACV,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,CAAA;IACvB,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,GAAG,GAAG,OAAO,CAAC,CAAA;IAC/D,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,oFAAoF;IACpF,wFAAwF;IACxF,2BAA2B;IAC3B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAA;IACvC,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAA;QACtC,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtB,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC5B,SAAQ;QACV,CAAC;QACD,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;YACzB,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC5B,MAAM,cAAc,CAAC,GAAG,CAAC,CAAA;YACzB,SAAS,EAAE,CAAA;YACX,SAAQ;QACV,CAAC;QACD,qFAAqF;QACrF,mFAAmF;QACnF,uFAAuF;QACvF,wFAAwF;QACxF,0CAA0C;QAC1C,MAAM,iBAAiB,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAA;QAC1D,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAA;QAC5C,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACzB,yFAAyF;QACzF,qFAAqF;QACrF,kBAAkB;QAClB,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,IAAI,GAAG,GAAG,iBAAiB,GAAG,WAAW,EAAE,CAAC;YACtE,MAAM,WAAW,CAAC,GAAG,CAAC,CAAA;YACtB,OAAO,EAAE,CAAA;YACT,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC5B,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YAC5B,SAAQ;QACV,CAAC;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;QAClB,QAAQ,EAAE,CAAA;IACZ,CAAC;IACD,4FAA4F;IAC5F,sEAAsE;IACtE,KAAK,MAAM,EAAE,IAAI,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC;QACtC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAA;AACzC,CAAC;AAkBD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EACvC,UAAU,EACV,aAAa,EACb,OAAO,EACP,cAAc,EACd,KAAK,EACL,OAAO,GACU;IACjB,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,CAAA;IAC/D,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACzC,IAAI,KAAK,KAAK,OAAO;YAAE,SAAQ;QAC/B,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;YACzB,MAAM,cAAc,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;YAC7C,SAAS,EAAE,CAAA;YACX,SAAQ;QACV,CAAC;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;QACtC,QAAQ,EAAE,CAAA;IACZ,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAA;AAChC,CAAC"}
1
+ {"version":3,"file":"sweeper.js","sourceRoot":"","sources":["../../../src/infrastructure/workflows/sweeper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ -- Per-run re-drive count (docs/initiatives/observability-logging-gaps.md, D4 / slice 4.1).
2
+ --
3
+ -- The sweepers already knew how many runs they re-drove per pass, but only for that pass's log
4
+ -- line: the per-run history lived in an in-memory `orphanedSince` map holding a timestamp and
5
+ -- nothing else. That map dies with the process on Node and with the isolate on Cloudflare, where
6
+ -- the sweep additionally logs only aggregates (`{redriven: 3}`, no run ids) — so "was this run
7
+ -- re-driven three times or is this the first?" had no answer anywhere.
8
+ --
9
+ -- Deliberately NOT rev-guarded and deliberately outside the re-drive's own write: this counts
10
+ -- something that happened TO the run rather than deriving a value FROM it, so two racing sweepers
11
+ -- double-counting is a far better outcome than a lost update, and a `rev` bump here would collide
12
+ -- with the driver's own writes and let bookkeeping fail a re-drive.
13
+ --
14
+ -- Default 0 is honest for every existing row: a run that was re-driven before this column existed
15
+ -- has no recoverable count, and 0 is what "we do not know of any" has to read as. The counter is
16
+ -- kept when a run recovers — needing three re-drives is exactly what an operator wants to see
17
+ -- about a run that eventually succeeded.
18
+
19
+ ALTER TABLE agent_runs
20
+ ADD COLUMN redrive_count INTEGER NOT NULL DEFAULT 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/worker",
3
- "version": "0.137.2",
3
+ "version": "0.138.0",
4
4
  "description": "Reusable Cloudflare Worker library (Hono + D1) exposing the Agent Architecture Board core: the `createApp()` Hono factory, the default fetch/scheduled/queue handler, and the Durable Object + Workflow classes. Deployments (see deploy/backend) supply the wrangler.toml + config and re-export these.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -42,22 +42,22 @@
42
42
  "pino": "^10.3.1",
43
43
  "valibot": "^1.4.2",
44
44
  "workers-ai-provider": "^4.0.0",
45
- "@cat-factory/agents": "0.104.3",
46
- "@cat-factory/caching": "0.12.12",
47
- "@cat-factory/consensus": "0.13.25",
48
- "@cat-factory/contracts": "0.211.0",
49
- "@cat-factory/eks": "0.1.199",
50
- "@cat-factory/gates": "0.8.45",
51
- "@cat-factory/gitlab": "0.15.4",
52
- "@cat-factory/integrations": "0.116.4",
53
- "@cat-factory/kernel": "0.214.1",
54
- "@cat-factory/observability-langfuse": "0.9.42",
55
- "@cat-factory/observability-otel": "0.4.42",
56
- "@cat-factory/orchestration": "0.185.2",
57
- "@cat-factory/prompt-fragments": "0.15.36",
58
- "@cat-factory/provider-cloudflare": "0.7.351",
59
- "@cat-factory/server": "0.194.0",
60
- "@cat-factory/spend": "0.13.1"
45
+ "@cat-factory/agents": "0.105.0",
46
+ "@cat-factory/caching": "0.13.0",
47
+ "@cat-factory/eks": "0.1.200",
48
+ "@cat-factory/contracts": "0.212.0",
49
+ "@cat-factory/consensus": "0.13.26",
50
+ "@cat-factory/gates": "0.8.46",
51
+ "@cat-factory/observability-langfuse": "0.9.43",
52
+ "@cat-factory/kernel": "0.215.0",
53
+ "@cat-factory/observability-otel": "0.5.0",
54
+ "@cat-factory/orchestration": "0.186.0",
55
+ "@cat-factory/prompt-fragments": "0.15.37",
56
+ "@cat-factory/server": "0.195.0",
57
+ "@cat-factory/spend": "0.13.2",
58
+ "@cat-factory/integrations": "0.117.0",
59
+ "@cat-factory/gitlab": "0.15.5",
60
+ "@cat-factory/provider-cloudflare": "0.7.352"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@cloudflare/vitest-pool-workers": "^0.20.1",
@@ -65,7 +65,7 @@
65
65
  "typescript": "7.0.2",
66
66
  "vitest": "^4.1.10",
67
67
  "wrangler": "^4.118.0",
68
- "@cat-factory/conformance": "0.20.10"
68
+ "@cat-factory/conformance": "0.20.11"
69
69
  },
70
70
  "scripts": {
71
71
  "build": "tsc -b tsconfig.build.json",