# G-030 make.tcl dogfoods punk::args: tabled usage, declared subcommands, prompt-free flags Status: achieved 2026-07-14 Scope: src/make.tcl (dispatch, help, prompts), src/bootsupport/AGENTS.md + src/modules/AGENTS.md (bootstrap-tracked staleness contract), src/modules/punk/args-999999.0a1.0.tm (only as consumed) Goal: make.tcl - the first surface a developer sees - parses its subcommands and options via punk::args and showcases the tabled usage output for help and argument errors, every interactive y/n prompt gains a declared flag equivalent so agents can drive make.tcl with arguments instead of piped input, punk::args joins the bootstrap-tracked staleness set, and the boot phase plus the environment-repair commands keep working with degraded plain help when the bootsupport punk::args (or the table-rendering stack) is stale or unavailable. Acceptance: `tclsh src/make.tcl` and `-help` render punk::args tabled usage listing every subcommand with a summary, and `make.tcl help ` (or ` -help`) shows that subcommand's definition; invalid arguments produce a punk::args usage error rather than ad-hoc messages; every y/n prompt has a documented flag equivalent (proven at least for vfscommonupdate and the project-build confirmations: a run with the flag completes non-interactively with stdin closed) and a non-interactive stdin without the flag fails fast with usage rather than hanging or half-aborting; punk::args is added to the bootstrap-tracked buildversion set with the doc contract updated (src/bootsupport/AGENTS.md, src/modules/AGENTS.md); with bootsupport punk::args unavailable or unloadable, make.tcl still boots and `check`, `bootsupport` and `modules` remain usable with plain-text fallback help (the guarded-require degrade rule); layout make.tcl copies follow via the established sync/G-027 channels (noted, not hand-synced). ## Context make.tcl is the first surface a developer meets in a punkshell-derived project, but its command handling predates the ecosystem's own tooling: a hand-built help text, a bare `known_commands` list, ad-hoc argument handling per subcommand, and interactive y/n prompts (`vfscommonupdate`'s REPLACE confirmation, the project-build confirmations, bootsupport staleness prompts). Eating our own dogfood - punk::args definitions per subcommand with the tabled usage rendering - both showcases the ecosystem where it is most visible and makes the parsing declarative. The prompts are the practical payoff: agent-driven builds currently pipe `y` into stdin (fragile, undiscoverable - observed 2026-07-07 while rebuilding tomlish.exe). With punk::args parsing, prompt-free operation is just another declared option per subcommand, and non-interactive stdin without the flag can fail fast with usage instead of hanging on a read or half-aborting. Precedents already in-tree: src/tests/runtests.tcl parses via punk::args ((script)::runtests definition), and the tomlish cmdline app presents tabled usage as its first surface. ## Approach - One PUNKARGS definition per subcommand (@cmd -summary/-help + opts), plus a top-level definition enumerating subcommands - replacing punkboot_gethelp and the hand-maintained help strings. `make.tcl`, `make.tcl -help`, and per-subcommand help all render through punk::args::usage. - Prompt policy: interactive stdin -> prompt as today (default); flag supplied (e.g. -confirm 0 / -y, naming decision recorded here) -> proceed without prompting; non-interactive stdin without the flag -> usage error, fast. The bootsupport staleness prompt keeps its abort/prompt/proceed classification but gains the same flag route. - **Degradation is a hard requirement** (the 2026-07-06/07 incidents are the cautionary tale: a stale bundled fileutil disabled the very make.tcl step needed to fix it). The boot phase stays self-contained; punk::args is guarded-lazily required post-boot (the punkboot::utils pattern documented in src/bootsupport/AGENTS.md); when unavailable, dispatch and the repair commands (check, bootsupport, modules) keep working with plain-text fallback help. Note the tabled rendering also pulls punk::ansi/textblock/punk::char - exactly the modules whose same-version staleness broke shellfilter this week - so rendering must degrade independently of parsing (punk::args plain output when the ANSI stack is unhealthy). - Staleness tracking: punk::args joins the bootstrap-tracked buildversion set (currently punkcheck, punk::repo, punk::mix, punk::tdl) with the same bump-at-least-minor-on-call-site-API-change discipline; whether the rendering stack is also tracked or left to degrade is an implementation decision to record here (initial lean: track punk::args only - it is the parsing contract; rendering degrades). - Layout copies of make.tcl follow through the existing punkcheck-tracked sync (custom/_project) and the G-012/G-027 channels for the rest - noted in completion reports, never hand-synced. ## Alternatives considered - Ad-hoc -y flags bolted onto the current hand parsing - rejected: solves the agent problem but leaves the first-surface help un-showcased and the parsing divergent from the ecosystem's own conventions. - Requiring punk::args at boot (no fallback) - rejected: make.tcl must be able to repair the very bootsupport snapshot it loads punk::args from. ## Notes - Related: G-015 (agents driving punk tooling non-interactively), G-024 (mapvfs toml errors deserve the same declared-argument quality), G-025 (the version-report subcommand should be born punk::args-defined), G-027 (pull updates deliver the improved make.tcl to derived projects). - Observation parked here from the same session: runtests/make.tcl-adjacent tooling that returns result dicts should document their key shape (see the runx -tcl exitcode note in G-015's detail). - Archived-goal references in this file: G-015 achieved 2026-07-07 (goals/archive/G-015-script-subcommand-piped-stdin.md). ## Progress 2026-07-14: implemented whole and verified; punkproject 0.12.24. ### What shipped (src/make.tcl) - Declarative dispatch: punk::args definitions `(script)::punkboot` (top level: subcommand leader with -choicegroups/-choicelabels subtables) and `(script)::punkboot::` for all 15 subcommands, built in `::punkboot::argdoc` from single-source dicts (SUMMARIES/HELPTEXTS/SUBOPTS/ OPT_SYNOPSES) plus shared option fragments (OPT_CONFIRM/OPT_DIRTYABORT/ OPT_FORCEKILL) composed via multi-part `punk::args::define`. Explicit `@form -synopsis` per definition so usage shows the real invocation (`make.tcl modules ?-dirty-abort? ?-confirm 0|1?`) rather than the internal id. - `make.tcl` / `-help` / `help ?subcommand?` / ` -help` all render punk::args tabled usage (the missing/broken bootsupport-package NOTE was factored into `punkboot_availability_note` and is appended to both the tabled and the plain-fallback help). Invalid flags and unknown subcommands raise punk::args usage errors (exit 1); unambiguous subcommand prefixes resolve (`make.tcl vfsc...`). - `shell` is a declared passthrough: its definition documents that trailing args go to the repl unparsed. - Prompt policy - **naming decision: `-confirm 0|1` (boolean, default 1)**, declared on every subcommand that can hit a confirmation point: - `-confirm 1` (default): prompt when stdin is an interactive terminal; when stdin is NOT interactive, abort fast at the confirmation point with guidance instead of reading stdin (no more piped `y`, no half-aborts - the old vfscommonupdate decline path printed "done" and exited 0; it now exits 1 with "-aborted-"). - `-confirm 0`: never prompt; documented per-site resolutions: staleness minor-bump gate -> proceed, vfscommonupdate REPLACE -> proceed, kit source/target type mismatch -> skip that kit (only an interactive 'y' can force building a mismatched kit). All three `gets stdin` confirmation sites reworked; interactivity probe is `::punkboot::lib::stdin_is_interactive` (8.7+/9 `-inputmode` on terminal channels only; **Tcl 8.6 caveat**: no probe exists, stdin is assumed interactive there - piped 8.6 runs should pass -confirm explicitly; documented in the option help and bootsupport AGENTS.md). - Staleness tracking: punk::args joined `_runtime_deps` (`punk/args-buildversion.txt`). **Decision recorded: track punk::args only** - it is the parsing contract; the tabled-rendering stack (punk::ansi, textblock) stays untracked and degrades instead. - Degrade rule implemented at three levels: (1) boot requires for punk::args/punk::ansi/textblock are guarded (stderr note, no abort); (2) definition build is caught - any failure falls back to a self-contained scan (rewritten from the old hand parser; handles -k/-dirty-abort/-confirm and help) plus plain-text punkboot_gethelp; (3) rendering degrades independently of parsing (errorstyle minimal when the ANSI stack is unhealthy; usage render failure falls back to plain help). `PUNKBOOT_PLAIN=1` forces the degraded mode (troubleshooting/test hook). - Flag plumbing: `-k` (project/vfs/bin), `-dirty-abort` (the nine build/promotion commands) and `-confirm` now flow from parsed opts into `::punkboot::opt_forcekill/opt_dirty_abort/opt_confirm`; the old `lsearch $::argv` sites read those variables instead. ### Verification (all under tclsh 9.0.2, from repo root) - Bare/`-help`/`help `/` -help`: tabled usage with grouped subcommand/summary subtables; `help` with a bad subject and an unknown subcommand both raise choiceviolation usage errors (exit 1); `modules -bogus` raises invalidoption (exit 1). - `vfscommonupdate fast abort exit 1 with -confirm guidance, no changes; `vfscommonupdate -confirm 0 completed exit 0, idempotent (no git churn). - Staleness flag route proven live: adding punk::args to _runtime_deps immediately tripped the minor gate (bootsupport 0.5.0 vs source 0.12.0): `info ` want an explicit `@form -synopsis` (adopted here; possible future punk::args nicety: fall back to @cmd -name for synopsis rendering). ### Follow-up 2026-07-14 (same day, post-achievement): G-045 mechanisms adopted User review spotted @cmd -help Description blocks rendering with the first line indented less than continuations - the constructed-definition indent leak G-045 characterized (head-form multi-line values interpolated via [list] carry make.tcl's source indentation as data; the composed @cmd record line starts at column 0 so no whole-block base trim applies, and the renderer's max-4 undent leaves the residue). Notably the braced shared option fragments did NOT leak - as literal block-shaped parts they received file-style normalization, which is why argument help columns were aligned while @cmd help was not. Fix per G-045's preferred style (increment 4): HELPTEXTS and the inline shell/help/toplevel help values converted to block form (first value line whitespace-only) with a bare @normalize in every constructed definition (head-form values, e.g the option fragments, are contractually untouched). Added a capability probe inside the guarded block - punk::args::get_spec on representative ids forces resolution at define time, so a stale punk::args that accepts the raw text but cannot resolve a mechanism (e.g pre-@normalize snapshots) degrades to the plain fallback immediately instead of erroring at first parse. Verified flush Description rendering for toplevel/subcommand/ shell/help usage; dispatch, degraded mode and error paths re-verified. AGENTS infrastructure: src/modules/AGENTS.md "Documentation And Comments" gained a "punk::args definition authoring ergonomics" subsection pointing future documentation work at the G-045 mechanisms (@normalize + block form for constructed defs, -unindentedfields, -& continuation, container quoting rules, the explicit @form -synopsis lesson and the optional-choice error-quality workaround from this goal); src/AGENTS.md's make.tcl bullet cross-references it and names ::punkboot::argdoc as an in-tree constructed-def exemplar. (G-045 achieved 2026-07-12 - goals/archive/G-045-punkargs-authoring-ergonomics.md) ### Deferred / out of scope - The kit-type-mismatch confirmation cannot be triggered without a mismatched runtime/target configuration - its -confirm handling is code-reviewed, not runtime-proven (the prompt sites share the same policy helper). - punk::args error-selection improvement above left to punk::args goals rather than patched mid-goal - proposed 2026-07-14 as G-082 (goals/G-082-punkargs-error-selection.md); the -optional 0 workaround sites here and in src/modules/AGENTS.md are to be revisited when it ships. - Old `echo y | make.tcl vfscommonupdate` agent workflow is retired; docs updated (src/AGENTS.md, src/tests/shell/AGENTS.md, src/bootsupport/AGENTS.md, src/modules/AGENTS.md).