Fix: Exclude .factory/ directory from git commits
Summary
Prevent Factory internal state files (logs, conversation history, state files) from being committed to project repositories by ensuring .factory/ is always excluded from git operations.
Problem (Bug #4 from #167)
During Stage 2 execution, PR #19 accidentally included 86 Factory internal files:
.factory/logs/2025-11-04_21-49-13_sprint/prompts/msg_*.txt(65+ prompt/response files).factory/current-sprint.json- Full conversation history from all tickets
This caused Code Reviewer to review the wrong ticket - it read Ticket #1's conversation logs and echoed that instead of reviewing Ticket #3's actual code changes.
Impact:
- Code Reviewer sees incorrect context (other tickets' conversations)
- PRs become massive (1.5MB for simple config changes)
- Exposes internal Factory operations in public repos
- Token waste (Code Reviewer reads logs instead of code)
Root Cause
.factory/directory NOT in project's.gitignoregit_addtool stages everything matching patterns without filtering- Developer agent doesn't validate staged files before committing
Solution
Primary Fix: git_add tool should auto-exclude .factory/
Update src/factory/agents/tools.py:
def git_add(files: list[str], project_path: str) -> dict:
# ... existing validation ...
# IMPORTANT: Never commit Factory internal state
# Filter out .factory/ paths before staging
filtered_files = []
for file in files:
if not file.startswith('.factory/') and '/.factory/' not in file:
filtered_files.append(file)
else:
logger.warning(f"Skipping Factory internal file: {file}")
if not filtered_files:
return {"success": False, "error": "No files to add after filtering"}
# Stage filtered files
subprocess.run(["git", "add"] + filtered_files, cwd=project_path, ...)
Secondary Fix: CLI ensures .factory/ in .gitignore
At sprint start (Stage 2), verify .factory/ is in project's .gitignore:
# In cli.py, before execute_stage_2():
gitignore_path = project_dir / ".gitignore"
if gitignore_path.exists():
content = gitignore_path.read_text()
if '.factory/' not in content:
# Append .factory/ to gitignore
with open(gitignore_path, 'a') as f:
f.write('\n# Factory internal state (do not commit)\n.factory/\n')
Test Plan
- Unit test for git_add filtering:
- Create test files including
.factory/logs/test.txt - Call
git_add(['.factory/logs/test.txt', 'src/index.ts']) - Verify only
src/index.tsstaged - Verify warning logged for
.factory/file
- E2E test:
- Start fresh sprint with test project
- Let Developer complete one ticket
- Check staged files for PR: should NOT include
.factory/* - Check
.gitignore: should contain.factory/
- Verify existing repos:
- Run CLI on existing project without
.factory/in.gitignore - Verify CLI adds it automatically
- Verify no Factory files in subsequent commits
Acceptance Criteria
- [ ]
git_addtool filters out all.factory/paths - [ ] Warning logged when Factory files are skipped
- [ ] CLI verifies/adds
.factory/to.gitignoreat sprint start - [ ] Unit tests for
git_addfiltering - [ ] E2E test verifies no Factory files in PRs
- [ ] Documentation:
.factory/should never be committed - [ ] Test on existing repo without
.factory/in.gitignore
Related Issues
- Fixes Bug #4 in #167
- Prevents Code Reviewer from seeing wrong context
- Reduces PR size and token usage
Priority
High - This causes Code Reviewer to malfunction and review wrong tickets.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗