Files
worldmonitor/docs/api/ForecastService.openapi.json
Elie Habib dca83bb5e5 feat(forecast): simulation confidence sub-bar in ForecastPanel (#2526)
Add three fields to Forecast proto (simulation_adjustment,
sim_path_confidence, demoted_by_simulation) and implement a
thin colored underbar below each forecast title that encodes
simulation evidence without adding columns or text clutter.

Visual design (Option D):
- 2px colored bar, width = sim path confidence for positive adj,
  100% for negative/demoted (structural, not confidence-dependent)
- Green ≥0.70 conf, amber <0.70, orange negative, red demoted
- Opacity 0.45 at rest; 0.9 + text label on hover
- Plain language hover labels: "AI signal · +8%", "AI caution · −12%",
  "AI flag: dropped · −15%" — no "sim" jargon visible to users
- Demoted rows dim to opacity 0.5

Passes through simulation fields in buildPublishedForecastPayload.
No chip renders until the ExpandedPath → Forecast plumbing lands
(follow-up PR); all rendering code is ready and typecheck clean.

🤖 Generated with Claude Sonnet 4.6 via Claude Code + Compound Engineering v2.49.0

Co-authored-by: Claude Sonnet 4.6 (200K context) <noreply@anthropic.com>
2026-03-29 23:03:03 +04:00

1 line
11 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"components":{"schemas":{"CalibrationInfo":{"properties":{"drift":{"format":"double","type":"number"},"marketPrice":{"format":"double","type":"number"},"marketTitle":{"type":"string"},"source":{"type":"string"}},"type":"object"},"CascadeEffect":{"properties":{"domain":{"type":"string"},"effect":{"type":"string"},"probability":{"format":"double","type":"number"}},"type":"object"},"Error":{"description":"Error is returned when a handler encounters an error. It contains a simple error message that the developer can customize.","properties":{"message":{"description":"Error message (e.g., 'user not found', 'database connection failed')","type":"string"}},"type":"object"},"FieldViolation":{"description":"FieldViolation describes a single validation error for a specific field.","properties":{"description":{"description":"Human-readable description of the validation violation (e.g., 'must be a valid email address', 'required field missing')","type":"string"},"field":{"description":"The field path that failed validation (e.g., 'user.email' for nested fields). For header validation, this will be the header name (e.g., 'X-API-Key')","type":"string"}},"required":["field","description"],"type":"object"},"Forecast":{"properties":{"calibration":{"$ref":"#/components/schemas/CalibrationInfo"},"cascades":{"items":{"$ref":"#/components/schemas/CascadeEffect"},"type":"array"},"caseFile":{"$ref":"#/components/schemas/ForecastCase"},"confidence":{"format":"double","type":"number"},"createdAt":{"description":"Warning: Values \u003e 2^53 may lose precision in JavaScript","format":"int64","type":"integer"},"demotedBySimulation":{"type":"boolean"},"domain":{"type":"string"},"feedSummary":{"type":"string"},"id":{"type":"string"},"perspectives":{"$ref":"#/components/schemas/Perspectives"},"priorProbability":{"format":"double","type":"number"},"probability":{"format":"double","type":"number"},"projections":{"$ref":"#/components/schemas/Projections"},"region":{"type":"string"},"scenario":{"type":"string"},"signals":{"items":{"$ref":"#/components/schemas/ForecastSignal"},"type":"array"},"simPathConfidence":{"format":"double","type":"number"},"simulationAdjustment":{"description":"Simulation-scoring fields — populated when the deep forecast simulation pipeline\n has run for this forecast's state and produced a non-zero adjustment.\n simulation_adjustment: raw score delta (+0.08+0.12 positive, -0.12/-0.15 negative).\n sim_path_confidence: clamped [0,1] confidence of the matched sim top-path; 0 = not set.\n demoted_by_simulation: true when a negative adjustment crossed the 0.50 acceptance threshold.","format":"double","type":"number"},"timeHorizon":{"type":"string"},"title":{"type":"string"},"trend":{"type":"string"},"updatedAt":{"description":"Warning: Values \u003e 2^53 may lose precision in JavaScript","format":"int64","type":"integer"}},"type":"object"},"ForecastActor":{"properties":{"category":{"type":"string"},"constraints":{"items":{"type":"string"},"type":"array"},"id":{"type":"string"},"influenceScore":{"format":"double","type":"number"},"likelyActions":{"items":{"type":"string"},"type":"array"},"name":{"type":"string"},"objectives":{"items":{"type":"string"},"type":"array"},"role":{"type":"string"}},"type":"object"},"ForecastBranch":{"properties":{"kind":{"type":"string"},"outcome":{"type":"string"},"projectedProbability":{"format":"double","type":"number"},"rounds":{"items":{"$ref":"#/components/schemas/ForecastBranchRound"},"type":"array"},"summary":{"type":"string"},"title":{"type":"string"}},"type":"object"},"ForecastBranchRound":{"properties":{"actorMoves":{"items":{"type":"string"},"type":"array"},"developments":{"items":{"type":"string"},"type":"array"},"focus":{"type":"string"},"probabilityShift":{"format":"double","type":"number"},"round":{"format":"int32","type":"integer"}},"type":"object"},"ForecastCase":{"properties":{"actorLenses":{"items":{"type":"string"},"type":"array"},"actors":{"items":{"$ref":"#/components/schemas/ForecastActor"},"type":"array"},"baseCase":{"type":"string"},"branches":{"items":{"$ref":"#/components/schemas/ForecastBranch"},"type":"array"},"changeItems":{"items":{"type":"string"},"type":"array"},"changeSummary":{"type":"string"},"contrarianCase":{"type":"string"},"counterEvidence":{"items":{"$ref":"#/components/schemas/ForecastCaseEvidence"},"type":"array"},"escalatoryCase":{"type":"string"},"supportingEvidence":{"items":{"$ref":"#/components/schemas/ForecastCaseEvidence"},"type":"array"},"triggers":{"items":{"type":"string"},"type":"array"},"worldState":{"$ref":"#/components/schemas/ForecastWorldState"}},"type":"object"},"ForecastCaseEvidence":{"properties":{"summary":{"type":"string"},"type":{"type":"string"},"weight":{"format":"double","type":"number"}},"type":"object"},"ForecastSignal":{"properties":{"type":{"type":"string"},"value":{"type":"string"},"weight":{"format":"double","type":"number"}},"type":"object"},"ForecastWorldState":{"properties":{"activePressures":{"items":{"type":"string"},"type":"array"},"keyUnknowns":{"items":{"type":"string"},"type":"array"},"stabilizers":{"items":{"type":"string"},"type":"array"},"summary":{"type":"string"}},"type":"object"},"GetForecastsRequest":{"properties":{"domain":{"type":"string"},"region":{"type":"string"}},"type":"object"},"GetForecastsResponse":{"properties":{"forecasts":{"items":{"$ref":"#/components/schemas/Forecast"},"type":"array"},"generatedAt":{"description":"Warning: Values \u003e 2^53 may lose precision in JavaScript","format":"int64","type":"integer"}},"type":"object"},"GetSimulationOutcomeRequest":{"properties":{"runId":{"description":"IMPORTANT: Currently a no-op. Always returns the latest available outcome regardless of runId.\n Per-run lookup is reserved for Phase 3. Check the response 'note' field when runId is supplied\n and you need to detect a mismatch between requested and returned run.","type":"string"}},"type":"object"},"GetSimulationOutcomeResponse":{"properties":{"error":{"description":"Populated when the Redis lookup failed. Distinguish from healthy not-found (found=false, error=\"\").\n Value: \"redis_unavailable\" on Redis errors.","type":"string"},"found":{"type":"boolean"},"generatedAt":{"description":"Unix timestamp in milliseconds (from Date.now()). Warning: Values \u003e 2^53 may lose precision in JavaScript.. Warning: Values \u003e 2^53 may lose precision in JavaScript","format":"int64","type":"integer"},"note":{"description":"Populated when req.runId was supplied but does not match the returned outcome's runId.\n Indicates that per-run filtering is not yet active and the latest outcome was returned instead.","type":"string"},"outcomeKey":{"type":"string"},"runId":{"type":"string"},"schemaVersion":{"type":"string"},"theaterCount":{"format":"int32","type":"integer"},"theaterSummariesJson":{"description":"JSON-encoded array of theater summaries for the UI (populated when found=true).\n Shape: Array\u003c{ theaterId, theaterLabel, stateKind, topPaths: [{label, summary, confidence, keyActors}], dominantReactions, stabilizers, invalidators }\u003e\n Parse with JSON.parse() on the client. Empty string when found=false.","type":"string"}},"type":"object"},"GetSimulationPackageRequest":{"properties":{"runId":{"description":"Currently ignored; always returns the latest package. Reserved for Phase 3 per-run lookup.","type":"string"}},"type":"object"},"GetSimulationPackageResponse":{"properties":{"error":{"description":"Populated when the Redis lookup failed. Distinguish from healthy not-found (found=false, error=\"\").\n Value: \"redis_unavailable\" on Redis errors.","type":"string"},"found":{"type":"boolean"},"generatedAt":{"description":"Unix timestamp in milliseconds (from Date.now()). Warning: Values \u003e 2^53 may lose precision in JavaScript.. Warning: Values \u003e 2^53 may lose precision in JavaScript","format":"int64","type":"integer"},"note":{"description":"Populated when req.runId was supplied but does not match the returned package's runId.\n Indicates that per-run filtering is not yet active and the latest package was returned instead.","type":"string"},"pkgKey":{"type":"string"},"runId":{"type":"string"},"schemaVersion":{"type":"string"},"theaterCount":{"format":"int32","type":"integer"}},"type":"object"},"Perspectives":{"properties":{"contrarian":{"type":"string"},"regional":{"type":"string"},"strategic":{"type":"string"}},"type":"object"},"Projections":{"properties":{"d30":{"format":"double","type":"number"},"d7":{"format":"double","type":"number"},"h24":{"format":"double","type":"number"}},"type":"object"},"ValidationError":{"description":"ValidationError is returned when request validation fails. It contains a list of field violations describing what went wrong.","properties":{"violations":{"description":"List of validation violations","items":{"$ref":"#/components/schemas/FieldViolation"},"type":"array"}},"required":["violations"],"type":"object"}}},"info":{"title":"ForecastService API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/api/forecast/v1/get-forecasts":{"get":{"operationId":"GetForecasts","parameters":[{"in":"query","name":"domain","required":false,"schema":{"type":"string"}},{"in":"query","name":"region","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetForecastsResponse"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error response"}},"summary":"GetForecasts","tags":["ForecastService"]}},"/api/forecast/v1/get-simulation-outcome":{"get":{"operationId":"GetSimulationOutcome","parameters":[{"description":"IMPORTANT: Currently a no-op. Always returns the latest available outcome regardless of runId.\n Per-run lookup is reserved for Phase 3. Check the response 'note' field when runId is supplied\n and you need to detect a mismatch between requested and returned run.","in":"query","name":"runId","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSimulationOutcomeResponse"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error response"}},"summary":"GetSimulationOutcome","tags":["ForecastService"]}},"/api/forecast/v1/get-simulation-package":{"get":{"operationId":"GetSimulationPackage","parameters":[{"description":"Currently ignored; always returns the latest package. Reserved for Phase 3 per-run lookup.","in":"query","name":"runId","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSimulationPackageResponse"}}},"description":"Successful response"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error response"}},"summary":"GetSimulationPackage","tags":["ForecastService"]}}}}