diff --git a/.claude/skills/chat-system/SKILL.md b/.claude/skills/chat-system/SKILL.md index ec3b0027db8..9444fe6ebb5 100644 --- a/.claude/skills/chat-system/SKILL.md +++ b/.claude/skills/chat-system/SKILL.md @@ -75,6 +75,12 @@ Each decorator wraps `origin.Send()` and forwards `origin.MessageAdded` events, --- +## Rooms & local scene development + +Comms rooms are wired in `CommsContainer.Create`. In **local scene development** the Friends subsystem is disabled, so the LiveKit **chat room** (the transport that carries DMs) must not be connected at all: `CommsContainer` passes `IConnectiveRoom.Null.INSTANCE` for the chat room in that mode, exactly as it already does for the archipelago island room. Gate the connection **at the source** โ€” do not connect the room and then drop inbound DMs downstream, which leaves an unanswerable conversation half-alive. `PrivateConversationUserStateService.InitializeAsync` must also early-return when `FeatureId.LocalSceneDevelopment` is enabled, because waiting on a room that never connects only burns the timeout and logs a spurious error. + +--- + ## Chat Command Pattern ### Interface diff --git a/CLAUDE.md b/CLAUDE.md index 860b658407e..7685a3894b8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -144,6 +144,7 @@ Reviewers have repeatedly identified AI-generated code by these smells. Check yo * **Reimplementing primitives that already exist.** Before writing manual atlas UV math, check `TMP_Sprite Asset`. Before hand-batching profile lookups, check the batched `GetProfilesAsync(IReadOnlyList, ct)` overload. Before adding a bespoke event pathway, check `ViewEventBus` / `ChatEvents`. * **Comments that narrate caller/external behavior.** A comment must state only what the annotated code itself does or guarantees ("remove the corrupt file so the next read doesn't hit it"), never what callers or upper layers will do with the result ("so callers treat it as a miss and re-download"). External behavior can change without this code changing, silently turning the comment into a lie. * **Suppressing `CheckNamespace` with a ReSharper comment.** Never add `// ReSharper disable once CheckNamespace` (or the file-wide variant) โ€” fix the namespace or leave the warning visible. Rationale and full rule: [`docs/code-style-guidelines.md` ยง Namespaces](docs/code-style-guidelines.md#namespaces). +* **Encoding a transient fetch failure as a permanent capability downgrade.** When an asset or metadata fetch fails, don't flip a flag that the item's authoritative DTO owns โ€” e.g. setting `IsSmart = false` on a smart wearable whose `scene.json` was missing turns a recoverable content miss into a wrong, sticky classification. Keep the DTO-declared flag, log the failure with the item id, and **evict the half-built cache entry** (`cache.Remove(id)`) so the next request re-fetches it instead of being served the poisoned entry. (`SmartWearableCache` was corrected this way: keep `IsSmart` true, log, and evict rather than downgrade.) ### Other project-specific rules