---
name: missing-agent-detect
description: Engine substrate for the heartbeat-driven detector that finds skills that no specialist agent currently owns, and proposes a draft owner for user approval.
title: Missing Agent Detector
category: _meta
status: active
author: agentic
metadata:
  priority: 4
---
## Purpose

Closes one of the three Rule 21 gaps named in CLAUDE.md but unaddressed
before this skill: a skill exists in `system/skills/` but no agent
declares it in their `skills:` list. Such a skill never injects into
any subagent's prompt — its instructions, examples, and `allowed-tools`
contract simply never reach a model. The skill reads as "configured"
on disk while being structurally orphaned at runtime.

This detector closes that gap: it walks every loaded skill, checks
whether at least one agent has it in their `skills:` field, and
proposes either (a) attaching the orphan to an existing specialist or
(b) creating a new specialist if no existing agent fits the skill's
domain.

The "main" agent is intentionally NOT counted as an owner — main has
broad fallback access and isn't a specialist. A skill can technically
fire from main but it skips the orchestrator's tool-scoping pass and
loses the tool-grant filtering that makes specialists trustworthy.

**Why this is a Rule 21 capability and not just a lint check**: the
proposal is the user-facing artifact. Lint output gets ignored; a
`/proposals` inbox entry is reviewed.

## When this fires

Heartbeat-driven, daily by default. Pure deterministic scan — no LLM,
no log analysis, just set arithmetic over loaded skills + agent
definitions.

For each orphaned skill, the proposal carries:

* the **skill name + category + priority** so the user sees the
  importance
* a **suggested owner agent** (the existing specialist whose skill
  set is closest to this skill's category, or `null` if none fits)
* the suggestion is a hint, not a commitment — the user picks the
  real owner via the approval flow
* an **idempotent stable id** keyed on the skill name

## What it doesn't do

* **Never modifies an agent definition itself.** Approval writes a
  draft suggestion record; the user (via UI) edits the agent file.
* **Never proposes when the skill has `category: _meta`** (engine
  substrates are deliberately not assigned to any agent — they're
  read by the engine, not injected into prompts).
* **Never proposes when the skill is in `pending/` or `archived/`**
  (those are deliberately excluded from active dispatch).
* **Never proposes a fake agent name.** When no existing specialist
  fits, the proposal carries `suggested_owner: null` and the user
  decides to create a new agent definition file.

## Output format

For each orphaned skill, the detector writes one proposal to:

```
<vault>/agntspace/memory/pending/agent-proposals/cap-<sha8>.json
```

The proposal carries:

* `kind: "agent"`
* `target`: the skill name (the orphan)
* `title`: "Skill orphan: <name>"
* `description`: short one-paragraph rationale
* `rationale`: longer explanation surfacing the skill's category +
  priority + suggested owner OR "no fit found, consider new
  specialist"
* `examples`: existing agent slugs whose skill sets are closest
* `payload`:
  - `orphan_skill`: the skill name
  - `category`: skill category
  - `priority`: skill priority
  - `suggested_owner_agent`: agent slug OR null
  - `existing_owners`: list of agents that currently HAVE the skill
    (should always be empty — we wouldn't fire otherwise)

## Tuning knobs (`config/detect.yaml`)

* `enabled` (bool, default true) — gate the whole detector
* `count_main_as_owner` (bool, default false) — set true if you want
  main's skill list to count as ownership
* `excluded_categories` (list, default `["_meta"]`) — categories that
  never need an agent owner
* `excluded_statuses` (list, default `["pending", "archived",
  "draft"]`) — skill statuses to skip
* `skip_if_pending` (bool, default true) — dedup vs in-flight
  proposals
* `cadence_hours` (int, default 24) — heartbeat interval

Edit YAML, restart server, no code change. (Rule 12.)

## Approval semantics

Approval writes a stub agent suggestion record into the action plan
(or a `pending-agent-assignment` marker), marking the orphan as
acknowledged. The actual edit — adding the skill to the agent's
`skills:` list — is a manual edit. Approving here records the user's
intent so the next heartbeat scan doesn't re-propose it.

Rejection is silent — removes the pending file, emits a
`user_override` activity event. The orphan stays an orphan until
explicitly assigned.