karajan-code 4.48.1 → 4.48.3

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.48.1",
3
+ "version": "4.48.3",
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",
@@ -104,6 +104,7 @@
104
104
  "@babel/parser": "^7.29.7",
105
105
  "@karajan-family/governance": "^0.1.0",
106
106
  "@modelcontextprotocol/sdk": "^1.29.0",
107
+ "@xterm/xterm": "^6.0.0",
107
108
  "better-sqlite3": "^12.10.0",
108
109
  "chokidar": "^5.0.0",
109
110
  "commander": "^15.0.0",
@@ -120,8 +121,12 @@
120
121
  "sqlite-vec": "^0.1.9",
121
122
  "valibot": "^1.4.1",
122
123
  "web-tree-sitter": "^0.26.9",
124
+ "ws": "^8.21.3",
123
125
  "yaml": "^2.9.0"
124
126
  },
127
+ "optionalDependencies": {
128
+ "node-pty": "^1.1.0"
129
+ },
125
130
  "devDependencies": {
126
131
  "@eslint/js": "^10.0.1",
127
132
  "@vitest/coverage-v8": "^4.1.8",
@@ -20,6 +20,16 @@ const HARNESS_PREFIX = ".karajan/harness/";
20
20
  const SAFE_DIR = /^(\$HOME)?(\/[\w.@%+~-]+)+$/;
21
21
 
22
22
  const sha256 = (buf) => createHash("sha256").update(buf).digest("hex");
23
+ // KJC-BUG-0311: the kj judging now, to tell a seal made by another version. Read
24
+ // lazily and never fatal (a bundled binary may not carry package.json): unknown
25
+ // means no seal counts as "older", so the strict re-render rule applies.
26
+ let kjVersionCache;
27
+ const kjVersion = () => {
28
+ if (kjVersionCache === undefined) {
29
+ try { kjVersionCache = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8")).version ?? null; } catch { kjVersionCache = null; }
30
+ }
31
+ return kjVersionCache;
32
+ };
23
33
 
24
34
  /**
25
35
  * @returns {{files: Set<string>, reason?: string}} rutas repo-relativas de
@@ -41,6 +51,10 @@ export function verifiedSupervisorFiles({ projectDir, trackedOnly = false }) {
41
51
  if (!signed.ok) return { files: new Set(), reason: signed.reason };
42
52
  const ok = new Set();
43
53
  const unjudgeable = new Set();
54
+ const current = kjVersion();
55
+ const olderSeal = current && typeof prov?.kj_version === "string" && prov.kj_version !== current ? prov.kj_version : null;
56
+ let vouched = false;
57
+ let stale = false;
44
58
  // KJC-BUG-0259 (user's decision, option A): history is judged with the kj of
45
59
  // when it was committed. The harness guards are machine-local and never in the
46
60
  // repo; the review and each PR's CI verify them when the seal is made. A check
@@ -87,13 +101,23 @@ export function verifiedSupervisorFiles({ projectDir, trackedOnly = false }) {
87
101
  continue;
88
102
  }
89
103
  if (canonical != null && sha256(Buffer.from(canonical, "utf8")) === entry.sha256) ok.add(entry.file);
104
+ // KJC-BUG-0311 (#2052): sealed with another kj whose template this kj cannot
105
+ // re-render. A phone of the roster signed these very bytes: that vouches for
106
+ // them. Without that signature recomputation is the only proof, so it stays
107
+ // denied (an unsigned provenance could claim any version to skip it).
108
+ else if (olderSeal && signed.required) { ok.add(entry.file); vouched = true; }
109
+ else if (olderSeal) stale = true;
90
110
  }
91
111
  // `complete` = ninguna entrada FALLO y alguna verifico. Exigir que todas
92
112
  // verifiquen hacia imposible sellar desde cualquier sitio que no fuera la
93
113
  // maquina que sello, porque los guardias no viajan con el repo (0212).
94
114
  const judged = (e) => ok.has(e.file) || unjudgeable.has(e.file);
95
115
  const complete = ok.size > 0 && entries.every((e) => typeof e?.file === "string" && judged(e));
96
- return { files: ok, complete, unjudgeable, signed: signed.required };
116
+ return {
117
+ files: ok, complete, unjudgeable, signed: signed.required,
118
+ ...(vouched ? { vouchedOlder: olderSeal } : {}),
119
+ ...(stale ? { reason: `sellado con kj ${olderSeal} y este kj (${current}) no puede recomputar su plantilla, y sin firma del padrón nada más lo respalda: re-séllalo con kj harden --commit` } : {}),
120
+ };
97
121
  }
98
122
 
99
123
  /**
@@ -117,6 +141,7 @@ export function liftSealedSupervisorViolations({ projectDir, violations, tracked
117
141
  ...(unjudged > 0 ? [`${unjudged} guardia(s) del sello no existen en este checkout y no se han podido comprobar aquí`] : []),
118
142
  // KJC-TSK-0964: what the signature did or did not prove is said, never assumed.
119
143
  ...(sealed.signed === false ? ["proyecto sin padrón de firmantes: el sello no lleva firma verificable y su garantía es solo local"] : []),
144
+ ...(sealed.vouchedOlder ? [`sellado con kj ${sealed.vouchedOlder}: este kj no puede recomputar su plantilla y lo respalda la firma del padrón sobre esos bytes`] : []),
120
145
  ...(kept.length === violations.length && sealed.reason ? [sealed.reason] : []),
121
146
  ];
122
147
  return {