karajan-code 2.7.0 → 2.7.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/bin/kj-tail +12 -1
- package/package.json +3 -1
- package/scripts/build-sea.mjs +1 -1
- package/src/orchestrator/flow-runner.js +8 -0
- package/src/session/journal/summary-writer.js +51 -0
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
26
|
-
> **v2.
|
|
26
|
+
> **v2.7.2 released** — Skills observability: `summary.md` now shows a "Skills Used" section listing the addyosmani slugs resolved per role + OpenSkills installed/recommended, and `kj-tail` v1.37.0 highlights `[skills:*]` events with a 🎯 icon (magenta on success, yellow on graceful-degradation). Carries the full v2.7 feature set: [`addyosmani/agent-skills`](https://github.com/addyosmani/agent-skills) as Karajan's first-source process catalog (20+ lifecycle workflows — TDD, code-review-and-quality, security-and-hardening, performance-optimization, git-workflow-and-versioning, CI/CD, debugging-and-error-recovery, spec-driven-development, planning-and-task-breakdown…) injected per role **before** OpenSkills stack skills, shallow-cloned into `~/.karajan/agent-skills/` and refreshed weekly via `git pull`. SEA platform binaries (`linux-x64`, `darwin-arm64`, `win-x64`) publish correctly again after the v2.7.1 workflow fix. New CLI: `kj skills sync-addyosmani`, `kj skills list-addyosmani`. New config: `skills.sources`, `skills.addyosmani.{enabled,refreshDays,repoUrl}`. See [CHANGELOG.md](./CHANGELOG.md) for full history and [MIGRATION-v2.md](./MIGRATION-v2.md) for v1→v2 breaking changes.
|
|
27
27
|
|
|
28
28
|
You describe what you want to build. Karajan orchestrates multiple AI agents to plan it, implement it, test it, review it with SonarQube, and iterate. No babysitting required.
|
|
29
29
|
|
package/bin/kj-tail
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
set -euo pipefail
|
|
6
6
|
|
|
7
|
-
VERSION="1.
|
|
7
|
+
VERSION="1.37.0"
|
|
8
8
|
|
|
9
9
|
# ── Colors ──────────────────────────────────────────────
|
|
10
10
|
RED='\033[0;31m'
|
|
@@ -248,6 +248,17 @@ filter_line() {
|
|
|
248
248
|
return
|
|
249
249
|
fi
|
|
250
250
|
|
|
251
|
+
# Skills (addyosmani catalog + OpenSkills marketplace)
|
|
252
|
+
if [[ "$clean" == *"[skills:"* ]] || [[ "$clean" == *"[skills]"* ]]; then
|
|
253
|
+
# Highlight failures/unavailability in yellow, successes in magenta
|
|
254
|
+
if [[ "$clean" == *"unavailable"* ]] || [[ "$clean" == *"would have used"* ]]; then
|
|
255
|
+
echo -e "${prefix}${YELLOW} ├─ 🎯 ${clean}${RESET}"
|
|
256
|
+
else
|
|
257
|
+
echo -e "${prefix}${MAGENTA} ├─ 🎯 ${clean}${RESET}"
|
|
258
|
+
fi
|
|
259
|
+
return
|
|
260
|
+
fi
|
|
261
|
+
|
|
251
262
|
# TDD
|
|
252
263
|
if [[ "$clean" == *"TDD"* ]] || [[ "$clean" == *"tdd"* ]]; then
|
|
253
264
|
echo -e "${prefix}${GREEN} ├─ 📋 ${clean}${RESET}"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "karajan-code",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.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",
|
|
@@ -61,6 +61,8 @@
|
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@changesets/cli": "^2.30.0",
|
|
63
63
|
"@vitest/coverage-v8": "^4.0.18",
|
|
64
|
+
"esbuild": "^0.28.0",
|
|
65
|
+
"postject": "^1.0.0-alpha.6",
|
|
64
66
|
"vitest": "^4.0.0"
|
|
65
67
|
}
|
|
66
68
|
}
|
package/scripts/build-sea.mjs
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* 4. Inject the blob into the binary with postject
|
|
11
11
|
* 5. (macOS only) Re-sign the binary with ad-hoc signature
|
|
12
12
|
*
|
|
13
|
-
* Requirements (installed
|
|
13
|
+
* Requirements (installed as devDependencies — run `npm ci` first):
|
|
14
14
|
* - esbuild
|
|
15
15
|
* - postject
|
|
16
16
|
*
|
|
@@ -452,6 +452,14 @@ async function finalizeApprovedSession({ config, gitCtx, task, logger, session,
|
|
|
452
452
|
finishedAt: new Date().toISOString(),
|
|
453
453
|
brainDecisions: Array.isArray(session.brainDecisions) ? session.brainDecisions.length : 0,
|
|
454
454
|
solomonInvocations: Array.isArray(session.solomonRulings) ? session.solomonRulings.length : 0,
|
|
455
|
+
// KJC-TSK-0327: surface skill-source decisions in the summary so the
|
|
456
|
+
// post-mortem shows which process skills (addyosmani) and stack skills
|
|
457
|
+
// (OpenSkills) actually shaped the role prompts.
|
|
458
|
+
skills: {
|
|
459
|
+
addyosmani: session.addyosmaniSkills,
|
|
460
|
+
installed: session.autoInstalledSkills,
|
|
461
|
+
recommended: session.skillsRecommended,
|
|
462
|
+
},
|
|
455
463
|
}, { logger });
|
|
456
464
|
logger.info(`Session journal written to ${journalDir}`);
|
|
457
465
|
} catch (err) {
|
|
@@ -26,6 +26,10 @@ import path from "node:path";
|
|
|
26
26
|
* @property {string} [finishedAt] - ISO timestamp (optional)
|
|
27
27
|
* @property {number} [solomonInvocations]
|
|
28
28
|
* @property {number} [brainDecisions]
|
|
29
|
+
* @property {Object} [skills] - skill sources used this session (KJC-TSK-0327)
|
|
30
|
+
* @property {Object} [skills.addyosmani] - { available, action, resolvedSlugs, reason }
|
|
31
|
+
* @property {string[]} [skills.installed] - OpenSkills installed this run (session.autoInstalledSkills)
|
|
32
|
+
* @property {string[]} [skills.recommended] - wouldHaveUsed when OpenSkills CLI missing
|
|
29
33
|
*/
|
|
30
34
|
|
|
31
35
|
function esc(text) {
|
|
@@ -103,6 +107,48 @@ function renderBreakdownByRole(breakdown) {
|
|
|
103
107
|
return ["| Role | Tokens | Cost |", "|---|---|---|", ...rows].join("\n");
|
|
104
108
|
}
|
|
105
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Render the Skills section: which process skills (addyosmani) were resolved
|
|
112
|
+
* for the task, which OpenSkills were installed, and which skills would have
|
|
113
|
+
* helped but couldn't be installed (graceful-degradation path).
|
|
114
|
+
*
|
|
115
|
+
* Returns null when no skill activity happened (no addyosmani, no installs,
|
|
116
|
+
* no recommendations) so the section is elided.
|
|
117
|
+
*/
|
|
118
|
+
function renderSkills(skills) {
|
|
119
|
+
if (!skills || typeof skills !== "object") return null;
|
|
120
|
+
const addy = skills.addyosmani;
|
|
121
|
+
const installed = Array.isArray(skills.installed) ? skills.installed : [];
|
|
122
|
+
const recommended = Array.isArray(skills.recommended) ? skills.recommended : [];
|
|
123
|
+
|
|
124
|
+
const hasAddy = addy && (addy.available === true || addy.available === false);
|
|
125
|
+
if (!hasAddy && installed.length === 0 && recommended.length === 0) return null;
|
|
126
|
+
|
|
127
|
+
const lines = [];
|
|
128
|
+
|
|
129
|
+
if (hasAddy) {
|
|
130
|
+
if (addy.available) {
|
|
131
|
+
const action = addy.action || "ready";
|
|
132
|
+
const slugs = Array.isArray(addy.resolvedSlugs) ? addy.resolvedSlugs : [];
|
|
133
|
+
lines.push(`- **addyosmani/agent-skills** (process, 1st source): ${esc(action)}` +
|
|
134
|
+
(slugs.length > 0 ? ` — resolved slugs: ${slugs.map((s) => `\`${esc(s)}\``).join(", ")}` : " — no role/task-specific slugs resolved"));
|
|
135
|
+
} else {
|
|
136
|
+
const reason = addy.reason ? ` — ${esc(addy.reason)}` : "";
|
|
137
|
+
lines.push(`- **addyosmani/agent-skills**: unavailable${reason}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (installed.length > 0) {
|
|
142
|
+
lines.push(`- **OpenSkills installed**: ${installed.map((s) => `\`${esc(s)}\``).join(", ")}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (recommended.length > 0) {
|
|
146
|
+
lines.push(`- **OpenSkills recommended** (CLI missing, would-have-used): ${recommended.map((s) => `\`${esc(s)}\``).join(", ")}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return lines.join("\n");
|
|
150
|
+
}
|
|
151
|
+
|
|
106
152
|
function renderJournalLinks(files) {
|
|
107
153
|
if (!Array.isArray(files) || files.length === 0) return "_No additional journal files._";
|
|
108
154
|
return files.map((f) => `- [${esc(f)}](./${f})`).join("\n");
|
|
@@ -146,6 +192,11 @@ export function buildSummaryMarkdown(input) {
|
|
|
146
192
|
sections.push("", "## Budget breakdown (by role)", "", breakdown);
|
|
147
193
|
}
|
|
148
194
|
|
|
195
|
+
const skillsSection = renderSkills(input.skills);
|
|
196
|
+
if (skillsSection) {
|
|
197
|
+
sections.push("", "## Skills Used", "", skillsSection);
|
|
198
|
+
}
|
|
199
|
+
|
|
149
200
|
sections.push("", "## Commits", "", renderCommits(input.commits));
|
|
150
201
|
|
|
151
202
|
sections.push("", "## Journal files", "", renderJournalLinks(input.files));
|