karajan-code 2.14.0 → 2.14.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 CHANGED
@@ -23,7 +23,9 @@
23
23
 
24
24
  ---
25
25
 
26
- > **v2.14.0 released** — Quality pass. 16 PRs absorbing bug blockers (Solomon no longer rubber-stamps security issues misclassified as "style", coder filesystem-leak detection gains a second layer that catches `cd <abs> && pnpm init` even when the dir pre-existed, Sonar admin password rotation now surfaces silent failures), the four planner pathologies surfaced by the GRETA Plan 2 dogfooding (scope respect, transversal one-to-many deps, explicit `reuse` marker, and a brand-new **self-fix loop** where the plan-reviewer re-invokes the planner with structured feedback until zero issues remain), HU Board polish (zombie-TTL for crashed-runner prompts, less aggressive rate-limit with SSE exempt), and the first wave of `tests/` reorg (issue #368): ~93 files moved from root to mirror-subfolders. **4577/4577 tests passing**, **0 regressions** across all 16 PRs. Safe upgrade from 2.13.0.
26
+ > **v2.14.1 released** — Patch. Two more planner pathologies surfaced by dogfooding v2.14.0 against GRETA Plan 2: the **self-fix loop could regress** (iter 1 would drop 15→10 issues, iter 2 then deleted HUs the first iter had added, reaching 17 — worse than before iter 2 started) and the **planner declared `blocked_by` on async observers** (HUs that an async guardrail or cron *reacts to* were marked as depending on the guardrail, breaking the GRETA "AVISA-no-BLOQUEA" principle). Fixes: P5 snapshots the plan before each self-fix iter and reverts if `newCount > currentCount`; P6 lists six async-observer patterns in the planner prompt with a "consume vs react" heuristic. After P5+P6, regenerating Plan 2 GRETA returns to the baseline-iter-1 quality (9 findings) instead of v2.14.0's 17. 2 PRs (#684, #685). 4580/4580 tests passing. Safe upgrade from 2.14.0.
27
+ >
28
+ > **v2.14.0** — Quality pass. 16 PRs absorbing bug blockers (Solomon no longer rubber-stamps security issues misclassified as "style", coder filesystem-leak detection gains a second layer that catches `cd <abs> && pnpm init` even when the dir pre-existed, Sonar admin password rotation now surfaces silent failures), the four planner pathologies surfaced by the GRETA Plan 2 dogfooding (scope respect, transversal one-to-many deps, explicit `reuse` marker, and a brand-new **self-fix loop** where the plan-reviewer re-invokes the planner with structured feedback until zero issues remain), HU Board polish (zombie-TTL for crashed-runner prompts, less aggressive rate-limit with SSE exempt), and the first wave of `tests/` reorg (issue #368): ~93 files moved from root to mirror-subfolders. **4577/4577 tests passing**, **0 regressions** across all 16 PRs. Safe upgrade from 2.13.0.
27
29
  >
28
30
  > **v2.13.0** — HU Board hardening. Five PRs make the board resilient and self-healing after a dogfooding session uncovered four pathologies: a "Karajan needs an answer" prompt modal from days earlier blocking the entire UI, 18 zombi projects reappearing after every `kj board start`, the browser serving stale HTML/JS after a server restart, and the prompt modal showing a transparent background. Now: **tombstones** persist deletes across `fullScan` (`KJC-TSK-0380`), new endpoints `DELETE /api/prompts/:id`, `DELETE /api/plans/:planId`, `GET /api/tombstones`, `POST /api/tombstones/:type/:id/restore`; new command **`kj board cleanup`** sweeps ephemeral projects, orphan prompts and dangling session dirs in one pass; **`Cache-Control: no-store`** + `/api/version` polling auto-reloads the client when the server boot time changes; new **🧹 button** as manual escape hatch; CSS `--bg-secondary` finally declared so modals are opaque. 5 PRs (#654, #655, #656, #657, #658). 4522/4522 tests passing.
29
31
  >
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karajan-code",
3
- "version": "2.14.0",
3
+ "version": "2.14.1",
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",
@@ -73,7 +73,6 @@
73
73
  "valibot": "^1.3.1"
74
74
  },
75
75
  "devDependencies": {
76
- "@changesets/cli": "^2.30.0",
77
76
  "@eslint/js": "^10.0.1",
78
77
  "@vitest/coverage-v8": "^4.0.18",
79
78
  "esbuild": "^0.28.0",
@@ -246,6 +246,14 @@ async function planGenerateImpl({ task, config, logger, json, context, runLog, f
246
246
  if (currentCount === 0) break;
247
247
  runLog.logText(`[planner] self-fix iter ${i}/${maxFixerIterations} — patching ${currentCount} issue(s)`);
248
248
  progress.onOutput?.({ line: `Self-fix iter ${i}: patching ${currentCount} issue(s)`, kind: "text" });
249
+ // KJC-BUG-0046 / P5: snapshot plan + review BEFORE applying the patch
250
+ // so we can revert if the iteration regresses (newCount > currentCount).
251
+ // Dogfooding 2026-05-12: GRETA Plan 2 iter 2 went 10 → 17 findings
252
+ // because the fixer's deletions created dangling references the
253
+ // reviewer then flagged. Without the guard, the loop made the plan
254
+ // strictly worse than before iter 2 started.
255
+ const husSnapshot = JSON.parse(JSON.stringify(plan.hus));
256
+ const reviewSnapshot = JSON.parse(JSON.stringify(plan.review));
249
257
  const fix = await applyReviewerFeedback({
250
258
  agent: planner, task, hus: plan.hus, findings: plan.review,
251
259
  onOutput: progress.onOutput, silenceTimeoutMs, timeoutMs,
@@ -266,10 +274,20 @@ async function planGenerateImpl({ task, config, logger, json, context, runLog, f
266
274
  });
267
275
  if (!review2.ok) {
268
276
  runLog.logText(`[planner] re-review after iter ${i} failed: ${review2.error}`);
277
+ plan.hus = husSnapshot;
278
+ plan.review = reviewSnapshot;
279
+ break;
280
+ }
281
+ const newCount = findingsCount(review2.findings);
282
+ if (newCount > currentCount) {
283
+ // P5 convergence guard: iter made things worse — revert + stop.
284
+ plan.hus = husSnapshot;
285
+ plan.review = reviewSnapshot;
286
+ runLog.logText(`[planner] self-fix iter ${i} regressed (${currentCount} → ${newCount}) — reverted, stopping`);
269
287
  break;
270
288
  }
271
289
  plan.review = review2.findings;
272
- runLog.logText(`[planner] after self-fix iter ${i}: ${findingsCount(review2.findings)} issue(s) remaining`);
290
+ runLog.logText(`[planner] after self-fix iter ${i}: ${newCount} issue(s) remaining`);
273
291
  }
274
292
  }
275
293
  } else {
@@ -248,6 +248,14 @@ export function buildPlannerPrompt({ task, context, architectContext, productCon
248
248
  "- **Transversal dependencies (KJC-BUG-0043 / P2)**: when a step's description or `acceptance_tests` requires ALL members of a category (e.g. `listado transversal de warnings filtrables por guardrail`, `list of all assessments`, `summary across all guardrails`, `dashboard que agrega todos los X`), declare `dependencies` to ALL step ids in that category — NOT just the first one, NOT just the index/master step.",
249
249
  " - Example: a step `LIST-WARNINGS` whose AC reads *\"todos los warnings filtrables por guardrail\"* MUST list every `GUARD-001`, `GUARD-002`, … `GUARD-N` step in its plan as dependencies. Listing only `GUARD-001` is a bug — at execution time the listado will run before the rest of the guardrails exist and the AC will fail.",
250
250
  " - The detection signal is the AC/description, not the step title. If the title is generic (\"List warnings\") but the AC requires aggregation across N concrete items, you MUST resolve the N concrete items and depend on each.",
251
+ "- **Async-deps respect (KJC-BUG-0047 / P6)**: do NOT declare a dependency on a step that runs AFTER the dependent step asynchronously, even if its OUTPUT references or reacts to the dependent step. Common asynchronous-observer patterns to recognise:",
252
+ " - Guardrails / validators / monitors that watch for changes (\"AVISA-no-BLOQUEA\" — they warn but never block)",
253
+ " - Cron jobs / scheduled tasks (run on their own schedule)",
254
+ " - Webhooks / event handlers / listeners (reactive)",
255
+ " - Async queues / workers / pipelines (post-process)",
256
+ " - Audit logs / metric collectors (observe, don't gate)",
257
+ " - The heuristic: ask \"does X CONSUME a deliverable that must EXIST before X starts?\" → if yes, X is blocked_by Y. \"Does Y simply REACT to X after the fact?\" → X is NOT blocked_by Y; they are parallel.",
258
+ " - Example: an Outcome HU is NOT blocked_by its Guardrail (the guardrail evaluates the Outcome async). A processConversation pipeline IS blocked_by the input-storage HU (the input must exist first).",
251
259
  "",
252
260
  "### `reuse` (REQUIRED — empty array if none) — KJC-BUG-0044 / P3",
253
261
  "- `reuse` is NOT the same as `dependencies`. `dependencies` means \"X must complete before me (ordering)\"; `reuse` means \"I piggy-back on X's implementation instead of reimplementing the same logic in my own code\".",