@@ -4,12 +4,6 @@ set -euo pipefail
44
55SCRIPT_DIR=" $( cd " $( dirname " ${BASH_SOURCE[0]} " ) " && pwd) "
66
7- LOCAL_CONFIG=" ${SCRIPT_DIR} /config.local.sh"
8- if [[ -f " ${LOCAL_CONFIG} " ]]; then
9- # shellcheck disable=SC1090
10- source " ${LOCAL_CONFIG} "
11- fi
12-
137# Resolve a platform's install root via the SAME source as the Python sync engine
148# (sync/core/paths.py -> platform_install_root). Honors the top-level `paths`
159# override in env/secrets.json AND platform-specific defaults (e.g. CODEX_HOME for
@@ -41,7 +35,6 @@ CODEX_TARGET="${CODEX_TARGET:-${HOME}/.codex/AGENTS.md}"
4135GEMINI_TARGET=" ${GEMINI_TARGET:- ${HOME} / .gemini/ GEMINI.md} "
4236XCODE_CODEX_TARGET=" ${XCODE_CODEX_TARGET:- ${HOME} / Library/ Developer/ Xcode/ CodingAssistant/ codex/ AGENTS.md} "
4337XCODE_CLAUDE_TARGET=" ${XCODE_CLAUDE_TARGET:- ${HOME} / Library/ Developer/ Xcode/ CodingAssistant/ ClaudeAgentConfig/ CLAUDE.md} "
44- CURSOR_PROJECT_ROOTS=" ${CURSOR_PROJECT_ROOTS:- } "
4538# Recall-only preamble targets (cline / qwen) and full preamble
4639# targets (claude / codex / gemini / xcode / codebuddy) are now discovered from each
4740# platform's `preamble` declaration in env/platforms/<platform>.json — see the
@@ -69,6 +62,36 @@ REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
6962RECALL_CLI_PATH=" ${REPO_ROOT} /skills-engineering/plan-reviews/dist/cli.js"
7063SE_DIR=" $( cd " ${SCRIPT_DIR} /.." && pwd) "
7164
65+ resolve_cursor_project_roots () {
66+ if [[ -n " ${CURSOR_PROJECT_ROOTS:- } " ]]; then
67+ printf ' %s\n' " ${CURSOR_PROJECT_ROOTS} "
68+ return
69+ fi
70+ python3 - " ${REPO_ROOT} /env/secrets.json" << 'PY '
71+ import json
72+ import sys
73+ from pathlib import Path
74+
75+ path = Path(sys.argv[1])
76+ try:
77+ data = json.loads(path.read_text(encoding="utf-8"))
78+ except (OSError, json.JSONDecodeError):
79+ sys.exit(0)
80+
81+ paths = data.get("paths")
82+ if not isinstance(paths, dict):
83+ sys.exit(0)
84+
85+ roots = paths.get("cursor_project_roots")
86+ if isinstance(roots, str):
87+ print(roots)
88+ elif isinstance(roots, list):
89+ print(":".join(str(root) for root in roots if isinstance(root, str) and root.strip()))
90+ PY
91+ }
92+
93+ CURSOR_PROJECT_ROOTS=" $( resolve_cursor_project_roots) "
94+
7295DRY_RUN=false
7396
7497usage () {
@@ -89,7 +112,7 @@ Recall-only targets (historical-recall managed block, no ios-engineer audit):
89112
90113Cursor project rules (from sync-manifest skill:* lines):
91114 <repo>/.cursor/rules/<skill>.mdc
92- <CURSOR_PROJECT_ROOTS >/.cursor/rules/<skill>.mdc
115+ <env/secrets.json paths.cursor_project_roots >/.cursor/rules/<skill>.mdc
93116
94117Skill full text is synced by sync-skills.sh to ~/.*/skills/<skill>/ — run
95118sync-skill-full.sh or sync-skills.sh before this script.
@@ -546,5 +569,5 @@ if [[ -n "${CURSOR_PROJECT_ROOTS}" ]]; then
546569 sync_manifest_skill_cursor_rules " ${_root} "
547570 done
548571else
549- echo " CURSOR_PROJECT_ROOTS not set; skipping Cursor ios-engineer.mdc on external projects."
572+ echo " paths.cursor_project_roots not set in env/secrets.json ; skipping Cursor ios-engineer.mdc on external projects."
550573fi
0 commit comments