## 1. Возврат ошибки перехода (MINOR-7) - [x] 1.1 Разделить `transition` на `void`-обёртку и `transitionErr` (возвращает ошибку записи); пинги/скан — в `transitionErr` - [x] 1.2 `Apply`: заменить claim `transition(StateLinking)` на `transitionErr` с прерыванием до `linkPlan` при ошибке - [x] 1.3 `finishRecognition` (авто-раскладка): то же — при провале claim остаёмся в `recognizing`, `linkPlan` не зовём ## 2. Провал учёта не оставляет в linking (MAJOR-4 A) - [x] 2.1 В `linkPlan` при провале `CreateFileLinks` перевести задачу в `review` (код `persist`) вместо голого `return` ## 3. Sweep осиротевшего linking (MAJOR-4 B) - [x] 3.1 Добавить `sweepLinking`: под `w.mu` листить `linking` и переводить `linking → review` (код `interrupted`, причина «прерванная раскладка, повтори применение») - [x] 3.2 Вызвать `sweepLinking` в `pollOnce` (тик + старт) ## 4. Тесты - [x] 4.1 Провал claim перехода в `linking` прерывает `Apply` до хардлинков (нет файлов на диске, нет `file_link`, состояние `review`) - [x] 4.2 Провал `CreateFileLinks` уводит в `review` (файлы на диске есть, код `persist`) - [x] 4.3 `sweepLinking` переводит осиротевший `linking` в `review` (код `interrupted`); прочие состояния не задевает ## 5. Проверки - [x] 5.1 `task test` и `task lint` проходят - [x] 5.2 `openspec validate linking-transition-robustness --strict` проходит