What happened
The first two bootstrap dispatches of Live Ghost content smoke on main failed with schema-drift: run 32368632595 and run 32372419243. The failure is deterministic across both runs and is not credential- or transport-related: both runs authenticated and read 2xx JSON.
Classification (maintainer-led local investigation, aggregates only)
The first posts page from the approved origin (fields=html&formats=html&limit=100&page=1, Accept-Version: v6.0) returns htmlTypes: {"null": 8, "string": 92} with healthy pagination (137 posts over 2 pages). All eight null-html items have visibility: "public" — empty-bodied published posts, not restricted content. The smoke's schema layer currently requires a string html for every item, so every dispatch fails regardless of key or timing.
Why this is a contract amendment, not a hot-fix
Empty published posts are mutable editorial content, and the smoke contract requires editorial drift to be reported, not fatal. The pinned assertion "a string html value for every item" contradicts live Ghost Content API behaviour: html is null for empty published posts, and equally for members-only and paid posts on sites that have them.
Proposed amendment (reviewed change)
Tolerate html: null items in the schema layer, count them per resource, and report the count as a new aggregate row in the job summary. Null-html items contribute no structural signature and are never logged individually. Any other non-string html value remains fatal schema-drift. Update the offline synthetic-page tests and the smoke contract document accordingly.
Once amended, the smoke summary itself becomes the complete census of null-html items across all pages of both resources.
Downstream evidence for #221 and #222
The deep fragmenter contract treats html as a required Ghost field (null fails as INVALID_GHOST_CONTENT), and the deprecated wrapper throws a native TypeError on non-string html. A complete CLI run against a site with empty published posts would therefore fail the whole batch. The adoption decisions should settle whether Ghost html: null maps to the fallback-record path, is skipped, or remains a validation failure. #238 proposes making that choice publisher-facing for gated content.
Sequencing
Blocks #219: the baseline cannot be recorded from a failing run. Bootstrap resumes after this amendment merges and a fresh dispatch returns ok.
What happened
The first two bootstrap dispatches of
Live Ghost content smokeonmainfailed withschema-drift: run 32368632595 and run 32372419243. The failure is deterministic across both runs and is not credential- or transport-related: both runs authenticated and read 2xx JSON.Classification (maintainer-led local investigation, aggregates only)
The first posts page from the approved origin (
fields=html&formats=html&limit=100&page=1,Accept-Version: v6.0) returnshtmlTypes: {"null": 8, "string": 92}with healthy pagination (137 posts over 2 pages). All eight null-htmlitems havevisibility: "public"— empty-bodied published posts, not restricted content. The smoke's schema layer currently requires a stringhtmlfor every item, so every dispatch fails regardless of key or timing.Why this is a contract amendment, not a hot-fix
Empty published posts are mutable editorial content, and the smoke contract requires editorial drift to be reported, not fatal. The pinned assertion "a string
htmlvalue for every item" contradicts live Ghost Content API behaviour:htmlisnullfor empty published posts, and equally for members-only and paid posts on sites that have them.Proposed amendment (reviewed change)
Tolerate
html: nullitems in the schema layer, count them per resource, and report the count as a new aggregate row in the job summary. Null-htmlitems contribute no structural signature and are never logged individually. Any other non-stringhtmlvalue remains fatalschema-drift. Update the offline synthetic-page tests and the smoke contract document accordingly.Once amended, the smoke summary itself becomes the complete census of null-
htmlitems across all pages of both resources.Downstream evidence for #221 and #222
The deep fragmenter contract treats
htmlas a required Ghost field (nullfails asINVALID_GHOST_CONTENT), and the deprecated wrapper throws a nativeTypeErroron non-stringhtml. A complete CLI run against a site with empty published posts would therefore fail the whole batch. The adoption decisions should settle whether Ghosthtml: nullmaps to the fallback-record path, is skipped, or remains a validation failure. #238 proposes making that choice publisher-facing for gated content.Sequencing
Blocks #219: the baseline cannot be recorded from a failing run. Bootstrap resumes after this amendment merges and a fresh dispatch returns
ok.