[agent/codex:gpt-5.4-mini] Update the code against the AX (Agent Experience) design pri... #4

Merged
Virgil merged 1 commit from agent/update-the-code-against-the-ax--agent-ex into dev 2026-03-30 10:05:59 +00:00
2 changed files with 72 additions and 11 deletions

View file

@ -59,6 +59,7 @@ type DocblockResult struct {
Total int `json:"total"`
Documented int `json:"documented"`
Missing []MissingDocblock `json:"missing,omitempty"`
Warnings []DocblockWarning `json:"warnings,omitempty"`
Passed bool `json:"passed"`
}
@ -71,6 +72,13 @@ type MissingDocblock struct {
Reason string `json:"reason,omitempty"`
}
// DocblockWarning captures a partial parse failure while still preserving
// the successfully parsed files in the same directory.
type DocblockWarning struct {
Path string `json:"path"`
Error string `json:"error"`
}
// RunDocblockCheck checks docblock coverage for the given packages.
func RunDocblockCheck(paths []string, threshold float64, verbose, jsonOutput bool) error {
result, err := CheckDocblockCoverage(paths)
@ -92,14 +100,6 @@ func RunDocblockCheck(paths []string, threshold float64, verbose, jsonOutput boo
return nil
}
// Sort missing by file then line
slices.SortFunc(result.Missing, func(a, b MissingDocblock) int {
return cmp.Or(
cmp.Compare(a.File, b.File),
cmp.Compare(a.Line, b.Line),
)
})
// Print result
if verbose && len(result.Missing) > 0 {
cli.Print("%s\n\n", i18n.T("cmd.qa.docblock.missing_docs"))
@ -114,6 +114,13 @@ func RunDocblockCheck(paths []string, threshold float64, verbose, jsonOutput boo
cli.Blank()
}
if len(result.Warnings) > 0 {
for _, warning := range result.Warnings {
cli.Warnf("failed to parse %s: %s", warning.Path, warning.Error)
}
cli.Blank()
}
// Summary
coverageStr := fmt.Sprintf("%.1f%%", result.Coverage)
thresholdStr := fmt.Sprintf("%.1f%%", threshold)
@ -167,9 +174,12 @@ func CheckDocblockCoverage(patterns []string) (*DocblockResult, error) {
return !strings.HasSuffix(fi.Name(), "_test.go")
}, parser.ParseComments)
if err != nil {
// Log parse errors but continue to check other directories
cli.Warnf("failed to parse %s: %v", dir, err)
continue
// Preserve partial results when a directory contains both valid and
// invalid files. The caller decides how to present the warning.
result.Warnings = append(result.Warnings, DocblockWarning{
Path: dir,
Error: err.Error(),
})
}
for _, pkg := range pkgs {
@ -183,6 +193,21 @@ func CheckDocblockCoverage(patterns []string) (*DocblockResult, error) {
result.Coverage = float64(result.Documented) / float64(result.Total) * 100
}
slices.SortFunc(result.Missing, func(a, b MissingDocblock) int {
return cmp.Or(
cmp.Compare(a.File, b.File),
cmp.Compare(a.Line, b.Line),
cmp.Compare(a.Kind, b.Kind),
cmp.Compare(a.Name, b.Name),
)
})
slices.SortFunc(result.Warnings, func(a, b DocblockWarning) int {
return cmp.Or(
cmp.Compare(a.Path, b.Path),
cmp.Compare(a.Error, b.Error),
)
})
return result, nil
}

View file

@ -0,0 +1,36 @@
package qa
import (
"encoding/json"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRunDocblockCheckJSONOutput_IsDeterministicAndKeepsWarnings(t *testing.T) {
dir := t.TempDir()
writeTestFile(t, filepath.Join(dir, "b.go"), "package sample\n\nfunc Beta() {}\n")
writeTestFile(t, filepath.Join(dir, "a.go"), "package sample\n\nfunc Alpha() {}\n")
writeTestFile(t, filepath.Join(dir, "broken.go"), "package sample\n\nfunc Broken(\n")
restoreWorkingDir(t, dir)
var result DocblockResult
output := captureStdout(t, func() {
err := RunDocblockCheck([]string{"."}, 100, false, true)
require.Error(t, err)
})
require.NoError(t, json.Unmarshal([]byte(output), &result))
assert.False(t, result.Passed)
assert.Equal(t, 2, result.Total)
assert.Equal(t, 0, result.Documented)
require.Len(t, result.Missing, 2)
assert.Equal(t, "a.go", result.Missing[0].File)
assert.Equal(t, "b.go", result.Missing[1].File)
require.Len(t, result.Warnings, 1)
assert.Equal(t, ".", result.Warnings[0].Path)
assert.NotEmpty(t, result.Warnings[0].Error)
}