@sechroom/cli 2026.7.10 → 2026.7.11

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 +48 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -633,7 +633,22 @@ async function runApi(label, fn) {
633
633
  return res.data;
634
634
  }
635
635
  function fail(error) {
636
- const msg = typeof error === "object" && error !== null && "title" in error ? String(error.title) : typeof error === "object" ? JSON.stringify(error) : String(error);
636
+ let msg;
637
+ if (typeof error === "object" && error !== null && "title" in error) {
638
+ const problem = error;
639
+ msg = String(problem.title);
640
+ if (problem.errors && typeof problem.errors === "object") {
641
+ const detail = Object.entries(problem.errors).flatMap(
642
+ ([field, msgs]) => (Array.isArray(msgs) ? msgs : [msgs]).map((m) => ` ${field}: ${String(m)}`)
643
+ );
644
+ if (detail.length > 0) msg += `
645
+ ${detail.join("\n")}`;
646
+ }
647
+ } else if (typeof error === "object" && error !== null) {
648
+ msg = JSON.stringify(error);
649
+ } else {
650
+ msg = String(error);
651
+ }
637
652
  process.stderr.write(`error: ${msg}
638
653
  `);
639
654
  process.exit(1);
@@ -2851,12 +2866,12 @@ Examples:
2851
2866
  $ sechroom decomposition reject sug_XXXX --reason "wrong shape"`
2852
2867
  );
2853
2868
  decomposition.command("decompose <briefId>").description(
2854
- "Decompose a governed brief into a candidate Task graph (POST /governed-briefs/{id}/decompose)"
2869
+ "Decompose a work brief into a candidate Task graph (POST /work-briefs/{id}/decompose)"
2855
2870
  ).action(async (briefId, _opts, cmd) => {
2856
2871
  const cfg = resolveConfig(cmd.optsWithGlobals());
2857
2872
  const data = await runApi("Queueing decomposition", async () => {
2858
2873
  const client = await makeClient(cfg);
2859
- return client.POST("/governed-briefs/{id}/decompose", {
2874
+ return client.POST("/work-briefs/{id}/decompose", {
2860
2875
  params: { path: { id: briefId } },
2861
2876
  body: { id: briefId }
2862
2877
  });
@@ -5065,24 +5080,45 @@ Examples:
5065
5080
  $ sechroom relationship suggestions --status Pending --memory mem_XXXX
5066
5081
  $ sechroom relationship suggestion accept rsg_XXXX`
5067
5082
  );
5068
- relationship.command("create <fromMemoryId> <toMemoryId>").description("Create a relationship (POST /memories/{memoryId}/relationships)").option("--type <type>", "Relationship type (Reference, Related, Parent, Child, Follows, \u2026)", "Reference").action(async (fromMemoryId, toMemoryId, opts, cmd) => {
5083
+ relationship.command("create <fromMemoryId> <toMemoryId>").description("Create a relationship (POST /memories/{memoryId}/relationships)").option("--type <type>", "Relationship type (Reference, Related, Parent, Child, Follows, \u2026)", "Reference").option(
5084
+ "--to-version <number>",
5085
+ "Version of the target memory to pin the edge to (defaults to the target's current version)"
5086
+ ).action(async (fromMemoryId, toMemoryId, opts, cmd) => {
5069
5087
  const cfg = resolveConfig(cmd.optsWithGlobals());
5070
- const data = await runApi("Creating relationship", async () => {
5071
- const client = await makeClient(cfg);
5072
- return client.POST("/memories/{memoryId}/relationships", {
5088
+ const client = await makeClient(cfg);
5089
+ let toVersion;
5090
+ if (opts.toVersion !== void 0) {
5091
+ toVersion = Number(opts.toVersion);
5092
+ if (!Number.isInteger(toVersion) || toVersion < 1) {
5093
+ fail(`--to-version must be a positive integer (got '${opts.toVersion}').`);
5094
+ }
5095
+ } else {
5096
+ const target = await runApi(
5097
+ "Resolving target version",
5098
+ async () => client.GET("/memories/{memoryId}", { params: { path: { memoryId: toMemoryId } } })
5099
+ );
5100
+ if (typeof target.item?.currentVersion !== "number") {
5101
+ fail(`Could not resolve the current version of ${toMemoryId}; pass --to-version explicitly.`);
5102
+ }
5103
+ toVersion = target.item.currentVersion;
5104
+ }
5105
+ const data = await runApi(
5106
+ "Creating relationship",
5107
+ async () => client.POST("/memories/{memoryId}/relationships", {
5073
5108
  params: { path: { memoryId: fromMemoryId } },
5074
5109
  body: {
5075
5110
  toMemoryId,
5076
- type: opts.type
5111
+ type: opts.type,
5112
+ toVersion
5077
5113
  }
5078
- });
5079
- });
5114
+ })
5115
+ );
5080
5116
  const inversePart = data.inverseId ? ` ${style.dim(`(inverse ${data.inverseId})`)}` : "";
5081
5117
  const view = resolveViewUrl(cfg.baseUrl, data.url);
5082
5118
  const urlPart = view ? ` ${style.dim("\u2192")} ${view}` : "";
5083
5119
  emitAction(
5084
- `created relationship ${style.bold(data.id)} ${style.dim(`${fromMemoryId} \u2192 ${toMemoryId}`)}${inversePart}${urlPart}`,
5085
- data,
5120
+ `created relationship ${style.bold(data.id)} ${style.dim(`${fromMemoryId} \u2192 ${toMemoryId} @v${toVersion}`)}${inversePart}${urlPart}`,
5121
+ { ...data, toVersion },
5086
5122
  cmd.optsWithGlobals().json
5087
5123
  );
5088
5124
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sechroom/cli",
3
- "version": "2026.7.10",
3
+ "version": "2026.7.11",
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",