From 5478693298f528c9faeb6065bda0a4613fb4ab76 Mon Sep 17 00:00:00 2001 From: Rick Liu Date: Fri, 24 Jul 2026 00:27:13 +0100 Subject: [PATCH 1/2] feat(diff): white turn chip and brighter teal hand-off The diff's module header shared the run log's colors, so it read like more run output and the teal hand-off faded against the diff. Give the header its own identity: - the turn chip is white (inverted), not the log's indigo root color, so the banner reads as "this is the diff"; - the hand-off jumps from the dim slate teal to a brighter teal so the breadcrumb between diffs stays legible. Only the two diff color constants change; layout and non-color output are untouched. Co-Authored-By: Claude Opus 4.8 --- pkg/action/action.go | 7 ++++--- pkg/action/diff.go | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/action/action.go b/pkg/action/action.go index c447d43..afc14cc 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 + diff --git a/pkg/action/diff.go b/pkg/action/diff.go index 22426d5..3961792 100644 --- a/pkg/action/diff.go +++ b/pkg/action/diff.go @@ -17,8 +17,8 @@ const ( 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) + diffColorRoot = "\033[38;5;231m" // white — the diff's turn chip, set apart from the run log's indigo root chip + diffColorWorker = "\033[38;5;80m" // bright teal — the hand-off, lifted so the breadcrumb doesn't fade into the diff ) // printDiff computes a unified diff between old and new content and hands it to From 79b8d118da2c10f3a63b63fefdc420f044427cd0 Mon Sep 17 00:00:00 2001 From: Rick Liu Date: Fri, 24 Jul 2026 00:41:48 +0100 Subject: [PATCH 2/2] feat(diff): make the submodule hand-off a filled gray chip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bright color alone didn't stand out: the hand-off's hue sat next to the diff's cyan hunk lines, so a colored line couldn't separate from colored lines. Render the child — the module that produced the diff — as an inverted light-gray chip: a filled anchor no diff line has, one step below the white turn chip, and in neither the run log's indigo nor teal so it never reads as more run output. The marker and parent stay muted context. A turn with no submodule has no hand-off line, so it keeps just the white-chip turn banner, which already stands out on its own. Co-Authored-By: Claude Opus 4.8 --- pkg/action/action.go | 14 ++++++++------ pkg/action/diff.go | 6 +++--- pkg/action/diff_header_test.go | 10 +++++----- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/pkg/action/action.go b/pkg/action/action.go index afc14cc..ecd76d3 100644 --- a/pkg/action/action.go +++ b/pkg/action/action.go @@ -185,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 3961792..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;231m" // white — the diff's turn chip, set apart from the run log's indigo root chip - diffColorWorker = "\033[38;5;80m" // bright teal — the hand-off, lifted so the breadcrumb doesn't fade into the diff + 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) } }