reflector

package
v0.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 26, 2026 License: None detected not legal advice Imports: 0 Imported by: 0

Documentation

Overview

Package reflector is the umbrella namespace for the "Reflector" product abstraction: a family of three sibling interfaces -- validator.Validator, evolve.Evaluator, evolve.Reflector -- that each reflect on an artifact and emit, respectively, a commit verdict, a fitness score, or a replay-time side effect. This package defines no new top-level interface. It hosts type-safe adapters so a concrete implementation of one sibling can satisfy another sibling's signature, giving consumers "replaceability" (any of rule / LLM / ML backing can be plugged in wherever any sibling interface is expected) without forcing every author to write three copies.

Why three interfaces stay separate:

  • validator.Validator is a synchronous commit gate. Input is a staged DiffInput, output is a Verdict with Severity. Negative verdict blocks the commit.
  • evolve.Evaluator is a cheap scorer used in candidate-ranking / GA loops. Input is a Candidate (opaque Payload), output is a scalar fitness plus optional breakdown.
  • evolve.Reflector is fire-and-forget replay consumer. Input is a ReplayEvent pushed by LogReplayer, output is error only (err is logged, never halts the replayer).

A merged super-interface would force Reflector to fabricate a synthetic Verdict or force Validator to carry replay semantics. Neither fits. Go idiom is small interfaces composed via wrappers (io.Reader / io.Closer / io.ReadCloser), not one God interface.

What this package delivers:

ValidatorAsEvaluator   wraps validator.Validator as evolve.Evaluator
EvaluatorAsValidator   wraps evolve.Evaluator    as validator.Validator
ValidatorAsReflector   wraps validator.Validator as evolve.Reflector (side-channel)
EvaluatorAsReflector   wraps evolve.Evaluator    as evolve.Reflector (side-channel)

The reverse direction (Reflector -> Validator / Evaluator) is intentionally absent: Reflector.OnEvent has no return payload from which a synchronous Verdict or fitness can be reconstructed.

Replaceability guarantee. Each adapter returns the target interface type directly. A call site written against validator.Validator can be wired with a native impl or with EvaluatorAsValidator(...); the swap is a single construction-site line, and the rest of the call site stays free of reflector imports.

Concurrency. Wrapped implementations must be goroutine-safe. A single underlying Validator / Evaluator may be fan-out wrapped by several adapters (e.g. ValidatorAsEvaluator + ValidatorAsReflector) and therefore reached from multiple goroutines concurrently. If the underlying impl is not goroutine-safe, wrap a synchronizing decorator before passing it to the adapter.

反射器产品抽象的伞形命名空间. 三个同族接口 validator.Validator / evolve.Evaluator / evolve.Reflector 各自对一个待审对象做反思, 分别 产出 commit verdict / fitness / 回放副作用. 本包不引入新的顶层接口, 只提供类型安全的 adapter, 让一个具体实现同时满足另一个同族接口签名. "可替换性" 由此兑现 (规则 / LLM / ML 后端可互换接入任一同族接口的 调用点), 实现方不必重写三份.

为什么三个接口保持独立:

  • validator.Validator 是同步 commit 闸. 输入 staged DiffInput, 输出 带 Severity 的 Verdict. 否决即阻断 commit.
  • evolve.Evaluator 是候选排序 / GA 循环里的便宜打分器. 输入 Candidate (Payload 不透明), 输出标量 fitness 与可选 breakdown.
  • evolve.Reflector 是 fire-and-forget 的回放消费者. 输入 ReplayEvent, 输出仅 error (只记录, 不打断 replayer).

合一的超级接口要么逼 Reflector 伪造 Verdict, 要么逼 Validator 承担 回放语义, 都别扭. Go 惯例是小接口通过 wrapper 组合 (io.Reader / io.Closer / io.ReadCloser), 不是一个 God interface.

本包提供的 adapter:

ValidatorAsEvaluator   把 validator.Validator 包为 evolve.Evaluator
EvaluatorAsValidator   把 evolve.Evaluator    包为 validator.Validator
ValidatorAsReflector   把 validator.Validator 包为 evolve.Reflector (旁路)
EvaluatorAsReflector   把 evolve.Evaluator    包为 evolve.Reflector (旁路)

反向 (Reflector -> Validator / Evaluator) 刻意不做: OnEvent 无返回载荷, 无法反推同步 Verdict 或 fitness.

可替换性保证. 每个 adapter 直接返回目标接口类型. 针对 validator.Validator 写的调用点既可注入原生实现, 也可注入 EvaluatorAsValidator(...); 切换是 构造点一行改动, 其他调用代码不污染 reflector import.

并发语义. 被包装的实现必须 goroutine-safe. 同一底层 Validator / Evaluator 可能被多个 adapter 扇出包装 (例如 ValidatorAsEvaluator + ValidatorAsReflector), 因此会被多 goroutine 并发调用. 若底层实现非 goroutine-safe, 在传入 adapter 前套一层同步装饰器.

Example (EvaluatorAsValidator)

Example_evaluatorAsValidator wraps an evolve.Evaluator as a validator.Validator so a GA-style scorer can plug into the commit-gate pipeline without rewriting the scorer against the Validator interface.

Example_evaluatorAsValidator 把 evolve.Evaluator 包为 validator.Validator, 让 GA 式打分器直接接入 commit-gate 流水线, 无需 针对 Validator 接口重写打分器.

package main

import (
	"context"
	"encoding/json"
	"fmt"

	"git.flytoex.net/yuanwei/flyto-agent/pkg/evolve"
	"git.flytoex.net/yuanwei/flyto-agent/pkg/reflector"
	"git.flytoex.net/yuanwei/flyto-agent/pkg/validator"
)

func main() {
	scorer, _ := evolve.NewFuncEvaluator(func(_ context.Context, c evolve.Candidate) (float64, map[string]float64, error) {
		payload, _ := c.Payload.(map[string]any)
		if payload["risky"] == true {
			return 0.2, map[string]float64{"risk": 0.8}, nil
		}
		return 0.9, map[string]float64{"risk": 0.1}, nil
	})

	extract := func(d validator.DiffInput) (evolve.Candidate, error) {
		var payload map[string]any
		if err := json.Unmarshal(d.Raw, &payload); err != nil {
			return evolve.Candidate{}, err
		}
		return evolve.Candidate{ID: d.SourceTool, Payload: payload}, nil
	}

	v := reflector.EvaluatorAsValidator(scorer, extract, 0.5,
		reflector.WithName("ga-gate"),
		reflector.WithPolicyVersion("2026-04"),
	)

	vd, _ := v.Validate(context.Background(), validator.DiffInput{
		SourceTool: "SQLCAS",
		Raw:        []byte(`{"risky": true}`),
	})

	fmt.Println(v.Name(), vd.Approved, vd.Severity)
}
Output:
ga-gate false block

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrExtractFailed = errors.New("reflector: extractor failed")

ErrExtractFailed wraps any error returned by a caller-supplied extractor function. Adapters return it with %w so callers can detect the class with errors.Is.

ErrExtractFailed 包装 extractor 回调返回的 error. adapter 以 %w 透出, 调用方用 errors.Is 识别.

Functions

func EvaluatorAsReflector

func EvaluatorAsReflector(src evolve.Evaluator, extract EventToCandidate, sink FitnessSink) evolve.Reflector

EvaluatorAsReflector wraps an evolve.Evaluator so it satisfies evolve.Reflector for side-channel replay scoring. extract turns each ReplayEvent into a Candidate; sink receives the resulting fitness, breakdown, and any Score error or ErrExtractFailed. OnEvent always returns nil.

Panics at construction if src, extract or sink is nil.

EvaluatorAsReflector 把 evolve.Evaluator 包为 evolve.Reflector 做 回放旁路打分. extract 把 ReplayEvent 转为 Candidate; sink 收到产出 的 fitness / breakdown / Score error 或 ErrExtractFailed. OnEvent 始终返回 nil.

构造时 src / extract / sink 任一为 nil 直接 panic.

func EvaluatorAsValidator

func EvaluatorAsValidator(src evolve.Evaluator, extract DiffToCandidate, threshold float64, opts ...EvaluatorAsValidatorOption) validator.Validator

EvaluatorAsValidator wraps an evolve.Evaluator so it satisfies validator.Validator. extract turns each DiffInput into a Candidate the underlying Evaluator can score. fitness >= threshold yields Approved=true with SeverityWarn; below yields Approved=false with Severity controlled by WithBelowThresholdSeverity (default Block). breakdown is forwarded into Verdict.Details.

Panics at construction if src or extract is nil.

EvaluatorAsValidator 把 evolve.Evaluator 包为 validator.Validator. extract 把每个 DiffInput 转为 Candidate 交给底层 Evaluator 打分. fitness >= threshold 产出 Approved=true 且 SeverityWarn; 低于阈值 产出 Approved=false 且 Severity 由 WithBelowThresholdSeverity 控制 (默认 Block). breakdown 透传至 Verdict.Details.

构造时 src 或 extract 为 nil 直接 panic.

func ValidatorAsEvaluator

func ValidatorAsEvaluator(src validator.Validator, extract CandidateToDiff, opts ...ValidatorAsEvaluatorOption) evolve.Evaluator

ValidatorAsEvaluator wraps a validator.Validator so it satisfies evolve.Evaluator. extract turns each Candidate into a DiffInput the underlying Validator can review. If Verdict.Approved is true, the returned fitness is Verdict.Score. Otherwise fitness is 0 (override via WithRejectFitness). Verdict.Details is forwarded into breakdown on a best-effort basis (only numeric entries survive).

Panics at construction if src or extract is nil -- both are mandatory and nil indicates a programming error that should surface early rather than at the first Score call.

ValidatorAsEvaluator 把 validator.Validator 包为 evolve.Evaluator. extract 把每个 Candidate 转为 DiffInput 交给底层 Validator 审查. Verdict.Approved=true 时返回 fitness=Verdict.Score; 否则返回 0 (可用 WithRejectFitness 覆写). Verdict.Details 尽力透传为 breakdown (仅数值条目存活).

构造时 src 或 extract 为 nil 直接 panic -- 两者均为必传, nil 是编程 错误应尽早暴露.

func ValidatorAsReflector

func ValidatorAsReflector(src validator.Validator, extract EventToDiff, sink VerdictSink) evolve.Reflector

ValidatorAsReflector wraps a validator.Validator so it satisfies evolve.Reflector for side-channel replay observation. extract turns each ReplayEvent into a DiffInput; sink receives the resulting Verdict along with any Validate error or ErrExtractFailed. OnEvent always returns nil (Reflector contract: never halt the replayer), so extract / Validate errors flow through sink only.

Panics at construction if src, extract or sink is nil.

ValidatorAsReflector 把 validator.Validator 包为 evolve.Reflector 做回放旁路观察. extract 把 ReplayEvent 转为 DiffInput; sink 收到 产出的 Verdict 及 Validate error 或 ErrExtractFailed. OnEvent 始终 返回 nil (Reflector 契约: 不中断 replayer), extract / Validate 错误 仅通过 sink 传出.

构造时 src / extract / sink 任一为 nil 直接 panic.

Types

type CandidateToDiff

type CandidateToDiff func(c evolve.Candidate) (validator.DiffInput, error)

CandidateToDiff converts an evolve.Candidate into a validator.DiffInput. A non-nil error aborts the conversion; adapters wrap it with ErrExtractFailed before propagating.

CandidateToDiff 把 evolve.Candidate 转为 validator.DiffInput. 返回非 nil error 则终止转换, adapter 以 ErrExtractFailed 包装透出.

type DiffToCandidate

type DiffToCandidate func(d validator.DiffInput) (evolve.Candidate, error)

DiffToCandidate converts a validator.DiffInput into an evolve.Candidate.

DiffToCandidate 把 validator.DiffInput 转为 evolve.Candidate.

type EvaluatorAsValidatorOption

type EvaluatorAsValidatorOption func(*evaluatorAsValidatorConfig)

EvaluatorAsValidatorOption configures EvaluatorAsValidator.

EvaluatorAsValidatorOption 配置 EvaluatorAsValidator.

func WithBelowThresholdSeverity

func WithBelowThresholdSeverity(s validator.Severity) EvaluatorAsValidatorOption

WithBelowThresholdSeverity controls the Severity attached to the Verdict when fitness < threshold. Default is validator.SeverityBlock (fail-closed). Set to validator.SeverityWarn for advisory-only scoring.

WithBelowThresholdSeverity 控制 fitness < threshold 时 Verdict 的 Severity. 默认 validator.SeverityBlock (fail-closed). 可设为 validator.SeverityWarn 作为 advisory-only 打分.

func WithName

WithName overrides the adapter's Name(). Default is "evaluator-as-validator". Validators in the same process must not share a Name; if two EvaluatorAsValidator instances coexist, at least one must carry an explicit WithName.

WithName 覆写 adapter 的 Name(). 默认 "evaluator-as-validator". 同 进程内 Validator 不能同名; 若两个 EvaluatorAsValidator 共存, 至少 一个必须显式传 WithName.

func WithPolicyVersion

func WithPolicyVersion(v string) EvaluatorAsValidatorOption

WithPolicyVersion sets the PolicyVersion field the adapter stamps on every Verdict it emits, so replay audits can tell which policy version approved or rejected a past diff.

WithPolicyVersion 设置 adapter 在产出 Verdict 时写入的 PolicyVersion 字段, 便于回放审计判断当时的策略版本.

type EventToCandidate

type EventToCandidate func(ev evolve.ReplayEvent) (evolve.Candidate, error)

EventToCandidate converts an evolve.ReplayEvent into an evolve.Candidate for side-channel scoring during replay.

EventToCandidate 把 evolve.ReplayEvent 转为 evolve.Candidate, 用于 回放期旁路打分.

type EventToDiff

type EventToDiff func(ev evolve.ReplayEvent) (validator.DiffInput, error)

EventToDiff converts an evolve.ReplayEvent into a validator.DiffInput for side-channel validation during replay.

EventToDiff 把 evolve.ReplayEvent 转为 validator.DiffInput, 用于 回放期旁路校验.

type FitnessSink

type FitnessSink func(ev evolve.ReplayEvent, fitness float64, breakdown map[string]float64, err error)

FitnessSink receives each fitness score produced by EvaluatorAsReflector, plus breakdown and any Score error (or ErrExtractFailed). Same contract as VerdictSink.

FitnessSink 接收 EvaluatorAsReflector 产出的 fitness, 附带 breakdown 与 Score error (或 ErrExtractFailed). 契约与 VerdictSink 一致.

type ValidatorAsEvaluatorOption

type ValidatorAsEvaluatorOption func(*validatorAsEvaluatorConfig)

ValidatorAsEvaluatorOption configures ValidatorAsEvaluator.

ValidatorAsEvaluatorOption 配置 ValidatorAsEvaluator.

func WithRejectFitness

func WithRejectFitness(f float64) ValidatorAsEvaluatorOption

WithRejectFitness sets the fitness value ValidatorAsEvaluator emits when Verdict.Approved is false. Default is 0, which is the safe choice (GA tournaments will not prefer a rejected candidate over an approved one with any positive score). Set to a positive value to preserve gradient signal for GA use cases that need to differentiate "barely rejected" from "hard rejected".

WithRejectFitness 设置 ValidatorAsEvaluator 在 Verdict.Approved=false 时产出的 fitness. 默认 0, 保守选择 (GA 锦标选择不会把"被拒候选" 排在"通过+任意正分"之前). 设为正值可保留 GA 梯度信号, 用于区分 "微拒" 与 "硬拒".

type VerdictSink

type VerdictSink func(ev evolve.ReplayEvent, v validator.Verdict, err error)

VerdictSink receives each Verdict produced by ValidatorAsReflector, along with the originating ReplayEvent and any Validate error (or ErrExtractFailed from a failing extractor). The sink is how the side-channel signal leaves the adapter (log, metric, audit, parameter-evolver backpressure). OnEvent itself always returns nil so it never stops the replayer loop.

VerdictSink 接收 ValidatorAsReflector 产出的每个 Verdict, 附带触发 的 ReplayEvent 与 Validate error (或 extractor 失败时的 ErrExtractFailed). sink 是旁路信号离开 adapter 的唯一出口 (日志 / 指标 / 审计 / 反压给 ParameterEvolver). OnEvent 始终返回 nil, 不中断 replayer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL