Why: Project retrieval hits, tool results, and saved visible analysis must be individually traceable and fully analyzed before later project actions consume them. Evidence: RED tests first showed missing run-source capture, tool-result capture, and run-wide preflight; go test -p 1 ./... and go build ./... passed; isolated PostgreSQL source, migration, audit, and context tests passed. Impact: Persist actual run-bound sources with current-status checks and exact manifests behind the disabled X3 assembly gate; no live product path, migration, deployment, or release is enabled. Refs: TT-N03, TT-R01; approved X3 stage-five plan r1
131 lines
6.0 KiB
Go
131 lines
6.0 KiB
Go
package extension
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
core "agent-system-core"
|
|
)
|
|
|
|
// WorkObservation is built by the host from a committed message or an actual
|
|
// retrieval, tool, or visible analysis result. Callers and models cannot supply
|
|
// Actor, ProjectID, source identity, or the source authorization epoch.
|
|
// RunID may be empty for a newly committed user message or chat command.
|
|
type WorkObservation struct {
|
|
EventID string `json:"eventId"`
|
|
Phase string `json:"phase"`
|
|
Actor string `json:"actor"`
|
|
Owner string `json:"owner"`
|
|
ProjectID core.ID `json:"projectId"`
|
|
ConversationID core.ID `json:"conversationId,omitempty"`
|
|
RunID core.ID `json:"runId,omitempty"`
|
|
SourceKind string `json:"sourceKind"`
|
|
SourceID string `json:"sourceId"`
|
|
SourceVersion string `json:"sourceVersion"`
|
|
SourceSHA256 string `json:"sourceSha256"`
|
|
PartIndex int `json:"partIndex"`
|
|
SpanStart int `json:"spanStart"` // UTF-8 byte offset in the exact source
|
|
SpanEnd int `json:"spanEnd"`
|
|
Text string `json:"text,omitempty"` // only the actual authorized fragment
|
|
Scope string `json:"scope"` // private|project|controlled
|
|
Delivery string `json:"delivery"` // complete|summary-only|partial
|
|
DeliveryReason string `json:"deliveryReason,omitempty"`
|
|
Metadata map[string]string `json:"metadata,omitempty"`
|
|
AuthorizationEpoch string `json:"authorizationEpoch"`
|
|
ObservedAt time.Time `json:"observedAt"`
|
|
}
|
|
|
|
type WorkObservationState string
|
|
|
|
const (
|
|
WorkObservationAccepted WorkObservationState = "accepted" // durable intake, analysis may be pending
|
|
WorkObservationPending WorkObservationState = "pending"
|
|
WorkObservationDenied WorkObservationState = "denied"
|
|
WorkObservationPartial WorkObservationState = "partial"
|
|
)
|
|
|
|
type WorkObservationResult struct {
|
|
ReceiptID string `json:"receiptId"`
|
|
State WorkObservationState `json:"state"`
|
|
Reason string `json:"reason,omitempty"`
|
|
}
|
|
|
|
// ProjectWorkSource is one exact part consumed by the pending action. A hash
|
|
// mismatch or missing part must block Preflight rather than use a stale receipt.
|
|
type ProjectWorkSource struct {
|
|
EventID string `json:"eventId"`
|
|
SourceKind string `json:"sourceKind"`
|
|
SourceID string `json:"sourceId"`
|
|
SourceVersion string `json:"sourceVersion"`
|
|
SourceSHA256 string `json:"sourceSha256"`
|
|
PartIndex int `json:"partIndex"`
|
|
}
|
|
|
|
// ProjectWorkAction is constructed by the host immediately before model use,
|
|
// project command dispatch, or another project-affecting action. ProjectID is
|
|
// checked against the stored conversation or run, never trusted from Params.
|
|
type ProjectWorkAction struct {
|
|
Actor string `json:"actor"`
|
|
Owner string `json:"owner"`
|
|
ProjectID core.ID `json:"projectId"`
|
|
ConversationID core.ID `json:"conversationId,omitempty"`
|
|
RunID core.ID `json:"runId,omitempty"`
|
|
Action string `json:"action"`
|
|
TargetID string `json:"targetId,omitempty"`
|
|
TargetVersion string `json:"targetVersion,omitempty"`
|
|
Manifest []ProjectWorkSource `json:"manifest"`
|
|
SourceWatermark string `json:"sourceWatermark"`
|
|
}
|
|
|
|
type ProjectWorkDecisionState string
|
|
|
|
const (
|
|
ProjectWorkProceed ProjectWorkDecisionState = "proceed"
|
|
ProjectWorkClarify ProjectWorkDecisionState = "clarify"
|
|
ProjectWorkPending ProjectWorkDecisionState = "pending"
|
|
ProjectWorkDenied ProjectWorkDecisionState = "denied"
|
|
)
|
|
|
|
// ProjectWorkDecision is a domain decision, not a replacement for a controlled
|
|
// document's separate one-time human approval. A successful Observe ACK cannot
|
|
// be interpreted as ProjectWorkProceed.
|
|
type ProjectWorkDecision struct {
|
|
State ProjectWorkDecisionState `json:"state"`
|
|
DecisionID string `json:"decisionId"`
|
|
RiskID string `json:"riskId,omitempty"`
|
|
RiskRevision string `json:"riskRevision,omitempty"`
|
|
SourceWatermark string `json:"sourceWatermark,omitempty"`
|
|
Reason string `json:"reason,omitempty"`
|
|
Question string `json:"question,omitempty"`
|
|
Options []string `json:"options,omitempty"`
|
|
}
|
|
|
|
// ProjectRiskAnswer comes from a current authenticated session and persisted
|
|
// risk card. An answer is applied only after the provider commits a CAS receipt.
|
|
type ProjectRiskAnswer struct {
|
|
Actor string `json:"actor"`
|
|
Owner string `json:"owner"`
|
|
ProjectID core.ID `json:"projectId"`
|
|
RiskID string `json:"riskId"`
|
|
RiskRevision string `json:"riskRevision"`
|
|
Answer string `json:"answer"`
|
|
IdempotencyKey string `json:"idempotencyKey"`
|
|
}
|
|
|
|
// ProjectWorkObserver is owned by the project domain. Backend must check a
|
|
// returned decision against the exact current source manifest and must fail
|
|
// closed on missing provider, timeout, or partial analysis when project facts
|
|
// are required. RDM remains the sole persistent risk-state owner.
|
|
type ProjectWorkObserver struct {
|
|
Observe func(context.Context, WorkObservation) (WorkObservationResult, error)
|
|
Preflight func(context.Context, ProjectWorkAction) (ProjectWorkDecision, error)
|
|
Respond func(context.Context, ProjectRiskAnswer) (ProjectWorkDecision, error)
|
|
}
|
|
|
|
// ProjectWorkObservationRegistry is optional so older in-process extensions do
|
|
// not acquire a mandatory Registry method. Declarative plugins cannot register
|
|
// a callback. The host accepts one trusted RDM provider.
|
|
type ProjectWorkObservationRegistry interface {
|
|
RegisterProjectWorkObserver(ProjectWorkObserver) error
|
|
}
|