Self-maintenance¶
The binding keeps itself aligned with its dependencies. Deterministic bots detect and prepare every change; an LLM agent fills only the gaps a machine cannot close by rule; a human merges.
flowchart LR
R[Renovate] -->|PR renovate/*| S[sync.yml: changelog + licenses]
S -->|push| C[CI: tests · coverage · API diff]
C -->|red, or engine API grew| A[maintenance.yml: Qwen agent]
A -->|commit [maintenance]| C
C -->|green| H[Human review and merge]
A -->|3 attempts used| N[label needs-human]
M[health.yml, monthly] --> I[issue deps-health]
What it touches¶
Every file the system may change, who changes it and with which tool. Anything not listed is human-only.
| Target | Files | Who | Tool | When |
|---|---|---|---|---|
| Dependency pins | Cargo.toml (anytomd, pyo3, tokio), pyproject.toml dependency groups, .github/workflows/* action digests |
Renovate | Renovate | A new release upstream |
| Lockfiles | Cargo.lock, uv.lock |
Renovate, sync.yml |
cargo, uv | With every pin change |
| Changelog: engine line | CHANGELOG.md → ## [Unreleased] |
sync.yml |
awk | The engine version changes |
| Third-party licenses | THIRD_PARTY_LICENSES.md |
sync.yml |
cargo-about | Any Rust dependency changes |
| Binding code | crates/native/src/lib.rs, src/anytomd/ (infra, logic, backends) |
maintenance.yml agent |
Qwen Code, cargo, maturin | CI red, or engine API grew |
| Python surface | src/anytomd/logic/api.py, src/anytomd/__init__.py, src/anytomd/_native.pyi |
maintenance.yml agent |
Qwen Code | Something new is exposed |
| Tests | tests/ |
maintenance.yml agent |
Qwen Code, pytest | Every change the agent makes |
| Docs | docs/ (MkDocs), README.md |
maintenance.yml agent |
Qwen Code, mkdocs | Something new is exposed |
| Changelog: binding lines | CHANGELOG.md → ## [Unreleased] |
maintenance.yml agent |
Qwen Code | Every user-visible change |
| Health issue | GitHub issue labelled deps-health |
health.yml |
tools/health.py, gh |
Monthly |
| PR comments and labels | The Renovate PR | maintenance.yml |
gh | After each agent run |
The agent's limits are enforced by the workflow, not by trust: its commit keeps only crates/native/src/, src/anytomd/, tests/, docs/, CHANGELOG.md and README.md, and the App token cannot write .github/.
Human-only: merging, the package version, release tags (v*), the release date in CHANGELOG.md, .github/, QWEN.md, prek.toml, build and tooling config.
Moving parts¶
| Piece | Kind | Does |
|---|---|---|
.github/renovate.json |
Deterministic | Opens PRs for new versions: anytomd-rs at once, PyO3 and tokio separately, Python tooling and Actions grouped. Its Dependency Dashboard issue also marks packages without a release for a year as abandoned. |
sync.yml |
Deterministic | On renovate/*: adds the engine line to the changelog, regenerates THIRD_PARTY_LICENSES.md. |
ci.yml |
Deterministic | prek hooks (the same as every local commit: ruff, ty, tach, rustfmt, clippy, licenses freshness, zizmor, gitleaks), tests on Linux/macOS/Windows × Python 3.12/3.14, Rust coverage (≥ 90 % of lines), docs. On renovate/* also the upstream context: public API diff of the two engine versions (cargo public-api) and their release notes. Logs are kept as artifacts for the agent. |
maintenance.yml |
Agent | After CI on renovate/*: fix mode when CI is red, expose mode when CI is green but the engine's public API gained items. Runs Qwen Code under QWEN.md. |
health.yml |
Deterministic | First day of each month: checks every direct dependency for an archived repository, a vanished package, a last release older than 18 months, or no push in 12 months. Opens or refreshes one deps-health issue; closes it when all is well. |
release.yml |
Deterministic | On a v* tag matching the package version: wheels for five platforms, sdist, GitHub build provenance, PyPI via trusted publishing (with PEP 740 attestations). |
Guard rails¶
- The agent never commits. The workflow does, and only files under
crates/native/src/,src/anytomd/,tests/,docs/,CHANGELOG.mdandREADME.md; anything else it touched is discarded and listed in the PR comment. - The GitHub App has no
workflowspermission: no token in the pipeline can change.github/. - At most three
[maintenance]commits per branch; then the PR getsneeds-human. - Expose mode runs once per PR. Runs triggered by a stale head are skipped.
workflow_runis limited to same-repositoryrenovate/*branches, so forks never reach the secrets.- Nothing merges itself. Branch protection on
mainrequires one human approval.
Versioning¶
The package has its own semver (anytomd.__version__); the engine it embeds is anytomd.ENGINE_VERSION. An engine bump never changes the package version by itself: sync.yml records it in the changelog, and a human picks the next version when releasing.
Setup¶
One-time, in the GitHub repository settings.
GitHub App (Settings → Developer settings → GitHub Apps → New), webhook off, installed on this repository only:
| Permission | Access |
|---|---|
| Contents | Read and write |
| Pull requests | Read and write |
| Issues | Read and write |
| Metadata | Read |
| Workflows | No access |
Secrets and variables (Settings → Secrets and variables → Actions):
| Name | Kind | Value |
|---|---|---|
APP_CLIENT_ID |
Variable | The App's Client ID |
APP_PRIVATE_KEY |
Secret | The App's private key (.pem content) |
QWEN_API_KEY |
Secret | Alibaba Model Studio key |
QWEN_BASE_URL |
Variable, optional | OpenAI-compatible endpoint; default https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1 |
QWEN_MODEL |
Variable, optional | Default qwen3.8-max |
QWEN_CLI_VERSION |
Variable, optional | Pin @qwen-code/qwen-code; default latest |
Elsewhere: install the Renovate app on the repository; on PyPI add a trusted publisher (release.yml, environment pypi); enable Pages with source GitHub Actions; protect main (one approval, required checks, no bypass for the App); create the labels upstream-update, binding-update, tooling, ai-modified, needs-human, deps-health.
Running the pieces by hand¶
make apidiff OLD=1.3.0 NEW=1.3.1 # what the agent would see for that engine bump
make health # the monthly report, locally
make licenses # regenerate THIRD_PARTY_LICENSES.md
make cov # Rust coverage gate
health.yml and the Renovate dashboard both accept a manual run (Run workflow / the dashboard checkbox).