|
| 1 | +# SPDX-License-Identifier: PMPL-1.0-or-later |
| 2 | +# Bust — error-handling / failure-recovery runner |
| 3 | +# |
| 4 | +# Pairs with: Bustfile.a2ml (same directory) |
| 5 | +# Verb: bust |
| 6 | +# Semantics: every declared failure mode must have a recovery path that has |
| 7 | +# been exercised. Runner injects failures (via declared probes) |
| 8 | +# and verifies the recovery path works. Hard gate on any |
| 9 | +# failure-mode with missing or broken recovery. |
| 10 | +# CLI: `contractile bust check` → list failure modes + recovery status |
| 11 | +# `contractile bust drill` → inject declared failures, verify recovery |
| 12 | +# |
| 13 | +# Anything else in this directory is human-only notes/archive; machines ignore. |
| 14 | +# |
| 15 | +# Base: ../_base.ncl provides pedigree_schema, run_defaults, probe_schema. |
| 16 | +# See: docs/CONTRACTILE-SPEC.adoc |
| 17 | + |
| 18 | +let base = import "../_base.ncl" in |
| 19 | + |
| 20 | +{ |
| 21 | + pedigree = base.pedigree_schema & { |
| 22 | + contractile_verb = "bust", |
| 23 | + semantics = "error handling + failure recovery", |
| 24 | + security = { |
| 25 | + leash = 'Kennel, |
| 26 | + trust_level = "controlled failure injection; scoped to system-under-test", |
| 27 | + allow_network = false, |
| 28 | + allow_filesystem_write = true, # drills may write transient state (tmp dirs, test DBs) |
| 29 | + allow_subprocess = true, |
| 30 | + injection_scope = "system-under-test-only", |
| 31 | + }, |
| 32 | + metadata = { |
| 33 | + name = "bust-runner", |
| 34 | + version = "1.0.0", |
| 35 | + description = "Exercises declared failure modes and verifies recovery paths. Hard-gates on any failure mode without working recovery.", |
| 36 | + paired_xfile = "Bustfile.a2ml", |
| 37 | + author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>", |
| 38 | + }, |
| 39 | + }, |
| 40 | + |
| 41 | + schema = { |
| 42 | + failure_modes |
| 43 | + | Array { |
| 44 | + id | String, |
| 45 | + description | String, |
| 46 | + class | [| 'network, 'disk_full, 'oom, 'timeout, 'partial_write, 'panic, 'crash, 'rollback, 'concurrency |], |
| 47 | + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it |
| 48 | + injection_probe | String, # command that deterministically causes this failure |
| 49 | + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it |
| 50 | + recovery_probe | String, # command that verifies recovery (exit 0 = recovered) |
| 51 | + expected_recovery_time_seconds | Number | default = 30, |
| 52 | + # status_core values: 'declared, 'verified, 'failing; bust adds 'drilled |
| 53 | + status | [| 'declared, 'drilled, 'verified, 'failing |] | default = 'declared, |
| 54 | + notes | String | optional, |
| 55 | + }, |
| 56 | + }, |
| 57 | + |
| 58 | + # Runner behaviour — inherits from base.run_defaults. |
| 59 | + # bust adds record_recovery_times for performance tier feeding. |
| 60 | + run = base.run_defaults & { |
| 61 | + on_any_fail = "exit-nonzero", # missing or broken recovery blocks merge |
| 62 | + report_format = "a2ml", |
| 63 | + emit_summary = true, |
| 64 | + record_recovery_times = true, # feeds the performance tier |
| 65 | + }, |
| 66 | +} |
0 commit comments