Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions openspec/changes/arch-05-bridge-registry/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-02-08
78 changes: 78 additions & 0 deletions openspec/changes/arch-05-bridge-registry/CHANGE_VALIDATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Change Validation Report: arch-05-bridge-registry

**Validation Date**: 2026-02-08
**Change Proposal**: [proposal.md](./proposal.md)
**Validation Method**: Dry-run interface/dependency analysis + strict OpenSpec validation

## Executive Summary

- **Breaking Changes**: 0 detected
- **Impact Level**: Medium (new registry surface, additive manifest/schema behavior)
- **Validation Result**: Pass
- **User Decision Required**: No

## Breaking Change Analysis

No breaking interfaces were proposed.

Additive-only changes:

1. New `bridge_registry` module and `SchemaConverter` protocol.
2. New optional `service_bridges` manifest metadata.
3. New lifecycle registration behavior for declared bridges.
4. New backlog converter implementations.

Compatibility expectation:

- Modules without `service_bridges` remain valid and operational.
- Existing CLI commands continue functioning when bridge metadata is absent.

## Dependency Analysis

## Directly impacted runtime areas

- `src/specfact_cli/registry/module_packages.py`
- `src/specfact_cli/modules/init/src/commands.py`
- `src/specfact_cli/registry/bootstrap.py`
- `src/specfact_cli/modules/backlog/src/commands.py`

## Directly impacted tests

- `tests/unit/specfact_cli/registry/test_module_packages.py`
- `tests/unit/specfact_cli/registry/test_module_dependencies.py`
- `tests/unit/specfact_cli/registry/test_version_constraints.py`
- `tests/unit/specfact_cli/registry/test_init_module_lifecycle_ux.py`

## Risk notes

- `module_packages` is a shared registration path; metadata shape changes can affect init and bootstrap flows.
- Bridge ID conflict behavior must be deterministic and covered by tests.
- Converter import path validation should warn clearly and degrade gracefully.

## Dry-Run Validation Notes

Dry-run checks were performed as proposal-level analysis only (no implementation changes):

- Interface additions were checked for additive semantics.
- Dependent call sites were identified via `rg` against registry, init, and backlog modules.
- No code execution changes were applied to production files during validation stage.

## Artifact and Format Validation

- `proposal.md`: required sections present (`Why`, `What Changes`, `Capabilities`, `Impact`, `Source Tracking`).
- `design.md`: includes context, decisions, risks, migration, and sequence diagram.
- `tasks.md`: branch-first, tests-before-code ordering, issue creation task, PR-last.
- Spec deltas present for:
- `specs/bridge-registry/spec.md`
- `specs/module-packages/spec.md`
- `specs/module-lifecycle-management/spec.md`
- `specs/backlog-adapter/spec.md`

## OpenSpec Validation

- Command: `openspec validate arch-05-bridge-registry --strict`
- Result: `Change 'arch-05-bridge-registry' is valid`

## Conclusion

`arch-05-bridge-registry` is ready for implementation planning and execution under the documented TDD/SDD workflow.
126 changes: 126 additions & 0 deletions openspec/changes/arch-05-bridge-registry/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Design: Bridge Registry for Cross-Module Service Interoperability

## Context

`arch-04-core-contracts-interfaces` establishes module IO contracts and core/module isolation, but it does not define how modules publish reusable schema converters for external services. The internal analysis dated 2026-02-08 and the implementation plan identify this as the next architectural step (arch-05) required before marketplace-grade module decoupling.

Current state:

- Service mapping logic is module-local and not discoverable through a common registry contract.
- Module manifests support dependencies and core compatibility, but not converter bridge declarations.
- Core must stay decoupled from module internals while still enabling dynamic bridge usage.

## Goals / Non-Goals

**Goals:**

- Introduce a registry-level bridge abstraction (`SchemaConverter`, `BridgeRegistry`) for bidirectional schema conversion.
- Make bridge declarations manifest-driven (`service_bridges`) and validated at module registration time.
- Keep core/module isolation intact: no hardcoded core imports of module adapter implementations.
- Deliver backlog reference converters (ADO, Jira, Linear, GitHub) as first adopters.
- Document extension points for custom enterprise bridge mappings.

**Non-Goals:**

- Cryptographic signature validation and trust chain (arch-06).
- Marketplace install/uninstall UX and remote registry APIs (marketplace-01/02).
- Per-module Python environment isolation.
- Breaking existing module registration APIs.

## Decisions

### Decision 1: Protocol + Registry Pattern for Bridges

**Choice:** Define a `SchemaConverter` Protocol and a centralized `BridgeRegistry` with `register_converter()` and `get_converter()` methods.

**Rationale:**

- Preserves plugin-style extensibility already used in module discovery.
- Keeps conversion contract explicit and testable.
- Avoids hardcoded adapter branching in sync/backlog flows.

**Alternatives considered:**

- Inline converter logic in each command path: duplicates logic and increases coupling.
- Abstract base class with strict inheritance: less flexible than protocol-based structural typing.

### Decision 2: Manifest-Driven Bridge Registration

**Choice:** Extend `module-package.yaml` metadata with `service_bridges` entries containing bridge id, description, and converter class path.

**Rationale:**

- Keeps registration declarative and discoverable.
- Allows lifecycle validation before registration.
- Supports future marketplace metadata verification without changing runtime architecture.

**Alternatives considered:**

- Hardcoded module-specific bridge lists in core: violates core isolation.
- Runtime classpath scanning without manifest declarations: less deterministic and harder to validate.

### Decision 3: Graceful Degradation on Bridge Registration Failures

**Choice:** If a bridge declaration is invalid or import fails, skip that bridge with warning/debug logging; do not crash CLI startup.

**Rationale:**

- Matches existing module lifecycle behavior for compatibility/dependency issues.
- Supports parallel module evolution without blocking unrelated workflows.

**Alternatives considered:**

- Fail-fast for any invalid bridge: safer but too disruptive for modular incremental rollout.

### Decision 4: Backlog Module as Reference Bridge Provider

**Choice:** Implement first converter set in backlog module (`ado`, `jira`, `linear`, `github`) and register through metadata.

**Rationale:**

- Backlog already contains major external service integration surface.
- Provides concrete pattern for future modules to follow.

## Risks / Trade-offs

- **Risk:** Converter class import paths drift from code layout.
- **Mitigation:** Add registration-time path validation tests and clear startup warnings.
- **Risk:** Bridge IDs collide across modules.
- **Mitigation:** Deterministic registration rules and explicit duplicate handling with warnings.
- **Risk:** Converter logic divergence across modules.
- **Mitigation:** Publish docs and contract tests against the `SchemaConverter` protocol.
- **Trade-off:** Non-fatal bridge failures improve resilience but can hide misconfiguration.
- **Mitigation:** Elevated warning logs and dedicated validation tests in CI.

## Migration Plan

1. Add bridge registry and converter protocol with unit tests.
2. Extend manifest schema and parser for `service_bridges` metadata.
3. Add lifecycle registration hooks for bridge declaration validation and registry insertion.
4. Add backlog reference converters and manifest declarations.
5. Update docs and run quality gates.

Rollback strategy:

- Remove bridge registration calls from module lifecycle.
- Remove `service_bridges` metadata usage while keeping manifests backward compatible.
- Keep backlog adapters functional through existing direct paths until reintroduced.

## Open Questions

- Should duplicate bridge IDs fail registration or use first-wins semantics with warnings?
- Should converter registration support versioned bridge contracts in arch-06 or later?
- Should enterprise custom mappings be loaded at bridge-level registration or adapter execution time?

## Sequence Diagram: Manifest-Driven Bridge Registration

```text
CLI Startup -> ModuleRegistry: discover module packages
ModuleRegistry -> ManifestParser: parse module-package.yaml
ManifestParser --> ModuleRegistry: metadata (+service_bridges)
ModuleRegistry -> BridgeRegistry: register_converter(bridge_id, converter_class)
BridgeRegistry --> ModuleRegistry: success or warning
ModuleRegistry --> CLI Startup: module commands + bridges available
CLI Command -> BridgeRegistry: get_converter(service_id)
BridgeRegistry --> CLI Command: SchemaConverter implementation
```
55 changes: 55 additions & 0 deletions openspec/changes/arch-05-bridge-registry/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Change: Bridge Registry for Cross-Module Service Interoperability

## Why


`arch-04-core-contracts-interfaces` formalizes module IO contracts and core isolation, but modules still lack a standard way to expose reusable external-service schema converters. Without a bridge registry, modules either duplicate adapter logic or reintroduce coupling, which slows parallel development and blocks marketplace-ready interoperability.

## What Changes


- **NEW**: Add `src/specfact_cli/registry/bridge_registry.py` with `SchemaConverter` protocol and `BridgeRegistry` for converter registration/discovery.
- **MODIFY**: Extend module package metadata to declare `service_bridges` in `module-package.yaml`.
- **MODIFY**: Extend module lifecycle registration to validate and register declared service bridges without direct core-to-module imports.
- **MODIFY**: Add backlog bridge converter implementations (ADO, Jira, Linear, GitHub) under module-local adapters and register them via manifest metadata.
- **NEW**: Add user and developer documentation for bridge registry usage and custom bridge mappings.
- **NEW**: Add tests for bridge registry behavior, manifest parsing, registration-time validation, and module integration.

## Capabilities
### New Capabilities

- `bridge-registry`: Contract-driven registry for service schema converters so modules can publish and consume conversion bridges without hardcoded core logic.

### Modified Capabilities

- `module-packages`: Extend module package manifest schema with declarative bridge metadata.
- `module-lifecycle-management`: Extend discovery/registration flow to validate and register bridge converters safely.
- `backlog-adapter`: Add bridge converter implementations and mapping behaviors for backlog service integrations.

## Impact

- **Affected specs**: New spec for `bridge-registry`; delta specs for `module-packages`, `module-lifecycle-management`, and `backlog-adapter`.
- **Affected code**:
- `src/specfact_cli/registry/bridge_registry.py` (new)
- `src/specfact_cli/registry/module_packages.py` (bridge metadata loading and registration)
- `src/specfact_cli/models/module_package.py` (service bridge metadata)
- `src/specfact_cli/modules/backlog/src/adapters/*.py` (new converter modules)
- `tests/unit/registry/test_bridge_registry.py` (new)
- `tests/unit/registry/test_module_bridge_registration.py` (new)
- **Affected documentation**:
- `docs/reference/bridge-registry.md` (new)
- `docs/guides/creating-custom-bridges.md` (new)
- `docs/reference/architecture.md` and `docs/_layouts/default.html` (updated navigation and architecture notes)
- **Integration points**: module discovery, manifest parsing, registry startup, backlog adapters, sync workflows.
- **Backward compatibility**: Backward compatible. Modules without `service_bridges` remain valid and continue working.
- **Rollback plan**: Disable bridge registration in module lifecycle and remove `service_bridges` manifest handling; modules continue with existing adapter behavior.

---

## Source Tracking

<!-- source_repo: nold-ai/specfact-cli -->
- **GitHub Issue**: #207
- **Issue URL**: <https://github.com/nold-ai/specfact-cli/issues/207>
- **Last Synced Status**: proposed
- **Sanitized**: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Spec: Backlog Adapter

## ADDED Requirements

### Requirement: Backlog module provides bridge converters for supported services

The system SHALL provide backlog bridge converters for Azure DevOps, Jira, Linear, and GitHub using the shared bridge registry contract.

#### Scenario: Backlog module declares service bridges in manifest

- **WHEN** backlog module package metadata is discovered
- **THEN** manifest `service_bridges` SHALL declare converter entries for `ado`, `jira`, `linear`, and `github`
- **AND** each entry SHALL reference a converter class path under backlog adapters.

#### Scenario: Backlog converters satisfy schema converter contract

- **WHEN** bridge converters are loaded
- **THEN** each converter SHALL implement `to_bundle` and `from_bundle` operations
- **AND** conversion behavior SHALL preserve required backlog fields for round-trip workflows.

### Requirement: Backlog bridge mappings support custom enterprise overrides

The system SHALL allow custom bridge field mappings for backlog converter workflows.

#### Scenario: Custom mapping file overrides default mapping

- **WHEN** a custom mapping YAML exists for a configured service bridge
- **THEN** backlog converter behavior SHALL apply custom mapping before default mapping
- **AND** fallback to defaults when custom mappings are absent or incomplete.

#### Scenario: Invalid custom mapping falls back safely

- **WHEN** custom mapping configuration is malformed
- **THEN** converter execution SHALL continue with default mapping behavior
- **AND** SHALL emit warning/debug context for troubleshooting.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Spec: Bridge Registry

## ADDED Requirements

### Requirement: Bridge registry provides converter registration and lookup

The system SHALL provide a `BridgeRegistry` that supports module-driven registration and lookup of service schema converters.

#### Scenario: Register converter for service ID

- **WHEN** a module lifecycle registration step provides a valid bridge declaration
- **THEN** `BridgeRegistry` SHALL register the converter for the declared bridge ID
- **AND** the converter SHALL be retrievable by that same bridge ID.

#### Scenario: Lookup missing converter fails with explicit error

- **WHEN** code requests a converter for a bridge ID that is not registered
- **THEN** `BridgeRegistry` SHALL raise a clear lookup error
- **AND** the error SHALL include the missing bridge ID.

### Requirement: SchemaConverter protocol defines bidirectional conversion contract

The system SHALL provide a `SchemaConverter` protocol to standardize conversion between external service payloads and ProjectBundle-compatible data.

#### Scenario: Converter defines to_bundle contract

- **WHEN** a converter implements `SchemaConverter`
- **THEN** it SHALL implement `to_bundle(external_data: dict) -> dict`
- **AND** the returned payload SHALL be compatible with ProjectBundle construction.

#### Scenario: Converter defines from_bundle contract

- **WHEN** a converter implements `SchemaConverter`
- **THEN** it SHALL implement `from_bundle(bundle_data: dict) -> dict`
- **AND** the returned payload SHALL be service-specific output.

### Requirement: Bridge registry preserves core-module isolation

The system SHALL enforce bridge registration without introducing direct core imports from `specfact_cli.modules.*`.

#### Scenario: Core retrieves bridge via registry only

- **WHEN** core CLI workflows need a converter
- **THEN** they SHALL call `BridgeRegistry.get_converter()`
- **AND** SHALL NOT import converter implementations directly from module command packages.

#### Scenario: Invalid bridge declaration degrades gracefully

- **WHEN** module metadata declares an invalid converter class path
- **THEN** registration SHALL skip that bridge and log warning/debug context
- **AND** CLI startup SHALL continue for unaffected modules.

### Requirement: Bridge registration supports offline-first workflows

The system SHALL support bridge registration and local converter resolution without requiring network access.

#### Scenario: Offline startup with local manifests

- **WHEN** CLI starts in an offline environment
- **THEN** bridge registration SHALL complete using local module manifests and local Python imports
- **AND** SHALL NOT require external API or registry calls.
Loading
Loading