# tatlock-ui — the repo's command surface (D-27).
#
# Flutter rather than Python, so there is no venv and no PYTHON here. The
# reason the targets still exist under these names is the point of D-27: an
# agent or a person can run `make test` in any repo in this workspace without
# first working out which stack it is.

.DEFAULT_GOAL := help

.PHONY: help
help: ## Show this help
	@grep -hE '^[a-z][a-z0-9_-]*:.*?## ' $(MAKEFILE_LIST) \
	  | awk 'BEGIN{FS=":.*?## "}{printf "  \033[36m%-14s\033[0m %s\n", $$1, $$2}'

.PHONY: setup
setup: ## Fetch dependencies and generate code (run this after a fresh clone)
	flutter pub get
	$(MAKE) generate
	@ci/check_codegen.sh

.PHONY: generate
generate: ## Regenerate freezed/json_serializable/riverpod sources
	dart run build_runner build --delete-conflicting-outputs

.PHONY: check-codegen
check-codegen: ## Prove every part directive has a generated file on disk
	@ci/check_codegen.sh

.PHONY: test
test: ## Run the widget and unit tests
	@ci/check_codegen.sh \
	  || { echo "FAIL — generated sources missing or stale; run: make setup"; exit 69; }
	flutter test

# Why the guard above: *.freezed.dart and lib/**/*.g.dart are gitignored, so a
# fresh clone has none of them and most of the suite fails to compile rather
# than to assert. On 2026-08-09 that read as "26 passed, 17 failed" — which
# looks like broken tests and is actually a missing build step. After
# generating, the same suite is 452 passed. A test run that cannot compile
# should say so in those words.
#
# `setup` and `test` both call ci/check_codegen.sh rather than one calling
# the other's target, because `setup`'s job is "make the tree usable" (fails
# loud if codegen silently produced less than the tree needs) and `test`'s
# job is "is the tree usable right now" (fails loud if nobody ran setup at
# all, or ran it before a source file changed). Same check, two different
# questions, so a shared script rather than a shared Make target — a Make
# target can only be reused by depending on it, which would make `test`
# imply `flutter pub get` and `build_runner`, both slow, every run.
#
# The check walks every `part '<name>.g.dart'`/`part '<name>.freezed.dart'`
# directive under lib/ and confirms the named sibling file exists — not one
# sentinel file (the previous guard checked only
# user_preferences.freezed.dart, which would have missed 44 of the 45
# directives that exist today). See ci/check_codegen.sh for why this is
# preferred over `flutter analyze`: cheaper, and it targets exactly the
# generated/ungenerated distinction rather than static analysis in general.

.PHONY: lint
lint: ## Static analysis (analysis_options.yaml at the repo root)
	flutter analyze

.PHONY: build
build: ## Release build for the web target
	flutter build web --release

.PHONY: clean
clean: ## Remove build artefacts and the pub cache for this project
	flutter clean

# git hands a hook a non-login shell, which never sees ~/.local/bin — where
# gitleaks lands. Without this the scan reports "not installed" on every push,
# which is a check that fails open (D-24).
export PATH := $(HOME)/.local/bin:/usr/local/bin:$(PATH)

.PHONY: secrets
secrets: ## Scan the commits about to be pushed for credentials
	@ci/secrets.sh

# The call surface is identical in every repo; what it runs is not.
#
# `secrets` runs first, deliberately: it is the only failure here that cannot be
# undone by fixing it afterwards. A failed lint costs another commit; a pushed
# credential is cached and indexed whether or not it is later deleted.
#
# Some of these fail today, and are left wired anyway. The state was measured
# once and written down in T-56 rather than being worked around here — a gate
# quietly narrowed to what already passes is a gate that reports success for
# doing nothing, which is the failure this workspace keeps rediscovering.
.PHONY: pre-push
pre-push: secrets lint ## Everything the pre-push hook runs
	@echo "  --   not gated here yet: test (T-56)"
