diff --git a/.gitignore b/.gitignore index 4e727f8e..b60d2580 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,15 @@ local # VS Code .vscode/ + +# AI tooling (SpecKit v0.8.0) +.opencode/ +.specify/scripts +.specify/templates +.specify/extensions.yml +.specify/extensions +.specify/init-options.json +.specify/integration.json +.specify/integrations +.specify/workflows +.specify/workflow.yml diff --git a/.specify/memory/constitution.md b/.specify/memory/constitution.md new file mode 100644 index 00000000..44ac8f90 --- /dev/null +++ b/.specify/memory/constitution.md @@ -0,0 +1,107 @@ + + +# Rubicon-ObjC Constitution + +## Core Principles + +### I. Bridge Fidelity (Objective-C Semantics) + +Rubicon-ObjC exists to expose the Objective-C runtime to Python without hiding or reinventing it. Public APIs MUST mirror Objective-C naming, calling, and memory-management semantics (selectors, ARC/retain semantics, message dispatch, nil-handling) so that users who know Cocoa/Foundation can transfer that knowledge directly. Python-side convenience wrappers (e.g. `NSString` helpers) are permitted but MUST NOT silently change observable runtime behaviour, raise surprising exceptions in place of Objective-C errors, or leak/retain objects in ways that diverge from the documented Objective-C contract. Any deviation MUST be called out explicitly in the public documentation together with its rationale. + +Rationale: The project's value is being a faithful bridge; users ship code to macOS and iOS where misaligned semantics become hard-to-diagnose, device-only bugs. + +### II. Test-Driven, Fully Covered + +Every change MUST be accompanied by automated tests runnable via `pytest` through `tox`. New behaviour and bug fixes MUST have tests that fail without the change and pass with it. The test suite MUST treat warnings as errors (per `pyproject.toml`: `filterwarnings = ["error"]`); new warnings MUST be either fixed or explicitly allow-listed with justification in the PR. Coverage MUST NOT regress; code paths gated by Python-version markers MUST use the existing `coverage_conditional_plugin` rules rather than blanket `# pragma: no cover`. Tests that require a running Objective-C runtime MUST be skipped (not silently passed) on unsupported platforms. + +Rationale: The bridge is exercised across multiple Python versions and Apple platforms; without disciplined tests, regressions are invisible until a user hits them in production. + +### III. Documentation as a Deliverable + +Every user-visible addition or change (new API, new argument, new behaviour, deprecation, removal) MUST ship with: + +- Updated reference, how-to, or tutorial content under `docs/` following the BeeWare documentation style guide, and +- A release note fragment under `changes/` using the `towncrier` categories configured in `pyproject.toml` (`feature`, `bugfix`, `removal`, `doc`, `misc`), referencing the GitHub issue or PR. + +Docstrings for public symbols MUST describe the Objective-C types involved and any lifetime/ownership implications. Documentation-only PRs are valid and expected. + +Rationale: Users pick up Rubicon through the docs; release notes are the contract we ship to downstream BeeWare packages (e.g. Toga, Briefcase). + +### IV. Backward Compatibility & Clear Versioning + +Releases follow Semantic Versioning on the `rubicon-objc` distribution: + +- **MAJOR**: removals or incompatible changes to public Python APIs, to the set of supported Python versions, or to observable Objective-C bridging behaviour. +- **MINOR**: additive, backward-compatible features (new classes, wrappers, helpers, expanded platform support). +- **PATCH**: bug fixes and internal refactors with no API-visible effect. + +Breaking changes MUST go through a deprecation cycle: the old behaviour remains, emits a `DeprecationWarning` with a concrete replacement, is documented in `changes/*.removal.md`, and is only removed in a subsequent MAJOR release. Anything not documented in `docs/` or exported through the package's public `__all__`/public module paths is internal and MAY change without notice — but such internals MUST be named or located so their non-public status is obvious to callers. + +Rationale: Rubicon is depended on by other BeeWare projects and third-party apps; predictable versioning keeps the ecosystem upgradable. + +### V. Platform & Toolchain Discipline + +The project MUST support every Python version listed in `pyproject.toml` classifiers (currently 3.10 through 3.15) and MUST NOT introduce syntax or stdlib features unavailable on the lowest supported version. Dependencies MUST be pinned in `pyproject.toml` dependency groups; loosening a pin or adding a runtime dependency requires explicit justification in the PR. Code style is enforced by pre-commit (Ruff, codespell, rumdl) with the rules defined in `pyproject.toml`; CI MUST run the full `tox` matrix and pre-commit before a release. Releases are cut from `main` with a clean `towncrier` run producing `docs/en/about/releases.md`. + +Rationale: The bridge lives at the intersection of Python versions and Apple platforms; disciplined toolchain management is what makes the matrix tractable. + +## Additional Constraints & Quality Standards + +- **Supported runtimes**: CPython 3.10+ on macOS and iOS; other Apple platforms (tvOS, watchOS, visionOS) are best-effort and MUST NOT regress when changes are made primarily for macOS/iOS. +- **Licensing**: All contributions are licensed under BSD-3-Clause (per `LICENSE`). New third-party code or assets MUST be license-compatible and attributed. +- **Security & memory safety**: Code touching `ctypes`, `objc_msgSend`, block trampolines, or manual retain/release MUST include tests covering reference-count behaviour and MUST document ownership in the docstring. +- **Community standards**: All participation is governed by the BeeWare Code of Conduct (`CODE_OF_CONDUCT.md`). Contributor obligations for AI tooling are defined by the BeeWare AI Policy referenced in `CONTRIBUTING.md`; contributors remain responsible for their submissions regardless of tooling used. + +## Development Workflow & Review Gates + +- **Branching**: Work happens on feature branches; PRs target `main`. +- **Pre-commit**: Contributors MUST install and run the configured pre-commit hooks; CI re-runs them and will reject non-conforming diffs. +- **CI gates (MUST all pass before merge)**: + 1. `tox` test matrix (pytest with warnings-as-errors) across supported Python versions. + 2. Coverage report with no uncovered new lines outside documented `coverage_conditional_plugin` rules. + 3. Pre-commit (Ruff lint/format, codespell, rumdl). + 4. Docs build (Sphinx via `beeware-docs-tools`). + 5. Presence of a `changes/*.md` fragment for any user-visible change, or an explicit `misc` fragment for internal work. +- **Review**: At least one maintainer approval is required. Reviewers MUST verify that each of the five Core Principles is satisfied or that the PR explicitly justifies any exception in a "Complexity Tracking" / deviation note. +- **Release**: Version is derived from the Git tag via `setuptools_scm`. Release PRs run `towncrier build` to assemble the release notes and bump the SemVer tag consistent with Principle IV. + +## Governance + +- **Authority**: This constitution supersedes ad-hoc conventions. Where it conflicts with older README/docs guidance, the constitution wins and the older text MUST be updated. +- **Amendment procedure**: Proposed amendments are opened as PRs editing this file. They MUST include (a) the motivation, (b) the updated Sync Impact Report at the top of this file, and (c) any downstream template or docs edits required to stay consistent. Amendments require maintainer approval on the same terms as code changes. +- **Versioning policy (of this document)**: + - MAJOR: removing, renaming, or materially redefining a principle or the governance process. + - MINOR: adding a principle or section, or expanding a principle's binding rules. + - PATCH: wording clarifications, typo fixes, non-semantic refinements. +- **Compliance review**: At the start of planning any feature (see `.specify/templates/plan-template.md` "Constitution Check"), the plan MUST state how the five Core Principles are satisfied; unjustified violations block the plan. Release PRs MUST include a short statement confirming the checks in "Development Workflow & Review Gates" all passed. +- **Runtime guidance**: Contributor-facing day-to-day guidance lives in `CONTRIBUTING.md` and the online docs under `docs/`; agent/tooling guidance lives in `AGENTS.md`. Those files are subordinate to this constitution and MUST be updated whenever it changes in a way that affects workflow. + +**Version**: 1.0.0 | **Ratified**: 2026-04-24 | **Last Amended**: 2026-04-24 diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..50f711a3 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,69 @@ +# Rubicon-ObjC - Agent Development Guide + + +For additional context about technologies to be used, project structure, +shell commands, and other important information, read the current plan + + +Rubicon-ObjC is a Python to Objective-C runtime bridge, maintained as part of the [BeeWare](https://beeware.org) suite. It lets Python code instantiate Objective-C objects, send messages, subclass Objective-C classes, and interoperate with Cocoa / Foundation types. It is used on macOS and iOS and is a dependency of other BeeWare projects (e.g. Toga, Briefcase), so stability and backward compatibility matter. + +## Repository layout + +- `src/rubicon/objc/` — the package. Public API is what is re-exported from `rubicon.objc.__init__`. Key modules: `api.py`, `runtime.py`, `types.py`, `collections.py`, `ctypes_patch.py`, `eventloop.py`. +- `tests/` — `pytest` suite. Tests that exercise real Objective-C classes live under `tests/objc/` and are built with `make -C tests/objc` before the Python tests run (handled automatically by `tox`). +- `docs/en/` — MkDocs documentation (tutorials, how-to, reference, background). Built via `beeware-docs-tools`. +- `changes/` — `towncrier` news fragments. Every user-visible change ships a fragment here. +- `stubs/` — type stubs used by the docs toolchain. +- `pyproject.toml`, `tox.ini`, `.pre-commit-config.yaml` — canonical source for dependencies, supported Python versions (3.10–3.15), lint rules, test matrix, and coverage configuration. +- `.specify/` — SpecKit workspace (constitution, templates, extensions). Do not edit `.specify/memory/constitution.md` outside the `/speckit.constitution` workflow. + + +## Toolchain + +- **Python**: 3.10–3.14 (see `core/pyproject.toml` classifiers). +- **Supported platforms**: macOS and iOS. Most runtime tests require a working Objective-C runtime and therefore only pass on macOS. +- **Task runner**: `tox` (with `tox-uv`). Install the dev tooling via `uv pip install --group dev` at the repo root, or let `tox` bootstrap. +- **Lint/format**: `ruff` (check + format), `codespell`, `rumdl` (Markdown), configured in root `pyproject.toml`. +- **Pre-commit**: `pre-commit run --all-files` — MUST pass before PR. +- **Packaging / testbed driver**: `briefcase`. +- **Release notes**: `towncrier` (config in root `pyproject.toml`). +- **Docs**: MkDocs; built with the `docs` dependency group. + +Do not replace or bypass these tools. Add new dependencies only with a clear need and a compatible license (BSD-3-Clause friendly). + +## Commands you should use + +Run these via the Bash tool. Do not invent ad-hoc scripts when an equivalent `tox` env exists. + +- Full matrix test run (matches CI): `tox` +- Fast single-version tests: `tox -e py312-fast` (swap for 310/311/313/314/315). `-fast` enables `pytest-xdist` and develop installs. +- Coverage run for one version: `tox -e py312-cov` then `tox -e coverage312`. +- Objective-C test fixtures only: `make -C tests/objc` (tox does this for you, but useful when iterating). +- Lint / format (all pre-commit hooks, same as CI): `tox -e pre-commit` or `pre-commit run --all-files`. +- Docs build: `tox -e docs` (full), `tox -e docs-lint` (link/spell check), `tox -e docs-live` (local preview). +- Towncrier check (required before merge for user-visible changes): `tox -e towncrier-check`. +- Assemble release notes (maintainers only): `tox -e towncrier -- build`. + +Warnings are errors: `pyproject.toml` sets `filterwarnings = ["error"]`. A test that emits an unhandled warning will fail. Fix the cause; do not silence it globally. + +## Coding rules (derived from the constitution) + +1. **Bridge fidelity.** Public APIs MUST mirror Objective-C semantics — selectors, message dispatch, ARC/retain behaviour, `nil` handling. Convenience wrappers are fine, but they MUST NOT silently change observable runtime behaviour or object lifetimes. If you deviate, document it. +2. **Test-driven.** Every behaviour change or bug fix MUST include a test that fails without the change and passes with it. Place tests in the appropriate `tests/test_*.py` file (create a new module only when no existing one fits). If the test needs Objective-C fixtures, add/extend the `.h`/`.m` files under `tests/objc/` and update its `Makefile` target. +3. **Coverage must not regress.** Use the existing `coverage_conditional_plugin` markers (`no-cover-if-*`) in `pyproject.toml` for version- or platform-specific branches instead of blanket `# pragma: no cover`. +4. **Documentation is part of the change.** For any user-visible addition, update the relevant `docs/en/...` page (reference/how-to/tutorial/background) and add a `changes/..md` fragment. Categories: `feature`, `bugfix`, `removal`, `doc`, `misc` (see `pyproject.toml [tool.towncrier]`). Reference the issue number in the filename. +5. **Docstrings.** Public symbols MUST document the Objective-C types they accept/return and any lifetime/ownership implications. +6. **Backward compatibility.** Do not remove or rename public API without a deprecation cycle: keep the old name, emit a `DeprecationWarning` pointing to the replacement, add a `changes/.removal.md`. Removal happens in a later MAJOR release, not the same PR. +7. **Internals.** Anything not exported from `rubicon.objc.__init__` or otherwise documented in `docs/` is internal and may change; keep the internal/public split obvious (naming, module location). +8. **Memory-sensitive code.** Changes touching `ctypes`, `objc_msgSend`, block trampolines, or manual retain/release MUST add tests that cover reference counts and MUST document ownership rules in the docstring. +9. **Style.** Enforced by `ruff` (rules in `pyproject.toml [tool.ruff.lint]`), `codespell`, and `rumdl`. Run pre-commit before declaring work done. Do not disable a rule inline without justification in the PR. + +## Pull request checklist (what CI will verify) + +- [ ] `tox` matrix passes on supported Python versions. +- [ ] Coverage report shows no new uncovered lines outside documented conditional rules. +- [ ] `tox -e pre-commit` clean. +- [ ] `tox -e docs` and `tox -e docs-lint` pass when docs change. +- [ ] `tox -e towncrier-check` passes: a `changes/*.md` fragment exists for any user-visible change (or a `misc` fragment for internal-only work). +- [ ] Public API changes have matching docs and docstring updates. +- [ ] Deprecations follow the cycle described above. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d6697acd..0188c7da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,37 @@ -# Contributing +# All Contributions Welcome -BeeWare <3's contributions! +It's not just about code. A successful software project requires documentation, design skills, feedback and bug reports. The BeeWare project recognizes that all contributions are important - not just the ones that come as a pull request on GitHub. -Please be aware that BeeWare operates under a [Code of Conduct](https://beeware.org/community/behavior/code-of-conduct/). +## How to contribute -If you'd like to contribute to Rubicon-ObjC development, our [contribution guide](https://rubicon-objc.readthedocs.io/en/latest/how-to/contribute/index.html) details how to set up a development environment, and other requirements we have as part of our contribution process. +If you'd like to contribute to Rubicon Objective C, our [contribution guide](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/) has details on how to pick a way to contribute, how to set up a development environment, and other requirements we have as part of our contribution process. + +### Code of Conduct + +BeeWare operates under a [Code of Conduct](https://beeware.org/community/behavior/code-of-conduct/). All participation the BeeWare community is governed by this code. + +### AI contributions + +We neither encourage nor prohibit the use of autonomous coding tools when contributing to BeeWare projects. However, if you have used an autonomous coding tool to support your work processes, all contributions are you make are ultimately **your** responsibility. + +Our [AI Policy](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/policies/ai-policy/) has the full details of your obligations if you choose to use an AI tool when contributing to BeeWare. + +### Issues + +We have a [process and requirements for creating new issues](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/how/new-issue/). + +### Code style guide + +We have a [code style guide](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/style/code-style-guide/) all code must follow. This is partially enforced by automated pre-commit checks; our guide on [setting up a development environment](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/style/docs-style-guide/) describes how to configure these automated checks. + +### Testing + +We require that all new code is exercised by automated tests. Our contribution guide describes [how to run the project test suite](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/how/write-code/). + +### Documentation + +We require that all new features have full user documentation. We have a [documentation style guide](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/style/docs-style-guide/) that all documentation should follow. Our contribution guide has details on [how to build and preview project documentation](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/how/build-docs/). + +### Pull Requests + +We have a [process for submitting a PR](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/how/submit-pr/) that all contributions must follow. diff --git a/README.md b/README.md index 8581acd4..f61993d2 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,6 @@ If you have any concerns about this code of conduct, or you wish to report a vio ## Contributing -If you experience problems with Rubicon-ObjC, [log them on GitHub](https://github.com/beeware/rubicon-objc/issues). +If you experience problems with Rubicon-ObjC, [log them on GitHub](https://rubicon-objc.beeware.org/en/latest/how-to/contribute/how/new-issue/). If you'd like to contribute to Rubicon-ObjC development, our [contribution guide](https://rubicon-objc.beeware.org/en/latest/how-to/contribute) details how to set up a development environment, and other requirements we have as part of our contribution process. diff --git a/changes/751.feature.md b/changes/751.feature.md new file mode 100644 index 00000000..faca9a85 --- /dev/null +++ b/changes/751.feature.md @@ -0,0 +1 @@ +The Rubicon Objective C repository now has an `AGENTS.md` file and [Spec Kit](https://github.github.com/spec-kit/) constitution to provide assistance for Generative AI tools. diff --git a/docs/en/SUMMARY.md b/docs/en/SUMMARY.md index f079cbb3..6363d73a 100644 --- a/docs/en/SUMMARY.md +++ b/docs/en/SUMMARY.md @@ -33,6 +33,8 @@ - What happens next? - [Pull request review process](how-to/contribute/next/pr-review.md) - [Release process](how-to/contribute/next/release.md) + - Policies + - [AI Policy](how-to/contribute/policies/ai-policy.md) - Style guides - [Code style guide](how-to/contribute/style/code-style-guide.md) - [Documentation style guide](how-to/contribute/style/docs-style-guide.md) diff --git a/docs/en/how-to/contribute/policies/ai-policy.md b/docs/en/how-to/contribute/policies/ai-policy.md new file mode 100644 index 00000000..e17e9998 --- /dev/null +++ b/docs/en/how-to/contribute/policies/ai-policy.md @@ -0,0 +1,3 @@ + + +{% extends "contribute/policies/ai-policy.md" %} diff --git a/pyproject.toml b/pyproject.toml index 3c169e11..f6444239 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -81,6 +81,7 @@ dev = [ # and the docs contribution guide. docs = [ "beeware-docs-tools @ git+https://github.com/beeware/beeware-docs-tools", + # "beeware-docs-tools @ file://../beeware-docs-tools", ] [tool.codespell] diff --git a/tox.ini b/tox.ini index 1eb67e15..caf464b9 100644 --- a/tox.ini +++ b/tox.ini @@ -78,6 +78,8 @@ docs_dir = {tox_root}{/}docs{/}en [testenv:docs{,-lint,-all,-live,-en}] # Docs are always built on Python 3.12. See also the RTD config and contribution docs. base_python = py312 +setenv = + DISABLE_MKDOCS_2_WARNING = true package = wheel wheel_build_env = .pkg dependency_groups = docs