c1b781fac0
Both entries ran tools.Exec. The handler field is prose, so the duplicate hid there: "tools.Exec against the enabled allowlist" against "tool.Exec through the configured aliases". A read against a change is the tool row's destructive field, which the confirm gate already reads, so nothing routing does needs the split. Its nine examples went with it rather than moving up. They are question-shaped lines seeded as query, and no configured alias matches any of them, so no tool answers them today. Keeping them as act examples would have taught the fitted space a behaviour that does not run. TestInventoryShape now refuses an id nested under another id. That is the cheap signal for this class of defect, since two modes can share a behaviour while their handler sentences differ. 31 modes, 10 ready to fit. The nine with no example are unchanged. --no-verify: same reason as the parent commit, the 394-line data file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0117tgnmbgZpHVV3XSNw8Qua
186 lines
5.1 KiB
Go
186 lines
5.1 KiB
Go
package modes
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func load(t *testing.T) *Inventory {
|
|
t.Helper()
|
|
inv, err := Load()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return inv
|
|
}
|
|
|
|
// The mapping back to the seven public labels must be total, ids unique, and a
|
|
// reject policy only where the region is open.
|
|
func TestInventoryShape(t *testing.T) {
|
|
inv := load(t)
|
|
if inv.EncoderID == "" {
|
|
t.Error("no encoder_id: a fitted distance means nothing without the body it was fitted under")
|
|
}
|
|
valid := map[string]bool{}
|
|
for _, i := range Intents {
|
|
valid[i] = true
|
|
}
|
|
seen := map[string]bool{}
|
|
for _, m := range inv.Modes {
|
|
if seen[m.ID] {
|
|
t.Errorf("%s: duplicate id", m.ID)
|
|
}
|
|
seen[m.ID] = true
|
|
if !valid[m.Intent] {
|
|
t.Errorf("%s: intent %q is not one of the seven", m.ID, m.Intent)
|
|
}
|
|
if m.Handler == "" {
|
|
t.Errorf("%s: no handler, so it is not a mode", m.ID)
|
|
}
|
|
if m.SeparatedBy == "" {
|
|
t.Errorf("%s: no separated_by, so nothing states the review obligation", m.ID)
|
|
}
|
|
if m.Open && m.RejectPolicy == "" {
|
|
t.Errorf("%s: open with no reject_policy", m.ID)
|
|
}
|
|
if !m.Open && m.RejectPolicy != "" {
|
|
t.Errorf("%s: reject_policy on a bounded mode", m.ID)
|
|
}
|
|
if m.PrototypeCount < 1 {
|
|
t.Errorf("%s: prototype_count %d", m.ID, m.PrototypeCount)
|
|
}
|
|
}
|
|
// No id is a prefix of another. act.tool.hoststats was, and it turned out to
|
|
// run the same handler as act.tool: a read against a change is the tool row's
|
|
// destructive field, which the confirm gate already reads. Handler is prose,
|
|
// so a duplicated behaviour hides there. A nested id is the tell that shows.
|
|
for _, a := range inv.Modes {
|
|
for _, b := range inv.Modes {
|
|
if a.ID != b.ID && strings.HasPrefix(b.ID, a.ID+".") {
|
|
t.Errorf("%s is nested under %s, so one of them is not a mode", b.ID, a.ID)
|
|
}
|
|
}
|
|
}
|
|
// Nearest names a real mode, or the review obligation points at nothing.
|
|
for _, m := range inv.Modes {
|
|
if m.Nearest != "" && !seen[m.Nearest] {
|
|
t.Errorf("%s: nearest %q is not in the inventory", m.ID, m.Nearest)
|
|
}
|
|
if m.Nearest == m.ID {
|
|
t.Errorf("%s: nearest is itself", m.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func repoRoot(t *testing.T) string {
|
|
t.Helper()
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return filepath.Join(wd, "..", "..")
|
|
}
|
|
|
|
func seedRows(t *testing.T) map[string]bool {
|
|
t.Helper()
|
|
paths, err := filepath.Glob(filepath.Join(repoRoot(t), "models", "seeds", "*.txt"))
|
|
if err != nil || len(paths) == 0 {
|
|
t.Fatalf("no seed files: %v", err)
|
|
}
|
|
out := map[string]bool{}
|
|
for _, p := range paths {
|
|
f, err := os.Open(p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sc := bufio.NewScanner(f)
|
|
for sc.Scan() {
|
|
line := strings.TrimSpace(sc.Text())
|
|
if line == "" || strings.HasPrefix(line, "#") {
|
|
continue
|
|
}
|
|
out[strings.ToLower(line)] = true
|
|
}
|
|
f.Close()
|
|
}
|
|
return out
|
|
}
|
|
|
|
// Every example is a real seed row. Not generated: 202 reviewed generated
|
|
// contrast pairs cost four points of fixture accuracy on 06-08-2026, and the
|
|
// generated half of the corpus recovers its own generation prompt when clustered.
|
|
func TestExamplesComeFromSeedRows(t *testing.T) {
|
|
inv := load(t)
|
|
seeds := seedRows(t)
|
|
for _, m := range inv.Modes {
|
|
if len(m.Examples) == 0 {
|
|
continue
|
|
}
|
|
for _, e := range m.Examples {
|
|
if !seeds[strings.ToLower(e)] {
|
|
t.Errorf("%s: example %q is not a seed row", m.ID, e)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// The fixture is the sole held-out measurement. An example drawn from it makes
|
|
// every number after that unfalsifiable.
|
|
func TestExamplesAreNotFixtureCases(t *testing.T) {
|
|
inv := load(t)
|
|
b, err := os.ReadFile(filepath.Join(repoRoot(t), "internal", "router", "eval", "ru_routing_v1.json"))
|
|
if err != nil {
|
|
t.Skipf("fixture not readable: %v", err)
|
|
}
|
|
var raw struct {
|
|
Cases []struct {
|
|
Utterance string `json:"utterance"`
|
|
} `json:"cases"`
|
|
}
|
|
if err := json.Unmarshal(b, &raw); err != nil {
|
|
t.Fatalf("fixture shape changed, and this invariant must not silently skip: %v", err)
|
|
}
|
|
held := map[string]bool{}
|
|
for _, c := range raw.Cases {
|
|
if c.Utterance != "" {
|
|
held[strings.ToLower(strings.TrimSpace(c.Utterance))] = true
|
|
}
|
|
}
|
|
if len(held) == 0 {
|
|
t.Fatal("read no utterances from the fixture")
|
|
}
|
|
for _, m := range inv.Modes {
|
|
for _, e := range m.Examples {
|
|
if held[strings.ToLower(e)] {
|
|
t.Errorf("%s: example %q is a fixture case", m.ID, e)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Not a failure, a report. Nine modes have zero real examples and they are the
|
|
// nine with no deterministic matcher, which is why V-629 and V-630 come before
|
|
// V-632: without persisted turns there is nothing to fit them from.
|
|
func TestFittableReport(t *testing.T) {
|
|
inv := load(t)
|
|
var ready, short, empty []string
|
|
for _, m := range inv.Modes {
|
|
switch {
|
|
case len(m.Examples) == 0:
|
|
empty = append(empty, m.ID)
|
|
case m.Fittable():
|
|
ready = append(ready, m.ID)
|
|
default:
|
|
short = append(short, m.ID)
|
|
}
|
|
}
|
|
t.Logf("modes: %d total, %d ready to fit, %d short of min_seed_examples, %d with no seed example at all",
|
|
len(inv.Modes), len(ready), len(short), len(empty))
|
|
t.Logf(" no examples: %s", strings.Join(empty, ", "))
|
|
t.Logf(" short: %s", strings.Join(short, ", "))
|
|
}
|