karajan-code 2.3.0 → 2.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karajan-code",
3
- "version": "2.3.0",
3
+ "version": "2.3.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",
@@ -2,7 +2,7 @@ export const VALID_TASK_TYPES = new Set(["sw", "infra", "doc", "add-tests", "ref
2
2
 
3
3
  export const DEFAULT_POLICIES = {
4
4
  sw: { tdd: true, sonar: true, reviewer: true, testsRequired: true },
5
- infra: { tdd: false, sonar: false, reviewer: true, testsRequired: false },
5
+ infra: { tdd: false, sonar: false, reviewer: false, testsRequired: false },
6
6
  doc: { tdd: false, sonar: false, reviewer: true, testsRequired: false },
7
7
  "add-tests": { tdd: false, sonar: true, reviewer: true, testsRequired: true },
8
8
  refactor: { tdd: true, sonar: true, reviewer: true, testsRequired: false },
@@ -66,6 +66,20 @@ export function needsSetupHu({ isNewProject = false, stackHints = [], subtasks =
66
66
  return subtasks.some(s => setupKeywords.test(s));
67
67
  }
68
68
 
69
+ /**
70
+ * Filter conflicting stack hints. When Node.js ecosystem keywords are present,
71
+ * remove Go/Rust/Python keywords that were detected from gitignore patterns
72
+ * but aren't actually part of the task.
73
+ */
74
+ function filterConflictingHints(hints) {
75
+ if (!hints || hints.length === 0) return hints;
76
+ const nodeEcosystem = new Set(["express", "vite", "vitest", "jest", "next", "astro", "react", "vue", "svelte", "nestjs", "monorepo", "workspaces"]);
77
+ const goKeywords = new Set(["gin", "fiber", "go"]);
78
+ const hasNode = hints.some(h => nodeEcosystem.has(h));
79
+ if (!hasNode) return hints;
80
+ return hints.filter(h => !goKeywords.has(h));
81
+ }
82
+
69
83
  /**
70
84
  * Build a MINIMAL setup HU — project structure + deps only.
71
85
  * NEVER includes the full original task. The coder must only do setup.
@@ -168,13 +182,14 @@ export function generateHuBatch({
168
182
  }
169
183
 
170
184
  const stories = [];
171
- const needsSetup = needsSetupHu({ isNewProject, stackHints, subtasks });
185
+ const filteredHints = filterConflictingHints(stackHints);
186
+ const needsSetup = needsSetupHu({ isNewProject, stackHints: filteredHints, subtasks });
172
187
  let nextId = 1;
173
188
 
174
189
  const projectName = deriveProjectName(originalTask);
175
190
 
176
191
  if (needsSetup) {
177
- stories.push(buildSetupHu({ stackHints }));
192
+ stories.push(buildSetupHu({ stackHints: filteredHints }));
178
193
  nextId = 2;
179
194
  }
180
195
 
@@ -1669,6 +1669,16 @@ export async function runFlow({ task, config, logger, flags = {}, emitter = null
1669
1669
  ctx.brainCtx.feedbackQueue = fresh.feedbackQueue;
1670
1670
  ctx.brainCtx.verificationTracker = fresh.verificationTracker;
1671
1671
  }
1672
+ // Apply per-HU policies based on task_type (infra skips reviewer/sonar/tdd)
1673
+ const { applyPolicies } = await import("./guards/policy-resolver.js");
1674
+ const huPolicies = applyPolicies({ taskType: story.task_type, policies: ctx.config.policies });
1675
+ const savedFlags = { ...ctx.pipelineFlags };
1676
+ if (!huPolicies.reviewer) ctx.pipelineFlags.reviewerEnabled = false;
1677
+ if (!huPolicies.tdd) ctx.config.development = { ...ctx.config.development, methodology: "standard", require_test_changes: false };
1678
+ if (!huPolicies.sonar) ctx.config.sonarqube = { ...ctx.config.sonarqube, enabled: false };
1679
+ if (!huPolicies.testsRequired) ctx.pipelineFlags.testerEnabled = false;
1680
+ logger.info(`HU ${story.id} (${story.task_type}): policies → reviewer=${huPolicies.reviewer}, tdd=${huPolicies.tdd}, sonar=${huPolicies.sonar}, tests=${huPolicies.testsRequired}`);
1681
+
1672
1682
  const branchName = await prepareHuBranch({ story, huBranches, config: ctx.config, logger });
1673
1683
  try {
1674
1684
  const result = await runIterationLoop(ctx, { task: huTask, askQuestion, emitter, logger });
@@ -1678,6 +1688,7 @@ export async function runFlow({ task, config, logger, flags = {}, emitter = null
1678
1688
  return result;
1679
1689
  } finally {
1680
1690
  ctx.config.max_iterations = originalMaxIterations;
1691
+ Object.assign(ctx.pipelineFlags, savedFlags);
1681
1692
  }
1682
1693
  },
1683
1694
  emitter,