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,43 @@
|
|
|
1
|
+
import { type LedgerEventEnvelopeInput } from "../ledger/stable.js";
|
|
2
|
+
import type { ClockRuntime } from "./clock.js";
|
|
3
|
+
import { type CompiledTraceRuntime } from "./trace-compile.js";
|
|
4
|
+
import type { QueuedWorldAct, RuntimeTraceEvent, RuntimeVariableSample, WorldActResult } from "./types.js";
|
|
5
|
+
export type SimfileEventKind = "clock.sync" | "rule.fired" | "world.message" | "world.dm" | "world.act" | "wake.recommended" | "marker.seen";
|
|
6
|
+
export declare const WORLD_ACTOR = "@world";
|
|
7
|
+
/**
|
|
8
|
+
* Shared canonical-envelope constructor for every event kind minted while
|
|
9
|
+
* stepping a tick (and reused by `trace-run.ts` for its post-hoc
|
|
10
|
+
* `marker.seen` events, so there is exactly one place that stamps the
|
|
11
|
+
* causal envelope for simfile-native trace events).
|
|
12
|
+
*/
|
|
13
|
+
export declare const createTraceEvent: (runId: string, seq: number, kind: SimfileEventKind, simTime: number, actor: string, target: string, scope: string, payload: LedgerEventEnvelopeInput["payload"], causeEventIds?: readonly string[]) => RuntimeTraceEvent;
|
|
14
|
+
export interface StepSimfileTickContext {
|
|
15
|
+
runId: string;
|
|
16
|
+
seed: string;
|
|
17
|
+
precision: number;
|
|
18
|
+
clock: ClockRuntime;
|
|
19
|
+
runtime: CompiledTraceRuntime;
|
|
20
|
+
/** Mutated in place: the run's variable state, before this tick on entry
|
|
21
|
+
* and after this tick on return. */
|
|
22
|
+
state: Record<string, number>;
|
|
23
|
+
/** First seq number to mint for this tick's events. */
|
|
24
|
+
seq: number;
|
|
25
|
+
worldActsForTick?: readonly QueuedWorldAct[];
|
|
26
|
+
worldActResultsByActId: ReadonlyMap<string, WorldActResult>;
|
|
27
|
+
}
|
|
28
|
+
export interface StepSimfileTickResult {
|
|
29
|
+
events: RuntimeTraceEvent[];
|
|
30
|
+
sample: RuntimeVariableSample;
|
|
31
|
+
nextSeq: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Advances the world by exactly one tick: resolve the clock, apply any
|
|
35
|
+
* queued world.acts, run generators, recompute derived variables, evaluate
|
|
36
|
+
* rules (minting their world-effect events), then fold the tick's ending
|
|
37
|
+
* values back into `ctx.state`. This is the pure REFACTOR extraction of
|
|
38
|
+
* `runSimfileTrace`'s former inline per-tick loop body — same inputs, same
|
|
39
|
+
* outputs, same mutation order — so a live driver can call it once per
|
|
40
|
+
* wall-clock tick instead of only ever inside one big batch loop.
|
|
41
|
+
*/
|
|
42
|
+
export declare const stepSimfileTick: (tick: number, ctx: StepSimfileTickContext) => StepSimfileTickResult;
|
|
43
|
+
//# sourceMappingURL=step-tick.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-tick.d.ts","sourceRoot":"","sources":["../../src/runtime/step-tick.ts"],"names":[],"mappings":"AACA,OAAO,EAAiF,KAAK,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AACnJ,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,OAAO,EAA6B,KAAK,oBAAoB,EAA2C,MAAM,oBAAoB,CAAC;AACnI,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG3G,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,YAAY,GAAG,eAAe,GAAG,UAAU,GAAG,WAAW,GAAG,kBAAkB,GAAG,aAAa,CAAC;AAE7I,eAAO,MAAM,WAAW,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,OAAO,MAAM,EACb,KAAK,MAAM,EACX,MAAM,gBAAgB,EACtB,SAAS,MAAM,EACf,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,OAAO,MAAM,EACb,SAAS,wBAAwB,CAAC,SAAS,CAAC,EAC5C,gBAAe,SAAS,MAAM,EAAO,KACpC,iBAaoB,CAAC;AAwHxB,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,oBAAoB,CAAC;IAC9B;wCACoC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC7C,sBAAsB,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,KAAK,sBAAsB,KAAG,qBA0E3E,CAAC"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { drawUniform } from "../kernel/stochastic.js";
|
|
2
|
+
import { createCanonicalEventEnvelope, DEFAULT_EMITTER_STREAM_ID, DEFAULT_PRINCIPAL_ID } from "../ledger/stable.js";
|
|
3
|
+
import { resolveClockState } from "./clock.js";
|
|
4
|
+
import { clampAndRound } from "./numeric.js";
|
|
5
|
+
import { runRuleActions } from "./rule-actions.js";
|
|
6
|
+
import { variableTargetFromActions } from "./trace-compile.js";
|
|
7
|
+
import { applyWorldActsAtTick } from "./world-act.js";
|
|
8
|
+
export const WORLD_ACTOR = "@world";
|
|
9
|
+
/**
|
|
10
|
+
* Shared canonical-envelope constructor for every event kind minted while
|
|
11
|
+
* stepping a tick (and reused by `trace-run.ts` for its post-hoc
|
|
12
|
+
* `marker.seen` events, so there is exactly one place that stamps the
|
|
13
|
+
* causal envelope for simfile-native trace events).
|
|
14
|
+
*/
|
|
15
|
+
export const createTraceEvent = (runId, seq, kind, simTime, actor, target, scope, payload, causeEventIds = []) => createCanonicalEventEnvelope({
|
|
16
|
+
runId,
|
|
17
|
+
seq,
|
|
18
|
+
kind,
|
|
19
|
+
simTime,
|
|
20
|
+
provenance: "mechanical",
|
|
21
|
+
actor,
|
|
22
|
+
target,
|
|
23
|
+
scope,
|
|
24
|
+
payload,
|
|
25
|
+
streamId: DEFAULT_EMITTER_STREAM_ID,
|
|
26
|
+
principalId: DEFAULT_PRINCIPAL_ID,
|
|
27
|
+
causeEventIds
|
|
28
|
+
});
|
|
29
|
+
const runGenerator = (generator, variables, tick, simTime, phase, candidates, runSeed) => {
|
|
30
|
+
const active = generator.when ? generator.when.evaluator.evaluate(generator.when.node, {
|
|
31
|
+
tick,
|
|
32
|
+
simTime,
|
|
33
|
+
phase,
|
|
34
|
+
variables,
|
|
35
|
+
eventsAtTick: candidates
|
|
36
|
+
}) : true;
|
|
37
|
+
if (!active) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (generator.mode === "set") {
|
|
41
|
+
if (!generator.setExpr) {
|
|
42
|
+
throw new Error(`generator ${generator.id} missing set expression`);
|
|
43
|
+
}
|
|
44
|
+
variables[generator.target] = generator.setExpr.evaluate({
|
|
45
|
+
variables,
|
|
46
|
+
tick,
|
|
47
|
+
t: simTime
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (generator.mode === "delta") {
|
|
52
|
+
const delta = generator.deltaExpr
|
|
53
|
+
? generator.deltaExpr.evaluate({
|
|
54
|
+
variables,
|
|
55
|
+
tick,
|
|
56
|
+
t: simTime
|
|
57
|
+
})
|
|
58
|
+
: generator.delta ?? 0;
|
|
59
|
+
variables[generator.target] = (variables[generator.target] ?? 0) + delta;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const [min, max] = generator.uniform ?? [0, 0];
|
|
63
|
+
const delta = drawUniform({
|
|
64
|
+
runSeed,
|
|
65
|
+
generatorId: generator.id,
|
|
66
|
+
tick,
|
|
67
|
+
drawIndex: 0,
|
|
68
|
+
min,
|
|
69
|
+
max
|
|
70
|
+
});
|
|
71
|
+
variables[generator.target] = (variables[generator.target] ?? 0) + delta;
|
|
72
|
+
};
|
|
73
|
+
const runRule = (rule, tick, simTime, phase, tickState, candidates, precision, ranges, runId, nextSeq, emitTickEvent, nextVariables, clockSyncEventId) => {
|
|
74
|
+
const matches = rule.when.evaluator.evaluate(rule.when.node, {
|
|
75
|
+
tick,
|
|
76
|
+
simTime,
|
|
77
|
+
phase,
|
|
78
|
+
variables: tickState,
|
|
79
|
+
eventsAtTick: candidates
|
|
80
|
+
});
|
|
81
|
+
const shouldFire = rule.fireMode === "once"
|
|
82
|
+
? matches && !rule.hasFired
|
|
83
|
+
: matches && !rule.previousMatch;
|
|
84
|
+
rule.previousMatch = matches;
|
|
85
|
+
if (!shouldFire) {
|
|
86
|
+
return nextSeq;
|
|
87
|
+
}
|
|
88
|
+
rule.hasFired = true;
|
|
89
|
+
const target = variableTargetFromActions(rule.spec.do);
|
|
90
|
+
const fired = createTraceEvent(runId, nextSeq, "rule.fired", simTime, rule.id, target, target, {
|
|
91
|
+
rule: rule.id,
|
|
92
|
+
tick,
|
|
93
|
+
sim_time: simTime,
|
|
94
|
+
phase,
|
|
95
|
+
...(rule.variableIds.length > 0 ? { variables: [...rule.variableIds] } : {})
|
|
96
|
+
}, [clockSyncEventId]);
|
|
97
|
+
emitTickEvent(fired);
|
|
98
|
+
candidates.push({ kind: fired.kind, actor: fired.actor, target: fired.target, scope: fired.scope });
|
|
99
|
+
return runRuleActions(runId, nextSeq + 1, rule.id, tick, simTime, phase, rule.spec.do, tickState, precision, ranges, nextVariables, [fired.event_id], rule.variableIds, emitTickEvent);
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Advances the world by exactly one tick: resolve the clock, apply any
|
|
103
|
+
* queued world.acts, run generators, recompute derived variables, evaluate
|
|
104
|
+
* rules (minting their world-effect events), then fold the tick's ending
|
|
105
|
+
* values back into `ctx.state`. This is the pure REFACTOR extraction of
|
|
106
|
+
* `runSimfileTrace`'s former inline per-tick loop body — same inputs, same
|
|
107
|
+
* outputs, same mutation order — so a live driver can call it once per
|
|
108
|
+
* wall-clock tick instead of only ever inside one big batch loop.
|
|
109
|
+
*/
|
|
110
|
+
export const stepSimfileTick = (tick, ctx) => {
|
|
111
|
+
const { simTime, phase } = resolveClockState(ctx.clock, tick);
|
|
112
|
+
const tickEvents = [];
|
|
113
|
+
const candidates = [];
|
|
114
|
+
const emitTickEvent = (event) => {
|
|
115
|
+
tickEvents.push(event);
|
|
116
|
+
candidates.push({ kind: event.kind, actor: event.actor, target: event.target, scope: event.scope });
|
|
117
|
+
};
|
|
118
|
+
let seq = ctx.seq;
|
|
119
|
+
const clockSync = createTraceEvent(ctx.runId, seq, "clock.sync", simTime, WORLD_ACTOR, "global", "global", {
|
|
120
|
+
tick,
|
|
121
|
+
sim_time: simTime,
|
|
122
|
+
phase
|
|
123
|
+
});
|
|
124
|
+
emitTickEvent(clockSync);
|
|
125
|
+
seq += 1;
|
|
126
|
+
const tickState = { ...ctx.state };
|
|
127
|
+
seq = applyWorldActsAtTick(tick, simTime, ctx.worldActsForTick, tickState, {
|
|
128
|
+
runId: ctx.runId,
|
|
129
|
+
precision: ctx.precision,
|
|
130
|
+
ranges: ctx.runtime.ranges,
|
|
131
|
+
variableScopes: ctx.runtime.variableScopes,
|
|
132
|
+
resultsByActId: ctx.worldActResultsByActId,
|
|
133
|
+
nextSeq: seq,
|
|
134
|
+
emit: emitTickEvent
|
|
135
|
+
});
|
|
136
|
+
for (const generator of ctx.runtime.generators) {
|
|
137
|
+
runGenerator(generator, tickState, tick, simTime, phase, candidates, ctx.seed);
|
|
138
|
+
const range = ctx.runtime.ranges.get(generator.target);
|
|
139
|
+
if (!range) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
tickState[generator.target] = clampAndRound(tickState[generator.target] ?? 0, range, ctx.precision);
|
|
143
|
+
}
|
|
144
|
+
for (const variableId of ctx.runtime.derivedOrder) {
|
|
145
|
+
const spec = ctx.runtime.derivedExpressions.get(variableId);
|
|
146
|
+
const range = ctx.runtime.ranges.get(variableId);
|
|
147
|
+
if (!spec || !range) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
tickState[variableId] = clampAndRound(spec.expression.evaluate({
|
|
151
|
+
variables: tickState,
|
|
152
|
+
tick,
|
|
153
|
+
t: simTime
|
|
154
|
+
}), range, ctx.precision);
|
|
155
|
+
}
|
|
156
|
+
const nextVariables = { ...tickState };
|
|
157
|
+
for (const rule of ctx.runtime.rules) {
|
|
158
|
+
seq = runRule(rule, tick, simTime, phase, tickState, candidates, ctx.precision, ctx.runtime.ranges, ctx.runId, seq, emitTickEvent, nextVariables, clockSync.event_id);
|
|
159
|
+
}
|
|
160
|
+
for (const [id, value] of Object.entries(nextVariables)) {
|
|
161
|
+
const range = ctx.runtime.ranges.get(id);
|
|
162
|
+
if (!range) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
ctx.state[id] = clampAndRound(value, range, ctx.precision);
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
events: tickEvents,
|
|
169
|
+
sample: {
|
|
170
|
+
phase,
|
|
171
|
+
sim_time: simTime,
|
|
172
|
+
tick,
|
|
173
|
+
variables: { ...ctx.state }
|
|
174
|
+
},
|
|
175
|
+
nextSeq: seq
|
|
176
|
+
};
|
|
177
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Simfile, SimfileRule, SimfileRuleAction, SimfileVariable } from "../schema/model.js";
|
|
2
|
+
import { ConditionEvaluator, type ConditionNode } from "./condition.js";
|
|
3
|
+
import { type CompiledExpression } from "./expression.js";
|
|
4
|
+
interface RangeSpec {
|
|
5
|
+
min: number;
|
|
6
|
+
max: number;
|
|
7
|
+
}
|
|
8
|
+
interface VariableSpec {
|
|
9
|
+
id: string;
|
|
10
|
+
initial: number;
|
|
11
|
+
range: RangeSpec;
|
|
12
|
+
spec: SimfileVariable;
|
|
13
|
+
}
|
|
14
|
+
interface DerivedSpec {
|
|
15
|
+
expression: CompiledExpression;
|
|
16
|
+
}
|
|
17
|
+
export interface GeneratorRuntime {
|
|
18
|
+
id: string;
|
|
19
|
+
target: string;
|
|
20
|
+
range: RangeSpec;
|
|
21
|
+
mode: "set" | "delta" | "stochastic";
|
|
22
|
+
when?: {
|
|
23
|
+
node: ConditionNode;
|
|
24
|
+
evaluator: ConditionEvaluator;
|
|
25
|
+
};
|
|
26
|
+
delta?: number;
|
|
27
|
+
deltaExpr?: CompiledExpression;
|
|
28
|
+
setExpr?: CompiledExpression;
|
|
29
|
+
uniform?: [number, number];
|
|
30
|
+
}
|
|
31
|
+
export interface RuleRuntime {
|
|
32
|
+
id: string;
|
|
33
|
+
spec: SimfileRule;
|
|
34
|
+
when: {
|
|
35
|
+
node: ConditionNode;
|
|
36
|
+
evaluator: ConditionEvaluator;
|
|
37
|
+
};
|
|
38
|
+
fireMode: "once" | "per_crossing";
|
|
39
|
+
previousMatch: boolean;
|
|
40
|
+
hasFired: boolean;
|
|
41
|
+
/** Every variable id this rule's own `when:` condition references (`conditionVariableIds`) — `[]` for a rule gated on a phase/event condition instead. Threaded onto this rule's `rule.fired` event and every world-effect event it emits, so the viewer can attribute them to that variable's storyline. */
|
|
42
|
+
variableIds: string[];
|
|
43
|
+
}
|
|
44
|
+
export interface CompiledTraceRuntime {
|
|
45
|
+
initialState: Record<string, number>;
|
|
46
|
+
ranges: Map<string, RangeSpec>;
|
|
47
|
+
derivedOrder: string[];
|
|
48
|
+
derivedExpressions: Map<string, DerivedSpec>;
|
|
49
|
+
generators: GeneratorRuntime[];
|
|
50
|
+
rules: RuleRuntime[];
|
|
51
|
+
/** Declared `fed_by` writer per fed variable id (world.act authorization). */
|
|
52
|
+
variableFedBy: Map<string, string>;
|
|
53
|
+
/** Declared scope per variable id (world.act envelope scope). */
|
|
54
|
+
variableScopes: Map<string, string>;
|
|
55
|
+
}
|
|
56
|
+
export declare const parseVariableSpecs: (simfile: Simfile) => Map<string, VariableSpec>;
|
|
57
|
+
export declare const parseDerivedSpecs: (variables: ReadonlyMap<string, VariableSpec>) => {
|
|
58
|
+
order: string[];
|
|
59
|
+
specs: Map<string, DerivedSpec>;
|
|
60
|
+
};
|
|
61
|
+
export declare const compileGenerators: (simfile: Simfile, ranges: Map<string, RangeSpec>) => GeneratorRuntime[];
|
|
62
|
+
export declare const compileRules: (simfile: Simfile) => RuleRuntime[];
|
|
63
|
+
export declare const compileRuntime: (simfile: Simfile) => CompiledTraceRuntime;
|
|
64
|
+
export declare const variableTargetFromActions: (actions: readonly SimfileRuleAction[]) => string;
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=trace-compile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-compile.d.ts","sourceRoot":"","sources":["../../src/runtime/trace-compile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAoB,WAAW,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrH,OAAO,EAAwB,kBAAkB,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC9F,OAAO,EAAqB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,UAAU,SAAS;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,UAAU,WAAW;IACnB,UAAU,EAAE,kBAAkB,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,KAAK,GAAG,OAAO,GAAG,YAAY,CAAC;IACrC,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,SAAS,EAAE,kBAAkB,CAAA;KAAE,CAAC;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,SAAS,EAAE,kBAAkB,CAAA;KAAE,CAAC;IAC7D,QAAQ,EAAE,MAAM,GAAG,cAAc,CAAC;IAClC,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,6SAA6S;IAC7S,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC7C,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,8EAA8E;IAC9E,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,iEAAiE;IACjE,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,eAAO,MAAM,kBAAkB,GAC7B,SAAS,OAAO,KACf,GAAG,CAAC,MAAM,EAAE,YAAY,CAU1B,CAAC;AAmEF,eAAO,MAAM,iBAAiB,GAC5B,WAAW,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,KAC3C;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;CAwCpD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,SAAS,OAAO,EAChB,QAAQ,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,KAC7B,gBAAgB,EAMlB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,KAAG,WAAW,EAY1D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,OAAO,KAAG,oBA2BjD,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,SAAS,SAAS,iBAAiB,EAAE,KAAG,MAOjF,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { parseRange } from "../kernel/range.js";
|
|
2
|
+
import { conditionVariableIds, ConditionEvaluator } from "./condition.js";
|
|
3
|
+
import { compileExpression } from "./expression.js";
|
|
4
|
+
export const parseVariableSpecs = (simfile) => {
|
|
5
|
+
const variables = new Map();
|
|
6
|
+
for (const [id, spec] of Object.entries(simfile.variables)) {
|
|
7
|
+
const range = parseRange(spec.range);
|
|
8
|
+
const initial = spec.initial ?? 0;
|
|
9
|
+
const rawInitial = Number.isFinite(initial) ? initial : 0;
|
|
10
|
+
variables.set(id, { id, initial: rawInitial, range, spec });
|
|
11
|
+
}
|
|
12
|
+
return variables;
|
|
13
|
+
};
|
|
14
|
+
const compileWhen = (node) => ({
|
|
15
|
+
node: node,
|
|
16
|
+
evaluator: new ConditionEvaluator()
|
|
17
|
+
});
|
|
18
|
+
const compareIds = (left, right) => {
|
|
19
|
+
if (left < right)
|
|
20
|
+
return -1;
|
|
21
|
+
if (left > right)
|
|
22
|
+
return 1;
|
|
23
|
+
return 0;
|
|
24
|
+
};
|
|
25
|
+
const compileGenerator = (generatorId, generator, ranges) => {
|
|
26
|
+
const range = ranges.get(generator.variable);
|
|
27
|
+
if (!range) {
|
|
28
|
+
throw new Error(`generator ${generatorId} references unknown variable ${generator.variable}`);
|
|
29
|
+
}
|
|
30
|
+
if (generator.kind === "stochastic") {
|
|
31
|
+
const [min = 0, max = 0] = generator.uniform;
|
|
32
|
+
return {
|
|
33
|
+
id: generatorId,
|
|
34
|
+
target: generator.variable,
|
|
35
|
+
range,
|
|
36
|
+
mode: "stochastic",
|
|
37
|
+
uniform: [min, max],
|
|
38
|
+
when: generator.when ? compileWhen(generator.when) : undefined
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (generator.delta !== undefined) {
|
|
42
|
+
return {
|
|
43
|
+
id: generatorId,
|
|
44
|
+
target: generator.variable,
|
|
45
|
+
range,
|
|
46
|
+
mode: "delta",
|
|
47
|
+
delta: generator.delta,
|
|
48
|
+
when: generator.when ? compileWhen(generator.when) : undefined
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
if (generator.delta_eq !== undefined) {
|
|
52
|
+
return {
|
|
53
|
+
id: generatorId,
|
|
54
|
+
target: generator.variable,
|
|
55
|
+
range,
|
|
56
|
+
mode: "delta",
|
|
57
|
+
deltaExpr: compileExpression(generator.delta_eq),
|
|
58
|
+
when: generator.when ? compileWhen(generator.when) : undefined
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
id: generatorId,
|
|
63
|
+
target: generator.variable,
|
|
64
|
+
range,
|
|
65
|
+
mode: "set",
|
|
66
|
+
setExpr: compileExpression(generator.set_eq ?? "0"),
|
|
67
|
+
when: generator.when ? compileWhen(generator.when) : undefined
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export const parseDerivedSpecs = (variables) => {
|
|
71
|
+
const specs = new Map();
|
|
72
|
+
for (const [id, variable] of variables.entries()) {
|
|
73
|
+
if (variable.spec.derive === undefined) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
specs.set(id, { expression: compileExpression(variable.spec.derive.eq) });
|
|
77
|
+
}
|
|
78
|
+
const order = [];
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
const stack = new Set();
|
|
81
|
+
const visit = (variableId) => {
|
|
82
|
+
if (seen.has(variableId)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (stack.has(variableId)) {
|
|
86
|
+
throw new Error(`derived variable cycle at ${variableId}`);
|
|
87
|
+
}
|
|
88
|
+
stack.add(variableId);
|
|
89
|
+
const spec = specs.get(variableId);
|
|
90
|
+
if (spec) {
|
|
91
|
+
for (const dependency of spec.expression.dependencies) {
|
|
92
|
+
if (specs.has(dependency)) {
|
|
93
|
+
visit(dependency);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
stack.delete(variableId);
|
|
98
|
+
seen.add(variableId);
|
|
99
|
+
order.push(variableId);
|
|
100
|
+
};
|
|
101
|
+
for (const variableId of specs.keys()) {
|
|
102
|
+
visit(variableId);
|
|
103
|
+
}
|
|
104
|
+
return { order, specs };
|
|
105
|
+
};
|
|
106
|
+
export const compileGenerators = (simfile, ranges) => {
|
|
107
|
+
return Object.entries(simfile.generators)
|
|
108
|
+
.sort(([left], [right]) => compareIds(left, right))
|
|
109
|
+
.map(([generatorId, generator]) => compileGenerator(generatorId, generator, ranges));
|
|
110
|
+
};
|
|
111
|
+
export const compileRules = (simfile) => {
|
|
112
|
+
return Object.entries(simfile.rules)
|
|
113
|
+
.sort(([left], [right]) => compareIds(left, right))
|
|
114
|
+
.map(([ruleId, rule]) => ({
|
|
115
|
+
id: ruleId,
|
|
116
|
+
spec: rule,
|
|
117
|
+
when: compileWhen(rule.when),
|
|
118
|
+
fireMode: rule.fire,
|
|
119
|
+
previousMatch: false,
|
|
120
|
+
hasFired: false,
|
|
121
|
+
variableIds: conditionVariableIds(rule.when)
|
|
122
|
+
}));
|
|
123
|
+
};
|
|
124
|
+
export const compileRuntime = (simfile) => {
|
|
125
|
+
const variables = parseVariableSpecs(simfile);
|
|
126
|
+
const initialState = {};
|
|
127
|
+
const ranges = new Map();
|
|
128
|
+
const variableFedBy = new Map();
|
|
129
|
+
const variableScopes = new Map();
|
|
130
|
+
for (const [id, spec] of variables.entries()) {
|
|
131
|
+
initialState[id] = spec.initial;
|
|
132
|
+
ranges.set(id, spec.range);
|
|
133
|
+
variableScopes.set(id, spec.spec.scope);
|
|
134
|
+
if (spec.spec.fed_by !== undefined) {
|
|
135
|
+
variableFedBy.set(id, spec.spec.fed_by);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const { order, specs: derivedExpressions } = parseDerivedSpecs(variables);
|
|
139
|
+
return {
|
|
140
|
+
initialState,
|
|
141
|
+
ranges,
|
|
142
|
+
derivedOrder: order,
|
|
143
|
+
derivedExpressions,
|
|
144
|
+
generators: compileGenerators(simfile, ranges),
|
|
145
|
+
rules: compileRules(simfile),
|
|
146
|
+
variableFedBy,
|
|
147
|
+
variableScopes
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
export const variableTargetFromActions = (actions) => {
|
|
151
|
+
for (const action of actions) {
|
|
152
|
+
if ("to" in action) {
|
|
153
|
+
return action.to;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return "global";
|
|
157
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { scanMarkers, type MarkerDefinition } from "../ledger/markers.js";
|
|
2
|
+
import type { RuntimeTraceEvent } from "./types.js";
|
|
3
|
+
export declare const serializeCanonicalEvents: (events: readonly RuntimeTraceEvent[]) => string[];
|
|
4
|
+
export declare const scanTraceMarkers: (events: readonly RuntimeTraceEvent[], markers: Record<string, MarkerDefinition>) => ReturnType<typeof scanMarkers>;
|
|
5
|
+
//# sourceMappingURL=trace-export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-export.d.ts","sourceRoot":"","sources":["../../src/runtime/trace-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,eAAO,MAAM,wBAAwB,GAAI,QAAQ,SAAS,iBAAiB,EAAE,KAAG,MAAM,EACzD,CAAC;AAE9B,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,SAAS,iBAAiB,EAAE,EACpC,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,KACxC,UAAU,CAAC,OAAO,WAAW,CAAiC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { scanMarkers } from "../ledger/markers.js";
|
|
2
|
+
import { stableStringify } from "../ledger/stable.js";
|
|
3
|
+
export const serializeCanonicalEvents = (events) => events.map(stableStringify);
|
|
4
|
+
export const scanTraceMarkers = (events, markers) => scanMarkers(events, markers);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Simfile } from "../schema/model.js";
|
|
2
|
+
import type { RuntimeOptions, RuntimeTrace } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Executes a bounded deterministic trace by looping `stepSimfileTick` once
|
|
5
|
+
* per tick (the REFACTOR extraction, Slice memetics-a): all per-tick
|
|
6
|
+
* mechanics — clock resolve, world-act application, generators, derived
|
|
7
|
+
* variables, rules — live in `step-tick.ts` now, so a live driver can call
|
|
8
|
+
* the exact same function once per wall-clock tick instead of only inside
|
|
9
|
+
* this one big batch loop. This function's own job shrinks to setup
|
|
10
|
+
* (compile + initial state + world-act ingestion), the loop itself, and the
|
|
11
|
+
* post-hoc marker scan over the whole run's events — output is unchanged
|
|
12
|
+
* from before the extraction (see `trace.test.ts`, which is untouched).
|
|
13
|
+
*/
|
|
14
|
+
export declare const runSimfileTrace: (simfile: Simfile, options: RuntimeOptions) => RuntimeTrace;
|
|
15
|
+
//# sourceMappingURL=trace-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-run.d.ts","sourceRoot":"","sources":["../../src/runtime/trace-run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAKlD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAA4C,MAAM,YAAY,CAAC;AAYzG;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,OAAO,EAAE,SAAS,cAAc,KAAG,YAyE3E,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { scanMarkers } from "../ledger/markers.js";
|
|
2
|
+
import { parseClockSpec } from "./clock.js";
|
|
3
|
+
import { clampAndRound } from "./numeric.js";
|
|
4
|
+
import { createTraceEvent, stepSimfileTick } from "./step-tick.js";
|
|
5
|
+
import { compileRuntime } from "./trace-compile.js";
|
|
6
|
+
import { ingestWorldActs } from "./world-act.js";
|
|
7
|
+
const DEFAULT_PRECISION = 6;
|
|
8
|
+
const EVENT_FUSE_LIMIT = 5_000;
|
|
9
|
+
const validateNonNegativeInteger = (value, name) => {
|
|
10
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
11
|
+
throw new Error(`${name} must be a non-negative integer`);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Executes a bounded deterministic trace by looping `stepSimfileTick` once
|
|
16
|
+
* per tick (the REFACTOR extraction, Slice memetics-a): all per-tick
|
|
17
|
+
* mechanics — clock resolve, world-act application, generators, derived
|
|
18
|
+
* variables, rules — live in `step-tick.ts` now, so a live driver can call
|
|
19
|
+
* the exact same function once per wall-clock tick instead of only inside
|
|
20
|
+
* this one big batch loop. This function's own job shrinks to setup
|
|
21
|
+
* (compile + initial state + world-act ingestion), the loop itself, and the
|
|
22
|
+
* post-hoc marker scan over the whole run's events — output is unchanged
|
|
23
|
+
* from before the extraction (see `trace.test.ts`, which is untouched).
|
|
24
|
+
*/
|
|
25
|
+
export const runSimfileTrace = (simfile, options) => {
|
|
26
|
+
const precision = Math.max(0, Math.floor(options.precision ?? DEFAULT_PRECISION));
|
|
27
|
+
validateNonNegativeInteger(precision, "precision");
|
|
28
|
+
validateNonNegativeInteger(options.ticks, "ticks");
|
|
29
|
+
const clock = parseClockSpec(simfile.clock);
|
|
30
|
+
const runtime = compileRuntime(simfile);
|
|
31
|
+
const state = {};
|
|
32
|
+
for (const [id, value] of Object.entries(runtime.initialState)) {
|
|
33
|
+
const range = runtime.ranges.get(id);
|
|
34
|
+
if (!range) {
|
|
35
|
+
throw new Error(`variable ${id} missing range`);
|
|
36
|
+
}
|
|
37
|
+
state[id] = clampAndRound(value, range, precision);
|
|
38
|
+
}
|
|
39
|
+
const worldActIngestion = ingestWorldActs(options.worldActs ?? [], {
|
|
40
|
+
ticks: options.ticks,
|
|
41
|
+
ranges: runtime.ranges,
|
|
42
|
+
variableFedBy: runtime.variableFedBy
|
|
43
|
+
});
|
|
44
|
+
const events = [];
|
|
45
|
+
const samples = [];
|
|
46
|
+
let seq = 1;
|
|
47
|
+
const emitEvent = (event) => {
|
|
48
|
+
events.push(event);
|
|
49
|
+
if (events.length > options.ticks * EVENT_FUSE_LIMIT) {
|
|
50
|
+
throw new Error(`event fuse tripped at ${events.length} events`);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
for (let tick = 0; tick < options.ticks; tick += 1) {
|
|
54
|
+
const step = stepSimfileTick(tick, {
|
|
55
|
+
runId: options.runId,
|
|
56
|
+
seed: options.seed,
|
|
57
|
+
precision,
|
|
58
|
+
clock,
|
|
59
|
+
runtime,
|
|
60
|
+
state,
|
|
61
|
+
seq,
|
|
62
|
+
worldActsForTick: worldActIngestion.queueByTick.get(tick),
|
|
63
|
+
worldActResultsByActId: worldActIngestion.resultsByActId
|
|
64
|
+
});
|
|
65
|
+
seq = step.nextSeq;
|
|
66
|
+
samples.push(step.sample);
|
|
67
|
+
for (const event of step.events) {
|
|
68
|
+
emitEvent(event);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (const [markerId, hits] of Object.entries(scanMarkers(events, simfile.markers))) {
|
|
72
|
+
for (const hit of hits) {
|
|
73
|
+
emitEvent(createTraceEvent(options.runId, seq, "marker.seen", hit.simTime, markerId, hit.scope, hit.scope, {
|
|
74
|
+
alias: hit.alias,
|
|
75
|
+
marker: markerId,
|
|
76
|
+
source_event_id: hit.eventId,
|
|
77
|
+
source_event_kind: hit.eventKind
|
|
78
|
+
}, [hit.eventId]));
|
|
79
|
+
seq += 1;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
runId: options.runId,
|
|
84
|
+
seed: options.seed,
|
|
85
|
+
ticks: options.ticks,
|
|
86
|
+
variables: state,
|
|
87
|
+
events,
|
|
88
|
+
samples,
|
|
89
|
+
diagnostics: [],
|
|
90
|
+
actResults: worldActIngestion.results
|
|
91
|
+
};
|
|
92
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./clock.js";
|
|
2
|
+
export * from "./condition.js";
|
|
3
|
+
export * from "./expression.js";
|
|
4
|
+
export * from "./run-record.js";
|
|
5
|
+
export * from "./step-tick.js";
|
|
6
|
+
export * from "./trace-export.js";
|
|
7
|
+
export * from "./trace-run.js";
|
|
8
|
+
export * from "./viewer-trace.js";
|
|
9
|
+
export * from "./world-act.js";
|
|
10
|
+
//# sourceMappingURL=trace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/runtime/trace.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./clock.js";
|
|
2
|
+
export * from "./condition.js";
|
|
3
|
+
export * from "./expression.js";
|
|
4
|
+
export * from "./run-record.js";
|
|
5
|
+
export * from "./step-tick.js";
|
|
6
|
+
export * from "./trace-export.js";
|
|
7
|
+
export * from "./trace-run.js";
|
|
8
|
+
export * from "./viewer-trace.js";
|
|
9
|
+
export * from "./world-act.js";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { LedgerEventEnvelope } from "../ledger/stable.js";
|
|
2
|
+
/**
|
|
3
|
+
* A world.act queued for deterministic ingestion at a given tick. This is the
|
|
4
|
+
* B58 driver stand-in for a live agent tool call: `run_id`, `actor`,
|
|
5
|
+
* `principal_id`, and `cause_event_ids` are trusted-injection fields (never
|
|
6
|
+
* model-supplied); `act_id`, `action`, `variable`, `value` are the only
|
|
7
|
+
* model-authored fields per the `world_act` tool surface.
|
|
8
|
+
*/
|
|
9
|
+
export interface QueuedWorldAct {
|
|
10
|
+
at_tick: number;
|
|
11
|
+
act_id: string;
|
|
12
|
+
action: "variable:set";
|
|
13
|
+
variable: string;
|
|
14
|
+
value: number;
|
|
15
|
+
actor: string;
|
|
16
|
+
principal_id: string;
|
|
17
|
+
cause_event_ids?: string[];
|
|
18
|
+
}
|
|
19
|
+
/** Rejection codes for a queued world.act, in ingestion check order. */
|
|
20
|
+
export type WorldActRejectionCode = "unknown_variable" | "not_authorized" | "out_of_range" | "not_finite" | "duplicate" | "run_closed";
|
|
21
|
+
/** Tool-facing outcome of ingesting a single queued world.act. */
|
|
22
|
+
export interface WorldActResult {
|
|
23
|
+
accepted: boolean;
|
|
24
|
+
act_id: string;
|
|
25
|
+
event_id?: string;
|
|
26
|
+
apply_tick?: number;
|
|
27
|
+
code?: WorldActRejectionCode;
|
|
28
|
+
}
|
|
29
|
+
export interface RuntimeOptions {
|
|
30
|
+
runId: string;
|
|
31
|
+
seed: string;
|
|
32
|
+
ticks: number;
|
|
33
|
+
precision?: number;
|
|
34
|
+
worldActs?: readonly QueuedWorldAct[];
|
|
35
|
+
}
|
|
36
|
+
export type RuntimeTraceEventPayload = Record<string, unknown> | Array<unknown> | string | number | boolean | null;
|
|
37
|
+
/**
|
|
38
|
+
* A single runtime-emitted trace event. This is a `LedgerEventEnvelope`: every
|
|
39
|
+
* event produced by `runSimfileTrace` carries the full causal envelope
|
|
40
|
+
* (version, run_id, emitter, principal_id, recorded_at, cause_event_ids) —
|
|
41
|
+
* those fields are typed optional here only so hand-written fixtures in other
|
|
42
|
+
* modules' tests (which predate the causal envelope) keep type-checking.
|
|
43
|
+
*/
|
|
44
|
+
export type RuntimeTraceEvent = LedgerEventEnvelope<RuntimeTraceEventPayload>;
|
|
45
|
+
export interface RuntimeVariableSample {
|
|
46
|
+
phase: string | undefined;
|
|
47
|
+
sim_time: number;
|
|
48
|
+
tick: number;
|
|
49
|
+
variables: Record<string, number>;
|
|
50
|
+
}
|
|
51
|
+
export interface RuntimeTrace {
|
|
52
|
+
runId: string;
|
|
53
|
+
seed: string;
|
|
54
|
+
ticks: number;
|
|
55
|
+
variables: Record<string, number>;
|
|
56
|
+
events: RuntimeTraceEvent[];
|
|
57
|
+
samples: RuntimeVariableSample[];
|
|
58
|
+
diagnostics: string[];
|
|
59
|
+
actResults: WorldActResult[];
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=types.d.ts.map
|