@cat-factory/worker 0.142.0 → 0.144.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 (41) hide show
  1. package/dist/index.d.ts.map +1 -1
  2. package/dist/index.js +6 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/infrastructure/config/agents.d.ts.map +1 -1
  5. package/dist/infrastructure/config/agents.js +4 -1
  6. package/dist/infrastructure/config/agents.js.map +1 -1
  7. package/dist/infrastructure/config/retention.d.ts.map +1 -1
  8. package/dist/infrastructure/config/retention.js +6 -0
  9. package/dist/infrastructure/config/retention.js.map +1 -1
  10. package/dist/infrastructure/container-assembly.d.ts.map +1 -1
  11. package/dist/infrastructure/container-assembly.js +37 -15
  12. package/dist/infrastructure/container-assembly.js.map +1 -1
  13. package/dist/infrastructure/container-executor-deps.d.ts +20 -2
  14. package/dist/infrastructure/container-executor-deps.d.ts.map +1 -1
  15. package/dist/infrastructure/container-executor-deps.js +5 -4
  16. package/dist/infrastructure/container-executor-deps.js.map +1 -1
  17. package/dist/infrastructure/container-model-resolver.d.ts +8 -2
  18. package/dist/infrastructure/container-model-resolver.d.ts.map +1 -1
  19. package/dist/infrastructure/container-model-resolver.js +13 -4
  20. package/dist/infrastructure/container-model-resolver.js.map +1 -1
  21. package/dist/infrastructure/env.d.ts +4 -0
  22. package/dist/infrastructure/env.d.ts.map +1 -1
  23. package/dist/infrastructure/env.js.map +1 -1
  24. package/dist/infrastructure/repositories/D1GateOutcomeRepository.d.ts +12 -0
  25. package/dist/infrastructure/repositories/D1GateOutcomeRepository.d.ts.map +1 -0
  26. package/dist/infrastructure/repositories/D1GateOutcomeRepository.js +64 -0
  27. package/dist/infrastructure/repositories/D1GateOutcomeRepository.js.map +1 -0
  28. package/dist/infrastructure/repositories/D1ModelPresetRepository.d.ts.map +1 -1
  29. package/dist/infrastructure/repositories/D1ModelPresetRepository.js +9 -4
  30. package/dist/infrastructure/repositories/D1ModelPresetRepository.js.map +1 -1
  31. package/dist/infrastructure/repositories/D1PlatformMetricsRepository.d.ts +6 -1
  32. package/dist/infrastructure/repositories/D1PlatformMetricsRepository.d.ts.map +1 -1
  33. package/dist/infrastructure/repositories/D1PlatformMetricsRepository.js +124 -0
  34. package/dist/infrastructure/repositories/D1PlatformMetricsRepository.js.map +1 -1
  35. package/dist/infrastructure/workflows/retention.d.ts +17 -2
  36. package/dist/infrastructure/workflows/retention.d.ts.map +1 -1
  37. package/dist/infrastructure/workflows/retention.js +9 -2
  38. package/dist/infrastructure/workflows/retention.js.map +1 -1
  39. package/migrations/0078_model_preset_provider_preference.sql +10 -0
  40. package/migrations/0079_gate_outcomes_and_run_days.sql +82 -0
  41. package/package.json +18 -18
@@ -0,0 +1,82 @@
1
+ -- Two queryable projections behind the operator dashboard
2
+ -- (docs/initiatives/platform-operator-observability.md, slices 4b and 7).
3
+ --
4
+ -- `gate_outcomes`: one flat row per SETTLED polling gate. The live gate state (`attempts`,
5
+ -- `attemptLog`, the escalation phase) lives inside the per-run `detail` JSON blob as
6
+ -- `steps[].gate.*`, which is right for the run window and unusable for a rollup: aggregating it
7
+ -- would mean `json_each` here and `jsonb_array_elements` on Postgres, both reaching into the
8
+ -- engine's internal step-serialization shape, and neither expressible as one GROUP BY. So the
9
+ -- engine writes the terminal verdict as columns and the rollup is an ordinary aggregate.
10
+ --
11
+ -- The id is DERIVED by the writer as `<runId>:<stepIndex>:<outcome>` rather than minted, so the
12
+ -- durable drivers' replays collapse onto one row instead of inflating every statistic the table
13
+ -- exists to report; a step re-run that ends DIFFERENTLY still records its own row.
14
+ CREATE TABLE gate_outcomes (
15
+ id TEXT NOT NULL,
16
+ workspace_id TEXT NOT NULL,
17
+ execution_id TEXT NOT NULL,
18
+ block_id TEXT NOT NULL,
19
+ gate_kind TEXT NOT NULL, -- the gate step's agent kind (`ci`, `conflicts`, …)
20
+ helper_kind TEXT, -- the escalation agent (`ci-fixer`, …), or NULL
21
+ outcome TEXT NOT NULL, -- 'passed' | 'exhausted'
22
+ attempts INTEGER NOT NULL DEFAULT 0, -- helper dispatches spent (0 = precheck-clean)
23
+ max_attempts INTEGER NOT NULL DEFAULT 0,
24
+ helper_failures INTEGER NOT NULL DEFAULT 0, -- helper jobs that themselves failed
25
+ duration_ms INTEGER, -- gate entry → verdict, NULL when unknown
26
+ created_at INTEGER NOT NULL,
27
+ PRIMARY KEY (id)
28
+ );
29
+
30
+ -- The rollup's access path: every read is "this account's workspaces, settled since T".
31
+ CREATE INDEX idx_gate_outcomes_workspace_created ON gate_outcomes (workspace_id, created_at);
32
+ -- The retention prune's access path (a global range delete, not workspace-scoped).
33
+ CREATE INDEX idx_gate_outcomes_created ON gate_outcomes (created_at);
34
+
35
+ -- `platform_run_days`: the daily rollup of `agent_runs` that serves the dashboard's `30d` and
36
+ -- `90d` windows. Those windows exist BECAUSE of this table: scanning a quarter of every run the
37
+ -- deployment ever made, on each dashboard load and each alert sweep, is the cost the rollup
38
+ -- removes, and it produces a series nobody can read at finer resolution anyway.
39
+ --
40
+ -- `failure_kind` uses '' (never NULL) for a non-failed status, because it is part of the primary
41
+ -- key: SQLite permits NULLs in a PK and does NOT treat two of them as equal, so a nullable column
42
+ -- here would let the same bucket be inserted repeatedly and silently double-count the day. The
43
+ -- repository maps '' back to NULL at the read boundary, so the port's shape is unaffected.
44
+ --
45
+ -- Rewritten in place by the sweep (DELETE the recomputed window, then INSERT it), never appended:
46
+ -- a day's counts are not final until the day is over, so the current day must be CORRECTED on
47
+ -- each pass. The DELETE is what makes it a rewrite: a run's `status` mutates in place while its
48
+ -- `created_at` stays put, so an upsert alone would leave the `(day, 'running')` bucket of a run
49
+ -- that has since settled standing beside its new `(day, 'done')` one, and count it twice forever.
50
+ CREATE TABLE platform_run_days (
51
+ workspace_id TEXT NOT NULL,
52
+ day_start INTEGER NOT NULL, -- UTC-midnight epoch ms
53
+ status TEXT NOT NULL,
54
+ failure_kind TEXT NOT NULL DEFAULT '', -- '' for every status but 'failed' (see above)
55
+ run_count INTEGER NOT NULL,
56
+ PRIMARY KEY (workspace_id, day_start, status, failure_kind)
57
+ );
58
+
59
+ -- The prune's access path; the account-scoped read rides the primary key's leading columns.
60
+ CREATE INDEX idx_platform_run_days_day ON platform_run_days (day_start);
61
+
62
+ -- `platform_rollup_state`: how far the SWEEP has covered, which is a fact about the sweep and
63
+ -- therefore cannot be derived from the rolled-up rows.
64
+ --
65
+ -- `MAX(day_start)` over `platform_run_days` was the obvious-looking answer and is ambiguous in
66
+ -- both directions: for an account, an idle fortnight and a wedged sweep return the same value,
67
+ -- and NO rows at all describes a brand-new account exactly as well as a rollup that has never
68
+ -- run. Both readings call for opposite operator responses, so the dashboard must not be left to
69
+ -- guess between them (an un-materialised rollup and an idle quarter are the "absent is not zero"
70
+ -- pair this whole projection exists to keep apart).
71
+ --
72
+ -- One row per rollup, DEPLOYMENT-scoped rather than per account: the pass covers every workspace
73
+ -- at once, so its coverage has no tenant dimension, and it carries no tenant data (a day
74
+ -- boundary and a timestamp). Written in the SAME transaction as the rewrite it describes, so it
75
+ -- can never claim coverage the rows do not have. NOT workspace-scoped, so deliberately absent
76
+ -- from the delete cascade and from the retention prune.
77
+ CREATE TABLE platform_rollup_state (
78
+ rollup TEXT NOT NULL, -- 'run_days'
79
+ through_day INTEGER NOT NULL, -- newest UTC-midnight day boundary the pass covered
80
+ updated_at INTEGER NOT NULL,
81
+ PRIMARY KEY (rollup)
82
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/worker",
3
- "version": "0.142.0",
3
+ "version": "0.144.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.106.7",
46
- "@cat-factory/caching": "0.13.8",
47
- "@cat-factory/consensus": "0.13.34",
48
- "@cat-factory/contracts": "0.220.0",
49
- "@cat-factory/eks": "0.1.208",
50
- "@cat-factory/gates": "0.8.54",
51
- "@cat-factory/gitlab": "0.15.13",
52
- "@cat-factory/integrations": "0.121.0",
53
- "@cat-factory/kernel": "0.222.0",
54
- "@cat-factory/observability-langfuse": "0.9.51",
55
- "@cat-factory/observability-otel": "0.6.0",
56
- "@cat-factory/orchestration": "0.191.0",
57
- "@cat-factory/prompt-fragments": "0.15.45",
58
- "@cat-factory/provider-cloudflare": "0.7.360",
59
- "@cat-factory/server": "0.203.0",
60
- "@cat-factory/spend": "0.13.10"
45
+ "@cat-factory/agents": "0.107.0",
46
+ "@cat-factory/caching": "0.14.0",
47
+ "@cat-factory/consensus": "0.14.0",
48
+ "@cat-factory/contracts": "0.222.0",
49
+ "@cat-factory/eks": "0.1.210",
50
+ "@cat-factory/gates": "0.8.56",
51
+ "@cat-factory/integrations": "0.121.2",
52
+ "@cat-factory/kernel": "0.224.0",
53
+ "@cat-factory/observability-langfuse": "0.9.53",
54
+ "@cat-factory/observability-otel": "0.7.1",
55
+ "@cat-factory/orchestration": "0.193.0",
56
+ "@cat-factory/provider-cloudflare": "0.7.362",
57
+ "@cat-factory/prompt-fragments": "0.15.47",
58
+ "@cat-factory/gitlab": "0.15.15",
59
+ "@cat-factory/spend": "0.13.12",
60
+ "@cat-factory/server": "0.205.0"
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.19"
68
+ "@cat-factory/conformance": "0.21.1"
69
69
  },
70
70
  "scripts": {
71
71
  "build": "tsc -b tsconfig.build.json",