Skip to main content
← Back to list
01Issue
BugShippedSwamp CLIPublic
Assigneesstack72

Relationships

#2187 license-headers task is a silent no-op inside .claude worktrees (absolute-path skip patterns)

Opened by skunk-ape · 9/16/2026· Shipped 9/17/2026

Problem

deno run license-headers silently does nothing when run from a Claude Code worktree under .claude/worktrees/. It reports success:

Done. Added headers to 0 files, skipped 2 (already had header).

while every new file in src/ goes untouched. integration/copyright_header_test.ts then fails on those files — after the task has already claimed there was nothing to do.

Cause

scripts/add_license_headers.ts builds its skip patterns from SKIP_DIRS and matches them against absolute paths:

skip: [...SKIP_DIRS].map((d) => new RegExp(`(^|/)${d}(/|$)`)),

SKIP_DIRS contains .claude. When the checkout itself lives under .claude/worktrees/<n>/, that pattern matches every absolute path the walk produces, so the entire tree is skipped and the script becomes a vacuous no-op.

This is a known defect that was only half-fixed

integration/copyright_header_test.ts already carries a comment describing exactly this bug and its fix — matching the skip list against the repository-relative path split on the native SEPARATOR, rather than regex-matching the absolute path:

The old form was wrong twice over: it never matched on Windows (where the separator is "\"), and when the checkout itself lived under a skipped name — e.g. a git worktree beneath .claude/worktrees/ — the pattern matched every absolute path and silently skipped the entire tree, turning the whole check into a vacuous pass.

The fix landed in the test but never reached the script, so the two now disagree: the test walks the tree correctly and fails, while the script skips it and passes.

Suggested fix

Port the test's isSkipped approach into scripts/add_license_headers.ts: compute relative(ROOT, entry.path), split on SEPARATOR, and check whether any segment is in SKIP_DIRS — instead of regex-matching the absolute path. That fixes the worktree case and the Windows case together.

Worth checking whether any other script in scripts/ shares the pattern.

Impact

Low severity, but it wastes time in a confusing way: the task reports success, and the failure surfaces later in the verification workflow as a copyright-header test failure with no obvious connection to the no-op run.

Reproduction

  1. From a worktree under .claude/worktrees/, add a new .ts file to src/ with no licence header.
  2. deno run license-headers → "Added headers to 0 files".
  3. deno run test integration/copyright_header_test.ts → fails on the new file.

Found while implementing swamp-club lab #2180.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 10 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

9/17/2026, 12:51:53 AM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack729/16/2026, 11:51:25 PM
Editable. Press Enter to edit.

stack72 commented 9/17/2026, 12:51:58 AM

Thanks @skunk-ape for reporting this! We shipped: Fix the license-header task so repository-relative exclusion checks do not mistake a .claude/worktrees checkout ancestor for an in-repository directory, eliminating its silent no-op while preserving intended excluded folders.. The fix has been merged and a release is on its way. We appreciate your contribution to swamp.

Sign in to post a ripple.