phase 2: matrix.downgrade reads WeakModels from config
migrate the strong-model auto-downgrade gate from a hardcoded weak list to cfg.Models.WeakModels. backward compatible: existing API preserved, callers that don't migrate keep using DefaultWeakModels. changes: - internal/matrix/downgrade.go: split IsWeakModel into rule-based base (`:free` suffix/infix) + literal-list lookup. New IsWeakModelInList(model, list) takes the config-supplied list. DowngradeInput grows a WeakModels field; nil falls back to DefaultWeakModels (preserves pre-phase-2 behavior). - internal/workflow/modes.go: add MatrixDowngradeWithWeakList(list) factory mirroring MatrixSearch's pattern. Plain MatrixDowngrade kept for backward compat. - cmd/matrixd/main.go: handlers struct holds weakModels populated from cfg.Models.WeakModels at startup; handleDowngrade threads it into every DowngradeInput. - cmd/observerd/main.go: registerBuiltinModes accepts weakModels and uses the factory variant. observerd reads cfg.Models.WeakModels in main(). end-to-end verified: downgrade + matrix + observer + workflow smokes all pass. Existing TestMaybeDowngrade_TruthTable + TestIsWeakModel unchanged (backward compat). Two new tests cover the config path: - TestIsWeakModelInList — covers rule + literal + empty + nil - TestMaybeDowngrade_WithConfigList — verifies cfg list overrides default Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,40 @@ func MatrixDowngrade(_ Context, input map[string]any) (map[string]any, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MatrixDowngradeWithWeakList is the config-driven variant of
|
||||
// MatrixDowngrade — callers pass cfg.Models.WeakModels at startup
|
||||
// and the closure includes that list in every DowngradeInput.
|
||||
// nil/empty list falls back to matrix.DefaultWeakModels (matching the
|
||||
// plain MatrixDowngrade behavior).
|
||||
func MatrixDowngradeWithWeakList(weakModels []string) Mode {
|
||||
return func(_ Context, input map[string]any) (map[string]any, error) {
|
||||
var req struct {
|
||||
Mode string `json:"mode"`
|
||||
Model string `json:"model"`
|
||||
ForcedMode bool `json:"forced_mode"`
|
||||
ForceFullOverride bool `json:"force_full_override"`
|
||||
}
|
||||
if err := remarshalInput(input, &req); err != nil {
|
||||
return nil, fmt.Errorf("matrix.downgrade: %w", err)
|
||||
}
|
||||
if req.Mode == "" || req.Model == "" {
|
||||
return nil, fmt.Errorf("matrix.downgrade: mode and model are required")
|
||||
}
|
||||
dec := matrix.MaybeDowngrade(matrix.DowngradeInput{
|
||||
Mode: req.Mode,
|
||||
Model: req.Model,
|
||||
ForcedMode: req.ForcedMode,
|
||||
ForceFullOverride: req.ForceFullOverride,
|
||||
WeakModels: weakModels,
|
||||
})
|
||||
return map[string]any{
|
||||
"mode": dec.Mode,
|
||||
"downgraded_from": dec.DowngradedFrom,
|
||||
"reason": dec.Reason,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// DistillationScore wraps distillation.ScoreRecord — re-runs the
|
||||
// scorer over a single EvidenceRecord. Useful as a workflow node
|
||||
// that grades a freshly-produced evidence row.
|
||||
|
||||
Reference in New Issue
Block a user