Skip to content

docs(web/guides): correct migrations and seeding guides to verified 4.0.x behavior - #3094

Merged
bpamiri merged 1 commit into
developfrom
peter/docs-audit2-migrations-seeding
Jun 12, 2026
Merged

docs(web/guides): correct migrations and seeding guides to verified 4.0.x behavior#3094
bpamiri merged 1 commit into
developfrom
peter/docs-audit2-migrations-seeding

Conversation

@bpamiri

@bpamiri bpamiri commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Guide-behavioral-audit batch 2, work item p1-14-migrations. Fixes the docs-affected findings in basics/migrations.mdx and basics/seeding.mdx. Every correction documents verified current behavior (CLI 4.0.3 + develop source) and cites the tracking issue where the underlying behavior is broken-but-unfixed.

Corrections

basics/migrations.mdx

  1. migrate info / migrate doctor port fallback (claim mig-08, both) — the aside claimed read-only commands "still probe common ports as a fallback". Verified false on 4.0.3 and develop: both route through requireProjectConfig=true (Module.cfc:3796-3804) and refuse with Wheels.ServerNotRunning even when the server runs on 8080. Rewritten to current behavior, citing #3080.
  2. Exit codes (evidence from mig-09/mig-28, group note) — added a one-sentence caution that a failed migration currently still exits 0, so pipelines should not gate on $? alone (#3081).
  3. Generator filename (claim mig-11, docs-wrong) — wheels generate migration CreatePosts produces <ts>_CreatePosts.cfc verbatim (Module.cfc:3094), never snake_cased or _table-suffixed; timestamp is the local clock, not "UTC-ish". Fixed the example and the Filename format section, with a contrast note that the snake_case shape comes from the model generator (wheels g model Post<ts>_create_posts_table.cfc).
  4. limit=8 → BIGINT row (claim mig-17, docs-wrong) — no such mapping exists anywhere (MySQL integer→INT; Abstract.typeToSQL appends (limit) as a display width). Row now points at t.bigInteger().
  5. columnName alias (sketch item 4) — softened "not columnName and null": singular columnName IS accepted via $combineArguments on every helper; null remains never-accepted (allowNull).
  6. Seed-data SQL (claims mig-26/mig-27, docs-wrong) — the guide's own NOW() example fails on SQLite (no such function: NOW), the default wheels new database, and SQL Server has no native NOW(); no adapter rewrites it. Example and prose now use CURRENT_TIMESTAMP (works on MySQL/PG/MSSQL/H2/SQLite). "Parameter binding in execute() is unreliable" corrected to the real contract: execute(required string sql) has no parameters argument at all (Migration.cfc:460).

basics/seeding.mdx

  1. wheels generate seed bullets (claims seed-08/seed-09, docs-wrong) — both bullets removed: the command errors with Unknown generator type: seed on 4.0.3 and develop (no seed case in the generate() switch), and no --all variant exists. Replaced with the verified scaffold path wheels generate snippets seed-data plus an explicit "no such command" note.
  2. wheels seed --generate (claim seed-10, code-broken) — paragraph rewritten: the flag is currently non-functional (every model errors, zero rows created, success still reported), citing #3082.
  3. seedOnce third outcome (sketch item 8, evidence seed-11) — documented the validation-failure path: entry recorded as failed and the run rolls back; as of 4.0.4 with success=false and a non-zero exit (fix(seed): fail and roll back when seedOnce entries fail validation #2987), while 4.0.3 rolled back silently and still reported created counts.

Verification

  • pnpm verify:docs src/content/docs/v4-0-0/basics/migrations.mdx src/content/docs/v4-0-0/basics/seeding.mdx → 13 tagged blocks, 13 passed, exit 0
  • Evidence source: guide-behavioral-audit raw output for p1-14-migrations (wheels CLI 4.0.3 + Lucee 7 + SQLite; develop@ddeec99bf source reads)

Note: repo CLAUDE.md anti-pattern #5 repeats the NOW()/binding errors; the worktree's CLAUDE.md was already updated on develop for the generate-seed/snippets facts, and the CLAUDE.md NOW() fix is left to the campaign's collateral sweep (out of this PR's scoped files).

🤖 Generated with Claude Code

….0.x behavior

Audit batch 2 (p1-14-migrations) corrections, all behavior-verified on
CLI 4.0.3 + develop source:

- migrate info/doctor have no common-port fallback — they require the
  project-bound port config like the write commands (#3080)
- failed migrations currently exit 0; warn against gating CI on $? (#3081)
- generator filename is <ts>_<NameAsTyped>.cfc verbatim from the local
  clock — the snake_case _table shape belongs to the model generator
- columnName (singular) is an accepted alias; null is never accepted
- remove the nonexistent 'limit=8 maps to BIGINT on MySQL' mapping;
  point at t.bigInteger()
- NOW() fails on SQLite (default DB) and SQL Server; the portable
  spelling is CURRENT_TIMESTAMP; execute() has no parameters argument
- replace nonexistent 'wheels generate seed [--all]' with
  'wheels generate snippets seed-data'
- mark 'wheels seed --generate' as non-functional (#3082)
- document the seedOnce validation-failure outcome (rollback +
  non-zero exit as of 4.0.4; silent on 4.0.3)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Peter Amiri <peter@alurium.com>

@wheels-bot wheels-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wheels Bot — Reviewer

TL;DR: This PR corrects the migrations and seeding guides to match verified 4.0.x behavior — port-fallback semantics for migrate info/doctor, exit-code caveat, generator filename shape, the limit→BIGINT myth, the columnName alias, NOW() vs CURRENT_TIMESTAMP portability, the nonexistent wheels generate seed command, the broken --generate flag, and the seedOnce validation-failure path. I independently verified every factual claim against the source on this branch; all nine check out, the three new tracking issues exist with matching titles, and the commit is commitlint-clean. Verdict: approve.

Correctness

Each correction verified against the code, not just the PR's citations:

  1. migrate info/doctor port bindingrunMigration() in cli/lucli/Module.cfc routes all actions (including info/doctor) through $requireRunningServer(requireProjectConfig = true); there is no read-side common-port fallback. #3080 is open and matches ("migrate info/doctor refuse the common-port fallback…"). The old aside was wrong; the new text is right.
  2. Exit-code caveat#3081 is open and matches ("migrate latest/up/down exit 0 on a failed migration"). One-sentence caution is appropriately scoped.
  3. Generator filenamegenerateMigration() builds "#timestamp#_#migrationName#.cfc" with the name verbatim (no snake_casing, no _table suffix), and Helpers.cfc:141 generateMigrationTimestamp() uses now() — local clock, confirming the "UTC-ish" removal. The contrast note is also right: the snake_case shape comes from the model/scaffold path (cli/lucli/services/Scaffold.cfc:287, className = "create_#tableName#_table").
  4. limit=8 → BIGINT row — no such mapping exists. vendor/wheels/databaseAdapters/MySQL/ maps integerINT, and Abstract.cfc::typeToSQL() appends (#options.limit#) to the type name. Pointing readers at t.bigInteger() is correct.
  5. columnName singular aliasTableDefinition.cfc:134 ($addTypedColumns) runs $combineArguments(combine = "columnNames,columnName", required = true) for every typed column helper, exactly as the new prose says; allowNull is the only nullable flag (vendor/wheels/migrator/CLAUDE.md documents both).
  6. execute() / NOW()Migration.cfc:460 is public void function execute(required string sql) — no parameters argument, so "parameter binding is unreliable" was indeed the wrong framing. No adapter rewrites NOW() (grep finds it only in two reference-doc examples), SQLite has no NOW() function, and T-SQL has no native NOW()CURRENT_TIMESTAMP is the portable ANSI form across all five engines named. The {test:compile} tag on the example block is preserved.
  7. wheels generate seed — confirmed nonexistent: the generate() switch in Module.cfc has no seed case and throws Wheels.InvalidArguments with exactly Unknown generator type: seed (Module.cfc:578–581). The replacement path is accurate: the seed-data snippets generator writes app/snippets/seeds.cfm and app/snippets/seeds-development.cfm (Module.cfc:3661–3673).
  8. wheels seed --generate#3082 is open and its title matches the new prose verbatim ("non-functional — every model errors, zero rows created, reports success").
  9. seedOnce third outcomevendor/wheels/Seeder.cfc:90–102 rolls back and returns success = false when totalFailed > 0, matching the documented 4.0.4 behavior; the comment at Seeder.cfc:39 corroborates that commit-with-report was the prior (silent) behavior.

Docs

  • Non-blocking, already disclosed in the PR body: root CLAUDE.md anti-pattern #5 still tells contributors to "use NOW() for database-agnostic dates (MySQL/PG/MSSQL/H2/SQLite)" and that "parameter binding in execute() is unreliable" — both now contradicted by this guide (and by Migration.cfc:460). Deferring to the campaign's collateral sweep is reasonable, but until it lands the repo's own instructions steer agents toward seed SQL that fails on the default wheels new database. Worth landing that sweep promptly.
  • Changelog fragment correctly omitted — docs-type guide correction, not a user-facing fix/feat.

Commits

  • Single commit docs(web/guides): correct migrations and seeding guides to verified 4.0.x behavior — valid type, free-form scope, subject under 100 chars, not ALL-CAPS. Clean.

@bpamiri
bpamiri merged commit 70eb85c into develop Jun 12, 2026
14 checks passed
@bpamiri
bpamiri deleted the peter/docs-audit2-migrations-seeding branch June 12, 2026 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant