You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Routing for sg and vale should include lists of supported languages #151
In order for agents to clearly identify if a rule can be built locally, the list of supported languages for sg and vale should be in the routing recipe.
Remaining are the two GitHub Actions YAML rules — pr-workflow-no-branches-filter and pr-workflow-ready-for-review. Both depend on ast-grep handling YAML, which I still haven't verified; if it doesn't, route will likely send them to runtime, which needs a login. Want me to press on to #4?
Discovered in @taskless/cli-nightly@0.11.0-20260824013916xe788b11
pr-workflow-no-branches-filter was authored as a real rule (language: Yaml, matching branches: inside a pull_request mapping): taskless verify → ✓, taskless test → ✓. ast-grep gives YAML real node kinds (block_mapping_pair, flow_node, plain_scalar), so route should not have sent these to runtime.
But a separate bug would have made it look unsupported
taskless check finds nothing under .github/ for a byte-identical file it finds elsewhere:
$ taskless check → No issues found.
$ cp .github/workflows/bad.yml notdot/ && taskless check
notdot/bad.yml:3:5 error[pr-workflow-no-branches-filter] pull_request must not carry a branches filter
ast-grep's walker skips hidden directories by default and runAstGrepScan never passes --no-ignore hidden (packages/cli/src/rules/scan.ts:139-146). No sg rule can see .github/, .circleci/, .vscode/, or .husky/ today. Vale does not have this blind spot — the same run reported .github/HIDDEN.md — so the two static engines disagree about whether .github/ exists. Arguably the higher-priority half of this issue.
On Vale, the list is not the interesting part — the failure tier is
Probed against the shipped 3.17.1 (Vale self-reports no format list, so every tier here is measured):
everything else, including .yml.toml.sh.sql, is linted as whole-file prose — a Vale rule on YAML flags its code, not just its comments
.rst.adoc.asciidoc.xml.dita.mdx hard-fail:E100, exit 2, needing rst2html / asciidoctor / an XSLT / dita / mdx2vast, none of which we ship
That last tier is quiet and total. One such file anywhere takes down the entire Vale pass, not just that file — measured: with a .adoc present, 3 Vale findings dropped to 0 and check still exited on sg's finding alone. Routing a prose rule at an AsciiDoc or reStructuredText repo therefore silently disables every other Vale rule, and nothing in route.txt or create-vale-rule.txt says so.
Design note — the part worth arguing about
There is no existing source of truth for either list. The generated src/generated/ast-grep-rule-schema.json types language as a bare string with no enum ($defs.Language is a placeholder); verify never validates it, so any string passes; and detect --json reports repo languages in a different vocabulary (C++ vs ast-grep's Cpp). The binaries are the only authority.
route.txt currently says nothing about language support — its engine table (agent/route.txt:66-71) is entirely about evidence shape. The closest it comes is conceding that availability is uncertain and telling the agent to pick an engine "whose availability you can assert," while giving it no way to assert it.
I'd argue against transcribing the lists into the recipe. Two lists that drift on a version bump with nothing to catch them, and prose that quietly stops being true is worse than the current silence — which at least makes the agent ask. Vale's is worse than a list anyway; the useful content is the tiers, including "these six hard-fail."
Instead: a pinned constant in src/rules/capabilities.ts (pure data, so the Worker-safe prompts/recipes.ts can import it), substituted into the recipes as %(SG_LANGUAGES)s / %(VALE_FORMATS)s, with vendor-contract tests asserting the constant still matches the binaries. That is the pattern test/ast-grep-vendor-contract.test.ts already exists for — exact-pinned binary plus a test that fires on the bump — so the list cannot drift without something going red. ast-grep self-reports via sg run -h; Vale reports nothing, so its tiers get probe-based pins.
Rejected the third option, extending detect --json with an engines block: openspec/specs/cli-detect/spec.md:100 frames detect as an offline repo scan, engine reach is knowable at build time rather than repo-scan time, and it would cost a third subprocess turn in a recipe already spending two.
Also worth stating in the recipe: a language absent from both lists is not a reason to escalate to runtime — create-legacy-rule should be checked first, since the repo's own linter may already cover it.
Implemented by #155 (71f4394), which added both lists to the routing recipe. route now carries:
ast-grep's 26 languages, in its own spelling, verbatim into a rule's language: field — with the note that off-list names split two ways: an alias it recognizes (cpp for Cpp) reaches the right parser, while one it does not (C# for CSharp) aborts config parsing and takes every other rule's report down with it.
Vale's four format tiers by extension — markup, comments-only, plaintext fallback, and the converter-dependent formats this build excludes whatever is installed on the machine.
The blocker this issue records is also resolved
The quoted context is a prior onboarding pass that stopped here:
Remaining are the two GitHub Actions YAML rules — pr-workflow-no-branches-filter and pr-workflow-ready-for-review. Both depend on ast-grep handling YAML, which I still haven't verified; if it doesn't, route will likely send them to runtime, which needs a login.
Yaml is on the list, so both are sg rules and neither needs a login. A later onboarding pass reached the same question and had it answered by the recipe rather than stalling — which is this issue's fix working end to end. Both rules are now written, verified, and tested, under the names used above, in #168.
Activity
theCodeDrift commentedon Aug 24, 2026
Yes — ast-grep supports YAML here, and both GitHub Actions rules belong in
create-sg-rulewith no login.The pinned binary (
@ast-grep/cli@0.41.0, exact-pinned inpackages/cli/package.json) enumerates 26 languages insg run -h:Bash, C, Cpp, CSharp, Css, Elixir, Go, Haskell, Hcl, Html, Java, JavaScript, Json, Kotlin, Lua, Nix, Php, Python, Ruby, Rust, Scala, Solidity, Swift, Tsx, TypeScript, Yamlpr-workflow-no-branches-filterwas authored as a real rule (language: Yaml, matchingbranches:inside apull_requestmapping):taskless verify→ ✓,taskless test→ ✓. ast-grep gives YAML real node kinds (block_mapping_pair,flow_node,plain_scalar), sorouteshould not have sent these to runtime.But a separate bug would have made it look unsupported
taskless checkfinds nothing under.github/for a byte-identical file it finds elsewhere:ast-grep's walker skips hidden directories by default and
runAstGrepScannever passes--no-ignore hidden(packages/cli/src/rules/scan.ts:139-146). Nosgrule can see.github/,.circleci/,.vscode/, or.husky/today. Vale does not have this blind spot — the same run reported.github/HIDDEN.md— so the two static engines disagree about whether.github/exists. Arguably the higher-priority half of this issue.On Vale, the list is not the interesting part — the failure tier is
Probed against the shipped 3.17.1 (Vale self-reports no format list, so every tier here is measured):
.md.markdown.html.org.py .rb .js .jsx .ts .tsx .go .rs .java .c .h .cpp .hpp .cs .php .swift .scala .lua .hs .clj .pl .r .jl .less .proto.yml.toml.sh.sql, is linted as whole-file prose — a Vale rule on YAML flags its code, not just its comments.rst.adoc.asciidoc.xml.dita.mdxhard-fail:E100, exit 2, needingrst2html/asciidoctor/ an XSLT /dita/mdx2vast, none of which we shipThat last tier is quiet and total. One such file anywhere takes down the entire Vale pass, not just that file — measured: with a
.adocpresent, 3 Vale findings dropped to 0 andcheckstill exited on sg's finding alone. Routing a prose rule at an AsciiDoc or reStructuredText repo therefore silently disables every other Vale rule, and nothing inroute.txtorcreate-vale-rule.txtsays so.Design note — the part worth arguing about
There is no existing source of truth for either list. The generated
src/generated/ast-grep-rule-schema.jsontypeslanguageas a bare string with no enum ($defs.Languageis a placeholder);verifynever validates it, so any string passes; anddetect --jsonreports repo languages in a different vocabulary (C++vs ast-grep'sCpp). The binaries are the only authority.route.txtcurrently says nothing about language support — its engine table (agent/route.txt:66-71) is entirely about evidence shape. The closest it comes is conceding that availability is uncertain and telling the agent to pick an engine "whose availability you can assert," while giving it no way to assert it.I'd argue against transcribing the lists into the recipe. Two lists that drift on a version bump with nothing to catch them, and prose that quietly stops being true is worse than the current silence — which at least makes the agent ask. Vale's is worse than a list anyway; the useful content is the tiers, including "these six hard-fail."
Instead: a pinned constant in
src/rules/capabilities.ts(pure data, so the Worker-safeprompts/recipes.tscan import it), substituted into the recipes as%(SG_LANGUAGES)s/%(VALE_FORMATS)s, with vendor-contract tests asserting the constant still matches the binaries. That is the patterntest/ast-grep-vendor-contract.test.tsalready exists for — exact-pinned binary plus a test that fires on the bump — so the list cannot drift without something going red. ast-grep self-reports viasg run -h; Vale reports nothing, so its tiers get probe-based pins.Rejected the third option, extending
detect --jsonwith anenginesblock:openspec/specs/cli-detect/spec.md:100framesdetectas an offline repo scan, engine reach is knowable at build time rather than repo-scan time, and it would cost a third subprocess turn in a recipe already spending two.Also worth stating in the recipe: a language absent from both lists is not a reason to escalate to runtime —
create-legacy-ruleshould be checked first, since the repo's own linter may already cover it.feat(cli): state each local engine's reach in the routing recipe
feat(cli): state each local engine's reach in the routing recipe
feat(cli): state each local engine's reach in the routing recipe
theCodeDrift commentedon Aug 25, 2026
Implemented by #155 (
71f4394), which added both lists to the routing recipe.routenow carries:language:field — with the note that off-list names split two ways: an alias it recognizes (cppforCpp) reaches the right parser, while one it does not (C#forCSharp) aborts config parsing and takes every other rule's report down with it.The blocker this issue records is also resolved
The quoted context is a prior onboarding pass that stopped here:
Yamlis on the list, so both aresgrules and neither needs a login. A later onboarding pass reached the same question and had it answered by the recipe rather than stalling — which is this issue's fix working end to end. Both rules are now written, verified, and tested, under the names used above, in #168.Closing as done.