Закрывает две связанные дыры «claim-then-side-effect» в раскладке хардлинками. MINOR-7: transition глотал ошибку записи состояния — на путях Apply и авто-раскладки выполнение продолжалось к хардлинкам при незакоммиченном claim перехода в linking, а финальный linking→done отклонялся графом (задача застревала со stale-планом). Выделен transitionErr, возвращающий ошибку; Apply и finishRecognition прерываются ДО linkPlan при провале claim. Обёртка transition (void) сохранена для fire-and-forget переходов — соседние функции воркера не тронуты. MAJOR-4: (A) провал CreateFileLinks после создания хардлинков больше не оставляет задачу в linking голым return — уводим в review (код persist), повтор Apply идемпотентен. (B) новый шаг pollOnce sweepLinking возвращает осиротевшие после краха linking-задачи в review (код interrupted) на тике и старте; любая linking под w.mu устарела по построению. Восстановлен инвариант «у каждого нетерминального состояния есть владелец». Граф переходов не тронут (ребро linking→review уже объявлено). Тесты: провал claim не создаёт хардлинков; провал учёта уводит в review; sweep осиротевшего linking. OpenSpec-change linking-transition-robustness (дельты file-layout, state-reconciliation). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
35 lines
1.9 KiB
Markdown
35 lines
1.9 KiB
Markdown
## 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` проходит
|