Skip to content

Compliance Scoring

Codaris scores a pipeline against a versioned ruleset derived from the nf-core specifications, and applies rollback-safe fixes for the rules it fails. The score describes how closely a pipeline follows the nf-core and Nextflow DSL2 standards. It is not a certification under any regulatory framework, and the report says so in those words.


The ruleset

Property Value
Name Codaris nf-core Compliance Ruleset
Version 1.1.0 (ruleset file compliance_ruleset_v1.1.0_nfcore-4.0.2.yml)
Upstream nf-core specifications at tools 4.0.2, plus the Strict-Syntax family (CR-0240 to CR-0249) checked against the Nextflow strict-syntax documentation
Rules 249: 135 Components, 46 Pipelines, 34 Configs, 15 Reviews, 12 Test-Data, 7 Specifications
Tiers 77 REQUIRED (a failure blocks compliance), 22 PREREQUISITE (gating context), 150 RECOMMENDED (advisory)
Methods 100 deterministic (checked mechanically), 134 heuristic (judged by the evaluator model), 15 informational (context, not scored)

Every rule has an id (CR-0001 to CR-0249), a title, a description, the tier, the method, the files it applies to, and the source it was derived from. /rules in the chat and codaris review --json expose the catalogue; the YAML is in backend/app/rulesets/.

Automated nf-core lint is deliberately outside the ruleset. Lint runs as its own step (codaris lint, and inside every build), and rule CR-0063 (Pass lint tests) records its outcome.

Profiles

Profile Rules scored Use
core (default) 164 Calibrated on 2026-08-21 against nf-core/fetchngs and nf-core/demultiplex; the rules that judge decisively with limited context
full 249 Every rule, including the ones parked out of core because they need the whole pipeline in view

codaris review --profile full or CODARIS_RULE_PROFILE=full selects the second.

Examples

Rule Title Tier Method
CR-0001 Each module must emit versions (through a topic: channel entry) REQUIRED deterministic
CR-0002 Module container references are to a specific version of the container, not latest REQUIRED deterministic
CR-0014 Naming of args variables (args, args2, … by the tool's position in a pipe) REQUIRED deterministic
CR-0020 A stub block must exist in every module REQUIRED deterministic
CR-0063 Pass lint tests (no undocumented nf-core lint failures) REQUIRED heuristic
CR-0102 Options the tool does not require are passed through ext.args, not as val inputs RECOMMENDED deterministic
CR-0177 Output channel names follow the major output file (bam, not ch_bam) RECOMMENDED deterministic

Running a review

codaris review ./my-pipeline              # core profile, evaluator model for the heuristic rules
codaris review ./my-pipeline --quick      # deterministic checkers and nf-core lint only, no model
codaris review ./my-pipeline --json       # one JSON object with the score, the grade, and the report paths

In the chat the same audit is /audit (the counterpart of codaris audit), or /review --compliance; /review --quick is the quick pass. A bare /review is a different, cheaper engine: the structural wiring review (review_pipeline: channels, params, containers, configs; free, deterministic, a few seconds). Which engine answers is decided by the text you type, not by the model: a bare /review binds review_pipeline and nothing else, and /audit binds the scorecard tool and nothing else, so the same message always runs the same engine. A /review that asks something (/review are the channels wired?), names a path, or carries --security or --lint stays in Review mode, where the model picks the engine by what you asked.

The audit is read-only: it writes nothing into the pipeline (the report comes back in the answer; nf-core lint runs on a throwaway copy), and /audit cannot apply fixes; only /remediate (or /autofix) does. Ask for the report to be saved and it writes docs/compliance-report.json, and nothing else.

Every scored result opens with one line that carries its numbers, and the chat repeats it word for word rather than summarising from the tables:

COMPLIANCE SUMMARY: score 52.9% (grade F, graded: yes) | findings: 38 unaddressed (94 open checks) | audit agreement: 5/12 = 41.7% | checks evaluated: 384/386 | written: nothing (read-only)

graded: no replaces the letter when fewer than half of the checks produced a verdict; findings is the fix directives not applied and, in brackets, the checks that failed or warned; audit agreement is the share of a sample of verdicts that the second model confirmed on re-derivation, or no audit run; written: lists the files this call wrote, so a read-only run says nothing (read-only) and a run that applies fixes lists each file. The chat does not say a report was generated or saved unless that field lists it.

The command prints the Markdown report and closes with one line:

Review — overall 91.4% (grade A)
Report: /path/to/my-pipeline/docs/compliance-report.json

The command asks for docs/compliance-report.json inside the pipeline, with a scorecard per category and the findings per rule; remediate also writes the interactive HTML report, the score history and the fix plan. The score is weighted: each applicable rule counts its ruleset weight, so a REQUIRED failure costs more than a RECOMMENDED one, and the overall figure is the ratio over every applicable rule rather than an average of the categories. The grade is a letter band on the score (A+ from 97, A from 93, down to F below 60). The grade is given only when at least half of the checks produced a verdict. If the evaluator could not answer most of them, the report says Not graded: 17 of 386 checks evaluated and labels the score as the share of the evaluated checks that pass, rather than printing a letter over a handful of checks.


Remediation

codaris remediate ./my-pipeline
codaris remediate ./my-pipeline --allow-destructive --max-iterations 3

remediate (and /remediate in the chat) proposes a fix for each failed rule that has a deterministic repair, applies it with a backup, re-validates the file, and keeps the change only when a verifier model agrees it addresses the rule without breaking anything else. Each attempt is recorded as applied, rejected and rolled back, withdrawn, or skipped, and the closing summary counts them:

Remediation — overall 94.8% (grade A)
Applied 6, rejected/rolled back 1, withdrawn 0, skipped 2, errors 0.
  applied:
    …one line per fix, naming the rule and the file…
  rolled back:
    …the fixes the verifier rejected, with its reason…
Report: /path/to/my-pipeline/docs/compliance-report.json

Fixes that are not rollback-safe run only with --allow-destructive.


Containers

Every process the compiler writes declares a quay.io/biocontainers image with an explicit version tag, taken from the module's own declaration. A latest tag is a CR-0002 violation; a tag that the registry does not know is reported by the container check (CODARIS_CONTAINER_LOOKUP=0 turns the network lookup off for air-gapped hosts). Pinning by image digest is a choice you make in the pipeline; Codaris verifies the tag it writes and leaves the digest form to you.


The provenance record

The build writes .codaris/provenance.json after its last write to the tree:

{
  "codaris_signature": "CODARIS-SIG-667b27218694e713",
  "sha256_merkle_root": "667b2721…",
  "pipeline_name": "rnaseq",
  "manifest": {
    "conf/base.config": "…",
    "main.nf": "…",
    "modules/nf-core/fastqc/main.nf": "…",
    "workflows/rnaseq.nf": "…"
  },
  "method": "sha256 of each file under PROVENANCE_GLOBS, then sha256 over '<path>\\0<sha256>\\n' for every entry in path order",
  "scope": ["main.nf", "nextflow.config", "nextflow_schema.json", "conf/*.config", "workflows/**/*.nf", "subworkflows/**/*.nf", "modules/**/*.nf"],
  "computed_at": "2026-10-11T03:40:12+00:00",
  "verify": "python -m app.engine.security_scanner verify <pipeline_dir>"
}

The record identifies the files a build report describes. python -m app.engine.security_scanner verify <pipeline> recomputes the manifest and lists the files changed, added, or removed since; the exit code is 0 when nothing changed. The record is a content fingerprint computed by the same process that wrote the files; it carries no signature from a key and no claim about the build platform.