修復市場情報 writer CLI lazy import
All checks were successful
CD Pipeline / deploy (push) Successful in 1m22s
All checks were successful
CD Pipeline / deploy (push) Successful in 1m22s
This commit is contained in:
@@ -19,11 +19,11 @@ if str(REPO_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(REPO_ROOT))
|
||||
|
||||
with contextlib.redirect_stdout(sys.stderr):
|
||||
from services.market_intel import MarketIntelService # noqa: E402
|
||||
from services.market_intel.candidate_queue_review_decision_writer_cli import ( # noqa: E402
|
||||
APPROVAL_ENV_VAR,
|
||||
build_candidate_queue_review_decision_writer_cli_plan,
|
||||
)
|
||||
from services.market_intel.phase import MARKET_INTEL_PHASE # noqa: E402
|
||||
|
||||
|
||||
def parse_args(argv=None):
|
||||
@@ -71,7 +71,6 @@ def _load_transaction_preview(path):
|
||||
|
||||
def main(argv=None):
|
||||
args = parse_args(argv)
|
||||
service = MarketIntelService()
|
||||
plan = build_candidate_queue_review_decision_writer_cli_plan(
|
||||
transaction_preview=_load_transaction_preview(args.transaction_json),
|
||||
execute_requested=args.execute,
|
||||
@@ -81,7 +80,7 @@ def main(argv=None):
|
||||
backup_verified=args.backup_verified,
|
||||
review_inventory_smoke_passed=args.review_inventory_smoke_passed,
|
||||
)
|
||||
plan["phase"] = service.phase
|
||||
plan["phase"] = MARKET_INTEL_PHASE
|
||||
print(json.dumps(plan, ensure_ascii=False, indent=2, sort_keys=True))
|
||||
return int(plan.get("exit_code", 2))
|
||||
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
"""跨平台市場情報服務模組。"""
|
||||
|
||||
from services.market_intel.service import MarketIntelService, MarketIntelRuntimeStatus
|
||||
|
||||
__all__ = ["MarketIntelService", "MarketIntelRuntimeStatus"]
|
||||
|
||||
|
||||
def __getattr__(name):
|
||||
if name in __all__:
|
||||
from services.market_intel.service import (
|
||||
MarketIntelRuntimeStatus,
|
||||
MarketIntelService,
|
||||
)
|
||||
|
||||
return {
|
||||
"MarketIntelService": MarketIntelService,
|
||||
"MarketIntelRuntimeStatus": MarketIntelRuntimeStatus,
|
||||
}[name]
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
|
||||
3
services/market_intel/phase.py
Normal file
3
services/market_intel/phase.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""市場情報 rollout phase 單一來源。"""
|
||||
|
||||
MARKET_INTEL_PHASE = "phase_69_candidate_queue_review_decision_writer_cli"
|
||||
@@ -66,6 +66,7 @@ from services.market_intel.opportunity_scoring import (
|
||||
)
|
||||
from services.market_intel.platform_seed import build_platform_seed_rows
|
||||
from services.market_intel.platform_seed_db_diff import build_platform_seed_db_diff_plan
|
||||
from services.market_intel.phase import MARKET_INTEL_PHASE
|
||||
from services.market_intel.scheduler_plan import build_scheduler_attach_plan
|
||||
from services.market_intel.platform_seed_writer import (
|
||||
build_platform_seed_writer_plan,
|
||||
@@ -108,7 +109,7 @@ class MarketIntelRuntimeStatus:
|
||||
class MarketIntelService:
|
||||
"""市場情報入口服務,先集中 feature gate 與安全狀態。"""
|
||||
|
||||
phase = "phase_69_candidate_queue_review_decision_writer_cli"
|
||||
phase = MARKET_INTEL_PHASE
|
||||
|
||||
def get_runtime_status(self) -> MarketIntelRuntimeStatus:
|
||||
return MarketIntelRuntimeStatus(
|
||||
|
||||
@@ -7698,3 +7698,36 @@ def test_candidate_queue_writer_cli_script_outputs_blocked_gate(tmp_path):
|
||||
assert data["scheduler_attached"] is False
|
||||
assert data["transaction_preview_summary"]["statement_count"] == 1
|
||||
assert "execute_requested" in data["blocked_reasons"]
|
||||
|
||||
|
||||
def test_review_decision_writer_cli_script_outputs_blocked_gate_without_login_env():
|
||||
env = {
|
||||
key: value
|
||||
for key, value in os.environ.items()
|
||||
if key not in {"LOGIN_PASSWORD", "SECRET_KEY"}
|
||||
}
|
||||
result = subprocess.run(
|
||||
[sys.executable, "scripts/market_intel_review_decision_writer.py"],
|
||||
capture_output=True,
|
||||
check=False,
|
||||
env=env,
|
||||
text=True,
|
||||
)
|
||||
data = json.loads(result.stdout)
|
||||
|
||||
assert result.returncode == 0
|
||||
assert data["mode"] == "candidate_queue_review_decision_writer_cli_blocked"
|
||||
assert data["phase"] == "phase_69_candidate_queue_review_decision_writer_cli"
|
||||
assert data["execute_requested"] is False
|
||||
assert data["apply_real_write_requested"] is False
|
||||
assert data["approval_token_present"] is False
|
||||
assert data["writer_implementation_enabled"] is False
|
||||
assert data["ready_for_real_write"] is False
|
||||
assert data["api_executes_cli"] is False
|
||||
assert data["api_reads_approval_token"] is False
|
||||
assert data["database_connection_opened"] is False
|
||||
assert data["database_write_executed"] is False
|
||||
assert data["database_commit_executed"] is False
|
||||
assert data["scheduler_attached"] is False
|
||||
assert data["writes_executed"] is False
|
||||
assert data["exit_code"] == 0
|
||||
|
||||
Reference in New Issue
Block a user