All acceptance items met and recorded in the goal file: clean-checkout +
punk-getzig-pinned-zig build PASS (shallow-path/longpaths MAX_PATH caveat
recorded; c:/T available as a shallow test base per user), recovered +
rebased piperepl patch set with the G-103 opt-out gate policy and full
behaviour matrix (automated rows + user interactive verification),
tclsh90spr/tclsh90sprzip products, per-version punk-getzig into versioned
dirs (all four paths verified), both-VCS tracking + samplesuite1/
vendorbuild reconciliation, bin/AGENTS.md naming policy + punk-getzig
rename. Flipped to achieved 2026-07-20 and archived; GOALS/GOALS-archive
updated; achieved markers added to the six referencing goals flagged by
the lint reference sweep (G-097, G-100, G-102, G-103, G-104, G-106).
goals_lint clean (79 active, 27 archived).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
G-098 (suite_tcl90 Tk+tklib, tcllib/tcllibc via critcl, test gating)
flipped to achieved 2026-07-20 and archived - all acceptance items
recorded in the goal file across increments 1-7 (Tk 9.0.2 + tklib,
tcllib+tcllibc ~248x hashing speedup, parsed-totals test gate with
dispositioned baseline, full punkshell runtests parity with the Tcl903
baseline including Tk suites unskipped, kit-hosted runs fixed).
New proposed goals mirror the arc for fossil core-8-6-branch (8.6 stays
punkshell's real Tcl 8 target; current punk86-class kits ride prebuilt
third-party tclkits - a provenance gap):
- G-099: suite_tcl86 core - zig-only 8.6 runtime + thread 2.8-branch +
tclvfs + parsed-totals core-test gate with its own dispositioned
baseline. Records expected differences (no zipfs, entry-point/bundled
lib divergences, no tcl::process).
- G-100: Tk 8.6 + tklib + tcllib/tcllibc via critcl on the 8.6 runtime +
punkshell runtests census against a native 8.6 kit baseline.
- G-101: kit container strategy without zipfs (metakit/tclkit lineage vs
cookfs vs zipvfs boot; TEMP_REFERENCE/metakit + KitCreator guidance) -
separated so the well-understood ports stay incrementally landable.
Sequencing recorded in each goal: recommendation is to close G-096's
remainder and run the punk905_beta trial to promotion before activating
the 8.6 arc, so shared suite scaffolding settles before it is forked.
goals_lint clean.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Sweep: G-096 detail and the punk::lib gate comment now point at the archived
path with achieved phrasing. goals_lint clean (72 active, 25 archived).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Content-identical rename (flip edits landed in the previous commit); GOALS.md
entry removed and the summary record (amended *** acceptance) appended to
GOALS-archive.md per the achieved flip workflow. Rides along: CHANGELOG.md
gains the required [0.17.1] entry matching the punkproject.toml bump from the
previous commit (punk::path 0.4.0 *** pathglob + separable lattice; runtests
targeting rework).
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
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
-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
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
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
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
An interactive shell orphaned by its hosting console dying (killed
conhost/terminal) previously spun ~2 cores forever: the Tcl 9 windows
console driver never delivers the dead-console state to the script as a
fileevent (tclWinConsole.c ConsoleEventProc only notifies on buffered
data) while its reader thread busy-loops on the persistent channel error,
so the script level is completely blind and nothing ever closes the
channel.
Fix: repl::console_watchdog - a self-rescheduling liveness poll (default
5s, repl::console_watchdog_ms; read-only GetConsoleMode probe via
chan configure -inputmode) armed by repl::start only for a tcl9 console
input channel serving the process-default console on windows. On probe
failure it closes the input channel (stopping the driver's reader
thread) and finishes the repl via the normal eof done-path; app-punkshell
then finds no console reopenable and exits cleanly. Piped, foreign-console
and tcl 8.6 inputs never arm it. repl::start's post-vwait reader
deregistration now tolerates a watchdog-closed channel.
Verification (2026-07-12): kill procedure post-fix exits the orphan in
1.5-2.0s with no traceback (src mode and rebuilt kits punkbi/punk91/
punk902z); 25s live-console soak shows no spurious trigger, CPU delta 0;
piped stdin unaffected; repl consolebackends 3/3 and punk::console suites
88 pass / 1 skip; root cause verified against plain tclsh 9.0.3.
Upstream ticket filed: https://core.tcl-lang.org/tcl/tktview/f10d91c2d3
Included:
- goals: G-039 flipped achieved 2026-07-12 and archived (index entry to
GOALS-archive.md, detail file to goals/archive/ with full root-cause,
repro and verification record); reference sweep adds the eof done-value
producer note to G-038
- src/modules/punk/AGENTS.md: watchdog contract documented
- project version 0.12.1 -> 0.12.2 + CHANGELOG entry
- vfs payload sync: _vfscommon.vfs punk/repl 0.4.0 -> 0.5.0
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Finalises the G-062 achieved flip staged by the prior session (punkshell
0.12.1): LICENSE.txt (BSD-2-Clause, Julian Marcel Noble 2023-2026) at the
repo root, README/punkproject.toml/AGENTS.md license declarations, index
record to GOALS-archive.md and detail file to goals/archive/.
Archive-loss prevention, from the G-015 incident (its achieved-status
verification parenthetical was silently dropped by the 2026-07-11 two-tier
restructure's Status-line normalisation; the text is restored to the G-015
archive file's Notes with provenance):
- root AGENTS.md 'Doc Restructures': deleted-line conservation check before
committing bulk doc migrations, structured-field-normalisation hazard
(relocate prose to body sections first), moves separated from edits
- goals/AGENTS.md: lintable header field grammar (one line per field, bare
Status values), flip-time verification evidence recorded in the body, the
archive move content-identical, and a new archive-time reference sweep:
pending-tense mentions of the archived goal updated in the live tier, and
actionable archived notes pointed to from the affected live goal's Notes
- GOALS.md maintenance rules: achieved-flip clause extended to require the
evidence write-up and the reference sweep
Retroactive reference sweep over all 12 archived goals (25 live detail
files): pending-tense fixes (G-002 G-008 G-013 G-016 G-017 G-021 G-022
G-031 G-042 G-044 G-050 - G-017's Goal/Acceptance annotated as
gate-satisfied, contract meaning unchanged), forward pointers pushed from
archived notes (G-062 license-seeding follow-on -> G-012/G-027, G-037
vendorlib/vfs drift semantics -> G-024, G-058 static-baseline mechanism ->
G-005), and one 'Archived-goal references' Notes bullet per remaining
referencing file so every live mention of an archived goal is resolvable
without consulting the archive index.
scriptlib/developer/goals_lint.tcl (new, plain tclsh): validates detail-file
header grammar, strict status values in both tiers, orphan rules in both
directions, Status/Scope mirror consistency, plus an informational (never
fatal) warning for live files referencing an archived goal with no
achieved/archive marker - baseline now zero warnings. Root AGENTS.md
scriptlib/developer ownership note widened to cover developer utilities.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Acceptance verified (consolebackends.test child-process drivers): repls run
interactively through ssh-socket and tk-widget ::opunk::Console subclasses
with size/at_eof/can_respond answered by the overrides, base class and
punk::console unchanged. Detail file records increment 2 and the non-gating
residue (per-run output batching, punk/0-only junction wiring, raw-mode
untested on foreign consoles, process-global console state -> G-008).
Project version 0.10.3 -> 0.11.0 with changelog entry (new user-visible
shell capability: repl::init -console).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
- GOALS.md collapsed to summary entries (ID/status/title/Scope/detail pointer): 104.6KB -> 23KB so a full read stays cheap; Scope lines kept verbatim so path-grep goal discovery still works
- canonicality split: index canonical for ID/status/title/Scope, detail file canonical for Goal:/Acceptance:; all 61 detail-file headers reconciled from the index (fixes stale copies, e.g. G-036 detail acceptance predated the achieved rework), bodies preserved untouched
- detail files created for the three index-only goals G-017, G-034, G-054; every goal now has one
- 10 achieved goals (G-007 G-015 G-036 G-037 G-040 G-046 G-049 G-054 G-058 G-059) archived: summary records appended to GOALS-archive.md, detail files moved to goals/archive/; archive-on-flip replaces the ~30-achieved-entries trigger
- GOALS.md preamble/rules reworked: read workflow (read index in full, then detail files of scope-intersecting goals before editing), contract spans both tiers with proposal-first unchanged, next-free-ID counts the archive, achieved flip judged against the detail-file Acceptance and includes archiving
- progress convention codified from G-001 increment-1 practice: index entries carry status only, never progress; incremental progress lives in the detail file's ## Progress section (landed/remaining); achieved flip requires the remaining-work list resolved - a partial increment never flips a goal
- goals/AGENTS.md rewritten for the split (required 4-field header, one detail file per goal, orphan rules covering archive/); root AGENTS.md Child DOX Index + Repo-wide Notes updated; GOALS-archive.md preamble updated
- stale detail-file paths updated to goals/archive/ in src/lib/app-punkscript/punkscript.tcl (comment), runtimebash_wsl.test, wslprobe.tcl and the G-042 detail file; propagated copies (root lib/, src/vfs/_vfscommon.vfs, src/_build) left to refresh via normal build steps
- no project version bump: governance docs and source comments only, no user-visible shell behaviour
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
Harness-agnostic technical project goal system. GOALS.md holds the canonical one-line index with format spec, status taxonomy, maintenance rules, and an agent-authoring workflow so agents asked to 'help me write a goal for X' ask the right questions. GOALS-archive.md is the achieved-goals archive stub. goals/AGENTS.md is the DOX child doc covering naming (G-<id>-<slug>.md), when a detail file is warranted, and the no-orphans/archive rule. goals/archive/.gitkeep tracks the archive dir.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Assisted-by: harness=opencode; primary-model=unknown; api-location=unknown