yog 0.0.1

yog: a balls-oriented session manager for lernie loops (egui frontend)
Documentation
.PHONY: all build release test coverage lint fmt fmt-check check run install-hooks install uninstall ci publish clean rules-audit deny

# Install location for `make install`. Defaults to the XDG-ish user-local
# convention; override for system-wide installs or packaging:
#   make install INSTALL_PREFIX=/usr/local
INSTALL_PREFIX ?= $(HOME)/.local
INSTALL_BIN    := $(INSTALL_PREFIX)/bin

# Build output root. Defaults to `target`; the local-CICD plugin
# (scripts/bl-install-main) overrides it to the repo's own target/ while
# building from an ephemeral worktree, so the release build stays incremental.
# Exported so the cargo invocations below honor it too.
CARGO_TARGET_DIR ?= target
export CARGO_TARGET_DIR

all: check

build:
	cargo build

release:
	cargo build --release

# Tests run in parallel. Fixtures write throwaway executables and fork
# subprocesses; every fork in the test binary routes through one
# `SPAWN_LOCK` spawn discipline (see `src/lib.rs` `test_support`), so a fork
# can never inherit a not-yet-closed write fd on a script another test is
# about to exec (the ETXTBSY race that once forced serial runs).
test:
	cargo test

TARPAULIN_PIN := 0.35.2

coverage:
	@have=$$(cargo tarpaulin --version 2>/dev/null | awk '{print $$NF}'); \
	if [ "$$have" != "$(TARPAULIN_PIN)" ]; then \
	  echo "tarpaulin $(TARPAULIN_PIN) required (have: $${have:-none}); see tarpaulin.toml" >&2; \
	  echo "  cargo install cargo-tarpaulin --version $(TARPAULIN_PIN) --locked" >&2; \
	  exit 1; \
	fi
	cargo tarpaulin --fail-under 100 --skip-clean --engine llvm --out Stdout

# The complete static gate: clippy (reads Cargo.toml [lints]) + the ast-grep
# rules audit + the cargo-deny supply-chain audit. All three are pinned so the
# gate is reproducible — ast-grep 0.44.1 (sgconfig.yml), cargo-deny 0.20.2
# (deny.toml), toolchain 1.95.0 (rust-toolchain.toml). CI runs this exact target
# via `make ci`; there is no CI-only lint step to drift from.
lint:
	cargo clippy --all-targets -- -D warnings
	$(MAKE) rules-audit
	$(MAKE) deny

# Supply-chain audit (cargo-deny 0.20.2 — see deny.toml): licenses, advisories
# (yanked + the three ignored eframe-stack RUSTSECs), bans (openssl-sys /
# native-tls — yog has no TLS surface), and known-registry sources.
deny:
	cargo deny check

# Static audit of every ast-grep rule (rules/, pinned ast-grep 0.44.1 — see
# sgconfig.yml). Both directions: `src` must be clean (exit 0), and every
# deliberate violation in rules/fixtures must fire (scan exits non-zero) so a
# silently-broken rule cannot pass unnoticed. Rules: `unsafe` confined to
# cli_outbound/sys.rs, `Mutex`/`RwLock` confined to state.rs, no `Rc`/`RefCell`
# anywhere.
rules-audit:
	ast-grep scan src
	@if ast-grep scan rules/fixtures >/dev/null 2>&1; then \
	  echo "rules-audit: rules/fixtures was NOT flagged — a rule has regressed" >&2; \
	  exit 1; \
	fi
	@echo "rules-audit: src clean; fixtures flagged (all rules live)"

fmt:
	cargo fmt

fmt-check:
	cargo fmt --check

check: fmt-check lint coverage

# Launch the window over every enumerated workspace (plain `cargo run`, no
# REPO). Optionally preset the startup focus on one workspace with WS=:
#   make run
#   make run WS=/path/to/workspace
run:
	@if [ -n "$(WS)" ]; then \
	  cargo run --quiet -- --workspace "$(WS)"; \
	else \
	  cargo run --quiet; \
	fi

install-hooks:
	git config core.hooksPath .githooks
	@echo "hooks: core.hooksPath -> .githooks"

install: release
	@mkdir -p "$(INSTALL_BIN)"
	@install -m 0755 $(CARGO_TARGET_DIR)/release/yog "$(INSTALL_BIN)/yog"
	@echo "installed $(INSTALL_BIN)/yog"
	@echo "note: the window drives the 'lernie' binary; install it from the lernie repo."

uninstall:
	@rm -f "$(INSTALL_BIN)/yog" && echo "removed $(INSTALL_BIN)/yog"

ci: check

# Publish to crates.io. The dry-run always runs; the real upload runs ONLY
# with an explicit CONFIRM=yes. Publishing 0.0.1 is a deliberate human
# decision, never a side effect of running this target.
#   make publish              # dry-run only
#   make publish CONFIRM=yes  # dry-run, then real publish
publish:
	cargo publish --dry-run --locked
ifeq ($(CONFIRM),yes)
	cargo publish --locked
else
	@echo "dry-run passed. Publishing is an explicit decision: re-run with 'make publish CONFIRM=yes'."
endif

clean:
	cargo clean