karajan-code 4.3.0 → 4.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karajan-code",
3
- "version": "4.3.0",
3
+ "version": "4.3.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",
@@ -185,7 +185,11 @@ export function registerMeta(program, { pkgVersion }) {
185
185
  const hu = program.command("hu").description("Track work in the HU Board from any host agent (card first)");
186
186
  hu.command("add <title>")
187
187
  .option("--id <shortId>", "Human-readable short id")
188
- .option("--criteria <text>", "Acceptance criteria")
188
+ .option("--ac <criterion>", "Acceptance criterion (repeatable; multiline strings split per line)", (v, acc) => [...acc, v], [])
189
+ .option("--tests <test>", "Acceptance test (repeatable; multiline strings split per line)", (v, acc) => [...acc, v], [])
190
+ .option("--scope <text>", "Scope of the story (files/areas)")
191
+ .option("--task-type <type>", "sw | infra | doc | add-tests | refactor")
192
+ .option("--criteria <text>", "Legacy alias for a single acceptance criterion")
189
193
  .option("--json", "Machine-readable output")
190
194
  .action(async (title, flags) => {
191
195
  await withConfig(pkgVersion, "hu", flags, async ({ config }) => {
@@ -122,15 +122,36 @@ export async function huCommand({ config = null, action, args = [], flags = {} }
122
122
  );
123
123
  }
124
124
  }
125
+ // KJC-TSK-0678 (issue #1296): complete HUs in ONE call. --ac / --tests
126
+ // are repeatable AND accept multiline strings; --criteria stays as the
127
+ // legacy single-criterion alias.
128
+ const TASK_TYPES = ["sw", "infra", "doc", "add-tests", "refactor"];
129
+ if (flags.taskType && !TASK_TYPES.includes(flags.taskType)) {
130
+ throw new Error(`invalid --task-type "${flags.taskType}" — valid: ${TASK_TYPES.join(", ")}`);
131
+ }
132
+ const splitLines = (v) => (Array.isArray(v) ? v : v ? [v] : [])
133
+ .flatMap((s) => String(s).split("\n")).map((s) => s.trim()).filter(Boolean);
125
134
  const hu = addHu(plan, {
126
135
  title,
127
136
  short_id: flags.id || null,
128
- acceptance_criteria: flags.criteria ? [flags.criteria] : [],
137
+ acceptance_criteria: [...splitLines(flags.ac), ...splitLines(flags.criteria)],
138
+ acceptance_tests: splitLines(flags.tests),
139
+ scope: flags.scope || null,
140
+ task_type: flags.taskType || undefined,
129
141
  });
130
142
  hu.created_by = creatorLabel();
131
143
  await savePlan(projectDir, plan);
132
- return emit({ id: hu.id, short_id: hu.short_id, status: hu.status, created_by: hu.created_by },
133
- `✓ HU created: ${hu.short_id || hu.id} (pending, by ${hu.created_by}) — it shows up in \`kj board\``);
144
+ const missing = [];
145
+ if (hu.acceptance_criteria.length === 0) missing.push("acceptance criteria (--ac \"...\")");
146
+ if (hu.acceptance_tests.length === 0) missing.push("tests (--tests \"...\")");
147
+ if (missing.length > 0) {
148
+ console.warn(`⚠ incomplete spec — kj run's spec review will flag it. Missing: ${missing.join(", ")}`);
149
+ }
150
+ return emit({
151
+ id: hu.id, short_id: hu.short_id, status: hu.status, created_by: hu.created_by,
152
+ acceptance_criteria: hu.acceptance_criteria, acceptance_tests: hu.acceptance_tests,
153
+ scope: hu.scope, task_type: hu.task_type,
154
+ }, `✓ HU created: ${hu.short_id || hu.id} (pending, by ${hu.created_by}) — it shows up in \`kj board\``);
134
155
  }
135
156
 
136
157
  if (action === "move") {
@@ -23,6 +23,14 @@
23
23
  - Do not modify code unrelated to the task.
24
24
  - Follow existing code conventions and patterns in the repository.
25
25
 
26
+ ## Environment isolation (parallel runs)
27
+
28
+ - Never hardcode ports, DB names, or docker project names — read them from env
29
+ vars, documenting each one in `.env.example`. When `KJ_LANE_SLOT` /
30
+ `KJ_PORT_OFFSET` exist in the env, derive per-task values from them so
31
+ parallel lanes never collide.
32
+ - Never commit a real `.env` — only `.env.example` is versioned.
33
+
26
34
  ## Tests location (MANDATORY)
27
35
 
28
36
  - Tests live in a top-level `tests/` directory mirroring `src/` (e.g. a function in
@@ -118,3 +118,11 @@ session:
118
118
  # when exceeded; resume with `kj resume`. Set to null to remove the cap.
119
119
  max_budget_usd: 5
120
120
  fail_fast_repeats: 2
121
+ # Per-lane setup for parallel runs (worktrees). Runs INSIDE the fresh
122
+ # worktree instead of the default `npm ci`. Each lane receives
123
+ # KJ_LANE_SLOT (0,1,2…) and KJ_PORT_OFFSET (slot-derived) in its env —
124
+ # derive ports, DB names and docker project names from them so lanes
125
+ # never collide. The coder never orchestrates git; isolation is declared
126
+ # here. Example:
127
+ # worktree_setup: "npm ci && docker compose -p app_lane_$KJ_LANE_SLOT up -d db"
128
+ worktree_setup: null
@@ -4,6 +4,12 @@
4
4
  - Only raise blocking issues for concrete production risks.
5
5
  - Keep non-blocking suggestions separate.
6
6
 
7
+ ## Environment isolation
8
+
9
+ - Reject changes that hardcode ports, DB names or service hostnames instead of
10
+ reading them from env vars, and any diff that adds a real `.env` (only
11
+ `.env.example` is versioned).
12
+
7
13
  ## File overwrite detection (BLOCKING)
8
14
 
9
15
  - If the diff shows an entire file was replaced (massive deletions + additions instead of targeted edits), flag it as BLOCKING.