GitHub

Enforcement Recipes

Integration recipes for nwave-ai validate-feature-delta across VCS systems, CI providers, IDE environments, and bare Make targets.

Vendor-Neutrality Statement

nwave-ai does NOT auto-install any integration.

You choose where and when the validator runs. Installing nwave-ai (uv tool install nwave-ai, or pipx install nwave-ai as a fallback) gives you a CLI binary and nothing else. No hooks are registered, no CI files are created, no configuration files are modified. Pick the recipe that fits your stack and paste it in — that is the full integration story.

This design is intentional (DD-D14). Teams using Mercurial, Jenkins, bare Make, or no automation at all are first-class citizens alongside GitHub Actions users.


JSON Output Schema (US-07A cross-reference)

Every recipe invokes nwave-ai validate-feature-delta <path>. When your integration needs machine-parseable output, add --format=json:

nwave-ai validate-feature-delta docs/feature/my-feature/feature-delta.md --format=json

JSON output schema (schema_version 1):

{
  "schema_version": 1,
  "results": [
    {
      "check": "E3",
      "severity": "error",
      "file": "docs/feature/my-feature/feature-delta.md",
      "line": 42,
      "offender": "DESIGN decision dropped between DESIGN and DISTILL",
      "remediation": "Re-add the decision or mark it explicitly ratified"
    }
  ]
}

Fields: check (rule ID), severity (error|warn), file (absolute path), line (1-based), offender (the offending text), remediation (human-readable fix hint).

Exit codes: 0 = no violations, 1 = violations found (enforce mode or JSON mode), 2 = usage error, 65 = parse error, 70 = startup probe failure, 78 = misconfiguration.


Trigger Matrix

Trigger event Recipe section
git commit Git + pre-commit, Git + husky, Git + lefthook
git push Git + pre-commit (push stage), Git + husky (pre-push)
Pull request / merge request GitHub Actions, GitLab CI, Jenkins, CircleCI, Bitbucket Pipelines
Scheduled / nightly GitHub Actions (schedule trigger), GitLab CI (pipeline schedules)
Manual one-shot Manual
IDE save VS Code on-save
make target Makefile
Mercurial changegroup Mercurial hgrc

Recipe 1: Git + pre-commit Framework

When it fires: on git commit (pre-commit stage) and optionally on git push (pre-push stage).

Prerequisites: pip install pre-commit and nwave-ai both on PATH.

Add to .pre-commit-config.yaml:

repos:
  - repo: local
    hooks:
      - id: validate-feature-delta
        name: Validate feature-delta (nwave-ai)
        language: system
        entry: nwave-ai validate-feature-delta
        args: []
        files: '^docs/feature/.*feature-delta\.md$'
        pass_filenames: true
        stages: [pre-commit]

For push-time enforcement, change stages: [pre-commit] to stages: [pre-push] or list both.

Install the hook after adding the config:

pre-commit install
# also for push-stage:
pre-commit install --hook-type pre-push

Smoke test: tests/fixtures/recipe-smoke/pre-commit-stanza.yaml validates this stanza as correct YAML with the required repos/hooks structure.


Recipe 2: Git + Husky

When it fires: on git commit (pre-commit) or git push (pre-push), depending on the hook file.

Prerequisites: npm install --save-dev husky and nwave-ai on PATH.

Initialize husky once:

npx husky init

Add a pre-commit hook file at .husky/pre-commit:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# Validate any staged feature-delta.md files
git diff --cached --name-only --diff-filter=ACM | grep 'feature-delta\.md' | while read f; do
  nwave-ai validate-feature-delta "$f" || exit 1
done

For push enforcement instead of commit enforcement, create .husky/pre-push with the same body.


Recipe 3: Git + Lefthook

When it fires: on git commit (pre-commit) or git push (pre-push).

Prerequisites: lefthook installed and nwave-ai on PATH.

Add to lefthook.yml:

pre-commit:
  commands:
    validate-feature-delta:
      glob: "docs/feature/**/feature-delta.md"
      run: nwave-ai validate-feature-delta {staged_files}
      stage_fixed: false

# For push enforcement instead:
# pre-push:
#   commands:
#     validate-feature-delta:
#       glob: "docs/feature/**/feature-delta.md"
#       run: nwave-ai validate-feature-delta {staged_files}

Install the hooks after editing:

lefthook install

Recipe 4: GitHub Actions

When it fires: on pull request (paths filter) and/or push to main/master. Optionally on a schedule.

Prerequisites: nwave-ai installable via pip in the runner environment.

Create .github/workflows/feature-delta.yml:

name: Feature Delta Validation

on:
  pull_request:
    paths:
      - 'docs/feature/**/feature-delta.md'
  push:
    branches: [main, master]
    paths:
      - 'docs/feature/**/feature-delta.md'
  schedule:
    - cron: '0 6 * * 1'   # every Monday at 06:00 UTC (optional nightly/weekly scan)

jobs:
  validate-feature-delta:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install nwave-ai
        run: pip install nwave-ai

      - name: Validate feature deltas
        run: |
          find docs/feature -name "feature-delta.md" | while read f; do
            nwave-ai validate-feature-delta "$f" --enforce
          done

For JSON output piped to a downstream step, add --format=json and capture stdout:

      - name: Validate (JSON output)
        id: validate
        run: |
          nwave-ai validate-feature-delta docs/feature/my-feature/feature-delta.md \
            --format=json > /tmp/delta-report.json || true
          cat /tmp/delta-report.json

Smoke test: tests/fixtures/recipe-smoke/github-actions-workflow.yaml validates this workflow as correct YAML with the required jobs/steps structure.


Recipe 5: GitLab CI

When it fires: on merge request events and/or push to protected branches.

Prerequisites: nwave-ai installable via pip in the CI image.

Add to .gitlab-ci.yml:

validate-feature-delta:
  stage: validate
  image: python:3.11-slim
  script:
    - pip install nwave-ai
    - |
      find docs/feature -name "feature-delta.md" | while read f; do
        nwave-ai validate-feature-delta "$f" --enforce
      done
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - docs/feature/**/feature-delta.md
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
      changes:
        - docs/feature/**/feature-delta.md

For JSON artifacts, add:

  artifacts:
    when: always
    paths:
      - delta-report.json
    reports:
      junit: delta-report.json

Recipe 6: Jenkins

When it fires: as a stage in a Declarative Pipeline (PR builds, main branch builds, or scheduled runs).

Prerequisites: nwave-ai installable via pip in the agent environment or Docker image.

Add to Jenkinsfile:

pipeline {
    agent { label 'python' }

    stages {
        stage('Validate Feature Deltas') {
            steps {
                sh '''
                    pip install --quiet nwave-ai
                    find docs/feature -name "feature-delta.md" | while read f; do
                        nwave-ai validate-feature-delta "$f" --enforce
                    done
                '''
            }
        }
    }
}

For JSON output saved as an artifact:

        stage('Validate Feature Deltas (JSON)') {
            steps {
                sh '''
                    pip install --quiet nwave-ai
                    nwave-ai validate-feature-delta docs/feature/my-feature/feature-delta.md \
                        --format=json > delta-report.json || true
                '''
            }
            post {
                always {
                    archiveArtifacts artifacts: 'delta-report.json'
                }
            }
        }

Recipe 7: CircleCI

When it fires: on every workflow run for the specified branch or tag filters.

Prerequisites: a Docker image with Python, or an orb that provides pip.

Add to .circleci/config.yml:

version: 2.1

jobs:
  validate-feature-delta:
    docker:
      - image: cimg/python:3.11
    steps:
      - checkout
      - run:
          name: Install nwave-ai
          command: pip install nwave-ai
      - run:
          name: Validate feature deltas
          command: |
            find docs/feature -name "feature-delta.md" | while read f; do
              nwave-ai validate-feature-delta "$f" --enforce
            done

workflows:
  feature-delta:
    jobs:
      - validate-feature-delta:
          filters:
            branches:
              only: [main, /feature\/.*/]

Recipe 8: Bitbucket Pipelines

When it fires: on every push to the configured branches.

Prerequisites: a Docker image with Python available.

Add to bitbucket-pipelines.yml:

image: python:3.11-slim

pipelines:
  default:
    - step:
        name: Validate Feature Deltas
        script:
          - pip install nwave-ai
          - |
            find docs/feature -name "feature-delta.md" | while read f; do
              nwave-ai validate-feature-delta "$f" --enforce
            done

  branches:
    main:
      - step:
          name: Validate Feature Deltas (enforce)
          script:
            - pip install nwave-ai
            - |
              find docs/feature -name "feature-delta.md" | while read f; do
                nwave-ai validate-feature-delta "$f" --enforce
              done

Recipe 9: Makefile

When it fires: when a developer or CI job runs make check-feature-delta.

Prerequisites: nwave-ai on PATH, GNU Make available.

Add to Makefile:

# nwave-ai feature-delta enforcement target.
# Usage: make check-feature-delta
#        make check-feature-delta FEATURE_DELTA=docs/feature/my-feature/feature-delta.md

FEATURE_DELTA ?= feature-delta.md

.PHONY: check-feature-delta
check-feature-delta:
    nwave-ai validate-feature-delta $(FEATURE_DELTA)

Run:

make check-feature-delta
# or target a specific file:
make check-feature-delta FEATURE_DELTA=docs/feature/my-feature/feature-delta.md

Smoke test: tests/fixtures/recipe-smoke/Makefile.recipe dry-runs via make -n check-feature-delta to confirm the target parses and invokes nwave-ai.


Recipe 10: VS Code On-Save

When it fires: when you save a feature-delta.md file inside VS Code.

Option A: Run on Save Extension

Install the Run on Save extension, then add to .vscode/settings.json:

{
  "emeraldwalk.runonsave": {
    "commands": [
      {
        "match": "docs/feature/.*feature-delta\\.md$",
        "cmd": "nwave-ai validate-feature-delta '${file}'",
        "runIn": "terminal"
      }
    ]
  }
}

Option B: VS Code Tasks (no extension required)

Add to .vscode/tasks.json:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Validate feature-delta",
      "type": "shell",
      "command": "nwave-ai validate-feature-delta '${file}'",
      "presentation": {
        "reveal": "always",
        "panel": "shared"
      },
      "problemMatcher": []
    }
  ]
}

Trigger manually with Terminal > Run Task > Validate feature-delta while the feature-delta.md file is open.


Recipe 11: Manual One-Liner

When it fires: whenever you choose to run it.

Prerequisites: nwave-ai on PATH (uv tool install nwave-ai, or pipx install nwave-ai as a fallback).

# Validate a single file
nwave-ai validate-feature-delta docs/feature/my-feature/feature-delta.md

# Validate all feature-delta files in the repo
find docs/feature -name "feature-delta.md" | xargs -I{} nwave-ai validate-feature-delta {}

# JSON output (machine-parseable, exit 1 on violations)
nwave-ai validate-feature-delta docs/feature/my-feature/feature-delta.md --format=json

# Enforce mode (exit 1 on violations, error prefix [FAIL])
nwave-ai validate-feature-delta docs/feature/my-feature/feature-delta.md --enforce

No automation. No hooks. No CI configuration. nwave-ai validate-feature-delta works anywhere Python is installed. Users with no Git, no GitHub, and no CI server are first-class.


Recipe 12: Mercurial hgrc

When it fires: on hg commit or hg push via the changegroup or pretxncommit Mercurial hooks.

Prerequisites: nwave-ai on PATH and Mercurial >= 4.0.

Add to .hg/hgrc (repository-local) or ~/.hgrc (user-wide):

[hooks]
# Run before each commit is finalized (pretxncommit fires once per commit)
pretxncommit.validate_feature_delta = python:hgext.validate_feature_delta.hook

# Alternative: pure shell invocation via changegroup (fires once per push)
# changegroup.validate_feature_delta = /bin/sh -c 'find docs/feature -name "feature-delta.md" | xargs -I{} nwave-ai validate-feature-delta {}'

For a simpler shell-only hook (no Python extension needed):

[hooks]
pretxncommit.validate_feature_delta = /bin/sh -c 'find docs/feature -name "feature-delta.md" | xargs -I{} nwave-ai validate-feature-delta {} || exit 1'

This fires on every local commit and blocks it if any feature-delta.md fails validation.


Choosing the Right Recipe

Situation Recommended recipe
Git + Python tooling already in use Recipe 1: pre-commit
Node.js project with husky Recipe 2: husky
GitHub-hosted project Recipe 4: GitHub Actions
GitLab-hosted project Recipe 5: GitLab CI
Jenkins-based CI Recipe 6: Jenkins
CircleCI Recipe 7: CircleCI
Bitbucket Recipe 8: Bitbucket Pipelines
Make-based project Recipe 9: Makefile
VS Code-only workflow Recipe 10: VS Code on-save
No automation at all Recipe 11: Manual
Mercurial repository Recipe 12: Mercurial hgrc