Skip to content

Commit a445a79

Browse files
Pigbibiclaude
andcommitted
refactor: split repo into python/ and web/ with independent CI
- Move Python scripts to python/scripts/ with own pyproject.toml - Move Python tests to python/tests/ with __init__.py - Move shell tooling to python/shell/ - Keep JS web app and JS tests in web/ and tests/ - Update all path references in workflows, scripts, and tests - Add docs/ARCHITECTURE.md documenting the three-tier design - Split validate.yml into independent Python and JS jobs - Update dependabot.yml to point to /python - Update READMEs with new directory structure Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 9180677 commit a445a79

24 files changed

Lines changed: 222 additions & 57 deletions

.github/dependabot.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: 2
22
updates:
33
- package-ecosystem: "pip"
4-
directory: "/"
4+
directory: "/python"
55
schedule:
66
interval: "weekly"
77
open-pull-requests-limit: 5

.github/workflows/codex_pr_review.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
OPENAI_MODEL: ${{ vars.OPENAI_MODEL || 'gpt-5.4-mini' }}
4343
CODEX_AUDIT_SERVICE_URL: ${{ secrets.CODEX_AUDIT_SERVICE_URL }}
4444
CODEX_AUDIT_SERVICE_AUDIENCE: ${{ vars.CODEX_AUDIT_SERVICE_AUDIENCE || 'quant-codex-audit' }}
45-
run: python scripts/run_codex_pr_review.py
45+
run: python python/scripts/run_codex_pr_review.py
4646

4747
- name: Upload review diagnostics
4848
if: always()

.github/workflows/codex_review_gate.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
id: gate
5555
env:
5656
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57-
run: python scripts/gate_codex_app_review.py
57+
run: python python/scripts/gate_codex_app_review.py
5858

5959
- name: Upload gate diagnostics
6060
if: always()

.github/workflows/deploy-strategy-switch-console.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ on:
66
paths:
77
- ".github/workflows/deploy-strategy-switch-console.yml"
88
- "platform-config.json"
9-
- "scripts/build_config.py"
10-
- "scripts/sync_strategy_switch_page_asset.py"
9+
- "python/scripts/build_config.py"
10+
- "python/scripts/sync_strategy_switch_page_asset.py"
1111
- "web/strategy-switch-console/**"
1212
workflow_dispatch:
1313
inputs:
@@ -54,9 +54,9 @@ jobs:
5454
- name: Build config & assets from platform-config.json
5555
run: |
5656
set -euo pipefail
57-
python3 scripts/build_platform_config.py
58-
python3 scripts/inject_platform_config.py
59-
python3 scripts/sync_strategy_switch_page_asset.py
57+
python3 python/scripts/build_platform_config.py
58+
python3 python/scripts/inject_platform_config.py
59+
python3 python/scripts/sync_strategy_switch_page_asset.py
6060
6161
- name: Validate Worker assets
6262
continue-on-error: true

.github/workflows/manual-strategy-switch.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ jobs:
212212
id: platform
213213
run: |
214214
set -euo pipefail
215-
repo="$(python3 scripts/runtime_settings.py repository "${PLATFORM}")"
215+
repo="$(python3 python/scripts/runtime_settings.py repository "${PLATFORM}")"
216216
echo "repository=${repo}" >> "$GITHUB_OUTPUT"
217217
218218
- name: Fetch existing service targets
@@ -302,14 +302,14 @@ jobs:
302302
if [ -s "${EXISTING_SERVICE_TARGETS_JSON_FILE:-}" ]; then
303303
args+=(--existing-service-targets-json-file "${EXISTING_SERVICE_TARGETS_JSON_FILE}")
304304
fi
305-
python3 scripts/build_runtime_switch.py "${args[@]}"
306-
python3 scripts/runtime_settings.py validate "${target_file}"
305+
python3 python/scripts/build_runtime_switch.py "${args[@]}"
306+
python3 python/scripts/runtime_settings.py validate "${target_file}"
307307
echo "TARGET_FILE=${target_file}" >> "$GITHUB_ENV"
308308
309309
- name: Preview assignments
310310
run: |
311311
set -euo pipefail
312-
python3 scripts/runtime_settings.py render "${TARGET_FILE}" --format json --redact-values > "${RUNNER_TEMP}/assignments.json"
312+
python3 python/scripts/runtime_settings.py render "${TARGET_FILE}" --format json --redact-values > "${RUNNER_TEMP}/assignments.json"
313313
python - <<'PY' "${TARGET_FILE}" "${RUNNER_TEMP}/assignments.json" >> "$GITHUB_STEP_SUMMARY"
314314
import json
315315
import sys
@@ -336,7 +336,7 @@ jobs:
336336
337337
- name: Apply GitHub variable updates
338338
if: env.APPLY_SWITCH == 'true'
339-
run: python3 scripts/runtime_settings.py apply "${TARGET_FILE}" --yes
339+
run: python3 python/scripts/runtime_settings.py apply "${TARGET_FILE}" --yes
340340

341341
- name: Dispatch platform sync workflow
342342
if: env.APPLY_SWITCH == 'true' && env.TRIGGER_PLATFORM_SYNC == 'true'
@@ -374,7 +374,7 @@ jobs:
374374
import urllib.request
375375
376376
root = os.environ.get("GITHUB_WORKSPACE") or os.getcwd()
377-
sys.path.insert(0, os.path.join(root, "scripts"))
377+
sys.path.insert(0, os.path.join(root, "python", "scripts"))
378378
import runtime_settings
379379
380380
base_url = os.environ["STRATEGY_SWITCH_CONSOLE_URL"].rstrip("/")

.github/workflows/validate.yml

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ permissions:
88
contents: read
99

1010
jobs:
11-
validate:
11+
python:
1212
runs-on: ubuntu-latest
1313
timeout-minutes: 15
1414
steps:
@@ -18,9 +18,6 @@ jobs:
1818
- uses: actions/setup-python@v6
1919
with:
2020
python-version: "3.12"
21-
- uses: actions/setup-node@v6
22-
with:
23-
node-version: "22"
2421
- name: Check whitespace
2522
run: |
2623
set -euo pipefail
@@ -31,23 +28,37 @@ jobs:
3128
git diff-tree --check --no-commit-id --root -r HEAD
3229
fi
3330
- name: Validate platform config
34-
run: python3 scripts/build_config.py --check
31+
run: python3 python/scripts/build_config.py --check
3532
- name: Validate runtime targets
36-
run: python3 scripts/runtime_settings.py validate
37-
- name: Run unit tests
38-
run: python3 -m unittest discover -s tests -v
33+
run: python3 python/scripts/runtime_settings.py validate
34+
- name: Run Python unit tests
35+
run: python3 -m unittest discover -s python/tests -v
3936
- name: Checkout internal dependency consumer repos
4037
env:
4138
GH_TOKEN: ${{ github.token }}
42-
run: bash scripts/checkout_internal_dependency_consumers.sh --output-root ..
39+
run: bash python/shell/checkout_internal_dependency_consumers.sh --output-root ..
4340
- name: Report internal dependency matrix
44-
run: python3 scripts/check_internal_dependency_matrix.py --projects-root .. --json --strict --require-consumer-files
41+
run: python3 python/scripts/check_internal_dependency_matrix.py --projects-root .. --json --strict --require-consumer-files
42+
43+
js:
44+
runs-on: ubuntu-latest
45+
timeout-minutes: 10
46+
steps:
47+
- uses: actions/checkout@v6
48+
with:
49+
fetch-depth: 0
50+
- uses: actions/setup-node@v6
51+
with:
52+
node-version: "22"
53+
- uses: actions/setup-python@v6
54+
with:
55+
python-version: "3.12"
4556
- name: Validate strategy switch web assets
4657
run: |
4758
set -euo pipefail
48-
python3 scripts/build_config.py --check
49-
python3 scripts/build_config.py
50-
python3 scripts/sync_strategy_switch_page_asset.py
59+
python3 python/scripts/build_config.py --check
60+
python3 python/scripts/build_config.py
61+
python3 python/scripts/sync_strategy_switch_page_asset.py
5162
git diff --exit-code -- web/strategy-switch-console/page_asset.js web/strategy-switch-console/strategy_profiles_asset.js
5263
jq empty web/strategy-switch-console/strategy-profiles.example.json
5364
node --experimental-default-type=module tests/strategy_switch_worker_validation.mjs

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,23 @@ It supports the system but does not decide which strategy should be live. Strate
1919

2020
## Repository layout
2121

22-
- `tests/`: unit, contract, and regression tests.
22+
- `python/`: Python tooling (scripts, tests, pyproject.toml) — validation, code generation, deployment scripts.
23+
- `web/`: JavaScript web app (Cloudflare Workers strategy switch console).
24+
- `schemas/`: JSON Schema files shared by both Python and JS.
25+
- `tests/`: JavaScript unit/integration tests.
2326
- `.github/workflows/`: CI, scheduled jobs, release, or deployment workflows.
24-
- `scripts/`: operator scripts and local helpers.
27+
- `docs/ARCHITECTURE.md`: Detailed architecture documentation.
2528

2629
## Quick start
2730

2831
```bash
29-
python3 scripts/runtime_settings.py validate
30-
python3 -m unittest discover -s tests -v
32+
python3 python/scripts/runtime_settings.py validate
33+
python3 -m unittest discover -s python/tests -v
3134
```
3235

3336
## Manual Strategy Switch
3437

35-
`.github/workflows/manual-strategy-switch.yml` provides a central manual switch entrypoint. It builds a transient runtime target from workflow inputs, validates it with `scripts/runtime_settings.py`, and writes GitHub variables into the target platform repository. It currently supports `longbridge`, `ibkr`, `schwab`, and `firstrade`.
38+
`.github/workflows/manual-strategy-switch.yml` provides a central manual switch entrypoint. It builds a transient runtime target from workflow inputs, validates it with `python/scripts/runtime_settings.py`, and writes GitHub variables into the target platform repository. It currently supports `longbridge`, `ibkr`, `schwab`, and `firstrade`.
3639

3740
Recommended flow:
3841

README.zh-CN.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,23 @@ QuantRuntimeSettings 是 QuantStrategyLab 的运行配置包。为 QuantStrategy
1919

2020
## 仓库结构
2121

22-
- `tests/`:单元测试、契约测试和回归测试。
22+
- `python/`:Python 工具链(脚本、测试、pyproject.toml)— 校验、代码生成、部署工具。
23+
- `web/`:JavaScript Web 应用(Cloudflare Workers 策略切换控制台)。
24+
- `schemas/`:JSON Schema 文件,Python 和 JS 共享。
25+
- `tests/`:JavaScript 单元测试和集成测试。
2326
- `.github/workflows/`:CI、定时任务、发布或部署 workflow。
24-
- `scripts/`:运维脚本和本地辅助工具
27+
- `docs/ARCHITECTURE.md`:详细架构文档
2528

2629
## 快速开始
2730

2831
```bash
29-
python3 scripts/runtime_settings.py validate
30-
python3 -m unittest discover -s tests -v
32+
python3 python/scripts/runtime_settings.py validate
33+
python3 -m unittest discover -s python/tests -v
3134
```
3235

3336
## 一键切换策略
3437

35-
`.github/workflows/manual-strategy-switch.yml` 提供手动触发的中控切换入口。它会根据表单参数生成运行目标,复用 `scripts/runtime_settings.py` 校验并写入目标平台仓库的 GitHub variables。当前支持 `longbridge``ibkr``schwab``firstrade`
38+
`.github/workflows/manual-strategy-switch.yml` 提供手动触发的中控切换入口。它会根据表单参数生成运行目标,复用 `python/scripts/runtime_settings.py` 校验并写入目标平台仓库的 GitHub variables。当前支持 `longbridge``ibkr``schwab``firstrade`
3639

3740
推荐流程:
3841

docs/ARCHITECTURE.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# QuantRuntimeSettings Architecture
2+
3+
## Overview
4+
5+
QuantRuntimeSettings is a **config-driven** runtime settings package that serves as the central control plane for QuantStrategyLab deployments. It defines versioned strategy-to-platform assignments and hosts a Cloudflare Workers-based strategy switch console.
6+
7+
The repository has a **three-tier architecture** built around a single source of truth:
8+
9+
```
10+
platform-config.json (single source of truth)
11+
|
12+
v
13+
Python scripts (validation, code generation, deployment tooling)
14+
|
15+
v
16+
Generated assets (config.js, page_asset.js, strategy_profiles_asset.js)
17+
|
18+
v
19+
Web application (Cloudflare Worker + frontend SPA)
20+
```
21+
22+
---
23+
24+
## Directory Layout
25+
26+
```
27+
.
28+
├── platform-config.json # Central configuration (single source of truth)
29+
├── internal_dependency_matrix.json # Internal git dependency pin tracking
30+
31+
├── python/ # Python tooling (tests, CI, scripts)
32+
│ ├── pyproject.toml # Python project definition & linter config
33+
│ ├── scripts/ # Build & validation scripts
34+
│ │ ├── build_config.py # Full build pipeline
35+
│ │ ├── build_platform_config.py # Generate config.js from platform-config.json
36+
│ │ ├── build_runtime_switch.py # Build transient runtime targets
37+
│ │ ├── runtime_settings.py # Core validation & assignment engine
38+
│ │ ├── check_internal_dependency_matrix.py
39+
│ │ ├── gate_codex_app_review.py # PR merge gate
40+
│ │ ├── inject_platform_config.py # Inject config into index.html
41+
│ │ ├── run_codex_pr_review.py # Codex AI PR review
42+
│ │ └── sync_strategy_switch_page_asset.py
43+
│ ├── tests/ # Python unit tests
44+
│ │ ├── test_runtime_settings.py
45+
│ │ └── test_internal_dependency_matrix.py
46+
│ └── shell/ # Shell scripts (Python ecosystem)
47+
│ └── checkout_internal_dependency_consumers.sh
48+
49+
├── web/ # JavaScript web application
50+
│ └── strategy-switch-console/ # Cloudflare Workers app
51+
│ ├── worker.js # Worker backend (OAuth, routing, KV)
52+
│ ├── index.html # SPA shell
53+
│ ├── app.js # Frontend JavaScript
54+
│ ├── app.css # Frontend styles
55+
│ ├── config.js # Generated: Platform config constants
56+
│ ├── page_asset.js # Generated: Embedded index.html
57+
│ ├── strategy_profiles_asset.js # Generated: Strategy catalog
58+
│ ├── app_css.js # Generated: Embedded styles
59+
│ ├── app_js.js # Generated: Embedded JS
60+
│ └── wrangler.toml.example # Cloudflare Workers config template
61+
62+
├── schemas/ # Shared JSON Schema (consumed by both)
63+
│ └── runtime-target.schema.json # Runtime target validation schema
64+
65+
├── tests/ # JavaScript tests
66+
│ ├── strategy_switch_worker_validation.mjs
67+
│ └── test_cash_financing.js
68+
69+
├── docs/ # Documentation
70+
├── examples/targets/ # Example runtime targets per platform
71+
├── prompts/ # LLM prompt templates
72+
73+
└── .github/workflows/ # CI/CD workflows
74+
├── validate.yml # Python + JS validation (split jobs)
75+
├── deploy-strategy-switch-console.yml
76+
├── manual-strategy-switch.yml
77+
├── codex_pr_review.yml
78+
└── codex_review_gate.yml
79+
```
80+
81+
---
82+
83+
## Tier 1: Source of Truth — `platform-config.json`
84+
85+
Defines the entire runtime configuration universe:
86+
87+
- **4 domains**: `us_equity`, `hk_equity`, `cn_equity`, `crypto`
88+
- **6 platforms**: `longbridge`, `ibkr`, `schwab`, `firstrade`, `qmt`, `binance`
89+
- **18 strategy profiles** with features: income layer, option overlay, DCA, combo
90+
- **Platform capabilities, CSS theming, default accounts, repositories, variable scopes**
91+
92+
Never hardcode platform or strategy data in frontend code — regenerate from this file.
93+
94+
---
95+
96+
## Tier 2: Python Tooling (`python/`)
97+
98+
The `python/` directory contains all Python code, organized as a self-contained project with its own `pyproject.toml`.
99+
100+
**Key scripts:**
101+
102+
| Script | Purpose |
103+
|--------|---------|
104+
| `build_config.py` | Full pipeline: validate config, generate strategy profiles, inject into index.html |
105+
| `build_platform_config.py` | Generate `config.js` (ES module) from `platform-config.json` |
106+
| `runtime_settings.py` | Core engine: validate targets, render variables, apply via `gh` CLI |
107+
| `build_runtime_switch.py` | Build transient runtime targets for manual strategy switch |
108+
| `inject_platform_config.py` | Inject platform config globals into `index.html` |
109+
| `sync_strategy_switch_page_asset.py` | Embed HTML/JSON as ES module assets for Worker deployment |
110+
111+
**Dependency boundary:** Python scripts consume `schemas/runtime-target.schema.json`, `platform-config.json`, and write to `web/strategy-switch-console/`. They do **not** depend on the JavaScript code.
112+
113+
---
114+
115+
## Tier 3: Web Application (`web/`)
116+
117+
A Cloudflare Workers-based strategy switch console. Built with vanilla JS (no framework) and deployed via Wrangler.
118+
119+
**Key files:**
120+
121+
| File | Role |
122+
|------|------|
123+
| `worker.js` | Backend: OAuth, session management, config serving, switch dispatch, KV caching |
124+
| `index.html` | SPA shell with bilingual (zh/en) UI, platform selection, strategy configuration |
125+
| `app.js` | Frontend form logic, i18n, summary panel |
126+
| `config.js` (generated) | Platform config constants consumed by both frontend and worker |
127+
128+
**Dependency boundary:** The web app consumes generated assets (`config.js`, `page_asset.js`) and reads `platform-config.json` indirectly via the Worker API. It does **not** depend on Python scripts at runtime.
129+
130+
---
131+
132+
## CI/CD: Independent Validation
133+
134+
The `validate.yml` workflow runs **two independent jobs**:
135+
136+
1. **`python`** — Python tests, config validation, runtime target validation, dependency matrix checks
137+
2. **`js`** — JS module syntax checks, Worker asset validation, SPA integration tests
138+
139+
Neither job depends on the other. This ensures that a change to Python scripts doesn't need to wait for JS tests, and vice versa.
140+
141+
---
142+
143+
## Change Guide
144+
145+
- **Add a platform/strategy**: Edit `platform-config.json`, then run `python3 python/scripts/build_config.py` to regenerate all derived files.
146+
- **Modify build logic**: Edit files in `python/scripts/`, run `python3 -m unittest discover -s python/tests`.
147+
- **Modify web UI**: Edit files in `web/strategy-switch-console/`, run `node tests/strategy_switch_worker_validation.mjs`.
148+
- **Update runner**: Run both Python and JS validation locally before committing.
File renamed without changes.

0 commit comments

Comments
 (0)