diff --git a/skills/agency-health/SKILL.md b/skills/agency-health/SKILL.md new file mode 100644 index 00000000..b710c7e6 --- /dev/null +++ b/skills/agency-health/SKILL.md @@ -0,0 +1,108 @@ +--- +name: agency-health +description: Grade one agency case over a bounded period by folding its projection state and receipt-stub ledger aggregates into a typed health bundle. +runx: + category: ops +--- + +# Agency Health + +`agency-health` is a read-only operator skill for grading one running agency +case over a bounded period. It reads domain-keyed case state through +`data-store read_projection`, reads cross-run aggregate signals through `ledger` +by receipt id-stub only, and returns a typed health bundle plus typed +intervention findings. + +## Purpose + +Use this skill when an operator needs to know whether one agency is healthy +enough to continue without widening caps or authority. It does not append +events, widen authority, route money, or issue follow-up runs. It only grades +the folded case and names the next lane when intervention is warranted. + +## Inputs + +- `data_source_ref`: logical source for the case projection read. +- `store_id`: binding or fixture store used for the projection fold. +- `agency_ref`: the agency stream ref being graded. +- `period` (optional): bounded window with `from` and `to`. +- `case_id` (optional): concrete case id when the agency groups more than one + case. +- `health_baseline` (optional): + - `threshold_days_stuck` + - `cap_pressure_pct` + - `refusal_spike_rate` + +## Output + +`agency_health_report` returns: + +- `decision`: `ready`, `needs_more_evidence`, or `needs_human` +- `agency_ref` +- `case_id` +- `period` +- `health_verdict` + - `status` + - `findings[]` +- `intervention_findings[]` +- `refused_reason` when the case cannot be graded safely + +Each `health_verdict.findings[]` entry ties a folded metric to a named norm. +This skill grades these metrics by name: + +- `seal_rate` +- `stuck_case_count` +- `cap_usage_pct` +- `escalation_backlog` + +Each `intervention_findings[]` entry names a `target_lane` and cites the +grounding `case_id` and turn or ledger id-stub. + +## Lane rules + +- `improve-skill`: dispatch/tooling failure inside the case +- `policy-author`: written baseline or cap thresholds need tightening +- `human-ops`: any critical finding, cap widening, or authority widening path + +This is dispatch-by-naming only. The report grants no access, carries no +ceiling, and is consumed only when a downstream driver or operator issues a +separate governed run. + +## Refusals + +This skill refuses to: + +- grade a signal not grounded in the folded case projection or a ledger + aggregate referenced only by id-stub +- invent a cap or threshold it cannot read from the supplied baseline or case + context +- invent a turn state the folded event order does not support + +If no readable case events exist over the requested period, it returns +`decision: needs_more_evidence`, grades no findings, and emits no intervention. + +## Harness contract + +The package ships two inline harness cases: + +- `concerning-agency-sealed` + - sealed result + - `decision: ready` + - `health_verdict.status: degraded` + - graded findings present + - typed intervention findings present +- `no-case-events-stop` + - sealed result + - `decision: needs_more_evidence` + - no findings graded + - no intervention emitted + +## Operator reading + +Interpretation is intentionally narrow: + +- `decision: ready` means the case is assessable, not healthy +- `status: degraded` means continued work is possible but intervention is + warranted +- `needs_more_evidence` means the folded case and ledger aggregate are too thin + to grade honestly diff --git a/skills/agency-health/X.yaml b/skills/agency-health/X.yaml new file mode 100644 index 00000000..a4e56ab7 --- /dev/null +++ b/skills/agency-health/X.yaml @@ -0,0 +1,200 @@ +skill: agency-health +version: "0.2.0" + +catalog: + kind: skill + audience: operator + visibility: public + role: context + +harness: + cases: + - name: concerning-agency-sealed + inputs: + data_source_ref: local://agency-state + store_id: fixture-agency-health + agency_ref: agency://support/growth + case_id: case-stuck-1 + period: + from: "2026-07-12T00:00:00Z" + to: "2026-07-13T12:00:00Z" + health_baseline: + threshold_days_stuck: 2 + cap_pressure_pct: 85 + refusal_spike_rate: 0.2 + caller: + answers: + agent_task.agency-health.output: + agency_health_report: + decision: ready + agency_ref: agency://support/growth + case_id: case-stuck-1 + period: + from: "2026-07-12T00:00:00Z" + to: "2026-07-13T12:00:00Z" + health_verdict: + status: degraded + findings: + - name: seal_rate + assessment: weak + norm: ">= 0.90 over the requested period" + metric: + value: 0.67 + unit: ratio + grounding: + case_id: case-stuck-1 + turn_numbers: + - 27 + - 28 + - 29 + ledger_id_stubs: + - rcpt_case_stuck_01 + - rcpt_case_stuck_02 + - rcpt_case_stuck_03 + - name: stuck_case_count + assessment: elevated + norm: "<= 1 consecutive stuck turn window" + metric: + value: 3 + unit: turns + grounding: + case_id: case-stuck-1 + turn_numbers: + - 27 + - 28 + - 29 + ledger_id_stubs: + - rcpt_case_stuck_01 + - name: cap_usage_pct + assessment: elevated + norm: "< 85%" + metric: + value: 92 + unit: percent + grounding: + case_id: case-stuck-1 + turn_numbers: + - 29 + ledger_id_stubs: + - rcpt_case_stuck_03 + - name: escalation_backlog + assessment: warning + norm: "0 pending critical escalations" + metric: + value: 1 + unit: items + grounding: + case_id: case-stuck-1 + turn_numbers: + - 29 + ledger_id_stubs: + - rcpt_case_stuck_03 + intervention_findings: + - target_lane: improve-skill + reason: Dispatch is burning turns without advancing the case. + grounding: + case_id: case-stuck-1 + turn_number: 29 + ledger_id_stub: rcpt_case_stuck_03 + - target_lane: policy-author + reason: The baseline thresholds and caps need tightening for this mandate. + grounding: + case_id: case-stuck-1 + turn_number: 29 + ledger_id_stub: rcpt_case_stuck_03 + - target_lane: human-ops + reason: Cap pressure is high enough that any widening or critical remedy must escalate. + grounding: + case_id: case-stuck-1 + turn_number: 29 + ledger_id_stub: rcpt_case_stuck_03 + expect: + status: sealed + receipt: + schema: runx.receipt.v1 + state: sealed + disposition: closed + + - name: no-case-events-stop + inputs: + data_source_ref: local://agency-state + store_id: fixture-agency-health + agency_ref: agency://support/empty + case_id: case-empty-1 + period: + from: "2026-07-12T00:00:00Z" + to: "2026-07-13T12:00:00Z" + health_baseline: + threshold_days_stuck: 2 + cap_pressure_pct: 85 + refusal_spike_rate: 0.2 + caller: + answers: + agent_task.agency-health.output: + agency_health_report: + decision: needs_more_evidence + agency_ref: agency://support/empty + case_id: case-empty-1 + period: + from: "2026-07-12T00:00:00Z" + to: "2026-07-13T12:00:00Z" + health_verdict: + status: needs_more_evidence + findings: [] + intervention_findings: [] + refused_reason: No readable case events or grounded ledger aggregates were available for this agency over the requested period. + expect: + status: sealed + receipt: + schema: runx.receipt.v1 + state: sealed + disposition: closed + + - name: agency-health-needs-agent + inputs: + data_source_ref: local://agency-state + store_id: fixture-agency-health + agency_ref: agency://support/pending + case_id: case-needs-agent-1 + period: + from: "2026-07-12T00:00:00Z" + to: "2026-07-13T12:00:00Z" + expect: + status: needs_agent + +runners: + analyze: + default: true + type: agent-task + agent: analyst + task: agency-health + outputs: + agency_health_report: object + artifacts: + wrap_as: agency_health_report_packet + packet: runx.agency_health_report.v1 + inputs: + data_source_ref: + type: string + required: true + description: Stable logical ref for the domain-keyed state source. + store_id: + type: string + required: true + description: Store binding used for the folded projection read. + agency_ref: + type: string + required: true + description: Agency stream ref to fold across the requested period. + period: + type: json + required: false + description: Optional bounded time window with from/to timestamps. + case_id: + type: string + required: false + description: Optional concrete case id when the agency groups more than one case. + health_baseline: + type: json + required: false + description: Optional baseline thresholds for stuck days, cap pressure, and refusal spike rate.