state

package
v1.5.0 Latest Latest
Warning

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

Go to latest
Published: May 14, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Save

func Save(state *State) error

Save writes the given State to disk.

Types

type AIReview

type AIReview struct {
	Summary  string `json:"summary"`            // rendered final review text (legacy: free-form markdown)
	Findings string `json:"findings,omitempty"` // per-batch raw findings (PR-level only)

	// Structured review output — populated by Phase 5+ review flows.
	// When present, the TUI renders this instead of the legacy Summary field.
	Structured *ReviewOutput `json:"structured,omitempty"`

	// DiffSnapshot records the DiffHash of each file at the time the review
	// was generated. Used to detect staleness when diffs change after a review.
	DiffSnapshot map[string]string `json:"diff_snapshot,omitempty"`

	// SecurityDigest is the AOI pre-scan summary injected into review prompts.
	// Persisted so the TUI can display it even after the review is cached.
	SecurityDigest string `json:"security_digest,omitempty"`

	// DeepFindings from AOI-driven review calls (structured findings with severity, category, etc.)
	DeepFindings []DeepFinding `json:"deep_findings,omitempty"`
}

AIReview stores the result of an AI review for a file or the overall PR.

type DeepDismissal added in v1.4.0

type DeepDismissal struct {
	AOIID     string `json:"aoi_id"`
	Evidence  string `json:"evidence,omitempty"`
	Rationale string `json:"rationale"`
}

DeepDismissal is a dismissed AOI from Phase 3 review.

type DeepFinding added in v1.4.0

type DeepFinding struct {
	FindingID   string `json:"finding_id,omitempty"` // assigned before recheck (e.g. "F-001")
	AOIID       string `json:"aoi_id"`
	File        string `json:"file"`
	Lines       string `json:"lines"`
	Severity    string `json:"severity"` // "critical", "high", "medium", "low", "nit"
	Category    string `json:"category"`
	Subcategory string `json:"subcategory,omitempty"`
	Dimension   string `json:"dimension"`
	Title       string `json:"title"`
	Description string `json:"description"`
	Evidence    string `json:"evidence,omitempty"` // what was verified and found (tool-backed)
	// EvidenceSnippet is 1-3 verbatim lines from File at Lines that
	// prove the finding. Phase 3's prompt requires it, and the
	// in-loop verifier matches this against the file before the
	// finding is accepted — anchoring every claim to text that
	// actually exists at the cited location. Findings whose snippet
	// doesn't match get one refinement round trip and, if still
	// unmatched, are dropped.
	EvidenceSnippet string `json:"evidence_snippet,omitempty"`
	Trigger         string `json:"trigger"`
	Suggestion      string `json:"suggestion,omitempty"`

	// Systemic is set by the recheck parser when a finding came out
	// of the `consolidated` bucket — i.e. it represents a cross-file
	// pattern merged from multiple per-file findings, not an
	// individual issue. The two-pass recheck pipeline uses this to
	// route systemic findings around the per-file dismiss pass
	// (their context is the multi-file aggregation, not any single
	// file). Was previously inferred via an `isSystemic` heuristic
	// (File=="multiple" / Title prefix); the flag is authoritative
	// because the producer sets it explicitly.
	Systemic bool `json:"systemic,omitempty"`
}

DeepFinding is a confirmed issue from Phase 3 review.

type DeepReviewResult added in v1.4.0

type DeepReviewResult struct {
	// Type is "individual" or "grouped".
	Type string `json:"type"`

	// CacheKey is the hash used to look up this result.
	CacheKey string `json:"cache_key"`

	// Category and Subcategory identify the concern area.
	Category    string `json:"category"`
	Subcategory string `json:"subcategory,omitempty"`

	// RawOutput is the LLM's JSON response (unparsed for flexibility).
	RawOutput json.RawMessage `json:"raw_output"`

	// Findings extracted from the LLM output.
	Findings []DeepFinding `json:"findings,omitempty"`

	// Dismissals extracted from the LLM output.
	Dismissals []DeepDismissal `json:"dismissals,omitempty"`

	// CrossCutting observation (grouped reviews only).
	CrossCutting string `json:"cross_cutting,omitempty"`
}

DeepReviewResult stores the cached output of a Phase 3 review call.

type DismissedRecord added in v1.5.0

type DismissedRecord struct {
	FindingID string      `json:"finding_id"`
	Finding   DeepFinding `json:"finding"`
	Rationale string      `json:"rationale"`
}

DismissedRecord is one finding that recheck removed, with the rationale the model gave for removing it. The original finding is kept so the report can render it inline next to the rationale — users need to see what got dismissed, not just that something did.

type FileState

type FileState struct {
	Status          ReviewStatus    `json:"status"`
	DiffHash        string          `json:"diff_hash"`
	Chat            []Message       `json:"chat,omitempty"`
	Purpose         string          `json:"purpose,omitempty"`           // AI-generated description of what the file does
	BatchFindings   string          `json:"batch_findings,omitempty"`    // cached findings from PR-level batch review
	AOIResults      json.RawMessage `json:"aoi_results,omitempty"`       // cached AOI scan result (AOIScanResult JSON)
	AOIContextLines int             `json:"aoi_context_lines,omitempty"` // context lines used when AOI was generated
	FileType        string          `json:"file_type,omitempty"`         // cached file classification (e.g. "handler", "test")
}

FileState holds the review status and chat history for a specific file

type FindingRevalidation added in v1.3.0

type FindingRevalidation struct {
	Verdict    string `json:"verdict"` // "true-positive", "false-positive", "fixed", "uncertain"
	Reasoning  string `json:"reasoning"`
	Confidence string `json:"confidence"` // "high", "medium", "low"
}

FindingRevalidation holds the result of a security revalidation pass.

type Message

type Message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

Message represents a single chat message in an AI conversation

type ReviewFinding

type ReviewFinding struct {
	Severity   string `json:"severity"`             // "critical", "high", "medium", "low", "nit"
	Confidence string `json:"confidence,omitempty"` // "high", "medium", "low" — set by synthesis after verification
	Category   string `json:"category"`             // "bug", "security", "performance", "testing", "style", "architecture", "docs"
	File       string `json:"file"`
	Line       int    `json:"line"`
	Title      string `json:"title"`
	Detail     string `json:"detail"`
	Suggestion string `json:"suggestion,omitempty"`
	CWE        string `json:"cwe,omitempty"`      // e.g. "CWE-89" — populated for security findings
	Resolved   bool   `json:"resolved,omitempty"` // user-toggled or auto-resolved by task completion

	// SourceIDs lists the deep-finding IDs (e.g. "F-001", "F-007") this
	// synthesis finding derives from. One synthesis finding can cite
	// multiple deep findings when synthesis consolidates a systemic
	// pattern across files. Consumers should dereference these against
	// the top-level `deep_findings` list for evidence / trigger / per-
	// site file:line ranges — synthesis findings keep only a single
	// representative file/line and a short narrative.
	//
	// Empty/omitted when synthesis ran without deep findings as input
	// (single-pass review path).
	SourceIDs []string `json:"source_ids,omitempty"`

	// Revalidation — populated by the security revalidation pass (Phase 4).
	Revalidation *FindingRevalidation `json:"revalidation,omitempty"`
}

ReviewFinding is a single finding from the structured review.

func (ReviewFinding) SeverityRank

func (f ReviewFinding) SeverityRank() int

SeverityRank returns a numeric rank for sorting findings by severity (lower = more severe).

type ReviewOutput

type ReviewOutput struct {
	Summary            string          `json:"summary"`
	Verdict            string          `json:"verdict"` // "approve", "request_changes", "comment"
	Findings           []ReviewFinding `json:"findings"`
	MissingTests       []string        `json:"missing_tests"`
	QuestionsForAuthor []string        `json:"questions_for_author"`
}

ReviewOutput is the structured JSON output from a PR review. Both single-pass and multi-pass synthesis produce this format.

type ReviewStatus

type ReviewStatus string

ReviewStatus represents the current review state of a file

const (
	StatusUnreviewed ReviewStatus = "unreviewed"
	StatusReviewed   ReviewStatus = "reviewed"
	StatusModified   ReviewStatus = "modified" // Represents a file that was reviewed but has new changes
)

type State

type State struct {
	PRNumber           string                `json:"pr_number"`
	GlobalChat         []Message             `json:"global_chat,omitempty"`
	Review             *AIReview             `json:"review,omitempty"` // PR-level AI review
	Files              map[string]*FileState `json:"files"`
	ProjectContext     string                `json:"project_context,omitempty"`      // cached project briefing
	ProjectContextHash string                `json:"project_context_hash,omitempty"` // hash of inputs used to generate it
	PRBrief            string                `json:"pr_brief,omitempty"`             // cached PR-specific briefing (comments, prior reviews, CI)
	PRBriefHash        string                `json:"pr_brief_hash,omitempty"`        // hash of inputs used to generate the PR brief

	// DeepReviews caches Phase 3 deep review results. Keyed by a hash of the
	// review inputs (file content + AOI content + focus dimensions for individual;
	// all AOI content + focus dimensions for grouped).
	DeepReviews map[string]*DeepReviewResult `json:"deep_reviews,omitempty"`

	// RecheckCache caches Phase 3b recheck output by hash of the input
	// findings + project context + mode. The value is a serialized
	// []DeepFinding (the cleaned, deduplicated set).
	RecheckCache map[string]json.RawMessage `json:"recheck_cache,omitempty"`

	// SynthesisCache caches Phase 4 synthesis output by hash of the input
	// findings + cross-cutting + project context. The value is a serialized
	// SynthesisResult (audit-package type, opaque to this package).
	SynthesisCache map[string]json.RawMessage `json:"synthesis_cache,omitempty"`

	// DeepFindings is the top-level persisted list of Phase 1 + Phase 1c
	// findings, independent of the synthesized Review object. Populated
	// incrementally as each batch completes so a crash, cancellation, or
	// failed-synthesis still leaves the user with their findings on
	// reopen. The Review tab reads this when state.Review is nil — which
	// is the default in TUI mode where synthesis is skipped.
	DeepFindings []DeepFinding `json:"deep_findings,omitempty"`

	// RecheckDismissals records every finding the Phase 3b recheck pass
	// removed, along with the LLM's rationale. Persisted so the audit
	// report can show users WHY a finding disappeared, and so prompt
	// tuning can be measured (compare dismissal counts and rationales
	// across runs). Replaces the previous "DismissedCount only" output,
	// which routed rationales to log.Printf and lost them.
	RecheckDismissals []DismissedRecord `json:"recheck_dismissals,omitempty"`
	// contains filtered or unexported fields
}

State represents the persisted review state for a single pull request

func Load

func Load(prNumber string) (*State, error)

Load reads the state for a given PR number from disk. If the file does not exist, it returns a new, empty State.

func NewState

func NewState(prNumber string) *State

NewState initializes a new empty state object for a PR

func (*State) AppendDeepFindings added in v1.4.0

func (s *State) AppendDeepFindings(findings []DeepFinding)

AppendDeepFindings adds findings to the top-level list. Holds the write lock for the whole append so concurrent batch goroutines don't drop entries via read-then-write races.

func (*State) ClearAllCaches added in v1.3.0

func (s *State) ClearAllCaches()

ClearAllCaches clears all per-file cached data (batch findings, AOI results) and the PR-level review. Used by forceReReview.

func (*State) ClearDeepFindings added in v1.4.0

func (s *State) ClearDeepFindings()

ClearDeepFindings empties the persisted list. Used when the pipeline starts a fresh review run and wants to discard stale incremental findings before accumulating new ones.

func (*State) ClearDeepReviews added in v1.4.0

func (s *State) ClearDeepReviews()

ClearDeepReviews removes all cached Phase 3 results.

func (*State) ClearPRBrief added in v1.4.0

func (s *State) ClearPRBrief()

ClearPRBrief invalidates the cached PR brief. Use when external state (e.g. the prior AI review) changes in a way that should force regeneration even if the input hash hasn't moved.

func (*State) CollectCachedFindings added in v1.3.0

func (s *State) CollectCachedFindings(paths []string) (combined string, fileFindings map[string]string)

CollectCachedFindings reassembles per-file findings from cache.

func (*State) CountCachedBatchFindings added in v1.4.0

func (s *State) CountCachedBatchFindings(paths []string) int

CountCachedBatchFindings returns how many of the given paths have a non-empty BatchFindings entry in state. Holds the read lock for the entire iteration so the count is consistent against concurrent writers — callers that build their own loops via HasFile + direct Files map access would race.

func (*State) DiffSnapshotFromFiles

func (s *State) DiffSnapshotFromFiles() map[string]string

DiffSnapshotFromFiles returns a snapshot of the current DiffHash for each file in the state. This is meant to be stored on AIReview.DiffSnapshot at the time a review is generated so staleness can be detected later.

func (*State) GetAOIResults added in v1.3.0

func (s *State) GetAOIResults(path string) (json.RawMessage, int)

GetAOIResults returns the cached AOI results for a file, or nil. Also returns the context lines used when the results were generated.

func (*State) GetBatchFindings added in v1.3.0

func (s *State) GetBatchFindings(path string) (purpose, findings string)

GetBatchFindings returns the cached purpose and findings for a file.

func (*State) GetDeepFindings added in v1.4.0

func (s *State) GetDeepFindings() []DeepFinding

GetDeepFindings returns a copy of the persisted deep findings. Returning a copy keeps callers from racing with concurrent writers.

func (*State) GetDeepReview added in v1.4.0

func (s *State) GetDeepReview(key string) *DeepReviewResult

GetDeepReview returns a cached Phase 3 result by key, or nil.

func (*State) GetFileType added in v1.4.0

func (s *State) GetFileType(path string) string

GetFileType returns the cached classification type for a file, or empty string.

func (*State) GetPRBrief added in v1.4.0

func (s *State) GetPRBrief() (brief, inputHash string)

GetPRBrief returns the cached PR brief and its input hash.

func (*State) GetProjectContext added in v1.3.0

func (s *State) GetProjectContext() (summary, inputHash string)

GetProjectContext returns the cached project context and its input hash.

func (*State) GetRecheckCache added in v1.4.0

func (s *State) GetRecheckCache(key string) json.RawMessage

GetRecheckCache returns a cached recheck result by key, or nil.

func (*State) GetRecheckDismissals added in v1.5.0

func (s *State) GetRecheckDismissals() []DismissedRecord

GetRecheckDismissals returns a copy of the persisted dismissal log.

func (*State) GetSynthesisCache added in v1.4.0

func (s *State) GetSynthesisCache(key string) json.RawMessage

GetSynthesisCache returns a cached synthesis result by key, or nil.

func (*State) HasCachedBatch added in v1.3.0

func (s *State) HasCachedBatch(paths []string) bool

HasCachedBatch reports whether all files in the given paths have cached findings.

func (*State) HasFile added in v1.3.0

func (s *State) HasFile(path string) bool

HasFile reports whether a file exists in the state.

func (*State) IsReviewStale

func (s *State) IsReviewStale() bool

IsReviewStale reports whether the stored review's DiffSnapshot differs from the current file diff hashes. A review is considered stale when any file's hash has changed, files have been added, or files have been removed since the review was generated.

func (*State) SetAOIResults added in v1.3.0

func (s *State) SetAOIResults(path string, data json.RawMessage, contextLines int)

SetAOIResults stores AOI scan results for a file along with the context lines used to generate them. Creates the FileState if it doesn't exist.

func (*State) SetBatchFindings added in v1.3.0

func (s *State) SetBatchFindings(path, purpose, findings string)

SetBatchFindings stores the batch review purpose and findings for a file.

func (*State) SetDeepFindings added in v1.4.0

func (s *State) SetDeepFindings(findings []DeepFinding)

SetDeepFindings replaces the persisted top-level deep findings. Used by the pipeline at recheck boundaries (replace) and on load migration. For incremental append during Phase 1, use AppendDeepFindings.

func (*State) SetDeepReview added in v1.4.0

func (s *State) SetDeepReview(key string, result *DeepReviewResult)

SetDeepReview stores a Phase 3 deep review result by cache key.

func (*State) SetFileType added in v1.4.0

func (s *State) SetFileType(path, fileType string)

SetFileType stores the classification type for a file.

func (*State) SetPRBrief added in v1.4.0

func (s *State) SetPRBrief(brief, inputHash string)

SetPRBrief stores a cached PR-specific briefing (summary of comments, prior AI reviews, CI status) and its input hash. Mirrors the SetProjectContext API so callers in internal/prcontext can use it the same way internal/project uses ProjectContext.

func (*State) SetProjectContext added in v1.3.0

func (s *State) SetProjectContext(summary, inputHash string)

SetProjectContext stores a cached project context and its input hash.

func (*State) SetRecheckCache added in v1.4.0

func (s *State) SetRecheckCache(key string, raw json.RawMessage)

SetRecheckCache stores a recheck output (serialized JSON) by cache key.

func (*State) SetRecheckDismissals added in v1.5.0

func (s *State) SetRecheckDismissals(dismissals []DismissedRecord)

SetRecheckDismissals replaces the persisted dismissal log. Called once per recheck run with the full list — recheck dismissals are produced as a batch, not incrementally, so a full overwrite is the right shape (vs. AppendDeepFindings which streams during Phase 3).

func (*State) SetSynthesisCache added in v1.4.0

func (s *State) SetSynthesisCache(key string, raw json.RawMessage)

SetSynthesisCache stores a synthesis output (serialized JSON) by cache key.

func (*State) SyncWithDiffs

func (s *State) SyncWithDiffs(currentDiffHashes map[string]string, prFiles map[string]bool)

SyncWithDiffs compares current diff hashes against stored hashes and invalidates state where necessary. currentDiffHashes maps file path to SHA-256 hash of its current diff (only files where diff succeeded). prFiles is the complete set of files in the PR (used to detect removed files).

Jump to

Keyboard shortcuts

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