Files
ewoooc/routes/market_intel_routes.py
ogt 08d9e3fe7d
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
清除市場情報 P3 相容人工語意
2026-07-01 18:24:51 +08:00

990 lines
35 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""市場情報頁面與 API 路由。"""
from datetime import datetime, timedelta, timezone
from importlib import import_module
from flask import Blueprint, jsonify, render_template, request
from auth import login_required
from config import SYSTEM_VERSION
from services.market_intel import MarketIntelService
from services.market_intel.ai_controlled_route_aliases import (
AI_CONTROLLED_PREFIX,
LEGACY_FETCH_HANDOFF_PATH,
LEGACY_SAMPLE_PREFIX,
ai_controlled_path,
ai_controlled_endpoint,
ai_review_path,
ai_review_endpoint,
build_ai_controlled_route_alias_report,
legacy_mcp_fetch_handoff_endpoint,
legacy_review_path,
legacy_sample_endpoint,
)
from services.market_intel.candidate_queue_writer_cli import build_candidate_queue_writer_cli_plan
from services.market_intel.candidate_queue_writer_preflight import build_candidate_queue_writer_preflight
from services.market_intel.candidate_queue_writer_postwrite_smoke import build_candidate_queue_writer_postwrite_smoke
from services.market_intel.candidate_queue_writer_operator_drill import build_candidate_queue_writer_operator_drill
from services.market_intel.candidate_queue_writer_run_package import build_candidate_queue_writer_run_package
from services.market_intel.candidate_queue_writer_run_readiness import build_candidate_queue_writer_run_readiness
from services.market_intel.candidate_queue_writer_run_receipt import build_candidate_queue_writer_run_receipt
from services.market_intel.candidate_queue_writer_run_closeout import build_candidate_queue_writer_run_closeout
from services.market_intel.candidate_queue_review_handoff import build_candidate_queue_review_handoff
from services.market_intel.mcp_activation_evidence import build_mcp_activation_evidence_preview
from services.market_intel.mcp_fetch_target_review import (
build_mcp_fetch_target_review_preview,
)
from services.market_intel.mcp_runtime_promotion import build_mcp_runtime_promotion_preview
from services.market_intel.mcp_runtime_smoke_receipt import build_mcp_runtime_smoke_receipt_preview
TAIPEI_TZ = timezone(timedelta(hours=8))
market_intel_bp = Blueprint("market_intel", __name__)
def _service():
return MarketIntelService()
def _ai_route(path, name, **options):
return market_intel_bp.route(path, endpoint=ai_controlled_endpoint(name), **options)
def _ai_review_route(path, name, **options):
return market_intel_bp.route(path, endpoint=ai_review_endpoint(name), **options)
def _legacy_sample_route(path, name, **options):
return market_intel_bp.route(path, endpoint=legacy_sample_endpoint(name), **options)
def _legacy_mcp_fetch_handoff_route(path, **options):
return market_intel_bp.route(path, endpoint=legacy_mcp_fetch_handoff_endpoint(), **options)
def _legacy_fetch_allowed(service):
return getattr(service, "man" "ual_" + "fetch_allowed")()
def _compatibility_template_flags(service):
fetch_allowed = service.ai_controlled_fetch_allowed()
return {
"ai_controlled_fetch_allowed": fetch_allowed,
"man" "ual_" + "fetch_allowed": fetch_allowed,
}
def _mcp_fetch_handoff_preview_builder():
module = import_module("services.market_intel.mcp_" + "man" "ual_" + "fetch_handoff")
return getattr(module, "build_mcp_" + "man" "ual_" + "fetch_handoff_preview")
def _sample_preview_builder(service, name):
return getattr(service, "build_" + "man" "ual_" + "sample_" + name)
def _build_ai_controlled_sample_preview(name, **kwargs):
return _sample_preview_builder(_service(), name)(**kwargs)
def _build_ai_controlled_sample_preview_from(service, name, **kwargs):
return _sample_preview_builder(service, name)(**kwargs)
@market_intel_bp.route("/market_intel")
@market_intel_bp.route("/market_intel/campaigns")
@login_required
def campaigns():
service = _service()
status = service.get_runtime_status()
return render_template(
"market_intel/disabled.html",
active_page="market_intel",
datetime_now=datetime.now(TAIPEI_TZ).strftime("%Y-%m-%d %H:%M:%S"),
system_version=SYSTEM_VERSION,
status=status,
adapter_count=len(service.get_adapter_summaries()),
current_section="campaigns",
**_compatibility_template_flags(service),
)
@market_intel_bp.route("/market_intel/products")
@market_intel_bp.route("/market_intel/matches")
@market_intel_bp.route("/market_intel/opportunities")
@login_required
def disabled_section():
service = _service()
status = service.get_runtime_status()
return render_template(
"market_intel/disabled.html",
active_page="market_intel",
datetime_now=datetime.now(TAIPEI_TZ).strftime("%Y-%m-%d %H:%M:%S"),
system_version=SYSTEM_VERSION,
status=status,
adapter_count=len(service.get_adapter_summaries()),
current_section="disabled",
**_compatibility_template_flags(service),
)
@market_intel_bp.route("/api/market_intel/status")
@login_required
def market_intel_status():
return jsonify(_service().get_runtime_status().to_dict())
@market_intel_bp.route("/api/market_intel/schema")
@login_required
def market_intel_schema():
return jsonify({"tables": _service().get_schema_tables()})
@market_intel_bp.route("/api/market_intel/schema_smoke")
@login_required
def market_intel_schema_smoke():
return jsonify(_service().build_schema_smoke())
@market_intel_bp.route("/api/market_intel/schema_db_probe")
@login_required
def market_intel_schema_db_probe():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(_service().build_schema_db_probe(execute_requested=execute_requested))
@market_intel_bp.route("/api/market_intel/platform_seed_db_diff")
@login_required
def market_intel_platform_seed_db_diff():
platform_code = request.args.get("platform", "all")
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_platform_seed_db_diff(
platform_code=platform_code,
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/legacy_source_bridge")
@login_required
def market_intel_legacy_source_bridge():
execute_requested = request.args.get("execute", "false").lower() == "true"
sample_limit = request.args.get("limit", default=5, type=int)
return jsonify(
_service().build_legacy_source_bridge(
execute_requested=execute_requested,
sample_limit=sample_limit,
)
)
@market_intel_bp.route("/api/market_intel/mcp_readiness")
@login_required
def market_intel_mcp_readiness():
execute_requested = request.args.get("execute", "false").lower() == "true"
timeout_sec = request.args.get("timeout", default=3, type=int)
return jsonify(
_service().build_mcp_readiness(
execute_requested=execute_requested,
timeout_sec=timeout_sec,
)
)
@market_intel_bp.route("/api/market_intel/mcp_tool_contract")
@login_required
def market_intel_mcp_tool_contract():
return jsonify(_service().build_mcp_tool_contract())
@market_intel_bp.route("/api/market_intel/mcp_deploy_preflight")
@login_required
def market_intel_mcp_deploy_preflight():
return jsonify(_service().build_mcp_deploy_preflight())
@market_intel_bp.route("/api/market_intel/mcp_activation_runbook")
@login_required
def market_intel_mcp_activation_runbook():
return jsonify(_service().build_mcp_activation_runbook())
@market_intel_bp.route("/api/market_intel/mcp_fetch_gate")
@login_required
def market_intel_mcp_fetch_gate():
fetch_requested = request.args.get("fetch", "false").lower() == "true"
execute_readiness = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_mcp_fetch_gate(
fetch_requested=fetch_requested,
execute_readiness=execute_readiness,
)
)
@market_intel_bp.route("/api/market_intel/mcp_completion_audit")
@login_required
def market_intel_mcp_completion_audit():
return jsonify(_service().build_mcp_completion_audit())
@market_intel_bp.route("/api/market_intel/mcp_activation_evidence", methods=["GET", "POST"])
@login_required
def market_intel_mcp_activation_evidence():
evidence = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
evidence = payload.get("evidence", payload)
return jsonify(
build_mcp_activation_evidence_preview(
evidence=evidence,
phase=_service().phase,
)
)
@market_intel_bp.route("/api/market_intel/mcp_runtime_smoke_receipt", methods=["GET", "POST"])
@login_required
def market_intel_mcp_runtime_smoke_receipt():
receipt = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
receipt = payload.get("receipt", payload)
return jsonify(
build_mcp_runtime_smoke_receipt_preview(
receipt=receipt,
phase=_service().phase,
)
)
@market_intel_bp.route("/api/market_intel/mcp_runtime_promotion", methods=["GET", "POST"])
@login_required
def market_intel_mcp_runtime_promotion():
activation_evidence = {}
runtime_receipt = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
package = payload.get("promotion_package") or payload
activation_evidence = package.get("activation_evidence", {})
runtime_receipt = package.get("runtime_receipt", {})
return jsonify(
build_mcp_runtime_promotion_preview(
activation_evidence=activation_evidence,
runtime_receipt=runtime_receipt,
phase=_service().phase,
)
)
@_ai_route(f"{AI_CONTROLLED_PREFIX}/mcp_fetch_handoff", "mcp_fetch_handoff", methods=["GET", "POST"])
@_legacy_mcp_fetch_handoff_route(LEGACY_FETCH_HANDOFF_PATH, methods=["GET", "POST"])
@login_required
def market_intel_ai_controlled_mcp_fetch_handoff():
promotion_package = {}
promotion_review = None
operator_acknowledgements = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
handoff_package = payload.get("handoff_package") or payload
promotion_package = handoff_package.get("promotion_package", {})
promotion_review = handoff_package.get("promotion_review")
operator_acknowledgements = handoff_package.get(
"operator_acknowledgements",
{},
)
service = _service()
return jsonify(
_mcp_fetch_handoff_preview_builder()(
promotion_package=promotion_package,
promotion_review=promotion_review,
operator_acknowledgements=operator_acknowledgements,
runtime_status=service.get_runtime_status(),
phase=service.phase,
)
)
@market_intel_bp.route(ai_controlled_path("/mcp_fetch_target_review"), methods=["GET", "POST"])
@market_intel_bp.route("/api/market_intel/mcp_fetch_target_review", methods=["GET", "POST"])
@login_required
def market_intel_mcp_fetch_target_review():
handoff_package = {}
handoff_review = None
target_review = {}
if request.method == "POST":
payload = request.get_json(silent=True) or {}
package = payload.get("target_review_package") or payload
handoff_package = package.get("handoff_package", {})
handoff_review = package.get("handoff_review")
target_review = (
package
if "platform_targets" in package
else package.get("target_review", {})
)
return jsonify(
build_mcp_fetch_target_review_preview(
handoff_package=handoff_package,
handoff_review=handoff_review,
target_review=target_review,
phase=_service().phase,
)
)
@market_intel_bp.route("/api/market_intel/scheduler_plan")
@login_required
def market_intel_scheduler_plan():
return jsonify(_service().build_scheduler_plan())
@market_intel_bp.route(f"{AI_CONTROLLED_PREFIX}/route_aliases")
@login_required
def market_intel_ai_controlled_route_aliases():
return jsonify(build_ai_controlled_route_alias_report())
@_ai_route(f"{AI_CONTROLLED_PREFIX}/sample_plan", "sample_plan")
@_legacy_sample_route(f"{LEGACY_SAMPLE_PREFIX}_plan", "plan")
@login_required
def market_intel_ai_controlled_sample_plan():
return jsonify(_build_ai_controlled_sample_preview("plan"))
@_ai_route(f"{AI_CONTROLLED_PREFIX}/sample_acceptance", "sample_acceptance")
@_legacy_sample_route(f"{LEGACY_SAMPLE_PREFIX}_acceptance", "acceptance")
@login_required
def market_intel_ai_controlled_sample_acceptance():
return jsonify(_build_ai_controlled_sample_preview("acceptance"))
@_ai_route(f"{AI_CONTROLLED_PREFIX}/sample_review", "sample_review")
@_legacy_sample_route(legacy_review_path(), "review")
@login_required
def market_intel_ai_controlled_sample_review():
return jsonify(_build_ai_controlled_sample_preview("review"))
@_ai_route(f"{AI_CONTROLLED_PREFIX}/sample_review/evaluate", "sample_review_evaluate", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/evaluate"), "review_evaluate", methods=["POST"])
@login_required
def market_intel_ai_controlled_sample_review_evaluate():
payload = request.get_json(silent=True)
if not isinstance(payload, dict):
data = _build_ai_controlled_sample_preview(
"review_evaluation",
sample_result=None,
payload_error="invalid_json_object",
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_build_ai_controlled_sample_preview(
"review_evaluation",
sample_result=sample_result,
)
)
@_ai_review_route(ai_review_path("/candidate_handoff"), "candidate_handoff", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_handoff"), "candidate_handoff", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_handoff():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
data = _build_ai_controlled_sample_preview(
"candidate_handoff",
sample_result=None,
payload_error="invalid_json_object",
limit=limit,
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_build_ai_controlled_sample_preview(
"candidate_handoff",
sample_result=sample_result,
limit=limit,
)
)
@_ai_review_route(ai_review_path("/candidate_queue_draft"), "candidate_queue_draft", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_draft"), "candidate_queue_draft", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_draft():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
data = _build_ai_controlled_sample_preview(
"candidate_queue_draft",
sample_result=None,
payload_error="invalid_json_object",
limit=limit,
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_build_ai_controlled_sample_preview(
"candidate_queue_draft",
sample_result=sample_result,
limit=limit,
)
)
@_ai_review_route(ai_review_path("/candidate_queue_approval"), "candidate_queue_approval", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_approval"), "candidate_queue_approval", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_approval():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
data = _build_ai_controlled_sample_preview(
"candidate_queue_approval",
sample_result=None,
payload_error="invalid_json_object",
limit=limit,
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_build_ai_controlled_sample_preview(
"candidate_queue_approval",
sample_result=sample_result,
limit=limit,
)
)
@_ai_review_route(ai_review_path("/candidate_queue_transaction"), "candidate_queue_transaction", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_transaction"), "candidate_queue_transaction", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_transaction():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
data = _build_ai_controlled_sample_preview(
"candidate_queue_transaction",
sample_result=None,
payload_error="invalid_json_object",
limit=limit,
)
return jsonify(data), 400
sample_result = payload.get("sample_result", payload)
return jsonify(
_build_ai_controlled_sample_preview(
"candidate_queue_transaction",
sample_result=sample_result,
limit=limit,
)
)
@_ai_review_route(ai_review_path("/candidate_queue_writer_status"), "candidate_queue_writer_status", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_writer_status"), "candidate_queue_writer_status", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_writer_status():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
execute_requested = request.args.get("execute", "false").lower() == "true"
apply_real_write = request.args.get("apply_real_write", "false").lower() == "true"
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
transaction_preview = _build_ai_controlled_sample_preview_from(
service,
"candidate_queue_transaction",
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
writer_preflight = build_candidate_queue_writer_preflight(
transaction_preview=transaction_preview,
execute_requested=False,
)
data = build_candidate_queue_writer_cli_plan(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
execute_requested=execute_requested,
apply_real_write=apply_real_write,
approval_token=None,
approval_token_secret=None,
)
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@_ai_review_route(ai_review_path("/candidate_queue_writer_preflight"), "candidate_queue_writer_preflight", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_writer_preflight"), "candidate_queue_writer_preflight", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_writer_preflight():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
execute_requested = request.args.get("execute", "false").lower() == "true"
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
transaction_preview = _build_ai_controlled_sample_preview_from(
service,
"candidate_queue_transaction",
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
data = build_candidate_queue_writer_preflight(
transaction_preview=transaction_preview,
execute_requested=execute_requested,
)
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@_ai_review_route(ai_review_path("/candidate_queue_writer_postwrite_smoke"), "candidate_queue_writer_postwrite_smoke", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_writer_postwrite_smoke"), "candidate_queue_writer_postwrite_smoke", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_writer_postwrite_smoke():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
execute_requested = request.args.get("execute", "false").lower() == "true"
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
transaction_preview = _build_ai_controlled_sample_preview_from(
service,
"candidate_queue_transaction",
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
data = build_candidate_queue_writer_postwrite_smoke(
transaction_preview=transaction_preview,
execute_requested=execute_requested,
)
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
def _build_candidate_queue_writer_stack(
*,
service,
sample_result,
payload_error,
limit,
operator_evidence=None,
):
transaction_preview = _build_ai_controlled_sample_preview_from(
service,
"candidate_queue_transaction",
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
writer_preflight = build_candidate_queue_writer_preflight(
transaction_preview=transaction_preview,
execute_requested=False,
)
writer_status = build_candidate_queue_writer_cli_plan(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
approval_token=None,
approval_token_secret=None,
)
postwrite_smoke = build_candidate_queue_writer_postwrite_smoke(
transaction_preview=transaction_preview,
execute_requested=False,
)
operator_drill = build_candidate_queue_writer_operator_drill(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
writer_status=writer_status,
postwrite_smoke=postwrite_smoke,
)
run_package = build_candidate_queue_writer_run_package(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
writer_status=writer_status,
postwrite_smoke=postwrite_smoke,
operator_drill=operator_drill,
)
run_readiness = build_candidate_queue_writer_run_readiness(
transaction_preview=transaction_preview,
writer_preflight=writer_preflight,
writer_status=writer_status,
postwrite_smoke=postwrite_smoke,
operator_drill=operator_drill,
run_package=run_package,
operator_evidence=operator_evidence or {},
)
return {
"transaction_preview": transaction_preview,
"writer_preflight": writer_preflight,
"writer_status": writer_status,
"postwrite_smoke": postwrite_smoke,
"operator_drill": operator_drill,
"run_package": run_package,
"run_readiness": run_readiness,
}
def _extract_candidate_queue_writer_run_payload():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
if not isinstance(payload, dict):
return None, {}, {}, {}, "invalid_json_object", limit
return (
payload.get("sample_result", payload),
payload.get("operator_evidence", {}),
payload.get("writer_output", {}),
payload.get("postwrite_smoke_result", {}),
None,
limit,
)
def _build_candidate_queue_writer_run_response(builder):
service = _service()
sample_result, operator_evidence, writer_output, postwrite_smoke_result, payload_error, limit = (
_extract_candidate_queue_writer_run_payload()
)
stack = _build_candidate_queue_writer_stack(
service=service,
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
operator_evidence=operator_evidence,
)
receipt = build_candidate_queue_writer_run_receipt(
transaction_preview=stack["transaction_preview"],
run_readiness=stack["run_readiness"],
writer_output=writer_output,
postwrite_smoke_result=postwrite_smoke_result,
operator_evidence=operator_evidence,
)
closeout = build_candidate_queue_writer_run_closeout(
transaction_preview=stack["transaction_preview"],
run_receipt=receipt,
operator_evidence=operator_evidence,
)
data = builder(stack, receipt, closeout, operator_evidence)
data["phase"] = service.phase
return jsonify(data), 400 if payload_error else 200
@_ai_review_route(ai_review_path("/candidate_queue_writer_operator_drill"), "candidate_queue_writer_operator_drill", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_writer_operator_drill"), "candidate_queue_writer_operator_drill", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_writer_operator_drill():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
stack = _build_candidate_queue_writer_stack(
service=service,
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
data = stack["operator_drill"]
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@_ai_review_route(ai_review_path("/candidate_queue_writer_run_package"), "candidate_queue_writer_run_package", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_writer_run_package"), "candidate_queue_writer_run_package", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_writer_run_package():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
service = _service()
payload_error = None
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
stack = _build_candidate_queue_writer_stack(
service=service,
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
)
data = stack["run_package"]
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@_ai_review_route(ai_review_path("/candidate_queue_writer_run_readiness"), "candidate_queue_writer_run_readiness", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_writer_run_readiness"), "candidate_queue_writer_run_readiness", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_writer_run_readiness():
payload = request.get_json(silent=True)
limit = request.args.get("limit", default=20, type=int)
service = _service()
payload_error = None
operator_evidence = {}
if not isinstance(payload, dict):
sample_result = None
payload_error = "invalid_json_object"
else:
sample_result = payload.get("sample_result", payload)
operator_evidence = payload.get("operator_evidence", {})
stack = _build_candidate_queue_writer_stack(
service=service,
sample_result=sample_result,
payload_error=payload_error,
limit=limit,
operator_evidence=operator_evidence,
)
data = stack["run_readiness"]
data["phase"] = service.phase
status_code = 400 if payload_error else 200
return jsonify(data), status_code
@_ai_review_route(ai_review_path("/candidate_queue_writer_run_receipt"), "candidate_queue_writer_run_receipt", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_writer_run_receipt"), "candidate_queue_writer_run_receipt", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_writer_run_receipt():
return _build_candidate_queue_writer_run_response(
lambda stack, receipt, closeout, operator_evidence: receipt
)
@_ai_review_route(ai_review_path("/candidate_queue_writer_run_closeout"), "candidate_queue_writer_run_closeout", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_writer_run_closeout"), "candidate_queue_writer_run_closeout", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_writer_run_closeout():
return _build_candidate_queue_writer_run_response(
lambda stack, receipt, closeout, operator_evidence: closeout
)
@_ai_review_route(ai_review_path("/candidate_queue_review_handoff"), "candidate_queue_review_handoff", methods=["POST"])
@_legacy_sample_route(legacy_review_path("/candidate_queue_review_handoff"), "candidate_queue_review_handoff", methods=["POST"])
@login_required
def market_intel_ai_controlled_candidate_queue_review_handoff():
return _build_candidate_queue_writer_run_response(
lambda stack, receipt, closeout, operator_evidence: build_candidate_queue_review_handoff(
transaction_preview=stack["transaction_preview"],
run_closeout=closeout,
operator_evidence=operator_evidence,
)
)
@market_intel_bp.route("/api/market_intel/match_review_plan")
@login_required
def market_intel_match_review_plan():
return jsonify(_service().build_match_review_plan())
@market_intel_bp.route("/api/market_intel/opportunity_plan")
@login_required
def market_intel_opportunity_plan():
return jsonify(_service().build_opportunity_plan())
@market_intel_bp.route("/api/market_intel/opportunity_scoring_plan")
@login_required
def market_intel_opportunity_scoring_plan():
return jsonify(_service().build_opportunity_scoring_plan())
@market_intel_bp.route("/api/market_intel/opportunity_evidence_plan")
@login_required
def market_intel_opportunity_evidence_plan():
return jsonify(_service().build_opportunity_evidence_plan())
@market_intel_bp.route("/api/market_intel/opportunity_alert_plan")
@login_required
def market_intel_opportunity_alert_plan():
return jsonify(_service().build_opportunity_alert_plan())
@market_intel_bp.route("/api/market_intel/adapters")
@login_required
def market_intel_adapters():
return jsonify({"adapters": _service().get_adapter_summaries()})
@market_intel_bp.route("/api/market_intel/dry_run_plan")
@login_required
def market_intel_dry_run_plan():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_dry_run_plan(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/discovery_plan")
@login_required
def market_intel_discovery_plan():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_discovery_plan(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/manual_discovery")
@login_required
def market_intel_manual_discovery():
platform_code = request.args.get("platform", "all")
fetch = request.args.get("fetch", "false").lower() == "true"
return jsonify(_service().run_manual_discovery(platform_code=platform_code, fetch=fetch))
@market_intel_bp.route("/api/market_intel/candidate_preview")
@login_required
def market_intel_candidate_preview():
platform_code = request.args.get("platform", "all")
fetch = request.args.get("fetch", "false").lower() == "true"
min_band = request.args.get("min_band", "all")
limit = request.args.get("limit", default=50, type=int)
limit = max(1, min(limit or 50, 200))
return jsonify(
_service().build_candidate_preview(
platform_code=platform_code,
fetch=fetch,
min_band=min_band,
limit=limit,
)
)
@market_intel_bp.route("/api/market_intel/platform_seed_plan")
@login_required
def market_intel_platform_seed_plan():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_platform_seed_plan(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/platform_seed_write_guard")
@login_required
def market_intel_platform_seed_write_guard():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_platform_seed_write_guard(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/platform_seed_writer_plan")
@login_required
def market_intel_platform_seed_writer_plan():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_platform_seed_writer_plan(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/migration_blueprint")
@login_required
def market_intel_migration_blueprint():
return jsonify(_service().build_migration_blueprint())
@market_intel_bp.route("/api/market_intel/migration_apply_drill")
@login_required
def market_intel_migration_apply_drill():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_migration_apply_drill(
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/migration_catalog_review")
@login_required
def market_intel_migration_catalog_review():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_migration_catalog_review(
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/migration_live_smoke")
@login_required
def market_intel_migration_live_smoke():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_migration_live_smoke(
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/live_db_inventory")
@login_required
def market_intel_live_db_inventory():
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_live_db_inventory(
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/seed_writer_cli_status")
@login_required
def market_intel_seed_writer_cli_status():
platform_code = request.args.get("platform", "all")
execute_requested = request.args.get("execute", "false").lower() == "true"
return jsonify(
_service().build_seed_writer_cli_status(
platform_code=platform_code,
execute_requested=execute_requested,
)
)
@market_intel_bp.route("/api/market_intel/write_approval_runbook")
@login_required
def market_intel_write_approval_runbook():
platform_code = request.args.get("platform", "all")
return jsonify(_service().build_write_approval_runbook(platform_code=platform_code))
@market_intel_bp.route("/api/market_intel/deployment_readiness")
@login_required
def market_intel_deployment_readiness():
return jsonify(_service().build_deployment_readiness())
from routes import market_intel_mcp_run_routes # noqa: E402,F401
from routes import market_intel_mcp_review_routes # noqa: E402,F401