From 9d112e900e855ff6838e7ff9fa132e793acb4220 Mon Sep 17 00:00:00 2001 From: scanner Date: Mon, 5 Oct 2026 23:32:57 -0400 Subject: [PATCH 1/5] ci: check out live main in meeting-recordings refresh so auto-commit does not race Signed-off-by: scanner --- .github/workflows/meeting-recordings-refresh.yml | 6 ++++++ changelog.d/fixed-meeting-recordings-refresh-checkout.md | 1 + 2 files changed, 7 insertions(+) create mode 100644 changelog.d/fixed-meeting-recordings-refresh-checkout.md diff --git a/.github/workflows/meeting-recordings-refresh.yml b/.github/workflows/meeting-recordings-refresh.yml index c8ae70d..29b4a54 100644 --- a/.github/workflows/meeting-recordings-refresh.yml +++ b/.github/workflows/meeting-recordings-refresh.yml @@ -16,6 +16,12 @@ jobs: timeout-minutes: 10 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + # On `schedule`, github.sha is main as of trigger time. If the job sits in + # the runner queue (run 37370568225 waited 70 min) that base is stale and + # the auto-commit push below is rejected non-fast-forward. Checking out the + # branch by name fetches the live tip at job start instead. + ref: main - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: '22' diff --git a/changelog.d/fixed-meeting-recordings-refresh-checkout.md b/changelog.d/fixed-meeting-recordings-refresh-checkout.md new file mode 100644 index 0000000..cf68505 --- /dev/null +++ b/changelog.d/fixed-meeting-recordings-refresh-checkout.md @@ -0,0 +1 @@ +- Check out live `main` in the meeting-recordings refresh workflow so the scheduled auto-commit no longer fails with a non-fast-forward push when the job is queued. From 1d875f994e2848e533dd5a0d1b577b7d2e9af863 Mon Sep 17 00:00:00 2001 From: scanner Date: Mon, 5 Oct 2026 23:35:48 -0400 Subject: [PATCH 2/5] style: apply prettier to the repository Signed-off-by: scanner --- .github/aw/github-agentic-workflows.md | 716 +++++----- .github/fuzzing/fuzz-mdx-sanitizer.ts | 212 +-- .github/workflows/markdownlint-cli2.yml | 2 +- .../workflows/meeting-recordings-refresh.yml | 6 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/typecheck.yml | 2 +- .github/workflows/vitest.yml | 2 +- CONTRIBUTING.md | 1 - eslint.config.mjs | 16 +- mdx-components.js | 23 +- netlify/functions/nps.mts | 32 +- netlify/nps-relay/relay.test.ts | 1262 ++++++++++------- netlify/nps-relay/relay.ts | 838 ++++++----- public/403.html | 300 ++-- public/404.html | 300 ++-- runbooks/README.md | 4 +- scripts/check-internal-links-helpers.test.ts | 44 +- scripts/check-internal-links-helpers.ts | 4 +- scripts/check-internal-links.ts | 2 +- scripts/generate-shared-config.test.ts | 28 +- scripts/generate-shared-config.ts | 40 +- scripts/markdown-fences.test.ts | 8 +- scripts/markdown-fences.ts | 3 +- scripts/mdx-to-markdown.test.ts | 58 +- scripts/mdx-to-markdown.ts | 90 +- scripts/npm-audit-gate.test.ts | 14 +- scripts/npm-audit-gate.ts | 14 +- scripts/scrub-legacy-branding.test.ts | 30 +- scripts/scrub-legacy-branding.ts | 65 +- .../sync-hive-docs.case-1-exact-path.test.ts | 11 +- scripts/sync-hive-docs.ts | 7 +- scripts/sync-sibling-docs.test.ts | 58 +- scripts/sync-sibling-docs.ts | 217 ++- scripts/update-meeting-recordings.ts | 190 ++- src/__tests__/DocsFooter.behavior.test.tsx | 29 +- src/__tests__/DocsFooter.copy.test.ts | 69 +- .../ErrorFallbackUI.behavior.test.tsx | 10 +- src/__tests__/Footer.behavior.test.tsx | 49 +- .../LanguageSwitcher.behavior.test.tsx | 8 +- src/__tests__/MeetingsPage.behavior.test.tsx | 471 +++--- src/__tests__/Navbar.behavior.test.tsx | 35 +- src/__tests__/NotFoundUI.behavior.test.tsx | 49 +- src/__tests__/NotFoundUI.copy.test.ts | 56 +- .../RelatedProjects.behavior.test.tsx | 50 +- .../TableOfContents.behavior.test.tsx | 6 +- src/__tests__/ThemeToggle.behavior.test.tsx | 16 +- .../VersionSelector.behavior.test.tsx | 9 +- .../buildPageMapForBranch-wrapper.test.ts | 67 +- .../check-internal-links-helpers.test.ts | 35 +- .../communityMeetingsSchedule.test.ts | 103 +- ...docs-image-route.containment-guard.test.ts | 65 +- .../docs-image-route.readfile-throws.test.ts | 56 +- src/__tests__/docs-image-route.test.ts | 255 ++-- .../docs-layout.metadata-jsonld.test.tsx | 354 +++-- .../docs-page-render.spektacular.test.ts | 148 +- src/__tests__/docs-page-render.test.ts | 95 +- .../docs-slug-page.params-metadata.test.tsx | 333 +++-- src/__tests__/fetchConfig.test.ts | 370 ++--- src/__tests__/gtagEvent.test.ts | 102 +- src/__tests__/healthz-route.test.ts | 219 +-- src/__tests__/i18n-settings.test.ts | 64 +- src/__tests__/logger.test.ts | 58 +- src/__tests__/metrics-3xx-branch.test.ts | 42 +- src/__tests__/metrics-edge-branches.test.ts | 78 +- src/__tests__/metrics-route.test.ts | 26 +- src/__tests__/metrics.test.ts | 42 +- src/__tests__/page-map-hive-arm.test.ts | 101 +- src/__tests__/proxy.test.ts | 165 ++- src/__tests__/remarkStripMdxJs.test.ts | 221 +-- src/__tests__/rewriteImagePaths.test.ts | 127 +- src/__tests__/robots.test.ts | 20 +- .../sanitize.contributor-and-img.test.ts | 218 +-- ...anitize.contributor-non-github-url.test.ts | 68 +- .../sanitize.contributor-nongithub.test.ts | 46 +- src/__tests__/sanitize.test.ts | 711 ++++++---- src/__tests__/search-route.extra.test.ts | 296 ++-- .../search-route.hive-project-file.test.ts | 112 +- .../search-route.non-error-throw.test.ts | 87 +- .../search-route.sort-comparator.test.ts | 139 +- src/__tests__/search-route.test.ts | 212 +-- .../search-route.title-only-long.test.ts | 88 +- src/__tests__/sitemap.test.ts | 217 +-- ...nsformMdx.escaped-bracket-fallback.test.ts | 36 +- .../transformMdx.escaped-close.test.ts | 44 +- src/__tests__/transformMdx.lt-paren.test.ts | 42 +- src/__tests__/transformMdx.test.ts | 612 ++++---- ...ransformMdx.tilde-fence-and-closer.test.ts | 87 +- src/__tests__/url.getLocalizedUrl.test.ts | 138 +- src/__tests__/url.test.ts | 174 +-- src/__tests__/useGithubStats.effect.test.tsx | 150 +- src/__tests__/useGithubStats.test.tsx | 86 +- src/__tests__/useSharedConfig.fetch.test.ts | 343 +++-- src/__tests__/useSharedConfig.hook.test.tsx | 188 +-- ...aredConfig.merge-fallback-branches.test.ts | 227 +-- src/__tests__/useSharedConfig.test.ts | 201 +-- src/__tests__/versions.test.ts | 310 ++-- src/app/[locale]/layout.tsx | 24 +- src/app/api/docs-image/[...path]/route.ts | 94 +- src/app/api/healthz/route.ts | 54 +- src/app/api/metrics/route.ts | 8 +- src/app/api/search/route.ts | 183 +-- src/app/error.tsx | 7 +- src/app/globals.css | 202 ++- src/app/robots.ts | 10 +- src/app/sitemap.ts | 109 +- src/components/ErrorFallbackUI.tsx | 46 +- src/components/Footer.tsx | 18 +- src/components/GoogleAnalytics.tsx | 2 +- src/components/Navbar.tsx | 103 +- src/components/NotFoundUI.tsx | 83 +- .../animations/globe/NetworkGlobe.tsx | 1 - src/components/community/MeetingsPage.tsx | 370 +++-- src/components/navbar/useNavDropdowns.ts | 4 +- src/config/community-meetings.ts | 56 +- src/config/versions.ts | 126 +- src/hooks/useSharedConfig.ts | 57 +- src/lib/communityMeetingsSchedule.ts | 159 ++- src/lib/logger.ts | 28 +- src/lib/metrics.ts | 34 +- src/lib/remarkStripMdxJs.ts | 45 +- src/lib/rewriteImagePaths.ts | 25 +- src/lib/sanitizeHtml.ts | 371 ++--- src/lib/transformMdx.ts | 10 +- src/lib/url.ts | 2 +- src/proxy.ts | 14 +- tsconfig.json | 15 +- vitest.config.ts | 33 +- 127 files changed, 8977 insertions(+), 6752 deletions(-) diff --git a/.github/aw/github-agentic-workflows.md b/.github/aw/github-agentic-workflows.md index 115efca..d96b749 100644 --- a/.github/aw/github-agentic-workflows.md +++ b/.github/aw/github-agentic-workflows.md @@ -158,362 +158,364 @@ The YAML frontmatter supports these fields: version: "3.12" action-repo: "actions/setup-python" action-version: "v5" - ``` - -- **`jobs:`** - Groups together all the jobs that run in the workflow (object) - - Standard GitHub Actions jobs configuration - - Each job can have: `name`, `runs-on`, `steps`, `needs`, `if`, `env`, `permissions`, `timeout-minutes`, etc. - - For most agentic workflows, jobs are auto-generated; only specify this for advanced multi-job workflows - - Example: - ```yaml - jobs: - custom-job: - runs-on: ubuntu-latest - steps: - - name: Custom step - run: echo "Custom job" - ``` - -- **`engine:`** - AI processor configuration - - String format: `"copilot"` (default, recommended), `"custom"` (user-defined steps) - - ⚠️ **Experimental engines**: `"claude"` and `"codex"` are available but experimental - - Object format for extended configuration: - ```yaml - engine: - id: copilot # Required: coding agent identifier (copilot, custom, or experimental: claude, codex) - version: beta # Optional: version of the action (has sensible default) - model: gpt-5 # Optional: LLM model to use (has sensible default) - max-turns: 5 # Optional: maximum chat iterations per run (has sensible default) - max-concurrency: 3 # Optional: max concurrent workflows across all workflows (default: 3) - env: # Optional: custom environment variables (object) - DEBUG_MODE: "true" - args: ["--verbose"] # Optional: custom CLI arguments injected before prompt (array) - error_patterns: # Optional: custom error pattern recognition (array) - - pattern: "ERROR: (.+)" - level_group: 1 - ``` - - **Note**: The `version`, `model`, `max-turns`, and `max-concurrency` fields have sensible defaults and can typically be omitted unless you need specific customization. - - **Custom engine format** (⚠️ experimental): - - ```yaml - engine: - id: custom # Required: custom engine identifier - max-turns: 10 # Optional: maximum iterations (for consistency) - max-concurrency: 5 # Optional: max concurrent workflows (for consistency) - steps: # Required: array of custom GitHub Actions steps - - name: Run tests - run: npm test ``` - The `custom` engine allows you to define your own GitHub Actions steps instead of using an AI processor. Each step in the `steps` array follows standard GitHub Actions step syntax with `name`, `uses`/`run`, `with`, `env`, etc. This is useful for deterministic workflows that don't require AI processing. - - **Environment Variables Available to Custom Engines:** - - Custom engine steps have access to the following environment variables: - - **`$GH_AW_PROMPT`**: Path to the generated prompt file (`/tmp/gh-aw/aw-prompts/prompt.txt`) containing the markdown content from the workflow. This file contains the natural language instructions that would normally be sent to an AI processor. Custom engines can read this file to access the workflow's markdown content programmatically. - - **`$GH_AW_SAFE_OUTPUTS`**: Path to the safe outputs file (when safe-outputs are configured). Used for writing structured output that gets processed automatically. - - **`$GH_AW_MAX_TURNS`**: Maximum number of turns/iterations (when max-turns is configured in engine config). +```` - Example of accessing the prompt content: - - ```bash - # Read the workflow prompt content - cat $GH_AW_PROMPT +- **`jobs:`** - Groups together all the jobs that run in the workflow (object) + - Standard GitHub Actions jobs configuration + - Each job can have: `name`, `runs-on`, `steps`, `needs`, `if`, `env`, `permissions`, `timeout-minutes`, etc. + - For most agentic workflows, jobs are auto-generated; only specify this for advanced multi-job workflows + - Example: + ```yaml + jobs: + custom-job: + runs-on: ubuntu-latest + steps: + - name: Custom step + run: echo "Custom job" + ``` - # Process the prompt content in a custom step - - name: Process workflow instructions - run: | - echo "Workflow instructions:" - cat $GH_AW_PROMPT - # Add your custom processing logic here - ``` +- **`engine:`** - AI processor configuration + - String format: `"copilot"` (default, recommended), `"custom"` (user-defined steps) + - ⚠️ **Experimental engines**: `"claude"` and `"codex"` are available but experimental + - Object format for extended configuration: + ```yaml + engine: + id: copilot # Required: coding agent identifier (copilot, custom, or experimental: claude, codex) + version: beta # Optional: version of the action (has sensible default) + model: gpt-5 # Optional: LLM model to use (has sensible default) + max-turns: 5 # Optional: maximum chat iterations per run (has sensible default) + max-concurrency: 3 # Optional: max concurrent workflows across all workflows (default: 3) + env: # Optional: custom environment variables (object) + DEBUG_MODE: "true" + args: ["--verbose"] # Optional: custom CLI arguments injected before prompt (array) + error_patterns: # Optional: custom error pattern recognition (array) + - pattern: "ERROR: (.+)" + level_group: 1 + ``` + - **Note**: The `version`, `model`, `max-turns`, and `max-concurrency` fields have sensible defaults and can typically be omitted unless you need specific customization. + - **Custom engine format** (⚠️ experimental): + + ```yaml + engine: + id: custom # Required: custom engine identifier + max-turns: 10 # Optional: maximum iterations (for consistency) + max-concurrency: 5 # Optional: max concurrent workflows (for consistency) + steps: # Required: array of custom GitHub Actions steps + - name: Run tests + run: npm test + ``` + + The `custom` engine allows you to define your own GitHub Actions steps instead of using an AI processor. Each step in the `steps` array follows standard GitHub Actions step syntax with `name`, `uses`/`run`, `with`, `env`, etc. This is useful for deterministic workflows that don't require AI processing. + + **Environment Variables Available to Custom Engines:** + + Custom engine steps have access to the following environment variables: + - **`$GH_AW_PROMPT`**: Path to the generated prompt file (`/tmp/gh-aw/aw-prompts/prompt.txt`) containing the markdown content from the workflow. This file contains the natural language instructions that would normally be sent to an AI processor. Custom engines can read this file to access the workflow's markdown content programmatically. + - **`$GH_AW_SAFE_OUTPUTS`**: Path to the safe outputs file (when safe-outputs are configured). Used for writing structured output that gets processed automatically. + - **`$GH_AW_MAX_TURNS`**: Maximum number of turns/iterations (when max-turns is configured in engine config). + + Example of accessing the prompt content: + + ```bash + # Read the workflow prompt content + cat $GH_AW_PROMPT + + # Process the prompt content in a custom step + - name: Process workflow instructions + run: | + echo "Workflow instructions:" + cat $GH_AW_PROMPT + # Add your custom processing logic here + ``` - **`network:`** - Network access control for AI engines (top-level field) - - String format: `"defaults"` (curated allow-list of development domains) - - Empty object format: `{}` (no network access) - - Object format for custom permissions: - ```yaml - network: - allowed: - - "example.com" - - "*.trusted-domain.com" - firewall: true # Optional: Enable AWF (Agent Workflow Firewall) for Copilot engine - ``` - - **Firewall configuration** (Copilot engine only): - ```yaml - network: - firewall: - version: "v1.0.0" # Optional: AWF version (defaults to latest) - log-level: debug # Optional: debug, info (default), warn, error - args: ["--custom-arg", "value"] # Optional: additional AWF arguments - ``` + - String format: `"defaults"` (curated allow-list of development domains) + - Empty object format: `{}` (no network access) + - Object format for custom permissions: + ```yaml + network: + allowed: + - "example.com" + - "*.trusted-domain.com" + firewall: true # Optional: Enable AWF (Agent Workflow Firewall) for Copilot engine + ``` + - **Firewall configuration** (Copilot engine only): + ```yaml + network: + firewall: + version: "v1.0.0" # Optional: AWF version (defaults to latest) + log-level: debug # Optional: debug, info (default), warn, error + args: ["--custom-arg", "value"] # Optional: additional AWF arguments + ``` - **`tools:`** - Tool configuration for coding agent - - `github:` - GitHub API tools - - `allowed:` - Array of allowed GitHub API functions - - `mode:` - "local" (Docker, default) or "remote" (hosted) - - `version:` - MCP server version (local mode only) - - `args:` - Additional command-line arguments (local mode only) - - `read-only:` - Restrict to read-only operations (boolean) - - `github-token:` - Custom GitHub token - - `toolsets:` - Enable specific GitHub toolset groups (array only) - - **Default toolsets** (when unspecified): `context`, `repos`, `issues`, `pull_requests`, `users` - - **All toolsets**: `context`, `repos`, `issues`, `pull_requests`, `actions`, `code_security`, `dependabot`, `discussions`, `experiments`, `gists`, `labels`, `notifications`, `orgs`, `projects`, `secret_protection`, `security_advisories`, `stargazers`, `users`, `search` - - Use `[default]` for recommended toolsets, `[all]` to enable everything - - Examples: `toolsets: [default]`, `toolsets: [default, discussions]`, `toolsets: [repos, issues]` - - **Recommended**: Prefer `toolsets:` over `allowed:` for better organization and reduced configuration verbosity - - `agentic-workflows:` - GitHub Agentic Workflows MCP server for workflow introspection - - Provides tools for: - - `status` - Show status of workflow files in the repository - - `compile` - Compile markdown workflows to YAML - - `logs` - Download and analyze workflow run logs - - `audit` - Investigate workflow run failures and generate reports - - **Use case**: Enable AI agents to analyze GitHub Actions traces and improve workflows based on execution history - - **Example**: Configure with `agentic-workflows: true` or `agentic-workflows:` (no additional configuration needed) - - `edit:` - File editing tools (required to write to files in the repository) - - `web-fetch:` - Web content fetching tools - - `web-search:` - Web search tools - - `bash:` - Shell command tools - - `playwright:` - Browser automation tools - - Custom tool names for MCP servers + - `github:` - GitHub API tools + - `allowed:` - Array of allowed GitHub API functions + - `mode:` - "local" (Docker, default) or "remote" (hosted) + - `version:` - MCP server version (local mode only) + - `args:` - Additional command-line arguments (local mode only) + - `read-only:` - Restrict to read-only operations (boolean) + - `github-token:` - Custom GitHub token + - `toolsets:` - Enable specific GitHub toolset groups (array only) + - **Default toolsets** (when unspecified): `context`, `repos`, `issues`, `pull_requests`, `users` + - **All toolsets**: `context`, `repos`, `issues`, `pull_requests`, `actions`, `code_security`, `dependabot`, `discussions`, `experiments`, `gists`, `labels`, `notifications`, `orgs`, `projects`, `secret_protection`, `security_advisories`, `stargazers`, `users`, `search` + - Use `[default]` for recommended toolsets, `[all]` to enable everything + - Examples: `toolsets: [default]`, `toolsets: [default, discussions]`, `toolsets: [repos, issues]` + - **Recommended**: Prefer `toolsets:` over `allowed:` for better organization and reduced configuration verbosity + - `agentic-workflows:` - GitHub Agentic Workflows MCP server for workflow introspection + - Provides tools for: + - `status` - Show status of workflow files in the repository + - `compile` - Compile markdown workflows to YAML + - `logs` - Download and analyze workflow run logs + - `audit` - Investigate workflow run failures and generate reports + - **Use case**: Enable AI agents to analyze GitHub Actions traces and improve workflows based on execution history + - **Example**: Configure with `agentic-workflows: true` or `agentic-workflows:` (no additional configuration needed) + - `edit:` - File editing tools (required to write to files in the repository) + - `web-fetch:` - Web content fetching tools + - `web-search:` - Web search tools + - `bash:` - Shell command tools + - `playwright:` - Browser automation tools + - Custom tool names for MCP servers - **`safe-outputs:`** - Safe output processing configuration (preferred way to handle GitHub API write operations) - - `create-issue:` - Safe GitHub issue creation (bugs, features) - - ```yaml - safe-outputs: - create-issue: - title-prefix: "[ai] " # Optional: prefix for issue titles - labels: [automation, agentic] # Optional: labels to attach to issues - assignees: [user1, copilot] # Optional: assignees (use 'copilot' for bot) - max: 5 # Optional: maximum number of issues (default: 1) - target-repo: "owner/repo" # Optional: cross-repository - ``` - - When using `safe-outputs.create-issue`, the main job does **not** need `issues: write` permission since issue creation is handled by a separate job with appropriate permissions. - - **Temporary IDs and Sub-Issues:** - When creating multiple issues, use `temporary_id` (format: `aw_` + 12 hex chars) to reference parent issues before creation. References like `#aw_abc123def456` in issue bodies are automatically replaced with actual issue numbers. Use the `parent` field to create sub-issue relationships: - - ```json - {"type": "create_issue", "temporary_id": "aw_abc123def456", "title": "Parent", "body": "Parent issue"} - {"type": "create_issue", "parent": "aw_abc123def456", "title": "Sub-task", "body": "References #aw_abc123def456"} - ``` - - - `close-issue:` - Close issues with comment - ```yaml - safe-outputs: - close-issue: - target: "triggering" # Optional: "triggering" (default), "*", or number - required-labels: [automated] # Optional: only close with any of these labels - required-title-prefix: "[bot]" # Optional: only close matching prefix - max: 20 # Optional: max closures (default: 1) - target-repo: "owner/repo" # Optional: cross-repository - ``` - - `create-discussion:` - Safe GitHub discussion creation (status, audits, reports, logs) - - ```yaml - safe-outputs: - create-discussion: - title-prefix: "[ai] " # Optional: prefix for discussion titles - category: "General" # Optional: discussion category name, slug, or ID (defaults to first category if not specified) - max: 3 # Optional: maximum number of discussions (default: 1) - target-repo: "owner/repo" # Optional: cross-repository - ``` - - The `category` field is optional and can be specified by name (e.g., "General"), slug (e.g., "general"), or ID (e.g., "DIC_kwDOGFsHUM4BsUn3"). If not specified, discussions will be created in the first available category. Category resolution tries ID first, then name, then slug. - - When using `safe-outputs.create-discussion`, the main job does **not** need `discussions: write` permission since discussion creation is handled by a separate job with appropriate permissions. - - - `close-discussion:` - Close discussions with comment and resolution - ```yaml - safe-outputs: - close-discussion: - target: "triggering" # Optional: "triggering" (default), "*", or number - required-category: "Ideas" # Optional: only close in category - required-labels: [resolved] # Optional: only close with labels - required-title-prefix: "[ai]" # Optional: only close matching prefix - max: 1 # Optional: max closures (default: 1) - target-repo: "owner/repo" # Optional: cross-repository - ``` - Resolution reasons: `RESOLVED`, `DUPLICATE`, `OUTDATED`, `ANSWERED`. - - `add-comment:` - Safe comment creation on issues/PRs/discussions - ```yaml - safe-outputs: - add-comment: - max: 3 # Optional: maximum number of comments (default: 1) - target: "*" # Optional: target for comments (default: "triggering") - discussion: true # Optional: target discussions - target-repo: "owner/repo" # Optional: cross-repository - ``` - When using `safe-outputs.add-comment`, the main job does **not** need `issues: write` or `pull-requests: write` permissions since comment creation is handled by a separate job with appropriate permissions. - - `create-pull-request:` - Safe pull request creation with git patches - ```yaml - safe-outputs: - create-pull-request: - title-prefix: "[ai] " # Optional: prefix for PR titles - labels: [automation, ai-agent] # Optional: labels to attach to PRs - reviewers: [user1, copilot] # Optional: reviewers (use 'copilot' for bot) - draft: true # Optional: create as draft PR (defaults to true) - if-no-changes: "warn" # Optional: "warn" (default), "error", or "ignore" - target-repo: "owner/repo" # Optional: cross-repository - ``` - When using `output.create-pull-request`, the main job does **not** need `contents: write` or `pull-requests: write` permissions since PR creation is handled by a separate job with appropriate permissions. - - `create-pull-request-review-comment:` - Safe PR review comment creation on code lines - ```yaml - safe-outputs: - create-pull-request-review-comment: - max: 3 # Optional: maximum number of review comments (default: 1) - side: "RIGHT" # Optional: side of diff ("LEFT" or "RIGHT", default: "RIGHT") - target: "*" # Optional: "triggering" (default), "*", or number - target-repo: "owner/repo" # Optional: cross-repository - ``` - When using `safe-outputs.create-pull-request-review-comment`, the main job does **not** need `pull-requests: write` permission since review comment creation is handled by a separate job with appropriate permissions. - - `update-issue:` - Safe issue updates - ```yaml - safe-outputs: - update-issue: - status: true # Optional: allow updating issue status (open/closed) - target: "*" # Optional: target for updates (default: "triggering") - title: true # Optional: allow updating issue title - body: true # Optional: allow updating issue body - max: 3 # Optional: maximum number of issues to update (default: 1) - target-repo: "owner/repo" # Optional: cross-repository - ``` - When using `safe-outputs.update-issue`, the main job does **not** need `issues: write` permission since issue updates are handled by a separate job with appropriate permissions. - - `update-pull-request:` - Update PR title or body - ```yaml - safe-outputs: - update-pull-request: - title: true # Optional: enable title updates (default: true) - body: true # Optional: enable body updates (default: true) - max: 1 # Optional: max updates (default: 1) - target: "*" # Optional: "triggering" (default), "*", or number - target-repo: "owner/repo" # Optional: cross-repository - ``` - Operation types: `append` (default), `prepend`, `replace`. - - `close-pull-request:` - Safe pull request closing with filtering - ```yaml - safe-outputs: - close-pull-request: - required-labels: [test, automated] # Optional: only close PRs with these labels - required-title-prefix: "[bot]" # Optional: only close PRs with this title prefix - target: "triggering" # Optional: "triggering" (default), "*" (any PR), or explicit PR number - max: 10 # Optional: maximum number of PRs to close (default: 1) - target-repo: "owner/repo" # Optional: cross-repository - ``` - When using `safe-outputs.close-pull-request`, the main job does **not** need `pull-requests: write` permission since PR closing is handled by a separate job with appropriate permissions. - - `add-labels:` - Safe label addition to issues or PRs - ```yaml - safe-outputs: - add-labels: - allowed: [bug, enhancement, documentation] # Optional: restrict to specific labels - max: 3 # Optional: maximum number of labels (default: 3) - target: "*" # Optional: "triggering" (default), "*" (any issue/PR), or number - target-repo: "owner/repo" # Optional: cross-repository - ``` - When using `safe-outputs.add-labels`, the main job does **not** need `issues: write` or `pull-requests: write` permission since label addition is handled by a separate job with appropriate permissions. - - `add-reviewer:` - Add reviewers to pull requests - ```yaml - safe-outputs: - add-reviewer: - reviewers: [user1, copilot] # Optional: restrict to specific reviewers - max: 3 # Optional: max reviewers (default: 3) - target: "*" # Optional: "triggering" (default), "*", or number - target-repo: "owner/repo" # Optional: cross-repository - ``` - Use `reviewers: copilot` to assign Copilot PR reviewer bot. Requires PAT as `COPILOT_GITHUB_TOKEN`. - - `assign-milestone:` - Assign issues to milestones - ```yaml - safe-outputs: - assign-milestone: - allowed: [v1.0, v2.0] # Optional: restrict to specific milestone titles - max: 1 # Optional: max assignments (default: 1) - target-repo: "owner/repo" # Optional: cross-repository - ``` - - `link-sub-issue:` - Safe sub-issue linking - ```yaml - safe-outputs: - link-sub-issue: - parent-required-labels: [epic] # Optional: parent must have these labels - parent-title-prefix: "[Epic]" # Optional: parent must match this prefix - sub-required-labels: [task] # Optional: sub-issue must have these labels - sub-title-prefix: "[Task]" # Optional: sub-issue must match this prefix - max: 1 # Optional: maximum number of links (default: 1) - target-repo: "owner/repo" # Optional: cross-repository - ``` - Links issues as sub-issues using GitHub's parent-child relationships. Agent output includes `parent_issue_number` and `sub_issue_number`. Use with `create-issue` temporary IDs or existing issue numbers. - - `update-project:` - Manage GitHub Projects boards - ```yaml - safe-outputs: - update-project: - max: 20 # Optional: max project operations (default: 10) - github-token: ${{ secrets.PROJECTS_PAT }} # Optional: token with projects:write - ``` - Not supported for cross-repository operations. - - `push-to-pull-request-branch:` - Push changes to PR branch - ```yaml - safe-outputs: - push-to-pull-request-branch: - target: "*" # Optional: "triggering" (default), "*", or number - title-prefix: "[bot] " # Optional: require title prefix - labels: [automated] # Optional: require all labels - if-no-changes: "warn" # Optional: "warn" (default), "error", or "ignore" - ``` - Not supported for cross-repository operations. - - `update-release:` - Update GitHub release descriptions - ```yaml - safe-outputs: - update-release: - max: 1 # Optional: max releases (default: 1, max: 10) - target-repo: "owner/repo" # Optional: cross-repository - github-token: ${{ secrets.CUSTOM_TOKEN }} # Optional: custom token - ``` - Operation types: `replace`, `append`, `prepend`. - - `create-code-scanning-alert:` - Generate SARIF security advisories - ```yaml - safe-outputs: - create-code-scanning-alert: - max: 50 # Optional: max findings (default: unlimited) - ``` - Severity levels: error, warning, info, note. - - `create-agent-task:` - Create GitHub Copilot agent tasks - ```yaml - safe-outputs: - create-agent-task: - base: main # Optional: base branch (defaults to current) - target-repo: "owner/repo" # Optional: cross-repository - ``` - Requires PAT as `COPILOT_GITHUB_TOKEN`. - - `assign-to-agent:` - Assign Copilot agents to issues - ```yaml - safe-outputs: - assign-to-agent: - name: "copilot" # Optional: agent name - target-repo: "owner/repo" # Optional: cross-repository - ``` - Requires PAT with elevated permissions as `GH_AW_AGENT_TOKEN`. - - `noop:` - Log completion message for transparency (auto-enabled) - ```yaml - safe-outputs: - noop: - ``` - The noop safe-output provides a fallback mechanism ensuring workflows never complete silently. When enabled (automatically by default), agents can emit human-visible messages even when no other actions are required (e.g., "Analysis complete - no issues found"). This ensures every workflow run produces visible output. - - `missing-tool:` - Report missing tools or functionality (auto-enabled) - ```yaml - safe-outputs: - missing-tool: - ``` - The missing-tool safe-output allows agents to report when they need tools or functionality not currently available. This is automatically enabled by default and helps track feature requests from agents. - - **Global Safe Output Configuration:** - - `github-token:` - Custom GitHub token for all safe output jobs - ```yaml - safe-outputs: - create-issue: - add-comment: - github-token: ${{ secrets.CUSTOM_PAT }} # Use custom PAT instead of GITHUB_TOKEN - ``` - Useful when you need additional permissions or want to perform actions across repositories. + - `create-issue:` - Safe GitHub issue creation (bugs, features) + + ```yaml + safe-outputs: + create-issue: + title-prefix: "[ai] " # Optional: prefix for issue titles + labels: [automation, agentic] # Optional: labels to attach to issues + assignees: [user1, copilot] # Optional: assignees (use 'copilot' for bot) + max: 5 # Optional: maximum number of issues (default: 1) + target-repo: "owner/repo" # Optional: cross-repository + ``` + + When using `safe-outputs.create-issue`, the main job does **not** need `issues: write` permission since issue creation is handled by a separate job with appropriate permissions. + + **Temporary IDs and Sub-Issues:** + When creating multiple issues, use `temporary_id` (format: `aw_` + 12 hex chars) to reference parent issues before creation. References like `#aw_abc123def456` in issue bodies are automatically replaced with actual issue numbers. Use the `parent` field to create sub-issue relationships: + + ```json + {"type": "create_issue", "temporary_id": "aw_abc123def456", "title": "Parent", "body": "Parent issue"} + {"type": "create_issue", "parent": "aw_abc123def456", "title": "Sub-task", "body": "References #aw_abc123def456"} + ``` + + - `close-issue:` - Close issues with comment + ```yaml + safe-outputs: + close-issue: + target: "triggering" # Optional: "triggering" (default), "*", or number + required-labels: [automated] # Optional: only close with any of these labels + required-title-prefix: "[bot]" # Optional: only close matching prefix + max: 20 # Optional: max closures (default: 1) + target-repo: "owner/repo" # Optional: cross-repository + ``` + - `create-discussion:` - Safe GitHub discussion creation (status, audits, reports, logs) + + ```yaml + safe-outputs: + create-discussion: + title-prefix: "[ai] " # Optional: prefix for discussion titles + category: "General" # Optional: discussion category name, slug, or ID (defaults to first category if not specified) + max: 3 # Optional: maximum number of discussions (default: 1) + target-repo: "owner/repo" # Optional: cross-repository + ``` + + The `category` field is optional and can be specified by name (e.g., "General"), slug (e.g., "general"), or ID (e.g., "DIC_kwDOGFsHUM4BsUn3"). If not specified, discussions will be created in the first available category. Category resolution tries ID first, then name, then slug. + + When using `safe-outputs.create-discussion`, the main job does **not** need `discussions: write` permission since discussion creation is handled by a separate job with appropriate permissions. + + - `close-discussion:` - Close discussions with comment and resolution + ```yaml + safe-outputs: + close-discussion: + target: "triggering" # Optional: "triggering" (default), "*", or number + required-category: "Ideas" # Optional: only close in category + required-labels: [resolved] # Optional: only close with labels + required-title-prefix: "[ai]" # Optional: only close matching prefix + max: 1 # Optional: max closures (default: 1) + target-repo: "owner/repo" # Optional: cross-repository + ``` + Resolution reasons: `RESOLVED`, `DUPLICATE`, `OUTDATED`, `ANSWERED`. + - `add-comment:` - Safe comment creation on issues/PRs/discussions + ```yaml + safe-outputs: + add-comment: + max: 3 # Optional: maximum number of comments (default: 1) + target: "*" # Optional: target for comments (default: "triggering") + discussion: true # Optional: target discussions + target-repo: "owner/repo" # Optional: cross-repository + ``` + When using `safe-outputs.add-comment`, the main job does **not** need `issues: write` or `pull-requests: write` permissions since comment creation is handled by a separate job with appropriate permissions. + - `create-pull-request:` - Safe pull request creation with git patches + ```yaml + safe-outputs: + create-pull-request: + title-prefix: "[ai] " # Optional: prefix for PR titles + labels: [automation, ai-agent] # Optional: labels to attach to PRs + reviewers: [user1, copilot] # Optional: reviewers (use 'copilot' for bot) + draft: true # Optional: create as draft PR (defaults to true) + if-no-changes: "warn" # Optional: "warn" (default), "error", or "ignore" + target-repo: "owner/repo" # Optional: cross-repository + ``` + When using `output.create-pull-request`, the main job does **not** need `contents: write` or `pull-requests: write` permissions since PR creation is handled by a separate job with appropriate permissions. + - `create-pull-request-review-comment:` - Safe PR review comment creation on code lines + ```yaml + safe-outputs: + create-pull-request-review-comment: + max: 3 # Optional: maximum number of review comments (default: 1) + side: "RIGHT" # Optional: side of diff ("LEFT" or "RIGHT", default: "RIGHT") + target: "*" # Optional: "triggering" (default), "*", or number + target-repo: "owner/repo" # Optional: cross-repository + ``` + When using `safe-outputs.create-pull-request-review-comment`, the main job does **not** need `pull-requests: write` permission since review comment creation is handled by a separate job with appropriate permissions. + - `update-issue:` - Safe issue updates + ```yaml + safe-outputs: + update-issue: + status: true # Optional: allow updating issue status (open/closed) + target: "*" # Optional: target for updates (default: "triggering") + title: true # Optional: allow updating issue title + body: true # Optional: allow updating issue body + max: 3 # Optional: maximum number of issues to update (default: 1) + target-repo: "owner/repo" # Optional: cross-repository + ``` + When using `safe-outputs.update-issue`, the main job does **not** need `issues: write` permission since issue updates are handled by a separate job with appropriate permissions. + - `update-pull-request:` - Update PR title or body + ```yaml + safe-outputs: + update-pull-request: + title: true # Optional: enable title updates (default: true) + body: true # Optional: enable body updates (default: true) + max: 1 # Optional: max updates (default: 1) + target: "*" # Optional: "triggering" (default), "*", or number + target-repo: "owner/repo" # Optional: cross-repository + ``` + Operation types: `append` (default), `prepend`, `replace`. + - `close-pull-request:` - Safe pull request closing with filtering + ```yaml + safe-outputs: + close-pull-request: + required-labels: [test, automated] # Optional: only close PRs with these labels + required-title-prefix: "[bot]" # Optional: only close PRs with this title prefix + target: "triggering" # Optional: "triggering" (default), "*" (any PR), or explicit PR number + max: 10 # Optional: maximum number of PRs to close (default: 1) + target-repo: "owner/repo" # Optional: cross-repository + ``` + When using `safe-outputs.close-pull-request`, the main job does **not** need `pull-requests: write` permission since PR closing is handled by a separate job with appropriate permissions. + - `add-labels:` - Safe label addition to issues or PRs + ```yaml + safe-outputs: + add-labels: + allowed: [bug, enhancement, documentation] # Optional: restrict to specific labels + max: 3 # Optional: maximum number of labels (default: 3) + target: "*" # Optional: "triggering" (default), "*" (any issue/PR), or number + target-repo: "owner/repo" # Optional: cross-repository + ``` + When using `safe-outputs.add-labels`, the main job does **not** need `issues: write` or `pull-requests: write` permission since label addition is handled by a separate job with appropriate permissions. + - `add-reviewer:` - Add reviewers to pull requests + ```yaml + safe-outputs: + add-reviewer: + reviewers: [user1, copilot] # Optional: restrict to specific reviewers + max: 3 # Optional: max reviewers (default: 3) + target: "*" # Optional: "triggering" (default), "*", or number + target-repo: "owner/repo" # Optional: cross-repository + ``` + Use `reviewers: copilot` to assign Copilot PR reviewer bot. Requires PAT as `COPILOT_GITHUB_TOKEN`. + - `assign-milestone:` - Assign issues to milestones + ```yaml + safe-outputs: + assign-milestone: + allowed: [v1.0, v2.0] # Optional: restrict to specific milestone titles + max: 1 # Optional: max assignments (default: 1) + target-repo: "owner/repo" # Optional: cross-repository + ``` + - `link-sub-issue:` - Safe sub-issue linking + ```yaml + safe-outputs: + link-sub-issue: + parent-required-labels: [epic] # Optional: parent must have these labels + parent-title-prefix: "[Epic]" # Optional: parent must match this prefix + sub-required-labels: [task] # Optional: sub-issue must have these labels + sub-title-prefix: "[Task]" # Optional: sub-issue must match this prefix + max: 1 # Optional: maximum number of links (default: 1) + target-repo: "owner/repo" # Optional: cross-repository + ``` + Links issues as sub-issues using GitHub's parent-child relationships. Agent output includes `parent_issue_number` and `sub_issue_number`. Use with `create-issue` temporary IDs or existing issue numbers. + - `update-project:` - Manage GitHub Projects boards + ```yaml + safe-outputs: + update-project: + max: 20 # Optional: max project operations (default: 10) + github-token: ${{ secrets.PROJECTS_PAT }} # Optional: token with projects:write + ``` + Not supported for cross-repository operations. + - `push-to-pull-request-branch:` - Push changes to PR branch + ```yaml + safe-outputs: + push-to-pull-request-branch: + target: "*" # Optional: "triggering" (default), "*", or number + title-prefix: "[bot] " # Optional: require title prefix + labels: [automated] # Optional: require all labels + if-no-changes: "warn" # Optional: "warn" (default), "error", or "ignore" + ``` + Not supported for cross-repository operations. + - `update-release:` - Update GitHub release descriptions + ```yaml + safe-outputs: + update-release: + max: 1 # Optional: max releases (default: 1, max: 10) + target-repo: "owner/repo" # Optional: cross-repository + github-token: ${{ secrets.CUSTOM_TOKEN }} # Optional: custom token + ``` + Operation types: `replace`, `append`, `prepend`. + - `create-code-scanning-alert:` - Generate SARIF security advisories + ```yaml + safe-outputs: + create-code-scanning-alert: + max: 50 # Optional: max findings (default: unlimited) + ``` + Severity levels: error, warning, info, note. + - `create-agent-task:` - Create GitHub Copilot agent tasks + ```yaml + safe-outputs: + create-agent-task: + base: main # Optional: base branch (defaults to current) + target-repo: "owner/repo" # Optional: cross-repository + ``` + Requires PAT as `COPILOT_GITHUB_TOKEN`. + - `assign-to-agent:` - Assign Copilot agents to issues + ```yaml + safe-outputs: + assign-to-agent: + name: "copilot" # Optional: agent name + target-repo: "owner/repo" # Optional: cross-repository + ``` + Requires PAT with elevated permissions as `GH_AW_AGENT_TOKEN`. + - `noop:` - Log completion message for transparency (auto-enabled) + ```yaml + safe-outputs: + noop: + ``` + The noop safe-output provides a fallback mechanism ensuring workflows never complete silently. When enabled (automatically by default), agents can emit human-visible messages even when no other actions are required (e.g., "Analysis complete - no issues found"). This ensures every workflow run produces visible output. + - `missing-tool:` - Report missing tools or functionality (auto-enabled) + ```yaml + safe-outputs: + missing-tool: + ``` + The missing-tool safe-output allows agents to report when they need tools or functionality not currently available. This is automatically enabled by default and helps track feature requests from agents. + + **Global Safe Output Configuration:** + - `github-token:` - Custom GitHub token for all safe output jobs + ```yaml + safe-outputs: + create-issue: + add-comment: + github-token: ${{ secrets.CUSTOM_PAT }} # Use custom PAT instead of GITHUB_TOKEN + ``` + Useful when you need additional permissions or want to perform actions across repositories. - **`command:`** - Command trigger configuration for /mention workflows - **`cache:`** - Cache configuration for workflow dependencies (object or array) @@ -527,11 +529,11 @@ The `cache:` field supports the same syntax as the GitHub Actions `actions/cache ```yaml cache: - key: node-modules-${{ hashFiles('package-lock.json') }} - path: node_modules - restore-keys: | - node-modules- -``` + key: node-modules-${{ hashFiles('package-lock.json') }} + path: node_modules + restore-keys: | + node-modules- +```` **Multiple Caches:** @@ -908,12 +910,12 @@ network: defaults # Use ecosystem identifiers for common development tools network: allowed: - - defaults # Basic infrastructure - - python # Python/PyPI ecosystem - - node # Node.js/NPM ecosystem - - containers # Container registries + - defaults # Basic infrastructure + - python # Python/PyPI ecosystem + - node # Node.js/NPM ecosystem + - containers # Container registries - "api.custom.com" # Custom domain - firewall: true # Enable AWF (Copilot engine only) + firewall: true # Enable AWF (Copilot engine only) # Or allow specific domains only network: diff --git a/.github/fuzzing/fuzz-mdx-sanitizer.ts b/.github/fuzzing/fuzz-mdx-sanitizer.ts index 37de67f..21d53e0 100644 --- a/.github/fuzzing/fuzz-mdx-sanitizer.ts +++ b/.github/fuzzing/fuzz-mdx-sanitizer.ts @@ -14,202 +14,208 @@ * Exit 0 = all invariants held; Exit 1 = violation found. */ -import { sanitizeHtmlForMdx } from '../../src/lib/sanitizeHtml' +import { sanitizeHtmlForMdx } from "../../src/lib/sanitizeHtml"; // --------------------------------------------------------------------------- // CLI arguments // --------------------------------------------------------------------------- const args: Record = Object.fromEntries( - process.argv.slice(2).map((a) => { - const [k, v] = a.replace(/^--/, '').split('=') - return [k, v ?? true] - }), -) -const ITERATIONS = parseInt(String(args['iterations'] ?? '20000'), 10) -const SEED = parseInt(String(args['seed'] ?? Date.now()), 10) + process.argv.slice(2).map(a => { + const [k, v] = a.replace(/^--/, "").split("="); + return [k, v ?? true]; + }) +); +const ITERATIONS = parseInt(String(args["iterations"] ?? "20000"), 10); +const SEED = parseInt(String(args["seed"] ?? Date.now()), 10); // --------------------------------------------------------------------------- // Seedable PRNG (xorshift32) for reproducible runs // --------------------------------------------------------------------------- -let state = (SEED >>> 0) || 0xcafebabe +let state = SEED >>> 0 || 0xcafebabe; function rand(): number { - state ^= state << 13 - state ^= state >> 17 - state ^= state << 5 - return (state >>> 0) / 0xffffffff + state ^= state << 13; + state ^= state >> 17; + state ^= state << 5; + return (state >>> 0) / 0xffffffff; } function randInt(lo: number, hi: number): number { - return Math.floor(rand() * (hi - lo + 1)) + lo + return Math.floor(rand() * (hi - lo + 1)) + lo; } function randChoice(arr: T[]): T { - return arr[randInt(0, arr.length - 1)] + return arr[randInt(0, arr.length - 1)]; } // --------------------------------------------------------------------------- // Seed corpus — real-world XSS and MDX edge cases // --------------------------------------------------------------------------- const SEEDS: string[] = [ - '

Hello

World

', + "

Hello

World

", '', - '', + "", '', - 'ipt>alert(1)', - 'ipt>ipt>evil', - 'text', - '', - 'alert(1)', - '{# jinja comment #}', - '

text

', - 'xle>.evil{}', - 'he\x00llo', - '\x01\x02\x03\x04\x05\x06\x07', - 'test\x7Fvalue', + "ipt>alert(1)", + "ipt>ipt>evil", + "text", + "", + "alert(1)", + "{# jinja comment #}", + "

text

", + "xle>.evil{}", + "he\x00llo", + "\x01\x02\x03\x04\x05\x06\x07", + "test\x7Fvalue", '', 'link', '
hover
', '', 'frame src="evil.html">', '', - '', - 'alert(1)]]>', + "", + "alert(1)]]>", '', '

text

', - ''.repeat(50), - 'nested', - '', - 'plain text with no HTML', -] + "".repeat(50), + "nested", + "", + "plain text with no HTML", +]; // --------------------------------------------------------------------------- // Injections for mutation // --------------------------------------------------------------------------- const INJECTIONS: string[] = [ - '', - '', - '', - 'onerror=alert(1)', + "", + "", + "", + "onerror=alert(1)", ' onclick="evil()"', - '', - '', - '\x00', - '\x7F', - '${7*7}', - '{{7*7}}', - '{# test #}', + "", + "", + "\x00", + "\x7F", + "${7*7}", + "{{7*7}}", + "{# test #}", '