Repository navigation
feat(vale): schema-check per-rule .vale.ini in verify (slice 1) #768
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # THIS NAME IS AN INTERFACE, NOT A LABEL. `release-cli-nightly.yml` triggers on | |
| # `workflow_run: workflows: [Validate]`, which matches this string and not this | |
| # file's path — a nightly is only published from a commit this workflow passed | |
| # on. Rename it and the nightly stops firing permanently, with no error | |
| # anywhere and nothing turning red. Rename both together, or neither. | |
| name: Validate | |
| on: | |
| push: | |
| branches: [main] | |
| # No `branches:` filter, deliberately. Lint, typecheck, and tests have no | |
| # interest in where a PR eventually merges, and filtering on `main` silently | |
| # skipped this workflow on stacked PRs. | |
| # | |
| # The filter matches the PR's base ref, but GitHub also resolves a stacked | |
| # PR's *eventual* target and matches on that — so `branches: [main]` did run | |
| # on PRs based on another branch, until it stopped. Measured on the | |
| # #71→#93→#94→#95→#100→#102→#103→#106 stack: every PR up to #102 got a | |
| # `Validate` run, while #103 and #106 got none, across 16 `pull_request` | |
| # events that other workflows handled fine. A filter that works for six PRs | |
| # and quietly fails on the seventh is worse than one that never worked, | |
| # because nobody re-checks it. | |
| # | |
| # `ready_for_review` is NOT in the default set (opened/synchronize/reopened) | |
| # and must be named: without it a draft marked ready gets no fresh run until | |
| # something happens to push again, which is exactly the state #103 sat in. | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| permissions: | |
| contents: read | |
| # This workflow runs the CLI this repository builds. Its telemetry is the same | |
| # production client a user's install has, so every invocation here would count | |
| # as adoption. Opting out is the CLI's own switch, read by the built binary. | |
| env: | |
| TASKLESS_TELEMETRY_DISABLED: "1" | |
| jobs: | |
| validate: | |
| name: Validate | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0 | |
| - name: Setup Node | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version-file: .nvmrc | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Lint | |
| run: pnpm lint | |
| - name: Typecheck | |
| run: pnpm typecheck | |
| - name: Build | |
| run: pnpm build | |
| - name: Test | |
| run: pnpm test | |
| # `test:scripts` covers .github/scripts/ AND the skill scripts under | |
| # .agents/skills/*/scripts/, which are zero-dependency CommonJS with | |
| # node:test suites beside them. It lives in package.json so the same | |
| # command runs locally. | |
| # | |
| # Its globs are UNQUOTED on purpose. Node's own glob expansion exits 0 | |
| # when a pattern matches nothing, so a renamed or moved directory would | |
| # report a clean pass having run no tests at all; an unmatched shell glob | |
| # reaches node as a literal path and fails loudly with "Could not find". | |
| # An absent check reads like a passing one, so take the loud failure. | |
| - name: Test workflow and skill scripts | |
| run: pnpm test:scripts | |
| # House style, enforced rather than documented. The rules live in | |
| # `.taskless/` and are scoped to the documents people and agents actually | |
| # read: every README, CLAUDE.md, `.conventions/*.md`, this directory's | |
| # workflows, and comments under `packages/cli/src/`. | |
| # | |
| # A step here, not a standalone `taskless.yml`. The canonical recipe | |
| # (`taskless agent ci`) writes a separate workflow so that onboarding | |
| # never touches a pipeline it does not own, but the two things this repo | |
| # needs are only available inside this job. Branch protection requires | |
| # `Validate` and nothing else, so a separate workflow would report and | |
| # block nothing, which is the whole of what #104 asked for; and `check` | |
| # runs this repo's own build, which the `Build` step above has already | |
| # produced. Full scan rather than the recipe's diff scan, for the reason | |
| # `Validate specs` gives below: rot accumulates in the files a PR does | |
| # not touch, and the scoped corpus is small enough that a diff scan buys | |
| # nothing. | |
| # | |
| # Placed after the test steps rather than immediately after `Build`, so | |
| # that the existing signal order (lint, types, build, tests) stays intact | |
| # for anyone used to reading these logs. It only needs to be after | |
| # `Build`; nothing above it depends on it. | |
| # | |
| # `pnpm cli` is the workspace build, NOT a published release. That is a | |
| # deliberate divergence from `ci.txt` and is ENFORCED, not requested: | |
| # the `ci-uses-workspace-cli` rule fails this very workflow if the | |
| # invocation is changed back, and carries the reasoning in its `note:`. | |
| # `Build` above ran `pnpm build` on this same commit, so `dist/` here | |
| # can be neither stale nor missing, and an absent `dist/` would fail | |
| # this step loudly rather than pass it empty. | |
| # | |
| # This blocks. `check` exits non-zero on any error-severity finding and | |
| # on an engine that failed or timed out, so an em dash added to a covered | |
| # document turns the build red. Warning-severity rules report without | |
| # failing, which is what `severity: warning` in a rule means. | |
| # | |
| # No authentication and no secrets: static rules (Vale and ast-grep) run | |
| # unauthenticated. Runtime rules under `.taskless/rules/runtime/` are | |
| # skipped without a token; that directory is empty today, and wiring | |
| # `TASKLESS_TOKEN` is the separate decision to make when it is not. | |
| - name: Check house style | |
| run: pnpm cli check | |
| # Repo-wide, not changed-files-only: spec rot accumulates in the specs a | |
| # PR does not touch, so a scoped check would never surface it. | |
| - name: Validate specs | |
| run: pnpm openspec validate --all --strict | |
| # `--strict` validates what the parser read, not that it read the whole | |
| # file. A second `##` inside `## Requirements` ends the section and every | |
| # requirement below it becomes invisible — valid, unread, and green. | |
| - name: Check spec requirement visibility | |
| run: node .github/scripts/openspec-visibility.cjs |