# External-orchestrator example: the TEAM owns this loop; spine only checks it.
#
# This Makefile is the team's orchestrator. Config Spine never executes a
# step here — it validates the payloads that cross each seam (Level 1 of the
# runtime adoption ladder). See README.md and
# docs/integration/external_orchestrator.md.
#
#   make               happy path: geometry -> aero -> sizing -> report
#   make FAIL=icd      the aero tool emits an ICD-violating drag table;
#                      `spine check-io` stops the pipeline with a located
#                      SPINE- diagnostic naming the analysis and port
#   make FAIL=team     the team's own aero function crashes; a plain Python
#                      traceback with no spine frames (spine is not in the
#                      call path)
#   make audit         the CI pair: spine validate + spine shadow-audit
#   make clean

SPINE  ?= spine
PYTHON ?= python3
ROOT   ?= $(abspath $(CURDIR)/../..)
FAIL   ?=

RUN     := projects/vehicle_sizing/runs/vehicle_sizing.yaml
BUILD   := $(ROOT)/outputs/external_orchestrator
SESSION := $(BUILD)/shadow-session

# The same library root the vehicle_sizing run manifest declares: the team's
# own package, imported by the team's own steps. No adapter manifests are
# involved anywhere in this pipeline.
export PYTHONPATH := $(ROOT)/examples/team_vehicle
export SEED_FAILURE := $(FAIL)

# Workspace root for the in-process shadow checks (spine.shadow resolves
# explicit root= first, then SPINE_ROOT, then the current directory).
export SPINE_ROOT := $(ROOT)

.PHONY: all geometry aero sizing report audit clean

all: report

# Step 0 - team-owned input preparation. Reads the same geometry artifact the
# spine run manifest pins, so the numbers stay tied to the ICD.
geometry:
	mkdir -p $(BUILD)
	rm -rf $(SESSION)
	$(PYTHON) steps/prepare_geometry.py --root $(ROOT) --out $(BUILD)/geometry.json

# Step 1 - a non-Python tool behind a file handoff. The tool itself adopts
# nothing; `spine check-io` shadow-validates the files on both sides and
# appends a record to the shared session directory.
aero: geometry
	$(SPINE) check-io --analysis vehicle_aero --root $(ROOT) \
		--inputs geometry=$(BUILD)/geometry.json --session $(SESSION)
	$(PYTHON) tools/aero_tool.py $(BUILD)/geometry.json $(BUILD)/aero_out.json
	$(SPINE) check-io --analysis vehicle_aero --root $(ROOT) \
		--outputs $(BUILD)/aero_out.json --session $(SESSION)

# Step 2 - a Python driver step using the two-line shadow pattern inside
# `with shadow.session(...)`. Runs last so the session's report.json folds in
# the check-io records step 1 already dropped into $(SESSION).
sizing: aero
	$(PYTHON) steps/run_sizing.py --root $(ROOT) --build $(BUILD) --session $(SESSION)

# Step 3 - render the session report: per-check pass/fail plus ICD coverage.
report: sizing
	$(SPINE) shadow-report $(SESSION)

# The CI pair (no execution): authored-file validation plus the static check
# that the shadow lines in steps/ have not drifted from the ICD.
audit:
	cd $(ROOT) && $(SPINE) validate --run $(RUN)
	$(SPINE) shadow-audit --root $(ROOT) --path $(CURDIR)/steps

clean:
	rm -rf $(BUILD)
