@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.
Files changed (2) hide show
  1. package/dist/index.js +17 -107
  2. 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 refreshExecutorInstance(
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 refreshExecutorInstance(cfg, id, opts.ttl);
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 refreshExecutorInstance(cfg, id, opts.ttl);
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 refreshExecutorInstance(cfg, id, ttlSeconds) {
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
- "Deprecated: ignored; the installed executor selects its delivery subscription"
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
- try {
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
- try {
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 (!opts.name && (opts.workspace?.length ?? 0) === 0 && (opts.tag?.length ?? 0) === 0 && !opts.executorInstance)
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: --name, --workspace, --tag, and --executor-instance are retired; delivery, eligibility, and identity come from the installed executor advertisement.\n"
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/{instanceId}/accept)").action(async (id, _opts, cmd) => {
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/{instanceId}/accept", {
5930
- params: { path: { instanceId: id } },
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/{instanceId}/reject)").option("--reason <reason>", "Why it's being rejected").option("--reason-code <code>", "Structured reason code").action(async (id, opts, cmd) => {
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/{instanceId}/reject", {
5941
- params: { path: { instanceId: id } },
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sechroom/cli",
3
- "version": "2026.7.20-rc.5cee4cf5",
3
+ "version": "2026.7.20",
4
4
  "description": "Sechroom CLI — a thin, generated client over the Sechroom HTTP API. An agent/human surface alongside MCP.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",