Chapter 9 — Improving the specification
This chapter decides, from the results observed in Chapter 7, where to change the specification, and checks the change by running it again. The chapter consists of exercises only.
9.1 What you'll learn
- Use observations from simulation to identify which knob to turn.
- Adjust the spec at the right layer (deadline / monitor / lifecycle / actor / runtime).
- Validate the change with a re-run.
9.2 Background
Which layer fixes which symptom
Each layer of the design has its own kind of fix:
| Symptom in trace | Layer that fixes it | Example fix |
|---|---|---|
| Deadline expires for every robot | Spec — relax deadline | 5s → 7s |
| One robot's monitor fires too often (false positive) | Spec — tighten rule | < 20 → < 15 |
Robots reach Violated because the world model is wrong | Runtime — fix world snapshot keys | check update_instance_world calls |
| Reward never gets paid | Runtime — implement reward execution | extend engine.py |
| All robots succeed but the aggregate is wrong (e.g., late) | New monitor or new contract | add FLEET_THROUGHPUT_SLA |
This is a small but useful typology of regressions in normative SoS specs.
9.3 Exercises
Exercise 9.1 (★) — Diagnose one failure
Goal: Pick one violation from your Chapter 7 traces. Explain in 1 paragraph: which layer would you change, and how.
Submit: session5_diagnosis.md (1 page).
Exercise 9.2 (★★) — Apply the fix
Goal: Implement your diagnosis. Save the fixed spec as my_delivery_v3.cadl.
Procedure:
-
Make the change you diagnosed in 5.1.
-
Generate the IR of the new file and re-run the demo against it, as in Exercise 7.2:
cd ~/program/cadl_repocadl sim-ir my_delivery_v3.cadl --format json > my_delivery_v3.ir.jsoncd ~/program/cadl-raspimouse-simulatorpython3 -m cadl.runtime.multi_robot_demo --ir ~/program/cadl_repo/my_delivery_v3.ir.json --summary -
Confirm the violation you fixed is gone and you didn't break anything else.
Submit: my_delivery_v3.cadl + diff against v2.
Exercise 9.3 (★★★) — Implement reward execution
Goal: Currently a reward is written in the spec (incentives.rules) but never applied — and the rule text does not even reach the runtime. When the spec is lowered to the IR (cadl_repo/src/cadl/sim/lower.py), only lambda and incentive_type are kept, under the contract's governance; the rules list is dropped. Make the Python runtime maintain a per-actor balance and credit a reward when a contract reaches Completed.
Procedure:
-
Extend
ContractRuntimewithbalances: dict[str, float], accessorruntime.balance(actor_id), and a way to receive the rules, for exampleContractRuntime(ir, log_path=None, reward_rules=[...]). -
Get the rules. Because the IR does not carry them, read them from the
.cadlsource with the cadl parser in a separate script that writes them to JSON (if your file has noincentives:block, add the one from Chapter 4):# dump_rules.py — run with the Python environment where cadl-lang is installedimport json, sysfrom cadl.parser import parse_filesos = parse_file(sys.argv[1])rules = [{"contract": c.id, "rule": r.description}for c in sos.contracts if c.incentivesfor r in c.incentives.rules]json.dump(rules, open(sys.argv[2], "w"), indent=2)# python dump_rules.py my_delivery_v2.cadl rules.json# -> [{"contract": "DELIVERY_SLA", "rule": "reward(ROBOT[i], 10) when on_time_delivery"}]The script has to be separate: the simulator repository has its own top-level
cadl/package, which shadowscadl-lang, sofrom cadl.parser import parse_filefails withNo module named 'cadl.parser'inside the runtime, its tests, or anything run withpython -mfrom the simulator root. Run the script from another directory and passrules.jsonto the demo (add a--rewards rules.jsonoption tomulti_robot_demo).Each rule is a raw string. Parse entries of the form
reward(<actor_ref>, <amount>) when on_time_deliveryyourself (a regular expression is enough) and skip the others (the bundled example also has apenalty(...)rule).Stretch variant: instead of reading the source, extend
lower.py(andGovernanceParamsinsim/ir.py) so that the IR carries the rules, for example asgovernance.incentive_rules. Runcadlfrom your edited checkout (pip install -e .; the PyPI release does not have the key), confirm that the rules appear in the output ofcadl sim-ir --format json, and let the runtime read them from the IR. -
Decide who is paid. The runtime knows only the instance id (
robot-0-1); a contract instance has no actor field. Pass the actor when the instance is opened (for exampleopen_instance(..., actors={"ROBOT": "robot-0"})) and map the rule'sROBOT[i]to it. -
Credit on entry to a terminal state. An instance is closed in two places —
StateMachineEngine.fire_transition(ordinary transitions, includingcomplete) andContractRuntime._fire_state_jump(deadline and monitor jumps) — so hook both. Defineon_time_deliveryyourself as "the instance enteredCompletedand has noviolationrecord"; the runtime's predicate evaluator cannot decide it, because it treats a bare identifier as true. -
Add
cadl/runtime/tests/test_rewards.pywith at least:- One test: a robot earns 10 on a
Completeddelivery. - One test: no reward is paid on a
Violateddelivery.
- One test: a robot earns 10 on a
-
Update
multi_robot_demo --summaryto print final balances. With the bundled scenario,robot-0ends with 10 and the other four with 0.
Reflection: The CADL spec already says reward(ROBOT[i], 10) when on_time_delivery, but until this exercise the runtime ignored it — the IR did not even carry it. Where is the line between "the spec says so" and "the runtime does so"?
Exercise 9.4 (★★★) — Final report
Goal: A 3-page report covering the entire course.
| Page | Content |
|---|---|
| 1 | Initial CADL model (v1), the question your model is asking, and what was missing in v1. |
| 2 | Simulation results — baseline vs your modifications. Tables and at least one screenshot from cadl-explorer. |
| 3 | Reflection: what did adding norms buy you? What did running the simulation teach you that the spec alone could not? Where do you think SoS-DSL could go next? |
Using this chapter in a class
Before the session.
- All deliverables from Chapters 4–7.
Wrap-up and homework.
Submit by the end of the last session (Chapter 9):
my_delivery_v1.cadl/v2.cadl/v3.cadl.session5_diagnosis.md+ final report (3 pages).- (Optional)
test_rewards.pyand the modifiedengine.py.