Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions .cursor/docs-scope.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Documentation Scope - Defines what needs public-facing docs vs docstrings only

# PUBLIC MODULES (comprehensive /docs required)
public_modules:
- path: "common/"
description: "Shared utilities and global configuration"
doc_level: "comprehensive"
doc_files: ["docs/api/common.md", "docs/setup/configuration.md"]
# Add new public modules:
# - path: "src/api/"
# description: "Public REST API"
# doc_level: "comprehensive"
# doc_files: ["docs/api/rest-api.md"]

# PUBLIC API PATTERNS
public_api_patterns:
- pattern: "^[^_].*" # No leading underscore
scope: "all"
- marker: "# Public API" # Explicit marker
scope: "all"

# EXPORTED APIs (user-facing imports)
exported_apis:
- "common.global_config"
- "common.global_config.GlobalConfig"

# PRIVATE MODULES (docstrings only, no /docs)
private_modules:
- {path: "src/utils/", description: "Internal utilities", doc_level: "minimal"}
- {path: "tests/", description: "Test suite", doc_level: "minimal"}
- {path: "init/", description: "Init scripts", doc_level: "minimal"}
- {path: "utils/", description: "Internal utilities", doc_level: "minimal"}

# PRIVATE API PATTERNS
private_api_patterns:
- pattern: "^_.*" # Leading underscore
scope: "all"
- marker: "# Internal only" # Explicit marker
scope: "all"

# EXCLUSIONS (never document)
exclude_from_docs:
- ".github/"
- ".git/"
- ".cursor/"
- "**/__pycache__/"
- "**/*.pyc"
- ".env*"
- "*.log"
- ".pytest_cache/"
- ".mypy_cache/"
- "node_modules/"
- "dist/"
- "build/"

# DOCUMENTATION REQUIREMENTS
documentation_requirements:
comprehensive: # Public modules
- "API reference in /docs/api/"
- "Usage examples"
- "Setup guide"
minimal: # Private modules
- "Docstrings only"
- "Inline comments for complex logic"

# UPDATE TRIGGERS
update_triggers:
high_priority_paths:
- "common/"
- "src/api/"
significant_change_threshold: 50
critical_patterns:
- "**/__init__.py"
- "**/global_config.*"
- "**/README.md"

# DOCS STRUCTURE
docs_structure:
api_reference: "docs/api/"
user_guides: "docs/guides/"
setup_instructions: "docs/setup/"
examples: "docs/examples/"
prompts: "docs/prompts/"
commands: "docs/commands/"
90 changes: 90 additions & 0 deletions .cursor/rules/documentation.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
description: Documentation standards and scope for public-facing APIs
globs:
- "docs/**"
- "**/*.md"
alwaysApply: true
---

# Documentation Standards

## Quick Reference

**ALWAYS read `.cursor/docs-scope.yml` first** - it defines what needs documentation.

### What to Document in /docs (PUBLIC APIs)
- Modules in `public_modules` (e.g., `common/`)
- Functions/classes in `__all__` exports
- Code marked `# Public API`
- No underscore prefix in public modules

### What NOT to Document in /docs (PRIVATE/INTERNAL)
- Modules in `private_modules` (e.g., `utils/`, `tests/`)
- Underscore-prefixed code (`_private_function`)
- Code marked `# Internal only`
- Paths in `exclude_from_docs`

## Decision Tree

```
Is it in public_modules? → YES = Document in /docs
Is it in __all__? → YES = Document in /docs
Has # Public API marker? → YES = Document in /docs
Has underscore prefix? → YES = Skip /docs (docstrings only)
Is it in private_modules? → YES = Skip /docs (docstrings only)
```

## Documentation Structure

Per `.cursor/docs-scope.yml`:
- **docs/api/** - API reference
- **docs/guides/** - User guides
- **docs/setup/** - Setup instructions
- **docs/examples/** - Code examples

## Quality Standards

**Public APIs** - Comprehensive:
```python
# Public API
class APIClient:
"""Client for the REST API.

See docs/api/client.md for full reference.

Example:
>>> client = APIClient("https://api.example.com")
>>> client.get("/users")
"""
```

**Private code** - Docstrings only:
```python
# Internal only
def _retry(func):
"""Internal retry helper."""
pass
```

## Markers

```python
# Public API - Forces /docs documentation
def public_func(): pass

# Internal only - Prevents /docs documentation
def _private_func(): pass
```

## Restrictions

- ✅ Modify `docs/**` only
- ❌ Never touch code, configs, or CI files
- ❌ Never over-document private utilities

## Checklist

- [ ] Read `.cursor/docs-scope.yml`
- [ ] Changes only in `docs/**`
- [ ] Only documented public APIs
- [ ] Followed docs structure from scope file
137 changes: 137 additions & 0 deletions .github/workflows/cursor_update_docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: Update Documentation

on:
push:
branches:
- main
paths-ignore:
- 'docs/**'
- '**.md'
- '.github/workflows/**'
pull_request:
types: [closed]
branches:
- main

permissions:
contents: write
pull-requests: write
actions: read

jobs:
update-docs:
# Only run on merged PRs or direct pushes to main
if: >-
${{ github.event_name == 'push' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.merged == true) }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Check if significant code changes occurred
id: check-changes
run: |
# Get the comparison base
if [ "${{ github.event_name }}" = "pull_request" ]; then
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.merge_commit_sha }}"
else
BASE_SHA="${{ github.event.before }}"
HEAD_SHA="${{ github.sha }}"
fi

# Get list of changed files
CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA")
echo "Changed files:"
echo "$CHANGED_FILES"

# Count changed lines in non-docs files
CHANGED_LINES=$(git diff --numstat "$BASE_SHA" "$HEAD_SHA" | \
grep -v "^[0-9]* [0-9]* docs/" | \
awk '{sum += $1 + $2} END {print sum}')

echo "changed_lines=$CHANGED_LINES" >> $GITHUB_OUTPUT

# Check if public-facing modules changed (from .cursor/docs-scope.yml)
# Public modules that should trigger docs updates: common/, src/api/
PUBLIC_MODULE_CHANGED=false
if echo "$CHANGED_FILES" | grep -q "^common/"; then
PUBLIC_MODULE_CHANGED=true
echo "Public module 'common/' was modified"
fi
# Add more public module checks as needed
# if echo "$CHANGED_FILES" | grep -q "^src/api/"; then
# PUBLIC_MODULE_CHANGED=true
# fi

# Check for critical file patterns
CRITICAL_CHANGED=false
if echo "$CHANGED_FILES" | grep -qE "(/__init__\.py$|global_config\.|README\.md$)"; then
CRITICAL_CHANGED=true
echo "Critical file pattern detected"
fi

# Consider it "significant" if:
# 1. More than 50 lines changed outside docs, OR
# 2. A public module changed, OR
# 3. A critical file pattern changed
if [ "$CHANGED_LINES" -gt 50 ] || [ "$PUBLIC_MODULE_CHANGED" = true ] || [ "$CRITICAL_CHANGED" = true ]; then
echo "significant=true" >> $GITHUB_OUTPUT
echo "Documentation update triggered (lines: $CHANGED_LINES, public: $PUBLIC_MODULE_CHANGED, critical: $CRITICAL_CHANGED)"
else
echo "significant=false" >> $GITHUB_OUTPUT
echo "No significant changes requiring docs update"
fi

- name: Install Cursor CLI
if: steps.check-changes.outputs.significant == 'true'
run: |
curl https://cursor.com/install -fsS | bash
echo "$HOME/.cursor/bin" >> $GITHUB_PATH

- name: Configure git identity
if: steps.check-changes.outputs.significant == 'true'
run: |
git config user.name "Cursor Agent"
git config user.email "cursoragent@cursor.com"

- name: Update documentation
if: steps.check-changes.outputs.significant == 'true'
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
MODEL: gpt-5
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_PREFIX: docs-update
run: |
cursor-agent -p "Update /docs for recent codebase changes.

Context: ${{ github.repository }}, branch: ${{ github.ref_name }}, changed lines: ${{ steps.check-changes.outputs.changed_lines }}

CRITICAL SETUP:
1. Read \`.cursor/docs-scope.yml\` - defines public vs private modules
2. Read \`.cursor/rules/documentation.mdc\` - documentation standards

SCOPE RULES:
- Document in /docs: \`public_modules\` from docs-scope.yml (e.g., common/), exported APIs, \`# Public API\` markers
- Skip /docs: \`private_modules\` (utils/, tests/), underscore-prefixed code, \`# Internal only\` markers
- Never document: Paths in \`exclude_from_docs\`

RESTRICTIONS (CRITICAL):
- ONLY modify files in /docs/** - NEVER touch code, configs, or CI files
- ONLY document public-facing APIs - NEVER over-document private/internal code
- Use \`git add docs/\` before committing

WORKFLOW:
1. Review code changes via \`git diff\`
2. Filter for public module changes only (check against docs-scope.yml)
3. Update relevant /docs files (docs/api/, docs/guides/, etc.)
4. Create branch: ${{ env.BRANCH_PREFIX }}-<timestamp>
5. Commit and push
6. Create PR: \`gh pr create --title 'docs: Update for codebase changes' --body '<list modules documented>'\`

If no public API changes, exit without creating PR.
" --force --model "$MODEL" --output-format=text
Loading