Shared daily/manual own-workspace cleanup contract — bounded, Git-aware, non-force reclamation of registered non-primary task worktrees and their dependency caches, with an exact same-user process observation and authoritative terminal/history/peer joins.
Resources
1Install
npx skillscat add t-benze/happyranch/workspace-cleanup Install via the SkillsCat registry.
Integrated team-move F candidate handoff (THR296seq135)
Founder-controlled teams move capability/preview/apply/show/recover now has
public service/CLI source. F proposes APPLY_AVAILABLE=True with actual native
apply AND recovery readiness gates; whole-feature independent acceptance and
manager guarded merge remain required. Skills/agents gain no execution or
ambient-bearer self-admission authority. Manage-agent retains team/role; transfers use the
separate admitted founder operation. Preview uses only the pure native planner,
not materializers/resets/reservations. Exact normalized client bytes/key are
privately fsynced before POST, including exact saved-file reuse/apply reads;
a complete prior failed-save file requires fresh descriptor/byte validation,
file fsync/close and containing-directory fsync/close. Partial/changed bytes
refuse without overwrite/new key; same-UID limitations remain. Preserve key on
transport loss and use same-key
show, never automatic second apply. HTTP202/CLI3 is in-flight, saved COMPLETE
readback/release alone permits apply200/CLI0; refusal/repair is1, parser2.
Show is read-only; recover explicitly binds SAME ID/revision and native prior
owner/process proof/CAS. Durable daemon tasks survive client disconnect; shutdown
reaps them before DB close without clearing holds. Diagnostic-org read/recovery
uses strict native owners, closes before positive normal attachment and clears
only after successful native map insertion. Native dedup redelivery follows.
Show/recover diagnostics distinguish strict saved bounded code/owner IDs and
original/latest recovery/publisher identities from current native census and
publisher owner observations. Diagnostic-only reads require no ordinary attachment
or preview; unavailable ownership stays unknown. Async failure/secondary close
or attachment facts are safe process-local observations, never durable evidence.
Resolve named dependencies before explicit SAME operation/target/revision recovery;
no automatic retry or TTL takeover. Both show GET forms declare202/CLI3 in-flight.
D staging/history/leases, C1-C3 uncertainty/EMPTY budgets and actual callbacks
remain. Earlier unavailable-E statements below describe historical checkpoints.
Current contract: docs/superpowers/specs/2026-10-14-online-team-move.md and
engineering-owned docs/runbooks/online-team-move.md. F candidate source,
independent acceptance/merge, separately authorized release loading and exact
Founder live operation are distinct. Shared bearer does not prove human presence. Behavior
UNEXECUTED, integration INCLUDING callback SKIPPED24342, units RETIRED; no new
cases/campaign, live operation, deployment or cleanup authority follows.
F native release preparation runs through OrgState.load: strict read-only move
discovery precedes naming preflight, generic compatibility writes, roster
validation, publication and producer admission. After complete native workflow
validation, the DB-owned install_team_move_schema transaction validates exact
existing layout/history/org identity, refuses held/unknown state, installs only
the literal ONE table if absent, and validates before COMMIT. Repeated compatible
attachment is idempotent. Generic Database/runtime-audit, capability/preview/show
and restricted diagnostic recovery never install or repair it. Source delivery
does not call it on production: separately authorized compatible release loading
through the supported launcher performs native preparation; Founder assembles
no files, SQL or offline manifest. Missing schema/owners are engineering release
dependencies. Even an empty installed table requires reader@3. An absent optional
layout remains compatible with generic/older readers; source rollback cannot
undo durable state or grant a downgrade.
F also freezes C2 thread retry initialization explicitly, including EMPTY
budgets. New initial/fallback/nudge phase initialization is distinct from a
frozen zero budget; deferral/reentry cannot replenish it. Old missing facts keep
their original history interpretation but refuse ambiguous new retry/reentry
with team_move_thread_retry_initialization_unknown; no history is backfilled.
Updated shell/Mac launchers require online-team-move@3 (reads old @1/@2), so
earlier supported parsers refuse before startup. Already-running old daemons,
obsolete launchers and unchecked old interpreters remain outside that guard.
All behavioral/installation/recovery/launcher observations remain UNEXECUTED.
Historical task attribution is separate from current launch eligibility. The
complete parent/child/revisit/chain/fanout/workflow closure retains task team keys,
recorded participants and permanent IDs, including retired actors authenticated
by the existing strict naming owner or native INTEGER task/result/SID attribution.
It never resolves settled history through today's manager or requires re-enrollment.
Unknown identity/graph facts remain actionable census blockers without discarding
collected inventory; dependent sessions/jobs/recovery callbacks/workflows remain
joined even for terminal tasks. New execution still requires a current executable
owner. No historical record, team, callback or binding is rewritten.
The SAME INTEGER thread invocation/agent/SID preparation owner spans native
materialization, integrity, repository refresh and launch-spec/cache preparation,
including helper-internal omissions and caught failures. Such uncertainty appends
the existing sticky failed_cleanup fact BEFORE ordinary failure settlement;
backend preparation/cleanup and native workspace/cache failures retain ownership.
Later success/callback/terminal state cannot erase it. Serializer, audit COMMIT,
strict history reader, restart/reentry and census preserve that fact, independently
of frozen EMPTY/nonempty retries. Ordinary stale-claim/agent/breaker or missing
launch-seam refusals before effects retain their native no-effect disposition;
returned failure alone never proves compensation. No new schema/journal/backfill
or generic producer identity is introduced. All behavior remains UNEXECUTED.
Ordinary tasks carry their SAME native TaskInvocation/task/agent/runtime SID
through materialization, integrity (including retries), package omissions,
repository refresh, attachment writes/cleanup, task scratch and builtin/custom
cache/workspace setup. Safe deferred ownership becomes durably prepared before
preparation resumes; this never clears existing uncertainty.
Preparation failure sets the existing local reservation cleanup flag BEFORE the
fallible strict Pause save/COMMIT, then retains execution_unknown/unknown in
the admitted journal. Terminal/callback/quiescent later attempts and safe unrelated
worktree cleanup cannot clear it. Settlement persists that fact before release;
failed saves retain local ownership and original plus persistence errors.
Restart treats unclosed task prepared entries as unknown, including terminal
rows and prepared recovery/retry owners; absence of first launch is no proof of
preparation cleanup. Unknown deferred entries cannot authorize a fresh launch.
Native pre-effect source/artifact validation, repo-scan and missing launch-seam refusals
retain their no-effect disposition. Existing retry/recovery IDs, frozen budgets,
INTEGER callbacks and authority-v2 are preserved. No new field/journal, history
backfill, compensation or clearance writer is introduced. Behavior UNEXECUTED.
D private operation and startup holds (THR296seq135)
The corrected reader is online-team-move@3 (also reads old @1/@2 records); supported
launchers pass --reader-guarded-start=online-team-move@3 and reject earlier D
readers. Per-org open/identity/SQLite errors remain diagnostic-only and survive
startup/switch readback. Restricted recovery preserves the original error on
close failure; standalone close failures retain native classification and holds.
Recovery reconciles only pre-recorded operation staging
intent/acquired identity/terminal disposition in existing audits. Unknown acquired
identity or cleanup stays held even after owner-finished; no glob deletion or
legacy evidence adoption is allowed. Native discovery and publication capture
run outside durable profile/publication mutation leases, with revision/epoch/CAS
revalidation before mutation and at final release. This grants no skill execution,
cleanup, activation, live operation or behavioral-proof authority.
Global/rebind/claim/retry/synchronization profile writers retain diagnostic roots
and refuse without diagnostic filesystem/DB acquisition while leased, even with
EMPTY dependencies.
Adapter removal reports the retained EMPTY-dependency diagnostic refusal as
HTTP409 with detail.code; its bounded ProfileCoordinatorError translation
preserves unrelated exceptions and native removal/audit/compensation.
Native startup/attachment performs positive inspection
outside leases. Matching attachment revalidates its actual already-open DB owner
in the short segment; only successful attachment clears its diagnostic. Other
roots, failed attachment, current holds and malformed history stay held. D's
own-operation/native-identity exception also checks EMPTY dependencies. Public
recovery/reattachment is source-wired by E and gated on actual native owners by F; no skill authority is granted.
D supplies private canonical/context/reset/profile/publication/recovery source.
E supplies public API/CLI source; F proposes reviewed source enablement with
separate actual apply/recovery readiness gates;
no skill or agent may invoke the private owner or use ambient bearer credentials
to self-admit a move. Manage-agent still cannot transfer teams. New startup
schema-owner discovery precedes compatibility writers and partial membership;
unknown/unresolved state keeps that org diagnostic-only and its durable holds.
Only admitted bounded same-operation recovery can reconcile exact owned images
and native owner evidence; no timeout, missing tracker or source rollback releases
it. Updated launchers require the guarded reader protocol; old running daemons
and arbitrary direct old interpreters remain outside that protection. Source
and static checks do not prove behavior. No activation/restart/live move, new
tests/campaign, callback fabrication or cleanup authority follows. Earlier C3
checkpoint text below records that slice only; current D disposition is indocs/superpowers/specs/2026-10-14-online-team-move.md. SAME13 observations stay;
behavior/recovery UNEXECUTED, integration INCLUDING callback SKIPPED24342,
Python units RETIRED. Native permission/execution enforcement is unchanged.
workspace-cleanup
Native C3 preparation failure or ordinary process return never proves file,
package or process cleanup. Unknown ownership remains in retained audit census.
New retry budgets explicitly freeze even an empty schedule; missing legacy facts
cannot authorize replenishment/reentry. Schedule runtime SID is pinned through
real preparation/spec/execution and is distinct from provider resume identity.
Custom-skill authority validates before reservations; only explicit native
validation/rollback/temporary-cleanup evidence can settle a refused writer.
No history deletion, automatic recovery, apply or execution authority follows.
An online team-move hold reserves affected agents and source/target membership. The native cleanup trigger defers before work allocation, without advancing an occurrence; real cleanup tasks and unknown process/workspace tails block the move. Never delete another owner’s workspace, clear uncertainty or fabricate settlement to free a hold. Existing cleanup authority and all preservation gates remain. Apply is unavailable; behavior remains UNEXECUTED.
THR307's independent daemon disk sweeper defaults to dry_run and has its own
ended-task/ended-structural-root, fresh jobs, recursive-age and containment
contract. Under Founder seq117 it does not inspect OS-process usage: once both
the task and its structural root have ended, nightly sweeping may remove their
task scratch and eligible worktrees. Stop and reap task-owned processes before
successful completion; do not rely on those folders afterward. Settle owned jobs;
genuine authorized native job waits keep the existing blocked/wait callbacks,
never fake completion. Filesystem mount containment remains in force.
This grants no agent deletion authority or end-of-task deletion hook, replaces
none of this skill's legacy gates, and disables none of the seven nightly agent
sessions. Other cleanup owners' process gates and old flags remain unchanged.
Durable output and sibling task-scratch manifests/locks stay excluded. Put
regenerable fixture/cache trees in runtime task-tmp; retain only concise evidence
in output. Do not run historical cleanup, activate on-mode, or use a manual
fallback on this note's authority.
The one shared workspace-cleanup skill for every agent, including no-repo
agents. It is invoked two ways, and both use exactly this contract:
Manual dispatch. The task brief's first line is exactly:
HAPPYRANCH SYSTEM WORKSPACE CLEANUP RUN (manual-dispatch)A manual request that does not carry that exact first line is
inventory-only: report candidates and skips, and take no action. Manual
runs never advance the scheduled occurrence count.Daemon daily trigger. The daemon's daily marker is exactly:
HAPPYRANCH SYSTEM WORKSPACE CLEANUP RUN (daemon-triggered)The daemon composes the brief that begins with that marker, so the same skill
and the same gates apply automatically.
Both markers identify the same skill. No other skill, task, or prompt grants
cleanup authority.
Scope
You may only ever consider paths inside your own workspace:<workspace>/repos/<repo>/.claude/worktrees/* (registered linked worktrees) and
the literal node_modules/.venv caches inside them. Never touch another
agent's workspace, the primary checkout, workspace roots, output/, memory/,
artifact stores, configuration, databases, logs, canonical skills, or any
unknown path. Never use elevation.
Report-only ordinal
The first two triggered cleanups for an agent are strictly report-only: no
deletion, no move, no modification. Only from the third triggered run, and only
when every gate below is re-derived at action time, may you act. Manual dispatch
contributes zero to that count; a manual run still requires the two prior
joined terminal daemon occurrences before it may act.
Authoritative joins (R5 / R6.5 / R7)
Authoritative recorded terminal status plus a fresh, complete, current scan of
folder use replaces separate live-session/task-to-process identity for terminal
candidates, terminal cleanup peers, and the two prior joined terminal scheduled
occurrences. Nonterminal peers block. Missing, conflicting, or incomplete
non-exempt evidence is a skip. Positive use blocks.
- R5 (target task). The owning task must be terminal and older than the
retention floor (24 hours for a cache, 7 days for a whole worktree). The
owning task and its terminal time come from the authoritative read-onlyhappyranch recallrecord; the shared OS UID and any directory mtime are
never used to establish the owner or the terminal age. - R6.5 (cleanup peers). Union all same-owner cleanup peers across all
statuses from a complete keyset-paged assigned-task lookup — the manual
marker, the daemon marker, and trigger-history rows — and omit only your own
acting task. Any nonterminal peer is a skip. Recheck after claim and again
immediately before every action. Unrelated audit history, however large,
never makes this candidate-specific join incomplete. - R7 (prior occurrences). Require exactly two distinct prior joined terminal
scheduled occurrences. Duplicates collapse. The filtered trigger audit is
read through complete keyset pages; missing, malformed, changing, or failed
pages are a skip. - Cooperative overlap. Perform the peer and listing recheck after claim and
immediately before each action. This is cooperative, not a lock. A new peer
appearing in the window makes the action a skip.
Ownership and protected paths
Only a registered, non-primary, clean whole worktree whose HEAD is durably
preserved, with no open or closed-unmerged PR for its branch, and no protection,
may be considered. Durable preservation is exactly one of: the existing
accepted durable ref (normally origin/main); a freshly verified owning-task
remote branch on origin whose head contains (is equal to or descends from)
the candidate HEAD; a confirmed merged PR for that same task branch whose
head contains the candidate HEAD; or a merged PR from any task whose head is
independently confirmed to contain the candidate HEAD. When the owning live
remote branch exists, it is authoritative: if its head does not contain the
candidate HEAD, or its containment evidence fails, refuse without consulting
owning-task or any-task merged-PR alternatives. The any-task proof
requires complete, non-truncated, double-read discovery; a stable closed PR
projection with MERGED, non-empty mergedAt, and base equal to the
double-read repository default branch; and a stable complete compare proving
the candidate is equal to or an ancestor of the PR head. Discovery alone never
counts. Another task's open or closed-unmerged PR never preserves; an owning
branch's open or closed-unmerged PR remains a refusal even if a different
merged PR contains the candidate. Missing, stale, unfetchable, truncated,
diverged, conflicting, changing, or malformed remote/PR evidence refuses. A
confirmed merged PR preserves the integrated content but may not preserve the
original commit topology. Refuse
cross-owner, protected, symlink/shared/unknown, dirty whole worktrees,
local-only or unreachable commits, and insufficient age. Never rewrite, move,
archive, bundle, tag, quarantine, or repair preserved work.
The sole dirty-tree exception is a literal immediate-child node_modules or.venv cache. Its containing worktree may be dirty, but every other gate still
applies and the action may remove only that cache. The dirty whole-worktree is
never removed or cleaned. Source bytes and Git status must be identical before
and after the cache action.
Current-use observation
Before acting, run the bundled read-only helper only through a task-bound,
host-visible HappyRanch job. Never run it directly in the cleanup session and
never fall back to an in-session scan. A whole-worktree candidate is passed as
its own target. A literal node_modules/.venv cache candidate MUST
also resolve to its containing registered worktree so that use anywhere in that
worktree (for example a process whose cwd is a sibling src/) blocks even
though the cache directory itself is untouched:
The job carries the literal, shell-quoted command for the existing packagedscripts/check_path_use.py, the active cleanup task/session binding, and a
unique receipt nonce. Submit it with the single-line happyranch jobs submit --from-file contract, wait with the same task/session binding, then consumejobs show and jobs output. Authenticate the exact job id, task, agent,
session-bearing rationale, nonce/title, interpreter, workspace cwd, script,
fresh submission time, terminal status, exit code, complete stdout/stderr, and
scanner JSON. Only exact completed + exit 0 + empty stderr + matching target
clear_observationcontinues. Rejected, failed, timeout, output-cap, nonzero,
stale, mismatched, malformed, or missing output refuses without mutation.
For a whole-worktree candidate the containing worktree is the candidate itself,
so --containing-worktree may be omitted. For a cache candidate the helper
derives the deepest registered non-primary (linked) worktree containing the
target, excluding the primary checkout identified by Git's first porcelain
record (and never selecting an unregistered nested directory such as web/).
When supplied explicitly, it must match that canonical root. Missing,
tied-deepest, unregistered, or changed registration is unknown, never adirname fallback.
It returns exactly one of clear_observation, blocked, or unknown
(never safe), and exit 0 only for clear_observation.
- Complete same-user population. Every process running as your user must be
read, except confirmed-exited processes and the fixed login/session daemons
matched by an exact readable process name AND its exact bounded cgroup
role:sshd-sessioninsession-<N>.scopeunder your user slice;systemd(the per-user manager) and(sd-pam)inuser@<UID>.service/init.scope;ssh-agentinuser@<UID>.service/app.slice/ssh-agent.service;gpg-agentinuser@<UID>.service/app.slice/gpg-agent.service;gcr-ssh-agentor itsssh-agentchild alias inuser@<UID>.service/app.slice/gcr-ssh-agent.service.
- Name alone, role alone, a unit/session lookalike, a generic
*.service/*agentwildcard, an arbitrary cgroup, or a different UID never
qualifies. A qualifying exception is deliberately not inspected:
unreadableexe/namespace does not veto it, and it is not proof the service
cannot use the path. - Root-owned processes are outside the scan — never permission to run as root.
- Any other unreadable same-user process makes coverage
unknown->
skip. A readable occupied non-exempt member isblocked. Positive use
blocks even when coverage is otherwise incomplete. - An independently absent PID/TID
statconfirms that sampled process or
thread exited. If the correspondingstatremains readable, a missing,
unreadable, or incompletestatusis an incomplete identity ->unknown,
not confirmed exit. An unparseable starttime, PID/TID reuse, or changed
real/effective/saved/fs credentials is alsounknown. - Per thread, the helper checks
cwd,root,exe,maps, and the private
FD table, and verifies cross-mount-namespace path identity. Every newly
admitted read/iteration — including each maps line and each FD entry — is
admitted against one shared deadline; an already admitted syscall is not
hard-preempted, and a scan that exhausts the deadline never claims success.
The current-use scanner treats a parseable leader Z as evidence for that task
only. It independently enumerates the bounded group frontier before requiring
leader namespaces or references. Repeated PID/TID, Tgid, starttime and complete
UID identity with repeated Z may omit only that task's dead references; live
workers still require their own cwd, root, exe, maps, private fd table,
mount/user namespaces and path resolution through their own proc root. Missing
worker census after leader exit remains unknown; Threads: 1, a controller's
TIDs or a guessed singleton never substitute for a complete census. Canonical
positive ASCII TIDs, uniqueness, actual group membership and unique complete
Pid/Tgid/Uid/State status fields are required. Malformed identities, reuse or
credential changes refuse; ordinary live R/S transitions alone are not reuse.
Thread membership/count observations converge within the existing pass cap
and shared deadline, reserving final census and identity/view checks. Known
positive use remains blocked even with incomplete evidence. Public result,
coverage and row schemas, scan/Bounds compatibility and exits 0/3/2 are retained.
For receipts from this revised source, scanned counts distinct admitted
non-exempt group leaders; exited counts distinct confirmed terminal task
identities (Tgid,TID,starttime,all four UIDs), with initially absent unbracketed
PID census slots accounted separately; vanished counts deduplicated actual
absence/closed-reference observations, including separately observed reopened
reference incarnations. A present confirmed Z contributes one exited and zero
vanished; leader/task-leader aliases and rediscovery do not recount it. These
counters are different units and must not be summed as population proof.
Historical receipts retain their original source-bound event meanings and
bytes. This correction grants no cleanup, package refresh, deployment or
live-process unreadability waiver.
This is a snapshot with a disclosed later-opener/write-interruption and
data-loss residual risk. It is not a claim of OS-wide absence or future
non-use, and it is not executable-identity authentication.
Deliberate same-user entry swapping inside an already validated cache or
worktree during removal is an accepted residual outside this accident-prevention
threat model because unlink/rmdir do not follow links outside the target; all
nested-mount, cross-device, non-owned, protected-descendant, symlink, identity,
pathname, action-time, and other accidental or ambiguous drift refusals remain
mandatory.
The sole external-symlink exception is an interpreter link directly inside<V>/bin/, where <V> is literally named .venv and has a regular ownedpyvenv.cfg. Its basename must match exactly python, python3, orpython3.<digits>. The fully resolved target must be an existing regular file
under either ${UV_PYTHON_INSTALL_DIR} (when set), otherwise${XDG_DATA_HOME:-$HOME/.local/share}/uv/python, or the one absolute home
directory recorded by that pyvenv.cfg; it must remain outside the workspace,
candidate, containing worktree, primary checkout, and every protected path.
The snapshot records the link text, resolved target, and target identity so
drift refuses. This applies to a .venv cache and to a nested .venv anywhere
inside a whole-worktree candidate. Every other external/dangling/directory or
protected symlink refuses as external_or_protected_symlink. Descriptor-rooted
deletion unlinks the symlink itself and never follows it.
Eligibility gates (literal commands)
Every gate below is re-derived at action time, before the current-use scan and
again immediately before each action. Each command is the literal check; a
non-zero exit refuses. $CANDIDATE is the literal cache or worktree path;$CONTAINING is the containing registered worktree (equal to $CANDIDATE for a
whole-worktree candidate), and for a cache candidate it must be the actual
registered root and is supplied explicitly. Worktree-level gates
(non-primary, registration, clean, durable-preservation-and-pr) inspect$CONTAINING; per-path gates (workspace-scope, ownership,filesystem-ownership, protected-task, not-symlink,same-filesystem, retention-age, cache-immediate-parent-manifest,current-use-scan) inspect $CANDIDATE. $PRIMARY is the owning primary
checkout, $WORKSPACE is your own agent workspace, $AGE_SECONDS is 86400 for
a cache or 604800 for a whole worktree, $AGENT is your own agent name, and$TASK_JSON is the authoritative happyranch recall record for the owning
task. The commands are POSIX/Linux/macOS portable and use python3 for
containment, identity, device, age and JSON so they never depend on a
platform-specific stat.
The executable forms of these gates live only inscripts/run_cleanup_candidate.sh; this document does not carry a second
copy. The shipped script executes them directly in the documented order.
That order, in both the initial and immediately-pre-action passes, is:
workspace-scopecanonical-shapenon-primaryownershipfilesystem-ownershipprotected-taskretention-agenot-symlinksame-filesystemcache-immediate-parent-manifest(cache only)registrationclean(whole worktree only)cache-gitignored-and-untracked(cache only)durable-preservation-and-prcurrent-use-scanrecursive-boundary
For the initial pass, the first authoritative peer/history join runs aftercache-immediate-parent-manifest and before registration, so cheap
candidate-local refusals do not pay for the join or later Git, PR, scan, and
tree work. The second peer/history join remains immediately before the complete
pre-action pass. No gate is omitted from either pass. Gate refusals name the
exact gate as gate:<gate-id> on the initial pass andpre_action_gate:<gate-id> on the pre-action pass; the establishedcache_not_gitignored reason remains unchanged.
cache-immediate-parent-manifest applies only to a node_modules/.venv
cache; skip it for a whole worktree. clean applies only to a whole worktree;
every other gate applies to both. A cache must also be positively Git-ignored
at its containing worktree, have no tracked entry beneath it, and produce no
tracked or untracked status row; any Git error or negative result refuses ascache_not_gitignored before isolation. A
non-exempt unreadable same-user process, a missing/ambiguous containing
worktree, or any incomplete listing makes the scan unknown -> skip; a positive
non-exempt use makes it blocked -> skip; only clear_observation with every
gate exit 0 permits the non-force action.
Preparation and observed handoff (THR-259 seq506)
Begin with the packaged scripts/prepare_cleanup.py; preparation never grants
Git, scanner or deletion clearance. Use absolute paths and a new empty evidence
directory, retaining the native inventory, complete assigned-task and filtered
trigger-history receipts, measurements, and exact historical exclusions:
python3 "$SKILL/scripts/prepare_cleanup.py" prepare --inventory "$INVENTORY" \
--history-exclusions "$HISTORY_EXCLUSIONS" --output-dir "$PREPARED" \
--max-candidates 40The captured inventory object has complete: true, binding (the literal
WORKSPACE, PRIMARY, AGENT, ORG, ACTING_TASK, SESSION_ID, CLEANUP_MARKER values),repositories_state (present or positively absent), repository_receipts,assigned_task_receipts, trigger_history_receipts, and candidates.
Each native receipt retains argv, absolute cwd, integer exit_code, stdout,
stderr and error (null for a successful complete receipt). Collect every page
before claiming completeness; a failed enumeration is never an empty census.
Each candidate retains candidate, containing, kind, allocated_bytes, its nativelisting task record and measurement_receipts. The listing has task_id,
assigned_agent, status and completed_at. This is captured source evidence, not
an authenticated clearance or permission to omit an action-time join.
The history object contains only complete, sources (absolute path and
sha256 for each exact original history/exclusion artifact) and excluded_paths.
Retain the actual prior attempts/outcomes and exclusions in those artifacts;
never replace them with counts. Unknown scope/history prevents an actionable
manifest. Historical containing-tree/cache overlap stays excluded. Do not
revive TASK9513, parked551/43, TASK10711/10918 or TASK10929 attempts.
Only explicit aware timestamp strings are accepted. Z, +00:00 and nonzero
offsets compare as UTC instants; original strings remain in the receipts.
Missing/malformed/naive/changed times and changed task/owner/status refuse.
Inclusive age floors are exactly 604800 seconds for a worktree and 86400 for a
cache, without directory mtime, guessed UTC or rounding. Both existing
candidate passes call the packaged retention helper and retain their gate
reason order. Preparation freezes at most40 by worktree/cache, terminal instant
and literal path before fresh recalls and measurements; refusal never refills.
prepared_nonempty supplies a useful exact four-key manifest; known unrelated
eligible rows may survive isolated candidate uncertainty with its reasons.no_candidates_complete is exit0 with retained native evidence and no request.
An exhausted uncertain selection or incomplete inventory/history is nonzeroincomplete, with no actionable request. No-repo agents retain native
repository-directory/configuration, assigned-task and filtered-history receipts;
PRIMARY may be empty only for this no-action preparation. They need no invented
host baseline or empty action job.
For a separately allocated marked cleanup, render one supported request withscripts/observe_cleanup_batch.py job-request --preparation ABS --output ABS --evidence-dir ABS --deadline-seconds 1200 --candidate-timeout-seconds 180 --max-runtime-seconds 2100. The evidence directory is new and beneath
workspace output/ACTING_TASK. Set CLEANUP_SESSION_DEADLINE to the explicit aware
owner deadline established from authentic session/launch evidence; an unavailable
remaining budget refuses. This helper does not discover or extend a session
budget, and a caller-supplied label alone is not authoritative launch evidence.
The wall budget exceeds deadline plus a whole candidate timeout and finite
observation/reaping margin while fitting the fresh remaining owner budget.
Retain the effective TMPDIR. There is no public clock or runner override.
The renderer emits only supported jobs fields, Bash, the current task/session,
one shell-quoted packaged observer command, and optionally an existing relative
cwd_hint. Workspace-root cwd omits the hint. Absolute/traversal/unknown fields,
unsupported values, stale artifacts/bindings and insufficient budgets refuse.
Validate against current supported SubmitBody/_validate_cwd_hint when verifying
source parity. Submit exactly once using happyranch jobs submit --org ORG --from-file ABS, preserving the original request hash and native command,
stdout/stderr/exit. Rejection or unknown transport ends that attempt; do not
change cwd, retry, submit an alternative or refill. The renderer never submits.
The outer job runs observe_cleanup_batch.py run with the frozen manifest and
history. It writes before.json, then admits only the default packaged batch
and candidate runner, then attempts after.json even after a batch failure.
Readable self UID/GID/PID/namespaces/mountinfo, host-init and one unstacked proc
mount are mandatory. Root PID1 namespace read errors are diagnostic, without
an added equality veto. This observation does not replace the unchanged nested
host scanner. Required findmnt/Git commands preserve raw stdout/stderr/exits.
Protected metadata includes workspace .codex/.aws, home .codex/.aws, primary
Git metadata, outputs/memory/artifacts/logs/configuration and skill roots,
symlink/resolved-target identity and longest covering mount. Credential contents
are never read. Positive absence requires a readable inspected ancestor;
unreadable, dangling, capped or ambiguous evidence is an error.
Baseline or before.json write failure invokes no batch. The observer retains
batch.json with native argv, cwd, exit and captured raw streams immediately after
the default batch returns, before fallible post-observation or after.json writes.
sequence.json preserves batch_started, source hashes, binding, write errors,
native batch exit and both batch/postcheck causes. An after.json or final sequence
write failure remains nonzero with unknown postcondition. If sequence.json cannot
be persisted, the single cleanup_sequence_fallback JSON on captured stdout retains
the sequence and both causes; persisted:false means no sequence file is claimed.
Each native stream is capped at1MiB. Preserve that captured fallback alongside the
native job receipt.
JSON writers flush, fsync and close a one-attempt .NAME.pending sibling before
publishing the canonical name with an exclusive hard link; existing canonical or
pending evidence is never replaced. Pending siblings remain evidence, are never
consumed as canonical receipts, and need no unlink for failure safety. This does
not add a directory-fsync/crash-durability guarantee. On observer write failure, report
--sequence must select the exact captured cleanup_sequence_fallback JSON file;
report retains its native batch/source/binding/write causes, blocks even against
success-valued pending bytes, and separately retains admitted-result/pending facts.
A missing canonical sequence also produces blocked intent with an evidence error.
Never substitute the candidate journal for a batch receipt. Batch failure, incomplete
batch, missing/malformed post evidence or protected/context drift stays nonzero
and incomplete even after another phase succeeds. Stop on evidence/report
failure. Concurrent output metadata changes are disclosed; unique reclaimed
physical bytes remain unknown. Retain the exact native journal and authenticate
actual jobs show/output identity, binding, stored command/cwd, timestamps,
terminal status and exit, complete output totals/truncation independently.
Local attempt and publication evidence
The local evidence ordering is attempt envelope → fresh native gates → canonical
eligibility → first mutation → native terminal outcome → verified fsynced journal
append → canonical reference-only acknowledgement → whole-coverage admission.
The batch journal is the sole ordered outcome ledger. Direct Bash use needs the
same bound manifest/history/journal/evidence sink; stdout alone grants no action.
Cache isolation-directory creation is mutation. Failed rename/rmdir causes and
separate original/cache/directory identity and measurements survive; only positive
restoration/absence/source/status/raw-index proof admits safe refusal. Residue or
uncertainty halts. Git read observations suppress optional index refresh.
Raw index/shared-index preservation compares device/inode/mode/owner/size and
exact bytes; mtime brackets each read but Git's shared-index timestamp touch
is not a byte or inode change.
Each attempt and acknowledgement uses the existing exclusive pending write,
flush/fsync/close and exclusive hard-link publisher. A canonical file with its
identical expected staging sibling is valid; pending alone, conflict or collision
is not. Acknowledgements reference binding, envelope/eligibility identities and
exact journal prefix/row range/hash/ordinal, without a second success ledger.
Batch resume and report preflight the entire bounded namespace and journal before
any skip/admission; orphan or unacknowledged terminal evidence blocks, including
when fallback is missing/truncated. Explicit native failure/interruption wins over
readable files. Same-batch acknowledged prefix progress and later enclosing native
batch/sequence/postcheck completeness are separate prerequisites. No automatic
recovery or directory-fsync/crash-atomic guarantee follows. Historical bytes remain
historical, with missing new-contract proof explicit; never rebind or retry them.
Captured native uncertainty (output cap, timeout, spawn/capture failure, signal or
failed publication) is distinct from a fully captured ordinary nonzero gate
denial. The writer and every eligibility/coverage/resume/report reader retain
the native cause and block action or next admission, even with healthy enclosing
files or missing fallback. Native action/capture children inherit the candidate
cancellation group. The batch stops and reconciles its owned group before
terminal observations; outer capture allows that cleanup before forced kill.
Residual or unproven survival is unknown and unsafe, never clean completion or
permission to retry. Possible mutation remains partial/unknown without reuse.
An existing empty attempt namespace or journal also requires enclosing native
recovery proof: failed envelope-directory creation cannot become a fresh run.
Direct Bash requires absolute WC_MANIFEST, WC_HISTORY, WC_JOURNAL andWC_EVIDENCE_DIR under the current WORKSPACE/output/ACTING_TASK sink,
beside the existing environment binding. It dispatches the packaged batch for
that exact candidate; WC_ATTEMPT is reserved for the batch-to-runner handoff.
The frozen manifest supplies the exact containing path/kind/allocated bytes.attempts/<manifest-ordinal>/attempt.json binds literal argv, current binding,
manifest/history/native source hashes and package identity; eligible.json
retains complete bounded native gate inputs and held snapshot/measurements.terminal-native.json retains the original outcome and complete gate/action
inputs; ack.json references only the sole journal bytes and evidence identities.
Any orphan, unexpected entry, pending-only publication or failed native input
capture halts. Complete inputs exceeding the existing bounds refuse, never trim.
Eligibility is revalidated against the held source and recursive boundary before
mutation. Source/status/index and positive postconditions remain action gates.
Compact input collection within existing readers
Use a new task-output collector command, never rewrite original native stdout.
Retain every complete native assigned-task and filtered trigger page/command
separately, with original argv/cwd/times/exits/streams/totals/cursors. Validate
terminal cursors, exact totals, unique owner IDs, repeated stable page evidence
and required peer/history coverage before producing a compact collection receipt.
The compact command's own stdout may project each listing to task_id,
assigned_agent, status and completed_at and required peer/trigger facts, with
original native files and hashes retained as provenance. Its stdout is its own
native receipt; never relabel another CLI's stdout as compact. Include repository
and measurement receipts, binding and complete original history in the WHOLE
inventory byte count (≤16MiB), not only the candidate array. Missing pages,
truncation, changed hashes or unknown history refuse. Hashes alone are not native
coverage. The reader still requires actual argv/cwd/exit/stdout/stderr/error receipt
fields; reference-only receipts are unsupported. If collection cannot meet that
contract, return the exact reader/projection boundary before action. Historical
oversized/incomplete inputs are not repaired or rebound. Frozen launch deadline,
authentic ACTIVE host/job/callback evidence and runtime-loaded provenance remain
separate operational prerequisites; these source changes grant no allocation.
Delivered procedure (executable control flow)
Execute the bundled Bash program directly; do not copy, source, extract, or
evaluate commands from this Markdown file:
bash "$SKILL/scripts/run_cleanup_candidate.sh" "$CANDIDATE" "$CONTAINING"Here $SKILL is only the caller's path to the installed skill directory used
to locate the runner. Once launched, the runner resolves its own installed
directory from the real path of its script location and uses that directory for
its sibling scripts/check_path_use.py; an inherited $SKILL never selects a
sibling helper.
CANDIDATE is the literal cache or worktree path and CONTAINING is its
registered containing worktree (the same path for a whole-worktree candidate).
Direct use dispatches the bound one-journal driver; native runner output remains
in its terminal evidence. The candidate operation returns 0 only for a verified removal and 2 only for a refusal whose final
state has no outstanding mutation, established by positive original-cache,
isolation-absence, source/status/raw-index and measurement proof after any
isolation-directory creation, rename or restoration. Exit 3 is the anomaly
family. A restoration failure before recursive deletion is the distinctisolation_anomaly / isolation_restore_failed; once descriptor-rooted
deletion begins, or git worktree remove is invoked, every later failure isremoved_with_anomaly. Both exit-3 decisions carry the anomaly reason and
measured original, isolated-candidate, isolation-directory-residue, total, and
filesystem accounting. An unavailable residual measurement is explicit (null
plus measurement_error), never a false zero. An anomaly is never reported asrefused, and further batch mutations must halt.
The observed wrapper invokes this existing resumable driver with its default
packaged runner; the following is its command shape, not an alternate unobserved
submission procedure:
python3 "$SKILL/scripts/run_cleanup_batch.py" \
--manifest "$MANIFEST" --journal "$JOURNAL" \
--history-exclusions "$HISTORY" --evidence-dir "$EVIDENCE_DIR" \
--max-candidates 40 --deadline-seconds 1200 --candidate-timeout-seconds 180Here too $SKILL is only the caller's path used to locate the installed batch
driver. The driver and each runner resolve their packaged sibling scripts from
their own locations rather than from that shell variable.
The manifest is a JSON array or JSONL with exactly candidate, containing,kind (worktree or cache), and inventory allocated_bytes. The driver
orders worktrees first and caches second, largest first within each class with
literal-path tie-breaking. It invokes this runner once per candidate with
literal argv, publishes the attempt envelope, then verifies/fsyncs a terminal
journal row and publishes its acknowledgement after every attempt. Only a
closed-schema exit-2 pre-action receipt (refused, report_only, orinventory_only) and a closed-schema exit-0 verified-removal receipt permit the
next candidate. Any exit 3, timeout, signal death, unreceipted nonzero exit,
malformed/missing output, exit/receipt mismatch, runner exception, or other
unclassifiable result is journaled and halts the batch with a nonzero exit. Each
runner owns a new process session; timeout sends SIGTERM then SIGKILL to the
whole process group, reaps the runner, and records whether group survival could
be ruled out before halting. A later reader requires complete enclosing native
observation/sequence and whole-namespace acknowledgement coverage before it
skips a unique, valid terminal row
whose candidate, containing worktree, kind, allocated bytes, and exact argv
match the current manifest. A stale, malformed, unsafe, duplicate, or conflicting
journal row fails closed before any runner starts. Bounds stop only between
candidates: the batch deadline prevents starting a new candidate but never
preempts one already in flight. The separate per-candidate timeout still
terminates that candidate's whole process group, journals the unsafe halt, and
stops the batch with a nonzero exit; such a row remains deliberately
unresumable.
Run each observed wrapper as a durable happyranch job bound to the cleanup task's
current ACTIVE task/session, choose a batch/deadline comfortably inside one
session (target at most about 40 minutes), ensure the job wall budget exceeds
the batch deadline plus one full per-candidate timeout, and wait in-session withhappyranch jobs wait. The per-candidate runner still submits and authenticates
its own nested host-visible scan job at action time; never replace that scan
with an in-process shortcut. If the session ends mid-batch, later nested job
submissions fail closed without mutation; a later cleanup task resumes from the
fsync'd journal. This outer-job-to-nested-scanner flow is verified on a
disposable target; an unknown scanner result remains an ordinary fail-closed
refusal rather than a batch-wide stop.
Authorized actions (non-force only)
Cache. Atomically isolate one literal real
node_modulesor.venv
directory inside a same-filesystem private sibling boundary, revalidate its
inode/tree/owner/device and the protected-set identity against the complete
action snapshot, then open and recursively remove only that isolated object
through authenticated no-follow directory descriptors. A replacement before
descriptor admission refuses without deletion. Descriptor-relative primitive
support is checked only after the candidate has been moved into private
isolation: an unsupported platform refuses before recursive deletion only
when the caller successfully restores the cache. A failed restoration emits
exit-3isolation_anomaly/isolation_restore_failed, measures both the
original and isolated locations plus isolation-directory residue, and halts
the batch; it is never a refusal and never emitsremoved_cache. The cache must be
inside a registered, non-primary linked worktree of your own workspace, and
removal is allowed only when its
immediate parent has the accepted lock/manifest, the owning task has been
terminal past the 24-hour floor, durable preservation/no-open-or-unmerged-PR
evidence clears, and the exact host-job current-use receipt clears. The
containing worktree may otherwise be dirty; preserve its source bytes and
exact Git status and never remove or clean that worktree.Whole worktree. After seven terminal days, remove one clean registered
non-primary worktree with exactly:git -C <primary> worktree remove <literal-path>Never
--force. Never userm -rf, a glob, a parent root, orgit cleanto remove a worktree;git worktree pruneis allowed only for an
already-missing registered path after a dry-run confirms the exact stale
record. Cache recursion uses only the descriptor-rooted primitive above,
neverrm -rfor a later standalone pathname dispatch. A changed or
reappearing original candidate path, isolation residue, or identity mismatch
fails stopped and never emitsremoved_cache.
The procedure's JSON action receipt records the literal path, apparent and
allocated bytes before/after, filesystem free space before/after, and the
concurrent/unattributed filesystem delta. Record literal argv and exit status
beside that receipt and perform protected-path postchecks. Stop further
mutations on any action, evidence, or report failure.
This implementation and witness task deletes no production residue, never
deploys, restarts, activates a flag, or sweeps. That prohibition belongs to this
delivery task; the separately authorized future daily/manual use of this skill
retains exactly the narrow cache/worktree actions and protections above, under
the same action-time gates.
Reporting
Complete through the normal task contract, creating output/<task_id>/ withinventory.json, final-ledger.jsonl, and report.md. Routine scheduled and
exact-marker manual cleanup results remain durable on the existing agent page
through normal task completion/results. Do not create cleanup-report threads or
post routine cleanup results to threads. There is no routine thread reuse obligation. Preserve all historical threads,
messages, associations, results and audits. Explicit founder-requested coordination
and required callbacks remain.
Three supporting indexes accelerate the existing read-only cleanup projection.
They do not backfill history, increment daemon count or grant cleanup authority.
Report actual removed/skipped counts and reasons, measured sizes, allocated and
apparent bytes separately, unknown unique reclaimed bytes, failures, partial
outcomes and independent verification gaps honestly in summary and risks. Never
turn unavailable measurement or an unverified outcome into zero or success.
The durable batch journal is the ordered source for final-ledger.jsonl;
preserve each literal argv, timestamps, exit status, native parsed receipt or
malformed raw output, and stop reason/stop facts.
Use observe_cleanup_batch.py report with absolute inventory, sequence,
task-projection, result-projection, audit-projection and output-dir paths, plus
--preparation ABS for a prepared no-action manifest with known excluded rows, to
retain publication.json and a current completion-intent.json. These are local
artifacts. Reporting verifies current inventory binding and native receipts.
For nonempty inventory with only known exclusions, it checks the same-bound
preparation against original and copied inventory hashes, manifest/history hashes,
original history sources, owner receipt and independently reconstructed excluded
rows at the retained observation time. A state string alone supplies no proof.
A verified empty manifest retains the nonempty inventory and all exclusion/peer/
history receipts, emits no request and needs no invented batch baseline. Changed,
mismatched, uncertain or missing preparation evidence stays incomplete.
Result admission/terminal-pending is a separate retained fact: missing/incomplete
inventory, failed baseline, missing/failed postcheck or sequence/write failure
still produces blocked intent and nonzero exit despite an admitted result.
Complete-evidence pending remains useful local evidence, never a sent callback.
A failed executor/lifecycle or absent canonical output publication
overrides a local success payload or persisted result ID. While the genuine
session is still alive, an admitted result can honestly be terminal-pending;
that is not proof of callback failure. Original callback command/HTTP/CLI exit
or full executor error remains missing until native evidence exists. Never
replay a callback or rewrite historical results. The report helper never sends
one. Final callback stdout/exit belongs to the native session receipt and
later supported parent reads; no action follows the final callback to inspect it.
Use the normal task-owner or subtask summary protocol and submithappyranch report-completion --org <slug> --from-file <ABSOLUTE_PAYLOAD_PATH>
with the current session binding as the final action. Artifact writing alone is
not completion. Truthful anomalies and required escalations remain.
Root task Pause outcomes
A held/deferred task is unfinished, not terminal/orphan evidence. Preserve its worktree and original owner. Terminal lifecycle alone cannot discharge possible-launch, host/tree or cleanup ACTION uncertainty; use the existing authoritative evidence and non-force contract. Pause does not change scheduler/selector eligibility or authorize reclamation. Real admitted cleanup runs under its existing owner after commitment; interrupted ACTION stays unknown and must not be replayed.
Separate future root-terminal owner
This manual/daily procedure keeps its marker, age, ordinal, peer/history,
authenticated host-job scanner and cache gates. Its Git preservation,
recursive snapshot and protected post-action identities call the same bundledworktree_safety.py as the runtime root owner. Owning live-branch contradiction
refuses before fresh default or squash/merged-PR fallback. Recursive enumeration
and capture are bounded; unknown evidence retains.
Only a newly committed structural root in completed/failed/cancelled/superseded
can reconsider its parent tree after teardown, including NULL-parent workflow
tasks. Revisit/supersession links protect, never enroll other families. Child
recorded deferral is advisory only at that root pass, without result/history
rewrites. Dirty/local-only/open/active/held/successor-used/protected/unknown paths
retain. This skill does not authorize agents to invoke a root pass manually or
rescan already-terminal roots.
Root admission uses bounded raw task audit under the existing lock and a stable
committed start INTEGER id; replay/missing finish never retries. One owner batch
shares 10s work (0.5s DB,50ms lock admissions),1s report and1s owned-group reap;
16 events/256 nodes/depth64/page64/16 attempts,5s clipped candidate ceiling,
200000 recursive/pending entries,1MiB capture and256KiB receipts. The 12s target
is conditional on ordinary synchronous SQLite/storage/kernel I/O. Incomplete
membership/protection means zero removal with exact frontier/unknown total;
action caps name all remainder. Non-force success requires absence,
unregistration, preserved branch and protected identities. Possibly partial
post-action/report anomaly halts later mutation. Terminal/results/history/report
survive refusal/failure. No queue, retry, detached action, extra schedule,
cache-only root action, deployment or historical authority is added.
C3 writer disposition follows the actual authority/profile interval through
native naming reconciliation and explicit leading validation. Stale rename or
prompt CAS may settle only after successful native rollback/reconciliation;
unfenced status alone proves nothing. Caught reconciliation/publication/clone
failure, cancellation and partial effects retain unknown ownership. Skill scratch
cleanup requires no-follow lstat ENOENT; surviving entries, inspection errors and
prior uncertainty stay unknown. Cleanup causes are retained; existing unknown
history is never cleared. These are source accounting rules, not behavioral
verification or new execution/activation authority.
Current-main C3 composition preserves automatic job admission: omitted/false
review_required executes through native owner checks; true refuses before allocation,
legacy true pending is inert, and /run remains a tombstone. Authenticated later
prerequisite loss rechecks move/causal ownership in the native Pause transaction
before its failed-before-launch CAS, audit/journal COMMIT and genuine wake. Only
that exact completed no-launch refusal may settle; partial scratch/environment,
output or process effects and earlier uncertainty remain in producer history.
Naming keeps INSTALL-only N-SAC-1 structural admission and actual install-diagnostic
provenance alongside SAME native disposition, rollback and reconciliation rules;
no removed whole-release naming fingerprint is restored.
The scheduled daemon disk worker reserves a global native writer per admitted
org before spawn, through supervision/reap/report. Held/unowned orgs defer with
bounded codes in the existing summary/audit; other admitted orgs continue. On-mode
child admission and prune re-read the actual parent's active global writer ID
through strict append-only history and validate the optional move layout/hold.
An installed layout with missing/unknown ownership refuses before mutation; absent
layout preserves native behavior. Missing/incomplete effect closure, interruption
and partial mutation retain unknown writer evidence; a clean later provider result
cannot erase it. The common1800-second window includes reservation admission.
Off/default dry_run, metadata/process/age/containment safeguards and manual dry-run
remain; no cleanup/activation authority follows. These source changes have no
behavioral/migration/recovery proof; integration INCLUDING callback SKIPPED24342,
Python units RETIRED. That C3 checkpoint had no COMPLETE writer; current D/E/F
source and independent gates are described above. No live capability follows.