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.
- package/README.md +143 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +348 -0
- package/dist/coverage/index.d.ts +2 -0
- package/dist/coverage/index.d.ts.map +1 -0
- package/dist/coverage/index.js +1 -0
- package/dist/coverage/matrix.d.ts +21 -0
- package/dist/coverage/matrix.d.ts.map +1 -0
- package/dist/coverage/matrix.js +173 -0
- package/dist/coverage/render.d.ts +3 -0
- package/dist/coverage/render.d.ts.map +1 -0
- package/dist/coverage/render.js +26 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/kernel/duration.d.ts +9 -0
- package/dist/kernel/duration.d.ts.map +1 -0
- package/dist/kernel/duration.js +44 -0
- package/dist/kernel/index.d.ts +4 -0
- package/dist/kernel/index.d.ts.map +1 -0
- package/dist/kernel/index.js +3 -0
- package/dist/kernel/range.d.ts +6 -0
- package/dist/kernel/range.d.ts.map +1 -0
- package/dist/kernel/range.js +16 -0
- package/dist/kernel/stochastic.d.ts +10 -0
- package/dist/kernel/stochastic.d.ts.map +1 -0
- package/dist/kernel/stochastic.js +25 -0
- package/dist/ledger/index.d.ts +4 -0
- package/dist/ledger/index.d.ts.map +1 -0
- package/dist/ledger/index.js +3 -0
- package/dist/ledger/markers.d.ts +46 -0
- package/dist/ledger/markers.d.ts.map +1 -0
- package/dist/ledger/markers.js +108 -0
- package/dist/ledger/stable.d.ts +65 -0
- package/dist/ledger/stable.d.ts.map +1 -0
- package/dist/ledger/stable.js +78 -0
- package/dist/ledger/validation.d.ts +16 -0
- package/dist/ledger/validation.d.ts.map +1 -0
- package/dist/ledger/validation.js +127 -0
- package/dist/moltnet/index.d.ts +3 -0
- package/dist/moltnet/index.d.ts.map +1 -0
- package/dist/moltnet/index.js +2 -0
- package/dist/moltnet/transcript-export.d.ts +34 -0
- package/dist/moltnet/transcript-export.d.ts.map +1 -0
- package/dist/moltnet/transcript-export.js +68 -0
- package/dist/moltnet/world-participant.d.ts +77 -0
- package/dist/moltnet/world-participant.d.ts.map +1 -0
- package/dist/moltnet/world-participant.js +221 -0
- package/dist/observe/artifacts.d.ts +16 -0
- package/dist/observe/artifacts.d.ts.map +1 -0
- package/dist/observe/artifacts.js +31 -0
- package/dist/observe/causalStreams.d.ts +19 -0
- package/dist/observe/causalStreams.d.ts.map +1 -0
- package/dist/observe/causalStreams.js +38 -0
- package/dist/observe/compute.d.ts +17 -0
- package/dist/observe/compute.d.ts.map +1 -0
- package/dist/observe/compute.js +97 -0
- package/dist/observe/index.d.ts +11 -0
- package/dist/observe/index.d.ts.map +1 -0
- package/dist/observe/index.js +10 -0
- package/dist/observe/manifest.d.ts +79 -0
- package/dist/observe/manifest.d.ts.map +1 -0
- package/dist/observe/manifest.js +87 -0
- package/dist/observe/memoryBanks.d.ts +38 -0
- package/dist/observe/memoryBanks.d.ts.map +1 -0
- package/dist/observe/memoryBanks.js +86 -0
- package/dist/observe/observe.d.ts +32 -0
- package/dist/observe/observe.d.ts.map +1 -0
- package/dist/observe/observe.js +73 -0
- package/dist/observe/report.d.ts +165 -0
- package/dist/observe/report.d.ts.map +1 -0
- package/dist/observe/report.js +138 -0
- package/dist/observe/seedSpread.d.ts +49 -0
- package/dist/observe/seedSpread.d.ts.map +1 -0
- package/dist/observe/seedSpread.js +262 -0
- package/dist/observe/seedSpreadArtifacts.d.ts +49 -0
- package/dist/observe/seedSpreadArtifacts.d.ts.map +1 -0
- package/dist/observe/seedSpreadArtifacts.js +118 -0
- package/dist/observe/spreadMatcher.d.ts +45 -0
- package/dist/observe/spreadMatcher.d.ts.map +1 -0
- package/dist/observe/spreadMatcher.js +124 -0
- package/dist/report/index.d.ts +4 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +3 -0
- package/dist/report/probeArtifact.d.ts +26 -0
- package/dist/report/probeArtifact.d.ts.map +1 -0
- package/dist/report/probeArtifact.js +119 -0
- package/dist/report/probes.d.ts +52 -0
- package/dist/report/probes.d.ts.map +1 -0
- package/dist/report/probes.js +164 -0
- package/dist/report/score.d.ts +27 -0
- package/dist/report/score.d.ts.map +1 -0
- package/dist/report/score.js +14 -0
- package/dist/report/transcripts.d.ts +12 -0
- package/dist/report/transcripts.d.ts.map +1 -0
- package/dist/report/transcripts.js +17 -0
- package/dist/runtime/causal-fixture.d.ts +26 -0
- package/dist/runtime/causal-fixture.d.ts.map +1 -0
- package/dist/runtime/causal-fixture.js +36 -0
- package/dist/runtime/clock.d.ts +25 -0
- package/dist/runtime/clock.d.ts.map +1 -0
- package/dist/runtime/clock.js +63 -0
- package/dist/runtime/condition.d.ts +55 -0
- package/dist/runtime/condition.d.ts.map +1 -0
- package/dist/runtime/condition.js +122 -0
- package/dist/runtime/emit-causal-fixture.d.ts +2 -0
- package/dist/runtime/emit-causal-fixture.d.ts.map +1 -0
- package/dist/runtime/emit-causal-fixture.js +45 -0
- package/dist/runtime/expression.d.ts +11 -0
- package/dist/runtime/expression.d.ts.map +1 -0
- package/dist/runtime/expression.js +305 -0
- package/dist/runtime/numeric.d.ts +7 -0
- package/dist/runtime/numeric.d.ts.map +1 -0
- package/dist/runtime/numeric.js +11 -0
- package/dist/runtime/rule-actions.d.ts +5 -0
- package/dist/runtime/rule-actions.d.ts.map +1 -0
- package/dist/runtime/rule-actions.js +82 -0
- package/dist/runtime/run-record.d.ts +73 -0
- package/dist/runtime/run-record.d.ts.map +1 -0
- package/dist/runtime/run-record.js +179 -0
- package/dist/runtime/step-tick.d.ts +43 -0
- package/dist/runtime/step-tick.d.ts.map +1 -0
- package/dist/runtime/step-tick.js +177 -0
- package/dist/runtime/trace-compile.d.ts +66 -0
- package/dist/runtime/trace-compile.d.ts.map +1 -0
- package/dist/runtime/trace-compile.js +157 -0
- package/dist/runtime/trace-export.d.ts +5 -0
- package/dist/runtime/trace-export.d.ts.map +1 -0
- package/dist/runtime/trace-export.js +4 -0
- package/dist/runtime/trace-run.d.ts +15 -0
- package/dist/runtime/trace-run.d.ts.map +1 -0
- package/dist/runtime/trace-run.js +92 -0
- package/dist/runtime/trace.d.ts +10 -0
- package/dist/runtime/trace.d.ts.map +1 -0
- package/dist/runtime/trace.js +9 -0
- package/dist/runtime/types.d.ts +61 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/viewer-trace.d.ts +64 -0
- package/dist/runtime/viewer-trace.d.ts.map +1 -0
- package/dist/runtime/viewer-trace.js +164 -0
- package/dist/runtime/world-act.d.ts +55 -0
- package/dist/runtime/world-act.d.ts.map +1 -0
- package/dist/runtime/world-act.js +156 -0
- package/dist/schema/binding.d.ts +23 -0
- package/dist/schema/binding.d.ts.map +1 -0
- package/dist/schema/binding.js +249 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +4 -0
- package/dist/schema/model.d.ts +244 -0
- package/dist/schema/model.d.ts.map +1 -0
- package/dist/schema/model.js +222 -0
- package/dist/schema/parse.d.ts +10 -0
- package/dist/schema/parse.d.ts.map +1 -0
- package/dist/schema/parse.js +15 -0
- package/dist/schema/semantic.d.ts +3 -0
- package/dist/schema/semantic.d.ts.map +1 -0
- package/dist/schema/semantic.js +135 -0
- package/dist/sims/composeRunManifest.d.ts +54 -0
- package/dist/sims/composeRunManifest.d.ts.map +1 -0
- package/dist/sims/composeRunManifest.js +40 -0
- package/dist/sims/composedJungianSimDriver.d.ts +50 -0
- package/dist/sims/composedJungianSimDriver.d.ts.map +1 -0
- package/dist/sims/composedJungianSimDriver.js +199 -0
- package/dist/sims/composedOfficeSimDriver.d.ts +53 -0
- package/dist/sims/composedOfficeSimDriver.d.ts.map +1 -0
- package/dist/sims/composedOfficeSimDriver.js +162 -0
- package/dist/sims/exchangeWait.d.ts +56 -0
- package/dist/sims/exchangeWait.d.ts.map +1 -0
- package/dist/sims/exchangeWait.js +66 -0
- package/dist/sims/index.d.ts +14 -0
- package/dist/sims/index.d.ts.map +1 -0
- package/dist/sims/index.js +13 -0
- package/dist/sims/moltnetRoomClient.d.ts +47 -0
- package/dist/sims/moltnetRoomClient.d.ts.map +1 -0
- package/dist/sims/moltnetRoomClient.js +41 -0
- package/dist/sims/poll.d.ts +19 -0
- package/dist/sims/poll.d.ts.map +1 -0
- package/dist/sims/poll.js +23 -0
- package/dist/sims/spawnfileCli.d.ts +49 -0
- package/dist/sims/spawnfileCli.d.ts.map +1 -0
- package/dist/sims/spawnfileCli.js +90 -0
- package/dist/sims/spawnfileReceipts.d.ts +76 -0
- package/dist/sims/spawnfileReceipts.d.ts.map +1 -0
- package/dist/sims/spawnfileReceipts.js +107 -0
- package/dist/sims/worldDrivenOfficeSimDriver.d.ts +59 -0
- package/dist/sims/worldDrivenOfficeSimDriver.d.ts.map +1 -0
- package/dist/sims/worldDrivenOfficeSimDriver.js +182 -0
- package/dist/sims/worldLedgerWriter.d.ts +32 -0
- package/dist/sims/worldLedgerWriter.d.ts.map +1 -0
- package/dist/sims/worldLedgerWriter.js +39 -0
- package/dist/sims/worldSeedLint.d.ts +42 -0
- package/dist/sims/worldSeedLint.d.ts.map +1 -0
- package/dist/sims/worldSeedLint.js +73 -0
- package/dist/sims/worldTickIngest.d.ts +27 -0
- package/dist/sims/worldTickIngest.d.ts.map +1 -0
- package/dist/sims/worldTickIngest.js +35 -0
- package/dist/sims/worldTickLoop.d.ts +64 -0
- package/dist/sims/worldTickLoop.d.ts.map +1 -0
- package/dist/sims/worldTickLoop.js +122 -0
- package/dist/view/engineProvenance.d.ts +46 -0
- package/dist/view/engineProvenance.d.ts.map +1 -0
- package/dist/view/engineProvenance.js +76 -0
- package/dist/view/index.d.ts +14 -0
- package/dist/view/index.d.ts.map +1 -0
- package/dist/view/index.js +107 -0
- package/dist/view/membranes.d.ts +14 -0
- package/dist/view/membranes.d.ts.map +1 -0
- package/dist/view/membranes.js +127 -0
- package/dist/view/runDetect.d.ts +2 -0
- package/dist/view/runDetect.d.ts.map +1 -0
- package/dist/view/runDetect.js +47 -0
- package/dist/view/runRawArtifacts.d.ts +48 -0
- package/dist/view/runRawArtifacts.d.ts.map +1 -0
- package/dist/view/runRawArtifacts.js +143 -0
- package/dist/view/runTimeline.d.ts +24 -0
- package/dist/view/runTimeline.d.ts.map +1 -0
- package/dist/view/runTimeline.js +204 -0
- package/dist/view/runTimelineRecords.d.ts +42 -0
- package/dist/view/runTimelineRecords.d.ts.map +1 -0
- package/dist/view/runTimelineRecords.js +244 -0
- package/dist/view/runTimelineRefs.d.ts +27 -0
- package/dist/view/runTimelineRefs.d.ts.map +1 -0
- package/dist/view/runTimelineRefs.js +31 -0
- package/dist/view/runTimelineTypes.d.ts +99 -0
- package/dist/view/runTimelineTypes.d.ts.map +1 -0
- package/dist/view/runTimelineTypes.js +1 -0
- package/dist/view/runViewModel.d.ts +21 -0
- package/dist/view/runViewModel.d.ts.map +1 -0
- package/dist/view/runViewModel.js +66 -0
- package/dist/view/runViewModelCompute.d.ts +24 -0
- package/dist/view/runViewModelCompute.d.ts.map +1 -0
- package/dist/view/runViewModelCompute.js +157 -0
- package/dist/view/runViewModelTypes.d.ts +177 -0
- package/dist/view/runViewModelTypes.d.ts.map +1 -0
- package/dist/view/runViewModelTypes.js +1 -0
- package/dist/view/runWorldTrace.d.ts +97 -0
- package/dist/view/runWorldTrace.d.ts.map +1 -0
- package/dist/view/runWorldTrace.js +88 -0
- package/dist/view/server.d.ts +12 -0
- package/dist/view/server.d.ts.map +1 -0
- package/dist/view/server.js +306 -0
- package/package.json +65 -0
- package/web/dist/assets/index-CJHLjfsG.js +49 -0
- package/web/dist/assets/index-DJOsPsU8.css +1 -0
- package/web/dist/index.html +13 -0
- 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
|