{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://fluid.dev/schemas/experiment.schema.json", "title": "FLUID experiment record", "description": "Connects hypotheses to revisions under bounded conditions. Experiments must be interruptible (ArchitectureBlueprint.md section 16).", "type": "object", "properties": { "fluid_experiment": { "type": "object", "properties": { "schema_version": { "$ref": "common.schema.json#/$defs/schemaVersion" }, "id": { "$ref": "common.schema.json#/$defs/experimentId" }, "interface_id": { "$ref": "common.schema.json#/$defs/interfaceId" }, "hypothesis_refs": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/hypothesisId" }, "minItems": 1, "description": "An experiment without a hypothesis measures nothing in particular." }, "mechanism": { "enum": ["sandbox", "shadow", "synthetic", "replay", "canary", "opt_in", "cohort", "tenant", "percentage"] }, "control_revision": { "$ref": "common.schema.json#/$defs/revisionId" }, "candidate_revisions": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/revisionId" }, "minItems": 1 }, "cohorts": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/cohortId" } }, "allocation": { "type": "object", "description": "Shares by revision id or by the reserved key 'control'. Allocation is deterministic and enacted by the router, never by this record.", "additionalProperties": { "$ref": "common.schema.json#/$defs/unitInterval" }, "minProperties": 2 }, "start_at": { "$ref": "common.schema.json#/$defs/timestamp" }, "planned_end_at": { "oneOf": [{ "$ref": "common.schema.json#/$defs/timestamp" }, { "type": "null" }] }, "max_duration_hours": { "type": "number", "exclusiveMinimum": 0 }, "metrics": { "type": "object", "description": "Primary metrics and guardrails are kept distinct so a scalar can never hide a regression (ArchitectureBlueprint.md section 48.5).", "properties": { "primary": { "type": "array", "items": { "type": "string" }, "minItems": 1 }, "guardrails": { "type": "array", "items": { "type": "string" } }, "secondary": { "type": "array", "items": { "type": "string" } }, "learning": { "type": "array", "items": { "type": "string" } } }, "required": ["primary"], "additionalProperties": false }, "start_conditions": { "type": "array", "items": { "type": "string" } }, "stop_conditions": { "type": "array", "items": { "type": "string" }, "minItems": 1, "description": "Every experiment has a stop condition (ArchitectureBlueprint.md section 55, invariant 7)." }, "amendments": { "type": "array", "description": "Success criteria may not be changed after results are visible without recording the amendment (ArchitectureBlueprint.md section 18).", "items": { "type": "object", "properties": { "at": { "$ref": "common.schema.json#/$defs/timestamp" }, "actor": { "$ref": "common.schema.json#/$defs/actor" }, "change": { "type": "string", "minLength": 1 }, "reason": { "type": "string", "minLength": 1 } }, "required": ["at", "actor", "change", "reason"], "additionalProperties": false } }, "result": { "type": "object", "properties": { "state": { "enum": ["PLANNED", "RUNNING", "STOPPED", "COMPLETED", "ABANDONED"] }, "preferred_revision": { "oneOf": [{ "$ref": "common.schema.json#/$defs/revisionId" }, { "type": "null" }] }, "stopped_reason": { "type": ["string", "null"] }, "evidence_refs": { "type": "array", "items": { "$ref": "common.schema.json#/$defs/evidenceRef" } } }, "required": ["state"], "additionalProperties": false } }, "required": [ "schema_version", "id", "interface_id", "hypothesis_refs", "control_revision", "candidate_revisions", "allocation", "metrics", "stop_conditions", "result" ], "additionalProperties": false } }, "required": ["fluid_experiment"], "additionalProperties": false }