-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathMakefile
More file actions
193 lines (156 loc) · 8.45 KB
/
Copy pathMakefile
File metadata and controls
193 lines (156 loc) · 8.45 KB
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
.DEFAULT_GOAL := help
NODE_VERSION ?= $(shell cat .node-version 2>/dev/null || echo 24)
SKILL_EVAL_ROOT ?= /tmp/cc-thingz-skill-eval-root
SKILL_EVAL_WORKSPACE ?= /tmp/cc-thingz-skill-eval-workspace
SKILL_EVAL_INCLUDE ?= **
SKILL_EVAL_SOURCE ?= skills
SKILL_EVAL_TARGET ?= gpt-5.4-mini
SKILL_EVAL_JUDGE ?= gpt-5.4-mini
SKILL_EVAL_LOG_FORMAT ?= jsonl
SKILL_EVAL_LOG_FILE ?= $(SKILL_EVAL_WORKSPACE)/events.jsonl
SKILL_EVAL_REPORT ?= $(SKILL_EVAL_WORKSPACE)/summary.md
SKILL_EVAL_HTML_REPORT ?= 1
SKILL_EVAL_BASELINE ?= 1
SKILL_EVAL_CONCURRENCY ?= 4
SKILL_EVAL_STRICT ?= 1
SKILL_EVAL_CLI ?= $(shell if command -v agent-skills-eval >/dev/null 2>&1; then printf 'agent-skills-eval'; elif command -v bunx >/dev/null 2>&1; then printf 'bunx agent-skills-eval'; elif command -v fnm >/dev/null 2>&1; then printf 'fnm exec --using $(NODE_VERSION) -- npx --yes agent-skills-eval'; else printf 'npx --yes agent-skills-eval'; fi)
# --- Lint ---
.PHONY: lint lint-python lint-shell lint-markdown lint-typescript
lint: lint-python lint-shell lint-markdown lint-typescript ## Run all linters
lint-python: ## Lint Python files with ruff
uv run ruff check .
uv run ruff format --check .
lint-shell: ## Lint shell scripts with shellcheck + shfmt (matches CI's action-sh-checker scope)
@command -v shellcheck >/dev/null 2>&1 || { echo "shellcheck not installed"; exit 1; }
@command -v shfmt >/dev/null 2>&1 || { echo "shfmt not installed"; exit 1; }
find src scripts -name '*.sh' -exec shellcheck {} +
find src scripts -name '*.sh' -exec shfmt -i 0 -d {} +
@# Cover .bats test files and extension-less shell scripts CI also lints
find tests -name '*.bats' -exec shfmt -i 0 -d {} +
shfmt -i 0 -d scripts/git-hooks/pre-commit scripts/git-hooks/pre-push scripts/release/release-tag
lint-markdown: ## Lint Markdown files
@command -v markdownlint-cli2 >/dev/null 2>&1 || { echo "markdownlint-cli2 not installed — skipping"; exit 0; }
markdownlint-cli2 '**/*.md' '!node_modules/**'
lint-typescript: ## Type-check Pi extension TypeScript
bun x tsc --noEmit
# --- Test ---
.PHONY: test test-ts skill-evals-prepare skill-evals skill-evals-fast skill-evals-both skill-evals-summary
test: ## Run pytest suite
uv run --extra test python -m pytest tests/ -v
test-ts: ## Run Bun TypeScript tests (Pi extensions)
bun test src/pi-extensions --isolate
skill-evals-prepare: ## Build temporary Agent Skills eval tree under /tmp
uv run python scripts/evals/prepare-skill-evals.py --out $(SKILL_EVAL_ROOT) --source-dir $(SKILL_EVAL_SOURCE)
skill-evals: skill-evals-prepare ## Run paid Agent Skills evals and print fix-focused summary
@set -u; \
if [ -f .env ]; then set -a; . ./.env; set +a; fi; \
test -n "$${OPENAI_API_KEY:-}" || { echo "OPENAI_API_KEY missing"; exit 2; }; \
mkdir -p $(SKILL_EVAL_WORKSPACE); \
baseline_flag=""; \
if [ "$(SKILL_EVAL_BASELINE)" != "0" ]; then baseline_flag="--baseline"; fi; \
report_flag="--no-report"; \
if [ "$(SKILL_EVAL_HTML_REPORT)" != "0" ]; then report_flag="--report"; fi; \
$(SKILL_EVAL_CLI) $(SKILL_EVAL_ROOT) \
--include '$(SKILL_EVAL_INCLUDE)' \
--workspace $(SKILL_EVAL_WORKSPACE) \
$$baseline_flag \
--target $(SKILL_EVAL_TARGET) \
--judge $(SKILL_EVAL_JUDGE) \
--base-url https://api.openai.com/v1 \
--api-key-env OPENAI_API_KEY \
--concurrency $(SKILL_EVAL_CONCURRENCY) \
--log-format $(SKILL_EVAL_LOG_FORMAT) \
--log-file $(SKILL_EVAL_LOG_FILE) \
--layout iteration \
--strict \
$$report_flag; \
status=$$?; \
uv run python scripts/evals/summarize-skill-evals.py $(SKILL_EVAL_WORKSPACE) --markdown $(SKILL_EVAL_REPORT) || true; \
if [ "$(SKILL_EVAL_STRICT)" = "0" ]; then exit 0; fi; \
exit $$status
skill-evals-fast: ## Fast paid skill eval loop: no baseline, no HTML, higher concurrency, advisory
$(MAKE) skill-evals SKILL_EVAL_BASELINE=0 SKILL_EVAL_HTML_REPORT=0 SKILL_EVAL_CONCURRENCY=8 SKILL_EVAL_STRICT=0
skill-evals-both: ## Run source and Codex/Gemini overlay evals in parallel with separate workspaces
@set +e; \
$(MAKE) skill-evals SKILL_EVAL_SOURCE=skills SKILL_EVAL_ROOT=/tmp/cc-thingz-skill-eval-root-source SKILL_EVAL_WORKSPACE=/tmp/cc-thingz-skill-eval-workspace-source SKILL_EVAL_LOG_FILE=/tmp/cc-thingz-skill-eval-workspace-source/events.jsonl SKILL_EVAL_REPORT=/tmp/cc-thingz-skill-eval-workspace-source/summary.md SKILL_EVAL_STRICT=0 & \
pid1=$$!; \
$(MAKE) skill-evals SKILL_EVAL_SOURCE=skills-codex SKILL_EVAL_ROOT=/tmp/cc-thingz-skill-eval-root-codex SKILL_EVAL_WORKSPACE=/tmp/cc-thingz-skill-eval-workspace-codex SKILL_EVAL_LOG_FILE=/tmp/cc-thingz-skill-eval-workspace-codex/events.jsonl SKILL_EVAL_REPORT=/tmp/cc-thingz-skill-eval-workspace-codex/summary.md SKILL_EVAL_STRICT=0 & \
pid2=$$!; \
wait $$pid1; status1=$$?; \
wait $$pid2; status2=$$?; \
[ $$status1 -eq 0 ] && [ $$status2 -eq 0 ]
skill-evals-summary: ## Print summary for latest skill eval workspace
uv run python scripts/evals/summarize-skill-evals.py $(SKILL_EVAL_WORKSPACE) --markdown $(SKILL_EVAL_REPORT)
# --- Validate ---
# `make build` regenerates every derived artifact idempotently and `make check`
# fails if anything diverges from canonical sources. Per-artifact --check
# targets are gone — they duplicated what `make check` already proves
# end-to-end, and disagreed with each other when generators changed.
.PHONY: validate validate-config validate-executables validate-genericity lint-instructions
validate: validate-config validate-genericity validate-executables ## Validate canonical sources (frontmatter, executable bits, plugin layout)
validate-config: ## Validate plugin configs and frontmatter
uv run python scripts/validate/validate-config.py
validate-genericity: ## Reject Claude-only tokens in vendor-neutral base SKILL.md/AGENT.md
uv run python scripts/validate/validate_genericity.py
lint-instructions: ## Lint agent/skill instructions (advisory)
@uv run python src/skills/reviewing-instructions/scripts/lint-instructions.py
validate-executables: ## Check shell + Python entry scripts have executable bit
@fail=0; \
for f in $$(find src -name 'hook.py' -type f) \
$$(find src scripts -name '*.sh') \
scripts/git-hooks/pre-commit scripts/git-hooks/pre-push scripts/release/release-tag; do \
[ -x "$$f" ] || { echo "ERROR: $$f is not executable"; fail=1; }; \
done; \
[ $$fail -eq 0 ] || exit 1
# --- Format ---
.PHONY: fmt
fmt: ## Auto-format Python and shell files
uv run ruff check --fix .
uv run ruff format .
find src scripts -name '*.sh' -exec shfmt -i 0 -w {} +
shfmt -i 0 -w scripts/git-hooks/pre-commit scripts/git-hooks/pre-push scripts/release/release-tag
# --- One-shot build: regenerate everything derived from canonical sources ---
.PHONY: build check
build: ## Regenerate dist/ and root manifests from canonical sources under src/
uv run python scripts/build/compile.py
check: build ## Build, then fail if any tracked file changed (drift detection)
@if ! git diff --quiet --exit-code; then \
echo "ERROR: derived artifacts drifted. See diff above for either updated sources or hand-edited generated files."; \
echo " Hand-edits to generated files are overwritten by 'make build' — edit canonical sources under src/ instead."; \
git --no-pager diff --stat; \
exit 1; \
fi
@untracked=$$(git ls-files --others --exclude-standard -- dist/ .claude-plugin/ .agents/plugins/ gemini-extension.json); \
if [ -n "$$untracked" ]; then \
echo "ERROR: build produced untracked derived files — add them or remove a stale src/ entry:"; \
echo "$$untracked" | sed 's/^/ /'; \
exit 1; \
fi
@echo "check: clean (all derived artifacts match canonical sources)"
# --- CI (runs everything) ---
.PHONY: ci
ci: lint validate check test test-ts ## Run full CI pipeline locally (lint + validate + build & check drift + tests)
# --- Setup ---
.PHONY: setup
setup: ## Install repo-tracked git hooks (pre-commit + pre-push) and dev deps
git config core.hooksPath scripts/git-hooks
uv sync --extra test
@echo "Setup complete — git hooks active via core.hooksPath=scripts/git-hooks"
# --- Push ---
.PHONY: push
push: ## Push master to origin and all private mirrors (CI rewrites manifests)
git push origin master
git push cc-forge master:main --force-with-lease
# --- Release ---
.PHONY: release
release: ## Create release tag (usage: make release V=1.2.0)
ifndef V
$(error Usage: make release V=1.2.0)
endif
scripts/release/release-tag v$(V)
@echo "Push with: git push origin master v$(V)"
# --- Help ---
.PHONY: help
help: ## Show this help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'