syntax = "proto3";

package worldmonitor.forecast.v1;

import "sebuf/http/annotations.proto";

message ForecastSignal {
  string type = 1;
  string value = 2;
  double weight = 3;
}

message CascadeEffect {
  string domain = 1;
  string effect = 2;
  double probability = 3;
}

message CalibrationInfo {
  string market_title = 1;
  double market_price = 2;
  double drift = 3;
  string source = 4;
}

message Perspectives {
  string strategic = 1;
  string regional = 2;
  string contrarian = 3;
}

message Projections {
  double h24 = 1;
  double d7 = 2;
  double d30 = 3;
}

message ForecastCaseEvidence {
  string type = 1;
  string summary = 2;
  double weight = 3;
}

message ForecastActor {
  string id = 1;
  string name = 2;
  string category = 3;
  string role = 4;
  repeated string objectives = 5;
  repeated string constraints = 6;
  repeated string likely_actions = 7;
  double influence_score = 8;
}

message ForecastWorldState {
  string summary = 1;
  repeated string active_pressures = 2;
  repeated string stabilizers = 3;
  repeated string key_unknowns = 4;
}

message ForecastBranchRound {
  int32 round = 1;
  string focus = 2;
  repeated string developments = 3;
  repeated string actor_moves = 4;
  double probability_shift = 5;
}

message ForecastBranch {
  string kind = 1;
  string title = 2;
  string summary = 3;
  string outcome = 4;
  double projected_probability = 5;
  repeated ForecastBranchRound rounds = 6;
}

message ForecastCase {
  repeated ForecastCaseEvidence supporting_evidence = 1;
  repeated ForecastCaseEvidence counter_evidence = 2;
  repeated string triggers = 3;
  repeated string actor_lenses = 4;
  string base_case = 5;
  string escalatory_case = 6;
  string contrarian_case = 7;
  string change_summary = 8;
  repeated string change_items = 9;
  repeated ForecastActor actors = 10;
  ForecastWorldState world_state = 11;
  repeated ForecastBranch branches = 12;
}

message Forecast {
  string id = 1;
  string domain = 2;
  string region = 3;
  string title = 4;
  string scenario = 5;
  string feed_summary = 19;
  double probability = 6;
  double confidence = 7;
  string time_horizon = 8;
  repeated ForecastSignal signals = 9;
  repeated CascadeEffect cascades = 10;
  // Forecast trend direction. Current values are "rising", "falling", and
  // "stable". The seeder compares probability against the prior forecast
  // snapshot and uses a +/-0.05 deadband: deltas above +0.05 are rising,
  // below -0.05 are falling, and everything inside the band is stable.
  string trend = 11;
  double prior_probability = 12;
  CalibrationInfo calibration = 13;
  int64 created_at = 14 [(sebuf.http.int64_encoding) = INT64_ENCODING_NUMBER];
  int64 updated_at = 15 [(sebuf.http.int64_encoding) = INT64_ENCODING_NUMBER];
  Perspectives perspectives = 16;
  Projections projections = 17;
  ForecastCase case_file = 18;
  // Simulation-scoring fields — populated when the deep forecast simulation pipeline
  // has run for this forecast's state and produced a non-zero adjustment.
  // simulation_adjustment: raw score delta (+0.08–+0.12 positive, -0.12/-0.15 negative).
  // sim_path_confidence: clamped [0,1] confidence of the matched sim top-path; 0 = not set.
  // demoted_by_simulation: true when a negative adjustment crossed the 0.50 acceptance threshold.
  double simulation_adjustment = 20;
  double sim_path_confidence = 21;
  bool demoted_by_simulation = 22;
}
