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