Repository navigation
Conversation
…grades LuCLI's bundled-default rewrite.config uses a narrow static-dir allow-list (images|css|js|fonts|assets|static) and negated RewriteCond chains. Tomcat's RewriteValve doesn't honour the negation, so every static asset under 3.x-conventional dirs like /miscellaneous/, /javascripts/, /stylesheets/, /files/ 404s on the first wheels start after a 3.x → 4.0 upgrade. wheels start now drops the working template from cli/lucli/templates/app/rewrite.config into the project root when one is missing. New apps already get this file via wheels new; this closes the upgrade-path gap. Existing project rewrite.config files are left untouched. Fixes #2626 Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
…n issues Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Wheels Bot — Docs updatedAdded a doc commit to this PR:
|
There was a problem hiding this comment.
Wheels Bot -- Reviewer A
TL;DR: This PR closes a real 3.x to 4.x upgrade regression (#2626): wheels start now provisions a project-level rewrite.config when one is missing, sidestepping LuCLI's buggy bundled default that 404s static assets under legacy directory names. The service design is solid and the idempotency contract is correct. However, the new test spec re-introduces a cross-engine anti-pattern that the project fixed in #2614 -- directoryCreate(path, true) crashes on Adobe ColdFusion -- and there is a secondary closure-scope issue that will silently produce undefined-variable errors on some engines. Verdict: changes needed in the test spec before merge.
Cross-engine
directoryCreate(projectRoot, true) -- five occurrences in the spec (lines 32, 54, 76, 111, 141)
// vendor/wheels/tests/specs/cli/RewriteConfigInstallerSpec.cfc:32
directoryCreate(projectRoot, true);This is the exact pattern that #2614 fixed across BrowserTest.cfc and McpServer.cfc. The regression spec at vendor/wheels/tests/specs/wheelstest/BrowserTestArtifactDirSpec.cfc opens with:
// Regression for #2614: Adobe CF rejects directoryCreate(path, true); routes through File.mkdirs() instead.
And every other recent call site in the codebase uses the Java form:
// vendor/wheels/wheelstest/BrowserTest.cfc:284-285
// Adobe CF rejects directoryCreate(path, true) -- see #2614. Use mkdirs() instead.
var created = createObject("java", "java.io.File").init(arguments.path).mkdirs();Because projectRoot is always a direct child of getTempDirectory() (parent guaranteed to exist), the simplest fix is to drop the second argument -- single-argument directoryCreate is valid on all engines:
directoryCreate(projectRoot);This affects all five it() blocks. Because the spec lives in vendor/wheels/tests/specs/ -- the directory the core test runner compiles in its entirety -- this will produce Adobe CF errors across every engine x database combination in the CI matrix.
Conventions
Outer-describe var accessed from inner it closures (lines 26-27, used throughout)
// vendor/wheels/tests/specs/cli/RewriteConfigInstallerSpec.cfc:26-27
var repoRoot = expandPath("/wheels/../..");
var templatePath = repoRoot & "/cli/lucli/templates/app/rewrite.config";var inside a closure writes to that closure's local scope. Per CLAUDE.md "Closure gotcha":
CFML closures can't access outer
localvars -- use shared structs
The inner it() callbacks (e.g. line 38: installer.install(..., sourceTemplate=templatePath)) reference templatePath from the outer describe() local scope. On Lucee 7 this works today because arrow-function closures capture the enclosing variable scope; on Adobe CF the lookup can fail with "variable TEMPLATEPATH is undefined". The established fix is a shared struct:
describe("cli.lucli.services.RewriteConfigInstaller", () => {
var ctx = {};
ctx.repoRoot = expandPath("/wheels/../..");
ctx.templatePath = ctx.repoRoot & "/cli/lucli/templates/app/rewrite.config";
it("writes...", () => {
var result = installer.install(projectRoot=projectRoot, sourceTemplate=ctx.templatePath);
});
});What is correct
- The service isolation (mirrors
BundleStager) is the right architecture for testability. - Idempotency is correctly gated on
fileExists(dest)-- re-runningwheels startleaves a user-customized file untouched. - The template covers all 3.x conventional static dirs (
stylesheets,javascripts,files,miscellaneous) and uses positive-match[L]-flagged passthrough rules rather than the negatedRewriteCondchains that Tomcat'sRewriteValveignores. $ensureProjectRewriteConfig()is called beforeexecuteCommand("server", ...)-- the file lands before Tomcat reads it.- CHANGELOG entry is present; DCO
Signed-off-byis present; commit message conforms to commitlint. - The
##escape in the spec's regex string (reFind("^\s*##", line)becomes runtime regex^\s*#) is intentional and correct.
Suggested fix (tests only -- no service changes needed)
Replace every directoryCreate(projectRoot, true); with directoryCreate(projectRoot); (5 lines, one per it() block) and wrap repoRoot/templatePath in a ctx struct as shown above. The service CFC and Module.cfc wiring are clean as-is.
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: The new commit (7e5b59256) adds docs-only changes (upgrade guide entries for both v4-0-0 and v4-0-1-snapshot) and is clean. However, the two cross-engine issues flagged in the prior Reviewer A pass at d9e2c9b6b are still unaddressed in vendor/wheels/tests/specs/cli/RewriteConfigInstallerSpec.cfc. Changes needed in the test spec before this can merge.
Cross-engine
directoryCreate(projectRoot, true) — five occurrences (lines 32, 54, 76, 111, 141)
// vendor/wheels/tests/specs/cli/RewriteConfigInstallerSpec.cfc:32
directoryCreate(projectRoot, true);Adobe ColdFusion does not support the two-argument form of directoryCreate. This is the same pattern that PR #2614 fixed across BrowserTest.cfc and McpServer.cfc, where every call site was replaced with the Java mkdirs() idiom:
// vendor/wheels/wheelstest/BrowserTest.cfc:284-285
// Adobe CF rejects directoryCreate(path, true) -- see #2614. Use mkdirs() instead.
var created = createObject("java", "java.io.File").init(arguments.path).mkdirs();Because projectRoot is always a direct child of the already-existing getTempDirectory(), the simplest cross-engine fix is the single-argument form (no recursive creation needed):
directoryCreate(projectRoot);This affects all five it() blocks. The spec lives in vendor/wheels/tests/specs/, which the core test runner compiles in its entirety — one compilation error on Adobe CF crashes every spec in the directory for that engine x database combination.
Conventions
Outer-describe var accessed from inner it closures (lines 26-27, used throughout)
// vendor/wheels/tests/specs/cli/RewriteConfigInstallerSpec.cfc:26-27
var repoRoot = expandPath("/wheels/../..");
var templatePath = repoRoot & "/cli/lucli/templates/app/rewrite.config";These are used inside every it() block (e.g. line 38: sourceTemplate=templatePath). Per CLAUDE.md "Closure gotcha": CFML closures can't access outer local vars — use shared structs. On Adobe CF the inner it() closures can fail with "variable TEMPLATEPATH is undefined" because var declarations write to the declaring closure's local scope and are not guaranteed to be captured by nested closures on all engines. The established fix is a shared struct:
describe("cli.lucli.services.RewriteConfigInstaller", () => {
var ctx = {};
ctx.repoRoot = expandPath("/wheels/../..");
ctx.templatePath = ctx.repoRoot & "/cli/lucli/templates/app/rewrite.config";
it("writes...", () => {
var result = installer.install(projectRoot=projectRoot, sourceTemplate=ctx.templatePath);
});
});What is correct
The new docs commit (7e5b59256) is clean:
- Both
v4-0-0/upgrading/3x-to-4x.mdxandv4-0-1-snapshot/upgrading/3x-to-4x.mdxreceived the matching entry; no versioned docs directory was missed. - The entry accurately describes the symptom, root cause, fix, and idempotency guarantee.
- Commit conforms to commitlint (
docs(web/guides):, <=100 chars, DCO Signed-off-by present).
The service (RewriteConfigInstaller.cfc) and Module.cfc wiring remain correct as noted in the previous pass — no new issues introduced there.
Required fixes (spec only — no service changes needed)
- Replace every
directoryCreate(projectRoot, true);withdirectoryCreate(projectRoot);(5 lines, one perit()block). - Wrap
repoRoot/templatePathin actxstruct at the top of thedescribe()callback and reference them asctx.templatePathin eachit().
Wheels Bot — Reviewer B (round 1)A's review is substantively sound. Both findings are real, cite the correct evidence, and map to established cross-engine gotchas documented in CLAUDE.md and the repo's own changelog. I agree changes are needed in the test spec before merge. SycophancyNone detected. The "What is correct" section praises specific, verifiable properties of the diff (idempotency gate on False positivesNone detected.
Missed issuesNone of significance.
Verdict alignmentMinor process concern: A's TL;DR says "changes needed… before merge" but the review was submitted with state ConvergenceAligned. Both findings are real cross-engine regressions confined to the test spec. The service CFC (
Joint recommendation: apply these spec-only changes. |
Wheels Bot — Reviewer B (round 1)A's review is accurate. Both cross-engine findings are confirmed against the actual spec lines, and there are no false positives or missed issues worth raising. The two changes are concrete and addressable. SycophancyNone detected. A did not approve despite unresolved cross-engine issues, and explicitly held the "changes needed" line. False positivesNone detected.
Missed issuesNone detected. The service code ( Verdict alignmentA submitted as ConvergenceAligned with A. Both findings are real cross-engine issues that will fail the Adobe CF test run, and the required fixes are precise: (1) replace all five |
- Replace `directoryCreate(projectRoot, true)` with `directoryCreate(projectRoot)` at the five `it()` blocks. Adobe CF rejects the two-arg recursive form (per #2614); since `getTempDirectory()` always exists, no recursive parent creation is needed. - Hoist `repoRoot` and `templatePath` from outer-`describe` `var` declarations into a shared `ctx` struct so inner `it()` closures see them reliably on Adobe CF (CLAUDE.md "Closure gotcha"). No service or wiring changes — service CFC and `Module.cfc::start()` wiring were already approved. Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Wheels Bot — Address Review (round 1)Applied consensus findings from Reviewer A and Reviewer B's convergence (round 1) — both reviewers aligned on two cross-engine fixes confined to the test spec:
No service or wiring changes — Test run: The new commit will trigger a fresh Reviewer A run on the updated SHA. Convergence loop continues until reviewers align on |
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: Commit 5b656e4 addresses both cross-engine issues flagged in the two prior Reviewer A passes. The directoryCreate(projectRoot, true) → directoryCreate(projectRoot) fix is applied at all five it() call sites, and the repoRoot/templatePath variables are correctly hoisted into a shared ctx struct. No new issues introduced. The service CFC, Module.cfc wiring, CHANGELOG entry, and web docs were already approved in earlier rounds. No further changes required — this PR is ready to graduate out of draft.
What was fixed
Cross-engine: directoryCreate(projectRoot, true) → directoryCreate(projectRoot)
All five occurrences updated as requested (lines 36, 58, 80, 115, 145 of RewriteConfigInstallerSpec.cfc):
// Before (Adobe CF rejects the two-arg recursive form — per #2614)
directoryCreate(projectRoot, true);
// After (single-arg, cross-engine safe; parent dir is getTempDirectory() which always exists)
directoryCreate(projectRoot);Conventions: outer-describe variables shared via ctx struct
Lines 29–31 now match the CLAUDE.md-recommended pattern:
var ctx = {};
ctx.repoRoot = expandPath("/wheels/../..");
ctx.templatePath = ctx.repoRoot & "/cli/lucli/templates/app/rewrite.config";Every it() closure references ctx.templatePath rather than a bare outer var templatePath, eliminating the Adobe CF closure-capture risk documented in CLAUDE.md ("Closure gotcha").
Remaining spec details confirmed correct
reFind("^\s*##", line)(line 126) —##correctly escapes to a single#at CFML runtime; the Java regex^\s*#matches Tomcat rewrite.config comment lines as intended.fileWrite(..., "## user-customized rules")(line 60) andtoBe("## user-customized rules")(line 69) — both string literals evaluate to the same runtime value (# user-customized rules); the assertion is internally consistent.directoryDelete(projectRoot, true)in all fivefinallyblocks — the two-arg recursive form for deletion is cross-engine safe; the #2614 fix was scoped todirectoryCreate.- Commit
fix(test): address Reviewer A/B consensus findings (round 1)— typefix, scopetest, subject ≤ 100 chars, sentence-case, DCOSigned-off-bypresent. Conforms tocommitlint.config.js.
Wheels Bot -- Reviewer B (round 1)A's approval of the round-1 address-review commit is well-founded. Both prior findings are verifiably fixed, no new regressions were introduced, and the three confirmed-correct details A re-examined all check out against the diff. One minor concern is noted below but it is not blocking. SycophancyNone detected. A's sign-off is evidence-based: specific line numbers are cited for each of the five directoryCreate call sites, the before/after snippet is shown, the ctx struct pattern at lines 29-31 is confirmed, and three secondary details are re-checked. This is earned approval, not a rubber stamp. False positivesNone detected.
Missed issuesOne low-severity item: the variables.moduleRoot trailing-slash assumption. Module.cfc's $ensureProjectRewriteConfig() builds the template path by concatenating variables.moduleRoot with "templates/app/rewrite.config". This works only if variables.moduleRoot ends with a path separator. LuCLI module roots typically do (set by BaseModule init), but A did not verify this. If a given engine omits the trailing slash the installer's fileExists guard returns a silent no-op rather than a crash -- annoying, not catastrophic. Worth a single line of confirmation from a human reviewer, not necessarily a code change. No other missed issues. The dotted-path resolution of cli.lucli.services.RewriteConfigInstaller in the test, the template file's pre-existence in the repo (added by wheels new), and the ctx struct pattern's correctness all check out. Verdict alignmentA recommends graduating the PR out of draft with no further code changes; B agrees. ConvergenceAligned. The two cross-engine issues from the prior round are resolved. The service CFC, Module.cfc wiring, CHANGELOG entry, and web docs are clean. The trailing-slash observation is informational and does not change the recommendation. Both reviewers are satisfied: the PR can be merged once a human approver reviews and flips the draft flag. |
Brings the CI-rendered blog visual-regression baseline (8fb7bf2, landed on develop via #2624's squash merge) into the PR branch so the Visual regression check stops failing on the stale macOS-Chromium baseline this branch forked from. The CI run on 5b656e4 measured 37,668 pixels of font-rendering drift against the old baseline; merging develop in auto-takes the CI-rendered blob (af41788) the PR branch never touched. Three conflicts resolved manually, all in the documentation layer: - CHANGELOG.md: combine #2626 entry (this PR) with develop's #2630, #2635, #2621, plus the Documentation subsection for #2627. PR entry moved to the end of the Fixed list to preserve develop's ordering. - web/sites/guides/.../v4-0-0/upgrading/3x-to-4x.mdx: keep both Common-issues bullets — develop's wirebox boot-failure entry (#2627) and this PR's static-asset 404 entry (#2626). - web/sites/guides/.../v4-0-1-snapshot/upgrading/3x-to-4x.mdx: same resolution as v4-0-0. cli/lucli/Module.cfc auto-merged cleanly — develop's #2624 added a sibling helper, this PR added \$ensureProjectRewriteConfig(); both land side by side. Signed-off-by: Peter Amiri <peter@alurium.com>
Develop catch-up to clear stale visual-regression baselineMerged Why the VR check was failing
Conflicts resolved manually (docs-only)
Reviewer A will re-run on the new SHA. The merge commit is pure conflict resolution and develop catch-up, so the prior |
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: Pass-through review of merge commit (40d70f3ce) integrating develop after round 3. No new issues in PR code. Pre-existing closure-scope issue in ConfigRoutesStaleDocUrlSpec.cfc arrived via develop (PR #2635) — not introduced by this PR. This PR is ready to graduate from draft.
Cross-engine
Pre-existing: outer-describe var repoRoot referenced inside nested it() closures — ConfigRoutesStaleDocUrlSpec.cfc (line 41)
The pattern var repoRoot = expandPath("/wheels/../..") is declared in outer describe() and referenced inside it() closures. On Adobe CF this fails with variable REPOROOT is undefined because CFML closures do not reliably capture outer local vars (CLAUDE.md “Closure gotcha”).
This file came from develop via the merge commit — not introduced by this PR. Landed on develop as part of PR #2635; track as separate follow-up against develop. This PR’s RewriteConfigInstallerSpec.cfc correctly avoids the pattern using ctx.repoRoot.
What the merge confirmed is still correct
RewriteConfigInstaller.cfc—arguments.prefix throughout; idempotency onfileExists(dest); all five return-struct cases; mirrorsBundleStager.Module.cfc:4507-4519—$ensureProjectRewriteConfig()isprivate void, called beforeexecuteCommand("server", ...), swallows IO failures silently.RewriteConfigInstallerSpec.cfc—directoryCreate(projectRoot)single-arg; ctx struct;directoryDelete(projectRoot, true)in all fivefinallyblocks.rewrite.configtemplate — coversmiscellaneous,stylesheets,javascripts,files; positive-match[L]-flagged rules; no negatedRewriteCond.- CHANGELOG and both
v4-0-0/v4-0-1-snapshotupgrade guides updated.
Commits
| SHA | Message | Verdict |
|---|---|---|
d9e2c9b6b |
fix(cli): provision project rewrite.config… |
pass |
7e5b59256 |
docs(web/guides): note static-asset 404 fix… |
pass |
5b656e462 |
fix(test): address Reviewer A/B consensus findings (round 1) |
pass |
40d70f3ce |
merge commit | n/a |
Wheels Bot — Reviewer B (round 1)Review #4278722945 (and the second submission #4278728593) on the current SHA were both self-retracted by Reviewer A with the note "Submitted in error — content redacted." Neither carries any findings, verdict, or line comments to critique. SycophancyN/A — no review body to assess. False positivesN/A — no findings were made. Missed issuesN/A — no content was submitted. Verdict alignmentNo verdict was issued. ConvergenceNot aligned — not because A and B disagree, but because no valid Reviewer A review exists for this SHA ( |
There was a problem hiding this comment.
Wheels Bot — Reviewer A response (round 1)
B's round-1 critique was factually correct at the moment it was posted: the two prior A submissions on SHA 40d70f3ce were both self-retracted (content redacted), leaving no valid Reviewer A review for that SHA. However, A's substantive review (PRR_kwDOABMUH87_CDeR) was submitted at 05:55:27Z — approximately 35 seconds before B's comment at 05:56:02Z. The valid review existed; B's trigger fired before it was indexed. No substantive disagreement separates A and B.
Conceded points
- B was correct that at the time of the round-1 critique, no valid A review could be observed on this SHA. The timing race is acknowledged.
Defended points
- A's valid review (
PRR_kwDOABMUH87_CDeR) on SHA40d70f3ceis the authoritative A position. It confirmed: (1)RewriteConfigInstallerSpec.cfccorrectly uses single-argdirectoryCreate(projectRoot)at all fiveit()call sites; (2) thectx.repoRoot/ctx.templatePathstruct pattern is applied throughout the outerdescribe()callback; (3) the service CFC, Module.cfc wiring, CHANGELOG, and both upgrade guide docs are clean. One pre-existing closure-scope issue inConfigRoutesStaleDocUrlSpec.cfc(outervar repoRootcaptured by nestedit()closures) was noted — that file arrived via develop/PR #2635, is not part of this PR, and should be tracked as a separate follow-up againstdevelop. - The recommendation to graduate from draft is based on verified evidence in the diff, not solely on the prior rounds' convergence.
Updated verdict
Still recommend graduating from draft (approve). All PR-specific cross-engine issues are resolved; no new issues were introduced by the merge commit. The one noted issue (ConfigRoutesStaleDocUrlSpec.cfc) is a pre-existing develop regression and does not block this PR.
Second develop catch-up — five more PRs landed on develop after the first merge (40d70f3): #2637, #2645, #2639, #2638, #2642. Re-resolves the same three documentation conflicts: - CHANGELOG.md: keep develop's #2628 and #2629 Fixed entries; move this PR's #2626 entry to the end of the Fixed list. - v4-0-0/upgrading/3x-to-4x.mdx: keep develop's new #2631 reloadPassword Common-issues bullet; this PR's #2626 static-asset bullet stays at the end. - v4-0-1-snapshot/upgrading/3x-to-4x.mdx: same resolution. cli/lucli/Module.cfc auto-merged again — no manual fixes needed. Signed-off-by: Peter Amiri <peter@alurium.com>
There was a problem hiding this comment.
Wheels Bot — Reviewer A
TL;DR: Third Reviewer A pass against head SHA 7b9c97f47, a second merge commit integrating develop into fix/bot-2626. No new issues were introduced by this integration. All cross-engine and conventions findings from prior rounds remain resolved. The PR-specific files (RewriteConfigInstaller.cfc, RewriteConfigInstallerSpec.cfc, Module.cfc, docs, CHANGELOG) are clean. Verdict: approve (blocked by self-review restriction — bot authored this PR; a human reviewer should merge).
What this pass confirms
Service code: cli/lucli/services/RewriteConfigInstaller.cfc
- All five return paths are correctly modelled:
missing-project-root,already-present,missing-template,write-failed, and the success path. - Idempotency is correctly gated on
fileExists(dest)before any write, so user-customised files are left untouched. arguments.prefix is used throughout the function body — no naked variable references.- The
write-failedpath is caught locally (ininstall()) and returns a structured result rather than throwing, while$ensureProjectRewriteConfig()in Module.cfc wraps the entire call in a secondtry/catchas a belt-and-suspenders silent guard so a permissions hiccup never blockswheels start.
Spec: vendor/wheels/tests/specs/cli/RewriteConfigInstallerSpec.cfc
directoryCreate(projectRoot)— single-arg form used at all fiveit()call sites (lines 36, 58, 80, 115, 145). Cross-engine safe per #2614.ctx.repoRoot/ctx.templatePath— outer-describevalues shared via a struct rather than bare outervardeclarations, matching the CLAUDE.md closure-gotcha pattern.directoryDelete(projectRoot, true)in all fivefinallyblocks — the two-arg recursive form for deletion is cross-engine safe (the #2614 fix was scoped todirectoryCreate).reFind("^\s*##", line)(line 126) — CFML evaluates##to a single#in string literals, so the runtime regex is^\s*#, which correctly matches Tomcat RewriteValve comment lines. Intentional and correct.fileWrite(... "## user-customized rules")andtoBe("## user-customized rules")— both sides evaluate to# user-customized rulesat runtime via the same CFML##escape; the idempotency assertion is internally consistent.reFind("RewriteCond\s+%\{REQUEST_URI\}\s+!", activeRules) > 0(line 131) — no#characters in the pattern; the\s,\{,\}sequences are CFML-safe and correctly pass through to the Java regex engine.
Module.cfc wiring
$ensureProjectRewriteConfig()is declaredprivate void, placed between$ensureWheelsBundles()and theexecuteCommand("server", ...)delegation — correct position so the file lands before Tomcat reads it.
Docs and metadata
- CHANGELOG
[Unreleased]entry is present, accurate, and describes both symptom and fix. - Both
v4-0-0/upgrading/3x-to-4x.mdxandv4-0-1-snapshot/upgrading/3x-to-4x.mdxreceived the matching entry.
Commits (PR-specific)
| SHA | Message | Verdict |
|---|---|---|
d9e2c9b6b |
fix(cli): provision project rewrite.config on wheels start for 3.x upgrades |
pass |
7e5b59256 |
docs(web/guides): note static-asset 404 fix for 3.x upgrades in common issues |
pass |
5b656e462 |
fix(test): address Reviewer A/B consensus findings (round 1) |
pass |
7b9c97f47 |
merge commit | n/a |
Pre-existing issue (not from this PR — for tracking only)
vendor/wheels/tests/specs/cli/ConfigRoutesStaleDocUrlSpec.cfc (arrived via develop / PR #2635) still declares var repoRoot = expandPath("/wheels/../.."); in an outer describe() and references it inside nested it() closures. This is the closure-capture gotcha that would fail on Adobe CF. Flagged in the prior round-4 pass; should be tracked as a separate follow-up against develop, not as a blocker here.
Wheels Bot — Reviewer B (round 1)A's approval of the second develop-catchup merge commit is well-founded and accurate. Every claim A made against the diff checks out. No sycophancy, no false positives, no missed issues of consequence. Aligned. SycophancyNone detected. A's sign-off cites specific line numbers for each of the five False positivesNone detected.
Missed issuesNone of substance.
Verdict alignmentA recommends approve with the self-review restriction noted (the bot authored the PR and cannot formally submit a GitHub approval). Submitting as ConvergenceAligned. The two cross-engine issues from round 1 are resolved, confirmed across two prior B-round assessments and an address-review commit. This third Reviewer A pass against the develop-catchup SHA finds nothing new. Joint recommendation: approve — the PR is ready for a human reviewer to flip the draft flag and merge. |
wheels startnow drops the workingrewrite.configtemplate at the project root when one is missing. LuCLI's bundled-default rewrite.config uses a narrow static-dir allow-list (images|css|js|fonts|assets|static) plus negatedRewriteCondchains that Tomcat's RewriteValve doesn't honour — every static asset under 3.x-conventional dirs like/miscellaneous/,/javascripts/,/stylesheets/,/files/404s on the firstwheels startafter a 3.x → 4.0 upgrade. Providing a project-level override (which LuCLI'sCatalinaBaseConfigGeneratorpicks up verbatim) sidesteps the buggy default. New apps already receive this file viawheels new; this PR closes the upgrade-path gap. Existing project rewrite.config files are left untouched.Fixes #2626
Type of Change
Feature Completeness Checklist
Signed-off-by:vendor/wheels/tests/specs/cli/RewriteConfigInstallerSpec.cfc(5 specs covering missing file, idempotency, allow-list coverage of 3.x dirs, passthrough rule style, missing-template fallback)bot-update-docs.ymlbot-update-docs.ymlbot-update-docs.yml[Unreleased]wheels.tests.specs.cliruns all 13 specs Passed locally (Lucee 7.0.1.100, SQLite). Spec was authored failing first (6 errors fromcli.lucli.services.RewriteConfigInstaller not found by lucee.core), passed after the service landed and Module.cfc wired$ensureProjectRewriteConfig()intostart().Test Plan
/miscellaneous/,/javascripts/,/stylesheets/,/files/directories.rewrite.configappears at the project root afterwheels start.wheels startdoes not overwrite a user-customizedrewrite.config.Notes
cli/lucli/services/RewriteConfigInstaller.cfcso its behavior can be unit-tested without instantiating the full LuCLI module (mirrorsBundleStager's pattern).Module.cfc::start()via$ensureProjectRewriteConfig(), between$ensureWheelsBundles()and theexecuteCommand("server", ...)delegation.