@patronage/software-factory 1.0.0-alpha.21 → 1.0.0-alpha.22
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 +14 -6
- package/dist/index.js +13 -9
- package/package.json +3 -8
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ Generated production workflows may call `psf production:impact --before <sha> --
|
|
|
66
66
|
|
|
67
67
|
Generated pull-request workflows may call `psf candidate:impact --base <sha> --head <sha> --github-output <path>` to route Candidate verification surfaces. The command evaluates the same profile impact declarations and pnpm dependency graph from the exact base/head identity, diffed from their merge base; it is the candidate-named sibling of `production:impact` and replaces repository-owned path filters, never adds a second matcher. The `head` commit must be the checked-out `HEAD`, and both commits must be reachable (`fetch-depth: 0`). Every doubt path — unreadable identity, malformed or unsupported graph data, an unowned profile change, a working-tree profile that differs from the head commit, or classifier refusal — fails closed and leaves every declared target demanded. `production:impact` keeps its merge-push `before`/`after` contract unchanged.
|
|
68
68
|
|
|
69
|
-
For factory workflow, install the four canonical skills
|
|
69
|
+
For factory workflow, install the four canonical skills as the `patronage-software-factory` host plugin (Claude Code, Codex, or Cursor; see [`skills/README.md`](../skills/README.md)). Cloud agents that cannot load host plugins fall back to:
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
72
|
npx skills add https://github.com/patronage/software-factory -g --all
|
package/dist/index.d.ts
CHANGED
|
@@ -1423,9 +1423,9 @@ declare const managedReadinessLedgerSchema: z.ZodObject<{
|
|
|
1423
1423
|
reviewedHeadSha: z.ZodOptional<z.ZodString>;
|
|
1424
1424
|
reviewedPatchId: z.ZodOptional<z.ZodString>;
|
|
1425
1425
|
status: z.ZodEnum<{
|
|
1426
|
+
blocked: "blocked";
|
|
1426
1427
|
"not-required": "not-required";
|
|
1427
1428
|
stale: "stale";
|
|
1428
|
-
blocked: "blocked";
|
|
1429
1429
|
current: "current";
|
|
1430
1430
|
missing: "missing";
|
|
1431
1431
|
}>;
|
|
@@ -1435,9 +1435,9 @@ declare const managedReadinessLedgerSchema: z.ZodObject<{
|
|
|
1435
1435
|
reviewedHeadSha: z.ZodOptional<z.ZodString>;
|
|
1436
1436
|
reviewedPatchId: z.ZodOptional<z.ZodString>;
|
|
1437
1437
|
status: z.ZodEnum<{
|
|
1438
|
+
blocked: "blocked";
|
|
1438
1439
|
"not-required": "not-required";
|
|
1439
1440
|
stale: "stale";
|
|
1440
|
-
blocked: "blocked";
|
|
1441
1441
|
current: "current";
|
|
1442
1442
|
missing: "missing";
|
|
1443
1443
|
}>;
|
|
@@ -2415,9 +2415,9 @@ declare const loadEvidenceEnvelopes: (cwd: string) => LoadedEvidenceEnvelope[];
|
|
|
2415
2415
|
//#region src/review-proof-applicability.d.ts
|
|
2416
2416
|
declare const REVIEW_STATUS_VALUES: readonly ["not-required", "current", "stale", "missing", "blocked"];
|
|
2417
2417
|
declare const reviewStatusSchema: z.ZodEnum<{
|
|
2418
|
+
blocked: "blocked";
|
|
2418
2419
|
"not-required": "not-required";
|
|
2419
2420
|
stale: "stale";
|
|
2420
|
-
blocked: "blocked";
|
|
2421
2421
|
current: "current";
|
|
2422
2422
|
missing: "missing";
|
|
2423
2423
|
}>;
|
|
@@ -2566,8 +2566,8 @@ declare const boundaryCheckProofSchema: z.ZodObject<{
|
|
|
2566
2566
|
value: z.ZodString;
|
|
2567
2567
|
}, z.core.$strip>>;
|
|
2568
2568
|
status: z.ZodEnum<{
|
|
2569
|
-
ready: "ready";
|
|
2570
2569
|
blocked: "blocked";
|
|
2570
|
+
ready: "ready";
|
|
2571
2571
|
}>;
|
|
2572
2572
|
}, z.core.$strip>;
|
|
2573
2573
|
type BoundaryCheckProofRecord = z.infer<typeof boundaryCheckProofSchema>;
|
|
@@ -2582,6 +2582,14 @@ interface BoundaryCheckGithub {
|
|
|
2582
2582
|
interface BoundaryCheckArgs {
|
|
2583
2583
|
cwd?: string;
|
|
2584
2584
|
epic: number;
|
|
2585
|
+
/**
|
|
2586
|
+
* Closeout-final mode (#853): a manifest-declared issue whose closing-PR
|
|
2587
|
+
* set is empty is a blocking reason, not a notice. Off by default so the
|
|
2588
|
+
* interior boundary review (run before the terminal release PR exists,
|
|
2589
|
+
* e.g. epic #842's own review of #844) keeps working; the epic closeout
|
|
2590
|
+
* step turns this on as the last check before factory:closeout.
|
|
2591
|
+
*/
|
|
2592
|
+
final?: boolean;
|
|
2585
2593
|
json?: boolean;
|
|
2586
2594
|
output?: string;
|
|
2587
2595
|
repo?: string;
|
|
@@ -4147,13 +4155,13 @@ declare const evaluateReadiness: (input: EvaluationInput) => {
|
|
|
4147
4155
|
reviews: {
|
|
4148
4156
|
correctness: {
|
|
4149
4157
|
required: boolean;
|
|
4150
|
-
status: "
|
|
4158
|
+
status: "blocked" | "not-required" | "stale" | "current" | "missing";
|
|
4151
4159
|
reviewedHeadSha?: string | undefined;
|
|
4152
4160
|
reviewedPatchId?: string | undefined;
|
|
4153
4161
|
};
|
|
4154
4162
|
security?: {
|
|
4155
4163
|
required: boolean;
|
|
4156
|
-
status: "
|
|
4164
|
+
status: "blocked" | "not-required" | "stale" | "current" | "missing";
|
|
4157
4165
|
reviewedHeadSha?: string | undefined;
|
|
4158
4166
|
reviewedPatchId?: string | undefined;
|
|
4159
4167
|
} | undefined;
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import { parse } from "yaml";
|
|
|
17
17
|
import { FACTORY_PROOF_GATE_APP_ID, FACTORY_PROOF_GATE_STEP_NAME, GitHubApiError, mintInstallationToken, previewProofInventory, productionImpactTargetOutput, readVitestProfileDocument } from "@patronage/factory-ci";
|
|
18
18
|
import { promisify } from "node:util";
|
|
19
19
|
//#region package.json
|
|
20
|
-
var version = "1.0.0-alpha.
|
|
20
|
+
var version = "1.0.0-alpha.22";
|
|
21
21
|
//#endregion
|
|
22
22
|
//#region src/review-rungs.ts
|
|
23
23
|
const EVIDENCE_REVIEW_RUNGS$1 = [
|
|
@@ -162,10 +162,11 @@ const DEFAULT_TERMINAL_BASE = "main";
|
|
|
162
162
|
*
|
|
163
163
|
* A PR that closed without merging contributes NO closing link (#821): it
|
|
164
164
|
* carried nothing into the boundary, so it is not a member and cannot fail
|
|
165
|
-
* one. The dropped link is recorded on the issue. Closeout blocks
|
|
166
|
-
* that flavor: an issue whose carriers all closed without merging. A
|
|
167
|
-
* issue that never had any closing link is reported as a notice,
|
|
168
|
-
* blocking reason
|
|
165
|
+
* one. The dropped link is recorded on the issue. Closeout blocks by default
|
|
166
|
+
* only on that flavor: an issue whose carriers all closed without merging. A
|
|
167
|
+
* declared issue that never had any closing link is reported as a notice,
|
|
168
|
+
* not a blocking reason — except under boundary:check --final, which blocks
|
|
169
|
+
* on that flavor too (#853).
|
|
169
170
|
*/
|
|
170
171
|
const buildBoundaryMembershipGraph = (manifest, fetchClosingPullRequests) => {
|
|
171
172
|
const memberships = [];
|
|
@@ -5439,10 +5440,12 @@ function runBoundaryCheck(args, dependencies = {}) {
|
|
|
5439
5440
|
selected
|
|
5440
5441
|
});
|
|
5441
5442
|
const uncoveredIssueReasons = graph.unlinkedIssues.flatMap((entry) => entry.closedWithoutMerge === void 0 ? [] : [`issue #${entry.issue} (wave ${entry.wave}) is uncovered: its only closing link(s) ${entry.closedWithoutMerge.map((pr) => `PR #${pr}`).join(", ")} closed without merging`]);
|
|
5443
|
+
const finalUncoveredIssueReasons = args.final ? graph.unlinkedIssues.flatMap((entry) => entry.closedWithoutMerge === void 0 ? [`issue #${entry.issue} (wave ${entry.wave}) has no linked closing PR; --final requires every declared issue to be covered before closeout`] : []) : [];
|
|
5442
5444
|
blockingReasons.unshift(...boundaryTopologyReasons({
|
|
5443
5445
|
manifest: parsed.manifest,
|
|
5444
5446
|
pullRequests: computed.pullRequests
|
|
5445
|
-
}), ...uncoveredIssueReasons);
|
|
5447
|
+
}), ...uncoveredIssueReasons, ...finalUncoveredIssueReasons);
|
|
5448
|
+
const specHashNotices = selected?.proof.specHash !== void 0 && selected.proof.specHash.value !== specHash ? [`boundary-review proof spec sha256 ${selected.proof.specHash.value} does not match current epic spec sha256 ${specHash}; use the specHash from the blocked boundary:check record instead of hashing shell-rendered output`] : [];
|
|
5446
5449
|
record = {
|
|
5447
5450
|
blockingReasons,
|
|
5448
5451
|
boundary: parsed.manifest.boundary,
|
|
@@ -5454,7 +5457,7 @@ function runBoundaryCheck(args, dependencies = {}) {
|
|
|
5454
5457
|
algo: "sha256",
|
|
5455
5458
|
value: parsed.manifestHash
|
|
5456
5459
|
},
|
|
5457
|
-
notices: computed.notices,
|
|
5460
|
+
notices: [...computed.notices, ...specHashNotices],
|
|
5458
5461
|
repo,
|
|
5459
5462
|
...selected ? { reviewProof: {
|
|
5460
5463
|
...selected.commentId === void 0 ? {} : { commentId: selected.commentId },
|
|
@@ -6203,7 +6206,7 @@ const renderReport = (record) => {
|
|
|
6203
6206
|
return `${lines.join("\n")}\n`;
|
|
6204
6207
|
};
|
|
6205
6208
|
function createBoundaryCheckCommand(output, action) {
|
|
6206
|
-
return markCwdOptionDefault(new Command("boundary:check").description("Boundary readiness gate (T8): require a membership-fresh boundary-review proof at the declared closeout rung. Blocks closeout/enablement, never merge.").requiredOption("--epic <number>", "issue number carrying the factory-boundary manifest, which may be the work issue itself (#789)", positiveInteger$1("--epic")).option("--repo <owner/name>", "GitHub repository (default: resolved from --cwd)").option("--cwd <path>", "repository working directory", collectCwdOption).option("--output <path>", "write an additional proof copy to this path").option("--profile <path>", "path to the project profile JSON file").option("--json", "print the full proof record as JSON").action(withGateTiming({
|
|
6209
|
+
return markCwdOptionDefault(new Command("boundary:check").description("Boundary readiness gate (T8): require a membership-fresh boundary-review proof at the declared closeout rung. Blocks closeout/enablement, never merge.").requiredOption("--epic <number>", "issue number carrying the factory-boundary manifest, which may be the work issue itself (#789)", positiveInteger$1("--epic")).option("--repo <owner/name>", "GitHub repository (default: resolved from --cwd)").option("--cwd <path>", "repository working directory", collectCwdOption).option("--output <path>", "write an additional proof copy to this path").option("--profile <path>", "path to the project profile JSON file").option("--json", "print the full proof record as JSON").option("--final", "closeout-final mode (#853): a declared issue with no closing PR blocks instead of only noticing. Run as the last check before factory:closeout.").action(withGateTiming({
|
|
6207
6210
|
gate: "boundary:check",
|
|
6208
6211
|
resolveLedgerRoot: (options) => resolveCwdOption(options.cwd),
|
|
6209
6212
|
stderr: output.stderr
|
|
@@ -6213,7 +6216,8 @@ function createBoundaryCheckCommand(output, action) {
|
|
|
6213
6216
|
epic: options.epic,
|
|
6214
6217
|
...options.repo ? { repo: options.repo } : {},
|
|
6215
6218
|
...options.output ? { output: options.output } : {},
|
|
6216
|
-
...options.json ? { json: true } : {}
|
|
6219
|
+
...options.json ? { json: true } : {},
|
|
6220
|
+
...options.final ? { final: true } : {}
|
|
6217
6221
|
};
|
|
6218
6222
|
const record = action ? action(args) : runBoundaryCheck(args);
|
|
6219
6223
|
output.stdout.write(options.json ? `${JSON.stringify(record, null, 2)}\n` : renderReport(record));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patronage/software-factory",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.22",
|
|
4
4
|
"description": "Shared Patronage software factory CLI and project-profile validation tools",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"picomatch": "^4.0.5",
|
|
38
38
|
"yaml": "^2.9.0",
|
|
39
39
|
"zod": "4.4.3",
|
|
40
|
-
"@patronage/factory-ci": "1.0.0-alpha.
|
|
40
|
+
"@patronage/factory-ci": "1.0.0-alpha.22"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "24.13.3",
|
|
@@ -52,8 +52,7 @@
|
|
|
52
52
|
"tsx": "4.23.1",
|
|
53
53
|
"typescript": "5.9.3",
|
|
54
54
|
"ultracite": "7.10.5",
|
|
55
|
-
"vitest": "4.1.10"
|
|
56
|
-
"vitest-evals": "0.14.0"
|
|
55
|
+
"vitest": "4.1.10"
|
|
57
56
|
},
|
|
58
57
|
"engines": {
|
|
59
58
|
"node": "^24.0.0"
|
|
@@ -70,10 +69,6 @@
|
|
|
70
69
|
"precoverage": "bash ../scripts/ensure-worktree-bootstrap.sh",
|
|
71
70
|
"coverage": "vitest run --coverage",
|
|
72
71
|
"docs:reference": "tsx scripts/update-command-reference.ts",
|
|
73
|
-
"eval:review": "tsx evals/review-prompts/track-b/reviewRunner.ts",
|
|
74
|
-
"eval:review:report": "tsx evals/review-prompts/track-b/reviewReport.ts",
|
|
75
|
-
"eval:review:rescore": "tsx evals/review-prompts/track-b/rescore.ts",
|
|
76
|
-
"eval:review:run": "vitest run --config evals/review-prompts/vitest.eval.config.ts",
|
|
77
72
|
"pack:smoke": "bash scripts/pack-smoke.sh",
|
|
78
73
|
"profile:schema": "tsx scripts/generate-profile-schema.ts",
|
|
79
74
|
"pretest": "bash ../scripts/ensure-worktree-bootstrap.sh",
|