From ccd9287e5f1908f1c2f290b802d1983badfd0a6d Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Mon, 24 Aug 2026 13:16:46 +0800 Subject: [PATCH 1/2] fix: isolate quant monitor repository sync Co-Authored-By: Codex --- ops/quant-monitor/scripts/common_env.sh | 5 ++++- .../scripts/sync_strategy_repos.sh | 21 ++++++++++++------- .../codex-daily-briefing.service.example | 2 +- .../systemd/codex-quant.service.example | 2 +- .../tests/test_deploy_scripts.py | 10 ++++++++- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/ops/quant-monitor/scripts/common_env.sh b/ops/quant-monitor/scripts/common_env.sh index 4c149fdc..fd4cb2c3 100755 --- a/ops/quant-monitor/scripts/common_env.sh +++ b/ops/quant-monitor/scripts/common_env.sh @@ -7,7 +7,10 @@ AAB_ROOT="${AIAUDIT_BRIDGE_ROOT:-$(cd "$ROOT/../.." && pwd)}" PROJECTS_ROOT="${PROJECTS_ROOT:-$HOME/Projects}" QUANT_PROJECTS_ROOT="${QUANT_PROJECTS_ROOT:-$ROOT/data/lifecycle-projects}" LIFECYCLE_LOCAL_ROOT="${LIFECYCLE_LOCAL_ROOT:-$ROOT/data/lifecycle-store}" -QPK_ROOT="${QUANT_PLATFORM_KIT_ROOT:-$PROJECTS_ROOT/QuantPlatformKit}" +# Monitoring must never import an editable QuantPlatformKit checkout from a +# developer workspace: the monitor synchronizes and consumes this dedicated +# mirror instead. +QPK_ROOT="${QUANT_PLATFORM_KIT_ROOT:-$QUANT_PROJECTS_ROOT/QuantPlatformKit}" VENV="${QUANT_MONITOR_VENV:-$ROOT/.venv}" export QUANT_MONITOR_ROOT="$ROOT" diff --git a/ops/quant-monitor/scripts/sync_strategy_repos.sh b/ops/quant-monitor/scripts/sync_strategy_repos.sh index f5c69f7b..a301b316 100755 --- a/ops/quant-monitor/scripts/sync_strategy_repos.sh +++ b/ops/quant-monitor/scripts/sync_strategy_repos.sh @@ -7,29 +7,34 @@ REPOS=( UsEquityStrategies CryptoStrategies ) -ROOT="${PROJECTS_ROOT:-$HOME/Projects}" +ROOT="${QUANT_MONITOR_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}" +MIRROR_ROOT="${QUANT_PROJECTS_ROOT:-$ROOT/data/lifecycle-projects}" +REPOSITORY_BASE_URL="${QUANT_MONITOR_REPOSITORY_BASE_URL:-https://github.com/QuantStrategyLab}" failed=0 + +mkdir -p "$MIRROR_ROOT" + for repo in "${REPOS[@]}"; do - dir="$ROOT/$repo" + dir="$MIRROR_ROOT/$repo" if [[ -d "$dir/.git" ]]; then if ! git -C "$dir" fetch origin main --quiet; then echo "[sync] $repo fetch failed" >&2 failed=1 continue fi - if ! git -C "$dir" checkout main --quiet; then + if ! git -C "$dir" checkout --detach --quiet origin/main; then echo "[sync] $repo checkout failed" >&2 failed=1 continue fi - if ! git -C "$dir" pull --ff-only origin main --quiet; then - echo "[sync] $repo pull failed" >&2 + echo "[sync] $repo ok" + else + if ! git clone --depth 1 "$REPOSITORY_BASE_URL/$repo.git" "$dir" --quiet; then + echo "[sync] $repo clone failed" >&2 failed=1 continue fi - echo "[sync] $repo ok" - else - echo "[sync] skip missing $dir" >&2 + echo "[sync] $repo cloned" fi done exit "$failed" diff --git a/ops/quant-monitor/systemd/codex-daily-briefing.service.example b/ops/quant-monitor/systemd/codex-daily-briefing.service.example index e5100386..9f4c6dc8 100644 --- a/ops/quant-monitor/systemd/codex-daily-briefing.service.example +++ b/ops/quant-monitor/systemd/codex-daily-briefing.service.example @@ -10,7 +10,7 @@ Group=ubuntu WorkingDirectory=/home/ubuntu/Projects/AIAuditBridge/ops/quant-monitor Environment=QUANT_MONITOR_ROOT=/home/ubuntu/Projects/AIAuditBridge/ops/quant-monitor Environment=AIAUDIT_BRIDGE_ROOT=/home/ubuntu/Projects/AIAuditBridge -Environment=QUANT_PLATFORM_KIT_ROOT=/home/ubuntu/Projects/QuantPlatformKit +Environment=QUANT_PLATFORM_KIT_ROOT=/home/ubuntu/Projects/AIAuditBridge/ops/quant-monitor/data/lifecycle-projects/QuantPlatformKit Environment=QUANT_SENTINEL_TELEGRAM_SECRET_NAME=quant-sentinel-telegram-bot-token Environment=QUANT_SENTINEL_GCP_PROJECT=firstradequant Environment=GLOBAL_TELEGRAM_CHAT_ID= diff --git a/ops/quant-monitor/systemd/codex-quant.service.example b/ops/quant-monitor/systemd/codex-quant.service.example index 0a0edd98..a451e532 100644 --- a/ops/quant-monitor/systemd/codex-quant.service.example +++ b/ops/quant-monitor/systemd/codex-quant.service.example @@ -10,7 +10,7 @@ Group=ubuntu WorkingDirectory=/home/ubuntu/Projects/AIAuditBridge/ops/quant-monitor Environment=QUANT_MONITOR_ROOT=/home/ubuntu/Projects/AIAuditBridge/ops/quant-monitor Environment=AIAUDIT_BRIDGE_ROOT=/home/ubuntu/Projects/AIAuditBridge -Environment=QUANT_PLATFORM_KIT_ROOT=/home/ubuntu/Projects/QuantPlatformKit +Environment=QUANT_PLATFORM_KIT_ROOT=/home/ubuntu/Projects/AIAuditBridge/ops/quant-monitor/data/lifecycle-projects/QuantPlatformKit Environment=QUANT_SENTINEL_TELEGRAM_SECRET_NAME=quant-sentinel-telegram-bot-token Environment=QUANT_SENTINEL_GCP_PROJECT=firstradequant # Set on VPS only — do not commit real chat id to git: diff --git a/ops/quant-monitor/tests/test_deploy_scripts.py b/ops/quant-monitor/tests/test_deploy_scripts.py index 3d823cba..c9f03b35 100644 --- a/ops/quant-monitor/tests/test_deploy_scripts.py +++ b/ops/quant-monitor/tests/test_deploy_scripts.py @@ -46,10 +46,18 @@ def test_common_env_separates_code_and_lifecycle_data_roots(self) -> None: str(Path(home) / "Projects"), str(monitor_root / "data" / "lifecycle-projects"), str(monitor_root / "data" / "lifecycle-store"), - str(Path(home) / "Projects" / "QuantPlatformKit"), + str(monitor_root / "data" / "lifecycle-projects" / "QuantPlatformKit"), ], ) + def test_strategy_sync_uses_dedicated_mirrors(self) -> None: + script = (ROOT / "scripts" / "sync_strategy_repos.sh").read_text(encoding="utf-8") + + self.assertIn('MIRROR_ROOT="${QUANT_PROJECTS_ROOT:-$ROOT/data/lifecycle-projects}"', script) + self.assertIn('dir="$MIRROR_ROOT/$repo"', script) + self.assertIn("checkout --detach --quiet origin/main", script) + self.assertNotIn("pull --ff-only", script) + def test_health_check_syncs_artifacts_before_monitoring(self) -> None: script = (ROOT / "scripts" / "health_check.sh").read_text(encoding="utf-8") From 771e1d734602524d58d1795bd66364076ce81251 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Mon, 24 Aug 2026 13:25:22 +0800 Subject: [PATCH 2/2] test: cover isolated monitor sync failures Co-Authored-By: Codex --- tests/test_quant_monitor_sync_strategy_repos.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_quant_monitor_sync_strategy_repos.py b/tests/test_quant_monitor_sync_strategy_repos.py index de9f712b..ec00dd9a 100644 --- a/tests/test_quant_monitor_sync_strategy_repos.py +++ b/tests/test_quant_monitor_sync_strategy_repos.py @@ -9,14 +9,14 @@ class SyncStrategyReposTests(unittest.TestCase): - def test_exits_nonzero_when_a_repo_pull_fails(self) -> None: + def test_exits_nonzero_when_a_repo_fetch_fails(self) -> None: repo_root = Path(__file__).resolve().parents[1] script = repo_root / "ops" / "quant-monitor" / "scripts" / "sync_strategy_repos.sh" with tempfile.TemporaryDirectory() as tmp: - projects_root = Path(tmp) / "Projects" + mirror_root = Path(tmp) / "lifecycle-projects" bin_dir = Path(tmp) / "bin" - projects_root.mkdir() + mirror_root.mkdir() bin_dir.mkdir() for name in [ @@ -26,7 +26,7 @@ def test_exits_nonzero_when_a_repo_pull_fails(self) -> None: "UsEquityStrategies", "CryptoStrategies", ]: - (projects_root / name / ".git").mkdir(parents=True) + (mirror_root / name / ".git").mkdir(parents=True) git_stub = bin_dir / "git" git_stub.write_text( @@ -45,8 +45,8 @@ def test_exits_nonzero_when_a_repo_pull_fails(self) -> None: if len(args) >= 3 and args[0] == "-C": repo = Path(args[1]).name command = args[2] - if repo == "QuantPlatformKit" and command == "pull": - print("error: simulated pull failure", file=sys.stderr) + if repo == "QuantPlatformKit" and command == "fetch": + print("error: simulated fetch failure", file=sys.stderr) raise SystemExit(1) raise SystemExit(0) """ @@ -57,7 +57,7 @@ def test_exits_nonzero_when_a_repo_pull_fails(self) -> None: env = { **os.environ, - "PROJECTS_ROOT": str(projects_root), + "QUANT_PROJECTS_ROOT": str(mirror_root), "PATH": f"{bin_dir}:{os.environ.get('PATH', '')}", } completed = subprocess.run( @@ -70,7 +70,7 @@ def test_exits_nonzero_when_a_repo_pull_fails(self) -> None: ) self.assertNotEqual(completed.returncode, 0) - self.assertIn("[sync] QuantPlatformKit pull failed", completed.stderr) + self.assertIn("[sync] QuantPlatformKit fetch failed", completed.stderr) self.assertIn("[sync] CnEquityStrategies ok", completed.stdout) self.assertNotIn("[sync] QuantPlatformKit ok", completed.stdout)