Skip to main content

Independent verification layer for software projects

Project description

Assay

PyPI License: AGPL-3.0-only

Visual verification for software projects.

Assay captures browser screenshots, computes pixel-level diffs against approved baselines, and surfaces results through a dashboard with a before/after slider. It runs Playwright tests in Docker and delivers structured results to a Grain workflow via an ingest API.


Features

  • Visual diff — pixel-level comparison of screenshots against approved baselines; highlights regressions in red
  • Before/after slider — side-by-side and overlay views in the dashboard
  • Baseline management — approve or reject baseline updates per check; no silent regressions
  • Screenshot gallery — browseable dashboard with thumbnails, check status, and diff overlays
  • Scheduled runs — cron-based scheduling with configurable suites and targets
  • Grain integration — ingest results directly into a Grain task packet for structured review and closure
  • Browser SDK — TypeScript SDK for capturing screenshots and metadata from inside your app
  • Docker runner — isolated Playwright execution with a prebuilt image

Requirements

  • Python 3.11+
  • Docker (for assay run)
  • Node.js 18+ (for the TypeScript browser SDK)

Install

uv tool install assay-kit

Or with pip:

pip install assay-kit

Or from source:

git clone https://github.com/Diwata-Labs/Assay.git
cd Assay
pip install -e .

Quick start

1. Configure

Create assay.toml in your project root (all fields optional — defaults shown):

[project]
name = "my-project"

[runner]
docker_image = "assay-playwright:latest"
timeout_seconds = 300

[output]
directory = "./assay-output"

[serve]
host = "127.0.0.1"
port = 8000

[keys]
store = "~/.assay/keys.json"

[schedule]
store = "~/.assay/schedules.json"

2. Run a test

assay run --target https://your-app.example.com

Exit codes: 0 = pass, 3 = fail, 1 = inconclusive or error.

3. Start the ingest server

# Create an API key first
assay key create --name ci

# Start the server
assay serve

4. Open the dashboard

Navigate to http://localhost:8000 to see the screenshot gallery, check results, and diff views.

5. Schedule recurring runs

# Add a schedule (standard 5-field cron)
assay schedule add --cron "0 8 * * *" --suite smoke --target https://your-app.example.com

# List schedules
assay schedule list

# Start the scheduler (foreground; Ctrl+C to stop)
assay schedule run

# Remove a schedule
assay schedule remove <id>

Dashboard

The Assay dashboard (assay serve) provides:

  • Screenshot gallery — thumbnails for every captured check, sorted by run
  • Check results — pass/fail/inconclusive status per check with diff metadata
  • Visual diff viewer — side-by-side before/after comparison with a draggable overlay slider
  • Baseline management — approve a new baseline or reject and keep the existing one per check

Baselines are stored locally alongside your output directory. Approving a baseline makes it the reference for future runs.


Grain integration

Assay results can be ingested directly into a Grain task packet for structured review before closure.

The ingest API is protected by API key auth. Create a key before starting the server:

assay key create --name grain
assay key list

The ingest endpoint accepts structured payloads from the browser SDK or from assay run. Grain reads the result via:

grain verify submit --id TASK-0001
grain verify status --verification-id VERIFY-0001-001

Browser SDK

The browser SDK is for human/in-app capture from a real browser. It is not the agent path — its capture() reads the live DOM and throws outside a browser. Agents should use the CLI, POST /ingest, or MCP (see Agent / programmatic access).

Install the TypeScript SDK in your web app:

npm install @diwata-labs/assay-sdk
import { AssaySDK } from "@diwata-labs/assay-sdk";

const sdk = new AssaySDK({
  apiKey: "your-api-key",
  endpoint: "http://localhost:8000",
});

// Capture a screenshot and metadata, POST to /ingest
await sdk.capture({ comment: "Optional human note" });

The SDK captures the current viewport, serializes metadata, and POSTs to the ingest endpoint. Results appear in the dashboard immediately.


Agent / programmatic access

Assay is fully familiar-drivable: an agent can run the entire verification loop headlessly, with no browser and no dashboard. Agents use the CLI, POST /ingest, or the MCP server — never the browser SDK (its capture() is DOM-locked and throws in Node).

The machine-readable contract — every tool, its JSON Schema, and the HTTP endpoints — lives at src/assay/contracts/tool_manifest.json and is served at GET /mcp/manifest. Treat that as the source of truth.

Three agent surfaces

  1. CLI — the most complete surface. Every agent-relevant command takes --format json:

    assay init --non-interactive --admin-email a@b.com --admin-password "$PW" --format json
    assay run --target https://app.example.com --task-id TASK-0001 --format json
    assay check --format json
    assay key create --name agent --format json
    assay baseline approve VERIFY-0001-001 --format json
    assay baseline list --format json
    

    assay init --non-interactive (alias --yes) never prompts or reads a TTY — pass the admin email/password as flags or via ASSAY_ADMIN_EMAIL / ASSAY_ADMIN_PASSWORD for zero-touch setup.

  2. POST /ingest — submit a captured screenshot payload directly. Authenticated with the X-Assay-Key header. The request body conforms to the JSON Schema src/assay/schemas/sdk_ingest.schema.json; the stored result conforms to src/assay/schemas/assay_payload.schema.json.

  3. MCP serverGET /mcp/tools, GET /mcp/manifest, POST /mcp/call. All /mcp/* and /baselines* routes require a valid API key (X-Assay-Key). The tools cover the full loop:

    tool purpose
    run_verification trigger a real run; returns verification_id + outcome + diff
    get_report structured report for a verification_id
    get_status poll a verification_id (pending / complete)
    list_runs list runs, filter by task_id / outcome
    list_baselines list set baselines
    approve_baseline / reject_baseline / set_baseline drive the baseline workflow
    KEY=$(assay key create --name agent --format json | tail -1 | python -c 'import sys,json;print(json.load(sys.stdin)["key"])')
    
    curl -s localhost:8000/mcp/call -H "X-Assay-Key: $KEY" \
      -d '{"tool":"run_verification","input":{"target":"https://app.example.com"}}'
    
    curl -s localhost:8000/mcp/call -H "X-Assay-Key: $KEY" \
      -d '{"tool":"approve_baseline","input":{"verification_id":"VERIFY-0001-001"}}'
    

Baselines are also manageable headlessly over API-key HTTP: GET /baselines, POST /baselines/set|approve|reject (body {"verification_id": "..."}) — no dashboard needed.


Docker runner

The assay run command requires a pre-built Docker image containing Playwright.

Build locally

cd runner
docker build -t assay-playwright:latest .

Use a custom image

[runner]
docker_image = "myregistry.example.com/assay-playwright:latest"

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Lint
ruff check src/ tests/

# Type check
mypy src/assay

License

AGPL-3.0-only. Commercial licensing for closed-source or hosted use: ss@diwata.domains

Project details


Download files

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

Source Distribution

assay_kit-0.3.3.tar.gz (150.1 kB view details)

Uploaded Source

Built Distribution

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

assay_kit-0.3.3-py3-none-any.whl (104.8 kB view details)

Uploaded Python 3

File details

Details for the file assay_kit-0.3.3.tar.gz.

File metadata

  • Download URL: assay_kit-0.3.3.tar.gz
  • Upload date:
  • Size: 150.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for assay_kit-0.3.3.tar.gz
Algorithm Hash digest
SHA256 bdad6ac12d42c54adfb1bf727cb578cdbfff965947684923e9a4c6533e2bad80
MD5 e54bed47a3ab7e5ef41f214196223ff3
BLAKE2b-256 daba84384dbeb4deb009792ab32dd01d1da5cb656a42fd50c738d1ad66c272a2

See more details on using hashes here.

File details

Details for the file assay_kit-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: assay_kit-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 104.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for assay_kit-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 a6a9f00732810cf520cab91361be44438b366c6b461b2177536afcfd0de2679f
MD5 7e59a175301271378dafa154239643af
BLAKE2b-256 dc91f2d1d6b583017e0bd236667daa8735d2d75b61ed7b1658e8b447ed802636

See more details on using hashes here.

Supported by

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