Skip to content

v2.0.0: modernised velocity post extraction from foundryos and alloy#1

Merged
thushan merged 49 commits into
mainfrom
feature/v2
May 16, 2026
Merged

v2.0.0: modernised velocity post extraction from foundryos and alloy#1
thushan merged 49 commits into
mainfrom
feature/v2

Conversation

@thushan
Copy link
Copy Markdown
Member

@thushan thushan commented May 16, 2026

Summary

This is the first proper release of velocity post extraction out of FoundryOS and Alloy.

Module path bumped to github.com/tensorfoundrylabs/velocity/v2. 45 commits, ~7 months of work folded onto one branch.

Headline changes

  • Module path: velocityvelocity/v2 (Go semver requirement for v2+)
  • Single constructor: New(opts ...Option) replaces NewWithBuilder + Preset* family
  • Package split: stateful animated types moved to velocity/live; slog handler in velocity/slogbridge; all renderables (Box/Table/Tree/Banner/KeyValue/SystemInfo/StatusItem/Group/ContinuationBlock) live in root
  • pretty package killed: Pretty facade and renderables consolidated into root; NewPrettyFromLogger(log) shares the logger's mutex
  • Theme rebuild: immutable construction via NewTheme + ThemeOption; semantic StyleSlot enum; Theme.Format/Wrap/Stylish
  • Writer trust model: default-untrusted; WriterTrusted() opt-in; capability interfaces (ThemedWriter, LeveledWriter, FlushableWriter, TrustedWriter)
  • New built-ins: RingBufferWriter, Notify/NotifyLines/NotifyBox, Hyperlink (OSC 8), Secure/SecureURL/Redacted/Truncated field constructors with <secure> tag scanning
  • Logger.Status redesigned to render inline (indented under parent log line, no own timestamp); JSON writers still emit structured records
  • Colour pipeline: NO_COLOR / FORCE_COLOR env var support, correct TTY gating end-to-end

thushan added 30 commits May 9, 2026 13:59
Updates go.mod, all internal imports, examples, slogbridge, benchmarks, and
README install/import snippets to github.com/tensorfoundrylabs/velocity/v2.
thushan added 16 commits May 15, 2026 06:48
…ates, TTYRenderable

Three root causes found and fixed in one pass:

1. template.useColours was always true when the theme had colours, causing ANSI to
   leak into pipes and files. It now derives from actual TTY state at construction.

2. StatusItem/Group/ContinuationBlock detected TTY from the io.Writer passed to
   Render(), but Logger.Render() passes an intermediate *bytes.Buffer — which is
   never a terminal. Added TTYRenderable interface with RenderTTY(w, isTTY bool)
   and updated Logger.Render/RenderRaw to call it, passing the console writer's
   resolved isTTY so colour decisions are always correct.

3. On Windows, terminal emulators (VS Code, Git Bash, Windows Terminal) proxy stdout
   through a named pipe; term.IsTerminal returns false even on a real terminal.
   Added FORCE_COLOR / NO_COLOR env var support via resolveColourForWriter(). Set
   FORCE_COLOR=1 to force colour in any of these environments.

ConsoleWriter.SetTheme now also updates template.useColours to match the new theme
and current TTY state, so a SetTheme call on a TTY writer correctly re-enables colour.
Four root causes:

1. Theme.ResetStr() was missing — renderers always emitted Reset (\033[0m) even
   when the colour prefix was an empty string (mono/noColour theme). Added
   Theme.ResetStr() that returns "" for noColour themes; all render functions in
   renderable.go, pretty.go, continuation.go, group.go, and status.go updated to
   use it instead of the bare Reset constant.

2. NewPrettyFromLogger used log.Theme() which always returns the colour theme.
   Changed to log.Style() which returns noColourTheme when colour is off.

3. NewPretty(w, nil) always fell back to ThemeNightOwl regardless of TTY state.
   Now calls resolveColourForWriter(w) and selects ThemeMono when colour is off.

4. Logger.Style() only checked cfg.DisableColour and writer presence, not the
   actual resolved TTY state of the console writer. Added isTTY check so callers
   using style.Format() / style.Wrap() get plain text in NO_COLOR and piped modes.

Two test assertions that checked the old (incorrect) behaviour updated to use
t.Setenv("FORCE_COLOR","1") to exercise the colour path in CI without a TTY.
Five examples were passing explicit theme objects (ThemeNightOwl) or calling
velocity.Hyperlink() directly without a TTY guard, causing ANSI and OSC 8
sequences to leak into pipes and NO_COLOR runs.

- tables, notify, terminal-velocity: NewTable/NewTree/NewBox calls switched from
  velocity.ThemeNightOwl to log.Style() so colour follows the resolved TTY state.
- themes: slot demo uses log.Style() instead of the raw theme so NO_COLOR is
  respected even in a demo context.
- hyperlinks: Hyperlink() calls with WithHyperlinkFallback() cannot override OSC 8
  when HyperlinksSupported()=true; replace with plain string construction or TTY
  guard so pipes always get clean text.
- terminal-velocity: added a local link() helper that gates Hyperlink on
  IsTerminalWriter(os.Stdout) && HyperlinksSupported().
scanSecure was a per-Logger atomic copied at With()/Detailed() time. When a
parent gained an untrusted writer after a child was created, recomputeScanSecure
only updated the parent — children kept stale false, leaking <secure> tags in
plaintext. Move scanSecure onto the shared writerSet so every AddWriter/RemoveWriter
call is immediately visible to all loggers sharing the topology.

Regression test: TestSecureTag_ChildLoggerSeesWriterAddedAfterCreation.
Positive test: TestSecureTag_TrustedWriterAddedAfterChildDoesNotFlipScan.
@thushan thushan changed the title v2.0.0: clean-break release with /v2 module path v2.0.0: modernised velocity post extraction from foundryos and alloy May 16, 2026
@thushan thushan merged commit 64a54ca into main May 16, 2026
4 checks passed
@thushan thushan deleted the feature/v2 branch May 16, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant