agent-orchestrator/backend/internal/ports/tracker_observations.go

108 lines
4.3 KiB
Go

// This file defines provider-neutral Tracker DTOs used at the boundary between
// the (future) Tracker observer, persistence layer, and lifecycle manager. The
// shape mirrors ports.SCMObservation so the lifecycle reducer in
// lifecycle.Manager has the same "Fetched + ObservedAt + normalized facts +
// Changed discriminator" contract for both lanes.
package ports
import (
"time"
"github.com/aoagents/agent-orchestrator/backend/internal/domain"
)
// TrackerObservation is the provider-neutral issue observation emitted by the
// Tracker observer and consumed by lifecycle.Manager.ApplyTrackerFacts.
// Provider adapters normalize their tracker-specific payloads into this DTO
// before the observer persists/notifies.
type TrackerObservation struct {
// Fetched is true only when the provider refresh succeeded and the nested
// facts are authoritative for this poll.
Fetched bool
// ObservedAt is the observer timestamp for this normalized snapshot.
ObservedAt time.Time
// Provider is the normalized tracker provider name, e.g. "github".
Provider string
// Host is the tracker host that served this observation.
Host string
// Repo is the full repository/project name shown to AO users, usually
// "owner/name" for GitHub-issue trackers.
Repo string
// Issue contains the normalized issue facts (state, assignee, title, body).
Issue TrackerIssueObservation
// Comments contains the normalized comments observed on the issue. The
// observer is responsible for windowing/dedup; lifecycle treats every
// entry as a fact about the current snapshot.
Comments []TrackerCommentObservation
// Changed marks which semantic buckets changed compared with the DB snapshot.
Changed TrackerChanged
}
// TrackerChanged marks which semantic state buckets changed in the successful
// poll. The discriminator lets lifecycle skip work cheaply when only one
// bucket moved; today it also lets the reducer fire reactions on the right
// edges (assignee-only change vs comment-only change).
type TrackerChanged struct {
// State is true when Issue.State changed since the last persisted snapshot.
State bool
// Assignee is true when Issue.Assignee changed since the last persisted snapshot.
Assignee bool
// Comments is true when the comment set changed (new comment, edit, or removal).
Comments bool
}
// TrackerIssueObservation carries the normalized issue facts. The field set is
// deliberately the minimum that lifecycle reactions need today; provider
// adapters keep richer per-provider metadata behind their own packages.
type TrackerIssueObservation struct {
// URL is the canonical issue browser URL used as the persistence key.
URL string
// Number is the provider's issue number within the repository/project.
Number int
// State is AO's normalized issue state from domain.NormalizedIssueState
// (open, in_progress, review, done, cancelled).
State domain.NormalizedIssueState
// Title is the provider issue title.
Title string
// Body is the issue description as plain text/markdown.
Body string
// Assignee is the login/identifier of the currently primary assignee, or
// "" when the issue is unassigned. Multi-assignee tracking is not part of
// the lifecycle contract today.
Assignee string
// Author is the login/name of the issue author.
Author string
// Labels is the normalized label set on the issue.
Labels []string
// CreatedAtProvider is the provider's issue creation timestamp.
CreatedAtProvider time.Time
// UpdatedAtProvider is the provider's last issue update timestamp.
UpdatedAtProvider time.Time
// ClosedAtProvider is the provider's close timestamp when the issue is closed.
ClosedAtProvider time.Time
}
// TrackerCommentObservation is one normalized issue comment.
type TrackerCommentObservation struct {
// ID is the provider's stable comment identifier.
ID string
// Author is the provider login/name of the commenter.
Author string
// Body is the comment text.
Body string
// URL is a provider link to the comment.
URL string
// IsBot is true when the provider identifies the author as a bot. The
// lifecycle reducer treats new bot comments as actionable nudges.
IsBot bool
// CreatedAtProvider is the provider's comment creation timestamp.
CreatedAtProvider time.Time
// UpdatedAtProvider is the provider's last comment update timestamp when
// the provider exposes one.
UpdatedAtProvider time.Time
}