Automated operation contracts¶
Referenced from
claude.md§ Automated operation contracts. This file contains the detailed checklists for each operation type.
Sync job contract¶
Every sync-* operation modifies or overwrites user-controlled files or resources. Users must retain full control: each sync operation must be individually disableable via [tool.repomatic].
Required properties (checklist for adding or auditing a sync job):
Config toggle. A
*_sync: bool = Truefield in theConfigdataclass. Dotted sub-key in[tool.repomatic](e.g.,gitignore.sync = false). Alphabetically sorted among existing sync fields.CLI command. A
repomatic sync-*command that loads config, checks the toggle, and exits cleanly (ctx.exit(0)) when disabled. Uses@pass_contextto receivectx.Toggle enforcement. For CLI-based syncs: the toggle field goes in
SUBCOMMAND_CONFIG_FIELDS(checked in the CLI, not exposed as metadata). For workflow-only syncs (no CLI command): the toggle is exposed as a metadata output and checked in the job’sif:condition. For syncs whose workflow also gates other steps on the toggle (likesync-binaries, whose output a separategit-commit-pushstep commits): both at once, a CLI check plus a metadata output kept out ofSUBCOMMAND_CONFIG_FIELDS.Workflow job. A
sync-*job in the appropriate workflow file (usuallyautofix.yaml, but lifecycle-specific syncs may live elsewhere — e.g.,sync-dev-releasein_release-engine.yaml,sync-labelsinlabels.yaml). Requires: metadataneeds:when applicable, prerequisiteif:conditions, PR creation viapeter-evans/create-pull-request(branch name = job ID, body fromrepomatic pr-body --template sync-*). Exceptions: syncs targeting API resources (e.g., labels) rather than repo files apply changes directly, andsync-binariesruns as release-lane recording whose output is pushed straight to the default branch (see § Release-lane direct commits).Documentation. Config table row and TOML example in
docs/configuration.md. Job description with “Skipped if” clause indocs/workflows.md. Changelog entry.Tests. Default and custom value assertions in
test_repomatic_config_defaultsandtest_repomatic_config_custom_values.
Invariants:
A disabled toggle must produce zero side effects: no file writes, no API calls, no PRs.
Update job contract¶
Every update-* operation computes derived artifacts from project state (lockfiles, git history, source code). Unlike sync operations, these generate computed output rather than overwriting user-authored content.
Required properties:
CLI command. A
repomatic update-*command.Workflow job. An
update-*job in the appropriate workflow file with PR creation viapeter-evans/create-pull-request(branch name = job ID, body fromrepomatic pr-body --template update-*).Documentation. Job description in
docs/workflows.md. Changelog entry.
Optional properties:
CLI command. A CLI wrapper is only required when the update runs custom repomatic Python logic (e.g.,
update-deps-graph). Updates that invoke external tools or standalone scripts (e.g.,sphinx-apidoc) may call them directly from the workflow without arepomatic update-*wrapper.Config toggle. Add a
*_update: bool = Truetoggle only when the generated output involves files the user may want to manage independently. If added, follow the sync toggle pattern (Config field,SUBCOMMAND_CONFIG_FIELDS, tests).Config parameters. Output paths, filtering options, or depth limits belong as Config fields (e.g.,
dependency-graph.output,dependency-graph.level). These configure behavior without enabling/disabling the operation.
Format and fix job contract¶
Every format-* and fix-* operation rewrites files using a pinned external tool. format-* enforces canonical style (semantics-preserving); fix-* corrects content errors such as typos (semantics-altering). The naming convention table in CLAUDE.md § Naming conventions for automated operations defines when to use each prefix.
Required properties:
CLI command. A
repomatic format-*orrepomatic fix-*command that wraps a pinned external tool (e.g., ruff, mdformat, jq, typos).Workflow job. A job in the appropriate workflow file (usually
autofix.yaml) with PR creation viapeter-evans/create-pull-request(branch name = job ID, body fromrepomatic pr-body --template verb-noun).Documentation. Job description in
docs/workflows.md. Changelog entry.
Invariants:
No config toggle. Format jobs gate on metadata file-detection outputs (e.g.,
python_files,markdown_files,json_files) making them self-skipping when irrelevant. Fix jobs may run unconditionally when the tool applies to all file types.The external tool version must be pinned in the CLI command for reproducibility.
Lint job contract¶
Every lint-* operation checks content without modifying it. Lint operations are read-only.
Required properties:
CLI command. A
repomatic lint-*command. Returns exit code 0 on pass, non-zero on failure.Workflow job. A
lint-*job inlint.yaml(notautofix.yaml). No PR creation — lints gate merges via status checks.Documentation. Job description in
docs/workflows.md. Changelog entry.
Optional properties:
CLI command. A CLI wrapper is only required when the lint runs custom Python logic (e.g.,
lint-repo). Lints that invoke a standard external tool (mypy,yamllint,actionlint,zizmor,gitleaks, etc.) may call the tool directly from the workflow without arepomatic lint-*wrapper.
Invariants:
Read-only. No file writes, no PRs, no side effects beyond exit code and stdout/stderr output.
Lives in
lint.yaml, notautofix.yaml.
Scan job contract¶
Every scan-* operation submits release artifacts to an external analysis service (like scan-virustotal) and records the results in the repository. The submission is the operation’s point (seeding AV vendor databases); the recorded results are the durable trace of what the service reported.
Required properties:
CLI command. A
repomatic scan-*command that performs the submission and writes the result records (likescan-virustotal --records).Workflow job. A
scan-*job in the release engine (_release-engine.yaml), running afterpublish-releaseso the released assets exist. Gated on the service’s API key secret: no key, no scan.Config toggle for the recording. The in-repo recording must be disableable via
[tool.repomatic]:binaries.sync = falseskips the catalog regeneration and commit steps while the scan itself still runs. Because the commit is performed by a separategit-commit-pushstep, the toggle is exposed as a metadata output (kept out ofSUBCOMMAND_CONFIG_FIELDS) and checked in the stepif:conditions, in addition to the usual CLI check inside the pairedsync-*command.Documentation. Job description in
docs/workflows.md. Changelog entry.Tests. Default and custom value assertions in
test_repomatic_config_defaultsandtest_repomatic_config_custom_values.
Invariants:
Idempotent: re-running a scan upserts result records (no duplicate snapshots), and regenerating the catalog is convergent.
The recording only ever touches generated data files (scan history JSON, catalog CSV, generated page), never user-authored content.
Release-lane direct commits¶
Important
scan-virustotal records its results with a direct push to the default branch (via repomatic git-commit-push), not a pull request. This is the only file-modifying operation exempt from the PR convention. Disable it with [tool.repomatic] binaries.sync = false.
A post-release recording job gets nothing from a PR:
The data is not reviewable: it records facts about an already-published, immutable release, fetched from external APIs (VirusTotal, the GitHub Releases API). Rejecting or editing the diff cannot change the release; it can only make the record wrong or missing.
The binaries page must be fresh at release time: the push (with
REPOMATIC_PATconfigured) triggers the docs deploy, so download links and VirusTotal verdicts are live exactly when users and downstream distributors (Chocolatey, Scoop) fetch the new binaries. A PR would leave the page stale until someone merges it.The job is the tail of the release pipeline: ending a release on an open PR means every release needs a follow-up merge, or per-repo auto-merge wiring (branch protection, required checks, a PAT that triggers CI) that can block indefinitely. That adds failure modes for zero review value.
The push is engineered for a busy default branch: git-commit-push is idempotent, rebases and retries on rejection, and multi-release runs are serialized with max-parallel: 1. Repositories that do not want automated pushes on their default branch set [tool.repomatic] binaries.sync = false: binaries are still scanned, nothing is committed.
PR body template conventions¶
PR body templates in repomatic/templates/ are the downstream user’s primary window into what an automated operation did and why. Each template should help users understand, verify, and customize the operation.
Frontmatter:
title. The PR title, and the commit-message fallback.docs. A deep link to the job’s section of the hosted workflows reference.repomatic pr-bodysurfaces it as the leadingDocumentationentry of the collapsibleWorkflow metadatablock, so the body carries no standalone description section.footer: false. The metadata block already appends the attribution footer once; every template opts out of a second copy.
Body elements (include what applies, with ## section headings):
Configuration section. For operations driven by
[tool.repomatic], a## Configurationsection listing the relevant options as bullets deep-linking into the hosted configuration reference. Sync and update templates lead with it, after their$diff_tablewhen they take one.Customization tip. For format and fix operations, a
> [!TIP]block naming the[tool.X]pyproject.tomlsection and/or native config file as the way to override defaults, linked to the tool’s own configuration reference.
Example (format job):
---
title: Format X
docs: https://kdeldycke.github.io/repomatic/workflows.html#format-x-format-x
footer: false
---
> [!TIP]
> Customize formatting rules via [`[tool.X]`](https://example.com/configuration/)
> in your `pyproject.toml`, or via a native `x.toml` file.