Documentation
¶
Overview ¶
Package curate is the Phase-2 grooming agent: it dedups the KB backlog, gates the decision-ready queue on incident resolution, surfaces recurring blind spots as knowledge-gap issues, and drives lifecycle/decay. It writes to the forge only — it never merges and never touches a human-labelled artifact.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ClosedPRLister ¶ added in v0.4.0
type ClosedPRLister interface {
ListClosedUnmergedPRsByLabel(ctx context.Context, label string) ([]providers.CuratedIssue, error)
}
ClosedPRLister lists closed-but-unmerged KB PRs carrying a label. Merged PRs are accepted entries (never suppressed) and are filtered out by the implementation.
type ClosedPRSuppression ¶ added in v0.4.0
type ClosedPRSuppression struct {
Forge ClosedPRLister
}
ClosedPRSuppression derives the suppression set on every run from the forge's closed-unmerged KB PRs — no mutable store or watermark, mirroring Recurrence's idempotent, ledger-driven design. The forge retains closed PRs, and each carries the same hidden DupFingerprint marker the drafter stamped, so the set is reconstructable each pass. A markerless (legacy/hand-filed) close is skipped: there is no stable key to suppress or count it on.
func (ClosedPRSuppression) Suppressed ¶ added in v0.4.0
func (s ClosedPRSuppression) Suppressed(ctx context.Context) (map[string]SuppressedEntry, error)
Suppressed implements SuppressionSource.
type Dedup ¶
type Dedup struct {
Forge Forge
Threshold float64 // title-Jaccard fallback threshold for markerless PRs; default 0.6 when 0
Log *slog.Logger
}
Dedup collapses near-identical open KB PRs: the lowest-numbered PR in a cluster is canonical; the rest are closed with a back-ref comment. Conservative by design (high similarity threshold) — a missed merge is cheaper than a wrong close.
type Forge ¶
type Forge interface {
ListPRsByLabel(ctx context.Context, label string) ([]providers.CuratedIssue, error)
ListIssuesByLabel(ctx context.Context, label string) ([]providers.CuratedIssue, error)
Comment(ctx context.Context, number int, body string) error
ReplaceLabel(ctx context.Context, number int, remove, add string) error
Close(ctx context.Context, number int) error
OpenIssue(ctx context.Context, inv providers.Investigation) (providers.Ref, error)
}
Forge is the forge surface the groomer needs (all read/label/close — never merge).
type LedgerResolutionChecker ¶
LedgerResolutionChecker reports a curated PR's incident has resolved when the outcome ledger holds a matching resolved episode. The join is keyed on the deterministic dedup fingerprint (resource+cause) carried in the PR body and stamped on every ledger open — stable across the LLM's prose, so a reworded re-investigation of one incident still resolves the matching PR. A PR filed before the fingerprint was wired carries no marker; it falls back to a whitespace-normalized title join. Source-agnostic: it reads the ledger's episodes, never a trigger-specific API.
func (LedgerResolutionChecker) IsResolved ¶
func (c LedgerResolutionChecker) IsResolved(_ context.Context, pr providers.CuratedIssue) (bool, error)
IsResolved implements ResolutionChecker.
type Lifecycle ¶
type Lifecycle struct {
Forge Forge
StaleAfter time.Duration // 0 disables the sweep
Now func() time.Time // injectable clock; nil ⇒ time.Now
Log *slog.Logger
}
Lifecycle closes stale, unprotected KB artifacts — those with no forge activity within StaleAfter. A PR whose age is unknown (zero UpdatedAt) is never closed.
type Pass ¶
Pass is one grooming pass (dedup, queue, lifecycle…). Each is independent and resilient: a pass error is logged, not fatal — the agent runs the rest.
type Queue ¶
type Queue struct {
Forge Forge
Checker ResolutionChecker
Log *slog.Logger
}
Queue applies the merge condition: a quality-passing (solved) PR becomes ready-to-merge when the incident is resolved, OR when a human has labelled it accepted. Unresolved + unaccepted PRs wait (surfaced, never auto-queued).
type Recurrence ¶
type Recurrence struct {
Forge Forge
Ledger interface {
Episodes() ([]outcome.Episode, error)
}
Threshold int // default 3 when 0
// Suppressed, when set, is the set of KB entries a human closed WITHOUT merging
// (keyed by DupFingerprint). Their episodes are counted SEPARATELY — silently,
// keyed on the fingerprint — and, past the threshold, escalate via a knowledge-gap
// issue that LINKS the closed PR ("closed unmerged but recurred N times —
// reconsider?") instead of the plain gap message. A close-without-merge is a
// deliberate "no": we respect it and never reopen the PR. Nil disables the branch
// (behaviour is then identical to the pre-suppression pass).
Suppressed SuppressionSource
Log *slog.Logger
}
Recurrence opens ONE knowledge-gap issue when an unresolved incident pattern recurs at least Threshold times. It is ledger-driven and idempotent: it recomputes counts from the outcome ledger every run and opens an issue only when no knowledge-gap issue for that pattern already exists — so re-running never double-opens (no mutable store or watermark).
func (Recurrence) Run ¶
func (r Recurrence) Run(ctx context.Context) error
Run opens a knowledge-gap issue for each pattern that crosses the threshold and has none open yet. Episodes belonging to a suppressed (closed-unmerged) entry are routed to a separate escalation that links the closed PR rather than the generic gap issue.
type ResolutionChecker ¶
type ResolutionChecker interface {
IsResolved(ctx context.Context, pr providers.CuratedIssue) (bool, error)
}
ResolutionChecker reports whether the incident behind a curated PR has cleared (alert resolved / resource healthy). Implemented read-only over the cluster.
type SuppressedEntry ¶ added in v0.4.0
type SuppressedEntry struct {
Fingerprint string // curator DupFingerprint (resource+cause); the join key against ledger episodes
PRNumber int // the closed-unmerged KB PR to reference in the escalation
Reason string // the close-reason label, when one distinguishes it (e.g. "wontfix"); "" otherwise
}
SuppressedEntry is a KB entry a human closed WITHOUT merging — a deliberate "not knowledge-base-worthy". It is keyed on the entry's DupFingerprint so the recurrence pass can keep counting the incident silently and, past the threshold, escalate via a knowledge-gap issue that LINKS the closed PR — never reopening it.
type SuppressionSource ¶ added in v0.4.0
type SuppressionSource interface {
Suppressed(ctx context.Context) (map[string]SuppressedEntry, error)
}
SuppressionSource yields the set of suppressed fingerprints (closed-unmerged KB entries a human rejected), keyed by DupFingerprint. Recurrence consults it to escalate-via-issue instead of re-litigating a human "no".