refactor(view): drop mutual conflict; align with multi-driver pattern#92
Merged
Conversation
PR #88 added Composer `conflict` declarations between view-latte and view-twig. This is duplication — Marko's DI already catches double-bindings via BindingConflictException at boot. The conflict forced view-twig into "autoload-dev only" mode in the monorepo, making view asymmetric with database/cache/queue (where both drivers sit in `require` together). Drops the Composer conflict blocks. view-twig becomes a regular monorepo package: in `repositories[]`, in `require`, full autoload via its own composer.json (no more manual src namespace in root autoload-dev). twig/twig is no longer needed in root require-dev — it's pulled in transitively now that view-twig is in require. Trade-off: failure point moves from `composer install` time to boot time. The boot-time error ("Two modules bind ViewInterface: X and Y") is more actionable than Composer's dependency-resolution noise, and fires immediately on the next request. This pattern aligns with how Magento handles module conflicts (DI-level, not composer-level) and how every other Marko multi-driver family already works today. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 27, 2026
markshust
added a commit
that referenced
this pull request
May 27, 2026
PR #92 settled the architectural question: Marko relies on DI-level BindingConflictException for double-binding detection, not Composer `conflict` declarations. This plan no longer adds conflict blocks or validates them — every rollout task is correspondingly simpler. Changes: - Deleted task 004 (pilot conflict blocks) — no longer needed - Updated _plan.md task table, objective, success criteria, risks - Removed assertConflictBlocksMatch from KnownDriversValidator (task 001); helper now exposes assertSkeletonSuggestContainsAll + assertDocsUrlsResolveToValidPattern - Stripped conflict sub-step / requirement / acceptance criterion from rollout tasks 008-016 (multi-driver) and 011 (inertia) - Rewrote task 017 (view): both view-latte and view-twig now in monorepo post-PR #92, no conflicts, both belong in known-drivers.php - Cleaned up "vacuous conflict assertion" phrasing from single-driver tasks 018-024 - Simplified task 024 (page-cache): removed page-cache-entity conflict verification (moot when no drivers have conflicts) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
markshust
added a commit
that referenced
this pull request
May 27, 2026
…mark ready Closes the gap left by deleting the conflict-blocks pilot task in the previous commit. Tasks 005-025 each decrement by one (005 -> 004, 006 -> 005, ..., 025 -> 024). All cross-references updated: - File names - Task headers - Depends-on fields - _plan.md task table - Prose references Also updates two stale references to view-twig in Discovery Notes that predated PR #88 / #92 (both drivers are now in monorepo, view rollout is no longer a single-driver case). Status: planning -> ready (plan-orchestrate expects this). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR #88 added Composer `conflict` declarations between `marko/view-latte` and `marko/view-twig`. This drops them, aligning view with the same pattern used by `marko/database`, `marko/cache`, `marko/queue`, etc. — where both drivers can be installed simultaneously and Marko's DI catches the double-binding at boot via `BindingConflictException`.
Why drop the conflicts?
Three reasons:
1. Marko already has the canonical detection mechanism. `BindingConflictException` throws at boot time when two modules bind the same interface. That's the framework's loud, expressive error path. Composer `conflict` declarations duplicate this in a less expressive medium — Composer can only say "incompatible," not "two modules bind ViewInterface, remove one."
2. O(n²) maintenance burden. Each new driver in a family requires updating every existing sibling's `conflict` block. PR #91 was going to ship a CI test enforcing sync between `known-drivers.php` and these conflict blocks — but that's infrastructure to maintain other infrastructure. `known-drivers.php` alone is enough source of truth.
3. Monorepo asymmetry. Because of the conflicts, view-twig couldn't sit in `require` next to view-latte — it had to live as a "phantom" via root `autoload-dev` namespace mappings, while view-latte was fully installed. After this change, view-twig is a regular monorepo package, fully symmetric with view-latte. Matches how database-mysql + database-pgsql coexist today.
What changed
Trade-off
Failure detection moves from `composer install` time to boot time. In practice the gap is seconds (any subsequent request triggers boot), and the boot-time error message is more actionable than Composer's dependency-resolution failures. Aligned with Magento's long-established prior art (module conflicts caught at DI level, not at composer.json) — which Marko inherits its DI heritage from.
Downstream impact
This blocks/feeds two open plans:
Test plan
🤖 Generated with Claude Code