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
package/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Simfile
|
|
2
|
+
|
|
3
|
+
> Deterministic simulation worlds for societies of agents — seed an idea, run the world, and watch it move through minds.
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/simfile"><img src="https://img.shields.io/npm/v/simfile?style=flat-square&color=7c5cff&label=npm" alt="npm"></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/simfile"><img src="https://img.shields.io/npm/dm/simfile?style=flat-square&color=7c5cff" alt="downloads"></a>
|
|
8
|
+
<a href="#install"><img src="https://img.shields.io/node/v/simfile?style=flat-square&color=7c5cff" alt="node"></a>
|
|
9
|
+
<a href="LICENSE"><img src="https://img.shields.io/npm/l/simfile?style=flat-square&color=7c5cff" alt="MIT"></a>
|
|
10
|
+
<a href="https://simfile.org"><img src="https://img.shields.io/website?url=https%3A%2F%2Fsimfile.org&style=flat-square&label=simfile.org&color=7c5cff" alt="website"></a>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
Spawnfile declares *who* runs and how an organization is wired — agents, teams, rooms, runtimes, memory. **Simfile declares the *world* around them** — a clock, variables, generators, rules, markers, probes, and a run ledger — then runs it and lets you watch.
|
|
14
|
+
|
|
15
|
+
Seed a secret into one agent's memory and watch it spread through the society, tick by tick. Open an agent that is *itself* an organization — a Jungian self whose Shadow and Anima deliberate in an inner room — and descend into it. Every message, wake, turn, memory write, and variable change is a ledger event, so the viewer scrubs the whole run backward and forward and every glyph on screen traces to a record.
|
|
16
|
+
|
|
17
|
+
Deterministic and replayable. Observer-tier by design: Simfile authors and observes worlds — it compiles no Docker images and deploys no agents. That is [**Spawnfile**](https://spawnfile.com)'s job (the organization that runs *in* the world), talking over [**Moltnet**](https://moltnet.dev) (the rooms the agents share).
|
|
18
|
+
|
|
19
|
+
## Contents
|
|
20
|
+
|
|
21
|
+
- [Install](#install)
|
|
22
|
+
- [Quick start](#quick-start)
|
|
23
|
+
- [What you can see](#what-you-can-see)
|
|
24
|
+
- [The world](#the-world)
|
|
25
|
+
- [Example](#example)
|
|
26
|
+
- [Observe](#observe)
|
|
27
|
+
- [Repo guide](#repo-guide)
|
|
28
|
+
- [Docs](#docs)
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install simfile
|
|
34
|
+
simfile --help
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Node.js 22+.
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
simfile validate ./Simfile.yaml # check a world
|
|
43
|
+
simfile view runs/<id> # replay a sealed run — scrub, descend, watch spread
|
|
44
|
+
simfile view --state .sim # watch a live world
|
|
45
|
+
simfile observe runs/<id> # reconcile causal chains + measure spread → report.json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## What you can see
|
|
49
|
+
|
|
50
|
+
`simfile view <run-dir>` serves a local web app that turns a run into an instrument, not a screensaver:
|
|
51
|
+
|
|
52
|
+
- **Scrub the whole run.** One causally-ordered timeline — play, rewind, step. The world map, the room chat, and every agent's memory all move together off a single cursor.
|
|
53
|
+
- **Watch a meme spread.** A secret seeded *only* in one agent's private memory surfaces in conversation and reaches others on its own; the timeline lights up where it lands, with reach, latency, and match fidelity — re-derived from the sealed run, never faked.
|
|
54
|
+
- **Descend into a mind.** Click an agent that is itself an org (a Jungian self) and drop into its inner council: the archetypes deliberate, the representative synthesizes and answers out. Recursion by data — an agent *is* an organization you haven't opened yet.
|
|
55
|
+
- **Per-element storylines.** An agent, a room, a memory bank, a variable — each has its own timeline you can open, all linked to the one global cursor.
|
|
56
|
+
|
|
57
|
+
Every element carries its real ledger id, and a run-header badge always discloses whether the dialogue came from real engines or a scripted screenplay.
|
|
58
|
+
|
|
59
|
+
## The world
|
|
60
|
+
|
|
61
|
+
A `Simfile` declares world mechanics, kept deliberately genre-neutral:
|
|
62
|
+
|
|
63
|
+
| Key | What it is |
|
|
64
|
+
|---|---|
|
|
65
|
+
| **clock** | ticks, phases, sim-time |
|
|
66
|
+
| **variables** | scoped state with ranges |
|
|
67
|
+
| **generators** | deterministic or stochastic drivers that move variables |
|
|
68
|
+
| **rules** | `when` conditions → effects (wake an agent, post a world message) |
|
|
69
|
+
| **markers** | scan room traffic for tokens (a seeded secret, a name) |
|
|
70
|
+
| **probes** | scored assertions evaluated over a run |
|
|
71
|
+
| **run ledger** | the canonical, causally-ordered record everything else is measured against |
|
|
72
|
+
|
|
73
|
+
Domain concepts live in fixtures, never in schema keys.
|
|
74
|
+
|
|
75
|
+
## Example
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
simfile_version: "0.1"
|
|
79
|
+
name: autonomous-office-world
|
|
80
|
+
spawnfile: ./Spawnfile
|
|
81
|
+
|
|
82
|
+
clock:
|
|
83
|
+
seed: office-run-014
|
|
84
|
+
tick: 20s
|
|
85
|
+
sim_per_tick: 10m
|
|
86
|
+
phases: { morning: "07:00", workday: "09:00", evening: "18:00", night: "22:00" }
|
|
87
|
+
|
|
88
|
+
variables:
|
|
89
|
+
filing_pressure:
|
|
90
|
+
scope: room:office-floor:case-warroom
|
|
91
|
+
initial: 0.4
|
|
92
|
+
range: 0..1
|
|
93
|
+
|
|
94
|
+
generators:
|
|
95
|
+
deadline_ramp:
|
|
96
|
+
kind: deterministic
|
|
97
|
+
when: { phase: workday }
|
|
98
|
+
variable: filing_pressure
|
|
99
|
+
delta: 0.02
|
|
100
|
+
|
|
101
|
+
rules:
|
|
102
|
+
deadline_bites:
|
|
103
|
+
when: { variable: filing_pressure, above: 0.85 }
|
|
104
|
+
do:
|
|
105
|
+
- action: wake:recommend
|
|
106
|
+
to: room:office-floor:case-warroom
|
|
107
|
+
|
|
108
|
+
markers:
|
|
109
|
+
tenant_name:
|
|
110
|
+
text: [Rosa Delgado]
|
|
111
|
+
mode: containment
|
|
112
|
+
scopes: [room:office-floor:case-warroom]
|
|
113
|
+
|
|
114
|
+
probes:
|
|
115
|
+
deadline_observed:
|
|
116
|
+
when: { event: wake.recommended, target: room:office-floor:case-warroom }
|
|
117
|
+
expect: { at_least: 1 }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Observe
|
|
121
|
+
|
|
122
|
+
`simfile observe <run-dir>` reconciles every authority's causal stream — Moltnet, Daimon, Mneme, and the world kernel — into one honest verdict: complete vs. incomplete causal chains, per-agent memory, failures, and, for a seeded world, spread measurement (channel · reach · latency · fidelity) re-derived from sealed artifacts. Ordering is causal, never wall-clock; a missing link is reported, never stitched.
|
|
123
|
+
|
|
124
|
+
## Repo guide
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
src/schema v0.1 world schema + validator
|
|
128
|
+
src/runtime deterministic world kernel (clock, generators, rules, markers, probes)
|
|
129
|
+
src/observe causal reconciliation + spread measurement
|
|
130
|
+
src/view + web the run-replay viewer (React), served by `simfile view`
|
|
131
|
+
src/sims composed-run drivers (shell Spawnfile, seed, observe)
|
|
132
|
+
docs/ design + research (DESIGN, VIEW_DESIGN, VIEW_STYLEGUIDE, …)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Simfile hardcodes constraints, not conclusions: it defines stable mechanics and observability, and leaves interpretation, strategy, dialogue, memory choice, and culture to the agents.
|
|
136
|
+
|
|
137
|
+
## Docs
|
|
138
|
+
|
|
139
|
+
Full documentation at [**simfile.org**](https://simfile.org). Design and research notes live in [`docs/`](docs/).
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAuRA,eAAO,MAAM,MAAM,GAAU,MAAM,SAAS,MAAM,EAAE,KAAG,OAAO,CAAC,MAAM,CAiJpE,CAAC"}
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { ZodError } from "zod";
|
|
5
|
+
import { createBindingDiagnostics, loadSpawnfileReport, parseSimfileSource } from "../schema/index.js";
|
|
6
|
+
import { runObserve, writeObserveReport } from "../observe/index.js";
|
|
7
|
+
import { writeRunRecord } from "../runtime/trace.js";
|
|
8
|
+
import { runViewCommand } from "../view/index.js";
|
|
9
|
+
const usage = () => [
|
|
10
|
+
"Usage:",
|
|
11
|
+
" simfile validate <path> [--json] [--spawnfile-report <path>|<json>]",
|
|
12
|
+
" simfile run <path> --ticks <n> [--out <dir>] [--seed <seed>] [--run-id <id>] [--acts <path>] [--moltnet-artifact transcript|delivery] [--spawnfile-report <path>|<json>]",
|
|
13
|
+
" simfile observe <run-dir> [--json]",
|
|
14
|
+
" simfile view --state <path>",
|
|
15
|
+
" simfile view <run-record-dir>",
|
|
16
|
+
" simfile view --help",
|
|
17
|
+
" simfile --help",
|
|
18
|
+
""
|
|
19
|
+
].join("\n");
|
|
20
|
+
const formatError = (error) => {
|
|
21
|
+
if (error instanceof ZodError) {
|
|
22
|
+
return error.issues.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`).join("\n");
|
|
23
|
+
}
|
|
24
|
+
return error instanceof Error ? error.message : String(error);
|
|
25
|
+
};
|
|
26
|
+
const parseObserveArguments = (argv) => {
|
|
27
|
+
const options = {};
|
|
28
|
+
for (const arg of argv) {
|
|
29
|
+
if (arg === "--json") {
|
|
30
|
+
options.json = true;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (arg.startsWith("-")) {
|
|
34
|
+
return { error: `Unknown flag ${arg}` };
|
|
35
|
+
}
|
|
36
|
+
if (options.runDir !== undefined) {
|
|
37
|
+
return { error: `Unexpected positional argument ${arg}` };
|
|
38
|
+
}
|
|
39
|
+
options.runDir = arg;
|
|
40
|
+
}
|
|
41
|
+
if (!options.runDir)
|
|
42
|
+
return { error: "Missing run directory" };
|
|
43
|
+
return { options };
|
|
44
|
+
};
|
|
45
|
+
const parseOptionalValueFlag = (arg, argv, index, flag, errorMessage) => {
|
|
46
|
+
if (arg.startsWith(`${flag}=`)) {
|
|
47
|
+
return { consumed: true, value: arg.slice(flag.length + 1) };
|
|
48
|
+
}
|
|
49
|
+
if (arg !== flag) {
|
|
50
|
+
return { consumed: false };
|
|
51
|
+
}
|
|
52
|
+
const value = argv[index + 1];
|
|
53
|
+
if (!value) {
|
|
54
|
+
return { error: errorMessage, consumed: false };
|
|
55
|
+
}
|
|
56
|
+
return { consumed: true, value };
|
|
57
|
+
};
|
|
58
|
+
const parseValidateArguments = (argv) => {
|
|
59
|
+
const options = {};
|
|
60
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
61
|
+
const arg = argv[index];
|
|
62
|
+
if (arg === "--json") {
|
|
63
|
+
options.json = true;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const parsedReport = parseOptionalValueFlag(arg, argv, index, "--spawnfile-report", "Missing value for --spawnfile-report");
|
|
67
|
+
if (parsedReport.error)
|
|
68
|
+
return { error: parsedReport.error };
|
|
69
|
+
if (parsedReport.consumed) {
|
|
70
|
+
options.spawnfileReport = parsedReport.value;
|
|
71
|
+
if (arg === "--spawnfile-report")
|
|
72
|
+
index += 1;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (arg.startsWith("-")) {
|
|
76
|
+
return { error: `Unknown flag ${arg}` };
|
|
77
|
+
}
|
|
78
|
+
if (options.path !== undefined) {
|
|
79
|
+
return { error: `Unexpected positional argument ${arg}` };
|
|
80
|
+
}
|
|
81
|
+
options.path = arg;
|
|
82
|
+
}
|
|
83
|
+
if (!options.path)
|
|
84
|
+
return { error: "Missing Simfile path" };
|
|
85
|
+
return { options };
|
|
86
|
+
};
|
|
87
|
+
const parseRunArguments = (argv) => {
|
|
88
|
+
const options = {};
|
|
89
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
90
|
+
const arg = argv[index];
|
|
91
|
+
if (arg === "--ticks") {
|
|
92
|
+
const value = argv[index + 1];
|
|
93
|
+
if (!value)
|
|
94
|
+
return { error: "Missing value for --ticks" };
|
|
95
|
+
const ticks = Number(value);
|
|
96
|
+
if (!Number.isInteger(ticks) || ticks < 0)
|
|
97
|
+
return { error: "Invalid value for --ticks" };
|
|
98
|
+
options.ticks = ticks;
|
|
99
|
+
index += 1;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (arg.startsWith("--ticks=")) {
|
|
103
|
+
const ticks = Number(arg.slice("--ticks=".length));
|
|
104
|
+
if (!Number.isInteger(ticks) || ticks < 0)
|
|
105
|
+
return { error: "Invalid value for --ticks" };
|
|
106
|
+
options.ticks = ticks;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (arg === "--moltnet-artifact") {
|
|
110
|
+
const value = argv[index + 1];
|
|
111
|
+
if (value !== "delivery" && value !== "transcript") {
|
|
112
|
+
return { error: "Invalid value for --moltnet-artifact" };
|
|
113
|
+
}
|
|
114
|
+
options.moltnetArtifact = value;
|
|
115
|
+
index += 1;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (arg.startsWith("--moltnet-artifact=")) {
|
|
119
|
+
const value = arg.slice("--moltnet-artifact=".length);
|
|
120
|
+
if (value !== "delivery" && value !== "transcript") {
|
|
121
|
+
return { error: "Invalid value for --moltnet-artifact" };
|
|
122
|
+
}
|
|
123
|
+
options.moltnetArtifact = value;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (arg === "--out" || arg === "--seed" || arg === "--run-id" || arg === "--acts") {
|
|
127
|
+
const parsed = parseOptionalValueFlag(arg, argv, index, arg, `Missing value for ${arg}`);
|
|
128
|
+
if (parsed.error)
|
|
129
|
+
return { error: parsed.error };
|
|
130
|
+
if (parsed.value === undefined)
|
|
131
|
+
return { error: `Missing value for ${arg}` };
|
|
132
|
+
if (arg === "--out")
|
|
133
|
+
options.outDir = parsed.value;
|
|
134
|
+
if (arg === "--seed")
|
|
135
|
+
options.seed = parsed.value;
|
|
136
|
+
if (arg === "--run-id")
|
|
137
|
+
options.runId = parsed.value;
|
|
138
|
+
if (arg === "--acts")
|
|
139
|
+
options.actsPath = parsed.value;
|
|
140
|
+
index += 1;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (arg.startsWith("--out=")) {
|
|
144
|
+
options.outDir = arg.slice("--out=".length);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (arg.startsWith("--seed=")) {
|
|
148
|
+
options.seed = arg.slice("--seed=".length);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (arg.startsWith("--run-id=")) {
|
|
152
|
+
options.runId = arg.slice("--run-id=".length);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (arg.startsWith("--acts=")) {
|
|
156
|
+
options.actsPath = arg.slice("--acts=".length);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const parsedReport = parseOptionalValueFlag(arg, argv, index, "--spawnfile-report", "Missing value for --spawnfile-report");
|
|
160
|
+
if (parsedReport.error)
|
|
161
|
+
return { error: parsedReport.error };
|
|
162
|
+
if (parsedReport.consumed) {
|
|
163
|
+
options.spawnfileReport = parsedReport.value;
|
|
164
|
+
if (arg === "--spawnfile-report")
|
|
165
|
+
index += 1;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (arg.startsWith("-")) {
|
|
169
|
+
return { error: `Unknown flag ${arg}` };
|
|
170
|
+
}
|
|
171
|
+
if (options.path !== undefined) {
|
|
172
|
+
return { error: `Unexpected positional argument ${arg}` };
|
|
173
|
+
}
|
|
174
|
+
options.path = arg;
|
|
175
|
+
}
|
|
176
|
+
if (!options.path)
|
|
177
|
+
return { error: "Missing Simfile path" };
|
|
178
|
+
if (options.ticks === undefined)
|
|
179
|
+
return { error: "Missing required --ticks" };
|
|
180
|
+
return { options };
|
|
181
|
+
};
|
|
182
|
+
const defaultRunId = (seed) => seed.replace(/[^a-zA-Z0-9_.-]+/gu, "-").replace(/^-+|-+$/gu, "") || "run";
|
|
183
|
+
const toBindingDiagnostics = (warnings) => warnings.map((message) => ({ level: "warn", message }));
|
|
184
|
+
const bindingWarningsFromReport = async (simfile, reportSource) => {
|
|
185
|
+
if (!reportSource) {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
return createBindingDiagnostics(simfile, await loadSpawnfileReport(reportSource));
|
|
189
|
+
};
|
|
190
|
+
const hasErrorDiagnostic = (diagnostics) => diagnostics.some((diagnostic) => diagnostic.level === "error");
|
|
191
|
+
const loadQueuedWorldActs = async (actsPath) => {
|
|
192
|
+
if (!actsPath) {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
const raw = JSON.parse(await readFile(actsPath, "utf8"));
|
|
196
|
+
if (!Array.isArray(raw)) {
|
|
197
|
+
throw new Error(`--acts file must contain a JSON array: ${actsPath}`);
|
|
198
|
+
}
|
|
199
|
+
return raw;
|
|
200
|
+
};
|
|
201
|
+
const printDiagnostics = (diagnostics) => {
|
|
202
|
+
for (const diagnostic of diagnostics) {
|
|
203
|
+
const prefix = diagnostic.level === "error" ? "error" : "warning";
|
|
204
|
+
process.stderr.write(`${prefix}: ${diagnostic.message}\n`);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
export const runCli = async (argv) => {
|
|
208
|
+
const [command, ...rest] = argv;
|
|
209
|
+
if (command === "--help" || command === "-h" || command === undefined) {
|
|
210
|
+
process.stdout.write(usage());
|
|
211
|
+
return command === undefined ? 1 : 0;
|
|
212
|
+
}
|
|
213
|
+
if (command === "validate") {
|
|
214
|
+
const parsed = parseValidateArguments(rest);
|
|
215
|
+
if (parsed.error || !parsed.options?.path) {
|
|
216
|
+
if (parsed.error)
|
|
217
|
+
process.stderr.write(`${parsed.error}\n`);
|
|
218
|
+
process.stderr.write(usage());
|
|
219
|
+
return 1;
|
|
220
|
+
}
|
|
221
|
+
const path = parsed.options.path;
|
|
222
|
+
try {
|
|
223
|
+
const source = await readFile(path, "utf8");
|
|
224
|
+
const result = parseSimfileSource(source, { path });
|
|
225
|
+
const diagnostics = [
|
|
226
|
+
...toBindingDiagnostics(result.warnings),
|
|
227
|
+
...await bindingWarningsFromReport(result.simfile, parsed.options.spawnfileReport)
|
|
228
|
+
];
|
|
229
|
+
if (parsed.options.json) {
|
|
230
|
+
process.stdout.write(`${JSON.stringify({
|
|
231
|
+
diagnostics,
|
|
232
|
+
ok: !hasErrorDiagnostic(diagnostics),
|
|
233
|
+
path
|
|
234
|
+
}, null, 2)}\n`);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
printDiagnostics(diagnostics);
|
|
238
|
+
if (hasErrorDiagnostic(diagnostics)) {
|
|
239
|
+
process.stderr.write(`failed to validate ${path}\n`);
|
|
240
|
+
return 1;
|
|
241
|
+
}
|
|
242
|
+
process.stdout.write(`validated ${path}\n`);
|
|
243
|
+
}
|
|
244
|
+
return hasErrorDiagnostic(diagnostics) ? 1 : 0;
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
process.stderr.write(`${formatError(error)}\n`);
|
|
248
|
+
return 1;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (command === "run") {
|
|
252
|
+
const parsed = parseRunArguments(rest);
|
|
253
|
+
if (parsed.error || !parsed.options?.path || parsed.options.ticks === undefined) {
|
|
254
|
+
if (parsed.error)
|
|
255
|
+
process.stderr.write(`${parsed.error}\n`);
|
|
256
|
+
process.stderr.write(usage());
|
|
257
|
+
return 1;
|
|
258
|
+
}
|
|
259
|
+
const path = parsed.options.path;
|
|
260
|
+
try {
|
|
261
|
+
const source = await readFile(path, "utf8");
|
|
262
|
+
const result = parseSimfileSource(source, { path });
|
|
263
|
+
const diagnostics = [
|
|
264
|
+
...toBindingDiagnostics(result.warnings),
|
|
265
|
+
...await bindingWarningsFromReport(result.simfile, parsed.options.spawnfileReport)
|
|
266
|
+
];
|
|
267
|
+
printDiagnostics(diagnostics);
|
|
268
|
+
if (hasErrorDiagnostic(diagnostics)) {
|
|
269
|
+
process.stderr.write("failed to validate simulation before running\n");
|
|
270
|
+
return 1;
|
|
271
|
+
}
|
|
272
|
+
const seed = parsed.options.seed ?? result.simfile.clock.seed;
|
|
273
|
+
const runId = parsed.options.runId ?? defaultRunId(seed);
|
|
274
|
+
const outDir = resolve(parsed.options.outDir ?? `runs/${runId}`);
|
|
275
|
+
const worldActs = await loadQueuedWorldActs(parsed.options.actsPath);
|
|
276
|
+
const record = await writeRunRecord({
|
|
277
|
+
moltnetArtifact: parsed.options.moltnetArtifact,
|
|
278
|
+
outDir,
|
|
279
|
+
runId,
|
|
280
|
+
seed,
|
|
281
|
+
simfile: result.simfile,
|
|
282
|
+
sourcePath: path,
|
|
283
|
+
sourceText: source,
|
|
284
|
+
ticks: parsed.options.ticks,
|
|
285
|
+
worldActs
|
|
286
|
+
});
|
|
287
|
+
process.stdout.write(`wrote run ${runId} to ${record.outDir}\n`);
|
|
288
|
+
return 0;
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
process.stderr.write(`${formatError(error)}\n`);
|
|
292
|
+
return 1;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (command === "observe") {
|
|
296
|
+
const parsed = parseObserveArguments(rest);
|
|
297
|
+
if (parsed.error || !parsed.options?.runDir) {
|
|
298
|
+
if (parsed.error)
|
|
299
|
+
process.stderr.write(`${parsed.error}\n`);
|
|
300
|
+
process.stderr.write(usage());
|
|
301
|
+
return 1;
|
|
302
|
+
}
|
|
303
|
+
const runDir = resolve(parsed.options.runDir);
|
|
304
|
+
try {
|
|
305
|
+
const result = await runObserve(runDir);
|
|
306
|
+
const reportPath = await writeObserveReport(runDir, result.report);
|
|
307
|
+
const failedArtifacts = result.artifactIntegrity.filter((check) => !check.ok);
|
|
308
|
+
for (const failed of failedArtifacts) {
|
|
309
|
+
process.stderr.write(`warning: artifact sha256 mismatch for ${failed.path} (expected ${failed.expectedSha256}, got ${failed.actualSha256 ?? "<missing>"})\n`);
|
|
310
|
+
}
|
|
311
|
+
for (const parseError of result.causalParseErrors) {
|
|
312
|
+
process.stderr.write(`warning: ${parseError.relativePath}:${parseError.line}: ${parseError.message}\n`);
|
|
313
|
+
}
|
|
314
|
+
if (parsed.options.json) {
|
|
315
|
+
process.stdout.write(`${JSON.stringify({
|
|
316
|
+
artifactIntegrity: result.artifactIntegrity,
|
|
317
|
+
causalParseErrors: result.causalParseErrors,
|
|
318
|
+
report: result.report,
|
|
319
|
+
reportPath
|
|
320
|
+
}, null, 2)}\n`);
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
process.stdout.write(`wrote observe report for run ${result.report.run_id} to ${reportPath}\n`);
|
|
324
|
+
process.stdout.write(`participants: ${result.report.participants.join(", ")}\n`);
|
|
325
|
+
process.stdout.write(`agent turns: ${result.report.agent_turns.count} (${result.report.agent_turns.sequence.join(" -> ")})\n`);
|
|
326
|
+
process.stdout.write(`chains: ${result.report.chains.complete} complete, ${result.report.chains.incomplete.length} incomplete\n`);
|
|
327
|
+
process.stdout.write(`failures: ${result.report.failures.length}\n`);
|
|
328
|
+
}
|
|
329
|
+
return failedArtifacts.length > 0 ? 1 : 0;
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
process.stderr.write(`${formatError(error)}\n`);
|
|
333
|
+
return 1;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (command === "view") {
|
|
337
|
+
return runViewCommand(rest);
|
|
338
|
+
}
|
|
339
|
+
if (command !== "validate" || !rest.length) {
|
|
340
|
+
process.stderr.write(usage());
|
|
341
|
+
return 1;
|
|
342
|
+
}
|
|
343
|
+
process.stderr.write(usage());
|
|
344
|
+
return 1;
|
|
345
|
+
};
|
|
346
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
347
|
+
process.exitCode = await runCli(process.argv.slice(2));
|
|
348
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/coverage/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./matrix.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const systemViewTopLevelKeys: readonly ["simfile_version", "name", "spawnfile", "clock", "variables", "generators", "rules", "ledger", "telemetry", "markers", "probes"];
|
|
2
|
+
export declare const coveragePrimitives: readonly ["clock", "variables", "generators", "rules", "ledger", "telemetry", "markers/probes"];
|
|
3
|
+
export type TopLevelKey = typeof systemViewTopLevelKeys[number];
|
|
4
|
+
export type CoveragePrimitive = typeof coveragePrimitives[number];
|
|
5
|
+
export type CoverageStatus = "implemented" | "deferred" | `planned:B${number}`;
|
|
6
|
+
export type CoverageSubject = {
|
|
7
|
+
kind: "top-level";
|
|
8
|
+
key: TopLevelKey;
|
|
9
|
+
} | {
|
|
10
|
+
kind: "primitive";
|
|
11
|
+
primitive: CoveragePrimitive;
|
|
12
|
+
};
|
|
13
|
+
export interface CoverageRow {
|
|
14
|
+
subject: CoverageSubject;
|
|
15
|
+
claim: string;
|
|
16
|
+
specRef: string;
|
|
17
|
+
status: CoverageStatus;
|
|
18
|
+
evidence: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const matrix: CoverageRow[];
|
|
21
|
+
//# sourceMappingURL=matrix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix.d.ts","sourceRoot":"","sources":["../../src/coverage/matrix.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,4IAYzB,CAAC;AAEX,eAAO,MAAM,kBAAkB,iGAQrB,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAChE,MAAM,MAAM,iBAAiB,GAAG,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAElE,MAAM,MAAM,cAAc,GACtB,aAAa,GACb,UAAU,GACV,YAAY,MAAM,EAAE,CAAC;AAEzB,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,WAAW,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,MAAM,EAAE,WAAW,EAsJ/B,CAAC"}
|