karajan-code 1.14.0 → 1.15.0
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/package.json +1 -1
- package/src/cli.js +1 -0
- package/src/mcp/run-kj.js +1 -0
- package/src/mcp/server-handlers.js +6 -0
- package/src/mcp/tools.js +1 -0
- package/src/orchestrator/pre-loop-stages.js +9 -6
- package/src/orchestrator.js +4 -2
- package/src/prompts/triage.js +2 -2
- package/src/roles/triage-role.js +6 -0
- package/templates/roles/triage.md +9 -1
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -87,6 +87,7 @@ program
|
|
|
87
87
|
.option("--auto-pr")
|
|
88
88
|
.option("--enable-becaria", "Enable BecarIA Gateway (early PR + dispatch comments/reviews)")
|
|
89
89
|
.option("--branch-prefix <prefix>")
|
|
90
|
+
.option("--task-type <type>", "Explicit task type: sw, infra, doc, add-tests, refactor")
|
|
90
91
|
.option("--methodology <name>")
|
|
91
92
|
.option("--no-auto-rebase")
|
|
92
93
|
.option("--no-sonar")
|
package/src/mcp/run-kj.js
CHANGED
|
@@ -48,6 +48,7 @@ export async function runKjCommand({ command, commandArgs = [], options = {}, en
|
|
|
48
48
|
normalizeBoolFlag(options.autoPush, "--auto-push", args);
|
|
49
49
|
normalizeBoolFlag(options.autoPr, "--auto-pr", args);
|
|
50
50
|
if (options.autoRebase === false) args.push("--no-auto-rebase");
|
|
51
|
+
addOptionalValue(args, "--task-type", options.taskType);
|
|
51
52
|
normalizeBoolFlag(options.noSonar, "--no-sonar", args);
|
|
52
53
|
if (options.smartModels === true) args.push("--smart-models");
|
|
53
54
|
if (options.smartModels === false) args.push("--no-smart-models");
|
|
@@ -565,6 +565,12 @@ export async function handleToolCall(name, args, server, extra) {
|
|
|
565
565
|
if (!a.task) {
|
|
566
566
|
return failPayload("Missing required field: task");
|
|
567
567
|
}
|
|
568
|
+
if (a.taskType) {
|
|
569
|
+
const validTypes = ["sw", "infra", "doc", "add-tests", "refactor"];
|
|
570
|
+
if (!validTypes.includes(a.taskType)) {
|
|
571
|
+
return failPayload(`Invalid taskType "${a.taskType}". Valid values: ${validTypes.join(", ")}`);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
568
574
|
if (!isPreflightAcked()) {
|
|
569
575
|
const { config } = await loadConfig();
|
|
570
576
|
const { listAgents } = await import("../commands/agents.js");
|
package/src/mcp/tools.js
CHANGED
|
@@ -88,6 +88,7 @@ export const tools = [
|
|
|
88
88
|
branchPrefix: { type: "string" },
|
|
89
89
|
smartModels: { type: "boolean", description: "Enable/disable smart model selection based on triage complexity" },
|
|
90
90
|
checkpointInterval: { type: "number", description: "Minutes between interactive checkpoints (default: 5). Set 0 to disable." },
|
|
91
|
+
taskType: { type: "string", enum: ["sw", "infra", "doc", "add-tests", "refactor"], description: "Explicit task type for policy resolution. Overrides triage classification." },
|
|
91
92
|
noSonar: { type: "boolean" },
|
|
92
93
|
kjHome: { type: "string" },
|
|
93
94
|
sonarToken: { type: "string" },
|
|
@@ -56,12 +56,14 @@ export async function runTriageStage({ config, logger, emitter, eventBase, sessi
|
|
|
56
56
|
const recommendedRoles = new Set(triageOutput.result?.roles || []);
|
|
57
57
|
const roleOverrides = {};
|
|
58
58
|
if (triageOutput.ok) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
roleOverrides.
|
|
62
|
-
roleOverrides.
|
|
63
|
-
roleOverrides.
|
|
64
|
-
roleOverrides.
|
|
59
|
+
// Triage can activate roles, but cannot deactivate roles explicitly enabled in pipeline config
|
|
60
|
+
const p = config.pipeline || {};
|
|
61
|
+
roleOverrides.plannerEnabled = recommendedRoles.has("planner") || Boolean(p.planner?.enabled);
|
|
62
|
+
roleOverrides.researcherEnabled = recommendedRoles.has("researcher") || Boolean(p.researcher?.enabled);
|
|
63
|
+
roleOverrides.refactorerEnabled = recommendedRoles.has("refactorer") || Boolean(p.refactorer?.enabled);
|
|
64
|
+
roleOverrides.reviewerEnabled = recommendedRoles.has("reviewer") || Boolean(p.reviewer?.enabled);
|
|
65
|
+
roleOverrides.testerEnabled = recommendedRoles.has("tester") || Boolean(p.tester?.enabled);
|
|
66
|
+
roleOverrides.securityEnabled = recommendedRoles.has("security") || Boolean(p.security?.enabled);
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
const shouldDecompose = triageOutput.result?.shouldDecompose || false;
|
|
@@ -72,6 +74,7 @@ export async function runTriageStage({ config, logger, emitter, eventBase, sessi
|
|
|
72
74
|
level: triageOutput.result?.level || null,
|
|
73
75
|
roles: Array.from(recommendedRoles),
|
|
74
76
|
reasoning: triageOutput.result?.reasoning || null,
|
|
77
|
+
taskType: triageOutput.result?.taskType || "sw",
|
|
75
78
|
shouldDecompose,
|
|
76
79
|
subtasks
|
|
77
80
|
};
|
package/src/orchestrator.js
CHANGED
|
@@ -44,7 +44,8 @@ export async function runFlow({ task, config, logger, flags = {}, emitter = null
|
|
|
44
44
|
let testerEnabled = Boolean(config.pipeline?.tester?.enabled);
|
|
45
45
|
let securityEnabled = Boolean(config.pipeline?.security?.enabled);
|
|
46
46
|
let reviewerEnabled = config.pipeline?.reviewer?.enabled !== false;
|
|
47
|
-
|
|
47
|
+
// Triage is always mandatory — it classifies taskType for policy resolution
|
|
48
|
+
const triageEnabled = true;
|
|
48
49
|
|
|
49
50
|
// --- Dry-run: return summary without executing anything ---
|
|
50
51
|
if (flags.dryRun) {
|
|
@@ -282,8 +283,9 @@ export async function runFlow({ task, config, logger, flags = {}, emitter = null
|
|
|
282
283
|
if (flags.enableSecurity !== undefined) securityEnabled = Boolean(flags.enableSecurity);
|
|
283
284
|
|
|
284
285
|
// --- Policy resolver: gate stages by taskType ---
|
|
286
|
+
// Priority: explicit flag > config > triage classification > default (sw)
|
|
285
287
|
const resolvedPolicies = applyPolicies({
|
|
286
|
-
taskType: flags.taskType || config.taskType || null,
|
|
288
|
+
taskType: flags.taskType || config.taskType || stageResults.triage?.taskType || null,
|
|
287
289
|
policies: config.policies,
|
|
288
290
|
});
|
|
289
291
|
session.resolved_policies = resolvedPolicies;
|
package/src/prompts/triage.js
CHANGED
|
@@ -47,10 +47,10 @@ export function buildTriagePrompt({ task, instructions, availableRoles }) {
|
|
|
47
47
|
);
|
|
48
48
|
|
|
49
49
|
sections.push(
|
|
50
|
-
"Classify the task complexity, recommend only the necessary pipeline roles, and assess whether the task should be decomposed into smaller subtasks.",
|
|
50
|
+
"Classify the task complexity, determine its taskType, recommend only the necessary pipeline roles, and assess whether the task should be decomposed into smaller subtasks.",
|
|
51
51
|
"Keep the reasoning short and practical.",
|
|
52
52
|
"Return a single valid JSON object and nothing else.",
|
|
53
|
-
'JSON schema: {"level":"trivial|simple|medium|complex","roles":["planner|researcher|refactorer|reviewer|tester|security"],"reasoning":string,"shouldDecompose":boolean,"subtasks":string[]}'
|
|
53
|
+
'JSON schema: {"level":"trivial|simple|medium|complex","roles":["planner|researcher|refactorer|reviewer|tester|security"],"taskType":"sw|infra|doc|add-tests|refactor","reasoning":string,"shouldDecompose":boolean,"subtasks":string[]}'
|
|
54
54
|
);
|
|
55
55
|
|
|
56
56
|
sections.push(`## Task\n${task}`);
|
package/src/roles/triage-role.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { BaseRole } from "./base-role.js";
|
|
2
2
|
import { createAgent as defaultCreateAgent } from "../agents/index.js";
|
|
3
3
|
import { buildTriagePrompt } from "../prompts/triage.js";
|
|
4
|
+
import { VALID_TASK_TYPES } from "../guards/policy-resolver.js";
|
|
4
5
|
|
|
5
6
|
const VALID_LEVELS = new Set(["trivial", "simple", "medium", "complex"]);
|
|
6
7
|
const VALID_ROLES = new Set(["planner", "researcher", "refactorer", "reviewer", "tester", "security"]);
|
|
8
|
+
const FALLBACK_TASK_TYPE = "sw";
|
|
7
9
|
|
|
8
10
|
function resolveProvider(config) {
|
|
9
11
|
return (
|
|
@@ -74,6 +76,7 @@ export class TriageRole extends BaseRole {
|
|
|
74
76
|
level: "medium",
|
|
75
77
|
roles: ["reviewer"],
|
|
76
78
|
reasoning: "Unstructured output, using safe defaults.",
|
|
79
|
+
taskType: FALLBACK_TASK_TYPE,
|
|
77
80
|
provider,
|
|
78
81
|
raw: result.output
|
|
79
82
|
},
|
|
@@ -87,11 +90,13 @@ export class TriageRole extends BaseRole {
|
|
|
87
90
|
const reasoning = String(parsed.reasoning || "").trim() || "No reasoning provided.";
|
|
88
91
|
const shouldDecompose = Boolean(parsed.shouldDecompose);
|
|
89
92
|
const subtasks = normalizeSubtasks(parsed.subtasks);
|
|
93
|
+
const taskType = VALID_TASK_TYPES.includes(parsed.taskType) ? parsed.taskType : FALLBACK_TASK_TYPE;
|
|
90
94
|
|
|
91
95
|
const triageResult = {
|
|
92
96
|
level,
|
|
93
97
|
roles,
|
|
94
98
|
reasoning,
|
|
99
|
+
taskType,
|
|
95
100
|
provider
|
|
96
101
|
};
|
|
97
102
|
|
|
@@ -116,6 +121,7 @@ export class TriageRole extends BaseRole {
|
|
|
116
121
|
level: "medium",
|
|
117
122
|
roles: ["reviewer"],
|
|
118
123
|
reasoning: "Failed to parse triage output, using safe defaults.",
|
|
124
|
+
taskType: FALLBACK_TASK_TYPE,
|
|
119
125
|
provider,
|
|
120
126
|
raw: result.output
|
|
121
127
|
},
|
|
@@ -8,6 +8,7 @@ Return a single valid JSON object and nothing else:
|
|
|
8
8
|
```json
|
|
9
9
|
{
|
|
10
10
|
"level": "trivial|simple|medium|complex",
|
|
11
|
+
"taskType": "sw|infra|doc|add-tests|refactor",
|
|
11
12
|
"roles": ["planner", "researcher", "refactorer", "reviewer", "tester", "security"],
|
|
12
13
|
"reasoning": "brief practical justification",
|
|
13
14
|
"shouldDecompose": false,
|
|
@@ -15,7 +16,14 @@ Return a single valid JSON object and nothing else:
|
|
|
15
16
|
}
|
|
16
17
|
```
|
|
17
18
|
|
|
18
|
-
##
|
|
19
|
+
## Task type classification
|
|
20
|
+
- `sw`: writing or modifying business logic, features, APIs, components, services.
|
|
21
|
+
- `infra`: CI/CD, Docker, deploy scripts, build configuration, environment setup.
|
|
22
|
+
- `doc`: documentation, README, CHANGELOG, comments-only changes.
|
|
23
|
+
- `add-tests`: adding tests to existing code without changing functionality.
|
|
24
|
+
- `refactor`: restructuring code without changing external behavior.
|
|
25
|
+
|
|
26
|
+
## Complexity classification
|
|
19
27
|
- `trivial`: tiny, low-risk, straightforward. Usually no extra roles.
|
|
20
28
|
- `simple`: limited scope with low risk. Usually reviewer only.
|
|
21
29
|
- `medium`: moderate scope/risk. Reviewer required; optional planner/researcher.
|