Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/product-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: product-validation

on:
pull_request:
push:
branches: [main]
Comment on lines +5 to +6

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use the previous revision as the base for main pushes

On a push to main, checkout makes both HEAD and origin/main resolve to the newly pushed commit, while the committed manifest has requireEntireCheckpoint: true. The runner therefore examines an empty origin/main..HEAD range and throws before executing any validator, so this workflow's main-push path cannot pass; use the push event's previous commit as the base or restrict this workflow to pull requests.

Useful? React with 👍 / 👎.

workflow_dispatch:

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 50
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with: {node-version: 22}
- name: Validate exact candidate
run: |
set -o pipefail
install -m 755 scripts/tabellio-validator.mjs "$RUNNER_TEMP/tabellio-validator"
PATH="$RUNNER_TEMP:$PATH" node scripts/tabellio-validate.mjs gate \
--repo . \
--repo-id IntelIP/Tabellio \
--base origin/main \
--commit HEAD \
--manifest tabellio.validation.json | tee tabellio-validation-result.json
- name: Upload validation result
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: tabellio-validation-${{ github.event.pull_request.head.sha || github.sha }}
path: |
tabellio-validation-result.json
refs/tabellio/validations/
if-no-files-found: warn
2 changes: 2 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ jobs:
fallow audit \
--base "origin/${{ github.base_ref }}" \
--gate new-only \
--health-baseline quality-baselines/fallow-health.json \
--dupes-baseline quality-baselines/fallow-dupes.json \
--format json \
--quiet \
--explain \
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
node_modules/
.tabellio/
.tabellio/*
!.tabellio/
!.tabellio/validators.json
agentic-pr-evidence.json
tabellio-pr-evidence.json
tabellio-context.json
Expand Down
35 changes: 35 additions & 0 deletions .tabellio/validators.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"schemaVersion": "tabellio-adapter/v0.1",
"profiles": {
"static": {
"commands": [["npm", "run", "check"]],
"metrics": [],
"cost": {"telemetry": "not_applicable", "usd": null, "modelCalls": null, "toolCalls": null},
"summary": "Control-plane tests and repository checks"
},
"schema": {
"commands": [["npm", "run", "tabellio:platform:check"]],
"metrics": [{"name": "platform_contract_pass", "unit": "boolean", "passValue": 1, "failValue": 0}],
"cost": {"telemetry": "available", "usd": 0, "modelCalls": 0, "toolCalls": 0},
"summary": "Platform and schema contract checks"
},
"semantic": {
"commands": [["npm", "run", "tabellio:validate:example:check"]],
"metrics": [{"name": "validation_contract_examples_pass", "unit": "boolean", "passValue": 1, "failValue": 0}],
"cost": {"telemetry": "available", "usd": 0, "modelCalls": 0, "toolCalls": 0},
"summary": "Typed validation examples and evidence contracts"
},
"workflow": {
"commands": [["npm", "run", "tabellio:run:example:check"], ["npm", "run", "tabellio:review:example:check"]],
"metrics": [{"name": "run_review_workflows_pass", "unit": "boolean", "passValue": 1, "failValue": 0}],
"cost": {"telemetry": "available", "usd": 0, "modelCalls": 0, "toolCalls": 0},
"summary": "Agent run and review lifecycle examples"
},
"security": {
"commands": [["node", "scripts/check-tabellio-external-actions.mjs", "--evidence", "examples/tabellio-evidence/minimal-evidence.json"]],
"metrics": [{"name": "external_action_policy_pass", "unit": "boolean", "passValue": 1, "failValue": 0}],
"cost": {"telemetry": "available", "usd": 0, "modelCalls": 0, "toolCalls": 0},
"summary": "External-action and side-effect policy checks"
}
}
}
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@ All notable changes to Tabellio are recorded here.

## Unreleased

## 0.4.0 - 2026-07-16

### Added

- Product-validity manifests that bind acceptance outcomes, invariants, forbidden outcomes, risk, and required validator types to an exact candidate commit.
- Typed schema, semantic, workflow, visual, operational, and security evidence with bounded metrics, artifact digests, and cost telemetry.
- Fail-closed `passed`, `failed`, and `blocked` decisions with threshold and cost-budget enforcement.
- `tabellio-validate gate` for CI enforcement without external JSON parsing.
- `tabellio-validator` for repository-declared shell-free adapter commands, metric extraction, and common evidence emission.

### Changed

- Product-changing work now requires evidence beyond command exit status when the manifest declares typed validators.
- Missing required evidence, missing metrics, command errors, timeouts, and unknown required cost telemetry block readiness.
- Existing v0.1 manifests and v0.1/v0.2 result readers remain supported during migration.

### Release Gates

- `tabellio-preflight --profile release`
- `npm run check`
- Fallow whole-repository and changed-code scans
- `npm pack --dry-run --json`
- Exact merged-head Tabellio validation

## 0.3.0 - 2026-07-15

### Added
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Tabellio attaches a structured evidence packet to a pull request. The packet is
| Git | Repository, base branch, head branch, commit SHA, and PR metadata |
| Runtime | Human, CI, or agent runtime that produced the change |
| Diff | Changed files |
| Validation | Commands run and check results |
| Validation | Exact-head commands plus structural, semantic, workflow, visual, operational, and security results |
| Approvals | Required, granted, denied, or skipped approvals |
| Side effects | Deployment, migration, infra, billing, secret, provider, and destructive-action policy |
| Artifacts | Evidence files generated by the run |
Expand Down Expand Up @@ -58,7 +58,7 @@ AI-assisted pull requests should not depend on reviewer trust alone. Tabellio gi
| Layer | Tooling | Role |
| --- | --- | --- |
| Runtime | [Node.js 20+](https://nodejs.org/) | Runs the local writer and validators |
| Validation | `tabellio-validate` on any trusted worker | Runs an exact committed command manifest and stores results on a Git ref |
| Validation | `tabellio-validate` on any trusted worker | Runs exact committed command or typed product validators and stores results on a Git ref |
| Evidence contract | [JSON Schema](https://json-schema.org/) | Validates the evidence envelope and external-action policy |
| Code storage | [GitHub](https://github.com/) | Stores code refs and tags; provides a thin pull-request shell |
| Stacked review | [git-spice](https://abhinav.github.io/git-spice/) | Stack engine for small dependent GitHub pull requests |
Expand Down Expand Up @@ -103,6 +103,12 @@ npm run tabellio:platform:check
node scripts/tabellio-validate.mjs run --repo . --commit HEAD --manifest tabellio.validation.json
```

Use `gate` in CI. It persists the same exact-head result but exits non-zero unless the final decision is `passed`:

```bash
tabellio-validate gate --repo . --repo-id owner/repository --base main --commit HEAD --manifest tabellio.validation.json
```

Keep `origin` limited to ordinary code branches and tags. Configure a separate private GitHub repository under another remote name before publishing control refs. The transport refuses to target `origin`.

Before agent or release work, run:
Expand Down Expand Up @@ -162,6 +168,7 @@ node scripts/tabellio-run.mjs promote --run-id run-42 --repo .
```

See [Agent run lifecycle](docs/agent-run-lifecycle.md) for state and failure behavior.
See [Product validation](docs/product-validation.md) for acceptance contracts, typed evidence, cost gates, and repository adapters.

Package scripts:

Expand Down
2 changes: 2 additions & 0 deletions docs/codex-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ Codex review is not:
- deployment approval
- substitute for human ownership
- proof that agent output is secure

When the repository commits a product-validation manifest, review begins only after the exact pull-request head has a `passed` v0.3 decision. A `blocked` decision means the evidence is incomplete or untrustworthy; it is not a product pass and should not be converted into reviewer guesswork.
63 changes: 63 additions & 0 deletions docs/design-memory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Product Design Memory

Tabellio can attest visual intent and regression evidence without becoming a design tool or screenshot database.

## Ownership

Product repositories own committed design memory:

```text
design/
product.design.json
baselines/manifest.json
decisions/*.md
```

`tabellio-product-design/v0.1` records visual thesis, canonical token and component sources, reference lock, forbidden patterns, required themes, viewports, states, accessibility policy, and baseline manifest location. Source digests detect drift between the profile and the files it claims as authority.

`tabellio-visual-baselines/v0.1` records human-approved captures by surface, viewport, theme, and state. Each capture points to a durable artifact URI with SHA-256 digest. `file:` URIs are rejected because detached validation worktrees are removed after a run.

`policy.surfaces` declares the required route or component matrix. Approved manifests must cover every declared viewport, theme, and state combination.

`tabellio-ui-review/v0.1` records model judgment as typed evidence: exact commit and profile digests, reviewed capture digests, model identity, cost telemetry, structured findings, verdict, and blockers. It complements deterministic checks; it never approves or rewrites baselines.

New products may commit a `proposed` empty baseline manifest while capture work is pending. A capture run may replace it with a complete proposed manifest bound to the captured commit. Proposed manifests keep approval fields null and always block product readiness until a human promotes them to `approved`.

Git stores design history. Tabellio binds the profile, baselines, visual metrics, critique artifacts, and validation decision to the exact candidate commit.

## Validation

Check a product repository:

```bash
tabellio-design-memory \
--repo . \
--profile design/product.design.json
```

The checker verifies profile and baseline shape, repository-relative source paths, source digests, profile digest, product identity, viewport/state/theme references, and durable artifact URIs.

Finalize a product-owned PNG capture matrix into a proposed manifest:

```bash
tabellio-design-captures \
--repo . \
--profile design/product.design.json \
--captures-dir .artifacts/tabellio/visual-captures \
--artifact-base-uri "artifact+github://OWNER/REPO/actions/runs/RUN_ID/design-captures/" \
--source-commit "$GITHUB_SHA" \
--out .artifacts/tabellio/visual-baseline-candidate.json
```

Capture files use `<surface-id>--<viewport>--<theme>--<state>.png`. Finalization fails when any declared matrix cell is absent, a file is not PNG, the commit is not exact, or the artifact URI is ephemeral. Output creation is exclusive; existing evidence is never overwritten.

Use two visual validators when product readiness matters:

- `visual-contract`: deterministic capture completeness, token/profile checks, fonts, overflow, accessibility, and visual diff metrics.
- `visual-judgment`: structured model critique for hierarchy, signifiers, grouping, density, feedback, and reference fidelity.

Require model cost telemetry. Missing profile, baselines, artifacts, metrics, or required cost telemetry is `blocked`. Never update an approved baseline automatically.

## Rollout

Start with one product-specific design system and one unrelated product. Keep profile files small by referencing canonical sources instead of copying full tokens or component inventories. Add a cross-product read-only catalog only after profiles prove portable.
3 changes: 2 additions & 1 deletion docs/operations-hardening.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ Tabellio keeps code and control state in standard Git objects, but production sa

## Bounded Work

- Validation manifests allow at most 50 commands, 100 arguments per command, and one-hour command timeouts.
- Validation manifests allow at most 50 commands or validators, 100 arguments per entry, and one-hour command timeouts.
- Timed-out commands receive `SIGTERM`, then `SIGKILL` after one second. Fail-fast suites mark remaining commands skipped.
- Full stdout and stderr are hashed; only the newest 16 KiB of each stream is retained.
- Typed evidence files are limited to 1 MiB, 100 metrics, and 50 immutable artifact references. Required missing cost telemetry blocks validation instead of being treated as zero spend.
- Agent reviews allow at most 1,000 findings. Review cycles bound feedback, fixes, check statuses, titles, bodies, summaries, event details, and retained event history.
- Remote control-ref reads and atomic pushes use a 15-minute timeout. Local atomic ref updates use a 30-second timeout.

Expand Down
84 changes: 84 additions & 0 deletions docs/product-validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Product Validation

Tabellio product validation answers a stronger question than “did tests exit zero?”: did the exact committed candidate satisfy its declared user outcomes while staying inside semantic, visual, operational, cost, and safety boundaries?

## Contracts

`tabellio-validation/v0.2` binds three layers in one committed manifest:

1. `acceptance` records the source request, risk, required outcomes, invariants, forbidden outcomes, and required validator types.
2. `validators` run shell-free argument arrays in the exact-head detached worktree.
3. `policy` applies metric thresholds and cost requirements to a bounded evidence report.

Validator types are `static`, `schema`, `semantic`, `workflow`, `visual`, `operational`, and `security`. Static validators can use command exit status alone. Every other type must emit `tabellio-validator-evidence/v0.1` at its declared relative path.

## Evidence

An evidence report contains:

- `status`: the adapter’s passed, failed, or blocked observation;
- numeric metrics with explicit units;
- cost telemetry state, USD cost, model calls, and tool calls;
- immutable artifact metadata for screenshots, traces, reports, or source snapshots.

The runner validates the evidence shape and validator identity, embeds the bounded report in the durable result, and evaluates policy itself. Adapter-reported `passed` cannot override a failed metric threshold or exceeded cost cap.

## Decision Semantics

| Decision | Meaning |
| --- | --- |
| `passed` | Every required validator completed with trustworthy evidence inside all thresholds. |
| `failed` | Trustworthy evidence proves a required product or budget threshold was missed. |
| `blocked` | Required proof is missing or untrustworthy because of invalid evidence, missing metrics or cost telemetry, command errors, or timeouts. |

Fail closed. Never translate `blocked` into `passed`, and never treat missing cost telemetry as zero.

## Repository Adapters

Keep product knowledge in each repository. The adapter runs the existing eval, browser, design, cost, or security harness and writes the common evidence contract.

Use `tabellio-validator` for simple adapters. Commit `.tabellio/validators.json` with `tabellio-adapter/v0.1` profiles containing shell-free command arrays, evidence metrics, cost telemetry, and a concise summary. Metrics may map command pass/fail to numeric values or extract a numeric capture group from bounded command output.

- AI systems: stable golden cases in pull requests; larger live suites on schedules or release gates.
- Web applications: critical journeys, desktop/mobile screenshot comparisons, loaded-font assertions, overflow, and accessibility metrics.
- Operational systems: projected and observed provider usage, worker counts, polling frequency, rate limits, latency, and spend.
- Structured outputs: strict schema validation plus semantic oracles that catch plausible but wrong values.

Use fixtures and isolated namespaces in pull requests. Live external mutation remains separately approval-gated.

## Review Integration

Review sync reads only the newest validation result stored under the exact pull-request head. `passed` becomes a successful local check; `failed` or `blocked` prevents merge readiness. A new head requires new validation.

Run contract checks with:

```bash
node scripts/check-tabellio-validation.mjs --manifest examples/tabellio-validation/product-manifest.json
node scripts/check-tabellio-validation.mjs --evidence examples/tabellio-validation/minimal-validator-evidence.json
```

Run the exact-head suite with:

```bash
node scripts/tabellio-validate.mjs run \
--repo . \
--repo-id example/project \
--base main \
--commit HEAD \
--manifest tabellio.validation.json
```

Use the fail-closed command in CI:

```bash
tabellio-validate gate \
--repo . \
--repo-id example/project \
--base main \
--commit HEAD \
--manifest tabellio.validation.json
```

`gate` still records the result. It exits non-zero when the decision is `failed` or `blocked`.

Artifact upload and path-based automatic validator selection remain scheduler or repository-policy responsibilities. The first contract keeps evaluation portable without creating a second CI or deployment authority.
12 changes: 12 additions & 0 deletions docs/releases/v0.4.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Tabellio v0.4.0 adds product-validity and cost-aware validation.

## Highlights

- Acceptance contracts declare user outcomes, invariants, forbidden outcomes, risk, and required evidence types.
- Typed validators cover schema, semantics, workflows, visuals, operations, cost, and security.
- Evidence carries numeric metrics, explicit units, cost telemetry, tool and model call counts, and immutable artifact metadata.
- Policy evaluation belongs to the runner. Adapter-reported success cannot override a missed threshold or cost cap.
- Missing or untrustworthy required proof is `blocked`, never an implied pass.
- `tabellio-validate gate` records exact-head results and exits non-zero unless the decision is `passed`.

Existing v0.1 validation manifests remain readable. Live provider calls, deployments, infrastructure changes, and publication remain separately approval-gated.
Loading
Loading