feat(skill): Engage routing when a linter is named - #27
Merged
Conversation
Reverse the named-tool suppression: naming a linter (eslint, ruff, biome, ast-grep) now ENGAGES the skill's routing flow via `taskless help route` instead of quieting it. Replace the "Quiet suggestion" section with a route-through-route body that forbids fetching `rule create` directly and adds no linter knowledge, and relax the install gate so the `existing` path (which only reads the repo) is not blocked when `.taskless/` is absent. Description measures 835/1024 chars. Skill version is build-locked to the package version, so a minor changeset drives the bump rather than a hand-edited mismatch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a labeled request→route calibration dataset for the route recipe covering both failure directions: over-claim (Taskless grabbing a packaged/formatter job that should stay `existing`) and over-escalate (a locally-solvable request wrongly sent to the login-gated service that should stay `static`), plus genuine `remote` cases. The route decision is agent-made by following help/route.txt, so the coverage test guards the dataset's balance across routes and traps rather than running a code classifier. Closes out the change: openspec validate passes, full CLI suite green, detect + routing recipes smoke-tested end-to-end. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the consolidated taskless agent skill to treat “named linter” rule-authoring requests as an explicit entry into Taskless’s new local-first routing flow (route → existing/static/remote), removing the previous suppression/quiet-offer behavior.
Changes:
- Update
skills/taskless/SKILL.mdtrigger + body so rule-authoring always starts atnpx @taskless/cli help route, even when a specific linter is named; remove the “Quiet suggestion” suppression path. - Relax the install gate so
route/existing(repo-reading paths) are not blocked by the absence of.taskless/, while still offering install when routing lands onstatic/remote. - Add a changeset intended to drive a minor version bump for this behavior change.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| skills/taskless/SKILL.md | Switch rule-authoring posture to always route via help route (including named linters) and remove suppression path. |
| openspec/changes/local-rule-routing/tasks.md | Mark the skill-posture tasks complete and note the intended release/versioning approach. |
| .changeset/local-rule-routing.md | Add a minor changeset describing the local-first routing layer and updated skill behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
* feat/local-rule-help: docs(cli): Align route recipe with the three-state contract docs(cli): Show detect output shape in the route recipe docs(openspec): Clarify detect output schema is internal, not published docs(openspec): Address review feedback on local-rule-routing contract
* feat/local-rule-skill: docs(cli): Align route recipe with the three-state contract docs(cli): Show detect output shape in the route recipe docs(openspec): Clarify detect output schema is internal, not published docs(openspec): Address review feedback on local-rule-routing contract
PR #27 review: - The changeset targeted the private, unpublished root `@taskless/skills` package, which produces no release and is overwritten by sync-skill-versions. Target `@taskless/cli` — the published package and the version source of truth that skill metadata.version is locked to. - Add `stylelint` to the skill body's example tool list so it matches the description's list. - Update the tasks.md 4.3 note to describe the real release mechanism (@taskless/cli version drives the skill version via sync-skill-versions). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat/local-rule-help: docs(cli): Address review on routing recipes fix(cli): Harden detect against malformed manifests and false positives
* feat/local-rule-skill: fix(skill): Target @taskless/cli in the changeset; align tool lists docs(cli): Address review on routing recipes fix(cli): Harden detect against malformed manifests and false positives
PR #28 review: - The trap-coverage test asserted the traps were declared but never verified each trap has at least one case, so the dataset could silently stop covering a failure direction (e.g. under-engage) while the test stayed green. Now every declared trap must have >= 1 case, and under-engage cases are asserted to route to `existing`. - Fix the tasks.md note to point at the real fixture/test paths under packages/cli/test/. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
All 25 tasks are complete, so finalize the change on the tip of the stack: apply the delta specs into the main specs (new cli-detect and cli-rule-routing capabilities; cli-help and skill-taskless updates) and move the change to openspec/changes/archive/2026-06-12-local-rule-routing/. With no unarchived change remaining, the PR OpenSpec Archive Check passes for the final merged state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 12, 2026
* feat/local-rule-help: ci(openspec): Skip the archive check on non-tip stacked PRs (#31) docs(openspec): Clarify detect output schema is internal, not published docs(openspec): Address review feedback on local-rule-routing contract docs(openspec): Propose local-rule-routing change chore(skill): Refine the stacked-PR archive-check guidance chore(skill): Scope iterate-pr archive check to the stack tip chore(config): Allow git-town in project settings
* feat/local-rule-skill: ci(openspec): Skip the archive check on non-tip stacked PRs (#31) docs(openspec): Clarify detect output schema is internal, not published docs(openspec): Address review feedback on local-rule-routing contract docs(openspec): Propose local-rule-routing change chore(skill): Refine the stacked-PR archive-check guidance chore(skill): Scope iterate-pr archive check to the stack tip chore(config): Allow git-town in project settings
* feat/local-rule-help: feat(cli): Make detect monorepo-aware; languages → linters; drop frameworks
* feat/local-rule-skill: feat(cli): Make detect monorepo-aware; languages → linters; drop frameworks
- Mirror the detect contract changes into the synced cli-detect capability spec: drop frameworks, add the languages-only / per-language-manifest / monorepo scenarios. - Add a README testing section clarifying the two kinds of test: the local vitest suite (deterministic, no agent) versus the route-honesty dataset, whose automated test only guards the fixture structure while the actual agent evaluation is a separate manual calibration step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat/local-rule-help: docs(cli): Update route recipe detect example for the new shape
* feat/local-rule-skill: docs(cli): Update route recipe detect example for the new shape
* feat/local-rule-help: feat(cli): Add linters for already-detected Go, Rust, and PHP
* feat/local-rule-skill: feat(cli): Add linters for already-detected Go, Rust, and PHP
When the restructure-cli-telemetry change lands, detect/help must conform to the cli_run + cli_help taxonomy. Mark both sites with a shared TODO(telemetry-taxonomy) tag: drop the silent cli_detect capture in detect.ts (the easy-to-miss half) and convert the help_<topic> assertions (which fail on rebase, so they self-surface). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reference the tracking issue (#39) from both reconciliation anchors so the context lives next to the code. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat/local-rule-help: (21 commits)
refactor(cli): Uppercase the acronym in CLIConfig
refactor(cli): Uppercase the acronym in CLIErrorEnvelope too
fix(cli): Carry the CLIErrorCode rename into auth.ts
docs(openspec): Uppercase CLIError/CLIErrorCode in the change contract
docs(openspec): Uppercase CLIError/CLIErrorCode in the analytics spec
refactor(cli): Uppercase the CLI acronym in CliError/CliErrorCode
docs(openspec): Sync corrected check/help spec into the archived capability
fix(cli): Resolve cli_run identity at invocation start, not end
test(cli): Prove help_* removal once via a source scan, not per-test
test(cli): Assert no legacy help_* event on served-topic and index paths
refactor(cli): Single-pass check counts; robust cli_installed assertion
fix(cli): Only emit cli_rule_created/improved when rules are written
fix(cli): Resolve cli_run identity fresh; tighten cli_error + drop cli_version
docs(openspec): Address review on the telemetry contract
ci(openspec): Skip the archive check on non-tip stacked PRs
chore(openspec): Archive restructure-cli-telemetry and sync specs
feat(cli): Collapse help_* into cli_help { topic }; drop cli_info
feat(cli): Concrete auth + lifecycle events; drop start/_completed pairs
feat(cli): Emit concrete rule events; drop rule start/_completed pairs
feat(cli): Emit cli_run once per invocation from the runner
...
* feat/local-rule-skill: (21 commits)
refactor(cli): Uppercase the acronym in CLIConfig
refactor(cli): Uppercase the acronym in CLIErrorEnvelope too
fix(cli): Carry the CLIErrorCode rename into auth.ts
docs(openspec): Uppercase CLIError/CLIErrorCode in the change contract
docs(openspec): Uppercase CLIError/CLIErrorCode in the analytics spec
refactor(cli): Uppercase the CLI acronym in CliError/CliErrorCode
docs(openspec): Sync corrected check/help spec into the archived capability
fix(cli): Resolve cli_run identity at invocation start, not end
test(cli): Prove help_* removal once via a source scan, not per-test
test(cli): Assert no legacy help_* event on served-topic and index paths
refactor(cli): Single-pass check counts; robust cli_installed assertion
fix(cli): Only emit cli_rule_created/improved when rules are written
fix(cli): Resolve cli_run identity fresh; tighten cli_error + drop cli_version
docs(openspec): Address review on the telemetry contract
ci(openspec): Skip the archive check on non-tip stacked PRs
chore(openspec): Archive restructure-cli-telemetry and sync specs
feat(cli): Collapse help_* into cli_help { topic }; drop cli_info
feat(cli): Concrete auth + lifecycle events; drop start/_completed pairs
feat(cli): Emit concrete rule events; drop rule start/_completed pairs
feat(cli): Emit cli_run once per invocation from the runner
...
The telemetry restructure has landed on main, so the detect stack now adopts
the new event taxonomy:
- detect.ts: drop the bespoke cli_detect capture. detect is read-only, so the
per-invocation cli_run denominator (from the runner) covers it. Removes the
now-unused getTelemetry import.
- help-routing-telemetry.test.ts: the per-topic help_<topic> events collapsed
into cli_help { topic }; assert cli_help for the routing topics.
Clears both TODO(#39) anchors. Closes #39.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat/local-rule-help: test(cli): Assert cli_help for routing topics (telemetry taxonomy) chore(cli): Drop cli_detect on the detect branch (telemetry taxonomy)
* feat/local-rule-skill: test(cli): Assert cli_help for routing topics (telemetry taxonomy) chore(cli): Drop cli_detect on the detect branch (telemetry taxonomy)
test(cli): Add route honesty eval fixtures and finalize change
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Flip the skill's posture toward the routing layer. Previously, naming a linter (eslint, ruff, biome, ast-grep) suppressed the skill to a one-line offer. Now it ENGAGES the routing flow via
taskless help route, because Taskless can help author the rule in that tool's own dialect.Changes to
skills/taskless/SKILL.md:taskless help route(the body forbids fetchingrule createdirectly and adds no linter knowledge — the skill stays a thin router).existingpath (which only reads the repo) isn't blocked when.taskless/is absent;static/remotestill offer install.The skill
metadata.versionis build-locked equal to the package version (enforced byassertSkillVersions), so this ships aminorchangeset to drive the bump in lockstep rather than hand-editing a mismatch.Stacked on #26. The validation/eval/smoke pass lands last.
Refs TSKL Runtime Rules
Stack generated by Git Town