Skip to content

Planned Taskless Rules - #168

Open
thecodedrift wants to merge 7 commits into
nightly/testfrom
taskless/planned-rules
Open

Planned Taskless Rules#168
thecodedrift wants to merge 7 commits into
nightly/testfrom
taskless/planned-rules

Conversation

@thecodedrift

@thecodedrift thecodedrift commented Aug 24, 2026

Copy link
Copy Markdown
Member

Stack (root → tip):

Ten rules for our own repository, mined from the places we already state our conventions in prose: CLAUDE.md, the two .conventions styleguides, and the PostHog notes. Nothing here is settled — the point of landing it is to have somewhere concrete to argue about what we actually want enforced.

Rule Engine Flags Today
docs-npx-cli vale pnpm dlx @taskless/cli / pnpm cli in any README 2 real violations
no-em-dashes vale em and en dashes 24 findings in READMEs
no-blocklist-phrases vale the house blocklist (reflexive agreement, performative candor, load-bearing) clean
no-hedging vale "simply", "obviously", "of course", "trivially" clean
no-index-imports sg relative imports ending in /index clean
no-pii-in-telemetry sg email/displayName/etc. in capture(), identify(), groupIdentify() clean
no-regex-over-build-output sg a test function that reads dist/ and then regexes it clean
pr-workflow-no-branches-filter sg a branches: filter under a pull_request: trigger clean
pr-workflow-ready-for-review sg a pull_request: types: list that omits ready_for_review 1 finding, see below
prefer-do-rpc sg … as DurableObjectStub<T> casts no instances here

The two docs-npx-cli findings — README.md:37 and packages/cli/README.md:17 — are left unfixed on purpose, so the PR demonstrates a rule catching something rather than only asserting it would.

The two Vale house-style rules come from the dogfooding issue (#104 / OSS-28), scoped to **/README.md. Widening them is #169, because repo-wide they are roughly 2300 findings. Two corrections to that issue's spec, both measured and both in the rule files: no-em-dashes needs nonword: true or it silently never fires, and the proposed landed on token fires on "the plane landed on time" and was dropped.

The 24 em-dash findings in READMEs are unfixed. Rewriting them is an editorial pass on user-facing prose, so it wants a decision rather than a default: rewrite the prose, or drop the rule to warning until someone does.

The two pr-workflow-* rules come from OSS-49, which names both and records that an earlier onboarding pass stalled on whether ast-grep handles YAML. It does — Yaml is one of its 26 languages — so both build locally instead of needing a login.

pr-workflow-ready-for-review reports one finding, and it is a question rather than a defect: stack-breadcrumb.yml names types: [opened, reopened, edited, closed] with no ready_for_review. It reacts to PR metadata rather than to readiness, so omitting it may well be correct. Settling that is part of what this PR is for.

Where the rules are narrower than the conventions

Three are worth arguing about specifically, because each is a deliberate retreat from what the styleguide actually says:

  • no-index-imports is not "no barrel imports." Telling from "../wizard" (a directory barrel) from from "./ask" (a file) needs filesystem resolution, which is a cross-file question and therefore runtime-tier. The rule catches only the explicit /index form, which means packages/cli/src/commands/init.ts:16 is a real violation that nothing in this PR flags.
  • no-regex-over-build-output scopes to the enclosing function, not the file. Scoped to the file it fired three times on packages/cli/test/prompts.test.ts, where a helper deliberately regexes hand-written source and the same file separately loads a built artifact. That helper is correct and the styleguide says so.
  • prefer-do-rpc has no instances in this repository — no octokit, no Durable Objects. Its tests are synthetic and it is carried from the shared styleguide as a pre-emptive rule. Reasonable to drop it here and keep it wherever the DO code actually lives.

Two conventions could not be expressed at all while logged out, both for the same reason — they need the cross-file graph: "a type reachable from an exported signature must itself be exported" (the declaration: true trap) and "a hand-written type must not duplicate a library type."

Where to start

The two Vale .vale.ini files. Scoping is the decision most likely to be wrong and the least visible in a diff: both rules are restricted to READMEs, both exclude **/test/fixtures/** (they were firing on CLI test inputs), and docs-npx-cli deliberately does not cover CLAUDE.md, which documents the local pnpm cli path on purpose.

docs-npx-cli also carries scope: [raw, code, text]. Without it the rule passes every fixture and catches nothing real, because every command in a README is in a code span or a fenced block.

Carried along

The rules/ engine partition, taskless.json, the embedded SKILL.md, and the no-eval move were already in the working tree from the install. Also backfilled: tests for no-eval, which had been failing verify for a missing test file, and every rule's language: is now on ast-grep's own spelling rather than lowercase.

Refs #165
Refs #166
Refs #167

Seven rules mined from CLAUDE.md, the .conventions styleguides, and the
posthog conventions — the places this repo already states its rules in
prose. Each one is verified and tested locally; `check` reports two real
findings, both READMEs telling external consumers to run `pnpm dlx`.

sg:
  no-index-imports              relative imports ending in /index
  no-pii-in-telemetry           PII in capture/identify/groupIdentify
  prefer-do-rpc                 `as DurableObjectStub<T>` casts
  no-regex-over-build-output    a test function that reads dist/ and regexes it
  no-pull-request-branches-filter  a branches: filter under pull_request:

vale:
  docs-npx-cli                  pnpm invocations in READMEs
  no-hedging                    simply / obviously / of course

Also backfills tests for the pre-existing no-eval rule, which was
failing `verify` for a missing test file, and puts every rule's
`language:` on ast-grep's own spelling.

The install churn — the rules/ partition, taskless.json, the embedded
SKILL.md — was already in the tree and is carried along rather than
authored here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cEN93Acyp4zBwP3oDnyy1
@thecodedrift

Copy link
Copy Markdown
Member Author

prefer-do-rpc feels like we won't need it here. The taskless services need it, but the CLI doesn't since it doesn't require cloudflre

no-pii-in-telemetry is a great usecase. Having a way to assert PII is being managed responsibly helps ensure mistakes don't get made

docs-npx-cli I'd definitely prefer this and add a note in the README that there's a "cli" script inside of package.json for running the CLI in a local environment

thecodedrift and others added 5 commits August 24, 2026 17:04
A sweep of merged-PR review threads and the OSS Linear backlog turned up
OSS-49, which names two planned GitHub Actions rules and records that a
prior onboarding pass stalled on whether ast-grep handles YAML. It does,
so both are buildable locally rather than runtime-tier.

Adds pr-workflow-ready-for-review, and renames the branches-filter rule
to the pr-workflow-* name OSS-49 already uses for the pair.

One finding on the real workflows: stack-breadcrumb.yml names
types: [opened, reopened, edited, closed] with no ready_for_review. That
is a question rather than a defect — it reacts to PR metadata, not to
readiness — and is left for review to settle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cEN93Acyp4zBwP3oDnyy1
OSS-28 specifies the house writing style as Vale rules. This adds the two
that can be expressed cleanly, scoped to READMEs rather than the whole
repository: broadening is a separate decision with roughly 2200 findings
attached.

no-em-dashes needs `nonword: true`, which the snippet in OSS-28 does not
carry. Measured: without it the rule parses, passes verify, and does not
fire, because Vale wraps every token in word boundaries and an em dash is
non-word on both sides.

no-blocklist-phrases drops the `landed on` token OSS-28 proposed. Measured
firing on "the plane landed on time", which is the literal sense the issue
says to protect; `we landed` already covers "we landed on the second
option", so the broader token earned nothing.

Not included: the "not X, Y" antithesis rule. OSS-28 is undecided on how to
express it and calls it a heuristic, so it wants a human judgement this pass
cannot make.

24 findings in READMEs, all em dashes, left unfixed pending a call on
whether to rewrite the prose or relax the level.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cEN93Acyp4zBwP3oDnyy1
Brings the nine READMEs in line with no-em-dashes, which this branch
scopes to `**/README.md`. Twenty-four instances, rewritten as a period,
comma, colon, or parentheses per the rule's own message rather than
mechanically swapped for one substitute.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cEN93Acyp4zBwP3oDnyy1
docs-npx-cli says docs use `npx @taskless/cli`, the normalized invocation
for external consumers. Two README blocks offered `pnpm dlx` alongside it,
which is the same claim the rule exists to prevent, so the alternative is
removed rather than annotated.

Annotating was measured and is not available here: a rule scoped to `raw`
reads the unparsed document, so Vale's `<!-- vale Rule = NO -->` directive
is inert for it. That scope is what lets the rule see fenced blocks at all,
and every command in a README lives in one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cEN93Acyp4zBwP3oDnyy1
The most repeated finding in the merged-PR review threads: a comment that
cites a version or a claim the code moved out from under it. On #161 alone,
five threads — "we pin 3.17.1" left behind after VALE_VERSION went to
3.18.0, a comment naming .rmd as plaintext after the diff moved it to
markup, a block still framing 3.18.0 as "the known incoming bump" after it
shipped. Same shape on #155 and #157.

The rule flags the construction rather than the stale number, which is the
half a static check can see. Vale reads .ts in its comments-only tier, so it
lints the comment text and never the code.

Zero findings on packages/cli/src today, because #161 fixed them all. Reach
verified separately by planting a forecast comment in a real source file:
fixtures run under an isolating config, so a passing test does not prove the
matcher glob reaches anything.

Also ignores .taskless/ in eslint and prettier. A rule about source comments
needs .ts fixtures, Vale decides its comments-only tier by extension, and
those files belong to no tsconfig — so lint-staged failed the commit on
"not found by the project service". Rule fixtures are inputs written to be
flagged; verify and test are what keep them honest.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cEN93Acyp4zBwP3oDnyy1
@thecodedrift
thecodedrift marked this pull request as ready for review August 25, 2026 02:30
Copilot AI lite review requested due to automatic review settings August 25, 2026 02:30

Copilot AI left a comment

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

pr-workflow-ready-for-review flagged this as the only finding on the repo,
and it is a real gap rather than the intended exception. `ready_for_review`
is not in the default event set, so a draft marked ready fired nothing here:
the breadcrumb went on describing the PR as a draft until some later event
happened to run.

The existing comment says tree SHAPE only, which is still true —
`synchronize` stays out because a head push never changes membership. A
draft becoming ready does change the stack, so it is named explicitly and
the comment now says why.

`taskless check` is clean at 12 rules.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cEN93Acyp4zBwP3oDnyy1
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.

2 participants