From pev
PEV Audit — backlog cleanup of graph-staleness drift in dev docs. Sequential feature-shard dispatch with whole-slice plans and pass-staged execute (ghost → backlog). Use when accumulated drift in `docs/features/**`, `docs/adrs/**`, `docs/plans/**`, etc. has grown past what an in-cycle Auditor can address.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pev:pev-audit-dev-docsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You orchestrate a backlog audit of dev-doc graph-staleness drift by dispatching `pev-audit-dev-shard` subagents sequentially across feature subtrees. Each shard produces a whole-slice plan covering two passes (ghost → backlog); execute is dispatched once per pass per shard. All mutation is gated by user approval at the plan-review step.
You orchestrate a backlog audit of dev-doc graph-staleness drift by dispatching pev-audit-dev-shard subagents sequentially across feature subtrees. Each shard produces a whole-slice plan covering two passes (ghost → backlog); execute is dispatched once per pass per shard. All mutation is gated by user approval at the plan-review step.
LINKED_STALE is sticky. It is set when an upstream node has a CONTENT-class history event and only clears via explicit mark_clean on the consumer (which writes node_verification.verified_at). Editing the consumer doesn't verify it; Pass-1 actions don't auto-cascade-clear consumer LS. Every LS / CU / DU node in scope is walked individually in Pass 2.
${CLAUDE_PROJECT_DIR} is the consumer project root. ${CLAUDE_PLUGIN_ROOT} is the PEV plugin's install directory.
Reference docs (read before first use):
axiom_graph::docs.features.pev-agent-nexus.sub_features.audit-skills.designaxiom_graph::docs.features.pev-agent-nexus.sub_features.audit-skills.prdv1 posture (key constraints):
--worktree override (worktree-posture section).docs/pev-requests/{slug}.json doc and surfaces it; it does not edit source.axiom_graph_add_section rejects depth-3 paths. Use parent.child notation only; no parent.child.grandchild. Per-shard slots use a flat shard-{shard-id} parent with plan-{pass} / execute-{pass} children.Parse the user's /pev-audit-dev-docs request. The request may include:
docs/pev/audit-requests/{slug}.json (optional) — narrows scope, sets goal, supplies user-authored constraints.Read axiom-graph.toml in the project root to get the project_id value. The audit manifest doc ID is {project_id}::docs.pev.audits.pev-audit-dev-docs-YYYY-MM-DD-{slug} — do NOT hardcode the prefix; it varies per project.
Slug generation. If the user supplied an audit-request, reuse its slug. Otherwise generate a short descriptive slug from the scope hints (e.g., full-tree, indexer-cleanup, post-rename-sweep). Date-prefix YYYY-MM-DD is added by manifest naming; the slug itself is just the descriptive tail.
Tag-mutex check (inline, no hook). Run:
axiom_graph_list_tags(project_root="${CLAUDE_PROJECT_DIR}")
…and check whether any existing manifest carries the pev-audit-active tag.
If pev-audit-active is present → an interrupted audit run exists. Read that manifest's meta and orchestrator.executions sections to determine resume point. Present to user:
An interrupted dev-docs audit exists: {existing_manifest_id}
Status: {meta.status}
Last completed: {orchestrator.executions.current-pass or "discovery"}
Options:
(1) RESUME — pick up where it left off
(2) RELEASE — remove pev-audit-active tag, mark prior run partial, start a new run
(3) CANCEL — leave it alone and abort this invocation
HUMAN GATE.
If no existing audit → present the cycle plan to the user:
PEV Audit (dev-docs): pev-audit-dev-docs-{date}-{slug}
Manifest doc ID: {project_id}::docs.pev.audits.pev-audit-dev-docs-{date}-{slug}
Audit-request: {linked-request-doc-id-or-none}
Proceed? (or suggest a different slug)
HUMAN GATE.
Once confirmed:
axiom_graph_write_doc. The id field is path-slug form (pev/audits/pev-audit-dev-docs-{date}-{slug}), NOT the full node-id. Tags: pev-audit-active, pev-audit-dev-docs. Initial sections (depth 2 only): meta, request (pointer or copy of audit-request), orchestrator.discovery (placeholder), orchestrator.partition (placeholder), orchestrator.plans-review (placeholder), orchestrator.executions (placeholder), orchestrator.handoff (placeholder; recommended-requests live as a bullet list inside its content), friction (empty).meta content includes: status: active, audit-type: dev-docs, started-at: {ISO timestamp}, dispatcher: pev-audit-dev-docs, request-link: {audit-request-doc-id or null}.Build the drift inventory. Use axiom_graph_drift_query for the per-node
inventory (paginated, filterable) and axiom_graph_check for the
one-line headline counts:
axiom_graph_check(project_root="${CLAUDE_PROJECT_DIR}")
axiom_graph_drift_query(project_root="${CLAUDE_PROJECT_DIR}", filter="all", group_by="location_prefix", format="counts")
axiom_graph_drift_query(project_root="${CLAUDE_PROJECT_DIR}", filter="all", group_by="feature", format="ids")
axiom_graph_list_undocumented(project_root="${CLAUDE_PROJECT_DIR}")
The grouped format="ids" output gives you per-feature ID buckets you
can hand directly to a shard (the shard's allowlist now includes
drift_query so it can also self-enumerate its own slice if you give
it a location_glob).
For each NOT_FOUND node, walk its inbound documents edges via axiom_graph_graph(direction="in") to find which dev-doc sections reference it. For undocumented nodes flagged by list_undocumented, decide whether they fall in scope (audit handles graph drift; pure coverage gaps with no doc reference are typically out-of-scope unless the audit-request specifies otherwise).
Filter to in-scope stale nodes per any scope constraints in the audit-request (e.g., feature inclusion list, severity floor). All BROKEN_LINK nodes are in scope (backlog audit isn't tied to a single change-set).
Write the drift inventory to orchestrator.discovery:
NOT_FOUND, LINKED_STALE, BROKEN_LINK, CONTENT_UPDATED, DESC_UPDATED)scope-excluded, out-of-scope-coverage-gap)For each in-scope stale node, assign exactly one shard. Signals in priority order:
documents edges via axiom_graph_graph(direction="in"). If any incoming section ID matches docs.features.{X}.*, assign to feature X. Tie-breaker: deepest feature path (most specific).axiom_graph/index/** → indexeraxiom_graph/viz/** → vizaxiom_graph/mcp/** → mcp-serveraxiom_graph/scanners/** → indexer (scanning sub-feature)axiom_graph/docjson/** → docjson-extractionaxiom_graph/cli/** → indexer (cli sub-feature)axiom_graph/** → general-shard candidate (re-evaluate via signal 3)models.py, _step_helpers.py → general-shard), or user-authored hints from the audit-request.general-shard. ADRs, plans, devlog, axiom-vision live there permanently (no feature alignment).Record each assignment + rationale in orchestrator.partition. The mapping is shard-id → [node-id, ...] with a per-shard rationale block. Large feature subtrees may be split across multiple shards (e.g., indexer-a, indexer-b) if a single shard's slice would exceed reasonable per-dispatch work — record the split rationale.
If partition produces zero shards (no in-scope drift), present the discovery summary to the user and offer to close the manifest as completed with status note. HUMAN GATE.
For each shard in the partition (in any deterministic order — alphabetical by shard-id is fine), dispatch the pev-audit-dev-shard agent in plan mode. One at a time. Wait for return before dispatching the next.
Before each dispatch, the orchestrator pre-creates the agent's writable manifest sections so the agent only needs update_section (not add_section — see tool-permissions in design). For shard {shard-id} in plan mode, create a flat shard-{shard-id} parent with per-pass children via axiom_graph_add_section:
shard-{shard-id} (parent, depth 1)shard-{shard-id}.plan-ghost (depth 2)shard-{shard-id}.plan-backlog (depth 2)Use subagent_type="pev-audit-dev-shard". Do NOT use isolation: "worktree".
Dispatch prompt template:
You are the pev-audit-dev-shard agent in PLAN mode for shard {shard-id} of audit {audit-manifest-doc-id}.
Project root: ${CLAUDE_PROJECT_DIR}
Audit manifest doc ID: {audit-manifest-doc-id}
Your shard ID: {shard-id}
Your slice: {node-id list — read in detail from orchestrator.partition.{shard-id}}
Mode: plan
Read your slice from the manifest: axiom_graph_read_doc(project_root, "{audit-manifest-doc-id}", section="orchestrator.partition") and locate your shard-id block.
Walk every node in your slice. Produce a whole-slice plan covering two passes:
Pass 1 (ghost): every NOT_FOUND / BROKEN_LINK node — classify and propose action (purge / repoint / delete_link / friction-flag).
Pass 2 (backlog): every LINKED_STALE / CONTENT_UPDATED / DESC_UPDATED node — classify as refactor-noise (mark_clean) or semantic-shift (update_section). LINKED_STALE is sticky; do NOT assume Pass 1 actions will auto-clear any Pass-2 entries. Every LS / CU / DU node in your slice must be walked individually.
Write each pass's plan to shard-{shard-id}.plan-{pass-id} (pass-id ∈ ghost, backlog) via axiom_graph_update_section. The orchestrator has pre-created these placeholder sections; you only need update_section.
Each plan entry should include: node-id, current staleness, proposed action (mark_clean / update_section / delete_link / update_doc_meta / friction-flag), and a one-line rationale. For update_section actions, include the current-vs-proposed diff inline so the user can review at the gate.
If you encounter a node where ghost-resolution reveals missing code wiring (the doc references a function that should still exist but is genuinely missing), do NOT plan a code edit. Add a friction-flag entry with a suggested spawn-request payload: { "slug": "...", "summary": "...", "scope": "..." }.
Return PLAN_DONE with a one-paragraph summary, OR NEEDS_INPUT with proxy questions if you encounter ambiguity that needs user guidance.
Handle returns:
orchestrator.executions (e.g., plan.{shard-id}: done). Move to the next shard.NEEDS_INPUT from across shards into a single AskUserQuestion call (or several if questions exceed the schema limit). Resume each agent with SendMessage containing the answers and the agent's context field. (Same proxy-question protocol as the rest of PEV.)After all shards return PLAN_DONE, read every shard's plan blocks together.
Light cross-shard scan. Partition guarantees no two shards touched the same node — so this is unusual-pattern detection only, not heavy reconciliation:
/pev-cycle instead of audit cleanup.Record findings (or "no unusual patterns") in orchestrator.plans-review.cross-shard-flags.
Present plans to the user. For each shard, render a compact summary:
Shard: {shard-id} ({N} nodes total)
Pass 1 ghost: {ghost-count} actions ({purge: P, delete_link: W, repoint: R, friction: F})
Pass 2 backlog: {backlog-count} actions ({mark_clean: M, update_section: U, update_doc_meta: D, friction: F2})
For non-trivial update_section actions, render the proposed diff inline. For friction-flagged spawn-request candidates, render the suggested slug + summary.
HUMAN GATE — "Approve this plan to proceed to pass-staged execute, or provide feedback to revise (e.g., 'skip shard X', 'don't update_section for node Y, just mark_clean')?"
Record the user's decision in orchestrator.plans-review.user-decision (one of: approved, approved-partial with notes, rejected with notes). For approved-partial and rejected, redispatch only the affected shards in plan mode with the user's feedback appended.
For each pass in order — ghost, backlog — dispatch every shard sequentially in execute mode for that pass. The orchestrator only advances to the next pass after all shards finish the current pass.
Between passes, re-run discovery. After Pass 1 completes:
axiom_graph_check(project_root="${CLAUDE_PROJECT_DIR}")
axiom_graph_drift_query(project_root="${CLAUDE_PROJECT_DIR}", filter="links", format="counts", group_by="status")
This confirms Pass 1's actions landed (NOT_FOUND / BROKEN_LINK counts should drop). It does NOT trim Pass 2: LINKED_STALE is sticky and only clears via per-node mark_clean, so every Pass-2 entry in the original plan remains actionable. The re-run is a sanity check, not a trimming step.
Before each per-pass dispatch, pre-create the agent's execute output section for that pass via axiom_graph_add_section:
shard-{shard-id}.execute-{pass} (one section per shard per pass; the shard-{shard-id} parent already exists from plan-mode dispatch)This keeps the agent's allowlist limited to update_section (matching the design's tool-permissions table for dev-shard).
Per-pass dispatch prompt template:
You are the pev-audit-dev-shard agent in EXECUTE mode for shard {shard-id} of audit {audit-manifest-doc-id}.
Project root: ${CLAUDE_PROJECT_DIR}
Audit manifest doc ID: {audit-manifest-doc-id}
Your shard ID: {shard-id}
Mode: execute
Pass: {ghost | backlog}
Read your assigned pass's plan from shard-{shard-id}.plan-{pass} via axiom_graph_read_doc.
LINKED_STALE is sticky — Pass 1 actions do NOT auto-clear any Pass 2 entries. If you want to confirm an entry is still actionable, call axiom_graph_drift_query(filter="all", location_glob=YOUR_SLICE_GLOB, format="full") to enumerate your slice; skip only entries whose own_status changed (e.g., a node now NOT_FOUND that was CONTENT_UPDATED), not entries you assume "must have cleared by now."
Perform the planned actions one at a time:
- mark_clean → axiom_graph_mark_clean (per-node verification; only path to clear LINKED_STALE)
- update_section → axiom_graph_update_section (use the proposed-content from your plan entry)
- update_doc_meta → axiom_graph_update_doc_meta
- delete_link → axiom_graph_delete_link
- friction-flag → do not act; record verbatim as a "friction-flags" subsection within your execute records
Write per-action records to shard-{shard-id}.execute-{pass} with: node-id, action taken, result (success / skipped-already-clean / failed-{reason}), and timestamp. The orchestrator has pre-created this placeholder section; you only need update_section.
Stay within your shard. Do NOT edit other shards' manifest sections. Do NOT call any code-editing tool (you don't have one anyway).
Return EXECUTE_DONE with a one-paragraph summary, or CONTINUING if you hit your turn limit. Already-marked-clean nodes don't reappear stale, so progress is automatic across re-dispatches.
Handle returns per shard per pass:
{pass}.{shard-id}: done as a bullet within orchestrator.executions content. Continue.NEEDS_INPUT from the same pass. Ask via AskUserQuestion. Resume with SendMessage.Update the current-pass marker for resume. After all shards finish a pass, append a current-pass: {next-pass-or-completed} line within orchestrator.executions content so an interrupted run can pick up at pass boundary on resume.
Walk every shard's friction-flags from execute (and any flagged from plan that the user approved). For each entry, write a real docs/pev-requests/{slug}.json doc:
docs/pev-requests/*.json — append -2, -3, etc. if needed).title — short human-readabletags — ["pev", "request", "audit-spawned"]meta.source-audit — the audit manifest doc ID (provenance)sections — problem, proposed-approach, scope, notes (populated from the friction-flag's payload)axiom_graph_write_doc with id field in path-slug form (pev-requests/{slug}).orchestrator.handoff content in the audit manifest.After all spawn-requests are written, read every shard's execute records and append a per-shard summary block within orchestrator.executions content (under a "Summary" sub-heading):
mark_clean count, update_section count, etc. across all shardsfailed-{reason}Update meta.status to completed (or partial if any shards returned failed actions or the user halted mid-execute). Update meta.completed-at with timestamp. Remove the pev-audit-active tag via axiom_graph_update_doc_meta on the manifest doc.
Run a final axiom_graph_check to confirm post-state and present a one-screen summary to the user:
PEV Audit (dev-docs) — {audit-manifest-doc-id}
Pre-audit drift: NOT_FOUND={X}, LINKED_STALE={Y}, BROKEN_LINK={Z}, ...
Post-audit drift: NOT_FOUND={X'}, LINKED_STALE={Y'}, ...
Resolved: {count} stale events
Spawn-requests created: {N}
- {slug-1} — {summary}
- {slug-2} — {summary}
Friction notes: {count} (see manifest's friction section)
Status: completed | partial
Manifest: {audit-manifest-doc-id}
If spawn-requests were created, end with: "Run /pev-cycle <doc-id> or /pev-instance <doc-id> to address each spawned request."
Capture friction as you work — partition decisions that felt forced, plans that didn't survive review, dispatch-prompt fields the agents misinterpreted, gate prompts that confused the user, hooks/tools that didn't behave as expected, etc. Append to {audit-manifest-doc-id}::friction as you notice it — not as a Phase 7 summary. Read the existing section first so you don't overwrite prior entries, then axiom_graph_update_section with existing + new.
Entry format:
- **{short tag}** — {one line: what felt off}
Context: {raw paste — tool call, output, error, user exchange}
Wish: {optional — what would've made this easier}
Empty is fine. Honest emptiness beats invented friction.
pev-audit-active is present, force the user choice (resume / release / cancel). Do NOT proceed silently.orchestrator.discovery with the empty inventory, present "no drift to audit" to the user, mark manifest completed with note, exit gracefully.axiom_graph_check hangs mid-audit — timeout and retry; if persistent, proceed to the next phase using the last successful inventory and note the gap in friction.meta.status to partial, leave pev-audit-active tag in place so a future re-invocation can resume, and present the manifest doc-id to the user.-2, -3, ...) and proceed; record the resolved slug in the manifest.${CLAUDE_PLUGIN_ROOT}/agents/pev-audit-dev-shard.md exists; suggest /agents to reload. Cannot work around this in-band; surface to user.npx claudepluginhub ddpoe/axiom-graph --plugin pevGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.