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
Include `wheels-sse.js`(located at `/wheels/assets/js/wheels-sse.js`) for a zero-dependency EventSource client with auto-reconnect.
165
+
`wheels-sse.js`is a zero-dependency EventSource client with auto-reconnect. It is NOT served at any URL by the framework — copy it from `vendor/wheels/public/assets/js/wheels-sse.js` into your app (e.g. `public/javascripts/wheels-sse.js`) and include it with `javaScriptIncludeTag("wheels-sse")` or a plain script tag.
**Reference example**: [`vendor/wheels/wheelstest/DialogConsumer.cfc`](../../vendor/wheels/wheelstest/DialogConsumer.cfc) shows the CFC-based pattern used by `BrowserClient` to proxy Playwright's `Consumer<Dialog>`. The probe in `$requireDialogSupport` mirrors the real call shape so engine compatibility is verified on the same code path.
172
172
173
+
### `for` Loops Inside `finally` Blocks Miscompile on Lucee 7
174
+
175
+
Lucee 7.0.1+100 throws `variable [local] doesn't exist` at runtime when a `for` loop declares or iterates `local`-/`var`-scoped variables inside a `finally` block. Both loop forms are affected — `for (init; cond; step)` and `for (item in collection)`. Isolated with minimal probes: bare assignments and function calls inside `finally` compile and run fine; loops do not. One probe shape even produced a JVM `Expecting a stackmap frame` bytecode-verifier error, pointing at a codegen bug in Lucee's `finally`-block compilation.
// RIGHT — hoist the loop into a helper; the finally body is just a call
188
+
try {
189
+
doWork();
190
+
} finally {
191
+
$restoreState(local.savedState);
192
+
}
193
+
```
194
+
195
+
**Why**: Lucee 7's bytecode generation for `finally` blocks mishandles the `local` scope frame for loop constructs. Adobe CF and BoxLang are unaffected.
196
+
197
+
**Reference example**: `$restoreEmailViewVariables()` in [`vendor/wheels/controller/miscellaneous.cfc`](../../vendor/wheels/controller/miscellaneous.cfc) — the `sendEmail` variables-scope restore runs from `finally` via a `public``$`-prefixed helper (mixin invariant: helpers must be public). Found while addressing review on [#2922](https://github.com/wheels-dev/wheels/pull/2922).
198
+
173
199
### `DirectoryCreate()` Second Argument Is Lucee-Only
174
200
175
201
Lucee accepts `DirectoryCreate(path, createPath, mode)` and recurses parent directories when `createPath=true`. Adobe CF's signature varies by version and at least some Adobe builds reject any second argument with `"The function takes 1 parameter"` (issue #2567).
Copy file name to clipboardExpand all lines: .ai/wheels/troubleshooting/common-errors.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,6 +29,20 @@ Wheels failed to initialize. Check the server log for details.
29
29
30
30
**Note:** Before the #2774 fix, this failure cascaded into a second `[WO] does not exist` exception that hid the real cause. If you see the old cascade on a version that predates this fix (i.e. 4.0.1 or earlier), the underlying cause is always a failed `onApplicationStart` — see above.
31
31
32
+
### "key [ENGINEADAPTER] doesn't exist" / "Element WHEELS.ENGINEADAPTER is undefined" in dev error page
33
+
**Error (on-page or in server log):**
34
+
```
35
+
key [ENGINEADAPTER] doesn't exist (Lucee)
36
+
Element WHEELS.ENGINEADAPTER is undefined (Adobe CF)
37
+
```
38
+
39
+
**Cause:** An exception during `onApplicationStart` (e.g. `Wheels.Cors.InvalidConfiguration` from an invalid `config/settings.cfm` value) triggered `onError`, which itself crashed because three request-lifecycle helpers — `$getRequestTimeout()`, `$statusCode()`, and `$contentType()` — read `application.wheels.engineAdapter` directly after gating on `$hasEngineAdapter()`. That gate checks both `application.wheels` and the startup-staging struct `application.$wheels`, but the subsequent read assumed the adapter had been promoted to `application.wheels`. When only the `$wheels` branch matched (the failed-startup state), the read threw and replaced the original exception (fixed in [#3108](https://github.com/wheels-dev/wheels/pull/3108)).
40
+
41
+
**Resolution:**
42
+
The `[ENGINEADAPTER]` crash is a symptom — the real error happened during startup. Check the server log for the original `onApplicationStart` exception; common causes include invalid middleware configuration, a missing CFML mapping, or a syntax error in `config/settings.cfm` or `config/routes.cfm`.
43
+
44
+
After upgrading past the #3108 fix, `onError` surfaces the original startup exception directly.
Copy file name to clipboardExpand all lines: .ai/wheels/wheels-bot.md
+11-7Lines changed: 11 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,24 +1,28 @@
1
1
# Wheels Bot
2
2
3
-
`wheels-bot[bot]` is a custom GitHub App that runs Claude-powered automation on issues and PRs in `wheels-dev/wheels`. Five stages, all opt-out via the `[skip-claude]` label or repo variable `WHEELS_BOT_ENABLED=false`. Slash-command prompts live in `.claude/commands/`; workflows in `.github/workflows/bot-*.yml`. Full user-facing docs: [`docs/contributing/wheels-bot.md`](../../docs/contributing/wheels-bot.md).
3
+
`wheels-bot[bot]` is a custom GitHub App that runs Claude-powered automation on issues and PRs in `wheels-dev/wheels`. All stages are opt-out via the `[skip-claude]` label or repo variable `WHEELS_BOT_ENABLED=false`. Slash-command prompts live in `.claude/commands/`; workflows in `.github/workflows/bot-*.yml`. Full user-facing docs: [`docs/contributing/wheels-bot.md`](../../docs/contributing/wheels-bot.md).
4
4
5
5
## Stages
6
6
7
7
| Stage | Trigger | Model | Output |
8
8
|---|---|---|---|
9
9
| Triage | issue opened/reopened | Opus | Comment classifying as `bug` / `framework-design` / `other` (+ confidence on `bug` path). Reads code with the allowlisted tools to resolve uncertainty before rating. |
10
10
| Research | bot triage emits `framework-design` marker | Opus | Comment comparing Rails / Laravel / Django / Phoenix / Spring Boot / +1 and recommending a Wheels-idiomatic path (+ confidence). |
11
-
| Propose Fix | bot triage emits `triage-confidence:high\|medium` OR research emits `research-confidence:high\|medium` (or `workflow_dispatch`) | Opus | TDD-mandatory draft PR on branch `fix/bot-<issue>-<slug>`. Spec-then-implementation, both required by `bot-tdd-gate.yml`. |
12
-
| Reviewer A | PR opened / synchronized / ready_for_review | Sonnet | Single PR review with line comments, verdict, and `wheels-bot:review-a:<pr>:<sha>` marker. |
13
-
| Reviewer B | Reviewer A submits a review | Sonnet | PR comment critiquing A for sycophancy, false positives, and missed issues. Loop cap = 3 rounds. |
11
+
| Propose Fix | bot triage emits `triage-confidence:high\|medium` OR research emits `research-confidence:high\|medium` (or `workflow_dispatch`). A pre-gate skips the run when a `peter/issue-<N>-*` branch or an open non-bot PR already targets the issue (campaign guard). | Opus | TDD-mandatory draft PR on branch `fix/bot-<issue>-<slug>`. Spec-then-implementation, both required by `bot-tdd-gate.yml`. |
12
+
| Reviewer | PR opened / synchronized / ready_for_review (`bot-review.yml`; fork PRs via maintainer-labeled `bot-review-fork.yml`) | Opus | Single PR review with line comments, verdict, and `wheels-bot:review-a:<pr>:<sha>` marker (legacy marker name retained). The prompt includes a self-adversarial pass — refute each finding against the actual code before posting — replacing the retired Reviewer B critique loop. Supersession (#3048): when a still-active wheels-bot `CHANGES_REQUESTED` exists and the re-review has zero blocking findings, the verdict is submitted as APPROVE (nits in the body) so the stale block clears without manual dismissal; fork PRs stay comment-only — the bot never approves a fork PR. |
13
+
| Address Review |**opt-in**: maintainer applies the `bot-address-review` label or dispatches `bot-address-review.yml`| Opus | Applies the most recent wheels-bot review's findings on the current head SHA, pushes to the PR branch, comments with `wheels-bot:address-review:<pr>:<sha>:<round>`. |
14
+
15
+
**Model policy:** judging gate = opus, coding stages = opus, janitorial = sonnet (Fable 5 was the judging gate until its 2026-06 deactivation; the reviewer moved to Opus 4.8) (auto-close, write-docs, update-docs stay on Sonnet).
16
+
17
+
**Retired (2026-06-11):** the Reviewer A / Reviewer B convergence loop (`bot-review-b.yml`, `/review-the-review`, `/respond-to-critique`) and the `converged-*` auto-fire chain into address-review. The loop was expensive and flaky, B's marginal catch rate no longer justified a second model pass, and the auto-fire push chain landed a broken spec on a PR (#3005). `bot-advisor.yml` (the loop's deadlock-breaker) is retained but inert — its trigger marker is no longer produced.
14
18
15
19
## Marker conventions (HTML comments, used for idempotency)
@@ -31,7 +35,7 @@ Flip the repo variable `WHEELS_BOT_ENABLED` to `false` to halt every bot workflo
31
35
32
36
## Auto-fire safety net
33
37
34
-
The bot is permitted to chain stages (triage → research → propose-fix), and handoff fires on `*-confidence:high` OR `*-confidence:medium`. Low stays manual. Sensitive areas (security, middleware, migrations, deploy, DI, cross-engine) are caught by the propose-fix prompt's own step-4 safety net, which posts a `fix-held` marker instead of opening a PR. Reviewer A and B then critique whatever propose-fix produces, escalating to the Senior Advisor on deadlock. All bot PRs land as `--draft` and require a human approving review on `develop`.
38
+
The bot is permitted to chain stages (triage → research → propose-fix), and handoff fires on `*-confidence:high` OR `*-confidence:medium`. Low stays manual. Sensitive areas (security, middleware, migrations, deploy, DI, cross-engine) are caught by the propose-fix prompt's own step-4 safety net, which posts a `fix-held` marker instead of opening a PR. The Reviewer then reviews whatever propose-fix produces. Address-review never auto-fires — a human opts the PR in via the `bot-address-review` label. All bot PRs land as `--draft` and require a human approving review on `develop`.
0 commit comments