Browse Source

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
master
Julian Noble 4 days ago
parent
commit
3d14721d42
  1. 4
      CHANGELOG.md
  2. 4
      GOALS-archive.md
  3. 4
      GOALS.md
  4. 79
      goals/archive/G-001-pluggable-console-backends.md
  5. 2
      punkproject.toml

4
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 <spec>` 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 `<builtexe> src` / `<builtexe> src shell` available for evaluating uncommitted source directly, building is the promotion step the warning treats it as.

4
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.

4
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
<!-- Append new goals below using the format above. Keep the list ordered by G-<id>. IDs are never reused; achieved goals move to GOALS-archive.md, so ID gaps are normal. -->
### 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

79
goals/G-001-pluggable-console-backends.md → 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 <spec> 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 <spec>` 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).

2
punkproject.toml

@ -1,3 +1,3 @@
[project]
name = "punkshell"
version = "0.10.3"
version = "0.11.0"

Loading…
Cancel
Save