karajan-code 2.14.0 → 2.14.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 +5 -1
- package/package.json +1 -2
- package/src/commands/plan/generate.js +19 -1
- package/src/prompts/planner.js +19 -1
package/README.md
CHANGED
|
@@ -23,7 +23,11 @@
|
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
-
> **v2.14.
|
|
26
|
+
> **v2.14.2 released** — Patch. More dogfooding fallout from GRETA Plan 2 v2.14.1: the **▶ Run button** on the HU Board appeared on every `pending` card regardless of `blocked_by` (you could launch a HU whose deps don't exist yet — the user caught it instantly), and titles on the board lost their **`[EPICA]` prefix** at some point in v2.14.x evolution, making it impossible to tell at a glance which area of the plan a card belonged to. Fixes: `canRunHu` now requires `blockedBy.length === 0` before showing ▶; the planner prompt now demands `description: "[EPICA] one-sentence description"` with INFRA/SHARED fallbacks. Plus a new doc `docs/task-templates/spec-conventions.md` collecting the 6 SPEC conventions the planner v2.14.x understands (épicas, scope exclusions, transversal deps, reuse, async observers, explicit deps), so users don't have to rediscover them by dogfooding. 2 PRs (#687, #688). 4584/4584 tests passing. Safe upgrade from 2.14.1.
|
|
27
|
+
>
|
|
28
|
+
> **v2.14.1** — 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.
|
|
29
|
+
>
|
|
30
|
+
> **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
31
|
>
|
|
28
32
|
> **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
33
|
>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "karajan-code",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.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",
|
|
@@ -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}: ${
|
|
290
|
+
runLog.logText(`[planner] after self-fix iter ${i}: ${newCount} issue(s) remaining`);
|
|
273
291
|
}
|
|
274
292
|
}
|
|
275
293
|
} else {
|
package/src/prompts/planner.js
CHANGED
|
@@ -226,7 +226,7 @@ export function buildPlannerPrompt({ task, context, architectContext, productCon
|
|
|
226
226
|
"```json",
|
|
227
227
|
"{",
|
|
228
228
|
' "id": "<short symbolic identifier you choose for this step, e.g. \'INFRA-001\' or \'AUTH-SIGNUP\'>",',
|
|
229
|
-
' "description": "<what this step achieves, one sentence>",',
|
|
229
|
+
' "description": "<[EPICA] prefix + what this step achieves, one sentence>",',
|
|
230
230
|
' "commit": "<conventional commit message>",',
|
|
231
231
|
' "spec_section": "<see rules below>",',
|
|
232
232
|
' "acceptance_tests": [ /* see rules below */ ],',
|
|
@@ -235,6 +235,16 @@ export function buildPlannerPrompt({ task, context, architectContext, productCon
|
|
|
235
235
|
"}",
|
|
236
236
|
"```",
|
|
237
237
|
"",
|
|
238
|
+
"### `description` (REQUIRED — MUST start with `[EPICA] ` prefix)",
|
|
239
|
+
"- The first 80 chars of `description` become the HU's title on the board, so the prefix is the user's only at-a-glance signal of \"which area of the plan does this card belong to\".",
|
|
240
|
+
"- Identify the EPICA from the task text — typically a heading like `### Épica PROFILE`, `## Auth`, `# Layer N — name`, or a categorical noun the user uses repeatedly (e.g. `INFRA`, `SHARED`, `UI`, `API`).",
|
|
241
|
+
"- Format: `[EPICA] one-sentence description`. Examples:",
|
|
242
|
+
" - `[PROFILE] Subir CV cifrado con envelope encryption a Storage`",
|
|
243
|
+
" - `[GUARD] Guardarraíl 4 inline en pipeline processConversation`",
|
|
244
|
+
" - `[INFRA] Provisionar Firestore Vector Search por instancia`",
|
|
245
|
+
"- If no EPICA fits, use `[SHARED]` for cross-cutting utilities or `[INFRA]` for setup steps.",
|
|
246
|
+
"- Keep the EPICA name short (≤12 chars) and consistent across the plan — group same-area HUs under the SAME tag.",
|
|
247
|
+
"",
|
|
238
248
|
"### `id` (REQUIRED for cross-references)",
|
|
239
249
|
"- A short symbolic identifier you assign to this step (e.g. `INFRA-001`, `AUTH-SIGNUP`, `team-list-page`).",
|
|
240
250
|
"- It only has to be unique within this plan; the system maps it to a stable internal HU id afterwards.",
|
|
@@ -248,6 +258,14 @@ export function buildPlannerPrompt({ task, context, architectContext, productCon
|
|
|
248
258
|
"- **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
259
|
" - 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
260
|
" - 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.",
|
|
261
|
+
"- **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:",
|
|
262
|
+
" - Guardrails / validators / monitors that watch for changes (\"AVISA-no-BLOQUEA\" — they warn but never block)",
|
|
263
|
+
" - Cron jobs / scheduled tasks (run on their own schedule)",
|
|
264
|
+
" - Webhooks / event handlers / listeners (reactive)",
|
|
265
|
+
" - Async queues / workers / pipelines (post-process)",
|
|
266
|
+
" - Audit logs / metric collectors (observe, don't gate)",
|
|
267
|
+
" - 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.",
|
|
268
|
+
" - 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
269
|
"",
|
|
252
270
|
"### `reuse` (REQUIRED — empty array if none) — KJC-BUG-0044 / P3",
|
|
253
271
|
"- `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\".",
|