From 8ff7ccaee16ce4947e494cb546a77538f57c652a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Mar 2026 14:08:17 +0000 Subject: [PATCH] feat: upgrade to core v0.8.0-alpha.1, replace banned stdlib imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace fmt, strings, path/filepath, core/log with Core primitives. coreerr.E→core.E. Keep strings.ContainsAny/SplitSeq/Index/Repeat. Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 8 ++++-- analytics.go | 21 ++++++++------- conventions_test.go | 7 +++-- go.mod | 2 +- go.sum | 4 +-- html.go | 44 +++++++++++++++---------------- parser.go | 64 ++++++++++++++++++++------------------------- search.go | 15 +++++------ video.go | 29 ++++++++++---------- 9 files changed, 94 insertions(+), 100 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 3d39ce2..93f0665 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -46,8 +46,12 @@ Coverage target: maintain ≥90.9%. - Exported declarations must have Go doc comments beginning with the identifier name - `go test ./...` and `go vet ./...` must pass before commit - SPDX header on all source files: `// SPDX-Licence-Identifier: EUPL-1.2` -- Error handling: all errors must use `coreerr.E(op, msg, err)` from `dappco.re/go/core/log`, never `fmt.Errorf` or `errors.New` -- Banned imports in non-test Go files: `errors`, `github.com/pkg/errors`, and legacy `forge.lthn.ai/...` paths +- Error handling: all errors must use `core.E(op, msg, err)` from `dappco.re/go/core`, never `fmt.Errorf` or `errors.New` +- Banned imports in non-test Go files: `fmt`, `errors`, `path/filepath`, `dappco.re/go/core/log`, `github.com/pkg/errors`, and legacy `forge.lthn.ai/...` paths +- Use `core.Sprintf`/`core.Sprint` instead of `fmt.Sprintf`/`fmt.Sprint` +- Use `core.Lower`/`core.Contains`/`core.Trim`/`core.TrimSuffix` etc. instead of `strings.*` where core provides an equivalent +- Use `core.PathBase`/`core.PathGlob`/`core.Concat` instead of `filepath.*` +- Allowed stdlib in non-test files: `encoding/json` (for json.RawMessage, json.Unmarshal), `strings` (for SplitSeq, ContainsAny, Repeat, Index — no core equivalent), `os/exec` - Conventional commits: `type(scope): description` - Co-Author trailer: `Co-Authored-By: Virgil ` diff --git a/analytics.go b/analytics.go index 93e5f07..2fa0191 100644 --- a/analytics.go +++ b/analytics.go @@ -2,11 +2,12 @@ package session import ( - "fmt" "maps" "slices" "strings" "time" + + "dappco.re/go/core" ) // SessionAnalytics holds computed metrics for a parsed session. @@ -98,22 +99,22 @@ func Analyse(sess *Session) *SessionAnalytics { // FormatAnalytics returns a tabular text summary suitable for CLI display. func FormatAnalytics(a *SessionAnalytics) string { - var b strings.Builder + b := core.NewBuilder() b.WriteString("Session Analytics\n") b.WriteString(strings.Repeat("=", 50) + "\n\n") - b.WriteString(fmt.Sprintf(" Duration: %s\n", formatDuration(a.Duration))) - b.WriteString(fmt.Sprintf(" Active Time: %s\n", formatDuration(a.ActiveTime))) - b.WriteString(fmt.Sprintf(" Events: %d\n", a.EventCount)) - b.WriteString(fmt.Sprintf(" Success Rate: %.1f%%\n", a.SuccessRate*100)) - b.WriteString(fmt.Sprintf(" Est. Input Tk: %d\n", a.EstimatedInputTokens)) - b.WriteString(fmt.Sprintf(" Est. Output Tk: %d\n", a.EstimatedOutputTokens)) + b.WriteString(core.Sprintf(" Duration: %s\n", formatDuration(a.Duration))) + b.WriteString(core.Sprintf(" Active Time: %s\n", formatDuration(a.ActiveTime))) + b.WriteString(core.Sprintf(" Events: %d\n", a.EventCount)) + b.WriteString(core.Sprintf(" Success Rate: %.1f%%\n", a.SuccessRate*100)) + b.WriteString(core.Sprintf(" Est. Input Tk: %d\n", a.EstimatedInputTokens)) + b.WriteString(core.Sprintf(" Est. Output Tk: %d\n", a.EstimatedOutputTokens)) if len(a.ToolCounts) > 0 { b.WriteString("\n Tool Breakdown\n") b.WriteString(" " + strings.Repeat("-", 48) + "\n") - b.WriteString(fmt.Sprintf(" %-14s %6s %6s %10s %10s\n", + b.WriteString(core.Sprintf(" %-14s %6s %6s %10s %10s\n", "Tool", "Calls", "Errors", "Avg", "Max")) b.WriteString(" " + strings.Repeat("-", 48) + "\n") @@ -122,7 +123,7 @@ func FormatAnalytics(a *SessionAnalytics) string { errors := a.ErrorCounts[tool] avg := a.AvgLatency[tool] max := a.MaxLatency[tool] - b.WriteString(fmt.Sprintf(" %-14s %6d %6d %10s %10s\n", + b.WriteString(core.Sprintf(" %-14s %6d %6d %10s %10s\n", tool, a.ToolCounts[tool], errors, formatDuration(avg), formatDuration(max))) } diff --git a/conventions_test.go b/conventions_test.go index d9569b0..c1d2ea0 100644 --- a/conventions_test.go +++ b/conventions_test.go @@ -19,8 +19,11 @@ func TestConventions_BannedImports_Good(t *testing.T) { files := parseGoFiles(t, ".") banned := map[string]string{ - "errors": "use coreerr.E(op, msg, err) for package errors", - "github.com/pkg/errors": "use coreerr.E(op, msg, err) for package errors", + "errors": "use core.E(op, msg, err) from dappco.re/go/core", + "fmt": "use core.Sprintf/core.Sprint from dappco.re/go/core", + "path/filepath": "use core.Path*/PathGlob from dappco.re/go/core", + "github.com/pkg/errors": "use core.E(op, msg, err) from dappco.re/go/core", + "dappco.re/go/core/log": "use dappco.re/go/core directly (core.E, core.Wrap)", } for _, file := range files { diff --git a/go.mod b/go.mod index 1737a81..11183d1 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module dappco.re/go/core/session go 1.26.0 require ( - dappco.re/go/core/log v0.1.0 + dappco.re/go/core v0.8.0-alpha.1 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index c36983c..5092fed 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -dappco.re/go/core/log v0.1.0 h1:pa71Vq2TD2aoEUQWFKwNcaJ3GBY8HbaNGqtE688Unyc= -dappco.re/go/core/log v0.1.0/go.mod h1:Nkqb8gsXhZAO8VLpx7B8i1iAmohhzqA20b9Zr8VUcJs= +dappco.re/go/core v0.8.0-alpha.1 h1:gj7+Scv+L63Z7wMxbJYHhaRFkHJo2u4MMPuUSv/Dhtk= +dappco.re/go/core v0.8.0-alpha.1/go.mod h1:f2/tBZ3+3IqDrg2F5F598llv0nmb/4gJVCFzM5geE4A= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/html.go b/html.go index 2d53fe1..53c34a6 100644 --- a/html.go +++ b/html.go @@ -2,20 +2,18 @@ package session import ( - "fmt" "html" "os" - "strings" "time" - coreerr "dappco.re/go/core/log" + "dappco.re/go/core" ) // RenderHTML generates a self-contained HTML timeline from a session. func RenderHTML(sess *Session, outputPath string) error { f, err := os.Create(outputPath) if err != nil { - return coreerr.E("RenderHTML", "create html", err) + return core.E("RenderHTML", "create html", err) } defer f.Close() @@ -31,7 +29,7 @@ func RenderHTML(sess *Session, outputPath string) error { } } - fmt.Fprintf(f, ` + f.WriteString(core.Sprintf(` @@ -93,14 +91,14 @@ body { background: var(--bg); color: var(--fg); font-family: var(--font); font-s shortID(sess.ID), shortID(sess.ID), sess.StartTime.Format("2006-01-02 15:04:05"), formatDuration(duration), - toolCount) + toolCount)) if errorCount > 0 { - fmt.Fprintf(f, ` - %d errors`, errorCount) + f.WriteString(core.Sprintf(` + %d errors`, errorCount)) } - fmt.Fprintf(f, ` + f.WriteString(` + f.WriteString(`