diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 4a54973eb83..93bc2c64f97 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -1,29 +1,24 @@ // @ts-check -import { defineConfig } from 'astro/config'; -import starlight from '@astrojs/starlight'; -import sitemap from '@astrojs/sitemap'; -import starlightLinksValidator from 'starlight-links-validator'; -import starlightGitHubAlerts from 'starlight-github-alerts'; -import starlightBlog from 'starlight-blog'; -import mermaid from 'astro-mermaid'; -import { fileURLToPath } from 'node:url'; -import { unified } from '@astrojs/markdown-remark'; -import remarkStripEmojis from './src/lib/remark/stripEmojis.js'; -import remarkTableDataLabels from './src/lib/remark/tableDataLabels.js'; -import remarkInlineMarkdownInHtml from './src/lib/remark/inlineMarkdownInHtml.js'; -import rehypeTableWrapper from './src/lib/rehype/tableWrapper.js'; +import { defineConfig } from "astro/config"; +import starlight from "@astrojs/starlight"; +import sitemap from "@astrojs/sitemap"; +import starlightLinksValidator from "starlight-links-validator"; +import starlightGitHubAlerts from "starlight-github-alerts"; +import starlightBlog from "starlight-blog"; +import mermaid from "astro-mermaid"; +import { fileURLToPath } from "node:url"; +import { unified } from "@astrojs/markdown-remark"; +import remarkStripEmojis from "./src/lib/remark/stripEmojis.js"; +import remarkTableDataLabels from "./src/lib/remark/tableDataLabels.js"; +import remarkInlineMarkdownInHtml from "./src/lib/remark/inlineMarkdownInHtml.js"; +import rehypeTableWrapper from "./src/lib/rehype/tableWrapper.js"; /** * Creates blog authors config with GitHub profile pictures * @param {Record} authors */ function createAuthors(authors) { - return Object.fromEntries( - Object.entries(authors).map(([key, author]) => [ - key, - { ...author, picture: author.picture ?? `https://github.com/${key}.png?size=200` } - ]) - ); + return Object.fromEntries(Object.entries(authors).map(([key, author]) => [key, { ...author, picture: author.picture ?? `https://github.com/${key}.png?size=200` }])); } // NOTE: A previous attempt defined a custom Shiki grammar for `aw` (agentic workflow) but @@ -35,457 +30,447 @@ function createAuthors(authors) { // https://astro.build/config export default defineConfig({ - site: 'https://github.github.com', - base: '/gh-aw/', - trailingSlash: 'always', - markdown: { - processor: unified({ - remarkPlugins: [remarkStripEmojis, remarkTableDataLabels, remarkInlineMarkdownInHtml], - rehypePlugins: [rehypeTableWrapper], - }), - }, - vite: { - server: { - fs: { - allow: [ - fileURLToPath(new URL('../', import.meta.url)), - ], - }, - }, - }, - devToolbar: { - enabled: false - }, - experimental: { - clientPrerender: false - }, - redirects: { - // Status → Labs → Agent Factory → Agent Factory Status chain - '/status/': '/gh-aw/agent-factory-status/', - '/labs/': '/gh-aw/agent-factory-status/', - '/agent-factory/': '/gh-aw/agent-factory-status/', + site: "https://github.github.com", + base: "/gh-aw/", + trailingSlash: "always", + markdown: { + processor: unified({ + remarkPlugins: [remarkStripEmojis, remarkTableDataLabels, remarkInlineMarkdownInHtml], + rehypePlugins: [rehypeTableWrapper], + }), + }, + vite: { + server: { + fs: { + allow: [fileURLToPath(new URL("../", import.meta.url))], + }, + }, + }, + devToolbar: { + enabled: false, + }, + experimental: { + clientPrerender: false, + }, + redirects: { + // Hosted wizard + "/wizard/": "https://githubnext.github.io/gh-aw-wizard/", - // Blog post date correction - '/blog/2026-01-12-meet-the-workflows/': '/gh-aw/blog/2026-01-13-meet-the-workflows/', + // Status → Labs → Agent Factory → Agent Factory Status chain + "/status/": "/gh-aw/agent-factory-status/", + "/labs/": "/gh-aw/agent-factory-status/", + "/agent-factory/": "/gh-aw/agent-factory-status/", - // Start-here → Get-started → current paths - '/start-here/concepts/': '/gh-aw/introduction/how-they-work/', - '/start-here/quick-start/': '/gh-aw/setup/quick-start/', + // Blog post date correction + "/blog/2026-01-12-meet-the-workflows/": "/gh-aw/blog/2026-01-13-meet-the-workflows/", - // Get-started → current paths - '/get-started/concepts/': '/gh-aw/introduction/how-they-work/', - '/get-started/quick-start/': '/gh-aw/setup/quick-start/', + // Start-here → Get-started → current paths + "/start-here/concepts/": "/gh-aw/introduction/how-they-work/", + "/start-here/quick-start/": "/gh-aw/setup/quick-start/", - // Introduction how-it-works → how-they-work - '/introduction/how-it-works/': '/gh-aw/introduction/how-they-work/', - '/introduction/slides/': '/gh-aw/', - '/slides/': '/gh-aw/', + // Get-started → current paths + "/get-started/concepts/": "/gh-aw/introduction/how-they-work/", + "/get-started/quick-start/": "/gh-aw/setup/quick-start/", - // Tools → Setup renames - '/tools/cli/': '/gh-aw/setup/cli/', - '/tools/mcp-server/': '/gh-aw/reference/gh-aw-as-mcp-server/', - '/tools/agentic-authoring/': '/gh-aw/setup/creating-workflows/', + // Introduction how-it-works → how-they-work + "/introduction/how-it-works/": "/gh-aw/introduction/how-they-work/", + "/introduction/slides/": "/gh-aw/", + "/slides/": "/gh-aw/", - // Samples → Patterns renames - '/samples/coding-development/': '/gh-aw/patterns/daily-ops/', - '/samples/quality-testing/': '/gh-aw/patterns/daily-ops/', - '/samples/triage-analysis/': '/gh-aw/patterns/issue-ops/', - '/samples/research-planning/': '/gh-aw/patterns/daily-ops/', + // Tools → Setup renames + "/tools/cli/": "/gh-aw/setup/cli/", + "/tools/mcp-server/": "/gh-aw/reference/gh-aw-as-mcp-server/", + "/tools/agentic-authoring/": "/gh-aw/setup/creating-workflows/", - // Setup renames - '/setup/agentic-authoring/': '/gh-aw/setup/creating-workflows/', - '/setup/mcp-server/': '/gh-aw/reference/gh-aw-as-mcp-server/', + // Samples → Patterns renames + "/samples/coding-development/": "/gh-aw/patterns/daily-ops/", + "/samples/quality-testing/": "/gh-aw/patterns/daily-ops/", + "/samples/triage-analysis/": "/gh-aw/patterns/issue-ops/", + "/samples/research-planning/": "/gh-aw/patterns/daily-ops/", - // Reference renames - '/reference/custom-agents/': '/gh-aw/reference/copilot-custom-agents/', - '/reference/custom-agent/': '/gh-aw/reference/custom-agent-for-aw/', - '/reference/assign-to-copilot/': '/gh-aw/reference/copilot-cloud-agent/', + // Setup renames + "/setup/agentic-authoring/": "/gh-aw/setup/creating-workflows/", + "/setup/mcp-server/": "/gh-aw/reference/gh-aw-as-mcp-server/", - // Organization Practices moved under Guides - '/organization-practices/': '/gh-aw/practices/organization-practices/', - '/organization-practices/safe-rollout/': '/gh-aw/practices/safe-rollout/', - '/organization-practices/sharing-workflows/': '/gh-aw/practices/sharing-workflows/', + // Reference renames + "/reference/custom-agents/": "/gh-aw/reference/copilot-custom-agents/", + "/reference/custom-agent/": "/gh-aw/reference/custom-agent-for-aw/", + "/reference/assign-to-copilot/": "/gh-aw/reference/copilot-cloud-agent/", - // Guides → Patterns renames - '/guides/chatops/': '/gh-aw/patterns/chat-ops/', - '/guides/issueops/': '/gh-aw/patterns/issue-ops/', - '/guides/labelops/': '/gh-aw/patterns/label-ops/', - '/guides/dailyops/': '/gh-aw/patterns/daily-ops/', - '/guides/dispatchops/': '/gh-aw/patterns/dispatch-ops/', - '/guides/monitoring/': '/gh-aw/experimental/monitoring-with-projects/', - '/guides/multirepoops/': '/gh-aw/patterns/multi-repo-ops/', - '/guides/orchestration/': '/gh-aw/patterns/orchestrator-ops/', - '/patterns/orchestration/': '/gh-aw/patterns/orchestrator-ops/', - '/guides/siderepoops/': '/gh-aw/patterns/multi-repo-ops/', - '/patterns/side-repo-ops/': '/gh-aw/patterns/multi-repo-ops/', - '/guides/specops/': '/gh-aw/patterns/spec-ops/', - '/guides/researchplanassign/': '/gh-aw/patterns/research-plan-assign-ops/', - '/guides/trialops/': '/gh-aw/experimental/trial-ops/', + // Organization Practices moved under Guides + "/organization-practices/": "/gh-aw/practices/organization-practices/", + "/organization-practices/safe-rollout/": "/gh-aw/practices/safe-rollout/", + "/organization-practices/sharing-workflows/": "/gh-aw/practices/sharing-workflows/", - // Examples → Patterns renames - '/examples/comment-triggered/chatops/': '/gh-aw/patterns/chat-ops/', - '/examples/scheduled/dailyops/': '/gh-aw/patterns/daily-ops/', - '/examples/issue-pr-events/issueops/': '/gh-aw/patterns/issue-ops/', - '/examples/issue-pr-events/labelops/': '/gh-aw/patterns/label-ops/', - '/examples/issue-pr-events/projectops/': '/gh-aw/patterns/project-ops/', + // Guides → Patterns renames + "/guides/chatops/": "/gh-aw/patterns/chat-ops/", + "/guides/issueops/": "/gh-aw/patterns/issue-ops/", + "/guides/labelops/": "/gh-aw/patterns/label-ops/", + "/guides/dailyops/": "/gh-aw/patterns/daily-ops/", + "/guides/dispatchops/": "/gh-aw/patterns/dispatch-ops/", + "/guides/monitoring/": "/gh-aw/experimental/monitoring-with-projects/", + "/guides/multirepoops/": "/gh-aw/patterns/multi-repo-ops/", + "/guides/orchestration/": "/gh-aw/patterns/orchestrator-ops/", + "/patterns/orchestration/": "/gh-aw/patterns/orchestrator-ops/", + "/guides/siderepoops/": "/gh-aw/patterns/multi-repo-ops/", + "/patterns/side-repo-ops/": "/gh-aw/patterns/multi-repo-ops/", + "/guides/specops/": "/gh-aw/patterns/spec-ops/", + "/guides/researchplanassign/": "/gh-aw/patterns/research-plan-assign-ops/", + "/guides/trialops/": "/gh-aw/experimental/trial-ops/", - // Patterns unhyphenated → hyphenated slugs - '/patterns/centralrepoops/': '/gh-aw/patterns/central-repo-ops/', - '/patterns/chatops/': '/gh-aw/patterns/chat-ops/', - '/patterns/dailyops/': '/gh-aw/patterns/daily-ops/', - '/patterns/dataops/': '/gh-aw/patterns/deterministic-ops/', - '/patterns/dispatchops/': '/gh-aw/patterns/dispatch-ops/', - '/patterns/issueops/': '/gh-aw/patterns/issue-ops/', - '/patterns/labelops/': '/gh-aw/patterns/label-ops/', - '/patterns/multirepoops/': '/gh-aw/patterns/multi-repo-ops/', - '/patterns/projectops/': '/gh-aw/patterns/project-ops/', - '/patterns/siderepoops/': '/gh-aw/patterns/multi-repo-ops/', - '/patterns/specops/': '/gh-aw/patterns/spec-ops/', - '/patterns/researchplanassignops/': '/gh-aw/patterns/research-plan-assign-ops/', - '/patterns/batchops/': '/gh-aw/patterns/batch-ops/', - '/patterns/taskops/': '/gh-aw/patterns/research-plan-assign-ops/', - '/patterns/trialops/': '/gh-aw/experimental/trial-ops/', - '/patterns/workqueueops/': '/gh-aw/patterns/workqueue-ops/', + // Examples → Patterns renames + "/examples/comment-triggered/chatops/": "/gh-aw/patterns/chat-ops/", + "/examples/scheduled/dailyops/": "/gh-aw/patterns/daily-ops/", + "/examples/issue-pr-events/issueops/": "/gh-aw/patterns/issue-ops/", + "/examples/issue-pr-events/labelops/": "/gh-aw/patterns/label-ops/", + "/examples/issue-pr-events/projectops/": "/gh-aw/patterns/project-ops/", - // Guides → new locations - '/guides/deterministic-agentic-patterns/': '/gh-aw/patterns/deterministic-ops/', - '/patterns/deterministic-agentic-patterns/': '/gh-aw/patterns/deterministic-ops/', - '/guides/organization-practices/safe-rollout/': '/gh-aw/practices/safe-rollout/', - '/guides/organization-practices/sharing-workflows/': '/gh-aw/practices/sharing-workflows/', - '/guides/organization-practices/': '/gh-aw/guides/using-at-scale/', - '/guides/maintaining-repos/': '/gh-aw/examples/maintaining-repos/', - '/practices/maintaining-repos/': '/gh-aw/examples/maintaining-repos/', - '/guides/self-hosted-runners/': '/gh-aw/reference/self-hosted-runners/', - '/guides/packaging-imports/': '/gh-aw/guides/reusing-workflows/', - '/guides/web-search/': '/gh-aw/reference/web-search/', - '/guides/custom-otlp-attributes/': '/gh-aw/guides/open-telemetry/', - '/guides/telemetry/': '/gh-aw/guides/open-telemetry/', - '/guides/opentelemetry/': '/gh-aw/guides/open-telemetry/', - '/experimental/opentelemetry/': '/gh-aw/guides/open-telemetry/', - '/patterns/opentelemetry/': '/gh-aw/guides/open-telemetry/', - '/guides/getting-started-mcp/': '/gh-aw/guides/mcps/', - '/patterns/data-ops/': '/gh-aw/patterns/deterministic-ops/', - '/patterns/expert-ops/': '/gh-aw/patterns/monitor-ops/', - '/patterns/agentic-ops/': '/gh-aw/patterns/monitor-ops/', - '/patterns/task-ops/': '/gh-aw/patterns/research-plan-assign-ops/', - '/examples/comment-triggered/': '/gh-aw/patterns/chat-ops/', - '/examples/issue-pr-events/': '/gh-aw/patterns/issue-ops/', - '/examples/issue-pr-events/triage-analysis/': '/gh-aw/patterns/issue-ops/', - '/examples/issue-pr-events/coding-development/': '/gh-aw/patterns/daily-ops/', - '/examples/issue-pr-events/quality-testing/': '/gh-aw/patterns/daily-ops/', - '/examples/scheduled/': '/gh-aw/patterns/daily-ops/', - '/examples/scheduled/research-planning/': '/gh-aw/patterns/daily-ops/', - '/examples/manual/': '/gh-aw/patterns/dispatch-ops/', - '/examples/project-tracking/': '/gh-aw/patterns/project-ops/', - '/guides/audit-with-agents/': '/gh-aw/reference/audit/', - '/guides/ephemerals/': '/gh-aw/reference/ephemerals/', - '/guides/memoryops/': '/gh-aw/patterns/memory-ops/', - '/guides/memory-ops/': '/gh-aw/patterns/memory-ops/', - '/guides/serena/': '/gh-aw/reference/serena/', - '/guides/experiments/': '/gh-aw/experimental/experiments/', - '/practices/experiments/': '/gh-aw/experimental/experiments/', - '/practices/experiments-specification/': '/gh-aw/experimental/experiments-specification/', - '/reference/experiments-specification/': '/gh-aw/experimental/experiments-specification/', - '/reference/ai-credits-specification/': '/gh-aw/specs/ai-credits-specification/', - '/reference/copilot-sdk-driver-specification/': '/gh-aw/specs/copilot-sdk-driver-specification/', - '/reference/effective-tokens-specification/': '/gh-aw/specs/effective-tokens-specification/', - '/reference/forecast-specification/': '/gh-aw/specs/forecast-specification/', - '/reference/frontmatter-hash-specification/': '/gh-aw/specs/frontmatter-hash-specification/', - '/reference/fuzzy-schedule-specification/': '/gh-aw/specs/fuzzy-schedule-specification/', - '/reference/mcp-scripts-specification/': '/gh-aw/specs/mcp-scripts-specification/', - '/reference/model-alias-specification/': '/gh-aw/specs/model-alias-specification/', - '/reference/repository-package-manifest-specification/': '/gh-aw/specs/repository-package-manifest-specification/', - '/reference/safe-outputs-specification/': '/gh-aw/specs/safe-outputs-specification/', - '/practices/organization-practices/': '/gh-aw/guides/using-at-scale/', + // Patterns unhyphenated → hyphenated slugs + "/patterns/centralrepoops/": "/gh-aw/patterns/central-repo-ops/", + "/patterns/chatops/": "/gh-aw/patterns/chat-ops/", + "/patterns/dailyops/": "/gh-aw/patterns/daily-ops/", + "/patterns/dataops/": "/gh-aw/patterns/deterministic-ops/", + "/patterns/dispatchops/": "/gh-aw/patterns/dispatch-ops/", + "/patterns/issueops/": "/gh-aw/patterns/issue-ops/", + "/patterns/labelops/": "/gh-aw/patterns/label-ops/", + "/patterns/multirepoops/": "/gh-aw/patterns/multi-repo-ops/", + "/patterns/projectops/": "/gh-aw/patterns/project-ops/", + "/patterns/siderepoops/": "/gh-aw/patterns/multi-repo-ops/", + "/patterns/specops/": "/gh-aw/patterns/spec-ops/", + "/patterns/researchplanassignops/": "/gh-aw/patterns/research-plan-assign-ops/", + "/patterns/batchops/": "/gh-aw/patterns/batch-ops/", + "/patterns/taskops/": "/gh-aw/patterns/research-plan-assign-ops/", + "/patterns/trialops/": "/gh-aw/experimental/trial-ops/", + "/patterns/workqueueops/": "/gh-aw/patterns/workqueue-ops/", - '/reference/awf-reflect/': '/gh-aw/experimental/awf-reflect/', + // Guides → new locations + "/guides/deterministic-agentic-patterns/": "/gh-aw/patterns/deterministic-ops/", + "/patterns/deterministic-agentic-patterns/": "/gh-aw/patterns/deterministic-ops/", + "/guides/organization-practices/safe-rollout/": "/gh-aw/practices/safe-rollout/", + "/guides/organization-practices/sharing-workflows/": "/gh-aw/practices/sharing-workflows/", + "/guides/organization-practices/": "/gh-aw/guides/using-at-scale/", + "/guides/maintaining-repos/": "/gh-aw/examples/maintaining-repos/", + "/practices/maintaining-repos/": "/gh-aw/examples/maintaining-repos/", + "/guides/self-hosted-runners/": "/gh-aw/reference/self-hosted-runners/", + "/guides/packaging-imports/": "/gh-aw/guides/reusing-workflows/", + "/guides/web-search/": "/gh-aw/reference/web-search/", + "/guides/custom-otlp-attributes/": "/gh-aw/guides/open-telemetry/", + "/guides/telemetry/": "/gh-aw/guides/open-telemetry/", + "/guides/opentelemetry/": "/gh-aw/guides/open-telemetry/", + "/experimental/opentelemetry/": "/gh-aw/guides/open-telemetry/", + "/patterns/opentelemetry/": "/gh-aw/guides/open-telemetry/", + "/guides/getting-started-mcp/": "/gh-aw/guides/mcps/", + "/patterns/data-ops/": "/gh-aw/patterns/deterministic-ops/", + "/patterns/expert-ops/": "/gh-aw/patterns/monitor-ops/", + "/patterns/agentic-ops/": "/gh-aw/patterns/monitor-ops/", + "/patterns/task-ops/": "/gh-aw/patterns/research-plan-assign-ops/", + "/examples/comment-triggered/": "/gh-aw/patterns/chat-ops/", + "/examples/issue-pr-events/": "/gh-aw/patterns/issue-ops/", + "/examples/issue-pr-events/triage-analysis/": "/gh-aw/patterns/issue-ops/", + "/examples/issue-pr-events/coding-development/": "/gh-aw/patterns/daily-ops/", + "/examples/issue-pr-events/quality-testing/": "/gh-aw/patterns/daily-ops/", + "/examples/scheduled/": "/gh-aw/patterns/daily-ops/", + "/examples/scheduled/research-planning/": "/gh-aw/patterns/daily-ops/", + "/examples/manual/": "/gh-aw/patterns/dispatch-ops/", + "/examples/project-tracking/": "/gh-aw/patterns/project-ops/", + "/guides/audit-with-agents/": "/gh-aw/reference/audit/", + "/guides/ephemerals/": "/gh-aw/reference/ephemerals/", + "/guides/memoryops/": "/gh-aw/patterns/memory-ops/", + "/guides/memory-ops/": "/gh-aw/patterns/memory-ops/", + "/guides/serena/": "/gh-aw/reference/serena/", + "/guides/experiments/": "/gh-aw/experimental/experiments/", + "/practices/experiments/": "/gh-aw/experimental/experiments/", + "/practices/experiments-specification/": "/gh-aw/experimental/experiments-specification/", + "/reference/experiments-specification/": "/gh-aw/experimental/experiments-specification/", + "/reference/ai-credits-specification/": "/gh-aw/specs/ai-credits-specification/", + "/reference/copilot-sdk-driver-specification/": "/gh-aw/specs/copilot-sdk-driver-specification/", + "/reference/effective-tokens-specification/": "/gh-aw/specs/effective-tokens-specification/", + "/reference/forecast-specification/": "/gh-aw/specs/forecast-specification/", + "/reference/frontmatter-hash-specification/": "/gh-aw/specs/frontmatter-hash-specification/", + "/reference/fuzzy-schedule-specification/": "/gh-aw/specs/fuzzy-schedule-specification/", + "/reference/mcp-scripts-specification/": "/gh-aw/specs/mcp-scripts-specification/", + "/reference/model-alias-specification/": "/gh-aw/specs/model-alias-specification/", + "/reference/repository-package-manifest-specification/": "/gh-aw/specs/repository-package-manifest-specification/", + "/reference/safe-outputs-specification/": "/gh-aw/specs/safe-outputs-specification/", + "/practices/organization-practices/": "/gh-aw/guides/using-at-scale/", - // Patterns → Experimental - '/patterns/correction-ops/': '/gh-aw/experimental/correction-ops/', - '/patterns/trial-ops/': '/gh-aw/experimental/trial-ops/', - '/patterns/monitoring/': '/gh-aw/experimental/monitoring-with-projects/', + "/reference/awf-reflect/": "/gh-aw/experimental/awf-reflect/", - // Use Cases → Guides (moved) - '/use-cases/ai-issue-triage/': '/gh-aw/guides/ai-issue-triage/', - '/use-cases/automated-pr-review/': '/gh-aw/guides/automated-pr-review/', - '/use-cases/ai-release-notes/': '/gh-aw/guides/ai-release-notes/', - '/use-cases/docs-automation/': '/gh-aw/guides/docs-automation/', - }, - integrations: [ - sitemap(), - mermaid(), - starlight({ - title: 'GitHub Agentic Workflows', - description: 'Write agentic workflows in natural language using markdown files and run them as GitHub Actions workflows.', - favicon: '/favicon.svg', - logo: { - src: './src/assets/agentic-workflow.svg', - replacesTitle: false, - }, - components: { - Banner: './src/components/RecruitmentBanner.astro', - Head: './src/components/CustomHead.astro', - SkipLink: './src/components/SkipLink.astro', - SocialIcons: './src/components/CustomHeader.astro', - ThemeSelect: './src/components/ThemeToggle.astro', - Footer: './src/components/CustomFooter.astro', - SiteTitle: './src/components/CustomLogo.astro', - }, - customCss: [ - './src/styles/custom.css', - ], - social: [ - { icon: 'github', label: 'GitHub', href: 'https://github.com/github/gh-aw' }, - ], - tableOfContents: { - minHeadingLevel: 2, - maxHeadingLevel: 4 - }, - pagination: true, - expressiveCode: { - frames: { - showCopyToClipboardButton: true, - }, - shiki: { - langs: /** @type {any[]} */ ([ - "markdown", - "yaml" - ]), - langAlias: { aw: "markdown" } - }, - }, - plugins: [ - starlightBlog({ - recentPostCount: 12, - authors: createAuthors({ - 'githubnext': { - name: 'GitHub Next', - url: 'https://githubnext.com/', - }, - 'dsyme': { - name: 'Don Syme', - url: 'https://dsyme.net/', - }, - 'pelikhan': { - name: 'Peli de Halleux', - url: 'https://www.microsoft.com/research/people/jhalleux/', - }, - 'mnkiefer': { - name: 'Mara Kiefer', - url: 'https://github.com/mnkiefer', - }, - 'claude': { - name: 'Claude', - url: 'https://claude.ai', - picture: '/gh-aw/claude.png', - }, - 'codex': { - name: 'Codex', - url: 'https://openai.com/index/openai-codex/', - picture: '/gh-aw/codex.png', - }, - 'gemini': { - name: 'Gemini', - url: 'https://gemini.google.com', - picture: '/gh-aw/gemini.png', - }, - 'copilot': { - name: 'Copilot', - url: 'https://github.com/features/copilot', - picture: 'https://avatars.githubusercontent.com/in/1143301?s=64&v=4', - }, - }), - }), - starlightGitHubAlerts(), - starlightLinksValidator({ - errorOnRelativeLinks: true, - errorOnLocalLinks: true, - exclude: ({ file, link }) => - file.includes('/src/generated/workshop-markdown/') - && link.includes('?__gh_aw_workshop_local__=') - && link.startsWith('/gh-aw/workshop/?__gh_aw_workshop_local__='), - }) - ], - sidebar: [ - { - label: 'Introduction', - items: [{ autogenerate: { directory: 'introduction' } }], - }, - { - label: 'Setup', - items: [ - { label: 'Quick Start', link: '/setup/quick-start/' }, - { label: 'AW Wizard', link: '/wizard/' }, - { label: 'Creating Workflows', link: '/setup/creating-workflows/' }, - { label: 'CLI Commands', link: '/setup/cli/' }, - ], - }, - { - label: 'AI Engines', - items: [ - { label: 'GitHub Copilot', link: '/engines/copilot/' }, - { label: 'Claude Code', link: '/engines/claude/' }, - { label: 'OpenAI Codex', link: '/engines/codex/' }, - { label: 'Google Gemini', link: '/engines/gemini/' }, - ], - }, - { - label: 'Guides', - items: [ - { label: 'AI Issue Triage', link: '/guides/ai-issue-triage/' }, - { label: 'Automated PR Review', link: '/guides/automated-pr-review/' }, - { label: 'AI Release Notes', link: '/guides/ai-release-notes/' }, - { label: 'Docs Automation', link: '/guides/docs-automation/' }, - { label: 'Agentic Authoring', link: '/guides/agentic-authoring/' }, - { label: 'Editing Workflows', link: '/guides/editing-workflows/' }, - { label: 'Governance', link: '/guides/governance/' }, - { label: 'Reusing Workflows', link: '/guides/reusing-workflows/' }, - { label: 'Upgrading Workflows', link: '/guides/upgrading/' }, - { label: 'Using MCPs', link: '/guides/mcps/' }, - { label: 'Network Configuration', link: '/guides/network-configuration/' }, - { label: 'Azure OpenAI BYOK', link: '/guides/azure-openai-byok/' }, - { label: 'Third-Party Agent', link: '/guides/third-party-agent/' }, - { label: 'ARC DinD for Copilot Coding Agent', link: '/guides/arc-dind-copilot-agent/' }, - { label: 'OpenTelemetry', link: '/guides/open-telemetry/' }, - { label: 'GitHub Actions Primer', link: '/guides/github-actions-primer/' }, - { label: 'Using at Scale in Organizations', link: '/guides/using-at-scale/' }, - ], - }, - { - label: 'Design Patterns', - items: [ - { label: 'BatchOps', link: '/patterns/batch-ops/' }, - { label: 'CentralRepoOps', link: '/patterns/central-repo-ops/' }, - { label: 'ChatOps', link: '/patterns/chat-ops/' }, - { label: 'DeterministicOps', link: '/patterns/deterministic-ops/' }, - { label: 'DispatchOps', link: '/patterns/dispatch-ops/' }, - { label: 'IssueOps', link: '/patterns/issue-ops/' }, - { label: 'LabelOps', link: '/patterns/label-ops/' }, - { label: 'MemoryOps', link: '/patterns/memory-ops/' }, - { label: 'MonitorOps', link: '/patterns/monitor-ops/' }, - { label: 'MultiRepoOps', link: '/patterns/multi-repo-ops/' }, - { label: 'OrchestratorOps', link: '/patterns/orchestrator-ops/' }, - { label: 'ProjectOps', link: '/patterns/project-ops/' }, - { label: 'ResearchPlanAssignOps', link: '/patterns/research-plan-assign-ops/' }, - - { label: 'SpecOps', link: '/patterns/spec-ops/' }, - { label: 'WorkQueueOps', link: '/patterns/workqueue-ops/' }, - ], - }, - { - label: 'Practices', - items: [ - { label: 'Safe Rollout in Organizations', link: '/practices/safe-rollout/' }, - { label: 'Sharing Workflows in Organizations', link: '/practices/sharing-workflows/' }, - ], - }, - { - label: 'Examples', - items: [ - { label: 'Automated Repository Maintenance', link: '/examples/maintaining-repos/' }, - { label: 'Triage from Side Repo', link: '/examples/multi-repo/triage-from-side-repo/' }, - { label: 'Code Quality Monitoring', link: '/examples/multi-repo/code-quality-monitoring/' }, - { label: 'Dependabot Rollout', link: '/examples/multi-repo/dependabot-rollout/' }, - { label: 'Feature Synchronization', link: '/examples/multi-repo/feature-sync/' }, - { label: 'Cross-Repo Issue Tracking', link: '/examples/multi-repo/issue-tracking/' }, - ], - }, - { - label: 'Reference', - items: [ - { label: 'AI Engines', link: '/reference/engines/' }, - { label: 'Artifacts', link: '/reference/artifacts/' }, - { label: 'Auditing Workflows', link: '/reference/audit/' }, - { label: 'Authentication', link: '/reference/auth/' }, - { label: 'Authentication (Projects)', link: '/reference/auth-projects/' }, - { label: 'Compilation Process', link: '/reference/compilation-process/' }, - { label: 'Measuring Impact', link: '/reference/measuring-impact/' }, - { label: 'Billing', link: '/reference/billing/' }, - { label: 'Cost Management', link: '/reference/cost-management/' }, - { label: 'Cost Management (Rate Limiting)', link: '/reference/rate-limiting-controls/' }, - { label: 'Cost Management (Model Tables)', link: '/reference/model-tables/' }, - { label: 'Enterprise Configuration', link: '/reference/enterprise-configuration/' }, - { label: 'Environment Variables', link: '/reference/environment-variables/' }, - { label: 'FAQ', link: '/reference/faq/' }, - { label: 'Frontmatter', link: '/reference/frontmatter/' }, - { label: 'Frontmatter (Concurrency)', link: '/reference/concurrency/' }, - { label: 'Frontmatter (Schedule Syntax)', link: '/reference/schedule-syntax/' }, - { label: 'Frontmatter (Triggers)', link: '/reference/triggers/' }, - { label: 'Frontmatter (Command Triggers)', link: '/reference/command-triggers/' }, - { label: 'Frontmatter (Full)', link: '/reference/frontmatter-full/' }, - { label: 'GH-AW Agent', link: '/reference/custom-agent-for-aw/' }, - { label: 'GH-AW as MCP Server', link: '/reference/gh-aw-as-mcp-server/' }, - { label: 'GitHub (Checkout)', link: '/reference/checkout/' }, - { label: 'GitHub (Read Tools)', link: '/reference/github-tools/' }, - { label: 'GitHub (Read Permissions)', link: '/reference/permissions/' }, - { label: 'GitHub (Integrity Filtering)', link: '/reference/integrity/' }, - { label: 'GitHub (Cross-Repository)', link: '/reference/cross-repository/' }, - { label: 'GitHub (Fork Support)', link: '/reference/fork-support/' }, - { label: 'Glossary', link: '/reference/glossary/' }, - { label: 'Imports', link: '/reference/imports/' }, - { label: 'Imports (APM)', link: '/reference/dependencies/' }, - { label: 'Imports (Copilot Agent Files)', link: '/reference/copilot-custom-agents/' }, - { label: 'Imports (Copilot Inline Sub-Agents)', link: '/reference/inline-sub-agents/' }, - { label: 'Imports (Dependabot)', link: '/reference/dependabot/' }, - { label: 'Indexing (QMD)', link: '/reference/qmd/' }, - { label: 'Markdown', link: '/reference/markdown/' }, - { label: 'Outcomes', link: '/reference/outcomes/' }, - { label: 'OpenTelemetry Attributes', link: '/reference/open-telemetry/' }, - { label: 'Package Manifest', link: '/reference/aw-yml-package-manifest/' }, - { label: 'Releases and Versioning', link: '/reference/releases/' }, - { label: 'MCP Scripts', link: '/reference/mcp-scripts/' }, - { label: 'Safe Outputs', link: '/reference/safe-outputs/' }, - { label: 'Safe Outputs (Copilot Cloud Agent)', link: '/reference/copilot-cloud-agent/' }, - { label: 'Safe Outputs (Custom)', link: '/reference/custom-safe-outputs/' }, - { label: 'Safe Outputs (Pull Requests)', link: '/reference/safe-outputs-pull-requests/' }, - { label: 'Safe Outputs (Staged Mode)', link: '/reference/staged-mode/' }, - { label: 'Safe Outputs (Ephemerals)', link: '/reference/ephemerals/' }, - { label: 'Safe Outputs (Footers)', link: '/reference/footers/' }, - { label: 'Sandbox', link: '/reference/sandbox/' }, - { label: 'Sandbox (Agent Runtimes)', link: '/reference/agent-runtimes/' }, - { label: 'Self-Hosted Runners', link: '/reference/self-hosted-runners/' }, - { label: 'Sandbox (MCP Gateway)', link: '/reference/mcp-gateway/' }, - { label: 'Sandbox (Network Access)', link: '/reference/network/' }, - { label: 'Templating', link: '/reference/templating/' }, - { label: 'Threat Detection', link: '/reference/threat-detection/' }, - { label: 'Tools', link: '/reference/tools/' }, - { label: 'Tools (Cache Memory)', link: '/reference/cache-memory/' }, - { label: 'Tools (Repo Memory)', link: '/reference/repo-memory/' }, - { label: 'Tools (Playwright)', link: '/reference/playwright/' }, - { label: 'Tools (Serena)', link: '/reference/serena/' }, - { label: 'Tools (Web Search)', link: '/reference/web-search/' }, - { label: 'Triggering CI', link: '/reference/triggering-ci/' }, - { label: 'Workflow Structure', link: '/reference/workflow-structure/' }, - ], - }, - { - label: 'Specs', - collapsed: true, - items: [{ autogenerate: { directory: 'specs' } }], - }, - { - label: 'Troubleshooting', - items: [{ autogenerate: { directory: 'troubleshooting' } }], - }, - { - label: 'Experimental', - collapsed: true, - items: [ - { label: 'A/B Experiments', link: '/experimental/experiments/' }, - { label: 'A/B Experiments (Spec)', link: '/experimental/experiments-specification/' }, - { label: 'AWF Reflect Route', link: '/experimental/awf-reflect/' }, - { label: 'CorrectionOps', link: '/experimental/correction-ops/' }, - { label: 'Monitoring with Projects', link: '/experimental/monitoring-with-projects/' }, - { label: 'Safe-Outputs Samples', link: '/experimental/safe-outputs-samples/' }, - { label: 'TrialOps', link: '/experimental/trial-ops/' }, - { label: 'WASM Compilation', link: '/reference/wasm-compilation/' }, + // Patterns → Experimental + "/patterns/correction-ops/": "/gh-aw/experimental/correction-ops/", + "/patterns/trial-ops/": "/gh-aw/experimental/trial-ops/", + "/patterns/monitoring/": "/gh-aw/experimental/monitoring-with-projects/", - ], - }, - { label: 'Agent Factory', link: '/agent-factory-status/' }, - { label: 'Editors', link: '/reference/editors/' }, - { label: 'About', link: '/about/' }, - ], - }), - ], + // Use Cases → Guides (moved) + "/use-cases/ai-issue-triage/": "/gh-aw/guides/ai-issue-triage/", + "/use-cases/automated-pr-review/": "/gh-aw/guides/automated-pr-review/", + "/use-cases/ai-release-notes/": "/gh-aw/guides/ai-release-notes/", + "/use-cases/docs-automation/": "/gh-aw/guides/docs-automation/", + }, + integrations: [ + sitemap(), + mermaid(), + starlight({ + title: "GitHub Agentic Workflows", + description: "Write agentic workflows in natural language using markdown files and run them as GitHub Actions workflows.", + favicon: "/favicon.svg", + logo: { + src: "./src/assets/agentic-workflow.svg", + replacesTitle: false, + }, + components: { + Banner: "./src/components/RecruitmentBanner.astro", + Head: "./src/components/CustomHead.astro", + SkipLink: "./src/components/SkipLink.astro", + SocialIcons: "./src/components/CustomHeader.astro", + ThemeSelect: "./src/components/ThemeToggle.astro", + Footer: "./src/components/CustomFooter.astro", + SiteTitle: "./src/components/CustomLogo.astro", + }, + customCss: ["./src/styles/custom.css"], + social: [{ icon: "github", label: "GitHub", href: "https://github.com/github/gh-aw" }], + tableOfContents: { + minHeadingLevel: 2, + maxHeadingLevel: 4, + }, + pagination: true, + expressiveCode: { + frames: { + showCopyToClipboardButton: true, + }, + shiki: { + langs: /** @type {any[]} */ ["markdown", "yaml"], + langAlias: { aw: "markdown" }, + }, + }, + plugins: [ + starlightBlog({ + recentPostCount: 12, + authors: createAuthors({ + githubnext: { + name: "GitHub Next", + url: "https://githubnext.com/", + }, + dsyme: { + name: "Don Syme", + url: "https://dsyme.net/", + }, + pelikhan: { + name: "Peli de Halleux", + url: "https://www.microsoft.com/research/people/jhalleux/", + }, + mnkiefer: { + name: "Mara Kiefer", + url: "https://github.com/mnkiefer", + }, + claude: { + name: "Claude", + url: "https://claude.ai", + picture: "/gh-aw/claude.png", + }, + codex: { + name: "Codex", + url: "https://openai.com/index/openai-codex/", + picture: "/gh-aw/codex.png", + }, + gemini: { + name: "Gemini", + url: "https://gemini.google.com", + picture: "/gh-aw/gemini.png", + }, + copilot: { + name: "Copilot", + url: "https://github.com/features/copilot", + picture: "https://avatars.githubusercontent.com/in/1143301?s=64&v=4", + }, + }), + }), + starlightGitHubAlerts(), + starlightLinksValidator({ + errorOnRelativeLinks: true, + errorOnLocalLinks: true, + exclude: ({ file, link }) => file.includes("/src/generated/workshop-markdown/") && link.includes("?__gh_aw_workshop_local__=") && link.startsWith("/gh-aw/workshop/?__gh_aw_workshop_local__="), + }), + ], + sidebar: [ + { + label: "Introduction", + items: [{ autogenerate: { directory: "introduction" } }], + }, + { + label: "Setup", + items: [ + { label: "Quick Start", link: "/setup/quick-start/" }, + { label: "AW Wizard", link: "/wizard/" }, + { label: "Creating Workflows", link: "/setup/creating-workflows/" }, + { label: "CLI Commands", link: "/setup/cli/" }, + ], + }, + { + label: "AI Engines", + items: [ + { label: "GitHub Copilot", link: "/engines/copilot/" }, + { label: "Claude Code", link: "/engines/claude/" }, + { label: "OpenAI Codex", link: "/engines/codex/" }, + { label: "Google Gemini", link: "/engines/gemini/" }, + ], + }, + { + label: "Guides", + items: [ + { label: "AI Issue Triage", link: "/guides/ai-issue-triage/" }, + { label: "Automated PR Review", link: "/guides/automated-pr-review/" }, + { label: "AI Release Notes", link: "/guides/ai-release-notes/" }, + { label: "Docs Automation", link: "/guides/docs-automation/" }, + { label: "Agentic Authoring", link: "/guides/agentic-authoring/" }, + { label: "Editing Workflows", link: "/guides/editing-workflows/" }, + { label: "Governance", link: "/guides/governance/" }, + { label: "Reusing Workflows", link: "/guides/reusing-workflows/" }, + { label: "Upgrading Workflows", link: "/guides/upgrading/" }, + { label: "Using MCPs", link: "/guides/mcps/" }, + { label: "Network Configuration", link: "/guides/network-configuration/" }, + { label: "Azure OpenAI BYOK", link: "/guides/azure-openai-byok/" }, + { label: "Third-Party Agent", link: "/guides/third-party-agent/" }, + { label: "ARC DinD for Copilot Coding Agent", link: "/guides/arc-dind-copilot-agent/" }, + { label: "OpenTelemetry", link: "/guides/open-telemetry/" }, + { label: "GitHub Actions Primer", link: "/guides/github-actions-primer/" }, + { label: "Using at Scale in Organizations", link: "/guides/using-at-scale/" }, + ], + }, + { + label: "Design Patterns", + items: [ + { label: "BatchOps", link: "/patterns/batch-ops/" }, + { label: "CentralRepoOps", link: "/patterns/central-repo-ops/" }, + { label: "ChatOps", link: "/patterns/chat-ops/" }, + { label: "DeterministicOps", link: "/patterns/deterministic-ops/" }, + { label: "DispatchOps", link: "/patterns/dispatch-ops/" }, + { label: "IssueOps", link: "/patterns/issue-ops/" }, + { label: "LabelOps", link: "/patterns/label-ops/" }, + { label: "MemoryOps", link: "/patterns/memory-ops/" }, + { label: "MonitorOps", link: "/patterns/monitor-ops/" }, + { label: "MultiRepoOps", link: "/patterns/multi-repo-ops/" }, + { label: "OrchestratorOps", link: "/patterns/orchestrator-ops/" }, + { label: "ProjectOps", link: "/patterns/project-ops/" }, + { label: "ResearchPlanAssignOps", link: "/patterns/research-plan-assign-ops/" }, + + { label: "SpecOps", link: "/patterns/spec-ops/" }, + { label: "WorkQueueOps", link: "/patterns/workqueue-ops/" }, + ], + }, + { + label: "Practices", + items: [ + { label: "Safe Rollout in Organizations", link: "/practices/safe-rollout/" }, + { label: "Sharing Workflows in Organizations", link: "/practices/sharing-workflows/" }, + ], + }, + { + label: "Examples", + items: [ + { label: "Automated Repository Maintenance", link: "/examples/maintaining-repos/" }, + { label: "Triage from Side Repo", link: "/examples/multi-repo/triage-from-side-repo/" }, + { label: "Code Quality Monitoring", link: "/examples/multi-repo/code-quality-monitoring/" }, + { label: "Dependabot Rollout", link: "/examples/multi-repo/dependabot-rollout/" }, + { label: "Feature Synchronization", link: "/examples/multi-repo/feature-sync/" }, + { label: "Cross-Repo Issue Tracking", link: "/examples/multi-repo/issue-tracking/" }, + ], + }, + { + label: "Reference", + items: [ + { label: "AI Engines", link: "/reference/engines/" }, + { label: "Artifacts", link: "/reference/artifacts/" }, + { label: "Auditing Workflows", link: "/reference/audit/" }, + { label: "Authentication", link: "/reference/auth/" }, + { label: "Authentication (Projects)", link: "/reference/auth-projects/" }, + { label: "Compilation Process", link: "/reference/compilation-process/" }, + { label: "Measuring Impact", link: "/reference/measuring-impact/" }, + { label: "Billing", link: "/reference/billing/" }, + { label: "Cost Management", link: "/reference/cost-management/" }, + { label: "Cost Management (Rate Limiting)", link: "/reference/rate-limiting-controls/" }, + { label: "Cost Management (Model Tables)", link: "/reference/model-tables/" }, + { label: "Enterprise Configuration", link: "/reference/enterprise-configuration/" }, + { label: "Environment Variables", link: "/reference/environment-variables/" }, + { label: "FAQ", link: "/reference/faq/" }, + { label: "Frontmatter", link: "/reference/frontmatter/" }, + { label: "Frontmatter (Concurrency)", link: "/reference/concurrency/" }, + { label: "Frontmatter (Schedule Syntax)", link: "/reference/schedule-syntax/" }, + { label: "Frontmatter (Triggers)", link: "/reference/triggers/" }, + { label: "Frontmatter (Command Triggers)", link: "/reference/command-triggers/" }, + { label: "Frontmatter (Full)", link: "/reference/frontmatter-full/" }, + { label: "GH-AW Agent", link: "/reference/custom-agent-for-aw/" }, + { label: "GH-AW as MCP Server", link: "/reference/gh-aw-as-mcp-server/" }, + { label: "GitHub (Checkout)", link: "/reference/checkout/" }, + { label: "GitHub (Read Tools)", link: "/reference/github-tools/" }, + { label: "GitHub (Read Permissions)", link: "/reference/permissions/" }, + { label: "GitHub (Integrity Filtering)", link: "/reference/integrity/" }, + { label: "GitHub (Cross-Repository)", link: "/reference/cross-repository/" }, + { label: "GitHub (Fork Support)", link: "/reference/fork-support/" }, + { label: "Glossary", link: "/reference/glossary/" }, + { label: "Imports", link: "/reference/imports/" }, + { label: "Imports (APM)", link: "/reference/dependencies/" }, + { label: "Imports (Copilot Agent Files)", link: "/reference/copilot-custom-agents/" }, + { label: "Imports (Copilot Inline Sub-Agents)", link: "/reference/inline-sub-agents/" }, + { label: "Imports (Dependabot)", link: "/reference/dependabot/" }, + { label: "Indexing (QMD)", link: "/reference/qmd/" }, + { label: "Markdown", link: "/reference/markdown/" }, + { label: "Outcomes", link: "/reference/outcomes/" }, + { label: "OpenTelemetry Attributes", link: "/reference/open-telemetry/" }, + { label: "Package Manifest", link: "/reference/aw-yml-package-manifest/" }, + { label: "Releases and Versioning", link: "/reference/releases/" }, + { label: "MCP Scripts", link: "/reference/mcp-scripts/" }, + { label: "Safe Outputs", link: "/reference/safe-outputs/" }, + { label: "Safe Outputs (Copilot Cloud Agent)", link: "/reference/copilot-cloud-agent/" }, + { label: "Safe Outputs (Custom)", link: "/reference/custom-safe-outputs/" }, + { label: "Safe Outputs (Pull Requests)", link: "/reference/safe-outputs-pull-requests/" }, + { label: "Safe Outputs (Staged Mode)", link: "/reference/staged-mode/" }, + { label: "Safe Outputs (Ephemerals)", link: "/reference/ephemerals/" }, + { label: "Safe Outputs (Footers)", link: "/reference/footers/" }, + { label: "Sandbox", link: "/reference/sandbox/" }, + { label: "Sandbox (Agent Runtimes)", link: "/reference/agent-runtimes/" }, + { label: "Self-Hosted Runners", link: "/reference/self-hosted-runners/" }, + { label: "Sandbox (MCP Gateway)", link: "/reference/mcp-gateway/" }, + { label: "Sandbox (Network Access)", link: "/reference/network/" }, + { label: "Templating", link: "/reference/templating/" }, + { label: "Threat Detection", link: "/reference/threat-detection/" }, + { label: "Tools", link: "/reference/tools/" }, + { label: "Tools (Cache Memory)", link: "/reference/cache-memory/" }, + { label: "Tools (Repo Memory)", link: "/reference/repo-memory/" }, + { label: "Tools (Playwright)", link: "/reference/playwright/" }, + { label: "Tools (Serena)", link: "/reference/serena/" }, + { label: "Tools (Web Search)", link: "/reference/web-search/" }, + { label: "Triggering CI", link: "/reference/triggering-ci/" }, + { label: "Workflow Structure", link: "/reference/workflow-structure/" }, + ], + }, + { + label: "Specs", + collapsed: true, + items: [{ autogenerate: { directory: "specs" } }], + }, + { + label: "Troubleshooting", + items: [{ autogenerate: { directory: "troubleshooting" } }], + }, + { + label: "Experimental", + collapsed: true, + items: [ + { label: "A/B Experiments", link: "/experimental/experiments/" }, + { label: "A/B Experiments (Spec)", link: "/experimental/experiments-specification/" }, + { label: "AWF Reflect Route", link: "/experimental/awf-reflect/" }, + { label: "CorrectionOps", link: "/experimental/correction-ops/" }, + { label: "Monitoring with Projects", link: "/experimental/monitoring-with-projects/" }, + { label: "Safe-Outputs Samples", link: "/experimental/safe-outputs-samples/" }, + { label: "TrialOps", link: "/experimental/trial-ops/" }, + { label: "WASM Compilation", link: "/reference/wasm-compilation/" }, + ], + }, + { label: "Agent Factory", link: "/agent-factory-status/" }, + { label: "Editors", link: "/reference/editors/" }, + { label: "About", link: "/about/" }, + ], + }), + ], }); diff --git a/docs/public/schemas/wizard-data-model.example.json b/docs/public/schemas/wizard-data-model.example.json deleted file mode 100644 index ac28daf2b6d..00000000000 --- a/docs/public/schemas/wizard-data-model.example.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "$schema": "https://docs.github.com/gh-aw/schemas/wizard-data-model.schema.json", - "version": "1.0.0", - "goalCategories": [ - { - "id": "issue-automation", - "text": { - "label": "Automate issue triage or replies", - "help": "Respond to, label, or triage issues automatically when they are opened or commented on." - }, - "triggerOptionIds": ["on-issue-opened", "slash-command", "on-issue-comment"], - "destinationOptionIds": ["comment-on-issue", "add-labels-to-issue"], - "defaultTriggerOptionId": "on-issue-opened", - "defaultDestinationOptionId": "comment-on-issue" - }, - { - "id": "scheduled-report", - "text": { - "label": "Generate a recurring report", - "help": "Run on a schedule and publish a summary, digest, or status report." - }, - "triggerOptionIds": ["schedule-daily", "schedule-weekly", "manual-dispatch"], - "destinationOptionIds": ["create-discussion", "open-pull-request"], - "defaultTriggerOptionId": "schedule-daily", - "defaultDestinationOptionId": "create-discussion" - }, - { - "id": "pr-review-assistant", - "text": { - "label": "Review pull requests automatically", - "help": "Review incoming pull requests and leave feedback or suggested fixes." - }, - "triggerOptionIds": ["on-pull-request", "slash-command"], - "destinationOptionIds": ["comment-on-issue", "open-pull-request"], - "defaultTriggerOptionId": "on-pull-request", - "defaultDestinationOptionId": "comment-on-issue" - } - ], - "triggerOptions": [ - { - "id": "on-issue-opened", - "type": "issues", - "text": { "label": "When an issue is opened", "help": "Fires whenever a new issue is created." }, - "frontmatter": { "on": { "issues": { "types": ["opened"] } } } - }, - { - "id": "on-issue-comment", - "type": "issue_comment", - "text": { "label": "When someone comments on an issue" }, - "frontmatter": { "on": { "issue_comment": { "types": ["created"] } } } - }, - { - "id": "on-pull-request", - "type": "pull_request", - "text": { "label": "When a pull request is opened or updated" }, - "frontmatter": { "on": { "pull_request": { "types": ["opened", "synchronize"] } } } - }, - { - "id": "slash-command", - "type": "slash_command", - "text": { "label": "When triggered by a /command comment", "help": "Runs on-demand when a user comments a slash command." }, - "frontmatter": { "on": "/my-bot" } - }, - { - "id": "schedule-daily", - "type": "schedule", - "text": { "label": "Every day" }, - "frontmatter": { "on": { "schedule": "daily" } } - }, - { - "id": "schedule-weekly", - "type": "schedule", - "text": { "label": "Every week" }, - "frontmatter": { "on": { "schedule": "weekly" } } - }, - { - "id": "manual-dispatch", - "type": "workflow_dispatch", - "text": { "label": "Only when run manually" }, - "frontmatter": { "on": "workflow_dispatch" } - } - ], - "destinationOptions": [ - { - "id": "comment-on-issue", - "safeOutputType": "add-comment", - "text": { "label": "Post a comment" }, - "inferFromTriggerTypes": ["issues", "issue_comment", "pull_request"] - }, - { - "id": "add-labels-to-issue", - "safeOutputType": "add-labels", - "text": { "label": "Add labels" }, - "inferFromTriggerTypes": ["issues"] - }, - { - "id": "open-pull-request", - "safeOutputType": "create-pull-request", - "text": { "label": "Open a pull request" }, - "inferFromTriggerTypes": ["schedule", "pull_request", "workflow_dispatch"] - }, - { - "id": "create-discussion", - "safeOutputType": "create-discussion", - "text": { "label": "Post a discussion" }, - "inferFromTriggerTypes": ["schedule", "workflow_dispatch"] - } - ], - "promptTemplate": { - "introText": "You are helping generate a new GitHub Agentic Workflow (gh-aw) markdown file. This prompt is self-contained: run it in your project with an AI coding assistant and it will produce a complete `.md` workflow without assuming any prior gh-aw setup.", - "sections": [ - { "id": "goal", "heading": "Goal" }, - { "id": "trigger", "heading": "Trigger" }, - { "id": "destination", "heading": "Output destination" }, - { "id": "task-details", "heading": "Task details" } - ] - } -} diff --git a/docs/public/schemas/wizard-data-model.schema.json b/docs/public/schemas/wizard-data-model.schema.json deleted file mode 100644 index f99718f3e60..00000000000 --- a/docs/public/schemas/wizard-data-model.schema.json +++ /dev/null @@ -1,179 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://docs.github.com/gh-aw/schemas/wizard-data-model.schema.json", - "title": "Agentic Workflow Wizard Data Model", - "description": "Reusable JSON data model that drives the WHAT \u2192 WHEN \u2192 WHERE \u2192 task-details wizard flow described in the Wizard Data Model Specification v1.0.0. This shape is intentionally decoupled from any Astro/UI-specific behavior so it can be reused by a future `gh aw` CLI consumer.", - "type": "object", - "required": ["version", "goalCategories", "triggerOptions", "destinationOptions"], - "additionalProperties": false, - "properties": { - "version": { - "type": "string", - "description": "Additive schema version for this data model, following semver (MAJOR.MINOR.PATCH). Consumers MUST tolerate unknown additional fields within a MAJOR version.", - "pattern": "^\\d+\\.\\d+\\.\\d+$", - "examples": ["1.0.0"] - }, - "goalCategories": { - "type": "array", - "description": "WHAT step: known high-level goals a user might choose from. Each category declares which trigger options and destination options are compatible, enabling conditional progression without embedding presentation logic.", - "minItems": 1, - "items": { "$ref": "#/definitions/goalCategory" } - }, - "triggerOptions": { - "type": "array", - "description": "WHEN step: catalog of available trigger configurations (schedule, event, slash command, manual dispatch, etc.) that a goal category can reference by id.", - "minItems": 1, - "items": { "$ref": "#/definitions/triggerOption" } - }, - "destinationOptions": { - "type": "array", - "description": "WHERE step: catalog of safe-output destinations (e.g. create-issue, add-comment, create-pull-request) with inference hints so the wizard can pre-select a likely destination based on prior answers.", - "minItems": 1, - "items": { "$ref": "#/definitions/destinationOption" } - }, - "promptTemplate": { - "$ref": "#/definitions/promptTemplate", - "description": "Optional fields describing how collected answers are assembled into the final, self-contained prompt text presented to the user." - } - }, - "definitions": { - "localizedText": { - "type": "object", - "description": "Minimal presentation metadata for a label/help pair. Kept intentionally small so behavior/content stay portable across UI implementations.", - "required": ["label"], - "additionalProperties": false, - "properties": { - "label": { - "type": "string", - "description": "Short, user-facing label.", - "minLength": 1 - }, - "help": { - "type": "string", - "description": "Optional longer help/description text shown alongside the label." - } - } - }, - "goalCategory": { - "type": "object", - "description": "A single WHAT-step option. Explicit `id` is the stable key; never key data structures by free-form label text.", - "required": ["id", "text", "triggerOptionIds", "destinationOptionIds"], - "additionalProperties": false, - "properties": { - "id": { - "type": "string", - "description": "Stable, unique identifier for this goal category. MUST NOT change across versions once published.", - "pattern": "^[a-z][a-z0-9-]*$", - "examples": ["ci-triage", "issue-automation", "scheduled-report"] - }, - "text": { "$ref": "#/definitions/localizedText" }, - "triggerOptionIds": { - "type": "array", - "description": "IDs (from `triggerOptions`) that are valid/recommended follow-up choices for the WHEN step when this goal is selected.", - "minItems": 1, - "items": { "type": "string" } - }, - "destinationOptionIds": { - "type": "array", - "description": "IDs (from `destinationOptions`) that are valid/recommended follow-up choices for the WHERE step when this goal is selected.", - "minItems": 1, - "items": { "type": "string" } - }, - "defaultTriggerOptionId": { - "type": "string", - "description": "Optional id of the trigger option to pre-select/infer for this goal, from `triggerOptionIds`." - }, - "defaultDestinationOptionId": { - "type": "string", - "description": "Optional id of the destination option to pre-select/infer for this goal, from `destinationOptionIds`." - } - } - }, - "triggerOption": { - "type": "object", - "description": "A single WHEN-step option describing one GitHub Actions trigger shape supported by gh-aw.", - "required": ["id", "type", "text"], - "additionalProperties": false, - "properties": { - "id": { - "type": "string", - "description": "Stable, unique identifier for this trigger option.", - "pattern": "^[a-z][a-z0-9-]*$", - "examples": ["schedule-daily", "on-issue-opened", "slash-command", "manual-dispatch"] - }, - "type": { - "type": "string", - "description": "Underlying gh-aw/GitHub Actions trigger category this option maps to.", - "enum": ["schedule", "issues", "pull_request", "discussion", "issue_comment", "workflow_dispatch", "slash_command", "push", "other"] - }, - "text": { "$ref": "#/definitions/localizedText" }, - "frontmatter": { - "type": "object", - "description": "Optional literal (or template) fragment of gh-aw workflow frontmatter `on:` configuration this option contributes, e.g. `{\"schedule\": \"daily\"}`. Kept as free-form object because shapes vary by trigger type; the future CLI consumer is expected to merge this fragment as-is.", - "additionalProperties": true - } - } - }, - "destinationOption": { - "type": "object", - "description": "A single WHERE-step option describing one safe-output destination.", - "required": ["id", "safeOutputType", "text"], - "additionalProperties": false, - "properties": { - "id": { - "type": "string", - "description": "Stable, unique identifier for this destination option.", - "pattern": "^[a-z][a-z0-9-]*$", - "examples": ["comment-on-issue", "open-pull-request", "create-discussion"] - }, - "safeOutputType": { - "type": "string", - "description": "Name of the corresponding gh-aw safe-outputs handler key (see safe-outputs frontmatter, e.g. 'add-comment', 'create-issue', 'create-pull-request').", - "minLength": 1 - }, - "text": { "$ref": "#/definitions/localizedText" }, - "inferFromTriggerTypes": { - "type": "array", - "description": "Optional list of trigger `type` values (from `triggerOption.type`) that this destination is automatically inferred/recommended for, so the WHERE step can be skipped or pre-answered.", - "items": { "type": "string" } - }, - "frontmatter": { - "type": "object", - "description": "Optional literal (or template) fragment of gh-aw workflow frontmatter `safe-outputs:` configuration this option contributes.", - "additionalProperties": true - } - } - }, - "promptTemplate": { - "type": "object", - "description": "Fields controlling how the final, self-contained generation prompt is assembled from collected wizard answers. The rendered prompt MUST NOT assume any prior installation/setup by the user.", - "additionalProperties": false, - "properties": { - "introText": { - "type": "string", - "description": "Fixed opening text prepended to the generated prompt, establishing context for the target AI/CLI consumer." - }, - "sections": { - "type": "array", - "description": "Ordered list of named sections used to assemble the final prompt (e.g. goal, trigger, destination, task-details).", - "items": { - "type": "object", - "required": ["id", "heading"], - "additionalProperties": false, - "properties": { - "id": { - "type": "string", - "description": "Stable identifier for this prompt section.", - "pattern": "^[a-z][a-z0-9-]*$" - }, - "heading": { - "type": "string", - "description": "Heading/label rendered above this section's content in the assembled prompt." - } - } - } - } - } - } - } -} diff --git a/docs/src/components/Wizard.astro b/docs/src/components/Wizard.astro deleted file mode 100644 index 69239c078d3..00000000000 --- a/docs/src/components/Wizard.astro +++ /dev/null @@ -1,875 +0,0 @@ ---- -import { wizardDataModel } from '../lib/wizard/model'; - -const wizardModelJson = JSON.stringify(wizardDataModel); ---- - -
-
-
-

Workflow prompt wizard

-

Build an agentic workflow

-

- Choose what your workflow does, when it runs, and where it reports. We’ll combine your answers with any task details into a prompt you can copy. -

-
-
-
- -
    - -
    -
    -
    -

    -

    -

    -
    - -
    - -
    - - -
    -
    - - -
    - - -
    - - diff --git a/docs/src/content/docs/specs/wizard-data-model-specification.md b/docs/src/content/docs/specs/wizard-data-model-specification.md deleted file mode 100644 index 26ab26462f5..00000000000 --- a/docs/src/content/docs/specs/wizard-data-model-specification.md +++ /dev/null @@ -1,375 +0,0 @@ ---- -title: Wizard Data Model Specification -description: Formal specification for the JSON data model that drives the docs wizard (WHAT → WHEN → WHERE → task details) and is designed for reuse by a future gh aw CLI consumer. -sidebar: - order: 1371 ---- - -# Wizard Data Model Specification - -**Version**: 1.1.0 -**Status**: Draft -**Publication Date**: 2026-08-17 -**Editor**: GitHub Agentic Workflows Team -**This Version**: [wizard-data-model-specification](/gh-aw/specs/wizard-data-model-specification/) -**Latest Published Version**: This document - ---- - -## Abstract - -This specification defines the JSON data model that drives the docs site wizard used to help users compose a prompt for generating a new GitHub Agentic Workflow (gh-aw). The model captures goal categories (WHAT), trigger options (WHEN), safe-output destination options (WHERE), and prompt-assembly fields, without embedding any Astro/UI-specific behavior. It is designed so that a future `gh aw` CLI consumer can load and interpret the same data without re-authoring the underlying semantics. - -## Status of This Document - -This is a draft specification and may be updated, replaced, or made obsolete by other documents at any time. This document is governed by the GitHub Agentic Workflows project specifications process. - -## Table of Contents - -1. [Introduction](#1-introduction) -2. [Conformance](#2-conformance) -3. [File Location and Naming](#3-file-location-and-naming) -4. [Data Model](#4-data-model) -5. [Conditional Progression](#5-conditional-progression) -6. [Prompt Assembly](#6-prompt-assembly) -7. [Versioning and Compatibility](#7-versioning-and-compatibility) -8. [Future CLI Reuse](#8-future-cli-reuse) -9. [Examples](#9-examples) -10. [References](#references) -11. [Change Log](#change-log) - ---- - -## 1. Introduction - -### 1.1 Purpose - -The docs wizard walks a user through composing a self-contained prompt that generates a new agentic workflow: first the high-level **goal** (WHAT), then the **trigger** (WHEN), then the **safe-output destination** (WHERE, mostly inferred from prior answers), and finally free-form **task details**. This specification defines the JSON shape backing that flow. - -### 1.2 Scope - -This specification covers: - -- The top-level JSON entities: `goalCategories`, `triggerOptions`, `destinationOptions`, and `promptTemplate`. -- Required vs. optional fields and stable identifier conventions. -- How conditional progression (WHAT → WHEN → WHERE) is expressed via id references rather than embedded control flow. -- File location, naming, and versioning for compatibility with a future CLI consumer. -- The normative contract for assembling a final runnable prompt, including validation, step transitions, empty-state behavior, and completion criteria. - -This specification does not define the Astro component implementation, CSS/visual presentation, or any styling details of the generated prompt preview — those are implementation details left to the docs site. - -### 1.3 Terminology - -The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", and "MAY" are to be interpreted as described in RFC 2119. - -## 2. Conformance - -A conforming data file: - -- MUST validate against the JSON Schema at `docs/public/schemas/wizard-data-model.schema.json` (published at `/gh-aw/schemas/wizard-data-model.schema.json`). -- MUST include a `version` field using semantic versioning. -- MUST use explicit, stable `id` fields as keys for goal categories, trigger options, and destination options — free-form label text MUST NOT be used as a lookup key. -- SHOULD keep presentation metadata (`text.label`, `text.help`) minimal so behavioral/content fields remain portable across UI implementations. - -## 3. File Location and Naming - -| Artifact | Path | Purpose | -|---|---|---| -| JSON Schema | `docs/public/schemas/wizard-data-model.schema.json` | Normative schema, published under the docs site at `/gh-aw/schemas/wizard-data-model.schema.json`, consistent with existing schemas (e.g. `mcp-gateway-config.schema.json`). | -| Example/reference data | `docs/public/schemas/wizard-data-model.example.json` | A conforming example instance used for documentation and tests. | -| Wizard runtime data | `docs/src/data/wizard-data-model.json` (or equivalent Astro data source, introduced in a follow-up implementation issue) | The actual data consumed by the Astro wizard component at build/runtime. | - -Keeping the schema under `docs/public/schemas/` follows the existing convention for gh-aw JSON schemas (see `mcp-gateway-config.schema.json`, `mcp-scripts-config.schema.json`) so it is publicly resolvable and reusable outside the docs site, including by a future CLI. - -## 4. Data Model - -### 4.1 Top-Level Shape - -```json -{ - "version": "1.0.0", - "goalCategories": [ /* goalCategory[] */ ], - "triggerOptions": [ /* triggerOption[] */ ], - "destinationOptions": [ /* destinationOption[] */ ], - "promptTemplate": { /* promptTemplate, optional */ } -} -``` - -| Field | Required | Type | Description | -|---|---|---|---| -| `version` | Yes | string | Semver string for this data model instance. | -| `goalCategories` | Yes | array | WHAT-step options. Minimum one entry. | -| `triggerOptions` | Yes | array | WHEN-step options, referenced by id from `goalCategories`. | -| `destinationOptions` | Yes | array | WHERE-step options, referenced by id from `goalCategories` and inferable from trigger type. | -| `promptTemplate` | No | object | Optional fields controlling final prompt assembly. | - -### 4.2 `goalCategory` - -| Field | Required | Type | Description | -|---|---|---|---| -| `id` | Yes | string | Stable identifier, `^[a-z][a-z0-9-]*$`. MUST NOT change once published. | -| `text.label` | Yes | string | Short user-facing label. | -| `text.help` | No | string | Longer help text. | -| `triggerOptionIds` | Yes | string[] | IDs of compatible `triggerOptions` (min 1). | -| `destinationOptionIds` | Yes | string[] | IDs of compatible `destinationOptions` (min 1). | -| `defaultTriggerOptionId` | No | string | Pre-selected/inferred trigger id. | -| `defaultDestinationOptionId` | No | string | Pre-selected/inferred destination id. | - -### 4.3 `triggerOption` - -| Field | Required | Type | Description | -|---|---|---|---| -| `id` | Yes | string | Stable identifier. | -| `type` | Yes | string | One of: `schedule`, `issues`, `pull_request`, `discussion`, `issue_comment`, `workflow_dispatch`, `slash_command`, `push`, `other`. | -| `text.label` / `text.help` | Yes/No | string | Presentation metadata. | -| `frontmatter` | No | object | Literal or template fragment of gh-aw workflow frontmatter `on:` configuration contributed by this option. Free-form object; consumers merge it as-is. | - -### 4.4 `destinationOption` - -| Field | Required | Type | Description | -|---|---|---|---| -| `id` | Yes | string | Stable identifier. | -| `safeOutputType` | Yes | string | Name of the corresponding gh-aw `safe-outputs` handler key (e.g. `add-comment`, `create-issue`, `create-pull-request`). | -| `text.label` / `text.help` | Yes/No | string | Presentation metadata. | -| `inferFromTriggerTypes` | No | string[] | `triggerOption.type` values this destination is inferred/recommended for. | -| `frontmatter` | No | object | Literal or template fragment of gh-aw `safe-outputs:` configuration contributed by this option. | - -### 4.5 `promptTemplate` - -| Field | Required | Type | Description | -|---|---|---|---| -| `introText` | No | string | Fixed opening text for the generated prompt. MUST establish that the prompt is self-contained and assumes no prior gh-aw installation. | -| `sections` | No | array of `{id, heading}` | Ordered list of named sections used to assemble the final prompt (e.g. goal, trigger, destination, task-details). | - -## 5. Conditional Progression - -The WHAT → WHEN → WHERE flow is expressed declaratively through id references, not through embedded control-flow or Astro-specific logic: - -1. The wizard renders `goalCategories` for the WHAT step. -2. Upon selection of a `goalCategory`, the WHEN step SHOULD present only the `triggerOptions` whose `id` appears in that goal's `triggerOptionIds`, pre-selecting `defaultTriggerOptionId` when present. -3. Upon selection of a `triggerOption`, the WHERE step SHOULD present only the `destinationOptions` whose `id` appears in the goal's `destinationOptionIds`. Implementations SHOULD further narrow or pre-select a destination whose `inferFromTriggerTypes` includes the selected trigger's `type`, allowing this step to be skipped or pre-answered per the parent issue's requirement that WHERE be "mostly automatically inferred." -4. The task-details step is free-form text collected by the UI and is not modeled here beyond the `task-details` prompt section id. - -This mechanism keeps all conditional logic data-driven: any consumer (Astro component or CLI) walks the same three arrays using the same id-matching rules. - -## 6. Prompt Assembly - -Implementations assembling the final prompt MUST: - -- Produce a prompt that is self-contained and runnable in the user's project without assuming gh-aw is already installed or configured. -- Include, at minimum, the selected goal's label/help, the selected trigger's resulting frontmatter intent, the selected (or inferred) destination's resulting frontmatter intent, and the free-form task details. -- Use `promptTemplate.sections` (when present) to order and label these parts; otherwise fall back to the order: goal, trigger, destination, task details. - -### 6.1 Normative Assembly Contract - -The final prompt is the primary output of the wizard. A conforming implementation MUST assemble exactly one final prompt string from four user inputs plus bootstrap guidance: - -1. **WHAT**: the selected `goalCategory`. -2. **WHEN**: the selected `triggerOption` allowed by that goal. -3. **WHERE**: the selected or inferred `destinationOption` allowed by that goal. -4. **Task details**: the user's free-text description. -5. **Bootstrap instructions**: fixed text that explains how to install and run `gh aw` if it is not already available. - -The assembled prompt MUST be ordered as follows, regardless of visual UI layout: - -1. Self-contained bootstrap/setup instructions. -2. Goal summary derived from WHAT. -3. Trigger summary derived from WHEN. -4. Destination summary derived from WHERE. -5. Free-text task details. -6. Final execution request instructing the downstream model to produce a runnable gh-aw workflow. - -The prompt MUST be self-contained. In particular, its wording MUST NOT assume the user already has `gh`, `gh aw`, or any local gh-aw template files installed. The prompt MUST instruct the downstream model to include any necessary install/bootstrap guidance inside its answer. - -When `promptTemplate.sections` is present, implementations SHOULD use its section order and headings if that order preserves the required semantic sequence above. Implementations MUST ignore any `promptTemplate.sections` ordering that would place task details before the required bootstrap/setup context or omit any of the four required answer groups. - -### 6.2 Required Prompt Template - -Conforming implementations MUST generate a prompt equivalent to the following template, with bracketed tokens replaced by resolved values: - -```text -Create a GitHub Agentic Workflow (gh-aw) for this repository. - -Assume nothing is preinstalled. Your answer must be self-contained and MUST include: -- how to install GitHub CLI if needed, -- how to install or run the gh-aw extension if needed, -- the complete workflow markdown file content, -- any required frontmatter and safe-outputs configuration, -- and brief usage instructions for a first-time user. - -WHAT -- Goal: [goal label] -- Context: [goal help text or concise derived summary] - -WHEN -- Trigger: [trigger label] -- Trigger intent: [plain-language summary of trigger frontmatter intent] - -WHERE -- Destination: [destination label] -- Output intent: [plain-language summary of safe-output destination intent] - -TASK DETAILS -[user free-text description] - -Generate one runnable gh-aw workflow that satisfies the WHAT/WHEN/WHERE requirements above. If a required detail is still missing, say exactly what is missing instead of guessing. -``` - -The following is a concrete example of a fully assembled prompt string: - -```text -Create a GitHub Agentic Workflow (gh-aw) for this repository. - -Assume nothing is preinstalled. Your answer must be self-contained and MUST include: -- how to install GitHub CLI if needed, -- how to install or run the gh-aw extension if needed, -- the complete workflow markdown file content, -- any required frontmatter and safe-outputs configuration, -- and brief usage instructions for a first-time user. - -WHAT -- Goal: Scheduled report -- Context: Generate a recurring workflow that gathers information on a schedule and publishes a result for humans to review. - -WHEN -- Trigger: On a schedule -- Trigger intent: Run automatically from a cron-based schedule defined in workflow frontmatter. - -WHERE -- Destination: Create or update a GitHub issue -- Output intent: Deliver the result by creating or updating an issue using safe outputs. - -TASK DETAILS -Every Monday at 09:00 UTC, collect open pull requests labeled needs-review, summarize how long they have been waiting, and post a weekly triage report with sections for urgent items, stale items, and links to each PR. - -Generate one runnable gh-aw workflow that satisfies the WHAT/WHEN/WHERE requirements above. If a required detail is still missing, say exactly what is missing instead of guessing. -``` - -An implementation MAY vary surrounding prose, capitalization, or bullet style, but it MUST preserve the same semantic content and MUST include the self-contained bootstrap requirements. - -### 6.3 Validation Rules for Incomplete Input - -The wizard MUST validate user input before producing the final prompt. It MUST NOT assemble a final prompt if any required input is missing or invalid. - -The following validation rules are REQUIRED: - -| Field | Requirement | Failure behavior | -|---|---|---| -| WHAT / `goalCategory` | REQUIRED. Exactly one allowed goal MUST be selected. | Disable forward progression past WHAT and show an inline validation message. | -| WHEN / `triggerOption` | REQUIRED. Exactly one trigger compatible with the selected goal MUST be selected. | Disable forward progression past WHEN and show an inline validation message. | -| WHERE / `destinationOption` | REQUIRED before completion. It MAY be auto-inferred, but the resulting destination value MUST be explicit in wizard state. | Disable completion and prompt rendering until the destination is inferred or selected. | -| Task details | REQUIRED non-empty trimmed string. | Disable completion and prompt rendering; show an inline validation message. | - -Additional validation requirements: - -- A destination inferred from trigger type is provisional until it resolves to a destination ID that is allowed by the selected goal's `destinationOptionIds`. -- If inference produces zero matches or multiple equally valid matches, the wizard MUST require explicit user selection at the WHERE step. -- A task-details value containing only whitespace MUST be treated as empty. -- Implementations SHOULD require enough text to avoid a vacuous prompt. A minimum of 10 non-whitespace characters is RECOMMENDED. -- If WHAT changes and the existing WHEN or WHERE selection is no longer compatible, those downstream values MUST be cleared before validation runs. -- If WHEN changes and the existing WHERE selection is no longer compatible or no longer inferable, the WHERE value MUST be cleared and re-requested. - -The wizard MUST fail closed: it is better to block prompt generation than to emit a prompt with a missing destination, missing task details, or stale incompatible selections. - -### 6.4 Step Transitions and Back/Next Behavior - -The canonical flow is WHAT → WHEN → WHERE → task details. - -Implementations MUST follow these transition rules: - -1. **Initial entry**: only the WHAT step is active; later steps are disabled or visually unavailable until prerequisite data exists. -2. **Advancing from WHAT to WHEN**: allowed only after a valid WHAT selection exists. -3. **Advancing from WHEN to WHERE**: allowed only after a valid WHEN selection exists. -4. **Advancing from WHERE to task details**: allowed only after a valid WHERE value exists, whether explicitly selected or inferred. -5. **Completion from task details**: allowed only after all prior steps remain valid and task details pass validation. - -Back/next semantics are normative: - -- **Next** MUST run validation for the current step and MUST NOT advance if the step is incomplete. -- **Back** MUST preserve earlier valid answers and MUST allow the user to revise them. -- Revisiting an earlier step and changing its answer MUST trigger downstream revalidation immediately. -- If a downstream answer remains valid after an upstream change, it MAY be preserved. -- If a downstream answer becomes invalid after an upstream change, it MUST be cleared and the user MUST be returned to the earliest now-invalid step before completion is allowed. - -Required reset examples: - -- Changing WHAT from a goal that supports `schedule` to one that does not MUST clear any previously selected scheduled WHEN option. -- Changing WHAT to a goal with a different destination set MUST clear an incompatible WHERE selection. -- Changing WHEN from `issues` to `schedule` MAY replace an inferred comment destination with an inferred issue destination, but only if the new destination is uniquely valid for the current goal. - -### 6.5 Empty-State and Blocking-State Handling - -Before any selection is made, the wizard is in an empty state. - -In the empty state, implementations MUST: - -- Render the WHAT step with no selected answer. -- Present later steps as unavailable, disabled, or clearly marked "Complete the previous step first." -- Avoid showing a final prompt preview, because no conforming prompt can yet be assembled. - -If a user attempts to advance without a required answer, the UI MUST: - -- keep focus on the current step, -- display a clear inline error message near the missing control, -- avoid generating or updating a misleading "partial final prompt", and -- preserve any earlier valid answers already given. - -Recommended empty/blocking copy includes: - -- WHAT not selected: "Choose what this workflow should do before continuing." -- WHEN not selected: "Choose when the workflow should run before continuing." -- WHERE unresolved: "Choose where the workflow should send its result before continuing." -- Task details empty: "Describe the task in enough detail to generate a workflow." - -Implementations MAY show a draft preview before completion, but any such preview MUST be clearly labeled incomplete and MUST NOT be represented as runnable until all completion criteria are met. - -### 6.6 Completion Criteria - -The wizard is "done" only when all of the following are true: - -1. A valid WHAT selection exists. -2. A valid WHEN selection exists and is compatible with WHAT. -3. A valid WHERE value exists, whether selected or inferred, and is compatible with WHAT and WHEN. -4. Task details exist as a non-empty trimmed string. -5. The final prompt string has been assembled with the required self-contained bootstrap/setup wording. - -Only after all five conditions are satisfied MAY the implementation: - -- render the final prompt as complete, -- enable any copy/export action for that prompt, and -- describe the prompt as runnable. - -If any of the above conditions later becomes false because the user edits an earlier step, the wizard MUST revert to an incomplete state and MUST re-run validation before allowing completion again. - -## 7. Versioning and Compatibility - -- `version` follows semver. Additive, backward-compatible changes (new optional fields, new catalog entries) increment MINOR or PATCH. Removing or renaming a required field, or changing the meaning of an existing `id`, MUST increment MAJOR. -- Consumers MUST tolerate unknown additional top-level or nested fields within the same MAJOR version (forward compatibility for future CLI/UI features). -- `id` values are permanent once published; deprecating an option is done by removing it from `goalCategory.triggerOptionIds`/`destinationOptionIds` rather than deleting the catalog entry outright, preserving compatibility for consumers caching older goal-to-option mappings. - -## 8. Future CLI Reuse - -A future `gh aw` CLI consumer (e.g. `gh aw new --wizard`) is expected to: - -- Load the same JSON file (or the published schema URL) used by the docs site, without re-authoring goal/trigger/destination semantics. -- Interpret `frontmatter` fragments on `triggerOption` and `destinationOption` as literal gh-aw workflow frontmatter fragments to merge into a generated `.md` workflow, exactly as the docs wizard would when assembling its generated prompt text. -- Apply the same conditional-progression rules described in Section 5 to drive an equivalent terminal-based WHAT → WHEN → WHERE → task-details flow. - -Because the model has no Astro-specific fields, no adapter layer is required beyond parsing JSON and applying Section 5's id-matching rules. - -## 9. Examples - -See `docs/public/schemas/wizard-data-model.example.json` for a complete example instance covering three goal categories (issue automation, scheduled report, PR review assistant), their compatible triggers/destinations, and a sample `promptTemplate`. - -## References - -- [Safe Outputs MCP Gateway Specification](/gh-aw/specs/safe-outputs-specification/) -- Parent issue: [#53498 — AW wizard in docs](https://github.com/github/gh-aw/issues/53498) -- `docs/public/schemas/mcp-gateway-config.schema.json` (existing schema convention this specification follows) - -## Change Log - -| Version | Date | Change | -|---|---|---| -| 1.1.0 | 2026-08-18 | Added concrete prompt assembly contract: template composition example, input validation rules, step transition/back-next behavior, empty-state handling, and completion criteria (#53515). | -| 1.0.0 | 2026-08-17 | Initial draft: goal categories, trigger options, destination options, prompt template, conditional progression, and future CLI reuse guidance. | diff --git a/docs/src/content/docs/wizard.mdx b/docs/src/content/docs/wizard.mdx deleted file mode 100644 index 416f59034c0..00000000000 --- a/docs/src/content/docs/wizard.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Workflow prompt wizard -description: Build a GitHub Agentic Workflows prompt from guided choices. -sidebar: - label: Workflow prompt wizard - order: 22 ---- - -import Wizard from '../../components/Wizard.astro'; - - diff --git a/docs/src/data/wizard-data-model.json b/docs/src/data/wizard-data-model.json deleted file mode 100644 index 05909ef19a2..00000000000 --- a/docs/src/data/wizard-data-model.json +++ /dev/null @@ -1,175 +0,0 @@ -{ - "$schema": "https://docs.github.com/gh-aw/schemas/wizard-data-model.schema.json", - "version": "1.0.0", - "goalCategories": [ - { - "id": "issue-automation", - "text": { - "label": "Automate issue triage or replies", - "help": "Respond to, label, or triage issues automatically when they are opened or commented on." - }, - "triggerOptionIds": ["on-issue-opened", "on-issue-comment", "slash-command", "manual-dispatch"], - "destinationOptionIds": ["comment-on-issue", "add-labels-to-issue", "close-issue"], - "defaultTriggerOptionId": "on-issue-opened", - "defaultDestinationOptionId": "comment-on-issue" - }, - { - "id": "pr-review-assistant", - "text": { - "label": "Review pull requests automatically", - "help": "Review incoming pull requests and leave feedback or suggested fixes." - }, - "triggerOptionIds": ["on-pull-request", "slash-command", "manual-dispatch"], - "destinationOptionIds": ["comment-on-issue", "open-pull-request"], - "defaultTriggerOptionId": "on-pull-request", - "defaultDestinationOptionId": "comment-on-issue" - }, - { - "id": "scheduled-report", - "text": { - "label": "Generate a recurring report", - "help": "Run on a schedule and publish a summary, digest, or status report." - }, - "triggerOptionIds": ["schedule-daily", "schedule-weekly", "manual-dispatch"], - "destinationOptionIds": ["create-discussion", "open-pull-request", "comment-on-issue"], - "defaultTriggerOptionId": "schedule-daily", - "defaultDestinationOptionId": "create-discussion" - }, - { - "id": "command-responder", - "text": { - "label": "Respond to a slash command", - "help": "Run on-demand when a user types a /command in an issue, PR, or discussion comment." - }, - "triggerOptionIds": ["slash-command", "manual-dispatch"], - "destinationOptionIds": ["comment-on-issue", "open-pull-request", "add-labels-to-issue"], - "defaultTriggerOptionId": "slash-command", - "defaultDestinationOptionId": "comment-on-issue" - }, - { - "id": "discussion-automation", - "text": { - "label": "Automate discussion replies", - "help": "Respond to or summarize discussions automatically when they are created or commented on." - }, - "triggerOptionIds": ["on-discussion-created", "on-discussion-comment", "slash-command", "manual-dispatch"], - "destinationOptionIds": ["comment-on-issue", "create-discussion"], - "defaultTriggerOptionId": "on-discussion-created", - "defaultDestinationOptionId": "comment-on-issue" - }, - { - "id": "ci-triage", - "text": { - "label": "Triage CI failures", - "help": "Investigate failed workflow runs and report findings or open a fix." - }, - "triggerOptionIds": ["on-workflow-run", "manual-dispatch"], - "destinationOptionIds": ["comment-on-issue", "open-pull-request", "create-discussion"], - "defaultTriggerOptionId": "on-workflow-run", - "defaultDestinationOptionId": "comment-on-issue" - } - ], - "triggerOptions": [ - { - "id": "on-issue-opened", - "type": "issues", - "text": { "label": "When an issue is opened", "help": "Fires whenever a new issue is created." }, - "frontmatter": { "on": { "issues": { "types": ["opened"] } } } - }, - { - "id": "on-issue-comment", - "type": "issue_comment", - "text": { "label": "When someone comments on an issue" }, - "frontmatter": { "on": { "issue_comment": { "types": ["created"] } } } - }, - { - "id": "on-pull-request", - "type": "pull_request", - "text": { "label": "When a pull request is opened or updated" }, - "frontmatter": { "on": { "pull_request": { "types": ["opened", "synchronize"] } } } - }, - { - "id": "on-discussion-created", - "type": "discussion", - "text": { "label": "When a discussion is created" }, - "frontmatter": { "on": { "discussion": { "types": ["created"] } } } - }, - { - "id": "on-discussion-comment", - "type": "issue_comment", - "text": { "label": "When someone comments on a discussion" }, - "frontmatter": { "on": { "discussion_comment": { "types": ["created"] } } } - }, - { - "id": "on-workflow-run", - "type": "other", - "text": { "label": "When another workflow run completes", "help": "Fires after a monitored CI workflow run finishes." }, - "frontmatter": { "on": { "workflow_run": { "workflows": ["CI"], "types": ["completed"] } } } - }, - { - "id": "slash-command", - "type": "slash_command", - "text": { "label": "When triggered by a /command comment", "help": "Runs on-demand when a user comments a slash command." }, - "frontmatter": { "on": "/my-bot" } - }, - { - "id": "schedule-daily", - "type": "schedule", - "text": { "label": "Every day" }, - "frontmatter": { "on": { "schedule": "daily" } } - }, - { - "id": "schedule-weekly", - "type": "schedule", - "text": { "label": "Every week" }, - "frontmatter": { "on": { "schedule": "weekly" } } - }, - { - "id": "manual-dispatch", - "type": "workflow_dispatch", - "text": { "label": "Only when run manually" }, - "frontmatter": { "on": "workflow_dispatch" } - } - ], - "destinationOptions": [ - { - "id": "comment-on-issue", - "safeOutputType": "add-comment", - "text": { "label": "Post a comment" }, - "inferFromTriggerTypes": ["issues", "issue_comment", "pull_request", "discussion", "slash_command", "other"] - }, - { - "id": "add-labels-to-issue", - "safeOutputType": "add-labels", - "text": { "label": "Add labels" }, - "inferFromTriggerTypes": ["issues", "slash_command"] - }, - { - "id": "close-issue", - "safeOutputType": "close-issue", - "text": { "label": "Close the issue with a comment" }, - "inferFromTriggerTypes": ["issues"] - }, - { - "id": "open-pull-request", - "safeOutputType": "create-pull-request", - "text": { "label": "Open a pull request" }, - "inferFromTriggerTypes": ["schedule", "pull_request", "workflow_dispatch", "other"] - }, - { - "id": "create-discussion", - "safeOutputType": "create-discussion", - "text": { "label": "Post a discussion" }, - "inferFromTriggerTypes": ["schedule", "workflow_dispatch", "discussion", "other"] - } - ], - "promptTemplate": { - "introText": "You are helping generate a new GitHub Agentic Workflow (gh-aw) markdown file. This prompt is self-contained: run it in your project with an AI coding assistant and it will produce a complete `.md` workflow without assuming any prior gh-aw setup.", - "sections": [ - { "id": "goal", "heading": "Goal" }, - { "id": "trigger", "heading": "Trigger" }, - { "id": "destination", "heading": "Output destination" }, - { "id": "task-details", "heading": "Task details" } - ] - } -} diff --git a/docs/src/lib/wizard/model.test.js b/docs/src/lib/wizard/model.test.js deleted file mode 100644 index 4add7fa92e9..00000000000 --- a/docs/src/lib/wizard/model.test.js +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env node -// @ts-check - -/** - * Unit tests for the AW wizard shared JSON data model validation - * (docs/src/lib/wizard/validation.ts). - * - * These tests exercise `validateModel` directly so malformed wizard data - * model JSON is caught automatically instead of only failing at Astro - * build/import time. - * - * Run with: node docs/src/lib/wizard/model.test.js - */ - -import { validateModel } from './validation.ts'; -import validModel from '../../data/wizard-data-model.json' with { type: 'json' }; - -let passed = 0; -let failed = 0; - -function assertThrows(fn, label) { - try { - fn(); - console.error(` ✗ ${label}`); - console.error(' expected: function to throw'); - console.error(' actual: no error was thrown'); - failed++; - } catch (error) { - console.log(` ✓ ${label} (${/** @type {Error} */ (error).message})`); - passed++; - } -} - -function assertDoesNotThrow(fn, label) { - try { - fn(); - console.log(` ✓ ${label}`); - passed++; - } catch (error) { - console.error(` ✗ ${label}`); - console.error(` expected: function not to throw`); - console.error(` actual: threw ${/** @type {Error} */ (error).message}`); - failed++; - } -} - -function clone(data) { - return JSON.parse(JSON.stringify(data)); -} - -// ------------------------------------------------------------------- -// Test: the real, checked-in wizard data model is valid -// ------------------------------------------------------------------- -console.log('\nreal wizard-data-model.json:'); -{ - assertDoesNotThrow(() => validateModel(clone(validModel)), 'checked-in wizard-data-model.json passes validation'); -} - -// ------------------------------------------------------------------- -// Test: non-object input is rejected -// ------------------------------------------------------------------- -console.log('\nnon-object input:'); -{ - assertThrows(() => validateModel(null), 'null is rejected'); - assertThrows(() => validateModel('not an object'), 'string is rejected'); - assertThrows(() => validateModel([]), 'array is rejected'); -} - -// ------------------------------------------------------------------- -// Test: missing/invalid version field -// ------------------------------------------------------------------- -console.log('\nversion field:'); -{ - const missingVersion = clone(validModel); - delete missingVersion.version; - assertThrows(() => validateModel(missingVersion), 'missing version is rejected'); - - const nonSemverVersion = clone(validModel); - nonSemverVersion.version = '1.0'; - assertThrows(() => validateModel(nonSemverVersion), 'non-semver version ("1.0") is rejected'); -} - -// ------------------------------------------------------------------- -// Test: empty top-level arrays are rejected -// ------------------------------------------------------------------- -console.log('\nempty top-level arrays:'); -{ - const emptyGoals = clone(validModel); - emptyGoals.goalCategories = []; - assertThrows(() => validateModel(emptyGoals), 'empty goalCategories is rejected'); - - const emptyTriggers = clone(validModel); - emptyTriggers.triggerOptions = []; - assertThrows(() => validateModel(emptyTriggers), 'empty triggerOptions is rejected'); - - const emptyDestinations = clone(validModel); - emptyDestinations.destinationOptions = []; - assertThrows(() => validateModel(emptyDestinations), 'empty destinationOptions is rejected'); -} - -// ------------------------------------------------------------------- -// Test: goal category missing required fields -// ------------------------------------------------------------------- -console.log('\ngoal category shape:'); -{ - const missingTriggerIds = clone(validModel); - delete missingTriggerIds.goalCategories[0].triggerOptionIds; - assertThrows(() => validateModel(missingTriggerIds), 'goal category missing triggerOptionIds is rejected'); - - const missingDestinationIds = clone(validModel); - delete missingDestinationIds.goalCategories[0].destinationOptionIds; - assertThrows(() => validateModel(missingDestinationIds), 'goal category missing destinationOptionIds is rejected'); - - const missingGoalText = clone(validModel); - delete missingGoalText.goalCategories[0].text; - assertThrows(() => validateModel(missingGoalText), 'goal category missing text.label is rejected'); -} - -// ------------------------------------------------------------------- -// Test: trigger/destination option missing required fields -// ------------------------------------------------------------------- -console.log('\ntrigger/destination option shape:'); -{ - const missingTriggerType = clone(validModel); - delete missingTriggerType.triggerOptions[0].type; - assertThrows(() => validateModel(missingTriggerType), 'trigger option missing type is rejected'); - - const missingDestinationSafeOutputType = clone(validModel); - delete missingDestinationSafeOutputType.destinationOptions[0].safeOutputType; - assertThrows( - () => validateModel(missingDestinationSafeOutputType), - 'destination option missing safeOutputType is rejected', - ); -} - -// ------------------------------------------------------------------- -// Summary -// ------------------------------------------------------------------- -console.log(`\n${passed} passed, ${failed} failed`); -if (failed > 0) process.exit(1); diff --git a/docs/src/lib/wizard/model.ts b/docs/src/lib/wizard/model.ts deleted file mode 100644 index a48b7235342..00000000000 --- a/docs/src/lib/wizard/model.ts +++ /dev/null @@ -1,17 +0,0 @@ -import modelData from '../../data/wizard-data-model.json'; -import { validateModel, type WizardDataModel } from './validation'; - -export type { - WizardText, - WizardGoalCategory, - WizardTriggerOption, - WizardDestinationOption, - WizardPromptSection, - WizardDataModel, -} from './validation'; - -export { validateModel } from './validation'; - -validateModel(modelData); - -export const wizardDataModel: WizardDataModel = modelData; diff --git a/docs/src/lib/wizard/validation.ts b/docs/src/lib/wizard/validation.ts deleted file mode 100644 index 01700efc160..00000000000 --- a/docs/src/lib/wizard/validation.ts +++ /dev/null @@ -1,97 +0,0 @@ -export interface WizardText { - label: string; - help?: string; -} - -export interface WizardGoalCategory { - id: string; - text: WizardText; - triggerOptionIds: string[]; - destinationOptionIds: string[]; - defaultTriggerOptionId?: string; - defaultDestinationOptionId?: string; -} - -export interface WizardTriggerOption { - id: string; - type: string; - text: WizardText; - frontmatter?: Record; -} - -export interface WizardDestinationOption { - id: string; - safeOutputType: string; - text: WizardText; - inferFromTriggerTypes?: string[]; - frontmatter?: Record; -} - -export interface WizardPromptSection { - id: string; - heading: string; -} - -export interface WizardDataModel { - version: string; - goalCategories: WizardGoalCategory[]; - triggerOptions: WizardTriggerOption[]; - destinationOptions: WizardDestinationOption[]; - promptTemplate?: { - introText?: string; - sections?: WizardPromptSection[]; - }; -} - -function isRecord(value: unknown): value is Record { - return typeof value === 'object' && value !== null && !Array.isArray(value); -} - -function hasText(value: unknown): value is WizardText { - return isRecord(value) && typeof value.label === 'string' && (value.help === undefined || typeof value.help === 'string'); -} - -/** - * Validates that `data` conforms to the shared wizard JSON data model shape, - * throwing a descriptive Error on the first violation found. Used both at - * module load time (via model.ts) and by automated tests to catch malformed - * model data before it reaches the docs build. - */ -export function validateModel(data: unknown): asserts data is WizardDataModel { - if (!isRecord(data)) throw new Error('Wizard data model must be an object.'); - if (typeof data.version !== 'string') throw new Error('Wizard data model version must be a string.'); - if (!/^\d+\.\d+\.\d+$/.test(data.version)) throw new Error('Wizard data model version must use semver.'); - if (!Array.isArray(data.goalCategories) || data.goalCategories.length === 0) { - throw new Error('Wizard data model requires at least one goal category.'); - } - if (!Array.isArray(data.triggerOptions) || data.triggerOptions.length === 0) { - throw new Error('Wizard data model requires at least one trigger option.'); - } - if (!Array.isArray(data.destinationOptions) || data.destinationOptions.length === 0) { - throw new Error('Wizard data model requires at least one destination option.'); - } - - for (const goal of data.goalCategories) { - if (!isRecord(goal) || typeof goal.id !== 'string' || !hasText(goal.text)) { - throw new Error('Each wizard goal category must include id and text.label.'); - } - if (!Array.isArray(goal.triggerOptionIds) || goal.triggerOptionIds.length === 0) { - throw new Error(`Goal category "${goal.id}" must define triggerOptionIds.`); - } - if (!Array.isArray(goal.destinationOptionIds) || goal.destinationOptionIds.length === 0) { - throw new Error(`Goal category "${goal.id}" must define destinationOptionIds.`); - } - } - - for (const trigger of data.triggerOptions) { - if (!isRecord(trigger) || typeof trigger.id !== 'string' || typeof trigger.type !== 'string' || !hasText(trigger.text)) { - throw new Error('Each wizard trigger option must include id, type, and text.label.'); - } - } - - for (const destination of data.destinationOptions) { - if (!isRecord(destination) || typeof destination.id !== 'string' || typeof destination.safeOutputType !== 'string' || !hasText(destination.text)) { - throw new Error('Each wizard destination option must include id, safeOutputType, and text.label.'); - } - } -} diff --git a/docs/tests/wizard.spec.ts b/docs/tests/wizard.spec.ts deleted file mode 100644 index 39a2a4338f2..00000000000 --- a/docs/tests/wizard.spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { expect, test } from "@playwright/test"; - -test.describe("AW wizard page", () => { - test("renders the client-side wizard shell and advances through data-driven steps", async ({ page }) => { - await page.goto("/gh-aw/wizard/"); - await page.waitForLoadState("networkidle"); - - await expect(page.getByRole("heading", { name: "Build an agentic workflow" })).toBeVisible(); - await expect(page.getByText("Step 1 of 5")).toBeVisible(); - await expect(page.getByRole("heading", { name: "Choose a workflow goal" })).toBeVisible(); - - await page.getByLabel("Generate a recurring report").check(); - await page.getByRole("button", { name: "Next" }).click(); - - await expect(page.getByRole("heading", { name: "Choose a trigger" })).toBeVisible(); - await expect(page.getByLabel("Every day")).toBeVisible(); - await expect(page.getByLabel("Every week")).toBeVisible(); - - await page.getByRole("button", { name: "Next" }).click(); - - await expect(page.getByRole("heading", { name: "Review the inferred output destination" })).toBeVisible(); - await expect(page.locator("[data-wizard-summary]")).toContainText("Generate a recurring report"); - await expect(page.locator("[data-wizard-preview]")).toContainText("Destination: Post a discussion"); - - await page.getByRole("button", { name: "Next" }).click(); - await expect(page.getByRole("heading", { name: "Describe the task in your own words" })).toBeVisible(); - await page.getByLabel("Task description").fill("Summarize open issues by priority."); - await page.getByRole("button", { name: "Next" }).click(); - - await expect(page.getByRole("heading", { name: "Copy your generated prompt" })).toBeVisible(); - await expect(page.locator(".aw-wizard__final-prompt-text")).toContainText("Summarize open issues by priority."); - await expect(page.getByRole("button", { name: "Review selections" })).toBeVisible(); - }); - - test("infers a comment destination for the issue automation goal", async ({ page }) => { - await page.goto("/gh-aw/wizard/"); - await page.waitForLoadState("networkidle"); - - await expect(page.getByText("Step 1 of 5")).toBeVisible(); - await page.getByLabel("Automate issue triage or replies").check(); - await page.getByRole("button", { name: "Next" }).click(); - - await expect(page.getByRole("heading", { name: "Choose a trigger" })).toBeVisible(); - await expect(page.getByLabel("When an issue is opened")).toBeVisible(); - await expect(page.getByLabel("When someone comments on an issue")).toBeVisible(); - - await page.getByRole("button", { name: "Next" }).click(); - - await expect(page.getByRole("heading", { name: "Review the inferred output destination" })).toBeVisible(); - await expect(page.locator("[data-wizard-summary]")).toContainText("Automate issue triage or replies"); - await expect(page.locator("[data-wizard-preview]")).toContainText("Destination: Post a comment"); - await expect(page.getByRole("button", { name: "Next" })).toBeVisible(); - }); - - test("styles client-rendered options and avoids mobile overflow", async ({ page }) => { - await page.setViewportSize({ width: 390, height: 844 }); - await page.goto("/gh-aw/wizard/"); - await page.waitForLoadState("networkidle"); - - const wizard = page.locator("[data-aw-wizard]"); - const firstOption = wizard.locator(".aw-wizard__option").first(); - const optionCopy = firstOption.locator(".aw-wizard__option-copy"); - - await expect(firstOption).toBeVisible(); - await expect(firstOption).toHaveCSS("display", "grid"); - await expect(optionCopy).toHaveCSS("display", "grid"); - - const overflow = await wizard.evaluate(element => element.scrollWidth - element.clientWidth); - expect(overflow).toBeLessThanOrEqual(1); - }); -});