Browse Source
G-031: split the monolithic vfs main (punk_main.tcl: 1190-line apply block - ~1060 lines boot machinery, ~100 lines dispatch tail) into a layout-owned boot core (shipped via _vfscommon.vfs, sourced by vfs-relative path since no package paths exist at boot; pull-updatable per the G-027 ownership model) and a thin project-owned main declaring app subcommands at commented customization points. Fork cost measured: tomlish_main.tcl carries ~20 custom lines on a stale 500-line 2025 vintage copy; project_main.tcl (901 lines) same at template vintage - boot improvements never reach derived projects. Acceptance: behaviour parity across dispatch cases and vfs types, project subcommand added by editing only the thin main (tomlish the proving ground), boot core versioned/reportable (G-025). G-032: the default dispatch defines subcommands via punk::args - tabled -help enumerating built-in and project-registered subcommands, parsed options with tabled usage errors (script/G-015 or version-report/G-025 as first candidates), G-030 degradation rules (guarded require; parsing falls back to switch semantics, help to a plain list; rendering degrades independently). Parked decision: the silent unknown-arg->script reclassification should stop swallowing typos (candidate rule: reclassify only when the argument names an existing file). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.commaster
3 changed files with 154 additions and 0 deletions
@ -0,0 +1,84 @@
|
||||
# G-031 Componentized kit boot: thin project-owned main + shared layout-owned boot core |
||||
|
||||
Status: proposed |
||||
Scope: src/vfs/_config/ (punk_main.tcl, project_main.tcl restructure), src/vfs/_vfscommon.vfs (boot core delivery), src/project_layouts/ (thin-main skeleton, via established sync channels) |
||||
Acceptance: as in root GOALS.md index (canonical). |
||||
|
||||
## Context |
||||
|
||||
src/vfs/_config/punk_main.tcl is a 1190-line single `apply` block mixing two |
||||
very different concerns: |
||||
|
||||
- **Boot machinery** (~1060 lines): vfs mount detection (zipfs/metakit/cookfs), |
||||
starkit handling, package-mode token parsing (dev/os/src/internal), module |
||||
and auto_path setup, libunknown, src-mode #modpod registration. |
||||
- **Application dispatch** (~100 lines at the tail): subcommand extraction and |
||||
the tclsh/shellspy/punk/shell/script cases. |
||||
|
||||
Every kit's main.tcl is already a fauxlink to one such file per project |
||||
(`main.tcl#..+_config+<name>_main.tcl#@punk::boot,merge_over`), and derived |
||||
projects fork the whole file to customize the tail. Measured cost (2026-07-07): |
||||
|
||||
- tomlish_main.tcl: 547 lines, of which the genuinely tomlish-specific dispatch |
||||
tail is ~20 lines - the rest is a 2025-vintage copy of the boot boilerplate, |
||||
already 632 diff-lines adrift from current punk_main in the first 450 lines. |
||||
Boot improvements since (src mode, modpod registration) never reached it. |
||||
- project_main.tcl (layout template): 901 lines, same story at template vintage. |
||||
|
||||
A project developer wanting one custom subcommand must wade through - and then |
||||
permanently own - a thousand lines of boot code. |
||||
|
||||
## Approach |
||||
|
||||
- Split into: |
||||
- **Boot core** (layout-owned): the boot machinery plus the default dispatch, |
||||
shipped inside the kit via _vfscommon.vfs (every kit already merges it) and |
||||
`source`d from the thin main by vfs-relative path. Layout-owned per the |
||||
G-027 ownership classification -> pull-updatable in derived projects, so |
||||
boot fixes propagate instead of dying in forks. |
||||
- **Thin project main** (project-owned skeleton): declares project |
||||
subcommands and launch defaults at clearly commented customization points, |
||||
then hands over to the boot core. This is the file a project developer |
||||
reads and edits. |
||||
- Boot-phase constraint: the boot core cannot be a package (no package paths |
||||
exist yet) - it is sourced by vfs-relative path from the thin main. The |
||||
default dispatch portion runs post-boot and may be package-based if that |
||||
proves cleaner; record the split point here when decided. |
||||
- Registration model: the thin main declares subcommands (name -> handler |
||||
package/command, plus optional punk::args definition id for G-032) before |
||||
invoking the default dispatch; built-ins (tclsh/shellspy/punk/shell/script, |
||||
and G-025's version-report) come from the boot core, project additions merge |
||||
in. Default-subcommand and no-args behaviour are declared, not hardcoded |
||||
(a shell-like default remains the punkshell behaviour; a tool-like default |
||||
such as tomlish's -help injection becomes a declared choice). |
||||
- Boot core carries its own version/identity so a kit can report the boot |
||||
vintage it embeds (G-025 stamping is the natural vehicle). |
||||
- Layout skeletons follow through the established sync channels (custom/ |
||||
_project sync step now; G-012/G-027 for the rest) - noted in completion |
||||
reports, never hand-synced. |
||||
|
||||
## Alternatives considered |
||||
|
||||
- Leaving the monolith and documenting "edit the tail" - rejected: the fork |
||||
cost is proven (tomlish, project_main both adrift); documentation does not |
||||
stop vintage divergence, pull-updatable payload does. |
||||
- Making the entire main (incl. dispatch tail) layout-owned and pushing project |
||||
customization into data/config only - rejected for now: subcommand handlers |
||||
are code; a thin project-owned code file with a clear contract is simpler |
||||
than inventing a config schema for arbitrary launch behaviour. Revisit if |
||||
the thin mains themselves start accreting boilerplate. |
||||
|
||||
## Notes |
||||
|
||||
- Sequencing with G-015: the script-subcommand work touches the same dispatch |
||||
tail. Either order works, but whichever lands second must preserve the |
||||
other's behaviour; if G-015 proceeds first on the monolith, its dispatch |
||||
logic moves into the boot core here. |
||||
- Related: G-027 (ownership + pull channel this is designed for), G-025 |
||||
(boot-core vintage reporting), G-032 (punk::args-defined dispatch built on |
||||
the registration model), G-012 (layout payload hygiene), G-018 (plain tclsh |
||||
kits deliberately carry NO punk boot layer - out of scope here). |
||||
- The tomlish silent-exe incident (2026-07-07, tomlish 1.1.10 fix) is a |
||||
reminder that launch-path contracts are easy to break invisibly - behaviour |
||||
parity in the acceptance means exercising each dispatch case, not just |
||||
booting. |
||||
@ -0,0 +1,58 @@
|
||||
# G-032 Kit launcher dogfoods punk::args: tabled help and parsed subcommands |
||||
|
||||
Status: proposed |
||||
Scope: src/vfs/_config/ (default dispatch), src/lib/app-punkshell and sibling app packages as touched |
||||
Acceptance: as in root GOALS.md index (canonical). |
||||
|
||||
## Context |
||||
|
||||
The kit launcher is, alongside make.tcl (G-030), the first surface a user or |
||||
agent meets - and it should showcase the ecosystem's own argument tooling the |
||||
way the tomlish cmdline app already does (tabled usage on -help/no-args). |
||||
Today the dispatch in punk_main.tcl is a bare `switch` on the first argument |
||||
with no help output at all: an unknown first argument silently becomes a |
||||
`script` attempt, and there is no way to discover the subcommands |
||||
(tclsh/shellspy/punk/shell/script) or the package-mode tokens without reading |
||||
the source. |
||||
|
||||
Builds on G-031's registration model: the thin project main declares |
||||
subcommands with optional punk::args definition ids; the shared dispatch |
||||
renders and parses from those declarations - so a project's subcommands appear |
||||
in `-help` by registration alone. |
||||
|
||||
## Approach |
||||
|
||||
- punk::args definitions for the top-level dispatch (subcommand enumeration |
||||
with @cmd summaries, package-mode leader documented) and per-subcommand |
||||
options. `<punkexe> -help`, `<punkexe> help <subcommand>`, and |
||||
`<subcommand> -help` all render tabled usage. |
||||
- Parse errors on declared subcommands produce punk::args usage errors |
||||
(tabled), not silent fallthrough. The unknown-first-arg -> script |
||||
reclassification survives only where it does not swallow obvious mistakes - |
||||
the exact rule is an implementation decision to record here (candidates: |
||||
reclassify only when the argument names an existing file, else usage error). |
||||
- **Degradation per the G-030 rules**: the kit normally bundles punk::args and |
||||
the rendering stack, but src/dev modes and damaged kits must not brick the |
||||
launcher - guarded lazy require; parsing degrades to the current switch |
||||
semantics and help to a plain subcommand list when punk::args (or the ANSI |
||||
stack, independently) is unavailable. |
||||
- Exit-code and output-cleanliness expectations follow G-015: help to stdout |
||||
exit 0; usage errors to stderr nonzero; no launcher chatter on the app's |
||||
channels. |
||||
|
||||
## Alternatives considered |
||||
|
||||
- Help text maintained by hand in the dispatch - rejected: the same |
||||
hand-maintained-help drift make.tcl has (G-030), and project-registered |
||||
subcommands would need dispatch edits to become discoverable. |
||||
- Requiring punk::args at boot - rejected: same repair-path reasoning as G-030 |
||||
and the punkboot::utils guarded-require rule. |
||||
|
||||
## Notes |
||||
|
||||
- Related: G-031 (registration model this renders from - soft prerequisite; |
||||
could proceed on the monolith but shouldn't), G-030 (make.tcl counterpart |
||||
and the shared degradation doctrine), G-015 (script subcommand options are a |
||||
natural first parsed subcommand; exit-code semantics), G-025 (version-report |
||||
subcommand born punk::args-defined), G-013 (the debugrepl activation review |
||||
mentions proper-command conversions that would slot into the same pattern). |
||||
Loading…
Reference in new issue