completioncandidate

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package completioncandidate implements detection rules that surface GTD tasks that appear done but whose status is still pending or in_progress.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Candidate

type Candidate struct {
	ID                uuid.UUID
	WorkspaceID       *uuid.UUID
	TaskID            uuid.UUID
	RepoName          string
	Reason            Reason
	EvidenceRefs      []string
	Confidence        Confidence
	SuggestedArtifact string
	Status            Status
	DetectedAt        time.Time
	ResolvedAt        *time.Time
}

Candidate is the domain model for a completion_candidates row.

type Confidence

type Confidence string

Confidence represents how certain the detection rule is about the candidate.

const (
	ConfidenceHigh   Confidence = "high"
	ConfidenceMedium Confidence = "medium"
	ConfidenceLow    Confidence = "low"
)

type DetectParams

type DetectParams struct {
	WorkspaceID    *uuid.UUID
	StaleThreshold time.Duration // default 24h; hours of inactivity before flagging in_progress task
	LookbackDays   int           // default 7, max 30; days of activity_log to scan
}

DetectParams holds the detection configuration for DetectAndUpsert.

type PgStore

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

PgStore is the Postgres-backed implementation of Store.

func NewPgStore

func NewPgStore(pool *pgxpool.Pool, workspaceID *uuid.UUID) *PgStore

NewPgStore creates a Postgres-backed Store.

func (*PgStore) DetectAndUpsert

func (s *PgStore) DetectAndUpsert(ctx context.Context, p DetectParams) ([]Candidate, error)

DetectAndUpsert runs all 4 detection rules and upserts results.

func (*PgStore) ListPendingCandidates

func (s *PgStore) ListPendingCandidates(ctx context.Context, workspaceID *uuid.UUID) ([]Candidate, error)

ListPendingCandidates returns candidates with status='pending' scoped to the store's workspace (or the provided workspaceID override).

func (*PgStore) PruneResolved

func (s *PgStore) PruneResolved(ctx context.Context, olderThan time.Duration) (int64, error)

PruneResolved deletes candidates whose resolved_at is older than olderThan.

func (*PgStore) UpsertCandidate

func (s *PgStore) UpsertCandidate(ctx context.Context, p UpsertParams) (*Candidate, error)

UpsertCandidate inserts or refreshes a candidate identified by (task_id, reason).

func (*PgStore) WriteAutoApplied

func (s *PgStore) WriteAutoApplied(
	ctx context.Context,
	taskID uuid.UUID,
	evidenceRefs []string,
	suggestedArtifact string,
) error

WriteAutoApplied inserts (or refreshes) a completion_candidates row with status='auto_applied' reason='artifact_evidence'. Used by reconcile_merged_prs (sprint feature/gtd-enforce-server-side GTD-fix 9/12) to audit the auto-close.

ON CONFLICT (task_id, reason) the existing row is updated: detected_at refreshed, evidence_refs replaced, suggested_artifact set, AND status forced to 'auto_applied' (in contrast to UpsertCandidate which preserves existing status). This ensures a previously pending candidate flips to auto_applied on the second pass.

type Reason

type Reason string

Reason identifies which detection rule produced the candidate.

const (
	ReasonStaleInProgress  Reason = "stale_in_progress"
	ReasonFinishWorkGap    Reason = "finish_work_gap"
	ReasonArtifactEvidence Reason = "artifact_evidence"
	ReasonCompletionSignal Reason = "completion_signal"
	// ReasonPRMerged indicates a fuzzy-matched PR likely closes this task.
	// Surfaced by the Phase 2 reconcile detector (GTD-fix 10/12, sprint
	// feature/0519-gtd-reconcile-phase2) for tasks whose branch_name and
	// pr_url linkage are both NULL — i.e. legacy backlog where the GTD-fix
	// 9/12 exact-match path can never apply. Confidence is always 'medium'
	// (not 'high') so the candidate enters the manual-accept queue; this
	// matcher MUST NOT auto-apply because Jaccard similarity false-positives
	// are common enough that silent task closure would damage trust.
	ReasonPRMerged Reason = "pr_merged_fuzzy"
)

type SQLiteStore

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

SQLiteStore is the SQLite-backed implementation of Store. It accepts a *sql.DB directly so list queries (sql.Rows) can be used. Wiring in cmd/server/main.go passes the connection extracted from wbtsqlite.DB via its ExecContext-family public methods.

func NewSQLiteStore

func NewSQLiteStore(db *sql.DB, workspaceID string) *SQLiteStore

NewSQLiteStore creates a SQLiteStore backed by the given *sql.DB and optional workspace UUID string. workspaceID may be "" for unscoped mode.

func (*SQLiteStore) DetectAndUpsert

func (s *SQLiteStore) DetectAndUpsert(ctx context.Context, p DetectParams) ([]Candidate, error)

DetectAndUpsert runs all 4 detection rules and upserts results.

func (*SQLiteStore) ListPendingCandidates

func (s *SQLiteStore) ListPendingCandidates(ctx context.Context, workspaceID *uuid.UUID) ([]Candidate, error)

ListPendingCandidates returns candidates with status='pending', scoped to the store's workspace (or the provided workspaceID override).

func (*SQLiteStore) PruneResolved

func (s *SQLiteStore) PruneResolved(ctx context.Context, olderThan time.Duration) (int64, error)

PruneResolved deletes candidates whose resolved_at is older than olderThan.

func (*SQLiteStore) UpsertCandidate

func (s *SQLiteStore) UpsertCandidate(ctx context.Context, p UpsertParams) (*Candidate, error)

UpsertCandidate inserts or refreshes a candidate identified by (task_id, reason). On conflict (task_id, reason) detected_at, confidence, and evidence_refs are updated.

func (*SQLiteStore) WriteAutoApplied

func (s *SQLiteStore) WriteAutoApplied(
	ctx context.Context,
	taskID uuid.UUID,
	evidenceRefs []string,
	suggestedArtifact string,
) error

WriteAutoApplied inserts (or refreshes) a completion_candidates row with status='auto_applied' reason='artifact_evidence'. SQLite-side parity for the reconcile_merged_prs flow; see Store interface doc + the Postgres twin.

type Status

type Status string

Status represents the lifecycle of a completion candidate.

const (
	StatusPending     Status = "pending"
	StatusAccepted    Status = "accepted"
	StatusRejected    Status = "rejected"
	StatusAutoApplied Status = "auto_applied"
)

type Store

type Store interface {
	// ListPendingCandidates returns all candidates with status='pending',
	// optionally filtered to the given workspace.
	ListPendingCandidates(ctx context.Context, workspaceID *uuid.UUID) ([]Candidate, error)

	// UpsertCandidate inserts or updates a candidate identified by (task_id, reason).
	// On conflict (task_id, reason) the detected_at is refreshed and confidence updated.
	UpsertCandidate(ctx context.Context, p UpsertParams) (*Candidate, error)

	// PruneResolved deletes resolved candidates older than olderThan. Returns the
	// number of rows deleted.
	PruneResolved(ctx context.Context, olderThan time.Duration) (int64, error)

	// DetectAndUpsert runs all 4 detection rules against the tasks / work_sessions /
	// activity_log tables and upserts any matches into completion_candidates.
	// Returns all upserted candidates (including previously pending ones that were
	// refreshed). Read-only for tasks; writes to completion_candidates only.
	DetectAndUpsert(ctx context.Context, p DetectParams) ([]Candidate, error)

	// WriteAutoApplied inserts a completion_candidates row recording an auto-apply
	// event (status='auto_applied', reason='artifact_evidence'). Used by the
	// reconcile_merged_prs flow (sprint feature/gtd-enforce-server-side
	// GTD-fix 9/12) to audit-log which task was auto-closed by which PR.
	//
	// On conflict (task_id, reason) the existing row is refreshed (detected_at
	// updated, evidence_refs replaced, suggested_artifact set, status forced to
	// auto_applied so a previously-pending candidate is closed). This mirrors
	// the UpsertCandidate ON CONFLICT semantics but additionally forces the
	// status column.
	WriteAutoApplied(ctx context.Context, taskID uuid.UUID, evidenceRefs []string, suggestedArtifact string) error
}

Store is the backend-agnostic interface for the completioncandidate domain. Both SQLite and Postgres stores must satisfy this interface.

type UpsertParams

type UpsertParams struct {
	WorkspaceID       *uuid.UUID
	TaskID            uuid.UUID
	RepoName          string
	Reason            Reason
	EvidenceRefs      []string
	Confidence        Confidence
	SuggestedArtifact string
}

UpsertParams holds the inputs for creating or updating a candidate.

Jump to

Keyboard shortcuts

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