Skip to content

Commit fae26ea

Browse files
Pigbibicodex
andcommitted
docs(qsl): separate bundle and rollout version sources
Co-Authored-By: Codex <noreply@openai.com>
1 parent 20a3a5c commit fae26ea

2 files changed

Lines changed: 61 additions & 32 deletions

File tree

docs/qsl_compat_upgrade.md

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,31 @@ python scripts/render_qsl_dependency_graph.py --repo-root . --format md
5151
- 当前 checker 已识别 `legacy_reason``live_constraint_files``owner` / `expires_at` / `next_action` 已进入 checker warning,用于约束过渡例外的负责人、到期日和下一步动作。
5252
- `--non-strict` 仅用于本地快速预览,不作为发布门禁依据。
5353

54-
## 当前中心兼容基线
55-
56-
- Bundle: `2026.08.0`
57-
- QPK: `3acab1923a97b805b077c85c6c19657be0143bac`
58-
- UsEquityStrategies: `be1a2c9f7c388d4dd78bda6c2dd7ccad0d4b13b4`
59-
- HkEquityStrategies: `72008f44050b0dc7415334535dbe784793180159`
60-
- CnEquityStrategies: `167355385dde4e1a2b9dea4ede7077f9fbda13ce`
61-
- CryptoStrategies: `d2b43112154c35c7b6c2651a240054926a779ae9`
62-
- QuantStrategyPlugins: `c798397d9ca9230e404673d7774bac3d478217dc`
63-
- MarketSignalSources: `956dd380f75aac4ecb6f8443d95619c8a7f1c52b`
54+
## 版本真相边界与受控升级
55+
56+
不要在文档中把一个 SHA 解释为“所有平台当前运行版本”。QSL 有三个各司其职的版本来源:
57+
58+
| 目的 | 唯一来源 | 含义 |
59+
| --- | --- | --- |
60+
| 兼容目标 | `compat/bundles/<bundle>.toml` | 已发布的兼容 bundle;用于严格仓库校验与回退基线。 |
61+
| 已验证平台实际 pin | `internal_dependency_matrix.json` | 从各 consumer 仓库的 `main` 依赖文件生成;这是平台/策略当前已合入版本的唯一台账。 |
62+
| 下一轮 QPK 候选 | `QuantPlatformKit/QPK_PIN` | 只表示待分阶段推广的候选,不代表任何平台已经升级。 |
63+
64+
`QPK_PIN` 变更先经过候选安装与依赖检查,再以只改该文件的 PR 进入主分支。随后才按
65+
`strategy → consumer → aggregate bundle` 顺序创建下游 PR;每一个下游 PR 仍须通过自身 CI,
66+
不会直接触发运行时部署或交易。平台版本与候选不同步时,优先读取 matrix,而不是 bundle
67+
或候选 pin。
68+
69+
在同步下游仓库后,用生成器维护和核对实际台账:
70+
71+
```bash
72+
python3 python/scripts/qslctl.py generate-matrix --projects-root .. --check --strict
73+
python3 python/scripts/qslctl.py generate-matrix --projects-root .. --sync
74+
python3 python/scripts/check_internal_dependency_matrix.py --projects-root .. --strict --require-consumer-files
75+
```
76+
77+
第一条命令用于 CI/监测,第二条只在经过下游 CI 的变更需要提交台账时使用。这样 bundle、
78+
候选和实际运行依赖不会再因重复手工维护而相互矛盾。
6479

6580
## Phase-2 Transition Warning 收敛路径
6681

python/tests/test_internal_dependency_matrix.py

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -99,32 +99,39 @@ def test_current_matrix_matches_local_workspace(self):
9999
self.assertEqual(report.missing_files, [])
100100
self.assertEqual(report.issues, [])
101101

102-
def test_tracked_qpk_consumer_pins_match_latest_matrix_snapshot(self):
103-
expected_pins_by_consumer = {
104-
"BinancePlatform": "9f7e7f8335e97f83f66677ad5e73254a1a421759",
105-
"CharlesSchwabPlatform": "9f7e7f8335e97f83f66677ad5e73254a1a421759",
106-
"CnEquityStrategies": "54d4ba901ae4e72e09c143c051747b900de55022",
107-
"CryptoStrategies": "54d4ba901ae4e72e09c143c051747b900de55022",
108-
"FirstradePlatform": "9f7e7f8335e97f83f66677ad5e73254a1a421759",
109-
"HkEquityStrategies": "54d4ba901ae4e72e09c143c051747b900de55022",
110-
"InteractiveBrokersPlatform": "9f7e7f8335e97f83f66677ad5e73254a1a421759",
111-
"LongBridgePlatform": "9f7e7f8335e97f83f66677ad5e73254a1a421759",
112-
"UsEquityStrategies": "54d4ba901ae4e72e09c143c051747b900de55022",
113-
"UsEquitySnapshotPipelines": "2341557b8ded834bd41ef5a92111361dbf8844d9",
102+
def test_tracked_qpk_consumer_pins_are_coherent_per_consumer(self):
103+
tracked_consumers = {
104+
"BinancePlatform",
105+
"CharlesSchwabPlatform",
106+
"CnEquityStrategies",
107+
"CryptoStrategies",
108+
"FirstradePlatform",
109+
"HkEquityStrategies",
110+
"InteractiveBrokersPlatform",
111+
"LongBridgePlatform",
112+
"UsEquityStrategies",
113+
"UsEquitySnapshotPipelines",
114114
}
115115
matrix_pins = check_internal_dependency_matrix.load_matrix(ROOT / "internal_dependency_matrix.json")
116116
refs = {
117117
(pin.consumer_repo, pin.path): pin.ref
118118
for pin in matrix_pins
119-
if pin.consumer_repo in expected_pins_by_consumer and pin.source_repo == "QuantPlatformKit"
119+
if pin.consumer_repo in tracked_consumers and pin.source_repo == "QuantPlatformKit"
120120
}
121-
expected_refs = {
122-
(consumer_repo, path): ref
123-
for consumer_repo, ref in expected_pins_by_consumer.items()
121+
expected_keys = {
122+
(consumer_repo, path)
123+
for consumer_repo in tracked_consumers
124124
for path in ("pyproject.toml", "uv.lock")
125125
}
126126

127-
self.assertEqual(refs, expected_refs)
127+
self.assertEqual(set(refs), expected_keys)
128+
for consumer_repo in tracked_consumers:
129+
consumer_refs = {
130+
refs[(consumer_repo, path)]
131+
for path in ("pyproject.toml", "uv.lock")
132+
}
133+
self.assertEqual(len(consumer_refs), 1)
134+
self.assertRegex(next(iter(consumer_refs)), r"^[0-9a-f]{40}$")
128135

129136
uesp_strategy_refs = {
130137
(pin.consumer_repo, pin.path): pin.ref
@@ -133,12 +140,19 @@ def test_tracked_qpk_consumer_pins_match_latest_matrix_snapshot(self):
133140
and pin.source_repo == "UsEquityStrategies"
134141
}
135142
self.assertEqual(
136-
uesp_strategy_refs,
137-
{
138-
("UsEquitySnapshotPipelines", path): "180701592efda47d8acd824dca98f3d74a5ee462"
139-
for path in ("pyproject.toml", "uv.lock")
140-
},
143+
set(uesp_strategy_refs),
144+
{("UsEquitySnapshotPipelines", path) for path in ("pyproject.toml", "uv.lock")},
141145
)
146+
self.assertEqual(len(set(uesp_strategy_refs.values())), 1)
147+
self.assertRegex(next(iter(uesp_strategy_refs.values())), r"^[0-9a-f]{40}$")
148+
149+
def test_upgrade_document_distinguishes_target_candidate_and_observed_pins(self):
150+
document = (ROOT / "docs" / "qsl_compat_upgrade.md").read_text(encoding="utf-8")
151+
152+
self.assertIn("compat/bundles/<bundle>.toml", document)
153+
self.assertIn("internal_dependency_matrix.json", document)
154+
self.assertIn("QuantPlatformKit/QPK_PIN", document)
155+
self.assertNotRegex(document, r"[0-9a-f]{40}")
142156

143157
def test_require_consumer_files_treats_missing_paths_as_issues(self):
144158
projects_root = self._make_projects_root({})

0 commit comments

Comments
 (0)