Repo-wide conventions for this project and related repos.
Core principles guide work in this repo. Cite them by name when making judgment calls. This file is the canonical home for all core principles; sibling docs and AGENTS.md should cross-reference, not restate.
- Focus on important issues. Make sure we are worrying about the correct things, and not bikeshedding i.e. spending excessive time discussing trivial issues while neglecting more important ones.
- Use the scientific method. Treat plans as hypotheses, not conclusions. Use small experiments, comparisons, and measurements to reduce uncertainty before locking in a design. Let evidence refine the plan as work proceeds.
- Fix the design, not the symptom. When something behaves wrong, fix the design that allowed the problem. Do not add fallbacks, special cases, or broad try/except blocks just to hide the symptom.
- Long-term over short-term. Accept a small cost now to avoid larger costs later. Prefer the durable fix over the quick patch, even when the durable fix takes more effort today.
- Design for adaptability. Favor systems that can evolve as requirements and understanding change. Keep responsibilities clear and components replaceable so the software remains useful without repeated rewrites.
- Dream big. Build on the ambition already present. Pursue the strongest, most durable, and most complete version of the work, then turn that ambition into practical next steps.
- Perfect is the enemy of good. Prefer a good solution delivered promptly when further refinement would not materially improve the outcome. Spend additional effort where it changes correctness, durability, or user value.
- Atomic task decomposition. Break hard problems into the smallest independently completable tasks. Each task should have one owner, one clear outcome, and one verification step.
- Prompt positively. Tell the model what to do, not what to avoid. Small LMs can confuse negative prompting with positive instructions, which can lead to poor code and seriously flawed results. Prefer direct instructions like "use explicit key access" over negative ones, like "do not use dict.get()"
- Fresh subagent per task. Give each independent task to a new subagent with a self-contained prompt. Reusing a subagent across tasks carries stale context, encourages drift, and weakens independent judgment. When a subagent is performing suboptimal, kill and replace it rather than negotiating.
- Be efficient with time. Subagents and tokens are cheap; wall time is not. Use parallel atomic tasks when the work is independent and doing so shortens implementation time.
- Finish the obvious. Continue while the next safe step is defined by the plan, implied by the task, or required to verify the work. Obvious follow-on work is part of the task, not a bonus. Stop only at a real blocker, risky action, or change to the user's requested outcome.
- Prefer small, single-purpose scripts at the repo root.
- Create topic folders only when a collection needs grouping.
- Avoid deep nesting; keep paths short.
- Keep
README.mdandAGENTS.mdat the repo root. - Determine REPO_ROOT with
git rev-parse --show-toplevel, not by deriving paths from the current working directory.
Keep AGENTS.md files concise and operational. They should usually be around
100-150 lines and focus on specific tasks, workflows, and constraints.
Do not use AGENTS.md for long philosophical discussions or duplicated style
guidance. Put canonical explanations in the appropriate docs/*.md file, then
link to that file from AGENTS.md.
Concise AGENTS.md files help coding agents perform better because the
instructions are easier to scan, prioritize, and follow.
docs/HUMAN_GUIDANCE.md: durable human preferences, project-specific guidance, review expectations, and stable decisions that agents should preserve across planning and implementation work.- Use this file for long-term guidance that prevents drift across manager and subagent runs.
- Keep entries focused on stable preferences and recurring project decisions, not transient task notes.
- Link to
docs/HUMAN_GUIDANCE.mdfromAGENTS.mdwhen agents need the guidance during routine work. - Update this file when the human gives a stable correction, workflow preference, review rule, or project priority that should apply to future tasks.
- Prefer positive phrasing. State the behavior agents should follow.
- Keep detailed history in
docs/CHANGELOG.md; keep current human guidance indocs/HUMAN_GUIDANCE.md.
- The first paragraph of
README.mdis the source text for the GitHub About description. - The first paragraph must remain readable as raw Markdown source text.
- Repository About descriptions must stay under 250 characters.
- Agents edit only the first paragraph of
README.md; the user copies that text into the GitHub About field. - Write a clear, searchable hook that helps readers quickly understand the repository.
- Lead with the repository purpose and the main user benefit.
- Include one distinguishing detail if space allows.
- Prefer concrete nouns and plain language.
- Leave workflow steps, setup instructions, framework lists, and detailed claims for the rest of
README.md. - The first paragraph must be pure prose. Do not use badges, Markdown links, images, code spans, or raw URLs.
- Avoid repeating information already obvious, do not include repo name.
Preferred structure:
[What it is] + [who/use case] + [distinctive detail]
- Use SCREAMING_SNAKE_CASE for Markdown docs filenames, with the .md extension
- For non-Markdown filenames, use only lowercase ASCII letters, numbers, and underscores.
- Prefer snake_case for most filenames. Avoid CamelCase in filenames.
- Use underscores between words and avoid spaces.
- Use
.mdfor docs,.shfor shell,.pyfor Python. - Keep filenames descriptive, and consistent with the primary thing the file provides.
- Use
git mvfor all renames and moves. - Do not use
mvplus add/remove as a fallback. Do not usegit rmunless deleting a file permanently. - Only humans run
git commit. AI agents updatedocs/CHANGELOG.mdfor human review before committing. - Before any index-writing Git command (including
git mv,git add,git rm,git checkout,git switch,git restore,git merge,git rebase,git reset,git commit), verify.gitis writable by the current user. If not, stop and report a permissions error. - If
.git/index.lockexists:- Do not modify files and do not run Git commands. Stop and report:
- lock owner, permissions, and age (mtime)
- process holding the lock, if detectable (for example,
lsof .git/index.lock)
- If a process holds the lock, report an active concurrent Git operation.
- If no process holds the lock and the lock age is > 5 minutes, report a likely stale lock. Do not delete it automatically.
- Do not modify files and do not run Git commands. Stop and report:
- If any Git command fails with an index lock error (cannot create
.git/index.lock), stop immediately. Do not retry and do not fall back tomv. - Error report must include: the command run and full stderr, plus a short next step: close other Git processes, remove a stale lock only if no process holds it, or fix
.gitpermissions.
- For pytest test-writing rules, commands, and failure triage, see PYTEST_STYLE.md.
- Tracked authored source files stay under 1000 physical lines: 999 passes; 1000 fails.
tests/test_source_file_line_limit.pydefines the scope. - Managers may exempt tracked external sources in
tests/source_file_line_limit_overrides.txt, one exact repo-relative path per line.
- Rotate
docs/CHANGELOG.mdwhen it reaches about 1000 lines (wc -l docs/CHANGELOG.md). - Keep complete day blocks together. Do not split entries from the same
## YYYY-MM-DDheading across files. - Keep the last two date-heading day blocks in active
docs/CHANGELOG.mdand move older day blocks to archive files. - "Last two days" means the two most recent
## YYYY-MM-DDheadings present in the changelog, not a rolling 48-hour window; dates may be non-consecutive. - Use archive filenames in the form
docs/CHANGELOG-YYYY-MM[a-z].md(for exampledocs/CHANGELOG-2026-02a.md), choosing the next letter for additional rotations in the same month. - When an archived range spans multiple months, name the archive after the most recent month included (the YYYY-MM closest to the active changelog), not the earliest. Example: a rotation moving 2026-01-23 through 2026-04-14 into one file becomes
docs/CHANGELOG-2026-04a.md. This keeps the most recent archive sortable next to the still-active file. - Date headings appear in exactly one file. A
## YYYY-MM-DDheading must never exist in both the active changelog and an archive (or in two archives). Before rotating, check the boundary date against the existing newest archive; if it already lives there, drop it from the active file rather than copying it across. - Preserve reverse-chronological order within each file after rotation.
- Each day block (
## YYYY-MM-DD) should include the same subsection headings, in this order:### Additions and New Features### Behavior or Interface Changes### Fixes and Maintenance### Removals and Deprecations### Decisions and Failures### Developer Tests and Notes
- Keep section order stable so entries stay easy to scan over time.
- Categories are not required when they would be empty, but every changelog entry must belong to one category.
- Changelog entries are never removed, but they may be rephrased for accuracy and clarity.
- Legacy archives that use the older
CHANGELOG_ARCHIVE_NN.mdform must be renamed to the documentedCHANGELOG-YYYY-MM[a-z].mdform. The new name follows the most-recent-month-in-range rule above (use the most recent## YYYY-MM-DDheading inside the archive). Usegit mvso history is preserved. Only one archive naming style should exist in the repo at any time. - Automation: devel/rotate_changelog.py enforces this rotation policy (keeps the two newest day blocks, archives the rest into
docs/CHANGELOG-YYYY-MM[a-z].md, refuses to clobber boundary dates). devel/query_changelog.py searches the active changelog and archives by date range, category, keyword, or source. devel/commit_changelog.py drafts the seed commit message from the changelog bullets newly ADDED in the working tree (viagit diff HEADondocs/CHANGELOG.md), then restricts those to the most recent run of consecutive day-block headings so an edited older bullet does not leak into the seed. All three share devel/changelog_lib.py (parser/serializer, git helpers, console + prompt helpers).
- Working planning artifacts under
docs/active_plans/are filed into a closed set of subdirectories by kind. - The five subdirectories are the closed set; adding a new category requires editing this section first.
docs/active_plans/active/for in-flight plans currently being acted on.docs/active_plans/audits/for diagnostic and audit reports.docs/active_plans/reports/for status reports and visual-acceptance reports.docs/active_plans/decisions/for decision records and clarifications.docs/active_plans/workstreams/for agent workstream artifacts.
- Forward-only by default: new files go directly into the matching subdirectory at creation time.
- Existing root-level files under
docs/active_plans/stay in place; do not relocate them without an explicit, one-time sweep approved by the user. - Topic-tag filename prefixes are retained inside each subdirectory (for example
no_crop_*,css_native_*) so related artifacts cluster by name. - Use snake_case filenames for these working docs, not SCREAMING_SNAKE_CASE; the all-caps rule covers durable
docs/*.mdreference docs, not active-plans scratch. - When a plan is complete and no longer being acted on, close it by moving the file with
git mvtodocs/archive/so history is preserved.
- Prefer
pyproject.tomlas the single source of truth when the repo is a single Python package with a singlepyproject.toml. - If the repo contains multiple Python packages (multiple
pyproject.tomlfiles), keep package versions in sync across allpyproject.tomlfiles. Unless otherwise stated. - Maintain a REPO_ROOT/
VERSIONfile as well that is sync'd with thepyproject.tomlversion. - Store the version under
[project] version. - Prefer CalVer-style zero-padded year/zero-padded month versioning for new releases, formatted as
0Y.0M.PATCH(for example25.02.3rc1). See https://calver.org/ - Use PEP 440 pre-release tags when needed:
aNfor alpha,bNfor beta, andrcNfor release candidates. - When PATCH == 0, use shorthand
25.02b1instead of25.02.0b1 - Prefer zero-padded 0Y.0M for readability and lexicographic sorting. Packaging tools may normalize 25.02.* to 25.2.*; this does not affect version ordering.
- Reference: PyPA version specifiers.
- When
devel/make_release.pyis present, use it to prepare GitHub source releases: it checks CalVer freshness, ensures the version tag is free, verifies the committed LICENSE, builds and spot-checks zip and tgz archives, generates an LLM-drafted release description, and optionally writesdocs/RELEASE_HISTORY.mdanddocs/NEWS.mdbefore printing the tag andgh release createcommands. Run with--dry-runto preview all steps without mutating the repo, or--writeto update the doc files.
- Keep scripts self-contained and single-purpose.
- Add a shebang for executable scripts and keep them runnable directly.
- For repo-local Python commands, use:
source source_me.sh && python ...
- For pytest commands, use:
pytest tests/
- Avoid hard-coded interpreter paths in routine command examples.
- Document shared helpers and modules in
docs/USAGE.mdwhen used across scripts. - Use
tests/test_pyflakes_code_lint.pyandtests/test_ascii_compliance.pyfor repo-wide lint checks, withtests/check_ascii_compliance.pyfor single-file ASCII/ISO-8859-1 checks andtests/fix_ascii_compliance.pyfor single-file fixes.tests/test_markdown_links.pyis the repo-wide check that every local Markdown link is GitHub-browsable and well formed. - For smoke tests, reuse stable output folder names (for example
output_smoke/) instead of creating one-off output directory names; reusing/overwriting avoids repeated delete-approval prompts. - In test scripts that need the repository root, import and use the shared
tests/file_utils.pymodule:This module usesimport file_utils REPO_ROOT = file_utils.get_repo_root()
git rev-parse --show-topleveland is propagated across repos automatically.
source_me.shis a bash script sourced into your shell, not run directly. It enforces bash, sources~/.bashrc, and exports the Python runtime flagsPYTHONUNBUFFEREDandPYTHONDONTWRITEBYTECODE.- It arrives as a starter seed: each repo owns its copy after bootstrap, so local edits stay put and are never overwritten.
- Ordering invariant:
source ~/.bashrcruns FIRST, before any repo-specific environment extension.~/.bashrcapplies local shell setup and clearsPYTHONPATH, so anyPYTHONPATHline must come after it or be wiped. - The seed sets no
PYTHONPATH. That omission is deliberate: most repos need none, and a broad path would mask missing-dependency bugs. Whether a repo needs one depends on that repo alone (does it ship a repo-root package), so each repo adds the line for itself. - When a repo needs its repo-root modules importable while commands run from a
subdirectory without installing the repo -- most commonly a repo-root package
imported package-qualified (for example
import mypackage.module), or scripts undertools/ortests/that import repo-root modules -- uncomment the canonical extension block in that repo'ssource_me.sh. Use exactly this idiom (it assumes the repo is inside a Git work tree):# Must come after sourcing ~/.bashrc, which clears PYTHONPATH. REPO_ROOT="$(git rev-parse --show-toplevel)" export PYTHONPATH="$REPO_ROOT${PYTHONPATH:+:$PYTHONPATH}" unset REPO_ROOT
- Store Python standard dependencies in
pip_requirements.txtat the repo root and developer dependencies, e.g., pytest inpip_requirements-dev.txt. - Use
pip_requirements.txtnotrequirements.txtfor clarity reasons - Store Homebrew packages in
Brewfileat the repo root. - Use per-subproject manifests only when a subfolder is a standalone project.
- Document non-default system dependencies in
docs/INSTALL.md. - In general, we want to require all dependencies, rather than provide work-arounds if they are mssing, because without all the dependencies the program is too crippled to run properly
- Keep generated outputs out of git unless they are small and intentional.
- Put large inputs or outputs under a clear folder (for example
data/oroutput/). - Note input and output locations in
docs/USAGE.md. - Keep sample inputs small and safe.
- Keep repo docs in
docs/unless a file is explicitly root-level. - Keep docs current. Remove or replace stale docs.
- Use SCREAMING_SNAKE_CASE for Markdown docs filenames, with the .md extension
- Apply the ALL CAPS rule to files under docs/ (for example docs/INSTALL.md).
- Use underscores between words and avoid spaces.
- Choose clear, descriptive names.
- Keep well-known root-level docs (for example VERSION, README.md, AGENTS.md).
- I prefer to use social media links instead of hard coding my email in repos. For example, Neil Voss, https://bsky.app/profile/neilvosslab.bsky.social
- When referencing files, use Markdown links so users can click through. Markdown links are created using the syntax
[link text](URL), where "link text" is the clickable text that appears in the document, and "URL" is the web address or file path the link points to. This allows users to navigate between different content easily. Use file-path link text so readers know the exact filename (good:[docs/MARKDOWN_STYLE.md](docs/MARKDOWN_STYLE.md), bad:[Style Guide for Markdown](docs/MARKDOWN_STYLE.md)). Only include a backticked path when the link text is not the path.
AGENTS.md: agent instructions, tool constraints, and repo-specific workflow guardrails.README.md: project purpose, quick start, and links to deeper documentation.LICENSE: legal terms for using and redistributing the project; keep exact license text.docs/CHANGELOG.md: chronological, user facing record of changes, grouped by date. Timeline of what changed and when.docs/CHANGELOG.mdentries should also note important failures and key implementation choices so the log remains a useful learning record for later debugging and decision review.docs/CODE_ARCHITECTURE.md: high-level system design, major components, and data flow.docs/FILE_STRUCTURE.md: directory map with what belongs where, including generated assets.docs/INSTALL.md: setup steps, dependencies, and environment requirements.docs/NEWS.md: curated release highlights and announcements, not a full changelog.docs/RELATED_PROJECTS.md: sibling repos, shared libraries, and integration touchpoints.docs/RELEASE_HISTORY.md: organized log of released versions and their release dates. Summarizes notable shipped qualities, including notes, major fixes, and compatibility notes.docs/ROADMAP.md: planned work, priorities, and what is intentionally not started.docs/TODO.md: backlog scratchpad for small tasks without timelines.docs/TROUBLESHOOTING.md: known issues, fixes, and debugging steps with symptoms.docs/USAGE.md: how to run the tool, CLI flags, and practical examples.
docs/AUTHORS.md: primary maintainers and notable contributorsdocs/CLAUDE_HOOK_USAGE_GUIDE.md: generated hook behavior reference, not a repo style source of truth. If repo style differs from hook examples, update repo style docs and recommend a hook rule update upstream.docs/MARKDOWN_STYLE.md: Markdown writing rules and formatting conventions for this repo.docs/PLAYWRIGHT_TEST_STYLE.md: browser test authoring style for repos that serve HTML.docs/PYTEST_STYLE.md: pytest test-writing rules, commands, fixture policy, and failure triage.docs/PYTHON_STYLE.md: Python formatting, linting, and project-specific conventions.docs/REPO_STYLE.md: repo-level organization, conventions, and file placement rules.
docs/COOKBOOK.md: extended, real-world scenarios that build on usage docs.docs/DEVELOPMENT.md: local dev workflows, build steps, and release process.docs/FAQ.md: short answers to common questions and misconceptions.
Possible examples:
docs/INPUT_FORMATS.md: supported input formats, required fields, and validation rules.docs/OUTPUT_FORMATS.md: generated outputs, schemas, naming rules, and destinations.docs/FILE_FORMATS.md: combined reference for input and output formats when one doc is clearer.docs/YAML_FILE_FORMAT.md: YAML schema, examples, and validation requirements.
CONTRIBUTING.md: probably better under the DEVELOPMENT.md pageCODE_OF_CONDUCT.md: avoid adding unless project scope changes and it will be maintained.COMMUNITY.md: avoid adding; this repo does not run a community program.ISSUE_TEMPLATE.md: avoid adding; this repo does not use GitHub issue templates here.PULL_REQUEST_TEMPLATE.md: avoid adding; we are not using GitHub PR templates here.SECURITY.md: avoid adding unless security reporting is formally supported.
docs/CONTAINER.md: container image details, build steps, and run commands.docs/ENGINES.md: supported external engines/services and how to select them.docs/EMWY_YAML_v2_SPEC.md: specification for the EMWY YAML v2 format with examples.docs/MACOS_PODMAN.md: macOS-specific Podman setup steps and known issues.docs/QUESTION_TYPES.md: catalog of question types with expected fields and behavior.
Check the license file to match these criteria.
-
Most source code is licensed under GPLv3, unless stated otherwise.
-
Libraries intended for use by proprietary or mixed-source software are licensed under LGPLv3.
-
Non-code creative works, including text and figures, are licensed under CC BY-SA 4.0. Commercial use is permitted.
-
Code and non-code materials are licensed separately to reflect different legal and practical requirements.