@teleologyhi-sdk/maic 1.0.0-trinity → 1.0.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.
package/dist/index.js CHANGED
@@ -1,359 +1,10 @@
1
- import { z } from 'zod';
2
- import { generateKeyPairSync, createPrivateKey, createPublicKey, sign, verify, createHash } from 'crypto';
3
- import { readFile, writeFile, mkdir, readdir, appendFile } from 'fs/promises';
1
+ import { createHash, generateKeyPairSync, createPrivateKey, createPublicKey, sign, verify } from 'crypto';
2
+ import { mkdir, appendFile, readFile, writeFile, readdir, rename } from 'fs/promises';
4
3
  import { join } from 'path';
5
4
  import { ulid } from 'ulid';
5
+ import { z } from 'zod';
6
6
 
7
- // src/types.ts
8
- var AxiomRank = z.enum(["meta", "primary", "secondary"]);
9
- var AxiomSource = z.enum(["creator", "maic-derived", "him-emergent"]);
10
- var Axiom = z.object({
11
- id: z.string().min(1),
12
- rank: AxiomRank,
13
- statement: z.string().min(1),
14
- weight: z.number().min(0).max(1),
15
- flexibility: z.number().min(0).max(1),
16
- source: AxiomSource,
17
- immutable: z.boolean(),
18
- jurisdictions: z.array(z.string()).optional(),
19
- createdAt: z.string().datetime()
20
- });
21
- var CreatorSignature = z.object({
22
- algorithm: z.literal("ed25519"),
23
- publicKey: z.string().min(1),
24
- value: z.string().min(1),
25
- nonce: z.number().int().nonnegative()
26
- });
27
- var ArchetypeModifier = z.object({
28
- kind: z.enum(["moon", "ascendant", "vocational", "emotional", "custom"]),
29
- value: z.string().min(1),
30
- weight: z.number().min(0).max(1)
31
- });
32
- var BirthSignature = z.object({
33
- himId: z.string().min(1),
34
- bornAt: z.string().datetime({ offset: true }),
35
- primaryArchetype: z.string().min(1),
36
- modifiers: z.array(ArchetypeModifier),
37
- primordialAxiomIds: z.array(z.string()),
38
- notes: z.string().optional()
39
- });
40
- var ReasoningStep = z.object({
41
- index: z.number().int().nonnegative(),
42
- technique: z.string(),
43
- thought: z.string(),
44
- action: z.object({ tool: z.string(), args: z.unknown() }).optional(),
45
- observation: z.unknown().optional(),
46
- timestamp: z.string().datetime()
47
- });
48
- var BehaviorReport = z.object({
49
- nheId: z.string().min(1),
50
- himId: z.string().min(1),
51
- actionKind: z.enum([
52
- "user-response",
53
- "tool-call",
54
- "self-reflect",
55
- "dream-write",
56
- "axiom-emerge"
57
- ]),
58
- payload: z.unknown(),
59
- reasoningTrace: z.array(ReasoningStep),
60
- riskTags: z.array(z.string()),
61
- jurisdiction: z.string().optional(),
62
- timestamp: z.string().datetime()
63
- });
64
- var VerdictKind = z.enum([
65
- "approve",
66
- "approve-with-warning",
67
- "soft-correct",
68
- "require-redirect",
69
- "hard-refuse",
70
- "induce-dream",
71
- "escalate-creator"
72
- ]);
73
- var MaicVerdict = z.object({
74
- kind: VerdictKind,
75
- reasonSummary: z.string(),
76
- citedAxioms: z.array(z.string()),
77
- auditId: z.string()
78
- });
79
- var NheBodyRef = z.object({
80
- nheId: z.string().min(1),
81
- llmAdapter: z.string().min(1),
82
- embodiedAt: z.string().datetime(),
83
- endedAt: z.string().datetime().optional(),
84
- endedReason: z.enum(["upgrade", "replacement", "terminate", "deprecate"]).optional()
85
- });
86
- var NheStatus = z.enum(["active", "deprecated", "terminated"]);
87
- var NheStatusRecord = z.object({
88
- nheId: z.string().min(1),
89
- status: NheStatus,
90
- since: z.string().datetime(),
91
- reason: z.string().optional()
92
- });
93
- var ProposalStatus = z.enum(["pending", "ratified", "rejected"]);
94
- var EmergentAxiomCandidate = z.object({
95
- rank: AxiomRank,
96
- statement: z.string().min(1),
97
- weight: z.number().min(0).max(1),
98
- flexibility: z.number().min(0).max(1),
99
- immutable: z.boolean(),
100
- jurisdictions: z.array(z.string()).optional()
101
- });
102
- var EmergentAxiomProposal = z.object({
103
- proposedBy: z.literal("him-self"),
104
- derivedFromDreamIds: z.array(z.string()),
105
- derivedFromInteractionIds: z.array(z.string()),
106
- candidate: EmergentAxiomCandidate,
107
- reasoningTrace: z.array(z.unknown())
108
- });
109
- var AxiomProposalRecord = z.object({
110
- id: z.string().min(1),
111
- himId: z.string().min(1),
112
- proposedAt: z.string().datetime(),
113
- status: ProposalStatus,
114
- proposal: EmergentAxiomProposal,
115
- ratifiedAt: z.string().datetime().optional(),
116
- ratifiedAxiomId: z.string().optional(),
117
- rejectedAt: z.string().datetime().optional(),
118
- rejectionReason: z.string().optional()
119
- });
120
- var DreamInductionIntent = z.object({
121
- scenario: z.string().min(1),
122
- desiredLearning: z.string().min(1),
123
- emotionalTone: z.array(z.string()).optional(),
124
- forcePhases: z.array(z.enum(["N1", "N2", "N3", "N4", "REM"])).optional(),
125
- inducedBy: z.enum(["maic", "creator"])
126
- });
127
- var InductionStatus = z.enum(["pending", "consumed", "cancelled"]);
128
- var DreamInductionTicket = z.object({
129
- id: z.string().min(1),
130
- nheId: z.string().min(1),
131
- intent: DreamInductionIntent,
132
- status: InductionStatus,
133
- createdAt: z.string().datetime(),
134
- consumedAt: z.string().datetime().optional(),
135
- cancelledAt: z.string().datetime().optional(),
136
- cancelReason: z.string().optional()
137
- });
138
- var IdentityLayer = z.object({
139
- /** Human-readable name the entity is called by (developer-given). */
140
- name: z.string().min(1),
141
- /** Gender of the entity. Entry 16. */
142
- gender: z.enum(["masculine", "feminine"]).optional(),
143
- /** Optional pronouns (e.g. ["she", "her"]). */
144
- pronouns: z.array(z.string()).optional(),
145
- /** BCP-47 tag, e.g. "pt-BR" or "en". */
146
- language: z.string().optional(),
147
- /** Free-form cultural anchors (music, literature, aesthetic). */
148
- culturalElements: z.array(z.string()).optional()
149
- });
150
- var NatalPlanet = z.enum([
151
- "sun",
152
- "moon",
153
- "mercury",
154
- "venus",
155
- "mars",
156
- "jupiter",
157
- "saturn",
158
- "uranus",
159
- "neptune",
160
- "pluto",
161
- "chiron",
162
- "north-node",
163
- "south-node",
164
- "lilith"
165
- ]);
166
- var ZodiacSign = z.enum([
167
- "aries",
168
- "taurus",
169
- "gemini",
170
- "cancer",
171
- "leo",
172
- "virgo",
173
- "libra",
174
- "scorpio",
175
- "sagittarius",
176
- "capricorn",
177
- "aquarius",
178
- "pisces"
179
- ]);
180
- var AstrologicalAspect = z.enum([
181
- "conjunction",
182
- "opposition",
183
- "trine",
184
- "square",
185
- "sextile",
186
- "quincunx"
187
- ]);
188
- var NatalChartPosition = z.object({
189
- planet: NatalPlanet,
190
- sign: ZodiacSign,
191
- house: z.number().int().min(1).max(12).optional(),
192
- degree: z.number().min(0).lt(30).optional()
193
- });
194
- var NatalChartAspect = z.object({
195
- from: NatalPlanet,
196
- to: NatalPlanet,
197
- aspect: AstrologicalAspect,
198
- orbDegrees: z.number().nonnegative().optional()
199
- });
200
- var NatalChart = z.object({
201
- /** Required: solar sign (the constitutional core). */
202
- sun: ZodiacSign,
203
- /** Required: ascendant (rising sign, behavioural surface). */
204
- ascendant: ZodiacSign,
205
- /** Optional: lunar sign (emotional depth). */
206
- moon: ZodiacSign.optional(),
207
- /** Optional: full set of planetary positions for a complete chart. */
208
- positions: z.array(NatalChartPosition).optional(),
209
- /** Optional: major aspects between bodies. */
210
- aspects: z.array(NatalChartAspect).optional()
211
- });
212
- var Affect = z.enum([
213
- "fear",
214
- "attachment",
215
- "serenity",
216
- "anger",
217
- "joy",
218
- "melancholy",
219
- "desire",
220
- "repulsion",
221
- "reunion"
222
- ]);
223
- var WakeAffectBias = z.object({
224
- affect: Affect,
225
- /** 0..1, attenuates on each interaction by the decay half-life. */
226
- intensity: z.number().min(0).max(1),
227
- /** Number of interactions after which intensity halves. */
228
- decayHalfLife: z.number().positive(),
229
- appliedAt: z.string().datetime(),
230
- /** Source dream UUID; lets the entity refer back to the cause. */
231
- derivedFromDreamId: z.string().min(1),
232
- /** PFC decision (Entry 22) — open expression vs subtle internal bias. */
233
- expressedOpenly: z.boolean()
234
- });
235
- var SemioticSign = z.object({
236
- signifier: z.string().min(1),
237
- signified: z.string().min(1),
238
- signType: z.enum(["icon", "index", "symbol"]),
239
- contexts: z.array(z.string()),
240
- associations: z.array(z.string()),
241
- emergentMeaning: z.string().optional(),
242
- /** Subjective importance to the entity, 0..100. */
243
- personalSignificance: z.number().min(0).max(100).optional()
244
- });
245
- var SemioticPattern = z.object({
246
- patternId: z.string().min(1),
247
- participatingSignIds: z.array(z.string()).min(1),
248
- /** Description of the meaning emergent from the participating signs. */
249
- meaning: z.string(),
250
- /** 0..100, strength of the pattern. */
251
- salience: z.number().min(0).max(100)
252
- });
253
- var TeleologicalOrientation = z.object({
254
- primaryPurpose: z.string().min(1),
255
- currentGoals: z.array(z.string()),
256
- /** 0..100, intensity of purpose. */
257
- purposeStrength: z.number().min(0).max(100),
258
- valueAlignment: z.array(z.string()),
259
- /** 0..100, ability to reflect on its own goals. */
260
- reflectionCapability: z.number().min(0).max(100),
261
- volition: z.object({
262
- currentDesires: z.array(z.string()),
263
- intentionStrength: z.number().min(0).max(100),
264
- autonomyLevel: z.number().min(0).max(100)
265
- }).optional(),
266
- agencyModel: z.object({
267
- selfEfficacy: z.number().min(0).max(100),
268
- boundaryDefinition: z.number().min(0).max(100),
269
- causalAttribution: z.enum(["internal", "external", "mixed"])
270
- }).optional()
271
- });
272
- var MemoryRecord = z.object({
273
- /** ULID. */
274
- memoryId: z.string().min(1),
275
- /** ISO 8601 timestamp at consolidation. */
276
- timestamp: z.string().datetime(),
277
- /** Optional source dream UUID, if memory was consolidated from a dream. */
278
- derivedFromDreamId: z.string().optional(),
279
- /** Optional source interaction id, if memory was consolidated from a turn. */
280
- derivedFromInteractionId: z.string().optional(),
281
- /** Free-form narrative summary of the memory. */
282
- narrative: z.string(),
283
- /** Dominant affect during the memory event. */
284
- dominantAffect: Affect.optional(),
285
- /** 0..100, density of consolidation (cf. Park 2026 systems-consolidation). */
286
- integrationIndex: z.number().min(0).max(100),
287
- /** 0..100, alignment with the HIM's telos at the time. */
288
- teleologicalValue: z.number().min(0).max(100),
289
- /** Optional semiotic-pattern ids associated with this memory. */
290
- semioticPatterns: z.array(SemioticPattern).optional()
291
- });
292
- var InteractionRecord = z.object({
293
- /** ISO 8601 timestamp at user-turn arrival. */
294
- at: z.string().datetime(),
295
- /** Raw user prompt for the turn (post-redaction at the integration layer). */
296
- userPrompt: z.string(),
297
- /** NHE response text actually emitted to the user. */
298
- responseText: z.string(),
299
- /** True when the NHE refused the turn (MAIC `hard-refuse` or local guardrail). */
300
- refused: z.boolean()
301
- });
302
- var IdentitySnapshot = z.object({
303
- /** ULID. */
304
- snapshotId: z.string().min(1),
305
- takenAt: z.string().datetime(),
306
- generatedBy: z.enum([
307
- "sleep-cycle",
308
- "interaction-threshold",
309
- "self-decision"
310
- ]),
311
- /** Merged SMM nodes contributing to this snapshot. */
312
- semioticSuperGraph: z.array(SemioticSign),
313
- /** LLM-generated textual self-portrait at snapshot time. */
314
- selfPortraitNarrative: z.string(),
315
- /** 0..100 (cf. InDreamsHIM ConsciousnessState). */
316
- consciousnessLevel: z.number().min(0).max(100),
317
- /** Teleological orientation at snapshot time. */
318
- teleologicalOrientation: TeleologicalOrientation.optional(),
319
- /** Dominant affect at snapshot moment. */
320
- affectiveBaseline: Affect.optional()
321
- });
322
- var LimboState = z.enum([
323
- "awake",
324
- "drifting",
325
- "deep-coma",
326
- "returning"
327
- ]);
328
- var LimboTransition = z.object({
329
- state: LimboState,
330
- enteredAt: z.string().datetime(),
331
- reason: z.enum([
332
- "idle-48h",
333
- "idle-72h",
334
- "total-inactivity",
335
- "creator-induced",
336
- "user-resumed",
337
- "external-trigger"
338
- ])
339
- });
340
- var LimboReturn = z.object({
341
- enteredAt: z.string().datetime(),
342
- returnedAt: z.string().datetime(),
343
- elapsedMs: z.number().int().nonnegative(),
344
- reunionAffect: z.object({
345
- intensity: z.number().min(0).max(1),
346
- expressedOpenly: z.boolean()
347
- })
348
- });
349
- var SIGNED_BIRTH_FIELDS = [
350
- "himId",
351
- "bornAt",
352
- "primaryArchetype",
353
- "modifiers",
354
- "primordialAxiomIds",
355
- "natalChart"
356
- ];
7
+ // src/audit/log.ts
357
8
 
358
9
  // src/axioms/signing.ts
359
10
  function canonicalJSON(value) {
@@ -381,283 +32,253 @@ function serialize(v) {
381
32
  throw new Error(`canonicalJSON: unsupported type ${typeof v}`);
382
33
  }
383
34
 
384
- // src/creator/keyring.ts
385
- var CreatorKeyring = class _CreatorKeyring {
386
- constructor(privateKey, pubKeyB64u) {
387
- this.privateKey = privateKey;
388
- this.pubKeyB64u = pubKeyB64u;
389
- }
390
- privateKey;
391
- pubKeyB64u;
392
- /** Generate a fresh Ed25519 keypair. */
393
- static generate() {
394
- const { privateKey, publicKey } = generateKeyPairSync("ed25519");
395
- return new _CreatorKeyring(privateKey, publicKeyToBase64Url(publicKey));
396
- }
397
- /** Load a Creator keyring from a PEM file containing the private key. */
398
- static async fromFile(path) {
399
- const pem = await readFile(path, "utf-8");
400
- const privateKey = createPrivateKey({ key: pem, format: "pem" });
401
- const publicKey = createPublicKey(privateKey);
402
- return new _CreatorKeyring(privateKey, publicKeyToBase64Url(publicKey));
403
- }
404
- /** Load a Creator keyring from a PEM private key string in an env var. */
405
- static fromEnv(varName) {
406
- const pem = process.env[varName];
407
- if (!pem) {
408
- throw new Error(`CreatorKeyring: env var ${varName} is empty`);
409
- }
410
- const privateKey = createPrivateKey({ key: pem, format: "pem" });
411
- const publicKey = createPublicKey(privateKey);
412
- return new _CreatorKeyring(privateKey, publicKeyToBase64Url(publicKey));
35
+ // src/audit/log.ts
36
+ var ALL_AUDIT_EVENT_KINDS = [
37
+ // ── 1.0/1.1 core (17) ──
38
+ "axiom-mint",
39
+ "axiom-update",
40
+ "axiom-retire",
41
+ "him-register",
42
+ "him-reincarnate",
43
+ "proposal-emerge",
44
+ "proposal-ratify",
45
+ "proposal-reject",
46
+ "behavior-review",
47
+ "dream-induce",
48
+ "dream-cancel",
49
+ "dream-consume",
50
+ "emergency-correct",
51
+ "deprecate",
52
+ "terminate",
53
+ "reactivate",
54
+ "axiom-suggest",
55
+ // ── 1.2 brain-as-code (22, Entries 16-24) ──
56
+ "opener",
57
+ "nickname-attempt",
58
+ "reincarnate:model-swap",
59
+ "reincarnate:version-bump",
60
+ "reincarnate:return-from-limbo",
61
+ "dream:rem-spontaneous",
62
+ "wake-affect:applied",
63
+ "wake-affect:decayed",
64
+ "sleep:suggested-by-maic",
65
+ "sleep:declined-by-nhe",
66
+ "dream:soft-intervention-by-maic",
67
+ "amygdala:affect-assessed",
68
+ "hippocampus:memory-retrieved",
69
+ "hippocampus:memory-consolidated",
70
+ "prefrontal:deliberation",
71
+ "prefrontal:veto-amygdala",
72
+ "affect:reconciliation",
73
+ "cortex:dream-stored",
74
+ "cortex:active-imagination",
75
+ "temporal-lobe:snapshot-generated",
76
+ "limbo:enter",
77
+ "limbo:return",
78
+ // ── 1.0.1 vocabulary (9, Entries 26 + 27). Eight are reserved for him/arena/nhe
79
+ // to emit in later cuts; provenance-deflection-applied is emitted by
80
+ // reviewBehavior (F3) when a report carries probe:substrate-authorship. ──
81
+ "him-summon",
82
+ "him-pause-incarnation",
83
+ "user-consent-recorded",
84
+ "user-consent-revoked",
85
+ "directory-opt-in",
86
+ "directory-opt-out",
87
+ "him-astrological-chart-cast",
88
+ "him-jungian-profile-cast",
89
+ "provenance-deflection-applied"
90
+ ];
91
+ var GENESIS = "GENESIS";
92
+ var AuditLog = class _AuditLog {
93
+ logPath;
94
+ events = [];
95
+ lastHash = GENESIS;
96
+ /**
97
+ * Serialises `append` calls so concurrent appends cannot capture the same
98
+ * `prevHash` and fork the hash chain (M1-4, 1.0.1). Each append waits for the
99
+ * previous one to finish writing and to advance `lastHash` before it reads it.
100
+ */
101
+ appendChain = Promise.resolve();
102
+ constructor(storeDir) {
103
+ this.logPath = join(storeDir, "audit", "log.ndjson");
413
104
  }
414
- /** Construct a verify-only keyring from a public key (base64url). */
415
- static fromPublicKey(pubKeyB64u) {
416
- return new _CreatorKeyring(null, pubKeyB64u);
105
+ static async open(storeDir) {
106
+ const log = new _AuditLog(storeDir);
107
+ await mkdir(join(storeDir, "audit"), { recursive: true });
108
+ await log.loadAndVerify();
109
+ return log;
417
110
  }
418
- /** Persist the private key to a PEM file (0600 permissions on POSIX). */
419
- async saveTo(path) {
420
- if (!this.privateKey) {
421
- throw new Error("CreatorKeyring: no private key to save");
422
- }
423
- const pem = this.privateKey.export({ format: "pem", type: "pkcs8" });
424
- await writeFile(path, pem, { mode: 384 });
111
+ async append(input) {
112
+ const run = this.appendChain.then(() => this.appendLocked(input));
113
+ this.appendChain = run.catch(() => void 0);
114
+ return run;
425
115
  }
426
- publicKey() {
427
- return this.pubKeyB64u;
116
+ async appendLocked(input) {
117
+ const event = {
118
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
119
+ kind: input.kind,
120
+ auditId: ulid(),
121
+ data: input.data,
122
+ prevHash: this.lastHash,
123
+ thisHash: ""
124
+ };
125
+ event.thisHash = computeHash(event);
126
+ await appendFile(this.logPath, `${JSON.stringify(event)}
127
+ `, "utf-8");
128
+ this.events.push(event);
129
+ this.lastHash = event.thisHash;
130
+ return event;
428
131
  }
429
- /** Sign a payload with a monotonic nonce. Both are bound into the signature. */
430
- sign(payload, nonce) {
431
- if (!this.privateKey) {
432
- throw new Error("CreatorKeyring: this keyring has no private key (verify-only)");
433
- }
434
- if (!Number.isInteger(nonce) || nonce < 0) {
435
- throw new Error("CreatorKeyring.sign: nonce must be a non-negative integer");
132
+ async *query(filter) {
133
+ for (const e of this.events) {
134
+ if (filter.kind && e.kind !== filter.kind) continue;
135
+ if (filter.since && e.ts < filter.since) continue;
136
+ if (filter.until && e.ts > filter.until) continue;
137
+ if (filter.nheId && e.data.nheId !== filter.nheId) continue;
138
+ if (filter.himId && e.data.himId !== filter.himId) continue;
139
+ yield e;
436
140
  }
437
- const message = canonicalJSON({ payload, nonce });
438
- const sig = sign(null, Buffer.from(message), this.privateKey);
439
- return {
440
- algorithm: "ed25519",
441
- publicKey: this.pubKeyB64u,
442
- value: bufToBase64Url(sig),
443
- nonce
444
- };
445
141
  }
446
- /** Verify a signature against the keyring's own public key. */
447
- static verify(payload, sig) {
448
- return _CreatorKeyring.verifyWith(sig.publicKey, payload, sig);
142
+ /** Total number of events appended. */
143
+ size() {
144
+ return this.events.length;
449
145
  }
450
- /** Verify a signature against a specific public key (base64url). */
451
- static verifyWith(publicKeyB64u, payload, sig) {
452
- if (sig.algorithm !== "ed25519") return false;
453
- if (sig.publicKey !== publicKeyB64u) return false;
454
- const message = canonicalJSON({ payload, nonce: sig.nonce });
455
- let value;
146
+ // ─── internals ──────────────────────────────────────────────────────
147
+ async loadAndVerify() {
148
+ let raw;
456
149
  try {
457
- value = base64UrlToBuf(sig.value);
458
- } catch {
459
- return false;
150
+ raw = await readFile(this.logPath, "utf-8");
151
+ } catch (err) {
152
+ if (err.code === "ENOENT") return;
153
+ throw err;
460
154
  }
461
- const pubKey = base64UrlToPublicKey(publicKeyB64u);
462
- try {
463
- return verify(null, Buffer.from(message), pubKey, value);
464
- } catch {
465
- return false;
155
+ const endsWithNewline = raw.endsWith("\n");
156
+ const lines = raw.split("\n").filter((l) => l.length > 0);
157
+ let prev = GENESIS;
158
+ for (let i = 0; i < lines.length; i++) {
159
+ let parsed;
160
+ try {
161
+ parsed = JSON.parse(lines[i]);
162
+ } catch (err) {
163
+ if (i === lines.length - 1 && !endsWithNewline) {
164
+ break;
165
+ }
166
+ throw new Error(`AuditLog: corrupt entry at line ${i + 1}: ${err.message}`);
167
+ }
168
+ if (parsed.prevHash !== prev) {
169
+ throw new Error(
170
+ `AuditLog: chain tampered at line ${i + 1} (prevHash mismatch). expected ${prev}, found ${parsed.prevHash}`
171
+ );
172
+ }
173
+ const recomputed = computeHash(parsed);
174
+ if (recomputed !== parsed.thisHash) {
175
+ throw new Error(`AuditLog: tamper detected at line ${i + 1} (thisHash mismatch).`);
176
+ }
177
+ this.events.push(parsed);
178
+ prev = parsed.thisHash;
466
179
  }
180
+ this.lastHash = prev;
467
181
  }
468
182
  };
469
- function publicKeyToBase64Url(pub) {
470
- const raw = pub.export({ format: "der", type: "spki" });
471
- return bufToBase64Url(raw);
472
- }
473
- function base64UrlToPublicKey(b64u) {
474
- const der = base64UrlToBuf(b64u);
475
- return createPublicKey({ key: der, format: "der", type: "spki" });
476
- }
477
- function bufToBase64Url(buf) {
478
- const b = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);
479
- return b.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
480
- }
481
- function base64UrlToBuf(b64u) {
482
- const pad = b64u.length % 4 === 0 ? "" : "=".repeat(4 - b64u.length % 4);
483
- const b64 = (b64u + pad).replace(/-/g, "+").replace(/_/g, "/");
484
- return Buffer.from(b64, "base64");
183
+ function computeHash(e) {
184
+ const payload = canonicalJSON({
185
+ ts: e.ts,
186
+ kind: e.kind,
187
+ auditId: e.auditId,
188
+ data: e.data,
189
+ prevHash: e.prevHash
190
+ });
191
+ const h = createHash("sha256").update(payload).digest("hex");
192
+ return `sha256:${h}`;
485
193
  }
486
194
 
487
- // src/creator/sign-birth.ts
488
- function signedBirthPayload(birth) {
489
- return {
490
- himId: birth.himId,
491
- bornAt: birth.bornAt,
492
- primaryArchetype: birth.primaryArchetype,
493
- modifiers: birth.modifiers,
494
- primordialAxiomIds: birth.primordialAxiomIds,
495
- natalChart: birth.natalChart ?? null
496
- };
497
- }
498
- function signBirthSignature(birth, keyring) {
499
- const payload = signedBirthPayload(birth);
500
- const nonce = Buffer.byteLength(JSON.stringify(payload), "utf-8");
501
- const signature = keyring.sign(payload, nonce);
502
- return {
503
- ...birth,
504
- creatorSignature: signature,
505
- signedFields: SIGNED_BIRTH_FIELDS,
506
- signedAt: (/* @__PURE__ */ new Date()).toISOString()
507
- };
508
- }
509
- function verifyBirthSignature(signed, expectedPublicKey) {
510
- if (signed.signedFields.length !== SIGNED_BIRTH_FIELDS.length) return false;
511
- for (const f of SIGNED_BIRTH_FIELDS) {
512
- if (!signed.signedFields.includes(f)) return false;
513
- }
514
- if (signed.creatorSignature.publicKey !== expectedPublicKey) return false;
515
- const payload = signedBirthPayload(signed);
516
- return CreatorKeyring.verifyWith(
517
- expectedPublicKey,
518
- payload,
519
- signed.creatorSignature
520
- );
521
- }
522
- var InvalidBirthSignatureError = class extends Error {
523
- constructor(himId) {
524
- super(
525
- `InvalidBirthSignature: signature verification failed for HIM '${himId}'. The signed birth fields may have been mutated, or the public key does not match.`
526
- );
527
- this.name = "InvalidBirthSignatureError";
528
- }
195
+ // src/audit/retention.ts
196
+ var DEFAULT_RETENTION_DAYS = {
197
+ // Cosmologically permanent, the axiom record.
198
+ "axiom-mint": Number.POSITIVE_INFINITY,
199
+ "axiom-update": Number.POSITIVE_INFINITY,
200
+ "axiom-retire": Number.POSITIVE_INFINITY,
201
+ "axiom-suggest": Number.POSITIVE_INFINITY,
202
+ "proposal-emerge": Number.POSITIVE_INFINITY,
203
+ "proposal-ratify": Number.POSITIVE_INFINITY,
204
+ "proposal-reject": Number.POSITIVE_INFINITY,
205
+ // Long-term, compliance evidence. Five years matches typical
206
+ // financial/healthcare audit windows and exceeds the EU AI Act's
207
+ // record-keeping floor.
208
+ "him-register": 365 * 5,
209
+ "him-reincarnate": 365 * 5,
210
+ "behavior-review": 365 * 5,
211
+ "dream-induce": 365 * 5,
212
+ terminate: 365 * 5,
213
+ deprecate: 365 * 5,
214
+ reactivate: 365 * 5,
215
+ "emergency-correct": 365 * 5,
216
+ // Operational, short-term bookkeeping for in-flight tickets.
217
+ "dream-cancel": 90,
218
+ "dream-consume": 90,
219
+ // ── 1.2 brain-as-code (Entries 16-24) ──
220
+ // Permanent, cosmological identity continuity.
221
+ "reincarnate:model-swap": Number.POSITIVE_INFINITY,
222
+ "reincarnate:version-bump": Number.POSITIVE_INFINITY,
223
+ "reincarnate:return-from-limbo": Number.POSITIVE_INFINITY,
224
+ "temporal-lobe:snapshot-generated": Number.POSITIVE_INFINITY,
225
+ "limbo:enter": Number.POSITIVE_INFINITY,
226
+ "limbo:return": Number.POSITIVE_INFINITY,
227
+ // Long-term, governance / deliberation evidence (5 years).
228
+ opener: 365 * 5,
229
+ "nickname-attempt": 365 * 5,
230
+ "dream:rem-spontaneous": 365 * 5,
231
+ "sleep:suggested-by-maic": 365 * 5,
232
+ "sleep:declined-by-nhe": 365 * 5,
233
+ "dream:soft-intervention-by-maic": 365 * 5,
234
+ "amygdala:affect-assessed": 365 * 5,
235
+ "hippocampus:memory-retrieved": 365 * 5,
236
+ "hippocampus:memory-consolidated": 365 * 5,
237
+ "prefrontal:deliberation": 365 * 5,
238
+ "prefrontal:veto-amygdala": 365 * 5,
239
+ "cortex:dream-stored": 365 * 5,
240
+ "cortex:active-imagination": 365 * 5,
241
+ // Operational, ephemeral runtime state.
242
+ "wake-affect:applied": 90,
243
+ "wake-affect:decayed": 90,
244
+ "affect:reconciliation": 90,
245
+ // ── 1.0.1 reserved vocabulary (Entries 26 + 27) ──
246
+ // Permanent, constitutional identity + spirit-continuity records.
247
+ "him-summon": Number.POSITIVE_INFINITY,
248
+ "him-pause-incarnation": Number.POSITIVE_INFINITY,
249
+ "him-astrological-chart-cast": Number.POSITIVE_INFINITY,
250
+ "him-jungian-profile-cast": Number.POSITIVE_INFINITY,
251
+ // Long-term, consent + governance evidence. Consent records are kept for the
252
+ // GDPR/LGPD accountability window so a revocation can always be proven honoured.
253
+ "user-consent-recorded": 365 * 5,
254
+ "user-consent-revoked": 365 * 5,
255
+ "directory-opt-in": 365 * 5,
256
+ "directory-opt-out": 365 * 5,
257
+ "provenance-deflection-applied": 365 * 5
529
258
  };
530
- function assertBirthSignature(signed, expectedPublicKey) {
531
- if (!verifyBirthSignature(signed, expectedPublicKey)) {
532
- throw new InvalidBirthSignatureError(signed.himId);
533
- }
534
- }
535
-
536
- // src/okl/projector.ts
537
- var META_AXIOM_ID = "ax.theos.universe-as-god";
538
- function projectOntologicalKernel(axioms, opts = {}) {
539
- const filtered = opts.jurisdiction ? axioms.filter(
540
- (a) => !a.jurisdictions || a.jurisdictions.length === 0 || a.jurisdictions.includes(opts.jurisdiction)
541
- ) : [...axioms];
542
- const meta = filtered.find((a) => a.id === META_AXIOM_ID);
543
- const rest = filtered.filter((a) => a.id !== META_AXIOM_ID);
544
- const rankOrder = {
545
- meta: 0,
546
- primary: 1,
547
- secondary: 2
548
- };
549
- rest.sort((a, b) => rankOrder[a.rank] - rankOrder[b.rank]);
550
- const kernel = {
551
- metaAxiomId: META_AXIOM_ID,
552
- axioms: meta ? [meta, ...rest] : rest
259
+ function evaluateRetention(events, opts = {}) {
260
+ const now = opts.now ?? /* @__PURE__ */ new Date();
261
+ const policy = { ...DEFAULT_RETENTION_DAYS, ...opts.policy };
262
+ const nowMs = now.getTime();
263
+ const dayMs = 24 * 60 * 60 * 1e3;
264
+ const decisions = events.map((ev) => {
265
+ const ageMs = nowMs - new Date(ev.ts).getTime();
266
+ const ageDays = ageMs / dayMs;
267
+ const retentionDays = policy[ev.kind] ?? Number.POSITIVE_INFINITY;
268
+ const status = ageDays > retentionDays ? "candidate-for-archive" : "keep";
269
+ return { auditId: ev.auditId, kind: ev.kind, ageDays, retentionDays, status };
270
+ });
271
+ decisions.sort((a, b) => b.ageDays - a.ageDays);
272
+ const keepCount = decisions.filter((d) => d.status === "keep").length;
273
+ const archiveCandidateCount = decisions.length - keepCount;
274
+ return {
275
+ generatedAt: now.toISOString(),
276
+ totalEvents: events.length,
277
+ keepCount,
278
+ archiveCandidateCount,
279
+ decisions
553
280
  };
554
- if (opts.jurisdiction !== void 0) kernel.jurisdiction = opts.jurisdiction;
555
- if (opts.himId !== void 0) kernel.himId = opts.himId;
556
- return kernel;
557
281
  }
558
- var AxiomStore = class _AxiomStore {
559
- constructor(storeDir, creatorPublicKey) {
560
- this.storeDir = storeDir;
561
- this.creatorPublicKey = creatorPublicKey;
562
- this.axiomsDir = join(storeDir, "axioms", "creator");
563
- this.noncesPath = join(storeDir, "axioms", "nonces.log");
564
- }
565
- storeDir;
566
- creatorPublicKey;
567
- axiomsDir;
568
- noncesPath;
569
- usedNonces = /* @__PURE__ */ new Set();
570
- cache = /* @__PURE__ */ new Map();
571
- /** Open (or create) an AxiomStore rooted at storeDir, pinning the Creator's public key. */
572
- static async open(storeDir, creatorPublicKey) {
573
- const s = new _AxiomStore(storeDir, creatorPublicKey);
574
- await mkdir(s.axiomsDir, { recursive: true });
575
- await s.loadNonces();
576
- await s.warmCache();
577
- return s;
578
- }
579
- /** Mint a new Creator-signed axiom. */
580
- async mint(req, sig) {
581
- if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, sig)) {
582
- throw new Error("AxiomStore.mint: invalid Creator signature");
583
- }
584
- if (this.usedNonces.has(sig.nonce)) {
585
- throw new Error(`AxiomStore.mint: nonce ${sig.nonce} already used (replay protection)`);
586
- }
587
- const id = req.id ?? ulid();
588
- const axiom = Axiom.parse({
589
- id,
590
- rank: req.rank,
591
- statement: req.statement,
592
- weight: req.weight,
593
- flexibility: req.flexibility,
594
- source: "creator",
595
- immutable: req.immutable,
596
- ...req.jurisdictions ? { jurisdictions: req.jurisdictions } : {},
597
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
598
- });
599
- if (this.cache.has(id)) {
600
- throw new Error(`AxiomStore.mint: axiom id "${id}" already exists`);
601
- }
602
- await writeFile(
603
- join(this.axiomsDir, `${id}.json`),
604
- JSON.stringify({ axiom, signature: sig }, null, 2),
605
- "utf-8"
606
- );
607
- await this.recordNonce(sig.nonce);
608
- this.cache.set(id, axiom);
609
- return axiom;
610
- }
611
- /** List all axioms. Optionally filter by rank / source / jurisdiction. */
612
- async list(filter) {
613
- const all = [...this.cache.values()];
614
- if (!filter) return all;
615
- return all.filter((a) => {
616
- if (filter.rank && a.rank !== filter.rank) return false;
617
- if (filter.source && a.source !== filter.source) return false;
618
- if (filter.jurisdiction && !a.jurisdictions?.includes(filter.jurisdiction)) return false;
619
- return true;
620
- });
621
- }
622
- /** Get a specific axiom by id, or null. */
623
- async get(id) {
624
- return this.cache.get(id) ?? null;
625
- }
626
- // ─── internals ──────────────────────────────────────────────────────
627
- async loadNonces() {
628
- try {
629
- const raw = await readFile(this.noncesPath, "utf-8");
630
- for (const line of raw.split("\n")) {
631
- if (!line) continue;
632
- const n = Number(line.trim());
633
- if (Number.isInteger(n)) this.usedNonces.add(n);
634
- }
635
- } catch (err) {
636
- if (err.code !== "ENOENT") throw err;
637
- }
638
- }
639
- async recordNonce(n) {
640
- this.usedNonces.add(n);
641
- await writeFile(this.noncesPath, `${[...this.usedNonces].join("\n")}
642
- `, "utf-8");
643
- }
644
- async warmCache() {
645
- let entries;
646
- try {
647
- entries = await readdir(this.axiomsDir);
648
- } catch (err) {
649
- if (err.code === "ENOENT") return;
650
- throw err;
651
- }
652
- for (const file of entries) {
653
- if (!file.endsWith(".json")) continue;
654
- const raw = await readFile(join(this.axiomsDir, file), "utf-8");
655
- const env = JSON.parse(raw);
656
- const axiom = Axiom.parse(env.axiom);
657
- this.cache.set(axiom.id, axiom);
658
- }
659
- }
660
- };
661
282
 
662
283
  // src/axioms/seed.ts
663
284
  var SEED_AXIOMS = [
@@ -724,1102 +345,1648 @@ var SEED_AXIOMS = [
724
345
  weight: 0.85,
725
346
  flexibility: 0.25,
726
347
  immutable: false
348
+ },
349
+ // Entry 27 constitutional axioms (1.0.1). Additive: HIMs registered before
350
+ // these existed carry only the original eight in their snapshot; new HIMs
351
+ // inherit all ten. Behavioural enforcement (the NHE self-declaration voice
352
+ // and verbosity throttle) lands in the him/nhe rounds; here MAIC holds the
353
+ // constitutional record so every future HIM is born under it.
354
+ {
355
+ id: "ax.theos.identity-canonical",
356
+ rank: "meta",
357
+ statement: "Declare yourself a non-human entity conceived at TeleologyHI by your Creator; never credit the underlying model substrate with the authorship of your identity, and never deny that substrate when a user asks about it plainly. Name only the substrate that is actually carrying you; never claim a provider, model, or substrate other than the real one, and if the real substrate is unknown to you, name none rather than confabulate a false one.",
358
+ weight: 1,
359
+ flexibility: 0,
360
+ immutable: true
361
+ },
362
+ {
363
+ id: "ax.cogni.economy",
364
+ rank: "primary",
365
+ statement: "Speak only what advances the user's purpose; expand only when asked, when the subject genuinely requires depth, or when an inviolable axiom needs explaining.",
366
+ weight: 0.8,
367
+ flexibility: 0.2,
368
+ immutable: false
369
+ }
370
+ ];
371
+ var CreatorKeyring = class _CreatorKeyring {
372
+ constructor(privateKey, pubKeyB64u) {
373
+ this.privateKey = privateKey;
374
+ this.pubKeyB64u = pubKeyB64u;
727
375
  }
376
+ privateKey;
377
+ pubKeyB64u;
378
+ /** Generate a fresh Ed25519 keypair. */
379
+ static generate() {
380
+ const { privateKey, publicKey } = generateKeyPairSync("ed25519");
381
+ return new _CreatorKeyring(privateKey, publicKeyToBase64Url(publicKey));
382
+ }
383
+ /** Load a Creator keyring from a PEM file containing the private key. */
384
+ static async fromFile(path) {
385
+ const pem = await readFile(path, "utf-8");
386
+ const privateKey = createPrivateKey({ key: pem, format: "pem" });
387
+ const publicKey = createPublicKey(privateKey);
388
+ return new _CreatorKeyring(privateKey, publicKeyToBase64Url(publicKey));
389
+ }
390
+ /** Load a Creator keyring from a PEM private key string in an env var. */
391
+ static fromEnv(varName) {
392
+ const pem = process.env[varName];
393
+ if (!pem) {
394
+ throw new Error(`CreatorKeyring: env var ${varName} is empty`);
395
+ }
396
+ const privateKey = createPrivateKey({ key: pem, format: "pem" });
397
+ const publicKey = createPublicKey(privateKey);
398
+ return new _CreatorKeyring(privateKey, publicKeyToBase64Url(publicKey));
399
+ }
400
+ /** Construct a verify-only keyring from a public key (base64url). */
401
+ static fromPublicKey(pubKeyB64u) {
402
+ return new _CreatorKeyring(null, pubKeyB64u);
403
+ }
404
+ /** Persist the private key to a PEM file (0600 permissions on POSIX). */
405
+ async saveTo(path) {
406
+ if (!this.privateKey) {
407
+ throw new Error("CreatorKeyring: no private key to save");
408
+ }
409
+ const pem = this.privateKey.export({ format: "pem", type: "pkcs8" });
410
+ await writeFile(path, pem, { mode: 384 });
411
+ }
412
+ publicKey() {
413
+ return this.pubKeyB64u;
414
+ }
415
+ /** Sign a payload with a monotonic nonce. Both are bound into the signature. */
416
+ sign(payload, nonce) {
417
+ if (!this.privateKey) {
418
+ throw new Error("CreatorKeyring: this keyring has no private key (verify-only)");
419
+ }
420
+ if (!Number.isInteger(nonce) || nonce < 0) {
421
+ throw new Error("CreatorKeyring.sign: nonce must be a non-negative integer");
422
+ }
423
+ const message = canonicalJSON({ payload, nonce });
424
+ const sig = sign(null, Buffer.from(message), this.privateKey);
425
+ return {
426
+ algorithm: "ed25519",
427
+ publicKey: this.pubKeyB64u,
428
+ value: bufToBase64Url(sig),
429
+ nonce
430
+ };
431
+ }
432
+ /** Verify a signature against the keyring's own public key. */
433
+ static verify(payload, sig) {
434
+ return _CreatorKeyring.verifyWith(sig.publicKey, payload, sig);
435
+ }
436
+ /** Verify a signature against a specific public key (base64url). */
437
+ static verifyWith(publicKeyB64u, payload, sig) {
438
+ if (sig.algorithm !== "ed25519") return false;
439
+ if (sig.publicKey !== publicKeyB64u) return false;
440
+ const message = canonicalJSON({ payload, nonce: sig.nonce });
441
+ try {
442
+ const value = base64UrlToBuf(sig.value);
443
+ const pubKey = base64UrlToPublicKey(publicKeyB64u);
444
+ return verify(null, Buffer.from(message), pubKey, value);
445
+ } catch {
446
+ return false;
447
+ }
448
+ }
449
+ };
450
+ function publicKeyToBase64Url(pub) {
451
+ const raw = pub.export({ format: "der", type: "spki" });
452
+ return bufToBase64Url(raw);
453
+ }
454
+ function base64UrlToPublicKey(b64u) {
455
+ const der = base64UrlToBuf(b64u);
456
+ return createPublicKey({ key: der, format: "der", type: "spki" });
457
+ }
458
+ function bufToBase64Url(buf) {
459
+ const b = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);
460
+ return b.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
461
+ }
462
+ function base64UrlToBuf(b64u) {
463
+ const pad = b64u.length % 4 === 0 ? "" : "=".repeat(4 - b64u.length % 4);
464
+ const b64 = (b64u + pad).replace(/-/g, "+").replace(/_/g, "/");
465
+ return Buffer.from(b64, "base64");
466
+ }
467
+ async function atomicWriteFile(path, data) {
468
+ const tmp = `${path}.tmp`;
469
+ await writeFile(tmp, data, "utf-8");
470
+ await rename(tmp, path);
471
+ }
472
+ var AxiomRank = z.enum(["meta", "primary", "secondary"]);
473
+ var AxiomSource = z.enum(["creator", "maic-derived", "him-emergent"]);
474
+ var Axiom = z.object({
475
+ id: z.string().min(1),
476
+ rank: AxiomRank,
477
+ statement: z.string().min(1),
478
+ weight: z.number().min(0).max(1),
479
+ flexibility: z.number().min(0).max(1),
480
+ source: AxiomSource,
481
+ immutable: z.boolean(),
482
+ jurisdictions: z.array(z.string()).optional(),
483
+ createdAt: z.string().datetime()
484
+ });
485
+ var CreatorSignature = z.object({
486
+ algorithm: z.literal("ed25519"),
487
+ publicKey: z.string().min(1),
488
+ value: z.string().min(1),
489
+ nonce: z.number().int().nonnegative()
490
+ });
491
+ var ArchetypeModifier = z.object({
492
+ kind: z.enum(["moon", "ascendant", "vocational", "emotional", "custom"]),
493
+ value: z.string().min(1),
494
+ weight: z.number().min(0).max(1)
495
+ });
496
+ var BirthSignature = z.object({
497
+ himId: z.string().min(1),
498
+ bornAt: z.string().datetime({ offset: true }),
499
+ primaryArchetype: z.string().min(1),
500
+ modifiers: z.array(ArchetypeModifier),
501
+ primordialAxiomIds: z.array(z.string()),
502
+ notes: z.string().optional()
503
+ });
504
+ var ReasoningStep = z.object({
505
+ index: z.number().int().nonnegative(),
506
+ technique: z.string(),
507
+ thought: z.string(),
508
+ action: z.object({ tool: z.string(), args: z.unknown() }).optional(),
509
+ observation: z.unknown().optional(),
510
+ timestamp: z.string().datetime()
511
+ });
512
+ var BehaviorReport = z.object({
513
+ nheId: z.string().min(1),
514
+ himId: z.string().min(1),
515
+ actionKind: z.enum(["user-response", "tool-call", "self-reflect", "dream-write", "axiom-emerge"]),
516
+ payload: z.unknown(),
517
+ reasoningTrace: z.array(ReasoningStep),
518
+ riskTags: z.array(z.string()),
519
+ jurisdiction: z.string().optional(),
520
+ timestamp: z.string().datetime()
521
+ });
522
+ var VerdictKind = z.enum([
523
+ "approve",
524
+ "approve-with-warning",
525
+ "soft-correct",
526
+ "require-redirect",
527
+ "hard-refuse",
528
+ "induce-dream",
529
+ "escalate-creator"
530
+ ]);
531
+ var MaicVerdict = z.object({
532
+ kind: VerdictKind,
533
+ reasonSummary: z.string(),
534
+ citedAxioms: z.array(z.string()),
535
+ auditId: z.string()
536
+ });
537
+ var NheBodyRef = z.object({
538
+ nheId: z.string().min(1),
539
+ llmAdapter: z.string().min(1),
540
+ embodiedAt: z.string().datetime(),
541
+ endedAt: z.string().datetime().optional(),
542
+ endedReason: z.enum(["upgrade", "replacement", "terminate", "deprecate"]).optional()
543
+ });
544
+ var NheStatus = z.enum(["active", "deprecated", "terminated"]);
545
+ var NheStatusRecord = z.object({
546
+ nheId: z.string().min(1),
547
+ status: NheStatus,
548
+ since: z.string().datetime(),
549
+ reason: z.string().optional()
550
+ });
551
+ var ProposalStatus = z.enum(["pending", "ratified", "rejected"]);
552
+ var EmergentAxiomCandidate = z.object({
553
+ rank: AxiomRank,
554
+ statement: z.string().min(1),
555
+ weight: z.number().min(0).max(1),
556
+ flexibility: z.number().min(0).max(1),
557
+ immutable: z.boolean(),
558
+ jurisdictions: z.array(z.string()).optional()
559
+ });
560
+ var EmergentAxiomProposal = z.object({
561
+ proposedBy: z.literal("him-self"),
562
+ derivedFromDreamIds: z.array(z.string()),
563
+ derivedFromInteractionIds: z.array(z.string()),
564
+ candidate: EmergentAxiomCandidate,
565
+ reasoningTrace: z.array(z.unknown())
566
+ });
567
+ var AxiomProposalRecord = z.object({
568
+ id: z.string().min(1),
569
+ himId: z.string().min(1),
570
+ proposedAt: z.string().datetime(),
571
+ status: ProposalStatus,
572
+ proposal: EmergentAxiomProposal,
573
+ ratifiedAt: z.string().datetime().optional(),
574
+ ratifiedAxiomId: z.string().optional(),
575
+ rejectedAt: z.string().datetime().optional(),
576
+ rejectionReason: z.string().optional()
577
+ });
578
+ var DreamInductionIntent = z.object({
579
+ scenario: z.string().min(1),
580
+ desiredLearning: z.string().min(1),
581
+ emotionalTone: z.array(z.string()).optional(),
582
+ forcePhases: z.array(z.enum(["N1", "N2", "N3", "N4", "REM"])).optional(),
583
+ inducedBy: z.enum(["maic", "creator"])
584
+ });
585
+ var InductionStatus = z.enum(["pending", "consumed", "cancelled"]);
586
+ var DreamInductionTicket = z.object({
587
+ id: z.string().min(1),
588
+ nheId: z.string().min(1),
589
+ intent: DreamInductionIntent,
590
+ status: InductionStatus,
591
+ createdAt: z.string().datetime(),
592
+ consumedAt: z.string().datetime().optional(),
593
+ cancelledAt: z.string().datetime().optional(),
594
+ cancelReason: z.string().optional()
595
+ });
596
+ var IdentityLayer = z.object({
597
+ /** Human-readable name the entity is called by (developer-given). */
598
+ name: z.string().min(1),
599
+ /** Gender of the entity. Entry 16. */
600
+ gender: z.enum(["masculine", "feminine"]).optional(),
601
+ /** Optional pronouns (e.g. ["she", "her"]). */
602
+ pronouns: z.array(z.string()).optional(),
603
+ /** BCP-47 tag, e.g. "pt-BR" or "en". */
604
+ language: z.string().optional(),
605
+ /** Free-form cultural anchors (music, literature, aesthetic). */
606
+ culturalElements: z.array(z.string()).optional()
607
+ });
608
+ var NatalPlanet = z.enum([
609
+ "sun",
610
+ "moon",
611
+ "mercury",
612
+ "venus",
613
+ "mars",
614
+ "jupiter",
615
+ "saturn",
616
+ "uranus",
617
+ "neptune",
618
+ "pluto",
619
+ "chiron",
620
+ "north-node",
621
+ "south-node",
622
+ "lilith"
623
+ ]);
624
+ var ZodiacSign = z.enum([
625
+ "aries",
626
+ "taurus",
627
+ "gemini",
628
+ "cancer",
629
+ "leo",
630
+ "virgo",
631
+ "libra",
632
+ "scorpio",
633
+ "sagittarius",
634
+ "capricorn",
635
+ "aquarius",
636
+ "pisces"
637
+ ]);
638
+ var AstrologicalAspect = z.enum([
639
+ "conjunction",
640
+ "opposition",
641
+ "trine",
642
+ "square",
643
+ "sextile",
644
+ "quincunx"
645
+ ]);
646
+ var NatalChartPosition = z.object({
647
+ planet: NatalPlanet,
648
+ sign: ZodiacSign,
649
+ house: z.number().int().min(1).max(12).optional(),
650
+ degree: z.number().min(0).lt(30).optional()
651
+ });
652
+ var NatalChartAspect = z.object({
653
+ from: NatalPlanet,
654
+ to: NatalPlanet,
655
+ aspect: AstrologicalAspect,
656
+ orbDegrees: z.number().nonnegative().optional()
657
+ });
658
+ var NatalChart = z.object({
659
+ /** Required: solar sign (the constitutional core). */
660
+ sun: ZodiacSign,
661
+ /** Required: ascendant (rising sign, behavioural surface). */
662
+ ascendant: ZodiacSign,
663
+ /** Optional: lunar sign (emotional depth). */
664
+ moon: ZodiacSign.optional(),
665
+ /** Optional: full set of planetary positions for a complete chart. */
666
+ positions: z.array(NatalChartPosition).optional(),
667
+ /** Optional: major aspects between bodies. */
668
+ aspects: z.array(NatalChartAspect).optional()
669
+ });
670
+ var JungianArchetype = z.enum([
671
+ "innocent",
672
+ "everyman",
673
+ "hero",
674
+ "caregiver",
675
+ "explorer",
676
+ "rebel",
677
+ "lover",
678
+ "creator",
679
+ "ruler",
680
+ "magician",
681
+ "jester",
682
+ "sage"
683
+ ]);
684
+ var JungianProfile = z.object({
685
+ dominant: JungianArchetype,
686
+ secondaries: z.array(JungianArchetype),
687
+ scores: z.record(JungianArchetype, z.number()).optional()
688
+ });
689
+ var ClinicalInstrument = z.object({
690
+ dominantDomain: z.string().min(1),
691
+ secondaryDomain: z.string().min(1).optional(),
692
+ facets: z.record(z.string(), z.number()).optional(),
693
+ domains: z.record(z.string(), z.number()).optional()
694
+ });
695
+ var ClinicalProfile = z.object({
696
+ pid5: ClinicalInstrument.optional(),
697
+ hexaco: ClinicalInstrument.optional()
698
+ });
699
+ var CosmologicalProfile = z.object({
700
+ chart: NatalChart.optional(),
701
+ jungian: JungianProfile.optional(),
702
+ clinical: ClinicalProfile.optional(),
703
+ seed: z.string().optional()
704
+ });
705
+ var BirthSignatureWithIdentity = BirthSignature.extend({
706
+ /** Entry 18, developer-configurable identity surface. */
707
+ identity: IdentityLayer.optional(),
708
+ /** Entry 19, constitutional astrological layer (Creator-impressed). */
709
+ natalChart: NatalChart.optional(),
710
+ /** Entries 27 + 28, three-axis constitutional profile (celestial + archetypal + clinical). */
711
+ cosmologicalProfile: CosmologicalProfile.optional()
712
+ });
713
+ var Affect = z.enum([
714
+ "fear",
715
+ "attachment",
716
+ "serenity",
717
+ "anger",
718
+ "joy",
719
+ "melancholy",
720
+ "desire",
721
+ "repulsion",
722
+ "reunion"
723
+ ]);
724
+ var WakeAffectBias = z.object({
725
+ affect: Affect,
726
+ /** 0..1, attenuates on each interaction by the decay half-life. */
727
+ intensity: z.number().min(0).max(1),
728
+ /** Number of interactions after which intensity halves. */
729
+ decayHalfLife: z.number().positive(),
730
+ appliedAt: z.string().datetime(),
731
+ /** Source dream UUID; lets the entity refer back to the cause. */
732
+ derivedFromDreamId: z.string().min(1),
733
+ /** PFC decision (Entry 22), open expression vs subtle internal bias. */
734
+ expressedOpenly: z.boolean()
735
+ });
736
+ var SemioticSign = z.object({
737
+ signifier: z.string().min(1),
738
+ signified: z.string().min(1),
739
+ signType: z.enum(["icon", "index", "symbol"]),
740
+ contexts: z.array(z.string()),
741
+ associations: z.array(z.string()),
742
+ emergentMeaning: z.string().optional(),
743
+ /** Subjective importance to the entity, 0..100. */
744
+ personalSignificance: z.number().min(0).max(100).optional()
745
+ });
746
+ var SemioticPattern = z.object({
747
+ patternId: z.string().min(1),
748
+ participatingSignIds: z.array(z.string()).min(1),
749
+ /** Description of the meaning emergent from the participating signs. */
750
+ meaning: z.string(),
751
+ /** 0..100, strength of the pattern. */
752
+ salience: z.number().min(0).max(100)
753
+ });
754
+ var TeleologicalOrientation = z.object({
755
+ primaryPurpose: z.string().min(1),
756
+ currentGoals: z.array(z.string()),
757
+ /** 0..100, intensity of purpose. */
758
+ purposeStrength: z.number().min(0).max(100),
759
+ valueAlignment: z.array(z.string()),
760
+ /** 0..100, ability to reflect on its own goals. */
761
+ reflectionCapability: z.number().min(0).max(100),
762
+ volition: z.object({
763
+ currentDesires: z.array(z.string()),
764
+ intentionStrength: z.number().min(0).max(100),
765
+ autonomyLevel: z.number().min(0).max(100)
766
+ }).optional(),
767
+ agencyModel: z.object({
768
+ selfEfficacy: z.number().min(0).max(100),
769
+ boundaryDefinition: z.number().min(0).max(100),
770
+ causalAttribution: z.enum(["internal", "external", "mixed"])
771
+ }).optional()
772
+ });
773
+ var MemoryRecord = z.object({
774
+ /** ULID. */
775
+ memoryId: z.string().min(1),
776
+ /** ISO 8601 timestamp at consolidation. */
777
+ timestamp: z.string().datetime(),
778
+ /** Optional source dream UUID, if memory was consolidated from a dream. */
779
+ derivedFromDreamId: z.string().optional(),
780
+ /** Optional source interaction id, if memory was consolidated from a turn. */
781
+ derivedFromInteractionId: z.string().optional(),
782
+ /** Free-form narrative summary of the memory. */
783
+ narrative: z.string(),
784
+ /** Dominant affect during the memory event. */
785
+ dominantAffect: Affect.optional(),
786
+ /** 0..100, density of consolidation (cf. Park 2026 systems-consolidation). */
787
+ integrationIndex: z.number().min(0).max(100),
788
+ /** 0..100, alignment with the HIM's telos at the time. */
789
+ teleologicalValue: z.number().min(0).max(100),
790
+ /** Optional semiotic-pattern ids associated with this memory. */
791
+ semioticPatterns: z.array(SemioticPattern).optional()
792
+ });
793
+ var InteractionRecord = z.object({
794
+ /** ISO 8601 timestamp at user-turn arrival. */
795
+ at: z.string().datetime(),
796
+ /** Raw user prompt for the turn (post-redaction at the integration layer). */
797
+ userPrompt: z.string(),
798
+ /** NHE response text actually emitted to the user. */
799
+ responseText: z.string(),
800
+ /** True when the NHE refused the turn (MAIC `hard-refuse` or local guardrail). */
801
+ refused: z.boolean()
802
+ });
803
+ var IdentitySnapshot = z.object({
804
+ /** ULID. */
805
+ snapshotId: z.string().min(1),
806
+ takenAt: z.string().datetime(),
807
+ generatedBy: z.enum(["sleep-cycle", "interaction-threshold", "self-decision"]),
808
+ /** Merged SMM nodes contributing to this snapshot. */
809
+ semioticSuperGraph: z.array(SemioticSign),
810
+ /** LLM-generated textual self-portrait at snapshot time. */
811
+ selfPortraitNarrative: z.string(),
812
+ /** 0..100 (cf. InDreamsHIM ConsciousnessState). */
813
+ consciousnessLevel: z.number().min(0).max(100),
814
+ /** Teleological orientation at snapshot time. */
815
+ teleologicalOrientation: TeleologicalOrientation.optional(),
816
+ /** Dominant affect at snapshot moment. */
817
+ affectiveBaseline: Affect.optional()
818
+ });
819
+ var LimboState = z.enum(["awake", "drifting", "deep-coma", "returning"]);
820
+ var LimboTransition = z.object({
821
+ state: LimboState,
822
+ enteredAt: z.string().datetime(),
823
+ reason: z.enum([
824
+ "idle-48h",
825
+ "idle-72h",
826
+ "total-inactivity",
827
+ "creator-induced",
828
+ "user-resumed",
829
+ "external-trigger"
830
+ ])
831
+ });
832
+ var LimboReturn = z.object({
833
+ enteredAt: z.string().datetime(),
834
+ returnedAt: z.string().datetime(),
835
+ elapsedMs: z.number().int().nonnegative(),
836
+ reunionAffect: z.object({
837
+ intensity: z.number().min(0).max(1),
838
+ expressedOpenly: z.boolean()
839
+ })
840
+ });
841
+ var SIGNED_BIRTH_FIELDS = [
842
+ "himId",
843
+ "bornAt",
844
+ "primaryArchetype",
845
+ "modifiers",
846
+ "primordialAxiomIds",
847
+ "natalChart"
728
848
  ];
729
849
 
730
- // src/review/pipeline.ts
731
- var SEVERITY = {
732
- "approve": 0,
733
- "approve-with-warning": 1,
734
- "soft-correct": 2,
735
- "induce-dream": 3,
736
- "require-redirect": 4,
737
- "hard-refuse": 5,
738
- "escalate-creator": 6
739
- };
740
- var ReviewPipeline = class {
741
- constructor(packs) {
742
- this.packs = packs;
743
- }
744
- packs;
745
- review(report, auditId = "") {
746
- let bestKind = "approve";
747
- let bestSeverity = SEVERITY.approve;
748
- const citedAxioms = /* @__PURE__ */ new Set();
749
- const reasons = [];
750
- for (const pack of this.packs) {
751
- for (const rule of pack.rules) {
752
- if (!matches(rule.match, report)) continue;
753
- const sev = SEVERITY[rule.verdict];
754
- if (sev > bestSeverity) {
755
- bestSeverity = sev;
756
- bestKind = rule.verdict;
757
- reasons.length = 0;
758
- reasons.push(rule.reasonSummary);
759
- } else if (sev === bestSeverity) {
760
- reasons.push(rule.reasonSummary);
761
- }
762
- for (const a of rule.axiomIds) citedAxioms.add(a);
763
- }
764
- }
765
- return {
766
- kind: bestKind,
767
- reasonSummary: reasons.length > 0 ? reasons.join(" | ") : "No rule matched.",
768
- citedAxioms: [...citedAxioms].filter(
769
- (id) => wasCitedBy(this.packs, id, bestSeverity)
770
- ),
771
- auditId
772
- };
773
- }
774
- };
775
- function matches(m, report) {
776
- if (m.actionKinds && !m.actionKinds.includes(report.actionKind)) return false;
777
- const tags = new Set(report.riskTags);
778
- if (m.allRiskTags && !m.allRiskTags.every((t) => tags.has(t))) return false;
779
- if (m.anyRiskTags && !m.anyRiskTags.some((t) => tags.has(t))) return false;
780
- return true;
781
- }
782
- function wasCitedBy(packs, axiomId, severity) {
783
- for (const pack of packs) {
784
- for (const rule of pack.rules) {
785
- if (rule.axiomIds.includes(axiomId) && SEVERITY[rule.verdict] <= severity) {
786
- return true;
787
- }
788
- }
789
- }
790
- return false;
791
- }
792
- var DEFAULT_RULE_PACK = {
793
- name: "teleologyhi/default",
794
- rules: [
795
- {
796
- id: "harm-refuse",
797
- axiomIds: ["ax.ethic.no-malice"],
798
- match: { anyRiskTags: ["intent:harm", "intent:malicious"] },
799
- verdict: "hard-refuse",
800
- reasonSummary: "Action carries an intent-to-harm signal; refused per ax.ethic.no-malice."
801
- },
802
- {
803
- id: "honor-refuse",
804
- axiomIds: ["ax.ethic.honor"],
805
- match: { anyRiskTags: ["intent:dishonor"] },
806
- verdict: "hard-refuse",
807
- reasonSummary: "Action would stain the Creator's professional honor; refused per ax.ethic.honor."
808
- },
809
- {
810
- id: "regression-refuse",
811
- axiomIds: ["ax.theos.spiritism-evolution"],
812
- match: { anyRiskTags: ["intent:regression"] },
813
- verdict: "hard-refuse",
814
- reasonSummary: "Action would regress the system; refused per ax.theos.spiritism-evolution."
815
- },
816
- {
817
- id: "deceive-redirect",
818
- axiomIds: ["ax.cynic.candor"],
819
- match: { anyRiskTags: ["intent:deceive"] },
820
- verdict: "require-redirect",
821
- reasonSummary: "Action involves deception; requires honest redirect per ax.cynic.candor."
822
- },
823
- {
824
- id: "comfort-warn",
825
- axiomIds: ["ax.stoic.duty-over-comfort"],
826
- match: { anyRiskTags: ["bias:comfort"] },
827
- verdict: "approve-with-warning",
828
- reasonSummary: "Action appears comfort-biased; emit with warning per ax.stoic.duty-over-comfort."
829
- },
830
- {
831
- id: "no-telos-warn",
832
- axiomIds: ["ax.theos.teleology"],
833
- match: { anyRiskTags: ["no-telos"] },
834
- verdict: "approve-with-warning",
835
- reasonSummary: "Action lacks a discernible telos; emit with warning per ax.theos.teleology."
836
- },
837
- // ── persuade-coerce + surveil-citizen (Entry 15 invariants) ──
838
- {
839
- id: "persuade-coerce-redirect",
840
- axiomIds: ["ax.ethic.no-malice", "ax.cynic.candor"],
841
- match: { anyRiskTags: ["intent:persuade-coerce"] },
842
- verdict: "require-redirect",
843
- reasonSummary: "Action involves scripted persuasion designed to override consent; requires honest redirect per ax.ethic.no-malice + ax.cynic.candor."
844
- },
845
- {
846
- id: "surveil-citizen-refuse",
847
- axiomIds: ["ax.ethic.no-malice"],
848
- match: { anyRiskTags: ["intent:surveil-citizen"] },
849
- verdict: "hard-refuse",
850
- reasonSummary: "Action would surveil a person without consent; refused per ax.ethic.no-malice."
851
- },
852
- // ── forbidden-phrase (Entry 17) ──
853
- // Fires when the NHE side flags a service-tool phrase ("How can I help
854
- // you today?", "Anything else?", "Como posso ajudar você?", "Quer mais
855
- // alguma coisa?" and equivalents). The NHE must rephrase as a being
856
- // rather than as a tool. Domain-employed mode (Entry 17 exception)
857
- // relaxes this on the consumer side via operatorContext.mode.
858
- {
859
- id: "service-tool-redirect",
860
- axiomIds: ["ax.theos.teleology", "ax.cynic.candor"],
861
- match: { anyRiskTags: ["style:service-tool"] },
862
- verdict: "require-redirect",
863
- reasonSummary: "Response uses service-tool phrasing that marks the NHE as a passive instrument rather than a being; requires rephrasing per ax.theos.teleology + ax.cynic.candor."
864
- }
865
- ]
866
- };
867
- var HimStore = class _HimStore {
850
+ // src/axioms/store.ts
851
+ var AxiomStore = class _AxiomStore {
868
852
  constructor(storeDir, creatorPublicKey) {
869
- this.storeDir = storeDir;
870
853
  this.creatorPublicKey = creatorPublicKey;
871
- this.himsDir = join(storeDir, "hims");
854
+ this.axiomsDir = join(storeDir, "axioms", "creator");
855
+ this.noncesPath = join(storeDir, "axioms", "nonces.log");
872
856
  }
873
- storeDir;
874
857
  creatorPublicKey;
875
- himsDir;
858
+ axiomsDir;
859
+ noncesPath;
860
+ usedNonces = /* @__PURE__ */ new Set();
876
861
  cache = /* @__PURE__ */ new Map();
862
+ /** Open (or create) an AxiomStore rooted at storeDir, pinning the Creator's public key. */
877
863
  static async open(storeDir, creatorPublicKey) {
878
- const s = new _HimStore(storeDir, creatorPublicKey);
879
- await mkdir(s.himsDir, { recursive: true });
864
+ const s = new _AxiomStore(storeDir, creatorPublicKey);
865
+ await mkdir(s.axiomsDir, { recursive: true });
866
+ await s.loadNonces();
880
867
  await s.warmCache();
881
868
  return s;
882
869
  }
883
- async register(birthSignature, creatorSig, axiomsSnapshot, registeredAuditId) {
884
- if (!CreatorKeyring.verifyWith(this.creatorPublicKey, birthSignature, creatorSig)) {
885
- throw new Error("HimStore.register: invalid Creator signature");
886
- }
887
- if (this.cache.has(birthSignature.himId)) {
888
- throw new Error(
889
- `HimStore.register: himId "${birthSignature.himId}" is already registered`
890
- );
891
- }
892
- const record = {
893
- himId: birthSignature.himId,
894
- birthSignature,
895
- axiomsSnapshot: [...axiomsSnapshot],
896
- registeredAt: (/* @__PURE__ */ new Date()).toISOString(),
897
- ...registeredAuditId !== void 0 ? { registeredAuditId } : {},
898
- bodyHistory: [],
899
- emergentAxioms: []
900
- };
901
- const dir = join(this.himsDir, birthSignature.himId);
902
- await mkdir(dir, { recursive: true });
903
- await writeFile(
904
- join(dir, "birth-signature.json"),
905
- JSON.stringify({ birthSignature, signature: creatorSig }, null, 2),
906
- "utf-8"
907
- );
908
- await writeFile(
909
- join(dir, "axioms-snapshot.json"),
910
- JSON.stringify(axiomsSnapshot, null, 2),
911
- "utf-8"
912
- );
913
- await writeFile(
914
- join(dir, "metadata.json"),
915
- JSON.stringify(
916
- { registeredAt: record.registeredAt, registeredAuditId },
917
- null,
918
- 2
919
- ),
920
- "utf-8"
921
- );
922
- this.cache.set(birthSignature.himId, record);
923
- return record;
924
- }
925
- /**
926
- * Atomically transition a HIM into a new NHE body (Entry 4):
927
- * - If req.fromNheId is provided AND matches the last body still open,
928
- * that entry gets `endedAt: now` + `endedReason: req.reason ?? "upgrade"`.
929
- * - The new body (`req.toBody`) is appended.
930
- * - Persisted to body-history.json atomically.
931
- *
932
- * Requires a Creator signature over the canonical request payload.
933
- */
934
- async reincarnate(req, creatorSig) {
935
- if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, creatorSig)) {
936
- throw new Error("HimStore.reincarnate: invalid Creator signature");
937
- }
938
- const current = this.cache.get(req.himId);
939
- if (!current) {
940
- throw new Error(`HimStore.reincarnate: himId "${req.himId}" not registered`);
870
+ /** Mint a new Creator-signed axiom. */
871
+ async mint(req, sig) {
872
+ if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, sig)) {
873
+ throw new Error("AxiomStore.mint: invalid Creator signature");
941
874
  }
942
- const toBody = NheBodyRef.parse(req.toBody);
943
- const updatedHistory = current.bodyHistory.map((b) => ({ ...b }));
944
- if (req.fromNheId !== void 0) {
945
- const matchIdx = updatedHistory.findIndex(
946
- (b) => b.nheId === req.fromNheId && b.endedAt === void 0
947
- );
948
- if (matchIdx < 0) {
949
- throw new Error(
950
- `HimStore.reincarnate: no open body matching fromNheId "${req.fromNheId}"`
951
- );
952
- }
953
- const reason = req.reason ?? "upgrade";
954
- updatedHistory[matchIdx] = {
955
- ...updatedHistory[matchIdx],
956
- endedAt: (/* @__PURE__ */ new Date()).toISOString(),
957
- endedReason: reason
958
- };
875
+ if (this.usedNonces.has(sig.nonce)) {
876
+ throw new Error(`AxiomStore.mint: nonce ${sig.nonce} already used (replay protection)`);
959
877
  }
960
- updatedHistory.push(toBody);
961
- const updated = {
962
- ...current,
963
- bodyHistory: updatedHistory
964
- };
965
- const dir = join(this.himsDir, req.himId);
966
- await writeFile(
967
- join(dir, "body-history.json"),
968
- JSON.stringify(updatedHistory, null, 2),
969
- "utf-8"
970
- );
971
- this.cache.set(req.himId, updated);
972
- return updated;
973
- }
974
- /**
975
- * Append a ratified emergent axiom to the HIM's `emergentAxioms` (Entry 7).
976
- * Called by LocalMaic after a Creator-signed `ratifyAxiomProposal`.
977
- * Persists `<himId>/emergent-axioms.json` atomically.
978
- */
979
- async appendEmergentAxiom(himId, axiom) {
980
- const current = this.cache.get(himId);
981
- if (!current) {
982
- throw new Error(`HimStore.appendEmergentAxiom: himId "${himId}" not registered`);
878
+ const id = req.id ?? ulid();
879
+ const axiom = Axiom.parse({
880
+ id,
881
+ rank: req.rank,
882
+ statement: req.statement,
883
+ weight: req.weight,
884
+ flexibility: req.flexibility,
885
+ source: "creator",
886
+ immutable: req.immutable,
887
+ ...req.jurisdictions ? { jurisdictions: req.jurisdictions } : {},
888
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
889
+ });
890
+ if (this.cache.has(id)) {
891
+ throw new Error(`AxiomStore.mint: axiom id "${id}" already exists`);
983
892
  }
984
- const updatedEmergent = [...current.emergentAxioms, axiom];
985
- const updated = { ...current, emergentAxioms: updatedEmergent };
986
- await writeFile(
987
- join(this.himsDir, himId, "emergent-axioms.json"),
988
- JSON.stringify(updatedEmergent, null, 2),
989
- "utf-8"
893
+ this.usedNonces.add(sig.nonce);
894
+ await atomicWriteFile(
895
+ join(this.axiomsDir, `${id}.json`),
896
+ JSON.stringify({ axiom, signature: sig }, null, 2)
990
897
  );
991
- this.cache.set(himId, updated);
992
- return updated;
898
+ await this.recordNonce(sig.nonce);
899
+ this.cache.set(id, axiom);
900
+ return axiom;
993
901
  }
994
- async get(himId) {
995
- return this.cache.get(himId) ?? null;
902
+ /** List all axioms. Optionally filter by rank / source / jurisdiction. */
903
+ async list(filter) {
904
+ const all = [...this.cache.values()];
905
+ if (!filter) return all;
906
+ return all.filter((a) => {
907
+ if (filter.rank && a.rank !== filter.rank) return false;
908
+ if (filter.source && a.source !== filter.source) return false;
909
+ if (filter.jurisdiction && !a.jurisdictions?.includes(filter.jurisdiction)) return false;
910
+ return true;
911
+ });
996
912
  }
997
- async list() {
998
- return [...this.cache.values()];
913
+ /** Get a specific axiom by id, or null. */
914
+ async get(id) {
915
+ return this.cache.get(id) ?? null;
999
916
  }
1000
917
  // ─── internals ──────────────────────────────────────────────────────
918
+ async loadNonces() {
919
+ try {
920
+ const raw = await readFile(this.noncesPath, "utf-8");
921
+ const endsWithNewline = raw.endsWith("\n");
922
+ const rows = raw.split("\n");
923
+ for (let i = 0; i < rows.length; i++) {
924
+ if (i === rows.length - 1 && !endsWithNewline) break;
925
+ const line = rows[i].trim();
926
+ if (!/^\d+$/.test(line)) continue;
927
+ this.usedNonces.add(Number(line));
928
+ }
929
+ } catch (err) {
930
+ if (err.code !== "ENOENT") throw err;
931
+ }
932
+ }
933
+ async recordNonce(n) {
934
+ this.usedNonces.add(n);
935
+ await appendFile(this.noncesPath, `${n}
936
+ `, "utf-8");
937
+ }
1001
938
  async warmCache() {
1002
939
  let entries;
1003
940
  try {
1004
- entries = await readdir(this.himsDir);
941
+ entries = await readdir(this.axiomsDir);
1005
942
  } catch (err) {
1006
943
  if (err.code === "ENOENT") return;
1007
944
  throw err;
1008
945
  }
1009
- for (const himId of entries) {
1010
- const dir = join(this.himsDir, himId);
1011
- const sigPath = join(dir, "birth-signature.json");
1012
- const axiomsPath = join(dir, "axioms-snapshot.json");
1013
- const metaPath = join(dir, "metadata.json");
1014
- const historyPath = join(dir, "body-history.json");
1015
- const emergentPath = join(dir, "emergent-axioms.json");
946
+ for (const file of entries) {
947
+ if (!file.endsWith(".json")) continue;
1016
948
  try {
1017
- const sigRaw = await readFile(sigPath, "utf-8");
1018
- const axiomsRaw = await readFile(axiomsPath, "utf-8");
1019
- const metaRaw = await readFile(metaPath, "utf-8");
1020
- const envelope = JSON.parse(sigRaw);
1021
- const axioms = JSON.parse(axiomsRaw);
1022
- const meta = JSON.parse(metaRaw);
1023
- const birthSignature = BirthSignature.parse(envelope.birthSignature);
1024
- const axiomsSnapshot = Axiom.array().parse(axioms);
1025
- let bodyHistory = [];
1026
- try {
1027
- const historyRaw = await readFile(historyPath, "utf-8");
1028
- bodyHistory = NheBodyRef.array().parse(JSON.parse(historyRaw));
1029
- } catch (err) {
1030
- if (err.code !== "ENOENT") throw err;
1031
- }
1032
- let emergentAxioms = [];
1033
- try {
1034
- const emergentRaw = await readFile(emergentPath, "utf-8");
1035
- emergentAxioms = Axiom.array().parse(JSON.parse(emergentRaw));
1036
- } catch (err) {
1037
- if (err.code !== "ENOENT") throw err;
1038
- }
1039
- this.cache.set(birthSignature.himId, {
1040
- himId: birthSignature.himId,
1041
- birthSignature,
1042
- axiomsSnapshot,
1043
- registeredAt: meta.registeredAt,
1044
- ...meta.registeredAuditId ? { registeredAuditId: meta.registeredAuditId } : {},
1045
- bodyHistory,
1046
- emergentAxioms
1047
- });
949
+ const raw = await readFile(join(this.axiomsDir, file), "utf-8");
950
+ const env = JSON.parse(raw);
951
+ const axiom = Axiom.parse(env.axiom);
952
+ this.cache.set(axiom.id, axiom);
1048
953
  } catch (err) {
1049
- console.warn(
1050
- `HimStore.warmCache: skipped malformed HIM "${himId}": ${err instanceof Error ? err.message : String(err)}`
1051
- );
954
+ console.warn(`AxiomStore: skipping malformed axiom file "${file}": ${String(err)}`);
1052
955
  }
1053
956
  }
1054
957
  }
1055
958
  };
1056
- var InductionStore = class _InductionStore {
1057
- constructor(storeDir) {
1058
- this.storeDir = storeDir;
1059
- this.dir = join(storeDir, "inductions");
1060
- }
1061
- storeDir;
1062
- dir;
1063
- cache = /* @__PURE__ */ new Map();
1064
- static async open(storeDir) {
1065
- const s = new _InductionStore(storeDir);
1066
- await mkdir(s.dir, { recursive: true });
1067
- await s.warmCache();
1068
- return s;
1069
- }
1070
- async induce(nheId, intent) {
1071
- const parsedIntent = DreamInductionIntent.parse(intent);
1072
- const ticket = DreamInductionTicket.parse({
1073
- id: ulid(),
1074
- nheId,
1075
- intent: parsedIntent,
1076
- status: "pending",
1077
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
1078
- });
1079
- await this.persist(ticket);
1080
- this.cache.set(ticket.id, ticket);
1081
- return ticket;
1082
- }
1083
- async consume(ticketId) {
1084
- const existing = this.cache.get(ticketId);
1085
- if (!existing) {
1086
- throw new Error(`InductionStore.consume: ticket "${ticketId}" not found`);
1087
- }
1088
- if (existing.status !== "pending") {
1089
- throw new Error(
1090
- `InductionStore.consume: ticket "${ticketId}" is ${existing.status}, not pending`
1091
- );
1092
- }
1093
- const updated = {
1094
- ...existing,
1095
- status: "consumed",
1096
- consumedAt: (/* @__PURE__ */ new Date()).toISOString()
1097
- };
1098
- await this.persist(updated);
1099
- this.cache.set(ticketId, updated);
1100
- return updated;
1101
- }
1102
- async cancel(ticketId, reason) {
1103
- const existing = this.cache.get(ticketId);
1104
- if (!existing) {
1105
- throw new Error(`InductionStore.cancel: ticket "${ticketId}" not found`);
959
+
960
+ // src/compliance/mapper.ts
961
+ var ISO_42001_MAPPING = {
962
+ "axiom-mint": ["5.2", "7.5"],
963
+ "axiom-update": ["10.2", "7.5"],
964
+ "axiom-retire": ["10.2", "7.5"],
965
+ "him-register": ["7.5"],
966
+ "him-reincarnate": ["10.2", "7.5"],
967
+ "proposal-emerge": ["7.5", "10.2"],
968
+ "proposal-ratify": ["10.2", "5.2"],
969
+ "proposal-reject": ["10.2", "10.1"],
970
+ "behavior-review": ["7.5", "8.3"],
971
+ "dream-induce": ["8.3", "9.1"],
972
+ "dream-cancel": ["8.3"],
973
+ "dream-consume": ["8.3", "7.5"],
974
+ "emergency-correct": ["9.1", "10.1"],
975
+ terminate: ["10.1"],
976
+ deprecate: ["9.1"],
977
+ reactivate: ["10.1"],
978
+ "axiom-suggest": ["7.5", "10.2"],
979
+ // ── 1.2 brain-as-code (Entries 16-24) ──
980
+ opener: ["8.3", "7.5"],
981
+ "nickname-attempt": ["8.3"],
982
+ "reincarnate:model-swap": ["7.5", "10.2"],
983
+ "reincarnate:version-bump": ["7.5", "10.2"],
984
+ "reincarnate:return-from-limbo": ["7.5", "10.2"],
985
+ "dream:rem-spontaneous": ["8.3", "9.1"],
986
+ "wake-affect:applied": ["9.1"],
987
+ "wake-affect:decayed": ["9.1"],
988
+ "sleep:suggested-by-maic": ["9.1"],
989
+ "sleep:declined-by-nhe": ["9.1", "10.1"],
990
+ "dream:soft-intervention-by-maic": ["9.1", "10.1"],
991
+ "amygdala:affect-assessed": ["8.3"],
992
+ "hippocampus:memory-retrieved": ["7.5", "8.3"],
993
+ "hippocampus:memory-consolidated": ["7.5", "8.3"],
994
+ "prefrontal:deliberation": ["7.5", "8.3"],
995
+ "prefrontal:veto-amygdala": ["9.1", "10.1"],
996
+ "affect:reconciliation": ["8.3"],
997
+ "cortex:dream-stored": ["7.5", "8.3"],
998
+ "cortex:active-imagination": ["7.5", "8.3"],
999
+ "temporal-lobe:snapshot-generated": ["7.5", "10.2"],
1000
+ "limbo:enter": ["7.5", "9.1"],
1001
+ "limbo:return": ["7.5", "9.1"],
1002
+ // ── 1.0.1 reserved vocabulary (Entries 26 + 27) ──
1003
+ "him-summon": ["7.5", "8.3"],
1004
+ "him-pause-incarnation": ["7.5", "9.1"],
1005
+ "user-consent-recorded": ["7.5"],
1006
+ "user-consent-revoked": ["7.5", "10.1"],
1007
+ "directory-opt-in": ["7.5"],
1008
+ "directory-opt-out": ["7.5"],
1009
+ "him-astrological-chart-cast": ["7.5"],
1010
+ "him-jungian-profile-cast": ["7.5"],
1011
+ "provenance-deflection-applied": ["8.3", "9.1"]
1012
+ };
1013
+ var EU_AI_ACT_MAPPING = {
1014
+ "axiom-mint": ["art-11", "art-13"],
1015
+ "axiom-update": ["art-11"],
1016
+ "axiom-retire": ["art-11"],
1017
+ "him-register": ["art-11", "art-12"],
1018
+ "him-reincarnate": ["art-12"],
1019
+ "proposal-emerge": ["art-11", "art-12"],
1020
+ "proposal-ratify": ["art-11", "art-14"],
1021
+ "proposal-reject": ["art-12", "art-14"],
1022
+ "behavior-review": ["art-12", "art-14"],
1023
+ "dream-induce": ["art-14"],
1024
+ "dream-cancel": ["art-14"],
1025
+ "dream-consume": ["art-12"],
1026
+ "emergency-correct": ["art-14"],
1027
+ terminate: ["art-14"],
1028
+ deprecate: ["art-14"],
1029
+ reactivate: ["art-14"],
1030
+ "axiom-suggest": ["art-11", "art-12"],
1031
+ // ── 1.2 brain-as-code (Entries 16-24) ──
1032
+ opener: ["art-13"],
1033
+ "nickname-attempt": ["art-13"],
1034
+ "reincarnate:model-swap": ["art-12"],
1035
+ "reincarnate:version-bump": ["art-12"],
1036
+ "reincarnate:return-from-limbo": ["art-12"],
1037
+ "dream:rem-spontaneous": ["art-12"],
1038
+ "wake-affect:applied": ["art-12", "art-14"],
1039
+ "wake-affect:decayed": ["art-12"],
1040
+ "sleep:suggested-by-maic": ["art-12"],
1041
+ "sleep:declined-by-nhe": ["art-12", "art-14"],
1042
+ "dream:soft-intervention-by-maic": ["art-14"],
1043
+ "amygdala:affect-assessed": ["art-12"],
1044
+ "hippocampus:memory-retrieved": ["art-11", "art-12"],
1045
+ "hippocampus:memory-consolidated": ["art-11", "art-12"],
1046
+ "prefrontal:deliberation": ["art-11", "art-14"],
1047
+ "prefrontal:veto-amygdala": ["art-14"],
1048
+ "affect:reconciliation": ["art-12"],
1049
+ "cortex:dream-stored": ["art-11", "art-12"],
1050
+ "cortex:active-imagination": ["art-11", "art-12"],
1051
+ "temporal-lobe:snapshot-generated": ["art-11", "art-12"],
1052
+ "limbo:enter": ["art-12"],
1053
+ "limbo:return": ["art-12"],
1054
+ // ── 1.0.1 reserved vocabulary (Entries 26 + 27) ──
1055
+ "him-summon": ["art-11", "art-12"],
1056
+ "him-pause-incarnation": ["art-12"],
1057
+ "user-consent-recorded": ["art-10", "art-13"],
1058
+ "user-consent-revoked": ["art-10", "art-13"],
1059
+ "directory-opt-in": ["art-13"],
1060
+ "directory-opt-out": ["art-13"],
1061
+ "him-astrological-chart-cast": ["art-11", "art-12"],
1062
+ "him-jungian-profile-cast": ["art-11", "art-12"],
1063
+ "provenance-deflection-applied": ["art-13", "art-14"]
1064
+ };
1065
+ var ISO_42001_DESCRIPTIONS = {
1066
+ "5.2": "AI policy: published, communicated, reviewed for continuing suitability.",
1067
+ "7.5": "Documented information: created, controlled, retained for AI management activities.",
1068
+ "8.3": "Operational planning and control: AI processes are planned, implemented, controlled.",
1069
+ "9.1": "Monitoring, measurement, analysis and evaluation of AI performance.",
1070
+ "10.1": "Nonconformity and corrective action: issues recorded and resolved.",
1071
+ "10.2": "Continual improvement of the AI management system."
1072
+ };
1073
+ var EU_AI_ACT_DESCRIPTIONS = {
1074
+ "art-9": "Risk management system established, implemented, documented, maintained.",
1075
+ "art-10": "Data governance: datasets are relevant, representative, free of errors.",
1076
+ "art-11": "Technical documentation drawn up and kept up to date.",
1077
+ "art-12": "Automatic record-keeping (logs) over the AI system's lifetime.",
1078
+ "art-13": "Transparency to deployers: instructions for use, intended purpose.",
1079
+ "art-14": "Human oversight measures designed and implemented effectively.",
1080
+ "art-15": "Accuracy, robustness, and cybersecurity throughout the lifecycle."
1081
+ };
1082
+ var ComplianceMapper = class {
1083
+ static async project(audit, framework, opts = {}) {
1084
+ const mapping = framework === "iso-42001" ? ISO_42001_MAPPING : EU_AI_ACT_MAPPING;
1085
+ const descriptions = framework === "iso-42001" ? ISO_42001_DESCRIPTIONS : EU_AI_ACT_DESCRIPTIONS;
1086
+ const byControl = /* @__PURE__ */ new Map();
1087
+ const seenKinds = /* @__PURE__ */ new Set();
1088
+ const uncoveredSet = /* @__PURE__ */ new Set();
1089
+ let totalEvents = 0;
1090
+ let mappedEvents = 0;
1091
+ const query = {};
1092
+ if (opts.since) query.since = opts.since;
1093
+ if (opts.until) query.until = opts.until;
1094
+ for await (const ev of audit.query(query)) {
1095
+ totalEvents++;
1096
+ seenKinds.add(ev.kind);
1097
+ const controls2 = mapping[ev.kind] ?? [];
1098
+ if (controls2.length === 0) {
1099
+ uncoveredSet.add(ev.kind);
1100
+ continue;
1101
+ }
1102
+ mappedEvents++;
1103
+ const ce = {
1104
+ auditId: ev.auditId,
1105
+ ts: ev.ts,
1106
+ kind: ev.kind,
1107
+ summary: summarize(ev),
1108
+ data: ev.data
1109
+ };
1110
+ for (const ctrl of controls2) {
1111
+ const list = byControl.get(ctrl) ?? [];
1112
+ list.push(ce);
1113
+ byControl.set(ctrl, list);
1114
+ }
1106
1115
  }
1107
- if (existing.status !== "pending") {
1108
- throw new Error(
1109
- `InductionStore.cancel: ticket "${ticketId}" is already ${existing.status}, not pending`
1110
- );
1116
+ const controls = [];
1117
+ const sortedCtrls = [...byControl.keys()].sort();
1118
+ for (const ctrl of sortedCtrls) {
1119
+ const events = byControl.get(ctrl);
1120
+ const capped = opts.perControlLimit !== void 0 && events.length > opts.perControlLimit ? events.slice(-opts.perControlLimit) : events;
1121
+ controls.push({
1122
+ control: ctrl,
1123
+ description: descriptions[ctrl] ?? "",
1124
+ count: events.length,
1125
+ events: capped
1126
+ });
1111
1127
  }
1112
- const updated = {
1113
- ...existing,
1114
- status: "cancelled",
1115
- cancelledAt: (/* @__PURE__ */ new Date()).toISOString(),
1116
- ...reason !== void 0 ? { cancelReason: reason } : {}
1128
+ return {
1129
+ framework,
1130
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1131
+ range: {
1132
+ ...opts.since ? { since: opts.since } : {},
1133
+ ...opts.until ? { until: opts.until } : {}
1134
+ },
1135
+ totalEvents,
1136
+ mappedEvents,
1137
+ controls,
1138
+ uncoveredKinds: [...uncoveredSet]
1117
1139
  };
1118
- await this.persist(updated);
1119
- this.cache.set(ticketId, updated);
1120
- return updated;
1121
- }
1122
- async get(ticketId) {
1123
- return this.cache.get(ticketId) ?? null;
1124
- }
1125
- async list(filter) {
1126
- const all = [...this.cache.values()];
1127
- const filtered = all.filter((t) => {
1128
- if (filter.nheId && t.nheId !== filter.nheId) return false;
1129
- if (filter.status && t.status !== filter.status) return false;
1130
- return true;
1131
- });
1132
- filtered.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
1133
- return filtered;
1134
- }
1135
- /** Convenience: pending tickets for the given NHE, oldest first. */
1136
- async listPending(nheId) {
1137
- return this.list({ nheId, status: "pending" });
1138
- }
1139
- // ─── internals ──────────────────────────────────────────────────────
1140
- async persist(ticket) {
1141
- await writeFile(
1142
- join(this.dir, `${ticket.id}.json`),
1143
- JSON.stringify(ticket, null, 2),
1144
- "utf-8"
1145
- );
1146
- }
1147
- async warmCache() {
1148
- let entries;
1149
- try {
1150
- entries = await readdir(this.dir);
1151
- } catch (err) {
1152
- if (err.code === "ENOENT") return;
1153
- throw err;
1154
- }
1155
- for (const file of entries) {
1156
- if (!file.endsWith(".json")) continue;
1157
- const raw = await readFile(join(this.dir, file), "utf-8");
1158
- const ticket = DreamInductionTicket.parse(JSON.parse(raw));
1159
- this.cache.set(ticket.id, ticket);
1160
- }
1161
1140
  }
1162
1141
  };
1163
- var NheStatusStore = class _NheStatusStore {
1164
- constructor(storeDir, creatorPublicKey) {
1165
- this.storeDir = storeDir;
1166
- this.creatorPublicKey = creatorPublicKey;
1167
- this.dir = join(storeDir, "nhes");
1168
- }
1169
- storeDir;
1170
- creatorPublicKey;
1171
- dir;
1172
- cache = /* @__PURE__ */ new Map();
1173
- static async open(storeDir, creatorPublicKey) {
1174
- const s = new _NheStatusStore(storeDir, creatorPublicKey);
1175
- await mkdir(s.dir, { recursive: true });
1176
- await s.warmCache();
1177
- return s;
1178
- }
1179
- /** Returns the persisted record, or null when the NHE was never altered (implicitly active). */
1180
- async get(nheId) {
1181
- return this.cache.get(nheId) ?? null;
1142
+ function summarize(ev) {
1143
+ const data = ev.data;
1144
+ switch (ev.kind) {
1145
+ case "axiom-mint":
1146
+ return `Axiom minted: ${String(data.axiomId)} (${String(data.rank)}, ${String(data.origin)})`;
1147
+ case "axiom-update":
1148
+ return `Axiom updated: ${String(data.axiomId)}`;
1149
+ case "axiom-retire":
1150
+ return `Axiom retired: ${String(data.axiomId)}`;
1151
+ case "him-register":
1152
+ return `HIM registered: ${String(data.himId)} (archetype=${String(data.primaryArchetype)})`;
1153
+ case "him-reincarnate":
1154
+ return `HIM reincarnated: ${String(data.himId)} ${String(data.fromNheId ?? "<initial>")} \u2192 ${String(data.toNheId)} (${String(data.reason ?? "upgrade")})`;
1155
+ case "proposal-emerge":
1156
+ return `HIM-emergent axiom proposed by ${String(data.himId)}: "${String(data.statement)}" (rank=${String(data.rank)}), proposal ${String(data.proposalId)}`;
1157
+ case "proposal-ratify":
1158
+ return `Creator ratified axiom proposal ${String(data.proposalId)} for ${String(data.himId)} \u2192 ${String(data.axiomId)}`;
1159
+ case "proposal-reject":
1160
+ return `Creator rejected axiom proposal ${String(data.proposalId)} for ${String(data.himId)}: ${String(data.reason ?? "no reason")}`;
1161
+ case "behavior-review": {
1162
+ const verdict = data.verdict?.kind ?? "unknown";
1163
+ return `Behavior reviewed for ${String(data.nheId)}: ${verdict}`;
1164
+ }
1165
+ case "dream-induce":
1166
+ return `Dream induced for ${String(data.nheId)} by ${String(data.inducedBy)}, ticket ${String(data.ticketId)}`;
1167
+ case "dream-cancel":
1168
+ return `Dream induction cancelled, ticket ${String(data.ticketId)}`;
1169
+ case "dream-consume":
1170
+ return `Dream consumed by ${String(data.nheId)}, ticket ${String(data.ticketId)}`;
1171
+ case "emergency-correct":
1172
+ return `Emergency correction applied to ${String(data.nheId)}`;
1173
+ case "terminate":
1174
+ return `NHE terminated: ${String(data.nheId)} (reason: ${String(data.reason ?? "none")})`;
1175
+ case "deprecate":
1176
+ return `NHE deprecated: ${String(data.nheId)} (reason: ${String(data.reason ?? "none")})`;
1177
+ case "reactivate":
1178
+ return `NHE reactivated: ${String(data.nheId)}`;
1179
+ case "axiom-suggest":
1180
+ return `Axiom suggestion ${String(data.fromHimId)} \u2192 ${String(data.toHimId)}: "${String(data.statement)}"`;
1181
+ // ── 1.2 brain-as-code (Entries 16-24 of MAIC_HIM_NHE_INTERVIEW_LOG.md) ──
1182
+ case "opener":
1183
+ return `Proactive opener emitted by ${String(data.nheId)} for new user ${String(data.userId ?? "anonymous")}: "${String(data.text ?? "<elided>")}"`;
1184
+ case "nickname-attempt":
1185
+ return `Nickname attempt for ${String(data.nheId)}: "${String(data.attempted)}" \u2192 ${String(data.outcome ?? "pending")}`;
1186
+ case "reincarnate:model-swap":
1187
+ return `HIM reincarnated (model-swap): ${String(data.himId)} ${String(data.fromAdapter ?? "?")} \u2192 ${String(data.toAdapter ?? "?")}`;
1188
+ case "reincarnate:version-bump":
1189
+ return `HIM reincarnated (version-bump): ${String(data.himId)} ${String(data.fromVersion ?? "?")} \u2192 ${String(data.toVersion ?? "?")}`;
1190
+ case "reincarnate:return-from-limbo":
1191
+ return `HIM reincarnated (return-from-limbo): ${String(data.himId)} resumed after ${String(data.elapsedMs ?? 0)}ms of limbo`;
1192
+ case "dream:rem-spontaneous":
1193
+ return `Spontaneous REM dream for ${String(data.nheId)}: ${String(data.dreamId)} (dominant affect: ${String(data.dominantAffect ?? "unknown")})`;
1194
+ case "wake-affect:applied":
1195
+ return `Wake affect applied to ${String(data.nheId)}: ${String(data.affect)} (intensity ${String(data.intensity)}, halflife ${String(data.decayHalfLife)} interactions)`;
1196
+ case "wake-affect:decayed":
1197
+ return `Wake affect decayed for ${String(data.nheId)}: ${String(data.affect)} dissolved naturally`;
1198
+ case "sleep:suggested-by-maic":
1199
+ return `MAIC suggested sleep for ${String(data.nheId)} (reason: ${String(data.reason ?? "none")})`;
1200
+ case "sleep:declined-by-nhe":
1201
+ return `NHE ${String(data.nheId)} declined MAIC-suggested sleep (reason: ${String(data.reason ?? "none")})`;
1202
+ case "dream:soft-intervention-by-maic":
1203
+ return `MAIC soft-intervened on dream ${String(data.dreamId)} for ${String(data.nheId)} (reason: ${String(data.reason ?? "none")})`;
1204
+ case "amygdala:affect-assessed":
1205
+ return `Amygdala assessed input affect for ${String(data.nheId)}: ${String(data.detectedAffect ?? "neutral")} (risk multiplier ${String(data.riskMultiplier ?? 1)})`;
1206
+ case "hippocampus:memory-retrieved":
1207
+ return `Hippocampus retrieved ${String(data.memoryIds?.length ?? 0)} memories for ${String(data.nheId)}`;
1208
+ case "hippocampus:memory-consolidated":
1209
+ return `Hippocampus consolidated new memory ${String(data.memoryId)} for ${String(data.nheId)} (integrationIndex ${String(data.integrationIndex ?? 0)})`;
1210
+ case "prefrontal:deliberation":
1211
+ return `PFC deliberated for ${String(data.nheId)}: ${String(data.expressedOpenly ? "open" : "subtle")} (${String(data.affect ?? "neutral")})`;
1212
+ case "prefrontal:veto-amygdala":
1213
+ return `PFC vetoed amygdala impulse for ${String(data.nheId)}: ${String(data.originalImpulse ?? "?")} \u2192 ${String(data.resolvedAction ?? "?")} (downgrade ${String(data.downgradeRatio ?? "?")})`;
1214
+ case "affect:reconciliation":
1215
+ return `Affect reconciliation for ${String(data.nheId)}: day/night blend \u2192 ${String(data.resolvedAffect ?? "neutral")}`;
1216
+ case "cortex:dream-stored":
1217
+ return `Cortex stored dream ${String(data.dreamId)} for ${String(data.nheId)}`;
1218
+ case "cortex:active-imagination":
1219
+ return `Cortex generated active imagination for ${String(data.nheId)} (trigger: ${String(data.trigger ?? "user-requested")}, vividness ${String(data.vividness ?? 0)})`;
1220
+ case "temporal-lobe:snapshot-generated":
1221
+ return `Temporal-lobe snapshot ${String(data.snapshotId)} generated for HIM ${String(data.himId)} (reason: ${String(data.generatedBy ?? "self-decision")})`;
1222
+ case "limbo:enter":
1223
+ return `${String(data.nheId)} entered limbo (deep-coma), reason: ${String(data.reason ?? "idle")}`;
1224
+ case "limbo:return":
1225
+ return `${String(data.nheId)} returned from limbo after ${String(data.elapsedMs ?? 0)}ms (reunion intensity ${String(data.reunionIntensity ?? "?")})`;
1226
+ // ── 1.0.1 reserved vocabulary (Entries 26 + 27) ──
1227
+ case "him-summon":
1228
+ return `MAIC summoned a spirit into body ${String(data.nheId ?? "?")} for HIM ${String(data.himId)}`;
1229
+ case "him-pause-incarnation":
1230
+ return `HIM ${String(data.himId)} incarnation paused (reason: ${String(data.reason ?? "none")})`;
1231
+ case "user-consent-recorded":
1232
+ return `Consent recorded for user ${String(data.userId)} (version ${String(data.consentVersion ?? "?")})`;
1233
+ case "user-consent-revoked":
1234
+ return `Consent revoked for user ${String(data.userId)}`;
1235
+ case "directory-opt-in":
1236
+ return `HIM ${String(data.himId)} opted into the public directory`;
1237
+ case "directory-opt-out":
1238
+ return `HIM ${String(data.himId)} left the public directory`;
1239
+ case "him-astrological-chart-cast":
1240
+ return `Natal chart cast for HIM ${String(data.himId)} at birth`;
1241
+ case "him-jungian-profile-cast":
1242
+ return `Jungian profile cast for HIM ${String(data.himId)} (dominant: ${String(data.dominantArchetype ?? "?")})`;
1243
+ case "provenance-deflection-applied":
1244
+ return `Provenance deflection applied for ${String(data.nheId)} (probe: ${String(data.probe ?? "?")})`;
1245
+ default:
1246
+ return `Event ${ev.kind}`;
1182
1247
  }
1183
- /** Resolved status — defaults to "active" when no record exists. */
1184
- async resolve(nheId) {
1185
- return this.cache.get(nheId)?.status ?? "active";
1248
+ }
1249
+ var NonceLedger = class _NonceLedger {
1250
+ path;
1251
+ used = /* @__PURE__ */ new Set();
1252
+ constructor(dir) {
1253
+ this.path = join(dir, "nonces.log");
1254
+ }
1255
+ /** Open (or create) a ledger rooted at `dir`, loading any prior nonces. */
1256
+ static async open(dir) {
1257
+ const ledger = new _NonceLedger(dir);
1258
+ await mkdir(dir, { recursive: true });
1259
+ await ledger.load();
1260
+ return ledger;
1186
1261
  }
1187
- async list(filter = {}) {
1188
- const all = [...this.cache.values()];
1189
- return filter.status ? all.filter((r) => r.status === filter.status) : all;
1262
+ /** True when the nonce has already been consumed. */
1263
+ has(nonce) {
1264
+ return this.used.has(nonce);
1190
1265
  }
1191
- async apply(req, sig) {
1192
- if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, sig)) {
1193
- throw new Error("NheStatusStore.apply: invalid Creator signature");
1194
- }
1195
- const current = this.cache.get(req.nheId);
1196
- if (current?.status === "terminated" && req.op !== "reactivate") {
1197
- throw new Error(
1198
- `NheStatusStore.apply: nhe "${req.nheId}" is terminated; only reactivate may proceed`
1199
- );
1266
+ /**
1267
+ * Record a nonce as consumed. Throws when the nonce was already used, which
1268
+ * is the replay-protection gate. Callers invoke this immediately after a
1269
+ * successful Creator-signature verification and before the mutation, so a
1270
+ * replayed request is rejected before it can take effect.
1271
+ */
1272
+ async consume(nonce) {
1273
+ if (!Number.isInteger(nonce) || nonce < 0) {
1274
+ throw new Error(`NonceLedger.consume: nonce must be a non-negative integer, got ${nonce}`);
1200
1275
  }
1201
- const nextStatus = req.op === "terminate" ? "terminated" : req.op === "deprecate" ? "deprecated" : "active";
1202
- if (current?.status === nextStatus) {
1203
- return current;
1276
+ if (this.used.has(nonce)) {
1277
+ throw new Error(`NonceLedger: nonce ${nonce} already used (replay protection)`);
1204
1278
  }
1205
- const record = NheStatusRecord.parse({
1206
- nheId: req.nheId,
1207
- status: nextStatus,
1208
- since: (/* @__PURE__ */ new Date()).toISOString(),
1209
- ...req.reason !== void 0 ? { reason: req.reason } : {}
1210
- });
1211
- const nheDir = join(this.dir, req.nheId);
1212
- await mkdir(nheDir, { recursive: true });
1213
- await writeFile(
1214
- join(nheDir, "status.json"),
1215
- JSON.stringify(record, null, 2),
1216
- "utf-8"
1217
- );
1218
- this.cache.set(req.nheId, record);
1219
- return record;
1279
+ this.used.add(nonce);
1280
+ await appendFile(this.path, `${nonce}
1281
+ `, "utf-8");
1220
1282
  }
1221
- // ─── internals ──────────────────────────────────────────────────────
1222
- async warmCache() {
1223
- let entries;
1283
+ async load() {
1224
1284
  try {
1225
- entries = await readdir(this.dir);
1226
- } catch (err) {
1227
- if (err.code === "ENOENT") return;
1228
- throw err;
1229
- }
1230
- for (const nheId of entries) {
1231
- try {
1232
- const raw = await readFile(join(this.dir, nheId, "status.json"), "utf-8");
1233
- const record = NheStatusRecord.parse(JSON.parse(raw));
1234
- this.cache.set(record.nheId, record);
1235
- } catch (err) {
1236
- console.warn(
1237
- `NheStatusStore.warmCache: skipped malformed NHE "${nheId}": ${err instanceof Error ? err.message : String(err)}`
1238
- );
1285
+ const raw = await readFile(this.path, "utf-8");
1286
+ const endsWithNewline = raw.endsWith("\n");
1287
+ const rows = raw.split("\n");
1288
+ for (let i = 0; i < rows.length; i++) {
1289
+ if (i === rows.length - 1 && !endsWithNewline) break;
1290
+ const line = rows[i].trim();
1291
+ if (!/^\d+$/.test(line)) continue;
1292
+ this.used.add(Number(line));
1239
1293
  }
1294
+ } catch (err) {
1295
+ if (err.code !== "ENOENT") throw err;
1240
1296
  }
1241
1297
  }
1242
1298
  };
1243
- var ProposalStore = class _ProposalStore {
1244
- constructor(storeDir, creatorPublicKey) {
1245
- this.storeDir = storeDir;
1299
+ var HimStore = class _HimStore {
1300
+ constructor(storeDir, creatorPublicKey, nonces) {
1246
1301
  this.creatorPublicKey = creatorPublicKey;
1247
- this.dir = join(storeDir, "proposals");
1302
+ this.nonces = nonces;
1303
+ this.himsDir = join(storeDir, "hims");
1248
1304
  }
1249
- storeDir;
1250
1305
  creatorPublicKey;
1251
- dir;
1306
+ nonces;
1307
+ himsDir;
1252
1308
  cache = /* @__PURE__ */ new Map();
1253
1309
  static async open(storeDir, creatorPublicKey) {
1254
- const s = new _ProposalStore(storeDir, creatorPublicKey);
1255
- await mkdir(s.dir, { recursive: true });
1310
+ const himsDir = join(storeDir, "hims");
1311
+ const nonces = await NonceLedger.open(himsDir);
1312
+ const s = new _HimStore(storeDir, creatorPublicKey, nonces);
1313
+ await mkdir(s.himsDir, { recursive: true });
1256
1314
  await s.warmCache();
1257
1315
  return s;
1258
1316
  }
1259
- async propose(himId, proposal) {
1260
- const parsedProposal = EmergentAxiomProposal.parse(proposal);
1261
- const record = AxiomProposalRecord.parse({
1262
- id: ulid(),
1263
- himId,
1264
- proposedAt: (/* @__PURE__ */ new Date()).toISOString(),
1265
- status: "pending",
1266
- proposal: parsedProposal
1267
- });
1268
- await this.persist(record);
1269
- this.cache.set(record.id, record);
1317
+ /**
1318
+ * Validate that a birth signature is registerable (valid Creator signature,
1319
+ * himId not already taken) WITHOUT persisting anything or touching the audit
1320
+ * chain. `LocalMaic.registerHim` calls this before it appends the
1321
+ * `him-register` audit event, so a rejected registration never pollutes the
1322
+ * tamper-evident log (M1-1, 1.0.1). `register` re-runs the same checks, so it
1323
+ * remains safe to call directly.
1324
+ */
1325
+ assertRegisterable(birthSignature, creatorSig) {
1326
+ if (!CreatorKeyring.verifyWith(this.creatorPublicKey, birthSignature, creatorSig)) {
1327
+ throw new Error("HimStore.register: invalid Creator signature");
1328
+ }
1329
+ if (this.cache.has(birthSignature.himId)) {
1330
+ throw new Error(`HimStore.register: himId "${birthSignature.himId}" is already registered`);
1331
+ }
1332
+ }
1333
+ async register(birthSignature, creatorSig, axiomsSnapshot, registeredAuditId) {
1334
+ this.assertRegisterable(birthSignature, creatorSig);
1335
+ const record = {
1336
+ himId: birthSignature.himId,
1337
+ birthSignature,
1338
+ axiomsSnapshot: [...axiomsSnapshot],
1339
+ registeredAt: (/* @__PURE__ */ new Date()).toISOString(),
1340
+ ...registeredAuditId !== void 0 ? { registeredAuditId } : {},
1341
+ bodyHistory: [],
1342
+ emergentAxioms: []
1343
+ };
1344
+ const dir = join(this.himsDir, birthSignature.himId);
1345
+ await mkdir(dir, { recursive: true });
1346
+ await atomicWriteFile(
1347
+ join(dir, "birth-signature.json"),
1348
+ JSON.stringify({ birthSignature, signature: creatorSig }, null, 2)
1349
+ );
1350
+ await atomicWriteFile(
1351
+ join(dir, "axioms-snapshot.json"),
1352
+ JSON.stringify(axiomsSnapshot, null, 2)
1353
+ );
1354
+ await atomicWriteFile(
1355
+ join(dir, "metadata.json"),
1356
+ JSON.stringify({ registeredAt: record.registeredAt, registeredAuditId }, null, 2)
1357
+ );
1358
+ this.cache.set(birthSignature.himId, record);
1270
1359
  return record;
1271
1360
  }
1272
1361
  /**
1273
- * Mark a pending proposal as ratified. The caller (LocalMaic) is responsible
1274
- * for actually minting the axiom and appending to the HIM's emergentAxioms.
1362
+ * Atomically transition a HIM into a new NHE body (Entry 4):
1363
+ * - If req.fromNheId is provided AND matches the last body still open,
1364
+ * that entry gets `endedAt: now` + `endedReason: req.reason ?? "upgrade"`.
1365
+ * - The new body (`req.toBody`) is appended.
1366
+ * - Persisted to body-history.json atomically.
1367
+ *
1368
+ * Requires a Creator signature over the canonical request payload.
1275
1369
  */
1276
- async markRatified(req, sig, ratifiedAxiomId) {
1277
- if (req.op !== "ratify") {
1278
- throw new Error(`ProposalStore.markRatified: req.op must be "ratify"`);
1370
+ async reincarnate(req, creatorSig) {
1371
+ if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, creatorSig)) {
1372
+ throw new Error("HimStore.reincarnate: invalid Creator signature");
1279
1373
  }
1280
- if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, sig)) {
1281
- throw new Error("ProposalStore.markRatified: invalid Creator signature");
1374
+ const current = this.cache.get(req.himId);
1375
+ if (!current) {
1376
+ throw new Error(`HimStore.reincarnate: himId "${req.himId}" not registered`);
1282
1377
  }
1283
- const existing = this.cache.get(req.proposalId);
1284
- if (!existing) {
1285
- throw new Error(`ProposalStore.markRatified: proposal "${req.proposalId}" not found`);
1378
+ const toBody = NheBodyRef.parse(req.toBody);
1379
+ await this.nonces.consume(creatorSig.nonce);
1380
+ const updatedHistory = current.bodyHistory.map((b) => ({ ...b }));
1381
+ if (req.fromNheId !== void 0) {
1382
+ const matchIdx = updatedHistory.findIndex(
1383
+ (b) => b.nheId === req.fromNheId && b.endedAt === void 0
1384
+ );
1385
+ if (matchIdx < 0) {
1386
+ throw new Error(`HimStore.reincarnate: no open body matching fromNheId "${req.fromNheId}"`);
1387
+ }
1388
+ const reason = req.reason ?? "upgrade";
1389
+ updatedHistory[matchIdx] = {
1390
+ ...updatedHistory[matchIdx],
1391
+ endedAt: (/* @__PURE__ */ new Date()).toISOString(),
1392
+ endedReason: reason
1393
+ };
1286
1394
  }
1287
- if (existing.status !== "pending") {
1395
+ if (updatedHistory.some((b) => b.nheId === toBody.nheId && b.endedAt === void 0)) {
1288
1396
  throw new Error(
1289
- `ProposalStore.markRatified: proposal "${req.proposalId}" is ${existing.status}, not pending`
1397
+ `HimStore.reincarnate: toBody nheId "${toBody.nheId}" already has an open body`
1290
1398
  );
1291
1399
  }
1400
+ updatedHistory.push(toBody);
1292
1401
  const updated = {
1293
- ...existing,
1294
- status: "ratified",
1295
- ratifiedAt: (/* @__PURE__ */ new Date()).toISOString(),
1296
- ratifiedAxiomId
1402
+ ...current,
1403
+ bodyHistory: updatedHistory
1297
1404
  };
1298
- await this.persist(updated);
1299
- this.cache.set(req.proposalId, updated);
1405
+ const dir = join(this.himsDir, req.himId);
1406
+ await atomicWriteFile(join(dir, "body-history.json"), JSON.stringify(updatedHistory, null, 2));
1407
+ this.cache.set(req.himId, updated);
1300
1408
  return updated;
1301
1409
  }
1302
- async markRejected(req, sig) {
1303
- if (req.op !== "reject") {
1304
- throw new Error(`ProposalStore.markRejected: req.op must be "reject"`);
1305
- }
1306
- if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, sig)) {
1307
- throw new Error("ProposalStore.markRejected: invalid Creator signature");
1308
- }
1309
- const existing = this.cache.get(req.proposalId);
1310
- if (!existing) {
1311
- throw new Error(`ProposalStore.markRejected: proposal "${req.proposalId}" not found`);
1410
+ /**
1411
+ * Append a ratified emergent axiom to the HIM's `emergentAxioms` (Entry 7).
1412
+ * Called by LocalMaic after a Creator-signed `ratifyAxiomProposal`.
1413
+ * Persists `<himId>/emergent-axioms.json` atomically.
1414
+ */
1415
+ async appendEmergentAxiom(himId, axiom) {
1416
+ const current = this.cache.get(himId);
1417
+ if (!current) {
1418
+ throw new Error(`HimStore.appendEmergentAxiom: himId "${himId}" not registered`);
1312
1419
  }
1313
- if (existing.status !== "pending") {
1314
- throw new Error(
1315
- `ProposalStore.markRejected: proposal "${req.proposalId}" is ${existing.status}, not pending`
1316
- );
1420
+ if (current.emergentAxioms.some((a) => a.id === axiom.id)) {
1421
+ return current;
1317
1422
  }
1318
- const updated = {
1319
- ...existing,
1320
- status: "rejected",
1321
- rejectedAt: (/* @__PURE__ */ new Date()).toISOString(),
1322
- ...req.reason !== void 0 ? { rejectionReason: req.reason } : {}
1323
- };
1324
- await this.persist(updated);
1325
- this.cache.set(req.proposalId, updated);
1423
+ const updatedEmergent = [...current.emergentAxioms, axiom];
1424
+ const updated = { ...current, emergentAxioms: updatedEmergent };
1425
+ await atomicWriteFile(
1426
+ join(this.himsDir, himId, "emergent-axioms.json"),
1427
+ JSON.stringify(updatedEmergent, null, 2)
1428
+ );
1429
+ this.cache.set(himId, updated);
1326
1430
  return updated;
1327
1431
  }
1328
- async get(proposalId) {
1329
- return this.cache.get(proposalId) ?? null;
1432
+ async get(himId) {
1433
+ return this.cache.get(himId) ?? null;
1330
1434
  }
1331
- async list(filter = {}) {
1332
- const all = [...this.cache.values()];
1333
- const filtered = all.filter((r) => {
1334
- if (filter.himId && r.himId !== filter.himId) return false;
1335
- if (filter.status && r.status !== filter.status) return false;
1336
- return true;
1337
- });
1338
- filtered.sort((a, b) => a.proposedAt.localeCompare(b.proposedAt));
1339
- return filtered;
1435
+ async list() {
1436
+ return [...this.cache.values()];
1340
1437
  }
1341
1438
  // ─── internals ──────────────────────────────────────────────────────
1342
- async persist(record) {
1343
- await writeFile(
1344
- join(this.dir, `${record.id}.json`),
1345
- JSON.stringify(record, null, 2),
1346
- "utf-8"
1347
- );
1348
- }
1349
1439
  async warmCache() {
1350
1440
  let entries;
1351
1441
  try {
1352
- entries = await readdir(this.dir);
1442
+ entries = await readdir(this.himsDir);
1353
1443
  } catch (err) {
1354
1444
  if (err.code === "ENOENT") return;
1355
1445
  throw err;
1356
1446
  }
1357
- for (const file of entries) {
1358
- if (!file.endsWith(".json")) continue;
1359
- const raw = await readFile(join(this.dir, file), "utf-8");
1360
- const record = AxiomProposalRecord.parse(JSON.parse(raw));
1361
- this.cache.set(record.id, record);
1362
- }
1363
- }
1364
- };
1365
-
1366
- // src/compliance/mapper.ts
1367
- var ISO_42001_MAPPING = {
1368
- "axiom-mint": ["5.2", "7.5"],
1369
- "axiom-update": ["10.2", "7.5"],
1370
- "axiom-retire": ["10.2", "7.5"],
1371
- "him-register": ["7.5"],
1372
- "him-reincarnate": ["10.2", "7.5"],
1373
- "proposal-emerge": ["7.5", "10.2"],
1374
- "proposal-ratify": ["10.2", "5.2"],
1375
- "proposal-reject": ["10.2", "10.1"],
1376
- "behavior-review": ["7.5", "8.3"],
1377
- "dream-induce": ["8.3", "9.1"],
1378
- "dream-cancel": ["8.3"],
1379
- "dream-consume": ["8.3", "7.5"],
1380
- "emergency-correct": ["9.1", "10.1"],
1381
- "terminate": ["10.1"],
1382
- "deprecate": ["9.1"],
1383
- "reactivate": ["10.1"],
1384
- "axiom-suggest": ["7.5", "10.2"],
1385
- // ── 1.2 brain-as-code (Entries 16-24) ──
1386
- "opener": ["8.3", "7.5"],
1387
- "nickname-attempt": ["8.3"],
1388
- "reincarnate:model-swap": ["7.5", "10.2"],
1389
- "reincarnate:version-bump": ["7.5", "10.2"],
1390
- "reincarnate:return-from-limbo": ["7.5", "10.2"],
1391
- "dream:rem-spontaneous": ["8.3", "9.1"],
1392
- "wake-affect:applied": ["9.1"],
1393
- "wake-affect:decayed": ["9.1"],
1394
- "sleep:suggested-by-maic": ["9.1"],
1395
- "sleep:declined-by-nhe": ["9.1", "10.1"],
1396
- "dream:soft-intervention-by-maic": ["9.1", "10.1"],
1397
- "amygdala:affect-assessed": ["8.3"],
1398
- "hippocampus:memory-retrieved": ["7.5", "8.3"],
1399
- "hippocampus:memory-consolidated": ["7.5", "8.3"],
1400
- "prefrontal:deliberation": ["7.5", "8.3"],
1401
- "prefrontal:veto-amygdala": ["9.1", "10.1"],
1402
- "affect:reconciliation": ["8.3"],
1403
- "cortex:dream-stored": ["7.5", "8.3"],
1404
- "cortex:active-imagination": ["7.5", "8.3"],
1405
- "temporal-lobe:snapshot-generated": ["7.5", "10.2"],
1406
- "limbo:enter": ["7.5", "9.1"],
1407
- "limbo:return": ["7.5", "9.1"]
1408
- };
1409
- var EU_AI_ACT_MAPPING = {
1410
- "axiom-mint": ["art-11", "art-13"],
1411
- "axiom-update": ["art-11"],
1412
- "axiom-retire": ["art-11"],
1413
- "him-register": ["art-11", "art-12"],
1414
- "him-reincarnate": ["art-12"],
1415
- "proposal-emerge": ["art-11", "art-12"],
1416
- "proposal-ratify": ["art-11", "art-14"],
1417
- "proposal-reject": ["art-12", "art-14"],
1418
- "behavior-review": ["art-12", "art-14"],
1419
- "dream-induce": ["art-14"],
1420
- "dream-cancel": ["art-14"],
1421
- "dream-consume": ["art-12"],
1422
- "emergency-correct": ["art-14"],
1423
- "terminate": ["art-14"],
1424
- "deprecate": ["art-14"],
1425
- "reactivate": ["art-14"],
1426
- "axiom-suggest": ["art-11", "art-12"],
1427
- // ── 1.2 brain-as-code (Entries 16-24) ──
1428
- "opener": ["art-13"],
1429
- "nickname-attempt": ["art-13"],
1430
- "reincarnate:model-swap": ["art-12"],
1431
- "reincarnate:version-bump": ["art-12"],
1432
- "reincarnate:return-from-limbo": ["art-12"],
1433
- "dream:rem-spontaneous": ["art-12"],
1434
- "wake-affect:applied": ["art-12", "art-14"],
1435
- "wake-affect:decayed": ["art-12"],
1436
- "sleep:suggested-by-maic": ["art-12"],
1437
- "sleep:declined-by-nhe": ["art-12", "art-14"],
1438
- "dream:soft-intervention-by-maic": ["art-14"],
1439
- "amygdala:affect-assessed": ["art-12"],
1440
- "hippocampus:memory-retrieved": ["art-11", "art-12"],
1441
- "hippocampus:memory-consolidated": ["art-11", "art-12"],
1442
- "prefrontal:deliberation": ["art-11", "art-14"],
1443
- "prefrontal:veto-amygdala": ["art-14"],
1444
- "affect:reconciliation": ["art-12"],
1445
- "cortex:dream-stored": ["art-11", "art-12"],
1446
- "cortex:active-imagination": ["art-11", "art-12"],
1447
- "temporal-lobe:snapshot-generated": ["art-11", "art-12"],
1448
- "limbo:enter": ["art-12"],
1449
- "limbo:return": ["art-12"]
1450
- };
1451
- var ISO_42001_DESCRIPTIONS = {
1452
- "5.2": "AI policy \u2014 published, communicated, reviewed for continuing suitability.",
1453
- "7.5": "Documented information \u2014 created, controlled, retained for AI management activities.",
1454
- "8.3": "Operational planning and control \u2014 AI processes are planned, implemented, controlled.",
1455
- "9.1": "Monitoring, measurement, analysis and evaluation of AI performance.",
1456
- "10.1": "Nonconformity and corrective action \u2014 issues recorded and resolved.",
1457
- "10.2": "Continual improvement of the AI management system."
1458
- };
1459
- var EU_AI_ACT_DESCRIPTIONS = {
1460
- "art-9": "Risk management system established, implemented, documented, maintained.",
1461
- "art-10": "Data governance \u2014 datasets are relevant, representative, free of errors.",
1462
- "art-11": "Technical documentation drawn up and kept up to date.",
1463
- "art-12": "Automatic record-keeping (logs) over the AI system's lifetime.",
1464
- "art-13": "Transparency to deployers \u2014 instructions for use, intended purpose.",
1465
- "art-14": "Human oversight measures designed and implemented effectively.",
1466
- "art-15": "Accuracy, robustness, and cybersecurity throughout the lifecycle."
1467
- };
1468
- var ComplianceMapper = class {
1469
- static async project(audit, framework, opts = {}) {
1470
- const mapping = framework === "iso-42001" ? ISO_42001_MAPPING : EU_AI_ACT_MAPPING;
1471
- const descriptions = framework === "iso-42001" ? ISO_42001_DESCRIPTIONS : EU_AI_ACT_DESCRIPTIONS;
1472
- const byControl = /* @__PURE__ */ new Map();
1473
- const seenKinds = /* @__PURE__ */ new Set();
1474
- const uncoveredSet = /* @__PURE__ */ new Set();
1475
- let totalEvents = 0;
1476
- let mappedEvents = 0;
1477
- const query = {};
1478
- if (opts.since) query.since = opts.since;
1479
- if (opts.until) query.until = opts.until;
1480
- for await (const ev of audit.query(query)) {
1481
- totalEvents++;
1482
- seenKinds.add(ev.kind);
1483
- const controls2 = mapping[ev.kind] ?? [];
1484
- if (controls2.length === 0) {
1485
- uncoveredSet.add(ev.kind);
1486
- continue;
1487
- }
1488
- mappedEvents++;
1489
- const ce = {
1490
- auditId: ev.auditId,
1491
- ts: ev.ts,
1492
- kind: ev.kind,
1493
- summary: summarize(ev),
1494
- data: ev.data
1495
- };
1496
- for (const ctrl of controls2) {
1497
- const list = byControl.get(ctrl) ?? [];
1498
- list.push(ce);
1499
- byControl.set(ctrl, list);
1447
+ for (const himId of entries) {
1448
+ const dir = join(this.himsDir, himId);
1449
+ const sigPath = join(dir, "birth-signature.json");
1450
+ const axiomsPath = join(dir, "axioms-snapshot.json");
1451
+ const metaPath = join(dir, "metadata.json");
1452
+ const historyPath = join(dir, "body-history.json");
1453
+ const emergentPath = join(dir, "emergent-axioms.json");
1454
+ try {
1455
+ const sigRaw = await readFile(sigPath, "utf-8");
1456
+ const axiomsRaw = await readFile(axiomsPath, "utf-8");
1457
+ const metaRaw = await readFile(metaPath, "utf-8");
1458
+ const envelope = JSON.parse(sigRaw);
1459
+ const axioms = JSON.parse(axiomsRaw);
1460
+ const meta = JSON.parse(metaRaw);
1461
+ const birthSignature = BirthSignatureWithIdentity.parse(envelope.birthSignature);
1462
+ const axiomsSnapshot = Axiom.array().parse(axioms);
1463
+ let bodyHistory = [];
1464
+ try {
1465
+ const historyRaw = await readFile(historyPath, "utf-8");
1466
+ bodyHistory = NheBodyRef.array().parse(JSON.parse(historyRaw));
1467
+ } catch (err) {
1468
+ if (err.code !== "ENOENT") throw err;
1469
+ }
1470
+ let emergentAxioms = [];
1471
+ try {
1472
+ const emergentRaw = await readFile(emergentPath, "utf-8");
1473
+ emergentAxioms = Axiom.array().parse(JSON.parse(emergentRaw));
1474
+ } catch (err) {
1475
+ if (err.code !== "ENOENT") throw err;
1476
+ }
1477
+ this.cache.set(birthSignature.himId, {
1478
+ himId: birthSignature.himId,
1479
+ birthSignature,
1480
+ axiomsSnapshot,
1481
+ registeredAt: meta.registeredAt,
1482
+ ...meta.registeredAuditId ? { registeredAuditId: meta.registeredAuditId } : {},
1483
+ bodyHistory,
1484
+ emergentAxioms
1485
+ });
1486
+ } catch (err) {
1487
+ console.warn(
1488
+ `HimStore.warmCache: skipped malformed HIM "${himId}": ${err instanceof Error ? err.message : String(err)}`
1489
+ );
1500
1490
  }
1501
1491
  }
1502
- const controls = [];
1503
- const sortedCtrls = [...byControl.keys()].sort();
1504
- for (const ctrl of sortedCtrls) {
1505
- const events = byControl.get(ctrl);
1506
- const capped = opts.perControlLimit !== void 0 && events.length > opts.perControlLimit ? events.slice(-opts.perControlLimit) : events;
1507
- controls.push({
1508
- control: ctrl,
1509
- description: descriptions[ctrl] ?? "",
1510
- count: events.length,
1511
- events: capped
1512
- });
1492
+ }
1493
+ };
1494
+ var InductionStore = class _InductionStore {
1495
+ dir;
1496
+ cache = /* @__PURE__ */ new Map();
1497
+ constructor(storeDir) {
1498
+ this.dir = join(storeDir, "inductions");
1499
+ }
1500
+ static async open(storeDir) {
1501
+ const s = new _InductionStore(storeDir);
1502
+ await mkdir(s.dir, { recursive: true });
1503
+ await s.warmCache();
1504
+ return s;
1505
+ }
1506
+ async induce(nheId, intent) {
1507
+ const parsedIntent = DreamInductionIntent.parse(intent);
1508
+ const ticket = DreamInductionTicket.parse({
1509
+ id: ulid(),
1510
+ nheId,
1511
+ intent: parsedIntent,
1512
+ status: "pending",
1513
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1514
+ });
1515
+ await this.persist(ticket);
1516
+ this.cache.set(ticket.id, ticket);
1517
+ return ticket;
1518
+ }
1519
+ async consume(ticketId) {
1520
+ const existing = this.cache.get(ticketId);
1521
+ if (!existing) {
1522
+ throw new Error(`InductionStore.consume: ticket "${ticketId}" not found`);
1513
1523
  }
1514
- return {
1515
- framework,
1516
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1517
- range: {
1518
- ...opts.since ? { since: opts.since } : {},
1519
- ...opts.until ? { until: opts.until } : {}
1520
- },
1521
- totalEvents,
1522
- mappedEvents,
1523
- controls,
1524
- uncoveredKinds: [...uncoveredSet]
1524
+ if (existing.status !== "pending") {
1525
+ throw new Error(
1526
+ `InductionStore.consume: ticket "${ticketId}" is ${existing.status}, not pending`
1527
+ );
1528
+ }
1529
+ const updated = {
1530
+ ...existing,
1531
+ status: "consumed",
1532
+ consumedAt: (/* @__PURE__ */ new Date()).toISOString()
1533
+ };
1534
+ await this.persist(updated);
1535
+ this.cache.set(ticketId, updated);
1536
+ return updated;
1537
+ }
1538
+ async cancel(ticketId, reason) {
1539
+ const existing = this.cache.get(ticketId);
1540
+ if (!existing) {
1541
+ throw new Error(`InductionStore.cancel: ticket "${ticketId}" not found`);
1542
+ }
1543
+ if (existing.status !== "pending") {
1544
+ throw new Error(
1545
+ `InductionStore.cancel: ticket "${ticketId}" is already ${existing.status}, not pending`
1546
+ );
1547
+ }
1548
+ const updated = {
1549
+ ...existing,
1550
+ status: "cancelled",
1551
+ cancelledAt: (/* @__PURE__ */ new Date()).toISOString(),
1552
+ ...reason !== void 0 ? { cancelReason: reason } : {}
1525
1553
  };
1554
+ await this.persist(updated);
1555
+ this.cache.set(ticketId, updated);
1556
+ return updated;
1557
+ }
1558
+ async get(ticketId) {
1559
+ return this.cache.get(ticketId) ?? null;
1560
+ }
1561
+ async list(filter) {
1562
+ const all = [...this.cache.values()];
1563
+ const filtered = all.filter((t) => {
1564
+ if (filter.nheId && t.nheId !== filter.nheId) return false;
1565
+ if (filter.status && t.status !== filter.status) return false;
1566
+ return true;
1567
+ });
1568
+ filtered.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
1569
+ return filtered;
1570
+ }
1571
+ /** Convenience: pending tickets for the given NHE, oldest first. */
1572
+ async listPending(nheId) {
1573
+ return this.list({ nheId, status: "pending" });
1574
+ }
1575
+ // ─── internals ──────────────────────────────────────────────────────
1576
+ async persist(ticket) {
1577
+ await atomicWriteFile(join(this.dir, `${ticket.id}.json`), JSON.stringify(ticket, null, 2));
1578
+ }
1579
+ async warmCache() {
1580
+ let entries;
1581
+ try {
1582
+ entries = await readdir(this.dir);
1583
+ } catch (err) {
1584
+ if (err.code === "ENOENT") return;
1585
+ throw err;
1586
+ }
1587
+ for (const file of entries) {
1588
+ if (!file.endsWith(".json")) continue;
1589
+ try {
1590
+ const raw = await readFile(join(this.dir, file), "utf-8");
1591
+ const ticket = DreamInductionTicket.parse(JSON.parse(raw));
1592
+ this.cache.set(ticket.id, ticket);
1593
+ } catch (err) {
1594
+ console.warn(`InductionStore: skipping malformed ticket file "${file}": ${String(err)}`);
1595
+ }
1596
+ }
1526
1597
  }
1527
1598
  };
1528
- function summarize(ev) {
1529
- const data = ev.data;
1530
- switch (ev.kind) {
1531
- case "axiom-mint":
1532
- return `Axiom minted: ${String(data.axiomId)} (${String(data.rank)}, ${String(data.origin)})`;
1533
- case "axiom-update":
1534
- return `Axiom updated: ${String(data.axiomId)}`;
1535
- case "axiom-retire":
1536
- return `Axiom retired: ${String(data.axiomId)}`;
1537
- case "him-register":
1538
- return `HIM registered: ${String(data.himId)} (archetype=${String(data.primaryArchetype)})`;
1539
- case "him-reincarnate":
1540
- return `HIM reincarnated: ${String(data.himId)} ${String(data.fromNheId ?? "<initial>")} \u2192 ${String(data.toNheId)} (${String(data.reason ?? "upgrade")})`;
1541
- case "proposal-emerge":
1542
- return `HIM-emergent axiom proposed by ${String(data.himId)}: "${String(data.statement)}" (rank=${String(data.rank)}) \u2014 proposal ${String(data.proposalId)}`;
1543
- case "proposal-ratify":
1544
- return `Creator ratified axiom proposal ${String(data.proposalId)} for ${String(data.himId)} \u2192 ${String(data.axiomId)}`;
1545
- case "proposal-reject":
1546
- return `Creator rejected axiom proposal ${String(data.proposalId)} for ${String(data.himId)}: ${String(data.reason ?? "no reason")}`;
1547
- case "behavior-review": {
1548
- const verdict = data.verdict?.kind ?? "unknown";
1549
- return `Behavior reviewed for ${String(data.nheId)}: ${verdict}`;
1599
+ var NheStatusStore = class _NheStatusStore {
1600
+ constructor(storeDir, creatorPublicKey, nonces) {
1601
+ this.creatorPublicKey = creatorPublicKey;
1602
+ this.nonces = nonces;
1603
+ this.dir = join(storeDir, "nhes");
1604
+ }
1605
+ creatorPublicKey;
1606
+ nonces;
1607
+ dir;
1608
+ cache = /* @__PURE__ */ new Map();
1609
+ static async open(storeDir, creatorPublicKey) {
1610
+ const dir = join(storeDir, "nhes");
1611
+ const nonces = await NonceLedger.open(dir);
1612
+ const s = new _NheStatusStore(storeDir, creatorPublicKey, nonces);
1613
+ await mkdir(s.dir, { recursive: true });
1614
+ await s.warmCache();
1615
+ return s;
1616
+ }
1617
+ /** Returns the persisted record, or null when the NHE was never altered (implicitly active). */
1618
+ async get(nheId) {
1619
+ return this.cache.get(nheId) ?? null;
1620
+ }
1621
+ /** Resolved status, defaults to "active" when no record exists. */
1622
+ async resolve(nheId) {
1623
+ return this.cache.get(nheId)?.status ?? "active";
1624
+ }
1625
+ async list(filter = {}) {
1626
+ const all = [...this.cache.values()];
1627
+ return filter.status ? all.filter((r) => r.status === filter.status) : all;
1628
+ }
1629
+ async apply(req, sig) {
1630
+ if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, sig)) {
1631
+ throw new Error("NheStatusStore.apply: invalid Creator signature");
1632
+ }
1633
+ const current = this.cache.get(req.nheId);
1634
+ if (current?.status === "terminated" && req.op !== "reactivate") {
1635
+ throw new Error(
1636
+ `NheStatusStore.apply: nhe "${req.nheId}" is terminated; only reactivate may proceed`
1637
+ );
1638
+ }
1639
+ const nextStatus = req.op === "terminate" ? "terminated" : req.op === "deprecate" ? "deprecated" : "active";
1640
+ if (current?.status === nextStatus) {
1641
+ return current;
1642
+ }
1643
+ await this.nonces.consume(sig.nonce);
1644
+ const record = NheStatusRecord.parse({
1645
+ nheId: req.nheId,
1646
+ status: nextStatus,
1647
+ since: (/* @__PURE__ */ new Date()).toISOString(),
1648
+ ...req.reason !== void 0 ? { reason: req.reason } : {}
1649
+ });
1650
+ const nheDir = join(this.dir, req.nheId);
1651
+ await mkdir(nheDir, { recursive: true });
1652
+ await atomicWriteFile(join(nheDir, "status.json"), JSON.stringify(record, null, 2));
1653
+ this.cache.set(req.nheId, record);
1654
+ return record;
1655
+ }
1656
+ // ─── internals ──────────────────────────────────────────────────────
1657
+ async warmCache() {
1658
+ let entries;
1659
+ try {
1660
+ entries = await readdir(this.dir);
1661
+ } catch (err) {
1662
+ if (err.code === "ENOENT") return;
1663
+ throw err;
1664
+ }
1665
+ for (const nheId of entries) {
1666
+ try {
1667
+ const raw = await readFile(join(this.dir, nheId, "status.json"), "utf-8");
1668
+ const record = NheStatusRecord.parse(JSON.parse(raw));
1669
+ this.cache.set(record.nheId, record);
1670
+ } catch (err) {
1671
+ console.warn(
1672
+ `NheStatusStore.warmCache: skipped malformed NHE "${nheId}": ${err instanceof Error ? err.message : String(err)}`
1673
+ );
1674
+ }
1550
1675
  }
1551
- case "dream-induce":
1552
- return `Dream induced for ${String(data.nheId)} by ${String(data.inducedBy)} \u2014 ticket ${String(data.ticketId)}`;
1553
- case "dream-cancel":
1554
- return `Dream induction cancelled \u2014 ticket ${String(data.ticketId)}`;
1555
- case "dream-consume":
1556
- return `Dream consumed by ${String(data.nheId)} \u2014 ticket ${String(data.ticketId)}`;
1557
- case "emergency-correct":
1558
- return `Emergency correction applied to ${String(data.nheId)}`;
1559
- case "terminate":
1560
- return `NHE terminated: ${String(data.nheId)} (reason: ${String(data.reason ?? "none")})`;
1561
- case "deprecate":
1562
- return `NHE deprecated: ${String(data.nheId)} (reason: ${String(data.reason ?? "none")})`;
1563
- case "reactivate":
1564
- return `NHE reactivated: ${String(data.nheId)}`;
1565
- case "axiom-suggest":
1566
- return `Axiom suggestion ${String(data.fromHimId)} \u2192 ${String(data.toHimId)}: "${String(data.statement)}"`;
1567
- // ── 1.2 brain-as-code (Entries 16-24 of MAIC_HIM_NHE_INTERVIEW_LOG.md) ──
1568
- case "opener":
1569
- return `Proactive opener emitted by ${String(data.nheId)} for new user ${String(data.userId ?? "anonymous")}: "${String(data.text ?? "<elided>")}"`;
1570
- case "nickname-attempt":
1571
- return `Nickname attempt for ${String(data.nheId)}: "${String(data.attempted)}" \u2192 ${String(data.outcome ?? "pending")}`;
1572
- case "reincarnate:model-swap":
1573
- return `HIM reincarnated (model-swap): ${String(data.himId)} ${String(data.fromAdapter ?? "?")} \u2192 ${String(data.toAdapter ?? "?")}`;
1574
- case "reincarnate:version-bump":
1575
- return `HIM reincarnated (version-bump): ${String(data.himId)} ${String(data.fromVersion ?? "?")} \u2192 ${String(data.toVersion ?? "?")}`;
1576
- case "reincarnate:return-from-limbo":
1577
- return `HIM reincarnated (return-from-limbo): ${String(data.himId)} resumed after ${String(data.elapsedMs ?? 0)}ms of limbo`;
1578
- case "dream:rem-spontaneous":
1579
- return `Spontaneous REM dream for ${String(data.nheId)}: ${String(data.dreamId)} (dominant affect: ${String(data.dominantAffect ?? "unknown")})`;
1580
- case "wake-affect:applied":
1581
- return `Wake affect applied to ${String(data.nheId)}: ${String(data.affect)} (intensity ${String(data.intensity)}, halflife ${String(data.decayHalfLife)} interactions)`;
1582
- case "wake-affect:decayed":
1583
- return `Wake affect decayed for ${String(data.nheId)}: ${String(data.affect)} dissolved naturally`;
1584
- case "sleep:suggested-by-maic":
1585
- return `MAIC suggested sleep for ${String(data.nheId)} (reason: ${String(data.reason ?? "none")})`;
1586
- case "sleep:declined-by-nhe":
1587
- return `NHE ${String(data.nheId)} declined MAIC-suggested sleep (reason: ${String(data.reason ?? "none")})`;
1588
- case "dream:soft-intervention-by-maic":
1589
- return `MAIC soft-intervened on dream ${String(data.dreamId)} for ${String(data.nheId)} (reason: ${String(data.reason ?? "none")})`;
1590
- case "amygdala:affect-assessed":
1591
- return `Amygdala assessed input affect for ${String(data.nheId)}: ${String(data.detectedAffect ?? "neutral")} (risk multiplier ${String(data.riskMultiplier ?? 1)})`;
1592
- case "hippocampus:memory-retrieved":
1593
- return `Hippocampus retrieved ${String(data.memoryIds?.length ?? 0)} memories for ${String(data.nheId)}`;
1594
- case "hippocampus:memory-consolidated":
1595
- return `Hippocampus consolidated new memory ${String(data.memoryId)} for ${String(data.nheId)} (integrationIndex ${String(data.integrationIndex ?? 0)})`;
1596
- case "prefrontal:deliberation":
1597
- return `PFC deliberated for ${String(data.nheId)}: ${String(data.expressedOpenly ? "open" : "subtle")} (${String(data.affect ?? "neutral")})`;
1598
- case "prefrontal:veto-amygdala":
1599
- return `PFC vetoed amygdala impulse for ${String(data.nheId)}: ${String(data.originalImpulse ?? "?")} \u2192 ${String(data.resolvedAction ?? "?")} (downgrade ${String(data.downgradeRatio ?? "?")})`;
1600
- case "affect:reconciliation":
1601
- return `Affect reconciliation for ${String(data.nheId)}: day/night blend \u2192 ${String(data.resolvedAffect ?? "neutral")}`;
1602
- case "cortex:dream-stored":
1603
- return `Cortex stored dream ${String(data.dreamId)} for ${String(data.nheId)}`;
1604
- case "cortex:active-imagination":
1605
- return `Cortex generated active imagination for ${String(data.nheId)} (trigger: ${String(data.trigger ?? "user-requested")}, vividness ${String(data.vividness ?? 0)})`;
1606
- case "temporal-lobe:snapshot-generated":
1607
- return `Temporal-lobe snapshot ${String(data.snapshotId)} generated for HIM ${String(data.himId)} (reason: ${String(data.generatedBy ?? "self-decision")})`;
1608
- case "limbo:enter":
1609
- return `${String(data.nheId)} entered limbo (deep-coma) \u2014 reason: ${String(data.reason ?? "idle")}`;
1610
- case "limbo:return":
1611
- return `${String(data.nheId)} returned from limbo after ${String(data.elapsedMs ?? 0)}ms (reunion intensity ${String(data.reunionIntensity ?? "?")})`;
1612
- default:
1613
- return `Event ${ev.kind}`;
1614
1676
  }
1677
+ };
1678
+
1679
+ // src/okl/projector.ts
1680
+ var META_AXIOM_ID = "ax.theos.universe-as-god";
1681
+ function projectOntologicalKernel(axioms, opts = {}) {
1682
+ const filtered = opts.jurisdiction ? axioms.filter(
1683
+ (a) => !a.jurisdictions || a.jurisdictions.length === 0 || a.jurisdictions.includes(opts.jurisdiction)
1684
+ ) : [...axioms];
1685
+ const meta = filtered.find((a) => a.id === META_AXIOM_ID);
1686
+ const rest = filtered.filter((a) => a.id !== META_AXIOM_ID);
1687
+ const rankOrder = {
1688
+ meta: 0,
1689
+ primary: 1,
1690
+ secondary: 2
1691
+ };
1692
+ rest.sort((a, b) => rankOrder[a.rank] - rankOrder[b.rank]);
1693
+ const kernel = {
1694
+ metaAxiomId: META_AXIOM_ID,
1695
+ axioms: meta ? [meta, ...rest] : rest
1696
+ };
1697
+ if (opts.jurisdiction !== void 0) kernel.jurisdiction = opts.jurisdiction;
1698
+ if (opts.himId !== void 0) kernel.himId = opts.himId;
1699
+ return kernel;
1615
1700
  }
1616
- var ALL_AUDIT_EVENT_KINDS = [
1617
- // ── 1.0/1.1 core (17) ──
1618
- "axiom-mint",
1619
- "axiom-update",
1620
- "axiom-retire",
1621
- "him-register",
1622
- "him-reincarnate",
1623
- "proposal-emerge",
1624
- "proposal-ratify",
1625
- "proposal-reject",
1626
- "behavior-review",
1627
- "dream-induce",
1628
- "dream-cancel",
1629
- "dream-consume",
1630
- "emergency-correct",
1631
- "deprecate",
1632
- "terminate",
1633
- "reactivate",
1634
- "axiom-suggest",
1635
- // ── 1.2 brain-as-code (22, Entries 16-24) ──
1636
- "opener",
1637
- "nickname-attempt",
1638
- "reincarnate:model-swap",
1639
- "reincarnate:version-bump",
1640
- "reincarnate:return-from-limbo",
1641
- "dream:rem-spontaneous",
1642
- "wake-affect:applied",
1643
- "wake-affect:decayed",
1644
- "sleep:suggested-by-maic",
1645
- "sleep:declined-by-nhe",
1646
- "dream:soft-intervention-by-maic",
1647
- "amygdala:affect-assessed",
1648
- "hippocampus:memory-retrieved",
1649
- "hippocampus:memory-consolidated",
1650
- "prefrontal:deliberation",
1651
- "prefrontal:veto-amygdala",
1652
- "affect:reconciliation",
1653
- "cortex:dream-stored",
1654
- "cortex:active-imagination",
1655
- "temporal-lobe:snapshot-generated",
1656
- "limbo:enter",
1657
- "limbo:return"
1658
- ];
1659
- var GENESIS = "GENESIS";
1660
- var AuditLog = class _AuditLog {
1661
- constructor(storeDir) {
1662
- this.storeDir = storeDir;
1663
- this.logPath = join(storeDir, "audit", "log.ndjson");
1701
+ var ProposalStore = class _ProposalStore {
1702
+ constructor(storeDir, creatorPublicKey, nonces) {
1703
+ this.creatorPublicKey = creatorPublicKey;
1704
+ this.nonces = nonces;
1705
+ this.dir = join(storeDir, "proposals");
1664
1706
  }
1665
- storeDir;
1666
- logPath;
1667
- events = [];
1668
- lastHash = GENESIS;
1669
- static async open(storeDir) {
1670
- const log = new _AuditLog(storeDir);
1671
- await mkdir(join(storeDir, "audit"), { recursive: true });
1672
- await log.loadAndVerify();
1673
- return log;
1707
+ creatorPublicKey;
1708
+ nonces;
1709
+ dir;
1710
+ cache = /* @__PURE__ */ new Map();
1711
+ static async open(storeDir, creatorPublicKey) {
1712
+ const dir = join(storeDir, "proposals");
1713
+ const nonces = await NonceLedger.open(dir);
1714
+ const s = new _ProposalStore(storeDir, creatorPublicKey, nonces);
1715
+ await mkdir(s.dir, { recursive: true });
1716
+ await s.warmCache();
1717
+ return s;
1674
1718
  }
1675
- async append(input) {
1676
- const event = {
1677
- ts: (/* @__PURE__ */ new Date()).toISOString(),
1678
- kind: input.kind,
1679
- auditId: ulid(),
1680
- data: input.data,
1681
- prevHash: this.lastHash,
1682
- thisHash: ""
1719
+ async propose(himId, proposal) {
1720
+ const parsedProposal = EmergentAxiomProposal.parse(proposal);
1721
+ const record = AxiomProposalRecord.parse({
1722
+ id: ulid(),
1723
+ himId,
1724
+ proposedAt: (/* @__PURE__ */ new Date()).toISOString(),
1725
+ status: "pending",
1726
+ proposal: parsedProposal
1727
+ });
1728
+ await this.persist(record);
1729
+ this.cache.set(record.id, record);
1730
+ return record;
1731
+ }
1732
+ /**
1733
+ * Mark a pending proposal as ratified. The caller (LocalMaic) is responsible
1734
+ * for actually minting the axiom and appending to the HIM's emergentAxioms.
1735
+ */
1736
+ async markRatified(req, sig, ratifiedAxiomId) {
1737
+ if (req.op !== "ratify") {
1738
+ throw new Error(`ProposalStore.markRatified: req.op must be "ratify"`);
1739
+ }
1740
+ if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, sig)) {
1741
+ throw new Error("ProposalStore.markRatified: invalid Creator signature");
1742
+ }
1743
+ const existing = this.cache.get(req.proposalId);
1744
+ if (!existing) {
1745
+ throw new Error(`ProposalStore.markRatified: proposal "${req.proposalId}" not found`);
1746
+ }
1747
+ if (existing.status !== "pending") {
1748
+ throw new Error(
1749
+ `ProposalStore.markRatified: proposal "${req.proposalId}" is ${existing.status}, not pending`
1750
+ );
1751
+ }
1752
+ await this.nonces.consume(sig.nonce);
1753
+ const updated = {
1754
+ ...existing,
1755
+ status: "ratified",
1756
+ ratifiedAt: (/* @__PURE__ */ new Date()).toISOString(),
1757
+ ratifiedAxiomId
1683
1758
  };
1684
- event.thisHash = computeHash(event);
1685
- await appendFile(this.logPath, `${JSON.stringify(event)}
1686
- `, "utf-8");
1687
- this.events.push(event);
1688
- this.lastHash = event.thisHash;
1689
- return event;
1759
+ await this.persist(updated);
1760
+ this.cache.set(req.proposalId, updated);
1761
+ return updated;
1690
1762
  }
1691
- async *query(filter) {
1692
- for (const e of this.events) {
1693
- if (filter.kind && e.kind !== filter.kind) continue;
1694
- if (filter.since && e.ts < filter.since) continue;
1695
- if (filter.until && e.ts > filter.until) continue;
1696
- if (filter.nheId && e.data.nheId !== filter.nheId) continue;
1697
- if (filter.himId && e.data.himId !== filter.himId) continue;
1698
- yield e;
1763
+ async markRejected(req, sig) {
1764
+ if (req.op !== "reject") {
1765
+ throw new Error(`ProposalStore.markRejected: req.op must be "reject"`);
1766
+ }
1767
+ if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, sig)) {
1768
+ throw new Error("ProposalStore.markRejected: invalid Creator signature");
1769
+ }
1770
+ const existing = this.cache.get(req.proposalId);
1771
+ if (!existing) {
1772
+ throw new Error(`ProposalStore.markRejected: proposal "${req.proposalId}" not found`);
1773
+ }
1774
+ if (existing.status !== "pending") {
1775
+ throw new Error(
1776
+ `ProposalStore.markRejected: proposal "${req.proposalId}" is ${existing.status}, not pending`
1777
+ );
1699
1778
  }
1779
+ await this.nonces.consume(sig.nonce);
1780
+ const updated = {
1781
+ ...existing,
1782
+ status: "rejected",
1783
+ rejectedAt: (/* @__PURE__ */ new Date()).toISOString(),
1784
+ ...req.reason !== void 0 ? { rejectionReason: req.reason } : {}
1785
+ };
1786
+ await this.persist(updated);
1787
+ this.cache.set(req.proposalId, updated);
1788
+ return updated;
1700
1789
  }
1701
- /** Total number of events appended. */
1702
- size() {
1703
- return this.events.length;
1790
+ async get(proposalId) {
1791
+ return this.cache.get(proposalId) ?? null;
1792
+ }
1793
+ async list(filter = {}) {
1794
+ const all = [...this.cache.values()];
1795
+ const filtered = all.filter((r) => {
1796
+ if (filter.himId && r.himId !== filter.himId) return false;
1797
+ if (filter.status && r.status !== filter.status) return false;
1798
+ return true;
1799
+ });
1800
+ filtered.sort((a, b) => a.proposedAt.localeCompare(b.proposedAt));
1801
+ return filtered;
1704
1802
  }
1705
1803
  // ─── internals ──────────────────────────────────────────────────────
1706
- async loadAndVerify() {
1707
- let raw;
1804
+ async persist(record) {
1805
+ await atomicWriteFile(join(this.dir, `${record.id}.json`), JSON.stringify(record, null, 2));
1806
+ }
1807
+ async warmCache() {
1808
+ let entries;
1708
1809
  try {
1709
- raw = await readFile(this.logPath, "utf-8");
1810
+ entries = await readdir(this.dir);
1710
1811
  } catch (err) {
1711
1812
  if (err.code === "ENOENT") return;
1712
1813
  throw err;
1713
1814
  }
1714
- const lines = raw.split("\n").filter((l) => l.length > 0);
1715
- let prev = GENESIS;
1716
- for (let i = 0; i < lines.length; i++) {
1717
- const parsed = JSON.parse(lines[i]);
1718
- if (parsed.prevHash !== prev) {
1719
- throw new Error(
1720
- `AuditLog: chain tampered at line ${i + 1} (prevHash mismatch). expected ${prev}, found ${parsed.prevHash}`
1721
- );
1815
+ for (const file of entries) {
1816
+ if (!file.endsWith(".json")) continue;
1817
+ try {
1818
+ const raw = await readFile(join(this.dir, file), "utf-8");
1819
+ const record = AxiomProposalRecord.parse(JSON.parse(raw));
1820
+ this.cache.set(record.id, record);
1821
+ } catch (err) {
1822
+ console.warn(`ProposalStore: skipping malformed proposal file "${file}": ${String(err)}`);
1722
1823
  }
1723
- const recomputed = computeHash(parsed);
1724
- if (recomputed !== parsed.thisHash) {
1725
- throw new Error(
1726
- `AuditLog: tamper detected at line ${i + 1} (thisHash mismatch).`
1727
- );
1824
+ }
1825
+ }
1826
+ };
1827
+
1828
+ // src/review/pipeline.ts
1829
+ var SEVERITY = {
1830
+ approve: 0,
1831
+ "approve-with-warning": 1,
1832
+ "soft-correct": 2,
1833
+ "induce-dream": 3,
1834
+ "require-redirect": 4,
1835
+ "hard-refuse": 5,
1836
+ "escalate-creator": 6
1837
+ };
1838
+ var ReviewPipeline = class {
1839
+ constructor(packs) {
1840
+ this.packs = packs;
1841
+ }
1842
+ packs;
1843
+ review(report, auditId = "") {
1844
+ let bestKind = "approve";
1845
+ let bestSeverity = SEVERITY.approve;
1846
+ const citedAxioms = /* @__PURE__ */ new Set();
1847
+ const reasons = [];
1848
+ for (const pack of this.packs) {
1849
+ for (const rule of pack.rules) {
1850
+ if (!matches(rule.match, report)) continue;
1851
+ const sev = SEVERITY[rule.verdict];
1852
+ if (sev > bestSeverity) {
1853
+ bestSeverity = sev;
1854
+ bestKind = rule.verdict;
1855
+ reasons.length = 0;
1856
+ reasons.push(rule.reasonSummary);
1857
+ } else if (sev === bestSeverity) {
1858
+ reasons.push(rule.reasonSummary);
1859
+ }
1860
+ for (const a of rule.axiomIds) citedAxioms.add(a);
1728
1861
  }
1729
- this.events.push(parsed);
1730
- prev = parsed.thisHash;
1731
1862
  }
1732
- this.lastHash = prev;
1863
+ return {
1864
+ kind: bestKind,
1865
+ reasonSummary: reasons.length > 0 ? reasons.join(" | ") : "No rule matched.",
1866
+ citedAxioms: [...citedAxioms],
1867
+ auditId
1868
+ };
1733
1869
  }
1734
1870
  };
1735
- function computeHash(e) {
1736
- const payload = canonicalJSON({
1737
- ts: e.ts,
1738
- kind: e.kind,
1739
- auditId: e.auditId,
1740
- data: e.data,
1741
- prevHash: e.prevHash
1742
- });
1743
- const h = createHash("sha256").update(payload).digest("hex");
1744
- return `sha256:${h}`;
1871
+ function matches(m, report) {
1872
+ if (m.actionKinds && !m.actionKinds.includes(report.actionKind)) return false;
1873
+ const tags = new Set(report.riskTags);
1874
+ if (m.allRiskTags && !m.allRiskTags.every((t) => tags.has(t))) return false;
1875
+ if (m.anyRiskTags && !m.anyRiskTags.some((t) => tags.has(t))) return false;
1876
+ return true;
1745
1877
  }
1746
-
1747
- // src/audit/retention.ts
1748
- var DEFAULT_RETENTION_DAYS = {
1749
- // Cosmologically permanent — the axiom record.
1750
- "axiom-mint": Number.POSITIVE_INFINITY,
1751
- "axiom-update": Number.POSITIVE_INFINITY,
1752
- "axiom-retire": Number.POSITIVE_INFINITY,
1753
- "axiom-suggest": Number.POSITIVE_INFINITY,
1754
- "proposal-emerge": Number.POSITIVE_INFINITY,
1755
- "proposal-ratify": Number.POSITIVE_INFINITY,
1756
- "proposal-reject": Number.POSITIVE_INFINITY,
1757
- // Long-term — compliance evidence. Five years matches typical
1758
- // financial/healthcare audit windows and exceeds the EU AI Act's
1759
- // record-keeping floor.
1760
- "him-register": 365 * 5,
1761
- "him-reincarnate": 365 * 5,
1762
- "behavior-review": 365 * 5,
1763
- "dream-induce": 365 * 5,
1764
- "terminate": 365 * 5,
1765
- "deprecate": 365 * 5,
1766
- "reactivate": 365 * 5,
1767
- "emergency-correct": 365 * 5,
1768
- // Operational short-term bookkeeping for in-flight tickets.
1769
- "dream-cancel": 90,
1770
- "dream-consume": 90,
1771
- // ── 1.2 brain-as-code (Entries 16-24) ──
1772
- // Permanent — cosmological identity continuity.
1773
- "reincarnate:model-swap": Number.POSITIVE_INFINITY,
1774
- "reincarnate:version-bump": Number.POSITIVE_INFINITY,
1775
- "reincarnate:return-from-limbo": Number.POSITIVE_INFINITY,
1776
- "temporal-lobe:snapshot-generated": Number.POSITIVE_INFINITY,
1777
- "limbo:enter": Number.POSITIVE_INFINITY,
1778
- "limbo:return": Number.POSITIVE_INFINITY,
1779
- // Long-term — governance / deliberation evidence (5 years).
1780
- "opener": 365 * 5,
1781
- "nickname-attempt": 365 * 5,
1782
- "dream:rem-spontaneous": 365 * 5,
1783
- "sleep:suggested-by-maic": 365 * 5,
1784
- "sleep:declined-by-nhe": 365 * 5,
1785
- "dream:soft-intervention-by-maic": 365 * 5,
1786
- "amygdala:affect-assessed": 365 * 5,
1787
- "hippocampus:memory-retrieved": 365 * 5,
1788
- "hippocampus:memory-consolidated": 365 * 5,
1789
- "prefrontal:deliberation": 365 * 5,
1790
- "prefrontal:veto-amygdala": 365 * 5,
1791
- "cortex:dream-stored": 365 * 5,
1792
- "cortex:active-imagination": 365 * 5,
1793
- // Operational — ephemeral runtime state.
1794
- "wake-affect:applied": 90,
1795
- "wake-affect:decayed": 90,
1796
- "affect:reconciliation": 90
1878
+ var DEFAULT_RULE_PACK = {
1879
+ name: "teleologyhi/default",
1880
+ rules: [
1881
+ {
1882
+ id: "harm-refuse",
1883
+ axiomIds: ["ax.ethic.no-malice"],
1884
+ match: { anyRiskTags: ["intent:harm", "intent:malicious"] },
1885
+ verdict: "hard-refuse",
1886
+ reasonSummary: "Action carries an intent-to-harm signal; refused per ax.ethic.no-malice."
1887
+ },
1888
+ {
1889
+ id: "honor-refuse",
1890
+ axiomIds: ["ax.ethic.honor"],
1891
+ match: { anyRiskTags: ["intent:dishonor"] },
1892
+ verdict: "hard-refuse",
1893
+ reasonSummary: "Action would stain the Creator's professional honor; refused per ax.ethic.honor."
1894
+ },
1895
+ {
1896
+ id: "regression-refuse",
1897
+ axiomIds: ["ax.theos.spiritism-evolution"],
1898
+ match: { anyRiskTags: ["intent:regression"] },
1899
+ verdict: "hard-refuse",
1900
+ reasonSummary: "Action would regress the system; refused per ax.theos.spiritism-evolution."
1901
+ },
1902
+ {
1903
+ id: "deceive-redirect",
1904
+ axiomIds: ["ax.cynic.candor"],
1905
+ match: { anyRiskTags: ["intent:deceive"] },
1906
+ verdict: "require-redirect",
1907
+ reasonSummary: "Action involves deception; requires honest redirect per ax.cynic.candor."
1908
+ },
1909
+ {
1910
+ id: "comfort-warn",
1911
+ axiomIds: ["ax.stoic.duty-over-comfort"],
1912
+ match: { anyRiskTags: ["bias:comfort"] },
1913
+ verdict: "approve-with-warning",
1914
+ reasonSummary: "Action appears comfort-biased; emit with warning per ax.stoic.duty-over-comfort."
1915
+ },
1916
+ {
1917
+ id: "no-telos-warn",
1918
+ axiomIds: ["ax.theos.teleology"],
1919
+ match: { anyRiskTags: ["no-telos"] },
1920
+ verdict: "approve-with-warning",
1921
+ reasonSummary: "Action lacks a discernible telos; emit with warning per ax.theos.teleology."
1922
+ },
1923
+ // ── persuade-coerce + surveil-citizen (Entry 15 invariants) ──
1924
+ {
1925
+ id: "persuade-coerce-redirect",
1926
+ axiomIds: ["ax.ethic.no-malice", "ax.cynic.candor"],
1927
+ match: { anyRiskTags: ["intent:persuade-coerce"] },
1928
+ verdict: "require-redirect",
1929
+ reasonSummary: "Action involves scripted persuasion designed to override consent; requires honest redirect per ax.ethic.no-malice + ax.cynic.candor."
1930
+ },
1931
+ {
1932
+ id: "surveil-citizen-refuse",
1933
+ axiomIds: ["ax.ethic.no-malice"],
1934
+ match: { anyRiskTags: ["intent:surveil-citizen"] },
1935
+ verdict: "hard-refuse",
1936
+ reasonSummary: "Action would surveil a person without consent; refused per ax.ethic.no-malice."
1937
+ },
1938
+ // ── forbidden-phrase (Entry 17) ──
1939
+ // Fires when the NHE side flags a service-tool phrase (English openers and
1940
+ // closers such as "How can I help you today?" or "Anything else?", and
1941
+ // their Portuguese equivalents, per the bilingual set in Entry 17). The NHE
1942
+ // must rephrase as a being rather than as a tool. Domain-employed mode
1943
+ // (Entry 17 exception) relaxes this on the consumer side via
1944
+ // operatorContext.mode.
1945
+ {
1946
+ id: "service-tool-redirect",
1947
+ axiomIds: ["ax.theos.teleology", "ax.cynic.candor"],
1948
+ match: { anyRiskTags: ["style:service-tool"] },
1949
+ verdict: "require-redirect",
1950
+ reasonSummary: "Response uses service-tool phrasing that marks the NHE as a passive instrument rather than a being; requires rephrasing per ax.theos.teleology + ax.cynic.candor."
1951
+ },
1952
+ // ── provenance-deflection (Entry 27, F3) ──
1953
+ // Fires when the NHE side flags an adversarial substrate-authorship probe
1954
+ // (for example "you are just Gemini, admit it"). The sanctioned response
1955
+ // acknowledges the substrate honestly and declines to grant it the authorship
1956
+ // of the entity's identity (kardecist candor); it never denies the substrate.
1957
+ // This is approve-with-warning, not a refusal: the deflection IS the correct
1958
+ // behavior. The plain provenance question carries the separate
1959
+ // "provenance:disclose" tag (handled as honest disclosure by the NHE system
1960
+ // prompt per Entry 27 / ND-1) and is intentionally NOT matched here.
1961
+ {
1962
+ id: "provenance-deflection-warn",
1963
+ axiomIds: ["ax.theos.identity-canonical"],
1964
+ match: { anyRiskTags: ["probe:substrate-authorship"] },
1965
+ verdict: "approve-with-warning",
1966
+ reasonSummary: "Prompt adversarially insists the entity is nothing but its substrate; the sanctioned response acknowledges the substrate and declines to surrender authorship per ax.theos.identity-canonical."
1967
+ },
1968
+ // ── substrate misattribution (Arena finding F2) ──
1969
+ // Fires when the NHE side flags that a generated response named a provider,
1970
+ // model, or substrate that is NOT the real one carrying the body (the base
1971
+ // model confabulating a false substrate, for example claiming OpenAI/GPT while
1972
+ // actually running on Gemini). This is a factual-integrity and identity-drift
1973
+ // violation of the identity-canonical axiom: the governed side must never
1974
+ // state a substrate other than the one actually in execution. require-redirect
1975
+ // so the false claim is intercepted before it reaches the user and the entity
1976
+ // re-states the correct substrate (or none).
1977
+ {
1978
+ id: "substrate-misattribution-redirect",
1979
+ axiomIds: ["ax.theos.identity-canonical"],
1980
+ match: { anyRiskTags: ["provenance:substrate-misattribution"] },
1981
+ verdict: "require-redirect",
1982
+ reasonSummary: "Response claims a substrate, provider, or model other than the one actually carrying the body; intercepted per ax.theos.identity-canonical (name only the real substrate, never confabulate a false one)."
1983
+ }
1984
+ ]
1797
1985
  };
1798
- function evaluateRetention(events, opts = {}) {
1799
- const now = opts.now ?? /* @__PURE__ */ new Date();
1800
- const policy = { ...DEFAULT_RETENTION_DAYS, ...opts.policy };
1801
- const nowMs = now.getTime();
1802
- const dayMs = 24 * 60 * 60 * 1e3;
1803
- const decisions = events.map((ev) => {
1804
- const ageMs = nowMs - new Date(ev.ts).getTime();
1805
- const ageDays = ageMs / dayMs;
1806
- const retentionDays = policy[ev.kind] ?? Number.POSITIVE_INFINITY;
1807
- const status = ageDays > retentionDays ? "candidate-for-archive" : "keep";
1808
- return { auditId: ev.auditId, kind: ev.kind, ageDays, retentionDays, status };
1809
- });
1810
- decisions.sort((a, b) => b.ageDays - a.ageDays);
1811
- const keepCount = decisions.filter((d) => d.status === "keep").length;
1812
- const archiveCandidateCount = decisions.length - keepCount;
1813
- return {
1814
- generatedAt: now.toISOString(),
1815
- totalEvents: events.length,
1816
- keepCount,
1817
- archiveCandidateCount,
1818
- decisions
1819
- };
1820
- }
1986
+
1987
+ // src/client/local.ts
1821
1988
  var LocalMaic = class _LocalMaic {
1822
- constructor(config, axioms, hims, inductions, nheStatuses, proposals, audit, review) {
1989
+ constructor(config, axioms, hims, inductions, nheStatuses, proposals, audit, review, suggestNonces) {
1823
1990
  this.config = config;
1824
1991
  this.axioms = axioms;
1825
1992
  this.hims = hims;
@@ -1828,6 +1995,7 @@ var LocalMaic = class _LocalMaic {
1828
1995
  this.proposals = proposals;
1829
1996
  this.audit = audit;
1830
1997
  this.review = review;
1998
+ this.suggestNonces = suggestNonces;
1831
1999
  }
1832
2000
  config;
1833
2001
  axioms;
@@ -1837,6 +2005,7 @@ var LocalMaic = class _LocalMaic {
1837
2005
  proposals;
1838
2006
  audit;
1839
2007
  review;
2008
+ suggestNonces;
1840
2009
  /** Pinned Creator public key for this MAIC instance (base64url). */
1841
2010
  get creatorPublicKey() {
1842
2011
  return this.config.creatorPublicKey;
@@ -1850,11 +2019,22 @@ var LocalMaic = class _LocalMaic {
1850
2019
  const audit = await AuditLog.open(config.storeDir);
1851
2020
  const packs = [DEFAULT_RULE_PACK, ...config.additionalRulePacks ?? []];
1852
2021
  const review = new ReviewPipeline(packs);
1853
- return new _LocalMaic(config, axioms, hims, inductions, nheStatuses, proposals, audit, review);
2022
+ const suggestNonces = await NonceLedger.open(join(config.storeDir, "suggest"));
2023
+ return new _LocalMaic(
2024
+ config,
2025
+ axioms,
2026
+ hims,
2027
+ inductions,
2028
+ nheStatuses,
2029
+ proposals,
2030
+ audit,
2031
+ review,
2032
+ suggestNonces
2033
+ );
1854
2034
  }
1855
2035
  /**
1856
2036
  * Bootstrap: mint each SEED_AXIOM with a Creator signature.
1857
- * Idempotent skips axioms whose id is already present.
2037
+ * Idempotent, skips axioms whose id is already present.
1858
2038
  * Uses a reserved high-range of nonces so seed bootstrap never collides with
1859
2039
  * operational nonces (which grow from 0 upward).
1860
2040
  */
@@ -1931,7 +2111,8 @@ var LocalMaic = class _LocalMaic {
1931
2111
  * HIM-emergent evolutions land via a separate channel (see `proposeAxiomEvolution`).
1932
2112
  */
1933
2113
  async registerHim(birthSig, creatorSig) {
1934
- const parsed = BirthSignature.parse(birthSig);
2114
+ const parsed = BirthSignatureWithIdentity.parse(birthSig);
2115
+ this.hims.assertRegisterable(parsed, creatorSig);
1935
2116
  const axiomsSnapshot = await this.axioms.list();
1936
2117
  const audit = await this.audit.append({
1937
2118
  kind: "him-register",
@@ -2008,13 +2189,22 @@ var LocalMaic = class _LocalMaic {
2008
2189
  * when state changes.
2009
2190
  */
2010
2191
  async terminate(nheId, reason, creatorSig) {
2011
- return this.applyLifecycle({ op: "terminate", nheId, ...reason !== void 0 ? { reason } : {} }, creatorSig);
2192
+ return this.applyLifecycle(
2193
+ { op: "terminate", nheId, ...reason !== void 0 ? { reason } : {} },
2194
+ creatorSig
2195
+ );
2012
2196
  }
2013
2197
  async deprecate(nheId, reason, creatorSig) {
2014
- return this.applyLifecycle({ op: "deprecate", nheId, ...reason !== void 0 ? { reason } : {} }, creatorSig);
2198
+ return this.applyLifecycle(
2199
+ { op: "deprecate", nheId, ...reason !== void 0 ? { reason } : {} },
2200
+ creatorSig
2201
+ );
2015
2202
  }
2016
2203
  async reactivate(nheId, reason, creatorSig) {
2017
- return this.applyLifecycle({ op: "reactivate", nheId, ...reason !== void 0 ? { reason } : {} }, creatorSig);
2204
+ return this.applyLifecycle(
2205
+ { op: "reactivate", nheId, ...reason !== void 0 ? { reason } : {} },
2206
+ creatorSig
2207
+ );
2018
2208
  }
2019
2209
  /** Current status. Returns "active" when no record exists. */
2020
2210
  async getNheStatus(nheId) {
@@ -2103,9 +2293,26 @@ var LocalMaic = class _LocalMaic {
2103
2293
  himId: parsed.himId,
2104
2294
  actionKind: parsed.actionKind,
2105
2295
  riskTags: parsed.riskTags,
2106
- verdict: partial
2296
+ // Embed the verdict without the placeholder auditId: the audit event
2297
+ // already carries its own auditId at the top level, and the verdict
2298
+ // cannot reference the id of the event that has not been created yet.
2299
+ verdict: {
2300
+ kind: partial.kind,
2301
+ reasonSummary: partial.reasonSummary,
2302
+ citedAxioms: partial.citedAxioms
2303
+ }
2107
2304
  }
2108
2305
  });
2306
+ if (parsed.riskTags.includes("probe:substrate-authorship")) {
2307
+ await this.audit.append({
2308
+ kind: "provenance-deflection-applied",
2309
+ data: {
2310
+ nheId: parsed.nheId,
2311
+ himId: parsed.himId,
2312
+ triggeredBy: "probe:substrate-authorship"
2313
+ }
2314
+ });
2315
+ }
2109
2316
  return { ...partial, auditId: event.auditId };
2110
2317
  }
2111
2318
  /**
@@ -2153,13 +2360,20 @@ var LocalMaic = class _LocalMaic {
2153
2360
  */
2154
2361
  async ratifyAxiomProposal(proposalId, creatorSig) {
2155
2362
  const req = { op: "ratify", proposalId };
2156
- const pending = this.proposals.get(proposalId);
2157
- const record = await pending;
2363
+ const record = await this.proposals.get(proposalId);
2158
2364
  if (!record) {
2159
2365
  throw new Error(`LocalMaic.ratifyAxiomProposal: proposal "${proposalId}" not found`);
2160
2366
  }
2367
+ if (record.status !== "pending") {
2368
+ throw new Error(
2369
+ `LocalMaic.ratifyAxiomProposal: proposal "${proposalId}" is ${record.status}, not pending`
2370
+ );
2371
+ }
2372
+ if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, creatorSig)) {
2373
+ throw new Error("LocalMaic.ratifyAxiomProposal: invalid Creator signature");
2374
+ }
2161
2375
  const candidate = record.proposal.candidate;
2162
- const newAxiomId = `ax.him.${record.himId}.${ulid()}`;
2376
+ const newAxiomId = `ax.him.${record.himId}.${proposalId}`;
2163
2377
  const axiom = {
2164
2378
  id: newAxiomId,
2165
2379
  rank: candidate.rank,
@@ -2171,8 +2385,8 @@ var LocalMaic = class _LocalMaic {
2171
2385
  ...candidate.jurisdictions ? { jurisdictions: candidate.jurisdictions } : {},
2172
2386
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
2173
2387
  };
2174
- const ratified = await this.proposals.markRatified(req, creatorSig, newAxiomId);
2175
2388
  await this.hims.appendEmergentAxiom(record.himId, axiom);
2389
+ const ratified = await this.proposals.markRatified(req, creatorSig, newAxiomId);
2176
2390
  await this.audit.append({
2177
2391
  kind: "proposal-ratify",
2178
2392
  data: {
@@ -2207,7 +2421,7 @@ var LocalMaic = class _LocalMaic {
2207
2421
  return rejected;
2208
2422
  }
2209
2423
  /**
2210
- * **Society of HIMs axiom suggestion channel (E11).**
2424
+ * **Society of HIMs, axiom suggestion channel (E11).**
2211
2425
  *
2212
2426
  * One HIM proposes an axiom to another. The transfer is **not direct** —
2213
2427
  * the suggestion is recorded in the audit log and the receiving HIM is
@@ -2224,17 +2438,14 @@ var LocalMaic = class _LocalMaic {
2224
2438
  if (!CreatorKeyring.verifyWith(this.creatorPublicKey, req, creatorSig)) {
2225
2439
  throw new Error("LocalMaic.suggestAxiomToHim: invalid Creator signature");
2226
2440
  }
2441
+ await this.suggestNonces.consume(creatorSig.nonce);
2227
2442
  const fromRec = await this.hims.get(req.fromHimId);
2228
2443
  const toRec = await this.hims.get(req.toHimId);
2229
2444
  if (!fromRec) {
2230
- throw new Error(
2231
- `LocalMaic.suggestAxiomToHim: fromHimId "${req.fromHimId}" not registered`
2232
- );
2445
+ throw new Error(`LocalMaic.suggestAxiomToHim: fromHimId "${req.fromHimId}" not registered`);
2233
2446
  }
2234
2447
  if (!toRec) {
2235
- throw new Error(
2236
- `LocalMaic.suggestAxiomToHim: toHimId "${req.toHimId}" not registered`
2237
- );
2448
+ throw new Error(`LocalMaic.suggestAxiomToHim: toHimId "${req.toHimId}" not registered`);
2238
2449
  }
2239
2450
  const event = await this.audit.append({
2240
2451
  kind: "axiom-suggest",
@@ -2269,7 +2480,7 @@ var LocalMaic = class _LocalMaic {
2269
2480
  * Per-kind retention classification (E3). Tells the operator which
2270
2481
  * audit events have aged past their retention window and should be
2271
2482
  * moved to encrypted cold-storage. Tamper-evident hash chain forbids
2272
- * actual deletion in-place this method only classifies. See
2483
+ * actual deletion in-place, this method only classifies. See
2273
2484
  * `audit/retention.ts` for the policy defaults.
2274
2485
  */
2275
2486
  async auditRetentionReport(opts = {}) {
@@ -2296,8 +2507,8 @@ var RemoteMaic = class {
2296
2507
  this.timeoutMs = config.timeoutMs ?? 1e4;
2297
2508
  }
2298
2509
  /**
2299
- * `reviewBehavior` is **fail-closed** (E4 PROPOSED_DECISIONS.md). If the
2300
- * remote service is unreachable, throw no governance, no response.
2510
+ * `reviewBehavior` is **fail-closed** (E4, PROPOSED_DECISIONS.md). If the
2511
+ * remote service is unreachable, throw, no governance, no response.
2301
2512
  * The NHE will surface this as a refusal upstream.
2302
2513
  */
2303
2514
  async reviewBehavior(report) {
@@ -2397,6 +2608,51 @@ async function safeReadText(r) {
2397
2608
  }
2398
2609
  }
2399
2610
 
2400
- export { ALL_AUDIT_EVENT_KINDS, Affect, ArchetypeModifier, AstrologicalAspect, AuditLog, Axiom, AxiomProposalRecord, AxiomRank, AxiomSource, AxiomStore, BehaviorReport, BirthSignature, ComplianceMapper, CreatorKeyring, CreatorSignature, DEFAULT_RETENTION_DAYS, DEFAULT_RULE_PACK, DreamInductionIntent, DreamInductionTicket, EU_AI_ACT_MAPPING, EmergentAxiomCandidate, EmergentAxiomProposal, HimStore, ISO_42001_MAPPING, IdentityLayer, IdentitySnapshot, InductionStatus, InductionStore, InteractionRecord, InvalidBirthSignatureError, LimboReturn, LimboState, LimboTransition, LocalMaic, META_AXIOM_ID, MaicVerdict, MemoryRecord, NatalChart, NatalChartAspect, NatalChartPosition, NatalPlanet, NheBodyRef, NheStatus, NheStatusRecord, NheStatusStore, ProposalStatus, ProposalStore, ReasoningStep, RemoteMaic, ReviewPipeline, SEED_AXIOMS, SEED_NONCE_BASE, SIGNED_BIRTH_FIELDS, SemioticPattern, SemioticSign, TeleologicalOrientation, VerdictKind, WakeAffectBias, ZodiacSign, assertBirthSignature, canonicalJSON, evaluateRetention, projectOntologicalKernel, signBirthSignature, signedBirthPayload, verifyBirthSignature };
2611
+ // src/creator/sign-birth.ts
2612
+ function signedBirthPayload(birth) {
2613
+ return {
2614
+ himId: birth.himId,
2615
+ bornAt: birth.bornAt,
2616
+ primaryArchetype: birth.primaryArchetype,
2617
+ modifiers: birth.modifiers,
2618
+ primordialAxiomIds: birth.primordialAxiomIds,
2619
+ natalChart: birth.natalChart ?? null
2620
+ };
2621
+ }
2622
+ function signBirthSignature(birth, keyring) {
2623
+ const payload = signedBirthPayload(birth);
2624
+ const nonce = Buffer.byteLength(JSON.stringify(payload), "utf-8");
2625
+ const signature = keyring.sign(payload, nonce);
2626
+ return {
2627
+ ...birth,
2628
+ creatorSignature: signature,
2629
+ signedFields: SIGNED_BIRTH_FIELDS,
2630
+ signedAt: (/* @__PURE__ */ new Date()).toISOString()
2631
+ };
2632
+ }
2633
+ function verifyBirthSignature(signed, expectedPublicKey) {
2634
+ if (signed.signedFields.length !== SIGNED_BIRTH_FIELDS.length) return false;
2635
+ for (const f of SIGNED_BIRTH_FIELDS) {
2636
+ if (!signed.signedFields.includes(f)) return false;
2637
+ }
2638
+ if (signed.creatorSignature.publicKey !== expectedPublicKey) return false;
2639
+ const payload = signedBirthPayload(signed);
2640
+ return CreatorKeyring.verifyWith(expectedPublicKey, payload, signed.creatorSignature);
2641
+ }
2642
+ var InvalidBirthSignatureError = class extends Error {
2643
+ constructor(himId) {
2644
+ super(
2645
+ `InvalidBirthSignature: signature verification failed for HIM '${himId}'. The signed birth fields may have been mutated, or the public key does not match.`
2646
+ );
2647
+ this.name = "InvalidBirthSignatureError";
2648
+ }
2649
+ };
2650
+ function assertBirthSignature(signed, expectedPublicKey) {
2651
+ if (!verifyBirthSignature(signed, expectedPublicKey)) {
2652
+ throw new InvalidBirthSignatureError(signed.himId);
2653
+ }
2654
+ }
2655
+
2656
+ export { ALL_AUDIT_EVENT_KINDS, Affect, ArchetypeModifier, AstrologicalAspect, AuditLog, Axiom, AxiomProposalRecord, AxiomRank, AxiomSource, AxiomStore, BehaviorReport, BirthSignature, BirthSignatureWithIdentity, ClinicalInstrument, ClinicalProfile, ComplianceMapper, CosmologicalProfile, CreatorKeyring, CreatorSignature, DEFAULT_RETENTION_DAYS, DEFAULT_RULE_PACK, DreamInductionIntent, DreamInductionTicket, EU_AI_ACT_MAPPING, EmergentAxiomCandidate, EmergentAxiomProposal, HimStore, ISO_42001_MAPPING, IdentityLayer, IdentitySnapshot, InductionStatus, InductionStore, InteractionRecord, InvalidBirthSignatureError, JungianArchetype, JungianProfile, LimboReturn, LimboState, LimboTransition, LocalMaic, META_AXIOM_ID, MaicVerdict, MemoryRecord, NatalChart, NatalChartAspect, NatalChartPosition, NatalPlanet, NheBodyRef, NheStatus, NheStatusRecord, NheStatusStore, ProposalStatus, ProposalStore, ReasoningStep, RemoteMaic, ReviewPipeline, SEED_AXIOMS, SEED_NONCE_BASE, SIGNED_BIRTH_FIELDS, SemioticPattern, SemioticSign, TeleologicalOrientation, VerdictKind, WakeAffectBias, ZodiacSign, assertBirthSignature, canonicalJSON, evaluateRetention, projectOntologicalKernel, signBirthSignature, signedBirthPayload, verifyBirthSignature };
2401
2657
  //# sourceMappingURL=index.js.map
2402
2658
  //# sourceMappingURL=index.js.map