@kal-elsam/kairo-runtime 0.23.2 → 0.24.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,31 @@ Historical entries below may reference the legacy `@kal-elsam/harness` package n
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## 0.24.0 — 2026-09-18 (Kairo Runtime)
9
+
10
+ Minor release. ASK mode joins PROJECT TEAM.
11
+
12
+ ### Changed
13
+
14
+ - ASK mode now checks PROJECT TEAM's Explorer role first (read-only
15
+ investigation is exactly Explorer's job), via the same routing real
16
+ execution already uses — instead of always going through a fully
17
+ separate, generic quota/effort heuristic. Falls back to that
18
+ heuristic only when there's no active team yet, or Explorer's real
19
+ assignment isn't one ASK can actually invoke (Cursor/OpenCode
20
+ Go/Zen aren't ask-capable yet). Role is always Explorer, never
21
+ inferred from the question's text.
22
+
23
+ ### Fixed
24
+
25
+ - A flaky timing test in `quick-ask.test.js` (from 0.23.2) used
26
+ margins too tight to reliably survive full-suite load; widened them.
27
+
28
+ Not yet in this release: PLAN mode routing through the Orchestrator
29
+ role (plan creation is currently structurally Codex-only, a bigger
30
+ change than a routing choice), and AGENT mode (an open product
31
+ question on whether it should skip the plan→approve gate).
32
+
8
33
  ## 0.23.2 — 2026-09-18 (Kairo Runtime)
9
34
 
10
35
  Patch release.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kal-elsam/kairo-runtime",
3
- "version": "0.23.2",
3
+ "version": "0.24.0",
4
4
  "description": "Kairo Runtime — local agent operating system for Codex, Cursor, Claude, Pi, Engram, and Graphify.",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/Kal-elSam/harness#readme",
@@ -23,8 +23,12 @@ import { computeRoleEvaluations } from "../intelligence/capability-scoring.js";
23
23
  // The Bootstrap Analyst investigates read-only via askProvider
24
24
  // (intelligence/quick-ask.js), which only actually supports these two
25
25
  // providers today — offering any other real candidate as an "alternative"
26
- // here would be a menu item Kairo can't actually run.
27
- const ASK_SUPPORTED_ADAPTERS = new Set(["codex", "claude"]);
26
+ // here would be a menu item Kairo can't actually run. Exported: ASK mode's
27
+ // own real-time routing (service.js's planAsk) needs this exact same real
28
+ // constraint when it tries to route a plain question through a PROJECT
29
+ // TEAM role — a role assigned to, say, opencode-go is a real, valid team
30
+ // assignment, just not one askProvider can call.
31
+ export const ASK_SUPPORTED_ADAPTERS = new Set(["codex", "claude"]);
28
32
 
29
33
  /**
30
34
  * The Bootstrap Analyst as a temporary, read-only WORKFLOW — deliberately
@@ -26,8 +26,8 @@ import { appendTranscriptEntry, clearTranscript, readTranscript } from "./transc
26
26
  import { readSession, writeSessionMode } from "./session-store.js";
27
27
  import { computeProjectProfile } from "./project-profile.js";
28
28
  import {
29
- buildProjectStrategy, computeBootstrapAnalystAlternatives, computeBootstrapAnalystCatalog, isStrategyStale,
30
- computeProjectTeamEditCatalog, applyProjectTeamOverride, resetProjectTeamAssignment
29
+ ASK_SUPPORTED_ADAPTERS, buildProjectStrategy, computeBootstrapAnalystAlternatives, computeBootstrapAnalystCatalog,
30
+ isStrategyStale, computeProjectTeamEditCatalog, applyProjectTeamOverride, resetProjectTeamAssignment
31
31
  } from "./project-strategy.js";
32
32
  import { buildAnalystPrompt, deriveRoleRequirements, parseProjectAnalysis } from "./project-analysis.js";
33
33
  import { buildSanitizedSnapshot } from "./sanitized-snapshot.js";
@@ -662,6 +662,34 @@ export function createConversationService(deps = {}) {
662
662
  */
663
663
  async planAsk({ cwd, task }) {
664
664
  const projectRoot = await root(cwd);
665
+ // PROJECT TEAM's own Explorer role first — a real, approved,
666
+ // project-specific assignment beats the generic heuristic below,
667
+ // same principle as real execution routing. Explorer, never a
668
+ // guess from the question's text: resolveProjectRoute's whole
669
+ // design is that a role is always the caller's own explicit fixed
670
+ // choice, never inferred per-call — ASK questions are read-only
671
+ // investigation, which is exactly Explorer's job.
672
+ const teamRoute = await this.routeProjectExecution("Explorer", projectRoot);
673
+ const teamModel = teamRoute.decision === "ROUTED" ? teamRoute.model
674
+ : teamRoute.decision === "WAIT_FOR_PROJECT_TEAM" ? teamRoute.suggestedAlternative?.model ?? null
675
+ : null;
676
+ // Only when that real assignment is one askProvider can actually
677
+ // call (see ASK_SUPPORTED_ADAPTERS's own doc) — a role can be
678
+ // validly assigned to Cursor/OpenCode Go/Zen, which ASK simply
679
+ // can't invoke yet, so that's a real reason to fall through below,
680
+ // never an error.
681
+ if (teamModel && ASK_SUPPORTED_ADAPTERS.has(teamModel.adapterId)) {
682
+ return {
683
+ decision: {
684
+ decision: "ROUTED", provider: teamModel.adapterId, model: teamModel.modelId,
685
+ why: `Explorer (PROJECT TEAM): ${teamRoute.why}`
686
+ },
687
+ projectRoot
688
+ };
689
+ }
690
+ // No active team, or Explorer's real assignment isn't ask-capable —
691
+ // fall back to the generic quota/capability heuristic so ASK stays
692
+ // useful even before a team is approved.
665
693
  const adapters = inspectAdapters({ cwd: projectRoot });
666
694
  let codexUsage = null;
667
695
  let claudeUsage = null;
@@ -89,7 +89,7 @@ export async function readCodexModels({
89
89
  child.once?.("close", () => { if (!finished) finish(unknown("codex app-server closed before model list")); });
90
90
 
91
91
  writeRequest(child, 1, "initialize", {
92
- clientInfo: { name: "kairo", title: "Kairo", version: "0.23.2" },
92
+ clientInfo: { name: "kairo", title: "Kairo", version: "0.24.0" },
93
93
  capabilities: {}
94
94
  });
95
95
  });
@@ -151,7 +151,7 @@ export async function readCodexUsage({
151
151
  child.once?.("close", () => { if (!finished) finish(unknown("codex app-server closed before rate limits")); });
152
152
 
153
153
  writeRequest(child, 1, "initialize", {
154
- clientInfo: { name: "kairo", title: "Kairo", version: "0.23.2" },
154
+ clientInfo: { name: "kairo", title: "Kairo", version: "0.24.0" },
155
155
  capabilities: {}
156
156
  });
157
157
  });