diff --git a/build/transform_json_sections.ts b/build/transform_json_sections.ts index daf7512007..65ea758bad 100644 --- a/build/transform_json_sections.ts +++ b/build/transform_json_sections.ts @@ -47,10 +47,16 @@ interface CodeExample { } interface PageJsonInput { + // Emitted by the Hugo templates and carried through untouched. Declared so the + // spread below preserves them explicitly rather than by accident: schema_version is + // what consumers gate re-parsing on, and since is the only version information the + // feed carries. + schema_version?: number; id: string; title: string; url: string; summary: string; + since?: string; content?: string; tags: string[]; last_updated: string; @@ -60,10 +66,12 @@ interface PageJsonInput { type PageType = 'content' | 'index'; interface PageJsonOutput { + schema_version?: number; id: string; title: string; url: string; summary: string; + since?: string; page_type: PageType; content_hash?: string; tags: string[]; diff --git a/config.toml b/config.toml index bd7c208cde..480907858b 100644 --- a/config.toml +++ b/config.toml @@ -62,6 +62,17 @@ anchor = "smart" tagManagerId = "GTM-TKZ6J9R" gitHubRepo = "https://github.com/redis/docs" +# Schema version for the AI-facing JSON and Markdown outputs. Emitted as +# `schema_version` in each per-page JSON record and in the Markdown metadata block. +# +# Increment this ONLY when the shape of a record changes: a field added, removed or +# renamed, or a new value entering the `role` vocabulary. It must NOT change when page +# content changes -- consumers gate re-parsing on it, and a version that moves with +# content is a second content hash, which they will learn to ignore. +# +# Changing what a field *contains* is not a shape change and does not bump this. +aiSchemaVersion = 1 + # Display and sort order for client examples clientsExamples = ["Python", "Node.js", "ioredis", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C", "C#-Sync (NRedisStack)", "C#-Async (NRedisStack)", "C#-Sync (SE.Redis)", "C#-Async (SE.Redis)", "RedisVL", "PHP", "Ruby", "Rust-Sync", "Rust-Async"] searchService = "/convai/api/search-service" diff --git a/content/ai-agent-resources.md b/content/ai-agent-resources.md index 6ae34a4aee..b5c579f26f 100644 --- a/content/ai-agent-resources.md +++ b/content/ai-agent-resources.md @@ -65,16 +65,29 @@ Two consequences worth knowing if you diff the feed against the sitemap: - Both figures move. The feed is rebuilt at least daily and the corpus grows, so treat any page count as a snapshot. +### Schema version + +Every record carries a `schema_version` integer, and the same value appears in the +`json metadata` block of the Markdown output. It is currently **1**. + +It increments only when the **shape** of a record changes: a field added, removed or +renamed, or a new value entering the [role vocabulary](#section-roles). It does **not** +change when page content changes, and it does not change when the value inside a field +changes without the field itself changing. Use `content_hash` to detect content changes; +use `schema_version` to detect when your parser might need attention. + ### JSON schema Each document contains: | Field | Type | Description | |-------|------|-------------| +| `schema_version` | integer | Version of the record format. See [Schema version](#schema-version). | | `id` | string | Unique identifier, the page's path without a file extension (for example `develop/clients/redis-py`) | | `title` | string | Page title | | `url` | string | Canonical URL | | `summary` | string | Short description | +| `since` | string | Redis version the command was introduced in. Present on command pages only. | | `page_type` | string | `"content"` (has prose) or `"index"` (navigation only) | | `content_hash` | string | SHA256 hash for cache invalidation (content pages only) | | `sections` | array | Content split by headings with semantic roles | diff --git a/layouts/_default/section.json b/layouts/_default/section.json index f88dafde72..95915770b7 100644 --- a/layouts/_default/section.json +++ b/layouts/_default/section.json @@ -22,10 +22,12 @@ {{- end -}} { + "schema_version": {{ site.Params.aiSchemaVersion | jsonify }}, "id": {{ $id | jsonify }}, "title": {{ .Title | jsonify }}, "url": {{ .Permalink | jsonify }}, - "summary": {{ $summary | jsonify }}, + "summary": {{ $summary | jsonify }},{{ with .Params.since }} + "since": {{ . | jsonify }},{{ end }} "content": {{ $content | jsonify }}, "tags": {{ $tags | jsonify }}, "last_updated": {{ $lastUpdated | jsonify }}, diff --git a/layouts/_default/section.md b/layouts/_default/section.md index 800ebf5e4b..139c2741f6 100644 --- a/layouts/_default/section.md +++ b/layouts/_default/section.md @@ -2,6 +2,7 @@ ```json metadata { + "schema_version": {{ site.Params.aiSchemaVersion | jsonify }}, "title": {{ .Title | jsonify }}, "description": {{ (.Params.description | default .Description) | plainify | replaceRE "\\s+" " " | strings.TrimSpace | jsonify }}, "categories": {{ .Params.categories | jsonify }}{{ if .Params.arguments }}, diff --git a/layouts/_default/single.json b/layouts/_default/single.json index a9325cbf43..30727f7fed 100644 --- a/layouts/_default/single.json +++ b/layouts/_default/single.json @@ -11,10 +11,12 @@ {{- $lastUpdated := .Lastmod.Format "2006-01-02T15:04:05Z07:00" -}} { + "schema_version": {{ site.Params.aiSchemaVersion | jsonify }}, "id": {{ $id | jsonify }}, "title": {{ .Title | jsonify }}, "url": {{ .Permalink | jsonify }}, - "summary": {{ $summary | jsonify }}, + "summary": {{ $summary | jsonify }},{{ with .Params.since }} + "since": {{ . | jsonify }},{{ end }} "content": {{ $content | jsonify }}, "tags": {{ $tags | jsonify }}, "last_updated": {{ $lastUpdated | jsonify }} diff --git a/layouts/_default/single.md b/layouts/_default/single.md index 800ebf5e4b..139c2741f6 100644 --- a/layouts/_default/single.md +++ b/layouts/_default/single.md @@ -2,6 +2,7 @@ ```json metadata { + "schema_version": {{ site.Params.aiSchemaVersion | jsonify }}, "title": {{ .Title | jsonify }}, "description": {{ (.Params.description | default .Description) | plainify | replaceRE "\\s+" " " | strings.TrimSpace | jsonify }}, "categories": {{ .Params.categories | jsonify }}{{ if .Params.arguments }},