diff --git a/GOALS.md b/GOALS.md index 3e6f52bc..8fe5950c 100644 --- a/GOALS.md +++ b/GOALS.md @@ -114,4 +114,4 @@ Acceptance: from a grandchild subshell a single switch command reaches the grand Scope: src/modules/punk/console-999999.0a1.0.tm, src/modules/opunk/console-999999.0a1.0.tm, src/modules/punk/repl-999999.0a1.0.tm Detail: goals/G-011-console-stderr-semantics.md Goal: a console optionally carries an err channel as an attribute of its canonical {in out} identity - {in out err} specs accepted everywhere -console is, err resolving to process stderr for the default console and to the console's out channel elsewhere - so diagnostics and emit-to-err are first-class per-console operations instead of raw puts stderr. -Acceptance: console_spec_resolve and every -console site accept an {in out err} spec (err optional; existing pair/instance-name/object spec forms unchanged); opunk::Console exposes the err channel (nullable, additive base-class change); an unset err resolves to stderr for the default console and to the console's own out channel otherwise; punk::console's own warnings/diagnostics emitted while operating on a resolvable console go to that console's err (raw puts stderr remains only where no console is in play); an emit-to-err path exists and is exercised by at least one real consumer (e.g punk::repl); the effective err is discoverable from any thread/interp via console_fact_get; ownership/fact/mode-cache keys remain canonical {in out}; the existing console test suites pass unchanged. +Acceptance: console_spec_resolve and every -console site accept an {in out err} spec (err optional; existing pair/instance-name/object spec forms unchanged); opunk::Console exposes the err channel (nullable, additive base-class change); an unset err resolves to stderr for the default console and to the console's own out channel otherwise; punk::console's own warnings/diagnostics emitted while operating on a resolvable console go to that console's err (raw puts stderr remains only where no console is in play); an emit-to-err path exists and is exercised by at least one real consumer (e.g punk::repl); the effective err is discoverable from any thread/interp via console_fact_get (fact key err, returning the effective err channel name); ownership/fact/mode-cache keys remain canonical {in out}; the existing console test suites pass unchanged. diff --git a/goals/G-011-console-stderr-semantics.md b/goals/G-011-console-stderr-semantics.md index 65d34677..09942244 100644 --- a/goals/G-011-console-stderr-semantics.md +++ b/goals/G-011-console-stderr-semantics.md @@ -2,7 +2,7 @@ Status: proposed Scope: src/modules/punk/console-999999.0a1.0.tm, src/modules/opunk/console-999999.0a1.0.tm, src/modules/punk/repl-999999.0a1.0.tm -Acceptance: console_spec_resolve and every -console site accept an {in out err} spec (err optional; existing pair/instance-name/object spec forms unchanged); opunk::Console exposes the err channel (nullable, additive base-class change); an unset err resolves to stderr for the default console and to the console's own out channel otherwise; punk::console's own warnings/diagnostics emitted while operating on a resolvable console go to that console's err (raw puts stderr remains only where no console is in play); an emit-to-err path exists and is exercised by at least one real consumer (e.g punk::repl); the effective err is discoverable from any thread/interp via console_fact_get; ownership/fact/mode-cache keys remain canonical {in out}; the existing console test suites pass unchanged. +Acceptance: console_spec_resolve and every -console site accept an {in out err} spec (err optional; existing pair/instance-name/object spec forms unchanged); opunk::Console exposes the err channel (nullable, additive base-class change); an unset err resolves to stderr for the default console and to the console's own out channel otherwise; punk::console's own warnings/diagnostics emitted while operating on a resolvable console go to that console's err (raw puts stderr remains only where no console is in play); an emit-to-err path exists and is exercised by at least one real consumer (e.g punk::repl); the effective err is discoverable from any thread/interp via console_fact_get (fact key err, returning the effective err channel name); ownership/fact/mode-cache keys remain canonical {in out}; the existing console test suites pass unchanged. ## Context @@ -51,10 +51,14 @@ untouched. only for contexts where no console is in play (e.g module-load-time warnings). 5. **Emit path.** A first-class emit-to-err form (shape decided at implementation time - e.g an err-target variant of the opt_console_out convention) exercised by at least one real - consumer such as punk::repl, proving subshells can present stderr distinctly. -6. **Cross-thread discovery.** The effective err is exposed through console_fact_get so any - thread/interp of a session can answer "where do this console's diagnostics go" (G-007 - location transparency extends to the err attribute). + consumer such as punk::repl. The two consumer-shaped clauses divide deliberately: the + internal diagnostics migration (item 4) proves the abstraction serves its own first + consumer and is self-contained; the external consumer proves the *public* emit form is + usable by subshells wanting to present stderr distinctly. +6. **Cross-thread discovery.** The effective err is exposed through console_fact_get under + fact key `err`, returning the effective err channel name, so any thread/interp of a + session can answer "where do this console's diagnostics go" (G-007 location transparency + extends to the err attribute). ## Alternatives considered @@ -74,13 +78,27 @@ untouched. ## Notes +- **The "-console surface" is the choke points, not per-site edits.** The module's documented + convention already funnels every -console site through a small resolution set: + console_spec_resolve, internal::hybrid_console_spec, internal::opt_console_out / + opt_console_channels (+_var variants), internal::spec_to_channelpair, and the shared PUNKARGS + fragments ::punk::console::argdoc::console_opts / console_emit_opts. Accepting the 3-element + form there satisfies "every -console site" by construction; a site that bypasses these + helpers is already a convention violation to be fixed on discovery, not a reason to audit + the whole module up front. - **Channel-name locality.** Like in/out, an err channel name is thread-local for non-std channels; the fact-store exposure inherits the owner-qualified keying that already handles this for other facts. What is discoverable cross-thread is the owner-context name (and the default-console case, where std names are process-wide). - **G-001 interaction.** G-001's acceptance requires the base class unchanged *by G-001's own work*; the nullable err field is an additive change made by this goal. If G-011 lands first, - G-001 subclasses simply inherit the field; sequencing either way is safe. + G-001 subclasses simply inherit the field; sequencing either way is safe. Backend authors + should note the default is "merge into out": a backend with a genuinely distinct diagnostic + stream (e.g a separate ssh extended-data channel or a dedicated tk widget pane) must set err + explicitly at construction to get separation. +- **previous_stty_state_stderr stays as-is.** It preserves stty state of the process stderr fd + across raw-mode cycling - terminal-mode restoration, orthogonal to diagnostic output routing. + This goal adds nothing to it and removes nothing from it. - **G-008/G-009 interaction.** Once err exists, a per-subshell re-route of diagnostics is console state that a G-008 state set could capture; that is enrichment for those goals, not part of this goal's acceptance.