Vendored from the now-committed upstream project (c:/repo/jn/tclmodules/fauxlink,
checkins c82c9bb9 + ed1eebdb): punk::args documentation blocks including a
(package)fauxlink id (inert PUNKARGS + registration, no punk::args dependency;
full surfacing awaits G-075), decode_unicode_escapes hexless-%U first-char-drop
fix, 3-segment comment validation/decoding parity, link_as stub now errors
instead of silently no-oping, and a 62-test upstream suite (src/tests/fauxlink.test)
covering resolve/decode behaviour and the documentation metadata.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Two independent list-flattening bugs made `runtests.tcl foo.test bar.test`
match zero files, forcing agents to run files individually:
- the trailing glob value is -multiple 1, so its parsed value is a list;
plain lappend nested it as a single space-containing element
- punk::path::treefilenames declares tailglobs as a -multiple 1 positional
(one glob per argument), but the whole file_globs list was passed as one
argument, re-collapsing it (this also broke multiple globs supplied via
-tcltestoptions {-file {...}})
Single names always worked because a one-element Tcl list flattens to
itself, which masked both bugs. Verified: two file tails now discover and
run both suites (files=2, 40/40 pass).
Also note multi-file-tail support in src/tests/AGENTS.md Work Guidance.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- punk::mix::templates modpod (0.1.4): dead templates/layouts/project payload
subtree removed - design-generation residue with no reader; layout payloads
live in src/project_layouts, located via layout_refs.
- src/make.tcl: unused old_layout_update_list (referencing the long-gone
src/mixtemplates and modules/punk/mix/templates paths) removed; bootsupport
help text now names src/project_layouts/custom/_project/<layoutname> instead
of mixtemplates.
- src/project_layouts custom/_project make.tcl copies: punkcheck-managed sync
outputs refreshed by the verification 'make.tcl modules' run.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- @vendor+punk+project-0.1.ref renamed to project@vendor+punk+project-0.1.ref:
the alias yields the exact layout name 'punk.project', so project.new's
defaulted -layout resolves unambiguously (previously tcl::prefix::match saw
only punk.project-0.1 / punk.project-0.1_overrides).
- Junk/test refs removed from the selectable layout list: test2, the
custom/_project duplicate sample-0.1 ref, and the alias-less punk.shell-0.1
ref whose target was an a.txt-only folder (folder removed too; the real
shell layout remains exposed as punk.shell-0.1_overrides).
- src/project_layouts/README.md rewritten to describe the implemented
punk.templates + layout_refs mechanism including the ref filename grammar,
the not-yet-implemented overlay semantics, and a G-087 pointer; the dead
punk.projectlayout capability description is gone.
Layout names after this change: punk.sample-0.1 punk.project punk.minimal
punk.basic punk.shell-0.1_overrides punk.project-0.1_overrides.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- put -> puts at all six no-handler warning sites (commandset layout x2,
project, module, scriptwrap, mix/base get_template_basefolders - the sweep
found three sites beyond the review's list). Three procs also dereferenced
an unset result variable after the warning; the no-handler paths now warn
and return an empty dict. layout references_as_dict and module templates_dict
warning messages no longer misattribute their owning proc.
- punk::cap::handlers::templates: brace the absolute-pathtype existence test
('if {!file exists $normpath}' raised an expr syntax error on any
absolute-pathtype provider registration), and add the missing dict-exists
check in pkg_register's duplicate-registration guard (errored 'key not known
in dictionary' for any second provider package registering a capability).
- Versions: commandset layout 0.1.1, project 0.2.2, module 0.1.1,
scriptwrap 0.1.1, cap handlers templates 0.1.1; punk::mix::base 0.1 -> 0.1.1
(manually versioned: file renamed, provide block updated, history comment
added).
Verified: scratch no-handler/registration checks 13/13 (see
goals/G-087-thin-project-layouts.md Progress); runtests prune/fossilmove/
multishell/libsearch all pass; make.tcl modules builds clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New goal from the 2026-07-16 layout-system review: thin layouts with
generation-time infrastructure injection, fauxlink layout refs, and a working
overlay merge primitive. Detail file carries the review findings (unimplemented
merge, dead module-pathtype refs, stale fat snapshots, latent bugs), the staged
approach (hygiene first), and the hygiene-stage completion record.
Activated at user direction 2026-07-17.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Vendored library payloads and vfs kit payloads legitimately carry CRLF
endings (upstream files are kept as-is; the LF preference governs authored
text). Without the globs, large vendor/vfs checkins block on fossil''s
interactive CRLF prompt - the tablelist 7.11 catch-up (fossil 3316d3c7)
had to use --no-warnings. Policy documented in .fossil-settings/AGENTS.md
alongside the binary-glob rationale. crlf-glob is fossil-only (no
.gitignore-style counterpart), so no dual-VCS derivation applies.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The old Tk dll set aside during the punk9win.vfs split is no longer
wanted in the tk903 kit payload; the 9.0b2-era dll remains available in
punk9wintk90b2.vfs.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Closes the loophole flagged in the 6.22 -> 7.11 swap: with the .tm
files deleted, a future make.tcl vendorupdate would have regenerated
them from these entries. tablelist now ships solely as the
src/vendorlib/tablelist7.11 pkgIndex lib.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The punk9win.vfs kit was split into punk9wintk90b2.vfs and
punk9wintk903.vfs; the treectrl/Img/twapi/cffi payloads G-020 relies on
live in punk9wintk903.vfs/lib_tcl9 (the actively mapped tclsfe/punk91
kit). Path-only update, user-approved; goal contract otherwise
unchanged. goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New vfs_startup_script_warning check runs for each .vfs folder about to
be built against a runtime: it passes if the folder has a root main.tcl
or a root fauxlink resolving to the name main.tcl whose target exists
and is a .tcl file. Otherwise a noticeable warning is emitted and the
build proceeds (a kit with no startup script is legal).
Warnings use a new general-purpose ::punkboot::print_build_warnings
channel: column-0 BUILD-WARNING: token for greppability, ANSI highlight
for humans, and recap at end of run via the wrapped ::exit (same
treatment as PROVENANCE-WARNING). Overlay-only folders with no runtime
mapping (e.g _vfscommon.vfs) are not checked. Contract documented in
src/vfs/AGENTS.md.
Motivated by the punk9win.vfs split initially dropping the main.tcl
punk_main fauxlink from punk9wintk90b2.vfs.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Adds the main.tcl fauxlink omitted from the punk9win.vfs split, and
points the commented-out tclsh90b2/tksfe-twapi-x64 mapvfs.config
entries at the new kit names.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Remove src/vendormodules/tablelist-6.22.tm and tablelist_tile-6.22.tm
in favour of the multi-file src/vendorlib/tablelist7.11/ (pure Tcl,
upstream layout with pkgIndex.tcl). _vfscommon.vfs follows via
make.tcl vfscommonupdate: modules/tablelist*-6.22.tm removed,
lib/tablelist7.11 added.
Note: src/vendormodules/include_modules.config still lists the
tablelist/tablelist_tile module sources; a future make.tcl
vendorupdate would regenerate the 6.22-era .tm files unless those
entries are removed.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Replace the single punk9win.vfs payload with two per-Tk-version kits:
- punk9wintk90b2.vfs: content-identical copy of punk9win.vfs (same Tk
9.0b2-era bin/tcl9tk90.dll) except the main.tcl punk_main fauxlink
was not carried over (kit is parked; its tclsh90b4_piperepl mapping
remains commented out in mapvfs.config)
- punk9wintk903.vfs: same payload with a newer Tk bin/tcl9tk90.dll
(Dec 2025 build, Tk 9.0.3) and the old 9.0b2-era dll set aside as
bin/tcl9tk90xxx.dll; adds lib_tcl9/apave4.4.10 (pure Tcl); drops the
modules_tcl9 Thread-3.0b3 modules (Thread is static in the tclsfe
runtime); now the mapping target for tclsfe-x64.exe (punk91 kit)
src/runtime/mapvfs.config and src/runtime/vendorlib_vfs.toml (tcludp
install targets) retargeted from punk9win.vfs to the new kit names.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-directed removal of the two pipeline-based development iterations flagged
as candidates in the 0.7.0 hygiene pass. Both were undocumented, unexported
global aliases superseded by the plain proc nscommands (which adds
weird-namespace handling); no callers existed in the repo and nscommands1 was
broken - it referenced nonexistent commands (nsthis2, inspect at global
scope) and errored on first use. Recoverable via git history.
ns/nav/repl suites 111/111 green. buildversion 0.7.1 -> 0.8.0 (command
removal); project 0.12.36 + CHANGELOG (patch - the aliases were never part of
the documented shell contract).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved from the serversecretsync tm-path-shadowing incident
(8.6 require-before-path-setup silently selected a stale tomlish from the
machine-default tm paths over the project's vendored copy). Default
mechanism per user: vendor punk::libunknown + punk::packagepreference as
the light layout's bootstrap minimum. Related: G-012/G-027/G-029/G-035.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The -return summarydict choicelabel claimed the linemap key appears only when
-n is supplied - actual behaviour (pinned in ansi/grepstr.test since the
characterization wave) is that linemap is always present. Help text corrected
to match; deferred-to-the-hygiene-pass item from the grepstr characterization.
ansi suites 63/63 green. buildversion 0.1.2 -> 0.1.3; project 0.12.35 +
CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Both fixes were pinned as known warts before the change; the pins flip with it:
- get_nslist: the -types default sat inside a braced dict-create literal, so it
was the literal string $known_types - any call without -types (notably bare
user-level `nslist`) errored with the malformed "Unrecognised namespace
member type: $known_types". An unsupplied -types now defaults to all known
member types. Pin flipped: nslist.test nslist_types_default_error_QUIRK ->
nslist_types_default (bare nslist renders children + commands). nslist's own
PUNKARGS -types gained help text, deliberately without a -default so the
passthrough stays absent when unsupplied.
- nsjoinall: the non-empty-prefix-vs-absolute-path error message carried a
copy-paste "nsjoin:" prefix - now "nsjoinall:". Pin flipped in
nsprimitives.test nsjoinall_edges.
- nscommands: commented out a development trace puts (">>> base: ...") that
polluted stdout on the weird-namespace path (same treatment as the 0.1.1
doc-lookup trace-puts cleanup; not pinned).
Suites green: ns/nav/repl 111/111; full source-tree run at the known baseline
(only core exec-14.3, pre-existing). buildversion 0.7.0 -> 0.7.1; project
0.12.34 + CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
No change to shipped behaviour (ns+nav+repl suites 111/111 green). Minor bump
because unused procs were removed.
Removed (~1200 lines, recoverable via git history):
- the fully commented-out predecessor help command arginfo (~930 lines) -
its own header marked it replaced by cmdhelp
- superseded/deprecated name-primitive twins nsparts1, nsprefix1,
nsprefix_orig, nstail1, nstail_orig (never exported, no callers; NOT
drop-in equivalents - divergence on 5+ colon runs was pinned in
nsprimitives.test before removal; those divergence pins are removed with
the twins and replaced by a direct nsprefix long-colon-run pin - the
divergence record lives in the test file history, commit 0c7168a1)
- obsolete nsglob_as_re1, empty stubs ns_relative_to_location/
ns_absolute_to_location, obsolete internal::_pkguse_vars, an if-0 block in
nstree_list, unused interp_aliases assignment in get_ns_dicts, assorted
commented-out remnants (pre-punk::args defaults blocks, pipedata width
calcs, corp default-retrieval experiments, cmdtrace trace-add alternates)
Documentation accuracy:
- nsprefix comment corrected (:::a prefix is :: not ::a - per pins)
- nsglob_as_re stale "should be fixed" note replaced with an accurate
description of the in-place negative-lookahead fix (* matches an inner
single colon, never crosses ::)
- nstree_list previously empty PUNKARGS summary/help fields filled
- nstail gained a doc comment; nseval_ifexists gained the native-vs-punk
p:::x divergence note; the dangling "string functions" sentence completed
- cmdhelp help typos (auto-gnerated, commands commands); corp -syntax help
truncated sentence completed
Flagged, deliberately unchanged (comment only):
- get_nslist red-strike/masked alias display branches appear unreachable
from current bucket derivation (nslist.test fixture findings) - reassess
at the planned display rework
- nscommands1/nscommands2 pipeline aliases: superseded removal candidates
(nscommands1 errors on first use - references nonexistent nsthis2)
- cmdtrace stdout/stderr noise deferred to proposed G-085
- test_switch* marked as live cmdtrace test fixtures (used by cmdtrace.test)
All inserted/updated comments carry 2026-07-14 Agent-Generated/Agent-Updated
marks. buildversion 0.6.0 -> 0.7.0. Known-wart fixes sanctioned by the pinned
backlog (nslist -types default, nsjoinall error prefix) follow separately.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New shell/testsuites/punkexe/shellnavns.test - one hang-proof punk_run piped
session against the built executable in src launch mode (dev modules, so
current punk::repl/nav source is exercised without a rebuild):
PROVEN end-to-end:
- n/ sets ::punk::nav::ns::ns_current in the running shell
- the current namespace continues into `subshell punk` and back out, and the
0.5.2 stray-namespace seeding fix holds live (no phantom ns_current
namespace in the subshell context)
- navigation inside the subshell takes effect; the session exits cleanly
(exitcode 0, no timeout, exit unwinds subshell -> parent -> terminate)
FINDINGS from the E3 probes (pinned in the test with markers):
- the FIRST subshell evaluates in the SAME code interp as the parent shell -
the "first subshell asymmetry" already TODO-documented in repl::init.
Continuity therefore manifests via shared state at shell level (SHARED
marker: a variable set in the subshell is visible to the parent after
exit, and the parent adopts the subshell''s final namespace). The
repl::start seeding template - the carry-over mechanism for genuinely
separate code interps - is proven at module level in punk/repl
nscurrent.test. A G-002-style isolated subshell would flip these pins.
- KNOWN GAP: piped-session submissions evaluate at :: even after n/ sets
ns_current - the inscope application proven interactively and at module
level does not take effect for subsequent piped submissions in this spawn
shape. Root cause undetermined (piped-path evaluation vs kit/codethread
interplay); flagged for investigation alongside G-038 session-context
work.
Verified: shell/** suite 42 total / 40 passed / 0 failed (2 gated skips)
under Tcl 9.0.3. AGENTS updated (shell contracts bullet; punk/repl module
index E3 reference).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Groundwork requested for the future rework of n/ n// n/// output to punk
tables with terminal-width responsiveness: the underlying display elements
and navigation/retention semantics are now pinned so only deliberately
REWORK-flagged pins flip when the layout changes.
- punk/ns nslist.test (11): tier A pins get_ns_dicts classification buckets
(the machine contract: children/packagetails/packageprefixes per the
package-names derivation, commands/exported/imported/aliases/procs/
ensembles/oo/coroutines/usageinfo incl alias-target doc resolution and its
update_definitions dependence, alias edge cases, native via builtin ns);
tier B pins per-element marking layout-agnostically (underline/underdouble/
underdotted package styles, type tag colours, exported green / imported -I
under overtype SGR canonicalization, the punkargs doc icon); tier C pins
the CURRENT hardcoded 2-col/4-col layout and nspath subtables, explicitly
flagged to flip with the rework; KNOWN QUIRK pinned: bare nslist without
-types errors with a malformed message (literal dollar-known_types).
Findings recorded: the red-strike/masked alias display branches appear
unreachable from current bucket derivation.
- punk/nav/ns navns.test (6, new suite dir): ns/ navigation state machine
(absolute/relative/glob-no-nav/failed-nav preservation/quad-colon
normalization), v-form content selection, ensemble annotation, and the
::punk::nav::ns::ns_current variable contract.
- punk/repl nscurrent.test (4): repl retention proven against a REAL
codethread (repl::init, synchronous runscript sends): inscope evaluation,
retention across submissions, n/ navigation retained, auto-create-with-
notice for a missing current namespace.
- punk::repl 0.5.2 fix: repl::start''s codethread seeding template
namespace-eval''d the full ns_current VARIABLE name, creating a stray
namespace of that name in every code interp (phantom child in n/ listings
of the nav namespace). Now ensures only the parent ::punk::nav::ns.
Subshell namespace carry-over semantics unchanged; pinned behaviourally
(mirrored template) plus a source-text guard, pending the planned
end-to-end piped subshell test (E3) at the shell level.
Verified: punk/ns 80/80, punk/nav 6/6, punk/repl 7/7 under Tcl 9.0.3;
nslist/navns/nscurrent green under 8.7. Console queries mocked throughout
(the render path consults get_size/get_tabstops). Project 0.12.33 +
CHANGELOG; tests AGENTS.md index updated.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New check pair in punk::lib::check, in the established style (G-076
console_deadspin exemplar: pure facts-in/verdict-out classifier
tclbug_nestedswitch_tracelines_signature + has_tclbug_* proc returning the
standard buginfo dict {bug bugref description level}, auto-surfaced through
the help tcl warning report via the info procs enumeration).
Unlike the version-gated checks, this one is a LIVE behavioural probe (safe
and cheap - no console interaction): a dynamically-defined proc with a
nested 4-word switch is enterstep-traced for inner arm 1 (affected split-
list index 1 - reports line 3) and the default arm (index 5, beyond the
command word count - reports line 2 correctly), matched against the
characterized wrong/right signature. Detection therefore flips
automatically on a Tcl runtime containing the upstream fix - no fixed_in
version variable needed. Probe layout note: a 2-arm probe would put the
default body at affected index 3 and hide the signature (both arms
mismark) - the middle arm exists to push default to safe index 5 (this
initially bit the probe itself, confirming the law once more).
Followup-when-fixed documented in the proc: re-verify with
scriptlib/developer/tcl_switch_traceline_repro.tcl, flip the
ns/cmdtrace.test GAP pins and fixed-canary, update the punk::ns::cmdtrace
argdoc caveat, note the fixed-in version. New canary test
cmdtrace_upstream_bug_check_canary asserts the check still reports the bug
- on a fixed Tcl it fails first and points at that workflow.
Verified: punk/ns 69/69 and punk/lib 37/37 under Tcl 9.0.3; cmdtrace.test
6/6 under 8.7; all has_tclbug_*/has_libbug_* procs exercised help-tcl style
without error; probe self-cleans (no temp proc/var residue).
punk::lib buildversion 0.4.3 -> 0.5.0 (new API procs = minor); project
0.12.32 + CHANGELOG; tests AGENTS.md index updated.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved wording (drafted from the 2026-07-14 cmdtrace investigation):
an attribution option (live|sourcefile|auto - sourcefile mode doubling as a
practical workaround for the upstream nested-switch mis-attribution, tcl
tktview 5d5b1052280c976ea3d4) and a documented machine dict return for
future hotspot-analysis/repl consumers (implies no interactive pause).
Context records the unexplored regime boundary (module .tm procs trace
relative, plain sourced procs absolute) as goal groundwork. goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
cmdtrace gains -pause <bool> (default 1, existing interactive behaviour
unchanged): -pause 0 bypasses the "paused - hit enter key to continue"
askuser in _cmdtrace_leave so cmdtrace runs unattended and the marked-up
traced-body report (return value) can be captured by scripts and tests.
Line-mismark investigation (all punk-free raw enterstep probes, results
byte-identical on Tcl 8.6.17 / 8.7a6 / 9.0.3 - conclusively upstream):
- with the ::switch argdoc available (punk::args::moduledoc::tclcore),
cmdtrace marks flat single-block switches and 2-word-form nested switches
correctly for EVERY arm; the residual mismarks match the raw trace data
- empirical law, predictive across 4 command shapes x 6 arms and deeper
nestings: an arm body at index j of the split pattern/body list reports
container-relative lines (shift = switch command line within its
containing script - 1) exactly when j lands on a LITERAL word of the
switch command (options, --, or the block); dynamic words and j beyond
the command word count fall back to correct arm-relative attribution.
Position-based, not call-order based. Explains the ticket observation
that the affected-arm count "varies based on switch options".
- suspected machinery: Tcl_SwitchObjCmd passes split-list index j as the
TclNREvalObjEx word; TclInitCompileEnv adopts ctx line[word] when the
index happens to be in range of a per-word array describing the switch
command itself (the splitObjs munging looks intended to prevent this)
Artifacts:
- new tests ns/cmdtrace.test (5): -pause 0 smoke + error-call count,
flat-switch and 2-word-nested correct-mark guards, upstream mismark GAP
pins (gated on have_tclcoredocs - cmdtrace arm-offset correction parses
supplied switch commands against the ::switch argdoc)
- scriptlib/developer/tcl_switch_traceline_repro.tcl: standalone pure-Tcl
repro + findings write-up, suitable as an attachment/addition to the
upstream ticket
- cmdtrace argdoc caveat updated: cites the ticket and the characterized
pattern (was "possibly an unreported bug")
Verified: punk/ns suite 68/68 under Tcl 9.0.3; cmdtrace.test 5/5 under 8.7.
punk::ns buildversion 0.5.0 -> 0.6.0 (new flag = minor); project 0.12.31 +
CHANGELOG; tests AGENTS.md index updated.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New punk/ansi suites and extended punk/ns corp.test, characterizing the
corp -> grepstr -> untabify tab-handling interaction and the standalone
behaviours. All console-query paths are mocked (the overtype renderline.test
get_tabstops pattern, extended to get_size + punk::console::tabwidth): the
-untabify none / -stops terminal / -stops <int> paths consult
punk::console::get_tabstops / get_size which emit live terminal queries that
block or error in headless/piped environments - mocking is the answer to
probing that behaviour deterministically in the test harness.
- ansi/untabify.test (10): -stops 8/int/list/terminal(mocked), -with
spaces/unicode(U+21E5 + U+00A0)/custom pair, multiline, usage errors, and
the EXPERIMENTAL -plastic elastic-tabstop mode: basic expansion, the
cross-line column-alignment property, -with composition - pinned as
interim behaviour (hardcoded 8-multiple stops marked temp in source) and
deliberately retained for possible future repl editbuf use.
- ansi/grepstr.test (9): return modes incl summarydict (linemap pinned
always-present; -help claims -n-only - reconciliation deferred to the
hygiene pass), exact highlight SGR wrapping, -n numbering with * match
counts, invert + empty-highlight strip, -C context with break indicators,
capture groups, and tab handling: warns once per call on stderr, a simple
single-pass tab line survives with correct highlights.
- ns/corp.test (+6): basic-highlight ansistrip equivalence with -syntax none,
-n numbering, -untabify spaces exact tab-free expansion + proper 4-element
-syntax none list, -untabify unicode markers, the KNOWN DEFICIENCY pin for
default -untabify none on a tabbed body (5 grepstr warnings; brace overlays
mangle tabbed lines - leaked/shifted close-braces pinned exactly under
mocked tabstops; flip deliberately if tab handling is fixed or corp moves
off grepstr), and a ::tcl::CopyDirectory -untabify spaces smoke test
(tab-free, warning-free, constraint-guarded).
src/tests/modules/AGENTS.md punk/ansi + punk/ns index entries updated.
Verified: punk/ansi 63/63 and punk/ns 63/63 under Tcl 9.0.3; the three
new/extended files green under Tcl 8.7 (10/10, 9/9, 13/13).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The stringstartswith(*) arm of get_dict_can_assign_value''s multi-member
tail-clause reservation walk compared the prefix against $tp (the type
string) instead of $rv (the candidate value). Consequences (pinned pre-fix
in the previous commit):
- a later optional clause mixing literal(...) and stringstartswith(...)
members never had genuinely matching trailing words reserved - a greedy
-multiple argument swallowed them and the tail clause was silently lost
- a prefix text that happened to prefix the literal type string (e.g str vs
stringstartswith(str)) wrongly reserved NON-matching words, raising a
spurious toomanyarguments overflow
One-token fix; allocation_tailclause_ssw_reservation_GAP flipped to the
correct expectations (matching words reserved; non-matching words left to
the -multiple argument with no error); literal-only and no-match guards
unchanged. Known remaining approximation (pre-existing, noted in the
buildversion changelog): the walk still requires a literal* member in the
tail clause''s typelist to run at all - a stringstartswith-only tail clause
is not reserved.
Verified: full punk/args suite 231 total / 227 passed / 0 failed (4 intended
skips), punk/ns 57/57 under Tcl 9.0.3; allocation.test 10/10 under Tcl 8.7.
punk::args buildversion 0.12.2 -> 0.12.3; project 0.12.30 + CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
allocation.test gains coverage for the get_dict_can_assign_value multi-member
tail-clause reservation walk (a later optional clause mixing literal(...) and
stringstartswith(...) members, guarded from a greedy -multiple argument):
- guards (must hold pre and post fix): literal-only tail clause reserved
correctly; non-matching trailing words correctly left to the -multiple arg
- allocation_tailclause_ssw_reservation_GAP pins the current bug: the
stringstartswith(*) arm matches against $tp (the type string) instead of
$rv (the value), so matching trailing words are swallowed by the -multiple
argument (optional tail clause lost), and a prefix text that happens to
prefix the type string (str vs stringstartswith(str)) wrongly reserves
non-matching words, ending in a spurious toomanyarguments overflow
Verified 10/10 against the unfixed module under Tcl 9.0.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
No behaviour change (full args suite 224/0-failed, ns 57/57, 8.7 spot check).
Removed (~1100 lines of commented-out code, recoverable via git history):
- old-signature private::check_clausecolumn ("old version")
- _check_clausecolumn2 "interim version" experiment (its collect-all-clause-
failures idea preserved as an in-place note for G-072-era rework)
- pre-parsekey opts ordering loop, pasted opts-logic reference copy in the
values loop, disabled XXXliteral* switch arm, misc debug remnants
MAINTENANCE comments: the leaders/values loop-parity notes expanded into a
dated refactor assessment - shared clause-assignment helper extraction is
indicated (drift is real: G-082 duplicated its selection block, parsekey
idents exist only values-side) but deferred to ride the G-084 parity work
under the G-046 hot-path constraints; mirror-or-justify rule stated at both
loops. The old "synchronize with values loop" todo folded into it.
Documentation accuracy:
- get_dict PUNKARGS + doctools: real result keys (leaders opts values
received solos multis id form, + formstatus when candidacy ran); directive
lists corrected beyond @cmd/@leaders/@opts/@values; false primordial claims
removed ("only supports -flag val pairs, not solo options" / "only the
last value is used")
- parse -help example fixed (dict exists bracketing was broken) and header
dofilestuff example fixed (stray trailing 1 after -type existingfile);
punk::parse -> punk::args::parse; typos
- goal cross-refs annotated at code sites (G-053 -multiple ranges, G-084
values/leaders parsekey incompleteness); wrong test-name comments corrected
to parsekey_repeat_ordering
Flagged, deliberately unfixed (comment only, no pins exist): suspected bug in
the multi-member clause "stringstartswith(*" arm of get_dict_can_assign_value
- it matches against $tp (the type string) instead of $rv (the value), so it
always succeeds.
All inserted/updated comments carry 2026-07-14 Agent-Generated/Agent-Updated
marks. punk::args buildversion 0.12.1 -> 0.12.2; project 0.12.29 + CHANGELOG.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
A word rejected by an OPTIONAL argument's allocation screen (G-071
restricted-choice screen, or the basic int/double/bool/number/dict type
screen) that subsequently overflows the argument list now reports the
specific rejection instead of "Received more values than can be assigned":
- choiceviolation naming the word and allowed choices, with -badarg/-badval
and the final-validation message template (Leading/Trailing argument
attribution), for choice-screen rejections
- typemismatch naming the declared (normalized) type, with -badarg/-badval,
for basic-type screen rejections
Mechanism: private::get_dict_can_assign_value returns a 'rejection' record
(single-member clauses only; literal-category mismatches deliberately not
recorded); get_dict_form collects first-rejection-per-word from the three
allocation call sites (leader/value split trial, leaders loop, values loop)
into a per-form store; the two toomanyarguments raise sites prefer a
recorded rejection for the unassignable word. Genuinely-surplus words still
report toomanyarguments; words consumed by later slots parse unchanged;
multiform selection (rank_form_failures) untouched.
errorselection.test _GAP pins flipped to the pointed expectations (pre-fix
behaviour pinned in the previous commit). punk::args buildversion
0.12.0 -> 0.12.1.
Closeout: G-082 flipped achieved + archived (index -> GOALS-archive.md,
detail -> goals/archive/ with mechanism/verification/residue recorded);
G-073 note updated to point at the new rejection-record seam;
src/modules/AGENTS.md authoring-ergonomics bullet re-documented (-optional 0
workaround no longer needed on >= 0.12.1; make.tcl keeps it - it runs
against the bootsupport 0.12.0 snapshot). Project version 0.12.28 +
CHANGELOG.
Verified: full punk/args suite 228/224/0-failed (4 intended skips) and
punk/ns 57/57 under Tcl 9.0.3; errorselection.test 7/7 under Tcl 8.7;
make.tcl frobnicate still pointed; goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Set G-082 active (user-directed). New errorselection.test pins current
single-form error selection before the fix:
- _GAP pins: an optional choice-restricted leader (make.tcl dispatch shape),
an optional choice-restricted value, and an optional typed (int) value each
reject a word that then overflows - all report generic
{toomanyarguments N index I} with no -badarg/-badval attribution,
discarding the specific rejection (regression vs punk::args 0.5.0)
- reference pins: the -optional 0 equivalents report pointed choiceviolation
with -badarg/-badval and Leading/Trailing argument messages
- guards: genuine surplus stays toomanyarguments; a rejected word consumed by
a later slot parses cleanly; multiform failures still route through
rank_form_failures (noformmatch)
Verified: 7/7 pass against the unfixed module under Tcl 9.0.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The detail files carried richer scope text than the index (user-directed
resolution: enrich the index rather than trim the files). goals_lint now clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The 0.12.22 -> 0.12.23 bump landed in 49ec22a9 (doc: restore 'dev
doc.validate' via wrapped bin/dtplite.cmd, 2026-07-13) without a CHANGELOG
entry, and the doc-tooling/punknative/fontprep work committed between the
0.12.23 and 0.12.24 bumps was likewise unrecorded. Adds the 0.12.23 entry
(dtplite wrap, summarized from the original commit message) and a second
0.12.24 bullet covering the between-bump doc-tooling work and the G-078..G-081
goal drafting - both marked as retrospective additions.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New proposed goal G-082: single-form parse error selection should prefer an
optional argument's specific choice/type rejection over the generic
"more values than can be assigned" overflow (regression vs punk::args 0.5.0
found while dogfooding in G-030; the -optional 0 workaround sites in make.tcl
and the AGENTS authoring-ergonomics bullet are flagged for revisiting when it
ships).
Sibling notes parked in existing proposed goals:
- G-028: make.tcl's name-only process-sweep misidentification (unrelated
same-named executables) - full-path matching rides the same
process-identification infrastructure as the locker report.
- G-025: punk-exe-hosted make.tcl runs the kit's pre-loaded module copies, not
bootsupport snapshots - a self-report surface for running-interp module
provenance would make the mixing observable.
- G-073: reciprocal relation to G-082 (both want the "surface the specific
rejection" seam in validation error reporting).
- G-075: synopsis renders the definition id rather than @cmd -name - consider
a fallback for non-command ids when reworking id rendering.
goals_lint: unchanged (only the pre-existing G-078/G-081 index-mirror findings).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Fixes the two user-reported symptoms of '<punkexe> src/make.tcl shell':
Missing prompts: app-punkscript correctly forces ::tcl_interactive 0 for
script execution, and punk::repl is already loaded at kit boot - so the shell
branch's 'package require punk::repl' re-loads nothing and the repl's
load-time interactivity probe (repl line ~44) never re-runs, leaving prompts
suppressed on a real console. The shell branch now recomputes
::tcl_interactive via punk::repl::is_interactive against the actual input
channel before repl::init/start. Piped behaviour unchanged (probe still
reports non-interactive).
Raw-mode 'invalid command name struct::set': the accelerator-reload block
(package forget + rename of sha1/md5/struct::* so reloads can pick up
accelerators from the restored full paths) relied on later package-require
chains to restore the forgotten packages. Under a kit, the consumers
(punk::lib, punk::du, punk::nav::fs, flagfilter) were pre-loaded at kit boot,
their requires never re-fire, and the first repl-thread-side call of a
struct::set-backed punk::lib proc (lunique_unordered's self-redefining first
invocation, reached via flagfilter/nav::fs in interactive/raw paths) hit the
destroyed command. The block now records which of the forgotten packages were
actually loaded and re-requires them immediately. Verified by thread-probe:
the repl-thread interp now shows struct::set 2.2.5 + sha1 2.0.5 restored
identically under tclsh90 and punk91 (previously absent under punk91); the
codethread was always unaffected (it re-requires its own package list).
src/AGENTS.md: new note - punk-exe-hosted make.tcl runs in a pre-loaded
interp, not a virgin one (no-op requires, load-time state like the
tcl_interactive probe, kit-vs-bootsupport module provenance mixing); interp
surgery in make.tcl must restore deliberately and be tested under both tclsh
and a punk exe. Layout make.tcl copies re-synced via the punkcheck channel.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Self-build guard (user-identified gap): when make.tcl is driven by a built punk
executable, the kit whose deployed executable is the running interpreter is now
skipped before any build work, with guidance to rerun under tclsh or a
different kit. Previously the pre-deploy process sweep matched processes by
executable name only and would taskkill the build's own process mid-run with
-k (suicide: remaining kits unbuilt, no recap, dangling punkcheck event);
without -k only the polite kill's refusal on console processes saved the run,
and the deploy delete of the running image would fail with a cryptic message.
The sweep additionally excludes the build's own pid unconditionally, covering
a same-named copy driving the build from a non-deploy path. Informational and
update subcommands were already safe (they exit before the kit machinery);
building other kits from a punk exe remains supported. Verified live:
'punk91 src/make.tcl vfs -confirm 0' skips punk91.exe with the warning and
processes the other kits normally; plain tclsh runs unaffected.
libunknown quietening: 'punkexe src/make.tcl <cmd>' emitted
"punk::libunknown::init already done - unnecessary call? info frame -1: ..."
because punk_main.tcl had already initialised libunknown (renaming ::package)
and make.tcl unconditionally re-sourced the bootsupport copy and called init
again, tripping init's load-bearing rename guard. make.tcl now leaves an
already-active libunknown in place (no re-source - also avoids silently
swapping the running copy for the bootsupport copy when versions diverge);
plain tclsh runs source+init exactly as before. Verified: no diagnostic from
'punk91 src/make.tcl projectversion'.
src/AGENTS.md build guidance updated (punk-exe-driven builds and the self-kit
skip); layout make.tcl copies re-synced via the punkcheck channel.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Fixes the constructed-definition indent leak user review spotted in
'make.tcl help' output (@cmd -help Description first line rendered less
indented than continuations): HELPTEXTS and the inline shell/help/toplevel
help values are now block-form (first value line whitespace-only) with a bare
@normalize in every constructed definition, per G-045's preferred style. The
braced option fragments never leaked (literal block-shaped parts get
file-style normalization) and head-form values are contractually untouched by
@normalize. Also adds a define-time capability probe (punk::args::get_spec on
representative ids inside the guarded block) so a stale punk::args that
accepts the raw text but cannot resolve a mechanism (e.g pre-@normalize
snapshots) degrades to the plain fallback immediately instead of erroring at
first parse.
AGENTS infrastructure for future documentation work: src/modules/AGENTS.md
"Documentation And Comments" gains a "punk::args definition authoring
ergonomics" subsection (G-045 mechanisms: @normalize + block form for
constructed defs, -unindentedfields, -& record continuation, container
quoting rules; plus the G-030 lessons: explicit @form -synopsis for
script-level ids, -optional 0 for pointed choiceviolation errors);
src/AGENTS.md cross-references it and names ::punkboot::argdoc as the
in-tree constructed-def exemplar. Follow-up recorded in the G-030 archive.
Verified: flush Description rendering for toplevel/subcommand/shell/help
usage; dispatch, degraded mode (PUNKBOOT_PLAIN) and usage-error paths
re-verified; layout make.tcl copies re-synced via 'make.tcl bootsupport
-confirm 0' (punkcheck channel); goals_lint unchanged (only the pre-existing
G-078/G-081 index-mirror findings).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Snapshot refresh via 'make.tcl modules -confirm 0' + 'make.tcl bootsupport
-confirm 0' after punk::args joined the bootstrap-tracked staleness set
(bootsupport had 0.5.0 vs source 0.12.0 - the new gate tripped as designed).
Superseded versions pruned by punkcheck records; project-layout bootsupport
trees and layout make.tcl copies followed via the established punkcheck
channel (punk.basic, punk.project-0.1, punk.shell-0.1).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
All 15 make.tcl subcommands are punk::args-declared ((script)::punkboot +
(script)::punkboot::<sub>, built from single-source summary/help/opt dicts with
shared option fragments and explicit @form -synopsis). Bare make.tcl / -help,
'help ?subcommand?' and '<subcommand> -help' render tabled usage; invalid
flags/subcommands raise punk::args usage errors (exit 1) with unambiguous
prefix resolution; 'shell' is a declared passthrough.
Prompt policy: new -confirm 0|1 (default 1) on every confirmation point
(bootsupport minor-staleness gate, vfscommonupdate REPLACE, kit-type mismatch).
Default prompts only on an interactive terminal and aborts fast with guidance
on non-interactive stdin (::punkboot::lib::stdin_is_interactive; Tcl 8.6 lacks
the -inputmode probe and is assumed interactive). -confirm 0 proceeds
(staleness, REPLACE) or skips the mismatched kit. The piped-y agent workflow is
retired; the old vfscommonupdate decline half-abort (printed done, exit 0) now
exits 1.
Degrade rule: punk::args/punk::ansi/textblock boot requires guarded; definition
load caught with fallback to a self-contained scan (-k/-dirty-abort/-confirm
supported) + plain punkboot_gethelp (availability NOTE factored into
punkboot_availability_note, shared by both paths); rendering degrades
independently of parsing (errorstyle minimal / plain help when the ANSI stack
is unhealthy); PUNKBOOT_PLAIN=1 forces degraded mode. punk::args joins the
bootstrap-tracked _runtime_deps staleness set (parsing contract only - the
rendering stack degrades instead; contract docs updated in
src/bootsupport/AGENTS.md + src/modules/AGENTS.md, workflow docs in
src/AGENTS.md + src/tests/shell/AGENTS.md).
Verified: usage/help/error paths, vfscommonupdate fail-fast and -confirm 0 runs
with closed stdin, staleness flag route live (args 0.5.0->0.12.0 tripped the
gate), degraded-mode help/check/info, full 'project -k -confirm 0' kit build.
Dogfooding finding recorded in the goal file: punk::args 0.12.0 reports generic
overflow where 0.5.0 reported choiceviolation for optional-choice mismatches
(worked around with required leaders; candidate error-selection improvement).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Formalize the follow-on work identified during the punk::args documentation
trials and ansi->html prototyping (2026-07-13/14):
- G-078 punk::ansi ANSI->HTML rendering api: promote the prototype ansi2html
converter + headless ansicat flatten entry into a documented punk::ansi
api (palette option, art mode with bold-as-bright and block sealing,
-assets embed|link|none using the vendored punkdoc-mono; docs-screenshot
enabler)
- G-079 default-colour semantics: renderspace replay output bakes explicit
SGR 40 for never-set backgrounds; preserve default fg/bg semantically so
html can theme-match any page background (current workaround: black pre)
- G-080 deterministic cell-grid rendering mode: inline-block cell emulation
to eliminate the residual sub-pixel seams the span-mode recipe accepts
- G-081 argdoc build pipeline: dev doc.* generation of doctools + punk-native
html + markdown from punk::args definitions against dev modules, incl.
per-form table rendering, deeper-namespace pages, @package surfacing
(G-075) and shared doc-set font assets
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Improvements from user review of the punk::ansi trial page:
- command index <nav> at page top (doctools-style jump list); hook to
display @package info above it when specs carry package_info (guarded -
key absent in older punk::args spec dicts)
- multiform commands: punk::args::usage renders all form synopses but only
the default form arg table (terminal UX expects i -form N) - the page now
adds a per-form ARG TABLE for each form that has arguments, trimmed at the
table-header separator so the command/description/synopsis panel is not
repeated per form (renderspace lines are colour-self-contained, so slicing
at a line boundary is safe); argument-less forms are skipped
- pre backdrop is now true black (page body stays dark grey):
overtype::renderspace overlay output emits explicit SGR 40 and example
helpers treat default background as the terminal backdrop - on black they
blend as in a terminal (proper fix = default-colour semantics, goal)
- row pitch line-height:17px (integer, just under the 17.85px inline
background height at font-size 15.36px) - the fractional 1.15em pitch put
row boundaries at fractional positions and showed periodic hairline gaps
through solid-bg runs
- explicit package require punk::lib (tstr placeholder resolution uses
punk::lib::undent; previously loaded only by transitive luck when usage
ran before get_spec)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Outcome of empirical seam/aspect testing of the ansi2html rendering against
src/testansi cp437 art (chrome + firefox, user-verified):
- punkdoc-mono.woff2 rebuilt with STOCK line metrics. The interim
normalize-to-win-metrics experiment (hhea/typo := win) is REJECTED and now
documented: it grows browsers'"'"' inline content area to 1.3213em, so at row
pitches below that every span'"'"'s background bleeds ~2.5px into neighbouring
rows - wrong-coloured bars under solid blocks. Kept as commented-out
normalize_line_metrics() in make_punkdoc_mono.py with rationale.
- font builds are now byte-reproducible: TTFont(..., recalcTimestamp=False)
keeps the source head.modified (two consecutive builds hash identically).
README records the new output sha256 and the reproducibility note, plus a
cell-geometry section for css authors (0.5859375em advance -> integer 9px
cells at font-size 15.36px; blocks paint the 1.3213em win cell) and the
settled art recipe: stock metrics + tight line-height:1.0 pitch +
transform:scaleY(1.3212890625) for terminal aspect (accepted trade-off:
minor residual sub-pixel seams; deterministic future fix would be
inline-block cell-grid emulation). Larger pitches (17.85/20px) tested and
rejected - stark row seams.
- punkargs_punknative.tcl: font-size 13px -> 15.36px (integer cell width -
fractional advances round differently at styled-span boundaries and seam
block/border glyphs); line-height stays 1.15 for text-oriented doc tables.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Repo policy is LF for text files; the as-downloaded copy had CRLF (also
tripped the fossil crlf warning on checkin).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
src/scriptapps/tools/fontprep/: pinned monospace web font for the punk-native
html doc pipeline, closing the glyph-coverage gap the probe identified -
unicode 16 octants (U+1CC00-1CEBF) and Symbols for Legacy Computing
(U+1FB00-1FBFF) needed by ansicat/textblock rendering are absent from
commonly-installed monospace fonts (even system Cascadia copies are commonly
pre-2404 and lack them).
- punkdoc-mono.woff2: glyph subset of Cascadia Mono v2404.23 VARIABLE ttf
(wght axis 200-700 kept - true bold from one ~80KB file; 1561 cmap
codepoints incl. full CP437 repertoire, box/blocks/geometric, braille,
legacy computing + octants). Coverage verified 157/160 against the measured
glyph inventory - identical to the full source font (misses are deliberate:
em-space + fullwidth forms are converter-normalization/fallback territory).
- renaming is REQUIRED by licence: Cascadia's SIL OFL 1.1 declares Reserved
Font Name "Cascadia Code" and subsetting is modification. Name table is
surgical: family records renamed, Microsoft copyright preserved verbatim
(OFL requirement), trademark record removed (a renamed copy must not assert
Microsoft's mark), OFL statement/url in licence records, provenance credit
in the description record.
- LICENSE-cascadia-OFL.txt (from the v2404.23 tag), punkdoc-unicodes.txt
(whole-block ranges with headroom), make_punkdoc_mono.py (fonttools subset+
rename script), README.md (full provenance: source/output sha256s, exact
command, regeneration steps). Python fonttools is one-time prep tooling
only - the doc build never invokes it; generators just read the .woff2.
Track licence in the G-063 inventory.
punkargs_punknative.tcl: new -assets option consuming the vendored font:
embed (default) = data-uri @font-face, fully self-contained page;
link = copy punkdoc-mono.woff2 beside the output and reference relatively
(shared+cached across a doc set); none = css stack only, with
warn-and-degrade when the asset is missing. font-weight 200 700 descriptor,
punkdoc-mono prepended to the fallback stack.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Two G-candidate prototypes under src/scriptapps/tools/ for punk::args as the
documentation source of truth (run against bootsupport modules with a plain
tclsh, e.g: tclsh punkargs_to_doctools.tcl punk::path out.man):
- punkargs_to_doctools.tcl: package's punk::args definitions -> doctools .man
(Tcl-standard [arg]/[opt] synopsis conventions by design - punk s-style is
out of scope for the doctools target). Covers @cmd summary/help, per-form
[call] synopses, argument detail lists in argspace order (leaders/options/
trailing values), constraint sentences (defaults/choices/ranges), id aliases
as cross-references. Validated via 'dtplite validate' (bin/dtplite.cmd);
punk::path trial output renders clean through the html/text/nroff engines.
- punkargs_punknative.tcl: doctools-free pipeline faithful to punk s-style.
html = punk::args::usage ANSI output converted via a minimal SGR->CSS
ansi2html (16/256/truecolour, bold/dim/italic/underline/strike/reverse) on
punk::ansi::ta::split_codes - candidate for a punk::ansi public api (also
the docs-screenshot enabler for ansicat/textblock output). markdown = GFM
with verbatim s-style synopsis fences + per-form argument tables.
-boxmap none (default) keeps faithful heavy box glyphs; -boxmap light maps
to the light set as a portability fallback.
Key findings baked into the code comments:
- css font stacks must be set on the pre element itself - the UA stylesheet's
'pre {font-family:monospace}' overrides body inheritance (cause of an
initially-misdiagnosed overlong-border rendering bug)
- glyph coverage probe over src/testansi + textblock::periodic/frames +
punk::args::usage (160 codepoints incl. unicode 16 octants and legacy
computing blocks): Cascadia Mono >=2404.23 covers 157/160; embedding or
referencing a pinned punkdoc-mono font remains the plan for doc-set output
since octant/legacy glyphs are absent from commonly installed fonts.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
'dev doc.validate' invokes a bare dtplite command which the repl
unknown-handler resolves via auto_execok on PATH - no dtplite executable
existed (only the legacy misnamed bin/dtplite_run.bat), giving
"invalid command name dtplite".
- src/scriptapps/dtplite.tcl: LF-converted (polyglot payloads are embedded
verbatim into the LF-only multishell output); fall back to the
project-vendored tcllib (src/vendorlib_tcl9/<arch>/tcllib*) when the
invoking tclsh lacks the dtplite package
- src/scriptapps/dtplite_wrap.toml: new scriptset config (tclsh nextshell
on all platforms)
- bin/dtplite.cmd: generated polyglot via
punk::mix::commandset::scriptwrap::multishell (checkfile-clean, LF-only)
- src/tests/shell/testsuites/binscripts/dtplite.test: artifact pins
(LF-only, checkfile, byte-identical round-trip re-wrap) + execution
usecases (usage error, validate good/bad file, validate directory tree,
html generation) - 8/8 pass under runtests
- AGENTS.md (bin, src/scriptapps): record the dtplite scriptset, its test
pin and the LF-only payload requirement
- punkproject.toml: 0.12.22 -> 0.12.23
Verified: 'dev doc.validate' in punk902z src validates all 64
src/doc .man files clean. The doctools pipeline remains interim -
punk::args is the intended doc source of truth.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com