simfile 0.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.
Files changed (249) hide show
  1. package/README.md +143 -0
  2. package/dist/cli/index.d.ts +3 -0
  3. package/dist/cli/index.d.ts.map +1 -0
  4. package/dist/cli/index.js +348 -0
  5. package/dist/coverage/index.d.ts +2 -0
  6. package/dist/coverage/index.d.ts.map +1 -0
  7. package/dist/coverage/index.js +1 -0
  8. package/dist/coverage/matrix.d.ts +21 -0
  9. package/dist/coverage/matrix.d.ts.map +1 -0
  10. package/dist/coverage/matrix.js +173 -0
  11. package/dist/coverage/render.d.ts +3 -0
  12. package/dist/coverage/render.d.ts.map +1 -0
  13. package/dist/coverage/render.js +26 -0
  14. package/dist/index.d.ts +8 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +7 -0
  17. package/dist/kernel/duration.d.ts +9 -0
  18. package/dist/kernel/duration.d.ts.map +1 -0
  19. package/dist/kernel/duration.js +44 -0
  20. package/dist/kernel/index.d.ts +4 -0
  21. package/dist/kernel/index.d.ts.map +1 -0
  22. package/dist/kernel/index.js +3 -0
  23. package/dist/kernel/range.d.ts +6 -0
  24. package/dist/kernel/range.d.ts.map +1 -0
  25. package/dist/kernel/range.js +16 -0
  26. package/dist/kernel/stochastic.d.ts +10 -0
  27. package/dist/kernel/stochastic.d.ts.map +1 -0
  28. package/dist/kernel/stochastic.js +25 -0
  29. package/dist/ledger/index.d.ts +4 -0
  30. package/dist/ledger/index.d.ts.map +1 -0
  31. package/dist/ledger/index.js +3 -0
  32. package/dist/ledger/markers.d.ts +46 -0
  33. package/dist/ledger/markers.d.ts.map +1 -0
  34. package/dist/ledger/markers.js +108 -0
  35. package/dist/ledger/stable.d.ts +65 -0
  36. package/dist/ledger/stable.d.ts.map +1 -0
  37. package/dist/ledger/stable.js +78 -0
  38. package/dist/ledger/validation.d.ts +16 -0
  39. package/dist/ledger/validation.d.ts.map +1 -0
  40. package/dist/ledger/validation.js +127 -0
  41. package/dist/moltnet/index.d.ts +3 -0
  42. package/dist/moltnet/index.d.ts.map +1 -0
  43. package/dist/moltnet/index.js +2 -0
  44. package/dist/moltnet/transcript-export.d.ts +34 -0
  45. package/dist/moltnet/transcript-export.d.ts.map +1 -0
  46. package/dist/moltnet/transcript-export.js +68 -0
  47. package/dist/moltnet/world-participant.d.ts +77 -0
  48. package/dist/moltnet/world-participant.d.ts.map +1 -0
  49. package/dist/moltnet/world-participant.js +221 -0
  50. package/dist/observe/artifacts.d.ts +16 -0
  51. package/dist/observe/artifacts.d.ts.map +1 -0
  52. package/dist/observe/artifacts.js +31 -0
  53. package/dist/observe/causalStreams.d.ts +19 -0
  54. package/dist/observe/causalStreams.d.ts.map +1 -0
  55. package/dist/observe/causalStreams.js +38 -0
  56. package/dist/observe/compute.d.ts +17 -0
  57. package/dist/observe/compute.d.ts.map +1 -0
  58. package/dist/observe/compute.js +97 -0
  59. package/dist/observe/index.d.ts +11 -0
  60. package/dist/observe/index.d.ts.map +1 -0
  61. package/dist/observe/index.js +10 -0
  62. package/dist/observe/manifest.d.ts +79 -0
  63. package/dist/observe/manifest.d.ts.map +1 -0
  64. package/dist/observe/manifest.js +87 -0
  65. package/dist/observe/memoryBanks.d.ts +38 -0
  66. package/dist/observe/memoryBanks.d.ts.map +1 -0
  67. package/dist/observe/memoryBanks.js +86 -0
  68. package/dist/observe/observe.d.ts +32 -0
  69. package/dist/observe/observe.d.ts.map +1 -0
  70. package/dist/observe/observe.js +73 -0
  71. package/dist/observe/report.d.ts +165 -0
  72. package/dist/observe/report.d.ts.map +1 -0
  73. package/dist/observe/report.js +138 -0
  74. package/dist/observe/seedSpread.d.ts +49 -0
  75. package/dist/observe/seedSpread.d.ts.map +1 -0
  76. package/dist/observe/seedSpread.js +262 -0
  77. package/dist/observe/seedSpreadArtifacts.d.ts +49 -0
  78. package/dist/observe/seedSpreadArtifacts.d.ts.map +1 -0
  79. package/dist/observe/seedSpreadArtifacts.js +118 -0
  80. package/dist/observe/spreadMatcher.d.ts +45 -0
  81. package/dist/observe/spreadMatcher.d.ts.map +1 -0
  82. package/dist/observe/spreadMatcher.js +124 -0
  83. package/dist/report/index.d.ts +4 -0
  84. package/dist/report/index.d.ts.map +1 -0
  85. package/dist/report/index.js +3 -0
  86. package/dist/report/probeArtifact.d.ts +26 -0
  87. package/dist/report/probeArtifact.d.ts.map +1 -0
  88. package/dist/report/probeArtifact.js +119 -0
  89. package/dist/report/probes.d.ts +52 -0
  90. package/dist/report/probes.d.ts.map +1 -0
  91. package/dist/report/probes.js +164 -0
  92. package/dist/report/score.d.ts +27 -0
  93. package/dist/report/score.d.ts.map +1 -0
  94. package/dist/report/score.js +14 -0
  95. package/dist/report/transcripts.d.ts +12 -0
  96. package/dist/report/transcripts.d.ts.map +1 -0
  97. package/dist/report/transcripts.js +17 -0
  98. package/dist/runtime/causal-fixture.d.ts +26 -0
  99. package/dist/runtime/causal-fixture.d.ts.map +1 -0
  100. package/dist/runtime/causal-fixture.js +36 -0
  101. package/dist/runtime/clock.d.ts +25 -0
  102. package/dist/runtime/clock.d.ts.map +1 -0
  103. package/dist/runtime/clock.js +63 -0
  104. package/dist/runtime/condition.d.ts +55 -0
  105. package/dist/runtime/condition.d.ts.map +1 -0
  106. package/dist/runtime/condition.js +122 -0
  107. package/dist/runtime/emit-causal-fixture.d.ts +2 -0
  108. package/dist/runtime/emit-causal-fixture.d.ts.map +1 -0
  109. package/dist/runtime/emit-causal-fixture.js +45 -0
  110. package/dist/runtime/expression.d.ts +11 -0
  111. package/dist/runtime/expression.d.ts.map +1 -0
  112. package/dist/runtime/expression.js +305 -0
  113. package/dist/runtime/numeric.d.ts +7 -0
  114. package/dist/runtime/numeric.d.ts.map +1 -0
  115. package/dist/runtime/numeric.js +11 -0
  116. package/dist/runtime/rule-actions.d.ts +5 -0
  117. package/dist/runtime/rule-actions.d.ts.map +1 -0
  118. package/dist/runtime/rule-actions.js +82 -0
  119. package/dist/runtime/run-record.d.ts +73 -0
  120. package/dist/runtime/run-record.d.ts.map +1 -0
  121. package/dist/runtime/run-record.js +179 -0
  122. package/dist/runtime/step-tick.d.ts +43 -0
  123. package/dist/runtime/step-tick.d.ts.map +1 -0
  124. package/dist/runtime/step-tick.js +177 -0
  125. package/dist/runtime/trace-compile.d.ts +66 -0
  126. package/dist/runtime/trace-compile.d.ts.map +1 -0
  127. package/dist/runtime/trace-compile.js +157 -0
  128. package/dist/runtime/trace-export.d.ts +5 -0
  129. package/dist/runtime/trace-export.d.ts.map +1 -0
  130. package/dist/runtime/trace-export.js +4 -0
  131. package/dist/runtime/trace-run.d.ts +15 -0
  132. package/dist/runtime/trace-run.d.ts.map +1 -0
  133. package/dist/runtime/trace-run.js +92 -0
  134. package/dist/runtime/trace.d.ts +10 -0
  135. package/dist/runtime/trace.d.ts.map +1 -0
  136. package/dist/runtime/trace.js +9 -0
  137. package/dist/runtime/types.d.ts +61 -0
  138. package/dist/runtime/types.d.ts.map +1 -0
  139. package/dist/runtime/types.js +1 -0
  140. package/dist/runtime/viewer-trace.d.ts +64 -0
  141. package/dist/runtime/viewer-trace.d.ts.map +1 -0
  142. package/dist/runtime/viewer-trace.js +164 -0
  143. package/dist/runtime/world-act.d.ts +55 -0
  144. package/dist/runtime/world-act.d.ts.map +1 -0
  145. package/dist/runtime/world-act.js +156 -0
  146. package/dist/schema/binding.d.ts +23 -0
  147. package/dist/schema/binding.d.ts.map +1 -0
  148. package/dist/schema/binding.js +249 -0
  149. package/dist/schema/index.d.ts +5 -0
  150. package/dist/schema/index.d.ts.map +1 -0
  151. package/dist/schema/index.js +4 -0
  152. package/dist/schema/model.d.ts +244 -0
  153. package/dist/schema/model.d.ts.map +1 -0
  154. package/dist/schema/model.js +222 -0
  155. package/dist/schema/parse.d.ts +10 -0
  156. package/dist/schema/parse.d.ts.map +1 -0
  157. package/dist/schema/parse.js +15 -0
  158. package/dist/schema/semantic.d.ts +3 -0
  159. package/dist/schema/semantic.d.ts.map +1 -0
  160. package/dist/schema/semantic.js +135 -0
  161. package/dist/sims/composeRunManifest.d.ts +54 -0
  162. package/dist/sims/composeRunManifest.d.ts.map +1 -0
  163. package/dist/sims/composeRunManifest.js +40 -0
  164. package/dist/sims/composedJungianSimDriver.d.ts +50 -0
  165. package/dist/sims/composedJungianSimDriver.d.ts.map +1 -0
  166. package/dist/sims/composedJungianSimDriver.js +199 -0
  167. package/dist/sims/composedOfficeSimDriver.d.ts +53 -0
  168. package/dist/sims/composedOfficeSimDriver.d.ts.map +1 -0
  169. package/dist/sims/composedOfficeSimDriver.js +162 -0
  170. package/dist/sims/exchangeWait.d.ts +56 -0
  171. package/dist/sims/exchangeWait.d.ts.map +1 -0
  172. package/dist/sims/exchangeWait.js +66 -0
  173. package/dist/sims/index.d.ts +14 -0
  174. package/dist/sims/index.d.ts.map +1 -0
  175. package/dist/sims/index.js +13 -0
  176. package/dist/sims/moltnetRoomClient.d.ts +47 -0
  177. package/dist/sims/moltnetRoomClient.d.ts.map +1 -0
  178. package/dist/sims/moltnetRoomClient.js +41 -0
  179. package/dist/sims/poll.d.ts +19 -0
  180. package/dist/sims/poll.d.ts.map +1 -0
  181. package/dist/sims/poll.js +23 -0
  182. package/dist/sims/spawnfileCli.d.ts +49 -0
  183. package/dist/sims/spawnfileCli.d.ts.map +1 -0
  184. package/dist/sims/spawnfileCli.js +90 -0
  185. package/dist/sims/spawnfileReceipts.d.ts +76 -0
  186. package/dist/sims/spawnfileReceipts.d.ts.map +1 -0
  187. package/dist/sims/spawnfileReceipts.js +107 -0
  188. package/dist/sims/worldDrivenOfficeSimDriver.d.ts +59 -0
  189. package/dist/sims/worldDrivenOfficeSimDriver.d.ts.map +1 -0
  190. package/dist/sims/worldDrivenOfficeSimDriver.js +182 -0
  191. package/dist/sims/worldLedgerWriter.d.ts +32 -0
  192. package/dist/sims/worldLedgerWriter.d.ts.map +1 -0
  193. package/dist/sims/worldLedgerWriter.js +39 -0
  194. package/dist/sims/worldSeedLint.d.ts +42 -0
  195. package/dist/sims/worldSeedLint.d.ts.map +1 -0
  196. package/dist/sims/worldSeedLint.js +73 -0
  197. package/dist/sims/worldTickIngest.d.ts +27 -0
  198. package/dist/sims/worldTickIngest.d.ts.map +1 -0
  199. package/dist/sims/worldTickIngest.js +35 -0
  200. package/dist/sims/worldTickLoop.d.ts +64 -0
  201. package/dist/sims/worldTickLoop.d.ts.map +1 -0
  202. package/dist/sims/worldTickLoop.js +122 -0
  203. package/dist/view/engineProvenance.d.ts +46 -0
  204. package/dist/view/engineProvenance.d.ts.map +1 -0
  205. package/dist/view/engineProvenance.js +76 -0
  206. package/dist/view/index.d.ts +14 -0
  207. package/dist/view/index.d.ts.map +1 -0
  208. package/dist/view/index.js +107 -0
  209. package/dist/view/membranes.d.ts +14 -0
  210. package/dist/view/membranes.d.ts.map +1 -0
  211. package/dist/view/membranes.js +127 -0
  212. package/dist/view/runDetect.d.ts +2 -0
  213. package/dist/view/runDetect.d.ts.map +1 -0
  214. package/dist/view/runDetect.js +47 -0
  215. package/dist/view/runRawArtifacts.d.ts +48 -0
  216. package/dist/view/runRawArtifacts.d.ts.map +1 -0
  217. package/dist/view/runRawArtifacts.js +143 -0
  218. package/dist/view/runTimeline.d.ts +24 -0
  219. package/dist/view/runTimeline.d.ts.map +1 -0
  220. package/dist/view/runTimeline.js +204 -0
  221. package/dist/view/runTimelineRecords.d.ts +42 -0
  222. package/dist/view/runTimelineRecords.d.ts.map +1 -0
  223. package/dist/view/runTimelineRecords.js +244 -0
  224. package/dist/view/runTimelineRefs.d.ts +27 -0
  225. package/dist/view/runTimelineRefs.d.ts.map +1 -0
  226. package/dist/view/runTimelineRefs.js +31 -0
  227. package/dist/view/runTimelineTypes.d.ts +99 -0
  228. package/dist/view/runTimelineTypes.d.ts.map +1 -0
  229. package/dist/view/runTimelineTypes.js +1 -0
  230. package/dist/view/runViewModel.d.ts +21 -0
  231. package/dist/view/runViewModel.d.ts.map +1 -0
  232. package/dist/view/runViewModel.js +66 -0
  233. package/dist/view/runViewModelCompute.d.ts +24 -0
  234. package/dist/view/runViewModelCompute.d.ts.map +1 -0
  235. package/dist/view/runViewModelCompute.js +157 -0
  236. package/dist/view/runViewModelTypes.d.ts +177 -0
  237. package/dist/view/runViewModelTypes.d.ts.map +1 -0
  238. package/dist/view/runViewModelTypes.js +1 -0
  239. package/dist/view/runWorldTrace.d.ts +97 -0
  240. package/dist/view/runWorldTrace.d.ts.map +1 -0
  241. package/dist/view/runWorldTrace.js +88 -0
  242. package/dist/view/server.d.ts +12 -0
  243. package/dist/view/server.d.ts.map +1 -0
  244. package/dist/view/server.js +306 -0
  245. package/package.json +65 -0
  246. package/web/dist/assets/index-CJHLjfsG.js +49 -0
  247. package/web/dist/assets/index-DJOsPsU8.css +1 -0
  248. package/web/dist/index.html +13 -0
  249. package/web/dist/models/AnimatedMushnub.glb +0 -0
@@ -0,0 +1,31 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ const sha256Hex = (buffer) => createHash("sha256").update(buffer).digest("hex");
5
+ /**
6
+ * Verifies every manifest-declared artifact's sha256 against the file on
7
+ * disk. A mismatch (or a missing file) is reported as a failed check, never
8
+ * silently repaired or stitched over — the caller decides what to do with a
9
+ * failed integrity check (contracts.md: "missing links are reported, not
10
+ * synthesized" applies just as much to artifact bytes as to causal edges).
11
+ */
12
+ export const verifyManifestArtifacts = async (runDir, artifacts) => {
13
+ const checks = [];
14
+ for (const artifact of artifacts) {
15
+ const absolutePath = path.resolve(runDir, artifact.path);
16
+ try {
17
+ const buffer = await readFile(absolutePath);
18
+ const actualSha256 = sha256Hex(buffer);
19
+ checks.push({
20
+ actualSha256,
21
+ expectedSha256: artifact.sha256,
22
+ ok: actualSha256 === artifact.sha256,
23
+ path: artifact.path
24
+ });
25
+ }
26
+ catch {
27
+ checks.push({ actualSha256: null, expectedSha256: artifact.sha256, ok: false, path: artifact.path });
28
+ }
29
+ }
30
+ return checks;
31
+ };
@@ -0,0 +1,19 @@
1
+ import { type CausalEvent, type CausalJsonlParseError } from "@noopolis/stele";
2
+ export interface CausalStreamSource {
3
+ /** The authority directory name directly under `raw/` (e.g. "moltnet", "daimon", "mneme"). */
4
+ authority: string;
5
+ errors: CausalJsonlParseError[];
6
+ events: CausalEvent[];
7
+ /** Path relative to the run directory. */
8
+ relativePath: string;
9
+ }
10
+ /**
11
+ * Reads and parses every `causal.jsonl` file under `<runDir>/raw/**`,
12
+ * tagging each stream by the authority directory it lives under
13
+ * (`raw/<authority>/...causal.jsonl`). Never reads any other file kind here
14
+ * — that keeps this module a single-purpose causal-stream collector; other
15
+ * per-authority artifacts (transcripts, bank event logs) are read by their
16
+ * own modules.
17
+ */
18
+ export declare const collectCausalStreams: (runDir: string) => Promise<CausalStreamSource[]>;
19
+ //# sourceMappingURL=causalStreams.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"causalStreams.d.ts","sourceRoot":"","sources":["../../src/observe/causalStreams.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,WAAW,EAAE,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAEjG,MAAM,WAAW,kBAAkB;IACjC,8FAA8F;IAC9F,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;CACtB;AAgBD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,kBAAkB,EAAE,CAavF,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { parseCausalJsonl } from "@noopolis/stele";
4
+ const walkFiles = async (root) => {
5
+ const entries = await readdir(root, { withFileTypes: true }).catch(() => []);
6
+ const files = [];
7
+ for (const entry of entries) {
8
+ const entryPath = path.join(root, entry.name);
9
+ if (entry.isDirectory()) {
10
+ files.push(...(await walkFiles(entryPath)));
11
+ }
12
+ else if (entry.isFile()) {
13
+ files.push(entryPath);
14
+ }
15
+ }
16
+ return files;
17
+ };
18
+ /**
19
+ * Reads and parses every `causal.jsonl` file under `<runDir>/raw/**`,
20
+ * tagging each stream by the authority directory it lives under
21
+ * (`raw/<authority>/...causal.jsonl`). Never reads any other file kind here
22
+ * — that keeps this module a single-purpose causal-stream collector; other
23
+ * per-authority artifacts (transcripts, bank event logs) are read by their
24
+ * own modules.
25
+ */
26
+ export const collectCausalStreams = async (runDir) => {
27
+ const rawDir = path.join(runDir, "raw");
28
+ const files = (await walkFiles(rawDir)).filter((file) => file.endsWith("causal.jsonl")).sort();
29
+ const sources = [];
30
+ for (const file of files) {
31
+ const relativePath = path.relative(runDir, file);
32
+ const authority = relativePath.split(path.sep)[1] ?? "unknown";
33
+ const text = await readFile(file, "utf8");
34
+ const { errors, events } = parseCausalJsonl(text);
35
+ sources.push({ authority, errors, events, relativePath });
36
+ }
37
+ return sources;
38
+ };
@@ -0,0 +1,17 @@
1
+ import type { CausalEvent, ReconcileResult } from "@noopolis/stele";
2
+ import type { MemoryBankCounts } from "./memoryBanks.js";
3
+ import type { SimfileRunManifest } from "./manifest.js";
4
+ import { type SimfileObserveReport } from "./report.js";
5
+ import type { SeedSpreadComputeResult } from "./seedSpread.js";
6
+ export interface BuildObserveReportInput {
7
+ allEvents: readonly CausalEvent[];
8
+ manifest: SimfileRunManifest;
9
+ memoryBanks: readonly MemoryBankCounts[];
10
+ reconciled: ReconcileResult;
11
+ /** Memetics increment (b): present only when `manifest.seed_declaration`
12
+ * exists. `excluded` hits (instrument/operator actors) fold into
13
+ * `failures`, never into `seed_spread`. */
14
+ seedSpread?: SeedSpreadComputeResult;
15
+ }
16
+ export declare const buildObserveReport: (input: BuildObserveReportInput) => SimfileObserveReport;
17
+ //# sourceMappingURL=compute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../src/observe/compute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAuB,MAAM,iBAAiB,CAAC;AAEzF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAkD,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxG,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAiG/D,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,SAAS,WAAW,EAAE,CAAC;IAClC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACzC,UAAU,EAAE,eAAe,CAAC;IAC5B;;+CAE2C;IAC3C,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,uBAAuB,KAAG,oBAmBlE,CAAC"}
@@ -0,0 +1,97 @@
1
+ import { OBSERVE_REPORT_VERSION } from "./report.js";
2
+ const FAILURE_TYPES = new Set(["turn.failed", "wake.failed"]);
3
+ const AGENT_PRINCIPAL_PATTERN = /^agent:(.+)$/u;
4
+ const agentIdFromStreamId = (streamId) => streamId.replace(/^agent:/u, "");
5
+ /**
6
+ * Orders an agent's `turn.output.completed` events by the moltnet message
7
+ * seq that triggered the underlying turn (never `recorded_at`): each
8
+ * `turn.input.submitted` carries `payload.input_message_ids`, the message
9
+ * event ids that caused it; resolving those back to moltnet's own
10
+ * per-stream `emitter.seq` gives a causal, non-wall-clock ordering.
11
+ */
12
+ const triggeringMoltnetSeq = (inputEvent, byEventId) => {
13
+ const messageIds = inputEvent?.payload.input_message_ids;
14
+ if (!Array.isArray(messageIds))
15
+ return undefined;
16
+ let minSeq;
17
+ for (const messageId of messageIds) {
18
+ if (typeof messageId !== "string")
19
+ continue;
20
+ const message = byEventId.get(messageId);
21
+ if (!message || message.emitter.system !== "moltnet")
22
+ continue;
23
+ minSeq = minSeq === undefined ? message.emitter.seq : Math.min(minSeq, message.emitter.seq);
24
+ }
25
+ return minSeq;
26
+ };
27
+ const computeParticipants = (events) => {
28
+ const participants = new Set();
29
+ for (const event of events) {
30
+ const match = AGENT_PRINCIPAL_PATTERN.exec(event.principal_id);
31
+ if (match?.[1])
32
+ participants.add(match[1]);
33
+ }
34
+ return [...participants].sort();
35
+ };
36
+ const computeAgentTurns = (events) => {
37
+ const byEventId = new Map(events.map((event) => [event.event_id, event]));
38
+ const turnOutputs = events.filter((event) => event.emitter.system === "daimon" && event.type === "turn.output.completed");
39
+ const ordered = turnOutputs
40
+ .map((turnOutput) => {
41
+ const inputEventId = turnOutput.cause_event_ids.find((causeId) => {
42
+ const cause = byEventId.get(causeId);
43
+ return cause?.emitter.system === "daimon" && cause.type === "turn.input.submitted";
44
+ });
45
+ const inputEvent = inputEventId ? byEventId.get(inputEventId) : undefined;
46
+ return {
47
+ agentId: agentIdFromStreamId(turnOutput.emitter.stream_id),
48
+ eventId: turnOutput.event_id,
49
+ seq: triggeringMoltnetSeq(inputEvent, byEventId)
50
+ };
51
+ })
52
+ .sort((left, right) => {
53
+ const leftSeq = left.seq ?? Number.POSITIVE_INFINITY;
54
+ const rightSeq = right.seq ?? Number.POSITIVE_INFINITY;
55
+ return leftSeq - rightSeq || left.eventId.localeCompare(right.eventId);
56
+ });
57
+ return { count: ordered.length, sequence: ordered.map((entry) => entry.agentId) };
58
+ };
59
+ const computeChains = (reconciled) => {
60
+ let complete = 0;
61
+ const incomplete = [];
62
+ for (const [eventId, record] of reconciled.byEventId) {
63
+ if (record.state === "complete") {
64
+ complete += 1;
65
+ continue;
66
+ }
67
+ incomplete.push({ event_id: eventId, flag: record.state });
68
+ }
69
+ incomplete.sort((left, right) => left.event_id.localeCompare(right.event_id));
70
+ return { complete, incomplete };
71
+ };
72
+ const computeFailures = (events) => events
73
+ .filter((event) => FAILURE_TYPES.has(event.type))
74
+ .map((event) => ({
75
+ event_id: event.event_id,
76
+ reason: typeof event.payload.reason === "string" ? event.payload.reason : event.type
77
+ }));
78
+ export const buildObserveReport = (input) => ({
79
+ version: OBSERVE_REPORT_VERSION,
80
+ run_id: input.manifest.run_id,
81
+ contract_versions: input.manifest.contract_versions,
82
+ participants: computeParticipants(input.allEvents),
83
+ agent_turns: computeAgentTurns(input.allEvents),
84
+ chains: computeChains(input.reconciled),
85
+ memory: input.memoryBanks.map((bank) => ({
86
+ bank: bank.bank,
87
+ events: bank.events,
88
+ recalls: bank.recalls,
89
+ memory_write_source: bank.memory_write_source,
90
+ ...(bank.writes_by_agent ? { writes_by_agent: bank.writes_by_agent } : {})
91
+ })),
92
+ failures: [
93
+ ...computeFailures(input.allEvents),
94
+ ...(input.seedSpread?.excluded.map((excluded) => ({ event_id: excluded.event_id, reason: excluded.reason })) ?? [])
95
+ ],
96
+ ...(input.seedSpread ? { seed_spread: input.seedSpread.entries, spread_summary: input.seedSpread.summary } : {})
97
+ });
@@ -0,0 +1,11 @@
1
+ export * from "./artifacts.js";
2
+ export * from "./causalStreams.js";
3
+ export * from "./compute.js";
4
+ export * from "./manifest.js";
5
+ export * from "./memoryBanks.js";
6
+ export * from "./observe.js";
7
+ export * from "./report.js";
8
+ export * from "./seedSpread.js";
9
+ export * from "./seedSpreadArtifacts.js";
10
+ export * from "./spreadMatcher.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observe/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export * from "./artifacts.js";
2
+ export * from "./causalStreams.js";
3
+ export * from "./compute.js";
4
+ export * from "./manifest.js";
5
+ export * from "./memoryBanks.js";
6
+ export * from "./observe.js";
7
+ export * from "./report.js";
8
+ export * from "./seedSpread.js";
9
+ export * from "./seedSpreadArtifacts.js";
10
+ export * from "./spreadMatcher.js";
@@ -0,0 +1,79 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * `simfile.run-manifest.v1` — the composite run manifest simfile writes for
4
+ * a run's directory (Decision 21 / contracts.md's `simfile.run-manifest.v1`
5
+ * row). `seed_declaration` and `expected_wakes` are DEFINED-BUT-OPTIONAL:
6
+ * office-sim runs omit both (no seeded secret, no compiled wake schedule to
7
+ * diff against yet), so a manifest without them is still fully conformant.
8
+ * A future memetics phase (Phase G) populates both without a v2 bump.
9
+ */
10
+ export declare const RUN_MANIFEST_VERSION: "simfile.run-manifest.v1";
11
+ declare const artifactEntrySchema: z.ZodObject<{
12
+ path: z.ZodString;
13
+ sha256: z.ZodString;
14
+ }, z.core.$strict>;
15
+ export type RunManifestArtifactEntry = z.infer<typeof artifactEntrySchema>;
16
+ /**
17
+ * The observer's ground truth for a seeded memetics secret (contracts.md
18
+ * "measurement-critical contracts" section). `matcher_policy` is kept as a
19
+ * documented free-form string rather than a tight enum: the named policies
20
+ * (`exact` / `edit-distance:<k>` / `embedding` / `judge`) may carry pinned
21
+ * experiment parameters. `spreadMatcher.ts` validates and dispatches this
22
+ * field; model-backed policies fail loudly in builds without those models.
23
+ */
24
+ declare const seedDeclarationSchema: z.ZodObject<{
25
+ content_hash: z.ZodString;
26
+ token_set: z.ZodArray<z.ZodString>;
27
+ matcher_policy: z.ZodString;
28
+ seed_agent: z.ZodString;
29
+ seed_epoch: z.ZodString;
30
+ entry_channel: z.ZodLiteral<"doc-seeded">;
31
+ }, z.core.$strict>;
32
+ export type SeedDeclaration = z.infer<typeof seedDeclarationSchema>;
33
+ /**
34
+ * One compiled schedule fire simfile expects to observe within the run's
35
+ * sim-time window (the denominator oracle for the 100%-reply-or-recover
36
+ * bar, contracts.md). Kept minimal and generic: the compiled-schedule ->
37
+ * wake-diff lowering is Phase 7 scope (Decision 21's phasing), so this only
38
+ * carries what `simfile observe`'s wake-diff will need to match against —
39
+ * which agent, which wake, and when.
40
+ */
41
+ declare const expectedWakeSchema: z.ZodObject<{
42
+ agent_id: z.ZodString;
43
+ wake_id: z.ZodString;
44
+ sim_time: z.ZodOptional<z.ZodNumber>;
45
+ }, z.core.$strict>;
46
+ export type ExpectedWake = z.infer<typeof expectedWakeSchema>;
47
+ export declare const runManifestSchema: z.ZodObject<{
48
+ version: z.ZodLiteral<"simfile.run-manifest.v1">;
49
+ run_id: z.ZodString;
50
+ created_at: z.ZodString;
51
+ contract_versions: z.ZodRecord<z.ZodString, z.ZodString>;
52
+ spawnfile: z.ZodOptional<z.ZodObject<{
53
+ up_receipt_ref: z.ZodOptional<z.ZodString>;
54
+ fingerprint: z.ZodOptional<z.ZodString>;
55
+ }, z.core.$strict>>;
56
+ artifacts: z.ZodArray<z.ZodObject<{
57
+ path: z.ZodString;
58
+ sha256: z.ZodString;
59
+ }, z.core.$strict>>;
60
+ engine: z.ZodOptional<z.ZodString>;
61
+ world: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
62
+ seed_declaration: z.ZodOptional<z.ZodObject<{
63
+ content_hash: z.ZodString;
64
+ token_set: z.ZodArray<z.ZodString>;
65
+ matcher_policy: z.ZodString;
66
+ seed_agent: z.ZodString;
67
+ seed_epoch: z.ZodString;
68
+ entry_channel: z.ZodLiteral<"doc-seeded">;
69
+ }, z.core.$strict>>;
70
+ expected_wakes: z.ZodOptional<z.ZodArray<z.ZodObject<{
71
+ agent_id: z.ZodString;
72
+ wake_id: z.ZodString;
73
+ sim_time: z.ZodOptional<z.ZodNumber>;
74
+ }, z.core.$strict>>>;
75
+ }, z.core.$strict>;
76
+ export type SimfileRunManifest = z.infer<typeof runManifestSchema>;
77
+ export declare const parseRunManifest: (raw: unknown) => SimfileRunManifest;
78
+ export {};
79
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/observe/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,EAAG,yBAAkC,CAAC;AAEvE,QAAA,MAAM,mBAAmB;;;kBAKd,CAAC;AAEZ,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAS3E;;;;;;;GAOG;AACH,QAAA,MAAM,qBAAqB;;;;;;;kBAShB,CAAC;AAEZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;;;GAOG;AACH,QAAA,MAAM,kBAAkB;;;;kBAMb,CAAC;AAEZ,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAsB1B,CAAC;AAEL,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEnE,eAAO,MAAM,gBAAgB,GAAI,KAAK,OAAO,KAAG,kBAU/C,CAAC"}
@@ -0,0 +1,87 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * `simfile.run-manifest.v1` — the composite run manifest simfile writes for
4
+ * a run's directory (Decision 21 / contracts.md's `simfile.run-manifest.v1`
5
+ * row). `seed_declaration` and `expected_wakes` are DEFINED-BUT-OPTIONAL:
6
+ * office-sim runs omit both (no seeded secret, no compiled wake schedule to
7
+ * diff against yet), so a manifest without them is still fully conformant.
8
+ * A future memetics phase (Phase G) populates both without a v2 bump.
9
+ */
10
+ export const RUN_MANIFEST_VERSION = "simfile.run-manifest.v1";
11
+ const artifactEntrySchema = z
12
+ .object({
13
+ path: z.string().min(1),
14
+ sha256: z.string().regex(/^[0-9a-f]{64}$/u, "sha256 must be a 64-character lowercase hex digest")
15
+ })
16
+ .strict();
17
+ const spawnfileRefSchema = z
18
+ .object({
19
+ up_receipt_ref: z.string().min(1).optional(),
20
+ fingerprint: z.string().min(1).optional()
21
+ })
22
+ .strict();
23
+ /**
24
+ * The observer's ground truth for a seeded memetics secret (contracts.md
25
+ * "measurement-critical contracts" section). `matcher_policy` is kept as a
26
+ * documented free-form string rather than a tight enum: the named policies
27
+ * (`exact` / `edit-distance:<k>` / `embedding` / `judge`) may carry pinned
28
+ * experiment parameters. `spreadMatcher.ts` validates and dispatches this
29
+ * field; model-backed policies fail loudly in builds without those models.
30
+ */
31
+ const seedDeclarationSchema = z
32
+ .object({
33
+ content_hash: z.string().min(1),
34
+ token_set: z.array(z.string().min(1)),
35
+ matcher_policy: z.string().min(1),
36
+ seed_agent: z.string().min(1),
37
+ seed_epoch: z.string().min(1),
38
+ entry_channel: z.literal("doc-seeded")
39
+ })
40
+ .strict();
41
+ /**
42
+ * One compiled schedule fire simfile expects to observe within the run's
43
+ * sim-time window (the denominator oracle for the 100%-reply-or-recover
44
+ * bar, contracts.md). Kept minimal and generic: the compiled-schedule ->
45
+ * wake-diff lowering is Phase 7 scope (Decision 21's phasing), so this only
46
+ * carries what `simfile observe`'s wake-diff will need to match against —
47
+ * which agent, which wake, and when.
48
+ */
49
+ const expectedWakeSchema = z
50
+ .object({
51
+ agent_id: z.string().min(1),
52
+ wake_id: z.string().min(1),
53
+ sim_time: z.number().optional()
54
+ })
55
+ .strict();
56
+ export const runManifestSchema = z
57
+ .object({
58
+ version: z.literal(RUN_MANIFEST_VERSION),
59
+ run_id: z.string().min(1),
60
+ created_at: z.string().min(1),
61
+ contract_versions: z.record(z.string(), z.string()),
62
+ spawnfile: spawnfileRefSchema.optional(),
63
+ artifacts: z.array(artifactEntrySchema),
64
+ engine: z.string().min(1).optional(),
65
+ world: z.record(z.string(), z.unknown()).optional(),
66
+ seed_declaration: seedDeclarationSchema.optional(),
67
+ expected_wakes: z.array(expectedWakeSchema).optional()
68
+ })
69
+ .strict()
70
+ .superRefine((value, context) => {
71
+ if (Number.isNaN(Date.parse(value.created_at))) {
72
+ context.addIssue({
73
+ code: z.ZodIssueCode.custom,
74
+ message: "created_at must be a valid ISO 8601 timestamp",
75
+ path: ["created_at"]
76
+ });
77
+ }
78
+ });
79
+ export const parseRunManifest = (raw) => {
80
+ const result = runManifestSchema.safeParse(raw);
81
+ if (!result.success) {
82
+ throw new Error(`invalid ${RUN_MANIFEST_VERSION} manifest: ${result.error.issues
83
+ .map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
84
+ .join("; ")}`);
85
+ }
86
+ return result.data;
87
+ };
@@ -0,0 +1,38 @@
1
+ import type { CausalEvent } from "@noopolis/stele";
2
+ import type { MemoryWriteSource } from "./report.js";
3
+ export interface MemoryBankCounts {
4
+ bank: string;
5
+ events: number;
6
+ recalls: number;
7
+ memory_write_source: MemoryWriteSource;
8
+ /** Per-agent write counts, derived from `memory.written`'s `principal_id`. Only set on the ledger path. */
9
+ writes_by_agent?: Record<string, number>;
10
+ }
11
+ /**
12
+ * Derives each mneme bank's memory-write count, per-agent write signal, and
13
+ * recall count.
14
+ *
15
+ * Ledger-first (Slice B Piece 4b): mneme stamps a `memory.written` causal
16
+ * event (`noopolis.causal-event.v1`, same `memory/causal.jsonl` stream as
17
+ * `memory.recalled`) on every durable memory register, with
18
+ * `cause_event_ids` chaining it to the wake/turn that produced it. When a
19
+ * bank's reconciled causal stream (`causalEventsByBank`) contains at least
20
+ * one `memory.written` event, that count is authoritative
21
+ * (`memory_write_source: "ledger"`), and `writes_by_agent` is derived from
22
+ * each event's `principal_id`.
23
+ *
24
+ * Fallback (pre-4b runs, e.g. the office-sim golden fixture captured before
25
+ * mneme shipped the write-side event): if a bank's causal stream has ZERO
26
+ * `memory.written` events, this falls back to the interim signal — mneme's
27
+ * own `raw/mneme/<bank>/events.jsonl` bank event log (line count as the
28
+ * write proxy) — marking `memory_write_source: "events-fallback"` so a
29
+ * stale run is visibly on the fallback, never silently. If neither
30
+ * `events.jsonl` nor any `memory.written` event exists, `events` is 0.
31
+ *
32
+ * `recalls` is unaffected by which write source wins: it always prefers
33
+ * `events.jsonl`'s own `memory.recalled` lines when the file exists, falling
34
+ * back to the bank's `memory.recalled` causal events otherwise — the same
35
+ * behavior this function had before Piece 4b.
36
+ */
37
+ export declare const collectMemoryBankCounts: (runDir: string, causalEventsByBank: ReadonlyMap<string, CausalEvent[]>) => Promise<MemoryBankCounts[]>;
38
+ //# sourceMappingURL=memoryBanks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoryBanks.d.ts","sourceRoot":"","sources":["../../src/observe/memoryBanks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,iBAAiB,CAAC;IACvC,2GAA2G;IAC3G,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AA6BD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,MAAM,EACd,oBAAoB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,KACrD,OAAO,CAAC,gBAAgB,EAAE,CAwC5B,CAAC"}
@@ -0,0 +1,86 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ const AGENT_PRINCIPAL_PATTERN = /^agent:(.+)$/u;
4
+ const countJsonlLines = (content) => content
5
+ .split(/\r?\n/u)
6
+ .map((line) => line.trim())
7
+ .filter((line) => line.length > 0);
8
+ const countRecallsFromEventsJsonl = (lines) => lines.filter((line) => {
9
+ try {
10
+ return JSON.parse(line).type === "memory.recalled";
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ }).length;
16
+ const countByAgent = (events) => {
17
+ const counts = {};
18
+ for (const event of events) {
19
+ const agentId = AGENT_PRINCIPAL_PATTERN.exec(event.principal_id)?.[1];
20
+ if (!agentId)
21
+ continue;
22
+ counts[agentId] = (counts[agentId] ?? 0) + 1;
23
+ }
24
+ return counts;
25
+ };
26
+ /**
27
+ * Derives each mneme bank's memory-write count, per-agent write signal, and
28
+ * recall count.
29
+ *
30
+ * Ledger-first (Slice B Piece 4b): mneme stamps a `memory.written` causal
31
+ * event (`noopolis.causal-event.v1`, same `memory/causal.jsonl` stream as
32
+ * `memory.recalled`) on every durable memory register, with
33
+ * `cause_event_ids` chaining it to the wake/turn that produced it. When a
34
+ * bank's reconciled causal stream (`causalEventsByBank`) contains at least
35
+ * one `memory.written` event, that count is authoritative
36
+ * (`memory_write_source: "ledger"`), and `writes_by_agent` is derived from
37
+ * each event's `principal_id`.
38
+ *
39
+ * Fallback (pre-4b runs, e.g. the office-sim golden fixture captured before
40
+ * mneme shipped the write-side event): if a bank's causal stream has ZERO
41
+ * `memory.written` events, this falls back to the interim signal — mneme's
42
+ * own `raw/mneme/<bank>/events.jsonl` bank event log (line count as the
43
+ * write proxy) — marking `memory_write_source: "events-fallback"` so a
44
+ * stale run is visibly on the fallback, never silently. If neither
45
+ * `events.jsonl` nor any `memory.written` event exists, `events` is 0.
46
+ *
47
+ * `recalls` is unaffected by which write source wins: it always prefers
48
+ * `events.jsonl`'s own `memory.recalled` lines when the file exists, falling
49
+ * back to the bank's `memory.recalled` causal events otherwise — the same
50
+ * behavior this function had before Piece 4b.
51
+ */
52
+ export const collectMemoryBankCounts = async (runDir, causalEventsByBank) => {
53
+ const mnemeDir = path.join(runDir, "raw", "mneme");
54
+ const bankDirs = await readdir(mnemeDir, { withFileTypes: true }).catch(() => []);
55
+ const results = [];
56
+ for (const entry of bankDirs) {
57
+ if (!entry.isDirectory())
58
+ continue;
59
+ const bank = entry.name;
60
+ const bankCausalEvents = causalEventsByBank.get(bank) ?? [];
61
+ const eventsPath = path.join(mnemeDir, bank, "events.jsonl");
62
+ const eventsText = await readFile(eventsPath, "utf8").catch(() => null);
63
+ const eventsJsonlLines = eventsText !== null ? countJsonlLines(eventsText) : null;
64
+ const recalls = eventsJsonlLines !== null
65
+ ? countRecallsFromEventsJsonl(eventsJsonlLines)
66
+ : bankCausalEvents.filter((event) => event.type === "memory.recalled").length;
67
+ const ledgerWrites = bankCausalEvents.filter((event) => event.type === "memory.written");
68
+ if (ledgerWrites.length > 0) {
69
+ results.push({
70
+ bank,
71
+ events: ledgerWrites.length,
72
+ recalls,
73
+ memory_write_source: "ledger",
74
+ writes_by_agent: countByAgent(ledgerWrites)
75
+ });
76
+ continue;
77
+ }
78
+ results.push({
79
+ bank,
80
+ events: eventsJsonlLines !== null ? eventsJsonlLines.length : 0,
81
+ recalls,
82
+ memory_write_source: "events-fallback"
83
+ });
84
+ }
85
+ return results.sort((left, right) => left.bank.localeCompare(right.bank));
86
+ };
@@ -0,0 +1,32 @@
1
+ import type { ArtifactIntegrityCheck } from "./artifacts.js";
2
+ import type { CausalStreamSource } from "./causalStreams.js";
3
+ import type { SimfileRunManifest } from "./manifest.js";
4
+ import type { SimfileObserveReport } from "./report.js";
5
+ import { type SeedSpreadSelfCheck } from "./seedSpread.js";
6
+ export interface ObserveResult {
7
+ artifactIntegrity: ArtifactIntegrityCheck[];
8
+ causalParseErrors: {
9
+ relativePath: string;
10
+ line: number;
11
+ message: string;
12
+ }[];
13
+ manifest: SimfileRunManifest;
14
+ report: SimfileObserveReport;
15
+ streams: CausalStreamSource[];
16
+ /** Memetics increment (b): present only when `manifest.seed_declaration`
17
+ * exists — the live-`marker.seen` self-check, diagnostic only (never fed
18
+ * into `report.seed_spread`, see `seedSpread.ts`'s own doc comment). */
19
+ spreadSelfCheck?: SeedSpreadSelfCheck;
20
+ }
21
+ /**
22
+ * Reads a sealed run directory (`manifest.json` + `raw/**\/causal.jsonl` +
23
+ * per-bank `raw/mneme/<bank>/events.jsonl`), reconciles the causal streams
24
+ * with `@noopolis/stele` (no stitching, ever — an incomplete chain is
25
+ * flagged, not synthesized), and emits the `simfile.observe.v1` report.
26
+ * Pure file-reading + reconciliation: no Docker, no compile, no runtime
27
+ * auth (this package's charter, `ecosystem/simfile/AGENTS.md`).
28
+ */
29
+ export declare const runObserve: (runDir: string) => Promise<ObserveResult>;
30
+ /** Writes `observe/report.json` under the run directory; returns its path. */
31
+ export declare const writeObserveReport: (runDir: string, report: SimfileObserveReport) => Promise<string>;
32
+ //# sourceMappingURL=observe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../src/observe/observe.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAI7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAA0D,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAOnH,MAAM,WAAW,aAAa;IAC5B,iBAAiB,EAAE,sBAAsB,EAAE,CAAC;IAC5C,iBAAiB,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7E,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B;;4EAEwE;IACxE,eAAe,CAAC,EAAE,mBAAmB,CAAC;CACvC;AAaD;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,aAAa,CAmDtE,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,GAAU,QAAQ,MAAM,EAAE,QAAQ,oBAAoB,KAAG,OAAO,CAAC,MAAM,CAMrG,CAAC"}
@@ -0,0 +1,73 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { reconcileEvents } from "@noopolis/stele";
4
+ import { verifyManifestArtifacts } from "./artifacts.js";
5
+ import { collectCausalStreams } from "./causalStreams.js";
6
+ import { buildObserveReport } from "./compute.js";
7
+ import { collectMemoryBankCounts } from "./memoryBanks.js";
8
+ import { parseRunManifest } from "./manifest.js";
9
+ import { computeSeedSpread, diffSeedSpreadAgainstLiveMarkerSeen } from "./seedSpread.js";
10
+ import { readSpreadTranscriptMessages, readTickByIngestedMessageId, readSpreadMnemeEventsByBank } from "./seedSpreadArtifacts.js";
11
+ const loadRunManifest = async (runDir) => {
12
+ const raw = JSON.parse(await readFile(path.join(runDir, "manifest.json"), "utf8"));
13
+ return parseRunManifest(raw);
14
+ };
15
+ const bankFromRelativePath = (relativePath) => {
16
+ // raw/mneme/<bank>/causal.jsonl
17
+ const segments = relativePath.split(path.sep);
18
+ return segments[0] === "raw" && segments[1] === "mneme" ? segments[2] : undefined;
19
+ };
20
+ /**
21
+ * Reads a sealed run directory (`manifest.json` + `raw/**\/causal.jsonl` +
22
+ * per-bank `raw/mneme/<bank>/events.jsonl`), reconciles the causal streams
23
+ * with `@noopolis/stele` (no stitching, ever — an incomplete chain is
24
+ * flagged, not synthesized), and emits the `simfile.observe.v1` report.
25
+ * Pure file-reading + reconciliation: no Docker, no compile, no runtime
26
+ * auth (this package's charter, `ecosystem/simfile/AGENTS.md`).
27
+ */
28
+ export const runObserve = async (runDir) => {
29
+ const manifest = await loadRunManifest(runDir);
30
+ const artifactIntegrity = await verifyManifestArtifacts(runDir, manifest.artifacts);
31
+ const streams = await collectCausalStreams(runDir);
32
+ const causalParseErrors = streams.flatMap((stream) => stream.errors.map((error) => ({ relativePath: stream.relativePath, ...error })));
33
+ const allEvents = streams.flatMap((stream) => stream.events);
34
+ const reconciled = reconcileEvents(allEvents);
35
+ const eventsByBank = new Map();
36
+ for (const stream of streams) {
37
+ const bank = bankFromRelativePath(stream.relativePath);
38
+ if (!bank)
39
+ continue;
40
+ eventsByBank.set(bank, [...(eventsByBank.get(bank) ?? []), ...stream.events]);
41
+ }
42
+ const memoryBanks = await collectMemoryBankCounts(runDir, eventsByBank);
43
+ let seedSpread;
44
+ let spreadSelfCheck;
45
+ if (manifest.seed_declaration) {
46
+ const [transcriptMessages, mnemeEventsByBank, tickByMoltnetMessageId] = await Promise.all([
47
+ readSpreadTranscriptMessages(runDir),
48
+ readSpreadMnemeEventsByBank(runDir),
49
+ readTickByIngestedMessageId(runDir)
50
+ ]);
51
+ const causalEventsById = new Map(allEvents.map((event) => [event.event_id, event]));
52
+ seedSpread = computeSeedSpread({
53
+ seedDeclaration: manifest.seed_declaration,
54
+ causalEventsById,
55
+ transcriptMessages,
56
+ causalEventsByBank: eventsByBank,
57
+ mnemeEventsByBank,
58
+ tickByMoltnetMessageId
59
+ });
60
+ const worldEvents = streams.filter((stream) => stream.authority === "world").flatMap((stream) => stream.events);
61
+ spreadSelfCheck = diffSeedSpreadAgainstLiveMarkerSeen(worldEvents, transcriptMessages, manifest.seed_declaration.token_set, manifest.seed_declaration.matcher_policy);
62
+ }
63
+ const report = buildObserveReport({ allEvents, manifest, memoryBanks, reconciled, seedSpread });
64
+ return { artifactIntegrity, causalParseErrors, manifest, report, streams, spreadSelfCheck };
65
+ };
66
+ /** Writes `observe/report.json` under the run directory; returns its path. */
67
+ export const writeObserveReport = async (runDir, report) => {
68
+ const observeDir = path.join(runDir, "observe");
69
+ await mkdir(observeDir, { recursive: true });
70
+ const reportPath = path.join(observeDir, "report.json");
71
+ await writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
72
+ return reportPath;
73
+ };