@patronage/software-factory 1.0.0-alpha.6 → 1.0.0-alpha.7

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 CHANGED
@@ -37,7 +37,7 @@ A stacked release train has one terminal release-owning slice. Interior slices d
37
37
  A stable cut has two phases. Phase 1 is the verified package candidate: steps 1 through 4 below, ending in the attended npm publish, tag, and GitHub release. Phase 2 is post-publication stable-doc convergence: steps 5 and 6, a normal admitted docs PR followed by the read-only convergence assertion from a clean `main`. Stable docs must never claim an unpublished version, so they cannot land in the phase-1 change. Prerelease behavior is unchanged: prerelease notes may land before publish while stable docs keep naming the prior stable version.
38
38
 
39
39
  1. Bump `package.json` to valid SemVer. The assertion derives its expected stable or prerelease channel from the version; it accepts no channel flag.
40
- 2. Publish to npm per the [repository operations runbook](../docs/repository-operations.md#publishing) (attended, hand-cut, `pnpm publish` only). Both factory packages pin `publishConfig.tag: next`, so a bare `pnpm --filter @patronage/software-factory publish` lands on `next` and cannot move `latest`. A prerelease is therefore the bare command; a stable version must say it out loud: `pnpm --filter @patronage/software-factory publish --tag latest`. Forgetting the flag on a stable cut leaves `latest` untouched for the convergence assertion to flag the safe failure direction.
40
+ 2. Publish to npm per the [repository operations runbook](../docs/repository-operations.md#publishing) (attended, hand-cut, `pnpm publish` only). **Always pass `--tag` explicitly, on every publish, prerelease or stable** — `pnpm --filter @patronage/software-factory publish --tag next` for a prerelease, `--tag latest` for a stable cut. A filtered publish takes pnpm's recursive path, which passes its own `--tag` (defaulting to `latest`) to npm and therefore ignores the `publishConfig.tag: next` pin both factory packages carry; that is how 1.0.0-alpha.6 briefly took `latest` (#658). The pins stay as belt and braces, but they are not the control. Omitting the flag is not a safe failure: on the filtered command it moves `latest`, which the convergence assertion can only report after the fact.
41
41
  3. Cut the `software-factory-vX.Y.Z` tag and push it.
42
42
  4. Cut the GitHub release for that tag, with notes covering features, deletions, breaking changes, and closed issues. Mark it as a prerelease exactly when its SemVer version has a prerelease component. When the release changes the profile `schemaVersion`, state it in the notes — the profile schema version is a separate axis from the package version.
43
43
  5. Converge the stable docs after publication. Update affected `software-factory-docs/` pages through a normal admitted docs PR. Stable docs must state the current stable version. Prerelease docs may record the candidate and its migration notes, but must not represent it as the current stable release.
package/dist/index.d.ts CHANGED
@@ -3323,8 +3323,8 @@ declare const FACTORY_TRACE_EVENT_DEFINITIONS: readonly [DefinedTraceEvent<"revi
3323
3323
  interiorCycle: z.ZodOptional<z.ZodNumber>;
3324
3324
  observedAt: z.ZodString;
3325
3325
  purpose: z.ZodEnum<{
3326
- code: "code";
3327
3326
  review: "review";
3327
+ code: "code";
3328
3328
  }>;
3329
3329
  slotResolution: z.ZodObject<{
3330
3330
  effort: z.ZodEnum<{
@@ -3402,8 +3402,8 @@ declare const FACTORY_TRACE_EVENT_DEFINITIONS: readonly [DefinedTraceEvent<"revi
3402
3402
  interiorCycle: z.ZodOptional<z.ZodNumber>;
3403
3403
  observedAt: z.ZodString;
3404
3404
  purpose: z.ZodEnum<{
3405
- code: "code";
3406
3405
  review: "review";
3406
+ code: "code";
3407
3407
  }>;
3408
3408
  slotResolution: z.ZodObject<{
3409
3409
  effort: z.ZodEnum<{
@@ -3472,8 +3472,8 @@ declare const FACTORY_TRACE_EVENT_DEFINITIONS: readonly [DefinedTraceEvent<"revi
3472
3472
  interiorCycle: z.ZodOptional<z.ZodNumber>;
3473
3473
  observedAt: z.ZodString;
3474
3474
  purpose: z.ZodEnum<{
3475
- code: "code";
3476
3475
  review: "review";
3476
+ code: "code";
3477
3477
  }>;
3478
3478
  slotResolution: z.ZodObject<{
3479
3479
  effort: z.ZodEnum<{
@@ -3545,7 +3545,7 @@ declare const FACTORY_TRACE_EVENT_DEFINITIONS: readonly [DefinedTraceEvent<"revi
3545
3545
  exitCode: number | null;
3546
3546
  harness: string;
3547
3547
  observedAt: string;
3548
- purpose: "code" | "review";
3548
+ purpose: "review" | "code";
3549
3549
  slotResolution: {
3550
3550
  effort: "high" | "low" | "medium" | "xhigh";
3551
3551
  engine: string;
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ import { parse } from "yaml";
17
17
  import { promisify } from "node:util";
18
18
  import { GitHubApiError, mintInstallationToken } from "@patronage/factory-ci";
19
19
  //#region package.json
20
- var version = "1.0.0-alpha.6";
20
+ var version = "1.0.0-alpha.7";
21
21
  //#endregion
22
22
  //#region src/review-rungs.ts
23
23
  const EVIDENCE_REVIEW_RUNGS$1 = [
@@ -8553,8 +8553,24 @@ function positiveInteger(name) {
8553
8553
  };
8554
8554
  }
8555
8555
  function resolveCwdOption(cwd) {
8556
- if (typeof cwd !== "string" || cwd.trim() === "") throw new Error("--cwd requires a non-empty path; relative values resolve against the current working directory");
8557
- return path.resolve(cwd);
8556
+ const value = typeof cwd === "string" ? cwd : ".";
8557
+ if (value.trim() === "") throw new Error("--cwd requires a non-empty path; relative values resolve against the current working directory");
8558
+ return path.resolve(value);
8559
+ }
8560
+ function collectCwdOption(rawValue, previous) {
8561
+ if (previous === void 0) return rawValue;
8562
+ const previousResolved = resolveCwdOption(previous);
8563
+ const currentResolved = resolveCwdOption(rawValue);
8564
+ if (previousResolved !== currentResolved) throw new Error(`--cwd was passed multiple times with conflicting values: "${previous}" (resolves to ${previousResolved}) and "${rawValue}" (resolves to ${currentResolved})`);
8565
+ return rawValue;
8566
+ }
8567
+ function markCwdOptionDefault(command) {
8568
+ const option = command.options.find((candidate) => candidate.attributeName() === "cwd");
8569
+ if (option) {
8570
+ option.defaultValue = ".";
8571
+ option.defaultValueDescription = ".";
8572
+ }
8573
+ return command;
8558
8574
  }
8559
8575
  function resolveCheckoutPath(cwd, target) {
8560
8576
  return path.resolve(cwd, target);
@@ -8577,7 +8593,7 @@ const renderReport = (record) => {
8577
8593
  return `${lines.join("\n")}\n`;
8578
8594
  };
8579
8595
  function createBoundaryCheckCommand(output, action) {
8580
- return 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>", "epic issue number carrying the factory-boundary manifest", positiveInteger("--epic")).option("--repo <owner/name>", "GitHub repository (default: resolved from --cwd)").option("--cwd <path>", "repository working directory", ".").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({
8596
+ 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>", "epic issue number carrying the factory-boundary manifest", positiveInteger("--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({
8581
8597
  gate: "boundary:check",
8582
8598
  resolveLedgerRoot: (options) => resolveCwdOption(options.cwd),
8583
8599
  stderr: output.stderr
@@ -8616,7 +8632,7 @@ function createBoundaryCheckCommand(output, action) {
8616
8632
  }
8617
8633
  output.stdout.write(options.json ? `${JSON.stringify(record, null, 2)}\n` : renderReport(record));
8618
8634
  if (record.status !== "ready") throw new Error(`boundary:check refused: ${record.blockingReasons.join("; ")}`);
8619
- }));
8635
+ })));
8620
8636
  }
8621
8637
  //#endregion
8622
8638
  //#region src/checkout-repository.ts
@@ -11219,7 +11235,7 @@ const runDemandWaive = (args, dependencies = {}) => {
11219
11235
  * offers no way to declare a demand met, only to waive it on the record.
11220
11236
  */
11221
11237
  function createDemandWaiveCommand(_output, action = runDemandWaive) {
11222
- return new Command("demand:waive").description("Waive one resolved demand for one candidate, on the operator's identity, with the rationale recorded in the proof").requiredOption("--pr <number>", "pull request number", positiveInteger("--pr")).requiredOption("--demand <key>", "resolved demand key, e.g. review-rung:human, required-check:core, merge-freeze").requiredOption("--rationale <text>", "why this demand is being waived").option("--cwd <path>", "working directory to evaluate", ".").option("--json", "print the recorded waiver as JSON").option("--output <path>", "waiver record JSON path").action((options) => {
11238
+ return markCwdOptionDefault(new Command("demand:waive").description("Waive one resolved demand for one candidate, on the operator's identity, with the rationale recorded in the proof").requiredOption("--pr <number>", "pull request number", positiveInteger("--pr")).requiredOption("--demand <key>", "resolved demand key, e.g. review-rung:human, required-check:core, merge-freeze").requiredOption("--rationale <text>", "why this demand is being waived").option("--cwd <path>", "working directory to evaluate", collectCwdOption).option("--json", "print the recorded waiver as JSON").option("--output <path>", "waiver record JSON path").action((options) => {
11223
11239
  action({
11224
11240
  cwd: resolveCwdOption(options.cwd),
11225
11241
  demand: options.demand,
@@ -11228,7 +11244,7 @@ function createDemandWaiveCommand(_output, action = runDemandWaive) {
11228
11244
  pr: options.pr,
11229
11245
  rationale: options.rationale
11230
11246
  });
11231
- });
11247
+ }));
11232
11248
  }
11233
11249
  //#endregion
11234
11250
  //#region src/demand-resolution.ts
@@ -11821,7 +11837,7 @@ const describeOrphans = (orphans) => {
11821
11837
  return ` ${orphans.length} spool location(s) hold this repository's evidence under an earlier key it no longer resolves to — a key-format change strands evidence there where no drain looks: ${described}. Drain each with \`psf hq:flush --dir <path>\`.`;
11822
11838
  };
11823
11839
  /**
11824
- * Red when HQ evidence is waiting for this repository: its own spool or a
11840
+ * Warns when HQ evidence is waiting for this repository: its own spool or a
11825
11841
  * sibling location written under an earlier key of its own that it no longer
11826
11842
  * resolves to (#420). Another repository's spool under the shared root is that
11827
11843
  * repository's business, never this check's (#446).
@@ -11834,8 +11850,15 @@ const describeOrphans = (orphans) => {
11834
11850
  * the spool resolve exactly one key, so evidence written under an older one is
11835
11851
  * invisible to a drain and, before this, to doctor: the failure epic #389 was
11836
11852
  * chartered to end is evidence that is neither delivered nor visibly stranded.
11837
- * An orphan holding pending events is red for the same reason the repo-keyed
11838
- * spool is.
11853
+ * An orphan holding pending events warns for the same reason the repo-keyed
11854
+ * spool does.
11855
+ *
11856
+ * `warning`, not `error` (#659, epic #663 wave 1): a spooled event is real
11857
+ * HQ-delivery lag, but doctor is a read-only diagnostic that must never gain a
11858
+ * flush side-effect, and a preflight gate that treats doctor's exit code as
11859
+ * the bar must not block admission on delivery lag it cannot fix from here.
11860
+ * `psf hq:flush` — a trusted local session, not doctor — is still how the
11861
+ * spool actually drains.
11839
11862
  */
11840
11863
  async function hqSpoolDoctorCheck(input, dependencies = {}) {
11841
11864
  const countSpool = dependencies.countSpool ?? countHqSpoolWork;
@@ -11852,17 +11875,17 @@ async function hqSpoolDoctorCheck(input, dependencies = {}) {
11852
11875
  if (counted.pending > 0) return {
11853
11876
  message: `${counted.pending} HQ event(s) are spooled locally.${oldestNote}${locationsNote} ${FLUSH_REMEDY}${orphanNote}`,
11854
11877
  name: HQ_SPOOL_CHECK_NAME,
11855
- status: "error"
11878
+ status: "warning"
11856
11879
  };
11857
11880
  if (counted.unlistable > 0) return {
11858
11881
  message: `${counted.unlistable} spool location(s) exist but could not be listed within budget, so this cannot be reported as empty.${locationsNote} ${FLUSH_REMEDY}${orphanNote}`,
11859
11882
  name: HQ_SPOOL_CHECK_NAME,
11860
- status: "error"
11883
+ status: "warning"
11861
11884
  };
11862
11885
  return {
11863
11886
  message: `This repository's HQ spool is empty, but stranded evidence is waiting under the spool root ${swept.root}.${orphanNote}`,
11864
11887
  name: HQ_SPOOL_CHECK_NAME,
11865
- status: "error"
11888
+ status: "warning"
11866
11889
  };
11867
11890
  }
11868
11891
  const readJsonFiles = async (dir, readFileImpl) => {
@@ -12213,7 +12236,7 @@ function repositoryUrlMatches(origin, profile) {
12213
12236
  //#endregion
12214
12237
  //#region src/commands/doctor.ts
12215
12238
  function createDoctorCommand(output) {
12216
- return new Command("doctor").description("Validate a project profile without mutating GitHub or local files").option("--base <ref>", "base branch or ref for --preflight", "origin/main").option("--cwd <path>", "working directory to validate", ".").option("--json", "print the doctor report as JSON").option("--preflight", "also list the pre-checkable admission requirements for the current candidate (read-only; never blocks); findings-file shape and wave membership have no read-only pre-check").option("--profile <path>", "path to the project profile JSON file").action(async (options) => {
12239
+ return markCwdOptionDefault(new Command("doctor").description("Validate a project profile without mutating GitHub or local files").option("--base <ref>", "base branch or ref for --preflight", "origin/main").option("--cwd <path>", "working directory to validate", collectCwdOption).option("--json", "print the doctor report as JSON").option("--preflight", "also list the pre-checkable admission requirements for the current candidate (read-only; never blocks); findings-file shape and wave membership have no read-only pre-check").option("--profile <path>", "path to the project profile JSON file").action(async (options) => {
12217
12240
  const report = await doctorProjectProfile({
12218
12241
  base: options.base,
12219
12242
  cwd: resolveCwdOption(options.cwd),
@@ -12223,7 +12246,7 @@ function createDoctorCommand(output) {
12223
12246
  if (options.json) output.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
12224
12247
  else output.stdout.write(formatHumanReport(report));
12225
12248
  if (!report.ok) process.exitCode = 1;
12226
- });
12249
+ }));
12227
12250
  }
12228
12251
  function formatHumanReport(report) {
12229
12252
  return [
@@ -12631,7 +12654,7 @@ function optionalString(key, flagValue, stdinValue) {
12631
12654
  return resolved ? { [key]: resolved } : {};
12632
12655
  }
12633
12656
  function createEvidenceEmitCommand(output, action = runEvidenceEmit, readInput = readStdin) {
12634
- return new Command("evidence:emit").description("Build, validate, and write an external-evidence envelope (ADR 0014)").option("--cwd <path>", "repository working directory", ".").option("--base <ref>", "base branch or ref for the three-way binding", "origin/main").option("--check <name>", "declared requiredChecks name this evidence satisfies").option("--outcome <pass|fail>", "the check outcome").option("--producer <id>", "the producing identity (recorded, not gated)").option("--policy-version <version>", "canonical prompt / Warden rules version").option("--session-id <id>", "producer session id (independence join key)").option("--request-id <id>", "producer request id (join key)").option("--findings-pointer <ref>", "pointer to findings (never embedded)").option("--profile <path>", "path to the project profile JSON file (accepted for a uniform consumer-wrapper flag set and loaded strictly when supplied)").option("--output <path>", "write the envelope to a specific path").option("--stdin", "merge JSON field values from stdin (flags win)").option("--json", "print the written envelope as JSON").action((options) => {
12657
+ return markCwdOptionDefault(new Command("evidence:emit").description("Build, validate, and write an external-evidence envelope (ADR 0014)").option("--cwd <path>", "repository working directory", collectCwdOption).option("--base <ref>", "base branch or ref for the three-way binding", "origin/main").option("--check <name>", "declared requiredChecks name this evidence satisfies").option("--outcome <pass|fail>", "the check outcome").option("--producer <id>", "the producing identity (recorded, not gated)").option("--policy-version <version>", "canonical prompt / Warden rules version").option("--session-id <id>", "producer session id (independence join key)").option("--request-id <id>", "producer request id (join key)").option("--findings-pointer <ref>", "pointer to findings (never embedded)").option("--profile <path>", "path to the project profile JSON file (accepted for a uniform consumer-wrapper flag set and loaded strictly when supplied)").option("--output <path>", "write the envelope to a specific path").option("--stdin", "merge JSON field values from stdin (flags win)").option("--json", "print the written envelope as JSON").action((options) => {
12635
12658
  const cwd = resolveCwdOption(options.cwd);
12636
12659
  const fromStdin = options.stdin ? readInput() : {};
12637
12660
  rejectRetiredStdinFields(fromStdin);
@@ -12658,7 +12681,7 @@ function createEvidenceEmitCommand(output, action = runEvidenceEmit, readInput =
12658
12681
  });
12659
12682
  output.stdout.write(`evidence:emit wrote envelope for "${result.envelope.check}" to ${result.path}\n`);
12660
12683
  if (options.json && "envelope" in result) output.stdout.write(`${JSON.stringify(result.envelope, null, 2)}\n`);
12661
- });
12684
+ }));
12662
12685
  }
12663
12686
  //#endregion
12664
12687
  //#region src/hq-flush.ts
@@ -12821,7 +12844,7 @@ const hqFlushExitCode = (result) => {
12821
12844
  //#endregion
12822
12845
  //#region src/commands/hq-flush.ts
12823
12846
  function createHqFlushCommand(output, action = runHqFlush) {
12824
- return new Command("hq:flush").description("Drain this repository's spooled HQ evidence and report every event; exits 1 when transport failed and 2 when the drain did not finish").option("--cwd <path>", "working directory to evaluate", ".").option("--dir <path>", "drain an explicit spool directory instead of the default locations; repeatable", (value, previous = []) => [...previous, value]).option("--json", "print the flush result as JSON").option("--profile <path>", "path to the project profile JSON file").action(async (options) => {
12847
+ return markCwdOptionDefault(new Command("hq:flush").description("Drain this repository's spooled HQ evidence and report every event; exits 1 when transport failed and 2 when the drain did not finish").option("--cwd <path>", "working directory to evaluate", collectCwdOption).option("--dir <path>", "drain an explicit spool directory instead of the default locations; repeatable", (value, previous = []) => [...previous, value]).option("--json", "print the flush result as JSON").option("--profile <path>", "path to the project profile JSON file").action(async (options) => {
12825
12848
  const result = await action({
12826
12849
  cwd: resolveCwdOption(options.cwd),
12827
12850
  ...options.dir ? { dir: options.dir } : {},
@@ -12831,7 +12854,7 @@ function createHqFlushCommand(output, action = runHqFlush) {
12831
12854
  output.stdout.write(options.json ? `${JSON.stringify(result, null, 2)}\n` : renderHqFlush(result));
12832
12855
  const exitCode = hqFlushExitCode(result);
12833
12856
  if (exitCode !== 0) process.exitCode = exitCode;
12834
- });
12857
+ }));
12835
12858
  }
12836
12859
  //#endregion
12837
12860
  //#region src/follow-up.ts
@@ -15694,7 +15717,7 @@ async function deliverSpooledEvidence({ awaitPending, cwd, flush, profilePath })
15694
15717
  //#endregion
15695
15718
  //#region src/commands/pr-publish.ts
15696
15719
  function createPrPublishCommand(_output, action = runPrPublish) {
15697
- return new Command("pr:publish").description("Compose supplied proof into a ready-for-human handoff; never launches review").option("--pr <number>", "pull request number", positiveInteger("--pr")).option("--base <ref>", "explicit base branch or ref override").option("--authoring-session <id>", "known authoring session identity for verification retries").option("--cwd <path>", "working directory to evaluate", ".").option("--epic <number>", "epic issue containing the factory-boundary manifest; the composed readiness evaluation then applies the wave-demanded review rung (#351)", positiveInteger("--epic")).option("--findings <path>", "clean-session findings to validate when no current review proof is available").option("--json", "print the publish result as JSON").option("--output <path>", "write readiness proof JSON to a file").option("--profile <path>", "path to the project profile JSON file").option("--review-proof <path>", "pr:review proof JSON path").option("--verify-proof <path>", "pr:verify proof JSON path").action(async (options) => {
15720
+ return markCwdOptionDefault(new Command("pr:publish").description("Compose supplied proof into a ready-for-human handoff; never launches review").option("--pr <number>", "pull request number", positiveInteger("--pr")).option("--base <ref>", "explicit base branch or ref override").option("--authoring-session <id>", "known authoring session identity for verification retries").option("--cwd <path>", "working directory to evaluate", collectCwdOption).option("--epic <number>", "epic issue containing the factory-boundary manifest; the composed readiness evaluation then applies the wave-demanded review rung (#351)", positiveInteger("--epic")).option("--findings <path>", "clean-session findings to validate when no current review proof is available").option("--json", "print the publish result as JSON").option("--output <path>", "write readiness proof JSON to a file").option("--profile <path>", "path to the project profile JSON file").option("--review-proof <path>", "pr:review proof JSON path").option("--verify-proof <path>", "pr:verify proof JSON path").action(async (options) => {
15698
15721
  await action({
15699
15722
  authoringSessionIds: options.authoringSession ? [options.authoringSession] : void 0,
15700
15723
  base: options.base ?? "",
@@ -15708,12 +15731,12 @@ function createPrPublishCommand(_output, action = runPrPublish) {
15708
15731
  reviewProof: options.reviewProof,
15709
15732
  verifyProof: options.verifyProof
15710
15733
  });
15711
- });
15734
+ }));
15712
15735
  }
15713
15736
  //#endregion
15714
15737
  //#region src/commands/pr-ready.ts
15715
15738
  function createPrReadyCommand(output, action) {
15716
- return new Command("pr:ready").description("Evaluate typed proof and GitHub state for final readiness").requiredOption("--pr <number>", "pull request number", positiveInteger("--pr")).option("--base <ref>", "explicit base branch or ref override").option("--authoring-session <id...>", "recorded authoring session id(s) for review-type requiredCheck independence (ADR 0014 §5)").option("--cwd <path>", "working directory to evaluate", ".").option("--epic <number>", "epic issue containing the factory-boundary manifest; readiness then evaluates the wave-demanded review rung (#351)", positiveInteger("--epic")).option("--json", "print the readiness proof as JSON").option("--output <path>", "write proof JSON to a file").option("--profile <path>", "path to the project profile JSON file").option("--review-proof <path>", "pr:review proof JSON path").option("--verify-proof <path>", "pr:verify proof JSON path").action(withGateTiming({
15739
+ return markCwdOptionDefault(new Command("pr:ready").description("Evaluate typed proof and GitHub state for final readiness").requiredOption("--pr <number>", "pull request number", positiveInteger("--pr")).option("--base <ref>", "explicit base branch or ref override").option("--authoring-session <id...>", "recorded authoring session id(s) for review-type requiredCheck independence (ADR 0014 §5)").option("--cwd <path>", "working directory to evaluate", collectCwdOption).option("--epic <number>", "epic issue containing the factory-boundary manifest; readiness then evaluates the wave-demanded review rung (#351)", positiveInteger("--epic")).option("--json", "print the readiness proof as JSON").option("--output <path>", "write proof JSON to a file").option("--profile <path>", "path to the project profile JSON file").option("--review-proof <path>", "pr:review proof JSON path").option("--verify-proof <path>", "pr:verify proof JSON path").action(withGateTiming({
15717
15740
  gate: "pr:ready",
15718
15741
  resolveLedgerRoot: (options) => resolveCwdOption(options.cwd),
15719
15742
  stderr: output.stderr
@@ -15731,7 +15754,7 @@ function createPrReadyCommand(output, action) {
15731
15754
  verifyProof: options.verifyProof
15732
15755
  };
15733
15756
  await (action ? action(args) : runPrReady(args));
15734
- }));
15757
+ })));
15735
15758
  }
15736
15759
  //#endregion
15737
15760
  //#region src/gate-foreground-guard.ts
@@ -15760,7 +15783,7 @@ function assertForegroundGate({ gate, env = process.env }) {
15760
15783
  //#endregion
15761
15784
  //#region src/commands/pr-review.ts
15762
15785
  function createPrReviewCommand(output, action) {
15763
- return new Command("pr:review").description("Validate clean-session findings and write typed review proof").option("--base <ref>", "base branch or ref", "origin/main").option("--cwd <path>", "working directory to review", ".").option("--cycle <number>", "review cycle number", positiveInteger("--cycle"), 1).option("--mode <mode>", "correctness, security, or all", "all").option("--findings <path>", "typed clean-session findings JSON file").option("--dispositions <path>", "JSON file of ladder disposition declarations (waived / follow-up-filed / fixed-in-thread) for previously flagged findings").option("--issue <number>", "issue number recorded on the review ladder trace", positiveInteger("--issue")).option("--output <path>", "write proof JSON to a file").option("--profile <path>", "path to the project profile JSON file").option("--verify-proof <path>", "pr:verify proof JSON path").action(withGateTiming({
15786
+ return markCwdOptionDefault(new Command("pr:review").description("Validate clean-session findings and write typed review proof").option("--base <ref>", "base branch or ref", "origin/main").option("--cwd <path>", "working directory to review", collectCwdOption).option("--cycle <number>", "review cycle number", positiveInteger("--cycle"), 1).option("--mode <mode>", "correctness, security, or all", "all").option("--findings <path>", "typed clean-session findings JSON file").option("--dispositions <path>", "JSON file of ladder disposition declarations (waived / follow-up-filed / fixed-in-thread) for previously flagged findings").option("--issue <number>", "issue number recorded on the review ladder trace", positiveInteger("--issue")).option("--output <path>", "write proof JSON to a file").option("--profile <path>", "path to the project profile JSON file").option("--verify-proof <path>", "pr:verify proof JSON path").action(withGateTiming({
15764
15787
  gate: "pr:review",
15765
15788
  resolveCycle: (options) => options.cycle,
15766
15789
  resolveLedgerRoot: (options) => resolveCwdOption(options.cwd),
@@ -15785,12 +15808,12 @@ function createPrReviewCommand(output, action) {
15785
15808
  verifyProof: options.verifyProof
15786
15809
  };
15787
15810
  await (action ? action(args) : runPrReview(args, { publishCheckRun: createFactoryCheckPublisher(output) }));
15788
- }));
15811
+ })));
15789
15812
  }
15790
15813
  //#endregion
15791
15814
  //#region src/commands/pr-verify.ts
15792
15815
  function createPrVerifyCommand(output, action = runPrVerify) {
15793
- return new Command("pr:verify").description("Run project-profile verification commands and write typed proof").option("--base <ref>", "base branch or ref", "origin/main").option("--cwd <path>", "working directory to verify", ".").option("--docs-only", "run the docs/process verification gate").option("--trivial", "run the trivial verification gate").option("--full", "run the full verification gate").option("--authoring-session <id>", "explicit authoring session identity (required for review evidence)").option("--json", "print the proof as JSON after verification").option("--output <path>", "write proof JSON to a file").option("--profile <path>", "path to the project profile JSON file").option("--no-status", "skip posting the patronage-factory/pr-verify commit status").action(withGateTiming({
15816
+ return markCwdOptionDefault(new Command("pr:verify").description("Run project-profile verification commands and write typed proof").option("--base <ref>", "base branch or ref", "origin/main").option("--cwd <path>", "working directory to verify", collectCwdOption).option("--docs-only", "run the docs/process verification gate").option("--trivial", "run the trivial verification gate").option("--full", "run the full verification gate").option("--authoring-session <id>", "explicit authoring session identity (required for review evidence)").option("--json", "print the proof as JSON after verification").option("--output <path>", "write proof JSON to a file").option("--profile <path>", "path to the project profile JSON file").option("--no-status", "skip posting the patronage-factory/pr-verify commit status").action(withGateTiming({
15794
15817
  gate: "pr:verify",
15795
15818
  resolveLedgerRoot: (options) => resolveCwdOption(options.cwd),
15796
15819
  stderr: output.stderr
@@ -15812,7 +15835,7 @@ function createPrVerifyCommand(output, action = runPrVerify) {
15812
15835
  requireKnownAuthoringSession: true
15813
15836
  }, dependencies);
15814
15837
  if (options.json) output.stdout.write(`${JSON.stringify(proof, null, 2)}\n`);
15815
- }));
15838
+ })));
15816
15839
  }
15817
15840
  function modeFor(options) {
15818
15841
  if (options.docsOnly) return "docs-only";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patronage/software-factory",
3
- "version": "1.0.0-alpha.6",
3
+ "version": "1.0.0-alpha.7",
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.6"
40
+ "@patronage/factory-ci": "1.0.0-alpha.7"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "24.13.3",