Browse Source
All 15 make.tcl subcommands are punk::args-declared ((script)::punkboot + (script)::punkboot::<sub>, built from single-source summary/help/opt dicts with shared option fragments and explicit @form -synopsis). Bare make.tcl / -help, 'help ?subcommand?' and '<subcommand> -help' render tabled usage; invalid flags/subcommands raise punk::args usage errors (exit 1) with unambiguous prefix resolution; 'shell' is a declared passthrough. Prompt policy: new -confirm 0|1 (default 1) on every confirmation point (bootsupport minor-staleness gate, vfscommonupdate REPLACE, kit-type mismatch). Default prompts only on an interactive terminal and aborts fast with guidance on non-interactive stdin (::punkboot::lib::stdin_is_interactive; Tcl 8.6 lacks the -inputmode probe and is assumed interactive). -confirm 0 proceeds (staleness, REPLACE) or skips the mismatched kit. The piped-y agent workflow is retired; the old vfscommonupdate decline half-abort (printed done, exit 0) now exits 1. Degrade rule: punk::args/punk::ansi/textblock boot requires guarded; definition load caught with fallback to a self-contained scan (-k/-dirty-abort/-confirm supported) + plain punkboot_gethelp (availability NOTE factored into punkboot_availability_note, shared by both paths); rendering degrades independently of parsing (errorstyle minimal / plain help when the ANSI stack is unhealthy); PUNKBOOT_PLAIN=1 forces degraded mode. punk::args joins the bootstrap-tracked _runtime_deps staleness set (parsing contract only - the rendering stack degrades instead; contract docs updated in src/bootsupport/AGENTS.md + src/modules/AGENTS.md, workflow docs in src/AGENTS.md + src/tests/shell/AGENTS.md). Verified: usage/help/error paths, vfscommonupdate fail-fast and -confirm 0 runs with closed stdin, staleness flag route live (args 0.5.0->0.12.0 tripped the gate), degraded-mode help/check/info, full 'project -k -confirm 0' kit build. Dogfooding finding recorded in the goal file: punk::args 0.12.0 reports generic overflow where 0.5.0 reported choiceviolation for optional-choice mismatches (worked around with required leaders; candidate error-selection improvement). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.commaster
12 changed files with 676 additions and 221 deletions
@ -1,77 +0,0 @@ |
|||||||
# G-030 make.tcl dogfoods punk::args: tabled usage, declared subcommands, prompt-free flags |
|
||||||
|
|
||||||
Status: proposed |
|
||||||
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 <subcommand>` (or `<subcommand> -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). |
|
||||||
@ -0,0 +1,189 @@ |
|||||||
|
# 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 <subcommand>` (or `<subcommand> -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::<subcommand>` 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?` / `<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 <sub>`/`<sub> -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 </dev/null` -> fast abort exit 1 with -confirm guidance, |
||||||
|
no changes; `vfscommonupdate -confirm 0 </dev/null` -> 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 </dev/null` aborted fast exit 1; `modules -confirm 0` and |
||||||
|
`bootsupport -confirm 0` proceeded non-interactively and refreshed the |
||||||
|
snapshot (args 0.12.0 + punk 0.2.6, lib 0.4.3, ns 0.5.0, repl 0.5.1, |
||||||
|
tclcore moduledoc 0.3.4), after which the gate is silent. |
||||||
|
- Degraded mode: `PUNKBOOT_PLAIN=1` runs of bare help / `check` / `info |
||||||
|
-confirm 0` / unknown-command all work on the plain scan + gethelp |
||||||
|
(exit codes preserved). The guarded-require path was also exercised for real |
||||||
|
during development (a transient condition inversion ran the whole session on |
||||||
|
the fallback - plain help rendered, flags worked). |
||||||
|
- Full `project -k -confirm 0` regression build with stdin a pipe: completed, |
||||||
|
kits built/installed (see repo CHANGELOG 0.12.24 entry). |
||||||
|
- Layout make.tcl + bootsupport copies followed via the established punkcheck |
||||||
|
channel (`make.tcl bootsupport` run; not hand-synced) - G-027 remains the |
||||||
|
delivery route to derived projects. |
||||||
|
|
||||||
|
### Findings on punk::args (dogfooding yield) |
||||||
|
|
||||||
|
- Optional-arg choice-mismatch error-quality regression between 0.5.0 and |
||||||
|
0.12.0: a leader/value with `-optional 1` and restricted -choices that |
||||||
|
receives a non-matching word now falls through to a generic |
||||||
|
"Received more values than can be assigned" (toomanyarguments) instead of |
||||||
|
the pointed choiceviolation that 0.5.0 reported (verified: identical defs, |
||||||
|
only the loaded punk::args version differs; -choicegroups and @form presence |
||||||
|
are NOT factors). Worked around here by declaring `subcommand`/`subject` |
||||||
|
`-optional 0` (dispatch only parses when a word is present, so the empty |
||||||
|
case never reaches parse). Candidate punk::args improvement: single-form |
||||||
|
error selection should prefer a nearby choiceviolation over |
||||||
|
toomanyarguments when a rejected optional arg explains the overflow |
||||||
|
(adjacent to the rank_form_failures work; relates to proposed G-073). |
||||||
|
- `@cmd -name` is displayed in the COMMAND header but the auto-generated |
||||||
|
synopsis uses the definition id - script-level definitions with ids like |
||||||
|
`(script)::punkboot::<sub>` want an explicit `@form -synopsis` (adopted |
||||||
|
here; possible future punk::args nicety: fall back to @cmd -name for |
||||||
|
synopsis rendering). |
||||||
|
|
||||||
|
### 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 |
||||||
|
(G-072/G-073 territory) rather than patched mid-goal. |
||||||
|
- 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). |
||||||
@ -1,4 +1,4 @@ |
|||||||
[project] |
[project] |
||||||
name = "punkshell" |
name = "punkshell" |
||||||
version = "0.12.23" |
version = "0.12.24" |
||||||
license = "BSD-2-Clause" |
license = "BSD-2-Clause" |
||||||
|
|||||||
Loading…
Reference in new issue