Acceptance fully met: per-defect dispositions recorded, module tarjar-free,
suite green (punk91 7/7, tclsh90 7/7, punk86 6/7 with the 8.6 zipfs
limitation recorded per G-034), 0.1.6 re-vendored with suite passing,
tarjar-artifact dispositions user-confirmed (all five keeps, none deleted).
Index entry moved to GOALS-archive.md; sweep updates pending-tense mentions
in G-029/G-109/G-157 and pushes actionable findings to G-034 (redirect =
zero-dep load path; 8.6 vfs::zip dll-load measured) and G-110 (8.6
copy-to-temp datapoint). Detail-file rename to goals/archive/ follows as a
pure-move commit.
Claude-Session: https://claude.ai/code/session_0156PuejSCGjgeGb7jiABrDU
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
A third-party 8.6 kit under evaluation (Lean Undroidwish Construction Kit, 32-bit windows)
could not load its own bundled twapi 4.7.2 inside punkshell:
P% package require twapi
invalid command name "twapi::set_scriptdir"
("package ifneeded twapi 4.7.2" script)
twapi's pkgIndex.tcl defines 'namespace eval twapi { proc set_scriptdir ... }' when the
INDEX is sourced, and its ifneeded script calls that command at require time. The command
existed - as ::punk::libunknown::twapi::set_scriptdir. punk::libunknown 0.2.0 moved index
sourcing out of 'namespace eval ::' into source_pkgindex, a proc of the punk::libunknown
namespace, to stop each index's helper variables leaking into the global namespace and to
stop a user global named 'dir' being clobbered. That fixed the frame, but a proc body
executes in ITS OWN namespace, so an index's RELATIVE 'namespace eval foo' started
creating ::punk::libunknown::foo instead of ::foo. Stock tclPkgUnknown is a proc in ::,
so indexes have always had global resolution; the ifneeded script, evaluated later at
global scope, then looked for a command that was never there.
The body now runs via apply with :: as its namespace argument, which gives both
properties at once: a local frame (index helper variables still discarded, user 'dir'
still safe) and the global resolution context indexes are written against.
Not twapi-specific: any index that defines commands or namespaces at source time for its
own ifneeded scripts to use hits this, and the pattern is common in third-party indexes.
punkshell's own vendored twapi 5.0b1 happens to avoid it (self-contained 'apply' ifneeded
scripts), which is why the tree never surfaced it.
Verified on the LUCK 8.6.10 runtime end-to-end - 'package require twapi' at the punkshell
prompt now returns 4.7.2 with ::twapi::scriptdir correctly set - and pinned generically by
pkgindex_relative_namespace_is_global in the discovery suite, whose new fixture copies
twapi's pattern so no third-party kit is needed. The pin was proven to bite: driven
against the pre-fix body the same fixture fails with 'invalid command name' and leaves
::punk::libunknown::pklu_nsindex behind; against 0.2.3 it resolves and leaves nothing.
Full suite 1165 tests, 1144 passed, 1 failure - core/tcl exec-14.3, the documented
baseline.
Manual-version bump per src/modules/AGENTS.md: file renamed, Meta line, manpage_begin and
provide-block updated, version-history line appended. The rename sweep converted the two
goal Scope references (G-035, G-109) from the exact filename to the glob form
src/modules/punk/libunknown-*.tm that GOALS.md's own Scope-authoring guidance recommends,
so the reference stops drifting at every bump.
Also records in G-035 the mechanism behind its "avoid mixing .tm and pkgIndex.tcl
provision" folklore, which this investigation identified (non-contract Notes). Stock
::tcl:™️:UnknownHandler returns early when $satisfied is set and therefore never falls
through to ::tclPkgUnknown, so a require satisfied from a .tm suppresses the whole library
scan. Measured with a synthetic fixture on both 8.6.10 and 9.0.3: with mixpkg 1.0 as a .tm
and mixpkg 2.0 in an auto_path library under 'package prefer latest', stock returns 1.0
and reports only 1.0 from 'package versions', runs no index side effect and registers no
sibling package; the libunknown chain returns 2.0 and does all three. libunknown already
neutralises it - its handler still computes $satisfied but the early return is commented
out - and that unconditional fallthrough is exactly what the epoch cache pays for. The
folklore is therefore substantiated for stock Tcl with a named failure mode (silent
older-version selection) and neutralised under the punkshell chain, with stock behaviour
still reachable in any interp that has not run punk::libunknown::init.
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
- GOALS.md: "Goals-system: v2" front matter; canonical "Goals system versions"
section; Scope structure rule (elements separated by '; ' at top level,
commas only inside parens/braces); Child DOX Index note in root AGENTS.md
- goals_lint.tcl: new finding for top-level commas in Scope lines
(paren/brace depth-aware)
- goals_xref.tcl: repo-local configuration via goals/xref.conf (path roots,
stop words, file extensions, reference containers, module dirs,
bare_path_roots, prefix_anchors); defaults byte-identical to previous
behaviour (verified on this tree)
- goals/AGENTS.md: cross-repo goal references drop the G- prefix; xref.conf
documented in Verification
- Scope delimiter normalisation across GOALS.md, GOALS-archive.md and all
detail files, live and archived: 224 lines, top-level commas only;
conservation verified (goals_xref report byte-identical pre/post, diff
hunks are Scope lines only). Archived tier converted under explicit user
approval; sanctioned exception recorded in GOALS-archive.md.
Assisted-by: harness=opencode; primary-model=openrouter/moonshotai/kimi-k3; api-location=openrouter.ai
- platform records + 'help platforms' gain buildsuite
(supported|planned|candidate|none): whether OUR zig buildsuites produce
runtimes for a platform. Deliberately a separate axis from tiers -
punkbin-structured repos (or third-party equivalents) can host runtimes
built by any mechanism, so runtime-tier hosting coexists with
buildsuite=none (netbsd/dragonflybsd-class examples, per user review).
openbsd/netbsd/dragonflybsd records now carry the runtime tier.
Current values: win32-x86_64 supported (suite_tcl90), linux-x86_64
planned (G-105), linux-arm64/linux-arm/macosx/freebsd-* candidate,
rest none.
- G-109 notes record the binary-.tm platform reality the user's fat-tm
experience established (retracting this survey's earlier
'tm-are-cross-platform' shorthand): multi-platform fat .tm are the
wrong shape (oversized downloads; same-version shadowing leaves no
drop-in path), platform segregation must ride tcl:™️:path via
per-platform TM ROOTS selected by boot - and platform dirs cannot nest
inside an existing tm root (subdirs are namespace components), so those
roots must be sibling trees. Candidate manifest field: declared target
platform so libunknown can skip wrong-platform binary .tm.
Project 0.18.1.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Two goals split out of the modpod/TIP-741 characterization work, user-approved.
G-109 (libunknown manifest-declared multi-name discovery): a zip-based .tm
declares case-variant and sub-package require names in a manifest at a
well-known internal location, discovered by libunknown at scan time - with
real-disk scan performance preserved (worst-case parity with plain tclsh's
builtin tm handler; libunknown exists to fix slow-drive/large-tree scan cost).
Multi-name .tm are punkshell-only (documented); TIP 590 lowercase single-name
stays the plain-tclsh happy path; extensive-tests bar recorded.
G-110 (extraction cache investigation): whether per-run fresh-temp-dir copies
are necessary or replaceable by a single per-user content-addressed cache
(hash-keyed parent dir). Carries the 2026-07-21 sniff evidence: concurrent
sharing of one copy works; classic Win32 delete refused while mapped; POSIX-
semantics delete succeeds with mappings unharmed (a third option next to TIPs
741/709: unlink-after-load on modern NTFS). Fallback requirement recorded:
punkshell wants a win32/old-Windows fallback (industrial systems on isolated
VMs/old hardware) - capability-probe, classic-safe GC degradation. Precedents
(.NET single-file, critcl cache), sibling-dll sets, AV interplay, and the
cheapest-first implementation surfaces (modpod stub -> suite core patch ->
upstream) recorded.
G-066 note pointed at the new goals.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com