In-place closeout edits ahead of the archive move (per the goals/AGENTS.md
pure-rename discipline): detail-file Status flipped to achieved 2026-07-20
(all amended acceptance clauses verified - see the detail file's Progress
record), the console-attachment finding pushed to live G-061's Notes as part
of the archive reference sweep, and punkproject.toml patch-bumped 0.17.0 ->
0.17.1 for the punk::path 0.4.0 pathglob addition shipping in kit payloads
(user-directed). goals_lint transiently red until the archive-move commit.
Claude-Session: https://claude.ai/code/session_01BNUVVkYq9vHa6G3S9a3XTZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved contract amendment replacing the day-1 file-relpath filter: one
directory-oriented pathglob semantics at every layer, with the ergonomics gap
closed in the syntax itself.
punk::path 0.4.0:
- *** as a whole segment matches ZERO or more segments (join-aware regex in
pathglob_as_re: an adjacent separator is absorbed into an optional group),
so X/*** = X and everything below - the subtree spelling; ***/f.txt matches
at any depth including the root.
- include separability fix: an exact or single-segment-glob full match no
longer sets allbelow (the deep walk previously dragged the whole subtree in
for X and X/* patterns; the zipfs walk was already separable).
- exclude separability fix (new exclude_state classifier, both walks): only
**|***-tail patterns prune the matched subtree; other matches exclude just
that directory's files - the **/_aside vs **/_aside/** argdoc distinction is
now real. Dead _path_matches_any removed.
- legacy bare-* include collapse removed (a * in -include-paths is the
one-below lattice form, not a match-everything alias; no caller used it).
- globmatchpath default-nocase driveletter exception rewritten as a direct
regex-head rewrite (the regex-text file-split broke on c:/***'s glued group
and accepted non-alpha drives).
- path.test +5 lattice/*** pins (40 total).
runtests.tcl:
- -include-paths/-exclude-paths pass through to treefilenames unchanged;
argdocs teach the separable X | X/* | X/** | X/*** lattice; directory and
file-name axes independent (tails); single-file targeting = exact dir
pattern + file tail.
- -serial-paths reconciled to the same directory-of-file reading (default now
modules/punk/console/*** modules/opunk/console/*** via
runtests_discovery::dir_matches_any) - the pre-existing file-path serial
matching was the other same-option-different-referent divergence.
- per-pattern zero-match stderr advisory (the X/**-for-subtree foot-gun points
at X/***).
- json report emitter: whitespace-padded entier-looking values now take the
quoted-escaped path ('string is entier -strict' accepts surrounding
whitespace - a failed test's "0\n" result_was embedded a raw newline and
truncated the parseable report line).
- testsupport/discovery.tcl now a thin passthrough (requires punk::path
0.4.0-); pathdiscovery.test rewritten to the directory-semantics contract
(22 tests incl. the X/** zero-match advisory characterization); AGENTS.md
targeting guidance swept to /*** across src/tests and src/modules/opunk.
Verification (native tclsh 9.0.3, piped, serialized): 45-probe matrix, path
suite 40/40, runner suite 22/22; vs the pre-G-093 baseline the default
discovery FILE SET differs by exactly the added runner suite and result
parity only by the five new path tests (+ that suite); mode parity -jobs 16
vs singleproc: PARITY ok (94/1037/failed=1 exec-14.3). Goal contract amended
in the detail file; full record there.
Claude-Session: https://claude.ai/code/session_01BNUVVkYq9vHa6G3S9a3XTZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Root cause (recorded in the goal file): punk::path::treefilenames matches
-include-paths against the DIRECTORY containing files, and its documented
X/** boundary semantics exclude files directly in X - so suites keeping
.test files at the subtree root (scriptwrap, binscripts, punkexe) were
silently missed by X/** targeting: the G-092 four-pattern (2/13 files) and
repeated-flag (zero files) failures. punk::args -multiple accumulation
probed healthy - repeated flags and a single space-separated value reach
discovery identically; no punk change was needed or made.
runtests.tcl now filters the tailbase-relative FILE paths after an
unrestricted walk (new testsupport/discovery.tcl: globmatchpath,
any-include-match, exclusion wins): X/** includes files directly in X, an
exact relative path targets a single file, a bare directory path matches
nothing (append /**). -exclude-paths exposed (same syntax and accumulation,
exclusion wins over inclusion). -discover-only prints the discovered list
plus a RUNTESTS_FILES tcl-list line and exits before any run machinery -
subsecond via a two-stage boot (discovery phase loads only punk::args +
punk::path; punk/Thread/shellrun/punk::tcltestrun and the testinterp/child
path assembly load after the exit).
New regression suite runner/testsuites/discovery/pathdiscovery.test
(23 tests: pure filter, fixture-tree walk+filter, end-to-end -discover-only
children including both G-092 characterization forms; ~7s wall,
parallel-safe). src/tests/AGENTS.md targeting wording reconciled; new
src/tests/runner/AGENTS.md. G-093 index status proposed -> active
(user-directed).
Verification (native tclsh 9.0.3, piped Bash context): pre-change baseline
default -jobs 16 (93 files / 1010 tests / failed=1 exec-14.3 only) vs
post-change -jobs 16 with -exclude-paths runner/**: PARITY ok; post-change
default run differs from baseline only by the added suite (+23 passing);
mode parity -jobs 16 vs singleproc sequential: PARITY ok (94/1033/1).
Claude-Session: https://claude.ai/code/session_01BNUVVkYq9vHa6G3S9a3XTZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Content-identical rename (edits landed in the previous commit); GOALS.md entry
removed and the summary record appended to GOALS-archive.md per the achieved
flip workflow.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Stage 4 - documented overlay semantics implemented (commandset::layout 0.2.0):
layout_materialize resolves a layout to its overlay chain (vendor tier then
custom tier per store+vendor, <name>@<base> derived-layout folders expanding
their base chain first, cycle-guarded) and composes multi-folder chains into a
disposable staging dir applying <item>.anti deletion markers (zero-byte marker
files recommended - committable, unlike the originally documented empty marker
folders, which are also accepted). Single-folder chains with no markers are
used in place, so punk.project (store and zipfs modpod) behaviour is unchanged.
project.new (commandset::project 0.4.0) copies from the materialized path and
the layout listing/scanning commands show the effective merged view.
Fixtures: punk.othersample is now a live derived layout (new custom-deck
fauxlink ref + .gitignore.anti demo marker); extra.txt/store README rewritten
to the implemented semantics. New tcltest suite
src/tests/modules/punk/mix/testsuites/layout/materialize.test (20 tests).
Anti markers deliberately stay a plain filename convention rather than
tag-bearing fauxlinks: a fauxlink is a reference tooling may follow (fcat
auto-follows), a marker is a tombstone with no target.
Stage 5 - retirements and generated-project version seeding:
- The empty unimplemented child-side src/PROJECT_LAYOUTS_CREATE_FROM_... marker
folder is deleted along with its project.new and make.tcl sync exclusions.
- The vendor/custom x _project matrix collapses for layouts: custom/<vendor> is
the one override level; _project folders join no overlay chain (the
pseudo-vendor remains for decktemplates module/utility templates only).
- project.new seeds generated projects post-materialization (only-if-missing,
never from payload): punkproject.toml ([project] name + 0.1.0), a matching
CHANGELOG.md ## [0.1.0] header, and punkorigin.toml - an interim generation
provenance baseline (utc, layout name + resolved store target,
punk::mix::templates version, punkshell version when derivable, origin path)
for the G-027 pull design to adopt (noted in G-027).
Also: script-mode/programmatic project.new robustness (explicit shellrun
require; punk::mix::util askuser/do_in_path/foreach-file fully qualified -
the util:: shorthand exists only after cli commandset import). Includes the
concurrently-landed (other session, previously uncommitted) 0.3.1 early
module-name validation fix in project.new, shipped within the 0.4.0 bump.
G-087 flipped achieved 2026-07-19 (verification in the detail file; archive
move follows in the next commit). punkshell 0.16.0 -> 0.17.0.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Outcomes of the 2026-07-19 punkcheck module review:
- G-094 [proposed]: single OO record lifecycle - installtrack/installevent
becomes the sole implementation with an eager|deferred persistence policy,
punkcheck::install rebuilt as an OO consumer in deferred mode, the
zero-caller installfile_begin/finished/skipped trio retired to shims, and
the o_record_list staleness fixed. The single save chokepoint is G-095's
attachment point.
- G-095 [proposed]: concurrent-writer safety - atomic temp+rename saves,
advisory EXCL lockfile serializing whole installer events per punkcheck
root, merge-on-flush for deferred mode, non-interactive-safe
duplicate-INSTALLER recovery. SQLite recorded as rejected for now (TDL
human readability/debugability overriding; three-part reconsideration bar).
- G-027: acceptance reframed - .punkcheck records demoted from sole
provenance basis to acceleration layer; safe-overwrite classification
survives record loss via a committed baseline record (origin identity +
pulled version, pristine content re-derivable from the origin's VCS),
degrading conservatively (report/confirm - never silent overwrite, never a
wedged pull). Approach classification bullet extended to match.
- G-095 notes carry the tiered expendability taxonomy (build trees: recopies
only; synced-targets bin/ deploy: non-self-healing skip wedge; derived
projects: G-027 baseline) and the cross-tier invariant: absent records
degrade to skip/confirm, never to overwrite.
- (The G-087 cross-pointer to G-094/G-095 already landed with the stage-3
sources commit.)
goals_lint clean (73 active-index goals, 22 archived).
Claude-Session: https://claude.ai/code/session_01L7MfuYBfYpUFpVafo5JowC
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
punk::cap::handlers::templates 0.3.0: module-pathtype layout refs resolve
against the providing module's own templates/project_layouts store (sibling of
its layout_refs folder) instead of the never-existing <modulebase>/src tree -
module-carried thin layouts become usable.
punk::mix::templates 0.2.0: ships the thin punk.project layout payload inside
the modpod (payload synced from src/project_layouts by make.tcl - see below);
shellproject_multivendor declaration fixed decktemplates -> src/decktemplates
(shell-project layouts/templates were invisible when cwd was outside any
project).
punk::mix::commandset::project 0.3.0: project.new injects bootsupport into the
generated project at generation time via new lib::bootsupport_inject - manifest
(include_modules.config) driven module resolution from the generating shell's
project bootsupport tree, or a standalone kit's tcl:™️:list paths (999999.*
dev versions never injected; latest-version non-glob semantics matching
make.tcl bootsupport; adjacent non-.tm support files such as struct sets_*.tcl
and textutil .tex data carried along; bootsupport lib* trees copied from a
shell project, notice emitted for manifest-less standalone kits); punkcheck-
recorded with plain-copy degradation. -layout now prefix-matches the live
layout set instead of the package-load-time snapshot.
punkcheck 0.4.0: start_installer_event no longer writes literal '$eventid'/
'$rel_source'/'$rel_target'/'$config' into event headers (braced-literal
expansion bug, latent since inception - collided as duplicate ids when install
and installtrack writers shared one db); sources with no common root vs the
punkcheck folder (e.g //zipfs:/ module-mounted layouts) are recorded as
independent absolute paths instead of erroring.
punk::mix::base 0.1.1 -> 0.1.2 (manually versioned rename): cksum_path no
longer hangs forever on vfs-mounted files - tcllib -file digest modes read via
fileevent+vwait and zipfs channels never deliver fileevents (empty
ZipChannelWatchChannel in core); non-native files are slurped and digested in
data mode (new cksum_data_command per algorithm + cksum_crc_data/
cksum_adler32_data helpers; exec-based sha3 errors cleanly for vfs paths).
make.tcl: custom/_project layout bootsupport-sync retired (project layouts
store no snapshots); sync_layouts retargeted to thin vendor layouts (make.tcl,
build.tcl + bootsupport manifest copies; punkcheck db at
src/project_layouts/.punkcheck) plus store->modpod punk.project payload sync
(excludes bin/sdx.kit and src/PROJECT_LAYOUTS_* marker; fossil settings kept
via core-exclude override); bootsupport copy onto a modpod the running
make.tcl has mounted records OK when target content is already identical
(FAILED-record churn fix); workflow text updated (DIAGRAM 1b) and help/argdoc
texts adjusted.
bootsupport include_modules.config: added previously-recordless-but-required
entries cmdline (fileutil dep), struct::set (make.tcl accelerators), textutil,
textutil::expander, textutil::patch - generated projects' make.tcl now boots
under a plain tclsh.
Docs: root/src/bootsupport/punk AGENTS.md updated for the retired sync and
build-managed modpod payload; goal detail G-087 stage-3 progress record;
CHANGELOG 0.16.0 + punkproject.toml bump.
Claude-Session: https://claude.ai/code/session_01WS3VakZo4sgbFzcQFW3twZ
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Three tests fail only under a half-attached console (stderr=console,
stdout=file): grepstr highlight tests emit empty SGR and nslist marking
loses its markers - punk::console process-global colour state under
mixed tty-ness. Fully-piped and -jobs runs green; fully-interactive
unverified. Recorded on G-061 (user direction) as a concrete
context-matrix workload for the pseudoconsole harness, alongside the
interim Start-Process selective-redirection repro technique and a
pointer to the related capture_stderr utf-16le fix (913ea749).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Title broadened in both tiers; Goal/Acceptance gain the -exclude-paths
clauses: expose treefilenames' existing capability on runtests (or an
equivalent post-discovery globmatchpath filter), accumulate semantics
matching -include-paths, exclusion winning over inclusion, a
subtree-exclusion run discovering exactly default-discovery minus that
subtree, and both options pinned by the same regression-suite
combination matrix. Notes record the bundling and the middle-ground
motivation examples.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-directed from the G-092 measurement findings: a single
-include-paths value with four deep patterns matched only one subtree,
and repeated -include-paths flags matched zero files, both under the
default *.test tail glob - contradicting the documented accumulate
semantics. Context records the full repro matrix (multi-pattern forms
with explicit tails worked; standalone globmatchpath matched the same
patterns, implicating the treefilenames walk/prune or option-value
shape), the candidate root causes, and the tail-glob workaround. Notes
record that treefilenames already implements -exclude-paths unexposed
by runtests - the planned middle-ground option should be pinned by the
same regression suite.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
multishell.test (10 tests, ~105s solo child - the -jobs floor) split five
ways along shared-fixture boundaries, every test moved verbatim with its
provenance lines: multishell.test keeps wrap + structure/LF-only + exec
smoke (incl WSL); multishell_wrapverify.test (fresh-wrap checkfile) and
multishell_wrapdeterminism.test (byte-identical re-wrap) each re-pay the
wrap fixture; runtimecmd_checkfile.test and runtimecmd_roundtrip.test
guard the committed bin/runtime.cmd and its source round-trip with no
wrap fixture at all. argparsingtest.test (17 tests, ~32s) split into
timeit/discover/contract/first_call (11) + argparsingtest_compare.test
(compare_*, 6). Assessed and left unsplit: dtplite.test (24.6s solo),
scriptexec.test (12s); exec.test excluded as imported core material.
File headers point at the src/tests/modules/AGENTS.md punk/mix bullet
for the sibling map; the runtests longest-first weight table carries
measured post-split weights.
runtests_parity.tcl gains a -names mode: multiset comparison of
'- testname:' lines from '-report markdown -show-passes 1' captures,
file attribution ignored - verbatim moves compare identical, lost/
duplicated/renamed tests are reported.
Verified (native tclsh 9.0.3): repeated -jobs 8 full-suite runs 1m26.3s
/ 1m26.8s (was 2m16s at G-091, ~5m40s sequential - 4.07x vs the
pre-parallel baseline, 36.6% vs the G-091 reference); slowest child
30.7s / 31.3s (bound 45s); NAMES identical (989 occurrences) vs the
pre-split sequential capture; tallies identical in every run (989/973/
15/1, exec-14.3 sole failure, files 87 -> 92); PARITY ok -jobs 8 vs
-jobs 1 and between repeats; repo clean after runs. Notable finding
recorded in the goal file: child-wall contention inflation (~45% with
50s+ dominant children present) collapsed to ~15% once the work
distribution was flattened - splitting reduced both the critical path
and the contention itself.
G-092 flipped to achieved 2026-07-19 and archived (GOALS-archive.md
record, detail file with full verification evidence to goals/archive/).
goals_lint clean. Also noted in the goal file, out of scope: runtests
-include-paths multi-pattern/repeated-flag matching misbehaved during
measurement (single value with four deep patterns matched one; repeated
flags matched zero) - contradicts documented semantics, needs its own
investigation.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved draft from the G-091 verification data: multishell.test's
~2m child wall is the -jobs floor (full-suite -jobs 8 = 2m16s); splitting
the long suites (multishell, dtplite, argparsingtest, scriptexec if
worthwhile; exec.test excluded as imported core material) along
shared-fixture boundaries targets no child wall above 45s and at least a
25% full-suite improvement, with name-level test conservation, provenance
lines travelling with moved tests, weight-table updates, and parity
gating. Context records the fixture-duplication tradeoff (total CPU up,
wall down) and the complementary lean-children candidate.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
-jobs N (implies -singleproc 0; explicit -singleproc 1 conflicts) runs
test files through a tpool of N concurrent child processes with
per-child capture files and tcltest -tmpdir subdirs, longest-first
static-weight submission, and a -serial-paths serial tail (default: the
console-state suites modules/punk/console/** + modules/opunk/console/**;
piped-child-driven suites proved parallel-safe and each serial file
costs its full child boot strictly after the parallel phase). Cached
results feed the unchanged processing loop in discovery order, so
reports are identical in shape and order to sequential runs. Watch mode
emits file-collected events (completion order, output relayed there);
file-end (tallies) stays discovery-order. The runner now reports jobs
phase times and the ten slowest child WALL times (child wall includes
boot + file-level fixture cost that per-test usec misses).
Two Tcl-core-level behaviours found and worked around in the child
spawn (see the verification record in the archived goal file):
- concurrent BLOCKING execs from worker threads convoy on Windows (all
return at the longest concurrent child's exit; plain sleepers 2-12s
from 8 workers all walled at 12.0s) -> spawn via 'exec ... &' and
poll per-pid tcl::process status; blocking fallback retained for
runtimes without tcl::process (tcl 8.6).
- Tcl_ReapDetachedProcs runs on every exec and purges finished
background children process-wide, racing the poll (nondeterministic
'key <pid> not known in dictionary') -> tcl::process autopurge false
+ explicit per-pid purge after the status read.
Verified on native tclsh 9.0.3: repeated -jobs 8 full-suite runs
2m16.2s / 2m15.6s with PARITY ok vs -jobs 1, between repeats, and vs
the pre-parallel baseline (987-test identity, exec-14.3 sole expected
failure); 2.58x vs the ~350s sequential baseline (2.41x vs one
cooler-machine 5m28.8s sequential run - recorded in the goal file);
repo clean after every run.
G-091 flipped to achieved 2026-07-19 and archived (entry to
GOALS-archive.md, detail file to goals/archive/ with the verification
record; reference sweep updated runtests.tcl comments and the
src/tests/AGENTS.md marker). goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Both user-approved 2026-07-18 from the runx -teelog / runtests watch-mode
work (a65f9e5b) and the -singleproc 0 completion (218fbb1c).
G-090 records the probe evidence deliberately not addressed in that work:
float-placement starvation of a tee under the float-locked capture
junction, insert_transform re-instantiation churn, parked-worker adoption
never re-applying settings (silent cross-target log misrouting), the
per-file teehandle worker-thread leak in unwatched singleproc runs, and
the tcludp Tcl 9 receive-fileevent first-datagram-only behaviour.
G-091 is the phase-2 parallel test plan over the phase-1 child spawn:
tpool -jobs N, per-child tmpdirs, serial group for console-sensitive
suites, parity + >=2.5x acceptance (floor ~90s, multishell.test bound).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New goal (user-approved wording): make.tcl bakes a curated scriptlib into
kit vfs app/scriptlib so standalone binaries have working lib: scripts, with
precedence following the packagemode mental model - kit-internal-wins only
for the default 'internal' launch, src/dev modes putting the live project
scriptlib first, and proj: (G-033) adding the visited project's scriptlib.
Context records the 2026-07-18 findings: kit-internal resolver branch never
exercised (no build path exists), not-overridable policy scoped to default
mode per user direction, missing boot->runtime packagemode hint, cookfs
mount-root gap, and the out-of-scope app-shellspy mapping. goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Goal for embedding a short marker in the usage/error table's bottom frame edge
(bottom-right @examples indicator, counterpart of the top 'Usage' title). Two
severable deliverables: frame-parity -subtitle/-subtitlealign on
textblock::class::table (must work with or without footer rows), and footer
rows with column spans independent of the body via configure_footer mirroring
the header API (the -show_footer/-ansibase_footer/-ansiborder_footer styling
knobs already exist but no footer-row methods do). arg_error's interim
'Example:' header row retires when this lands.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- CHANGELOG + version bump for the fauxlink 0.1.2 vendor pull, tomlish catch-up
and bootsupport refresh.
- G-087 detail Notes updated: fauxlink 0.1.2 upstream work record, punkshell
fauxlink consumer survey (fcat follows only .fauxlink not .fxlnk; make.tcl
merge_over + startup-script check; kit boot fallback), the (package) id
status relative to G-075, and the recorded intention that punk::nav::fs
should gain fauxlink handling analogous to its punk::winlnk shortcut
treatment (candidate goal).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New goal from the 2026-07-16 layout-system review: thin layouts with
generation-time infrastructure injection, fauxlink layout refs, and a working
overlay merge primitive. Detail file carries the review findings (unimplemented
merge, dead module-pathtype refs, stale fat snapshots, latent bugs), the staged
approach (hygiene first), and the hygiene-stage completion record.
Activated at user direction 2026-07-17.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The punk9win.vfs kit was split into punk9wintk90b2.vfs and
punk9wintk903.vfs; the treectrl/Img/twapi/cffi payloads G-020 relies on
live in punk9wintk903.vfs/lib_tcl9 (the actively mapped tclsfe/punk91
kit). Path-only update, user-approved; goal contract otherwise
unchanged. goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved from the serversecretsync tm-path-shadowing incident
(8.6 require-before-path-setup silently selected a stale tomlish from the
machine-default tm paths over the project's vendored copy). Default
mechanism per user: vendor punk::libunknown + punk::packagepreference as
the light layout's bootstrap minimum. Related: G-012/G-027/G-029/G-035.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved wording (drafted from the 2026-07-14 cmdtrace investigation):
an attribution option (live|sourcefile|auto - sourcefile mode doubling as a
practical workaround for the upstream nested-switch mis-attribution, tcl
tktview 5d5b1052280c976ea3d4) and a documented machine dict return for
future hotspot-analysis/repl consumers (implies no interactive pause).
Context records the unexplored regime boundary (module .tm procs trace
relative, plain sourced procs absolute) as goal groundwork. goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
A word rejected by an OPTIONAL argument's allocation screen (G-071
restricted-choice screen, or the basic int/double/bool/number/dict type
screen) that subsequently overflows the argument list now reports the
specific rejection instead of "Received more values than can be assigned":
- choiceviolation naming the word and allowed choices, with -badarg/-badval
and the final-validation message template (Leading/Trailing argument
attribution), for choice-screen rejections
- typemismatch naming the declared (normalized) type, with -badarg/-badval,
for basic-type screen rejections
Mechanism: private::get_dict_can_assign_value returns a 'rejection' record
(single-member clauses only; literal-category mismatches deliberately not
recorded); get_dict_form collects first-rejection-per-word from the three
allocation call sites (leader/value split trial, leaders loop, values loop)
into a per-form store; the two toomanyarguments raise sites prefer a
recorded rejection for the unassignable word. Genuinely-surplus words still
report toomanyarguments; words consumed by later slots parse unchanged;
multiform selection (rank_form_failures) untouched.
errorselection.test _GAP pins flipped to the pointed expectations (pre-fix
behaviour pinned in the previous commit). punk::args buildversion
0.12.0 -> 0.12.1.
Closeout: G-082 flipped achieved + archived (index -> GOALS-archive.md,
detail -> goals/archive/ with mechanism/verification/residue recorded);
G-073 note updated to point at the new rejection-record seam;
src/modules/AGENTS.md authoring-ergonomics bullet re-documented (-optional 0
workaround no longer needed on >= 0.12.1; make.tcl keeps it - it runs
against the bootsupport 0.12.0 snapshot). Project version 0.12.28 +
CHANGELOG.
Verified: full punk/args suite 228/224/0-failed (4 intended skips) and
punk/ns 57/57 under Tcl 9.0.3; errorselection.test 7/7 under Tcl 8.7;
make.tcl frobnicate still pointed; goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Set G-082 active (user-directed). New errorselection.test pins current
single-form error selection before the fix:
- _GAP pins: an optional choice-restricted leader (make.tcl dispatch shape),
an optional choice-restricted value, and an optional typed (int) value each
reject a word that then overflows - all report generic
{toomanyarguments N index I} with no -badarg/-badval attribution,
discarding the specific rejection (regression vs punk::args 0.5.0)
- reference pins: the -optional 0 equivalents report pointed choiceviolation
with -badarg/-badval and Leading/Trailing argument messages
- guards: genuine surplus stays toomanyarguments; a rejected word consumed by
a later slot parses cleanly; multiform failures still route through
rank_form_failures (noformmatch)
Verified: 7/7 pass against the unfixed module under Tcl 9.0.3.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New proposed goal G-082: single-form parse error selection should prefer an
optional argument's specific choice/type rejection over the generic
"more values than can be assigned" overflow (regression vs punk::args 0.5.0
found while dogfooding in G-030; the -optional 0 workaround sites in make.tcl
and the AGENTS authoring-ergonomics bullet are flagged for revisiting when it
ships).
Sibling notes parked in existing proposed goals:
- G-028: make.tcl's name-only process-sweep misidentification (unrelated
same-named executables) - full-path matching rides the same
process-identification infrastructure as the locker report.
- G-025: punk-exe-hosted make.tcl runs the kit's pre-loaded module copies, not
bootsupport snapshots - a self-report surface for running-interp module
provenance would make the mixing observable.
- G-073: reciprocal relation to G-082 (both want the "surface the specific
rejection" seam in validation error reporting).
- G-075: synopsis renders the definition id rather than @cmd -name - consider
a fallback for non-command ids when reworking id rendering.
goals_lint: unchanged (only the pre-existing G-078/G-081 index-mirror findings).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Fixes the constructed-definition indent leak user review spotted in
'make.tcl help' output (@cmd -help Description first line rendered less
indented than continuations): HELPTEXTS and the inline shell/help/toplevel
help values are now block-form (first value line whitespace-only) with a bare
@normalize in every constructed definition, per G-045's preferred style. The
braced option fragments never leaked (literal block-shaped parts get
file-style normalization) and head-form values are contractually untouched by
@normalize. Also adds a define-time capability probe (punk::args::get_spec on
representative ids inside the guarded block) 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.
AGENTS infrastructure for future documentation work: src/modules/AGENTS.md
"Documentation And Comments" gains a "punk::args definition authoring
ergonomics" subsection (G-045 mechanisms: @normalize + block form for
constructed defs, -unindentedfields, -& record continuation, container
quoting rules; plus the G-030 lessons: explicit @form -synopsis for
script-level ids, -optional 0 for pointed choiceviolation errors);
src/AGENTS.md cross-references it and names ::punkboot::argdoc as the
in-tree constructed-def exemplar. Follow-up recorded in the G-030 archive.
Verified: flush Description rendering for toplevel/subcommand/shell/help
usage; dispatch, degraded mode (PUNKBOOT_PLAIN) and usage-error paths
re-verified; layout make.tcl copies re-synced via 'make.tcl bootsupport
-confirm 0' (punkcheck channel); goals_lint unchanged (only the pre-existing
G-078/G-081 index-mirror findings).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
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.com
Formalize the follow-on work identified during the punk::args documentation
trials and ansi->html prototyping (2026-07-13/14):
- G-078 punk::ansi ANSI->HTML rendering api: promote the prototype ansi2html
converter + headless ansicat flatten entry into a documented punk::ansi
api (palette option, art mode with bold-as-bright and block sealing,
-assets embed|link|none using the vendored punkdoc-mono; docs-screenshot
enabler)
- G-079 default-colour semantics: renderspace replay output bakes explicit
SGR 40 for never-set backgrounds; preserve default fg/bg semantically so
html can theme-match any page background (current workaround: black pre)
- G-080 deterministic cell-grid rendering mode: inline-block cell emulation
to eliminate the residual sub-pixel seams the span-mode recipe accepts
- G-081 argdoc build pipeline: dev doc.* generation of doctools + punk-native
html + markdown from punk::args definitions against dev modules, incl.
per-form table rendering, deeper-namespace pages, @package surfacing
(G-075) and shared doc-set font assets
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New punk::args::formcheck <id> ?-return dict|summary?: reports the form pairs
of a multiform definition that some argument list could cleanly match
simultaneously (the multipleformmatches inputs). Static pairwise pass over the
resolved FORMS enumerates each form's positional word-slot chains (leaders then
values; -optional and ?-wrapped clause-member branching; -multiple capped;
options excluded - order-free), screens aligned equal-length chains per
position (discriminator words via choiceword_match, type witnesses from a
small table), and CONFIRMS every candidate witness arglist with a real
single-form parse against both forms (parse_status - no raise, no
user-supplied words, no define/resolve cost). Findings are therefore witnessed
- discriminated form pairs cannot false-alarm; misses (exotic types,
option-requiring forms, enumeration caps) are the documented conservative
direction. Classes: type_weakness (discriminator aligned with a permissive
non-validating type - any/none/string/ansistring/globstring/expr/script) vs
structural (forms genuinely share an argument shape).
New @form key -overlapallowed <formname-list> sanctions a KNOWN overlap on
either pair member: the finding reports with sanctioned 1 and leaves the
result's unsanctioned list (the actionable/gate subset). Parse behaviour is
never affected; unknown form names are rejected at definition resolve
(end-of-forms cycle). @form directive doc updated.
tclcore moduledoc 0.3.4: the documented after cancelid/cancelscript overlap
(runtime-liveness ambiguity, 0.3.0 record) sanctioned on the cancelid form -
::after now reports zero unsanctioned findings while 'after cancel <id-shaped>'
still raises multipleformmatches. ::lseq deliberately unsanctioned: formcheck
reports range/start_count (witness {1 count 1}) AND range/count (witness
{1 by 1}) - both real, both rooted in the expr-typed end slot, kept visible
pending an expr syntax-validating type (G-069/G-070).
Tests: new args/formcheck.test (7) - no-finding cases (parse withid/withdef
pair, afterish/sharedform fixtures), class+sanction fixture, unknown-form
rejection, -return summary, ::lseq/::after pins with witnesses re-verified,
sanction parse-neutrality. punk::args suite 210/210, punk::ns 57/57.
G-074 achieved and archived (acceptance review in the detail file); G-055
verification gate gains the formcheck step (unsanctioned must be empty for
regenerated multiform commands).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Proposed goal, wording user-approved 2026-07-13: make the perl/python/node -e
reflex work on punk kits (top-level and script subcommand forms) instead of
erroring, without ever reproducing stock-tclsh argv-swallow/stdin misparse
behaviour. Companion to the tclsh -e guardrails commit (AGENTS.md entry +
claude deny hook).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
New goal G-076 (active): adopt the upstream tcl9 dead-console fix (ticket
f10d91c2d3, root-caused in G-039) via a single version gate shared by the
'help tcl' warning and the repl watchdog arming.
- punk::lib 0.4.3: has_tclbug_console_deadspin + pure classifier
tclbug_console_deadspin_applies, gate variable
check::tclbug_console_deadspin_fixed_in (empty = all Tcl 9 windows
runtimes affected). Buginfo dicts gain a mitigated/mitigation axis
orthogonal to level; the deadspin check reports mitigated when
punk::repl >= 0.5.0 is available to the runtime.
- punk::repl 0.5.1: repl::start arms the dead-console watchdog only when
the check reports the runtime affected - recording a verified fixed
release once flips both consumers.
- punk 0.2.6: 'help tcl' renders mitigated warnings subdued (term-grey)
with a "(mitigated)" annotation and the mitigation text; severity
classification unchanged.
- checkbugs.test: classifier truth table, live-check consistency, and
mitigated-axis validation in the generic every-check sweep.
The fixed_in flip is deliberately deferred until a released Tcl passes
the G-039 kill-procedure re-verification (watchdog disabled, clean
script-visible eof exit) - recorded as the goal's remaining acceptance
item.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Authoring-style change only, user-directed: the interim %AFTERIDPREFIX%
string map is replaced by plain tstr placeholders, with the harvest
variable set in the argdoc namespace - the defspace registered PUNKARGS
definitions resolve placeholders in when an argdoc child exists (the
rule documented in punk::args 0.11.1). One mechanism now serves both
the -type parse field (expanded at first resolve) and the -help display
fields (expanded at display time); the module showcases the placeholder
style, with string map reserved for genuinely build-time cases.
Behaviour identical to 0.3.0: resolved -type stringstartswith(after#),
form discrimination, parity pins and rendered help re-verified.
punk::args 201/202 (1 pre-existing skip), punk::ns 57/57. G-055
workflow note updated to name the tstr-in-argdoc pattern as preferred.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The 0.3.0 record claimed tstr placeholders in non-display fields are not
expanded for plain PUNKARGS definitions. Controlled probes show all
authoring styles (direct define, registered PUNKARGS, argdoc-subns
variable) DO expand parse-field placeholders - the ::after attempt
failed because update_definitions resolves registered definitions in
the argdoc subnamespace whenever one exists, while the harvest variable
had landed in the parent namespace, and an unresolvable param is left
silently literal. Module comment, buildversion changelog line and the
G-055 workflow note corrected; the silent-literal fallback noted in
G-055 as a diagnostic gap (a literal placeholder reaching a parse field
is always an authoring error and could warn).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
The cancelid and info forms' id argument is typed
stringstartswith(<prefix>) with the prefix harvested from the running
interpreter at define time (safe create+cancel probe; after# on 8.6.11
and 9.0.3) - substituted via a build-time %AFTERIDPREFIX% string map
because tstr placeholders in non-display fields are not expanded for
plain PUNKARGS definitions (G-046 defers display fields only; noted in
G-055 for the regeneration workflow). -typesynopsis id keeps the
synopsis as the man page's 'id'; both ids gain man-page-derived help.
Effect under G-041 form candidacy: 'i after cancel someid' resolves
cleanly to the cancelscript form, matching real Tcl's silent
script-match no-op; 'after info <non-id>' is model-rejected where real
errors at runtime (parity-true). An id-SHAPED word after cancel stays
truthfully ambiguous (cancelid+cancelscript) - real Tcl resolves that
junction by id liveness at runtime, which no static type expresses.
Dead-id over-acceptance on 'after info' recorded as the accepted
runtime-liveness boundary.
Tests: three parity pins added in tclcoreparity.test (id-shape harvest
agreement with live ids, cancel discrimination incl the liveness
ambiguity witness, info error-vs-ok parity + accepted dead-id
divergence). punk::args 201/202 (1 pre-existing skip), punk::ns 57/57.
Live-verified on punk902z src ('i after cancel someid' renders info
scheme).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Acceptance reviewed clause-by-clause in the detail file: auto-selection
on a unique clean match (forms.test GAPs flipped), candidate-naming
noformmatch/multipleformmatches errors, -form list restriction across
get_dict/parse/parse_status/arg_error, doc surface presenting the
best-matching form(s) ('i after cancel <id>' presents the cancel form;
's after cancel someid' underlines the matching synopsis lines),
explicit single -form unchanged, full punk::args/punk::ns suites pass
(full tree 822/836 with only the exec-14.3 baseline failure).
Flip edits: index entry to GOALS-archive.md (achieved 2026-07-13),
detail Status flipped with acceptance review and live-verification
record, reference sweep updates G-044 (candidacy API now available -
parse_status formstatus), G-055 backlink, G-072 backlink. Detail-file
move to goals/archive/ follows as a pure rename; goals_lint transiently
unclean between the two commits.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
cmdhelp ('i'): the -form option defaults to * (was 0) with parse's
list semantics, and both render sites present the form the advisory
parse selected - 'i after cancel <id>' presents the cancel form's
argument table with its synopsis line underlined; 'i lseq 0 10 2'
presents the range form info-scheme. When no form matches, the ranked
candidates are passed to arg_error (best candidate's table, all
candidates marked, message naming each form's failure); when several
forms match, all matching forms are marked under the ambiguity message.
punk::ns::synopsis ('s'): trailing argument words after a multiform
command path underline the form(s) they match - matching forms from the
advisory parse's formstatus, or the best candidate when none fully
matches ('s after cancel someid' marks both cancel forms; 's lseq
0 10 2' marks the range form). Ordinal line position maps lines to
declaration-order forms in both full and summary renders; marking is
skipped under alias-currying excess or an explicit -form.
punk::args 0.11.0: the documented @form -synopsis override now renders
in punk::args::synopsis full and summary output (arg_error honoured it
already) - the adjacent forms.test GAP flipped
(forms_form_synopsis_override_rendered). Candidate ranking extended:
form_literal_affinity treats required RESTRICTED-choice arguments as
discriminators via choiceword_match (the tclcore models express
subcommand words as -choices), so 'after cancel' ranks the cancel
forms first instead of falling back to declaration order.
Real-model findings recorded in the goal detail: 'after cancel someid'
is genuinely ambiguous in the doc-faithful model (cancelid vs
cancelscript - real Tcl disambiguates semantically); 'lseq 1 count 5'
ambiguity traces to the expr-typed operands (noted in G-055 as a
model-tightening candidate alongside TIP 746).
Tests: cmdhelp.test gains the multiform doc-surface pins (autoselected
form presented, noformmatch best-candidate table + candidate naming,
synopsis marking present/absent). punk::ns 57/57, punk::args 198/199
(1 pre-existing skip); full source-tree suite in the detail record.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
punk::args::parse/get_dict with the default -form * (or any multi-form
selection) now attempts every permitted form instead of effectively
parsing form 0 only. Exactly one clean match auto-selects (result gains
a 'form' key; 'formstatus' reports every candidate when candidacy ran).
No match raises a 'noformmatch' validation error naming each candidate
form's first-line failure, ranked best-candidate first (leading-literal
affinity with the supplied words, then incomplete before invalid, then
declaration order). Several clean matches raise 'multipleformmatches'
naming the forms - deliberately no silent preference (recorded in the
goal detail); callers pass -form to disambiguate.
-form now accepts the documented list of form names/indices across
get_dict, parse, parse_status and arg_error via a shared resolver
(private::form_selection). arg_error renders the argument table for the
first listed form and marks all listed forms' synopsis entries; parse's
error render passes the ranked candidate list so the closest form's
argument table shows under the no-match message.
parse_status: 'form' is now the matched (or best-candidate) form - the
per-argument statuses and badarg marking are built for it - and the new
documented 'formstatus' key carries per-form status/failureclass/badarg/
message (caller-attributed), the per-form compatibility surface the
G-044 completion/hinting consumer needs on partial argument lists.
Engine restructure: the single-form parse body of get_dict extracted
verbatim to private::get_dict_form (argspecs resolved in the caller's
context before selection; no caller-frame use inside - verified).
Single-form definitions take the direct path unchanged.
Tests: forms.test GAP pins flipped (forms_parse_autoselect,
forms_parse_formlist_restriction) plus new coverage: shared-prologue
arity discrimination, noformmatch ranking + errorcode payload,
multipleformmatches + explicit -form disambiguation, formstatus in
results and parse_status. punk::args 198 pass / 1 pre-existing skip,
punk::ns 53/53, punk::lib 35/35.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
User-approved draft from the 8.6-vs-9 string is dict forward-compat
requirement: a new definition key (candidate -choiceunavailable) for
choices that are recognised but not available in the current runtime -
displayed among the choices with their -choicelabels notes, participating
in prefix disambiguation via the shared choiceword_match resolver (so
abbreviations colliding with forward-version choices are ambiguous
everywhere), and rejected at parse with a tailored recognised-but-
unavailable message. Adoption by the tclcore string is model gives 8.6
users the dict class annotated and reserved (deliberately stricter than
real 8.6 for the di prefix - recorded as a user-sanctioned parity
exemption; full-word behaviour stays parity-true), plus an
i-string-is-dict documentation id generated from the static description.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Space-form docid prefix parity: cmd_traverse's space-delimited child
docid jump, on an exact-word miss, now resolves the word against the
current level's choices-bearing first leader via
punk::args::choiceword_match (the shared G-040 resolver - -choiceprefix,
-nocase, -choicealiases, denylist, reservelist honoured) and retries
with the canonical word. 'i string is tr' resolves to the
"::tcl::string::is true" documentation exactly when 'string is tr 1'
executes; 'string is bool' -> boolean; ambiguous ('d'), unknown ('zz')
and denied words stay at the parent exactly when parse rejects them.
resolvedargs records the canonical, mirroring parse normalization. No
second matching rule exists.
Truthful cmdtype: cmdinfo classifies cmdwhich-notfound + non-empty docid
as 'doconly' (was 'notfound') - documentation-only levels below real
commands (per-class ids like "::tcl::string::is true", documented TclOO
method docids; the method case adopts doconly per the recorded design
decision, refinable by G-052). Consumers audited: cmdhelp/synopsis/eg
are docid-driven, cmdtrace tests only for 'proc', punk::help topic
fallback uses cmdwhich; punk::lib script analysis updated in step
(doconly accepted alongside notfound, bucketing unchanged).
Tests: the four G-051 GAP pins flipped and renamed
(cmdhelp_pseudo_command_cmdtype_doconly,
cmdhelp_spaceform_docid_prefix_honoured + ambiguous/unknown guard,
cmdhelp_string_is_true_pseudo_doconly,
cmdhelp_string_is_prefix_honoured). punk::ns 53/53 (cmdflow + non-GAP
cmdhelp unchanged), punk::args 193 pass / 1 pre-existing skip,
punk::lib 35/35; full source-tree suite result in the detail file.
Live verification (punk902z src): 'i string is tr' renders
byte-identical to 'i string is true' except the failure banner echoing
the typed words.
Flip edits: G-051 index entry to GOALS-archive.md (achieved 2026-07-13),
detail Status flipped with acceptance review and verification record,
reference sweep updates G-052 Notes. Detail-file move to goals/archive/
follows as a pure rename; goals_lint transiently unclean between the two
commits.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Root cause: get_dict_can_assign_value blanket-satisfied the member check
for any argument carrying choices, so an optional restricted-choice value
(the lseq '..'/'to' noise word) consumed any word whenever arity
permitted, starving later elements/clauses and failing validation with a
confusing trailing-choices error ('lseq 0 10 2' shape).
Fix: an allocation choice screen using choiceword_match (the shared G-040
implementation - exact/alias/prefix/nocase semantics; -choicemultiple
words screened per list member within min/max), applied only where
allocation has an alternative: -optional arguments and further
occurrences of -multiple arguments. Required arguments are deliberately
not screened - the word must fill them and validation's choiceviolation
reporting stays informative (the existing parsestatus/cmdhelp/choices
pins forced and now document both refinements). -choicerestricted 0
behaviour unchanged.
Results: the allocation.test GAPs flipped ('1 2 3' and '1 2 by 3' parse
with correct clause shapes {{} 3}/{by 3}; '1 2 3 4' gets the plain
excess-values rejection instead of blaming the unrelated optional);
prefix normalization survives the screen; all noise-word variants and
if-shape guards unchanged. lseq moduledoc matrix parses per lseq.n under
-form range, and 'i lseq 0 10 2' works end-to-end. Remaining lseq
divergences trace to G-041 form selection or the -type expr laxity
recorded in G-055 - not allocation.
Also corrected an increment-1 mis-premise: parse_status ALREADY accepts
-form before the withid/withdef tail per its documented synopsis - the
probe had passed it trailing. GAP replaced by
parsestatus_form_option_order (correct-order acceptance incl. the form
key, trailing rejection). No code change was needed for that acceptance
clause.
Verification: punk::args suite 193 pass / 1 pre-existing skip / 0 fail;
punk::ns 53/53; full source-tree suite 813 pass / 13 skip / 1 fail =
exec-14.3 only (known baseline) - zero regressions (tclsh 9.0.3; lseq
verification in punk902z src, Tcl 9.0.2).
Flip edits: G-071 index entry moved to GOALS-archive.md (achieved
2026-07-12), detail Status flipped with the acceptance review and
before/after record; reference sweep updates G-041 (prerequisite fixed,
parse_status correction) and G-072 Notes. The detail-file move to
goals/archive/ follows as a pure rename; goals_lint transiently unclean
between the two commits.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com