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
Add an agent update instruction set: a recipe that tells an agent what changed in a Taskless upgrade and what to do about the rules already in the project.
Today an engine upgrade is silent from the rule author's side. The vendored ast-grep or Vale version moves, the schema regenerates, and an existing rule either keeps working, starts failing verify, or quietly matches a different set of nodes. Nothing tells the agent which of the three happened, or what the new layout expects.
Why now
The 0.41.0 to 0.45.2 ast-grep upgrade (#162) is the first one with a real migration surface, and it is a good small case to build against:
A tightened requirement.fix is now required on a rewriter (SerializableRewriter.required moves from ["rule","id"] to ["id","fix","rule"]). A rewriter without one was accepted before and is rejected now. It could never have worked, so this surfaces a latent bug rather than breaking behavior, but the author still has to act.
New capabilities.Markdown and Dart become available languages, and Markdown in particular comes with sharp limits (block grammar only, no inline nodes, no counts or absence) that an author will get wrong without guidance.
Changed matching semantics. Metavariable binding no longer leaks across nthChild siblings or out of a negated not, and root metavariables now match comments. A valid, unchanged rule can match a different set of nodes with no error.
The third class is the one an author cannot discover on their own.
What the recipe should do
taskless agent update (name to be decided) should answer, for the version being moved to:
What changed in the engines, in rule-author terms rather than changelog terms.
What in this project is affected. Concretely: scan .taskless/rules/ and name the rules touched by each change, rather than describing the change abstractly and leaving the author to grep.
What to do about each, split by whether it is mechanical or authorial. A rewriter missing fix cannot be auto-fixed, because fix is replacement text and therefore intent; the recipe should surface the rule and help the author write it, not silently transform it.
What is newly possible. New languages and new constructs, with the caveats attached, so an upgrade is also an opportunity rather than only a chore.
What cannot be checked. Where matching semantics changed, say so plainly and name the affected constructs, so an author knows to re-run test against fixtures rather than assuming silence means safety.
Notes
Pre-1.0, some sloppiness across upgrades is acceptable. The goal is not a guaranteed-safe migration, it is that the author is told what happened and is not left to discover it from a rule that stopped firing.
This is the agent-facing counterpart to the changeset. The changeset says what changed in the release; this says what it means for the rules in front of you.
The recipe is not discoverable unless the root skill routes to it. skills/taskless/SKILL.md carries a Topics table mapping an intent to npx @taskless/cli agent <topic>, and this needs a row alongside the existing ones (route, onboard, improve-rule, delete-rule, check, auth, ci).
The row should say what the recipe is for, in the terms an agent will be thinking in: determining whether rule rewriting is necessary beyond what the standard Taskless migration already does.
That distinction is the point of the skill, and it needs stating plainly in both the root skill and the recipe itself:
The standard migration rewrites the layout. Running check or verify migrates the .taskless/ directory structure in place. It is automatic and an agent does not have to reason about it. Its invisibility to the machine interface is The .taskless/ migration is invisible to the machine interface #178.
This recipe covers what migration cannot touch: the content of the rules. A rewriter that now requires fix, a rule whose matching semantics shifted under a new engine version, a rule that could now be expressed better with a newly supported language. None of that is a layout change, none of it is mechanical, and the standard migration will never do it.
An agent that has run a migration and seen it succeed will otherwise reasonably conclude the upgrade is complete. The root skill entry exists to say: the directory is migrated, the rules may still need work, and here is how to find out.
Naming: agent update is already taken
packages/cli/src/agent/update.txt exists and means something else: refreshing the installed Taskless skills in the user's coding-agent tools to the bundled version, via taskless update. That is a tooling refresh with no view of rules at all.
Two jobs now collide on the word "update":
topic
meaning
existing agent update
refresh installed skills to the bundled version
this recipe
decide whether rules need rewriting after an engine or CLI upgrade
Pick a distinct topic name (agent migrate-rules, agent upgrade-rules, or similar) rather than overloading update, and cross-reference the two so an agent that lands on the wrong one is redirected. Whatever it is called, the root skill table needs to make the difference obvious at a glance, since an agent choosing from that table has only one line to go on.
Decided: reclaim the update name
The existing agent update topic is going away. Refreshing installed skills is the CLI's job (taskless update), not a recipe's, so a skill topic explaining it earns nothing. packages/cli/src/agent/update.txt should be removed or reduced, and update becomes this recipe. The naming collision noted above resolves itself; no migrate-rules alias is needed.
Structure: a sequential ledger, one section per version
The recipe is a list of sections, in release order:
## Migrating to 0.11.0
<what an agent must do about existing rules>
## Migrating to 0.12.0
No agent work for this version.
An agent starts at the project's last reconciled version and walks forward to the installed one, doing what each section says.
Two properties matter:
Every released version gets a section, including the empty ones. A version with nothing to do says so explicitly. Silence is ambiguous: an agent cannot tell "nothing to do here" from "nobody wrote this section", and the whole point of the recipe is to remove that ambiguity. An explicit no-op is a claim; a missing section is an unknown.
Sections are cumulative, not replaceable. An agent three versions behind must get all three, in order, because a later migration can depend on an earlier one having run.
Correction: install.cliVersion is maintained, and this section previously said it was not
An earlier version of this section claimed, as a measurement, that this repository's taskless.json reads 0.6.0 while running 0.11.0, and concluded that nothing advances the field. That reading was taken from a git worktree checked out at origin/main, not from the working branch, and the conclusion drawn from it was wrong.
Measured properly:
ref
version
install.cliVersion
origin/main
2
0.6.0
the onboarding branch (210ac00)
5
0.11.0-20260824213902xf26a7b0
The directory-structure handling does what it should: it migrated the config version and wrote the current CLI version. main lags only because the onboarding commits are on a branch that has not landed there.
The real question about a start marker
install.cliVersion is maintained, so it is a candidate. What it is not is a statement about rules.
It records the version that last migrated the layout. A layout migration bumps it without any agent having read a single rule, so a project can carry a current cliVersion and still have rules that nobody reconciled against the engine changes in that release. Keying the ledger off it would mean an agent skips migrations it never performed, which fails in the quiet direction: the walk reports nothing to do and the rules stay wrong.
So the decision is whether the ledger:
Reuses install.cliVersion, accepting that a layout migration silently marks rule work as done. Cheapest, and wrong whenever the two diverge.
Adds a separate marker meaning "rule content reconciled up to X", advanced only when the agent completes a walk. Correct, and it raises the questions below.
If a separate marker:
Where it lives. taskless.json is the obvious home, though it currently describes installation rather than rule state.
Who advances it. A partial or abandoned walk must not record completion, so the agent claiming success is not sufficient on its own.
A fresh project with no marker. Probably record the current version and do nothing, since a project created at 0.11.0 has no history to migrate, but it should be stated rather than inferred.
A marker ahead of the installed CLI, which is the downgrade case.
Summary
Add an
agent updateinstruction set: a recipe that tells an agent what changed in a Taskless upgrade and what to do about the rules already in the project.Today an engine upgrade is silent from the rule author's side. The vendored ast-grep or Vale version moves, the schema regenerates, and an existing rule either keeps working, starts failing
verify, or quietly matches a different set of nodes. Nothing tells the agent which of the three happened, or what the new layout expects.Why now
The 0.41.0 to 0.45.2 ast-grep upgrade (#162) is the first one with a real migration surface, and it is a good small case to build against:
fixis now required on a rewriter (SerializableRewriter.requiredmoves from["rule","id"]to["id","fix","rule"]). A rewriter without one was accepted before and is rejected now. It could never have worked, so this surfaces a latent bug rather than breaking behavior, but the author still has to act.MarkdownandDartbecome available languages, and Markdown in particular comes with sharp limits (block grammar only, no inline nodes, no counts or absence) that an author will get wrong without guidance.nthChildsiblings or out of a negatednot, and root metavariables now match comments. A valid, unchanged rule can match a different set of nodes with no error.The third class is the one an author cannot discover on their own.
What the recipe should do
taskless agent update(name to be decided) should answer, for the version being moved to:.taskless/rules/and name the rules touched by each change, rather than describing the change abstractly and leaving the author to grep.fixcannot be auto-fixed, becausefixis replacement text and therefore intent; the recipe should surface the rule and help the author write it, not silently transform it.testagainst fixtures rather than assuming silence means safety.Notes
.taskless/migration being invisible to the machine interface. Same theme, different surface: this issue is about the rules, The .taskless/ migration is invisible to the machine interface #178 is about the directory layout.Refs #162
Refs #178
Refs TSKL-291
Registration in the root skill
The recipe is not discoverable unless the root skill routes to it.
skills/taskless/SKILL.mdcarries a Topics table mapping an intent tonpx @taskless/cli agent <topic>, and this needs a row alongside the existing ones (route,onboard,improve-rule,delete-rule,check,auth,ci).The row should say what the recipe is for, in the terms an agent will be thinking in: determining whether rule rewriting is necessary beyond what the standard Taskless migration already does.
That distinction is the point of the skill, and it needs stating plainly in both the root skill and the recipe itself:
checkorverifymigrates the.taskless/directory structure in place. It is automatic and an agent does not have to reason about it. Its invisibility to the machine interface is The .taskless/ migration is invisible to the machine interface #178.fix, a rule whose matching semantics shifted under a new engine version, a rule that could now be expressed better with a newly supported language. None of that is a layout change, none of it is mechanical, and the standard migration will never do it.An agent that has run a migration and seen it succeed will otherwise reasonably conclude the upgrade is complete. The root skill entry exists to say: the directory is migrated, the rules may still need work, and here is how to find out.
Naming:
agent updateis already takenpackages/cli/src/agent/update.txtexists and means something else: refreshing the installed Taskless skills in the user's coding-agent tools to the bundled version, viataskless update. That is a tooling refresh with no view of rules at all.Two jobs now collide on the word "update":
agent updatePick a distinct topic name (
agent migrate-rules,agent upgrade-rules, or similar) rather than overloadingupdate, and cross-reference the two so an agent that lands on the wrong one is redirected. Whatever it is called, the root skill table needs to make the difference obvious at a glance, since an agent choosing from that table has only one line to go on.Decided: reclaim the
updatenameThe existing
agent updatetopic is going away. Refreshing installed skills is the CLI's job (taskless update), not a recipe's, so a skill topic explaining it earns nothing.packages/cli/src/agent/update.txtshould be removed or reduced, andupdatebecomes this recipe. The naming collision noted above resolves itself; nomigrate-rulesalias is needed.Structure: a sequential ledger, one section per version
The recipe is a list of sections, in release order:
An agent starts at the project's last reconciled version and walks forward to the installed one, doing what each section says.
Two properties matter:
Correction:
install.cliVersionis maintained, and this section previously said it was notAn earlier version of this section claimed, as a measurement, that this repository's
taskless.jsonreads0.6.0while running 0.11.0, and concluded that nothing advances the field. That reading was taken from a git worktree checked out atorigin/main, not from the working branch, and the conclusion drawn from it was wrong.Measured properly:
versioninstall.cliVersionorigin/main0.6.0210ac00)0.11.0-20260824213902xf26a7b0The directory-structure handling does what it should: it migrated the config version and wrote the current CLI version.
mainlags only because the onboarding commits are on a branch that has not landed there.The real question about a start marker
install.cliVersionis maintained, so it is a candidate. What it is not is a statement about rules.It records the version that last migrated the layout. A layout migration bumps it without any agent having read a single rule, so a project can carry a current
cliVersionand still have rules that nobody reconciled against the engine changes in that release. Keying the ledger off it would mean an agent skips migrations it never performed, which fails in the quiet direction: the walk reports nothing to do and the rules stay wrong.So the decision is whether the ledger:
install.cliVersion, accepting that a layout migration silently marks rule work as done. Cheapest, and wrong whenever the two diverge.If a separate marker:
taskless.jsonis the obvious home, though it currently describes installation rather than rule state.