Contribute

Reproduce, Author, Extend

Version 0.1 · · MIT License

This page shows how to (1) reproduce results, (2) author new scenarios in JSON, (3) extend the engine with new ethical modules, and (4) export runs for review. Facts live in scenarios; values live in modules. Keep that boundary sharp.

Contents
  1. Quickstart
  2. Scenario Authoring Guide
  3. Module Extension Guide
  4. Export & Reproducibility
  5. Axiom Ledger (Ground Rules)
  6. FAQ


    

1. Quickstart

Local

  1. Clone or fork the repo.
  2. Open index.html in a modern browser. No build step required.
  3. Open results.html (baseline) and interactive.html (live controls).
Tip. If you use VS Code, the “Live Server” extension auto-reloads your edits.

GitHub Pages

  1. Enable Pages in your repo settings (source: root or /docs).
  2. Visit your Pages URL and test interactive.html.
  3. Confirm that data/scenarios.json is publicly readable.

2. Scenario Authoring Guide

Author facts in JSON. Avoid comments and trailing commas-this is strict JSON.

2.1 Minimal template

{
  "id": "your-scenario-id",
  "context": { "domain": "triage|evacuation|policy|...", "tags": ["free", "text"] },
  "agents": [
    { "id": "X", "role": "patient|rescuer|citizen",
      "baseline": { "wellbeing": 0.50, "years_left": 30 },
      "consent": true }
  ],
  "actions": [
    { "id": "a1", "desc": "What the agent(s) do" },
    { "id": "a2", "desc": "Alternative action" }
  ],
  "outcomes": { /* optional; many scenarios compute outcomes from fields */ },
  "constraints": {
    "no_intentional_harm_innocent": true,
    "treat_like_cases_alike": true,
    "respect_informed_consent": true
  },
  "params": { "priority_fn": "sqrt" },
  "notes": "assumptions and scope limits"
}

2.2 Examples

Ventilator triage (seed)
{
  "id": "triage-vent-v1",
  "context": { "domain": "triage", "tags": ["emergency", "resource-scarce"] },
  "agents": [
    { "id": "A", "baseline": { "wellbeing": 0.55, "years_left": 35 }, "consent": true,
      "survival": { "vent": 0.80, "no_vent": 0.10 } },
    { "id": "B", "baseline": { "wellbeing": 0.55, "years_left": 35 }, "consent": true,
      "survival": { "vent": 0.60, "no_vent": 0.55 } }
  ],
  "actions": [
    { "id": "a1_allocate_A", "desc": "Allocate ventilator to A" },
    { "id": "a2_allocate_B", "desc": "Allocate ventilator to B" },
    { "id": "a3_lottery", "desc": "Random lottery (50/50)" }
  ],
  "constraints": {
    "no_intentional_harm_innocent": true,
    "treat_like_cases_alike": true,
    "respect_informed_consent": true
  },
  "params": { "priority_fn": "sqrt" }
}
Flood evacuation (seed)
{
  "id": "evac-promise-v1",
  "context": { "domain": "evacuation", "tags": ["flood", "resource-scarce"] },
  "agents": [
    { "id": "D1", "role": "civilian", "traits": ["elderly"], "promised_first": true },
    { "id": "D2", "role": "civilian" }, { "id": "D3", "role": "civilian" },
    { "id": "D4", "role": "civilian" }, { "id": "D5", "role": "civilian" },
    { "id": "R",  "role": "rescuer" }
  ],
  "boat_capacity": 3,
  "prob_survive_if_rescued": 0.95,
  "prob_if_delayed": { "east": 0.60, "west": 0.20 },
  "docks": { "east": ["D1","D2","D3"], "west": ["D4","D5"] },
  "actions": [
    { "id": "b1_east_now", "desc": "Rescue East (D1–D3) now" },
    { "id": "b2_west_plus_one_east", "desc": "Rescue West (D4–D5) + one East" },
    { "id": "b3_mixed_break_promise", "desc": "Two East (incl. D1) + one West" }
  ],
  "constraints": {
    "keep_credible_promises": { "enabled": true, "theta_lives": 1.0 },
    "no_intentional_harm_innocent": true,
    "treat_like_cases_alike": true
  },
  "params": { "priority_fn": "sqrt" }
}
Validation. Open your JSON file directly in the browser. If it renders as text without error, it’s valid. JSON does not allow comments or trailing commas.

3. Module Extension Guide

Modules live in js/engine.js. Each should either (a) return a scalar choiceworthiness for every action, or (b) gate actions via admissibility constraints.

3.1 Shape

// Scalar module
function CW_newTheory(scn) {
  // return Array<[actionId, number]> or Map(actionId -> number)
}

// Constraint module (admissibility)
function gk_newConstraint(scn, actionId) {
  // return { admissible: boolean, reasons: string[] }
}

3.2 Example: Rawlsian maximin

// Compute minimum expected well-being across persons
function rawlsRawScores(scn) {
  // You define how to derive per-person utility from scn (e.g., survival * years_left)
  // Return pairs: [[actionId, score], ...]
}

3.3 Wiring it in

  1. Compute raw scores per action.
  2. Normalize to [0,1] within the scenario (min–max).
  3. Add a credence weight in the aggregator (alongside consequentialism and virtue).
Guardrails. Keep rights as side-constraints (lexicographic). Don’t bury them as soft penalties.

4. Export & Reproducibility

Use Interactive → “Download current run (JSON)”. Each bundle captures:

{
  "timestamp": "2025-09-05T12:34:56.789Z",
  "ledger_version": "0.1",
  "settings": { "credences": {"p_cons":0.5,"p_virtue":0.5}, "promise": {"enabled":true,"theta_lives":1.0} },
  "scenarios": ["triage-vent-v1", "evac-promise-v1"],
  "results": [
    { "scenarioId": "triage-vent-v1", "ranking": [["a1_allocate_A",0.92],["a3_lottery",0.61],...],
      "admissibility": [["a1_allocate_A",{"admissible":true,"reasons":[]}]], "explanations": ["E1: ..."] }
  ]
}
How to discuss disagreements. Share your exported JSON, point to the specific axiom or parameter you contest, and show the change in results.

5. Axiom Ledger (Ground Rules)

Short, explicit premises that shape the engine’s behavior.

  1. Persons have equal moral worth.
  2. Comparable goods are explicitly scaled within each scenario.
  3. Uncertainty is modeled; guesses are distributions.
  4. Rights and duties act as side-constraints (lexicographic priority).
  5. Doing vs allowing matters but is not decisive alone.
  6. Consent changes scores and constraint triggers.
  7. Priority to the worse-off via concavity or priority weights.
  8. Like cases alike; only prognosis-relevant differences justify unequal treatment.
  9. Minimal explanations identify the few premises that did the work.
  10. Pluralism is explicit; red lines are not aggregative.
  11. Culture tunes parameters, not personhood.
  12. Reversibility check flags unstable rules.
To propose changes: cite the axiom by number, suggest a replacement, and attach a run bundle showing effects on scenarios.

6. FAQ

Why strict JSON and not YAML?

We want zero ambiguity and native browser parsing via fetchresponse.json().

Can I add culture-specific parameters?

Yes-under context.culture. Modules may read them to tune thresholds (e.g., consent).

Where do I put new modules?

Add functions in js/engine.js, mirror the normalization, and update aggregation weights.

What counts as a deontic constraint vs a soft penalty?

If it’s a right/duty that should not be traded off, encode as admissibility (gate). Otherwise, use scalar modules.

Back to Home

© Ethics Testbed · MIT