forjar 1.27.0

Rust-native Infrastructure as Code — bare-metal first, BLAKE3 state, provenance tracing
Documentation
# forjar - Rust CLI Binary Makefile
# Generated by Pragmatic AI Labs MCP Agent Toolkit (pmat)

.PHONY: all check format lint test test-fast bench bench-update build build-release run clean install help coverage audit deny doc-test install-hooks quorum publish-from-tag

# Default target: run all checks and build
all: format check lint test build

# Install tracked git hooks (quality + quorum gates)
install-hooks:
	./scripts/install-hooks.sh

# Verify this branch's quorum receipt (what pre-push runs)
quorum:
	./scripts/quorum-gate.sh

# Type check the code
check:
	cargo check

# Format code with rustfmt
format:
	cargo fmt --all

# Lint with clippy
lint:
	cargo clippy --all-targets -- -D warnings

# Run tests
test:
	cargo test

# Run fast tests (lib only, no integration tests)
test-fast:
	cargo test --lib

# Run benchmarks (Criterion, 95% confidence intervals)
bench:
	cargo bench

# Run benchmarks and update benchmarks/RESULTS.md
bench-update:
	cargo run --release --bin forjar -- bench --iterations 1000 --json \
		| python3 scripts/bench_update.py > benchmarks/RESULTS.md

# Build debug binary
build:
	cargo build

# Build release binary
build-release:
	cargo build --release

# Run the application
run:
	cargo run

# Clean build artifacts
clean:
	cargo clean

# Install the binary to cargo bin directory
install: build-release
	cargo install --path .

# Run coverage analysis
coverage:
	cargo llvm-cov --summary-only --fail-under-lines 95

.PHONY: coverage-check
coverage-check:
	@# The name the pre-release protocol looks for, and the gate it enforces.
	@#
	@# The floor is enforced by llvm-cov ITSELF via --fail-under-lines, never by
	@# parsing a percentage in shell. The protocol warns about precisely that
	@# shape, having watched it print a pass on a broken run:
	@#
	@#     if [ -n "$$COV" ] && [ "$$COV" -lt 95 ]; then fail; else PASS; fi
	@#
	@# An EMPTY percentage — broken instrumentation, a changed summary format,
	@# anything that stops TOTAL parsing — takes the else branch and reports
	@# success. Here an unmeasurable run is a non-zero exit from the tool that
	@# did the measuring, so "unmeasured" and "met" cannot be confused.
	@#
	@# No `|| true` on this line, and none on anything that produces the
	@# measurement: that is the other half of the same defect.
	cargo llvm-cov --summary-only --fail-under-lines 95

# Run security audit
audit:
	cargo audit
	cargo deny check

# Run doc tests
doc-test:
	cargo test --doc

# Show help
help:
	@echo "forjar - Available targets:"
	@echo "  all           - Run format, check, lint, test, and build"
	@echo "  check         - Type check the code"
	@echo "  format        - Format code with rustfmt"
	@echo "  lint          - Run clippy linter"
	@echo "  test          - Run tests"
	@echo "  test-fast     - Run fast tests (lib only)"
	@echo "  bench         - Run benchmarks"
	@echo "  bench-update  - Run benchmarks and update benchmarks/RESULTS.md"
	@echo "  build         - Build debug binary"
	@echo "  build-release - Build optimized release binary"
	@echo "  run           - Run the application"
	@echo "  clean         - Remove build artifacts"
	@echo "  install       - Install the binary"
	@echo "  coverage      - Run coverage analysis (95% minimum)"
	@echo "  coverage-check - Enforce the 95% floor (pre-release gate)"
	@echo "  audit         - Run security audit (cargo-audit + cargo-deny)"
	@echo "  doc-test      - Run documentation tests"
	@echo "  dogfood       - The standing gates B C D G (hermetic; run on every commit)"
	@echo "  dogfood-release - dogfood plus A E (a receipt per merged PR), F (coverage + in-diff mutants) and H (crux); the pre-publish gate"
	@echo "  dogfood-published VERSION=x.y.z - gates C and D against the crate crates.io serves"
	@echo "  release-check - Tag, GitHub release, crates.io, docs.rs, quorum receipts, crux doc"
	@echo "  help          - Show this help message"

# ---------------------------------------------------------------- forjar-dogfood
#
# The eight standing gates of PMAT-163. Each script prints exactly one
# `GATE <letter> PASS|FAIL <detail>` line and its exit code IS the verdict, so
# make's own fail-fast is the aggregation: the first RED stops the target and
# the line above it says what and why. No `-` prefix and no `|| true` anywhere
# below — a gate whose failure is swallowed is a gate that prints.
#
# Which gate runs where, and why the split:
#
#   dogfood           B C D G   cheap, hermetic, no network beyond the API calls
#                               gate B already makes. Safe on every commit.
#   dogfood-release  + A E F H  A and E ask GitHub for the PRs merged since the
#                               last tag and demand a harness receipt and a
#                               quorum receipt for each. They run FIRST because
#                               they take seconds, and a release missing a
#                               receipt should not have to wait on a coverage
#                               build to hear so. F is a full coverage build
#                               plus an in-diff mutation run (minutes); H is RED
#                               until the release's CRUX reconciliation is
#                               written. All four block a PUBLISH, not a commit.
#   dogfood-published           the same C and D against the artifact crates.io
#                               actually serves, which is the only way to catch
#                               a surface that exists in the tree and not in the
#                               shipped binary.
#   release-check               post-tag: tag, release, crates.io, docs.rs,
#                               quorum receipts, crux doc. Pre-tag it reports
#                               the registry arms PENDING rather than FAIL.
.PHONY: dogfood dogfood-release dogfood-published release-check
dogfood:
	bash scripts/dogfood/comply.sh
	bash scripts/dogfood/surface.sh
	bash scripts/dogfood/docs.sh
	bash scripts/dogfood/contracts.sh

dogfood-release: dogfood
	bash scripts/dogfood/harness.sh
	bash scripts/dogfood/quorum.sh
	bash scripts/dogfood/coverage.sh
	bash scripts/dogfood/crux-reconcile.sh

dogfood-published:
	@# VERSION is required and is NOT defaulted to the tree's version: the
	@# whole point of this target is to measure a DIFFERENT artifact, and a
	@# default would let it silently re-measure the tree and pass.
	test -n "$(VERSION)"
	rm -rf /tmp/forjar-scratch
	cargo install forjar --version $(VERSION) --locked --root /tmp/forjar-scratch
	FORJAR_DOGFOOD_BIN=/tmp/forjar-scratch/bin/forjar bash scripts/dogfood/surface.sh
	FORJAR_DOGFOOD_BIN=/tmp/forjar-scratch/bin/forjar bash scripts/dogfood/docs.sh

release-check:
	bash scripts/dogfood/release-check.sh

# Publish the workspace to crates.io from a detached worktree of TAG
# (PMAT-165). Never from the ambient working tree, never --allow-dirty:
#   make publish-from-tag TAG=v1.26.0
#   make publish-from-tag TAG=v1.26.0 DRY_RUN=1
.PHONY: publish-from-tag
publish-from-tag:
	@test -n "$(TAG)" || { echo "usage: make publish-from-tag TAG=vX.Y.Z"; exit 2; }
	DRY_RUN=$(DRY_RUN) bash scripts/publish-from-tag.sh "$(TAG)"

.PHONY: cb200-ratchet
cb200-ratchet:
	@# CB-200 (TDG Grade Gate) is a dated ratchet, not a suppression. The gate
	@# still reports the debt; this asserts it never GROWS. 61 was measured
	@# identical on origin/main and release/1.16.0 (2026-08-21), so this release
	@# introduced none of it. The count is COMPARED, not merely printed: a target
	@# that echoes a number is documentation, and documentation does not fail.
	@bash scripts/cb200-ratchet.sh