Contributing¶
Thanks for helping improve ChartworkAI. This document covers the dev setup, the checks your PR has to pass, and the one convention that surprises newcomers: substantive changes need a decision record.
Dev environment¶
Requires Python 3.9 or newer.
Supported and tested range: 3.9 – 3.13. requires-python is >=3.9 with no upper
bound, which is the normal convention for a library — capping it makes pip resolve to
an older release instead of saying why. The practical consequence is that pip will
install this on 3.14 too, a version CI does not exercise. It is expected to work
(the suite passed there when it was last run) but it is not a version we verify, so
treat a 3.14 problem as unsupported until 3.14 is added to the matrix and to the
classifiers together.
git clone https://github.com/v-datos/chartworkai.git
cd chartworkai
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
That installs the chartworkai CLI in editable mode plus pytest and ruff. Run the tests:
The core has zero runtime dependencies and that is a hard constraint, not an accident. ChartworkAI governs projects in any language and must never impose a dependency tree on the repo it audits. A PR that adds a runtime dependency needs a decision record arguing the case.
The project dogfoods itself¶
This repo is managed with its own framework (see
docs/decisions/20260607_DEC001_self_host.md). The compliance checker runs against this
repository, and your PR must keep the self-check passing:
Once the Python CLI is installed, the same check is available as:
chartworkai check . # exit 0 = pass, 1 = failures
chartworkai check . --json # machine-readable output
Both must exit 0 before you open a PR. The full verification loop, including a bootstrap smoke test into a temp directory:
sh -n scripts/check_framework_compliance.sh
sh -n scripts/init_project_from_framework.sh
python scripts/sync_framework_manifest.py --check
scripts/init_project_from_framework.sh /tmp/cw-example "Example Project" example_project
scripts/check_framework_compliance.sh /tmp/cw-example
Gates that trip people up: no duplicate ## headings in living documents, no unresolved
{{placeholder}} tokens in active docs, TASKS.md has exactly one In Progress section and
uses checkbox bullets rather than tables, the current phase number in docs/phase_plan.md also
appears in PROJECT_CHARTER.md, and every decision file is linked from the charter.
A freshly bootstrapped scaffold deliberately fails the check until you fill in the
placeholders and remove the temporary _framework_* directories. That is the graduation gate, not
a bug.
Decision records¶
Anything that changes scope, a shared convention, a schema, or phase gating gets a dated,
authority-stamped file in docs/decisions/. This is the traceability the whole framework exists
to provide — skip it and the change will be questioned six months from now with no answer
available.
Filename: YYYYMMDD_<NS>###_<title>.md — for example
docs/decisions/20260613_DEC004_product_model.md.
The namespace <NS> is one of:
| Namespace | Use for |
|---|---|
DEC |
Scope, methodology, and design decisions |
DQ |
Data-quality rulings |
SC |
Scope-change rulings |
MD |
Methodology / domain rulings |
The checker enforces this pattern, so a malformed name fails the build.
Contents — start from templates/decisions/YYYYMMDD_decision.template.md. Each file carries a
Date / Authority / Status header, then Context (with the options considered), Ruling, Rationale,
Implementation notes, Consequences per agent, and Related decisions.
Link it from the charter. Every non-README decision must appear in the ## 8. Decision log
table in PROJECT_CHARTER.md:
| 2026-06-13 | Product model and go-to-market strategy | Orchestrator | `docs/decisions/20260613_DEC004_product_model.md` |
An unlinked decision file is a compliance failure.
Pull requests¶
- Keep them small and focused. One concern per PR. A refactor and a behavior change in the same diff will be sent back.
- Tests for behavior changes. New CLI behavior or a bug fix needs a test that fails before your change and passes after it.
- Update
CHANGELOG.md. Add an entry under## [Unreleased]in the appropriate Added / Changed / Fixed / Removed group. - Change framework rules in
framework.jsonfirst. If you add or change profiles, required artifacts, layout, templates, prompts, scripts, or extensions, runpython scripts/sync_framework_manifest.pyand commit its shell/documentation projections.python scripts/sync_framework_manifest.py --checkmust pass. - Fill in the PR template (
.github/PULL_REQUEST_TEMPLATE.md), including the verification commands you actually ran. - Write commit subjects in the imperative mood and keep them under ~72 characters.
- No assistant co-author trailers. Don't add
Co-Authored-By:lines for an AI assistant. Attribution belongs to the person who reviewed and submitted the change; an assistant trailer registers tooling as a repository contributor.
Code style¶
Shell — POSIX sh, not bash. No bashisms: no arrays, no [[ ]], no local. Every script
starts with #!/usr/bin/env sh and set -eu. Every script must parse cleanly:
Quote your expansions. The scripts run against arbitrary user repositories where paths contain spaces.
Python — formatted and linted with ruff (line length 100, target py39):
Type hints are required on public functions. Support Python 3.9 through 3.13, so no
match statements and no X | Y unions at runtime.
Markdown — direct and concrete. Document what the thing does and what it costs, not how
exciting it is. Templates use {{placeholder}} tokens; keep them consistent with the existing
set, since the checker scans for unresolved ones.
Stay assistant-agnostic. Core operating documents must not hard-code a specific AI assistant's name, slash commands, or file conventions. The checker has a tool-leak gate for exactly this.
Reporting bugs and vulnerabilities¶
Ordinary bugs: open a GitHub issue with your version, platform, shell, and a reproduction.
Security vulnerabilities: do not open a public issue. Follow SECURITY.md.
License¶
By contributing, you agree that your contributions are licensed under the Apache License 2.0
(LICENSE).