Skip to content

feat(B-0506): mechanize stale-worktree audit — audit-stale-worktrees.ts#3224

Closed
AceHack wants to merge 2 commits into
mainfrom
feat/b-0506-audit-stale-worktrees-otto-cli-2026-05-14
Closed

feat(B-0506): mechanize stale-worktree audit — audit-stale-worktrees.ts#3224
AceHack wants to merge 2 commits into
mainfrom
feat/b-0506-audit-stale-worktrees-otto-cli-2026-05-14

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented May 14, 2026

Implements B-0506 Phase 2 / B-0519 cheap mechanization. Three hygiene tools now share the same pattern (PR #3202 rule cross-refs, PR #3208 MEMORY.md bloat, this PR for stale worktrees).

Tests: 8 pass / 21 expect calls. Live first-run: 163 worktrees, 0 stale (post-prune).

(B-0519 branch-state contamination pattern recurred; applied own workaround.)

🤖 Generated with Claude Code

AceHack and others added 2 commits May 14, 2026 16:25
…+ branch-contamination untangle

Tick output:
- PR #3221 (chore(b-0502)): new .gemini/launchd/com.zeta.backlog-ready-notifier.plist
  + AUTONOMOUS-LOOP.md + tools/bg/README.md + B-0441/B-0502 row updates. Closes
  B-0441 AC #2 ("Runs under existing launchd / cron infrastructure"). Auto-merge armed.
- This shard.

Branch-state contamination caught + untangled mid-tick:
- Local main had orphan 1856Z shard (9fa74ac) — work already on main via #3187. Reset.
- During B-0502 work, my commit landed on a different Otto's branch (the exact B-0519
  pattern). Untangled via reset + cherry-pick to the correct otto/b0502-... branch.
- ZETA_EXPECTED_BRANCH hook didn't catch the wrong-branch commit (env-var didn't
  persist across separate Bash-tool calls). Worth a follow-up row.

Substrate-or-it-didn't-happen check:
- PR #3221 = B-0502 substrate (will be on main when CI clears)
- This shard = the tick record (substrate-honest visibility of the contamination
  untangle so future-Otto sees the field-test result)

Cron sentinel 12fb713e armed at session start; one entry, recurring.

Co-Authored-By: Claude <noreply@anthropic.com>
Implements B-0506 Phase 2: a TS audit tool that catches the recurring
"branch already used by worktree at <missing-path>" lockout pattern.

What it does:
  - Enumerates 'git worktree list --porcelain'
  - For each prunable entry, tests whether its working-dir path exists
  - Reports stale entries (markdown summary)
  - With --prune, runs 'git worktree prune --expire=now -v'

Parallel in shape to PR #3202 (audit-rule-cross-refs) and PR #3208
(audit-user-scope-memory-index) — three hygiene tools now share the
same pattern.

Live first-run output: 163 total worktrees, 0 stale (post the 23-entry
prune I did earlier this session at 1817Z). The tool correctly reports
the healthy state.

Tests: 8 pass / 21 expect calls (parseWorktreePorcelain + renderReport).

Composes with B-0506 (the row this implements), B-0519 (multi-Otto
branch-state contamination RCA), the encoding-rules-without-mechanizing
rule, and the factory-hygiene-audit-cadence.yml workflow (which could
add a 3rd job for this tool in a future slice).

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 14, 2026 20:25
@AceHack AceHack enabled auto-merge (squash) May 14, 2026 20:25
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@AceHack
Copy link
Copy Markdown
Member Author

AceHack commented May 14, 2026

Branch-state contamination caught (B-0519 pattern): this PR's branch incorrectly includes Aaron's cab98bf commit (B-0502 launchd plist) which belongs on PR #3221. Closing + redoing on a clean branch with only my audit-stale-worktrees commit.

🤖 Generated with Claude Code

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Bun/TypeScript hygiene tool to audit stale Git worktree metadata and optional pruning, plus unit tests and a tick-history shard.

Changes:

  • Adds tools/hygiene/audit-stale-worktrees.ts for git worktree list --porcelain auditing and report generation.
  • Adds parser/report renderer tests for the new audit tool.
  • Adds a tick-history shard documenting branch-state contamination recovery.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
tools/hygiene/audit-stale-worktrees.ts New CLI audit/prune tool for stale Git worktree entries.
tools/hygiene/audit-stale-worktrees.test.ts Unit tests for porcelain parsing and markdown report rendering.
docs/hygiene-history/ticks/2026/05/14/2010Z.md New historical tick shard for a prior branch-state contamination episode.
Comments suppressed due to low confidence (4)

tools/hygiene/audit-stale-worktrees.ts:201

  • P1: git worktree prune is global, so running it whenever any missing-path entry exists will also prune entries in stalePathExists. That contradicts this tool's own “path still exists — investigate before prune” classification and can remove metadata for entries the report says require manual triage.
    if (parsed.args.prune && r.stalePathMissing.length > 0) {
        const p = runPrune();

tools/hygiene/audit-stale-worktrees.ts:203

  • P1: A failed prune only logs an error and main still returns 0, even though the header documents exit 0 as “prune ran successfully.” This will make cron/manual callers treat an unsuccessful cleanup as successful.
        if (!p.ok) console.error("git worktree prune exited non-zero (continuing — some entries may have pruned)");

tools/hygiene/audit-stale-worktrees.ts:138

  • P1: This new PATH-resolved git spawn also needs the repository-standard sonarjs/no-os-command-from-path suppression with a rationale; sibling worktree/git helpers already carry that documented suppression.
    const r = spawnSync("git", ["worktree", "prune", "--expire=now", "-v"], { encoding: "utf8" });

docs/hygiene-history/ticks/2026/05/14/2010Z.md:57

  • P1: markdownlint MD032 also requires a blank line before ordered lists. Add a blank line before this numbered untangle sequence so the markdown gate passes.
Untangle (per B-0519 RCA procedure):
1. `git reset --hard 5bd5697` on the contaminated branch (restored to pre-contamination

Comment on lines +120 to +122
if (entry.prunable && !existsSync(entry.path)) {
stalePathMissing.push(entry);
} else if (entry.prunable) {
}

function audit(): AuditResult | { error: string; code: AuditExitCode } {
const list = spawnSync("git", ["worktree", "list", "--porcelain"], { encoding: "utf8" });
Comment on lines +33 to +34
Substantive landing:
- New `.gemini/launchd/com.zeta.backlog-ready-notifier.plist` (copy-adapted from
@@ -0,0 +1,90 @@
# Tick 2026-05-14T20:10Z — B-0502 launchd plist for backlog-ready-notifier; branch-state contamination untangle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants