@mneme-ai/core 2.66.0 → 2.68.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +5 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/protoplasm/auto_wrap.d.ts +33 -0
  6. package/dist/protoplasm/auto_wrap.d.ts.map +1 -0
  7. package/dist/protoplasm/auto_wrap.js +72 -0
  8. package/dist/protoplasm/auto_wrap.js.map +1 -0
  9. package/dist/protoplasm/crawl_planner.d.ts +14 -0
  10. package/dist/protoplasm/crawl_planner.d.ts.map +1 -0
  11. package/dist/protoplasm/crawl_planner.js +50 -0
  12. package/dist/protoplasm/crawl_planner.js.map +1 -0
  13. package/dist/protoplasm/criu_pickle.d.ts +49 -0
  14. package/dist/protoplasm/criu_pickle.d.ts.map +1 -0
  15. package/dist/protoplasm/criu_pickle.js +73 -0
  16. package/dist/protoplasm/criu_pickle.js.map +1 -0
  17. package/dist/protoplasm/extensions.test.d.ts +8 -0
  18. package/dist/protoplasm/extensions.test.d.ts.map +1 -0
  19. package/dist/protoplasm/extensions.test.js +175 -0
  20. package/dist/protoplasm/extensions.test.js.map +1 -0
  21. package/dist/protoplasm/findings_ledger.d.ts +19 -0
  22. package/dist/protoplasm/findings_ledger.d.ts.map +1 -0
  23. package/dist/protoplasm/findings_ledger.js +81 -0
  24. package/dist/protoplasm/findings_ledger.js.map +1 -0
  25. package/dist/protoplasm/ghost_cell.d.ts +30 -0
  26. package/dist/protoplasm/ghost_cell.d.ts.map +1 -0
  27. package/dist/protoplasm/ghost_cell.js +95 -0
  28. package/dist/protoplasm/ghost_cell.js.map +1 -0
  29. package/dist/protoplasm/hydra_quorum.d.ts +43 -0
  30. package/dist/protoplasm/hydra_quorum.d.ts.map +1 -0
  31. package/dist/protoplasm/hydra_quorum.js +124 -0
  32. package/dist/protoplasm/hydra_quorum.js.map +1 -0
  33. package/dist/protoplasm/immortal.test.d.ts +12 -0
  34. package/dist/protoplasm/immortal.test.d.ts.map +1 -0
  35. package/dist/protoplasm/immortal.test.js +118 -0
  36. package/dist/protoplasm/immortal.test.js.map +1 -0
  37. package/dist/protoplasm/index.d.ts +52 -0
  38. package/dist/protoplasm/index.d.ts.map +1 -0
  39. package/dist/protoplasm/index.js +53 -0
  40. package/dist/protoplasm/index.js.map +1 -0
  41. package/dist/protoplasm/lan_gossip.d.ts +75 -0
  42. package/dist/protoplasm/lan_gossip.d.ts.map +1 -0
  43. package/dist/protoplasm/lan_gossip.js +140 -0
  44. package/dist/protoplasm/lan_gossip.js.map +1 -0
  45. package/dist/protoplasm/orchestrator.d.ts +29 -0
  46. package/dist/protoplasm/orchestrator.d.ts.map +1 -0
  47. package/dist/protoplasm/orchestrator.js +60 -0
  48. package/dist/protoplasm/orchestrator.js.map +1 -0
  49. package/dist/protoplasm/parasite.d.ts +42 -0
  50. package/dist/protoplasm/parasite.d.ts.map +1 -0
  51. package/dist/protoplasm/parasite.js +69 -0
  52. package/dist/protoplasm/parasite.js.map +1 -0
  53. package/dist/protoplasm/phoenix_hook.d.ts +49 -0
  54. package/dist/protoplasm/phoenix_hook.d.ts.map +1 -0
  55. package/dist/protoplasm/phoenix_hook.js +64 -0
  56. package/dist/protoplasm/phoenix_hook.js.map +1 -0
  57. package/dist/protoplasm/protoplasm.test.d.ts +13 -0
  58. package/dist/protoplasm/protoplasm.test.d.ts.map +1 -0
  59. package/dist/protoplasm/protoplasm.test.js +142 -0
  60. package/dist/protoplasm/protoplasm.test.js.map +1 -0
  61. package/dist/protoplasm/quantum_probe.d.ts +21 -0
  62. package/dist/protoplasm/quantum_probe.d.ts.map +1 -0
  63. package/dist/protoplasm/quantum_probe.js +118 -0
  64. package/dist/protoplasm/quantum_probe.js.map +1 -0
  65. package/dist/protoplasm/seamless_boot.d.ts +28 -0
  66. package/dist/protoplasm/seamless_boot.d.ts.map +1 -0
  67. package/dist/protoplasm/seamless_boot.js +106 -0
  68. package/dist/protoplasm/seamless_boot.js.map +1 -0
  69. package/dist/protoplasm/super_quan_probe.d.ts +24 -0
  70. package/dist/protoplasm/super_quan_probe.d.ts.map +1 -0
  71. package/dist/protoplasm/super_quan_probe.js +132 -0
  72. package/dist/protoplasm/super_quan_probe.js.map +1 -0
  73. package/dist/protoplasm/ts_auto_wrap.d.ts +53 -0
  74. package/dist/protoplasm/ts_auto_wrap.d.ts.map +1 -0
  75. package/dist/protoplasm/ts_auto_wrap.js +102 -0
  76. package/dist/protoplasm/ts_auto_wrap.js.map +1 -0
  77. package/dist/protoplasm/types.d.ts +84 -0
  78. package/dist/protoplasm/types.d.ts.map +1 -0
  79. package/dist/protoplasm/types.js +9 -0
  80. package/dist/protoplasm/types.js.map +1 -0
  81. package/dist/protoplasm/usb_soul.d.ts +35 -0
  82. package/dist/protoplasm/usb_soul.d.ts.map +1 -0
  83. package/dist/protoplasm/usb_soul.js +162 -0
  84. package/dist/protoplasm/usb_soul.js.map +1 -0
  85. package/dist/protoplasm/wal.d.ts +46 -0
  86. package/dist/protoplasm/wal.d.ts.map +1 -0
  87. package/dist/protoplasm/wal.js +145 -0
  88. package/dist/protoplasm/wal.js.map +1 -0
  89. package/dist/protoplasm/wisdom_space.d.ts +30 -0
  90. package/dist/protoplasm/wisdom_space.d.ts.map +1 -0
  91. package/dist/protoplasm/wisdom_space.js +77 -0
  92. package/dist/protoplasm/wisdom_space.js.map +1 -0
  93. package/dist/truth_gate/claims.d.ts.map +1 -1
  94. package/dist/truth_gate/claims.js +18 -0
  95. package/dist/truth_gate/claims.js.map +1 -1
  96. package/dist/truth_gate/probes.d.ts.map +1 -1
  97. package/dist/truth_gate/probes.js +42 -0
  98. package/dist/truth_gate/probes.js.map +1 -1
  99. package/package.json +1 -1
@@ -0,0 +1,175 @@
1
+ /**
2
+ * 🧬 PROTOPLASM — v2.68.0 extension tests
3
+ *
4
+ * Pin invariants for USB SOUL / HYDRA QUORUM / LAN GOSSIP / TS AUTO-WRAP /
5
+ * CRIU PICKLE. Tests skip the OS-specific bits where they cannot run.
6
+ */
7
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
8
+ import { mkdtempSync, rmSync, writeFileSync, readFileSync, existsSync } from "node:fs";
9
+ import { tmpdir } from "node:os";
10
+ import { join } from "node:path";
11
+ import { syncTo, syncFrom, verifyMount } from "./usb_soul.js";
12
+ import { statusHydra, tryBecomePrimary, refreshPrimary, releasePrimary } from "./hydra_quorum.js";
13
+ import { LanGossip, GOSSIP_TUNING } from "./lan_gossip.js";
14
+ import { scanSourceFile, rewriteSourceFile } from "./ts_auto_wrap.js";
15
+ import { probeCriu, snapshot, restore } from "./criu_pickle.js";
16
+ let tmpDir;
17
+ beforeEach(() => { tmpDir = mkdtempSync(join(tmpdir(), "protoplasm-ext-")); });
18
+ afterEach(() => { try {
19
+ rmSync(tmpDir, { recursive: true, force: true });
20
+ }
21
+ catch { /* */ } });
22
+ describe("USB SOUL", () => {
23
+ it("syncTo + syncFrom round-trip preserves files", () => {
24
+ const ledger = join(tmpDir, "ledger");
25
+ const mount = join(tmpDir, "fake-usb");
26
+ require("node:fs").mkdirSync(ledger, { recursive: true });
27
+ require("node:fs").mkdirSync(mount, { recursive: true });
28
+ writeFileSync(join(ledger, "wal.jsonl"), "wal-content");
29
+ writeFileSync(join(ledger, "findings.jsonl"), "findings-content");
30
+ writeFileSync(join(ledger, ".key"), "secret-key-32-chars-min-please-ok");
31
+ const out = syncTo(mount, ledger);
32
+ expect(out.ok).toBe(true);
33
+ expect(out.copied?.length).toBe(3);
34
+ const restoreDir = join(tmpDir, "restored");
35
+ const r = syncFrom(mount, restoreDir);
36
+ expect(r.ok).toBe(true);
37
+ expect(readFileSync(join(restoreDir, "wal.jsonl"), "utf8")).toBe("wal-content");
38
+ expect(readFileSync(join(restoreDir, ".key"), "utf8")).toBe("secret-key-32-chars-min-please-ok");
39
+ });
40
+ it("verifyMount false on nonexistent path", () => {
41
+ const v = verifyMount(join(tmpDir, "does-not-exist"));
42
+ expect(v.ok).toBe(false);
43
+ });
44
+ it("syncTo fails gracefully on bad mount", () => {
45
+ const r = syncTo("/nonexistent/path/whatsoever", tmpDir);
46
+ expect(r.ok).toBe(false);
47
+ expect(r.reason).toBeTruthy();
48
+ });
49
+ });
50
+ describe("HYDRA QUORUM", () => {
51
+ it("first pid acquires primary; second sees secondary (must use real alive pid for primary)", () => {
52
+ const ledger = tmpDir;
53
+ const realPid = process.pid; // alive
54
+ const fakeSecondaryPid = 99002; // dead — just for "other observer" pov
55
+ const a = tryBecomePrimary(ledger, realPid);
56
+ expect(a.role).toBe("primary");
57
+ const bStatus = statusHydra(ledger, fakeSecondaryPid);
58
+ expect(bStatus.role).toBe("secondary");
59
+ expect(bStatus.primaryPid).toBe(realPid);
60
+ });
61
+ it("stale primary lock (dead pid) → status reports uncontested for any observer", () => {
62
+ const ledger = tmpDir;
63
+ // Write a lock with a known-dead pid
64
+ writeFileSync(join(ledger, "hydra.primary"), JSON.stringify({ pid: 99001, ts: Date.now() }));
65
+ const s = statusHydra(ledger, process.pid);
66
+ expect(s.role).toBe("uncontested"); // dead pid → can take over
67
+ });
68
+ it("refreshPrimary returns false when displaced", () => {
69
+ const ledger = tmpDir;
70
+ tryBecomePrimary(ledger, process.pid);
71
+ // Externally overwrite to simulate displacement
72
+ writeFileSync(join(ledger, "hydra.primary"), JSON.stringify({ pid: 88888, ts: Date.now() }));
73
+ const ok = refreshPrimary(ledger, process.pid);
74
+ expect(ok).toBe(false);
75
+ });
76
+ it("releasePrimary unlinks lock", () => {
77
+ const ledger = tmpDir;
78
+ tryBecomePrimary(ledger, process.pid);
79
+ expect(existsSync(join(ledger, "hydra.primary"))).toBe(true);
80
+ releasePrimary(ledger, process.pid);
81
+ expect(existsSync(join(ledger, "hydra.primary"))).toBe(false);
82
+ });
83
+ });
84
+ describe("LAN GOSSIP", () => {
85
+ it("HMAC frame round-trip via loopback unicast", async () => {
86
+ // Use 2 sockets on localhost, NOT multicast (CI environments often block multicast)
87
+ const g1 = new LanGossip({ secret: "test-secret-gossip", group: "127.0.0.1", port: 0 });
88
+ const r1 = await g1.start();
89
+ // Even if multicast fails, peer storage logic still works in unit test via direct handleMessage
90
+ expect(typeof r1.ok).toBe("boolean");
91
+ g1.close();
92
+ }, 5000);
93
+ it("verifyFrame rejects tampered hmac", async () => {
94
+ const g = new LanGossip({ secret: "secret-a" });
95
+ const r = await g.start();
96
+ if (!r.ok) {
97
+ g.close();
98
+ return;
99
+ } // skip when multicast unavailable
100
+ let receivedCount = 0;
101
+ const tamperFrame = JSON.stringify({ v: 1, hostId: "evil", pid: 99, ts: new Date().toISOString(),
102
+ summary: { healthy: 999, warn: 0, broken: 0, totalFns: 0, walRows: 0 }, hmac: "DEADBEEF12345678" });
103
+ const sock = require("node:dgram").createSocket("udp4");
104
+ sock.send(Buffer.from(tamperFrame), GOSSIP_TUNING.DEFAULT_PORT, GOSSIP_TUNING.DEFAULT_GROUP);
105
+ await new Promise((r) => setTimeout(r, 200));
106
+ expect(receivedCount).toBe(0); // tampered should be silently rejected
107
+ sock.close();
108
+ g.close();
109
+ }, 5000);
110
+ });
111
+ describe("TS AUTO-WRAP — scan + rewrite", () => {
112
+ it("scanSourceFile finds export function + arrow exports", () => {
113
+ const src = join(tmpDir, "sample.ts");
114
+ writeFileSync(src, `
115
+ export function alpha(x: number) { return x * 2; }
116
+ export async function beta(): Promise<void> { return; }
117
+ export const gamma = (n: number) => n + 1;
118
+ export const delta = async () => 42;
119
+ const internal = () => 0; // not exported, must be ignored
120
+ export { someOther } from "./other.js"; // re-export, ignored
121
+ `);
122
+ const r = scanSourceFile(src);
123
+ expect(r.exports.find((e) => e.name === "alpha")).toBeDefined();
124
+ expect(r.exports.find((e) => e.name === "beta")?.isAsync).toBe(true);
125
+ expect(r.exports.find((e) => e.name === "gamma")).toBeDefined();
126
+ expect(r.exports.find((e) => e.name === "internal")).toBeUndefined();
127
+ expect(r.hasImportSuperQuan).toBe(false);
128
+ });
129
+ it("rewriteSourceFile dry-run reports count without writing", () => {
130
+ const src = join(tmpDir, "sample.ts");
131
+ const original = `export function foo() { return 1; }\nexport async function bar() { return 2; }\n`;
132
+ writeFileSync(src, original);
133
+ const r = rewriteSourceFile(src, "sample", { dryRun: true });
134
+ expect(r.exportsWrapped).toBe(2);
135
+ expect(r.rewritten).toBe(false);
136
+ expect(readFileSync(src, "utf8")).toBe(original);
137
+ });
138
+ it("rewriteSourceFile refuses when super_quan already imported", () => {
139
+ const src = join(tmpDir, "sample.ts");
140
+ writeFileSync(src, `import { withSuperQuanProbe } from "@mneme-ai/core/protoplasm";\nexport function foo() {}\n`);
141
+ const r = rewriteSourceFile(src, "sample");
142
+ expect(r.rewritten).toBe(false);
143
+ expect(r.reason).toMatch(/already imports/);
144
+ });
145
+ });
146
+ describe("CRIU PICKLE (Linux-only — graceful on Win/macOS)", () => {
147
+ it("probeCriu returns supported=false on non-Linux", () => {
148
+ const r = probeCriu();
149
+ if (process.platform !== "linux") {
150
+ expect(r.supported).toBe(false);
151
+ expect(r.reason).toMatch(/Linux-only/);
152
+ }
153
+ else {
154
+ // on Linux without criu installed: still false but different reason
155
+ expect([true, false]).toContain(r.supported);
156
+ }
157
+ });
158
+ it("snapshot returns ok=false with reason on unsupported platform", () => {
159
+ if (process.platform === "linux")
160
+ return; // skip — Linux may succeed
161
+ const r = snapshot(process.pid, tmpDir);
162
+ expect(r.ok).toBe(false);
163
+ expect(r.reason).toBeTruthy();
164
+ });
165
+ it("restore on missing image dir returns ok=false", () => {
166
+ if (process.platform !== "linux") {
167
+ const r = restore("/nonexistent");
168
+ expect(r.ok).toBe(false);
169
+ return;
170
+ }
171
+ const r = restore(join(tmpDir, "does-not-exist"));
172
+ expect(r.ok).toBe(false);
173
+ });
174
+ });
175
+ //# sourceMappingURL=extensions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensions.test.js","sourceRoot":"","sources":["../../src/protoplasm/extensions.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAa,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AAChH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAiB,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhE,IAAI,MAAc,CAAC;AAEnB,UAAU,CAAC,GAAG,EAAE,GAAG,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/E,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAAC,CAAC;AAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/F,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACvC,OAAO,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,aAAa,CAAC,CAAC;QACxD,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,CAAC;QAClE,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,mCAAmC,CAAC,CAAC;QAEzE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEnC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAChF,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IACnG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,GAAG,MAAM,CAAC,8BAA8B,EAAE,MAAM,CAAC,CAAC;QACzD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,yFAAyF,EAAE,GAAG,EAAE;QACjG,MAAM,MAAM,GAAG,MAAM,CAAC;QACtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAO,QAAQ;QAC3C,MAAM,gBAAgB,GAAG,KAAK,CAAC,CAAI,uCAAuC;QAC1E,MAAM,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAE/B,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,MAAM,GAAG,MAAM,CAAC;QACtB,qCAAqC;QACrC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAM,2BAA2B;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,MAAM,CAAC;QACtB,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACtC,gDAAgD;QAChD,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7F,MAAM,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,MAAM,GAAG,MAAM,CAAC;QACtB,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,oFAAoF;QACpF,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QACxF,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QAC5B,gGAAgG;QAChG,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC,EAAE,IAAI,CAAC,CAAC;IAET,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,CAAC,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAAC,CAAC,CAAC,KAAK,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC,CAAE,kCAAkC;QACrE,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC9F,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACtG,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC,YAAY,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;QAC7F,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAE,uCAAuC;QACvE,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,CAAC,CAAC,KAAK,EAAE,CAAC;IACZ,CAAC,EAAE,IAAI,CAAC,CAAC;AACX,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACtC,aAAa,CAAC,GAAG,EAAE;;;;;;;CAOtB,CAAC,CAAC;QACC,MAAM,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAChE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAChE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACrE,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,kFAAkF,CAAC;QACpG,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC7B,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACtC,aAAa,CAAC,GAAG,EAAE,6FAA6F,CAAC,CAAC;QAClH,MAAM,CAAC,GAAG,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kDAAkD,EAAE,GAAG,EAAE;IAChE,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,GAAG,SAAS,EAAE,CAAC;QACtB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,oEAAoE;YACpE,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;YAAE,OAAO,CAAK,2BAA2B;QACzE,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACxC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,MAAM,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;YAClC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QACD,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 🦠 PROTOPLASM — findings_ledger
3
+ *
4
+ * HMAC-chained append-only log of super_quan findings.
5
+ * Same canonical-JSON pattern as PASSPORT/MIRRAGE/TIME-CRYSTAL/REFLOG ledgers.
6
+ */
7
+ import type { SuperQuanFinding } from "./types.js";
8
+ /** Canonical JSON: deterministic key sort + undefined removed. */
9
+ export declare function canonicalJson(obj: unknown): string;
10
+ export declare function chainHmac(prevHmac: string, finding: Omit<SuperQuanFinding, "hmac" | "prev">, secret: string): string;
11
+ export declare function appendFinding(ledgerPath: string, finding: Omit<SuperQuanFinding, "hmac" | "prev">, secret: string): SuperQuanFinding;
12
+ export declare function lastHmac(ledgerPath: string): string;
13
+ export declare function readLedger(ledgerPath: string): SuperQuanFinding[];
14
+ export declare function verifyChain(ledgerPath: string, secret: string): {
15
+ ok: boolean;
16
+ brokenAt?: number;
17
+ rows: number;
18
+ };
19
+ //# sourceMappingURL=findings_ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findings_ledger.d.ts","sourceRoot":"","sources":["../../src/protoplasm/findings_ledger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAelD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpH;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC,EAChD,MAAM,EAAE,MAAM,GACb,gBAAgB,CAOlB;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAKjE;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAWhH"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * 🦠 PROTOPLASM — findings_ledger
3
+ *
4
+ * HMAC-chained append-only log of super_quan findings.
5
+ * Same canonical-JSON pattern as PASSPORT/MIRRAGE/TIME-CRYSTAL/REFLOG ledgers.
6
+ */
7
+ import { createHmac } from "node:crypto";
8
+ import { appendFileSync, existsSync, readFileSync, mkdirSync } from "node:fs";
9
+ import { dirname } from "node:path";
10
+ /** Canonical JSON: deterministic key sort + undefined removed. */
11
+ export function canonicalJson(obj) {
12
+ const seen = new WeakSet();
13
+ const visit = (v) => {
14
+ if (v === null || typeof v !== "object")
15
+ return v;
16
+ if (seen.has(v))
17
+ return "[Circular]";
18
+ seen.add(v);
19
+ if (Array.isArray(v))
20
+ return v.map(visit);
21
+ const sorted = {};
22
+ for (const k of Object.keys(v).sort()) {
23
+ const val = v[k];
24
+ if (val !== undefined)
25
+ sorted[k] = visit(val);
26
+ }
27
+ return sorted;
28
+ };
29
+ return JSON.stringify(visit(obj));
30
+ }
31
+ export function chainHmac(prevHmac, finding, secret) {
32
+ return createHmac("sha256", secret).update(prevHmac + "::" + canonicalJson(finding)).digest("hex").slice(0, 16);
33
+ }
34
+ export function appendFinding(ledgerPath, finding, secret) {
35
+ mkdirSync(dirname(ledgerPath), { recursive: true });
36
+ const prev = lastHmac(ledgerPath);
37
+ const hmac = chainHmac(prev, finding, secret);
38
+ const full = { ...finding, prev, hmac };
39
+ appendFileSync(ledgerPath, JSON.stringify(full) + "\n", "utf8");
40
+ return full;
41
+ }
42
+ export function lastHmac(ledgerPath) {
43
+ if (!existsSync(ledgerPath))
44
+ return "0".repeat(16);
45
+ const lines = readFileSync(ledgerPath, "utf8").trim().split("\n").filter(Boolean);
46
+ if (lines.length === 0)
47
+ return "0".repeat(16);
48
+ try {
49
+ return JSON.parse(lines[lines.length - 1]).hmac;
50
+ }
51
+ catch {
52
+ return "0".repeat(16);
53
+ }
54
+ }
55
+ export function readLedger(ledgerPath) {
56
+ if (!existsSync(ledgerPath))
57
+ return [];
58
+ return readFileSync(ledgerPath, "utf8").trim().split("\n").filter(Boolean).map((l) => {
59
+ try {
60
+ return JSON.parse(l);
61
+ }
62
+ catch {
63
+ return null;
64
+ }
65
+ }).filter((x) => x !== null);
66
+ }
67
+ export function verifyChain(ledgerPath, secret) {
68
+ const rows = readLedger(ledgerPath);
69
+ let prev = "0".repeat(16);
70
+ for (let i = 0; i < rows.length; i++) {
71
+ const { hmac, prev: storedPrev, ...rest } = rows[i];
72
+ if (storedPrev !== prev)
73
+ return { ok: false, brokenAt: i, rows: rows.length };
74
+ const recomputed = chainHmac(prev, rest, secret);
75
+ if (recomputed !== hmac)
76
+ return { ok: false, brokenAt: i, rows: rows.length };
77
+ prev = hmac;
78
+ }
79
+ return { ok: true, rows: rows.length };
80
+ }
81
+ //# sourceMappingURL=findings_ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findings_ledger.js","sourceRoot":"","sources":["../../src/protoplasm/findings_ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 👻 PROTOPLASM — GHOST CELL
3
+ *
4
+ * Every `mneme <cmd>` spawns a detached watchdog child that outlives
5
+ * parent by N seconds. If parent dies cleanly (exit 0), ghost expires
6
+ * silently. If parent dies abnormally (SIGKILL, SIGSEGV, exit != 0),
7
+ * ghost detects + spawns heal cycle.
8
+ *
9
+ * "Last words of dying parent → first words of newborn child."
10
+ *
11
+ * Implementation:
12
+ * spawn(node, [ghost_script], { detached: true, stdio: 'ignore' }).unref()
13
+ *
14
+ * Ghost script:
15
+ * - Waits N seconds polling parent PID
16
+ * - Reads parent's last heartbeat from .mneme/protoplasm/heartbeat.json
17
+ * - If heartbeat is stale + parent gone → trigger heal
18
+ *
19
+ * Detached + unref'd means parent can exit and ghost continues.
20
+ */
21
+ export interface GhostCellOptions {
22
+ parentPid: number;
23
+ ledgerDir: string;
24
+ watchdogMs?: number;
25
+ hmacKey: string;
26
+ }
27
+ /** Spawn a detached ghost cell that watches the current process.
28
+ * Returns child PID. Parent can exit immediately; ghost continues. */
29
+ export declare function spawnGhostCell(opts: GhostCellOptions): number | null;
30
+ //# sourceMappingURL=ghost_cell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ghost_cell.d.ts","sourceRoot":"","sources":["../../src/protoplasm/ghost_cell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAqDD;uEACuE;AACvE,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAuBpE"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * 👻 PROTOPLASM — GHOST CELL
3
+ *
4
+ * Every `mneme <cmd>` spawns a detached watchdog child that outlives
5
+ * parent by N seconds. If parent dies cleanly (exit 0), ghost expires
6
+ * silently. If parent dies abnormally (SIGKILL, SIGSEGV, exit != 0),
7
+ * ghost detects + spawns heal cycle.
8
+ *
9
+ * "Last words of dying parent → first words of newborn child."
10
+ *
11
+ * Implementation:
12
+ * spawn(node, [ghost_script], { detached: true, stdio: 'ignore' }).unref()
13
+ *
14
+ * Ghost script:
15
+ * - Waits N seconds polling parent PID
16
+ * - Reads parent's last heartbeat from .mneme/protoplasm/heartbeat.json
17
+ * - If heartbeat is stale + parent gone → trigger heal
18
+ *
19
+ * Detached + unref'd means parent can exit and ghost continues.
20
+ */
21
+ import { spawn } from "node:child_process";
22
+ import { writeFileSync, mkdirSync } from "node:fs";
23
+ import { join } from "node:path";
24
+ const GHOST_SCRIPT = `
25
+ const fs = require("node:fs");
26
+ const path = require("node:path");
27
+ const { parentPid, ledgerDir, watchdogMs } = JSON.parse(process.argv[2] || "{}");
28
+ const heartbeatPath = path.join(ledgerDir, "heartbeat.json");
29
+ const ghostLogPath = path.join(ledgerDir, "ghost_log.jsonl");
30
+
31
+ function alive(pid) {
32
+ try { process.kill(pid, 0); return true; } catch { return false; }
33
+ }
34
+
35
+ function log(event, details) {
36
+ try {
37
+ fs.appendFileSync(ghostLogPath, JSON.stringify({ ts: new Date().toISOString(), pid: process.pid, event, parentPid, details }) + "\\n");
38
+ } catch {}
39
+ }
40
+
41
+ log("ghost-spawned", { watchdogMs });
42
+
43
+ const deadline = Date.now() + (watchdogMs || 30000);
44
+ let parentDiedAt = null;
45
+
46
+ (async () => {
47
+ while (Date.now() < deadline) {
48
+ if (parentDiedAt === null && !alive(parentPid)) {
49
+ parentDiedAt = Date.now();
50
+ log("parent-died");
51
+ // Check if parent left a clean shutdown marker (heartbeat ts within last 1s)
52
+ try {
53
+ const hb = JSON.parse(fs.readFileSync(heartbeatPath, "utf8"));
54
+ const hbAge = Date.now() - new Date(hb.ts).getTime();
55
+ if (hbAge < 1000) {
56
+ log("clean-exit", { hbAge });
57
+ } else {
58
+ log("abnormal-exit", { hbAge });
59
+ // FUTURE: trigger heal action — for now just log
60
+ fs.appendFileSync(path.join(ledgerDir, "heal_queue.jsonl"),
61
+ JSON.stringify({ ts: new Date().toISOString(), parentPid, reason: "ghost-detected-abnormal-exit", hbAge }) + "\\n");
62
+ }
63
+ } catch (e) {
64
+ log("heartbeat-read-error", { msg: String(e) });
65
+ }
66
+ break;
67
+ }
68
+ await new Promise(r => setTimeout(r, 500));
69
+ }
70
+ log("ghost-expired");
71
+ process.exit(0);
72
+ })();
73
+ `;
74
+ /** Spawn a detached ghost cell that watches the current process.
75
+ * Returns child PID. Parent can exit immediately; ghost continues. */
76
+ export function spawnGhostCell(opts) {
77
+ try {
78
+ mkdirSync(opts.ledgerDir, { recursive: true });
79
+ // Write ghost script to temp file (detached child needs accessible script)
80
+ const scriptPath = join(opts.ledgerDir, "ghost_runner.cjs");
81
+ writeFileSync(scriptPath, GHOST_SCRIPT, "utf8");
82
+ // Windows quirk: detached + paths with spaces need shell wrapping;
83
+ // POSIX works with direct exec.
84
+ const isWin = process.platform === "win32";
85
+ const child = isWin
86
+ ? spawn(process.execPath, [scriptPath, JSON.stringify({ parentPid: opts.parentPid, ledgerDir: opts.ledgerDir, watchdogMs: opts.watchdogMs ?? 30000 })], { detached: true, stdio: "ignore", windowsHide: true, windowsVerbatimArguments: false })
87
+ : spawn(process.execPath, [scriptPath, JSON.stringify({ parentPid: opts.parentPid, ledgerDir: opts.ledgerDir, watchdogMs: opts.watchdogMs ?? 30000 })], { detached: true, stdio: "ignore" });
88
+ child.unref();
89
+ return child.pid ?? null;
90
+ }
91
+ catch {
92
+ return null;
93
+ }
94
+ }
95
+ //# sourceMappingURL=ghost_cell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ghost_cell.js","sourceRoot":"","sources":["../../src/protoplasm/ghost_cell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AASjC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDpB,CAAC;AAEF;uEACuE;AACvE,MAAM,UAAU,cAAc,CAAC,IAAsB;IACnD,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,2EAA2E;QAC3E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;QAC5D,aAAa,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QAChD,mEAAmE;QACnE,gCAAgC;QAChC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;QAC3C,MAAM,KAAK,GAAG,KAAK;YACjB,CAAC,CAAC,KAAK,CACH,OAAO,CAAC,QAAQ,EAChB,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,KAAK,EAAE,CAAC,CAAC,EAC5H,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,CACxF;YACH,CAAC,CAAC,KAAK,CACH,OAAO,CAAC,QAAQ,EAChB,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,KAAK,EAAE,CAAC,CAAC,EAC5H,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CACpC,CAAC;QACN,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 🐉 PROTOPLASM — HYDRA QUORUM
3
+ *
4
+ * "Cut one head, two more grow."
5
+ *
6
+ * Multi-process co-hosting. N PIDs (typically 3) compete for PRIMARY
7
+ * lock; non-primaries become SECONDARIES. Primary writes new findings;
8
+ * secondaries replay + watch.
9
+ *
10
+ * Leader election: simple file-based lock with timeout.
11
+ * - .mneme/protoplasm/hydra.primary (PID + timestamp of current primary)
12
+ * - lock acquired by atomic write-if-not-exists
13
+ * - primary refreshes timestamp every 5s
14
+ * - if primary stale (>15s) → any secondary can take over
15
+ *
16
+ * No Raft / Paxos — file-based is enough for liveness; HMAC chain on
17
+ * findings remains the trust layer regardless of which head wrote what.
18
+ */
19
+ export type HydraRole = "primary" | "secondary" | "uncontested";
20
+ export interface HydraStatus {
21
+ role: HydraRole;
22
+ primaryPid: number | null;
23
+ primaryAge: number;
24
+ ownPid: number;
25
+ acquiredAt?: string;
26
+ lockPath: string;
27
+ }
28
+ export declare function statusHydra(ledgerDir: string, ownPid?: number): HydraStatus;
29
+ /** Attempt to become primary. Idempotent if already primary.
30
+ * Returns final role + reason. */
31
+ export declare function tryBecomePrimary(ledgerDir: string, ownPid?: number): HydraStatus;
32
+ /** Refresh primary timestamp (call every REFRESH_MS while primary).
33
+ * Returns true if still primary; false if got displaced. */
34
+ export declare function refreshPrimary(ledgerDir: string, ownPid?: number): boolean;
35
+ /** Release primary (graceful step-down). */
36
+ export declare function releasePrimary(ledgerDir: string, ownPid?: number): boolean;
37
+ /** Wire as background refresher. Returns cancel fn. */
38
+ export declare function startHydraHeartbeat(ledgerDir: string, ownPid?: number): () => void;
39
+ export declare const HYDRA_TUNING: {
40
+ STALE_MS: number;
41
+ REFRESH_MS: number;
42
+ };
43
+ //# sourceMappingURL=hydra_quorum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydra_quorum.d.ts","sourceRoot":"","sources":["../../src/protoplasm/hydra_quorum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAgCD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,SAAc,GAAG,WAAW,CAQhF;AAED;mCACmC;AACnC,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,SAAc,GAAG,WAAW,CAQrF;AAED;6DAC6D;AAC7D,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,SAAc,GAAG,OAAO,CAM/E;AAED,4CAA4C;AAC5C,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,SAAc,GAAG,OAAO,CAK/E;AAED,uDAAuD;AACvD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,SAAc,GAAG,MAAM,IAAI,CAUvF;AAED,eAAO,MAAM,YAAY;;;CAA2B,CAAC"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * 🐉 PROTOPLASM — HYDRA QUORUM
3
+ *
4
+ * "Cut one head, two more grow."
5
+ *
6
+ * Multi-process co-hosting. N PIDs (typically 3) compete for PRIMARY
7
+ * lock; non-primaries become SECONDARIES. Primary writes new findings;
8
+ * secondaries replay + watch.
9
+ *
10
+ * Leader election: simple file-based lock with timeout.
11
+ * - .mneme/protoplasm/hydra.primary (PID + timestamp of current primary)
12
+ * - lock acquired by atomic write-if-not-exists
13
+ * - primary refreshes timestamp every 5s
14
+ * - if primary stale (>15s) → any secondary can take over
15
+ *
16
+ * No Raft / Paxos — file-based is enough for liveness; HMAC chain on
17
+ * findings remains the trust layer regardless of which head wrote what.
18
+ */
19
+ import { writeFileSync, readFileSync, existsSync, mkdirSync, unlinkSync } from "node:fs";
20
+ import { join, dirname } from "node:path";
21
+ const STALE_MS = 15_000;
22
+ const REFRESH_MS = 5_000;
23
+ function lockPath(ledgerDir) {
24
+ return join(ledgerDir, "hydra.primary");
25
+ }
26
+ function readLock(p) {
27
+ if (!existsSync(p))
28
+ return null;
29
+ try {
30
+ const j = JSON.parse(readFileSync(p, "utf8"));
31
+ if (typeof j.pid === "number" && typeof j.ts === "number")
32
+ return j;
33
+ }
34
+ catch { /* */ }
35
+ return null;
36
+ }
37
+ function writeLock(p, pid) {
38
+ mkdirSync(dirname(p), { recursive: true });
39
+ // Best-effort atomic-ish: write to tmp, rename
40
+ const tmp = p + ".tmp." + pid;
41
+ writeFileSync(tmp, JSON.stringify({ pid, ts: Date.now() }), "utf8");
42
+ try {
43
+ require("node:fs").renameSync(tmp, p);
44
+ }
45
+ catch {
46
+ try {
47
+ writeFileSync(p, JSON.stringify({ pid, ts: Date.now() }));
48
+ }
49
+ catch { /* */ }
50
+ }
51
+ }
52
+ function alivePid(pid) {
53
+ try {
54
+ process.kill(pid, 0);
55
+ return true;
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ export function statusHydra(ledgerDir, ownPid = process.pid) {
62
+ const p = lockPath(ledgerDir);
63
+ const lock = readLock(p);
64
+ if (!lock)
65
+ return { role: "uncontested", primaryPid: null, primaryAge: 0, ownPid, lockPath: p };
66
+ const age = Date.now() - lock.ts;
67
+ if (lock.pid === ownPid)
68
+ return { role: "primary", primaryPid: ownPid, primaryAge: age, ownPid, lockPath: p };
69
+ if (age > STALE_MS || !alivePid(lock.pid))
70
+ return { role: "uncontested", primaryPid: lock.pid, primaryAge: age, ownPid, lockPath: p };
71
+ return { role: "secondary", primaryPid: lock.pid, primaryAge: age, ownPid, lockPath: p };
72
+ }
73
+ /** Attempt to become primary. Idempotent if already primary.
74
+ * Returns final role + reason. */
75
+ export function tryBecomePrimary(ledgerDir, ownPid = process.pid) {
76
+ const p = lockPath(ledgerDir);
77
+ const before = statusHydra(ledgerDir, ownPid);
78
+ if (before.role === "primary")
79
+ return before;
80
+ if (before.role === "secondary")
81
+ return before; // someone else holds it freshly
82
+ // uncontested — claim it
83
+ writeLock(p, ownPid);
84
+ return { role: "primary", primaryPid: ownPid, primaryAge: 0, ownPid, lockPath: p, acquiredAt: new Date().toISOString() };
85
+ }
86
+ /** Refresh primary timestamp (call every REFRESH_MS while primary).
87
+ * Returns true if still primary; false if got displaced. */
88
+ export function refreshPrimary(ledgerDir, ownPid = process.pid) {
89
+ const p = lockPath(ledgerDir);
90
+ const lock = readLock(p);
91
+ if (!lock || lock.pid !== ownPid)
92
+ return false;
93
+ writeLock(p, ownPid);
94
+ return true;
95
+ }
96
+ /** Release primary (graceful step-down). */
97
+ export function releasePrimary(ledgerDir, ownPid = process.pid) {
98
+ const p = lockPath(ledgerDir);
99
+ const lock = readLock(p);
100
+ if (!lock || lock.pid !== ownPid)
101
+ return false;
102
+ try {
103
+ unlinkSync(p);
104
+ return true;
105
+ }
106
+ catch {
107
+ return false;
108
+ }
109
+ }
110
+ /** Wire as background refresher. Returns cancel fn. */
111
+ export function startHydraHeartbeat(ledgerDir, ownPid = process.pid) {
112
+ const interval = setInterval(() => {
113
+ const ok = refreshPrimary(ledgerDir, ownPid);
114
+ if (!ok) {
115
+ // We were displaced. Try to reacquire next tick.
116
+ tryBecomePrimary(ledgerDir, ownPid);
117
+ }
118
+ }, REFRESH_MS);
119
+ if (typeof interval.unref === "function")
120
+ interval.unref();
121
+ return () => clearInterval(interval);
122
+ }
123
+ export const HYDRA_TUNING = { STALE_MS, REFRESH_MS };
124
+ //# sourceMappingURL=hydra_quorum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hydra_quorum.js","sourceRoot":"","sources":["../../src/protoplasm/hydra_quorum.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 🩸 PROTOPLASM — IMMORTAL ATOM tests
3
+ *
4
+ * Pin 5 invariants that make PROTOPLASM survive process death:
5
+ * I-IMMORTAL-1: WAL persists baseline BEFORE RAM update
6
+ * I-IMMORTAL-2: replay reconstructs baselines from WAL
7
+ * I-IMMORTAL-3: tampered WAL row → verify detects
8
+ * I-IMMORTAL-4: seamlessBoot is idempotent (safe to call N times)
9
+ * I-IMMORTAL-5: parasiteTick writes heartbeat
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=immortal.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"immortal.test.d.ts","sourceRoot":"","sources":["../../src/protoplasm/immortal.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}