@catalyst-cloud/schema 0.1.19 → 0.1.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@catalyst-cloud/schema",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "type": "module",
5
5
  "description": "Typed Drizzle schema = single source of truth for the per-tenant Mirror DO SQLite store (CTC-13 / ADR-0002). Shared by the mirror Worker, the host-sync replica, and the browser OPFS replica.",
6
6
  "license": "MIT",
@@ -1600,6 +1600,13 @@ export const durableEventTypes = {
1600
1600
  wakes: false,
1601
1601
  entity: "ticket",
1602
1602
  },
1603
+ "relay.phase.completed": {
1604
+ rationale:
1605
+ "CTC-985 — a relay-done.json receipt materialized a phase completion in the tenant DO's own relay_phase_state. ADR-0039 durable-fact example ('a phase started, completed, failed, or was preempted'), and the one fact that can create NEW eligible work for a ticket, so the dispatcher cohort must wake on it the same way fence.claimed and phase.dispatch.requested already do.",
1606
+ ingestVerb: "artifacts.event",
1607
+ wakes: { consumerClass: "dispatcher" },
1608
+ entity: "ticket",
1609
+ },
1603
1610
  "session.ended": {
1604
1611
  rationale: "An agent session ended — a real lifecycle boundary fact.",
1605
1612
  ingestVerb: "coordination.publish",
@@ -1937,10 +1944,6 @@ export const telemetryEventTypes = {
1937
1944
  reason:
1938
1945
  "Part of the recovery.skipped.* family: The bare fallback skip marker with no reason suffix (1 line) — same family.",
1939
1946
  },
1940
- "recovery.skipped.already-shipped-pr-3750-merged-head-matches-origin-main": {
1941
- reason:
1942
- "Part of the recovery.skipped.* family: Same free-text-reason-in-type defect as the pr-1071 sibling, for a different PR — flagged for phase-3.",
1943
- },
1944
1947
  "recovery.skipped.artifact-not-gate-visible": {
1945
1948
  reason:
1946
1949
  "Part of the recovery.skipped.* family: A recurring pre-condition check ('is the artifact visible to the gate yet') re-logged on every sweep pass until it resolves — 14,710 lines/mo.",
@@ -1965,10 +1968,6 @@ export const telemetryEventTypes = {
1965
1968
  reason:
1966
1969
  "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 14,699 lines/mo.",
1967
1970
  },
1968
- "recovery.skipped.pr-1071-blocked-by-a-pre-existing-repo-wide-ci-failure-on-main-n": {
1969
- reason:
1970
- "Part of the recovery.skipped.* family: ⚠️ The clearest evidence of the family's defect: a full free-text incident explanation baked directly into the event NAME (confirmed against the raw log line) and re-logged 3,960 times for one PR. This is a producer bug flagged for the phase-3 inventory — the reason belongs in payload, never in `type`.",
1971
- },
1972
1971
  "recovery.skipped.prior-artifact-missing": {
1973
1972
  reason:
1974
1973
  "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 35,141 lines/mo, the largest of the skip-reason family.",
@@ -1977,10 +1976,6 @@ export const telemetryEventTypes = {
1977
1976
  reason:
1978
1977
  "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 28,906 lines/mo.",
1979
1978
  },
1980
- "recovery.skipped.source-conflict-ctl708-unavailable": {
1981
- reason:
1982
- "Part of the recovery.skipped.* family: Same free-text-reason-in-type defect, embedding a specific ticket's conflict detail in the type — flagged for phase-3.",
1983
- },
1984
1979
  "recovery.skipped.ticket-already-merged-pipeline-regressed": {
1985
1980
  reason:
1986
1981
  "Part of the recovery.skipped.* family: A recurring pre-condition check re-logged every sweep pass — 14,868 lines/mo.",
@@ -76,7 +76,19 @@ export function eventArchiveKey(coords: EventArchiveCoords): string {
76
76
  // is well-formed. Re-deriving the yyyy-mm-dd prefix from the parsed Date and requiring it to match
77
77
  // the input's own date prefix rejects that rollover instead of misfiling into a wrong partition.
78
78
  const roundTripDatePrefix = occurredAt.slice(0, 10);
79
- const parsedDatePrefix = new Date(occurredAtMs).toISOString().slice(0, 10);
79
+ // Codex P2 (PR #1250): derive the parsed prefix in the TIMESTAMP'S OWN offset, not UTC — a
80
+ // valid instant like 2026-08-24T23:30:00-02:00 is already Aug 25 in UTC, so a UTC comparison
81
+ // rejects a well-formed date the regex deliberately accepts. The rollover check still fires:
82
+ // an out-of-range date (2026-02-30) rolls forward and lands on a different calendar date in
83
+ // ANY fixed offset.
84
+ const offsetMatch = /(?:Z|([+-])(\d{2}):(\d{2}))$/.exec(occurredAt);
85
+ const offsetMs =
86
+ offsetMatch && offsetMatch[1]
87
+ ? (offsetMatch[1] === "-" ? -1 : 1) *
88
+ (Number(offsetMatch[2]) * 3600 + Number(offsetMatch[3]) * 60) *
89
+ 1000
90
+ : 0;
91
+ const parsedDatePrefix = new Date(occurredAtMs + offsetMs).toISOString().slice(0, 10);
80
92
  if (roundTripDatePrefix !== parsedDatePrefix) {
81
93
  throw new Error(
82
94
  `eventArchiveKey: occurredAt ${JSON.stringify(occurredAt)} is not a valid date`,
@@ -214,6 +214,13 @@ export const MIRROR_MIGRATIONS = {
214
214
  tag: "0028_burly_nemesis",
215
215
  breakpoints: true,
216
216
  },
217
+ {
218
+ idx: 29,
219
+ version: "6",
220
+ when: 1787615021252,
221
+ tag: "0029_square_silhouette",
222
+ breakpoints: true,
223
+ },
217
224
  ],
218
225
  },
219
226
  migrations: {
@@ -272,5 +279,7 @@ export const MIRROR_MIGRATIONS = {
272
279
  "0027_closed_miek":
273
280
  "CREATE TABLE `check_suites` (\n\t`repo_id` text NOT NULL,\n\t`check_suite_id` text PRIMARY KEY NOT NULL,\n\t`head_sha` text,\n\t`head_branch` text,\n\t`status` text,\n\t`conclusion` text,\n\t`app_slug` text,\n\t`latest_check_runs_count` integer,\n\t`updated_at` integer\n);\n--> statement-breakpoint\nCREATE INDEX `idx_check_suites_sha` ON `check_suites` (`head_sha`);--> statement-breakpoint\nCREATE TABLE `push_events` (\n\t`delivery_id` text PRIMARY KEY NOT NULL,\n\t`repo_id` text NOT NULL,\n\t`ref` text NOT NULL,\n\t`before` text,\n\t`after` text,\n\t`forced` integer,\n\t`created` integer,\n\t`deleted` integer,\n\t`base_ref` text,\n\t`pusher_id` text,\n\t`head_commit_sha` text,\n\t`updated_at` integer\n);\n--> statement-breakpoint\nCREATE INDEX `idx_push_events_repo_ref` ON `push_events` (`repo_id`,`ref`,`updated_at`);--> statement-breakpoint\nALTER TABLE `pull_requests` ADD `merge_commit_sha` text;",
274
281
  "0028_burly_nemesis": "ALTER TABLE `check_suites` ADD `pull_request_numbers` text;",
282
+ "0029_square_silhouette":
283
+ "CREATE INDEX `idx_relations_type_related` ON `relations` (`type`,`related_identifier`);",
275
284
  },
276
285
  } as const;
package/src/mirror.ts CHANGED
@@ -148,7 +148,18 @@ export const relations = sqliteTable(
148
148
  related_identifier: text("related_identifier"),
149
149
  updated_at: integer("updated_at"),
150
150
  },
151
- (t) => [index("idx_relations_issue").on(t.issue_identifier)],
151
+ (t) => [
152
+ index("idx_relations_issue").on(t.issue_identifier),
153
+ // CTC-990: serves evaluateBlockers' incoming-`blocks` lookup (work-eligibility.ts) —
154
+ // `WHERE type = 'blocks' AND related_identifier = ?`, run inside /work/acquire's
155
+ // transactionSync CAS burst, so it cannot afford a full scan. Composite (not single-column)
156
+ // because the predicate always constrains both columns with equality — measured to let SQLite
157
+ // seek on both. `relations` is a Drizzle-mirrored table (replicates to every host/browser
158
+ // replica), so its indexes belong here, in the SSOT, never as a DO-side
159
+ // `CREATE INDEX IF NOT EXISTS` — a DO-side index on a mirrored table would be invisible to the
160
+ // daemon/browser replicas and to this file's own fidelity tests (ADR-0002).
161
+ index("idx_relations_type_related").on(t.type, t.related_identifier),
162
+ ],
152
163
  );
153
164
 
154
165
  // Linear IssueHistory events (CTC-14) — the per-issue change timeline. Captured INLINE on the issues