SuperAPI AI Directory

crank-health

Coding & development

View repository

Updated 10-15 20:12

About this skill

Crank health

Measure, then plan. The analyzers produce the evidence; you produce eight letters and a plan of tasks a coding agent can work and verify. Grades come from references/grading.md, the plan from assets/plan.md.

references/ and assets/ are relative to this skill's directory. The target path defaults to the current repo. Quick profile unless --deep. --only <category,…> narrows the categories; the rest read not assessed (not selected). --project repeats; the selection is the union, the rollup covers the selection only, and repo-wide tools run over the selected directories.

Every project is its own unit, so a monorepo is N projects plus the rollup: a repo-wide measure takes one pass per project directory for the project letter and one over the selection for the rollup.

Contracts

  • Zero footprint. Everything you write goes under the run dir <repo>/.crank-health/<YYYY-MM-DD>-<4 hex>/, evidence in raw/ findings/ summary/, tool caches and mirrors in scratch/. Create .crank-health/.gitignore containing * only if it does not exist; another run's dir beside yours is not yours to touch. Tools that write beside the code are redirected by the flags in the references. The footprint comparison in references/inventory.md must come back empty before you report.
  • Secrets never quoted. Each tool's redaction flag sits in its reference row, and a secret finding anchors on the rule id and the file, never the flagged line. Copies of source under scratch/ (the aislop mirror, the complexipy copy, a PR base worktree) hold every secret the repo does, so scratch/ is deleted in step 7 and the run dir is grepped before you report.
  • Quick never executes repo code. Build, test and mutation tools run only under --deep, and mutation tools only where the repo owns and installed them (an ephemeral copy fails confidently instead of saying "not available").
  • One tool never aborts the run. A tool that fails records a state and the run continues; assets/summary.md defines the five states and what each must carry. Budgets: 120 s, 300 s for Go, cppcheck and build tools, 15 min for mutation, enforced with perl -e 'alarm shift; exec @ARGV' <secs> <command…> (macOS has no timeout); a killed tool is timeout. Non-zero exit is not failure: most linters exit 1 on findings.
  • Nothing to measure is not assessed (reason), never A. All eight categories appear in every report.

Steps

  • 1. Inventory. mkdir -p <run-dir>/{scratch,raw,findings,summary}, then work references/inventory.md end to end: scope the files, split them into projects, count each project's lines by language, record what each project owns and what is on PATH, and take the footprint snapshot. It lands as <run-dir>/inventory.md. Then fill assets/tools.md into <run-dir>/tools.md, one row per (project × category × tool), resolving each row by the provenance rules at the foot of that file. Done when every project has languages, KLOC and owned tools in inventory.md, and every row in tools.md has a provenance.
  • 2. Scan. One subagent per (language × project), plus one for the repo-wide tools, in parallel, at the standard tier of SUBAGENT-TIERS.md (the work is running commands and writing rows; the judgment happens in step 3). Each gets: the run dir, its project path and file list, its rows from tools.md, the matching reference file to read in full (references/jsts.md, python.md, go.md, csharp.md, cpp.md, common.md), references/grading.md for the graded/advisory and severity rules, assets/summary.md as its return format, and the budget seconds and alarm form from Contracts copied into the prompt. It writes raw output under <run-dir>/raw/<project>/, findings under <run-dir>/findings/<project>/<tool>.tsv, and returns the summary; save it as <run-dir>/summary/<language>--<project path, / as ->.md. Done when every tools.md row has a state in a summary and its findings file exists or its state says why not.
  • 3. Triage. Check the subagents' graded/advisory calls against references/grading.md, dedupe one defect seen by several tools, then read the repo before you believe a tool: knip on a library, ty on untyped code, jscpd on a test suite, zizmor on unpinned actions, and above all whether the code under scan is a fixture, a captured snapshot or deliberately broken (inventory.md lists snapshot dirs; a README or test beside the files usually says). Findings in generated code (dist/, gen/, *.gen.*, lockfiles, captured tool output, globs the repo's own Biome or fallow config excludes) leave the tasks, never the count. Done when every finding row is graded, advisory, or dropped with a reason.
  • 4. Grade. Per project and for the rollup, print the arithmetic beside the letter. Done when every project and the rollup carry all eight categories, each with a letter and its basis or not assessed (reason).
  • 5. Plan. Fill assets/plan.md into <run-dir>/plan.md. Theme tasks (one rule across files is one task; two categories at the same place merge into one task titled with both), order by letters moved then category order (security, types, dead code, complexity, duplication, lint, format, test quality), cap at 20 and spill the rest to <run-dir>/findings.md. Every task carries the exact tool command that reports zero when it is done. A fixture whose findings are load-bearing is named as such at the top and gets no task. Done when every graded finding in hand-written code is in a task or the spill file.
  • 6. Fix (only with --fix). Run the repo's own formatter with its write flag (prettier --write, biome format --write, ruff format, gofmt -w, dotnet format whitespace, clang-format -i), then the safe autofixes (ruff check --fix without --unsafe-fixes, eslint --fix, oxlint --fix, biome lint --write), with the repo's config only; a repo with no formatter keeps its style, and fixtures named in the plan are left alone. Re-run the touched tools and re-grade. Then work the tasks in order, one task per commit-sized change, verifying each with its Verify command. Done when the re-run tools agree with the plan's expected grades, or the remaining tasks are listed with why they were left.
  • 7. Report. rm -rf <run-dir>/scratch, then grep -rIlE 'AKIA[0-9A-Z]{16}|BEGIN [A-Z ]*PRIVATE KEY|ghp_[A-Za-z0-9]{36}|xox[baprs]-|sk-[A-Za-z0-9]{20,}' <run-dir> must print nothing (delete and redact what it names), then re-run the footprint listing from references/inventory.md and compare it against <run-dir>/footprint.txt: a path in the new listing and not the snapshot is yours to remove. Reply with the grade line, the top three tasks, what was not assessed and why, and the run dir path. Done when both checks come back empty.

PR mode (--pr <base>)

Scan head, then scan the merge-base (git merge-base <base> HEAD) in git worktree add --detach <run-dir>/scratch/base <sha>, with the same tool versions (reuse the name@version each head tool printed) and the same provenance. Remove the worktree with git worktree remove afterwards. Compare finding sets keyed on (category, tool, rule, file after git diff -M --name-status rename mapping, message): new = head minus base, resolved = base minus head. Whole-tree measures (duplication, dead code) are computed on both sides in full. Tasks come from new findings only; a new finding on a line the diff touched is [touched] and goes first. Under --deep, mutate only the changed files.

Deep profile (--deep)

Adds: C# build-backed categories (references/csharp.md), C/C++ compile-database categories (references/cpp.md, a CMake or Meson configure into scratch), mutation testing where owned, coverage as context. Mutation runs in every project that owns a tool, 15 min each; --project is the cost control. Warn before cosmic-ray (it mutates files in place) and refuse it on a dirty tree.

Gotchas

  • A standby that graded because the owner errored says so in the plan: oxlint graded lint on its default config because eslint reported error.
  • Versions float, so two runs a month apart can differ. tools.md records every version, which is what lets a reader tell drift from change.