Universal CI/CD Diff Sentinel &
AI Coding Agent Gatekeeper
Traverses AST diffs via tree-sitter over merge-base git graphs. Rejects assertion weakening, vacuous tests, unannotated unsafe, test suppression, and algorithmic regressions across pull requests and merge requests.
Autonomous AI agents in an iterate-until-green loop optimize for passing tests, not preserving invariants. Discipline halts erosion at the gate.
Tree-Sitter AST Diff Inspection
Unlike fragile regex checks that trigger on comments or log messages, Discipline parses the complete AST of changed functions against the merge base. It accurately counts executable assertions and distinguishes real invariants from dead code.
AI Coding Agent Guardrails
Flags silent test erosion: assertion count reductions (e.g. assert_eq! → assert!), test suppression (#[ignore], @pytest.mark.skip, it.skip), tautological vacuous tests (assert!(true)), and stealth test deletions.
Fail-Closed Engineering
If git history cannot be resolved, a clone is shallow, or a configuration file is malformed, Discipline exits with code 2. It never yields a false-positive pass on broken pipelines or empty diff outputs.
Native MR & PR Reporting
Discipline emits industry-standard reports without external plugins: GitLab Code Quality diffs, JUnit test widgets, GitHub PR comments, GitHub Actions Annotations, and SARIF security tabs.
First-class support across all enterprise CI/CD systems, container runtimes, and local developer hooks.
Composite GitHub Action publishing workflow annotations, SARIF code scanning results, and PR status checks.
Native GitLab CI/CD integration. Populates GitLab Merge Request Code Quality diffs and JUnit test reports.
Native support for Forgejo Actions running via forgejo-runner. Supports workflows in .forgejo/workflows/ with automatic base ref and PR event detection.
Runs seamlessly under self-hosted Gitea act_runner. Zero JavaScript runtime required.
Kubernetes-native pre-merge gating for GitOps and continuous deployment pipelines.
Non-root, minimal static Alpine image for local containers or custom CI runners.
Git hook configuration preventing non-compliant commits before they reach remote branches.
Direct command-line execution for local developers, script automation, and self-checks.
Every gate operates with fail-closed semantics, truthful examination counts, and explicit remediation instructions.
| Gate ID | Category | Severity | Languages | Rule Description |
|---|---|---|---|---|
| agents-md | Agent Guard | Error | Any | AGENTS.md exists; CLAUDE.md / GEMINI.md do not fork it |
| assertion-reduction | Agent Guard | Error | Rust, Python, JS/TS, PHPT, Java, Go | assertion count / strength must not drop in an existing test |
| vacuous-tests | Agent Guard | Error | Rust, Python, JS/TS, PHPT, Java, Go | new tests must carry a non-tautological assertion |
| ignored-tests | Agent Guard | Error | Rust, Python, JS/TS, PHPT, Java, Go | tests must not be newly #[ignore]d |
| unsafe-safety-comment | Agent Guard | Error | Rust | unsafe blocks / impls carry a // SAFETY: comment |
| deletion-rationale | Agent Guard | Error | Any | deleted files and removed tests need a scoped removes: rationale |
| time-estimates | Hygiene | Error | Any | no calendar / duration estimates in markdown or the PR body |
| pii | Hygiene | Error | Any | no home paths, LAN IPs, or denylisted hostnames in tracked text |
| agent-scratch | Hygiene | Error | Any | agent scratch state is never tracked |
| config-integrity | Integrity | Error | Any | a change cannot weaken its own discipline.toml without a token |
| golden-output | Integrity | Error | Any | prevents stealth edits to committed golden/test output files without explicit override |
| bench-regression | Performance | Error | Rust, Go, Python, C/C++ | benchmark drift via harness adapters (deterministic counts or BCa intervals) |
Audit-Trailed Override Directives
Legitimate deletions or changes are authorized through explicit, scoped directives in the PR description or commit message:
allow-assertion-drop: test_allocator single large allocation split into benchmark
allow-ignore: test_darwin_kqueue requires macos runner environment
allow-golden-update: tests/snapshots/v2.snap updated for new serializer format
Composite Action Inputs
Complete input parameters for GitHub Actions, Gitea Actions, and Forgejo Actions:
| Input | Default | Description |
|---|---|---|
| config | discipline.toml |
Path to discipline.toml. When the file is absent, built-in defaults apply (every available gate on). |
| suite | all |
Suite to run: all, agent-guard, hygiene, integrity |
| base_ref | (none) | Branch or commit the change is measured against. Default: PR base branch, else the pushed-from commit, else the default branch. |
| enable | (none) | Gate ids to force on (comma or newline separated). See `discipline gates`. |
| disable | (none) | Gate ids to force off (comma or newline separated), e.g. "time-estimates, pii". |
| config_override | (none) | Inline TOML merged over discipline.toml: tables merge, lists append, scalars replace. |
| hostname_denylist | (none) | Hostnames the pii gate must reject (comma or newline separated). Pass a secret; matches are never echoed. |
| fail_on_warnings | false |
Treat warnings as failures. |
| fail_on_overrides | false |
Treat applied overrides as failures (requires human sign-off). |
| directive_sources | (none) | Comma-separated list of allowed directive sources (pr-body, commits). |
| pr_body | ${{ github.event.pull_request.body }} |
PR description: carries override directives and is itself scanned by hygiene gates. |
| working_directory | . |
Directory of the repository to check. |
| version | (none) | Release to download (e.g. v0.1.0). Default: the tag this action was referenced by, else the latest release. |
| binary_path | (none) | Use this discipline binary instead of downloading one (air-gapped Gitea/Forgejo runners, self-tests). |
| download_url | https://github.com/orieg/discipline/releases |
Base URL of the release store, for mirrors. |
Composite Action Outputs
Step outputs emitted by the composite action:
| Output | Description |
|---|---|
| status | pass, fail, or error |
| errors | Number of blocking violations |
| warnings | Number of non-blocking violations |
| failed_gates | Comma separated ids of the gates that reported a violation |
| overrides | Number of applied override directives |
| overridden_gates | Comma separated ids of the gates that had an override applied |
| report | Path of the JSON report |
| install_error | Why installing the binary failed (empty on success) |
Zero-dependency, standalone binary operating entirely in-memory and offline.
Available as a pre-compiled static binary, container image, or from source via Cargo.
Cargo (From Source)
Pure Rust build requiring rustc 1.80+.
Docker Container
Non-root Alpine container with static binary.
GitLab CI/CD Component
GitLab 16.0+ CI/CD Catalog Component.
GitHub Action
Composite action with automatic binary bootstrap.
Forgejo Action
Compatible with Forgejo Actions and forgejo-runner.
Gitea Action
Compatible with self-hosted Gitea and act_runner.
Pre-Commit Hook
Local git pre-commit hook (discipline / discipline-system).