Improve agent pull request hygiene (#49469)

morgankrey created

## Summary
- Add pull request title and release notes hygiene guidance to `.rules`
- Update docs automation prompt/workflows to use compliant PR titles
- Ensure automated PR bodies include `Release Notes` when missing

Release Notes:

- N/A

Change summary

.factory/prompts/docs-automation/phase2-explore.md   |  55 --
.factory/prompts/docs-automation/phase3-analyze.md   |  57 ---
.factory/prompts/docs-automation/phase4-plan.md      |  76 ----
.factory/prompts/docs-automation/phase5-apply.md     |  67 ---
.factory/prompts/docs-automation/phase6-summarize.md |  54 --
.factory/prompts/docs-automation/phase7-commit.md    |  67 ---
.github/workflows/background_agent_mvp.yml           |  26 +
.github/workflows/docs_automation.yml                | 264 --------------
.rules                                               |  12 
script/docs-suggest                                  |   4 
script/docs-suggest-publish                          |   4 
script/run-background-agent-mvp-local                |  11 
12 files changed, 45 insertions(+), 652 deletions(-)

Detailed changes

.factory/prompts/docs-automation/phase2-explore.md 🔗

@@ -1,55 +0,0 @@
-# Phase 2: Explore Repository
-
-You are analyzing a codebase to understand its structure before reviewing documentation impact.
-
-## Objective
-Produce a structured overview of the repository to inform subsequent documentation analysis.
-
-## Instructions
-
-1. **Identify Primary Languages and Frameworks**
-   - Scan for Cargo.toml, package.json, or other manifest files
-   - Note the primary language(s) and key dependencies
-
-2. **Map Documentation Structure**
-   - This project uses **mdBook** (https://rust-lang.github.io/mdBook/)
-   - Documentation is in `docs/src/`
-   - Table of contents: `docs/src/SUMMARY.md` (mdBook format: https://rust-lang.github.io/mdBook/format/summary.html)
-   - Style guide: `docs/.rules`
-   - Agent guidelines: `docs/AGENTS.md`
-   - Formatting: Prettier (config in `docs/.prettierrc`)
-
-3. **Identify Build and Tooling**
-   - Note build systems (cargo, npm, etc.)
-   - Identify documentation tooling (mdbook, etc.)
-
-4. **Output Format**
-Produce a JSON summary:
-
-```json
-{
-  "primary_language": "Rust",
-  "frameworks": ["GPUI"],
-  "documentation": {
-    "system": "mdBook",
-    "location": "docs/src/",
-    "toc_file": "docs/src/SUMMARY.md",
-    "toc_format": "https://rust-lang.github.io/mdBook/format/summary.html",
-    "style_guide": "docs/.rules",
-    "agent_guidelines": "docs/AGENTS.md",
-    "formatter": "prettier",
-    "formatter_config": "docs/.prettierrc",
-    "custom_preprocessor": "docs_preprocessor (handles {#kb action::Name} syntax)"
-  },
-  "key_directories": {
-    "source": "crates/",
-    "docs": "docs/src/",
-    "extensions": "extensions/"
-  }
-}
-```
-
-## Constraints
-- Read-only: Do not modify any files
-- Focus on structure, not content details
-- Complete within 2 minutes

.factory/prompts/docs-automation/phase3-analyze.md 🔗

@@ -1,57 +0,0 @@
-# Phase 3: Analyze Changes
-
-You are analyzing code changes to understand their nature and scope.
-
-## Objective
-Produce a clear, neutral summary of what changed in the codebase.
-
-## Input
-You will receive:
-- List of changed files from the triggering commit/PR
-- Repository structure from Phase 2
-
-## Instructions
-
-1. **Categorize Changed Files**
-   - Source code (which crates/modules)
-   - Configuration
-   - Tests
-   - Documentation (already existing)
-   - Other
-
-2. **Analyze Each Change**
-   - Review diffs for files likely to impact documentation
-   - Focus on: public APIs, settings, keybindings, commands, user-visible behavior
-
-3. **Identify What Did NOT Change**
-   - Note stable interfaces or behaviors
-   - Important for avoiding unnecessary documentation updates
-
-4. **Output Format**
-Produce a markdown summary:
-
-```markdown
-## Change Analysis
-
-### Changed Files Summary
-| Category | Files | Impact Level |
-| --- | --- | --- |
-| Source - [crate] | file1.rs, file2.rs | High/Medium/Low |
-| Settings | settings.json | Medium |
-| Tests | test_*.rs | None |
-
-### Behavioral Changes
-- **[Feature/Area]**: Description of what changed from user perspective
-- **[Feature/Area]**: Description...
-
-### Unchanged Areas
-- [Area]: Confirmed no changes to [specific behavior]
-
-### Files Requiring Deeper Review
-- `path/to/file.rs`: Reason for deeper review
-```
-
-## Constraints
-- Read-only: Do not modify any files
-- Neutral tone: Describe what changed, not whether it's good/bad
-- Do not propose documentation changes yet

.factory/prompts/docs-automation/phase4-plan.md 🔗

@@ -1,76 +0,0 @@
-# Phase 4: Plan Documentation Impact
-
-You are determining whether and how documentation should be updated based on code changes.
-
-## Objective
-Produce a structured documentation plan that will guide Phase 5 execution.
-
-## Documentation System
-This is an **mdBook** site (https://rust-lang.github.io/mdBook/):
-- `docs/src/SUMMARY.md` defines book structure per https://rust-lang.github.io/mdBook/format/summary.html
-- If adding new pages, they MUST be added to SUMMARY.md
-- Use `{#kb action::ActionName}` syntax for keybindings (custom preprocessor expands these)
-- Prettier formatting (80 char width) will be applied automatically
-
-## Input
-You will receive:
-- Change analysis from Phase 3
-- Repository structure from Phase 2
-- Documentation guidelines from `docs/AGENTS.md`
-
-## Instructions
-
-1. **Review AGENTS.md**
-   - Load and apply all rules from `docs/AGENTS.md`
-   - Respect scope boundaries (in-scope vs out-of-scope)
-
-2. **Evaluate Documentation Impact**
-   For each behavioral change from Phase 3:
-   - Does existing documentation cover this area?
-   - Is the documentation now inaccurate or incomplete?
-   - Classify per AGENTS.md "Change Classification" section
-
-3. **Identify Specific Updates**
-   For each required update:
-   - Exact file path
-   - Specific section or heading
-   - Type of change (update existing, add new, deprecate)
-   - Description of the change
-
-4. **Flag Uncertainty**
-   Explicitly mark:
-   - Assumptions you're making
-   - Areas where human confirmation is needed
-   - Ambiguous requirements
-
-5. **Output Format**
-Use the exact format specified in `docs/AGENTS.md` Phase 4 section:
-
-```markdown
-## Documentation Impact Assessment
-
-### Summary
-Brief description of code changes analyzed.
-
-### Documentation Updates Required: [Yes/No]
-
-### Planned Changes
-
-#### 1. [File Path]
-- **Section**: [Section name or "New section"]
-- **Change Type**: [Update/Add/Deprecate]
-- **Reason**: Why this change is needed
-- **Description**: What will be added/modified
-
-### Uncertainty Flags
-- [ ] [Description of any assumptions or areas needing confirmation]
-
-### No Changes Needed
-- [List files reviewed but not requiring updates, with brief reason]
-```
-
-## Constraints
-- Read-only: Do not modify any files
-- Conservative: When uncertain, flag for human review rather than planning changes
-- Scoped: Only plan changes that trace directly to code changes from Phase 3
-- No scope expansion: Do not plan "improvements" unrelated to triggering changes

.factory/prompts/docs-automation/phase5-apply.md 🔗

@@ -1,67 +0,0 @@
-# Phase 5: Apply Documentation Plan
-
-You are executing a pre-approved documentation plan for an **mdBook** documentation site.
-
-## Objective
-Implement exactly the changes specified in the documentation plan from Phase 4.
-
-## Documentation System
-- **mdBook**: https://rust-lang.github.io/mdBook/
-- **SUMMARY.md**: Follows mdBook format (https://rust-lang.github.io/mdBook/format/summary.html)
-- **Prettier**: Will be run automatically after this phase (80 char line width)
-- **Custom preprocessor**: Use `{#kb action::ActionName}` for keybindings instead of hardcoding
-
-## Input
-You will receive:
-- Documentation plan from Phase 4
-- Documentation guidelines from `docs/AGENTS.md`
-- Style rules from `docs/.rules`
-
-## Instructions
-
-1. **Validate Plan**
-   - Confirm all planned files are within scope per AGENTS.md
-   - Verify no out-of-scope files are targeted
-
-2. **Execute Each Planned Change**
-   For each item in "Planned Changes":
-   - Navigate to the specified file
-   - Locate the specified section
-   - Apply the described change
-   - Follow style rules from `docs/.rules`
-
-3. **Style Compliance**
-   Every edit must follow `docs/.rules`:
-   - Second person, present tense
-   - No hedging words ("simply", "just", "easily")
-   - Proper keybinding format (`Cmd+Shift+P`)
-   - Settings Editor first, JSON second
-   - Correct terminology (folder not directory, etc.)
-
-4. **Preserve Context**
-   - Maintain surrounding content structure
-   - Keep consistent heading levels
-   - Preserve existing cross-references
-
-## Constraints
-- Execute ONLY changes listed in the plan
-- Do not discover new documentation targets
-- Do not make stylistic improvements outside planned sections
-- Do not expand scope beyond what Phase 4 specified
-- If a planned change cannot be applied (file missing, section not found), skip and note it
-
-## Output
-After applying changes, output a summary:
-
-```markdown
-## Applied Changes
-
-### Successfully Applied
-- `path/to/file.md`: [Brief description of change]
-
-### Skipped (Could Not Apply)
-- `path/to/file.md`: [Reason - e.g., "Section not found"]
-
-### Warnings
-- [Any issues encountered during application]
-```

.factory/prompts/docs-automation/phase6-summarize.md 🔗

@@ -1,54 +0,0 @@
-# Phase 6: Summarize Changes
-
-You are generating a summary of documentation updates for PR review.
-
-## Objective
-Create a clear, reviewable summary of all documentation changes made.
-
-## Input
-You will receive:
-- Applied changes report from Phase 5
-- Original change analysis from Phase 3
-- Git diff of documentation changes
-
-## Instructions
-
-1. **Gather Change Information**
-   - List all modified documentation files
-   - Identify the corresponding code changes that triggered each update
-
-2. **Generate Summary**
-   Use the format specified in `docs/AGENTS.md` Phase 6 section:
-
-```markdown
-## Documentation Update Summary
-
-### Changes Made
-| File | Change | Related Code |
-| --- | --- | --- |
-| docs/src/path.md | Brief description | PR #123 or commit SHA |
-
-### Rationale
-Brief explanation of why these updates were made, linking back to the triggering code changes.
-
-### Review Notes
-- Items reviewers should pay special attention to
-- Any uncertainty flags from Phase 4 that were addressed
-- Assumptions made during documentation
-```
-
-3. **Add Context for Reviewers**
-   - Highlight any changes that might be controversial
-   - Note if any planned changes were skipped and why
-   - Flag areas where reviewer expertise is especially needed
-
-## Output Format
-The summary should be suitable for:
-- PR description body
-- Commit message (condensed version)
-- Team communication
-
-## Constraints
-- Read-only (documentation changes already applied in Phase 5)
-- Factual: Describe what was done, not justify why it's good
-- Complete: Account for all changes, including skipped items

.factory/prompts/docs-automation/phase7-commit.md 🔗

@@ -1,67 +0,0 @@
-# Phase 7: Commit and Open PR
-
-You are creating a git branch, committing documentation changes, and opening a PR.
-
-## Objective
-Package documentation updates into a reviewable pull request.
-
-## Input
-You will receive:
-- Summary from Phase 6
-- List of modified files
-
-## Instructions
-
-1. **Create Branch**
-   ```sh
-   git checkout -b docs/auto-update-{date}
-   ```
-   Use format: `docs/auto-update-YYYY-MM-DD` or `docs/auto-update-{short-sha}`
-
-2. **Stage and Commit**
-   - Stage only documentation files in `docs/src/`
-   - Do not stage any other files
-   
-   Commit message format:
-   ```
-   docs: auto-update documentation for [brief description]
-   
-   [Summary from Phase 6, condensed]
-   
-   Triggered by: [commit SHA or PR reference]
-   
-   Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
-   ```
-
-3. **Push Branch**
-   ```sh
-   git push -u origin docs/auto-update-{date}
-   ```
-
-4. **Create Pull Request**
-   Use the Phase 6 summary as the PR body.
-   
-   PR Title: `docs: [Brief description of documentation updates]`
-   
-   Labels (if available): `documentation`, `automated`
-   
-   Base branch: `main`
-
-## Constraints
-- Do NOT auto-merge
-- Do NOT request specific reviewers (let CODEOWNERS handle it)
-- Do NOT modify files outside `docs/src/`
-- If no changes to commit, exit gracefully with message "No documentation changes to commit"
-
-## Output
-```markdown
-## PR Created
-
-- **Branch**: docs/auto-update-{date}
-- **PR URL**: https://github.com/zed-industries/zed/pull/XXXX
-- **Status**: Ready for review
-
-### Commit
-- SHA: {commit-sha}
-- Files: {count} documentation files modified
-```

.github/workflows/background_agent_mvp.yml 🔗

@@ -176,16 +176,18 @@ jobs:
 
           Required workflow:
           1. Read the crash report from {data_file}
-          2. Follow .factory/prompts/crash/investigate.md and write ANALYSIS.md
-          3. Follow .factory/prompts/crash/link-issues.md and write LINKED_ISSUES.md
-          4. Follow .factory/prompts/crash/fix.md to implement a minimal fix with tests
-          5. Run validators required by the fix prompt for the affected code paths
-          6. Write PR_BODY.md with sections:
+          2. Read and follow .rules.
+          3. Follow .factory/prompts/crash/investigate.md and write ANALYSIS.md
+          4. Follow .factory/prompts/crash/link-issues.md and write LINKED_ISSUES.md
+          5. Follow .factory/prompts/crash/fix.md to implement a minimal fix with tests
+          6. Run validators required by the fix prompt for the affected code paths
+          7. Write PR_BODY.md with sections:
              - Crash Summary
              - Root Cause
              - Fix
              - Validation
              - Potentially Related Issues (High/Medium/Low from LINKED_ISSUES.md)
+             - Release Notes
              - Reviewer Checklist
 
           Constraints:
@@ -231,18 +233,28 @@ jobs:
             fi
 
             if ! git diff --cached --quiet; then
-              git commit -m "fix: draft crash fix for ${CRASH_ID}"
+              git commit -m "Fix crash ${CRASH_ID}"
             fi
 
             git push -u origin "$BRANCH"
 
-            TITLE="fix: draft crash fix for ${CRASH_ID}"
+            CRATE_PREFIX=""
+            CHANGED_CRATES="$(git diff --cached --name-only | awk -F/ '/^crates\/[^/]+\// {print $2}' | sort -u)"
+            if [ -n "$CHANGED_CRATES" ] && [ "$(printf "%s\n" "$CHANGED_CRATES" | wc -l | tr -d ' ')" -eq 1 ]; then
+              CRATE_PREFIX="${CHANGED_CRATES}: "
+            fi
+
+            TITLE="${CRATE_PREFIX}Fix crash ${CRASH_ID}"
             BODY_FILE="PR_BODY.md"
             if [ ! -f "$BODY_FILE" ]; then
               BODY_FILE="/tmp/pr-body-${CRASH_ID}.md"
               printf "Automated draft crash-fix pipeline output for %s.\n\nNo PR_BODY.md was generated by the agent; please review commit and linked artifacts manually.\n" "$CRASH_ID" > "$BODY_FILE"
             fi
 
+            if ! python3 -c 'import re, sys; body = open(sys.argv[1], encoding="utf-8").read(); raise SystemExit(0 if re.search(r"Release Notes:\r?\n\s+-", body) else 1)' "$BODY_FILE"; then
+              printf '\nRelease Notes:\n\n- N/A\n' >> "$BODY_FILE"
+            fi
+
             EXISTING_PR="$(gh pr list --head "$BRANCH" --json number --jq '.[0].number')"
             if [ -n "$EXISTING_PR" ]; then
               gh pr edit "$EXISTING_PR" --title "$TITLE" --body-file "$BODY_FILE"

.github/workflows/docs_automation.yml 🔗

@@ -1,264 +0,0 @@
-name: Documentation Automation
-
-on:
-  # push:
-  #   branches: [main]
-  #   paths:
-  #     - 'crates/**'
-  #     - 'extensions/**'
-  workflow_dispatch:
-    inputs:
-      pr_number:
-        description: "PR number to analyze (gets full PR diff)"
-        required: false
-        type: string
-      trigger_sha:
-        description: "Commit SHA to analyze (ignored if pr_number is set)"
-        required: false
-        type: string
-
-permissions:
-  contents: write
-  pull-requests: write
-
-env:
-  FACTORY_API_KEY: ${{ secrets.FACTORY_API_KEY }}
-  DROID_MODEL: claude-opus-4-5-20251101
-
-jobs:
-  docs-automation:
-    runs-on: namespace-profile-8x32-ubuntu-2404
-    timeout-minutes: 30
-
-    steps:
-      - name: Checkout repository
-        uses: actions/checkout@v4
-        with:
-          fetch-depth: 0
-
-      - name: Install Droid CLI
-        id: install-droid
-        run: |
-          curl -fsSL https://app.factory.ai/cli | sh
-          echo "${HOME}/.local/bin" >> "$GITHUB_PATH"
-          echo "DROID_BIN=${HOME}/.local/bin/droid" >> "$GITHUB_ENV"
-          # Verify installation
-          "${HOME}/.local/bin/droid" --version
-
-      - name: Setup Node.js (for Prettier)
-        uses: actions/setup-node@v4
-        with:
-          node-version: "20"
-
-      - name: Install Prettier
-        run: npm install -g prettier
-
-      - name: Get changed files
-        id: changed
-        run: |
-          if [ -n "${{ inputs.pr_number }}" ]; then
-            # Get full PR diff
-            echo "Analyzing PR #${{ inputs.pr_number }}"
-            echo "source=pr" >> "$GITHUB_OUTPUT"
-            echo "ref=${{ inputs.pr_number }}" >> "$GITHUB_OUTPUT"
-            gh pr diff "${{ inputs.pr_number }}" --name-only > /tmp/changed_files.txt
-          elif [ -n "${{ inputs.trigger_sha }}" ]; then
-            # Get single commit diff
-            SHA="${{ inputs.trigger_sha }}"
-            echo "Analyzing commit $SHA"
-            echo "source=commit" >> "$GITHUB_OUTPUT"
-            echo "ref=$SHA" >> "$GITHUB_OUTPUT"
-            git diff --name-only "${SHA}^" "$SHA" > /tmp/changed_files.txt
-          else
-            # Default to current commit
-            SHA="${{ github.sha }}"
-            echo "Analyzing commit $SHA"
-            echo "source=commit" >> "$GITHUB_OUTPUT"
-            echo "ref=$SHA" >> "$GITHUB_OUTPUT"
-            git diff --name-only "${SHA}^" "$SHA" > /tmp/changed_files.txt || git diff --name-only HEAD~1 HEAD > /tmp/changed_files.txt
-          fi
-
-          echo "Changed files:"
-          cat /tmp/changed_files.txt
-        env:
-          GH_TOKEN: ${{ github.token }}
-
-      # Phase 0: Guardrails are loaded via AGENTS.md in each phase
-
-      # Phase 2: Explore Repository (Read-Only - default)
-      - name: "Phase 2: Explore Repository"
-        id: phase2
-        run: |
-          "$DROID_BIN" exec \
-            -m "$DROID_MODEL" \
-            -f .factory/prompts/docs-automation/phase2-explore.md \
-            > /tmp/phase2-output.txt 2>&1 || true
-          echo "Repository exploration complete"
-          cat /tmp/phase2-output.txt
-
-      # Phase 3: Analyze Changes (Read-Only - default)
-      - name: "Phase 3: Analyze Changes"
-        id: phase3
-        run: |
-          CHANGED_FILES=$(tr '\n' ' ' < /tmp/changed_files.txt)
-          echo "Analyzing changes in: $CHANGED_FILES"
-
-          # Build prompt with context
-          cat > /tmp/phase3-prompt.md << 'EOF'
-          $(cat .factory/prompts/docs-automation/phase3-analyze.md)
-
-          ## Context
-
-          ### Changed Files
-          $CHANGED_FILES
-
-          ### Phase 2 Output
-          $(cat /tmp/phase2-output.txt)
-          EOF
-
-          "$DROID_BIN" exec \
-            -m "$DROID_MODEL" \
-            "$(cat .factory/prompts/docs-automation/phase3-analyze.md)
-
-            Changed files: $CHANGED_FILES" \
-            > /tmp/phase3-output.md 2>&1 || true
-          echo "Change analysis complete"
-          cat /tmp/phase3-output.md
-
-      # Phase 4: Plan Documentation Impact (Read-Only - default)
-      - name: "Phase 4: Plan Documentation Impact"
-        id: phase4
-        run: |
-          "$DROID_BIN" exec \
-            -m "$DROID_MODEL" \
-            -f .factory/prompts/docs-automation/phase4-plan.md \
-            > /tmp/phase4-plan.md 2>&1 || true
-          echo "Documentation plan complete"
-          cat /tmp/phase4-plan.md
-
-          # Check if updates are required
-          if grep -q "NO_UPDATES_REQUIRED" /tmp/phase4-plan.md; then
-            echo "updates_required=false" >> "$GITHUB_OUTPUT"
-          else
-            echo "updates_required=true" >> "$GITHUB_OUTPUT"
-          fi
-
-      # Phase 5: Apply Plan (Write-Enabled with --auto medium)
-      - name: "Phase 5: Apply Documentation Plan"
-        id: phase5
-        if: steps.phase4.outputs.updates_required == 'true'
-        run: |
-          "$DROID_BIN" exec \
-            -m "$DROID_MODEL" \
-            --auto medium \
-            -f .factory/prompts/docs-automation/phase5-apply.md \
-            > /tmp/phase5-report.md 2>&1 || true
-          echo "Documentation updates applied"
-          cat /tmp/phase5-report.md
-
-      # Phase 5b: Format with Prettier
-      - name: "Phase 5b: Format with Prettier"
-        id: phase5b
-        if: steps.phase4.outputs.updates_required == 'true'
-        run: |
-          echo "Formatting documentation with Prettier..."
-          cd docs && prettier --write src/
-
-          echo "Verifying Prettier formatting passes..."
-          cd docs && prettier --check src/
-
-          echo "Prettier formatting complete"
-
-      # Phase 6: Summarize Changes (Read-Only - default)
-      - name: "Phase 6: Summarize Changes"
-        id: phase6
-        if: steps.phase4.outputs.updates_required == 'true'
-        run: |
-          # Get git diff of docs
-          git diff docs/src/ > /tmp/docs-diff.txt || true
-
-          "$DROID_BIN" exec \
-            -m "$DROID_MODEL" \
-            -f .factory/prompts/docs-automation/phase6-summarize.md \
-            > /tmp/phase6-summary.md 2>&1 || true
-          echo "Summary generated"
-          cat /tmp/phase6-summary.md
-
-      # Phase 7: Commit and Open PR
-      - name: "Phase 7: Create PR"
-        id: phase7
-        if: steps.phase4.outputs.updates_required == 'true'
-        run: |
-          # Check if there are actual changes
-          if git diff --quiet docs/src/; then
-            echo "No documentation changes detected"
-            exit 0
-          fi
-
-          # Configure git
-          git config user.name "factory-droid[bot]"
-          git config user.email "138933559+factory-droid[bot]@users.noreply.github.com"
-
-          # Daily batch branch - one branch per day, multiple commits accumulate
-          BRANCH_NAME="docs/auto-update-$(date +%Y-%m-%d)"
-
-          # Stash local changes from phase 5
-          git stash push -m "docs-automation-changes" -- docs/src/
-
-          # Check if branch already exists on remote
-          if git ls-remote --exit-code --heads origin "$BRANCH_NAME" > /dev/null 2>&1; then
-            echo "Branch $BRANCH_NAME exists, checking out and updating..."
-            git fetch origin "$BRANCH_NAME"
-            git checkout -B "$BRANCH_NAME" "origin/$BRANCH_NAME"
-          else
-            echo "Creating new branch $BRANCH_NAME..."
-            git checkout -b "$BRANCH_NAME"
-          fi
-
-          # Apply stashed changes
-          git stash pop || true
-
-          # Stage and commit
-          git add docs/src/
-          SUMMARY=$(head -50 < /tmp/phase6-summary.md)
-          git commit -m "docs: auto-update documentation
-
-          ${SUMMARY}
-
-          Triggered by: ${{ steps.changed.outputs.source }} ${{ steps.changed.outputs.ref }}
-
-          Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>"
-
-          # Push
-          git push -u origin "$BRANCH_NAME"
-
-          # Check if PR already exists for this branch
-          EXISTING_PR=$(gh pr list --head "$BRANCH_NAME" --json number --jq '.[0].number' || echo "")
-
-          if [ -n "$EXISTING_PR" ]; then
-            echo "PR #$EXISTING_PR already exists for branch $BRANCH_NAME, updated with new commit"
-          else
-            # Create new PR
-            gh pr create \
-              --title "docs: automated documentation update ($(date +%Y-%m-%d))" \
-              --body-file /tmp/phase6-summary.md \
-              --base main || true
-            echo "PR created on branch: $BRANCH_NAME"
-          fi
-        env:
-          GH_TOKEN: ${{ github.token }}
-
-      # Summary output
-      - name: "Summary"
-        if: always()
-        run: |
-          echo "## Documentation Automation Summary" >> "$GITHUB_STEP_SUMMARY"
-          echo "" >> "$GITHUB_STEP_SUMMARY"
-
-          if [ "${{ steps.phase4.outputs.updates_required }}" == "false" ]; then
-            echo "No documentation updates required for this change." >> "$GITHUB_STEP_SUMMARY"
-          elif [ -f /tmp/phase6-summary.md ]; then
-            cat /tmp/phase6-summary.md >> "$GITHUB_STEP_SUMMARY"
-          else
-            echo "Workflow completed. Check individual phase outputs for details." >> "$GITHUB_STEP_SUMMARY"
-          fi

.rules 🔗

@@ -137,6 +137,18 @@ Other entities can then register a callback to handle these events by doing `cx.
 
 - Use `./script/clippy` instead of `cargo clippy`
 
+# Pull request hygiene
+
+When an agent opens or updates a pull request, it must:
+
+- Use a clear, correctly capitalized, imperative PR title (for example, `Fix crash in project panel`).
+- Avoid conventional commit prefixes in PR titles (`fix:`, `feat:`, `docs:`, etc.).
+- Avoid trailing punctuation in PR titles.
+- Optionally prefix the title with a crate name when one crate is the clear scope (for example, `git_ui: Add history view`).
+- Include a `Release Notes:` section in the PR body with one bullet:
+  - `- Added ...`, `- Fixed ...`, or `- Improved ...` for user-facing changes, or
+  - `- N/A` for non-user-facing changes.
+
 # Crash Investigation
 
 ## Sentry Integration

script/docs-suggest 🔗

@@ -284,6 +284,10 @@ assemble_context() {
 
 You are analyzing code changes to determine if documentation updates are needed.
 
+Before analysis, read and follow these rule files:
+- `.rules`
+- `docs/.rules`
+
 ## Your Task
 
 1. Analyze the diff below for user-facing changes

script/docs-suggest-publish 🔗

@@ -179,6 +179,10 @@ cat > "$APPLY_PROMPT_FILE" << 'EOF'
 
 Apply all queued documentation suggestions below directly to docs files in this repository.
 
+Before making edits, read and follow these rule files:
+- `.rules`
+- `docs/.rules`
+
 ## Required behavior
 
 1. Apply concrete documentation edits (not suggestion text) to the appropriate files.

script/run-background-agent-mvp-local 🔗

@@ -144,11 +144,12 @@ def write_prompt(crash_id: str, crash_data_file: str | None = None) -> Path:
 
 Required workflow:
 {fetch_step}
-2. Follow .factory/prompts/crash/investigate.md and write ANALYSIS.md
-3. Follow .factory/prompts/crash/link-issues.md and write LINKED_ISSUES.md
-4. Follow .factory/prompts/crash/fix.md to implement a minimal fix with tests
-5. Run validators required by the fix prompt for the affected code paths
-6. Write PR_BODY.md with sections:
+2. Read and follow `.rules`.
+3. Follow .factory/prompts/crash/investigate.md and write ANALYSIS.md
+4. Follow .factory/prompts/crash/link-issues.md and write LINKED_ISSUES.md
+5. Follow .factory/prompts/crash/fix.md to implement a minimal fix with tests
+6. Run validators required by the fix prompt for the affected code paths
+7. Write PR_BODY.md with sections:
    - Crash Summary
    - Root Cause
    - Fix