100%

Terminal-exhaustion three-cause classifier

Goal

Add the discriminator the system lacks today: a three-cause terminal-exhaustion classifier. gap_test is purely structural (no metric reachability); this section adds the reachability + corpus-stability + remaining-work-disposition signals that separate decomposition_exhausted (do more work) from mis_fit (re-scope) and dependency_blocked (wait/relocate).

Implementation sketch

New module scripts/plan_orchestrator/terminal_exhaustion.py (script-first §4). classify_terminal_exhaustion(plan_dir) consumes ledger_evolution_runtime.state.{assemble_corpus,corpus_digest,read_no_op_record} + mission_reground.gap_test (untouched) + the remaining work_item dispositions. Verdict enum + evidence dict. Exception-safe: errors -> mis_fit (conservative existing route).

Spec references

scripts/plan_orchestrator/mission_reground.py:gap_test (structural-only, untouched); scripts/ledger_evolution_runtime/state.py:{assemble_corpus,corpus_digest,read_no_op_record}; learning-ledger.md §13 (anchor-liveness signals); script-first.md §4 (runtime layout).

Work Items

  • Define the terminal-exhaustion verdict enum {mis_fit, decomposition_exhausted, dependency_blocked} + an evidence dict (the gate_metric reachability reading, the corpus_digest-stability flag, the gap_test structural verdict, the remaining-work disposition tally) in a new scripts/plan_orchestrator/terminal_exhaustion.py module (script-first: logic in the runtime, never skill prose).

  • Implement classify_terminal_exhaustion(plan_dir) -> dict ALONGSIDE mission_reground.gap_test (gap_test is structural-only and stays untouched). Reachability = residual movement toward gate_metric.direction across recent ledger cycles AND no whole-class wall; corpus stability via ledger_evolution_runtime.state.read_no_op_record == corpus_digest(assemble_corpus(plan_dir)).

  • Implement the dependency-blocked discriminator: remaining work_items classified INERT/BLOCKED against another domain (the aims-burden #275 shape) resolve to dependency_blocked, NOT decomposition_exhausted. Exception-safe: any IO/parse error returns mis_fit (the conservative existing route), never raises into serve emission.

  • Author pytest matrix in scripts/plan_orchestrator/tests/ covering all three verdicts on fixtures (reachable+stable -> decomposition_exhausted; unreachable -> mis_fit; INERT-remaining -> dependency_blocked) + the error-path fallback. Tests precede the implementation per TDD.

Fresh intel (regenerated)

{ “schema_version”: 1, “target”: { “kind”: “plan-section”, “ref”: “grind-exhaustion-forward-escalation/s-06c459a0” }, “generated_at”: “2026-06-19T16:39:27.235079+00:00”, “graph_state”: { “head_sha”: “a1b25f7a”, “last_code_import_at”: “2026-06-19T16:39:12.852Z”, “embedding_stale”: false, “insights_stale”: false, “cpg_stale”: false }, “surfaces”: {}, “summary”: “intel-package[plan-section:grind-exhaustion-forward-escalation/s-06c459a0] agent-authored dossier”, “degraded”: false, “dossier”: { “objective_symbols”: [], “tiers”: {}, “agent_authored”: true, “difficulty”: { “class”: “routine”, “research_online”: false, “research_mode”: “auto”, “signals”: [], “plan_dir”: “/home/eric/projects/ori_lang/plans/grind-exhaustion-forward-escalation” } } }

(full dossier: terminal-exhaustion-classifier—s-06c459a0.intel.json)