///|
pub(all) enum OperatorPanel {
DataSourcePanel
ChartPanel
DecisionPanel
EventStreamPanel
PromptDebugPanel
ReviewPanel
FollowUpPanel
ExportPanel
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) enum OperatorAction {
ConfigureDataSource
SubmitMarketSnapshot
RunAnalysis
InspectChart
InspectEvents
InspectPrompts
InspectReviews
StartFollowUp
ExportRun
ReplayRun
} derive(Debug, Eq, ToJson, FromJson)
///|
pub(all) struct OperatorRunView {
run_id : @domain.RunId
status : @workflow.AnalysisRunStatus
title : String
symbol : @domain.Symbol
timeframe : @domain.Timeframe
adapter : String
model : String
chart_path : String?
event_count : Int
book_artifact_count : Int
review_count : Int
blocking_review_count : Int
followup_topic_count : Int
replay_available : Bool
replay_step_count : Int
export_item_count : Int
panels : Array[OperatorPanel]
actions : Array[OperatorAction]
} derive(Debug, Eq, ToJson, FromJson)
///|
fn blocking_review_count(queue : @review.ReviewQueue) -> Int {
queue.items.fold(init=0, fn(count, item) {
if item.priority is Blocking {
count + 1
} else {
count
}
})
}
///|
fn event_count(bundle : @workflow.AnalysisRunBundle) -> Int {
match bundle.projection {
Some(projection) => projection.result.events.length()
None => 0
}
}
///|
fn artifact_count(bundle : @workflow.AnalysisRunBundle) -> Int {
match bundle.write_plan {
Some(plan) => plan.artifacts.length()
None => 0
}
}
///|
fn chart_path(bundle : @workflow.AnalysisRunBundle) -> String? {
match bundle.chart_frame {
Some(frame) => Some(frame.artifact_path)
None => None
}
}
///|
fn completed_panels(review_count : Int) -> Array[OperatorPanel] {
let panels = [
DataSourcePanel,
ChartPanel,
DecisionPanel,
EventStreamPanel,
PromptDebugPanel,
FollowUpPanel,
ExportPanel,
]
if review_count > 0 {
panels.push(ReviewPanel)
}
panels
}
///|
fn completed_actions(review_count : Int) -> Array[OperatorAction] {
let actions = [
ConfigureDataSource,
RunAnalysis,
InspectChart,
InspectEvents,
InspectPrompts,
StartFollowUp,
ExportRun,
ReplayRun,
]
if review_count > 0 {
actions.push(InspectReviews)
}
actions
}
///|
fn planned_panels() -> Array[OperatorPanel] {
[DataSourcePanel, ReviewPanel, FollowUpPanel]
}
///|
fn planned_actions() -> Array[OperatorAction] {
[
ConfigureDataSource,
SubmitMarketSnapshot,
RunAnalysis,
InspectReviews,
StartFollowUp,
]
}
///|
pub fn operator_run_view(
bundle : @workflow.AnalysisRunBundle,
) -> OperatorRunView {
let follow_up = @followup.prepare_follow_up_context(bundle)
let replay_plan = @replay.prepare_replay_plan(bundle)
let export_manifest = @export.prepare_export_manifest(bundle)
let review_count = follow_up.review_queue.items.length()
let status = bundle.status
{
run_id: bundle.request.run_id,
status,
title: bundle.request.operator_request,
symbol: bundle.request.market.symbol,
timeframe: bundle.request.market.timeframe,
adapter: bundle.market_fetch.plan.adapter,
model: bundle.request.gateway.default_model,
chart_path: chart_path(bundle),
event_count: event_count(bundle),
book_artifact_count: artifact_count(bundle),
review_count,
blocking_review_count: blocking_review_count(follow_up.review_queue),
followup_topic_count: follow_up.suggested_topics.length(),
replay_available: replay_plan.can_replay,
replay_step_count: replay_plan.steps.length(),
export_item_count: export_manifest.item_count,
panels: if status is Completed {
completed_panels(review_count)
} else {
planned_panels()
},
actions: if status is Completed {
completed_actions(review_count)
} else {
planned_actions()
},
}
}