@biffo/cli 0.313.0 → 0.313.2

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 (2) hide show
  1. package/dist/index.js +78 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -719,7 +719,8 @@ function checkCoreOwnership({
719
719
  branch = "",
720
720
  commitMessage = "",
721
721
  warnOnly = [],
722
- templateShippedPaths = null
722
+ templateShippedPaths = null,
723
+ upgradeCommitFiles = null
723
724
  }) {
724
725
  const empty = {
725
726
  blocked: [],
@@ -729,8 +730,13 @@ function checkCoreOwnership({
729
730
  knownOrphans: []
730
731
  };
731
732
  if (!isInstance) return { skipped: "template", ...empty };
732
- if (branch.startsWith(UPGRADE_BRANCH_PREFIX)) return { skipped: "upgrade-branch", ...empty };
733
- const manifestTemplateOwned = changedFiles.filter((f) => isTemplateOwned(f, manifest));
733
+ let effectiveChangedFiles = changedFiles;
734
+ if (branch.startsWith(UPGRADE_BRANCH_PREFIX)) {
735
+ const exempt = new Set(upgradeCommitFiles ?? []);
736
+ effectiveChangedFiles = changedFiles.filter((f) => !exempt.has(f));
737
+ if (effectiveChangedFiles.length === 0) return { skipped: "upgrade-branch", ...empty };
738
+ }
739
+ const manifestTemplateOwned = effectiveChangedFiles.filter((f) => isTemplateOwned(f, manifest));
734
740
  const knownOrphans = [];
735
741
  const templateOwned = [];
736
742
  for (const path of manifestTemplateOwned) {
@@ -4455,7 +4461,35 @@ function buildPrBody(from, to, plan, migrations, base = GLOBAL_DISPATCH_REF, loc
4455
4461
  lines.push(
4456
4462
  "Automated core upgrade generated by `biffo core upgrade` (ADR-0006).",
4457
4463
  "",
4458
- `Bumps the Biffo template core from **${from}** to **${to}** and updates \`biffo.core.json\`. Only template-owned paths (see \`core-manifest.json\`) were touched \u2014 product, plugin, and infra files were left untouched.`,
4464
+ // SCOPED TO THE COMMIT THIS TOOL WRITES, NOT TO THE BRANCH (#1999).
4465
+ //
4466
+ // The old wording was "Only template-owned paths were touched — product,
4467
+ // plugin, and infra files were left untouched", stated flatly about the PR.
4468
+ // It is true when this runs and routinely FALSE by the time the PR merges,
4469
+ // because an instance carrying a divergence declaration cannot go green
4470
+ // without a second, user-owned commit on this same branch:
4471
+ // `test_known_divergence_derivation_matches_the_current_core_pin` asserts
4472
+ // the derivation constant equals `biffo.core.json`'s pin in BOTH
4473
+ // directions, so bumping the pin without re-deriving is red on a required
4474
+ // check, and re-deriving without the bump turns `dev` red instead. Neither
4475
+ // half can land alone.
4476
+ //
4477
+ // Live cost of the old wording, tabsii-com/tabsii-platform#1420: a
4478
+ // prosecutor compared the branch head to this claim, correctly found the
4479
+ // claim false, and rejected the PR. The remediation split the re-derivation
4480
+ // into a stacked PR and deadlocked — the upgrade could not go green without
4481
+ // it, and it could not merge before the upgrade. Three builder dispatches, a
4482
+ // model escalation and a blocker filed at the owner, with nothing wrong in
4483
+ // the code at any point. The tool asserted something it cannot keep true and
4484
+ // a guard believed it.
4485
+ //
4486
+ // This says only what the tool actually knows: what ITS OWN commit did.
4487
+ // #1994 made that distinction real on the guard side too, scoping the
4488
+ // ownership exemption to the mechanical commit — so the body and the guard
4489
+ // now mean the same thing by "the upgrade".
4490
+ `Bumps the Biffo template core from **${from}** to **${to}** and updates \`biffo.core.json\`.`,
4491
+ "",
4492
+ `The commit generated by \`biffo core upgrade\` touches only template-owned paths (see \`core-manifest.json\`) \u2014 no product, plugin or infra files. **Any later commit on this branch is an ordinary reviewable change and is not covered by that statement.** A divergence-pin re-derivation belongs here, for example: the pin-equality test requires it to land together with the core bump, and it edits a user-owned path by design.`,
4459
4493
  ...carriedPrsSection(carriedPrs),
4460
4494
  "",
4461
4495
  `## Changes (${plan.changes.length})`,
@@ -12722,7 +12756,37 @@ async function fetchTemplateShippedPaths(repoRoot, runner = defaultRunner) {
12722
12756
  return paths.length > 0 ? new Set(paths) : null;
12723
12757
  }
12724
12758
 
12759
+ // src/lib/upgrade-commit-files.ts
12760
+ var defaultRunner2 = async (args, cwd) => {
12761
+ const result = await execa("git", args, { cwd, reject: false, timeout: 15e3 });
12762
+ return { stdout: String(result.stdout ?? ""), exitCode: result.exitCode ?? null };
12763
+ };
12764
+ var splitLines = (stdout) => stdout.split("\n").map((line) => line.trim()).filter(Boolean);
12765
+ async function resolveUpgradeCommitFiles(repoRoot, base, opts = {}, runner = defaultRunner2) {
12766
+ let rev;
12767
+ try {
12768
+ rev = await runner(["rev-list", "--reverse", `${base}..HEAD`], repoRoot);
12769
+ } catch {
12770
+ return null;
12771
+ }
12772
+ if (rev.exitCode !== 0) return null;
12773
+ const commits = splitLines(rev.stdout);
12774
+ if (commits.length === 0) {
12775
+ return opts.stagedFallbackFiles ?? null;
12776
+ }
12777
+ const first = commits[0];
12778
+ let diff;
12779
+ try {
12780
+ diff = await runner(["diff-tree", "--no-commit-id", "--name-only", "-r", first], repoRoot);
12781
+ } catch {
12782
+ return null;
12783
+ }
12784
+ if (diff.exitCode !== 0) return null;
12785
+ return splitLines(diff.stdout);
12786
+ }
12787
+
12725
12788
  // src/scripts/check-core-ownership.ts
12789
+ var LOCAL_UPGRADE_BASE = "origin/dev";
12726
12790
  var BOLD = "\x1B[1m";
12727
12791
  var DIM = "\x1B[2m";
12728
12792
  var RED = "\x1B[31m";
@@ -12748,6 +12812,7 @@ async function runOwnershipCheck(argv) {
12748
12812
  let changedFiles;
12749
12813
  let deletedFiles = [];
12750
12814
  let commitMessage = "";
12815
+ let ciBase = null;
12751
12816
  if (staged) {
12752
12817
  const { stdout } = await execa("git", ["diff", "--cached", "--name-status"], { cwd: root });
12753
12818
  ({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
@@ -12762,11 +12827,12 @@ async function runOwnershipCheck(argv) {
12762
12827
  process.exit(2);
12763
12828
  }
12764
12829
  await execa("git", ["fetch", "--quiet", "origin", base], { cwd: root, reject: false });
12765
- const { stdout } = await execa("git", ["diff", "--name-status", `origin/${base}...HEAD`], {
12830
+ ciBase = `origin/${base}`;
12831
+ const { stdout } = await execa("git", ["diff", "--name-status", `${ciBase}...HEAD`], {
12766
12832
  cwd: root
12767
12833
  });
12768
12834
  ({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
12769
- const { stdout: log2 } = await execa("git", ["log", "--format=%B", `origin/${base}..HEAD`], {
12835
+ const { stdout: log2 } = await execa("git", ["log", "--format=%B", `${ciBase}..HEAD`], {
12770
12836
  cwd: root,
12771
12837
  reject: false
12772
12838
  });
@@ -12777,6 +12843,11 @@ async function runOwnershipCheck(argv) {
12777
12843
  reject: false
12778
12844
  });
12779
12845
  const branch = resolveBranch(process.env, gitBranch);
12846
+ const upgradeCommitFiles = branch.startsWith(UPGRADE_BRANCH_PREFIX) ? await resolveUpgradeCommitFiles(
12847
+ root,
12848
+ ciBase ?? LOCAL_UPGRADE_BASE,
12849
+ staged ? { stagedFallbackFiles: changedFiles } : {}
12850
+ ) : null;
12780
12851
  const templateShippedPaths = staged ? null : await fetchTemplateShippedPaths(root);
12781
12852
  if (!staged && templateShippedPaths === null) {
12782
12853
  console.error(
@@ -12790,6 +12861,7 @@ async function runOwnershipCheck(argv) {
12790
12861
  branch,
12791
12862
  commitMessage,
12792
12863
  warnOnly: readDivergenceConfig(root).warnOnly,
12864
+ upgradeCommitFiles,
12793
12865
  templateShippedPaths
12794
12866
  });
12795
12867
  if (result.knownOrphans.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biffo/cli",
3
- "version": "0.313.0",
3
+ "version": "0.313.2",
4
4
  "description": "Biffo project scaffolding CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",