@kontextmind/kxm 0.7.120 → 0.7.122
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/.claude-plugin/marketplace.json +1 -1
- package/.kxm/gates.yaml +24 -0
- package/.kxm/workflows/land.yaml +95 -0
- package/CHANGELOG.md +16 -0
- package/docs/contributing/assignment-runner.md +56 -22
- package/docs/guides/agent-skills.md +1 -1
- package/docs/reference/cli-reference.md +130 -1
- package/docs/reference/workflow-catalog.md +7 -0
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +370 -169
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm/SKILL.md +2 -1
- package/plugins/kxm/skills/kxm-runs/SKILL.md +25 -1
- package/plugins/kxm/src/cli/assign.ts +144 -0
- package/plugins/kxm/src/cli/land.ts +48 -0
- package/plugins/kxm/src/cli.ts +86 -0
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/scripts/pr-land.d.mts +2 -0
- package/scripts/pr-land.mjs +971 -0
|
@@ -17313,7 +17313,7 @@ function sessionTokenFixHint(policy) {
|
|
|
17313
17313
|
}
|
|
17314
17314
|
|
|
17315
17315
|
// plugins/kxm/src/mcp-server.ts
|
|
17316
|
-
var VERSION = "0.7.
|
|
17316
|
+
var VERSION = "0.7.122";
|
|
17317
17317
|
var CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
|
|
17318
17318
|
var inbox = /* @__PURE__ */ new Map();
|
|
17319
17319
|
var notifiedInbox = /* @__PURE__ */ new Set();
|
package/plugins/kxm/package.json
CHANGED
|
@@ -20,7 +20,8 @@ writers, or replace `.kxm/roster.yaml` trusted policy.
|
|
|
20
20
|
| Delegate to or answer another agent | `kxm-peer` | `peer` (`peer await` is capped at 60 seconds) |
|
|
21
21
|
| Work inside a durable workflow run, gates, signed callbacks | `kxm-workflow` | `workflow`, `gate` |
|
|
22
22
|
| Role definitions, role hosts, model rosters | `kxm-definitions` | `role` |
|
|
23
|
-
| Create, drive, inspect, or cancel a run,
|
|
23
|
+
| Create, drive, inspect, or cancel a run, use a worktree lane, or land a branch | `kxm-runs` | `run`, `runs`, `lane`, `land` |
|
|
24
|
+
| Create, drive, inspect, or cancel a run, use a worktree lane, or run the developer assignment loop | `kxm-runs` | `run`, `runs`, `lane`, `assign` |
|
|
24
25
|
| What we know or decided, recall, context footprint, Git memory | `kxm-context-memory` | `context`, `memory`, `explain` |
|
|
25
26
|
| Turn a repeated practice into a governed skill | `kxm-skill-lifecycle` | `skills` |
|
|
26
27
|
| What KXM learned, repeated asks, recorded route spend | `kxm-routing-improve` | `routing`, `improve` |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kxm-runs
|
|
3
|
-
description: Create, drive, and inspect local KXM runs,
|
|
3
|
+
description: Create, drive, and inspect local KXM runs, manage worktree lanes, land a branch, and run the developer assignment loop. kxm runs drive with --simulated executes a run model-free and settles it with a verified receipt. Use when asked to start a workflow run, check its status, read its receipt, cancel it, smoke-test a workflow, create a lane, land the current branch, or call kxm assign (run, witness, plan-current, attribute, observe-cost, accept, change-report).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# KXM runs
|
|
@@ -26,6 +26,14 @@ create, or logs verbs under `runs`.
|
|
|
26
26
|
| `kxm lane status <unit>` | One lane plus its last run status, or unknown when the supervisor is not answering | `--json` |
|
|
27
27
|
| `kxm lane drop <unit>` | Remove the worktree and the record. The branch is not deleted | `--force`, `--json` |
|
|
28
28
|
| `kxm lane run <unit>` | Create the lane if needed, start a run from a brief, and drive it | `--brief <file>` (required), `--workflow <id>`, `--base <ref>`, `--wait`, `--timeout-ms <n>`, `--json` |
|
|
29
|
+
| `kxm land` | Verify, regenerate docs, push, open or reuse a pull request, rebase, unblock, squash-merge, watch the release, and note a milestone | `--pr <n>`, `--stage <name>`, `--body-file <path>`, `--json`, `--dry-run` |
|
|
30
|
+
| `kxm assign run` | Dispatch one assignment manifest. The runner performs every check | `--manifest <path>` |
|
|
31
|
+
| `kxm assign witness` | Run the fixed witness for an existing record | `--record-dir <path>` |
|
|
32
|
+
| `kxm assign plan-current` | Stamp or advance the current-plan pointer | `--task-dir <path>`, `--plan <path>`, `--sha256 <hex>`, `--base-commit <sha>`, `--expected-generation <n>` |
|
|
33
|
+
| `kxm assign attribute` | Attach a private note. It is not proof | `--task-dir <path>`, `--record-dir <path>`, `--class <class>`, `--explanation-file <path>` |
|
|
34
|
+
| `kxm assign observe-cost` | Import one cost-only observation | `--task-dir <path>`, `--input <path>` |
|
|
35
|
+
| `kxm assign accept` | Bind a witnessed commit and two critic records | `--task-dir <path>`, `--commit <sha>`, `--record-dir <path>`, `--critic <path>` twice, optional `--observed-pr <id>`, `--observed-ci <id>` |
|
|
36
|
+
| `kxm assign change-report` | Report attempts, rework, and spend | `--task-dir <path>` |
|
|
29
37
|
|
|
30
38
|
The run record and its events keep only the prompt's hash, but the full
|
|
31
39
|
prompt text is kept in a local `run-events.db.run-prompts.json` file (mode
|
|
@@ -65,6 +73,22 @@ file. `kxm run --lane <unit>` and `kxm runs status|drive|receipt|cancel --lane`
|
|
|
65
73
|
discover the project from the lane worktree. `kxm lane run <unit> --brief <file>`
|
|
66
74
|
creates the lane when it is missing, starts the run, and drives it.
|
|
67
75
|
|
|
76
|
+
`kxm land` lands the current branch. With no `--stage` it runs these stages in
|
|
77
|
+
order: `verify`, `docs`, `push`, `pr`, `rebase`, `unblock`, `merge`,
|
|
78
|
+
`release`, `milestone`. `verify` runs `npm run verify` on a clean tree and is
|
|
79
|
+
not replaced by the later stages. `docs` regenerates the roadmap when
|
|
80
|
+
`plans/kxm-roadmap/update-dashboard.mjs` is present and commits only those
|
|
81
|
+
generated pages. `push` publishes the branch. `pr` reuses the open pull
|
|
82
|
+
request or creates one from `--body-file`. `rebase` rebases onto
|
|
83
|
+
`origin/main` for at most five rounds, resolving only the dist rebuild, the
|
|
84
|
+
CHANGELOG Unreleased union, and the tracker "Landed in this tree" union.
|
|
85
|
+
`unblock` reruns one failed check and reports a required review. `merge`
|
|
86
|
+
squash-merges. `release` waits for the tag and the npm publish. `milestone`
|
|
87
|
+
reports `deep_review_required` when a phase flips to done or the body contains
|
|
88
|
+
a `Milestone:` line, and does not run the review. `--dry-run` prints each
|
|
89
|
+
stage's plan and does not mutate.
|
|
90
|
+
`kxm assign` spawns `node scripts/assignment-run.mjs` from the project root and returns the child's exit code. Paths are passed through as given. `--dry-run` prints that argv and does not spawn. `--json` formats this command's own output and is not forwarded. The group does not load a working-directory `.env`. A project without `scripts/assignment-run.mjs` is refused with `assign_runner_missing`. Outside a KXM project the refusal is `project_required`. Witness, roster, and acceptance checks belong to the runner, documented in `docs/contributing/assignment-runner.md`.
|
|
91
|
+
|
|
68
92
|
## Refusals
|
|
69
93
|
|
|
70
94
|
- `run_workflow_unknown`: the workflow ID is not a project workflow. Run only
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { discoverKxmProjectRoot } from "../project-config.ts";
|
|
5
|
+
import { CLI_RESULT_SCHEMA, print, type Runtime } from "./types.ts";
|
|
6
|
+
|
|
7
|
+
export interface AssignSpawnOptions {
|
|
8
|
+
cwd: string;
|
|
9
|
+
stdio: "inherit";
|
|
10
|
+
env: NodeJS.ProcessEnv;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface AssignSpawnResult {
|
|
14
|
+
status: number | null;
|
|
15
|
+
error?: Error;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Test seam. Production leaves `spawn` unset and uses `spawnSync`. */
|
|
19
|
+
export const kxmAssignCliSeams: {
|
|
20
|
+
spawn?: (command: string, args: readonly string[], options: AssignSpawnOptions) => AssignSpawnResult;
|
|
21
|
+
} = {};
|
|
22
|
+
|
|
23
|
+
export type AssignVerb =
|
|
24
|
+
| "run"
|
|
25
|
+
| "witness"
|
|
26
|
+
| "plan-current"
|
|
27
|
+
| "attribute"
|
|
28
|
+
| "observe-cost"
|
|
29
|
+
| "accept"
|
|
30
|
+
| "change-report";
|
|
31
|
+
|
|
32
|
+
export interface AssignArgs {
|
|
33
|
+
manifest?: string;
|
|
34
|
+
recordDir?: string;
|
|
35
|
+
taskDir?: string;
|
|
36
|
+
plan?: string;
|
|
37
|
+
sha256?: string;
|
|
38
|
+
baseCommit?: string;
|
|
39
|
+
expectedGeneration?: string;
|
|
40
|
+
classification?: string;
|
|
41
|
+
explanationFile?: string;
|
|
42
|
+
input?: string;
|
|
43
|
+
commit?: string;
|
|
44
|
+
critics?: readonly string[];
|
|
45
|
+
observedPr?: string;
|
|
46
|
+
observedCi?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const RUNNER_REL = "scripts/assignment-run.mjs";
|
|
50
|
+
|
|
51
|
+
function refuse(runtime: Runtime, command: string, error: string, text: string): number {
|
|
52
|
+
print(runtime.io, runtime.json, { ok: false, command, error }, text);
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function flag(value: string | undefined): string {
|
|
57
|
+
if (value === undefined) throw new Error("assign invocation missing a parsed flag");
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Argv after `node scripts/assignment-run.mjs`, in the recipe's flag order.
|
|
62
|
+
* The runner's usage text documents no `--json` flag. `accept` prints JSON
|
|
63
|
+
* and takes none, so the global `--json` flag stays on this command. */
|
|
64
|
+
function runnerArgv(subcommand: AssignVerb, args: AssignArgs): string[] {
|
|
65
|
+
switch (subcommand) {
|
|
66
|
+
case "run":
|
|
67
|
+
return ["run", "--manifest", flag(args.manifest)];
|
|
68
|
+
case "witness":
|
|
69
|
+
return ["witness", "--record-dir", flag(args.recordDir)];
|
|
70
|
+
case "plan-current":
|
|
71
|
+
return [
|
|
72
|
+
"plan-current",
|
|
73
|
+
"--task-dir", flag(args.taskDir),
|
|
74
|
+
"--plan", flag(args.plan),
|
|
75
|
+
"--sha256", flag(args.sha256),
|
|
76
|
+
"--base-commit", flag(args.baseCommit),
|
|
77
|
+
"--expected-generation", flag(args.expectedGeneration),
|
|
78
|
+
];
|
|
79
|
+
case "attribute":
|
|
80
|
+
return [
|
|
81
|
+
"attribute",
|
|
82
|
+
"--task-dir", flag(args.taskDir),
|
|
83
|
+
"--record-dir", flag(args.recordDir),
|
|
84
|
+
"--class", flag(args.classification),
|
|
85
|
+
"--explanation-file", flag(args.explanationFile),
|
|
86
|
+
];
|
|
87
|
+
case "observe-cost":
|
|
88
|
+
return ["observe-cost", "--task-dir", flag(args.taskDir), "--input", flag(args.input)];
|
|
89
|
+
case "accept": {
|
|
90
|
+
const argv = [
|
|
91
|
+
"accept",
|
|
92
|
+
"--task-dir", flag(args.taskDir),
|
|
93
|
+
"--commit", flag(args.commit),
|
|
94
|
+
"--record-dir", flag(args.recordDir),
|
|
95
|
+
];
|
|
96
|
+
for (const critic of args.critics ?? []) argv.push("--critic", critic);
|
|
97
|
+
if (args.observedPr !== undefined) argv.push("--observed-pr", args.observedPr);
|
|
98
|
+
if (args.observedCi !== undefined) argv.push("--observed-ci", args.observedCi);
|
|
99
|
+
return argv;
|
|
100
|
+
}
|
|
101
|
+
case "change-report":
|
|
102
|
+
return ["change-report", "--task-dir", flag(args.taskDir)];
|
|
103
|
+
default: {
|
|
104
|
+
const unreachable: never = subcommand;
|
|
105
|
+
throw new Error(`unknown assign verb ${String(unreachable)}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function cmdAssign(runtime: Runtime, subcommand: AssignVerb, args: AssignArgs): Promise<number> {
|
|
111
|
+
const command = `assign ${subcommand}`;
|
|
112
|
+
const root = discoverKxmProjectRoot(runtime.cwd);
|
|
113
|
+
if (!root) return refuse(runtime, command, "project_required", `${command} requires a KXM project (run kxm init first)`);
|
|
114
|
+
if (!existsSync(join(root, "scripts", "assignment-run.mjs"))) {
|
|
115
|
+
return refuse(runtime, command, "assign_runner_missing", `${command} requires scripts/assignment-run.mjs in the project root`);
|
|
116
|
+
}
|
|
117
|
+
const argv = ["node", RUNNER_REL, ...runnerArgv(subcommand, args)];
|
|
118
|
+
if (runtime.dryRun) {
|
|
119
|
+
// print() redacts every 64-hex string. plan-current passes a plan sha256
|
|
120
|
+
// through unchanged, so the dry-run argv is written directly.
|
|
121
|
+
const payload = { schema: CLI_RESULT_SCHEMA, ok: true, command, dryRun: true, argv };
|
|
122
|
+
runtime.io.stdout(runtime.json ? `${JSON.stringify(payload)}\n` : `${argv.join(" ")}\n`);
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
// Never load a `.env` from the working directory. The justfile keeps
|
|
126
|
+
// `set dotenv-load` off for the same reason: a gitignored `.env` could set
|
|
127
|
+
// `NODE_OPTIONS`, and that value runs before the runner validates identity,
|
|
128
|
+
// tree, or roster. Pass the process environment through unchanged.
|
|
129
|
+
const spawn = kxmAssignCliSeams.spawn ?? ((commandName: string, commandArgs: readonly string[], options: AssignSpawnOptions): AssignSpawnResult => {
|
|
130
|
+
const result = spawnSync(commandName, commandArgs, {
|
|
131
|
+
cwd: options.cwd,
|
|
132
|
+
stdio: options.stdio,
|
|
133
|
+
env: options.env,
|
|
134
|
+
windowsHide: true,
|
|
135
|
+
});
|
|
136
|
+
return { status: result.status, ...(result.error ? { error: result.error } : {}) };
|
|
137
|
+
});
|
|
138
|
+
const result = spawn("node", argv.slice(1), { cwd: root, stdio: "inherit", env: runtime.env });
|
|
139
|
+
if (result.status === null) {
|
|
140
|
+
const detail = result.error?.message ?? "the assignment runner could not be started";
|
|
141
|
+
return refuse(runtime, command, "assign_spawn_failed", detail);
|
|
142
|
+
}
|
|
143
|
+
return result.status;
|
|
144
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { discoverKxmProjectRoot } from "../project-config.ts";
|
|
4
|
+
import { findKxmRepoRoot } from "../repo-root.ts";
|
|
5
|
+
import { print, type Runtime } from "./types.ts";
|
|
6
|
+
|
|
7
|
+
export interface LandOptions {
|
|
8
|
+
pr?: string;
|
|
9
|
+
stage?: string;
|
|
10
|
+
bodyFile?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function childEnv(): NodeJS.ProcessEnv {
|
|
14
|
+
const env: NodeJS.ProcessEnv = {};
|
|
15
|
+
for (const [name, value] of Object.entries(process.env)) {
|
|
16
|
+
if (value === undefined) continue;
|
|
17
|
+
if (name.toUpperCase().startsWith("GIT_")) continue;
|
|
18
|
+
env[name] = value;
|
|
19
|
+
}
|
|
20
|
+
return env;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function refuse(runtime: Runtime, error: string, text: string): number {
|
|
24
|
+
print(runtime.io, runtime.json, { ok: false, command: "land", error }, text);
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Spawn scripts/pr-land.mjs and stream its JSON lines. The exit code is the script's. */
|
|
29
|
+
export function cmdLand(runtime: Runtime, options: LandOptions = {}): Promise<number> {
|
|
30
|
+
const root = discoverKxmProjectRoot(runtime.cwd);
|
|
31
|
+
if (!root) {
|
|
32
|
+
return Promise.resolve(refuse(runtime, "project_required", "land requires a KXM project (run kxm init first)"));
|
|
33
|
+
}
|
|
34
|
+
const script = join(findKxmRepoRoot(import.meta.url), "scripts", "pr-land.mjs");
|
|
35
|
+
const args = [script];
|
|
36
|
+
if (options.pr) args.push("--pr", options.pr);
|
|
37
|
+
if (options.stage) args.push("--stage", options.stage);
|
|
38
|
+
if (options.bodyFile) args.push("--body-file", options.bodyFile);
|
|
39
|
+
if (runtime.json) args.push("--json");
|
|
40
|
+
if (runtime.dryRun) args.push("--dry-run");
|
|
41
|
+
return new Promise((resolveExit) => {
|
|
42
|
+
const child = spawn(process.execPath, args, { cwd: root, env: childEnv(), windowsHide: true });
|
|
43
|
+
child.stdout.on("data", (chunk: Buffer) => runtime.io.stdout(chunk.toString("utf8")));
|
|
44
|
+
child.stderr.on("data", (chunk: Buffer) => runtime.io.stderr(chunk.toString("utf8")));
|
|
45
|
+
child.once("error", () => resolveExit(1));
|
|
46
|
+
child.once("close", (code) => resolveExit(code ?? 1));
|
|
47
|
+
});
|
|
48
|
+
}
|
package/plugins/kxm/src/cli.ts
CHANGED
|
@@ -131,6 +131,9 @@ import {
|
|
|
131
131
|
cmdLaneStatus,
|
|
132
132
|
} from "./cli/lanes.ts";
|
|
133
133
|
|
|
134
|
+
import { cmdLand } from "./cli/land.ts";
|
|
135
|
+
import { cmdAssign } from "./cli/assign.ts";
|
|
136
|
+
|
|
134
137
|
import {
|
|
135
138
|
cmdStatus,
|
|
136
139
|
cmdDash,
|
|
@@ -197,6 +200,9 @@ const USAGE_ERROR_CODES = new Set([
|
|
|
197
200
|
const DRY_RUN_COMMANDS: ReadonlySet<string> = new Set([
|
|
198
201
|
"init", "backup", "restore", "run", "explain", "suggest", "update", "dash", "completion", "completion install",
|
|
199
202
|
"lane create", "lane list", "lane status", "lane drop", "lane run",
|
|
203
|
+
"land",
|
|
204
|
+
"assign run", "assign witness", "assign plan-current", "assign attribute",
|
|
205
|
+
"assign observe-cost", "assign accept", "assign change-report",
|
|
200
206
|
"plugin install", "plugin",
|
|
201
207
|
"runs status", "runs drive", "runs receipt", "runs cancel", "runs list",
|
|
202
208
|
"tenant status", "models inventory-refresh", "harness list", "auth token",
|
|
@@ -485,6 +491,86 @@ function createProgram(ctx: CliContext, result: { code: number }): Command {
|
|
|
485
491
|
});
|
|
486
492
|
});
|
|
487
493
|
|
|
494
|
+
addGlobalOptions(program.command("land").description("Land the current branch: verify, regenerate docs, push, pull request, rebase, unblock, squash-merge, release, and milestone"))
|
|
495
|
+
.option("--pr <n>", "Existing pull request number")
|
|
496
|
+
.option("--stage <name>", "Run one stage: verify, docs, push, pr, rebase, unblock, merge, release, or milestone")
|
|
497
|
+
.option("--body-file <path>", "Pull request body file used when creating a pull request")
|
|
498
|
+
.action(async function landAction(this: Command, options: { pr?: string; stage?: string; bodyFile?: string }) {
|
|
499
|
+
result.code = await cmdLand(runtimeFrom(ctx, this), {
|
|
500
|
+
...(options.pr !== undefined ? { pr: options.pr } : {}),
|
|
501
|
+
...(options.stage !== undefined ? { stage: options.stage } : {}),
|
|
502
|
+
...(options.bodyFile !== undefined ? { bodyFile: options.bodyFile } : {}),
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
const assignCmd = addGlobalOptions(program.command("assign").description("Run this repository's developer assignment runner"));
|
|
506
|
+
assignCmd.helpCommand("help", "Show assign help");
|
|
507
|
+
addGlobalOptions(assignCmd.command("run").description("Dispatch a bound assignment manifest"))
|
|
508
|
+
.requiredOption("--manifest <path>", "Absolute path to the assignment manifest")
|
|
509
|
+
.action(async function assignRunAction(this: Command, options: { manifest: string }) {
|
|
510
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "run", { manifest: options.manifest });
|
|
511
|
+
});
|
|
512
|
+
addGlobalOptions(assignCmd.command("witness").description("Run the fixed verification witness for an existing assignment"))
|
|
513
|
+
.requiredOption("--record-dir <path>", "Absolute path to the assignment record directory")
|
|
514
|
+
.action(async function assignWitnessAction(this: Command, options: { recordDir: string }) {
|
|
515
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "witness", { recordDir: options.recordDir });
|
|
516
|
+
});
|
|
517
|
+
addGlobalOptions(assignCmd.command("plan-current").description("Stamp or advance the current-plan pointer"))
|
|
518
|
+
.requiredOption("--task-dir <path>", "Absolute path to the task directory")
|
|
519
|
+
.requiredOption("--plan <path>", "Absolute path to the plan file")
|
|
520
|
+
.requiredOption("--sha256 <hex>", "SHA-256 of the plan file")
|
|
521
|
+
.requiredOption("--base-commit <sha>", "Base commit the pointer records")
|
|
522
|
+
.requiredOption("--expected-generation <n>", "Generation the pointer must currently have")
|
|
523
|
+
.action(async function assignPlanCurrentAction(this: Command, options: { taskDir: string; plan: string; sha256: string; baseCommit: string; expectedGeneration: string }) {
|
|
524
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "plan-current", {
|
|
525
|
+
taskDir: options.taskDir,
|
|
526
|
+
plan: options.plan,
|
|
527
|
+
sha256: options.sha256,
|
|
528
|
+
baseCommit: options.baseCommit,
|
|
529
|
+
expectedGeneration: options.expectedGeneration,
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
addGlobalOptions(assignCmd.command("attribute").description("Attach a private attribution note"))
|
|
533
|
+
.requiredOption("--task-dir <path>", "Absolute path to the task directory")
|
|
534
|
+
.requiredOption("--record-dir <path>", "Absolute path to the assignment record directory")
|
|
535
|
+
.requiredOption("--class <class>", "orchestration, model, environment, or unclassified")
|
|
536
|
+
.requiredOption("--explanation-file <path>", "Absolute path to the note file")
|
|
537
|
+
.action(async function assignAttributeAction(this: Command, options: { taskDir: string; recordDir: string; class: string; explanationFile: string }) {
|
|
538
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "attribute", {
|
|
539
|
+
taskDir: options.taskDir,
|
|
540
|
+
recordDir: options.recordDir,
|
|
541
|
+
classification: options.class,
|
|
542
|
+
explanationFile: options.explanationFile,
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
addGlobalOptions(assignCmd.command("observe-cost").description("Import one historical cost observation as cost-only"))
|
|
546
|
+
.requiredOption("--task-dir <path>", "Absolute path to the task directory")
|
|
547
|
+
.requiredOption("--input <path>", "Absolute path to the observation file")
|
|
548
|
+
.action(async function assignObserveCostAction(this: Command, options: { taskDir: string; input: string }) {
|
|
549
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "observe-cost", { taskDir: options.taskDir, input: options.input });
|
|
550
|
+
});
|
|
551
|
+
addGlobalOptions(assignCmd.command("accept").description("Bind an exact witnessed commit and two critic PASS records"))
|
|
552
|
+
.requiredOption("--task-dir <path>", "Absolute path to the task directory")
|
|
553
|
+
.requiredOption("--commit <sha>", "Commit to accept")
|
|
554
|
+
.requiredOption("--record-dir <path>", "Absolute path to the writer record directory")
|
|
555
|
+
.requiredOption("--critic <path>", "Absolute path to a critic record directory; pass twice", (value: string, previous: string[]) => previous.concat(value), [] as string[])
|
|
556
|
+
.option("--observed-pr <id>", "Observed pull request id")
|
|
557
|
+
.option("--observed-ci <id>", "Observed CI run id")
|
|
558
|
+
.action(async function assignAcceptAction(this: Command, options: { taskDir: string; commit: string; recordDir: string; critic: string[]; observedPr?: string; observedCi?: string }) {
|
|
559
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "accept", {
|
|
560
|
+
taskDir: options.taskDir,
|
|
561
|
+
commit: options.commit,
|
|
562
|
+
recordDir: options.recordDir,
|
|
563
|
+
critics: options.critic,
|
|
564
|
+
...(options.observedPr !== undefined ? { observedPr: options.observedPr } : {}),
|
|
565
|
+
...(options.observedCi !== undefined ? { observedCi: options.observedCi } : {}),
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
addGlobalOptions(assignCmd.command("change-report").description("Report attempts, rework, costs, and retained verification history"))
|
|
569
|
+
.requiredOption("--task-dir <path>", "Absolute path to the task directory")
|
|
570
|
+
.action(async function assignChangeReportAction(this: Command, options: { taskDir: string }) {
|
|
571
|
+
result.code = await cmdAssign(runtimeFrom(ctx, this), "change-report", { taskDir: options.taskDir });
|
|
572
|
+
});
|
|
573
|
+
|
|
488
574
|
addGlobalOptions(program.command("run").description("Create a KXM run without executing steps; follow its prerequisites, then kxm runs drive <runId> --wait")
|
|
489
575
|
.argument("[workflow]", "Workflow id to run")
|
|
490
576
|
.argument("[prompt...]", "Run prompt (events keep its hash; the full text is kept in a local 0600 sidecar file)")
|
|
@@ -11,7 +11,7 @@ import { deliverInboxNotification } from "./inbox.ts";
|
|
|
11
11
|
import type { HubEvent, MessageRecord } from "./protocol.ts";
|
|
12
12
|
import { sessionTokenFixHint } from "./session-token-hint.ts";
|
|
13
13
|
|
|
14
|
-
const VERSION = "0.7.
|
|
14
|
+
const VERSION = "0.7.122";
|
|
15
15
|
const CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
|
|
16
16
|
const inbox = new Map<string, MessageRecord>();
|
|
17
17
|
const notifiedInbox = new Set<string>();
|