@sechroom/cli 2026.7.4 → 2026.7.6

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 +49 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1545,6 +1545,7 @@ function registerChannel(program2) {
1545
1545
  const filter = readFilter(opts);
1546
1546
  const sub = await ensureSubscription(cfg, opts.name, filter);
1547
1547
  const conn = await openConnection(cfg, (payload) => {
1548
+ if (!shouldDeliver(payload, filter)) return;
1548
1549
  process.stdout.write(
1549
1550
  (typeof payload === "string" ? payload : JSON.stringify(payload)) + "\n"
1550
1551
  );
@@ -1586,6 +1587,7 @@ function registerChannel(program2) {
1586
1587
  await mcp.connect(new StdioServerTransport());
1587
1588
  await ensureSubscription(cfg, opts.name, filter);
1588
1589
  const conn = await openConnection(cfg, (payload) => {
1590
+ if (!shouldDeliver(payload, filter)) return;
1589
1591
  const { content, meta } = summarizeEvent(payload);
1590
1592
  void mcp.notification({
1591
1593
  method: "notifications/claude/channel",
@@ -1605,7 +1607,10 @@ function registerChannel(program2) {
1605
1607
  });
1606
1608
  channel.command("install").description(
1607
1609
  "Wire `sechroom channel mcp` into the project .mcp.json as a Claude Code channel MCP server (idempotent)"
1608
- ).option("--workspace <wsp...>", "Restrict dispatches to these workspace id(s)").option(
1610
+ ).option(
1611
+ "--workspace <wsp...>",
1612
+ "Restrict dispatches to these workspace id(s)"
1613
+ ).option(
1609
1614
  "--tag <tag...>",
1610
1615
  "Tag(s) a dispatch must carry to match (repeatable). Default targets WLP task dispatches.",
1611
1616
  ["kind:task"]
@@ -1726,20 +1731,58 @@ function holdOpen(conn) {
1726
1731
  process.on("SIGTERM", stop);
1727
1732
  });
1728
1733
  }
1729
- function summarizeEvent(payload) {
1734
+ function parseEvent(payload) {
1730
1735
  let data = payload;
1731
1736
  if (typeof payload === "string") {
1732
1737
  try {
1733
1738
  data = JSON.parse(payload);
1734
1739
  } catch {
1735
- return { content: payload, meta: {} };
1740
+ return { eventType: "", memoryId: "", workspaceId: "", tags: void 0 };
1736
1741
  }
1737
1742
  }
1738
1743
  const obj = data ?? {};
1739
1744
  const inner = obj.data ?? obj;
1740
- const eventType = str(inner.eventType ?? inner.EventType ?? obj.type) || "substrate.event";
1741
- const memoryId = str(inner.memoryId ?? inner.MemoryId);
1742
- const workspaceId = str(inner.workspaceId ?? inner.WorkspaceId);
1745
+ const rawTags = inner.tags ?? inner.Tags;
1746
+ return {
1747
+ eventType: str(inner.eventType ?? inner.EventType ?? obj.type) || "substrate.event",
1748
+ memoryId: str(inner.memoryId ?? inner.MemoryId),
1749
+ workspaceId: str(inner.workspaceId ?? inner.WorkspaceId),
1750
+ tags: Array.isArray(rawTags) ? rawTags.filter((t) => typeof t === "string") : void 0
1751
+ };
1752
+ }
1753
+ function shouldDeliver(payload, filter) {
1754
+ const { workspaceId, tags } = parseEvent(payload);
1755
+ if (filter.workspaceScope.length > 0 && (!workspaceId || !filter.workspaceScope.includes(workspaceId)))
1756
+ return false;
1757
+ if (filter.tags.length > 0) {
1758
+ if (!tags) return false;
1759
+ return facetedTagMatch(tags, filter.tags);
1760
+ }
1761
+ return true;
1762
+ }
1763
+ function facetedTagMatch(eventTags, filterTags) {
1764
+ const have = new Set(eventTags);
1765
+ const groups = /* @__PURE__ */ new Map();
1766
+ for (const f of filterTags) {
1767
+ const ns = f.endsWith(":*") ? f.slice(0, -2) : namespaceOf(f);
1768
+ const group = groups.get(ns) ?? [];
1769
+ group.push(f);
1770
+ groups.set(ns, group);
1771
+ }
1772
+ for (const [ns, group] of groups) {
1773
+ const ok2 = group.some(
1774
+ (f) => f.endsWith(":*") ? eventTags.some((t) => namespaceOf(t) === ns) : have.has(f)
1775
+ );
1776
+ if (!ok2) return false;
1777
+ }
1778
+ return true;
1779
+ }
1780
+ function namespaceOf(tag) {
1781
+ const i = tag.indexOf(":");
1782
+ return i >= 0 ? tag.slice(0, i) : tag;
1783
+ }
1784
+ function summarizeEvent(payload) {
1785
+ const { eventType, memoryId, workspaceId } = parseEvent(payload);
1743
1786
  const content = memoryId ? `${eventType}: ${memoryId}${workspaceId ? ` (workspace ${workspaceId})` : ""}` : typeof payload === "string" ? payload : JSON.stringify(payload);
1744
1787
  const meta = {};
1745
1788
  if (eventType) meta.event_type = eventType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sechroom/cli",
3
- "version": "2026.7.4",
3
+ "version": "2026.7.6",
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",