@mnemom/mnemom 0.17.37 → 0.17.38-next.1

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 (131) 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 +11 -0
  4. package/dist/commands/agent-run.js +37 -0
  5. package/dist/commands/agent-setup.d.ts +11 -9
  6. package/dist/commands/agent-setup.js +24 -19
  7. package/dist/commands/agent-share-render.d.ts +5 -5
  8. package/dist/commands/agent-share-render.js +9 -7
  9. package/dist/commands/agent-share-test-issuer.d.ts +1 -1
  10. package/dist/commands/agent-share-test-issuer.js +1 -1
  11. package/dist/commands/agent.d.ts +8 -1
  12. package/dist/commands/agent.js +14 -3
  13. package/dist/commands/card.js +1 -1
  14. package/dist/commands/onboard.js +5 -4
  15. package/dist/commands/scan.d.ts +35 -8
  16. package/dist/commands/scan.js +134 -45
  17. package/dist/commands/verify-card.d.ts +25 -1
  18. package/dist/commands/verify-card.js +29 -2
  19. package/dist/commands/wrap.js +4 -3
  20. package/dist/index.js +8 -6
  21. package/dist/lib/commit-report.d.ts +7 -13
  22. package/dist/lib/commit-report.js +12 -5
  23. package/dist/lib/conduct-receipt.d.ts +8 -3
  24. package/dist/lib/conduct-receipt.js +29 -7
  25. package/dist/lib/experimental.d.ts +1 -1
  26. package/dist/lib/experimental.js +1 -12
  27. package/dist/lib/runner/executor-client.d.ts +5 -0
  28. package/dist/lib/runner/executor-client.js +8 -0
  29. package/dist/lib/runner/job.d.ts +37 -0
  30. package/dist/lib/runner/job.js +74 -1
  31. package/dist/lib/runner/phases.d.ts +7 -2
  32. package/dist/lib/runner/phases.js +7 -2
  33. package/dist/lib/runner/proxy.d.ts +26 -2
  34. package/dist/lib/runner/proxy.js +33 -1
  35. package/dist/lib/runner/record-commit.d.ts +16 -0
  36. package/dist/lib/runner/record-commit.js +7 -0
  37. package/dist/lib/scan/report-email.d.ts +19 -2
  38. package/dist/lib/scan/report-email.js +78 -22
  39. package/dist/lib/scan/scan.d.ts +2 -0
  40. package/dist/lib/scan/scan.js +2 -1
  41. package/dist/lib/scan/share.d.ts +8 -6
  42. package/dist/lib/scan/share.js +28 -11
  43. package/dist/lib/scan/spend/anthropic-usage.d.ts +20 -1
  44. package/dist/lib/scan/spend/anthropic-usage.js +32 -7
  45. package/dist/lib/scan/spend/anthropic-wif.d.ts +42 -0
  46. package/dist/lib/scan/spend/anthropic-wif.js +153 -0
  47. package/dist/lib/starter-integrity.d.ts +20 -0
  48. package/dist/lib/starter-integrity.js +28 -0
  49. package/package.json +2 -5
  50. package/node_modules/@mnemom/aip-verifier/LICENSE +0 -190
  51. package/node_modules/@mnemom/aip-verifier/dist/claim-lint-CVITIRcU.d.cts +0 -478
  52. package/node_modules/@mnemom/aip-verifier/dist/claim-lint-CVITIRcU.d.ts +0 -478
  53. package/node_modules/@mnemom/aip-verifier/dist/index.cjs +0 -971
  54. package/node_modules/@mnemom/aip-verifier/dist/index.cjs.map +0 -1
  55. package/node_modules/@mnemom/aip-verifier/dist/index.d.cts +0 -330
  56. package/node_modules/@mnemom/aip-verifier/dist/index.d.ts +0 -330
  57. package/node_modules/@mnemom/aip-verifier/dist/index.js +0 -933
  58. package/node_modules/@mnemom/aip-verifier/dist/index.js.map +0 -1
  59. package/node_modules/@mnemom/aip-verifier/dist/render-lines.cjs +0 -879
  60. package/node_modules/@mnemom/aip-verifier/dist/render-lines.cjs.map +0 -1
  61. package/node_modules/@mnemom/aip-verifier/dist/render-lines.d.cts +0 -96
  62. package/node_modules/@mnemom/aip-verifier/dist/render-lines.d.ts +0 -96
  63. package/node_modules/@mnemom/aip-verifier/dist/render-lines.js +0 -875
  64. package/node_modules/@mnemom/aip-verifier/dist/render-lines.js.map +0 -1
  65. package/node_modules/@mnemom/aip-verifier/package.json +0 -86
  66. package/node_modules/@noble/ed25519/LICENSE +0 -21
  67. package/node_modules/@noble/ed25519/README.md +0 -371
  68. package/node_modules/@noble/ed25519/index.d.ts +0 -391
  69. package/node_modules/@noble/ed25519/index.js +0 -933
  70. package/node_modules/@noble/ed25519/index.ts +0 -1134
  71. package/node_modules/@noble/ed25519/package.json +0 -54
  72. package/node_modules/@noble/hashes/LICENSE +0 -21
  73. package/node_modules/@noble/hashes/README.md +0 -478
  74. package/node_modules/@noble/hashes/_blake.d.ts +0 -20
  75. package/node_modules/@noble/hashes/_blake.js +0 -59
  76. package/node_modules/@noble/hashes/_md.d.ts +0 -95
  77. package/node_modules/@noble/hashes/_md.js +0 -209
  78. package/node_modules/@noble/hashes/_u64.d.ts +0 -36
  79. package/node_modules/@noble/hashes/_u64.js +0 -77
  80. package/node_modules/@noble/hashes/argon2.d.ts +0 -148
  81. package/node_modules/@noble/hashes/argon2.js +0 -577
  82. package/node_modules/@noble/hashes/blake1.d.ts +0 -162
  83. package/node_modules/@noble/hashes/blake1.js +0 -630
  84. package/node_modules/@noble/hashes/blake2.d.ts +0 -203
  85. package/node_modules/@noble/hashes/blake2.js +0 -573
  86. package/node_modules/@noble/hashes/blake3.d.ts +0 -68
  87. package/node_modules/@noble/hashes/blake3.js +0 -310
  88. package/node_modules/@noble/hashes/eskdf.d.ts +0 -91
  89. package/node_modules/@noble/hashes/eskdf.js +0 -225
  90. package/node_modules/@noble/hashes/hkdf.d.ts +0 -70
  91. package/node_modules/@noble/hashes/hkdf.js +0 -152
  92. package/node_modules/@noble/hashes/hmac.d.ts +0 -50
  93. package/node_modules/@noble/hashes/hmac.js +0 -93
  94. package/node_modules/@noble/hashes/index.d.ts +0 -1
  95. package/node_modules/@noble/hashes/index.js +0 -34
  96. package/node_modules/@noble/hashes/legacy.d.ts +0 -107
  97. package/node_modules/@noble/hashes/legacy.js +0 -348
  98. package/node_modules/@noble/hashes/package.json +0 -91
  99. package/node_modules/@noble/hashes/pbkdf2.d.ts +0 -66
  100. package/node_modules/@noble/hashes/pbkdf2.js +0 -176
  101. package/node_modules/@noble/hashes/scrypt.d.ts +0 -98
  102. package/node_modules/@noble/hashes/scrypt.js +0 -304
  103. package/node_modules/@noble/hashes/sha2.d.ts +0 -176
  104. package/node_modules/@noble/hashes/sha2.js +0 -446
  105. package/node_modules/@noble/hashes/sha3-addons.d.ts +0 -533
  106. package/node_modules/@noble/hashes/sha3-addons.js +0 -973
  107. package/node_modules/@noble/hashes/sha3.d.ts +0 -208
  108. package/node_modules/@noble/hashes/sha3.js +0 -475
  109. package/node_modules/@noble/hashes/src/_blake.ts +0 -67
  110. package/node_modules/@noble/hashes/src/_md.ts +0 -227
  111. package/node_modules/@noble/hashes/src/_u64.ts +0 -111
  112. package/node_modules/@noble/hashes/src/argon2.ts +0 -693
  113. package/node_modules/@noble/hashes/src/blake1.ts +0 -677
  114. package/node_modules/@noble/hashes/src/blake2.ts +0 -648
  115. package/node_modules/@noble/hashes/src/blake3.ts +0 -344
  116. package/node_modules/@noble/hashes/src/eskdf.ts +0 -265
  117. package/node_modules/@noble/hashes/src/hkdf.ts +0 -161
  118. package/node_modules/@noble/hashes/src/hmac.ts +0 -130
  119. package/node_modules/@noble/hashes/src/index.ts +0 -33
  120. package/node_modules/@noble/hashes/src/legacy.ts +0 -361
  121. package/node_modules/@noble/hashes/src/pbkdf2.ts +0 -219
  122. package/node_modules/@noble/hashes/src/scrypt.ts +0 -375
  123. package/node_modules/@noble/hashes/src/sha2.ts +0 -486
  124. package/node_modules/@noble/hashes/src/sha3-addons.ts +0 -1157
  125. package/node_modules/@noble/hashes/src/sha3.ts +0 -525
  126. package/node_modules/@noble/hashes/src/utils.ts +0 -978
  127. package/node_modules/@noble/hashes/src/webcrypto.ts +0 -283
  128. package/node_modules/@noble/hashes/utils.d.ts +0 -560
  129. package/node_modules/@noble/hashes/utils.js +0 -687
  130. package/node_modules/@noble/hashes/webcrypto.d.ts +0 -121
  131. package/node_modules/@noble/hashes/webcrypto.js +0 -228
@@ -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()))
@@ -20,6 +20,7 @@ import { type GithubBases } from "../lib/runner/github-base.js";
20
20
  import type { JobDeps, Workspace } from "../lib/runner/job.js";
21
21
  import { type PhaseInvocation } from "../lib/runner/phases.js";
22
22
  import { type RunFlags } from "../lib/runner/options.js";
23
+ import { type RecordCommitBody } from "../lib/commit-report.js";
23
24
  export interface RunDeps {
24
25
  env: NodeJS.ProcessEnv;
25
26
  fetch: FetchFn;
@@ -55,6 +56,16 @@ export declare function prepareWorkspace(git: Git, cloneUrl: string, sessionId:
55
56
  export declare function cleanupWorkspace(ws: Workspace): Promise<void>;
56
57
  /** Commits on the job branch that no origin ref has: the clone's base is origin's default branch. */
57
58
  export declare function commitsAhead(git: Git, ws: Workspace): Promise<number>;
59
+ /**
60
+ * The working copy's HEAD; null only when the clone has no commit at all. Any other failure throws,
61
+ * so the job never mistakes an unreadable HEAD for "since the base" and re-reports earlier phases.
62
+ */
63
+ export declare function headSha(git: Git, ws: Workspace): Promise<string | null>;
64
+ /**
65
+ * RecordCommit/v1 bodies for the commits since `since` (null: since the base), oldest first. The
66
+ * repo is the job's: on a local lane origin is the fake GitHub, not github.com.
67
+ */
68
+ export declare function commitBodies(git: Git, ws: Workspace, since: string | null, lineageKey: string, repo: string): Promise<RecordCommitBody[]>;
58
69
  /** Push the job branch and open its PR against the repo's default branch; resolves its URL. */
59
70
  export declare function openPr(git: Git, fetch: FetchFn, token: string | null, repo: string, ws: Workspace, title: string, body: string, apiBase?: string): Promise<string>;
60
71
  /** merge_on_green: GitHub's auto-merge on the PR (squash). */
@@ -31,6 +31,7 @@ import { exitCodeFor, outcomeLine, refusedOutcome, USAGE_EXIT_CODE, } from "../l
31
31
  import { phaseEnv } from "../lib/runner/phases.js";
32
32
  import { resolveRunPlan } from "../lib/runner/options.js";
33
33
  import { startModelProxy } from "../lib/runner/proxy.js";
34
+ import { commitBody, realGit } from "../lib/commit-report.js";
34
35
  import { resolveGithubToken } from "./agent-fuel.js";
35
36
  import { executorStatePath } from "../vendor/durable-contract/index.js";
36
37
  /** The refusal of a runner with no ANTHROPIC_API_KEY (34.30.1); a config error, exit 2. */
@@ -165,6 +166,40 @@ export async function commitsAhead(git, ws) {
165
166
  throw new Error(`git rev-list answered ${n}`);
166
167
  return n;
167
168
  }
169
+ /**
170
+ * The working copy's HEAD; null only when the clone has no commit at all. Any other failure throws,
171
+ * so the job never mistakes an unreadable HEAD for "since the base" and re-reports earlier phases.
172
+ */
173
+ export async function headSha(git, ws) {
174
+ let sha;
175
+ try {
176
+ sha = await git(ws.dir, ["rev-parse", "--verify", "--quiet", "HEAD"]);
177
+ }
178
+ catch (e) {
179
+ if ((await git(ws.dir, ["rev-list", "-n", "1", "--all"])) === "")
180
+ return null;
181
+ throw e;
182
+ }
183
+ if (!/^[0-9a-f]{40}$/.test(sha))
184
+ throw new Error(`git rev-parse answered ${sha.slice(0, 40)}`);
185
+ return sha;
186
+ }
187
+ /**
188
+ * RecordCommit/v1 bodies for the commits since `since` (null: since the base), oldest first. The
189
+ * repo is the job's: on a local lane origin is the fake GitHub, not github.com.
190
+ */
191
+ export async function commitBodies(git, ws, since, lineageKey, repo) {
192
+ const range = since === null ? ["HEAD", "--not", "--remotes=origin"] : [`${since}..HEAD`];
193
+ const out = await git(ws.dir, ["rev-list", "--reverse", ...range]);
194
+ const local = realGit(ws.dir);
195
+ const bodies = [];
196
+ for (const sha of out.split("\n").filter(Boolean)) {
197
+ const built = commitBody(local, sha, lineageKey, repo);
198
+ if (built.ok)
199
+ bodies.push(built.body);
200
+ }
201
+ return bodies;
202
+ }
168
203
  /** Push the job branch and open its PR against the repo's default branch; resolves its URL. */
169
204
  export async function openPr(git, fetch, token, repo, ws, title, body, apiBase = GITHUB_BASES.api) {
170
205
  await git(ws.dir, ["push", "--quiet", "origin", `HEAD:refs/heads/${ws.branch}`]);
@@ -239,6 +274,8 @@ export function liveJobDeps(api, opts) {
239
274
  runPhase: (inv, ws, modelUrl, signal) => runPhaseProcess(inv, ws, modelUrl, signal, opts.env),
240
275
  openPr: (repo, ws, title, body) => openPr(git, opts.fetch, token, repo, ws, title, body, gh.api),
241
276
  commitsAhead: (ws) => commitsAhead(git, ws),
277
+ headSha: (ws) => headSha(git, ws),
278
+ commitBodies: (ws, since, lineageKey, repo) => commitBodies(git, ws, since, lineageKey, repo),
242
279
  enableAutoMerge: (prUrl) => enableAutoMerge(opts.fetch, token, prUrl, gh),
243
280
  cleanup: cleanupWorkspace,
244
281
  };
@@ -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",
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Bridge from `mnemom agent share` to the aip verifier (`@mnemom/aip-verifier`, aip#192/#178):
2
+ * Bridge from `mnemom agent share` to the aip verifier (`@mnemom/verify`, aip#192/#178):
3
3
  * the renderer (`renderLines`) and claim-lint (`lintRendering`) are the ONLY source of what a
4
- * card may say. No word lists live here. The package is a runtime dependency pinned to the aip
5
- * release tarball and is loaded lazily, so the default CLI path never touches it; if it is
4
+ * card may say. No word lists live here. The package is a runtime dependency pinned to an exact
5
+ * npm registry version and is loaded lazily, so the default CLI path never touches it; if it is
6
6
  * absent at runtime the share command fails closed with a clear message.
7
7
  */
8
8
  import type { LineRenderer, SharedCardLine } from "./agent-share.js";
9
- import type * as AipMain from "@mnemom/aip-verifier";
10
- import type * as AipRender from "@mnemom/aip-verifier/render-lines";
9
+ import type * as AipMain from "@mnemom/verify";
10
+ import type * as AipRender from "@mnemom/verify/render-lines";
11
11
  export interface VerifierModules {
12
12
  lintRendering: typeof AipMain.lintRendering;
13
13
  renderLines: typeof AipRender.renderLines;
@@ -1,14 +1,14 @@
1
1
  /**
2
- * Bridge from `mnemom agent share` to the aip verifier (`@mnemom/aip-verifier`, aip#192/#178):
2
+ * Bridge from `mnemom agent share` to the aip verifier (`@mnemom/verify`, aip#192/#178):
3
3
  * the renderer (`renderLines`) and claim-lint (`lintRendering`) are the ONLY source of what a
4
- * card may say. No word lists live here. The package is a runtime dependency pinned to the aip
5
- * release tarball and is loaded lazily, so the default CLI path never touches it; if it is
4
+ * card may say. No word lists live here. The package is a runtime dependency pinned to an exact
5
+ * npm registry version and is loaded lazily, so the default CLI path never touches it; if it is
6
6
  * absent at runtime the share command fails closed with a clear message.
7
7
  */
8
8
  const defaultLoader = async () => {
9
9
  const [main, render] = await Promise.all([
10
- import("@mnemom/aip-verifier"),
11
- import("@mnemom/aip-verifier/render-lines"),
10
+ import("@mnemom/verify"),
11
+ import("@mnemom/verify/render-lines"),
12
12
  ]);
13
13
  return { lintRendering: main.lintRendering, renderLines: render.renderLines };
14
14
  };
@@ -20,9 +20,11 @@ async function loadVerifier(load) {
20
20
  catch (error) {
21
21
  const e = error;
22
22
  if (e.code === "ERR_MODULE_NOT_FOUND" || e.code === "MODULE_NOT_FOUND") {
23
- throw new Error("the aip verifier (@mnemom/aip-verifier) is not installed: it ships bundled inside @mnemom/mnemom, so reinstall with `npm install -g @mnemom/mnemom`", { cause: error });
23
+ throw new Error("the aip verifier (@mnemom/verify) is not installed: it is a dependency of @mnemom/mnemom, so reinstall with `npm install -g @mnemom/mnemom`", { cause: error });
24
24
  }
25
- throw new Error(`the aip verifier (@mnemom/aip-verifier) failed to load: ${e.message ?? error}`, { cause: error });
25
+ throw new Error(`the aip verifier (@mnemom/verify) failed to load: ${e.message ?? error}`, {
26
+ cause: error,
27
+ });
26
28
  }
27
29
  }
28
30
  /**
@@ -23,7 +23,7 @@
23
23
  * TEST_SHARECARD_PUBLIC_KEY_HEX / TEST_SHARECARD_JWKS below, which a verifier must be given
24
24
  * explicitly as the trusted key; the production JWKS never contains it.
25
25
  */
26
- import type * as AipVerifier from "@mnemom/aip-verifier";
26
+ import type * as AipVerifier from "@mnemom/verify";
27
27
  import type { AgentShareDeps, CardIssuer } from "./agent-share.js";
28
28
  /** aip test key id; ids of every test key start with this prefix. */
29
29
  export declare const TEST_KEY_ID = "test-sharecard-key-1";
@@ -80,7 +80,7 @@ const PKCS8_ED25519_PREFIX = Buffer.from("302e020100300506032b657004220420", "he
80
80
  export function createTestCardIssuer(opts = {}) {
81
81
  const now = opts.now ?? (() => new Date());
82
82
  const cardId = opts.cardId ?? (() => `card-test-${randomBytes(6).toString("hex")}`);
83
- const load = opts.loadVerifier ?? (() => import("@mnemom/aip-verifier"));
83
+ const load = opts.loadVerifier ?? (() => import("@mnemom/verify"));
84
84
  return {
85
85
  async issue(lines) {
86
86
  const { shareCardSigningInput } = await load();
@@ -401,11 +401,18 @@ export declare function fedStatuslineWanted(version: string): boolean;
401
401
  */
402
402
  export declare function exemptLoopbackFromProxy(env: NodeJS.ProcessEnv): void;
403
403
  /**
404
- * Print the conduct receipt (experimental `record`) — the exit call site here, and the one a
404
+ * Print the conduct receipt (on by default; MNEMOM_AGENT_RECEIPT=0 opts out) — the exit call site here, and the one a
405
405
  * durable park calls. Never throws: a failure is one warning line, and the caller's exit code
406
406
  * is untouched.
407
407
  */
408
408
  export declare function sayConductReceipt(launch: ReceiptLaunch, trigger?: "exit" | "park", receipt?: typeof conductReceiptFor): Promise<void>;
409
+ /**
410
+ * Whether `mnemom agent` reads and prints the conduct receipt at exit (MNE-9013: on by default,
411
+ * graduated from experimental `record`; MNEMOM_AGENT_RECEIPT=0 opts out). Claude only: the
412
+ * receipt reads the lineage key the base-URL proxy captures, and that proxy fronts
413
+ * ANTHROPIC_BASE_URL alone, so another CLI would only gain a proxy that can capture nothing.
414
+ */
415
+ export declare function receiptWanted(env: NodeJS.ProcessEnv): boolean;
409
416
  /** Whether a terminal implicit launch runs the turn-origin proxy (MNEMOM_AGENT_TURN_HEADER=0 opts out). */
410
417
  export declare function turnProxyWanted(env: NodeJS.ProcessEnv): boolean;
411
418
  /** The flag that lets base-url-proxy.mjs use an http door on a loopback literal (C17-R16 T3). */
@@ -847,7 +847,7 @@ export async function agentCommand(scenarioArg, options = {}) {
847
847
  if (shape === "terminal") {
848
848
  // Record keys the lineage under the served agent's org, not the account org (lib/record-org).
849
849
  const recordOrgId = recordOrgWanted({
850
- receipt: experimental.includes("record"),
850
+ receipt: cli.name === "claude" && receiptWanted(process.env),
851
851
  commitReport: cli.name === "claude" && commitReportEnabled(process.env[COMMIT_REPORT_ENV]),
852
852
  fedStatusline: cli.name === "claude" && fedStatuslineWanted(CLI_VERSION),
853
853
  }) && account.orgId
@@ -895,7 +895,8 @@ export async function agentCommand(scenarioArg, options = {}) {
895
895
  },
896
896
  }
897
897
  : {}),
898
- receipt: experimental.includes("record")
898
+ // On by default (MNE-9013); prints only when the org's record returns tally data.
899
+ receipt: cli.name === "claude" && Boolean(account.orgId) && receiptWanted(process.env)
899
900
  ? { orgId: recordOrgId, agentId: servedAgentId }
900
901
  : undefined,
901
902
  orgId: recordOrgId,
@@ -1671,7 +1672,7 @@ export function exemptLoopbackFromProxy(env) {
1671
1672
  env.no_proxy = [lower, "127.0.0.1,localhost"].filter(Boolean).join(",");
1672
1673
  }
1673
1674
  /**
1674
- * Print the conduct receipt (experimental `record`) — the exit call site here, and the one a
1675
+ * Print the conduct receipt (on by default; MNEMOM_AGENT_RECEIPT=0 opts out) — the exit call site here, and the one a
1675
1676
  * durable park calls. Never throws: a failure is one warning line, and the caller's exit code
1676
1677
  * is untouched.
1677
1678
  */
@@ -1684,6 +1685,16 @@ export async function sayConductReceipt(launch, trigger = "exit", receipt = cond
1684
1685
  say(fmt.warn(`mnemom agent: no conduct receipt (${err instanceof Error ? err.message : String(err)})`));
1685
1686
  }
1686
1687
  }
1688
+ /**
1689
+ * Whether `mnemom agent` reads and prints the conduct receipt at exit (MNE-9013: on by default,
1690
+ * graduated from experimental `record`; MNEMOM_AGENT_RECEIPT=0 opts out). Claude only: the
1691
+ * receipt reads the lineage key the base-URL proxy captures, and that proxy fronts
1692
+ * ANTHROPIC_BASE_URL alone, so another CLI would only gain a proxy that can capture nothing.
1693
+ */
1694
+ export function receiptWanted(env) {
1695
+ const raw = (env.MNEMOM_AGENT_RECEIPT ?? "").trim().toLowerCase();
1696
+ return !["0", "off", "false", "no"].includes(raw);
1697
+ }
1687
1698
  /** Whether a terminal implicit launch runs the turn-origin proxy (MNEMOM_AGENT_TURN_HEADER=0 opts out). */
1688
1699
  export function turnProxyWanted(env) {
1689
1700
  const raw = (env.MNEMOM_AGENT_TURN_HEADER ?? "").trim().toLowerCase();
@@ -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" },
@@ -7,12 +7,12 @@
7
7
  import { type GitHubCredential } from "../lib/scan/credential.js";
8
8
  import { type ScanDeps, type ScanResult } from "../lib/scan/scan.js";
9
9
  import { selectSpend } from "../lib/scan/spend/spend-tiers.js";
10
- import { type AnthropicUsageDeps } from "../lib/scan/spend/anthropic-usage.js";
10
+ import { type AnthropicUsageDeps, type MeasuredUsage } from "../lib/scan/spend/anthropic-usage.js";
11
+ import { type WifDeps } from "../lib/scan/spend/anthropic-wif.js";
11
12
  import { type RecordDeps, type RecordOutcome } from "../lib/scan/record.js";
12
13
  import { type CostSpend } from "../lib/scan/cost-per-pr.js";
13
14
  import { type ReportEmailDeps } from "../lib/scan/report-email.js";
14
15
  import { type RepoListDeps } from "../lib/scan/repo-picker.js";
15
- import { type ReportRecipients } from "../lib/scan/share.js";
16
16
  export interface ScanCommandOptions {
17
17
  repos: string[];
18
18
  period?: {
@@ -20,8 +20,10 @@ export interface ScanCommandOptions {
20
20
  end: string;
21
21
  };
22
22
  share?: string;
23
- /** Report recipient. Required unless the runner is the CTO (asked when omitted). */
23
+ /** Alias of one --email (kept for older scripts). */
24
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[];
25
27
  /** Tier 2: the CTO's own monthly figure, as typed. Needs MNEMOM_ORG_SCAN_MODE=true. */
26
28
  monthlySpend?: string;
27
29
  /** Tier 2 without a figure on the command line: ask for one on the terminal. */
@@ -33,6 +35,8 @@ export interface ScanCommandOptions {
33
35
  anthropicOver200kShare?: number | null;
34
36
  /** Test seam: the fetch behind the two Anthropic reads. */
35
37
  anthropicDeps?: AnthropicUsageDeps;
38
+ /** Test seam: the WIF assertion mint and Anthropic token exchange (MNE-9706). */
39
+ wifDeps?: WifDeps;
36
40
  /**
37
41
  * The org the report is emailed for; inferred from the signed-in user's single non-personal org when
38
42
  * omitted (see resolveScanOrg). The Record totals preview (MNEMOM_ORG_SCAN_MODE=true) reads ONLY an
@@ -68,11 +72,24 @@ export interface ScanCommandOptions {
68
72
  /** Parses repeated/comma-separated `--repo owner/name`. Returns null on any invalid slug. */
69
73
  export declare function parseRepoFlags(raw: string[] | undefined): string[] | null;
70
74
  export declare const isEmail: (v: unknown) => v is string;
71
- /** The runner's email (mnemom login, else asked) and the CTO's (flag, else "are you the CTO?"). */
72
- export declare function resolveRecipients(o: {
73
- 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[];
74
86
  ctoEmail?: string;
75
- }): 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;
76
93
  /** The CTO's figure in USD, or null for none. Throws fixed text only; the input is never echoed. */
77
94
  export declare function resolveSelfReportedSpend(o: ScanCommandOptions): Promise<number | null>;
78
95
  /**
@@ -93,10 +110,20 @@ export declare const TIER1_FALLBACK_NOTE = "Tier 1 skipped: falling back to the
93
110
  * fixed sentence: the key, the thrown value and the response never reach the terminal. The caller then falls
94
111
  * back to tier 2, then tier 3.
95
112
  */
113
+ export declare const WIF_OK_NOTE = "Read Anthropic usage through workload identity federation.";
114
+ /**
115
+ * Tier 1 through WIF (MNE-9706): Mnemom issues an identity token for the org, this machine exchanges it at
116
+ * Anthropic and reads only the two usage reports with the result. "not_configured" when the WIF ids are
117
+ * not set; "failed" (after printing a fixed sentence) for every failure, so the caller falls back to the key.
118
+ */
119
+ export declare function measuredUsageViaWif(o: ScanCommandOptions, orgId: string, period: {
120
+ start: string;
121
+ end: string;
122
+ }): Promise<MeasuredUsage | "not_configured" | "failed">;
96
123
  export declare function resolveMeasuredUsage(o: ScanCommandOptions, period: {
97
124
  start: string;
98
125
  end: string;
99
- }): Promise<{
126
+ }, orgId?: string): Promise<{
100
127
  usd: number;
101
128
  over200kShare: number | null;
102
129
  } | null>;