mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
3a54d5ff53
Collapse the four drifted cmd/ao host-seam shapes into one shared clicontract.HostOptions consumed by all 17 command modules; delete the positional-func and bespoke-struct seams and the doctor GlobalOptions bundle. - clicontract/host.go: single HostOptions union (OutputMode/Verbose/Verbosef/ DryRun/ProjectRoot/GoalsPath/LedgerPath/Version/Now/EnrichFlagErr), one shared WriteJSON (byte-identical to the three deleted copies), one shared ExitError (Label field preserves doctor's stderr surfacing; gate stays silent). - config_module.go + doctor_module.go: package-level module/service singletons -> newConfigCommand()/newDoctorCommand() constructors; 7 allowlist rows removed. - carveout_regression_test.go: three AST drift guards (shared seam type / no direct host effects / no module-service singleton vars), each RED-proven. - docs/architecture/go-cli.md: document the intentional two-tier shape (5 full hexagonal, 12 app-seam); drop the stale opportunistic-extraction sentence. Zero behavior change: ao -o json capabilities byte-identical; full suite + -shuffle=on -count=2 green; 0 lint issues; gate check --full 67/67.
81 lines
2.1 KiB
Go
81 lines
2.1 KiB
Go
package init
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/boshu2/agentops/cli/internal/clicontract"
|
|
)
|
|
|
|
func newTestModule(dryRun bool) Module {
|
|
return NewModule(clicontract.HostOptions{DryRun: func() bool { return dryRun }})
|
|
}
|
|
|
|
func TestModule_Contract(t *testing.T) {
|
|
contract := newTestModule(false).Contract()
|
|
if contract.ID != "ao.init" {
|
|
t.Fatalf("contract ID = %q, want ao.init", contract.ID)
|
|
}
|
|
if contract.Output != clicontract.OutputText {
|
|
t.Fatalf("output = %v, want OutputText", contract.Output)
|
|
}
|
|
if contract.Effects&clicontract.EffectFilesystem == 0 {
|
|
t.Fatalf("effects = %v, want filesystem", contract.Effects)
|
|
}
|
|
}
|
|
|
|
func TestModule_CommandAttributes(t *testing.T) {
|
|
command := newTestModule(false).Command()
|
|
if command.Use != "init" {
|
|
t.Fatalf("Use = %q, want init", command.Use)
|
|
}
|
|
if command.GroupID != "start" {
|
|
t.Fatalf("GroupID = %q, want start", command.GroupID)
|
|
}
|
|
}
|
|
|
|
func TestInitCreatesEvidenceStorageWithoutGitMutation(t *testing.T) {
|
|
dir := t.TempDir()
|
|
t.Chdir(dir)
|
|
var output bytes.Buffer
|
|
command := newTestModule(false).Command()
|
|
command.SetOut(&output)
|
|
command.SetArgs(nil)
|
|
if err := command.Execute(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, relative := range []string{
|
|
filepath.Join(".agents", "ao", "verdicts", "sha256"),
|
|
filepath.Join(".agents", "ao", "provenance"),
|
|
filepath.Join(".agents", "handoff"),
|
|
} {
|
|
if info, err := os.Stat(filepath.Join(dir, relative)); err != nil || !info.IsDir() {
|
|
t.Fatalf("missing %s: %v", relative, err)
|
|
}
|
|
}
|
|
if _, err := os.Stat(filepath.Join(dir, ".gitignore")); !os.IsNotExist(err) {
|
|
t.Fatal("init must not edit Git ignore state")
|
|
}
|
|
}
|
|
|
|
func TestInitDryRunCreatesNothing(t *testing.T) {
|
|
dir := t.TempDir()
|
|
t.Chdir(dir)
|
|
var output bytes.Buffer
|
|
command := newTestModule(true).Command()
|
|
command.SetOut(&output)
|
|
command.SetArgs(nil)
|
|
if err := command.Execute(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(output.String(), "would create") {
|
|
t.Fatalf("dry-run output missing 'would create': %s", output.String())
|
|
}
|
|
if _, err := os.Stat(filepath.Join(dir, ".agents")); !os.IsNotExist(err) {
|
|
t.Fatal("dry-run must not create directories")
|
|
}
|
|
}
|