New goal G-076 (active): adopt the upstream tcl9 dead-console fix (ticket
f10d91c2d3, root-caused in G-039) via a single version gate shared by the
'help tcl' warning and the repl watchdog arming.
- punk::lib 0.4.3: has_tclbug_console_deadspin + pure classifier
tclbug_console_deadspin_applies, gate variable
check::tclbug_console_deadspin_fixed_in (empty = all Tcl 9 windows
runtimes affected). Buginfo dicts gain a mitigated/mitigation axis
orthogonal to level; the deadspin check reports mitigated when
punk::repl >= 0.5.0 is available to the runtime.
- punk::repl 0.5.1: repl::start arms the dead-console watchdog only when
the check reports the runtime affected - recording a verified fixed
release once flips both consumers.
- punk 0.2.6: 'help tcl' renders mitigated warnings subdued (term-grey)
with a "(mitigated)" annotation and the mitigation text; severity
classification unchanged.
- checkbugs.test: classifier truth table, live-check consistency, and
mitigated-axis validation in the generic every-check sweep.
The fixed_in flip is deliberately deferred until a released Tcl passes
the G-039 kill-procedure re-verification (watchdog disabled, clean
script-visible eof exit) - recorded as the goal's remaining acceptance
item.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New bare @normalize directive: opts a definition into indent normalization
of BLOCK-FORM multi-line field values (first line whitespace-only, as
authored by opening a braced literal with a newline). The structural first
newline and a whitespace-only trailing line are dropped, the content
lines' common leading whitespace is the block's base indent, the first
content line is unindented fully and subsequent lines are re-based to the
standard 4-space continuation convention (deeper relative indents
preserved; whitespace-only inner lines become empty). Fields in a record's
-unindentedfields are exempt. Implemented as a resolve pre-pass over the
split records (private::normalize_records / rebase_multiline_value);
@normalize with options is an error.
Head-form values are never altered - their base indent is unknowable
(continuations uniformly at 6 may be base-4 with the deliberate +2
relative convention, or base-6 flush; re-basing would flatten the former).
The idempotence test caught exactly that on a file-style definition during
implementation, narrowing the user-confirmed re-base semantics to block
form only - which also makes @normalize a proven no-op on conforming
file-style definitions.
Consumer proof (punk 0.2.5, per the recorded user decision):
::punk::helptopic::define_docs converts from interim left-margin authoring
to indented block-form values under @normalize, dropping its
-unindentedfields declarations; 'i help' and 'i help_chunks' verified
aligned in punk902z src, including the blank-line separator in the
combined basehelp+extra block.
Tests: new normalize.test (5 tests: block re-base, block left-margin,
head-form boundary, exemption byte-exactness, file-style idempotence);
rendering.test P4 characterization stays pinned as the deliberate unopted
default with its text updated to reference @normalize. punk::args suite
186 pass / 1 pre-existing skip / 0 fail; punk::ns 53/53; full source-tree
suite 806 pass / 13 skip / 1 fail = exec-14.3 only (known baseline) - zero
regressions (tclsh 9.0.3). define doc documents the directive.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
::punk::helptopic::define_docs now authors its help text at the left
margin and declares -unindentedfields {-help} on the generated @cmd line
(honoured as of punk::args 0.6.1, increment 1) and on the topic argument
line (a gate that existed all along but was never applied here).
Previously: the @cmd -help braced literal carried ~16 spaces of source
indent into the constructed definition (constructed defs get no
whole-block normalization, pinned P4 characterization), so the
Description block rendered continuations +12 right of the first line;
the \n-relative topic -help rendered its first line +4 (the injected
display prefix). Both blocks now render flush. Help text content
unchanged (manual ~70-col folding retained).
Verified in punk902z src (arg_error render + i help end-to-end);
punk::ns suite 53/53; make.tcl modules builds clean. Planning note
recorded in the goal detail file: the constructed-def normalization
increment picks its consumer proof (define_docs re-conversion vs
ensemble_subcommands_definition) when it lands.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Activated and completed under user direction (2026-07-08). Aliases for choice
values are now first-class: accepted at parse, normalized to their canonical
choice in results, folded into the canonical entry in usage display, and
resolved identically by the punk::ns doc-lookup walk.
- punk::args 0.3.0:
* -choicealiases {alias canonical ...} on argument lines; dict shape
validated in the option switch, alias->existing-choice and no-collision
cross-validated after spec merge (surfaces at resolve time - define is
lazy)
* the choice-word matching chain extracted from get_dict into the shared
resolver punk::args::choiceword_match {word nocase allchoices
choicealiases choiceprefix denylist reservelist} -> {matched exact
canonical}; get_dict delegates to it (writeback/lset logic stays at the
call site) - one implementation for parser and doc walk
* exact aliases match under any -choiceprefix/-nocase setting; alias names
join the prefix-calculation pool when -choiceprefix is true; deny applies
to the matched NAME (denied alias requires the full alias; a canonical
reached via its alias is exempt from the canonical's own deny entry)
* display: aliases fold into the canonical entry as an '(alias: x)' /
'(aliases: x|y)' label note (single convergence point covers all render
paths); alias names join the display prefix calculation so highlighted
minimal prefixes stay truthful
* define doc gains the -choicealiases section
- punk::ns 0.1.2: cmd_traverse resolves subcommand words via choiceword_match
- -choiceprefixdenylist/-choiceprefixreservelist now honoured in doc lookup
(the two pinned parity GAP tests flipped to agreement), aliases normalize
before choiceinfo lookup, -nocase honoured in the walk
- punk 0.2.3: punk::help adopts the feature - 'i help' lists one entry per
registered topic (topics+help, tcl, env+environment, console+term|terminal);
topic words accept aliases and unique prefixes with the user-decided
minimum-prefix policy recorded in ::punk::helptopic: denylist {help}
(h/he/hel stay command words), reservelist {c to tc} (fall through to
command lookup; e/en and te/ter fall through naturally as ambiguous).
Argless 'help' output byte-identical to the strict-80 baseline.
- tests: choices.test +5 (alias exact/prefix normalization, noprefix exact-
only, nocase, the punk::help policy matrix, resolve-time validation);
cmdflow.test parity tests flipped from GAP to agreement + alias-traverse and
display-fold assertions (+flowaliased fixture)
- suites: punk/args 98 pass + 1 skip, punk/ns 28 pass, punk/lib 21 pass
- G-040 flipped active -> achieved 2026-07-08; detail file records
implementation and verification
- project 0.4.10 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
From interactive review of the help restructure: 'i help' / 'i help <topic>'
usage tables rendered ~160 columns wide. Only the argless 'help' overview is
strictly 80-column - but the rest should stay reasonable, and the usage tables
do not yet wrap to terminal width, so punk::args source line lengths directly
set table width.
- helptopic argdoc help texts manually folded at ~70 columns ('help tcl' was
the worst offender at ~230 chars on one line)
- generated ::punk::help/::punk::help_chunks definitions: basehelp/topichelp/
chunks-note folded; topic choice grid rendered with -choicecolumns 2 (the
largest width contributor)
- dynamically built definitions don't get the file-sourced indentation
normalization - topichelp's continuation over-indented, fixed with an
explicit \n join
- results: i help 68 cols, per-topic 61-65; argless 'help' output byte-
identical to the strict-80 baseline; punk/ns 26 and punk/args 93+1 suites
pass
- future improvement noted in CHANGELOG: automated (potentially language-
dependent) wrapping of help text to available width, e.g. via tcllib's
text-adjust facilities
- project 0.4.9 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Completes G-036's remaining acceptance item - version-based detection of the
vulnerable combination (tcludp < 1.0.13 on Tcl 9 Windows: the per-thread exit
handler closes the process-global sockListLock/waitForSock events, silently
freezing every other udp-using thread's event loop after any udp-loaded thread
exits; root-caused and fixed-by-upgrade in 0.4.3).
- punk::lib 0.3.0: has_libbug_udp_threadexit gathers live facts (loaded udp
version, else best available registered version discovered without loading
the binary via an unsatisfiable package require triggering the index scan)
and delegates the verdict to the pure classifier
libbug_udp_threadexit_applies (facts in, verdict out - testable). has_libbug_*
is the new check family for bundled/vendored library bugs; buginfo dicts may
carry a full 'url' reference key for non tcl-core trackers.
- punk 0.2.1: 'help tcl' scans has_libbug_* alongside has_tclbug_*, renders the
url key when present, and no longer errors on a triggered check carrying a
reference without a description (latent unset-indent fix).
- new checkbugs.test: classifier combination matrix, live-check dict shape and
classifier consistency, and a buginfo-contract test across all existing
check procs.
- verified: current kit (udp 1.0.13) reports bug=0 with no warning; a simulated
triggered has_libbug_* check renders description + url in the help tcl
warning block. Suites: punk/lib 21 pass, punk/ns 26 pass.
- G-036 flipped to achieved 2026-07-08 (index acceptance REMAINING annotated
DONE; detail file gains the Detection section). Open non-gating decisions
recorded in the detail file: punk8win (8.6) kit udp 1.0.12 swap; optional
upstream tickets for residual tcludp trunk weaknesses.
- project 0.4.7 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- each topic (topics|help, tcl, env|environment, console|term|terminal) is a
handler proc returning {channel text} chunks, with its own punk::args
definition (id ::punk::helptopic::<topic>) so 'i help <topic>' renders
documented usage
- registering a topic (re)generates the ::punk::help / ::punk::help_chunks
definitions, so 'i help' shows a documented topic table that always matches
the registry (previously an autogenerated stub); the registry is the seam
for future subshell-declared topics
- 'help topics' derived from the registry (all aliases listed, fits 80 cols)
- no-arg overview and command-fallthrough output byte-identical to before;
80-column layout preserved; verified on tcl 9 and 8.6 kits via the script
and shell subcommands
- 'help env' degrades to a one-line notice when punk::config is not
initialised (e.g. script contexts) instead of an error stack + exit 1
- shared table_block helper destroys table objects after print (previously
leaked several per help invocation)
- project 0.4.4 (CHANGELOG entry)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com