Skip to main content

MAID Runner

PyPI version Python Version License: MIT

A tool-agnostic validation framework and Python library for the Manifest-driven AI Development (MAID) methodology. MAID Runner validates that code artifacts align with declarative YAML manifests, ensuring architectural integrity in AI-assisted development. Integrates with ArchSpec for spec-to-code pipelines.

Watch the introductory video

Full AI Compiler workflow guide

Why MAID Runner?

LLMs generate code based on statistical likelihood, optimizing for "plausibility" rather than architectural soundness. Without intervention, this leads to "AI Slop" -- code that is syntactically valid but architecturally chaotic.

MAID Runner enforces three-stream validation:

  • Acceptance (WHAT): Immutable tests from specifications define system behavior
  • Structural (SKELETON): AST-level verification that code matches manifest contracts
  • Unit (HOW): Implementation-level tests verify internal correctness

This transforms AI from a "Junior Developer" requiring reactive code review into a "Stochastic Compiler" that translates rigid specifications into implementation details.

Full philosophy documentation

Supported Languages

Language Extensions Parser Key Features
Python .py AST (built-in) Classes, functions, methods, attributes, type hints, async/await, decorators
TypeScript/JS .ts, .tsx, .js, .jsx tree-sitter Classes, interfaces, type aliases, enums, namespaces, generics, JSX/TSX; React and Angular through TypeScript-backed parsing
Svelte .svelte tree-sitter Components, props, exports, script blocks, reactive statements

Validator Plugins

For language requests, use the validator plugin path instead of adding new in-tree parsers to this repository. See docs/validator-plugin-authoring.md for the plugin contract, maid_runner.validators entry-point packaging, conformance kit usage, maid validators audit command, and support boundary.

Quick Start

macOS / Linux:

curl -LsSf https://maidrunner.dev/install.sh | sh

Windows PowerShell:

irm https://maidrunner.dev/install.ps1 | iex

Then, inside your project:

maid init
maid howto quickstart

That is the whole starting path. maid howto opens the guided topics, and each topic ends by pointing at the next one. Adding MAID to a codebase that already exists starts at Brownfield Onboarding.

Alternative installation methods

Already use uv?

uv tool install maid-runner

Already have Python 3.10+?

pip install maid-runner

Pin an exact release on macOS or Linux:

curl -LsSf https://maidrunner.dev/install.sh | sh -s -- --version 2.25.0

Installation

The bootstrap installers use uv internally and install the core Python validator. For all language and quality extras, use uv tool install "maid-runner[all]"; typescript, svelte, quality, and watch can be selected the same way.

Claude Code Plugin

/plugin marketplace add aidrivencoder/claude-plugins
/plugin install maid-runner@aidrivencoder

Multi-Tool Support

maid init                        # Claude Code (default)
maid init --tool codex           # Codex repo skills
maid init --tool cursor          # Cursor IDE
maid init --tool windsurf        # Windsurf IDE
maid init --tool generic         # Generic MAID.md

Commit-Time MAID Verification

maid init creates or safely updates a MAID-managed block in .pre-commit-config.yaml while it preserves existing hooks, comments, formatting, and other project configuration. The managed hook runs:

maid verify --profile pre-commit --since HEAD

This generated command requires maid-runner>=2.25.0. A newer global init must not be mixed with a project hook that deliberately resolves an older runner; refresh the runner used by the hook before regenerating the configuration. The profile is gate-equivalent to the v2.24 expansion, retained for auditability:

maid verify --summary --advisory --allow-empty --require-plan-lock --require-red-evidence --fail-fast --no-changed-scope --file-tracking-scope task --plan-lock-scope task --since HEAD

MAID provisions the project configuration but does not replace or activate Git hooks. For a standard pre-commit setup, run pre-commit install. If Git core.hooksPath points to a global hook directory, keep that dispatcher and have it invoke the repository's pre-commit configuration instead of replacing the global hook.

Repo-Level Claude Install

Use maid init --tool claude inside shared repositories as a repo-level Claude install for the MAID-only Claude skills, implementation-review agent, and marked CLAUDE.md guidance. The .claude/skills source payload includes the current MAID workflow skills for planning, plan review, implementation, implementation review, evolution, auditing, and incident logging.

Repo-Level Codex Install

Use maid init --tool codex inside repositories that should receive the repo-owned Codex MAID skills. It installs .codex/manifest.json, the distributed .codex/skills payload, skill-local agent metadata, and a marked MAID Runner section in AGENTS.md.

CLI Reference

Command Purpose Key Options
maid validate [manifest] Validate manifest against code --mode schema|behavioral|implementation, --artifact-coverage, --no-chain, --coherence, --file-tracking, --worktree-scope, --changed-scope, --json, --packet [path], --watch, --watch-all
maid validators List discovered validator records for auditability --json
maid test Run validation commands from manifests --manifest <path>, --jobs N, --watch, --watch-all, --fail-fast, --json
maid pgtap -- <psql arguments> Run a file-backed pgTAP script with MAID-safe red-phase exit semantics Requires -f/--file; forces ON_ERROR_STOP=1; explicit pgTAP assertion failures exit 1 and infrastructure/setup failures exit 2
maid verify Run the combined done gate --profile handoff|pre-commit|agent-retry|deep, --summary, --strict, --advisory, --file-tracking-scope repository|task, --plan-lock-scope repository|task, --artifact-coverage, --knockout, --knockout-limit N, --knockout-allow-dirty, --require-plan-lock, --require-red-evidence, --worktree-scope, --changed-scope, --no-changed-scope, --since, --base-ref, --test-jobs N, --json, --packet [path]
maid assess Recommend an advisory verify profile from deterministic change signals --since, --base-ref, --json
maid plan lock|revise|status <manifest> Tamper-evident plan locks over a manifest and its behavioral tests --legacy-baseline --reason (tracked legacy lock), --reason (revise), --stash-implementation, --preserve-red-evidence, --json (status), --project-root
maid task start|stop|status Manage the active task manifest pointer in .maid/active-manifest start <manifest-path>, status --json
maid hook scope-check Check whether a file path is inside the active task manifest scope --path <file-path>, --stdin, --strict
maid benchmark [project ...] Run local benchmark timings for MAID validation gates --manifest-dir, --command-prefix, --repeat, --json-output, --markdown-output, --json
maid incident capture|update|list Store and review caller-asserted gaming incident records capture --manifest <path> --packet <path> --rejected-diff <path> --tags <comma-list>, update <incident-path> --chosen-diff <path>, list --tag <tag> --json
maid snapshot <file> Generate manifest from existing code --output-dir, --output, --with-tests, --force, --dry-run, --json
maid snapshot-system Aggregate all active manifests --output, --manifest-dir
maid bootstrap [directory] Bootstrap manifests or rank brownfield coverage work --rank, --model legacy-v1|risk-v1, --limit, --explain, --deep, --output-dir, --exclude, --include-private, --dry-run, --json
maid learn Refresh the deterministic Outcome index --manifest-dir, --output, --include-status, --json, --quiet
maid recall Search the deterministic Outcome index --text, --tag, --path, --artifact, --validation-command, --manifest-slug, --allow-stale-index, --json
maid insights Aggregate deterministic Outcome insights --index, --manifest-dir, --allow-stale-index, --limit, --json
maid feedback export Write explicitly marked Outcome lessons to a local-only MAID Runner feedback bundle --index, --output, --manifest-dir, --project-root, --allow-stale-index, --force, --json
maid feedback aggregate Validate and aggregate local MAID Runner feedback bundles into an advisory intake report <bundle>..., --output, --force, --json
maid enrich prompt|validate|render Build and verify deterministic Outcome enrichment artifacts --index, --digest, --md-output, --output, --allow-stale-index, --json
maid evaluate run <manifest> Report deterministic after-action run evidence; see docs/run-evaluation.md --project-root, --json, --quiet
maid manifests <file> List manifests referencing a file --manifest-dir, --quiet
maid files Show file tracking status --manifest-dir, --fail-on undeclared|registered|scope-only|any, --quiet
maid graph Knowledge graph operations query, export, analyze
maid coherence Run coherence checks --checks, --exclude, --json
maid schema Display manifest JSON Schema
maid audit supersessions Audit supersession artifact preservation --manifest-dir, --seal, --unseal, --lock, --json, --quiet
maid init Initialize MAID in project --tool claude|codex|cursor|windsurf|generic|auto
maid howto Interactive methodology guide --section quickstart|create|validate|workflow|commands|brownfield|snapshot|migrate|troubleshooting|serve
maid manifest create <file> Create manifest for a file --goal, --artifacts, --dry-run
maid chain log Show manifest event log --until-seq N, --version-tag TAG, --active, --json
maid chain replay Preview effective artifacts at a point in time --until-seq N, --version-tag TAG, --json
maid serve Run a long-lived validator daemon over a Unix socket --socket, --pidfile, --project-root, --client-timeout
maid daemon ping|validate|verify Diagnostic client for a running daemon --transport auto|unix|tcp, --runtime-dir, --socket, --timeout, --json
maid skills install Install the user-level maid-onboard skill into ~/.claude and ~/.codex --user, --link, --target-root <dir>

General exit codes: 0 = success, 1 = validation failure or internal error, 2 = usage error. Command-specific contracts can define narrower meanings. For example, maid hook scope-check exits 2 for a denied scope decision. Use --quiet for automation.

Failure Packets For Agent Retries

Agent retry loops can run gates with packet output:

maid validate --packet
maid verify --packet

Each packet-aware gate writes a failure packet only when the run fails with exit code 1. A passing run creates no packet at a missing path. If the path already contains a recognizable MAID packet, the gate safely clears it in place as a version-1 marker with exit_code: 0 and empty manifest, diagnostics, and test_output sections. Consumers must use the gate result and packet exit_code; never infer failure from the packet path's existence. An unsafe pre-existing destination is preserved, and a passing gate exits 2 because its requested packet state could not be cleared. Passing --packet without a path uses .maid/last-failure-packet.json.

On failure, read the packet before retrying. It includes the failed command, exit code, project root, failed manifest excerpts, diagnostics with next_action, failed-command output tails, and environment versions. Retry loops should respect next_action kinds, stay within manifest scope, and stop at the documented attempt bound instead of silently weakening tests or manifests.

Edit-Time Scope Enforcement

MAID can expose the active implementation contract to editor and agent hooks so out-of-scope writes are rejected before handoff. After promoting a draft manifest, start the task pointer:

maid task start manifests/<slug>.manifest.yaml

At handoff, after implementation review and Outcome capture, clear the pointer idempotently:

maid task stop

The active task resolver uses MAID_ACTIVE_MANIFEST first, then the single-line .maid/active-manifest file written by maid task start, and then falls back to no active task. maid task status --json reports the resolved path and whether it came from the environment, the file, or no active task.

Hook integrations call maid hook scope-check --path <file-path> or pipe an agent event object to maid hook scope-check --stdin with a JSON {"path": "..."} payload. The command prints one JSON decision object:

{"decision": "allow"|"deny", "reason": "...", "active_manifest": "..."}

It exits with exit code 0 for allow, 2 for deny, and 1 for internal errors. With no active task, the default fail-open policy allows the write with reason no-active-task; broken hook execution also fails open so an interactive editor is not bricked. Locked-down autonomous loops should pass --strict, which turns both no-active-task and internal-error outcomes into denies.

With an active task, the hook allows the manifest's files.create, files.edit, files.scope, and files.delete paths, the active manifest file, declared test files, and paths under manifests/drafts/. Other paths are denied with a reason naming the active manifest and nearby declared scope entries. The hook is fast advisory infrastructure only: maid verify changed-scope checks remain the authoritative handoff evidence, and hook decisions do not add ErrorCode entries.

Hook wiring is installed by maid init payloads. Claude receives PreToolUse settings for write/edit tool events. Cursor receives hooks.json, and Codex receives managed AGENTS.md guidance for the same pre-edit decision semantics.

Run maid howto --section commands for detailed usage and examples. For common failure modes, see docs/troubleshooting.md or run maid howto --section troubleshooting.

Common Workflows

# Validate all manifests (chains enabled by default)
maid validate

# Validate a single manifest
maid validate manifests/add-auth.manifest.yaml

# Validate without chain merging
maid validate manifests/add-auth.manifest.yaml --no-chain

# Validate behavioral tests
maid validate manifests/add-auth.manifest.yaml --mode behavioral

# End the approved planning loop with a tamper-evident plan lock
maid plan lock manifests/add-auth.manifest.yaml

# Validate with coherence checks
maid validate --coherence

# TDD watch mode (single manifest)
maid test --manifest manifests/add-auth.manifest.yaml --watch

# Multi-manifest watch (entire codebase)
maid test --watch-all

# Run all validation commands
maid test

# Branch handoff gate for humans, CI, and AI agents
maid verify --base-ref <parent-branch>

# Compact handoff output; use --advisory on brownfield trees when warnings
# should be reported without failing verification stages
maid verify --summary
maid verify --summary --advisory

# Implementation handoff gate requiring the approved plan lock and red phase
maid verify --require-plan-lock --require-red-evidence

# The same gate by name; --profile handoff expands to
# --summary --require-plan-lock --require-red-evidence, and the applied
# profile and its flags are reported in the output
maid verify --profile handoff
maid assess --base-ref origin/main

# Opt-in Python-only constraint evidence gates for high-risk review
maid validate --artifact-coverage manifests/add-auth.manifest.yaml
maid verify --artifact-coverage --knockout

# Brownfield onboarding: prioritize incomplete coverage before adding contracts
maid bootstrap --rank --model risk-v1 --limit 20

# Draft a manifest from one implemented change; choose exactly one baseline
maid manifest from-diff --since <commit> --slug describe-the-change
maid manifest from-diff --base-ref <parent-branch> --slug describe-the-change
maid manifest from-diff --worktree --slug describe-the-change

# JSON output for CI/CD
maid validate --json

# Audit supersession drops and seal current legacy drops
maid audit supersessions --manifest-dir manifests --json
maid audit supersessions --manifest-dir manifests --seal

Plan Locks And Red-Phase Evidence

maid plan lock <manifest> seals the approved manifest and its behavioral test files after the planning loop passes behavioral validation and the user approves the plan. maid plan revise <manifest> --reason "<text>" records intentional plan changes with a required reason, and maid plan status <manifest> reports lock state, hash matches or mismatches, and red evidence.

If implementation review adds or tightens behavioral tests after implementation is already present, use maid plan revise <manifest> --reason "<text>" --stash-implementation. The command stashes only declared non-test implementation files, leaves the revised manifest and behavioral tests in place, captures fresh red evidence, restores the implementation changes, and saves the revised lock only when the evidence is valid red.

Red-phase evidence uses exit-code-only classification: pytest exit 1 is valid red, exits 2/3/4/5 are invalid, and exit 0 means the tests already pass and are not red. maid plan lock --no-run records red_evidence: null.

For a completed tracked manifest that predates plan locks, use maid plan lock <manifest> --legacy-baseline --reason "<text>". This records a separate, auditable green legacy baseline while leaving red_evidence: null; it never claims that historical red evidence exists. The migration is accepted by the strict red-evidence gate only after MAID verifies that the manifest existed at Git HEAD, no implementation or test paths are dirty, its artifact/file contract is unchanged, prior validate argv is retained or extended only with discovered behavioral-test paths after a non-option token, current validation is green, and validation did not mutate contract files. The new lock is published exclusively, so validation or a concurrent process cannot overwrite the destination during evidence capture.

Plan-lock enforcement is opt-in. The implementation handoff command maid verify --require-plan-lock --require-red-evidence scopes requirement errors to the task window: E700 PLAN_LOCK_MISSING, E704 RED_PHASE_EVIDENCE_MISSING, and E705 RED_PHASE_EVIDENCE_INVALID apply to active manifests whose manifest file changed in the verify run. E704 also applies when an in-scope manifest has no plan lock under --require-red-evidence. Integrity errors apply regardless of task-window scope: E701 BEHAVIORAL_TEST_MODIFIED_AFTER_LOCK, E702 MANIFEST_CONTRACT_WEAKENED_AFTER_LOCK, E703 PLAN_LOCK_STALE, and E706 PLAN_LOCK_UNREADABLE.

Constraint Evidence Gates

maid verify --artifact-coverage and maid validate --artifact-coverage run the manifest's pytest-based validate: commands under coverage.py and fail when a declared Python public function, method, or class body is never executed by the tests. The gate is opt-in and Python-only. Attribute artifacts are excluded, and a class passes when any declared method on the class executes. Install the optional quality extra with maid-runner[quality]; requesting the gate without that extra fails closed with E307 semantics instead of silently skipping the evidence check. Artifact-coverage subprocesses have a finite 15-minute default that repositories can adjust with a positive number of seconds in .maidrc.yaml:

artifact_coverage:
  timeout_seconds: 900

maid verify --knockout is an opt-in Python-only gate that replaces each declared public function or method body with raise NotImplementedError("maid-knockout"), runs the manifest's validate commands, and restores the source file with hash verification. Use --knockout-limit to bound the number of artifacts tested and --knockout-allow-dirty when a reviewed workflow deliberately allows dirty target files. Knockout runs in manifest declaration order and is not full mutation testing; it checks one bounded failure mode rather than promising general mutation coverage.

CI/CD Integration

Use CI/CD Integration for GitHub Actions, GitLab CI, Jenkins, CircleCI, and generic pipeline examples that run maid verify, maid test --json, and publish .maid/ JSON reports. GitHub users can also start from the dedicated GitHub Actions guide.

File Tracking

When validating with manifest chains (default), MAID Runner reports file compliance status:

  • UNDECLARED: Files not in any manifest (no audit trail)
  • REGISTERED: Files tracked but incomplete (missing artifacts/tests)
  • SCOPE_ONLY: Files writable through files.scope without an artifact contract
  • TRACKED: Files with full MAID compliance

files.scope is write authorization, not proof of artifact coverage. Scope-only files remain valid for route wiring, configuration, generated derivatives, and other implementation surfaces without stable public artifacts, but they appear in their own inventory bucket. Use maid files --fail-on scope-only or maid verify --fail-on-scope-only when a repository or CI boundary requires every production file to have an artifact contract. maid files --fail-on any also includes scope-only files.

During normal verification, repository-wide file tracking remains the default for maid verify. During incremental brownfield adoption, scope only the verify file-tracking stage to an explicit task window:

maid verify --file-tracking-scope task --base-ref <parent-branch>
maid verify --file-tracking-scope task --since <task-start-commit>

Task scope still blocks changed undeclared or weakly registered production files; it only omits untouched historical inventory from that verify stage. Use maid files whenever you need the full repository inventory. The --advisory and --no-changed-scope options do not disable file tracking.

Changed-Scope Handoff Gate

maid verify runs changed-scope by default. Use it at branch handoff, review, and CI boundaries to close the loophole where a file changed during the task is listed only under files.read after the edit has already been committed. Callers must opt out explicitly with --no-changed-scope.

Recommended branch review command:

maid verify --base-ref <parent-branch>

Use --base-ref for stacked branches because MAID compares from git merge-base <parent-branch> HEAD to the current working tree. Use --since <commit-ish> when the exact task baseline is known:

maid validate --changed-scope --since <task-start-commit>
maid verify --since <task-start-commit>

The baseline can also be recorded in active manifests:

metadata:
  maid_task_base: <task-start-commit>

When maid verify runs without --since, --base-ref, or an unambiguous metadata.maid_task_base, MAID fails closed with E115 instead of guessing main, master, dev, development, or a remote branch. Git does not retain a reliable branch-origin fact after rebases and merges, and a default commit count can miss task changes, so the baseline must be real evidence supplied by the caller or manifest. files.read never grants write permission; changed source files must be declared in files.create, files.edit, files.scope, or files.delete. Use files.scope for changed route-wiring or prop-only files without public artifact contracts, including Svelte route files whose behavior is covered through tests but whose local state and handlers should not be declared as public artifacts. Use --include-tests when the handoff should also enforce changed test files.

Use --worktree-scope for fast live checks of uncommitted local changes. Use maid verify for branch handoff because changed-scope checks committed, staged, unstaged, and untracked files since the task baseline by default. Use maid validate --changed-scope only when you want the lower-level validate command to run the same gate explicitly.

Brownfield Onboarding

Brownfield entry: prioritize coverage risk, then generate reviewed drafts per change.

For existing projects, start with a ranked adoption pass instead of bulk snapshotting every file:

maid bootstrap --rank --model risk-v1 --limit 20
maid bootstrap --rank --model risk-v1 --explain src/auth/session.py
maid bootstrap --rank --model risk-v1 --json

The deterministic risk-v1 model ranks undeclared, read-only, and writable files without artifact contracts using coverage gap, production blast radius, recent change pressure, repository-relative complexity, and test evidence. Every contribution includes its raw value, confidence, and evidence. Test imports remain separate from production dependency reachability. Missing history or validator evidence lowers confidence and receives a conservative contribution instead of being treated as zero risk.

legacy-v1 remains the default for compatibility in this release:

maid bootstrap --rank --model legacy-v1 --limit 20

It preserves the original lexicographic ordering by lifetime churn, then inbound_refs, then public_artifacts. Use risk-v1 for new brownfield adoption planning.

Repository owners can set explicit priority floors and entrypoints in .maidrc.yaml. Floors change the displayed priority band but never the numeric score:

coverage_recommendation:
  critical_paths:
    - pattern: "src/auth/**"
      minimum_priority: high
    - pattern: "src/payments/**"
      minimum_priority: critical
  entrypoints:
    - src/main.py
  cache: true
  deep:
    command: [python, -m, pytest, tests, -q]

Static reports are cached at .maid/cache/coverage-risk-v1.json using the repository HEAD and content fingerprints for source, manifests, configuration, Outcomes, and incidents. --deep bypasses this cache, requires the configured Python pytest command, and replaces the four-point static test-reference signal with executed pytest-cov evidence. Outcome and incident matches are advisory zero-point context and cannot change ordering.

Onboard the top files one at a time. For an implemented change, generate a draft contract from the diff:

maid manifest from-diff --base-ref <parent-branch> --slug describe-the-change

maid manifest from-diff requires exactly one of --since <commit>, --base-ref <ref>, or --worktree; MAID does not guess a baseline. Generated manifests land in manifests/drafts/ with metadata.needs_review: true, so the author reviews the draft, replaces the goal placeholder, fills any placeholder artifacts, clears needs_review, and then promotes through the draft workflow.

Manifest Structure (v2 YAML)

schema: "2"
goal: "Implement email validation"
type: feature
files:
  create:
    - path: validators/email_validator.py
      artifacts:
        - kind: class
          name: EmailValidator
        - kind: method
          name: validate
          of: EmailValidator
          args:
            - name: email
              type: str
          returns: bool
  read:
    - tests/test_email_validation.py
validate:
  - pytest tests/test_email_validation.py -v

V1 JSON manifests are auto-converted when loaded.

Validation Modes

Mode Files Behavior
Strict files.create Implementation must EXACTLY match declared artifacts
Permissive files.edit Implementation must CONTAIN declared artifacts
Scope-only files.scope File is writable for scope gates without public artifact validation

Artifact Kinds

Common: class, function, method, attribute, enum

TypeScript-specific: interface, type, namespace

For Python, a direct subclass of a standard-library enum.Enum, IntEnum, StrEnum, Flag, or IntFlag base is represented by one kind: enum artifact. Direct imports and import enum aliases are supported; enum members are covered by the enum artifact and are not declared separately. Existing snapshots that represent Python enums as a class plus attributes remain valid.

Angular TypeScript Boundary

Angular source files are supported as TypeScript files. MAID Runner collects decorated classes, fields, methods, and signal-style input() / output() fields through TypeScriptValidator; Angular decorator names and decorator metadata are not public MAID artifacts.

Required-import validation uses the same TypeScript import scanner for Angular standalone component imports and lazy import() route modules. Third-party imports such as @angular/core remain package imports and do not satisfy project-local required imports.

maid snapshot tracks literal Angular templateUrl, styleUrl, and styleUrls companion files in files.read when those files exist. Template HTML and CSS/SCSS contents are tracked as file boundaries, not parsed into Angular artifacts.

React TypeScript Boundary

React .tsx and .jsx files are supported through TypeScriptValidator. MAID Runner collects ordinary TypeScript artifacts such as function components, typed const components, custom hooks, provider functions, props interfaces, and props type aliases. It also recognizes common inline wrapper exports using memo, React.memo, forwardRef, React.forwardRef, and anonymous default-exported arrow components as function artifacts.

Required-import validation uses TypeScript import identity for React tests and components, including Testing Library test files, barrel imports, React.lazy(() => import(...)), path aliases from tsconfig.json, and local CSS module imports. Package imports such as react, react-dom, and @testing-library/* remain external package imports and do not satisfy project-local required imports.

maid snapshot tracks existing relative style and static asset imports from React TSX/JSX files in files.read, including CSS modules, side-effect stylesheets, SVGs, and other non-code assets. MAID Runner does not parse CSS, assets, DOM behavior, React runtime semantics, React Native, Next.js, Remix, Vite, or bundler-specific behavior as MAID artifacts.

Manifest Event Log

MAID Runner v2.4.0 introduces an event-log system for tracking manifest history:

schema: "2"
goal: "Add user authentication"
type: feature
sequence_number: 42         # optional — deterministic ordering
version_tag: "v2.4.0"       # optional — release label

Inspect the event log:

maid chain log                    # Full history (includes superseded)
maid chain log --until-seq 10     # Up to sequence 10
maid chain log --version-tag v2.4.0 --json
maid chain log --active           # Active manifests only

Preview artifact state at a point in time:

maid chain replay --until-seq 10 --json
maid chain replay --version-tag v2.4.0

The event log provides deterministic ordering via sequence_number (falls back to created), includes superseded manifests in the historical record, and supports point-in-time queries through event_log_until() and replay_until() APIs.

Supersession Artifact Preservation

When manifest A supersedes manifest B, MAID Runner audits every public artifact declared by B. Each superseded artifact must be accounted for by A in one of three ways:

  • Re-declare the artifact in A for the same file path.
  • List the artifact's file under A's files.delete and ensure the file is gone.
  • Declare the artifact under A's removed_artifacts and ensure the symbol is absent from the current source file.

If a replacement manifest drops artifacts without one of those structural signals, maid validate reports E110 ARTIFACT_DROPPED_BY_SUPERSESSION. This prevents a supersession from silently shrinking the validation surface.

Use the dedicated audit command to inspect these drops:

maid audit supersessions --manifest-dir manifests
maid audit supersessions --manifest-dir manifests --json

Brownfield repositories can seal existing legacy drops once:

maid audit supersessions --manifest-dir manifests --seal

This writes .maid/legacy-grandfathered.lock. The lock records each legacy drop by superseding slug, superseding manifest content hash, superseded slug, file path, and artifact key. After the lock exists, matching legacy drops are reported as E111 GRANDFATHERED_SUPERSESSION info entries. New drops, or drops from an edited superseding manifest whose content hash changed, are not covered by the lock.

Re-sealing a repository with an existing sealed lock is blocked unless --unseal is passed:

maid audit supersessions --manifest-dir manifests --seal --unseal

Treat --unseal as a deliberate migration action. It should be visible in review because it can add or replace grandfathered drops.

To intentionally remove an artifact while superseding a manifest, declare it in removed_artifacts:

schema: "2"
goal: "Replace old auth helper"
type: refactor
supersedes:
  - add-old-auth-helper
removed_artifacts:
  - kind: function
    name: old_auth_helper
    file: src/auth/helpers.py
    reason: "Replaced by AuthService.authenticate"
files:
  edit:
    - path: src/auth/service.py
      artifacts:
        - kind: class
          name: AuthService
validate:
  - pytest tests/auth/test_service.py -v

removed_artifacts is not trusted as self-attestation. Implementation validation verifies that the named symbol is absent from the referenced file and reports E311 REMOVED_ARTIFACT_STILL_PRESENT if it is still defined, the file cannot be parsed, the path escapes the project root, or no validator can inspect that file type.

Validator Daemon (maid serve)

A long-lived local daemon that exposes the validator over a Unix socket so AI agents, editor integrations, and tight TDD loops can validate manifests without paying Python startup per call. NDJSON protocol, repo-bound project root, locked-down socket permissions.

maid serve --socket .maid/serve.sock --pidfile .maid/serve.pid

Use maid_runner.daemon.client.DaemonClient with resolve_daemon_endpoint() for long-lived agent or editor integrations. The maid daemon ping|validate|verify command is a diagnostic wrapper around that client for checking a running daemon from the shell; it still starts a fresh CLI process for each call, so it is not the daemon performance path for tight loops.

See docs/maid-serve.md for protocol, methods, security defaults, and example client.

Development Workflow

Phase 1: Goal Definition

Define the high-level feature or bug fix.

Phase 2: Planning Loop

  1. Create manifest: maid manifest create <file> --goal "Description"
  2. Create behavioral tests in tests/
  3. Validate: maid validate <manifest> --mode behavioral
  4. Iterate until validation passes

For larger batches, use draft manifests as the planning queue: keep mutable planning inventory in manifests/drafts/, promote one implementation-sized draft into manifests/, then implement and validate the promoted path. See Draft Manifest Workflow.

Phase 3: Implementation Loop

  1. Implement code per manifest
  2. Validate: maid validate <manifest>
  3. Run tests: maid test --manifest <manifest>
  4. Iterate until all tests pass

Phase 4: Integration

Verify complete chain: maid validate and maid test pass for all active manifests.

Library API

MAID Runner provides a Python library API for direct integration with tools, CI/CD, and custom scripts.

Basic Validation

from maid_runner import validate, validate_all

# Validate a single manifest
result = validate("manifests/add-auth.manifest.yaml")
if result.success:
    print("All checks passed")
else:
    for error in result.errors:
        print(f"{error.code.value}: {error.message}")

# Validate all manifests in directory
batch = validate_all("manifests/")
print(f"{batch.passed}/{batch.total_manifests} passed")

Manifest Chain Operations

from maid_runner import ManifestChain

chain = ManifestChain("manifests/")

for m in chain.active_manifests():
    print(f"{m.slug}: {m.goal}")

artifacts = chain.merged_artifacts_for("src/auth/service.py")

Loading and Saving Manifests

from maid_runner import load_manifest, save_manifest

manifest = load_manifest("manifests/add-auth.manifest.yaml")  # YAML v2 or JSON v1
print(manifest.goal)
save_manifest(manifest, "manifests/copy.manifest.yaml")

Snapshot Generation

from maid_runner import generate_snapshot

manifest = generate_snapshot("src/auth/service.py")
print(f"Found {len(manifest.all_file_specs[0].artifacts)} artifacts")

JSON Output for Tool Integration

from maid_runner import validate

result = validate("manifests/add-auth.manifest.yaml")
print(result.to_json())  # Structured JSON output

Custom Validator Registration

from maid_runner import ValidatorRegistry, BaseValidator, CollectionResult

class GoValidator(BaseValidator):
    @classmethod
    def supported_extensions(cls):
        return (".go",)

    def collect_implementation_artifacts(self, source, file_path):
        return CollectionResult(artifacts=[], language="go", file_path=str(file_path))

    def collect_behavioral_artifacts(self, source, file_path):
        return CollectionResult(artifacts=[], language="go", file_path=str(file_path))

ValidatorRegistry.register(GoValidator)

MAID Ecosystem

Tool Purpose
MAID Agents Automated workflow orchestration using Claude Code agents
MAID Runner MCP MCP server exposing validation to AI agents
MAID LSP Language Server Protocol for real-time IDE validation
MAID for VS Code VS Code/Cursor extension with manifest explorer and diagnostics
Claude Plugins Plugin marketplace including MAID Runner
ArchSpec AI-powered spec generation with MAID manifest export

Development Setup

# Install dependencies
uv sync
uv sync --group dev

# Run tests
uv run python -m pytest tests/ -v

# Code quality
make format      # Auto-fix formatting
make lint        # Check style
make type-check  # Type checking

Project Structure

maid-runner/
├── docs/                    # Documentation
├── manifests/               # Active task manifests (YAML v2)
│   └── drafts/              # Mutable draft manifest queue
├── tests/
│   ├── core/                # Core module tests
│   ├── validators/          # Validator tests
│   ├── coherence/           # Coherence check tests
│   ├── graph/               # Knowledge graph tests
│   ├── compat/              # Compatibility tests
│   ├── cli/                 # CLI tests
│   ├── integration/         # Integration tests
│   └── e2e/                 # End-to-end tests
├── maid_runner/
│   ├── core/                # Manifest loading, validation, chain, types
│   ├── validators/          # Language-specific artifact collectors
│   ├── graph/               # Knowledge graph (manifest relationships)
│   ├── coherence/           # Architectural coherence checks
│   ├── compat/              # V1 JSON backward compatibility
│   ├── cli/commands/        # CLI command modules
│   └── schemas/             # JSON Schema (v1, v2)
├── examples/                # Example scripts
└── .claude/                 # Claude Code configuration

Testing

uv run python -m pytest tests/ -v                    # All tests
uv run python -m pytest tests/core/ -v               # Core tests
uv run python -m pytest tests/validators/ -v          # Validator tests
maid test                                            # MAID validation commands

Requirements

  • Python 3.10+
  • Core: jsonschema, pyyaml
  • Optional: tree-sitter, tree-sitter-typescript (TypeScript/JS and Angular .ts support), tree-sitter-svelte (Svelte support)
  • Dev: black, ruff, mypy, pytest

Contributing

This project dogfoods MAID methodology. All changes require:

  1. A manifest in manifests/
  2. Behavioral tests in tests/
  3. Passing structural validation
  4. Passing behavioral tests

Use manifests/drafts/ for mutable planned work that has not been promoted into the active manifest chain yet.

See CONTRIBUTING.md and CLAUDE.md for guidelines.

License

MIT License. See LICENSE for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

maid_runner-2.26.0.tar.gz (576.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

maid_runner-2.26.0-py3-none-any.whl (613.6 kB view details)

Uploaded Python 3

File details

Details for the file maid_runner-2.26.0.tar.gz.

File metadata

  • Download URL: maid_runner-2.26.0.tar.gz
  • Upload date:
  • Size: 576.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for maid_runner-2.26.0.tar.gz
Algorithm Hash digest
SHA256 a595ae69ed4e8939ce04c6f71089fd2492b460187499bdb695964595c2ad870d
MD5 de083d2f1ec4b8ae9c98c188c2ee33ec
BLAKE2b-256 c2acaf4a6fd839fafd1614d78a63900b1fb2106f4be60f75caac0308cde57d59

See more details on using hashes here.

Provenance

The following attestation bundles were made for maid_runner-2.26.0.tar.gz:

Publisher: publish.yml on mamertofabian/maid-runner

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file maid_runner-2.26.0-py3-none-any.whl.

File metadata

  • Download URL: maid_runner-2.26.0-py3-none-any.whl
  • Upload date:
  • Size: 613.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for maid_runner-2.26.0-py3-none-any.whl
Algorithm Hash digest
SHA256 00e5006f87c2b344882f4ee6e16f900f69303b5573e92f9a7a038a1cc3426a19
MD5 ca2c5a269fee3292465dee8448a54088
BLAKE2b-256 223aa5b2135944708189d466b156dfa4fca5d2ad2d71ef2556c47be9cb45460b

See more details on using hashes here.

Provenance

The following attestation bundles were made for maid_runner-2.26.0-py3-none-any.whl:

Publisher: publish.yml on mamertofabian/maid-runner

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

2.27.1

2 files

2.27.0

2 files

This release

2.26.0 This release

2 files

2.25.0

2 files

2.24.0

2 files

2.23.2

2 files

2.23.1

2 files

2.23.0

2 files

2.22.0

2 files

2.21.1

2 files

2.21.0

2 files

2.20.0

2 files

2.19.1

2 files

2.19.0

2 files

2.18.0

2 files

2.17.1

2 files

2.17.0

2 files

2.16.3

2 files

2.16.2

2 files

2.16.1

2 files

2.16.0

2 files

2.15.0

2 files

2.14.0

2 files

2.13.0

2 files

2.12.0

2 files

2.11.0

2 files

2.10.1

2 files

2.10.0

2 files

2.9.4

2 files

2.9.3

2 files

2.9.2

2 files

2.9.1

2 files

2.9.0

2 files

2.8.3

2 files

2.8.2

2 files

2.8.1

2 files

2.8.0

2 files

2.7.3

2 files

2.7.2

2 files

2.7.1

2 files

2.7.0

2 files

2.6.0

2 files

2.5.2

2 files

2.5.1

2 files

2.5.0

2 files

2.4.0

2 files

2.3.1

2 files

2.3.0

2 files

2.2.4

2 files

2.2.3

2 files

2.2.0

2 files

2.1.1

2 files

2.1.0

2 files

2.0.1

2 files

2.0.0

2 files

0.11.4

2 files

0.11.3

2 files

0.11.2

2 files

0.11.1

2 files

0.11.0

2 files

0.10.0

2 files

0.9.4

2 files

0.9.3

2 files

0.9.2

2 files

0.9.1

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.1

2 files

0.4.0

2 files

0.3.1

2 files

0.3.0

2 files

0.2.9

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page