Quantified Self MCP Server
This local MCP server lets AI assistants inspect, record, export, and statistically analyze personal health data stored in SQLite, with provenance and privacy controls.
Read daily health metrics across date ranges, including steps, sleep, resting heart rate, weight, workout minutes, mood, water, heart rate, and HRV.
Read raw timestamped measurements and individual workout sessions.
Export daily health metrics to a CSV file on disk without returning every row through the model context.
Log or update daily metrics, raw measurements, and workout sessions; clear a single metric for a day.
Check data freshness, coverage, gaps, latest imports, and recent import history.
Preview source-priority aggregation and inspect per-source provenance to resolve conflicting device readings.
Analyze metrics with baselines, anomaly detection, trends, period comparisons, correlations, recent changes, and a full explain-a-specific-day bundle.
Return evidence/claim tiers with mandatory caveats and data-health warnings so AI conclusions distinguish supported findings from weak or suggestive signals.
Keep data local in SQLite, with optional private-field redaction via HEALTH_PRIVATE_FIELDS, and support importing from CSV, Apple Health, WHOOP, Oura, and Android Health Connect through setup CLIs.
Allows importing health data from Apple Health export files (XML) into the local database, as well as reading and logging daily health metrics.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Quantified Self MCP ServerWhat was my average sleep and steps last week?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Quantified Self MCP
Your health data. Your AI. Your machine.
A privacy-first, local Model Context Protocol (MCP) server that connects AI assistants to your personal health history — with statistical evidence, provenance, and granular privacy built in.
⚡ Instant Client Setup
Connect Quantified Self MCP to your favorite AI assistant in seconds:
Claude Desktop
Add this to your Claude Desktop configuration:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"quantified-self": {
"command": "uvx",
"args": ["quantified-self-mcp"]
}
}
}(Or point "command" to your installed quantified-self-mcp binary if installed via pip).
Cursor
In Cursor, navigate to Settings → Features → MCP Servers → Add New MCP Server, or add to .cursor/mcp.json:
{
"mcpServers": {
"quantified-self": {
"command": "uvx",
"args": ["quantified-self-mcp"]
}
}
}Windsurf
Add to your mcp_config.json:
{
"mcpServers": {
"quantified-self": {
"command": "uvx",
"args": ["quantified-self-mcp"]
}
}
}Need guides for LM Studio, Open WebUI, or Android Health Connect? See our step-by-step Client Guides.
Related MCP server: apple-health-mcp
🚀 Quick Start
1. Install
pip install quantified-self-mcp2. Import Your Health History
Quantified Self MCP automatically creates and manages a local SQLite database (health.db):
# From CSV:
quantified-self-init-db your-health-data.csv
# From Apple Health export:
quantified-self-init-db export.xml
# From WHOOP Developer API (v2) JSON:
quantified-self-init-db whoop.json --source whoop
# From Oura Ring API (v2) JSON:
quantified-self-init-db oura.json --source oura
# From Android Health Connect export:
quantified-self-init-db health_connect_export.zip3. Verify Setup
Run the built-in diagnostic tool to verify Python dependencies, schema integrity, and database readiness:
quantified-self-doctor4. Ask Your AI
Open your MCP-connected assistant and ask questions in plain English:
"How has my sleep and resting heart rate changed over the last 30 days?"
"Why did my HRV drop last week?"
"What patterns exist between my workout minutes and sleep quality?"
"Which of my health metrics changed the most this month?"💡 Why Quantified Self MCP?
Most health apps either trap your data in a closed cloud dashboard or feed raw numbers blindly into an LLM. Quantified Self MCP provides a trustworthy, analytical bridge:
Feature | Standard Health Dashboards | Naive LLM Prompts | Quantified Self MCP |
Data Ownership | ❌ Locked in Cloud | ⚠️ Uploaded to 3rd-party | ✅ 100% Local SQLite |
Privacy Redaction | ❌ All or nothing | ❌ Raw data dumped | ✅ Granular Field Exclusion |
Statistical Claims | ⚠️ Uncalibrated percentages | ❌ Hallucinated correlations | ✅ ClaimEvidence & Caveats |
Provenance Tracking | ❌ Opaque | ❌ None | ✅ Multi-source origin stamps |
Atomic Snapshots | ⚠️ Manual exports | ❌ None | ✅ WAL-safe backup/restore |
🔒 100% Local & Private
Your database lives on your machine in SQLite. No proprietary health cloud required. If you want a completely offline, air-gapped system, pair it with local models via LM Studio or Ollama.
You can also redact specific sensitive metrics from being exposed to the AI:
export HEALTH_PRIVATE_FIELDS=weight_kg,moodPrivate fields remain safely stored in SQLite for your own records, but are blocked from all AI queries and analytics.
🔎 Evidence & Provenance Engine
When an AI analyzes your health, a number without context is dangerous.
If an LLM sees a 24% drop in HRV, did it come from 30 continuous days of wearable data, or just 4 sparse readings with a week-long gap?
Quantified Self MCP solves this with an integrated ClaimEvidence Engine:
Analysis Result
↓
claim: ClaimEvidence
├── evidence → Raw coverage observed (days logged, max gap, freshness)
├── profile → Dimension assessment (sample size, temporal span, missingness)
└── decision → Authoritative claim tier:
[ insufficient | suggestive | detectable_not_meaningful | supported ]
+ specific mandatory caveats (must_state)Example: Naive vs. Evidence-Backed AI Response
Without Evidence Engine (Naive LLM):
"Your HRV dropped 24% over the last month. You may be overtraining."
With Quantified Self MCP Evidence:
"Your HRV decreased 24% over the last 30 days — but HRV was only logged on 71% of those days with a 5-day recording gap, so this is flagged as suggestive rather than a confirmed trend. (Source: Apple Watch)."
Every analytical tool (calculate_metric_trend, explain_metric_change, detect_metric_anomalies) returns explicit claim tiers alongside mandatory disclosures.
📊 Supported Data & Integrations
Quantified Self MCP ships with 20 specialized tools spanning raw measurements, longitudinal statistics, and data health:
AI Agent (Claude / Cursor / LM Studio)
│
MCP Protocol
│
▼
┌──────────────────────────────────────────────────┐
│ Quantified Self MCP │
│ │
│ • Data Access • Longitudinal Analytics │
│ • Workout Tracking • ClaimEvidence Engine │
│ • Provenance Resolver • Data Freshness/Health │
└────────────────────────┬─────────────────────────┘
│
▼
Local SQLite (health.db)Metrics Supported Out of the Box
Metric | Category | Standard Unit | Notes |
👟 Steps | Activity | count | Summed per day with multi-source deduplication |
😴 Sleep | Recovery | hours | Provenance-checked interval handling |
❤️ Resting Heart Rate | Cardiovascular | bpm | Daily baseline tracking & anomaly detection |
📈 HRV (Heart Rate Variability) | Recovery | ms | RMSSD/SDNN normalized |
⚖️ Weight & Body Fat | Measurements | kg / % | High-precision episodic measurement tracking |
🏋️ Workouts | Activity | minutes / kcal | Individual workout sessions with sport metadata |
🙂 Mood | Wellness | 1-5 scale | Subjective well-being logs |
💧 Water Intake | Nutrition | ml | Daily fluid tracking |
The schema is fully extensible with custom metric definitions in metric_registry.py.
🔌 Client Compatibility
Client / Assistant | Compatibility | Documentation |
Claude Desktop | ✅ Official Support | |
Cursor | ✅ Full Support | |
Windsurf | ✅ Full Support | Configure via |
LM Studio | ✅ Local AI | |
Open WebUI | ✅ Self-Hosted | |
Android Health Connect | ✅ Export & Ingest |
🛠️ Operations & Data Safety
Atomic WAL Backups
Never copy health.db while your server or MCP client is running: SQLite runs in WAL mode, meaning uncommitted writes live in health.db-wal.
Use the built-in backup CLI, which takes a live, consistent snapshot:
# Create a verified snapshot:
quantified-self-backup create ~/backups/health-2026-11-04.db
# Safe restore (checks schema integrity before moving old DB aside):
quantified-self-backup restore ~/backups/health-2026-11-04.dbDiagnostics
Run anytime to check your Python runtime, database version, and environment configuration:
quantified-self-doctor📚 Documentation
Deep-dive documentation and technical specs:
🤝 Contributing
Contributions are warmly welcomed! We are actively looking for contributions in:
New wearable & app adapters (Garmin, Oura, Fitbit)
Specialized analytical & correlation tools
Evidence engine calibration
New MCP client integrations
Please review CONTRIBUTING.md and CODE_OF_CONDUCT.md before opening a pull request.
📄 License
Licensed under the MIT License.
Available Tools
20 toolsaggregate_measurementsPreview a source-priority resolution of a day's measurementsARead-onlyIdempotent
Preview what one day's raw measurements would roll up to if a conflicting metric were resolved using source_priority, alongside that day's actual current daily_metrics values.
daily_metrics is a database-maintained projection (see db/schema.sql): every log_measurement/import automatically keeps it in sync the moment it's written, using each metric's fixed aggregation method: summed for steps, sleep_hours, workout_minutes and water_ml; averaged for resting_heart_rate, mood, heart_rate and hrv_ms; the latest reading for weight_kg (see aggregation_rules). When a metric has measurements from more than one source on a day, the projection uses only one source's observations — never a blend of devices. It takes the highest-ranked present source in the stored source priority list (manual log_daily_metric entries rank first by default); if none is ranked, the source that observed the most hours of that day, then the one with the latest observation, then by name. This tool writes nothing: "aggregated" previews what the source_priority you pass would produce; "row" is the real, currently-stored value, which differs from "aggregated" whenever the stored priority differs from the one you pass.
If a metric has measurements from more than one source that day (e.g. an Apple Watch and a Garmin both logging resting_heart_rate), use get_metric_provenance first to see whether they actually disagree.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | The day to preview, formatted YYYY-MM-DD. | |
| source_priority | No | Ordered list of source names, e.g. ["Apple Watch", "Garmin"]. For any metric with more than one source that day, the first name in this list that's actually present wins in "aggregated" and the other source's readings for that metric are dropped from that preview. Omit to use the stored priority list and the same fallback the stored projection uses. Never affects "row" — see above. |
Output Schema
| Name | Required | Description |
|---|---|---|
| row | Yes | |
| date | Yes | |
| aggregated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far beyond the annotations, it discloses the resolution algorithm (highest-ranked present source in the stored priority list, manual entries ranked first, then most hours observed, then latest observation, then name), that sources are never blended, and the crucial "aggregated" vs "row" divergence when the passed priority differs from the stored one. It also flags a real behavioral trait annotations cannot express: returned data enters the conversation sent to the calling client's model, which matters for cloud-hosted models. The "writes nothing" line merely restates readOnlyHint, but the rest is substantive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded and no sentence is pure filler, but the middle paragraph is a long digression into how daily_metrics is maintained ("see db/schema.sql", per-metric aggregation methods, multi-level tie-breaking) that a caller largely does not need in order to invoke a two-parameter preview. Source-file references and multi-clause em-dash sentences make it denser than the tool's complexity warrants.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, two-parameter preview with a full output schema and complete schema coverage, nothing an agent needs is missing: it knows what is computed, what the parameter changes, what is never changed, and what to check first when sources conflict. The privacy caveat is a bonus that closes the last ambiguity about handling the returned data.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema description already explains the ordering/dropping behavior and that "row" is never affected, so the schema does most of the work. The description adds real meaning on top: the explicit consequence that non-winning sources' readings are dropped from the preview, and that omitting the parameter falls back to the stored priority with the same tie-breaking chain used by the projection.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Preview what one day's raw measurements would roll up to if a conflicting metric were resolved using source_priority, alongside that day's actual current daily_metrics values" gives a specific verb (preview), a specific resource (a day's measurements plus the daily_metrics projection), and explicitly separates the "aggregated" preview from the "row" value. This is clearly distinct from siblings like read_health_data or get_metric_history, which return data rather than a hypothetical resolution.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the core usage context (preview a hypothetical source_priority before relying on it) and names a concrete prerequisite alternative: "use get_metric_provenance first" when multiple sources disagree. It also implicitly excludes writes ("This tool writes nothing"), but gives no explicit when-not-to-use guidance relative to read_health_data or get_metric_history, which would have made this a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calculate_metric_trendCalculate metric trendARead-onlyIdempotent
Fit a simple straight-line trend to one metric over a window and report its direction, slope (change per day), and r_squared (how well a straight line actually fits — low r_squared means "noisy," not "flat").
Use this tool when:
the user asks whether one metric is trending up/down/flat over a continuous window (e.g. "is my weight trending down?", "how has my HRV changed?").
Do not use this tool when:
the user wants two specific, separately-defined ranges compared (e.g. "this month vs last month") rather than a single continuous slope -> use
compare_metric_periodsinstead.the user asks what's typical/normal rather than which direction it's moving -> use
get_baselineinstead.the user asks about isolated unusual days rather than an overall direction -> use
detect_metric_anomaliesinstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| metric | Yes | One of steps, sleep_hours, resting_heart_rate, weight_kg, workout_minutes, mood, water_ml, heart_rate, hrv_ms. | |
| end_date | No | Last day to include, formatted YYYY-MM-DD. Defaults to today. | |
| start_date | No | First day to include, formatted YYYY-MM-DD. Defaults to 30 days before end_date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| claim | Yes | Evidence and decision for the trend claim; read claim.decision before reporting it. |
| range | Yes | |
| trend | Yes | |
| metric | Yes | |
| evidence | Yes | DEPRECATED: identical to claim.evidence. Use claim.decision, not evidence.confidence. |
| data_health | No | Whether the data behind this result is complete, current and trustworthy. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the description is not obligated to restate it — and it doesn't. It instead adds genuinely new behavioral context: the model-disclosure privacy caveat about data leaving the local SQLite into a cloud conversation, and the interpretation caveat that low r_squared means 'noisy,' not 'flat.' It stops short of describing result shape or performance characteristics, so 4 rather than 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and return values before the routing lists, and the when/when-not blocks are scannable. The privacy paragraph is noticeably long relative to its low-frequency relevance, but it is substantive rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description still supplies the one thing the schema can't: how to read r_squared. Together with the explicit sibling routing and the privacy caveat, an agent has everything needed to select and call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: metric's allowed values, date format YYYY-MM-DD, and both defaults are already fully documented in the schema. The description adds no syntax or format detail beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (fit a straight-line trend) and resource (one metric over a window), plus exactly what is returned: direction, slope per day, and r_squared. This lets an agent distinguish it from get_metric_history, aggregate_measurements, and the regression-adjacent siblings without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains explicit 'use this tool when' and 'do not use this tool when' sections with three named alternatives (compare_metric_periods, get_baseline, detect_metric_anomalies), each tied to a concrete user-utterance trigger. Nothing about tool selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
clear_metricClear a single metricADestructiveIdempotent
Blank out (set to null) a single metric for a single day, without touching that day's other metrics. The counterpart to log_daily_metric for undoing a bad value — e.g. a mood logged for the wrong day, or a weight entered with the wrong units. Clears everything recorded for that metric/day — including individual log_measurement readings or imported rows, not just a value log_daily_metric wrote directly — so the metric genuinely goes back to "nothing recorded" rather than falling back to a blended value from whatever else is left.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | The day to clear a field for, formatted YYYY-MM-DD. | |
| field | Yes | Which metric to blank out. One of: steps, sleep_hours, resting_heart_rate, weight_kg, workout_minutes, mood, water_ml, heart_rate, hrv_ms. |
Output Schema
| Name | Required | Description |
|---|---|---|
| row | No | |
| note | No | |
| cleared | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations' destructiveHint by detailing the full scope of destruction: it clears everything recorded for that metric/day, including individual log_measurement readings and imported rows, not just values written by log_daily_metric. It also adds a privacy note about data becoming part of the conversation sent to a model, which annotations do not cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The main behavioral statement is front-loaded and precise, and the extra detail about clearing all related rows is necessary for a destructive tool. The privacy note adds relevant context but is somewhat tangential to invocation, keeping this from a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter destructive operation, the description fully covers what the tool does, the scope of the destruction, and a privacy consideration. The output schema exists, so return-value details are not the description's responsibility.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already fully documents both parameters. The description reinforces the behavior ('set to null', 'single metric', 'single day') but does not add meaning beyond the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a precise verb ('blank out / set to null') and identifies the exact resource ('a single metric for a single day'), making the operation unmistakable. It also distinguishes itself from the sibling log_daily_metric by explicitly naming it as the counterpart for undoing a bad value.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly explains when to use this tool: for undoing a bad value, with concrete examples like a mood logged for the wrong day or weight entered with wrong units. It does not enumerate explicit when-not-to-use cases or alternative tools, but the context is clear enough for an agent to route correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compare_metric_periodsCompare two periodsARead-onlyIdempotent
Compare one metric's average between two date ranges — e.g. "this month vs. last month" or "since starting a new medication vs. before." The two ranges may be any length and need not be adjacent or equal in size; each is summarized with its own baseline first.
Use this tool when:
the user names or implies two distinct date ranges to weigh against each other (e.g. "compare my average steps this month to last month", "since starting a new medication vs. before").
Do not use this tool when:
there's only one continuous window and the question is about direction over time, not two discrete ranges -> use
calculate_metric_trendinstead.the user wants "what's normal" for a single window, not a before/after comparison -> use
get_baselineinstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| metric | Yes | One of steps, sleep_hours, resting_heart_rate, weight_kg, workout_minutes, mood, water_ml, heart_rate, hrv_ms. | |
| period_a_end | Yes | ||
| period_b_end | Yes | ||
| period_a_start | Yes | ||
| period_b_start | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| claim | Yes | Evidence and decision for the period comparison claim; read claim.decision before reporting it. |
| delta | No | |
| metric | Yes | |
| period_a | Yes | |
| period_b | Yes | |
| pct_change | No | |
| data_health | No | Whether the data behind this result is complete and current (the weaker of the two periods). |
| period_a_stats | Yes | |
| period_b_stats | Yes | |
| period_a_evidence | Yes | DEPRECATED: identical to claim.evidence_a. Use claim.decision, not a standalone confidence field. |
| period_b_evidence | Yes | DEPRECATED: identical to claim.evidence_b. Use claim.decision, not a standalone confidence field. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry readOnly/idempotent/non-destructive, so the safety profile is covered, but the description adds genuinely new behavioral context: that each range is summarized with its own baseline, and a privacy note about data entering the caller's conversation. It stops short of describing result structure, though the output schema covers that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and then cleanly sectioned into when/not-when and a privacy note. The privacy paragraph is long relative to the tool's function but is defensible context; overall the structure is tight and scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema and full annotations present, the description covers purpose, routing, and privacy adequately. The main remaining gap is the unspecified date format and which period (A vs B) represents the comparison target, but for a local read-only analytics tool this is close to complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 20% (metric is documented with its allowed values), so the description must compensate for the four period_*_start/end parameters. It adds relationship semantics (ranges may be any length, non-adjacent, unequal) but never specifies the expected date format, leaving the most numerous parameters under-documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+scope: comparing one metric's average between two date ranges, with concrete examples. It clearly differentiates from siblings by naming the exact alternatives (calculate_metric_trend, get_baseline) an agent might confuse it with.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'use when' and 'do not use when' sections, each with named alternative tools and the condition that selects them (two discrete ranges vs. one continuous window vs. single-window baseline). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
detect_metric_anomaliesDetect metric anomaliesARead-onlyIdempotent
Flag days where one metric deviated sharply from its own baseline over the window, using a median/MAD-based modified z-score rather than a mean/stdev z-score — more robust for short, noisy personal-health series, where the mean/stdev version is easily dragged around by the very outliers it's supposed to catch.
Use this tool when:
the user asks whether anything looked unusual/off/weird on particular days for one metric (e.g. "was there anything unusual about my sleep last month?").
Do not use this tool when:
the user wants a general sense of what's typical, with no interest in flagging specific days -> use
get_baselineinstead.the user asks about a steady increase/decrease over time rather than isolated spikes/dips -> use
calculate_metric_trendinstead.the user already has one specific date in mind and wants the full "why" behind it (baseline, anomaly, trend, and correlations together) -> use
explain_metric_changeinstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| metric | Yes | One of steps, sleep_hours, resting_heart_rate, weight_kg, workout_minutes, mood, water_ml, heart_rate, hrv_ms. | |
| end_date | No | Last day to include, formatted YYYY-MM-DD. Defaults to today. | |
| threshold | No | Modified z-score cutoff. 3.5 (the default, Iglewicz & Hoaglin's standard value) flags only clear outliers; lower it (e.g. 2.5) to see more borderline days. | |
| start_date | No | First day to include, formatted YYYY-MM-DD. Defaults to 90 days before end_date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| claim | Yes | Evidence and decision for the anomaly claim; read claim.decision before reporting it. |
| range | Yes | |
| metric | Yes | |
| evidence | Yes | DEPRECATED: identical to claim.evidence. Use claim.decision, not evidence.confidence. |
| anomalies | Yes | |
| threshold | Yes | |
| data_health | No | Whether the data behind this result is complete, current and trustworthy. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the bar is lower, yet the description adds substantial non-structured context: the median/MAD modified z-score algorithm, why it is chosen over mean/stdev for short noisy health series, and a privacy note that returned data flows into the model's context. This is real behavioral disclosure an agent would otherwise lack.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core behavior and then organizes caveats into scannable when/when-not bullet lists, so evaluate-then-act ordering is clear. It runs somewhat long between the algorithm rationale and the privacy note, but each block carries distinct information rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter, single-required-param analytical tool with an output schema already present, the description supplies everything an agent needs: precise scope, sibling disambiguation, method/semantics of the threshold, and a data-handling caveat. Return-value explanation is correctly delegated to the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already documents metric, start_date, end_date, and the threshold default with its guidance. The description reinforces the robustness rationale behind the threshold but adds no new syntax, format, or constraint information beyond what the schema provides, so the baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+scope: flag days where one metric deviated sharply from its own baseline over a window, using a named statistical method. It explicitly distinguishes itself from get_baseline, calculate_metric_trend, and explain_metric_change, so an agent can route without opening sibling schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit 'Use this tool when' condition with a concrete user-phrasing example, plus a 'Do not use this tool when' list that names the correct alternative for each of three distinct misrouting scenarios (get_baseline, calculate_metric_trend, explain_metric_change). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_metric_changeExplain a metric changeARead-onlyIdempotent
Build an evidence bundle for "why did my look like that on ?": that day's value against a 90-day baseline, whether it qualifies as an anomaly, the trend leading into it, and any other metric that correlates with it strongly enough to be worth mentioning. Returns facts, not an explanation — turning "sleep was 2.6 stdev below baseline and resting heart rate correlates at r=0.71" into an actual answer for the person is what the calling model should do with these facts, not something this tool guesses at itself.
Do not use this tool when:
scanning across many metrics for what changed lately, without a specific metric/date in mind -> use
get_recent_changesinstead.you only need one piece of this bundle (just the baseline, just the trend, just anomalies, or just a correlation) rather than the full why-explanation -> use
get_baseline,calculate_metric_trend,detect_metric_anomalies, orfind_metric_correlationdirectly instead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | The day to explain, formatted YYYY-MM-DD. | |
| metric | Yes | One of steps, sleep_hours, resting_heart_rate, weight_kg, workout_minutes, mood, water_ml, heart_rate, hrv_ms. |
Output Schema
| Name | Required | Description |
|---|---|---|
| date | Yes | |
| trend | Yes | |
| value | No | |
| metric | Yes | |
| baseline | Yes | |
| sessions | No | |
| is_anomaly | Yes | |
| data_health | No | Whether the data behind this result is complete and current (the weaker of the two windows). |
| trend_claim | Yes | Evidence and decision for the 30-day trend leading into this day, assessed separately from the headline claim. Read trend_claim.decision before reporting it. |
| baseline_claim | Yes | Evidence and decision for the 90-day baseline statistics reported in "baseline" (and quoted in narrative_facts). Read baseline_claim.decision before stating what is typical for this metric; it is one of the components overall_decision is the weakest of. |
| baseline_range | Yes | |
| headline_claim | Yes | Evidence and decision for the headline claim: this day's value against its 90-day baseline. Read headline_claim.decision before reporting it. |
| narrative_facts | Yes | |
| conflicting_days | No | |
| modified_z_score | No | |
| overall_decision | Yes | The single decision governing this whole result: weakest-of-N over the headline claim (headline_claim.decision), the trend (trend_claim.decision), and every surfaced correlation's own decision. If any component is insufficient/suggestive, the composite is too — report overall_decision.tier and must_state rather than treating the headline claim as though the trend and correlations couldn't drag it down. |
| correlated_metrics | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnlyHint, idempotentHint, destructiveHint=false) and locality (openWorldHint=false), so the description correctly spends its words elsewhere: it discloses that the tool returns facts only and refuses to synthesize an explanation, and it adds a privacy warning that returned data becomes part of the conversation sent to the calling client's model. That privacy/data-egress disclosure is significant behavioral context an agent could not derive from any structured field.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose statement is front-loaded and the exclusions are bulleted rather than buried in prose, which makes the routing decision scannable. The privacy note runs three lines and is somewhat long relative to its operational importance, though it does earn its place as a genuine data-handling warning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description is not obliged to document return values, and instead it correctly characterizes the bundle's composition and its intentional limitation (facts, not conclusions). For a two-required-parameter read tool with full annotation coverage, nothing an agent needs in order to select and call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with `date` documented as YYYY-MM-DD and `metric` carrying its full enumerated value list, so the schema already does the heavy lifting. The description adds interpretive value by defining what the returned value is being compared against (a 90-day baseline) but offers no format or validation detail beyond the schema. Baseline 3 is the right score here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific, quotable framing of the task it serves ("why did my <metric> look like that on <date>?") and then enumerates exactly what the bundle contains: that day's value against a 90-day baseline, anomaly qualification, incoming trend, and correlated metrics. This is concrete enough to distinguish it from every sibling named, including the four single-purpose tools it composes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit 'Do not use this tool when' section with two named conditions and routes each to specific alternatives (`get_recent_changes` for cross-metric scanning; `get_baseline`, `calculate_metric_trend`, `detect_metric_anomalies`, `find_metric_correlation` when only one component is needed). Both the negative cases and the substitute tools are stated outright, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_health_data_csvExport health data to CSVADestructiveIdempotent
Write daily health metrics for a date range to a CSV file on disk, next to the database, instead of returning every row through this tool's own result.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
Unlike read_health_data, this is not capped at MAX_ROWS_RETURNED and the row values themselves are not included in this tool's response — only the resulting file's path and a row count are. That means a long-range export doesn't have to pass through a cloud LLM's context just to produce a file you can open yourself (in a spreadsheet, a notebook, another tool, etc.). Any metric listed in HEALTH_PRIVATE_FIELDS is still written as an empty cell in the file, since those fields shouldn't leave the database at all, not just stay out of the model's context.
| Name | Required | Description | Default |
|---|---|---|---|
| end_date | No | Last day to include, formatted YYYY-MM-DD. Defaults to today. | |
| start_date | No | First day to include, formatted YYYY-MM-DD. Defaults to 30 days before end_date. Ranges over ~10 years are rejected. |
Output Schema
| Name | Required | Description |
|---|---|---|
| path | Yes | |
| range | Yes | |
| rows_exported | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations mark destructiveHint=true and readOnlyHint=false, and the description fully supports this: it states it writes to disk, does not return row values, and only provides file path and row count. It goes beyond annotations by disclosing the privacy implication (data becomes part of the conversation) and the handling of HEALTH_PRIVATE_FIELDS as empty cells. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is somewhat long but each paragraph earns its place: purpose, privacy note, and comparison with read_health_data. It is front-loaded with the main action and uses structured paragraphs. Slightly verbose but not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool that writes to disk and has privacy implications, the description covers all necessary aspects: side effects, return value (path and row count), difference from read_health_data, private field behavior, and privacy guidance. The output schema exists, so return format is already specified. An agent has everything needed to decide and call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% coverage: both start_date and end_date have clear descriptions with formatting and defaults. The description adds no new semantic detail about the parameters beyond 'date range', so it stays at the baseline for well-covered schemas.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource pair: 'Write daily health metrics for a date range to a CSV file on disk, next to the database.' It clearly distinguishes itself from read_health_data by contrasting the output (file path vs. rows) and the row cap. An agent immediately knows what this tool does and how it differs from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly names the alternative (read_health_data) and explains the differentiator: this tool is not capped at MAX_ROWS_RETURNED and avoids passing data through the model context. It also advises treating the export like pasting into a chat if the model is cloud-based. This gives the agent clear conditions for choosing this tool over alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_metric_correlationFind correlation between two metricsARead-onlyIdempotent
Compute the Pearson correlation between two metrics over the same window, joined by date. Correlation, not causation: a strong r just means the two moved together, not that one caused the other. A question phrased causally ("does my sleep affect my mood?") still gets only this association. The result does not show that one metric affects or causes the other, so report r, n and the wording the claim allows, and say nothing stronger.
Use this tool when:
the user names or implies two different metrics and asks whether they move together (e.g. "does my sleep affect my mood?", "do days with more workout minutes tend to have a higher HRV?").
Do not use this tool when:
only one metric is in question -> use
get_baseline,calculate_metric_trend, ordetect_metric_anomaliesinstead, depending on what's being asked about that one metric.the question is why one metric looked the way it did on a specific date -> use
explain_metric_change, which already reports the other metrics that correlate with it.the question is whether one metric differs between two time periods (e.g. before vs. after a date) -> use
compare_metric_periods.
Reading the result: report what was observed (r, n, and how many days of each metric were present) separately from what may be claimed about it. Read claim.decision before reporting r. Its tier (insufficient, suggestive, detectable_not_meaningful or supported) is the strongest wording allowed, and a high r from a thin or gappy sample is capped there, not in r itself, so never judge a correlation from r alone. claim.decision.template is a sentence frame, not finished text: replace "..." with the finding, and {limiting_factors} with the must_state entries put into plain words. Those entries are codes, not sentences (practical_not_evaluated, for example, means that whether the difference matters in practice was not checked), so do not quote a code to the user. When data_health is not VALID, say why.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| end_date | No | Last day to include, formatted YYYY-MM-DD. Defaults to today. | |
| lag_days | No | Shift metric_b this many days later before joining — 1 tests whether metric_a today predicts metric_b tomorrow (e.g. "does poor sleep tonight predict lower steps tomorrow?"). 0 (default) compares same-day values. | |
| metric_a | Yes | ||
| metric_b | Yes | ||
| start_date | No | First day to include, formatted YYYY-MM-DD. Defaults to 90 days before end_date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| n | Yes | |
| r | No | |
| note | No | |
| claim | Yes | Evidence and decision for the correlation claim; read claim.decision before reporting it. |
| lag_days | Yes | |
| metric_a | Yes | |
| metric_b | Yes | |
| evidence_a | Yes | DEPRECATED: identical to claim.evidence_a. Use claim.decision, not a standalone confidence field. |
| evidence_b | Yes | DEPRECATED: identical to claim.evidence_b. Use claim.decision, not a standalone confidence field. |
| data_health | No | Whether the data behind this result is complete and current (the weaker of the two metrics). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnlyHint, idempotentHint, destructiveHint=false), and the description goes well beyond them: it discloses that gappy or thin samples cap the claim tier rather than r, that data_health must be reported when not VALID, and adds a privacy note about local SQLite data flowing into cloud models. That is exactly the context structured fields cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and organized under clear Use/Do-not-use/Reading-the-result headers. It runs long and the no-causation warning is restated across three consecutive sentences, which costs some density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the presence of an output schema, the description supplies the interpretive contract — read claim.decision before r, treat template as a frame, translate must_state codes rather than quoting them, surface limiting_factors and data_health. For a statistics tool whose numbers are easy to over-report, that is the missing piece an agent needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 60% and the two required params (metric_a, metric_b) carry no schema description; the description never clarifies what form those metric identifiers take or whether they may be equal. It does reinforce the lag/date-join semantics ('joined by date', 'over the same window'), but mainly restates what lag_days and start/end_date already document.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — Pearson correlation between two metrics over the same window, joined by date — and immediately scopes the scope of the claim ('association, not causation'). It is trivially distinguishable from aggregate_measurements, get_baseline, or explain_metric_change.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use list with example phrasings, plus three named do-not-use branches routing to get_baseline/calculate_metric_trend/detect_metric_anomalies, explain_metric_change, and compare_metric_periods. An agent can pick the correct sibling without opening any other schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_baselineGet metric baselineARead-onlyIdempotent
Compute "what's normal" for one metric over a window: mean, median, and standard deviation. This is the number every other analytics tool below measures against, so a wider window (60-90+ days) gives a more stable baseline than the 30-day default read_health_data uses.
Use this tool when:
the user asks what's normal/typical/usual for one metric (e.g. "what's normal for my resting heart rate?"), with no particular day or direction of change in mind.
Do not use this tool when:
the user asks whether a metric is going up/down over time -> use
calculate_metric_trendinstead.the user asks whether specific days looked unusual -> use
detect_metric_anomaliesinstead.the user wants two ranges compared against each other -> use
compare_metric_periodsinstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| metric | Yes | One of steps, sleep_hours, resting_heart_rate, weight_kg, workout_minutes, mood, water_ml, heart_rate, hrv_ms. | |
| end_date | No | Last day to include, formatted YYYY-MM-DD. Defaults to today. | |
| start_date | No | First day to include, formatted YYYY-MM-DD. Defaults to 90 days before end_date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| claim | Yes | Evidence and decision for the "what's normal" claim; read claim.decision before reporting it. |
| range | Yes | |
| metric | Yes | |
| baseline | Yes | |
| evidence | Yes | DEPRECATED: identical to claim.evidence. Use claim.decision, not evidence.confidence. |
| data_health | No | Whether the data behind this baseline is complete, current and trustworthy. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, closed-world, non-destructive), and the description adds real behavioral context beyond them: window-length stability guidance implying a wider window is safer, that the tool is the reference point other analytics compare against, and an explicit privacy disclosure about data entering a cloud-hosted conversation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core computation, then structured when/when-not blocks, closing with a privacy note. The privacy paragraph is long but non-redundant and genuinely actionable, so little is wasted even if the whole is verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be described. The description covers purpose, selection criteria, alternatives, window sizing, and a disclosure about data propagation, leaving no obvious gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents metric enum values and date formats, establishing the baseline of 3. The description adds window-sizing advice (60-90+ days) that guides start_date, but it frames this against read_health_data's default rather than this tool's own 90-day default, so the value added is modest and slightly oblique.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (compute) and resource (baseline statistics: mean, median, standard deviation) for a single metric over a window, and distinguishes itself from the sibling tools that measure against it. An agent can tell immediately what this returns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'use this tool when' and 'do not use this tool when' blocks, each negative case routed to a named alternative (calculate_metric_trend, detect_metric_anomalies, compare_metric_periods) with the discriminating user intent spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_data_statusCheck how current the data isARead-onlyIdempotent
Report how current and complete the database is: latest data date, coverage window, gaps, last successful import, and an overall status of CURRENT, STALE, INCOMPLETE, NO_DATA or IMPORT_FAILED. Check this before drawing conclusions from any analysis, and say so when the status is anything other than CURRENT.
Use this tool when:
the user asks how up to date their data is, or whether an import is needed.
you are about to interpret recent data and want to know whether it is fresh enough to trust.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| stale_after_days | No | How many days the latest data may trail today before the status becomes STALE. Defaults to 2. |
Output Schema
| Name | Required | Description |
|---|---|---|
| gaps | Yes | |
| as_of | Yes | |
| action | No | |
| reason | No | |
| source | No | |
| status | Yes | |
| coverage | Yes | |
| gap_count | Yes | |
| days_behind | No | |
| latest_data | No | |
| missing_days | Yes | |
| latest_import | No | |
| days_with_data | Yes | |
| stale_after_days | Yes | |
| last_successful_import | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover read-only/idempotent/non-destructive safety, so the description's added value is the status vocabulary (CURRENT/STALE/INCOMPLETE/NO_DATA/IMPORT_FAILED) and the privacy disclosure that returned data flows into the conversation sent to a possibly-cloud model. That privacy note is genuinely beyond annotations. It doesn't describe whether results are cached or how gaps are computed, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded: the output inventory comes first, then usage triggers, then the privacy caveat. The privacy paragraph is somewhat long but earns its place by disclosing data egress. Minor repetition between the opening sentence and the status list keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-optional-param read-only status tool, it covers purpose, triggers, output vocabulary, and the privacy/egress implication. With the output schema handling return structure and annotations handling safety, nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single stale_after_days parameter is fully documented in the schema, including its default and threshold meaning. The description adds nothing about the parameter, so the baseline 3 for schema-documented params is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (report how current and complete the database is) and enumerates the exact outputs: latest data date, coverage window, gaps, last import, and status values. It is clearly distinguishable from siblings like get_import_status or get_recent_changes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this tool when' section gives two concrete triggering conditions (user asks about freshness; about to interpret recent data), and it states a when-not condition by instructing the agent to caveat when status isn't CURRENT. Alternatives are not named but the routing logic is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_import_statusList recent importsARead-onlyIdempotent
List the most recent import runs, newest first: which importer, the source file's name and SHA-256, whether the run succeeded, failed or was interrupted, and how many rows were loaded, skipped and written.
Use this tool when:
the user asks what was imported and when, or why an import did not go through.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many import runs to return (1-50). Defaults to 5. |
Output Schema
| Name | Required | Description |
|---|---|---|
| imports | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, non-destructive and closed-world, so the safety profile is covered. The description adds real context beyond that: newest-first ordering, the exact fields returned, and an unusually valuable privacy note about data flowing into the model conversation when the client is cloud-hosted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded, the usage conditions are cleanly bulleted, and the privacy caveat is separated. The privacy note runs three sentences and is slightly verbose, but its content is non-redundant and operationally relevant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and annotations covering the safety profile, the description only needs to route and contextualize. It does that fully, describing the returned fields, ordering, and a privacy dimension an agent would otherwise miss.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the single 'limit' parameter is fully documented in the schema with its range and default. The description adds no meaning beyond that, which is the expected baseline when the schema does the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('List the most recent import runs, newest first') and enumerates exactly what each entry contains (importer, source file name and SHA-256, run outcome, row counts). This is precise enough to separate it from siblings like get_data_status or get_recent_changes, since 'import runs' is a clearly distinct resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use conditions ('the user asks what was imported and when, or why an import did not go through'), which is clear routing guidance. It stops short of naming alternatives or stating when-not to use it, so it is strong but not fully exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_metric_historyGet metric historyARead-onlyIdempotent
Read one metric's day-by-day values, without the other six metrics read_health_data always includes. Use this when you only care about a single metric (e.g. before calling get_baseline or calculate_metric_trend yourself) and don't need the full multi-metric payload.
Use this tool when:
the user wants one specific metric's history/trend over time (e.g. "show my weight over the last 30 days", "how has resting heart rate changed this month").
Do not use this tool when:
the request is broad/general, across multiple metrics at once -> use
read_health_datainstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| metric | Yes | One of steps, sleep_hours, resting_heart_rate, weight_kg, workout_minutes, mood, water_ml, heart_rate, hrv_ms. Rejected if configured as private via HEALTH_PRIVATE_FIELDS. | |
| end_date | No | Last day to include, formatted YYYY-MM-DD. Defaults to today. | |
| start_date | No | First day to include, formatted YYYY-MM-DD. Defaults to 30 days before end_date. |
Output Schema
| Name | Required | Description |
|---|---|---|
| range | Yes | |
| metric | Yes | |
| points | Yes | |
| evidence | Yes | Coverage/quality of the data a single-metric analytical result is based on. See evidence.build_evidence for how each field is computed. |
| data_health | No | Whether this history is complete, current and trustworthy; see DataHealth. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds genuinely non-obvious context: the payload is single-metric only, and a privacy note explains that returned data enters the conversation and may leave the machine if the client model is cloud-hosted — a trait found nowhere in the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core distinction from read_health_data, then cleanly structured as when/when-not bullets. The four-sentence privacy note is unusually verbose relative to the rest and dilutes an otherwise tight definition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, single-metric query with full parameter documentation, rich annotations and a declared output schema, the description covers everything an agent needs: scope, alternatives, and a data-handling caveat. Return-value details are correctly left to the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents metric, start_date and end_date with formats, defaults and the private-field rejection rule. The description adds no parameter-level syntax or semantics beyond what the schema provides, which is the expected baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read one metric's day-by-day values') and immediately contrasts scope with the sibling read_health_data, which 'always includes' the other six metrics. An agent can distinguish the two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use section with concrete example utterances ('show my weight over the last 30 days') and an explicit when-not section naming the alternative tool (read_health_data) for broad multi-metric requests. Routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_metric_provenanceBreak a metric down by sourceARead-onlyIdempotent
Show one metric's raw measurements for one day, broken down by which source reported them — answers "which one is correct?" when e.g. an Apple Watch and a Garmin disagree on resting heart rate, instead of silently averaging two different devices into one number.
Do not use this tool when:
the user just wants a plain day-by-day history for the metric, with no need to see the per-source breakdown -> use
get_metric_historyinstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | The day to inspect, formatted YYYY-MM-DD. | |
| metric | Yes | Name of the metric to inspect, e.g. "resting_heart_rate". |
Output Schema
| Name | Required | Description |
|---|---|---|
| date | Yes | |
| metric | Yes | |
| sources | Yes | |
| conflict | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive behavior, and the description adds meaningful context beyond that: it explains the data becomes part of the conversation and may be sent to a cloud model. This is a real behavioral disclosure about data flow and privacy that an agent could not infer from the schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well structured: purpose leads, a do-not-use block clearly distinguishes the sibling tool, and the privacy note is placed at the end. It is longer than strictly necessary because of the privacy explanation, but each paragraph earns its place and the key information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple two-parameter input, full schema coverage, output schema presence, and complete annotations, the description covers what an agent needs to call this tool correctly. The only minor gap is that it does not spell out the exact return shape or whether source values are normalized, but the output schema covers that burden.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers 100% of the two parameters, including formats and examples for `date` and `metric`. The description does not add much beyond the schema, but the terms 'one day' and 'metric' reinforce the single-day, single-metric scope. The schema does the heavy lifting, so a baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a concrete action and resource: 'Show one metric's raw measurements for one day, broken down by which source reported them.' It directly distinguishes the tool from the sibling `get_metric_history` by emphasizing the per-source breakdown and the 'which one is correct?' use case. The verb and scope are specific enough that an agent can tell what it is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly names the alternative: 'Do not use this tool when... use `get_metric_history` instead.' It also gives a concrete triggering scenario (e.g., Apple Watch and Garmin disagreeing on resting heart rate), making both when-to-use and when-not-to-use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recent_changesGet recent changesARead-onlyIdempotent
Scan every (non-private) metric for what's changed lately: a recent period vs. the four-times-as-long period before it (period-over-period shift), any anomalies inside the recent period, and a trend over it. The single best tool to start a "how have I been doing?" conversation with — it does the scanning across all metrics that would otherwise take one get_baseline/detect_metric_anomalies/calculate_metric_trend call per metric.
Do not use this tool when:
the user already named a specific metric and wants the full why-bundle for it (value, baseline, anomaly flag, trend, correlated metrics) -> use
explain_metric_changeinstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | Length of the "recent" window in days (default 7). The comparison baseline is the 4x-as-long period immediately before it, so a 7-day recent window compares against the preceding 28 days. |
Output Schema
| Name | Required | Description |
|---|---|---|
| changes | Yes | |
| data_health | No | Whether the data behind these changes is complete and current (the weakest metric window). |
| recent_range | Yes | |
| baseline_range | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/local, so the safety profile is covered. The description still adds real context beyond them: it discloses the scan is limited to non-private metrics, and the privacy note explains that returned data leaves the local SQLite store and enters the client's model context. Rate limits or response shape are not covered, but this is meaningfully more than the annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose and the routing rule are front-loaded and waste-free; the privacy paragraph is longer than the tool's mechanics but carries non-redundant decision-relevant information. Slight verbosity in the multi-clause opening, but nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A single optional parameter, full annotations, and an output schema mean the description only needs to carry routing and privacy concerns — which it does. Use case, exclusion, and data-handling caveat are all present, so an agent has everything needed to select and call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single `days` parameter is fully documented in the schema, including the 4x baseline relationship. The description restates the same period-over-period mechanics rather than adding syntax or constraints, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (scan all non-private metrics for period-over-period shift, anomalies, and trend) and explicitly differentiates itself from three siblings by name. An agent can tell what this does and how it relates to get_baseline/detect_metric_anomalies/calculate_metric_trend without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly frames the tool as the entry point for a 'how have I been doing?' conversation, and adds an explicit 'Do not use this tool when' clause routing the user to `explain_metric_change` when a specific metric is named. Both the when and the when-not are stated with named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_daily_metricLog a daily metricADestructiveIdempotent
Record one or more health metrics for a single day, creating that day's row if it doesn't already have one.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
Only the metrics you pass are written — anything left as null is not touched, so logging just today's mood doesn't erase today's steps if they were set earlier. To undo a value logged by mistake, use clear_metric rather than trying to overwrite it with a placeholder.
Use this tool when:
the user is recording a simple day-level value for one of the nine fixed metrics below (e.g. "log my weight as 82 kg", "I walked 8,000 steps today").
Do not use this tool when:
the observation needs its own timestamp/source, or the day may have more than one reading of the same metric -> use
log_measurementinstead.it's a workout/exercise session -> use
log_workout_sessioninstead (workout_minutes here is just the daily total, not the session itself).
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | The day to log, formatted YYYY-MM-DD. | |
| mood | No | Mood rating on a 1-10 scale. | |
| steps | No | Step count for the day. 0-200,000. | |
| hrv_ms | No | Heart rate variability in milliseconds. 0-300. | |
| water_ml | No | Water intake in millilitres. 0-10,000. | |
| weight_kg | No | Body weight in kilograms. 1-500. | |
| heart_rate | No | Non-resting heart rate reading in bpm. 20-250. | |
| sleep_hours | No | Hours of sleep. 0-24. | |
| workout_minutes | No | Minutes of exercise. 0-1,440. | |
| resting_heart_rate | No | Resting heart rate in bpm. 20-250. |
Output Schema
| Name | Required | Description |
|---|---|---|
| row | Yes | |
| logged | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses the crucial merge behavior: null metrics are untouched and only passed metrics are written. It also adds a privacy note about data becoming part of the conversation and suggests clear_metric for undo. These are meaningful behavioral details that do not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a front-loaded core statement, a privacy section, a merge-behavior section, and explicit usage conditions. Despite its length, every section addresses a real agent decision and no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating tool with 10 parameters, the description covers sibling selection, partial-update semantics, privacy implications, and recovery via clear_metric. An output schema exists, so return-value details are not necessary. The tool is fully specified for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes all 10 parameters with units and ranges, so the baseline is 3. The description adds context like 'workout_minutes here is just the daily total' and the null-not-touched rule, but does not need to repeat the schema's per-parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Record one or more health metrics for a single day', and explains the row-creation behavior. It also explicitly distinguishes itself from siblings like log_measurement and log_workout_session, so an agent can tell them apart without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description has clear 'Use this tool when' and 'Do not use this tool when' sections with concrete conditions and named alternatives. It routes timestamped readings to log_measurement and workout sessions to log_workout_session, leaving no ambiguity about selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_measurementLog a raw measurementA
Record a single raw observation — one metric, one value, one point in time — rather than a whole day's summary. Use this instead of log_daily_metric when the source, exact time, or the fact that there were multiple readings that day matters (e.g. three separate workouts, or a wearable's periodic heart-rate samples).
Use this tool when:
recording one timestamped observation where the exact time, source, or possibility of multiple same-day readings matters (e.g. "record my blood pressure reading from my cuff at 7am").
Do not use this tool when:
it's just a single end-of-day value for a fixed metric -> use
log_daily_metricinstead.it's a workout/exercise session -> use
log_workout_sessioninstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| unit | No | Unit the value is in, e.g. "bpm", "kg". Optional. If provided, must match the metric's canonical unit (case-insensitive); convert the reading to that canonical unit before logging. | |
| value | Yes | The numeric reading. | |
| metric | Yes | Name of the metric, e.g. "resting_heart_rate", "steps". Not free-form: must already have an entry in the aggregation_rules table (steps, sleep_hours, resting_heart_rate, weight_kg, workout_minutes, mood, water_ml, heart_rate, hrv_ms, out of the box) — daily_metrics is a database-maintained projection over measurements (see db/schema.sql), so every metric written to it needs a known aggregation method (sum/mean/last) or there would be nothing telling the projection how to roll same-day readings up. metrics_schema lists the current set. | |
| source | No | Where this came from, e.g. "Apple Watch", "manual". Optional. | |
| timestamp | Yes | When the observation was taken, YYYY-MM-DD or a full ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SS). Give local wall-clock time. A numeric UTC offset (e.g. -08:00) is dropped before storing, so the reading belongs to the day written in the timestamp; a trailing "Z" is kept and counts as UTC. | |
| source_type | No | Category of source, e.g. "wearable", "manual", "app". Optional. |
Output Schema
| Name | Required | Description |
|---|---|---|
| measurement | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the write/safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false), so the bar is lower, but the description adds real context beyond them: the privacy note about returned data entering the conversation, and the explanation that metrics must exist in aggregation_rules because daily_metrics is a projection. It does not warn that repeated calls create duplicate readings despite idempotentHint=false, which is the one notable gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core distinction is front-loaded in the first sentence, followed by well-structured when/when-not bullets. The privacy paragraph is long but earns its place by disclosing a non-obvious data-flow consequence; overall it is slightly verbose but not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation, and the description covers the remaining decision-relevant concerns: when to pick this over siblings, the metric-registry constraint, timestamp semantics, and the privacy implication. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents timestamp format, unit canonicalization, and the metric constraint in detail. The description reinforces the 'one metric, one value' framing and the multiple-readings rationale but adds no syntax or format detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Record a single raw observation — one metric, one value, one point in time') and explicitly contrasts it with the day-summary sibling log_daily_metric. An agent can distinguish it from log_daily_metric and log_workout_session without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit 'Use this tool when' and 'Do not use this tool when' sections, naming both alternatives (log_daily_metric for end-of-day values, log_workout_session for exercise sessions) and the condition that selects each. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_workout_sessionLog a workout sessionA
Record one workout as a structured event — activity, timing, intensity, and heart-rate response — rather than folding it into the day's workout_minutes total. Use this alongside (not instead of) log_daily_metric/log_measurement for workout_minutes: this is what lets explain_metric_change say what the workout was, not just how long it ran. A day can have more than one session; each call adds a new row.
Use this tool when:
the user describes an actual workout/exercise session (e.g. "I went running for 40 minutes", "log today's strength workout").
Do not use this tool when:
the user only wants to record the day's total exercise minutes as a single number, with no activity type/timing/intensity -> use
log_daily_metric(workout_minutes) orlog_measurementinstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | The day the workout happened, YYYY-MM-DD. | |
| notes | No | Free-text notes, e.g. route or how it felt. Optional. | |
| source | No | Where this came from, e.g. "Apple Watch", "manual". Optional. | |
| intensity | No | One of "low", "moderate", "high". Optional. | |
| start_time | No | When it started, HH:MM (24-hour) or a full ISO timestamp. Optional. | |
| activity_type | Yes | What kind of workout, e.g. "running", "cycling", "strength". Free-form. | |
| avg_heart_rate | No | Average heart rate during the workout, bpm. Optional. | |
| max_heart_rate | No | Peak heart rate during the workout, bpm. Optional. | |
| duration_minutes | Yes | How long it lasted, in minutes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| session | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false and openWorldHint=false; the description adds the meaningful consequence that a day can hold multiple sessions and each call appends a new row, which explains the non-idempotent behavior. The privacy note about the local SQLite file versus data flowing into the calling client's model context is genuinely useful operational context. It stops short of saying what happens on duplicate/retried submissions, so it is not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded, and the when/when-not bullets are scannable with zero filler. The three-sentence privacy paragraph is longer than the rest of the guidance and only tangentially about invoking the tool, which slightly dilutes focus, but it is still structured and earns most of its space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described, and all parameters are covered by the schema. For a 9-parameter append-style logging tool, the definition supplies purpose, routing rules, append semantics, and privacy implications — everything an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all nine parameters, including the intensity vocabulary and date/time formats, are already documented in the schema. The description only summarizes the field groups (activity, timing, intensity, heart-rate) without adding formats, ranges, or validation rules. Baseline 3 is correct when the schema carries the semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ("Record one workout as a structured event") and enumerates the dimensions captured (activity, timing, intensity, heart-rate response). It explicitly contrasts itself with log_daily_metric/log_measurement for workout_minutes, so an agent can separate it from the closest siblings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit "Use this tool when" list with concrete user utterances ("I went running for 40 minutes") and a "Do not use this tool when" block naming the exact fallback tools for total-minutes-only logging. Both the positive and negative routing conditions are stated, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_health_dataRead health dataARead-onlyIdempotent
Read daily health metrics from the local database: steps, sleep hours, resting heart rate, weight (kg), workout minutes, mood, and water intake (ml).
Use this tool when:
the request is broad/general, across multiple metrics at once (e.g. "what health data do I have?", "overview of this week").
Do not use this tool when:
the user wants one specific metric's history/trend over time -> use
get_metric_historyinstead.the user wants raw/individual measurement rows (timestamp, source) -> use
read_measurementsinstead.the user wants workout sessions specifically -> use
read_workout_sessionsinstead.the user is asking why something changed, or wants a trend, anomaly, comparison, or correlation -> use
explain_metric_change(one metric, one date) orget_recent_changes(scan across all metrics) instead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| end_date | No | Last day to include, formatted YYYY-MM-DD. Defaults to today. | |
| start_date | No | First day to include, formatted YYYY-MM-DD. Defaults to 30 days before end_date. Ranges over ~10 years are rejected. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | Yes | |
| range | Yes | |
| summary | Yes | |
| coverage | Yes | Multi-metric coverage for a Layer-1 result spanning several metrics at once. See evidence.build_coverage_summary for how each field is computed; unlike Evidence (one metric, gaps/freshness/recent_gap), this reports a coverage_percent per metric side by side. |
| truncated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is established. The description adds meaningful context beyond that: the data returned is daily aggregated metrics (not raw rows), the database is a local SQLite file, and returned data may be sent to the configured model — a privacy-relevant behavior an agent should weigh before invoking.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every section earns its place: a front-loaded metrics list, explicit routing rules, and a privacy note. The use of bullets under 'Use when' and 'Do not use when' makes the guidance scannable for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the crowded sibling set (17 tools), the description fully disambiguates this tool from get_metric_history, read_measurements, read_workout_sessions, explain_metric_change, and get_recent_changes. Combined with rich annotations, full schema coverage, and an output schema, nothing needed to select or invoke the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents start_date and end_date with defaults and formatting. The description adds no new parameter-level detail, but under high schema coverage the baseline of 3 applies; no compensation is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read daily health metrics from the local database,' and lists the exact metrics covered (steps, sleep, heart rate, etc.). It also distinguishes itself from closely related siblings (get_metric_history, read_measurements, read_workout_sessions), so an agent knows exactly what this tool does and does not cover.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Use this tool when' section explicitly directs broad/general multi-metric requests to this tool, and the 'Do not use this tool when' section names four alternatives with the exact conditions that should route elsewhere. This is the strongest possible usage guidance — no inference is required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_measurementsRead raw measurementsARead-onlyIdempotent
Read individual measurement rows (not the daily_metrics aggregate), most recent first. Use this to see exactly when and where each reading came from, rather than just a day's summarized value.
Use this tool when:
the user wants raw/individual observations (e.g. "what measurements have I recorded?"), including their timestamp or source.
Do not use this tool when:
the user wants a broad, multi-metric overview -> use
read_health_datainstead.the user wants one metric's day-by-day history -> use
get_metric_historyinstead.the user wants workout sessions -> use
read_workout_sessionsinstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum rows to return, 1 to 1000 (default 200). | |
| metric | No | Only return this metric. Omit for all metrics. | |
| source | No | Only return rows from this source, e.g. "Apple Watch". Omit for all sources. | |
| end_date | No | Only return rows on/before this date (YYYY-MM-DD). Omit for no upper bound. | |
| start_date | No | Only return rows on/after this date (YYYY-MM-DD). Omit for no lower bound. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| measurements | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds genuinely new context that annotations cannot express: default ordering (most recent first), the distinction from aggregated output, and a privacy note that returned rows become part of the model conversation. It omits pagination/truncation behavior, but the output schema likely covers the shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then cleanly segmented into when/when-not lists and a privacy note. Slightly long, and the privacy paragraph is the most verbose part, but each block earns its place by adding decision-relevant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, 5-parameter, schema-rich tool with an output schema and full annotation coverage, this description supplies everything an agent needs: scope, routing to siblings, ordering, and a privacy caveat. No gaps remain that would cause a misselection or misinvocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all five parameters (limit, metric, source, start_date, end_date) are already documented with defaults and format hints. The description's mention of 'timestamp or source' loosely maps to the source/date params but adds no syntax or format detail beyond the schema. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read individual measurement rows'), explicitly scopes it against the daily_metrics aggregate, and specifies ordering ('most recent first'). The contrast with the aggregate makes it immediately distinguishable from read_health_data and get_metric_history.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'use when' conditions with an example query, plus a 'do not use when' list that names three alternatives (read_health_data, get_metric_history, read_workout_sessions) and the condition selecting each. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_workout_sessionsRead workout sessionsARead-onlyIdempotent
Read individual workout sessions (not the daily_metrics workout_minutes total), most recent day first. Use this to see what each workout actually was — activity, timing, intensity, heart rate — rather than just a day's summed minutes.
Use this tool when:
the user asks about workouts/exercise sessions specifically (e.g. "what workouts did I do this week?", "show my recent gym sessions").
Do not use this tool when:
the user just wants the daily workout_minutes total, not individual sessions -> use
read_health_dataorget_metric_historyinstead.
Privacy note: this server and its SQLite file are entirely local, but the data returned by this tool becomes part of the conversation sent to whatever model the calling client is configured with. If that model runs in the cloud rather than on your machine, treat this the same as pasting the data into a chat with that provider.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum rows to return, 1 to 1000 (default 200). | |
| end_date | No | Only return sessions on/before this date (YYYY-MM-DD). Omit for no upper bound. | |
| start_date | No | Only return sessions on/after this date (YYYY-MM-DD). Omit for no lower bound. | |
| activity_type | No | Only return sessions of this activity type. Omit for all types. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| sessions | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/non-destructive, but the description adds behavior they cannot express: result ordering ('most recent day first') and the fact the output is session-level rather than aggregated. The privacy note — that returned data enters the conversation sent to the calling client's model — is genuinely load-bearing context an agent would otherwise not have.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core statement and sibling differentiation before the when/when-not lists, which is the right order. The privacy paragraph is several lines long and slightly over-weighted for a selection decision, but it is substantive rather than filler, so only a small deduction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation, and the description covers scope, granularity, ordering, alternatives and data-handling. The only minor gap is truncation behavior — that limit defaults to 200 and caps at 1000 is left entirely to the schema, which matters for a session-listing tool that can silently omit older rows.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with each of limit, start_date, end_date and activity_type already documented including format (YYYY-MM-DD) and omit-for-unbounded semantics. The description adds no meaning beyond that — the 'this week' example only implies date-range filtering. Baseline 3 applies when the schema carries the parameter burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read individual workout sessions') and immediately disambiguates it from the aggregated daily workout_minutes total, so an agent can distinguish it from get_metric_history or read_health_data without opening any schema. It also names the record fields returned (activity, timing, intensity, heart rate), which pins down the granularity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this tool when' examples ('what workouts did I do this week?') and an explicit 'Do not use this tool when' branch that routes to read_health_data or get_metric_history for summed minutes. Both the positive condition and the exclusion are stated, which is the full bar for this dimension.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.6.0- Changed
log_measurement1 field changed- changed
Input schema / properties / unit / descriptionPrevious value: -"Unit the value is in, e.g. \"bpm\", \"kg\". Optional."New value: +"Unit the value is in, e.g. \"bpm\", \"kg\". Optional. If provided,\nmust match the metric's canonical unit (case-insensitive);\nconvert the reading to that canonical unit before logging."
3 tool updates
v1.0.36- Changed
explain_metric_change2 fields changed- added
Output schema / properties / sessions / items / properties / duration_minutes / anyOfAdded value: +[ + { + "type": "integer" + }, + { + "type": "null" + } +] - removed
Output schema / properties / sessions / items / properties / duration_minutes / typeRemoved value: -"integer"
- Changed
log_workout_session2 fields changed- added
Output schema / properties / session / properties / duration_minutes / anyOfAdded value: +[ + { + "type": "integer" + }, + { + "type": "null" + } +] - removed
Output schema / properties / session / properties / duration_minutes / typeRemoved value: -"integer"
- Changed
read_workout_sessions2 fields changed- added
Output schema / properties / sessions / items / properties / duration_minutes / anyOfAdded value: +[ + { + "type": "integer" + }, + { + "type": "null" + } +] - removed
Output schema / properties / sessions / items / properties / duration_minutes / typeRemoved value: -"integer"
1 tool update
v1.0.34- Changed
log_measurement1 field changed- changed
Input schema / properties / timestamp / descriptionPrevious value: -"When the observation was taken, YYYY-MM-DD or a full\nISO 8601 timestamp (YYYY-MM-DDTHH:MM:SS)."New value: +"When the observation was taken, YYYY-MM-DD or a full\nISO 8601 timestamp (YYYY-MM-DDTHH:MM:SS). Give local\nwall-clock time. A numeric UTC offset (e.g. -08:00) is dropped\nbefore storing, so the reading belongs to the day written in\nthe timestamp; a trailing \"Z\" is kept and counts as UTC."
2 tool updates
v1.0.31- Changed
read_measurements1 field changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum rows to return (default 200)."New value: +"Maximum rows to return, 1 to 1000 (default 200)."
- Changed
read_workout_sessions1 field changed- changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum rows to return (default 200)."New value: +"Maximum rows to return, 1 to 1000 (default 200)."
10 tool updates
v1.0.30- Changed
calculate_metric_trend1 field changed- added
Output schema / properties / data_healthAdded value: +{ + "anyOf": [ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, MIXED_SOURCES, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every\ncondition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the data behind this result is complete, current and trustworthy." +}
- Changed
compare_metric_periods1 field changed- added
Output schema / properties / data_healthAdded value: +{ + "anyOf": [ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, MIXED_SOURCES, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every\ncondition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the data behind this result is complete and current (the weaker of the two periods)." +}
- Changed
detect_metric_anomalies1 field changed- added
Output schema / properties / data_healthAdded value: +{ + "anyOf": [ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, MIXED_SOURCES, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every\ncondition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the data behind this result is complete, current and trustworthy." +}
- Changed
explain_metric_change2 fields changed- added
Output schema / properties / correlated_metrics / items / properties / data_healthAdded value: +{ + "anyOf": [ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, MIXED_SOURCES, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every\ncondition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the data behind this result is complete and current (the weaker of the two metrics)." +} - added
Output schema / properties / data_healthAdded value: +{ + "anyOf": [ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, MIXED_SOURCES, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every\ncondition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the data behind this result is complete and current (the weaker of the two windows)." +}
- Changed
find_metric_correlation1 field changed- added
Output schema / properties / data_healthAdded value: +{ + "anyOf": [ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, MIXED_SOURCES, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every\ncondition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the data behind this result is complete and current (the weaker of the two metrics)." +}
- Changed
get_baseline1 field changed- changed
Output schema / properties / data_health / anyOfPrevious value: -[ - { - "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every condition that\napplies. See data_health.compose_data_health for how it is decided.", - "properties": { - "completeness": { - "properties": { - "coverage_ratio": { - "type": "number" - }, - "expected_days": { - "type": "integer" - }, - "missing_days": { - "type": "integer" - }, - "observed_days": { - "type": "integer" - } - }, - "required": [ - "expected_days", - "observed_days", - "coverage_ratio", - "missing_days" - ], - "type": "object" - }, - "coverage": { - "properties": { - "end": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "requested_end": { - "type": "string" - }, - "requested_start": { - "type": "string" - }, - "start": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - } - }, - "required": [ - "requested_start", - "requested_end" - ], - "type": "object" - }, - "freshness": { - "properties": { - "age_days": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Days from the latest observation to the end of the requested window." - }, - "dataset_days_behind": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Days from the dataset's latest data (any metric) to today." - }, - "latest_data": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - } - }, - "type": "object" - }, - "gaps": { - "items": { - "properties": { - "days": { - "type": "integer" - }, - "end": { - "type": "string" - }, - "start": { - "type": "string" - } - }, - "required": [ - "start", - "end", - "days" - ], - "type": "object" - }, - "type": "array" - }, - "last_import": { - "anyOf": [ - { - "properties": { - "finished_at": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "importer": { - "type": "string" - }, - "source_file": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "status": { - "type": "string" - } - }, - "required": [ - "importer", - "status" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "default": null - }, - "last_successful_import": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "observations": { - "description": "Number of daily values the result is computed from.", - "type": "integer" - }, - "reasons": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "type": "string" - } - }, - "required": [ - "status", - "reasons", - "freshness", - "coverage", - "completeness", - "gaps", - "observations" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, MIXED_SOURCES, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every\ncondition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } +]
- Changed
get_data_status1 field changed- changed
Output schema / properties / latest_import / anyOfPrevious value: -[ - { - "properties": { - "error": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "finished_at": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "id": { - "type": "integer" - }, - "importer": { - "type": "string" - }, - "measurements_written": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - }, - "rows_loaded": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - }, - "rows_skipped": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - }, - "source_file": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "source_sha256": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "started_at": { - "type": "string" - }, - "status": { - "type": "string" - } - }, - "required": [ - "id", - "importer", - "status", - "started_at" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "properties": { + "coverage_after_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "coverage_after_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "coverage_before_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "coverage_before_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "id": { + "type": "integer" + }, + "importer": { + "type": "string" + }, + "measurements_written": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "records_added": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "records_removed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "records_seen": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "records_unchanged": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "records_updated": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "rows_loaded": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "rows_skipped": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "source_sha256": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "started_at": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "required": [ + "id", + "importer", + "status", + "started_at" + ], + "type": "object" + }, + { + "type": "null" + } +]
- Changed
get_import_status9 fields changed- added
Output schema / properties / imports / items / properties / coverage_after_endAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Output schema / properties / imports / items / properties / coverage_after_startAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Output schema / properties / imports / items / properties / coverage_before_endAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Output schema / properties / imports / items / properties / coverage_before_startAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null +} - added
Output schema / properties / imports / items / properties / records_addedAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null +} - added
Output schema / properties / imports / items / properties / records_removedAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null +} - added
Output schema / properties / imports / items / properties / records_seenAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null +} - added
Output schema / properties / imports / items / properties / records_unchangedAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null +} - added
Output schema / properties / imports / items / properties / records_updatedAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null +}
- Changed
get_metric_history1 field changed- changed
Output schema / properties / data_health / anyOfPrevious value: -[ - { - "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every condition that\napplies. See data_health.compose_data_health for how it is decided.", - "properties": { - "completeness": { - "properties": { - "coverage_ratio": { - "type": "number" - }, - "expected_days": { - "type": "integer" - }, - "missing_days": { - "type": "integer" - }, - "observed_days": { - "type": "integer" - } - }, - "required": [ - "expected_days", - "observed_days", - "coverage_ratio", - "missing_days" - ], - "type": "object" - }, - "coverage": { - "properties": { - "end": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "requested_end": { - "type": "string" - }, - "requested_start": { - "type": "string" - }, - "start": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - } - }, - "required": [ - "requested_start", - "requested_end" - ], - "type": "object" - }, - "freshness": { - "properties": { - "age_days": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Days from the latest observation to the end of the requested window." - }, - "dataset_days_behind": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "description": "Days from the dataset's latest data (any metric) to today." - }, - "latest_data": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - } - }, - "type": "object" - }, - "gaps": { - "items": { - "properties": { - "days": { - "type": "integer" - }, - "end": { - "type": "string" - }, - "start": { - "type": "string" - } - }, - "required": [ - "start", - "end", - "days" - ], - "type": "object" - }, - "type": "array" - }, - "last_import": { - "anyOf": [ - { - "properties": { - "finished_at": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "importer": { - "type": "string" - }, - "source_file": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "status": { - "type": "string" - } - }, - "required": [ - "importer", - "status" - ], - "type": "object" - }, - { - "type": "null" - } - ], - "default": null - }, - "last_successful_import": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "observations": { - "description": "Number of daily values the result is computed from.", - "type": "integer" - }, - "reasons": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "type": "string" - } - }, - "required": [ - "status", - "reasons", - "freshness", - "coverage", - "completeness", - "gaps", - "observations" - ], - "type": "object" - }, - { - "type": "null" - } -]New value: +[ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, MIXED_SOURCES, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every\ncondition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } +]
- Changed
get_recent_changes1 field changed- added
Output schema / properties / data_healthAdded value: +{ + "anyOf": [ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, MIXED_SOURCES, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every\ncondition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the data behind these changes is complete and current (the weakest metric window)." +}
6 tool updates
v1.0.29- Changed
get_baseline1 field changed- added
Output schema / properties / data_healthAdded value: +{ + "anyOf": [ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every condition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether the data behind this baseline is complete, current and trustworthy." +}
- Added
get_data_status - Added
get_import_status - Changed
get_metric_history1 field changed- added
Output schema / properties / data_healthAdded value: +{ + "anyOf": [ + { + "description": "Data-quality state behind one result (not a medical or statistical confidence score). status is one of\nVALID, VALID_WITH_GAPS, INSUFFICIENT_DATA, STALE, IMPORT_INCOMPLETE; reasons lists every condition that\napplies. See data_health.compose_data_health for how it is decided.", + "properties": { + "completeness": { + "properties": { + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + } + }, + "required": [ + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days" + ], + "type": "object" + }, + "coverage": { + "properties": { + "end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + }, + "start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "requested_start", + "requested_end" + ], + "type": "object" + }, + "freshness": { + "properties": { + "age_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the latest observation to the end of the requested window." + }, + "dataset_days_behind": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Days from the dataset's latest data (any metric) to today." + }, + "latest_data": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "type": "object" + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "last_import": { + "anyOf": [ + { + "properties": { + "finished_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "importer": { + "type": "string" + }, + "source_file": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "status": { + "type": "string" + } + }, + "required": [ + "importer", + "status" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_successful_import": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observations": { + "description": "Number of daily values the result is computed from.", + "type": "integer" + }, + "reasons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "reasons", + "freshness", + "coverage", + "completeness", + "gaps", + "observations" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Whether this history is complete, current and trustworthy; see DataHealth." +}
- Changed
log_measurement2 fields changed- added
Output schema / properties / measurement / properties / value / anyOfAdded value: +[ + { + "type": "number" + }, + { + "type": "null" + } +] - removed
Output schema / properties / measurement / properties / value / typeRemoved value: -"number"
- Changed
read_measurements2 fields changed- added
Output schema / properties / measurements / items / properties / value / anyOfAdded value: +[ + { + "type": "number" + }, + { + "type": "null" + } +] - removed
Output schema / properties / measurements / items / properties / value / typeRemoved value: -"number"
6 tool updates
v1.0.28- Changed
calculate_metric_trend3 fields changed- removed
Output schema / properties / claim_decisionRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.decision. Use claim.decision instead.", - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" -} - removed
Output schema / properties / evidence_profileRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.profile. Use claim.decision instead.", - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" -} - changed
Output schema / requiredPrevious value: -[ - "metric", - "range", - "trend", - "claim", - "evidence", - "evidence_profile", - "claim_decision" -]New value: +[ + "metric", + "range", + "trend", + "claim", + "evidence" +]
- Changed
compare_metric_periods3 fields changed- removed
Output schema / properties / claim_decisionRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.decision. Use claim.decision instead.", - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" -} - removed
Output schema / properties / evidence_profileRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.profile. Use claim.decision instead.", - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" -} - changed
Output schema / requiredPrevious value: -[ - "metric", - "period_a", - "period_b", - "period_a_stats", - "period_b_stats", - "claim", - "period_a_evidence", - "period_b_evidence", - "evidence_profile", - "claim_decision" -]New value: +[ + "metric", + "period_a", + "period_b", + "period_a_stats", + "period_b_stats", + "claim", + "period_a_evidence", + "period_b_evidence" +]
- Changed
detect_metric_anomalies3 fields changed- removed
Output schema / properties / claim_decisionRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.decision. Use claim.decision instead.", - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" -} - removed
Output schema / properties / evidence_profileRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.profile. Use claim.decision instead.", - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" -} - changed
Output schema / requiredPrevious value: -[ - "metric", - "range", - "threshold", - "anomalies", - "claim", - "evidence", - "evidence_profile", - "claim_decision" -]New value: +[ + "metric", + "range", + "threshold", + "anomalies", + "claim", + "evidence" +]
- Changed
explain_metric_change8 fields changed- removed
Output schema / properties / claim_decisionRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to headline_claim.decision. Use headline_claim.decision instead.", - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" -} - removed
Output schema / properties / correlated_metrics / items / properties / claim_decisionRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.decision. Use claim.decision instead.", - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" -} - removed
Output schema / properties / correlated_metrics / items / properties / evidence_profileRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.profile. Use claim.decision instead.", - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" -} - changed
Output schema / properties / correlated_metrics / items / requiredPrevious value: -[ - "metric_a", - "metric_b", - "lag_days", - "n", - "claim", - "evidence_a", - "evidence_b", - "evidence_profile", - "claim_decision" -]New value: +[ + "metric_a", + "metric_b", + "lag_days", + "n", + "claim", + "evidence_a", + "evidence_b" +] - removed
Output schema / properties / evidence_profileRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to headline_claim.profile. Use headline_claim.decision instead.", - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" -} - removed
Output schema / properties / trend_claim_decisionRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to trend_claim.decision. Use trend_claim.decision instead.", - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" -} - removed
Output schema / properties / trend_evidence_profileRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to trend_claim.profile. Use trend_claim.decision instead.", - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" -} - changed
Output schema / requiredPrevious value: -[ - "metric", - "date", - "baseline_range", - "baseline", - "is_anomaly", - "trend", - "correlated_metrics", - "narrative_facts", - "baseline_claim", - "headline_claim", - "trend_claim", - "evidence_profile", - "claim_decision", - "trend_evidence_profile", - "trend_claim_decision", - "overall_decision" -]New value: +[ + "metric", + "date", + "baseline_range", + "baseline", + "is_anomaly", + "trend", + "correlated_metrics", + "narrative_facts", + "baseline_claim", + "headline_claim", + "trend_claim", + "overall_decision" +]
- Changed
find_metric_correlation3 fields changed- removed
Output schema / properties / claim_decisionRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.decision. Use claim.decision instead.", - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" -} - removed
Output schema / properties / evidence_profileRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.profile. Use claim.decision instead.", - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" -} - changed
Output schema / requiredPrevious value: -[ - "metric_a", - "metric_b", - "lag_days", - "n", - "claim", - "evidence_a", - "evidence_b", - "evidence_profile", - "claim_decision" -]New value: +[ + "metric_a", + "metric_b", + "lag_days", + "n", + "claim", + "evidence_a", + "evidence_b" +]
- Changed
get_recent_changes3 fields changed- removed
Output schema / properties / changes / items / properties / claim_decisionRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.decision. Use claim.decision instead.", - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" -} - removed
Output schema / properties / changes / items / properties / evidence_profileRemoved value: -{ - "deprecated": true, - "description": "DEPRECATED: identical to claim.profile. Use claim.decision instead.", - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" -} - changed
Output schema / properties / changes / items / requiredPrevious value: -[ - "metric", - "kind", - "detail", - "claim", - "evidence", - "evidence_profile", - "claim_decision" -]New value: +[ + "metric", + "kind", + "detail", + "claim", + "evidence" +]
2 tool updates
v1.0.27- Changed
explain_metric_change2 fields changed- added
Output schema / properties / baseline_claimAdded value: +{ + "description": "Evidence and decision for the 90-day baseline statistics reported in \"baseline\" (and quoted in narrative_facts). Read baseline_claim.decision before stating what is typical for this metric; it is one of the components overall_decision is the weakest of.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence": { + "description": "Descriptive data coverage behind this claim.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence", + "profile", + "decision" + ], + "type": "object" +} - changed
Output schema / requiredPrevious value: -[ - "metric", - "date", - "baseline_range", - "baseline", - "is_anomaly", - "trend", - "correlated_metrics", - "narrative_facts", - "headline_claim", - "trend_claim", - "evidence_profile", - "claim_decision", - "trend_evidence_profile", - "trend_claim_decision", - "overall_decision" -]New value: +[ + "metric", + "date", + "baseline_range", + "baseline", + "is_anomaly", + "trend", + "correlated_metrics", + "narrative_facts", + "baseline_claim", + "headline_claim", + "trend_claim", + "evidence_profile", + "claim_decision", + "trend_evidence_profile", + "trend_claim_decision", + "overall_decision" +]
- Changed
get_recent_changes8 fields changed- added
Output schema / properties / changes / items / properties / claimAdded value: +{ + "description": "Evidence and decision for this change note's claim; read claim.decision before reporting it.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence": { + "description": "Descriptive data coverage behind this claim.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence", + "profile", + "decision" + ], + "type": "object" +} - added
Output schema / properties / changes / items / properties / claim_decision / deprecatedAdded value: +true - changed
Output schema / properties / changes / items / properties / claim_decision / descriptionPrevious value: -"How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it."New value: +"DEPRECATED: identical to claim.decision. Use claim.decision instead." - added
Output schema / properties / changes / items / properties / evidence / deprecatedAdded value: +true - changed
Output schema / properties / changes / items / properties / evidence / descriptionPrevious value: -"Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed."New value: +"DEPRECATED: identical to claim.evidence. Use claim.decision, not evidence.confidence." - added
Output schema / properties / changes / items / properties / evidence_profile / deprecatedAdded value: +true - changed
Output schema / properties / changes / items / properties / evidence_profile / descriptionPrevious value: -"Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate."New value: +"DEPRECATED: identical to claim.profile. Use claim.decision instead." - changed
Output schema / properties / changes / items / requiredPrevious value: -[ - "evidence_profile", - "claim_decision", - "metric", - "kind", - "detail", - "evidence" -]New value: +[ + "metric", + "kind", + "detail", + "claim", + "evidence", + "evidence_profile", + "claim_decision" +]
5 tool updates
v1.0.26- Changed
calculate_metric_trend8 fields changed- added
Output schema / properties / claimAdded value: +{ + "description": "Evidence and decision for the trend claim; read claim.decision before reporting it.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence": { + "description": "Descriptive data coverage behind this claim.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence", + "profile", + "decision" + ], + "type": "object" +} - added
Output schema / properties / claim_decision / deprecatedAdded value: +true - changed
Output schema / properties / claim_decision / descriptionPrevious value: -"How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it."New value: +"DEPRECATED: identical to claim.decision. Use claim.decision instead." - added
Output schema / properties / evidence / deprecatedAdded value: +true - changed
Output schema / properties / evidence / descriptionPrevious value: -"Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed."New value: +"DEPRECATED: identical to claim.evidence. Use claim.decision, not evidence.confidence." - added
Output schema / properties / evidence_profile / deprecatedAdded value: +true - changed
Output schema / properties / evidence_profile / descriptionPrevious value: -"Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate."New value: +"DEPRECATED: identical to claim.profile. Use claim.decision instead." - changed
Output schema / requiredPrevious value: -[ - "evidence_profile", - "claim_decision", - "metric", - "range", - "trend", - "evidence" -]New value: +[ + "metric", + "range", + "trend", + "claim", + "evidence", + "evidence_profile", + "claim_decision" +]
- Changed
compare_metric_periods10 fields changed- added
Output schema / properties / claimAdded value: +{ + "description": "Evidence and decision for the period comparison claim; read claim.decision before reporting it.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence_a": { + "description": "Descriptive data coverage behind the first source.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "evidence_b": { + "description": "Descriptive data coverage behind the second source.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...), assessed jointly across both sources where relevant. Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence_a", + "evidence_b", + "profile", + "decision" + ], + "type": "object" +} - added
Output schema / properties / claim_decision / deprecatedAdded value: +true - changed
Output schema / properties / claim_decision / descriptionPrevious value: -"How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it."New value: +"DEPRECATED: identical to claim.decision. Use claim.decision instead." - added
Output schema / properties / evidence_profile / deprecatedAdded value: +true - changed
Output schema / properties / evidence_profile / descriptionPrevious value: -"Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate."New value: +"DEPRECATED: identical to claim.profile. Use claim.decision instead." - added
Output schema / properties / period_a_evidence / deprecatedAdded value: +true - changed
Output schema / properties / period_a_evidence / descriptionPrevious value: -"Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed."New value: +"DEPRECATED: identical to claim.evidence_a. Use claim.decision, not a standalone confidence field." - added
Output schema / properties / period_b_evidence / deprecatedAdded value: +true - changed
Output schema / properties / period_b_evidence / descriptionPrevious value: -"Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed."New value: +"DEPRECATED: identical to claim.evidence_b. Use claim.decision, not a standalone confidence field." - changed
Output schema / requiredPrevious value: -[ - "evidence_profile", - "claim_decision", - "metric", - "period_a", - "period_b", - "period_a_stats", - "period_b_stats", - "period_a_evidence", - "period_b_evidence" -]New value: +[ + "metric", + "period_a", + "period_b", + "period_a_stats", + "period_b_stats", + "claim", + "period_a_evidence", + "period_b_evidence", + "evidence_profile", + "claim_decision" +]
- Changed
detect_metric_anomalies8 fields changed- added
Output schema / properties / claimAdded value: +{ + "description": "Evidence and decision for the anomaly claim; read claim.decision before reporting it.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence": { + "description": "Descriptive data coverage behind this claim.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence", + "profile", + "decision" + ], + "type": "object" +} - added
Output schema / properties / claim_decision / deprecatedAdded value: +true - changed
Output schema / properties / claim_decision / descriptionPrevious value: -"How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it."New value: +"DEPRECATED: identical to claim.decision. Use claim.decision instead." - added
Output schema / properties / evidence / deprecatedAdded value: +true - changed
Output schema / properties / evidence / descriptionPrevious value: -"Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed."New value: +"DEPRECATED: identical to claim.evidence. Use claim.decision, not evidence.confidence." - added
Output schema / properties / evidence_profile / deprecatedAdded value: +true - changed
Output schema / properties / evidence_profile / descriptionPrevious value: -"Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate."New value: +"DEPRECATED: identical to claim.profile. Use claim.decision instead." - changed
Output schema / requiredPrevious value: -[ - "evidence_profile", - "claim_decision", - "metric", - "range", - "threshold", - "anomalies", - "evidence" -]New value: +[ + "metric", + "range", + "threshold", + "anomalies", + "claim", + "evidence", + "evidence_profile", + "claim_decision" +]
- Changed
explain_metric_change35 fields changed- removed
Output schema / properties / baseline_evidenceRemoved value: -{ - "description": "Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed.", - "properties": { - "confidence": { - "type": "string" - }, - "coverage_ratio": { - "type": "number" - }, - "expected_days": { - "type": "integer" - }, - "freshness_days": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - }, - "gaps": { - "items": { - "properties": { - "days": { - "type": "integer" - }, - "end": { - "type": "string" - }, - "start": { - "type": "string" - } - }, - "required": [ - "start", - "end", - "days" - ], - "type": "object" - }, - "type": "array" - }, - "measurement_count": { - "type": "integer" - }, - "missing_days": { - "type": "integer" - }, - "observed_days": { - "type": "integer" - }, - "observed_end": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "observed_start": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "recent_gap_days": { - "type": "integer" - }, - "requested_end": { - "type": "string" - }, - "requested_start": { - "type": "string" - } - }, - "required": [ - "requested_start", - "requested_end", - "expected_days", - "observed_days", - "coverage_ratio", - "missing_days", - "measurement_count", - "gaps", - "recent_gap_days", - "confidence" - ], - "type": "object" -} - added
Output schema / properties / claim_decision / deprecatedAdded value: +true - changed
Output schema / properties / claim_decision / descriptionPrevious value: -"How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it."New value: +"DEPRECATED: identical to headline_claim.decision. Use headline_claim.decision instead." - added
Output schema / properties / correlated_metrics / items / properties / claimAdded value: +{ + "description": "Evidence and decision for the correlation claim; read claim.decision before reporting it.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence_a": { + "description": "Descriptive data coverage behind the first source.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "evidence_b": { + "description": "Descriptive data coverage behind the second source.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...), assessed jointly across both sources where relevant. Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence_a", + "evidence_b", + "profile", + "decision" + ], + "type": "object" +} - added
Output schema / properties / correlated_metrics / items / properties / claim_decision / deprecatedAdded value: +true - changed
Output schema / properties / correlated_metrics / items / properties / claim_decision / descriptionPrevious value: -"How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it."New value: +"DEPRECATED: identical to claim.decision. Use claim.decision instead." - removed
Output schema / properties / correlated_metrics / items / properties / evidence_a / anyOfRemoved value: -[ - { - "description": "Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed.", - "properties": { - "confidence": { - "type": "string" - }, - "coverage_ratio": { - "type": "number" - }, - "expected_days": { - "type": "integer" - }, - "freshness_days": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - }, - "gaps": { - "items": { - "properties": { - "days": { - "type": "integer" - }, - "end": { - "type": "string" - }, - "start": { - "type": "string" - } - }, - "required": [ - "start", - "end", - "days" - ], - "type": "object" - }, - "type": "array" - }, - "measurement_count": { - "type": "integer" - }, - "missing_days": { - "type": "integer" - }, - "observed_days": { - "type": "integer" - }, - "observed_end": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "observed_start": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "recent_gap_days": { - "type": "integer" - }, - "requested_end": { - "type": "string" - }, - "requested_start": { - "type": "string" - } - }, - "required": [ - "requested_start", - "requested_end", - "expected_days", - "observed_days", - "coverage_ratio", - "missing_days", - "measurement_count", - "gaps", - "recent_gap_days", - "confidence" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / correlated_metrics / items / properties / evidence_a / defaultRemoved value: -null - added
Output schema / properties / correlated_metrics / items / properties / evidence_a / deprecatedAdded value: +true - added
Output schema / properties / correlated_metrics / items / properties / evidence_a / descriptionAdded value: +"DEPRECATED: identical to claim.evidence_a. Use claim.decision, not a standalone confidence field." - added
Output schema / properties / correlated_metrics / items / properties / evidence_a / propertiesAdded value: +{ + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } +} - added
Output schema / properties / correlated_metrics / items / properties / evidence_a / requiredAdded value: +[ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" +] - added
Output schema / properties / correlated_metrics / items / properties / evidence_a / typeAdded value: +"object" - removed
Output schema / properties / correlated_metrics / items / properties / evidence_b / anyOfRemoved value: -[ - { - "description": "Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed.", - "properties": { - "confidence": { - "type": "string" - }, - "coverage_ratio": { - "type": "number" - }, - "expected_days": { - "type": "integer" - }, - "freshness_days": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - }, - "gaps": { - "items": { - "properties": { - "days": { - "type": "integer" - }, - "end": { - "type": "string" - }, - "start": { - "type": "string" - } - }, - "required": [ - "start", - "end", - "days" - ], - "type": "object" - }, - "type": "array" - }, - "measurement_count": { - "type": "integer" - }, - "missing_days": { - "type": "integer" - }, - "observed_days": { - "type": "integer" - }, - "observed_end": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "observed_start": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "recent_gap_days": { - "type": "integer" - }, - "requested_end": { - "type": "string" - }, - "requested_start": { - "type": "string" - } - }, - "required": [ - "requested_start", - "requested_end", - "expected_days", - "observed_days", - "coverage_ratio", - "missing_days", - "measurement_count", - "gaps", - "recent_gap_days", - "confidence" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / correlated_metrics / items / properties / evidence_b / defaultRemoved value: -null - added
Output schema / properties / correlated_metrics / items / properties / evidence_b / deprecatedAdded value: +true - added
Output schema / properties / correlated_metrics / items / properties / evidence_b / descriptionAdded value: +"DEPRECATED: identical to claim.evidence_b. Use claim.decision, not a standalone confidence field." - added
Output schema / properties / correlated_metrics / items / properties / evidence_b / propertiesAdded value: +{ + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } +} - added
Output schema / properties / correlated_metrics / items / properties / evidence_b / requiredAdded value: +[ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" +] - added
Output schema / properties / correlated_metrics / items / properties / evidence_b / typeAdded value: +"object" - added
Output schema / properties / correlated_metrics / items / properties / evidence_profile / deprecatedAdded value: +true - changed
Output schema / properties / correlated_metrics / items / properties / evidence_profile / descriptionPrevious value: -"Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate."New value: +"DEPRECATED: identical to claim.profile. Use claim.decision instead." - removed
Output schema / properties / correlated_metrics / items / properties / sample_confidenceRemoved value: -{ - "type": "string" -} - changed
Output schema / properties / correlated_metrics / items / requiredPrevious value: -[ - "evidence_profile", - "claim_decision", - "metric_a", - "metric_b", - "lag_days", - "n", - "sample_confidence" -]New value: +[ + "metric_a", + "metric_b", + "lag_days", + "n", + "claim", + "evidence_a", + "evidence_b", + "evidence_profile", + "claim_decision" +] - added
Output schema / properties / evidence_profile / deprecatedAdded value: +true - changed
Output schema / properties / evidence_profile / descriptionPrevious value: -"Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate."New value: +"DEPRECATED: identical to headline_claim.profile. Use headline_claim.decision instead." - added
Output schema / properties / headline_claimAdded value: +{ + "description": "Evidence and decision for the headline claim: this day's value against its 90-day baseline. Read headline_claim.decision before reporting it.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence": { + "description": "Descriptive data coverage behind this claim.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence", + "profile", + "decision" + ], + "type": "object" +} - added
Output schema / properties / overall_decisionAdded value: +{ + "description": "The single decision governing this whole result: weakest-of-N over the headline claim (headline_claim.decision), the trend (trend_claim.decision), and every surfaced correlation's own decision. If any component is insufficient/suggestive, the composite is too — report overall_decision.tier and must_state rather than treating the headline claim as though the trend and correlations couldn't drag it down.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" +} - added
Output schema / properties / trend_claimAdded value: +{ + "description": "Evidence and decision for the 30-day trend leading into this day, assessed separately from the headline claim. Read trend_claim.decision before reporting it.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence": { + "description": "Descriptive data coverage behind this claim.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence", + "profile", + "decision" + ], + "type": "object" +} - added
Output schema / properties / trend_claim_decision / deprecatedAdded value: +true - added
Output schema / properties / trend_claim_decision / descriptionAdded value: +"DEPRECATED: identical to trend_claim.decision. Use trend_claim.decision instead." - removed
Output schema / properties / trend_evidenceRemoved value: -{ - "description": "Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed.", - "properties": { - "confidence": { - "type": "string" - }, - "coverage_ratio": { - "type": "number" - }, - "expected_days": { - "type": "integer" - }, - "freshness_days": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - }, - "gaps": { - "items": { - "properties": { - "days": { - "type": "integer" - }, - "end": { - "type": "string" - }, - "start": { - "type": "string" - } - }, - "required": [ - "start", - "end", - "days" - ], - "type": "object" - }, - "type": "array" - }, - "measurement_count": { - "type": "integer" - }, - "missing_days": { - "type": "integer" - }, - "observed_days": { - "type": "integer" - }, - "observed_end": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "observed_start": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "recent_gap_days": { - "type": "integer" - }, - "requested_end": { - "type": "string" - }, - "requested_start": { - "type": "string" - } - }, - "required": [ - "requested_start", - "requested_end", - "expected_days", - "observed_days", - "coverage_ratio", - "missing_days", - "measurement_count", - "gaps", - "recent_gap_days", - "confidence" - ], - "type": "object" -} - added
Output schema / properties / trend_evidence_profile / deprecatedAdded value: +true - added
Output schema / properties / trend_evidence_profile / descriptionAdded value: +"DEPRECATED: identical to trend_claim.profile. Use trend_claim.decision instead." - changed
Output schema / requiredPrevious value: -[ - "evidence_profile", - "claim_decision", - "metric", - "date", - "baseline_range", - "baseline", - "is_anomaly", - "trend", - "correlated_metrics", - "narrative_facts", - "baseline_evidence", - "trend_evidence", - "trend_evidence_profile", - "trend_claim_decision" -]New value: +[ + "metric", + "date", + "baseline_range", + "baseline", + "is_anomaly", + "trend", + "correlated_metrics", + "narrative_facts", + "headline_claim", + "trend_claim", + "evidence_profile", + "claim_decision", + "trend_evidence_profile", + "trend_claim_decision", + "overall_decision" +]
- Changed
find_metric_correlation21 fields changed- added
Output schema / properties / claimAdded value: +{ + "description": "Evidence and decision for the correlation claim; read claim.decision before reporting it.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence_a": { + "description": "Descriptive data coverage behind the first source.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "evidence_b": { + "description": "Descriptive data coverage behind the second source.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...), assessed jointly across both sources where relevant. Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence_a", + "evidence_b", + "profile", + "decision" + ], + "type": "object" +} - added
Output schema / properties / claim_decision / deprecatedAdded value: +true - changed
Output schema / properties / claim_decision / descriptionPrevious value: -"How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it."New value: +"DEPRECATED: identical to claim.decision. Use claim.decision instead." - removed
Output schema / properties / evidence_a / anyOfRemoved value: -[ - { - "description": "Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed.", - "properties": { - "confidence": { - "type": "string" - }, - "coverage_ratio": { - "type": "number" - }, - "expected_days": { - "type": "integer" - }, - "freshness_days": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - }, - "gaps": { - "items": { - "properties": { - "days": { - "type": "integer" - }, - "end": { - "type": "string" - }, - "start": { - "type": "string" - } - }, - "required": [ - "start", - "end", - "days" - ], - "type": "object" - }, - "type": "array" - }, - "measurement_count": { - "type": "integer" - }, - "missing_days": { - "type": "integer" - }, - "observed_days": { - "type": "integer" - }, - "observed_end": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "observed_start": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "recent_gap_days": { - "type": "integer" - }, - "requested_end": { - "type": "string" - }, - "requested_start": { - "type": "string" - } - }, - "required": [ - "requested_start", - "requested_end", - "expected_days", - "observed_days", - "coverage_ratio", - "missing_days", - "measurement_count", - "gaps", - "recent_gap_days", - "confidence" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / evidence_a / defaultRemoved value: -null - added
Output schema / properties / evidence_a / deprecatedAdded value: +true - added
Output schema / properties / evidence_a / descriptionAdded value: +"DEPRECATED: identical to claim.evidence_a. Use claim.decision, not a standalone confidence field." - added
Output schema / properties / evidence_a / propertiesAdded value: +{ + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } +} - added
Output schema / properties / evidence_a / requiredAdded value: +[ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" +] - added
Output schema / properties / evidence_a / typeAdded value: +"object" - removed
Output schema / properties / evidence_b / anyOfRemoved value: -[ - { - "description": "Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed.", - "properties": { - "confidence": { - "type": "string" - }, - "coverage_ratio": { - "type": "number" - }, - "expected_days": { - "type": "integer" - }, - "freshness_days": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null - }, - "gaps": { - "items": { - "properties": { - "days": { - "type": "integer" - }, - "end": { - "type": "string" - }, - "start": { - "type": "string" - } - }, - "required": [ - "start", - "end", - "days" - ], - "type": "object" - }, - "type": "array" - }, - "measurement_count": { - "type": "integer" - }, - "missing_days": { - "type": "integer" - }, - "observed_days": { - "type": "integer" - }, - "observed_end": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "observed_start": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null - }, - "recent_gap_days": { - "type": "integer" - }, - "requested_end": { - "type": "string" - }, - "requested_start": { - "type": "string" - } - }, - "required": [ - "requested_start", - "requested_end", - "expected_days", - "observed_days", - "coverage_ratio", - "missing_days", - "measurement_count", - "gaps", - "recent_gap_days", - "confidence" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / evidence_b / defaultRemoved value: -null - added
Output schema / properties / evidence_b / deprecatedAdded value: +true - added
Output schema / properties / evidence_b / descriptionAdded value: +"DEPRECATED: identical to claim.evidence_b. Use claim.decision, not a standalone confidence field." - added
Output schema / properties / evidence_b / propertiesAdded value: +{ + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } +} - added
Output schema / properties / evidence_b / requiredAdded value: +[ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" +] - added
Output schema / properties / evidence_b / typeAdded value: +"object" - added
Output schema / properties / evidence_profile / deprecatedAdded value: +true - changed
Output schema / properties / evidence_profile / descriptionPrevious value: -"Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate."New value: +"DEPRECATED: identical to claim.profile. Use claim.decision instead." - removed
Output schema / properties / sample_confidenceRemoved value: -{ - "type": "string" -} - changed
Output schema / requiredPrevious value: -[ - "evidence_profile", - "claim_decision", - "metric_a", - "metric_b", - "lag_days", - "n", - "sample_confidence" -]New value: +[ + "metric_a", + "metric_b", + "lag_days", + "n", + "claim", + "evidence_a", + "evidence_b", + "evidence_profile", + "claim_decision" +]
1 tool update
v1.0.24- Changed
get_baseline4 fields changed- added
Output schema / properties / claimAdded value: +{ + "description": "Evidence and decision for the \"what's normal\" claim; read claim.decision before reporting it.", + "properties": { + "decision": { + "description": "How strongly this claim may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it.", + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + "evidence": { + "description": "Descriptive data coverage behind this claim.", + "properties": { + "confidence": { + "type": "string" + }, + "coverage_ratio": { + "type": "number" + }, + "expected_days": { + "type": "integer" + }, + "freshness_days": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null + }, + "gaps": { + "items": { + "properties": { + "days": { + "type": "integer" + }, + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end", + "days" + ], + "type": "object" + }, + "type": "array" + }, + "measurement_count": { + "type": "integer" + }, + "missing_days": { + "type": "integer" + }, + "observed_days": { + "type": "integer" + }, + "observed_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "observed_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null + }, + "recent_gap_days": { + "type": "integer" + }, + "requested_end": { + "type": "string" + }, + "requested_start": { + "type": "string" + } + }, + "required": [ + "requested_start", + "requested_end", + "expected_days", + "observed_days", + "coverage_ratio", + "missing_days", + "measurement_count", + "gaps", + "recent_gap_days", + "confidence" + ], + "type": "object" + }, + "profile": { + "description": "Per-dimension evidence quality behind this claim (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate.", + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + } + }, + "required": [ + "evidence", + "profile", + "decision" + ], + "type": "object" +} - added
Output schema / properties / evidence / deprecatedAdded value: +true - changed
Output schema / properties / evidence / descriptionPrevious value: -"Coverage/quality of the data a single-metric analytical result is\nbased on. See evidence.build_evidence for how each field is computed."New value: +"DEPRECATED: identical to claim.evidence. Use claim.decision, not evidence.confidence." - changed
Output schema / requiredPrevious value: -[ - "metric", - "range", - "baseline", - "evidence" -]New value: +[ + "metric", + "range", + "baseline", + "claim", + "evidence" +]
7 tool updates
v1.0.23- Changed
aggregate_measurements1 field changed- changed
Input schema / properties / source_priority / descriptionPrevious value: -"Ordered list of source names, e.g. [\"Apple\nWatch\", \"Garmin\"]. For any metric with more than one source\nthat day, the first name in this list that's actually present\nwins in \"aggregated\" and the other source's readings for that\nmetric are dropped from that preview. Omit to fall back to\nwhichever source was imported most recently. Never affects\n\"row\" — see above."New value: +"Ordered list of source names, e.g. [\"Apple\nWatch\", \"Garmin\"]. For any metric with more than one source\nthat day, the first name in this list that's actually present\nwins in \"aggregated\" and the other source's readings for that\nmetric are dropped from that preview. Omit to use the stored\npriority list and the same fallback the stored projection\nuses. Never affects \"row\" — see above."
- Changed
calculate_metric_trend11 fields changed- removed
Output schema / properties / claim_decision / anyOfRemoved value: -[ - { - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / claim_decision / defaultRemoved value: -null - added
Output schema / properties / claim_decision / propertiesAdded value: +{ + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } +} - added
Output schema / properties / claim_decision / requiredAdded value: +[ + "tier", + "permitted_phrasing_class", + "must_state", + "template" +] - added
Output schema / properties / claim_decision / typeAdded value: +"object" - removed
Output schema / properties / evidence_profile / anyOfRemoved value: -[ - { - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / evidence_profile / defaultRemoved value: -null - added
Output schema / properties / evidence_profile / propertiesAdded value: +{ + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } +} - added
Output schema / properties / evidence_profile / requiredAdded value: +[ + "metric", + "analysis", + "dimensions" +] - added
Output schema / properties / evidence_profile / typeAdded value: +"object" - changed
Output schema / requiredPrevious value: -[ - "metric", - "range", - "trend", - "evidence" -]New value: +[ + "evidence_profile", + "claim_decision", + "metric", + "range", + "trend", + "evidence" +]
- Changed
compare_metric_periods11 fields changed- removed
Output schema / properties / claim_decision / anyOfRemoved value: -[ - { - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / claim_decision / defaultRemoved value: -null - added
Output schema / properties / claim_decision / propertiesAdded value: +{ + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } +} - added
Output schema / properties / claim_decision / requiredAdded value: +[ + "tier", + "permitted_phrasing_class", + "must_state", + "template" +] - added
Output schema / properties / claim_decision / typeAdded value: +"object" - removed
Output schema / properties / evidence_profile / anyOfRemoved value: -[ - { - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / evidence_profile / defaultRemoved value: -null - added
Output schema / properties / evidence_profile / propertiesAdded value: +{ + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } +} - added
Output schema / properties / evidence_profile / requiredAdded value: +[ + "metric", + "analysis", + "dimensions" +] - added
Output schema / properties / evidence_profile / typeAdded value: +"object" - changed
Output schema / requiredPrevious value: -[ - "metric", - "period_a", - "period_b", - "period_a_stats", - "period_b_stats", - "period_a_evidence", - "period_b_evidence" -]New value: +[ + "evidence_profile", + "claim_decision", + "metric", + "period_a", + "period_b", + "period_a_stats", + "period_b_stats", + "period_a_evidence", + "period_b_evidence" +]
- Changed
detect_metric_anomalies11 fields changed- removed
Output schema / properties / claim_decision / anyOfRemoved value: -[ - { - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / claim_decision / defaultRemoved value: -null - added
Output schema / properties / claim_decision / propertiesAdded value: +{ + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } +} - added
Output schema / properties / claim_decision / requiredAdded value: +[ + "tier", + "permitted_phrasing_class", + "must_state", + "template" +] - added
Output schema / properties / claim_decision / typeAdded value: +"object" - removed
Output schema / properties / evidence_profile / anyOfRemoved value: -[ - { - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / evidence_profile / defaultRemoved value: -null - added
Output schema / properties / evidence_profile / propertiesAdded value: +{ + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } +} - added
Output schema / properties / evidence_profile / requiredAdded value: +[ + "metric", + "analysis", + "dimensions" +] - added
Output schema / properties / evidence_profile / typeAdded value: +"object" - changed
Output schema / requiredPrevious value: -[ - "metric", - "range", - "threshold", - "anomalies", - "evidence" -]New value: +[ + "evidence_profile", + "claim_decision", + "metric", + "range", + "threshold", + "anomalies", + "evidence" +]
- Changed
explain_metric_change32 fields changed- removed
Output schema / properties / claim_decision / anyOfRemoved value: -[ - { - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / claim_decision / defaultRemoved value: -null - added
Output schema / properties / claim_decision / propertiesAdded value: +{ + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } +} - added
Output schema / properties / claim_decision / requiredAdded value: +[ + "tier", + "permitted_phrasing_class", + "must_state", + "template" +] - added
Output schema / properties / claim_decision / typeAdded value: +"object" - removed
Output schema / properties / correlated_metrics / items / properties / claim_decision / anyOfRemoved value: -[ - { - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / correlated_metrics / items / properties / claim_decision / defaultRemoved value: -null - added
Output schema / properties / correlated_metrics / items / properties / claim_decision / propertiesAdded value: +{ + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } +} - added
Output schema / properties / correlated_metrics / items / properties / claim_decision / requiredAdded value: +[ + "tier", + "permitted_phrasing_class", + "must_state", + "template" +] - added
Output schema / properties / correlated_metrics / items / properties / claim_decision / typeAdded value: +"object" - removed
Output schema / properties / correlated_metrics / items / properties / evidence_profile / anyOfRemoved value: -[ - { - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / correlated_metrics / items / properties / evidence_profile / defaultRemoved value: -null - added
Output schema / properties / correlated_metrics / items / properties / evidence_profile / propertiesAdded value: +{ + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } +} - added
Output schema / properties / correlated_metrics / items / properties / evidence_profile / requiredAdded value: +[ + "metric", + "analysis", + "dimensions" +] - added
Output schema / properties / correlated_metrics / items / properties / evidence_profile / typeAdded value: +"object" - changed
Output schema / properties / correlated_metrics / items / requiredPrevious value: -[ - "metric_a", - "metric_b", - "lag_days", - "n", - "sample_confidence" -]New value: +[ + "evidence_profile", + "claim_decision", + "metric_a", + "metric_b", + "lag_days", + "n", + "sample_confidence" +] - removed
Output schema / properties / evidence_profile / anyOfRemoved value: -[ - { - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / evidence_profile / defaultRemoved value: -null - added
Output schema / properties / evidence_profile / propertiesAdded value: +{ + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } +} - added
Output schema / properties / evidence_profile / requiredAdded value: +[ + "metric", + "analysis", + "dimensions" +] - added
Output schema / properties / evidence_profile / typeAdded value: +"object" - removed
Output schema / properties / trend_claim_decision / anyOfRemoved value: -[ - { - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / trend_claim_decision / defaultRemoved value: -null - added
Output schema / properties / trend_claim_decision / propertiesAdded value: +{ + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } +} - added
Output schema / properties / trend_claim_decision / requiredAdded value: +[ + "tier", + "permitted_phrasing_class", + "must_state", + "template" +] - added
Output schema / properties / trend_claim_decision / typeAdded value: +"object" - removed
Output schema / properties / trend_evidence_profile / anyOfRemoved value: -[ - { - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / trend_evidence_profile / defaultRemoved value: -null - added
Output schema / properties / trend_evidence_profile / propertiesAdded value: +{ + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } +} - added
Output schema / properties / trend_evidence_profile / requiredAdded value: +[ + "metric", + "analysis", + "dimensions" +] - added
Output schema / properties / trend_evidence_profile / typeAdded value: +"object" - changed
Output schema / requiredPrevious value: -[ - "metric", - "date", - "baseline_range", - "baseline", - "is_anomaly", - "trend", - "correlated_metrics", - "narrative_facts", - "baseline_evidence", - "trend_evidence" -]New value: +[ + "evidence_profile", + "claim_decision", + "metric", + "date", + "baseline_range", + "baseline", + "is_anomaly", + "trend", + "correlated_metrics", + "narrative_facts", + "baseline_evidence", + "trend_evidence", + "trend_evidence_profile", + "trend_claim_decision" +]
- Changed
find_metric_correlation11 fields changed- removed
Output schema / properties / claim_decision / anyOfRemoved value: -[ - { - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / claim_decision / defaultRemoved value: -null - added
Output schema / properties / claim_decision / propertiesAdded value: +{ + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } +} - added
Output schema / properties / claim_decision / requiredAdded value: +[ + "tier", + "permitted_phrasing_class", + "must_state", + "template" +] - added
Output schema / properties / claim_decision / typeAdded value: +"object" - removed
Output schema / properties / evidence_profile / anyOfRemoved value: -[ - { - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / evidence_profile / defaultRemoved value: -null - added
Output schema / properties / evidence_profile / propertiesAdded value: +{ + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } +} - added
Output schema / properties / evidence_profile / requiredAdded value: +[ + "metric", + "analysis", + "dimensions" +] - added
Output schema / properties / evidence_profile / typeAdded value: +"object" - changed
Output schema / requiredPrevious value: -[ - "metric_a", - "metric_b", - "lag_days", - "n", - "sample_confidence" -]New value: +[ + "evidence_profile", + "claim_decision", + "metric_a", + "metric_b", + "lag_days", + "n", + "sample_confidence" +]
- Changed
get_recent_changes11 fields changed- removed
Output schema / properties / changes / items / properties / claim_decision / anyOfRemoved value: -[ - { - "properties": { - "must_state": { - "items": { - "type": "string" - }, - "type": "array" - }, - "permitted_phrasing_class": { - "type": "string" - }, - "template": { - "type": "string" - }, - "tier": { - "type": "string" - } - }, - "required": [ - "tier", - "permitted_phrasing_class", - "must_state", - "template" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / changes / items / properties / claim_decision / defaultRemoved value: -null - added
Output schema / properties / changes / items / properties / claim_decision / propertiesAdded value: +{ + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } +} - added
Output schema / properties / changes / items / properties / claim_decision / requiredAdded value: +[ + "tier", + "permitted_phrasing_class", + "must_state", + "template" +] - added
Output schema / properties / changes / items / properties / claim_decision / typeAdded value: +"object" - removed
Output schema / properties / changes / items / properties / evidence_profile / anyOfRemoved value: -[ - { - "properties": { - "analysis": { - "type": "string" - }, - "dimensions": { - "items": { - "properties": { - "can_block": { - "default": true, - "type": "boolean" - }, - "details": { - "additionalProperties": true, - "type": "object" - }, - "dimension": { - "enum": [ - "sample", - "temporal", - "robustness", - "missingness", - "practical", - "measurement_validity", - "provenance" - ], - "type": "string" - }, - "reason_codes": { - "items": { - "type": "string" - }, - "type": "array" - }, - "status": { - "enum": [ - "adequate", - "negligible", - "not_assessed", - "weak", - "concern", - "blocking" - ], - "type": "string" - } - }, - "required": [ - "dimension", - "status" - ], - "type": "object" - }, - "type": "array" - }, - "effect": { - "additionalProperties": true, - "type": "object" - }, - "metric": { - "type": "string" - } - }, - "required": [ - "metric", - "analysis", - "dimensions" - ], - "type": "object" - }, - { - "type": "null" - } -] - removed
Output schema / properties / changes / items / properties / evidence_profile / defaultRemoved value: -null - added
Output schema / properties / changes / items / properties / evidence_profile / propertiesAdded value: +{ + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } +} - added
Output schema / properties / changes / items / properties / evidence_profile / requiredAdded value: +[ + "metric", + "analysis", + "dimensions" +] - added
Output schema / properties / changes / items / properties / evidence_profile / typeAdded value: +"object" - changed
Output schema / properties / changes / items / requiredPrevious value: -[ - "metric", - "kind", - "detail", - "evidence" -]New value: +[ + "evidence_profile", + "claim_decision", + "metric", + "kind", + "detail", + "evidence" +]
6 tool updates
v1.0.20- Changed
calculate_metric_trend2 fields changed- added
Output schema / properties / claim_decisionAdded value: +{ + "anyOf": [ + { + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it." +} - added
Output schema / properties / evidence_profileAdded value: +{ + "anyOf": [ + { + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate." +}
- Changed
compare_metric_periods2 fields changed- added
Output schema / properties / claim_decisionAdded value: +{ + "anyOf": [ + { + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it." +} - added
Output schema / properties / evidence_profileAdded value: +{ + "anyOf": [ + { + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate." +}
- Changed
detect_metric_anomalies2 fields changed- added
Output schema / properties / claim_decisionAdded value: +{ + "anyOf": [ + { + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it." +} - added
Output schema / properties / evidence_profileAdded value: +{ + "anyOf": [ + { + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate." +}
- Changed
explain_metric_change6 fields changed- added
Output schema / properties / claim_decisionAdded value: +{ + "anyOf": [ + { + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it." +} - added
Output schema / properties / correlated_metrics / items / properties / claim_decisionAdded value: +{ + "anyOf": [ + { + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it." +} - added
Output schema / properties / correlated_metrics / items / properties / evidence_profileAdded value: +{ + "anyOf": [ + { + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate." +} - added
Output schema / properties / evidence_profileAdded value: +{ + "anyOf": [ + { + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate." +} - added
Output schema / properties / trend_claim_decisionAdded value: +{ + "anyOf": [ + { + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null +} - added
Output schema / properties / trend_evidence_profileAdded value: +{ + "anyOf": [ + { + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null +}
- Changed
find_metric_correlation2 fields changed- added
Output schema / properties / claim_decisionAdded value: +{ + "anyOf": [ + { + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it." +} - added
Output schema / properties / evidence_profileAdded value: +{ + "anyOf": [ + { + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate." +}
- Changed
get_recent_changes2 fields changed- added
Output schema / properties / changes / items / properties / claim_decisionAdded value: +{ + "anyOf": [ + { + "properties": { + "must_state": { + "items": { + "type": "string" + }, + "type": "array" + }, + "permitted_phrasing_class": { + "type": "string" + }, + "template": { + "type": "string" + }, + "tier": { + "type": "string" + } + }, + "required": [ + "tier", + "permitted_phrasing_class", + "must_state", + "template" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "How strongly this result may be stated. tier is insufficient, suggestive, detectable_not_meaningful or supported; every entry in must_state has to be mentioned when reporting it." +} - added
Output schema / properties / changes / items / properties / evidence_profileAdded value: +{ + "anyOf": [ + { + "properties": { + "analysis": { + "type": "string" + }, + "dimensions": { + "items": { + "properties": { + "can_block": { + "default": true, + "type": "boolean" + }, + "details": { + "additionalProperties": true, + "type": "object" + }, + "dimension": { + "enum": [ + "sample", + "temporal", + "robustness", + "missingness", + "practical", + "measurement_validity", + "provenance" + ], + "type": "string" + }, + "reason_codes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "status": { + "enum": [ + "adequate", + "negligible", + "not_assessed", + "weak", + "concern", + "blocking" + ], + "type": "string" + } + }, + "required": [ + "dimension", + "status" + ], + "type": "object" + }, + "type": "array" + }, + "effect": { + "additionalProperties": true, + "type": "object" + }, + "metric": { + "type": "string" + } + }, + "required": [ + "metric", + "analysis", + "dimensions" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Per-dimension evidence quality behind this result (sample, temporal, missingness, ...). Dimensions without an evaluator yet are 'not_assessed' and cap the claim, never count as adequate." +}
TDQS
Scored across 20 tools
The tool descriptions carefully carve out boundaries between similar-looking operations: daily metric vs. raw measurement vs. workout session, broad reads vs. metric-specific reads, and baseline vs. trend vs. anomaly vs. period comparison vs. full explanation. The explicit 'use this when / do not use this when' guidance makes selection unambiguous even across the analytics tools.
Every tool uses snake_case with a clear verb-first pattern (log_, read_, get_, clear_, export_, aggregate_, find_, detect_, calculate_, compare_, explain_). The vocabulary is predictable enough that an agent can infer the resource/action from the name.
Twenty tools is on the higher side, but the surface is well-scoped to a real quantified-self health domain with logging, reading, exporting, data-quality checks, and multiple analytics operations. Most tools earn their place, though the analytics cluster is dense enough that a smaller consolidated surface could be argued for.
Core lifecycle coverage is present: logging, clearing, reading daily aggregates, raw measurements, workout sessions, export, import status, data status, and a full analytics suite. Minor gaps remain around editing/deleting individual measurements or workout sessions and triggering imports, but the main agent workflows are covered.
Maintenance
Related MCP Connectors
Personal finance, bank account, and shared memory connector for Claude, ChatGPT, Gemini Spark & more
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Your personal data for AI — Telegram, bank, courses, Zoom & more, scoped to you.
Your labs, wearables, DNA and notes as one health record your AI agent can read (OAuth 2.1).
Related MCP Servers
- AlicenseAqualityAmaintenanceAn MCP server that allows users to query and analyze their Apple Health data using SQL and natural language, utilizing DuckDB for fast and efficient health data analysis.399 npm575MIT
- AlicenseNot gradedqualityDmaintenanceLoads Apple Health export data into a local SQLite database and exposes tools to query health metrics and workout records via natural language.3MIT
- AlicenseNot gradedqualityDmaintenanceEnables querying personal data synced from services like Lunch Money and Strava using SQL via Claude.12 npm1MIT
- AlicenseBqualityDmaintenanceEnables AI agents to interact with local SQLite databases with full CRUD, schema introspection, foreign key relations, generated columns, and multi-format import/export (CSV, JSON, XLSX) through natural language.269 npmMIT