DEV Community

Fernando Paladini
Fernando Paladini

Posted on

Turn Spec Drift into a Pull Request Check with SpecGov

TL;DR

Spec-driven development is useful only while the code and its governing artifacts stay aligned. SpecGov is a local, MIT-licensed CLI and GitHub Action that maps implementation paths to requirements, ADRs, docs, or specs, then reports when a code change bypasses them.

This tutorial uses the stable v0.1.0 release to build a small manifest, run a local scan, simulate a pull request check, and add the same check to GitHub Actions. The workflow is advisory first, so a team can learn where its mappings are incomplete before making them blocking.

What you will build

By the end, a repository will have a .specgov.yml manifest that says which artifacts govern src/auth/**. SpecGov can then report a warning when a pull request changes src/auth/session.ts without changing a related specification or design document.

SpecGov does not replace a spec-authoring method. It works with existing Markdown contracts, ADRs, .specs folders, Kiro specs, and Spec Kit plans. It reads local files and Git metadata. The project documentation describes it as framework agnostic, PR native, advisory first, and private by default.

Prerequisites

You need:

  • Node.js 20 or newer. The package declares node >=20.
  • A Git repository with a few documentation or specification files.
  • Git, if you want to run the pull request comparison locally.
  • A GitHub repository if you want to add the Action.

The stable release is specgov@0.1.0, published under the MIT license. The current repository also contains newer pre-release work, so pin the version when you need repeatable behavior.

Install the stable CLI

You can install the published CLI globally:

npm install -g specgov@0.1.0
Enter fullscreen mode Exit fullscreen mode

Or use it without changing the global environment:

npx specgov@0.1.0 --help
Enter fullscreen mode Exit fullscreen mode

The CLI exposes init, scan, check-pr, trace, and drift. The first four are enough for a useful pull request gate. The v0.1.0 README documents the complete command surface and exit codes.

Add a small manifest

Create .specgov.yml at the repository root. Start with one high-value mapping instead of trying to govern every path immediately:

version: 1
mode: advisory

artifacts:
  - path: "docs/**/*.md"
    kind: documentation
    owner: docs
  - path: "adr/**/*.md"
    kind: decision
    owner: architecture
  - path: ".specs/**/*.md"
    kind: specification
    owner: engineering

mappings:
  - code: "src/auth/**"
    specs:
      - "docs/auth/**"
      - "adr/auth/**"
      - ".specs/features/auth/**"
    description: Authentication behavior must stay aligned with its specs.

rules:
  require_spec_impact_for_code_changes: true
  require_lifecycle_status: false
  require_owner_for_active_specs: false
  stale_after_days: 180

ignore:
  - "node_modules/**"
  - "dist/**"
  - ".git/**"
Enter fullscreen mode Exit fullscreen mode

The artifacts entries tell SpecGov what belongs to the repository's governance layer. A mappings entry connects implementation paths to the artifacts that must move with them. The mapping is explicit: an unrelated changed document does not satisfy the rule by accident.

Keep mode: advisory while the manifest is new. Advisory mode reports warnings but returns success for those warnings. Strict mode returns exit code 1 when governance findings should block a pull request.

Run the local checks

First scan the repository and emit JSON for a script or CI job:

specgov scan --format json
Enter fullscreen mode Exit fullscreen mode

Then simulate a pull request that changes an authentication file:

specgov check-pr --format json --changed-file src/auth/session.ts
Enter fullscreen mode Exit fullscreen mode

With the manifest above and no related spec change, the result should contain a SPEC_IMPACT_MISSING warning. That warning is useful evidence, not a failure in advisory mode. It tells the author which code path changed and which spec roots should be considered.

For a human-readable report, omit --format json:

specgov check-pr --changed-file src/auth/session.ts
Enter fullscreen mode Exit fullscreen mode

You can also create a trace index for automation:

specgov trace --out .specgov.trace.json
Enter fullscreen mode Exit fullscreen mode

The exact report depends on your repository. The important verification is reproducible: run the same command against the same checkout and inspect the finding code, related files, status, and exit code.

Add the GitHub Action

Once the local mapping makes sense, add a workflow such as .github/workflows/specgov.yml:

name: SpecGov

on:
  pull_request:

jobs:
  specgov:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: paladini/specgov@v0.1.0
        with:
          mode: advisory
          base-ref: ${{ github.event.pull_request.base.sha }}
          head-ref: ${{ github.event.pull_request.head.sha }}
Enter fullscreen mode Exit fullscreen mode

The repository's stable README uses the same action contract and recommends pinning the Action to a version tag for repeatable CI behavior. The checkout needs full history because the check compares the pull request's base and head references.

When the mapping has earned trust, change mode to strict for the paths you are ready to enforce. Treat that as a policy decision: a strict rule can block a pull request, so the mapped artifact roots must be maintained with the same care as source code.

Why this works

The useful abstraction is a small graph:

  1. Artifact globs identify the documents that can govern behavior.
  2. Code-to-spec mappings connect implementation paths to those artifacts.
  3. Git changes provide the pull request scope.
  4. SpecGov compares the scope with the mappings and emits Markdown or JSON evidence.

This is more precise than checking whether a repository contains a file named SPEC.md. It also avoids asking an agent or model to guess which document matters. The manifest makes the relationship explicit and reviewable.

Failure modes and limitations

An empty glob or a typo in a path can make a mapping look complete while matching nothing. Run scan and review its artifact list before enabling strict mode.

SpecGov does not prove that a requirement is correct, that an implementation satisfies the requirement semantically, or that a declared producer really authored an artifact. It reports structural relationships and policy findings. A passing scan is not a correctness guarantee.

The stable release is marked pre-release in its README, and the CLI, report shape, and Action inputs may change before a first mature release. Pin 0.1.0 in tutorials and workflows, then review changes before upgrading.

The security boundary is intentionally narrow. Version 0.1 runs locally or in the GitHub runner, does not require an API key, does not call a model, and does not upload repository contents. That does not make the surrounding runner trusted automatically. Review third-party Actions, protect workflow changes, and avoid exposing private reports in public logs.

FAQ

Does SpecGov require GitHub?

No. The CLI can run locally in any Git repository. GitHub Actions is an integration point for pull request review.

Does it support only one specification framework?

No. The stable release supports custom folders and mappings, including docs, ADRs, .specs, Kiro-style specs, and Spec Kit-style plans.

Should every repository start in strict mode?

No. Start advisory, fix empty or overly broad mappings, observe real findings, and make only trusted paths strict.

Does a warning mean the code is unsafe?

No. It means the configured governance relationship is incomplete for the changed path. A reviewer still needs to decide whether the code, artifact, or mapping should change.

Takeaway

Spec drift becomes actionable when a repository can state which artifacts govern which code paths. SpecGov turns that statement into a deterministic local check and a pull request report. Start with one mapping, keep it advisory, verify the findings, and tighten enforcement only when the repository's own evidence supports it.

AI assistance disclosure: I used AI assistance to organize this tutorial and edit its prose. The project behavior, commands, configuration, version, license, limitations, and verification results were checked against the public repository, the stable v0.1.0 tag, package metadata, and local test/build commands.

What is the first code-to-artifact mapping in your repository that would benefit from an advisory check?

Top comments (0)