Repository navigation
Expand file tree
/
Copy pathworkflow.sh
More file actions
executable file
·417 lines (391 loc) · 12.4 KB
/
Copy pathworkflow.sh
File metadata and controls
executable file
·417 lines (391 loc) · 12.4 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
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
#!/usr/bin/env bash
# Local monorepo workflow: Rust core → SDK artifacts → main app (src/) (no registry publish).
#
# The main app (./src/cyt/) uses cyt-indexer-sdk from sdk/python via pyproject.toml:
# [tool.uv.sources]
# cyt-indexer-sdk = { path = "sdk/python", editable = true }
# Production installs (pip install clear-your-tools) pull cyt-indexer-sdk from PyPI instead.
#
# Usage:
# ./scripts/local/dev/workflow.sh [--short|--silent] [--serial] [--xdist] [--runtime] <command> [args...]
#
# Options:
# --short | --silent Only print error/warning lines (hide info/success noise)
# --serial Force legacy serial test path (debug / low-RAM machines)
# --xdist Enable pytest -n auto inside each Python unit shard (parallel gate only)
# --runtime Enable runtime tests that may spawn cyt hook daemon or launch proxy
#
# Commands:
# Core (Rust):
# core-rust | rust parallel rust gate (or serial cargo test with --serial)
# indexer [subcmd] cyt-indexer build tools|skills / retrieve (see help)
#
# SDKs:
# sdk-python maturin develop --release + pytest tests/unit + verify
# sdk-rust-release cyt-indexer python+node release build + fossa-deps cargo entries
# sdk-verify verify sdk/python install + native import
# sdk-typescript npm ci, build, test (sdk/typescript)
# sdk-c cmake build + ctest (sdk/c)
# sdk-go build C FFI + go test (sdk/go)
# sdk-all all SDK targets above
#
# Main app (src/):
# app-setup | setup uv sync workspace (editable sdk/python via pyproject.toml)
# app-verify verify main app (src/) re-exports local cyt-indexer-sdk
# app-test | test parallel python gate (or serial pytest with --serial)
# app-test-runtime pytest runtime category (may spawn hook daemon / launch proxy)
# app-build | build-wheels
# uv build clear-your-tools wheel/sdist
# app-all app-setup → app-verify → app-test → app-build
#
# Other:
# proxy [args...] verify + uv run src/cyt/cli/app.py proxy ...
# simulate-registry isolated venv: install built wheels + cargo/npm dry-run checks
# ci app-setup → app-verify → ast-grep → import checks → ruff → pytest categories → app-build
# all parallel monorepo gate (rust → sdk c/go/ts → py; use --serial for legacy)
#
# Examples:
# ./scripts/local/dev/workflow.sh all
# ./scripts/local/dev/workflow.sh --silent sdk-go
# ./scripts/local/dev/workflow.sh sdk-go
# ./scripts/local/dev/workflow.sh proxy --port 8834
# KEEP_SIM_DIR=1 ./scripts/local/dev/workflow.sh simulate-registry
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "${SCRIPT_DIR}/helpers.sh"
export SHORTEN_ROOT="${CYT_REPO_ROOT}"
CYT_LOCAL_DEV_SHORT="${CYT_LOCAL_DEV_SHORT:-}"
CYT_LOCAL_DEV_RUNTIME="${CYT_LOCAL_DEV_RUNTIME:-}"
CYT_WORKFLOW_SERIAL="${CYT_WORKFLOW_SERIAL:-}"
CYT_WORKFLOW_XDIST="${CYT_WORKFLOW_XDIST:-}"
LOCAL_DEV_ARGS=()
while (($#)); do
case "$1" in
--short | --silent)
CYT_LOCAL_DEV_SHORT=1
shift
;;
--serial)
CYT_WORKFLOW_SERIAL=1
shift
;;
--xdist)
CYT_WORKFLOW_XDIST=1
shift
;;
--runtime)
CYT_LOCAL_DEV_RUNTIME=1
shift
;;
*)
LOCAL_DEV_ARGS+=("$1")
shift
;;
esac
done
export CYT_LOCAL_DEV_SHORT
export CYT_WORKFLOW_SERIAL
export CYT_WORKFLOW_XDIST
if [[ -n "${CYT_LOCAL_DEV_RUNTIME}" ]]; then
export CYT_RUN_RUNTIME_TESTS=1
else
unset CYT_RUN_RUNTIME_TESTS
fi
usage() {
sed -n '2,46p' "$0" | sed 's/^# \{0,1\}//'
}
_cyt_local_dev_main() {
local cmd="${1:-}"
shift || true
case "${cmd}" in
core-rust | rust)
require_repo_root
cyt_prek_parallel_gate rust-only
;;
indexer)
require_repo_root
require_cmd jq
sub="${1:-all}"
shift || true
case "${sub}" in
build)
target="${1:-tools}"
shift || true
case "${target}" in
tools)
cyt_indexer_build_catalog
;;
skills)
cyt_indexer_build_skills "$@"
;;
*)
die "unknown build target: ${target} (try: tools, skills)"
;;
esac
;;
survivors)
cyt_indexer_extract_survivors
;;
retrieve)
target="${1:-tools}"
if [[ "${target}" == --* ]]; then
target="tools"
else
shift || true
fi
case "${target}" in
tools)
cyt_indexer_retrieve "$@"
;;
skills)
cyt_indexer_retrieve_skills "$@"
;;
*)
die "unknown retrieve target: ${target} (try: tools, skills)"
;;
esac
;;
all)
cyt_indexer_all "$@"
;;
-h | --help | help)
cat <<EOF
Usage: ./scripts/local/dev/workflow.sh indexer [build|survivors|retrieve|all] [args...]
build tools jq '.body.tools' debug/full_example.json -> cyt-indexer build tools -> .catalog/
build skills cyt-indexer build skills --skills DIR [--output DIR]
survivors jq rerank json/md -> .catalog/survivors.json (scores as numbers)
retrieve tools cyt-indexer retrieve tools with default policies (score filter off for rerank survivors)
retrieve skills cyt-indexer retrieve skills --catalog DIR --doc-id ID --query TYPE --output FILE
all build tools + survivors + retrieve (default)
Retrieve defaults:
--system-policy prune_optional
--mcp-policy prune_all
--tool-policy AskUserQuestion=always_include
Override via env:
CYT_CATALOG_DIR CYT_EXAMPLE_JSON CYT_SURVIVORS_JSON CYT_RETRIEVE_OUT
CYT_INDEXER_SYSTEM_POLICY CYT_INDEXER_MCP_POLICY
CYT_INDEXER_TOOL_POLICIES='AskUserQuestion=always_include Agent=prune_optional'
Examples:
./scripts/local/dev/workflow.sh indexer
./scripts/local/dev/workflow.sh indexer build
./scripts/local/dev/workflow.sh indexer build skills --skills ~/.claude/skills --output ./.catalog
./scripts/local/dev/workflow.sh indexer retrieve --tool-policy Bash=always_include
./scripts/local/dev/workflow.sh indexer retrieve skills --catalog ./.catalog --doc-id lean-ctx__skill --query content --line_num 15
EOF
;;
*)
die "unknown indexer subcommand: ${sub} (try: build, survivors, retrieve, all)"
;;
esac
;;
sdk-python)
require_repo_root
cyt_build_sdk_python
cyt_verify_sdk_python
;;
sdk-rust-release)
require_repo_root
cyt_build_sdk_rust_release
;;
sdk-verify)
require_repo_root
cyt_verify_sdk_python
;;
sdk-typescript)
require_repo_root
cyt_build_sdk_typescript
;;
sdk-c)
require_repo_root
cyt_build_sdk_c
;;
sdk-go)
require_repo_root
cyt_build_sdk_go
;;
sdk-all)
require_repo_root
cyt_section "SDK: Python"
cyt_build_sdk_python
cyt_verify_sdk_python
cyt_section "SDK: C"
cyt_build_sdk_c
cyt_section "SDK: Go"
cyt_build_sdk_go
cyt_section "SDK: TypeScript"
cyt_build_sdk_typescript
;;
app-setup | setup)
require_repo_root
cyt_sync_app
;;
app-verify)
require_repo_root
cyt_verify_app_python
;;
verify)
require_repo_root
cyt_verify_sdk_python
cyt_verify_app_python
;;
app-test | test)
require_repo_root
if [[ "${CYT_WORKFLOW_SERIAL:-}" == 1 ]]; then
cyt_test_app
else
cyt_prek_parallel_gate py-only
fi
;;
app-test-runtime)
require_repo_root
cyt_test_app_runtime
;;
app-build | build-wheels)
require_repo_root
cyt_sync_app
cyt_verify_app_python
cyt_build_app_wheel
;;
app-all)
require_repo_root
cyt_build_all_app
;;
proxy)
require_repo_root
cyt_run_proxy "$@"
;;
simulate-registry)
require_repo_root
require_cmd uv
require_cmd cargo
require_cmd npm
local sim_label="simulate-registry" sim_total=10
cyt_step "${sim_label}" 1 "${sim_total}" "sync app"
cyt_sync_app
cyt_step_done "${sim_label}"
cyt_step "${sim_label}" 2 "${sim_total}" "build SDK Python (maturin + pytest)"
# Prek-loop runs pytest-sdk-python / local-dev-sdk-python before this hook.
# On Windows, maturin develop cannot overwrite _native.pyd while pytest still
# holds the DLL; step 5 (uv build) compiles Rust again for the wheel smoke test.
if [[ -f "${CYT_REPO_ROOT}/sdk/python/src/cyt_indexer/_native.pyd" ]] ||
[[ -f "${CYT_REPO_ROOT}/sdk/python/src/cyt_indexer/_native.so" ]]; then
SKIP_MATURIN_DEVELOP=1 cyt_build_sdk_python
else
cyt_build_sdk_python
fi
cyt_step_done "${sim_label}"
cyt_step "${sim_label}" 3 "${sim_total}" "build Rust indexer (cargo build/test + catalog smoke)"
cyt_build_rust
cyt_step_done "${sim_label}"
cyt_step "${sim_label}" 4 "${sim_total}" "prepare isolated install workspace"
SIM_DIR="${CYT_SIM_DIR:-$(mktemp -d "${TMPDIR:-/tmp}/cyt-local-dev.XXXXXX")}"
SIM_DIR="$(cd "${SIM_DIR}" && pwd -P)"
KEEP_SIM_DIR="${KEEP_SIM_DIR:-}"
trap '[[ -n "${KEEP_SIM_DIR}" ]] || rm -rf "${SIM_DIR}"' EXIT
mkdir -p "${SIM_DIR}/dist-sdk" "${SIM_DIR}/dist-app" "${SIM_DIR}/npm-pack"
cyt_step_done "${sim_label}"
cyt_step "${sim_label}" 5 "${sim_total}" "build cyt-indexer-sdk wheel"
cyt_run chunk_run_without_worktree_patches "${CYT_REPO_ROOT}" \
bash -c "cd \"${CYT_REPO_ROOT}/sdk/python\" && uv build -o \"${SIM_DIR}/dist-sdk\""
cyt_step_done "${sim_label}"
cyt_step "${sim_label}" 6 "${sim_total}" "build clear-your-tools wheel"
cyt_run bash -c "cd \"${CYT_REPO_ROOT}\" && uv build -o \"${SIM_DIR}/dist-app\""
cyt_step_done "${sim_label}"
cyt_step "${sim_label}" 7 "${sim_total}" "cargo publish --dry-run"
cyt_cargo_publish_dry_run
cyt_step_done "${sim_label}"
cyt_step "${sim_label}" 8 "${sim_total}" "npm pack TypeScript SDK"
cyt_run bash -c "cd \"${CYT_REPO_ROOT}/sdk/typescript\" && npm ci && npm run build && npm pack --pack-destination \"${SIM_DIR}/npm-pack\""
cyt_step_done "${sim_label}"
cyt_step "${sim_label}" 9 "${sim_total}" "install wheels in isolated venv"
SIM_VENV="${SIM_DIR}/venv"
cyt_run uv venv "${SIM_VENV}"
SIM_PY="$(cyt_venv_python "${SIM_VENV}")"
SDK_WHL=("${SIM_DIR}"/dist-sdk/cyt_indexer_sdk-*.whl)
APP_WHL=("${SIM_DIR}"/dist-app/clear_your_tools-*.whl)
[[ -f "${SDK_WHL[0]}" ]] || die "SDK wheel not found under ${SIM_DIR}/dist-sdk"
[[ -f "${APP_WHL[0]}" ]] || die "app wheel not found under ${SIM_DIR}/dist-app"
cyt_run uv pip install --python "${SIM_PY}" "${SDK_WHL[0]}"
# Avoid `path.whl[all]` on Windows: uv wrongly parses `[all]` in file URLs (C:/Users/... → C:~/...).
cyt_run uv pip install --python "${SIM_PY}" "${APP_WHL[0]}"
cyt_step_done "${sim_label}"
cyt_step "${sim_label}" 10 "${sim_total}" "smoke imports"
cyt_run "${SIM_PY}" - <<'PY'
from importlib import metadata
from cyt_indexer._native import build_catalog_index as native_build
from cyt_indexer.build import build_catalog_index as sdk_build
from cyt.indexer.build import build_catalog_index as app_build
import cyt
assert callable(native_build)
assert sdk_build is app_build
assert metadata.version("cyt-indexer-sdk") == metadata.version("clear-your-tools")
print("OK: isolated wheel install")
print(" cyt version:", getattr(cyt, "__version__", "?"))
print(" cyt-indexer-sdk:", metadata.version("cyt-indexer-sdk"))
PY
cyt_step_done "${sim_label}"
if [[ -z "${CYT_LOCAL_DEV_SHORT:-}" ]]; then
info "simulate-registry done (${SIM_DIR})"
fi
if [[ -n "${KEEP_SIM_DIR}" ]]; then
trap - EXIT
info "KEEP_SIM_DIR=1 — directory kept"
fi
;;
all)
require_repo_root
cyt_run_all
if [[ -n "${CYT_RUN_RUNTIME_TESTS:-}" ]]; then
cyt_test_app_runtime
fi
info "all done"
;;
ci)
require_repo_root
cyt_section "CI"
cyt_verify_dependency_pins
cyt_sync_app
cyt_verify_app_python
cyt_verify_sdk_import
if command -v ast-grep >/dev/null 2>&1; then
info "ast-grep scan"
cyt_run ast-grep scan src/ sdk/
else
info "skip ast-grep (not on PATH)"
fi
cyt_run uv run python scripts/pre-commit-hooks/check_agent_imports.py
cyt_run uv run python scripts/pre-commit-hooks/check_cyt_client_imports.py
if command -v ruff >/dev/null 2>&1 || [[ -x "${CYT_VENV_BIN}/ruff" ]]; then
info "ruff check"
cyt_run uv run ruff check src/cyt src/tests
else
info "skip ruff (not on PATH)"
fi
if [[ "${CYT_WORKFLOW_SERIAL:-}" == 1 ]]; then
cyt_test_app_python
cyt_build_app_wheel
else
cyt_prek_parallel_gate py-only
fi
;;
"" | -h | --help | help)
usage
;;
*)
if [[ -n "${CYT_LOCAL_DEV_SHORT:-}" ]]; then
die "unknown command: ${cmd}"
fi
echo "unknown command: ${cmd}" >&2
echo >&2
usage >&2
return 1
;;
esac
}
if [[ -n "${CYT_LOCAL_DEV_SHORT}" ]]; then
_cyt_local_dev_main "${LOCAL_DEV_ARGS[@]}" 2>&1 | "${SCRIPT_DIR}/../../lib/shorten-paths.sh" | cyt_filter_short_logs
else
_cyt_local_dev_main "${LOCAL_DEV_ARGS[@]}" 2>&1 | "${SCRIPT_DIR}/../../lib/shorten-paths.sh"
fi
exit "${PIPESTATUS[0]}"