Developer Guide#

Installation From Source (Development)#

Clone the repository and install in editable mode with the dev dependency group (which provides pytest, pre-commit, and ipython):

pip install -e . --group dev

Project Layout#

historia/
├── src/historia/         # Main package source
│   ├── _cli.py           # CLI entry points
│   └── data/
│       └── github/       # GitHub data fetch/dump/update APIs
├── tests/                # Pytest test suite
├── docs/                 # Sphinx documentation source
├── AGENTS.md             # Agent/AI contributor instructions
├── CHANGELOG.md          # Release changelog
└── pyproject.toml        # Project metadata and tool configuration

Testing#

This project uses pytest for its test suite.

python -m pytest

Assertion Style#

Always place the actual (observed) value on the left and the expected value on the right:

# Correct
assert actual_value == expected_value

# Incorrect
assert expected_value == actual_value

AI-Generated Tests#

Tests written or substantially assisted by AI must be marked with the ai_generated marker:

import pytest

@pytest.mark.ai_generated
def test_something():
    ...

Use pytest.mark.parametrize wherever appropriate to reduce test duplication.

Code Quality (Pre-commit Hooks)#

This project uses pre-commit to enforce code quality automatically before each commit.

The configured hooks are:

  • black — code formatting

  • ruff — linting and import sorting (with auto-fix)

  • codespell — spell checking

  • mypy — static type checking

Install the hooks once after cloning:

pre-commit install

Run all hooks manually against all files (recommended before opening a PR):

pre-commit run --all-files

Pre-commit will auto-fix most formatting and lint issues. Re-run the command afterward to confirm everything passes.

CLI#

The Historia package exposes a single entry point:

  • historia — primary entrypoint

Commands are organized into sub-groups:

  • historia update — data management

    • historia update github — fetch raw GitHub activity data for a user

  • historia project — GitHub Project management

    • historia project create — create a new GitHub Project page

    • historia project populate — populate a project from fetched data

    • historia project update dates — update item date fields in a project

    • historia project transition — transition project items between statuses

Since every command requires at least one option, running any command or sub-group without arguments automatically prints its help text:

historia
historia update
historia project

Changelog#

Add a short description of any user-facing change to the ## Upcoming section of CHANGELOG.md under the appropriate subsection:

  • ### 🚀 Enhancement — new features

  • ### 🐛 Bug Fix — bug fixes

  • ### 📝 Documentation — documentation-only changes

  • ### 🏠 Internal — refactors, tooling, CI, and test infrastructure

  • ### 🔩 Dependency Updates — dependency-only changes

Include the GitHub PR link at the end of each entry:

- Brief description of the change. ([#N](https://github.com/CodyCBakerPhD/historia/pull/N))

Building Documentation#

Building Locally#

Install the docs dependencies:

pip install -e . --group docs

Build the HTML output:

python -m sphinx -b html docs docs/_build/html

Open docs/_build/html/index.html in your browser to preview the result.

AI Usage Addendum#

Materials across repositories in this organization have been prepared with the assistance of agentic AI coding tools and large language models (LLMs), alongside direct human authoring and supervision.

Our working practice is: 👤 Human review and accountability. We strive to have final versions of all work — prose, code, figures, and specifications — to be reviewed and/or edited by human authors, who remain accountable for the content. 🪪 Transparent annotation. Where AI tools materially contributed to a commit, we strive to annotate that commit adequately and trustworthily (for example, via a Co-Authored-By trailer identifying the tool and model version), so that the provenance of individual changes can be inspected in the git history. 🔍 Inspectable provenance. Because all work is developed in public git repositories with pull-request review, readers can trace portions of the materials which involved AI assistance.

AI tools are used as assistive instruments; they do not substitute for the scientific judgment, domain expertise, or editorial responsibility of the human authors.

Commit Co-Authorship#

When an AI tool (agent, coding assistant, IDE integration) materially contributes to a commit, the commit MUST include a Co-Authored-By trailer identifying both the tool and its version and the model and its version. This makes the git history the inspectable provenance record so anyone reading the repo can tell which tool produced which change.

Format (replace all <…> placeholders with actual values):

Co-Authored-By: <Tool> <tool-version> / <Model> <model-version> <noreply@<vendor-domain>>

Discover the tool version from the tool itself (commonly --version) and use the model identifier the tool reports. Don’t guess.

Example: Claude Code#

Co-Authored-By: Claude Code 2.1.63 / Claude Opus 4.6 <noreply@anthropic.com>

claude --version reports the Claude Code CLI version; the active model is reported by the CLI in its status / via /model.

Agent / AI Contributor Instructions#

Agent instructions#

  • Always run pre-commit before committing and pushing changes

  • To the best of your ability, ensure tests are passing

  • Follow assertion style (actual on left, expected on right)

  • Always mark AI-generated tests with ai_generated Pytest marker

  • Attempt to utilize pytest.mark.parametrize wherever appropriate to reduce duplication in test cases

  • For tests, avoid importing private-marked API functions (those with leading underscores) and always favor importing what is publicly exposed through __init__.py files

  • Bump the version in pyproject.toml once per pull request when either any file under src/ changes (excluding tests/ and docs/), or pyproject.toml itself changes.; do NOT bump for changes that are purely CI/workflow, documentation, or configuration (e.g., GitHub Actions workflows, AGENTS.md, README.md badges)

  • For API signatures, require keyword arguments for multi-input functions using (*, ...). For any function with exactly one caller-supplied parameter (excluding self and cls), require positional-only usage with the / designator

  • Leave a short description of the change or addition in the top ## Upcoming section of the CHANGELOG.md under the appropriate subsection (### 🚀 Enhancement, ### 🐛 Bug Fix, ### 📝 Documentation, ### 🔩 Dependency Updates, or ### 🏠 Internal) as a new item (line starts with -); create the subsection if it does not yet exist; include the GitHub PR link at the end of each entry in the format ([#N](https://github.com/stamped-principles/stamped-checklist/pull/N)

  • PR titles should be human-readable and in the past tense; they should NOT use conventional commit style

  • Always add new imports to the top of the file rather than locally scoped inside a function; the only exception is if it is needed to avoid a circular dependency

  • Never include code other than imports, __all__, simple import errors, or magic __dir__ overrides in any __init__.py file

  • For external dependencies, always avoid specific import style (e.g., using import abc from xyz keyword) in favor of the generic full import (e.g., import xyz; xyz.abc)

  • For internal imports, always use the relative import style (e.g., from .foo import bar); when monkeypatching such imports in tests, target the importing module’s binding, not the original definition module (e.g., foo.baz, instead of foo._bar.baz)

  • Every commit you author MUST include a Co-Authored-By trailer identifying both your tool name + version and your underlying model + version. Format (replace all <…> placeholders with actual values): `Co-Authored-By: / <noreply@>

  • Avoid using excessive em-dashes, colons, and semi-colons in written text such as documentation. Prefer breaking into separate, shorter sentences instead

  • Prefer assigning return values to named locals before return when this improves readability and debugger breakpoint placement

  • Never expose private names (those with a leading underscore) in any module’s __all__

  • Do not add compatibility aliases when renaming functions. Update all call sites to the canonical name instead

  • Favor defining one-word names for CLI flags, then map those onto longer more explicit keyword arguments at the API level