Verification

The verification engine runs acceptance checks defined in acceptance.yaml against the project directory. It answers the question: “Does the implementation comply with the spec?”


Command

intake verify <SPEC_DIR> -p <PROJECT_DIR> [options]
# Verify with terminal report
intake verify specs/user-api/ -p .

# Only checks with tag "api"
intake verify specs/user-api/ -p . -t api -t security

# JUnit format for CI
intake verify specs/user-api/ -p . -f junit > test-results.xml

# Stop at the first failure
intake verify specs/user-api/ -p . --fail-fast

acceptance.yaml Structure

checks:
  - id: check-01
    name: "Unit tests pass"
    type: command
    command: "python -m pytest tests/ -q"
    required: true
    tags: [tests, ci]

  - id: check-02
    name: "Routes file exists"
    type: files_exist
    paths:
      - src/routes.py
      - src/models.py
    required: true
    tags: [structure]

  - id: check-03
    name: "Endpoints have authentication"
    type: pattern_present
    glob: "src/**/*.py"
    patterns:
      - "auth_required|@login_required|verify_token"
    required: true
    tags: [security]

  - id: check-04
    name: "No hardcoded passwords"
    type: pattern_absent
    glob: "src/**/*.py"
    patterns:
      - "password\\s*=\\s*['\"]\\w+"
    required: true
    tags: [security]

The 4 Check Types

command

Runs a shell command and verifies that the exit code is 0.

- id: check-tests
  name: "Tests pass"
  type: command
  command: "python -m pytest tests/ -q"
  required: true
FieldTypeDescription
commandstringShell command to execute

The command runs in the project directory (--project-dir). stdout and stderr are captured (truncated to 1000 and 500 chars respectively).

Timeout: configurable via verification.timeout_per_check (default: 120 seconds).

files_exist

Verifies that all listed files exist.

- id: check-structure
  name: "Main files exist"
  type: files_exist
  paths:
    - src/main.py
    - src/models.py
    - tests/test_main.py
  required: true
FieldTypeDescription
pathslist[string]Paths relative to the project directory

Fails if any of the paths do not exist.

pattern_present

Verifies that regex patterns exist in files matching a glob.

- id: check-logging
  name: "Modules have logging"
  type: pattern_present
  glob: "src/**/*.py"
  patterns:
    - "import logging|import structlog"
  required: false
  tags: [quality]
FieldTypeDescription
globstringGlob pattern to find files (e.g.: src/**/*.py)
patternslist[string]Regex patterns to search for (case-insensitive)

Fails if any pattern is not found in any file matching the glob. That is, it verifies that ALL patterns are present in ALL files.

pattern_absent

Verifies that regex patterns do NOT exist in files matching a glob.

- id: check-no-secrets
  name: "No hardcoded secrets"
  type: pattern_absent
  glob: "src/**/*.py"
  patterns:
    - "API_KEY\\s*=\\s*['\"]sk-"
    - "password\\s*=\\s*['\"]\\w{8,}"
  required: true
  tags: [security]
FieldTypeDescription
globstringGlob pattern to find files
patternslist[string]Regex patterns that must NOT exist (case-insensitive)

Fails if any pattern is found in any file.


Common Fields for Each Check

FieldTypeDefaultDescription
idstring"unknown"Unique identifier for the check
namestringsame as idDescriptive name
typestring"command"Check type: command, files_exist, pattern_present, pattern_absent
requiredbooltrueWhether it is mandatory. Non-required checks can fail without affecting the exit code.
tagslist[string][]Tags for filtering with --tags

Tags and Filtering

Checks can have tags to run subsets:

checks:
  - id: check-tests
    tags: [tests, ci]
    ...
  - id: check-security
    tags: [security, ci]
    ...
  - id: check-docs
    tags: [docs]
    ...
# Only checks with tag "ci"
intake verify specs/my-spec/ -p . -t ci

# Checks with tag "security" OR "tests"
intake verify specs/my-spec/ -p . -t security -t tests

A check runs if it has at least one of the specified tags.


Fail-fast

With --fail-fast, verification stops at the first required check that fails:

intake verify specs/my-spec/ -p . --fail-fast

Checks that were not executed are counted as “skipped” in the report.


Report Formats

Terminal (default)

Rich table with colors:

                    Verification Report: my-spec
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━┓
┃ ID        ┃ Check             ┃ Status ┃ Required ┃ Time   ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━┩
│ check-01  │ Tests pass        │ PASS   │ Yes      │ 1.2s   │
│ check-02  │ Files exist       │ PASS   │ Yes      │ 0.0s   │
│ check-03  │ Auth present      │ FAIL   │ Yes      │ 0.1s   │
└───────────┴───────────────────┴────────┴──────────┴────────┘
  Passed: 2  Failed: 1  Skipped: 0

JSON

intake verify specs/my-spec/ -p . -f json
{
  "spec_name": "my-spec",
  "total_checks": 3,
  "passed": 2,
  "failed": 1,
  "skipped": 0,
  "all_required_passed": false,
  "results": [
    {
      "id": "check-01",
      "name": "Tests pass",
      "passed": true,
      "required": true,
      "output": "3 passed in 1.2s",
      "duration_ms": 1200
    }
  ]
}

JUnit XML

intake verify specs/my-spec/ -p . -f junit > test-results.xml
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
  <testsuite name="my-spec" tests="3" failures="1" skipped="0">
    <testcase name="Tests pass" classname="check-01" time="1.200"/>
    <testcase name="Files exist" classname="check-02" time="0.001"/>
    <testcase name="Auth present" classname="check-03" time="0.100">
      <failure message="Pattern 'auth_required' not found in src/routes.py"/>
    </testcase>
  </testsuite>
</testsuites>

CI/CD Integration

GitHub Actions

name: Verify Spec Compliance
on: [push, pull_request]

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install intake
        run: pip install intake-ai-cli

      - name: Run acceptance checks
        run: intake verify specs/my-feature/ -p . -f junit > test-results.xml

      - name: Upload test results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: test-results
          path: test-results.xml

verify.sh Script (via generic export)

If you use the generic exporter, a standalone verify.sh is generated that does not require intake to be installed:

# Export
intake export specs/my-feature/ -f generic -o output/

# Run directly
./output/verify.sh /path/to/project

Exit Codes

CodeMeaning
0All required checks passed (optional checks may have failed)
1At least one required check failed
2Execution error (spec not found, invalid YAML, etc.)