Browse Source

make.tcl: new 'workflow' subcommand - embedded ASCII build/release data-flow overview

Prints the release-ready command sequence, source -> built-packages ->
bootsupport / kit-vfs / kit-executable folder-flow diagrams, and keyed notes
(magic-version stamping, punkcheck provenance, staleness gate, -confirm
policy, locked-exe deploys, VCS-tracked output targets). The text is embedded
in make.tcl (::punkboot::workflow_text) rather than a data file so it travels
with the make.tcl copies seeded into generated-project layouts; content is
project-generic accordingly. A MAINTENANCE key in the output states the
update contract.

punk::args-documented via the existing constructed-definition machinery
(SUMMARIES/HELPTEXTS/SUBOPTS + informational SUBGROUPS entry) so tabled help,
'help workflow' and the top-level subcommand table all cover it; also
registered in known_commands and the plain punkboot_gethelp fallback, and
exempted from the bootsupport staleness gate alongside check/projectversion.
Verified in normal and PUNKBOOT_PLAIN dispatch; stray arguments raise a
punk::args toomanyarguments usage error; output is pure ASCII, width <= 100.

src/AGENTS.md Work Guidance gains the agent update contract: change the
workflow text in the same change-set as any build data-flow change, keep the
ASCII/width/structure rules, verify with 'make.tcl workflow' (+ one
PUNKBOOT_PLAIN run), and the registration-point checklist for subcommand
changes. Layout make.tcl copies propagate via 'make.tcl bootsupport' - never
hand-synced. punkshell 0.12.42.

Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
master
Julian Noble 4 days ago
parent
commit
c1c7ab3ee7
  1. 4
      CHANGELOG.md
  2. 2
      punkproject.toml
  3. 1
      src/AGENTS.md
  4. 171
      src/make.tcl

4
CHANGELOG.md

@ -5,6 +5,10 @@ The latest `## [X.Y.Z]` header must match the `version` field in `punkproject.to
Entries are newest-first; one bullet per notable change. See the root `AGENTS.md`
"Project Versioning" section for the bump policy.
## [0.12.42] - 2026-07-17
- make.tcl: new informational subcommand `workflow` - prints an embedded plain-ASCII overview of the build/release data flow (release-ready command sequence, source->built-packages->bootsupport/kit-vfs/kit folder diagrams, keyed notes on version stamping, punkcheck provenance, the staleness gate, -confirm and locked-exe deploys). punk::args-documented like the other subcommands (tabled help + PUNKBOOT_PLAIN fallback covered); exempt from the bootsupport staleness gate alongside check/projectversion. The text lives in ::punkboot::workflow_text so it travels with make.tcl into generated-project layouts; update contract for keeping it current documented in src/AGENTS.md Work Guidance and in the output's MAINTENANCE key.
## [0.12.41] - 2026-07-17
- punk::args 0.12.4: resolve's undefined-id miss path is now collision-aware - an inline definition (`parse ... withdef`, direct resolve) whose @id is already registered with different content quietly purges the id's existing cache entries before registering (matching define's re-creation behaviour), instead of repointing the id while stale cache entries lingered (previously a subsequent define with the original text was a silent no-op, leaving withid lookups stuck on the inline definition). The disabled blanket 'called with undefined id' stderr warning removed (it flagged supported usage). Known residual: the miss path still records no -defspace for @dynamic definitions first seen via resolve. New define.test pin (define_resolve_id_shadow, characterized pre-fix).

2
punkproject.toml

@ -1,4 +1,4 @@
[project]
name = "punkshell"
version = "0.12.41"
version = "0.12.42"
license = "BSD-2-Clause"

1
src/AGENTS.md

@ -67,6 +67,7 @@ Recovery after a wrong path guess:
- All build/promotion commands (`project`, `packages`, `modules`, `libs`, `vfs`, `vfslibs`, `bin`, `bootsupport`, `vfscommonupdate`) warn similarly when this project's own `src/` has uncommitted fossil/git changes (dirt outside `src/` is ignored). Warn-only by default; pass `-dirty-abort` to make the check aborting. For evaluating uncommitted source without a build, prefer `<builtexe> src` / `<builtexe> src shell`. The check is `punkboot::utils::vcs_dirty_warnings` (optional scope argument) loaded guardedly from bootsupport - if the snapshot is stale/missing the check degrades to a skip notice (but `-dirty-abort` then aborts rather than silently losing the requested strictness).
- Provenance warnings (dirty-src gate + vendorupdate source-project check) print with a plain column-0 `PROVENANCE-WARNING:` token (grep for it in captured build output) and are recapped at the end of the run via make.tcl's wrapped `::exit`. Interactive terminal runs get a 3-second ctrl-c grace countdown before a dirty build proceeds; piped/agent runs skip it. `tclsh src/make.tcl check` reports the current src provenance status and what the build commands would do.
- Use `tclsh src/make.tcl vfscommonupdate` to rebuild `_vfscommon.vfs`. The REPLACE confirmation prompts on an interactive terminal; unattended/agent runs must pass `-confirm 0` (with the default `-confirm 1` and a piped/closed stdin, make.tcl aborts fast with guidance instead of reading stdin - do not pipe `y`).
- `tclsh src/make.tcl workflow` prints an embedded ASCII data-flow overview of the build/release workflow (release-ready command sequence, source→outputs folder flow, kit assembly, keyed notes). The text lives in `::punkboot::workflow_text` in `src/make.tcl` - embedded rather than a data file so it travels with the make.tcl copies seeded into generated projects. **Update contract (agents):** whenever build data flow changes - a make.tcl subcommand added/removed/repurposed, a source or output folder added or rerouted, a propagation target added, a gate (staleness/provenance/confirm) or deploy behaviour changed - update the workflow text in the same change-set. Keep it plain ASCII, max line width 100, and preserve the RELEASE SEQUENCE / DIAGRAM / KEY-NOTES / MAINTENANCE structure; verify by running `tclsh src/make.tcl workflow` (and once under `PUNKBOOT_PLAIN=1`). Adding/changing a subcommand also means: SUMMARIES + HELPTEXTS + SUBOPTS (+ SUBGROUPS) in `::punkboot::argdoc`, `known_commands`, the plain `punkboot_gethelp` text, and a project-version bump (make.tcl interface is product surface per root AGENTS.md). Layout make.tcl copies pick the change up via `make.tcl bootsupport` - do not hand-sync them.
- make.tcl subcommands and flags are punk::args-declared (G-030): `tclsh src/make.tcl help ?subcommand?` or `<subcommand> -help` shows tabled usage; invalid arguments produce punk::args usage errors. The dispatch degrades to plain scan/help when the bootsupport punk::args (or its rendering stack) is stale or unavailable; `PUNKBOOT_PLAIN=1` forces the degraded mode for troubleshooting. The `::punkboot::argdoc` definitions are constructed (string-built) and use the G-045 authoring mechanisms — block-form help values + `@normalize`, explicit `@form -synopsis` — see src/modules/AGENTS.md "punk::args definition authoring ergonomics" before editing them or authoring similar definitions.
- Uncommitted `make.tcl`-generated outputs may be batched into one commit, regardless of how many `make.tcl` invocations produced them. This covers punkcheck-managed build outputs that are VCS-tracked: `src/bootsupport/`, `_vfscommon.vfs/modules` + `/lib`, and declared per-kit `*.vfs/lib_tcl<N>/<pkg>` subfolders. (Root `modules/`, `lib/`, `modules_tcl<N>/`, `lib_tcl<N>/` are gitignored and never committed.) Each module's old→new version rename is atomic; a regeneration reflects one build-output refresh, not independent hand-edits. This is a carve-out from generic "split aggressively" commit guidance for punkcheck-managed build outputs only — it does not cover user-curated VFS content (`_config/`, per-kit `*.vfs/` outside declared `lib_tcl<N>` subfolders, `_aside/`, `mkzipfix.vfs`, `_vfscommon.vfs/doc`), which commits separately per its own concerns.
- Use `punk make.tcl project` or `punk902z make.tcl project` inside Punk shell when building binaries through Punk. Driving make.tcl from a built punk executable is supported for informational/update subcommands and for kit builds of *other* kits — the kit whose deployed executable is running the build is skipped with a warning (it cannot be replaced while running, and the pre-deploy process sweep must not kill the build itself; the sweep also excludes the build's own pid in all cases). Rebuild that kit from tclsh or a different kit.

171
src/make.tcl

@ -21,7 +21,7 @@ namespace eval ::punkboot {
variable foldername [file tail $scriptfolder]
variable pkg_requirements [list]; variable pkg_missing [list];variable pkg_loaded [list]
variable help_flags [list -help --help /? -h]
variable known_commands [list project modules libs packages vfs vfslibs bin info check shell vendorupdate bootsupport vfscommonupdate projectversion]
variable known_commands [list project modules libs packages vfs vfslibs bin info check shell vendorupdate bootsupport vfscommonupdate projectversion workflow]
}
@ -1395,6 +1395,8 @@ proc ::punkboot::punkboot_gethelp {args} {
append h " - run the punk shell using bootsupport libraries." \n
append h " $scriptname projectversion" \n
append h " - advisory check: verify CHANGELOG.md matches punkproject.toml and warn if src/ has changes since the last project-version bump." \n \n
append h " $scriptname workflow" \n
append h " - print an ASCII data-flow overview of the build/release workflow (edit -> packages -> bootsupport -> kits)" \n \n
append h " $scriptname help ?subcommand?" \n
append h " - show usage for $scriptname or one of its subcommands (equivalent: $scriptname <subcommand> -help)" \n \n
append h " Flags:" \n
@ -1412,6 +1414,152 @@ proc ::punkboot::punkboot_gethelp {args} {
append h [punkboot_availability_note]
return $h
}
#Embedded build/release workflow overview - the output of the 'workflow' subcommand.
#Embedded (rather than a data file) so it travels with make.tcl wherever it runs, including
#the make.tcl copies seeded into generated projects via the project layouts.
#Contract for updates (see also src/AGENTS.md 'Work Guidance'): when build data flow changes
#(subcommand added/removed/repurposed, source or output folder flow changed, new propagation
#target), this text changes in the same commit. Plain ASCII only, max line width 100.
proc ::punkboot::workflow_text {} {
set txt {
build & release workflow - from module edit to kits + bootsupport (punk project layout)
=============================================================================
Scope: data flow from editing a module under src/ through to a release-ready
rebuild (built packages, bootsupport refresh, kit vfs, kit executables).
All commands run from the projectroot with a native tclsh, e.g:
tclsh src/make.tcl <subcommand> -confirm 0 (see [K6])
RELEASE SEQUENCE (the order that satisfies the staleness + provenance gates)
----------------------------------------------------------------------------
(1) edit src/modules/foo-999999.0a1.0.tm code change [K1]
(2) bump src/modules/foo-buildversion.txt module version + changelog comment
punkproject.toml + CHANGELOG.md project version (if shipped behaviour) [K2]
(3) test tclsh src/tests/runtests.tcl ... runs against src/ trees (if present)
(4) commit source changes (git/fossil) clean tree -> committed provenance [K3]
(5) build tclsh src/make.tcl modules -confirm 0 (or 'packages' = modules + libs)
(6) build tclsh src/make.tcl bootsupport -confirm 0 run twice: 2nd pass must copy 0 files [K4]
(7) build tclsh src/make.tcl vfscommonupdate -confirm 0
(8) build tclsh src/make.tcl project -confirm 0 kits; close running kit shells first [K5]
(9) commit tracked build outputs src/bootsupport, src/project_layouts
copies, src/vfs/_vfscommon.vfs
DIAGRAM 1 - DATA FLOW: SOURCE -> BUILT PACKAGES -> PROPAGATION TARGETS
----------------------------------------------------------------------------
src/modules/foo-999999.0a1.0.tm [K1] src/lib/
src/modules/foo-buildversion.txt src/vendorlib/
src/vendormodules/ (+ *_tcl9 variants) |
| |
| make.tcl modules | make.tcl libs
| (stamp real version, pack #modpod-*, |
| prune superseded) |
v v
modules/ modules_tcl8/ modules_tcl9/ lib/ lib_tcl8/ lib_tcl9/
e.g. modules/foo-0.12.4.tm
== BUILT PACKAGES (projectroot output trees, punkcheck-recorded [K3]) ==
|
+--------------------------------------+
| |
| make.tcl bootsupport [K4] | make.tcl vfscommonupdate
| (curated subset) | (REPLACE semantics: vfs modules/libs
v | are overwritten with built set)
src/bootsupport/modules/ v
(the module set make.tcl itself src/vfs/_vfscommon.vfs/modules/ + libs
boots from; staleness-gated) (VCS-tracked kit payload source)
| |
| same run, second hop | make.tcl project (or: make.tcl vfs)
v v
src/project_layouts/custom/_project/ src/_build/<kit>.exe --deploy--> bin/<kit>.exe
<layoutname>/src/bootsupport/ (see DIAGRAM 2) [K5]
(template copies seeded into projects
generated by 'dev project.new')
DIAGRAM 2 - KIT ASSEMBLY DETAIL (inside 'make.tcl project' / 'make.tcl vfs')
----------------------------------------------------------------------------
src/runtime/mapvfs.config which vfs folder pairs with which runtime -> kit name
src/runtime/<runtime>.exe bare Tcl runtime (tclkit / tclsfe build)
src/vfs/_vfscommon.vfs/ common payload (built modules + libs, main boot support)
src/vfs/<kitspecific>.vfs/ per-kit overlay (main.tcl, kit-only modules/config)
_vfscommon.vfs <kitspecific>.vfs
| |
+-----------+----------+
| copy common, then merge overlay over it
v
src/_build/<kit>.exe.vfs
|
| tcl::zipfs::mkimg (vfs image appended to runtime exe)
v
src/_build/<kit>.exe
|
| deploy step: delete old bin/<kit>.exe, copy new one in
v
bin/<kit>.exe <-- FAILS (kit listed under FAILED KITS) if a
running shell still holds the old exe [K5]
KEY / NOTES
----------------------------------------------------------------------------
[K1] Source modules carry the literal magic version 999999.0a1.0 in the filename.
The real version is the first line of the sibling <modulename>-buildversion.txt;
bump it per semver (patch=fix, minor=api add, major=breaking) and append a
'#<version> - ...' changelog comment line below it. The modules build stamps
the real version into the output filename and package provide.
(A project may carry manually-versioned exceptions - see src/modules/AGENTS.md
if present.)
[K2] Project version (punkproject.toml [project] version + matching CHANGELOG.md
entry) is change-driven: bump when the change ships user-visible behaviour.
Advisory check: tclsh src/make.tcl projectversion
[K3] Every build target root gets a .punkcheck file recording what was installed
from where (punkcheck provenance). Building from a tree with uncommitted
changes under src/ works but emits PROVENANCE-WARNINGs - commit source first
for release builds. Output-tree commits (step 9) come after the builds.
[K4] Bootsupport staleness gate: make.tcl compares tracked module versions in
src/bootsupport against built sources; a stale bootsupport makes other
subcommands warn/prompt/abort (per bump level) unless -confirm 0. After a
tracked module bump, refresh with 'make.tcl bootsupport' and rerun it until
a pass copies 0 files (layout copies have needed a second pass historically).
[K5] The deploy step cannot replace a kit exe that is currently executing. Close
running kit shells before step 8, or rerun 'make.tcl vfs -confirm 0'
afterwards - the freshly built kits wait in src/_build. punkcheck records
mean the rerun only redoes the failed deploys.
[K6] All confirmation prompts follow -confirm: unattended/agent runs must pass
-confirm 0 (non-interactive stdin aborts fast at prompts; piping 'y' is
retired). 'make.tcl help <subcommand>' shows per-subcommand usage.
[K7] Testing hooks along the way:
- src/tests/runtests.tcl exercises the src/ trees directly (dev modules).
- '<builtkit>.exe dev' (or '<builtkit> src') runs a built shell against the
project dev modules - useful for testing built packages before they are
baked into kits via vfscommonupdate + project.
[K8] What is VCS-tracked where (checkin targets after a build):
tracked: src/** (sources, src/bootsupport, src/project_layouts copies,
src/vfs/_vfscommon.vfs), punkproject.toml, CHANGELOG.md
untracked: modules*/ lib*/ at projectroot, src/_build/, bin/<kit>.exe
(bin/ scripts/tools are tracked; kit executables are not)
MAINTENANCE (agents take note)
----------------------------------------------------------------------------
This text is embedded in make.tcl (::punkboot::workflow_text). When the build
data flow changes - a make.tcl subcommand added/removed/repurposed, a source or
output folder added or rerouted, a new propagation target, a changed gate or
deploy behaviour - update this text in the same change-set and verify with
'tclsh src/make.tcl workflow'. Plain ASCII only; max line width 100. A make.tcl
interface change is product surface: bump the project version (at least patch).
}
return [string trim $txt \n]
}
#Missing/broken bootsupport-package NOTE shown with help output.
#Factored out of punkboot_gethelp (G-030) so both the punk::args tabled help path and the
#plain-text fallback help append the same information. Returns "" when there is nothing to report.
@ -1508,6 +1656,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO
info "Show the name and base folder of the project to be built"
check "Show module/library paths and any potentially problematic packages for running this script"
projectversion "Advisory check: CHANGELOG.md vs punkproject.toml and src/ changes since last version bump"
workflow "Print an ASCII data-flow overview of the build/release workflow (edit -> packages -> bootsupport -> kits)"
shell "Run the punk shell using bootsupport libraries"
help "Show usage for make.tcl or one of its subcommands"
}
@ -1595,6 +1744,15 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO
"
Advisory check: verify CHANGELOG.md matches punkproject.toml and warn
if src/ has changes since the last project-version bump."
workflow
"
Print a plain-text (ASCII diagram) overview of the build/release
workflow: the release-ready command sequence and how data flows from
editing a module under src/ through built packages to bootsupport,
the kit vfs and the kit executables.
The text is embedded in make.tcl (::punkboot::workflow_text) so it is
available wherever make.tcl runs; its MAINTENANCE key states the
update contract for keeping it in step with build behaviour."
}
#shared option fragments composed into the per-subcommand definitions below
variable OPT_CONFIRM {
@ -1645,6 +1803,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO
info {OPT_CONFIRM}
check {}
projectversion {}
workflow {}
}
#synopsis fragments matching the shared option fragments (explicit @form -synopsis
#so usage shows the real invocation 'make.tcl <subcommand> ...' rather than the
@ -1697,7 +1856,7 @@ if {[info exists ::env(PUNKBOOT_PLAIN)] && [string is true -strict $::env(PUNKBO
variable SUBGROUPS {
"build & promotion" {project packages modules libs vfs vfslibs bin}
"source maintenance" {vendorupdate bootsupport vfscommonupdate}
"informational" {info check projectversion help}
"informational" {info check projectversion workflow help}
"interactive" {shell}
}
punk::args::define\
@ -1891,7 +2050,8 @@ set forcekill $::punkboot::opt_forcekill
# - minor bump -> prompt user; backward-compat aliases *should* keep old bootsupport functional
# - patch bump -> warn and proceed (non-breaking)
# 'check' is exempt in all cases the warning is shown at the end of its output instead.
if {[info exists ::punkboot::stale_bootsupport] && $::punkboot::command ne "check" && $::punkboot::command ne "projectversion"} {
# 'projectversion' and 'workflow' are informational/read-only and are likewise exempt.
if {[info exists ::punkboot::stale_bootsupport] && $::punkboot::command ni {check projectversion workflow}} {
set _stale $::punkboot::stale_bootsupport
set _have_major 0
set _have_minor 0
@ -2422,6 +2582,11 @@ if {$::punkboot::command eq "projectversion"} {
exit 0
}
if {$::punkboot::command eq "workflow"} {
puts stdout [::punkboot::workflow_text]
exit 0
}
if {$::punkboot::command eq "shell"} {
package require struct::list
package require punk

Loading…
Cancel
Save