Tree:
9f56dcb3e8
master
v0.1a
${ noResults }
163 Commits (9f56dcb3e8c4d1c3bac6c707a4a73ecf108f326c)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
72d6815492 |
make.tcl overview: interim single-column layout (cell-wrap revisit noted)
User decision: -choicecolumns back to 1 on both the rich overview and the lean dispatch definition - the long one-line summaries make the two-column layout too wide without table cell wrapping. Revisit -choicecolumns 2 when cell wrapping is implemented; the '## FORM' header-line dropping in the overview cells is accepted. Max render width drops ~250 -> 168 columns. help/colour suites 16/16. punkshell 0.41.2. Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com |
1 week ago |
|
|
157715fadd |
make.tcl: rich top-level help overview (i info style)
User-directed: bare 'make.tcl help' / 'make.tcl' / '-help' now render a per-subcommand overview in the repl 'i info' style - each cell carries the subcommand's one-line summary plus its own auto-generated bracket-notation synopsis line(s) (per-form lines for the multi-form tool/buildsuite), grouped by the existing SUBGROUPS in two columns. Stock punk::args machinery: rich -choicelabels built at lazy resolve time by ::punkboot::argdoc::overview_labels (punk::args::synopsis -noheader per subcommand id, '## FORM' headers dropped for compactness) + -choicecolumns 2, hung on the separate (script)::punkboot.overview id so the label cost (a few ms) is paid only when the top-level help renders - the lean (script)::punkboot definition remains the dispatch surface (now also -choicecolumns 2 for its unknown-subcommand error render) and is deliberately excluded from the capability probe. Plain PUNKBOOT_PLAIN fallback help unchanged. maketclhelp toplevel test updated to pin the overview (tool/buildsuite form synopsis lines, ESC-free); help/colour/bakelist suites 25/25. punkshell 0.41.1. Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com |
1 week ago |
|
|
13dc78191b |
make.tcl: restricted kitname choices + single memoized mapvfs read
User-directed pair completing the declaration-authoritative arc: 1. bake/bakelist kitnames are -choicerestricted 1: the configured kit names + @group selectors (computed into the declaration when the mapping parses at definition time) now GATE at dispatch - an unknown kit is a punk::args choice error before any build (the no-build guarantee moves to the gate), unambiguous prefixes resolve to canonical names, and the dry-run help mirrors the verdict ('help bake punk91 -confirm 0' is now a pointed choice error naming '-confirm' rather than a value-swallow). The handlers' own validation remains the backstop where declarations cannot gate: PUNKBOOT_PLAIN degraded mode, and a definition-time mapping-read failure (the choices clause is omitted entirely - no gate). 2. All kit-mapping consumers share ONE memoized parse per invocation: new punkboot::lib::mapvfs_model front door (locate+parse, keyed by resolved mapfile/rtbase/sourcefolder/target - a PUNK_MAPVFS_CONFIG override keys its own entry) consumed by the definition-time choices (now passing the real bin/runtime rtbase - mapvfs_parse is pure, so the models are interchangeable) and the five handler sites (selective bake, main bake, bakelist, vfslibs %platform% derivation, check smoke listing). Success is cached; a throwing parse deliberately is not, so each caller diagnoses fresh. maketclbakelist.test: unknown-name pins updated to the dispatch choice error + PUNKBOOT_PLAIN backstop variants (runner gains envoverrides); maketclhelp.test: bake dry-run case now pins the choice-gate rejection and 'help bake punk91' acceptance. Full punkexe subtree 114 tests, 0 fail. punkshell 0.41.0. Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com |
1 week ago |
|
|
120ca92b49 |
make.tcl help: pure dry-run + received-args report (G-143 follow-up)
User-directed: the bare-action carve-out is removed - 'make.tcl help
buildsuite build' now falls through to the punk::args diagnosis like any
other incomplete line (exit 1). Empirically the error table carries the
form's argument rows alongside the all-forms synopsis and per-form
reasons, so the diagnosis IS the form documentation and the carve-out
bought nothing but an exit code. Accepted lines gain a one-line
received-args report after the usage table, built from the parse
result's 'received' key (defaulted opts omitted):
'dry-run: line accepted (form build) - action = build | -test = 0 |
toolname = punkzip'. This makes punk::args' value-swallow visible
('kitname = punk91 -confirm 0' for the out-of-order line) - an interim
make.tcl-side clue until punk::args grows an annotated success render.
bake/bakelist kitname -choicerestricted 0 confirmed deliberate
(discoverability-only choices; handler validation authoritative;
define-time mapvfs parse best-effort). maketclhelp.test pins updated;
help/tool/colour suites 20/20. punkshell 0.40.3.
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
|
1 week ago |
|
|
0604d23729 |
make.tcl help dry-runs the supplied command line through the declaration (G-143 follow-up)
User-directed second refinement: 'make.tcl help <subcommand> ?arg ...?'
(and '<subcommand> ?arg ...? -help') now parses the words through the
subcommand's punk::args declaration exactly as dispatch would (form
auto-selection, choice prefixes). An accepted line renders the matched
action's single-form usage ('help tool build -test 0 punkzip', 'help
tool bu'); a rejected line (unknown action, option-first line, unknown
flag in option position) emits the same punk::args noformmatch
diagnosis dispatch gives - all-forms synopsis plus per-form reasons -
on stderr, exit 1: the error table is itself usage documentation, so
help verdicts mirror dispatch verdicts. Carve-out: a bare action
word/prefix renders its form directly, since forms with required
values ('buildsuite build' needs a suitename) would fail a strict
dry-run. Replaces 0.40.1's leading-word-only selection and option-first
whole-usage fallback. Empirical punk::args findings recorded (archived
goal file + probes): flag-like words at/after the first value position
parse as values; -regexprepass/-regexprefail are honoured during form
matching (a '-regexprefail {^-}' value disambiguates flag-led lines -
the punk::auto_exec::hash latent selection ambiguity). maketclhelp.test
pins updated; help/tool/colour suites 20/20. punkshell 0.40.2.
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
|
1 week ago |
|
|
77485434ef |
make.tcl help takes the subcommand's own command line (G-143 refinement)
User-directed reshape of the help-depth interface: 'make.tcl help
<subcommand> ?arg ...?' (and '<subcommand> ?arg ...? -help') now accepts
the subcommand's command line as typed and renders the usage most
specific to it - 'make.tcl help tool build -test 0 punkzip' shows the
tool build form via its leading action word (the same literal-leader
word punk::args form auto-selection keys on at dispatch). Words after
the action are tolerated and ignored; an option-first line falls back to
the whole subcommand's usage; single-form subjects (e.g 'help bake
punk91 -confirm 0') ignore the words entirely; an unknown action word on
a multi-form subject stays a pointed exit-1 usage error. The 0.40.0
numeric form-index acceptance ('help tool 2') is withdrawn as
unintuitive. Probe recorded: the repl 'i' (punk::ns::cmdhelp) tolerates
trailing argument words but does not form-narrow flat multi-form
commands - make.tcl help now exceeds it there. maketclhelp.test pins
updated (12 tests, all green + tool/colour suites); punkshell 0.40.1.
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
|
1 week ago |
|
|
6711302b5c |
G-143 achieved: make.tcl multi-form tool/buildsuite definitions + per-action help depth
tool/buildsuite/help are multi-form punk::args definitions (one @form per action, literal single-choice action leaders + choicelabels): 'help tool' / 'help buildsuite' render one synopsis line per action; 'make.tcl help <subcommand> <action>' - equivalently '<subcommand> <action> -help', or a 0-based form index ('help tool 2') - renders that action's single-form usage; unknown actions and out-of-range indexes are pointed punk::args errors (exit 1). tool dispatch parses through the definition (unknown actions/flags: exit-1 usage errors). User-approved deviation: the declared positional model puts options before tool names ('tool build -test 0 <name> ...'); docs/agent guidance updated to match and a flag-shaped tool name earns a stderr hint; the PUNKBOOT_PLAIN degraded scan keeps the historic flag-anywhere parse. buildsuite driver-arg passthrough unchanged. G-144 consumer follow-through: all 17 per-subcommand @form -synopsis overrides retired (automatic @cmd -name bracket-notation synopses; top-level make.tcl override kept deliberately). Pinned by new punkexe/maketclhelp.test (12 tests); full punkexe subtree green (114 tests, 0 fail). Goal flipped to achieved and archived; punkshell 0.40.0. Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com |
1 week ago |
|
|
543dd1df40 |
G-144 achieved: punk::args auto-synopsis @cmd -name fallback for (script) ids
Auto-generated synopses for (script)-prefixed constructed definition ids now lead with the declared @cmd -name (the invocation name - e.g 'make.tcl modules' for (script)::punkboot::modules) instead of the raw id, across punk::args::synopsis full/summary renders and the usage/arg_error synopsis sections that funnel through them (punk::args 0.12.7 -> 0.13.0). The fallback is gated on the (script) prefix only (user-confirmed narrowing): (autodef) ids are excluded - their id-minus-tag IS the invocation (arg_error's existing tag strip surfaces it) while their @cmd -name is a display label ('destroy', 'Object: ::x'); (shared)/(package)/(default)/(widgetcommand) doc ids declare no invocation-style -name today and render the id as before. Real command ids render byte-identical (full args testsuite passes with no pin updates). Six new synopsis.test pins: (script) full/summary/multiform/ surfaces, no-name constructed id, autodef unchanged, real-id byte-identical. Goal tiers: index entry archived to GOALS-archive.md, detail file moved to goals/archive/ (G-143's pending-tense Related line rewritten to reflect achievement + follow-through pointer: make.tcl's @form -synopsis overrides are now optional, retirement under G-143 or a follow-on edit). Docs: @form -synopsis directive known-case text, synopsis -help, src/modules/AGENTS.md ergonomics bullet. Project 0.39.5 -> 0.39.6 (patch: latent capability, no shipped definition renders differently today). Bootsupport refresh (make.tcl modules + bootsupport): snapshot gains args-0.13.0.tm and picks up two lagging source syncs - mix/commandset::layout 0.2.0 -> 0.3.0, mix/commandset::project 0.4.0 -> 0.4.1, and the shellfilter 0.2.4 G-145 comment; superseded copies pruned. Assisted-by: harness=opencode; primary-model=openrouter/moonshotai/kimi-k3; api-location=openrouter.ai |
1 week ago |
|
|
24bc272c93 |
G-012 achieved: inert VCS-config template payloads + layout gitignore refresh
Layout .gitignore payloads are now stored inert as gitignore.in and
materialized to .gitignore at project generation, ending the
self-censoring-template hazard (live nested .gitignore files silently
untracked template content in git while fossil managed it fine):
- punk::mix::commandset::layout 0.3.0: layout_materialize_renames map;
layout_stage_chain renames inert payloads after composing all overlay
layers (.anti markers keep targeting store names); layout_materialize
withholds the in-place fast path from inert-payload folders so the
store is never renamed; inert+live name conflict errors loudly
- make.tcl thin-layout sync refreshes every vendor/punk layout's
gitignore.in from the canonical repo-root .gitignore (punkcheck-tracked
sync_layouts events); workflow text updated
- the four vintage payload variants eliminated as drift: all payloads
now byte-identical mirrors of root; modpod copy carried and its stale
.gitignore pruned
- materialize.test +5 G-012 characterization tests (25/25; mix subtree
71 pass / 1 known skip)
Verified end-to-end: generation from each affected layout yields a
byte-identical .gitignore (othersample .anti case yields none); root
edits propagate to payloads via make.tcl libs in both directions; the
|
1 week ago |
|
|
15a7e27acb |
G-145 achieved: ansistrip transform drops 'clear' op - remnant-free piped help
The Tcl core delivers 'clear' to a transform stack before EVERY write op
(output-buffer flush-down; tclIORTrans.c ReflectOutput, gated on METH_CLEAR -
intentional and test-pinned, but under-documented: doc/transchan.n and TIP 230
scope clear to seek/read-side buffers). ::punkboot::ansistrip::transchan's
clear handler ran 'dict unset carry $chanid', discarding a split sequence's
held ESC tail at every write-chunk boundary: the next chunk's ESC-less
remainder ('0;1m', '1m') passed through unstripped as orphan fragment text in
piped usage tables, while the dropped ESC bytes kept the G-113 zero-ESC pin
green. The transform is write-only with no read-side state, so its
contract-conformant clear is a no-op - it no longer declares the op, the
per-write calls never fire, and the split-sequence carry survives every chunk
boundary. finalize still drops an end-of-stream partial sequence. No change in
textblock/punk::ansi (pre-transform stream verified well-formed during
diagnosis; exonerated).
Pin: maketclcolour.test gains maketcl_colour_help_tables_zero_remnants -
piped 'tclsh src/make.tcl help' for all 20 declared SUMMARIES subjects plus
bare 'help'/'-help', asserting exit 0, zero ESC bytes, zero orphan fragments
(two-step detector: strip complete sequences, then scan for [0-9;]+m not
preceded by ESC or an open bracket - a raw scan false-positives on ';1m' inside complete
multi-parameter SGR). Failing-first evidence: pre-fix the pin names exactly
the 5 fragmenting invocations (help, -help, help libs, help info, help
bootsupport); the 22-invocation NO_COLOR+PUNK_FORCE_COLOR pre-transform
corpus carries no legit text matching the detector.
Verified (tclsh 8.7a6, win32-x86_64): all 22 invocations byte-level clean;
PUNK_FORCE_COLOR=1 output intact (1177 complete sequences, 0 orphans); the 3
G-113 colour-policy pins pass unchanged; shell/testsuites/punkexe family (15
files, 102 tests) and shell/*** (127 tests) green, warnings pre-existing only;
'make.tcl packages' verified, layout + modpod make.tcl copies synced by the
build (punkcheck-managed outputs batched here per the carve-out).
Bookkeeping: goal flipped active -> achieved 2026-08-01, detail file archived
(goals/archive/G-145-piped-usage-ansi-remnants.md), G-056 Notes gains the
exoneration pointer; src/AGENTS.md colour bullet + src/tests/shell/AGENTS.md
suite description updated; project version 0.39.4 (patch) with CHANGELOG
entry.
Assisted-by: harness=opencode; primary-model=opencode/kimi-k3; api-location=unknown
|
1 week ago |
|
|
a70ddfbdb3 |
G-127 increment 3: kit-location characterization + multi-record name selection fix
- new punkexe/maketclkitlocations.test (PUNK_MAPVFS_CONFIG fixtures, nothing built): two-target one-vfs distinct locations (flat vs kits/<platform>/), same-name two-non-native coexistence without runtime-rename, same-target duplicate keeps <name>_<runtime>; mismatch clause referenced as G-133 regression pin (binaryarch.test + maketclpayloadcheck.test) - mapvfs_match_outputs: a plain kit name now selects ALL matching records (one per target) instead of the first hit - pre-G-127 uniqueness assumption removed; filtered bakelist + selective bake cover every target of a shared name - full punkexe subtree pass: 15 files, 101 tests, 0 failed (4 constraint skips) Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
1 week ago |
|
|
f2649393c0 |
G-127 increment 1: target-keyed kit output split (src/_build|bin -> kits/<platform>/ for non-default targets)
- make.tcl kit loop: per-kit build/deploy dirs keyed by rt_target vs host default (flat locations unchanged for native kits); merged .vfs image, icon/resources sidecar, arch scan, offset probe, smoke probe, release-gate, self-build guard, punkcheck events and final install all follow the per-kit locations (per-tier bin/kits/<platform>/.punkcheck ledger) - duplicate-name guard per (target,name) in kit loop + mapvfs_kit_outputs: same-named kits for different targets coexist; records gain out_tier - bakelist: cross-target rows carry out=kits/<platform>/, detail block prints tiered paths, deploy-state resolves per tier - kit-loop cross-platform TODO retired pointing at G-127 - maketclplatform.test crosstarget pins updated to tiered surface (5/5 pass; maketclbakelist.test 9/9 pass untouched) - LIVE relocation: bake punkshell902 -> bin/kits/linux-x86_64/punkshell902 (valid ELF + sidecar); G-127 Progress section records increment + remaining Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
1 week ago |
|
|
0d80cf6771 |
G-024 + G-115 achieved: mapvfs.toml kit mapping + declarative per-.vfs payloads (punkshell 0.38.0)
G-024 - kit mapping converted to toml (tomlish-parsed), same-day activation->achieved: - src/runtime/mapvfs.toml: [kit.<name>] / [group.<name>] / [scheme.<name>] tables (header comment = user-facing spec). All 12 active line-format mappings migrated (order preserved - identical bakelist rows vs the legacy parse); historical comments carried over; mapvfs.config deleted here AND in the project-0.1 layout (converted to mapvfs.toml there). - make.tcl reader family under the unchanged G-121 model surface: mapvfs_locate (toml > legacy; PUNK_MAPVFS_CONFIG env override = characterization seam), mapvfs_parse dispatching on extension, strict mapvfs_parse_toml, deprecated mapvfs_parse_config fallback (un-migrated generated projects keep baking, with a NOTE; toml wins when both files exist). Shared toml helpers hoisted to punkboot::lib (inline toml_untag copies removed). - Strict entry-named validation: unknown keys/types/schemes, conflicting targets, duplicate outputs, parse failures fatal (exit 3 pre-build). Full-bake unresolvables split by nature: missing vfs folder (repo content) fatal per entry; missing runtime file (environment - part-populated stores are legitimate) entry-named recapped BUILD-WARNING + skip. - Groups: @<group> selection in bake/bakelist, group/default/scheme notes columns + detail lines, groups listed in errors and argdoc choices. verify-ix86 wraps the G-129 kits; bake_default=false excludes entries from full bakes. - G-023 versioned scheme declared live ([scheme.punk8]/[scheme.punk9], group versioned, bake_default=false pending G-023 activation): parse-time expansion from punkproject.toml to punk<gen>-<version> / punk<gen>-dev / release-gated punk<gen>; kit loop creates the plain name when absent and never overwrites it on a normal bake. punk9-dev baked end-to-end; punk9 gate skip demonstrated. - Consumer dedupe fix: several entries may share one runtime on one vfs - kit-output enumeration and the kit-loop runtimes list process each distinct runtime once (latent multiplication in the legacy format, unreachable there). G-115 - declarative .vfs composition with drop-in preservation, same-day activation->achieved: - Sibling declarations src/vfs/<name>.vfs.toml ([payload.<name>]: source, source_root src|packages, target, supersedes, replace) materialized by the new VFSPAYLOAD phase (bakehouse/bake/vfslibs; selective bakes narrow; strict entry-named errors). Drop-in-wins precedence via punkcheck -overwrite synced-targets: undeclared or modified-since-install files preserved and reported (changed-but-preserved NOTE = files_skipped minus sources_unchanged); supersedes/replace are the explicit exceptions; an undeclared .vfs is untouched. - vendorlib_vfs.toml relationship settled: folded/superseded - all six install entries migrated into per-.vfs files for the 13 participating folders (first materialization run reproduced every payload with zero tracked-content change); file deleted; a leftover copy warns and is ignored. - Demonstration kit punkdeclare (group declare-demo, bake_default=false, smokerequire udp+tcllibc): VCS carries only the boot fauxlink; the whole lib_tcl9 payload (tcludp vendor tree + tcllibc consent-gated packages tier) rematerializes from the declaration - clean-tree rebuild smokes pass in-kit, and drop-in survival was proven live (a foreign pkgIndex.tcl and an undeclared note both survived; the foreign file genuinely won until removed, caught by the G-133 smoke probe as designed). Payload ignored in both VCS (.gitignore + derived ignore-glob; ignore-sync verification clean). - Docs: src/vfs/README.md (format + precedence spec), src/vfs + src/runtime + src + bin AGENTS.md, ARCHITECTURE.md (+lint clean), workflow text and summaries/helptexts/argdoc; layout store seeds the convention (vfs README + mapvfs.toml; machinery travels via the established make.tcl sync). Verification: legacy-vs-toml identical kit rows; punkluck86 force-rebuilt under both formats content-identical (identical 1.73MB runtime+stamp prefix, identical 2993-member payloads; whole-artifact byte identity is not a pipeline property - consecutive same-config rebuilds differ in zip timestamp metadata, pre-existing); punkexe suite 98 tests 0 failures incl. 5 new G-024 characterizations (maketclbakelist.test: @group filter + PUNK_MAPVFS_CONFIG fixture tests) and updated pins (payloadcheck declared list + punkdeclare; platform detail wording). Goals: both flipped achieved 2026-07-31 with evidence in the detail files; GOALS.md entries moved to GOALS-archive.md; live-tier reference sweep applied (G-004/G-019/G-023/G-025/G-026/G-035/G-065/G-127/G-131/G-137/G-141) including the G-127 mapvfs-seam retirement note (PUNK_MAPVFS_CONFIG) and a direct G-137<->G-127 bridge replacing the archived G-024 one. Detail files move to goals/archive/ in the follow-up pure-rename commit. Also included as found: the developer's concurrent G-142 goal addition (GOALS.md entry + goals/G-142-punkbin-listing-manifests.md), committed unmodified for git/fossil coherence - not agent-authored. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
1 week ago |
|
|
670ab78dd8 |
G-123 increment 5: consent surface + e2e demonstration + acceptance walk (punkshell 0.36.0)
fetch now surfaces the artifact's build-origin class in its report
("provenance: class=<c>" after sidecar retrieval, table-aware read,
both payloads, re-wrapped, pinned in runtimecmd_provenance.test) -
the acceptance's consent-surface clause.
END-TO-END DEMONSTRATION (live, fully reverted): fixture punkbin
served via httpfixture with a suffixless testplat-x86_64 runtime; the
committed bin/punk-runtime.cmd fetched fakert-suite-r1 (-platform +
-trust-server; sha1 ok, sidecar + provenance line) and 'use -platform'
materialized the working copy; a temporary mapvfs entry wired it to a
bakelist row: runtime file bin/runtime/testplat-x86_64/fakert-suite
(present), target=testplat-x86_64 - with the .exe-named negative half
(runtime=missing) captured first. Config reverted, tier removed, tree
verified clean. Live canonical evidence also captured: unattended
fetch of tclsh9.0.5-punk-r2.exe from the real origin ran gate-free
(published r2 hash matched).
Full battery: provenance 5/5, freshness + checkfile 12/12,
runtimebash_wsl PASS, dtplite 8/8 (after its separate 0.35.1
pre-existing-fallout fix), roundtrip byte-identical under the punk
baseline runner. Acceptance walk recorded item-by-item in the goal
Progress - every item evidence-satisfied; user-gated follow-throughs
(punkbin push + classification review; index Scope ps1-path
correction) recorded as outside acceptance.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
1 week ago |
|
|
643ac3aa37 |
G-123 increment 4: provenance/gate characterization + bare-name sidecar fetch (punkshell 0.35.0)
Payload fix, both payloads (found designing the coverage): fetch only retrieved beside-toml sidecars for -r<N> family names, so a fetched bare-named third-party artifact arrived WITHOUT the retroactive record its class display depends on. fetch now tries the sidecar for ANY name; absence stays tolerated (no-basis degradation unchanged). bin/punk-runtime.cmd re-wrapped. NEW binscripts suite runtimecmd_provenance.test (5 tests, both payload routes, httpfixture non-native tier testplat-x86_64: suite-built -r1 family artifact + bare third-party artifact with a retroactive-style schema-v2 sidecar + a record-less artifact): server-trust gate refusal from the non-canonical origin (canonical url + -trust-server named, no artifact lands), -trust-server flag fetch including sidecar retrieval, PUNKBIN_TRUST_SERVER=1 unattended form, class= tags in list -remote + plain list (third-party tagged, suite-built quiet, record-less untagged), and info schema-v2 fields + provenance_class row with the flat 'class = runtime' ordering-caveat pin and record-row parity between payloads. All green: new suite 5/5; pinned checkfile + freshness 12/12; roundtrip byte-identical under the tclsh9.0.5-punk baseline runner. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
1 week ago |
|
|
bc22def1dc |
G-123 increment 3: punk-runtime server-trust consent gate (punkshell 0.34.0)
fetch - the executable-retrieving act - now gates at entry when the origin is non-canonical (PUNKBIN_URL override): the explicit -trust-server flag or PUNKBIN_TRUST_SERVER=1 env (unattended form) is the acknowledgement, one vocabulary with make.tcl libfetch's gate (G-139). The canonical punkbin origin gates nothing (G-058's unattended tclsfe constraint fetch is unchanged); metadata-only actions (list -remote, platforms -remote) never gate; never an interactive prompt. Refusal wording mirrors libfetch's. ps1: -trust-server is pre-scanned before parameter binding (hyphenated dynamic-parameter names are fragile under the PS 5.1 binder the windows wrap routes through). Trap recorded in the goal Progress: a ps1 comment line must never BEGIN with the word 'requires' - PowerShell parses '#requires ...' as the #Requires statement and fails the whole file (found by the powershell.exe 5.1 smoke). runtimecmd_freshness.test: env seam gains PUNKBIN_TRUST_SERVER=1 + the matching teardown unset (the fixture is a non-canonical origin, so its fetch-driving tests need the unattended acknowledgement) - flagged as a test-contract edit in the goal Progress; every existing assertion unchanged and passing. Gate refusal characterization lands with the increment-4 fixture coverage. Payload growth pushed template label :exit_multishell onto a 512-byte cmd label-scan boundary - checkfile caught it as designed; fixed via a +16-byte spacer line (the documented knob). bin/punk-runtime.cmd re-wrapped. Verification: gate smokes in both payloads (refusal + both acknowledgement forms; ps1 under powershell.exe 5.1); checkfile 0 ERROR; pinned tests all PASS (checkfile + freshness 12/12, roundtrip byte-identical under the tclsh9.0.5-punk baseline runner). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
1 week ago |
|
|
d50115517f |
libfetch characterization test + isolation seams (punkshell 0.32.1)
make.tcl libfetch gains env-only isolation seams - PUNK_LIBFETCH_CONFIG (alternate declarations file) and PUNK_LIBFETCH_PACKAGES (alternate tier root), the PUNK_RUNTIME_PLATFORM idiom - so fixture/mirror runs never read the real declarations or write the real bin/packages tier. Neither seam bypasses the -trust-server consent gate. New shell/testsuites/punkexe/maketcllibfetch.test (piped maketcl* harness + testsupport/httpfixture.tcl + a file:// mirror; the canonical origin is never contacted) pins the G-139 behaviours that previously had only manual session evidence: the server-trust gate refusing non-canonical origins with exit 3 before any network access or tier write, -serverurl-over-PUNKBIN_URL precedence, consented fetch/verify/materialize (sha1sums + zip + sidecar + installed-shape tree with embedded record), idempotent re-run vs -force, declared-revision-change re-materialization keyed to the tree record (with the sidecar-not-listed note lane), sha1-MISMATCH rejection without residue, missing-from-server-sha1sums failure, and the no-config no-op. 8/8 pass in both runner modes (singleproc + -jobs); full punkexe subtree green (93 runnable, 0 failed); the real bin/packages tier verified untouched. Also refreshes the stale src/runtime/libpackages.toml header (r1 IS published as of 2026-07-30; the G-139 reference now points at the archive) and documents the seams there and in the libfetch help text. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
1 week ago |
|
|
4aae330b31 |
G-134 achieved: flip, archive record - archive-relative output is a checked contract; punkshell 0.30.7
Implemented and achieved same day. punkboot::utils 0.6.0 gains kit_offsetstyle_report (argdoc'd thin classifier over punk::zip::archive_info), synced via modules + bootsupport (one stale dead-pid .punkcheck.lock removed per the recorded recovery) and promoted into _vfscommon. make.tcl: guarded getter, post-assembly probe beside the smoke-require block (recapped BUILD-WARNING only on a FILE-relative attached payload; plain/none/unreadable silent; NOTE on stale bootsupport), and the 'check' row (ACTIVE (advisory) + contract lines). Characterization: offsetstyle.test 7/7 (mkzip -runtime/-offsettype hermetic fixtures for plain/archive/file, none on text + metakit-magic binary, unreadable detail, src/_build baseline sweep - no kit image probes file); maketcl_check_offsetstyle_pin added (payload-check suite 4/4). Full utils suite 69/69, punkexe suite 81/0, live punkluck86 bake silent as the acceptance's baseline clause requires. Docs: src/AGENTS.md pin bullet with does/does-not-guarantee, bin/AGENTS.md deployed-kit section, ARCHITECTURE.md check-family bullet (architecture_lint clean). Reference sweep: no live-tier references beyond the index entry; goals_xref shows no pairs bridged solely by G-134. Archive move follows as a pure-rename commit. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
0e0a64eb23 |
punk-runtime fetch: materialization hint when the working name is absent; punkshell 0.30.4
Closes the observed UX gap (G-128 detail, program-files checkout findings): fetch reports an active runtime, but bakes reference the suffixless WORKING name that only 'use' materializes - so a first fetch left bakelist reading runtime=missing with nothing pointing at the next step. Both payloads (ps1 + bash, parity wording) now print note: bakes and projects reference <working> - materialize it with: punk-runtime use <artifact> after fetching an -r<N> artifact whose working name is absent, and stay silent once it exists (the downloads-never-bind rule is unchanged - fetch still materializes nothing). Sources edited under src/scriptapps/bin and bin/punk-runtime.cmd regenerated via scriptwrap multishell (-force 1; checkfile ERROR-free, 4 normal possibly-bogus warnings) - committed together per the wrap workflow; runtimecmd_roundtrip byte-identity passes. New pin runtimecmd_fetch_materialize_hint in runtimecmd_freshness.test (11/11, ~+5s: hint present on both payloads via the fixture server, absent after use via the cmd route). Live-verified against the real punkbin server from the spaced test checkout: hint fires on the no-download path too, silent with the working copy present. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
f2530d53c3 |
G-128: spaced-path characterization test; goal records for the program-files checkout findings
punkres.test gains punkres_spaced_paths (8/8, ~3s file total): the store
fixture copied into a directory AND filename carrying spaces, stamped with
the consent flag and read back byte-identical - characterizing the Tcl-list
exec quoting the seam relies on (kit_icon_embed_punkres builds its command
with list/lappend and evaluates it via catch of a pure list: word-per-element,
no {*} needed, no re-substitution).
Goal detail records the live evidence from the user's test checkout at
'C:/repo/jn/program files/punkshell': bake punk9_beta there embedded via
punkres with every path spaced (kit wears PUNKSHELL, boots, bakelist
deployed=current), punk-runtime.cmd fetch/use polyglot fine under spaces,
tool build via PUNK_ZIG override; plus the runtime-store finding - fetch
downloads only the -rN artifact, materialization of the mapvfs-named working
copy needs 'use <full-artifact-name>' (suffixless use selects existing
runtimes only), bakelist reads runtime=missing until then - with candidate
UX improvements flagged for the user.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
5e9f1c75fc |
G-128: seam selects punkres when built; characterization tests; punkshell 0.30.1
src/make.tcl kit icon seam (G-057): mechanism selection is now punkres-first - kiticon::punkres_available (memoized; binary presence at bin/punkres(.exe) is the selection signal) + kit_icon_embed_punkres (exec wrapper; punkres verifies its own output). twapi arm unchanged as fallback; when NEITHER serves the skip notice combines both reasons and names the 'make.tcl tool build punkres' remedy. Sidecar embedding value gains 'punkres' (bin/AGENTS.md format doc, ARCHITECTURE.md kit-icon bullet updated; architecture_lint clean). Live-bake fallback matrix on punkluck86 (win32-ix86 = PE32 arm live): punkres present -> embedded via punkres, kit boots + smoke OK; punkres absent + twapi loadable -> via twapi; both absent -> unavailable with combined notice, embedding none (exact pre-G-128 degradation). Live parity: both arms' baked kits listing-identical (codepage host-ACP noise finding recorded in the goal detail) with byte-identical extracted icons. New src/tests/shell/testsuites/punkexe/punkres.test (7/7 under the tclsh9.0.5-punk runner; self-gates on bin/punkres + store fixture): overlay- unsafe refusal exit 3 with untouched input, consented file-relative shift with convention preserved, payload intact via punk::zip members + crc-verified extraction, icon replaced (extract-ico == punkshell.ico), idempotent re-stamp byte-identical, make.tcl tool info punkres provenance records. Full punkexe suite 83 tests 0 failed (no collateral). Goal detail: Notes findings (codepage noise, root-vendorlib twapi fragility, nested tclsfe payload, metakit move-safety -> G-101 pointer updated) + Progress increment 1 with the two remaining acceptance items (non-windows-host e2e, punkbin publication route) and one acceptance-wording flag for the user (metakit 'kit' shape vs 'zip overlay' clause). punkshell 0.30.1 + CHANGELOG. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
03306be068 |
argparsingtest 1.3.0: opt, cmdline and tepam are optional, not module-level requires
The module hard-required opt, cmdline and tepam at load time, so on a punkshell build
without tcllib 'package require argparsingtest' died outright with "can't find package
opt". A harness whose whole job is comparing parser libraries is useless precisely on the
runtime you wanted to measure, and the module already had the right pattern for this:
argp, parse_args and argparse degrade to a not_loaded row rather than taking the module
down with them. The three tcllib parsers were the odd ones out. Reproduced before the
change with punk module paths only and an emptied auto_path, which is where tcllib's
pkgIndex-based packages come from.
Every parser this module compares is now optional. Their roster entries become
{optional opt}, {optional cmdline} and {optional tepam}, so discover_parsers reports
not_loaded when the package is absent and nothing in the harness calls them. punk::args
and Tcl 8.6- remain hard requires - the harness itself is built on those.
The guard differs by package because the dependency does:
cmdline is only ever called INSIDE proc bodies, so the catch-guarded require at the top
is the whole story - the wrapper procs stay defined and are simply never invoked.
opt and tepam are used at DEFINITION time: tcl::OptProc and tepam::procedure are the
commands that create the wrapper procs. Their seven definition sites (four opt, across
opts/tkstyle/tclstyle/sandwich; three tepam) are each additionally guarded, so with the
package absent the proc does not exist at all.
Those sites test 'package present' rather than wrapping the definition in a bare catch.
Both tolerate absence, but a presence test still lets a genuine error in a spec raise
loudly on a runtime that does have the package, where a catch would swallow it. The
pre-existing argp registration site keeps its original catch idiom - working code, not
part of this change.
Pinned by module_loads_without_optional_parser_packages: a child interp with an emptied
auto_path that asserts the module loads, that each absent package's parser reports
not_loaded, and that the opt and tepam wrapper procs genuinely do not exist. Where a
runtime supplies one of the three as a .tm on a module path the test degrades to
asserting the module still loads, which is the main claim anyway.
Tests that name parsers explicitly (first_call_library_backed, first_call_positional_styles,
sandwich_strictness) now filter through a loaded_parsers helper, and the tclstyle
cmdline_typed status assertion derives its expectation from package presence: those
parsers can now legitimately be missing.
Verification: 26/26 pass under the 32-bit luck-test2 runtime with no skips, 24 pass +
2 skip under native Tcl 9.0.3. With opt and tepam hidden, the built 1.3.0 module loads,
reports both as not_loaded, and compare lists them in its "not loaded:" footer instead of
the whole module failing to load.
Claude-Session: https://claude.ai/code/session_01Q82VuBXzgeKsAwMYHrbpP1
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
|
2 weeks ago |
|
|
df6642e189 |
punk::zip 0.3.0: punkzip extraction accelerator + parity suite (G-126); 0.28.4
The final G-126 acceptance clauses:
- punk::zip::accelerator (auto|none|<path>): auto probes
env(PUNKZIP_EXE) then a punkzip beside [info nameofexecutable];
resolution cached until reconfigured
- unzip hands whole-archive member WRITING to the accelerator only when
the call is one it serves identically (globs {*}, no excludes,
default -overwrite/-mtime/-verify, ascii member names) and re-stamps
mtimes with punk::zip's local-time convention afterwards, so the two
engines produce identical trees; preflight refusals, member selection
and the returned names always come from punk::zip's own reader (the
G-124 floor, unchanged); accelerator failure falls back to pure Tcl
silently; last_unzip_engine/last_accelerator_note expose the per-call
decision
- parity suite zipaccel.test (9 tests): identical names, bytes and
mtimes through both engines over the G-124 shapes and whole-kit
extraction of the file-relative tclsh90b4_piperepl.exe (841 members);
listings engine-independent; punkzip porcelain agrees with punk::zip
member dicts on every shared field (mtime excluded by design - UTC vs
local convention); pure path proven when the binary is absent;
selective calls proven to run pure. Implicit directories (kits store
no dir entries) are excluded from mtime comparison - neither engine
stamps them
- recorded benchmark (in the goal detail): accelerator fixed cost
~9-13ms, crossover ~15-20 members, material (>= x1.7) from ~50;
x2.3-2.6 at kit scale under a native tclsh and x3.8-4.9 kit-hosted
(punk91.exe 21.9s -> 5.7s) - the bake-from-kit case the goal
motivated
- full runtests at recorded baseline under tclsh9.0.5-punk: 1186/1211,
1 failed = the pre-existing exec-14.3 baseline
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
91d3594570 |
punkcheck 0.6.1: installtrack self-heals damaged persisted event history
Field failure (2026-07-27, second dev machine): 'make.tcl bake
punk9_beta' died in the vfslibs phase with
eventcollection ... key '$eventid' already exists in collection
because that machine's src/vfs/.punkcheck predates punkcheck 0.3.2.
The 0.3.2 note fixed the WRITER (a braced template wrote the literal
strings '$eventid' etc into event headers) but files written before it
keep the damage, and the modern installtrack constructor - which
reloads persisted events into a collection keyed by -id - collided on
the duplicate literals and aborted the whole bake.
- punkcheck 0.6.1: the constructor reload now self-heals instead of
aborting: an EVENT record with a missing or duplicate -id is
reconstructed under a synthesized unique id ('damaged-id-...') with
a stderr warning naming the file and the offending id. Synthesized
ids match no INSTALL record's -eventid reference, so healed events
age out through normal -keep_events pruning. Reload also tolerates
missing -source/-targets keys.
- oolib 0.1.4: the collection duplicate-key error no longer misnames
the object as 'col_processors' (stray copy-paste in the generic
class).
- regression test installtrack_damaged_event_history_selfheal seeds a
real two-event file, rewrites both -id values to the braced literal
{$eventid} (as the damaged files carry it - the record loader
evaluates records, so only a braced literal survives as the string),
and asserts the reload succeeds with both events kept under distinct
keys (one healed). Suite: 30/30.
- before/after proof against the released artifacts: punkcheck 0.6.0
(exact-pinned) reproduces the field abort on the crafted file;
0.6.1 heals it. Bootsupport promoted to punkcheck-0.6.1 + oolib-0.1.4
(superseded copies pruned), so make.tcl bakes get the fix.
Remedy already applied on the affected machine (file deletion); with
this fix, remaining old .punkcheck files anywhere self-heal with a
warning instead of failing builds.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
d76a7907ea |
make.tcl tool subcommand: build vendored zig tools into bin/ (G-126); 0.28.3
New surface for the vendored first-party build tools under src/tools:
make.tcl tool list|info|build|test ?<toolname> ...? ?-test 0|1?
- discovery is convention-based (a src/tools directory carrying
build.zig is a tool), so the G-128 tool will appear with zero
make.tcl edits; per-tool records are read tolerantly from
build.zig.zon (version, minimum_zig_version floor) and PROVENANCE.md
(upstream, vendored commit)
- list/info report installed-binary state (current|stale|absent vs
bin/<name><exe-suffix>) and the resolved toolchain
- toolchain resolution: PUNK_ZIG=<path> overrides; otherwise
bin/tools/zig* is scanned and the LOWEST release satisfying the floor
wins - deterministic as newer toolchains get unpacked beside the
pinned one; dev builds count only when their base version exceeds
the floor
- build runs the tree's own 'zig build test' as an EXIT-CODE gate
(expected stderr warnings do not fail it), then builds ReleaseSafe
and installs to bin/; nothing installs when the gate or build fails;
-test 0 skips the gate; build caches are deliberately left in place
between runs for rebuild speed (git- and fossil-ignored)
- zig stays OPTIONAL: packages/bake never require the step; without a
suitable toolchain, list reports the state and build/test exit
nonzero with bin/punk-getzig.cmd guidance
- full subcommand accompaniments per src/AGENTS.md: punk::args argdoc
(SUMMARIES/HELPTEXTS/bespoke passthrough definition), SUBGROUPS
("vendored tools"), known_commands, degraded-mode dispatch, plain
help text, bootsupport-staleness exemption, workflow text (new
OUT-OF-BAND SUBSYSTEMS section also covering buildsuite), project
version 0.28.3 + CHANGELOG entry
- piped characterization (zig-independent):
src/tests/shell/testsuites/punkexe/maketcltool.test - 4/4 green
- verified live: 'tool build punkzip' gated on the vendored tree's
130/130 suite and installed bin/punkzip.exe (ReleaseSafe, v2.3.1,
1.1MB) over the stale Nov-2024 v2.1.0 binary; list state flipped
stale -> current; PUNKBOOT_PLAIN degraded dispatch and tabled help
verified
G-126 Progress updated: the acceptance's build-step clause is
satisfied. Remaining: punk::zip fast path, parity suite, benchmark.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
583dd5e0b2 |
G-133: bake payload/target consistency checks - advisory arch scan + smoke-require probe
- punkboot::utils 0.5.0: binary_arch_classify (PE Machine field, ELF e_machine,
Mach-O thin+universal - honest unknowns), platform_expected_binary,
platform_discriminated_segment (canonical <os>-<cpu> tokens + vendor spellings,
extensible namespace variables), vfs_binary_arch_report (per-directory exemption,
exempt subtrees counted unread)
- make.tcl: advisory binary-arch scan at the G-125 gate seam (recapped
BUILD-WARNINGs naming file/found-arch/kit-target, capped at 8 per kit with honest
total; cross-target kits included); post-build smoke-require probe running the
freshly built artifact via its tclsh subcommand with drained stdin (failures
recapped naming kit/package/actual error; cross-target skip with stated reason;
undeclared kits run nothing new); mapvfs.config entries accept a 5th
smoke-require element (mapvfs_parse/mapvfs_kit_outputs carry smokerequire);
'check' reports scan ACTIVE/UNAVAILABLE + declared smoke matrix; workflow K11
- mapvfs.config: smoke-requires declared - punkluck86 {Thread} (the 2026-07-27
incident construction), punk91ix86 {Thread iocp}, punkshell902 {Thread}
(cross-target skip demonstrator)
- tests: binaryarch.test (generated header fixtures only - no committed binaries;
punkluck86 case reproduced; iocp pair + win-x64 exemptions; real-tree sweep with
known-real findings filtered), maketclpayloadcheck.test (piped check
characterization, ESC-free per G-113)
- docs: src/AGENTS.md + bin/AGENTS.md state what the checks do and do NOT
guarantee; src/runtime/AGENTS.md entry grammar; ARCHITECTURE.md bake section
- REAL FINDING on the scan's first sweep: zint.dll 2.13.0 in punk8win.vfs
lib_tcl8/ is 32-bit (PE i386, confirmed with file(1)) and can never load in the
x64 tcl8 kits punk86/punkbi/punksys that carry it - those bakes warn until the
payload is fixed
- punkshell 0.28.2
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
191d8ff490 |
G-129: kit boot derives its payload mount from the runtime's mount table (punkshell 0.28.0)
Boot (punk_main.tcl + project_main.tcl, identical copies):
- zipfs presence keys on tcl::zipfs::mount - present in every supported zipfs
generation - not tcl::zipfs::root (8.7/9-era; absent from the androwish/
undroidwish 8.6 backport, whose ::zipfs ensemble also lacks a root subcommand).
- New factored ::punkboot procs (zipfs_mount_pairs, zipfs_kit_mountbase,
path_within) derive where this executable's attached archive actually mounted:
the mount-table entry whose archive file is [info nameofexecutable] (the
backport reports it without the windows drive prefix - handled), fallback the
mount containing the boot script. //zipfs:/app stays the expected modern
answer, not an assumption. Procs remain defined post-boot for tests.
- A mounted archive that cannot be attributed to the executable is reported on
stderr instead of silently configuring no internal paths (the old failure shape).
- The starkit quick-search line [zipfs root]/app/tcl_library (an error on the
backport) uses the derived base; internal_paths gains the derived base when no
zipfs volume root covers it; the internal-only simulate-kit branch recognises a
script under the derived mount as kit-internal.
make.tcl (necessary companion fixes - Scope extension flagged in the goal file):
- Runtime capability probe keys has_zipfs on tcl::zipfs::mount (was root, which
refused zip assembly for the backport; the block also rode a body-less
'if {![catch ..]}' that only worked because piped-stdin tclsh continues past
command errors).
- merge_over resolves relative fauxlink targets against the link file's own
directory (the fauxlink module's symlink semantics) - identical for the
pre-existing root-level links, required for the new nested one.
Payload + matrix:
- punk8win.vfs gains an app/main.tcl fauxlink beside root main.tcl: the
undroidwish family auto-runs app/main.tcl INSIDE the attached archive
(embedded /app/main.tcl string in the exe) and ignores a root main.tcl.
Inert in the metakit kits sharing the payload (punksys/punk86/punkbi verified).
- mapvfs.config: punkluck86 (tclsh8.6.10-luck-zip) + punk91ix86
(tclsh9.1b0-tclsfe), both zip kits targeting win32-ix86.
Tests + docs:
- New shell/testsuites/punkexe/kitmountpoint.test (4 tests): backport exe-path
attribution, modern-32 //zipfs:/app, baked punkexe regression pin,
unattributed-mount stderr report + no foreign paths. Self-gates on the
untracked verification runtimes.
- bin/AGENTS.md "Kit-wrappable runtime requirements (G-129)" + src/AGENTS.md
pointer, src/vfs/AGENTS.md boot contract, src/tests/shell/AGENTS.md suite doc,
ARCHITECTURE.md boot-chain bullet.
- Thin-layout + templates-modpod copies synced (make.tcl modules; _config boot
mains refreshed into the project-0.1 store layout per the
|
2 weeks ago |
|
|
20ee103120 |
boot-precondition gate learns the exe-path-mount tcl library convention (punkshell 0.27.2)
The G-125 gate refuses a kit whose merged .vfs supplies no tcl library. It knew two conventions - tcl_library/ for zipfs-attached kits and lib/tcl<major>.<minor>/ for starkit-style ones - which covered all ten kit trees this project builds. A third-party runtime under evaluation (Lean Undroidwish Construction Kit, 32-bit windows, Tcl 8.6.10) uses a third: its attached archive mounts at the EXECUTABLE'S OWN PATH rather than at //zipfs:/app, so [info library] is <exe>/tcl8.6 and the library sits at tcl8.6/ in the root of the tree. The gate reported that runtime unbootable - a false refusal on a directory that is unmistakably a complete Tcl library (auto.tcl, clock.tcl, encoding/, history.tcl, init.tcl, package.tcl ...). Found while investigating whether our bake infrastructure can handle that kit; the androwish/undroidwish zipfs backport for 8.6 mounts this way generally, so it is a family of runtimes, not one artifact. punkboot::utils 0.3.0 -> 0.4.0 adds tcl<M>.<m>/ at the vfs root as a third recognised location; the report's 'checked' list and the not-found reason name all three, as do 'make.tcl check' and the workflow K10 key note. Glob note worth keeping: the root tcl[0-9]* pattern also matches the tcl8/ and tcl9/ MODULE trees this project's own kits carry. They hold no init.tcl, so the existing qualification test rejects them without needing a narrower pattern - now pinned by bootlib_module_tree_not_a_library so a later tightening of the glob has to argue with a test rather than look like an obvious cleanup. Verified: the LUCK runtime's extracted tree now reports ok=1 locations=tcl8.6, and all ten assembled src/_build/*.vfs trees still pass with unchanged detected locations (tcl_library for the six zipfs kits, lib/tcl8.6 for punk86/punkbi/punksys, lib/tcl9.0 for punkshell902). Full suite 1167 tests, 1146 passed, 1 failure - core/tcl exec-14.3, the documented baseline. One of the gate's own punkexe pins failed first time round and was right to: re-wrapping the 'check' report split "...that / cannot initialise" across lines. The pattern now matches across the break rather than the assertion being loosened. Note this does NOT make such a runtime bakeable yet - src/vfs/_config/punk_main.tcl still probes zipfs with 'info commands tcl::zipfs::root' (a 9-era command the 8.6 backport lacks) and assumes the //zipfs:/app mount point, so a kit built on it would not find its own payload. That is separate work; this change only stops the gate refusing a tree that has a perfectly good library. Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com |
2 weeks ago |
|
|
ec781d7019 |
punk::libunknown 0.2.3: pkgIndex.tcl scripts run in the global namespace again (punkshell 0.27.1)
A third-party 8.6 kit under evaluation (Lean Undroidwish Construction Kit, 32-bit windows)
could not load its own bundled twapi 4.7.2 inside punkshell:
P% package require twapi
invalid command name "twapi::set_scriptdir"
("package ifneeded twapi 4.7.2" script)
twapi's pkgIndex.tcl defines 'namespace eval twapi { proc set_scriptdir ... }' when the
INDEX is sourced, and its ifneeded script calls that command at require time. The command
existed - as ::punk::libunknown::twapi::set_scriptdir. punk::libunknown 0.2.0 moved index
sourcing out of 'namespace eval ::' into source_pkgindex, a proc of the punk::libunknown
namespace, to stop each index's helper variables leaking into the global namespace and to
stop a user global named 'dir' being clobbered. That fixed the frame, but a proc body
executes in ITS OWN namespace, so an index's RELATIVE 'namespace eval foo' started
creating ::punk::libunknown::foo instead of ::foo. Stock tclPkgUnknown is a proc in ::,
so indexes have always had global resolution; the ifneeded script, evaluated later at
global scope, then looked for a command that was never there.
The body now runs via apply with :: as its namespace argument, which gives both
properties at once: a local frame (index helper variables still discarded, user 'dir'
still safe) and the global resolution context indexes are written against.
Not twapi-specific: any index that defines commands or namespaces at source time for its
own ifneeded scripts to use hits this, and the pattern is common in third-party indexes.
punkshell's own vendored twapi 5.0b1 happens to avoid it (self-contained 'apply' ifneeded
scripts), which is why the tree never surfaced it.
Verified on the LUCK 8.6.10 runtime end-to-end - 'package require twapi' at the punkshell
prompt now returns 4.7.2 with ::twapi::scriptdir correctly set - and pinned generically by
pkgindex_relative_namespace_is_global in the discovery suite, whose new fixture copies
twapi's pattern so no third-party kit is needed. The pin was proven to bite: driven
against the pre-fix body the same fixture fails with 'invalid command name' and leaves
::punk::libunknown::pklu_nsindex behind; against 0.2.3 it resolves and leaves nothing.
Full suite 1165 tests, 1144 passed, 1 failure - core/tcl exec-14.3, the documented
baseline.
Manual-version bump per src/modules/AGENTS.md: file renamed, Meta line, manpage_begin and
provide-block updated, version-history line appended. The rename sweep converted the two
goal Scope references (G-035, G-109) from the exact filename to the glob form
src/modules/punk/libunknown-*.tm that GOALS.md's own Scope-authoring guidance recommends,
so the reference stops drifting at every bump.
Also records in G-035 the mechanism behind its "avoid mixing .tm and pkgIndex.tcl
provision" folklore, which this investigation identified (non-contract Notes). Stock
::tcl:™️:UnknownHandler returns early when $satisfied is set and therefore never falls
through to ::tclPkgUnknown, so a require satisfied from a .tm suppresses the whole library
scan. Measured with a synthetic fixture on both 8.6.10 and 9.0.3: with mixpkg 1.0 as a .tm
and mixpkg 2.0 in an auto_path library under 'package prefer latest', stock returns 1.0
and reports only 1.0 from 'package versions', runs no index side effect and registers no
sibling package; the libunknown chain returns 2.0 and does all three. libunknown already
neutralises it - its handler still computes $satisfied but the early return is commented
out - and that unconditional fallthrough is exactly what the epoch cache pays for. The
folklore is therefore substantiated for stock Tcl with a named failure mode (silent
older-version selection) and neutralised under the punkshell chain, with stock behaviour
still reachable in any interp that has not run punk::libunknown::init.
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
|
2 weeks ago |
|
|
b7c632b670 |
G-125 achieved: a kit that cannot boot is not deployed (punkshell 0.27.0)
The kit machinery already knew when it had failed to extract anything from a source
runtime, and under G-122 that notice became a recapped BUILD-WARNING - but the build
still assembled an artifact, DELETED the deployed kit and copied the new one over it,
closing running instances of the kit first. Field-observed 2026-07-26: an msys2-hosted
bake of punk91 produced a 49,501,792-byte bin/punk91.exe that failed at startup with
"application-specific initialization failed: Cannot find a usable init.tcl", by which
point the previously working kit was already gone. G-124 removed the particular cause;
this removes the class. A build tool should not make a working executable worse.
A bake now refuses any kit whose merged .vfs supplies no tcl library: the kit is listed
under FAILED KITS with a reason naming the cause and NOTHING is written - no
src/_build/<kit>, no deploy, and the previously deployed bin/<kit> is left byte-identical.
The gate sits immediately after the _vfscommon.vfs + <kit>.vfs merges and before the
kit-type assembly switch, the last point at which no build product exists; a refusal
appends to failed_kits, ends the punkcheck event FAILED and continues, so the punkcheck
records stay consistent with what is on disk. The merged src/_build/<kit>.vfs tree is
deliberately left behind - it is the evidence for the refusal.
It gates on the BOOT PRECONDITION, not on the extraction step having run. Some .vfs
folders legitimately supply their own tcl library (src/vfs/punk8_statictwapi.vfs,
punk9test.vfs and mkzipfix.vfs do today), and those must keep building - so the check
reads the merged tree. It is structural and executes nothing, which also makes it valid
for cross-target kits this host could never run, and costs 0.63ms per kit (measured over
200 iterations against the real src/_build/punk905.exe.vfs), so it runs unconditionally.
The predicate is punkboot::utils::vfs_boot_library_report (0.2.0 -> 0.3.0), called through
a guarded require modelled on the existing get_src_provenance_warnings: a stale or missing
bootsupport snapshot degrades the gate to a NOTE rather than failing every kit. Both
branches were observed live - before the bootsupport propagation 'make.tcl check' reported
UNAVAILABLE, after it ACTIVE. Scope was extended at activation (user-approved) to put the
predicate in that module rather than private to the build script, because a gate that
cannot be exercised cannot be characterized, and punkboot::utils is already where
make.tcl's provenance gate helper lives.
What qualifies as a tcl library: tcl_library/init.tcl (zipfs-attached kits) or
lib/tcl<major>.<minor>/init.tcl (starkit-style), AND at least one companion file beside it
(tm.tcl, package.tcl, auto.tcl, clock.tcl, history.tcl, word.tcl) or an encoding/
directory. The companion test is load-bearing: every punkshell kit carries
lib/BWidget1.10.1/init.tcl, so a check that looked for any init.tcl anywhere would pass a
kit with no tcl library at all. lib/tcllib2.0 is correctly not matched by the lib/tcl[0-9]*
glob. Verified against all 10 assembled trees in src/_build - both conventions are
represented (tcl_library for punk902z/punk905/punk91/punk9_beta/punk9bi_beta/punkmagic,
lib/tcl8.6 for punk86/punkbi/punksys, lib/tcl9.0 for punkshell902).
The no-extraction BUILD-WARNING was reworded from "will not initialise unless src/vfs/<x>
supplies one" - a consequence the build then ignored - to "will FAIL the boot-precondition
gate unless src/vfs/<x> supplies one". It stays a warning rather than becoming the failure,
because a .vfs that supplies its own library needs no extraction.
Verified 2026-07-27 end-to-end against a temporary fixture kit (a mapvfs entry pointing a
zip kit at a payload-free runtime, plus a vfs with no tcl library), with sentinel files
standing in for a previously deployed kit and a previous build product. Across the failing
run bin/punkgatefixture.exe (sha1 2a0700eb...) and src/_build/punkgatefixture.exe (sha1
12c50567...) were byte-identical with unchanged mtimes, and the kit was reported under
FAILED KITS with the cause named. Adding tcl_library/{init.tcl,tm.tcl} to that same fixture
vfs - extraction still yielding nothing - made it build and deploy normally, which is the
other half of the criterion. The fixture was removed afterwards and mapvfs.config restored
byte-identical to its backup. Real-kit bake through the gate: punk905 builds, deploys and
boots.
Characterization: 12 tests in modules/punkboot/utils/testsuites/utils/bootlibrary.test
(both conventions, the companion-file requirement and its BWidget decoy, near-miss
reporting, missing/empty trees, and a sweep asserting every assembled src/_build/*.vfs
tree still passes so the gate cannot fail kits that boot today) and 2 in
shell/testsuites/punkexe/maketclbootgate.test (the ACTIVE/UNAVAILABLE report, ESC-free per
the G-113 piped policy). Existing punkexe suites pass unchanged.
Documented in src/AGENTS.md with the remedy when a kit is refused, in ARCHITECTURE.md
beside the provenance gates, and in the embedded 'make.tcl workflow' data flow as key note
K10 (verified under the default and PUNKBOOT_PLAIN=1 paths, within the 100-column budget).
The achieved flip archives the entry and the detail file, and sweeps the live tier: G-127
(its output location inherits the never-written guarantee as long as the gate stays
upstream of the artifact write, and its payload/target mismatch reporting should share this
vocabulary), G-028 (the sibling "why bin/<kit> was not updated" surface in the same deploy
step) and G-101 (a new container type must land its library where the gate looks, or extend
the location list).
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
|
2 weeks ago |
|
|
4bd0ab1354 |
argparsingtest 1.2.0: parse_args/argparse timing wrappers, plus a sandwich calling style
compare's tables listed parse_args and argparse under "not loaded:" on the one runtime
carrying both - bin/runtime/win32-ix86/tclsh8.6.10-luck-test2.exe (argparse 0.61,
parse_args 0.5.1). Neither was missing. Both sat in optional_externals, the probe-only
list whose entries can never be better than not_wrappable, and compare bucketed
not_wrappable into the same footer line as not_loaded - so a package that was present and
working read as absent.
Timing wrappers now exist for both, and they move out of optional_externals into the
style rosters under a new {optional <pkg>} marker that generalises the former hardcoded
argp case: loaded when the package was present at module load, not_loaded otherwise.
getopt and cmdr stay probe-only. compare now reports not_wrappable separately - a
"no timing wrapper:" table line, and a not_wrappable key in the dict and json forms - so
the two conditions cannot be conflated again.
Availability is per-runtime and the two do not travel together (surveyed 2026-07-26): the
32-bit luck-test2 kit has both, the native Tcl 9.0.3 install has argparse only, punk902z
and punk91 have parse_args only, punk905 has neither. The tests constrain them separately
for that reason.
Style support was measured rather than assumed. argparse reaches tk style only via -mixed
(its default mode rejects leading positionals as excess arguments) and its switches need
an explicit -argument in the element spec or their values fall through as positionals.
parse_args cannot consume leading positionals at all, so tkstyle parse_args is
unsupported. Both wrappers call their library by fully qualified name: the procs
deliberately share the package name, so an unqualified call would resolve to the wrapper
itself - infinite recursion in argparse's case.
The fourth calling style, sandwich, is 2 mandatory leading positionals, THEN the 10 keyed
options, THEN 3 mandatory trailing positionals. The 2/3 split is asymmetric on purpose -
an even split could be satisfied by a parser that merely halves the positional block. All
three candidates support a valueless flag, so the argvec exercises -join as a solo flag
alongside the -flag value pairs. Wrappers: manual_switch, punkargs, punkargs_by_id,
punkargs_parsecache, opt and argparse, returning {{p1 p2} {p3 p4 p5} optsdict} - grouped
rather than the flat {p1 p2 opts} of the other positional styles, because positionals now
sit on both sides of the options.
punk::args and opt model that arrangement - @leaders/@opts/@values are three separate
sections, and tcl::OptProc fills positional slots in declaration order - and both reject
options placed ahead of the leaders, as does the hand-rolled baseline. argparse reaches
the style only through -mixed, which permits switches ANYWHERE, so it parses the argvec
correctly without being able to enforce it: the identical spec also accepts all five
positionals trailing. It is timed for the parse, not credited with expressing the
constraint, and both halves of that are pinned by tests (sandwich_strictness,
sandwich_argparse_is_permissive) rather than left as a silent difference. Its flag
convention differs too, opts being reported in each parser's natural form: a supplied
bare flag yields an empty-string value and an omitted one is absent from the dict, where
the others report -join as 1 or 0.
cmdline, tepam, argp and parse_args are unsupported N/A rows in this style, each verified
to fail on its argvec. cmdline is the one worth naming: cmdline::getoptions returns
WITHOUT error having parsed nothing at all - every option left at its default and the
whole argument list untouched - so a check that only looks for a raised error would
wrongly credit it.
Verification: 25/25 pass under the 32-bit runtime with no skips, which is the only
configuration that exercises every new test; 23 pass + 2 skip under native Tcl 9.0.3,
where parse_args is absent. first_call times the new parsers in fresh child interps,
confirming these binary extensions load a second time in-process.
Built artifacts are not in this commit - modules/ is git-ignored. modules/
argparsingtest-1.2.0.tm was deployed via 'make.tcl modules' so the dev shell can see it:
a plain 'package require argparsingtest' there resolves a deployed stable version in
preference to the 999999.0a1.0 source module, so source edits are invisible until built.
Claude-Session: https://claude.ai/code/session_01Q82VuBXzgeKsAwMYHrbpP1
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
|
2 weeks ago |
|
|
78d9bf238a |
G-124 achieved: dependency-free zip reading in punk::zip (punkshell 0.26.0)
punk::zip could write a zip and split an executable-prefixed one, but nothing in the tree
could READ a zip without zipfs, vfs::zip or tcllib's zipfile::decode - a system package
punkshell does not vendor, with exactly one consumer: make.tcl's zipfs-less kit
extraction. Measured at drafting: msys2's /usr/bin/tclsh8.6 has no tcllib, so a bake
driven from that host could not lift the runtime's own zip (its tcl_library) into the kit
and the artifact did not boot.
punk::zip 0.1.1 -> 0.2.0 adds three commands, stock Tcl only. archive_info reports where
the archive begins inside its host file and which offset convention it uses; members
walks the central directory and returns one dict per entry without decompressing
anything; unzip extracts all or part of it with every member's crc32 verified,
directories materialized, and the writer's 2MB whole-member-vs-streaming threshold
mirrored. All three accept a plain .zip or a zip attached to an executable or script
prefix, so "what is inside this kit / runtime / modpod" is now answerable on a runtime
without zipfs.
The offset derivation is stated once and shared: offsetbase = cdiroffset - diroffset.
Positive means an external preamble with archive-relative offsets, zero means the offsets
are file-relative (or there is no preamble); dataoffset is the split point either way.
Because every surface reads the ORIGINAL file at that base, the file-relative shape stops
being a special case - the broken split-off intermediate is never produced.
tclsh90b4_piperepl.exe is the store's one file-relative artifact: the old
split-then-tcllib path still fails on it with exactly "Bad zip file. Bad closure.", and
it now extracts all 841 members crc-verified in 735ms.
extract_preamble consumes that machinery instead of carrying its own scan, and two
defects went with the refactor: it read 28 bytes of a 30-byte local file header, and it
derived the file-relative base from the FIRST central directory record only (its own
'#todo! loop through all cdr file headers'). The shared walk takes the minimum over ALL
records and then validates that a PK\3\4 really sits there. Its five puts stdout debug
lines are gone.
Refusals are decided for every selected member before any file is opened, so an
unsupported archive cannot leave a half-populated directory: encrypted entries, zip64
size/offset fields, unknown compression methods, crc mismatch (partial file removed) and
member paths that would escape the target are each named. Store and deflate only,
mirroring the writer's own primitives.
make.tcl's zipfs-less extraction now calls punk::zip::unzip on the original runtime and no
longer creates the extracted_<runtime>.zip intermediate. No punkshell code requires
zipfile::decode any more. Two categories of hit remain and are deliberate: tcllib's own
zip/decode.tcl shipped as a LIBRARY inside some .vfs payloads, and one guarded optional
probe inside the vendored third-party ooxml1.10/ooxml.tcl.
First tests punk::zip has ever had (src/tests/modules/punk/zip/), covering the three
archive shapes from one source tree, the introspection output, the named refusals, and
the mkzip -> read round trip - the first coverage that what punkshell WRITES is readable.
Verification, all 2026-07-26. Reference host for the dependency-free claim: msys2
tclsh8.6 8.6.12, probed as zipfs / vfs::zip / zipfile::decode all ABSENT - suite driven
there harness-free, 28 passed, 2 skipped (the zipfs-gated cross-checks only), 0 failed.
30/30 under Tcl 9.0.3, 28 + 2 skipped under native 8.6. Full source-tree suite after the
change: 1142 tests, 1 failure - core/tcl exec-14.3, the documented baseline. Independent
cross-check: 868 members of tclsh905.exe extracted byte-identical against the same
archive mounted with tcl zipfs. Bake demonstration: 'bake -confirm 0 punk905' driven by
the msys2 tclsh8.6 (host=msys-x86_64, target=win32-x86_64) produced
extracted_tclsh905.exe/{tcl_library,lib} with no intermediate .zip, and the deployed kit
boots with tcl_library at //zipfs:/app/tcl_library, 95 encodings, msgcat 1.7.1, http
2.10.2 - and reads itself with the new reader.
Trap worth keeping: zlib stream inflate's 'get' returns only what the stream has already
produced, so one get per put silently truncates a large member to the first few chunks
(measured 327680 of 5048890 bytes on both 8.6.12 and 9.0.3). The inner drain loop is
load-bearing, and the >2MB streaming test exists to catch its removal.
Standing question answered and pinned: zipfs does NOT misidentify punk::zip::mkzip
directories. It keys on the trailing slash (which punk::zip::walk always emits), not the
stored permission bits, exactly as the current cli-999999.0a1.0.tm wording says - the
older, less precise wording survives only in frozen module snapshots under
src/vfs/mkzipfix.vfs and src/vfs/project.vfs. The real difference from zipfs mkzip is
that zipfs writes no directory entries at all.
The achieved flip archives the entry and the detail file, and sweeps the live tier: G-034
(the reader is its extract-rather-than-mount alternative, plus the measured finding that
make.tcl on 8.6 cannot mount its own templates modpod), G-101 (the read half of a
zipfs-less 8.6 container is solved), G-125 (the gate now has a named failure reason to
report), G-126 (the member-dict keys and fixture set its parity suite must reproduce, and
a back-pointer to G-128 whose only recorded bridge was this goal), G-128 (archive_info
answers "is this artifact safe to move the overlay of?" in one call).
One acceptance clause is reported for review rather than claimed silently: "NO
zipfile::decode requirement remains anywhere in the shipped tree" is satisfied for
punkshell's own code, with the vendored-third-party residue named above.
The archived detail file's diff is a rename plus the flip's evidence write-up.
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
|
2 weeks ago |
|
|
04d2a51b67 |
G-122 achieved: make.tcl bakes by target platform, not host personality (punkshell 0.25.0)
Everything a bake EMITS is now keyed by the artifact's TARGET platform rather than the driving tclsh's personality: the bin/runtime/<tier> store a runtime is read from, .exe suffixing of runtime files and kit outputs, presence checks, and whether the pre-deploy process sweep uses tasklist/taskkill or ps/kill. Host semantics - copy commands, path handling, filesystem case rules, prompts - stay keyed to the host. The default target is the host's platform canon EXCEPT for a cygwin-family host (an msys2/cygwin-runtime tclsh, which reports tcl_platform(platform) unix on windows), which targets win32-x86_64. Such a host now drives the identical kit set, names and store addressing as a native tclsh; before, it reported every kit runtime=missing against a nonexistent mingw64-x86_64 store. mapvfs.config entries take an optional 4th element naming the kit's target platform, so a runtime kept in another platform's tier is a first-class mapping entry. The linux tclkit entry now declares linux-x86_64 and bakes to a suffixless bin/punkshell902. Zip-type kits assemble without zipfs in the driving tcl: when tcl::zipfs::mkimg is absent (any 8.6) the image is built by raw-runtime split + punk::zip::mkzip + concatenation - the same helper the zipcat type uses. Both mount identically (archive-start-relative offsets). Fixes exposed by the above: the runtime capability probe looked for a suffixless filename and so reported find-fail for every runtime on windows; with real capabilities arriving, the extraction try-list was found to test capability presence rather than value, which would send a plain zipfs runtime down the kit path where a failed sdx mksplit replaces raw_runtime with the un-split original; BUILDCOPY names now follow the runtime's own filename; runtime map keys strip only .exe (file rootname would eat the last dotted segment of tclsh9.0.5); and native windows command lines run through a guard suppressing msys2's posix-path argument rewriting - without it taskkill /PID <n> reached taskkill as taskkill C:/<msysroot>/PID <n>, so the sweep could find a running kit but never replace it. punk::platform folds the msys2 family (mingw64/mingw32/ucrt64/clang*) onto one stable 'msys' tag and CYGWIN_NT onto 'cygwin' - msys2's uname renders that token from MSYSTEM, so one binary otherwise canonizes differently per launching shell. New normalize_os; cygwin-x86_64 added to the platform table; 'help platforms' documents the fold. make.tcl check reports the derivation on one line; bakelist rows carry target=<platform> for non-default targets and the detail block names the tier; workflow text gains key note [K9]. New characterization suite maketclplatform.test (5 tests, two self-gating on discovering and probing a real msys/cygwin tclsh). Full suite 1112 tests: 1093 passed, 18 skipped, 1 failed = the documented exec-14.3 baseline. Verified: msys2 tclsh8.6 bakelist output identical to native Tcl 9; a changed punk91 baked and deployed from that host with the sweep killing a running instance msys ps cannot see; a real cross-target linux kit baked from windows to a 24MB ELF; a zipfs-less 8.6 bake producing a bootable zip kit. Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com |
2 weeks ago |
|
|
0abd07ecd7 |
G-121: make.tcl bakelist + selective bake (punkshell 0.24.0)
One parsed-mapping model (::punkboot::lib::mapvfs_parse / mapvfs_kit_outputs / mapvfs_match_outputs) now backs the kit surfaces - the bake machinery, the new bakelist report and the bake/bakelist argdoc kit-name choices all consume the model, never the file format, so the G-024 toml conversion can swap the reader underneath. - bakelist ?kitname ...? (informational SUBGROUP): kit name, type, runtime with presence, vfs folder, deployed state of bin/<kit> vs src/_build/<kit> (current|stale|absent|nobuild; size/mtime fast path, byte-compare when in doubt), anomalies as trailing key=value notes (runtime=missing, vfs=missing, rtrev=r<cur><r<max> via the shared runtime_materialization_check core). Name filtering doubles as per-kit detail (resolved paths/sizes/mtimes). - bake ?kitname ...?: selective kit assembly - unknown names error before any build listing the configured names (flag-order hint included); selected-but- unbuildable kits (missing runtime/vfs) fail fast; runtime BUILDCOPY/caps probe/vfs cksums/vfslibs phase all narrow to the selected kits so other kits' _build/bin artifacts and punkcheck records stay untouched. Bare bake unchanged (verified full-set run). Deprecated alias vfs mirrors the values. - argdocs: SUBVALUES/VALUES_SYNOPSES mechanism, kitname choices enumerated from the mapping at define time (-choicerestricted 0, degrade-safe), block-form help values; SUMMARIES/HELPTEXTS/SUBOPTS/SUBGROUPS/known_commands/plain gethelp/workflow text updated per the update contract; degraded-mode (PUNKBOOT_PLAIN) dispatch collects trailing kit names. - mapvfs.config todo comment retired to point at G-121. - piped characterization: src/tests/shell/testsuites/punkexe/maketclbakelist.test (full-report row/vocabulary + ESC-free, filtered detail, unknown-name errors on both surfaces with the no-build guarantee) - 4 PASS; maketclcolour.test still 3 PASS. - selective-refresh verification (recorded in the goal file): forced punk91 rebuild + deploy via 'bake -confirm 0 punk91'; stat diffs over src/_build and bin show only punk91.exe, punk91.exe.vfs, raw_tclsfe-x64.exe and bin/punk91.exe changed; .punkcheck diffs mention only punk91's records (negative grep for all other kit/vfs names clean). - docs: src/AGENTS.md work-guidance bullet; ARCHITECTURE.md build-entry subcommand list refreshed (bake/bakehouse naming + bakelist, stale in-flux G-112 mention dropped); CHANGELOG 0.24.0 + punkproject.toml minor bump. Claude-Session: https://claude.ai/code/session_01Jz7wkUsknJzyuJ3tgMaL2t Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
ac7dcdb02a |
colour policy: never wrap utf-16 console channels; 8.6 windows console auto-detected by encoding signature
Defect: the G-113 ansistrip transform was pushed onto Tcl 8.6 windows CONSOLE
channels, which encode utf-16 ('unicode') - at byte level ESC arrives as 1B 00
so sequences passed through unstripped and the hold-back carry deferred/
dropped real content, seriously mangling interactive punk86/punksys
'src/make.tcl help' layout (user-reported). Chunk-boundary handling itself is
sound: a rig proved strip output invariant across chunk sizes 1..4096 over
byte-transparent encodings; the failing dimension was encoding, not cutting.
(Comparison recorded: shellfilter::chan::ansistrip is the complement - it
decodes per the channel encoding and buffers undecodable tails, but assumes
line-buffering for sequence splits.)
Fix is detection, not utf-16 stripping: only 8.6 windows console channels
report -encoding unicode (pipes/files get the system encoding; hidden-console
probes confirmed across bawt tclsh86 8.6.13, punk86 8.6.17, punksys 8.6.13;
tcl9 consoles report utf-16 but are caught by -winsize first). The policy now
treats that signature as tty: mode=tty, colour ON, no transform - interactive
8.6 windows colour with no env var and no twapi. The transform push is now
PER CHANNEL and skips utf-16-class channels ('> file' from an 8.6 console
wraps stdout only - stderr console keeps its ANSI); ansistrip_pushed is the
wrapped-channel list, shell pops exactly those, policy/check lines print
ansistrip=stdout+stderr|stdout|0.
Verified: hidden-console 8.6 x3 mode=tty ansistrip=0; half-redirected punk86
console run ansistrip=stdout; piped 8.6/9 batteries unchanged (zero ESC,
force re-colours); punkexe suites 54/0 (maketclcolour pins updated to the
channel-list format). punkshell 0.23.2 + CHANGELOG; src/AGENTS bullet updated.
8.6 unix/WSL stays plain-by-default pending the probe-ladder goal.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
2 weeks ago |
|
|
232f2f6096 |
contextual sweep: deprecated make.tcl subcommand references (user-directed, incl. contract lines)
Each site read in context, not grep-replaced; bakehouse vs bake chosen per meaning, and missing invocation arguments supplied where the reference describes an unattended flow: - G-005 Approach + Notes, G-006 Acceptance + body: 'make.tcl project' -> 'make.tcl bakehouse' (the full consumer build these goals integrate with; no flags - conceptual references on a clean checkout, not recipes). - G-057 Acceptance: 'make.tcl project' -> 'make.tcl bake' (icon embedding lives in the kit-wrap stage and must hold for a bare bake; bakehouse inherits). - G-028 Context DELIBERATELY UNCHANGED: dated 2026-07-07 incident narrative - the command actually run; history stays verbatim (alias keeps it readable). - src/runtime/mapvfs.config todo: 'vfs' -> 'bake' wish, re-annotated - G-104 achieved WITHOUT the single-kit-by-name/list-kits item (still open). - src/runtime/vendorlib_vfs.toml header: vfslibs now runs as a phase of bake (G-112 fold), not 'as part of project'. - shellexit.test + staticruntime.test rebuild comments: 'project' -> 'bake' AND stale '(interactive y confirmation)' / bare vfscommonupdate corrected to '-confirm 0' (piped y retired since G-030) - the missing-arguments class. - punk.project layout store vfs READMEs (lib + modules): 'make.tcl vfs' -> 'make.tcl bake'; modpod template twins propagated via the punkcheck layout->modpod sync (make.tcl modules run), never hand-edited. Variant-phrasing sweep confirmed non-hits: G-115 '(vfs assembly)' names the src/vfs payload tier (name retained), G-047 'make.tcl/project.new' is the dev project.new command. Archive tier + CHANGELOG history untouched. goals_lint + goals_xref refs clean. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
a949414bf8 |
make.tcl window doc sweep: bake/bakehouse vocabulary across workflow references
Root README, src/README, src/AGENTS.md (full-build guidance, provenance command list incl. bakehouse's default-on dirty gate, punk-exe-hosted builds, verification), src/modules + src/lib + src/vfs + src/tests + src/tests/shell + src/runtime AGENTS.md workflow references, and the rebuild-instruction comments in scriptexec.test/tclshcmd.test. G-104's G-058 mention gains its archive marker. Historical CHANGELOG entries untouched; goal-file contract texts (G-005/G-006/G-057 Acceptance mention 'make.tcl project') left for proposal-first user approval - the deprecated alias keeps them executable. Layout make.tcl copies are punkcheck-synced build outputs - they refresh via the normal sync channels in the acceptance build, never hand-edited. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
e03ce1d64a |
G-113: make.tcl terminal-aware colour policy (tty probe, force overrides, zero-ESC piped)
Startup policy: NO_COLOR > PUNK_FORCE_COLOR/FORCE_COLOR > stdout -winsize tty probe (Tcl 8.7+/9); Tcl 8.6 fails OFF. Piped/unknown non-forced runs push an ansistrip transform on stdout+stderr - zero ESC bytes from every emitter incl. module-side (punk::ansi's colour_disabled deliberately keeps non-colour effects; design finding recorded in the goal file). shell pops the transform. sgr_cache cleared for punk-exe-hosted pre-loaded interps per the punk::ansi contract. define_global_ansi fully gated; raw-SGR literals routed through new ::punkboot::sgr gate (fixes a malformed \x1b\31m). check reports the policy. make.tcl converted CRLF->LF. Verified: tclsh90 + punk91 kit piped zero-ESC (check/help/workflow/modules); force overrides re-colour piped output; NO_COLOR always suppresses colour; 8.6 tcl86-plain; real Windows console mode=tty (hidden-console evidence); WSL pty mode=tty vs piped-plain (tclkit-902-Linux64). New suite punkexe/maketclcolour.test 3/3. src/AGENTS.md bullet revised; punkshell 0.22.2. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
19c63ac60e |
punk-runtime list -remote identity columns (G-119 follow-on, user-directed)
The starred active row previously never changed across 'use' switches (every -rN materializes to the same working name) and carried the name-keyed dead end '(not listed on server)' - true of the name, unexplanatory for a working copy whose bytes match a server artifact. Rows the server listing does not name now carry an untitled identity middle column: from=<artifact> for materialized working copies (the beside-toml source; content verified against that artifact's server sha1 so the Remote cell shows a real status - Same version, CONTENT DIFFERS for the immutable-artifact anomaly, or '(artifact not listed on server)'), sha1=<name> for tomlless byte-copies (default-first- then-ordinal pick, the same rule as the freshness fallback so row identity and freshness verdict always name the same artifact). '(not listed on server)' remains only for genuinely unknown files; the (server default) row annotation follows artifact identity onto working copies of the default. Table header/rules widened to the three-column layout, payload row formats now column-aligned across ps1/bash; help text updated; bin/punk-runtime.cmd rewrapped (checkfile clean). Chosen shape (user-approved from mockup variants): untitled middle column with self-keyed from=/sha1= tags - consistent with the plain list metadata summary's from= vocabulary and self-describing when a row is pasted without its header. runtimecmd_freshness.test +3 row-shape tests (identity columns, the identity-following default annotation, anomaly statuses) with ps1/bash parity: 10/10 pass; scriptwrap + binscripts battery 35 pass / 1 pre-existing skip / 0 fail (roundtrip + checkfile pins green, WSL row pins unaffected). bin/AGENTS.md + shell tests AGENTS updated. punkshell 0.22.0. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
f562d13d2e |
G-119: punk-runtime freshness verdict - active vs server default (both payloads)
list -remote now states the relationship between the ACTIVE runtime and the SERVER DEFAULT whenever both are known: explicit freshness: AHEAD/ BEHIND verdicts naming both revisions (BEHIND adds a fetch+use update guidance line), an equivalent current verdict where the (= server default) identity annotation did not fire, a different-series incomparable note, and a stated no-revision-basis note for pre-family actives - with sha1 VALUE-matching against the server sha1sums identifying a byte-copy of a server artifact by content (support-file rows excluded; first ordinal/C-collation match in both payloads). A NO-NAME fetch prints the same verdict as a one-line note when the active diverges from the resolved default (BEHIND carries an inline 'use <default>' hint - the artifact was just fetched). Revision basis: -r<N> parsed from artifact-named actives, else the beside-toml revision field (materialized working copies); the default's revision parses from its defaults.txt name. Verdict lines are byte-identical across the payloads; guidance lines keep each payload's program-name convention. Help text (list/fetch sections) mentions the new surface; bin/punk-runtime.cmd rewrapped (checkfile clean, no spacer resize). New fixture-server suite shell/testsuites/binscripts/runtimecmd_freshness.test: a child-process http file server (new src/tests/testsupport/httpfixture.tcl) serves a crafted punkbin layout behind the PUNKBIN_URL override; the ps1 payload runs as the staged committed .cmd via cmd.exe (wrap-pinned path), the bash payload directly under a probed msys/git bash (on windows the polyglot routes unix shells to the powershell payload; WSL bash rejected - WSL2 cannot reach a 127.0.0.1 fixture server). Covers the five G-119 acceptance scenarios with per-scenario ps1/bash verdict-line parity plus bash-side extras (different-series incomparable, fetch-mode BEHIND hint): 7/7 pass; scriptwrap + binscripts subtrees 32 pass / 1 pre-existing skip / 0 fail (roundtrip, checkfile, WSL, dtplite unaffected). bin/AGENTS.md runtime-manager contract records the verdict surface; src/tests + src/tests/shell AGENTS docs cover the new suite and helper. punkshell 0.21.0 + CHANGELOG entry. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
83d2c6f44c |
G-118 item 11: env-gated hidden-console test for the dorepl console-reopen path
New src/tests/testsupport/consoleinject.ps1: the G-106 recipe's injection half as a committed helper - FreeConsole/AttachConsole to a target pid's console, open CONIN$, type lines as WriteConsoleInput key events. tclshcmd.test: constraint punkconsole (windows + PUNK_TEST_CONSOLE=1; normal runs skip) gates two tests driving the reopen path end-to-end in the child's OWN hidden console (outer Start-Process -WindowStyle Hidden wrapper owns a fresh console; wrapper runs '<kit> tclsh' there with std handles redirected to files; piped code sets dorepl; injected lines + exit 0 finish it). Pinned: reopened flips 0 -> 1 at reopen with istty immutable at 0, inputbuffer published empty, reopen notice silent by default and STDERR-only under TCLSH_PIPEREPL_DEBUG=1, injected exit completes with code 0 - closing the item-1/7 console-side residue. Deadlines + wrapper-tree kill keep the tests hang-proof; the piped-harness HANG RULE stands for everything else. Verified: PUNK_TEST_CONSOLE=1 run 21/21 against punk9_beta; normal run 19 pass + 2 console skips; shell/*** suite 64 pass / 4 skips / 0 fail. AGENTS updates: src/tests/shell (tclshcmd bullet - coverage now exists, refined hang rule), src/tests (testsupport index + .ps1 helpers wording). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
a015ada542 |
G-117 achieved: flip, archive, reference sweep; reopened pin; G-118 items 1+7 verified
Acceptance evidence in the archived detail file: embed verified in all three family members (family_check), sidecar derived from embed with identical build_id, 'info' identifies sidecar-paired/renamed-stray/pre-v1 files without execution and flags doctored-sidecar disagreements, punkbin AGENTS.md schema docs, roundtrip pin green, record survives make.tcl kit wrapping (punk9_beta reads its runtime's r2 record in-kit), r2 re-emitted with full v1 records. Sweep: achieved markers in G-025/G-057/G-108/G-116/G-118/G-119 (G-025's survival expectation updated to confirmed). tclshcmd.test pins ::tclsh(reopened) publication on the rebuilt patched kits (G-118 items 1+7 landed+verified; Progress updated). build905.zig: packager git-identity leg judges success by output not out_code (resolved 'unrecorded' on this host - effective at next emission). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
17250a8c97 |
tclsh subcommand G-118 items 3/4/5/9: argv0 stock parity, clean not-found, console fail-fast, project_main parity (0.20.0)
- no-script forms set ::argv0 to the executable path (was the kit boot script) - missing script file: file-exists pre-check, clean message, exit 1 (existing-file source errors keep their full trace) - no piperepl machinery (unpatched runtime or TCLSH_PIPEREPL=0): terminal stdin fails fast with usage guidance (app-punkscript probe) instead of blocking in a raw read; piped degraded eval unchanged; patch-missing notice now 'note:' and a deliberate TCLSH_PIPEREPL=0 opt-out is quiet (old debug lines deleted) - project_main.tcl mirrors the full tclsh dispatch (script-arg/dash/-encoding/ lib: forms; was single-arg-only with stale gate default 0); layout _config copies byte-synced (interim duplication pending G-031) - tclshcmd.test 17 -> 19 (tclsh_noscript_argv0, tclsh_script_notfound); shell subtree 64 pass / 2 goal-gated skips / 0 fail against rebuilt kits Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
2 weeks ago |
|
|
f3a9067cbf |
runtimebash_wsl.test: tolerate G-103 metadata-era list row format (stale glob)
Local 'list' rows are column-padded '* <name %-35s> (active) <metadata>' since 61cf903d; the test's single-space '* fakert_beta (active)' glob predates that and failed. Assertion intent unchanged: the row is starred AND active-marked. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
e61411c19a |
tclsh subcommand review: tclshcmd.test suite + contract doc corrections
- new punkexe suite (17 tests): dispatch contract (script-arg argv0/argv/ info-script state, honest exit codes, piped no-arg eval, stock arg forms, lib: refusal) plus the piperepl launch-state contract on patched kits (istty/dorepl/evalinput published, piped script-arg state all-zero, unconsumed-piped-input safety default, evalinput opt-in ordering, script consuming stdin itself) and the unpatched degraded-mode notice - hang rule baked in: no test or fixture may set ::tclsh(dorepl) (the console-reopen path blocks under a piped harness; G-106-recipe territory) - patched-kit resolution: env PUNK_PIPEREPL_TEST_EXE, else the punkexe if it probes patched, else bin/punk9_beta.exe / punk9bi_beta.exe - encoding coverage is byte-level (utf-8 vs iso8859-1 fixture; [format %c 233] keeps the .test file pure ascii, runner-encoding-proof) - patches/README.md: corrected the tcl_interactive divergence note (console script-arg runs READ 1 where stock reads 0 - piped launches identical; the early link stays load-bearing for the piped prompt opt-in) and recorded the '? reopen stdin from console' stdout residue as known - shell/AGENTS.md: tclshcmd bullet; stale runtime.bash names corrected to punk-runtime.bash/punk-runtime.cmd Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
168a98d85f |
G-106: powershell console-mode fallback overhaul - punk::console 0.8.0, canonical server script, tests (project 0.17.8)
Raw mode on twapi-less windows runtimes made dependable and quiet: lazy singleton server (tsv-shared per process, spawn no longer at module load), parent-pid self-reaping (no orphan pwsh), the 20s keepalive-without-pinger and the first-message listener kill (reader Close disposing the pipe stream) both fixed, disableraw served on no-inputmode runtimes (8.6 path), enable confirmed via live tcl9 -inputmode before return, script resolution env -> argv0 -> module-dir -> embedded copy (pwd fallback gone; kits need no scriptlib on disk). PUNK_PS_CONSOLEMODE_DEBUG=1 for diagnostics both sides. scriptlib/utils/pwsh reconciled: canonical consolemode_server_async.ps1 rewritten (protocol enableraw|disableraw|ping|exit, parent-pid watch, posh-git MIT attribution for the C# snippet), five experiment variants retired (consolemode_server.ps1, *_async1.ps1, *_async.2ps1, consolemode.ps1, consolemode_enableraw.ps1), README labels the folder. New console suite psfallback.test pins the embedded-copy/file sync and the resolution chain. punk::repl stale comment fix (no behaviour change). Verified per the recipe recorded in the goal detail file: hidden-console selftests on suite tclsh90spr + zipfs kit tclsh90sprzip (25s-idle survival, stop/respawn, zero orphans), live make.tcl-shell and bare-repl sessions driven by injected keystrokes (console mode 0x1E7<->0x1E1 read externally), embedded-resolution forced run, console testsuite 76/76. G-106 acceptance met - achieved flip recorded in the detail file; archive move follows in the next commit. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
0eda40af32 |
runtests: version-floor the runner's requires (fossilized-kit rejection); concurrency child floor
Root cause of the punk86-kit runtests failure: a punk-kit interpreter's
boot pre-registers its kit-stamped package versions, and an unversioned
require satisfiable by such a registration never fires package unknown -
the freshly-added bootsupport tm path is never scanned. The old kit's
punk::args 0.1.0 won the require, then the versioned punk::path 0.4.0-
pulled a modern module whose load-time argdoc needs punk::args::define:
invalid command name.
Floors added: punk::args 0.12- (runtests.tcl toplevel), punk::lib
0.5.1- (both 8.6 lpop guards; punk::path 0.4.0- already floored in
discovery.tcl). Feature-era minimums, not latest pins - their purpose is
rejecting fossils so package unknown resolves the bootsupport copy.
Verified: the floors alone resurrect even the OLD fossilized punk86 kit
(discover-only + a 35/35 suite run); native 9 and 8.6 unaffected.
concurrency.test child preamble floors its punkcheck require (0.6-):
kit-hosted children boot with kit-stamped punkcheck PRELOADED, and a
stale kit (pre-vfscommonupdate _vfscommon) made children fail on
'invalid command name punkcheck:🔒:acquire' - the floor turns that
into a loud version-conflict in the child log.
src/tests/AGENTS.md records the floor rationale and the kit-hosted
child-suite requirement (vfscommonupdate-current kit content).
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
|
3 weeks ago |
|
|
099ac699e3 |
G-097: bin utility naming sweep - punk-bits, punk-runtime, punk-tclargs, selfsign
The remaining pre-policy punkshell-own bin utilities take the punk- prefix (bin/AGENTS.md policy, G-096); external-tool wrappers (dtplite/sdx/kettle) and getpunk stay unprefixed. No behaviour changes ride along. - runtime scriptset: sources/toml renamed (src/scriptapps/bin/punk-runtime.*), the eight ps1 usage/guidance messages now say punk-runtime.cmd, the bash payload's filename-derivation comment example updated; REWRAPPED -> bin/punk-runtime.cmd (checkfile clean) with the .ps1 twin regenerated as a byte-copy. The roundtrip + checkfile pins retarget the new names and pass. - tclargs + bits: sources/tomls renamed; bin artifacts moved BYTE-FAITHFULLY (git mv, no rewrap): a pre-rename drift check showed both carry pre-template-refresh wraps (477-byte delta = the template's 2025 wmic-deprecation timestamp fix; runtime was in sync). Regenerating them is a behaviour change and is deliberately not smuggled into the rename - recorded in the goal. Fresh .ps1 twins cut from the current .cmds; stale untracked bits.bat/bits.ps1/tclargs.ps1/runtime.ps1 removed. - selfsign experiments: SELFSIGN.PS1 -> punk-selfsign.ps1 (case normalized), wrap toml + cert-create script renamed; the four untracked bin experiment scripts renamed on disk; the exported .cer is not a script and keeps its name. - runtimebash_wsl.test: functional staged-filename sites updated (bash ./punk-runtime.bash; solo-fixture cp) along with comments. - Docs: bin/AGENTS.md (examples, policy paragraph records the sweep, runtime contract section, pin pointer corrected to runtimecmd_roundtrip.test), src/scriptapps/AGENTS.md, root AGENTS.md, README.md, src/README.md, untracked bin/runtime/README.md, G-060 reference, libunknown comment (src copy; root modules/ + bootsupport copies catch up on their re-vendor cycles). Suites green: scriptwrap + binscripts 26 run / 25 passed / 1 constraint-skip / 0 failed - the roundtrip pin passes against the renamed artifact. Discovered and recorded for user decision (goal Progress): the project LAYOUT stores ship stale utility copies - runtime.cmd (2025-era payload) and getzig.cmd (the G-096 rename missed this channel) - so generated projects still receive old-named utilities; folding the layout channel into this goal's scope vs a layout-sync mechanism is flagged. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
c9c8a932e7 |
concurrency.test: retrying workspace cleanup for background-child log race
The two child-spawning tests (two-writers, lock-holder) proceed on the children's done-marker files, but a just-finished child can still hold its redirected stdout log open for a beat after writing the marker - on Windows the -cleanup tree delete then hits 'permission denied' (observed as a ~1-in-3 flake under the slower Tcl 8.6 interp, exposed by the new native-8.6 runtests support; same race existed under Tcl 9). cleanup_workspace retries the delete briefly (10s deadline) instead of flaking. 8/8 consecutive clean runs under 8.6.17 post-fix; Tcl 9.0.3 punkcheck subtree 84/84. Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |
|
|
1fbee821fc |
runtests: native Tcl 8.6 support via guarded punk::lib compat load (lpop)
The validated compat family is brought across for the harness: guarded 'package require punk::lib' when ::lpop is absent, at both boot levels - the toplevel two-stage boot (right after punk::args, whose parse needs lpop at runtests.tcl's own argument parsing) and the singleproc testinterp (before the shellrun preload, whose runx parses via punk::args::parse). No-ops on Tcl 8.7+/9: -discover-only stays ~0.35s. Native 8.6.17 verification: -discover-only works; punkcheck subtree 84/84, punk/lib subtree 43/43+1 gated skip, runner discovery suite 22/22, and a multiproc (-singleproc 0) probe 49/49. Tcl 9.0.3 regression per the src/tests/AGENTS.md runner-change contract: full suite in both modes with -report json, runtests_parity.tcl reports PARITY: ok (files=96 total=1064 passed=1047 skipped=16 failed=1 - the sole failure is the documented pre-existing exec-14.3 baseline). src/tests/AGENTS.md records the supported-interpreter change and the still-broken punk86-kit runtests route (kit/dev module skew - use a native 8.6 tclsh for 8.6 legs). Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com |
3 weeks ago |