@kurrent/kcap 0.11.10 → 0.11.12
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/bin/kcap.js +8 -26
- package/bin/refresh.js +104 -1
- package/bin/resolve.js +61 -0
- package/kcap/.claude-plugin/plugin.json +1 -1
- package/kcap/skills/agent-flows/SKILL.md +14 -8
- package/kcap/skills/review-flows/SKILL.md +18 -10
- package/package.json +9 -9
package/bin/kcap.js
CHANGED
|
@@ -5,28 +5,11 @@
|
|
|
5
5
|
const { execFileSync, spawnSync } = require("child_process");
|
|
6
6
|
const path = require("path");
|
|
7
7
|
const fs = require("fs");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} catch {
|
|
14
|
-
try {
|
|
15
|
-
return fs.readdirSync("/lib").some((f) => f.startsWith("ld-musl-"));
|
|
16
|
-
} catch {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const PLATFORM_PACKAGES = {
|
|
23
|
-
"darwin-arm64": "@kurrent/kcap-darwin-arm64",
|
|
24
|
-
"linux-x64": "@kurrent/kcap-linux-x64",
|
|
25
|
-
"linux-arm64": "@kurrent/kcap-linux-arm64",
|
|
26
|
-
"linux-musl-x64": "@kurrent/kcap-linux-musl-x64",
|
|
27
|
-
"linux-musl-arm64": "@kurrent/kcap-linux-musl-arm64",
|
|
28
|
-
"win32-x64": "@kurrent/kcap-win-x64",
|
|
29
|
-
};
|
|
8
|
+
// Platform detection + native-binary resolution live in resolve.js — a
|
|
9
|
+
// side-effect-free module shared with refresh.js (which must never require
|
|
10
|
+
// THIS file: during `kcap update`, runUpdate executes before the final
|
|
11
|
+
// module.exports below, so it would see partial exports).
|
|
12
|
+
const { PLATFORM_PACKAGES, platformKey } = require("./resolve");
|
|
30
13
|
|
|
31
14
|
// Resolves the npm dist-tag to install for `kcap update`, based on the
|
|
32
15
|
// resolved channel reported by `kcap update --check`'s `install_tag` field.
|
|
@@ -203,12 +186,11 @@ function printLockedBinaryHelp(globalRoot, onlyIfFound = false) {
|
|
|
203
186
|
// runs the update flow), so it's guarded to only run when this file is
|
|
204
187
|
// executed directly — not when `require()`d (e.g. by the test).
|
|
205
188
|
if (require.main === module) {
|
|
206
|
-
const
|
|
207
|
-
const
|
|
208
|
-
const packageName = PLATFORM_PACKAGES[platformKey];
|
|
189
|
+
const key = platformKey();
|
|
190
|
+
const packageName = PLATFORM_PACKAGES[key];
|
|
209
191
|
|
|
210
192
|
if (!packageName) {
|
|
211
|
-
console.error(`Unsupported platform: ${
|
|
193
|
+
console.error(`Unsupported platform: ${key}`);
|
|
212
194
|
console.error(`Supported: ${Object.keys(PLATFORM_PACKAGES).join(", ")}`);
|
|
213
195
|
process.exit(1);
|
|
214
196
|
}
|
package/bin/refresh.js
CHANGED
|
@@ -7,8 +7,14 @@
|
|
|
7
7
|
// when the package manager allows install scripts to run.
|
|
8
8
|
// - kcap.js `update` — runs after a user-initiated `kcap update`, which works
|
|
9
9
|
// even when the package manager blocks postinstall scripts.
|
|
10
|
+
//
|
|
11
|
+
// This file must never require kcap.js: during `kcap update`, runUpdate executes
|
|
12
|
+
// before kcap.js's final module.exports assignment, so it would observe partial
|
|
13
|
+
// exports. Shared platform/binary resolution lives in resolve.js instead.
|
|
10
14
|
|
|
11
15
|
const { spawnSync } = require("child_process");
|
|
16
|
+
const path = require("path");
|
|
17
|
+
const fs = require("fs");
|
|
12
18
|
|
|
13
19
|
// One entry per agent. Order is independent — each refresh is gated by its own
|
|
14
20
|
// marker via `--if-installed`, which no-ops unless the user has previously
|
|
@@ -28,6 +34,11 @@ const REFRESHES = [
|
|
|
28
34
|
// from one never prevents the others and never throws to the caller — a failed
|
|
29
35
|
// refresh must never break `npm install` or report `kcap update` as failed.
|
|
30
36
|
function runRefreshes(launcherPath) {
|
|
37
|
+
// Point the shipped Claude plugin's MCP entries at the native binary. Runs
|
|
38
|
+
// here because runRefreshes fires at exactly the two moments the plugin dir
|
|
39
|
+
// has just been (re)written by npm: postinstall and `kcap update`.
|
|
40
|
+
patchPluginMcpConfig(launcherPath);
|
|
41
|
+
|
|
31
42
|
for (const argv of REFRESHES) {
|
|
32
43
|
try {
|
|
33
44
|
spawnSync(process.execPath, [launcherPath, ...argv], {
|
|
@@ -44,4 +55,96 @@ function runRefreshes(launcherPath) {
|
|
|
44
55
|
}
|
|
45
56
|
}
|
|
46
57
|
|
|
47
|
-
|
|
58
|
+
// ── Claude plugin .mcp.json patch ───────────────────────────────────────────
|
|
59
|
+
//
|
|
60
|
+
// The plugin ships `"command": "kcap"`, which resolves to the node wrapper —
|
|
61
|
+
// one resident Node runtime per MCP server per open Claude session (~25 MB
|
|
62
|
+
// idle each). Rewriting the command to the resolved native binary makes Claude
|
|
63
|
+
// spawn the binary directly. Best-effort: on any failure the shipped value
|
|
64
|
+
// stays in place, which still works via the wrapper.
|
|
65
|
+
|
|
66
|
+
// The servers shipped in the plugin's .mcp.json, keyed by canonical
|
|
67
|
+
// `["mcp", <suffix>]` args. Only these exact name/args pairs are patched —
|
|
68
|
+
// anything else in the file is preserved verbatim.
|
|
69
|
+
const PLUGIN_MCP_SERVERS = {
|
|
70
|
+
"kcap-review": "review",
|
|
71
|
+
"kcap-sessions": "sessions",
|
|
72
|
+
"kcap-flows": "flows",
|
|
73
|
+
"kcap-memory": "memory",
|
|
74
|
+
"kcap-workitems": "workitems",
|
|
75
|
+
"kcap-analytics": "analytics",
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// A command this patcher may rewrite: the shipped literal "kcap", or an
|
|
79
|
+
// absolute path whose basename is the kcap binary (a previous patch that has
|
|
80
|
+
// gone stale after an npm re-layout). Handles both path flavors so a stale
|
|
81
|
+
// Windows path is still recognized. Anything else is a customization → keep.
|
|
82
|
+
function isPatchableKcapCommand(command) {
|
|
83
|
+
if (command === "kcap") return true;
|
|
84
|
+
if (typeof command !== "string") return false;
|
|
85
|
+
if (!path.posix.isAbsolute(command) && !path.win32.isAbsolute(command)) return false;
|
|
86
|
+
const base = command.split(/[\\/]/).pop().toLowerCase();
|
|
87
|
+
return base === "kcap" || base === "kcap.exe";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Pure: rewrites in place the canonical plugin entries of `cfg` whose command
|
|
91
|
+
// is patchable, returning whether anything changed. Throws on a shape that
|
|
92
|
+
// isn't the plugin config (caller turns that into the single warning).
|
|
93
|
+
function patchPluginMcpServers(cfg, binaryPath) {
|
|
94
|
+
if (!cfg || typeof cfg !== "object" || Array.isArray(cfg)) {
|
|
95
|
+
throw new Error("config is not an object");
|
|
96
|
+
}
|
|
97
|
+
const servers = cfg.mcpServers;
|
|
98
|
+
if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
|
|
99
|
+
throw new Error("mcpServers is not an object");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let changed = false;
|
|
103
|
+
for (const [name, suffix] of Object.entries(PLUGIN_MCP_SERVERS)) {
|
|
104
|
+
const entry = servers[name];
|
|
105
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
106
|
+
if (!Array.isArray(entry.args) || entry.args.length !== 2 ||
|
|
107
|
+
entry.args[0] !== "mcp" || entry.args[1] !== suffix) continue; // customized args → keep
|
|
108
|
+
if (!isPatchableKcapCommand(entry.command)) continue; // customized command → keep
|
|
109
|
+
if (entry.command === binaryPath) continue; // already current
|
|
110
|
+
entry.command = binaryPath;
|
|
111
|
+
changed = true;
|
|
112
|
+
}
|
|
113
|
+
return changed;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Rewrites the plugin's shipped .mcp.json (a sibling `kcap/` dir of the
|
|
117
|
+
// launcher's `bin/`) so Claude spawns the native binary directly. Validates
|
|
118
|
+
// before writing, writes a sibling temp file, then renames atomically — the
|
|
119
|
+
// original survives any pre-rename failure. Never throws; on failure it emits
|
|
120
|
+
// ONE concise warning and leaves the shipped `"command": "kcap"` in place.
|
|
121
|
+
// `binaryPath` is a test seam; real callers let it resolve.
|
|
122
|
+
function patchPluginMcpConfig(launcherPath, binaryPath) {
|
|
123
|
+
let mcpJsonPath;
|
|
124
|
+
try {
|
|
125
|
+
binaryPath = binaryPath || require("./resolve").resolveNativeBinary();
|
|
126
|
+
if (!binaryPath) return; // unsupported platform / package missing — wrapper keeps working
|
|
127
|
+
|
|
128
|
+
mcpJsonPath = path.join(path.dirname(launcherPath), "..", "kcap", ".mcp.json");
|
|
129
|
+
if (!fs.existsSync(mcpJsonPath)) return; // dev checkout / plugin not shipped
|
|
130
|
+
|
|
131
|
+
const cfg = JSON.parse(fs.readFileSync(mcpJsonPath, "utf8"));
|
|
132
|
+
if (!patchPluginMcpServers(cfg, binaryPath)) return; // already patched / nothing canonical
|
|
133
|
+
|
|
134
|
+
const tmp = `${mcpJsonPath}.tmp-${process.pid}-${Date.now()}`;
|
|
135
|
+
try {
|
|
136
|
+
fs.writeFileSync(tmp, JSON.stringify(cfg, null, 2) + "\n");
|
|
137
|
+
fs.renameSync(tmp, mcpJsonPath);
|
|
138
|
+
} catch (e) {
|
|
139
|
+
try { fs.unlinkSync(tmp); } catch {}
|
|
140
|
+
throw e;
|
|
141
|
+
}
|
|
142
|
+
} catch (e) {
|
|
143
|
+
console.warn(
|
|
144
|
+
`kcap: could not point the Claude plugin MCP entries at the native binary` +
|
|
145
|
+
` (${e && e.message ? e.message : e}); they will keep launching via the node wrapper.`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = { runRefreshes, patchPluginMcpConfig, patchPluginMcpServers, isPatchableKcapCommand };
|
package/bin/resolve.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Side-effect-free platform/native-binary resolution, shared by kcap.js (the
|
|
2
|
+
// launcher) and refresh.js (postinstall / `kcap update` refresh).
|
|
3
|
+
//
|
|
4
|
+
// This lives in its OWN module — refresh.js must never require kcap.js: during
|
|
5
|
+
// `kcap update`, runUpdate executes BEFORE kcap.js's final module.exports
|
|
6
|
+
// assignment, so a refresh.js → kcap.js require would observe partial exports
|
|
7
|
+
// exactly on that path. Requiring this module has no side effects.
|
|
8
|
+
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const fs = require("fs");
|
|
11
|
+
|
|
12
|
+
function isMusl() {
|
|
13
|
+
if (process.platform !== "linux") return false;
|
|
14
|
+
try {
|
|
15
|
+
return fs.readFileSync("/usr/bin/ldd", "utf8").includes("musl");
|
|
16
|
+
} catch {
|
|
17
|
+
try {
|
|
18
|
+
return fs.readdirSync("/lib").some((f) => f.startsWith("ld-musl-"));
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const PLATFORM_PACKAGES = {
|
|
26
|
+
"darwin-arm64": "@kurrent/kcap-darwin-arm64",
|
|
27
|
+
"linux-x64": "@kurrent/kcap-linux-x64",
|
|
28
|
+
"linux-arm64": "@kurrent/kcap-linux-arm64",
|
|
29
|
+
"linux-musl-x64": "@kurrent/kcap-linux-musl-x64",
|
|
30
|
+
"linux-musl-arm64": "@kurrent/kcap-linux-musl-arm64",
|
|
31
|
+
"win32-x64": "@kurrent/kcap-win-x64",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function platformKey() {
|
|
35
|
+
const musl = process.platform === "linux" && isMusl() ? "-musl" : "";
|
|
36
|
+
return `${process.platform}${musl}-${process.arch}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Absolute path to the native kcap binary for the current platform, or null
|
|
40
|
+
// when the platform is unsupported, the platform package isn't installed, or
|
|
41
|
+
// the binary file is missing. `basedir` (optional) overrides where module
|
|
42
|
+
// resolution starts — tests point it at a fake package layout; callers inside
|
|
43
|
+
// the real install tree omit it (resolution then starts from this file).
|
|
44
|
+
function resolveNativeBinary(basedir) {
|
|
45
|
+
const packageName = PLATFORM_PACKAGES[platformKey()];
|
|
46
|
+
if (!packageName) return null;
|
|
47
|
+
|
|
48
|
+
let binaryDir;
|
|
49
|
+
try {
|
|
50
|
+
const opts = basedir ? { paths: [basedir] } : undefined;
|
|
51
|
+
binaryDir = path.dirname(require.resolve(`${packageName}/package.json`, opts));
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
57
|
+
const binaryPath = path.join(binaryDir, "bin", `kcap${ext}`);
|
|
58
|
+
return fs.existsSync(binaryPath) ? binaryPath : null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = { PLATFORM_PACKAGES, isMusl, platformKey, resolveNativeBinary };
|
|
@@ -44,7 +44,10 @@ Once the user has explicitly opted into a flow (see above), pick the `definition
|
|
|
44
44
|
|
|
45
45
|
For the reserved `spec-review` and `code-review` aliases, reviewer-vendor language is role-bound:
|
|
46
46
|
pass the one vendor explicitly named as the reviewer, ignore driver-harness mentions, honor
|
|
47
|
-
negation, omit the vendor when none is named, and ask when multiple candidates remain.
|
|
47
|
+
negation, omit the vendor when none is named, and ask when multiple candidates remain. Omitting
|
|
48
|
+
`vendor` resolves to the definition's authored vendor when it declares one, then to your saved
|
|
49
|
+
`flows.reviewer_vendor` preference, then (with nothing saved) a `reviewer_vendor_required`
|
|
50
|
+
response — see `review-flows`' "Choosing the reviewer vendor" for the full chain. Custom
|
|
48
51
|
catalog definitions keep their authored vendors unless an explicit single-participant override is
|
|
49
52
|
requested; dynamic definitions always carry vendors per participant and reject a top-level override.
|
|
50
53
|
|
|
@@ -52,12 +55,15 @@ requested; dynamic definitions always carry vendors per participant and reject a
|
|
|
52
55
|
|
|
53
56
|
Your harness is holding an MCP tool schema it cached before kcap was upgraded, and kcap cannot
|
|
54
57
|
refresh a schema the harness has already cached. A parameter you cannot see is one you cannot send:
|
|
55
|
-
**do not start the flow and then report that the named reviewer ran** — without `vendor`
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
the
|
|
60
|
-
|
|
58
|
+
**do not start the flow and then report that the named reviewer ran** — without `vendor` you get
|
|
59
|
+
whatever the flow definition's authored vendor resolves to, or — for a vendor-less definition — an
|
|
60
|
+
automatic retry against your saved `flows.reviewer_vendor` preference, or a
|
|
61
|
+
`reviewer_vendor_required` response if none is saved; none of these is guaranteed to be the vendor
|
|
62
|
+
the user named. Nothing server-side can catch this for you: an omitted `vendor` is indistinguishable
|
|
63
|
+
from a caller who deliberately wants that resolved vendor, so the request carries no trace of the
|
|
64
|
+
name the user asked for. Tell the user to restart the harness session (or reconnect the
|
|
65
|
+
`kcap-flows` MCP server) and start a fresh task; start without `vendor` only if they then
|
|
66
|
+
explicitly ask you to proceed with whatever vendor the definition or saved preference resolves to.
|
|
61
67
|
|
|
62
68
|
Canonical reviewer aliases for reserved review flows: Claude / Claude Code → `claude`; Codex /
|
|
63
69
|
OpenAI Codex → `codex`; Cursor / cursor-agent → `cursor`; GitHub Copilot / Copilot CLI → `copilot`;
|
|
@@ -204,7 +210,7 @@ report completion to user
|
|
|
204
210
|
|
|
205
211
|
| Tool | Required args | Optional args | When to call |
|
|
206
212
|
|---|---|---|---|
|
|
207
|
-
| `start_flow` | Exactly one of `definition_id` (catalog id, e.g. `spec-review`, `code-review`, or a custom catalog id) or `definition_yaml` (inline dynamic definition — see "Composing a dynamic flow"); plus `target_kind` (what is being worked on: `spec`, `code`, `pr`, `branch`, `file`, etc.), `target_ref` (a path, branch name, or PR URL/number that identifies the target), `target_title` (short human-readable title), `context` (background context: what to focus on, constraints, definition of done) | `vendor` (reserved aliases only — explicit reviewer vendor; omit
|
|
213
|
+
| `start_flow` | Exactly one of `definition_id` (catalog id, e.g. `spec-review`, `code-review`, or a custom catalog id) or `definition_yaml` (inline dynamic definition — see "Composing a dynamic flow"); plus `target_kind` (what is being worked on: `spec`, `code`, `pr`, `branch`, `file`, etc.), `target_ref` (a path, branch name, or PR URL/number that identifies the target), `target_title` (short human-readable title), `context` (background context: what to focus on, constraints, definition of done) | `vendor` (reserved aliases only — explicit reviewer vendor; omit to use the definition's authored vendor, or your saved `flows.reviewer_vendor` preference if it declares none), `model` (reserved aliases only — explicit reviewer model override; REQUIRES `vendor`, rejected on dynamic/multi-participant starts), `instructions`, `mode` (`context-only` — optional; by default the participant's worktree is mirrored from THIS SESSION's project directory, not from the directory you are working in. Pass `context-only` to opt out and treat the submitted context as authoritative) | Once, at the start of a flow task. |
|
|
208
214
|
| `send_to_participant` | `flow_run_id`, `participant` (role name declared in the flow definition's `participants` map; single-participant definitions use `reviewer` — an unknown role is rejected, naming the valid ones), `message` | `instructions`, `async` (defaults to `true`) | After addressing a non-clean result for that role, or to launch a role for the first time. Pass the same `flow_run_id`, the role's name, and the updated message. |
|
|
209
215
|
| `get_flow_status` | `flow_run_id` | — | Poll or check the current status of a flow run (running, waiting, completed, failed). |
|
|
210
216
|
| `close_flow` | `flow_run_id` | — | Only after the definition's clean signal — or when abandoning the task early; the run otherwise stays open until closed. |
|
|
@@ -47,8 +47,12 @@ Treat the driver harness and reviewer as independent. A request such as "ask Cla
|
|
|
47
47
|
selects `vendor: "claude"` even when the current driver is Codex; mentions of the driver do not
|
|
48
48
|
select a reviewer. Anchor vendor language to the reviewer role ("Claude reviewer", "review with
|
|
49
49
|
Cursor", "ask Codex for review"), including negation ("not Claude"). If exactly one reviewer
|
|
50
|
-
vendor is named, pass it. If none is named, omit `vendor
|
|
51
|
-
|
|
50
|
+
vendor is named, pass it. If none is named, omit `vendor`: the flow definition's authored vendor
|
|
51
|
+
applies when it declares one; otherwise your saved `flows.reviewer_vendor` preference is applied
|
|
52
|
+
automatically (the response says so), and with no preference the server returns
|
|
53
|
+
`reviewer_vendor_required` — ask the user which reviewer vendor to use, pass it explicitly, and
|
|
54
|
+
offer to save it with `kcap config set flows.reviewer_vendor <vendor>`. If multiple reviewer
|
|
55
|
+
candidates remain after negation, ask the user to choose; never guess.
|
|
52
56
|
|
|
53
57
|
Canonical reviewer aliases: Claude / Claude Code → `claude`; Codex / OpenAI Codex → `codex`;
|
|
54
58
|
Cursor / cursor-agent → `cursor`; GitHub Copilot / Copilot CLI → `copilot`; Gemini / Gemini CLI →
|
|
@@ -65,16 +69,19 @@ cannot send. kcap cannot refresh a schema the harness has already cached.
|
|
|
65
69
|
|
|
66
70
|
When that happens and the user has named a reviewer:
|
|
67
71
|
|
|
68
|
-
- **Do not start the flow and then report that the named reviewer ran.** Without `vendor`
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
- **Do not start the flow and then report that the named reviewer ran.** Without `vendor` you get
|
|
73
|
+
whatever the flow definition's authored vendor resolves to, or — for a vendor-less definition —
|
|
74
|
+
an automatic retry against your saved `flows.reviewer_vendor` preference, or a
|
|
75
|
+
`reviewer_vendor_required` response if none is saved; none of these is guaranteed to be the
|
|
76
|
+
vendor the user named. Claiming the named reviewer ran when you could not send the parameter is
|
|
77
|
+
the single failure this contract exists to prevent.
|
|
72
78
|
- Tell the user their harness is holding a stale kcap MCP schema, and that the fix is to
|
|
73
79
|
restart the harness session (or reconnect the `kcap-flows` MCP server) and start a fresh task.
|
|
74
|
-
- Start without `vendor` only if the user, having been told, explicitly asks
|
|
80
|
+
- Start without `vendor` only if the user, having been told, explicitly asks you to proceed with
|
|
81
|
+
whatever vendor the definition or saved preference resolves to.
|
|
75
82
|
|
|
76
83
|
**Nothing server-side catches this for you.** An omitted `vendor` is indistinguishable from a caller
|
|
77
|
-
who deliberately
|
|
84
|
+
who deliberately wants that resolved vendor — the request carries no trace of the name the user
|
|
78
85
|
asked for, so there is nothing for the server to reject. The `client_upgrade_required`,
|
|
79
86
|
`flow_client_protocol_required`, and `flow_client_protocol_unsupported` errors below are separate
|
|
80
87
|
protections, against *protocol* skew; they do **not** fire on a cached schema that simply omits the
|
|
@@ -131,8 +138,9 @@ After applying the role-surface safety gate, if `start_review_flow` / `submit_re
|
|
|
131
138
|
|
|
132
139
|
- **`400` starting `no_daemon_available:`** — no connected daemon has the repo checked out. Relay the server's remediation verbatim, then act on the part you can: run `kcap daemon start -d` on a machine with the repo cloned (add `--name <new-name>` if the account already runs a daemon elsewhere), or get the repo cloned on a machine that already runs one. **You cannot redirect the flow at another daemon or checkout** — these tools expose no daemon or repo-path parameter. If the server's text suggests passing `daemon_name` / `repo_path`, ignore that part: do not invent those arguments, and do not retry unchanged.
|
|
133
140
|
- **`400` starting `daemon_outdated:`** — the daemon's kcap is too old to host flow participants. Relay the server error's remediation verbatim — it names the outdated daemon; the fix: update kcap (`npm i -g @kurrent/kcap`), then `kcap daemon restart --name <its-name>` (works for detached and service-managed daemons alike — a raw `daemon stop` deliberately refuses a service-managed one; `kcap daemon status` lists names, and `--when-idle` defers the restart if the daemon is busy).
|
|
134
|
-
- **`reviewer_vendor_required`** —
|
|
141
|
+
- **`reviewer_vendor_required`** — ask the user to name a reviewer vendor, pass it explicitly, and offer to save it (`kcap config set flows.reviewer_vendor <vendor>`); this appears only when the definition declares no vendor and no preference is saved.
|
|
135
142
|
- **`reviewer_vendor_unavailable`** — the selected vendor is not installed/certified unattended on an eligible daemon; do not silently fall back to another vendor.
|
|
143
|
+
- **`reviewer_vendor_unresolvable`** — returned from `submit_review_round` on a legacy in-flight run whose pinned definition lost its vendor and has no recorded assignment; close the flow and start a new one.
|
|
136
144
|
- **`client_upgrade_required`, `flow_client_protocol_required`, or `flow_client_protocol_unsupported`** — update kcap; reserved review aliases fail closed on stale clients.
|
|
137
145
|
- **`reserved_review_alias_shape`** — an admin changed a reserved alias to an invalid participant shape; restore exactly one participant named `reviewer`.
|
|
138
146
|
- **`400` starting `participant_unavailable:`** — the reviewer agent died and automatic relaunch is not available yet. Close this flow and start a new one, carrying your context forward; re-submitting will keep failing.
|
|
@@ -161,7 +169,7 @@ if findings:
|
|
|
161
169
|
|
|
162
170
|
| Tool | Required args | Optional args | When to call |
|
|
163
171
|
|---|---|---|---|
|
|
164
|
-
| `start_review_flow` | `kind` (`spec-review`\|`code-review`), `target_kind` (what is being reviewed: `spec`, `code`, `pr`, `branch`, `file`, etc.), `target_ref` (a path, branch name, or PR URL/number that identifies the target), `target_title` (short human-readable title, e.g. spec name or PR title), `context` (background context: what to focus on, constraints, definition of done) | `vendor` (explicit reviewer vendor; omit
|
|
172
|
+
| `start_review_flow` | `kind` (`spec-review`\|`code-review`), `target_kind` (what is being reviewed: `spec`, `code`, `pr`, `branch`, `file`, etc.), `target_ref` (a path, branch name, or PR URL/number that identifies the target), `target_title` (short human-readable title, e.g. spec name or PR title), `context` (background context: what to focus on, constraints, definition of done) | `vendor` (explicit reviewer vendor; omit to use the definition's authored vendor, or your saved `flows.reviewer_vendor` preference if it declares none), `model` (explicit reviewer model override — REQUIRES `vendor`; only pass it when the user named a model), `instructions`, `mode` (`context-only` — optional) | Once, at the start of a review task. |
|
|
165
173
|
| `submit_review_round` | `flow_run_id`, `context` | `instructions` | After addressing findings. Pass the same `flow_run_id` and the updated context. |
|
|
166
174
|
| `get_review_flow_status` | `flow_run_id` | — | Poll or check the current status of a flow (running, waiting, completed, failed). |
|
|
167
175
|
| `close_review_flow` | `flow_run_id` | — | Only after the reviewer returns `clean`. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kurrent/kcap",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.12",
|
|
4
4
|
"description": "CLI companion for Kurrent Capacitor — records and visualizes Claude Code sessions",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"repository": {
|
|
@@ -14,17 +14,17 @@
|
|
|
14
14
|
"postinstall": "node bin/postinstall.js"
|
|
15
15
|
},
|
|
16
16
|
"optionalDependencies": {
|
|
17
|
-
"@kurrent/kcap-darwin-arm64": "0.11.
|
|
18
|
-
"@kurrent/kcap-linux-arm64": "0.11.
|
|
19
|
-
"@kurrent/kcap-linux-musl-arm64": "0.11.
|
|
20
|
-
"@kurrent/kcap-linux-musl-x64": "0.11.
|
|
21
|
-
"@kurrent/kcap-linux-x64": "0.11.
|
|
22
|
-
"@kurrent/kcap-win-x64": "0.11.
|
|
17
|
+
"@kurrent/kcap-darwin-arm64": "0.11.12",
|
|
18
|
+
"@kurrent/kcap-linux-arm64": "0.11.12",
|
|
19
|
+
"@kurrent/kcap-linux-musl-arm64": "0.11.12",
|
|
20
|
+
"@kurrent/kcap-linux-musl-x64": "0.11.12",
|
|
21
|
+
"@kurrent/kcap-linux-x64": "0.11.12",
|
|
22
|
+
"@kurrent/kcap-win-x64": "0.11.12"
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"bin/",
|
|
26
26
|
"kcap/"
|
|
27
27
|
],
|
|
28
|
-
"kcapReleaseCommit": "
|
|
29
|
-
"kcapReleaseTag": "v0.11.
|
|
28
|
+
"kcapReleaseCommit": "b02e5f0a0e20700edd6787f61704419b78556f30",
|
|
29
|
+
"kcapReleaseTag": "v0.11.12"
|
|
30
30
|
}
|