Skip to content
XADEN

Developer Guide

What Xaden checks

On this page

Read this before you trust a green result: which checks ran, which did not, and what you can change.

A project keeps your own tests and linters: Xaden runs only the commands you map with check.<kind> in xaden/xaden.conf, plus Xaden’s own checks.

The checks

CheckAdopted projectIf the tool is missingNetworkPre-commit hook
Requirements format, traceability, documentation structureyes (no guides to check)no toolnoyes, except expired security exceptions
gitleaks secret scanyesskipped; fails with --strict and in CInoyes
semgrep with local rulesyes, rules from the pinned Xadenskipped; fails with --strict and in CInoyes
shellcheck on shell filesyes, under the mode and baselineskipped; fails with --strict and in CInoyes
actionlint on workflowsyes, optional, under the mode and baselinenot runnoyes
zizmor on workflowsyes, optional, under the mode and baselinenot runnoyes
jscpd duplicationonly with .jscpd.jsonskippednono
ruff (Python lint and format)only what check.lint mapsfailsnoyes
mypy (Python types)only what check.typecheck mapsfailsnono
pytest (Python tests)only what check.test mapsfailsnono
npm run (Node lint, typecheck, test)only what the same three keys mapfailsnolint only
bandit (Python security)unless mapped: check.securityskipped; fails with --strict and in CInono
pip-audit (Python dependencies)unless mapped: check.auditskipped; fails with --strict and in CIyesno
npm audit (Node dependencies)unless mapped: check.auditskipped; fails with --strict and in CIyesno

The local semgrep rules are one file per language in the pinned Xaden’s .semgrep/ folder: rules.yml for Python and JavaScript/TypeScript, go.yml for Go, and so on. A file in a language without such a file gets no SAST finding, so a green run says nothing about it.

A skipped check makes the run INCOMPLETE, never a success. The three audit rows are check kinds of an adopted project like test and lint: check.audit (every stack) and check.security (Bandit, Python only). xaden project adopt finds an existing command (a Makefile target audit or security, an npm script audit); xaden project add-preset python maps pip-audit and bandit -q -r . -x ./.venv,./node_modules,./tests, xaden project add-preset node maps npm audit --audit-level=high. The audits never run in the pre-commit hook (they need the network and are slow); the generated CI workflow installs the pinned tools before xaden check --strict. An audit finding names no file, so it cannot be baselined: it fails in changed-files and strict and warns in advisory.

What an adopted project is told

A new adoption expects the audits: expect names audit (and security for Python), so an unmapped one is a gap until you map it. An adoption from before keeps its expect line; xaden core upgrade and xaden project pin never add to it, so no run turns red by an update. Its full run prints a NOT COVERED: line for each check Xaden knows for your stack and nothing maps, and names the key that would map it:

NOT COVERED: pip-audit; a project made by xaden project create runs it. Map it with check.audit in xaden/xaden.conf (see "What Xaden checks")

The line only informs. When expect in xaden/xaden.conf names the kind (expect = test,lint,audit), a missing mapping is a gap instead: a warning in advisory and changed-files, a failure in strict.

A project made by xaden project create never prints this line for what its stacks run.

Make the gates blocking

Four settings turn the checks from advice into a gate:

mode = strict
expect = test,lint,typecheck
missing-tools = fail
require-signature = true
  • mode = strict: any new finding fails, in any file (Check modes and baselines).
  • expect naming every kind of check your stack should have: a kind without a command fails instead of passing unnoticed.
  • missing-tools = fail: a check whose tool is missing fails the run, locally and in the pre-commit, instead of ending INCOMPLETE (CI and releases already fail on a missing tool).
  • require-signature = true: every Xaden your project runs came from a signed release (Verify releases).

Loosening any of the four is an approval point.

A change to the checks is reviewed as code

The settings that decide how a project is checked live in the repository, so a pull request could loosen them and pass by its own rules. In a pull request run, CI compares mode, missing-tools, hook-checks, expect, check.*, findings-status.*, require-signature, version, checksum, the AIDD pin (aidd-cli, aidd-release, aidd-integrity, aidd-commit), the baselines and .github/workflows/xaden.yml with the merge base. A difference fails the run with check settings changed and the changed lines, and no mapped command runs: a check.lint = ... line from a pull request never executes before someone read it. A baseline that grew counts as a change. A key with leading whitespace counts too, because the settings reader ignores the whitespace.

A person who may merge reads the lines and adds the label xaden-settings-accepted to the pull request; the run then continues with the changed settings. The workflow xaden project adopt writes passes the label as SETTINGS_ACCEPTED; an older workflow needs the new one (xaden project pin writes it beside yours as xaden.yml-dist).

Limits: a pull request can also edit the workflow, so protect xaden/xaden.conf, xaden/baselines/ and .github/workflows/ with required review (CODEOWNERS and branch protection). A repository that was not adopted at the merge base, and every run outside a pull request, compares nothing.

In pre-commit, a check.* line that differs from the last commit is shown and runs only after a yes; without a terminal it is skipped, and xaden check runs it later.

These pages describe Xaden v0.6.0, released 2026-10-22.