core

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 17, 2026 License: MIT Imports: 10 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
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

func MarshalCommand(c Command) ([]byte, error)

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.

func NewULID

func NewULID() ulid.ULID

NewULID generates a new ULID using crypto/rand entropy.

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.

func NewCard

func NewCard(cardType, title, createdBy string) Card

NewCard creates a Card with the given type, title, and creator. Defaults: lane="Ideas", order=0.0, empty refs.

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

type CardNotFoundError struct {
	CardID ulid.ULID
}

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

func UnmarshalCommand(data []byte) (Command, error)

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

func (e Event) MarshalJSON() ([]byte, error)

MarshalJSON serializes the Event with its payload inlined.

func (*Event) UnmarshalJSON

func (e *Event) UnmarshalJSON(data []byte) error

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

type QuestionIDMismatchError struct {
	Expected ulid.ULID
	Got      ulid.ULID
}

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

type SpecActorHandle struct {
	SpecID ulid.ULID
	// contains filtered or unexported fields
}

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

func NewSpecCore(title, oneLiner, goal string) SpecCore

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

func (s *SpecState) Apply(event *Event)

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

func (s SpecState) MarshalJSON() ([]byte, error)

MarshalJSON serializes SpecState, including pending_question as a typed JSON field.

func (*SpecState) UnmarshalJSON

func (s *SpecState) UnmarshalJSON(data []byte) error

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

func (u UndoEntry) MarshalJSON() ([]byte, error)

MarshalJSON serializes the UndoEntry with properly typed inverse events.

func (*UndoEntry) UnmarshalJSON

func (u *UndoEntry) UnmarshalJSON(data []byte) error

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.

Directories

Path Synopsis
ABOUTME: Exports a SpecState as a DOT graph for the DOT Runner constrained runtime DSL.
ABOUTME: Exports a SpecState as a DOT graph for the DOT Runner constrained runtime DSL.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL