karajan-code 3.15.0 → 3.15.2
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 +1 -1
- package/package.json +2 -2
- package/packages/ai-trash/package.json +1 -1
- package/packages/hu-board/package.json +1 -1
- package/src/brain/agent-error-classifier.js +5 -1
- package/src/checks/node.js +6 -2
- package/src/git/automation.js +17 -4
- package/src/orchestrator/solomon-escalation.js +5 -1
- package/src/roles/commiter-role.js +10 -3
- package/src/utils/agent-detect.js +4 -1
- package/src/utils/git.js +10 -0
package/README.md
CHANGED
|
@@ -234,7 +234,7 @@ Karajan ships as **layers you opt into**. The base CLI is tiny (~5 MB). Heavier
|
|
|
234
234
|
- **Pipeline RAM peak**: 1–2 GB per `kj run` (one orchestrator + one coder + one reviewer subprocess at a time).
|
|
235
235
|
- **SQLite is in-process.** No separate DB daemon. `~/.karajan/` is a folder, not a service.
|
|
236
236
|
- **First-run Ollama pull**: ~5 min in the background; you can keep working — `kj` falls back to a cloud embedder if Ollama isn't ready yet.
|
|
237
|
-
- **Runtime**: Node.js ≥ 22.
|
|
237
|
+
- **Runtime**: Node.js ≥ 22.12.0 (Active LTS). v3.0.0 dropped Node 20 support. Use `kj doctor` to verify your environment.
|
|
238
238
|
|
|
239
239
|
## Two ways to use Karajan
|
|
240
240
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "karajan-code",
|
|
3
|
-
"version": "3.15.
|
|
3
|
+
"version": "3.15.2",
|
|
4
4
|
"description": "Local multi-agent coding orchestrator with TDD, SonarQube, and code review pipeline",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"cli"
|
|
25
25
|
],
|
|
26
26
|
"engines": {
|
|
27
|
-
"node": ">=22.
|
|
27
|
+
"node": ">=22.12.0"
|
|
28
28
|
},
|
|
29
29
|
"kj": {
|
|
30
30
|
"harden": {
|
|
@@ -31,7 +31,11 @@ export const ERROR_CLASS = Object.freeze({
|
|
|
31
31
|
const ONE_HOUR_MS = 60 * 60 * 1000;
|
|
32
32
|
const ONE_WEEK_MS = 7 * 24 * 60 * 60 * 1000;
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
// `error\s+authenticating` + `IneligibleTierError` (KJC-BUG-0113): the
|
|
35
|
+
// retired Gemini Code Assist CLI fails with "Error authenticating:
|
|
36
|
+
// IneligibleTierError … migrate to Antigravity" — it classified as
|
|
37
|
+
// UNKNOWN_FATAL and left the run without the AUTH escalation message.
|
|
38
|
+
const AUTH_PATTERNS = /\b401\b|\b403\b|unauthorized|invalid\s+api\s+key|authentication\s+failed|expired\s+token|error\s+authenticating|IneligibleTierError/i;
|
|
35
39
|
const SILENCED_PATTERNS = /killed\s+after\s+\d+\s*ms|silence\s*timeout|no\s+output\s+for\s+\d+/i;
|
|
36
40
|
// `session\s+limit` / `weekly\s+limit` cover Claude Code's usage caps
|
|
37
41
|
// ("You've hit your session limit · resets 10:10pm"). Without them the
|
package/src/checks/node.js
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
* Node.js runtime version check. Requires Node >= 22 — the Active LTS
|
|
3
3
|
* baseline since Karajan v3.0.0 (KJC-TSK-0500, 2026-06-03). Node 20 was
|
|
4
4
|
* dropped because (a) Node 20 reaches EOL on 2026-04-30 and (b) three
|
|
5
|
-
* dependencies forced the bump:
|
|
6
|
-
*
|
|
5
|
+
* dependencies forced the bump: commander 15 needs ≥22.12.0 and
|
|
6
|
+
* better-sqlite3 v12.10+ dropped Node 20 prebuilds. engines.node is
|
|
7
|
+
* ">=22.12.0" — the highest RUNTIME floor. KJC-BUG-0111: it briefly sat
|
|
8
|
+
* at 22.22.1 (lint-staged 17's floor — a devDependency end users never
|
|
9
|
+
* run) and npm silently served karajan-code@2.34.0 to every Node
|
|
10
|
+
* 22.0-22.21 install; keep dev-tool floors out of engines.
|
|
7
11
|
* Strategy: manual — we cannot auto-upgrade the runtime. Users on older
|
|
8
12
|
* Node get a clear upgrade instruction with nvm + brew hints instead of a
|
|
9
13
|
* silent runtime crash.
|
package/src/git/automation.js
CHANGED
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
commitAll,
|
|
17
17
|
pushBranch,
|
|
18
18
|
createPullRequest,
|
|
19
|
-
listPendingPaths
|
|
19
|
+
listPendingPaths,
|
|
20
|
+
hasRemote
|
|
20
21
|
} from "../utils/git.js";
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -276,7 +277,19 @@ export async function finalizeGitAutomation({ config, gitCtx, task, logger, sess
|
|
|
276
277
|
logger.info(committed ? "Committed changes" : "No changes to commit");
|
|
277
278
|
}
|
|
278
279
|
|
|
279
|
-
|
|
280
|
+
// KJC-BUG-0112: without an `origin` remote (the quickstart scenario:
|
|
281
|
+
// fresh folder + git init) push/PR automation has nothing to talk to —
|
|
282
|
+
// fetchBase used to throw here and escalate to Solomon on EVERY
|
|
283
|
+
// iteration, burning the whole budget on an expected condition.
|
|
284
|
+
const remoteAvailable = (config.git.auto_push || config.git.auto_pr)
|
|
285
|
+
? await hasRemote()
|
|
286
|
+
: false;
|
|
287
|
+
if ((config.git.auto_push || config.git.auto_pr) && !remoteAvailable) {
|
|
288
|
+
logger.info("No remote configured — skipping push/PR automation");
|
|
289
|
+
await addCheckpoint(session, { stage: "git-push", skipped: "no-remote" });
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (remoteAvailable && (config.git.auto_push || config.git.auto_pr)) {
|
|
280
293
|
await fetchBase(gitCtx.baseBranch);
|
|
281
294
|
await ensureBranchUpToDateWithBase({
|
|
282
295
|
branch: gitCtx.branch,
|
|
@@ -286,14 +299,14 @@ export async function finalizeGitAutomation({ config, gitCtx, task, logger, sess
|
|
|
286
299
|
await addCheckpoint(session, { stage: "git-rebase-check", branch: gitCtx.branch });
|
|
287
300
|
}
|
|
288
301
|
|
|
289
|
-
if (config.git.auto_push || config.git.auto_pr) {
|
|
302
|
+
if (remoteAvailable && (config.git.auto_push || config.git.auto_pr)) {
|
|
290
303
|
await pushBranch(gitCtx.branch);
|
|
291
304
|
await addCheckpoint(session, { stage: "git-push", branch: gitCtx.branch });
|
|
292
305
|
logger.info(`Pushed branch: ${gitCtx.branch}`);
|
|
293
306
|
}
|
|
294
307
|
|
|
295
308
|
let prUrl = session.ci_pr_url || null;
|
|
296
|
-
if (config.git.auto_pr && !prUrl) {
|
|
309
|
+
if (remoteAvailable && config.git.auto_pr && !prUrl) {
|
|
297
310
|
const body = buildPrBody({ task, stageResults });
|
|
298
311
|
prUrl = await createPullRequest({
|
|
299
312
|
baseBranch: gitCtx.baseBranch,
|
|
@@ -123,7 +123,11 @@ export async function invokeSolomon({ config, logger, emitter, eventBase, stage,
|
|
|
123
123
|
return escalateToHuman({ askQuestion, session, emitter, eventBase, stage, conflict, iteration });
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
// KJC-BUG-0113: the fallback used to be "gemini" — Google retired the
|
|
127
|
+
// Gemini Code Assist CLI for individuals (IneligibleTierError), so an
|
|
128
|
+
// unconfigured Solomon died on every escalation. Claude matches the
|
|
129
|
+
// brain.provider default.
|
|
130
|
+
const solomonProvider = config?.roles?.solomon?.provider || "claude";
|
|
127
131
|
emitProgress(
|
|
128
132
|
emitter,
|
|
129
133
|
makeEvent("solomon:start", { ...eventBase, stage: "solomon" }, {
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
commitAll,
|
|
9
9
|
pushBranch,
|
|
10
10
|
createPullRequest,
|
|
11
|
-
revParse
|
|
11
|
+
revParse,
|
|
12
|
+
hasRemote
|
|
12
13
|
} from "../utils/git.js";
|
|
13
14
|
|
|
14
15
|
function buildCommitMessage(task) {
|
|
@@ -59,7 +60,13 @@ export class CommiterRole extends BaseRole {
|
|
|
59
60
|
await commitAll(msg);
|
|
60
61
|
const commitHash = await revParse("HEAD");
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
// KJC-BUG-0112: no `origin` remote (quickstart scenario) → skip
|
|
64
|
+
// push/PR instead of throwing on fetch.
|
|
65
|
+
const remoteAvailable = push ? await hasRemote() : false;
|
|
66
|
+
if (push && !remoteAvailable) {
|
|
67
|
+
this.logger?.info?.("No remote configured — skipping push/PR");
|
|
68
|
+
}
|
|
69
|
+
if (push && remoteAvailable) {
|
|
63
70
|
const baseBranch = this.config.base_branch || "main";
|
|
64
71
|
await fetchBase(baseBranch);
|
|
65
72
|
await ensureBranchUpToDateWithBase({
|
|
@@ -71,7 +78,7 @@ export class CommiterRole extends BaseRole {
|
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
let prUrl = null;
|
|
74
|
-
if (push && createPr) {
|
|
81
|
+
if (push && createPr && remoteAvailable) {
|
|
75
82
|
const baseBranch = this.config.base_branch || "main";
|
|
76
83
|
prUrl = await createPullRequest({
|
|
77
84
|
baseBranch,
|
|
@@ -12,7 +12,10 @@ const KNOWN_AGENTS = [
|
|
|
12
12
|
|
|
13
13
|
export async function checkBinary(name, versionArg = "--version") {
|
|
14
14
|
const resolved = resolveBin(name);
|
|
15
|
-
|
|
15
|
+
// KJC-BUG-0113: a zombie CLI that hangs on --version (seen with the
|
|
16
|
+
// retired Gemini Code Assist binary) must not hang init/preflight —
|
|
17
|
+
// 5s is generous for a version print.
|
|
18
|
+
const res = await runCommand(resolved, [versionArg], { timeout: 5000 });
|
|
16
19
|
const version = (res.stdout || res.stderr || "").split("\n")[0].trim();
|
|
17
20
|
return { ok: res.exitCode === 0, version, path: resolved };
|
|
18
21
|
}
|
package/src/utils/git.js
CHANGED
|
@@ -251,6 +251,16 @@ export async function commitAll(message, cwd = null) {
|
|
|
251
251
|
return { committed: true, commit: { hash, message: commitMessage } };
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
/**
|
|
255
|
+
* KJC-BUG-0112: whether the repo has an `origin` remote. The quickstart
|
|
256
|
+
* scenario (fresh folder + git init) has none — post-approval push/PR
|
|
257
|
+
* automation must skip instead of failing and escalating to Solomon.
|
|
258
|
+
*/
|
|
259
|
+
export async function hasRemote(cwd = null) {
|
|
260
|
+
const res = await run("git", ["remote", "get-url", "origin"], cwd ? { cwd } : {});
|
|
261
|
+
return res.exitCode === 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
254
264
|
export async function pushBranch(branch, cwd = null) {
|
|
255
265
|
await runGit(["push", "-u", "origin", branch], cwd ? { cwd } : {});
|
|
256
266
|
}
|