Skip to content

feat: fuzzy "Did you mean?" suggestions for engine, event, permission, and MCP type typos#33467

Open
Copilot wants to merge 4 commits into
mainfrom
copilot/add-fuzzy-matching-for-errors
Open

feat: fuzzy "Did you mean?" suggestions for engine, event, permission, and MCP type typos#33467
Copilot wants to merge 4 commits into
mainfrom
copilot/add-fuzzy-matching-for-errors

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 20, 2026

Users see unhelpful errors like invalid engine: copiliot with no recovery hint. This extracts the existing Levenshtein fuzzy matching from pkg/parser into a reusable pkg/stringutil utility and applies it to four additional validation sites.

Changes

pkg/stringutil/fuzzy_match.go (new)

  • Moves FindClosestMatches + LevenshteinDistance out of pkg/parser/schema_suggestions.go into pkg/stringutil
  • pkg/parser now delegates to stringutil — no duplication

pkg/workflow/event_validation.go (new)

  • Validates event type names in the on: section against the full list of 35 GitHub Actions events
  • Only fires when the unknown name is close to a known event (distance ≤ 3), so new events or gh-aw extensions (bots, command, reaction, roles, stop-after, etc.) pass silently

pkg/workflow/permissions_validation.go

  • New ValidatePermissionScopeNames checks permission map keys for typos against all known GITHUB_TOKEN and GitHub App scopes

pkg/workflow/mcp_property_validation.go

  • Invalid MCP type value now includes a Did you mean: stdio? hint when the typo is close

Example errors after this change

unknown event type "pus" in 'on:' section.

Did you mean: push?

Valid event types include: branch_protection_rule, check_run, ...
unknown permission scope "contnts".

Did you mean: contents?

Valid permission scopes include: actions, attestations, checks, ...
tool 'my-server' mcp configuration 'type' must be one of: stdio, http. Got: stdi.

Did you mean: stdio?

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh gh repo view --json owner,name --jq .owner.login + "/" + .name 64/bin/go GOINSECURE GOMOD ode-gyp-bin/sh go env heck '**/*.cjs' OUTPUT GO111MODULE 64/bin/go ./../.prettieriginfocmp GOMOD GOMODCACHE sh (http block)
    • Triggering command: /usr/bin/gh gh repo view --json owner,name --jq .owner.login + "/" + .name ache/go/1.25.8/x64/bin/go GOINSECURE onpins GOMODCACHE go env /ref/tags/v9.0.0 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh pr list --repo github/gh-aw --state all --author app/github-actions --search created:2026-05-11T23:58:00Z..2026-05-12T00:05:00Z --limit 1 --json number --jq .[0].number GOMOD GOMODCACHE go (http block)
  • https://api.github.com/orgs/owner/actions/secrets
    • Triggering command: /usr/bin/gh gh api /orgs/owner/actions/secrets --jq .secrets[].name 6041413/001' 6041413/001' 64/bin/go GOINSECURE GOMOD ode-gyp-bin/node-bool go ache�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE node (http block)
    • Triggering command: /usr/bin/gh gh api /orgs/owner/actions/secrets --jq .secrets[].name "prettier" --wriGOINSECURE infocmp 64/bin/go xterm-color bash /usr/bin/infocmp-json sh -c "prettier" --cheGOINSECURE infocmp 64/bin/go ithub-script/gitgit infocmp bject.type] | @tuser.email go (http block)
    • Triggering command: /usr/bin/gh gh api /orgs/owner/actions/secrets --jq .secrets[].name --write ../../../**/*.jsGOMOD 64/bin/go --ignore-path ../../../.prettienv sv node /hom�� --check **/*.cjs 64/bin/go **/*.json --ignore-path ../../../.pretti/tmp/gh-aw-test-runs/20260520-061316-128257/test-source-field-variant-2888404131/.github/workflows go (http block)
  • https://api.github.com/orgs/test-owner/actions/secrets
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name 76041413/001' 76041413/001' 64/bin/go GOINSECURE GOMOD GOMODCACHE go env heck '**/*.cjs' -errorsas GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE node (http block)
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name "prettier" --wriGOINSECURE infocmp 64/bin/go xterm-color /opt/hostedtoolcenv /usr/bin/infocmp-json sh -c "prettier" --cheGOINSECURE infocmp 64/bin/go ithub-script/gitinfocmp infocmp run-script/lib/nxterm-color go (http block)
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name echo "��� JSON fGOINSECURE infocmp 64/bin/go --ignore-path ..go go sv npx pret�� --check scripts/**/*.js 64/bin/go .prettierignore 554051/b488/cons-1 sv go (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv runs/20260520-060134-69210/test-remote.upstream.url -buildtags (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 --jq x_amd64/vet 0134-69210/test-gh stmain.go ache/go/1.25.8/x/repos/actions/github-script/git/ref/tags/v9 x_amd64/vet api /repos/actions/github-script/git/ref/tags/v9 --jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 --jq sv /ref/tags/v9 iG/B0021Cz1E9JNj-1 sv gh api /repos/actions/github-script/git/ref/tags/v9 --jq /usr/bin/gh --remote=https:/infocmp v1.0.0 /usr/libexec/docxterm-color gh (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv 0134-69210/test-980119932/.githugo1.25.8 GO111MODULE ache/go/1.25.8/x64/pkg/tool/linu-nolocalimports m0s GOMOD (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv ref/tags/v1 config sv remote.upstream.infocmp GO111MODULE 64/bin/go gh api /repos/actions/github-script/git/ref/tags/v9 --jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 node sv tags/v5 node sv /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linufeature-branch -ato�� /ref/tags/v9 -buildtags sv -errorsas -ifaceassert -nilfunc gh (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv 2/001/test-frontmatter-with-nested-objects.md GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile e=/t�� /ref/tags/v9 GO111MODULE sv m0s GOMOD (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv ithub-script/git/ref/tags/v9.0.0 go 1/x64/bin/node .github/workflowinfocmp GO111MODULE 64/bin/go go -has�� ithub/workflows/approach-validator.md go /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/compile -json GO111MODULE 64/bin/go /opt/hostedtoolcache/go/1.25.8/x--jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv -bool (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv g_.a GO111MODULE (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE /opt/hostedtoolcache/go/1.25.8/x-lang=go1.25 GOINSECURE GOMOD GOMODCACHE go env 3113918796 GO111MODULE e/git GOINSECURE GOMOD GOMODCACHE e/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv s/1234567890 GO111MODULE umber, url: .html_url, status: .status, conclusion: .conclusion, workflowName: .name, workflowPa/repos/actions/github-script/git/ref/tags/v9 GOINSECURE GOMOD GOMODCACHE go env ExpressionCompiledOutput25362799remote.upstream.url GO111MODULE 2597895/b443/vet.cfg GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv ithub-script/git/ref/tags/v9 --jq ndor/bin/bash /repos/actions/ginfocmp --jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv bject.type] | @t/repos/actions/github-script/git/ref/tags/v9 infocmp ache/node/24.14.1/x64/bin/node /ref/tags/v9 infocmp sv gh _har�� /ref/tags/v9 --jq sv /ref/tags/v9 infocmp sv ache/go/1.25.8/x--jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv /tmp/gh-aw-add-gitattributes-test1774420814/.github/workflows l ache/node/24.14.1/x64/bin/node remote.origin.urinfocmp GOWORK 64/bin/go ache/node/24.14.1/x64/bin/node s-31�� ere node /usr/bin/git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv */*.ts' '**/*.jsGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go k/gh�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD erignore go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv */*.ts' '**/*.jsGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go ache�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD r go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv rite '**/*.cjs' GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env te 'scripts/**/*GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9.0.0
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9.0.0 --jq [.object.sha, .object.type] | @tsv */*.ts' '**/*.jsGOINSECURE GO111MODULE 64/pkg/tool/linuGOMODCACHE GOINSECURE GOMOD (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9.0.0 --jq [.object.sha, .object.type] | @tsv */*.ts' '**/*.jsGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env rite 'scripts/**GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env te 'scripts/**/*GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv -bool }} {{context.Compiler}} r: $owner, name: $name) { hasDiscussionsEnabled } } -errorsas -ifaceassert -nilfunc eutil.test 4525�� 2597895/b553/_pkg_.a security 2597895/b553=> -nxv GO111MODULE 1/x64/bin/node /opt/hostedtoolc--jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 --jq r: $owner, name: $name) { hasDiscussionsEnabled } } 2/001/test-frontinfocmp g/envutil/envuti-1 ache/go/1.25.8/xxterm-color gh api /repos/actions/github-script/git-errorsas --jq x_amd64/vet 001/inlined-b.mdgh GO111MODULE 2597895/b492=> x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv ithub-script/git/ref/tags/v9 --jq (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv 0134-69210/test-150052456/.githu@{u} GO111MODULE 2597895/b469/importcfg.link GOINSECURE GOMOD GOMODCACHE WwD6T2Y1Mgb6R/dYBwNveZymPsRCHwADTest User env ithub-script/git/ref/tags/v9 GO111MODULE 1/x64/bin/node GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv vaScript613383212/001/test-inlined-imports-enabl-errorsas g/repoutil/repoutil_test.go /usr/local/sbin/iptables -errorsas -ifaceassert -nilfunc iptables -w runs/20260520-060134-69210/test-remote.origin.url security 2597895/b534/vet.cfg url GO111MODULE k/_temp/uv-pytho/repos/actions/github-script/git/ref/tags/v9 /opt/hostedtoolc--jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv GOMODCACHE go 1/x64/bin/node te 'scripts/**/*node GO111MODULE 64/bin/go 1/x64/bin/node -C 2597895/b571/syncutil.test config .0/x64/bin/go remote.upstream.ls on 64/bin/go __35F2t1F7AEM/wVIjl6JE2QkluJttAG--jq (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv /a.out g/jsonutil/json_test.go ortcfg.link GOINSECURE gj33pWKk9TOfgPuEworkflow GOMODCACHE g_.a env CommaSeparatedCoid,name,path,state GO111MODULE e/git GOINSECURE GOMOD GOMODCACHE e/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv 5549/001/stability-test.md GO111MODULE 2597895/b498/fileutil.test GOINSECURE GOMOD GOMODCACHE 2597895/b498/filowner/repo e=/t�� CompiledOutput858998079/001 GO111MODULE (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuowner/host-repo env 3113918796 (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv 5549/001/stability-test.md GoFiles,IgnoredGoFiles,IgnoredOtherFiles,CFiles,-ifaceassert tartedAt,updatedAt,event,headBranch,headSha,displayTitle GOINSECURE GOMOD GOMODCACHE go env 3113918796 GO111MODULE e/git-upload-pack l GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 ^remote\..*\.gh-resolved$ sv -json GO111MODULE ache/go/1.25.8/x-bool infocmp -1 xterm-color go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv xterm-color node 1/x64/bin/npm /ref/tags/v9 l sv 1/x64/bin/npm -1 xterm-color /opt/hostedtoolcache/go/1.25.8/x--jq (http block)
  • https://api.github.com/repos/aws-actions/configure-aws-credentials/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/aws-actions/configure-aws-credentials/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv t0 {{context.GOARCH}} {{context.Compiler}} 2597895/b571/syncutil.test m0s GO111MODULE (http block)
    • Triggering command: /usr/bin/gh gh api /repos/aws-actions/configure-aws-credentials/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv 2597895/b559/_pkg_.a --revs ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet --thin --delta-base-off--version -q ache/go/1.25.8/x64/pkg/tool/linu--jq -C vwZq/lx0Gb5zyLwK7BniNvwZq config /usr/bin/git tent.md GO111MODULE 64/bin/go git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/aws-actions/configure-aws-credentials/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv xterm-color go (http block)
  • https://api.github.com/repos/azure/login/git/ref/tags/v2
    • Triggering command: /usr/bin/gh gh api /repos/azure/login/git/ref/tags/v2 --jq [.object.sha, .object.type] | @tsv git-upload-pack '/tmp/TestParseDefaultBranchFromLsRemoteWithRealGitbranch_with_hyphen2517096680/git git-upload-pack '/tmp/TestParseDefaultBranchFromLsRemoteWithRealGitbranch_with_hyphen2517096680/config 1/x64/bin/node -json GO111MODULE 64/bin/go 1/x64/bin/node -1 ErrorFormatting2526937966/001 go /usr/bin/git ]]; then GH_AW/usr/lib/git-core/git on 64/bin/go git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/azure/login/git/ref/tags/v2 --jq [.object.sha, .object.type] | @tsv /repos/actions/github-script/git/ref/tags/v9 --jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/azure/login/git/ref/tags/v2 --jq [.object.sha, .object.type] | @tsv ithub-script/git/ref/tags/v9 --jq bject.type] | @tsv /repos/actions/ginfocmp --jq (http block)
  • https://api.github.com/repos/docker/login-action/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/docker/login-action/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv --bare --initial-branch=my-default 2597895/b573/testutil.test te 'scripts/**/*infocmp GO111MODULE 64/bin/go 2597895/b573/testutil.test e=/t�� t0 go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/docker/login-action/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv /repos/actions/github-script/git/ref/tags/v9 --jq (http block)
    • Triggering command: /usr/bin/gh gh api /repos/docker/login-action/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv 40\} ster.patch (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v0.1.2
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv ST_PATH_PREFIX_ARGS="" if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then GH_AW_DOCKER_HOST_PATH_PREgh 2597895/b485/_testmain.go 1/x64/bin/node -s -w -buildmode=exe ache/go/1.25.8/x64/pkg/tool/linuremote.upstream.url t-ha�� Imports40570588/001/noflag-a.md -importcfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv ST_PATH_PREFIX_ARGS="" if [[ "${DOCKER_HOST:-}" =~ ^tcp:// ]]; then GH_AW_DOCKER_HOST_PATH_PREgh --jq sv 2/001/test-frontinfocmp stmain.go ache/go/1.25.8/xxterm-color gh api /ref/tags/v9 --jq sv 0134-69210/test-gh GO111MODULE ache/go/1.25.8/x/repos/actions/github-script/git/ref/tags/v9 gh (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv /repos/actions/github-script/git/ref/tags/v9 --jq repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } /ref/tags/v9 Test User sv gh api /ref/tags/v9 --jq sv /ref/tags/v9 go sv gh (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv 5549/001/stability-test.md 2597895/b456/vet.cfg tartedAt,updatedAt,event,headBranch,headSha,displayTitle H_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" fi echo "$GH_AW_DOCKER_HOST_PATH_PREFIX_AR GOMOD GOMODCACHE ache/go/1.25.8/xcurrent (local changes) env go t.go r: $owner, name:new (upstream) GOINSECURE GOMOD GOMODCACHE VY6dJJT3q2T3n/9b/tmp/gh-aw-merge-3626168162/new.md (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv xterm-color 64/pkg/tool/linutest@example.com (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 git 1/x64/bin/npm H_PREFIX_ARGS="--docker-host-path-prefix /tmp/gh-aw" fi echo "$GH_AW_DOCKER_HOST_PATH_PREFIX_AR Test User me: String!) { --noprofile 1/x64/bin/npm -1 xterm-color /opt/hostedtoolc--jq (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/xcurrent (local changes) env /ref/tags/v9.0.0base (original) GO111MODULE verutil.test GOINSECURE GOMOD GOMODCACHE verutil.test (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv -v 64/pkg/tool/linuconfig (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv xterm-color 2597895/b586/importcfg (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --limit 100 --created >=2026-05-13 -tests 64/bin/go go eWit�� -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --limit 100 --created >=2026-04-20 GOMOD GOMODCACHE go itcu�� -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --limit 100 --created >=2026-02-19 GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/link GOINSECURE GOMOD GOMODCACHE x_amd64/link (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name .cfg 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuorigin env y_only_defaults_repo1909025328/0remote.upstream.url GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE til GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env mpiledOutput1926566056/001 GO111MODULE .cfg GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name mLsRemoteWithRealGitmain_branch696322851/001' 64/bin/go GOINSECURE GOMOD GOMODCACHE go env 01/main.md GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuremote.origin.url (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name .cfg ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go estl�� -json GO111MODULE 64/pkg/tool/linux_amd64/asm GOINSECURE GOMOD GOMODCACHE hqTyUHF/pN7cv-DOVeUyFlVlSS3Z (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 .cfg stants.test GOINSECURE GOMOD GOMODCACHE hNpLusf/mfmHkuRMremote.origin.url 4525�� 980119932/.github/workflows GO111MODULE 9964dc89e22acd9cc9420135091f8505-d GOINSECURE igFiles,SwigCXXFinit GOMODCACHE 64/pkg/tool/linux_amd64/asm (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env 1956/001/stabili.github/workflows/test.md GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1234567890
    • Triggering command: /usr/bin/gh gh api repos/{owner}/{repo}/actions/runs/1234567890 --jq {databaseId: .id, number: .run_number, url: .html_url, status: .status, conclusion: .conclusion, workflowName: .name, workflowPath: .path, createdAt: .created_at, startedAt: .run_started_at, updatedAt: .updated_at, event: .event, headBranch: .head_branch, te '../../../**/-errorsas ntic_workflows_p-ifaceassert 64/bin/go GOINSECURE GOMOD GOMODCACHE /opt/hostedtoolc-tests -l ck '**/*.cjs' '**/*.ts' '**/*.jsGOINSECURE pkg/workflow/safe_output_validatGOMOD 64/bin/go pkg/workflow/safgit pkg/workflow/safinit pkg/workflow/saf--bare sh (http block)
    • Triggering command: /usr/bin/gh gh api repos/{owner}/{repo}/actions/runs/1234567890 --jq {databaseId: .id, number: .run_number, url: .html_url, status: .status, conclusion: .conclusion, workflowName: .name, workflowPath: .path, createdAt: .created_at, startedAt: .run_started_at, updatedAt: .updated_at, event: .event, headBranch: .head_branch, h3037241875/001' h3037241875/001' 64/bin/go #!/bin/bash expo/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/link infocmp /usr/bin/infocmpGOPATH sh -c "prettier" --cheGOSUMDB infocmp 64/bin/go ithub-script/git/usr/lib/git-core/git infocmp bject.type] | @t--pack_header=2,3 go (http block)
    • Triggering command: /usr/bin/gh gh api repos/{owner}/{repo}/actions/runs/1234567890 --jq {databaseId: .id, number: .run_number, url: .html_url, status: .status, conclusion: .conclusion, workflowName: .name, workflowPath: .path, createdAt: .created_at, startedAt: .run_started_at, updatedAt: .updated_at, event: .event, headBranch: .head_branch, npx prettier --cGOINSECURE infocmp 64/bin/go ignore-path .././opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/link go run-script/lib/nGOPATH node /hom�� --check scripts/**/*.js 64/bin/go -d ache/go/1.25.8/x-c sv go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuremote.origin.url env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env y_with_explicit_repo3365755103/001 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuremote.origin.url (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE ache/go/1.25.8/x-nilfunc GOINSECURE GOMOD GOMODCACHE go env mpiledOutput1926566056/001 GO111MODULE .cfg GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name l_test.go ache/go/1.25.8/x-lang=go1.25 GOINSECURE yY/cLcqoeswEkgcGremote GOMODCACHE go env y_only_defaults_go1.25.8 GO111MODULE ache/go/1.25.8/x-nolocalimports GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE CM/ZrKagBgLkf-C7config GOMODCACHE go env edOutput1205701337/001 GO111MODULE ck GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE l_url, status: .status, conclusion: .conclusion, workflowName: .name, workflowPath: .path, creat--get GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/link (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name GO111MODULE ache/go/1.25.8/x-importcfg GOINSECURE GOMOD GOMODCACHE go env y_with_explicit_repo3365755103/001 GO111MODULE .cfg GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuupstream env mpiledOutput308882985/001 GO111MODULE .cfg GOINSECURE util GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/pkg/tool/linux_amd64/link GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuTest User (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name .cfg ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env y_with_explicit_repo3365755103/001 GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 GO111MODULE ache/go/1.25.8/x-buildmode=exe GOINSECURE GOMOD GOMODCACHE go env edOutput1205701337/001 GO111MODULE ow.lock.yml GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linutest@example.com (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path -c=4 -nolocalimports -importcfg /tmp/go-build409997261/b001/importcfg -pack /tmp/testenv-2653148459/main.go go env heck '**/*.cjs' -test.timeout=10m0s GO111MODULE 64/bin/go ./../.prettierig/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/link GOMOD GOMODCACHE node (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 /tmp/go-build331-V=full 64/bin/go ehXx4wa/hf93mBrTaCX6oPJi3rVy /hom�� --write ../../../**/*.json x_amd64/compile --ignore-path ../../../.pretticonfig 64/bin/go x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 GOMOD GOMODCACHE x_amd64/link env g_.a GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE by/eGEWi6XnNytCvremote.origin.url (http block)
  • https://api.github.com/repos/github/gh-aw/contents/.github/workflows/shared/reporting.md
    • Triggering command: /tmp/go-build3452597895/b478/cli.test /tmp/go-build3452597895/b478/cli.test -test.testlogfile=/tmp/go-build3452597895/b478/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true nore GOMOD GOMODCACHE go env te '**/*.cjs' '*GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /tmp/go-build642554051/b478/cli.test /tmp/go-build642554051/b478/cli.test -test.testlogfile=/tmp/go-build642554051/b478/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true /ref/tags/v9 -extld=gcc sv sh -c npx prettier --wGOINSECURE infocmp 64/bin/go xterm-color infocmp (http block)
    • Triggering command: /tmp/go-build565609717/b478/cli.test /tmp/go-build565609717/b478/cli.test -test.testlogfile=/tmp/go-build565609717/b478/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true **/*.json --ignore-path ../../../.pretti-json sh -c "prettier" --wriGOINSECURE infocmp 64/bin/go rror go e sh (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/dev
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/dev --jq [.object.sha, .object.type] | @tsv erignore go .test te '../../../**/git GO111MODULE 64/bin/go .test Enve�� /tmp/TestGuardPolicyMinIntegrityOnlyCompiledOutput2311135157/001 config ache/node/24.14.1/x64/bin/node remote.upstream.infocmp GOPROXY 64/bin/go _DOCKER_HOST_PATH_PREFIX_ARGS" (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/dev --jq [.object.sha, .object.type] | @tsv erignore l /usr/bin/git te '../../../**/git GO111MODULE 64/bin/go git -C /tmp/TestGuardPolicyBlockedUsersApprovalLabelsCompiledOutput1926566056/001 config _id":200}] remote.origin.urinfocmp --merged=d5a2c2d-1 64/bin/go git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/dev --jq [.object.sha, .object.type] | @tsv /repos/actions/github-script/git/ref/tags/v9 --jq /usr/bin/gh 0652063/b001/_pkgit k/gh-aw/gh-aw/pkadd 0652063/b001=> gh api ithub-script/git/ref/tags/v9 --jq 64/pkg/tool/linux_amd64/vet licyMinIntegrityinfocmp -test.v=true /usr/lib/git-corxterm-color _DOCKER_HOST_PATH_PREFIX_ARGS" (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv GOMODCACHE (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv /repos/actions/github-script/git/ref/tags/v9 --jq /usr/bin/gh 376" GH_AW_DOCKEinfocmp -buildtags 64/pkg/tool/linuxterm-color gh api ithub-script/git/ref/tags/v9 --jq 64/pkg/tool/linux_amd64/vet runs/20260520-06infocmp -buildtags (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv /repos/actions/github-script/git/ref/tags/v9 --jq (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE .cfg GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x--json env (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 Test User sv (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 git sv /tmp/TestGuardPogh config 0"}} ache/go/1.25.8/x--jq -1 .*/\1/p -aw" fi echo "$GH_AW_DOCKER_HOST_PATH_PREFIX_AR sv 0134-69210/test-gh node ache/node/24.14./repos/actions/github-script/git/ref/tags/v9 infocmp (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv --write scripts/**/*.js x_amd64/vet .prettierignore --log-level=erro-C 64/bin/go x_amd64/vet -c echo "��� JSON fremote.upstream.url bash 64/bin/go --ignore-path ..infocmp sh 64/bin/go node (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env le-frontmatter.md GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv ctionpins_intern--exclude-hidden=receive pec_test.go x_amd64/vet .prettierignore --log-level=errolist 64/bin/go x_amd64/vet orts�� -w herFiles,CFiles,CgoFiles,CXXFiles,MFiles,HFiles,FFiles,SFiles,SwigFiles,SwigCXXFiles,SysoFiles,T-1 x_amd64/link pkg/workflow/actgit pkg/workflow/add-C pkg/workflow/add/tmp/gh-aw-test-runs/20260520-060134-69210/test-2071234678 x_amd64/link (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv run format:pkg-json x_amd64/vet tierignore /tmp/go-build331-o s,MFiles,HFiles,/tmp/go-build3452597895/b545/logger.test x_amd64/vet /opt�� run lint:cjs x_amd64/link GOMODCACHE sh 64/bin/go x_amd64/link (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv npx prettier --write '../../../*-errorsas /opt/hostedtoolcGO111MODULE x_amd64/vet -unreachable=falgit /tmp/go-build331-C 64/bin/go x_amd64/vet -c npx prettier --cremote.upstream.url erignore 64/bin/go ignore-path ../.git /tmp/go-build342init 64/bin/go sh (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq [.object.sha, .object.type] | @tsv echo "��� Formatgo1.25.8 /opt/hostedtoolc-c=4 x_amd64/compile tierignore /tmp/go-build331-C 64/bin/go x_amd64/compile run lint:cjs bash 64/bin/go te 'scripts/**/*git 6603448/b353/impconfig 64/bin/go sh (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env tmatter-with-envremote.origin.url GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/issues/17
    • Triggering command: /usr/bin/gh gh api repos/github/gh-aw/issues/17 go env te '../../../**/-errorsas GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE git -c ck '**/*.cjs' '*remote.upstream.url log 64/bin/go -n1 --format=format:commit --end-of-options-m node (http block)
    • Triggering command: /usr/bin/gh gh api repos/github/gh-aw/issues/17 /bin/sh -c unformatted=$(goGOINSECURE gh 64/bin/go --ignore-path ../opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet --jq (http block)
    • Triggering command: /usr/bin/gh gh api repos/github/gh-aw/issues/17 -tests /tmp/go-build565609717/b575/vet.cfg npx prettier --cGOINSECURE infocmp 64/bin/go ignore-path .././opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet go sv sh -c "prettier" --che-errorsas infocmp 64/bin/go tierignore ache/go/1.25.8/x-atomic sv go (http block)
  • https://api.github.com/repos/google-github-actions/auth/git/ref/tags/v2
    • Triggering command: /usr/bin/gh gh api /repos/google-github-actions/auth/git/ref/tags/v2 --jq [.object.sha, .object.type] | @tsv g/timeutil/format.go g/timeutil/format_test.go ache/node/24.14.1/x64/bin/node te 'scripts/**/*infocmp b/gh-aw/pkg/stat-1 64/bin/go git t-73�� bility_SameInputSameOutput1698595549/001/stability-test.md config clusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle ]]; then GH_AWhead on 64/bin/go 2597895/b561/importcfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/google-github-actions/auth/git/ref/tags/v2 --jq [.object.sha, .object.type] | @tsv xterm-color ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/google-github-actions/auth/git/ref/tags/v2 --jq [.object.sha, .object.type] | @tsv ster.patch --jq (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv 680421329 GO111MODULE $name) { hasDiscussionsEnabled } } GOINSECURE GOMOD GOMODCACHE ortcfg env 2/001/test-frontmatter-with-nested-objects.md GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv /ref/tags/v9 remote.origin.url sv -json GO111MODULE x_amd64/asm /opt/hostedtoolc--jq /tmp�� /ref/tags/v9 x_amd64/asm sv e-frontmatter.md/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GO111MODULE 64/pkg/tool/linu-bool /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv f/tags/v4 git sv /tmp/TestGuardPogh remote 0"}} ache/go/1.25.8/x--jq -1 /ref/tags/v9 h-aw" fi echo "$GH_AW_DOCKER_HOST_PATH_PREFIX_A sv 0134-69210/test-gh remote.origin.urapi ache/node/24.14./repos/actions/github-script/git/ref/tags/v9 infocmp (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linutest@example.com env g_.a GO111MODULE .cfg GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE go env y_with_explicit_repo1057034264/0remote.origin.url GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE go env -2305421560/.github/workflows GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/org/repo/pulls/1
    • Triggering command: /usr/bin/gh gh api repos/org/repo/pulls/1 ade71ee0 ache�� -json GO111MODULE 64/bin/go rkflow/js/**/*.j/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOMOD erignore bash --no�� ck '**/*.cjs' '*-p GOPROXY 64/bin/go GOSUMDB GOWORK ache/go/1.25.8/xgit-receive-pack '/tmp/TestParseDefaultBranchFromLsRemoteWithRealGitmain_branch276041413/001' sh (http block)
    • Triggering command: /usr/bin/gh gh api repos/org/repo/pulls/1 -tests /tmp/go-build642554051/b561/vet.cfg --write ../../../**/*.jsGOMOD 64/bin/go --ignore-path ../../../.pretti-V=full (http block)
    • Triggering command: /usr/bin/gh gh api repos/org/repo/pulls/1 -tests /tmp/go-build565609717/b564/vet.cfg npx prettier --cGOINSECURE gh 64/bin/go ignore-path .././opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/asm --jq (http block)
  • https://api.github.com/repos/owner/repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/owner/repo/actions/secrets --jq .secrets[].name -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go ache�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD ode-gyp-bin/node-test.paniconexit0 node (http block)
    • Triggering command: /usr/bin/gh gh api /repos/owner/repo/actions/secrets --jq .secrets[].name "prettier" --wriGOINSECURE infocmp 64/bin/go ithub-script/gitgo bash bject.type] | @t-json sh -c "prettier" --cheGOINSECURE infocmp 64/bin/go ithub-script/git/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/link infocmp ker/cli-plugins//tmp/go-build642554051/b549/parser.test go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/owner/repo/actions/secrets --jq .secrets[].name (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD GOMODCACHE go env heck '**/*.cjs' -s GO111MODULE 64/bin/go ./../.prettieriggit GOMOD GOMODCACHE sh (http block)
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD GOMODCACHE go env heck '**/*.cjs' -s GO111MODULE 64/bin/go ./../.prettieriggo GOMOD GOMODCACHE sh (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-remote-workflow --limit 30 --repo owner/repo 64/pkg/tool/linu.github/workflows/test.md env 3984953658/.github/workflows GO111MODULE 64/pkg/tool/linux_amd64/link GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linutest@example.com (http block)
  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go ache�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE node (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name "prettier" --wriGOINSECURE infocmp 64/bin/go ithub-script/gitgo grep bject.type] | @t-json sh -c "prettier" --cheGOINSECURE infocmp 64/bin/go ithub-script/gitgit infocmp de go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name 9818567/001' 9818567/001' 64/bin/go --ignore-path ../../../.prettienv sv node /hom�� --check **/*.cjs 64/bin/go **/*.json --ignore-path ../../../.pretti/repos/actions/github-script/git/ref/tags/v9.0.0 go (http block)
  • https://api.github.com/repos/test/repo
    • Triggering command: /usr/bin/gh gh api /repos/test/repo --jq .default_branch 0134-69210/test-add-source-path-3393565528/.gith--detach GO111MODULE x_amd64/link GOINSECURE GOMOD GOMODCACHE x_amd64/link env DefaultBranchFromLsRemoteWithRealGitbranch_with_-p DefaultBranchFromLsRemoteWithRealGitbranch_with_main ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 06/m1mI9m8ZybBw5sh (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test/repo --jq .default_branch ab-testing-advisor.md GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuremote.origin.url env -4167405817/.github/workflows GO111MODULE tartedAt,updatedAt,event,headBranch,headSha,displayTitle GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/test/repo --jq .default_branch -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linuremote.origin.url env -json GO111MODULE tartedAt,updatedAt,event,headBranch,headSha,displayTitle GOINSECURE GOMOD GOMODCACHE go (http block)

If you need me to access, download, or install something from one of these locations, you can either:


Generated by 👨‍🍳 PR Sous Chef · ● 17M ·

Copilot AI linked an issue May 20, 2026 that may be closed by this pull request
9 tasks
Copilot AI and others added 2 commits May 20, 2026 06:10
…on, MCP validations

- Create pkg/stringutil/fuzzy_match.go with FindClosestMatches and LevenshteinDistance
- Update pkg/parser/schema_suggestions.go to delegate to stringutil (no code duplication)
- Create pkg/stringutil/fuzzy_match_test.go with comprehensive test coverage
- Create pkg/workflow/event_validation.go with GitHub event type validation + fuzzy suggestions
  - Defines complete list of valid GitHub Actions event types
  - Skips gh-aw-specific on: section extensions (bots, command, reaction, roles, etc.)
  - Suggests closest match when typo detected (e.g. 'pus' → 'push')
- Wire ValidateEventTypes into compiler_orchestrator_frontmatter.go
- Add ValidatePermissionScopeNames to pkg/workflow/permissions_validation.go
  - Validates permission scope names for typos (e.g. 'contnts' → 'contents')
  - Suggests closest match when unknown scope closely resembles a valid one
- Wire ValidatePermissionScopeNames into permissions_compiler_validator.go
- Add fuzzy matching to mcp_property_validation.go for MCP type typos
  - Suggests 'stdio' when user types 'stdi', 'http' when user types 'htpp', etc.
- Create test files: event_validation_test.go, permissions_scope_validation_test.go

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/af7e4321-5479-40d1-92b6-38a732fd7972

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
…ScopeNames

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/af7e4321-5479-40d1-92b6-38a732fd7972

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI changed the title [WIP] Add fuzzy matching for common user input errors feat: fuzzy "Did you mean?" suggestions for engine, event, permission, and MCP type typos May 20, 2026
Copilot AI requested a review from gh-aw-bot May 20, 2026 06:16
@pelikhan pelikhan marked this pull request as ready for review May 20, 2026 06:29
Copilot AI review requested due to automatic review settings May 20, 2026 06:29
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

PR Code Quality Reviewer completed the code quality review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🧪 Test Quality Sentinel completed test quality analysis.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Excellent implementation of fuzzy matching for typo suggestions. The code is well-structured, thoroughly tested, and provides a meaningful UX improvement.

Strengths

  • Clean refactoring: Properly extracted FindClosestMatches and LevenshteinDistance from pkg/parser into reusable pkg/stringutil
  • Efficient algorithm: Space-optimized Levenshtein with proper early exits for empty strings
  • Conservative validation: Only flags potential typos (distance ≤ 3), avoiding false positives for new GitHub features
  • Comprehensive tests: Table-driven tests cover typical cases, edge cases, and boundary conditions
  • Consistent integration: Applied uniformly across 4 validation sites (engine, events, permissions, MCP types)
  • Actionable errors: Clear "Did you mean?" suggestions help users fix typos quickly

Code Quality

✅ Logic correctness and edge case handling
✅ Performance (O(n·m) with space optimization)
✅ Error handling and user-facing messages
✅ Test coverage and patterns
✅ Code organization and maintainability

No changes required.

Note

🔒 Integrity filter blocked 1 item

The following item was blocked because it doesn't meet the GitHub integrity level.

  • #33467 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

🔎 Code quality review by PR Code Quality Reviewer · ● 4.2M

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /tdd (test-driven development) and /zoom-out (architectural consistency) based on this being a refactor + new feature PR.

Key Themes

Test Coverage Gaps — The new fuzzy matching utility has good happy-path tests, but is missing:

  • Case-insensitive exact match verification
  • gh-aw extension key handling in event validation
  • Stress test for the Levenshtein space optimization

Inconsistent Error Messages — The three validation sites (events, permissions, MCP types) each format "Did you mean?" errors differently, creating inconsistent UX. Consider extracting a shared error formatter.

PR Description Mismatch — The description claims "four additional validation sites" but only three are implemented (events, permissions, MCP types). Engine validation appears to be missing.

Positive Highlights

Excellent refactoring — Moving fuzzy matching into pkg/stringutil creates a clean, reusable utility
Thoughtful design — The silent pass for unknown-but-distant values avoids false positives for new GitHub features
Good test structure — Table-driven tests are well-organized and descriptive

Verdict

This is solid work overall. The test coverage gaps are minor and the architectural inconsistency in error formatting is a nice-to-have improvement rather than a blocker. The missing fourth validation site (engine) should be clarified — either add it or update the PR description.

No blocking issues, but addressing the test gaps would strengthen the regression safety.


Reference: Matt Pocock's /tdd and /zoom-out skills from mattpocock/skills

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · ● 8.9M

{
name: "case insensitive Copilot is exact match of copilot, no suggestions",
target: "Copilot",
candidates: []string{"copilot", "claude", "codex", "custom"},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The test case "case insensitive Copilot is exact match of copilot, no suggestions" verifies that exact matches are skipped, but it doesn't verify case-insensitive matching.

Consider adding a test with mixed case input to ensure the case-insensitive comparison works:

{
    name:       "case insensitive exact match COPILOT skipped",
    target:     "COPILOT",
    candidates: []string{"copilot", "claude"},
    maxResults: 3,
    want:       nil,
},

This ensures the strings.ToLower() normalization in FindClosestMatches actually works as intended.

},
wantErr: true,
errContains: "Did you mean",
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The production code in event_validation.go has logic to skip gh-aw extension keys like bots, command, reaction, etc., but there's no test case verifying this behavior.

Add a test to ensure gh-aw extensions are not flagged as typos:

{
    name: "gh-aw extension keys are silently skipped",
    frontmatter: map[string]any{
        "on": map[string]any{
            "push":           nil,
            "bots":           []string{"dependabot"},
            "slash_command":  "deploy",
            "reaction":       "eyes",
        },
    },
    wantErr: false,
},

This protects against regressions where valid gh-aw extensions might accidentally trigger typo suggestions.

continue
}

return fmt.Errorf(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/zoom-out] The error message format here differs from the one in permissions_validation.go line 461. This creates inconsistent UX across validation errors.

In event_validation.go:

"Did you mean: %s?\n\nValid event types include..."

In permissions_validation.go:

"Did you mean: %s?\n\nValid permission scopes include..."

In mcp_property_validation.go (line 72):

"Did you mean: %s?\n\nExample:\ntools:..."

Consider extracting a shared error formatter into pkg/stringutil or establishing a consistent pattern:

func FormatDidYouMeanError(itemType, invalidValue string, suggestions, validOptions []string, docsURL string) string

This would ensure all typo suggestions have the same structure and tone.

// LevenshteinDistance computes the Levenshtein distance between two strings.
// This is the minimum number of single-character edits (insertions, deletions, or substitutions)
// required to change one string into the other.
func LevenshteinDistance(a, b string) int {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The comment on line 74 claims "We only need the previous row, so we can optimize space" but there's no test verifying this optimization actually works for large inputs.

Consider adding a stress test in fuzzy_match_test.go:

func TestLevenshteinDistanceLargeStrings(t *testing.T) {
    // Verify the space optimization works for long strings
    longA := strings.Repeat("abcdefghij", 100) // 1000 chars
    longB := strings.Repeat("abcdefghik", 100) // 1000 chars, 1 char diff per 10
    
    distance := LevenshteinDistance(longA, longB)
    assert.Equal(t, 100, distance, "Should handle long strings correctly")
}

This ensures the row-swap optimization (lines 105-106) doesn't break with larger inputs.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds fuzzy “Did you mean?” suggestions for common workflow configuration typos by extracting reusable Levenshtein matching into pkg/stringutil and applying it to additional validation sites (events, permissions, MCP type), improving error recovery guidance.

Changes:

  • Introduces pkg/stringutil fuzzy matching utilities and updates parser schema suggestions to delegate to them.
  • Adds workflow validations with fuzzy suggestions for on: event types and permission scope map keys.
  • Enhances MCP type validation errors to include “Did you mean?” hints when applicable, and adds unit tests for the new utilities/validators.
Show a summary per file
File Description
pkg/workflow/permissions_validation.go Adds ValidatePermissionScopeNames to suggest corrections for mistyped permission scope keys.
pkg/workflow/permissions_scope_validation_test.go Adds unit tests for permission-scope typo validation behavior.
pkg/workflow/permissions_compiler_validator.go Hooks permission-scope typo validation into the compiler permission validation pipeline.
pkg/workflow/mcp_property_validation.go Adds fuzzy “Did you mean?” suggestions for invalid MCP type values.
pkg/workflow/event_validation.go New validator to detect likely typos in on: event names and suggest corrections.
pkg/workflow/event_validation_test.go Adds unit tests for event-type typo validation behavior.
pkg/workflow/compiler_orchestrator_frontmatter.go Invokes event-type typo validation during frontmatter parsing/validation.
pkg/stringutil/fuzzy_match.go New shared Levenshtein + closest-match utility used across validators.
pkg/stringutil/fuzzy_match_test.go Unit tests for shared fuzzy matching utilities.
pkg/parser/schema_suggestions.go Refactors existing fuzzy matching to call into pkg/stringutil.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 10/10 changed files
  • Comments generated: 5

"github-app": true,
"github-token": true,
"label_command": true,
"labels": true,
Comment on lines +134 to +153
// Check each event name against the list of known valid events
for _, eventName := range eventNames {
if isKnownGitHubEvent(eventName) {
continue
}

// Skip gh-aw-specific on: section extensions
if ghAwOnSectionKeys[eventName] {
eventValidationLog.Printf("Skipping gh-aw extension key: %q", eventName)
continue
}

eventValidationLog.Printf("Unknown event type: %q", eventName)

// Only flag as a typo when there is a close match
suggestions := stringutil.FindClosestMatches(eventName, validGitHubEventTypes, 3)
if len(suggestions) == 0 {
eventValidationLog.Printf("No close matches found for unknown event %q, skipping", eventName)
continue
}
Comment on lines +455 to +456
suggestions := stringutil.FindClosestMatches(scopeKey, allScopes, 3)
if len(suggestions) == 0 {
Comment on lines 62 to 74
// Normalize "local" to "stdio" for validation
if typeStr == "local" {
typeStr = "stdio"
}

// Validate type is one of the supported types
if !parser.IsMCPType(typeStr) {
validTypes := []string{"stdio", "http"}
suggestions := stringutil.FindClosestMatches(typeStr, validTypes, 1)
if len(suggestions) > 0 {
return fmt.Errorf("tool '%s' mcp configuration 'type' must be one of: stdio, http (per MCP Gateway Specification). Note: 'local' is accepted for backward compatibility and treated as 'stdio'. Got: %s.\n\nDid you mean: %s?\n\nExample:\ntools:\n %s:\n type: \"stdio\"\n command: \"node server.js\"\n\nSee: %s", toolName, typeStr, strings.Join(suggestions, ", "), toolName, constants.DocsToolsURL)
}
return fmt.Errorf("tool '%s' mcp configuration 'type' must be one of: stdio, http (per MCP Gateway Specification). Note: 'local' is accepted for backward compatibility and treated as 'stdio'. Got: %s.\n\nExample:\ntools:\n %s:\n type: \"stdio\"\n command: \"node server.js\"\n\nSee: %s", toolName, typeStr, toolName, constants.DocsToolsURL)
Comment on lines +12 to +67
func TestValidateEventTypes(t *testing.T) {
tests := []struct {
name string
frontmatter map[string]any
wantErr bool
errContains string
}{
{
name: "valid event string form",
frontmatter: map[string]any{
"on": "push",
},
wantErr: false,
},
{
name: "valid events in list form",
frontmatter: map[string]any{
"on": []any{"push", "pull_request"},
},
wantErr: false,
},
{
name: "valid events in map form",
frontmatter: map[string]any{
"on": map[string]any{
"push": nil,
"workflow_dispatch": nil,
},
},
wantErr: false,
},
{
name: "typo pus suggests push",
frontmatter: map[string]any{
"on": []any{"pus"},
},
wantErr: true,
errContains: "Did you mean",
},
{
name: "typo pull_rquest suggests pull_request",
frontmatter: map[string]any{
"on": map[string]any{
"pull_rquest": nil,
},
},
wantErr: true,
errContains: "Did you mean",
},
{
name: "unknown event with no close match is silently skipped",
frontmatter: map[string]any{
"on": []any{"completely_unknown_event_xyz"},
},
wantErr: false,
},
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

PR Code Quality Reviewer completed the code quality review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot review all comments

@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 100/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All tests enforce behavioral contracts with comprehensive edge case coverage.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Quality Review

This PR successfully extracts fuzzy matching into a reusable utility and applies it consistently across validation sites. The core logic is sound and well-tested.

Issues to address:

  1. Missing error handling in ValidatePermissionScopeNames after YAML parsing
  2. Performance concern in LevenshteinDistance - unnecessary allocations for short strings
  3. Inconsistent error formatting between validation sites

What was done well:

  • ✅ Clean refactoring with proper extraction to pkg/stringutil
  • ✅ Comprehensive test coverage with table-driven tests
  • ✅ Backward compatibility maintained in pkg/parser
  • ✅ Good documentation and helpful "Did you mean?" suggestions

Please address the inline comments before merging.

Note

🔒 Integrity filter blocked 1 item

The following item was blocked because it doesn't meet the GitHub integrity level.

  • #33467 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

🔎 Code quality review by PR Code Quality Reviewer · ● 3.9M

if err := yaml.Unmarshal([]byte(content), &permsMap); err != nil {
// Not a map (e.g., a shorthand like "read-all"); nothing to validate
return nil
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error handling after YAML unmarshal

The code parses content as YAML but doesn't validate whether the resulting map is actually a permissions map with scope keys. If someone provides malformed YAML that parses successfully as a map but has unexpected structure, this could cause silent failures or panics in the loop.

Suggestion: Add a type assertion or validation to ensure permsMap[scopeKey] values are of expected type (string or nil) before proceeding with the loop.


// Create a 2D matrix for dynamic programming
// We only need the previous row, so we can optimize space
previousRow := make([]int, bLen+1)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential performance issue: unnecessary allocations

The implementation allocates two full-length slices (previousRow and currentRow) on every call, even for very short strings. For the common case of 3-10 character typos, this is wasteful.

Suggestion: Consider pre-allocating a reusable buffer pool or use stack-allocated arrays for strings under a certain length threshold (e.g., 32 characters). This would reduce GC pressure when called frequently during compilation.

validTypes := []string{"stdio", "http"}
suggestions := stringutil.FindClosestMatches(typeStr, validTypes, 1)
if len(suggestions) > 0 {
return fmt.Errorf("tool '%s' mcp configuration 'type' must be one of: stdio, http (per MCP Gateway Specification). Note: 'local' is accepted for backward compatibility and treated as 'stdio'. Got: %s.\n\nDid you mean: %s?\n\nExample:\ntools:\n %s:\n type: \"stdio\"\n command: \"node server.js\"\n\nSee: %s", toolName, typeStr, strings.Join(suggestions, ", "), toolName, constants.DocsToolsURL)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent error message format

The error message here is very long and includes inline examples. Compare this to the cleaner format in permissions_validation.go (line ~455) where the suggestion is brief and actionable.

Suggestion: Simplify this error message to match the pattern used elsewhere:

return fmt.Errorf("tool '%s' mcp configuration 'type' must be one of: stdio, http. Got: %s. Did you mean: %s?", toolName, typeStr, strings.Join(suggestions, ", "))

Move the detailed example and documentation link to a separate doc comment or user-facing guide.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🧪 Test Quality Sentinel completed test quality analysis.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /improve-codebase-architecture, /zoom-out, and /tdd based on this PR's refactor + feature addition nature.

Key Themes

  1. Reusability gap: The maxDistance = 3 constant is hardcoded in FindClosestMatches, limiting reusability across different validation strictness requirements.

  2. Pattern duplication: Event validation and permission validation both implement the same "fuzzy match with silent skip" pattern — opportunity to extract a shared helper.

  3. Maintenance burden: The static validGitHubEventTypes array will become stale as GitHub adds new events. Consider documenting maintenance expectations or adding an integration test.

  4. Test clarity: The "cop" → "codex" test documents surprising behavior without explaining the rationale.

  5. Observability: Silent skips for unknown values with no close matches are invisible to users. Debug logging would help troubleshooting.

Title vs Implementation Discrepancy

⚠️ The PR title mentions "engine" validation, but the diff shows no engine_validation.go changes. The PR body also claims "four additional validation sites" but only implements three (events, permissions, MCP types). Did engine validation get deferred to a follow-up PR?

Positive Highlights

  • Clean extraction: Moving fuzzy matching from pkg/parser to pkg/stringutil is the right architectural move
  • Comprehensive tests: Both fuzzy_match_test.go and validation tests have good coverage of edge cases
  • User-friendly errors: The "Did you mean?" suggestions are a significant UX improvement
  • Backward compatible: Silent-skip behavior for unknown values preserves forward compatibility
  • Consistent error format: All validation sites use the same error message structure

Verdict

This is solid work that meaningfully improves the user experience. The inline comments suggest follow-up improvements (not blockers) to make the utility more reusable and the validation logic more consistent.

No changes requested — these are architectural deepening opportunities for future PRs.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · ● 6.9M

//
// This function is useful for "Did you mean?" suggestions when a user provides
// an unrecognized value (e.g., a typo in an engine name or event type).
func FindClosestMatches(target string, candidates []string, maxResults int) []string {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/improve-codebase-architecture] The FindClosestMatches function has a magic number (maxDistance = 3) that is hardcoded inside the function body. This constant defines the acceptable typo tolerance for suggestions.

Problem: If a future validation site needs a different distance threshold (e.g., maxDistance = 2 for stricter matching), callers cannot customize it without duplicating the entire function.

Suggestion: Expose maxDistance as a parameter:

func FindClosestMatches(target string, candidates []string, maxResults int, maxDistance int) []string {

Or provide a sensible default with a separate function:

func FindClosestMatchesWithDistance(target string, candidates []string, maxResults int, maxDistance int) []string { ... }

func FindClosestMatches(target string, candidates []string, maxResults int) []string {
    return FindClosestMatchesWithDistance(target, candidates, maxResults, 3)
}

This makes the utility more reusable and aligns with the goal of extracting logic into a shared package.

target: "cop",
candidates: []string{"copilot", "claude", "codex", "custom"},
maxResults: 3,
want: []string{"codex"},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] This test (partial match cop suggests codex within distance 3) validates surprising behavior:

  • Input: "cop"
  • Expected: "codex"
  • But "copilot" is at distance 4, so it's excluded

Problem: This test is documenting an edge case but doesn't explain why this behavior is correct. Is "cop" → "codex" the intended suggestion, or is this exposing a limitation of the current maxDistance = 3 threshold?

Suggestion: Add a comment explaining the rationale:

{
    name:       "partial match cop suggests codex within distance 3",
    // "copilot" has distance 4 (too far), but "codex" has distance 3 (acceptable)
    // This demonstrates the maxDistance cutoff working as intended
    target:     "cop",
    candidates: []string{"copilot", "claude", "codex", "custom"},
    maxResults: 3,
    want:       []string{"codex"},
},

Or, if this is unintended, consider raising maxDistance or making it configurable per the previous comment.

eventNames = append(eventNames, key)
}
default:
eventValidationLog.Printf("'on' section has unexpected type %T, skipping event type validation", on)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/zoom-out] The silent-skip behavior for unknown events with no close match is a design decision with UX tradeoffs:

Current behavior: Unknown event "completely_unknown_event_xyz" passes silently.

Pro: Won't block workflows using future GitHub Actions events.
Con: Users won't be warned about misspellings that happen to be far from any known event.

Suggestion: Consider adding a debug-level log so authors can discover silent skips when troubleshooting:

if len(suggestions) == 0 {
    eventValidationLog.Printf("Unknown event %q has no close matches (distance > 3), allowing silently", eventName)
    continue
}

This preserves forward compatibility while making the behavior discoverable when DEBUG=workflow:event_validation is enabled.


// validGitHubEventTypes is the list of all supported GitHub Actions event types.
// Source: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
var validGitHubEventTypes = []string{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] The validGitHubEventTypes list is static and will become stale as GitHub adds new event types. There's no test ensuring this list is kept up-to-date.

Suggestion: Add a test comment documenting the maintenance expectation:

// validGitHubEventTypes is the list of all supported GitHub Actions event types.
// Source: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
// MAINTENANCE: Update this list when GitHub adds new event types. Consider adding
// a test that fetches the canonical list and compares it to this array.
var validGitHubEventTypes = []string{

Or better: add an integration test that fetches GitHub's event schema and validates this list is complete (if a stable API exists for event metadata).

allScopes = append(allScopes, string(PermissionCopilotRequests))
// "all" is a meta-key that is always valid in shorthand contexts
validMeta := map[string]bool{
"all": true,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/zoom-out] This function (ValidatePermissionScopeNames) duplicates the "silent skip" pattern from event_validation.go line 130. Both functions:

  1. Check for close matches using stringutil.FindClosestMatches
  2. Skip unknown values with no suggestions
  3. Return an error for typos with suggestions

Opportunity: Extract this validation pattern into a reusable helper:

// stringutil/validator.go
func ValidateWithSuggestions(value string, validValues []string, fieldName string, docsURL string) error {
    if slices.Contains(validValues, value) {
        return nil
    }
    suggestions := FindClosestMatches(value, validValues, 3)
    if len(suggestions) == 0 {
        return nil // silent skip
    }
    return fmt.Errorf("unknown %s %q.\n\nDid you mean: %s?\n\nSee: %s",
        fieldName, value, strings.Join(suggestions, ", "), docsURL)
}

This would make the validation logic consistent across event types, permissions, and future validation sites.

@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 100/100

Excellent test quality

Metric Value
New/modified tests analyzed 4 test functions (19 table-driven scenarios)
✅ Design tests (behavioral contracts) 4 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 4 (100%)
Duplicate test clusters 0
Test inflation detected No
🚨 Coding-guideline violations 0

Test Classification Summary

Test Function File Scenarios Classification Edge Cases
TestFindClosestMatches pkg/stringutil/fuzzy_match_test.go 10 ✅ Design Empty strings, exact matches, no matches
TestLevenshteinDistance pkg/stringutil/fuzzy_match_test.go 9 ✅ Design Empty strings, identical strings
TestValidateEventTypes pkg/workflow/event_validation_test.go 8 ✅ Design Typos, unknown events, missing section
TestValidatePermissionScopeNames pkg/workflow/permissions_scope_validation_test.go 8 ✅ Design Typos, unknown scopes, empty YAML

Quality Highlights

✅ Excellent Test Design

All tests follow best practices:

  1. Table-driven patterns - Each test function uses t.Run() over a slice of test cases, covering multiple scenarios efficiently
  2. Behavioral contracts - All tests verify observable behavior that users/callers depend on:
    • FindClosestMatches: Returns correct fuzzy match suggestions within distance threshold
    • LevenshteinDistance: Computes correct edit distances for string pairs
    • ValidateEventTypes: Validates event types and provides helpful error messages
    • ValidatePermissionScopeNames: Validates permission scopes and suggests corrections
  3. Comprehensive edge case coverage - Every test includes boundary conditions:
    • Empty inputs
    • Exact matches (should not suggest)
    • No close matches (should return nil)
    • Error paths with helpful messages
  4. Proper assertions with messages - All assertions include descriptive context: assert.Equal(t, want, got, "descriptive message")
  5. No forbidden patterns - Zero use of mock libraries (gomock/testify/mock)
  6. Proper build tags - All test files correctly declare //go:build !integration on line 1

📊 Test Inflation Analysis

All ratios are healthy (below 2:1 threshold):

Test File Test Lines Production Lines Ratio
fuzzy_match_test.go 123 111 1.11:1 ✅
event_validation_test.go 97 169 0.57:1 ✅
permissions_scope_validation_test.go 81 82 0.99:1 ✅

Verdict

Check passed. 0% of new tests are implementation tests (threshold: 30%). All tests verify behavioral contracts with excellent edge case coverage. No coding-guideline violations detected.


📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

🧪 Test quality analysis by Test Quality Sentinel · ● 5.2M ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 100/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All tests verify behavioral contracts with comprehensive edge case coverage.

…xclusion, test coverage

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 20, 2026

@copilot review all comments

All review comments addressed in the latest commit:

  • pull_request_reviewer and needs missing from exclusion set — both added to ghAwOnSectionKeys; tests added for each synthetic key being silently skipped
  • Case-only typos for events (Push, Pull_Request) — added an explicit check before fuzzy matching: if strings.ToLower(eventName) matches a known event, return an error suggesting the canonical lowercase form; tests added
  • Case-only typos for permission scopes (Contents, Issues) — same pattern: check strings.ToLower(scopeKey) against the valid scopes map before fuzzy matching; tests added
  • MCP type case differences (Stdio, HTTP, Local) — typeStr is now normalized to strings.ToLower(strings.TrimSpace(typeStr)) early so uppercase/mixed-case values are accepted silently

Copilot AI requested a review from pelikhan May 20, 2026 06:49
@github-actions
Copy link
Copy Markdown
Contributor

Please refresh the branch and rerun checks.

Generated by 👨‍🍳 PR Sous Chef · ● 17M ·

@github-actions github-actions Bot mentioned this pull request May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[plan] Add fuzzy matching for common user input errors

4 participants