valent-pipeline 0.19.40 → 0.19.41

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valent-pipeline",
3
- "version": "0.19.40",
3
+ "version": "0.19.41",
4
4
  "description": "v3 multi-agent AI pipeline for software development lifecycle",
5
5
  "type": "module",
6
6
  "bin": {
@@ -489,6 +489,29 @@ export function startStory({ root, story, targetBranch = '', prefix = 'story/',
489
489
 
490
490
  git(root, ['checkout', base]);
491
491
  git(root, ['checkout', '-b', branch]);
492
+ // BUG-2 (M-36, 2026-06-19): a branch BASED ON a source story branch (--from-story, e.g. an inline bug
493
+ // fix) starts at the SOURCE's tip — which can predate commits made to the TARGET since the source was
494
+ // cut, most importantly the rejected story's BUG ENTRIES that the disposition filed to the shared
495
+ // backlog on the target. The freshly-based branch then can't see them, so `backlog ship --story <bug>`
496
+ // errors "not found" (and an eventual --into merge fights stale target state). The target is the source
497
+ // of truth for shared sprint state, so sync it into the new branch. Guarded tightly: ONLY when actually
498
+ // basing on another branch (basedOnStory) and the target is genuinely ahead — a fresh story off the
499
+ // target is already current (no-op) — and ONLY on this create path, never on a resume (a refresh after
500
+ // the critic pin would move HEAD past it). A conflict (source + target diverged on the SAME file) aborts
501
+ // cleanly and leaves the branch at its base — degraded but no worse than before, and surfaced — rather
502
+ // than wedging a half-merge that would hard-stop every later commit in this checkout.
503
+ let refreshedFromTarget = false;
504
+ let refreshConflict = false;
505
+ if (basedOnStory && branchExists(root, target) && !isMergedInto(root, target, branch)) {
506
+ try {
507
+ git(root, ['merge', '--no-ff', '-m',
508
+ buildCommitMessage({ storyId: story, phase: 'sync', summary: `sync ${target} into ${branch} (inherit shared state from a behind base)` }), target]);
509
+ refreshedFromTarget = true;
510
+ } catch {
511
+ if (mergeInProgress(root)) git(root, ['merge', '--abort']);
512
+ refreshConflict = true;
513
+ }
514
+ }
492
515
  writeFlowRecord(root, story, {
493
516
  schema: 1,
494
517
  kind: 'git-flow',
@@ -499,7 +522,9 @@ export function startStory({ root, story, targetBranch = '', prefix = 'story/',
499
522
  basedOnStory: basedOnStory ? storyBranchName(prefix, fromStory) : null,
500
523
  startedAt: new Date().toISOString(),
501
524
  });
502
- return { branch, base, target, created: true, resumed: false, snapshotSha };
525
+ return { branch, base, target, created: true, resumed: false, snapshotSha,
526
+ ...(refreshedFromTarget ? { refreshedFromTarget: true } : {}),
527
+ ...(refreshConflict ? { refreshConflict: true } : {}) };
503
528
  }
504
529
 
505
530
  /**