Adoption and hardening roadmap¶
Strategic roadmap for making lifecore_ros2 adoptable beyond the author.
This roadmap addresses structural feedback on the 0.x baseline: the core release is shipped, but scaling adoption requires clear positioning, ergonomic APIs, concurrency safety, strict lifecycle contract, and strong test coverage.
It is organised by nine concerns, each declaring intent, in-scope, out-of-scope, and success signal. Actionable items are tracked in the planning backlog.
—
Guiding principle¶
A developer must be able to create a working
LifecycleComponentin under 2 minutes without reading the full documentation.
Every item below is validated against this principle. If a proposed change increases friction without proportional value, it is rejected.
—
1. Positioning — frame the repo as a library¶
Intent. Stop presenting lifecore_ros2 as “a ROS 2 project” and state clearly that it is a minimal lifecycle composition library for ROS 2 components.
In-scope.
Explicit “Why lifecore_ros2 exists” section in
README.mdTarget audience statement: modular robotics, complex embedded systems, runtime orchestration of lifecycle components
One architecture diagram:
Node ↔ Components ↔ Lifecycle
Out-of-scope.
Marketing copy, logos, branding assets
Comparison matrix against unrelated libraries or middleware
Success signal. A reader who lands on the repo understands in < 30 s what the library is for and who it targets.
Status. ✓ Shipped in v0.4.0: README positioning, architecture diagram, canonical sentence in pyproject.toml.
—
2. API ergonomics — fight over-abstraction¶
Intent. Verify empirically that the current API does not force a developer through ten steps to produce a useful component.
In-scope.
Friction audit: count steps required to (a) create a publisher component, (b) create a subscriber component, (c) compose them under a node
Identify verbose hooks or mandatory overrides that could be optional
Document a canonical “shortest path” example and track it as a regression
Out-of-scope.
Introducing new abstractions to hide complexity (the answer to verbosity is removal, not layering)
Config-driven component creation (deferred — see backlog)
Success signal. The shortest-path publisher example fits on one screen and does not require the reader to know every _on_* hook.
Status. ✓ Shipped in v0.4.0: friction audit documented, msg_type inference implemented, examples/minimal_subscriber.py locked as 24-line regression target.
—
3. Naming convention — lock it in¶
Intent. Stabilise naming now that LifecycleComponent / LifecycleComponentNode have converged. Prevent drift into Core, Manager, Handler synonyms.
In-scope.
Repository-wide naming rules: promote to an authoritative doc section
Explicit rule: no
Abstractprefix; useBaseor no prefixExplicit rule: behavioural interfaces use
Interfacesuffix only if truly neededEnforcement: lint or review checklist item
Out-of-scope.
Renaming any currently-exported public symbol
Retrofitting historical decisions already shipped in 0.x
Success signal. No PR introduces *Manager, *Handler, *Core, or Abstract* classes without being flagged in review.
Status. ✓ Shipped in v0.4.0: naming rules in .github/instructions/naming-conventions.instructions.md, review checklist in CONTRIBUTING.md.
—
4. Ownership & threading — make the concurrency model explicit¶
Intent. Decide and document the threading contract of LifecycleComponentNode and LifecycleComponent. Either protect shared state or declare a single-thread model. No implicit assumptions.
In-scope.
Audit of
add_component, lifecycle transitions, callback dispatch, and component destruction for data racesDecision record: single-threaded model vs mutex-protected model
Explicit rule: forbidden concurrent transitions and their enforcement
Atomic or guarded lifecycle state reads
Out-of-scope.
Introducing a custom executor or threading primitives beyond rclpy
Supporting arbitrary multi-executor topologies (deferred)
Success signal. A reader can answer “can I call add_component from a callback?” by reading one paragraph in the docs.
Status. ✓ Shipped in v0.4.0: single-threaded executor + RLock model, concurrency contract documented in docs/architecture.rst, ConcurrentTransitionError enforcement.
—
5. Strict lifecycle contract¶
Intent. Treat the lifecycle as a contract, not a suggestion. Reject invalid transitions loudly instead of silently accepting them.
In-scope.
Double
activate,deactivatewithout prioractivate, and other invalid sequences → raise a typed exception or return a documented failureExplicit, actionable log messages at every transition boundary
State always coherent: no partial transitions leaking visible state
Out-of-scope.
Replacing native ROS 2 lifecycle semantics with a parallel state machine
Success signal. A test suite covers every invalid transition and asserts the library rejects it deterministically.
Status. ✓ Shipped in v0.4.0: invalid transitions table in docs/architecture.rst, library logging, rollback on failure.
—
6. Test coverage — close the critical gap¶
Intent. Raise test coverage from “nominal paths work” to “the library is trustworthy under stress”.
In-scope.
Unit: full lifecycle walk, double activate/deactivate, add/remove component
Concurrency: multi-thread
add_component, activation during add, destruction duringspinIntegration: node with multiple components, inter-component interactions
Regression: one test per fixed bug going forward
Out-of-scope.
End-to-end system tests requiring a full ROS 2 graph and real hardware
Performance benchmarks (tracked separately if ever needed)
Success signal. CI fails deterministically on any regression in lifecycle semantics, ownership, or activation gating.
Status. ✓ Shipped in v0.4.0: unit, concurrency, and integration test suites; ConcurrentTransitionError / InvalidLifecycleTransitionError coverage; regression test discipline in CONTRIBUTING.md.
—
7. Differentiators — what makes lifecore_ros2 worth adopting¶
Intent. Identify the three features that move the library from “correct” to “compelling” for professional teams. Plan them, but do not ship prematurely.
In-scope (future, gated on 1–6 being solid).
Runtime introspection: list components, read lifecycle state, debug helpers
Dynamic components: clean add/remove at runtime (hot reload)
Observability: structured logging, lifecycle tracing
Out-of-scope for now.
Any of the above before concurrency (4), strict contract (5), and tests (6) are done. Differentiators on a shaky base are liabilities, not assets.
Success signal. Each differentiator has a written design note and an explicit gate referencing prerequisites from sections 4–6.
Status. ✓ Shipped in v0.4.0: design notes in docs/design_notes/ for runtime introspection, dynamic components, and observability.
—
8. README — onboarding quality¶
Intent. The README must get a new reader productive fast.
In-scope.
30-second quickstart (copy-paste runnable)
One complete, realistic example
Architecture diagram (reuse from §1)
Design rules and guardrails (link, do not duplicate)
Out-of-scope.
Full tutorial content (lives in Sphinx docs under
docs/)
Success signal. A reader unfamiliar with the project can run a working lifecycle component within five minutes of cloning.
Status. ✓ Shipped in v0.4.0: quickstart, examples, architecture diagram, links to docs.
—
9. Long-term vision¶
Intent. State the trajectory explicitly so contributors and users can self-select.
Trajectory.
Stable public API (promote to 1.0.0 only when sections 4, 5, 6 are green)
Solid docs (Sphinx + README + examples in sync)
Bulletproof tests (see §6)
Becomes: (a) a base for modular robots, (b) an internal team library, (c) a recognised ROS 2 package
Explicit non-goals.
Full application platform with service orchestration or task scheduling
Domain components, plugin system, or config-driven runtime (deferred)
Status. ✓ Shipped in v0.4.0: long-term vision documented, non-goals explicit, 1.0.0 promotion gate defined in backlog.
—
Sequencing¶
The nine sections are not independent. Recommended order:
Positioning (§1) and README (§8) — cheap, unlock adoption feedback
Naming lock-in (§3) — prevents churn in later work
Concurrency contract (§4) and strict lifecycle (§5) — foundational
Test coverage (§6) — validates §4 and §5
API ergonomics audit (§2) — performed against a stable, tested base
Differentiators (§7) — only after 1–6 are green
Promotion to 1.0.0 is gated on §4, §5, §6 being complete and §1, §2, §8 being materially improved.
—