Repository navigation
TDD 0069: session-owned /build-tdds lock and 0067 follow-ups - #190
Merged
Merged
Conversation
New tests/build-hardening.test.sh drives TDD 0069's verification plan (obs 1-13 incl. 5b): tl_session_pid under real python3 parents and wrapper chains, the session-owned lock with sleeper owners, concurrent racers on temp repos, the extracted tl:lock / tl:unlock / tl:escalation-fellback-record blocks, the probe's folder cleanup against a stub claude, tl_run_retry_begin's report copy, and base-sha validation. escalation.test.sh [12] and run-record.test.sh [E] move to the new retry-begin shape and lock-line format; the aggregator registers the new eval. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
run-record.sh: tl_session_pid walks ps ancestors past shells and wrappers (never PID 1) and prints `<pid> <start>`. tl_run_lock records `pid=<pid> start=<start>`, treats an owner as live only with the same lstart, acquires with bash noclobber (not mkdir), re-enters for the same owner, refuses an unreadable line, and reclaims a dead or reused owner under a noclobber `lock.reclaim` guard with a re-read compare (stale guard broken by an atomic mv). tl_run_unlock removes only its own or a dead owner's lock; tl_run_lock_reclaim is an alias. tl_run_retry_begin copies the failed report itself and prints report= / implementer_report= / archive=. tl_escalation_fellback_check validates the base sha. SKILL.md: tl:lock / tl:unlock blocks; the fall-back reason travels by file through tl:escalation-fellback-record; step 7's rate-limit rule points to the credits_required fall-back; tl:retry-begin is one call; tl:escalation-verify validates TL_BASE_SHA. escalation-probe.sh: the EXIT trap removes the harness project folder for its mktemp scratch dir, with strict guards (never a symlink). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ki3TDnP2bNqqpEkFoZaEXq
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NpGG21Y2VGGhTQaFr4oshB
Base automatically changed from
build/20261006-131111/0068-format-and-lint-honors-config
to
master
October 6, 2026 20:08
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements TDD 0069 (PRD FR-18, FR-43, FR-88, FR-41). This PR hardens
/build-tdds(3.49.0) and adds the 0067 follow-ups. Plugin 3.50.0 → 3.51.0.What changed
Session-owned run lock (
scripts/lib/run-record.sh, FR-18 / FR-43):tl_session_pidwalks thepsancestors past shells and wrappers (bash,bwrap,timeout, …). It never returns PID 1, and it prints<pid> <start>. The lock is now owned by the long-lived session, not by the dead-on-return Bash-tool shell$$, so the FR-18 guard actually guards.pid=<pid> start=<lstart>. The owner counts as live only while that PID still has the same start time (detects PID reuse). Legacy bare-PID locks are still read.mkdir, which is not atomic on uutils. It is re-entrant for the same owner and refuses an unreadable or partial line.lock.reclaimguard, which re-reads the lock before deleting it. A stale guard is broken with an atomicmv.tl_run_unlockremoves only its own lock or a dead owner's.tl_run_lock_reclaimremains as an alias.SKILL.mdgains thetl:lock/tl:unlockblocks.0067 follow-ups (FR-88 / FR-41):
tl:escalation-fellback-record. It is never interpolated into a shell, its control bytes are stripped, and only the first line is kept.credits_requiredfall-back. That refusal is not a pause.tests/live/escalation-probe.shremoves its harness project folder on exit. It is strictly guarded and never follows a symlink.tl_run_retry_begincopies the failed report itself and printsreport=/implementer_report=/archive=.tl:retry-beginis a single call.tl_escalation_fellback_checkandtl:escalation-verifyvalidate the base sha (40-hex), so a bad value gives rc 2.Gates
test(failing)64fe70c precedesfeatf2491f8Deviations (accepted in review)
tl_run_unlocktakes an optional owner argument, mirroringtl_run_lock.tl:unlockprintslock=released.TL_REPO/TL_RUN/TL_SLUGand never reads a symlinked reason file.mv.Non-blocking review notes (follow-up candidates)
ps -o comm=can print a full path (/bin/zsh), and the stop-list comparison would then miss the shell. The fix is to strip the path and a leading-(run-record.sh:168)..stalefile (:238).:273).Not verified here
claudeescalation probe.tl_session_pidreturns rc 1 there, the skill stops loudly.🤖 Generated with Claude Code
https://claude.ai/code/session_01NpGG21Y2VGGhTQaFr4oshB