--- name: diagnose-slice description: Use this skill to diagnose why a Cratis slice misbehaves — read model not updating, TypeScript proxy missing, command rejected unexpectedly, projection/observer quarantined, AutoMap mismatch, reactor side effects not appended, or specs flaking. Symptom → likely cause → the rule/skill that owns the fix. Use when something "isn't working" and the cause isn't obvious. --- Symptom → likely cause → fix for the common ways a Cratis **application** slice misbehaves. Each row routes to the rule/skill that owns the detail — start there. Reproduce a real defect with a spec before and after the fix. ## Backend / Chronicle | Symptom | Likely cause | Fix → | | --- | --- | --- | | Read model query returns empty / stale | projection not wired: event→read-model property names differ (AutoMap only maps **matching** names), or a default value masks missing wiring | `add-projection`, `cratis-readmodel`; `[SetFrom]` for name diffs; no default values on `[ReadModel]` props | | App crashes on startup with a projection error | duplicate `[FromEvent]` for the same event on one read model | `add-projection` (one `[FromEvent]` per event) | | Command always "not successful" with **no** validation errors | `[Roles]`/authorization: an unauthorized result isn't successful and carries no validation errors | `auth-and-identity`, `cratis-command`; assert `ShouldNotBeAuthorized()` | | Command rejected unexpectedly | a `CommandValidator`/`ConceptValidator` rule, or `Provide()` short-circuited with `ValidationResult.Error` | `add-business-rule`, `cratis-command` | | Handler returns HTTP 500 instead of rejecting | threw from `Provide()`/`Handle()` for a *business* rule (that's an exception, not a rejection) | return `Result` — `add-business-rule` | | Reactor's returned events never appended | returned `EventForEventSourceId` on a Chronicle version before reactor support | return event objects, or `ReactorSideEffect` for another target — [reactors.md](https://github.com/Cratis/AI/blob/main/.ai/rules/reactors.md) | | Projection/reactor stops processing ("quarantined") | a handler threw; the partition paused and the observer quarantined (does **not** auto-resume) | read the failure off the server first — **inspect-running-chronicle**; then fix the handler (make it idempotent) and replay — [reactors.md](https://github.com/Cratis/AI/blob/main/.ai/rules/reactors.md) | | Duplicate side effect on replay | non-idempotent reactor without `[OnceOnly]` | mark the handler `[OnceOnly]` — [reactors.md](https://github.com/Cratis/AI/blob/main/.ai/rules/reactors.md) | | Chronicle analyzer warns on an event property | a nullable event property | model the optional fact as a **separate** event — [vertical-slices.md](https://github.com/Cratis/AI/blob/main/.ai/rules/vertical-slices.md), `event-modeling` | | A read model needs a field from another slice | wrong stream boundary / missing event | re-model (information completeness) — `event-modeling`; never cross-read another read model at runtime | ## Frontend / proxies | Symptom | Likely cause | Fix → | | --- | --- | --- | | TS can't find the command/query proxy (`Cannot find module`) | proxies regenerate on a **Debug** build; you only built Release | build Debug — `new-vertical-slice` (backend phase) | | Edited a generated file and it reverted | generated proxies (`// @generated by Cratis`) are never hand-edited | fix the C# source and rebuild — [general.md](https://github.com/Cratis/AI/blob/main/.ai/rules/general.md) | | `DataPage` won't show live data | passed a snapshot query, or expected a non-existent `observableQuery` prop | pass the observable query to the single `query` prop (auto-detected) — `cratis-react-page`, [components.md](https://github.com/Cratis/AI/blob/main/.ai/rules/components.md) | | Dialog/dropdown renders behind an overlay | used raw `primereact/dialog` or `primereact/dropdown` | use the Cratis wrappers from `@cratis/components/*` — [dialogs.md](https://github.com/Cratis/AI/blob/main/.ai/rules/dialogs.md), [components.md](https://github.com/Cratis/AI/blob/main/.ai/rules/components.md) | ## Specs | Symptom | Likely cause | Fix → | | --- | --- | --- | | Spec code leaks into a Release build | spec not wrapped in `#if DEBUG … #endif` | wrap the file — [specs.scenarios.csharp.md](https://github.com/Cratis/AI/blob/main/.ai/rules/specs.scenarios.csharp.md) | | Off-by-one in event-tail assertions | sequence numbers are **zero-based** (tail of one event is `0`) | [specs.scenarios.csharp.md](https://github.com/Cratis/AI/blob/main/.ai/rules/specs.scenarios.csharp.md) | | Order-dependent flake on a uniqueness rule | a hardcoded value collides across tests | use a per-test value (`Guid.NewGuid()`); don't reach for `[Collection]` for collisions — [specs.scenarios.csharp.md](https://github.com/Cratis/AI/blob/main/.ai/rules/specs.scenarios.csharp.md) | ## When the symptom is only visible on a running server Everything above is diagnosed from the code. When the read model is stale **in a deployed store** and the same slice behaves locally, the answer is in the server's own state rather than the source — a failed partition carrying the exception that stopped it, an observer that never registered, an event that was never appended. Use **inspect-running-chronicle**; the `cratis` CLI reads all of it. The distinction that matters: a failed partition does not retry itself, so what looks like "the projection is slow" is usually "the projection stopped, permanently, with a recorded reason nobody has read". ## When nothing here fits Re-read the owning rule ([vertical-slices.md](https://github.com/Cratis/AI/blob/main/.ai/rules/vertical-slices.md), [reactors.md](https://github.com/Cratis/AI/blob/main/.ai/rules/reactors.md), or the `cratis-readmodel` skill), confirm the build is clean in **both Debug and Release**, and reproduce the symptom with a spec. Don't infer framework behavior from package internals — if the rules/skills don't answer it, ask.