docs: align destroy references with #2493 type-scoped contract#2514
docs: align destroy references with #2493 type-scoped contract#2514
Conversation
PR #2513 narrowed `wheels destroy <Name> controller` so it deletes only the controller .cfc and its spec — views are left in place. The cascade case lives on the resource form (`wheels destroy <Name>` with no type). Three doc surfaces still described the old behaviour or carried stale filenames: - tutorial/03-crud-scaffold.mdx: "Drop the hand-written controller and views" used to be one command. Now needs two (`destroy controller` + `destroy view`) so the tutorial's stated intent — drop controller AND views, keep model + migration + route — works under the new contract. Explanatory line added so readers understand why the split exists. - command-line-tools/wheels-commands/scaffold-cleanup.mdx: the "destroy is destructive" caution said "destroy removes whole view directories by default" — true only for the resource form and `destroy view`, not `destroy controller`. Rewrote that bullet to call out the boundary explicitly. Also fixed the example output to reference the actual generated spec filename (`PostsControllerSpec.cfc`, not `PostsSpec.cfc`) — a stale reference left over from before #2502. - command-line-tools/mcp-integration.mdx: the `wheels_destroy` tool description was generic. Made it crisper so AI agents understand the cascade-vs-scoped split before they call the tool. The Types table on scaffold-cleanup.mdx (line 48) was already correct — it described `controller` as removing only the CFC + spec even when the implementation cascaded views. The behaviour now matches the doc.
| |---|---| | ||
| | `wheels_generate` | Scaffold a model, controller, view, migration, scaffold, route, test, property, or helper. | | ||
| | `wheels_destroy` | Remove a previously generated component and its associated files. | | ||
| | `wheels_destroy` | Remove a previously generated component. The default `resource` type cascades (model + controller + views + tests + route + drop-table migration); `model`, `controller`, and `view` are scoped to that artefact only. | |
There was a problem hiding this comment.
🟡 The new wheels_destroy description groups model with controller and view as 'scoped to that artefact only', but destroyModel in cli/lucli/services/Destroy.cfc also writes a drop-table migration (line 97). This contradicts the same PR's scaffold-cleanup.mdx, which states 'destroy model and destroy resource generate a drop-table migration'. Consider rewording so AI agents see that type=model has the same migration side effect as the resource form.
Extended reasoning...
Bug: MCP wheels_destroy description omits drop-table migration for type=model
The new tool description added in this PR reads:
The default
resourcetype cascades (model + controller + views + tests + route + drop-table migration);model,controller, andvieware scoped to that artefact only.
This groups model with controller and view as if all three are pure-deletion operations. That's accurate for controller and view, but not for model.
Why the wording is wrong
cli/lucli/services/Destroy.cfc lines 82–100 (destroyModel) deletes the model CFC and its spec and calls generateRemoveTableMigration(lCase(variables.helpers.pluralize(clean))) on line 97. destroyController and destroyView do not generate any migration. So model shares the migration side effect with the resource form, not the artefact-only behaviour of controller/view.
The PR is internally inconsistent on this point. The companion scaffold-cleanup.mdx (also touched here) says explicitly:
destroy modelanddestroy resourcegenerate a drop-table migration but do not execute it.
…and its Types table lists the model row as removing 'Model CFC, model spec, plus a new drop-table migration file'. The MCP description directly contradicts both of those.
Why this matters for the stated audience
The PR description says the rewording is 'so AI agents understand the cascade-vs-scoped split before they call the tool'. An agent reading only the MCP tools/list output (the typical case — agents do not browse scaffold-cleanup.mdx) would conclude that wheels_destroy(name="Foo", type="model") is a pure-deletion operation. In reality, that call leaves a <timestamp>_remove_foos_table.cfc file in app/migrator/migrations/ that drops the table on the next wheels migrate latest — a notable filesystem and future-schema side effect.
Step-by-step proof
- Agent calls
wheels_destroy(name="Posts", type="model"). Module.cfcdispatches toDestroy.cfc::destroyModel.destroyModeldeletesapp/models/Posts.cfcandtests/specs/models/PostsSpec.cfc(lines 87–94).- Then it calls
generateRemoveTableMigration("posts")at line 97, writing a new<ts>_remove_posts_table.cfcintoapp/migrator/migrations/. - The MCP description told the agent this type was 'scoped to that artefact only' — so the agent does not know the migration file exists, and a later
wheels migrate latestwill drop the table.
Suggested fix
Move 'drop-table migration' out of the resource clause, e.g.:
The default
resourcetype cascades (model + controller + views + tests + route);modelremoves the model CFC and spec;controllerandvieware scoped to that artefact only. Bothresourceandmodelalso write a drop-table migration that you must run manually.
Severity is nit — the table is otherwise accurate, the synopsis and Types table elsewhere are correct, and an agent that follows the link to scaffold-cleanup.mdx would learn the truth. But since the PR's stated intent is to make this exact description AI-agent-friendly, the omission is on-topic for review.
Summary
Doc follow-up to PR #2513, which narrowed
wheels destroy <Name> controllerto delete only the controller.cfc+ spec (no longer cascading views). Three doc surfaces still described the old behaviour or carried stale filenames — this PR aligns them.Changes
start-here/tutorial/03-crud-scaffold.mdxChapter 3 says "Drop the hand-written controller and views. The model, migration, seed file, and the
resources("posts")route stay." Under the old contract that was a singlewheels destroy Posts controller --force. Under the new contract that command leaves the views directory alone.The tutorial's stated intent (drop controller AND views, keep everything else) needs two commands now:
The resource form (
wheels destroy Posts) would also work but it'd drop the model, migration, and route — which the chapter explicitly wants to keep. Added an explanatory sentence so readers understand why the split exists.command-line-tools/wheels-commands/scaffold-cleanup.mdxTwo fixes:
destroy removes whole view directories by default— true for the resource form anddestroy view, NOT fordestroy controller. Rewrote that bullet to call out the boundary explicitly.tests/specs/controllers/PostsSpec.cfc— stale name from before fix(cli): wheels destroy looks for ControllerSpec, not Spec #2502 fixed the destroy filename. Corrected toPostsControllerSpec.cfc.The Types table on line 48 was already accurate (described
controlleras removing only the CFC + spec). The behaviour now matches.command-line-tools/mcp-integration.mdxThe
wheels_destroytool description was a generic one-liner. Made it crisper so AI agents understand the cascade-vs-scoped split before they call the tool.Out of scope
command-line-tools/index.mdxline 91 ("undo a generator cleanly") — generic enough to leave alone.command-line-tools/wheels-commands/code-quality.mdxline 176 — generic related-link description.digging-deeper/caching.mdxline 229 — refers to the HTTPdestroyREST verb, not the CLI command. Untouched.v3-0-0/...) — frozen historical version, do not touch.Test plan
tutorial/03-crud-scaffold.mdx— the two-command block appears with the explanatory paragraph.scaffold-cleanup.mdx— caution bullet calls out the controller-vs-resource boundary; example output referencesPostsControllerSpec.cfc.mcp-integration.mdx—wheels_destroyrow reads correctly in the table.wheels generate scaffold Postsucceeds after the two destroy commands run.Generated by Claude Code