diff --git a/pkg/action/action.go b/pkg/action/action.go index c447d43..ecd76d3 100644 --- a/pkg/action/action.go +++ b/pkg/action/action.go @@ -170,9 +170,10 @@ func DiffHeader(breadcrumb []string, target string, color bool) string { } // diffTurnBanner heads one bulk turn: the root module as an inverted "≡ … ≡" chip -// (mirroring the log's root section header) followed by the turn's instance name -// in bold. This is the anchor the eye lands on, so turn boundaries stand out in a -// long batch. Callers put the separating blank line above the whole header block. +// followed by the turn's instance name in bold. The chip is white rather than the +// run log's indigo root color, so the banner reads as "this is the diff" and not +// more run output. It is the anchor the eye lands on, so turn boundaries stand out +// in a long batch. Callers put the separating blank line above the header block. func diffTurnBanner(root, turn string, color bool) string { if color { return diffColorInvert + diffColorRoot + diffColorBold + " ≡ " + root + " ≡ " + diffColorReset + @@ -184,18 +185,20 @@ func diffTurnBanner(root, turn string, color bool) string { // diffHandoffChain renders the submodule hand-off lines beneath a turn banner: // one "▸ parent › child" per descent step from the turn down to the leaf, the // run log's nested-dispatch form — no root chip, so headers inside a turn read -// lighter. The marker and parent share the worker teal so the hand-off reads as -// one legible breadcrumb unit rather than fading into the diff; the child, the -// step that matters, stays bold. Empty when the breadcrumb stops at the turn. +// lighter. The child — the module that produced the diff — is an inverted light- +// gray chip: a filled anchor so the breadcrumb stands out against the diff, one +// step below the white turn chip, and in neither the log's indigo nor teal so it +// never reads as more run output. The marker and parent stay muted context. +// Empty when the breadcrumb stops at the turn. func diffHandoffChain(segs []string, color bool) string { var b strings.Builder for i := 1; i+1 < len(segs); i++ { parent, child := segs[i], segs[i+1] if color { - b.WriteString(diffColorWorker + "▸ " + parent + " › " + diffColorReset + - diffColorBold + child + diffColorReset + "\n") + b.WriteString(diffColorMuted + "▸ " + parent + " › " + diffColorReset + + diffColorInvert + diffColorSub + " " + child + " " + diffColorReset + "\n") } else { - b.WriteString("▸ " + parent + " › " + child + "\n") + b.WriteString("▸ " + parent + " › [" + child + "]\n") } } return b.String() diff --git a/pkg/action/diff.go b/pkg/action/diff.go index 22426d5..870e7c1 100644 --- a/pkg/action/diff.go +++ b/pkg/action/diff.go @@ -16,9 +16,9 @@ const ( diffColorGreen = "\033[32m" diffColorCyan = "\033[36m" diffColorInvert = "\033[7m" - diffColorMuted = "\033[38;5;244m" // mid gray — matches the log handler's muted tone - diffColorRoot = "\033[38;5;61m" // muted indigo — the orchestrator chip (log's root color) - diffColorWorker = "\033[38;5;66m" // slate teal — the hand-off marker (log's worker color) + diffColorMuted = "\033[38;5;244m" // mid gray — the hand-off marker, parent context, and target line + diffColorRoot = "\033[38;5;231m" // white — the turn chip, top of the diff header + diffColorSub = "\033[38;5;250m" // light gray — the submodule chip, one step below the turn ) // printDiff computes a unified diff between old and new content and hands it to diff --git a/pkg/action/diff_header_test.go b/pkg/action/diff_header_test.go index 29470de..eb1c28b 100644 --- a/pkg/action/diff_header_test.go +++ b/pkg/action/diff_header_test.go @@ -32,7 +32,7 @@ func TestDiffHeader_SubmoduleGetsRootFreeHandoff(t *testing.T) { // root and item, then a "▸ item › submodule" hand-off with no root chip. got := DiffHeader([]string{"bulk-deploy-k8s", "deploy-k8s-2", "autocert"}, "acme/cluster-2 (main)", false) want := "\n[≡ bulk-deploy-k8s ≡] deploy-k8s-2\n" + - "▸ deploy-k8s-2 › autocert\n" + + "▸ deploy-k8s-2 › [autocert]\n" + "acme/cluster-2 (main)\n" if got != want { t.Errorf("got %q, want %q", got, want) @@ -44,8 +44,8 @@ func TestDiffHeader_ColorTurnBannerAndHandoff(t *testing.T) { want := "\n" + diffColorInvert + diffColorRoot + diffColorBold + " ≡ deps-bump ≡ " + diffColorReset + " " + diffColorBold + "service-a" + diffColorReset + "\n" + - diffColorWorker + "▸ service-a › " + diffColorReset + - diffColorBold + "autocert" + diffColorReset + "\n" + + diffColorMuted + "▸ service-a › " + diffColorReset + + diffColorInvert + diffColorSub + " autocert " + diffColorReset + "\n" + diffColorMuted + "acme/service-a" + diffColorReset + "\n" if got != want { t.Errorf("got %q, want %q", got, want) @@ -106,7 +106,7 @@ func TestDiffCollector_BannerOncePerTurnHandoffPerSubmodule(t *testing.T) { t.Errorf("expected deploy-1 named 3 times, got %d:\n%s", n, out) } for _, want := range []string{ - "▸ deploy-1 › autocert", "▸ deploy-1 › ingress", "▸ deploy-2 › autocert", + "▸ deploy-1 › [autocert]", "▸ deploy-1 › [ingress]", "▸ deploy-2 › [autocert]", } { if !strings.Contains(out, want) { t.Errorf("expected hand-off %q, got:\n%s", want, out) @@ -114,7 +114,7 @@ func TestDiffCollector_BannerOncePerTurnHandoffPerSubmodule(t *testing.T) { } // Every header block is set off from the diff above it by a blank line, so a // breadcrumb between two diffs stays visible — the within-turn submodule too. - if !strings.Contains(out, "\n\n▸ deploy-1 › ingress") { + if !strings.Contains(out, "\n\n▸ deploy-1 › [ingress]") { t.Errorf("expected a blank line before the within-turn submodule header, got:\n%s", out) } }