@kurrent/kcap 1.3.0-beta.5 → 1.3.0-beta.7
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/refresh.js +26 -142
- package/bin/resolve.js +2 -7
- package/kcap/.claude-plugin/plugin.json +1 -1
- package/kcap/.mcp.json +1 -1
- package/kcap/README.md +1 -0
- package/kcap/hooks/hooks.json +10 -0
- package/kcap/skills/agent-flows/SKILL.md +36 -24
- package/kcap/skills/eval-watch/SKILL.md +94 -131
- package/kcap/skills/plans/SKILL.md +10 -3
- package/kcap/skills/review-flows/SKILL.md +9 -4
- package/kcap/skills/start-agents/SKILL.md +167 -0
- package/kcap/skills/work-items/SKILL.md +11 -1
- package/package.json +9 -9
- package/kcap/skills/suggest-review-flow/SKILL.md +0 -94
package/bin/refresh.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// Refreshes kcap's user-scope coding-agent installs
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// Refreshes kcap's user-scope coding-agent installs after an install or upgrade, by running
|
|
2
|
+
// `kcap refresh` — the native binary owns the refresh list and the Claude plugin's .mcp.json patch,
|
|
3
|
+
// so every installer (npm, the install scripts, a script install's `kcap update`) runs the same one.
|
|
4
4
|
//
|
|
5
5
|
// Shared by:
|
|
6
6
|
// - postinstall.js — runs after `npm install -g @kurrent/kcap` (incl. upgrades),
|
|
@@ -10,150 +10,34 @@
|
|
|
10
10
|
//
|
|
11
11
|
// This file must never require kcap.js: during `kcap update`, runUpdate executes
|
|
12
12
|
// before kcap.js's final module.exports assignment, so it would observe partial
|
|
13
|
-
// exports.
|
|
13
|
+
// exports.
|
|
14
14
|
|
|
15
15
|
const { spawnSync } = require("child_process");
|
|
16
|
-
const path = require("path");
|
|
17
|
-
const fs = require("fs");
|
|
18
16
|
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
// opted in (marker file present OR pre-marker install detected). A vendor entry
|
|
22
|
-
// also refreshes the shared ~/.agents/skills tree, but only tops up one that is
|
|
23
|
-
// already there: `plugin remove --skills` must survive an upgrade.
|
|
24
|
-
const REFRESHES = [
|
|
25
|
-
["plugin", "install", "--skills", "--if-installed"],
|
|
26
|
-
["plugin", "install", "--codex", "--if-installed"],
|
|
27
|
-
["plugin", "install", "--cursor", "--if-installed"],
|
|
28
|
-
["plugin", "install", "--copilot", "--if-installed"],
|
|
29
|
-
["plugin", "install", "--pi", "--if-installed"], // Pi extension (~/.pi/agent/extensions/kcap.ts)
|
|
30
|
-
["plugin", "install", "--opencode", "--if-installed"], // OpenCode plugin (~/.config/opencode/plugins/kcap.ts)
|
|
31
|
-
["plugin", "install", "--gemini", "--if-installed"], // Gemini hooks/MCP/instructions (~/.gemini)
|
|
32
|
-
["plugin", "install", "--kiro", "--if-installed"], // Kiro agent hooks (~/.kiro/agents/kcap.json)
|
|
33
|
-
["plugin", "install", "--antigravity", "--if-installed"], // Antigravity hooks (~/.gemini/config/plugins/kcap)
|
|
34
|
-
["plugin", "install", "--if-installed"], // Claude
|
|
35
|
-
];
|
|
17
|
+
// Above the binary's own worst case: eleven steps, each bounded at 60s.
|
|
18
|
+
const REFRESH_TIMEOUT_MS = 15 * 60_000;
|
|
36
19
|
|
|
37
|
-
// Runs
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
function runRefreshes(launcherPath) {
|
|
42
|
-
// Point the shipped Claude plugin's MCP entries at the native binary. Runs
|
|
43
|
-
// here because runRefreshes fires at exactly the two moments the plugin dir
|
|
44
|
-
// has just been (re)written by npm: postinstall and `kcap update`.
|
|
45
|
-
patchPluginMcpConfig(launcherPath);
|
|
46
|
-
|
|
47
|
-
for (const argv of REFRESHES) {
|
|
48
|
-
try {
|
|
49
|
-
spawnSync(process.execPath, [launcherPath, ...argv], {
|
|
50
|
-
stdio: "ignore",
|
|
51
|
-
env: process.env,
|
|
52
|
-
// Hard ceiling so a stalled child can never hang the caller.
|
|
53
|
-
timeout: 60_000,
|
|
54
|
-
killSignal: "SIGKILL",
|
|
55
|
-
windowsHide: true,
|
|
56
|
-
});
|
|
57
|
-
} catch {
|
|
58
|
-
// Never fail the caller.
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ── Claude plugin .mcp.json patch ───────────────────────────────────────────
|
|
64
|
-
//
|
|
65
|
-
// The plugin ships `"command": "kcap"`, which resolves to the node wrapper —
|
|
66
|
-
// one resident Node runtime per MCP server per open Claude session (~25 MB
|
|
67
|
-
// idle each). Rewriting the command to the resolved native binary makes Claude
|
|
68
|
-
// spawn the binary directly. Best-effort: on any failure the shipped value
|
|
69
|
-
// stays in place, which still works via the wrapper.
|
|
70
|
-
|
|
71
|
-
// The servers shipped in the plugin's .mcp.json, keyed by canonical
|
|
72
|
-
// `["mcp", <suffix>]` args. Only these exact name/args pairs are patched —
|
|
73
|
-
// anything else in the file is preserved verbatim.
|
|
74
|
-
const PLUGIN_MCP_SERVERS = {
|
|
75
|
-
"kcap-review": "review",
|
|
76
|
-
"kcap-sessions": "sessions",
|
|
77
|
-
"kcap-flows": "flows",
|
|
78
|
-
"kcap-memory": "memory",
|
|
79
|
-
"kcap-workitems": "workitems",
|
|
80
|
-
"kcap-plans": "plans",
|
|
81
|
-
"kcap-artefacts": "artefacts",
|
|
82
|
-
"kcap-analytics": "analytics",
|
|
83
|
-
"kcap-knowledge": "knowledge",
|
|
84
|
-
"kcap-handoff": "handoff",
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// A command this patcher may rewrite: the shipped literal "kcap", or an
|
|
88
|
-
// absolute path whose basename is the kcap binary (a previous patch that has
|
|
89
|
-
// gone stale after an npm re-layout). Handles both path flavors so a stale
|
|
90
|
-
// Windows path is still recognized. Anything else is a customization → keep.
|
|
91
|
-
function isPatchableKcapCommand(command) {
|
|
92
|
-
if (command === "kcap") return true;
|
|
93
|
-
if (typeof command !== "string") return false;
|
|
94
|
-
if (!path.posix.isAbsolute(command) && !path.win32.isAbsolute(command)) return false;
|
|
95
|
-
const base = command.split(/[\\/]/).pop().toLowerCase();
|
|
96
|
-
return base === "kcap" || base === "kcap.exe";
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Pure: rewrites in place the canonical plugin entries of `cfg` whose command
|
|
100
|
-
// is patchable, returning whether anything changed. Throws on a shape that
|
|
101
|
-
// isn't the plugin config (caller turns that into the single warning).
|
|
102
|
-
function patchPluginMcpServers(cfg, binaryPath) {
|
|
103
|
-
if (!cfg || typeof cfg !== "object" || Array.isArray(cfg)) {
|
|
104
|
-
throw new Error("config is not an object");
|
|
105
|
-
}
|
|
106
|
-
const servers = cfg.mcpServers;
|
|
107
|
-
if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
|
|
108
|
-
throw new Error("mcpServers is not an object");
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let changed = false;
|
|
112
|
-
for (const [name, suffix] of Object.entries(PLUGIN_MCP_SERVERS)) {
|
|
113
|
-
const entry = servers[name];
|
|
114
|
-
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
115
|
-
if (!Array.isArray(entry.args) || entry.args.length !== 2 ||
|
|
116
|
-
entry.args[0] !== "mcp" || entry.args[1] !== suffix) continue; // customized args → keep
|
|
117
|
-
if (!isPatchableKcapCommand(entry.command)) continue; // customized command → keep
|
|
118
|
-
if (entry.command === binaryPath) continue; // already current
|
|
119
|
-
entry.command = binaryPath;
|
|
120
|
-
changed = true;
|
|
121
|
-
}
|
|
122
|
-
return changed;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Rewrites the plugin's shipped .mcp.json (a sibling `kcap/` dir of the
|
|
126
|
-
// launcher's `bin/`) so Claude spawns the native binary directly. Validates
|
|
127
|
-
// before writing, writes a sibling temp file, then renames atomically — the
|
|
128
|
-
// original survives any pre-rename failure. Never throws; on failure it emits
|
|
129
|
-
// ONE concise warning and leaves the shipped `"command": "kcap"` in place.
|
|
130
|
-
// `binaryPath` is a test seam; real callers let it resolve.
|
|
131
|
-
function patchPluginMcpConfig(launcherPath, binaryPath) {
|
|
132
|
-
let mcpJsonPath;
|
|
20
|
+
// Runs `kcap refresh` through the given launcher (an absolute path to kcap.js), so the NEW
|
|
21
|
+
// launcher and the NEW binary run it after an upgrade. Never throws and never fails the caller:
|
|
22
|
+
// a failed refresh must never break `npm install` or report `kcap update` as failed. Its stderr
|
|
23
|
+
// (which steps failed, a plugin patch that could not be written) is passed on through `warn`.
|
|
24
|
+
function runRefreshes(launcherPath, warn = console.warn) {
|
|
133
25
|
try {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
try { fs.unlinkSync(tmp); } catch {}
|
|
149
|
-
throw e;
|
|
150
|
-
}
|
|
151
|
-
} catch (e) {
|
|
152
|
-
console.warn(
|
|
153
|
-
`kcap: could not point the Claude plugin MCP entries at the native binary` +
|
|
154
|
-
` (${e && e.message ? e.message : e}); they will keep launching via the node wrapper.`,
|
|
155
|
-
);
|
|
26
|
+
const result = spawnSync(process.execPath, [launcherPath, "refresh"], {
|
|
27
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
28
|
+
encoding: "utf8",
|
|
29
|
+
env: process.env,
|
|
30
|
+
timeout: REFRESH_TIMEOUT_MS,
|
|
31
|
+
killSignal: "SIGKILL",
|
|
32
|
+
windowsHide: true,
|
|
33
|
+
});
|
|
34
|
+
const stderr = (result.stderr || "").trim();
|
|
35
|
+
if (stderr) warn(stderr);
|
|
36
|
+
if (result.status !== 0)
|
|
37
|
+
warn("kcap: some agent integrations were not refreshed; run `kcap refresh` to retry.");
|
|
38
|
+
} catch {
|
|
39
|
+
// Never fail the caller.
|
|
156
40
|
}
|
|
157
41
|
}
|
|
158
42
|
|
|
159
|
-
module.exports = { runRefreshes
|
|
43
|
+
module.exports = { runRefreshes };
|
package/bin/resolve.js
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
// Side-effect-free platform/native-binary resolution
|
|
2
|
-
//
|
|
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.
|
|
1
|
+
// Side-effect-free platform/native-binary resolution for kcap.js (the launcher).
|
|
2
|
+
// Requiring this module has no side effects.
|
|
8
3
|
|
|
9
4
|
const path = require("path");
|
|
10
5
|
const fs = require("fs");
|
package/kcap/.mcp.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"command": "kcap",
|
|
16
16
|
"args": ["mcp", "flows"],
|
|
17
17
|
"cwd": "${CLAUDE_PROJECT_DIR}",
|
|
18
|
-
"description": "Structured AI agent flows — start_review_flow, submit_review_round, get_review_flow_status, close_review_flow (review-specific) plus their generic equivalents start_flow, send_to_participant, get_flow_status, close_flow (any flow-definition catalog id). Launches a SEPARATE hosted participant agent through your daemon and iterates to sign-off; requires `kcap login` and a running daemon with this repo checked out (the tools are inert otherwise). Use only when the user explicitly asks for a review flow / agent flow / to submit for review — for an ordinary 'review my PR' or 'code review' request, review directly and do not call these tools."
|
|
18
|
+
"description": "Structured AI agent flows — start_review_flow, submit_review_round, get_review_flow_status, close_review_flow (review-specific) plus their generic equivalents start_flow, send_to_participant, get_flow_status, close_flow (any flow-definition catalog id). Launches a SEPARATE hosted participant agent through your daemon and iterates to sign-off; requires `kcap login` and a running daemon with this repo checked out (the tools are inert otherwise). Use the flow tools only when the user explicitly asks for a review flow / agent flow / to submit for review — for an ordinary 'review my PR' or 'code review' request, review directly and do not call these tools. Also list_start_agent_options and start_agent: when the user asks to start a separate hosted agent that works on its own, use these — not your harness's own subagent tool, a flow, or the `kcap agent start` CLI."
|
|
19
19
|
},
|
|
20
20
|
"kcap-memory": {
|
|
21
21
|
"command": "kcap",
|
package/kcap/README.md
CHANGED
|
@@ -20,6 +20,7 @@ Search and recall past Kurrent Capacitor sessions from inside the agent.
|
|
|
20
20
|
| `get_session_transcript` | Speaker-tagged transcript window, with `around_event` drill-in for search hits |
|
|
21
21
|
| `list_repo_plans` | List a repository's declared plans you can see, most recently touched first |
|
|
22
22
|
| `get_declared_plans` | A plan's documents and full task list, by `plan_id` or `session_id` |
|
|
23
|
+
| `get_session_evals` | Eval state and scores for up to 25 sessions by id; works on every plan |
|
|
23
24
|
|
|
24
25
|
Repo-aware: it resolves the cwd to a repo hash at startup, so `search_sessions` defaults to *this* repo.
|
|
25
26
|
|
package/kcap/hooks/hooks.json
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-flows
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
work directly instead.
|
|
4
|
+
Use this skill to drive a structured agent *flow*: a separate hosted
|
|
5
|
+
participant agent runs a definition from the server's flow catalogue and
|
|
6
|
+
iterates with you until sign-off. Use it when the user names a flow or
|
|
7
|
+
definition id ("run the code-review flow", "start a flow", "use flow
|
|
8
|
+
definition X"), when the user accepts a flow you offered, or when you are
|
|
9
|
+
about to offer one listed under "Flows you may offer" in your session
|
|
10
|
+
context because its when-to-use applies. Before starting a flow, call
|
|
11
|
+
get_flow_definition and follow its guide. Do NOT use this skill (and do NOT
|
|
12
|
+
call the flows MCP tools) for an ordinary request such as "review my PR",
|
|
13
|
+
"do X for me", or "check this over" where the user wants you to do the work
|
|
14
|
+
yourself — do it directly instead. To start a hosted agent that works on its
|
|
15
|
+
own, use `start-agents`.
|
|
17
16
|
---
|
|
18
17
|
|
|
19
18
|
# Agent Flows
|
|
20
19
|
|
|
21
|
-
Use the `kcap mcp flows` MCP tools (`list_flow_definitions`, `start_flow`, `send_to_participant`, `get_flow_status`, `close_flow`) to run a structured agent **flow**: your work is handed to a **separate, hosted participant agent** driven by a flow definition from the server's catalog, which returns a result (kind `findings` with the participant's result text, or `clean`); you address a `findings` result and keep iterating until the clean signal. This is a deliberate, heavier workflow — use it
|
|
20
|
+
Use the `kcap mcp flows` MCP tools (`list_flow_definitions`, `get_flow_definition`, `start_flow`, `send_to_participant`, `get_flow_status`, `close_flow`) to run a structured agent **flow**: your work is handed to a **separate, hosted participant agent** driven by a flow definition from the server's catalog, which returns a result (kind `findings` with the participant's result text, or `clean`); you address a `findings` result and keep iterating until the clean signal. This is a deliberate, heavier workflow — use it when the user asks for a flow or accepts one you offered, never on your own initiative.
|
|
22
21
|
|
|
23
22
|
## Long rounds are normal
|
|
24
23
|
|
|
@@ -38,15 +37,14 @@ and end the reviewer turn. The hosted-reviewer contract wins over driver-looking
|
|
|
38
37
|
|
|
39
38
|
These tools do **not** perform the work themselves — they hand it off to a separate hosted participant agent running a named flow definition. If the user simply asked *you* to do something in a normal session — e.g. "review my PR", "review this diff", "check this spec", "do X" — just do it yourself and report the result directly. Do **NOT** call `start_flow` / `send_to_participant` for an ordinary request; that would spin up a hosted agent the user did not ask for.
|
|
40
39
|
|
|
41
|
-
Only start a flow when the user explicitly asks for
|
|
40
|
+
Only start a flow when the user explicitly asks for one — e.g. "start a flow", "run the code-review flow", "use flow definition X", or "re-review after I address the findings" via a flow — or accepts a flow you offered. Offer a flow only when your session context lists it under **Flows you may offer** and its when-to-use applies to what just happened; ask, and never start it before the user says yes. Skip the offer when the user asked you to do the work yourself, or while you are mid-task.
|
|
42
41
|
|
|
43
42
|
## Choosing the flow definition
|
|
44
43
|
|
|
45
|
-
Once the user has
|
|
44
|
+
Once the user has asked for a flow or accepted one you offered (see above), pick the `definition_id`:
|
|
46
45
|
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
- Anything else → the definition id the user named, or one from `list_flow_definitions` (read-only), which lists every definition this server can start — operator-published ones included — with its version, description, participant roles and their authored vendor and model, and whether it is single- or multi-participant. Call it whenever the user has not named a definition, or named one you have not seen listed: a definition it does not list is disabled, deleted or unknown, and `start_flow` will refuse it. If several fit, ask the user rather than guessing. A server that answers that it cannot list definitions only predates the tool — the two built-ins and any id the user names still work.
|
|
46
|
+
- The flow the user named, or the one you offered and they accepted.
|
|
47
|
+
- If the user has not named one → choose from `list_flow_definitions` (read-only), which lists every definition this server can start — operator-published ones included — with its version, description, participant roles and their authored vendor and model, and whether it is single- or multi-participant. Call it whenever the user has not named a definition, or named one you have not seen listed: a definition it does not list is disabled, deleted or unknown, and `start_flow` will refuse it. If several fit, ask the user rather than guessing. A server that answers that it cannot list definitions only predates the tool — the two built-ins and any id the user names still work.
|
|
50
48
|
|
|
51
49
|
For the reserved `spec-review` and `code-review` aliases, reviewer-vendor language is role-bound:
|
|
52
50
|
pass the one vendor explicitly named as the reviewer, ignore driver-harness mentions, honor
|
|
@@ -87,6 +85,10 @@ vendor supports this: the daemon must advertise a runtime model resolver for the
|
|
|
87
85
|
(Claude and Codex today; other vendors keep vendor-only overrides with no model choice) or the
|
|
88
86
|
server rejects the override outright.
|
|
89
87
|
|
|
88
|
+
## Read the flow's guide first
|
|
89
|
+
|
|
90
|
+
Before a catalogue start (`definition_id`), call `get_flow_definition(definition_id)`. The guide is written by whoever published the flow: what to put in `context`, which target to name, how to iterate on its results and when to close. Where it differs from the generic rules below, follow the guide. A server that does not publish guides says so; then work from the definition's description and the rules below. A flow started with an inline `definition_yaml` has no catalogue id and no guide: drive it by the generic rules and its own YAML.
|
|
91
|
+
|
|
90
92
|
## Composing a dynamic flow
|
|
91
93
|
|
|
92
94
|
If nothing `list_flow_definitions` shows fits — no `definition_id` covers the roles or workflow you need — compose one inline instead: pass `definition_yaml` to `start_flow` in place of `definition_id`. Provide exactly one of the two, never both. (`start_review_flow` / `submit_review_round` stay catalog-only — this only applies to the generic `start_flow`.)
|
|
@@ -146,7 +148,7 @@ After applying the role-surface safety gate, if `start_flow` / `send_to_particip
|
|
|
146
148
|
5. **If participant output is unclear or requires user input**, pause and ask the user before proceeding.
|
|
147
149
|
6. **Never start a nested flow.** If you are the hosted participant (see above), do not call these tools yourself.
|
|
148
150
|
7. **Address each role independently.** A flow definition declares one or more participant roles in its `participants` map (single-participant definitions use `reviewer`). A multi-participant `start_flow` returns no round — nothing has launched yet. Call `send_to_participant(flow_run_id, participant=<role>, message=…)` naming the role you want to address; its first message launches that role's agent lazily. Only one round is in flight per role at a time — sending to a role that's still working on a round gets a `409` naming the busy round — but every OTHER role stays addressable in the meantime. Sending an unknown role is rejected by the server, which names the valid roles in its error.
|
|
149
|
-
8. **
|
|
151
|
+
8. **Ask the participant only for what the flow's guide allows.** If the guide says CI covers tests, do not ask the participant to run them; participant feedback is on what the flow exists to judge.
|
|
150
152
|
9. **State where your changes live.** The participant's worktree is mirrored from **this session's project directory**, not from the directory you are working in, and no tool parameter can redirect it. So if you changed directory, are a subagent in another checkout, or the changeset lives in another worktree/repo/machine, the participant will NOT see it: say so in `context`/`message`, give it an explicit commit range (never `git diff origin/main...HEAD`), and inline the diffs — or pass `mode: "context-only"` to make your context the sole source of truth. The participant flags referenced changes it cannot find; incomplete context wastes a full round.
|
|
151
153
|
|
|
152
154
|
## Pending messages
|
|
@@ -169,10 +171,17 @@ The server enforces per-run budgets; watch for these in tool error responses:
|
|
|
169
171
|
|
|
170
172
|
## Workflow
|
|
171
173
|
|
|
174
|
+
A catalogue flow (`definition_id`) starts with its guide; an inline `definition_yaml` flow skips this step:
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
get_flow_definition(definition_id)
|
|
178
|
+
→ read the driver guide; prepare the context it asks for
|
|
179
|
+
```
|
|
180
|
+
|
|
172
181
|
Single-participant definitions start eagerly — round 1 runs as part of `start_flow`:
|
|
173
182
|
|
|
174
183
|
```
|
|
175
|
-
start_flow(definition_id, target_kind, target_ref, target_title, context)
|
|
184
|
+
start_flow(definition_id, target_kind, target_ref, target_title, session_title, context)
|
|
176
185
|
→ participant returns a result: kind findings (with the result text) | kind clean
|
|
177
186
|
|
|
178
187
|
if clean:
|
|
@@ -191,7 +200,7 @@ if findings:
|
|
|
191
200
|
Multi-participant definitions start round-less — you address each role yourself, and the run is clean only in aggregate:
|
|
192
201
|
|
|
193
202
|
```
|
|
194
|
-
start_flow(definition_id, target_kind, target_ref, target_title, context)
|
|
203
|
+
start_flow(definition_id, target_kind, target_ref, target_title, session_title, context)
|
|
195
204
|
→ no round yet — roles have not launched
|
|
196
205
|
|
|
197
206
|
send_to_participant(flow_run_id, participant="reviewer", message=…)
|
|
@@ -217,7 +226,8 @@ report completion to user
|
|
|
217
226
|
| Tool | Required args | Optional args | When to call |
|
|
218
227
|
|---|---|---|---|
|
|
219
228
|
| `list_flow_definitions` | — | — | Before `start_flow`, whenever the user has not named a definition or named one you have not seen listed. Read-only: returns each runnable definition's id, version, description, whether it is single- or multi-participant, and its participants' role, authored vendor and model. A `server_catching_up` error is retryable — do not read it as an empty catalog. |
|
|
220
|
-
| `
|
|
229
|
+
| `get_flow_definition` | `definition_id` | — | Before every catalogue (`definition_id`) `start_flow`. Read-only: returns the definition's participants and when to use it, then its authored driver guide (what to submit, how to iterate, when to close). An unknown, disabled or deleted id is an error; an older server reports that it publishes no guides. |
|
|
230
|
+
| `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), `session_title` (the participant session's title: a short phrase naming this piece of work, specific enough to tell it apart from other sessions — it replaces the definition's generic opening instruction as the name), `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. |
|
|
221
231
|
| `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. |
|
|
222
232
|
| `get_flow_status` | — | `flow_run_id` (omit to read the newest open flow this session started, or on a harness without a session identity the newest one started from this workspace; several open flows are listed instead), `session_id` (look up another session's flows; defaults to this session), `wait` (`true`/`false`, defaults to `false`) — when `true`, blocks until the round is terminal or roughly 3.5 minutes pass, instead of returning the current snapshot immediately | Poll or check the current status of a flow run (running, waiting, completed, failed). Use `wait: true` to ride out a long round instead of polling repeatedly yourself, and omit `flow_run_id` to recover a flow whose id you never received or lost. |
|
|
223
233
|
| `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. |
|
|
@@ -225,13 +235,14 @@ report completion to user
|
|
|
225
235
|
## Example (custom definition)
|
|
226
236
|
|
|
227
237
|
```
|
|
228
|
-
# Step 1 — start (all
|
|
238
|
+
# Step 1 — start (all six args required; the participant sees a mirror of THIS SESSION's
|
|
229
239
|
# project directory, not of the directory you are working in — pass mode="context-only" to opt out)
|
|
230
240
|
start_flow(
|
|
231
241
|
definition_id="code-review",
|
|
232
242
|
target_kind="branch",
|
|
233
243
|
target_ref="feature/add-null-check",
|
|
234
244
|
target_title="Add null check on user input",
|
|
245
|
+
session_title="Review the null check on user input",
|
|
235
246
|
context="Review the diff on this branch for correctness and adherence to project conventions."
|
|
236
247
|
)
|
|
237
248
|
# → returns flow_run_id, e.g. "flow_abc123"
|
|
@@ -260,6 +271,7 @@ start_flow(
|
|
|
260
271
|
target_kind="branch",
|
|
261
272
|
target_ref="feature/add-null-check",
|
|
262
273
|
target_title="Add null check on user input",
|
|
274
|
+
session_title="Review and test the null check on user input",
|
|
263
275
|
context="Review the diff on this branch and write/run tests for the new code path."
|
|
264
276
|
)
|
|
265
277
|
# → returns flow_run_id, e.g. "flow_xyz789"; no round in the response
|
|
@@ -4,38 +4,31 @@ description: >-
|
|
|
4
4
|
Follow a kcap import that setup just started and the evals landing on it —
|
|
5
5
|
"Follow my kcap import" (the prompt `kcap setup` hands to your agent), "watch my
|
|
6
6
|
import", "how is my import going", "are my evals done yet". Reads the handoff file
|
|
7
|
-
setup wrote, polls
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
skill.
|
|
7
|
+
setup wrote, polls the eval state of exactly the sessions that import created,
|
|
8
|
+
waits for the sessions that imported while the user watched to be evaluated,
|
|
9
|
+
summarizes their evals, links to the results and offers the guided tour. Works on
|
|
10
|
+
every plan. Not for browsing evals in general — that is the guided-tour skill.
|
|
12
11
|
---
|
|
13
12
|
|
|
14
13
|
# Eval watch
|
|
15
14
|
|
|
16
|
-
You follow ONE import: the sessions listed in a handoff file `kcap setup` wrote. Every
|
|
17
|
-
|
|
18
|
-
an
|
|
19
|
-
|
|
15
|
+
You follow ONE import: the sessions listed in a handoff file `kcap setup` wrote. Every lookup you
|
|
16
|
+
make names only those sessions — never a repo-wide or tenant-wide read. If a response ever carries
|
|
17
|
+
an entry for a session id outside the cohort, discard it: never count it, link it, or mention it.
|
|
18
|
+
|
|
19
|
+
Eval state comes from `get_session_evals` in the `kcap-sessions` MCP — never from the
|
|
20
|
+
`kcap-analytics` MCP, which is a paid feature the workspace may not have.
|
|
20
21
|
|
|
21
22
|
## The safety rule — read this first
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
Two grammars gate everything below:
|
|
24
25
|
- **Run id** (a `(run: <id>)` token, and the file's own `run_id`): `^[0-9a-f]{32}$`.
|
|
25
|
-
- **Session id** (`session_ids`, `foreground_succeeded_ids`, and any id you
|
|
26
|
-
`^[A-Za-z0-9_-]{1,128}$`.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
The `kcap-analytics` MCP takes raw SQL text with no parameter binding, so the session-id grammar is
|
|
32
|
-
the SQL-safety boundary, not just a format check. The class excludes quote, backslash, whitespace
|
|
33
|
-
and `;`, so a value that matches it can never close a string literal or open a new statement — a
|
|
34
|
-
matching id is emitted as a single-quoted literal (`'<id>'`) with **no escaping**, because none is
|
|
35
|
-
needed and none should be attempted. A run of hyphens such as `--` matches the grammar and is safe
|
|
36
|
-
to emit this way: inside a quoted literal it is data, not a SQL comment. An id that fails either
|
|
37
|
-
grammar is **never** placed in SQL, a path, or a link — reject it and move on (section 2 below says
|
|
38
|
-
what each layer's rejection does); never sanitize or escape an id into something that would pass.
|
|
26
|
+
- **Session id** (`session_ids`, `foreground_succeeded_ids`, and any id you pass to a tool or put
|
|
27
|
+
in a link): `^[A-Za-z0-9_-]{1,128}$`.
|
|
28
|
+
|
|
29
|
+
An id that fails its grammar is **never** placed in a tool call, a path, or a link — reject it and
|
|
30
|
+
move on (section 2 below says what each layer's rejection does); never sanitize or escape an id
|
|
31
|
+
into something that would pass.
|
|
39
32
|
|
|
40
33
|
## 1. Find the run
|
|
41
34
|
|
|
@@ -44,12 +37,12 @@ what each layer's rejection does); never sanitize or escape an id into something
|
|
|
44
37
|
it does match, the run is bound: read ONLY `<config>/import-handoff-<id>.json`, where `<config>`
|
|
45
38
|
is `$KCAP_CONFIG_DIR` when set, else `~/.config/kcap`, and check it against every Layer A rule in
|
|
46
39
|
section 2, plus one more: its `run_id` field must equal `<id>` exactly. Missing, unreadable, or
|
|
47
|
-
failing any of those checks → say so and CLOSE (section 7) with no
|
|
40
|
+
failing any of those checks → say so and CLOSE (section 7) with no lookup. **Never fall through to
|
|
48
41
|
another run's file** — a different run's cohort does not belong to the run the user asked for.
|
|
49
42
|
- Otherwise list `<config>/import-handoff-*.json`, keep the locator-valid ones (section 2) that are
|
|
50
|
-
watchable (`handoff_offered` true, or `handoff_suppressed` is `
|
|
51
|
-
`no_agent_detected`), pick the newest `written_at`, and say which others you passed over.
|
|
52
|
-
- Nothing qualifies → say you found no import to follow and CLOSE with no
|
|
43
|
+
watchable (`handoff_offered` true, or `handoff_suppressed` is `analytics_not_in_plan`,
|
|
44
|
+
`skill_not_installed` or `no_agent_detected`), pick the newest `written_at`, and say which others you passed over.
|
|
45
|
+
- Nothing qualifies → say you found no import to follow and CLOSE with no lookup.
|
|
53
46
|
|
|
54
47
|
## 2. Validate the file — three layers
|
|
55
48
|
|
|
@@ -57,24 +50,25 @@ A failure at a lower layer never re-opens the file for a higher one.
|
|
|
57
50
|
|
|
58
51
|
**Layer A** (may this file be selected at all): JSON parses; `schema_version` is 1; `run_id` matches
|
|
59
52
|
`^[0-9a-f]{32}$`; `written_at` parses as ISO-8601 and is within the last 24 hours; `handoff_offered`
|
|
60
|
-
is a boolean. Fail → not selectable; try the next candidate file, or close with no
|
|
53
|
+
is a boolean. Fail → not selectable; try the next candidate file, or close with no lookup if none
|
|
61
54
|
remain.
|
|
62
55
|
|
|
63
56
|
**Layer B** (may its ids drive data): `cohort` ∈ {exact, partial_exact, unknown}; `background` ∈
|
|
64
57
|
{not_needed, running, exited_zero, failed}; `foreground_certainty` ∈ {complete, incomplete};
|
|
65
58
|
`handoff_suppressed` is null or one of import_failed, no_new_sessions, nothing_landed,
|
|
66
|
-
analytics_not_in_plan, skill_not_installed, no_agent_detected
|
|
59
|
+
analytics_not_in_plan, skill_not_installed, no_agent_detected (older setups write
|
|
60
|
+
`analytics_not_in_plan`); every entry of `session_ids` and
|
|
67
61
|
`foreground_succeeded_ids` matches `^[A-Za-z0-9_-]{1,128}$`; `unattributed_on_disk` is a
|
|
68
62
|
non-negative integer. Fail → **no data**: the file stays selected, but say the record is unreadable
|
|
69
|
-
and CLOSE with links only (section 7), no
|
|
63
|
+
and CLOSE with links only (section 7), no lookup.
|
|
70
64
|
|
|
71
65
|
**Layer C** (may it supply links): `server_url` starts with `http://` or `https://`. Fail → no
|
|
72
|
-
file-sourced links (fall back to `kcap whoami` per section 7) and no
|
|
66
|
+
file-sourced links (fall back to `kcap whoami` per section 7) and no lookup — an unverifiable
|
|
73
67
|
`server_url` also means the server-binding check in section 4 cannot run. `background_log` and
|
|
74
68
|
`profile` are shown as plain text — never as a link or a command to run — only when they contain no
|
|
75
69
|
control characters and are under 512 characters; otherwise omit them.
|
|
76
70
|
|
|
77
|
-
Never splice an unvalidated value into
|
|
71
|
+
Never splice an unvalidated value into a tool call, a path, or a link.
|
|
78
72
|
|
|
79
73
|
## 3. No-handoff files
|
|
80
74
|
|
|
@@ -82,144 +76,113 @@ If `handoff_offered` is false, branch on `handoff_suppressed` and CLOSE:
|
|
|
82
76
|
- `no_new_sessions` → "nothing to watch — that import found no new sessions".
|
|
83
77
|
- `nothing_landed` → "the sessions that import selected were skipped at import time"; point at
|
|
84
78
|
`kcap import --all` for per-session reasons; no retry.
|
|
85
|
-
- `analytics_not_in_plan` → the plan sentence (section 6); the import ran; no retry.
|
|
86
79
|
- `import_failed` → "that import did not get running"; name `kcap import --all --yes` and the
|
|
87
80
|
`background_log` when displayable.
|
|
88
|
-
- `skill_not_installed` / `no_agent_detected` → the import ran and you
|
|
89
|
-
now: continue as if offered, watching the file's cohort as usual (sections 4–5).
|
|
81
|
+
- `analytics_not_in_plan` / `skill_not_installed` / `no_agent_detected` → the import ran and you
|
|
82
|
+
can follow it now: continue as if offered, watching the file's cohort as usual (sections 4–5).
|
|
90
83
|
|
|
91
84
|
## 4. Bind to the server — fail closed
|
|
92
85
|
|
|
93
86
|
If the selected file's `cohort` is `unknown`, skip this check and go straight to section 5 — there
|
|
94
|
-
is no cohort to
|
|
87
|
+
is no cohort to look up either way, and the mismatch remediation below would be misleading when
|
|
95
88
|
watching was never possible.
|
|
96
89
|
|
|
97
90
|
Otherwise, run `kcap whoami` and compare its server URL to `server_url`: lowercase scheme and host,
|
|
98
91
|
drop a default port (80 for http, 443 for https only), trim a trailing slash, compare the path
|
|
99
|
-
as-is. Match → continue to section 5. Mismatch or `whoami` failure →
|
|
92
|
+
as-is. Match → continue to section 5. Mismatch or `whoami` failure → make **NO** eval lookup.
|
|
100
93
|
CLOSE with the file's links and this remediation: start your agent from a shell where `kcap whoami`
|
|
101
94
|
reports `<server_url>` — set `KCAP_PROFILE=<profile>`, unset `KCAP_URL`, and set `KCAP_CONFIG_DIR`
|
|
102
95
|
if kcap uses a custom config directory — then prompt again.
|
|
103
96
|
|
|
104
97
|
## 5. Watch the cohort
|
|
105
98
|
|
|
106
|
-
Cohort = `session_ids` (`cohort: unknown` or empty → CLOSE with links, no
|
|
107
|
-
the entries of `foreground_succeeded_ids` that are also in `session_ids
|
|
108
|
-
imported while the user watched setup, and the ones this watch waits on.
|
|
109
|
-
count. A foreground entry missing from `session_ids` is never
|
|
110
|
-
"M of the sessions that imported first are outside the 500 this
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
most
|
|
99
|
+
Cohort = `session_ids` (`cohort: unknown` or empty → CLOSE with links, no lookup); N is its size.
|
|
100
|
+
Foreground = the entries of `foreground_succeeded_ids` that are also in `session_ids`, in file
|
|
101
|
+
order: the sessions that imported while the user watched setup, and the ones this watch waits on.
|
|
102
|
+
K is the foreground count. A foreground entry missing from `session_ids` is never looked up; when
|
|
103
|
+
any are missing, say "M of the sessions that imported first are outside the 500 this import
|
|
104
|
+
recorded".
|
|
105
|
+
|
|
106
|
+
**Watched set** W, at most 25 sessions: the first 25 foreground sessions, then — only while fewer
|
|
107
|
+
than 25 — the other cohort sessions in file order. Open with: "Watching W of the N sessions from
|
|
108
|
+
this import; waiting for the K that imported first to be evaluated". When K > 25 add "the first 25
|
|
109
|
+
of them"; for `partial_exact` add "the sessions that imported first and the most recent others,
|
|
110
|
+
500 at most; older ones may land and evaluate unobserved"; if `unattributed_on_disk` > 0 add the
|
|
114
111
|
sentence from section 7.
|
|
115
112
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
poll — nothing from it commits — and counts as one failure toward the two-failure stop rule.
|
|
140
|
-
|
|
141
|
-
A 429 fails the poll. If its text matches `retry after (\d+)s`, wait that many seconds before the
|
|
142
|
-
next poll; otherwise wait 60 seconds. Never poll sooner than the 30-second cadence either way. HTTP
|
|
143
|
-
403 with `analytics_not_in_plan` → CLOSE immediately with the plan sentence (section 6); no
|
|
144
|
-
polling, no retry, no wait.
|
|
145
|
-
|
|
146
|
-
Progress = cohort ids that arrived / cohort size, and foreground ids evaluated / K, both computed
|
|
147
|
-
from the batch rows only — never a separate count, never repo- or tenant-wide. Cadence: first
|
|
148
|
-
snapshot immediately, then every 30 seconds. Say the progress after each poll.
|
|
149
|
-
|
|
150
|
-
**Baseline**: the first snapshot's rows. An eval present there is *pre-existing*; one whose
|
|
151
|
-
`eval_run_id` was null or absent there and non-null in a later poll *completed during this watch*.
|
|
152
|
-
Every summary labels each session with one of those two phrases.
|
|
113
|
+
**One poll** = ONE `get_session_evals` call with `session_ids` set to W — never two in flight. Each
|
|
114
|
+
entry's `state` is one of:
|
|
115
|
+
- `not_found` — not ingested yet (or not visible to you);
|
|
116
|
+
- `not_evaluated` — arrived, no eval yet;
|
|
117
|
+
- `queued` — arrived, eval waiting for a worker or a retry (`queue_position`, `next_attempt_at`);
|
|
118
|
+
- `running` — arrived, eval in progress (`questions_done` of `total_questions`);
|
|
119
|
+
- `completed` — arrived and evaluated: `eval_run_id`, `evaluated_at`, `overall_score` (out of 5),
|
|
120
|
+
`judge_model`, `summary`, `categories`, `weakest_questions`;
|
|
121
|
+
- `failed` — arrived, the eval run failed (`failure_reason`);
|
|
122
|
+
- `error` — this lookup failed.
|
|
123
|
+
|
|
124
|
+
Arrived = any state but `not_found` and `error`. A tool error (including a login prompt), or any
|
|
125
|
+
`error` entry, fails the poll: nothing from it commits, and it counts toward the two-failure stop
|
|
126
|
+
rule. If the tool is missing — no `kcap-sessions` MCP, or one without `get_session_evals` — this
|
|
127
|
+
kcap is older than the skill: say to update kcap and restart the agent, then CLOSE.
|
|
128
|
+
|
|
129
|
+
Progress = watched sessions arrived / W and foreground sessions evaluated / min(K, 25), from the
|
|
130
|
+
poll's entries only. Cadence: first snapshot immediately, then every 30 seconds. Say the progress
|
|
131
|
+
after each poll.
|
|
132
|
+
|
|
133
|
+
**Baseline**: the first snapshot. A session `completed` there is *pre-existing*; one that was not
|
|
134
|
+
`completed` there, or completed with a different `eval_run_id`, and is `completed` in a later poll
|
|
135
|
+
*completed during this watch*. Every summary labels each session with one of those two phrases.
|
|
153
136
|
|
|
154
137
|
**Stop**, evaluated in this order after each poll whose results have already committed:
|
|
155
|
-
1. K > 0 and every foreground session
|
|
138
|
+
1. K > 0 and every watched foreground session is `completed` → summarize all of them, ordered by
|
|
156
139
|
`evaluated_at` then `session_id`. A pre-existing eval counts: the wait is for these sessions to
|
|
157
140
|
be evaluated, whenever that happened.
|
|
158
|
-
2. K = 0 and three
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
3. `cohort: exact`,
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
Never fires for `partial_exact` or an empty cohort.
|
|
141
|
+
2. K = 0 and three watched sessions completed during this watch → summarize those three, ordered by
|
|
142
|
+
`evaluated_at` then `session_id`. Pre-existing evals never satisfy this rule: on a re-import they
|
|
143
|
+
belong to an earlier run, and stopping on them would end the watch before this import produced
|
|
144
|
+
anything.
|
|
145
|
+
3. `cohort: exact`, N ≤ 25, and every cohort session is `completed` → summarize the foreground
|
|
146
|
+
sessions, or with K = 0 the three with the newest `evaluated_at` (ties by `session_id`). This
|
|
147
|
+
rule may fire on the first snapshot with nothing but pre-existing evals: a cohort that is
|
|
148
|
+
already fully evaluated has nothing left to wait for, and the labels say so.
|
|
167
149
|
4. Two consecutive failed polls → stop, reporting the failures.
|
|
168
150
|
5. 10 minutes since the first snapshot → stop. No new poll starts after the deadline, but a poll
|
|
169
151
|
already dispatched before it finishes normally, and its outcome is still checked against rules
|
|
170
152
|
1–4 first. On a deadline stop, summarize the foreground sessions that did complete and name the
|
|
171
|
-
ones still pending, with
|
|
172
|
-
|
|
153
|
+
ones still pending, with their state; if none of them completed, summarize instead up to three
|
|
154
|
+
watched sessions with the newest `evaluated_at` (ties by `session_id`).
|
|
173
155
|
|
|
174
156
|
No idle early-stop — quiet polls are normal and are not a reason to stop early. Evals take minutes
|
|
175
157
|
per session, and the foreground sessions are the newest, so they are usually the last to complete.
|
|
176
158
|
|
|
177
|
-
**
|
|
178
|
-
the
|
|
179
|
-
|
|
180
|
-
`
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
Strongest = highest mean, weakest = lowest, ties alphabetical by category. A truncated or failed
|
|
191
|
-
detail query, or a session with no assessed rows, → summarize that session by `overall_score` alone
|
|
192
|
-
and say so; this never affects poll success or the stop rules above.
|
|
193
|
-
|
|
194
|
-
**What a detailed session summary says**, one short paragraph each: the link (section 7), the
|
|
195
|
-
baseline label, then vendor and model, length (`duration_min`, rounded, and `event_count`),
|
|
196
|
-
`overall_score` out of 5 and the judge model, strongest and weakest category with their means, and
|
|
197
|
-
the two weakest questions with their scores. When the `kcap-sessions` MCP is available, call `get_session_summary` once per
|
|
198
|
-
summarized session and lead with its title or first sentence when it returns one; an empty summary
|
|
199
|
-
is left out silently, never called "no summary".
|
|
200
|
-
|
|
201
|
-
**Cohort facts**, one line after the summaries, from the last committed poll's rows only: sessions
|
|
202
|
-
arrived out of N, sessions evaluated, and the mean `overall_score` across the evaluated ones.
|
|
159
|
+
**What a session summary says.** The first five sessions in summary order get one short paragraph
|
|
160
|
+
each: the link (section 7), the baseline label, `overall_score` out of 5 and the judge model, the
|
|
161
|
+
strongest and weakest of `categories` by `score` (ties alphabetical by name), the two
|
|
162
|
+
`weakest_questions` with their scores, and the gist of the judge's `summary`. When
|
|
163
|
+
`get_session_summary` returns a title or a first sentence for the session, lead with it; an empty
|
|
164
|
+
summary is left out silently, never called "no summary". Every later session gets a one-line entry
|
|
165
|
+
— link, label and `overall_score`. A completed entry with no categories is summarized by
|
|
166
|
+
`overall_score` alone; say so.
|
|
167
|
+
|
|
168
|
+
**Cohort facts**, one line after the summaries, from the last committed poll only: watched
|
|
169
|
+
sessions arrived out of W, sessions evaluated, and the mean `overall_score` across the evaluated
|
|
170
|
+
ones.
|
|
203
171
|
|
|
204
172
|
## 6. When little or nothing completes
|
|
205
173
|
|
|
206
174
|
Explain the real gates plainly: auto-eval may be off for a repository; the server needs an eval
|
|
207
175
|
agent configured; sessions under the minimum event count are skipped; already-evaluated sessions
|
|
208
|
-
are not re-run; a recovery sweep runs hourly.
|
|
209
|
-
immediately with the block below.
|
|
210
|
-
|
|
211
|
-
Plan sentence (used here and from sections 3 and 5): "Insights isn't in this workspace's plan, so
|
|
212
|
-
evals can't be followed from here; your import continues and evals appear in the Capacitor UI."
|
|
176
|
+
are not re-run; a recovery sweep runs hourly. A `failed` session names its `failure_reason`.
|
|
213
177
|
|
|
214
178
|
## 7. CLOSE — always
|
|
215
179
|
|
|
216
180
|
1. How to keep watching: prompt `Follow my kcap import` again (with the same `(run: <id>)` line
|
|
217
181
|
when you were bound to one).
|
|
218
|
-
2. Links:
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
once logged in.
|
|
182
|
+
2. Links: `<server_url>/sessions/<session_id>?tab=evaluation` per session; all results
|
|
183
|
+
`<server_url>/sessions`. No valid file → `server_url` from `kcap whoami`; if that fails too, say
|
|
184
|
+
the results live in the Capacitor server UI and that `kcap whoami` prints the URL once logged
|
|
185
|
+
in.
|
|
223
186
|
3. When `unattributed_on_disk` > 0: "N sessions on disk had no repository match; any of them that
|
|
224
187
|
imported show without one — `kcap remap` places them."
|
|
225
188
|
4. Offer the guided tour with the exact prompt `Start kcap guided tour`.
|
|
@@ -34,9 +34,16 @@ through the `kcap-plans` MCP tools; nothing infers it. Three rules:
|
|
|
34
34
|
While a plan's `is_complete` is `false`, never call `set_plan_tasks`
|
|
35
35
|
on it for any reason — the list would be rebuilt from a view that is
|
|
36
36
|
missing tasks.
|
|
37
|
-
3. **Keep whatever ledger your own workflow asks for as well
|
|
38
|
-
replace the harness's task list, not your notes or
|
|
39
|
-
workflow tells you to maintain
|
|
37
|
+
3. **Keep whatever ledger your own workflow asks for as well, and move both
|
|
38
|
+
together.** These tools replace the harness's task list, not your notes or
|
|
39
|
+
any file another workflow tells you to maintain — a subagent-driven
|
|
40
|
+
development `progress.md`, an executing-plans checklist. Pair every write to
|
|
41
|
+
that ledger with an `update_plan_task` in the same turn: `in_progress` when
|
|
42
|
+
you start or dispatch a task, `completed` when it passes its review rather
|
|
43
|
+
than when the work first comes back. The user watches the Capacitor ledger,
|
|
44
|
+
and a task finished only in your own file still reads as `pending` there.
|
|
45
|
+
When subagents do the tasks, the coordinating session makes these calls — a
|
|
46
|
+
subagent's own session is not on the plan.
|
|
40
47
|
|
|
41
48
|
## Resuming a plan
|
|
42
49
|
|
|
@@ -8,7 +8,8 @@ description: >-
|
|
|
8
8
|
this skill (and do NOT call the flows MCP tools) for an ordinary review
|
|
9
9
|
request such as "review my PR", "review this diff/spec/design", or "code
|
|
10
10
|
review" where the user just wants you to review it yourself — perform that
|
|
11
|
-
review directly instead.
|
|
11
|
+
review directly instead. For any other catalogue flow, or a flow offered
|
|
12
|
+
from your session context, use `agent-flows`.
|
|
12
13
|
---
|
|
13
14
|
|
|
14
15
|
# Review Flows
|
|
@@ -156,7 +157,10 @@ After applying the role-surface safety gate, if `start_review_flow` / `submit_re
|
|
|
156
157
|
## Workflow
|
|
157
158
|
|
|
158
159
|
```
|
|
159
|
-
|
|
160
|
+
get_flow_definition(kind)
|
|
161
|
+
→ follow its guide: what to submit, how to iterate (a server that publishes no guides says so; the rest of this skill applies)
|
|
162
|
+
|
|
163
|
+
start_review_flow(kind, target_kind, target_ref, target_title, session_title, context)
|
|
160
164
|
→ reviewer returns a result: findings (with the findings text) | clean
|
|
161
165
|
|
|
162
166
|
if clean:
|
|
@@ -176,7 +180,7 @@ if findings:
|
|
|
176
180
|
|
|
177
181
|
| Tool | Required args | Optional args | When to call |
|
|
178
182
|
|---|---|---|---|
|
|
179
|
-
| `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. |
|
|
183
|
+
| `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), `session_title` (the reviewer session's title: a short phrase naming this review, specific enough to tell it apart from other sessions — it replaces the generic "Review this PR/code" name), `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. |
|
|
180
184
|
| `submit_review_round` | `flow_run_id`, `context` | `instructions` | After addressing findings. Pass the same `flow_run_id` and the updated context. |
|
|
181
185
|
| `get_review_flow_status` | — | `flow_run_id` (omit to read the newest open flow this session started, or on a harness without a session identity the newest one started from this workspace; several open flows are listed instead), `session_id` (look up another session's flows; defaults to this session), `wait` (`true`/`false`, defaults to `false`) — when `true`, blocks until the round is terminal or roughly 3.5 minutes pass, instead of returning the current snapshot immediately | Poll or check the current status of a flow (running, waiting, completed, failed). Use `wait: true` to ride out a long round instead of polling repeatedly yourself, and omit `flow_run_id` to recover a flow whose id you never received or lost. |
|
|
182
186
|
| `close_review_flow` | `flow_run_id` | — | Only after the reviewer returns `clean`. |
|
|
@@ -184,13 +188,14 @@ if findings:
|
|
|
184
188
|
## Example (code review)
|
|
185
189
|
|
|
186
190
|
```
|
|
187
|
-
# Step 1 — start (all
|
|
191
|
+
# Step 1 — start (all six args required; the reviewer sees a mirror of THIS SESSION's
|
|
188
192
|
# project directory, not of the directory you are working in — pass mode="context-only" to opt out)
|
|
189
193
|
start_review_flow(
|
|
190
194
|
kind="code-review",
|
|
191
195
|
target_kind="branch",
|
|
192
196
|
target_ref="feature/add-null-check",
|
|
193
197
|
target_title="Add null check on user input",
|
|
198
|
+
session_title="Review the null check on user input",
|
|
194
199
|
context="Review the diff on this branch for correctness and adherence to project conventions."
|
|
195
200
|
)
|
|
196
201
|
# → returns flow_run_id, e.g. "flow_abc123"
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: start-agents
|
|
3
|
+
description: >-
|
|
4
|
+
This skill should be used ONLY when the user explicitly asks for work to be
|
|
5
|
+
handed to separate agents — e.g. "start an agent for this", "start a hosted
|
|
6
|
+
agent", "start an agent for each of these", "hand this to another agent",
|
|
7
|
+
"run these in separate sessions". It covers `list_start_agent_options` and
|
|
8
|
+
`start_agent`, the `kcap mcp flows` tools that check this machine's daemon
|
|
9
|
+
and then start an ordinary hosted agent with a working directory and a
|
|
10
|
+
prompt, returning at once so the agent runs on its own. Use them INSTEAD of
|
|
11
|
+
your harness's own subagent or background-agent tool (which stays inside
|
|
12
|
+
this session), a flow, or the `kcap agent start` CLI. Do NOT use it for work
|
|
13
|
+
you can do yourself in this session, for an iterative review loop the user
|
|
14
|
+
asked for (use `review-flows`), or for a flow whose rounds you drive (use
|
|
15
|
+
`agent-flows`).
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Start agents
|
|
19
|
+
|
|
20
|
+
`start_agent` hands one task to one **separate hosted agent**: an ordinary
|
|
21
|
+
hosted agent with its own session, its own worktree and its own context. The
|
|
22
|
+
user supervises it from the dashboard, as they supervise any hosted agent. You
|
|
23
|
+
start it and move on. You do not drive it, wait for it or read its result.
|
|
24
|
+
|
|
25
|
+
It is how a list of independent tasks, such as a set of loose ends or the next
|
|
26
|
+
steps of a work item, gets done without all of it landing in one context.
|
|
27
|
+
|
|
28
|
+
## When to use it
|
|
29
|
+
|
|
30
|
+
Only when the user asks for separate agents. A list of tasks is not a request
|
|
31
|
+
to fan out: if the user asked you to fix something, fix it here.
|
|
32
|
+
|
|
33
|
+
Every started agent runs a paid model and takes a slot on the user's daemon.
|
|
34
|
+
|
|
35
|
+
## Not these look-alikes
|
|
36
|
+
|
|
37
|
+
- Your harness's own subagent or background-agent tool (Claude Code's Agent
|
|
38
|
+
or Task tool, Codex's `spawn_agent`) runs inside this session and is
|
|
39
|
+
recorded as part of it. That is exactly what a separate agent is not.
|
|
40
|
+
- A flow (`start_flow`, `start_review_flow`) is a loop you drive round by
|
|
41
|
+
round until sign-off. A started agent is not driven.
|
|
42
|
+
- The `kcap agent start` command bypasses the server's limits and its record
|
|
43
|
+
of who started what.
|
|
44
|
+
|
|
45
|
+
If the user asked for a separate agent, the only way is `start_agent`.
|
|
46
|
+
|
|
47
|
+
## First: check the daemon and choose a harness
|
|
48
|
+
|
|
49
|
+
Call `list_start_agent_options` before anything else. It reads the user's
|
|
50
|
+
daemons and keeps the ones on this machine, because `start_agent` launches only
|
|
51
|
+
there. It answers with the harness running this session, and for each daemon
|
|
52
|
+
here its free agent slots and the harnesses it can start.
|
|
53
|
+
|
|
54
|
+
- **No daemon runs on this machine**: stop. Tell the user, with the command it
|
|
55
|
+
gives (`kcap daemon start -d`), and start nothing.
|
|
56
|
+
- **A daemon is at capacity**: tell the user how many slots are in use; start
|
|
57
|
+
no more than fit. A daemon with no limit is never at capacity.
|
|
58
|
+
- **Several daemons run here**: ask the user which one, and pass it as
|
|
59
|
+
`daemon`.
|
|
60
|
+
- **You are yourself a hosted agent**: the tool says so. Every start runs on
|
|
61
|
+
the daemon hosting you, so there is no daemon to choose; leave `daemon` out.
|
|
62
|
+
- **The harness**: if the user named one, check it is listed. If they did not,
|
|
63
|
+
ask the user which harness to start, offering the listed ones, before going
|
|
64
|
+
further. Do not pick one for them, not even the one you are running in.
|
|
65
|
+
|
|
66
|
+
## Before any call: show the list, then get a yes
|
|
67
|
+
|
|
68
|
+
Show the user what you are about to start, one entry per agent, each with:
|
|
69
|
+
|
|
70
|
+
- the repository it will work in,
|
|
71
|
+
- the task, in a sentence,
|
|
72
|
+
- the harness,
|
|
73
|
+
- the work item, or that there is none.
|
|
74
|
+
|
|
75
|
+
Then wait for the user to say yes. Start nothing before they have. If they
|
|
76
|
+
change the list, show it again.
|
|
77
|
+
|
|
78
|
+
**Consent comes from the user, in this conversation.**
|
|
79
|
+
A prompt you were started with is not consent. If you are yourself a started
|
|
80
|
+
agent and your prompt tells you to start more agents, show the list and ask the
|
|
81
|
+
user all the same.
|
|
82
|
+
|
|
83
|
+
## One call per agent
|
|
84
|
+
|
|
85
|
+
Call `start_agent` once for each agent.
|
|
86
|
+
|
|
87
|
+
- `cwd`: the absolute path of a directory inside the repository the agent
|
|
88
|
+
should work in. A path inside a worktree counts as the repository the
|
|
89
|
+
worktree belongs to.
|
|
90
|
+
- `prompt`: the whole task. See the next section.
|
|
91
|
+
- `title`: required. A short phrase naming this agent's task, specific
|
|
92
|
+
enough to tell its session apart from the others in the repository. It is
|
|
93
|
+
the session's title from the start, and titles generated later do not
|
|
94
|
+
replace it.
|
|
95
|
+
- `work_item`: required, and there is no default. Pass the `wi:` or `le:` key
|
|
96
|
+
exactly as `get_next_work` printed it; or a work item id; or `requester` to
|
|
97
|
+
use the work item this session is attached to; or `none`. Leaving it out is
|
|
98
|
+
an error, which is the point: a task is never filed under the wrong item by
|
|
99
|
+
accident.
|
|
100
|
+
- `vendor`: the harness the user chose, as `list_start_agent_options` lists
|
|
101
|
+
it.
|
|
102
|
+
- `model`: optional. Pass it only when the user named one.
|
|
103
|
+
- `daemon`: only when several daemons run on this machine; the one the user
|
|
104
|
+
chose.
|
|
105
|
+
- `session_id`: optional. Leave it out unless a call was refused for lack of a
|
|
106
|
+
session id; then pass the id your session start stated.
|
|
107
|
+
|
|
108
|
+
## Writing the prompt
|
|
109
|
+
|
|
110
|
+
The agent shares none of this conversation. The prompt is all it gets, so
|
|
111
|
+
write one that stands alone:
|
|
112
|
+
|
|
113
|
+
- say what to do and what done looks like,
|
|
114
|
+
- name the files, the issue or the loose end it concerns,
|
|
115
|
+
- include what you learned here that it would otherwise have to rediscover,
|
|
116
|
+
- and make sure it names the session it came from, by ending it with:
|
|
117
|
+
"This task was handed over from Kurrent Capacitor session `<your session
|
|
118
|
+
id>`. Read that session with the kcap-sessions tools if you need the
|
|
119
|
+
background."
|
|
120
|
+
|
|
121
|
+
Keep it under 16 384 bytes. For more than that, put the detail in a file in the
|
|
122
|
+
repository and tell the agent to read it.
|
|
123
|
+
|
|
124
|
+
## After the calls
|
|
125
|
+
|
|
126
|
+
Each call answers `requested`, with the agent's id and the url of its page.
|
|
127
|
+
`requested` means the launch command was sent. It does not mean the agent is
|
|
128
|
+
running, and nothing is attached when the call returns: the server tries once,
|
|
129
|
+
later, to attach the new session to the work item you named.
|
|
130
|
+
|
|
131
|
+
Do not wait for the agents, and do not poll them. Do not call `start_agent`
|
|
132
|
+
again to find out whether an agent started.
|
|
133
|
+
|
|
134
|
+
Then report to the user:
|
|
135
|
+
|
|
136
|
+
- the url of every agent that was requested,
|
|
137
|
+
- every refusal, in the server's words.
|
|
138
|
+
|
|
139
|
+
## Refusals
|
|
140
|
+
|
|
141
|
+
A refusal states its reason. Relay it; do not retry in a loop.
|
|
142
|
+
|
|
143
|
+
- `already_in_progress`: a start on the same key is in flight, or one was sent
|
|
144
|
+
in the last 30 seconds. Do not repeat it.
|
|
145
|
+
- `no_daemon_on_this_machine`: none of the user's daemons runs here, or the one
|
|
146
|
+
that does is too old to say which machine it is on. The user starts one with
|
|
147
|
+
`kcap daemon start -d`, or updates kcap and restarts the daemon.
|
|
148
|
+
- `ambiguous_daemon`: several daemons run here. Ask the user which, and pass
|
|
149
|
+
`daemon`.
|
|
150
|
+
- `vendor_unavailable`: the daemon does not host that harness. The refusal
|
|
151
|
+
lists the ones it does; ask the user to pick one of them.
|
|
152
|
+
- `daemon_at_capacity`, `start_limit_reached`: there is no room. Stop starting
|
|
153
|
+
agents and tell the user how many were requested.
|
|
154
|
+
- `work_item_resolved`: the item was merged or split. The message says where it
|
|
155
|
+
went, as far as you may see. Ask the user which item to use.
|
|
156
|
+
- `work_item_not_visible`, `session_not_found`: you named something that is not
|
|
157
|
+
there for you. Check the key.
|
|
158
|
+
- `failed`, or a call that timed out: the agent may or may not have started.
|
|
159
|
+
Tell the user to look at the agents page. Do not start it again unasked.
|
|
160
|
+
- "This server cannot start agents": the server does not offer the feature.
|
|
161
|
+
There is nothing to retry.
|
|
162
|
+
|
|
163
|
+
## If `start_agent` is not among your tools
|
|
164
|
+
|
|
165
|
+
Tell the user to update kcap, run `kcap setup`, and restart the harness. Do not
|
|
166
|
+
start agents another way in its place: the limits and the record of who started
|
|
167
|
+
what belong to this tool.
|
|
@@ -89,6 +89,16 @@ end twice is a no-op (`created: false`). It refuses text shorter than 12 or long
|
|
|
89
89
|
500 characters and "none"-style phrases — do not declare that there is nothing left.
|
|
90
90
|
Loose ends are the user's; they are never converted into work items by this tool.
|
|
91
91
|
|
|
92
|
+
Name the issue it is about with an optional `subject` (`PROJ-123`, `#123`, `owner/repo#123`,
|
|
93
|
+
or a GitHub issue URL). When the server fetches it and finds it already closed, the result
|
|
94
|
+
says so and tells you to check the remote before treating the end as unfinished.
|
|
95
|
+
|
|
96
|
+
The feed files an end under a work item. An end that names an issue goes under that
|
|
97
|
+
issue's item, or stands alone when the issue has none. Otherwise it goes under this
|
|
98
|
+
session's primary item. When that is wrong, say where it belongs: `work_item_id` for a
|
|
99
|
+
known item with no issue of its own, or `standalone: true` when it belongs to none of
|
|
100
|
+
this session's work, such as an issue still to be filed. Set at most one of the two.
|
|
101
|
+
|
|
92
102
|
When you finish a listed or declared loose end, close it with `close_loose_end`, naming it by
|
|
93
103
|
the `loose_end_id` that `get_next_work`'s evidence or `list_loose_ends` shows. A later sighting
|
|
94
104
|
of the same work reopens it on its own; `reopen_loose_end` undoes a mistaken close.
|
|
@@ -128,7 +138,7 @@ loose ends with `declare_loose_end` (one call per item, never "none"), then call
|
|
|
128
138
|
| `declare_work_item` | exactly one of `issue_key` \| `pr_number` \| `work_item_id` \| `new_title` | Attach the session to a work item (or create one). `session_id` defaults to the current session. |
|
|
129
139
|
| `get_session_work_items` | — | List what the current session is attached to. |
|
|
130
140
|
| `get_next_work` | — | What the user should work on next, ranked, with because-clauses and evidence. `repo_hash` defaults to the current repository; `limit` defaults to 5 (max 20). |
|
|
131
|
-
| `declare_loose_end` | `text` | Record one unfinished item in the user's next-work ledger. `session_id` defaults to the current session. |
|
|
141
|
+
| `declare_loose_end` | `text` | Record one unfinished item in the user's next-work ledger. `subject` optionally names the issue it is about; `work_item_id` or `standalone` says which item it belongs under. `session_id` defaults to the current session. |
|
|
132
142
|
| `list_loose_ends` | — | List loose ends with their `loose_end_id`: `status` open (default) or closed, `repo_hash` defaults to the current repository, `limit` 20 (max 50), `cursor` from `next_cursor`. |
|
|
133
143
|
| `close_loose_end` | `loose_end_id` | Mark a finished loose end done. `session_id` defaults to the current session. |
|
|
134
144
|
| `reopen_loose_end` | `loose_end_id` | Undo a close. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kurrent/kcap",
|
|
3
|
-
"version": "1.3.0-beta.
|
|
3
|
+
"version": "1.3.0-beta.7",
|
|
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": "1.3.0-beta.
|
|
18
|
-
"@kurrent/kcap-linux-arm64": "1.3.0-beta.
|
|
19
|
-
"@kurrent/kcap-linux-musl-arm64": "1.3.0-beta.
|
|
20
|
-
"@kurrent/kcap-linux-musl-x64": "1.3.0-beta.
|
|
21
|
-
"@kurrent/kcap-linux-x64": "1.3.0-beta.
|
|
22
|
-
"@kurrent/kcap-win-x64": "1.3.0-beta.
|
|
17
|
+
"@kurrent/kcap-darwin-arm64": "1.3.0-beta.7",
|
|
18
|
+
"@kurrent/kcap-linux-arm64": "1.3.0-beta.7",
|
|
19
|
+
"@kurrent/kcap-linux-musl-arm64": "1.3.0-beta.7",
|
|
20
|
+
"@kurrent/kcap-linux-musl-x64": "1.3.0-beta.7",
|
|
21
|
+
"@kurrent/kcap-linux-x64": "1.3.0-beta.7",
|
|
22
|
+
"@kurrent/kcap-win-x64": "1.3.0-beta.7"
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"bin/",
|
|
26
26
|
"kcap/"
|
|
27
27
|
],
|
|
28
|
-
"kcapReleaseCommit": "
|
|
29
|
-
"kcapReleaseTag": "v1.3.0-beta.
|
|
28
|
+
"kcapReleaseCommit": "ea55466b11f901d54ed75d89900f6b316e86dd33",
|
|
29
|
+
"kcapReleaseTag": "v1.3.0-beta.7"
|
|
30
30
|
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: suggest-review-flow
|
|
3
|
-
description: >-
|
|
4
|
-
Use this skill when implementation is complete — a feature or bugfix is functionally
|
|
5
|
-
finished, tests pass, or you are about to commit / open a PR / merge — or when a spec is
|
|
6
|
-
finalized. At that moment, proactively OFFER an independent second-harness review even if
|
|
7
|
-
the user did not ask, because a fresh, separate reviewer catches what the author's own model
|
|
8
|
-
misses. It calls list_reviewer_vendors to recommend a reviewer that will actually run for
|
|
9
|
-
this repo, offers a spec-review or code-review flow, and hands off to the review-flows skill
|
|
10
|
-
only after the user accepts — it never starts a flow itself. Do NOT use it when the user
|
|
11
|
-
asks you to review something yourself ("review this", "code review this", "look over my
|
|
12
|
-
spec"), or mid-task before the work is finished.
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
# Suggest a review flow
|
|
16
|
-
|
|
17
|
-
You have reached a milestone where an **independent** review adds real value: a
|
|
18
|
-
separate coding-agent session, with none of this session's context, reviews the
|
|
19
|
-
work — and a different model catches what the author's own model glossed over.
|
|
20
|
-
Most people never think to do this. Your job here is to **offer** it at the
|
|
21
|
-
right moment, recommend a reviewer that will actually run, and — only if the
|
|
22
|
-
user says yes — hand off to the `review-flows` skill. **This skill never starts
|
|
23
|
-
a review flow itself.**
|
|
24
|
-
|
|
25
|
-
## When to offer (and when not to)
|
|
26
|
-
|
|
27
|
-
Offer at exactly two milestones:
|
|
28
|
-
|
|
29
|
-
- **Spec complete** — you just produced AND presented a finalized spec/design
|
|
30
|
-
this session → offer a `spec-review` flow.
|
|
31
|
-
- **Implementation complete** — the change is functionally finished (you say so,
|
|
32
|
-
or you are about to commit / open a PR / merge) → offer a `code-review` flow.
|
|
33
|
-
|
|
34
|
-
Do NOT offer (stay silent) when:
|
|
35
|
-
|
|
36
|
-
- The user asked you to **review something yourself** ("review this", "code
|
|
37
|
-
review this", "look over the spec"). Just perform that review locally — no
|
|
38
|
-
offer, no flow.
|
|
39
|
-
- You are only part-way through: rough mid-stream brainstorming, a partial plan,
|
|
40
|
-
a routine edit, or work whose known checks are still failing.
|
|
41
|
-
- A review flow for this artifact is already engaged, active, or just completed.
|
|
42
|
-
- Another skill (brainstorming, writing-plans, finishing-a-development-branch,
|
|
43
|
-
requesting-code-review) is mid-flow — let it finish; offer at the seam.
|
|
44
|
-
|
|
45
|
-
**Offer at most once per artifact.** Key the offer on (milestone type + the
|
|
46
|
-
target's identity + its revision): the same spec or the same change never gets
|
|
47
|
-
offered twice, but a materially revised artifact may be offered again, and a
|
|
48
|
-
second, different artifact of the same kind may be offered on its own. If the
|
|
49
|
-
user declines or moves on, stay silent for that artifact. A failed availability
|
|
50
|
-
lookup counts as the one prompt for that artifact — do not re-prompt.
|
|
51
|
-
|
|
52
|
-
## How to recommend a reviewer
|
|
53
|
-
|
|
54
|
-
1. Call **`list_reviewer_vendors`** (read-only; safe to call before offering).
|
|
55
|
-
It returns `reviewers[]` (vendors that can actually run for this repo now),
|
|
56
|
-
`driver_vendor` (the harness you are running in, or absent if unknown), and
|
|
57
|
-
`diagnostics`.
|
|
58
|
-
2. **Prefer a reviewer different from the driver.** A different model is the
|
|
59
|
-
highest-value review. If one non-driver reviewer is available, recommend it;
|
|
60
|
-
if several, offer a short choice — never assert one vendor is "better".
|
|
61
|
-
3. **If the only available reviewer is your own vendor, still offer it** —
|
|
62
|
-
framed as an independent, context-free reviewer session. The value is the
|
|
63
|
-
clean second look, not necessarily a different model.
|
|
64
|
-
4. **If `driver_vendor` is absent (unknown)**, do NOT claim "a different model";
|
|
65
|
-
frame the offer as "a separate, independent reviewer session" and offer a
|
|
66
|
-
choice from `reviewers[]`.
|
|
67
|
-
5. **If `reviewers[]` is empty**, read `diagnostics.reason` and give one line of
|
|
68
|
-
guidance instead of a dead end:
|
|
69
|
-
- `no_daemons_connected` → start a daemon (`kcap daemon start -d`).
|
|
70
|
-
- `no_repo_hosting_daemon` → run a daemon on a machine that has this repo.
|
|
71
|
-
- `no_unattended_reviewer` → install/certify a second harness as a reviewer.
|
|
72
|
-
- `repo_unresolved` → the current directory isn't a recognized repo.
|
|
73
|
-
- `lookup_failed` → couldn't reach the server; suggest checking `kcap status`.
|
|
74
|
-
- `schema_skew` → the kcap client/server is out of date; suggest updating.
|
|
75
|
-
|
|
76
|
-
## Handing off (only after the user accepts)
|
|
77
|
-
|
|
78
|
-
- You MAY run the read-only `list_reviewer_vendors` lookup automatically, but you
|
|
79
|
-
**MUST NOT start a review flow until the user affirmatively accepts THIS
|
|
80
|
-
offer.**
|
|
81
|
-
- On acceptance, invoke the **`review-flows`** skill to run it, preserving the
|
|
82
|
-
chosen `kind` (spec-review / code-review), the target, and the chosen reviewer
|
|
83
|
-
vendor.
|
|
84
|
-
- If the reviewer vendor turns out to be unavailable at start (a snapshot race),
|
|
85
|
-
`review-flows` surfaces the reason — do not silently substitute another vendor;
|
|
86
|
-
re-recommend and get fresh consent.
|
|
87
|
-
|
|
88
|
-
## If `list_reviewer_vendors` is not available
|
|
89
|
-
|
|
90
|
-
Your harness caches the kcap MCP tool list when it connects. If kcap was
|
|
91
|
-
upgraded mid-session, `list_reviewer_vendors` may be missing from this session.
|
|
92
|
-
Do NOT guess availability and do NOT shell out as a workaround — tell the user
|
|
93
|
-
to restart the harness (or reconnect the `kcap-flows` MCP server) so the tool
|
|
94
|
-
appears, then offer again.
|