Spec review & approval workflow: frontmatter contract, transition detection, role→person→channel routing, and a status gate.
Project description
hureva
A spec review & approval workflow you install into your team's repo: generate
specs with Claude, get structured review from non-technical teammates (PM, UX, QA)
before code is written, and record approval in git so it can gate the build.
Based on docs/spec-review-workflow-specification.md.
hureva is a versioned package teams install, not copy. Your specs live in your
own repo under specs/; you add a small workflow that pip installs a pinned
version of hureva and runs it, plus a bit of config. Nothing is hosted, and none
of hureva's code lives in your repo.
Installing it? See
SETUP.mdfor the step-by-step guide.
How it works
- The spec is a
spec.mdwhose frontmatter is the contract (§4.2):status, role-based access (owner/approvers/commenters/viewers), and the sign-off trail. People are named by roster key; channels resolve fromspecs/roster.yml. - Work happens on a
spec/<slug>branch. Pushing a status change fires the workflow, which compares the spec'sstatusacross the push's two commits and acts only on a transition (§7.4). draft → in_reviewnotifies reviewers;→ approvedtells the owner "ready to build." The gate is advisory by default and can be hardened to block un-approved specs (§6.3).
Library
| Piece | Module | Spec |
|---|---|---|
| Frontmatter / roster / defaults models | hureva.models |
§4.2–4.4 |
Frontmatter parsing (+ lenient status reader) |
hureva.frontmatter |
§4.2 |
specs_dir-derived paths, config, defaults seeding |
hureva.config |
§4.1, §4.4 |
| Two-commit transition detection (pure fn) | hureva.transitions |
§7.4 |
| Changed-spec discovery from a push | hureva.discovery |
§7.4 |
| Event → role → person → channel routing | hureva.routing |
§7.1 |
| Sender interface + dry-run + Slack + SMTP | hureva.senders |
§7.3 |
| Notify orchestration + CLI | hureva.notify |
§7 |
| Status gate + CLI (advisory / enforced) | hureva.gate |
§6 |
Create a spec + branch (/new-spec) |
hureva.new_spec |
§14.2 |
The logic is a pure library (git/env reading is a thin shell), delivery is behind
a Sender interface, and the specs path is configurable — nothing hard-codes
specs.
How teams install it
hureva is a PyPI package (hureva), published on each GitHub Release. The
fastest path is to scaffold the setup, then follow the printed checklist:
pip install hureva
hureva-init # writes the workflow + config, prints next steps
Under the hood that adds one small, static workflow that installs the versioned package and runs its two commands — notify, then gate:
# team-repo/.github/workflows/spec-review.yml
on:
push:
branches: ["spec/**"] # status changes happen on spec branches (§7.4)
paths: ["specs/**"] # (literal — Actions can't use a variable here)
jobs:
spec-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 } # both push commits reachable (§7.4)
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- run: pip install "hureva~=1.0" # ← version pin lives here
- run: hureva-notify --specs-dir specs
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
# SMTP_* too, if using email
- run: hureva-gate --changed --specs-dir specs # add --enforced to block
Nothing of hureva's code lives in the team repo — the workflow is generic "install a tool and run it" plumbing, and all behavior is in the versioned package.
Versioning — pin the package
pip install "hureva~=1.0" is the version pin (like "hureva": "^1.0" in a
dependency list). It's the alternative to copying hureva's code in (which drifts
and never gets fixes): you install a released version.
~=1.0takes any 1.x release, so compatible fixes flow in automatically.- Pin exactly with
==1.2.3; move to the next major (~=2.0) when you choose, after reading its release notes.
CLIs
Commands (also runnable as python -m hureva.<module>). The operational ones take
--specs-dir (default specs).
# One-time: scaffold the workflow + config into this repo, print next steps
hureva-init
# Create a spec + its spec/<slug> branch (seeds roles from defaults.yml)
hureva-new-spec <slug> --title "Feature title"
# Route notifications for a push (--dry-run prints without delivering)
hureva-notify --dry-run
# Gate the specs changed in a push
hureva-gate --changed # advisory (exit 0)
hureva-gate --changed --enforced # block if not approved
hureva-gate <slug> --require-all-approvers # gate one spec by slug
hureva-notify / hureva-gate --changed read the GitHub push event
($GITHUB_EVENT_PATH, set by the runner; or --event-file) to get the
before/after commits. Recipients come from the spec's frontmatter roles; each
channel resolves from roster.yml (Slack if present, else email). A name missing
from the roster is reported loudly, never dropped silently.
Channels
Delivery is enabled by the environment (§13.6):
- Slack — set
SLACK_BOT_TOKEN. Handles:#channel, a member ID (U…), or an email (DM resolved viausers.lookupByEmail). - SMTP email — set
SMTP_HOST(+SMTP_PORT,SMTP_USERNAME,SMTP_PASSWORD,SMTP_FROM). Optional; a Slack-only team just doesn't set it.
A channel is used only if its secret is present. --dry-run needs no credentials.
Develop
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hureva-1.0.0.tar.gz.
File metadata
- Download URL: hureva-1.0.0.tar.gz
- Upload date:
- Size: 31.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4f33902806f74df22b6eca9bc021a12197f3f8b33ccddfece1e30501ea33d34
|
|
| MD5 |
cf81d24aafeec6e09981ba9d5eda6bcd
|
|
| BLAKE2b-256 |
ee981e3d756632bd977d100d7526b5eadb5195ead465ada244a9d29077e416d9
|
Provenance
The following attestation bundles were made for hureva-1.0.0.tar.gz:
Publisher:
publish.yml on growth-beaker/hureva
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hureva-1.0.0.tar.gz -
Subject digest:
b4f33902806f74df22b6eca9bc021a12197f3f8b33ccddfece1e30501ea33d34 - Sigstore transparency entry: 2094685575
- Sigstore integration time:
-
Permalink:
growth-beaker/hureva@f1f0a14e32557e841baaf8145b401fa86284a3c8 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/growth-beaker
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f1f0a14e32557e841baaf8145b401fa86284a3c8 -
Trigger Event:
release
-
Statement type:
File details
Details for the file hureva-1.0.0-py3-none-any.whl.
File metadata
- Download URL: hureva-1.0.0-py3-none-any.whl
- Upload date:
- Size: 28.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c41db9f6428e3050c12ac233609f89cd58ae9793493fdf778a5aa156db78bf2a
|
|
| MD5 |
639a77d00dbe4b1fb8e21e3bd337bc68
|
|
| BLAKE2b-256 |
7daf98187b4c164cc61429988b29766df37bb5ddc03c701918dfcb25ed2d4414
|
Provenance
The following attestation bundles were made for hureva-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on growth-beaker/hureva
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hureva-1.0.0-py3-none-any.whl -
Subject digest:
c41db9f6428e3050c12ac233609f89cd58ae9793493fdf778a5aa156db78bf2a - Sigstore transparency entry: 2094686138
- Sigstore integration time:
-
Permalink:
growth-beaker/hureva@f1f0a14e32557e841baaf8145b401fa86284a3c8 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/growth-beaker
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f1f0a14e32557e841baaf8145b401fa86284a3c8 -
Trigger Event:
release
-
Statement type: