Skip to content

Commit f1985bb

Browse files
Pigbibicodex
andcommitted
feat(qsl): converge taxonomy and bundle governance
Co-Authored-By: Codex <noreply@openai.com>
1 parent b16a480 commit f1985bb

12 files changed

Lines changed: 397 additions & 20 deletions

File tree

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @Pigbibi

.github/codex_auto_merge_policy.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
],
4545
"timeout_minutes": 20,
4646
"max_diff_lines": 2400,
47-
"block_on_review_failure": false
47+
"auto_converge_after": 0,
48+
"block_on_review_failure": true
4849
}
4950
}

.github/workflows/codex_pr_review.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ jobs:
1919
uses: QuantStrategyLab/AIAuditBridge/.github/workflows/codex_pr_review.yml@main
2020
with:
2121
caller_concurrency_key: pr-${{ github.event.pull_request.number || github.run_id }}
22-
allow_unconfigured_backend: true
22+
allow_unconfigured_backend: false
23+
api_fallback_enabled: "false"
24+
direct_api_primary_enabled: "false"
2325
secrets: inherit
2426
permissions:
2527
contents: read

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ on:
129129
type: string
130130
default: sync-cloud-run-env.yml
131131

132+
permissions:
133+
contents: read
134+
132135
concurrency:
133136
group: runtime-strategy-switch-${{ inputs.platform }}-${{ inputs.target_name }}
134137
cancel-in-progress: false

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ This repository is the central manifest source for QSL compatibility checks.
4444
- `scripts/check_qsl_compat.py`: validate a repo's QSL compliance in `pyproject.toml`/`uv.lock` against central bundle.
4545
- `python/scripts/qslctl.py`: unified QSL version-control CLI for repo checks, workspace checks, ring reports/plans, and matrix generation.
4646
- `scripts/render_qsl_dependency_graph.py`: render dependency graph for review.
47-
- `compat/bundles/2026.07.2.toml`: current compatibility bundle baseline (CalVer).
47+
- `compat/bundles/2026.07.3.toml`: current compatibility bundle baseline (CalVer).
4848
- `compat/repo-tiers.toml`: repo tier and upgrade ring policy notes.
4949
- [QSL compatibility docs](docs/qsl_compat_upgrade.md)
5050

compat/bundles/2026.07.3.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name = "2026.07.3"
2+
description = "QSL compatibility bundle after runtime QPK pin convergence"
3+
created_at = "2026-07-10"
4+
5+
[repos]
6+
QuantPlatformKit = "69a0256934d081b5ef309a885384b9eb9f62cf90"
7+
UsEquityStrategies = "17ddb86c72d44b2c7b78ba7a10d8f71b21180166"
8+
HkEquityStrategies = "b6a8ac2ad3c8110b5ea74fb059c8206388d63bcd"
9+
CnEquityStrategies = "12c0cd4801060fcb2f9452ffd9a7f48df446ddd0"
10+
CryptoStrategies = "ef78312d7653095f585c4f75d45bf765bedc2751"
11+
QuantStrategyPlugins = "1f3a27b8fd83d71b583f4f5160a748e95fbefaa1"
12+
MarketSignalSources = "bda8ab10b80a646e4b579ef4c0d5dfe90776e908"

docs/qsl_compat_upgrade.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ This repository defines the QSL central compatibility manifest and its upgrade p
55
## 文件结构
66

77
- `compat/bundles/*.toml`
8-
- 每个 bundle 用 Calendar Version 命名(当前:`2026.07.2`)。
8+
- 每个 bundle 用 Calendar Version 命名(当前:`2026.07.3`)。
99
- 记录 QSL 管控的固定内部仓库提交。
1010
- `compat/repo-tiers.toml`
1111
- 记录仓库层级(`core/strategy-lib/pipeline/runtime/ops`)与升级 ring 规则。
@@ -26,8 +26,8 @@ This repository defines the QSL central compatibility manifest and its upgrade p
2626

2727
```toml
2828
[qsl]
29-
bundle = "2026.07.2" # 选择要对齐的 central bundle
30-
compat = "2026.07.2" # 兼容检查入口(与 bundle 相同)
29+
bundle = "2026.07.3" # 选择要对齐的 central bundle
30+
compat = "2026.07.3" # 兼容检查入口(与 bundle 相同)
3131
tier = "ops/tooling"
3232
upgrade_ring = "ring_e"
3333
allow_legacy = false # 需要临时兼容时可先放开
@@ -53,7 +53,7 @@ python scripts/render_qsl_dependency_graph.py --repo-root . --format md
5353

5454
## 当前中心兼容基线
5555

56-
- Bundle: `2026.07.2`
56+
- Bundle: `2026.07.3`
5757
- QPK: `37c81901160c5b31127a27dba1c63944933fb6bf`
5858
- UsEquityStrategies: `17ddb86c72d44b2c7b78ba7a10d8f71b21180166`
5959
- HkEquityStrategies: `b6a8ac2ad3c8110b5ea74fb059c8206388d63bcd`

python/scripts/qslctl.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ def _status_bucket(result: RepoCheckResult) -> str:
187187

188188

189189
def _issue_kind(message: str) -> str:
190+
if message.startswith("invalid qsl.tier "):
191+
return "invalid qsl.tier"
192+
if message.startswith("invalid qsl.upgrade_ring "):
193+
return "invalid qsl.upgrade_ring"
194+
if message.startswith("tier/ring mismatch "):
195+
return "tier/ring mismatch"
196+
if message.startswith("forbidden dependency direction "):
197+
return "forbidden dependency direction"
190198
if message.startswith("bundle pin mismatch for "):
191199
return "bundle pin mismatch"
192200
if message.startswith("forbidden short/invalid ref "):
@@ -197,6 +205,10 @@ def _issue_kind(message: str) -> str:
197205
return "legacy dependency files detected"
198206
if message.startswith("unmanaged qsl dependency "):
199207
return "unmanaged qsl dependency"
208+
if message.startswith("non-canonical qsl.tier "):
209+
return "non-canonical qsl.tier"
210+
if message.startswith("non-canonical qsl.upgrade_ring "):
211+
return "non-canonical qsl.upgrade_ring"
200212
return "other"
201213

202214

python/tests/test_qsl_compat_checker.py

Lines changed: 140 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,42 @@ def _write_bundle(self, compat_root: Path, bundle_name: str, repos: dict[str, st
3030
block.append(f'{repo} = "{ref}"')
3131
bundle_path.write_text("\n".join(block) + "\n", encoding="utf-8")
3232

33+
def _write_repo_tiers(self, compat_root: Path) -> None:
34+
path = compat_root / "compat" / "repo-tiers.toml"
35+
path.parent.mkdir(parents=True, exist_ok=True)
36+
path.write_text(
37+
"[tiers]\n"
38+
'core = { name = "core" }\n'
39+
'strategy_lib = { name = "strategy-lib" }\n'
40+
'pipeline = { name = "pipeline" }\n'
41+
'runtime = { name = "runtime" }\n'
42+
'ops = { name = "ops/tooling" }\n'
43+
"\n[upgrade_rings]\n"
44+
'ring_a = "core"\n'
45+
'ring_b = "strategy-lib"\n'
46+
'ring_c = "pipeline"\n'
47+
'ring_d = "runtime"\n'
48+
'ring_e = "ops/tooling"\n'
49+
"\n[upgrade_rules]\n"
50+
"allow_drift = [\n"
51+
' "ops/tooling:runtime",\n'
52+
' "ops/tooling:pipeline",\n'
53+
' "ops/tooling:strategy-lib",\n'
54+
' "ops/tooling:core",\n'
55+
' "runtime:pipeline",\n'
56+
' "runtime:strategy-lib",\n'
57+
' "runtime:core",\n'
58+
' "pipeline:strategy-lib",\n'
59+
' "pipeline:core",\n'
60+
' "strategy-lib:core",\n'
61+
"]\n",
62+
encoding="utf-8",
63+
)
64+
3365
def test_root_compat_bundle_and_ring_schema(self):
3466
with tempfile.TemporaryDirectory() as workspace:
3567
compat_root = Path(workspace)
68+
self._write_repo_tiers(compat_root)
3669
self._write_bundle(
3770
compat_root,
3871
"2026.07.2",
@@ -63,6 +96,7 @@ def test_root_compat_bundle_and_ring_schema(self):
6396
def test_not_enforced_bundle_reports_warning_for_short_sha_and_mismatch_but_main_stays_issue(self):
6497
with tempfile.TemporaryDirectory() as workspace:
6598
compat_root = Path(workspace)
99+
self._write_repo_tiers(compat_root)
66100
self._write_bundle(
67101
compat_root,
68102
"2026.07.2",
@@ -103,6 +137,7 @@ def test_not_enforced_bundle_reports_warning_for_short_sha_and_mismatch_but_main
103137
def test_live_constraint_files_allow_full_sha_drift_from_bundle(self):
104138
with tempfile.TemporaryDirectory() as workspace:
105139
compat_root = Path(workspace)
140+
self._write_repo_tiers(compat_root)
106141
self._write_bundle(
107142
compat_root,
108143
"2026.07.2",
@@ -111,7 +146,7 @@ def test_live_constraint_files_allow_full_sha_drift_from_bundle(self):
111146
repo_root = self._make_repo_root(
112147
qsl_toml=(
113148
'tier = "core"\n'
114-
"ring = 0\n"
149+
'upgrade_ring = "ring_a"\n'
115150
"allow_legacy = true\n"
116151
"[compat]\n"
117152
'bundle = "2026.07.2"\n'
@@ -135,6 +170,7 @@ def test_live_constraint_files_allow_full_sha_drift_from_bundle(self):
135170
def test_live_constraint_files_still_block_short_refs(self):
136171
with tempfile.TemporaryDirectory() as workspace:
137172
compat_root = Path(workspace)
173+
self._write_repo_tiers(compat_root)
138174
self._write_bundle(
139175
compat_root,
140176
"2026.07.2",
@@ -143,7 +179,7 @@ def test_live_constraint_files_still_block_short_refs(self):
143179
repo_root = self._make_repo_root(
144180
qsl_toml=(
145181
'tier = "core"\n'
146-
"ring = 0\n"
182+
'upgrade_ring = "ring_a"\n'
147183
"allow_legacy = true\n"
148184
"[compat]\n"
149185
'bundle = "2026.07.2"\n'
@@ -167,6 +203,7 @@ def test_live_constraint_files_still_block_short_refs(self):
167203
def test_not_enforced_bundle_exception_metadata_notes(self):
168204
with tempfile.TemporaryDirectory() as workspace:
169205
compat_root = Path(workspace)
206+
self._write_repo_tiers(compat_root)
170207
self._write_bundle(
171208
compat_root,
172209
"2026.07.2",
@@ -175,7 +212,7 @@ def test_not_enforced_bundle_exception_metadata_notes(self):
175212
repo_root = self._make_repo_root(
176213
qsl_toml=(
177214
'tier = "pipeline"\n'
178-
"ring = 2\n"
215+
'upgrade_ring = "ring_c"\n'
179216
'owner = "pipeline-team"\n'
180217
'expires_at = "2099-12-31"\n'
181218
'next_action = "remove transition pin drift"\n'
@@ -198,6 +235,7 @@ def test_not_enforced_bundle_exception_metadata_notes(self):
198235
def test_legacy_reason_suppresses_allowed_legacy_warning(self):
199236
with tempfile.TemporaryDirectory() as workspace:
200237
compat_root = Path(workspace)
238+
self._write_repo_tiers(compat_root)
201239
self._write_bundle(
202240
compat_root,
203241
"2026.07.2",
@@ -206,7 +244,7 @@ def test_legacy_reason_suppresses_allowed_legacy_warning(self):
206244
repo_root = self._make_repo_root(
207245
qsl_toml=(
208246
'tier = "pipeline"\n'
209-
"ring = 2\n"
247+
'upgrade_ring = "ring_c"\n'
210248
"allow_legacy = true\n"
211249
'legacy_reason = "runtime deployment compatibility"\n'
212250
'owner = "runtime-team"\n'
@@ -232,6 +270,104 @@ def test_legacy_reason_suppresses_allowed_legacy_warning(self):
232270
self.assertIn("bundle pin mismatch", warnings[0])
233271
self.assertIn("legacy_reason=runtime deployment compatibility", notes)
234272

273+
def test_non_canonical_tier_and_ring_emit_warnings(self):
274+
with tempfile.TemporaryDirectory() as workspace:
275+
compat_root = Path(workspace)
276+
self._write_repo_tiers(compat_root)
277+
self._write_bundle(
278+
compat_root,
279+
"2026.07.2",
280+
{"QuantPlatformKit": "37c81901160c5b31127a27dba1c63944933fb6bf"},
281+
)
282+
repo_root = self._make_repo_root(
283+
qsl_toml=(
284+
'tier = "strategy-library"\n'
285+
"ring = 1\n"
286+
"[compat]\n"
287+
'bundle = "2026.07.2"\n'
288+
),
289+
pyproject=(
290+
'dependencies = ["quant-platform-kit @ '
291+
'git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@37c81901160c5b31127a27dba1c63944933fb6bf"]\n'
292+
),
293+
)
294+
295+
ok, issues, warnings, _notes = check_qsl_compat._check(repo_root=repo_root, compat_root=compat_root)
296+
297+
self.assertTrue(ok)
298+
self.assertEqual(issues, [])
299+
self.assertTrue(any("non-canonical qsl.tier 'strategy-library'" in item for item in warnings))
300+
self.assertTrue(any("non-canonical qsl.upgrade_ring '1'" in item for item in warnings))
301+
302+
def test_runtime_platform_alias_maps_to_runtime_without_direction_error(self):
303+
with tempfile.TemporaryDirectory() as workspace:
304+
root = Path(workspace)
305+
compat_root = root / "QuantRuntimeSettings"
306+
self._write_repo_tiers(compat_root)
307+
self._write_bundle(
308+
compat_root,
309+
"2026.07.2",
310+
{"QuantPlatformKit": "37c81901160c5b31127a27dba1c63944933fb6bf"},
311+
)
312+
(root / "QuantPlatformKit").mkdir(parents=True, exist_ok=True)
313+
(root / "QuantPlatformKit" / "qsl.toml").write_text(
314+
'tier = "core"\nupgrade_ring = "ring_a"\n[compat]\nbundle = "2026.07.2"\n',
315+
encoding="utf-8",
316+
)
317+
repo_root = self._make_repo_root(
318+
qsl_toml=(
319+
'tier = "runtime-platform"\n'
320+
"ring = 3\n"
321+
"[compat]\n"
322+
'bundle = "2026.07.2"\n'
323+
),
324+
pyproject=(
325+
'dependencies = ["quant-platform-kit @ '
326+
'git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@37c81901160c5b31127a27dba1c63944933fb6bf"]\n'
327+
),
328+
)
329+
330+
ok, issues, warnings, _notes = check_qsl_compat._check(repo_root=repo_root, compat_root=compat_root)
331+
332+
self.assertTrue(ok)
333+
self.assertEqual(issues, [])
334+
self.assertTrue(any("non-canonical qsl.tier 'runtime-platform'" in item for item in warnings))
335+
self.assertTrue(any("non-canonical qsl.upgrade_ring '3'" in item for item in warnings))
336+
337+
def test_forbidden_dependency_direction_is_reported(self):
338+
with tempfile.TemporaryDirectory() as workspace:
339+
root = Path(workspace)
340+
compat_root = root / "QuantRuntimeSettings"
341+
self._write_repo_tiers(compat_root)
342+
self._write_bundle(
343+
compat_root,
344+
"2026.07.2",
345+
{"UsEquityStrategies": "17ddb86c72d44b2c7b78ba7a10d8f71b21180166"},
346+
)
347+
(root / "UsEquityStrategies").mkdir(parents=True, exist_ok=True)
348+
(root / "UsEquityStrategies" / "qsl.toml").write_text(
349+
'tier = "strategy-lib"\nupgrade_ring = "ring_b"\n[compat]\nbundle = "2026.07.2"\n',
350+
encoding="utf-8",
351+
)
352+
repo_root = self._make_repo_root(
353+
qsl_toml=(
354+
'tier = "core"\n'
355+
'upgrade_ring = "ring_a"\n'
356+
"[compat]\n"
357+
'bundle = "2026.07.2"\n'
358+
),
359+
pyproject=(
360+
'dependencies = ["us-equity-strategies @ '
361+
'git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@17ddb86c72d44b2c7b78ba7a10d8f71b21180166"]\n'
362+
),
363+
)
364+
365+
ok, issues, warnings, _notes = check_qsl_compat._check(repo_root=repo_root, compat_root=compat_root)
366+
367+
self.assertFalse(ok)
368+
self.assertEqual(warnings, [])
369+
self.assertTrue(any("forbidden dependency direction" in item for item in issues))
370+
235371

236372
if __name__ == "__main__":
237373
unittest.main()

0 commit comments

Comments
 (0)