Persist validated_only shadow plans without executing, gate elevated tiers behind INTENT_PLAN_PROJECT_ALLOWLIST, and keep legacy chat routing for shadow.
87 lines
2.9 KiB
Go
87 lines
2.9 KiB
Go
package intentflow
|
|
|
|
import "sync/atomic"
|
|
|
|
// RolloutMetrics is the in-process I2 counter set used for shadow reconciliation
|
|
// and allowlist gates. Durable plan facts still flow through intent.plan.* events.
|
|
type RolloutMetrics struct {
|
|
PlansCreated atomic.Int64
|
|
ShadowPlans atomic.Int64
|
|
AutoReadPlans atomic.Int64
|
|
ConfirmPlans atomic.Int64
|
|
AllowlistDenied atomic.Int64
|
|
CounterfactualWouldExecute atomic.Int64
|
|
CounterfactualWouldConfirm atomic.Int64
|
|
CounterfactualWouldClarify atomic.Int64
|
|
CounterfactualWouldReject atomic.Int64
|
|
CounterfactualPassthrough atomic.Int64
|
|
ReconciliationDiffs atomic.Int64
|
|
}
|
|
|
|
var globalMetrics RolloutMetrics
|
|
|
|
// Metrics returns the process-wide rollout counters.
|
|
func Metrics() *RolloutMetrics { return &globalMetrics }
|
|
|
|
// Snapshot is a plain copy for tests and admin surfaces.
|
|
type MetricsSnapshot struct {
|
|
PlansCreated int64 `json:"plans_created"`
|
|
ShadowPlans int64 `json:"shadow_plans"`
|
|
AutoReadPlans int64 `json:"auto_read_plans"`
|
|
ConfirmPlans int64 `json:"confirm_plans"`
|
|
AllowlistDenied int64 `json:"allowlist_denied"`
|
|
CounterfactualWouldExecute int64 `json:"cf_would_execute"`
|
|
CounterfactualWouldConfirm int64 `json:"cf_would_confirm"`
|
|
CounterfactualWouldClarify int64 `json:"cf_would_clarify"`
|
|
CounterfactualWouldReject int64 `json:"cf_would_reject"`
|
|
CounterfactualPassthrough int64 `json:"cf_passthrough"`
|
|
ReconciliationDiffs int64 `json:"reconciliation_diffs"`
|
|
}
|
|
|
|
func (m *RolloutMetrics) Snapshot() MetricsSnapshot {
|
|
if m == nil {
|
|
return MetricsSnapshot{}
|
|
}
|
|
return MetricsSnapshot{
|
|
PlansCreated: m.PlansCreated.Load(),
|
|
ShadowPlans: m.ShadowPlans.Load(),
|
|
AutoReadPlans: m.AutoReadPlans.Load(),
|
|
ConfirmPlans: m.ConfirmPlans.Load(),
|
|
AllowlistDenied: m.AllowlistDenied.Load(),
|
|
CounterfactualWouldExecute: m.CounterfactualWouldExecute.Load(),
|
|
CounterfactualWouldConfirm: m.CounterfactualWouldConfirm.Load(),
|
|
CounterfactualWouldClarify: m.CounterfactualWouldClarify.Load(),
|
|
CounterfactualWouldReject: m.CounterfactualWouldReject.Load(),
|
|
CounterfactualPassthrough: m.CounterfactualPassthrough.Load(),
|
|
ReconciliationDiffs: m.ReconciliationDiffs.Load(),
|
|
}
|
|
}
|
|
|
|
func ResetMetricsForTest() {
|
|
globalMetrics = RolloutMetrics{}
|
|
}
|
|
|
|
const (
|
|
cfWouldExecute = "would_execute"
|
|
cfWouldConfirm = "would_confirm"
|
|
cfWouldClarify = "would_clarify"
|
|
cfWouldReject = "would_reject"
|
|
cfPassthrough = "would_passthrough"
|
|
)
|
|
|
|
func recordCounterfactual(route string) {
|
|
m := Metrics()
|
|
switch route {
|
|
case cfWouldExecute:
|
|
m.CounterfactualWouldExecute.Add(1)
|
|
case cfWouldConfirm:
|
|
m.CounterfactualWouldConfirm.Add(1)
|
|
case cfWouldClarify:
|
|
m.CounterfactualWouldClarify.Add(1)
|
|
case cfWouldReject:
|
|
m.CounterfactualWouldReject.Add(1)
|
|
default:
|
|
m.CounterfactualPassthrough.Add(1)
|
|
}
|
|
}
|