@mnemom/mnemom 0.17.38-next.0 → 0.17.38-next.2

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 (79) hide show
  1. package/dist/commands/agent-doctor.d.ts +2 -2
  2. package/dist/commands/agent-doctor.js +4 -4
  3. package/dist/commands/agent-run.d.ts +10 -2
  4. package/dist/commands/agent-run.js +12 -6
  5. package/dist/commands/agent-setup.d.ts +11 -9
  6. package/dist/commands/agent-setup.js +24 -19
  7. package/dist/commands/card.js +1 -1
  8. package/dist/commands/onboard.js +5 -4
  9. package/dist/commands/scan.d.ts +21 -7
  10. package/dist/commands/scan.js +93 -56
  11. package/dist/commands/verify-card.d.ts +25 -1
  12. package/dist/commands/verify-card.js +29 -2
  13. package/dist/commands/wrap.js +4 -3
  14. package/dist/index.js +7 -5
  15. package/dist/lib/runner/executor-client.d.ts +6 -0
  16. package/dist/lib/runner/executor-client.js +6 -0
  17. package/dist/lib/runner/job.d.ts +12 -3
  18. package/dist/lib/runner/job.js +30 -2
  19. package/dist/lib/scan/caps.d.ts +1 -35
  20. package/dist/lib/scan/caps.js +2 -67
  21. package/dist/lib/scan/cost-per-pr.d.ts +1 -93
  22. package/dist/lib/scan/cost-per-pr.js +2 -101
  23. package/dist/lib/scan/credential.d.ts +2 -26
  24. package/dist/lib/scan/credential.js +5 -58
  25. package/dist/lib/scan/failure.d.ts +1 -10
  26. package/dist/lib/scan/failure.js +2 -43
  27. package/dist/lib/scan/pr-source.d.ts +1 -57
  28. package/dist/lib/scan/pr-source.js +2 -132
  29. package/dist/lib/scan/report-email.d.ts +9 -89
  30. package/dist/lib/scan/report-email.js +76 -92
  31. package/dist/lib/scan/scan.d.ts +1 -67
  32. package/dist/lib/scan/scan.js +2 -194
  33. package/dist/lib/scan/share.d.ts +10 -6
  34. package/dist/lib/scan/share.js +28 -11
  35. package/dist/lib/scan/spend/ai-tool-detect.d.ts +1 -6
  36. package/dist/lib/scan/spend/ai-tool-detect.js +2 -18
  37. package/dist/lib/scan/spend/anthropic-usage.d.ts +1 -76
  38. package/dist/lib/scan/spend/anthropic-usage.js +2 -269
  39. package/dist/lib/scan/spend/prices.d.ts +1 -33
  40. package/dist/lib/scan/spend/prices.js +2 -57
  41. package/dist/lib/scan/spend/spend-estimate.d.ts +1 -30
  42. package/dist/lib/scan/spend/spend-estimate.js +2 -70
  43. package/dist/lib/scan/spend/spend-tiers.d.ts +1 -16
  44. package/dist/lib/scan/spend/spend-tiers.js +6 -26
  45. package/dist/lib/scan/spend/token-rate.d.ts +1 -30
  46. package/dist/lib/scan/spend/token-rate.js +2 -54
  47. package/dist/lib/starter-integrity.d.ts +20 -0
  48. package/dist/lib/starter-integrity.js +28 -0
  49. package/dist/vendor/shared/org-scan-core/caps.d.ts +35 -0
  50. package/dist/vendor/shared/org-scan-core/caps.js +68 -0
  51. package/dist/vendor/shared/org-scan-core/cost-per-pr.d.ts +93 -0
  52. package/dist/vendor/shared/org-scan-core/cost-per-pr.js +101 -0
  53. package/dist/vendor/shared/org-scan-core/credential.d.ts +43 -0
  54. package/dist/vendor/shared/org-scan-core/credential.js +74 -0
  55. package/dist/vendor/shared/org-scan-core/failure.d.ts +10 -0
  56. package/dist/vendor/shared/org-scan-core/failure.js +43 -0
  57. package/dist/vendor/shared/org-scan-core/index.d.ts +18 -0
  58. package/dist/vendor/shared/org-scan-core/index.js +19 -0
  59. package/dist/vendor/shared/org-scan-core/pr-source.d.ts +61 -0
  60. package/dist/vendor/shared/org-scan-core/pr-source.js +138 -0
  61. package/dist/vendor/shared/org-scan-core/report-build.d.ts +120 -0
  62. package/dist/vendor/shared/org-scan-core/report-build.js +119 -0
  63. package/dist/vendor/shared/org-scan-core/scan.d.ts +75 -0
  64. package/dist/vendor/shared/org-scan-core/scan.js +202 -0
  65. package/dist/vendor/shared/org-scan-core/spend/ai-tool-detect.d.ts +6 -0
  66. package/dist/vendor/shared/org-scan-core/spend/ai-tool-detect.js +18 -0
  67. package/dist/vendor/shared/org-scan-core/spend/anthropic-usage.d.ts +76 -0
  68. package/dist/vendor/shared/org-scan-core/spend/anthropic-usage.js +270 -0
  69. package/dist/{lib/scan → vendor/shared/org-scan-core}/spend/cost-corpus.v1.js +1 -0
  70. package/dist/vendor/shared/org-scan-core/spend/prices.d.ts +33 -0
  71. package/dist/vendor/shared/org-scan-core/spend/prices.js +58 -0
  72. package/dist/vendor/shared/org-scan-core/spend/spend-estimate.d.ts +30 -0
  73. package/dist/vendor/shared/org-scan-core/spend/spend-estimate.js +71 -0
  74. package/dist/vendor/shared/org-scan-core/spend/spend-select.d.ts +16 -0
  75. package/dist/vendor/shared/org-scan-core/spend/spend-select.js +26 -0
  76. package/dist/vendor/shared/org-scan-core/spend/token-rate.d.ts +30 -0
  77. package/dist/vendor/shared/org-scan-core/spend/token-rate.js +55 -0
  78. package/package.json +2 -2
  79. /package/dist/{lib/scan → vendor/shared/org-scan-core}/spend/cost-corpus.v1.d.ts +0 -0
@@ -10,7 +10,7 @@
10
10
  * (200 + the x-mnemom-verdict header that proves the governance pipeline is
11
11
  * live), Remote-Control capability (node + openssl + the --remote-control flag),
12
12
  * claude.ai login (informational — Remote Control needs it), the agent's governance
13
- * modes (off by default for new agents), and CLI auto-update status.
13
+ * modes (integrity observe, Safe House off for new agents), and CLI auto-update status.
14
14
  */
15
15
  type Mark = "ok" | "warn" | "miss" | "info";
16
16
  export interface DoctorOptions {
@@ -51,7 +51,7 @@ export interface GovernanceProbe {
51
51
  /**
52
52
  * The governance line: the composed (every layer, strictest wins) integrity and
53
53
  * Safe House modes of the agent a launch would use. Signed out, no such agent,
54
- * or an unreadable card → info with the off-by-default note, never a MISS
54
+ * or an unreadable card → info with the new-agent default note, never a MISS
55
55
  * (governance never blocks a launch). On → info naming the per-turn cost; a
56
56
  * stricter layer outranks the agent's own card (any rung up the ladder off <
57
57
  * observe < nudge < enforce, MNE-8612) → warn naming the layer.
@@ -10,7 +10,7 @@
10
10
  * (200 + the x-mnemom-verdict header that proves the governance pipeline is
11
11
  * live), Remote-Control capability (node + openssl + the --remote-control flag),
12
12
  * claude.ai login (informational — Remote Control needs it), the agent's governance
13
- * modes (off by default for new agents), and CLI auto-update status.
13
+ * modes (integrity observe, Safe House off for new agents), and CLI auto-update status.
14
14
  */
15
15
  import { spawnSync } from "node:child_process";
16
16
  import { existsSync } from "node:fs";
@@ -119,7 +119,7 @@ export async function agentDoctorCommand(options = {}) {
119
119
  add("info", "claude.ai login: could not determine");
120
120
  }
121
121
  add(gate.mark, gate.text, gate.hint);
122
- // ── governance (off by default for new agents) ──
122
+ // ── governance (integrity observe, Safe House off for new agents) ──
123
123
  const gov = await probeGovernance(options.agent);
124
124
  add(gov.mark, gov.text, gov.hint);
125
125
  // ── CLI auto-update ──
@@ -236,7 +236,7 @@ const OPT_IN_HINT = GOVERNANCE_OPT_IN_HINT.trim();
236
236
  /**
237
237
  * The governance line: the composed (every layer, strictest wins) integrity and
238
238
  * Safe House modes of the agent a launch would use. Signed out, no such agent,
239
- * or an unreadable card → info with the off-by-default note, never a MISS
239
+ * or an unreadable card → info with the new-agent default note, never a MISS
240
240
  * (governance never blocks a launch). On → info naming the per-turn cost; a
241
241
  * stricter layer outranks the agent's own card (any rung up the ladder off <
242
242
  * observe < nudge < enforce, MNE-8612) → warn naming the layer.
@@ -244,7 +244,7 @@ const OPT_IN_HINT = GOVERNANCE_OPT_IN_HINT.trim();
244
244
  export async function probeGovernance(agent) {
245
245
  const offByDefault = {
246
246
  mark: "info",
247
- text: "governance: off by default for new agents (AIP integrity analysis, Safe House screening)",
247
+ text: "governance: new agents get AIP integrity analysis (observe); Safe House screening is off by default",
248
248
  hint: `${OPT_IN_HINT} Agents set up before this default keep their cards.`,
249
249
  };
250
250
  if (!(await isLoggedIn()))
@@ -8,7 +8,9 @@
8
8
  * errors exit 2 with no outcome line; every outcome line goes to stdout, every log to stderr.
9
9
  *
10
10
  * The GitHub token (GH_TOKEN, GITHUB_TOKEN, else `gh auth token`) is the runner's own: it reaches
11
- * git only through GIT_CONFIG_* env (never argv) and the phases never see it (phaseEnv).
11
+ * git only through GIT_CONFIG_* env (never argv) and the phases never see it (phaseEnv). Under
12
+ * --oidc the PR is pushed and opened with the job's PR token instead (ruling 34.34): the api's
13
+ * Record App token for the seal's repo, fetched with the lease key, carried the same way.
12
14
  *
13
15
  * So is the Anthropic key (ruling 34.30.1): the phases' model calls are billed to the runner's own
14
16
  * ANTHROPIC_API_KEY, which only the model proxy holds and sets on each upstream request. A runner
@@ -35,7 +37,9 @@ export interface RunDeps {
35
37
  stop: AbortSignal;
36
38
  /** The text of this host's executor-state.json, or null when there is none. */
37
39
  readExecutorState?(): Promise<string | null>;
38
- jobDeps(api: RunnerApi, executorId: string | null, github: GithubBases, modelKey: string): JobDeps;
40
+ jobDeps(api: RunnerApi, executorId: string | null, github: GithubBases, modelKey: string,
41
+ /** True under --oidc: the job opens its PR with the api's PR token (ruling 34.34). */
42
+ prTokenFromLease: boolean): JobDeps;
39
43
  }
40
44
  /** The refusal of a runner with no ANTHROPIC_API_KEY (34.30.1); a config error, exit 2. */
41
45
  export declare const RUNNER_MODEL_KEY_MISSING = "runner_model_key_missing";
@@ -78,6 +82,10 @@ export declare function liveJobDeps(api: RunnerApi, opts: {
78
82
  executorId: string | null;
79
83
  github: GithubBases;
80
84
  modelKey: string;
85
+ /** The credential is the --oidc exchange: the PR uses the job's PR token (ruling 34.34). */
86
+ prTokenFromLease?: boolean;
87
+ /** The git runner for an env; tests inject one to see which credentials a push carries. */
88
+ makeGit?: (env: NodeJS.ProcessEnv) => Git;
81
89
  }): JobDeps;
82
90
  /** The process wiring: signals, stdout and stderr. Resolves the exit code. */
83
91
  export declare function runAgentRun(flags: RunFlags): Promise<number>;
@@ -8,7 +8,9 @@
8
8
  * errors exit 2 with no outcome line; every outcome line goes to stdout, every log to stderr.
9
9
  *
10
10
  * The GitHub token (GH_TOKEN, GITHUB_TOKEN, else `gh auth token`) is the runner's own: it reaches
11
- * git only through GIT_CONFIG_* env (never argv) and the phases never see it (phaseEnv).
11
+ * git only through GIT_CONFIG_* env (never argv) and the phases never see it (phaseEnv). Under
12
+ * --oidc the PR is pushed and opened with the job's PR token instead (ruling 34.34): the api's
13
+ * Record App token for the seal's repo, fetched with the lease key, carried the same way.
12
14
  *
13
15
  * So is the Anthropic key (ruling 34.30.1): the phases' model calls are billed to the runner's own
14
16
  * ANTHROPIC_API_KEY, which only the model proxy holds and sets on each upstream request. A runner
@@ -91,7 +93,7 @@ export async function agentRunCommand(flags, deps) {
91
93
  }
92
94
  const api = runnerApi({ apiUrl: deps.apiUrl, executorKey, fetch: deps.fetch });
93
95
  const loop = { failMode: plan.failMode, stop: deps.stop, emit: deps.emit };
94
- const job = deps.jobDeps(api, executorId, gh.bases, modelKey);
96
+ const job = deps.jobDeps(api, executorId, gh.bases, modelKey, plan.credential.kind === "oidc");
95
97
  return plan.form === "once" ? runOnce(job, loop) : runWatch(job, loop);
96
98
  }
97
99
  // ── GitHub and git, for the live driver ──────────────────────────────────────
@@ -259,7 +261,10 @@ export function runPhaseProcess(inv, ws, modelUrl, signal, parentEnv = process.e
259
261
  export function liveJobDeps(api, opts) {
260
262
  const gh = opts.github;
261
263
  const token = resolveGithubToken(opts.env);
262
- const git = liveGit(gitAuthEnv(opts.env, token, gh.web));
264
+ const makeGit = opts.makeGit ?? liveGit;
265
+ const git = makeGit(gitAuthEnv(opts.env, token, gh.web));
266
+ // The PR token's git: a fresh env, so its header replaces the runner token's, never adds to it.
267
+ const gitFor = (t) => t === null ? git : makeGit(gitAuthEnv(opts.env, t, gh.web));
263
268
  return {
264
269
  api,
265
270
  executorId: opts.executorId,
@@ -272,11 +277,12 @@ export function liveJobDeps(api, opts) {
272
277
  startProxy: (state) => startModelProxy(`${getGatewayUrl()}/anthropic`, state, opts.modelKey),
273
278
  prepareWorkspace: (repo, sessionId) => prepareWorkspace(git, `${gh.web}/${repo}.git`, sessionId),
274
279
  runPhase: (inv, ws, modelUrl, signal) => runPhaseProcess(inv, ws, modelUrl, signal, opts.env),
275
- openPr: (repo, ws, title, body) => openPr(git, opts.fetch, token, repo, ws, title, body, gh.api),
280
+ openPr: (repo, ws, title, body, prToken) => openPr(gitFor(prToken), opts.fetch, prToken ?? token, repo, ws, title, body, gh.api),
276
281
  commitsAhead: (ws) => commitsAhead(git, ws),
277
282
  headSha: (ws) => headSha(git, ws),
278
283
  commitBodies: (ws, since, lineageKey, repo) => commitBodies(git, ws, since, lineageKey, repo),
279
- enableAutoMerge: (prUrl) => enableAutoMerge(opts.fetch, token, prUrl, gh),
284
+ enableAutoMerge: (prUrl, prToken) => enableAutoMerge(opts.fetch, prToken ?? token, prUrl, gh),
285
+ prTokenFromLease: opts.prTokenFromLease === true,
280
286
  cleanup: cleanupWorkspace,
281
287
  };
282
288
  }
@@ -296,7 +302,7 @@ export function runAgentRun(flags) {
296
302
  err: (line) => process.stderr.write(`${line}\n`),
297
303
  stop: stop.signal,
298
304
  readExecutorState: () => readFile(executorStatePath(homedir()), "utf8").catch(() => null),
299
- jobDeps: (api, executorId, github, modelKey) => liveJobDeps(api, { fetch, env: process.env, executorId, github, modelKey }),
305
+ jobDeps: (api, executorId, github, modelKey, prTokenFromLease) => liveJobDeps(api, { fetch, env: process.env, executorId, github, modelKey, prTokenFromLease }),
300
306
  }).finally(() => {
301
307
  process.off("SIGTERM", onSignal);
302
308
  process.off("SIGINT", onSignal);
@@ -6,12 +6,13 @@
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
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
9
+ * costs a model call is split (operator 2026-11-04, MNE-9728, matching the API new-agent
10
+ * default): AIP integrity analysis is ON (observe) for a new agent so it is analyzed and can earn
11
+ * a reputation rating, billed at cost; Safe House screening stays OFF until asked for (operator
12
+ * 2026-10-02); governance that costs none stays ON (operator 2026-10-03: autonomy is
12
13
  * rules-only verification + policy). The goal contract is what nudges (re-anchor
13
14
  * on drift). Specifically:
14
- * - alignment card: autonomy_mode = observe, integrity_mode = off, the agent's
15
+ * - alignment card: autonomy_mode = observe, integrity_mode = observe, the agent's
15
16
  * org as principal (delegated_authority), Claude Code tool names as bounded
16
17
  * actions, coding forbidden actions, defined values, grace 0, and no default
17
18
  * escalation trigger for irreversible operations (the customer adds their own);
@@ -22,8 +23,8 @@
22
23
  * older default's content and keeps the agent's modes.
23
24
  * - goal-alignment: nudge — sealed per-conversation via the goal contract
24
25
  * (--goal …), graded and re-anchored by the gateway.
25
- * `--governance [integrity,safe-house]` opts a setup in (observe-only, billed at
26
- * cost on top of the agent fee); `--no-governance` turns every card off, autonomy
26
+ * `--governance [integrity,safe-house]` picks exactly those features on (observe-only,
27
+ * billed at cost on top of the agent fee; `--governance none` opts out of both); `--no-governance` turns every card off, autonomy
27
28
  * included; a refresh of an already-claimed agent keeps the
28
29
  * modes its own cards carry unless a --governance / --no-governance flag says otherwise.
29
30
  *
@@ -40,7 +41,8 @@ import { type CardSources, type CodeEntitlement } from "../lib/api.js";
40
41
  export type GovernanceMode = "off" | "observe";
41
42
  /**
42
43
  * The governance features a setup turns on. Each is a model call per turn that
43
- * the customer pays for at cost, so both are off unless asked for.
44
+ * the customer pays for at cost. Integrity is on for a new agent (opt out with `--governance none`
45
+ * or `--no-governance`); Safe House is off unless asked for.
44
46
  */
45
47
  export interface GovernanceOptIn {
46
48
  /**
@@ -58,7 +60,7 @@ export interface GovernanceOptIn {
58
60
  export declare const GOVERNANCE_FEATURES: readonly ["integrity", "safe-house"];
59
61
  /**
60
62
  * Parse the `--governance [features]` / `--no-governance` flag. undefined = not
61
- * given (new agents get autonomy only; a refresh keeps the agent's current modes),
63
+ * given (new agents get autonomy + integrity; a refresh keeps the agent's current modes),
62
64
  * true = every feature, false (`--no-governance`) = everything off, autonomy
63
65
  * included, a string = a comma-separated list of `integrity`, `safe-house`, `all`
64
66
  * or `none`, each keeping autonomy on. Throws on an unknown name.
@@ -140,7 +142,7 @@ interface ExistingCards {
140
142
  align: Record<string, unknown> | null;
141
143
  prot: Record<string, unknown> | null;
142
144
  }
143
- /** Printed when a setup ran without --governance: how to opt in, and what it costs. */
145
+ /** Printed when a setup ran without --governance: what is on by default, how to change it, and what it costs. */
144
146
  export declare const GOVERNANCE_OPT_IN_HINT: string;
145
147
  /**
146
148
  * The default governed-agent slug for the current customer: `agent-<handle>`,
@@ -6,12 +6,13 @@
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
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
9
+ * costs a model call is split (operator 2026-11-04, MNE-9728, matching the API new-agent
10
+ * default): AIP integrity analysis is ON (observe) for a new agent so it is analyzed and can earn
11
+ * a reputation rating, billed at cost; Safe House screening stays OFF until asked for (operator
12
+ * 2026-10-02); governance that costs none stays ON (operator 2026-10-03: autonomy is
12
13
  * rules-only verification + policy). The goal contract is what nudges (re-anchor
13
14
  * on drift). Specifically:
14
- * - alignment card: autonomy_mode = observe, integrity_mode = off, the agent's
15
+ * - alignment card: autonomy_mode = observe, integrity_mode = observe, the agent's
15
16
  * org as principal (delegated_authority), Claude Code tool names as bounded
16
17
  * actions, coding forbidden actions, defined values, grace 0, and no default
17
18
  * escalation trigger for irreversible operations (the customer adds their own);
@@ -22,8 +23,8 @@
22
23
  * older default's content and keeps the agent's modes.
23
24
  * - goal-alignment: nudge — sealed per-conversation via the goal contract
24
25
  * (--goal …), graded and re-anchored by the gateway.
25
- * `--governance [integrity,safe-house]` opts a setup in (observe-only, billed at
26
- * cost on top of the agent fee); `--no-governance` turns every card off, autonomy
26
+ * `--governance [integrity,safe-house]` picks exactly those features on (observe-only,
27
+ * billed at cost on top of the agent fee; `--governance none` opts out of both); `--no-governance` turns every card off, autonomy
27
28
  * included; a refresh of an already-claimed agent keeps the
28
29
  * modes its own cards carry unless a --governance / --no-governance flag says otherwise.
29
30
  *
@@ -55,7 +56,7 @@ const say = (line = "") => console.error(line);
55
56
  export const GOVERNANCE_FEATURES = ["integrity", "safe-house"];
56
57
  /**
57
58
  * Parse the `--governance [features]` / `--no-governance` flag. undefined = not
58
- * given (new agents get autonomy only; a refresh keeps the agent's current modes),
59
+ * given (new agents get autonomy + integrity; a refresh keeps the agent's current modes),
59
60
  * true = every feature, false (`--no-governance`) = everything off, autonomy
60
61
  * included, a string = a comma-separated list of `integrity`, `safe-house`, `all`
61
62
  * or `none`, each keeping autonomy on. Throws on an unknown name.
@@ -219,15 +220,16 @@ export function newAgentModes(governance) {
219
220
  const autonomy = modeOf(governance?.autonomy ?? true);
220
221
  return {
221
222
  autonomy,
222
- integrity: modeOf(governance?.integrity ?? false),
223
+ integrity: modeOf(governance?.integrity ?? true),
223
224
  protection: modeOf(governance?.safeHouse ?? false),
224
225
  allowUnmappedTools: autonomy === "observe" ? true : undefined,
225
226
  };
226
227
  }
227
228
  /**
228
229
  * The plan for refreshing an EXISTING agent: an explicit --governance /
229
- * --no-governance wins; else it keeps the modes its own cards carry. No agent-layer
230
- * card → the new-agent defaults (it never had one). A card with no mode field →
230
+ * --no-governance wins; else it keeps the modes its own cards carry. No agent-layer card → autonomy and Safe House get the
231
+ * new-agent defaults but integrity stays off (an existing agent is never silently opted in to billed
232
+ * analysis; MNE-9728). A card with no mode field →
231
233
  * observe (the prior CLI always wrote observe). A failed read → null: skip the refresh.
232
234
  */
233
235
  async function existingAgentPlan(agentId, governance) {
@@ -252,7 +254,7 @@ async function existingAgentPlan(agentId, governance) {
252
254
  return {
253
255
  modes: {
254
256
  autonomy: align ? (modeField(align, "autonomy_mode") ?? "observe") : fresh.autonomy,
255
- integrity: align ? (modeField(align, "integrity_mode") ?? "observe") : fresh.integrity,
257
+ integrity: align ? (modeField(align, "integrity_mode") ?? "observe") : "off", // an existing agent with no card of its own is not silently opted in to billed analysis (MNE-9728)
256
258
  protection: prot ? (modeField(prot, "mode") ?? "observe") : fresh.protection,
257
259
  allowUnmappedTools: align
258
260
  ? typeof ownAllow === "boolean"
@@ -263,9 +265,10 @@ async function existingAgentPlan(agentId, governance) {
263
265
  existing: { align, prot },
264
266
  };
265
267
  }
266
- /** Printed when a setup ran without --governance: how to opt in, and what it costs. */
267
- export const GOVERNANCE_OPT_IN_HINT = " Governance (AIP integrity analysis, Safe House screening) is off by default. Turn it on with " +
268
- "`mnemom agent setup --governance` (or --governance integrity / safe-house); it is billed at cost on top of the agent fee.";
268
+ /** Printed when a setup ran without --governance: what is on by default, how to change it, and what it costs. */
269
+ export const GOVERNANCE_OPT_IN_HINT = " AIP integrity analysis is on (observe) for new agents; Safe House screening is off by default. " +
270
+ "Opt out of integrity with `mnemom agent setup --governance none` (or --no-governance); turn Safe House on with " +
271
+ "`--governance integrity,safe-house`. Both are billed at cost on top of the agent fee.";
269
272
  /**
270
273
  * The default governed-agent slug for the current customer: `agent-<handle>`,
271
274
  * where <handle> is the local-part of their mnemom login email (sanitised), or
@@ -457,8 +460,8 @@ async function confirmClaimed(opts, anchorKey, fp) {
457
460
  const plan = await existingAgentPlan(agentId, opts.governance);
458
461
  if (plan) {
459
462
  if (!opts.governance) {
460
- say(fmt.dim(` Keeping its current governance (${describeModes(plan.modes)}). New agents default to off; ` +
461
- "`--governance` turns it on, `--no-governance` turns it off."));
463
+ say(fmt.dim(` Keeping its current governance (${describeModes(plan.modes)}). New agents default to integrity observe; ` +
464
+ "`--governance` picks features, `--no-governance` turns everything off."));
462
465
  }
463
466
  // The principal is the agent's own org, which a refresh may launch from another.
464
467
  const ownOrg = await agentOrgId(agentId);
@@ -511,7 +514,7 @@ async function confirmClaimed(opts, anchorKey, fp) {
511
514
  }
512
515
  say(fmt.success(`mnemom agent: claimed '${slug}' (${agentId}) in ${opts.orgLabel}.`));
513
516
  await noteSameNamedAgent(slug, agentId);
514
- // Publish the default cards (autonomy observe; integrity + Safe House off unless
517
+ // Publish the default cards (autonomy + integrity observe; Safe House off unless
515
518
  // --governance). A card write that can't complete does NOT undo the claim — the agent is
516
519
  // claimed and governed on whatever landed; we warn how to finish it.
517
520
  if (opts.setup !== false) {
@@ -1443,9 +1446,11 @@ function carryForward(card, kind) {
1443
1446
  return card;
1444
1447
  return upgradeInPlace(card, kind) ?? card;
1445
1448
  }
1446
- export function buildCodeAlignmentCard(agentId, modes = {
1449
+ export function buildCodeAlignmentCard(agentId,
1450
+ // Every production caller passes modes; the fallback's integrity matches the new-agent default (MNE-9728).
1451
+ modes = {
1447
1452
  autonomy: "off",
1448
- integrity: "off",
1453
+ integrity: "observe",
1449
1454
  }, principal = UNSPECIFIED_PRINCIPAL) {
1450
1455
  return {
1451
1456
  card_version: "unified/2026-04-26",
@@ -885,7 +885,7 @@ export async function cardEditCommand(agentName, options = {}) {
885
885
  card_version: "unified/2026-04-26",
886
886
  agent_id: agentId,
887
887
  autonomy_mode: "observe",
888
- integrity_mode: "off",
888
+ integrity_mode: "observe", // new-agent default (MNE-9728); set to off to opt out
889
889
  enforcement: { allow_unmapped_tools: true },
890
890
  principal: { type: "agent", identifier: agentId, relationship: "delegated_authority" },
891
891
  values: { declared: ["transparency", "safety", "honesty"] },
@@ -45,6 +45,7 @@ import { isInteractive, askInput, askYesNo } from "../lib/prompt.js";
45
45
  import { getWebsiteUrl } from "../lib/config.js";
46
46
  import { openBrowser } from "../lib/oauth.js";
47
47
  import { fmt } from "../lib/format.js";
48
+ import { starterIntegrityMode } from "../lib/starter-integrity.js";
48
49
  const FULL_PROOF_RE = /^[0-9a-f]{64}$/;
49
50
  /**
50
51
  * Entry point for `mnemom onboard`. Throws on a fatal error (caught by the
@@ -94,7 +95,7 @@ export async function onboardCommand(options = {}) {
94
95
  say();
95
96
  say(`${fmt.badge("alignment", "cyan")} Declaring your alignment card…`);
96
97
  try {
97
- await putAlignmentCard(agentId, JSON.stringify(buildStarterAlignmentCard(agentId)), "application/json",
98
+ await putAlignmentCard(agentId, JSON.stringify(buildStarterAlignmentCard(agentId, await starterIntegrityMode(agentId))), "application/json",
98
99
  // A STABLE key so a re-run replays the same server-side reservation
99
100
  // (idempotent no-op) rather than writing a divergent duplicate card.
100
101
  { idempotencyKey: `onboard-alignment-${agentId}` });
@@ -353,16 +354,16 @@ async function earnRating(agentId, steps, say) {
353
354
  // ── starter alignment card ──────────────────────────────────────────────────────
354
355
  /**
355
356
  * 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
+ * as the agent's own card has it (observe for a new agent, MNE-9728; see lib/starter-integrity.ts) — the honest, minimal declaration
357
358
  * of intent for a freshly-onboarded agent. Mirrors the shape `wrap` seeds so the
358
359
  * two skill-runners produce a consistent first card.
359
360
  */
360
- function buildStarterAlignmentCard(agentId) {
361
+ function buildStarterAlignmentCard(agentId, integrityMode) {
361
362
  return {
362
363
  card_version: "unified/2026-04-26",
363
364
  agent_id: agentId,
364
365
  autonomy_mode: "observe",
365
- integrity_mode: "off",
366
+ integrity_mode: integrityMode, // the agent's own mode; observe for a new agent (MNE-9728)
366
367
  // No capability mappings here, so unmapped tools must pass or every turn fails.
367
368
  enforcement: { allow_unmapped_tools: true },
368
369
  principal: { type: "agent", identifier: agentId, relationship: "delegated_authority" },
@@ -10,10 +10,9 @@ import { selectSpend } from "../lib/scan/spend/spend-tiers.js";
10
10
  import { type AnthropicUsageDeps, type MeasuredUsage } from "../lib/scan/spend/anthropic-usage.js";
11
11
  import { type WifDeps } from "../lib/scan/spend/anthropic-wif.js";
12
12
  import { type RecordDeps, type RecordOutcome } from "../lib/scan/record.js";
13
- import { type CostSpend } from "../lib/scan/cost-per-pr.js";
13
+ import type { CostSpend } from "../lib/scan/cost-per-pr.js";
14
14
  import { type ReportEmailDeps } from "../lib/scan/report-email.js";
15
15
  import { type RepoListDeps } from "../lib/scan/repo-picker.js";
16
- import { type ReportRecipients } from "../lib/scan/share.js";
17
16
  export interface ScanCommandOptions {
18
17
  repos: string[];
19
18
  period?: {
@@ -21,8 +20,10 @@ export interface ScanCommandOptions {
21
20
  end: string;
22
21
  };
23
22
  share?: string;
24
- /** Report recipient. Required unless the runner is the CTO (asked when omitted). */
23
+ /** Alias of one --email (kept for older scripts). */
25
24
  ctoEmail?: string;
25
+ /** Extra recipients of the report (repeatable; comma-separated accepted). The runner and every org admin always get it. */
26
+ email?: string[];
26
27
  /** Tier 2: the CTO's own monthly figure, as typed. Needs MNEMOM_ORG_SCAN_MODE=true. */
27
28
  monthlySpend?: string;
28
29
  /** Tier 2 without a figure on the command line: ask for one on the terminal. */
@@ -71,11 +72,24 @@ export interface ScanCommandOptions {
71
72
  /** Parses repeated/comma-separated `--repo owner/name`. Returns null on any invalid slug. */
72
73
  export declare function parseRepoFlags(raw: string[] | undefined): string[] | null;
73
74
  export declare const isEmail: (v: unknown) => v is string;
74
- /** The runner's email (mnemom login, else asked) and the CTO's (flag, else "are you the CTO?"). */
75
- export declare function resolveRecipients(o: {
76
- runnerEmail?: string;
75
+ export declare const DELETE_CONTACT = "privacy@mnemom.ai";
76
+ export declare const EMAIL_ONE_MSG = "Enter one email address, like you@company.com.";
77
+ export declare const EMAIL_LIST_MSG = "Enter email addresses like you@company.com, separated by commas.";
78
+ export declare const MAX_EXTRA_EMAILS = 10;
79
+ /**
80
+ * The people to add to the report email (the runner and every org admin always get it). Comes from the
81
+ * repeatable --email flag (and its alias --cto-email), each value one address or a comma-separated list;
82
+ * on a terminal with none given, asks once (blank to skip). Plain-language errors; the value is never echoed.
83
+ */
84
+ export declare function resolveExtraEmails(o: {
85
+ email?: string[];
77
86
  ctoEmail?: string;
78
- }): Promise<ReportRecipients>;
87
+ isTty?: boolean;
88
+ }): Promise<string[]>;
89
+ /** The runner's own address from the Mnemom login, or undefined (the server resolves it for the email either way). */
90
+ export declare function runnerEmailFromLogin(o: {
91
+ runnerEmail?: string;
92
+ }): string | undefined;
79
93
  /** The CTO's figure in USD, or null for none. Throws fixed text only; the input is never echoed. */
80
94
  export declare function resolveSelfReportedSpend(o: ScanCommandOptions): Promise<number | null>;
81
95
  /**