Contributing to LinkForge
Thank you for your interest in contributing to LinkForge! This guide will help you get started.
Table of Contents
Code of Conduct
Be respectful, inclusive, and professional. We’re all here to build great robotics tools together.
Getting Started
Prerequisites
Python 3.11+
Blender 4.2+
Git
just (Command Runner)
macOS:
brew install justLinux:
sudo apt install just(or viasnap/cargo)Windows:
choco install justorscoop install justUniversal:
cargo install just(requires Rust)
uv (Python package manager) - Install:
curl -LsSf https://astral.sh/uv/install.sh | sh
Fork and Clone
# Fork the repository on GitHub, then:
git clone https://github.com/YOUR_USERNAME/linkforge.git
cd linkforge
Development Setup
1. Install Dependencies
# Install everything (deps + pre-commit hooks)
just install
2. Verify Setup
# Run tests to verify everything works
just test
# Run linter and type checker
just check
# Build extension
just build
Project Structure
linkforge/
├── core/ # Core Robotics Logic (pip package)
│ └── src/linkforge/core/
├── platforms/
│ └── blender/ # Blender Extension (.zip)
├── tests/ # Test Suite (unit + integration)
├── examples/ # Example URDF/XACRO files
└── pyproject.toml # Workspace config
See ARCHITECTURE for detailed architecture diagrams.
Development Workflow
graph LR
A[Fork & Clone] --> B[Feature Branch]
B --> C[Code & Test]
C --> D[pre-commit Checks]
D --> E[Pull Request]
E --> F{Review}
F -- Fixes --> C
F -- Approved --> G[Merge to main]
G --> H[Automated Release PR]
H --> I[Tag & Release]
1. Create a Feature Branch
git checkout -b feature/your-feature-name
2. Make Changes
Write code following our Code Style
Add tests for new functionality
Update documentation as needed
3. Run Quality Checks
# Run all tests (Core + Blender)
just test
# Run specific tiers
just test-core # Fast core logic (unit + integration)
just test-unit-blender # Mocked platform logic unit tests
just test-integration-blender # Full Blender integration tests
# Run linter and type checker
just check
# Fix linting issues automatically
just fix
4. Live Testing in Blender (Development Mode)
LinkForge uses a Development Junction system to link your workspace directly into Blender without needing to build and re-install packages.
# 1. Establish the link (Run once)
just develop
# 2. Open Blender
# 3. Edit > Preferences > Extensions
# 4. Search for "LinkForge" and Enable it
Any changes you make to the .py files in your editor will be instantly available in Blender (you only need to restart Blender or reload the extension).
5. Testing the Release (Optional)
If you want to verify the final user experience (including bundled wheels):
# 1. Build the production ZIPs
just build
# 2. In Blender: Edit > Preferences > Extensions
# 3. Dropdown (⌄) > Install from Disk
# 4. Select dist/linkforge-blender-x.x.x-macos_arm64.zip
6. Commit Changes
git add .
git commit -s -m "feat: add your feature description"
Commit Message Format:
feat:New featurefix:Bug fixdocs:Documentation changestest:Test additions/changesrefactor:Code refactoringperf:Performance improvementschore:Maintenance tasks
Testing
Running Tests
LinkForge uses a Tiered Testing Architecture to balance speed and fidelity:
Tier |
Command |
Scope |
|---|---|---|
Core |
|
Models, Kinematics, Parsers (Zero-deps) |
Logic |
|
Blender Adapters & Math (Mocked |
Integration |
|
Real Scene Interaction (Real Blender) |
See Automated Testing for our full strategy and coverage metrics.
To run specific tests or categories:
# Run with coverage (Combined report)
just coverage
# Run specific core test file (manual)
uv run pytest tests/unit/core/test_robot.py
# Run specific Blender integration test file (manual)
uv run python scripts/blender_launcher.py tests/integration/platforms/blender/test_roundtrip.py
Manual QA (Mandatory)
For features involving UI, viewport transforms, or complex exports, automated tests are not enough. Contributors must follow and pass the Manual QA Protocol before submitting a PR.
Objective: Ensure export validity (URDF/XACRO standards), correct physics calculations, and UI stability across macOS, Windows, and Linux.
Protocol: Follow the 7-Phase checklist in
docs/testing/manual_qa.md.
Writing Tests
Unit Test Example
def test_link_creation():
"""Test creating a link with valid parameters."""
link = Link(
name="test_link",
visuals=[],
collisions=[],
inertial=Inertial(mass=1.0, inertia=InertiaTensor.stability_floor())
)
assert link.name == "test_link"
assert link.inertial.mass == 1.0
Round-Trip Test Example
def test_sensor_roundtrip():
"""Test sensor origin survives import-export cycle."""
# Create robot with sensor
robot = Robot(
name="test",
initial_links=[Link(name="base_link")],
initial_sensors=[
Sensor(
name="test_camera",
type=SensorType.CAMERA,
link_name="base_link",
camera_info=CameraInfo(),
origin=Transform(xyz=(0.1, 0.0, 0.2))
)
]
)
# Export to URDF
generator = URDFGenerator()
urdf = generator.generate(robot)
# Re-import
from linkforge.core import URDFParser
robot2 = URDFParser().parse_string(urdf)
# Verify sensor origin preserved
assert robot2.sensors[0].origin == robot.sensors[0].origin
Unit Tests (
tests/unit/): Test individual functions/classes in isolation, split intocore/andplatforms/.Integration Tests (
tests/integration/): Test full workflows and round-trips, split intocore/(logic, parsers) andplatforms/(Blender-specific).
[!TIP] Use Central Fixtures: Always use the
examples_dirfixture fromtests/conftest.pywhen accessing example URDFs. Avoid hardcoding relative paths like../../examples.
We follow a Tiered Mocking Strategy based on the level of interaction:
Platform Logic Tests (
unit/platforms/): Prefer Mocks.For math and transformation logic in adapters, use
unittest.mockto verify inputs/outputs.This allows for sub-second developer loops without booting Blender.
Integration Tests (
integration/platforms/): Prefer Real Data.For scene manipulation and UI operators, use a real (headless) Blender instance.
Use
bpy.ops.object.empty_add()to create real objects in your test fixtures.Use the
blender_clean_scenefixture to ensure environment isolation.
Core Tests (
unit/core/): Zero Dependencies.Instantiate real
Robot,Link, orJointobjects.Mock only for external edge cases: Filesystem failures or missing optional dependencies.
Debugging in Blender
from linkforge.core import get_logger
logger = get_logger(__name__)
logger.error(f"Debug: {variable}")
# View in Blender Console (Window > Toggle System Console)
Code Style
Python Style Guide
Documentation Standards (Lean Google Style)
We follow a Lean Google Style for documentation. Every module and class must be documented to provide high-level context and component breakdowns:
Module Headers: Summarize the purpose and categorize key components (Models, Validators, Utilities).
Concise Summaries: Focus on intent and physical implications rather than just restating the signature.
Core Components: Use a structured list in module docstrings to identify the main actors.
"""Module title.
Brief high-level summary of role in the IR.
Core Components:
- ComponentA: Brief role description.
- ComponentB: Brief role description.
"""
“Physics as Truth” Design Principle
LinkForge follows a strict Physics as Truth philosophy. The Intermediate Representation (IR) is not just a data structure; it is a physical model that must remain stable and plausible at all times.
Strict Validation: All models (Link, Joint, Sensor) must implement
__post_init__guardrails for physical properties (e.g., non-negative mass, normalized axes, valid LIDAR ranges).Orchestrated Checks: Global consistency (cycles, connectivity, ros2_control limits) is enforced by the
RobotValidator.Fail Fast: We prefer a
RobotValidationErrorat construction time over a physics engine crash at runtime.
# Good
def parse_float(text: str | None, default: float | None = None) -> float:
...
# Bad
def parse_float(text, default=None):
...
Linting Configuration
Our project rigorously enforces code quality using ruff. The definitive configuration (including line length, target version, and active rule sets) is maintained centrally in pyproject.toml. Please refer to the [tool.ruff.lint] section in that file for the current active and ignored rules.
Pre-commit Hooks
Pre-commit automatically runs on git commit:
ruff check- Linting (with auto-fix)ruff format- Code formattingconventional-pre-commit- Enforces conventional commit messagescodespell- Catches common typos in code and docsStandard file checks - trailing whitespace, EOF newline, YAML/TOML/JSON validation, large files, merge conflicts, etc.
Submitting Changes
Developer Certificate of Origin (DCO)
All contributions to this project must be accompanied by a Developer Certificate of Origin (DCO) sign-off. This ensures that you have the right to submit the code under the project’s open-source license.
To sign off on a commit, simply use the -s flag when committing:
git commit -s -m "Your descriptive commit message"
This will automatically add the following line to your commit message:
Signed-off-by: Your Name <your.email@example.com>
Pull Request Process
Push your branch
git push origin feature/your-feature-name
Create Pull Request
Go to GitHub and create a PR
Fill out the PR template
Link any related issues
Check Pull Request Status
Ensure the CI pipeline passes (GitHub Actions).
Once you create the PR, follow the automated checklist provided in the PR description template. This ensures all standards (tests, linting, quality) are met before maintainer review.
Code Review
Address review comments
Keep commits clean and logical
Squash commits if requested
Merge
Maintainer will merge once approved
Your contribution will be in the next release!
PR Title Format
Use conventional commits:
feat: Add support for new sensor typefix: Correct sensor origin exportdocs: Update architecture diagramstest: Add round-trip tests for transmissions
Release Process
LinkForge uses Release Please to automate versioning and changelogs.
Automation: When code is merged into
main, Release Please will automatically create (or update) a “Release PR”.Versioning: This PR will contain a version bump in
pyproject.toml,blender_manifest.toml,CITATION.cff, and an updatedCHANGELOG.mdbased on your commit messages.Merging: Once a maintainer merges this Release PR, a GitHub Tag and Release are automatically created.
Distribution: The
release-please.ymlworkflow will then build the extension.zipand attach it to the GitHub Release.
Release Standards
To maintain a professional and consistent appearance:
Tagging: Always use simple
vprefixed tags (e.g.,v1.3.0). This is handled automatically by the configuration.Release Titles: Follow the format
v1.x.x: [Major Highlight]. For example:v1.3.0: Performance & Control Refinement.Changelog: Use the project’s custom sections (🚀 Features, 🐞 Bug Fixes, etc.) to keep notes organized.
[!NOTE] This is why Conventional Commits are required. Without them, the release automation cannot determine if a change should bump the MAJOR, MINOR, or PATCH version.
Technical Considerations
To maintain LinkForge’s status as a professional-grade Linter & Bridge, we prioritize stability in three key areas:
1. The Blender Bridge (Foundation)
LinkForge must remain compatible with the latest Blender LTS (Long Term Support) and the current stable release.
Vigilance: When a new Blender version (e.g., 6.0) enters Beta, we prioritize testing our Blender integration to ensure no API breaking changes affect our users.
2. URDF/XACRO Fidelity (Core)
Our primary goal is 100% compliance with official specifications.
Cross-Simulator Support: We ensure that generated files work seamlessly across Gazebo (Classic & Sim), Webots, Isaac Sim, and MuJoCo.
Precision: Physics calculations (inertia tensors) must remain scientifically accurate, as they are the “brain” of the exported robot.
3. The ROS 2 Ecosystem (Integration)
While LinkForge supports ros2_control, it is designed to be distribution-agnostic where possible.
Compatibility: We target compatibility with active ROS 2 LTS distributions (like Humble and Jazzy) and Rolling.
Maintenance: If the official
ros2_controlXML syntax changes in a newer ROS version, we update our generators to support those changes while maintaining backward compatibility.
4. Validation Extensibility (Quality Control)
To maintain the highest standards of robot description quality, LinkForge uses a Modular Validation Registry.
The Rule: Every new core model feature must be accompanied by a corresponding
ValidationCheckincore/src/linkforge/core/validation/checks.py.Implementation: Inherit from
ValidationCheck, implement therun()method, and append your class toRobotValidator.DEFAULT_CHECKS.Testing: Add isolated unit tests for your new check in
tests/unit/core/test_validation_checks.py.
Maintainer Expectations
As a maintainer-driven project, we aim to be transparent about our availability and response times:
Review Cycle: Expect an initial response or feedback on PRs within 7 business days.
Issue Triage: New issues are usually triaged during our weekly maintenance window (typically weekends).
Issue Assignment & Progress:
If you are interested in an issue, please comment to ask for assignment.
We value momentum. If an assigned issue has no activity (comments or PR) for 14 days, we will check in.
After 21 days of inactivity, the issue may be unassigned to allow other contributors to help.
Public Communication: We prefer all discussions to happen in public issues or GitHub Discussions to ensure the community benefits from the shared knowledge.
Decision Making: For major architectural changes, we follow a consensus-based approach among core maintainers. If you are proposing a large change, please open a Discussion first to get early feedback.
Governance
LinkForge is currently maintained by @arounamounchili and the community.
Core Maintainers: Responsible for architectural oversight and final merging.
Contributors: Anyone who submits code, documentation, or feedback.
Recognition: We follow the All Contributors specification to recognize all types of contributions.
Getting Help
Documentation: Check the Official Documentation and Architecture Guide
Issues: Search existing issues
Discussions: Ask in GitHub Discussions
Recognition
We value every contribution! To keep things simple for maintainers, contributor recognition is fully automated:
README.md: Handled by the@all-contributorsbot.CHANGELOG.md& Release Notes: Automated viarelease-pleasebased on commit messages.GitHub Contributors: Managed automatically by GitHub’s platform.
All Contributors Bot
We use the @all-contributors bot to automatically recognize all types of contributions.
How to get recognized: If you’ve contributed (code, docs, ideas, etc.), you can ask the bot to add you by commenting on an issue or pull request:
@all-contributors please add @username for <contribution-type>
Replace <contribution-type> with one of the valid contribution types (e.g., code, doc, bug, etc.).
Academic Recognition
For profound core contributions (e.g., advanced mathematical noise models, novel simulator integrations, or deep physics engine refinements), we may invite you to be listed as a co-author in the CITATION.cff file and the official documentation. This ensures your high-level domain expertise is properly attributed in future academic research using LinkForge.
(Note: Standard features, basic sensor additions, and bug fixes are highly valued and will be celebrated via our standard Open Source contributors framework, but they do not automatically qualify for academic co-authorship).
Thank you for contributing to LinkForge!