[agent/claude:opus] DX audit and fix. 1) Review CLAUDE.md — update any outdate... #1

Merged
Virgil merged 1 commit from agent/dx-audit-and-fix--1--review-claude-md into main 2026-03-17 08:02:40 +00:00
9 changed files with 66 additions and 25 deletions

View file

@ -60,7 +60,7 @@ All file operations use `io.Medium` from `forge.lthn.ai/core/go-io`. Production
- **UK English** in comments and strings (colour, organisation, notarisation)
- **Strict types** — all parameters and return types explicitly typed
- **Error wrapping**`fmt.Errorf("package.Function: message: %w", err)`
- **Error wrapping**`coreerr.E("package.Function", "message", err)` via `coreerr "forge.lthn.ai/core/go-log"`
- **testify** (`assert`/`require`) for assertions
- **Test naming**`_Good` (happy path), `_Bad` (expected errors), `_Ugly` (edge cases)
- **Conventional commits**`type(scope): description`

View file

@ -5,12 +5,12 @@ import (
"embed"
"forge.lthn.ai/core/cli/pkg/cli"
"forge.lthn.ai/core/go-build/locales"
_ "forge.lthn.ai/core/go-build/locales" // registers locale translations
"forge.lthn.ai/core/go-i18n"
)
func init() {
cli.RegisterCommands(AddBuildCommands, locales.FS)
cli.RegisterCommands(AddBuildCommands)
}
// Style aliases from shared package

View file

@ -222,11 +222,7 @@ func downloadAsset(assetURL, destDir string) error {
func runBuild(fromPath string) error {
fmt.Printf("%s %s\n", i18n.T("cmd.build.from_path.starting"), fromPath)
info, err := os.Stat(fromPath)
if err != nil {
return coreerr.E("pwa.runBuild", i18n.T("cmd.build.from_path.error.invalid_path"), err)
}
if !info.IsDir() {
if !coreio.Local.IsDir(fromPath) {
return coreerr.E("pwa.runBuild", i18n.T("cmd.build.from_path.error.must_be_directory"), nil)
}

View file

@ -8,11 +8,10 @@
package sdkcmd
import (
"fmt"
"os"
"forge.lthn.ai/core/go-build/pkg/sdk"
"forge.lthn.ai/core/cli/pkg/cli"
"forge.lthn.ai/core/go-build/pkg/sdk"
"forge.lthn.ai/core/go-i18n"
coreerr "forge.lthn.ai/core/go-log"
)
@ -97,10 +96,10 @@ func runSDKDiff(basePath, specPath string) error {
return coreerr.E("sdk.Diff", i18n.T("cmd.sdk.diff.error.base_required"), nil)
}
fmt.Printf("%s %s\n", sdkHeaderStyle.Render(i18n.T("cmd.sdk.diff.label")), i18n.ProgressSubject("check", "breaking changes"))
fmt.Printf(" %s %s\n", i18n.T("cmd.sdk.diff.base_label"), sdkDimStyle.Render(basePath))
fmt.Printf(" %s %s\n", i18n.Label("current"), sdkDimStyle.Render(specPath))
fmt.Println()
cli.Print("%s %s\n", sdkHeaderStyle.Render(i18n.T("cmd.sdk.diff.label")), i18n.ProgressSubject("check", "breaking changes"))
cli.Print(" %s %s\n", i18n.T("cmd.sdk.diff.base_label"), sdkDimStyle.Render(basePath))
cli.Print(" %s %s\n", i18n.Label("current"), sdkDimStyle.Render(specPath))
cli.Blank()
result, err := sdk.Diff(basePath, specPath)
if err != nil {
@ -108,14 +107,14 @@ func runSDKDiff(basePath, specPath string) error {
}
if result.Breaking {
fmt.Printf("%s %s\n", sdkErrorStyle.Render(i18n.T("cmd.sdk.diff.breaking")), result.Summary)
cli.Print("%s %s\n", sdkErrorStyle.Render(i18n.T("cmd.sdk.diff.breaking")), result.Summary)
for _, change := range result.Changes {
fmt.Printf(" - %s\n", change)
cli.Print(" - %s\n", change)
}
return cli.Exit(1, cli.Err("%s", result.Summary))
}
fmt.Printf("%s %s\n", sdkSuccessStyle.Render(i18n.T("cmd.sdk.label.ok")), result.Summary)
cli.Print("%s %s\n", sdkSuccessStyle.Render(i18n.T("cmd.sdk.label.ok")), result.Summary)
return nil
}
@ -127,15 +126,15 @@ func runSDKValidate(specPath string) error {
s := sdk.New(projectDir, &sdk.Config{Spec: specPath})
fmt.Printf("%s %s\n", sdkHeaderStyle.Render(i18n.T("cmd.sdk.label.sdk")), i18n.T("cmd.sdk.validate.validating"))
cli.Print("%s %s\n", sdkHeaderStyle.Render(i18n.T("cmd.sdk.label.sdk")), i18n.T("cmd.sdk.validate.validating"))
detectedPath, err := s.DetectSpec()
if err != nil {
fmt.Printf("%s %v\n", sdkErrorStyle.Render(i18n.Label("error")), err)
cli.Print("%s %v\n", sdkErrorStyle.Render(i18n.Label("error")), err)
return err
}
fmt.Printf(" %s %s\n", i18n.Label("spec"), sdkDimStyle.Render(detectedPath))
fmt.Printf("%s %s\n", sdkSuccessStyle.Render(i18n.T("cmd.sdk.label.ok")), i18n.T("cmd.sdk.validate.valid"))
cli.Print(" %s %s\n", i18n.Label("spec"), sdkDimStyle.Render(detectedPath))
cli.Print("%s %s\n", sdkSuccessStyle.Render(i18n.T("cmd.sdk.label.ok")), i18n.T("cmd.sdk.validate.valid"))
return nil
}

View file

@ -1,7 +1,15 @@
// Package locales embeds translation files for this module.
package locales
import "embed"
import (
"embed"
"forge.lthn.ai/core/go-i18n"
)
//go:embed *.json
var FS embed.FS
func init() {
i18n.RegisterLocales(FS, ".")
}

View file

@ -3,9 +3,12 @@
package api
import (
"os"
"testing"
"forge.lthn.ai/core/go-build/pkg/build"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestBuildProvider_Good_Identity(t *testing.T) {
@ -75,3 +78,38 @@ func TestBuildProvider_Good_NilHub(t *testing.T) {
// emitEvent should not panic with nil hub
p.emitEvent("build.started", map[string]any{"test": true})
}
func TestGetBuilder_Good_SupportedTypes(t *testing.T) {
b, err := getBuilder(build.ProjectTypeGo)
require.NoError(t, err)
assert.Equal(t, "go", b.Name())
b, err = getBuilder(build.ProjectTypeWails)
require.NoError(t, err)
assert.Equal(t, "wails", b.Name())
}
func TestGetBuilder_Bad_UnsupportedType(t *testing.T) {
_, err := getBuilder(build.ProjectType("unknown"))
assert.ErrorIs(t, err, os.ErrNotExist)
}
func TestBuildProvider_Good_ResolveDir(t *testing.T) {
p := NewProvider("/tmp", nil)
dir, err := p.resolveDir()
require.NoError(t, err)
assert.Equal(t, "/tmp", dir)
}
func TestBuildProvider_Good_ResolveDirRelative(t *testing.T) {
p := NewProvider(".", nil)
dir, err := p.resolveDir()
require.NoError(t, err)
// Should return an absolute path
assert.True(t, len(dir) > 1 && dir[0] == '/')
}
func TestBuildProvider_Good_MediumSet(t *testing.T) {
p := NewProvider(".", nil)
assert.NotNil(t, p.medium, "medium should be set to io.Local")
}

View file

@ -262,7 +262,7 @@ func (b *LinuxKitBuilder) validateLinuxKitCli() error {
}
for _, p := range paths {
if _, err := os.Stat(p); err == nil {
if io.Local.IsFile(p) {
return nil
}
}

View file

@ -267,7 +267,7 @@ func (b *TaskfileBuilder) validateTaskCli() error {
}
for _, p := range paths {
if _, err := os.Stat(p); err == nil {
if io.Local.IsFile(p) {
return nil
}
}

View file

@ -210,7 +210,7 @@ func (p *ScoopPublisher) commitToBucket(ctx context.Context, bucket string, data
// Ensure bucket directory exists
bucketDir := filepath.Join(tmpDir, "bucket")
if _, err := os.Stat(bucketDir); os.IsNotExist(err) {
if !coreio.Local.IsDir(bucketDir) {
bucketDir = tmpDir // Some repos put manifests in root
}