@patronage/software-factory 0.25.0 → 0.30.0-alpha.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/CONTEXT.md +1 -1
- package/README.md +5 -5
- package/dist/index.d.ts +284 -392
- package/dist/index.js +1149 -1099
- package/dist/schemas.d.ts +60 -168
- package/dist/schemas.js +39 -70
- package/package.json +1 -1
package/dist/schemas.d.ts
CHANGED
|
@@ -109,105 +109,6 @@ interface FollowUpAction {
|
|
|
109
109
|
command: string;
|
|
110
110
|
}
|
|
111
111
|
//#endregion
|
|
112
|
-
//#region src/merge-preflight/worktree-held-branch.d.ts
|
|
113
|
-
/**
|
|
114
|
-
* Detects when a PR head branch is checked out in a local git worktree.
|
|
115
|
-
*
|
|
116
|
-
* `gh pr merge --delete-branch` fails when the local branch is held by a
|
|
117
|
-
* worktree (git refuses to delete a checked-out branch), which previously
|
|
118
|
-
* broke the auto-merge lane mid-merge (patronage/internal#284). The merge
|
|
119
|
-
* preflight surfaces this as an actionable notice — not a hard fail — so the
|
|
120
|
-
* operator merges without `--delete-branch` (or prunes the worktree first)
|
|
121
|
-
* and defers local branch cleanup to closeout.
|
|
122
|
-
*/
|
|
123
|
-
interface WorktreeHeldBranch {
|
|
124
|
-
branch: string;
|
|
125
|
-
worktreePath: string;
|
|
126
|
-
}
|
|
127
|
-
//#endregion
|
|
128
|
-
//#region src/pr-readiness/merge-identity.d.ts
|
|
129
|
-
interface PostProofCommit {
|
|
130
|
-
sha: string;
|
|
131
|
-
subject: string;
|
|
132
|
-
}
|
|
133
|
-
type MergeIdentityResult = {
|
|
134
|
-
kind: "match";
|
|
135
|
-
headSha: string;
|
|
136
|
-
} | {
|
|
137
|
-
kind: "diverged";
|
|
138
|
-
liveHeadSha: string;
|
|
139
|
-
postProofCommits?: PostProofCommit[];
|
|
140
|
-
proofHeadSha: string;
|
|
141
|
-
};
|
|
142
|
-
type MergeGuardIdentity = MergeIdentityResult | {
|
|
143
|
-
kind: "live-head-invalid";
|
|
144
|
-
pr: number;
|
|
145
|
-
received: string;
|
|
146
|
-
} | {
|
|
147
|
-
kind: "ready-proof-missing";
|
|
148
|
-
errorDetail?: string;
|
|
149
|
-
readyProofPath: string;
|
|
150
|
-
} | {
|
|
151
|
-
kind: "ready-proof-pr-mismatch";
|
|
152
|
-
proofPr: number;
|
|
153
|
-
requestedPr: number;
|
|
154
|
-
} | {
|
|
155
|
-
kind: "ready-proof-not-ready";
|
|
156
|
-
blockingReasons: string[];
|
|
157
|
-
status: string;
|
|
158
|
-
};
|
|
159
|
-
//#endregion
|
|
160
|
-
//#region src/review-rungs.d.ts
|
|
161
|
-
declare const EVIDENCE_REVIEW_RUNGS: readonly ["independent-model", "oracle", "human"];
|
|
162
|
-
type EvidenceReviewRung = (typeof EVIDENCE_REVIEW_RUNGS)[number];
|
|
163
|
-
//#endregion
|
|
164
|
-
//#region src/pr-merge-check.d.ts
|
|
165
|
-
interface PrMergeCheckProof {
|
|
166
|
-
schemaVersion: 1;
|
|
167
|
-
blockingReasons: string[];
|
|
168
|
-
boundary?: {
|
|
169
|
-
autoMerge: boolean;
|
|
170
|
-
epic: number;
|
|
171
|
-
review: EvidenceReviewRung;
|
|
172
|
-
wave: string;
|
|
173
|
-
};
|
|
174
|
-
command: "patronage-factory pr:merge-check";
|
|
175
|
-
/**
|
|
176
|
-
* Machine-safe arg array for the obvious next action (#523): on `pass`, the
|
|
177
|
-
* remote-only GitHub merge API invocation for this PR; on `fail`, the re-run that clears the
|
|
178
|
-
* block (`pr:ready`, or `pr:verify` then `pr:ready` after a head
|
|
179
|
-
* divergence). Same `argv` shape `factory:delegate --print` emits. Optional
|
|
180
|
-
* and purely additive — existing consumers ignore it.
|
|
181
|
-
*/
|
|
182
|
-
followUp?: FollowUpAction;
|
|
183
|
-
identity: MergeGuardIdentity;
|
|
184
|
-
/**
|
|
185
|
-
* The pushed PR head SHA fetched from GitHub at check time. Absent only
|
|
186
|
-
* when GitHub returned no usable 40-hex head (identity kind
|
|
187
|
-
* "live-head-invalid"), which is itself a fail-closed blocking state.
|
|
188
|
-
*/
|
|
189
|
-
liveHeadSha?: string;
|
|
190
|
-
/**
|
|
191
|
-
* Actionable operational notices that do not block the merge, e.g. a PR
|
|
192
|
-
* head branch held by a local worktree, which makes
|
|
193
|
-
* `gh pr merge --delete-branch` fail (patronage/internal#284).
|
|
194
|
-
*/
|
|
195
|
-
notices?: string[];
|
|
196
|
-
pr: number;
|
|
197
|
-
status: "pass" | "fail";
|
|
198
|
-
/**
|
|
199
|
-
* Demands that were in force, were NOT met, and were waived by the operator
|
|
200
|
-
* (#354). Each entry carries the demand's refusals verbatim, so a waived
|
|
201
|
-
* demand can never read as a met one; the merge proceeds on the recorded
|
|
202
|
-
* operator act, not on evidence.
|
|
203
|
-
*/
|
|
204
|
-
waivedDemands?: WaivedDemand[];
|
|
205
|
-
/** Present when the PR head branch is checked out in a local worktree. */
|
|
206
|
-
worktreeHeldBranch?: WorktreeHeldBranch;
|
|
207
|
-
/** All merge-relevant branches held by local worktrees (head and default). */
|
|
208
|
-
worktreeHeldBranches?: WorktreeHeldBranch[];
|
|
209
|
-
}
|
|
210
|
-
//#endregion
|
|
211
112
|
//#region src/diff-classification.d.ts
|
|
212
113
|
declare const DIFF_CLASSIFICATIONS: readonly ["docs/process-only", "trivial", "non-trivial"];
|
|
213
114
|
type DiffClassification = (typeof DIFF_CLASSIFICATIONS)[number];
|
|
@@ -252,6 +153,10 @@ interface ReviewFindingAttributes {
|
|
|
252
153
|
title: string;
|
|
253
154
|
}
|
|
254
155
|
//#endregion
|
|
156
|
+
//#region src/review-rungs.d.ts
|
|
157
|
+
declare const EVIDENCE_REVIEW_RUNGS: readonly ["independent-model", "oracle", "human"];
|
|
158
|
+
type EvidenceReviewRung = (typeof EVIDENCE_REVIEW_RUNGS)[number];
|
|
159
|
+
//#endregion
|
|
255
160
|
//#region src/review-ladder-ledger.d.ts
|
|
256
161
|
type LadderCycleStage = "interior" | "gate";
|
|
257
162
|
type LadderFindingReport = ReviewFindingAttributes;
|
|
@@ -371,12 +276,11 @@ declare const managedReadinessLedgerSchema: z.ZodObject<{
|
|
|
371
276
|
name: z.ZodString;
|
|
372
277
|
reason: z.ZodOptional<z.ZodString>;
|
|
373
278
|
scope: z.ZodOptional<z.ZodObject<{
|
|
374
|
-
classifications: z.
|
|
279
|
+
classifications: z.ZodArray<z.ZodEnum<{
|
|
375
280
|
"docs/process-only": "docs/process-only";
|
|
376
281
|
trivial: "trivial";
|
|
377
282
|
"non-trivial": "non-trivial";
|
|
378
|
-
}
|
|
379
|
-
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
283
|
+
}>>;
|
|
380
284
|
}, z.core.$strict>>;
|
|
381
285
|
scopeReason: z.ZodString;
|
|
382
286
|
status: z.ZodEnum<{
|
|
@@ -577,7 +481,20 @@ type ManagedReadinessLedger = z.infer<typeof managedReadinessLedgerSchema>;
|
|
|
577
481
|
//#endregion
|
|
578
482
|
//#region src/pr-ready.d.ts
|
|
579
483
|
interface PrReadyProof {
|
|
580
|
-
schemaVersion:
|
|
484
|
+
schemaVersion: 3;
|
|
485
|
+
/**
|
|
486
|
+
* What GitHub actually did when this run armed native auto-merge (#477).
|
|
487
|
+
* Present exactly when readiness passed and the arming ran; read back from
|
|
488
|
+
* the PR rather than inferred from the invocation, because `gh pr merge
|
|
489
|
+
* --auto` arms, merges, or does nothing with the same exit code and the same
|
|
490
|
+
* empty output. `not-armed` means the candidate is admitted but nothing will
|
|
491
|
+
* merge it, and `followUp` carries the re-dispatch.
|
|
492
|
+
*/
|
|
493
|
+
arming?: {
|
|
494
|
+
detail?: string;
|
|
495
|
+
headSha: string;
|
|
496
|
+
outcome: "armed" | "merged" | "not-armed";
|
|
497
|
+
};
|
|
581
498
|
/**
|
|
582
499
|
* Why this run blocked, one entry per refusing demand (#391): `code` is the
|
|
583
500
|
* demand key from the resolver's vocabulary, `detail` the one-sentence
|
|
@@ -590,11 +507,12 @@ interface PrReadyProof {
|
|
|
590
507
|
humanBlockingReasons: string[];
|
|
591
508
|
command: "patronage-factory pr:ready";
|
|
592
509
|
/**
|
|
593
|
-
* Machine-safe arg array for the obvious next action (#523): when `ready
|
|
594
|
-
*
|
|
595
|
-
*
|
|
596
|
-
* pr:
|
|
597
|
-
*
|
|
510
|
+
* Machine-safe arg array for the obvious next action (#523): when `ready`
|
|
511
|
+
* but arming did not take effect, a `pr:ready` re-dispatch (idempotent on
|
|
512
|
+
* an unchanged head); otherwise the `gh pr ready` undraft repair or the
|
|
513
|
+
* `pr:verify` re-run that the blocking reasons name (re-verify the head,
|
|
514
|
+
* then re-run pr:ready). Same `argv` shape `factory:delegate --print`
|
|
515
|
+
* emits. Optional and purely additive.
|
|
598
516
|
*/
|
|
599
517
|
followUp?: FollowUpAction;
|
|
600
518
|
/**
|
|
@@ -604,6 +522,12 @@ interface PrReadyProof {
|
|
|
604
522
|
* pushed HEAD, not a re-derivation. See the ledger schema.
|
|
605
523
|
*/
|
|
606
524
|
ledger: ManagedReadinessLedger;
|
|
525
|
+
/**
|
|
526
|
+
* Actionable facts that did not block (#477): a settling merge-freeze
|
|
527
|
+
* generation that armed with a notice, and how each waived demand reads to a
|
|
528
|
+
* human. Absent when there are none.
|
|
529
|
+
*/
|
|
530
|
+
notices?: string[];
|
|
607
531
|
/** Committed profile blob evaluated by readiness. Required for merge. */
|
|
608
532
|
profileBlobSha?: string;
|
|
609
533
|
/** Checkout-relative committed profile path evaluated by readiness. */
|
|
@@ -612,6 +536,13 @@ interface PrReadyProof {
|
|
|
612
536
|
/** Trusted checkout repository used for all GitHub reads and writes. */
|
|
613
537
|
repository?: string;
|
|
614
538
|
status: ReadinessStatus;
|
|
539
|
+
/**
|
|
540
|
+
* Demands that were in force, were NOT met, and were waived by the operator
|
|
541
|
+
* (#354, moved here from the merge-time proof by #477). Each entry carries
|
|
542
|
+
* the demand's refusals verbatim, so a waived demand can never read as a met
|
|
543
|
+
* one; the arming proceeds on the recorded operator act, not on evidence.
|
|
544
|
+
*/
|
|
545
|
+
waivedDemands?: WaivedDemand[];
|
|
615
546
|
}
|
|
616
547
|
//#endregion
|
|
617
548
|
//#region src/pr-readiness/external-evidence.d.ts
|
|
@@ -1296,64 +1227,24 @@ declare const boundaryCheckProofSchema: z.ZodObject<{
|
|
|
1296
1227
|
}>;
|
|
1297
1228
|
}, z.core.$strip>;
|
|
1298
1229
|
type BoundaryCheckProofRecord = z.infer<typeof boundaryCheckProofSchema>;
|
|
1299
|
-
declare const
|
|
1300
|
-
declare const prMergeCheckProofSchema: z.ZodObject<{
|
|
1301
|
-
blockingReasons: z.ZodArray<z.ZodString>;
|
|
1302
|
-
command: z.ZodLiteral<"patronage-factory pr:merge-check">;
|
|
1303
|
-
followUp: z.ZodOptional<z.ZodObject<{
|
|
1304
|
-
argv: z.ZodArray<z.ZodString>;
|
|
1305
|
-
command: z.ZodString;
|
|
1306
|
-
}, z.core.$strict>>;
|
|
1307
|
-
identity: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1308
|
-
headSha: z.ZodString;
|
|
1309
|
-
kind: z.ZodLiteral<"match">;
|
|
1310
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
1311
|
-
kind: z.ZodLiteral<"diverged">;
|
|
1312
|
-
liveHeadSha: z.ZodString;
|
|
1313
|
-
postProofCommits: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1314
|
-
sha: z.ZodString;
|
|
1315
|
-
subject: z.ZodString;
|
|
1316
|
-
}, z.core.$strip>>>;
|
|
1317
|
-
proofHeadSha: z.ZodString;
|
|
1318
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
1319
|
-
kind: z.ZodLiteral<"live-head-invalid">;
|
|
1320
|
-
pr: z.ZodNumber;
|
|
1321
|
-
received: z.ZodString;
|
|
1322
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
1323
|
-
errorDetail: z.ZodOptional<z.ZodString>;
|
|
1324
|
-
kind: z.ZodLiteral<"ready-proof-missing">;
|
|
1325
|
-
readyProofPath: z.ZodString;
|
|
1326
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
1327
|
-
kind: z.ZodLiteral<"ready-proof-pr-mismatch">;
|
|
1328
|
-
proofPr: z.ZodNumber;
|
|
1329
|
-
requestedPr: z.ZodNumber;
|
|
1330
|
-
}, z.core.$strip>, z.ZodObject<{
|
|
1331
|
-
blockingReasons: z.ZodArray<z.ZodString>;
|
|
1332
|
-
kind: z.ZodLiteral<"ready-proof-not-ready">;
|
|
1333
|
-
status: z.ZodString;
|
|
1334
|
-
}, z.core.$strip>], "kind">;
|
|
1335
|
-
liveHeadSha: z.ZodOptional<z.ZodString>;
|
|
1336
|
-
notices: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1337
|
-
pr: z.ZodNumber;
|
|
1338
|
-
schemaVersion: z.ZodLiteral<1>;
|
|
1339
|
-
status: z.ZodEnum<{
|
|
1340
|
-
pass: "pass";
|
|
1341
|
-
fail: "fail";
|
|
1342
|
-
}>;
|
|
1343
|
-
waivedDemands: z.ZodOptional<z.ZodArray<z.ZodType<WaivedDemand, unknown, z.core.$ZodTypeInternals<WaivedDemand, unknown>>>>;
|
|
1344
|
-
worktreeHeldBranch: z.ZodOptional<z.ZodObject<{
|
|
1345
|
-
branch: z.ZodString;
|
|
1346
|
-
worktreePath: z.ZodString;
|
|
1347
|
-
}, z.core.$strip>>;
|
|
1348
|
-
}, z.core.$strip>;
|
|
1349
|
-
declare const PR_READY_SCHEMA_VERSION = 2;
|
|
1230
|
+
declare const PR_READY_SCHEMA_VERSION = 3;
|
|
1350
1231
|
/**
|
|
1351
|
-
* The pr:ready proof versions a reader still accepts. `pr:ready` emits
|
|
1352
|
-
* (#
|
|
1353
|
-
* and HQ must ingest them without degrading, so the wire schema parses
|
|
1232
|
+
* The pr:ready proof versions a reader still accepts. `pr:ready` emits v3 only
|
|
1233
|
+
* (#477) — one current contract — but v1 and v2 events were spooled before the
|
|
1234
|
+
* bumps and HQ must ingest them without degrading, so the wire schema parses
|
|
1235
|
+
* all three.
|
|
1354
1236
|
*/
|
|
1355
|
-
declare const SUPPORTED_PR_READY_SCHEMA_VERSIONS: readonly [1, 2];
|
|
1237
|
+
declare const SUPPORTED_PR_READY_SCHEMA_VERSIONS: readonly [1, 2, 3];
|
|
1356
1238
|
declare const prReadyProofSchema: z.ZodObject<{
|
|
1239
|
+
arming: z.ZodOptional<z.ZodObject<{
|
|
1240
|
+
detail: z.ZodOptional<z.ZodString>;
|
|
1241
|
+
headSha: z.ZodString;
|
|
1242
|
+
outcome: z.ZodEnum<{
|
|
1243
|
+
merged: "merged";
|
|
1244
|
+
armed: "armed";
|
|
1245
|
+
"not-armed": "not-armed";
|
|
1246
|
+
}>;
|
|
1247
|
+
}, z.core.$strip>>;
|
|
1357
1248
|
blockedReasons: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1358
1249
|
code: z.ZodString;
|
|
1359
1250
|
detail: z.ZodString;
|
|
@@ -1382,12 +1273,11 @@ declare const prReadyProofSchema: z.ZodObject<{
|
|
|
1382
1273
|
name: z.ZodString;
|
|
1383
1274
|
reason: z.ZodOptional<z.ZodString>;
|
|
1384
1275
|
scope: z.ZodOptional<z.ZodObject<{
|
|
1385
|
-
classifications: z.
|
|
1276
|
+
classifications: z.ZodArray<z.ZodEnum<{
|
|
1386
1277
|
"docs/process-only": "docs/process-only";
|
|
1387
1278
|
trivial: "trivial";
|
|
1388
1279
|
"non-trivial": "non-trivial";
|
|
1389
|
-
}
|
|
1390
|
-
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1280
|
+
}>>;
|
|
1391
1281
|
}, z.core.$strict>>;
|
|
1392
1282
|
scopeReason: z.ZodString;
|
|
1393
1283
|
status: z.ZodEnum<{
|
|
@@ -1661,6 +1551,7 @@ declare const prReadyProofSchema: z.ZodObject<{
|
|
|
1661
1551
|
verifiedHeadSha: z.ZodOptional<z.ZodString>;
|
|
1662
1552
|
}, z.core.$strip>;
|
|
1663
1553
|
}, z.core.$strip>;
|
|
1554
|
+
notices: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1664
1555
|
profileBlobSha: z.ZodOptional<z.ZodString>;
|
|
1665
1556
|
profilePath: z.ZodOptional<z.ZodString>;
|
|
1666
1557
|
repairs: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
@@ -1673,12 +1564,13 @@ declare const prReadyProofSchema: z.ZodObject<{
|
|
|
1673
1564
|
command: z.ZodString;
|
|
1674
1565
|
}, z.core.$strip>>>;
|
|
1675
1566
|
repository: z.ZodOptional<z.ZodString>;
|
|
1676
|
-
schemaVersion: z.ZodNumber & z.ZodType<1 | 2, number, z.core.$ZodTypeInternals<1 | 2, number>>;
|
|
1567
|
+
schemaVersion: z.ZodNumber & z.ZodType<1 | 2 | 3, number, z.core.$ZodTypeInternals<1 | 2 | 3, number>>;
|
|
1677
1568
|
status: z.ZodEnum<{
|
|
1678
1569
|
ready: "ready";
|
|
1679
1570
|
blocked: "blocked";
|
|
1680
1571
|
"slice-ready/not-final": "slice-ready/not-final";
|
|
1681
1572
|
}>;
|
|
1573
|
+
waivedDemands: z.ZodOptional<z.ZodArray<z.ZodType<WaivedDemand, unknown, z.core.$ZodTypeInternals<WaivedDemand, unknown>>>>;
|
|
1682
1574
|
}, z.core.$strip>;
|
|
1683
1575
|
//#endregion
|
|
1684
|
-
export { BLOCKED_REASONS_MAX, BLOCKED_REASON_DETAIL_MAX, BOUNDARY_CHECK_SCHEMA_VERSION, BOUNDARY_REVIEW_PROOF_KIND, type BlockedReason, BoundaryCheckProofRecord, type BoundaryReviewProof, type CloseoutArtifact, EVIDENCE_ENVELOPE_SCHEMA_VERSION, type EvidenceEnvelope,
|
|
1576
|
+
export { BLOCKED_REASONS_MAX, BLOCKED_REASON_DETAIL_MAX, BOUNDARY_CHECK_SCHEMA_VERSION, BOUNDARY_REVIEW_PROOF_KIND, type BlockedReason, BoundaryCheckProofRecord, type BoundaryReviewProof, type CloseoutArtifact, EVIDENCE_ENVELOPE_SCHEMA_VERSION, type EvidenceEnvelope, PR_READY_SCHEMA_VERSION, PR_REVIEW_SCHEMA_VERSION, type ParsedRetroEnvelope, type PrReadyProof, type PrReviewProof, type PrVerifyProof, RETRO_ENVELOPE_SCHEMA_VERSION, RETRO_ENVELOPE_VALIDATORS, RETRO_ENVELOPE_WIRE_BOUNDS, type RetroEnvelope, SUPPORTED_PR_READY_SCHEMA_VERSIONS, SUPPORTED_PR_VERIFY_SCHEMA_VERSIONS, SUPPORTED_RETRO_ENVELOPE_SCHEMA_VERSIONS, type WaivedDemand, blockedReasonSchema, blockedReasonsSchema, boundaryCheckProofSchema, boundaryReviewProofSchema, closeoutArtifactSchema, evidenceEnvelopeSchema, prReadyProofSchema, prReviewProofSchema, prVerifyProofSchema, retroEnvelopeV1Schema, retroEpicReference, waivedDemandSchema };
|
package/dist/schemas.js
CHANGED
|
@@ -10,6 +10,13 @@ Object.fromEntries(EVIDENCE_REVIEW_RUNGS$1.map((rung, index) => [rung, index]));
|
|
|
10
10
|
//#region src/demand-keys.ts
|
|
11
11
|
/** The demands that exist at most once per candidate. */
|
|
12
12
|
const DEMAND_KEYS = {
|
|
13
|
+
/**
|
|
14
|
+
* The boundary wave that authorizes this candidate's merge schedule (#477).
|
|
15
|
+
* In force exactly when GitHub already has auto-merge enabled: a live
|
|
16
|
+
* schedule with no wave demand resolved is an unauthorized merge waiting to
|
|
17
|
+
* happen.
|
|
18
|
+
*/
|
|
19
|
+
boundaryWave: "boundary-wave",
|
|
13
20
|
/** The PR is still a draft. */
|
|
14
21
|
draft: "draft",
|
|
15
22
|
/** The candidate is not the intended final human review point. */
|
|
@@ -24,6 +31,12 @@ const DEMAND_KEYS = {
|
|
|
24
31
|
mergeFreeze: "merge-freeze",
|
|
25
32
|
/** GitHub's mergeability / merge-state rollup. */
|
|
26
33
|
mergeState: "merge-state",
|
|
34
|
+
/**
|
|
35
|
+
* A native GitHub approval, demanded when the boundary wave in force does
|
|
36
|
+
* not authorize machine merge (#477). "Green = authorized to merge" is then
|
|
37
|
+
* a property of the branded required check itself.
|
|
38
|
+
*/
|
|
39
|
+
nativeApproval: "native-approval",
|
|
27
40
|
/** The PR body's required rendered sections. */
|
|
28
41
|
prBodySections: "pr-body-sections",
|
|
29
42
|
/** A current, head-bound, passing typed `pr:verify` proof. */
|
|
@@ -54,7 +67,7 @@ const percentEncode = (character) => {
|
|
|
54
67
|
* demand nobody waived, and make HQ count two causes as one.
|
|
55
68
|
*
|
|
56
69
|
* Deterministic in both directions of use: the key a `pr:ready` proof records
|
|
57
|
-
* is the key a `pr:
|
|
70
|
+
* is the key a `pr:ready` waiver matches.
|
|
58
71
|
*/
|
|
59
72
|
const demandQualifier = (value) => value.replaceAll(/[^A-Za-z0-9._/-]/gu, percentEncode);
|
|
60
73
|
const FIXED_DEMAND_KEYS = Object.values(DEMAND_KEYS);
|
|
@@ -132,7 +145,7 @@ const demandKeySchema = z.string().refine((value) => {
|
|
|
132
145
|
* reason codes must come from. A waiver store is durable operator evidence
|
|
133
146
|
* written before today's vocabulary existed, so tightening its validation
|
|
134
147
|
* would make an existing record parse as no waiver and let the next write drop
|
|
135
|
-
* it. A waiver naming a key nobody resolves is already inert — `pr:
|
|
148
|
+
* it. A waiver naming a key nobody resolves is already inert — `pr:ready`
|
|
136
149
|
* reports it as an unapplied waiver — so nothing is admitted by accepting it.
|
|
137
150
|
*/
|
|
138
151
|
const waiverDemandKeySchema = z.string().regex(/^[a-z][a-z0-9-]*(?::[A-Za-z0-9._%/-]+)?$/u, "A demand key is a lowercase family, optionally qualified by its resolved value (e.g. review-rung:human).");
|
|
@@ -979,67 +992,7 @@ const boundaryCheckProofSchema = z.object({
|
|
|
979
992
|
}).optional(),
|
|
980
993
|
status: z.enum(["ready", "blocked"])
|
|
981
994
|
});
|
|
982
|
-
const
|
|
983
|
-
z.object({
|
|
984
|
-
headSha: z.string().regex(/^[0-9a-f]{40}$/u),
|
|
985
|
-
kind: z.literal("match")
|
|
986
|
-
}),
|
|
987
|
-
z.object({
|
|
988
|
-
kind: z.literal("diverged"),
|
|
989
|
-
liveHeadSha: z.string().regex(/^[0-9a-f]{40}$/u),
|
|
990
|
-
postProofCommits: z.array(z.object({
|
|
991
|
-
sha: z.string().min(1),
|
|
992
|
-
subject: z.string()
|
|
993
|
-
})).optional(),
|
|
994
|
-
proofHeadSha: z.string().regex(/^[0-9a-f]{40}$/u)
|
|
995
|
-
}),
|
|
996
|
-
z.object({
|
|
997
|
-
kind: z.literal("live-head-invalid"),
|
|
998
|
-
pr: z.number().int().positive(),
|
|
999
|
-
received: z.string()
|
|
1000
|
-
}),
|
|
1001
|
-
z.object({
|
|
1002
|
-
errorDetail: z.string().optional(),
|
|
1003
|
-
kind: z.literal("ready-proof-missing"),
|
|
1004
|
-
readyProofPath: z.string().min(1)
|
|
1005
|
-
}),
|
|
1006
|
-
z.object({
|
|
1007
|
-
kind: z.literal("ready-proof-pr-mismatch"),
|
|
1008
|
-
proofPr: z.number().int().positive(),
|
|
1009
|
-
requestedPr: z.number().int().positive()
|
|
1010
|
-
}),
|
|
1011
|
-
z.object({
|
|
1012
|
-
blockingReasons: z.array(z.string()),
|
|
1013
|
-
kind: z.literal("ready-proof-not-ready"),
|
|
1014
|
-
status: z.string().min(1)
|
|
1015
|
-
})
|
|
1016
|
-
]);
|
|
1017
|
-
const PR_MERGE_CHECK_SCHEMA_VERSION = 1;
|
|
1018
|
-
const prMergeCheckProofSchema = z.object({
|
|
1019
|
-
blockingReasons: z.array(z.string()),
|
|
1020
|
-
command: z.literal("patronage-factory pr:merge-check"),
|
|
1021
|
-
followUp: followUpActionSchema.optional(),
|
|
1022
|
-
identity: mergeGuardIdentitySchema,
|
|
1023
|
-
liveHeadSha: z.string().regex(/^[0-9a-f]{40}$/u).optional(),
|
|
1024
|
-
notices: z.array(z.string()).optional(),
|
|
1025
|
-
pr: z.number().int().positive(),
|
|
1026
|
-
schemaVersion: z.literal(1),
|
|
1027
|
-
status: z.enum(["pass", "fail"]),
|
|
1028
|
-
waivedDemands: z.array(waivedDemandSchema).optional(),
|
|
1029
|
-
worktreeHeldBranch: z.object({
|
|
1030
|
-
branch: z.string().min(1),
|
|
1031
|
-
worktreePath: z.string().min(1)
|
|
1032
|
-
}).optional()
|
|
1033
|
-
});
|
|
1034
|
-
const requiredCheckScopeSchema = z.object({
|
|
1035
|
-
classifications: z.array(z.enum(DIFF_CLASSIFICATIONS)).min(1).optional(),
|
|
1036
|
-
labels: z.array(z.string().min(1)).min(1).optional()
|
|
1037
|
-
}).strict().superRefine((scope, context) => {
|
|
1038
|
-
if (scope.labels === void 0 && scope.classifications === void 0) context.addIssue({
|
|
1039
|
-
code: "custom",
|
|
1040
|
-
message: "requiredChecks scope must declare at least one condition (labels and/or classifications)."
|
|
1041
|
-
});
|
|
1042
|
-
});
|
|
995
|
+
const requiredCheckScopeSchema = z.object({ classifications: z.array(z.enum(DIFF_CLASSIFICATIONS)).min(1) }).strict();
|
|
1043
996
|
const readinessRepairSchema = z.object({
|
|
1044
997
|
action: z.string().min(1),
|
|
1045
998
|
code: z.enum([
|
|
@@ -1214,21 +1167,36 @@ const managedReadinessLedgerSchema = z.object({
|
|
|
1214
1167
|
verifiedHeadSha: z.string().optional()
|
|
1215
1168
|
})
|
|
1216
1169
|
});
|
|
1217
|
-
const PR_READY_SCHEMA_VERSION =
|
|
1170
|
+
const PR_READY_SCHEMA_VERSION = 3;
|
|
1218
1171
|
/**
|
|
1219
|
-
* The pr:ready proof versions a reader still accepts. `pr:ready` emits
|
|
1220
|
-
* (#
|
|
1221
|
-
* and HQ must ingest them without degrading, so the wire schema parses
|
|
1172
|
+
* The pr:ready proof versions a reader still accepts. `pr:ready` emits v3 only
|
|
1173
|
+
* (#477) — one current contract — but v1 and v2 events were spooled before the
|
|
1174
|
+
* bumps and HQ must ingest them without degrading, so the wire schema parses
|
|
1175
|
+
* all three.
|
|
1222
1176
|
*/
|
|
1223
|
-
const SUPPORTED_PR_READY_SCHEMA_VERSIONS = [
|
|
1177
|
+
const SUPPORTED_PR_READY_SCHEMA_VERSIONS = [
|
|
1178
|
+
1,
|
|
1179
|
+
2,
|
|
1180
|
+
3
|
|
1181
|
+
];
|
|
1224
1182
|
const prReadySchemaVersionSchema = z.number().refine((value) => SUPPORTED_PR_READY_SCHEMA_VERSIONS.includes(value), { message: `schemaVersion must be one of: ${SUPPORTED_PR_READY_SCHEMA_VERSIONS.join(", ")}` });
|
|
1225
1183
|
const prReadyProofSchema = z.object({
|
|
1184
|
+
arming: z.object({
|
|
1185
|
+
detail: z.string().min(1).optional(),
|
|
1186
|
+
headSha: z.string().regex(/^[0-9a-f]{40}$/u),
|
|
1187
|
+
outcome: z.enum([
|
|
1188
|
+
"armed",
|
|
1189
|
+
"merged",
|
|
1190
|
+
"not-armed"
|
|
1191
|
+
])
|
|
1192
|
+
}).optional(),
|
|
1226
1193
|
blockedReasons: blockedReasonsSchema.optional(),
|
|
1227
1194
|
blockingReasons: z.array(z.string()),
|
|
1228
1195
|
command: z.literal("patronage-factory pr:ready"),
|
|
1229
1196
|
followUp: followUpActionSchema.optional(),
|
|
1230
1197
|
humanBlockingReasons: z.array(z.string()).default([]),
|
|
1231
1198
|
ledger: managedReadinessLedgerSchema,
|
|
1199
|
+
notices: z.array(z.string().min(1)).optional(),
|
|
1232
1200
|
profileBlobSha: z.string().regex(/^[0-9a-f]{40}$/u).optional(),
|
|
1233
1201
|
profilePath: z.string().min(1).optional(),
|
|
1234
1202
|
repairs: z.array(readinessRepairSchema).default([]),
|
|
@@ -1238,7 +1206,8 @@ const prReadyProofSchema = z.object({
|
|
|
1238
1206
|
"ready",
|
|
1239
1207
|
"blocked",
|
|
1240
1208
|
"slice-ready/not-final"
|
|
1241
|
-
])
|
|
1209
|
+
]),
|
|
1210
|
+
waivedDemands: z.array(waivedDemandSchema).optional()
|
|
1242
1211
|
}).superRefine((proof, context) => {
|
|
1243
1212
|
if (proof.schemaVersion < 2) {
|
|
1244
1213
|
if (proof.blockedReasons !== void 0) context.addIssue({
|
|
@@ -1254,4 +1223,4 @@ const prReadyProofSchema = z.object({
|
|
|
1254
1223
|
})) context.addIssue(issue);
|
|
1255
1224
|
});
|
|
1256
1225
|
//#endregion
|
|
1257
|
-
export { BLOCKED_REASONS_MAX, BLOCKED_REASON_DETAIL_MAX, BOUNDARY_CHECK_SCHEMA_VERSION, BOUNDARY_REVIEW_PROOF_KIND, EVIDENCE_ENVELOPE_SCHEMA_VERSION,
|
|
1226
|
+
export { BLOCKED_REASONS_MAX, BLOCKED_REASON_DETAIL_MAX, BOUNDARY_CHECK_SCHEMA_VERSION, BOUNDARY_REVIEW_PROOF_KIND, EVIDENCE_ENVELOPE_SCHEMA_VERSION, PR_READY_SCHEMA_VERSION, PR_REVIEW_SCHEMA_VERSION, RETRO_ENVELOPE_SCHEMA_VERSION, RETRO_ENVELOPE_VALIDATORS, RETRO_ENVELOPE_WIRE_BOUNDS, SUPPORTED_PR_READY_SCHEMA_VERSIONS, SUPPORTED_PR_VERIFY_SCHEMA_VERSIONS, SUPPORTED_RETRO_ENVELOPE_SCHEMA_VERSIONS, blockedReasonSchema, blockedReasonsSchema, boundaryCheckProofSchema, boundaryReviewProofSchema, closeoutArtifactSchema, evidenceEnvelopeSchema, prReadyProofSchema, prReviewProofSchema, prVerifyProofSchema, retroEnvelopeV1Schema, retroEpicReference, waivedDemandSchema };
|