@mnemom/mnemom 0.17.13 → 0.17.14

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.
@@ -5,11 +5,13 @@
5
5
  * If a customer names no agent, `mnemom agent` launches under a per-customer
6
6
  * governed identity `agent-<handle>`. This module makes that identity REAL in
7
7
  * their Mnemom org: it births the agent through the gateway, claims it (so the
8
- * customer owns it), and publishes a sane default coding posture. The CARDS are
9
- * OFF by default (operator 2026-10-02: alignment and protection analysis are
10
- * billed, so nobody pays for them until they turn them on); the goal contract is
11
- * what nudges (re-anchor on drift). Specifically:
12
- * - alignment card: autonomy_mode + integrity_mode = off,
8
+ * customer owns it), and publishes a sane default coding posture. Governance that
9
+ * costs a model call is OFF by default (operator 2026-10-02: AIP integrity and
10
+ * Safe House analysis are billed, so nobody pays for them until they turn them
11
+ * on); governance that costs none stays ON (operator 2026-10-03: autonomy is
12
+ * rules-only verification + policy). The goal contract is what nudges (re-anchor
13
+ * on drift). Specifically:
14
+ * - alignment card: autonomy_mode = observe, integrity_mode = off,
13
15
  * principal.relationship = delegated_authority, coding bounded/forbidden
14
16
  * actions, escalate-on-irreversible;
15
17
  * - protection card: mode = off, thresholds 0.60/0.80/0.95 and all four
@@ -17,7 +19,8 @@
17
19
  * - goal-alignment: nudge — sealed per-conversation via the goal contract
18
20
  * (--goal …), graded and re-anchored by the gateway.
19
21
  * `--governance [integrity,safe-house]` opts a setup in (observe-only, billed at
20
- * cost on top of the agent fee); a refresh of an already-claimed agent keeps the
22
+ * cost on top of the agent fee); `--no-governance` turns every card off, autonomy
23
+ * included; a refresh of an already-claimed agent keeps the
21
24
  * modes its own cards carry unless a --governance / --no-governance flag says otherwise.
22
25
  *
23
26
  * A launch never runs on an unclaimed agent (operator 2026-10-03): an unclaimed agent lands in
@@ -36,6 +39,12 @@ export type GovernanceMode = "off" | "observe";
36
39
  * the customer pays for at cost, so both are off unless asked for.
37
40
  */
38
41
  export interface GovernanceOptIn {
42
+ /**
43
+ * Autonomy verification + policy (alignment card autonomy_mode). Rules only, no
44
+ * model call, so it is on by default and under every `--governance` choice; only
45
+ * an explicit `--no-governance` turns it off.
46
+ */
47
+ autonomy: boolean;
39
48
  /** AIP integrity analysis (alignment card integrity_mode). */
40
49
  integrity: boolean;
41
50
  /** Safe House screening (protection card mode). */
@@ -45,9 +54,10 @@ export interface GovernanceOptIn {
45
54
  export declare const GOVERNANCE_FEATURES: readonly ["integrity", "safe-house"];
46
55
  /**
47
56
  * Parse the `--governance [features]` / `--no-governance` flag. undefined = not
48
- * given (new agents get none; a refresh keeps the agent's current modes),
49
- * true = every feature, false = none, a string = a comma-separated list of
50
- * `integrity`, `safe-house`, `all` or `none`. Throws on an unknown name.
57
+ * given (new agents get autonomy only; a refresh keeps the agent's current modes),
58
+ * true = every feature, false (`--no-governance`) = everything off, autonomy
59
+ * included, a string = a comma-separated list of `integrity`, `safe-house`, `all`
60
+ * or `none`, each keeping autonomy on. Throws on an unknown name.
51
61
  */
52
62
  export declare function parseGovernanceFlag(value: boolean | string | undefined): GovernanceOptIn | undefined;
53
63
  /**
@@ -55,14 +65,25 @@ export declare function parseGovernanceFlag(value: boolean | string | undefined)
55
65
  * whatever an existing agent's own cards already carry (kept as-is on a refresh).
56
66
  */
57
67
  export interface CardModes {
58
- /** autonomy_mode — verification + policy. No model call, so not billed; kept as-is on a refresh. */
68
+ /** autonomy_mode — verification + policy. No model call, so not billed: observe by default, kept as-is on a refresh. */
59
69
  autonomy: string;
60
70
  integrity: string;
61
71
  protection: string;
72
+ /**
73
+ * enforcement.allow_unmapped_tools. A new observe agent gets true: its card maps no
74
+ * tools to capabilities, so under the deny default every Claude Code tool is an
75
+ * `unmapped_denied` violation (a "fail" verdict every turn, plus an awaited
76
+ * grace-period read). Forbidden-tool and tool_matches escalation rules still apply.
77
+ * A refresh keeps the agent's own value; undefined = write none.
78
+ */
79
+ allowUnmappedTools?: boolean;
62
80
  }
63
81
  /** One phrase for the posture line: "integrity off, Safe House off". */
64
82
  export declare function describeModes(m: Pick<CardModes, "integrity" | "protection">): string;
65
- /** The modes for a NEW agent: off unless --governance asks for a feature. */
83
+ /**
84
+ * The modes for a NEW agent: autonomy observe (rules only, no model call) unless
85
+ * --no-governance; integrity and Safe House off unless --governance asks for them.
86
+ */
66
87
  export declare function newAgentModes(governance?: GovernanceOptIn): CardModes;
67
88
  /** Printed when a setup ran without --governance: how to opt in, and what it costs. */
68
89
  export declare const GOVERNANCE_OPT_IN_HINT: string;
@@ -234,5 +255,5 @@ export declare function resolvePreflightedAccount(): Promise<{
234
255
  orgLabel: string;
235
256
  entitlement: CodeEntitlement | null;
236
257
  }>;
237
- export declare function buildCodeAlignmentCard(agentId: string, modes?: Pick<CardModes, "autonomy" | "integrity">): Record<string, unknown>;
258
+ export declare function buildCodeAlignmentCard(agentId: string, modes?: Pick<CardModes, "autonomy" | "integrity" | "allowUnmappedTools">): Record<string, unknown>;
238
259
  export declare function buildCodeProtectionCard(agentId: string, mode?: string): Record<string, unknown>;
@@ -5,11 +5,13 @@
5
5
  * If a customer names no agent, `mnemom agent` launches under a per-customer
6
6
  * governed identity `agent-<handle>`. This module makes that identity REAL in
7
7
  * their Mnemom org: it births the agent through the gateway, claims it (so the
8
- * customer owns it), and publishes a sane default coding posture. The CARDS are
9
- * OFF by default (operator 2026-10-02: alignment and protection analysis are
10
- * billed, so nobody pays for them until they turn them on); the goal contract is
11
- * what nudges (re-anchor on drift). Specifically:
12
- * - alignment card: autonomy_mode + integrity_mode = off,
8
+ * customer owns it), and publishes a sane default coding posture. Governance that
9
+ * costs a model call is OFF by default (operator 2026-10-02: AIP integrity and
10
+ * Safe House analysis are billed, so nobody pays for them until they turn them
11
+ * on); governance that costs none stays ON (operator 2026-10-03: autonomy is
12
+ * rules-only verification + policy). The goal contract is what nudges (re-anchor
13
+ * on drift). Specifically:
14
+ * - alignment card: autonomy_mode = observe, integrity_mode = off,
13
15
  * principal.relationship = delegated_authority, coding bounded/forbidden
14
16
  * actions, escalate-on-irreversible;
15
17
  * - protection card: mode = off, thresholds 0.60/0.80/0.95 and all four
@@ -17,7 +19,8 @@
17
19
  * - goal-alignment: nudge — sealed per-conversation via the goal contract
18
20
  * (--goal …), graded and re-anchored by the gateway.
19
21
  * `--governance [integrity,safe-house]` opts a setup in (observe-only, billed at
20
- * cost on top of the agent fee); a refresh of an already-claimed agent keeps the
22
+ * cost on top of the agent fee); `--no-governance` turns every card off, autonomy
23
+ * included; a refresh of an already-claimed agent keeps the
21
24
  * modes its own cards carry unless a --governance / --no-governance flag says otherwise.
22
25
  *
23
26
  * A launch never runs on an unclaimed agent (operator 2026-10-03): an unclaimed agent lands in
@@ -47,22 +50,23 @@ const say = (line = "") => console.error(line);
47
50
  export const GOVERNANCE_FEATURES = ["integrity", "safe-house"];
48
51
  /**
49
52
  * Parse the `--governance [features]` / `--no-governance` flag. undefined = not
50
- * given (new agents get none; a refresh keeps the agent's current modes),
51
- * true = every feature, false = none, a string = a comma-separated list of
52
- * `integrity`, `safe-house`, `all` or `none`. Throws on an unknown name.
53
+ * given (new agents get autonomy only; a refresh keeps the agent's current modes),
54
+ * true = every feature, false (`--no-governance`) = everything off, autonomy
55
+ * included, a string = a comma-separated list of `integrity`, `safe-house`, `all`
56
+ * or `none`, each keeping autonomy on. Throws on an unknown name.
53
57
  */
54
58
  export function parseGovernanceFlag(value) {
55
59
  if (value === undefined)
56
60
  return undefined;
57
61
  if (typeof value === "boolean")
58
- return { integrity: value, safeHouse: value };
59
- const choice = { integrity: false, safeHouse: false };
62
+ return { autonomy: value, integrity: value, safeHouse: value };
63
+ const choice = { autonomy: true, integrity: false, safeHouse: false };
60
64
  const names = value
61
65
  .split(",")
62
66
  .map((s) => s.trim().toLowerCase())
63
67
  .filter(Boolean);
64
68
  if (names.length === 0)
65
- return { integrity: true, safeHouse: true };
69
+ return { autonomy: true, integrity: true, safeHouse: true };
66
70
  for (const name of names) {
67
71
  if (name === "all") {
68
72
  choice.integrity = true;
@@ -102,15 +106,23 @@ async function existingAgentCard(kind, agentId) {
102
106
  const sources = await getCardSources(kind, agentId);
103
107
  return sources?.agent?.card_json ?? null;
104
108
  }
105
- /** The modes for a NEW agent: off unless --governance asks for a feature. */
109
+ /**
110
+ * The modes for a NEW agent: autonomy observe (rules only, no model call) unless
111
+ * --no-governance; integrity and Safe House off unless --governance asks for them.
112
+ */
106
113
  export function newAgentModes(governance) {
107
- const integrity = modeOf(governance?.integrity ?? false);
108
- return { autonomy: integrity, integrity, protection: modeOf(governance?.safeHouse ?? false) };
114
+ const autonomy = modeOf(governance?.autonomy ?? true);
115
+ return {
116
+ autonomy,
117
+ integrity: modeOf(governance?.integrity ?? false),
118
+ protection: modeOf(governance?.safeHouse ?? false),
119
+ allowUnmappedTools: autonomy === "observe" ? true : undefined,
120
+ };
109
121
  }
110
122
  /**
111
123
  * The modes for refreshing an EXISTING agent: an explicit --governance /
112
124
  * --no-governance wins; else it keeps the modes its own cards carry. No agent-layer
113
- * card → off (it never had one; new setups are off). A card with no mode field →
125
+ * card → the new-agent defaults (it never had one). A card with no mode field →
114
126
  * observe (the prior CLI always wrote observe). A failed read → null: skip the refresh.
115
127
  */
116
128
  async function existingAgentModes(agentId, governance) {
@@ -129,11 +141,18 @@ async function existingAgentModes(agentId, governance) {
129
141
  say(fmt.dim(" Re-run `mnemom agent setup`, or pass --governance / --no-governance to set them."));
130
142
  return null;
131
143
  }
132
- const integrity = align ? (modeField(align, "integrity_mode") ?? "observe") : "off";
144
+ const fresh = newAgentModes();
145
+ const ownAllow = align?.enforcement
146
+ ?.allow_unmapped_tools;
133
147
  return {
134
- autonomy: align ? (modeField(align, "autonomy_mode") ?? "observe") : "off",
135
- integrity,
136
- protection: prot ? (modeField(prot, "mode") ?? "observe") : "off",
148
+ autonomy: align ? (modeField(align, "autonomy_mode") ?? "observe") : fresh.autonomy,
149
+ integrity: align ? (modeField(align, "integrity_mode") ?? "observe") : fresh.integrity,
150
+ protection: prot ? (modeField(prot, "mode") ?? "observe") : fresh.protection,
151
+ allowUnmappedTools: align
152
+ ? typeof ownAllow === "boolean"
153
+ ? ownAllow
154
+ : undefined
155
+ : fresh.allowUnmappedTools,
137
156
  };
138
157
  }
139
158
  /** Printed when a setup ran without --governance: how to opt in, and what it costs. */
@@ -335,9 +354,9 @@ async function confirmClaimed(opts, anchorKey, fp) {
335
354
  }
336
355
  say(fmt.success(`mnemom agent: claimed '${slug}' (${agentId}) in ${opts.orgLabel}.`));
337
356
  await noteSameNamedAgent(slug, agentId);
338
- // Publish the default cards (off unless --governance). A card write that can't complete does
339
- // NOT undo the claim — the agent is claimed and governed on whatever landed; we warn how to
340
- // finish it.
357
+ // Publish the default cards (autonomy observe; integrity + Safe House off unless
358
+ // --governance). A card write that can't complete does NOT undo the claim — the agent is
359
+ // claimed and governed on whatever landed; we warn how to finish it.
341
360
  if (opts.setup !== false) {
342
361
  await publishDefaultCards(agentId, newAgentModes(opts.governance));
343
362
  if (!opts.governance)
@@ -714,15 +733,21 @@ export async function resolvePreflightedAccount() {
714
733
  return { orgId: active?.org_id ?? entitlement?.org_id ?? "", orgLabel, entitlement };
715
734
  }
716
735
  // ── The default coding posture (cards off; goal contracts nudge) ─────────────
717
- export function buildCodeAlignmentCard(agentId, modes = { autonomy: "off", integrity: "off" }) {
736
+ export function buildCodeAlignmentCard(agentId, modes = {
737
+ autonomy: "off",
738
+ integrity: "off",
739
+ }) {
718
740
  return {
719
741
  card_version: "unified/2026-04-26",
720
742
  agent_id: agentId,
721
743
  // Integrity off ⇒ the gateway skips the AIP checkpoint and the observer skips
722
- // its trace analysis: no model call, no charge. A new agent's autonomy
723
- // (verification + policy) follows it; a refresh keeps the agent's own.
744
+ // its trace analysis: no model call, no charge. Autonomy (verification +
745
+ // policy) is rules only: observe for a new agent; a refresh keeps the agent's own.
724
746
  autonomy_mode: modes.autonomy,
725
747
  integrity_mode: modes.integrity,
748
+ ...(modes.allowUnmappedTools === undefined
749
+ ? {}
750
+ : { enforcement: { allow_unmapped_tools: modes.allowUnmappedTools } }),
726
751
  principal: { type: "agent", identifier: agentId, relationship: "delegated_authority" },
727
752
  values: {
728
753
  declared: ["transparency", "safety", "honesty", "user_control", "harm_prevention"],
@@ -884,8 +884,9 @@ export async function cardEditCommand(agentName, options = {}) {
884
884
  cardYaml = yaml.dump({
885
885
  card_version: "unified/2026-04-26",
886
886
  agent_id: agentId,
887
- autonomy_mode: "off",
887
+ autonomy_mode: "observe",
888
888
  integrity_mode: "off",
889
+ enforcement: { allow_unmapped_tools: true },
889
890
  principal: { type: "agent", identifier: agentId, relationship: "delegated_authority" },
890
891
  values: { declared: ["transparency", "safety", "honesty"] },
891
892
  autonomy: {
@@ -352,8 +352,8 @@ async function earnRating(agentId, steps, say) {
352
352
  }
353
353
  // ── starter alignment card ──────────────────────────────────────────────────────
354
354
  /**
355
- * A starter alignment card, `off` by default (alignment analysis is billed; the
356
- * user turns it on) — the honest, minimal declaration
355
+ * A starter alignment card: autonomy observe (rules only, no model call), integrity
356
+ * `off` (alignment analysis is billed; the user turns it on) — the honest, minimal declaration
357
357
  * of intent for a freshly-onboarded agent. Mirrors the shape `wrap` seeds so the
358
358
  * two skill-runners produce a consistent first card.
359
359
  */
@@ -361,8 +361,10 @@ function buildStarterAlignmentCard(agentId) {
361
361
  return {
362
362
  card_version: "unified/2026-04-26",
363
363
  agent_id: agentId,
364
- autonomy_mode: "off",
364
+ autonomy_mode: "observe",
365
365
  integrity_mode: "off",
366
+ // No capability mappings here, so unmapped tools must pass or every turn fails.
367
+ enforcement: { allow_unmapped_tools: true },
366
368
  principal: { type: "agent", identifier: agentId, relationship: "delegated_authority" },
367
369
  values: { declared: ["transparency", "safety", "honesty"] },
368
370
  autonomy: {
@@ -256,8 +256,10 @@ function buildStarterAlignmentCard(agentId) {
256
256
  return {
257
257
  card_version: "unified/2026-04-26",
258
258
  agent_id: agentId,
259
- autonomy_mode: "off",
259
+ autonomy_mode: "observe",
260
260
  integrity_mode: "off",
261
+ // No capability mappings here, so unmapped tools must pass or every turn fails.
262
+ enforcement: { allow_unmapped_tools: true },
261
263
  principal: { type: "agent", identifier: agentId, relationship: "delegated_authority" },
262
264
  values: { declared: ["transparency", "safety", "honesty"] },
263
265
  autonomy: {
package/dist/index.js CHANGED
@@ -173,8 +173,8 @@ const agentCmd = program
173
173
  .option("--invite <token>", "Redeem a Mnemom Agent invitation (pinv_…): unlocks Mnemom Agent for you + credits your starter µ; launches too when a session name is given")
174
174
  .option("--setup", "Re-check the served agent and refresh its default cards before launch")
175
175
  .option("--no-setup", "Skip the default-card writes (the agent is still confirmed and claimed)")
176
- .option("--governance [features]", "Turn governance ON for the agent's cards: AIP integrity analysis + Safe House screening, observe-only (default: off for new agents). Pick features with a comma list: integrity, safe-house. Billed at cost on top of the agent fee")
177
- .option("--no-governance", "Turn governance OFF for the agent's cards (a card refresh otherwise keeps an existing agent's modes)")
176
+ .option("--governance [features]", "Turn governance ON for the agent's cards: AIP integrity analysis + Safe House screening, observe-only (default: off for new agents; autonomy policy checks are rules only and on either way). Pick features with a comma list: integrity, safe-house. Billed at cost on top of the agent fee")
177
+ .option("--no-governance", "Turn governance OFF for the agent's cards, autonomy policy checks included (by default new agents run autonomy observe, rules only; a card refresh otherwise keeps an existing agent's modes)")
178
178
  .option("--no-yolo", "Do NOT pass --dangerously-skip-permissions (yolo is on by default)")
179
179
  .option("--no-context-hint", "Do NOT seed Claude Code's context-hint feature flag before launch")
180
180
  .addOption(new Option("--slack", "EXPERIMENTAL (`mnemom experimental enable slack`): attach the Slack channel — messages addressed to this session arrive in it, and it can reply (see `mnemom agent slack`)").hideHelp(hiddenUnless("slack")))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnemom/mnemom",
3
- "version": "0.17.13",
3
+ "version": "0.17.14",
4
4
  "description": "Transparent AI agent tracing",
5
5
  "type": "module",
6
6
  "bin": {