5.4 KiB
G-035 Characterise mixed .tm / pkgIndex.tcl provision of the same package
Status: proposed Scope: src/tests/modules/punk/libunknown/testsuites/ (characterization suite), src/modules/punk/libunknown-0.1.tm and src/modules/punk/packagepreference-999999.0a1.0.tm (as characterised, fixed only if outright bugs surface), src/modules/AGENTS.md + src/lib/AGENTS.md (resulting guidance) Goal: the behaviour when the same package is provided both as a .tm module and as a pkgIndex.tcl-based library - same or differing versions, under the standard package unknown, punk::libunknown and punk::packagepreference - is characterised by committed tests, and the currently informal working rule ("avoid mixing provision forms for one package - unexpected behaviour even with libunknown's improvements") is either substantiated with the specific failure modes named in AGENTS.md guidance, or retired if the characterisation shows the machinery now handles mixing predictably. Acceptance: a committed test suite (extending src/tests/modules/punk/libunknown/testsuites/) characterises at least: same name+version provided via .tm and via pkgIndex.tcl (which registration wins, and whether it is deterministic across scan-trigger orderings) under the standard scanner, under punk::libunknown, and with punk::packagepreference active; differing versions across the two forms (version selection integrity including package prefer latest, and whether the losing form's registration lingers); re-registration effects (package forget then re-require crossing forms); surprising-but-accepted behaviours are pinned with GAP/known-quirk comments (the fossilmove characterization pattern), outright bugs fixed or filed as goals; the resulting do/don't guidance lands in src/modules/AGENTS.md and src/lib/AGENTS.md naming the characterised failure modes (or explicitly lifting the avoid-mixing rule if unwarranted).
Context
Tcl packages arrive by two registration routes with different machinery:
- .tm modules:
tcl::tmpath scan duringpackage unknown; registration keyed on name-version from the filename; the same-version tie-break rules are now pinned by src/tests/modules/punk/libunknown/testsuites/shadowing/ (2026-07-07): tcl:™️:add prepends, head of tcl:™️:list wins exact-version ties, version beats order, punk::libunknown preserves all of it. - pkgIndex.tcl libraries: auto_path directory scan (tclPkgUnknown)
evaluating index scripts; different scan timing, different overwrite
semantics,
auto_pathordering rather than tm-list ordering.
When the SAME package is provided by both routes - same version or different
versions - the interaction is not well characterised. The user's standing
informal rule (recalled 2026-07-07): avoid mixing .tm and pkgIndex.tcl
provision for one package - unexpected behaviour was observed even after
punk::libunknown's improvements to the unknown-handler chain. That rule is
currently folklore: undocumented, unproven, and untested. Meanwhile the punk
ecosystem genuinely straddles both forms (src/modules .tm trees vs src/lib
pkgIndex libraries; kits carry both; punk::packagepreference overloads
package require on top of the unknown-handler chain), so accidental mixing
is a realistic hazard - and same-version-different-content drift (the
2026-07-06 textblock incident class) would interact with it unpredictably.
Questions the characterisation must answer
- Same name+version via .tm and via pkgIndex.tcl: which registration wins? Is it deterministic, or dependent on which scan ran first (tm scan vs auto_path scan can be triggered in either order by unrelated requires)?
- Different versions across forms: does version selection stay correct
(including under
package prefer latestand with alpha/dev versions)? Does the losing form'spackage ifneededregistration linger, and can it resurface viapackage forget+ re-require? - How do punk::libunknown and punk::packagepreference each change the
answers? (libunknown replaces/wraps the unknown chain; packagepreference
overloads
package requireitself - three layers that can each reorder scans.) - Are there differences across Tcl 8.6 and 9 (tm.tcl and tclPkgUnknown have evolved)?
Approach
- Extend the shadowing suite's child-interp probe pattern: scratch dirs providing the same test package as a .tm and as a pkgIndex.tcl library, all combinations of {same version, tm newer, pkgIndex newer} x {standard scanner, libunknown, packagepreference} x scan-trigger orderings.
- Pin observed behaviour; mark surprising-but-tolerable outcomes with GAP/known-quirk comments (the fossilmove characterization pattern) rather than encoding wishes; anything outright broken is fixed or filed.
- Convert the folklore into documentation: AGENTS.md guidance in src/modules and src/lib stating either the substantiated avoid-mixing rule with its named failure modes, or the conditions under which mixing is safe.
Notes
- Related: the shadowing pin-tests (same suite family - this goal's tests extend them), G-033 (visitor-mode path mixing makes cross-form collisions more reachable: a kit's internal libs vs a visited project's .tm trees), G-026/G-024 (same-version drift provenance), punk::packagepreference 0.1.1 (its moduledoc auto-load hook lives in exactly this machinery).
- Out of scope: redesigning the loading machinery. This goal is characterise-document-and-pin; behavioural changes only for outright bugs.