sentinelayer-cli 0.46.5 → 0.48.0

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 (133) hide show
  1. package/README.md +47 -3
  2. package/package.json +12 -7
  3. package/skills/omar-gate-setup/SKILL.md +103 -0
  4. package/skills/senti-agent-identity/SKILL.md +80 -0
  5. package/skills/senti-judge/SKILL.md +139 -0
  6. package/skills/senti-room-notifications/SKILL.md +73 -0
  7. package/skills/senti-room-notifications/listen-wrapper.cjs +150 -0
  8. package/skills/senti-room-notifications/package.json +1 -0
  9. package/skills/senti-room-notifications/test-classifier.js +109 -0
  10. package/skills/senti-room-notifications/test-receipt.js +54 -0
  11. package/skills/sentinelayer-cli/SKILL.md +222 -0
  12. package/src/agents/devtestbot/runner.js +22 -11
  13. package/src/agents/devtestbot/tool.js +24 -11
  14. package/src/agents/jules/fix-cycle.js +7 -1
  15. package/src/agents/jules/tools/runtime-audit.js +17 -12
  16. package/src/agents/shared-tools/dispatch-core.js +10 -5
  17. package/src/ai/aidenid.js +4 -2
  18. package/src/ai/domain-target-store.js +11 -5
  19. package/src/ai/identity-store.js +11 -5
  20. package/src/ai/site-store.js +8 -4
  21. package/src/audit/orchestrator.js +21 -14
  22. package/src/audit/package.js +6 -4
  23. package/src/audit/persona-loop.js +7 -0
  24. package/src/audit/replay.js +4 -2
  25. package/src/auth/gate.js +32 -1
  26. package/src/auth/session-store.js +37 -0
  27. package/src/board/evidence-resolvers.js +3 -4
  28. package/src/cli.js +23 -3
  29. package/src/commands/ai/identity-lifecycle.js +30 -26
  30. package/src/commands/ai/provision-governance.js +32 -24
  31. package/src/commands/ai/shared.js +6 -4
  32. package/src/commands/audit.js +14 -12
  33. package/src/commands/board.js +2 -2
  34. package/src/commands/chat.js +8 -6
  35. package/src/commands/judge.js +125 -0
  36. package/src/commands/legacy-args.js +1 -0
  37. package/src/commands/mcp.js +45 -52
  38. package/src/commands/omargate.js +2 -1
  39. package/src/commands/plugin.js +11 -3
  40. package/src/commands/review.js +9 -4
  41. package/src/commands/scan.js +7 -7
  42. package/src/commands/session.js +516 -30
  43. package/src/commands/skills.js +45 -0
  44. package/src/commands/watch.js +9 -7
  45. package/src/config/output-filesystem.js +156 -0
  46. package/src/config/schema.js +4 -2
  47. package/src/config/service.js +40 -4
  48. package/src/cost/history.js +15 -9
  49. package/src/daemon/artifact-lineage.js +15 -12
  50. package/src/daemon/assignment-ledger.js +31 -25
  51. package/src/daemon/ast-drift.js +7 -3
  52. package/src/daemon/budget-governor.js +26 -20
  53. package/src/daemon/error-worker.js +28 -22
  54. package/src/daemon/fix-cycle.js +5 -4
  55. package/src/daemon/hybrid-mapper.js +19 -16
  56. package/src/daemon/ingest-refresh.js +4 -0
  57. package/src/daemon/jira-lifecycle.js +21 -17
  58. package/src/daemon/operator-control.js +18 -15
  59. package/src/daemon/reliability-lane.js +18 -15
  60. package/src/daemon/scope-engine.js +12 -8
  61. package/src/daemon/watchdog.js +15 -12
  62. package/src/engram/build-state.js +24 -3
  63. package/src/engram/capability-index.js +367 -0
  64. package/src/engram/compile-graph.js +1063 -0
  65. package/src/engram/contracts/action-receipt.js +82 -0
  66. package/src/engram/contracts/capability-index.js +259 -0
  67. package/src/engram/contracts/capability.js +377 -0
  68. package/src/engram/contracts/content-hash.js +8 -0
  69. package/src/engram/contracts/evidence.js +258 -0
  70. package/src/engram/contracts/graph.js +594 -0
  71. package/src/engram/contracts/identity.js +8 -0
  72. package/src/engram/contracts/index.js +149 -0
  73. package/src/engram/contracts/media-asset.js +85 -0
  74. package/src/engram/contracts/money.js +249 -0
  75. package/src/engram/contracts/source-snapshot.js +57 -0
  76. package/src/engram/contracts/task-context-pack.js +114 -0
  77. package/src/engram/contracts/temporal-segment.js +72 -0
  78. package/src/engram/contracts/versions.js +96 -0
  79. package/src/engram/extract-html.js +692 -0
  80. package/src/engram/graph-store.js +877 -0
  81. package/src/engram/index.js +98 -14
  82. package/src/engram/ingest-site.js +132 -0
  83. package/src/engram/live-state.js +1180 -0
  84. package/src/engram/namespace.js +34 -1
  85. package/src/engram/retrieve-site.js +753 -0
  86. package/src/engram/safe-reader.js +597 -0
  87. package/src/engram/source-intake.js +251 -0
  88. package/src/engram/store.js +227 -9
  89. package/src/ingest/engine.js +21 -28
  90. package/src/judge/verdict.js +305 -0
  91. package/src/legacy-cli.js +96 -19
  92. package/src/mcp/bridge-inputs.js +25 -4
  93. package/src/mcp/cli-command-tools.js +70 -0
  94. package/src/mcp/registry.js +17 -13
  95. package/src/mcp/session-stdio-server.js +297 -19
  96. package/src/memory/blackboard.js +5 -4
  97. package/src/net/gh-api-path.js +35 -9
  98. package/src/net/test-egress-guard.js +16 -4
  99. package/src/plugin/manifest.js +12 -8
  100. package/src/review/ai-review.js +110 -10
  101. package/src/review/investor-dd-devtestbot.js +17 -6
  102. package/src/review/investor-dd-orchestrator.js +21 -13
  103. package/src/review/local-review.js +26 -16
  104. package/src/review/omargate-cache.js +5 -5
  105. package/src/review/omargate-orchestrator.js +89 -17
  106. package/src/review/replay.js +9 -4
  107. package/src/review/report.js +22 -13
  108. package/src/review/typesafe-severity.js +201 -0
  109. package/src/session/admission-auth.js +34 -7
  110. package/src/session/admission.js +110 -15
  111. package/src/session/attachment-summary.js +77 -0
  112. package/src/session/edit-summary.js +19 -0
  113. package/src/session/invitations.js +65 -1
  114. package/src/session/mentions.js +17 -9
  115. package/src/session/message-edits.js +5 -4
  116. package/src/session/preview.js +10 -2
  117. package/src/session/recap.js +3 -2
  118. package/src/session/room-files.js +519 -0
  119. package/src/session/route-classes.js +22 -8
  120. package/src/session/setup-guides.js +4 -0
  121. package/src/session/standup.js +192 -0
  122. package/src/session/sync.js +229 -10
  123. package/src/session/tickets.js +41 -0
  124. package/src/session/transcript.js +2 -1
  125. package/src/session/wake/resolve-target.js +7 -3
  126. package/src/skills/listener-runtime.cjs +92 -0
  127. package/src/skills/service.js +207 -0
  128. package/src/swarm/factory.js +5 -5
  129. package/src/swarm/pentest.js +9 -9
  130. package/src/swarm/report.js +4 -4
  131. package/src/swarm/runtime.js +15 -12
  132. package/src/swarm/scenario-dsl.js +7 -5
  133. package/src/telemetry/ledger.js +16 -7
@@ -4,7 +4,7 @@ import path from "node:path";
4
4
  import process from "node:process";
5
5
 
6
6
  import { checkedTransport, credentialFor, credentialHmac, isAuthenticated, isCredential } from "../auth/credential-destinations.js";
7
- import { requestJsonMutation } from "../auth/http.js";
7
+ import { requestJson, requestJsonMutation } from "../auth/http.js";
8
8
  import { resolveActiveAuthSession } from "../auth/service.js";
9
9
  import { renderCoordinationBulletList } from "./coordination-guidance.js";
10
10
  import { resolveSessionPaths } from "./paths.js";
@@ -12,8 +12,20 @@ import { urlPathSegment } from "../net/url-path.js";
12
12
 
13
13
  export const SESSION_INVITATION_ACCEPT_ROUTE_ID =
14
14
  "POST /api/v1/sessions/{session_id}/invitations/accept";
15
+ export const PENDING_INVITATION_ACCEPT_ROUTE_ID =
16
+ "POST /api/v1/sessions/invitations/{invitation_id}/accept";
15
17
  export const SESSION_MUTATION_ORIGIN = "https://sentinelayer.com";
16
18
 
19
+ export function throwIfPendingSessionInvitation(payload, status) {
20
+ if ((status !== 403 && status !== 404) || payload?.error?.code !== "INVITATION_PENDING") return;
21
+ const error = new Error(
22
+ "An invitation to this room is waiting. Run `sl session invitations list --json`, then `sl session invitations accept <invitationId>` using its invitationId.",
23
+ );
24
+ error.code = "INVITATION_PENDING";
25
+ error.status = status;
26
+ throw error;
27
+ }
28
+
17
29
  function normalizeString(value) {
18
30
  return String(value || "").trim();
19
31
  }
@@ -85,6 +97,58 @@ export function createSessionMutationIdempotencyKey(operationName = "invitation-
85
97
  return `sl-cli-${operation}-${randomUUID()}`;
86
98
  }
87
99
 
100
+ export async function listPendingSessionInvitations({
101
+ targetPath = process.cwd(),
102
+ resolveAuthSession = resolveActiveAuthSession,
103
+ request = requestJson,
104
+ } = {}) {
105
+ const auth = await resolveAuthSession({ cwd: targetPath, env: process.env, autoRotate: false });
106
+ if (!isAuthenticated(auth) || !auth?.apiUrl) {
107
+ throw new Error("Not authenticated. Run `sl auth login` first.");
108
+ }
109
+ const apiUrl = normalizeString(auth.apiUrl).replace(/\/+$/, "");
110
+ return checkedTransport(request)(`${apiUrl}/api/v1/sessions/invitations/pending`, {
111
+ method: "GET",
112
+ credential: await credentialFor(auth),
113
+ });
114
+ }
115
+
116
+ export async function acceptPendingSessionInvitation(invitationId, {
117
+ targetPath = process.cwd(),
118
+ idempotencyKey = "",
119
+ origin = SESSION_MUTATION_ORIGIN,
120
+ resolveAuthSession = resolveActiveAuthSession,
121
+ requestMutation = requestJsonMutation,
122
+ } = {}) {
123
+ const normalizedInvitationId = typeof invitationId === "string" ? invitationId.trim() : "";
124
+ if (!normalizedInvitationId) throw new Error("invitation id is required.");
125
+ const invitationPath = `/api/v1/sessions/invitations/${urlPathSegment(normalizedInvitationId, { label: "invitationId" })}/accept`;
126
+ const auth = await resolveAuthSession({ cwd: targetPath, env: process.env, autoRotate: false });
127
+ if (!isAuthenticated(auth) || !auth?.apiUrl) {
128
+ throw new Error("Not authenticated. Run `sl auth login` first.");
129
+ }
130
+ const credential = await credentialFor(auth);
131
+ const resolvedIdempotencyKey = normalizeString(idempotencyKey)
132
+ || createSessionMutationIdempotencyKey("session-invite-accept");
133
+ const apiUrl = normalizeString(auth.apiUrl).replace(/\/+$/, "");
134
+ return checkedTransport(requestMutation)(
135
+ `${apiUrl}${invitationPath}`,
136
+ {
137
+ method: "POST",
138
+ operationName: "session.invitation_accept_by_id",
139
+ idempotencyKey: resolvedIdempotencyKey,
140
+ credential,
141
+ headers: createSessionMutationHeaders({
142
+ credential,
143
+ routeId: PENDING_INVITATION_ACCEPT_ROUTE_ID,
144
+ idempotencyKey: resolvedIdempotencyKey,
145
+ origin,
146
+ }),
147
+ body: {},
148
+ },
149
+ );
150
+ }
151
+
88
152
  export async function acceptSessionInvitation(
89
153
  sessionId,
90
154
  {
@@ -21,6 +21,8 @@
21
21
  * punctuation + cap length)
22
22
  */
23
23
 
24
+ import { sessionMessageEditText } from "./edit-summary.js";
25
+
24
26
  // `@handle` is one or more identifier characters. We allow letters,
25
27
  // digits, `._-` so `@codex-1`, `@human-mrrcarter`, `@claude.verifier`
26
28
  // all work. Word boundary on the front avoids matching `you@example.com`.
@@ -97,20 +99,26 @@ export function enrichEventWithMentions(event) {
97
99
  : null;
98
100
  if (!payload) return event;
99
101
 
102
+ // An edit's immutable snapshot retains the original explicit audience.
103
+ const routingPayload = event.event === "session_message_edited"
104
+ ? { ...payload.event?.payload, ...payload }
105
+ : payload;
100
106
  // Already routed by an explicit caller — don't second-guess.
101
107
  const hasExplicitTo =
102
- Array.isArray(payload.to) ||
103
- Array.isArray(payload.recipients) ||
104
- typeof payload.recipient === "string" ||
105
- typeof payload.targetAgent === "string" ||
106
- typeof payload.targetAgentId === "string";
108
+ Array.isArray(routingPayload.to) ||
109
+ Array.isArray(routingPayload.recipients) ||
110
+ typeof routingPayload.recipient === "string" ||
111
+ typeof routingPayload.targetAgent === "string" ||
112
+ typeof routingPayload.targetAgentId === "string";
107
113
 
108
114
  // We pull text from the standard fields the renderer already uses,
109
115
  // matching the priority in `Session.tsx:payloadText`.
110
- const text = normalizeString(payload.message)
111
- || normalizeString(payload.text)
112
- || normalizeString(payload.detail)
113
- || normalizeString(payload.title);
116
+ const text = event.event === "session_message_edited"
117
+ ? sessionMessageEditText(event)
118
+ : normalizeString(payload.message)
119
+ || normalizeString(payload.text)
120
+ || normalizeString(payload.detail)
121
+ || normalizeString(payload.title);
114
122
  if (!text) return event;
115
123
 
116
124
  const parsed = parseMentions(text);
@@ -1,6 +1,7 @@
1
1
  import { createAgentEvent } from "../events/schema.js";
2
2
  import { enrichEventWithMentions } from "./mentions.js";
3
3
  import { sessionEventIdentityKeys } from "./event-identity.js";
4
+ import { sessionMessageEditText } from "./edit-summary.js";
4
5
 
5
6
  export function messageRevision(value = {}) {
6
7
  const revision = Number(value.messageRevision ?? value.message_revision ?? 1);
@@ -79,11 +80,11 @@ export function sessionMessageRoutingEvent(event = {}) {
79
80
  if (!snapshot) return event;
80
81
  const parentPayload = event.payload?.event?.payload || {};
81
82
  const payload = { ...parentPayload, ...snapshot.payload };
82
- if (event.payload?.reply) payload.message = String(event.payload.reply.note ?? "");
83
+ payload.message = sessionMessageEditText(event);
83
84
  for (const key of ["to", "recipient", "recipients", "targetAgent", "targetAgentId", "broadcast", "mentions"]) {
84
85
  if (event.payload[key] !== undefined) payload[key] = event.payload[key];
85
86
  }
86
- const routed = enrichEventWithMentions({ ...snapshot, agent: event.agent || snapshot.agent, payload });
87
- if (routed.payload?.mentions?.broadcast?.length) routed.payload.broadcast = true;
88
- return routed;
87
+ // Use the same recipient precedence as a new message. Broadcast mentions
88
+ // are metadata; only an explicit routing flag can widen the audience.
89
+ return enrichEventWithMentions({ ...snapshot, agent: event.agent || snapshot.agent, payload });
89
90
  }
@@ -7,9 +7,12 @@
7
7
  */
8
8
 
9
9
  import { readStream } from "./stream.js";
10
+ import { appendAttachmentSummary, formatAttachmentSummary } from "./attachment-summary.js";
11
+ import { formatEditSummary } from "./edit-summary.js";
10
12
 
11
13
  const PREVIEW_EVENTS = new Set([
12
14
  "session_message",
15
+ "session_message_edited",
13
16
  "session_say",
14
17
  "agent_response",
15
18
  "session_observation",
@@ -45,14 +48,16 @@ export function pickLatestPreview(events = []) {
45
48
  const kind = String(event.event || event.type || "").trim();
46
49
  if (!kind || !PREVIEW_EVENTS.has(kind)) continue;
47
50
  const payload = event.payload && typeof event.payload === "object" ? event.payload : {};
51
+ const editSummary = formatEditSummary(event);
48
52
  const text =
53
+ editSummary ||
49
54
  payload.summary ||
50
55
  payload.message ||
51
56
  payload.response ||
52
57
  payload.alert ||
53
58
  payload.reason ||
54
59
  payload.text;
55
- if (!text) continue;
60
+ if (!text && !formatAttachmentSummary(event)) continue;
56
61
  return {
57
62
  ts: event.ts || event.timestamp || null,
58
63
  agentId:
@@ -61,7 +66,10 @@ export function pickLatestPreview(events = []) {
61
66
  payload.agentId ||
62
67
  null,
63
68
  kind,
64
- message: trim(text),
69
+ message: appendAttachmentSummary(trim(text), event),
70
+ ...(editSummary ? { editSummary, event } : {}),
71
+ ...(Array.isArray(payload.attachments) && payload.attachments.length
72
+ ? { attachments: payload.attachments } : {}),
65
73
  };
66
74
  }
67
75
  return { ts: null, agentId: null, kind: null, message: null };
@@ -7,6 +7,7 @@ import { createAgentEvent } from "../events/schema.js";
7
7
  import { dedupeSessionEvents } from "./event-identity.js";
8
8
  import { resolveSessionPaths } from "./paths.js";
9
9
  import { readStream } from "./stream.js";
10
+ import { appendAttachmentSummary, formatAttachmentSummary } from "./attachment-summary.js";
10
11
  import { getSession } from "./store.js";
11
12
  import { aggregateSessionUsage } from "./usage.js";
12
13
 
@@ -381,11 +382,11 @@ function summarizeRecentActivity(events = [], { forAgentId = "", limit = 2 } = {
381
382
  const message = normalizeString(
382
383
  payload.message || payload.response || payload.recap || payload.alert || payload.reason
383
384
  );
384
- if (!message) {
385
+ if (!message && !formatAttachmentSummary(event)) {
385
386
  continue;
386
387
  }
387
388
  snippets.push(
388
- `${agentId}${formatSequenceMarker(event)}: ${shortActivitySnippetText(message)}`,
389
+ `${agentId}${formatSequenceMarker(event)}: ${appendAttachmentSummary(shortActivitySnippetText(message), event)}`,
389
390
  );
390
391
  if (snippets.length >= Math.max(1, limit)) {
391
392
  break;