aicx 0.9.2

Operator CLI + MCP server: canonical corpus first, optional semantic index second (Claude Code, Codex, Gemini)
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
# AICX Build System
# Local developer flow + release/readiness helpers

# --- Cargo PATH discovery ---------------------------------------------------
# Surface cargo from ~/.cargo/bin when the calling shell (uv-run, sh -c,
# CI runners that strip PATH) didn't source ~/.cargo/env. Idempotent —
# no-op when cargo is already reachable, silent when rustup isn't installed.
ifeq (,$(shell command -v cargo 2>/dev/null))
  ifneq (,$(wildcard $(HOME)/.cargo/bin/cargo))
    export PATH := $(HOME)/.cargo/bin:$(PATH)
  endif
endif

.PHONY: all build build-native release-binaries install install-bin install-config install-cargo git-hooks
.PHONY: precheck precheck-native test test-native check fmt fmt-check clippy clippy-native semgrep ci clean help manifest-check
.PHONY: embeddings-check embeddings-test embeddings-clippy embeddings-hydrate embeddings-info
.PHONY: version version-show version-check version-bump version-patch bump-patch changelog-close release-notes release-plan release-prepare release-check release-tag release-push package-check release-bundle release-bundle-only-binaries test-e2e

all: build

PACKAGE_NAME := $(shell grep '^name = ' Cargo.toml | head -n 1 | cut -d '"' -f 2)
VERSION := $(shell grep '^version = ' Cargo.toml | head -n 1 | cut -d '"' -f 2)
TAG := v$(VERSION)

# --- Python discovery (release tooling needs stdlib tomllib, i.e. 3.11+) ----
# macOS system python3 is 3.9 (no tomllib). Pick the newest available 3.11+
# from PATH; fall back to plain python3 (scripts will fail-fast with a clear
# message if it's < 3.11).
PYTHON := $(shell command -v python3.14 2>/dev/null || command -v python3.13 2>/dev/null || command -v python3.12 2>/dev/null || command -v python3.11 2>/dev/null || command -v python3)
KEYS ?= $(if $(AICX_KEYS_DIR),$(AICX_KEYS_DIR),$(HOME)/.keys)
NOTARY_PROFILE ?= $(AICX_NOTARY_PROFILE)
CLEAN ?= 1
EMBEDDER_PROFILE ?= base
NATIVE ?= 0
FEATURES ?=
TARGET ?= $(shell rustc -vV | sed -n 's/^host: //p')
CODESIGN ?= auto
CARGO_BUILD ?= cargo build
DIST_DIR ?= $(CURDIR)/dist
DRY_RUN ?= 0
RELEASE_BINARIES := aicx aicx-mcp

build:
	cargo build --locked --release --bin aicx --bin aicx-mcp

build-native:
	cargo build --locked --release --features native-embedder --bin aicx --bin aicx-mcp

release-binaries:
	@if [ -z "$(STAGING_DIR)" ]; then \
		echo "STAGING_DIR is required. Usage: make release-binaries STAGING_DIR=/tmp/stage TARGET=$(TARGET)" >&2; \
		exit 1; \
	fi
	$(CARGO_BUILD) --locked --release --target "$(TARGET)" --bin aicx --bin aicx-mcp
	@mkdir -p "$(STAGING_DIR)/bin" "$(STAGING_DIR)/components"
	@for bin in $(RELEASE_BINARIES); do \
		install -m 0755 "target/$(TARGET)/release/$$bin" "$(STAGING_DIR)/bin/$$bin"; \
		printf '  %s -> %s\n' "$$bin" "$(STAGING_DIR)/bin/$$bin"; \
	done
	@case "$(TARGET)" in \
		*apple-darwin) \
			if [ "$(CODESIGN)" = "0" ]; then \
				echo "  codesign skipped (CODESIGN=0)"; \
			elif [ -n "$${MACOS_DEVELOPER_ID_APPLICATION:-}" ]; then \
				for bin in $(RELEASE_BINARIES); do \
					codesign --force --timestamp --options runtime --sign "$$MACOS_DEVELOPER_ID_APPLICATION" "$(STAGING_DIR)/bin/$$bin"; \
					codesign --verify --verbose=2 "$(STAGING_DIR)/bin/$$bin" >/dev/null; \
					printf '  codesigned %s\n' "$$bin"; \
				done; \
			elif [ "$(CODESIGN)" = "1" ]; then \
				echo "MACOS_DEVELOPER_ID_APPLICATION is required for CODESIGN=1" >&2; \
				exit 1; \
			else \
				echo "  codesign skipped (set CODESIGN=1 and MACOS_DEVELOPER_ID_APPLICATION for release)"; \
			fi ;; \
	esac
	@$(PYTHON) -c 'import json, pathlib, sys; staging=pathlib.Path(sys.argv[1]); version=sys.argv[2]; commit=sys.argv[3]; data={"source":"loctree-aicx","commit":commit,"components":[{"name":"aicx","version":version,"source":"loctree-aicx"},{"name":"aicx-mcp","version":version,"source":"loctree-aicx"}]}; path=staging/"components"/"loctree-aicx.json"; path.write_text(json.dumps(data, indent=2)+"\n", encoding="utf-8"); print(f"  metadata -> {path}")' "$(STAGING_DIR)" "$(VERSION)" "$$(git rev-parse --short=12 HEAD)"

release-binaries-linux:
	@for target in x86_64-unknown-linux-gnu aarch64-unknown-linux-musl; do \
		echo "==> Building $$target"; \
		cross build --release --target $$target --bin aicx --bin aicx-mcp || exit 1; \
		mkdir -p dist/aicx-v$(VERSION)-$$target-slim-unsigned; \
		cp target/$$target/release/aicx target/$$target/release/aicx-mcp dist/aicx-v$(VERSION)-$$target-slim-unsigned/; \
		(cd dist && tar -czf aicx-v$(VERSION)-$$target-slim-unsigned.tar.gz aicx-v$(VERSION)-$$target-slim-unsigned/); \
	done

install:
	./install.sh
	@$(MAKE) git-hooks

install-bin:
	AICX_INSTALL_MODE=local ./install.sh --shadow-check-only
	cargo install --path . --locked --force --bin aicx --bin aicx-mcp
	AICX_INSTALL_MODE=local ./install.sh --verify-path-only

install-config:
	./install.sh --skip-install

install-cargo:
	@echo "crates.io install is not the active AICX distribution path."
	@echo "Use GitHub Release bundles, npm, Homebrew tap, or a local checkout install."
	@echo "For this checkout, run: make install-bin"

git-hooks:
	@echo "Installing git hooks..."
	@bash ./tools/install-githooks.sh
	@echo "✓ pre-commit + pre-push hooks installed"

precheck:
	cargo check --locked -p aicx --all-targets
	cargo check --locked -p aicx-embeddings

precheck-native:
	cargo check --locked -p aicx-embeddings --features gguf
	cargo check --locked -p aicx --features native-embedder --all-targets

manifest-check:
	@$(PYTHON) -c 'import sys, re; text = open("Cargo.toml", "r").read(); bad = [m.group(1) for m in re.finditer(r"^([\w-]+)\s*=.*path\s*=", text, re.MULTILINE) if m.group(1) not in ("rmcp-memex", "aicx-embeddings", "aicx-retrieve", "aicx-parser", "aicx-monitor", "aicx-progress-contracts", "path")]; sys.exit("Manifest policy check failed:\n  - Unexpected local path dependency: " + ", ".join(bad)) if bad else print("Manifest policy: ok (approved local product deps only)")'

test:
	cargo test --locked -p aicx --all-targets
	cargo test --locked -p aicx-embeddings

test-native:
	cargo test --locked -p aicx-embeddings --features gguf
	cargo test --locked -p aicx --features native-embedder --test native_embedder

# End-to-end pipeline test against operator's canonical ~/.aicx/config.toml.
# Fail-fast when preconditions missing (no config, empty corpus, embedder
# unreachable) per operator doctrine — distinct from a CI test that
# silently skips on missing infra.
test-e2e:
	cargo test --locked -p aicx --features e2e-aicx --test e2e_pipeline -- --nocapture
	cargo test --locked -p aicx --features e2e-aicx --test e2e_context_pack_ingest -- --nocapture

test-retrieval-eval:
	cargo test --test retrieval_eval_harness

test-retrieval-eval-live:
	cargo test --test retrieval_eval_harness --features e2e-aicx -- --nocapture

test-retrieval-eval-rebaseline:
	AICX_RETRIEVAL_EVAL_WRITE_BASELINE=1 cargo test --test retrieval_eval_harness --features e2e-aicx -- --nocapture

check:
	@echo "=== AICX Quality Gate ==="
	@echo "[1/10] Checking manifest portability..."
	@$(MAKE) manifest-check
	@echo "[2/10] Checking formatting..."
	@cargo fmt --all --check || (echo "Run 'make fmt' to fix formatting." && exit 1)
	@echo "[3/10] Running default cargo check..."
	@$(MAKE) precheck
	@echo "[4/10] Running native GGUF cargo check..."
	@$(MAKE) precheck-native
	@echo "[5/10] Running default clippy..."
	@$(MAKE) clippy
	@echo "[6/10] Running native GGUF clippy..."
	@$(MAKE) clippy-native
	@echo "[7/10] Running default tests..."
	@$(MAKE) test
	@echo "[8/10] Running native GGUF tests..."
	@$(MAKE) test-native
	@echo "[9/10] Building slim release binaries..."
	@cargo build --locked --release --bin aicx --bin aicx-mcp
	@echo "[10/10] Running Semgrep (if available)..."
	@if command -v semgrep >/dev/null 2>&1 || command -v pipx >/dev/null 2>&1; then \
		SEMGREP=$$(command -v semgrep || echo "pipx run semgrep"); \
		$$SEMGREP --config auto --error --quiet . --exclude target; \
	else \
		echo "[!] Semgrep not available, skipping (install: pipx install semgrep)"; \
	fi
	@echo "=== All checks passed ==="

fmt:
	cargo fmt --all

fmt-check:
	cargo fmt --all --check

clippy:
	cargo clippy --locked -p aicx --all-targets -- -D warnings
	cargo clippy --locked -p aicx-embeddings -- -D warnings

clippy-native:
	cargo clippy --locked -p aicx-embeddings --features gguf -- -D warnings
	cargo clippy --locked -p aicx --features native-embedder --all-targets -- -D warnings

embeddings-info:
	@case "$(EMBEDDER_PROFILE)" in \
		base) repo="mradermacher/F2LLM-v2-0.6B-GGUF"; file="F2LLM-v2-0.6B.Q4_K_M.gguf"; size="~397 MB"; dim="1024";; \
		dev) repo="mradermacher/F2LLM-v2-1.7B-GGUF"; file="F2LLM-v2-1.7B.Q4_K_M.gguf"; size="~1.1 GB"; dim="2048";; \
		premium) repo="mradermacher/F2LLM-v2-1.7B-GGUF"; file="F2LLM-v2-1.7B.Q6_K.gguf"; size="~1.4 GB"; dim="2048";; \
		*) echo "Unsupported EMBEDDER_PROFILE=$(EMBEDDER_PROFILE). Use base, dev, or premium." >&2; exit 1;; \
	esac; \
	printf "profile: %s\nrepo: %s\nfile: %s\nsize: %s\ndim: %s\n" "$(EMBEDDER_PROFILE)" "$$repo" "$$file" "$$size" "$$dim"

embeddings-hydrate:
	@if ! command -v hf >/dev/null 2>&1; then \
		echo "Missing 'hf' CLI. Install HuggingFace CLI first, then retry."; \
		exit 1; \
	fi
	@case "$(EMBEDDER_PROFILE)" in \
		base) repo="mradermacher/F2LLM-v2-0.6B-GGUF"; file="F2LLM-v2-0.6B.Q4_K_M.gguf";; \
		dev) repo="mradermacher/F2LLM-v2-1.7B-GGUF"; file="F2LLM-v2-1.7B.Q4_K_M.gguf";; \
		premium) repo="mradermacher/F2LLM-v2-1.7B-GGUF"; file="F2LLM-v2-1.7B.Q6_K.gguf";; \
		*) echo "Unsupported EMBEDDER_PROFILE=$(EMBEDDER_PROFILE). Use base, dev, or premium." >&2; exit 1;; \
	esac; \
	echo "Hydrating AICX native embedder: $$repo $$file"; \
	hf download "$$repo" "$$file"

embeddings-check:
	cargo check --locked -p aicx-embeddings --features gguf

embeddings-test:
	cargo test --locked -p aicx-embeddings --features gguf

embeddings-clippy:
	cargo clippy --locked -p aicx-embeddings --features gguf -- -D warnings

semgrep:
	@if command -v semgrep >/dev/null 2>&1 || command -v pipx >/dev/null 2>&1; then \
		SEMGREP=$$(command -v semgrep || echo "pipx run semgrep"); \
		$$SEMGREP --config auto --error --quiet . --exclude target; \
	else \
		echo "[!] Semgrep not available, skipping (install: pipx install semgrep)"; \
	fi

ci: check
	@echo "CI-equivalent local checks passed."

version: version-show

version-show:
	@printf "package: %s\n" "$(PACKAGE_NAME)"
	@printf "version: %s\n" "$(VERSION)"
	@printf "tag: %s\n" "$(TAG)"
	@if git rev-parse --verify "refs/tags/$(TAG)" >/dev/null 2>&1; then \
		echo "tag-state: exists"; \
	else \
		echo "tag-state: missing"; \
	fi

version-check:
	@$(PYTHON) tools/release_sync.py check
	@bash tools/release-channel-check.sh

version-bump:
ifeq ($(origin VERSION),command line)
	@$(PYTHON) tools/release_sync.py bump "$(VERSION)"
	@echo ""
	@echo "Versioned release surfaces synced from Cargo.toml into workspace crates + docs + distribution/npm."
	@echo "Cargo.lock is intentionally not touched by version-bump."
	@echo "To sync the lockfile for all workspace packages (no network):"
	@echo "  cargo update --workspace --offline"
	@echo "Or rely on 'make release-prepare' to sync it for you."
else
	@echo "VERSION is required. Usage: make version-bump VERSION={patch|minor|major|x.y.z}" >&2 && exit 1
endif

version-patch bump-patch:
	@$(MAKE) version-bump VERSION=patch

changelog-close:
	@$(PYTHON) tools/changelog_close.py $(if $(CHANGELOG_GENERATE),--generate-if-empty)

release-notes:
	@$(PYTHON) tools/release_sync.py notes $(if $(origin VERSION),$(VERSION),) $(if $(OUTPUT),--output $(OUTPUT),)

release-plan:
	@echo "AICX release flow"
	@echo ""
	@echo "1. Ensure branch is merged and green."
	@echo "2. Prepare the release bundle:"
	@echo "     make release-prepare VERSION={patch|minor|major|x.y.z}"
	@echo "   (runs version-bump + changelog-close + release-notes preview + precheck)"
	@echo "3. Review diff, commit Cargo.toml + Cargo.lock + CHANGELOG.md + any synced docs/package manifests."
	@echo "4. Run: make release-check"
	@echo "5. Create annotated tag: make release-tag"
	@echo "6. Push tag: make release-push"
	@echo "7. Wait for GitHub Actions to build signed release archives from the pushed tag."
	@echo "8. Publish npm after GitHub Release assets exist:"
	@echo "     gh workflow run npm-publish.yml -f version=$(VERSION)"
	@echo "9. Optional local macOS signed bundle:"
	@echo "     make release-bundle KEYS=$(HOME)/.keys"
	@echo "     make release-bundle KEYS=$(HOME)/.keys NATIVE=1"
	@echo "     make release-bundle KEYS=$(HOME)/.keys NOTARY_PROFILE=my-notary-profile"
	@echo "     make release-bundle KEYS=$(HOME)/.keys CLEAN=0    # keep local target artifacts"
	@echo "10. Optional native embedder sanity:"
	@echo "     make embeddings-info EMBEDDER_PROFILE=base"
	@echo "     make embeddings-hydrate EMBEDDER_PROFILE=base"
	@echo "     make test-native"
	@echo "11. GitHub Actions release workflow builds archives and derives GitHub release notes from CHANGELOG.md."
	@echo ""
	@echo "Reference docs:"
	@echo "  - docs/RELEASES.md"
	@echo "  - docs/COMMANDS.md"

release-prepare:
ifeq ($(origin VERSION),command line)
	@$(MAKE) version-bump VERSION=$(VERSION)
	@$(MAKE) changelog-close CHANGELOG_GENERATE=1
	@cargo update --workspace --offline
	@$(MAKE) version-check
	@$(PYTHON) tools/release_sync.py notes --output dist/release-notes.md
	@$(MAKE) precheck
else
	@echo "VERSION is required. Usage: make release-prepare VERSION={patch|minor|major|x.y.z}" >&2 && exit 1
endif
	@echo ""
	@echo "=== Release prepared ==="
	@echo "Next: review diff, commit, then:"
	@echo "  make release-check"
	@echo "  make release-tag"
	@echo "  make release-push"
	@echo "  cat dist/release-notes.md   # preview GitHub release body"
	@echo "  make release-bundle KEYS=$(HOME)/.keys [CLEAN=0]"

release-check:
	@bash tools/release-channel-check.sh
	@$(PYTHON) tools/release_sync.py check --require-version-section
	@$(MAKE) check
	@echo "Release readiness passed."

release-tag:
	@if git rev-parse --verify "refs/tags/$(TAG)" >/dev/null 2>&1; then \
		echo "Tag $(TAG) already exists."; \
		exit 1; \
	fi
	@key="$${LOCTREE_GPG_KEY_ID:-}"; \
	if [ -z "$$key" ]; then \
		echo "LOCTREE_GPG_KEY_ID is not set — refusing to create unsigned release tag." >&2; \
		echo "Export the org's GPG key id in your shell (zshrc) or pass LOCTREE_GPG_KEY_ID=... inline." >&2; \
		exit 1; \
	fi; \
	pp="$${LOCTREE_GPG_PASSPHRASE_FILE:-$$HOME/.keys/.gpg.passphrase}"; \
	if [ -r "$$pp" ]; then \
		echo "warmup" | gpg --batch --pinentry-mode loopback --passphrase-file "$$pp" --local-user "$$key" --detach-sign -o /dev/null 2>/dev/null || true; \
	fi; \
	git tag -as -u "$$key" "$(TAG)" -m "Release $(TAG)"
	@echo "Created GPG-signed annotated tag $(TAG)"

release-push:
	git push origin "$(TAG)"

package-check:
	@echo "crates.io packaging is intentionally disabled for aicx."
	@echo "Use GitHub Release archives + npm platform packages instead."
	@echo "Run: make release-check"

release-bundle:
	@KEYS="$(KEYS)" \
	NOTARY_PROFILE="$(NOTARY_PROFILE)" \
	TARGET="$(TARGET)" \
	DIST_DIR="$(DIST_DIR)" \
	DRY_RUN="$(DRY_RUN)" \
	AICX_CLEAN_AFTER_BUILD="$(CLEAN)" \
	NATIVE="$(NATIVE)" \
	FEATURES="$(FEATURES)" \
	PACKAGE_NAME="$(PACKAGE_NAME)" \
	./tools/release_bundle.sh

release-bundle-only-binaries:
	@AICX_RELEASE_BUNDLE_ONLY_BINARIES=1 \
	TARGET="$(TARGET)" \
	DIST_DIR="$(DIST_DIR)" \
	DRY_RUN="$(DRY_RUN)" \
	AICX_CLEAN_AFTER_BUILD="$(CLEAN)" \
	NATIVE="$(NATIVE)" \
	FEATURES="$(FEATURES)" \
	PACKAGE_NAME="$(PACKAGE_NAME)" \
	./tools/release_bundle.sh

clean:
	cargo clean

# Help colors
HELP_C_CYAN   := \033[36m
HELP_C_GREEN  := \033[32m
HELP_C_YELLOW := \033[33m
HELP_C_RESET  := \033[0m

help:
	@printf '\n$(HELP_C_CYAN)%s$(HELP_C_RESET)\n' 'AICX Build System'
	@printf '\n'
	@printf '  $(HELP_C_YELLOW)%s$(HELP_C_RESET)\n' 'CORE COMMANDS'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'build' '- Build release binaries (aicx + aicx-mcp)'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'build-native' '- Build release binaries with native GGUF embedder support'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'install' '- Install binaries + configure local MCP clients via install.sh'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'install-bin' '- Install only aicx + aicx-mcp from the current checkout'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'install-config' '- Configure local MCP clients without reinstalling binaries'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'install-cargo' '- Explain why crates.io install is not the active path'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'git-hooks' '- Install repo-local pre-commit + pre-push hooks'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'precheck' '- Quick default cargo check'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'precheck-native' 'Quick native GGUF cargo check'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'manifest-check' '- Fail if Cargo.toml uses local path dependencies'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'check' '- Full local gate (fmt, check, clippy, test, build, semgrep)'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'test' '- Run all tests'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'test-native' '- Run native GGUF embedder tests'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'fmt' '- Format all Rust code'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'clean' '- Clean build artifacts'
	@printf '\n'
	@printf '  $(HELP_C_YELLOW)%s$(HELP_C_RESET)\n' 'NATIVE EMBEDDINGS'
	@printf '%s\n' '  make embeddings-info EMBEDDER_PROFILE=base|dev|premium     - Show GGUF profile details'
	@printf '%s\n' '  make embeddings-hydrate EMBEDDER_PROFILE=base|dev|premium  - Download selected GGUF into HF cache'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'embeddings-check' '- Check aicx-embeddings with GGUF backend'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'embeddings-test' '- Test aicx-embeddings with GGUF backend'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'embeddings-clippy' '- Clippy aicx-embeddings with GGUF backend'
	@printf '\n'
	@printf '  $(HELP_C_YELLOW)%s$(HELP_C_RESET)\n' 'RELEASE / VERSION'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'version' '- Alias for version-show'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'version-show' '- Show package version and tag state'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'version-check' '- Validate synced release surfaces (Cargo/docs/npm/changelog basics)'
	@printf '%s\n' '  make version-bump VERSION=X - Bump version and sync docs/npm surfaces. X={patch|minor|major|x.y.z}'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'version-patch' '- Alias for version-bump VERSION=patch'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'bump-patch' '- Alias for version-bump VERSION=patch'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'changelog-close' "- Close CHANGELOG '## [Unreleased]' to current version + date"
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'release-notes' '- Print release notes body derived from CHANGELOG current version section'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'release-plan' '- Print the full post-merge release flow'
	@printf '%s\n' '  make release-prepare VERSION=X - version-bump + changelog-close + notes preview + precheck. X={patch|minor|major|x.y.z}'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'release-check' '- Strict release readiness gate'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'release-tag' '- Create annotated tag from Cargo.toml version'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'release-push' '- Push the current release tag to origin'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'package-check' '- Explain binary-release packaging track'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'release-bundle' '- Local macOS bundle + codesign + notarize using KEYS/NOTARY_PROFILE (NATIVE=1 for GGUF backend)'
	@printf '\n'
	@printf '  $(HELP_C_YELLOW)%s$(HELP_C_RESET)\n' 'QUICK START'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'install' '- Contributor/local operator setup'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'check' '- Full local verification'
	@printf '    $(HELP_C_GREEN)%-18s$(HELP_C_RESET) %s\n' 'release-plan' '- Review release flow before tagging'