- 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
7.2 KiB
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
# 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:
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 inpyproject.tomlsuppressesE501(line-too-long) and pre-existing simplifications viaper-file-ignores— these are not blockers.
Test Workflow
# 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
_utils.pyis a leaf module — imports only from stdlib andpaperforge/config.py. Must never import frompaperforge.worker.*orpaperforge.commands.*. This prevents circular dependencies.- Worker modules do not import each other directly — use
_sync.run_selection_sync(vault)(module-reference pattern) inocr.pyto break the sync↔ocr cycle. - Config flows one way:
paperforge/config.py→_utils.py→ worker modules. No reverse imports. - Re-exports preserve backward compatibility: Moved functions retain
# Re-exported from _utils.pycomments 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
-
No new
print()calls in worker modules — uselogger = logging.getLogger(__name__)withlogger.info(),logger.debug(), etc.print()is reserved for user-facing stdout output in CLI commands (paperforge/commands/). -
Import shared utilities from
_utils.py— do not copy-pasteread_json,write_json,load_journal_db, etc. into new modules. If you need a utility, add it to_utils.pyfirst. -
_utils.pyis a leaf module — must never import frompaperforge.worker.*orpaperforge.commands.*. Violations cause circular import errors. -
Requirement IDs in commit messages — link commits to requirements using the format:
feat(UX-01): add auto_analyze_after_ocr. Requirement IDs are tracked inREQUIREMENTS.mdand.planning/. -
Pre-commit hooks run on
git commit— do not bypass them with--no-verify. Fix hook failures rather than skipping them. -
Forward slashes in paths — use
Path.as_posix()for all path-to-string conversions. This ensures consistent wikilinks regardless of OS. -
Structured logging — use
logging.getLogger(__name__)at module level. Log levels:DEBUGfor detailed diagnostics,INFOfor normal operations,WARNINGfor recoverable issues,ERRORfor failures. -
No live API calls in tests — all tests must use deterministic sandbox fixtures. Mock external services where necessary.
-
Type hints — use
from __future__ import annotationsat the top of new modules for PEP 604-style type hints. -
Backward compatibility — API breaks are unacceptable within a major version. Use function-level imports and re-exports when refactoring.
Pull Request Process
- Ensure all tests pass and lint is clean.
- Update CHANGELOG.md under
[Unreleased]with the changes. - Update documentation (AGENTS.md, command docs) if user-facing behavior changes.
- Create a pull request with a clear description of changes and motivation.
- Reference requirement IDs where applicable.
Getting Help
- Open an issue on GitHub: https://github.com/LLLin000/PaperForge/issues
- Run
paperforge doctorfor system diagnostics - Review
docs/INSTALLATION.mdanddocs/ARCHITECTURE.mdfor detailed setup and design docs
Thank you for contributing to PaperForge Lite — Building a better literature workflow, underground!