Skip to content

fix(cli): strip {{enums}} placeholder in legacy CommandBox generator template - #3191

Closed
wheels-bot[bot] wants to merge 1 commit into
developfrom
fix/bot-3180-forgebox-wheels-cli-is-the-legacy-commandbox-modul
Closed

fix(cli): strip {{enums}} placeholder in legacy CommandBox generator template#3191
wheels-bot[bot] wants to merge 1 commit into
developfrom
fix/bot-3180-forgebox-wheels-cli-is-the-legacy-commandbox-modul

Conversation

@wheels-bot

@wheels-bot wheels-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

The legacy CommandBox-module generator (cli/src/models/TemplateService.cfc)
substituted {{belongsToRelationships}}, {{hasManyRelationships}},
{{hasOneRelationships}}, and {{validations}} but had no branch for the
{{enums}} placeholder
that ships in its own model template
(cli/src/templates/ModelContent.txt). As a result box wheels generate model
(the ForgeBox-installed wheels-cli) leaked a literal {{enums}} into the
generated config() body — invalid CFML. This path has no enum codegen at all
(unlike the LuCLI generator at cli/lucli/services/CodeGen.cfc, which renders
enums), so the minimal, safe fix is to strip the placeholder unconditionally,
mirroring the existing no-validations fallback.

Related Issue

Refs #3180

This PR ships only the standalone {{enums}} leak. The broader maintainer
decision the issue also raises — whether to keep publishing the legacy
CommandBox-module CLI to ForgeBox vs. point users at the LuCLI distribution —
is explicitly out of scope per triage, so this uses Refs (not Fixes) to
avoid auto-closing the tracking issue.

Type of Change

  • Bug fix
  • New feature
  • Enhancement to existing feature
  • Documentation update
  • Refactoring

Feature Completeness Checklist

  • DCO sign-off -- commit carries Signed-off-by: (git commit -s)
  • Tests -- failing-then-passing regression spec (see Test Plan)
  • Framework Docs -- handled separately by bot-update-docs.yml
  • AI Reference Docs -- handled separately by bot-update-docs.yml
  • CLAUDE.md -- handled separately by bot-update-docs.yml
  • Changelog fragment -- changelog.d/3180-cli-legacy-template-enums-leak.fixed.md
  • Test runner passes -- see Test Plan note

Test Plan

Spec: cli/lucli/tests/specs/services/LegacyTemplateServiceEnumsSpec.cfc
(placed in the LuCLI suite because it runs only on the bundled Lucee, where
instantiating the legacy cli.src.* CFC is safe — the cross-engine core
suite must not compile/instantiate the CommandBox-module generator).

The spec instantiates cli.src.models.TemplateService, exposes the private
processTemplate via makePublic, and feeds it the model-template body with an
empty context:

  • Before the fix: every sibling placeholder ({{validations}},
    {{belongsToRelationships}}) is stripped by its existing else branch, but
    {{enums}} survives, so expect(result).notToInclude("{{enums}}") fails —
    isolating exactly the reported defect.
  • After the fix: all three assertions pass.

Run with bash tools/test-cli-local.sh.

Note: the bot's sandbox for this run could not boot a test server
(tools/test-local.sh hits a BSD-vs-GNU sed incompatibility, and the
server-boot paths used by tools/test-cli-local.sh are permission-gated),
so the failing→passing transition was verified by tracing processTemplate
rather than executed locally. CI (bot-tdd-gate.yml + the standard CLI
test workflow) runs the spec for real on this PR.

…template

The legacy CommandBox-module generator (cli/src/models/TemplateService.cfc)
substituted {{belongsToRelationships}}, {{hasManyRelationships}},
{{hasOneRelationships}}, and {{validations}} but had no branch for the
{{enums}} placeholder carried by its model template. box wheels generate
model therefore leaked a literal {{enums}} into the generated config() body
as invalid CFML. This legacy path has no enum codegen (unlike the LuCLI
generator at cli/lucli/services/CodeGen.cfc), so the placeholder is now
stripped unconditionally, mirroring the no-validations fallback.

Adds a regression spec under cli/lucli/tests/specs/services/ that exercises
the legacy TemplateService.processTemplate via makePublic and asserts the
{{enums}} placeholder never survives into generated output.

Refs #3180

Signed-off-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
@wheels-bot

wheels-bot Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Wheels Bot — No doc updates

Reviewed this PR's diff and found no docs that need updating (purely internal bug fix to the legacy CommandBox-module generator's template processing — no existing guide page covers this path, no .ai/wheels/ layer doc tracks it, and no CLAUDE.md convention changed).

@wheels-bot wheels-bot Bot left a comment

Copy link
Copy Markdown
Contributor Author

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 fixes the legacy CommandBox-module generator (cli/src/models/TemplateService.cfc) leaking a literal {{enums}} placeholder into generated model config() bodies (box wheels generate model, refs #3180), by stripping the placeholder unconditionally — mirroring the existing no-validations fallback. The diff is small, correct, and well-tested; I verified every load-bearing assumption in the new spec against the actual code. Verdict: comment (no blocking findings; final confidence on the new spec's green run is delegated to CI per the PR's own disclosure that the sandbox could not execute it locally).

Verification notes (all checks passed)

Correctness

  • The defect is real: cli/src/templates/ModelContent.txt:9 carries {{enums}}, and pre-fix processTemplate had branches only for belongsToRelationships / hasManyRelationships / hasOneRelationships / validations (TemplateService.cfc:90-132) — nothing consumed {{enums}}, and the generic {{key}} loop (lines 52-67) only substitutes keys present in the context.
  • The unconditional strip at cli/src/models/TemplateService.cfc:139 is placed after the generic loop, so a hypothetical future context.enums simple value would still substitute first and the strip becomes a no-op — no regression path.
  • reReplace with \{\{enums\}\} is case-sensitive and matches the template's lowercase placeholder exactly, consistent with the sibling branches.

Tests

  • cli/lucli/tests/specs/services/LegacyTemplateServiceEnumsSpec.cfc is correctly wired: wheels.wheelstest.system.BaseSpec is the established base for CLI service specs (22 prior uses in that directory); makePublic exists (vendor/wheels/wheelstest/system/BaseSpec.cfc:1570) with prior art in ServerDetectionSpec.cfc:45; the dot-path new cli.src.models.TemplateService() resolves from the repo-root webroot exactly as the runner's directory = "cli.lucli.tests.specs" does (cli/lucli/tests/runner.cfm:5).
  • Instantiation with an empty context is safe: TemplateService.cfc has no init(), and every access to the WireBox-injected variables.helpers is guarded by a structKeyExists check on context keys the spec never sets (lines 70-80, 221-228).
  • The failing-then-passing TDD claim holds by inspection: pre-fix, no code path removed {{enums}}, so expect(result).notToInclude("{{enums}}") would fail. Non-blocking note: per the PR body the spec was traced, not executed, in the bot sandbox — the CLI test workflow on this PR is the authoritative confirmation; please ensure it is green before merge.
  • Placing the spec in the LuCLI suite (not the cross-engine core suite) is the right call — the core suite's directory="wheels.tests.specs" would eagerly compile the legacy cli.src.* CFC on every engine.

Docs

  • Changelog fragment changelog.d/3180-cli-legacy-template-enums-leak.fixed.md uses a valid type and the fragment system correctly (no direct CHANGELOG.md edit).

Commits

  • Single commit 2d5037a conforms to commitlint (fix(cli):, subject ≤ 100 chars, not ALL-CAPS) and carries a DCO sign-off matching the author email. The issue ##3180 doubled-hash in the new code comment matches existing repo style (vendor/wheels/Global.cfc:4285), so no change needed there.

No Correctness, Cross-engine, or Security findings. The Refs (not Fixes) linkage to keep the broader ForgeBox-distribution decision open on #3180 matches the triage scope.

@bpamiri

bpamiri commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Superseded by #3197 (merged): a propose-fix draft that raced the ForgeBox path-repair campaign for the same issue; the campaign PR landed first and closed the underlying issue. Closing the duplicate.

@bpamiri bpamiri closed this Jun 13, 2026
@bpamiri
bpamiri deleted the fix/bot-3180-forgebox-wheels-cli-is-the-legacy-commandbox-modul branch June 13, 2026 04:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant