karajan-code 2.5.0 → 2.6.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 +39 -4
- package/package.json +5 -2
- package/src/agents/aider-agent.js +1 -2
- package/src/agents/base-agent.js +63 -1
- package/src/agents/claude-agent.js +3 -4
- package/src/agents/codex-agent.js +1 -2
- package/src/agents/gemini-agent.js +1 -2
- package/src/agents/index.js +11 -2
- package/src/agents/opencode-agent.js +1 -2
- package/src/brain/decision-tracker.js +123 -0
- package/src/brain/decisor.js +243 -0
- package/src/brain/solomon-consult.js +171 -0
- package/src/budget/comparison.js +96 -0
- package/src/checks/binaries.js +123 -0
- package/src/checks/ci.js +105 -0
- package/src/checks/config-files.js +217 -0
- package/src/checks/dir-setup.js +63 -0
- package/src/checks/mcp-health.js +157 -0
- package/src/checks/node.js +61 -0
- package/src/checks/ports.js +110 -0
- package/src/checks/rtk.js +36 -0
- package/src/checks/runner.js +267 -0
- package/src/checks/skills.js +49 -0
- package/src/checks/sonar.js +67 -0
- package/src/checks/system.js +53 -0
- package/src/checks/tokens.js +96 -0
- package/src/checks/types.js +105 -0
- package/src/cli.js +29 -3
- package/src/commands/board.js +23 -0
- package/src/commands/doctor.js +130 -362
- package/src/commands/resume.js +1 -1
- package/src/commands/run.js +2 -1
- package/src/commands/skills.js +49 -0
- package/src/config/schema.js +222 -0
- package/src/config.js +32 -3
- package/src/guards/policy-resolver.js +8 -0
- package/src/hu/store.js +9 -0
- package/src/infrastructure/command-runner.js +44 -0
- package/src/infrastructure/environment.js +38 -0
- package/src/infrastructure/file-system-service.js +63 -0
- package/src/infrastructure/mocks.js +182 -0
- package/src/mcp/handlers/management-handlers.js +7 -2
- package/src/mcp/tools.js +10 -3
- package/src/orchestrator/config-init.js +16 -1
- package/src/orchestrator/flow-runner.js +2085 -0
- package/src/orchestrator/pipeline-context.js +17 -0
- package/src/orchestrator/preflight-checks.js +78 -4
- package/src/orchestrator/solomon-escalation.js +55 -0
- package/src/orchestrator/stages/stage-executor.js +155 -0
- package/src/orchestrator.js +19 -1923
- package/src/prompts/architect.js +2 -2
- package/src/prompts/coder.js +2 -2
- package/src/prompts/prompt-resolver.js +127 -0
- package/src/prompts/reviewer.js +2 -2
- package/src/roles/agent-role.js +9 -0
- package/src/roles/architect-role.js +3 -1
- package/src/roles/base-role.js +40 -2
- package/src/roles/coder-role.js +3 -1
- package/src/roles/security-role.js +12 -0
- package/src/roles/tester-role.js +11 -0
- package/src/session/journal/decisions-writer.js +200 -0
- package/src/session/journal/iteration-logger.js +194 -0
- package/src/session/journal/summary-writer.js +176 -0
- package/src/session/journal/tree-writer.js +164 -0
- package/src/skills/semantic-detector.js +147 -0
- package/src/skills/skill-detector.js +186 -8
- package/src/skills/skill-loader.js +131 -1
- package/src/skills/skills-cache.js +128 -0
- package/src/types/agent.js +55 -0
- package/src/types/config.js +114 -0
- package/src/types/hu.js +47 -0
- package/src/types/index.js +38 -0
- package/src/types/policy.js +43 -0
- package/src/types/session.js +74 -0
- package/src/types/solomon.js +87 -0
- package/src/types/stage.js +68 -0
- package/src/utils/display/event-handlers.js +389 -0
- package/src/utils/display/formatters.js +132 -0
- package/src/utils/display/header.js +48 -0
- package/src/utils/display/session-summary.js +108 -0
- package/src/utils/display/solomon.js +42 -0
- package/src/utils/port-check.js +45 -0
- package/src/utils/port-occupant.js +95 -0
- package/src/utils/provider-env.js +116 -0
- package/src/utils/with-timeout.js +42 -0
- package/templates/roles/architect/anthropic.md +65 -0
- package/templates/roles/architect/default.md +63 -0
- package/templates/roles/architect/google.md +52 -0
- package/templates/roles/architect/openai.md +51 -0
- package/templates/roles/architect/opencode.md +50 -0
- package/templates/roles/coder/anthropic.md +72 -0
- package/templates/roles/coder/default.md +69 -0
- package/templates/roles/coder/google.md +78 -0
- package/templates/roles/coder/openai.md +59 -0
- package/templates/roles/coder/opencode.md +49 -0
- package/templates/roles/planner/anthropic.md +50 -0
- package/templates/roles/planner/default.md +48 -0
- package/templates/roles/planner/google.md +66 -0
- package/templates/roles/planner/openai.md +46 -0
- package/templates/roles/planner/opencode.md +53 -0
- package/templates/roles/reviewer/anthropic.md +61 -0
- package/templates/roles/reviewer/default.md +62 -0
- package/templates/roles/reviewer/google.md +63 -0
- package/templates/roles/reviewer/openai.md +57 -0
- package/templates/roles/reviewer/opencode.md +42 -0
- package/templates/roles/solomon/anthropic.md +71 -0
- package/templates/roles/solomon/default.md +83 -0
- package/templates/roles/solomon/google.md +61 -0
- package/templates/roles/solomon/openai.md +53 -0
- package/templates/roles/solomon/opencode.md +55 -0
- package/src/utils/display.js +0 -669
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared check schema for doctor/preflight subsystem.
|
|
3
|
+
*
|
|
4
|
+
* A Check describes an environment requirement (binary present, port free,
|
|
5
|
+
* token configured, MCP reachable...). Each check can optionally remediate
|
|
6
|
+
* itself when it fails, using one of 4 strategies:
|
|
7
|
+
*
|
|
8
|
+
* - "auto" → fix without asking. Use for non-invasive, reversible changes
|
|
9
|
+
* (in-memory runtime overrides, starting existing services,
|
|
10
|
+
* creating files under ~/.karajan/, etc.)
|
|
11
|
+
* - "prompt" → ask user before fixing. Use for invasive changes that touch
|
|
12
|
+
* the user's system outside Karajan's scope (global npm install,
|
|
13
|
+
* writing kj.config.yml, `gh auth login`, etc.)
|
|
14
|
+
* - "manual" → cannot auto-fix, only report a hint (Node runtime upgrade,
|
|
15
|
+
* missing Docker, missing API key with no admin creds)
|
|
16
|
+
* - "none" → informational check, always OK (Karajan version, feature
|
|
17
|
+
* disabled by config)
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {Object} CheckResult
|
|
22
|
+
* @property {boolean} ok - true if check passes
|
|
23
|
+
* @property {"fail"|"warn"|"info"} [severity] - relevant when !ok; default "fail"
|
|
24
|
+
* @property {string} detail - human-readable status
|
|
25
|
+
* @property {string} [fix] - remediation hint shown when manual or user declines
|
|
26
|
+
* @property {Object} [extra] - structured data consumed by remediate (e.g. occupant PID, host, roles)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {Object} RemediationContext
|
|
31
|
+
* @property {Object} config - resolved Karajan config
|
|
32
|
+
* @property {AbortSignal} [signal] - cancellation
|
|
33
|
+
* @property {Object} extra - check's CheckResult.extra
|
|
34
|
+
* @property {Object} logger - logger instance
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Object} RemediationResult
|
|
39
|
+
* @property {boolean} fixed - true if remediation succeeded
|
|
40
|
+
* @property {string} detail - what was done, human-readable
|
|
41
|
+
* @property {Object} [changes] - runtime config overrides to merge into the active session
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {Object} Check
|
|
46
|
+
* @property {string} name - slug, unique across all checks (e.g. "node-version")
|
|
47
|
+
* @property {string} label - human label (e.g. "Node.js runtime")
|
|
48
|
+
* @property {"auto"|"prompt"|"manual"|"none"} strategy
|
|
49
|
+
* @property {(ctx: { config: Object }) => Promise<CheckResult>} detect
|
|
50
|
+
* @property {(ctx: RemediationContext) => Promise<RemediationResult>} [remediate]
|
|
51
|
+
* @property {string} [describe] - shown to user when strategy is "prompt"
|
|
52
|
+
* @property {(config: Object) => boolean} [applies] - if false, check is SKIPPED (lazy evaluation). Default: always applies.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @typedef {Object} CheckReport
|
|
57
|
+
* @property {string} name
|
|
58
|
+
* @property {string} label
|
|
59
|
+
* @property {"OK"|"FIXED"|"WARN"|"FAIL"|"SKIPPED"|"TIMEOUT"} status
|
|
60
|
+
* @property {"auto"|"prompt"|"manual"|"none"} strategy
|
|
61
|
+
* @property {string} detail - detect detail or remediate detail when FIXED
|
|
62
|
+
* @property {string} [fix] - remediation hint for FAIL/WARN
|
|
63
|
+
* @property {number} runMs - total time (detect + remediate + re-verify)
|
|
64
|
+
* @property {boolean} [cached] - future: served from cache
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @typedef {Object} RunReport
|
|
69
|
+
* @property {CheckReport[]} checks
|
|
70
|
+
* @property {Object} overrides - merged runtime overrides from auto-remediations
|
|
71
|
+
* @property {number} totalMs
|
|
72
|
+
* @property {{ ok: number, fixed: number, warn: number, fail: number, skipped: number, timeout: number }} summary
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Status constants.
|
|
77
|
+
*/
|
|
78
|
+
export const STATUS = Object.freeze({
|
|
79
|
+
OK: "OK",
|
|
80
|
+
FIXED: "FIXED",
|
|
81
|
+
WARN: "WARN",
|
|
82
|
+
FAIL: "FAIL",
|
|
83
|
+
SKIPPED: "SKIPPED",
|
|
84
|
+
TIMEOUT: "TIMEOUT",
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
export const STRATEGY = Object.freeze({
|
|
88
|
+
AUTO: "auto",
|
|
89
|
+
PROMPT: "prompt",
|
|
90
|
+
MANUAL: "manual",
|
|
91
|
+
NONE: "none",
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
export const SEVERITY = Object.freeze({
|
|
95
|
+
FAIL: "fail",
|
|
96
|
+
WARN: "warn",
|
|
97
|
+
INFO: "info",
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Whether the final status blocks the pipeline (for preflight).
|
|
102
|
+
*/
|
|
103
|
+
export function isBlocking(status) {
|
|
104
|
+
return status === STATUS.FAIL || status === STATUS.TIMEOUT;
|
|
105
|
+
}
|
package/src/cli.js
CHANGED
|
@@ -128,6 +128,10 @@ program
|
|
|
128
128
|
.option("--no-smart-models", "Disable smart model selection")
|
|
129
129
|
.option("--design", "Activate design refactoring mode (impeccable role applies design changes)")
|
|
130
130
|
.option("--domain <text-or-path>", "Domain knowledge: inline text or path to .md file")
|
|
131
|
+
.option("--skills-mode <mode>", "Skill detection mode: auto|regex|semantic|none (default: auto)")
|
|
132
|
+
.option("--brain <mode>", "Brain decisor: on|off (default: on). When off, only legacy flags drive routing.")
|
|
133
|
+
.option("--skip-role <role...>", "Force one or more roles OFF regardless of triage (e.g. --skip-role tester security)")
|
|
134
|
+
.option("--force-role <role...>", "Force one or more roles ON regardless of triage")
|
|
131
135
|
.option("--dry-run", "Show what would be executed without running anything")
|
|
132
136
|
.option("--json", "Output JSON only (no styled display)")
|
|
133
137
|
.option("-q, --quiet", "Show only stage status lines, suppress raw agent output (default)")
|
|
@@ -172,9 +176,22 @@ program
|
|
|
172
176
|
|
|
173
177
|
program
|
|
174
178
|
.command("doctor")
|
|
175
|
-
.description("Check environment requirements")
|
|
176
|
-
.
|
|
177
|
-
|
|
179
|
+
.description("Check environment requirements and auto-remediate when possible")
|
|
180
|
+
.option("--check-only", "Detect issues without applying fixes")
|
|
181
|
+
.option("-y, --yes", "Auto-confirm prompts for invasive remediations (CI mode)")
|
|
182
|
+
.option("--json", "Emit machine-readable JSON instead of human output")
|
|
183
|
+
.option("--verbose", "Include fix hints and timing for every check")
|
|
184
|
+
.action(async (flags) => {
|
|
185
|
+
const exitCode = await withConfig("doctor", {}, (ctx) =>
|
|
186
|
+
doctorCommand({
|
|
187
|
+
...ctx,
|
|
188
|
+
checkOnly: !!flags.checkOnly,
|
|
189
|
+
yes: !!flags.yes,
|
|
190
|
+
json: !!flags.json,
|
|
191
|
+
verbose: !!flags.verbose,
|
|
192
|
+
})
|
|
193
|
+
);
|
|
194
|
+
if (Number.isInteger(exitCode)) process.exit(exitCode);
|
|
178
195
|
});
|
|
179
196
|
|
|
180
197
|
program
|
|
@@ -198,6 +215,15 @@ program
|
|
|
198
215
|
await reportCommand(flags);
|
|
199
216
|
});
|
|
200
217
|
|
|
218
|
+
program
|
|
219
|
+
.command("skills [action]")
|
|
220
|
+
.description("Manage the local OpenSkills cache (actions: list | clear-cache)")
|
|
221
|
+
.action(async (action) => {
|
|
222
|
+
const { skillsCommand } = await import("./commands/skills.js");
|
|
223
|
+
const exitCode = await skillsCommand({ action: action || "list" });
|
|
224
|
+
if (Number.isInteger(exitCode)) process.exit(exitCode);
|
|
225
|
+
});
|
|
226
|
+
|
|
201
227
|
program
|
|
202
228
|
.command("roles [subcommand] [role]")
|
|
203
229
|
.description("List pipeline roles or show role template instructions")
|
package/src/commands/board.js
CHANGED
|
@@ -115,6 +115,29 @@ export async function boardStatus(port = 4000) {
|
|
|
115
115
|
};
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Render a highlighted cyan box with the HU Board URL + optional project name.
|
|
120
|
+
* Centralizes the banner used by both the init-time auto-start (flow-runner.js)
|
|
121
|
+
* and the post-planner auto-HU generation safety net so they stay in sync.
|
|
122
|
+
*
|
|
123
|
+
* @param {Object} params
|
|
124
|
+
* @param {string} params.url - "http://localhost:4000"
|
|
125
|
+
* @param {string} params.status - "started" | "already running"
|
|
126
|
+
* @param {string} [params.projectName] - optional project label
|
|
127
|
+
* @returns {string} ANSI-escaped box ready for console.log
|
|
128
|
+
*/
|
|
129
|
+
export function renderBoardBanner({ url, status, projectName }) {
|
|
130
|
+
const title = projectName ? ` Project: \u001b[1m${projectName}\u001b[0m` : null;
|
|
131
|
+
const lines = [
|
|
132
|
+
"",
|
|
133
|
+
"\u001b[36m\u256d\u2500 HU Board \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e",
|
|
134
|
+
`\u001b[36m\u2502\u001b[0m \u001b[1m${status}\u001b[0m \u001b[4m${url}\u001b[0m`,
|
|
135
|
+
];
|
|
136
|
+
if (title) lines.push(`\u001b[36m\u2502\u001b[0m${title}`);
|
|
137
|
+
lines.push("\u001b[36m\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\u001b[0m", "");
|
|
138
|
+
return lines.join("\n");
|
|
139
|
+
}
|
|
140
|
+
|
|
118
141
|
export async function boardCommand({ action = "start", port = 4000, logger }) {
|
|
119
142
|
switch (action) {
|
|
120
143
|
case "start": {
|