From 2096039e03479a6ea5eb28c42afa4c3ce4280a33 Mon Sep 17 00:00:00 2001 From: Research Assistant Date: Mon, 27 Apr 2026 17:59:18 +0800 Subject: [PATCH] docs(DX-04): create CONTRIBUTING.md with dev setup and conventions - Development setup instructions (pip install -e .[test]) - Pre-commit hooks setup and hook descriptions - Test workflow with common pytest invocations - Architecture overview (two-layer design, leaf module rule) - Code conventions (10 rules: logging, imports, commit format, etc.) - Pull request process and getting help section --- CONTRIBUTING.md | 172 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..14c2d410 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,172 @@ +# Contributing to PaperForge Lite + +Thank you for your interest in contributing to PaperForge Lite! This document provides setup instructions, workflow guidelines, and code conventions to help you get started. + +--- + +## Development Setup + +```bash +# Clone the repository +git clone https://github.com/LLLin000/PaperForge.git +cd PaperForge + +# Editable install with test dependencies +pip install -e ".[test]" + +# Verify installation +python -m paperforge --version +``` + +### Requirements + +- Python 3.10+ +- Zotero + Better BibTeX plugin (for end-to-end testing) +- Obsidian (for Base view generation) +- PaddleOCR API Key (for OCR pipeline — configure in `.env`) + +--- + +## Pre-commit Hooks + +Before committing, install the pre-commit hooks to ensure code quality: + +```bash +pip install pre-commit +pre-commit install +``` + +Hooks are configured in `.pre-commit-config.yaml` and include: + +- **Ruff lint** (`ruff check --fix`) — catches common errors and style issues +- **Ruff format** (`ruff format`) — enforces consistent code formatting +- **check-yaml** — validates YAML file syntax +- **check-toml** — validates TOML file syntax +- **end-of-file-fixer** — ensures files end with a single newline +- **trailing-whitespace-fixer** — removes trailing whitespace +- **Consistency audit** (`scripts/consistency_audit.py`) — detects duplicate utility functions across modules + +> **Note:** Pre-commit hooks run automatically on `git commit`. Do not bypass them. If a hook fails, fix the issue and re-commit. The Ruff configuration in `pyproject.toml` suppresses `E501` (line-too-long) and pre-existing simplifications via `per-file-ignores` — these are not blockers. + +--- + +## Test Workflow + +```bash +# Run all tests, stop on first failure +pytest tests/ -x + +# Verbose output +pytest tests/ -v + +# Filter by keyword (e.g., OCR-related tests) +pytest tests/ -k "ocr" + +# Run with coverage report +pytest tests/ --cov + +# Collect tests only (no execution) — useful for import validation +pytest tests/ --collect-only +``` + +### Test Requirements + +- **All tests must pass before merging.** The current baseline is 203+ tests, 0 failures, 0 errors (2 pre-existing skips for PDF-dependent tests). +- **Lint must pass:** `ruff check . && ruff format --check .` +- Do not introduce new test failures or lint violations. +- Tests must not make live API calls (PaddleOCR, etc.). Use sandbox fixtures in `tests/sandbox/`. + +### Test Structure + +Tests are in `tests/` with a shared `conftest.py` providing fixtures. The `tests/sandbox/` directory contains generated deterministic fixtures for OCR, Zotero exports, and vault layouts. Fixture generation scripts are in `tests/sandbox/generate_*.py` — run these only when fixtures need updating. + +--- + +## Architecture Overview + +PaperForge Lite uses a **two-layer design**: + +``` +Worker Layer (automated, deterministic, CLI-triggered) + paperforge/worker/ + ├── _utils.py — Leaf module: shared utilities (read_json, write_json, etc.) + ├── sync.py — Zotero sync (selection-sync, index-refresh) + ├── ocr.py — OCR pipeline (upload, poll, postprocess) + ├── repair.py — State and path repair + ├── status.py — Doctor and status commands + ├── deep_reading.py — Deep-reading queue management + ├── base_views.py — Obsidian Base view generation + ├── update.py — Auto-update system + ├── _progress.py — Progress bar utilities + └── _retry.py — Retry with backoff utilities + +Agent Layer (interactive, reasoning-driven, user-triggered) + paperforge/skills/literature-qa/ + ├── scripts/ld_deep.py — /pf-deep implementation + ├── prompt_deep_subagent.md — Agent prompt for deep reading + └── chart-reading/ — 14 chart-type review guides +``` + +### Key Architecture Rules + +1. **`_utils.py` is a leaf module** — imports only from stdlib and `paperforge/config.py`. Must never import from `paperforge.worker.*` or `paperforge.commands.*`. This prevents circular dependencies. +2. **Worker modules do not import each other directly** — use `_sync.run_selection_sync(vault)` (module-reference pattern) in `ocr.py` to break the sync↔ocr cycle. +3. **Config flows one way:** `paperforge/config.py` → `_utils.py` → worker modules. No reverse imports. +4. **Re-exports preserve backward compatibility:** Moved functions retain `# Re-exported from _utils.py` comments in original modules. + +### Key Files + +| File | Purpose | +|------|---------| +| `paperforge/config.py` | Path resolution and config loading | +| `paperforge/cli.py` | CLI entry point and command routing | +| `paperforge/__main__.py` | `python -m paperforge` entry point | +| `paperforge.json` | User-facing configuration (paths, update settings, feature flags) | +| `setup_wizard.py` | Interactive first-time setup | +| `scripts/consistency_audit.py` | Duplicate utility function detection | + +--- + +## Code Conventions + +1. **No new `print()` calls in worker modules** — use `logger = logging.getLogger(__name__)` with `logger.info()`, `logger.debug()`, etc. `print()` is reserved for user-facing stdout output in CLI commands (`paperforge/commands/`). + +2. **Import shared utilities from `_utils.py`** — do not copy-paste `read_json`, `write_json`, `load_journal_db`, etc. into new modules. If you need a utility, add it to `_utils.py` first. + +3. **`_utils.py` is a leaf module** — must never import from `paperforge.worker.*` or `paperforge.commands.*`. Violations cause circular import errors. + +4. **Requirement IDs in commit messages** — link commits to requirements using the format: `feat(UX-01): add auto_analyze_after_ocr`. Requirement IDs are tracked in `REQUIREMENTS.md` and `.planning/`. + +5. **Pre-commit hooks** run on `git commit` — do not bypass them with `--no-verify`. Fix hook failures rather than skipping them. + +6. **Forward slashes in paths** — use `Path.as_posix()` for all path-to-string conversions. This ensures consistent wikilinks regardless of OS. + +7. **Structured logging** — use `logging.getLogger(__name__)` at module level. Log levels: `DEBUG` for detailed diagnostics, `INFO` for normal operations, `WARNING` for recoverable issues, `ERROR` for failures. + +8. **No live API calls in tests** — all tests must use deterministic sandbox fixtures. Mock external services where necessary. + +9. **Type hints** — use `from __future__ import annotations` at the top of new modules for PEP 604-style type hints. + +10. **Backward compatibility** — API breaks are unacceptable within a major version. Use function-level imports and re-exports when refactoring. + +--- + +## Pull Request Process + +1. Ensure all tests pass and lint is clean. +2. Update CHANGELOG.md under `[Unreleased]` with the changes. +3. Update documentation (AGENTS.md, command docs) if user-facing behavior changes. +4. Create a pull request with a clear description of changes and motivation. +5. Reference requirement IDs where applicable. + +--- + +## Getting Help + +- Open an issue on GitHub: https://github.com/LLLin000/PaperForge/issues +- Run `paperforge doctor` for system diagnostics +- Review `docs/INSTALLATION.md` and `docs/ARCHITECTURE.md` for detailed setup and design docs + +--- + +*Thank you for contributing to PaperForge Lite — Building a better literature workflow, underground!*