← Files incident.ioARCHIVED FILE
skills/doctor/references/extensions.md
7.83 KB · Oct 7, 2026 · 18:03 UTC
# The extensions leg
Plugins and their skills, checked end to end. Needs the incident.io connection's
extension tools (`extension_plugin_list`, `extension_skill_feedback_list`); without
them, this leg reduces to asking the user to read the dashboard's Extensions page and
the per-plugin feedback panels, and recording what they report.
Work per plugin, in this order — each check feeds the next.
## 1. Sync state
`extension_plugin_list`: check sync first, because nothing downstream of a broken
sync is current — the report still orders findings most-actionable first, wherever a
sync problem ends up ranking. A `last_synced_at` far in the past on
a plugin whose repository changes often is worth a line too: agents may be following
stale instructions. Route: the error text usually says whether it's the repository
(fix there), the tree (a skill-authoring brief), or access (a dashboard page).
Match a local tree to an account plugin by repository source, branch, and skill set,
not by display name alone. If they differ, treat them as separate versions. Account
feedback describes the mounted version; do not use it to create a brief against the
local tree unless its exact file and quote verify there.
## 2. Are the skills earning their loads?
`extension_skill_feedback_list(plugin: "…")` per plugin — but read `usage_count`
against `assessed_count` before you read the funnel at all. Three corrections first:
- **The funnel only counts loads that have been assessed.** A skill loaded but not yet
assessed reads `{followed: 0, not_used: 0, partial: 0}`, which is what a skill nobody
ever loaded reads too. Compare `usage_count` to tell them apart. Assessment waits on
the run's scorecard, and a production scorecard waits on the incident closing, so a
young skill's funnel is usually just behind.
- **These numbers cover two surfaces: investigations and chat.** A skill the team runs
in a coding agent on their own machines records nothing here. Its zero tells you
incident.io's agents never loaded it, and nothing more. Check what a skill is for
before calling it unused.
- **Count the chances before you call a count low.** Take the moments the skill could
have served in the same window, and compare it against a skill of a similar age.
Five loads is damning beside fifty opportunities and unremarkable beside six.
Then the funnel:
- **In step 1's skill list but absent from the feedback** — never loaded. Either the
description never matches real requests (a skill-authoring brief: rewrite the
trigger) or the skill serves a moment that has not yet occurred; say which is
more likely from its description, and don't manufacture urgency about a young
skill.
- **Loaded but never assessed** (`usage_count` above zero, `assessed_count` zero) — the
skill hasn't been graded yet. Report it that way, instead of reporting the empty
funnel as a result. Where it persists across reviews, the loads are probably
unassessable — a run with no check, or one whose traces have aged out. Report that
too: a skill nobody can grade never builds up the feedback an improvement needs.
- **Loaded much, followed little** (high `not_used`) — the description over-promises.
Brief: tighten the description to what the body delivers.
- **Followed but not helping** (`hurt` or persistent `neutral` contributions) — the
instructions take runs the wrong way; the highest-severity skill finding there is.
Brief with the examples the feedback carries.
- **Healthy funnels get a healthy line.** Name the skills that are working; the
report reads as a review, not a complaint. A healthy funnel on a plugin whose sync
is failing gets its credit with the caveat: the feedback describes the mounted
version, not what's in the repository now.
## 3. The issues worth acting on
Issues arrive most-actionable-first, but doctor's job is triage, not transcription:
- First, check the plugin's repository for prior reports. No directory holds them: the
skills that write one offer a dated file anywhere in the repository, or the pull
request description. So search for the headings they use — `# Estate review`
(doctor) and `# Estate report` (extensions) — and read the
pull requests where the session can. They record what earlier runs proposed and what
the team declined, and a declined issue is reported differently below. Where the
record is kept is [report.md](report.md)'s cadence section.
- **An empty search is not evidence that nothing was declined.** Report that no prior
record was found, and report separately that pull requests were unreadable, where
they were. Neither supports the "previously declined" label.
- Verify each issue's anchor (`target_file`, `target_quote`) against the plugin's
current tree before reporting it — apply the "Read the feedback with these
corrections" section of the `skill-authoring` skill's improve reference, including its
distrust of `likely_resolved` (the rest of that file is edit-mode material; doctor
stops at the brief). An issue that verifies becomes one line in a brief; an issue
that doesn't is noted as probably stale, not escalated. If either anchor is absent,
report that the issue could not be verified; do not infer an anchor from similar
local text.
- Cluster by skill: one brief per skill carrying its verified issues — each with its
`issue_key`, which the improve job uses to anchor its pre-ship verification to the
recorded problem — and the strengths that must survive the fix, ready to hand to
skill-authoring's improve job.
- An issue the team has already declined (a dismissal recorded over
`extension_skill_feedback_update`, or a won't-fix note in the plugin's repository
or pull requests) is reported once as "previously declined — still recurring", not
re-escalated every run. Dismissed issues leave the feedback by default, so make one
pass per review with `include_dismissed` — without it, a recurrence of a declined
issue is indistinguishable from a new one, and the report can't honestly use the
"previously declined" label at all.
## 4. Feedback orphaned by renames
A skill whose feedback says it isn't in the current version was renamed or removed —
which one is usually undecidable from the data, so ask the user rather than guessing.
Removed and meant to be: fine, one line. Renamed: its history no longer informs the
new directory — worth a line so the team knows the rename reset the skill's track
record, and a caution against repeating it casually.
## 5. Convention drift
Spot-check each plugin's tree against the `skill-authoring` skill's format reference —
this is a sample for
the report, not a full audit:
- Every skill directory registered in the plugin README's skills table; connections
the skills call present in its connections table. Where the repository itself says a
directory is left out on purpose, that is not a finding — check before reporting one.
- No client-prefixed tool names or single-environment invocation syntax in skill
bodies — these break the skill in environments the feedback may not cover.
- References that nothing links to.
- Skills with no provenance stamp (`metadata.incident-io-plugin-version` in the
frontmatter), or stamped with a version well behind this plugin's own. Plugin list
entries report each skill's `authoring_plugin_version`, so this needs no tree read.
An unstamped skill was written by hand or by another tool; a stale stamp means the
authoring guidance has moved on since it was last touched. Neither is a defect on
its own — route it as a brief for the improve job, which refreshes the stamp as it
goes, and rank it below anything the feedback says is actually going wrong.
Drift becomes part of the per-skill brief where one exists, or a small standalone
brief where the skill is otherwise healthy.
## What this leg does not do
Edit, re-sync, or dismiss. Where a fix is obvious, the brief says exactly what to
change — and stops there.
SHA-256: 3d445d99dcc3a598de0746b7b50cdca5adf56afdae180ed5d312d3be8d9dc83b