Repository navigation
fix(onboard): refuse a behind .taskless/ in onboard and report instead of migrating - #630
Conversation
|
@claude /review |
|
Claude finished @theCodeDrift's task in 2m 17s —— View job Review: fix(onboard): refuse a behind
|
Thanks. No changes needed. — AI Coding Agent |
…d of migrating onboard and report ran ensureTasklessDirectory in every mode, so fetching the onboarding recipe or drafting a report migrated .taskless/, and 0005 moves and deletes tracked files. Both now call requireCurrentSchema first, like check and verify, and still scaffold a .taskless/ that is absent.
9bec323 to
7926b60
Compare
Stack (root → tip):
taskless onboardandtaskless reportmigrated.taskless/as a side effect, in every mode. Migration0005moves and deletes tracked files, so an agent that fetched the onboarding recipe, or drafted a report, rewrote the repository of any project whose scaffold was behind the CLI.check,validateandverifyalready refuse in that case, andinitis meant to be the only command that migrates.What changed
commands/onboard.ts: callsrequireCurrentSchemabeforeensureTasklessDirectory, in every mode (recipe,--force,--mark-complete). A behind scaffold exits 1 withError (SCAFFOLD_MIGRATION_REQUIRED): …naminginit; an ahead one withSCAFFOLD_VERSION_MISMATCH. The code is printed in prose becauseonboardhas no--jsonenvelope, the same formreportalready uses.commands/report.ts: the same check, in all three modes (draft,--from,--delete), routed through the command's existingguarded/failpath, so--jsongets the{ ok: false, code, message }envelope and prose getsError (CODE): ….ensureTasklessDirectoryafterwards, so a project with no.taskless/is scaffolded as before. That call can no longer migrate, because the refusal already ran.reportkeeps its--json-suppressingonNotice.onboardhas no JSON mode, so it keeps the default notice.cli-onboardandcli-reportboth required bootstrapping.taskless/. The change restates each requirement in full with the refusal and two new scenarios, and is archived in this PR (single-PR delivery). Scenario counts before and after archive: 42→44 and 53→55.patch.Testing
test/no-implicit-migration.test.ts: on a version-3 scaffold, every mode ofonboardandreportexits 1 withSCAFFOLD_MIGRATION_REQUIREDon stderr, prints nothing on stdout, and leaves the tree unchanged (manifest still version 3, flat rule not moved, norules/sg/).report --jsonreturns the envelope. Both commands refuse a version-99 scaffold. With no.taskless/at all,onboardscaffolds to the latest version andreport --jsondrafts with no migration prose on stderr.test/onboard.test.ts: the fixtures seededversion: 2and relied on onboard migrating them. They now seedLATEST_SCHEMA_VERSION.pnpm typecheck,pnpm lint, andpnpm --filter @taskless/cli test(2977 passed) all pass locally.Audit of the other
ensureTasklessDirectorycallersrules/verify.ts:521(verifyRule) is only reached throughrules/inspect.ts, whose callers arecommands/verify.ts(validate/verify) andreport/draft.ts(reportdraft and--from). All three now refuse a behind or ahead scaffold before getting there. On a current scaffold the call is a no-op, and on an absent one the command has already scaffolded it. No other caller exists, so it cannot migrate.rules/files.ts:80(writeServedRule) is reached byrule create/rule improve(rules/generate.ts) andrule restore/rule rollback(rules/recover.ts).commands/rules.tsnever callsrequireCurrentSchema, so on a behind scaffold these commands still migrate, after the service call, with migration notices going to stderr even under--json. That breaks the "onlyinitmigrates" rule. These are writing commands, and the migration produces the layout the served rule is written into, so the output is correct, but the user did not ask for the rewrite of unrelated tracked files. My conclusion is that they should refuse, and the natural place to decide that is Make the .taskless/ schema state and each command's migrate/refuse policy explicit #626, which assigns every command an explicit schema policy. I left it out of this PR to keep onboard and report run .taskless/ migrations, which move and delete tracked files #621 scoped, and because Multi-rule generation writes earlier rules before a later one is rejected #623 is changingwriteServedRule.Fixes #621