@praxisflux/gates
v0.54.0
Published
praxisflux gate checks as a zero-dependency CLI (spec-bridge, wiki-freshness, course) — status can't exceed proven artifacts
Readme
Consuming praxisflux gates from another repo
praxisflux's gates — "status can't exceed proven artifacts" — are enforceable in repos that don't carry praxisflux itself. There are two enforcement points, deliberately split the same way praxisflux splits them for its own development:
- Locally / interactively: the installed plugins' Stop hooks run the gates as you work.
These float with plugin updates and are advisory and opt-in by design — they exist
only where a plugin is installed, and they never block over a missing runtime (a
gate.shthat can't findnodenotices once on stderr, then no-ops). - In CI: the composite GitHub Action runs the same gates at a pinned release. CI is authoritative. Pin drift between local and CI is fine by design.
The tenet this split delivers: gates make dishonest status expensive locally and impossible in CI. Local hooks raise the cost of overstating what's proven while you work; the CI surface below is where an overstated status actually cannot land.
The action
jobs:
gates:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # wiki-freshness resolves pins through git history
- uses: evanstern/[email protected]
with:
gates: spec-bridge, wiki-freshnessThe action runs the gates via npx @praxisflux/gates@<version> — the npm package carved from
the same tree, pinned in lockstep with the tag you chose, and guaranteed live before the tag
exists (release order: npm publish, then tag). No install step, no dependencies (the gates
are zero-dependency Node, and every runner ships node + npm). Upgrade by bumping the tag;
Dependabot's github-actions ecosystem automates that.
Inputs
| input | default | meaning |
|--------------|---------------|---------|
| gates | (required) | Comma-separated: spec-bridge, wiki-freshness, course. An unknown name fails the build — gates never skip silently. |
| path | . | Repository root to check, relative to the workspace. |
| wiki-dir | docs/wiki | Grounded-corpus directory for wiki-freshness. |
| course-dir | docs/course | Built course directory for the course gate. |
The gates
spec-bridge— every Backlog task linked to a Spec Kit spec dir carries a status its spec artifacts prove (needs abacklog/dir; passes trivially with zero linked tasks). The gate honors the checked repo's own.spec-bridge.json:strictDone(analyze-gated Done) andstatusVocabulary(opt-in phase-level status names, enforced at that finer granularity). The contract for both lives inspec-bridge/README.md.wiki-freshness— everydocs/wikinote is fresh against itsverified_againstpin (needs full git history:fetch-depth: 0; a shallow clone fails with exactly that fix).course— a built codebase-to-course course passes its output gate (self-contained, quizzes/translations per module, current chrome stamp).
The npm package
The same surface ships on npm as @praxisflux/gates (published with provenance by the
release pipeline, version lockstep with the marketplace release), so non-GitHub CI and
one-off local runs need no praxisflux checkout:
npx @praxisflux/gates --gates spec-bridge,wiki-freshness --path /path/to/repoThe package's bin (praxisflux-gates) is scripts/run-gates.mjs itself, carved out by
scripts/build-npm.mjs with the chassis and gate modules alongside — same flags, same exit
codes, same failure lines.
The contract
Gate names, inputs, and exit codes (0 all pass · 1 any gate failed — a gate that crashes
while running counts as failed · 2 usage error) are
praxisflux's versioned consumer interface, released and semver-bumped like everything else
(docs/releasing.md); each failure line names its fix. You can also invoke the runner
directly from any praxisflux checkout:
node scripts/run-gates.mjs --gates spec-bridge,wiki-freshness --path /path/to/repo