mayhem-cli 0.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mayhem/agent/__init__.py +1 -0
- mayhem/agent/cli.py +36 -0
- mayhem/agents/__init__.py +1 -0
- mayhem/agents/capabilities.py +106 -0
- mayhem/agents/executors.py +430 -0
- mayhem/agents/impact.py +729 -0
- mayhem/agents/lease_client.py +141 -0
- mayhem/agents/probes.py +284 -0
- mayhem/agents/protocol.py +134 -0
- mayhem/agents/server.py +281 -0
- mayhem/agents/sinks.py +60 -0
- mayhem/agents/transports.py +134 -0
- mayhem/agents/watchdog.py +140 -0
- mayhem/cli/__init__.py +11 -0
- mayhem/cli/app.py +154 -0
- mayhem/cli/campaign.py +496 -0
- mayhem/cli/config_cmd.py +47 -0
- mayhem/cli/context.py +23 -0
- mayhem/cli/dependency.py +429 -0
- mayhem/cli/exit_codes.py +24 -0
- mayhem/cli/experiment.py +24 -0
- mayhem/cli/lifecycle.py +805 -0
- mayhem/cli/resolver.py +72 -0
- mayhem/cli/services.py +459 -0
- mayhem/cli/style.py +101 -0
- mayhem/cli/toolkit.py +41 -0
- mayhem/cli/topology.py +127 -0
- mayhem/config.py +208 -0
- mayhem/controller/__init__.py +1 -0
- mayhem/controller/compensation.py +2156 -0
- mayhem/controller/executor.py +1719 -0
- mayhem/controller/janitor.py +196 -0
- mayhem/controller/observability_collector.py +382 -0
- mayhem/controller/observations.py +102 -0
- mayhem/controller/planner.py +715 -0
- mayhem/controller/recovery.py +245 -0
- mayhem/controller/resilience_report.py +585 -0
- mayhem/controller/resource_manager.py +457 -0
- mayhem/controller/safety.py +392 -0
- mayhem/domain/__init__.py +6 -0
- mayhem/domain/campaigns.py +118 -0
- mayhem/domain/cancellation.py +110 -0
- mayhem/domain/candidates.py +101 -0
- mayhem/domain/capabilities.py +86 -0
- mayhem/domain/catalog.py +727 -0
- mayhem/domain/checks.py +173 -0
- mayhem/domain/common.py +104 -0
- mayhem/domain/coverage.py +106 -0
- mayhem/domain/decisions.py +57 -0
- mayhem/domain/errors.py +87 -0
- mayhem/domain/events.py +61 -0
- mayhem/domain/execution_context.py +120 -0
- mayhem/domain/execution_loci.py +94 -0
- mayhem/domain/experiments.py +370 -0
- mayhem/domain/faults.py +239 -0
- mayhem/domain/identity.py +200 -0
- mayhem/domain/k8s_adapter.py +132 -0
- mayhem/domain/leases.py +186 -0
- mayhem/domain/load_strategy.py +98 -0
- mayhem/domain/m5_campaign.py +120 -0
- mayhem/domain/maniac.py +93 -0
- mayhem/domain/observability.py +146 -0
- mayhem/domain/outcomes.py +92 -0
- mayhem/domain/remote_agent_interface.py +70 -0
- mayhem/domain/resources.py +245 -0
- mayhem/domain/risks.py +61 -0
- mayhem/domain/run_outcome.py +146 -0
- mayhem/domain/runtime_adapter.py +256 -0
- mayhem/domain/success.py +329 -0
- mayhem/domain/topology.py +452 -0
- mayhem/infra/__init__.py +1 -0
- mayhem/infra/campaign_engine.py +205 -0
- mayhem/infra/candidate_gates.py +124 -0
- mayhem/infra/candidate_generator.py +110 -0
- mayhem/infra/coverage_repository.py +101 -0
- mayhem/infra/lease_repository.py +129 -0
- mayhem/infra/maniac.py +103 -0
- mayhem/infra/migrations.py +596 -0
- mayhem/infra/migrator.py +149 -0
- mayhem/infra/report.py +227 -0
- mayhem/infra/store.py +200 -0
- mayhem/py.typed +0 -0
- mayhem/spec.py +52 -0
- mayhem/toolkit/__init__.py +1 -0
- mayhem/toolkit/fingerprint.py +69 -0
- mayhem/toolkit/hashing.py +32 -0
- mayhem/toolkit/manifests/docker.yaml +11 -0
- mayhem/toolkit/manifests/podman.yaml +11 -0
- mayhem/toolkit/manifests/stress-ng.yaml +11 -0
- mayhem/toolkit/manifests/tc-netem.yaml +11 -0
- mayhem/toolkit/manifests/toxiproxy.yaml +10 -0
- mayhem/toolkit/registry.py +185 -0
- mayhem/toolkit/tool_runner.py +129 -0
- mayhem/topology/__init__.py +10 -0
- mayhem/topology/providers/__init__.py +0 -0
- mayhem/topology/providers/adapter_registry.py +60 -0
- mayhem/topology/providers/base.py +31 -0
- mayhem/topology/providers/compose.py +207 -0
- mayhem/topology/providers/docker_adapter.py +277 -0
- mayhem/topology/providers/docker_runtime.py +461 -0
- mayhem/topology/providers/podman_adapter.py +328 -0
- mayhem/topology/resolve.py +196 -0
- mayhem/topology/service.py +158 -0
- mayhem_cli-0.5.1.dist-info/METADATA +555 -0
- mayhem_cli-0.5.1.dist-info/RECORD +107 -0
- mayhem_cli-0.5.1.dist-info/WHEEL +4 -0
- mayhem_cli-0.5.1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
"""Schema v1 — canonical DDL from docs/reference/sqlite-schema.md."""
|
|
2
|
+
|
|
3
|
+
from mayhem.infra.migrator import Migration
|
|
4
|
+
|
|
5
|
+
M0001_INITIAL = Migration(
|
|
6
|
+
version=1,
|
|
7
|
+
name="initial",
|
|
8
|
+
statements=(
|
|
9
|
+
"""
|
|
10
|
+
CREATE TABLE config_snapshots (
|
|
11
|
+
id TEXT PRIMARY KEY,
|
|
12
|
+
resolved_json TEXT NOT NULL,
|
|
13
|
+
source_map TEXT NOT NULL,
|
|
14
|
+
created_at TEXT NOT NULL
|
|
15
|
+
)
|
|
16
|
+
""",
|
|
17
|
+
"""
|
|
18
|
+
CREATE TABLE topology_snapshots (
|
|
19
|
+
id TEXT PRIMARY KEY,
|
|
20
|
+
run_id TEXT REFERENCES runs(id),
|
|
21
|
+
graph_json TEXT NOT NULL,
|
|
22
|
+
drift_report TEXT NOT NULL,
|
|
23
|
+
fingerprint TEXT NOT NULL
|
|
24
|
+
)
|
|
25
|
+
""",
|
|
26
|
+
"""
|
|
27
|
+
CREATE TABLE runs (
|
|
28
|
+
id TEXT PRIMARY KEY,
|
|
29
|
+
experiment_name TEXT NOT NULL,
|
|
30
|
+
kind TEXT NOT NULL CHECK (kind IN ('deterministic','random')),
|
|
31
|
+
spec_json TEXT NOT NULL,
|
|
32
|
+
plan_json TEXT NOT NULL,
|
|
33
|
+
seed INTEGER,
|
|
34
|
+
status TEXT NOT NULL CHECK (status IN
|
|
35
|
+
('created','planning','validated','running','recovering',
|
|
36
|
+
'completed','failed','aborted')),
|
|
37
|
+
environment_fingerprint TEXT NOT NULL,
|
|
38
|
+
config_snapshot_id TEXT NOT NULL REFERENCES config_snapshots(id),
|
|
39
|
+
topology_snapshot_id TEXT REFERENCES topology_snapshots(id),
|
|
40
|
+
started_at TEXT,
|
|
41
|
+
ended_at TEXT,
|
|
42
|
+
summary_md TEXT
|
|
43
|
+
)
|
|
44
|
+
""",
|
|
45
|
+
"CREATE INDEX idx_runs_status ON runs(status)",
|
|
46
|
+
"CREATE INDEX idx_runs_started ON runs(started_at DESC)",
|
|
47
|
+
"""
|
|
48
|
+
CREATE TABLE step_runs (
|
|
49
|
+
id TEXT PRIMARY KEY,
|
|
50
|
+
run_id TEXT NOT NULL REFERENCES runs(id),
|
|
51
|
+
seq INTEGER NOT NULL,
|
|
52
|
+
parent_step_id TEXT REFERENCES step_runs(id),
|
|
53
|
+
action_type TEXT NOT NULL,
|
|
54
|
+
action_json TEXT NOT NULL,
|
|
55
|
+
status TEXT NOT NULL CHECK (status IN
|
|
56
|
+
('pending','running','completed','failed','skipped','cancelled')),
|
|
57
|
+
started_at TEXT,
|
|
58
|
+
ended_at TEXT,
|
|
59
|
+
error TEXT
|
|
60
|
+
)
|
|
61
|
+
""",
|
|
62
|
+
"""
|
|
63
|
+
CREATE TABLE fault_leases (
|
|
64
|
+
id TEXT PRIMARY KEY,
|
|
65
|
+
state TEXT NOT NULL CHECK (state IN
|
|
66
|
+
('pending','active','releasing','released','expired','orphaned','dirty')),
|
|
67
|
+
owner_agent TEXT NOT NULL,
|
|
68
|
+
undo_json TEXT NOT NULL,
|
|
69
|
+
verify_json TEXT NOT NULL,
|
|
70
|
+
ttl_seconds REAL NOT NULL,
|
|
71
|
+
expires_at TEXT NOT NULL,
|
|
72
|
+
injected_at TEXT,
|
|
73
|
+
released_at TEXT,
|
|
74
|
+
release_mechanism TEXT,
|
|
75
|
+
escalation_notes TEXT
|
|
76
|
+
)
|
|
77
|
+
""",
|
|
78
|
+
"CREATE INDEX idx_leases_state ON fault_leases(state)",
|
|
79
|
+
"""
|
|
80
|
+
CREATE TABLE fault_invocations (
|
|
81
|
+
id TEXT PRIMARY KEY,
|
|
82
|
+
run_id TEXT NOT NULL REFERENCES runs(id),
|
|
83
|
+
step_run_id TEXT NOT NULL REFERENCES step_runs(id),
|
|
84
|
+
fault_id TEXT NOT NULL,
|
|
85
|
+
targets_json TEXT NOT NULL,
|
|
86
|
+
params_json TEXT NOT NULL,
|
|
87
|
+
backend TEXT NOT NULL,
|
|
88
|
+
lease_id TEXT UNIQUE NOT NULL REFERENCES fault_leases(id)
|
|
89
|
+
)
|
|
90
|
+
""",
|
|
91
|
+
"""
|
|
92
|
+
CREATE TABLE recovery_records (
|
|
93
|
+
id TEXT PRIMARY KEY,
|
|
94
|
+
lease_id TEXT NOT NULL REFERENCES fault_leases(id),
|
|
95
|
+
attempt INTEGER NOT NULL,
|
|
96
|
+
mechanism TEXT NOT NULL,
|
|
97
|
+
undo_results_json TEXT NOT NULL,
|
|
98
|
+
verified INTEGER NOT NULL CHECK (verified IN (0, 1)),
|
|
99
|
+
at TEXT NOT NULL
|
|
100
|
+
)
|
|
101
|
+
""",
|
|
102
|
+
"""
|
|
103
|
+
CREATE TABLE tool_runs (
|
|
104
|
+
id TEXT PRIMARY KEY,
|
|
105
|
+
invocation_ref TEXT,
|
|
106
|
+
argv_digest TEXT NOT NULL,
|
|
107
|
+
argv_json TEXT NOT NULL,
|
|
108
|
+
env_digest TEXT NOT NULL,
|
|
109
|
+
host TEXT NOT NULL,
|
|
110
|
+
exit_code INTEGER,
|
|
111
|
+
duration_ms INTEGER,
|
|
112
|
+
truncated INTEGER NOT NULL DEFAULT 0 CHECK (truncated IN (0, 1)),
|
|
113
|
+
stdout_ref TEXT,
|
|
114
|
+
stderr_ref TEXT
|
|
115
|
+
)
|
|
116
|
+
""",
|
|
117
|
+
"""
|
|
118
|
+
CREATE TABLE agent_states (
|
|
119
|
+
id TEXT PRIMARY KEY,
|
|
120
|
+
host TEXT NOT NULL,
|
|
121
|
+
roles_json TEXT NOT NULL,
|
|
122
|
+
capabilities_json TEXT NOT NULL,
|
|
123
|
+
state TEXT NOT NULL CHECK (state IN ('ready','busy','dead','retired')),
|
|
124
|
+
last_heartbeat TEXT NOT NULL
|
|
125
|
+
)
|
|
126
|
+
""",
|
|
127
|
+
"""
|
|
128
|
+
CREATE TABLE events (
|
|
129
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
130
|
+
run_id TEXT REFERENCES runs(id),
|
|
131
|
+
ts TEXT NOT NULL,
|
|
132
|
+
kind TEXT NOT NULL,
|
|
133
|
+
payload_json TEXT NOT NULL
|
|
134
|
+
)
|
|
135
|
+
""",
|
|
136
|
+
"CREATE INDEX idx_events_run_ts ON events(run_id, ts)",
|
|
137
|
+
"""
|
|
138
|
+
CREATE TABLE steady_state_evaluations (
|
|
139
|
+
id TEXT PRIMARY KEY,
|
|
140
|
+
run_id TEXT NOT NULL REFERENCES runs(id),
|
|
141
|
+
check_id TEXT NOT NULL,
|
|
142
|
+
phase TEXT NOT NULL CHECK (phase IN ('pre','during','post')),
|
|
143
|
+
passed INTEGER NOT NULL CHECK (passed IN (0, 1)),
|
|
144
|
+
measured_json TEXT NOT NULL,
|
|
145
|
+
expectation_json TEXT NOT NULL,
|
|
146
|
+
evaluated_at TEXT NOT NULL
|
|
147
|
+
)
|
|
148
|
+
""",
|
|
149
|
+
"""
|
|
150
|
+
CREATE TABLE maniac_decisions (
|
|
151
|
+
id TEXT PRIMARY KEY,
|
|
152
|
+
run_id TEXT UNIQUE REFERENCES runs(id),
|
|
153
|
+
candidates_json TEXT NOT NULL,
|
|
154
|
+
weights_json TEXT NOT NULL,
|
|
155
|
+
rng_state TEXT NOT NULL,
|
|
156
|
+
chosen_plan_json TEXT NOT NULL,
|
|
157
|
+
decided_at TEXT NOT NULL
|
|
158
|
+
)
|
|
159
|
+
""",
|
|
160
|
+
),
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
M0002_LEASE_CONTEXT = Migration(
|
|
164
|
+
version=2,
|
|
165
|
+
name="lease_context",
|
|
166
|
+
statements=(
|
|
167
|
+
"ALTER TABLE fault_leases ADD COLUMN run_id TEXT",
|
|
168
|
+
"ALTER TABLE fault_leases ADD COLUMN fault_id TEXT NOT NULL DEFAULT ''",
|
|
169
|
+
"ALTER TABLE fault_leases ADD COLUMN targets_json TEXT NOT NULL DEFAULT '[]'",
|
|
170
|
+
"ALTER TABLE fault_leases ADD COLUMN created_epoch_s REAL NOT NULL DEFAULT 0",
|
|
171
|
+
),
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
M0003_CAMPAIGNS_OBSERVATIONS = Migration(
|
|
175
|
+
version=3,
|
|
176
|
+
name="campaigns_and_observations",
|
|
177
|
+
statements=(
|
|
178
|
+
"""
|
|
179
|
+
CREATE TABLE campaigns (
|
|
180
|
+
id TEXT PRIMARY KEY,
|
|
181
|
+
name TEXT NOT NULL,
|
|
182
|
+
description TEXT NOT NULL DEFAULT '',
|
|
183
|
+
status TEXT NOT NULL DEFAULT 'draft'
|
|
184
|
+
CHECK (status IN ('draft','scheduled','running','paused','completed','aborted')),
|
|
185
|
+
experiments_json TEXT NOT NULL DEFAULT '[]',
|
|
186
|
+
window_json TEXT NOT NULL DEFAULT '{}',
|
|
187
|
+
policy_json TEXT NOT NULL DEFAULT '{}',
|
|
188
|
+
labels_json TEXT NOT NULL DEFAULT '{}',
|
|
189
|
+
created_at TEXT NOT NULL,
|
|
190
|
+
updated_at TEXT NOT NULL
|
|
191
|
+
)
|
|
192
|
+
""",
|
|
193
|
+
"CREATE INDEX idx_campaigns_status ON campaigns(status)",
|
|
194
|
+
"""
|
|
195
|
+
CREATE TABLE observations (
|
|
196
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
197
|
+
kind TEXT NOT NULL,
|
|
198
|
+
run_id TEXT NOT NULL,
|
|
199
|
+
source TEXT NOT NULL DEFAULT '',
|
|
200
|
+
data_json TEXT NOT NULL DEFAULT '{}',
|
|
201
|
+
timestamp TEXT NOT NULL
|
|
202
|
+
)
|
|
203
|
+
""",
|
|
204
|
+
"CREATE INDEX idx_observations_run ON observations(run_id)",
|
|
205
|
+
"CREATE INDEX idx_observations_kind ON observations(kind)",
|
|
206
|
+
),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
M0004_DRILL_RUN_KIND = Migration(
|
|
210
|
+
version=4,
|
|
211
|
+
name="drill_run_kind",
|
|
212
|
+
statements=(
|
|
213
|
+
# Rebuild `runs` (no ALTER support for CHECK constraints in SQLite) so the
|
|
214
|
+
# `kind` column admits 'drill' plans (Phase 5). FK enforcement is disabled
|
|
215
|
+
# for the migration by run_migrations; id values are preserved.
|
|
216
|
+
"""
|
|
217
|
+
CREATE TABLE runs_new (
|
|
218
|
+
id TEXT PRIMARY KEY,
|
|
219
|
+
experiment_name TEXT NOT NULL,
|
|
220
|
+
kind TEXT NOT NULL CHECK (kind IN ('deterministic','random','drill')),
|
|
221
|
+
spec_json TEXT NOT NULL,
|
|
222
|
+
plan_json TEXT NOT NULL,
|
|
223
|
+
seed INTEGER,
|
|
224
|
+
status TEXT NOT NULL CHECK (status IN
|
|
225
|
+
('created','planning','validated','running','recovering',
|
|
226
|
+
'completed','failed','aborted')),
|
|
227
|
+
environment_fingerprint TEXT NOT NULL,
|
|
228
|
+
config_snapshot_id TEXT NOT NULL REFERENCES config_snapshots(id),
|
|
229
|
+
topology_snapshot_id TEXT REFERENCES topology_snapshots(id),
|
|
230
|
+
started_at TEXT,
|
|
231
|
+
ended_at TEXT,
|
|
232
|
+
summary_md TEXT
|
|
233
|
+
)
|
|
234
|
+
""",
|
|
235
|
+
"""
|
|
236
|
+
INSERT INTO runs_new (id, experiment_name, kind, spec_json, plan_json, seed,
|
|
237
|
+
status, environment_fingerprint, config_snapshot_id, topology_snapshot_id,
|
|
238
|
+
started_at, ended_at, summary_md)
|
|
239
|
+
SELECT id, experiment_name, kind, spec_json, plan_json, seed,
|
|
240
|
+
status, environment_fingerprint, config_snapshot_id, topology_snapshot_id,
|
|
241
|
+
started_at, ended_at, summary_md
|
|
242
|
+
FROM runs
|
|
243
|
+
""",
|
|
244
|
+
"DROP TABLE runs",
|
|
245
|
+
"ALTER TABLE runs_new RENAME TO runs",
|
|
246
|
+
"CREATE INDEX idx_runs_status ON runs(status)",
|
|
247
|
+
"CREATE INDEX idx_runs_started ON runs(started_at DESC)",
|
|
248
|
+
),
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
M0005_STEP_RUN_BYPASS_STATUS = Migration(
|
|
252
|
+
version=5,
|
|
253
|
+
name="step_run_bypass_status",
|
|
254
|
+
statements=(
|
|
255
|
+
# Rebuild `step_runs` so `status` admits 'bypassed' — the per-fault
|
|
256
|
+
# fail-safe outcome where the impact gate proved tooling absent and the
|
|
257
|
+
# engine skipped the injection instead of failing the run.
|
|
258
|
+
"""
|
|
259
|
+
CREATE TABLE step_runs_new (
|
|
260
|
+
id TEXT PRIMARY KEY,
|
|
261
|
+
run_id TEXT NOT NULL REFERENCES runs(id),
|
|
262
|
+
seq INTEGER NOT NULL,
|
|
263
|
+
parent_step_id TEXT REFERENCES step_runs(id),
|
|
264
|
+
action_type TEXT NOT NULL,
|
|
265
|
+
action_json TEXT NOT NULL,
|
|
266
|
+
status TEXT NOT NULL CHECK (status IN
|
|
267
|
+
('pending','running','completed','failed','skipped','cancelled','bypassed')),
|
|
268
|
+
started_at TEXT,
|
|
269
|
+
ended_at TEXT,
|
|
270
|
+
error TEXT
|
|
271
|
+
)
|
|
272
|
+
""",
|
|
273
|
+
"""
|
|
274
|
+
INSERT INTO step_runs_new (id, run_id, seq, parent_step_id, action_type,
|
|
275
|
+
action_json, status, started_at, ended_at, error)
|
|
276
|
+
SELECT id, run_id, seq, parent_step_id, action_type,
|
|
277
|
+
action_json, status, started_at, ended_at, error
|
|
278
|
+
FROM step_runs
|
|
279
|
+
""",
|
|
280
|
+
"DROP TABLE step_runs",
|
|
281
|
+
"ALTER TABLE step_runs_new RENAME TO step_runs",
|
|
282
|
+
),
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
M0006_RUNTIME_IDENTITY = Migration(
|
|
286
|
+
version=6,
|
|
287
|
+
name="runtime_identity",
|
|
288
|
+
statements=(
|
|
289
|
+
# Rebuild `step_runs` adding the canonical `runtime_identity` column and
|
|
290
|
+
# admitting `'target_drift'` as a first-class persisted step status
|
|
291
|
+
# (ADR-M1-3 Phase 1.4). `'bypassed'` and all prior statuses are retained
|
|
292
|
+
# so pre-M1 rows read identically (ADR-M1-4).
|
|
293
|
+
"""
|
|
294
|
+
CREATE TABLE step_runs_v6 (
|
|
295
|
+
id TEXT PRIMARY KEY,
|
|
296
|
+
run_id TEXT NOT NULL REFERENCES runs(id),
|
|
297
|
+
seq INTEGER NOT NULL,
|
|
298
|
+
parent_step_id TEXT REFERENCES step_runs(id),
|
|
299
|
+
action_type TEXT NOT NULL,
|
|
300
|
+
action_json TEXT NOT NULL,
|
|
301
|
+
status TEXT NOT NULL CHECK (status IN
|
|
302
|
+
('pending','running','completed','failed','skipped','cancelled',
|
|
303
|
+
'bypassed','target_drift')),
|
|
304
|
+
started_at TEXT,
|
|
305
|
+
ended_at TEXT,
|
|
306
|
+
error TEXT,
|
|
307
|
+
runtime_identity TEXT
|
|
308
|
+
)
|
|
309
|
+
""",
|
|
310
|
+
"""
|
|
311
|
+
INSERT INTO step_runs_v6 (id, run_id, seq, parent_step_id, action_type,
|
|
312
|
+
action_json, status, started_at, ended_at, error, runtime_identity)
|
|
313
|
+
SELECT id, run_id, seq, parent_step_id, action_type,
|
|
314
|
+
action_json, status, started_at, ended_at, error, NULL
|
|
315
|
+
FROM step_runs
|
|
316
|
+
""",
|
|
317
|
+
"DROP TABLE step_runs",
|
|
318
|
+
"ALTER TABLE step_runs_v6 RENAME TO step_runs",
|
|
319
|
+
# Nullable identity columns on every persisted record (ADR-M1-3).
|
|
320
|
+
"ALTER TABLE runs ADD COLUMN runtime_identity TEXT",
|
|
321
|
+
"ALTER TABLE fault_leases ADD COLUMN runtime_identity TEXT",
|
|
322
|
+
"ALTER TABLE observations ADD COLUMN runtime_identity TEXT",
|
|
323
|
+
"ALTER TABLE recovery_records ADD COLUMN runtime_identity TEXT",
|
|
324
|
+
),
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
M0007_FAULT_GROUPS = Migration(
|
|
329
|
+
version=7,
|
|
330
|
+
name="fault_groups",
|
|
331
|
+
statements=(
|
|
332
|
+
# Persistent fault-group attribution (ADR-M2-1/2-2): every executed
|
|
333
|
+
# step and fault invocation carries the group it belongs to. In-place
|
|
334
|
+
# column additions per Q9 (schema freeze enforced at M4).
|
|
335
|
+
"ALTER TABLE step_runs ADD COLUMN execution_group_id TEXT",
|
|
336
|
+
"ALTER TABLE step_runs ADD COLUMN group_mode TEXT",
|
|
337
|
+
"ALTER TABLE step_runs ADD COLUMN group_path TEXT",
|
|
338
|
+
"ALTER TABLE fault_invocations ADD COLUMN execution_group_id TEXT",
|
|
339
|
+
"CREATE INDEX idx_step_runs_group ON step_runs(execution_group_id)",
|
|
340
|
+
),
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
M0008_FAILED_TO_APPLY = Migration(
|
|
345
|
+
version=8,
|
|
346
|
+
name="failed_to_apply",
|
|
347
|
+
statements=(
|
|
348
|
+
# Execution-time capability revalidation (ADR-M2 Phase 2.3): a fault
|
|
349
|
+
# that reaches the mutation boundary but whose capability no longer
|
|
350
|
+
# holds (engine binary gone, tooling removed after plan time) is
|
|
351
|
+
# recorded as `'failed_to_apply'` instead of mutating or bypassing.
|
|
352
|
+
# Rebuild `step_runs` to admit the new persisted status; every prior
|
|
353
|
+
# status remains so pre-M8 rows read identically (ADR-M1-4).
|
|
354
|
+
"""
|
|
355
|
+
CREATE TABLE step_runs_v8 (
|
|
356
|
+
id TEXT PRIMARY KEY,
|
|
357
|
+
run_id TEXT NOT NULL REFERENCES runs(id),
|
|
358
|
+
seq INTEGER NOT NULL,
|
|
359
|
+
parent_step_id TEXT REFERENCES step_runs(id),
|
|
360
|
+
action_type TEXT NOT NULL,
|
|
361
|
+
action_json TEXT NOT NULL,
|
|
362
|
+
status TEXT NOT NULL CHECK (status IN
|
|
363
|
+
('pending','running','completed','failed','skipped','cancelled',
|
|
364
|
+
'bypassed','target_drift','failed_to_apply')),
|
|
365
|
+
started_at TEXT,
|
|
366
|
+
ended_at TEXT,
|
|
367
|
+
error TEXT,
|
|
368
|
+
runtime_identity TEXT,
|
|
369
|
+
execution_group_id TEXT,
|
|
370
|
+
group_mode TEXT,
|
|
371
|
+
group_path TEXT
|
|
372
|
+
)
|
|
373
|
+
""",
|
|
374
|
+
"""
|
|
375
|
+
INSERT INTO step_runs_v8 (id, run_id, seq, parent_step_id, action_type,
|
|
376
|
+
action_json, status, started_at, ended_at, error, runtime_identity,
|
|
377
|
+
execution_group_id, group_mode, group_path)
|
|
378
|
+
SELECT id, run_id, seq, parent_step_id, action_type,
|
|
379
|
+
action_json, status, started_at, ended_at, error, runtime_identity,
|
|
380
|
+
execution_group_id, group_mode, group_path
|
|
381
|
+
FROM step_runs
|
|
382
|
+
""",
|
|
383
|
+
"DROP TABLE step_runs",
|
|
384
|
+
"ALTER TABLE step_runs_v8 RENAME TO step_runs",
|
|
385
|
+
"CREATE INDEX idx_step_runs_group ON step_runs(execution_group_id)",
|
|
386
|
+
),
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
M0009_FORK_ATOMICITY = Migration(
|
|
391
|
+
version=9,
|
|
392
|
+
name="fork_atomicity",
|
|
393
|
+
statements=(
|
|
394
|
+
# ADR-M2 Phase 2.8 — fork atomicity. A run starts by snapshotting the
|
|
395
|
+
# topology fork and committing a plan *as a pair*; either both land or
|
|
396
|
+
# neither. The staging table records the commit phase so a crash
|
|
397
|
+
# between "fork durable" and "plan committed" leaves a durable marker
|
|
398
|
+
# the next startup can reconcile (orphaned fork -> cleaned up).
|
|
399
|
+
"""
|
|
400
|
+
CREATE TABLE run_fork_staging (
|
|
401
|
+
run_id TEXT PRIMARY KEY,
|
|
402
|
+
topo_id TEXT NOT NULL,
|
|
403
|
+
phase TEXT NOT NULL CHECK (phase IN ('planning','committed')),
|
|
404
|
+
created_at TEXT NOT NULL,
|
|
405
|
+
committed_at TEXT
|
|
406
|
+
)
|
|
407
|
+
""",
|
|
408
|
+
# Rebuild step_runs to admit the persisted `resource_conflict` status
|
|
409
|
+
# (ADR-M2 Phase 2.7).
|
|
410
|
+
"""
|
|
411
|
+
CREATE TABLE step_runs_v9 (
|
|
412
|
+
id TEXT PRIMARY KEY,
|
|
413
|
+
run_id TEXT NOT NULL REFERENCES runs(id),
|
|
414
|
+
seq INTEGER NOT NULL,
|
|
415
|
+
parent_step_id TEXT REFERENCES step_runs(id),
|
|
416
|
+
action_type TEXT NOT NULL,
|
|
417
|
+
action_json TEXT NOT NULL,
|
|
418
|
+
status TEXT NOT NULL CHECK (status IN
|
|
419
|
+
('pending','running','completed','failed','skipped','cancelled',
|
|
420
|
+
'bypassed','target_drift','failed_to_apply','resource_conflict')),
|
|
421
|
+
started_at TEXT,
|
|
422
|
+
ended_at TEXT,
|
|
423
|
+
error TEXT,
|
|
424
|
+
runtime_identity TEXT,
|
|
425
|
+
execution_group_id TEXT,
|
|
426
|
+
group_mode TEXT,
|
|
427
|
+
group_path TEXT
|
|
428
|
+
)
|
|
429
|
+
""",
|
|
430
|
+
"""
|
|
431
|
+
INSERT INTO step_runs_v9 (id, run_id, seq, parent_step_id, action_type,
|
|
432
|
+
action_json, status, started_at, ended_at, error, runtime_identity,
|
|
433
|
+
execution_group_id, group_mode, group_path)
|
|
434
|
+
SELECT id, run_id, seq, parent_step_id, action_type,
|
|
435
|
+
action_json, status, started_at, ended_at, error, runtime_identity,
|
|
436
|
+
execution_group_id, group_mode, group_path
|
|
437
|
+
FROM step_runs
|
|
438
|
+
""",
|
|
439
|
+
"DROP TABLE step_runs",
|
|
440
|
+
"ALTER TABLE step_runs_v9 RENAME TO step_runs",
|
|
441
|
+
"CREATE INDEX idx_step_runs_group ON step_runs(execution_group_id)",
|
|
442
|
+
),
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
# M0010 — NetworkPath target columns (ADR-M3-7).
|
|
447
|
+
#
|
|
448
|
+
# A fault step may target a first-class NetworkPath rather than a bare
|
|
449
|
+
# container name. The structured fault is already serialized in action_json;
|
|
450
|
+
# these three *nullable* columns make the path target queryable without parsing
|
|
451
|
+
# the blob and provide a stable place for the fingerprint. They are added with
|
|
452
|
+
# ALTER TABLE ADD COLUMN (nullable, no default) so existing step_runs rows are
|
|
453
|
+
# untouched — no table rebuild, no CHECK evolution needed.
|
|
454
|
+
M0010_NETWORK_PATH = Migration(
|
|
455
|
+
version=10,
|
|
456
|
+
name="network_path",
|
|
457
|
+
statements=(
|
|
458
|
+
"ALTER TABLE step_runs ADD COLUMN network_path TEXT",
|
|
459
|
+
"ALTER TABLE step_runs ADD COLUMN path_namespace TEXT",
|
|
460
|
+
"ALTER TABLE step_runs ADD COLUMN path_interface TEXT",
|
|
461
|
+
"ALTER TABLE step_runs ADD COLUMN network_fingerprint TEXT",
|
|
462
|
+
),
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
# ── M4-3/4-4/4-5: Success criteria verdict + observability (ADR-M4-3/4-4) ─
|
|
467
|
+
M0013_M4_SUCCESS_OBSERVABILITY = Migration(
|
|
468
|
+
version=13,
|
|
469
|
+
name="m4_success_observability",
|
|
470
|
+
statements=(
|
|
471
|
+
# A drill's machine-evaluable verdict (ADR-M4-3) and the raw criteria
|
|
472
|
+
# evaluation, persisted on the run row; both nullable — runs without
|
|
473
|
+
# declared criteria keep a NULL verdict and the existing status flow.
|
|
474
|
+
"ALTER TABLE runs ADD COLUMN verdict TEXT",
|
|
475
|
+
"ALTER TABLE runs ADD COLUMN criteria_json TEXT",
|
|
476
|
+
),
|
|
477
|
+
down_statements=(
|
|
478
|
+
# ADR-M4-5: a DB at the M4 schema can be restored to the frozen baseline.
|
|
479
|
+
"ALTER TABLE runs DROP COLUMN criteria_json",
|
|
480
|
+
"ALTER TABLE runs DROP COLUMN verdict",
|
|
481
|
+
),
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
# ── M4-4/4-1: Observability evidence + governing-decision trace (ADR-M4-4) ──
|
|
486
|
+
M0014_M4_OBSERVABILITY_AND_DECISIONS = Migration(
|
|
487
|
+
version=14,
|
|
488
|
+
name="m4_observability_decisions",
|
|
489
|
+
statements=(
|
|
490
|
+
# Collected observability evidence (ADR-M4-4) and the decision refs
|
|
491
|
+
# (ADR ids + decided-on timestamps, ADR-M4-1) that produced the run,
|
|
492
|
+
# both persisted on the run row; additive and nullable.
|
|
493
|
+
"ALTER TABLE runs ADD COLUMN observability_json TEXT",
|
|
494
|
+
"ALTER TABLE runs ADD COLUMN governing_decisions_json TEXT",
|
|
495
|
+
),
|
|
496
|
+
down_statements=(
|
|
497
|
+
"ALTER TABLE runs DROP COLUMN governing_decisions_json",
|
|
498
|
+
"ALTER TABLE runs DROP COLUMN observability_json",
|
|
499
|
+
),
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
# ── M5-1: Run and Outcome domain persistence (ADR-M5-1) ──────────────
|
|
504
|
+
M0011_M5_RUN_OUTCOME = Migration(
|
|
505
|
+
version=11,
|
|
506
|
+
name="m5_run_outcome",
|
|
507
|
+
statements=(
|
|
508
|
+
"""
|
|
509
|
+
CREATE TABLE m5_runs (
|
|
510
|
+
id TEXT PRIMARY KEY,
|
|
511
|
+
experiment_name TEXT NOT NULL,
|
|
512
|
+
spec_json TEXT NOT NULL,
|
|
513
|
+
plan_json TEXT NOT NULL,
|
|
514
|
+
seed INTEGER,
|
|
515
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
516
|
+
environment_fingerprint TEXT NOT NULL DEFAULT '',
|
|
517
|
+
config_snapshot_id TEXT NOT NULL DEFAULT '',
|
|
518
|
+
started_at TEXT NOT NULL DEFAULT '',
|
|
519
|
+
ended_at TEXT NOT NULL DEFAULT '',
|
|
520
|
+
description TEXT NOT NULL DEFAULT '',
|
|
521
|
+
verdict TEXT NOT NULL DEFAULT 'pass',
|
|
522
|
+
tags_json TEXT NOT NULL DEFAULT '[]',
|
|
523
|
+
extra_json TEXT NOT NULL DEFAULT '{}'
|
|
524
|
+
)
|
|
525
|
+
""",
|
|
526
|
+
"CREATE INDEX idx_m5_runs_status ON m5_runs(status)",
|
|
527
|
+
"CREATE INDEX idx_m5_runs_experiment ON m5_runs(experiment_name)",
|
|
528
|
+
"""
|
|
529
|
+
CREATE TABLE m5_outcomes (
|
|
530
|
+
run_id TEXT PRIMARY KEY REFERENCES m5_runs(id),
|
|
531
|
+
body_json TEXT NOT NULL DEFAULT '{}',
|
|
532
|
+
body_hash TEXT NOT NULL DEFAULT '',
|
|
533
|
+
checks_passed INTEGER NOT NULL DEFAULT 0,
|
|
534
|
+
checks_failed INTEGER NOT NULL DEFAULT 0,
|
|
535
|
+
metric_deltas_json TEXT NOT NULL DEFAULT '{}',
|
|
536
|
+
residual_effect TEXT NOT NULL DEFAULT '',
|
|
537
|
+
stability_signal TEXT NOT NULL DEFAULT '',
|
|
538
|
+
extra_json TEXT NOT NULL DEFAULT '{}'
|
|
539
|
+
)
|
|
540
|
+
""",
|
|
541
|
+
),
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
# ── M5-2: Coverage accounting (ADR-M5-3) ─────────────────────────────
|
|
546
|
+
M0012_M5_COVERAGE = Migration(
|
|
547
|
+
version=12,
|
|
548
|
+
name="m5_coverage",
|
|
549
|
+
statements=(
|
|
550
|
+
"""
|
|
551
|
+
CREATE TABLE m5_coverage (
|
|
552
|
+
cell_key TEXT PRIMARY KEY,
|
|
553
|
+
target TEXT NOT NULL,
|
|
554
|
+
fault_kind TEXT NOT NULL,
|
|
555
|
+
execution_context TEXT NOT NULL,
|
|
556
|
+
parameter_band TEXT NOT NULL,
|
|
557
|
+
run_id TEXT NOT NULL,
|
|
558
|
+
covered INTEGER NOT NULL DEFAULT 1,
|
|
559
|
+
extra_json TEXT NOT NULL DEFAULT '{}'
|
|
560
|
+
)
|
|
561
|
+
""",
|
|
562
|
+
"CREATE INDEX idx_m5_coverage_target ON m5_coverage(target)",
|
|
563
|
+
"CREATE INDEX idx_m5_coverage_fault ON m5_coverage(fault_kind)",
|
|
564
|
+
),
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
# ── Run liveness: the controller records its pid so the janitor can tell
|
|
569
|
+
# ── a dead owner from a live one and reclaim within-TTL leases it left.
|
|
570
|
+
# ── Without this, a crashed ``run`` wedges its targets until TTL (the
|
|
571
|
+
# ── reported "janitor did nothing" pain).
|
|
572
|
+
M0015_RUN_CONTROLLER_PID = Migration(
|
|
573
|
+
version=15,
|
|
574
|
+
name="run_controller_pid",
|
|
575
|
+
statements=("ALTER TABLE runs ADD COLUMN controller_pid INTEGER",),
|
|
576
|
+
down_statements=("ALTER TABLE runs DROP COLUMN controller_pid",),
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
ALL_MIGRATIONS: tuple[Migration, ...] = (
|
|
581
|
+
M0001_INITIAL,
|
|
582
|
+
M0002_LEASE_CONTEXT,
|
|
583
|
+
M0003_CAMPAIGNS_OBSERVATIONS,
|
|
584
|
+
M0004_DRILL_RUN_KIND,
|
|
585
|
+
M0005_STEP_RUN_BYPASS_STATUS,
|
|
586
|
+
M0006_RUNTIME_IDENTITY,
|
|
587
|
+
M0007_FAULT_GROUPS,
|
|
588
|
+
M0008_FAILED_TO_APPLY,
|
|
589
|
+
M0009_FORK_ATOMICITY,
|
|
590
|
+
M0010_NETWORK_PATH,
|
|
591
|
+
M0011_M5_RUN_OUTCOME,
|
|
592
|
+
M0012_M5_COVERAGE,
|
|
593
|
+
M0013_M4_SUCCESS_OBSERVABILITY,
|
|
594
|
+
M0014_M4_OBSERVABILITY_AND_DECISIONS,
|
|
595
|
+
M0015_RUN_CONTROLLER_PID,
|
|
596
|
+
)
|