revert: remove YAML support, keep JSON-only
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 15s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 28s
CI / review (gpt-5, security, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 30s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 51s
PR Ready Gate / clear-labels (pull_request) Successful in 2s
CI / test (pull_request) Successful in 15s
CI / review (anthropic--claude-4.6-sonnet, sonnet, SONNET_REVIEW_TOKEN) (pull_request) Successful in 28s
CI / review (gpt-5, security, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 30s
CI / review (gpt-5, gpt, GPT_REVIEW_TOKEN) (pull_request) Successful in 51s
The external dependency (goccy/go-yaml) violates the repository's stdlib-only convention (CONVENTIONS.md). While YAML provides better readability for multi-line strings, the convenience doesn't justify breaking a hard rule. Reverts: - External dependency on github.com/goccy/go-yaml - YAML parsing logic in persona.go - YAML persona files (restored as JSON) - YAML-specific tests - Design document (feature rejected) The persona files work fine with JSON. Multi-line strings use \n escapes which is less pretty but acceptable for internal files. This addresses all MAJOR findings from review bots regarding the external dependency violation.
This commit is contained in:
+10
-222
@@ -87,83 +87,6 @@ func TestListBuiltinPersonas(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPersonaFromYAMLFile(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "test.yaml")
|
||||
|
||||
content := `# Test persona
|
||||
name: test
|
||||
display_name: Test Persona
|
||||
identity: |
|
||||
You are a test persona.
|
||||
Multi-line identity works.
|
||||
focus:
|
||||
- testing
|
||||
- validation
|
||||
ignore:
|
||||
- nothing
|
||||
severity:
|
||||
major: Big problems
|
||||
minor: Small problems
|
||||
nit: Tiny problems
|
||||
`
|
||||
|
||||
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
p, err := LoadPersona(path)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadPersona failed: %v", err)
|
||||
}
|
||||
|
||||
if p.Name != "test" {
|
||||
t.Errorf("Name = %q, want %q", p.Name, "test")
|
||||
}
|
||||
if p.DisplayName != "Test Persona" {
|
||||
t.Errorf("DisplayName = %q, want %q", p.DisplayName, "Test Persona")
|
||||
}
|
||||
if len(p.Focus) != 2 {
|
||||
t.Errorf("Focus len = %d, want 2", len(p.Focus))
|
||||
}
|
||||
if !strings.Contains(p.Identity, "Multi-line") {
|
||||
t.Error("Identity should contain multi-line content")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPersonaFromYMLFile(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "test.yml")
|
||||
|
||||
content := `name: test
|
||||
display_name: Test YML
|
||||
identity: Test identity
|
||||
focus:
|
||||
- testing
|
||||
ignore: []
|
||||
severity:
|
||||
major: Big
|
||||
minor: Small
|
||||
nit: Tiny
|
||||
`
|
||||
|
||||
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
p, err := LoadPersona(path)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadPersona failed: %v", err)
|
||||
}
|
||||
|
||||
if p.Name != "test" {
|
||||
t.Errorf("Name = %q, want %q", p.Name, "test")
|
||||
}
|
||||
if p.DisplayName != "Test YML" {
|
||||
t.Errorf("DisplayName = %q, want %q", p.DisplayName, "Test YML")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPersonaFromJSONFile(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "test.json")
|
||||
@@ -207,38 +130,22 @@ func TestLoadPersonaFromJSONFile(t *testing.T) {
|
||||
func TestLoadPersonaValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
content string
|
||||
ext string
|
||||
json string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "missing name yaml",
|
||||
content: "identity: test\n",
|
||||
ext: ".yaml",
|
||||
name: "missing name",
|
||||
json: `{"identity": "test"}`,
|
||||
wantErr: "name is required",
|
||||
},
|
||||
{
|
||||
name: "missing identity yaml",
|
||||
content: "name: test\n",
|
||||
ext: ".yaml",
|
||||
name: "missing identity",
|
||||
json: `{"name": "test"}`,
|
||||
wantErr: "identity is required",
|
||||
},
|
||||
{
|
||||
name: "missing name json",
|
||||
content: `{"identity": "test"}`,
|
||||
ext: ".json",
|
||||
wantErr: "name is required",
|
||||
},
|
||||
{
|
||||
name: "missing identity json",
|
||||
content: `{"name": "test"}`,
|
||||
ext: ".json",
|
||||
wantErr: "identity is required",
|
||||
},
|
||||
{
|
||||
name: "display_name defaults to name",
|
||||
content: "name: test\nidentity: test identity\n",
|
||||
ext: ".yaml",
|
||||
name: "display_name defaults to name",
|
||||
json: `{"name": "test", "identity": "test identity"}`,
|
||||
// No error expected - should succeed
|
||||
},
|
||||
}
|
||||
@@ -246,8 +153,8 @@ func TestLoadPersonaValidation(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "test"+tt.ext)
|
||||
if err := os.WriteFile(path, []byte(tt.content), 0644); err != nil {
|
||||
path := filepath.Join(dir, "test.json")
|
||||
if err := os.WriteFile(path, []byte(tt.json), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
@@ -277,25 +184,12 @@ func TestLoadPersonaValidation(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadPersonaFileNotFound(t *testing.T) {
|
||||
_, err := LoadPersona("/nonexistent/path/persona.yaml")
|
||||
_, err := LoadPersona("/nonexistent/path/persona.json")
|
||||
if err == nil {
|
||||
t.Error("expected error for nonexistent file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPersonaInvalidYAML(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "invalid.yaml")
|
||||
if err := os.WriteFile(path, []byte("not valid yaml:\n - [broken"), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
_, err := LoadPersona(path)
|
||||
if err == nil {
|
||||
t.Error("expected error for invalid YAML")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPersonaInvalidJSON(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "invalid.json")
|
||||
@@ -309,38 +203,6 @@ func TestLoadPersonaInvalidJSON(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPersonaCaseInsensitiveExtension(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ext string
|
||||
}{
|
||||
{"lowercase yaml", ".yaml"},
|
||||
{"uppercase YAML", ".YAML"},
|
||||
{"mixed case Yaml", ".Yaml"},
|
||||
{"lowercase yml", ".yml"},
|
||||
{"uppercase YML", ".YML"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "test"+tt.ext)
|
||||
content := "name: test\nidentity: test identity\n"
|
||||
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
p, err := LoadPersona(path)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadPersona failed for extension %s: %v", tt.ext, err)
|
||||
}
|
||||
if p.Name != "test" {
|
||||
t.Errorf("Name = %q, want %q", p.Name, "test")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCapitalizeFirst(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
@@ -375,77 +237,3 @@ func TestListBuiltinPersonasReturnsEmptySlice(t *testing.T) {
|
||||
t.Error("ListBuiltinPersonas should return empty slice, not nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestYAMLMultilineStrings(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "multiline.yaml")
|
||||
|
||||
// Test literal block scalar (|) which preserves newlines
|
||||
content := `name: multiline
|
||||
display_name: Multiline Test
|
||||
identity: |
|
||||
First line.
|
||||
Second line.
|
||||
Third line.
|
||||
focus:
|
||||
- item one
|
||||
ignore: []
|
||||
severity:
|
||||
major: Major issue
|
||||
minor: Minor issue
|
||||
nit: Nit
|
||||
`
|
||||
|
||||
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
p, err := LoadPersona(path)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadPersona failed: %v", err)
|
||||
}
|
||||
|
||||
// Literal block scalar preserves newlines
|
||||
if !strings.Contains(p.Identity, "\n") {
|
||||
t.Error("Identity should contain newlines from literal block scalar")
|
||||
}
|
||||
if !strings.Contains(p.Identity, "Second line") {
|
||||
t.Error("Identity should contain 'Second line'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestYAMLComments(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "comments.yaml")
|
||||
|
||||
content := `# This is a comment
|
||||
name: commented # inline comment
|
||||
display_name: Commented Persona
|
||||
# Another comment
|
||||
identity: Test identity
|
||||
focus:
|
||||
- item # comment after item
|
||||
ignore: []
|
||||
severity:
|
||||
major: Major
|
||||
minor: Minor
|
||||
nit: Nit
|
||||
`
|
||||
|
||||
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
|
||||
t.Fatalf("failed to write test file: %v", err)
|
||||
}
|
||||
|
||||
p, err := LoadPersona(path)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadPersona failed: %v", err)
|
||||
}
|
||||
|
||||
// Comments should be ignored
|
||||
if p.Name != "commented" {
|
||||
t.Errorf("Name = %q, want %q", p.Name, "commented")
|
||||
}
|
||||
if p.Focus[0] != "item" {
|
||||
t.Errorf("Focus[0] = %q, want %q", p.Focus[0], "item")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user