karajan-code 1.37.0 → 1.38.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/README.md +7 -8
- package/docs/README.es.md +245 -34
- package/package.json +1 -1
- package/src/agents/resolve-bin.js +26 -14
- package/src/commands/code.js +3 -1
- package/src/commands/init.js +6 -4
- package/src/config.js +2 -2
- package/src/hu/store.js +57 -0
- package/src/mcp/server-handlers.js +3 -1
- package/src/orchestrator/hu-sub-pipeline.js +166 -0
- package/src/orchestrator/pre-loop-stages.js +120 -24
- package/src/orchestrator.js +94 -10
- package/src/planning-game/pipeline-adapter.js +37 -0
- package/src/prompts/hu-reviewer.js +55 -0
- package/src/prompts/triage.js +4 -2
- package/src/utils/os-detect.js +17 -8
- package/src/utils/process.js +7 -4
package/src/prompts/triage.js
CHANGED
|
@@ -11,7 +11,8 @@ const ROLE_DESCRIPTIONS = [
|
|
|
11
11
|
{ role: "security", description: "Audits code for security vulnerabilities. Checks auth, input validation, injection risks." },
|
|
12
12
|
{ role: "refactorer", description: "Cleans up and refactors code after the main implementation." },
|
|
13
13
|
{ role: "reviewer", description: "Reviews the code diff for quality issues. Standard quality gate." },
|
|
14
|
-
{ role: "architect", description: "Designs solution architecture — layers, patterns, data model, API contracts, tradeoffs. Activate when task creates new module/app, affects data model/APIs, complexity is medium/complex, or design is ambiguous." }
|
|
14
|
+
{ role: "architect", description: "Designs solution architecture — layers, patterns, data model, API contracts, tradeoffs. Activate when task creates new module/app, affects data model/APIs, complexity is medium/complex, or design is ambiguous." },
|
|
15
|
+
{ role: "hu-reviewer", description: "Certifies user stories before coding. Activate for medium/complex tasks that need story decomposition." }
|
|
15
16
|
];
|
|
16
17
|
|
|
17
18
|
export function buildTriagePrompt({ task, instructions, availableRoles }) {
|
|
@@ -37,13 +38,14 @@ export function buildTriagePrompt({ task, instructions, availableRoles }) {
|
|
|
37
38
|
"- **refactorer**: Enable only when explicitly requested or when the task is a refactoring task.",
|
|
38
39
|
"- **reviewer**: Enable for most tasks as a quality gate. Disable only for trivial, single-line changes.",
|
|
39
40
|
"- **architect**: Enable when creating new modules/apps, changing data models or APIs, medium/complex tasks, or when design approach is ambiguous. Disable for simple fixes, doc-only, or CSS-only changes.",
|
|
41
|
+
"- **hu-reviewer**: Enable for medium/complex tasks that benefit from story decomposition and certification. Disable for trivial/simple tasks, doc-only, or CSS-only changes.",
|
|
40
42
|
"",
|
|
41
43
|
"Note: coder is ALWAYS active — you don't need to decide on it."
|
|
42
44
|
].join("\n"),
|
|
43
45
|
"Classify the task complexity, determine its taskType, recommend only the necessary pipeline roles, and assess whether the task should be decomposed into smaller subtasks.",
|
|
44
46
|
"Keep the reasoning short and practical.",
|
|
45
47
|
"Return a single valid JSON object and nothing else.",
|
|
46
|
-
'JSON schema: {"level":"trivial|simple|medium|complex","roles":["planner|researcher|refactorer|reviewer|tester|security|architect"],"taskType":"sw|infra|doc|add-tests|refactor","reasoning":string,"shouldDecompose":boolean,"subtasks":string[]}',
|
|
48
|
+
'JSON schema: {"level":"trivial|simple|medium|complex","roles":["planner|researcher|refactorer|reviewer|tester|security|architect|hu-reviewer"],"taskType":"sw|infra|doc|add-tests|refactor","reasoning":string,"shouldDecompose":boolean,"subtasks":string[]}',
|
|
47
49
|
`## Task\n${task}`
|
|
48
50
|
);
|
|
49
51
|
|
package/src/utils/os-detect.js
CHANGED
|
@@ -5,37 +5,46 @@ import os from "node:os";
|
|
|
5
5
|
*/
|
|
6
6
|
export function getPlatform() {
|
|
7
7
|
const platform = os.platform();
|
|
8
|
-
|
|
8
|
+
if (platform === "win32") return "windows";
|
|
9
|
+
if (platform === "darwin") return "macos";
|
|
10
|
+
return "linux";
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
const INSTALL_COMMANDS = {
|
|
12
14
|
rtk: {
|
|
13
15
|
macos: "brew install rtk && rtk init --global",
|
|
14
|
-
linux: "curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh && rtk init --global"
|
|
16
|
+
linux: "curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh && rtk init --global",
|
|
17
|
+
windows: "Download from https://github.com/rtk-ai/rtk/releases and add to PATH"
|
|
15
18
|
},
|
|
16
19
|
claude: {
|
|
17
20
|
macos: "npm install -g @anthropic-ai/claude-code",
|
|
18
|
-
linux: "npm install -g @anthropic-ai/claude-code"
|
|
21
|
+
linux: "npm install -g @anthropic-ai/claude-code",
|
|
22
|
+
windows: "npm install -g @anthropic-ai/claude-code"
|
|
19
23
|
},
|
|
20
24
|
codex: {
|
|
21
25
|
macos: "npm install -g @openai/codex",
|
|
22
|
-
linux: "npm install -g @openai/codex"
|
|
26
|
+
linux: "npm install -g @openai/codex",
|
|
27
|
+
windows: "npm install -g @openai/codex"
|
|
23
28
|
},
|
|
24
29
|
gemini: {
|
|
25
30
|
macos: "npm install -g @google/gemini-cli",
|
|
26
|
-
linux: "npm install -g @google/gemini-cli"
|
|
31
|
+
linux: "npm install -g @google/gemini-cli",
|
|
32
|
+
windows: "npm install -g @google/gemini-cli"
|
|
27
33
|
},
|
|
28
34
|
aider: {
|
|
29
35
|
macos: "pipx install aider-chat",
|
|
30
|
-
linux: "pipx install aider-chat || pip3 install aider-chat"
|
|
36
|
+
linux: "pipx install aider-chat || pip3 install aider-chat",
|
|
37
|
+
windows: "pip install aider-chat"
|
|
31
38
|
},
|
|
32
39
|
opencode: {
|
|
33
40
|
macos: "curl -fsSL https://opencode.ai/install | bash",
|
|
34
|
-
linux: "curl -fsSL https://opencode.ai/install | bash"
|
|
41
|
+
linux: "curl -fsSL https://opencode.ai/install | bash",
|
|
42
|
+
windows: "See https://github.com/nicepkg/opencode for Windows install"
|
|
35
43
|
},
|
|
36
44
|
docker: {
|
|
37
45
|
macos: "brew install --cask docker",
|
|
38
|
-
linux: "sudo apt install docker.io docker-compose-v2 (or see https://docs.docker.com/engine/install/)"
|
|
46
|
+
linux: "sudo apt install docker.io docker-compose-v2 (or see https://docs.docker.com/engine/install/)",
|
|
47
|
+
windows: "Download Docker Desktop from https://www.docker.com/products/docker-desktop/"
|
|
39
48
|
}
|
|
40
49
|
};
|
|
41
50
|
|
package/src/utils/process.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { execa } from "execa";
|
|
2
2
|
|
|
3
|
+
const isWin = process.platform === "win32";
|
|
4
|
+
const KILL_SIGNAL = isWin ? "SIGTERM" : "SIGKILL";
|
|
5
|
+
|
|
3
6
|
function buildSilenceKilledResult(silenceTimeoutMs, stdout, signal) {
|
|
4
7
|
return {
|
|
5
8
|
exitCode: 143,
|
|
6
9
|
stdout,
|
|
7
10
|
stderr: `Command killed after ${Number(silenceTimeoutMs)}ms without output`,
|
|
8
11
|
timedOut: true,
|
|
9
|
-
signal: signal ||
|
|
12
|
+
signal: signal || KILL_SIGNAL
|
|
10
13
|
};
|
|
11
14
|
}
|
|
12
15
|
|
|
@@ -52,7 +55,7 @@ async function awaitWithTimeout(subprocess, timeout, getStdout) {
|
|
|
52
55
|
const timeoutResult = new Promise((resolve) => {
|
|
53
56
|
timer = setTimeout(() => {
|
|
54
57
|
try {
|
|
55
|
-
subprocess.kill(
|
|
58
|
+
subprocess.kill(KILL_SIGNAL, { forceKillAfterDelay: 1000 });
|
|
56
59
|
} catch {
|
|
57
60
|
// no-op
|
|
58
61
|
}
|
|
@@ -61,7 +64,7 @@ async function awaitWithTimeout(subprocess, timeout, getStdout) {
|
|
|
61
64
|
stdout: getStdout(),
|
|
62
65
|
stderr: `Command timed out after ${timeout}ms`,
|
|
63
66
|
timedOut: true,
|
|
64
|
-
signal:
|
|
67
|
+
signal: KILL_SIGNAL
|
|
65
68
|
});
|
|
66
69
|
}, timeout);
|
|
67
70
|
});
|
|
@@ -94,7 +97,7 @@ export async function runCommand(command, args = [], options = {}) {
|
|
|
94
97
|
outputSilenceTimer = setTimeout(() => {
|
|
95
98
|
silenceTimedOut = true;
|
|
96
99
|
try {
|
|
97
|
-
subprocess.kill(
|
|
100
|
+
subprocess.kill(KILL_SIGNAL, { forceKillAfterDelay: 1000 });
|
|
98
101
|
} catch {
|
|
99
102
|
// no-op
|
|
100
103
|
}
|