Skill Tracer
Skills › Scientific Agent Skills › simpy › cli-guide.md

cli-guide.md

291 lines · skills/simpy/references/cli-guide.md at 5f2bc03

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Bundled CLI guide
2
3Reviewed 2026-10-01 for skill version 1.6 and SimPy 4.1.2.
4
5The scripts implement one transparent finite-horizon exponential
6arrival/exponential service multi-server queue. They are examples and diagnostics,
7not a generic model execution platform.
8

Bundled CLI guide

Reviewed 2026-10-01 for skill version 1.6 and SimPy 4.1.2.

The scripts implement one transparent finite-horizon exponential arrival/exponential service multi-server queue. They are examples and diagnostics, not a generic model execution platform.

Raw lines 1 to 8
9## Safety contract
11All scripts:
13- use only SimPy and the Python standard library;
14- build `--help` when SimPy is absent, so options remain inspectable before
15 installation;
16- make no network or external-service calls;
17- accept only local regular files with fixed suffixes;
18- reject URLs, symlinks, duplicate JSON keys, `NaN`/infinity, unknown keys, and
19 oversized inputs;
20- never evaluate configuration text, run user Python, resolve callables, or import
21 plugins;
22- enforce time, event, entity, queue, trace, and replication caps;
23- emit strict deterministic JSON (`allow_nan=False`);
24- write explicit outputs atomically with mode `0600`;
25- refuse overwrite unless `--force` is supplied.
27Run from the repository root after the pinned install:
29```bash
30uv pip install "simpy==4.1.2"
31```
33Commands that execute a simulation gate SimPy through a shared dependency loader.
34If it is absent, they exit without a traceback and print the pinned installation
35command above. They also reject a different installed version because scheduler
36instrumentation is release-specific. Configuration validation and artifact summarization remain usable
37without SimPy.

Safety contract

All scripts:

  • use only SimPy and the Python standard library;
  • build --help when SimPy is absent, so options remain inspectable before installation;
  • make no network or external-service calls;
  • accept only local regular files with fixed suffixes;
  • reject URLs, symlinks, duplicate JSON keys, NaN/infinity, unknown keys, and oversized inputs;
  • never evaluate configuration text, run user Python, resolve callables, or import plugins;
  • enforce time, event, entity, queue, trace, and replication caps;
  • emit strict deterministic JSON (allow_nan=False);
  • write explicit outputs atomically with mode 0600;
  • refuse overwrite unless --force is supplied.

Run from the repository root after the pinned install:

uv pip install "simpy==4.1.2"

Commands that execute a simulation gate SimPy through a shared dependency loader. If it is absent, they exit without a traceback and print the pinned installation command above. They also reject a different installed version because scheduler instrumentation is release-specific. Configuration validation and artifact summarization remain usable without SimPy.

Raw lines 9 to 38
39## Queue configuration schema
41Every field is optional; defaults are shown:
43```json
45 "analysis_mode": "terminating",
46 "base_seed": 20260723,
47 "horizon": 480.0,
48 "max_entities": 10000,
49 "max_events": 200000,
50 "mean_interarrival": 4.0,
51 "mean_service": 6.0,
52 "queue_capacity": 20,
53 "servers": 2,
54 "warm_up": 0.0
56```
58Semantics:
60- arrival and service durations are exponential means in the declared model time
61 unit;
62- there are `servers` simultaneous slots and at most `queue_capacity` waiting
63 entities;
64- an arrival seeing `servers + queue_capacity` admitted entities is rejected;
65- arrivals and services use separate deterministic stream seeds;
66- arrivals occur strictly before `horizon`;
67- numeric horizon excludes ordinary events exactly at that time;
68- completed-customer metrics exclude unfinished entities and disclose their count.
70Bounds:
72- `0 < horizon <= 1,000,000`;
73- `1 <= servers <= 10,000`;
74- `0 <= queue_capacity <= 100,000`;
75- positive finite means no greater than 1,000,000;
76- `1 <= max_entities <= 100,000`;
77- `10 <= max_events <= 1,000,000`;
78- base seed from 0 through `2^63 - 1`.
80For `analysis_mode="terminating"`, `warm_up` must be zero. For
81`analysis_mode="steady_state"`, warm-up must be positive and less than horizon.
82This validates consistency only; it does not establish that steady state was
83reached.
85Report schema 1.2 separates the measurement rules:
87- `window_arrivals` and `window_rejected` count events in `[warm_up, horizon)`;
88 `loss_probability` is their ratio (null when there are no window arrivals).
89- `window_departures` counts **all** completions in that time window, including
90 customers arriving before warm-up; throughput divides this by `horizon - warm_up`.
91- `observed_completed` and customer means use customers arriving at/after warm-up
92 and completed before the horizon; unfinished customer paths are excluded.
93- Queue length and utilization are time-weighted over `[warm_up, horizon)`.
94- The original arrivals/admitted/rejected/completed counters span the full run.
95- `event_processing.processed` includes the step whose callback stops the run.
97These synthetic exponential inputs demonstrate event mechanics; they are not
98calibrated estimates of a real queue. Record the time unit and justify inputs before
99using scenario contrasts. The report records `simpy_version` and `metric_windows`.

Queue configuration schema

Every field is optional; defaults are shown:

{
  "analysis_mode": "terminating",
  "base_seed": 20260723,
  "horizon": 480.0,
  "max_entities": 10000,
  "max_events": 200000,
  "mean_interarrival": 4.0,
  "mean_service": 6.0,
  "queue_capacity": 20,
  "servers": 2,
  "warm_up": 0.0
}

Semantics:

  • arrival and service durations are exponential means in the declared model time unit;
  • there are servers simultaneous slots and at most queue_capacity waiting entities;
  • an arrival seeing servers + queue_capacity admitted entities is rejected;
  • arrivals and services use separate deterministic stream seeds;
  • arrivals occur strictly before horizon;
  • numeric horizon excludes ordinary events exactly at that time;
  • completed-customer metrics exclude unfinished entities and disclose their count.

Bounds:

  • 0 < horizon <= 1,000,000;
  • 1 <= servers <= 10,000;
  • 0 <= queue_capacity <= 100,000;
  • positive finite means no greater than 1,000,000;
  • 1 <= max_entities <= 100,000;
  • 10 <= max_events <= 1,000,000;
  • base seed from 0 through 2^63 - 1.

For analysis_mode="terminating", warm_up must be zero. For analysis_mode="steady_state", warm-up must be positive and less than horizon. This validates consistency only; it does not establish that steady state was reached.

Report schema 1.2 separates the measurement rules:

  • window_arrivals and window_rejected count events in [warm_up, horizon); loss_probability is their ratio (null when there are no window arrivals).
  • window_departures counts all completions in that time window, including customers arriving before warm-up; throughput divides this by horizon - warm_up.
  • observed_completed and customer means use customers arriving at/after warm-up and completed before the horizon; unfinished customer paths are excluded.
  • Queue length and utilization are time-weighted over [warm_up, horizon).
  • The original arrivals/admitted/rejected/completed counters span the full run.
  • event_processing.processed includes the step whose callback stops the run.

These synthetic exponential inputs demonstrate event mechanics; they are not calibrated estimates of a real queue. Record the time unit and justify inputs before using scenario contrasts. The report records simpy_version and metric_windows.

Raw lines 39 to 100
101## Basic template
103```bash
104python skills/simpy/scripts/basic_simulation_template.py --help
105python skills/simpy/scripts/basic_simulation_template.py
106python skills/simpy/scripts/basic_simulation_template.py \
107 --config queue.json --output run.json
108```
110`--replication INDEX` selects deterministic derived arrival/service seeds. It does
111not itself create a confidence interval.
113Library use:
115```python
116from basic_simulation_template import QueueConfig, run_simulation
118config = QueueConfig.from_mapping({"horizon": 120, "servers": 3})
119report = run_simulation(config, replication=0)
120```

Basic template

python skills/simpy/scripts/basic_simulation_template.py --help
python skills/simpy/scripts/basic_simulation_template.py
python skills/simpy/scripts/basic_simulation_template.py \
  --config queue.json --output run.json

--replication INDEX selects deterministic derived arrival/service seeds. It does not itself create a confidence interval.

Library use:

from basic_simulation_template import QueueConfig, run_simulation

config = QueueConfig.from_mapping({"horizon": 120, "servers": 3})
report = run_simulation(config, replication=0)
Raw lines 101 to 121
Runs code python skills/simpy/scripts/basic_simulation_template.py :104
122## Bounded queue scenario and trace
124```bash
125python skills/simpy/scripts/bounded_queue_scenario.py \
126 --config queue.json \
127 --output scenario.json \
128 --trace-output trace.jsonl \
129 --trace-max-records 50000
130```
132The trace is capped and contains no event `repr`:
134```json
136 "event_id": 0,
137 "event_type": "Initialize",
138 "priority": 0,
139 "queue_size_before": 1,
140 "time": 0.0
142```
144The `.jsonl` file has one compact object per line. A trace can truncate while the
145bounded simulation completes; the report discloses `trace.truncated`.

Bounded queue scenario and trace

python skills/simpy/scripts/bounded_queue_scenario.py \
  --config queue.json \
  --output scenario.json \
  --trace-output trace.jsonl \
  --trace-max-records 50000

The trace is capped and contains no event repr:

{
  "event_id": 0,
  "event_type": "Initialize",
  "priority": 0,
  "queue_size_before": 1,
  "time": 0.0
}

The .jsonl file has one compact object per line. A trace can truncate while the bounded simulation completes; the report discloses trace.truncated.

Raw lines 122 to 146
Runs code python skills/simpy/scripts/bounded_queue_scenario.py :125
147## Replication configuration schema
149```json
151 "confidence": 0.95,
152 "model": {
153 "analysis_mode": "terminating",
154 "base_seed": 20260723,
155 "horizon": 480,
156 "max_entities": 10000,
157 "max_events": 200000,
158 "mean_interarrival": 4,
159 "mean_service": 6,
160 "queue_capacity": 20,
161 "servers": 2,
162 "warm_up": 0
163 },
164 "replications": 20
166```
168Additional experiment bounds:
170- 2-1,000 replications; one-run confidence intervals are rejected;
171- confidence strictly greater than 0.50 and at most 0.999;
172- `replications * max_events <= 5,000,000`;
173- `replications * max_entities <= 2,000,000`.
175```bash
176python skills/simpy/scripts/replication_runner.py --help
177python skills/simpy/scripts/replication_runner.py \
178 --config experiment.json --output intervals.json
179```
181The runner makes a two-sided Student-t interval from independent
182replication-level estimates. A metric undefined in any run is marked unavailable
183instead of dropping that run. It never constructs a CI from individual customers
184within one run.
186The seed manifest uses stable BLAKE2b derivation for separate arrival/service RNG
187objects. This is deterministic stream separation for the bundled example, not a
188formal proof of independent substreams. See `simulation-methodology.md`.

Replication configuration schema

{
  "confidence": 0.95,
  "model": {
    "analysis_mode": "terminating",
    "base_seed": 20260723,
    "horizon": 480,
    "max_entities": 10000,
    "max_events": 200000,
    "mean_interarrival": 4,
    "mean_service": 6,
    "queue_capacity": 20,
    "servers": 2,
    "warm_up": 0
  },
  "replications": 20
}

Additional experiment bounds:

  • 2-1,000 replications; one-run confidence intervals are rejected;
  • confidence strictly greater than 0.50 and at most 0.999;
  • replications * max_events <= 5,000,000;
  • replications * max_entities <= 2,000,000.
python skills/simpy/scripts/replication_runner.py --help
python skills/simpy/scripts/replication_runner.py \
  --config experiment.json --output intervals.json

The runner makes a two-sided Student-t interval from independent replication-level estimates. A metric undefined in any run is marked unavailable instead of dropping that run. It never constructs a CI from individual customers within one run.

The seed manifest uses stable BLAKE2b derivation for separate arrival/service RNG objects. This is deterministic stream separation for the bundled example, not a formal proof of independent substreams. See simulation-methodology.md.

Raw lines 147 to 189
Runs code python skills/simpy/scripts/replication_runner.py :176
190## Configuration validator
192Validation performs no simulation:
194```bash
195python skills/simpy/scripts/validate_simulation_config.py queue.json
196python skills/simpy/scripts/validate_simulation_config.py \
197 experiment.json --schema replication
198```
200Schemas are `queue`, `replication`, or `auto`. Auto identifies the replication
201schema by any top-level `model`, `replications`, or `confidence` key. There are no
202custom model names, module paths, class names, predicates, or callable fields.
204Unknown keys such as the following are rejected:
206```json
208 "plugin": "package.module",
209 "python": "print('run me')"
211```

Configuration validator

Validation performs no simulation:

python skills/simpy/scripts/validate_simulation_config.py queue.json
python skills/simpy/scripts/validate_simulation_config.py \
  experiment.json --schema replication

Schemas are queue, replication, or auto. Auto identifies the replication schema by any top-level model, replications, or confidence key. There are no custom model names, module paths, class names, predicates, or callable fields.

Unknown keys such as the following are rejected:

{
  "plugin": "package.module",
  "python": "print('run me')"
}
Raw lines 190 to 212
Runs code python skills/simpy/scripts/validate_simulation_config.py :195
213## Event/resource artifact summarizer
215Summarize a trace without importing or executing its originating model:
217```bash
218python skills/simpy/scripts/event_trace_summary.py trace.jsonl
219```
221Generate the separate, fixed ResourceMonitor demonstration and its CSV, then
222summarize it (`--samples` is an output path, not an input):
224```bash
225python skills/simpy/scripts/resource_monitor.py \
226 --samples resource.csv --output monitor.json
227python skills/simpy/scripts/event_trace_summary.py resource.csv
228```
230Accepted trace fields are exactly:
232`event_id`, `event_type`, `priority`, `queue_size_before`, `time`.
234Accepted resource CSV fields are exactly:
236`time`, `event`, `count`, `queue_length`, `utilization`.
238The summarizer reports decreasing event times and computes resource time averages
239by carrying each post-transition state forward to the next sample. Same-time
240priority/event-ID decreases are valid when callbacks insert new urgent events;
241the processing trace alone cannot prove scheduler heap ordering.
242It does not infer queue semantics from arbitrary column names.
244The replication runner consumes the replication JSON configuration and runs fresh
245model instances. It does not consume `trace.jsonl` or `resource.csv`. Each run
246provides one estimate per metric; the Student-t interval is across those estimates,
247not a separate confidence interval for each run.

Event/resource artifact summarizer

Summarize a trace without importing or executing its originating model:

python skills/simpy/scripts/event_trace_summary.py trace.jsonl

Generate the separate, fixed ResourceMonitor demonstration and its CSV, then summarize it (--samples is an output path, not an input):

python skills/simpy/scripts/resource_monitor.py \
  --samples resource.csv --output monitor.json
python skills/simpy/scripts/event_trace_summary.py resource.csv

Accepted trace fields are exactly:

event_id, event_type, priority, queue_size_before, time.

Accepted resource CSV fields are exactly:

time, event, count, queue_length, utilization.

The summarizer reports decreasing event times and computes resource time averages by carrying each post-transition state forward to the next sample. Same-time priority/event-ID decreases are valid when callbacks insert new urgent events; the processing trace alone cannot prove scheduler heap ordering. It does not infer queue semantics from arbitrary column names.

The replication runner consumes the replication JSON configuration and runs fresh model instances. It does not consume trace.jsonl or resource.csv. Each run provides one estimate per metric; the Student-t interval is across those estimates, not a separate confidence interval for each run.

Raw lines 213 to 248
Runs code python skills/simpy/scripts/event_trace_summary.py :218
Runs code python skills/simpy/scripts/resource_monitor.py :225
249## Resource monitor library
251```python
252from resource_monitor import EventTraceRecorder, ResourceMonitor
254monitor = ResourceMonitor(env, server, "server")
255trace = EventTraceRecorder(env, max_records=10_000)
256env.run(until=100)
257trace.detach()
258monitor.finalize(at=100)
260print(monitor.summary(start=20, end=100))
261monitor.export_csv("resource.csv")
262trace.export_jsonl("trace.jsonl")
263```
265The monitor patches one resource instance. Do not attach multiple wrappers to the
266same resource. Its queue timing and private-API caveats are in `monitoring.md`.

Resource monitor library

from resource_monitor import EventTraceRecorder, ResourceMonitor

monitor = ResourceMonitor(env, server, "server")
trace = EventTraceRecorder(env, max_records=10_000)
env.run(until=100)
trace.detach()
monitor.finalize(at=100)

print(monitor.summary(start=20, end=100))
monitor.export_csv("resource.csv")
trace.export_jsonl("trace.jsonl")

The monitor patches one resource instance. Do not attach multiple wrappers to the same resource. Its queue timing and private-API caveats are in monitoring.md.

Raw lines 249 to 267
268## Exit behavior
270Expected validation failures use `argparse` errors and nonzero exit status:
272- malformed/unknown config;
273- unsafe path or overwrite;
274- event/entity/replication budget violation;
275- event limit reached during the run;
276- invalid trace/resource artifact.
278An event-budget error is a failed/incomplete simulation, not a valid censored
279result. Increase a cap only after diagnosing why it was reached.

Exit behavior

Expected validation failures use argparse errors and nonzero exit status:

  • malformed/unknown config;
  • unsafe path or overwrite;
  • event/entity/replication budget violation;
  • event limit reached during the run;
  • invalid trace/resource artifact.

An event-budget error is a failed/incomplete simulation, not a valid censored result. Increase a cap only after diagnosing why it was reached.

Raw lines 268 to 280
281## Exact pinned tests
283```bash
284PYTHONDONTWRITEBYTECODE=1 uv run --isolated --no-project \
285 --python 3.13 --with "simpy==4.1.2" --with pytest \
286 python -m pytest tests/simpy -q
287```
289Tests cover scheduler boundaries, deterministic ties, Conditions, all resource
290families, preemption causes, monitor time weighting, trace round-trip, config/path
291safety, hard limits, seed determinism, and Student-t calculations.

Exact pinned tests

PYTHONDONTWRITEBYTECODE=1 uv run --isolated --no-project \
  --python 3.13 --with "simpy==4.1.2" --with pytest \
  python -m pytest tests/simpy -q

Tests cover scheduler boundaries, deterministic ties, Conditions, all resource families, preemption causes, monitor time weighting, trace round-trip, config/path safety, hard limits, seed determinism, and Student-t calculations.

Raw lines 281 to 291