Documentation
¶
Overview ¶
ABOUTME: Goroutine-based actor for processing spec commands and broadcasting events. ABOUTME: Provides SpecActorHandle for sending commands, subscribing to events, and reading state.
ABOUTME: Sentinel errors for the spec actor command validation. ABOUTME: Maps to barnstormer's ActorError enum variants.
ABOUTME: Card represents a kanban card with type, lane, ordering, and authorship. ABOUTME: Cards are the primary content units within a specification's board.
ABOUTME: Command is a tagged union representing all mutations to a spec. ABOUTME: 12 variants with custom JSON marshal/unmarshal using "type" discriminator.
ABOUTME: Event is the envelope for all spec mutations, wrapping EventPayload variants. ABOUTME: 13 EventPayload variants with tagged union JSON serialization via "type" discriminator.
ABOUTME: SpecCore holds the top-level metadata for a specification. ABOUTME: Three required fields (title, one_liner, goal) plus five optional detail fields.
ABOUTME: OptionalField[T] implements 3-state JSON semantics: absent, null, or value. ABOUTME: This solves the "null vs missing" problem for partial update APIs.
ABOUTME: OrderedMap provides a sorted map keyed by comparable types. ABOUTME: Equivalent to Rust's BTreeMap, used for deterministic card ordering by ULID.
ABOUTME: SpecState is the materialized state of a spec, built by replaying events. ABOUTME: The Apply method is a pattern-matching state reducer that folds events into state.
ABOUTME: Transcript types for agent/human communication within a spec. ABOUTME: Includes MessageKind, TranscriptMessage, and UserQuestion (3 variants).
ABOUTME: ULID generation helper using crypto/rand for monotonic IDs. ABOUTME: Centralizes ULID creation so all code uses the same entropy source.
Index ¶
- Variables
- func MarshalCommand(c Command) ([]byte, error)
- func MarshalEventPayload(p EventPayload) ([]byte, error)
- func MarshalUserQuestion(q UserQuestion) ([]byte, error)
- func NewULID() ulid.ULID
- type AgentStepFinishedPayload
- type AgentStepStartedPayload
- type AnswerQuestionCommand
- type AppendTranscriptCommand
- type AskQuestionCommand
- type BooleanQuestion
- type Card
- type CardCreatedPayload
- type CardDeletedPayload
- type CardMovedPayload
- type CardNotFoundError
- type CardUpdatedPayload
- type Command
- type CreateCardCommand
- type CreateSpecCommand
- type DeleteCardCommand
- type Event
- type EventBroadcaster
- type EventPayload
- type FinishAgentStepCommand
- type FreeformQuestion
- type MessageKind
- type MoveCardCommand
- type MultipleChoiceQuestion
- type OptionalField
- type OrderedMap
- func (m *OrderedMap[K, V]) Clone() *OrderedMap[K, V]
- func (m *OrderedMap[K, V]) Delete(key K)
- func (m *OrderedMap[K, V]) Get(key K) (V, bool)
- func (m *OrderedMap[K, V]) Keys() []K
- func (m *OrderedMap[K, V]) Len() int
- func (m *OrderedMap[K, V]) MarshalJSON() ([]byte, error)
- func (m *OrderedMap[K, V]) Range(fn func(K, V) bool)
- func (m *OrderedMap[K, V]) Set(key K, val V)
- func (m *OrderedMap[K, V]) Values() []V
- type QuestionAnsweredPayload
- type QuestionAskedPayload
- type QuestionIDMismatchError
- type SnapshotWrittenPayload
- type SpecActorHandle
- type SpecCore
- type SpecCoreUpdatedPayload
- type SpecCreatedPayload
- type SpecState
- type StartAgentStepCommand
- type TranscriptAppendedPayload
- type TranscriptMessage
- type UndoAppliedPayload
- type UndoCommand
- type UndoEntry
- type UpdateCardCommand
- type UpdateSpecCoreCommand
- type UserQuestion
Constants ¶
This section is empty.
Variables ¶
var ( // ErrSpecNotCreated indicates a command requires a spec that hasn't been created yet. ErrSpecNotCreated = errors.New("spec not yet created") // ErrQuestionAlreadyPending indicates a question is already waiting for an answer. ErrQuestionAlreadyPending = errors.New("a question is already pending") // ErrNoPendingQuestion indicates there's no question to answer. ErrNoPendingQuestion = errors.New("no pending question to answer") // ErrNothingToUndo indicates the undo stack is empty. ErrNothingToUndo = errors.New("nothing to undo") // ErrChannelClosed indicates the actor's command channel was closed. ErrChannelClosed = errors.New("actor channel closed") // ErrActorBusy indicates the actor's command buffer is full. ErrActorBusy = errors.New("actor command buffer full") // ErrUnknownCommand indicates the command type is not recognized by the actor. ErrUnknownCommand = errors.New("unknown command type") )
Functions ¶
func MarshalCommand ¶
MarshalCommand serializes a Command with a "type" discriminator field.
func MarshalEventPayload ¶
func MarshalEventPayload(p EventPayload) ([]byte, error)
MarshalEventPayload serializes an EventPayload with a "type" discriminator.
func MarshalUserQuestion ¶
func MarshalUserQuestion(q UserQuestion) ([]byte, error)
MarshalUserQuestion serializes a UserQuestion with a "type" discriminator.
Types ¶
type AgentStepFinishedPayload ¶
type AgentStepFinishedPayload struct {
AgentID string `json:"agent_id"`
DiffSummary string `json:"diff_summary"`
}
AgentStepFinishedPayload indicates an agent completed a work step.
func (AgentStepFinishedPayload) EventPayloadType ¶
func (p AgentStepFinishedPayload) EventPayloadType() string
type AgentStepStartedPayload ¶
type AgentStepStartedPayload struct {
AgentID string `json:"agent_id"`
Description string `json:"description"`
}
AgentStepStartedPayload indicates an agent began a work step.
func (AgentStepStartedPayload) EventPayloadType ¶
func (p AgentStepStartedPayload) EventPayloadType() string
type AnswerQuestionCommand ¶
type AnswerQuestionCommand struct {
QuestionID ulid.ULID `json:"question_id"`
Answer string `json:"answer"`
}
AnswerQuestionCommand answers a pending question.
func (AnswerQuestionCommand) CommandType ¶
func (c AnswerQuestionCommand) CommandType() string
type AppendTranscriptCommand ¶
type AppendTranscriptCommand struct {
Sender string `json:"sender"`
Content string `json:"content"`
}
AppendTranscriptCommand adds a message to the transcript.
func (AppendTranscriptCommand) CommandType ¶
func (c AppendTranscriptCommand) CommandType() string
type AskQuestionCommand ¶
type AskQuestionCommand struct {
Question UserQuestion `json:"-"` // Custom marshal handles this
}
AskQuestionCommand presents a question to the human user.
func (AskQuestionCommand) CommandType ¶
func (c AskQuestionCommand) CommandType() string
type BooleanQuestion ¶
type BooleanQuestion struct {
QID ulid.ULID `json:"question_id"`
Question string `json:"question"`
Default *bool `json:"default,omitempty"`
}
BooleanQuestion asks the user a yes/no question.
func (BooleanQuestion) QuestionID ¶
func (q BooleanQuestion) QuestionID() ulid.ULID
func (BooleanQuestion) QuestionType ¶
func (q BooleanQuestion) QuestionType() string
type Card ¶
type Card struct {
CardID ulid.ULID `json:"card_id"`
CardType string `json:"card_type"`
Title string `json:"title"`
Body *string `json:"body,omitempty"`
Lane string `json:"lane"`
Order float64 `json:"order"`
Refs []string `json:"refs"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
CreatedBy string `json:"created_by"`
UpdatedBy string `json:"updated_by"`
}
Card represents a kanban-style card within a spec. Mirrors barnstormer's Card struct with identical JSON field names.
type CardCreatedPayload ¶
type CardCreatedPayload struct {
Card Card `json:"card"`
}
CardCreatedPayload indicates a new card was created.
func (CardCreatedPayload) EventPayloadType ¶
func (p CardCreatedPayload) EventPayloadType() string
type CardDeletedPayload ¶
type CardDeletedPayload struct {
CardID ulid.ULID `json:"card_id"`
UpdatedBy string `json:"updated_by,omitempty"`
}
CardDeletedPayload indicates a card was removed.
func (CardDeletedPayload) EventPayloadType ¶
func (p CardDeletedPayload) EventPayloadType() string
type CardMovedPayload ¶
type CardMovedPayload struct {
CardID ulid.ULID `json:"card_id"`
Lane string `json:"lane"`
Order float64 `json:"order"`
UpdatedBy string `json:"updated_by,omitempty"`
}
CardMovedPayload indicates a card was moved to a new lane/position.
func (CardMovedPayload) EventPayloadType ¶
func (p CardMovedPayload) EventPayloadType() string
type CardNotFoundError ¶
CardNotFoundError indicates the referenced card doesn't exist.
func (*CardNotFoundError) Error ¶
func (e *CardNotFoundError) Error() string
type CardUpdatedPayload ¶
type CardUpdatedPayload struct {
CardID ulid.ULID `json:"card_id"`
Title *string `json:"title,omitempty"`
Body OptionalField[string] `json:"-"` // Custom marshal
CardType *string `json:"card_type,omitempty"`
Refs *[]string `json:"refs,omitempty"`
UpdatedBy string `json:"updated_by,omitempty"`
}
CardUpdatedPayload indicates a card was updated. Body uses OptionalField for 3-state semantics.
func (CardUpdatedPayload) EventPayloadType ¶
func (p CardUpdatedPayload) EventPayloadType() string
type Command ¶
type Command interface {
CommandType() string
// contains filtered or unexported methods
}
Command represents a mutation intent for a spec. Tagged union with 12 variants.
func UnmarshalCommand ¶
UnmarshalCommand deserializes a Command from JSON with a "type" discriminator.
type CreateCardCommand ¶
type CreateCardCommand struct {
CardType string `json:"card_type"`
Title string `json:"title"`
Body *string `json:"body,omitempty"`
Lane *string `json:"lane,omitempty"`
CreatedBy string `json:"created_by"`
}
CreateCardCommand creates a new card on the board.
func (CreateCardCommand) CommandType ¶
func (c CreateCardCommand) CommandType() string
type CreateSpecCommand ¶
type CreateSpecCommand struct {
Title string `json:"title"`
OneLiner string `json:"one_liner"`
Goal string `json:"goal"`
}
CreateSpecCommand creates a new spec with required fields.
func (CreateSpecCommand) CommandType ¶
func (c CreateSpecCommand) CommandType() string
type DeleteCardCommand ¶
type DeleteCardCommand struct {
CardID ulid.ULID `json:"card_id"`
UpdatedBy string `json:"updated_by"`
}
DeleteCardCommand removes a card from the board.
func (DeleteCardCommand) CommandType ¶
func (c DeleteCardCommand) CommandType() string
type Event ¶
type Event struct {
EventID uint64 `json:"event_id"`
SpecID ulid.ULID `json:"spec_id"`
Timestamp time.Time `json:"timestamp"`
Payload EventPayload `json:"-"` // Custom marshal/unmarshal
}
Event is the immutable envelope for a spec mutation.
func (Event) MarshalJSON ¶
MarshalJSON serializes the Event with its payload inlined.
func (*Event) UnmarshalJSON ¶
UnmarshalJSON deserializes the Event with its payload.
type EventBroadcaster ¶
type EventBroadcaster struct {
// contains filtered or unexported fields
}
EventBroadcaster provides a fan-out mechanism for events to multiple subscribers. Each subscriber gets a buffered channel. Broadcast is non-blocking (drops if full).
func NewEventBroadcaster ¶
func NewEventBroadcaster() *EventBroadcaster
NewEventBroadcaster creates a broadcaster with no initial subscribers.
func (*EventBroadcaster) Broadcast ¶
func (b *EventBroadcaster) Broadcast(event Event)
Broadcast sends an event to all subscribers. Non-blocking: drops if a subscriber's buffer is full.
func (*EventBroadcaster) Subscribe ¶
func (b *EventBroadcaster) Subscribe() chan Event
Subscribe creates a new buffered channel for receiving broadcast events.
func (*EventBroadcaster) Unsubscribe ¶
func (b *EventBroadcaster) Unsubscribe(ch chan Event)
Unsubscribe removes a channel from the subscriber list and closes it.
type EventPayload ¶
type EventPayload interface {
EventPayloadType() string
// contains filtered or unexported methods
}
EventPayload is a tagged union representing the 13 event variants.
func UnmarshalEventPayload ¶
func UnmarshalEventPayload(data []byte) (EventPayload, error)
UnmarshalEventPayload deserializes an EventPayload from JSON with a "type" discriminator.
type FinishAgentStepCommand ¶
type FinishAgentStepCommand struct {
AgentID string `json:"agent_id"`
DiffSummary string `json:"diff_summary"`
}
FinishAgentStepCommand marks the end of an agent's work step.
func (FinishAgentStepCommand) CommandType ¶
func (c FinishAgentStepCommand) CommandType() string
type FreeformQuestion ¶
type FreeformQuestion struct {
QID ulid.ULID `json:"question_id"`
Question string `json:"question"`
Placeholder *string `json:"placeholder,omitempty"`
ValidationHint *string `json:"validation_hint,omitempty"`
}
FreeformQuestion asks the user for open-ended text input.
func (FreeformQuestion) QuestionID ¶
func (q FreeformQuestion) QuestionID() ulid.ULID
func (FreeformQuestion) QuestionType ¶
func (q FreeformQuestion) QuestionType() string
type MessageKind ¶
type MessageKind string
MessageKind categorizes transcript messages for rendering.
const ( MessageKindChat MessageKind = "Chat" MessageKindStepStarted MessageKind = "StepStarted" MessageKindStepFinished MessageKind = "StepFinished" )
func (MessageKind) IsStep ¶
func (k MessageKind) IsStep() bool
IsStep returns true if this is a step-related message kind.
func (MessageKind) Prefix ¶
func (k MessageKind) Prefix() string
Prefix returns a display prefix for the message kind.
type MoveCardCommand ¶
type MoveCardCommand struct {
CardID ulid.ULID `json:"card_id"`
Lane string `json:"lane"`
Order float64 `json:"order"`
UpdatedBy string `json:"updated_by"`
}
MoveCardCommand moves a card to a different lane/position.
func (MoveCardCommand) CommandType ¶
func (c MoveCardCommand) CommandType() string
type MultipleChoiceQuestion ¶
type MultipleChoiceQuestion struct {
QID ulid.ULID `json:"question_id"`
Question string `json:"question"`
Choices []string `json:"choices"`
AllowMulti bool `json:"allow_multi"`
}
MultipleChoiceQuestion asks the user to pick from a list.
func (MultipleChoiceQuestion) QuestionID ¶
func (q MultipleChoiceQuestion) QuestionID() ulid.ULID
func (MultipleChoiceQuestion) QuestionType ¶
func (q MultipleChoiceQuestion) QuestionType() string
type OptionalField ¶
type OptionalField[T any] struct { Set bool // Was this field present in the JSON? Valid bool // Is the value non-null? Value T }
OptionalField represents a field that can be absent, explicitly null, or have a value. This maps to Rust's Option<Option<T>> pattern used in UpdateCard.body and CardUpdated.body.
- Set=false: field absent from JSON (don't update)
- Set=true, Valid=false: field is JSON null (clear the value)
- Set=true, Valid=true: field has a value (set to Value)
func Absent ¶
func Absent[T any]() OptionalField[T]
Absent returns an OptionalField that represents a missing field.
func Null ¶
func Null[T any]() OptionalField[T]
Null returns an OptionalField that represents an explicit null.
func Present ¶
func Present[T any](v T) OptionalField[T]
Present returns an OptionalField with a concrete value.
func (OptionalField[T]) MarshalJSON ¶
func (o OptionalField[T]) MarshalJSON() ([]byte, error)
MarshalJSON only emits JSON when the field is Set. If Set && !Valid, emits null. If Set && Valid, emits the value.
func (*OptionalField[T]) UnmarshalJSON ¶
func (o *OptionalField[T]) UnmarshalJSON(data []byte) error
UnmarshalJSON sets the field state based on the JSON value. A JSON null sets Set=true, Valid=false. Any other value sets both true.
type OrderedMap ¶
type OrderedMap[K interface {
comparable
String() string
}, V any] struct {
// contains filtered or unexported fields
}
OrderedMap maintains keys in sorted order, equivalent to BTreeMap in Rust. K must be comparable and support ordering via sort. In practice, K is ulid.ULID which implements fmt.Stringer for consistent ordering.
func NewOrderedMap ¶
func NewOrderedMap[K interface {
comparable
String() string
}, V any]() *OrderedMap[K, V]
NewOrderedMap creates an empty OrderedMap.
func (*OrderedMap[K, V]) Clone ¶
func (m *OrderedMap[K, V]) Clone() *OrderedMap[K, V]
Clone returns a shallow copy of the map.
func (*OrderedMap[K, V]) Delete ¶
func (m *OrderedMap[K, V]) Delete(key K)
Delete removes a key-value pair.
func (*OrderedMap[K, V]) Get ¶
func (m *OrderedMap[K, V]) Get(key K) (V, bool)
Get retrieves a value by key. Returns the value and whether it was found.
func (*OrderedMap[K, V]) Keys ¶
func (m *OrderedMap[K, V]) Keys() []K
Keys returns all keys in sorted order.
func (*OrderedMap[K, V]) Len ¶
func (m *OrderedMap[K, V]) Len() int
Len returns the number of entries.
func (*OrderedMap[K, V]) MarshalJSON ¶
func (m *OrderedMap[K, V]) MarshalJSON() ([]byte, error)
MarshalJSON serializes the map as a JSON object with sorted keys.
func (*OrderedMap[K, V]) Range ¶
func (m *OrderedMap[K, V]) Range(fn func(K, V) bool)
Range iterates over entries in sorted key order. Return false to stop.
func (*OrderedMap[K, V]) Set ¶
func (m *OrderedMap[K, V]) Set(key K, val V)
Set inserts or updates a key-value pair, maintaining sorted key order.
func (*OrderedMap[K, V]) Values ¶
func (m *OrderedMap[K, V]) Values() []V
Values returns all values in key-sorted order.
type QuestionAnsweredPayload ¶
type QuestionAnsweredPayload struct {
QuestionID ulid.ULID `json:"question_id"`
Answer string `json:"answer"`
}
QuestionAnsweredPayload indicates a pending question was answered.
func (QuestionAnsweredPayload) EventPayloadType ¶
func (p QuestionAnsweredPayload) EventPayloadType() string
type QuestionAskedPayload ¶
type QuestionAskedPayload struct {
Question UserQuestion `json:"-"` // Custom marshal
}
QuestionAskedPayload indicates a question was posed to the user.
func (QuestionAskedPayload) EventPayloadType ¶
func (p QuestionAskedPayload) EventPayloadType() string
type QuestionIDMismatchError ¶
QuestionIDMismatchError indicates the answered question ID doesn't match the pending one.
func (*QuestionIDMismatchError) Error ¶
func (e *QuestionIDMismatchError) Error() string
type SnapshotWrittenPayload ¶
type SnapshotWrittenPayload struct {
SnapshotID uint64 `json:"snapshot_id"`
}
SnapshotWrittenPayload indicates a state snapshot was saved.
func (SnapshotWrittenPayload) EventPayloadType ¶
func (p SnapshotWrittenPayload) EventPayloadType() string
type SpecActorHandle ¶
SpecActorHandle is the public interface for interacting with a spec actor. It is safe for concurrent use.
func SpawnActor ¶
func SpawnActor(specID ulid.ULID, initialState *SpecState) *SpecActorHandle
SpawnActor creates a new SpecActor goroutine and returns the handle.
func (*SpecActorHandle) ReadState ¶
func (h *SpecActorHandle) ReadState(fn func(s *SpecState))
ReadState calls the given function with a read lock on the current state. The function should not modify the state or hold references after returning.
func (*SpecActorHandle) SendCommand ¶
func (h *SpecActorHandle) SendCommand(cmd Command) ([]Event, error)
SendCommand sends a command to the actor and waits for the result.
func (*SpecActorHandle) Subscribe ¶
func (h *SpecActorHandle) Subscribe() chan Event
Subscribe returns a channel that receives broadcast events.
func (*SpecActorHandle) Unsubscribe ¶
func (h *SpecActorHandle) Unsubscribe(ch chan Event)
Unsubscribe removes a channel from the broadcast subscriber list and closes it.
type SpecCore ¶
type SpecCore struct {
SpecID ulid.ULID `json:"spec_id"`
Title string `json:"title"`
OneLiner string `json:"one_liner"`
Goal string `json:"goal"`
Description *string `json:"description,omitempty"`
Constraints *string `json:"constraints,omitempty"`
SuccessCriteria *string `json:"success_criteria,omitempty"`
Risks *string `json:"risks,omitempty"`
Notes *string `json:"notes,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
SpecCore represents the core metadata of a specification. Mirrors barnstormer's SpecCore with identical JSON field names.
func NewSpecCore ¶
NewSpecCore creates a SpecCore with the three required fields and a fresh ULID.
type SpecCoreUpdatedPayload ¶
type SpecCoreUpdatedPayload struct {
Title *string `json:"title,omitempty"`
OneLiner *string `json:"one_liner,omitempty"`
Goal *string `json:"goal,omitempty"`
Description *string `json:"description,omitempty"`
Constraints *string `json:"constraints,omitempty"`
SuccessCriteria *string `json:"success_criteria,omitempty"`
Risks *string `json:"risks,omitempty"`
Notes *string `json:"notes,omitempty"`
}
SpecCoreUpdatedPayload indicates spec metadata was updated.
func (SpecCoreUpdatedPayload) EventPayloadType ¶
func (p SpecCoreUpdatedPayload) EventPayloadType() string
type SpecCreatedPayload ¶
type SpecCreatedPayload struct {
Title string `json:"title"`
OneLiner string `json:"one_liner"`
Goal string `json:"goal"`
}
SpecCreatedPayload indicates a new spec was created.
func (SpecCreatedPayload) EventPayloadType ¶
func (p SpecCreatedPayload) EventPayloadType() string
type SpecState ¶
type SpecState struct {
Core *SpecCore `json:"core"`
Cards *OrderedMap[ulid.ULID, Card] `json:"cards"`
Transcript []TranscriptMessage `json:"transcript"`
PendingQuestion UserQuestion `json:"-"` // Custom marshal
UndoStack []UndoEntry `json:"undo_stack"`
LastEventID uint64 `json:"last_event_id"`
Lanes []string `json:"lanes"`
}
SpecState is the full materialized state of a spec, built by replaying events.
func NewSpecState ¶
func NewSpecState() *SpecState
NewSpecState creates an empty SpecState with default lanes.
func (*SpecState) Apply ¶
Apply folds a single event into this state. Reversible card mutations push undo entries. This is the heart of the event-sourcing reducer.
func (SpecState) MarshalJSON ¶
MarshalJSON serializes SpecState, including pending_question as a typed JSON field.
func (*SpecState) UnmarshalJSON ¶
UnmarshalJSON deserializes SpecState, handling the OrderedMap[ULID,Card] cards field and the UserQuestion interface for pending_question.
type StartAgentStepCommand ¶
type StartAgentStepCommand struct {
AgentID string `json:"agent_id"`
Description string `json:"description"`
}
StartAgentStepCommand marks the beginning of an agent's work step.
func (StartAgentStepCommand) CommandType ¶
func (c StartAgentStepCommand) CommandType() string
type TranscriptAppendedPayload ¶
type TranscriptAppendedPayload struct {
Message TranscriptMessage `json:"message"`
}
TranscriptAppendedPayload indicates a message was added to the transcript.
func (TranscriptAppendedPayload) EventPayloadType ¶
func (p TranscriptAppendedPayload) EventPayloadType() string
type TranscriptMessage ¶
type TranscriptMessage struct {
MessageID ulid.ULID `json:"message_id"`
Sender string `json:"sender"`
Content string `json:"content"`
Kind MessageKind `json:"kind"`
Timestamp time.Time `json:"timestamp"`
}
TranscriptMessage represents a single message in the spec's transcript.
func NewTranscriptMessage ¶
func NewTranscriptMessage(sender, content string) TranscriptMessage
NewTranscriptMessage creates a Chat-kind transcript message with a fresh ULID.
type UndoAppliedPayload ¶
type UndoAppliedPayload struct {
TargetEventID uint64 `json:"target_event_id"`
InverseEvents []EventPayload `json:"-"` // Custom marshal
}
UndoAppliedPayload indicates a previous operation was reversed.
func (UndoAppliedPayload) EventPayloadType ¶
func (p UndoAppliedPayload) EventPayloadType() string
type UndoCommand ¶
type UndoCommand struct{}
UndoCommand reverts the last undoable operation.
func (UndoCommand) CommandType ¶
func (c UndoCommand) CommandType() string
type UndoEntry ¶
type UndoEntry struct {
EventID uint64 `json:"event_id"`
Inverse []EventPayload `json:"-"` // Custom marshal for EventPayload slice
}
UndoEntry stores the inverse operations needed to revert a mutation.
func (UndoEntry) MarshalJSON ¶
MarshalJSON serializes the UndoEntry with properly typed inverse events.
func (*UndoEntry) UnmarshalJSON ¶
UnmarshalJSON deserializes the UndoEntry with properly typed inverse events.
type UpdateCardCommand ¶
type UpdateCardCommand struct {
CardID ulid.ULID `json:"card_id"`
Title *string `json:"title,omitempty"`
Body OptionalField[string] `json:"-"` // Custom marshal handles this
CardType *string `json:"card_type,omitempty"`
Refs *[]string `json:"refs,omitempty"`
UpdatedBy string `json:"updated_by"`
}
UpdateCardCommand updates an existing card's fields. Body uses OptionalField for 3-state semantics (absent/null/value).
func (UpdateCardCommand) CommandType ¶
func (c UpdateCardCommand) CommandType() string
type UpdateSpecCoreCommand ¶
type UpdateSpecCoreCommand struct {
Title *string `json:"title,omitempty"`
OneLiner *string `json:"one_liner,omitempty"`
Goal *string `json:"goal,omitempty"`
Description *string `json:"description,omitempty"`
Constraints *string `json:"constraints,omitempty"`
SuccessCriteria *string `json:"success_criteria,omitempty"`
Risks *string `json:"risks,omitempty"`
Notes *string `json:"notes,omitempty"`
}
UpdateSpecCoreCommand updates optional spec metadata fields.
func (UpdateSpecCoreCommand) CommandType ¶
func (c UpdateSpecCoreCommand) CommandType() string
type UserQuestion ¶
type UserQuestion interface {
QuestionType() string
QuestionID() ulid.ULID
// contains filtered or unexported methods
}
UserQuestion is a tagged union with 3 variants: Boolean, MultipleChoice, Freeform. JSON serialization uses a "type" discriminator field.
func UnmarshalUserQuestion ¶
func UnmarshalUserQuestion(data []byte) (UserQuestion, error)
UnmarshalUserQuestion deserializes a UserQuestion from JSON with a "type" discriminator.