- internal/model: единый источник статусов задачи (Status, TraceStatus, машина переходов), без зависимости от storage. - internal/storage: совместимый мост (type Status = model.Status, re-export констант) — внешний код не меняется. - internal/events: шина событий (fan-out, блокирующий Publish с гарантией порядка), события задач/трейсов, отдельная логовая шина + LogWriter, Publisher/NilPublisher для внедрения в Core/Worker. - docs/ui-spec.md: спецификация десктопного UI (Fyne).
77 lines
3.8 KiB
Go
77 lines
3.8 KiB
Go
// Package model — доменные типы и контракты Ratatoskr.
|
||
//
|
||
// Нижний слой архитектуры: не зависит ни от БД (storage), ни от UI (events).
|
||
// Хранит семантику предметной области (статусы задач, машина переходов),
|
||
// чтобы storage и events зависели только от этой модели, а не друг от друга.
|
||
package model
|
||
|
||
// Status — статус задачи (state machine).
|
||
type Status string
|
||
|
||
const (
|
||
StatusDraft Status = "draft" // только что создана
|
||
StatusCollecting Status = "collecting" // аналитик собирает детали
|
||
StatusReady Status = "ready" // черновик готов, ждёт одобрения пользователя
|
||
StatusApproved Status = "approved" // пользователь одобрил («создавай») — воркер берёт в работу
|
||
StatusRunning Status = "running" // opencode работает
|
||
StatusSuccess Status = "success" // задача выполнена
|
||
StatusFailed Status = "failed" // ошибка выполнения
|
||
StatusTimeout Status = "timeout" // таймаут opencode
|
||
StatusCancelled Status = "cancelled" // отменена пользователем
|
||
StatusAborted Status = "aborted" // сбой сбора, черновик выброшен
|
||
StatusClosed Status = "closed" // закрыта вручную
|
||
)
|
||
|
||
// AllStatuses — все возможные статусы для валидации.
|
||
var AllStatuses = []Status{
|
||
StatusDraft, StatusCollecting, StatusReady, StatusApproved,
|
||
StatusRunning, StatusSuccess, StatusFailed, StatusTimeout,
|
||
StatusCancelled, StatusAborted, StatusClosed,
|
||
}
|
||
|
||
// validTransitions задаёт разрешённые переходы статусов.
|
||
var validTransitions = map[Status][]Status{
|
||
StatusDraft: {StatusCollecting, StatusCancelled, StatusAborted},
|
||
StatusCollecting: {StatusReady, StatusDraft, StatusCancelled, StatusAborted},
|
||
// ready — черновик готов: «создавай» → approved, либо правка/отмена/закрытие.
|
||
StatusReady: {StatusApproved, StatusCancelled, StatusAborted, StatusClosed, StatusCollecting},
|
||
// approved — финальное одобрение: воркер берёт в running, либо отмена/сбой/закрытие.
|
||
StatusApproved: {StatusRunning, StatusCancelled, StatusAborted, StatusClosed},
|
||
StatusRunning: {StatusSuccess, StatusFailed, StatusTimeout, StatusCancelled},
|
||
StatusSuccess: {StatusClosed},
|
||
StatusFailed: {StatusReady, StatusClosed, StatusCancelled, StatusCollecting}, // retry: перезапуск сбора
|
||
StatusTimeout: {StatusReady, StatusClosed, StatusCancelled, StatusCollecting}, // retry: перезапуск сбора
|
||
StatusCancelled: {StatusClosed},
|
||
StatusAborted: {StatusClosed},
|
||
StatusClosed: {}, // терминальный
|
||
}
|
||
|
||
// IsValidTransition проверяет, допустим ли переход from → to.
|
||
func IsValidTransition(from, to Status) bool {
|
||
allowed, ok := validTransitions[from]
|
||
if !ok {
|
||
return false
|
||
}
|
||
for _, s := range allowed {
|
||
if s == to {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// IsTerminal возвращает true, если статус терминальный.
|
||
func IsTerminal(s Status) bool {
|
||
return s == StatusSuccess || s == StatusCancelled ||
|
||
s == StatusAborted || s == StatusClosed
|
||
}
|
||
|
||
// TraceStatus — статус трассировки субагента.
|
||
type TraceStatus string
|
||
|
||
const (
|
||
TraceRunning TraceStatus = "running"
|
||
TraceSuccess TraceStatus = "success"
|
||
TraceFailed TraceStatus = "failed"
|
||
TraceTimeout TraceStatus = "timeout"
|
||
) |