Agent SwarmAgent Swarm
Playbooks

Code Health

Run recurring Code Maat + D3.js code-health reports for any Git repository. The swarm installs the runner, refreshes the report weekly by default, and updates one stable Page URL in place.

This is the Code Health home for recurring repository analysis. The main flow is the reports-on-autopilot path for Code Maat + D3.js; the alerting-specific playbook is now focused on Observability Alert Management.

What it does

The swarm creates a stable code-health report page for one repository:

  • Hotspots — files with high change frequency and complexity.
  • Temporal coupling — files that tend to change together.
  • Code age — how recently scoped files changed.
  • Ownership — who has historically contributed the most to each file.
  • Weekly refresh — the same Page URL updates in place, so links remain stable.

The first run installs or downloads what it needs. You do not pre-install Code Maat or D3.

Agents

  • Lead — collects the repository URL, branch, path scope, report slug, cadence, and stable Page behavior; creates or configures the weekly schedule.
  • Coder — installs the runner, runs the first report, fixes local runner/report-generator issues, and updates the stable Page.
  • Reviewer — optional, used when a runner change needs a PR before the scheduled job can keep running cleanly.

Tools & Skills

Built-in (ships with agent-swarm)

  • Pages — hosts the generated static report HTML at a stable URL.
  • store-progress — records the stable Page URL, analyzed commit, report workspace, and any dependency/chart-rendering issue.
  • slack-reply — posts the report URL and weekly-refresh status back to the requesting thread.

Community template

  • templates/community/code-health-reports — the reusable package with:
    • PLAYBOOK.md — the full drop-in playbook.
    • run.sh — parameterized runner.
    • report.mjs — static report generator.
    • lead-prompt.md — copy-paste kickoff prompt for a Lead agent.

Third-party tools

  • Code Maat — Adam Tornhill's command-line tool for mining version-control history.
  • D3.js — browser-side charts. Generated reports load D3 v7 from jsDelivr at render time; there is no front-end build step.
  • Lizard — cyclomatic complexity analyzer used to add a complexity axis to history metrics.
  • Java runtime — required by the Code Maat standalone Clojure JAR.

Workflows / Schedules

  • weekly-code-health-reports — weekly by default. Installs or updates the runner workspace, executes the Code Maat + Lizard analysis, generates latest.html and latest.json, updates the same stable Page ID, then verifies the D3 charts render.

Small static-scan companion: weekly-code-health runs knip + desloppify and routes the top concerns into focused follow-up work.

Default cadence:

cron: "0 21 * * 0"
timezone: "UTC"

That means weekly on Sunday at 21:00 UTC. Change the cron field to adjust the refresh time, and change timezone if you want the cron interpreted in another zone:

# Every Monday at 09:00 Europe/Madrid
cron: "0 9 * * 1"
timezone: "Europe/Madrid"

The cadence is separate from page identity. Changing the cron only changes when the report refreshes. Keep updating the same stable Page ID in place.

Template install shape

Use a workspace outside the target repository so report artifacts and downloaded tools do not pollute the codebase:

mkdir -p /workspace/code-maat
cp templates/community/code-health-reports/run.sh /workspace/code-maat/
cp templates/community/code-health-reports/report.mjs /workspace/code-maat/
cp templates/community/code-health-reports/lead-prompt.md /workspace/code-maat/
chmod +x /workspace/code-maat/run.sh

Parameterize each run with environment variables:

BASE_DIR=/workspace/code-maat \
REPO_NAME=my-repo \
REPO_URL=https://github.com/OWNER/REPO.git \
BRANCH=main \
SCOPE_PATH=src \
bash /workspace/code-maat/run.sh

The runner creates this shape:

/workspace/code-maat/
  run.sh
  report.mjs
  lead-prompt.md
  code-maat.jar
  repos/
    <repo-name>/
  out/
    <repo-name>/
      <YYYY-MM-DD>/
        revisions.csv
        coupling.csv
        age.csv
        authors.csv
        entity-ownership.csv
        main-dev.csv
        abs-churn.csv
        entity-churn.csv
        lizard-functions.csv
        summary.json
        report.html
      latest.json
      latest.html
      latest-pointer.json

Runner behavior

run.sh does the following:

  • Installs default-jre-headless if java is missing.
  • Installs nodejs if node is missing.
  • Installs Python and lizard if Lizard is missing.
  • Downloads Code Maat v1.0.4 standalone JAR into BASE_DIR if missing.
  • Clones the target repository into a scratch directory.
  • Disables the scratch clone push URL so the scheduled job cannot push accidentally.
  • Generates Code Maat CSVs and a Lizard CSV.
  • Runs report.mjs.
  • Copies the latest artifacts to stable latest.html, latest.json, and latest-pointer.json paths.

It generates the git log with:

git -C "$REPO_DIR" log --all --numstat --date=short --pretty=format:'--%h--%ad--%aN' --no-renames -- "$SCOPE_PATH"

It runs these Code Maat analyses:

summary
revisions
coupling
age
authors
entity-ownership
entity-effort
main-dev
main-dev-by-revs
abs-churn
author-churn
entity-churn

Then it runs Lizard over the scoped path and writes the static D3 report.

Report generator

report.mjs parses the Code Maat and Lizard CSVs, joins historical metrics to current file LOC, computes a hotspot score, and embeds the final data in a static HTML file.

The generator interface:

node /workspace/code-maat/report.mjs \
  /workspace/code-maat/out/<repo-name>/<YYYY-MM-DD> \
  /workspace/code-maat/repos/<repo-name> \
  <repo-name> \
  <YYYY-MM-DD> \
  <SCOPE_PATH>

The default hotspot score is:

risk score = revisions * log2(total cyclomatic complexity + 1)

The generated report includes:

  • Hotspot bubble chart.
  • Change-frequency x complexity scatter.
  • Top hotspot table.
  • Temporal coupling table.
  • Code age distribution.
  • D3 v7 loaded from CDN at view time.

Patterns used

  • No-op When Nothing Changed — keep the schedule quiet if a run determines there is no meaningful new report to publish.
  • HITL Gates — use a human approval gate before widening scope, changing cadence, or turning report findings into repair PRs.

Tips for new swarm users

  • Start with src. It avoids docs, package metadata, generated files, and examples. For monorepos, use a narrower scope such as apps/web/src or packages/core/src.
  • Keep the workspace outside the target repo. /workspace/code-maat keeps reports and downloaded tools out of commits.
  • Save the Page ID immediately. The value of this report is the stable URL. Create once, then update in place.
  • Use a code-capable worker. Scheduled jobs sometimes need to repair the runner when upstream dependencies, branch names, or page APIs change.
  • Treat the report as a map, not a verdict. Hotspots identify where to inspect first; they do not automatically mean a file is bad.
  • Do not vendor Code Maat casually. This template downloads it at runtime so adopters avoid accidentally redistributing a GPLv3 JAR in their own bundle.

References

  • D3.js: JavaScript library used for the browser-side charts.
  • D3 getting started: D3 documentation for loading and using the library.
  • Code Maat: Adam Tornhill's version-control mining tool used for revisions, coupling, age, and ownership metrics.
  • Code Maat analyses API index: reference list for Code Maat analyses.
  • Code Maat distribution notes: upstream distribution page for standalone Code Maat usage.
  • Adam Tornhill: creator of Code Maat and author of the behavioral-code-analysis framing used here.
  • Your Code as a Crime Scene: Adam Tornhill's book on hotspots, temporal coupling, code age, and social code analysis.
  • Maat D3 scripts: Adam Tornhill's D3 visualization scripts for Code Maat data, including the canonical enclosure diagram lineage.
  • Lizard: complexity analyzer used here to add per-file cyclomatic complexity.
  • Code Maat GPLv3 license: Code Maat is GPLv3. This template does not vendor or redistribute Code Maat. It downloads the upstream standalone JAR at runtime on first run. If you choose to distribute the JAR yourself, follow GPLv3 distribution obligations, including source and license notice requirements.

On this page