@senad-d/branchme 0.3.17 → 0.3.18

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.18 - Unreleased
4
+
5
+ - Made the real-Git commit lock-retry regression deterministic by releasing the fixture lock after staging encounters it, rather than on a fixed timer.
6
+ - `integrate_branch` refuses only staged, unstaged or unmerged tracked changes in the control worktree, like `update_from_base`. Before, one untracked file refused every local merge, and no BranchMe tool can move a file.
7
+
3
8
  ## 0.3.17 - Unreleased
4
9
 
5
10
  - `revert_changes` refuses only ignored files at the paths the reverted commit touches, which Git could overwrite. Before, any ignored file in the checkout (`.env`, `.pi/`, `node_modules`) refused the revert, and in a repository with installed dependencies the whole-checkout listing passed the 4 MiB read cap first ("Local Git inspection exceeded the 4 MiB safety limit"), so the tool could not run in a working project.
package/README.md CHANGED
@@ -421,7 +421,7 @@ If pull request field autofill is enabled, after push_branch completes create a
421
421
 
422
422
  ### Verified local branch integration
423
423
 
424
- `integrate_branch` requires explicit intent and exactly two distinct existing local branch names: `sourceBranch` and `targetBranch`. The active Pi worktree is the control worktree; it must be clean, have no merge/rebase/cherry-pick/revert/sequencer operation in progress, and already have `targetBranch` checked out. BranchMe never switches to the target or infers one. A source checked out in another dirty linked worktree is allowed because integration reads only its committed local ref. Remote-only refs, commit IDs, paths, repositories, remotes, and owner-prefixed refs are rejected. Optional `worktreePath` makes another worktree of the same repository the control worktree: it must be the absolute root of the primary checkout or a registered linked worktree with the same Git common directory; relative paths, subdirectories, missing, bare, and foreign paths are refused before integration starts.
424
+ `integrate_branch` requires explicit intent and exactly two distinct existing local branch names: `sourceBranch` and `targetBranch`. The active Pi worktree is the control worktree; it must have no staged, unstaged, or unmerged tracked changes (untracked files do not block), have no merge/rebase/cherry-pick/revert/sequencer operation in progress, and already have `targetBranch` checked out. BranchMe never switches to the target or infers one. A source checked out in another dirty linked worktree is allowed because integration reads only its committed local ref. Remote-only refs, commit IDs, paths, repositories, remotes, and owner-prefixed refs are rejected. Optional `worktreePath` makes another worktree of the same repository the control worktree: it must be the absolute root of the primary checkout or a registered linked worktree with the same Git common directory; relative paths, subdirectories, missing, bare, and foreign paths are refused before integration starts.
425
425
 
426
426
  For a source not already reachable from the target, BranchMe runs this fixed normal-merge policy from the verified worktree root:
427
427
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@senad-d/branchme",
3
- "version": "0.3.17",
3
+ "version": "0.3.18",
4
4
  "type": "module",
5
5
  "description": "Pi extension for verified Git repository initialization, commit, branch, worktree, integration, retirement, push, and pull request workflows.",
6
6
  "license": "MIT",
@@ -217,10 +217,9 @@ async function integrationSourceHead(
217
217
  return head;
218
218
  }
219
219
 
220
- function integrationWorkingTreeIsClean(workingTree: WorkingTreeDetails, allowUntracked: boolean): boolean {
221
- return allowUntracked
222
- ? workingTree.staged + workingTree.unstaged === 0
223
- : workingTree.state === "clean";
220
+ // Untracked files never block: git itself refuses a merge that would overwrite one.
221
+ function integrationWorkingTreeIsClean(workingTree: WorkingTreeDetails): boolean {
222
+ return workingTree.staged + workingTree.unstaged === 0;
224
223
  }
225
224
 
226
225
  async function inspectIntegrationState(
@@ -242,7 +241,7 @@ async function inspectIntegrationState(
242
241
  timeout: GIT_STATUS_TIMEOUT_MS,
243
242
  });
244
243
  const workingTree = parseWorkingTreeStatus(statusResult.stdout).workingTree;
245
- const clean = integrationWorkingTreeIsClean(workingTree, prepared.remoteSource === true || prepared.sourceHeadFixed === true);
244
+ const clean = integrationWorkingTreeIsClean(workingTree);
246
245
  const sourceIsAncestorOfTarget = await isCommitAncestor(
247
246
  pi,
248
247
  rootCtx,
@@ -776,9 +775,9 @@ export async function prepareBranchIntegration(
776
775
  timeout: GIT_STATUS_TIMEOUT_MS,
777
776
  });
778
777
  const workingTree = parseWorkingTreeStatus(statusResult.stdout).workingTree;
779
- if (!integrationWorkingTreeIsClean(workingTree, remoteSource)) {
778
+ if (!integrationWorkingTreeIsClean(workingTree)) {
780
779
  throw new Error(
781
- "The control worktree must be clean, with no staged, unstaged, untracked, or unmerged changes, before integration.",
780
+ "The control worktree must be clean, with no staged, unstaged, or unmerged tracked changes, before integration.",
782
781
  );
783
782
  }
784
783