From 3d14721d42feba45e89dd78ca55520dc35866fc6 Mon Sep 17 00:00:00 2001 From: Julian Noble Date: Sat, 11 Jul 2026 20:52:50 +1000 Subject: [PATCH] goals: G-001 achieved 2026-07-11 - archive entry + detail; project 0.11.0 Acceptance verified (consolebackends.test child-process drivers): repls run interactively through ssh-socket and tk-widget ::opunk::Console subclasses with size/at_eof/can_respond answered by the overrides, base class and punk::console unchanged. Detail file records increment 2 and the non-gating residue (per-run output batching, punk/0-only junction wiring, raw-mode untested on foreign consoles, process-global console state -> G-008). Project version 0.10.3 -> 0.11.0 with changelog entry (new user-visible shell capability: repl::init -console). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com --- CHANGELOG.md | 4 + GOALS-archive.md | 4 + GOALS.md | 4 - .../G-001-pluggable-console-backends.md | 79 ++++++++++++++++--- punkproject.toml | 2 +- 5 files changed, 76 insertions(+), 17 deletions(-) rename goals/{ => archive}/G-001-pluggable-console-backends.md (69%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ebb98ae..3646f7fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ The latest `## [X.Y.Z]` header must match the `version` field in `punkproject.to Entries are newest-first; one bullet per notable change. See the root `AGENTS.md` "Project Versioning" section for the bump policy. +## [0.11.0] - 2026-07-11 + +- G-001 achieved: an interactive REPL can be launched against a non-detectable terminal-like device via an `::opunk::Console` subclass — `repl::init -console ` selects the console (channel pair, anchored instance name, or object value), `repl::start`'s input channel defaults to it, and the repl's output (prompts, results, and the code interp's stdout/stderr — diverted via shellfilter junction stacks and emitted per run) routes through the selected console's channels, with eof/size/capability answered by the subclass overrides (punk::repl 0.4.0; base `::opunk::Console` and `punk::console` untouched). Verified end-to-end by child-process driver tests: an `::opunk::SshConsole` socket session whose scripted remote terminal answers `CSI 6n` (size resolved over the socket) and a `::opunk::TkConsole` text widget wired as a live console by new `opunk::console::tk::console` (reflected output channel rendering into the widget + Return-binding input pipe, opunk::console::tk 0.2.0). Process-console behaviours (tcl_interactive prompt gating, stdin reopen on eof, raw-mode re-enable, the windows line re-decode experiment) now apply only when no foreign console is selected; default stdin/stdout repl behaviour is unchanged. + ## [0.10.3] - 2026-07-11 - make.tcl build/promotion commands (`project`, `packages`, `modules`, `libs`, `vfs`, `vfslibs`, `bin`, `bootsupport`, `vfscommonupdate`) now warn when `src/` has uncommitted fossil/git changes — artifacts built from dirty src have no committed provenance (G-026 direction). Warn-only by default; a new `-dirty-abort` flag makes the check aborting. Dirt outside `src/` is ignored (`punkboot::utils::vcs_dirty_warnings` gained an optional scope argument, utils 0.2.0). With ` src` / ` src shell` available for evaluating uncommitted source directly, building is the promotion step the warning treats it as. diff --git a/GOALS-archive.md b/GOALS-archive.md index 7024a884..215faa66 100644 --- a/GOALS-archive.md +++ b/GOALS-archive.md @@ -18,6 +18,10 @@ Do not edit archived entries except to fix a broken path. If an archived goal is ## Archived goals +### G-001 [achieved 2026-07-11] Pluggable console backends for non-detectable terminals → detail: goals/archive/G-001-pluggable-console-backends.md +Scope: src/modules/opunk/console-999999.0a1.0.tm, src/modules/punk/console-999999.0a1.0.tm, src/modules/punk/repl-999999.0a1.0.tm, src/lib/app-punkshell/punkshell.tcl +Acceptance: a subshell started with an ssh-channel-backed and a tk-widget-backed ::opunk::Console subclass runs an interactive REPL that reads/writes through that console; size, at_eof, and can_respond are answered by the subclass overrides; the base ::opunk::Console and punk::console module are unchanged. + ### G-007 [achieved 2026-07-05] Location-transparent punk::console across repl and code interps → detail: goals/archive/G-007-console-location-transparency.md Scope: src/modules/punk/console-999999.0a1.0.tm, src/modules/punk/repl-999999.0a1.0.tm, src/modules/punk/repl/codethread-999999.0a1.0.tm Acceptance: from a running punk session's code interp, without `repl eval`: `console_fact_get` returns the same values the parent sees and a fact set in the parent is immediately visible; a terminal query (e.g. `get_cursor_pos` or `dec_get_mode`) against the default console succeeds and cooperates with the repl reader (no lost or garbled input); a console constructed and owned by code-interp code is operated on locally (no round-trip to the parent); the existing console test suites pass and single-interp (non-repl) usage is unchanged. diff --git a/GOALS.md b/GOALS.md index 1db11578..4a3dc4ad 100644 --- a/GOALS.md +++ b/GOALS.md @@ -62,10 +62,6 @@ When the user asks to "write a goal for X" or "help me draft a goal for Y", do t -### G-001 [active] Pluggable console backends for non-detectable terminals -Scope: src/modules/opunk/console-999999.0a1.0.tm, src/modules/punk/console-999999.0a1.0.tm, src/modules/punk/repl-999999.0a1.0.tm, src/lib/app-punkshell/punkshell.tcl -Detail: goals/G-001-pluggable-console-backends.md - ### G-002 [proposed] Non-nested subshell with console targeting and inter-subshell comms Scope: src/modules/punk/repl-999999.0a1.0.tm, src/modules/punk/repl/codethread-999999.0a1.0.tm Detail: goals/G-002-non-nested-subshell.md diff --git a/goals/G-001-pluggable-console-backends.md b/goals/archive/G-001-pluggable-console-backends.md similarity index 69% rename from goals/G-001-pluggable-console-backends.md rename to goals/archive/G-001-pluggable-console-backends.md index 75f697d8..6104084d 100644 --- a/goals/G-001-pluggable-console-backends.md +++ b/goals/archive/G-001-pluggable-console-backends.md @@ -1,6 +1,6 @@ # G-001 Pluggable console backends for non-detectable terminals -Status: active +Status: achieved 2026-07-11 Scope: src/modules/opunk/console-999999.0a1.0.tm, src/modules/punk/console-999999.0a1.0.tm, src/modules/punk/repl-999999.0a1.0.tm, src/lib/app-punkshell/punkshell.tcl Goal: an interactive REPL can be launched against a non-detectable terminal-like device (ssh channel, tk text widget) via an ::opunk::Console subclass, with no edits to the base class or punk::console. Acceptance: a subshell started with an ssh-channel-backed and a tk-widget-backed ::opunk::Console subclass runs an interactive REPL that reads/writes through that console; size, at_eof, and can_respond are answered by the subclass overrides; the base ::opunk::Console and punk::console module are unchanged. @@ -82,14 +82,69 @@ method bodies use the parent's public accessor methods. Tests: src/tests/modules/opunk/console/testsuites/console/backends.test (8 tests; 7 green + tk env-gated on tcl 9.0.3 and 8.7; tk case verified under punk91). -### Remaining for acceptance - -- repl launch wiring: -console at repl::init (resolve via console_spec_resolve), - repl::start default input from the console, and OUTPUT parameterization - rputs/ - doprompt (and the code-interp channel shares) are stdout/stderr-hardwired today; - routing them via repl-level channel variables derived from the selected console is - the remaining engineering (repl.tm and app-punkshell are in scope for edits). -- Interactive-repl-through-backend verification for the ssh and tk cases (the - acceptance sentence). The tk case pairs naturally with the punkwish91 textwidget - virtual-console exploration (mapvfs notes); the ssh case can be simulated with the - scripted-remote-terminal socket technique before a real sshd session. +### Landed (increment 2, 2026-07-11) - acceptance met + +Repl launch wiring (punk::repl 0.4.0, base ::opunk::Console and punk::console still +UNCHANGED - verified via VCS status at the flip): + +- `repl::init -console ` resolves any console_spec_resolve form and stores per-repl + channel state (repl::conin/conout/conerr; conerr==conout for a foreign console - per-repl + err channels are G-011). `repl::start`'s inchan is now optional, defaulting to the + selected console's input. All existing callers (always explicit stdin) unchanged. +- Output routing: rputs maps stdout/stderr (and the debug pseudo-channels) per-repl; + doprompt writes conerr and prompts unconditionally for a foreign console (a selected + console is a terminal by declaration - process tcl_interactive no longer gates it). +- Code-interp output: for a foreign console the init_script (repltype punk/0) installs + shellfilter 'var' JUNCTION stacks on the code interp's stdout/stderr (no pass-through + to the process channels); the repl collects the pending vars after each runscript and + emits them to the console via rputs. Interleaving between the two streams within a + run is not preserved; emission is per-run (streaming is future work, see residue). +- Console-object dispatch: new repl::console_at_eof / console_get_size / + console_is_default helpers - eof checks at the reader loop and the error traps, and + size for the raw-mode width path, dispatch to the selected object's (possibly + overridden) at_eof/size; can_respond gates the ansi_wanted==2 settle without probing. + Process-console behaviours (stdin reopen on eof, raw-mode re-enable, mode line at + exit, the windows utf-16be line re-decode experiment) now apply only to the default + console. +- opunk::console::tk 0.2.0: TkConsole holds the widget in a subclass o_widget field + (always the authority for size/eof/capability; new 'widget' accessor) and accepts + -in/-out channels; new minimal wiring ::opunk::console::tk::console builds a + reflected output channel rendering into the widget plus a Return-binding input pipe + (submit/feed/teardown), so a channel-driven repl runs against the widget. Default + widget-path construction unchanged (backends.test pins re-verified). + +Acceptance verification (src/tests/modules/punk/repl/testsuites/repl/consolebackends.test, +exec-driven child processes via src/tests/testsupport/repl_console_driver.tcl - a repl +cannot run inside the shared runtests testinterp because codethread quit/exit callbacks +thread::send to the thread's MAIN interp): + +- ssh: ::opunk::SshConsole over a socket pair; the scripted remote terminal answers + CSI 6n (repl::console_get_size resolves 100x30 THROUGH THE SOCKET via punk::console's + provider, exercising the subclass size + can_respond overrides) and converses + prompt-by-prompt: results (7, 42), diverted code-interp stdout+stderr routed to the + socket, clean `exit 0` completion. +- tk: ::opunk::TkConsole over a wired text widget; lines "typed" via feed echo in the + widget, results and diverted output render into it, size from widget char dims + (100x30), at_eof from the widget marker/existence, clean `exit 0`. (Runs un-gated: + Tk loads only in the child process; self-gates when Tk is unavailable.) +- test: ::opunk::TestConsole chan-pipe double - same conversation, the repl seam for + future editbuf/repl characterization (G-044). + +### Residue / follow-on notes (non-gating) + +- Foreign-console code-interp output is emitted per-run (batch): a long-running command's + incremental output and between-run background `after` writes appear at the next run + boundary. A streaming bridge (junction-to-pipe + fileevent forwarding) is the natural + refinement - fits the G-002 subshell-comms work. +- Junction stacks are wired for repltype punk/0 only; safe/safebase/punksafe subshell + types on a foreign console would still write code-interp output to the process std + channels. +- Line mode is the verified path; raw-mode/editbuf behaviour on a foreign console is + untested (G-013 raw-default and G-044 completion work will exercise it; the width + path already routes via console_get_size). +- ansi_wanted/colour_disabled and the raw-state tsv remain process-global (documented + punk::console design); a foreign-console repl settling ansi_wanted affects the whole + process - scoped console state is G-008. +- get_prompt_config still keys result/info prompt decoration on process tcl_interactive, + so a foreign-console repl in a non-interactive process shows undecorated results + (prompts themselves are emitted). diff --git a/punkproject.toml b/punkproject.toml index 405c61b9..470ecfe0 100644 --- a/punkproject.toml +++ b/punkproject.toml @@ -1,3 +1,3 @@ [project] name = "punkshell" -version = "0.10.3" +version = "0.11.0"