kantban-cli 0.1.10 → 0.1.12
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/dist/{chunk-ZCUIGFSP.js → chunk-MTPUHYZV.js} +15 -66
- package/dist/chunk-MTPUHYZV.js.map +1 -0
- package/dist/{cron-OKQP6QDF.js → cron-QKX2LAAY.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/{pipeline-HTGCXNPL.js → pipeline-SFXKDLMA.js} +82 -10
- package/dist/pipeline-SFXKDLMA.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-ZCUIGFSP.js.map +0 -1
- package/dist/pipeline-HTGCXNPL.js.map +0 -1
- /package/dist/{cron-OKQP6QDF.js.map → cron-QKX2LAAY.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
RalphLoop,
|
|
3
3
|
cleanupMcpConfig,
|
|
4
4
|
generateMcpConfig
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MTPUHYZV.js";
|
|
6
6
|
|
|
7
7
|
// src/commands/cron.ts
|
|
8
8
|
import { execFile } from "child_process";
|
|
@@ -109,4 +109,4 @@ async function runCron(client, args) {
|
|
|
109
109
|
export {
|
|
110
110
|
runCron
|
|
111
111
|
};
|
|
112
|
-
//# sourceMappingURL=cron-
|
|
112
|
+
//# sourceMappingURL=cron-QKX2LAAY.js.map
|
package/dist/index.js
CHANGED
|
@@ -163,16 +163,16 @@ async function main() {
|
|
|
163
163
|
}
|
|
164
164
|
case "pipeline": {
|
|
165
165
|
if (args[0] === "stop") {
|
|
166
|
-
const { stopPipeline } = await import("./pipeline-
|
|
166
|
+
const { stopPipeline } = await import("./pipeline-SFXKDLMA.js");
|
|
167
167
|
await stopPipeline(args.slice(1));
|
|
168
168
|
} else {
|
|
169
|
-
const { runPipeline } = await import("./pipeline-
|
|
169
|
+
const { runPipeline } = await import("./pipeline-SFXKDLMA.js");
|
|
170
170
|
await runPipeline(client, args);
|
|
171
171
|
}
|
|
172
172
|
break;
|
|
173
173
|
}
|
|
174
174
|
case "cron": {
|
|
175
|
-
const { runCron } = await import("./cron-
|
|
175
|
+
const { runCron } = await import("./cron-QKX2LAAY.js");
|
|
176
176
|
await runCron(client, args);
|
|
177
177
|
break;
|
|
178
178
|
}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
parseStuckDetectionResponse,
|
|
14
14
|
parseTimeout,
|
|
15
15
|
resolveGatesForColumn
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-MTPUHYZV.js";
|
|
17
17
|
|
|
18
18
|
// src/commands/pipeline.ts
|
|
19
19
|
import { spawn as spawn2, execSync } from "child_process";
|
|
@@ -53,6 +53,65 @@ async function cleanupWorktree(worktreeName, exec = defaultExecFile) {
|
|
|
53
53
|
});
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
+
function execPromise(exec, cmd, args) {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
exec(cmd, args, (err, stdout, stderr) => {
|
|
59
|
+
if (err) reject(Object.assign(err, { stdout, stderr }));
|
|
60
|
+
else resolve({ stdout, stderr });
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async function findWorktreeForBranch(exec, branch) {
|
|
65
|
+
try {
|
|
66
|
+
const { stdout } = await execPromise(exec, "git", ["worktree", "list", "--porcelain"]);
|
|
67
|
+
const targetRef = `refs/heads/${branch}`;
|
|
68
|
+
let currentPath = null;
|
|
69
|
+
for (const line of stdout.split("\n")) {
|
|
70
|
+
if (line.startsWith("worktree ")) currentPath = line.slice("worktree ".length);
|
|
71
|
+
if (line.startsWith("branch ") && line.slice("branch ".length) === targetRef && currentPath) {
|
|
72
|
+
return currentPath;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
} catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function mergeWorktreeBranch(worktreeName, integrationBranch, exec = defaultExecFile) {
|
|
81
|
+
try {
|
|
82
|
+
await execPromise(exec, "git", ["branch", integrationBranch, "HEAD"]).catch(() => {
|
|
83
|
+
});
|
|
84
|
+
const checkedOutPath = await findWorktreeForBranch(exec, integrationBranch);
|
|
85
|
+
if (checkedOutPath) {
|
|
86
|
+
await execPromise(exec, "git", ["-C", checkedOutPath, "merge", "--no-edit", worktreeName]);
|
|
87
|
+
console.error(`[worktree] merged ${worktreeName} \u2192 ${integrationBranch}`);
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
const { stdout: baseOut } = await execPromise(exec, "git", ["merge-base", integrationBranch, worktreeName]);
|
|
91
|
+
const mergeBase = baseOut.trim();
|
|
92
|
+
const { stdout: integrationSha } = await execPromise(exec, "git", ["rev-parse", integrationBranch]);
|
|
93
|
+
if (integrationSha.trim() === mergeBase) {
|
|
94
|
+
const { stdout: worktreeSha } = await execPromise(exec, "git", ["rev-parse", worktreeName]);
|
|
95
|
+
await execPromise(exec, "git", ["update-ref", `refs/heads/${integrationBranch}`, worktreeSha.trim()]);
|
|
96
|
+
console.error(`[worktree] fast-forward merged ${worktreeName} \u2192 ${integrationBranch}`);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
const tmpWorktree = `merge-tmp-${Date.now()}`;
|
|
100
|
+
try {
|
|
101
|
+
await execPromise(exec, "git", ["worktree", "add", tmpWorktree, integrationBranch]);
|
|
102
|
+
await execPromise(exec, "git", ["-C", tmpWorktree, "merge", "--no-edit", worktreeName]);
|
|
103
|
+
console.error(`[worktree] merged ${worktreeName} \u2192 ${integrationBranch}`);
|
|
104
|
+
} finally {
|
|
105
|
+
await execPromise(exec, "git", ["worktree", "remove", "--force", tmpWorktree]).catch(() => {
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
} catch (err) {
|
|
110
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
111
|
+
console.error(`[worktree] merge failed for ${worktreeName} \u2192 ${integrationBranch}: ${msg}`);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
56
115
|
|
|
57
116
|
// src/lib/constraint-evaluator.ts
|
|
58
117
|
function resolveColumn(board, columnId, subjectRef) {
|
|
@@ -457,6 +516,7 @@ var PipelineOrchestrator = class {
|
|
|
457
516
|
worktreeEnabled: cfg?.worktree?.enabled,
|
|
458
517
|
worktreeOnMove: cfg?.worktree?.on_move,
|
|
459
518
|
worktreeOnDone: cfg?.worktree?.on_done,
|
|
519
|
+
worktreeIntegrationBranch: cfg?.worktree?.integration_branch,
|
|
460
520
|
invocationTier: cfg?.invocation_tier,
|
|
461
521
|
lookaheadColumnId: cfg?.lookahead_column_id,
|
|
462
522
|
runMemory: cfg?.run_memory,
|
|
@@ -1597,18 +1657,28 @@ ${findingsText}`)
|
|
|
1597
1657
|
);
|
|
1598
1658
|
}
|
|
1599
1659
|
const isTerminal = result.reason === "moved" || result.reason === "max_iterations" || result.reason === "error" || result.reason === "stalled" || result.reason === "stopped" || result.reason === "deleted";
|
|
1600
|
-
if (isTerminal && colConfig
|
|
1660
|
+
if (isTerminal && colConfig) {
|
|
1601
1661
|
const colScope2 = this.columnScopes.get(columnId);
|
|
1602
1662
|
const ticket2 = colScope2?.tickets.find((t) => t.id === ticketId);
|
|
1603
1663
|
if (ticket2) {
|
|
1604
1664
|
const worktreeName = generateWorktreeName(ticket2.ticket_number, colConfig.name);
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1665
|
+
if (colConfig.worktreeOnDone === "merge" && colConfig.worktreeIntegrationBranch && this.deps.mergeWorktree) {
|
|
1666
|
+
void this.deps.mergeWorktree(worktreeName, colConfig.worktreeIntegrationBranch).then((success) => {
|
|
1667
|
+
if (!success) {
|
|
1668
|
+
console.error(` [warn] Worktree merge failed for ${worktreeName} \u2192 ${colConfig.worktreeIntegrationBranch} \u2014 may need manual resolution`);
|
|
1669
|
+
}
|
|
1670
|
+
}).catch((err) => {
|
|
1671
|
+
console.error(` [warn] Worktree merge error for ${worktreeName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1672
|
+
});
|
|
1673
|
+
} else if (colConfig.worktreeOnDone === "cleanup" && this.deps.cleanupWorktree) {
|
|
1674
|
+
void this.deps.cleanupWorktree(worktreeName).then((success) => {
|
|
1675
|
+
if (!success) {
|
|
1676
|
+
console.error(` [warn] Worktree cleanup failed for ${worktreeName} \u2014 may need manual removal`);
|
|
1677
|
+
}
|
|
1678
|
+
}).catch((err) => {
|
|
1679
|
+
console.error(` [warn] Worktree cleanup error for ${worktreeName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1680
|
+
});
|
|
1681
|
+
}
|
|
1612
1682
|
}
|
|
1613
1683
|
}
|
|
1614
1684
|
this.deps.gateSnapshotStore?.clear(ticketId);
|
|
@@ -3643,6 +3713,7 @@ async function runPipeline(client, args) {
|
|
|
3643
3713
|
moveTicketToColumn: async (ticketId, columnId, handoff) => {
|
|
3644
3714
|
await client.patch(`/projects/${projectId}/tickets/${ticketId}/move`, {
|
|
3645
3715
|
column_id: columnId,
|
|
3716
|
+
position: 0,
|
|
3646
3717
|
handoff
|
|
3647
3718
|
});
|
|
3648
3719
|
},
|
|
@@ -3663,6 +3734,7 @@ async function runPipeline(client, args) {
|
|
|
3663
3734
|
// Run memory append — closure captures runMemory by reference (set after initialization)
|
|
3664
3735
|
appendRunMemory: (section, content) => runMemory ? runMemory.append(section, content) : Promise.resolve(),
|
|
3665
3736
|
cleanupWorktree: (name) => cleanupWorktree(name),
|
|
3737
|
+
mergeWorktree: (name, integrationBranch) => mergeWorktreeBranch(name, integrationBranch),
|
|
3666
3738
|
// Pipeline event emission — wsClient captured by reference (set later before any loops run)
|
|
3667
3739
|
emitPipelineEvent: (event) => {
|
|
3668
3740
|
wsClient?.send(event);
|
|
@@ -4046,4 +4118,4 @@ export {
|
|
|
4046
4118
|
runPipeline,
|
|
4047
4119
|
stopPipeline
|
|
4048
4120
|
};
|
|
4049
|
-
//# sourceMappingURL=pipeline-
|
|
4121
|
+
//# sourceMappingURL=pipeline-SFXKDLMA.js.map
|