Skip to content

Worktree-copy leaks untracked files in .archon/ into committed PR via bundled-defaults regen #1578

@leex279

Description

@leex279

Summary

  • What broke: When an Archon workflow runs, the worktree-copy step pulls untracked files from the source checkout into the new worktree. If any such file lands under .archon/workflows/defaults/ (or any path scanned by generate:bundled), the workflow's validation step regenerates packages/workflows/src/defaults/bundled-defaults.generated.ts to include it, and the workflow's commit/push step then commits both the leaked file and the regenerated bundle into the PR.
  • When it started: Pre-existing — same class of issue as fix(workflows): stop sweeping scratch artifacts from every git add -A site #1506 (fix(workflows): stop sweeping scratch artifacts from every git add -A site), which fixed the git add -A sweeping path but did not address the worktree-copy + bundled-defaults regeneration vector.
  • Severity: major — silently pollutes PRs with unrelated changes; reviewers may miss the leak; reverting requires manual cleanup.

Real-world repro

Hit during work on #1576 → the resulting PR #1577 included .archon/workflows/defaults/archon-feedback.yaml (+337 lines) and a corresponding bundled-defaults.generated.ts change, neither of which had any relationship to the actual fix (a one-line path-separator normalization in scripts/check-bundled-skill.ts). Cleanup commit: 4cebf054.

Steps to Reproduce

  1. In your Archon source checkout, create an untracked file at .archon/workflows/defaults/<anything>.yaml. (Leave it untracked — do not stage or commit.) The user's case was a draft of a personal community-feedback workflow.
  2. Run any Archon workflow that produces a PR (archon workflow run archon-fix-github-issue --branch ...).
  3. When the workflow opens its PR, observe that the PR includes:
    • The untracked file you never staged (.archon/workflows/defaults/<anything>.yaml)
    • A change to packages/workflows/src/defaults/bundled-defaults.generated.ts adding an entry for it

Expected vs Actual

  • Expected: The worktree starts from a clean checkout of the target branch. Untracked files in the source checkout do not propagate into the worktree, and definitely never get committed.
  • Actual: Worktree-copy pulls the untracked file into the worktree → bun run generate:bundled (run as part of validation/self-fix) regenerates bundled-defaults.generated.ts to embed it → workflow commits both files → both end up in the PR with no warning.

Root Cause

Two-step leak:

  1. packages/isolation/src/worktree-copy.ts copies untracked files from the source checkout into the new worktree (presumably as a "preserve in-progress work" feature).
  2. scripts/generate-bundled-defaults.ts scans .archon/workflows/defaults/ and .archon/commands/defaults/ on disk; whatever it finds gets embedded into the generated bundle.

When the workflow's validation/self-fix loop runs bun run generate:bundled, the regenerated bundle picks up the leaked file. The workflow's commit step then git adds both the leaked file and the regenerated bundle.

User Flow

Maintainer source checkout              Archon workflow                    Worktree                       PR
─────────────────────────               ───────────────                    ────────                       ──
.archon/workflows/defaults/      ─copy─▶ worktree-copy.ts          ─────▶  same untracked file            
  my-scratch.yaml (untracked)            (preserves in-progress work)      now sits in worktree           
                                                                                                          
                                         self-fix runs                                                    
                                         bun run generate:bundled  ─────▶  regenerated                    
                                                                            bundled-defaults.generated.ts  
                                                                            (embeds my-scratch.yaml)      
                                                                                                          
                                         workflow commits + pushes ─────▶  [X] both files end up in PR ──▶ leaked into PR
                                                                            with no warning to maintainer

Environment

  • Platform: CLI (archon workflow run archon-fix-github-issue)
  • Database: SQLite (default)
  • Running in worktree? Yes (worktree created by Archon)
  • OS: Windows 11 — but this is OS-agnostic; the worktree-copy + bundled-defaults regen is the same on every platform.

Logs

Excerpt from the workflow run that produced PR #1577:

worktree_creating  branch: fix/issue-1576
worktree_created   path: ~/.archon/workspaces/dynamous/Archon/worktrees/archon/task-fix-issue-1576
...
[archon-self-fix-all] Started
... (regenerates bundled-defaults.generated.ts) ...
git add packages/workflows/src/defaults/bundled-defaults.generated.ts
git add .archon/workflows/defaults/archon-feedback.yaml   ← leak
git commit -m "..."
git push

Resulting PR file list (before cleanup):

.archon/workflows/defaults/archon-feedback.yaml         +337  -0
packages/workflows/src/defaults/bundled-defaults.generated.ts   +3   -2
... (the actual fix and unrelated review-driven changes) ...

Impact

  • Affected workflows/commands: any workflow that opens a PR — archon-fix-github-issue, archon-feature-development, archon-idea-to-pr, archon-plan-to-pr, archon-ralph-dag, etc.
  • Reproduction rate: Always — given an untracked file under .archon/{workflows,commands}/defaults/ in the source checkout.
  • Workaround available?
    1. Maintainer hygiene — keep .archon/{workflows,commands}/defaults/ clean of untracked files; put draft workflows in .archon/workflows/ (project-scope, not defaults/) or ~/.archon/workflows/ (home-scope) instead.
    2. After-the-fact PR cleanup — git rm the leaked file, regenerate, commit, push.
  • Data loss risk? No — but it puts user's in-progress work into a public PR, which can be a privacy/IP concern.

Suggested Fixes

A few possibilities, not mutually exclusive:

  1. Don't copy untracked files into worktrees by default — or at least exclude .archon/{workflows,commands}/defaults/ from the copy set, since those paths are bundled-defaults territory and should never include local drafts.
  2. Refuse to commit/push files that weren't part of the workflow's own changes — the workflow knows which files it edited; anything else getting auto-staged is suspicious.
  3. Warn at workflow start if the source checkout has untracked files under .archon/{workflows,commands}/defaults/ — the user almost certainly didn't mean for those to be defaults/.
  4. Lint defaults/ to require tracked statusgenerate:bundled could refuse to embed a file that's not tracked in git, surfacing the issue at validation time.

The cleanest fix is probably (1) combined with (4): worktree-copy should skip defaults/ subtrees, and generate:bundled should warn when it finds untracked files there.

Scope

  • Package(s) likely involved: isolation (worktree-copy), workflows (bundled-defaults generation)
  • Module: packages/isolation/src/worktree-copy.ts, scripts/generate-bundled-defaults.ts

Related

Metadata

Metadata

Assignees

Labels

P1High priority - Address soon, next in queuearea: isolationWorktree isolation providerarea: workflowsWorkflow enginebugSomething is brokeneffort/mediumFew files, one domain or module, some coordination needed

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions