Make external chart adapter optional

This commit is contained in:
Codex
2026-05-13 21:10:35 +08:00
parent 1e7189abfa
commit 84e580ab63
5 changed files with 56 additions and 15 deletions
+8 -5
View File
@@ -2,7 +2,7 @@
## Current Goal
Automation execution-layer PXX remains closed and its known scope stays frozen. Under explicit user direction, the active product phase is a dense `Decision Assistant` operator workspace with grouped recall, broader replay baselines, note templates, quick-save shortcuts, read-only market context, and a continuous operator cockpit. This run closed D24/H24 internal non-trading polish by adding a replay-learning `learning_focus_queue` / `next_learning_focus_prompt`, then wiring that learning focus back into the unified `assistant_loop_queue` so the next replay priority becomes part of the main cockpit loop. Local validation passed, the current working tree was deployed, and remote smoke confirmed the latest Decision Assistant fields on the live host.
Automation execution-layer PXX remains closed and its known scope stays frozen. Under explicit user direction, the active product phase is a dense `Decision Assistant` operator workspace with grouped recall, broader replay baselines, note templates, quick-save shortcuts, read-only market context, and a continuous operator cockpit. This run closed E7 internal non-trading polish by reclassifying the external chart adapter as an optional reference: internal review-packet chart context remains primary, external chart URLs are advisory-only enhancements, and missing external configuration no longer blocks the main analysis loop. Local validation passed, the current working tree was deployed, and remote smoke confirmed the latest Decision Assistant fields on the live host.
## Current Branch
@@ -110,6 +110,7 @@ Automation execution-layer PXX remains closed and its known scope stays frozen.
- latest_decision_assistant_learning_attribution_slice: failure_missed_opportunity_setup_session_stats
- latest_decision_assistant_digest_high_value_slice: importance_templates_high_value_filter
- latest_decision_assistant_chart_source_slice: chart_readonly_source_inventory_stale_evidence
- latest_decision_assistant_chart_reference_slice: optional_external_chart_reference_internal_primary
- latest_decision_assistant_continuous_workspace_slice: continuous_workspace_rail
- latest_decision_assistant_workspace_evidence_slice: evidence_section_anchor_navigation
- latest_decision_assistant_weekly_trend_slice: weekly_trend_breakdown
@@ -214,7 +215,8 @@ Automation execution-layer PXX remains closed and its known scope stays frozen.
- latest_decision_assistant_workflow_session_status: implemented
- latest_decision_assistant_learning_attribution_status: implemented
- latest_decision_assistant_digest_high_value_status: implemented
- latest_decision_assistant_chart_source_status: implemented_inventory_only_external_url_missing
- latest_decision_assistant_chart_source_status: implemented_optional_reference_internal_primary
- latest_decision_assistant_chart_reference_status: implemented
- latest_decision_assistant_continuous_workspace_status: implemented
- latest_decision_assistant_workspace_evidence_status: implemented
- latest_decision_assistant_weekly_trend_status: implemented
@@ -229,7 +231,7 @@ Automation execution-layer PXX remains closed and its known scope stays frozen.
- latest_decision_assistant_workbench_status: visible_local_smoke
- latest_remote_decision_assistant_deploy_status: deployed_current_head
- latest_remote_decision_assistant_smoke_status: passed
- latest_remote_decision_assistant_review_packet_status: learning_focus_queue_replay_loop_visible
- latest_remote_decision_assistant_review_packet_status: chart_optional_reference_non_blocking_visible
- latest_p7_selector_choice: continue_periodic_analysis_decision_monitoring_with_maturity_rollup
- latest_p14_slice: webhook_transport_retry
- latest_p15_pxx_tasklist_status: ready
@@ -586,7 +588,7 @@ Automation execution-layer PXX remains closed and its known scope stays frozen.
## Current Risks Or Open Questions
- Remote deploy is no longer blocked. The remaining true external blocker is a real read-only external chart source URL/provider/access pattern; current E6 exposes inventory and stale-source evidence but cannot fetch an external chart without that input.
- Remote deploy is no longer blocked. External chart configuration is now an optional read-only enhancement: internal review-packet chart context remains primary, and missing external chart URLs no longer block the analysis loop.
- Browser screenshot capture adapter is a future enhancement, not a P8 closure blocker. The current adapter is an advisory review-packet HTML capture, and the review loop can still use an existing snapshot, an explicit `image_path`, or write an `unavailable` structured review.
- Visual review remains advisory and must not change execution permission, live readiness, trust bucket, risk governor, or operator confirmation.
- Alert-quality statistics remain advisory and must not change execution permission, live readiness, trust bucket, risk governor, or operator confirmation.
@@ -642,11 +644,12 @@ Automation execution-layer PXX remains closed and its known scope stays frozen.
- Latest W2/H22/F24 validation passed: focused operator workspace tests, 68 related unit/API/static tests, 713 full unit tests, 73 script static checks, `node --check src/web/app.js`, deploy smoke passed 11 endpoints, remote ops smoke passed 9 checks, and remote field smoke confirmed `workflow_session_completion_summary`, `digest_preference_profile`, and the deployed Evidence section anchor/navigation strings.
- Latest W3/H23 validation passed: focused operator workspace tests, 68 related unit/API/static tests, 713 full unit tests, 73 script static checks, `node --check src/web/app.js`, deploy smoke passed 11 endpoints, remote ops smoke passed 9 checks, and remote field smoke confirmed `assistant_loop_queue`, `assistant_loop_summary`, the Loop Queue UI anchor, and the deployed Workflow navigation entry.
- Latest D24/H24 validation passed: focused operator workspace tests, 68 related unit/API/static tests, 713 full unit tests, 73 script static checks, `node --check src/web/app.js`, deploy smoke passed 11 endpoints, remote ops smoke passed 9 checks, and remote field smoke confirmed `learning_focus_queue`, `next_learning_focus_prompt`, and replay-learning presence inside `assistant_loop_queue`.
- Latest E7 validation passed: focused operator workspace tests, 68 related unit/API/static tests, 713 full unit tests, 73 script static checks, `node --check src/web/app.js`, deploy smoke passed 11 endpoints, remote ops smoke passed 9 checks, and remote field smoke confirmed `chart_adapter_mode=optional_reference`, `chart_primary_mode=internal_review_packet_html`, and a non-blocking external chart adapter even when other supporting context sources are stale.
- Real-live order submission remains intentionally disabled because the OKX order adapter is still not a real-live submitter.
## Exact Next Step
D24/H24 internal cockpit polish is closed. The remaining true external blocker for the external-context branch is still the real external-chart step: provide a read-only chart source URL/provider/access pattern if the inventory should become an actual external chart adapter. Internal non-trading backlog still exists, but PXX remains closed; do not create P25/P26 automatically, and do not enable real trading.
E7 optional external-chart mode is closed. External chart URLs are now optional reference enhancements and are not required for the current analysis-only loop. Internal non-trading backlog still exists, but PXX remains closed; do not create P25/P26 automatically, and do not enable real trading.
## Validation Commands Used Recently
+8 -4
View File
@@ -152,7 +152,7 @@
- [x] H23 Workflow section navigation / loop queue continuity slice
- [x] D24 replay learning focus queue / next-focus prompt slice
- [x] H24 replay learning integrated into loop queue slice
- [ ] Blocked external input: provide read-only external chart source URL/provider/access pattern for real external chart adapter
- [x] E7 external chart optional reference / internal-primary mode slice
- [x] P8 local closure complete
- [x] P9 local closure complete
- [x] P10 local closure complete
@@ -267,6 +267,7 @@
- [x] latest_decision_assistant_workspace_loop_slice: workflow_section_navigation_loop_queue
- [x] latest_decision_assistant_learning_focus_slice: learning_focus_queue
- [x] latest_decision_assistant_learning_loop_slice: replay_learning_loop_queue
- [x] latest_decision_assistant_chart_reference_slice: optional_external_chart_reference_internal_primary
- [x] latest_decision_assistant_summary_status: implemented
- [x] latest_decision_assistant_change_summary_status: implemented
- [x] latest_decision_assistant_evidence_status: implemented
@@ -357,7 +358,8 @@
- [x] latest_decision_assistant_workflow_session_status: implemented
- [x] latest_decision_assistant_learning_attribution_status: implemented
- [x] latest_decision_assistant_digest_high_value_status: implemented
- [x] latest_decision_assistant_chart_source_status: implemented_inventory_only_external_url_missing
- [x] latest_decision_assistant_chart_source_status: implemented_optional_reference_internal_primary
- [x] latest_decision_assistant_chart_reference_status: implemented
- [x] latest_decision_assistant_continuous_workspace_status: implemented
- [x] latest_decision_assistant_workspace_evidence_status: implemented
- [x] latest_decision_assistant_weekly_trend_status: implemented
@@ -372,7 +374,7 @@
- [x] latest_decision_assistant_workbench_status: visible_local_smoke
- [x] latest_remote_decision_assistant_deploy_status: deployed_current_head
- [x] latest_remote_decision_assistant_smoke_status: passed
- [x] latest_remote_decision_assistant_review_packet_status: learning_focus_queue_replay_loop_visible
- [x] latest_remote_decision_assistant_review_packet_status: chart_optional_reference_non_blocking_visible
- [x] latest_p7_selector_choice: continue_periodic_analysis_decision_monitoring_with_maturity_rollup
- [x] latest_p14_slice: webhook_transport_retry
- [x] latest_p15_pxx_tasklist_status: ready
@@ -678,10 +680,12 @@
- [x] Deployed W3/H23 current tree and passed remote smoke: 11 deploy endpoints, 9 remote ops checks, and review-packet/static field smoke for `assistant_loop_queue`, `assistant_loop_summary`, Loop Queue UI strings, and Workflow navigation strings
- [x] Completed D24/H24 focused validation: operator workspace tests, 68 related unit/API/static tests, 713 full unit tests, 73 script static checks, and dashboard JS syntax
- [x] Deployed D24/H24 current tree and passed remote smoke: 11 deploy endpoints, 9 remote ops checks, and review-packet field smoke for `learning_focus_queue`, `next_learning_focus_prompt`, and replay-learning presence inside `assistant_loop_queue`
- [x] Completed E7 focused validation: operator workspace tests, 68 related unit/API/static tests, 713 full unit tests, 73 script static checks, and dashboard JS syntax
- [x] Deployed E7 current tree and passed remote smoke: 11 deploy endpoints, 9 remote ops checks, and review-packet field smoke for `chart_adapter_mode=optional_reference`, `chart_primary_mode=internal_review_packet_html`, and a non-blocking external chart adapter even when supporting context sources are stale
## Blocked
- [ ] External chart adapter is blocked until a real read-only chart source URL/provider/access pattern is provided.
- [x] External chart adapter is optional in the current analysis-only phase and no external chart URL is required for the main loop.
## Standing Guardrails
@@ -1470,6 +1470,7 @@ def _build_decision_assistant_external_context_summary(
announcements_snapshot=announcements_snapshot,
)
chart_stale_source_evidence = _build_external_context_chart_stale_source_evidence(chart_readonly_sources)
chart_adapter_mode = _external_context_chart_adapter_mode(chart_readonly_sources)
return {
"status": "active" if active_events or external_waiting_items or council_watch_items or operator_questions or next_confirmation_targets or exchange_events or announcements else "idle",
"news_window_code": news_window.get("code") or "unknown",
@@ -1497,6 +1498,8 @@ def _build_decision_assistant_external_context_summary(
"chart_readonly_source_count": len(chart_readonly_sources),
"chart_stale_source_evidence": chart_stale_source_evidence,
"chart_stale_source_count": len(chart_stale_source_evidence),
"chart_adapter_mode": chart_adapter_mode,
"chart_primary_mode": "internal_review_packet_html",
"chart_context_prompt": _external_context_chart_context_prompt(chart_readonly_sources),
"source_cards": [
{
@@ -2835,10 +2838,10 @@ def _build_external_context_chart_readonly_sources(
{
"source_id": "external_chart_adapter",
"source_type": "external_chart_readonly",
"status": "not_configured",
"freshness_status": "missing_source",
"stale_source_evidence": "external_chart_readonly_url_missing",
"prompt": "Configure a read-only chart URL before relying on external chart screenshots.",
"status": "optional_reference",
"freshness_status": "reference_optional_not_configured",
"stale_source_evidence": None,
"prompt": "Optional external chart reference is not configured; internal review packet chart remains primary.",
},
]
return sources
@@ -2847,9 +2850,14 @@ def _build_external_context_chart_readonly_sources(
def _build_external_context_chart_stale_source_evidence(chart_readonly_sources: list[dict]) -> list[dict]:
stale = []
for source in chart_readonly_sources:
if (
str(source.get("source_type") or "") == "external_chart_readonly"
and str(source.get("status") or "") == "optional_reference"
):
continue
freshness = str(source.get("freshness_status") or "")
status = str(source.get("status") or "")
if freshness in {"missing_source", "source_degraded"} or status in {"error", "not_configured"}:
if freshness in {"missing_source", "source_degraded"} or status in {"error"}:
stale.append(
{
"source_id": source.get("source_id"),
@@ -2862,8 +2870,28 @@ def _build_external_context_chart_stale_source_evidence(chart_readonly_sources:
return stale
def _external_context_chart_adapter_mode(chart_readonly_sources: list[dict]) -> str:
external_source = next(
(
dict(source)
for source in chart_readonly_sources
if str(source.get("source_type") or "") == "external_chart_readonly"
),
{},
)
return str(external_source.get("status") or "not_present")
def _external_context_chart_context_prompt(chart_readonly_sources: list[dict]) -> str:
stale_count = len(_build_external_context_chart_stale_source_evidence(chart_readonly_sources))
if any(
str(source.get("source_type") or "") == "external_chart_readonly"
and str(source.get("status") or "") == "optional_reference"
for source in chart_readonly_sources
):
if stale_count:
return f"Primary internal chart context is available; {stale_count} supporting chart context source(s) still need freshness review."
return "Primary internal chart context is available; external chart reference remains optional and is not required for analysis."
if stale_count:
return f"{stale_count} chart context source(s) need freshness review before use."
return "All chart context sources are available for read-only analysis."
+3
View File
@@ -1447,6 +1447,8 @@ function renderDecisionAssistant(summary) {
['exchange anomaly window', String(Boolean(externalContext.exchange_anomaly_window))],
['chart sources', String(externalContext.chart_readonly_source_count ?? 0)],
['stale chart sources', String(externalContext.chart_stale_source_count ?? 0)],
['chart adapter mode', externalContext.chart_adapter_mode || 'n/a'],
['chart primary mode', externalContext.chart_primary_mode || 'n/a'],
['chart context prompt', externalContext.chart_context_prompt || 'n/a'],
['chart stale evidence', formatList((externalContext.chart_stale_source_evidence || []).map((item) => `${item.source_id}: ${item.evidence}`))],
['exchange status', `${externalContext.exchange_status?.provider_name || 'unknown'} / ${externalContext.exchange_status?.status || 'unknown'}`],
@@ -1505,6 +1507,7 @@ function renderDecisionAssistant(summary) {
[
['type', item.source_type || 'n/a'],
['freshness', item.freshness_status || 'n/a'],
['status', item.status || 'n/a'],
['stale evidence', item.stale_source_evidence || 'n/a'],
['prompt', item.prompt || 'n/a'],
]
@@ -561,7 +561,10 @@ class OperatorWorkspaceServiceTests(unittest.TestCase):
self.assertIn("chart_readonly_sources", summary["external_context_summary"])
self.assertIn("chart_stale_source_evidence", summary["external_context_summary"])
self.assertGreaterEqual(summary["external_context_summary"]["chart_readonly_source_count"], 1)
self.assertGreaterEqual(summary["external_context_summary"]["chart_stale_source_count"], 1)
self.assertEqual(summary["external_context_summary"]["chart_stale_source_count"], 0)
self.assertEqual(summary["external_context_summary"]["chart_adapter_mode"], "optional_reference")
self.assertEqual(summary["external_context_summary"]["chart_primary_mode"], "internal_review_packet_html")
self.assertIn("optional", summary["external_context_summary"]["chart_context_prompt"].lower())
self.assertIn("CPI", summary["external_context_summary"]["headline"])
self.assertTrue(summary["no_trade_reason_items"])
self.assertIn("watch_london_open", summary["next_actions"])