domain

package
v0.0.12 Latest Latest
Warning

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

Go to latest
Published: Apr 3, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package domain contains pure types, events, commands, policies, aggregates, and domain logic. No I/O syscalls, no context.Context. Context-aware port interfaces live in internal/usecase/port. Infrastructure (logger, telemetry) lives in internal/platform.

Index

Constants

View Source
const (
	DefaultClaudeCmd  = "claude"
	DefaultModel      = "opus"
	DefaultTimeoutSec = 1980
)

Default values for Config fields. Used by DefaultConfig and post-load validation to avoid hardcoded strings throughout the codebase.

View Source
const (
	InboxDir   = "inbox"
	OutboxDir  = "outbox"
	ArchiveDir = "archive"
)
View Source
const AggregateTypeSession = "session"

AggregateTypeSession is the aggregate type for session lifecycle events.

View Source
const AggregateTypeWave = "wave"

AggregateTypeWave is the aggregate type for wave lifecycle events.

View Source
const CurrentEventSchemaVersion uint8 = 1

CurrentEventSchemaVersion is the schema version stamped on all new events. Legacy events (pre-Phase2) will have SchemaVersion 0 when deserialized.

View Source
const DefaultIdleTimeout = 30 * time.Minute

DefaultIdleTimeout is the default idle timeout for exiting after no D-Mail activity.

View Source
const InsightSchemaVersion = "1"

InsightSchemaVersion is the current schema version for insight files.

View Source
const MaxWavesPerCluster = 8

MaxWavesPerCluster is the cap on total waves per cluster. Beyond this count, nextgen is skipped to prevent infinite wave growth.

View Source
const PROpenLabel = "paintress:pr-open"

PROpenLabel is the label indicating that paintress has created a PR for this issue.

View Source
const RawFieldMaxBytes = 4096

RawFieldMaxBytes is the maximum size of the raw field and text data fields.

View Source
const StateDir = ".siren"
View Source
const StateFormatVersion = "1"

StateFormatVersion is the wire-format version embedded in SessionState JSON files. This is NOT the sightjack release version — it tracks the on-disk schema so that future readers can detect and migrate older state files.

Compatibility contract (ADR 0013):

  • Readers MUST accept all prior format versions (currently: "0.0.11", "1").
  • Writers MUST always emit the current version.
  • Bump only when the SessionState JSON structure changes incompatibly, and add a migration path for every prior version.
View Source
const StreamSchemaVersion uint8 = 1

StreamSchemaVersion is the current schema version for session stream events.

Variables

View Source
var ErrGoBack = errors.New("go back")

ErrGoBack signals the user chose to go back to the previous menu.

View Source
var ErrQuit = errors.New("user quit")

ErrQuit signals the user chose to quit.

View Source
var Policies = []Policy{
	{Name: "WaveAppliedComposeReport", Trigger: EventWaveApplied, Action: "ComposeReport"},
	{Name: "ReportSentDeliverToPhonewave", Trigger: EventReportSent, Action: "DeliverViaPhonewave"},
	{Name: "ScanCompletedGenerateWaves", Trigger: EventScanCompleted, Action: "GenerateWaves"},
	{Name: "WaveCompletedNextGen", Trigger: EventWaveCompleted, Action: "GenerateNextWaves"},
	{Name: "SpecificationSentDeliverToPhonewave", Trigger: EventSpecificationSent, Action: "DeliverViaPhonewave"},
}

Policies registers all known implicit policies in sightjack. These document the existing reactive behaviors for future automation.

View Source
var ShutdownKey = shutdownKey{}

ShutdownKey is used to embed the outer context in workCtx via context.WithValue. Commands retrieve it to get a context that survives workCtx cancellation.

Functions

func BuildCompletedWaveMap

func BuildCompletedWaveMap(waves []Wave) map[string]bool

BuildCompletedWaveMap returns a set of completed waves keyed by WaveKey (ClusterName:ID).

func CalcNewlyUnlocked

func CalcNewlyUnlocked(oldAvailable, newAvailable int) int

CalcNewlyUnlocked computes how many waves were newly unlocked after completing a wave. oldAvailable is the available count before the wave was completed (includes the completing wave). newAvailable is the available count after completion and unlock evaluation.

func CheckCompletenessConsistency

func CheckCompletenessConsistency(overall float64, clusters []ClusterScanResult) bool

CheckCompletenessConsistency verifies that the average of cluster completeness values matches the overall completeness within a tolerance. Returns true if a mismatch beyond the tolerance (5 percentage points) is detected.

func ChunkSlice

func ChunkSlice(items []string, size int) [][]string

ChunkSlice splits items into sub-slices of at most size elements.

func ClampCompleteness added in v0.0.11

func ClampCompleteness(v float64) float64

ClampCompleteness bounds a completeness value to [0, 1].

func CollectPROpenIssues added in v0.0.12

func CollectPROpenIssues(clusters []ClusterScanResult) map[string]bool

CollectPROpenIssues scans clusters for issues with the paintress:pr-open label and returns a set of issue IDs.

func CollectSpecSentIssueIDs added in v0.0.12

func CollectSpecSentIssueIDs(completed map[string]bool, waves []Wave) map[string]bool

CollectSpecSentIssueIDs returns issue IDs from completed waves' actions. Used as session-level race condition guard: issues that have already received spec D-Mails should not get new implementation waves even if paintress hasn't applied the pr-open label yet.

func ConfigPath

func ConfigPath(baseDir string) string

ConfigPath returns the path to the config file within .siren/.

func DetectFailedClusterNames

func DetectFailedClusterNames(clusters []ClusterScanResult, successes []WaveGenerateResult) map[string]bool

DetectFailedClusterNames compares input cluster counts to success counts and returns names where at least one instance failed wave generation. With duplicate cluster names, a name is marked failed if fewer instances succeeded than existed in the input.

func DetectRepeatedPattern added in v0.0.11

func DetectRepeatedPattern(fingerprints []string, threshold int) (bool, string)

DetectRepeatedPattern scans a slice of error fingerprints and reports whether any single fingerprint appears at least threshold times. Returns (true, fingerprint) if a repeated pattern is found, (false, "") otherwise.

func DetectWaveCycles added in v0.0.11

func DetectWaveCycles(waves []Wave) error

DetectWaveCycles performs DFS-based cycle detection on the wave prerequisite graph. Returns an error describing the cycle if one is found, nil otherwise.

func ErrorFingerprint added in v0.0.11

func ErrorFingerprint(errMsg string) string

ErrorFingerprint returns a short, stable hash of the error message that can be used to detect repeated identical errors across attempts.

func ExitCode

func ExitCode(err error) int

func FormatDoDSection

func FormatDoDSection(tmpl DoDTemplate) string

FormatDoDSection formats a DoD template into a text section for prompt injection.

func FormatSuccessRate

func FormatSuccessRate(rate float64, success, total int) string

FormatSuccessRate returns a human-readable string for the given success rate. Returns "no events" when total is zero.

func IsRateLimited

func IsRateLimited(output string) bool

IsRateLimited checks if the review output indicates a rate/quota limit.

func IsWaveApplyComplete

func IsWaveApplyComplete(result *WaveApplyResult) bool

IsWaveApplyComplete returns true when the apply result has no errors, indicating all actions were successfully applied.

func LogBanner added in v0.0.3

func LogBanner(logger Logger, dir BannerDirection, kind, name, description string)

LogBanner calls Banner if the logger supports it (type assertion). Safe to call with any Logger including NopLogger.

func LogHeader added in v0.0.10

func LogHeader(logger Logger, toolName, version string)

LogHeader calls Header if the logger supports it (type assertion). Prints a single-line startup header with tool name and version.

func LogSection added in v0.0.10

func LogSection(logger Logger, title string)

LogSection calls Section if the logger supports it (type assertion). Prints a single-line section separator for phase transitions.

func MailDir

func MailDir(baseDir, sub string) string

MailDir returns the path to a mail subdirectory under the state root.

func MarshalEvent

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

MarshalEvent serializes an Event to compact JSON (no trailing newline).

func MatchDoDTemplate

func MatchDoDTemplate(templates map[string]DoDTemplate, clusterName string) (bool, string)

MatchDoDTemplate finds a DoD template matching the cluster name. Matching uses case-insensitive prefix match. When multiple keys match, the longest matching prefix wins. Equal-length ties are broken by lexicographic comparison of lowercased keys for deterministic behavior.

func NeedsMoreWaves

func NeedsMoreWaves(cluster ClusterScanResult, waves []Wave) bool

NeedsMoreWaves returns true when post-completion wave generation should run for the given cluster. It returns false (skip nextgen) when any of:

  • cluster completeness >= 0.95 (effectively done)
  • available (non-completed) waves still remain for the cluster
  • total wave count for the cluster >= MaxWavesPerCluster

func PartialApplyDelta

func PartialApplyDelta(result *WaveApplyResult, delta WaveDelta) float64

PartialApplyDelta computes the adjusted delta for a partially applied wave. When TotalCount is 0, the original delta.After is returned.

func PropagateWaveUpdate

func PropagateWaveUpdate(waves []Wave, updated Wave)

PropagateWaveUpdate writes the updated wave back into the waves slice, matching by WaveKey so that subsequent AvailableWaves calls see the new state.

func PruneStaleWaves added in v0.0.11

func PruneStaleWaves(state *SessionState, validClusters []ClusterState) int

PruneStaleWaves removes waves whose cluster is no longer in the valid cluster set. Completed waves are preserved regardless. Modifies state.Waves in place. Returns the count of pruned waves.

func ReadyIssueIDs

func ReadyIssueIDs(waves []Wave) []string

ReadyIssueIDs returns issue IDs where ALL waves targeting them are completed. An issue is ready when every wave containing that issue has status "completed". Results are sorted for deterministic output.

func RelativeScanResultPath

func RelativeScanResultPath(baseDir, absPath string) string

RelativeScanResultPath converts an absolute scan result path to a path relative to baseDir for portable storage in event payloads. If the path is already relative, it is returned unchanged.

func ResolveDoDSection

func ResolveDoDSection(templates map[string]DoDTemplate, clusterName string) string

ResolveDoDSection looks up a DoD template matching clusterName and formats it as a text section. Returns "" when no matching template is found or when the templates map is nil. This consolidates the MatchDoDTemplate + FormatDoDSection pattern used in scanner, wave_generator, and wave.

func ResolveScanResultPath

func ResolveScanResultPath(baseDir, storedPath string) string

ResolveScanResultPath resolves a stored scan result path to an absolute path. If the stored path is already absolute (backwards compatibility with old events), it is returned as-is. If relative, it is joined with baseDir.

func SanitizeName

func SanitizeName(name string) string

SanitizeName converts a cluster name to a safe filename component. Only ASCII alphanumeric, hyphen, and underscore are kept; everything else becomes underscore.

func ScanDir

func ScanDir(baseDir, sessionID string) string

ScanDir returns the path to the scan directory for a given session.

func StallEscalationBody added in v0.0.11

func StallEscalationBody(wave Wave, errors []string, reason string) string

StallEscalationBody formats a d-mail body for a stall escalation message. It includes the wave title, the escalation reason, and the list of structural errors.

func StructuralErrors added in v0.0.11

func StructuralErrors(errors []string) []string

StructuralErrors filters errMsg slice, returning only those classified as structural by ClassifyError.

func SuccessRate

func SuccessRate(events []Event) float64

SuccessRate calculates the wave success rate from a list of events. It counts EventWaveApplied as success and EventWaveRejected as failure. Returns 0.0 if there are no relevant events.

func SummarizeReview

func SummarizeReview(comments string) string

SummarizeReview normalizes whitespace and truncates a review output string.

func TruncateField added in v0.0.12

func TruncateField(s string, maxBytes int) (string, bool)

TruncateField truncates s to maxBytes at a UTF-8 boundary, appending "..." if truncation occurred. Returns the (possibly truncated) string and whether truncation happened.

func UnmarshalEventPayload

func UnmarshalEventPayload(e Event, target any) error

UnmarshalEventPayload deserializes the Data field into the given target.

func ValidLang

func ValidLang(lang string) bool

ValidLang returns true if lang is a supported language code. Only "ja" and "en" are valid (used as template suffixes).

func ValidWaveActionType added in v0.0.3

func ValidWaveActionType(t string) bool

ValidWaveActionType reports whether t is a recognized wave action type.

func ValidateConfig added in v0.0.4

func ValidateConfig(cfg Config) []string

ValidateConfig checks the config for consistency and returns a list of errors. An empty slice means the config is valid.

func ValidateEvent

func ValidateEvent(e Event) error

ValidateEvent checks structural validity of an Event before persistence.

func ValidateSessionStreamEvent added in v0.0.12

func ValidateSessionStreamEvent(e SessionStreamEvent) error

ValidateSessionStreamEvent checks required fields.

func ValidateWaveApplyResult added in v0.0.11

func ValidateWaveApplyResult(result *WaveApplyResult, expectedActions int) error

ValidateWaveApplyResult checks the apply result for degenerate or invalid states. Returns an error if the result is nil, empty when actions were expected, or reports more applied actions than expected.

func WaveKey

func WaveKey(w Wave) string

WaveKey returns a globally unique key for a wave: "ClusterKey:ID". Falls back to ClusterName if ClusterKey is not set (backward compat).

Types

type ADRConflict

type ADRConflict struct {
	ExistingADRID string `json:"existing_adr_id"`
	Description   string `json:"description"`
}

ADRConflict represents a detected contradiction between a new ADR and an existing one.

type ADRGeneratedPayload

type ADRGeneratedPayload struct {
	ADRID string `json:"adr_id"`
	Title string `json:"title"`
}

ADRGeneratedPayload is the payload for EventADRGenerated.

type ActionResult

type ActionResult struct {
	Type    string `json:"type"`
	IssueID string `json:"issue_id"`
	Success bool   `json:"success"`
	Error   string `json:"error,omitempty"`
}

ActionResult reports the outcome of a single wave action application.

type AppendResult

type AppendResult struct {
	BytesWritten int // total bytes written to event files
}

AppendResult captures metrics from an event store Append operation.

type ApplyErrorBudget added in v0.0.11

type ApplyErrorBudget struct {
	// contains filtered or unexported fields
}

ApplyErrorBudget implements a circuit-breaker pattern for wave apply operations. It tracks consecutive failures and trips the circuit when the threshold is reached. A single success resets the circuit and the consecutive failure count.

func NewApplyErrorBudget added in v0.0.11

func NewApplyErrorBudget(threshold int) *ApplyErrorBudget

NewApplyErrorBudget creates a new ApplyErrorBudget with the given failure threshold. The circuit trips when consecutiveFailures >= threshold.

func (*ApplyErrorBudget) ConsecutiveFailures added in v0.0.11

func (b *ApplyErrorBudget) ConsecutiveFailures() int

ConsecutiveFailures returns the current count of consecutive failures.

func (*ApplyErrorBudget) IsTripped added in v0.0.11

func (b *ApplyErrorBudget) IsTripped() bool

IsTripped returns true when the consecutive failure count has reached or exceeded the threshold, indicating the circuit breaker has opened.

func (*ApplyErrorBudget) RecordAttempt added in v0.0.11

func (b *ApplyErrorBudget) RecordAttempt(success bool)

RecordAttempt records the result of a single apply attempt. If success is true, consecutive failures are reset to zero. If success is false, consecutive failures are incremented.

type ApplyResult

type ApplyResult struct {
	WaveID          string         `json:"wave_id"`
	AppliedActions  []ActionResult `json:"applied_actions"`
	RippleEffects   []Ripple       `json:"ripple_effects,omitempty"`
	NewCompleteness float64        `json:"new_completeness"`
	CompletedWave   *Wave          `json:"completed_wave,omitempty"`
	RemainingWaves  []Wave         `json:"remaining_waves,omitempty"`
}

ApplyResult is the output of `apply` subcommand. Reports per-action outcomes and downstream effects. CompletedWave carries the wave context so downstream pipe commands (e.g. nextgen) can operate without replaying event history. RemainingWaves carries sibling waves from the original plan so that nextgen can accurately determine whether follow-up generation is needed.

func ToApplyResult

func ToApplyResult(wave Wave, internal *WaveApplyResult) ApplyResult

ToApplyResult converts the internal WaveApplyResult to the pipe wire format ApplyResult. It builds per-action results from the wave's actions and the internal result's error list.

type ApplyWaveCommand

type ApplyWaveCommand struct {
	// contains filtered or unexported fields
}

ApplyWaveCommand represents the intent to approve and apply a wave.

func NewApplyWaveCommand

func NewApplyWaveCommand(repoPath RepoPath, sessionID SessionID, clusterName ClusterName) ApplyWaveCommand

func (ApplyWaveCommand) ClusterName

func (c ApplyWaveCommand) ClusterName() ClusterName

func (ApplyWaveCommand) RepoPath

func (c ApplyWaveCommand) RepoPath() RepoPath

func (ApplyWaveCommand) SessionID

func (c ApplyWaveCommand) SessionID() SessionID

type ApprovalChoice

type ApprovalChoice int

ApprovalChoice represents the human's choice at the wave approval prompt.

const (
	ApprovalApprove ApprovalChoice = iota
	ApprovalReject
	ApprovalDiscuss
	ApprovalQuit
	ApprovalSelective
)

type ApproverConfig added in v0.0.10

type ApproverConfig interface {
	IsAutoApprove() bool
	ApproveCmdString() string
}

ApproverConfig describes how approval behavior is configured. Implemented by GateConfig. Used by session.BuildApprover.

type ArchitectDiscussPromptData

type ArchitectDiscussPromptData struct {
	ClusterName     string
	WaveTitle       string
	WaveActions     string
	Topic           string
	OutputPath      string
	StrictnessLevel string
}

ArchitectDiscussPromptData holds template data for the architect discussion prompt.

type ArchitectResponse

type ArchitectResponse struct {
	Analysis     string `json:"analysis"`
	ModifiedWave *Wave  `json:"modified_wave"`
	Reasoning    string `json:"reasoning"`
	Decision     string `json:"decision,omitempty"`
}

ArchitectResponse is the output of an architect discussion round.

type AutoDiscussArchitectPromptData added in v0.0.3

type AutoDiscussArchitectPromptData struct {
	ClusterName     string
	WaveTitle       string
	WaveActions     string
	PriorContent    string // prior Devil's Advocate remarks (empty for round 0)
	FeedbackSection string // design-feedback D-Mails
	OutputPath      string
	StrictnessLevel string
}

AutoDiscussArchitectPromptData holds template data for the auto-discuss architect prompt.

type AutoDiscussDevilsAdvocatePromptData added in v0.0.3

type AutoDiscussDevilsAdvocatePromptData struct {
	ClusterName     string
	WaveTitle       string
	WaveActions     string
	PriorContent    string // prior Architect remarks
	ExistingADRs    []ExistingADR
	CLAUDEMDContent string // CLAUDE.md content (may be empty)
	OutputPath      string
	StrictnessLevel string
	RoundIndex      int
	TotalRounds     int
	IsFinalRound    bool
}

AutoDiscussDevilsAdvocatePromptData holds template data for the Devil's Advocate prompt.

type AutoDiscussResult added in v0.0.3

type AutoDiscussResult struct {
	Rounds     []AutoDiscussRound `json:"rounds"`
	OpenIssues []string           `json:"open_issues"`
	Summary    string             `json:"summary"`
}

AutoDiscussResult holds the full auto-discuss debate outcome.

func (AutoDiscussResult) ToArchitectResponse added in v0.0.3

func (r AutoDiscussResult) ToArchitectResponse() *ArchitectResponse

ToArchitectResponse converts the debate result into an ArchitectResponse so it can be passed to RunScribeADR unchanged.

type AutoDiscussRound added in v0.0.3

type AutoDiscussRound struct {
	Round   int    `json:"round"`
	Speaker string `json:"speaker"` // "architect" or "devils_advocate"
	Content string `json:"content"`
}

AutoDiscussRound captures a single round of the auto-discuss debate.

type BannerDirection added in v0.0.3

type BannerDirection int

BannerDirection indicates the direction of a D-Mail intent log.

const (
	BannerSend BannerDirection = iota
	BannerRecv
)

type BannerLogger added in v0.0.3

type BannerLogger interface {
	Banner(dir BannerDirection, kind, name, description string)
	Header(toolName, version string)
	Section(title string)
}

BannerLogger is an optional extension for loggers that support inverted-color banner lines for D-Mail intent logging.

type CheckStatus

type CheckStatus int

CheckStatus represents the outcome of a single doctor check.

const (
	CheckOK CheckStatus = iota
	CheckFail
	CheckSkip
	CheckWarn
	CheckFixed
)

func (CheckStatus) StatusLabel

func (s CheckStatus) StatusLabel() string

StatusLabel returns a display string for the check status.

type ClassifyPromptData

type ClassifyPromptData struct {
	TeamFilter      string
	ProjectFilter   string
	CycleFilter     string
	OutputPath      string
	StrictnessLevel string
	LabelsEnabled   bool
	LabelPrefix     string
	IsWaveMode      bool
}

ClassifyPromptData holds template data for the classify prompt.

type ClassifyResult

type ClassifyResult struct {
	Clusters        []ClusterClassification `json:"clusters"`
	TotalIssues     int                     `json:"total_issues"`
	ShibitoWarnings []ShibitoWarning        `json:"shibito_warnings,omitempty"`
}

ClassifyResult is the output of Pass 1 (cluster classification). Written by Claude Code to classify.json.

type ClusterClassification

type ClusterClassification struct {
	Name     string   `json:"name"`
	IssueIDs []string `json:"issue_ids"`
	Labels   []string `json:"labels,omitempty"`
}

ClusterClassification holds a cluster name and its issue IDs from Pass 1.

func FilterEmptyClassifications added in v0.0.11

func FilterEmptyClassifications(clusters []ClusterClassification) ([]ClusterClassification, int)

FilterEmptyClassifications removes clusters with zero issue IDs from the classification result. Returns the filtered list and the count of removed clusters.

type ClusterName

type ClusterName struct {
	// contains filtered or unexported fields
}

ClusterName is an always-valid, non-empty cluster name.

func NewClusterName

func NewClusterName(raw string) (ClusterName, error)

func (ClusterName) String

func (c ClusterName) String() string

type ClusterScanOutcome added in v0.0.11

type ClusterScanOutcome struct {
	ClusterName string
	Succeeded   bool
}

ClusterScanOutcome records whether wave generation succeeded for a single cluster.

type ClusterScanResult

type ClusterScanResult struct {
	Name                string        `json:"name"`
	Key                 string        `json:"key"`
	Completeness        float64       `json:"completeness"`
	Issues              []IssueDetail `json:"issues"`
	Observations        []string      `json:"observations"`
	Labels              []string      `json:"labels,omitempty"`
	EstimatedStrictness string        `json:"estimated_strictness,omitempty"`
	StrictnessReasoning string        `json:"strictness_reasoning,omitempty"`
	IssueCount          int           `json:"-"` // computed; used when Issues is nil (e.g. show command)
}

ClusterScanResult is the output of Pass 2 (per-cluster deep scan). Written by Claude Code to cluster_{name}.json.

func ClustersForIssueIDs added in v0.0.5

func ClustersForIssueIDs(clusters []ClusterScanResult, issueIDs []string) []ClusterScanResult

ClustersForIssueIDs returns the unique clusters that contain any of the given issue IDs. This is used to identify which clusters are affected by a report D-Mail.

func MergeClusterChunks

func MergeClusterChunks(name string, chunks []ClusterScanResult) ClusterScanResult

MergeClusterChunks combines multiple chunk results from the same cluster into a single ClusterScanResult, recalculating completeness from individual issues. Individual issue completeness values are clamped to [0, 1] before averaging.

func (ClusterScanResult) NumIssues

func (c ClusterScanResult) NumIssues() int

NumIssues returns the number of issues. It prefers len(Issues) when the slice is populated and falls back to the IssueCount field.

type ClusterState

type ClusterState struct {
	Name         string  `json:"name"`
	Completeness float64 `json:"completeness"`
	IssueCount   int     `json:"issue_count"`
}

ClusterState is the per-cluster state within SessionState.

type CodingSessionRecord added in v0.0.12

type CodingSessionRecord struct {
	ID                string
	ProviderSessionID string
	Provider          Provider
	Status            SessionStatus
	Model             string
	WorkDir           string
	CreatedAt         time.Time
	UpdatedAt         time.Time
	Metadata          map[string]string
}

CodingSessionRecord is the persistent record of an AI coding session.

func NewCodingSessionRecord added in v0.0.12

func NewCodingSessionRecord(provider Provider, model, workDir string) CodingSessionRecord

NewCodingSessionRecord creates a new record with status=running.

func (*CodingSessionRecord) Complete added in v0.0.12

func (r *CodingSessionRecord) Complete(providerSessionID string) error

Complete transitions from running to completed.

func (*CodingSessionRecord) Fail added in v0.0.12

func (r *CodingSessionRecord) Fail(reason string) error

Fail transitions from running to failed.

type CompletenessUpdatedPayload

type CompletenessUpdatedPayload struct {
	ClusterName         string  `json:"cluster_name"`
	ClusterCompleteness float64 `json:"cluster_completeness"`
	OverallCompleteness float64 `json:"overall_completeness"`
}

CompletenessUpdatedPayload is the payload for EventCompletenessUpdated.

type ComputedConfig added in v0.0.4

type ComputedConfig struct {
	EstimatedStrictness map[string]StrictnessLevel `yaml:"estimated_strictness,omitempty"`
}

ComputedConfig holds system-written fields that cannot be set via config set.

type Config

type Config struct {
	Tracker      IssueTrackerConfig     `yaml:"tracker"`
	Scan         ScanConfig             `yaml:"scan"`
	ClaudeCmd    string                 `yaml:"claude_cmd,omitempty"`
	Model        string                 `yaml:"model,omitempty"`
	TimeoutSec   int                    `yaml:"timeout_sec,omitempty"`
	Scribe       ScribeConfig           `yaml:"scribe"`
	Strictness   StrictnessConfig       `yaml:"strictness"`
	Retry        RetryConfig            `yaml:"retry"`
	Labels       LabelsConfig           `yaml:"labels"`
	Gate         GateConfig             `yaml:"gate"`
	DoDTemplates map[string]DoDTemplate `yaml:"dod_templates"`
	Lang         string                 `yaml:"lang"`
	Computed     ComputedConfig         `yaml:"computed,omitempty"`

	// Runtime-only: set from --linear flag, not persisted in config.yaml
	Mode TrackingMode `yaml:"-"`
}

Config holds the top-level sightjack configuration loaded from YAML.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a Config populated with sensible defaults.

type DeepScanPromptData

type DeepScanPromptData struct {
	ClusterName     string
	IssueIDs        string
	OutputPath      string
	StrictnessLevel string
	IsWaveMode      bool
}

DeepScanPromptData holds template data for the deep scan prompt.

type DeviationError

type DeviationError struct {
	TotalIssues int
}

DeviationError is returned when a scan detects issues (deviation from spec). Callers can use errors.As to distinguish deviation from runtime errors.

func (*DeviationError) Error

func (e *DeviationError) Error() string

type DiscussResult

type DiscussResult struct {
	WaveID        string             `json:"wave_id"`
	Analysis      string             `json:"analysis"`
	Reasoning     string             `json:"reasoning"`
	Decision      string             `json:"decision"`
	Modifications []WaveModification `json:"modifications,omitempty"`
	ADRWorthy     bool               `json:"adr_worthy"`
	ADRTitle      string             `json:"adr_title,omitempty"`
}

DiscussResult is the output of `discuss` subcommand. Captures the architect discussion outcome for a single wave.

type DiscussWaveCommand

type DiscussWaveCommand struct {
	// contains filtered or unexported fields
}

DiscussWaveCommand represents the intent to discuss a specific wave topic.

func NewDiscussWaveCommand

func NewDiscussWaveCommand(repoPath RepoPath, sessionID SessionID, clusterName ClusterName, topic Topic) DiscussWaveCommand

func (DiscussWaveCommand) ClusterName

func (c DiscussWaveCommand) ClusterName() ClusterName

func (DiscussWaveCommand) RepoPath

func (c DiscussWaveCommand) RepoPath() RepoPath

func (DiscussWaveCommand) SessionID

func (c DiscussWaveCommand) SessionID() SessionID

func (DiscussWaveCommand) Topic

func (c DiscussWaveCommand) Topic() Topic

type DoDCoverageReport added in v0.0.11

type DoDCoverageReport struct {
	TotalClusters     int
	CoveredClusters   int
	UncoveredClusters []string
}

DoDCoverageReport summarises which clusters have a matching DoD template and which are uncovered.

func BuildDoDCoverageReport added in v0.0.11

func BuildDoDCoverageReport(templates map[string]DoDTemplate, clusterNames []string) DoDCoverageReport

BuildDoDCoverageReport constructs a DoDCoverageReport by matching each cluster name against the provided DoD templates using MatchDoDTemplate. Clusters without a matching template are listed in UncoveredClusters.

type DoDTemplate

type DoDTemplate struct {
	Must   []string `yaml:"must"`
	Should []string `yaml:"should"`
}

DoDTemplate holds must/should Definition of Done items for a category.

type DoctorCheck added in v0.0.7

type DoctorCheck struct {
	Name    string
	Status  CheckStatus
	Message string
	Hint    string // optional remediation hint shown on failure
}

DoctorCheck holds the outcome of a single doctor check.

type ErrorKind added in v0.0.11

type ErrorKind string

ErrorKind classifies an error as structural or transient.

const (
	// ErrorKindStructural indicates a persistent, non-recoverable error
	// (e.g. missing file, permission denied).
	ErrorKindStructural ErrorKind = "structural"
	// ErrorKindTransient indicates a temporary, potentially self-resolving error
	// (e.g. network timeout, connection reset).
	ErrorKindTransient ErrorKind = "transient"
)

func ClassifyError added in v0.0.11

func ClassifyError(errMsg string) ErrorKind

ClassifyError classifies an error message as structural or transient. Structural errors are persistent and require human intervention. Transient errors may resolve on retry.

type Event

type Event struct {
	SchemaVersion uint8           `json:"schema_version,omitempty"`
	ID            string          `json:"id"`
	Type          EventType       `json:"type"`
	Timestamp     time.Time       `json:"timestamp"`
	Data          json.RawMessage `json:"data"`
	SessionID     string          `json:"session_id"`
	CorrelationID string          `json:"correlation_id,omitempty"`
	CausationID   string          `json:"causation_id,omitempty"`
	AggregateID   string          `json:"aggregate_id,omitempty"`
	AggregateType string          `json:"aggregate_type,omitempty"`
	SeqNr         uint64          `json:"seq_nr,omitempty"`
}

Event is the immutable event envelope persisted to the event store.

func NewEvent

func NewEvent(eventType EventType, data any, timestamp time.Time) (Event, error)

NewEvent creates an Event with a UUID, the given timestamp, and marshaled data payload.

type EventApplier

type EventApplier interface {
	Apply(event Event) error
	Rebuild(events []Event) error
}

EventApplier applies domain events to update materialized projections.

type EventType

type EventType string

EventType identifies the kind of domain event.

const (
	EventSessionStarted      EventType = "session_started"
	EventScanCompleted       EventType = "scan_completed"
	EventWavesGenerated      EventType = "waves_generated"
	EventWaveApproved        EventType = "wave_approved"
	EventWaveRejected        EventType = "wave_rejected"
	EventWaveModified        EventType = "wave_modified"
	EventWaveApplied         EventType = "wave_applied"
	EventWaveCompleted       EventType = "wave_completed"
	EventCompletenessUpdated EventType = "completeness_updated"
	EventWavesUnlocked       EventType = "waves_unlocked"
	EventNextGenWavesAdded   EventType = "nextgen_waves_added"
	EventADRGenerated        EventType = "adr_generated"
	EventReadyLabelsApplied  EventType = "ready_labels_applied"
	EventSessionResumed      EventType = "session_resumed"
	EventSessionRescanned    EventType = "session_rescanned"
	EventSpecificationSent   EventType = "specification_sent"
	EventReportSent          EventType = "report_sent"
	EventFeedbackSent        EventType = "feedback_sent"
	EventFeedbackReceived    EventType = "feedback_received"
)
const EventWaveStalled EventType = "wave_stalled"

EventWaveStalled is emitted when a wave is detected to be stalled due to repeated structural error patterns.

type ExistingADR

type ExistingADR struct {
	Filename string
	Content  string
}

ExistingADR holds the filename and content of an existing ADR file.

type FeedbackReceivedPayload added in v0.0.12

type FeedbackReceivedPayload struct {
	Kind  string `json:"kind"`
	Name  string `json:"name"`
	Count int    `json:"count"`
}

FeedbackReceivedPayload is the payload for EventFeedbackReceived.

type GateConfig

type GateConfig struct {
	NotifyCmd    string        `yaml:"notify_cmd"`
	ApproveCmd   string        `yaml:"approve_cmd"`
	AutoApprove  bool          `yaml:"auto_approve"`
	ReviewCmd    string        `yaml:"review_cmd"`
	ReviewBudget int           `yaml:"review_budget"` // max review cycles (0 = default 3)
	IdleTimeout  time.Duration `yaml:"idle_timeout"`  // idle timeout — exit after no D-Mail activity (0 = 24h safety cap, <0 = disable waiting)
}

GateConfig holds convergence gate notification and approval settings. GateConfig implements ApproverConfig.

func (GateConfig) ApproveCmdString

func (g GateConfig) ApproveCmdString() string

ApproveCmdString returns the approval command string.

func (GateConfig) EffectiveReviewBudget

func (g GateConfig) EffectiveReviewBudget() int

EffectiveReviewBudget returns the review budget, defaulting to 3 if unset.

func (GateConfig) HasApproveCmd

func (g GateConfig) HasApproveCmd() bool

HasApproveCmd reports whether an approval command is configured.

func (GateConfig) HasNotifyCmd

func (g GateConfig) HasNotifyCmd() bool

HasNotifyCmd reports whether a notification command is configured.

func (GateConfig) HasReviewCmd

func (g GateConfig) HasReviewCmd() bool

HasReviewCmd reports whether a review command is configured.

func (GateConfig) IsAutoApprove

func (g GateConfig) IsAutoApprove() bool

IsAutoApprove reports whether the gate is configured to auto-approve.

func (GateConfig) NotifyCmdString

func (g GateConfig) NotifyCmdString() string

NotifyCmdString returns the notification command string.

func (GateConfig) ReviewCmdString

func (g GateConfig) ReviewCmdString() string

ReviewCmdString returns the review command string.

func (*GateConfig) SetApproveCmd added in v0.0.4

func (g *GateConfig) SetApproveCmd(cmd string)

SetApproveCmd sets the approval command.

func (*GateConfig) SetAutoApprove added in v0.0.3

func (g *GateConfig) SetAutoApprove(v bool)

SetAutoApprove sets the auto-approve flag on the gate config.

func (*GateConfig) SetIdleTimeout added in v0.0.12

func (g *GateConfig) SetIdleTimeout(d time.Duration)

SetIdleTimeout sets the idle timeout for exiting after no D-Mail activity.

func (*GateConfig) SetNotifyCmd added in v0.0.4

func (g *GateConfig) SetNotifyCmd(cmd string)

SetNotifyCmd sets the notification command.

func (*GateConfig) SetReviewBudget added in v0.0.4

func (g *GateConfig) SetReviewBudget(n int)

SetReviewBudget sets the max review cycles.

func (*GateConfig) SetReviewCmd added in v0.0.4

func (g *GateConfig) SetReviewCmd(cmd string)

SetReviewCmd sets the review command.

type HandoffResult

type HandoffResult struct {
	IssueID string // Linear issue identifier
	Status  string // "success", "failed", "skipped"
	Error   string // non-empty when Status is "failed"
}

HandoffResult tracks the outcome of a handoff for a single issue.

type HandoverState added in v0.0.7

type HandoverState struct {
	Tool         string // "sightjack"
	Operation    string // "wave"
	Timestamp    time.Time
	InProgress   string            // Current task description
	Completed    []string          // What was done
	Remaining    []string          // What's left
	PartialState map[string]string // Tool-specific state (key=label, value=detail)
}

HandoverState captures in-progress work state when an operation is interrupted by a signal. The struct is pure data — no context, no I/O.

type IndexEntry added in v0.0.8

type IndexEntry struct {
	Timestamp string `json:"ts"`
	Operation string `json:"op"`
	Issue     string `json:"issue"`
	Status    string `json:"status"`
	Tool      string `json:"tool"`
	Path      string `json:"path"`
	Summary   string `json:"summary"`
}

IndexEntry represents one line in the archive index JSONL file.

type InitCommand

type InitCommand struct {
	// contains filtered or unexported fields
}

InitCommand represents the intent to initialize a sightjack project.

func NewInitCommand

func NewInitCommand(baseDir RepoPath, team, project, lang, strictness string) InitCommand

func (InitCommand) BaseDir

func (c InitCommand) BaseDir() RepoPath

func (InitCommand) Lang

func (c InitCommand) Lang() string

func (InitCommand) Project

func (c InitCommand) Project() string

func (InitCommand) Strictness

func (c InitCommand) Strictness() string

func (InitCommand) Team

func (c InitCommand) Team() string

type InsightContext added in v0.0.4

type InsightContext struct {
	Insights []InsightSummary `yaml:"insights,omitempty" json:"insights,omitempty"`
}

InsightContext is the optional context field added to D-Mail envelopes.

type InsightEntry added in v0.0.4

type InsightEntry struct {
	Title       string
	What        string
	Why         string
	How         string
	When        string
	Who         string
	Constraints string
	Extra       map[string]string // tool-specific optional fields
}

InsightEntry represents a single semantic insight with 6 required axes + optional extras.

func (InsightEntry) Format added in v0.0.4

func (e InsightEntry) Format() string

Format renders a single InsightEntry as Markdown.

type InsightFile added in v0.0.4

type InsightFile struct {
	SchemaVersion string         `yaml:"insight-schema-version"`
	Kind          string         `yaml:"kind"`
	Tool          string         `yaml:"tool"`
	UpdatedAt     time.Time      `yaml:"updated_at"`
	Entries       []InsightEntry `yaml:"-"` // parsed from Markdown body
}

InsightFile is the on-disk representation of an insight ledger file.

func UnmarshalInsightFile added in v0.0.4

func UnmarshalInsightFile(data []byte) (*InsightFile, error)

UnmarshalInsightFile parses a YAML frontmatter + Markdown insight file.

func (InsightFile) Marshal added in v0.0.4

func (f InsightFile) Marshal() ([]byte, error)

Marshal renders the full InsightFile as YAML frontmatter + Markdown body.

type InsightSummary added in v0.0.4

type InsightSummary struct {
	Source  string `yaml:"source" json:"source"`
	Summary string `yaml:"summary" json:"summary"`
}

InsightSummary is a single insight reference within a D-Mail context.

type IssueDetail

type IssueDetail struct {
	ID           string   `json:"id"`
	Identifier   string   `json:"identifier"`
	Title        string   `json:"title"`
	Status       string   `json:"status"`
	Completeness float64  `json:"completeness"`
	Gaps         []string `json:"gaps"`
	Labels       []string `json:"labels,omitempty"`
}

IssueDetail holds the deep scan analysis of a single issue.

func (IssueDetail) HasPROpen added in v0.0.12

func (d IssueDetail) HasPROpen() bool

HasPROpen reports whether this issue has the paintress:pr-open label.

type IssueTrackerConfig

type IssueTrackerConfig struct {
	Team    string `yaml:"team"`
	Project string `yaml:"project"`
	Cycle   string `yaml:"cycle"`
}

IssueTrackerConfig holds issue tracker integration settings.

type LabelsConfig

type LabelsConfig struct {
	Enabled    bool   `yaml:"enabled"`
	Prefix     string `yaml:"prefix"`
	ReadyLabel string `yaml:"ready_label"`
}

LabelsConfig holds Linear label assignment settings.

type Lang

type Lang struct {
	// contains filtered or unexported fields
}

Lang is an always-valid language code ("ja" or "en").

func NewLang

func NewLang(raw string) (Lang, error)

func (Lang) String

func (l Lang) String() string

type LoadResult

type LoadResult struct {
	FileCount        int // number of .jsonl files scanned
	CorruptLineCount int // number of lines skipped due to parse errors
}

LoadResult captures metrics from an event store Load operation.

type Logger

type Logger interface {
	Info(format string, args ...any)
	OK(format string, args ...any)
	Warn(format string, args ...any)
	Error(format string, args ...any)
	Debug(format string, args ...any)
}

Logger provides structured log output. Implementations must be goroutine-safe.

type NextGenPromptData

type NextGenPromptData struct {
	ClusterName     string
	Completeness    string
	Issues          string
	CompletedWaves  string
	ExistingADRs    []ExistingADR
	RejectedActions string
	FeedbackSection string
	ReportSection   string
	DoDSection      string
	OutputPath      string
	StrictnessLevel string
}

NextGenPromptData holds template data for post-completion wave generation.

type NextGenResult

type NextGenResult struct {
	ClusterName string `json:"cluster_name"`
	Waves       []Wave `json:"waves"`
	Reasoning   string `json:"reasoning"`
}

NextGenResult is the output of post-completion wave generation.

type NextGenWavesAddedPayload

type NextGenWavesAddedPayload struct {
	ClusterName string      `json:"cluster_name"`
	Waves       []WaveState `json:"waves"`
}

NextGenWavesAddedPayload is the payload for EventNextGenWavesAdded.

type NopLogger

type NopLogger struct{}

NopLogger is a no-op logger for testing and quiet mode.

func (*NopLogger) Debug

func (*NopLogger) Debug(string, ...any)

func (*NopLogger) Error

func (*NopLogger) Error(string, ...any)

func (*NopLogger) Info

func (*NopLogger) Info(string, ...any)

func (*NopLogger) OK

func (*NopLogger) OK(string, ...any)

func (*NopLogger) Warn

func (*NopLogger) Warn(string, ...any)

type PipeType

type PipeType int

PipeType represents the type of JSON wire data in the pipe interface.

const (
	PipeTypeUnknown    PipeType = iota
	PipeTypeScanResult          // JSON with top-level "clusters" key
	PipeTypeWavePlan            // JSON with top-level "waves" key
)

func DetectPipeType

func DetectPipeType(data []byte) PipeType

DetectPipeType identifies the wire type of JSON data by checking for the presence of discriminating top-level keys. "clusters" → ScanResult, "waves" → WavePlan.

type Policy

type Policy struct {
	Name    string    // unique identifier for the policy
	Trigger EventType // domain event that activates this policy
	Action  string    // description of the resulting command
}

Policy represents an implicit reactive rule: WHEN [EVENT] THEN [COMMAND]. See ADR S0014 for the POLICY pattern reference.

type Provider added in v0.0.12

type Provider string

Provider identifies which AI coding tool backs a session.

const (
	ProviderClaudeCode Provider = "claude-code"
	ProviderCodex      Provider = "codex"
	ProviderCopilot    Provider = "copilot"
	ProviderGeminiCLI  Provider = "gemini-cli"
	ProviderPi         Provider = "pi"
	ProviderKiro       Provider = "kiro"
)

func ParseProvider added in v0.0.12

func ParseProvider(s string) (Provider, error)

ParseProvider validates and returns a Provider from a raw string.

type ProviderErrorInfo added in v0.0.12

type ProviderErrorInfo struct {
	Kind    ProviderErrorKind
	ResetAt time.Time // parsed reset time (zero if unknown)
}

ProviderErrorInfo holds the classified result of a provider error.

func ClassifyProviderError added in v0.0.12

func ClassifyProviderError(provider Provider, stderr string) ProviderErrorInfo

ClassifyProviderError inspects stderr output and classifies the error based on the provider. Returns ProviderErrorNone if the error is not a rate limit or server error.

func (ProviderErrorInfo) IsTrip added in v0.0.12

func (i ProviderErrorInfo) IsTrip() bool

IsTrip returns true if the error should trip a circuit breaker.

type ProviderErrorKind added in v0.0.12

type ProviderErrorKind int

ProviderErrorKind classifies the type of provider error.

const (
	// ProviderErrorNone indicates no provider-level error (normal failure).
	ProviderErrorNone ProviderErrorKind = iota
	// ProviderErrorRateLimit indicates a rate limit was hit.
	ProviderErrorRateLimit
	// ProviderErrorServer indicates a server-side error (5xx).
	ProviderErrorServer
)

type ReadyLabelPromptData

type ReadyLabelPromptData struct {
	ReadyLabel    string
	ReadyIssueIDs string
}

ReadyLabelPromptData holds template data for the ready label prompt.

type ReadyLabelsAppliedPayload

type ReadyLabelsAppliedPayload struct {
	IssueIDs []string `json:"issue_ids"`
}

ReadyLabelsAppliedPayload is the payload for EventReadyLabelsApplied.

type RepoPath

type RepoPath struct {
	// contains filtered or unexported fields
}

RepoPath is an always-valid, non-empty repository path.

func NewRepoPath

func NewRepoPath(raw string) (RepoPath, error)

func (RepoPath) String

func (r RepoPath) String() string

type ResumeChoice

type ResumeChoice int

ResumeChoice represents the user's choice when a previous session is detected.

const (
	ResumeChoiceResume ResumeChoice = iota
	ResumeChoiceNew
	ResumeChoiceRescan
)

func ParseSessionMode

func ParseSessionMode(s string) (ResumeChoice, error)

ParseSessionMode converts a --session-mode flag value to a ResumeChoice.

type ResumeSessionCommand

type ResumeSessionCommand struct {
	// contains filtered or unexported fields
}

ResumeSessionCommand represents the intent to resume an existing session.

func NewResumeSessionCommand

func NewResumeSessionCommand(repoPath RepoPath, sessionID SessionID) ResumeSessionCommand

func (ResumeSessionCommand) RepoPath

func (c ResumeSessionCommand) RepoPath() RepoPath

func (ResumeSessionCommand) SessionID

func (c ResumeSessionCommand) SessionID() SessionID

type RetryConfig

type RetryConfig struct {
	MaxAttempts  int `yaml:"max_attempts"`
	BaseDelaySec int `yaml:"base_delay_sec"`
}

RetryConfig holds exponential backoff retry settings for Claude subprocess calls.

type ReviewResult added in v0.0.11

type ReviewResult struct {
	Passed   bool   // true if no actionable comments were found
	Output   string // raw review output
	Comments string // extracted review comments (empty if passed)
}

ReviewResult represents the outcome of a code review execution.

type Ripple

type Ripple struct {
	ClusterName string `json:"cluster_name"`
	Description string `json:"description"`
}

Ripple is a cross-cluster effect from applying a wave.

type RunScanCommand

type RunScanCommand struct {
	// contains filtered or unexported fields
}

RunScanCommand represents the intent to run a sightjack scan.

func NewRunScanCommand

func NewRunScanCommand(repoPath RepoPath, dryRun bool) RunScanCommand

func (RunScanCommand) DryRun

func (c RunScanCommand) DryRun() bool

func (RunScanCommand) RepoPath

func (c RunScanCommand) RepoPath() RepoPath

type RunSessionCommand

type RunSessionCommand struct {
	// contains filtered or unexported fields
}

RunSessionCommand represents the intent to start an interactive session.

func NewRunSessionCommand

func NewRunSessionCommand(repoPath RepoPath, dryRun bool) RunSessionCommand

func (RunSessionCommand) DryRun

func (c RunSessionCommand) DryRun() bool

func (RunSessionCommand) RepoPath

func (c RunSessionCommand) RepoPath() RepoPath

type ScanCompletedPayload

type ScanCompletedPayload struct {
	Clusters       []ClusterState `json:"clusters"`
	Completeness   float64        `json:"completeness"`
	ShibitoCount   int            `json:"shibito_count"`
	ScanResultPath string         `json:"scan_result_path"`
	LastScanned    time.Time      `json:"last_scanned"`
}

ScanCompletedPayload is the payload for EventScanCompleted.

type ScanConfig

type ScanConfig struct {
	ChunkSize      int `yaml:"chunk_size"`
	MaxConcurrency int `yaml:"max_concurrency"`
}

ScanConfig holds scan behavior settings.

type ScanRecoveryReport added in v0.0.11

type ScanRecoveryReport struct {
	// Outcomes contains one entry per cluster in the original scan order.
	Outcomes       []ClusterScanOutcome
	SucceededCount int
	FailedCount    int
}

ScanRecoveryReport summarises which clusters succeeded and which failed during wave generation so that callers can present partial results and decide on recovery actions.

func BuildScanRecoveryReport added in v0.0.11

func BuildScanRecoveryReport(clusters []ClusterScanResult, successes []WaveGenerateResult) ScanRecoveryReport

BuildScanRecoveryReport constructs a ScanRecoveryReport by comparing the full cluster list from the scan against the wave generation successes. It delegates failure detection to DetectFailedClusterNames so duplicate cluster names with partial failures are handled correctly.

type ScanResult

type ScanResult struct {
	Clusters        []ClusterScanResult `json:"clusters"`
	TotalIssues     int                 `json:"total_issues"`
	Completeness    float64             `json:"completeness"`
	Observations    []string            `json:"observations"`
	ShibitoWarnings []ShibitoWarning    `json:"shibito_warnings,omitempty"`
	ScanWarnings    []string            `json:"scan_warnings,omitempty"`
}

ScanResult is the merged result of Pass 1 + Pass 2. Wire format: output of `scan --json`.

func (*ScanResult) CalculateCompleteness

func (r *ScanResult) CalculateCompleteness()

CalculateCompleteness computes overall completeness as the average of cluster completeness values, and tallies total issues across all clusters.

func (*ScanResult) ClusterLabels

func (r *ScanResult) ClusterLabels(clusterName string) []string

ClusterLabels returns the labels for a named cluster, or nil if not found.

func (*ScanResult) StrictnessKeys

func (r *ScanResult) StrictnessKeys(clusterName string) []string

StrictnessKeys returns the lookup keys for ResolveStrictness: cluster name + key + labels.

type ScribeADRPromptData

type ScribeADRPromptData struct {
	ClusterName     string
	WaveTitle       string
	WaveActions     string
	Analysis        string
	Reasoning       string
	ADRNumber       string
	OutputPath      string
	StrictnessLevel string
	ExistingADRs    []ExistingADR
}

ScribeADRPromptData holds template data for the scribe ADR generation prompt.

type ScribeConfig

type ScribeConfig struct {
	Enabled           bool `yaml:"enabled"`
	AutoDiscussRounds int  `yaml:"auto_discuss_rounds"`
}

ScribeConfig holds Scribe Agent settings.

type ScribeResponse

type ScribeResponse struct {
	ADRID     string        `json:"adr_id"`
	Title     string        `json:"title"`
	Content   string        `json:"content"`
	Reasoning string        `json:"reasoning"`
	Conflicts []ADRConflict `json:"conflicts,omitempty"`
}

ScribeResponse is the output of the Scribe Agent (ADR generation).

type SessionAggregate

type SessionAggregate struct {
	// contains filtered or unexported fields
}

SessionAggregate owns session lifecycle state and produces events for session transitions.

func NewSessionAggregate

func NewSessionAggregate() *SessionAggregate

NewSessionAggregate creates an empty SessionAggregate.

func (*SessionAggregate) AddNextGenWaves

func (a *SessionAggregate) AddNextGenWaves(payload NextGenWavesAddedPayload, now time.Time) (Event, error)

AddNextGenWaves produces a nextgen_waves_added event.

func (*SessionAggregate) ApplyReadyLabels

func (a *SessionAggregate) ApplyReadyLabels(payload ReadyLabelsAppliedPayload, now time.Time) (Event, error)

ApplyReadyLabels produces a ready_labels_applied event.

func (*SessionAggregate) ApplyWave

func (a *SessionAggregate) ApplyWave(payload WaveAppliedPayload, now time.Time) (Event, error)

ApplyWave produces a wave_applied event.

func (*SessionAggregate) ApproveWave

func (a *SessionAggregate) ApproveWave(waveID, clusterName string, now time.Time) (Event, error)

ApproveWave produces a wave_approved event.

func (*SessionAggregate) CompleteWave

func (a *SessionAggregate) CompleteWave(payload WaveCompletedPayload, now time.Time) (Event, error)

CompleteWave produces a wave_completed event.

func (*SessionAggregate) GenerateADR

func (a *SessionAggregate) GenerateADR(payload ADRGeneratedPayload, now time.Time) (Event, error)

GenerateADR produces an adr_generated event.

func (*SessionAggregate) ModifyWave

func (a *SessionAggregate) ModifyWave(payload WaveModifiedPayload, now time.Time) (Event, error)

ModifyWave produces a wave_modified event.

func (*SessionAggregate) ReceiveFeedback added in v0.0.12

func (a *SessionAggregate) ReceiveFeedback(payload FeedbackReceivedPayload, now time.Time) (Event, error)

ReceiveFeedback produces a feedback_received event.

func (*SessionAggregate) RecordScan

func (a *SessionAggregate) RecordScan(payload ScanCompletedPayload, now time.Time) (Event, error)

RecordScan produces a scan_completed event.

func (*SessionAggregate) RecordWavesGenerated

func (a *SessionAggregate) RecordWavesGenerated(payload WavesGeneratedPayload, now time.Time) (Event, error)

RecordWavesGenerated produces a waves_generated event.

func (*SessionAggregate) RejectWave

func (a *SessionAggregate) RejectWave(waveID, clusterName string, now time.Time) (Event, error)

RejectWave produces a wave_rejected event.

func (*SessionAggregate) Rescan

func (a *SessionAggregate) Rescan(originalSessionID string, now time.Time) (Event, error)

Rescan produces a session_rescanned event.

func (*SessionAggregate) Resume

func (a *SessionAggregate) Resume(originalSessionID string, now time.Time) (Event, error)

Resume produces a session_resumed event.

func (*SessionAggregate) SendFeedback

func (a *SessionAggregate) SendFeedback(waveID, clusterName string, now time.Time) (Event, error)

SendFeedback produces a feedback_sent event.

func (*SessionAggregate) SendReport

func (a *SessionAggregate) SendReport(waveID, clusterName string, now time.Time) (Event, error)

SendReport produces a report_sent event.

func (*SessionAggregate) SendSpecification

func (a *SessionAggregate) SendSpecification(waveID, clusterName string, now time.Time) (Event, error)

SendSpecification produces a specification_sent event.

func (*SessionAggregate) SessionID

func (a *SessionAggregate) SessionID() string

SessionID returns the current session ID.

func (*SessionAggregate) SetSessionID

func (a *SessionAggregate) SetSessionID(id string)

SetSessionID sets the session ID (used for hydration from projection).

func (*SessionAggregate) Start

func (a *SessionAggregate) Start(project, strictness string, now time.Time) (Event, error)

Start produces a session_started event.

func (*SessionAggregate) UnlockWaves

func (a *SessionAggregate) UnlockWaves(unlockedIDs []string, now time.Time) (Event, error)

UnlockWaves produces a waves_unlocked event.

func (*SessionAggregate) UpdateCompleteness

func (a *SessionAggregate) UpdateCompleteness(clusterName string, clusterCompleteness, overallCompleteness float64, now time.Time) (Event, error)

UpdateCompleteness produces a completeness_updated event.

type SessionID

type SessionID struct {
	// contains filtered or unexported fields
}

SessionID is an always-valid, non-empty session identifier.

func NewSessionID

func NewSessionID(raw string) (SessionID, error)

func (SessionID) String

func (s SessionID) String() string

type SessionRescannedPayload

type SessionRescannedPayload struct {
	OriginalSessionID string `json:"original_session_id"`
}

SessionRescannedPayload is the payload for EventSessionRescanned.

type SessionResumedPayload

type SessionResumedPayload struct {
	OriginalSessionID string `json:"original_session_id"`
}

SessionResumedPayload is the payload for EventSessionResumed.

type SessionStartedPayload

type SessionStartedPayload struct {
	Project         string `json:"project"`
	StrictnessLevel string `json:"strictness_level"`
}

SessionStartedPayload is the payload for EventSessionStarted.

type SessionState

type SessionState struct {
	Version         string         `json:"version"`
	SessionID       string         `json:"session_id"`
	Project         string         `json:"project"`
	LastScanned     time.Time      `json:"last_scanned"`
	Completeness    float64        `json:"completeness"`
	Clusters        []ClusterState `json:"clusters"`
	Waves           []WaveState    `json:"waves,omitempty"`
	ADRCount        int            `json:"adr_count,omitempty"`
	ShibitoCount    int            `json:"shibito_count,omitempty"`
	FeedbackCount   int            `json:"feedback_count,omitempty"`
	StrictnessLevel string         `json:"strictness_level,omitempty"`
	ScanResultPath  string         `json:"scan_result_path,omitempty"`
}

SessionState is the materialized view projected from event replay.

func ProjectState

func ProjectState(events []Event) *SessionState

ProjectState replays a sequence of events to produce a SessionState. Unknown event types are silently skipped. Returns a zero-value SessionState for nil/empty input.

func (*SessionState) AllWavesCompleted added in v0.0.12

func (s *SessionState) AllWavesCompleted() bool

AllWavesCompleted returns true if all waves in the session have status "completed". Returns false for an empty wave list.

type SessionStatus added in v0.0.12

type SessionStatus string

SessionStatus tracks the lifecycle of a coding session.

const (
	SessionRunning   SessionStatus = "running"
	SessionCompleted SessionStatus = "completed"
	SessionFailed    SessionStatus = "failed"
	SessionAbandoned SessionStatus = "abandoned"
)

type SessionStreamEvent added in v0.0.12

type SessionStreamEvent struct {
	SchemaVersion     uint8           `json:"v"`
	ID                string          `json:"id"`
	Timestamp         time.Time       `json:"ts"`
	Tool              string          `json:"tool"`
	SessionID         string          `json:"session_id"`
	Provider          Provider        `json:"provider"`
	ProviderSessionID string          `json:"provider_session_id,omitempty"`
	Type              StreamEventType `json:"type"`
	ParentSessionID   string          `json:"parent_session_id,omitempty"`
	SubagentID        string          `json:"subagent_id,omitempty"`
	Data              json.RawMessage `json:"data"`
	Raw               string          `json:"raw,omitempty"`
	RawTruncated      bool            `json:"raw_truncated,omitempty"`
}

SessionStreamEvent is the unified JSONL envelope for live session streaming. Provider-agnostic: all AI coding tools emit events in this format.

func NewSessionStreamEvent added in v0.0.12

func NewSessionStreamEvent(tool string, provider Provider, eventType StreamEventType, data json.RawMessage) SessionStreamEvent

NewSessionStreamEvent creates a new event with schema version, UUID, and timestamp.

func (*SessionStreamEvent) WithRaw added in v0.0.12

func (e *SessionStreamEvent) WithRaw(raw string)

WithRaw attaches the raw provider JSONL line, truncating if necessary.

type ShibitoWarning

type ShibitoWarning struct {
	ClosedIssueID  string `json:"closed_issue_id"`
	CurrentIssueID string `json:"current_issue_id"`
	Description    string `json:"description"`
	RiskLevel      string `json:"risk_level"`
}

ShibitoWarning represents a detected resurrection risk — a previously closed issue pattern re-emerging in current issues.

type SilentError added in v0.0.7

type SilentError struct{ Err error }

ExitCode maps an error to a process exit code.

nil             → 0 (success)
DeviationError  → 2 (deviation detected)
other           → 1 (runtime error)

SilentError wraps an error whose message has already been printed to stderr by the command itself. main.go should suppress output for this error while still honouring the exit code via ExitCode.

func (*SilentError) Error added in v0.0.7

func (e *SilentError) Error() string

func (*SilentError) Unwrap added in v0.0.7

func (e *SilentError) Unwrap() error

type StatusReport

type StatusReport struct {
	LastScanned  time.Time `json:"last_scanned"`
	WavesTotal   int       `json:"waves_total"`
	InboxCount   int       `json:"inbox_count"`
	ArchiveCount int       `json:"archive_count"`
	SuccessRate  float64   `json:"success_rate"`
}

StatusReport holds operational status information for the sightjack tool.

func (StatusReport) FormatJSON

func (r StatusReport) FormatJSON() string

FormatJSON returns the status report as a compact JSON string.

func (StatusReport) FormatText

func (r StatusReport) FormatText() string

FormatText returns a human-readable status report string suitable for stdout.

type StreamEventType added in v0.0.12

type StreamEventType string

StreamEventType identifies the kind of session stream event.

const (
	StreamSessionStart  StreamEventType = "session_start"
	StreamSessionEnd    StreamEventType = "session_end"
	StreamToolUseStart  StreamEventType = "tool_use_start"
	StreamToolResult    StreamEventType = "tool_result"
	StreamAssistantText StreamEventType = "assistant_text"
	StreamThinking      StreamEventType = "thinking"
	StreamHookStart     StreamEventType = "hook_start"
	StreamHookResult    StreamEventType = "hook_result"
	StreamRateLimit     StreamEventType = "rate_limit"
	StreamError         StreamEventType = "error"
	StreamSubagentStart StreamEventType = "subagent_start"
	StreamSubagentEnd   StreamEventType = "subagent_end"
)

type StrictnessConfig

type StrictnessConfig struct {
	Default   StrictnessLevel            `yaml:"default"`
	Overrides map[string]StrictnessLevel `yaml:"overrides"`
}

StrictnessConfig holds user-settable DoD strictness level settings. Overrides are keyed by cluster name or Linear issue label (case-insensitive). Resolution: max(default, estimated, overrides) — strictness only goes up.

type StrictnessLevel

type StrictnessLevel string

StrictnessLevel controls change tolerance for existing implementations.

const (
	StrictnessFog      StrictnessLevel = "fog"
	StrictnessAlert    StrictnessLevel = "alert"
	StrictnessLockdown StrictnessLevel = "lockdown"
)

func ParseStrictnessLevel

func ParseStrictnessLevel(s string) (StrictnessLevel, error)

ParseStrictnessLevel parses a string into a StrictnessLevel. Case-insensitive. Returns error for unknown values.

func ResolveStrictness

func ResolveStrictness(cfg StrictnessConfig, estimated map[string]StrictnessLevel, labels []string) StrictnessLevel

ResolveStrictness determines the effective strictness level for a set of keys. Keys typically include the cluster name followed by Linear issue labels. Matching is case-insensitive. Resolution uses 3-layer max():

base = default
base = max(base, matched estimated values)
base = max(base, matched override values)

Strictness can only go up, never down. The estimated parameter comes from ComputedConfig.EstimatedStrictness.

func (StrictnessLevel) Valid

func (l StrictnessLevel) Valid() bool

Valid returns true if the level is a known strictness value.

type Topic

type Topic struct {
	// contains filtered or unexported fields
}

Topic is an always-valid, non-empty discussion topic.

func NewTopic

func NewTopic(raw string) (Topic, error)

func (Topic) String

func (t Topic) String() string

type TrackingMode added in v0.0.11

type TrackingMode string

TrackingMode determines the issue tracking backend. Wave mode (default) uses D-Mail archive as event source. Linear mode uses Linear MCP for issue tracking (legacy).

const (
	// ModeWave is the default mode: waves and steps drive expedition targeting.
	// D-Mail archive/ is the single source of truth for wave state.
	ModeWave TrackingMode = "wave"

	// ModeLinear uses Linear MCP for issue tracking (existing behavior).
	ModeLinear TrackingMode = "linear"
)

func NewTrackingMode added in v0.0.11

func NewTrackingMode(linear bool) TrackingMode

NewTrackingMode returns ModeLinear when linear is true, ModeWave otherwise.

func (TrackingMode) IsLinear added in v0.0.11

func (m TrackingMode) IsLinear() bool

IsLinear returns true when operating in Linear MCP mode.

func (TrackingMode) IsWave added in v0.0.11

func (m TrackingMode) IsWave() bool

IsWave returns true when operating in Wave-centric mode.

func (TrackingMode) String added in v0.0.11

func (m TrackingMode) String() string

String returns the mode name.

type Wave

type Wave struct {
	ID              string             `json:"id"`
	ClusterName     string             `json:"cluster_name"`
	ClusterKey      string             `json:"cluster_key,omitempty"`
	Title           string             `json:"title"`
	Description     string             `json:"description"`
	Actions         []WaveAction       `json:"actions"`
	Prerequisites   []string           `json:"prerequisites"`
	Delta           WaveDelta          `json:"delta"`
	Status          string             `json:"status"`
	ClusterContext  *ClusterScanResult `json:"cluster_context,omitempty"`
	ComplexityScore float64            `json:"complexity_score,omitempty"`
}

Wave is a unit of work proposed by AI for a cluster. Wire format: input to `discuss` and `apply` subcommands.

func ApplyModifiedWave

func ApplyModifiedWave(original, modified Wave, completed map[string]bool) Wave

ApplyModifiedWave merges a modified wave from the architect into the original, preserving identity fields (ID, ClusterName) so that completion bookkeeping remains stable. Status is recomputed from the modified prerequisites against the completed map to prevent applying waves with unmet dependencies.

func AutoSelectWave

func AutoSelectWave(available []Wave) (Wave, bool)

AutoSelectWave selects the first available wave for auto-approve mode. Returns the selected wave and true if one is available, or zero Wave and false if none.

func AvailableWaves

func AvailableWaves(waves []Wave, completed map[string]bool) []Wave

AvailableWaves returns waves that have "available" status and are not completed, sorted by ascending complexity score. The completed map is keyed by WaveKey (ClusterName:ID).

func CompletedWavesForCluster

func CompletedWavesForCluster(waves []Wave, clusterName string) []Wave

CompletedWavesForCluster returns all completed waves for the given cluster.

func EvaluateUnlocks

func EvaluateUnlocks(waves []Wave, completed map[string]bool) []Wave

EvaluateUnlocks checks locked waves and unlocks them if all prerequisites are met. Prerequisites and the completed map both use the composite "ClusterName:ID" format.

func FilterEmptyWaves added in v0.0.11

func FilterEmptyWaves(waves []Wave) ([]Wave, int)

FilterEmptyWaves removes waves that have zero actions (nil or empty slice). Returns the filtered list and the count of removed waves.

func FilterPROpenActions added in v0.0.12

func FilterPROpenActions(waves []Wave, prOpenIssues map[string]bool) []Wave

FilterPROpenActions removes implementation-oriented actions for issues that already have a PR open (paintress:pr-open label). Issue-management actions (add_dod, add_dependency, etc.) are preserved because sightjack handles them directly. Waves with no remaining actions are removed entirely.

func LastCompletedWaveForCluster added in v0.0.5

func LastCompletedWaveForCluster(waves []Wave, clusterName string) (Wave, bool)

LastCompletedWaveForCluster returns the last completed wave for the given cluster. Waves are assumed to be in insertion order, so the last match wins. Returns false if no completed wave exists for the cluster.

func MergeCompletedStatus

func MergeCompletedStatus(oldCompleted map[string]bool, newWaves []Wave) []Wave

MergeCompletedStatus preserves completed status from a previous session when waves are regenerated after a re-scan. Waves in newWaves that match a key in oldCompleted are marked "completed". Waves that were in the old session but not in newWaves are dropped (Linear removed them).

func MergeOldWaves

func MergeOldWaves(oldWaves, newWaves []Wave, scannedClusters, failedClusterNames map[string]bool) []Wave

MergeOldWaves carries forward waves from clusters that failed wave generation but are still present in the current scan. Old waves whose cluster was removed from the scan (resolved issues, reorganized clusters) are dropped so stale work items do not persist.

func MergeWaveResults

func MergeWaveResults(results []WaveGenerateResult) []Wave

MergeWaveResults flattens multiple per-cluster wave results into a single wave list, normalizing prerequisite IDs to the composite "ClusterName:ID" format and removing self-referencing prerequisites. Results are sorted by complexity score ascending.

func NormalizeWavePrerequisites

func NormalizeWavePrerequisites(waves []Wave) []Wave

NormalizeWavePrerequisites prefixes bare prerequisite IDs with the wave's own cluster name so that all keys in the completed map use the composite format. Prerequisites that already contain ":" are left unchanged.

func RemoveSelfReferences added in v0.0.11

func RemoveSelfReferences(waves []Wave) ([]Wave, int)

RemoveSelfReferences removes prerequisite entries where a wave references itself. Returns the cleaned wave list and the count of removed self-references. Must be called after NormalizeWavePrerequisites (self-references are only detectable once bare IDs have been expanded to composite format).

func RepairLockedWaves added in v0.0.11

func RepairLockedWaves(waves []Wave, completed map[string]bool) ([]Wave, int)

RepairLockedWaves unlocks waves whose prerequisites are all met but status is still "locked". Returns the repaired wave list and the count of repaired waves.

func RestoreWaves

func RestoreWaves(states []WaveState) []Wave

RestoreWaves converts persisted WaveState list back into Wave list for session resume.

func SortWavesByComplexity added in v0.0.11

func SortWavesByComplexity(waves []Wave) []Wave

SortWavesByComplexity returns a new slice of waves sorted by ascending ComplexityScore (actions + 0.5*prereqs). The sort is stable so that waves with equal complexity retain their original relative order. ComplexityScore is populated on each returned wave.

func ValidateWavePrerequisites added in v0.0.11

func ValidateWavePrerequisites(waves []Wave) ([]Wave, int)

ValidateWavePrerequisites removes prerequisites referencing waves not in the wave set. Returns the cleaned wave list and the count of removed dangling prerequisites.

type WaveAction

type WaveAction struct {
	Type        string `json:"type"`
	IssueID     string `json:"issue_id"`
	Description string `json:"description"`
	Detail      string `json:"detail"`
}

WaveAction is a single change proposed within a Wave.

type WaveAggregate

type WaveAggregate struct {
	// contains filtered or unexported fields
}

WaveAggregate owns wave lifecycle state and produces events for state transitions. It wraps domain/ pure functions with event emission.

func NewWaveAggregate

func NewWaveAggregate() *WaveAggregate

NewWaveAggregate creates an empty WaveAggregate.

func (*WaveAggregate) AddNextGen

func (a *WaveAggregate) AddNextGen(clusterName string, waves []WaveState, now time.Time) (Event, error)

AddNextGen produces a nextgen_waves_added event.

func (*WaveAggregate) AllWavesCompleted added in v0.0.11

func (a *WaveAggregate) AllWavesCompleted() bool

AllWavesCompleted reports whether every wave in the aggregate has been completed. Returns false for an empty wave list.

func (*WaveAggregate) Approve

func (a *WaveAggregate) Approve(waveID, clusterName string, now time.Time) (Event, error)

Approve produces a wave_approved event.

func (*WaveAggregate) Complete

func (a *WaveAggregate) Complete(waveID, clusterName string, applied, totalCount int, now time.Time) (Event, error)

Complete produces a wave_completed event and marks the wave as completed.

func (*WaveAggregate) Completed

func (a *WaveAggregate) Completed() map[string]bool

Completed returns the completed map.

func (*WaveAggregate) EvaluateUnlocks

func (a *WaveAggregate) EvaluateUnlocks(now time.Time) ([]Event, error)

EvaluateUnlocks checks locked waves and produces a waves_unlocked event if any are unlocked. Inlines unlock logic to avoid root → internal/domain circular import.

func (*WaveAggregate) IsCompleted

func (a *WaveAggregate) IsCompleted(waveKey string) bool

IsCompleted checks if a wave is completed by its WaveKey.

func (*WaveAggregate) MarkCompleted

func (a *WaveAggregate) MarkCompleted(waveKey string)

MarkCompleted marks a wave as completed by its WaveKey.

func (*WaveAggregate) MarkStalled added in v0.0.11

func (a *WaveAggregate) MarkStalled(waveID, clusterName, reason string, opts ...time.Time) (Event, error)

MarkStalled sets the wave's status to "stalled" and emits an EventWaveStalled event.

func (*WaveAggregate) RecordApplied

func (a *WaveAggregate) RecordApplied(payload WaveAppliedPayload, now time.Time) (Event, error)

RecordApplied produces a wave_applied event.

func (*WaveAggregate) Reject

func (a *WaveAggregate) Reject(waveID, clusterName string, now time.Time) (Event, error)

Reject produces a wave_rejected event.

func (*WaveAggregate) SetCompleted

func (a *WaveAggregate) SetCompleted(completed map[string]bool)

SetCompleted replaces the completed map (used for hydration from projection).

func (*WaveAggregate) SetWaves

func (a *WaveAggregate) SetWaves(waves []Wave)

SetWaves replaces the current wave list (used for hydration from projection).

func (*WaveAggregate) WaveStatusCounts added in v0.0.11

func (a *WaveAggregate) WaveStatusCounts() map[string]int

WaveStatusCounts returns a map of wave status to count across all waves. Possible keys are the status strings present in the wave list (e.g. "available", "locked", "completed").

func (*WaveAggregate) Waves

func (a *WaveAggregate) Waves() []Wave

Waves returns the current wave list.

type WaveAppliedPayload

type WaveAppliedPayload struct {
	WaveID      string   `json:"wave_id"`
	ClusterName string   `json:"cluster_name"`
	Applied     int      `json:"applied"`
	TotalCount  int      `json:"total_count"`
	Errors      []string `json:"errors,omitempty"`
}

WaveAppliedPayload is the payload for EventWaveApplied.

type WaveApplyPromptData

type WaveApplyPromptData struct {
	WaveID          string
	ClusterName     string
	Title           string
	Actions         string
	DoDSection      string
	OutputPath      string
	StrictnessLevel string
	LabelsEnabled   bool
	LabelPrefix     string
	IsWaveMode      bool
}

WaveApplyPromptData holds template data for the wave apply prompt.

type WaveApplyResult

type WaveApplyResult struct {
	WaveID     string   `json:"wave_id"`
	Applied    int      `json:"applied"`
	TotalCount int      `json:"total_count,omitempty"`
	Errors     []string `json:"errors"`
	Ripples    []Ripple `json:"ripples"`
}

WaveApplyResult is the Pass 4 output per wave.

type WaveCompletedPayload

type WaveCompletedPayload struct {
	WaveID      string `json:"wave_id"`
	ClusterName string `json:"cluster_name"`
	Applied     int    `json:"applied"`
	TotalCount  int    `json:"total_count"`
}

WaveCompletedPayload is the payload for EventWaveCompleted.

type WaveDelta

type WaveDelta struct {
	Before float64 `json:"before"`
	After  float64 `json:"after"`
}

WaveDelta holds expected completeness change.

func ClampDelta added in v0.0.11

func ClampDelta(d WaveDelta) WaveDelta

ClampDelta ensures Before and After are within [0, 1] and Before <= After. If Before > After (regression), they are swapped.

type WaveGeneratePromptData

type WaveGeneratePromptData struct {
	ClusterName     string
	Completeness    string
	Issues          string
	Observations    string
	DoDSection      string
	OutputPath      string
	StrictnessLevel string
}

WaveGeneratePromptData holds template data for the wave generation prompt.

type WaveGenerateResult

type WaveGenerateResult struct {
	ClusterName string `json:"cluster_name"`
	Waves       []Wave `json:"waves"`
}

WaveGenerateResult is the Pass 3 output per cluster.

type WaveIdentityPayload

type WaveIdentityPayload struct {
	WaveID      string `json:"wave_id"`
	ClusterName string `json:"cluster_name"`
}

WaveIdentityPayload is a shared payload for events that reference a single wave. Used by: EventWaveApproved, EventWaveRejected, EventSpecificationSent, EventReportSent.

type WaveModification

type WaveModification struct {
	ActionIndex int    `json:"action_index"`
	Change      string `json:"change"`
}

WaveModification describes a change made to a wave action during discussion.

type WaveModifiedPayload

type WaveModifiedPayload struct {
	WaveID      string    `json:"wave_id"`
	ClusterName string    `json:"cluster_name"`
	UpdatedWave WaveState `json:"updated_wave"`
}

WaveModifiedPayload is the payload for EventWaveModified.

type WavePlan

type WavePlan struct {
	Waves      []Wave      `json:"waves"`
	ScanResult *ScanResult `json:"scan_result,omitempty"`
}

WavePlan is the output of `waves` subcommand. Contains generated waves and optionally the scan result for context.

type WaveReference added in v0.0.11

type WaveReference struct {
	ID    string        `yaml:"id" json:"id"`
	Step  string        `yaml:"step,omitempty" json:"step,omitempty"`
	Steps []WaveStepDef `yaml:"steps,omitempty" json:"steps,omitempty"`
}

WaveReference links a D-Mail to a wave and optionally a specific step.

type WaveStalledPayload added in v0.0.11

type WaveStalledPayload struct {
	WaveID      string `json:"wave_id"`
	ClusterName string `json:"cluster_name"`
	Reason      string `json:"reason"`
}

WaveStalledPayload is the payload for EventWaveStalled.

type WaveState

type WaveState struct {
	ID            string       `json:"id"`
	ClusterName   string       `json:"cluster_name"`
	Title         string       `json:"title"`
	Status        string       `json:"status"`
	Prerequisites []string     `json:"prerequisites,omitempty"`
	ActionCount   int          `json:"action_count"`
	Actions       []WaveAction `json:"actions,omitempty"`
	Description   string       `json:"description,omitempty"`
	Delta         WaveDelta    `json:"delta,omitempty"`
}

WaveState is the per-wave state within SessionState.

func BuildWaveStates

func BuildWaveStates(waves []Wave) []WaveState

BuildWaveStates converts Wave list to WaveState list for persistence.

type WaveStepDef added in v0.0.11

type WaveStepDef struct {
	ID            string   `yaml:"id" json:"id"`
	Title         string   `yaml:"title" json:"title"`
	Description   string   `yaml:"description,omitempty" json:"description,omitempty"`
	Targets       []string `yaml:"targets,omitempty" json:"targets,omitempty"`
	Acceptance    string   `yaml:"acceptance,omitempty" json:"acceptance,omitempty"`
	Prerequisites []string `yaml:"prerequisites,omitempty" json:"prerequisites,omitempty"`
}

WaveStepDef defines a single step within a wave specification (D-Mail schema).

type WavesGeneratedPayload

type WavesGeneratedPayload struct {
	Waves []WaveState `json:"waves"`
}

WavesGeneratedPayload is the payload for EventWavesGenerated.

type WavesUnlockedPayload

type WavesUnlockedPayload struct {
	UnlockedWaveIDs []string `json:"unlocked_wave_ids"`
}

WavesUnlockedPayload is the payload for EventWavesUnlocked.

Jump to

Keyboard shortcuts

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