@cat-factory/contracts 0.165.0 → 0.167.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 (68) hide show
  1. package/dist/entities.d.ts +7 -0
  2. package/dist/entities.d.ts.map +1 -1
  3. package/dist/entities.js +7 -0
  4. package/dist/entities.js.map +1 -1
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/merge.d.ts +289 -1
  10. package/dist/merge.d.ts.map +1 -1
  11. package/dist/merge.js +60 -0
  12. package/dist/merge.js.map +1 -1
  13. package/dist/mergeTrackRecord.d.ts +183 -0
  14. package/dist/mergeTrackRecord.d.ts.map +1 -0
  15. package/dist/mergeTrackRecord.js +251 -0
  16. package/dist/mergeTrackRecord.js.map +1 -0
  17. package/dist/notification-webhooks.d.ts +5 -3
  18. package/dist/notification-webhooks.d.ts.map +1 -1
  19. package/dist/notifications.d.ts +42 -3
  20. package/dist/notifications.d.ts.map +1 -1
  21. package/dist/notifications.js +33 -1
  22. package/dist/notifications.js.map +1 -1
  23. package/dist/public-api.d.ts +3 -1
  24. package/dist/public-api.d.ts.map +1 -1
  25. package/dist/requests.d.ts +7 -0
  26. package/dist/requests.d.ts.map +1 -1
  27. package/dist/requests.js +1 -0
  28. package/dist/requests.js.map +1 -1
  29. package/dist/routes/board.d.ts +19 -0
  30. package/dist/routes/board.d.ts.map +1 -1
  31. package/dist/routes/execution.d.ts +5 -1
  32. package/dist/routes/execution.d.ts.map +1 -1
  33. package/dist/routes/execution.js +5 -1
  34. package/dist/routes/execution.js.map +1 -1
  35. package/dist/routes/index.d.ts +1 -0
  36. package/dist/routes/index.d.ts.map +1 -1
  37. package/dist/routes/index.js +1 -0
  38. package/dist/routes/index.js.map +1 -1
  39. package/dist/routes/initiative.d.ts +1 -0
  40. package/dist/routes/initiative.d.ts.map +1 -1
  41. package/dist/routes/merge.d.ts +354 -0
  42. package/dist/routes/merge.d.ts.map +1 -1
  43. package/dist/routes/mergeTrackRecord.d.ts +113 -0
  44. package/dist/routes/mergeTrackRecord.d.ts.map +1 -0
  45. package/dist/routes/mergeTrackRecord.js +33 -0
  46. package/dist/routes/mergeTrackRecord.js.map +1 -0
  47. package/dist/routes/notification-webhooks.d.ts +3 -3
  48. package/dist/routes/notifications.d.ts +12 -4
  49. package/dist/routes/notifications.d.ts.map +1 -1
  50. package/dist/routes/notifications.js +4 -2
  51. package/dist/routes/notifications.js.map +1 -1
  52. package/dist/routes/public-api.d.ts +9 -3
  53. package/dist/routes/public-api.d.ts.map +1 -1
  54. package/dist/routes/slack.d.ts +3 -3
  55. package/dist/routes/tasks.d.ts +3 -0
  56. package/dist/routes/tasks.d.ts.map +1 -1
  57. package/dist/routes/tracker.d.ts +3 -0
  58. package/dist/routes/tracker.d.ts.map +1 -1
  59. package/dist/routes/workspaces.d.ts +130 -2
  60. package/dist/routes/workspaces.d.ts.map +1 -1
  61. package/dist/slack.d.ts +2 -2
  62. package/dist/snapshot.d.ts +65 -1
  63. package/dist/snapshot.d.ts.map +1 -1
  64. package/dist/tracker.d.ts +12 -0
  65. package/dist/tracker.d.ts.map +1 -1
  66. package/dist/tracker.js +12 -0
  67. package/dist/tracker.js.map +1 -1
  68. package/package.json +1 -1
package/dist/merge.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as v from 'valibot';
2
2
  import { stepGatingSchema } from './consensus.js';
3
+ import { changeClassSchema, RULEABLE_CHANGE_CLASSES } from './mergeTrackRecord.js';
3
4
  // ---------------------------------------------------------------------------
4
5
  // Merge-policy wire contracts. After a pipeline's implementation work is done
5
6
  // and CI is green, a `merger` agent assesses the pull request along three axes —
@@ -32,6 +33,34 @@ export const REQUIREMENT_CONCERN_RANK = {
32
33
  medium: 2,
33
34
  high: 3,
34
35
  };
36
+ // ---------------------------------------------------------------------------
37
+ // Per-CLASS auto-merge rules. The score ceilings below apply uniformly to every
38
+ // change, which leaves a workspace unable to express "auto-merge dependency bumps
39
+ // and docs, always review schema changes". A preset therefore also carries an
40
+ // optional rule per {@link ChangeClass}, resolved against the run's deterministic,
41
+ // path-derived classification. See `docs/initiatives/merge-track-record.md`.
42
+ // ---------------------------------------------------------------------------
43
+ /**
44
+ * What a preset does with a pull request of a given change class:
45
+ *
46
+ * - `thresholds` — compare the merger's scores against this preset's ceilings (the default,
47
+ * and what an ABSENT entry means, so `{}` behaves exactly like no rules at all).
48
+ * - `always` — auto-merge regardless of the scores.
49
+ * - `never` — always route to a human, regardless of the scores.
50
+ */
51
+ export const mergeClassRuleSchema = v.picklist(['thresholds', 'always', 'never']);
52
+ /**
53
+ * A preset's per-class rules: a PARTIAL map from change class to its rule. An absent class
54
+ * means `thresholds`, so an empty object is the "behave exactly as before" identity.
55
+ *
56
+ * `unknown` is deliberately NOT a member: an unclassifiable diff (no VCS client wired, a
57
+ * transient provider outage) must fall back to the score thresholds rather than silently
58
+ * adopt a widened policy. See `RULEABLE_CHANGE_CLASSES`.
59
+ */
60
+ export const mergeClassRulesSchema = v.partial(
61
+ // STRICT: an unknown key (notably `unknown`, which no rule may ever match) is a 400 rather than
62
+ // being silently stripped. A caller who thinks they authored a rule must not be told it worked.
63
+ v.strictObject(Object.fromEntries(RULEABLE_CHANGE_CLASSES.map((c) => [c, mergeClassRuleSchema]))));
35
64
  export const mergeAssessmentSchema = v.object({
36
65
  /** How intricate the change is (size, coupling, subtlety). */
37
66
  complexity: v.pipe(v.number(), v.minValue(0), v.maxValue(1)),
@@ -118,6 +147,12 @@ export const riskPolicySchema = v.object({
118
147
  * built-in presets.
119
148
  */
120
149
  forkDecision: v.optional(v.nullable(stepGatingSchema)),
150
+ /**
151
+ * Per-change-class auto-merge rules ({@link mergeClassRulesSchema}). An absent class — and
152
+ * therefore an empty object — means "use the score ceilings above", so `{}` is the identity.
153
+ * A rule NEVER overrides `autoMergeEnabled: false`: that master switch wins first.
154
+ */
155
+ classRules: mergeClassRulesSchema,
121
156
  /** The workspace's fallback preset, used by tasks that pick none. Exactly one is true. */
122
157
  isDefault: v.boolean(),
123
158
  /**
@@ -154,6 +189,8 @@ export const createRiskPolicySchema = v.object({
154
189
  autoMergeEnabled: v.optional(v.boolean(), true),
155
190
  /** Estimate gating for the implementation-fork decision phase; absent ⇒ off in `auto` mode. */
156
191
  forkDecision: v.optional(v.nullable(stepGatingSchema)),
192
+ /** Per-change-class auto-merge rules; absent ⇒ every class uses the score ceilings. */
193
+ classRules: v.optional(mergeClassRulesSchema, {}),
157
194
  /** Make this the workspace default (demotes the previous default). */
158
195
  isDefault: v.optional(v.boolean(), false),
159
196
  });
@@ -172,6 +209,8 @@ export const updateRiskPolicySchema = v.object({
172
209
  humanReviewGraceMinutes: v.optional(graceMinutesSchema),
173
210
  autoMergeEnabled: v.optional(v.boolean()),
174
211
  forkDecision: v.optional(v.nullable(stepGatingSchema)),
212
+ /** Replaces the whole rule map (not merged), so clearing a class is a plain omission. */
213
+ classRules: v.optional(mergeClassRulesSchema),
175
214
  isDefault: v.optional(v.boolean()),
176
215
  });
177
216
  /** Parse-or-throw an assessment payload an agent returned (the engine validates it). */
@@ -195,6 +234,13 @@ export const mergeDecisionThresholdsSchema = v.object({
195
234
  maxRisk: v.pipe(v.number(), v.minValue(0), v.maxValue(1)),
196
235
  maxImpact: v.pipe(v.number(), v.minValue(0), v.maxValue(1)),
197
236
  autoMergeEnabled: v.boolean(),
237
+ /**
238
+ * The rule the preset carried for the run's resolved change class, when one applied —
239
+ * so the decision banner can say "auto-merged because this preset always auto-merges
240
+ * dependency bumps" rather than implying the scores did it. Absent when the class was
241
+ * `unknown` (rules never match it) or the preset left the class on `thresholds`.
242
+ */
243
+ classRule: v.optional(mergeClassRuleSchema),
198
244
  });
199
245
  export const mergeDecisionSchema = v.object({
200
246
  /** What the engine did: merged the PR for real, or left it open for a human. */
@@ -212,6 +258,11 @@ export const mergeDecisionSchema = v.object({
212
258
  * - `merge_partial`: review; a MULTI-REPO task auto-merged some of its PRs but an
213
259
  * intermediate merge failed (cross-repo merges are non-atomic), so the block is left
214
260
  * blocked with a notification enumerating the merged vs unmerged repos.
261
+ * - `class_auto_merge`: auto-merged because the preset's rule for the run's change class
262
+ * is `always` — the scores (and the rationale-credibility backstop) were bypassed by an
263
+ * explicit operator policy keyed on the DETERMINISTIC backend classification.
264
+ * - `class_requires_review`: review; the preset's rule for the change class is `never`,
265
+ * regardless of how low the scores were.
215
266
  */
216
267
  reason: v.picklist([
217
268
  'within_thresholds',
@@ -221,11 +272,20 @@ export const mergeDecisionSchema = v.object({
221
272
  'no_assessment',
222
273
  'merge_failed',
223
274
  'merge_partial',
275
+ 'class_auto_merge',
276
+ 'class_requires_review',
224
277
  ]),
225
278
  /** The merger's assessment (absent only when it produced no parseable one). */
226
279
  assessment: v.optional(mergeAssessmentSchema),
227
280
  thresholds: mergeDecisionThresholdsSchema,
228
281
  /** The axes that exceeded their ceiling (empty unless `reason` is `exceeded_thresholds`). */
229
282
  exceededAxes: v.array(mergeAxisSchema),
283
+ /**
284
+ * The run's deterministic change class, when classification resolved one. Recorded on the
285
+ * step so the SPA can show WHAT KIND of change the decision was made about (and, with the
286
+ * class's rollup, how that class has historically fared). Absent ⇒ classification did not
287
+ * run (no VCS client wired) — the same state `unknown` denotes on a track record.
288
+ */
289
+ changeClass: v.optional(changeClassSchema),
230
290
  });
231
291
  //# sourceMappingURL=merge.js.map
package/dist/merge.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,183 @@
1
+ import * as v from 'valibot';
2
+ /**
3
+ * What kind of change a run's pull request made, derived DETERMINISTICALLY on the backend
4
+ * from the PR's changed-file list (never from an agent's opinion). A small closed set so it
5
+ * can key a per-class merge rule, a rollup `GROUP BY`, and an i18n label.
6
+ *
7
+ * - `docs` — documentation + user-facing copy (Markdown, `docs/`, i18n catalogs).
8
+ * - `test` — test/spec/fixture files only.
9
+ * - `dependency` — dependency manifests + lockfiles (a bump).
10
+ * - `config` — CI workflows, tooling config, container/IaC manifests.
11
+ * - `source` — application/library source code (the catch-all for real code).
12
+ * - `schema` — database migrations + schema definitions (the riskiest: irreversible).
13
+ * - `unknown` — no changed-file list was available (no VCS client wired, or an empty diff).
14
+ *
15
+ * A MIXED diff resolves to the HIGHEST-RANKED class present (see `CHANGE_CLASS_RANK` /
16
+ * `classifyChangedFiles` in `@cat-factory/kernel`), so a per-class rule can only ever fire on a
17
+ * diff containing nothing riskier than that class.
18
+ */
19
+ export declare const changeClassSchema: v.PicklistSchema<["docs", "test", "dependency", "config", "source", "schema", "unknown"], undefined>;
20
+ export type ChangeClass = v.InferOutput<typeof changeClassSchema>;
21
+ /**
22
+ * Every {@link ChangeClass} in rank order (lowest → highest risk), `unknown` last. The
23
+ * ordering the preset editor renders and the rollup table iterates, so a new class is added
24
+ * in ONE place. `unknown` is deliberately last: it is a fallback outcome, not a policy target.
25
+ */
26
+ export declare const CHANGE_CLASSES: readonly ["docs", "test", "dependency", "config", "source", "schema", "unknown"];
27
+ /**
28
+ * The classes a per-class merge RULE may be authored for — every class except `unknown`.
29
+ * `unknown` must stay inert: an unclassifiable diff (a transient VCS outage) has to fall
30
+ * back to the score thresholds rather than silently adopt a widened policy.
31
+ */
32
+ export declare const RULEABLE_CHANGE_CLASSES: readonly ["docs", "test", "dependency", "config", "source", "schema"];
33
+ export type RuleableChangeClass = (typeof RULEABLE_CHANGE_CLASSES)[number];
34
+ /**
35
+ * How much review effort a human actually spent on a pull request before merging it — the
36
+ * ground truth the auto-merge score thresholds are trying to approximate.
37
+ *
38
+ * - `none` — merged with zero blocking comments.
39
+ * - `minor` — small comments / a nit pass, no substantive rework.
40
+ * - `major` — real rework was required.
41
+ *
42
+ * ALWAYS optional: an untagged merge records a null tag and every consumer treats null as
43
+ * "not tagged", never as `none`.
44
+ */
45
+ export declare const reviewEffortSchema: v.PicklistSchema<["none", "minor", "major"], undefined>;
46
+ export type ReviewEffort = v.InferOutput<typeof reviewEffortSchema>;
47
+ /** Every {@link ReviewEffort} in ascending order — the chip order the SPA renders. */
48
+ export declare const REVIEW_EFFORTS: readonly ["none", "minor", "major"];
49
+ /**
50
+ * What ultimately happened to the pull request a track record covers.
51
+ *
52
+ * - `pending_review` — the merger step routed it to a human; not yet resolved. Recorded at
53
+ * the decision so the class + scores are captured even if the human never comes back.
54
+ * - `auto_merged` — the engine merged it on the policy (thresholds or a class rule).
55
+ * - `human_merged` — a human confirmed the merge THROUGH cat-factory (a notification act
56
+ * or the inspector's merge control).
57
+ * - `external_merged` — a human merged it directly on the VCS provider, bypassing
58
+ * cat-factory; detected from the webhook ingest.
59
+ * - `rejected` — a human dismissed the review card instead of merging.
60
+ */
61
+ export declare const mergeTrackDecisionSchema: v.PicklistSchema<["pending_review", "auto_merged", "human_merged", "external_merged", "rejected"], undefined>;
62
+ export type MergeTrackDecision = v.InferOutput<typeof mergeTrackDecisionSchema>;
63
+ /**
64
+ * The decisions that represent a pull request that actually LANDED. The auto-merge share a
65
+ * rollup reports is `autoMerged / (every landed decision)` — a `pending_review` row is not in
66
+ * the denominator (nothing was decided yet) and neither is a `rejected` one.
67
+ */
68
+ export declare const MERGED_TRACK_DECISIONS: readonly ["auto_merged", "human_merged", "external_merged"];
69
+ /**
70
+ * One persisted merge decision: what kind of change it was, what the merger scored it, what
71
+ * the engine/human did, and how much review effort it needed. Written best-effort off the
72
+ * merge path — a failure to write one NEVER blocks or fails a merge.
73
+ *
74
+ * Provider-neutral by construction: the repo identity is `repoId` + `provider` (the kernel
75
+ * `VcsRepoRef`/`VcsProvider` vocabulary), never a GitHub-shaped `githubId`/`installationId`.
76
+ */
77
+ export declare const mergeTrackRecordSchema: v.ObjectSchema<{
78
+ /**
79
+ * Deterministic id, derived from the run: `mtr_<executionId>`. Deterministic so a durable-driver
80
+ * replay of a settled merger step collides with the row it already wrote (first write wins)
81
+ * instead of duplicating it.
82
+ */
83
+ readonly id: v.StringSchema<undefined>;
84
+ /** The task/block whose pull request this covers. */
85
+ readonly blockId: v.StringSchema<undefined>;
86
+ /**
87
+ * The run that produced the PR. Nullable at the wire/storage level because the column is, but
88
+ * every record written today is born at a merge DECISION POINT inside a run, so it is set. An
89
+ * external merge does not MINT a record — it settles the one the run already wrote (which is
90
+ * also why attribution keys on `(repoId, prNumber)`); a PR cat-factory never opened has no
91
+ * record and is correctly invisible to the track record.
92
+ */
93
+ readonly executionId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
94
+ /** The deterministic, path-derived change class (see {@link changeClassSchema}). */
95
+ readonly changeClass: v.PicklistSchema<["docs", "test", "dependency", "config", "source", "schema", "unknown"], undefined>;
96
+ /** How many files the PR changed, when the changed-file list was readable. */
97
+ readonly changedFileCount: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
98
+ /** The merger's complexity score at the decision, when it produced a parseable assessment. */
99
+ readonly complexity: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 1, undefined>]>, undefined>;
100
+ /** The merger's risk score at the decision, when one was produced. */
101
+ readonly risk: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 1, undefined>]>, undefined>;
102
+ /** The merger's impact score at the decision, when one was produced. */
103
+ readonly impact: v.NullableSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, 1, undefined>]>, undefined>;
104
+ /** The merge preset the decision was made against, for reading a record back in context. */
105
+ readonly riskPolicyId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
106
+ readonly riskPolicyName: v.NullableSchema<v.StringSchema<undefined>, undefined>;
107
+ /** What happened (see {@link mergeTrackDecisionSchema}). */
108
+ readonly decision: v.PicklistSchema<["pending_review", "auto_merged", "human_merged", "external_merged", "rejected"], undefined>;
109
+ /** The human's effort tag — null until somebody tags it. Tagging is never mandatory. */
110
+ readonly reviewEffort: v.NullableSchema<v.PicklistSchema<["none", "minor", "major"], undefined>, undefined>;
111
+ /** The PR number within its repo, when known. */
112
+ readonly prNumber: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
113
+ /** The PR's web URL, for the card's deep link. */
114
+ readonly prUrl: v.NullableSchema<v.StringSchema<undefined>, undefined>;
115
+ /** Provider-neutral repo id the PR belongs to (`VcsRepoRef.repoId`). */
116
+ readonly repoId: v.NullableSchema<v.StringSchema<undefined>, undefined>;
117
+ /** Which VCS provider hosts it — so a mixed-provider workspace reads back correctly. */
118
+ readonly provider: v.NullableSchema<v.PicklistSchema<["github", "gitlab"], undefined>, undefined>;
119
+ /** Epoch ms the decision was recorded (the merger step's resolution). */
120
+ readonly createdAt: v.NumberSchema<undefined>;
121
+ /** Epoch ms the decision reached a terminal value; null while `pending_review`. */
122
+ readonly resolvedAt: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
123
+ /** Epoch ms the effort tag was recorded; null while untagged. */
124
+ readonly taggedAt: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
125
+ }, undefined>;
126
+ export type MergeTrackRecord = v.InferOutput<typeof mergeTrackRecordSchema>;
127
+ /** The per-effort-level counts within a class's rollup. `untagged` counts null tags. */
128
+ export declare const reviewEffortDistributionSchema: v.ObjectSchema<{
129
+ readonly none: v.NumberSchema<undefined>;
130
+ readonly minor: v.NumberSchema<undefined>;
131
+ readonly major: v.NumberSchema<undefined>;
132
+ readonly untagged: v.NumberSchema<undefined>;
133
+ }, undefined>;
134
+ export type ReviewEffortDistribution = v.InferOutput<typeof reviewEffortDistributionSchema>;
135
+ /** One change class's accumulated track record — the number that justifies widening a rule. */
136
+ export declare const mergeClassRollupSchema: v.ObjectSchema<{
137
+ readonly changeClass: v.PicklistSchema<["docs", "test", "dependency", "config", "source", "schema", "unknown"], undefined>;
138
+ /** Every record in the class, including still-`pending_review` ones. */
139
+ readonly total: v.NumberSchema<undefined>;
140
+ /** Records whose PR landed (auto + human + external) — the auto-merge-share denominator. */
141
+ readonly merged: v.NumberSchema<undefined>;
142
+ readonly autoMerged: v.NumberSchema<undefined>;
143
+ readonly humanMerged: v.NumberSchema<undefined>;
144
+ readonly externalMerged: v.NumberSchema<undefined>;
145
+ readonly rejected: v.NumberSchema<undefined>;
146
+ readonly pendingReview: v.NumberSchema<undefined>;
147
+ readonly effort: v.ObjectSchema<{
148
+ readonly none: v.NumberSchema<undefined>;
149
+ readonly minor: v.NumberSchema<undefined>;
150
+ readonly major: v.NumberSchema<undefined>;
151
+ readonly untagged: v.NumberSchema<undefined>;
152
+ }, undefined>;
153
+ }, undefined>;
154
+ export type MergeClassRollup = v.InferOutput<typeof mergeClassRollupSchema>;
155
+ /**
156
+ * The auto-merge share of a class's LANDED records, 0..1, or null when nothing has landed
157
+ * yet (so the UI shows "no data" rather than a misleading 0%). Shared by the preset editor
158
+ * and any backend consumer so the two can never disagree.
159
+ */
160
+ export declare function autoMergeShare(rollup: MergeClassRollup): number | null;
161
+ /**
162
+ * The share of a class's TAGGED records that needed no blocking comments, 0..1, or null when
163
+ * nothing in the class has been tagged. This — not the auto-merge share — is the evidence that
164
+ * justifies flipping a class to `always`: it says humans found nothing to say.
165
+ */
166
+ export declare function frictionlessShare(rollup: MergeClassRollup): number | null;
167
+ /** An empty rollup for a class with no records yet (the UI renders every class, always). */
168
+ export declare function emptyMergeClassRollup(changeClass: ChangeClass): MergeClassRollup;
169
+ /**
170
+ * Body of `POST /blocks/:blockId/merge` — the inspector's merge control. Every field is optional,
171
+ * so `{}` is the historical no-body merge; `reviewEffort` records the effort tag onto the block's
172
+ * merge track record in the same request (the counterpart of the notification card's `act` body).
173
+ */
174
+ export declare const mergeBlockSchema: v.ObjectSchema<{
175
+ readonly reviewEffort: v.OptionalSchema<v.NullableSchema<v.PicklistSchema<["none", "minor", "major"], undefined>, undefined>, undefined>;
176
+ }, undefined>;
177
+ export type MergeBlockInput = v.InferOutput<typeof mergeBlockSchema>;
178
+ /** Tag a record with the review effort a human actually spent (`null` clears the tag). */
179
+ export declare const tagReviewEffortSchema: v.ObjectSchema<{
180
+ readonly reviewEffort: v.NullableSchema<v.PicklistSchema<["none", "minor", "major"], undefined>, undefined>;
181
+ }, undefined>;
182
+ export type TagReviewEffortInput = v.InferOutput<typeof tagReviewEffortSchema>;
183
+ //# sourceMappingURL=mergeTrackRecord.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeTrackRecord.d.ts","sourceRoot":"","sources":["../src/mergeTrackRecord.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAwB5B;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,sGAQ5B,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAEjE;;;;GAIG;AACH,eAAO,MAAM,cAAc,kFAQgB,CAAA;AAE3C;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,uEAOO,CAAA;AAE3C,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE1E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,yDAAyC,CAAA;AACxE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAEnE,sFAAsF;AACtF,eAAO,MAAM,cAAc,qCAAwE,CAAA;AAEnG;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,+GAMnC,CAAA;AACF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAE/E;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,6DAIe,CAAA;AAIlD;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;IACjC;;;;OAIG;;IAEH,qDAAqD;;IAErD;;;;;;OAMG;;IAEH,oFAAoF;;IAEpF,8EAA8E;;IAE9E,8FAA8F;;IAE9F,sEAAsE;;IAEtE,wEAAwE;;IAExE,4FAA4F;;;IAG5F,4DAA4D;;IAE5D,wFAAwF;;IAExF,iDAAiD;;IAEjD,kDAAkD;;IAElD,wEAAwE;;IAExE,wFAAwF;;IAExF,yEAAyE;;IAEzE,mFAAmF;;IAEnF,iEAAiE;;aAEjE,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAQ3E,wFAAwF;AACxF,eAAO,MAAM,8BAA8B;;;;;aAKzC,CAAA;AACF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,8BAA8B,CAAC,CAAA;AAE3F,+FAA+F;AAC/F,eAAO,MAAM,sBAAsB;;IAEjC,wEAAwE;;IAExE,4FAA4F;;;;;;;;;;;;;aAQ5F,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAE3E;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAGtE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAIzE;AAED,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,gBAAgB,CAYhF;AAID;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;aAE3B,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAEpE,0FAA0F;AAC1F,eAAO,MAAM,qBAAqB;;aAEhC,CAAA;AACF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,qBAAqB,CAAC,CAAA"}
@@ -0,0 +1,251 @@
1
+ import * as v from 'valibot';
2
+ import { vcsProviderSchema } from './routes/auth.js';
3
+ // ---------------------------------------------------------------------------
4
+ // Merge TRACK RECORD wire contracts — the accumulated human evidence behind the
5
+ // auto-merge policy.
6
+ //
7
+ // The merge decision itself runs on the `merger` agent's self-assessment (see
8
+ // `merge.ts`): scores vs the task's preset ceilings. This module models what the
9
+ // decision LEAVES BEHIND so the policy can eventually stand on evidence instead:
10
+ //
11
+ // - WHAT KIND of change it was (a deterministic, path-derived {@link ChangeClass}),
12
+ // - the merger's scores at the moment of the decision,
13
+ // - how much review effort a human actually spent ({@link ReviewEffort}, nullable
14
+ // until somebody tags it — tagging is never mandatory),
15
+ // - and what happened ({@link MergeTrackDecision}).
16
+ //
17
+ // Per-class rollups of those records are what justify WIDENING a policy, which is
18
+ // why merge presets carry per-class rules ({@link MergeClassRules} in `merge.ts`).
19
+ //
20
+ // Full design — the class precedence rules, the external-merge detection, and the
21
+ // preset reshape — is in `docs/initiatives/merge-track-record.md`.
22
+ // ---------------------------------------------------------------------------
23
+ /**
24
+ * What kind of change a run's pull request made, derived DETERMINISTICALLY on the backend
25
+ * from the PR's changed-file list (never from an agent's opinion). A small closed set so it
26
+ * can key a per-class merge rule, a rollup `GROUP BY`, and an i18n label.
27
+ *
28
+ * - `docs` — documentation + user-facing copy (Markdown, `docs/`, i18n catalogs).
29
+ * - `test` — test/spec/fixture files only.
30
+ * - `dependency` — dependency manifests + lockfiles (a bump).
31
+ * - `config` — CI workflows, tooling config, container/IaC manifests.
32
+ * - `source` — application/library source code (the catch-all for real code).
33
+ * - `schema` — database migrations + schema definitions (the riskiest: irreversible).
34
+ * - `unknown` — no changed-file list was available (no VCS client wired, or an empty diff).
35
+ *
36
+ * A MIXED diff resolves to the HIGHEST-RANKED class present (see `CHANGE_CLASS_RANK` /
37
+ * `classifyChangedFiles` in `@cat-factory/kernel`), so a per-class rule can only ever fire on a
38
+ * diff containing nothing riskier than that class.
39
+ */
40
+ export const changeClassSchema = v.picklist([
41
+ 'docs',
42
+ 'test',
43
+ 'dependency',
44
+ 'config',
45
+ 'source',
46
+ 'schema',
47
+ 'unknown',
48
+ ]);
49
+ /**
50
+ * Every {@link ChangeClass} in rank order (lowest → highest risk), `unknown` last. The
51
+ * ordering the preset editor renders and the rollup table iterates, so a new class is added
52
+ * in ONE place. `unknown` is deliberately last: it is a fallback outcome, not a policy target.
53
+ */
54
+ export const CHANGE_CLASSES = [
55
+ 'docs',
56
+ 'test',
57
+ 'dependency',
58
+ 'config',
59
+ 'source',
60
+ 'schema',
61
+ 'unknown',
62
+ ];
63
+ /**
64
+ * The classes a per-class merge RULE may be authored for — every class except `unknown`.
65
+ * `unknown` must stay inert: an unclassifiable diff (a transient VCS outage) has to fall
66
+ * back to the score thresholds rather than silently adopt a widened policy.
67
+ */
68
+ export const RULEABLE_CHANGE_CLASSES = [
69
+ 'docs',
70
+ 'test',
71
+ 'dependency',
72
+ 'config',
73
+ 'source',
74
+ 'schema',
75
+ ];
76
+ /**
77
+ * How much review effort a human actually spent on a pull request before merging it — the
78
+ * ground truth the auto-merge score thresholds are trying to approximate.
79
+ *
80
+ * - `none` — merged with zero blocking comments.
81
+ * - `minor` — small comments / a nit pass, no substantive rework.
82
+ * - `major` — real rework was required.
83
+ *
84
+ * ALWAYS optional: an untagged merge records a null tag and every consumer treats null as
85
+ * "not tagged", never as `none`.
86
+ */
87
+ export const reviewEffortSchema = v.picklist(['none', 'minor', 'major']);
88
+ /** Every {@link ReviewEffort} in ascending order — the chip order the SPA renders. */
89
+ export const REVIEW_EFFORTS = ['none', 'minor', 'major'];
90
+ /**
91
+ * What ultimately happened to the pull request a track record covers.
92
+ *
93
+ * - `pending_review` — the merger step routed it to a human; not yet resolved. Recorded at
94
+ * the decision so the class + scores are captured even if the human never comes back.
95
+ * - `auto_merged` — the engine merged it on the policy (thresholds or a class rule).
96
+ * - `human_merged` — a human confirmed the merge THROUGH cat-factory (a notification act
97
+ * or the inspector's merge control).
98
+ * - `external_merged` — a human merged it directly on the VCS provider, bypassing
99
+ * cat-factory; detected from the webhook ingest.
100
+ * - `rejected` — a human dismissed the review card instead of merging.
101
+ */
102
+ export const mergeTrackDecisionSchema = v.picklist([
103
+ 'pending_review',
104
+ 'auto_merged',
105
+ 'human_merged',
106
+ 'external_merged',
107
+ 'rejected',
108
+ ]);
109
+ /**
110
+ * The decisions that represent a pull request that actually LANDED. The auto-merge share a
111
+ * rollup reports is `autoMerged / (every landed decision)` — a `pending_review` row is not in
112
+ * the denominator (nothing was decided yet) and neither is a `rejected` one.
113
+ */
114
+ export const MERGED_TRACK_DECISIONS = [
115
+ 'auto_merged',
116
+ 'human_merged',
117
+ 'external_merged',
118
+ ];
119
+ const scoreSchema = v.pipe(v.number(), v.minValue(0), v.maxValue(1));
120
+ /**
121
+ * One persisted merge decision: what kind of change it was, what the merger scored it, what
122
+ * the engine/human did, and how much review effort it needed. Written best-effort off the
123
+ * merge path — a failure to write one NEVER blocks or fails a merge.
124
+ *
125
+ * Provider-neutral by construction: the repo identity is `repoId` + `provider` (the kernel
126
+ * `VcsRepoRef`/`VcsProvider` vocabulary), never a GitHub-shaped `githubId`/`installationId`.
127
+ */
128
+ export const mergeTrackRecordSchema = v.object({
129
+ /**
130
+ * Deterministic id, derived from the run: `mtr_<executionId>`. Deterministic so a durable-driver
131
+ * replay of a settled merger step collides with the row it already wrote (first write wins)
132
+ * instead of duplicating it.
133
+ */
134
+ id: v.string(),
135
+ /** The task/block whose pull request this covers. */
136
+ blockId: v.string(),
137
+ /**
138
+ * The run that produced the PR. Nullable at the wire/storage level because the column is, but
139
+ * every record written today is born at a merge DECISION POINT inside a run, so it is set. An
140
+ * external merge does not MINT a record — it settles the one the run already wrote (which is
141
+ * also why attribution keys on `(repoId, prNumber)`); a PR cat-factory never opened has no
142
+ * record and is correctly invisible to the track record.
143
+ */
144
+ executionId: v.nullable(v.string()),
145
+ /** The deterministic, path-derived change class (see {@link changeClassSchema}). */
146
+ changeClass: changeClassSchema,
147
+ /** How many files the PR changed, when the changed-file list was readable. */
148
+ changedFileCount: v.nullable(v.number()),
149
+ /** The merger's complexity score at the decision, when it produced a parseable assessment. */
150
+ complexity: v.nullable(scoreSchema),
151
+ /** The merger's risk score at the decision, when one was produced. */
152
+ risk: v.nullable(scoreSchema),
153
+ /** The merger's impact score at the decision, when one was produced. */
154
+ impact: v.nullable(scoreSchema),
155
+ /** The merge preset the decision was made against, for reading a record back in context. */
156
+ riskPolicyId: v.nullable(v.string()),
157
+ riskPolicyName: v.nullable(v.string()),
158
+ /** What happened (see {@link mergeTrackDecisionSchema}). */
159
+ decision: mergeTrackDecisionSchema,
160
+ /** The human's effort tag — null until somebody tags it. Tagging is never mandatory. */
161
+ reviewEffort: v.nullable(reviewEffortSchema),
162
+ /** The PR number within its repo, when known. */
163
+ prNumber: v.nullable(v.number()),
164
+ /** The PR's web URL, for the card's deep link. */
165
+ prUrl: v.nullable(v.string()),
166
+ /** Provider-neutral repo id the PR belongs to (`VcsRepoRef.repoId`). */
167
+ repoId: v.nullable(v.string()),
168
+ /** Which VCS provider hosts it — so a mixed-provider workspace reads back correctly. */
169
+ provider: v.nullable(vcsProviderSchema),
170
+ /** Epoch ms the decision was recorded (the merger step's resolution). */
171
+ createdAt: v.number(),
172
+ /** Epoch ms the decision reached a terminal value; null while `pending_review`. */
173
+ resolvedAt: v.nullable(v.number()),
174
+ /** Epoch ms the effort tag was recorded; null while untagged. */
175
+ taggedAt: v.nullable(v.number()),
176
+ });
177
+ // ---------------------------------------------------------------------------
178
+ // Per-class rollups — SQL aggregates (COUNT / GROUP BY / conditional SUM), never
179
+ // rows loaded and reduced in JS. ONE query per workspace returns every class, so
180
+ // the preset editor's stats load in a single round-trip.
181
+ // ---------------------------------------------------------------------------
182
+ /** The per-effort-level counts within a class's rollup. `untagged` counts null tags. */
183
+ export const reviewEffortDistributionSchema = v.object({
184
+ none: v.number(),
185
+ minor: v.number(),
186
+ major: v.number(),
187
+ untagged: v.number(),
188
+ });
189
+ /** One change class's accumulated track record — the number that justifies widening a rule. */
190
+ export const mergeClassRollupSchema = v.object({
191
+ changeClass: changeClassSchema,
192
+ /** Every record in the class, including still-`pending_review` ones. */
193
+ total: v.number(),
194
+ /** Records whose PR landed (auto + human + external) — the auto-merge-share denominator. */
195
+ merged: v.number(),
196
+ autoMerged: v.number(),
197
+ humanMerged: v.number(),
198
+ externalMerged: v.number(),
199
+ rejected: v.number(),
200
+ pendingReview: v.number(),
201
+ effort: reviewEffortDistributionSchema,
202
+ });
203
+ /**
204
+ * The auto-merge share of a class's LANDED records, 0..1, or null when nothing has landed
205
+ * yet (so the UI shows "no data" rather than a misleading 0%). Shared by the preset editor
206
+ * and any backend consumer so the two can never disagree.
207
+ */
208
+ export function autoMergeShare(rollup) {
209
+ if (rollup.merged === 0)
210
+ return null;
211
+ return rollup.autoMerged / rollup.merged;
212
+ }
213
+ /**
214
+ * The share of a class's TAGGED records that needed no blocking comments, 0..1, or null when
215
+ * nothing in the class has been tagged. This — not the auto-merge share — is the evidence that
216
+ * justifies flipping a class to `always`: it says humans found nothing to say.
217
+ */
218
+ export function frictionlessShare(rollup) {
219
+ const tagged = rollup.effort.none + rollup.effort.minor + rollup.effort.major;
220
+ if (tagged === 0)
221
+ return null;
222
+ return rollup.effort.none / tagged;
223
+ }
224
+ /** An empty rollup for a class with no records yet (the UI renders every class, always). */
225
+ export function emptyMergeClassRollup(changeClass) {
226
+ return {
227
+ changeClass,
228
+ total: 0,
229
+ merged: 0,
230
+ autoMerged: 0,
231
+ humanMerged: 0,
232
+ externalMerged: 0,
233
+ rejected: 0,
234
+ pendingReview: 0,
235
+ effort: { none: 0, minor: 0, major: 0, untagged: 0 },
236
+ };
237
+ }
238
+ // ---- Request bodies -------------------------------------------------------
239
+ /**
240
+ * Body of `POST /blocks/:blockId/merge` — the inspector's merge control. Every field is optional,
241
+ * so `{}` is the historical no-body merge; `reviewEffort` records the effort tag onto the block's
242
+ * merge track record in the same request (the counterpart of the notification card's `act` body).
243
+ */
244
+ export const mergeBlockSchema = v.object({
245
+ reviewEffort: v.optional(v.nullable(reviewEffortSchema)),
246
+ });
247
+ /** Tag a record with the review effort a human actually spent (`null` clears the tag). */
248
+ export const tagReviewEffortSchema = v.object({
249
+ reviewEffort: v.nullable(reviewEffortSchema),
250
+ });
251
+ //# sourceMappingURL=mergeTrackRecord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeTrackRecord.js","sourceRoot":"","sources":["../src/mergeTrackRecord.ts"],"names":[],"mappings":"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"}