@mnemom/mnemom 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -25
- package/dist/commands/agents.js +2 -7
- package/dist/commands/api-key.d.ts +37 -0
- package/dist/commands/api-key.js +179 -0
- package/dist/commands/auth.js +1 -2
- package/dist/commands/card.js +33 -22
- package/dist/commands/governance.d.ts +85 -0
- package/dist/commands/governance.js +329 -0
- package/dist/commands/integrity.js +1 -2
- package/dist/commands/license.js +13 -4
- package/dist/commands/listen.d.ts +29 -0
- package/dist/commands/listen.js +201 -0
- package/dist/commands/logs.js +1 -3
- package/dist/commands/org.js +4 -6
- package/dist/commands/protection.js +70 -23
- package/dist/commands/recipes.d.ts +34 -0
- package/dist/commands/recipes.js +80 -0
- package/dist/commands/status.js +6 -169
- package/dist/commands/team.js +5 -10
- package/dist/commands/validate.js +7 -4
- package/dist/commands/webhooks.d.ts +61 -0
- package/dist/commands/webhooks.js +328 -0
- package/dist/index.js +489 -1
- package/dist/lib/api.d.ts +199 -2
- package/dist/lib/api.js +207 -0
- package/dist/lib/auth.js +1 -5
- package/dist/lib/format.d.ts +4 -0
- package/dist/lib/format.js +6 -0
- package/dist/lib/listen-stream.d.ts +40 -0
- package/dist/lib/listen-stream.js +101 -0
- package/dist/lib/webhooks-api.d.ts +80 -0
- package/dist/lib/webhooks-api.js +172 -0
- package/dist/smoltbot-shim.js +3 -3
- package/package.json +1 -1
- package/dist/lib/model-cache.d.ts +0 -16
- package/dist/lib/model-cache.js +0 -137
- package/dist/lib/models.d.ts +0 -41
- package/dist/lib/models.js +0 -357
- package/dist/lib/openclaw.d.ts +0 -221
- package/dist/lib/openclaw.js +0 -474
package/README.md
CHANGED
|
@@ -26,23 +26,23 @@ That's it. `mnemom init` detects your configured AI provider API keys (Anthropic
|
|
|
26
26
|
|
|
27
27
|
## Supported Providers
|
|
28
28
|
|
|
29
|
-
| Provider
|
|
30
|
-
|
|
31
|
-
| Anthropic | Claude Opus 4.6, Opus 4.5, Sonnet 4.5 | Full (thinking blocks)
|
|
32
|
-
| OpenAI
|
|
33
|
-
| Gemini
|
|
29
|
+
| Provider | Models | Thinking/AIP | Auth |
|
|
30
|
+
| --------- | ------------------------------------- | ----------------------- | ----------------------- |
|
|
31
|
+
| Anthropic | Claude Opus 4.6, Opus 4.5, Sonnet 4.5 | Full (thinking blocks) | `x-api-key` |
|
|
32
|
+
| OpenAI | GPT-5.2, GPT-5.2 Pro, GPT-5 | Via reasoning summaries | `Authorization: Bearer` |
|
|
33
|
+
| Gemini | Gemini 2.5 Pro, Gemini 3 Pro | Full (thought parts) | `x-goog-api-key` |
|
|
34
34
|
|
|
35
35
|
## CLI Commands
|
|
36
36
|
|
|
37
|
-
| Command
|
|
38
|
-
|
|
39
|
-
| `mnemom init`
|
|
40
|
-
| `mnemom status`
|
|
41
|
-
| `mnemom integrity`
|
|
42
|
-
| `mnemom logs [-l N]`
|
|
43
|
-
| `mnemom card show`
|
|
44
|
-
| `mnemom card publish <file>`
|
|
45
|
-
| `mnemom card validate <file>` | Validate card JSON locally
|
|
37
|
+
| Command | Description |
|
|
38
|
+
| ----------------------------- | ---------------------------------------------------- |
|
|
39
|
+
| `mnemom init` | Configure tracing for your AI agent (multi-provider) |
|
|
40
|
+
| `mnemom status` | Show agent status, providers, and connection info |
|
|
41
|
+
| `mnemom integrity` | Display integrity score and verification stats |
|
|
42
|
+
| `mnemom logs [-l N]` | Show recent traces and actions |
|
|
43
|
+
| `mnemom card show` | Display active alignment card |
|
|
44
|
+
| `mnemom card publish <file>` | Publish alignment card from JSON file |
|
|
45
|
+
| `mnemom card validate <file>` | Validate card JSON locally |
|
|
46
46
|
|
|
47
47
|
## How It Works
|
|
48
48
|
|
|
@@ -84,20 +84,20 @@ What is **not** stored: your prompts, responses, or API key.
|
|
|
84
84
|
|
|
85
85
|
### AIP Compatibility Matrix
|
|
86
86
|
|
|
87
|
-
| Provider/Model
|
|
88
|
-
|
|
89
|
-
| Anthropic reasoning models (Opus, Sonnet) | Full
|
|
90
|
-
| OpenAI GPT-5 Thinking series
|
|
91
|
-
| Gemini 2.5/3 with thinking
|
|
92
|
-
| Non-reasoning models
|
|
87
|
+
| Provider/Model | AIP Support | Method |
|
|
88
|
+
| ----------------------------------------- | ------------ | ---------------------------------------- |
|
|
89
|
+
| Anthropic reasoning models (Opus, Sonnet) | Full | Thinking blocks analyzed directly |
|
|
90
|
+
| OpenAI GPT-5 Thinking series | Partial | Reasoning summaries (reduced confidence) |
|
|
91
|
+
| Gemini 2.5/3 with thinking | Full | Thought parts analyzed directly |
|
|
92
|
+
| Non-reasoning models | Tracing only | Synthetic clear verdict |
|
|
93
93
|
|
|
94
94
|
## Enforcement Modes
|
|
95
95
|
|
|
96
|
-
| Mode
|
|
97
|
-
|
|
98
|
-
| `observe` | Detect violations, record them, take no action (default)
|
|
99
|
-
| `nudge`
|
|
100
|
-
| `enforce` | Hard block with 403 for non-streaming; falls back to nudge for streaming
|
|
96
|
+
| Mode | Behavior |
|
|
97
|
+
| --------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
+
| `observe` | Detect violations, record them, take no action (default) |
|
|
99
|
+
| `nudge` | Detect violations, inject feedback into the agent's next request via system prompt — the agent sees it and can self-correct |
|
|
100
|
+
| `enforce` | Hard block with 403 for non-streaming; falls back to nudge for streaming |
|
|
101
101
|
|
|
102
102
|
Enforcement works across all providers where AIP is supported.
|
|
103
103
|
|
package/dist/commands/agents.js
CHANGED
|
@@ -23,18 +23,13 @@ export async function agentsListCommand() {
|
|
|
23
23
|
const idW = 40;
|
|
24
24
|
const seenW = 14;
|
|
25
25
|
const statusW = 14;
|
|
26
|
-
const header = "Name".padEnd(nameW) +
|
|
27
|
-
"ID".padEnd(idW) +
|
|
28
|
-
"Last Seen".padEnd(seenW) +
|
|
29
|
-
"Containment";
|
|
26
|
+
const header = "Name".padEnd(nameW) + "ID".padEnd(idW) + "Last Seen".padEnd(seenW) + "Containment";
|
|
30
27
|
console.log(` ${header}`);
|
|
31
28
|
console.log(` ${"─".repeat(nameW + idW + seenW + statusW)}`);
|
|
32
29
|
for (const agent of agents) {
|
|
33
30
|
const name = (agent.name ?? "-").slice(0, nameW - 2).padEnd(nameW);
|
|
34
31
|
const id = agent.id.padEnd(idW);
|
|
35
|
-
const lastSeen = agent.last_seen
|
|
36
|
-
? new Date(agent.last_seen).toLocaleDateString()
|
|
37
|
-
: "-";
|
|
32
|
+
const lastSeen = agent.last_seen ? new Date(agent.last_seen).toLocaleDateString() : "-";
|
|
38
33
|
const seen = lastSeen.padEnd(seenW);
|
|
39
34
|
const containment = agent.containment_status ?? "-";
|
|
40
35
|
console.log(` ${name}${id}${seen}${containment}`);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mnemom api-key ...` commands — capability-based API key management
|
|
3
|
+
* (ADR-049). Mirrors the dashboard scope picker and the API mint-time
|
|
4
|
+
* vocabulary; one CLI surface for the same key lifecycle operations.
|
|
5
|
+
*
|
|
6
|
+
* mnemom api-key list — list active personal keys
|
|
7
|
+
* mnemom api-key create --name <name> [--scopes a,b,c]
|
|
8
|
+
* — mint a new key
|
|
9
|
+
* mnemom api-key rotate <key_id> — atomic mint-new + revoke-old
|
|
10
|
+
* mnemom api-key revoke <key_id> — soft-delete
|
|
11
|
+
*
|
|
12
|
+
* Auth: any of the standard CLI auth methods — JWT (`mnemom login`),
|
|
13
|
+
* MNEMOM_API_KEY env, or a stored API key. Note the chicken-and-egg:
|
|
14
|
+
* to mint your first key you'll need a JWT (the website's create-key
|
|
15
|
+
* dialog is the alternative). After that, an `api:write` key can mint
|
|
16
|
+
* additional keys for itself.
|
|
17
|
+
*/
|
|
18
|
+
import { type ApiKeyScope } from "../lib/api.js";
|
|
19
|
+
/**
|
|
20
|
+
* Exported for tests. Parses a comma-separated `--scopes` flag value,
|
|
21
|
+
* accepts legacy `api` for backward compat, and returns a typed array.
|
|
22
|
+
* Throws on unknown scope names so users get a clear error instead of
|
|
23
|
+
* silently dropping intent.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseScopes(input: string | undefined): ApiKeyScope[];
|
|
26
|
+
export declare function apiKeyListCommand(opts: {
|
|
27
|
+
json?: boolean;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
export declare function apiKeyCreateCommand(opts: {
|
|
30
|
+
name?: string;
|
|
31
|
+
scopes?: string;
|
|
32
|
+
json?: boolean;
|
|
33
|
+
}): Promise<void>;
|
|
34
|
+
export declare function apiKeyRotateCommand(keyId: string | undefined, opts: {
|
|
35
|
+
json?: boolean;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
export declare function apiKeyRevokeCommand(keyId: string | undefined): Promise<void>;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mnemom api-key ...` commands — capability-based API key management
|
|
3
|
+
* (ADR-049). Mirrors the dashboard scope picker and the API mint-time
|
|
4
|
+
* vocabulary; one CLI surface for the same key lifecycle operations.
|
|
5
|
+
*
|
|
6
|
+
* mnemom api-key list — list active personal keys
|
|
7
|
+
* mnemom api-key create --name <name> [--scopes a,b,c]
|
|
8
|
+
* — mint a new key
|
|
9
|
+
* mnemom api-key rotate <key_id> — atomic mint-new + revoke-old
|
|
10
|
+
* mnemom api-key revoke <key_id> — soft-delete
|
|
11
|
+
*
|
|
12
|
+
* Auth: any of the standard CLI auth methods — JWT (`mnemom login`),
|
|
13
|
+
* MNEMOM_API_KEY env, or a stored API key. Note the chicken-and-egg:
|
|
14
|
+
* to mint your first key you'll need a JWT (the website's create-key
|
|
15
|
+
* dialog is the alternative). After that, an `api:write` key can mint
|
|
16
|
+
* additional keys for itself.
|
|
17
|
+
*/
|
|
18
|
+
import { listApiKeys, createApiKey, rotateApiKey, revokeApiKey, isLegacyScopeSet, API_KEY_SCOPES, DEFAULT_API_KEY_SCOPES, } from "../lib/api.js";
|
|
19
|
+
import { requireAuth } from "../lib/auth.js";
|
|
20
|
+
import { fmt } from "../lib/format.js";
|
|
21
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
22
|
+
/**
|
|
23
|
+
* Exported for tests. Parses a comma-separated `--scopes` flag value,
|
|
24
|
+
* accepts legacy `api` for backward compat, and returns a typed array.
|
|
25
|
+
* Throws on unknown scope names so users get a clear error instead of
|
|
26
|
+
* silently dropping intent.
|
|
27
|
+
*/
|
|
28
|
+
export function parseScopes(input) {
|
|
29
|
+
if (!input)
|
|
30
|
+
return [...DEFAULT_API_KEY_SCOPES];
|
|
31
|
+
const raw = input
|
|
32
|
+
.split(",")
|
|
33
|
+
.map((s) => s.trim())
|
|
34
|
+
.filter((s) => s.length > 0);
|
|
35
|
+
if (raw.length === 0)
|
|
36
|
+
return [...DEFAULT_API_KEY_SCOPES];
|
|
37
|
+
const valid = new Set(API_KEY_SCOPES);
|
|
38
|
+
// Accept legacy 'api' input here so users who copy-paste from older
|
|
39
|
+
// docs/scripts get a clean canonicalization. The API also aliases.
|
|
40
|
+
valid.add("api");
|
|
41
|
+
const unknown = raw.filter((s) => !valid.has(s));
|
|
42
|
+
if (unknown.length > 0) {
|
|
43
|
+
throw new Error(`Unknown scope(s): ${unknown.join(", ")}. ` +
|
|
44
|
+
`Valid: ${Array.from(API_KEY_SCOPES).join(", ")}`);
|
|
45
|
+
}
|
|
46
|
+
return raw;
|
|
47
|
+
}
|
|
48
|
+
function renderScopeBadge(scope) {
|
|
49
|
+
// Admin scopes get a visual marker so the audit trail in the CLI
|
|
50
|
+
// makes elevated keys obvious at a glance.
|
|
51
|
+
if (scope === "admin:platform" || scope === "admin:org") {
|
|
52
|
+
return fmt.warn(`[${scope}]`);
|
|
53
|
+
}
|
|
54
|
+
return `[${scope}]`;
|
|
55
|
+
}
|
|
56
|
+
function formatRow(key) {
|
|
57
|
+
const created = key.created_at ? new Date(key.created_at).toISOString().slice(0, 10) : "?";
|
|
58
|
+
const lastUsed = key.last_used_at
|
|
59
|
+
? new Date(key.last_used_at).toISOString().slice(0, 10)
|
|
60
|
+
: "never";
|
|
61
|
+
const scopes = (key.scopes ?? []).map(renderScopeBadge).join(" ");
|
|
62
|
+
const legacy = isLegacyScopeSet(key.scopes) ? fmt.dim(" (legacy)") : "";
|
|
63
|
+
return ` ${key.key_id} ${key.key_prefix}… ${key.name.padEnd(24)} ${scopes}${legacy}\n created ${created} · last used ${lastUsed}`;
|
|
64
|
+
}
|
|
65
|
+
// ─── mnemom api-key list ─────────────────────────────────────────────────
|
|
66
|
+
export async function apiKeyListCommand(opts) {
|
|
67
|
+
await requireAuth();
|
|
68
|
+
let keys;
|
|
69
|
+
try {
|
|
70
|
+
keys = await listApiKeys();
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
console.error(fmt.error(`Failed to list api keys: ${err instanceof Error ? err.message : err}`));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
if (opts.json) {
|
|
77
|
+
console.log(JSON.stringify(keys, null, 2));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (keys.length === 0) {
|
|
81
|
+
console.log("\nNo active api keys.\n");
|
|
82
|
+
console.log("Create one with `mnemom api-key create --name <name>`.\n");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
console.log();
|
|
86
|
+
console.log(fmt.header(`Active api keys (${keys.length})`));
|
|
87
|
+
console.log();
|
|
88
|
+
for (const k of keys) {
|
|
89
|
+
console.log(formatRow(k));
|
|
90
|
+
console.log();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// ─── mnemom api-key create ───────────────────────────────────────────────
|
|
94
|
+
export async function apiKeyCreateCommand(opts) {
|
|
95
|
+
await requireAuth();
|
|
96
|
+
if (!opts.name || opts.name.trim() === "") {
|
|
97
|
+
console.error(fmt.error("--name is required. Example: --name 'ci-prod'"));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
let scopes;
|
|
101
|
+
try {
|
|
102
|
+
scopes = parseScopes(opts.scopes);
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
console.error(fmt.error(err instanceof Error ? err.message : String(err)));
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
let created;
|
|
109
|
+
try {
|
|
110
|
+
created = await createApiKey(opts.name.trim(), scopes);
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
console.error(fmt.error(`Create failed: ${err instanceof Error ? err.message : err}`));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
if (opts.json) {
|
|
117
|
+
console.log(JSON.stringify(created, null, 2));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
console.log();
|
|
121
|
+
console.log(fmt.success(`Created ${created.key_id}`));
|
|
122
|
+
console.log();
|
|
123
|
+
console.log(fmt.label(" Name: ", ` ${created.name}`));
|
|
124
|
+
console.log(fmt.label(" Scopes: ", ` ${(created.scopes ?? []).join(", ")}`));
|
|
125
|
+
console.log(fmt.label(" Created: ", ` ${created.created_at}`));
|
|
126
|
+
console.log();
|
|
127
|
+
console.log(fmt.warn(" Cleartext (shown once — copy now):"));
|
|
128
|
+
console.log(` ${created.key}`);
|
|
129
|
+
console.log();
|
|
130
|
+
console.log(fmt.dim(" This is the only time the cleartext is returned."));
|
|
131
|
+
console.log(fmt.dim(" Mnemom stores only the SHA-256 hash; the key cannot be retrieved later."));
|
|
132
|
+
console.log();
|
|
133
|
+
}
|
|
134
|
+
// ─── mnemom api-key rotate ───────────────────────────────────────────────
|
|
135
|
+
export async function apiKeyRotateCommand(keyId, opts) {
|
|
136
|
+
await requireAuth();
|
|
137
|
+
if (!keyId) {
|
|
138
|
+
console.error(fmt.error("Usage: mnemom api-key rotate <key_id>"));
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
let rotated;
|
|
142
|
+
try {
|
|
143
|
+
rotated = await rotateApiKey(keyId);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
console.error(fmt.error(`Rotate failed: ${err instanceof Error ? err.message : err}`));
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
if (opts.json) {
|
|
150
|
+
console.log(JSON.stringify(rotated, null, 2));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
console.log();
|
|
154
|
+
console.log(fmt.success(`Rotated. Old key ${keyId} is now revoked.`));
|
|
155
|
+
console.log();
|
|
156
|
+
console.log(fmt.label(" New key id:", ` ${rotated.key_id}`));
|
|
157
|
+
console.log(fmt.label(" Name: ", ` ${rotated.name}`));
|
|
158
|
+
console.log(fmt.label(" Scopes: ", ` ${(rotated.scopes ?? []).join(", ")}`));
|
|
159
|
+
console.log();
|
|
160
|
+
console.log(fmt.warn(" New cleartext (shown once — copy now):"));
|
|
161
|
+
console.log(` ${rotated.key}`);
|
|
162
|
+
console.log();
|
|
163
|
+
}
|
|
164
|
+
// ─── mnemom api-key revoke ───────────────────────────────────────────────
|
|
165
|
+
export async function apiKeyRevokeCommand(keyId) {
|
|
166
|
+
await requireAuth();
|
|
167
|
+
if (!keyId) {
|
|
168
|
+
console.error(fmt.error("Usage: mnemom api-key revoke <key_id>"));
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
await revokeApiKey(keyId);
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
console.error(fmt.error(`Revoke failed: ${err instanceof Error ? err.message : err}`));
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
console.log(fmt.success(`Revoked ${keyId}.`));
|
|
179
|
+
}
|
package/dist/commands/auth.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { getAuthInfo, clearAuthTokens } from "../lib/auth.js";
|
|
2
|
-
import { loginWithBrowser, loginWithPassword } from "../lib/auth.js";
|
|
1
|
+
import { getAuthInfo, clearAuthTokens, loginWithBrowser, loginWithPassword } from "../lib/auth.js";
|
|
3
2
|
import { fmt } from "../lib/format.js";
|
|
4
3
|
import { askInput } from "../lib/prompt.js";
|
|
5
4
|
export async function loginCommand(options = {}) {
|
package/dist/commands/card.js
CHANGED
|
@@ -7,7 +7,7 @@ import { ALIGNMENT_CARD_MAX_BYTES, getAlignmentCard, putAlignmentCard, resolveAg
|
|
|
7
7
|
import { requireAuth } from "../lib/auth.js";
|
|
8
8
|
import { fmt } from "../lib/format.js";
|
|
9
9
|
import { askYesNo, isInteractive } from "../lib/prompt.js";
|
|
10
|
-
import { evaluatePolicy
|
|
10
|
+
import { evaluatePolicy } from "@mnemom/policy-engine";
|
|
11
11
|
function detectFormat(filePath) {
|
|
12
12
|
const ext = path.extname(filePath).toLowerCase();
|
|
13
13
|
if (ext === ".yaml" || ext === ".yml")
|
|
@@ -201,7 +201,7 @@ export function validateUnifiedCard(card) {
|
|
|
201
201
|
message: "Must contain at least one value.",
|
|
202
202
|
});
|
|
203
203
|
}
|
|
204
|
-
else if (!decl.every(s => typeof s === "string")) {
|
|
204
|
+
else if (!decl.every((s) => typeof s === "string")) {
|
|
205
205
|
checks.push({
|
|
206
206
|
name: "values.declared",
|
|
207
207
|
passed: false,
|
|
@@ -238,7 +238,8 @@ export function validateUnifiedCard(card) {
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
// hierarchy enum
|
|
241
|
-
if (v.hierarchy !== undefined &&
|
|
241
|
+
if (v.hierarchy !== undefined &&
|
|
242
|
+
!VALUE_HIERARCHIES.includes(String(v.hierarchy))) {
|
|
242
243
|
checks.push({
|
|
243
244
|
name: "values.hierarchy",
|
|
244
245
|
passed: false,
|
|
@@ -247,7 +248,8 @@ export function validateUnifiedCard(card) {
|
|
|
247
248
|
}
|
|
248
249
|
}
|
|
249
250
|
// ── autonomy.bounded_actions (required, non-empty; disjoint from forbidden_actions) ──
|
|
250
|
-
if (!isObj(card.autonomy) ||
|
|
251
|
+
if (!isObj(card.autonomy) ||
|
|
252
|
+
!Array.isArray(card.autonomy.bounded_actions)) {
|
|
251
253
|
checks.push({
|
|
252
254
|
name: "autonomy.bounded_actions",
|
|
253
255
|
passed: false,
|
|
@@ -428,7 +430,8 @@ export function validateUnifiedCard(card) {
|
|
|
428
430
|
message: "Required (non-empty string).",
|
|
429
431
|
});
|
|
430
432
|
}
|
|
431
|
-
if (cv.severity !== undefined &&
|
|
433
|
+
if (cv.severity !== undefined &&
|
|
434
|
+
!CONSCIENCE_SEVERITIES.includes(String(cv.severity))) {
|
|
432
435
|
checks.push({
|
|
433
436
|
name: `conscience.values[${i}].severity`,
|
|
434
437
|
passed: false,
|
|
@@ -676,20 +679,21 @@ export async function cardEditCommand(agentName, options = {}) {
|
|
|
676
679
|
if (!original) {
|
|
677
680
|
console.log(fmt.warn("No alignment card found. Creating a template..."));
|
|
678
681
|
}
|
|
679
|
-
const cardYaml = original ||
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
682
|
+
const cardYaml = original ||
|
|
683
|
+
yaml.dump({
|
|
684
|
+
card_version: "unified/2026-04-26",
|
|
685
|
+
agent_id: agentId,
|
|
686
|
+
autonomy_mode: "observe",
|
|
687
|
+
integrity_mode: "observe",
|
|
688
|
+
principal: { type: "agent", identifier: agentId, relationship: "delegated_authority" },
|
|
689
|
+
values: { declared: ["transparency", "safety", "honesty"] },
|
|
690
|
+
autonomy: {
|
|
691
|
+
bounded_actions: ["respond_to_prompts"],
|
|
692
|
+
forbidden_actions: [],
|
|
693
|
+
escalation_triggers: [],
|
|
694
|
+
},
|
|
695
|
+
audit: { retention_days: 30, queryable: false, trace_format: "otel" },
|
|
696
|
+
}, { lineWidth: 120, noRefs: true });
|
|
693
697
|
// Write to temp file
|
|
694
698
|
const tmpDir = os.tmpdir();
|
|
695
699
|
const tmpFile = path.join(tmpDir, `mnemom-card-${agentId}.yaml`);
|
|
@@ -703,7 +707,9 @@ export async function cardEditCommand(agentName, options = {}) {
|
|
|
703
707
|
try {
|
|
704
708
|
fs.unlinkSync(tmpFile);
|
|
705
709
|
}
|
|
706
|
-
catch {
|
|
710
|
+
catch {
|
|
711
|
+
/* ignore */
|
|
712
|
+
}
|
|
707
713
|
process.exit(1);
|
|
708
714
|
}
|
|
709
715
|
// Read back and compare
|
|
@@ -711,7 +717,9 @@ export async function cardEditCommand(agentName, options = {}) {
|
|
|
711
717
|
try {
|
|
712
718
|
fs.unlinkSync(tmpFile);
|
|
713
719
|
}
|
|
714
|
-
catch {
|
|
720
|
+
catch {
|
|
721
|
+
/* ignore */
|
|
722
|
+
}
|
|
715
723
|
if (edited === cardYaml) {
|
|
716
724
|
console.log("\nNo changes made.\n");
|
|
717
725
|
return;
|
|
@@ -808,7 +816,10 @@ export async function cardEvaluateCommand(file, options) {
|
|
|
808
816
|
// 2. Parse tool list from --tools or --tool-manifest
|
|
809
817
|
let tools = [];
|
|
810
818
|
if (options.tools) {
|
|
811
|
-
tools = options.tools
|
|
819
|
+
tools = options.tools
|
|
820
|
+
.split(",")
|
|
821
|
+
.map((t) => ({ name: t.trim() }))
|
|
822
|
+
.filter((t) => t.name);
|
|
812
823
|
}
|
|
813
824
|
else if (options.toolManifest) {
|
|
814
825
|
const manifestPath = path.resolve(options.toolManifest);
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mnemom governance` — operator CLI for governance signals (ADR-048).
|
|
3
|
+
*
|
|
4
|
+
* Subcommands:
|
|
5
|
+
*
|
|
6
|
+
* signals list | show | ack | resolve | dismiss
|
|
7
|
+
* destinations list | add | remove | test
|
|
8
|
+
* rules list | add | remove
|
|
9
|
+
*
|
|
10
|
+
* The signal surface is operator-actionable: cron-driven sideband
|
|
11
|
+
* detections, future protection / posture observations. Distinct from
|
|
12
|
+
* `mnemom advisories list` (now narrowed to runtime.* / manual.* per
|
|
13
|
+
* ADR-048 §1).
|
|
14
|
+
*/
|
|
15
|
+
interface ListOpts {
|
|
16
|
+
org?: string;
|
|
17
|
+
team?: string;
|
|
18
|
+
agent?: string;
|
|
19
|
+
source?: string;
|
|
20
|
+
severity?: string;
|
|
21
|
+
status?: string;
|
|
22
|
+
scope?: string;
|
|
23
|
+
patternType?: string;
|
|
24
|
+
limit?: string;
|
|
25
|
+
since?: string;
|
|
26
|
+
json?: boolean;
|
|
27
|
+
}
|
|
28
|
+
interface AckOpts {
|
|
29
|
+
action?: string;
|
|
30
|
+
json?: boolean;
|
|
31
|
+
}
|
|
32
|
+
interface ResolveOpts {
|
|
33
|
+
status: string;
|
|
34
|
+
action?: string;
|
|
35
|
+
json?: boolean;
|
|
36
|
+
}
|
|
37
|
+
interface DismissOpts {
|
|
38
|
+
reason?: string;
|
|
39
|
+
json?: boolean;
|
|
40
|
+
}
|
|
41
|
+
interface DestAddOpts {
|
|
42
|
+
org: string;
|
|
43
|
+
channel: string;
|
|
44
|
+
config: string;
|
|
45
|
+
name?: string;
|
|
46
|
+
filter?: string;
|
|
47
|
+
json?: boolean;
|
|
48
|
+
}
|
|
49
|
+
interface RuleAddOpts {
|
|
50
|
+
org: string;
|
|
51
|
+
name: string;
|
|
52
|
+
predicate: string;
|
|
53
|
+
destinations: string;
|
|
54
|
+
json?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export declare function governanceSignalsListCommand(opts: ListOpts): Promise<void>;
|
|
57
|
+
export declare function governanceSignalsShowCommand(signalId: string, opts: {
|
|
58
|
+
json?: boolean;
|
|
59
|
+
}): Promise<void>;
|
|
60
|
+
export declare function governanceSignalsAckCommand(signalId: string, opts: AckOpts): Promise<void>;
|
|
61
|
+
export declare function governanceSignalsResolveCommand(signalId: string, opts: ResolveOpts): Promise<void>;
|
|
62
|
+
export declare function governanceSignalsDismissCommand(signalId: string, opts: DismissOpts): Promise<void>;
|
|
63
|
+
export declare function governanceDestinationsListCommand(opts: {
|
|
64
|
+
org: string;
|
|
65
|
+
json?: boolean;
|
|
66
|
+
}): Promise<void>;
|
|
67
|
+
export declare function governanceDestinationsAddCommand(opts: DestAddOpts): Promise<void>;
|
|
68
|
+
export declare function governanceDestinationsRemoveCommand(destinationId: string, opts: {
|
|
69
|
+
org: string;
|
|
70
|
+
json?: boolean;
|
|
71
|
+
}): Promise<void>;
|
|
72
|
+
export declare function governanceDestinationsTestCommand(destinationId: string, opts: {
|
|
73
|
+
org: string;
|
|
74
|
+
json?: boolean;
|
|
75
|
+
}): Promise<void>;
|
|
76
|
+
export declare function governanceRulesListCommand(opts: {
|
|
77
|
+
org: string;
|
|
78
|
+
json?: boolean;
|
|
79
|
+
}): Promise<void>;
|
|
80
|
+
export declare function governanceRulesAddCommand(opts: RuleAddOpts): Promise<void>;
|
|
81
|
+
export declare function governanceRulesRemoveCommand(ruleId: string, opts: {
|
|
82
|
+
org: string;
|
|
83
|
+
json?: boolean;
|
|
84
|
+
}): Promise<void>;
|
|
85
|
+
export {};
|