@karajan-family/code 4.31.1 → 4.33.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 (37) hide show
  1. package/package.json +1 -1
  2. package/src/agents/aider-agent.js +2 -12
  3. package/src/agents/base-agent.js +9 -20
  4. package/src/agents/claude-agent.js +2 -12
  5. package/src/agents/codex-agent.js +2 -12
  6. package/src/agents/dead-models.js +74 -0
  7. package/src/agents/gemini-agent.js +2 -12
  8. package/src/agents/model-errors.js +35 -0
  9. package/src/agents/opencode-agent.js +2 -12
  10. package/src/brain/agent-error-classifier.js +19 -1
  11. package/src/brain/role-fallback-chain.js +100 -0
  12. package/src/brain/with-brain-recovery.js +59 -3
  13. package/src/checks/action-pins.js +131 -0
  14. package/src/checks/project-checks.js +11 -0
  15. package/src/checks/repo-state.js +89 -0
  16. package/src/cli/register-pipeline.js +15 -1
  17. package/src/commands/bootstrap.js +56 -0
  18. package/src/commands/check.js +5 -0
  19. package/src/commands/code.js +57 -4
  20. package/src/commands/env.js +2 -1
  21. package/src/commands/go.js +9 -10
  22. package/src/commands/harden.js +3 -1
  23. package/src/commands/review-gate.js +28 -5
  24. package/src/environment/panel.js +52 -0
  25. package/src/environment/playbook.js +7 -6
  26. package/src/harden/config-templates.js +7 -1
  27. package/src/harden/guidelines-engine.js +7 -3
  28. package/src/harden/guidelines-templates.js +60 -10
  29. package/src/harden/hook-templates.js +4 -1
  30. package/src/privacy/diff-scope.js +58 -0
  31. package/src/privacy/scan.js +18 -0
  32. package/src/prompts/card-context.js +57 -0
  33. package/src/prompts/session-context.js +68 -0
  34. package/src/review/one-shot-review.js +5 -0
  35. package/src/review/ui-evidence.js +65 -0
  36. package/src/roles/agent-role.js +11 -2
  37. package/src/start/project-script.js +84 -0
@@ -0,0 +1,84 @@
1
+ /**
2
+ * BOOT-C (KJC-TSK-0862) — the project's start script.
3
+ *
4
+ * From the Anthropic write-up on harnesses for long-running agents, and from
5
+ * the cold-start map: a session burns tokens working out how the project is
6
+ * launched, and worse, starts building on a tree that was already broken
7
+ * without knowing it. kj verifies the method; nobody verified that the
8
+ * application runs.
9
+ *
10
+ * kj declares the CONTRACT and checks it. The project writes the script,
11
+ * because kj cannot know how a project it has never seen is launched, and
12
+ * generating one from stack detection would produce the decorative artefact
13
+ * this codebase already rejects elsewhere (a config without its tool).
14
+ *
15
+ * It reports, it does not block: a badly written script must not stop work
16
+ * over something unrelated to the card. It earns the right to block when it
17
+ * proves reliable, the same path Sonar and the RAG took.
18
+ */
19
+
20
+ import { spawn } from "node:child_process";
21
+ import { existsSync } from "node:fs";
22
+ import { join } from "node:path";
23
+
24
+ export const DEFAULT_START_SCRIPT = ".karajan/start.sh";
25
+ export const DEFAULT_TIMEOUT_MS = 120_000;
26
+ export const MAX_OUTPUT_BYTES = 64 * 1024;
27
+
28
+ export const START_SCRIPT_CONTRACT = [
29
+ "El guion de arranque levanta lo que haya que levantar y corre un humo de referencia.",
30
+ "Sale con 0 si el proyecto arranca y el humo pasa; con otro código si no.",
31
+ "No modifica el árbol ni depende de credenciales: solo responde si esto funciona ahora mismo.",
32
+ ].join(" ");
33
+
34
+ /** Where the start script lives: the project's config decides, with a default. */
35
+ export function startScriptPath(projectDir, config = {}) {
36
+ return join(projectDir, config.start_script || DEFAULT_START_SCRIPT);
37
+ }
38
+
39
+ /**
40
+ * @returns {Promise<{status: "absent"|"ok"|"broken"|"timeout", exitCode?: number, output?: string, contract?: string, path: string}>}
41
+ */
42
+ export function runStartScript({ projectDir, config = {}, timeoutMs = DEFAULT_TIMEOUT_MS } = {}) {
43
+ const script = startScriptPath(projectDir, config);
44
+ if (!existsSync(script)) {
45
+ return Promise.resolve({ status: "absent", path: script, contract: START_SCRIPT_CONTRACT });
46
+ }
47
+ return new Promise((resolve) => {
48
+ const ownGroup = process.platform !== "win32";
49
+ const child = spawn("sh", [script], { cwd: projectDir, detached: ownGroup });
50
+ let output = "";
51
+ let truncated = false;
52
+ let timedOut = false;
53
+ // Bounded on purpose (catch de codex): a verbose or runaway script would
54
+ // otherwise eat the CLI's memory for the whole timeout. The LAST bytes are
55
+ // the ones worth keeping — that is where a failure explains itself.
56
+ const collect = (buf) => {
57
+ output += String(buf);
58
+ if (output.length > MAX_OUTPUT_BYTES) {
59
+ output = output.slice(-MAX_OUTPUT_BYTES);
60
+ truncated = true;
61
+ }
62
+ };
63
+ child.stdout?.on("data", collect);
64
+ child.stderr?.on("data", collect);
65
+ // Kill the GROUP, not just the shell (catch de codex): this script's whole
66
+ // job is to START things, so the dev server it launched would keep its port
67
+ // long after we reported a timeout.
68
+ const killTree = () => {
69
+ try {
70
+ if (ownGroup && child.pid) process.kill(-child.pid, "SIGKILL");
71
+ else child.kill("SIGKILL");
72
+ } catch { /* ya no está */ }
73
+ };
74
+ // A script that hangs is not a verdict: it is a script that hangs.
75
+ const timer = setTimeout(() => { timedOut = true; killTree(); }, timeoutMs);
76
+ child.on("error", (err) => { clearTimeout(timer); resolve({ status: "broken", path: script, exitCode: null, output: `${output}${err.message}`, truncated }); });
77
+ // Resolve on CLOSE, never before: the answer comes once the tree is down.
78
+ child.on("close", (code) => {
79
+ clearTimeout(timer);
80
+ if (timedOut) resolve({ status: "timeout", path: script, output, truncated });
81
+ else resolve({ status: code === 0 ? "ok" : "broken", exitCode: code, path: script, output, truncated });
82
+ });
83
+ });
84
+ }