Advertise truthful formats for unmarked datetimes and timestamps
Problem/Motivation
Two schema advertisements undersell or mis-state what their inputs accept, both pinned with comments in the schema matrix (#3583001 (closed)):
Unmarked datetime_iso8601 advertises format: "date" on 11.1+ cores. Core's DateTimeIso8601Normalizer emits date (its date-only field case), and the tool normalizer only overrides the format when a DateOnly/DateTime marker constraint is present. Without a marker, the core-path schema says "send a bare date" while the coercion subscriber accepts and re-emits full datetimes as canonical ISO 8601 — and the legacy (pre-11.1) path advertises date-time for the same definition, so the two paths contradict each other.
Timestamps advertise string-only on 11.1+ cores. Core normalizes timestamps to RFC 3339 strings, so the schema is {"type": ["string", "null"], "format": "date-time"}. The coercion subscriber happily converts integer seconds — the most natural spelling of a timestamp — but a strict invoker (the MCP bridge validates arguments against the advertised schema before Drupal is reached) rejects a bare integer at the gate, so that spelling is unreachable over MCP.
Steps to reproduce
- Normalize the input schema of
schema_matrix_tool(tool_test) on a 11.1+ core. - Observe
datetime_bareadvertisesformat: "date"whileplain_timestampadvertises string-only. - Call a bridged tool with an integer for a timestamp input — the SDK gate rejects it with "Expected
string|null".
Expected behavior
- An unmarked datetime advertises
format: "date-time"on both paths — the superset of what it accepts, consistent with the coercion behavior and with the legacy path. - A timestamp advertises
{"type": ["string", "integer", "null"], "format": "date-time"}so both the RFC 3339 spelling and integer seconds pass the gate (JSON Schema appliesformatto string instances only, so the union is valid).
Actual behavior
The core path advertises date for unmarked datetimes (contradicting the legacy path and the coercion contract), and integer timestamps are gate-rejected despite being fully supported at runtime.
Proposed Resolution
In ContextDefinitionNormalizer::getNormalizationSchema():
- For
datetime_iso8601without a marker constraint, setformat: "date-time"explicitly instead of inheriting core'sdate. - For
timestampon the core path, widen the type to["string", "integer"](null branch appended by the existing optional handling) and keep thedate-timeformat annotation and the Unix-seconds description note.
Both changes are prompt-visible wire-contract changes; the schema matrix expectations change with them, which is the intended review surface. The round-trip acceptance property already proves integer timestamps and full datetimes are accepted at runtime, so both changes only bring the advertisement in line with reality.
AI usage (if applicable)
- AI Assisted Issue: This issue was generated with AI assistance, but was reviewed and refined by the creator.
- AI Assisted Code: This code was mainly generated by a human, with AI autocompleting or parts AI generated, but under full human supervision.
- AI Generated Code: This code was mainly generated by an AI with human guidance, and reviewed, tested, and refined by a human.
- Vibe Coded: This code was generated by an AI and has only been functionally tested.