@@ -74,6 +74,240 @@ Healthy direction:
7474
7575---
7676
77+ ## Runtime health model
78+
79+ Backend stability is first-class platform state, not a conclusion the loop
80+ reconstructs from log tails. Watchers and runtime services should write or
81+ surface structured health records equivalent to:
82+
83+ ``` yaml
84+ backend_health :
85+ kodo :
86+ state : unstable
87+ failure_count : 2
88+ last_success_at : null
89+ last_failure :
90+ signature : signal:SIGKILL
91+ signal : SIGKILL
92+ exit_code : null
93+ cooldown_until : " ..."
94+ safe_retry_after : " ..."
95+ recovery_strategy : reduce_pressure
96+ ` ` `
97+
98+ Allowed states are ` unknown`, `healthy`, `degraded`, `unstable`,
99+ ` unavailable` , `recovering`, and `operator_blocked`.
100+
101+ Runtime watchers own these transitions :
102+ - Success resets backend health to `healthy`
103+ - ` SIGKILL` transitions to `unstable`, applies cooldown, and forbids immediate replay
104+ - Repeated backend failures transition toward `unavailable` and escalation
105+ - Exhausted recovery marks `operator_blocked` with an explicit reason
106+
107+ The loop should consume this state before reading raw logs. Raw logs are fallback
108+ evidence only when structured health records are missing or contradictory.
109+
110+ ---
111+
112+ # # Recovery ownership boundaries
113+
114+ The permanent target is :
115+
116+ ` ` ` text
117+ watchers = healer + coordinator
118+ loop = oversight + escalation + audit
119+ ` ` `
120+
121+ Watcher telemetry must include enough structured evidence for the next watcher
122+ or policy layer to act without prompt-side inference.
123+
124+ Required telemetry by owner :
125+ - `improve` : ` executor_exit_code` , `executor_signal`, `retry_strategy_used`,
126+ ` retry_strategy_changed` , `remediation_attempt_number`,
127+ ` remediation_lineage_id` , `prior_failure_signature`
128+ - `triage` : ` blocked_reason` , `blocked_by_backend`, `retry_safe`,
129+ ` queue_transition_recommendation`
130+ - `goal` / `propose` : ` duplicate_reason` , `suppression_reason`,
131+ ` starvation_detected` , `queue_deadlock_detected`
132+ - `watchdog` / runtime supervisor : ` backend_health_transition` ,
133+ ` cooldown_applied` , `recovery_attempt_started`, `recovery_attempt_result`
134+ - `review` : remediation lineage and retry adaptation fields matching `improve`
135+
136+ When these fields exist, the loop should validate and audit them. It should not
137+ repeat the same log analysis unless the structured telemetry is absent,
138+ incomplete, or semantically changed.
139+
140+ ---
141+
142+ # # Recovery strategies
143+
144+ Autonomous recovery is bounded and auditable. The platform may attempt :
145+ - Executor restart : restart backend process, restart watcher, reinitialize runtime
146+ - Queue healing : ` Blocked -> Backlog` , `Blocked -> Ready for AI`, stale lock cleanup
147+ - Runtime pressure mitigation : pause backend temporarily, reroute lightweight tasks,
148+ defer expensive remediation
149+ - Cooldown enforcement : wait until `safe_retry_after` before retrying the same lineage
150+
151+ Guardrails :
152+ - Do not widen runtime policy automatically
153+ - Do not increase `kodo` concurrency automatically
154+ - Do not bypass execution gates silently
155+ - Do not replay unsafe retries
156+ - Do not mutate queue state without structured evidence
157+
158+ ---
159+
160+ # # Self-healing state machine
161+
162+ The platform state machine is :
163+
164+ ` ` ` text
165+ HEALTHY
166+ -> DEGRADED
167+ -> RECOVERING
168+ -> HEALTHY
169+
170+ RECOVERING
171+ -> UNSTABLE
172+ -> COOLDOWN
173+ -> RECOVERING
174+
175+ UNSTABLE
176+ -> OPERATOR_BLOCKED
177+ -> PARKED_OPERATOR_BLOCKED
178+ ` ` `
179+
180+ The loop orchestrates and audits transitions. Watchers own the local recovery
181+ attempts and must emit transition events.
182+
183+ ---
184+
185+ # # Queue healing rules
186+
187+ Queue healing is allowed only when structured metadata proves the transition is
188+ safe.
189+
190+ Automatic duplicate-deadlock breaker :
191+
192+ ` ` ` text
193+ IF duplicate exists in Blocked
194+ AND no consumer can execute it
195+ AND retry_safe = true
196+ AND retry budget remains
197+ THEN transition Blocked -> Ready for AI
198+ ` ` `
199+
200+ Stale blocked recovery :
201+
202+ ` ` ` text
203+ IF task is Blocked beyond stale threshold
204+ AND retry_safe = true
205+ AND replay budget remains
206+ THEN transition Blocked -> Backlog
207+ ` ` `
208+
209+ Required queue metadata :
210+ - ` retry_lineage_id`
211+ - ` retry_safe`
212+ - ` backend_dependency`
213+ - ` recovery_attempt_count`
214+ - ` blocked_reason`
215+ - ` duplicate_key`
216+
217+ Required invariants :
218+ - No infinite replay
219+ - No duplicate storms
220+ - No unsafe unblock
221+ - No queue freeze caused by duplicate suppression
222+
223+ ---
224+
225+ # # Recovery budgets
226+
227+ Investigation and recovery are bounded by machine-enforced budgets :
228+
229+ ` ` ` yaml
230+ recovery_budget:
231+ max_cycles_before_escalation: 3
232+ max_equivalent_retries: 2
233+ max_recovery_attempts: 5
234+ ` ` `
235+
236+ After exhaustion, the system must escalate, park when appropriate, and wait for
237+ semantic evidence change. The loop should not perform fresh deep investigation
238+ for an unchanged, budget-exhausted root cause.
239+
240+ ---
241+
242+ # # Evidence fingerprinting
243+
244+ Use canonical evidence hashes to distinguish real change from timestamp churn.
245+
246+ Hash inputs :
247+ - exit code and signal
248+ - normalized stacktrace or failure category
249+ - queue state
250+ - watcher state
251+ - regression IDs
252+ - backend health state
253+
254+ Ignore :
255+ - timestamps
256+ - cycle IDs
257+ - run IDs
258+ - log ordering noise
259+
260+ Parked and stalled decisions should use these hashes. Timestamp-only changes are
261+ not new evidence.
262+
263+ ---
264+
265+ # # Formal parked behavior
266+
267+ ` PARKED_OPERATOR_BLOCKED` is a persisted system state, not just loop prose.
268+
269+ Parked metadata must include :
270+
271+ ` ` ` yaml
272+ parked_state:
273+ root_cause_signature: kodo_sigkill_plan_phase
274+ parked_reason: backend cooldown exhausted without safe retry
275+ unchanged_cycles: 14
276+ last_evidence_hash: abc123
277+ unpark_conditions:
278+ - backend_health_change
279+ - queue_change
280+ - runtime_config_change
281+ - watcher_state_change
282+ - execution_outcome_change
283+ ` ` `
284+
285+ When parked, skip repeated deep investigation. Check only unpark conditions and
286+ semantic evidence hash changes.
287+
288+ ---
289+
290+ # # Recovery telemetry
291+
292+ Recovery events should be emitted as structured records :
293+ - ` recovery_attempt_started`
294+ - ` recovery_attempt_result`
295+ - ` cooldown_applied`
296+ - ` backend_health_transition`
297+ - ` queue_healing_decision`
298+ - ` recovery_budget_exhausted`
299+ - ` parked_state_entered`
300+ - ` parked_state_unparked`
301+
302+ Loop summaries should report metrics derived from these records :
303+ - recovery success rate
304+ - retry adaptation rate
305+ - queue evolution quality
306+ - backend stability state
307+ - unchanged evidence cycles
308+
309+ ---
310+
77311# # Prerequisites
78312
79313Before starting the loop, confirm :
@@ -198,6 +432,10 @@ Collect exit codes and finding counts. Determine affected repos only from tool o
198432
199433STEP 2 — TRIAGE:
200434 .venv/bin/operations-center-triage-scan --config config/operations_center.local.yaml --apply
435+ This scan now includes queue self-healing when tasks carry structured evidence labels:
436+ retry_safe, queue_deadlock/no_consumer, dedup:<key>, retry-lineage:<id>.
437+ It may transition Blocked→Ready-for-AI or Blocked→Backlog only when retry budgets
438+ and safety evidence allow it; otherwise it comments an escalation.
201439
202440STEP 3 — BLOCKED/STALLED WORK INVESTIGATION:
203441Read the last 3 cycle summaries from .console/log.md to identify repeated patterns.
0 commit comments