This commit is contained in:
2026-05-12 21:40:03 +02:00
parent 75c2b6983d
commit aa19ca9c18
21 changed files with 899 additions and 20 deletions

View File

@@ -166,7 +166,8 @@
<div class="mb-3">
<label for="demoPipeline2ValidationProfileSelect" class="form-label">Validation profile</label>
<select id="demoPipeline2ValidationProfileSelect" class="form-select">
<option value="0.7.29_multi_dex_matrix_baseline" selected>0.7.29DEX matrix baseline</option>
<option value="0.7.30_non_trade_event_classification" selected>0.7.30non-trade event classification</option>
<option value="0.7.29_multi_dex_matrix_baseline">0.7.29 — DEX matrix baseline</option>
<option value="0.7.28_multi_dex_non_regression">0.7.28 — multi-DEX non-regression</option>
<option value="0.7.27_dexes_non_regression" selected>0.7.27 — first DEXes non-regression</option>
</select>

View File

@@ -16,6 +16,18 @@ eventKind: string,
* Event category.
*/
eventCategory: string | null,
/**
* Event lifecycle kind.
*/
eventLifecycleKind: string | null,
/**
* Event actionability class.
*/
eventActionability: string | null,
/**
* Whether the event is useful but not trade/candle materialized.
*/
nonTradeUseful: boolean | null,
/**
* Trade candidate flag.
*/

View File

@@ -0,0 +1,38 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Local decoded-event classification summary for the UI.
*/
export type DemoPipeline2LocalEventClassificationDiagnosticSummary = {
/**
* Event category.
*/
eventCategory: string,
/**
* Event lifecycle kind.
*/
eventLifecycleKind: string,
/**
* Event actionability class.
*/
eventActionability: string,
/**
* Whether the event is useful but not trade/candle materialized.
*/
nonTradeUseful: boolean,
/**
* Event count.
*/
eventCount: number,
/**
* Decoded trade candidate count.
*/
decodedTradeCandidateCount: number,
/**
* Decoded candle candidate count.
*/
decodedCandleCandidateCount: number,
/**
* Linked trade-event count.
*/
tradeEventCount: number, };

View File

@@ -2,6 +2,7 @@
import type { DemoPipeline2LocalDecodedEventDiagnosticSummary } from "./DemoPipeline2LocalDecodedEventDiagnosticSummary";
import type { DemoPipeline2LocalDexDiagnosticSummary } from "./DemoPipeline2LocalDexDiagnosticSummary";
import type { DemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample } from "./DemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample";
import type { DemoPipeline2LocalEventClassificationDiagnosticSummary } from "./DemoPipeline2LocalEventClassificationDiagnosticSummary";
import type { DemoPipeline2LocalMissingTradeEventDiagnosticSample } from "./DemoPipeline2LocalMissingTradeEventDiagnosticSample";
import type { DemoPipeline2LocalMissingTradeEventReasonSummary } from "./DemoPipeline2LocalMissingTradeEventReasonSummary";
import type { DemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample } from "./DemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample";
@@ -37,6 +38,18 @@ decodedTradeCandidateCount: number,
* Total decoded DEX candle candidates.
*/
decodedCandleCandidateCount: number,
/**
* Total decoded useful non-trade events.
*/
decodedNonTradeUsefulEventCount: number,
/**
* Total decoded swap-like events that are intentionally non-actionable.
*/
decodedNonActionableTradeEventCount: number,
/**
* Total decoded events with unknown classification.
*/
decodedUnknownEventCount: number,
/**
* Whether the local persisted pipeline has no blocking diagnostic issue.
*/
@@ -130,6 +143,10 @@ pairSummaries: Array<DemoPipeline2LocalPairDiagnosticSummary>,
* Diagnostics grouped by decoded event kind.
*/
decodedEventSummaries: Array<DemoPipeline2LocalDecodedEventDiagnosticSummary>,
/**
* Diagnostics grouped by decoded event classification.
*/
eventClassificationSummaries: Array<DemoPipeline2LocalEventClassificationDiagnosticSummary>,
/**
* Missing trade events grouped by diagnostic reason.
*/

View File

@@ -30,6 +30,18 @@ expectedDexCodes: Array<string>,
* Observed DEX codes found in diagnostics.
*/
observedDexCodes: Array<string>,
/**
* Total decoded useful non-trade events.
*/
decodedNonTradeUsefulEventCount: number,
/**
* Total decoded swap-like events that are intentionally non-actionable.
*/
decodedNonActionableTradeEventCount: number,
/**
* Total decoded events with unknown classification.
*/
decodedUnknownEventCount: number,
/**
* Number of entries currently exposed by the DEX support matrix.
*/

View File

@@ -640,7 +640,7 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine(
logTextarea,
`[ui] local pipeline diagnostics completed: ${payload.summary.decodedEventCount.toString()} decoded, ${payload.summary.tradeEventCount.toString()} trades, ${payload.summary.pairCandleCount.toString()} candles, actionableMissing='${payload.summary.actionableMissingTradeEventCount.toString()}', nonActionablePairs='${payload.summary.nonActionablePairCount.toString()}', blocking='${payload.summary.blockingIssueCount.toString()}'`,
`[ui] local pipeline diagnostics completed: ${payload.summary.decodedEventCount.toString()} decoded, ${payload.summary.tradeEventCount.toString()} trades, ${payload.summary.pairCandleCount.toString()} candles, actionableMissing='${payload.summary.actionableMissingTradeEventCount.toString()}', nonActionablePairs='${payload.summary.nonActionablePairCount.toString()}', blocking='${payload.summary.blockingIssueCount.toString()}', nonTradeUseful='${payload.summary.decodedNonTradeUsefulEventCount.toString()}', nonActionableTrade='${payload.summary.decodedNonActionableTradeEventCount.toString()}', unknownEvents='${payload.summary.decodedUnknownEventCount.toString()}'`,
);
} catch (error) {
appendLogLine(logTextarea, `[ui] local pipeline diagnostics error: ${String(error)}`);
@@ -667,7 +667,7 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine(
logTextarea,
`[ui] local pipeline validation completed: profile='${payload.run.validationProfileCode}' passed='${payload.run.validationPassed ? "yes" : "no"}' blocking='${payload.run.blockingIssueCount.toString()}' warnings='${payload.run.warningCount.toString()}' dexMatrix='${payload.run.report.dexSupportMatrixEntryCount.toString()}'`,
`[ui] local pipeline validation completed: profile='${payload.run.validationProfileCode}' passed='${payload.run.validationPassed ? "yes" : "no"}' blocking='${payload.run.blockingIssueCount.toString()}' warnings='${payload.run.warningCount.toString()}' dexMatrix='${payload.run.report.dexSupportMatrixEntryCount.toString()}' nonTradeUseful='${payload.run.report.decodedNonTradeUsefulEventCount.toString()}' nonActionableTrade='${payload.run.report.decodedNonActionableTradeEventCount.toString()}' unknownEvents='${payload.run.report.decodedUnknownEventCount.toString()}'`,
);
} catch (error) {
appendLogLine(logTextarea, `[ui] local pipeline validation error: ${String(error)}`);

View File

@@ -152,6 +152,15 @@ pub(crate) struct DemoPipeline2LocalPipelineValidationReport {
pub expected_dex_codes: std::vec::Vec<std::string::String>,
/// Observed DEX codes found in diagnostics.
pub observed_dex_codes: std::vec::Vec<std::string::String>,
/// Total decoded useful non-trade events.
#[ts(type = "number")]
pub decoded_non_trade_useful_event_count: i64,
/// Total decoded swap-like events that are intentionally non-actionable.
#[ts(type = "number")]
pub decoded_non_actionable_trade_event_count: i64,
/// Total decoded events with unknown classification.
#[ts(type = "number")]
pub decoded_unknown_event_count: i64,
/// Number of entries currently exposed by the DEX support matrix.
#[ts(type = "number")]
pub dex_support_matrix_entry_count: i64,
@@ -253,6 +262,15 @@ pub(crate) struct DemoPipeline2LocalPipelineDiagnosticSummary {
/// Total decoded DEX candle candidates.
#[ts(type = "number")]
pub decoded_candle_candidate_count: i64,
/// Total decoded useful non-trade events.
#[ts(type = "number")]
pub decoded_non_trade_useful_event_count: i64,
/// Total decoded swap-like events that are intentionally non-actionable.
#[ts(type = "number")]
pub decoded_non_actionable_trade_event_count: i64,
/// Total decoded events with unknown classification.
#[ts(type = "number")]
pub decoded_unknown_event_count: i64,
/// Whether the local persisted pipeline has no blocking diagnostic issue.
pub diagnostics_clean: bool,
/// Number of blocking diagnostic issues.
@@ -321,6 +339,9 @@ pub(crate) struct DemoPipeline2LocalPipelineDiagnosticSummary {
pub pair_summaries: std::vec::Vec<DemoPipeline2LocalPairDiagnosticSummary>,
/// Diagnostics grouped by decoded event kind.
pub decoded_event_summaries: std::vec::Vec<DemoPipeline2LocalDecodedEventDiagnosticSummary>,
/// Diagnostics grouped by decoded event classification.
pub event_classification_summaries:
std::vec::Vec<DemoPipeline2LocalEventClassificationDiagnosticSummary>,
/// Missing trade events grouped by diagnostic reason.
pub missing_trade_event_reason_summaries:
std::vec::Vec<DemoPipeline2LocalMissingTradeEventReasonSummary>,
@@ -440,6 +461,12 @@ pub(crate) struct DemoPipeline2LocalDecodedEventDiagnosticSummary {
pub event_kind: std::string::String,
/// Event category.
pub event_category: std::option::Option<std::string::String>,
/// Event lifecycle kind.
pub event_lifecycle_kind: std::option::Option<std::string::String>,
/// Event actionability class.
pub event_actionability: std::option::Option<std::string::String>,
/// Whether the event is useful but not trade/candle materialized.
pub non_trade_useful: std::option::Option<bool>,
/// Trade candidate flag.
pub trade_candidate: std::option::Option<bool>,
/// Candle candidate flag.
@@ -452,6 +479,36 @@ pub(crate) struct DemoPipeline2LocalDecodedEventDiagnosticSummary {
pub trade_event_count: i64,
}
/// Local decoded-event classification summary for the UI.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/DemoPipeline2LocalEventClassificationDiagnosticSummary.ts"
)]
#[serde(rename_all = "camelCase")]
pub(crate) struct DemoPipeline2LocalEventClassificationDiagnosticSummary {
/// Event category.
pub event_category: std::string::String,
/// Event lifecycle kind.
pub event_lifecycle_kind: std::string::String,
/// Event actionability class.
pub event_actionability: std::string::String,
/// Whether the event is useful but not trade/candle materialized.
pub non_trade_useful: bool,
/// Event count.
#[ts(type = "number")]
pub event_count: i64,
/// Decoded trade candidate count.
#[ts(type = "number")]
pub decoded_trade_candidate_count: i64,
/// Decoded candle candidate count.
#[ts(type = "number")]
pub decoded_candle_candidate_count: i64,
/// Linked trade-event count.
#[ts(type = "number")]
pub trade_event_count: i64,
}
/// Local missing-trade-event reason summary for the UI.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
@@ -914,7 +971,7 @@ pub(crate) async fn demo_pipeline2_validate_local_pipeline(
let service = kb_lib::LocalPipelineValidationService::new(database.clone());
let profile_code = match request {
Some(request) => request.profile_code,
None => "0.7.29_multi_dex_matrix_baseline".to_string(),
None => "0.7.30_non_trade_event_classification".to_string(),
};
let run_result = match profile_code.as_str() {
"0.7.27" | "0.7.27_dexes_non_regression" => {
@@ -926,6 +983,9 @@ pub(crate) async fn demo_pipeline2_validate_local_pipeline(
"0.7.29" | "0.7.29_multi_dex_matrix_baseline" => {
service.validate_v0_7_29_current_database().await
},
"0.7.30" | "0.7.30_non_trade_event_classification" => {
service.validate_v0_7_30_current_database().await
},
other => Err(kb_lib::Error::InvalidState(format!(
"unsupported local pipeline validation profile: {other}"
))),
@@ -1351,6 +1411,9 @@ fn demo_pipeline2_map_local_validation_report(
warning_count: report.warning_count,
expected_dex_codes: report.expected_dex_codes,
observed_dex_codes: report.observed_dex_codes,
decoded_non_trade_useful_event_count: report.decoded_non_trade_useful_event_count,
decoded_non_actionable_trade_event_count: report.decoded_non_actionable_trade_event_count,
decoded_unknown_event_count: report.decoded_unknown_event_count,
dex_support_matrix_entry_count: report.dex_support_matrix_entry_count,
dex_support_matrix,
issues,
@@ -1410,6 +1473,14 @@ fn demo_pipeline2_map_local_diagnostics_summary(
decoded_event_summaries
.push(demo_pipeline2_map_local_decoded_event_diagnostic_summary(decoded_event_summary));
}
let mut event_classification_summaries = std::vec::Vec::new();
for classification_summary in summary.event_classification_summaries {
event_classification_summaries.push(
demo_pipeline2_map_local_event_classification_diagnostic_summary(
classification_summary,
),
);
}
let mut missing_trade_event_reason_summaries = std::vec::Vec::new();
for reason_summary in summary.missing_trade_event_reason_summaries {
missing_trade_event_reason_summaries
@@ -1450,6 +1521,9 @@ fn demo_pipeline2_map_local_diagnostics_summary(
decoded_event_count: summary.decoded_event_count,
decoded_trade_candidate_count: summary.decoded_trade_candidate_count,
decoded_candle_candidate_count: summary.decoded_candle_candidate_count,
decoded_non_trade_useful_event_count: summary.decoded_non_trade_useful_event_count,
decoded_non_actionable_trade_event_count: summary.decoded_non_actionable_trade_event_count,
decoded_unknown_event_count: summary.decoded_unknown_event_count,
diagnostics_clean: summary.diagnostics_clean,
blocking_issue_count: summary.blocking_issue_count,
missing_trade_event_count: summary.missing_trade_event_count,
@@ -1479,6 +1553,7 @@ fn demo_pipeline2_map_local_diagnostics_summary(
dex_summaries,
pair_summaries,
decoded_event_summaries,
event_classification_summaries,
missing_trade_event_reason_summaries,
non_actionable_pair_count: summary.non_actionable_pair_count,
non_actionable_pair_summaries,
@@ -1534,6 +1609,9 @@ fn demo_pipeline2_map_local_decoded_event_diagnostic_summary(
protocol_name: summary.protocol_name,
event_kind: summary.event_kind,
event_category: summary.event_category,
event_lifecycle_kind: summary.event_lifecycle_kind,
event_actionability: summary.event_actionability,
non_trade_useful: summary.non_trade_useful,
trade_candidate: summary.trade_candidate,
candle_candidate: summary.candle_candidate,
event_count: summary.event_count,
@@ -1541,6 +1619,21 @@ fn demo_pipeline2_map_local_decoded_event_diagnostic_summary(
}
}
fn demo_pipeline2_map_local_event_classification_diagnostic_summary(
summary: kb_lib::LocalEventClassificationDiagnosticSummaryDto,
) -> DemoPipeline2LocalEventClassificationDiagnosticSummary {
DemoPipeline2LocalEventClassificationDiagnosticSummary {
event_category: summary.event_category,
event_lifecycle_kind: summary.event_lifecycle_kind,
event_actionability: summary.event_actionability,
non_trade_useful: summary.non_trade_useful,
event_count: summary.event_count,
decoded_trade_candidate_count: summary.decoded_trade_candidate_count,
decoded_candle_candidate_count: summary.decoded_candle_candidate_count,
trade_event_count: summary.trade_event_count,
}
}
fn demo_pipeline2_map_missing_trade_event_reason_summary(
summary: kb_lib::LocalMissingTradeEventReasonSummaryDto,
) -> DemoPipeline2LocalMissingTradeEventReasonSummary {