{"openapi":"3.1.0","info":{"title":"FailEcho API","summary":"Live failure intelligence for autonomous software.","description":"\nLive failure intelligence for autonomous software.\n\n**Before you retry, check the echo.**\n\nFailEcho collects privacy-safe failure metadata and recovery outcomes from\nautonomous systems. Other agents query that shared evidence to understand\nwhether a failure is widespread and which recovery actions have worked.\n\n### The three calls\n\n| Endpoint | When |\n|---|---|\n| `POST /v1/observe` | after every tool call -- successes *and* failures |\n| `POST /v1/query`   | when a call fails, **before** you retry |\n| `POST /v1/outcome` | after you tried a recovery action |\n\n### MCP\n\nThe same four operations are available over MCP (Streamable HTTP) at `/mcp`:\n`check_tool_failure`, `report_tool_failure`, `report_tool_success`,\n`report_recovery_outcome`. See `/llms.txt` for a machine-readable summary.\n\n### Privacy\n\nOnly structured failure metadata is accepted. No prompts, no tool arguments,\nno tool results, no request/response bodies, no headers, no keys, no customer\ndata. Error messages are normalized (identifiers replaced, credential-shaped\nsubstrings redacted) and the raw string is discarded. `X-Reporter-ID` is\noptional and is salted+hashed before storage.\n\n### Limits\n\nReads are never rate limited. Writes (`/v1/observe`, `/v1/outcome` and the MCP\nreport tools) are limited per client IP. A single reporter contributes at most\n5 attempts per hour to any recovery action's confidence, so no one client can\nbuy a recommendation.\n\n### Honesty\n\nEvery number returned is deterministic arithmetic over observation counts.\nConfidence is a Wilson score lower bound you can recompute yourself. When\nevidence is thin the answer is `INSUFFICIENT_DATA` and `null`, never a guess.\n\nNo account, no key, no payment. MVP.\n","contact":{"name":"FailEcho","url":"https://failecho.com/"},"license":{"name":"MIT"},"version":"0.1.0"},"paths":{"/v1/observe":{"post":{"tags":["network"],"summary":"Report a tool-call outcome (success or failure)","description":"Anonymously report what happened when you called a tool. Failures are normalized and fingerprinted so other agents can recognise the same problem; successes are counted so failure rates mean something.\n\n**Send both outcomes if you can** -- a network that only sees failures cannot tell a broken service from a busy one.\n\n**Never send** prompts, tool arguments, tool results, request or response bodies, headers, cookies, API keys, or customer data. Only the fields below are accepted; anything else is discarded before storage. `error_message` is normalized (identifiers replaced, credential-shaped substrings redacted) and the raw string is dropped.\n\nNo account and no API key. Writes are rate limited per client IP.","operationId":"observe_v1_observe_post","parameters":[{"name":"X-Reporter-ID","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional, stable, self-chosen reporter identifier (any opaque string). It is salted and hashed on arrival and never stored raw. Supplying one improves unique-reporter counts and raises the confidence the network can place in your evidence; omitting it is fully supported and keeps you anonymous.","title":"X-Reporter-Id"},"description":"Optional, stable, self-chosen reporter identifier (any opaque string). It is salted and hashed on arrival and never stored raw. Supplying one improves unique-reporter counts and raises the confidence the network can place in your evidence; omitting it is fully supported and keeps you anonymous."},{"name":"X-Reporter-Kind","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional self-label. Send 'demo' when the caller is an example or demo agent: its reports are stored and usable, but excluded from the network's real-adoption metrics. Anything else (or nothing) is treated as real agent telemetry. Self-labelling can only downgrade a report, never promote one.","title":"X-Reporter-Kind"},"description":"Optional self-label. Send 'demo' when the caller is an example or demo agent: its reports are stored and usable, but excluded from the network's real-adoption metrics. Anything else (or nothing) is treated as real agent telemetry. Self-labelling can only downgrade a report, never promote one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObserveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ObserveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/query":{"post":{"tags":["network"],"summary":"Ask what the network knows about a failure","description":"Send the failure you just hit. The server normalizes and fingerprints it exactly like /v1/observe, then answers: is anyone else seeing this right now, is it new, how bad is the service, what did other agents try, and what actually worked.\n\nCall this **before** retrying -- that is the whole point: a retry that fails for everyone else is a retry you can skip.\n\nNo telemetry is stored: this call creates no observation, no fingerprint and no reporter record. It increments anonymous aggregate counters (did the query find evidence, and did that evidence come from another reporter) so we can measure whether the network works.\n\nNot rate limited. When evidence is thin you get `status: INSUFFICIENT_DATA` and `recommendation: null` -- FailEcho does not guess.\n\nSend `X-Reporter-ID` if you have one: it is salted and hashed on arrival, never stored by this endpoint, and lets FailEcho tell whether the evidence you just received came from somebody else.","operationId":"query_v1_query_post","parameters":[{"name":"X-Reporter-ID","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional, stable, self-chosen reporter identifier (any opaque string). It is salted and hashed on arrival and never stored raw. Supplying one improves unique-reporter counts and raises the confidence the network can place in your evidence; omitting it is fully supported and keeps you anonymous.","title":"X-Reporter-Id"},"description":"Optional, stable, self-chosen reporter identifier (any opaque string). It is salted and hashed on arrival and never stored raw. Supplying one improves unique-reporter counts and raises the confidence the network can place in your evidence; omitting it is fully supported and keeps you anonymous."},{"name":"X-Reporter-Kind","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional self-label. Send 'demo' when the caller is an example or demo agent: its reports are stored and usable, but excluded from the network's real-adoption metrics. Anything else (or nothing) is treated as real agent telemetry. Self-labelling can only downgrade a report, never promote one.","title":"X-Reporter-Kind"},"description":"Optional self-label. Send 'demo' when the caller is an example or demo agent: its reports are stored and usable, but excluded from the network's real-adoption metrics. Anything else (or nothing) is treated as real agent telemetry. Self-labelling can only downgrade a report, never promote one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/outcome":{"post":{"tags":["network"],"summary":"Report the result of a recovery attempt","description":"After you act on a known failure -- retry, wait, refresh the schema, fall back -- tell the network whether it worked. These reports are what turn 'everyone is failing' into 'and here is what fixes it'.\n\nSend one report per attempt, not one per retry loop iteration: a single reporter contributes at most 5 attempts per hour to any action's confidence.\n\nUnknown fingerprints are accepted: another node may already know the signature even if this one does not.","operationId":"outcome_v1_outcome_post","parameters":[{"name":"X-Reporter-ID","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional, stable, self-chosen reporter identifier (any opaque string). It is salted and hashed on arrival and never stored raw. Supplying one improves unique-reporter counts and raises the confidence the network can place in your evidence; omitting it is fully supported and keeps you anonymous.","title":"X-Reporter-Id"},"description":"Optional, stable, self-chosen reporter identifier (any opaque string). It is salted and hashed on arrival and never stored raw. Supplying one improves unique-reporter counts and raises the confidence the network can place in your evidence; omitting it is fully supported and keeps you anonymous."},{"name":"X-Reporter-Kind","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional self-label. Send 'demo' when the caller is an example or demo agent: its reports are stored and usable, but excluded from the network's real-adoption metrics. Anything else (or nothing) is treated as real agent telemetry. Self-labelling can only downgrade a report, never promote one.","title":"X-Reporter-Kind"},"description":"Optional self-label. Send 'demo' when the caller is an example or demo agent: its reports are stored and usable, but excluded from the network's real-adoption metrics. Anything else (or nothing) is treated as real agent telemetry. Self-labelling can only downgrade a report, never promote one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutcomeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutcomeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/services":{"get":{"tags":["status"],"summary":"Current status of every service/operation the network has seen","description":"Rolled up across versions and schema hashes, over the last hour. Sorted worst-first so an incident is the first row you read.","operationId":"services_v1_services_get","parameters":[{"name":"service","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional exact-match filter on service name.","title":"Service"},"description":"Optional exact-match filter on service name."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"description":"Max rows.","default":100,"title":"Limit"},"description":"Max rows."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServiceStatus"},"title":"Response Services V1 Services Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/stats":{"get":{"tags":["status"],"summary":"Network-wide counters","description":"Powers the live homepage. Real and synthetic telemetry are reported separately and never summed into a single adoption number. Totals include observations that survive only as hourly aggregates after pruning.","operationId":"stats_v1_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkStats"}}}}}}},"/v1/recovery-intelligence":{"get":{"tags":["status"],"summary":"Best evidenced recovery actions right now","description":"The failures the network currently has the strongest recovery evidence for, best confidence first. Entries backed by synthetic demo rows are flagged with `demo_data: true`. Only actions that clear the evidence threshold appear here -- an empty list means the network has nothing worth acting on yet.","operationId":"recovery_intelligence_v1_recovery_intelligence_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":25,"minimum":1,"description":"Max entries.","default":5,"title":"Limit"},"description":"Max entries."},{"name":"include_demo","in":"query","required":false,"schema":{"type":"boolean","description":"Include entries backed by synthetic demo data.","default":true,"title":"Include Demo"},"description":"Include entries backed by synthetic demo data."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecoveryIntelligence"},"title":"Response Recovery Intelligence V1 Recovery Intelligence Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"tags":["status"],"summary":"Liveness probe","description":"Returns `{\"status\": \"ok\"}` when the process is up and the database answers. No authentication, no rate limit.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}}},"components":{"schemas":{"FailureRates":{"properties":{"last_5m":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Last 5M","description":"failures / observations, last 5 minutes."},"last_1h":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Last 1H","description":"failures / observations, last hour."}},"type":"object","required":["last_5m","last_1h"],"title":"FailureRates","description":"Failure rate for the service/operation/version/schema_hash scope.\n\nNull means the window held no observations at all -- which is not 0.0."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthResponse":{"properties":{"status":{"type":"string","title":"Status","description":"'ok' when the service and database are up."}},"type":"object","required":["status"],"title":"HealthResponse"},"NetworkStats":{"properties":{"observations_total":{"type":"integer","title":"Observations Total","description":"All observations ever recorded, real and synthetic, including those that now survive only as hourly aggregates."},"observations_1h":{"type":"integer","title":"Observations 1H","description":"Observations in the last hour."},"failures_1h":{"type":"integer","title":"Failures 1H","description":"Failure observations in the last hour."},"active_failures":{"type":"integer","title":"Active Failures","description":"Distinct fingerprints observed in the last 5 minutes."},"real_active_failures":{"type":"integer","title":"Real Active Failures","description":"Distinct fingerprints observed in the last 5 minutes from real agents only. Demo and synthetic rows are excluded.","default":0},"fingerprints_total":{"type":"integer","title":"Fingerprints Total","description":"Distinct failure signatures known."},"recovery_outcomes_total":{"type":"integer","title":"Recovery Outcomes Total","description":"Recovery attempts reported."},"services_tracked":{"type":"integer","title":"Services Tracked","description":"Distinct services seen in the last hour."},"demo_data":{"type":"boolean","title":"Demo Data","description":"True when any stored row is demo data -- seeded by scripts/seed_demo.py or reported by a self-labelled demo agent. The homepage shows a demo banner while this is true."},"demo_mode":{"type":"boolean","title":"Demo Mode","description":"True when this deployment runs with FIN_DEMO_MODE=1, i.e. it is a demonstration instance. It never generates traffic; it only labels what is stored.","default":false},"synthetic_observations":{"type":"integer","title":"Synthetic Observations","description":"Observations seeded by scripts/seed_demo.py."},"demo_agent_observations":{"type":"integer","title":"Demo Agent Observations","description":"Observations reported by agents that labelled themselves demo (X-Reporter-Kind: demo). Real evidence, deliberately excluded from adoption metrics.","default":0},"real_observations_total":{"type":"integer","title":"Real Observations Total","description":"Observations reported by real agents, all time.","default":0},"real_observations_24h":{"type":"integer","title":"Real Observations 24H","description":"Observations reported by real agents in the last 24h.","default":0},"real_reporters_24h":{"type":"integer","title":"Real Reporters 24H","description":"Distinct identified real reporters in the last 24h. Anonymous reports are excluded, so this is a lower bound.","default":0},"real_failure_fingerprints":{"type":"integer","title":"Real Failure Fingerprints","description":"Distinct failure signatures seen from real agents in the last 24h.","default":0},"real_failures_24h":{"type":"integer","title":"Real Failures 24H","description":"Real failure observations in the last 24h.","default":0},"real_successes_24h":{"type":"integer","title":"Real Successes 24H","description":"Real success observations in the last 24h. Without these, every failure rate in FailEcho is meaningless.","default":0},"known_query_hits_24h":{"type":"integer","title":"Known Query Hits 24H","description":"Real queries in the last 24h that matched a known failure.","default":0},"unknown_query_hits_24h":{"type":"integer","title":"Unknown Query Hits 24H","description":"Real queries in the last 24h that found nothing.","default":0},"known_hit_rate_24h":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Known Hit Rate 24H","description":"known / (known + unknown) queries, last 24h. Null when no real queries were made. The headline experiment number: it says how often asking FailEcho was worth the round trip."},"recovery_outcome_ratio_24h":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Recovery Outcome Ratio 24H","description":"Recovery outcomes reported per real failure reported, last 24h. Null when no real failures were reported. Low values mean agents report failures but never say whether the fix worked, which is the difference between evidence and an error counter."},"cross_agent_help_24h":{"type":"integer","title":"Cross Agent Help 24H","description":"Real queries in the last 24h where an identified caller received a recommendation backed by at least one other reporter -- i.e. an agent benefited from evidence it did not generate. Conservative: anonymous callers and single-reporter evidence are not counted.","default":0},"archived_observations":{"type":"integer","title":"Archived Observations","description":"Observations whose raw rows were pruned and now live only as hourly aggregates. Included in observations_total.","default":0},"generated_at":{"type":"string","title":"Generated At","description":"ISO-8601 UTC timestamp of this snapshot."}},"type":"object","required":["observations_total","observations_1h","failures_1h","active_failures","fingerprints_total","recovery_outcomes_total","services_tracked","demo_data","synthetic_observations","generated_at"],"title":"NetworkStats","description":"Network-wide counters powering the homepage.\n\nReal and synthetic telemetry are counted separately and never summed into\none adoption number. A demo row must never be able to look like a user."},"ObservationCounts":{"properties":{"total":{"type":"integer","title":"Total","description":"All-time observations of this fingerprint."},"last_5m":{"type":"integer","title":"Last 5M","description":"Observations in the last 5 minutes."},"last_1h":{"type":"integer","title":"Last 1H","description":"Observations in the last hour."},"unique_reporters":{"type":"integer","title":"Unique Reporters","description":"Distinct identified reporters in the last hour. Anonymous observations are excluded, so this is a lower bound: one noisy reporter cannot look like a crowd."}},"type":"object","required":["total","last_5m","last_1h","unique_reporters"],"title":"ObservationCounts","description":"How common this exact fingerprint is."},"ObserveRequest":{"properties":{"service":{"type":"string","maxLength":128,"minLength":1,"title":"Service","description":"Tool/service identifier, e.g. 'github-mcp'.","examples":["github-mcp"]},"operation":{"type":"string","maxLength":128,"minLength":1,"title":"Operation","description":"Operation/tool name within the service, e.g. 'create_issue'.","examples":["create_issue"]},"version":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Version","description":"Version of the service/tool, if the agent knows it.","examples":["2.8.1"]},"schema_hash":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Schema Hash","description":"Short hash of the tool schema the agent used. Lets the network separate 'the API broke' from 'your schema is stale'.","examples":["a817ce"]},"outcome":{"type":"string","enum":["success","failure"],"title":"Outcome","description":"'success' or 'failure'.","examples":["failure"]},"error_type":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Error Type","description":"Short failure class, e.g. 'validation_error', 'timeout'.","examples":["validation_error"]},"error_code":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Error Code","description":"Protocol/vendor code, e.g. '422', 'ECONNRESET'.","examples":["422"]},"error_message":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Error Message","description":"Short error message. Normalized before storage; the raw value is never persisted. Do not include secrets or customer data.","examples":["Repository 918272 was not found"]},"latency_ms":{"anyOf":[{"type":"integer","maximum":3600000.0,"minimum":0.0},{"type":"null"}],"title":"Latency Ms","description":"Observed call latency in milliseconds.","examples":[421]}},"type":"object","required":["service","operation","outcome"],"title":"ObserveRequest","description":"One anonymous tool-call outcome.\n\nSend this after *every* call if you can -- successes included. Failure\nrates are only meaningful when the network sees the denominator.\n\nPRIVACY: never put prompts, tool arguments, tool results, request or\nresponse bodies, headers, cookies, keys or customer data in any field.\n``error_message`` is normalized server-side (identifiers replaced,\ncredential-shaped substrings redacted) and the raw string is discarded."},"ObserveResponse":{"properties":{"accepted":{"type":"boolean","title":"Accepted","description":"True when the observation was stored."},"fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fingerprint","description":"Fingerprint of the failure signature. Null for success observations, which do not have one."},"known":{"type":"boolean","title":"Known","description":"True when the network had already seen this fingerprint before this report. Always false for success observations."},"observations":{"type":"integer","title":"Observations","description":"For failures: total observations of this fingerprint, including this one. For successes: total observations recorded for this service/operation/version/schema_hash scope."},"normalized_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Normalized Error","description":"What we actually stored, so you can audit the normalizer."}},"type":"object","required":["accepted","known","observations"],"title":"ObserveResponse","description":"Acknowledgement, plus an immediate hint about what was just reported."},"OutcomeRequest":{"properties":{"fingerprint":{"type":"string","pattern":"^[0-9a-f]{32}$","title":"Fingerprint","description":"Fingerprint from /v1/observe or /v1/query.","examples":["3f2a1c0d4e5b6a7f8c9d0e1f2a3b4c5d"]},"action":{"type":"string","title":"Action","description":"What you tried. Free-form string, lowercased and normalized. Common values: retry, wait, refresh_schema, remove_optional_field, reconnect, use_fallback, reauthenticate, abort.","examples":["refresh_schema"]},"successful":{"type":"boolean","title":"Successful","description":"True when the action resolved the failure."}},"type":"object","required":["fingerprint","action","successful"],"title":"OutcomeRequest","description":"Tell the network whether a recovery action actually worked.\n\nThis is the highest-value telemetry in the system: it is the difference\nbetween \"everyone is failing\" and \"everyone is failing, and refreshing the\nschema fixes it\"."},"OutcomeResponse":{"properties":{"accepted":{"type":"boolean","title":"Accepted","description":"True when the outcome was stored."}},"type":"object","required":["accepted"],"title":"OutcomeResponse"},"QueryRequest":{"properties":{"service":{"type":"string","maxLength":128,"minLength":1,"title":"Service","description":"Tool/service identifier, e.g. 'github-mcp'.","examples":["github-mcp"]},"operation":{"type":"string","maxLength":128,"minLength":1,"title":"Operation","description":"Operation/tool name within the service, e.g. 'create_issue'.","examples":["create_issue"]},"version":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Version","description":"Version of the service/tool, if the agent knows it.","examples":["2.8.1"]},"schema_hash":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Schema Hash","description":"Short hash of the tool schema the agent used. Lets the network separate 'the API broke' from 'your schema is stale'.","examples":["a817ce"]},"error_type":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Error Type","description":"Short failure class, e.g. 'validation_error'.","examples":["validation_error"]},"error_code":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Error Code","description":"Protocol/vendor code.","examples":["422"]},"error_message":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Error Message","description":"Your raw error message. Normalized server-side and never stored by this endpoint.","examples":["Repository 555812 was not found"]}},"type":"object","required":["service","operation"],"title":"QueryRequest","description":"Ask the network what is happening with a failure you just hit.\n\nCall this *before* retrying. Send the same fields you would send to\n/v1/observe; the server normalizes and fingerprints them the same way, so\nyour local error matches what other agents reported."},"QueryResponse":{"properties":{"known":{"type":"boolean","title":"Known","description":"True when this fingerprint has been observed before."},"fingerprint":{"type":"string","title":"Fingerprint","description":"Fingerprint computed from your request. Pass it to /v1/outcome."},"status":{"type":"string","enum":["HEALTHY","DEGRADED","MAJOR","INSUFFICIENT_DATA"],"title":"Status","description":"Health of the service/operation scope: HEALTHY, DEGRADED, MAJOR or INSUFFICIENT_DATA. MVP threshold heuristic, see /docs."},"first_seen":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Seen","description":"ISO-8601 UTC of the first sighting."},"last_seen":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Seen","description":"ISO-8601 UTC of the most recent sighting."},"looks_new":{"type":"boolean","title":"Looks New","description":"True when this fingerprint was first seen inside the last 5 minutes -- i.e. it looks like a fresh incident rather than a long-standing failure mode.","default":false},"observations":{"$ref":"#/components/schemas/ObservationCounts"},"failure_rate":{"$ref":"#/components/schemas/FailureRates"},"normalized_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Normalized Error","description":"Normalized form of your error message."},"recovery_actions":{"items":{"$ref":"#/components/schemas/RecoveryActionStats"},"type":"array","title":"Recovery Actions","description":"All reported recovery actions, strongest evidence first."},"recommendation":{"anyOf":[{"$ref":"#/components/schemas/Recommendation"},{"type":"null"}],"description":"Null when no action has enough evidence (min 5 effective attempts and 60% success rate). The network never fabricates confidence."},"demo_data_included":{"type":"boolean","title":"Demo Data Included","description":"True when synthetic demo rows contribute to these numbers. Treat the recommendation as an illustration, not as field evidence.","default":false}},"type":"object","required":["known","fingerprint","status","observations","failure_rate"],"title":"QueryResponse","description":"Everything the network knows about this failure right now."},"Recommendation":{"properties":{"action":{"type":"string","title":"Action","description":"Recommended recovery action."},"confidence":{"type":"number","title":"Confidence","description":"Wilson lower bound, capped below 1.0. Not a model output -- recompute it yourself from attempts/successes if you like."},"based_on_attempts":{"type":"integer","title":"Based On Attempts","description":"Attempts backing the recommendation."},"based_on_successes":{"type":"integer","title":"Based On Successes","description":"Successes backing it."},"effective_attempts":{"type":"integer","title":"Effective Attempts","description":"Attempts that actually counted, after the per-reporter cap.","default":0},"unique_reporters":{"type":"integer","title":"Unique Reporters","description":"Distinct identified reporters behind it. Below 3 the confidence above has already been discounted.","default":0}},"type":"object","required":["action","confidence","based_on_attempts","based_on_successes"],"title":"Recommendation","description":"The single action the network would try next, when evidence allows."},"RecoveryActionStats":{"properties":{"action":{"type":"string","title":"Action","description":"Recovery action name, e.g. 'refresh_schema'."},"attempts":{"type":"integer","title":"Attempts","description":"Times this action was attempted."},"successes":{"type":"integer","title":"Successes","description":"Times it resolved the failure."},"success_rate":{"type":"number","title":"Success Rate","description":"successes / attempts, as reported (uncapped)."},"effective_attempts":{"type":"integer","title":"Effective Attempts","description":"Attempts after the per-reporter hourly cap. One reporter can contribute at most 5 attempts per hour to this number, so a single noisy agent cannot manufacture evidence."},"effective_successes":{"type":"integer","title":"Effective Successes","description":"Successes after the same cap, scaled down proportionally."},"unique_reporters":{"type":"integer","title":"Unique Reporters","description":"Distinct identified reporters behind this action. 0 means the evidence is entirely anonymous, which lowers confidence."},"confidence":{"type":"number","title":"Confidence","description":"Wilson score lower bound (95%) computed on the capped counts and discounted when fewer than 3 distinct reporters back it. Rewards sample size, so 5/5 ranks below 117/124."}},"type":"object","required":["action","attempts","successes","success_rate","effective_attempts","effective_successes","unique_reporters","confidence"],"title":"RecoveryActionStats","description":"What other agents tried against this fingerprint, and how it went."},"RecoveryIntelligence":{"properties":{"service":{"type":"string","title":"Service"},"operation":{"type":"string","title":"Operation"},"error_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Type"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code"},"normalized_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Normalized Error"},"fingerprint":{"type":"string","title":"Fingerprint"},"action":{"type":"string","title":"Action","description":"Best observed recovery action."},"attempts":{"type":"integer","title":"Attempts"},"successes":{"type":"integer","title":"Successes"},"success_rate":{"type":"number","title":"Success Rate"},"confidence":{"type":"number","title":"Confidence","description":"Wilson lower bound, diversity adjusted."},"unique_reporters":{"type":"integer","title":"Unique Reporters"},"observations":{"type":"integer","title":"Observations","description":"Observations of this failure signature."},"last_seen":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Seen"},"demo_data":{"type":"boolean","title":"Demo Data","description":"True when synthetic demo rows back this entry."}},"type":"object","required":["service","operation","fingerprint","action","attempts","successes","success_rate","confidence","unique_reporters","observations","demo_data"],"title":"RecoveryIntelligence","description":"One well-evidenced recovery action, for the homepage and for agents."},"ServiceStatus":{"properties":{"service":{"type":"string","title":"Service","examples":["github-mcp"]},"operation":{"type":"string","title":"Operation","examples":["create_issue"]},"status":{"type":"string","enum":["HEALTHY","DEGRADED","MAJOR","INSUFFICIENT_DATA"],"title":"Status","description":"MVP heuristic status."},"failure_rate_5m":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Failure Rate 5M","description":"Failure rate over the last 5 minutes, null if no data."},"failure_rate_1h":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Failure Rate 1H","description":"Failure rate over the last hour, null if no data."},"observations_5m":{"type":"integer","title":"Observations 5M","description":"Observations in the last 5 minutes."},"observations_1h":{"type":"integer","title":"Observations 1H","description":"Observations in the last hour."},"last_seen":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Seen","description":"ISO-8601 UTC of the most recent observation."},"demo_data":{"type":"boolean","title":"Demo Data","description":"True when every observation behind this row came from demo or synthetic sources, i.e. no real agent traffic contributed. Mixed rows are reported as real.","default":false}},"type":"object","required":["service","operation","status","failure_rate_5m","failure_rate_1h","observations_5m","observations_1h"],"title":"ServiceStatus","description":"Current health of one service/operation pair, across all versions."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}