{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://mosaicstack.dev/schemas/wake-watch-list.schema.json", "title": "Mosaic Wake Watch-List", "description": "Declarative watch-list for the wake/heartbeat detector (EPIC #892). The SCHEMA is framework-owned; the VALUES are operator-supplied (repos, board files, lane anchors, per-class SLOs). This is the W2 schema contract only — the detector (W4) and digest renderer (W3) consume it. Per CONVERGED-DESIGN §1.4: 'operator repo; schema is framework, values are operator.'", "type": "object", "required": ["schema_version", "watches"], "additionalProperties": false, "properties": { "schema_version": { "type": "integer", "minimum": 1, "description": "Watch-list schema version. The wake component's manifest.txt declares the supported range (schema_min/schema_max, Gate B); a watch-list outside that range is rejected by the component, not silently coerced." }, "host": { "type": "string", "description": "Optional operator label for the host this watch-list serves. Per-host single-instance detector (§1.1). Operator-supplied; no semantic meaning to the schema." }, "repos": { "type": "array", "description": "Git repositories to watch. Source SHAs are descriptors, not the cursor (§2.4).", "items": { "type": "object", "required": ["id"], "additionalProperties": false, "properties": { "id": { "type": "string", "description": "Operator-chosen stable identifier for this repo watch." }, "remote": { "type": "string", "description": "Remote/clone locator (operator-supplied). No credentials inline; secrets are by-name via load_credentials." }, "branches": { "type": "array", "items": { "type": "string" }, "description": "Branch refs to track. Empty => default branch." }, "class": { "$ref": "#/$defs/class" }, "slo": { "$ref": "#/$defs/slo_ref" }, "aba_sensitive": { "type": "boolean", "default": false, "description": "If true, this source needs an event-stream/webhook rather than poll-only (intra-poll ABA mitigation, §2.4 / gate G5). Poll-only remains a mitigation, not elimination." } } } }, "board_files": { "type": "array", "description": "Board / decision files whose edits must be caught (repo-section/anchor-scoped hashing, §1.1). Human-decision file edits, not just API-visible state.", "items": { "type": "object", "required": ["id", "path"], "additionalProperties": false, "properties": { "id": { "type": "string" }, "repo": { "type": "string", "description": "Optional reference to a repos[].id this file lives in." }, "path": { "type": "string", "description": "File path (operator-supplied). Locators are hard: repo/issue#/SHA/file:anchor (§2.1)." }, "class": { "$ref": "#/$defs/class" }, "slo": { "$ref": "#/$defs/slo_ref" } } } }, "lane_anchors": { "type": "array", "description": "In-file anchors (headings/markers) scoping a lane's obligations, so a file edit outside the lane's anchor does not wake it.", "items": { "type": "object", "required": ["id", "anchor"], "additionalProperties": false, "properties": { "id": { "type": "string" }, "board_file": { "type": "string", "description": "Optional reference to a board_files[].id this anchor lives in." }, "anchor": { "type": "string", "description": "Anchor text/marker delimiting the lane's section within the file." }, "class": { "$ref": "#/$defs/class" }, "slo": { "$ref": "#/$defs/slo_ref" } } } }, "slos": { "type": "object", "description": "Named per-class urgency SLO tiers. SYMBOLIC — the operator sets concrete durations; the schema only fixes the shape and the class ordering intent (§4: security/lease/CI = tight; board = tens of minutes; routine = hours). No numeric parameters are baked into the framework.", "additionalProperties": { "type": "object", "additionalProperties": false, "properties": { "class": { "$ref": "#/$defs/class" }, "fallback_bound": { "type": "string", "description": "Operator-supplied duration (e.g. '5m', '30m', '4h'). Symbolic tier is set by the operator, not the framework." }, "fallback_cadence": { "type": "string", "description": "OPTIONAL, additive (schema_version 1, backward-compatible — omitting it is valid). The per-class cadence bound for the framework-shipped canon FALLBACK WAKE (F7 replacement-before-retirement, EPIC #892): the low-frequency SAFETY-wake timer (mosaic-wake-fallback.timer) that fires the canon drain INDEPENDENT of the event-driven detector, so a stalled detector cannot silently starve delivery. The A10 installer reads this per-class value and writes it as the fallback timer's OnUnitActiveSec via the blank-reset drop-in (exactly one effective OnUnitActiveUSec). SYMBOLIC — an operator-supplied duration (e.g. '30m', '1h', '4h'); the framework bakes in no numeric. Config, not code. Should be no tighter than this tier's `fallback_bound` (the safety wake is a floor, never the primary mechanism)." }, "quiet_hours_may_suppress": { "type": "boolean", "default": false, "description": "If true, quiet-hours may suppress the cold fallback for this tier. MUST remain false for actionable/critical classes (§3: quiet-hours never gate an actionable/critical class)." }, "measure_to": { "type": "string", "enum": ["consumed", "qualified-action-or-handoff"], "description": "Terminal the SLO is measured to (§4/G8): CONSUMED measures reading; qualified-action-or-handoff measures doing. Actionable/critical classes measure to the action terminal." } } } }, "watches": { "type": "array", "description": "The declared source-coverage inventory: a lane-by-lane list of every operational source the lane depends on, so an omitted source cannot make the retirement vector pass vacuously (§4/G3 parity inventory). Each entry references a source declared above by kind+id.", "items": { "type": "object", "required": ["lane", "sources"], "additionalProperties": false, "properties": { "lane": { "type": "string", "description": "Operator lane identifier this watch serves." }, "sources": { "type": "array", "minItems": 1, "items": { "type": "object", "required": ["kind", "id"], "additionalProperties": false, "properties": { "kind": { "type": "string", "enum": ["repo", "board_file", "lane_anchor"], "description": "Which top-level collection the id refers to." }, "id": { "type": "string", "description": "Reference to repos[].id / board_files[].id / lane_anchors[].id." } } } } } } } }, "$defs": { "class": { "type": "string", "enum": ["digest", "actionable", "human", "terminal-log", "reaction"], "description": "Wake class (§2.3). Only `digest` coalesces (cumulative-state replace); actionable/human APPEND. ALL classes are durable. Absent class => the consumer treats it as `actionable` (fail-safe)." }, "slo_ref": { "type": "string", "description": "Name of an entry in the top-level `slos` map to apply to this source." } } }