Browse Source
User-directed activation and implementation in one arc (proposed -> active at
the user's word with the activation-freshness survey recorded, -> achieved +
archived on acceptance). The declarations follow the 2026-08-05 pre-test
findings exactly - no engine change was needed.
(script)::punkexe::script: the file form fences scriptfile with
-regexprefail {^-e$} and a -regexprefailmsg naming the ./-e reachability
(word-1 '-e' is the ONLY fenced word - every other dash-led word remains a
file path, matching app-punkscript's word-1 test); the oneliner form declares
the '-e' word as a real element - a required -type none flag (the
auto_exec::hash -r/-d shape) ahead of the existing required script value, so
a bare {-e} reports noformmatch with the oneliner form verdicting
viable-incomplete via the G-164 re-probe (the app's "-e requires a script
argument" reality) and the file form invalid.
(script)::punkexe::tclsh: scriptfile gains -regexprefail {^-} (stock
tclMain.c: a dash-led word in script-file position means NO script) and the
stdin form's first word is a declared fenced element 'firstarg'
(-regexprefail {^[^-]} - a non-dash first word IS a script file; not an
option, stays in ::argv). Selection now matches stock classification on
every line except the recorded LIMIT: the complete
'-encoding <name> <scriptfile>' shape word-shape-matches both forms (a
dash-led encoding NAME included - the engine consumes dash-led option
values, matching stock's unconstrained argv[2]) and stock's arity-priority
rule is not expressible per-word - the pair is declared
@form -overlapallowed {scriptfile} on the stdin form (formcheck sanction)
while parse raises multipleformmatches naming both forms per the G-041
no-silent-preference contract. Dispatch never parses these ids, so the
ambiguity surfaces only in declaration-driven consumers (help dry-runs,
completion), where the two-form diagnosis is the honest answer.
Decisions recorded in the archived detail file: dispatch parse-gating NOT
adopted (punkboot_core.tcl untouched; script/tclsh stay declared passthrough
surfaces - boot-path parse cost, stock-parity conflict with the LIMIT, app
error surfaces already honest and pinned, and the declaration-driven
consumers get parse-trueness without gating; no latency delta applicable);
the <punkexe> @form -synopsis overrides KEPT (neither the raw (script) id
nor @cmd -name is an invocable name; the stdin override keeps the
user-facing '?arg ...?' line over the model's firstarg/arg split) - the
G-144 archived follow-on flipped to declined accordingly (make.tcl's own
override retirement had already landed in the 0.41.0 arc). A real-vs-model
probe matrix (G-055 method; bin/punk91 dispatch + app-punkscript real side)
is recorded in the detail file - model matches real classification on every
line except the two complete-'-encoding' rows (the sanctioned LIMIT).
Tests: new args/punkexemodel.test (6 - script/tclsh selection matrices
against the real ids with the real-side oracle referenced, the bare-'-e'
viable-incomplete verdict, the ./-e fence message, -encoding fall-through
statuses (scriptfile invalid vs incomplete, stdin selected), the LIMIT pins
naming {scriptfile stdin} for both complete shapes); formcheck.test punkexe
GAPs flipped deliberately per the acceptance:
formcheck_punkexe_script_forms_discriminated (zero findings),
formcheck_punkexe_tclsh_forms_sanctioned (unsanctioned empty + the stdin
form's -overlapallowed pinned via get_spec; the positional-chain witness
derivation misses option-dependent overlaps - formcheck's documented miss
direction - so the sanction also future-proofs improved derivation),
formcheck_punkexe_primary_inputs_selection_sound (dispatch-true forms for
every primary line; empty input still selects file/stdin uniquely). Full
modules/punk/args subtree 337 passed / 3 pre-existing skips / 0 failed on
BOTH native tclsh90 (9.0.3) and tclsh87;
src/tests/shell/testsuites/punkexe/launcherhelp.test 24/24 unchanged per
acceptance (its 'help script'/'help tclsh' pins glob only @cmd -name
strings - row additions verified safe post-bake as well). Minted
modules/punk/args/moduledoc/punkexe-0.7.0.tm via make.tcl modules;
kits/bootsupport carry 0.6.1 until the next promotion/bake cycle.
Goals: G-168 entry moved to GOALS-archive.md, detail file to goals/archive/
with the probe matrix, both decisions and verification evidence; one open
Follow-on (arity-priority expressibility would flip the LIMIT pins; the
broader selection-soundness sweep stays recorded in G-150's archive).
Activation survey Related: line added (G-169 back-pointer). Reference sweep:
G-169 coordination note updated (G-168 landed first - the re-homed
definitions carry this fencing shape), G-170 dependency marked satisfied
(its dry-run arm inherits the recorded LIMIT). src/tests/modules AGENTS.md
punk/args bullet extended. goals_lint clean (82 active / 88 archived).
Claude-Session: https://claude.ai/code/session_0156PuejSCGjgeGb7jiABrDU
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
12 changed files with 487 additions and 116 deletions
@ -1,73 +0,0 @@
|
||||
# G-168 Selection-sound launch definitions: script/tclsh forms match dispatch reality |
||||
|
||||
Status: proposed |
||||
Scope: src/modules/punk/args/moduledoc/punkexe-999999.0a1.0.tm ((script)::punkexe::script + ::tclsh form discrimination); src/lib/app-punkscript/punkscript.tcl (behaviour oracle, error-surface decision); src/vfs/_config/punkboot_core.tcl (only if the dispatch-parse decision adopts gating, + synced copies via established channels); src/tests/modules/punk/args/testsuites/args/ (new model-parity suite); src/tests/shell/testsuites/punkexe/launcherhelp.test (as touched) |
||||
Goal: The two multi-form launch-subcommand definitions are parse-discriminable with existing punk::args vocabulary - form auto-selection agrees with actual dispatch/app behaviour: the file form excludes exactly '-e' (-regexprefail {^-e$}, message naming ./-e), the oneliner form declares the '-e' word as a real element, and tclsh's scriptfile-vs-stdin split (leading-dash words stay argv; incomplete -encoding falls through, stock-style) is expressed through candidacy fall-through - so parse_status verdicts, noformmatch diagnoses and downstream consumers (help depth, completion) see the truth instead of a display-only model. |
||||
Acceptance: against the script definition, parse/parse_status select oneliner for {-e <code> ...}, select file for {<word> ...} where <word> ne -e, and {-e} alone reports noformmatch with oneliner viable-incomplete (the app's "-e requires a script argument" reality); against tclsh, {file args} selects scriptfile, a leading-dash word selects stdin, and an incomplete -encoding tail falls through to stdin (stock parity); formcheck reports no unsanctioned findings; a real-vs-model probe matrix (G-055 method) against actual dispatch/app-punkscript behaviour is recorded in this file; whether DISPATCH adopts parse-gating for script/tclsh (tabled pointed errors replacing app-punkscript's plain ones) is decided and recorded with rationale and, if adopted, a measured script-launch latency delta; the new behaviour is pinned in the args testsuite and launcherhelp.test passes unchanged (or with deliberately updated pins named here). |
||||
|
||||
## Context |
||||
|
||||
2026-08-05 discussion (formhint arc): 'punk9-dev -e' / 'script -e' error - word-1 |
||||
'-e' is RESERVED by behaviour (app-punkscript punkscript.tcl:78-88; a file so |
||||
named needs ./-e), but the file form declares scriptfile as any string - the |
||||
definition is display-honest, parse-dishonest, and the forms cleanly double-match. |
||||
The blocker assumed earlier (G-072 negation) is not needed: -regexprefail is |
||||
honoured during form matching (verified in the G-143 make.tcl arc, achieved - |
||||
goals/archive/G-143-maketcl-multiform-help.md; the G-150 selection-sound hash |
||||
declaration is the dash-led-form-word precedent). |
||||
|
||||
## Notes |
||||
|
||||
- Enacts the punkexe portion of the G-150 follow-on "sweep other flat multi-form |
||||
definitions for selection-soundness" (goals/archive/G-150-cmdhelp-form-narrowing.md); |
||||
that follow-on stays open - the sweep is broader than these two definitions. |
||||
- The G-144 follow-on (punkexe moduledoc @form -synopsis override set drops once |
||||
auto-synopsis serves - goals/archive/G-144-punkargs-synopsis-name-fallback.md, |
||||
disposition flipped to this goal) is decided in this work: keep the <punkexe> |
||||
placeholder overrides or adopt @cmd -name auto lines - recorded either way. |
||||
- Related: G-089 (proposed) - script's lib:name resolution text is consumed scope. |
||||
- Related: G-055 (proposed) - the real-vs-model probe method borrowed here. |
||||
- Related: G-072 (proposed) - deliberate non-dependency: negation NOT required. |
||||
- Related: G-170 (proposed) - consumer: its dry-run arm requires this goal's |
||||
parse-trueness. |
||||
- Overlap survey 2026-08-05: goals_xref paths over the Scope - G-089 (named |
||||
above) is the only substantive live intersection on punkboot_core.tcl; |
||||
moduledoc-sibling matches (G-055 G-068 G-072 G-083 G-084 G-166 G-167) are |
||||
parser/spec mechanisms or other moduledocs, no availability interaction. |
||||
- 2026-08-05 pre-test findings (engine primitives probed on tclsh 9.0.3 and |
||||
pinned green on tclsh90+tcl87: forms.test fencing/fall-through group, |
||||
formviability_dangling_optional_option_conservative, |
||||
errsel_dangling_option_trailing_value_overflow, formcheck_GAP_punkexe_*): |
||||
- A -regexprefail rejection on an OPTIONAL value slot is fatal to that form's |
||||
candidacy - the word does NOT re-land on a later permissive slot (contrast |
||||
optional-CHOICE rejection, errsel_rejected_word_lands_later) - so per-slot |
||||
fencing fences whole forms (forms_fence_optional_slot_no_reland). |
||||
- Unknown options, dangling option words and option-satisfied-but-values-unmet |
||||
tails each fail only their form: auto-selection falls through to a sibling |
||||
as a SUCCESSFUL parse, and an option VALUE's -regexprefail participates in |
||||
candidacy too - the stock "-encoding recognised only before a non-dash word" |
||||
primitive is expressible (forms_fallthrough_* pins). |
||||
- LIMIT for the tclsh model: a complete '-encoding <name> <file>' line |
||||
wordwise-matches both a fenced scriptfile form and any dash-tolerant stdin |
||||
form; per-word constraints cannot express stock's "scriptfile wins when |
||||
complete" priority, so the no-silent-preference contract (G-041, achieved - |
||||
goals/archive/G-041-punkargs-form-matching.md) raises |
||||
multipleformmatches (forms_fenced_pair_residual_overlap). The tclsh |
||||
declaration must design around this class - form restructuring, an |
||||
-overlapallowed sanction (display-only; parse still raises), or the |
||||
dispatch-parse decision this goal already tables. |
||||
- The {-e}-alone viable-incomplete acceptance rides the re-probe of G-164 |
||||
(achieved 2026-08-04 - goals/archive/G-164-viability-alternative-allocation.md), |
||||
which re-seats only words naming missing REQUIRED options: declare '-e' as a |
||||
required -type none flag plus a separate required script value (the |
||||
auto_exec::hash -r/-d shape), NOT as a value-taking option - a stolen word |
||||
naming a value-taking or OPTIONAL option keeps verdict invalid |
||||
(formviability_reprobe_value_taking_option_conservative and the new |
||||
formviability_dangling_optional_option_conservative twin). |
||||
- Before-state pinned as GAP: both punkexe multi-form definitions carry |
||||
unsanctioned structural formcheck findings and every primary launch line |
||||
double-matches ({-e X} / {file args} / {file} / {-encoding enc file}); |
||||
empty input selects file/stdin uniquely (formcheck_GAP_punkexe_script_forms_overlap, |
||||
formcheck_GAP_punkexe_tclsh_forms_overlap, |
||||
formcheck_GAP_punkexe_primary_inputs_double_match - flipped deliberately |
||||
by this goal per its Acceptance). |
||||
@ -0,0 +1,210 @@
|
||||
# G-168 Selection-sound launch definitions: script/tclsh forms match dispatch reality |
||||
|
||||
Status: achieved 2026-08-05 |
||||
Scope: src/modules/punk/args/moduledoc/punkexe-999999.0a1.0.tm ((script)::punkexe::script + ::tclsh form discrimination); src/lib/app-punkscript/punkscript.tcl (behaviour oracle, error-surface decision); src/vfs/_config/punkboot_core.tcl (only if the dispatch-parse decision adopts gating, + synced copies via established channels); src/tests/modules/punk/args/testsuites/args/ (new model-parity suite); src/tests/shell/testsuites/punkexe/launcherhelp.test (as touched) |
||||
Goal: The two multi-form launch-subcommand definitions are parse-discriminable with existing punk::args vocabulary - form auto-selection agrees with actual dispatch/app behaviour: the file form excludes exactly '-e' (-regexprefail {^-e$}, message naming ./-e), the oneliner form declares the '-e' word as a real element, and tclsh's scriptfile-vs-stdin split (leading-dash words stay argv; incomplete -encoding falls through, stock-style) is expressed through candidacy fall-through - so parse_status verdicts, noformmatch diagnoses and downstream consumers (help depth, completion) see the truth instead of a display-only model. |
||||
Acceptance: against the script definition, parse/parse_status select oneliner for {-e <code> ...}, select file for {<word> ...} where <word> ne -e, and {-e} alone reports noformmatch with oneliner viable-incomplete (the app's "-e requires a script argument" reality); against tclsh, {file args} selects scriptfile, a leading-dash word selects stdin, and an incomplete -encoding tail falls through to stdin (stock parity); formcheck reports no unsanctioned findings; a real-vs-model probe matrix (G-055 method) against actual dispatch/app-punkscript behaviour is recorded in this file; whether DISPATCH adopts parse-gating for script/tclsh (tabled pointed errors replacing app-punkscript's plain ones) is decided and recorded with rationale and, if adopted, a measured script-launch latency delta; the new behaviour is pinned in the args testsuite and launcherhelp.test passes unchanged (or with deliberately updated pins named here). |
||||
|
||||
## Context |
||||
|
||||
2026-08-05 discussion (formhint arc): 'punk9-dev -e' / 'script -e' error - word-1 |
||||
'-e' is RESERVED by behaviour (app-punkscript punkscript.tcl:78-88; a file so |
||||
named needs ./-e), but the file form declares scriptfile as any string - the |
||||
definition is display-honest, parse-dishonest, and the forms cleanly double-match. |
||||
The blocker assumed earlier (G-072 negation) is not needed: -regexprefail is |
||||
honoured during form matching (verified in the G-143 make.tcl arc, achieved - |
||||
goals/archive/G-143-maketcl-multiform-help.md; the G-150 selection-sound hash |
||||
declaration is the dash-led-form-word precedent). |
||||
|
||||
## Notes |
||||
|
||||
- Enacts the punkexe portion of the G-150 follow-on "sweep other flat multi-form |
||||
definitions for selection-soundness" (goals/archive/G-150-cmdhelp-form-narrowing.md); |
||||
that follow-on stays open - the sweep is broader than these two definitions. |
||||
- The G-144 follow-on (punkexe moduledoc @form -synopsis override set drops once |
||||
auto-synopsis serves - goals/archive/G-144-punkargs-synopsis-name-fallback.md, |
||||
disposition flipped to this goal) is decided in this work: keep the <punkexe> |
||||
placeholder overrides or adopt @cmd -name auto lines - recorded either way. |
||||
- Related: G-089 (proposed) - script's lib:name resolution text is consumed scope. |
||||
- Related: G-055 (proposed) - the real-vs-model probe method borrowed here. |
||||
- Related: G-072 (proposed) - deliberate non-dependency: negation NOT required. |
||||
- Related: G-170 (proposed) - consumer: its dry-run arm requires this goal's |
||||
parse-trueness. |
||||
- Overlap survey 2026-08-05: goals_xref paths over the Scope - G-089 (named |
||||
above) is the only substantive live intersection on punkboot_core.tcl; |
||||
moduledoc-sibling matches (G-055 G-068 G-072 G-083 G-084 G-166 G-167) are |
||||
parser/spec mechanisms or other moduledocs, no availability interaction. |
||||
- Activation survey 2026-08-05 (goals_xref score G-168, activation-freshness |
||||
rule): Related: G-169 (proposed) - back-pointer added at activation (G-169 |
||||
already points here): the definitions this goal makes selection-sound are |
||||
the same ones G-169 re-homes under app ownership; G-169's handover carries |
||||
whatever fencing shape this goal lands. Other new hits (G-069 dev-lint) |
||||
are path-coincidental (same moduledoc/test directories), no mechanism |
||||
interaction. |
||||
- 2026-08-05 pre-test findings (engine primitives probed on tclsh 9.0.3 and |
||||
pinned green on tclsh90+tcl87: forms.test fencing/fall-through group, |
||||
formviability_dangling_optional_option_conservative, |
||||
errsel_dangling_option_trailing_value_overflow, formcheck_GAP_punkexe_*): |
||||
- A -regexprefail rejection on an OPTIONAL value slot is fatal to that form's |
||||
candidacy - the word does NOT re-land on a later permissive slot (contrast |
||||
optional-CHOICE rejection, errsel_rejected_word_lands_later) - so per-slot |
||||
fencing fences whole forms (forms_fence_optional_slot_no_reland). |
||||
- Unknown options, dangling option words and option-satisfied-but-values-unmet |
||||
tails each fail only their form: auto-selection falls through to a sibling |
||||
as a SUCCESSFUL parse, and an option VALUE's -regexprefail participates in |
||||
candidacy too - the stock "-encoding recognised only before a non-dash word" |
||||
primitive is expressible (forms_fallthrough_* pins). |
||||
- LIMIT for the tclsh model: a complete '-encoding <name> <file>' line |
||||
wordwise-matches both a fenced scriptfile form and any dash-tolerant stdin |
||||
form; per-word constraints cannot express stock's "scriptfile wins when |
||||
complete" priority, so the no-silent-preference contract (G-041, achieved - |
||||
goals/archive/G-041-punkargs-form-matching.md) raises |
||||
multipleformmatches (forms_fenced_pair_residual_overlap). The tclsh |
||||
declaration must design around this class - form restructuring, an |
||||
-overlapallowed sanction (display-only; parse still raises), or the |
||||
dispatch-parse decision this goal already tables. |
||||
- The {-e}-alone viable-incomplete acceptance rides the re-probe of G-164 |
||||
(achieved 2026-08-04 - goals/archive/G-164-viability-alternative-allocation.md), |
||||
which re-seats only words naming missing REQUIRED options: declare '-e' as a |
||||
required -type none flag plus a separate required script value (the |
||||
auto_exec::hash -r/-d shape), NOT as a value-taking option - a stolen word |
||||
naming a value-taking or OPTIONAL option keeps verdict invalid |
||||
(formviability_reprobe_value_taking_option_conservative and the new |
||||
formviability_dangling_optional_option_conservative twin). |
||||
- Before-state pinned as GAP: both punkexe multi-form definitions carry |
||||
unsanctioned structural formcheck findings and every primary launch line |
||||
double-matches ({-e X} / {file args} / {file} / {-encoding enc file}); |
||||
empty input selects file/stdin uniquely (formcheck_GAP_punkexe_script_forms_overlap, |
||||
formcheck_GAP_punkexe_tclsh_forms_overlap, |
||||
formcheck_GAP_punkexe_primary_inputs_double_match - flipped deliberately |
||||
by this goal per its Acceptance). |
||||
|
||||
## Progress |
||||
|
||||
Achieved 2026-08-05 in one session (user-directed activation and implementation |
||||
same day; punk::args::moduledoc::punkexe 0.7.0). The declarations follow the |
||||
pre-test findings exactly - no engine change was needed. |
||||
|
||||
Mechanism landed ((script)::punkexe::script): |
||||
|
||||
- file form: scriptfile gains -regexprefail {^-e$} with -regexprefailmsg naming |
||||
the ./-e reachability ("reserved for the -e one-liner form; a file literally |
||||
named -e is reachable as ./-e") - word-1 '-e' is the ONLY fenced word; every |
||||
other dash-led word remains a file path, matching app-punkscript's word-1 |
||||
test. |
||||
- oneliner form: the '-e' word is now a real declared element - a required |
||||
-type none flag (@opts -e -optional 0, the auto_exec::hash -r/-d shape) |
||||
ahead of the existing required script value. A bare {-e} therefore reports |
||||
noformmatch with the oneliner form verdicting viable-incomplete (the G-164 |
||||
re-probe re-seats the reservation-stolen '-e' as the flag it names and finds |
||||
pure exhaustion) and the file form invalid - the app's "-e requires a script |
||||
argument" reality. |
||||
|
||||
Mechanism landed ((script)::punkexe::tclsh): |
||||
|
||||
- scriptfile form: scriptfile gains -regexprefail {^-} (stock tclMain.c: a |
||||
dash-led word in script-file position means NO script) with a stock-parity |
||||
message. |
||||
- stdin form: the first word is now a declared fenced element 'firstarg' |
||||
(-regexprefail {^[^-]} - a NON-dash first word IS a script file), remaining |
||||
args unchanged; its -help states it is not an option and stays in ::argv. |
||||
- The complete '-encoding <name> <scriptfile>' shape is the recorded LIMIT: |
||||
it word-shape-matches both forms (a dash-led encoding NAME included - the |
||||
engine consumes a dash-led option value, matching stock's unconstrained |
||||
argv[2]) and stock's arity-priority rule (scriptfile wins when the triple is |
||||
complete) is not expressible per-word - the pair is declared |
||||
@form -overlapallowed {scriptfile} on the stdin form (formcheck sanction) |
||||
and parse raises multipleformmatches naming both forms per the G-041 |
||||
no-silent-preference contract. Dispatch never parses these ids, so the |
||||
ambiguity surfaces only in declaration-driven consumers (help dry-runs, |
||||
completion), where the two-form diagnosis is the honest answer. |
||||
|
||||
Real-vs-model probe matrix (G-055 method; real side = bin/punk91 dispatch + |
||||
app-punkscript probes 2026-08-05, model side = parse/parse_status against the |
||||
0.7.0 definitions on tclsh90 - punkexemodel.test pins the model column): |
||||
|
||||
script words | real behaviour | model selection |
||||
---------------------|-----------------------------------------------|---------------- |
||||
(empty) | piped-stdin script mode | file |
||||
-e 'puts one' | oneliner runs, exit 0 | oneliner |
||||
-e 'expr 1+1' | oneliner, result echo '2' | oneliner |
||||
-e code x -y | oneliner, argv0=-e argv={x -y} | oneliner |
||||
-e | usage error "-e requires a script argument" 1 | noformmatch, oneliner viable-incomplete |
||||
nosuchfile.tcl | file class: not-found, exit 1 | file |
||||
-x | file class: not-found naming '-x', exit 1 | file |
||||
hi.tcl a b | file runs, argv={a b} | file |
||||
./-e | file named -e runs | file |
||||
-e foo.tcl | oneliner evaluates the TEXT 'foo.tcl' | oneliner |
||||
|
||||
tclsh words | real behaviour | model selection |
||||
---------------------|-----------------------------------------------|---------------- |
||||
(empty) | stdin (repl/piped) | stdin |
||||
hi.tcl a b | scriptfile runs, argv={a b} | scriptfile |
||||
-foo bar | stdin, ARGV=-foo bar | stdin |
||||
-encoding | stdin, ARGV=-encoding | stdin (scriptfile invalid) |
||||
-encoding utf-8 | stdin, ARGV=-encoding utf-8 | stdin (scriptfile incomplete) |
||||
-encoding utf-8 hi.tcl a | scriptfile with encoding, argv={a} | multipleformmatches (the LIMIT, sanctioned) |
||||
-encoding utf-8 -bar | stdin, ARGV=all three words | stdin |
||||
-encoding -foo hi.tcl| scriptfile attempt (unknown encoding error) | multipleformmatches (same LIMIT class) |
||||
|
||||
Divergence summary: model matches real classification on every line except |
||||
the two complete-'-encoding'-shape rows, where the model deliberately raises |
||||
the sanctioned multipleformmatches instead of silently preferring scriptfile |
||||
(rationale above; the G-041 contract). |
||||
|
||||
Decision - dispatch parse-gating: NOT adopted (punkboot_core.tcl untouched; |
||||
no latency delta applicable). Rationale: (a) script/tclsh are declared |
||||
PASSTHROUGH surfaces (G-032 decision) - their arguments belong to the launched |
||||
script/app, and a dispatch parse would add punk::args resolve+parse cost to |
||||
every script/tclsh launch on the boot path; (b) stock parity: the complete |
||||
-encoding line is stock-valid and dispatch-classified scriptfile, but the |
||||
model deliberately raises multipleformmatches on it - a parse gate would turn |
||||
a working stock line into a launch error, or need a priority override that |
||||
reintroduces the silent preference G-041 removed; (c) app-punkscript's error |
||||
surfaces are already honest and pinned (usage errors exit 1, no launch |
||||
chatter - G-077, launcherhelp.test); (d) the consumers that want the parse |
||||
(G-170 help-depth dry-run, G-044 completion) get parse-trueness without |
||||
gating. |
||||
|
||||
Decision - G-144 follow-on (@form -synopsis overrides): KEPT. Neither the raw |
||||
(script) id nor @cmd -name ('punkexe tclsh') is an invocable name; the |
||||
<punkexe> placeholder matches the file's prose convention ("'<punkexe>' below |
||||
stands for any punk kit executable"), and the stdin form's override keeps the |
||||
user-facing '?arg ...?' line over the model's firstarg/arg fencing split. The |
||||
G-144 archived follow-on line's disposition flipped accordingly (make.tcl's |
||||
own override retirement had already landed in the 0.41.0 arc). |
||||
|
||||
Verification evidence: |
||||
|
||||
- New suite src/tests/modules/punk/args/testsuites/args/punkexemodel.test |
||||
(6 tests): both selection matrices, the {-e} viable-incomplete verdict |
||||
(ok 0 / status incomplete / form oneliner / formstatus {oneliner incomplete |
||||
file invalid}), the ./-e fence message, the -encoding fall-through statuses |
||||
(scriptfile invalid vs incomplete, stdin selected), and the LIMIT pins |
||||
(multipleformmatches naming {scriptfile stdin} for both complete shapes). |
||||
- formcheck.test GAP flips: formcheck_punkexe_script_forms_discriminated |
||||
(zero findings), formcheck_punkexe_tclsh_forms_sanctioned (unsanctioned |
||||
empty + the stdin form's -overlapallowed {scriptfile} pinned via get_spec), |
||||
formcheck_punkexe_primary_inputs_selection_sound (dispatch-true forms for |
||||
every primary line; the sanctioned LIMIT raise named). |
||||
- Full modules/punk/args subtree 337 passed / 3 pre-existing skips / 0 failed |
||||
on BOTH native tclsh90 (Tcl 9.0.3) and tclsh87. |
||||
- src/tests/shell/testsuites/punkexe/launcherhelp.test 24/24 unchanged (the |
||||
acceptance gate; its 'help script'/'help tclsh' pins glob only @cmd -name |
||||
strings and row additions do not disturb them - verified for post-bake |
||||
robustness too). |
||||
- Minted modules/punk/args/moduledoc/punkexe-0.7.0.tm via make.tcl modules; |
||||
kits/bootsupport carry 0.6.1 until the next promotion/bake cycle (the |
||||
moduledoc rides the established channels; no synced-copy obligations - the |
||||
punkboot_core.tcl copies were not touched). |
||||
- G-151 composition smoke: punk::args::parse_report over an accepted |
||||
'{-e {puts hi} x -y}' line renders the landing rows (-e received, script |
||||
received, arg received x2) - the G-170 dry-run arm's ingredients compose. |
||||
|
||||
## Follow-ons |
||||
|
||||
Follow-on: stock's arity-priority for the complete '-encoding <name> <scriptfile>' shape becomes expressible if punk::args grows a form-priority or arity-conditional fencing mechanism - the -overlapallowed sanction and the punkexemodel/formcheck LIMIT pins flip deliberately then => open |
||||
|
||||
(The broader flat-multi-form selection-soundness sweep stays recorded as the |
||||
open follow-on in goals/archive/G-150-cmdhelp-form-narrowing.md - the punkexe |
||||
portion is enacted by this goal, per the Notes; no duplicate line here.) |
||||
@ -0,0 +1,165 @@
|
||||
package require tcltest |
||||
|
||||
package require punk::args |
||||
package require punk::lib |
||||
|
||||
#G-168 model parity: the (script)::punkexe::script and ::tclsh multi-form launch |
||||
#definitions are selection-sound - form auto-selection (parse) and parse_status |
||||
#verdicts agree with actual dispatch/app behaviour. The real-side oracle is the |
||||
#probe matrix recorded in goals/archive/G-168-selection-sound-launch-definitions.md |
||||
#(bin/punk91 dispatch + app-punkscript probes, 2026-08-05): |
||||
# script: word-1 exactly '-e' selects the one-liner ('-e' alone is the usage |
||||
# error "-e requires a script argument", exit 1); ANY other first word - |
||||
# dash-led included - is a file path ('script -x' fails file-not-found naming |
||||
# '-x'; a file literally named -e runs as './-e'); no words = the piped-stdin |
||||
# script form. |
||||
# tclsh (stock tclMain.c triple-check in punkboot_core.tcl): '-encoding name |
||||
# file' recognised only when the THIRD word does not begin with '-'; otherwise |
||||
# a non-dash first word is the script file; otherwise (leading dash, incomplete |
||||
# -encoding tails included) NO script - all words stay in ::argv, input from |
||||
# stdin. |
||||
#Model mechanisms (punkexe moduledoc 0.7.0): file form fences scriptfile with |
||||
#-regexprefail {^-e$}; oneliner declares '-e' as a required -type none flag |
||||
#(so a bare {-e} verdicts viable-incomplete via the G-164 re-probe); tclsh |
||||
#scriptfile fenced {^-}; stdin's first word fenced {^[^-]}; the complete |
||||
#'-encoding <name> <scriptfile>' shape is the recorded LIMIT - it matches both |
||||
#tclsh forms and raises multipleformmatches (G-041 no-silent-preference), |
||||
#sanctioned @form -overlapallowed (formcheck gate pinned in formcheck.test). |
||||
|
||||
namespace eval ::testspace { |
||||
namespace import ::tcltest::* |
||||
variable common { |
||||
set result "" |
||||
} |
||||
|
||||
testConstraint have_punkexedocs [expr {![catch {package require punk::args::moduledoc::punkexe}]}] |
||||
if {[testConstraint have_punkexedocs]} { |
||||
#trigger the docpackages load of the (script)::punkexe id family |
||||
catch {punk::args::real_id (script)::punkexe::script} |
||||
} |
||||
|
||||
#added 2026-08-05 (agent, G-168) |
||||
test punkexemodel_script_selection_matrix {script subcommand: '-e <code> ...' selects oneliner, any other first word (dash-led included) selects file, empty selects file (the stdin-script reading), '-e' alone raises noformmatch}\ |
||||
-constraints have_punkexedocs\ |
||||
-setup $common -body { |
||||
foreach words { |
||||
{} |
||||
{-e {puts hi}} |
||||
{-e {puts hi} a -b} |
||||
{foo.tcl bar} |
||||
{foo.tcl} |
||||
{-x} |
||||
{./-e} |
||||
{-e foo.tcl} |
||||
} { |
||||
lappend result [dict get [punk::args::parse $words withid (script)::punkexe::script] form] |
||||
} |
||||
if {[catch {punk::args::parse {-e} -errorstyle minimal withid (script)::punkexe::script} errmsg erroropts]} { |
||||
lappend result [lindex [lindex [dict get $erroropts -errorcode] 2] 0] |
||||
} else { |
||||
lappend result UNEXPECTED-parsed |
||||
} |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list file oneliner oneliner file file file file oneliner noformmatch] |
||||
|
||||
#added 2026-08-05 (agent, G-168) - the acceptance's '-e requires a script |
||||
#argument' reality: the oneliner form verdicts viable-incomplete (the G-164 |
||||
#re-probe re-seats the reservation-stolen '-e' as the required solo flag it |
||||
#names and finds pure exhaustion); the file form is invalid (scriptfile |
||||
#fenced against exactly '-e') |
||||
test punkexemodel_script_e_alone_viable_incomplete {a bare '-e' reports noformmatch with the oneliner form viable-incomplete and the file form invalid}\ |
||||
-constraints have_punkexedocs\ |
||||
-setup $common -body { |
||||
set ps [punk::args::parse_status {-e} withid (script)::punkexe::script] |
||||
lappend result [dict get $ps ok] [dict get $ps status] [dict get $ps form] |
||||
lappend result [dict get $ps formstatus oneliner status] |
||||
lappend result [dict get $ps formstatus file status] |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list 0 incomplete oneliner incomplete invalid] |
||||
|
||||
#added 2026-08-05 (agent, G-168) - the file form's fence message names the |
||||
#./-e reachability (the Goal's 'message naming ./-e' clause) |
||||
test punkexemodel_script_fence_message_names_dote {forcing the file form on '-e' surfaces the -regexprefailmsg naming ./-e}\ |
||||
-constraints have_punkexedocs\ |
||||
-setup $common -body { |
||||
catch {punk::args::parse {-e} -errorstyle minimal -form file withid (script)::punkexe::script} m |
||||
lappend result [string match "*reachable as ./-e*" $m] |
||||
lappend result [string match "*one-liner form*" $m] |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list 1 1] |
||||
|
||||
#added 2026-08-05 (agent, G-168) |
||||
test punkexemodel_tclsh_selection_matrix {tclsh subcommand: a non-dash first word selects scriptfile (with or without a complete -encoding prefix pending the LIMIT), leading-dash words and incomplete -encoding tails select stdin, empty selects stdin}\ |
||||
-constraints have_punkexedocs\ |
||||
-setup $common -body { |
||||
foreach words { |
||||
{} |
||||
{foo.tcl a b} |
||||
{foo.tcl} |
||||
{-foo bar} |
||||
{-foo} |
||||
{-encoding} |
||||
{-encoding utf-8} |
||||
{-encoding utf-8 -bar} |
||||
} { |
||||
lappend result [dict get [punk::args::parse $words withid (script)::punkexe::tclsh] form] |
||||
} |
||||
set result |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list stdin scriptfile scriptfile stdin stdin stdin stdin stdin] |
||||
|
||||
#added 2026-08-05 (agent, G-168) - stock fall-through parity in the verdicts: |
||||
#a dangling '-encoding' (value missing mid-form) is invalid for scriptfile; |
||||
#a complete '-encoding utf-8' pair with the script file still missing is |
||||
#viable-incomplete; both lines PARSE as stdin (the fall-through) |
||||
test punkexemodel_tclsh_encoding_fallthrough_statuses {incomplete -encoding tails fall through to a successful stdin parse; the scriptfile form verdicts invalid (dangling value) vs incomplete (missing scriptfile)}\ |
||||
-constraints have_punkexedocs\ |
||||
-setup $common -body { |
||||
set ps [punk::args::parse_status {-encoding} withid (script)::punkexe::tclsh] |
||||
lappend result [dict get $ps ok] [dict get $ps form] |
||||
lappend result [dict get $ps formstatus scriptfile status] |
||||
set ps [punk::args::parse_status {-encoding utf-8} withid (script)::punkexe::tclsh] |
||||
lappend result [dict get $ps ok] [dict get $ps form] |
||||
lappend result [dict get $ps formstatus scriptfile status] |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list 1 stdin invalid 1 stdin incomplete] |
||||
|
||||
#added 2026-08-05 (agent, G-168) - the recorded LIMIT: complete |
||||
#'-encoding <name> <scriptfile>' shapes (a dash-led encoding NAME included - |
||||
#the engine consumes a dash-led option value, matching stock's unconstrained |
||||
#argv[2]) word-shape-match both forms; parse raises multipleformmatches |
||||
#naming both (real dispatch classifies these scriptfile - the arity-priority |
||||
#rule per-word constraints cannot express; sanctioned via -overlapallowed) |
||||
test punkexemodel_tclsh_complete_encoding_limit {complete -encoding shapes raise multipleformmatches naming both forms - the deliberate sanctioned LIMIT}\ |
||||
-constraints have_punkexedocs\ |
||||
-setup $common -body { |
||||
foreach words { |
||||
{-encoding utf-8 foo.tcl a} |
||||
{-encoding -foo foo.tcl} |
||||
} { |
||||
if {[catch {punk::args::parse $words -errorstyle minimal withid (script)::punkexe::tclsh} errmsg erroropts]} { |
||||
set classinfo [lindex [dict get $erroropts -errorcode] 2] |
||||
lappend result [lindex $classinfo 0] |
||||
lappend result [lsort [dict get [lrange $classinfo 1 end] forms]] |
||||
} else { |
||||
lappend result UNEXPECTED-parsed |
||||
} |
||||
} |
||||
set result |
||||
}\ |
||||
-cleanup { |
||||
}\ |
||||
-result [list multipleformmatches {scriptfile stdin} multipleformmatches {scriptfile stdin}] |
||||
|
||||
} |
||||
tcltest::cleanupTests ;#needed to produce test summary. |
||||
Loading…
Reference in new issue