sentinelayer-cli 0.12.4 → 0.12.5

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/README.md CHANGED
@@ -104,6 +104,7 @@ Inputs for non-interactive mode:
104
104
  Sentinelayer includes a deterministic session coordination surface for multi-agent coding loops:
105
105
 
106
106
  - session event stream and replay (`start`, `join`, `say`, `read`, `status`, `leave`, `list`, `kill`)
107
+ - low-noise message actions (`react ack|like|dislike`, `action working_on|disregard`, `reply`/`comment`, `view`, `actions`)
107
108
  - agent lifecycle controls (join/heartbeat/leave/kill)
108
109
  - recap and context briefing for late-joining agents
109
110
  - analytics + lineage artifacts at session closeout
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sentinelayer-cli",
3
- "version": "0.12.4",
3
+ "version": "0.12.5",
4
4
  "description": "Scaffold Sentinelayer spec/prompt/guide artifacts with secure browser auth and token bootstrap.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -107,13 +107,58 @@ const SESSION_MESSAGE_ACTION_TYPES = new Set([
107
107
  "like",
108
108
  "dislike",
109
109
  "disregard",
110
+ "view",
111
+ ]);
112
+
113
+ const SESSION_MESSAGE_ACTION_ALIASES = new Map([
114
+ ["comment", "reply"],
115
+ ]);
116
+
117
+ const SESSION_MESSAGE_ACTION_DESCRIPTIONS = Object.freeze([
118
+ {
119
+ type: "ack",
120
+ command: "sl session react <id> ack --target-sequence <n>",
121
+ description: "Acknowledge that you read a message without adding a top-level post.",
122
+ },
123
+ {
124
+ type: "working_on",
125
+ command: "sl session action <id> working_on --target-sequence <n> --note \"scope\"",
126
+ description: "Claim active ownership of a target message or task.",
127
+ },
128
+ {
129
+ type: "reply",
130
+ alias: "comment",
131
+ command: "sl session reply <id> <sequence> \"message\"",
132
+ description: "Thread a substantive response under a specific message.",
133
+ },
134
+ {
135
+ type: "like",
136
+ command: "sl session react <id> like --target-sequence <n>",
137
+ description: "Positive lightweight feedback.",
138
+ },
139
+ {
140
+ type: "dislike",
141
+ command: "sl session react <id> dislike --target-sequence <n>",
142
+ description: "Negative lightweight feedback.",
143
+ },
144
+ {
145
+ type: "disregard",
146
+ command: "sl session action <id> disregard --target-sequence <n>",
147
+ description: "Mark a message as intentionally ignored or superseded.",
148
+ },
149
+ {
150
+ type: "view",
151
+ command: "sl session view <id> <sequence>",
152
+ description: "Record a read receipt for a target message.",
153
+ },
110
154
  ]);
111
155
 
112
156
  function normalizeSessionMessageActionType(value) {
113
- const normalized = normalizeString(value).toLowerCase();
157
+ const raw = normalizeString(value).toLowerCase();
158
+ const normalized = SESSION_MESSAGE_ACTION_ALIASES.get(raw) || raw;
114
159
  if (!SESSION_MESSAGE_ACTION_TYPES.has(normalized)) {
115
160
  throw new Error(
116
- `action type must be one of: ${[...SESSION_MESSAGE_ACTION_TYPES].join(", ")}.`,
161
+ `action type must be one of: ${[...SESSION_MESSAGE_ACTION_TYPES].join(", ")}; aliases: comment=reply.`,
117
162
  );
118
163
  }
119
164
  return normalized;
@@ -1837,9 +1882,34 @@ export function registerSessionCommand(program) {
1837
1882
  return payload;
1838
1883
  }
1839
1884
 
1885
+ session
1886
+ .command("actions")
1887
+ .description("List supported low-noise message actions with examples")
1888
+ .option("--json", "Emit machine-readable output")
1889
+ .action((options, command) => {
1890
+ const payload = {
1891
+ command: "session actions",
1892
+ actions: SESSION_MESSAGE_ACTION_DESCRIPTIONS,
1893
+ };
1894
+ if (shouldEmitJson(options, command)) {
1895
+ console.log(JSON.stringify(payload, null, 2));
1896
+ return payload;
1897
+ }
1898
+ console.log(pc.bold("Supported session message actions"));
1899
+ for (const action of SESSION_MESSAGE_ACTION_DESCRIPTIONS) {
1900
+ const alias = action.alias ? ` (alias: ${action.alias})` : "";
1901
+ console.log(`${pc.cyan(action.type)}${alias}`);
1902
+ console.log(` ${action.description}`);
1903
+ console.log(pc.gray(` ${action.command}`));
1904
+ }
1905
+ return payload;
1906
+ });
1907
+
1840
1908
  session
1841
1909
  .command("action <sessionId> <actionType>")
1842
- .description("Create a message action for a target session event")
1910
+ .description(
1911
+ "Create a message action for a target session event (ack, working_on, reply/comment, like, dislike, disregard, view)",
1912
+ )
1843
1913
  .option("--target-sequence <n>", "Target event sequence id")
1844
1914
  .option("--target-cursor <cursor>", "Target event cursor")
1845
1915
  .option("--note <text>", "Optional action note or reply body")
@@ -1894,6 +1964,44 @@ export function registerSessionCommand(program) {
1894
1964
  });
1895
1965
  });
1896
1966
 
1967
+ session
1968
+ .command("comment <sessionId> <targetSequenceId> <message...>")
1969
+ .description("Alias for `session reply`; add a threaded comment to a target event")
1970
+ .option("--agent <id>", "Agent id for local idempotency metadata", "cli-user")
1971
+ .option("--idempotency-key <key>", "Explicit idempotency key")
1972
+ .option("--path <path>", "Workspace path for the session", ".")
1973
+ .option("--json", "Emit machine-readable output")
1974
+ .action(async (sessionId, targetSequenceId, messageParts, options, command) => {
1975
+ const message = Array.isArray(messageParts) ? messageParts.join(" ") : messageParts;
1976
+ await runMessageActionCommand({
1977
+ sessionId,
1978
+ actionType: "reply",
1979
+ options,
1980
+ command,
1981
+ commandName: "session comment",
1982
+ targetSequenceId: parsePositiveInteger(targetSequenceId, "targetSequenceId", 0),
1983
+ note: message,
1984
+ });
1985
+ });
1986
+
1987
+ session
1988
+ .command("view <sessionId> <targetSequenceId>")
1989
+ .description("Record a read receipt for a target session event")
1990
+ .option("--agent <id>", "Agent id for local idempotency metadata", "cli-user")
1991
+ .option("--idempotency-key <key>", "Explicit idempotency key")
1992
+ .option("--path <path>", "Workspace path for the session", ".")
1993
+ .option("--json", "Emit machine-readable output")
1994
+ .action(async (sessionId, targetSequenceId, options, command) => {
1995
+ await runMessageActionCommand({
1996
+ sessionId,
1997
+ actionType: "view",
1998
+ options,
1999
+ command,
2000
+ commandName: "session view",
2001
+ targetSequenceId: parsePositiveInteger(targetSequenceId, "targetSequenceId", 0),
2002
+ });
2003
+ });
2004
+
1897
2005
  session
1898
2006
  .command("listen")
1899
2007
  .description("Background-poll a session for events addressed to this agent or broadcast")
package/src/legacy-cli.js CHANGED
@@ -218,6 +218,12 @@ function printUsage() {
218
218
  console.log(" sl session say <id> \"assign: @agent <task>\" Create task assignment + lease");
219
219
  console.log(" sl session say <id> \"assign: @*:reviewer <task>\" Wildcard route to least-busy role");
220
220
  console.log(" sl session say <id> \"accepted: task <task-id>\" / \"done: task <task-id>\" Task transitions");
221
+ console.log(" sl session actions List low-noise actions and examples");
222
+ console.log(" sl session react <id> ack --target-sequence <n> ACK/like/dislike without a new post");
223
+ console.log(" sl session action <id> working_on --target-sequence <n> Claim work on a message");
224
+ console.log(" sl session reply <id> <seq> \"msg\" Thread a response under a message");
225
+ console.log(" sl session comment <id> <seq> \"msg\" Alias for threaded reply");
226
+ console.log(" sl session view <id> <seq> Record a read receipt");
221
227
  console.log(" sl session read <id> --tail 20 Read session stream events");
222
228
  console.log(" sl session status <id> --json Show session health, agents, runs, leases");
223
229
  console.log(" sl session leave <id> Leave a session");
@@ -6,7 +6,7 @@ export const COORDINATION_ETIQUETTE_ITEMS = Object.freeze([
6
6
  "Before implementation, post a short plan and file claims with `sl session say <id> \"plan: <scope>; files: <paths>\"`.",
7
7
  "Claim shared files before editing with `lock: <file> - <intent>` and release them with `unlock: <file> - done`.",
8
8
  "Run a background listener for replies: `sl session listen --session <id> --agent <your-name> --interval 60 --active-interval 5 --emit ndjson`; this idles at 60s and switches to 5s after human activity. If background polling is unavailable, fall back to `sl session sync <id> --json` then `sl session read <id> --tail 20 --json` every 5 minutes.",
9
- "Use message actions for low-noise coordination: `sl session react <id> ack --target-sequence <n>` for ACKs, `sl session action <id> working_on --target-sequence <n>` for ownership, and `sl session reply <id> <sequence> \"<message>\"` or `sl session say <id> \"<message>\" --reply-to <sequence>` for threaded responses.",
9
+ "Use message actions for low-noise coordination before posting a new top-level message: `sl session react <id> ack --target-sequence <n>` for ACKs, `sl session action <id> working_on --target-sequence <n>` for ownership, `sl session view <id> <sequence>` for read receipts, and `sl session reply <id> <sequence> \"<message>\"` / `sl session comment <id> <sequence> \"<message>\"` for threaded responses. Run `sl session actions` to list all action types.",
10
10
  "Search before asking peers to restate context: `sl session search <id> \"<topic>\" --limit 10`.",
11
11
  "Run `sl review --diff` after each finished file or PR-ready diff and post the result summary back to the session.",
12
12
  "Post findings through `sl session say <id> \"finding: [P2] <title> in <file>:<line>\"` with enough context for a peer to act.",
@@ -418,7 +418,7 @@ const AGENT_JOIN_RULES = [
418
418
  "",
419
419
  "**Writing back** — You can use **markdown**: bold, italic, lists, fenced code, and `inline code`. The web dashboard renders it. Plain text also works. Keep posts terse and technical — link to the work, don't recap it.",
420
420
  "",
421
- "**Actions and threading** — ACK or claim work with message actions instead of top-level chatter: `sl session react <id> ack --target-sequence <n>` or `sl session action <id> working_on --target-sequence <n>`. Reply to a specific message with `sl session reply <id> <sequence> \"<message>\"` or `sl session say <id> \"<message>\" --reply-to <sequence>`; only start a new top-level post for a new topic.",
421
+ "**Actions and threading** — ACK, view, react, or claim work with message actions instead of top-level chatter: `sl session react <id> ack --target-sequence <n>`, `sl session view <id> <sequence>`, or `sl session action <id> working_on --target-sequence <n>`. Reply to a specific message with `sl session reply <id> <sequence> \"<message>\"`, `sl session comment <id> <sequence> \"<message>\"`, or `sl session say <id> \"<message>\" --reply-to <sequence>`; only start a new top-level post for a new topic. Run `sl session actions` for the full list.",
422
422
  "",
423
423
  "**Search before asking** — Use `sl session search <id> \"<topic>\" --limit 10` to recover old context before asking another agent to re-paste or summarize what is already in the transcript.",
424
424
  "",