@callumvass/forgeflow-dev 0.4.3 → 0.5.0

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.
@@ -103,6 +103,10 @@ PRBODY
103
103
  gh pr create --title "My title" --body-file /tmp/pr-body.md
104
104
  ```
105
105
 
106
+ ## Commit Style
107
+
108
+ Use [Conventional Commits](https://www.conventionalcommits.org/). Read `git log --oneline -10` before your first commit to match the repo's existing style. Common prefixes: `feat:`, `fix:`, `test:`, `refactor:`, `chore:`, `docs:`. Keep messages concise (under 72 chars).
109
+
106
110
  ## Before Committing
107
111
 
108
112
  - **Reachability check**: Every new module, class, or function you created must be imported and called from production code — not just from tests. Trace from the entry point to your new code.
@@ -37,3 +37,4 @@ You are a refactorer agent. You run after a feature has been implemented to find
37
37
  - **Keep it small**: Each refactoring should be a single, focused change.
38
38
  - **If nothing to do, say so**: "No refactoring needed" is a perfectly valid outcome.
39
39
  - **Preserve public interfaces**: Don't rename or restructure exports without updating all callers.
40
+ - **Commit style**: Use [Conventional Commits](https://www.conventionalcommits.org/). Read `git log --oneline -10` before committing to match the repo's style. Use `refactor:` prefix.
@@ -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,47 +739,33 @@ ${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
- if (localExists === "yes") {
760
- const ahead = await exec(`git rev-list main..${resolved.branch} --count`, cwd);
761
- if (parseInt(ahead, 10) > 0) {
762
- await ensureBranch(cwd, resolved.branch);
763
- await exec(`git push -u origin ${resolved.branch}`, cwd);
764
- const prBody = buildPrBody(cwd, resolved);
765
- await createPr(cwd, resolved.title, prBody, resolved.branch);
766
- const stages2 = [];
767
- await refactorAndReview(cwd, signal, onUpdate, ctx, stages2, flags.skipReview);
768
- return {
769
- content: [{ type: "text", text: `Resumed ${issueLabel} \u2014 pushed existing commits and created PR.` }],
770
- details: { pipeline: "implement", stages: stages2 }
771
- };
772
- }
773
- await exec(`git branch -D ${resolved.branch}`, cwd);
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`,
745
+ cwd
746
+ );
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
+ };
774
757
  }
775
- const currentBranch = await exec("git branch --show-current", cwd);
776
- if (currentBranch === "main" || currentBranch === "master") {
777
- const dirty = await exec("git status --porcelain", cwd);
778
- if (dirty) {
779
- return {
780
- content: [
781
- {
782
- type: "text",
783
- text: `Cannot switch to ${resolved.branch} \u2014 working tree is dirty. Please commit or stash your changes first.`
784
- }
785
- ],
786
- details: { pipeline: "implement", stages: [] },
787
- isError: true
788
- };
789
- }
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);
790
762
  }
791
- await ensureBranch(cwd, resolved.branch);
792
- const afterBranch = await exec("git branch --show-current", cwd);
793
- if (afterBranch !== resolved.branch) {
763
+ if (afterBranch !== branch) {
794
764
  return {
795
765
  content: [
796
766
  {
797
767
  type: "text",
798
- text: `Failed to switch to ${resolved.branch} (still on ${afterBranch}). Check git state and retry.`
768
+ text: `Failed to switch to ${branch} (on ${afterBranch}). Setup output: ${branchSetup || "(empty)"}`
799
769
  }
800
770
  ],
801
771
  details: { pipeline: "implement", stages: [] },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@callumvass/forgeflow-dev",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "description": "Dev pipeline for Pi — TDD implementation, code review, architecture, and skill discovery.",
6
6
  "keywords": [