From 714adf7c80a97a04e69332278b197cd073046991 Mon Sep 17 00:00:00 2001 From: Jakob Heuser Date: Sun, 26 Jul 2026 17:56:34 -0700 Subject: [PATCH 01/15] =?UTF-8?q?docs(openspec):=20add-vale-rule-engine=20?= =?UTF-8?q?=E2=80=94=20Vale=20as=20a=20second=20static-tier=20engine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01LdEhGzeQfSGJM3nKKNj7Bp --- .../add-vale-rule-engine/.openspec.yaml | 2 + .../changes/add-vale-rule-engine/design.md | 97 ++++++++++++++++++ .../changes/add-vale-rule-engine/proposal.md | 34 +++++++ .../specs/cli-check/spec.md | 52 ++++++++++ .../specs/cli-rule-format/spec.md | 75 ++++++++++++++ .../specs/cli-runtime-rule-execution/spec.md | 23 +++++ .../specs/cli-vale-rule-engine/spec.md | 98 +++++++++++++++++++ .../changes/add-vale-rule-engine/tasks.md | 45 +++++++++ 8 files changed, 426 insertions(+) create mode 100644 openspec/changes/add-vale-rule-engine/.openspec.yaml create mode 100644 openspec/changes/add-vale-rule-engine/design.md create mode 100644 openspec/changes/add-vale-rule-engine/proposal.md create mode 100644 openspec/changes/add-vale-rule-engine/specs/cli-check/spec.md create mode 100644 openspec/changes/add-vale-rule-engine/specs/cli-rule-format/spec.md create mode 100644 openspec/changes/add-vale-rule-engine/specs/cli-runtime-rule-execution/spec.md create mode 100644 openspec/changes/add-vale-rule-engine/specs/cli-vale-rule-engine/spec.md create mode 100644 openspec/changes/add-vale-rule-engine/tasks.md diff --git a/openspec/changes/add-vale-rule-engine/.openspec.yaml b/openspec/changes/add-vale-rule-engine/.openspec.yaml new file mode 100644 index 00000000..9e5b8a19 --- /dev/null +++ b/openspec/changes/add-vale-rule-engine/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-07-23 diff --git a/openspec/changes/add-vale-rule-engine/design.md b/openspec/changes/add-vale-rule-engine/design.md new file mode 100644 index 00000000..d44200bf --- /dev/null +++ b/openspec/changes/add-vale-rule-engine/design.md @@ -0,0 +1,97 @@ +## Context + +Taskless rules run today through one engine, ast-grep: `commands/check.ts` writes an ephemeral `sgconfig.yml` (`ruleDirs: [rules]`) and runs `sg scan --config … --json=stream`; rules live as bare ast-grep YAML at `.taskless/rules/*.yml`. A separate **runtime** tier (`runtime-rules//`: capture YAML + signed `check.ts`) runs only after an authenticated server reconcile. A `.taskless/` migration system exists (`filesystem/migrate.ts`→`runMigrations`, keyed on `taskless.json`'s `version`, invoked via `ensureTasklessDirectory`). + +We add **Vale**, a markup-aware prose linter, because ast-grep can't lint prose. The design was derived empirically against `vale 3.15.1` and `sg 0.41.0`; the facts that shaped it: + +- **Each tool already has a native, committed config that expresses everything we need** — ast-grep: a rule's native `files`/`ignores` scope it, `metadata` holds extra data; Vale: a `.vale.ini` **matcher** (a `[]` section) scopes rules by path glob and, because Vale accepts and silently ignores unknown keys, holds arbitrary Taskless data _within that matcher_. So Taskless needs **no separate metadata/sidecar layer** — each engine's own config is the source of truth. +- **Vale `.vale.ini` scoping composes cleanly and predictably** (all verified): `[] Style.Rule = YES` enables a rule for a path (no `BasedOnStyles` needed); overlapping enables **union**; `[] Style.Rule = NO` **disables** and wins over an enable, order-independent; globs support brace alternation with slashes (`[{marketing/**,docs/**}]`) and whole-section negation (`[!x]`). So arbitrary per-rule include/exclude lives in the `.ini` itself. +- **Vale requires a StyleName directory level** (`StylesPath/