@callumvass/forgeflow-dev 0.4.2 → 0.4.4

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/extensions/index.js +30 -65
  2. package/package.json +1 -1
@@ -419,22 +419,6 @@ function slugify(text, maxLen = 40) {
419
419
  }
420
420
  var JIRA_KEY_RE = /^[A-Z]+-\d+$/;
421
421
  var JIRA_BRANCH_RE = /feat\/([A-Z]+-\d+)/;
422
- async function ensureBranch(cwd, branch) {
423
- const currentBranch = await exec("git branch --show-current", cwd);
424
- if (currentBranch === branch) return;
425
- const localExists = await exec(`git rev-parse --verify ${branch} 2>/dev/null && echo yes || echo no`, cwd);
426
- if (localExists === "yes") {
427
- await exec(`git checkout ${branch}`, cwd);
428
- return;
429
- }
430
- await exec("git fetch origin", cwd);
431
- const remoteExists = await exec(`git rev-parse --verify origin/${branch} 2>/dev/null && echo yes || echo no`, cwd);
432
- if (remoteExists === "yes") {
433
- await exec(`git checkout -b ${branch} origin/${branch}`, cwd);
434
- } else {
435
- await exec(`git checkout -b ${branch}`, cwd);
436
- }
437
- }
438
422
  async function resolveIssue(cwd, issueArg) {
439
423
  if (issueArg && JIRA_KEY_RE.test(issueArg)) {
440
424
  return resolveJiraIssue(cwd, issueArg);
@@ -755,25 +739,38 @@ ${flags.customPrompt}` : "";
755
739
  };
756
740
  }
757
741
  if (resolved.branch) {
758
- const localExists = await exec(`git rev-parse --verify ${resolved.branch} 2>/dev/null && echo yes || echo no`, cwd);
759
- const remoteExists = localExists === "yes" ? "no" : await exec(
760
- `git fetch origin && git rev-parse --verify origin/${resolved.branch} 2>/dev/null && echo yes || echo no`,
742
+ const branch = resolved.branch;
743
+ const branchSetup = await exec(
744
+ `ahead=$(git rev-list main..${branch} --count 2>/dev/null || echo 0); if [ "$ahead" -gt 0 ] 2>/dev/null; then git checkout ${branch} && echo "RESUME:$ahead"; else git branch -D ${branch} 2>/dev/null; git branch -dr origin/${branch} 2>/dev/null; git checkout -b ${branch} && echo "FRESH"; fi`,
761
745
  cwd
762
746
  );
763
- if (localExists === "yes" || remoteExists === "yes") {
764
- await ensureBranch(cwd, resolved.branch);
765
- const ahead = await exec(`git rev-list main..${resolved.branch} --count`, cwd);
766
- if (parseInt(ahead, 10) > 0) {
767
- await exec(`git push -u origin ${resolved.branch}`, cwd);
768
- const prBody = buildPrBody(cwd, resolved);
769
- await createPr(cwd, resolved.title, prBody, resolved.branch);
770
- const stages2 = [];
771
- await refactorAndReview(cwd, signal, onUpdate, ctx, stages2, flags.skipReview);
772
- return {
773
- content: [{ type: "text", text: `Resumed ${issueLabel} \u2014 pushed existing commits and created PR.` }],
774
- details: { pipeline: "implement", stages: stages2 }
775
- };
776
- }
747
+ if (branchSetup.startsWith("RESUME:")) {
748
+ await exec(`git push -u origin ${branch}`, cwd);
749
+ const prBody = buildPrBody(cwd, resolved);
750
+ await createPr(cwd, resolved.title, prBody, branch);
751
+ const stages2 = [];
752
+ await refactorAndReview(cwd, signal, onUpdate, ctx, stages2, flags.skipReview);
753
+ return {
754
+ content: [{ type: "text", text: `Resumed ${issueLabel} \u2014 pushed existing commits and created PR.` }],
755
+ details: { pipeline: "implement", stages: stages2 }
756
+ };
757
+ }
758
+ let afterBranch = await exec("git branch --show-current", cwd);
759
+ if (afterBranch !== branch) {
760
+ await exec(`git checkout ${branch} 2>/dev/null || git checkout -b ${branch}`, cwd);
761
+ afterBranch = await exec("git branch --show-current", cwd);
762
+ }
763
+ if (afterBranch !== branch) {
764
+ return {
765
+ content: [
766
+ {
767
+ type: "text",
768
+ text: `Failed to switch to ${branch} (on ${afterBranch}). Setup output: ${branchSetup || "(empty)"}`
769
+ }
770
+ ],
771
+ details: { pipeline: "implement", stages: [] },
772
+ isError: true
773
+ };
777
774
  }
778
775
  }
779
776
  const stageList = [];
@@ -814,38 +811,6 @@ ${issueContext}${customPromptSection}`,
814
811
  }
815
812
  }
816
813
  }
817
- if (resolved.branch) {
818
- const currentBranch = await exec("git branch --show-current", cwd);
819
- if (currentBranch === "main" || currentBranch === "master") {
820
- const dirty = await exec("git status --porcelain", cwd);
821
- if (dirty) {
822
- return {
823
- content: [
824
- {
825
- type: "text",
826
- text: `Cannot switch to ${resolved.branch} \u2014 working tree is dirty. Please commit or stash your changes first.`
827
- }
828
- ],
829
- details: { pipeline: "implement", stages: [] },
830
- isError: true
831
- };
832
- }
833
- await ensureBranch(cwd, resolved.branch);
834
- const afterBranch = await exec("git branch --show-current", cwd);
835
- if (afterBranch !== resolved.branch) {
836
- return {
837
- content: [
838
- {
839
- type: "text",
840
- text: `Failed to switch to ${resolved.branch} (still on ${afterBranch}). Check git state and retry.`
841
- }
842
- ],
843
- details: { pipeline: "implement", stages: [] },
844
- isError: true
845
- };
846
- }
847
- }
848
- }
849
814
  cleanSignal(cwd, "blocked");
850
815
  const planSection = plan ? `
851
816
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@callumvass/forgeflow-dev",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "type": "module",
5
5
  "description": "Dev pipeline for Pi — TDD implementation, code review, architecture, and skill discovery.",
6
6
  "keywords": [