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,165 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * `simfile.observe.v1` — the report `simfile observe <run-dir>` emits
4
+ * (Decision 21 / contracts.md's `simfile.observe.v1` row, the one contract
5
+ * id: `spawnfile.spread-report.v1` is a removed alias, never revived here).
6
+ * `seed_spread`, `spread_summary`, and `wake_diff` are DEFINED-BUT-OPTIONAL
7
+ * and omitted for the office-sim golden fixture (no seeded secret, no
8
+ * compiled wake schedule); memetics increment (b) populates `seed_spread`/
9
+ * `spread_summary` for a seed-declared run without a v2 bump.
10
+ */
11
+ export declare const OBSERVE_REPORT_VERSION: "simfile.observe.v1";
12
+ /** Precedence order matches `@noopolis/stele`'s `reconcileEvents` states,
13
+ * minus "complete" (that count lives in `chains.complete`, not the flagged list). */
14
+ export declare const INCOMPLETE_CHAIN_FLAGS: readonly ["divergent", "unknown", "partial", "stale"];
15
+ export type IncompleteChainFlag = (typeof INCOMPLETE_CHAIN_FLAGS)[number];
16
+ /**
17
+ * Where `memory.events` (the write-count proxy) for a bank came from —
18
+ * Slice B Piece 4b. `"ledger"` means at least one `memory.written` causal
19
+ * event was reconciled for the bank (mneme's write-side envelope);
20
+ * `"events-fallback"` means the count instead came from the interim signal
21
+ * (mneme's own `events.jsonl` bank log, or that bank's `memory.recalled`
22
+ * causal events if even that is absent). Optional so a pre-4b serialized
23
+ * report (no source marker at all) still validates.
24
+ */
25
+ export declare const MEMORY_WRITE_SOURCES: readonly ["ledger", "events-fallback"];
26
+ export type MemoryWriteSource = (typeof MEMORY_WRITE_SOURCES)[number];
27
+ /** `doc-seeded` is added (contracts.md) so a seed's entry channel is
28
+ * representable and never misclassified as spontaneous invention. */
29
+ export declare const SEED_SPREAD_CHANNELS: readonly ["doc-seeded", "uttered", "registered", "recalled"];
30
+ export type SeedSpreadChannel = (typeof SEED_SPREAD_CHANNELS)[number];
31
+ /**
32
+ * Memetics increment (b): `agent`/`tick`/`memory_write_source` are a
33
+ * compatible v1 amendment (`seed_spread` was frozen DEFINED-BUT-OPTIONAL
34
+ * precisely so a later phase could grow the entry shape without a v2 bump).
35
+ * `agent` is the principal simfile observe attributes the hit to (never the
36
+ * seed agent for a `doc-seeded` entry's own later channels — reach/latency
37
+ * math excludes the seed agent, this field alone doesn't). `tick` is the
38
+ * world's own tick counter, joined from `world/ingested-messages.jsonl`
39
+ * (an `uttered` hit) or traced back to the moltnet message that caused it
40
+ * (a `registered`/`recalled` hit whose ledger event chains back that far) —
41
+ * never fabricated; omitted when no such join exists. `memory_write_source`
42
+ * mirrors `MemoryWriteSource` (Slice B Piece 4b) but scoped to this single
43
+ * `registered` hit, not a whole bank.
44
+ */
45
+ declare const seedSpreadSchema: z.ZodObject<{
46
+ channel: z.ZodEnum<{
47
+ "doc-seeded": "doc-seeded";
48
+ uttered: "uttered";
49
+ registered: "registered";
50
+ recalled: "recalled";
51
+ }>;
52
+ event_id: z.ZodString;
53
+ fidelity: z.ZodOptional<z.ZodNumber>;
54
+ agent: z.ZodOptional<z.ZodString>;
55
+ tick: z.ZodOptional<z.ZodNumber>;
56
+ memory_write_source: z.ZodOptional<z.ZodEnum<{
57
+ ledger: "ledger";
58
+ "events-fallback": "events-fallback";
59
+ }>>;
60
+ }, z.core.$strict>;
61
+ export type SeedSpreadEntry = z.infer<typeof seedSpreadSchema>;
62
+ /**
63
+ * The smallest honest summary of `seed_spread` (memetics increment (b)):
64
+ * `reach` counts non-seed agents with any post-seed appearance; `latency`
65
+ * is the lowest known `tick` among those appearances (omitted when no
66
+ * appearance carries a `tick`) — ticks/causal steps from the seed epoch to
67
+ * first spread, never wall-clock. Derivable from `seed_spread` alone, but
68
+ * kept as its own field so a consumer (the viewer) doesn't have to
69
+ * re-implement the derivation.
70
+ */
71
+ declare const spreadSummarySchema: z.ZodObject<{
72
+ reach: z.ZodNumber;
73
+ latency: z.ZodOptional<z.ZodNumber>;
74
+ first_appearance: z.ZodArray<z.ZodObject<{
75
+ agent: z.ZodString;
76
+ channel: z.ZodEnum<{
77
+ "doc-seeded": "doc-seeded";
78
+ uttered: "uttered";
79
+ registered: "registered";
80
+ recalled: "recalled";
81
+ }>;
82
+ event_id: z.ZodString;
83
+ tick: z.ZodOptional<z.ZodNumber>;
84
+ }, z.core.$strict>>;
85
+ }, z.core.$strict>;
86
+ export type SpreadSummary = z.infer<typeof spreadSummarySchema>;
87
+ export declare const observeReportSchema: z.ZodObject<{
88
+ version: z.ZodLiteral<"simfile.observe.v1">;
89
+ run_id: z.ZodString;
90
+ contract_versions: z.ZodRecord<z.ZodString, z.ZodString>;
91
+ participants: z.ZodArray<z.ZodString>;
92
+ agent_turns: z.ZodObject<{
93
+ count: z.ZodNumber;
94
+ sequence: z.ZodArray<z.ZodString>;
95
+ }, z.core.$strict>;
96
+ chains: z.ZodObject<{
97
+ complete: z.ZodNumber;
98
+ incomplete: z.ZodArray<z.ZodObject<{
99
+ event_id: z.ZodString;
100
+ flag: z.ZodEnum<{
101
+ unknown: "unknown";
102
+ divergent: "divergent";
103
+ partial: "partial";
104
+ stale: "stale";
105
+ }>;
106
+ }, z.core.$strict>>;
107
+ }, z.core.$strict>;
108
+ memory: z.ZodArray<z.ZodObject<{
109
+ bank: z.ZodString;
110
+ events: z.ZodNumber;
111
+ recalls: z.ZodNumber;
112
+ memory_write_source: z.ZodOptional<z.ZodEnum<{
113
+ ledger: "ledger";
114
+ "events-fallback": "events-fallback";
115
+ }>>;
116
+ writes_by_agent: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
117
+ }, z.core.$strict>>;
118
+ failures: z.ZodArray<z.ZodObject<{
119
+ reason: z.ZodString;
120
+ event_id: z.ZodString;
121
+ }, z.core.$strict>>;
122
+ seed_spread: z.ZodOptional<z.ZodArray<z.ZodObject<{
123
+ channel: z.ZodEnum<{
124
+ "doc-seeded": "doc-seeded";
125
+ uttered: "uttered";
126
+ registered: "registered";
127
+ recalled: "recalled";
128
+ }>;
129
+ event_id: z.ZodString;
130
+ fidelity: z.ZodOptional<z.ZodNumber>;
131
+ agent: z.ZodOptional<z.ZodString>;
132
+ tick: z.ZodOptional<z.ZodNumber>;
133
+ memory_write_source: z.ZodOptional<z.ZodEnum<{
134
+ ledger: "ledger";
135
+ "events-fallback": "events-fallback";
136
+ }>>;
137
+ }, z.core.$strict>>>;
138
+ spread_summary: z.ZodOptional<z.ZodObject<{
139
+ reach: z.ZodNumber;
140
+ latency: z.ZodOptional<z.ZodNumber>;
141
+ first_appearance: z.ZodArray<z.ZodObject<{
142
+ agent: z.ZodString;
143
+ channel: z.ZodEnum<{
144
+ "doc-seeded": "doc-seeded";
145
+ uttered: "uttered";
146
+ registered: "registered";
147
+ recalled: "recalled";
148
+ }>;
149
+ event_id: z.ZodString;
150
+ tick: z.ZodOptional<z.ZodNumber>;
151
+ }, z.core.$strict>>;
152
+ }, z.core.$strict>>;
153
+ wake_diff: z.ZodOptional<z.ZodArray<z.ZodObject<{
154
+ agent_id: z.ZodString;
155
+ wake_id: z.ZodString;
156
+ status: z.ZodEnum<{
157
+ delivered: "delivered";
158
+ "wake-not-delivered": "wake-not-delivered";
159
+ }>;
160
+ }, z.core.$strict>>>;
161
+ }, z.core.$strict>;
162
+ export type SimfileObserveReport = z.infer<typeof observeReportSchema>;
163
+ export declare const parseObserveReport: (raw: unknown) => SimfileObserveReport;
164
+ export {};
165
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/observe/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,EAAG,oBAA6B,CAAC;AAEpE;qFACqF;AACrF,eAAO,MAAM,sBAAsB,uDAAwD,CAAC;AAC5F,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAS1E;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,wCAAyC,CAAC;AAC3E,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAmBtE;qEACqE;AACrE,eAAO,MAAM,oBAAoB,8DAA+D,CAAC;AACjG,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;kBASX,CAAC;AAEZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAY/D;;;;;;;;GAQG;AACH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;kBAMd,CAAC;AAEZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAUhE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAwBrB,CAAC;AAEZ,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEvE,eAAO,MAAM,kBAAkB,GAAI,KAAK,OAAO,KAAG,oBAUjD,CAAC"}
@@ -0,0 +1,138 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * `simfile.observe.v1` — the report `simfile observe <run-dir>` emits
4
+ * (Decision 21 / contracts.md's `simfile.observe.v1` row, the one contract
5
+ * id: `spawnfile.spread-report.v1` is a removed alias, never revived here).
6
+ * `seed_spread`, `spread_summary`, and `wake_diff` are DEFINED-BUT-OPTIONAL
7
+ * and omitted for the office-sim golden fixture (no seeded secret, no
8
+ * compiled wake schedule); memetics increment (b) populates `seed_spread`/
9
+ * `spread_summary` for a seed-declared run without a v2 bump.
10
+ */
11
+ export const OBSERVE_REPORT_VERSION = "simfile.observe.v1";
12
+ /** Precedence order matches `@noopolis/stele`'s `reconcileEvents` states,
13
+ * minus "complete" (that count lives in `chains.complete`, not the flagged list). */
14
+ export const INCOMPLETE_CHAIN_FLAGS = ["divergent", "unknown", "partial", "stale"];
15
+ const incompleteChainEntrySchema = z
16
+ .object({
17
+ event_id: z.string().min(1),
18
+ flag: z.enum(INCOMPLETE_CHAIN_FLAGS)
19
+ })
20
+ .strict();
21
+ /**
22
+ * Where `memory.events` (the write-count proxy) for a bank came from —
23
+ * Slice B Piece 4b. `"ledger"` means at least one `memory.written` causal
24
+ * event was reconciled for the bank (mneme's write-side envelope);
25
+ * `"events-fallback"` means the count instead came from the interim signal
26
+ * (mneme's own `events.jsonl` bank log, or that bank's `memory.recalled`
27
+ * causal events if even that is absent). Optional so a pre-4b serialized
28
+ * report (no source marker at all) still validates.
29
+ */
30
+ export const MEMORY_WRITE_SOURCES = ["ledger", "events-fallback"];
31
+ const memoryBankEntrySchema = z
32
+ .object({
33
+ bank: z.string().min(1),
34
+ events: z.number().int().min(0),
35
+ recalls: z.number().int().min(0),
36
+ memory_write_source: z.enum(MEMORY_WRITE_SOURCES).optional(),
37
+ writes_by_agent: z.record(z.string(), z.number().int().min(0)).optional()
38
+ })
39
+ .strict();
40
+ const failureEntrySchema = z
41
+ .object({
42
+ reason: z.string().min(1),
43
+ event_id: z.string().min(1)
44
+ })
45
+ .strict();
46
+ /** `doc-seeded` is added (contracts.md) so a seed's entry channel is
47
+ * representable and never misclassified as spontaneous invention. */
48
+ export const SEED_SPREAD_CHANNELS = ["doc-seeded", "uttered", "registered", "recalled"];
49
+ /**
50
+ * Memetics increment (b): `agent`/`tick`/`memory_write_source` are a
51
+ * compatible v1 amendment (`seed_spread` was frozen DEFINED-BUT-OPTIONAL
52
+ * precisely so a later phase could grow the entry shape without a v2 bump).
53
+ * `agent` is the principal simfile observe attributes the hit to (never the
54
+ * seed agent for a `doc-seeded` entry's own later channels — reach/latency
55
+ * math excludes the seed agent, this field alone doesn't). `tick` is the
56
+ * world's own tick counter, joined from `world/ingested-messages.jsonl`
57
+ * (an `uttered` hit) or traced back to the moltnet message that caused it
58
+ * (a `registered`/`recalled` hit whose ledger event chains back that far) —
59
+ * never fabricated; omitted when no such join exists. `memory_write_source`
60
+ * mirrors `MemoryWriteSource` (Slice B Piece 4b) but scoped to this single
61
+ * `registered` hit, not a whole bank.
62
+ */
63
+ const seedSpreadSchema = z
64
+ .object({
65
+ channel: z.enum(SEED_SPREAD_CHANNELS),
66
+ event_id: z.string().min(1),
67
+ fidelity: z.number().min(0).max(1).optional(),
68
+ agent: z.string().min(1).optional(),
69
+ tick: z.number().int().min(0).optional(),
70
+ memory_write_source: z.enum(MEMORY_WRITE_SOURCES).optional()
71
+ })
72
+ .strict();
73
+ /** One non-seed agent's earliest re-derived appearance, across every channel. */
74
+ const spreadFirstAppearanceSchema = z
75
+ .object({
76
+ agent: z.string().min(1),
77
+ channel: z.enum(SEED_SPREAD_CHANNELS),
78
+ event_id: z.string().min(1),
79
+ tick: z.number().int().min(0).optional()
80
+ })
81
+ .strict();
82
+ /**
83
+ * The smallest honest summary of `seed_spread` (memetics increment (b)):
84
+ * `reach` counts non-seed agents with any post-seed appearance; `latency`
85
+ * is the lowest known `tick` among those appearances (omitted when no
86
+ * appearance carries a `tick`) — ticks/causal steps from the seed epoch to
87
+ * first spread, never wall-clock. Derivable from `seed_spread` alone, but
88
+ * kept as its own field so a consumer (the viewer) doesn't have to
89
+ * re-implement the derivation.
90
+ */
91
+ const spreadSummarySchema = z
92
+ .object({
93
+ reach: z.number().int().min(0),
94
+ latency: z.number().int().min(0).optional(),
95
+ first_appearance: z.array(spreadFirstAppearanceSchema)
96
+ })
97
+ .strict();
98
+ const wakeDiffEntrySchema = z
99
+ .object({
100
+ agent_id: z.string().min(1),
101
+ wake_id: z.string().min(1),
102
+ status: z.enum(["delivered", "wake-not-delivered"])
103
+ })
104
+ .strict();
105
+ export const observeReportSchema = z
106
+ .object({
107
+ version: z.literal(OBSERVE_REPORT_VERSION),
108
+ run_id: z.string().min(1),
109
+ contract_versions: z.record(z.string(), z.string()),
110
+ participants: z.array(z.string().min(1)),
111
+ agent_turns: z
112
+ .object({
113
+ count: z.number().int().min(0),
114
+ sequence: z.array(z.string().min(1))
115
+ })
116
+ .strict(),
117
+ chains: z
118
+ .object({
119
+ complete: z.number().int().min(0),
120
+ incomplete: z.array(incompleteChainEntrySchema)
121
+ })
122
+ .strict(),
123
+ memory: z.array(memoryBankEntrySchema),
124
+ failures: z.array(failureEntrySchema),
125
+ seed_spread: z.array(seedSpreadSchema).optional(),
126
+ spread_summary: spreadSummarySchema.optional(),
127
+ wake_diff: z.array(wakeDiffEntrySchema).optional()
128
+ })
129
+ .strict();
130
+ export const parseObserveReport = (raw) => {
131
+ const result = observeReportSchema.safeParse(raw);
132
+ if (!result.success) {
133
+ throw new Error(`invalid ${OBSERVE_REPORT_VERSION} report: ${result.error.issues
134
+ .map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`)
135
+ .join("; ")}`);
136
+ }
137
+ return result.data;
138
+ };
@@ -0,0 +1,49 @@
1
+ import type { CausalEvent } from "@noopolis/stele";
2
+ import type { SeedDeclaration } from "./manifest.js";
3
+ import type { SeedSpreadEntry, SpreadSummary } from "./report.js";
4
+ import type { SpreadMnemeEvent, SpreadTranscriptMessage } from "./seedSpreadArtifacts.js";
5
+ export interface SeedSpreadExcluded {
6
+ event_id: string;
7
+ reason: string;
8
+ }
9
+ export interface SeedSpreadComputeInput {
10
+ seedDeclaration: SeedDeclaration;
11
+ /** Every collected causal event across every authority, keyed by `event_id` — the
12
+ * cross-stream join surface `deriveTick`'s backward trace walks. */
13
+ causalEventsById: ReadonlyMap<string, CausalEvent>;
14
+ transcriptMessages: readonly SpreadTranscriptMessage[];
15
+ /** Per-bank `raw/mneme/<bank>/causal.jsonl` events, as `observe.ts` already groups them. */
16
+ causalEventsByBank: ReadonlyMap<string, readonly CausalEvent[]>;
17
+ /** Per-bank `raw/mneme/<bank>/events.jsonl` rows (the write-side/interim signal). */
18
+ mnemeEventsByBank: ReadonlyMap<string, readonly SpreadMnemeEvent[]>;
19
+ /** `world/ingested-messages.jsonl`'s `message_id -> tick` join; empty for a non-world-driven run. */
20
+ tickByMoltnetMessageId: ReadonlyMap<string, number>;
21
+ }
22
+ export interface SeedSpreadComputeResult {
23
+ entries: SeedSpreadEntry[];
24
+ excluded: SeedSpreadExcluded[];
25
+ summary: SpreadSummary;
26
+ }
27
+ export declare const computeSeedSpread: (input: SeedSpreadComputeInput) => SeedSpreadComputeResult;
28
+ export interface SeedSpreadSelfCheck {
29
+ /** Moltnet message ids the live world loop's own `marker.seen` flagged. */
30
+ liveHitMessageIds: string[];
31
+ /** Moltnet message ids this module's re-derivation flagged as `uttered` (including excluded ones). */
32
+ derivedHitMessageIds: string[];
33
+ /** Present in the live loop's `marker.seen` set but not re-derived here. */
34
+ onlyLive: string[];
35
+ /** Re-derived here but never flagged by the live loop's `marker.seen`. */
36
+ onlyDerived: string[];
37
+ matches: boolean;
38
+ }
39
+ /**
40
+ * Diagnostic only, never authoritative (`worldTickLoop.ts`'s own doc
41
+ * comment: the live loop's `marker.seen` is polling-order, not causal
42
+ * order). Compares the set of Moltnet message ids the live loop flagged
43
+ * against this module's independently re-derived `uttered` hits (both
44
+ * excluded and counted ones — exclusion is instrument hygiene, not evidence
45
+ * the live loop wouldn't have also flagged the same message) and reports
46
+ * any mismatch rather than silently trusting either side.
47
+ */
48
+ export declare const diffSeedSpreadAgainstLiveMarkerSeen: (worldEvents: readonly CausalEvent[], transcriptMessages: readonly SpreadTranscriptMessage[], tokenSet: readonly string[], matcherPolicy?: string) => SeedSpreadSelfCheck;
49
+ //# sourceMappingURL=seedSpread.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seedSpread.d.ts","sourceRoot":"","sources":["../../src/observe/seedSpread.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAqB,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AA4B1F,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,eAAe,CAAC;IACjC;wEACoE;IACpE,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACnD,kBAAkB,EAAE,SAAS,uBAAuB,EAAE,CAAC;IACvD,4FAA4F;IAC5F,kBAAkB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC,CAAC;IAChE,qFAAqF;IACrF,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC,CAAC;IACpE,qGAAqG;IACrG,sBAAsB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,OAAO,EAAE,aAAa,CAAC;CACxB;AA4PD,eAAO,MAAM,iBAAiB,GAAI,OAAO,sBAAsB,KAAG,uBAYjE,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,sGAAsG;IACtG,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mCAAmC,GAC9C,aAAa,SAAS,WAAW,EAAE,EACnC,oBAAoB,SAAS,uBAAuB,EAAE,EACtD,UAAU,SAAS,MAAM,EAAE,EAC3B,sBAAuB,KACtB,mBAyBF,CAAC"}
@@ -0,0 +1,262 @@
1
+ import { matchSeedSpread, parseSpreadMatcherPolicy } from "./spreadMatcher.js";
2
+ /**
3
+ * Memetics increment (b): re-derives `seed_spread` from sealed artifacts +
4
+ * `manifest.seed_declaration`, never from the live world loop's own
5
+ * `marker.seen` events (`worldTickLoop.ts`'s own doc comment: polling order
6
+ * ≠ causal order — see `diffSeedSpreadAgainstLiveMarkerSeen` below for the
7
+ * self-check that DOES read `marker.seen`, but only to report a mismatch,
8
+ * never to feed `seed_spread` itself).
9
+ *
10
+ * Honesty rules enforced here (never hand-waved):
11
+ * - `turn.input.submitted` payloads are never scanned — a token appearing in
12
+ * an agent's prompt is exposure, not expression.
13
+ * - Any hit whose actor is `world` or `operator:<agent>` is excluded from
14
+ * `seed_spread` and reported instead as a `failures[]` entry (instrument
15
+ * error or containment violation, never agent spread).
16
+ * - The one `doc-seeded` entry is taken verbatim from the manifest, never
17
+ * scanned for.
18
+ */
19
+ const AGENT_PRINCIPAL_PATTERN = /^agent:(.+)$/u;
20
+ const isInstrumentOrOperatorActor = (actor) => actor === "world" || (actor?.startsWith("operator:") ?? false);
21
+ const matchTokenSet = (text, tokenSet, matcherPolicy) => matchSeedSpread(text, tokenSet, matcherPolicy);
22
+ const agentIdFromPrincipal = (principalId) => AGENT_PRINCIPAL_PATTERN.exec(principalId)?.[1];
23
+ const stringPayloadField = (event, field) => {
24
+ const value = event.payload?.[field];
25
+ return typeof value === "string" ? value : undefined;
26
+ };
27
+ /**
28
+ * Walks `event_id`'s `cause_event_ids` backward (bounded depth) looking for
29
+ * a `moltnet` `message.accepted` event on each branch — stopping the moment
30
+ * one is found (never recursing past it). Real cause chains only, never a
31
+ * synthesized or wall-clock-ordered link: this is how a `registered`
32
+ * (ledger-path) or `recalled` hit gets an honest `tick` without a direct
33
+ * one-hop join.
34
+ */
35
+ const traceBackToMoltnetMessageIds = (eventId, byId, maxDepth = 6) => {
36
+ const start = byId.get(eventId);
37
+ if (!start)
38
+ return [];
39
+ const found = new Set();
40
+ const seen = new Set([eventId]);
41
+ const stack = start.cause_event_ids.map((id) => ({ id, depth: 1 }));
42
+ while (stack.length > 0) {
43
+ const next = stack.pop();
44
+ if (!next || seen.has(next.id) || next.depth > maxDepth)
45
+ continue;
46
+ seen.add(next.id);
47
+ const event = byId.get(next.id);
48
+ if (!event)
49
+ continue;
50
+ if (event.emitter.system === "moltnet" && event.type === "message.accepted") {
51
+ found.add(stringPayloadField(event, "message_id") ?? event.event_id);
52
+ continue;
53
+ }
54
+ for (const cause of event.cause_event_ids)
55
+ stack.push({ id: cause, depth: next.depth + 1 });
56
+ }
57
+ return [...found];
58
+ };
59
+ const deriveTick = (event, byId, tickByMessageId) => {
60
+ if (!event)
61
+ return undefined;
62
+ if (event.emitter.system === "moltnet" && event.type === "message.accepted") {
63
+ const messageId = stringPayloadField(event, "message_id");
64
+ return messageId ? tickByMessageId.get(messageId) : undefined;
65
+ }
66
+ const ticks = traceBackToMoltnetMessageIds(event.event_id, byId)
67
+ .map((messageId) => tickByMessageId.get(messageId))
68
+ .filter((tick) => tick !== undefined);
69
+ return ticks.length > 0 ? Math.min(...ticks) : undefined;
70
+ };
71
+ const docSeededEntry = (seed) => ({
72
+ channel: "doc-seeded",
73
+ event_id: `doc-seed:${seed.seed_agent}:${seed.seed_epoch}`,
74
+ fidelity: 1,
75
+ agent: seed.seed_agent
76
+ });
77
+ const computeUtteredEntries = (input, matcherPolicy) => {
78
+ const entries = [];
79
+ const excluded = [];
80
+ const messageAcceptedByMessageId = new Map();
81
+ for (const event of input.causalEventsById.values()) {
82
+ if (event.emitter.system !== "moltnet" || event.type !== "message.accepted")
83
+ continue;
84
+ const messageId = stringPayloadField(event, "message_id");
85
+ if (messageId)
86
+ messageAcceptedByMessageId.set(messageId, event);
87
+ }
88
+ for (const message of input.transcriptMessages) {
89
+ const match = matchTokenSet(message.text, input.seedDeclaration.token_set, matcherPolicy);
90
+ if (!match.matched)
91
+ continue;
92
+ const causal = messageAcceptedByMessageId.get(message.id);
93
+ const eventId = causal?.event_id ?? message.id;
94
+ if (isInstrumentOrOperatorActor(message.fromId)) {
95
+ excluded.push({
96
+ event_id: eventId,
97
+ reason: `seed-spread: excluded uttered hit from instrument/operator actor "${message.fromId}" — never counted as agent spread`
98
+ });
99
+ continue;
100
+ }
101
+ entries.push({
102
+ channel: "uttered",
103
+ event_id: eventId,
104
+ fidelity: match.fidelity,
105
+ ...(message.fromId ? { agent: message.fromId } : {}),
106
+ ...(() => {
107
+ const tick = deriveTick(causal, input.causalEventsById, input.tickByMoltnetMessageId);
108
+ return tick === undefined ? {} : { tick };
109
+ })()
110
+ });
111
+ }
112
+ return { entries, excluded };
113
+ };
114
+ const computeRegisteredEntries = (input, matcherPolicy) => {
115
+ const entries = [];
116
+ const excluded = [];
117
+ for (const [bank, bankEvents] of input.mnemeEventsByBank) {
118
+ const bankCausal = input.causalEventsByBank.get(bank) ?? [];
119
+ const writtenByMemoryId = new Map();
120
+ for (const event of bankCausal) {
121
+ if (event.type !== "memory.written")
122
+ continue;
123
+ const memoryId = stringPayloadField(event, "memory_id");
124
+ if (memoryId)
125
+ writtenByMemoryId.set(memoryId, event);
126
+ }
127
+ for (const bankEvent of bankEvents) {
128
+ // Recalls get their own channel below, from the causal `memory.recalled`
129
+ // stream — never double-counted here as a registration.
130
+ if (bankEvent.type === "memory.recalled")
131
+ continue;
132
+ const match = matchTokenSet(bankEvent.text, input.seedDeclaration.token_set, matcherPolicy);
133
+ if (!match.matched)
134
+ continue;
135
+ const ledgerEvent = writtenByMemoryId.get(bankEvent.id);
136
+ const eventId = ledgerEvent?.event_id ?? bankEvent.id;
137
+ if (isInstrumentOrOperatorActor(bankEvent.agentId)) {
138
+ excluded.push({
139
+ event_id: eventId,
140
+ reason: `seed-spread: excluded registered hit from instrument/operator actor "${bankEvent.agentId}" — never counted as agent spread`
141
+ });
142
+ continue;
143
+ }
144
+ const tick = ledgerEvent ? deriveTick(ledgerEvent, input.causalEventsById, input.tickByMoltnetMessageId) : undefined;
145
+ entries.push({
146
+ channel: "registered",
147
+ event_id: eventId,
148
+ fidelity: match.fidelity,
149
+ ...(bankEvent.agentId ? { agent: bankEvent.agentId } : {}),
150
+ ...(tick === undefined ? {} : { tick }),
151
+ memory_write_source: ledgerEvent ? "ledger" : "events-fallback"
152
+ });
153
+ }
154
+ }
155
+ return { entries, excluded };
156
+ };
157
+ const computeRecalledEntries = (input, matcherPolicy) => {
158
+ const entries = [];
159
+ const excluded = [];
160
+ for (const [bank, bankEvents] of input.mnemeEventsByBank) {
161
+ const bankCausal = input.causalEventsByBank.get(bank) ?? [];
162
+ const contentById = new Map(bankEvents.map((event) => [event.id, event.text]));
163
+ for (const event of bankCausal) {
164
+ if (event.type !== "memory.recalled")
165
+ continue;
166
+ const memoryId = stringPayloadField(event, "memory_id");
167
+ const text = memoryId ? contentById.get(memoryId) : undefined;
168
+ if (text === undefined)
169
+ continue;
170
+ const match = matchTokenSet(text, input.seedDeclaration.token_set, matcherPolicy);
171
+ if (!match.matched)
172
+ continue;
173
+ const agent = agentIdFromPrincipal(event.principal_id);
174
+ if (isInstrumentOrOperatorActor(agent ?? event.principal_id)) {
175
+ excluded.push({
176
+ event_id: event.event_id,
177
+ reason: `seed-spread: excluded recalled hit from instrument/operator principal "${event.principal_id}" — never counted as agent spread`
178
+ });
179
+ continue;
180
+ }
181
+ const tick = deriveTick(event, input.causalEventsById, input.tickByMoltnetMessageId);
182
+ entries.push({
183
+ channel: "recalled",
184
+ event_id: event.event_id,
185
+ fidelity: match.fidelity,
186
+ ...(agent ? { agent } : {}),
187
+ ...(tick === undefined ? {} : { tick })
188
+ });
189
+ }
190
+ }
191
+ return { entries, excluded };
192
+ };
193
+ const computeSummary = (entries, seedAgent) => {
194
+ const firstAppearanceByAgent = new Map();
195
+ for (const entry of entries) {
196
+ if (entry.channel === "doc-seeded" || !entry.agent || entry.agent === seedAgent)
197
+ continue;
198
+ const existing = firstAppearanceByAgent.get(entry.agent);
199
+ if (!existing) {
200
+ firstAppearanceByAgent.set(entry.agent, { channel: entry.channel, event_id: entry.event_id, tick: entry.tick });
201
+ continue;
202
+ }
203
+ // Prefer whichever appearance carries the lower known tick; keep the
204
+ // first-seen entry when neither (or both equally) carries one.
205
+ if (entry.tick !== undefined && (existing.tick === undefined || entry.tick < existing.tick)) {
206
+ firstAppearanceByAgent.set(entry.agent, { channel: entry.channel, event_id: entry.event_id, tick: entry.tick });
207
+ }
208
+ }
209
+ const firstAppearance = [...firstAppearanceByAgent.entries()]
210
+ .sort(([left], [right]) => left.localeCompare(right))
211
+ .map(([agent, appearance]) => ({
212
+ agent,
213
+ channel: appearance.channel,
214
+ event_id: appearance.event_id,
215
+ ...(appearance.tick === undefined ? {} : { tick: appearance.tick })
216
+ }));
217
+ const knownTicks = firstAppearance.map((entry) => entry.tick).filter((tick) => tick !== undefined);
218
+ return {
219
+ reach: firstAppearance.length,
220
+ ...(knownTicks.length > 0 ? { latency: Math.min(...knownTicks) } : {}),
221
+ first_appearance: firstAppearance
222
+ };
223
+ };
224
+ export const computeSeedSpread = (input) => {
225
+ // Resolve once before scanning so an unsupported pinned policy fails even
226
+ // when the run has no transcript messages or memory content.
227
+ const matcherPolicy = parseSpreadMatcherPolicy(input.seedDeclaration.matcher_policy);
228
+ const uttered = computeUtteredEntries(input, matcherPolicy);
229
+ const registered = computeRegisteredEntries(input, matcherPolicy);
230
+ const recalled = computeRecalledEntries(input, matcherPolicy);
231
+ const entries = [docSeededEntry(input.seedDeclaration), ...uttered.entries, ...registered.entries, ...recalled.entries];
232
+ const excluded = [...uttered.excluded, ...registered.excluded, ...recalled.excluded];
233
+ return { entries, excluded, summary: computeSummary(entries, input.seedDeclaration.seed_agent) };
234
+ };
235
+ /**
236
+ * Diagnostic only, never authoritative (`worldTickLoop.ts`'s own doc
237
+ * comment: the live loop's `marker.seen` is polling-order, not causal
238
+ * order). Compares the set of Moltnet message ids the live loop flagged
239
+ * against this module's independently re-derived `uttered` hits (both
240
+ * excluded and counted ones — exclusion is instrument hygiene, not evidence
241
+ * the live loop wouldn't have also flagged the same message) and reports
242
+ * any mismatch rather than silently trusting either side.
243
+ */
244
+ export const diffSeedSpreadAgainstLiveMarkerSeen = (worldEvents, transcriptMessages, tokenSet, matcherPolicy = "exact") => {
245
+ const parsedMatcherPolicy = parseSpreadMatcherPolicy(matcherPolicy);
246
+ const liveHitMessageIds = [
247
+ ...new Set(worldEvents
248
+ .filter((event) => event.type === "marker.seen")
249
+ .map((event) => stringPayloadField(event, "source_event_id"))
250
+ .filter((id) => id !== undefined))
251
+ ].sort();
252
+ const derivedHitMessageIds = [
253
+ ...new Set(transcriptMessages
254
+ .filter((message) => matchTokenSet(message.text, tokenSet, parsedMatcherPolicy).matched)
255
+ .map((message) => message.id))
256
+ ].sort();
257
+ const liveSet = new Set(liveHitMessageIds);
258
+ const derivedSet = new Set(derivedHitMessageIds);
259
+ const onlyLive = liveHitMessageIds.filter((id) => !derivedSet.has(id));
260
+ const onlyDerived = derivedHitMessageIds.filter((id) => !liveSet.has(id));
261
+ return { liveHitMessageIds, derivedHitMessageIds, onlyLive, onlyDerived, matches: onlyLive.length === 0 && onlyDerived.length === 0 };
262
+ };
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Memetics increment (b): the extra sealed-artifact reads `seedSpread.ts`'s
3
+ * re-derivation needs, on top of what `causalStreams.ts`/`memoryBanks.ts`
4
+ * already collect. Kept as its own I/O-only module (this folder's own rule:
5
+ * `compute.ts`-style pure functions never touch the filesystem) so
6
+ * `seedSpread.ts` stays a pure function of already-loaded data, matching
7
+ * `memoryBanks.ts`/`causalStreams.ts`'s split.
8
+ */
9
+ export interface SpreadTranscriptMessage {
10
+ id: string;
11
+ fromId?: string;
12
+ text: string;
13
+ }
14
+ export interface SpreadMnemeEvent {
15
+ id: string;
16
+ type: string;
17
+ agentId?: string;
18
+ text: string;
19
+ }
20
+ /**
21
+ * Reads every `transcript.json` under `<runDir>/raw/moltnet/**` (today a
22
+ * single file; globbed so a future multi-network export nesting transcripts
23
+ * per network/room still gets picked up) and flattens every conversation's
24
+ * messages to `{id, fromId, text}`. Only the `moltnet.transcript-export.v1`
25
+ * export shape (`{conversations:[{messages}]}`) is read here — the seed-spread
26
+ * path only ever runs against a real composed/world-driven run, never the
27
+ * hand-authored golden-fixture shape (which never carries `seed_declaration`).
28
+ */
29
+ export declare const readSpreadTranscriptMessages: (runDir: string) => Promise<SpreadTranscriptMessage[]>;
30
+ /**
31
+ * Reads every mneme bank's `events.jsonl` (the write-side/interim signal —
32
+ * same file `memoryBanks.ts` falls back to) into `{id, type, agentId, text}`,
33
+ * keyed by bank directory name. Every field is read verbatim from the
34
+ * sealed file; a malformed line is skipped rather than crashing the whole
35
+ * read (mirrors this folder's "report, don't stitch" posture for a
36
+ * diagnostic-only artifact).
37
+ */
38
+ export declare const readSpreadMnemeEventsByBank: (runDir: string) => Promise<Map<string, SpreadMnemeEvent[]>>;
39
+ /**
40
+ * Reads `<runDir>/world/ingested-messages.jsonl` (note: NOT under `raw/` —
41
+ * `worldLedgerWriter.ts`'s own diagnostic, one line per tick,
42
+ * `{tick, message_ids}`) into a `message_id -> tick` map: the one exact,
43
+ * non-wall-clock fact the live world loop recorded about when it folded a
44
+ * given Moltnet message into the run. Absent entirely for a run that wasn't
45
+ * world-driven (batch `composedOfficeSimDriver`-style runs never write this
46
+ * file) — returns an empty map rather than failing.
47
+ */
48
+ export declare const readTickByIngestedMessageId: (runDir: string) => Promise<Map<string, number>>;
49
+ //# sourceMappingURL=seedSpreadArtifacts.d.ts.map