claude-kanban 0.2.1 → 0.3.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.
package/dist/bin/cli.js CHANGED
@@ -36,7 +36,39 @@ function detectPackageManager(projectPath) {
36
36
  if (existsSync(join(projectPath, "bun.lockb"))) return "bun";
37
37
  return "npm";
38
38
  }
39
+ function detectProjectType(projectPath) {
40
+ if (existsSync(join(projectPath, "package.json"))) return "node";
41
+ if (existsSync(join(projectPath, "pyproject.toml")) || existsSync(join(projectPath, "requirements.txt")) || existsSync(join(projectPath, "setup.py"))) return "python";
42
+ if (existsSync(join(projectPath, "composer.json"))) return "php";
43
+ if (existsSync(join(projectPath, "Gemfile"))) return "ruby";
44
+ if (existsSync(join(projectPath, "go.mod"))) return "go";
45
+ if (existsSync(join(projectPath, "Cargo.toml"))) return "rust";
46
+ return "unknown";
47
+ }
39
48
  function detectProjectCommands(projectPath) {
49
+ const projectType = detectProjectType(projectPath);
50
+ switch (projectType) {
51
+ case "node":
52
+ return detectNodeCommands(projectPath);
53
+ case "python":
54
+ return detectPythonCommands(projectPath);
55
+ case "php":
56
+ return detectPHPCommands(projectPath);
57
+ case "ruby":
58
+ return detectRubyCommands(projectPath);
59
+ case "go":
60
+ return detectGoCommands(projectPath);
61
+ case "rust":
62
+ return detectRustCommands(projectPath);
63
+ default:
64
+ return {
65
+ testCommand: "",
66
+ typecheckCommand: "",
67
+ buildCommand: ""
68
+ };
69
+ }
70
+ }
71
+ function detectNodeCommands(projectPath) {
40
72
  const pm = detectPackageManager(projectPath);
41
73
  const run = pm === "npm" ? "npm run" : pm;
42
74
  const packageJsonPath = join(projectPath, "package.json");
@@ -48,11 +80,61 @@ function detectProjectCommands(projectPath) {
48
80
  } catch {
49
81
  }
50
82
  }
51
- const testCommand = scripts.test ? `${run} test` : 'echo "No test command configured"';
52
- const typecheckCommand = scripts.typecheck ? `${run} typecheck` : scripts["type-check"] ? `${run} type-check` : existsSync(join(projectPath, "tsconfig.json")) ? `${run === "npm run" ? "npx" : pm} tsc --noEmit` : 'echo "No typecheck command configured"';
53
- const buildCommand = scripts.build ? `${run} build` : 'echo "No build command configured"';
83
+ const testCommand = scripts.test ? `${run} test` : "";
84
+ const typecheckCommand = scripts.typecheck ? `${run} typecheck` : scripts["type-check"] ? `${run} type-check` : existsSync(join(projectPath, "tsconfig.json")) ? `${run === "npm run" ? "npx" : pm} tsc --noEmit` : "";
85
+ const buildCommand = scripts.build ? `${run} build` : "";
54
86
  return { testCommand, typecheckCommand, buildCommand };
55
87
  }
88
+ function detectPythonCommands(projectPath) {
89
+ const hasPytest = existsSync(join(projectPath, "pytest.ini")) || existsSync(join(projectPath, "pyproject.toml")) || existsSync(join(projectPath, "tests"));
90
+ const hasMypy = existsSync(join(projectPath, "mypy.ini")) || existsSync(join(projectPath, ".mypy.ini"));
91
+ return {
92
+ testCommand: hasPytest ? "pytest" : "",
93
+ typecheckCommand: hasMypy ? "mypy ." : "",
94
+ buildCommand: ""
95
+ };
96
+ }
97
+ function detectPHPCommands(projectPath) {
98
+ const hasPhpunit = existsSync(join(projectPath, "phpunit.xml")) || existsSync(join(projectPath, "phpunit.xml.dist"));
99
+ const hasPest = existsSync(join(projectPath, "tests", "Pest.php"));
100
+ const hasPhpstan = existsSync(join(projectPath, "phpstan.neon")) || existsSync(join(projectPath, "phpstan.neon.dist"));
101
+ let testCommand = "";
102
+ if (hasPest) {
103
+ testCommand = "./vendor/bin/pest";
104
+ } else if (hasPhpunit) {
105
+ testCommand = "./vendor/bin/phpunit";
106
+ }
107
+ return {
108
+ testCommand,
109
+ typecheckCommand: hasPhpstan ? "./vendor/bin/phpstan analyse" : "",
110
+ buildCommand: ""
111
+ };
112
+ }
113
+ function detectRubyCommands(projectPath) {
114
+ const hasRspec = existsSync(join(projectPath, "spec")) || existsSync(join(projectPath, ".rspec"));
115
+ const hasMinitest = existsSync(join(projectPath, "test"));
116
+ return {
117
+ testCommand: hasRspec ? "bundle exec rspec" : hasMinitest ? "bundle exec rake test" : "",
118
+ typecheckCommand: "",
119
+ // Ruby doesn't have built-in typechecking (sorbet is optional)
120
+ buildCommand: ""
121
+ };
122
+ }
123
+ function detectGoCommands(_projectPath) {
124
+ return {
125
+ testCommand: "go test ./...",
126
+ typecheckCommand: "go build ./...",
127
+ // Go's compiler is the typechecker
128
+ buildCommand: "go build"
129
+ };
130
+ }
131
+ function detectRustCommands(_projectPath) {
132
+ return {
133
+ testCommand: "cargo test",
134
+ typecheckCommand: "cargo check",
135
+ buildCommand: "cargo build"
136
+ };
137
+ }
56
138
  function createInitialPRD(projectName) {
57
139
  return {
58
140
  version: "1.0",
@@ -709,13 +791,30 @@ ${summary}
709
791
  /**
710
792
  * Build the prompt for a specific task
711
793
  */
712
- buildTaskPrompt(task, config) {
794
+ buildTaskPrompt(task, config, worktreeInfo) {
713
795
  const kanbanDir = join4(this.projectPath, KANBAN_DIR4);
714
796
  const prdPath = join4(kanbanDir, "prd.json");
715
797
  const progressPath = join4(kanbanDir, "progress.txt");
716
798
  const stepsText = task.steps.length > 0 ? `
717
799
  Verification steps:
718
800
  ${task.steps.map((s, i) => `${i + 1}. ${s}`).join("\n")}` : "";
801
+ const verifySteps = [];
802
+ if (config.project.typecheckCommand) {
803
+ verifySteps.push(`Run typecheck: ${config.project.typecheckCommand}`);
804
+ }
805
+ if (config.project.testCommand) {
806
+ verifySteps.push(`Run tests: ${config.project.testCommand}`);
807
+ }
808
+ const verifySection = verifySteps.length > 0 ? `3. Verify your work:
809
+ ${verifySteps.map((s) => ` - ${s}`).join("\n")}
810
+
811
+ ` : "";
812
+ const worktreeSection = worktreeInfo ? `## ENVIRONMENT
813
+ You are running in an isolated git worktree on branch "${worktreeInfo.branchName}".
814
+ This is a fresh checkout - dependencies (node_modules, vendor, etc.) are NOT installed.
815
+ Before running any build/test commands, install dependencies first (e.g., npm install, composer install, pip install).
816
+
817
+ ` : "";
719
818
  return `You are an AI coding agent. Complete the following task:
720
819
 
721
820
  ## TASK
@@ -726,26 +825,24 @@ Priority: ${task.priority}
726
825
  ${task.description}
727
826
  ${stepsText}
728
827
 
729
- ## INSTRUCTIONS
730
- 1. Implement this task as described above.
828
+ ${worktreeSection}## INSTRUCTIONS
829
+ 1. If dependencies are not installed, install them first.
731
830
 
732
- 2. Verify your work:
733
- - Run typecheck: ${config.project.typecheckCommand}
734
- - Run tests: ${config.project.testCommand}
831
+ 2. Implement this task as described above.
735
832
 
736
- 3. When complete, update the task in ${prdPath}:
833
+ ${verifySection}${verifySteps.length > 0 ? "4" : "3"}. When complete, update the task in ${prdPath}:
737
834
  - Find the task with id "${task.id}"
738
835
  - Set "passes": true
739
836
  - Set "status": "completed"
740
837
 
741
- 4. Document your work in ${progressPath}:
838
+ ${verifySteps.length > 0 ? "5" : "4"}. Document your work in ${progressPath}:
742
839
  - What you implemented and files changed
743
840
  - Key decisions made and why
744
841
  - Gotchas, edge cases, or tricky parts discovered
745
842
  - Useful patterns or approaches that worked well
746
843
  - Anything a future agent should know about this area of the codebase
747
844
 
748
- 5. Make a git commit with a descriptive message.
845
+ ${verifySteps.length > 0 ? "6" : "5"}. Make a git commit with a descriptive message.
749
846
 
750
847
  Focus only on this task. When successfully complete, output: <promise>COMPLETE</promise>`;
751
848
  }
@@ -769,7 +866,7 @@ Focus only on this task. When successfully complete, output: <promise>COMPLETE</
769
866
  const startedAt = /* @__PURE__ */ new Date();
770
867
  const worktreeInfo = this.createWorktree(taskId);
771
868
  const executionPath = worktreeInfo?.worktreePath || this.projectPath;
772
- const prompt = this.buildTaskPrompt(task, config);
869
+ const prompt = this.buildTaskPrompt(task, config, worktreeInfo);
773
870
  const kanbanDir = join4(this.projectPath, KANBAN_DIR4);
774
871
  const promptFile = join4(kanbanDir, `prompt-${taskId}.txt`);
775
872
  writeFileSync4(promptFile, prompt);