Acceptance verified in full (evidence in the detail file's Progress
section): concurrency suite green on Windows Tcl 9.0.3 (runtests) and
Tcl 8.6.17 (direct tcltest drive) plus a linux WSL tclsh 8.6.14 run
from a native-filesystem staging - two-writer no-corruption/no-loss
with a clean polling reader, lock timeout naming the holder, dead-pid
and age stale-breaks, non-interactive duplicate-INSTALLER recovery.
Real builds under the re-vendored 0.6.0 run with zero lock timeouts,
zero tripwire warnings and unchanged decisions.
Index entry moved to GOALS-archive.md; reference sweep: G-027's
punkcheck note updated to achieved tense, G-028 gains the
advisory-lock name-the-blocker precedent pointer. Detail file moves to
goals/archive/ in the adjacent commit (pure rename).
punkproject.toml 0.17.3 + CHANGELOG entry.
Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.com
@ -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.17.3] - 2026-07-21
- punkcheck 0.6.0 (G-095, goal achieved): concurrent writers to one `.punkcheck` file can no longer corrupt it or silently erase each other's records, and readers never see torn content. Saves are write-temp-then-atomic-rename (with reader-side retry for the Windows replace-window open denial); whole installer events hold an advisory sibling `.punkcheck.lock` (new `punkcheck::lock` namespace - holder pid/host/installer/timestamp in the lockfile, backoff-retry acquisition to a timeout that errors naming the holder, stale-break on provably-dead holder pid or age, in-process reference-counted re-acquisition; env overrides `PUNKCHECK_LOCK_TIMEOUT`/`PUNKCHECK_LOCK_STALEAGE`); deferred flushes merge own records into freshly-loaded file state; an mtime/size tripwire warns on protocol-bypassing writers; the duplicate-INSTALLER recovery raises a clean actionable error instead of prompting when stdin is non-interactive. Verified by a new concurrency suite (real child installer processes) on Windows Tcl 9.0.3 + 8.6.17 and linux (WSL tclsh 8.6.14).
## [0.17.2] - 2026-07-21
- punkcheck 0.5.0 (G-094, goal achieved): the installtrack/installevent object layer is the sole implementation of the .punkcheck record lifecycle, with a per-event persistence policy (`start_event ?-persistence eager|deferred?`; deferred updates flush via `$installer flush`, QUERY is never persisted) and a single save chokepoint (installtrack `save_working_recordset` - the G-095 attachment point). `punkcheck::install` is now a tree-walking OO consumer in deferred mode and its records carry the full field set including `-targets_cksums`. The zero-caller legacy proc pipeline (`start_installer_event`, `installfile_begin/started_install/finished_install/skipped_install`) is retired to error shims pointing at `punkcheck::installfile_help` (rewritten for the OO lifecycle). Sequential events on one installtrack no longer clobber prior targetset writes (ending an event now clears the active slot), and several latent bugs are fixed (installer-record `-name` trailing space on flush, event-history timestamp rewrites on reconstruction, `get_recordlist`, `targetset_dict`). Build skip/copy decisions are unchanged against pre-refactor `.punkcheck` state.
Acceptance: characterization suites install.test and installtrack.test pass (pins flipped only where this goal's contract deliberately changes behaviour, each flip recorded); a new test pins field equivalence between batch-installed and OO-installed records (including -targets_cksums, which the legacy proc pipeline never stored); a new regression test covers o_record_list coherence - two sequential events on one installtrack instance, with targetset writes in the first event, lose nothing at the second start_event; grep of src/modules, src/make.tcl and src/project_layouts finds no live caller of the retired trio outside shims and tests; a full make.tcl build completes with skip/copy decisions unchanged against pre-refactor .punkcheck state (no spurious recopies of unchanged sources).
Acceptance: a concurrency test drives two child tclsh installer processes against one .punkcheck folder - the file parses cleanly throughout (a polling load_records_from_file reader hits no TDL parse error), both installers' records are present afterwards, and no duplicate INSTALLER records exist; lock behaviour verified - the second writer observably waits, or times out with a message naming the holder from lockfile contents; stale-break verified against a planted orphan lockfile; suite passes on the project's Windows Tcl 8.6 + Tcl 9 test matrix (capability-gated where child-process facilities require it), with a unix run when an environment is available.
### G-102 [achieved 2026-07-21] buildsuite bootstrap without a pre-existing tclsh: zig-driver hybrid → detail: goals/archive/G-102-buildsuite-zig-bootstrap.md
Scope: src/buildsuites/suite_tcl90/ (driver split: zig-layer fetch/generate/compile + suite-tclsh-run Tcl phases; sources.config -> zon-shaped manifest migration), src/buildsuites/ (the pattern future suites fork - interplay with G-099), bin/tools/ (pinned zig acquisition per the consent-gated mechanism), src/scriptapps/bin/ punk-getzig (acquisition layer, unchanged in role)
Acceptance: from a clean checkout plus the pinned zig (acquired via the consent-gated download mechanism or self-built), a documented zig invocation performs the whole pipeline in an environment where no pre-existing tclsh is resolvable (PATH-scrubbed demonstration recorded in this file): fetch/stage sources per the declarative manifest (content-integrity pins for zig-fetched trees; the fossil-checkout flow retained as a documented dev alternative for live-branch work), generate the configure-products, build the runtime, then run the post-tclsh phases under the suite-built shell - tcllib install with tcllibc accelerators via critcl, tklib, tk - and the expected-failure-baselined test gate, with results matching the suite.tcl-driven equivalents; the manifest is the documented tweak surface and copied suite trees remain isolated (G-096 copy-and-tweak property preserved); the recipe pins the zig version it is written against (API-churn mitigation - the 0.14->0.16 migration cost is the recorded precedent); the bash+powershell polyglot alternative for this layer is recorded as considered and rejected, with polyglot craft remaining the ACQUISITION layer's mechanism (punk-getzig/getpunk first-contact story).
Goal: Concurrent writers to the same .punkcheck file cannot corrupt it or silently erase each other's records, and readers never observe torn content - every save is write-temp-then-atomic-rename (bounded retry for Windows sharing violations); an advisory cross-platform lockfile (open {WRONLY CREAT EXCL}, contents naming holder pid/host/installer/timestamp, bounded-retry acquisition, age-based stale-break with warning) serializes whole installer events per punkcheck root; deferred-mode flushes merge own records (INSTALLER by -name, FILEINFO by -targets) into freshly-loaded file state instead of wholesale overwrite; and the duplicate-INSTALLER sanity recovery degrades to a clean actionable error instead of an askuser prompt when stdin is non-interactive.
Acceptance: a concurrency test drives two child tclsh installer processes against one .punkcheck folder - the file parses cleanly throughout (a polling load_records_from_file reader hits no TDL parse error), both installers' records are present afterwards, and no duplicate INSTALLER records exist; lock behaviour verified - the second writer observably waits, or times out with a message naming the holder from lockfile contents; stale-break verified against a planted orphan lockfile; suite passes on the project's Windows Tcl 8.6 + Tcl 9 test matrix (capability-gated where child-process facilities require it), with a unix run when an environment is available.
@ -109,3 +109,67 @@ user + agent).
timeout message naming the lock holder is the advisory-lock sibling.
- Related: G-027 - a derived-project pull writing .punkcheck files while
builds run in that project is a future instance of exactly this scenario.
## Progress
- 2026-07-21 landed in full (punkcheck 0.6.0; bootsupport re-vendored the same day per the
advisory-protocol transition note; no consumer code changes were needed - see verification):
- Atomic saves: save_records_to_file is write-temp-then-atomic-rename (same-directory temp,
bounded-backoff retry for Windows sharing violations, temp cleanup on failure plus age-gated
sweep of abandoned temps). Complement found during testing: a reader's open can transiently
be denied on Windows while a writer's MoveFileEx replace is in flight, so