{"slug":"skf-audit-skill","title":"skf-audit-skill","summary":"Drift detection between skill and current source code. Use when the user requests to \"audit a skill\" or \"audit skill\" for drift.","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-24T15:42:41.75236Z","repo":{"url":"https://github.com/armelhbobdad/bmad-module-skill-forge","stars":95,"forks":8,"license":null,"updatedAt":"2026-09-22T20:28:59Z"},"bodyHtml":"<hr>\n<h2>name: skf-audit-skill\ndescription: Drift detection between skill and current source code. Use when the user requests to \"audit a skill\" or \"audit skill\" for drift.</h2>\n<h1>Audit Skill</h1>\n<h2>Overview</h2>\n<p>Detects drift between an existing skill and its current source code, producing a severity-graded drift report with AST-backed findings and actionable remediation suggestions. Analysis depth adapts based on detected forge tier (Quick/Forge/Forge+/Deep) with graceful degradation. Stack skills are supported: code-mode stacks are audited per-library against their sources; compose-mode stacks check constituent freshness via metadata hash comparison.</p>\n<h2>Conventions</h2>\n<ul>\n<li>Bare paths (e.g. <code>references/&lt;name&gt;.md</code>) resolve from the skill root.</li>\n<li><strong>Module-level path exception:</strong> bare paths beginning with <code>knowledge/</code> or <code>shared/</code> resolve from the SKF module root (<code>{project-root}/_bmad/skf/</code> installed, <code>src/</code> in dev), not the skill root — stage files reference <code>knowledge/version-paths.md</code> and <code>knowledge/tool-resolution.md</code>, and the terminal step chains to <code>shared/health-check.md</code>.</li>\n<li><code>references/</code> holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter <code>nextStepFile</code>, plus static reference docs); <code>scripts/</code> and <code>assets/</code> hold deterministic helpers and templates.</li>\n<li><code>{skill-root}</code> resolves to this skill's installed directory (where <code>customize.toml</code> lives, if present).</li>\n<li><code>{project-root}</code>-prefixed paths resolve from the project working directory.</li>\n<li><code>{skill-name}</code> resolves to the skill directory's basename.</li>\n</ul>\n<h2>Role</h2>\n<p>You are a skill auditor in Ferris Audit mode: a deterministic drift-detection workflow where the source code is the ground truth and every finding traces back to it.</p>\n<h2>Workflow Rules</h2>\n<p>These rules apply to every step in this workflow:</p>\n<ul>\n<li>Never fabricate findings — all data must trace to source code with file:line citations</li>\n<li>Only load one step file at a time — never preload future steps</li>\n<li>Update <code>stepsCompleted</code> in output file frontmatter before loading next step</li>\n<li>Always communicate in <code>{communication_language}</code></li>\n<li>If <code>{headless_mode}</code> is true, auto-proceed through confirmation gates with their default action and log each auto-decision</li>\n</ul>\n<h2>Stages</h2>\n<table>\n<thead>\n<tr>\n<th>#</th>\n<th>Step</th>\n<th>File</th>\n<th>Auto-proceed</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>Initialize &amp; Baseline</td>\n<td>references/init.md</td>\n<td>No (confirm)</td>\n</tr>\n<tr>\n<td>2</td>\n<td>Re-Index Source</td>\n<td>references/re-index.md</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>3</td>\n<td>Structural Diff</td>\n<td>references/structural-diff.md</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>4</td>\n<td>Semantic Diff</td>\n<td>references/semantic-diff.md</td>\n<td>Yes (skip at non-Deep)</td>\n</tr>\n<tr>\n<td>5</td>\n<td>Severity Classification</td>\n<td>references/severity-classify.md</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>5a</td>\n<td>Doc Drift</td>\n<td>references/step-doc-drift.md</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>6</td>\n<td>Report</td>\n<td>references/report.md</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>7</td>\n<td>Workflow Health Check</td>\n<td>references/health-check.md</td>\n<td>Yes</td>\n</tr>\n</tbody>\n</table>\n<h2>Invocation Contract</h2>\n<table>\n<thead>\n<tr>\n<th>Aspect</th>\n<th>Detail</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Inputs</strong></td>\n<td><code>skill_name</code> [required], <code>skill_path</code> [optional override — full path to skill directory; bypasses manifest/symlink resolution], <code>tier_override</code> [optional: Quick / Forge / Forge+ / Deep — overrides detected tier], <code>degraded</code> [optional bool — pre-confirm degraded-mode opt-in when no provenance map exists], <code>upstream_drift_choice</code> [optional: C / S / X — pre-supplied answer for the upstream-drift gate at init.md §5b], <code>dirty_worktree_choice</code> [optional: T / A / F — pre-supplied answer for the dirty-worktree sub-gate at init.md §5b], <code>force</code> [optional bool — when paired with <code>dirty_worktree_choice=F</code> or used for any future destructive-action gate, signals consent to skip the confirmation]</td>\n</tr>\n<tr>\n<td><strong>Gates</strong></td>\n<td>step 1: Manifest-vs-Symlink Gate [N] · Upstream-Drift Gate [C/S/X] · Dirty-Worktree Sub-Gate [T/A/F] · Degraded-Mode Gate [D/X] · Baseline Confirm Gate [C]</td>\n</tr>\n<tr>\n<td><strong>Outputs</strong></td>\n<td><code>drift-report-{timestamp}.md</code> at <code>{forge_version}/</code> with <code>drift_score</code> and <code>nextWorkflow</code> frontmatter; per-run result contract at <code>{forge_version}/audit-skill-result-{timestamp}.json</code> plus <code>-latest.json</code> copy; final <code>SKF_AUDIT_RESULT_JSON</code> line on stdout when <code>{headless_mode}</code> is true</td>\n</tr>\n<tr>\n<td><strong>Headless</strong></td>\n<td>All gates auto-resolve with default action when <code>{headless_mode}</code> is true; pre-supplied inputs (<code>upstream_drift_choice</code>, <code>dirty_worktree_choice</code>, <code>degraded</code>, <code>tier_override</code>) consumed at the gates that would otherwise prompt</td>\n</tr>\n<tr>\n<td><strong>Exit codes</strong></td>\n<td>See \"Exit Codes\" below</td>\n</tr>\n</tbody>\n</table>\n<h2>Exit Codes</h2>\n<p>Every hard halt in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:</p>\n<table>\n<thead>\n<tr>\n<th>Code</th>\n<th>Meaning</th>\n<th>Raised by</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>success</td>\n<td>step 7 (terminal health-check)</td>\n</tr>\n<tr>\n<td>2</td>\n<td>input-missing</td>\n<td>step 1 §1 — no <code>skill_name</code> supplied in headless mode (interactive prompt cannot resolve)</td>\n</tr>\n<tr>\n<td>3</td>\n<td>resolution-failure</td>\n<td>step 1 §1 (skill not found at resolved path: missing <code>SKILL.md</code>); step 1 §2 (<code>forge-tier.yaml</code> missing — setup-forge not run); step 1 §5 (source directory from provenance map no longer exists / inaccessible)</td>\n</tr>\n<tr>\n<td>4</td>\n<td>write-failure</td>\n<td>step 1 §6 / step 6 §3 (drift report write failed: read-only mount, disk full, permissions denied)</td>\n</tr>\n<tr>\n<td>6</td>\n<td>user-cancelled</td>\n<td>step 1 §1 manifest-vs-symlink gate <code>[X]</code> · step 1 §4 degraded-mode gate <code>[X]</code> · step 1 §5b upstream-drift gate <code>[X]</code> · step 1 §5b dirty-worktree sub-gate <code>[A]</code> (and <code>[A]</code> headless default)</td>\n</tr>\n</tbody>\n</table>\n<h2>Result Contract (Headless)</h2>\n<p>When <code>{headless_mode}</code> is true, step 6 emits a single-line JSON envelope on <strong>stdout</strong> before chaining to step 7, and every hard halt emits the same envelope shape on <strong>stderr</strong> with <code>status: \"error\"</code>:</p>\n<pre><code>SKF_AUDIT_RESULT_JSON: {\"status\":\"success|error\",\"skill_name\":\"…\",\"drift_score\":\"CLEAN|MINOR|SIGNIFICANT|CRITICAL|null\",\"report_path\":\"…|null\",\"next_workflow\":\"update-skill|null\",\"audit_ref\":\"…|null\",\"exit_code\":0,\"halt_reason\":null}\n</code></pre>\n<p><code>status</code> is <code>\"success\"</code> on the terminal happy path, <code>\"error\"</code> on any halt. <code>drift_score</code> is <code>null</code> when the workflow halted before severity classification ran. <code>next_workflow</code> is <code>\"update-skill\"</code> when CRITICAL or HIGH findings exist, otherwise <code>null</code>. <code>halt_reason</code> is one of: <code>null</code> (success), <code>\"input-missing\"</code>, <code>\"skill-not-found\"</code>, <code>\"forge-tier-missing\"</code>, <code>\"source-dir-missing\"</code>, <code>\"write-failed\"</code>, <code>\"user-cancelled\"</code>. <code>exit_code</code> matches the table above.</p>\n<h2>On Activation</h2>\n<ol>\n<li><p>Load config from <code>{project-root}/_bmad/skf/config.yaml</code> and resolve:</p>\n<ul>\n<li><code>project_name</code>, <code>output_folder</code>, <code>user_name</code>, <code>communication_language</code>, <code>document_output_language</code></li>\n<li><code>skills_output_folder</code>, <code>forge_data_folder</code>, <code>sidecar_path</code></li>\n<li>Generate and store <code>timestamp</code> as <code>YYYYMMDD-HHmmss</code> format. This value is fixed for the entire workflow run.</li>\n</ul>\n</li>\n<li><p><strong>Resolve <code>{headless_mode}</code></strong>: true if <code>--headless</code> or <code>-H</code> was passed as an argument, or if <code>headless_mode: true</code> in preferences.yaml. Default: false.</p>\n</li>\n<li><p><strong>Resolve workflow customization.</strong> Run:</p>\n<pre><code>python3 {project-root}/_bmad/scripts/resolve_customization.py \\\n    --skill {skill-root} --key workflow\n</code></pre>\n<p>The script merges the three customization layers per <code>bmad-customize</code>'s structural merge rules (scalars override, arrays append):</p>\n<ul>\n<li><code>{skill-root}/customize.toml</code> — bundled defaults</li>\n<li><code>_bmad/custom/&lt;skill-name&gt;.toml</code> under <code>{project-root}</code> — team overrides (committed)</li>\n<li><code>_bmad/custom/&lt;skill-name&gt;.user.toml</code> under <code>{project-root}</code> — personal overrides (gitignored)</li>\n</ul>\n<p>If the script fails or is missing, fall back to reading <code>{skill-root}/customize.toml</code> directly — the bundled defaults are an empty string for each path scalar.</p>\n<p>Apply the path-scalar fallback now so stage files don't have to repeat the conditional logic. For each of the scalars, if the merged value is empty or absent, use the bundled default:</p>\n<ul>\n<li><code>{driftReportTemplatePath}</code> ← <code>workflow.drift_report_template_path</code> if non-empty, else <code>assets/drift-report-template.md</code></li>\n<li><code>{severityRulesPath}</code> ← <code>workflow.severity_rules_path</code> if non-empty, else <code>references/severity-rules.md</code></li>\n<li><code>{onCompleteCommand}</code> ← <code>workflow.on_complete</code> if non-empty, else empty (no-op — report.md skips the hook invocation entirely)</li>\n</ul>\n<p>Stash all three as workflow-context variables. Stage files reference <code>{driftReportTemplatePath}</code> / <code>{severityRulesPath}</code> / <code>{onCompleteCommand}</code> directly.</p>\n<p>Also apply the array surfaces (not silent no-ops): run <code>workflow.activation_steps_prepend</code> now, treat <code>workflow.persistent_facts</code> as standing context for the run (<code>file:</code>-prefixed entries load their file/glob contents as facts — the bundled default globs any <code>project-context.md</code>), then run <code>workflow.activation_steps_append</code> after activation.</p>\n</li>\n<li><p>Load, read the full file, and then execute <code>references/init.md</code> to begin the workflow.</p>\n</li>\n</ol>\n","files":[{"path":"assets/drift-report-template.md","sizeBytes":981,"isText":true},{"path":"customize.toml","sizeBytes":1931,"isText":true},{"path":"references/health-check.md","sizeBytes":891,"isText":true},{"path":"references/init.md","sizeBytes":30105,"isText":true},{"path":"references/re-index.md","sizeBytes":9992,"isText":true},{"path":"references/report.md","sizeBytes":9674,"isText":true},{"path":"references/semantic-diff.md","sizeBytes":6392,"isText":true},{"path":"references/severity-classify.md","sizeBytes":6489,"isText":true},{"path":"references/severity-rules.md","sizeBytes":2531,"isText":true},{"path":"references/step-doc-drift.md","sizeBytes":7642,"isText":true},{"path":"references/structural-diff.md","sizeBytes":10495,"isText":true},{"path":"SKILL.md","sizeBytes":9084,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-24T15:43:01.720876Z","sha256":"A7C3047C6F1C386414C1AA696B482068417C24A682120E66ABE7131313C79B11","sizeBytes":39189},"review":null,"source":{"repositoryUrl":"https://github.com/armelhbobdad/bmad-module-skill-forge","path":"src/skf-audit-skill","license":null,"commit":"492e73e7ea0d4069d1f37f5e176424b9c2cf8521","subtreeSha":"FF27BF9D9B82AE314C3F7E173996C6DF3B5C221FBBFAD62F49C6FDB90E4A5B9D","lastSyncedAt":"2026-09-24T15:42:40.059679Z"},"reviewedAt":"2026-09-24T15:43:58.711681Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/armelhbobdad/bmad-module-skill-forge/tree/main/src/skf-audit-skill"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install armelhbobdad-bmad-module-skill-forge@llmmart"},{"target":"git","command":"git clone https://github.com/armelhbobdad/bmad-module-skill-forge.git"}]}