@sechroom/cli 2026.7.20-rc.5cee4cf5 → 2026.7.20
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/dist/index.js +17 -107
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2213,7 +2213,7 @@ function registerExecutor(program2) {
|
|
|
2213
2213
|
);
|
|
2214
2214
|
});
|
|
2215
2215
|
executor.command("refresh <id>").description("Refresh one advertisement lease once").option("--ttl <seconds>", "Advertisement TTL (30-600)", parseInteger, 120).action(async (id, opts, cmd) => {
|
|
2216
|
-
const data = await
|
|
2216
|
+
const data = await refresh(
|
|
2217
2217
|
resolveConfig(cmd.optsWithGlobals()),
|
|
2218
2218
|
id,
|
|
2219
2219
|
opts.ttl
|
|
@@ -2224,13 +2224,13 @@ function registerExecutor(program2) {
|
|
|
2224
2224
|
if (opts.interval >= opts.ttl)
|
|
2225
2225
|
fail("heartbeat interval must be shorter than the TTL");
|
|
2226
2226
|
const cfg = resolveConfig(cmd.optsWithGlobals());
|
|
2227
|
-
await
|
|
2227
|
+
await refresh(cfg, id, opts.ttl);
|
|
2228
2228
|
process.stderr.write(
|
|
2229
2229
|
style.green("executor heartbeat active") + style.dim(` \u2014 ${id}
|
|
2230
2230
|
`)
|
|
2231
2231
|
);
|
|
2232
2232
|
await holdHeartbeat(async () => {
|
|
2233
|
-
await
|
|
2233
|
+
await refresh(cfg, id, opts.ttl);
|
|
2234
2234
|
}, opts.interval * 1e3);
|
|
2235
2235
|
});
|
|
2236
2236
|
executor.command("offers <id>").description("List live dispatch offers addressed to this exact instance").action(async (id, _opts, cmd) => {
|
|
@@ -2275,7 +2275,7 @@ function parseTransport(value) {
|
|
|
2275
2275
|
return fail("transport must be push or pull");
|
|
2276
2276
|
}
|
|
2277
2277
|
}
|
|
2278
|
-
async function
|
|
2278
|
+
async function refresh(cfg, id, ttlSeconds) {
|
|
2279
2279
|
return api(
|
|
2280
2280
|
cfg,
|
|
2281
2281
|
`/me/executor-instances/${encodeURIComponent(id)}/refresh`,
|
|
@@ -2367,7 +2367,8 @@ function registerChannel(program2) {
|
|
|
2367
2367
|
);
|
|
2368
2368
|
const withFilterOpts = (c) => c.option(
|
|
2369
2369
|
"--name <name>",
|
|
2370
|
-
"
|
|
2370
|
+
"Subscription name (idempotent per name)",
|
|
2371
|
+
"wlp-dispatch"
|
|
2371
2372
|
).option(
|
|
2372
2373
|
"--tag <tag...>",
|
|
2373
2374
|
"Deprecated: executor eligibility comes from the installed capability advertisement"
|
|
@@ -2403,11 +2404,6 @@ function registerChannel(program2) {
|
|
|
2403
2404
|
instance.id
|
|
2404
2405
|
);
|
|
2405
2406
|
await drain();
|
|
2406
|
-
const stopReconciliation = startOfferReconciliation(drain);
|
|
2407
|
-
const stopHeartbeat = startExecutorHeartbeat(
|
|
2408
|
-
() => refreshExecutorInstance(cfg, instance.id, located.state.ttlSeconds),
|
|
2409
|
-
located.state.refreshAfterSeconds * 1e3
|
|
2410
|
-
);
|
|
2411
2407
|
if (json) {
|
|
2412
2408
|
emit(
|
|
2413
2409
|
{
|
|
@@ -2427,12 +2423,7 @@ function registerChannel(program2) {
|
|
|
2427
2423
|
) + style.dim("streaming matched events to stdout; Ctrl-C to stop.\n")
|
|
2428
2424
|
);
|
|
2429
2425
|
}
|
|
2430
|
-
|
|
2431
|
-
await holdOpen(conn);
|
|
2432
|
-
} finally {
|
|
2433
|
-
stopReconciliation();
|
|
2434
|
-
stopHeartbeat();
|
|
2435
|
-
}
|
|
2426
|
+
await holdOpen(conn);
|
|
2436
2427
|
});
|
|
2437
2428
|
withFilterOpts(
|
|
2438
2429
|
channel.command("mcp").description(
|
|
@@ -2473,23 +2464,13 @@ function registerChannel(program2) {
|
|
|
2473
2464
|
instance.id
|
|
2474
2465
|
);
|
|
2475
2466
|
await drain();
|
|
2476
|
-
const stopReconciliation = startOfferReconciliation(drain);
|
|
2477
|
-
const stopHeartbeat = startExecutorHeartbeat(
|
|
2478
|
-
() => refreshExecutorInstance(cfg, instance.id, located.state.ttlSeconds),
|
|
2479
|
-
located.state.refreshAfterSeconds * 1e3
|
|
2480
|
-
);
|
|
2481
2467
|
process.stderr.write(
|
|
2482
2468
|
style.dim(
|
|
2483
2469
|
`sechroom channel (mcp) \u2014 tenant ${cfg.tenant}, executor ${located.state.instanceKey}
|
|
2484
2470
|
`
|
|
2485
2471
|
)
|
|
2486
2472
|
);
|
|
2487
|
-
|
|
2488
|
-
await holdOpen(conn);
|
|
2489
|
-
} finally {
|
|
2490
|
-
stopReconciliation();
|
|
2491
|
-
stopHeartbeat();
|
|
2492
|
-
}
|
|
2473
|
+
await holdOpen(conn);
|
|
2493
2474
|
});
|
|
2494
2475
|
channel.command("install").description(
|
|
2495
2476
|
"Wire `sechroom channel mcp` into the project .mcp.json as a Claude Code channel MCP server (idempotent)"
|
|
@@ -2506,7 +2487,7 @@ function registerChannel(program2) {
|
|
|
2506
2487
|
).option("--dry-run", "Print what would change; write nothing").action((opts) => {
|
|
2507
2488
|
const path = join9(process.cwd(), ".mcp.json");
|
|
2508
2489
|
const dryRun = Boolean(opts.dryRun);
|
|
2509
|
-
const args = ["channel", "mcp"];
|
|
2490
|
+
const args = ["channel", "mcp", "--name", opts.name];
|
|
2510
2491
|
const entry = { command: "sechroom", args };
|
|
2511
2492
|
const config2 = readMcpConfig(path);
|
|
2512
2493
|
config2.mcpServers ??= {};
|
|
@@ -2563,11 +2544,11 @@ function requireExecutorState() {
|
|
|
2563
2544
|
return located;
|
|
2564
2545
|
}
|
|
2565
2546
|
function warnLegacyChannelOptions(opts) {
|
|
2566
|
-
if (
|
|
2547
|
+
if ((opts.workspace?.length ?? 0) === 0 && (opts.tag?.length ?? 0) === 0 && !opts.executorInstance)
|
|
2567
2548
|
return;
|
|
2568
2549
|
process.stderr.write(
|
|
2569
2550
|
style.dim(
|
|
2570
|
-
"channel: --
|
|
2551
|
+
"channel: --workspace, --tag, and --executor-instance are retired; eligibility and identity come from the installed executor advertisement.\n"
|
|
2571
2552
|
)
|
|
2572
2553
|
);
|
|
2573
2554
|
}
|
|
@@ -2584,26 +2565,6 @@ function createClaimDrain(cfg, executorInstanceId, deliver, dependencies = {}) {
|
|
|
2584
2565
|
return active2;
|
|
2585
2566
|
};
|
|
2586
2567
|
}
|
|
2587
|
-
function startOfferReconciliation(drain, intervalMilliseconds = 5e3, dependencies = {}) {
|
|
2588
|
-
const schedule = dependencies.setInterval ?? setInterval;
|
|
2589
|
-
const cancel = dependencies.clearInterval ?? clearInterval;
|
|
2590
|
-
const onError = dependencies.onError ?? ((error) => process.stderr.write(err(`channel claim failed: ${String(error)}
|
|
2591
|
-
`)));
|
|
2592
|
-
const timer = schedule(() => {
|
|
2593
|
-
void drain().catch(onError);
|
|
2594
|
-
}, intervalMilliseconds);
|
|
2595
|
-
return () => cancel(timer);
|
|
2596
|
-
}
|
|
2597
|
-
function startExecutorHeartbeat(refresh, intervalMilliseconds, dependencies = {}) {
|
|
2598
|
-
const schedule = dependencies.setInterval ?? setInterval;
|
|
2599
|
-
const cancel = dependencies.clearInterval ?? clearInterval;
|
|
2600
|
-
const onError = dependencies.onError ?? ((error) => process.stderr.write(err(`channel heartbeat failed: ${String(error)}
|
|
2601
|
-
`)));
|
|
2602
|
-
const timer = schedule(() => {
|
|
2603
|
-
void refresh().catch(onError);
|
|
2604
|
-
}, intervalMilliseconds);
|
|
2605
|
-
return () => cancel(timer);
|
|
2606
|
-
}
|
|
2607
2568
|
async function drainClaims(cfg, executorInstanceId, deliver, dependencies = {}) {
|
|
2608
2569
|
const request = dependencies.request ?? api;
|
|
2609
2570
|
const sleep = dependencies.sleep ?? ((milliseconds) => new Promise((resolve3) => setTimeout(resolve3, milliseconds)));
|
|
@@ -5922,23 +5883,23 @@ Examples:
|
|
|
5922
5883
|
});
|
|
5923
5884
|
emit(data, cmd.optsWithGlobals().json);
|
|
5924
5885
|
});
|
|
5925
|
-
suggestion.command("accept <id>").description("Accept a suggestion (POST /relationship-suggestions/{
|
|
5886
|
+
suggestion.command("accept <id>").description("Accept a suggestion (POST /relationship-suggestions/{id}/accept)").action(async (id, _opts, cmd) => {
|
|
5926
5887
|
const cfg = resolveConfig(cmd.optsWithGlobals());
|
|
5927
5888
|
const data = await runApi("Accepting suggestion", async () => {
|
|
5928
5889
|
const client = await makeClient(cfg);
|
|
5929
|
-
return client.POST("/relationship-suggestions/{
|
|
5930
|
-
params: { path: {
|
|
5890
|
+
return client.POST("/relationship-suggestions/{id}/accept", {
|
|
5891
|
+
params: { path: { id } },
|
|
5931
5892
|
body: {}
|
|
5932
5893
|
});
|
|
5933
5894
|
});
|
|
5934
5895
|
emitAction(`accepted suggestion ${style.bold(id)}`, data, cmd.optsWithGlobals().json);
|
|
5935
5896
|
});
|
|
5936
|
-
suggestion.command("reject <id>").description("Reject a suggestion (POST /relationship-suggestions/{
|
|
5897
|
+
suggestion.command("reject <id>").description("Reject a suggestion (POST /relationship-suggestions/{id}/reject)").option("--reason <reason>", "Why it's being rejected").option("--reason-code <code>", "Structured reason code").action(async (id, opts, cmd) => {
|
|
5937
5898
|
const cfg = resolveConfig(cmd.optsWithGlobals());
|
|
5938
5899
|
const data = await runApi("Rejecting suggestion", async () => {
|
|
5939
5900
|
const client = await makeClient(cfg);
|
|
5940
|
-
return client.POST("/relationship-suggestions/{
|
|
5941
|
-
params: { path: {
|
|
5901
|
+
return client.POST("/relationship-suggestions/{id}/reject", {
|
|
5902
|
+
params: { path: { id } },
|
|
5942
5903
|
body: {
|
|
5943
5904
|
reason: opts.reason ?? null,
|
|
5944
5905
|
...opts.reasonCode ? { reasonCode: opts.reasonCode } : {}
|
|
@@ -6913,56 +6874,6 @@ Examples:
|
|
|
6913
6874
|
});
|
|
6914
6875
|
}
|
|
6915
6876
|
|
|
6916
|
-
// src/commands/work-brief.ts
|
|
6917
|
-
function registerWorkBrief(program2) {
|
|
6918
|
-
const workBrief = program2.command("work-brief").description("Control an active work brief run");
|
|
6919
|
-
workBrief.addHelpText(
|
|
6920
|
-
"after",
|
|
6921
|
-
`
|
|
6922
|
-
Examples:
|
|
6923
|
-
$ sechroom work-brief pause mem_XXXX --reason-code operator-hold --source claude-code-chris
|
|
6924
|
-
$ sechroom work-brief resume mem_XXXX --reason-code operator-resume --source claude-code-chris --reason "Ready to continue"
|
|
6925
|
-
$ sechroom work-brief cancel mem_XXXX --reason-code operator-stopped --source claude-code-chris --reason "Work no longer required"`
|
|
6926
|
-
);
|
|
6927
|
-
registerLifecycleAction(workBrief, "pause");
|
|
6928
|
-
registerLifecycleAction(workBrief, "resume");
|
|
6929
|
-
registerLifecycleAction(workBrief, "cancel");
|
|
6930
|
-
}
|
|
6931
|
-
function registerLifecycleAction(workBrief, action) {
|
|
6932
|
-
const presentParticiple = action === "pause" ? "Pausing" : action === "resume" ? "Resuming" : "Cancelling";
|
|
6933
|
-
const pastTense = action === "pause" ? "paused" : action === "resume" ? "resumed" : "cancelled";
|
|
6934
|
-
workBrief.command(`${action} <briefId>`).description(`${capitalize(action)} an active work brief run`).requiredOption(
|
|
6935
|
-
"--reason-code <code>",
|
|
6936
|
-
"Stable machine-readable reason code"
|
|
6937
|
-
).requiredOption(
|
|
6938
|
-
"--source <source>",
|
|
6939
|
-
"Calling surface or lane recorded in the audit"
|
|
6940
|
-
).option("--reason <text>", "Optional human-readable reason").action(async (briefId, opts, cmd) => {
|
|
6941
|
-
const globals = cmd.optsWithGlobals();
|
|
6942
|
-
const cfg = resolveConfig(globals);
|
|
6943
|
-
const data = await runApi(`${presentParticiple} work brief`, async () => {
|
|
6944
|
-
const client = await makeClient(cfg);
|
|
6945
|
-
return client.POST("/work-briefs/{id}/lifecycle", {
|
|
6946
|
-
params: { path: { id: briefId } },
|
|
6947
|
-
body: {
|
|
6948
|
-
action,
|
|
6949
|
-
reasonCode: opts.reasonCode,
|
|
6950
|
-
source: opts.source,
|
|
6951
|
-
reasonText: opts.reason ?? null
|
|
6952
|
-
}
|
|
6953
|
-
});
|
|
6954
|
-
});
|
|
6955
|
-
emitAction(
|
|
6956
|
-
`${pastTense} work brief ${style.bold(briefId)} \u2192 ${data.outcome}`,
|
|
6957
|
-
data,
|
|
6958
|
-
globals.json
|
|
6959
|
-
);
|
|
6960
|
-
});
|
|
6961
|
-
}
|
|
6962
|
-
function capitalize(value) {
|
|
6963
|
-
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
6964
|
-
}
|
|
6965
|
-
|
|
6966
6877
|
// src/index.ts
|
|
6967
6878
|
function resolveVersion() {
|
|
6968
6879
|
try {
|
|
@@ -7125,7 +7036,6 @@ registerLookup(program);
|
|
|
7125
7036
|
registerRelationships(program);
|
|
7126
7037
|
registerWorkspace(program);
|
|
7127
7038
|
registerProject(program);
|
|
7128
|
-
registerWorkBrief(program);
|
|
7129
7039
|
registerDecomposition(program);
|
|
7130
7040
|
registerExecutor(program);
|
|
7131
7041
|
registerClose(program);
|
package/package.json
CHANGED