Files
weichen dc29b84cdf feat(ctx): inject cleaned project dialogue into squad and assistant
Add dialoguectx packaging, conflictresolve adjudication with HITL routing,
workspace context/dialogue/ injection (default on), and goose 00071.
2026-09-24 17:04:04 +00:00

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])
}