Audit para-obsidian plugin for convention drift across skills, commands, hooks, and plugin registration.
From para-obsidiannpx claudepluginhub nathanvale/side-quest-marketplace-old --plugin para-obsidianThis skill is limited to using the following tools:
references/conventions.mdExecutes pre-written implementation plans: critically reviews, follows bite-sized steps exactly, runs verifications, tracks progress with checkpoints, uses git worktrees, stops on blockers.
Guides idea refinement into designs: explores context, asks questions one-by-one, proposes approaches, presents sections for approval, writes/review specs before coding.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Audit the para-obsidian plugin for convention drift. Scans 8 domains: plugin registration, frontmatter schema, completion signals, allowed-tools accuracy, cross-references, brain routing coverage, references directory integrity, and observability gaps.
Not user-invocable — brain routes to it via keywords like "maintenance", "audit", "lint", "health check", "check conventions", "plugin health".
Read the conventions knowledge base:
Read({ file_path: "<plugin-root>/skills/maintenance/references/conventions.md" })
Use these rules as the source of truth for all checks. The plugin root is plugins/para-obsidian relative to the repo root.
Check that every component on disk has a matching entry in .claude-plugin/plugin.json.
1.1 — Discover components on disk:
Glob({ pattern: "plugins/para-obsidian/skills/*/SKILL.md" })
Glob({ pattern: "plugins/para-obsidian/commands/*.md" })
Glob({ pattern: "plugins/para-obsidian/agents/*.md" })
1.2 — Read plugin.json:
Read({ file_path: "<plugin-root>/.claude-plugin/plugin.json" })
1.3 — Compare:
For each component on disk, verify it has a matching entry in the appropriate plugin.json array (skills, commands, agents). Report:
For each skills/*/SKILL.md, parse the YAML frontmatter and check required fields.
Required fields: name, description, user-invocable, allowed-tools
Additional checks:
name must match the directory nameargument-hint (warning if missing)Report:
argument-hintFor each user-invocable skill, check if the SKILL.md body contains a SKILL_RESULT pattern.
Grep({ pattern: "SKILL_RESULT", path: "plugins/para-obsidian/skills/*/SKILL.md" })
Cross-reference with frontmatter user-invocable: true from Step 2.
Report:
SKILL_RESULT completion signalFor each skill, compare tools referenced in the SKILL.md body against the allowed-tools frontmatter declaration.
Detection patterns:
para_create(, para_list(, para_fm_get(, etc.mcp__plugin_para-obsidian_para-obsidian__<tool>Read(, Write(, Edit(, Glob(, Grep(, Bash(, WebFetch(, WebSearch(AskUserQuestion(, Skill(, Task(Exclusions:
<!-- ... -->)Report:
allowed-toolsallowed-tools but not referenced in bodyScan all SKILL.md files for references to other skills, commands, or files, and verify they resolve.
Reference patterns to detect:
Skill({ skill: "para-obsidian:<name>" → check skills/<name>/SKILL.md exists/para-obsidian:<name> → check skills/<name>/SKILL.md or commands/<name>.md exists[text](references/<file>) → check file exists relative to skill directoryReport:
Read the brain skill's routing table and verify coverage.
Read({ file_path: "<plugin-root>/skills/brain/SKILL.md" })
Checks:
Report:
For each skill with a references/ subdirectory, verify files are actually referenced.
Glob({ pattern: "plugins/para-obsidian/skills/*/references/*" })
For each file found, check if the parent SKILL.md contains a reference to it (filename match in link text or path).
Report:
references/ not referenced from SKILL.md (possible dead content)references/ that doesn't existCheck that skills routed through brain have telemetry coverage.
8.1 — Verify brain-telemetry hook exists:
Read({ file_path: "<plugin-root>/hooks/hooks.json" })
Confirm a PostToolUse hook on Skill matcher exists and points to brain-telemetry.ts.
8.2 — Check SKILL_RESULT coverage:
Cross-reference skills in the brain routing table (Step 6) with completion signal coverage (Step 3). Skills in the routing table without SKILL_RESULT have an observability gap.
Report:
SKILL_RESULT (telemetry will show undefined status)After all 8 domains are audited, produce a summary:
SKILL_RESULT:{"status":"<status>","skill":"maintenance","summary":"<N> domains audited, <M> issues found","issues":[<issue-list>]}
Status logic:
ok — Zero errors, zero warningspartial — Zero errors, one or more warningserror — One or more errorsIssue format: Each issue in the array:
{
"domain": "<1-8 domain name>",
"severity": "error|warning|info",
"file": "<relative path>",
"message": "<what's wrong>",
"fix": "<suggested remediation>"
}
Present the results to Nathan as a readable summary, not raw JSON. Group by domain, show severity with clear markers (e.g., [ERROR], [WARN], [INFO]). End with the SKILL_RESULT line for brain parsing.
plugins/para-obsidian/).references/conventions.md first.