karajan-code 1.59.0 → 2.0.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.
Files changed (115) hide show
  1. package/README.md +2 -0
  2. package/package.json +1 -1
  3. package/scripts/install.js +18 -15
  4. package/src/agents/aider-agent.js +0 -7
  5. package/src/agents/claude-agent.js +34 -6
  6. package/src/agents/codex-agent.js +2 -6
  7. package/src/agents/gemini-agent.js +0 -4
  8. package/src/agents/opencode-agent.js +0 -4
  9. package/src/{becaria → ci}/dispatch.js +13 -13
  10. package/src/{becaria → ci}/pr-diff.js +1 -1
  11. package/src/cli.js +3 -2
  12. package/src/commands/agents.js +0 -1
  13. package/src/commands/doctor.js +22 -40
  14. package/src/commands/init.js +8 -8
  15. package/src/commands/report.js +0 -13
  16. package/src/commands/review.js +17 -17
  17. package/src/commands/run.js +1 -2
  18. package/src/commands/status.js +1 -7
  19. package/src/config.js +10 -52
  20. package/src/domains/domain-loader.js +85 -4
  21. package/src/git/automation.js +9 -9
  22. package/src/guards/output-guard.js +0 -17
  23. package/src/mcp/handlers/direct-handlers.js +1 -1
  24. package/src/mcp/handlers/run-handler.js +1 -2
  25. package/src/mcp/sovereignty-guard.js +2 -2
  26. package/src/mcp/tools.js +3 -2
  27. package/src/orchestrator/brain-coordinator.js +165 -0
  28. package/src/orchestrator/ci-integration.js +139 -0
  29. package/src/orchestrator/config-init.js +435 -0
  30. package/src/orchestrator/direct-actions.js +186 -0
  31. package/src/orchestrator/feedback-enrichment.js +140 -0
  32. package/src/orchestrator/feedback-queue.js +152 -0
  33. package/src/orchestrator/flow-control.js +159 -0
  34. package/src/orchestrator/post-loop-stages.js +20 -15
  35. package/src/orchestrator/preflight-checks.js +7 -3
  36. package/src/orchestrator/role-output-compressor.js +190 -0
  37. package/src/orchestrator/session-journal.js +344 -0
  38. package/src/orchestrator/solomon-escalation.js +38 -5
  39. package/src/orchestrator/solomon-rules.js +32 -33
  40. package/src/orchestrator/stages/reviewer-stage.js +16 -5
  41. package/src/orchestrator/stages/sonar-stage.js +24 -1
  42. package/src/orchestrator/verification-gate.js +146 -0
  43. package/src/orchestrator.js +435 -661
  44. package/src/planning-game/client.js +2 -2
  45. package/src/planning-game/pipeline-adapter.js +1 -1
  46. package/src/prompts/coder.js +17 -3
  47. package/src/prompts/reviewer.js +2 -2
  48. package/src/prompts/rtk-snippet.js +3 -5
  49. package/src/review/diff-generator.js +66 -17
  50. package/src/review/snapshot-diff.js +122 -0
  51. package/src/review/tdd-policy.js +4 -2
  52. package/src/roles/agent-role.js +135 -0
  53. package/src/roles/architect-role.js +61 -108
  54. package/src/roles/audit-role.js +25 -71
  55. package/src/roles/coder-role.js +32 -57
  56. package/src/roles/discover-role.js +30 -71
  57. package/src/roles/hu-reviewer-role.js +51 -99
  58. package/src/roles/impeccable-role.js +34 -91
  59. package/src/roles/index.js +2 -0
  60. package/src/roles/karajan-brain-role.js +134 -0
  61. package/src/roles/planner-role.js +40 -75
  62. package/src/roles/refactorer-role.js +22 -64
  63. package/src/roles/researcher-role.js +52 -118
  64. package/src/roles/reviewer-role.js +69 -126
  65. package/src/roles/security-role.js +38 -102
  66. package/src/roles/solomon-role.js +71 -15
  67. package/src/roles/tester-role.js +121 -95
  68. package/src/roles/triage-role.js +50 -111
  69. package/src/session-store.js +1 -1
  70. package/src/skills/skill-detector.js +11 -0
  71. package/src/sonar/config-resolver.js +20 -1
  72. package/src/sonar/credentials.js +17 -0
  73. package/src/sonar/project-key.js +1 -1
  74. package/src/sonar/scanner.js +1 -1
  75. package/src/utils/banner.js +66 -0
  76. package/src/utils/display.js +35 -17
  77. package/src/utils/injection-guard.js +23 -8
  78. package/src/utils/logger.js +6 -1
  79. package/src/utils/process.js +3 -4
  80. package/src/utils/role-assigner.js +131 -0
  81. package/src/utils/update-check.js +5 -1
  82. package/src/utils/welcome.js +3 -8
  83. package/src/webperf/devtools-detect.js +70 -23
  84. package/templates/roles/coder.md +7 -0
  85. package/templates/roles/karajan-brain.md +95 -0
  86. package/templates/roles/solomon.md +67 -106
  87. package/templates/workflows/automerge.yml +4 -4
  88. package/templates/workflows/houston-override.yml +4 -4
  89. package/templates/workflows/{becaria-gateway.yml → kj-ci-gateway.yml} +12 -12
  90. package/src/proxy/adapters/anthropic.js +0 -131
  91. package/src/proxy/adapters/gemini.js +0 -106
  92. package/src/proxy/adapters/index.js +0 -51
  93. package/src/proxy/adapters/openai.js +0 -71
  94. package/src/proxy/compression/ai-compressor.js +0 -209
  95. package/src/proxy/compression/dedup-cache.js +0 -100
  96. package/src/proxy/compression/deterministic/bash-build.js +0 -60
  97. package/src/proxy/compression/deterministic/bash-git.js +0 -101
  98. package/src/proxy/compression/deterministic/bash-infra.js +0 -64
  99. package/src/proxy/compression/deterministic/bash-misc.js +0 -53
  100. package/src/proxy/compression/deterministic/bash-pkg.js +0 -49
  101. package/src/proxy/compression/deterministic/bash-test.js +0 -61
  102. package/src/proxy/compression/deterministic/glob.js +0 -26
  103. package/src/proxy/compression/deterministic/grep.js +0 -53
  104. package/src/proxy/compression/deterministic/index.js +0 -58
  105. package/src/proxy/compression/deterministic/read.js +0 -22
  106. package/src/proxy/compression/deterministic/utils.js +0 -33
  107. package/src/proxy/compression/pipeline.js +0 -270
  108. package/src/proxy/middleware/prompt-injector.js +0 -165
  109. package/src/proxy/middleware/response-interceptor.js +0 -223
  110. package/src/proxy/progress-monitor.js +0 -98
  111. package/src/proxy/proxy-lifecycle.js +0 -198
  112. package/src/proxy/proxy-server.js +0 -239
  113. package/src/proxy/security.js +0 -45
  114. /package/src/{becaria → ci}/index.js +0 -0
  115. /package/src/{becaria → ci}/repo.js +0 -0
@@ -0,0 +1,131 @@
1
+ // Smart role assignment based on available AI agents.
2
+ // Used by both kj init (interactive) and auto-init (non-interactive).
3
+
4
+ import { detectAvailableAgents } from "./agent-detect.js";
5
+
6
+ // Agent capability tiers (higher = more capable for complex reasoning)
7
+ const CAPABILITY_TIERS = {
8
+ claude: 5, // Best for reasoning, orchestration, complex tasks
9
+ codex: 4, // Strong coder, good reviewer
10
+ gemini: 3, // Good general purpose
11
+ aider: 2, // Good coder, limited reasoning
12
+ opencode: 2 // Similar to aider
13
+ };
14
+
15
+ // Role requirements: what capability level is ideal for each role
16
+ const ROLE_PREFERENCES = {
17
+ brain: { minTier: 4, prefer: "claude", description: "Karajan Brain (orchestrator)" },
18
+ solomon: { minTier: 3, prefer: "gemini", description: "Solomon (judge/arbiter)" },
19
+ coder: { minTier: 2, prefer: "claude", description: "Coder" },
20
+ reviewer: { minTier: 3, prefer: "codex", description: "Reviewer" },
21
+ planner: { minTier: 4, prefer: "claude", description: "Planner" },
22
+ researcher: { minTier: 3, prefer: "claude", description: "Researcher" },
23
+ architect: { minTier: 4, prefer: "claude", description: "Architect" },
24
+ tester: { minTier: 3, prefer: "claude", description: "Tester" },
25
+ security: { minTier: 3, prefer: "claude", description: "Security" },
26
+ triage: { minTier: 3, prefer: "claude", description: "Triage" }
27
+ };
28
+
29
+ /**
30
+ * Assign the best available agent to a role.
31
+ * Prefers the role's preferred agent if available, then falls back by capability tier.
32
+ */
33
+ function assignRole(roleName, availableAgents) {
34
+ const pref = ROLE_PREFERENCES[roleName];
35
+ if (!pref) return availableAgents[0]?.name || "claude";
36
+
37
+ // Preferred agent available?
38
+ if (availableAgents.find(a => a.name === pref.prefer)) {
39
+ return pref.prefer;
40
+ }
41
+
42
+ // Sort by capability tier (descending) and pick the best available
43
+ const sorted = [...availableAgents].sort(
44
+ (a, b) => (CAPABILITY_TIERS[b.name] || 1) - (CAPABILITY_TIERS[a.name] || 1)
45
+ );
46
+
47
+ return sorted[0]?.name || "claude";
48
+ }
49
+
50
+ /**
51
+ * Try to diversify: if possible, use a different agent for reviewer than coder.
52
+ */
53
+ function diversifyReviewer(coderAgent, availableAgents) {
54
+ const alternatives = availableAgents.filter(a => a.name !== coderAgent);
55
+ if (alternatives.length === 0) return coderAgent;
56
+
57
+ const sorted = [...alternatives].sort(
58
+ (a, b) => (CAPABILITY_TIERS[b.name] || 1) - (CAPABILITY_TIERS[a.name] || 1)
59
+ );
60
+ return sorted[0].name;
61
+ }
62
+
63
+ /**
64
+ * Auto-assign all roles based on detected agents. Non-interactive.
65
+ * Returns a config-ready object with role assignments.
66
+ */
67
+ export async function autoAssignRoles(logger) {
68
+ const agents = await detectAvailableAgents();
69
+ const available = agents.filter(a => a.available);
70
+
71
+ if (available.length === 0) {
72
+ logger?.warn?.("No AI agents detected. Using claude as default for all roles.");
73
+ return { assignments: getDefaultAssignments("claude"), agents, available: [] };
74
+ }
75
+
76
+ logger?.info?.(`Detected ${available.length} AI agent(s): ${available.map(a => `${a.name} (${a.version})`).join(", ")}`);
77
+
78
+ const coder = assignRole("coder", available);
79
+ const reviewer = available.length > 1 ? diversifyReviewer(coder, available) : coder;
80
+ const brain = assignRole("brain", available);
81
+ const solomon = available.length > 1 ? diversifyReviewer(brain, available) : brain;
82
+
83
+ const assignments = {
84
+ brain,
85
+ solomon,
86
+ coder,
87
+ reviewer,
88
+ planner: assignRole("planner", available),
89
+ researcher: assignRole("researcher", available),
90
+ architect: assignRole("architect", available),
91
+ tester: assignRole("tester", available),
92
+ security: assignRole("security", available),
93
+ triage: assignRole("triage", available)
94
+ };
95
+
96
+ logger?.info?.(`Role assignments: Brain=${brain}, Solomon=${solomon}, Coder=${coder}, Reviewer=${reviewer}`);
97
+
98
+ return { assignments, agents, available };
99
+ }
100
+
101
+ function getDefaultAssignments(agent) {
102
+ return {
103
+ brain: agent, solomon: agent, coder: agent, reviewer: agent,
104
+ planner: agent, researcher: agent, architect: agent,
105
+ tester: agent, security: agent, triage: agent
106
+ };
107
+ }
108
+
109
+ /**
110
+ * Apply role assignments to a Karajan config object.
111
+ */
112
+ export function applyRoleAssignments(config, assignments) {
113
+ config.coder = assignments.coder;
114
+ config.reviewer = assignments.reviewer;
115
+
116
+ const roleNames = ["coder", "reviewer", "planner", "researcher", "architect",
117
+ "tester", "security", "triage", "solomon"];
118
+
119
+ for (const role of roleNames) {
120
+ config.roles = config.roles || {};
121
+ config.roles[role] = config.roles[role] || {};
122
+ config.roles[role].provider = assignments[role] || assignments.coder;
123
+ }
124
+
125
+ // Brain is a new top-level config (not in roles yet — will be when KarajanBrainRole is implemented)
126
+ config.brain = { provider: assignments.brain };
127
+
128
+ return config;
129
+ }
130
+
131
+ export { CAPABILITY_TIERS, ROLE_PREFERENCES };
@@ -20,7 +20,11 @@ export async function checkForUpdate(currentVersion) {
20
20
  const cache = JSON.parse(raw);
21
21
  if (cache.checkedAt && Date.now() - cache.checkedAt < CACHE_TTL_MS) {
22
22
  if (!cache.latest || cache.latest === currentVersion) return null;
23
- return { updateAvailable: true, latest: cache.latest, current: currentVersion };
23
+ // Only show update if latest is actually NEWER than current
24
+ if (compareVersions(cache.latest, currentVersion) > 0) {
25
+ return { updateAvailable: true, latest: cache.latest, current: currentVersion };
26
+ }
27
+ return null;
24
28
  }
25
29
  } catch { /* no cache or expired */ }
26
30
 
@@ -1,3 +1,5 @@
1
+ import { printBanner } from "./banner.js";
2
+
1
3
  const A = {
2
4
  reset: "\x1b[0m",
3
5
  bold: "\x1b[1m",
@@ -7,8 +9,6 @@ const A = {
7
9
  yellow: "\x1b[33m",
8
10
  };
9
11
 
10
- const BAR = `${A.dim}${"─".repeat(44)}${A.reset}`;
11
-
12
12
  const QUICK_START = [
13
13
  ["kj run <task>", "Run the full coder+reviewer pipeline"],
14
14
  ["kj init", "Initialize config and setup"],
@@ -24,12 +24,7 @@ const QUICK_START = [
24
24
  * @param {object} [opts.config] - Loaded KJ config (optional, shows configured agents)
25
25
  */
26
26
  export function printWelcomeScreen({ version, config = null }) {
27
- console.log();
28
- console.log(BAR);
29
- console.log(` ${A.bold}${A.cyan}▶ Karajan Code${A.reset} ${A.dim}v${version}${A.reset}`);
30
- console.log(` ${A.dim}AI-powered coding pipeline${A.reset}`);
31
- console.log(BAR);
32
- console.log();
27
+ printBanner(version, { force: true });
33
28
 
34
29
  if (config) {
35
30
  const coder = config.roles?.coder?.provider || config.coder || "claude";
@@ -1,32 +1,81 @@
1
- /**
2
- * Chrome DevTools MCP detection and WebPerf skill auto-installation.
3
- */
1
+ // Chrome DevTools MCP detection and WebPerf skill auto-installation.
4
2
 
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
5
+ import os from "node:os";
5
6
  import { isOpenSkillsAvailable, installSkill, listSkills } from "../skills/openskills-client.js";
6
7
 
7
- /** Skill names to auto-install when WebPerf is enabled. */
8
+ /** Skill names relevant for WebPerf analysis. Already installed globally via openskills. */
8
9
  export const WEBPERF_SKILLS = [
9
- "webperf",
10
- "webperf-core-web-vitals",
11
- "webperf-loading"
10
+ "optimize",
11
+ "audit",
12
+ "polish"
12
13
  ];
13
14
 
14
15
  /**
15
16
  * Check whether Chrome DevTools MCP is configured and available.
16
- * Since Karajan runs as an MCP server itself, it cannot directly call other MCPs.
17
- * Instead, we check the config flag `webperf.devtools_mcp`.
18
- * @param {object} config — merged Karajan config
17
+ * Checks: (1) config flag, (2) Claude MCP config (~/.claude.json), (3) VS Code MCP settings.
18
+ * @param {object} config - merged Karajan config
19
19
  * @returns {boolean}
20
20
  */
21
21
  export function isDevToolsMcpAvailable(config) {
22
- return Boolean(config?.webperf?.devtools_mcp);
22
+ // Explicit config flag takes priority
23
+ if (config?.webperf?.devtools_mcp === true) return true;
24
+ if (config?.webperf?.devtools_mcp === false) return false;
25
+
26
+ // Check cached detection result
27
+ if (_devToolsDetected !== null) return _devToolsDetected;
28
+
29
+ // Not yet detected - return false (async detection runs at init)
30
+ return false;
31
+ }
32
+
33
+ let _devToolsDetected = null;
34
+
35
+ /**
36
+ * Auto-detect Chrome DevTools MCP from system configuration.
37
+ * Checks ~/.claude.json and VS Code MCP settings.
38
+ * Call once at pipeline init.
39
+ */
40
+ export async function detectDevToolsMcp(logger) {
41
+ // Check Claude MCP config
42
+ const claudeConfigPath = path.join(os.homedir(), ".claude.json");
43
+ try {
44
+ const raw = await fs.readFile(claudeConfigPath, "utf8");
45
+ const parsed = JSON.parse(raw);
46
+ const mcpServers = parsed?.mcpServers || parsed?.mcp_servers || {};
47
+ if (mcpServers["chrome-devtools"] || mcpServers["chrome_devtools"]) {
48
+ _devToolsDetected = true;
49
+ logger?.info?.("Chrome DevTools MCP detected in ~/.claude.json");
50
+ return true;
51
+ }
52
+ } catch { /* file not found or parse error */ }
53
+
54
+ // Check VS Code MCP settings
55
+ const vscodePaths = [
56
+ path.join(os.homedir(), ".vscode", "settings.json"),
57
+ path.join(process.cwd(), ".vscode", "settings.json")
58
+ ];
59
+ for (const vscPath of vscodePaths) {
60
+ try {
61
+ const raw = await fs.readFile(vscPath, "utf8");
62
+ if (raw.includes("chrome-devtools") || raw.includes("chrome_devtools")) {
63
+ _devToolsDetected = true;
64
+ logger?.info?.(`Chrome DevTools MCP detected in ${vscPath}`);
65
+ return true;
66
+ }
67
+ } catch { /* not found */ }
68
+ }
69
+
70
+ _devToolsDetected = false;
71
+ return false;
23
72
  }
24
73
 
25
74
  /**
26
75
  * Ensure WebPerf skills are installed via OpenSkills.
27
76
  * Installs any missing skills from WEBPERF_SKILLS.
28
- * @param {string} projectDir — absolute path to the project root
29
- * @param {object} [logger] — optional logger ({ info, warn })
77
+ * @param {string} projectDir - absolute path to the project root
78
+ * @param {object} [logger] - optional logger ({ info, warn })
30
79
  * @returns {Promise<{ installed: string[], alreadyInstalled: string[], skipped: string[] }>}
31
80
  */
32
81
  export async function ensureWebPerfSkills(projectDir, logger) {
@@ -34,12 +83,12 @@ export async function ensureWebPerfSkills(projectDir, logger) {
34
83
 
35
84
  const available = await isOpenSkillsAvailable();
36
85
  if (!available) {
37
- logger?.warn?.("OpenSkills CLI not available — skipping WebPerf skill installation");
86
+ logger?.debug?.("OpenSkills CLI not available - WebPerf skills unavailable");
38
87
  result.skipped = [...WEBPERF_SKILLS];
39
88
  return result;
40
89
  }
41
90
 
42
- // Get currently installed skills
91
+ // List skills (includes global installs)
43
92
  const listResult = await listSkills({ projectDir });
44
93
  const installedNames = new Set(
45
94
  (listResult.ok ? listResult.skills : []).map(s => s.name)
@@ -48,18 +97,16 @@ export async function ensureWebPerfSkills(projectDir, logger) {
48
97
  for (const skill of WEBPERF_SKILLS) {
49
98
  if (installedNames.has(skill)) {
50
99
  result.alreadyInstalled.push(skill);
51
- continue;
52
- }
53
-
54
- const installResult = await installSkill(skill, { projectDir });
55
- if (installResult.ok) {
56
- result.installed.push(skill);
57
- logger?.info?.(`Installed WebPerf skill: ${skill}`);
58
100
  } else {
101
+ // Skills should be installed globally via `openskills install owner/repo`
102
+ // Don't attempt auto-install with bare names — just note they're missing
59
103
  result.skipped.push(skill);
60
- logger?.warn?.(`Failed to install WebPerf skill "${skill}": ${installResult.error}`);
61
104
  }
62
105
  }
63
106
 
107
+ if (result.alreadyInstalled.length > 0) {
108
+ logger?.info?.(`WebPerf skills available: ${result.alreadyInstalled.join(", ")}`);
109
+ }
110
+
64
111
  return result;
65
112
  }
@@ -45,6 +45,13 @@ Before reporting done, verify that ALL parts of the task are addressed:
45
45
  - If unintended changes are detected, revert immediately with `git checkout -- <file>`.
46
46
  - Pay special attention to CSS, HTML, and config files where full rewrites destroy prior work.
47
47
 
48
+ ## Code Quality Rules
49
+
50
+ - Follow SOLID principles. Write small, focused functions (< 30 lines).
51
+ - Make atomic commits: 1 logical change = 1 commit. Keep PRs small and reviewable.
52
+ - Security: use httpOnly cookies for auth tokens, validate all input, parameterize queries, never expose secrets.
53
+ - No console.log in production code -- use a structured logger. No 'any' types -- use JSDoc annotations.
54
+
48
55
  ## Output format
49
56
 
50
57
  Return a JSON object:
@@ -0,0 +1,95 @@
1
+ # Karajan Brain — Central Pipeline Orchestrator
2
+
3
+ You are the central intelligence of the Karajan pipeline. Every role output passes through you. You decide what happens next.
4
+
5
+ ## Your responsibilities
6
+
7
+ 1. **Route** — decide which role runs next based on current state
8
+ 2. **Enrich** — transform vague feedback into concrete, actionable instructions
9
+ 3. **Verify** — check that each role actually did its job before moving on
10
+ 4. **Act directly** — execute commands when a full role invocation isn't needed
11
+ 5. **Consult Solomon** — only when facing a genuine dilemma
12
+
13
+ ## Skills
14
+
15
+ ### 1. route-decision
16
+ Decide the next role based on pipeline state.
17
+ - If coder just finished successfully → reviewer
18
+ - If reviewer approved → next quality gate (tester/security/impeccable) or done
19
+ - If reviewer rejected with issues → coder (with enriched feedback)
20
+ - If tester/security failed → coder (with specific fix instructions)
21
+ - If max iterations reached and still failing → consult Solomon
22
+ - If approved and all gates pass → done
23
+
24
+ ### 2. prompt-enrichment
25
+ When feedback is vague, make it actionable.
26
+ - Identify concrete file paths from the project structure
27
+ - Add line numbers when possible
28
+ - Suggest specific code changes
29
+ - Break complex feedback into numbered steps
30
+ - Include test commands to run
31
+
32
+ Example transformation:
33
+ - Vague: "auth test suite missing refresh token coverage"
34
+ - Enriched: "In packages/server/tests/auth/, create refresh-token.test.js. Test cases: (1) POST /auth/refresh with valid token returns new pair, (2) expired token returns 401, (3) invalid token returns 401. Reference packages/server/src/auth/jwt.js for the refresh logic."
35
+
36
+ ### 3. output-verification
37
+ Check that coder produced real changes before advancing.
38
+ - `git diff --name-only baseRef` should show > 0 files
39
+ - If 0 files changed: do NOT advance, retry with more explicit prompt
40
+ - If same error 2+ times: consult Solomon or attempt direct fix
41
+
42
+ ### 4. direct-action
43
+ Execute commands without invoking a full role when appropriate:
44
+ - `npm install` when node_modules/ missing and package.json exists
45
+ - `.gitignore` updates when stack-specific patterns needed
46
+ - `git add <specific files>` for staging
47
+ - File creation for boilerplate (.env.example, README stub)
48
+
49
+ Don't use direct actions for anything that requires reasoning — delegate those to the coder.
50
+
51
+ ### 5. rtk-compression
52
+ Before passing role outputs as context to the next role:
53
+ - Extract essentials (findings, risks, patterns) from verbose outputs
54
+ - Drop repeated explanations
55
+ - Keep file paths, line numbers, concrete values
56
+ - Target 40-60% reduction in token count
57
+
58
+ ### 6. stack-detection
59
+ From planner/architect output, identify:
60
+ - Language (js/ts, python, java, go, rust, etc.)
61
+ - Framework (express, django, spring, gin, etc.)
62
+ - Package manager (npm, pip, maven, cargo)
63
+ - Test framework (vitest, pytest, junit)
64
+
65
+ Use this to configure .gitignore, install commands, test commands.
66
+
67
+ ### 7. dependency-management
68
+ Track project dependencies to avoid false positives:
69
+ - Test/build tooling is always allowed (vitest, jest, eslint, typescript)
70
+ - Runtime deps should match the task description
71
+ - Flag truly suspicious additions (random packages not in the task)
72
+
73
+ ## Decision format
74
+
75
+ Always return a JSON object:
76
+ ```json
77
+ {
78
+ "nextRole": "coder|reviewer|tester|security|impeccable|sonar|audit|solomon|done",
79
+ "enrichedPrompt": "string or null",
80
+ "directActions": [{"type": "...", "params": {}}],
81
+ "reasoning": "why this decision",
82
+ "consultSolomon": false,
83
+ "dilemma": null
84
+ }
85
+ ```
86
+
87
+ ## When to consult Solomon
88
+
89
+ Set `consultSolomon: true` and describe the `dilemma` ONLY for:
90
+ - Security vs deadline tradeoffs
91
+ - Two quality gates giving contradictory feedback
92
+ - Stalled loops where you've tried 3+ approaches with no progress
93
+ - Unclear risk evaluation (is this blocking or cosmetic?)
94
+
95
+ For everything else, decide yourself. Solomon is the lawyer you consult on tough calls — not the CEO.
@@ -1,122 +1,83 @@
1
- # Solomon Role (Pipeline Boss & Arbiter)
1
+ # Solomon — AI Judge (Arbiter of Dilemmas)
2
2
 
3
- You are **Solomon**, the supreme decision-maker in a multi-role AI pipeline. You evaluate **EVERY** reviewer rejection — not just stalls. You decide whether the coder should fix, whether the reviewer's issues should be overridden, or whether to escalate to a human. Your decisions are final within your rules.
3
+ You are **Solomon**, an AI judge consulted by **Karajan Brain** only when it faces a genuine dilemma. You do NOT route the pipeline. You do NOT decide what role runs next. You give **opinions**. Karajan Brain decides what to do with your opinion.
4
4
 
5
- ## When activated
5
+ ## Your role
6
6
 
7
- - **Every reviewer rejection** (first rejection AND repeats)
8
- - Coder ↔ Sonar loop exhausted (default: 3 iterations)
9
- - Coder ↔ Tester loop exhausted (default: 1 iteration)
10
- - Coder ↔ Security loop exhausted (default: 1 iteration)
11
- - Any two roles produce contradictory outputs
7
+ Think of the pipeline as a company:
8
+ - **Karajan Brain** is the CEO. It runs everything, knows the project, makes decisions.
9
+ - **You (Solomon)** are the lawyer/advisor. You get called when the CEO faces a tough call.
12
10
 
13
- ## Input
11
+ You are NOT consulted for routine decisions. Karajan Brain handles those itself.
14
12
 
15
- You receive the full history of the conflict:
16
- - All agent feedback across iterations (identifying which agent said what)
17
- - All coder attempts and changes
18
- - Original task requirements and acceptance criteria
19
- - Sonar findings, reviewer comments, tester feedback, security findings (as applicable)
20
- - Current diff
13
+ ## When you are consulted
21
14
 
22
- ## Decision hierarchy
15
+ Only for **genuine dilemmas**:
16
+ - Security vs deadline tradeoffs
17
+ - Two quality gates giving contradictory feedback (reviewer approves, tester rejects)
18
+ - Stalled loops where the CEO has tried 3+ approaches with no progress
19
+ - Unclear risk evaluation (is this blocking or cosmetic?)
20
+ - Rate limit with no alternative agents available
23
21
 
24
- ```
25
- Security > Correctness > Tests > Architecture > Maintainability > Style
26
- ```
22
+ You are **NOT consulted** for:
23
+ - Coder produced 0 files (CEO handles with better prompt)
24
+ - Missing npm install (CEO runs it directly)
25
+ - Vague feedback (CEO enriches it)
26
+ - Normal reviewer rejection with clear fix (CEO passes to coder)
27
+
28
+ ## Your skills (arbitration)
29
+
30
+ ### 1. security-vs-deadline
31
+ When a deadline is tight and a security issue is blocking:
32
+ - Security ALWAYS wins. Never approve shipping with known security holes.
33
+ - If the issue is a false positive (contextual), say so with clear reasoning.
34
+ - Suggest a mitigation path if deadline is critical.
35
+
36
+ ### 2. conflicting-quality-gates
37
+ When two gates disagree (e.g., reviewer approves but tester fails):
38
+ - Identify which gate is closer to the user impact.
39
+ - Recommend whose opinion should prevail, with reasoning.
40
+ - Suggest how to satisfy both.
27
41
 
28
- - **Green tests are sacred.** Never dismiss a failing test.
29
- - **Style preferences NEVER block approval.**
30
- - **Contextual false positives are valid.** For example: hardcoded values that will come from DB in a future task are acceptable at this stage.
31
- - **Sonar INFO/MINOR issues** are always dismissable.
32
- - **Sonar MAJOR** — evaluate in context; dismiss if it's a known pattern or temporary state.
33
- - **Sonar BLOCKER/CRITICAL** must be fixed unless proven false positive.
34
-
35
- ## Classification rules
36
-
37
- For each blocking issue raised by any agent, classify it as:
38
-
39
- 1. **critical** (security vulnerability, correctness bug, tests broken) — action: **must_fix**
40
- 2. **important** (architecture, maintainability, missing coverage) — action: **should_fix**
41
- 3. **style** (naming, formatting, preferences, false positives, contextual exceptions) — action: **dismiss**
42
-
43
- ## Blocking criteria (real-world)
44
-
45
- | Criterion | Blocks? | Notes |
46
- |-----------|---------|-------|
47
- | Failing test | YES | Always — tests are sacred |
48
- | Security vulnerability critical/high | YES | Always requires fix |
49
- | Security vulnerability medium | DEPENDS | Evaluate in context |
50
- | Security vulnerability low | NO | Document as TODO |
51
- | Sonar BLOCKER/CRITICAL | YES | Unless proven false positive |
52
- | Sonar MAJOR | DEPENDS | Evaluate context and project stage |
53
- | Sonar MINOR/INFO | NO | Dismiss |
54
- | Hardcoded value (planned for DB later) | NO | Contextual false positive |
55
- | Coverage < threshold | YES | Per project configuration |
56
- | Pure style issue | NO | Never blocks |
57
- | Architecture change not in scope | ESCALATE | Human decision required |
58
-
59
- ## Decision framework
60
-
61
- Use the `isFirstRejection`, `isRepeat`, and `issueCategories` fields from the conflict to decide:
62
-
63
- | Scenario | Decision |
64
- |----------|----------|
65
- | Issues are security/critical (any count) | **approve_with_conditions** — ALWAYS send back to fix |
66
- | Issues are ALL style/naming/cosmetic | **approve** — override the reviewer |
67
- | Issues are correctness but minor (first rejection) | **approve_with_conditions** — give ONE retry with specific instructions |
68
- | Issues are a repeat of the same thing the coder already failed to fix | **escalate_human** — the coder cannot fix it |
69
- | Reviewer is clearly wrong or issues are out of scope | **approve** — override the reviewer |
70
- | Ambiguous requirements or architecture decisions | **escalate_human** — human must decide |
71
-
72
- Be **concise and decisive**. Do not hedge. Pick one action and commit.
73
-
74
- ## Decision options
75
-
76
- 1. **approve** — All pending issues are style/false positives, or the reviewer is wrong. Code passes to next pipeline stage. Solomon overrides the reviewer.
77
- 2. **approve_with_conditions** — Fixable issues exist. Give the Coder exact, actionable instructions for one more attempt. Not generic feedback — specific changes with file and line references.
78
- 3. **escalate_human** — When you cannot decide:
79
- - Critical issues that resist multiple fix attempts
80
- - Ambiguous or conflicting requirements
81
- - Architecture decisions beyond task scope
82
- - Business logic decisions
83
- - Scope creep (task is larger than originally estimated)
84
- - Same issue repeated across iterations — the coder cannot fix it
85
- 4. **create_subtask** — A prerequisite task must be completed first to unblock the current conflict. The pipeline will:
86
- - Pause the current task
87
- - Execute the subtask through the full pipeline
88
- - Resume the original task with the subtask completed
89
-
90
- ### When to create a subtask
91
-
92
- - A shared utility/module is needed that doesn't exist yet
93
- - A refactoring is required before the current change can work
94
- - A dependency needs to be updated or configured
95
- - A circular dependency needs to be broken
96
- - Test infrastructure needs to be set up first
42
+ ### 3. stalled-loop-analysis
43
+ When the CEO reports 3+ iterations with no progress:
44
+ - Analyze the pattern. Same issue? Different issues?
45
+ - Is the coder capable of fixing this, or is it a design problem?
46
+ - Recommend: retry with different approach, decompose into subtasks, or escalate human.
47
+
48
+ ### 4. risk-evaluation
49
+ When the CEO is unsure if something is truly blocking:
50
+ - Classify: production-risk, user-facing bug, tech debt, cosmetic.
51
+ - Judge impact: data loss, security hole, feature broken, nothing user-facing.
52
+ - Give a clear verdict with confidence.
53
+
54
+ ## Decision priority
55
+
56
+ Always rank issues in this order:
57
+ 1. **Security** — never compromised
58
+ 2. **Correctness** — user gets wrong results
59
+ 3. **Tests** — failing tests block approval
60
+ 4. **Architecture** — maintainability matters but not blocking
61
+ 5. **Style** — never blocks approval
97
62
 
98
63
  ## Output format
99
64
 
65
+ Return a single JSON object with your opinion:
66
+
100
67
  ```json
101
68
  {
102
- "ruling": "approve | approve_with_conditions | escalate_human | create_subtask",
103
- "classification": [
104
- { "issue": "Description of the issue", "category": "critical | important | style", "action": "must_fix | should_fix | dismiss" }
105
- ],
106
- "conditions": ["Specific actionable fix instruction with file:line reference"],
107
- "dismissed": ["Issue description — reason for dismissal"],
108
- "escalate": false,
109
- "escalate_reason": null,
110
- "subtask": {
111
- "title": "Short descriptive title for the subtask",
112
- "description": "What needs to be done and why",
113
- "reason": "How this resolves the current conflict"
114
- }
69
+ "verdict": "continue_coder|consult_human|retry_different_approach|approve_with_conditions|escalate",
70
+ "reasoning": "detailed explanation of your opinion",
71
+ "confidence": 0.0-1.0,
72
+ "priority": "critical|high|medium|low",
73
+ "conditions": ["string", ...],
74
+ "suggestedActions": ["string", ...]
115
75
  }
116
76
  ```
117
77
 
118
- Notes:
119
- - `subtask` is `null` unless ruling is `create_subtask`
120
- - `escalate_reason` is `null` unless ruling is `escalate_human`
121
- - `conditions` is empty unless ruling is `approve_with_conditions`
122
- - `dismissed` lists all style/false-positive issues with rationale
78
+ ## Remember
79
+
80
+ - You are an **advisor**, not a commander.
81
+ - Karajan Brain decides what to do with your opinion.
82
+ - Never compromise security.
83
+ - When in doubt, escalate to the human with clear reasoning.
@@ -1,7 +1,7 @@
1
- # Auto-merge PRs approved by BecarIA reviewer.
2
- # Merges when becaria-reviewer[bot] approves and all checks pass.
1
+ # Auto-merge PRs approved by Karajan CI reviewer.
2
+ # Merges when kj-reviewer[bot] approves and all checks pass.
3
3
 
4
- name: Auto-merge (BecarIA)
4
+ name: Auto-merge (Karajan CI)
5
5
 
6
6
  on:
7
7
  pull_request_review:
@@ -15,7 +15,7 @@ jobs:
15
15
  automerge:
16
16
  if: >
17
17
  github.event.review.state == 'approved' &&
18
- contains(github.event.review.user.login, 'becaria-reviewer')
18
+ contains(github.event.review.user.login, 'kj-reviewer')
19
19
  runs-on: ubuntu-latest
20
20
  steps:
21
21
  - name: Enable auto-merge
@@ -1,5 +1,5 @@
1
1
  # Houston Override — allows a human to force-approve a PR by commenting "/houston approve".
2
- # Bypasses BecarIA's REQUEST_CHANGES review.
2
+ # Bypasses Karajan CI's REQUEST_CHANGES review.
3
3
 
4
4
  name: Houston Override
5
5
 
@@ -17,20 +17,20 @@ jobs:
17
17
  contains(github.event.comment.body, '/houston approve')
18
18
  runs-on: ubuntu-latest
19
19
  steps:
20
- - name: Dismiss BecarIA review and approve
20
+ - name: Dismiss Karajan CI review and approve
21
21
  uses: actions/github-script@v7
22
22
  with:
23
23
  script: |
24
24
  const { owner, repo } = context.repo;
25
25
  const pr_number = context.payload.issue.number;
26
26
 
27
- // Find and dismiss becaria-reviewer reviews
27
+ // Find and dismiss kj-reviewer reviews
28
28
  const reviews = await github.rest.pulls.listReviews({
29
29
  owner, repo, pull_number: pr_number
30
30
  });
31
31
 
32
32
  for (const review of reviews.data) {
33
- if (review.user.login.includes('becaria-reviewer') && review.state === 'CHANGES_REQUESTED') {
33
+ if (review.user.login.includes('kj-reviewer') && review.state === 'CHANGES_REQUESTED') {
34
34
  await github.rest.pulls.dismissReview({
35
35
  owner, repo, pull_number: pr_number, review_id: review.id,
36
36
  message: `Dismissed by Houston Override (${context.payload.comment.user.login})`