kantban-cli 0.1.8 → 0.1.11
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 +4111 -0
- package/dist/chunk-ZCUIGFSP.js.map +1 -0
- package/dist/context-7YDNTI3P.js +30 -0
- package/dist/context-7YDNTI3P.js.map +1 -0
- package/dist/cron-OKQP6QDF.js +112 -0
- package/dist/cron-OKQP6QDF.js.map +1 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.js +179 -44
- package/dist/index.js.map +1 -1
- package/dist/pipeline-7LG74YA2.js +4098 -0
- package/dist/pipeline-7LG74YA2.js.map +1 -0
- package/dist/pipeline-init-IGZZOOLK.js +103 -0
- package/dist/pipeline-init-IGZZOOLK.js.map +1 -0
- package/dist/status-4GFXMVIM.js +128 -0
- package/dist/status-4GFXMVIM.js.map +1 -0
- package/dist/work-2V33NZAT.js +81 -0
- package/dist/work-2V33NZAT.js.map +1 -0
- package/package.json +5 -4
- package/dist/client.d.ts +0 -38
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -163
- package/dist/client.js.map +0 -1
- package/dist/commands/context.d.ts +0 -3
- package/dist/commands/context.d.ts.map +0 -1
- package/dist/commands/context.js +0 -27
- package/dist/commands/context.js.map +0 -1
- package/dist/commands/cron.d.ts +0 -3
- package/dist/commands/cron.d.ts.map +0 -1
- package/dist/commands/cron.js +0 -106
- package/dist/commands/cron.js.map +0 -1
- package/dist/commands/pipeline-init.d.ts +0 -2
- package/dist/commands/pipeline-init.d.ts.map +0 -1
- package/dist/commands/pipeline-init.js +0 -100
- package/dist/commands/pipeline-init.js.map +0 -1
- package/dist/commands/pipeline.d.ts +0 -4
- package/dist/commands/pipeline.d.ts.map +0 -1
- package/dist/commands/pipeline.js +0 -1222
- package/dist/commands/pipeline.js.map +0 -1
- package/dist/commands/status.d.ts +0 -3
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js +0 -135
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/work.d.ts +0 -3
- package/dist/commands/work.d.ts.map +0 -1
- package/dist/commands/work.js +0 -76
- package/dist/commands/work.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/advisor.d.ts +0 -108
- package/dist/lib/advisor.d.ts.map +0 -1
- package/dist/lib/advisor.js +0 -139
- package/dist/lib/advisor.js.map +0 -1
- package/dist/lib/checkpoint.d.ts +0 -15
- package/dist/lib/checkpoint.d.ts.map +0 -1
- package/dist/lib/checkpoint.js +0 -49
- package/dist/lib/checkpoint.js.map +0 -1
- package/dist/lib/constraint-evaluator.d.ts +0 -40
- package/dist/lib/constraint-evaluator.d.ts.map +0 -1
- package/dist/lib/constraint-evaluator.js +0 -189
- package/dist/lib/constraint-evaluator.js.map +0 -1
- package/dist/lib/cost-tracker.d.ts +0 -46
- package/dist/lib/cost-tracker.d.ts.map +0 -1
- package/dist/lib/cost-tracker.js +0 -120
- package/dist/lib/cost-tracker.js.map +0 -1
- package/dist/lib/evaluator.d.ts +0 -17
- package/dist/lib/evaluator.d.ts.map +0 -1
- package/dist/lib/evaluator.js +0 -71
- package/dist/lib/evaluator.js.map +0 -1
- package/dist/lib/event-emitter.d.ts +0 -28
- package/dist/lib/event-emitter.d.ts.map +0 -1
- package/dist/lib/event-emitter.js +0 -100
- package/dist/lib/event-emitter.js.map +0 -1
- package/dist/lib/event-queue.d.ts +0 -28
- package/dist/lib/event-queue.d.ts.map +0 -1
- package/dist/lib/event-queue.js +0 -73
- package/dist/lib/event-queue.js.map +0 -1
- package/dist/lib/gate-config.d.ts +0 -7
- package/dist/lib/gate-config.d.ts.map +0 -1
- package/dist/lib/gate-config.js +0 -68
- package/dist/lib/gate-config.js.map +0 -1
- package/dist/lib/gate-proxy-server.d.ts +0 -16
- package/dist/lib/gate-proxy-server.d.ts.map +0 -1
- package/dist/lib/gate-proxy-server.js +0 -385
- package/dist/lib/gate-proxy-server.js.map +0 -1
- package/dist/lib/gate-proxy.d.ts +0 -46
- package/dist/lib/gate-proxy.d.ts.map +0 -1
- package/dist/lib/gate-proxy.js +0 -104
- package/dist/lib/gate-proxy.js.map +0 -1
- package/dist/lib/gate-runner.d.ts +0 -13
- package/dist/lib/gate-runner.d.ts.map +0 -1
- package/dist/lib/gate-runner.js +0 -104
- package/dist/lib/gate-runner.js.map +0 -1
- package/dist/lib/gate-snapshot.d.ts +0 -12
- package/dist/lib/gate-snapshot.d.ts.map +0 -1
- package/dist/lib/gate-snapshot.js +0 -49
- package/dist/lib/gate-snapshot.js.map +0 -1
- package/dist/lib/light-call.d.ts +0 -37
- package/dist/lib/light-call.d.ts.map +0 -1
- package/dist/lib/light-call.js +0 -62
- package/dist/lib/light-call.js.map +0 -1
- package/dist/lib/logger.d.ts +0 -22
- package/dist/lib/logger.d.ts.map +0 -1
- package/dist/lib/logger.js +0 -98
- package/dist/lib/logger.js.map +0 -1
- package/dist/lib/mcp-config.d.ts +0 -24
- package/dist/lib/mcp-config.d.ts.map +0 -1
- package/dist/lib/mcp-config.js +0 -115
- package/dist/lib/mcp-config.js.map +0 -1
- package/dist/lib/orchestrator.d.ts +0 -392
- package/dist/lib/orchestrator.d.ts.map +0 -1
- package/dist/lib/orchestrator.js +0 -1636
- package/dist/lib/orchestrator.js.map +0 -1
- package/dist/lib/parse-utils.d.ts +0 -6
- package/dist/lib/parse-utils.d.ts.map +0 -1
- package/dist/lib/parse-utils.js +0 -64
- package/dist/lib/parse-utils.js.map +0 -1
- package/dist/lib/prompt-composer.d.ts +0 -131
- package/dist/lib/prompt-composer.d.ts.map +0 -1
- package/dist/lib/prompt-composer.js +0 -317
- package/dist/lib/prompt-composer.js.map +0 -1
- package/dist/lib/ralph-loop.d.ts +0 -123
- package/dist/lib/ralph-loop.d.ts.map +0 -1
- package/dist/lib/ralph-loop.js +0 -383
- package/dist/lib/ralph-loop.js.map +0 -1
- package/dist/lib/reaper.d.ts +0 -14
- package/dist/lib/reaper.d.ts.map +0 -1
- package/dist/lib/reaper.js +0 -114
- package/dist/lib/reaper.js.map +0 -1
- package/dist/lib/replanner.d.ts +0 -49
- package/dist/lib/replanner.d.ts.map +0 -1
- package/dist/lib/replanner.js +0 -61
- package/dist/lib/replanner.js.map +0 -1
- package/dist/lib/run-memory.d.ts +0 -37
- package/dist/lib/run-memory.d.ts.map +0 -1
- package/dist/lib/run-memory.js +0 -115
- package/dist/lib/run-memory.js.map +0 -1
- package/dist/lib/stream-parser.d.ts +0 -20
- package/dist/lib/stream-parser.d.ts.map +0 -1
- package/dist/lib/stream-parser.js +0 -65
- package/dist/lib/stream-parser.js.map +0 -1
- package/dist/lib/stuck-detector.d.ts +0 -47
- package/dist/lib/stuck-detector.d.ts.map +0 -1
- package/dist/lib/stuck-detector.js +0 -105
- package/dist/lib/stuck-detector.js.map +0 -1
- package/dist/lib/tool-profiles.d.ts +0 -19
- package/dist/lib/tool-profiles.d.ts.map +0 -1
- package/dist/lib/tool-profiles.js +0 -22
- package/dist/lib/tool-profiles.js.map +0 -1
- package/dist/lib/worktree.d.ts +0 -12
- package/dist/lib/worktree.d.ts.map +0 -1
- package/dist/lib/worktree.js +0 -29
- package/dist/lib/worktree.js.map +0 -1
- package/dist/lib/ws-client.d.ts +0 -31
- package/dist/lib/ws-client.d.ts.map +0 -1
- package/dist/lib/ws-client.js +0 -113
- package/dist/lib/ws-client.js.map +0 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// src/commands/pipeline-init.ts
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
var GATE_FILE = "pipeline.gates.yaml";
|
|
5
|
+
function detectProjectType(cwd) {
|
|
6
|
+
if (existsSync(join(cwd, "package.json"))) {
|
|
7
|
+
const pkg = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8"));
|
|
8
|
+
const scripts = pkg.scripts ?? {};
|
|
9
|
+
const pm = existsSync(join(cwd, "pnpm-lock.yaml")) ? "pnpm" : existsSync(join(cwd, "yarn.lock")) ? "yarn" : "npm";
|
|
10
|
+
return {
|
|
11
|
+
type: "node",
|
|
12
|
+
testCommand: scripts.test ? `${pm} test` : `${pm} vitest run`,
|
|
13
|
+
typecheckCommand: scripts.typecheck ? `${pm} typecheck` : `${pm} tsc --noEmit`,
|
|
14
|
+
lintCommand: scripts.lint ? `${pm} lint` : `${pm} eslint .`,
|
|
15
|
+
buildCommand: scripts.build ? `${pm} build` : 'echo "no build configured"'
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (existsSync(join(cwd, "Cargo.toml"))) {
|
|
19
|
+
return { type: "rust", testCommand: "cargo test", typecheckCommand: "cargo check", lintCommand: "cargo clippy", buildCommand: "cargo build" };
|
|
20
|
+
}
|
|
21
|
+
if (existsSync(join(cwd, "pyproject.toml")) || existsSync(join(cwd, "setup.py"))) {
|
|
22
|
+
return { type: "python", testCommand: "pytest", typecheckCommand: "mypy .", lintCommand: "ruff check .", buildCommand: 'echo "no build configured"' };
|
|
23
|
+
}
|
|
24
|
+
if (existsSync(join(cwd, "go.mod"))) {
|
|
25
|
+
return { type: "go", testCommand: "go test ./...", typecheckCommand: "go vet ./...", lintCommand: "golangci-lint run", buildCommand: "go build ./..." };
|
|
26
|
+
}
|
|
27
|
+
return { type: "unknown", testCommand: 'echo "configure your test command"', typecheckCommand: 'echo "configure your typecheck command"', lintCommand: 'echo "configure your lint command"', buildCommand: 'echo "configure your build command"' };
|
|
28
|
+
}
|
|
29
|
+
function yamlQuote(s) {
|
|
30
|
+
return `'${s.replace(/'/g, "''")}'`;
|
|
31
|
+
}
|
|
32
|
+
function generateGateFile(detection) {
|
|
33
|
+
return `# pipeline.gates.yaml \u2014 Gate definitions for KantBan pipeline
|
|
34
|
+
# Detected project type: ${detection.type}
|
|
35
|
+
#
|
|
36
|
+
# Gates are shell commands that produce pass/fail results.
|
|
37
|
+
# Required gates block ticket movement. Advisory gates show output but don't block.
|
|
38
|
+
|
|
39
|
+
default:
|
|
40
|
+
- name: typecheck
|
|
41
|
+
run: ${yamlQuote(detection.typecheckCommand)}
|
|
42
|
+
required: true
|
|
43
|
+
timeout: 60s
|
|
44
|
+
|
|
45
|
+
- name: tests
|
|
46
|
+
run: ${yamlQuote(detection.testCommand)}
|
|
47
|
+
required: true
|
|
48
|
+
timeout: 120s
|
|
49
|
+
|
|
50
|
+
- name: lint
|
|
51
|
+
run: ${yamlQuote(detection.lintCommand)}
|
|
52
|
+
required: false # advisory \u2014 output shown but doesn't block
|
|
53
|
+
|
|
54
|
+
# Column-specific overrides \u2014 matched by column name (case-insensitive)
|
|
55
|
+
# columns:
|
|
56
|
+
# implementation:
|
|
57
|
+
# extend: true # inherit default gates, add more
|
|
58
|
+
# gates:
|
|
59
|
+
# - name: build
|
|
60
|
+
# run: ${yamlQuote(detection.buildCommand)}
|
|
61
|
+
# required: true
|
|
62
|
+
# timeout: 120s
|
|
63
|
+
#
|
|
64
|
+
# qa:
|
|
65
|
+
# extend: false # replace default gates entirely
|
|
66
|
+
# gates:
|
|
67
|
+
# - name: e2e
|
|
68
|
+
# run: "echo 'configure your e2e test command'"
|
|
69
|
+
# required: true
|
|
70
|
+
# timeout: 300s
|
|
71
|
+
|
|
72
|
+
settings:
|
|
73
|
+
# cwd: .
|
|
74
|
+
env:
|
|
75
|
+
CI: "true"
|
|
76
|
+
total_timeout: 300s
|
|
77
|
+
budget:
|
|
78
|
+
max_input_tokens: 5000000
|
|
79
|
+
max_output_tokens: 1500000
|
|
80
|
+
warn_pct: 75
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
async function runPipelineInit() {
|
|
84
|
+
const cwd = process.cwd();
|
|
85
|
+
const filePath = join(cwd, GATE_FILE);
|
|
86
|
+
if (existsSync(filePath)) {
|
|
87
|
+
console.error(`Error: ${GATE_FILE} already exists in ${cwd}`);
|
|
88
|
+
console.error("Edit the existing file or delete it to regenerate.");
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
const detection = detectProjectType(cwd);
|
|
92
|
+
const content = generateGateFile(detection);
|
|
93
|
+
writeFileSync(filePath, content);
|
|
94
|
+
console.log(`Created ${GATE_FILE} (detected: ${detection.type} project)`);
|
|
95
|
+
console.log(`
|
|
96
|
+
Next steps:`);
|
|
97
|
+
console.log(` 1. Review and customize the gate file`);
|
|
98
|
+
console.log(` 2. Run: kantban pipeline <board-id>`);
|
|
99
|
+
}
|
|
100
|
+
export {
|
|
101
|
+
runPipelineInit
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=pipeline-init-IGZZOOLK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/pipeline-init.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst GATE_FILE = 'pipeline.gates.yaml';\n\ninterface ProjectDetection {\n type: string;\n testCommand: string;\n typecheckCommand: string;\n lintCommand: string;\n buildCommand: string;\n}\n\nfunction detectProjectType(cwd: string): ProjectDetection {\n if (existsSync(join(cwd, 'package.json'))) {\n const pkg = JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf-8')) as {\n scripts?: Record<string, string>;\n };\n const scripts = pkg.scripts ?? {};\n const pm = existsSync(join(cwd, 'pnpm-lock.yaml')) ? 'pnpm'\n : existsSync(join(cwd, 'yarn.lock')) ? 'yarn' : 'npm';\n return {\n type: 'node',\n testCommand: scripts.test ? `${pm} test` : `${pm} vitest run`,\n typecheckCommand: scripts.typecheck ? `${pm} typecheck` : `${pm} tsc --noEmit`,\n lintCommand: scripts.lint ? `${pm} lint` : `${pm} eslint .`,\n buildCommand: scripts.build ? `${pm} build` : 'echo \"no build configured\"',\n };\n }\n if (existsSync(join(cwd, 'Cargo.toml'))) {\n return { type: 'rust', testCommand: 'cargo test', typecheckCommand: 'cargo check', lintCommand: 'cargo clippy', buildCommand: 'cargo build' };\n }\n if (existsSync(join(cwd, 'pyproject.toml')) || existsSync(join(cwd, 'setup.py'))) {\n return { type: 'python', testCommand: 'pytest', typecheckCommand: 'mypy .', lintCommand: 'ruff check .', buildCommand: 'echo \"no build configured\"' };\n }\n if (existsSync(join(cwd, 'go.mod'))) {\n return { type: 'go', testCommand: 'go test ./...', typecheckCommand: 'go vet ./...', lintCommand: 'golangci-lint run', buildCommand: 'go build ./...' };\n }\n return { type: 'unknown', testCommand: 'echo \"configure your test command\"', typecheckCommand: 'echo \"configure your typecheck command\"', lintCommand: 'echo \"configure your lint command\"', buildCommand: 'echo \"configure your build command\"' };\n}\n\n/** YAML-safe single-quoting: escapes internal single quotes by doubling them */\nfunction yamlQuote(s: string): string {\n return `'${s.replace(/'/g, \"''\")}'`;\n}\n\nfunction generateGateFile(detection: ProjectDetection): string {\n return `# pipeline.gates.yaml — Gate definitions for KantBan pipeline\n# Detected project type: ${detection.type}\n#\n# Gates are shell commands that produce pass/fail results.\n# Required gates block ticket movement. Advisory gates show output but don't block.\n\ndefault:\n - name: typecheck\n run: ${yamlQuote(detection.typecheckCommand)}\n required: true\n timeout: 60s\n\n - name: tests\n run: ${yamlQuote(detection.testCommand)}\n required: true\n timeout: 120s\n\n - name: lint\n run: ${yamlQuote(detection.lintCommand)}\n required: false # advisory — output shown but doesn't block\n\n# Column-specific overrides — matched by column name (case-insensitive)\n# columns:\n# implementation:\n# extend: true # inherit default gates, add more\n# gates:\n# - name: build\n# run: ${yamlQuote(detection.buildCommand)}\n# required: true\n# timeout: 120s\n#\n# qa:\n# extend: false # replace default gates entirely\n# gates:\n# - name: e2e\n# run: \"echo 'configure your e2e test command'\"\n# required: true\n# timeout: 300s\n\nsettings:\n # cwd: .\n env:\n CI: \"true\"\n total_timeout: 300s\n budget:\n max_input_tokens: 5000000\n max_output_tokens: 1500000\n warn_pct: 75\n`;\n}\n\nexport async function runPipelineInit(): Promise<void> {\n const cwd = process.cwd();\n const filePath = join(cwd, GATE_FILE);\n\n if (existsSync(filePath)) {\n console.error(`Error: ${GATE_FILE} already exists in ${cwd}`);\n console.error('Edit the existing file or delete it to regenerate.');\n process.exit(1);\n }\n\n const detection = detectProjectType(cwd);\n const content = generateGateFile(detection);\n writeFileSync(filePath, content);\n\n console.log(`Created ${GATE_FILE} (detected: ${detection.type} project)`);\n console.log(`\\nNext steps:`);\n console.log(` 1. Review and customize the gate file`);\n console.log(` 2. Run: kantban pipeline <board-id>`);\n}\n"],"mappings":";AAAA,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,YAAY;AAErB,IAAM,YAAY;AAUlB,SAAS,kBAAkB,KAA+B;AACxD,MAAI,WAAW,KAAK,KAAK,cAAc,CAAC,GAAG;AACzC,UAAM,MAAM,KAAK,MAAM,aAAa,KAAK,KAAK,cAAc,GAAG,OAAO,CAAC;AAGvE,UAAM,UAAU,IAAI,WAAW,CAAC;AAChC,UAAM,KAAK,WAAW,KAAK,KAAK,gBAAgB,CAAC,IAAI,SACjD,WAAW,KAAK,KAAK,WAAW,CAAC,IAAI,SAAS;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa,QAAQ,OAAO,GAAG,EAAE,UAAU,GAAG,EAAE;AAAA,MAChD,kBAAkB,QAAQ,YAAY,GAAG,EAAE,eAAe,GAAG,EAAE;AAAA,MAC/D,aAAa,QAAQ,OAAO,GAAG,EAAE,UAAU,GAAG,EAAE;AAAA,MAChD,cAAc,QAAQ,QAAQ,GAAG,EAAE,WAAW;AAAA,IAChD;AAAA,EACF;AACA,MAAI,WAAW,KAAK,KAAK,YAAY,CAAC,GAAG;AACvC,WAAO,EAAE,MAAM,QAAQ,aAAa,cAAc,kBAAkB,eAAe,aAAa,gBAAgB,cAAc,cAAc;AAAA,EAC9I;AACA,MAAI,WAAW,KAAK,KAAK,gBAAgB,CAAC,KAAK,WAAW,KAAK,KAAK,UAAU,CAAC,GAAG;AAChF,WAAO,EAAE,MAAM,UAAU,aAAa,UAAU,kBAAkB,UAAU,aAAa,gBAAgB,cAAc,6BAA6B;AAAA,EACtJ;AACA,MAAI,WAAW,KAAK,KAAK,QAAQ,CAAC,GAAG;AACnC,WAAO,EAAE,MAAM,MAAM,aAAa,iBAAiB,kBAAkB,gBAAgB,aAAa,qBAAqB,cAAc,iBAAiB;AAAA,EACxJ;AACA,SAAO,EAAE,MAAM,WAAW,aAAa,sCAAsC,kBAAkB,2CAA2C,aAAa,sCAAsC,cAAc,sCAAsC;AACnP;AAGA,SAAS,UAAU,GAAmB;AACpC,SAAO,IAAI,EAAE,QAAQ,MAAM,IAAI,CAAC;AAClC;AAEA,SAAS,iBAAiB,WAAqC;AAC7D,SAAO;AAAA,2BACkB,UAAU,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAO9B,UAAU,UAAU,gBAAgB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,WAKrC,UAAU,UAAU,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,WAKhC,UAAU,UAAU,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAS1B,UAAU,UAAU,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBlD;AAEA,eAAsB,kBAAiC;AACrD,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,WAAW,KAAK,KAAK,SAAS;AAEpC,MAAI,WAAW,QAAQ,GAAG;AACxB,YAAQ,MAAM,UAAU,SAAS,sBAAsB,GAAG,EAAE;AAC5D,YAAQ,MAAM,oDAAoD;AAClE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAY,kBAAkB,GAAG;AACvC,QAAM,UAAU,iBAAiB,SAAS;AAC1C,gBAAc,UAAU,OAAO;AAE/B,UAAQ,IAAI,WAAW,SAAS,eAAe,UAAU,IAAI,WAAW;AACxE,UAAQ,IAAI;AAAA,YAAe;AAC3B,UAAQ,IAAI,yCAAyC;AACrD,UAAQ,IAAI,uCAAuC;AACrD;","names":[]}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// src/commands/status.ts
|
|
2
|
+
import { readFileSync, existsSync, statSync, readdirSync } from "fs";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
function formatUptime(ms) {
|
|
6
|
+
const totalMinutes = Math.floor(ms / 6e4);
|
|
7
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
8
|
+
const minutes = totalMinutes % 60;
|
|
9
|
+
if (hours > 0) return `${String(hours)}h ${String(minutes)}m`;
|
|
10
|
+
return `${String(minutes)}m`;
|
|
11
|
+
}
|
|
12
|
+
function isProcessRunning(pid) {
|
|
13
|
+
try {
|
|
14
|
+
process.kill(pid, 0);
|
|
15
|
+
return true;
|
|
16
|
+
} catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function showPipelineInfo(boardId) {
|
|
21
|
+
const pipelineDir = join(homedir(), ".kantban", "pipelines", boardId);
|
|
22
|
+
const pidFile = join(pipelineDir, "orchestrator.pid");
|
|
23
|
+
if (!existsSync(pidFile)) {
|
|
24
|
+
console.log("\nPipeline: not running");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const pidContent = readFileSync(pidFile, "utf8").trim();
|
|
28
|
+
const pid = Number(pidContent);
|
|
29
|
+
if (isNaN(pid) || pid <= 0) {
|
|
30
|
+
console.log("\nOrchestrator: not running (invalid PID file)");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!isProcessRunning(pid)) {
|
|
34
|
+
console.log("\nOrchestrator: not running (stale PID file)");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const pidStat = statSync(pidFile);
|
|
38
|
+
const uptimeMs = Date.now() - pidStat.mtimeMs;
|
|
39
|
+
console.log(`
|
|
40
|
+
Orchestrator: running (PID: ${String(pid)}, uptime: ${formatUptime(uptimeMs)})`);
|
|
41
|
+
if (!existsSync(pipelineDir)) return;
|
|
42
|
+
const entries = readdirSync(pipelineDir, { withFileTypes: true });
|
|
43
|
+
const ticketDirs = entries.filter((e) => e.isDirectory());
|
|
44
|
+
if (ticketDirs.length === 0) return;
|
|
45
|
+
const recentLoops = [];
|
|
46
|
+
for (const dir of ticketDirs) {
|
|
47
|
+
const ticketDir = join(pipelineDir, dir.name);
|
|
48
|
+
const files = readdirSync(ticketDir).filter((f) => f.startsWith("iteration-") && f.endsWith(".log"));
|
|
49
|
+
if (files.length === 0) continue;
|
|
50
|
+
files.sort();
|
|
51
|
+
const latestFile = files[files.length - 1];
|
|
52
|
+
const logPath = join(ticketDir, latestFile);
|
|
53
|
+
try {
|
|
54
|
+
const logContent = readFileSync(logPath, "utf8");
|
|
55
|
+
const logData = JSON.parse(logContent);
|
|
56
|
+
recentLoops.push({
|
|
57
|
+
ticket: dir.name,
|
|
58
|
+
lastIteration: Number(logData["iteration"] ?? 0),
|
|
59
|
+
outcome: String(logData["outcome"] ?? "unknown"),
|
|
60
|
+
timestamp: String(logData["timestamp"] ?? "")
|
|
61
|
+
});
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (recentLoops.length > 0) {
|
|
66
|
+
recentLoops.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
67
|
+
console.log(` Active/recent loops (${String(recentLoops.length)}):`);
|
|
68
|
+
for (const loop of recentLoops.slice(0, 10)) {
|
|
69
|
+
console.log(` ${loop.ticket} iter:${String(loop.lastIteration)} ${loop.outcome}`);
|
|
70
|
+
}
|
|
71
|
+
if (recentLoops.length > 10) {
|
|
72
|
+
console.log(` ... and ${String(recentLoops.length - 10)} more`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function runStatus(client, args) {
|
|
77
|
+
const [boardId] = args;
|
|
78
|
+
if (!boardId) {
|
|
79
|
+
console.error("Usage: kantban status <board-id>");
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
const projectId = process.env["KANTBAN_PROJECT_ID"];
|
|
83
|
+
if (!projectId) {
|
|
84
|
+
console.error("Error: KANTBAN_PROJECT_ID required");
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
const data = await client.get(
|
|
88
|
+
`/projects/${projectId}/pipeline-context`,
|
|
89
|
+
{ boardId }
|
|
90
|
+
);
|
|
91
|
+
const columns = data["columns"];
|
|
92
|
+
const cb = data["circuit_breaker"];
|
|
93
|
+
const board = data["board"];
|
|
94
|
+
console.log(`Pipeline Status: ${board?.["name"] ?? "Unknown Board"}`);
|
|
95
|
+
console.log("\u2500".repeat(60));
|
|
96
|
+
if (columns) {
|
|
97
|
+
for (const col of columns) {
|
|
98
|
+
const prompt = col["has_prompt"] ? "\u{1F4C4}" : " ";
|
|
99
|
+
const name = String(col["name"] ?? "(unnamed)");
|
|
100
|
+
const count = Number(col["ticket_count"] ?? 0);
|
|
101
|
+
const goal = col["goal"] ? ` \u2014 ${String(col["goal"])}` : "";
|
|
102
|
+
console.log(`${prompt} ${name} (${count} tickets)${goal}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (cb?.["threshold"]) {
|
|
106
|
+
console.log(`
|
|
107
|
+
Circuit Breaker: threshold=${String(cb["threshold"])}`);
|
|
108
|
+
}
|
|
109
|
+
const bottlenecks = await client.get(
|
|
110
|
+
`/projects/${projectId}/boards/${boardId}/bottlenecks`
|
|
111
|
+
);
|
|
112
|
+
const stuckCount = bottlenecks["stuck_tickets"]?.length ?? 0;
|
|
113
|
+
const wipCount = bottlenecks["wip_violations"]?.length ?? 0;
|
|
114
|
+
if (stuckCount > 0 || wipCount > 0) {
|
|
115
|
+
console.log(`
|
|
116
|
+
Warnings: ${stuckCount} stuck, ${wipCount} WIP violations`);
|
|
117
|
+
} else {
|
|
118
|
+
console.log("\nAll clear.");
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
showPipelineInfo(boardId);
|
|
122
|
+
} catch {
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
runStatus
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=status-4GFXMVIM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/status.ts"],"sourcesContent":["import { readFileSync, existsSync, statSync, readdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { KantBanCLIClient } from '../client.js';\n\n// ---------------------------------------------------------------------------\n// Pipeline runtime info helper\n// ---------------------------------------------------------------------------\n\nfunction formatUptime(ms: number): string {\n const totalMinutes = Math.floor(ms / 60_000);\n const hours = Math.floor(totalMinutes / 60);\n const minutes = totalMinutes % 60;\n if (hours > 0) return `${String(hours)}h ${String(minutes)}m`;\n return `${String(minutes)}m`;\n}\n\nfunction isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction showPipelineInfo(boardId: string): void {\n const pipelineDir = join(homedir(), '.kantban', 'pipelines', boardId);\n const pidFile = join(pipelineDir, 'orchestrator.pid');\n\n if (!existsSync(pidFile)) {\n console.log('\\nPipeline: not running');\n return;\n }\n\n const pidContent = readFileSync(pidFile, 'utf8').trim();\n const pid = Number(pidContent);\n if (isNaN(pid) || pid <= 0) {\n console.log('\\nOrchestrator: not running (invalid PID file)');\n return;\n }\n\n if (!isProcessRunning(pid)) {\n console.log('\\nOrchestrator: not running (stale PID file)');\n return;\n }\n\n // Process is running — calculate uptime from PID file mtime\n const pidStat = statSync(pidFile);\n const uptimeMs = Date.now() - pidStat.mtimeMs;\n console.log(`\\nOrchestrator: running (PID: ${String(pid)}, uptime: ${formatUptime(uptimeMs)})`);\n\n // Scan for recent iteration logs to show active/recent loop info\n if (!existsSync(pipelineDir)) return;\n\n const entries = readdirSync(pipelineDir, { withFileTypes: true });\n const ticketDirs = entries.filter((e) => e.isDirectory());\n\n if (ticketDirs.length === 0) return;\n\n const recentLoops: Array<{ ticket: string; lastIteration: number; outcome: string; timestamp: string }> = [];\n\n for (const dir of ticketDirs) {\n const ticketDir = join(pipelineDir, dir.name);\n const files = readdirSync(ticketDir).filter((f) => f.startsWith('iteration-') && f.endsWith('.log'));\n if (files.length === 0) continue;\n\n // Get the latest iteration log\n files.sort();\n const latestFile = files[files.length - 1]!;\n const logPath = join(ticketDir, latestFile);\n\n try {\n const logContent = readFileSync(logPath, 'utf8');\n const logData = JSON.parse(logContent) as Record<string, unknown>;\n recentLoops.push({\n ticket: dir.name,\n lastIteration: Number(logData['iteration'] ?? 0),\n outcome: String(logData['outcome'] ?? 'unknown'),\n timestamp: String(logData['timestamp'] ?? ''),\n });\n } catch {\n // Skip malformed log files\n }\n }\n\n if (recentLoops.length > 0) {\n // Sort by timestamp descending to show most recent first\n recentLoops.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n console.log(` Active/recent loops (${String(recentLoops.length)}):`);\n for (const loop of recentLoops.slice(0, 10)) {\n console.log(` ${loop.ticket} iter:${String(loop.lastIteration)} ${loop.outcome}`);\n }\n if (recentLoops.length > 10) {\n console.log(` ... and ${String(recentLoops.length - 10)} more`);\n }\n }\n}\n\nexport async function runStatus(client: KantBanCLIClient, args: string[]): Promise<void> {\n const [boardId] = args;\n if (!boardId) {\n console.error('Usage: kantban status <board-id>');\n process.exit(1);\n }\n\n const projectId = process.env['KANTBAN_PROJECT_ID'];\n if (!projectId) {\n console.error('Error: KANTBAN_PROJECT_ID required');\n process.exit(1);\n }\n\n const data = await client.get<Record<string, unknown>>(\n `/projects/${projectId}/pipeline-context`,\n { boardId },\n );\n\n const columns = data['columns'] as Array<Record<string, unknown>> | undefined;\n const cb = data['circuit_breaker'] as Record<string, unknown> | undefined;\n const board = data['board'] as Record<string, unknown> | undefined;\n\n console.log(`Pipeline Status: ${board?.['name'] ?? 'Unknown Board'}`);\n console.log('\\u2500'.repeat(60));\n\n if (columns) {\n for (const col of columns) {\n const prompt = col['has_prompt'] ? '\\u{1F4C4}' : ' ';\n const name = String(col['name'] ?? '(unnamed)');\n const count = Number(col['ticket_count'] ?? 0);\n const goal = col['goal'] ? ` \\u2014 ${String(col['goal'])}` : '';\n console.log(`${prompt} ${name} (${count} tickets)${goal}`);\n }\n }\n\n if (cb?.['threshold']) {\n console.log(`\\nCircuit Breaker: threshold=${String(cb['threshold'])}`);\n }\n\n // Fetch bottleneck info\n const bottlenecks = await client.get<Record<string, unknown>>(\n `/projects/${projectId}/boards/${boardId}/bottlenecks`,\n );\n const stuckCount = (bottlenecks['stuck_tickets'] as unknown[] | undefined)?.length ?? 0;\n const wipCount = (bottlenecks['wip_violations'] as unknown[] | undefined)?.length ?? 0;\n\n if (stuckCount > 0 || wipCount > 0) {\n console.log(`\\nWarnings: ${stuckCount} stuck, ${wipCount} WIP violations`);\n } else {\n console.log('\\nAll clear.');\n }\n\n // Show pipeline orchestrator runtime info (non-fatal on error)\n try {\n showPipelineInfo(boardId);\n } catch {\n // Pipeline info is supplementary — don't break the status command\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// src/commands/work.ts
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
function asRecord(val) {
|
|
4
|
+
return typeof val === "object" && val !== null && !Array.isArray(val) ? val : void 0;
|
|
5
|
+
}
|
|
6
|
+
function asStringArray(val) {
|
|
7
|
+
return Array.isArray(val) ? val.map((v) => String(v)) : [];
|
|
8
|
+
}
|
|
9
|
+
async function runWork(client, args) {
|
|
10
|
+
const [ticketId] = args;
|
|
11
|
+
if (!ticketId) {
|
|
12
|
+
console.error("Usage: kantban work <ticket-id> [--dry-run]");
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
const projectId = process.env["KANTBAN_PROJECT_ID"];
|
|
16
|
+
if (!projectId) {
|
|
17
|
+
console.error("Error: KANTBAN_PROJECT_ID required");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const context = await client.get(
|
|
21
|
+
`/projects/${projectId}/pipeline-context`,
|
|
22
|
+
{ ticketId }
|
|
23
|
+
);
|
|
24
|
+
const ticket = asRecord(context["ticket"]);
|
|
25
|
+
const signals = asStringArray(context["signals"]);
|
|
26
|
+
const rules = context["transition_rules"] ? String(context["transition_rules"]) : void 0;
|
|
27
|
+
const title = String(ticket?.["title"] ?? "Untitled");
|
|
28
|
+
const description = ticket?.["description"] ? String(ticket["description"]) : "";
|
|
29
|
+
const ticketIdStr = String(ticket?.["id"] ?? ticketId);
|
|
30
|
+
const promptLines = [
|
|
31
|
+
`# Task: ${title}`,
|
|
32
|
+
""
|
|
33
|
+
];
|
|
34
|
+
if (description) {
|
|
35
|
+
promptLines.push(description, "");
|
|
36
|
+
}
|
|
37
|
+
if (signals.length > 0) {
|
|
38
|
+
promptLines.push("## Signals");
|
|
39
|
+
for (const s of signals) {
|
|
40
|
+
promptLines.push(`- ${s}`);
|
|
41
|
+
}
|
|
42
|
+
promptLines.push("");
|
|
43
|
+
}
|
|
44
|
+
if (rules) {
|
|
45
|
+
promptLines.push("## Transition Rules", rules, "");
|
|
46
|
+
}
|
|
47
|
+
const toolPrefix = context["tool_prefix"] ? String(context["tool_prefix"]) : "kantban_";
|
|
48
|
+
promptLines.push(
|
|
49
|
+
`## Tool Prefix: ${toolPrefix}`,
|
|
50
|
+
`## Ticket ID: ${ticketIdStr}`,
|
|
51
|
+
`## Project ID: ${projectId}`
|
|
52
|
+
);
|
|
53
|
+
const prompt = promptLines.join("\n");
|
|
54
|
+
console.log(`Starting Claude session for: ${title}`);
|
|
55
|
+
console.log(`Ticket: ${ticketIdStr}`);
|
|
56
|
+
const dryRun = args.includes("--dry-run");
|
|
57
|
+
if (dryRun) {
|
|
58
|
+
console.log("\n--- Prompt (dry run) ---");
|
|
59
|
+
console.log(prompt);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const child = spawn("claude", ["-p", prompt], {
|
|
63
|
+
stdio: "inherit",
|
|
64
|
+
env: { ...process.env }
|
|
65
|
+
});
|
|
66
|
+
await new Promise((resolve) => {
|
|
67
|
+
child.on("error", (err) => {
|
|
68
|
+
console.error(`Failed to start claude: ${err.message}`);
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
resolve();
|
|
71
|
+
});
|
|
72
|
+
child.on("exit", (code) => {
|
|
73
|
+
process.exitCode = code ?? 0;
|
|
74
|
+
resolve();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
export {
|
|
79
|
+
runWork
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=work-2V33NZAT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/work.ts"],"sourcesContent":["import { spawn } from 'node:child_process';\nimport type { KantBanCLIClient } from '../client.js';\n\nfunction asRecord(val: unknown): Record<string, unknown> | undefined {\n return typeof val === 'object' && val !== null && !Array.isArray(val)\n ? (val as Record<string, unknown>)\n : undefined;\n}\n\nfunction asStringArray(val: unknown): string[] {\n return Array.isArray(val) ? val.map((v) => String(v)) : [];\n}\n\nexport async function runWork(client: KantBanCLIClient, args: string[]): Promise<void> {\n const [ticketId] = args;\n if (!ticketId) {\n console.error('Usage: kantban work <ticket-id> [--dry-run]');\n process.exit(1);\n }\n\n const projectId = process.env['KANTBAN_PROJECT_ID'];\n if (!projectId) {\n console.error('Error: KANTBAN_PROJECT_ID required');\n process.exit(1);\n }\n\n // Fetch ticket-scope context\n const context = await client.get<Record<string, unknown>>(\n `/projects/${projectId}/pipeline-context`,\n { ticketId },\n );\n\n const ticket = asRecord(context['ticket']);\n const signals = asStringArray(context['signals']);\n const rules = context['transition_rules'] ? String(context['transition_rules']) : undefined;\n\n const title = String(ticket?.['title'] ?? 'Untitled');\n const description = ticket?.['description'] ? String(ticket['description']) : '';\n const ticketIdStr = String(ticket?.['id'] ?? ticketId);\n\n // Build prompt for Claude\n const promptLines = [\n `# Task: ${title}`,\n '',\n ];\n\n if (description) {\n promptLines.push(description, '');\n }\n\n if (signals.length > 0) {\n promptLines.push('## Signals');\n for (const s of signals) {\n promptLines.push(`- ${s}`);\n }\n promptLines.push('');\n }\n\n if (rules) {\n promptLines.push('## Transition Rules', rules, '');\n }\n\n const toolPrefix = context['tool_prefix'] ? String(context['tool_prefix']) : 'kantban_';\n promptLines.push(\n `## Tool Prefix: ${toolPrefix}`,\n `## Ticket ID: ${ticketIdStr}`,\n `## Project ID: ${projectId}`,\n );\n\n const prompt = promptLines.join('\\n');\n\n console.log(`Starting Claude session for: ${title}`);\n console.log(`Ticket: ${ticketIdStr}`);\n\n // Check for dry run\n const dryRun = args.includes('--dry-run');\n if (dryRun) {\n console.log('\\n--- Prompt (dry run) ---');\n console.log(prompt);\n return;\n }\n\n // Spawn Claude with the prompt\n const child = spawn('claude', ['-p', prompt], {\n stdio: 'inherit',\n env: { ...process.env },\n });\n\n await new Promise<void>((resolve) => {\n child.on('error', (err) => {\n console.error(`Failed to start claude: ${err.message}`);\n process.exitCode = 1;\n resolve();\n });\n child.on('exit', (code) => {\n process.exitCode = code ?? 0;\n resolve();\n });\n });\n}\n"],"mappings":";AAAA,SAAS,aAAa;AAGtB,SAAS,SAAS,KAAmD;AACnE,SAAO,OAAO,QAAQ,YAAY,QAAQ,QAAQ,CAAC,MAAM,QAAQ,GAAG,IAC/D,MACD;AACN;AAEA,SAAS,cAAc,KAAwB;AAC7C,SAAO,MAAM,QAAQ,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC;AAC3D;AAEA,eAAsB,QAAQ,QAA0B,MAA+B;AACrF,QAAM,CAAC,QAAQ,IAAI;AACnB,MAAI,CAAC,UAAU;AACb,YAAQ,MAAM,6CAA6C;AAC3D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,YAAY,QAAQ,IAAI,oBAAoB;AAClD,MAAI,CAAC,WAAW;AACd,YAAQ,MAAM,oCAAoC;AAClD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,UAAU,MAAM,OAAO;AAAA,IAC3B,aAAa,SAAS;AAAA,IACtB,EAAE,SAAS;AAAA,EACb;AAEA,QAAM,SAAS,SAAS,QAAQ,QAAQ,CAAC;AACzC,QAAM,UAAU,cAAc,QAAQ,SAAS,CAAC;AAChD,QAAM,QAAQ,QAAQ,kBAAkB,IAAI,OAAO,QAAQ,kBAAkB,CAAC,IAAI;AAElF,QAAM,QAAQ,OAAO,SAAS,OAAO,KAAK,UAAU;AACpD,QAAM,cAAc,SAAS,aAAa,IAAI,OAAO,OAAO,aAAa,CAAC,IAAI;AAC9E,QAAM,cAAc,OAAO,SAAS,IAAI,KAAK,QAAQ;AAGrD,QAAM,cAAc;AAAA,IAClB,WAAW,KAAK;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,aAAa;AACf,gBAAY,KAAK,aAAa,EAAE;AAAA,EAClC;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,gBAAY,KAAK,YAAY;AAC7B,eAAW,KAAK,SAAS;AACvB,kBAAY,KAAK,KAAK,CAAC,EAAE;AAAA,IAC3B;AACA,gBAAY,KAAK,EAAE;AAAA,EACrB;AAEA,MAAI,OAAO;AACT,gBAAY,KAAK,uBAAuB,OAAO,EAAE;AAAA,EACnD;AAEA,QAAM,aAAa,QAAQ,aAAa,IAAI,OAAO,QAAQ,aAAa,CAAC,IAAI;AAC7E,cAAY;AAAA,IACV,mBAAmB,UAAU;AAAA,IAC7B,iBAAiB,WAAW;AAAA,IAC5B,kBAAkB,SAAS;AAAA,EAC7B;AAEA,QAAM,SAAS,YAAY,KAAK,IAAI;AAEpC,UAAQ,IAAI,gCAAgC,KAAK,EAAE;AACnD,UAAQ,IAAI,WAAW,WAAW,EAAE;AAGpC,QAAM,SAAS,KAAK,SAAS,WAAW;AACxC,MAAI,QAAQ;AACV,YAAQ,IAAI,4BAA4B;AACxC,YAAQ,IAAI,MAAM;AAClB;AAAA,EACF;AAGA,QAAM,QAAQ,MAAM,UAAU,CAAC,MAAM,MAAM,GAAG;AAAA,IAC5C,OAAO;AAAA,IACP,KAAK,EAAE,GAAG,QAAQ,IAAI;AAAA,EACxB,CAAC;AAED,QAAM,IAAI,QAAc,CAAC,YAAY;AACnC,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,cAAQ,MAAM,2BAA2B,IAAI,OAAO,EAAE;AACtD,cAAQ,WAAW;AACnB,cAAQ;AAAA,IACV,CAAC;AACD,UAAM,GAAG,QAAQ,CAAC,SAAS;AACzB,cAAQ,WAAW,QAAQ;AAC3B,cAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kantban-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "CLI for KantBan pipeline orchestration — bridges KantBan boards to local Claude Code sessions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"README.md"
|
|
27
27
|
],
|
|
28
28
|
"scripts": {
|
|
29
|
-
"build": "
|
|
30
|
-
"dev": "
|
|
29
|
+
"build": "tsup",
|
|
30
|
+
"dev": "tsup --watch",
|
|
31
31
|
"test": "vitest run",
|
|
32
32
|
"typecheck": "tsc --noEmit",
|
|
33
33
|
"postbuild": "chmod +x dist/index.js",
|
|
34
|
-
"prepublishOnly": "
|
|
34
|
+
"prepublishOnly": "tsup"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"js-yaml": "^4.1.1",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"@types/js-yaml": "^4.0.9",
|
|
44
44
|
"@types/node": "^22.0.0",
|
|
45
45
|
"@types/ws": "^8.18.1",
|
|
46
|
+
"tsup": "^8.5.1",
|
|
46
47
|
"typescript": "^5.8.0"
|
|
47
48
|
},
|
|
48
49
|
"engines": {
|
package/dist/client.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export declare const REQUEST_TIMEOUT_MS = 30000;
|
|
2
|
-
export declare const MAX_RETRIES = 2;
|
|
3
|
-
export declare const RETRY_BASE_MS = 500;
|
|
4
|
-
/** Returns true for statuses that are worth retrying (server errors + rate limit). */
|
|
5
|
-
export declare function isRetryableStatus(status: number): boolean;
|
|
6
|
-
/**
|
|
7
|
-
* Wraps `fetch` with:
|
|
8
|
-
* - Per-request AbortController timeout (REQUEST_TIMEOUT_MS)
|
|
9
|
-
* - Exponential backoff with jitter on retryable failures
|
|
10
|
-
* - Up to MAX_RETRIES retries (so MAX_RETRIES + 1 total attempts)
|
|
11
|
-
*
|
|
12
|
-
* @param _sleep — optional override for the backoff sleep (used in tests to avoid real delays)
|
|
13
|
-
*/
|
|
14
|
-
export declare function fetchWithRetry(url: string, init: RequestInit, retries?: number, _sleep?: (ms: number) => Promise<void>): Promise<Response>;
|
|
15
|
-
export declare class KantBanCLIClient {
|
|
16
|
-
private apiUrl;
|
|
17
|
-
private apiToken;
|
|
18
|
-
constructor(apiUrl: string, apiToken: string);
|
|
19
|
-
get baseUrl(): string;
|
|
20
|
-
get token(): string;
|
|
21
|
-
get<T>(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<T>;
|
|
22
|
-
post<T>(path: string, body?: Record<string, unknown>): Promise<T>;
|
|
23
|
-
claimTicket(projectId: string, ticketId: string): Promise<void>;
|
|
24
|
-
getFingerprint(projectId: string, ticketId: string): Promise<{
|
|
25
|
-
column_id: string | null;
|
|
26
|
-
updated_at: string;
|
|
27
|
-
comment_count: number;
|
|
28
|
-
signal_count: number;
|
|
29
|
-
field_value_count: number;
|
|
30
|
-
}>;
|
|
31
|
-
put<T>(path: string, body?: Record<string, unknown>): Promise<T>;
|
|
32
|
-
patch<T>(path: string, body?: Record<string, unknown>): Promise<T>;
|
|
33
|
-
delete<T = unknown>(path: string): Promise<T>;
|
|
34
|
-
getBoardProject(boardId: string): Promise<{
|
|
35
|
-
project_id: string;
|
|
36
|
-
}>;
|
|
37
|
-
}
|
|
38
|
-
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,WAAW,EACjB,OAAO,SAAc,EACrB,MAAM,GAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CACe,GAClD,OAAO,CAAC,QAAQ,CAAC,CAgCnB;AAID,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,QAAQ;gBADR,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM;IAG1B,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAEK,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAmBhG,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkBjE,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC;IAII,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkBhE,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkBlE,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAe7C,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAGxE"}
|
package/dist/client.js
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
// ── retry / timeout constants ─────────────────────────────────────────────
|
|
2
|
-
export const REQUEST_TIMEOUT_MS = 30_000;
|
|
3
|
-
export const MAX_RETRIES = 2;
|
|
4
|
-
export const RETRY_BASE_MS = 500;
|
|
5
|
-
/** Returns true for statuses that are worth retrying (server errors + rate limit). */
|
|
6
|
-
export function isRetryableStatus(status) {
|
|
7
|
-
return status >= 500 || status === 429;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Wraps `fetch` with:
|
|
11
|
-
* - Per-request AbortController timeout (REQUEST_TIMEOUT_MS)
|
|
12
|
-
* - Exponential backoff with jitter on retryable failures
|
|
13
|
-
* - Up to MAX_RETRIES retries (so MAX_RETRIES + 1 total attempts)
|
|
14
|
-
*
|
|
15
|
-
* @param _sleep — optional override for the backoff sleep (used in tests to avoid real delays)
|
|
16
|
-
*/
|
|
17
|
-
export async function fetchWithRetry(url, init, retries = MAX_RETRIES, _sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
|
|
18
|
-
let lastError;
|
|
19
|
-
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
20
|
-
const controller = new AbortController();
|
|
21
|
-
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
22
|
-
try {
|
|
23
|
-
const res = await fetch(url, { ...init, signal: controller.signal });
|
|
24
|
-
clearTimeout(timer);
|
|
25
|
-
// Non-retryable: 2xx (ok) or any non-retryable error status
|
|
26
|
-
if (res.ok || !isRetryableStatus(res.status)) {
|
|
27
|
-
return res;
|
|
28
|
-
}
|
|
29
|
-
// Retryable status — treat as a transient failure
|
|
30
|
-
lastError = new Error(`API error ${res.status}: ${await res.text()}`);
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
clearTimeout(timer);
|
|
34
|
-
lastError = err;
|
|
35
|
-
// Only retry on network/abort errors, not on logic errors
|
|
36
|
-
}
|
|
37
|
-
if (attempt < retries) {
|
|
38
|
-
// Exponential backoff with up to 50% random jitter
|
|
39
|
-
const delay = RETRY_BASE_MS * 2 ** attempt * (1 + Math.random() * 0.5);
|
|
40
|
-
await _sleep(delay);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
throw lastError;
|
|
44
|
-
}
|
|
45
|
-
// ── client ────────────────────────────────────────────────────────────────
|
|
46
|
-
export class KantBanCLIClient {
|
|
47
|
-
apiUrl;
|
|
48
|
-
apiToken;
|
|
49
|
-
constructor(apiUrl, apiToken) {
|
|
50
|
-
this.apiUrl = apiUrl;
|
|
51
|
-
this.apiToken = apiToken;
|
|
52
|
-
}
|
|
53
|
-
get baseUrl() {
|
|
54
|
-
return this.apiUrl;
|
|
55
|
-
}
|
|
56
|
-
get token() {
|
|
57
|
-
return this.apiToken;
|
|
58
|
-
}
|
|
59
|
-
async get(path, params) {
|
|
60
|
-
const url = new URL(path, this.apiUrl);
|
|
61
|
-
if (params) {
|
|
62
|
-
for (const [k, v] of Object.entries(params)) {
|
|
63
|
-
if (v !== undefined)
|
|
64
|
-
url.searchParams.set(k, String(v));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const res = await fetchWithRetry(url.toString(), {
|
|
68
|
-
headers: {
|
|
69
|
-
'Authorization': `Bearer ${this.apiToken}`,
|
|
70
|
-
'X-KantBan-Via': 'cli',
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
if (!res.ok)
|
|
74
|
-
throw new Error(`API error ${res.status}: ${await res.text()}`);
|
|
75
|
-
const json = (await res.json());
|
|
76
|
-
if (!json.success)
|
|
77
|
-
throw new Error(`API responded with success: false`);
|
|
78
|
-
return json.data;
|
|
79
|
-
}
|
|
80
|
-
async post(path, body) {
|
|
81
|
-
const url = new URL(path, this.apiUrl);
|
|
82
|
-
const headers = {
|
|
83
|
-
'Authorization': `Bearer ${this.apiToken}`,
|
|
84
|
-
'X-KantBan-Via': 'cli',
|
|
85
|
-
};
|
|
86
|
-
const init = { method: 'POST', headers };
|
|
87
|
-
if (body) {
|
|
88
|
-
headers['Content-Type'] = 'application/json';
|
|
89
|
-
init.body = JSON.stringify(body);
|
|
90
|
-
}
|
|
91
|
-
const res = await fetchWithRetry(url.toString(), init);
|
|
92
|
-
if (!res.ok)
|
|
93
|
-
throw new Error(`API error ${res.status}: ${await res.text()}`);
|
|
94
|
-
const json = (await res.json());
|
|
95
|
-
if (!json.success)
|
|
96
|
-
throw new Error(`API responded with success: false`);
|
|
97
|
-
return json.data;
|
|
98
|
-
}
|
|
99
|
-
async claimTicket(projectId, ticketId) {
|
|
100
|
-
await this.post(`/projects/${projectId}/tickets/${ticketId}/start`, {});
|
|
101
|
-
}
|
|
102
|
-
async getFingerprint(projectId, ticketId) {
|
|
103
|
-
return this.get(`/projects/${projectId}/tickets/${ticketId}/fingerprint`);
|
|
104
|
-
}
|
|
105
|
-
async put(path, body) {
|
|
106
|
-
const url = new URL(path, this.apiUrl);
|
|
107
|
-
const headers = {
|
|
108
|
-
'Authorization': `Bearer ${this.apiToken}`,
|
|
109
|
-
'X-KantBan-Via': 'cli',
|
|
110
|
-
};
|
|
111
|
-
const init = { method: 'PUT', headers };
|
|
112
|
-
if (body) {
|
|
113
|
-
headers['Content-Type'] = 'application/json';
|
|
114
|
-
init.body = JSON.stringify(body);
|
|
115
|
-
}
|
|
116
|
-
const res = await fetchWithRetry(url.toString(), init);
|
|
117
|
-
if (!res.ok)
|
|
118
|
-
throw new Error(`API error ${res.status}: ${await res.text()}`);
|
|
119
|
-
const json = (await res.json());
|
|
120
|
-
if (!json.success)
|
|
121
|
-
throw new Error(`API responded with success: false`);
|
|
122
|
-
return json.data;
|
|
123
|
-
}
|
|
124
|
-
async patch(path, body) {
|
|
125
|
-
const url = new URL(path, this.apiUrl);
|
|
126
|
-
const headers = {
|
|
127
|
-
'Authorization': `Bearer ${this.apiToken}`,
|
|
128
|
-
'X-KantBan-Via': 'cli',
|
|
129
|
-
};
|
|
130
|
-
const init = { method: 'PATCH', headers };
|
|
131
|
-
if (body) {
|
|
132
|
-
headers['Content-Type'] = 'application/json';
|
|
133
|
-
init.body = JSON.stringify(body);
|
|
134
|
-
}
|
|
135
|
-
const res = await fetchWithRetry(url.toString(), init);
|
|
136
|
-
if (!res.ok)
|
|
137
|
-
throw new Error(`API error ${res.status}: ${await res.text()}`);
|
|
138
|
-
const json = (await res.json());
|
|
139
|
-
if (!json.success)
|
|
140
|
-
throw new Error(`API responded with success: false`);
|
|
141
|
-
return json.data;
|
|
142
|
-
}
|
|
143
|
-
async delete(path) {
|
|
144
|
-
const url = new URL(path, this.apiUrl);
|
|
145
|
-
const res = await fetchWithRetry(url.toString(), {
|
|
146
|
-
method: 'DELETE',
|
|
147
|
-
headers: {
|
|
148
|
-
'Authorization': `Bearer ${this.apiToken}`,
|
|
149
|
-
'X-KantBan-Via': 'cli',
|
|
150
|
-
},
|
|
151
|
-
});
|
|
152
|
-
if (!res.ok)
|
|
153
|
-
throw new Error(`API error ${res.status}: ${await res.text()}`);
|
|
154
|
-
const json = (await res.json());
|
|
155
|
-
if (!json.success)
|
|
156
|
-
throw new Error(`API responded with success: false`);
|
|
157
|
-
return json.data;
|
|
158
|
-
}
|
|
159
|
-
async getBoardProject(boardId) {
|
|
160
|
-
return this.get(`/boards/${boardId}/project`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BxF"}
|
package/dist/commands/context.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export async function runContext(client, args) {
|
|
2
|
-
const [scopeType, scopeId] = args;
|
|
3
|
-
if (!scopeType || !scopeId) {
|
|
4
|
-
console.error('Usage: kantban context <board|column|ticket> <id>');
|
|
5
|
-
process.exit(1);
|
|
6
|
-
}
|
|
7
|
-
const projectId = process.env['KANTBAN_PROJECT_ID'];
|
|
8
|
-
if (!projectId) {
|
|
9
|
-
console.error('Error: KANTBAN_PROJECT_ID environment variable required for context command');
|
|
10
|
-
process.exit(1);
|
|
11
|
-
}
|
|
12
|
-
const params = {};
|
|
13
|
-
if (scopeType === 'board')
|
|
14
|
-
params['boardId'] = scopeId;
|
|
15
|
-
else if (scopeType === 'column')
|
|
16
|
-
params['columnId'] = scopeId;
|
|
17
|
-
else if (scopeType === 'ticket')
|
|
18
|
-
params['ticketId'] = scopeId;
|
|
19
|
-
else {
|
|
20
|
-
console.error(`Unknown scope type: ${scopeType}. Use board, column, or ticket.`);
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
const data = await client.get(`/projects/${projectId}/pipeline-context`, params);
|
|
24
|
-
// Output as structured JSON to stdout for piping
|
|
25
|
-
console.log(JSON.stringify(data, null, 2));
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=context.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAwB,EAAE,IAAc;IACvE,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClC,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACpD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;QAC7F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,SAAS,KAAK,OAAO;QAAE,MAAM,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC;SAClD,IAAI,SAAS,KAAK,QAAQ;QAAE,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;SACzD,IAAI,SAAS,KAAK,QAAQ;QAAE,MAAM,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;SACzD,CAAC;QACJ,OAAO,CAAC,KAAK,CAAC,uBAAuB,SAAS,iCAAiC,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAC3B,aAAa,SAAS,mBAAmB,EACzC,MAAM,CACP,CAAC;IAEF,iDAAiD;IACjD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC"}
|