Maintained in timewarp-architecture · Canonical file: SKILL.md

Install

npx skills add TimeWarpEngineering/timewarp-architecture --skill slice-isolation

Or copy the SKILL.md into your agent's skills directory.


Slice isolation (TWA0009)

Slices are independently removable vertical units. Folders organize humans; the namespace under SliceRoot is the law. Analyzer TWA0009 is the reactive safety net; this skill is for correct first placement so greenfield work does not couple product areas by accident.

Enforcement ships in TimeWarp.Architecture.Analyzers (and monorepo ProjectReference). Do not re-interpret rules here — mirror the analyzer.

Detection — when to invoke

Signal How to find it
Product area under features/ web-spa/features/…, web-contracts/features/…
Namespace under SliceRoot …Features.<Id> (or nested …Features.Admin.Roles)
TWA0009 / CrossSliceReference diagnostic text or attribute on a type
“Where does this page/state live?” any new product capability before scaffolding

Terms

Term Meaning
Slice Removable vertical capability; the isolation unit
Feature Informal product language only — not the analyzer’s unit name
Module IModule / host DI composition — not a product slice

Prefer saying slice in diagnostics, opt-outs, and agent prose. Namespace path may still use …Features.* (familiar VSA / contracts layout).

SliceRoot

Setting Value
Default {RootNamespace}.Features (from MSBuild RootNamespace)
Override MSBuild property TimeWarpSliceRoot (must be CompilerVisibleProperty)

Slice id = path under SliceRoot after stripping structural suffixes Pages, Components, Application. Nested ids are the full path:

Namespace Slice id / tier
…Features Substrate (bare root)
…Features.Applications Platform id Applications
…Features.Counters Product id Counters
…Features.Counters.Pages Product id Counters (suffix stripped)
…Features.Admin.Roles Product id Admin.Roles
…Components, layouts, app root types Outside SliceRoot

Folders usually mirror slices (features/counter/…Features.Counters) but moving a file does not change legal dependencies — only the namespace does.

Tiers (dependency rules)

Tier Example May reference
Outside …Components, shell, layouts Anything (composition free)
Substrate bare …Features (BaseComponent, shared base types) Outside, substrate, platform — not product without opt-out
Platform …Features.Applications Outside, substrate, platform — not product without opt-out
Product …Features.Counters, …Features.Admin.Roles Outside, substrate, platform, own product id, contracts (other assembly). Not another product id without opt-out

Forbidden without opt-out (TWA0009):

Free by design:

Placement matrix

Artifact Where
Page, state, actions, slice-local UI Inside the product slice namespace
App chrome / shell / empty MainLayout Outside SliceRoot (e.g. …Components) — see blazor-layout
Shared UI used by multiple slices components/ → namespace outside SliceRoot
Shared API shapes Contracts project (other assembly; free under TWA0009)
Host-wide modal / menu / branding state Platform Applications

Living anchors (timewarp-architecture template):

Role Path Namespace
Product web-spa/features/counter/ …Features.Counters
Nested product web-spa/features/admin/roles/ …Features.Admin.Roles
Platform web-spa/features/application/ …Features.Applications
Substrate web-spa/features/base/base-component.cs …Features
Outside shell web-spa/components/TimeWarpPage.razor …Components

Greenfield scaffold workflow

  1. Name the slice — plural, domain-oriented (Clients, Admin.Roles).
  2. Folder — kebab path under the project’s features/ tree (match sibling casing).
  3. Namespace{RootNamespace}.Features.{SliceId} (plural segments; nested with .).
  4. Colocate page, state, actions, and slice-private components in that namespace (pages are not shared infrastructure — no grab-bag …Pages for product UI).
  5. Contracts — same plural feature path under the contracts project (web-api-contracts skill). Other assembly → free across SPA slices.
  6. Wire nav / DI from Outside or platform — not from another product slice.
  7. Prefer share (Components / contracts) over [CrossSliceReference].
  8. Build — fix TWA0009 by relocating code first; mute only for deliberate demo/integration edges.

Share vs opt-out

Prefer share

Opt-out — deliberate edges only

using TimeWarp.Foundation.Features;

[CrossSliceReference(typeof(CounterState), "Living style guide exercises the counter throw-exception pipeline.")]
partial class StyleGuidePage;

Rules:

Living examples:

Limits agents must know

Limit Implication
Same assembly only Contracts / NuGet metadata types never trip TWA0009
Hand-written C# GeneratedCodeAnalysisFlags.None — pure .razor without .razor.cs is not scanned; put deliberate edges on code-behind
Folders can lie Namespace still owns the type
Structural suffixes …Counters.Pages is still product id Counters

Good / bad examples

Bad Why Fix
…Features.Counters type uses WeatherForecastsState product → product Share via Components/contracts, or reasoned [CrossSliceReference]
Product page in grab-bag …Pages outside any slice not removable with the capability Namespace under …Features.<Id>
Platform type reaches into Counters platform ↛ product Invert dependency (product → platform) or rare opt-out on platform type
Mute TWA0009 globally / without reason hides real coupling Relocate or scoped opt-out
Good Why
CounterPage uses ApplicationState product → platform free
TimeWarpPage in …Components Outside composition free
Admin.Roles only uses own types + contracts + platform nested product isolation

Agent checklist