refactor: address high-priority debt and publish to PyPI

- Fix TOCTOU race conditions by wrapping read-modify-write cycles
  under single-file locks in execution_state, portfolio_service,
  precheck_state, state_manager, and precheck_service.
- Add missing test coverage (96 tests total):
  - test_review_service.py (15 tests)
  - test_check_api.py (6 tests)
  - test_external_gate.py main branches (+10 tests)
  - test_trade_execution.py new commands (+8 tests)
- Unify all agent-consumed JSON messages to English.
- Config-ize hardcoded values (volume filter, schema_version) via
  get_user_config with sensible defaults.
- Add 1-hour TTL to exchange cache with force_new override.
- Add ruff and mypy to dev dependencies; fix all type errors.
- Add __all__ declarations to 11 service modules.
- Sync README with new commands, config tuning docs, and PyPI badge.
- Publish package as coinhunter==1.0.0 on PyPI with MIT license.
- Deprecate coinhunter-cli==1.0.1 with runtime warning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-16 01:21:27 +08:00
parent 01bb54dee5
commit 62c40a9776
53 changed files with 2338 additions and 671 deletions

View File

@@ -13,13 +13,6 @@ from importlib import import_module
from .services.precheck_service import run as _run_service
_CORE_EXPORTS = {
"PATHS",
"BASE_DIR",
"STATE_DIR",
"STATE_FILE",
"POSITIONS_FILE",
"CONFIG_FILE",
"ENV_FILE",
"BASE_PRICE_MOVE_TRIGGER_PCT",
"BASE_PNL_TRIGGER_PCT",
"BASE_PORTFOLIO_MOVE_TRIGGER_PCT",
@@ -64,14 +57,28 @@ _CORE_EXPORTS = {
"analyze_trigger",
"update_state_after_observation",
}
# Path-related exports are now lazy in precheck_core
_PATH_EXPORTS = {
"PATHS",
"BASE_DIR",
"STATE_DIR",
"STATE_FILE",
"POSITIONS_FILE",
"CONFIG_FILE",
"ENV_FILE",
}
_STATE_EXPORTS = {"mark_run_requested", "ack_analysis"}
__all__ = sorted(_CORE_EXPORTS | _STATE_EXPORTS | {"main"})
__all__ = sorted(_CORE_EXPORTS | _PATH_EXPORTS | _STATE_EXPORTS | {"main"})
def __getattr__(name: str):
if name in _CORE_EXPORTS:
return getattr(import_module(".services.precheck_core", __package__), name)
if name in _PATH_EXPORTS:
return getattr(import_module(".services.precheck_core", __package__), name)
if name in _STATE_EXPORTS:
return getattr(import_module(".services.precheck_state", __package__), name)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")