You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

11 KiB

G-169 App-owned launch-subcommand documentation consumed by the launcher

Status: achieved 2026-08-05 Scope: src/lib/app-punkscript/punkscript.tcl (carries its subcommand's punk::args definition via inert registration); src/modules/punk/args/moduledoc/punkexe-999999.0a1.0.tm (single-definer handover); src/vfs/_config/punkboot_core.tcl (built-in help resolution via app-owned ids, *_main.tcl declaration surface documented, + synced copies via established channels); src/tests/shell/testsuites/punkexe/launcherhelp.test Goal: A subcommand's punk::args definition can live in its handling app and the launcher consumes it - proven on app-punkscript owning (script)::punkexe::script (inert PUNKARGS registration, no load-time side effects, lazily resolved at help/error time) with the moduledoc entry handed over (one definer per id); the ownership rule is recorded (docs live with the owning code - app-owned for app-handled subcommands, moduledoc for core-owned surfaces like tclsh); and the existing *_main.tcl project-subcommand declaration surface (summary/package/argsid/parse) is documented as the official authoring mechanism it already is. Acceptance: app-punkscript carries the script definition and 'help script' renders it on a baked kit via lazy resolution (guarded package require + docpackages/argsid - no eager load at boot; help-path load cost measured and recorded); the punkexe moduledoc no longer defines the id (no duplicate-definition warnings; single definer verified); degraded/plain help path intact; the *_main.tcl declaration keys are documented where kit authors look (location decided in the work: core header contract + a durable doc) including the parse=1 gate; launcherhelp.test passes with a new app-owned-resolution pin.

Context

2026-08-05 discussion: the actual '-e' parsing lives in app-punkscript while its documentation lives in the punkexe moduledoc - co-location kills that drift class. Nothing structural prevents launcher consumption of app-owned docs: the argsid+package indirection and parse=1 gate already exist for project subcommands (punkboot_core.tcl:1779-1791, 2168-2192), and punk::args 0.12.7's docpackages association loads a documenting package lazily on first usage query. The moduledoc pattern remains right where implementation is external or core-owned (tclcore precedent: separation + parity pins).

Notes

  • Coordination with G-168 (achieved 2026-08-05 - goals/archive/G-168-selection-sound-launch-definitions.md): G-168 landed first, so THIS goal is the one that lands second and edits the definitions at their then-current home (never two definers) - the re-homed script definition carries G-168's fencing shape (file form scriptfile -regexprefail {^-e$} + ./-e message, oneliner '-e' as a required solo flag) and any tclsh re-home carries the {^-}/{^[^-]} fences plus the stdin form's -overlapallowed {scriptfile} sanction; the punkexemodel.test / formcheck.test pins guard the handover.
  • Related: G-075 (proposed) - sibling documentation-reachability surface.
  • Related: G-170 (proposed) - back-pointer added at activation 2026-08-05 (activation-freshness survey; G-170 already points here): its help-depth arms render whatever home this goal gives the definitions, and its formhint un-suppression edits them at that home.
  • Related: G-042/G-043 (proposed) - adjacent declaration-composition patterns; deliberate non-overlap (launch surface, not repl subshells).
  • Overlap survey 2026-08-05: app-punkscript intersects no live goals; the punkboot_core.tcl matches are the G-168 survey's set (G-089 nearest, others incidental).
  • 2026-08-05 pre-test pins (new args-tier docpackages.test, green tclsh90+tcl87): registration in ::punk::args::register::NAMESPACES is inert - the next update_definitions call id-SCANS the source without evaluating definitions, id_exists never triggers loading, and real_id/usage lazily load the registered source on the first query naming the documented namespace, including tag-prefixed script-level families (the (script)::punkexe::* path this goal rides). Duplicate ids resolve last-loaded-wins accompanied only by a stderr undefine notice - the engine carries a recorded detect-duplicates todo (punk::args update_definitions scan loop) - so the single-definer handover must withdraw the moduledoc entry in the same change-set that lands app ownership rather than rely on any warning surface (docpackages_duplicate_definers_last_registered_wins).

Progress

Achieved 2026-08-05 in one session (user-directed activation and implementation same day; app-punkscript 1.2 + app-punkscript-docs 1.2, punkexe moduledoc 0.8.0, punkboot moduledoc 0.3.1, punkboot core 0.6.0).

Mechanism landed:

  • src/lib/app-punkscript/punkscript.tcl carries the (script)::punkexe::script definition (the G-168 selection-sound shape moved VERBATIM - value strings byte-identical, so renders match the pre-handover moduledoc) in ::app::punkscript::argdoc, with an idempotent docs section: a plain namespace-variable set plus a membership-guarded lappend to ::punk::args::register::NAMESPACES - no package requires, no punk::args dependency, no definition evaluation (evaluation stays lazy on the first query naming the id, per the docpackages pre-test pins).
  • Docs-only loading: pkgIndex.tcl provides package app-punkscript-docs 1.2 from the SAME file via an execution gate (::app::punkscript::docs_only set around the source; punkscript.tcl returns after the docs section when the gate is up, and 'package provide app-punkscript' moves below the gate) - requiring the docs NEVER runs a script, and a later 'package require app-punkscript' re-sources with the gate down so the app runs normally (probed: docs-then-app in one process, APPRAN both orders, '-e'-alone usage error intact, no duplicate registrations).
  • Launcher consumption: punkboot_core 0.6.0 adds launcher_builtin_docpackages (dict: script -> app-punkscript-docs); launcher_show_help's built-in arm does a guarded 'package require' of the mapped docs package before the usage query - help-path only, never on boot/dispatch (the ready-probe and dispatch paths are untouched). Copies synced: project-0.1 layout + modpod-template layout byte-identical to the master (the template copy also re-synced by make.tcl modules' punkcheck step).
  • Single-definer handover: the punkexe moduledoc (0.8.0) no longer defines the id - a pointer comment stands in its place and the Overview records the ownership rule (docs live with the owning code: app-owned for app-handled subcommands, moduledoc for core-owned surfaces like tclsh/buildinfo/help and the top-level dispatch).

Decision - durable-doc location for the *_main.tcl declaration keys (the acceptance's 'location decided in the work'): the registration definition id (script)::punkboot::registration in the punkboot moduledoc IS the durable doc - it already documented all four project_subcommand_info keys (summary/argsid/package/parse incl the parse=1 gate) and its 'package' key text now also documents the app-owned docs-package pattern (0.3.1, with the gate shape pointed at src/lib/app-punkscript/pkgIndex.tcl). The core header contract (punkboot_core.tcl G-031 registration-model comment) now names that id explicitly and records the app-owned option; worked examples remain in the project_main.tcl template (verified present: summary/argsid example block). Kit authors reach the durable doc from the core header, the punkexe moduledoc Overview, and the template.

Help-path load cost (measured 2026-08-05, tclsh90, src tree): the app-ownership marginal cost is the guarded docs require - 3.5 ms (inert: namespace-variable set + registration lappend + gate return). The first 'help script' render measured 396 ms total, dominated by the one-time punk::ansi/textblock render-stack load + definition evaluation that occurs IDENTICALLY wherever the definition lives - so app ownership adds only the ~3.5 ms require to the help path, and nothing to boot/dispatch.

Verification evidence:

  • launcherhelp.test 25/25: the 24 existing pins unchanged plus the new launcherhelp_appowned_script_docs pin - the fake-main harness (G-031 shape, no bake) run THROUGH the baked kit's tclsh subcommand in src package mode, where the source tree serves the nested boot with version precedence: the src moduledoc defines no script id, so the successful tabular render carrying the G-168-era scriptfile help text (line-break-safe markers) proves app-owned lazy resolution; stderr asserted free of duplicate-definition ('clearing existing data') notices. Post-bake the kit-internal stack carries the same set and the render is identical. (Harness lesson recorded: manual tm/auto_path prepends in a fake main are WIPED by the nested boot's path configuration - the src package mode is the correct lever, and it resolves the project from the executable's own location.)
  • Full modules/punk/args subtree 337 passed / 3 pre-existing skips / 0 failed on BOTH tclsh90 and tclsh87 - the G-168 punkexemodel.test / formcheck.test pins now load the script id via app-punkscript-docs (src/lib derived from the test file location) and guard the handover exactly as the G-168 coordination note intended.
  • Src-level probes: moduledoc 0.8.0 loaded first -> id_exists 0 for the script id; app-punkscript-docs require -> registered, app NOT run, usage renders, forms {file oneliner}, G-168 selections/verdicts/formcheck all intact through the app-owned definition; no undefine notices.
  • App parity probes (the restructure must not break the runner): file/'-e' one-liner/'-e'-alone-usage-error/docs-then-app sequences all behave identically through the new file (src paths; template-provider warnings are minimal-path environment noise, absent in kit contexts).
  • shell/testsuites/punkexe subtree: launcherhelp 25/25 and the other launcher-adjacent suites green; the 10 failures in maketclbakelist.test / maketcllibfetch.test are PRE-EXISTING (reproduced identically at HEAD with this change-set stashed; the G-139 libfetch-test reading is a recorded pending user decision from the 2026-08-05 follow-on sweep).
  • Minted punkexe-0.8.0.tm + punkboot-0.3.1.tm via make.tcl modules.
  • Degraded/plain path intact: the PUNKBOOT_PLAIN launcherhelp pin passes unchanged, and mixed promotion states degrade gracefully by construction (old core never requires the docs package and the old moduledoc still defines the id; new core + old lib falls to the guarded-require failure and the plain summary line).

Follow-ons

Follow-on: the next vfscommonupdate/bake promotion carries the coherent set together - src/lib/app-punkscript (pkgIndex + punkscript.tcl 1.2), punkboot core 0.6.0 and punkexe moduledoc 0.8.0 (plus punkboot moduledoc 0.3.1) - after which the baked kit serves 'help script' from the app-owned definition in internal mode; mixed intermediate states degrade gracefully as recorded in Progress => landed 2026-08-06 (the same promotion + bake event that landed G-170's coherent-set line, by then carrying app-punkscript 1.3 / core 0.7.0 / punkexe moduledoc 0.9.0; the deployed kit's 'help script' now renders the app-owned definition in internal mode) Follow-on: extend app ownership to the other app-handled built-ins (shell/punk via app-punkshell, shellspy via app-shellspy) whose moduledoc entries are summary-level passthrough contracts today - same docs-package pattern, launcher_builtin_docpackages gains their entries => open