Files
SivanCola 525d397009 feat(studio): offer Standard and Minimal Agent modes
Problem: the shipped catalog and composer exposed more mode choices and status
badges than the requested Standard/Minimal workflow needs.

Fix: ship two native compositions, with a full-configuration Standard mode
and a terminal/image Minimal mode using a concise persona. Preserve retained
bindings and report retired defaults explicitly. Separate built-in cards from
custom presets, keep only the mode name in the trigger, and place run status
at the right. Keep source/lock details in the accessible label and menu.

Verification: gofmt, go vet, make lint/check, required boot/builtin tests,
complete root and Desktop Go suites, frontend typecheck/build and 5,343 tests.
Provider-boundary and custom read-only fixtures retain capability-denial
coverage. Browser checks cover light/dark, 1440px/390px and locked controls.
2026-10-18 00:28:15 +08:00

48 lines
1.7 KiB
Go

package agent
import (
"context"
"strings"
"testing"
"reasonix/internal/contract/agentcomposition"
"reasonix/internal/contract/tool"
"reasonix/internal/state/sessionstore"
)
func TestChildCompositionKeepsExactBindingAndIntersectsProfileCeiling(t *testing.T) {
d := agentcomposition.Builtins()[0]
d.ID = "user:reader"
d.Tools = agentcomposition.Selection{Mode: agentcomposition.Select, Members: []agentcomposition.Module{{ID: "read_file"}, {ID: "grep"}}}
d.Persona.Prefix = "PARENT PERSONA"
b := &agentcomposition.Binding{Resolved: d, Version: agentcomposition.Version{Definition: d, Revision: agentcomposition.Revision(d)}}
b.Seal()
ctx := context.WithValue(t.Context(), compositionContextKey{}, b)
s := sessionstore.NewSession("child instructions")
if err := BindChildComposition(ctx, s, true); err != nil {
t.Fatal(err)
}
if s.Composition().Digest != b.Digest || !strings.Contains(s.Snapshot()[0].Content, "PARENT PERSONA") {
t.Fatal("child lost binding or persona")
}
reg := tool.NewRegistry()
reg.Add(namedSchemaTool{name: "read_file", schema: `{"type":"object"}`})
reg.Add(namedSchemaTool{name: "bash", schema: `{"type":"object"}`})
restrictChildComposition(ctx, reg)
for _, name := range []string{"bash", "write_file", "grep"} {
reg.Add(namedSchemaTool{name: name, schema: `{"type":"object"}`})
if _, ok := reg.Get(name); ok {
t.Fatalf("child widened through %s", name)
}
}
if _, ok := reg.Get("read_file"); !ok {
t.Fatal("intersection dropped allowed reader")
}
other := agentcomposition.Clone(b)
other.Resolved.Persona.Prefix = "OTHER"
other.Seal()
if err := BindChildComposition(context.WithValue(ctx, compositionContextKey{}, other), s, true); err == nil {
t.Fatal("continued child accepted another binding")
}
}