karajan-code 4.35.1 → 4.36.0

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.
Files changed (42) hide show
  1. package/package.json +1 -1
  2. package/packages/hu-board/public/utils/board-view.js +2 -1
  3. package/packages/hu-board/public/utils/config-editor.js +5 -2
  4. package/packages/hu-board/public/utils/terminal-panel.js +2 -1
  5. package/packages/hu-board/src/config-yaml.js +11 -9
  6. package/packages/hu-board/src/project-dir.js +42 -0
  7. package/packages/hu-board/src/routes/api.js +11 -3
  8. package/packages/hu-board/src/terminal-wire.js +5 -1
  9. package/packages/hu-board/src/terminal.js +8 -3
  10. package/src/checks/rag-coverage.js +5 -4
  11. package/src/cli/register-meta.js +15 -4
  12. package/src/commands/board.js +20 -8
  13. package/src/commands/bootstrap.js +2 -0
  14. package/src/commands/env.js +8 -4
  15. package/src/commands/harden.js +26 -4
  16. package/src/commands/init.js +2 -1
  17. package/src/commands/plan/generate.js +4 -6
  18. package/src/commands/rag.js +69 -10
  19. package/src/commands/review-gate.js +14 -5
  20. package/src/commands/watch.js +13 -10
  21. package/src/config/defaults.js +3 -2
  22. package/src/environment/playbook.js +10 -3
  23. package/src/harden/guidelines-engine.js +24 -7
  24. package/src/harden/sentinel-hooks.js +68 -7
  25. package/src/lang/registry.js +2 -1
  26. package/src/mcp/handlers/rag-handler.js +14 -4
  27. package/src/orchestrator/drivers/post-loop.js +13 -11
  28. package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +3 -2
  29. package/src/orchestrator/stages/rag-context-stage.js +5 -2
  30. package/src/rag/auto-update.js +5 -3
  31. package/src/rag/coverage.js +13 -12
  32. package/src/rag/indexable.js +97 -0
  33. package/src/rag/indexer.js +31 -13
  34. package/src/rag/library.js +19 -13
  35. package/src/rag/migrate.js +73 -0
  36. package/src/rag/onnx-fallback.js +5 -3
  37. package/src/rag/project-store.js +48 -0
  38. package/src/rag/watcher.js +25 -14
  39. package/src/review/kj-provenance.js +26 -0
  40. package/src/review/verdict-store.js +6 -1
  41. package/src/start/sweep.js +4 -3
  42. package/src/utils/rulesync.js +61 -0
@@ -13,6 +13,7 @@ import crypto from "node:crypto";
13
13
  import fs from "node:fs/promises";
14
14
  import path from "node:path";
15
15
  import { runCommand } from "../utils/process.js";
16
+ import { kjStamp, stampDiffers, stampLabel } from "./kj-provenance.js";
16
17
 
17
18
  const STORE_DIR = path.join(".karajan", "reviews");
18
19
 
@@ -35,6 +36,7 @@ export async function saveVerdict(projectDir, diff, verdict) {
35
36
  const hash = diffHash(diff);
36
37
  const record = {
37
38
  ...verdict,
39
+ kj: kjStamp(), // KJC-TSK-0886: que kj lo emitio; nunca lo dicta quien llama
38
40
  diffHash: hash,
39
41
  timestamp: new Date().toISOString(),
40
42
  };
@@ -143,5 +145,8 @@ export async function checkVerdict(projectDir, diff) {
143
145
  if (verdict.verdict !== "approved") {
144
146
  return { ok: false, verdict, reason: `review was rejected by ${verdict.reviewer} — fix the issues and run \`kj review\` again` };
145
147
  }
146
- return { ok: true, verdict };
148
+ // KJC-TSK-0886: otro kj comprobando no bloquea, pero deja rastro.
149
+ const now = kjStamp();
150
+ if (!stampDiffers(verdict.kj, now)) return { ok: true, verdict };
151
+ return { ok: true, verdict, note: `verdict from ${stampLabel(verdict.kj)}, checked by ${stampLabel(now)}` };
147
152
  }
@@ -17,9 +17,10 @@ import { compareHarden } from "../harden/advisory.js";
17
17
  import { detectTestFramework } from "../utils/project-detect.js";
18
18
  import { detectQmd } from "../utils/qmd-detect.js";
19
19
  import {
20
- dbPath, openVecStore, projectSlug, countChunks, getLastIndexedCommit,
20
+ projectSlug, countChunks, getLastIndexedCommit,
21
21
  } from "../rag/vec-store.js";
22
22
  import { classifyMaturity } from "./maturity.js";
23
+ import { openProjectStore, projectDbPath } from "../rag/project-store.js";
23
24
 
24
25
  const CODE_EXT = new Set([
25
26
  ".js", ".mjs", ".cjs", ".ts", ".tsx", ".jsx", ".py", ".go",
@@ -96,8 +97,8 @@ function lastCommitAgeDays(projectDir) {
96
97
  /** Read-only RAG index status; null when no index file exists yet. */
97
98
  function readRagStatus(projectDir) {
98
99
  try {
99
- if (!existsSync(dbPath())) return { indexed: false, chunks: 0, lastIndexedCommit: null };
100
- const db = openVecStore();
100
+ if (!existsSync(projectDbPath(projectDir))) return { indexed: false, chunks: 0, lastIndexedCommit: null };
101
+ const db = openProjectStore({ projectDir });
101
102
  return {
102
103
  indexed: true,
103
104
  chunks: countChunks(db, { kind: "code" }),
@@ -0,0 +1,61 @@
1
+ /**
2
+ * KJC-TSK-0879 (issue #1310) — Rulesync compatibility.
3
+ *
4
+ * A Rulesync-managed repo keeps its agent rules in `.rulesync/rules/` and
5
+ * `rulesync generate` compiles them into CLAUDE.md, AGENTS.md, .cursor/rules and
6
+ * the rest, overwriting those files. A block kj writes straight into CLAUDE.md
7
+ * is erased by the next generate, so in such a repo kj writes into Rulesync's
8
+ * source instead, with the same managed markers.
9
+ */
10
+ import { execFileSync } from "node:child_process";
11
+ import { existsSync } from "node:fs";
12
+ import { join } from "node:path";
13
+
14
+ export const RULESYNC_RULE = join(".rulesync", "rules", "karajan.md");
15
+
16
+ // Rulesync's own rule frontmatter: not the root overview, applies to every
17
+ // target and every file.
18
+ const FRONTMATTER = [
19
+ "---",
20
+ "root: false",
21
+ 'targets: ["*"]',
22
+ 'description: "Karajan Code: method, guidelines and playbook (managed by kj)"',
23
+ 'globs: ["**/*"]',
24
+ "---",
25
+ "",
26
+ ].join("\n");
27
+
28
+ /** The project uses Rulesync when it has `.rulesync/` or `rulesync.jsonc`. */
29
+ export function detectRulesync(projectDir) {
30
+ return existsSync(join(projectDir, ".rulesync")) || existsSync(join(projectDir, "rulesync.jsonc"));
31
+ }
32
+
33
+ /** What a brand-new karajan.md starts with, before kj's managed blocks. */
34
+ export const rulesyncRuleSeed = () => FRONTMATTER;
35
+
36
+ const GENERATE_ARGS = ["generate", "--targets", "*", "--features", "*"];
37
+ const defaultRun = (cmd, args, cwd) => execFileSync(cmd, args, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" });
38
+
39
+ /**
40
+ * Compile kj's rules out to every agent, only when the project declared
41
+ * `rulesync.generate: true`: kj does not run someone else's compiler on its
42
+ * own. And never a package fetched on the fly: the local binary, or
43
+ * `npx --no-install`. A failure is said out loud and does not break the install.
44
+ */
45
+ export function maybeRulesyncGenerate({ projectDir, config, logger = console, run = defaultRun }) {
46
+ if (!detectRulesync(projectDir)) return { ran: false, reason: "no-rulesync" };
47
+ if (config?.rulesync?.generate !== true) {
48
+ logger.info?.(`kj: its rules are in ${RULESYNC_RULE}; run rulesync generate to reach your agents, or declare rulesync.generate: true`);
49
+ return { ran: false, reason: "not-opted-in" };
50
+ }
51
+ const local = join(projectDir, "node_modules", ".bin", "rulesync");
52
+ const [cmd, args] = existsSync(local) ? [local, GENERATE_ARGS] : ["npx", ["--no-install", "rulesync", ...GENERATE_ARGS]];
53
+ try {
54
+ run(cmd, args, projectDir);
55
+ logger.info?.("kj: rulesync generate spread kj's rules to every agent");
56
+ return { ran: true };
57
+ } catch (err) {
58
+ logger.warn?.(`kj: rulesync generate failed (${err.message}); kj's rules are in ${RULESYNC_RULE}, run it yourself`);
59
+ return { ran: false, reason: "failed" };
60
+ }
61
+ }