---
title: Template Synchronization
read_when:
  - "modifying commit message prompts"
  - "updating erk-diff-analysis skill references"
  - "encountering test_file_sync.py failures"
  - "working with commit-message-prompt.md"
tripwire:
  trigger: "Before modifying commit-message-prompt.md in either location"
  action: "Read [Template Synchronization](template-synchronization.md) first. Update BOTH synchronized files: .claude/skills/erk-diff-analysis/references/commit-message-prompt.md AND packages/erk-shared/src/erk_shared/gateway/gt/commit-message-prompt.md. CI test enforces byte-equality."
---

# Template Synchronization

Certain template files in erk must be kept byte-for-byte identical across multiple locations. This synchronization is enforced by automated tests but has no at-edit-time validation, so violations are discovered only during CI.

## Synchronized Files

### Commit Message Prompt

The commit message generation prompt exists in **two locations** that must be identical:

1. **Claude skill reference**: `.claude/skills/erk-diff-analysis/references/commit-message-prompt.md`
   - Used by the `erk-diff-analysis` skill when Claude generates commit messages
   - Loaded into Claude's context during skill execution

2. **Python package**: `packages/erk-shared/src/erk_shared/gateway/gt/commit_message_prompt.md`
   - Used by the Python CLI when invoking commit message generation
   - Read at runtime by the Graphite gateway

## Enforcement Mechanism

Synchronization is enforced by `tests/unit/test_file_sync.py:18-55`, specifically the test `test_diff_analysis_guide_in_sync_with_commit_message_prompt()`.

The test:

1. Reads both files using UTF-8 encoding
2. Compares content with byte-equality assertion (line 49)
3. Fails with descriptive error if content differs

**Assertion location**: `tests/unit/test_file_sync.py:49`

```python
assert claude_content == python_content, (
    "Skill prompt and Python package prompt are out of sync!\n"
    "These two files must have identical content:\n"
    f"  1. {claude_docs_copy.relative_to(repo_root)}\n"
    f"  2. {python_package_copy.relative_to(repo_root)}\n"
    "Update both files to keep them in sync."
)
```

## Why Synchronization is Required

The same prompt content serves two different execution contexts:

- **Skill context**: Claude reads the prompt when executing the `erk-diff-analysis` skill
- **CLI context**: Python code reads the prompt when invoking `erk exec gt commit-message`

If these diverge, commit messages will vary depending on whether they're generated by Claude (using the skill) or by the Python CLI (using the package copy). This inconsistency breaks the user's mental model.

## Tripwire: No At-Edit-Time Validation

There is **no mechanism** to prevent editing one file without updating the other. The only validation is the CI test.

**Common mistake**: Updating `.claude/skills/erk-diff-analysis/references/commit-message-prompt.md` to fix a Claude-side issue, forgetting to sync the Python package copy.

**Discovery**: CI failure with message "Skill prompt and Python package prompt are out of sync!"

## Update Workflow

When modifying the commit message prompt:

1. Edit **both** files with identical content
2. Verify byte-equality before committing:
   ```bash
   diff .claude/skills/erk-diff-analysis/references/commit-message-prompt.md \
        packages/erk-shared/src/erk_shared/gateway/gt/commit-message-prompt.md
   ```
3. Run the sync test locally:
   ```bash
   pytest tests/unit/test_file_sync.py::test_diff_analysis_guide_in_sync_with_commit_message_prompt
   ```

## Related Documentation

- [Commit Message Generation](commit-message-generation.md) - How the prompt is used
- [Erk Diff Analysis Skill](.claude/skills/erk-diff-analysis/skill.md) - Skill implementation
