@mnemom/mnemom 0.17.24 → 0.17.26

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 (43) hide show
  1. package/dist/commands/agent-config.js +9 -0
  2. package/dist/commands/agent-doctor.d.ts +3 -2
  3. package/dist/commands/agent-doctor.js +22 -7
  4. package/dist/commands/agent-goal.js +7 -2
  5. package/dist/commands/agent-sessions.js +2 -1
  6. package/dist/commands/agent-setup.d.ts +104 -4
  7. package/dist/commands/agent-setup.js +414 -18
  8. package/dist/commands/agent-slack.d.ts +14 -1
  9. package/dist/commands/agent-slack.js +108 -23
  10. package/dist/commands/agent.d.ts +29 -1
  11. package/dist/commands/agent.js +89 -12
  12. package/dist/commands/wrap.d.ts +2 -0
  13. package/dist/commands/wrap.js +13 -1
  14. package/dist/index.js +19 -5
  15. package/dist/lib/agent-identity-route.d.ts +21 -3
  16. package/dist/lib/agent-identity-route.js +42 -15
  17. package/dist/lib/agent-ledger.d.ts +5 -0
  18. package/dist/lib/agent.d.ts +62 -1
  19. package/dist/lib/agent.js +55 -0
  20. package/dist/lib/api.d.ts +33 -1
  21. package/dist/lib/api.js +10 -0
  22. package/dist/lib/experimental.js +14 -2
  23. package/dist/lib/goal-api.d.ts +3 -3
  24. package/dist/lib/goal-api.js +5 -2
  25. package/dist/lib/launcher-config.d.ts +18 -0
  26. package/dist/lib/launcher-config.js +47 -1
  27. package/dist/lib/oauth.d.ts +7 -0
  28. package/dist/lib/oauth.js +92 -17
  29. package/dist/lib/served-agent-cache.d.ts +8 -1
  30. package/dist/lib/served-agent-cache.js +11 -2
  31. package/dist/lib/slack-channel.d.ts +1 -0
  32. package/dist/lib/slack-channel.js +30 -12
  33. package/dist/lib/slack-route.d.ts +72 -9
  34. package/dist/lib/slack-route.js +113 -24
  35. package/dist/lib/slack-router.d.ts +37 -2
  36. package/dist/lib/slack-router.js +98 -13
  37. package/dist/lib/slack-state.d.ts +105 -4
  38. package/dist/lib/slack-state.js +230 -11
  39. package/dist/lib/subscription-login.d.ts +12 -3
  40. package/dist/lib/subscription-login.js +19 -7
  41. package/dist/mcp/handoff-server.mjs +31 -3
  42. package/dist/rc-proxy.mjs +14 -0
  43. package/package.json +1 -1
@@ -175,6 +175,9 @@ function deleteKey(cfg, key) {
175
175
  case "agent":
176
176
  delete cfg.agent;
177
177
  break;
178
+ case "agent_id":
179
+ delete cfg.agentId;
180
+ break;
178
181
  case "effort":
179
182
  delete cfg.effort;
180
183
  break;
@@ -217,6 +220,12 @@ function deleteKey(cfg, key) {
217
220
  case "slack_allow":
218
221
  delete cfg.slackAllow;
219
222
  break;
223
+ case "slack_aliases":
224
+ delete cfg.slackAliases;
225
+ break;
226
+ case "slack_sticky_threads":
227
+ delete cfg.slackStickyThreads;
228
+ break;
220
229
  default:
221
230
  requireSpec(key); // throws the known-keys message for anything unknown
222
231
  }
@@ -43,8 +43,9 @@ export interface GovernanceProbe {
43
43
  * The governance line: the composed (every layer, strictest wins) integrity and
44
44
  * Safe House modes of the agent a launch would use. Signed out, no such agent,
45
45
  * or an unreadable card → info with the off-by-default note, never a MISS
46
- * (governance never blocks a launch). On → info naming the per-turn cost; the
47
- * agent's own card says off but a stricter layer keeps it on → warn.
46
+ * (governance never blocks a launch). On → info naming the per-turn cost; a
47
+ * stricter layer outranks the agent's own card (any rung up the ladder off <
48
+ * observe < nudge < enforce, MNE-8612) → warn naming the layer.
48
49
  */
49
50
  export declare function probeGovernance(agent: string | undefined): Promise<GovernanceProbe>;
50
51
  export {};
@@ -24,7 +24,7 @@ import { isLoggedIn } from "../lib/auth.js";
24
24
  import { getActiveOrg } from "../lib/cli-config.js";
25
25
  import { isCodeNotEnabled, REQUEST_ACCESS_URL, sanitizeTerminalText, sourceLabel, withRequestAccess, } from "./agent-invite.js";
26
26
  import { probeUpdateStatus } from "../lib/update/doctor.js";
27
- import { describeModes, GOVERNANCE_OPT_IN_HINT, resolveDefaultSlug } from "./agent-setup.js";
27
+ import { describeModes, GOVERNANCE_OPT_IN_HINT, layersSettingMode, outranksAgentCard, resolveDefaultSlug, } from "./agent-setup.js";
28
28
  const MARK = { ok: "[ ok ]", warn: "[warn]", miss: "[MISS]", info: "[info]" };
29
29
  const out = (line = "") => console.log(line);
30
30
  /** Run the preflight and print the checklist. Sets process.exitCode on failure. */
@@ -232,8 +232,9 @@ const OPT_IN_HINT = GOVERNANCE_OPT_IN_HINT.trim();
232
232
  * The governance line: the composed (every layer, strictest wins) integrity and
233
233
  * Safe House modes of the agent a launch would use. Signed out, no such agent,
234
234
  * or an unreadable card → info with the off-by-default note, never a MISS
235
- * (governance never blocks a launch). On → info naming the per-turn cost; the
236
- * agent's own card says off but a stricter layer keeps it on → warn.
235
+ * (governance never blocks a launch). On → info naming the per-turn cost; a
236
+ * stricter layer outranks the agent's own card (any rung up the ladder off <
237
+ * observe < nudge < enforce, MNE-8612) → warn naming the layer.
237
238
  */
238
239
  export async function probeGovernance(agent) {
239
240
  const offByDefault = {
@@ -268,13 +269,27 @@ export async function probeGovernance(agent) {
268
269
  protection: read(prot, "agent", "mode"),
269
270
  };
270
271
  const text = `governance: ${slug} — ${describeModes(composed)}`;
271
- const stricter = (mine, eff) => mine === "off" && eff !== "off" && eff !== "unknown";
272
- const overridden = stricter(own.integrity, composed.integrity) || stricter(own.protection, composed.protection);
273
- if (overridden) {
272
+ // A stricter layer outranks the agent's own card on the ladder off < observe <
273
+ // nudge < enforce: name the feature, the mode that runs, and the layer that set it,
274
+ // and point only at the show command for a feature that was outranked.
275
+ const raised = [];
276
+ const shows = [];
277
+ const raise = (feature, mine, eff, sources, field, platformIsFloor, show) => {
278
+ if (!outranksAgentCard(mine, eff))
279
+ return;
280
+ const layers = layersSettingMode(sources, field, eff, { platform: platformIsFloor });
281
+ const from = layers.length > 0 ? ` from ${layers.join(" and ")}` : "";
282
+ raised.push(`${feature} ${eff}${from} (agent card: ${mine})`);
283
+ shows.push(show);
284
+ };
285
+ raise("integrity", own.integrity, composed.integrity, align, "integrity_mode", false, "`mnemom card show` prints the composed alignment card (integrity_mode).");
286
+ raise("Safe House", own.protection, composed.protection, prot, "mode", true, "`mnemom protection show` prints the composed Safe House card.");
287
+ if (raised.length > 0) {
274
288
  return {
275
289
  mark: "warn",
276
290
  text,
277
- hint: "the agent's own card says off, but a stricter org, team or platform policy keeps it on — it still runs and is billed",
291
+ hint: `a stricter org, team or platform policy outranks the agent's own card: ${raised.join(", ")}. ` +
292
+ `The stricter mode is the one that runs and is billed. Change it at that layer. ${shows.join(" ")}`,
278
293
  };
279
294
  }
280
295
  if (composed.integrity === "off" && composed.protection === "off") {
@@ -27,9 +27,14 @@ import { localGoalFlag, resolveSessionRef } from "./agent-sessions.js";
27
27
  * for. Lazy import: commands/agent.ts is the launcher and carries a heavy import graph.
28
28
  */
29
29
  export async function resolveLaunchCreds() {
30
- const { resolveAnthropicKey } = await import("./agent.js");
30
+ const { defaultMnemomKeyDeps, resolveAnthropicKey } = await import("./agent.js");
31
+ const { readMnemomKey } = await import("../lib/subscription-login.js");
31
32
  try {
32
- return { anthropicKey: await resolveAnthropicKey(process.env, { allowPrompt: false }) };
33
+ const anthropicKey = await resolveAnthropicKey(process.env, { allowPrompt: false });
34
+ // The Mnemom key the launch sent beside it (env, else the store; never minted here) — a
35
+ // pinned session's control calls need it, and every call is then asked as the launch was.
36
+ const mnemomKey = readMnemomKey(defaultMnemomKeyDeps());
37
+ return mnemomKey ? { anthropicKey, mnemomKey } : { anthropicKey };
33
38
  }
34
39
  catch {
35
40
  throw new Error("no Anthropic key in env (MNEMOM_AGENT_ANTHROPIC_KEY / ANTHROPIC_API_KEY) or ~/.mnemom/launcher.json — " +
@@ -329,7 +329,8 @@ export function buildShowView(local, remote, reason) {
329
329
  if (local.cc_session_id && local.launch_shape !== "server") {
330
330
  L.push(fmt.label("resume: ", resumeCommand({
331
331
  scenario: local.session,
332
- agent: local.agent_slug,
332
+ // A pinned launch resumes pinned (its served id), never by a name that could birth.
333
+ agent: local.agent_pinned && local.agent_id ? local.agent_id : local.agent_slug,
333
334
  ccSessionId: local.cc_session_id,
334
335
  })));
335
336
  }
@@ -13,7 +13,7 @@
13
13
  * on drift). Specifically:
14
14
  * - alignment card: autonomy_mode = observe, integrity_mode = off,
15
15
  * principal.relationship = delegated_authority, coding bounded/forbidden
16
- * actions, escalate-on-irreversible;
16
+ * actions, no default escalation triggers (the customer adds their own);
17
17
  * - protection card: mode = off, thresholds 0.60/0.80/0.95 and all four
18
18
  * screen_surfaces declared, ready for when it is turned on.
19
19
  * - goal-alignment: nudge — sealed per-conversation via the goal contract
@@ -31,7 +31,7 @@
31
31
  * (agents.ts), claimAgent + putAlignmentCard/putProtectionCard (lib/api.ts) — rather than
32
32
  * reinventing it.
33
33
  */
34
- import { type CodeEntitlement } from "../lib/api.js";
34
+ import { type CardSources, type CodeEntitlement } from "../lib/api.js";
35
35
  /** A card's governance mode as the CLI writes it: off, or observe-only. */
36
36
  export type GovernanceMode = "off" | "observe";
37
37
  /**
@@ -80,6 +80,53 @@ export interface CardModes {
80
80
  }
81
81
  /** One phrase for the posture line: "integrity off, Safe House off". */
82
82
  export declare function describeModes(m: Pick<CardModes, "integrity" | "protection">): string;
83
+ /**
84
+ * The governance mode ladder, weakest first. The same order mnemom-api composes
85
+ * on (compose.ts ALIGNMENT_MODE_ORDER and PROTECTION_MODE_ORDER): strictest wins.
86
+ */
87
+ export declare const MODE_LADDER: readonly ["off", "observe", "nudge", "enforce"];
88
+ /** A mode's rung on MODE_LADDER, or -1 when it is not on the ladder (absent, "unknown"). */
89
+ export declare function modeRank(mode: string | undefined): number;
90
+ /**
91
+ * True when the composed mode sits on a higher rung than the agent's own card, so a
92
+ * stricter layer decides the mode that runs. An agent card that sets no mode, or a
93
+ * composed mode that is not on the ladder, is never an outrank.
94
+ */
95
+ export declare function outranksAgentCard(own: string | undefined, effective: string): boolean;
96
+ /**
97
+ * The upstream layers of a sources envelope whose own card sets `field` to `mode`,
98
+ * named for a person (`team "Lane Leads"`, `org "Acme"`, `platform`), in cascade
99
+ * order. Those are the layers that put the composed mode where it is. `platform`
100
+ * is asked for only where the platform card is a floor (protection mode); for
101
+ * integrity_mode it is only a default, so it never outranks an agent card that
102
+ * sets one. Empty when no layer row matches (an older api without the rows, or a
103
+ * composed card older than a template edit).
104
+ */
105
+ export declare function layersSettingMode(sources: CardSources | null, field: string, mode: string, opts: {
106
+ platform: boolean;
107
+ }): string[];
108
+ /**
109
+ * The composed Safe House (protection) mode for the launch summary, naming the
110
+ * layer that set it when the agent's own card says something else:
111
+ * `enforce (from team "Lane Leads"; agent card: observe)`. Same mode as the
112
+ * agent card prints the mode alone. No composed card reads `unknown`.
113
+ */
114
+ export declare function describeComposedProtection(sources: CardSources | null): string;
115
+ /**
116
+ * How long the launch waits for the protection card sources before printing the
117
+ * line without them. An object so tests can shorten it, like TWIN_LISTING.
118
+ */
119
+ export declare const PROTECTION_READ: {
120
+ timeoutMs: number;
121
+ };
122
+ /**
123
+ * The launch summary's protection phrase for `agentId`: one `getCardSources`
124
+ * read (`GET /v1/protection/agent/:id?include=sources`, the same read the doctor
125
+ * makes), which carries both the composed card and every layer's own card. Best
126
+ * effort: it never throws, so the caller can start it early and await it later,
127
+ * and a failed or slow read prints `unknown` rather than holding up the launch.
128
+ */
129
+ export declare function readComposedProtection(agentId: string): Promise<string>;
83
130
  /**
84
131
  * The modes for a NEW agent: autonomy observe (rules only, no model call) unless
85
132
  * --no-governance; integrity and Safe House off unless --governance asks for them.
@@ -122,8 +169,18 @@ export interface ClaimedAgentOptions {
122
169
  slug: string;
123
170
  /** Anthropic-key launch: the key that anchors the gateway identity. Never logged. */
124
171
  anthropicKey?: string;
125
- /** Subscription launch: the Mnemom API key that anchors the gateway identity. Never logged. */
172
+ /**
173
+ * The Mnemom API key: on a subscription launch it anchors the gateway identity; on an api-key
174
+ * launch (beside `anthropicKey`) it rides along as the key principal, and the identity stays
175
+ * hash(Anthropic key, name). Required with `pin`. Never logged.
176
+ */
126
177
  mnemomKey?: string;
178
+ /**
179
+ * The agent id this launch pins (`--agent mnm-<uuid>` / launcher.toml `agent_id`). The gateway
180
+ * must serve exactly this agent (identity route `resolved_by: "pin"`) or the launch refuses;
181
+ * a pinned launch never claims and never births.
182
+ */
183
+ pin?: string;
127
184
  /** Gateway host the launch targets (the probe goes to the same cell). */
128
185
  gatewayHost: string;
129
186
  /**
@@ -156,6 +213,11 @@ export interface ClaimedAgentResult {
156
213
  agentId: string;
157
214
  /** true only when this call claimed it. */
158
215
  claimedNow: boolean;
216
+ /**
217
+ * The gateway rejected the Mnemom key an api-key launch offered alongside its Anthropic key;
218
+ * the agent was confirmed without it, and the launch must not send it either.
219
+ */
220
+ mnemomKeyRejected?: boolean;
159
221
  }
160
222
  /**
161
223
  * A failure worth retrying, and that an outage fallback may cover: no answer at all (network,
@@ -183,17 +245,55 @@ export declare function isTransient(err: unknown): boolean;
183
245
  * Interactive and non-interactive runs behave the same: there is no prompt to decline.
184
246
  * MNE-7650: the name is client-controlled, so a same-named org agent proves nothing — only the
185
247
  * served id counts.
248
+ *
249
+ * A PINNED launch (`opts.pin`, from `--agent mnm-<uuid>` / launcher.toml `agent_id`) takes a
250
+ * separate path (ensurePinnedAgent): the gateway must serve exactly the pin, and it never claims.
251
+ *
252
+ * An api-key launch that also carries a Mnemom key (`opts.mnemomKey` beside `opts.anthropicKey`)
253
+ * asks the probe with it too, so the answer is the one its requests will get. If the gateway
254
+ * rejects that key, the launch continues without it (result.mnemomKeyRejected) rather than fail.
186
255
  */
187
256
  export declare function ensureClaimedServedAgent(opts: ClaimedAgentOptions): Promise<ClaimedAgentResult>;
257
+ /**
258
+ * How long the anti-twin listing may take before it is treated as failed (best effort). An
259
+ * object so tests can shorten it, like CONFIRM_RETRY_DELAYS_MS.
260
+ */
261
+ export declare const TWIN_LISTING: {
262
+ timeoutMs: number;
263
+ };
264
+ /**
265
+ * The ids of the caller's OTHER live, claimed agents named `slug` in `orgId` — the same set the
266
+ * gateway's principal resolution picks from (claimed_by = the caller). Reads the caller's own
267
+ * agents (`GET /v1/agents?scope=all`), then each same-named one's full record for its claim and
268
+ * org; a tombstoned one (404) is skipped. Throws when the listing can't be completed in
269
+ * TWIN_LISTING.timeoutMs — every caller treats that as "unknown", never as "none".
270
+ */
271
+ export declare function claimedSameNamedAgents(slug: string, excludeId: string, orgId: string): Promise<string[]>;
272
+ /** The refusal when an unclaimed served agent would become a same-named twin. */
273
+ export declare function twinRefusal(slug: string, servedId: string, twins: readonly string[], orgLabel: string): string;
274
+ /**
275
+ * Resolve a pin before launch: the agent must be visible to the caller (the org-member view) and
276
+ * claimed; its name becomes the launch's slug (`x-mnemom-agent`, which the gateway checks against
277
+ * the pin). Any failure refuses — a pinned launch never falls back to a name.
278
+ */
279
+ export declare function resolvePinnedAgent(id: string): Promise<{
280
+ id: string;
281
+ slug: string;
282
+ }>;
188
283
  /**
189
284
  * One line for an api failure that keeps the parts an operator can act on: the
190
285
  * message, the error code, and the scope the endpoint said it needed
191
286
  * (`details.required_scope`). Never the token, never the body.
192
287
  */
193
288
  export declare function describeApiError(err: unknown): string;
194
- /** `mnemom agent setup [--agent <slug>] [--governance …]` — the explicit provisioning entry point. */
289
+ /**
290
+ * `mnemom agent setup [--agent <slug|mnm-id>] [--governance …]` — the explicit provisioning entry
291
+ * point. An id (`--agent mnm-<uuid>`, or launcher.toml `agent_id`) refreshes that pinned agent's
292
+ * cards and never claims or births; a malformed `mnm-…` refuses.
293
+ */
195
294
  export declare function agentSetupCommand(opts?: {
196
295
  agent?: string;
296
+ agentId?: string;
197
297
  governance?: GovernanceOptIn;
198
298
  }): Promise<void>;
199
299
  /** Thrown when the agent's org has no spendable MU balance. The user-facing