# How to Configure Custom Quality Gates in AIOX Beyond the Default npm run lint, typecheck, and test

> Learn to configure custom quality gates in AIOX by modifying the quality-gate-config.yaml file and implementing Node.js modules for advanced checks beyond default lint typecheck and test

- Repository: [SynkraAI/aiox-core](https://github.com/synkraai/aiox-core)
- Tags: how-to-guide
- Published: 2026-03-15

---

**You configure custom quality gates in AIOX by adding new `command` or `script` entries to [`.aiox-core/core/quality-gates/quality-gate-config.yaml`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/quality-gate-config.yaml) and implementing Node.js modules that export a Promise-returning function adhering to the `{ passed: boolean, summary: string }` contract.**

The **SynkraAI/aiox-core** repository provides a **three-layer Quality Gate system** that executes automatically before commits and pull requests. While the default pipeline runs `npm run lint`, `npm run typecheck`, and `npm test`, the architecture is deliberately **plug-in-friendly**, enabling you to configure custom quality gates that enforce security scans, custom linters, or manual review checklists.

## Understanding the AIOX Quality Gate Architecture

AIOX orchestrates quality gates through the **`QualityGateManager`** ([`.aiox-core/core/quality-gates/quality-gate-manager.js`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/quality-gate-manager.js)). This manager reads declarative configurations from [`.aiox-core/core/quality-gates/quality-gate-config.yaml`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/quality-gate-config.yaml) and dynamically loads implementations using Node.js `require`.

The system operates across three distinct layers:

1. **Layer 1 – Pre-Commit**: Fast static checks (lint, type-check) implemented in [`layer1-precommit.js`](https://github.com/SynkraAI/aiox-core/blob/main/layer1-precommit.js). Extend by adding **`command`** entries.
2. **Layer 2 – PR Automation**: CI-level validations (unit tests, integration tests) implemented in [`layer2-pr-automation.js`](https://github.com/SynkraAI/aiox-core/blob/main/layer2-pr-automation.js). Extend by registering **`script`** modules.
3. **Layer 3 – Human Review**: Manual or semi-automated review steps orchestrated via [`human-review-orchestrator.js`](https://github.com/SynkraAI/aiox-core/blob/main/human-review-orchestrator.js). Extend by declaring **`review-tasks`** with optional **`interactive: true`** flags.

Each layer respects the same execution contract: the manager invokes your module and expects a Promise resolving to an object with `passed` (boolean) and `summary` (string) properties. Because the manager simply `require`s the paths listed in the config, you can drop any executable Node.js module into the quality-gates directory and AIOX will treat it as a new gate.

## Step-by-Step Configuration of Custom Quality Gates

### Editing the YAML Configuration File

The central configuration lives in [`.aiox-core/core/quality-gates/quality-gate-config.yaml`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/quality-gate-config.yaml). To add a gate, append an entry to the appropriate layer array:

- Use **`command`** for shell commands (Layer 1).
- Use **`script`** for Node.js module paths (Layers 2 and 3).
- Use **`interactive: true`** for Layer 3 gates requiring human input.

### Implementing the Gate Logic Contract

Create a JavaScript file that exports a single function. This function must return a Promise that resolves to an object with:

- **`passed`**: Boolean indicating success or failure.
- **`summary`**: String describing the outcome for CLI and UI display.

The manager automatically invokes this function during `*push` and `*pre-push` workflows defined in [`bin/aiox.js`](https://github.com/SynkraAI/aiox-core/blob/main/bin/aiox.js).

## Practical Examples for Each Quality Gate Layer

### Layer 1 Example – Adding a Custom ESLint Rule Set (Pre-Commit)

Add a custom linting step that runs alongside the default `npm run lint`.

Update [`quality-gate-config.yaml`](https://github.com/SynkraAI/aiox-core/blob/main/quality-gate-config.yaml):

```yaml
layer1:
  - name: lint
    command: "npm run lint"
  - name: custom-eslint
    command: "node .aiox-core/core/quality-gates/custom-eslint.js"
    description: "Run project-specific ESLint rules"

```

Implement [`.aiox-core/core/quality-gates/custom-eslint.js`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/custom-eslint.js):

```javascript
const { exec } = require('child_process');

/**
 * Executes a custom ESLint command.
 * Must return {Promise<{passed: boolean, summary: string}>}
 */
module.exports = () => new Promise((resolve) => {
  exec('npx eslint src --config .eslintrc.custom.js', (err, stdout, stderr) => {
    if (err) {
      resolve({
        passed: false,
        summary: `Custom ESLint failures:\n${stderr || stdout}`,
      });
    } else {
      resolve({ passed: true, summary: 'Custom ESLint passed.' });
    }
  });
});

```

Now every pre-push executes both the default linter and your custom rules.

### Layer 2 Example – Integrating a Security Scanner (PR Automation)

Block pull requests containing vulnerable dependencies by adding a Layer 2 gate.

Update [`quality-gate-config.yaml`](https://github.com/SynkraAI/aiox-core/blob/main/quality-gate-config.yaml):

```yaml
layer2:
  - name: test
    command: "npm test"
  - name: scan-dependencies
    script: "./.aiox-core/core/quality-gates/dependency-scan.js"
    description: "OWASP Dependency-Check on node_modules"

```

Implement [`.aiox-core/core/quality-gates/dependency-scan.js`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/dependency-scan.js):

```javascript
const { exec } = require('child_process');

module.exports = async () => {
  return new Promise((resolve) => {
    exec('npx retire --outputformat json', (err, stdout) => {
      if (err) {
        resolve({
          passed: false,
          summary: `Dependency scan found issues:\n${stdout}`,
        });
      } else {
        const results = JSON.parse(stdout);
        if (results.length) {
          resolve({
            passed: false,
            summary: `Vulnerable packages detected:\n${JSON.stringify(results, null, 2)}`,
          });
        } else {
          resolve({ passed: true, summary: 'No vulnerable dependencies.' });
        }
      }
    });
  });
};

```

This gate executes automatically after unit tests, preventing merges when security issues exist.

### Layer 3 Example – Creating an Interactive Human Review Checklist

Enforce manual verification steps before merging.

Update [`quality-gate-config.yaml`](https://github.com/SynkraAI/aiox-core/blob/main/quality-gate-config.yaml):

```yaml
layer3:
  - name: checklist
    script: "./.aiox-core/core/quality-gates/manual-checklist.js"
    description: "Require reviewer to confirm checklist items"
    interactive: true

```

Implement [`.aiox-core/core/quality-gates/manual-checklist.js`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/manual-checklist.js):

```javascript
module.exports = async ({ ui }) => {
  const answer = await ui.confirm(
    'Did you verify that the new API follows the security guidelines?'
  );
  return {
    passed: answer,
    summary: answer
      ? 'Reviewer confirmed checklist.'
      : 'Checklist not approved – block merge.',
  };
};

```

When triggered, the **human-review-orchestrator.js** renders the UI prompt inside the AIOX interface. The merge remains blocked until the reviewer confirms the checklist.

## Key Source Files and Extension Points

Understanding these files enables advanced customization:

- **[`.aiox-core/core/quality-gates/quality-gate-config.yaml`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/quality-gate-config.yaml)**: Central declarative configuration where you register all custom gates.
- **[`.aiox-core/core/quality-gates/quality-gate-manager.js`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/quality-gate-manager.js)**: Core orchestrator that loads and executes gates via `require`.
- **[`.aiox-core/core/quality-gates/layer1-precommit.js`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/layer1-precommit.js)**: Built-in pre-commit layer for fast static analysis.
- **[`.aiox-core/core/quality-gates/layer2-pr-automation.js`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/layer2-pr-automation.js)**: Built-in PR automation layer for CI-level checks.
- **[`.aiox-core/core/quality-gates/human-review-orchestrator.js`](https://github.com/SynkraAI/aiox-core/blob/main/.aiox-core/core/quality-gates/human-review-orchestrator.js)**: Handles Layer 3 interactive workflows.
- **[`bin/aiox.js`](https://github.com/SynkraAI/aiox-core/blob/main/bin/aiox.js)**: CLI entry point triggering the `*push` workflow; extend here for manual gate invocation.

## Summary

- **AIOX uses a three-layer architecture** (Pre-Commit, PR Automation, Human Review) controlled by [`quality-gate-config.yaml`](https://github.com/SynkraAI/aiox-core/blob/main/quality-gate-config.yaml) and executed by `QualityGateManager`.
- **Configuration requires two steps**: adding an entry to the YAML config and implementing a Node.js module returning `{ passed, summary }`.
- **Layer 1** uses `command` for shell scripts; **Layer 2** uses `script` for modules; **Layer 3** supports `interactive: true` for UI prompts.
- **All custom gates** automatically integrate with `*push` and `*pre-push` workflows without modifying core framework code.

## Frequently Asked Questions

### What is the exact function signature my custom quality gate must implement?

Your module must export a function that returns a Promise resolving to an object with exactly two properties: `passed` (boolean) and `summary` (string). For Layer 3 interactive gates, the function receives a `{ ui }` object parameter containing UI interaction methods like `confirm()`.

### Can I use shell commands instead of JavaScript modules for custom gates?

Yes. For Layer 1 pre-commit gates, use the `command` key in [`quality-gate-config.yaml`](https://github.com/SynkraAI/aiox-core/blob/main/quality-gate-config.yaml) to specify any shell command. However, Layers 2 and 3 require the `script` key pointing to a JavaScript file to properly handle async execution and UI integration.

### How do I test a custom quality gate locally before committing?

Invoke the gate manually through the AIOX CLI entry point at [`bin/aiox.js`](https://github.com/SynkraAI/aiox-core/blob/main/bin/aiox.js), or require your module directly in a Node.js REPL to verify it returns the expected Promise structure. The `QualityGateManager` loads gates dynamically via `require`, so standard Node.js debugging applies.

### Will custom gates slow down the pre-push workflow?

Execution time depends on your implementation. Layer 1 gates run sequentially before every push, so heavy operations should reside in Layer 2 (PR automation) or Layer 3 (human review) to maintain fast feedback cycles during local development.