retrofit — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited retrofit (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Audit an existing repo's drift from a profile and remediate what's missing or misconfigured. This is the "fix it" counterpart to doctor's "tell me what's wrong."
Same logic as doctor — the audit is only meaningful against an intended baseline:
<!-- nyann:start --> markers)declares an active profile name.
--profile <name>, use that.profiles (starters + any user/team profiles). Don't silently default — the wrong baseline produces misleading drift.
Load via bin/load-profile.sh <name>. If exit 2 (not found), show the list the loader reports and ask again.
Run bin/detect-stack.sh --path <target> to get the StackDescriptor. This ensures the remediation step has stack context for gitignore templates, hook phases, and CLAUDE.md rendering.
bin/retrofit.sh --target <cwd> --profile <resolved-name>Do not pass `--report-only` — that's doctor's flag. Retrofit's default mode renders the report AND offers remediation guidance.
Pass --json only if the user explicitly asks for machine-readable output.
If the user said something like "only fix the docs drift", "leave my hooks alone", "just the gitignore", or otherwise wants to remediate one part of the audit without touching others, pass --scope <csv> to retrofit:
| User intent | --scope |
|---|---|
| "fix only the docs" | docs |
| "fix hooks but leave docs alone" | hooks |
| "fix the gitignore" | gitignore |
| "fix only docs and hooks" | docs,hooks |
| "fix the github protection settings" | github |
| "fix everything" / unstated | omit (default all) |
The accepted categories are docs, hooks, branching, gitignore, editorconfig, github, history, all. Unknown values exit non-zero; surface the error to the user verbatim.
When the report covers fewer than the full 7 categories, the rendered text adds a Scope: <csv> line under the heading. The remediation plan in step 5 uses the same --scope so that bootstrap only writes the matching files.
If the user did NOT specify a scope AND the resulting report shows drift in more than one category, prompt before remediation:
{
"questions": [{
"question": "Drift detected across multiple categories. Which to fix?",
"header": "Scope",
"multiSelect": true,
"options": [
{"label": "Docs", "description": "CLAUDE.md size, doc scaffolds, links, orphans, staleness"},
{"label": "Hooks", "description": "Husky, commitlint, pre-commit.com, core hooks"},
{"label": "Gitignore", "description": "Missing stack-typical entries"},
{"label": "Branching", "description": "Profile-declared base/long-lived branches"},
{"label": "GitHub", "description": "CI workflow, PR template, branch + tag protection"},
{"label": "Editorconfig","description": ".editorconfig presence"},
{"label": "All", "description": "Apply every remediation"}
]
}]
}Map the labels back to the --scope value: e.g. {Docs, Hooks} → docs,hooks. If the user picks "All", omit the flag.
| Code | Meaning | What to do |
|---|---|---|
| 0 | clean | "No drift detected. Repo matches the profile." Done. |
| 4 | warnings | Show the report. Offer to remediate (step 5). |
| 5 | critical | Show the report. Strongly recommend remediation (step 5). |
When drift exists (exit 4 or 5) and the user confirms they want to fix it:
writes[] entries:
.gitignore → gitignore combiner handles it.husky/*, commitlint.config.js → install-hooks.sh --jsts.pre-commit-config.yaml → install-hooks.sh --pythondocs/*, memory/* → scaffold-docs.shCLAUDE.md → gen-claudemd.sh.editorconfig → include in plan if profile declares itMisplaced docs (v1.9.0+): If the DriftReport's misplaced[] array is non-empty, docs exist at non-canonical paths. Before scaffolding new docs, offer to reorganize the existing ones:
{
"questions": [{
"question": "Found docs at non-standard paths. Reorganize to nyann conventions?",
"header": "Doc layout",
"options": [
{"label": "Yes, reorganize", "description": "Move docs to canonical paths (uses git mv). Content is preserved."},
{"label": "No, scaffold fresh", "description": "Leave existing files and create new ones at canonical paths."}
],
"multiSelect": false
}]
}If Yes: write the misplaced[] array to a temp file and run bin/reorganize-docs.sh --target <cwd> --moves <temp.json> --apply before the scaffold step. (Without --apply, the script previews only — pass --apply after the user confirms.) After moves complete, the scaffold step detects the files at canonical paths and skips creation — preserving user content.
If No: proceed normally — scaffold-docs creates fresh templates at canonical paths (existing non-canonical files remain untouched).
bin/route-docs.sh --profile <path> to get theDocumentationPlan (needed by bootstrap for scaffold-docs and gen-claudemd).
Archetype-aware retrofit (v1.6.0+): if the profile sets documentation.use_archetype_scaffolds: true, the resolved DocumentationPlan will include the per-archetype doc set (api-reference / runbook / deployment / glossary as applicable). compute-drift will surface any missing files from that set as missing entries, and remediation will scaffold them.
When the profile leaves use_archetype_scaffolds unset/false, retrofit does NOT auto-flip it. Per the v1.6.0 design, opt-in stays opt-in — surface the absent flag as informational only: "This profile could enable archetype-aware scaffolds. Run /nyann:migrate-profile or set use_archetype_scaffolds: true in your profile to opt in."
--target <cwd> --profile <profile.json> --doc-plan <doc-plan.json> --templates-csv <jsts|python|...> --output <plan.rendered.json> so preview.sh can diff .gitignore and CLAUDE.md` merges against the current files. Skip render-plan only when neither path appears as a merge action in the plan.
--target <cwd>. Pass --target so the merge-diff renderer resolves .path` entries against the actual repo. Show the user what will be created/merged. Respect skip requests.
bin/bootstrap.sh --source retrofit. The --sourceflag labels the boot record so /nyann:undo-bootstrap can tell remediation runs apart from initial setups. Capture the plan SHA-256 first via bin/preview.sh --emit-sha256, then pass it through as --plan-sha256 so bootstrap can verify the plan bytes haven't changed between the user's confirmation and execution. The SHA binding is required; bootstrap refuses to run without it.
sha=$(bin/preview.sh --plan <confirmed-plan.json> --emit-sha256)
bin/bootstrap.sh \
--target <cwd> \
--plan <confirmed-plan.json> \
--plan-sha256 "$sha" \
--profile <path> \
--doc-plan <doc-plan.json> \
--stack <stack.json> \
--source retrofitBootstrap is idempotent — existing user content is preserved, hooks are merged (not overwritten), gitignore entries are deduplicated.
Show the before/after delta.
Tell the user: "Past commits are informational only. Future commits will be validated by the hooks we just installed."
not app code.
npm install or pip install. Tell the user to run their package manager after retrofit.
End with a compact report:
doctor.bootstrap-project.with the new profile.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.