Add dialoguectx packaging, conflictresolve adjudication with HITL routing, workspace context/dialogue/ injection (default on), and goose 00071.
59 lines
1.7 KiB
Go
59 lines
1.7 KiB
Go
package conflictresolve
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
// Store persists conflict adjudications with CAS-style nonce uniqueness.
|
|
type Store struct {
|
|
Pool *pgxpool.Pool
|
|
}
|
|
|
|
// AdjudicationRecord is one durable verdict row.
|
|
type AdjudicationRecord struct {
|
|
ID int64
|
|
TaskRunID string
|
|
ProjectID int64
|
|
FactKey string
|
|
Resolution string
|
|
HITLRoute string
|
|
WinningValue string
|
|
DecidedBy string
|
|
EvidenceDigest string
|
|
Nonce string
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// Persist writes a verdict; duplicate (task_run_id, fact_key, nonce) is ignored.
|
|
func (s *Store) Persist(ctx context.Context, rec AdjudicationRecord) error {
|
|
if s == nil || s.Pool == nil {
|
|
return nil
|
|
}
|
|
if rec.Nonce == "" {
|
|
rec.Nonce = EvidenceDigest(rec.TaskRunID, rec.FactKey, rec.WinningValue, rec.Resolution)
|
|
}
|
|
if rec.EvidenceDigest == "" {
|
|
rec.EvidenceDigest = rec.Nonce
|
|
}
|
|
_, err := s.Pool.Exec(ctx, `
|
|
INSERT INTO context_conflict_adjudications
|
|
(task_run_id, project_id, fact_key, resolution, hitl_route, winning_value, decided_by, evidence_digest, nonce)
|
|
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
|
|
ON CONFLICT (task_run_id, fact_key, nonce) DO NOTHING
|
|
`, rec.TaskRunID, rec.ProjectID, rec.FactKey, rec.Resolution, rec.HITLRoute,
|
|
rec.WinningValue, rec.DecidedBy, rec.EvidenceDigest, rec.Nonce)
|
|
return err
|
|
}
|
|
|
|
// EvidenceDigest builds a stable CAS token for an adjudication.
|
|
func EvidenceDigest(taskRunID, factKey, winning, resolution string) string {
|
|
sum := sha256.Sum256([]byte(fmt.Sprintf("%s|%s|%s|%s", taskRunID, factKey, winning, resolution)))
|
|
return hex.EncodeToString(sum[:16])
|
|
}
|