taskplane 0.14.0 → 0.14.1

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.
@@ -627,8 +627,23 @@ function renderMergeAgents(batch, tmuxSessions) {
627
627
  const showRepos = knownRepos.length >= 2;
628
628
  const telemetry = currentData?.telemetry || {};
629
629
 
630
- // Check for active merge sessions (convention: orch-merge-*)
631
- const mergeSessions = (tmuxSessions || []).filter(s => s.startsWith("orch-merge"));
630
+ // Check for active merge sessions (convention: {prefix}-{opId}-merge-{N})
631
+ const mergeSessions = (tmuxSessions || []).filter(s => s.includes("-merge-"));
632
+
633
+ // Derive merge session name from lane session naming pattern.
634
+ // Lane sessions: "{prefix}-{opId}-lane-{N}", merge sessions: "{prefix}-{opId}-merge-{N}".
635
+ // Extract the prefix-opId part from the first lane and use it to construct merge names.
636
+ const lanes = batch?.lanes || [];
637
+ let mergePrefix = "orch-merge"; // fallback for legacy/unknown patterns
638
+ if (lanes.length > 0 && lanes[0].tmuxSessionName) {
639
+ const laneName = lanes[0].tmuxSessionName;
640
+ const laneMatch = laneName.match(/^(.+)-lane-\d+$/);
641
+ if (laneMatch) {
642
+ mergePrefix = laneMatch[1] + "-merge";
643
+ }
644
+ }
645
+ // Helper: get merge session name for a lane number
646
+ const getMergeSessionName = (laneNum) => `${mergePrefix}-${laneNum}`;
632
647
 
633
648
  if (mergeResults.length === 0 && mergeSessions.length === 0) {
634
649
  $mergeBody.innerHTML = '<div class="empty-state">No merge agents active</div>';
@@ -639,6 +654,9 @@ function renderMergeAgents(batch, tmuxSessions) {
639
654
  html += '<th>Wave</th><th>Status</th><th>Session</th><th>Telemetry</th><th>Attach</th><th>Details</th>';
640
655
  html += '</tr></thead><tbody>';
641
656
 
657
+ // Track sessions shown in wave result rows so we don't duplicate them below
658
+ const shownSessions = new Set();
659
+
642
660
  // Show merge results
643
661
  for (const mr of mergeResults) {
644
662
  // Repo filtering: if a repo is selected and this merge has repoResults,
@@ -653,12 +671,19 @@ function renderMergeAgents(batch, tmuxSessions) {
653
671
  : mr.status === "partial" ? "status-stalled"
654
672
  : "status-failed";
655
673
 
656
- // Look for matching tmux session
657
- const sessionName = `orch-merge-w${mr.waveIndex + 1}`;
658
- const alive = tmuxSet.has(sessionName);
659
-
660
- // Look for merge telemetry data
661
- const mergeTel = telemetry[sessionName] || telemetry[`orch-merge-${mr.waveIndex + 1}`] || null;
674
+ // Look for matching tmux merge sessions for this wave result.
675
+ // Merge sessions follow the naming pattern: {prefix}-{opId}-merge-{laneNumber}
676
+ // (e.g., "orch-henrylach-merge-1"). Find any alive merge sessions.
677
+ const waveMergeSessions = mergeSessions.filter(s => tmuxSet.has(s));
678
+ const sessionName = waveMergeSessions.length > 0 ? waveMergeSessions[0] : null;
679
+ const alive = sessionName !== null;
680
+ if (alive) shownSessions.add(sessionName);
681
+
682
+ // Look for merge telemetry data — check all merge sessions
683
+ let mergeTel = null;
684
+ for (const ms of mergeSessions) {
685
+ if (telemetry[ms]) { mergeTel = telemetry[ms]; break; }
686
+ }
662
687
 
663
688
  html += `<tr>`;
664
689
  html += `<td style="font-family:var(--font-mono);">Wave ${mr.waveIndex + 1}</td>`;
@@ -718,8 +743,7 @@ function renderMergeAgents(batch, tmuxSessions) {
718
743
 
719
744
  // Show active merge sessions not yet in results
720
745
  for (const sess of mergeSessions) {
721
- const alreadyShown = mergeResults.some((mr) => `orch-merge-w${mr.waveIndex + 1}` === sess);
722
- if (alreadyShown) continue;
746
+ if (shownSessions.has(sess)) continue;
723
747
 
724
748
  const sessTel = telemetry[sess] || null;
725
749
  const cmd = `tmux attach -t ${sess}`;
@@ -436,6 +436,7 @@ export function buildDashboardViewModel(
436
436
  return {
437
437
  phase: batchState.phase,
438
438
  batchId: batchState.batchId,
439
+ orchBranch: batchState.orchBranch || batchState.baseBranch || "",
439
440
  waveProgress,
440
441
  elapsed,
441
442
  summary,
@@ -684,7 +685,7 @@ export function createOrchWidget(
684
685
  } else if (vm.phase === "merging") {
685
686
  lines.push("");
686
687
  lines.push(truncateToWidth(
687
- theme.fg("accent", " 🔀 Merging lane branches into develop..."),
688
+ theme.fg("accent", ` 🔀 Merging lane branches into ${vm.orchBranch || "orch branch"}...`),
688
689
  width,
689
690
  ));
690
691
  } else if (vm.phase === "paused") {
@@ -1957,6 +1957,7 @@ export interface OrchLaneCardData {
1957
1957
  export interface OrchDashboardViewModel {
1958
1958
  phase: OrchBatchPhase;
1959
1959
  batchId: string;
1960
+ orchBranch: string; // e.g., "orch/henry-20260318T140000" — merge target branch
1960
1961
  waveProgress: string; // e.g., "2/3"
1961
1962
  elapsed: string; // e.g., "2m 14s"
1962
1963
  summary: OrchSummaryCounts;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskplane",
3
- "version": "0.14.0",
3
+ "version": "0.14.1",
4
4
  "description": "AI agent orchestration for pi — parallel task execution with checkpoint discipline",
5
5
  "keywords": [
6
6
  "pi-package",