# `Planck.Agent.SkillUsage`
[🔗](https://github.com/alexdesousa/planck/blob/v0.2.2/lib/planck/agent/skill_usage.ex#L1)

Per-project SQLite database tracking skill usage per agent type.

The DB lives at `.planck/skills.db` inside the project directory. It is
created on first use; callers pass the path explicitly so the module stays
stateless and testable.

The PK is `(team_name, agent_name, skill_name)`. `agent_type` is stored as a
plain column and is used only for the dynamic-orchestrator union query.

- `team_name` — team directory alias, e.g. `"my-team"`
- `agent_name` — `spec.name || spec.type`, e.g. `"Builder"`, `"orchestrator"`
- `agent_type` — `spec.type`, e.g. `"orchestrator"`, `"builder"`

Fixed agents are queried by `(team_name, agent_name)`. Dynamic orchestrators
(spawned via `spawn_agent`, no history of their own) are seeded by querying
`agent_type = 'orchestrator'` across the team.

## Schema

    CREATE TABLE skill_usage (
      team_name  TEXT NOT NULL,
      agent_name TEXT NOT NULL,
      agent_type TEXT NOT NULL,
      skill_name TEXT NOT NULL,
      use_count  INTEGER NOT NULL DEFAULT 0,
      last_used  TEXT,
      PRIMARY KEY (team_name, agent_name, skill_name)
    );

# `ranked_names`

```elixir
@spec ranked_names(
  Path.t(),
  String.t(),
  String.t(),
  [Planck.Agent.Skill.t()],
  pos_integer()
) :: [
  String.t()
]
```

Return the ranked skill names for an agent, with a cold-start fallback.

Queries the SQLite DB for the top `n` most recently used skills for
`(team_name, agent_name)`. When no history exists (first session), falls back
to the `n` most recently modified skill files — ensuring the index is always
populated even before any skills have been loaded.

# `record_use`

```elixir
@spec record_use(Path.t(), String.t(), String.t(), String.t(), String.t()) :: :ok
```

Record one use of `skill_name` by `(team_name, agent_name, agent_type)`.

Creates the DB and table if they do not exist. Increments `use_count` and
updates `last_used` to the current UTC timestamp. No-ops silently on error.

# `top_n`

```elixir
@spec top_n(Path.t(), String.t(), String.t(), pos_integer()) :: [String.t()]
```

Return the top `n` skill names for `(team_name, agent_name)`, ordered by
recency then count.

Returns an empty list when the DB does not exist or the agent has no history.

# `top_n_for_orchestrators`

```elixir
@spec top_n_for_orchestrators(Path.t(), String.t(), pos_integer()) :: [String.t()]
```

Return the top `n` skill names across all orchestrators in a given team.

Used to seed the skill ranking for dynamic orchestrators (spawned via
`spawn_agent`), which have no usage history of their own. Queries by
`agent_type = 'orchestrator'` so all fixed orchestrators in the team
contribute. Deduplicates and orders by recency then count.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
