quant1x 0.7.62.dev2__tar.gz → 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quant1x-0.8.0/.githooks/commit-msg +60 -0
- quant1x-0.8.0/.githooks/commit_msg_check.py +198 -0
- quant1x-0.8.0/.githooks/pre-commit +45 -0
- quant1x-0.8.0/.githooks/text_check.py +94 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/.gitignore +7 -1
- {quant1x-0.7.62.dev2/.vscode → quant1x-0.8.0/.vscode-default}/c_cpp_properties.json +1 -1
- {quant1x-0.7.62.dev2/.vscode → quant1x-0.8.0/.vscode-default}/settings.json +54 -29
- quant1x-0.8.0/.vscode-macos/settings.json +11 -0
- quant1x-0.8.0/.vscode-windows/launch.json +12 -0
- quant1x-0.8.0/.vscode-windows/settings.json +19 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/AGENTS.md +68 -0
- quant1x-0.8.0/CHANGELOG.md +2979 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/CMakeLists.txt +80 -9
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/Cargo.lock +534 -699
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/Cargo.toml +14 -3
- quant1x-0.8.0/PKG-INFO +575 -0
- quant1x-0.8.0/README.md +526 -0
- quant1x-0.8.0/assets/icons/android/ic_launcher-playstore.png +0 -0
- quant1x-0.8.0/assets/icons/android/mipmap-hdpi/ic_launcher.png +0 -0
- quant1x-0.8.0/assets/icons/android/mipmap-mdpi/ic_launcher.png +0 -0
- quant1x-0.8.0/assets/icons/android/mipmap-xhdpi/ic_launcher.png +0 -0
- quant1x-0.8.0/assets/icons/android/mipmap-xxhdpi/ic_launcher.png +0 -0
- quant1x-0.8.0/assets/icons/android/mipmap-xxxhdpi/ic_launcher.png +0 -0
- quant1x-0.8.0/assets/icons/icon-1024.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-1024x1024.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-20x20@1x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-20x20@2x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-20x20@3x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-29x29@1x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-29x29@2x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-29x29@3x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-40x40@2x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-40x40@3x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-60x60@2x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-60x60@3x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-76x76@1x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-76x76@2x.png +0 -0
- quant1x-0.8.0/assets/icons/ios/Icon-App-83.5x83.5@2x.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_128x128.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_128x128@2x.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_16x16.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_16x16@2x.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_256x256.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_256x256@2x.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_32x32.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_32x32@2x.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_512x512.png +0 -0
- quant1x-0.8.0/assets/icons/macos/icon_512x512@2x.png +0 -0
- quant1x-0.8.0/assets/icons/web/android-chrome-192x192.png +0 -0
- quant1x-0.8.0/assets/icons/web/android-chrome-512x512.png +0 -0
- quant1x-0.8.0/assets/icons/web/apple-touch-icon.png +0 -0
- quant1x-0.8.0/assets/icons/web/favicon-16x16.png +0 -0
- quant1x-0.8.0/assets/icons/web/favicon-32x32.png +0 -0
- quant1x-0.8.0/assets/icons/web/favicon-64x64.png +0 -0
- quant1x-0.8.0/assets/icons/web/favicon-96x96.png +0 -0
- quant1x-0.8.0/assets/icons/web/favicon.ico +0 -0
- quant1x-0.8.0/assets/icons/web/mstile-150x150.png +0 -0
- quant1x-0.8.0/assets/icons/web/site.webmanifest +19 -0
- quant1x-0.8.0/assets/icons/windows/app-256.png +0 -0
- quant1x-0.8.0/assets/icons/windows/app.ico +0 -0
- quant1x-0.8.0/logo.png +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/main.go +1 -1
- quant1x-0.8.0/mvnw +227 -0
- quant1x-0.8.0/mvnw.cmd +211 -0
- quant1x-0.8.0/pom.xml +88 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/pyproject.toml +10 -2
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/_version.py +3 -3
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/bits.py +4 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/asset_class.py +1 -1
- quant1x-0.8.0/quant1x/distributed/__init__.py +4 -0
- quant1x-0.8.0/quant1x/distributed/id/FileStateStore.java +145 -0
- quant1x-0.8.0/quant1x/distributed/id/Generator.java +46 -0
- quant1x-0.8.0/quant1x/distributed/id/HLC.java +155 -0
- quant1x-0.8.0/quant1x/distributed/id/Id.java +78 -0
- quant1x-0.8.0/quant1x/distributed/id/Option.java +57 -0
- quant1x-0.8.0/quant1x/distributed/id/PersistentState.java +35 -0
- quant1x-0.8.0/quant1x/distributed/id/README.md +235 -0
- quant1x-0.8.0/quant1x/distributed/id/StateStore.java +10 -0
- quant1x-0.8.0/quant1x/distributed/id/__init__.py +48 -0
- quant1x-0.8.0/quant1x/distributed/id/generator.py +74 -0
- quant1x-0.8.0/quant1x/distributed/id/hlc.py +109 -0
- quant1x-0.8.0/quant1x/distributed/id/id.py +83 -0
- quant1x-0.8.0/quant1x/distributed/id/option.py +80 -0
- quant1x-0.8.0/quant1x/distributed/id/queue.py +125 -0
- quant1x-0.8.0/quant1x/distributed/id/state_store.py +435 -0
- quant1x-0.8.0/quant1x/distributed/id/tests.py +306 -0
- quant1x-0.8.0/quant1x/id/id128/FileStateStore.java +279 -0
- quant1x-0.8.0/quant1x/id/id128/Generator.java +48 -0
- quant1x-0.8.0/quant1x/id/id128/HLC.java +219 -0
- quant1x-0.8.0/quant1x/id/id128/Id.java +88 -0
- quant1x-0.8.0/quant1x/id/id128/Option.java +99 -0
- quant1x-0.8.0/quant1x/id/id128/PersistentState.java +56 -0
- quant1x-0.8.0/quant1x/id/id128/README.md +387 -0
- quant1x-0.8.0/quant1x/id/id128/StateStore.java +36 -0
- quant1x-0.8.0/quant1x/id/id128/Uint128.java +284 -0
- quant1x-0.8.0/quant1x/id/id128/__init__.py +28 -0
- quant1x-0.8.0/quant1x/id/id128/generator.py +23 -0
- quant1x-0.8.0/quant1x/id/id128/hlc.py +103 -0
- quant1x-0.8.0/quant1x/id/id128/id.py +38 -0
- quant1x-0.8.0/quant1x/id/id128/id_test.py +93 -0
- quant1x-0.8.0/quant1x/id/id128/option.py +65 -0
- quant1x-0.8.0/quant1x/id/id128/state_store.py +274 -0
- quant1x-0.8.0/quant1x/id/id128/uint128.py +105 -0
- quant1x-0.8.0/quant1x/id/id64/ByteIO.java +59 -0
- quant1x-0.8.0/quant1x/id/id64/FileStateStore.java +272 -0
- quant1x-0.8.0/quant1x/id/id64/Generator.java +60 -0
- quant1x-0.8.0/quant1x/id/id64/HLC.java +202 -0
- quant1x-0.8.0/quant1x/id/id64/Id.java +94 -0
- quant1x-0.8.0/quant1x/id/id64/Option.java +97 -0
- quant1x-0.8.0/quant1x/id/id64/PersistentState.java +53 -0
- quant1x-0.8.0/quant1x/id/id64/README.md +246 -0
- quant1x-0.8.0/quant1x/id/id64/StateStore.java +36 -0
- quant1x-0.8.0/quant1x/id/id64/__init__.py +31 -0
- quant1x-0.8.0/quant1x/id/id64/generator.py +41 -0
- quant1x-0.8.0/quant1x/id/id64/hlc.py +114 -0
- quant1x-0.8.0/quant1x/id/id64/id.py +58 -0
- quant1x-0.8.0/quant1x/id/id64/id_test.py +163 -0
- quant1x-0.8.0/quant1x/id/id64/option.py +108 -0
- quant1x-0.8.0/quant1x/id/id64/state_store.py +267 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/learn/regime/plot_results.py +4 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/learn/regime/regime_switching_framework.py +4 -0
- quant1x-0.8.0/quant1x/runtime/__init__.py +0 -0
- quant1x-0.8.0/quant1x/runtime/ringbuffer.md +179 -0
- quant1x-0.8.0/quant1x/runtime/ringbuffer.py +210 -0
- quant1x-0.8.0/quant1x/runtime/ringbuffer_test.py +81 -0
- quant1x-0.8.0/quant1x.egg-info/PKG-INFO +575 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x.egg-info/SOURCES.txt +108 -6
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x.egg-info/scm_file_list.json +187 -8
- quant1x-0.8.0/quant1x.egg-info/scm_version.json +8 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/rust-toolchain.toml +1 -1
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/vcpkg.json +23 -13
- quant1x-0.7.62.dev2/CHANGELOG.md +0 -2435
- quant1x-0.7.62.dev2/PKG-INFO +0 -630
- quant1x-0.7.62.dev2/README.md +0 -583
- quant1x-0.7.62.dev2/logo.png +0 -0
- quant1x-0.7.62.dev2/quant1x/base/cache/market.dat +0 -4
- quant1x-0.7.62.dev2/quant1x/runtime/ringbuffer.md +0 -79
- quant1x-0.7.62.dev2/quant1x.cer +0 -0
- quant1x-0.7.62.dev2/quant1x.egg-info/PKG-INFO +0 -630
- quant1x-0.7.62.dev2/quant1x.egg-info/scm_version.json +0 -8
- quant1x-0.7.62.dev2/quant1x.pfx +0 -0
- quant1x-0.7.62.dev2/requirements.txt +0 -34
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/.clang-format +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/.clang-tidy +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/.clock_state +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/.editorconfig +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/.gitattributes +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/CONTRIBUTING.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/LICENSE +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/MANIFEST.in +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/b2c.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/labs/akshare.ipynb +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/labs/qlib.ipynb +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/labs/quant1x.ipynb +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/main.cpp +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/main.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/main.rs +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/proto/chips.proto +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/proto/snapshot.capnp +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/proto/snapshot.capnp.c++ +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/proto/test-snapshot.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/proto/trans.proto +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/proto/xdxr.proto +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/publish.bat +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/publish.ps1 +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/publish.sh +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/clock.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/dataclass_utils.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/embed.go.copy +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/except.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/filesystem.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/numeric.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/numeric.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/pattern.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/singleton.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/strings.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/strings.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/system.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/base/time.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/build-info.h.in +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/config/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/config/config.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/em/em_dividend.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/_constants.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/bar.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/bar_raw.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/client.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/command.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/config.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/datasource.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/financial_report.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/helpers.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/instruments.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/auction.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/ext/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/ext/ext-category.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/ext/hk_f10.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/ext/xdxr_hkex.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/fund.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/block.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/block_meta.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/finance_info.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/heartbeat.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/hello.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/minute_time.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/security_bars.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/security_count.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/security_list.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/security_quote.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/security_quote.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/transaction.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/level1/std/xdxr_info.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/market.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/money.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/notice.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/protocol.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/sector.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/share_holder.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/trans.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/contrib/data/tdx/xdxr.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/core/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/core/base.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/core/decode.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/core/defaults.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/adapter.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/base.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/cache.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/datasource.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/f10.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/margin_trading.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/market.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/calendar.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/exchange.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/forex.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/frequency.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/fund.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/fund.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/instrument.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/layout.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/region.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/session.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/session.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/sina/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/sina/decoder.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/ticker_rules/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/ticker_rules/market_bse.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/ticker_rules/market_hkex.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/ticker_rules/market_sse.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/ticker_rules/market_szse.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/ticker_rules/market_usa.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/ticker_rules/rule.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/meta/timestamp.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/adjustment.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/adjustment.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/bar.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/bar.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/company.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/company.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/dividend.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/dividend.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/sector.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/sector.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/trade.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/schema/trade.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/status.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/storage/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/storage/csv.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/storage/storage.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/data/storage/storage.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/device.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/devp.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/encoding/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/encoding/binary/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/encoding/binary/cstruct/FORK.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/encoding/binary/cstruct/LICENSE +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/encoding/binary/cstruct/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/encoding/binary/struc/LICENSE +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/encoding/binary/struc/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/encoding/json.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/encoding/yaml.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/factors/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/factors/f10.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/factors/financial_report.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/factors/notice.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/factors/safety_score.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/factors/share_holder.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/formula/README-MyTT.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/formula/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/formula/formula.ipynb +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/formula/formula.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/formula/formula_plus.py +0 -0
- {quant1x-0.7.62.dev2/quant1x/runtime → quant1x-0.8.0/quant1x/id}/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/cdtd.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/cdtd.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/f89k.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/f89k.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/hjk.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/hjk.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/ma1x.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/ma1x.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/p2fb.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/p2fb.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/indicators/winner.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/io/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/io/connection_pool.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/io/connection_pool.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/io/csv-reader.LICENSE +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/io/csv-reader.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/io/endpoint.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/io/operation_handler.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/learn/fpgrowth/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/learn/fpgrowth/fp_growth.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/learn/fpgrowth/fp_growth_example.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/learn/regime/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/log/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/log/logger.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/log4rs.yaml +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/net/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/net/conn.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/net/endpoint.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/net/handler.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/net/tcp_client_pool.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/network.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/proto/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/proto/security_info.proto +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/proto/snapshot.capnp.c++ +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/resources/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/resources/meta/tdxhy.inc +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/resources/meta/tdxzs.inc +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/resources/meta/tdxzs3.inc +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/runtime/once.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/runtime/scheduler.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/runtime/scheduler.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/ta/README.md +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/tools/inspect_blocks.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/types.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/util/SimHei.ttf +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/util/__init__.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/util/chart.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/util/font.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/util/util-font.ipynb +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x/version.py +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x.egg-info/dependency_links.txt +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x.egg-info/not-zip-safe +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x.egg-info/requires.txt +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/quant1x.egg-info/top_level.txt +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/setup.cfg +0 -0
- {quant1x-0.7.62.dev2 → quant1x-0.8.0}/test_loop.sh +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# commit-msg 钩子:提交信息编码校验(非法 UTF-8 / GBK 乱码 → 拒绝提交)
|
|
3
|
+
# 校验逻辑见同目录 commit_msg_check.py
|
|
4
|
+
hook_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
5
|
+
run_check() {
|
|
6
|
+
# 优先使用 python / python3;在 Windows 环境下回退到 py -3
|
|
7
|
+
if command -v python >/dev/null 2>&1; then
|
|
8
|
+
python -V >/dev/null 2>&1
|
|
9
|
+
probe=$?
|
|
10
|
+
if [ "$probe" -ne 126 ] && [ "$probe" -ne 127 ]; then
|
|
11
|
+
python "$hook_dir/commit_msg_check.py" "$1"
|
|
12
|
+
return $?
|
|
13
|
+
fi
|
|
14
|
+
fi
|
|
15
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
16
|
+
python3 -V >/dev/null 2>&1
|
|
17
|
+
probe=$?
|
|
18
|
+
if [ "$probe" -ne 126 ] && [ "$probe" -ne 127 ]; then
|
|
19
|
+
python3 "$hook_dir/commit_msg_check.py" "$1"
|
|
20
|
+
return $?
|
|
21
|
+
fi
|
|
22
|
+
fi
|
|
23
|
+
if command -v py >/dev/null 2>&1; then
|
|
24
|
+
py -3 -V >/dev/null 2>&1
|
|
25
|
+
probe=$?
|
|
26
|
+
if [ "$probe" -ne 126 ] && [ "$probe" -ne 127 ]; then
|
|
27
|
+
py -3 "$hook_dir/commit_msg_check.py" "$1"
|
|
28
|
+
return $?
|
|
29
|
+
fi
|
|
30
|
+
fi
|
|
31
|
+
return 127
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
run_check "$1"
|
|
35
|
+
check_rc=$?
|
|
36
|
+
if [ "$check_rc" -eq 127 ]; then
|
|
37
|
+
echo "commit-msg 校验未通过:未找到可用 Python 解释器(python/python3/py -3)。" >&2
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
if [ "$check_rc" -ne 0 ]; then
|
|
41
|
+
echo "commit-msg 校验未通过,提交已中止。请修正提交信息后重试。" >&2
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# 提交尾注/署名约束(仓库规则):
|
|
46
|
+
# - 禁止 Co-authored-by trailer
|
|
47
|
+
# - 禁止 Copilot/AI 署名(包含历史常见 noreply 地址)
|
|
48
|
+
msg_file="$1"
|
|
49
|
+
if [ -n "$msg_file" ] && [ -f "$msg_file" ]; then
|
|
50
|
+
if tr -d '\r' < "$msg_file" | grep -Eiq '^[[:space:]]*co-authored-by[[:space:]]*:'; then
|
|
51
|
+
echo "commit-msg 校验未通过:禁止 Co-authored-by trailer。" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
if tr -d '\r' < "$msg_file" | grep -Eiq 'copilot@users\.noreply\.github\.com|^[[:space:]]*(copilot|ai)[[:space:]]*(署名|signature)[[:space:]]*:'; then
|
|
55
|
+
echo "commit-msg 校验未通过:禁止 Copilot/AI 署名信息。" >&2
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
exit 0
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2026 Quant1X <wangfengxy@sina.cn>
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-only
|
|
4
|
+
|
|
5
|
+
"""commit-msg 校验:提交信息编码完整性检查(拒绝乱码/损坏文本)。
|
|
6
|
+
|
|
7
|
+
Windows 下中文提交信息若经 GBK 命令行/控制台传递,会被错误转码并作为
|
|
8
|
+
“合法 UTF-8 的乱码文本”写入提交对象(历史上有 daa14be / 8e49a85 两例)。
|
|
9
|
+
本脚本只做两类判断,全部基于编码事实,不维护任何“乱码特征字”黑名单:
|
|
10
|
+
|
|
11
|
+
一、硬性检查(编码损坏的直接证据)
|
|
12
|
+
- 必须整体是合法 UTF-8;
|
|
13
|
+
- 不含 NUL 字节、替换符 U+FFFD、私有区字符(PUA)。
|
|
14
|
+
这些都是正常输入不可能出现、只会由编码损坏产生的字符。
|
|
15
|
+
|
|
16
|
+
二、round-trip 反推(乱码检测主逻辑)
|
|
17
|
+
乱码的产生链是确定的:
|
|
18
|
+
原始 UTF-8 字节流 → 被按编码 E 误读(得到“乱码字符”)
|
|
19
|
+
→ 再以 UTF-8 存储(得到我们看到的文本)
|
|
20
|
+
因此把待检文本按 E 重新编码、再按 UTF-8 解码,若还原出的文本
|
|
21
|
+
“与原文不同且以汉字为主”,即可确认它是 E 误读的产物:
|
|
22
|
+
text.encode(E).decode('utf-8') → 原始中文
|
|
23
|
+
CANDIDATES 列出常见误读链(GB18030/CP1252/Latin-1/Shift_JIS/
|
|
24
|
+
EUC-KR/KOI8-R 等)。将来出现“UTF-8 被当作编码 X 读取”的新形态,
|
|
25
|
+
只需在 CANDIDATES 增补一行,无需维护字符表。
|
|
26
|
+
|
|
27
|
+
误报分析(为何“还原出汉字”是强信号):
|
|
28
|
+
- 正常中文文本按 GBK/GB18030 整体编码后,字节流几乎必然无法构成
|
|
29
|
+
合法 UTF-8(单字双字节落点不在 UTF-8 合法区间内,序列连续性亦
|
|
30
|
+
不成立),解码必然失败;即便以 errors='replace' 宽容扫描,GBK
|
|
31
|
+
字节偶合出的 UTF-8 片段也只会落在 Latin 区(2 字节 UTF-8 编码
|
|
32
|
+
范围 U+0080..U+07FF 不含汉字),汉字必须由 3 字节 UTF-8 编码,
|
|
33
|
+
这种连续偶合几乎不可能成串出现。因此“还原文本含 >= 2 个汉字”
|
|
34
|
+
基本只可能来自真正的乱码。
|
|
35
|
+
|
|
36
|
+
字节丢失处理:误读链若带丢字节(历史两例即如此),还原会以
|
|
37
|
+
errors='replace' 进行,丢失处产生 U+FFFD。此时用 “FFFD 数 <= 还原
|
|
38
|
+
汉字数” 约束:真乱码还原后汉字是主体、FFFD 只是零星丢失位;
|
|
39
|
+
正常文本偶合还原出的汉字极少而 FFFD 占绝对多数,二者可明确区分。
|
|
40
|
+
|
|
41
|
+
用法:
|
|
42
|
+
python commit_msg_check.py <commit-msg-file>
|
|
43
|
+
python commit_msg_check.py --debug <commit-msg-file> # 诊断模式
|
|
44
|
+
返回 0 通过;非 0 拒绝(信息输出到 stderr)。
|
|
45
|
+
|
|
46
|
+
--debug 模式:对每个 CANDIDATE 打印 round-trip 诊断(encode 结果、
|
|
47
|
+
解码模式、还原汉字数 / FFFD 数、是否命中),便于排查“新出现的乱码
|
|
48
|
+
形态应归入哪条误读链”。
|
|
49
|
+
"""
|
|
50
|
+
import re
|
|
51
|
+
import sys
|
|
52
|
+
|
|
53
|
+
# 误读链候选,按仓库环境(Windows/中文)常见度排序;每条注明典型场景,
|
|
54
|
+
# 日后按“实际观测到的新乱码形态”增补即可:
|
|
55
|
+
# gb18030 Windows 简体中文环境把 UTF-8 字节流按 GBK/CP936 读取后再以
|
|
56
|
+
# UTF-8 存储 —— 本仓库历史乱码(daa14be / 8e49a85)即此链;
|
|
57
|
+
# GB18030 是 GBK 的超集,覆盖其全部单/双字节形态
|
|
58
|
+
# cp1252 Windows 拉丁环境按 CP1252 读取 UTF-8(“é…” 型 mojibake)
|
|
59
|
+
# latin-1 逐字节无损映射的 ISO-8859-1,覆盖 cp1252 未包含的 0x80-0x9F 形态
|
|
60
|
+
# shift_jis 日文环境按 Shift_JIS/CP932 读取 UTF-8
|
|
61
|
+
# euc_kr 韩文环境按 EUC-KR 读取 UTF-8
|
|
62
|
+
# koi8_r 俄文/西里尔环境按 KOI8-R 读取 UTF-8
|
|
63
|
+
CANDIDATES = [
|
|
64
|
+
("gb18030", "UTF-8 被按 GBK/GB18030 误读"),
|
|
65
|
+
("cp1252", "UTF-8 被按 CP1252 误读"),
|
|
66
|
+
("latin-1", "UTF-8 被按 Latin-1(ISO-8859-1) 误读"),
|
|
67
|
+
("shift_jis", "UTF-8 被按 Shift_JIS/CP932 误读"),
|
|
68
|
+
("euc_kr", "UTF-8 被按 EUC-KR 误读"),
|
|
69
|
+
("koi8_r", "UTF-8 被按 KOI8-R 误读"),
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
# 汉字集合(CJK 扩展 A + 统一表意 + 兼容表意)—— 还原文本“汉字量”判断用
|
|
73
|
+
_HAN_RE = re.compile(r"[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _roundtrip(enc, text):
|
|
77
|
+
"""单候选 round-trip 反推。encode 失败(该编码不可能误读出此文本)返回 None。"""
|
|
78
|
+
try:
|
|
79
|
+
raw = text.encode(enc)
|
|
80
|
+
except UnicodeEncodeError:
|
|
81
|
+
return None
|
|
82
|
+
try:
|
|
83
|
+
recovered = raw.decode("utf-8")
|
|
84
|
+
mode = "strict"
|
|
85
|
+
loss = 0
|
|
86
|
+
except UnicodeDecodeError:
|
|
87
|
+
recovered = raw.decode("utf-8", errors="replace")
|
|
88
|
+
mode = "replace"
|
|
89
|
+
loss = recovered.count("\ufffd")
|
|
90
|
+
return {
|
|
91
|
+
"recovered": recovered,
|
|
92
|
+
"mode": mode,
|
|
93
|
+
"loss": loss,
|
|
94
|
+
"han": len(_HAN_RE.findall(recovered)),
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def detect_mojibake(text):
|
|
99
|
+
"""命中返回 (encoding, label, recovered),否则 None。"""
|
|
100
|
+
for enc, label in CANDIDATES:
|
|
101
|
+
r = _roundtrip(enc, text)
|
|
102
|
+
if r is None or r["recovered"] == text:
|
|
103
|
+
continue
|
|
104
|
+
if r["han"] >= 2 and r["loss"] <= r["han"]:
|
|
105
|
+
return enc, label, r["recovered"]
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _clean_preview(text, limit=72):
|
|
110
|
+
out = []
|
|
111
|
+
for ch in text:
|
|
112
|
+
if ch == "\ufffd":
|
|
113
|
+
continue
|
|
114
|
+
o = ord(ch)
|
|
115
|
+
if o < 32 and ch not in "\t\n":
|
|
116
|
+
continue
|
|
117
|
+
out.append(ch)
|
|
118
|
+
return "".join(out)[:limit]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _debug_report(text, valid_utf8):
|
|
122
|
+
sys.stderr.write("commit-msg 校验 --debug:\n")
|
|
123
|
+
if not valid_utf8:
|
|
124
|
+
sys.stderr.write(" 文本非合法 UTF-8,round-trip 检测跳过(硬性检查已拒绝)\n")
|
|
125
|
+
return
|
|
126
|
+
for enc, label in CANDIDATES:
|
|
127
|
+
r = _roundtrip(enc, text)
|
|
128
|
+
if r is None:
|
|
129
|
+
sys.stderr.write(" %-9s %s\n" % (enc, "encode 失败——不可能为该编码误读产物"))
|
|
130
|
+
continue
|
|
131
|
+
same = r["recovered"] == text
|
|
132
|
+
hit = (not same and r["han"] >= 2 and r["loss"] <= r["han"])
|
|
133
|
+
verdict = "命中" if hit else ("还原=原文" if same else "未命中")
|
|
134
|
+
sys.stderr.write(
|
|
135
|
+
" %-9s %s decode=%s han=%d loss=%d %s\n"
|
|
136
|
+
% (enc, r["mode"], verdict, r["han"], r["loss"], label)
|
|
137
|
+
)
|
|
138
|
+
if hit:
|
|
139
|
+
sys.stderr.write(" 反推还原:%s\n" % _clean_preview(r["recovered"]))
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def check(path, debug=False):
|
|
143
|
+
with open(path, "rb") as f:
|
|
144
|
+
raw = f.read()
|
|
145
|
+
problems = []
|
|
146
|
+
|
|
147
|
+
if b"\x00" in raw:
|
|
148
|
+
problems.append("包含 NUL 字节")
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
text = raw.decode("utf-8")
|
|
152
|
+
valid_utf8 = True
|
|
153
|
+
except UnicodeDecodeError as e:
|
|
154
|
+
problems.append("不是合法 UTF-8:%s" % e)
|
|
155
|
+
text = raw.decode("utf-8", errors="replace")
|
|
156
|
+
valid_utf8 = False
|
|
157
|
+
|
|
158
|
+
if "\ufffd" in text:
|
|
159
|
+
problems.append("含替换符 U+FFFD(编码损坏标记)")
|
|
160
|
+
|
|
161
|
+
if any("\ue000" <= ch <= "\uf8ff" for ch in text):
|
|
162
|
+
problems.append("含私有区字符 U+E000..U+F8FF(编码损坏迹象)")
|
|
163
|
+
|
|
164
|
+
if debug:
|
|
165
|
+
_debug_report(text, valid_utf8)
|
|
166
|
+
|
|
167
|
+
if valid_utf8:
|
|
168
|
+
hit = detect_mojibake(text)
|
|
169
|
+
if hit:
|
|
170
|
+
enc, label, recovered = hit
|
|
171
|
+
preview = _clean_preview(recovered)
|
|
172
|
+
problems.append(
|
|
173
|
+
"%s:round-trip 反推可还原为「%s%s」"
|
|
174
|
+
% (label, preview, "…" if len(recovered) > 72 else "")
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
if problems:
|
|
178
|
+
for p in problems:
|
|
179
|
+
sys.stderr.write("commit-msg 校验未通过:%s\n" % p)
|
|
180
|
+
sys.stderr.write(
|
|
181
|
+
"提示:Windows 下提交中文信息请走 UTF-8 文件方式,例如\n"
|
|
182
|
+
" git commit -F .git/commit-msg.tmp\n"
|
|
183
|
+
"不要把中文直接写在命令行 -m 参数里。\n"
|
|
184
|
+
)
|
|
185
|
+
return 1
|
|
186
|
+
return 0
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
if __name__ == "__main__":
|
|
190
|
+
args = sys.argv[1:]
|
|
191
|
+
debug = False
|
|
192
|
+
if args and args[0] == "--debug":
|
|
193
|
+
debug = True
|
|
194
|
+
args = args[1:]
|
|
195
|
+
if len(args) < 1:
|
|
196
|
+
sys.stderr.write("usage: commit_msg_check.py [--debug] <commit-msg-file>\n")
|
|
197
|
+
sys.exit(2)
|
|
198
|
+
sys.exit(check(args[0], debug=debug))
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# pre-commit 钩子:提交内容编码校验(新混入 BOM → 拒绝提交)
|
|
3
|
+
# 校验逻辑见同目录 text_check.py
|
|
4
|
+
hook_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
5
|
+
run_check() {
|
|
6
|
+
# 优先使用 python / python3;在 Windows 环境下回退到 py -3
|
|
7
|
+
if command -v python >/dev/null 2>&1; then
|
|
8
|
+
python -V >/dev/null 2>&1
|
|
9
|
+
probe=$?
|
|
10
|
+
if [ "$probe" -ne 126 ] && [ "$probe" -ne 127 ]; then
|
|
11
|
+
python "$hook_dir/text_check.py"
|
|
12
|
+
return $?
|
|
13
|
+
fi
|
|
14
|
+
fi
|
|
15
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
16
|
+
python3 -V >/dev/null 2>&1
|
|
17
|
+
probe=$?
|
|
18
|
+
if [ "$probe" -ne 126 ] && [ "$probe" -ne 127 ]; then
|
|
19
|
+
python3 "$hook_dir/text_check.py"
|
|
20
|
+
return $?
|
|
21
|
+
fi
|
|
22
|
+
fi
|
|
23
|
+
if command -v py >/dev/null 2>&1; then
|
|
24
|
+
py -3 -V >/dev/null 2>&1
|
|
25
|
+
probe=$?
|
|
26
|
+
if [ "$probe" -ne 126 ] && [ "$probe" -ne 127 ]; then
|
|
27
|
+
py -3 "$hook_dir/text_check.py"
|
|
28
|
+
return $?
|
|
29
|
+
fi
|
|
30
|
+
fi
|
|
31
|
+
return 127
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
run_check
|
|
35
|
+
check_rc=$?
|
|
36
|
+
if [ "$check_rc" -eq 127 ]; then
|
|
37
|
+
echo "pre-commit 校验未通过:未找到可用 Python 解释器(python/python3/py -3)。" >&2
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
if [ "$check_rc" -ne 0 ]; then
|
|
41
|
+
echo "pre-commit 校验未通过,提交已中止。请去掉新混入的 BOM 后重试。" >&2
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
exit 0
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2026 Quant1X <wangfengxy@sina.cn>
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-only
|
|
4
|
+
|
|
5
|
+
"""pre-commit 校验:拦截混进本次提交内容的 BOM。
|
|
6
|
+
|
|
7
|
+
仓库一律 UTF-8 无 BOM —— 规定见 AGENTS.md 的「文件编码与行尾约定」。这东西肉眼
|
|
8
|
+
不可见,Markdown 预览里往往也不显示,靠事后自查容易漏,故在提交这道口子上堵住。
|
|
9
|
+
|
|
10
|
+
**为什么只查新增行,不扫整个文件**:CHANGELOG.md 现存 17 处行首 U+FEFF,是历史
|
|
11
|
+
事实,已明确不予追溯修正。若钩子扫全文件,那么每改动一次该文件都会被拦下 ——
|
|
12
|
+
规矩一旦扰民,最后的结果只会是被 `--no-verify` 绕过去。故这里只检查**本次提交
|
|
13
|
+
新引入的行**:既往的不良留在原地不动,新的一个也不许进来。
|
|
14
|
+
|
|
15
|
+
**为什么不查 CRLF**:行尾已由 `.gitattributes` 的 `text eol=lf` 兜住 —— 实测带
|
|
16
|
+
CRLF 的文件 add 进暂存区时 git 就归一成了 LF,并打印 `CRLF will be replaced by
|
|
17
|
+
LF`。钩子重复那一层只是徒增啰嗦,故不管。
|
|
18
|
+
|
|
19
|
+
**如何取新增行**:`git diff --cached -U0 -- <文件>`,取以 `+` 开头且非 `+++`
|
|
20
|
+
文件头的那些行。附带的好处是:二进制文件 git 只输出 `Binary files ... differ`
|
|
21
|
+
而不产生 `+` 行,故无需另行判断是否二进制。
|
|
22
|
+
|
|
23
|
+
**例外**:`.bat` / `.cmd` 整体豁免 —— 它们是 Windows 批处理,形态自成一格。
|
|
24
|
+
|
|
25
|
+
用法:
|
|
26
|
+
python text_check.py
|
|
27
|
+
返回 0 通过;非 0 拒绝(信息输出到 stderr)。
|
|
28
|
+
"""
|
|
29
|
+
import subprocess
|
|
30
|
+
import sys
|
|
31
|
+
|
|
32
|
+
BOM = b"\xef\xbb\xbf"
|
|
33
|
+
|
|
34
|
+
# Windows 批处理整体豁免, 见 AGENTS.md 的文件编码与行尾约定
|
|
35
|
+
EXEMPT_SUFFIXES = (".bat", ".cmd")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _git(args, binary=False):
|
|
39
|
+
"""执行 git 子命令。失败即抛, 让钩子明确报错而不是静默放过。"""
|
|
40
|
+
proc = subprocess.run(
|
|
41
|
+
["git"] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
42
|
+
)
|
|
43
|
+
if proc.returncode != 0:
|
|
44
|
+
raise RuntimeError(
|
|
45
|
+
"git %s 失败: %s" % (" ".join(args), proc.stderr.decode("utf-8", "replace"))
|
|
46
|
+
)
|
|
47
|
+
return proc.stdout if binary else proc.stdout.decode("utf-8", "replace")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def staged_files():
|
|
51
|
+
"""本次待提交(新增/复制/修改)的文件列表; -z 分隔, 文件名带空格也拆不开。"""
|
|
52
|
+
out = _git(["diff", "--cached", "--name-only", "-z", "--diff-filter=ACM"])
|
|
53
|
+
return [f for f in out.split("\0") if f]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def added_lines(path):
|
|
57
|
+
"""本次提交在该文件里新增的行(字节), 去掉 diff 的 `+` 号与 `+++` 文件头。"""
|
|
58
|
+
raw = _git(["diff", "--cached", "-U0", "--", path], binary=True)
|
|
59
|
+
return [
|
|
60
|
+
line[1:]
|
|
61
|
+
for line in raw.split(b"\n")
|
|
62
|
+
if line.startswith(b"+") and not line.startswith(b"+++")
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def scan(path):
|
|
67
|
+
"""本次新增行里的 BOM 数。"""
|
|
68
|
+
return sum(line.count(BOM) for line in added_lines(path))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def main():
|
|
72
|
+
offenders = []
|
|
73
|
+
for path in staged_files():
|
|
74
|
+
if path.lower().endswith(EXEMPT_SUFFIXES):
|
|
75
|
+
continue
|
|
76
|
+
bom = scan(path)
|
|
77
|
+
if bom:
|
|
78
|
+
offenders.append((path, bom))
|
|
79
|
+
|
|
80
|
+
if not offenders:
|
|
81
|
+
return 0
|
|
82
|
+
|
|
83
|
+
sys.stderr.write("pre-commit 校验未通过:下列文件**本次新增的行**混进了 BOM\n\n")
|
|
84
|
+
for path, bom in offenders:
|
|
85
|
+
sys.stderr.write(" %s BOM=%d\n" % (path, bom))
|
|
86
|
+
sys.stderr.write(
|
|
87
|
+
"\nU+FEFF 多半是某次编辑把自带 BOM 的一段文本拼接进来的 —— 它肉眼看不见,\n"
|
|
88
|
+
"所见只是 `- ` 与正文之间多了个位置。修法见 AGENTS.md 的「文件编码与行尾约定」。\n"
|
|
89
|
+
)
|
|
90
|
+
return 1
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == "__main__":
|
|
94
|
+
sys.exit(main())
|
|
@@ -20,6 +20,9 @@ dist/
|
|
|
20
20
|
*.egg-info/
|
|
21
21
|
|
|
22
22
|
*.png
|
|
23
|
+
# 应用与网站图标是交付物, 需入库 (由 scripts/gen_icons.py 从 logo.png 生成)
|
|
24
|
+
!assets/icons/**/*.png
|
|
25
|
+
|
|
23
26
|
*.pkl
|
|
24
27
|
|
|
25
28
|
#visual studio
|
|
@@ -42,7 +45,10 @@ target/
|
|
|
42
45
|
.env
|
|
43
46
|
|
|
44
47
|
# vscode
|
|
45
|
-
.vscode/
|
|
48
|
+
.vscode/
|
|
46
49
|
|
|
47
50
|
# setuptools_scm generated version file
|
|
48
51
|
_version.py
|
|
52
|
+
|
|
53
|
+
# Maven Wrapper 下载缓存(首次运行自动下载,不入库)
|
|
54
|
+
.mvn/
|
|
@@ -1,13 +1,58 @@
|
|
|
1
1
|
{
|
|
2
|
+
// ===== 编辑器与字体 (VS Code 内置) =====
|
|
3
|
+
"editor.fontFamily": "'Source Code Pro', 'Courier New', monospace",
|
|
4
|
+
"editor.fontVariations": false,
|
|
5
|
+
"editor.inlayHints.fontFamily": "",
|
|
6
|
+
"editor.inlineSuggest.fontFamily": "'Source Code Pro', 'Courier New', monospace",
|
|
7
|
+
"debug.console.fontFamily": "'Source Code Pro', 'Courier New', monospace",
|
|
8
|
+
"chat.editor.fontFamily": "default",
|
|
9
|
+
"chat.fontFamily": "default",
|
|
10
|
+
|
|
11
|
+
// ===== 终端 (VS Code 内置) =====
|
|
12
|
+
"terminal.integrated.fontFamily": "'FiraCode Nerd Font Mono', 'Courier New', monospace",
|
|
13
|
+
"terminal.integrated.scrollback": 10000,
|
|
14
|
+
|
|
15
|
+
// ===== Python =====
|
|
16
|
+
"python.analysis.autoImportCompletions": true,
|
|
17
|
+
"python.envFile": "${workspaceFolder}/.env",
|
|
18
|
+
|
|
19
|
+
// ===== Go =====
|
|
20
|
+
"go.diagnostic.vulncheck": "Imports",
|
|
21
|
+
|
|
22
|
+
// ===== CMake =====
|
|
23
|
+
"cmake.launchBehavior": "reuseTerminal",
|
|
24
|
+
"cmake.buildDirectory": "${workspaceFolder}/build",
|
|
25
|
+
"cmake.configureSettings": {
|
|
26
|
+
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
|
|
27
|
+
"CMAKE_BUILD_TYPE": "Debug"
|
|
28
|
+
},
|
|
29
|
+
// "cmake.configureArgs": [
|
|
30
|
+
// "-DVCPKG_PREFER_SYSTEM_LIBS=OFF",
|
|
31
|
+
// "-DVCPKG_MANIFEST_MODE=OFF"
|
|
32
|
+
// ],
|
|
33
|
+
"cmake.buildArgs": [
|
|
34
|
+
"--config",
|
|
35
|
+
"Debug"
|
|
36
|
+
],
|
|
37
|
+
|
|
38
|
+
// ===== vcpkg =====
|
|
39
|
+
// triplet 与工具链路径随平台, 见 .vscode-windows / .vscode-macos
|
|
40
|
+
//"vcpkg.general.enable": true,
|
|
41
|
+
//"vcpkg.target.useStaticLib": false,
|
|
42
|
+
//"vcpkg.target.installDependencies": true,
|
|
43
|
+
//"vcpkg.target.preferSystemLibs": false,
|
|
44
|
+
//"vcpkg.target.useManifest": false,
|
|
45
|
+
|
|
46
|
+
// ===== C++ 测试 (C++ TestMate) =====
|
|
2
47
|
"testMate.cpp.test.advancedExecutables": [
|
|
3
48
|
{
|
|
4
|
-
// macOS / Linux:
|
|
49
|
+
// macOS / Linux: 可执行文件通常无扩展名
|
|
5
50
|
"pattern": "build/tests/catch2-*",
|
|
6
51
|
"cwd": "${workspaceFolder}",
|
|
7
52
|
"env": {}
|
|
8
53
|
},
|
|
9
54
|
{
|
|
10
|
-
// Windows:
|
|
55
|
+
// Windows: 保留 .exe 模式
|
|
11
56
|
"pattern": "build/tests/catch2-*.exe",
|
|
12
57
|
"cwd": "${workspaceFolder}",
|
|
13
58
|
"env": {}
|
|
@@ -25,7 +70,7 @@
|
|
|
25
70
|
"ASAN_OPTIONS": "detect_leaks=1",
|
|
26
71
|
"LSAN_OPTIONS": "suppressions=leaksanitizer.supp",
|
|
27
72
|
"DYLD_LIBRARY_PATH": "${command:cmake.buildDirectory}/lib"
|
|
28
|
-
}
|
|
73
|
+
}
|
|
29
74
|
},
|
|
30
75
|
"win32": {
|
|
31
76
|
"type": "cppdbg"
|
|
@@ -34,33 +79,13 @@
|
|
|
34
79
|
"program": "${exec}",
|
|
35
80
|
"args": "${argsArray}",
|
|
36
81
|
"cwd": "${command:cmake.launchTargetDirectory}",
|
|
37
|
-
"sourceFileMap": "${sourceFileMapObj}"
|
|
82
|
+
"sourceFileMap": "${sourceFileMapObj}"
|
|
38
83
|
},
|
|
39
84
|
"testMate.cpp.debug.noThrow": false,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"cmake.buildDirectory": "${workspaceFolder}/build",
|
|
43
|
-
"cmake.configureSettings": {
|
|
44
|
-
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
|
|
45
|
-
"CMAKE_BUILD_TYPE": "Debug"
|
|
46
|
-
},
|
|
47
|
-
"cmake.buildArgs": [
|
|
48
|
-
"--config",
|
|
49
|
-
"Debug"
|
|
50
|
-
],
|
|
51
|
-
"cmake.launchBehavior": "reuseTerminal",
|
|
52
|
-
"terminal.integrated.fontFamily": "'FiraCode Nerd Font Mono', 'Courier New', monospace",
|
|
53
|
-
"debug.console.fontFamily": "'Source Code Pro', 'Courier New', monospace",
|
|
54
|
-
"editor.inlayHints.fontFamily": "",
|
|
55
|
-
"editor.fontVariations": false,
|
|
56
|
-
"editor.fontFamily": "'Source Code Pro', 'Courier New', monospace",
|
|
57
|
-
"editor.inlineSuggest.fontFamily": "'Source Code Pro', 'Courier New', monospace",
|
|
58
|
-
"chat.editor.fontFamily": "default",
|
|
59
|
-
"chat.fontFamily": "default",
|
|
60
|
-
"terminal.integrated.scrollback": 10000,
|
|
61
|
-
"go.diagnostic.vulncheck": "Imports",
|
|
85
|
+
|
|
86
|
+
// ===== 代码运行 (Code Runner) =====
|
|
62
87
|
"code-runner.executorMap": {
|
|
63
|
-
|
|
88
|
+
"python": "python scripts/run_module.py $fullFileName"
|
|
64
89
|
},
|
|
65
|
-
"code-runner.runInTerminal": true
|
|
66
|
-
}
|
|
90
|
+
"code-runner.runInTerminal": true
|
|
91
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
// ===== Python =====
|
|
3
|
+
"python-envs.defaultEnvManager": "ms-python.python:pyenv",
|
|
4
|
+
|
|
5
|
+
// ===== CMake =====
|
|
6
|
+
// CMakeLists.txt 在 DEFINED ENV{VCPKG_ROOT} 缺失时 FATAL_ERROR, 故显式给出根目录,
|
|
7
|
+
// 不依赖外部终端环境。
|
|
8
|
+
// "cmake.configureEnvironment": {
|
|
9
|
+
// "VCPKG_ROOT": "/Users/wangfeng/runtime/vcpkg"
|
|
10
|
+
// }
|
|
11
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
// ===== vcpkg =====
|
|
3
|
+
// CMakeLists.txt 在 DEFINED ENV{VCPKG_ROOT} 缺失时 FATAL_ERROR, 故显式给出根目录,
|
|
4
|
+
// 不依赖外部终端环境; 工具链文件由同一根目录推导。
|
|
5
|
+
//"vcpkg.general.vcpkgPath": "d:\\runtime\\vcpkg",
|
|
6
|
+
// "vcpkg.target.hostTriplet": "x64-mingw-static",
|
|
7
|
+
// "vcpkg.target.defaultTriplet": "x64-mingw-static",
|
|
8
|
+
|
|
9
|
+
// ===== CMake =====
|
|
10
|
+
// "cmake.configureEnvironment": {
|
|
11
|
+
// "VCPKG_ROOT": "d:\\runtime\\vcpkg"
|
|
12
|
+
// },
|
|
13
|
+
// "cmake.configureSettings": {
|
|
14
|
+
// "CMAKE_TOOLCHAIN_FILE": "d:\\runtime\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake"
|
|
15
|
+
// }
|
|
16
|
+
|
|
17
|
+
// triplet 由 CMakeLists.txt 按编译器判定并以 FORCE 写入缓存, 此处不再重复指定:
|
|
18
|
+
// MinGW/GNU -> x64-mingw-static, MSVC/Clang -> x64-windows-static
|
|
19
|
+
}
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
- Go 实现必须位于功能子目录中,例如 `data/t1/`
|
|
18
18
|
- Go 包名必须与目录名完全一致(如 `package t1`)
|
|
19
19
|
- **禁止**为了"方便"合并 Go 文件到根目录
|
|
20
|
+
- Java 测试文件的 `package` 必须与 `tests/` 作为源码根目录时的目录层级一致;不应额外增加 `quant1x` 顶层包,但也不能省略 `tests` 根层级,例如 `tests/distributed/id` 对应 `package tests.distributed.id`
|
|
21
|
+
- 若 IDE/编译器提示 `The declared package "distributed.id" does not match the expected package "tests.distributed.id"`,这是错误配置;必须修正为 `tests` 目录根层级与 package 一致,并禁止在 Java 测试里人为多加 `quant1x.` 这一层
|
|
22
|
+
- 任何新增 Java 类/测试都必须遵循“模块目录 == package 层级(相对 tests 根目录)”的规则,避免出现 `quant1x.distributed.id`、`distributed.id` 这种与 `tests/` 根层级不一致的命名
|
|
20
23
|
|
|
21
24
|
## 三、命名规则
|
|
22
25
|
|
|
@@ -188,6 +191,71 @@ type Bar struct {
|
|
|
188
191
|
- ❌ 在代码或提交信息中自行推断版本号
|
|
189
192
|
- ❌ 修改 `CHANGELOG.md`、`pyproject.toml`、`Cargo.toml` 中的 `version` 字段
|
|
190
193
|
|
|
194
|
+
## 提交信息规范
|
|
195
|
+
|
|
196
|
+
- Git commit 的主题和正文必须使用中文,准确说明本次变更内容。
|
|
197
|
+
- 提交信息不得自行添加版本号、Git Tag 或发布相关信息。
|
|
198
|
+
- 所有代码变更(新特性、Bug 修复、重构、测试、文档、性能优化等)必须在提交主题中显式标注涉及的开发语言,确保多语言语义一致的审计性。
|
|
199
|
+
- 主题必须采用统一模板:`<type>[<language>]:<summary>`。
|
|
200
|
+
- `<type>` 取值建议:`feat`(新特性)、`fix`(修复)、`refactor`(重构)、`test`(测试)、`perf`(性能)、`docs`(文档)、`chore`(例行维护)。
|
|
201
|
+
- `<language>` 允许值:`python`、`cpp`、`rust`、`go`、`multi`。若涉及多个语言,使用 `python+cpp`、`python+rust+go` 等形式,优先按语义顺序书写:`python+cpp` > `python+cpp+rust+go`。
|
|
202
|
+
- 若是一处跨语言同步改动,正文必须补充:
|
|
203
|
+
1. 变更概述;
|
|
204
|
+
2. 涉及语言与文件范围;
|
|
205
|
+
3. 语义一致性说明;
|
|
206
|
+
4. 验证方式/测试命令。
|
|
207
|
+
- 主题中禁止仅写“update / optimize / fix”这类空泛描述,必须指明对象和语言,例如:
|
|
208
|
+
- `feat[python]:为 runtime ringbuffer 增加原生 Python 语义实现`
|
|
209
|
+
- `fix[cpp+rust]:修正 vyukov 退避策略与 arm64 调度兼容性`
|
|
210
|
+
- `test[python]:补充 ringbuffer 回归测试覆盖 close 与 wait_for_close`
|
|
211
|
+
- `docs[multi]:同步更新 ringbuffer 契约与跨语言语义说明`
|
|
212
|
+
- 若某次提交仅修改单一语言,主题中必须明确写出该语言;若跨语言同步提交,则必须写 `multi` 或多个语言组合;不得出现“无语言标记”的提交信息。
|
|
213
|
+
- 主题和正文都应优先使用中文,必要时保留英文术语(如 `RingBuffer`、`QueueFullError`、`try_push`)作为对象标识。
|
|
214
|
+
- 提交信息必须保持可审计、可分组、可检索,方便后续基于语言维度筛选 commit。
|
|
215
|
+
|
|
216
|
+
示例:
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
feat[python]:为 runtime ringbuffer 增加原生 Python 语义实现
|
|
220
|
+
|
|
221
|
+
- 新增 quant1x/runtime/ringbuffer.py,保留 try_push / try_pop / push / pop / close / wait_for_close 语义
|
|
222
|
+
- 目标为与 Go/C++/Rust 的 spec 契约保持一致,避免 Python 侧语义漂移
|
|
223
|
+
- 验证:PYTHONPATH=. python -m unittest quant1x.runtime.ringbuffer_test
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
```text
|
|
227
|
+
fix[cpp+rust]:修正 vyukov 退避策略,消除 arm64 争抢下的 convoy 效应
|
|
228
|
+
|
|
229
|
+
- 调整 backoff 退避策略,统一 C++ 与 Rust 的调度行为
|
|
230
|
+
- 重点修复 aarch64 上 yield/isb 差异导致的性能退化
|
|
231
|
+
- 说明:该修复仅影响调度策略,不改变 ringbuffer 语义契约
|
|
232
|
+
- 验证:cargo bench --bench vyukov_bench
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
```text
|
|
236
|
+
test[python+go]:补充 ringbuffer 语义回归测试,覆盖 close 与阻塞等待行为
|
|
237
|
+
|
|
238
|
+
- 以 Python 作为 spec 锚点,Go 侧对齐测试语义
|
|
239
|
+
- 验证:python -m unittest quant1x.runtime.ringbuffer_test
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### 提交前检查清单(Checklist)
|
|
243
|
+
|
|
244
|
+
在执行 `git commit` 之前,AI 必须逐项核对:
|
|
245
|
+
|
|
246
|
+
- [ ] 主题是否符合 `type[language]:summary` 模板?
|
|
247
|
+
- [ ] `type` 是否真实反映本次变更类型(feat / fix / refactor / test / perf / docs / chore)?
|
|
248
|
+
- [ ] `language` 是否准确标明本次涉及的开发语言,未标注或误标注均视为不合规?
|
|
249
|
+
- [ ] 若涉及多语言,是否使用 `python+cpp`、`python+rust+go` 等组合形式,而非笼统写 `multi`?
|
|
250
|
+
- [ ] 标题是否避免“update / optimize / fix”这类空泛描述,是否明确对象和影响?
|
|
251
|
+
- [ ] 正文是否包含:变更概述、涉及语言与文件范围、语义一致性说明、验证方式/命令?
|
|
252
|
+
- [ ] 若为跨语言同步改动,是否说明了语义一致性与测试验证方式?
|
|
253
|
+
- [ ] 是否未包含版本号、Git Tag、发布相关字符串?
|
|
254
|
+
- [ ] 是否使用中文为主,必要时保留英文术语作为对象标识?
|
|
255
|
+
- [ ] 是否能在审计时根据语言维度快速过滤和回溯?
|
|
256
|
+
|
|
257
|
+
提交未满足以上任一项,必须在提交前修正,不能直接提交。
|
|
258
|
+
|
|
191
259
|
## 十、一句话总结(给 AI 的记忆锚点)
|
|
192
260
|
|
|
193
261
|
> Quant1X 是多语言语义同构系统,Python 是 Spec,C++ 是 Truth,Rust / Go 是对齐实现,I/O 边界死守 `snake_case`。
|