Browse Source

G-113 proposed: tty-aware make.tcl colour output; interim NO_COLOR agent guidance

Assisted-by: harness=opencode; primary-model=openrouter/moonshotai/kimi-k3; api-location=openrouter.ai
master
Julian Noble 1 week ago
parent
commit
5aacc6a02a
  1. 6
      GOALS.md
  2. 31
      goals/G-113-maketcl-tty-aware-colour.md
  3. 1
      src/AGENTS.md

6
GOALS.md

@ -358,7 +358,7 @@ Detail: goals/G-104-maketcl-buildsuite-surface.md
Scope: src/buildsuites/suite_tcl90/ (target parameterization of recipe + driver; per-target out prefixes), src/buildsuites/ (layout/naming decision: target is an INVOCATION DIMENSION, suite folders stay version-named - no per-target tree copies), bin/runtime platform-dir naming alignment (punkshell's win32-x86_64-style names vs zig triples), punkbin per-target artifact layout (with G-103 metadata carrying the target), local WSL as the first cross-verification environment
Detail: goals/G-105-buildsuite-cross-target.md
### G-106 [proposed] powershell console-mode fallback: maintained raw-mode path for twapi-less runtimes
### G-106 [active] powershell console-mode fallback: maintained raw-mode path for twapi-less runtimes
Scope: src/modules/punk/console-999999.0a1.0.tm (enableRaw_powershell/disableRaw_powershell + the persistent server lifecycle), scriptlib/utils/pwsh/ (consolemode_server_async.ps1 canonical + experiment-variant reconciliation), ps-script resolution/packaging across launch contexts (argv0-derived pstooldir; kits via the G-089 scriptlib-in-kits interplay), src/make.tcl shell (the verified launch context)
Detail: goals/G-106-powershell-consolemode-fallback.md
@ -381,3 +381,7 @@ Detail: goals/G-111-modpod-tidy-tests.md
### G-112 [proposed] make.tcl subcommand rename: stage-true vocabulary around the promotion gates
Scope: src/make.tcl (subcommand tables, dispatch gating, help/workflow text), src/project_layouts/vendor/punk/basic/src/make.tcl + src/project_layouts/vendor/punk/project-0.1/src/make.tcl + src/modules/punk/mix/#modpod-templates-999999.0a1.0/templates/project_layouts/vendor/punk/project-0.1/src/make.tcl (layout copies via established sync channels), AGENTS.md + src/AGENTS.md + src/modules/AGENTS.md + src/lib/AGENTS.md + src/vfs/AGENTS.md + src/tests/AGENTS.md + src/tests/shell/AGENTS.md + README.md + src/README.md (workflow references), src/tests/shell/testsuites/punkexe/scriptexec.test + src/tests/shell/testsuites/punkexe/staticruntime.test (as touched)
Detail: goals/G-112-maketcl-subcommand-rename.md
### G-113 [proposed] make.tcl colour output is terminal-aware: SGR only on interactive tty, off when piped
Scope: src/make.tcl (startup colour policy, define_global_ansi), src/AGENTS.md (invocation guidance), src/tests/shell/testsuites/punkexe/ (piped-output characterization if a suite proves feasible); layout make.tcl copies via established sync channels
Detail: goals/G-113-maketcl-tty-aware-colour.md

31
goals/G-113-maketcl-tty-aware-colour.md

@ -0,0 +1,31 @@
# G-113 make.tcl colour output is terminal-aware: SGR only on interactive tty, off when piped
Status: proposed
Scope: src/make.tcl (startup colour policy, define_global_ansi), src/AGENTS.md (invocation guidance), src/tests/shell/testsuites/punkexe/ (piped-output characterization if a suite proves feasible); layout make.tcl copies via established sync channels
Goal: make.tcl emits ANSI SGR colour only when its output goes to an interactive terminal. Piped/redirected runs (agent harnesses, CI, log capture) produce SGR-free output with no caller action required; interactive terminal runs keep full colour by default; explicit env overrides work in both directions.
Acceptance: With NO_COLOR unset, representative informational and build subcommands (at minimum check, help, workflow, and one build command such as modules) run with stdout redirected to a file produce zero ESC (0x1B) bytes on stdout and stderr, verified on tclsh 9.x and a repo punk kit. The same commands on a real interactive terminal retain colour (manual verification, Windows console plus one unix tty). NO_COLOR=1 still suppresses all colour; a documented force-colour override re-enables colour on piped output. The Tcl 8.6 probe-fallback policy is documented and behaves as decided. The interim src/AGENTS.md NO_COLOR bullet is revised to describe the implemented behaviour.
## Context
Agents drive `tclsh src/make.tcl ...` with captured/piped output on every build-task closeout; today that output carries raw SGR sequences unless the caller remembered NO_COLOR=1, which no AGENTS doc mentioned before the interim bullet (see Notes). Humans at a terminal want the colour. The single existing switch (::punk::console::colour_disabled, set at make.tcl startup from NO_COLOR) is honoured dynamically by punk::ansi a+/a and by the define_global_ansi fallback branch, so auto-detection only needs to set that same variable from a tty probe at startup - no downstream changes.
## Approach
- Startup policy in make.tcl, evaluated before any output: NO_COLOR set -> colour off; force-colour env (name settled in the work; FORCE_COLOR is the de-facto standard) -> colour on; otherwise probe stdout and enable colour only when it is a terminal.
- Probe technique: channel-config key presence on stdout, mirroring the stdin_is_interactive precedent (chan configure key test; no package needed, core Tcl only).
- Key the decision on stdout (primary output channel); stderr colour follows the same switch for simplicity - agents capture both anyway, and the force override covers the user-redirecting-stdout case.
- Tcl 8.6 has no reliable probe (see make.tcl:316 comment); fail direction for colour is OFF (safe for agents), unlike stdin's ON. Document; reconsider only if 8.6 interactive colour matters in practice.
- Out of scope: the REPL launched by `make.tcl shell` (shell colour is the shell's own concern - colour on/off + NO_COLOR there).
## Alternatives considered
- Guidance-only (agents always set NO_COLOR=1) - rejected as the sole fix: relies on every harness remembering; kept as the documented explicit override and landed as interim guidance.
- Post-hoc SGR stripping in harnesses - rejected: pushes the burden onto every consumer.
- Per-channel colour policy (stderr coloured when it alone is a tty) - more faithful but more state; default is the stdout-keyed single switch, settled in the work.
## Notes
- 2026-07-22: interim src/AGENTS.md Work Guidance bullet landed (agents set NO_COLOR=1 for captured make.tcl runs) ahead of this goal's implementation; revise it to describe the auto-detection + overrides when this goal lands (tracked in Acceptance).
- Existing machinery: NO_COLOR -> colour_disabled (make.tcl:5-7); punk::ansi honours colour_disabled dynamically with a -forcecolour in-module override (src/modules/punk/ansi-999999.0a1.0.tm); PUNKBOOT_PLAIN is the env-switch precedent (make.tcl:1655); stdin probe precedent at make.tcl:319.
- Related: G-030 (achieved - prompt-free flags + the stdin probe this mirrors), G-011 (console stderr semantics - loose relation), G-104/G-112 (both touch make.tcl subcommand surfaces - coordinate if either goes active first).
- make.tcl interface is product surface (root AGENTS.md): this behaviour change ships with a punkproject.toml bump (patch) + CHANGELOG entry.

1
src/AGENTS.md

@ -63,6 +63,7 @@ Recovery after a wrong path guess:
- Use `tclsh src/make.tcl modules` to build just the module packages.
- Use `tclsh src/make.tcl libs` to build just the library packages.
- Use `tclsh src/make.tcl packages` to build both modules and libraries.
- Agent runs of `tclsh src/make.tcl ...` capture/pipe output: set `NO_COLOR=1` in the environment so captured output carries no ANSI SGR sequences (honoured from startup). Interactive terminal runs keep colour by default. G-113 tracks making this automatic via tty detection - revise this bullet when it lands.
- Use `tclsh src/make.tcl vendorupdate` to refresh vendormodules from config. It warns (non-fatal) for each source project whose fossil/git checkout is dirty - vendored artifacts built from a dirty tree have no committed provenance; commit in the source project to clear the warning (enforcement policy tracked by goal G-026).
- All build/promotion commands (`project`, `packages`, `modules`, `libs`, `vfs`, `vfslibs`, `bin`, `bootsupport`, `vfscommonupdate`) warn similarly when this project's own `src/` has uncommitted fossil/git changes (dirt outside `src/` is ignored). Warn-only by default; pass `-dirty-abort` to make the check aborting. For evaluating uncommitted source without a build, prefer `<builtexe> src` / `<builtexe> src shell`. The check is `punkboot::utils::vcs_dirty_warnings` (optional scope argument) loaded guardedly from bootsupport - if the snapshot is stale/missing the check degrades to a skip notice (but `-dirty-abort` then aborts rather than silently losing the requested strictness).
- Provenance warnings (dirty-src gate + vendorupdate source-project check) print with a plain column-0 `PROVENANCE-WARNING:` token (grep for it in captured build output) and are recapped at the end of the run via make.tcl's wrapped `::exit`. Interactive terminal runs get a 3-second ctrl-c grace countdown before a dirty build proceeds; piped/agent runs skip it. `tclsh src/make.tcl check` reports the current src provenance status and what the build commands would do.

Loading…
Cancel
Save