The official GitHub Action for IntentSpec, the open format for product intent.
Validates that your intent.md adheres to the IntentSpec Schema. Catches malformed specs, missing required fields, and typos in evidence anchors before they reach your main branch.
This repository validates the same format it uses: read its intent.md.
Supports IntentSpec v1.2, which adds the optional scope and verification fields, requires at least one outcome, and checks that evidence anchors resolve to sections that actually exist. The last two are new failure modes, so read Upgrading to v1.2 before you bump.
Add this to your workflow file (e.g., .github/workflows/intentspec.yml):
name: Validate IntentSpec
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate Intent Spec
uses: pathmodeio/validate-intentspec-action@v1
with:
file: 'intent.md' # Optional (default: intent.md)| Input | Description | Default | Required |
|---|---|---|---|
file |
Path to the intent markdown file | intent.md |
No |
- Required fields:
id,status,objective,outcomes(at least one outcome) - Enum constraints:
status,problemSeverity,strategicAlignment - Edge case shape: each entry must include
scenarioandexpectedBehavior - Scope shape (v1.2):
scope.inScopeandscope.outOfScopemust be arrays of strings - Evidence shape (v1.1): each evidence item must include
typeandexcerpt.typemust be one offriction,quote,observation,metric,request. - Anchor format (v1.1): evidence
anchorsmust matchobjective,userGoal,outcome:N,edgeCase:N,constraint:N, orhealthMetric:N— typos likeoutomce:0fail validation. - Anchor resolution (v1.2): anchors must point at sections that exist —
outcome:3in a two-outcome spec fails, as does anchoringuserGoalwhen the spec has none.
- Prevent drift. Specs without structure rot. Validation catches missing outcomes, broken edge case shapes, and typos in evidence references before they reach main.
- Keep evidence honest. Anchors that don't match a real spec section are caught at validation time — your evidence can't reference an outcome that doesn't exist.
- Governance. Make IntentSpec validation a required check on every PR.
@v1— floating tag, always points at the latest v1.x release (currentlyv1.2.5). Use this unless you need to pin.@v1.2.5— IntentSpec v1.2, current. Reads the heading aliases in SPEC.md section 2: when## Objectiveis absent,## Problemand then## Whycarry the objective, and## Proposed outcomestands in for an absent## Outcomes.## Whatis not an alias. A document using the canonical headings validates exactly as under v1.2.4.@v1.2.4— IntentSpec v1.2. Runs on Node 24; validation identical to v1.2.3.@v1.2.1–@v1.2.3— IntentSpec v1.2. Validate the normalized document, so a sectionedintent.md(lists under##headings) is read, not only its frontmatter. Tested against the published normalization corpus, so this Action reads a document the same way the other IntentSpec implementations do.@v1.2.0— IntentSpec v1.2. Addsscope+verificationfields and anchor resolution. Reads frontmatter only.@v1.1.0— IntentSpec v1.1. Adds evidence field validation.@v1.0.8— IntentSpec v1.0 (legacy). No evidence field validation.
Full notes for each version are on the releases page.
v1.2 introduces no new required fields, but it does enforce two rules the written spec already stated and the validator did not check. A spec that passed under v1.1 now fails if:
outcomesis present but empty. The spec has always said an IntentSpec MUST have at least one outcome. The schema now says it too, viaminItems: 1.- An evidence anchor points at a section that does not exist.
outcome:3in a two-outcome spec, oruserGoalin a spec that has nouserGoal, was accepted before and fails now.
Both cases were already non-conformant, so this is a validator fix rather than a change to the standard. It is still a behavior change for anyone tracking @v1: if a spec of yours falls into either case, fix the spec, or pin @v1.1.0 until you can.
npm ci
npm run build # bundles src/ into dist/ via ncc, then copies the schema
npm test # fixtures + anchor corpus + drift against intentspec.org
SKIP_DRIFT=1 npm test # same, without the network callsdist/ is the artifact consumers actually run, so it is committed and CI rebuilds
it and fails on any diff. Build with the Node major in .nvmrc, or that byte
comparison will flag a difference that is only a toolchain difference.
src/schema.json and test/anchors-corpus.json are copies. The originals live on
the site and are published at https://intentspec.org/schema.json and
https://intentspec.org/anchors-corpus.json; the weekly drift job fails if a copy
here falls behind. Sync from the site, rebuild, then release.