---
title: "BDPD v0.6 — Release Notebook"
subtitle: "Open Platform: registry refactors, plugin system, onboarding"
author: "Roberto Brunelli"
date: "2026-05-19"
release_tag: "v0.6"
release_type: "infrastructural"
format:
  html:
    toc: true
    code-fold: true
    embed-resources: true
---

# Overview {#sec-overview}

v0.6 is the **Open Platform** release. The platform that was already
plug-friendly for *agents* (HTTP, sandboxed JS, middle-man Python) is
now plug-friendly for the *world* itself: resource dynamics,
perturbations, schedulers, metrics, observation transforms, and
victory functions are all registry-based, with auto-discovery from
`plugins/`, six worked starter templates, and a conformance runner.
Three quickstart guides ("Play with an AI", "Design an experiment",
"Extend the engine") cover the three primary persona entry points.

This is an **infrastructural** release: no new findings, no new
physics, no behavioural change to the simulation. The contract is
that all five canonical sweeps from the paper reproduce
bit-identically against the v0.5.1 baseline. They do (see
[Regression evidence](#sec-regression)).

The architectural decisions inside v0.6 were chosen to be
*nested-safe* — see `BDPD_ultimate_edition.md` §5 — so that v1.0's
nested-arena dispatch does not require rewriting plugin signatures
shipped here.

# What changed {#sec-what-changed}

## Commits

`git log v0.5.1..v0.6 --oneline`, topological order:

```
18ee44e  v0.6-dev: preflight — regression baseline + check_regression.sh
98499a8  v0.6-dev: refactor — PERTURBATION_REGISTRY (registry-based dispatch)
9ffde36  v0.6-dev: feat — provenance manifest MVP
4518230  v0.6-dev: fix — check_regression.sh skips *.manifest.json sidecars
7c8d78d  v0.6-dev: feat — release notebook scaffold + figure provenance (v0.6.5 partial)
1d214e0  v0.6-dev: feat — seeded observation noise + P9 in regression (week 3a)
acc86af  v0.6-dev: feat — METRIC_REGISTRY + VICTORY_REGISTRY + engine context arg (week 3b)
c078f5d  v0.6-dev: feat — plugin scaffolding + conformance runner + remaining nested-safe (week 4)
908e7ad  v0.6-dev: docs — two quickstarts for getting-started (week 4 wrap)
912a919  v0.6-dev: docs — third quickstart "design an experiment" (week 4 wrap)
```

## High-level diff

- **Six registry refactors.** Perturbation, scheduler, metric, victory,
  observation transform, and engine systems all moved from
  hardcoded switch/case dispatch to keyed registry tables. Each
  registry is a plain object that third-party plugins may extend at
  load time; nothing else in the core needs to know.
- **Plugin loader + conformance runner.** `tools/plugin-loader.mjs`
  auto-discovers `plugins/<type>/*.js` at startup; `tools/plugin-check.mjs`
  validates a plugin against the per-type contract and runs a smoke
  test (engine: instantiate+step; perturbation: apply to stub arena;
  metric: compute over fixed wealth array; etc.).
- **Six starter plugins** in `examples/plugins/<type>/`, one per
  category, 30–50 lines each. All six pass `plugin-check` for both
  contract and smoke.
- **Nested-safe API decisions (8 of 8).** UUID agent IDs (already in
  v0.5), optional `context = {}` arg on engine `step`, observation
  `observe`, and perturbation `apply`; metric `aggregate` composability;
  perturbation `target` selector; `/api/v1/...` path alias; storage
  path constant `WORLDS_DATA_DIR`. See the matching table in
  `BDPD_ultimate_edition.md` §6.
- **Three getting-started quickstarts** —
  [Play with an AI](../getting-started/play-with-an-ai.md),
  [Design an experiment](../getting-started/design-an-experiment.md),
  [Extend the engine](../getting-started/extend-the-engine.md).
- **Provenance manifest MVP.** Every sweep run writes a
  `<results>.manifest.json` sibling with content-addressed hashes,
  the producing git commit, the definition file SHA, and the
  artifact list. Figure-side provenance is half-wired: PNG tEXt
  embedding works via `tools/manifest_helper.py register-figure` but
  must be invoked manually; auto-wiring with `experiments/sweep.py`
  lands in v0.6.5.

# Regression evidence {#sec-regression}

Strict regression — bit-identical JSON, after stripping the three
non-deterministic fields (`id`, `startedAt`, `finishedAt`) — is the
contract that makes the registry refactor trustworthy. v0.6 was
developed under that contract from commit `18ee44e` onward.

```
$ tools/check_regression.sh
PASS  aggressive_fraction
PASS  adaptive_effectiveness
PASS  observability_noise
PASS  perturbation_regen_shock
PASS  mule_strategy_override

OK: 5/5 sweeps match baseline.
```

Per-sweep provenance, all from commit `912a919` (HEAD of `v0.6-dev`,
clean working tree):

| Sweep                              | Status | Wall   | Manifest hash (truncated)            |
|------------------------------------|:------:|-------:|:-------------------------------------|
| `aggressive_fraction` (P1)         | PASS   | 0.28s  | `sha256:e4e4388a2a38…`                |
| `adaptive_effectiveness` (P8)      | PASS   | 0.77s  | `sha256:3a4302e04424…`                |
| `observability_noise` (P9)         | PASS   | 0.75s  | `sha256:0c529d241fb7…`                |
| `perturbation_regen_shock` (P10)   | PASS   | 0.45s  | `sha256:2ff5e872192e…`                |
| `mule_strategy_override` (P11)     | PASS   | 0.55s  | `sha256:1fe841ea91ec…`                |

Run IDs and full hashes live in the corresponding
`experiments/results/<sweep>_2026-05-19T04-55-*.manifest.json` files.

P9 (`observability_noise`) joined the strict regression set in week
3a (commit `1d214e0`), once the Gaussian noise generator on the
observation transform became RNG-seeded. The definition carries
`seed: 42`. P7 (`scheduler_comparison`) remains stochastic and is
deliberately excluded — see [Open items deferred](#sec-deferred).

# Figures {#sec-figures}

Each figure was generated from the corresponding result JSON in the
2026-05-19T04:55:xx batch. The `data-manifest` attribute below
carries the producing run's manifest SHA-256; the PNG itself carries
`bdpd_run_id`, `bdpd_results_sha256`, and `bdpd_manifest_path` in
its tEXt chunk (inspect with
`python tools/manifest_helper.py inspect-png <file>`).

![P1 — Aggressive-fraction phase transition.](../../experiments/figures/platform/aggressive_fraction__light_paper.png){#fig-p1 data-manifest="sha256:ed824f45f2b550edc5aa894478460d2f438329177b4764881bee39298eaa8446" data-run-id="835adffc-c05c-4612-8cee-bb502fde0cb9"}

![P8 — Reactive-vs-conservative welfare gap.](../../experiments/figures/platform/adaptive_effectiveness__light_paper.png){#fig-p8 data-manifest="sha256:3a4302e044245184c4c66c2a7b49c2bab094605ac9e6162f7ec709e974609809" data-run-id="91e65953-6353-4ea5-bdc9-91e9e16b212d"}

![P9 — Observability noise as selective blunter.](../../experiments/figures/platform/observability_noise__light_paper.png){#fig-p9 data-manifest="sha256:0c529d241fb7993d46777a93b14fd3725bcbdbba578d410b377abf707cb50813" data-run-id="bfc91767-0e38-4a75-beb4-fe99afa4c585"}

![P10 — Regen shock sweep at turn 20 (Seneca asymmetry).](../../experiments/figures/platform/perturbation_regen_shock__light_paper.png){#fig-p10 data-manifest="sha256:2ff5e872192e31f5ce3159fe5642447a190da05732c2ad59b73a40b23dc69594" data-run-id="1319b6a7-4e94-40f0-af8a-7f4729f18e05"}

![P11 — Mule strategy override (defection timing).](../../experiments/figures/platform/mule_strategy_override__light_paper.png){#fig-p11 data-manifest="sha256:1fe841ea91ecfd81f236fb9eaeb429dd9c2e0a1c4b4cc51f8fb3e758f777e7da" data-run-id="258d7c02-fe34-43bc-bdcf-99ba0f0beb31"}

# What didn't change (invariants) {#sec-invariants}

v0.6 is back-compatible with v0.5.1 along every user-facing
contract. Code written against v0.5.1 runs unchanged.

- **HTTP API.** `/api/arenas/...` endpoints, payload shapes, response
  shapes all unchanged. The new `/api/v1/...` is an alias, not a
  replacement.
- **Public function signatures.** `engine.step(demands, rng)`,
  `observation.observe(state, observability)`, and
  `applyPerturbation(arena, spec)` all still accept the original
  argument list. The new `context = {}` arg is optional and
  defaults to `{}`.
- **Built-in strategies.** `aggressive`, `conservative`, `adaptive`,
  `rcp`, `random` — bit-identical decisions per turn, verified by
  the regression set.
- **Built-in engines.** `logistic` and `seneca` produce identical
  trajectories given identical inputs.
- **Card game engine** (`agents/cards_ai_play.py`,
  `sweep_card_tournaments.py`) — not touched in this release.
- **Storage layout.** Arena state still lives under
  `worlds/default/arenas/<id>/...`; the path is now exposed as the
  `WORLDS_DATA_DIR` constant in `registry.js` but the write target
  is unchanged.
- **Experiment definition JSON schema.** Every definition under
  `experiments/definitions/` runs unchanged; the runner's behaviour
  on those files is bit-identical.

# Open items deferred {#sec-deferred}

Tracked for v0.6.5 (provenance follow-on) or v0.7 (Replication
Library):

- **`scheduler_comparison` (P7) not yet in strict regression.**
  `SequentialRandom` and `WealthWeighted` schedulers still use
  `Math.random()` directly. Same fix shape as the v0.6 observation
  noise plugin: accept an RNG seeded by the arena. Deferred to v0.6.5
  or v0.7.
- **PNG-side provenance auto-wiring.** `register-figure` works but
  must be invoked manually. v0.6.5 wires it into
  `experiments/sweep.py` so figure provenance is automatic when
  plots are regenerated.
- **`audit-paper`, `list-orphans`, `snapshot` subcommands** of
  `tools/manifest.mjs`. Useful for HAL/Zenodo deposit and orphan
  detection across `.qmd`. Tracked for v0.6.5.
- **Observation transform pipeline.** Marker public, dispatch still
  hardcoded in `platform/observability.js`. Pipeline-based dispatch
  lands in v0.7 alongside the noise plugin seeding completion.
- **MkDocs site light/dark toggle and README `<picture>` swap.**
  Polish docs items; assets already exist as light/dark pairs.
  Tracked in `BDPD_ultimate_edition.md` §15 "Decisioni ancora aperte".

# How to reproduce {#sec-reproduce}

```bash
# 1. Check out the exact code state
git checkout v0.6

# 2. Install dependencies
./scripts/setup.sh
source venv_py_bdpd/bin/activate

# 3. Run the strict regression set (bit-identical contract)
tools/check_regression.sh
#  → expects: OK: 5/5 sweeps match baseline.

# 4. Regenerate the canonical figures from the fresh result JSONs
for sweep in aggressive_fraction adaptive_effectiveness \
             observability_noise perturbation_regen_shock \
             mule_strategy_override ; do
  latest=$(ls -t experiments/results/${sweep}_*.json \
           | grep -v manifest | head -1)
  python3 experiments/sweep.py "$latest" \
          --theme light_paper --dpi 300 \
          --out experiments/figures/platform
done

# 5. Re-register each figure into its manifest (PNG tEXt + artifact entry)
for sweep in aggressive_fraction adaptive_effectiveness \
             observability_noise perturbation_regen_shock \
             mule_strategy_override ; do
  manifest=$(ls -t experiments/results/${sweep}_*.manifest.json | head -1)
  python3 tools/manifest_helper.py register-figure \
          --manifest "$manifest" \
          --figure   "experiments/figures/platform/${sweep}__light_paper.png" \
          --produced-by experiments/sweep.py
done

# 6. Verify every manifest and every figure
for m in experiments/results/*.manifest.json ; do
  node tools/manifest.mjs verify "$m" || break
done
for png in experiments/figures/platform/*.png ; do
  python3 tools/manifest_helper.py verify-figure "$png" 2>/dev/null
done
```

The provenance chain runs: code commit `912a919` → definition JSON
(`sha256:604359a0…` etc., per sweep) → results JSON (`sha256:2a091c67…`
etc., per sweep) → figure PNG with tEXt-embedded
`bdpd_results_sha256`. Any link broken at any layer fails the
corresponding `verify`.

# Citing this release {#sec-citing}

```bibtex
@software{bdpd_v0_6,
  title   = {BDPD v0.6 — Open Platform},
  author  = {Brunelli, Roberto},
  year    = {2026},
  version = {v0.6},
  url     = {https://gitlab.com/bdpd/bdpd/-/releases/v0.6},
  note    = {Regression manifest bundle: 5 canonical sweeps from commit 912a919, branch v0.6-dev, clean tree. Per-sweep manifest SHA-256s in §Regression evidence.}
}
```
