@patronage/software-factory 1.0.0-alpha.36 → 1.0.0-alpha.37
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/README.md +1 -1
- package/dist/index.d.ts +198 -19
- package/dist/index.js +3844 -3267
- package/dist/oxlint-jev/index.d.ts +3991 -1
- package/dist/schemas.d.ts +7 -5
- package/dist/schemas.js +13 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
The factory admits a pull request from evidence bound to its candidate. It validates policy and proof; it does not schedule workers, choose models, or run reviews. Those are jobs for the harness or operator.
|
|
6
6
|
|
|
7
|
-
Admission is fail closed. A clean-session review and required verification produce typed proof, then readiness decides whether the candidate may proceed. Evidence stays current when the candidate patch is unchanged; the push-triggered Verify workflow covers integration risk on every factory merge target — `main` and the `epic/**` integration branches. When a target goes red, the factory refuses new readiness decisions and authorized arming against that target; candidates armed before the target went red can still land. Epic policy, including review minimums and auto-merge
|
|
7
|
+
Admission is fail closed. A clean-session review and required verification produce typed proof, then readiness decides whether the candidate may proceed. Evidence stays current when the candidate patch is unchanged; the push-triggered Verify workflow covers integration risk on every factory merge target — `main` and the `epic/**` integration branches. When a target goes red, the factory refuses new readiness decisions and authorized arming against that target; candidates armed before the target went red can still land. `pr:ready` arms GitHub native auto-merge for every admitted pull request. It does not arm when the repository does not allow auto-merge, when the pull request carries the `factory:hold` label, or when a boundary wave keeps the candidate attended. Epic policy, including review minimums and the auto-merge decision for its members, lives in the boundary manifest. HQ observes this work; it never blocks a gate.
|
|
8
8
|
|
|
9
9
|
## Develop the package
|
|
10
10
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import { z } from "zod";
|
|
3
2
|
import { existsSync, readFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { z } from "zod";
|
|
4
4
|
import { PreviewProofRegistration } from "@patronage/factory-ci";
|
|
5
5
|
import { JsonValue, Questions, SystemOneRequest, choice, noul, score } from "@typesafe-ai/sdk";
|
|
6
6
|
|
|
@@ -948,10 +948,18 @@ declare const blockedReasonSchema: z.ZodObject<{
|
|
|
948
948
|
type BlockedReason = z.infer<typeof blockedReasonSchema>;
|
|
949
949
|
//#endregion
|
|
950
950
|
//#region src/arm-auto-merge.d.ts
|
|
951
|
+
/**
|
|
952
|
+
* How GitHub merges the candidate. `pr:ready` chooses `merge` for a
|
|
953
|
+
* recognized faithful catch-up merge (ADR 0028), because a squash drops the
|
|
954
|
+
* second parent and the target loses the merged base as an ancestor (#829).
|
|
955
|
+
* Every other candidate is squashed.
|
|
956
|
+
*/
|
|
957
|
+
type AutoMergeMethod = "merge" | "squash";
|
|
951
958
|
interface ArmAutoMergeInput {
|
|
952
959
|
cwd: string;
|
|
953
960
|
/** The validated PR head this arming is a compare-and-set against. */
|
|
954
961
|
headSha: string;
|
|
962
|
+
mergeMethod: AutoMergeMethod;
|
|
955
963
|
owner: string;
|
|
956
964
|
pr: number;
|
|
957
965
|
repo: string;
|
|
@@ -1660,8 +1668,8 @@ declare const mergeFreezeStateSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1660
1668
|
generationId: z.ZodNumber;
|
|
1661
1669
|
headSha: z.ZodString;
|
|
1662
1670
|
outcome: z.ZodEnum<{
|
|
1663
|
-
stale: "stale";
|
|
1664
1671
|
active: "active";
|
|
1672
|
+
stale: "stale";
|
|
1665
1673
|
}>;
|
|
1666
1674
|
reason: z.ZodString;
|
|
1667
1675
|
recordedAt: z.ZodISODateTime;
|
|
@@ -1950,9 +1958,9 @@ declare const managedReadinessLedgerSchema: z.ZodObject<{
|
|
|
1950
1958
|
reviewedPatchId: z.ZodOptional<z.ZodString>;
|
|
1951
1959
|
status: z.ZodEnum<{
|
|
1952
1960
|
"not-required": "not-required";
|
|
1961
|
+
stale: "stale";
|
|
1953
1962
|
blocked: "blocked";
|
|
1954
1963
|
current: "current";
|
|
1955
|
-
stale: "stale";
|
|
1956
1964
|
missing: "missing";
|
|
1957
1965
|
}>;
|
|
1958
1966
|
}, z.core.$strip>;
|
|
@@ -1962,9 +1970,9 @@ declare const managedReadinessLedgerSchema: z.ZodObject<{
|
|
|
1962
1970
|
reviewedPatchId: z.ZodOptional<z.ZodString>;
|
|
1963
1971
|
status: z.ZodEnum<{
|
|
1964
1972
|
"not-required": "not-required";
|
|
1973
|
+
stale: "stale";
|
|
1965
1974
|
blocked: "blocked";
|
|
1966
1975
|
current: "current";
|
|
1967
|
-
stale: "stale";
|
|
1968
1976
|
missing: "missing";
|
|
1969
1977
|
}>;
|
|
1970
1978
|
}, z.core.$strip>>;
|
|
@@ -2611,11 +2619,13 @@ interface PrReadyProof {
|
|
|
2611
2619
|
schemaVersion: 3;
|
|
2612
2620
|
/**
|
|
2613
2621
|
* What GitHub actually did when this run armed native auto-merge (#477).
|
|
2614
|
-
* Present exactly when a ready
|
|
2615
|
-
*
|
|
2616
|
-
*
|
|
2617
|
-
*
|
|
2618
|
-
*
|
|
2622
|
+
* Present exactly when a ready run called the arming module (#1299): not
|
|
2623
|
+
* for an `autoMerge: false` wave, and not when a notice names why the run
|
|
2624
|
+
* did not arm. Read back from the PR rather than inferred from the
|
|
2625
|
+
* invocation, because `gh pr merge --auto` arms, merges, or does nothing
|
|
2626
|
+
* with the same exit code and the same empty output. `not-armed` means the
|
|
2627
|
+
* candidate is admitted but nothing will merge it, and `followUp` carries
|
|
2628
|
+
* the re-dispatch.
|
|
2619
2629
|
*/
|
|
2620
2630
|
arming?: {
|
|
2621
2631
|
detail?: string;
|
|
@@ -2687,13 +2697,61 @@ interface PrReadyProof {
|
|
|
2687
2697
|
*/
|
|
2688
2698
|
waivedDemands?: WaivedDemand[];
|
|
2689
2699
|
}
|
|
2700
|
+
/** An issue's sub-issue parent, as the membership rule reads it (#1299). */
|
|
2701
|
+
interface IssueParent {
|
|
2702
|
+
labels: string[];
|
|
2703
|
+
number: number;
|
|
2704
|
+
state: string;
|
|
2705
|
+
}
|
|
2706
|
+
/** What `pr:ready` reads about one pull request before it arms (#1299). */
|
|
2707
|
+
interface PullRequestArmingFacts {
|
|
2708
|
+
/** GitHub's per-repository "Allow auto-merge" setting. */
|
|
2709
|
+
autoMergeAllowed: boolean;
|
|
2710
|
+
/**
|
|
2711
|
+
* GitHub's closing references for the pull request to issues in its own
|
|
2712
|
+
* repository, with their parents.
|
|
2713
|
+
*/
|
|
2714
|
+
closingIssues: {
|
|
2715
|
+
number: number;
|
|
2716
|
+
parent: IssueParent | null;
|
|
2717
|
+
}[];
|
|
2718
|
+
/**
|
|
2719
|
+
* GitHub has more closing references than the one page `pr:ready` reads,
|
|
2720
|
+
* so `closingIssues` is not the whole set.
|
|
2721
|
+
*/
|
|
2722
|
+
closingIssuesIncomplete: boolean;
|
|
2723
|
+
labels: string[];
|
|
2724
|
+
}
|
|
2725
|
+
/**
|
|
2726
|
+
* The GitHub reads behind the reasons not to arm an admitted candidate
|
|
2727
|
+
* (#1299). A read throws when GitHub cannot answer; `pr:ready` then does not
|
|
2728
|
+
* arm, and its notice says which read failed.
|
|
2729
|
+
*/
|
|
2730
|
+
interface ArmingPolicyReads {
|
|
2731
|
+
/** One issue's sub-issue parent, or `null` when it has none. */
|
|
2732
|
+
readIssueParent: (input: {
|
|
2733
|
+
issue: number;
|
|
2734
|
+
owner: string;
|
|
2735
|
+
repo: string;
|
|
2736
|
+
}) => IssueParent | null;
|
|
2737
|
+
readPullRequest: (input: {
|
|
2738
|
+
owner: string;
|
|
2739
|
+
pr: number;
|
|
2740
|
+
repo: string;
|
|
2741
|
+
}) => PullRequestArmingFacts;
|
|
2742
|
+
}
|
|
2690
2743
|
interface PrReadyDependencies {
|
|
2691
2744
|
/**
|
|
2692
|
-
* Arms GitHub native auto-merge
|
|
2693
|
-
*
|
|
2694
|
-
*
|
|
2745
|
+
* Arms GitHub native auto-merge for an admitted candidate (#477, #1299).
|
|
2746
|
+
* Defaults to the real `gh pr merge --auto` call plus the read-back that
|
|
2747
|
+
* says what actually happened.
|
|
2695
2748
|
*/
|
|
2696
2749
|
armAutoMerge?: (input: ArmAutoMergeInput) => ArmAutoMergeOutcome;
|
|
2750
|
+
/**
|
|
2751
|
+
* The GitHub reads behind the reasons not to arm (#1299). Defaults to the
|
|
2752
|
+
* real GraphQL reads.
|
|
2753
|
+
*/
|
|
2754
|
+
armingPolicy?: ArmingPolicyReads;
|
|
2697
2755
|
/**
|
|
2698
2756
|
* Reads the authoritative base review policy (#922): the profile committed at
|
|
2699
2757
|
* the live tip of the PR's own base ref. Defaults to the real GitHub reads,
|
|
@@ -2935,9 +2993,9 @@ declare const loadEvidenceEnvelopes: (cwd: string) => LoadedEvidenceEnvelope[];
|
|
|
2935
2993
|
declare const REVIEW_STATUS_VALUES: readonly ["not-required", "current", "stale", "missing", "blocked"];
|
|
2936
2994
|
declare const reviewStatusSchema: z.ZodEnum<{
|
|
2937
2995
|
"not-required": "not-required";
|
|
2996
|
+
stale: "stale";
|
|
2938
2997
|
blocked: "blocked";
|
|
2939
2998
|
current: "current";
|
|
2940
|
-
stale: "stale";
|
|
2941
2999
|
missing: "missing";
|
|
2942
3000
|
}>;
|
|
2943
3001
|
type ReviewStatus = z.infer<typeof reviewStatusSchema>;
|
|
@@ -3445,11 +3503,12 @@ interface PrPublishHandoff {
|
|
|
3445
3503
|
routeOwnedRepairs: ReadinessRepair[];
|
|
3446
3504
|
/**
|
|
3447
3505
|
* Whether the merge is actually on GitHub's schedule (#477, #515 review).
|
|
3448
|
-
* An admitted candidate is not a handed-off one: `pr:ready`
|
|
3449
|
-
*
|
|
3506
|
+
* An admitted candidate is not a handed-off one: `pr:ready` does not arm
|
|
3507
|
+
* when the repository does not allow auto-merge, the pull request carries
|
|
3508
|
+
* `factory:hold`, a boundary wave keeps it attended, or it is an epic member
|
|
3509
|
+
* run without `--epic` (#1299), and the arming can fail to take effect. A
|
|
3450
3510
|
* readiness status of `ready` says the candidate passed, never that anything
|
|
3451
|
-
* will merge it
|
|
3452
|
-
* one — so publish reads this before claiming nothing is owed.
|
|
3511
|
+
* will merge it, so publish reads this before claiming nothing is owed.
|
|
3453
3512
|
*/
|
|
3454
3513
|
scheduled: boolean;
|
|
3455
3514
|
status: PrReadyProof["status"];
|
|
@@ -4824,11 +4883,125 @@ interface EvaluationInput {
|
|
|
4824
4883
|
waivers?: DemandWaiver[];
|
|
4825
4884
|
}
|
|
4826
4885
|
declare const evaluateReadiness: (input: EvaluationInput) => {
|
|
4886
|
+
humanBlockingReasons: string[];
|
|
4887
|
+
ledger: {
|
|
4888
|
+
baseSha: string;
|
|
4889
|
+
blockingReasons: string[];
|
|
4890
|
+
classification: "docs/process-only" | "trivial" | "non-trivial";
|
|
4891
|
+
github: {
|
|
4892
|
+
draft: boolean;
|
|
4893
|
+
mergeStateStatus: string;
|
|
4894
|
+
mergeable: string;
|
|
4895
|
+
requiredChecks: "unknown" | "pending" | "passed" | "failed" | "none";
|
|
4896
|
+
unresolvedReviewThreads: number;
|
|
4897
|
+
reviewDecision?: string | null | undefined;
|
|
4898
|
+
};
|
|
4899
|
+
headSha: string;
|
|
4900
|
+
patchId: string;
|
|
4901
|
+
pr: number;
|
|
4902
|
+
repairs: {
|
|
4903
|
+
action: string;
|
|
4904
|
+
code: "undraft-pr" | "await-post-undraft-checks";
|
|
4905
|
+
command: string;
|
|
4906
|
+
}[];
|
|
4907
|
+
reviews: {
|
|
4908
|
+
correctness: {
|
|
4909
|
+
required: boolean;
|
|
4910
|
+
status: "not-required" | "stale" | "blocked" | "current" | "missing";
|
|
4911
|
+
reviewedHeadSha?: string | undefined;
|
|
4912
|
+
reviewedPatchId?: string | undefined;
|
|
4913
|
+
};
|
|
4914
|
+
security?: {
|
|
4915
|
+
required: boolean;
|
|
4916
|
+
status: "not-required" | "stale" | "blocked" | "current" | "missing";
|
|
4917
|
+
reviewedHeadSha?: string | undefined;
|
|
4918
|
+
reviewedPatchId?: string | undefined;
|
|
4919
|
+
} | undefined;
|
|
4920
|
+
};
|
|
4921
|
+
schemaVersion: 2;
|
|
4922
|
+
verification: {
|
|
4923
|
+
command: "patronage-factory pr:verify";
|
|
4924
|
+
prVerify: "missing";
|
|
4925
|
+
} | {
|
|
4926
|
+
command: "patronage-factory pr:verify";
|
|
4927
|
+
prVerify: "stale";
|
|
4928
|
+
verifiedHeadSha: string;
|
|
4929
|
+
} | {
|
|
4930
|
+
command: "patronage-factory pr:verify";
|
|
4931
|
+
prVerify: "passed-via-head";
|
|
4932
|
+
verifiedHeadSha: string;
|
|
4933
|
+
} | {
|
|
4934
|
+
command: "patronage-factory pr:verify";
|
|
4935
|
+
docsOnlyVerifiedHeadSha: string;
|
|
4936
|
+
prVerify: "docs-only-delta";
|
|
4937
|
+
verifiedHeadSha?: string | undefined;
|
|
4938
|
+
} | {
|
|
4939
|
+
command: "patronage-factory pr:verify";
|
|
4940
|
+
prVerify: "trivial-delta";
|
|
4941
|
+
trivialVerifiedHeadSha: string;
|
|
4942
|
+
verifiedHeadSha?: string | undefined;
|
|
4943
|
+
};
|
|
4944
|
+
externalChecks?: {
|
|
4945
|
+
checkType: "review" | "verify";
|
|
4946
|
+
name: string;
|
|
4947
|
+
scopeReason: string;
|
|
4948
|
+
status: "satisfied" | "unmet" | "out-of-scope";
|
|
4949
|
+
reason?: string | undefined;
|
|
4950
|
+
scope?: {
|
|
4951
|
+
classifications: ("docs/process-only" | "trivial" | "non-trivial")[];
|
|
4952
|
+
} | undefined;
|
|
4953
|
+
}[] | undefined;
|
|
4954
|
+
mergeBaseSha?: string | undefined;
|
|
4955
|
+
reviewCycleState?: {
|
|
4956
|
+
autoBlockingFindings: number;
|
|
4957
|
+
countsBySeverity: {
|
|
4958
|
+
critical: number;
|
|
4959
|
+
high: number;
|
|
4960
|
+
low: number;
|
|
4961
|
+
medium: number;
|
|
4962
|
+
unknown: number;
|
|
4963
|
+
};
|
|
4964
|
+
nonBlockingFindings: number;
|
|
4965
|
+
openFindings: number;
|
|
4966
|
+
windowExhausted: boolean;
|
|
4967
|
+
highestBlockingSeverity?: "unknown" | "critical" | "high" | "low" | "medium" | undefined;
|
|
4968
|
+
highestOpenSeverity?: "unknown" | "critical" | "high" | "low" | "medium" | undefined;
|
|
4969
|
+
maxReviewCycles?: number | undefined;
|
|
4970
|
+
reviewCycle?: number | undefined;
|
|
4971
|
+
staleRepeatFindings?: number | undefined;
|
|
4972
|
+
} | undefined;
|
|
4973
|
+
reviewLadder?: {
|
|
4974
|
+
cycleCounts: {
|
|
4975
|
+
gate: number;
|
|
4976
|
+
interior: number;
|
|
4977
|
+
};
|
|
4978
|
+
nextAction: "run-interior-cycle" | "advance-to-gate" | "run-gate-cycle" | "accept-nonblocking-findings" | "escalate-to-triage" | "ready-for-human";
|
|
4979
|
+
stage: "interior" | "gate" | "interior-complete";
|
|
4980
|
+
forcedTransition?: "gate-cap-exhausted" | "interior-cap-reached" | undefined;
|
|
4981
|
+
} | undefined;
|
|
4982
|
+
reviewRuns?: PrReviewResult[] | undefined;
|
|
4983
|
+
reviewTerminalState?: "blocked" | "accepted-with-findings" | "clean" | undefined;
|
|
4984
|
+
};
|
|
4985
|
+
/**
|
|
4986
|
+
* Facts a reader needs that are not refusals (#477): the settle-window
|
|
4987
|
+
* arming notice, and every waived demand rendered so it can never read as
|
|
4988
|
+
* a met one.
|
|
4989
|
+
*/
|
|
4990
|
+
notices: string[];
|
|
4991
|
+
repairs: {
|
|
4992
|
+
action: string;
|
|
4993
|
+
code: "undraft-pr" | "await-post-undraft-checks";
|
|
4994
|
+
command: string;
|
|
4995
|
+
}[];
|
|
4996
|
+
status: ReadinessStatus; /** Demands that were in force, were NOT met, and the operator waived. */
|
|
4997
|
+
waivedDemands: WaivedDemand[];
|
|
4998
|
+
catchUpRecognition: CatchUpRecognition;
|
|
4827
4999
|
blockedReasons: {
|
|
4828
5000
|
code: string;
|
|
4829
5001
|
detail: string;
|
|
4830
5002
|
}[];
|
|
4831
5003
|
blockingReasons: string[];
|
|
5004
|
+
} | {
|
|
4832
5005
|
humanBlockingReasons: string[];
|
|
4833
5006
|
ledger: {
|
|
4834
5007
|
baseSha: string;
|
|
@@ -4853,13 +5026,13 @@ declare const evaluateReadiness: (input: EvaluationInput) => {
|
|
|
4853
5026
|
reviews: {
|
|
4854
5027
|
correctness: {
|
|
4855
5028
|
required: boolean;
|
|
4856
|
-
status: "not-required" | "
|
|
5029
|
+
status: "not-required" | "stale" | "blocked" | "current" | "missing";
|
|
4857
5030
|
reviewedHeadSha?: string | undefined;
|
|
4858
5031
|
reviewedPatchId?: string | undefined;
|
|
4859
5032
|
};
|
|
4860
5033
|
security?: {
|
|
4861
5034
|
required: boolean;
|
|
4862
|
-
status: "not-required" | "
|
|
5035
|
+
status: "not-required" | "stale" | "blocked" | "current" | "missing";
|
|
4863
5036
|
reviewedHeadSha?: string | undefined;
|
|
4864
5037
|
reviewedPatchId?: string | undefined;
|
|
4865
5038
|
} | undefined;
|
|
@@ -4941,6 +5114,12 @@ declare const evaluateReadiness: (input: EvaluationInput) => {
|
|
|
4941
5114
|
}[];
|
|
4942
5115
|
status: ReadinessStatus; /** Demands that were in force, were NOT met, and the operator waived. */
|
|
4943
5116
|
waivedDemands: WaivedDemand[];
|
|
5117
|
+
catchUpRecognition?: undefined;
|
|
5118
|
+
blockedReasons: {
|
|
5119
|
+
code: string;
|
|
5120
|
+
detail: string;
|
|
5121
|
+
}[];
|
|
5122
|
+
blockingReasons: string[];
|
|
4944
5123
|
};
|
|
4945
5124
|
//#endregion
|
|
4946
5125
|
//#region src/evidence-emit.d.ts
|