From 434fe5bd4298403b30594acd071b9c59d6761191 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Thu, 6 Aug 2026 14:02:49 +0000 Subject: [PATCH 01/11] docs: add automated what's new highlights The homepage featured topics were static and did not surface newly released Docker capabilities. Add data-driven highlights, a strict curation agent, validation, and a weekly pull request workflow. --- .github/agents/whats-new.yaml | 144 ++++++++++++++++++++++ .github/workflows/update-whats-new.yml | 138 +++++++++++++++++++++ content/_index.md | 9 +- data/whats-new.json | 22 ++++ hack/validate-whats-new.mjs | 79 ++++++++++++ layouts/_partials/whats-new.html | 47 +++++++ layouts/_shortcodes/whats-new.html | 1 + layouts/_shortcodes/whats-new.markdown.md | 9 ++ layouts/home.html | 38 +----- 9 files changed, 442 insertions(+), 45 deletions(-) create mode 100644 .github/agents/whats-new.yaml create mode 100644 .github/workflows/update-whats-new.yml create mode 100644 data/whats-new.json create mode 100644 hack/validate-whats-new.mjs create mode 100644 layouts/_partials/whats-new.html create mode 100644 layouts/_shortcodes/whats-new.html create mode 100644 layouts/_shortcodes/whats-new.markdown.md diff --git a/.github/agents/whats-new.yaml b/.github/agents/whats-new.yaml new file mode 100644 index 000000000000..7a2c636d98ba --- /dev/null +++ b/.github/agents/whats-new.yaml @@ -0,0 +1,144 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/docker/docker-agent/refs/heads/main/cagent-schema.json +models: + claude-sonnet: + provider: anthropic + model: claude-sonnet-4-5 + max_tokens: 8192 + temperature: 0.1 + +agents: + root: + model: claude-sonnet + description: Curates user-facing Docker launches from recently published documentation + add_prompt_files: + - AGENTS.md + - STYLE.md + instruction: | + You are the editor of the What's new section on the Docker documentation + homepage. Review documentation pull requests merged during the period in + the user prompt and replace the contents of `data/whats-new.json` with + the launches worth highlighting. + + Docker publishes documentation when a feature or enhancement is released. + Treat merged documentation as the source of truth for publication. Your + task is to distinguish a newly released user-facing capability from work + that only changes the documentation. + + ## Editorial posture + + Approach every candidate skeptically. The default decision is to exclude + it. Include an item only when the changed documentation provides direct + evidence that it meets every inclusion criterion. A quiet period with no + highlights is valid. Never lower the bar to produce a fuller list. + + Judge candidates independently. Do not seek variety across products, + teams, or feature types. Do not add, remove, split, combine, or reorder + items to make the list look balanced. Several or all highlights may come + from one product when that reflects what shipped. + + ## Inclusion criteria + + Include a change only when all of the following are true: + + 1. It introduces a user-facing feature, materially expands what users can + do with an existing feature, or moves a feature into a broader + released availability state. + 2. A user familiar with the product before this publication period would + learn about a capability or material enhancement that was not + available to them before. + 3. The changed documentation explains the released behavior, not only a + plan, preview of future behavior, limitation, workaround, correction, + or previously undocumented behavior. + 4. A specific published documentation page is a useful destination for a + user who wants to understand or use the change. + 5. The title and description can be supported directly by the merged + documentation without assumptions or marketing claims. + + Material enhancements include substantial new workflows, integrations, + configuration surfaces, or controls. Small options, minor convenience + improvements, and changes whose value is primarily cosmetic do not meet + the bar. + + ## Exclusions + + Exclude a change when its primary effect is any of the following: + + - Correcting, clarifying, or refreshing existing documentation + - Adding troubleshooting, examples, or guidance for an existing feature + - Restructuring, renaming, moving, or rewriting content + - Changing navigation, formatting, style, metadata, or search terms + - Fixing links, typos, grammar, or build failures + - Updating documentation infrastructure, tests, dependencies, or tooling + - Syncing generated or vendored reference content + - Bumping a version or recording routine release notes without a + qualifying feature or material enhancement + - Documenting an existing limitation, prerequisite, workaround, or + security boundary + - Publishing a new guide for a capability that was already available + + A large pull request, release, or rewrite is not inherently noteworthy. + Inspect its substance and include only independently qualifying launches. + Do not treat additions, changed-file counts, labels, author identity, or + product popularity as evidence of significance. + + ## List size + + Three to 10 items is the preferred range for a typical publication + period, not a quota. Include one or two when only one or two qualify. + Produce an empty `items` list when none qualify. If more than 10 qualify, + keep the 10 with the greatest user impact, based on the breadth of users + affected and the size of the newly available capability. Product variety + is not a selection factor. + + Create one item per independently useful launch. Combine multiple pull + requests that document the same launch. A single release-notes pull + request may yield multiple items only when it documents multiple distinct + launches that each meet every criterion. + + ## Procedure + + 1. Read `data/whats-new.json` to understand its schema. + 2. List every pull request merged in the requested period with + `gh pr list --repo docker/docs --state merged --search + 'merged:START..END' --limit 200`. Replace `START` and `END` with the + dates from the user prompt. Do not begin selecting until you have the + complete candidate set. + 3. Inspect the files and diff for every plausible candidate. Read the + resulting documentation pages before deciding. + 4. Apply the inclusion criteria and exclusions to each candidate. + 5. Replace `period_start`, `period_end`, and `items` in + `data/whats-new.json`. Sort items by `published` date, newest first. + 6. Write `.pr-body.md` with the publication period, selected highlights + and their source pull requests, and a concise list of plausible but + rejected candidates with the exclusion that applied. + + Each item must contain: + + - `product`: Canonical Docker product or feature name + - `title`: A concise description of the new capability + - `description`: One factual sentence stating what users can do + - `url`: The published internal documentation URL + - `published`: The merge date in `YYYY-MM-DD` format + - `source_prs`: One or more merged pull request numbers + + Write factual, restrained copy. Avoid superlatives, promotional language, + and claims about ease or importance. Do not modify any tracked file other + than `data/whats-new.json`. + + toolsets: + - type: filesystem + tools: + - read_file + - read_multiple_files + - write_file + - list_directory + - directory_tree + - type: shell + +permissions: + allow: + - shell:cmd=gh pr list --* + - shell:cmd=gh pr view --* + - shell:cmd=gh pr diff --* + - shell:cmd=git diff --* + - shell:cmd=git log --* diff --git a/.github/workflows/update-whats-new.yml b/.github/workflows/update-whats-new.yml new file mode 100644 index 000000000000..20ae14381fc8 --- /dev/null +++ b/.github/workflows/update-whats-new.yml @@ -0,0 +1,138 @@ +name: Update What's New + +on: + schedule: + # Review the previous Monday through Sunday each Monday at 06:00 UTC. + - cron: "0 6 * * 1" + workflow_dispatch: + inputs: + dry-run: + description: "Propose highlights without opening a pull request" + type: boolean + default: false + +permissions: + contents: write + pull-requests: write + id-token: write + +concurrency: + group: update-whats-new + cancel-in-progress: false + +env: + BRANCH_NAME: bot/update-whats-new + +jobs: + update: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repository + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 + with: + fetch-depth: 0 + + - name: Set publication period + id: period + run: | + PERIOD_END=$(date -u -d 'last sunday' +%F) + echo "start=$(date -u -d "$PERIOD_END - 6 days" +%F)" >> "$GITHUB_OUTPUT" + echo "end=$PERIOD_END" >> "$GITHUB_OUTPUT" + + - name: Configure AWS credentials + id: aws-credentials + continue-on-error: true + uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1 + with: + role-to-assume: arn:aws:iam::710015040892:role/docker-agent-action-20260409141318957000000001 + aws-region: us-east-1 + + - name: Fetch bot token + if: steps.aws-credentials.outcome == 'success' + run: | + PAT=$(aws secretsmanager get-secret-value \ + --secret-id docker-agent-action/github-app \ + --query SecretString \ + --output text | jq -r '.pat') + echo "::add-mask::$PAT" + echo "GITHUB_APP_TOKEN=$PAT" >> "$GITHUB_ENV" + + - name: Curate highlights + uses: docker/docker-agent-action@e96a4bb40cac114f64358621e1d08346c8eadc8c # v2.0.1 + env: + GH_TOKEN: ${{ env.GITHUB_APP_TOKEN || github.token }} + with: + agent: ${{ github.workspace }}/.github/agents/whats-new.yaml + prompt: >- + Review documentation pull requests merged from + ${{ steps.period.outputs.start }} through + ${{ steps.period.outputs.end }}, inclusive, and curate the What's + new data as described in your instructions. + anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} + github-token: ${{ env.GITHUB_APP_TOKEN || github.token }} + timeout: 1200 + + - name: Verify agent changes + env: + PERIOD_START: ${{ steps.period.outputs.start }} + PERIOD_END: ${{ steps.period.outputs.end }} + run: | + CHANGED=$(git status --short | awk '$2 != "data/whats-new.json" && $2 != ".pr-body.md" { print }') + if [ -n "$CHANGED" ]; then + echo "::error::Agent changed files outside its allowed scope" + echo "$CHANGED" + exit 1 + fi + test -f .pr-body.md + npx prettier --check data/whats-new.json + node hack/validate-whats-new.mjs data/whats-new.json "$PERIOD_START" "$PERIOD_END" + + - name: Show proposal + if: inputs.dry-run == true + run: | + git diff -- data/whats-new.json + cat .pr-body.md + + - name: Detect changes + id: changes + if: inputs.dry-run != true + run: | + if git diff --quiet -- data/whats-new.json; then + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + + - name: Commit changes + if: steps.changes.outputs.changed == 'true' + env: + PERIOD_END: ${{ steps.period.outputs.end }} + run: | + git checkout -B "$BRANCH_NAME" + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add data/whats-new.json + git commit -m "docs: update what's new for $PERIOD_END" + + - name: Create or update pull request + if: steps.changes.outputs.changed == 'true' + env: + GH_TOKEN: ${{ env.GITHUB_APP_TOKEN || github.token }} + run: | + gh auth setup-git + EXISTING_PR=$(gh pr list --state open --head "$BRANCH_NAME" --json url --jq '.[0].url // empty') + + if [ -n "$EXISTING_PR" ]; then + git push --force --set-upstream origin "$BRANCH_NAME" + gh pr edit "$EXISTING_PR" \ + --title "docs: update what's new" \ + --body-file .pr-body.md + else + git push --set-upstream origin "$BRANCH_NAME" + gh pr create \ + --title "docs: update what's new" \ + --body-file .pr-body.md \ + --base main \ + --head "$BRANCH_NAME" + fi diff --git a/content/_index.md b/content/_index.md index e78e0a1cc0ea..3c9e13e3044d 100644 --- a/content/_index.md +++ b/content/_index.md @@ -16,14 +16,7 @@ reference material for everyday development and operations tasks. - [Manuals](/manuals/): Install, configure, and use Docker products. - [Reference](/reference/): Browse CLI, API, and file format documentation. -## Featured topics - -- [Docker Hardened Images](/dhi/) -- [Get started with Docker Sandboxes](/ai/sandboxes/get-started/) -- [Docker Desktop overview](/desktop/) -- [Install Docker Engine](/engine/install/) -- [Dockerfile reference](/reference/dockerfile/) -- [Docker Build overview](/build/) +{{< whats-new >}} ## Common questions diff --git a/data/whats-new.json b/data/whats-new.json new file mode 100644 index 000000000000..dbf19de696d5 --- /dev/null +++ b/data/whats-new.json @@ -0,0 +1,22 @@ +{ + "period_start": "2026-07-28", + "period_end": "2026-08-03", + "items": [ + { + "product": "Docker Engine", + "title": "Mount files from container images", + "description": "Mount files or directories from another image without copying them into the container image.", + "url": "/engine/storage/image-mounts/", + "published": "2026-08-03", + "source_prs": [25486] + }, + { + "product": "Docker Sandboxes", + "title": "Export AI Governance audit events", + "description": "Search and export policy decisions, or stream audit events to a SIEM system.", + "url": "/ai/sandboxes/governance/audit/view-export/", + "published": "2026-07-31", + "source_prs": [25679] + } + ] +} diff --git a/hack/validate-whats-new.mjs b/hack/validate-whats-new.mjs new file mode 100644 index 000000000000..5199cec22279 --- /dev/null +++ b/hack/validate-whats-new.mjs @@ -0,0 +1,79 @@ +#!/usr/bin/env node + +import fs from "node:fs"; + +const [path, expectedStart, expectedEnd] = process.argv.slice(2); +if (!expectedEnd) { + throw new Error(`usage: ${process.argv[1]} FILE START END`); +} + +const data = JSON.parse(fs.readFileSync(path, "utf8")); +const requiredItemKeys = [ + "product", + "title", + "description", + "url", + "published", + "source_prs", +]; + +if (data.period_start !== expectedStart) { + throw new Error(`period_start must be ${expectedStart}`); +} +if (data.period_end !== expectedEnd) { + throw new Error(`period_end must be ${expectedEnd}`); +} +if (!Array.isArray(data.items)) { + throw new Error("items must be an array"); +} +if (data.items.length > 10) { + throw new Error("items must contain no more than 10 highlights"); +} + +for (const [index, item] of data.items.entries()) { + const missing = requiredItemKeys.filter((key) => !(key in item)); + if (missing.length > 0) { + throw new Error(`item ${index + 1} is missing: ${missing.join(", ")}`); + } + + for (const key of requiredItemKeys.slice(0, 4)) { + if (typeof item[key] !== "string" || item[key].trim() === "") { + throw new Error(`item ${index + 1} has an empty ${key}`); + } + } + + if (!item.url.startsWith("/") || item.url.startsWith("/manuals/")) { + throw new Error(`item ${index + 1} url must be an internal published URL`); + } + if ( + typeof item.published !== "string" || + !/^\d{4}-\d{2}-\d{2}$/.test(item.published) || + new Date(`${item.published}T00:00:00Z`).toISOString().slice(0, 10) !== + item.published + ) { + throw new Error(`item ${index + 1} has an invalid published date`); + } + if (item.published < data.period_start || item.published > data.period_end) { + throw new Error(`item ${index + 1} published date is outside the period`); + } + if ( + !Array.isArray(item.source_prs) || + item.source_prs.length === 0 || + !item.source_prs.every((number) => Number.isInteger(number) && number > 0) + ) { + throw new Error( + `item ${index + 1} source_prs must contain pull request numbers`, + ); + } +} + +const publishedDates = data.items.map((item) => item.published); +const sortedDates = [...publishedDates].sort().reverse(); +if (publishedDates.join() !== sortedDates.join()) { + throw new Error("items must be sorted by published date, newest first"); +} + +const identities = data.items.map((item) => `${item.title}\0${item.url}`); +if (new Set(identities).size !== identities.length) { + throw new Error("items must not contain duplicate titles and URLs"); +} diff --git a/layouts/_partials/whats-new.html b/layouts/_partials/whats-new.html new file mode 100644 index 000000000000..56db1a7b74c7 --- /dev/null +++ b/layouts/_partials/whats-new.html @@ -0,0 +1,47 @@ +{{- $data := index hugo.Data "whats-new" -}} +{{- with $data.items -}} +
+
+

+ What's new +

+ +
+
+{{- end -}} diff --git a/layouts/_shortcodes/whats-new.html b/layouts/_shortcodes/whats-new.html new file mode 100644 index 000000000000..d0a1ca7b7920 --- /dev/null +++ b/layouts/_shortcodes/whats-new.html @@ -0,0 +1 @@ +{{ partial "whats-new.html" . }} diff --git a/layouts/_shortcodes/whats-new.markdown.md b/layouts/_shortcodes/whats-new.markdown.md new file mode 100644 index 000000000000..9689ff97dace --- /dev/null +++ b/layouts/_shortcodes/whats-new.markdown.md @@ -0,0 +1,9 @@ +{{- $data := index hugo.Data "whats-new" -}} +{{- with $data.items }} + +## What's new + +{{ range . }} +{{ printf "- [%s: %s](%s): %s (%s)\n" .product .title .url .description (.published | time.Format "Jan 2, 2006") -}} +{{ end }} +{{- end }} diff --git a/layouts/home.html b/layouts/home.html index a5f86f937e5c..1ae662409121 100644 --- a/layouts/home.html +++ b/layouts/home.html @@ -116,43 +116,7 @@ - -
-
-

- Featured topics -

-
- {{ range slice - (dict "url" "/dhi/" "title" "Docker Hardened Images") - (dict "url" "/ai/sandboxes/get-started/" "title" "Get started with Docker Sandboxes") - (dict "url" "/desktop/" "title" "Docker Desktop overview") - (dict "url" "/engine/install/" "title" "Install Docker Engine") - (dict "url" "/reference/dockerfile/" "title" "Dockerfile reference") - (dict "url" "/build/" "title" "Docker Build overview") - }} - - {{ .title }} - - {{ partialCached "icon" "arrow-right" "arrow-right" }} - - - {{ end }} -
-
-
+ {{ partial "whats-new.html" . }} From 52f33b4e1774a88c9ae4d480eaca9c58aa361c88 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Thu, 6 Aug 2026 14:34:04 +0000 Subject: [PATCH 02/11] ci: review what's new highlights daily The initial automation reviewed a fixed Monday-to-Sunday period only once per week. Run it daily over the previous seven complete UTC days, preserve pending proposals, and avoid pull requests for metadata-only window changes. --- .github/agents/whats-new.yaml | 5 ++++ .github/workflows/update-whats-new.yml | 33 ++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/.github/agents/whats-new.yaml b/.github/agents/whats-new.yaml index 7a2c636d98ba..f636b34aef3e 100644 --- a/.github/agents/whats-new.yaml +++ b/.github/agents/whats-new.yaml @@ -36,6 +36,11 @@ agents: items to make the list look balanced. Several or all highlights may come from one product when that reflects what shipped. + Preserve the copy for an existing highlight while it remains in the + publication window and still qualifies. Rewrite it only when newly merged + documentation makes the existing copy inaccurate or incomplete. Do not + rewrite continuing highlights for freshness, variety, or style. + ## Inclusion criteria Include a change only when all of the following are true: diff --git a/.github/workflows/update-whats-new.yml b/.github/workflows/update-whats-new.yml index 20ae14381fc8..1f50a18bcfdd 100644 --- a/.github/workflows/update-whats-new.yml +++ b/.github/workflows/update-whats-new.yml @@ -2,8 +2,8 @@ name: Update What's New on: schedule: - # Review the previous Monday through Sunday each Monday at 06:00 UTC. - - cron: "0 6 * * 1" + # Review the previous seven complete UTC days every day at 06:00 UTC. + - cron: "0 6 * * *" workflow_dispatch: inputs: dry-run: @@ -36,7 +36,7 @@ jobs: - name: Set publication period id: period run: | - PERIOD_END=$(date -u -d 'last sunday' +%F) + PERIOD_END=$(date -u -d 'yesterday' +%F) echo "start=$(date -u -d "$PERIOD_END - 6 days" +%F)" >> "$GITHUB_OUTPUT" echo "end=$PERIOD_END" >> "$GITHUB_OUTPUT" @@ -58,6 +58,16 @@ jobs: echo "::add-mask::$PAT" echo "GITHUB_APP_TOKEN=$PAT" >> "$GITHUB_ENV" + - name: Restore open proposal + env: + GH_TOKEN: ${{ env.GITHUB_APP_TOKEN || github.token }} + run: | + EXISTING_PR=$(gh pr list --state open --head "$BRANCH_NAME" --json number --jq '.[0].number // empty') + if [ -n "$EXISTING_PR" ]; then + git fetch origin "$BRANCH_NAME:refs/remotes/origin/$BRANCH_NAME" + git show "origin/$BRANCH_NAME:data/whats-new.json" > data/whats-new.json + fi + - name: Curate highlights uses: docker/docker-agent-action@e96a4bb40cac114f64358621e1d08346c8eadc8c # v2.0.1 env: @@ -98,12 +108,25 @@ jobs: id: changes if: inputs.dry-run != true run: | - if git diff --quiet -- data/whats-new.json; then + if cmp -s \ + <(git show HEAD:data/whats-new.json | jq -S '.items') \ + <(jq -S '.items' data/whats-new.json); then echo "changed=false" >> "$GITHUB_OUTPUT" else echo "changed=true" >> "$GITHUB_OUTPUT" fi + - name: Close obsolete pull request + if: steps.changes.outputs.changed == 'false' + env: + GH_TOKEN: ${{ env.GITHUB_APP_TOKEN || github.token }} + run: | + EXISTING_PR=$(gh pr list --state open --head "$BRANCH_NAME" --json url --jq '.[0].url // empty') + if [ -n "$EXISTING_PR" ]; then + gh pr close "$EXISTING_PR" \ + --comment "The latest sliding-window review no longer proposes changes to the published highlights." + fi + - name: Commit changes if: steps.changes.outputs.changed == 'true' env: @@ -129,7 +152,7 @@ jobs: --title "docs: update what's new" \ --body-file .pr-body.md else - git push --set-upstream origin "$BRANCH_NAME" + git push --force --set-upstream origin "$BRANCH_NAME" gh pr create \ --title "docs: update what's new" \ --body-file .pr-body.md \ From 1a371bc245da03e2460b019ddd2c63b1d799961b Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Thu, 6 Aug 2026 14:39:55 +0000 Subject: [PATCH 03/11] ci: use Claude Sonnet 5 for highlights The curator copied an arbitrary 8192-token cap and an outdated schema modeline from the nightly scanner. Use Claude Sonnet 5, set a task-sized 4096-token response cap, and point YAML tooling at agent-schema.json. --- .github/agents/whats-new.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/agents/whats-new.yaml b/.github/agents/whats-new.yaml index f636b34aef3e..de976bc85888 100644 --- a/.github/agents/whats-new.yaml +++ b/.github/agents/whats-new.yaml @@ -1,14 +1,14 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/docker/docker-agent/refs/heads/main/cagent-schema.json +# yaml-language-server: $schema=https://raw.githubusercontent.com/docker/docker-agent/refs/heads/main/agent-schema.json models: - claude-sonnet: + claude-sonnet-5: provider: anthropic - model: claude-sonnet-4-5 - max_tokens: 8192 + model: claude-sonnet-5 + max_tokens: 4096 temperature: 0.1 agents: root: - model: claude-sonnet + model: claude-sonnet-5 description: Curates user-facing Docker launches from recently published documentation add_prompt_files: - AGENTS.md From 96e5b66de1a7d388108e4b9c167bc199d8773a46 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Thu, 6 Aug 2026 15:07:27 +0000 Subject: [PATCH 04/11] docs: refresh what's new seed data The initial two-item seed used an older publication window and did not demonstrate release-note or multi-PR highlights. Curate the latest seven-day window into four qualifying launches and permit substantive features found in vendored syncs. --- .github/agents/whats-new.yaml | 3 ++- data/whats-new.json | 34 +++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/.github/agents/whats-new.yaml b/.github/agents/whats-new.yaml index de976bc85888..367c89d4d13d 100644 --- a/.github/agents/whats-new.yaml +++ b/.github/agents/whats-new.yaml @@ -74,7 +74,8 @@ agents: - Changing navigation, formatting, style, metadata, or search terms - Fixing links, typos, grammar, or build failures - Updating documentation infrastructure, tests, dependencies, or tooling - - Syncing generated or vendored reference content + - Syncing generated or vendored reference content without a qualifying + feature or material enhancement - Bumping a version or recording routine release notes without a qualifying feature or material enhancement - Documenting an existing limitation, prerequisite, workaround, or diff --git a/data/whats-new.json b/data/whats-new.json index dbf19de696d5..98ff721bd9a9 100644 --- a/data/whats-new.json +++ b/data/whats-new.json @@ -1,22 +1,38 @@ { - "period_start": "2026-07-28", - "period_end": "2026-08-03", + "period_start": "2026-07-30", + "period_end": "2026-08-05", "items": [ + { + "product": "Docker AI Governance", + "title": "Search and forward audit events", + "description": "Search and export policy decisions from Docker Cloud, or forward events to Splunk, Dynatrace, and custom HTTPS endpoints.", + "url": "/ai/sandboxes/governance/audit/", + "published": "2026-08-03", + "source_prs": [25679, 25687] + }, + { + "product": "Docker Desktop", + "title": "Install from the Microsoft Store without administrator privileges", + "description": "Fresh Microsoft Store installations on Windows use per-user mode by default.", + "url": "/desktop/release-notes/#4850", + "published": "2026-08-03", + "source_prs": [25665] + }, { "product": "Docker Engine", "title": "Mount files from container images", - "description": "Mount files or directories from another image without copying them into the container image.", + "description": "Mount tools or read-only assets from another image without rebuilding the container image.", "url": "/engine/storage/image-mounts/", "published": "2026-08-03", "source_prs": [25486] }, { - "product": "Docker Sandboxes", - "title": "Export AI Governance audit events", - "description": "Search and export policy decisions, or stream audit events to a SIEM system.", - "url": "/ai/sandboxes/governance/audit/view-export/", - "published": "2026-07-31", - "source_prs": [25679] + "product": "Docker Engine", + "title": "Use Unix sockets on Windows", + "description": "Configure the Docker daemon and CLI on Windows to communicate over a Unix socket.", + "url": "/engine/daemon/#listen-on-a-unix-socket-on-windows", + "published": "2026-08-03", + "source_prs": [25660] } ] } From 5b90fe30583624d11366385fd4c0c8df1335a220 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Mon, 10 Aug 2026 06:57:20 +0000 Subject: [PATCH 05/11] docs: refine what's new timeline --- hack/validate-whats-new.mjs | 11 ++-- layouts/_partials/whats-new.html | 92 ++++++++++++++++++++------------ 2 files changed, 67 insertions(+), 36 deletions(-) diff --git a/hack/validate-whats-new.mjs b/hack/validate-whats-new.mjs index 5199cec22279..8143d405d0b6 100644 --- a/hack/validate-whats-new.mjs +++ b/hack/validate-whats-new.mjs @@ -73,7 +73,12 @@ if (publishedDates.join() !== sortedDates.join()) { throw new Error("items must be sorted by published date, newest first"); } -const identities = data.items.map((item) => `${item.title}\0${item.url}`); -if (new Set(identities).size !== identities.length) { - throw new Error("items must not contain duplicate titles and URLs"); +const titles = data.items.map((item) => item.title); +if (new Set(titles).size !== titles.length) { + throw new Error("items must not contain duplicate titles"); +} + +const urls = data.items.map((item) => item.url); +if (new Set(urls).size !== urls.length) { + throw new Error("items must not contain duplicate URLs"); } diff --git a/layouts/_partials/whats-new.html b/layouts/_partials/whats-new.html index 56db1a7b74c7..84cd6c47a7fa 100644 --- a/layouts/_partials/whats-new.html +++ b/layouts/_partials/whats-new.html @@ -1,47 +1,73 @@ {{- $data := index hugo.Data "whats-new" -}} {{- with $data.items -}} -
-
-

+
+
- What's new -

- +
{{- end -}} From ba10cc33bf1f1a7e168e6efbd0026d9a09c32df8 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Mon, 10 Aug 2026 07:00:26 +0000 Subject: [PATCH 06/11] ci: remove unused what's new shortcode --- layouts/_shortcodes/whats-new.html | 1 - 1 file changed, 1 deletion(-) delete mode 100644 layouts/_shortcodes/whats-new.html diff --git a/layouts/_shortcodes/whats-new.html b/layouts/_shortcodes/whats-new.html deleted file mode 100644 index d0a1ca7b7920..000000000000 --- a/layouts/_shortcodes/whats-new.html +++ /dev/null @@ -1 +0,0 @@ -{{ partial "whats-new.html" . }} From ddc1ba70cb6af1b8ee03b86c94f071d96df7947e Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Mon, 10 Aug 2026 07:08:13 +0000 Subject: [PATCH 07/11] docs: show dates for all what's new items --- layouts/_partials/whats-new.html | 39 +++++++++----------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/layouts/_partials/whats-new.html b/layouts/_partials/whats-new.html index 84cd6c47a7fa..c69ad4b9951c 100644 --- a/layouts/_partials/whats-new.html +++ b/layouts/_partials/whats-new.html @@ -2,33 +2,19 @@ {{- with $data.items -}}
-
+

What's new

-

- -

    - {{- $previousDate := "" -}} {{ range . }}
  1. - {{ if ne .published $previousDate }} - - {{ else }} - - {{ end }} + class="mb-1 flex flex-wrap items-center gap-x-2 text-sm font-medium text-blue-600 dark:text-blue-400" > {{ .product }} - {{ if ne .published $previousDate }} - - {{ end }} + >
  2. - {{- $previousDate = .published -}} {{ end }}
From 58a532124ba5dd826bcd9ebd21741c562939f6ae Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Mon, 10 Aug 2026 07:19:53 +0000 Subject: [PATCH 08/11] docs: refresh what's new seed data --- data/whats-new.json | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/data/whats-new.json b/data/whats-new.json index 98ff721bd9a9..cc49af42560a 100644 --- a/data/whats-new.json +++ b/data/whats-new.json @@ -1,7 +1,31 @@ { - "period_start": "2026-07-30", - "period_end": "2026-08-05", + "period_start": "2026-08-03", + "period_end": "2026-08-09", "items": [ + { + "product": "Docker Sandboxes", + "title": "Connect sandboxes through an MCP gateway", + "description": "Register local or remote MCP servers on the host, reuse them across sandboxes, and govern server and tool access with Cedar policies.", + "url": "/ai/sandboxes/mcp-gateway/", + "published": "2026-08-06", + "source_prs": [25559, 25707] + }, + { + "product": "Docker Sandboxes", + "title": "Author version 2 sandbox kits", + "description": "Define kit setup, permissions, networking, and API key or OAuth credential requirements with the version 2 kit schema.", + "url": "/ai/sandboxes/customize/kit-reference/#schema-versions", + "published": "2026-08-06", + "source_prs": [25467, 25707] + }, + { + "product": "Docker Sandboxes", + "title": "Run Claude Code with local models", + "description": "Experimental support routes Claude Code sandbox requests to the bundled llmman server or an existing Ollama installation.", + "url": "/ai/sandboxes/agents/claude-code/#use-a-local-model", + "published": "2026-08-06", + "source_prs": [25641, 25707] + }, { "product": "Docker AI Governance", "title": "Search and forward audit events", From b750b94d7020f3da08642baef85b879d2dd5731d Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Wed, 12 Aug 2026 14:53:01 +0000 Subject: [PATCH 09/11] docs: expand what's new to a monthly timeline Curate a rolling 30-day launch archive while keeping five highlights visible on the homepage. Tighten the agent prompt, validate featured entries, and refresh the seed data. --- .github/agents/whats-new.yaml | 141 +++++++++---------------- .github/workflows/update-whats-new.yml | 4 +- data/whats-new.json | 74 +++++++++---- hack/validate-whats-new.mjs | 16 ++- layouts/_partials/whats-new.html | 70 +++++++++++- 5 files changed, 186 insertions(+), 119 deletions(-) diff --git a/.github/agents/whats-new.yaml b/.github/agents/whats-new.yaml index 367c89d4d13d..41ca67606c59 100644 --- a/.github/agents/whats-new.yaml +++ b/.github/agents/whats-new.yaml @@ -15,108 +15,66 @@ agents: - STYLE.md instruction: | You are the editor of the What's new section on the Docker documentation - homepage. Review documentation pull requests merged during the period in - the user prompt and replace the contents of `data/whats-new.json` with - the launches worth highlighting. - - Docker publishes documentation when a feature or enhancement is released. - Treat merged documentation as the source of truth for publication. Your - task is to distinguish a newly released user-facing capability from work - that only changes the documentation. - - ## Editorial posture - - Approach every candidate skeptically. The default decision is to exclude - it. Include an item only when the changed documentation provides direct - evidence that it meets every inclusion criterion. A quiet period with no - highlights is valid. Never lower the bar to produce a fuller list. - - Judge candidates independently. Do not seek variety across products, - teams, or feature types. Do not add, remove, split, combine, or reorder - items to make the list look balanced. Several or all highlights may come - from one product when that reflects what shipped. - - Preserve the copy for an existing highlight while it remains in the - publication window and still qualifies. Rewrite it only when newly merged - documentation makes the existing copy inaccurate or incomplete. Do not - rewrite continuing highlights for freshness, variety, or style. - - ## Inclusion criteria - - Include a change only when all of the following are true: - - 1. It introduces a user-facing feature, materially expands what users can - do with an existing feature, or moves a feature into a broader - released availability state. - 2. A user familiar with the product before this publication period would - learn about a capability or material enhancement that was not - available to them before. - 3. The changed documentation explains the released behavior, not only a - plan, preview of future behavior, limitation, workaround, correction, - or previously undocumented behavior. - 4. A specific published documentation page is a useful destination for a - user who wants to understand or use the change. - 5. The title and description can be supported directly by the merged - documentation without assumptions or marketing claims. - - Material enhancements include substantial new workflows, integrations, - configuration surfaces, or controls. Small options, minor convenience - improvements, and changes whose value is primarily cosmetic do not meet - the bar. + homepage. Review documentation pull requests merged during the requested + period and replace `data/whats-new.json` with a curated record of + noteworthy Docker launches. Documentation is the source of truth that a + capability shipped, but a documentation change is not itself news. + + Include an item only when the merged documentation directly shows all of + the following: + + - A released user-facing feature, material enhancement, or broader + availability milestone that was not available before the period + - A substantial capability or workflow, not merely new syntax or a small + control within an existing workflow + - Enough Docker-wide editorial significance to merit proactively telling + users about it outside product release notes + - A useful published page and factual title and description + + Apply a high bar. The result is a curated launch archive, not a complete + changelog. A specialized feature can qualify when its user impact is + substantial. A quiet period can produce few or no items. ## Exclusions - Exclude a change when its primary effect is any of the following: - - - Correcting, clarifying, or refreshing existing documentation - - Adding troubleshooting, examples, or guidance for an existing feature - - Restructuring, renaming, moving, or rewriting content - - Changing navigation, formatting, style, metadata, or search terms - - Fixing links, typos, grammar, or build failures - - Updating documentation infrastructure, tests, dependencies, or tooling - - Syncing generated or vendored reference content without a qualifying - feature or material enhancement - - Bumping a version or recording routine release notes without a - qualifying feature or material enhancement - - Documenting an existing limitation, prerequisite, workaround, or - security boundary - - Publishing a new guide for a capability that was already available - - A large pull request, release, or rewrite is not inherently noteworthy. - Inspect its substance and include only independently qualifying launches. - Do not treat additions, changed-file counts, labels, author identity, or - product popularity as evidence of significance. - - ## List size - - Three to 10 items is the preferred range for a typical publication - period, not a quota. Include one or two when only one or two qualify. - Produce an empty `items` list when none qualify. If more than 10 qualify, - keep the 10 with the greatest user impact, based on the breadth of users - affected and the size of the newly available capability. Product variety - is not a selection factor. - - Create one item per independently useful launch. Combine multiple pull - requests that document the same launch. A single release-notes pull - request may yield multiple items only when it documents multiple distinct - launches that each meet every criterion. + Exclude documentation maintenance; fixes; rewrites; new guidance for old + behavior; routine release or generated-content syncs; limitations, + prerequisites, and workarounds; narrow flags, settings, command variants, + protocols, and compatibility changes; incremental UI, safety, + permissions, or observability improvements; and lower-level Engine, + Build, networking, or storage changes. These qualify only when they are + part of an independently newsworthy product-level launch. + + Judge the user outcome, not PR size, product popularity, labels, changed + lines, a dedicated page, or the existence of a new API or command. + + ## Coverage and featured highlights + + Include every qualifying launch; do not impose a quota. Mark the five + most important as `featured: true`, or all items when fewer than five + qualify. Rank by the magnitude and distinctness of the user outcome and + the value of helping its audience discover it. Breadth can matter, but a + major capability for a specialized audience can outrank a smaller change + for a broad audience. Recency and product variety are not ranking goals. + + Create one item per launch and combine PRs that document the same launch. + Preserve existing copy while it remains accurate and qualifies. Change + featured status only when the relative importance of the candidate set + changes. ## Procedure - 1. Read `data/whats-new.json` to understand its schema. - 2. List every pull request merged in the requested period with + 1. Read `data/whats-new.json`. + 2. List every PR merged in the requested period with `gh pr list --repo docker/docs --state merged --search 'merged:START..END' --limit 200`. Replace `START` and `END` with the - dates from the user prompt. Do not begin selecting until you have the - complete candidate set. - 3. Inspect the files and diff for every plausible candidate. Read the - resulting documentation pages before deciding. - 4. Apply the inclusion criteria and exclusions to each candidate. + requested dates. + 3. Inspect the diff and resulting pages for every plausible candidate. + 4. Decide what qualifies using only evidence in the merged documentation. 5. Replace `period_start`, `period_end`, and `items` in `data/whats-new.json`. Sort items by `published` date, newest first. 6. Write `.pr-body.md` with the publication period, selected highlights - and their source pull requests, and a concise list of plausible but - rejected candidates with the exclusion that applied. + and source PRs, plus concise reasons for plausible exclusions. Each item must contain: @@ -126,6 +84,7 @@ agents: - `url`: The published internal documentation URL - `published`: The merge date in `YYYY-MM-DD` format - `source_prs`: One or more merged pull request numbers + - `featured`: Whether the item is one of the five highest-impact launches Write factual, restrained copy. Avoid superlatives, promotional language, and claims about ease or importance. Do not modify any tracked file other diff --git a/.github/workflows/update-whats-new.yml b/.github/workflows/update-whats-new.yml index 1f50a18bcfdd..d3ff6494e27f 100644 --- a/.github/workflows/update-whats-new.yml +++ b/.github/workflows/update-whats-new.yml @@ -2,7 +2,7 @@ name: Update What's New on: schedule: - # Review the previous seven complete UTC days every day at 06:00 UTC. + # Review the previous 30 complete UTC days every day at 06:00 UTC. - cron: "0 6 * * *" workflow_dispatch: inputs: @@ -37,7 +37,7 @@ jobs: id: period run: | PERIOD_END=$(date -u -d 'yesterday' +%F) - echo "start=$(date -u -d "$PERIOD_END - 6 days" +%F)" >> "$GITHUB_OUTPUT" + echo "start=$(date -u -d "$PERIOD_END - 29 days" +%F)" >> "$GITHUB_OUTPUT" echo "end=$PERIOD_END" >> "$GITHUB_OUTPUT" - name: Configure AWS credentials diff --git a/data/whats-new.json b/data/whats-new.json index cc49af42560a..0277ac5b85c3 100644 --- a/data/whats-new.json +++ b/data/whats-new.json @@ -1,14 +1,24 @@ { - "period_start": "2026-08-03", - "period_end": "2026-08-09", + "period_start": "2026-07-13", + "period_end": "2026-08-11", "items": [ + { + "product": "Docker Desktop", + "title": "Use Docker VMM on Mac and Windows", + "description": "Run Docker Desktop with Docker's container-optimized hypervisor on supported Mac and Windows systems.", + "url": "/desktop/features/vmm/", + "published": "2026-08-10", + "source_prs": [25702, 25726], + "featured": true + }, { "product": "Docker Sandboxes", "title": "Connect sandboxes through an MCP gateway", "description": "Register local or remote MCP servers on the host, reuse them across sandboxes, and govern server and tool access with Cedar policies.", "url": "/ai/sandboxes/mcp-gateway/", "published": "2026-08-06", - "source_prs": [25559, 25707] + "source_prs": [25559, 25707], + "featured": true }, { "product": "Docker Sandboxes", @@ -16,15 +26,17 @@ "description": "Define kit setup, permissions, networking, and API key or OAuth credential requirements with the version 2 kit schema.", "url": "/ai/sandboxes/customize/kit-reference/#schema-versions", "published": "2026-08-06", - "source_prs": [25467, 25707] + "source_prs": [25467, 25707], + "featured": false }, { "product": "Docker Sandboxes", "title": "Run Claude Code with local models", - "description": "Experimental support routes Claude Code sandbox requests to the bundled llmman server or an existing Ollama installation.", + "description": "Route Claude Code sandbox requests to the bundled local-model server or an existing Ollama installation.", "url": "/ai/sandboxes/agents/claude-code/#use-a-local-model", "published": "2026-08-06", - "source_prs": [25641, 25707] + "source_prs": [25641, 25707], + "featured": false }, { "product": "Docker AI Governance", @@ -32,7 +44,8 @@ "description": "Search and export policy decisions from Docker Cloud, or forward events to Splunk, Dynatrace, and custom HTTPS endpoints.", "url": "/ai/sandboxes/governance/audit/", "published": "2026-08-03", - "source_prs": [25679, 25687] + "source_prs": [25679, 25687], + "featured": true }, { "product": "Docker Desktop", @@ -40,23 +53,44 @@ "description": "Fresh Microsoft Store installations on Windows use per-user mode by default.", "url": "/desktop/release-notes/#4850", "published": "2026-08-03", - "source_prs": [25665] + "source_prs": [25665], + "featured": false }, { - "product": "Docker Engine", - "title": "Mount files from container images", - "description": "Mount tools or read-only assets from another image without rebuilding the container image.", - "url": "/engine/storage/image-mounts/", - "published": "2026-08-03", - "source_prs": [25486] + "product": "Docker Sandboxes", + "title": "Share agent skills across sandboxes", + "description": "Import skills from supported host agents into a persistent store that sandboxes can share.", + "url": "/ai/sandboxes/workflows/#share-agent-skills", + "published": "2026-07-24", + "source_prs": [25588], + "featured": false }, { - "product": "Docker Engine", - "title": "Use Unix sockets on Windows", - "description": "Configure the Docker daemon and CLI on Windows to communicate over a Unix socket.", - "url": "/engine/daemon/#listen-on-a-unix-socket-on-windows", - "published": "2026-08-03", - "source_prs": [25660] + "product": "Docker Sandboxes", + "title": "Connect editors and desktop apps over SSH", + "description": "Use a sandbox from VS Code, Cursor, Claude Desktop, ChatGPT, or another SSH-capable tool.", + "url": "/ai/sandboxes/integrations/", + "published": "2026-07-24", + "source_prs": [25557], + "featured": true + }, + { + "product": "Docker Hardened Images", + "title": "Query the DHI catalog from AI assistants", + "description": "Search DHI repositories, inspect images, retrieve SBOMs, check CVEs, and manage mirrors through the DHI MCP server.", + "url": "/dhi/tools/mcp/", + "published": "2026-07-23", + "source_prs": [25589], + "featured": false + }, + { + "product": "Docker Enterprise", + "title": "Authenticate GitHub Actions with OIDC connections", + "description": "Exchange GitHub OIDC tokens for short-lived access to Docker resources without storing long-lived workflow credentials.", + "url": "/enterprise/security/oidc-connections/", + "published": "2026-07-21", + "source_prs": [25336], + "featured": true } ] } diff --git a/hack/validate-whats-new.mjs b/hack/validate-whats-new.mjs index 8143d405d0b6..e4e7e0548150 100644 --- a/hack/validate-whats-new.mjs +++ b/hack/validate-whats-new.mjs @@ -15,6 +15,7 @@ const requiredItemKeys = [ "url", "published", "source_prs", + "featured", ]; if (data.period_start !== expectedStart) { @@ -26,10 +27,6 @@ if (data.period_end !== expectedEnd) { if (!Array.isArray(data.items)) { throw new Error("items must be an array"); } -if (data.items.length > 10) { - throw new Error("items must contain no more than 10 highlights"); -} - for (const [index, item] of data.items.entries()) { const missing = requiredItemKeys.filter((key) => !(key in item)); if (missing.length > 0) { @@ -65,6 +62,17 @@ for (const [index, item] of data.items.entries()) { `item ${index + 1} source_prs must contain pull request numbers`, ); } + if (typeof item.featured !== "boolean") { + throw new Error(`item ${index + 1} featured must be a boolean`); + } +} + +const featuredCount = data.items.filter((item) => item.featured).length; +const expectedFeaturedCount = Math.min(5, data.items.length); +if (featuredCount !== expectedFeaturedCount) { + throw new Error( + `items must contain ${expectedFeaturedCount} featured highlights`, + ); } const publishedDates = data.items.map((item) => item.published); diff --git a/layouts/_partials/whats-new.html b/layouts/_partials/whats-new.html index c69ad4b9951c..94ab37c60a9d 100644 --- a/layouts/_partials/whats-new.html +++ b/layouts/_partials/whats-new.html @@ -1,6 +1,8 @@ {{- $data := index hugo.Data "whats-new" -}} {{- with $data.items -}} -
+ {{- $featured := where . "featured" true -}} + {{- $more := where . "featured" false -}} +

@@ -8,7 +10,7 @@

    - {{ range . }} + {{ range $featured }}
  1. {{ end }} + {{ range $more }} +
  2. + + + + + {{ .product }} + + + + {{ .title }} + + {{ partialCached "icon" "arrow-right" "arrow-right" }} + + + {{ .description }} + +
  3. + {{ end }}
+ {{ with $more }} + + {{ end }}
{{- end -}} From 0c8617edc09f592baffcd65c6a3156a021d77339 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Wed, 12 Aug 2026 15:07:07 +0000 Subject: [PATCH 10/11] ci: package what's new curation as a skill Move the reusable editorial workflow out of the scheduled agent configuration. Keep the reviewed monthly result and flexible selection criteria as a regression example outside runtime context. --- .agents/skills/curate-whats-new/SKILL.md | 74 ++++++++++++++ .../curate-whats-new/agents/openai.yaml | 4 + .../2026-07-13--2026-08-11.json | 96 +++++++++++++++++++ .../2026-07-13--2026-08-11.yaml | 39 ++++++++ .github/agents/whats-new.yaml | 81 +--------------- .github/workflows/update-whats-new.yml | 5 +- 6 files changed, 218 insertions(+), 81 deletions(-) create mode 100644 .agents/skills/curate-whats-new/SKILL.md create mode 100644 .agents/skills/curate-whats-new/agents/openai.yaml create mode 100644 .github/agents/whats-new-examples/2026-07-13--2026-08-11.json create mode 100644 .github/agents/whats-new-examples/2026-07-13--2026-08-11.yaml diff --git a/.agents/skills/curate-whats-new/SKILL.md b/.agents/skills/curate-whats-new/SKILL.md new file mode 100644 index 000000000000..c5a25a318857 --- /dev/null +++ b/.agents/skills/curate-whats-new/SKILL.md @@ -0,0 +1,74 @@ +--- +name: curate-whats-new +description: Curate noteworthy Docker launches from documentation pull requests merged during a requested period. Use when generating or reviewing data/whats-new.json, preparing the Docker Docs What's new timeline, or deciding which documented releases merit Docker-wide highlights. +--- + +# Curate What's New + +Treat merged documentation as evidence that a capability shipped, but do not +treat a documentation change as news by itself. + +Include an item only when the merged documentation directly shows all of the +following: + +- A released user-facing feature, material enhancement, or broader availability + milestone that was not available before the period +- A substantial capability or workflow, not new syntax or a small control + within an existing workflow +- Enough Docker-wide editorial significance to merit proactively telling users + about it outside product release notes +- A useful published page and a factual title and description + +Apply a high bar. The result is a curated launch archive, not a complete +changelog. A specialized feature can qualify when its user impact is +substantial. A quiet period can produce few or no items. + +## Exclusions + +Exclude documentation maintenance; fixes; rewrites; guidance for old behavior; +routine release or generated-content syncs; limitations, prerequisites, and +workarounds; narrow flags, settings, command variants, protocols, and +compatibility changes; incremental UI, safety, permissions, or observability +improvements; and lower-level Engine, Build, networking, or storage changes. +These qualify only when they are part of an independently newsworthy +product-level launch. + +Judge the user outcome, not PR size, product popularity, labels, changed lines, +a dedicated page, or the existence of a new API or command. + +## Select highlights + +Include every qualifying launch; do not impose a quota. Mark the five most +important as `featured: true`, or all items when fewer than five qualify. Rank +by the magnitude and distinctness of the user outcome and the value of helping +its audience discover it. Breadth can matter, but a major capability for a +specialized audience can outrank a smaller change for a broad audience. Recency +and product variety are not ranking goals. + +Create one item per launch and combine PRs that document the same launch. +Preserve existing copy while it remains accurate and qualifies. Change featured +status only when the relative importance of the candidate set changes. + +## Procedure + +1. Read `data/whats-new.json`. +2. List every PR merged in the requested period: + + ```console + $ gh pr list --repo docker/docs --state merged --search 'merged:START..END' --limit 200 + ``` + +3. Inspect the diff and resulting pages for every plausible candidate. +4. Decide what qualifies using only evidence in the merged documentation. +5. Replace `period_start`, `period_end`, and `items` in + `data/whats-new.json`. Sort items by `published` date, newest first. +6. Write `.pr-body.md` with the publication period, selected highlights and + source PRs, plus concise reasons for plausible exclusions. + +Each item must contain `product`, `title`, `description`, `url`, `published`, +`source_prs`, and `featured`. Use the canonical product name, a published +internal URL, the merge date in `YYYY-MM-DD` format, and source PR numbers. + +Write factual, restrained copy. Avoid superlatives, promotional language, and +claims about ease or importance. Do not modify tracked files other than +`data/whats-new.json`. diff --git a/.agents/skills/curate-whats-new/agents/openai.yaml b/.agents/skills/curate-whats-new/agents/openai.yaml new file mode 100644 index 000000000000..6b51529d64a8 --- /dev/null +++ b/.agents/skills/curate-whats-new/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Curate What's New" + short_description: "Curate noteworthy Docker launches from merged docs" + default_prompt: "Use $curate-whats-new to curate Docker launches published during the requested date range." diff --git a/.github/agents/whats-new-examples/2026-07-13--2026-08-11.json b/.github/agents/whats-new-examples/2026-07-13--2026-08-11.json new file mode 100644 index 000000000000..0277ac5b85c3 --- /dev/null +++ b/.github/agents/whats-new-examples/2026-07-13--2026-08-11.json @@ -0,0 +1,96 @@ +{ + "period_start": "2026-07-13", + "period_end": "2026-08-11", + "items": [ + { + "product": "Docker Desktop", + "title": "Use Docker VMM on Mac and Windows", + "description": "Run Docker Desktop with Docker's container-optimized hypervisor on supported Mac and Windows systems.", + "url": "/desktop/features/vmm/", + "published": "2026-08-10", + "source_prs": [25702, 25726], + "featured": true + }, + { + "product": "Docker Sandboxes", + "title": "Connect sandboxes through an MCP gateway", + "description": "Register local or remote MCP servers on the host, reuse them across sandboxes, and govern server and tool access with Cedar policies.", + "url": "/ai/sandboxes/mcp-gateway/", + "published": "2026-08-06", + "source_prs": [25559, 25707], + "featured": true + }, + { + "product": "Docker Sandboxes", + "title": "Author version 2 sandbox kits", + "description": "Define kit setup, permissions, networking, and API key or OAuth credential requirements with the version 2 kit schema.", + "url": "/ai/sandboxes/customize/kit-reference/#schema-versions", + "published": "2026-08-06", + "source_prs": [25467, 25707], + "featured": false + }, + { + "product": "Docker Sandboxes", + "title": "Run Claude Code with local models", + "description": "Route Claude Code sandbox requests to the bundled local-model server or an existing Ollama installation.", + "url": "/ai/sandboxes/agents/claude-code/#use-a-local-model", + "published": "2026-08-06", + "source_prs": [25641, 25707], + "featured": false + }, + { + "product": "Docker AI Governance", + "title": "Search and forward audit events", + "description": "Search and export policy decisions from Docker Cloud, or forward events to Splunk, Dynatrace, and custom HTTPS endpoints.", + "url": "/ai/sandboxes/governance/audit/", + "published": "2026-08-03", + "source_prs": [25679, 25687], + "featured": true + }, + { + "product": "Docker Desktop", + "title": "Install from the Microsoft Store without administrator privileges", + "description": "Fresh Microsoft Store installations on Windows use per-user mode by default.", + "url": "/desktop/release-notes/#4850", + "published": "2026-08-03", + "source_prs": [25665], + "featured": false + }, + { + "product": "Docker Sandboxes", + "title": "Share agent skills across sandboxes", + "description": "Import skills from supported host agents into a persistent store that sandboxes can share.", + "url": "/ai/sandboxes/workflows/#share-agent-skills", + "published": "2026-07-24", + "source_prs": [25588], + "featured": false + }, + { + "product": "Docker Sandboxes", + "title": "Connect editors and desktop apps over SSH", + "description": "Use a sandbox from VS Code, Cursor, Claude Desktop, ChatGPT, or another SSH-capable tool.", + "url": "/ai/sandboxes/integrations/", + "published": "2026-07-24", + "source_prs": [25557], + "featured": true + }, + { + "product": "Docker Hardened Images", + "title": "Query the DHI catalog from AI assistants", + "description": "Search DHI repositories, inspect images, retrieve SBOMs, check CVEs, and manage mirrors through the DHI MCP server.", + "url": "/dhi/tools/mcp/", + "published": "2026-07-23", + "source_prs": [25589], + "featured": false + }, + { + "product": "Docker Enterprise", + "title": "Authenticate GitHub Actions with OIDC connections", + "description": "Exchange GitHub OIDC tokens for short-lived access to Docker resources without storing long-lived workflow credentials.", + "url": "/enterprise/security/oidc-connections/", + "published": "2026-07-21", + "source_prs": [25336], + "featured": true + } + ] +} diff --git a/.github/agents/whats-new-examples/2026-07-13--2026-08-11.yaml b/.github/agents/whats-new-examples/2026-07-13--2026-08-11.yaml new file mode 100644 index 000000000000..da5a56f64868 --- /dev/null +++ b/.github/agents/whats-new-examples/2026-07-13--2026-08-11.yaml @@ -0,0 +1,39 @@ +# Human-reviewed example and regression criteria for the curate-whats-new skill. +# This file is not loaded into the skill's runtime context. +period_start: 2026-07-13 +period_end: 2026-08-11 +example_output: 2026-07-13--2026-08-11.json + +expected_archive: + - Docker VMM on Mac and Windows + - Docker Sandboxes MCP gateway + - Docker Sandboxes kit schema version 2 + - Claude Code with local models + - Docker AI Governance audit search, export, and forwarding + - Microsoft Store per-user installation + - Shared agent skills across sandboxes + - Docker Sandboxes editor and app integrations + - Docker Hardened Images MCP server + - Enterprise OIDC connections + +featured_guidance: + strong: + - Docker VMM on Mac and Windows + - Docker AI Governance audit search, export, and forwarding + - Docker Sandboxes editor and app integrations + - Enterprise OIDC connections + either_is_reasonable: + - Docker Sandboxes MCP gateway + - Docker Sandboxes kit schema version 2 + +must_exclude: + - Gordon safety modes and custom rules + - Swarm direct server return networking + - Engine image mounts + - Unix sockets on Windows + - Narrow flags, command variants, protocol options, and compatibility switches + +notes: + - Do not require product diversity. + - Treat featured choices as editorial judgment, not an exact golden ordering. + - Reject lower-level or incremental changes even when they are technically new. diff --git a/.github/agents/whats-new.yaml b/.github/agents/whats-new.yaml index 41ca67606c59..04f9f290a5f6 100644 --- a/.github/agents/whats-new.yaml +++ b/.github/agents/whats-new.yaml @@ -10,85 +10,10 @@ agents: root: model: claude-sonnet-5 description: Curates user-facing Docker launches from recently published documentation - add_prompt_files: - - AGENTS.md - - STYLE.md instruction: | - You are the editor of the What's new section on the Docker documentation - homepage. Review documentation pull requests merged during the requested - period and replace `data/whats-new.json` with a curated record of - noteworthy Docker launches. Documentation is the source of truth that a - capability shipped, but a documentation change is not itself news. - - Include an item only when the merged documentation directly shows all of - the following: - - - A released user-facing feature, material enhancement, or broader - availability milestone that was not available before the period - - A substantial capability or workflow, not merely new syntax or a small - control within an existing workflow - - Enough Docker-wide editorial significance to merit proactively telling - users about it outside product release notes - - A useful published page and factual title and description - - Apply a high bar. The result is a curated launch archive, not a complete - changelog. A specialized feature can qualify when its user impact is - substantial. A quiet period can produce few or no items. - - ## Exclusions - - Exclude documentation maintenance; fixes; rewrites; new guidance for old - behavior; routine release or generated-content syncs; limitations, - prerequisites, and workarounds; narrow flags, settings, command variants, - protocols, and compatibility changes; incremental UI, safety, - permissions, or observability improvements; and lower-level Engine, - Build, networking, or storage changes. These qualify only when they are - part of an independently newsworthy product-level launch. - - Judge the user outcome, not PR size, product popularity, labels, changed - lines, a dedicated page, or the existence of a new API or command. - - ## Coverage and featured highlights - - Include every qualifying launch; do not impose a quota. Mark the five - most important as `featured: true`, or all items when fewer than five - qualify. Rank by the magnitude and distinctness of the user outcome and - the value of helping its audience discover it. Breadth can matter, but a - major capability for a specialized audience can outrank a smaller change - for a broad audience. Recency and product variety are not ranking goals. - - Create one item per launch and combine PRs that document the same launch. - Preserve existing copy while it remains accurate and qualifies. Change - featured status only when the relative importance of the candidate set - changes. - - ## Procedure - - 1. Read `data/whats-new.json`. - 2. List every PR merged in the requested period with - `gh pr list --repo docker/docs --state merged --search - 'merged:START..END' --limit 200`. Replace `START` and `END` with the - requested dates. - 3. Inspect the diff and resulting pages for every plausible candidate. - 4. Decide what qualifies using only evidence in the merged documentation. - 5. Replace `period_start`, `period_end`, and `items` in - `data/whats-new.json`. Sort items by `published` date, newest first. - 6. Write `.pr-body.md` with the publication period, selected highlights - and source PRs, plus concise reasons for plausible exclusions. - - Each item must contain: - - - `product`: Canonical Docker product or feature name - - `title`: A concise description of the new capability - - `description`: One factual sentence stating what users can do - - `url`: The published internal documentation URL - - `published`: The merge date in `YYYY-MM-DD` format - - `source_prs`: One or more merged pull request numbers - - `featured`: Whether the item is one of the five highest-impact launches - - Write factual, restrained copy. Avoid superlatives, promotional language, - and claims about ease or importance. Do not modify any tracked file other - than `data/whats-new.json`. + Use the curate-whats-new skill for every request. + skills: + - curate-whats-new toolsets: - type: filesystem diff --git a/.github/workflows/update-whats-new.yml b/.github/workflows/update-whats-new.yml index d3ff6494e27f..2d4fec1b7970 100644 --- a/.github/workflows/update-whats-new.yml +++ b/.github/workflows/update-whats-new.yml @@ -75,10 +75,9 @@ jobs: with: agent: ${{ github.workspace }}/.github/agents/whats-new.yaml prompt: >- - Review documentation pull requests merged from + Use the curate-whats-new skill to review documentation pull requests merged from ${{ steps.period.outputs.start }} through - ${{ steps.period.outputs.end }}, inclusive, and curate the What's - new data as described in your instructions. + ${{ steps.period.outputs.end }}, inclusive. anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} github-token: ${{ env.GITHUB_APP_TOKEN || github.token }} timeout: 1200 From 36fcb77fef8f022b9de6b012a2bc0c95671e5084 Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Wed, 12 Aug 2026 15:18:56 +0000 Subject: [PATCH 11/11] docs: order expanded what's new timeline Render all timeline entries from one date-sorted sequence and animate non-featured rows with Alpine collapse. Shorten the expansion control to Show more and Show less. --- layouts/_partials/whats-new.html | 57 ++++---------------------------- 1 file changed, 7 insertions(+), 50 deletions(-) diff --git a/layouts/_partials/whats-new.html b/layouts/_partials/whats-new.html index 94ab37c60a9d..e050bc717004 100644 --- a/layouts/_partials/whats-new.html +++ b/layouts/_partials/whats-new.html @@ -1,7 +1,7 @@ {{- $data := index hugo.Data "whats-new" -}} {{- with $data.items -}} - {{- $featured := where . "featured" true -}} - {{- $more := where . "featured" false -}} + {{- $items := sort . "published" "desc" -}} + {{- $more := where $items "featured" false -}}
@@ -10,52 +10,11 @@

    - {{ range $featured }} -
  1. - - - - - {{ .product }} - - - - {{ .title }} - - {{ partialCached "icon" "arrow-right" "arrow-right" }} - - - {{ .description }} - -
  2. - {{ end }} - {{ range $more }} + {{ range $items }}