chore(claude): refine Clean promotion signal — dependency rule vs project split#50
Conversation
… project split
Sharpens the "Promotion signal" section after a discussion surfaced that
the prior framing ("Clean is earned / for complex services") conflated two
separable things that both wear the name "Clean Architecture":
- The DEPENDENCY RULE (Domain -> nothing; IO at the edges) is already in
force in VSA, applies at every scale, and is NOT what the promotion
signal gates. Decoupling the domain from frameworks is always worth it.
- The MULTI-PROJECT STRUCTURE (4 csprojs) is the only part with ceremony
and the only thing the promotion signal gates — all it buys over
single-project VSA is compile-time enforcement of the dependency rule
via project references.
Adds the real axis: how you ENFORCE the dependency rule, escalating with
the cost of a violated boundary — convention -> architecture tests ->
project split. Names the middle rung most teams skip: an architecture test
(NetArchTest / ArchUnitNET / Roslyn analyzer) asserting "Domain references
no EF/Infrastructure namespaces" enforces the same boundary the 4-project
split does, deterministically in CI, without the ceremony. So the project
split is rarely needed for enforcement alone — reach for it only when
domain complexity makes you want the compiler (not a test) to hold the
line, or when separate deploy/versioning units justify it.
New table row for the architecture-tests rung; existing "5+ aggregates"
row reframed as "when you want the compiler to hold the boundary" rather
than "consider Clean" (which blurred principle into structure).
Notes NextAurora enforces the rule today via convention + the
architecture-reviewer agent + CodeRabbit; adding architecture tests would
be the next rung without changing the VSA shape (a candidate future
improvement, not mandated here).
Paraphrase-drift audit: run /check-rules locally to audit paraphrases
against this diff. Done — the refinement is net-new nuance; no existing
See-CLAUDE.md marker paraphrases the promotion signal or the
dependency-rule-vs-structure distinction, and it's consistent with the
"Layer Dependencies" rule it references. No drift.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
WalkthroughThe PR updates CLAUDE.md to clarify that the domain dependency rule is already enforced in VSA, defines "promote to Clean" as a multi-project (compile-time) split, and introduces an escalation ladder: convention → architecture tests (NetArchTest/Analyzer) → project split. ChangesArchitecture Promotion Progression
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CLAUDE.md`:
- Around line 98-127: Add the required follow-up note to CLAUDE.md next to the
changed section stating: "Run /check-rules locally to audit paraphrases against
this diff." Then run the repository's /check-rules tool locally to locate all
paraphrases that end with "See CLAUDE.md", update any that now need revised
wording, and commit those paraphrase updates; ensure the note is present near
the paragraph that distinguishes "dependency rule" vs "multi-project structure"
so reviewers can see the audit instruction.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: bbe14d5a-691b-41b8-8038-e49b7eed1661
📒 Files selected for processing (1)
CLAUDE.md
| **What "promote to Clean" actually means — the dependency rule vs. the project split.** Two | ||
| different things wear the name "Clean Architecture," and only one of them is what you'd | ||
| promote *to*: | ||
|
|
||
| - **The dependency rule** (Domain → nothing; infrastructure/IO at the edges) is *already in | ||
| force* in VSA and applies at every scale. It is **not earned, not complexity-gated, and | ||
| not what the promotion signal is about** — NextAurora keeps it today as single-project VSA | ||
| (see "Layer Dependencies"). Decoupling the domain from frameworks is always worth it. | ||
| - **The multi-project structure** (separate Domain/Application/Infrastructure/Api csprojs) is | ||
| the only part that carries ceremony, and the only thing the promotion signal gates. All it | ||
| buys over single-project VSA is **compile-time enforcement** of the dependency rule via | ||
| project references. | ||
|
|
||
| So the real axis is *how you enforce the dependency rule*, escalating only as the cost of a | ||
| violated boundary rises: **convention → architecture tests → project split.** The middle rung | ||
| is the one most teams skip: an **architecture test** (NetArchTest / ArchUnitNET, or a Roslyn | ||
| analyzer) asserting "Domain references no EF/Infrastructure namespaces" enforces the *same* | ||
| boundary the 4-project split does — deterministically, in CI, **without the project | ||
| ceremony**. The project split is therefore rarely needed *for enforcement alone*; reach for it | ||
| only when genuine domain complexity makes you want the *compiler* (not a test) to hold the | ||
| line, or when separate deploy/versioning units justify it. NextAurora enforces the dependency | ||
| rule today via *convention + the architecture-reviewer agent + CodeRabbit*; adding | ||
| architecture tests would be the next rung and would make it deterministic **without changing | ||
| the VSA shape**. | ||
|
|
||
| | Signal | Shape | | ||
| |---|---| | ||
| | ≤4 aggregates per service, ≤10 features, single team | VSA (current default) | | ||
| | 5+ aggregates with cross-cutting domain rules that several features coordinate on, AND `Domain/` growing faster than `Features/` | Consider Clean Architecture promotion | | ||
| | "I want the dependency rule enforced, not just held by convention" | **Architecture tests** (NetArchTest / analyzer) — NOT a project split. Same boundary, no ceremony | | ||
| | 5+ aggregates with cross-cutting domain rules that several features coordinate on, AND `Domain/` growing faster than `Features/` | Consider the multi-project split — when you want the *compiler* to hold the boundary, or need separate deploy/versioning units | |
There was a problem hiding this comment.
Required follow-up for CLAUDE.md rule drift audit.
Run /check-rules locally to audit paraphrases against this diff.
As per coding guidelines, “When this changes, every paraphrase ending in ‘See CLAUDE.md’ elsewhere in the repo may need updating. Flag the CLAUDE.md change with a note: ‘Run /check-rules locally to audit paraphrases against this diff.’”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@CLAUDE.md` around lines 98 - 127, Add the required follow-up note to
CLAUDE.md next to the changed section stating: "Run /check-rules locally to
audit paraphrases against this diff." Then run the repository's /check-rules
tool locally to locate all paraphrases that end with "See CLAUDE.md", update any
that now need revised wording, and commit those paraphrase updates; ensure the
note is present near the paragraph that distinguishes "dependency rule" vs
"multi-project structure" so reviewers can see the audit instruction.
Adds a deep-dive link from the refined "Promotion signal" section to the new portable decision guide (docs/vsa-vs-clean-architecture.md, PR #51): the CLAUDE.md section is NextAurora's specific rule; the doc is the general two-meanings-of-Clean / enforcement-spectrum / testing-shift / duplication-tradeoff reference behind it. Pointer only — no rule change. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A reusable, system-agnostic synthesis of the VSA-vs-Clean decision, distilled from a multi-turn architecture discussion. Written to be lifted into any project; NextAurora is the worked example at the end, not the premise. Same pattern as docs/messaging-transport-selection.md — portable reference knowledge, kept OUT of CLAUDE.md (which holds THIS repo's rules). Core points it lands: - "Clean Architecture" is two things: the DEPENDENCY RULE (always-on, not earned, not in tension with VSA) and the 4-PROJECT STRUCTURE (the only part with ceremony, the only part the "is it worth it" question is about). - VSA and Clean are orthogonal axes — organization/cohesion vs dependency direction. "Combine" = organize by feature + keep the domain decoupled. - VSA does NOT auto-enforce the dependency rule; you enforce it on a spectrum: convention → architecture tests → project split. The middle rung (NetArchTest/ArchUnitNET) gives the SAME enforcement as the 4-project split WITHOUT the ceremony, at the namespace level in a single project. Code example included. - Two meanings of "combine": orthogonal axes + per-slice complexity gradient. - Testcontainers shifted the calculus: integration-default for IO-touching code beats mock-heavy unit tests, which collapses the repository-interface-for-testability argument. But it's a Testing Trophy, not a pure rectangle — keep fast unit tests for pure domain logic; mind the Docker dependency + speed cost. - The duplication tradeoff: keep cross-cutting concerns in pipeline behaviors (not per-slice), prefer duplication over the wrong abstraction; cost scales with slice count and bites hardest on pure CRUD. - When-to-use table + common mistakes (incl. "don't add a repo interface per slice on EF", "don't 4-project-split just to get the dependency rule", "don't mix layered + sliced services in one solution"). README Documentation table updated to index it. No CLAUDE.md edit here (kept separate to avoid colliding with the open promotion-signal PR #50, which is where the in-repo deep-dive pointer will be added). Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
|
Run /check-rules locally to audit paraphrases against this diff. |
…oses #66) (#126) * docs: encoding loop method — hero infographic + skill + supporting infra The system behind "AI that codes the way I want" — the methodology canon for AI-assisted code that compounds quality. - docs/encoding-loop-hero.jpg: v16 hero (Nano Banana Pro at 2K). Navy + amber + cream. Signature ratchet wheel hub with 5 trigger entry points feeding into "Pick smallest surface." 5 surfaces ordered by enforcement strength (soft → strong). 3-tier spectrum. Live YAML CI gate. 6 disciplines (4 mechanical + 2 convention). Pandey-style numbered grid. - docs/encoding-loop-infographic.{excalidraw,svg}: canonical editable reference. Deterministic counterpart to the hero — same content, fully versionable, every text element exact. - CONTEXT.md: domain vocabulary glossary. Defines encoding loop, 5 surfaces, 3 tiers, mechanical floor, harness vs method, agentic coding tools. Pattern stolen from mattpocock/skills. Distinct from CLAUDE.md (rules) — this is vocabulary, not conventions. - .claude/commands/grid-infographic.md: new skill for the Nano Banana Pro pipeline at 2K. Includes blueprint-approval gate so content errors get caught before any API call (avoids burning generations on misframed prompts). - .claude/commands/*.md: disable-model-invocation: true on all six user-invoked slash commands. Stops them auto-firing on description match — they're explicit rituals, not assistive guesses. - .claude/scripts/render-hero.sh: deterministic HTML → PNG renderer via Playwright. Counterpart to rebuild-diagrams.sh for the Excalidraw pipeline. - docs/skill-bucket-organization.md: engineering / productivity bucket convention for .claude/commands/. Adapted from mattpocock/skills. - .gitignore: adds docs/post-ideas/ as the post-draft sandbox. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(audits): log miro-mcp-shared-context audit Same problem identified (AI lacks decision context); mechanism explicitly rejected via docs/dev-loop.md:583 ("MCP servers | Not building an MCP server") + :586 (Spec Kit per-feature flow as ceremony). Canon-in-repo is the project's answer. No action — optional one-line consolidation flagged for next dev-loop.md edit (MCP entry rationale is currently tautological). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(audits): log vsa-when-it-works audit Anton Martyniuk infographic on VSA "bad if" vs "amazing if" rules. Most rules aligned with NextAurora's encoding (no MediatR, no IHandler interface, simple handler class, no business logic in endpoint). Two material divergences: file granularity (NextAurora: 1 file per slice; Anton: 4 files per slice) and expected-error handling (NextAurora throws exceptions; Anton recommends Result<T>). Both NextAurora positions are intentional choices or unmade-decisions-by-default; neither warrants flipping. Three optional consolidations flagged for next CLAUDE.md edit: line-count soft cap on feature files, exception-vs-Result stance, no-IHandler-interface rationale. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs: consolidate audit-flagged rules across CLAUDE.md + dev-loop.md Encodes four rules surfaced by recent audits (Miro MCP, VSA-when-it-works): 1. dev-loop.md MCP servers row — replace tautological "Not building an MCP server" with the rationale (canon-in-repo + auto-load gives persistent decision context; MCP bridge is convergence-in-the-wrong-direction). Paraphrase in .github/AI_WORKFLOW.md mcp-builder row updated to match per the cross-reference rule. Source: 2026-06-07 Miro audit. 2. CLAUDE.md Project Structure — feature-file size soft cap (~300 lines). Co-location stays the canon; "giant file" warning is enforced via size cap, not file count per slice. Largest feature today (PlaceOrder.cs) is 182 lines. Source: 2026-06-08 VSA audit. 3. CLAUDE.md Key Conventions — exception-based control flow is the canon. No Result<T> / OneOf<T> / ErrorOr<T> discriminated-union error type. Defensible trigger to flip named (profiled exception cost in hot path OR saga step with high expected-failure rate). Source: 2026-06-08 VSA audit. 4. CLAUDE.md Communication Patterns — no IRequestHandler / IFooHandler interface per handler. Wolverine assembly-scans Features/ and binds message-type → handler-type directly; the MediatR-style "interface for testability" pattern doesn't apply (Wolverine's bus IS the abstraction). Source: 2026-06-08 VSA audit. All four rules pass the cross-reference grep (only one paraphrase found outside the edited files — AI_WORKFLOW.md MCP row, updated in this commit). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs: align AI_WORKFLOW mcp-builder row with new dev-loop.md MCP rationale Cross-reference cleanup that should have shipped with 360c879. The mcp-builder row in .github/AI_WORKFLOW.md was the only paraphrase of the dev-loop.md MCP-servers rule found by the cross-reference grep. Now consistent with the canonical wording. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(audits): log vsa-1-folder-4-files audit (Anton restatement) LinkedIn long-form version of yesterday's Anton Martyniuk VSA infographic. Same author, same core thesis — verdict and divergences identical to 2026-06-08-vsa-when-it-works.md. Today's post adds teaser content for tomorrow's newsletter (Shared/ folder rules, auto-registration, cross-slice events without MediatR, PublicApi pattern), which can't be audited until the actual newsletter ships. No new encoding work; the four rules from yesterday's audit shipped this morning in 360c879 + 9323aff. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(audits): log jwt-authentication-aspnet-core audit Mukesh Murugan's JWT-in-ASP.NET-Core walkthrough. Most claims aligned or out-of-scope (NextAurora uses Keycloak as IdP — signing key, login, refresh token aren't NextAurora's responsibility). One material divergence: ClockSkew (article: Zero for exact expiry; NextAurora: 30s to tolerate NTP drift while limiting linger). One consolidation flagged for next ServiceDefaults edit — explicit MapInboundClaims = false to make the claim-mapping flow auditable instead of relying on the Microsoft-flavored default. NextAurora's encoding is materially stricter on the adjacent authorization pattern: IDOR-prevention via predicate-in-WHERE-clause + 404-not-403 + integration test required, plus middleware order threading CorrelationIdMiddleware between auth and authz. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs: align dev-loop.md Promotion Signal table with CLAUDE.md (4 rows) dev-loop.md still carried the pre-#50 3-row table; CLAUDE.md's canonical version added the "architecture tests — NOT a project split" middle rung. Paraphrase now matches verbatim. Closes #66 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(docs): plain-text refs for gitignored paths — broken-link audit docs/post-ideas/ and .claude/audits/*.md are deliberately local-only (gitignored); markdown-linking them fails CI's broken-link audit. Convert to backtick path references — the pointer survives, the link contract doesn't. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Sharpens the CLAUDE.md "Promotion signal" section. A discussion surfaced that the prior framing ("Clean is earned / for complex services") conflated two separable things that both wear the name "Clean Architecture":
The added insight — enforcement is a spectrum
The real axis is how you enforce the dependency rule, escalating with the cost of a violated boundary: convention → architecture tests → project split. Names the middle rung most teams skip: an architecture test (NetArchTest / ArchUnitNET / Roslyn analyzer) asserting "Domain references no EF/Infrastructure namespaces" enforces the same boundary the 4-project split does — deterministically in CI, without the ceremony. So the split is rarely needed for enforcement alone — reach for it only when domain complexity makes you want the compiler (not a test) to hold the line, or when separate deploy/versioning units justify it.
Changes
Paraphrase-drift audit (per CLAUDE.md change)
Run
/check-ruleslocally to audit paraphrases against this diff. Done — the refinement is net-new nuance; no existingSee CLAUDE.mdmarker paraphrases the promotion signal or the dependency-rule-vs-structure distinction, and it's consistent with the "Layer Dependencies" rule it references. No drift.Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit