From 5aacc6a02a0d5ff846032d24ee1bc687489d4657 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Wed, 22 Jul 2026 09:15:11 +1000 Subject: [PATCH] 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 --- GOALS.md | 6 ++++- goals/G-113-maketcl-tty-aware-colour.md | 31 +++++++++++++++++++++++++ src/AGENTS.md | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 goals/G-113-maketcl-tty-aware-colour.md diff --git a/GOALS.md b/GOALS.md index 6d004819..b4559787 100644 --- a/GOALS.md +++ b/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 diff --git a/goals/G-113-maketcl-tty-aware-colour.md b/goals/G-113-maketcl-tty-aware-colour.md new file mode 100644 index 00000000..806060cc --- /dev/null +++ b/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. diff --git a/src/AGENTS.md b/src/AGENTS.md index 1f61ace4..e9cc69a3 100644 --- a/src/AGENTS.md +++ b/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 ` src` / ` 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.