Both user-approved drafts arising from the G-045 tclparser assessment:
- G-069: dev-time lint cross-checking punk::args record-splitter boundaries
against tclparser parse command where the binary is available -
dialect-aware comparison (-& pre-join, ANSI strip), capability-gated,
zero new runtime dependencies for punk::args.
- G-070: pure-Tcl implementation of the tclparser parse-command API scoped
to what punk::lib consumes, parity-verified against the C library over a
probe corpus; replaces the tclparser_tcl error stub with
prefer-C/fallback-pure dispatch. Reference source to be user-provided
under TEMP_REFERENCE with recorded provenance.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Increment 5 (final): the container quoting rules pinned by defquoting.test
now appear in the punk::args::define -help documentation - braced values
fully literal (backslash sequences survive as typed); double-quoted values
get Tcl backslash semantics at record parse while $ and [] stay literal
with no substitution outside tstr placeholders; the backslash-escaped
placeholder idiom renders a literal placeholder. Rendered section verified
in punk902z src (meta-escapes display correctly). punk::args suite 186
pass / 1 pre-existing skip / 0 fail.
Acceptance review recorded in the detail file: all criteria satisfied
across increments 1-5 (@cmd -unindentedfields 0.6.1, i help alignment
punk 0.2.4, -& record continuation 0.7.0, @normalize + define_docs
consumer proof 0.8.0/punk 0.2.5, quoting documentation 0.8.1; suite grown
128 -> 187 tests, GAPs flipped, none weakened, full source-tree suite zero
regressions).
Flip edits: G-045 index entry moved to GOALS-archive.md (achieved
2026-07-12), detail file Status flipped with evidence in Progress,
reference sweep updates G-053 notes. The detail file move to
goals/archive/ follows in the next commit as a pure rename (per the
goals/AGENTS.md archive rules) - goals_lint is transiently unclean between
the two.
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
An unquoted trailing -& element on a definition record line continues the
record on the next line. Implemented in
private::split_definition_records: the token is dropped and the next line
joins after a single space with its leading whitespace collapsed - exactly
how the Tcl parser joins backslash-newline continuations before a braced
definition ever reaches the splitter - so a -& record assembles
byte-identical to its backslash-continued equivalent. Motivation:
constructed (string-built) definitions cannot author backslash-newline
ergonomically (the building code's own quoting consumes it); -& is plain
text and survives any construction.
Collision rules (analysis and decision recorded in the goal detail file):
bare word preceded by whitespace (or whole line), trailing whitespace
tolerated; braced/quoted -& is data ({-&} escapes a literal trailing
value); mid-line -&, word-suffix abc-&, and -& inside still-open
braced/quoted values are data. Element-count disambiguation rejected
(action-at-a-distance; positional rule is locally decidable). Backslash
authoring unchanged - continuation is additive.
Tests: new recordcontinuation.test (6 tests) incl. backslash-twin
parse+render byte-equality and the constructed-def chaining case. Full
punk::args suite 181 pass / 1 pre-existing skip / 0 fail; full source-tree
suite 801 pass / 13 skip / 1 fail = exec-14.3 only (known baseline) - zero
regressions (tclsh 9.0.3). define doc documents -& alongside backslash
continuation.
Also recorded: tclparser considered and rejected for the splitter (ANSI
unbalanced-bracket data, dialect semantics outside Tcl grammar, binary
dependency vs G-004); dev-time parse cross-check lint flagged as candidate.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User decision 2026-07-12: when the constructed-definition normalization
mechanism lands, define_docs converts from its interim left-margin
authoring to indented-plus-normalized authoring, remaining the
acceptance criterion's consumer proof as written. Left-margin authoring
via -unindentedfields stays a supported style proven by the rendering
tests, but is not the preferred style for define_docs itself.
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
arg_error's cmd-help display transform (undent " "+help, max 4 - the
'#unindentedfields ?' todo site) is now gated by "-help" membership in the
@cmd line's -unindentedfields list, mirroring the existing per-argument
gate. The single transform site feeds both the table and string renderers,
so left-margin-authored @cmd help renders its first line flush with
continuations in both. @cmd -summary carries no indent transform in any
renderer, so -unindentedfields for -summary is vacuously honoured. No
in-tree definitions set -unindentedfields on @cmd - existing rendering is
unchanged. define doc for -unindentedfields now states where the option is
valid.
Tests: rendering_unindentedfields_cmd_help_GAP flipped to
rendering_unindentedfields_cmd_help (aligned expectation, both renderers
measured). Full punk::args suite 175 pass / 1 pre-existing skip / 0 fail;
punk::ns suite 53/53 (arg_error consumer); make.tcl modules builds clean
(tclsh 9.0.3).
Also: G-045 flipped proposed -> active (user direction 2026-07-12);
progress and remaining-work recorded in the detail file.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The args 0.6.0 module work (c309ed47) predated the 0.12.2 bump but its
changelog entry covered only G-039; the vfs payload sync (15c10637) ships
the user-visible synopsis rendering change in built kits, so it gets its
own patch bump and entry per the change-driven policy.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New user-preference bullet: agent-authored text avoids typographic
Unicode (em/en dashes, curly quotes, arrows, ellipses) in favour of ASCII
equivalents, with hard enforcement for outward-bound artifacts; documented
exceptions for non-ASCII subject matter, verbatim quotes, and explicit
requests. Existing files are not bulk-retrofitted.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Replaces args-0.5.0.tm with the built 0.6.0 (small restricted choice sets
display as literal alternates in synopses).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
An interactive shell orphaned by its hosting console dying (killed
conhost/terminal) previously spun ~2 cores forever: the Tcl 9 windows
console driver never delivers the dead-console state to the script as a
fileevent (tclWinConsole.c ConsoleEventProc only notifies on buffered
data) while its reader thread busy-loops on the persistent channel error,
so the script level is completely blind and nothing ever closes the
channel.
Fix: repl::console_watchdog - a self-rescheduling liveness poll (default
5s, repl::console_watchdog_ms; read-only GetConsoleMode probe via
chan configure -inputmode) armed by repl::start only for a tcl9 console
input channel serving the process-default console on windows. On probe
failure it closes the input channel (stopping the driver's reader
thread) and finishes the repl via the normal eof done-path; app-punkshell
then finds no console reopenable and exits cleanly. Piped, foreign-console
and tcl 8.6 inputs never arm it. repl::start's post-vwait reader
deregistration now tolerates a watchdog-closed channel.
Verification (2026-07-12): kill procedure post-fix exits the orphan in
1.5-2.0s with no traceback (src mode and rebuilt kits punkbi/punk91/
punk902z); 25s live-console soak shows no spurious trigger, CPU delta 0;
piped stdin unaffected; repl consolebackends 3/3 and punk::console suites
88 pass / 1 skip; root cause verified against plain tclsh 9.0.3.
Upstream ticket filed: https://core.tcl-lang.org/tcl/tktview/f10d91c2d3
Included:
- goals: G-039 flipped achieved 2026-07-12 and archived (index entry to
GOALS-archive.md, detail file to goals/archive/ with full root-cause,
repro and verification record); reference sweep adds the eof done-value
producer note to G-038
- src/modules/punk/AGENTS.md: watchdog contract documented
- project version 0.12.1 -> 0.12.2 + CHANGELOG entry
- vfs payload sync: _vfscommon.vfs punk/repl 0.4.0 -> 0.5.0
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New goals (user-approved drafts, all proposed) covering the declarative
vendoring direction:
- G-065 declarative vendoring: toml-declared external packages with
version/commit pinning, retrieval provenance, binary-scan gating with
punkproject.toml override; manual drop-ins stay supported (surfaced as
undeclared); agent-free by design
- G-066 pkgIndex.tcl-to-.tm repackaging: lib.copyasmodule expansion with
embedded LICENSE/metadata datafile and distribution-unit tracking for
multi-package upstreams (tcllib-style)
- G-067 module artifact channel: publish/retrieve prepared .tm modules
against configurable artifact servers, sharing the G-006 consent-gating
and source-override pattern
- G-068 agent-assisted moduledoc generation workflow for vendored
third-party libraries (G-055 pattern generalized), decoupled from basic
vendoring
G-063 contract extended (user-approved): vendored-package license
indications additionally carry verification provenance (method, verifier,
date), reported by the audit surface.
Proving case recorded in G-065 notes: the hand-trimmed tcl_oauth2_library
copy was load-tested then removed before ever being committed, so the
first vendoring of it runs end-to-end through the declaration; the
TEMP_REFERENCE clone remains the upstream stand-in.
goals_lint: clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Contract update (user-approved): Goal/Acceptance now make capture
disposition policy-governed - snapshots yield an opaque capture token by
default (no path or pixels in output), analysis relays token+prompt to
user-policy-permitted endpoints (local-only or allowlist) returning text
only, raw-image release (path/base64) is gated on explicit user config
with the default refusing, and every capture/disposition is audit-logged.
New "Privacy model (capture disposition)" section specifies the
mechanism: opaque tokens, mechanism-side endpoint checking, expose_pixels
policy (default analyze-only), policy config in user-profile scope
outside the repo, audit trail, AGENTS.md guidance as an additional layer
rather than the gate, and the honest enforcement ceiling (unrestricted
same-user exec can capture outside punk; target is private-by-default
sanctioned path + deliberate/auditable circumvention).
Notes record further hardening as a potential future task: separate-
principal broker with admin-owned config, and consent prompts - including
the trap that G-020 input injection can click an ordinary consent dialog,
so any prompt mode needs a surface SendInput cannot reach.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Finalises the G-062 achieved flip staged by the prior session (punkshell
0.12.1): LICENSE.txt (BSD-2-Clause, Julian Marcel Noble 2023-2026) at the
repo root, README/punkproject.toml/AGENTS.md license declarations, index
record to GOALS-archive.md and detail file to goals/archive/.
Archive-loss prevention, from the G-015 incident (its achieved-status
verification parenthetical was silently dropped by the 2026-07-11 two-tier
restructure's Status-line normalisation; the text is restored to the G-015
archive file's Notes with provenance):
- root AGENTS.md 'Doc Restructures': deleted-line conservation check before
committing bulk doc migrations, structured-field-normalisation hazard
(relocate prose to body sections first), moves separated from edits
- goals/AGENTS.md: lintable header field grammar (one line per field, bare
Status values), flip-time verification evidence recorded in the body, the
archive move content-identical, and a new archive-time reference sweep:
pending-tense mentions of the archived goal updated in the live tier, and
actionable archived notes pointed to from the affected live goal's Notes
- GOALS.md maintenance rules: achieved-flip clause extended to require the
evidence write-up and the reference sweep
Retroactive reference sweep over all 12 archived goals (25 live detail
files): pending-tense fixes (G-002 G-008 G-013 G-016 G-017 G-021 G-022
G-031 G-042 G-044 G-050 - G-017's Goal/Acceptance annotated as
gate-satisfied, contract meaning unchanged), forward pointers pushed from
archived notes (G-062 license-seeding follow-on -> G-012/G-027, G-037
vendorlib/vfs drift semantics -> G-024, G-058 static-baseline mechanism ->
G-005), and one 'Archived-goal references' Notes bullet per remaining
referencing file so every live mention of an archived goal is resolvable
without consulting the archive index.
scriptlib/developer/goals_lint.tcl (new, plain tclsh): validates detail-file
header grammar, strict status values in both tiers, orphan rules in both
directions, Status/Scope mirror consistency, plus an informational (never
fatal) warning for live files referencing an archived goal with no
achieved/archive marker - baseline now zero warnings. Root AGENTS.md
scriptlib/developer ownership note widened to cover developer utilities.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
An argument whose choice pool (-choices plus -choicegroups members,
deduplicated) has 1-3 members and -choicerestricted true (the default) now
renders those words unitalicised joined by | in synopses - e.g 'after cancel'
shows literal cancel, a 3-choice option shows (left|centre|right) - matching
the display style of literal()/literalprefix() type-alternates. Larger or
unrestricted choice sets keep the italicised argname/<type> display, and an
explicit -typesynopsis always takes precedence (textblock::frame -type
unchanged). New shared helper punk::args::private::synopsis_choice_literals
feeds both synopsis render paths (leaders/values via
synopsis_form_arg_display, options inline in synopsis); applies only to
single-element -type lists. Superseded commented-out single-choice sketches
removed; define doc for -choices documents the rule.
tests: synopsis.test 4 -> 13 - characterization coverage for
literal/literalprefix/stringstartswith/stringendswith type-alternates,
option alternate parenthesization, multi-element clause display (?type?
members, argname tail-word hints), -typesynopsis value-element lists and
option passthrough incl documenter ANSI, plus the new choice-literal rule
(leader/option/value positions, choicegroups counting, >3 and unrestricted
fallbacks, -typesynopsis precedence). rendering.test choicelabel fixtures
padded to 4 choices so markercol keeps matching the choices cell rather
than the now-literal synopsis line.
Known residue (deliberate): option-path -typesynopsis ?-trim edge cases
remain (todo comments at the render site) - resolve-time rejection deferred;
any future normalization surgery belongs to punk::ansi::ansistring/opunk::Str.
project 0.12.0
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Re-vendor the G-001 modules into bootsupport, the project-layout
bootsupport copies, and the runtime vfs: punk::repl 0.4.0 replaces 0.3.0
and opunk::console::tk 0.2.0 replaces 0.1.0.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New agent-maintainable scriptlib/developer/ area (recorded in root
AGENTS.md ownership notes). tkconsole_demo.tcl wires a Tk text widget as a
live ::opunk::TkConsole and runs an interactive repl against it, with a
layer-by-layer commented walkthrough of the mechanics: voo virtual
dispatch, the reflected-channel/input-pipe wiring, repl::init -console
routing and the junction-stack output diversion, and the vwait/Tk event
loop interplay. punk::args-documented options (--help renders the usage
table; the definition is registered for 'i developer::tkconsole_demo'):
-columns/-rows/-font/-title, -demo (auto-typed session via feed, including
a window-resize step showing size queries tracking actual dimensions) and
-autoclose (exercises the <Destroy> -> teardown -> eof path). Includes a
demo-installed code-interp bridge so in-session punk::console::get_size
reports the tk console's current size - documented as a hand-rolled
preview of G-008 scoped console state.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
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
New modules/punk/repl/testsuites/repl/consolebackends.test drives an
interactive repl through TestConsole (chan pipe pair), SshConsole (socket
pair with a scripted remote terminal answering CSI 6n - size 100x30
resolved over the socket) and TkConsole (wired text widget; self-gates on
Tk availability in the child) to a clean exit: prompt-by-prompt
conversation, results, diverted code-interp stdout/stderr. Each case execs
testsupport/repl_console_driver.tcl in a child tclsh - a repl cannot run
inside the shared runtests testinterp because the codethread's quit/exit
callbacks thread::send to the thread's MAIN interp (documented in
src/tests/AGENTS.md).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
TkConsole holds the widget in a subclass o_widget field (always the
authority for size/eof/capability; new 'widget' accessor) and accepts
optional -in/-out constructor channels. New minimal widget-console wiring
::opunk::console::tk::console: a reflected output channel rendering into
the widget (ansi-stripped when punk::ansi is present) plus an input pipe
fed by the <Return> binding or programmatic submit/feed, with <Destroy>
teardown flagging backend eof and closing the feed end - so a channel-
driven repl runs against the widget via 'repl::init -console'. The size
override now reports the widget's ACTUAL character dimensions while mapped
(current pixel size / font metrics - tracks live window resizing); the
requested -width/-height still answer for unmapped widgets, keeping
construction-time behaviour and existing test pins unchanged.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
repl::init -console <spec> selects the console the repl reads/writes (any
punk::console::console_spec_resolve form); repl::start's inchan is now
optional, defaulting to the selected console's input. Per-repl channel state
(conin/conout/conerr) routes rputs (stdout/stderr mapped per-repl) and
doprompt; for a foreign console the code interp's stdout/stderr are diverted
via shellfilter 'var' junction stacks and emitted to the console after each
run (repltype punk/0). New helpers console_is_default/console_at_eof/
console_get_size dispatch eof/size to the selected ::opunk::Console object's
(possibly overridden) methods. Process-console behaviours (tcl_interactive
prompt gating, stdin reopen on eof, raw-mode re-enable, windows utf-16be
line re-decode experiment, mode-line on exit) now apply only to the default
console. Default stdin/stdout behaviour unchanged. Also fixes rputs pseudo-
channel mapping in the 3-arg -nonewline form (mapped value previously
written over the -nonewline flag).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
G-062: canonical project license - root BSD-2-Clause LICENSE.txt with
SPDX-identified references in README.md, root AGENTS.md and a
machine-readable license field in punkproject.toml.
G-063: per-package license tracking - SPDX-normalized Meta license
indications via a friendly-name mapping module (authors need not know
SPDX ids), copyleft/viral-license flagging audit surface, and fixing
the literal %license% template placeholder seeding.
G-064: dev lib.search machine-parsable returns - ansi-free -return
dict/json with documented structure (G-049 pattern) plus an option
surfacing per-package license indications in table and machine returns.
All three proposed with user-approved wording (2026-07-11).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
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.
Warn-only by default; new -dirty-abort flag makes the check aborting.
With '<builtexe> src' available for evaluating uncommitted source directly,
building is the promotion step this treats it as.
- punkboot::utils 0.2.0: vcs_dirty_warnings gains optional scope arg so only
changes under a subpath (src) count; unscoped vendorupdate call unchanged.
- Warnings print with a plain column-0 PROVENANCE-WARNING: token (greppable
in redirected output) + ANSI colour, shared with vendorupdate's dirty
source-project check, and are recapped at end-of-run via a wrapped ::exit
so they survive scrolling chatty build output.
- Interactive terminal runs (stdin -inputmode probe, tcl 8.7+/9) get a 3s
ctrl-c grace countdown before a dirty build proceeds; piped/agent/CI runs
pay no delay.
- 'make.tcl check' reports src provenance status and what the build
commands would do.
- Guarded require: stale/missing punkboot::utils snapshot degrades the check
to a skip notice, but -dirty-abort then aborts rather than silently losing
the requested strictness.
Project 0.10.2 -> 0.10.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Verified nothing depends on the old version or filename before renaming:
all 'package require punk::libunknown' sites are unversioned; punk_main.tcl
and punk::repl locate the module by globbing libunknown-*.tm and picking the
highest by vcompare (so the renamed dev copy now also outversions the stale
bootsupport and project.vfs 0.1 copies deterministically, instead of relying
on tm path order for a same-version tie); bootsupport's
include_modules.config lists it by name only.
The 0.2.0 number retroactively versions the two changes shipped against the
0.1 filename earlier today (register_all_tm deep discovery - a minor API
addition - and the source_pkgindex sourcing-scope fix). A version-history
comment block in the module header now substitutes for the buildversion.txt
changelog other modules carry.
src/modules/AGENTS.md: the punk::libunknown exception bullets now spell out
the manual-versioning mechanics for agents - same Patch/Minor/Major bump
rules as buildversion-tracked modules, executed as a file rename plus Meta
line, manpage_begin, provide-block and version-history updates, with a
check for exact-version/filename dependents before any first bump.
discovery.test/libsearch.test: the source-tree libunknown locator now picks
the highest libunknown-*.tm by vcompare instead of plain lsort (robust to
future version bumps). Verified live in punk902z src: package provide
reports 0.2.0, register_all_tm present, lib.search deep discovery intact.
Suites green under tclsh90 and tclsh87. Build artifacts synced (root
modules/ and _vfscommon.vfs carry only libunknown-0.2.0.tm).
punkshell 0.10.2. Stale 0.1 copies remain in src/bootsupport/modules
(pending 'make.tcl bootsupport') and src/vfs/project.vfs (pending layout
maintenance) - both now cleanly outversioned at runtime.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
zipfs_tclPkgUnknown previously declared 'global dir' and executed pkgIndex.tcl
scripts via 'namespace eval ::' - the pkgIndex $dir contract was met by
writing the global namespace's dir variable, silently overwriting any user
global named 'dir' whenever a package require fell through to the pkg unknown
handler (observed misdirecting a file write into the user's Tcl installation
during test development), and each index's stray unqualified variables (ver,
pkg, script, _CawtSubDirs, ...) leaked into ::.
Index scripts now execute in a source_pkgindex proc frame: $dir is a formal
parameter and auto_path/env are global links - exactly the environment stock
tclPkgUnknown documents (its indexes see dir as the handler's proc-local plus
'global auto_path env'), without stock's incidental exposure of all its other
proc locals. tcl::Pkg::source uplevels into the caller's frame, so the scheme
works unchanged for the 8.6 pre-tip459 fallback. The legacy non-epoch branch
already sourced in the handler frame and simply gains stock parity from the
'global dir' removal.
Reviewed against tcllib 2.0's vendored index behaviours (all compatible):
qualified '$dir ni $::auto_path'/'lappend ::auto_path' extension in the
top-level index, its own apply-scoped subindex sweep (the same isolation
idiom), vsatisfies guards with early return, 'package provide' during index
sourcing (try/pkgIndex.tcl on 9+), and critcl-generated ifneeded strings
(md5c, tcllibc) whose proc definitions run at require time, not source time.
One deliberate divergence from stock: each index file gets its own frame,
so unqualified variables no longer persist between index files within one
sweep (stock shares its handler frame across the sweep) - nothing in tcllib
relies on that.
discovery.test: the GAP pin flips to libunknown_pkgunknown_preserves_global_dir,
plus new pins for the index contract - $dir-based ifneeded/source works,
unqualified 'lappend auto_path' extension reaches the real ::auto_path, and
stray index-script sets don't leak to ::. Verified live in punk902z src:
::dir no longer set at startup, user dir global survives package activity,
tcllib md5/struct::set/json load through the new frame, lib.search deep
discovery unaffected. Remaining startup globals def/pkg/ver come from
punkshell's own boot code (punk_main.tcl foreach loops), not the handler.
punkshell 0.10.1. punk::libunknown remains manually versioned at 0.1;
vfs artifact synced, bootsupport copy untouched as before.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
punk::libunknown gains register_all_tm: walks every tcl:™️:list path
recursively and registers ifneeded scripts for .tm modules at every
namespace depth (the tm unknown handler only registers siblings at the
requested depth, leaving never-requested subfolders like test::* invisible
to 'package names'). First registration wins - parity with the handler and
the shadowing pins. Reuses/populates the per-epoch directory index cache
(zipfs whole-tree listing; per-dir globs for filesystem paths; #modpod-*,
#tarjar-* and _build skipped) and runs at most once per tm epoch per
interp - the guard is the interp-local tm_fullscan variable, deliberately
not in the shareable epoch dict since ifneeded registrations are
interp-local.
punk::mix::commandset::loadedlib 0.2.0: search runs register_all_tm plus
the auto_path pkgIndex sweep by default when punk::libunknown is active,
so 'dev lib.search test' now shows deep modules without -refresh.
-refresh is repurposed to mean a genuine filesystem re-scan: package epoch
incr (invalidating the scan caches) then rediscovery - picking up .tm
files added/removed on disk. Without punk::libunknown (or with an older
copy lacking register_all_tm) -refresh falls back to the previous
dummy-require deep walk. Dependency fixes: highlight ansi computed only
when -highlight 1 via qualified punk::ansi with inline require (previously
relied on the shell-global a+ alias unconditionally and errored in bare
interps), inline requires for punk::path (fallback walk) and textblock
(table output).
New test suites (green under tclsh90 and tclsh87):
- modules/punk/libunknown/testsuites/discovery/discovery.test: lazy-depth
sibling registration, register_all_tm all-depths/cached-per-epoch/
head-wins-parity, package epoch shape and trace-driven increments,
epoch-cache short-circuit + incr recipe, and a GAP pin of
zipfs_tclPkgUnknown clobbering a user global 'dir' variable (stock
tclPkgUnknown keeps dir proc-local; fix candidate).
- modules/punk/mix/testsuites/loadedlib/libsearch.test: search match
semantics, default deep discovery, -refresh re-scan contract, highlight
without shell-global ansi aliases.
Both suites source the source-tree punk::libunknown directly by path:
'package require' would tie-break the same-version bootsupport copy by tm
path order (testinterp order favours bootsupport; child-interp
'tm::add {*}list' reverses precedence).
Verified live in 'punk902z src'. Build artifacts synced via make.tcl
packages + vfscommonupdate (loadedlib-0.2.0.tm, libunknown-0.1.tm).
Note: src/bootsupport copy of punk::libunknown intentionally untouched -
becomes stale until the next 'make.tcl bootsupport' sync; loadedlib
degrades gracefully against it. punk::libunknown remains manually
versioned at 0.1.
punkshell 0.10.0 (see CHANGELOG.md; also records the 0.9.1 doc-only
-refresh help rewrite).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
A scratchpad test repo (fossil-init/opened 2026-07-06 while probing
ignore-glob semantics) registered repo:/ckout: rows in the global
_fossil config-db and persisted as row 1 of dev projects.work.
Instance cleaned up (fossil all ignore + dir removal + ckout prune).
- root AGENTS.md User Preferences: throwaway fossil repos must use a
scratch FOSSIL_HOME so registration lands in a disposable config-db;
includes the remediation recipe.
- G-016 Notes: the staleness concern applies to fossil's own central
config-db, not just a punk-maintained registry; the shipped
enumeration design needs a staleness story for both VCS sources,
especially the -return dict|json machine forms.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- src/tests/AGENTS.md: agent-added tests carry a one-line provenance comment `#added <YYYY-MM-DD> (agent[, G-<id>])[ - <short note>]` - immutable facts only (never "G-NNN will flip this" expectations, which live in _GAP_ test names and goal files); user-added tests optional; no bulk retrofit of existing suites. Rationale: provenance must survive where VCS history does not travel - packaged test modules (G-029), git+fossil dual history, file regeneration/moves
- GOALS.md maintenance rules: marking a goal superseded/abandoned includes a test sweep - grep G-<old id> (at minimum src/tests) plus the tests named in the goal's detail-file Acceptance, and record each test's disposition (transfers to the superseding goal / stands down to plain characterization / lapses) in the appropriate detail file; the sweep never deletes, skips, or weakens tests on its own
- the provenance lines are what keep the supersession sweep's grep reliable over time; closes the dangling-GAP-pin risk analyzed for superseded goals
- no project version bump: governance docs only
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
- the ::tcl::string::is definition harvests its class set at define time from the bad-class error message of a deliberately invalid probe (safe, side-effect-free) - accept/reject parity with the loading interpreter by construction: 8.6.13 = 21 classes (no dict - the previous static 9.0 list wrongly ACCEPTED string is dict there), 8.7a6 = 23 (+dict +unicode), 9.0.3 = 22 (unicode removed). Fallback to the 9.0 set if the message format ever changes
- hand-written man-page descriptions (kept verbatim, tstr-processed as before so the A_WARN highlights are unchanged) apply only to classes the runtime accepts; accepted-but-undescribed future classes get a generic label; static version notes added to dict (not in 8.6) and the new unicode entry (unreleased 8.7 only - removed in tcl 9). The per-class virtual docids (::tcl::string::is <class>) follow the harvested set automatically
- new tclcoreparity.test (4 tests, gated on have_tclcoredocs): choices equal the live-harvested set and every documented choice is really accepted; per-class docids exist for every class; error-vs-ok outcome agrees between real string is and parse_status across the 23-shape probe matrix (missing args, trailing flag-like str, option/class prefixes + ambiguity, unknown option/class, -failindex var consumption, per-version dict/unicode presence, divergent-classification shapes); version-note labels conditional on presence. Expectations derived from the LIVE interpreter, never version arithmetic - green on 9.0.3, 8.7a6 and (via a direct tcltest driver, since runtests infrastructure does not run under the plain 8.6 kit) 8.6.13
- full punk/args + punk/ns trees green (219 pass + 1 pre-existing skip) incl the have_tclcoredocs cmdhelp pins
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The prior commit message described these detail-file notes but the file edit had not landed (tool sequencing miss) - this commit adds them: dict-first assembly with table rendered from it, suggested per-checkout record shape, json via tcllib json::write as the G-017 parse target, markdown deliberately not offered as a machine form.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- G-016 goal+acceptance: -return option (default table unchanged; dict = canonical machine form with documented per-checkout records incl the VCS field; json = faithful rendering for out-of-process consumers, round-trips the dict data)
- G-017 acceptance: the documented agent invocation standardizes on -return json as the parse target with its record fields (replaces the vaguer "expected output shape")
- G-016 detail records the design decisions: dict-first assembly (table rendered from it), suggested record shape, json via tcllib json::write, markdown deliberately not offered as a machine form (json for parsing, table for humans)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- ConPTY (windows) + pty (unix) expect-like harness: spawn a built punkshell on a size-controlled pseudo-terminal, send keys incl control/arrow sequences, await patterns in the rendered ANSI byte stream with timeouts and forced teardown, full transcript capture
- the durable byte-accurate tier of the repl verification model recorded in goals/G-044 detail: pure layer (commandcomplete.test, done), console-seam unit tier (G-001 as enabling refactor), rendered tiers (G-020 screen capture near-term windows bridge; this goal headless + cross-platform)
- first verification targets = preserve-list behaviours: the in-proc {set x "{*}{"} continuation-hint sequence, raw-mode tab-marker rendering/deletion, up-arrow recall + edit of a multiline history entry
- detail file records open implementation questions (driving ConPTY from tcl: twapi surface vs helper exe; harness/shell synchronisation incl the inter-subshell beep-protocol idea vs prompt sentinels) and the G-059 WSL / G-060 QEMU-guest execution extensions
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- new commandcomplete.test (6 tests, green 9.0.3 + 8.7): punk::lib::system::incomplete pure-function characterization - the info-complete quoting quirk (a quoted word with unbalanced braces e.g set x "{*}{" is complete standalone but needs extra closers inside a proc body; the pending-opener stack { " { " shrinks per typed closer), single openers, tabs in open braces, escapes, and an incomplete<->info-complete parity property over a case battery
- goals/G-044 detail: the user-specified preserve-list any repl refactor must honour (info-complete parity + quirk, closing-prompt hints incl the accepted single-candidate limitation pinned-not-fixed, raw-mode colour staging in-progress vs submitted, literal tab acceptance with raw-mode marker edit smarts, dim space dots display-only never leaking into submitted strings/history, up/down navigation of MULTILINE editbuf history with recalled entries editable) + testability findings: class_editbuf is console-coupled at its core (add_chunk renders via overtype::renderline against live terminal metrics - cursor-position size probing, DECRQPSR tabstops) so items 3-6 are not unit-characterizable until a console seam exists - G-001 (pluggable console backends / ::opunk::Console test double) is the enabling refactor, not just a feature goal
- goals/G-020 detail: repl interactive-behaviour verification recorded as a driving use case (near-term windows harness: keystroke injection + capture) pending the durable pseudoconsole expect-alternative
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The 0.8.1 entry was written via a PowerShell interpolated string in which backtick-r and backtick-f in `runtime.cmd`/`fetch` were interpreted as CR/FF control characters. Text now reads correctly with intended markdown backticks.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- list -remote against an unreachable artifact server now warns and compares using the previously fetched sha1sums.txt instead of dying on an unhandled Invoke-WebRequest error (parity with the bash payload); no cached copy -> clear error + return
- the fetch path always fell through silently to a cached sha1sums.txt on download failure - it now announces "proceeding with cached copy" (behaviour unchanged, messaging explicit)
- fixed latent undefined-variable bug: the list -remote branch created the runtime folder with $container (only defined in the fetch branch) - now $archfolder
- bin/runtime.cmd regenerated (checkfile clean, roundtrip pin green 9 pass + 1 skip); verified live: unreachable PUNKBIN_URL -> cached-fallback table renders (tclsfe-x64 "Same version" against the punkbin pin), normal fetch path unchanged
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- new src/tests/testsupport/wslprobe.tcl (::punktest::wsl): memoized capability probe for the wsllinux constraint - default distro launches and unames as Linux, tools present (bash/mktemp/wslpath + sha1 tool), native tempdir file round trip; any failure -> skip with reason, so wsl.exe-present-but-unusable installs cannot false-positive. Staging helpers (staging_create/copy_in/run_in/cleanup) enforce the design: execution on the distro NATIVE filesystem only, shared /mnt used for one-way copy-in/out, the windows checkout never operated on from inside WSL (DrvFs slowness + cross-boundary stat differences that make git re-hash its index and fossil see phantom changes). Probe uses wsl -e invocations only (wsl --status/-l emit UTF-16)
- multishell.test: scriptwrap_multishell_exec_wsl_sh - the polyglot sh payload produces its marker under the distro bash from native staging (the direct isunix twin still skips on windows)
- new shell/testsuites/binscripts/runtimebash_wsl.test (8 tests): runtime.bash first-ever execution on real unix - multi-candidate run errors listing candidates, use/list/run round trip with argument passing, PUNK_ACTIVE_RUNTIME override, unknown/unselectable use errors, stale-active guidance, single-candidate fallback, offline list -remote (crafted cached sha1sums.txt + PUNKBIN_URL forced fetch failure), and the checkout-untouched guard (git status --porcelain identical before/after per acceptance)
- green on tcl 9.0.3 + 8.7 against Ubuntu-24.04/WSL2; suites skip cleanly when the probe fails; enablement/limitations in src/tests/AGENTS.md (known limitation: a present-but-HANGING wsl can stall the probe)
- GOALS.md G-059 flipped to achieved 2026-07-11; detail file records the outcome incl the UTF-16 discovery and the 512-byte label regression this work surfaced (caught by the guardrail suite as designed)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- bash/zsh payload gains list -remote parity with the powershell payload: local-vs-server sha1 comparison table (Same version / UPDATE AVAILABLE / not listed on server, plus remote-only entries), falling back to a cached sha1sums.txt with a warning when the server is unreachable (the powershell version has no cached fallback - candidate backport)
- both payloads: artifact server base url overridable via PUNKBIN_URL (mirrors/testing - also what makes the new feature testable offline)
- first real catch for the 512-byte label guard: the payload growth pushed the template's :exit_multishell target label across a boundary from its callsite (checkfile ERROR at wrap time); fixed with a documented byte-alignment spacer comment at the end of runtime.bash, and the resize-the-spacer workflow recorded in bin/AGENTS.md
- bin/runtime.cmd regenerated via scriptwrap (roundtrip pin green; multishell suite 9 pass + 1 skip on 9.0.3 and 8.7); runtime.bash syntax-checked under bash and zsh; windows list/use/run sanity re-verified
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- G-059: capability-probed WSL constraint for driving unix-side tests from Windows (multishell sh-payload execution, runtime.bash behaviour). Native-filesystem execution is a design constraint: per-test artifacts staged into a WSL-native tempdir with one-way copy-in/out, no repo checkout inside WSL for these cases, future full-suite mode via a separate native clone - the Windows checkout is never operated on via /mnt (DrvFs slowness + cross-boundary stat differences force git index re-hashing and fossil phantom changes; two VCS clients must not share a working tree). Acceptance includes verifying the Windows checkout git/fossil state is untouched by a WSL-gated run.
- G-060: QEMU guests as strictly external tooling behind a hypervisor-agnostic guest-driving contract (provision/stage/run/collect, push-based - same pattern as G-059; guests never share a working tree with the host). GPL-safe posture recorded: external-process invocation only, no QEMU binaries or derived code in punkshell or punkbin, guest OS images not redistributed - fetched/built per machine. First target FreeBSD x86_64; config home deferred to the buildsuites toml direction.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- run no longer launches the last runtime alphabetically: resolution is PUNK_ACTIVE_RUNTIME env override -> bin/runtime/<platform>/active.toml (constrained single-key toml, written by the new 'use <name>' subcommand, marked with * in list, covered by the existing bin/* VCS ignores) -> sole installed candidate -> error listing candidates. First fetch sets active only when none recorded; later fetches never steal it. Stale active (file removed) reported with reselect guidance.
- bash/zsh payload fetch reaches checksum parity with the powershell payload: fetches sha1sums.txt, locates the stored hash, skips when the local copy matches, downloads to .tmp and installs only on sha1 match; sha1 tool detection (sha1sum/shasum/sha1/openssl) with refusal of unverified downloads when none present; optional runtime-name argument added (fetch <name>)
- fixes: powershell "stored hash from sha1sums.txt" printed an undefined variable ($storedhash -> $stored_sha1); bash MSYS branch invalid assignment (interp = ...); candidate listings for run/list/use exclude .tmp leftovers and non-runtime files (a stray .txt could previously be selected by run)
- runtime scriptset sources relocated to src/scriptapps/bin (proper home alongside getzig.*); bin/runtime.cmd regenerated via scriptwrap from the new location - roundtrip test path updated, suite green on 9.0.3 (8 pass + unix-gated skip), runtime.bash syntax-checked under bash and zsh
- verified live on windows: multiple-runtimes-no-active errors with candidates (previously silently launched tksfe-twapi-x64), use/list/run against tclsfe-x64 and env override to tclsh902z, fetch no-steal + first-fetch auto-set, checksum-match no-download path
- docs: bin/AGENTS.md documents the fetch/use/run contract and updated generated-polyglot workflow paths; src/scriptapps/AGENTS.md scriptset-home wording updated
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- tclsfe-x64.exe is not a tk runtime and the tk-having sfe variants are wish-based (unsuitable), so punk91 moves off punk9win_for_tkruntime.vfs (which is intended for kits that already carry Tk) to punk9win.vfs - Tk loads as an extension per the punkbin runtime convention
- commented-out tksfe-twapi-x64 experiment recorded: the kit builds and can run tk apps (punkwish91 lib:tkhello) but the tk console does not display; noted todos - get the builtin tk console showing for exploration (unsuitable long-term: no ansi handling) and consider a textwidget-based virtual console capable of hosting the punk shell (relates to G-001 pluggable console backends)
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- new src/tests/modules/punk/mix/testsuites/scriptwrap/multishell.test (9 tests, green on tcl 9.0.3 + 8.7, unix exec case constraint-gated): scriptset wrap via the module-provided punk.multishell.cmd template (payloads + _wrap.toml fixture) - output produced, MULTISHELL magic line, payloads embedded verbatim, configured win32 nextshell present, LF-only endings, byte-identical re-wrap determinism; checkfile 512-byte label/boundary validation reports no label location errors for a fresh wrap AND for the committed bin/runtime.cmd; the runtime scriptset ROUND-TRIP pin - re-wrapping src/scriptapps runtime.ps1+runtime.bash+runtime_wrap.toml reproduces bin/runtime.cmd byte for byte (verified identical before pinning), so hand-edits to the output or unregenerated payload changes both fail; execution smoke - cmd.exe runs the polyglot and dispatches the powershell payload (windows), sh payload execution gated to unix (on windows the shell layer deliberately relaunches via the win32 nextshell)
- guidance strengthened so "fix bin/<name>.cmd" routes to sources: root AGENTS.md bin/ index entry now states the .cmd polyglots are scriptwrap-generated from src/scriptapps; bin/AGENTS.md gains a "Generated polyglot .cmd scripts - never edit in place" section with the 4-step fix workflow (edit payloads/toml, re-wrap with multishell -askme 0, heed checkfile ERRORs, commit source + regenerated output together); src/scriptapps/AGENTS.md documents the scriptset->bin/*.cmd relationship and regeneration command; tests index updated
- context: the polyglot technique is deliberately maintained despite fragility (user direction 2026-07-10) until hiding techniques close in the underlying languages - these pins are the guardrails
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com