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
- GOALS.md collapsed to summary entries (ID/status/title/Scope/detail pointer): 104.6KB -> 23KB so a full read stays cheap; Scope lines kept verbatim so path-grep goal discovery still works
- canonicality split: index canonical for ID/status/title/Scope, detail file canonical for Goal:/Acceptance:; all 61 detail-file headers reconciled from the index (fixes stale copies, e.g. G-036 detail acceptance predated the achieved rework), bodies preserved untouched
- detail files created for the three index-only goals G-017, G-034, G-054; every goal now has one
- 10 achieved goals (G-007 G-015 G-036 G-037 G-040 G-046 G-049 G-054 G-058 G-059) archived: summary records appended to GOALS-archive.md, detail files moved to goals/archive/; archive-on-flip replaces the ~30-achieved-entries trigger
- GOALS.md preamble/rules reworked: read workflow (read index in full, then detail files of scope-intersecting goals before editing), contract spans both tiers with proposal-first unchanged, next-free-ID counts the archive, achieved flip judged against the detail-file Acceptance and includes archiving
- progress convention codified from G-001 increment-1 practice: index entries carry status only, never progress; incremental progress lives in the detail file's ## Progress section (landed/remaining); achieved flip requires the remaining-work list resolved - a partial increment never flips a goal
- goals/AGENTS.md rewritten for the split (required 4-field header, one detail file per goal, orphan rules covering archive/); root AGENTS.md Child DOX Index + Repo-wide Notes updated; GOALS-archive.md preamble updated
- stale detail-file paths updated to goals/archive/ in src/lib/app-punkscript/punkscript.tcl (comment), runtimebash_wsl.test, wslprobe.tcl and the G-042 detail file; propagated copies (root lib/, src/vfs/_vfscommon.vfs, src/_build) left to refresh via normal build steps
- no project version bump: governance docs and source comments only, no user-visible shell behaviour
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- three new backend modules under src/modules/opunk/console/, base ::opunk::Console and punk::console UNCHANGED (the G-001 acceptance constraint - verified diff-clean):
* opunk::console::test / ::opunk::TestConsole - deterministic channel-pair test double: fixed size via -columns/-rows, is_console_or_tty/can_respond 1 (settled value wins), at_eof = plain chan eof with NO probe (pending bytes never consumed - pinned). The console seam identified by the G-044 repl characterization work
* opunk::console::ssh / ::opunk::SshConsole - socket-carried terminal sessions: construction-time capability (detection is the wrong tool - per goal detail), chan-eof without byte-consuming probes, size via the registered ANSI size-query provider over the connection. Flagship test: a scripted remote terminal answers CSI 6n over a socket pair and size resolves 100x30 through punk::console machinery querying the socket
* opunk::console::tk / ::opunk::TkConsole - Tk text widget as terminal: widget path in the inherited in/out slots (documented non-channel reuse), terminal_class tk-text, size from widget char dims, at_eof via backend marker (opunk::console::tk::set_eof) or widget destruction; no Tk require at module load. Verified live under punk91 src (the tk-loading experiment kit)
- voo -extends subclassing pattern recorded in opunk/AGENTS.md: children inherit public accessors + field INDEX variables (not parent-private my.* accessors) - constructors initialise inherited private fields via index vars, method bodies use parent public accessor methods; virtual dispatch via the slot-0 tag needs no base changes
- tests: modules/opunk/console backends.test (8 tests: dispatch, spec_resolve acceptance of subclass values, probe-free eof, settled-capability precedence, ssh capability/eof/size-over-socket/settled-0-no-emission, tk gated behind env PUNK_TEST_TK=1) - 7 green + tk skip on tcl 9.0.3 and 8.7; tk case verified standalone under punk91
- goal detail records progress + remaining work (repl -console launch wiring, output-channel parameterization, interactive acceptance verification); goal stays active
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
G-001 pluggable console backends for non-detectable terminals (ssh channel, tk widget) via ::opunk::Console subclasses. G-002 non-nested subshell with console targeting and inter-subshell comms, including thread::send -async routing to the code sub-interp and the canonical launch API design (subshell as sole entry point, interp alias as context signal). G-003 configurable resource limits (command-count, time via interp limit) and sandboxing spectrum (interp hide/expose/alias, safe::interpCreate) on subshell interps, downstream of G-002's asymmetry fix.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Assisted-by: harness=opencode; primary-model=unknown; api-location=unknown