Context and Problem Statement
Spec Kitty already models tracker routing as:
- a team-level installation,
- optional user links,
- an explicit resource mapping from an external resource to a Spec Kitty project,
- runtime resolution from local project context to the mapped external resource.
That architecture is sound, but the current bind and discovery surfaces are too lossy.
Today:
- the CLI still asks for bind-time metadata such as
project_slug, - the tracker discovery layer collapses provider-native machine identity into
generic
resource_idandresource_labelfields, - provider-specific connector construction still depends on raw identifiers such
as Linear
team_id, Jiraproject_key, GitHubowner/repo, and GitLabproject_id, - the user experience therefore drifts toward asking humans for tracker-native metadata that the system can usually discover itself.
This is the wrong architectural seam.
For SaaS-backed providers, users should connect an installation and then bind a local Spec Kitty project to one of the resources discoverable under that installation. They should not need to know or type machine metadata such as team keys, project keys, repo paths, numeric IDs, or future Azure DevOps coordinates.
Decision Drivers
- No raw metadata prompts in the normal path — the system should not ask the user for tracker-native identifiers it can enumerate itself.
- Provider-native routing — discovered resources must preserve the machine identity needed to build hosted connectors correctly.
- Cross-provider consistency — Jira, Linear, GitHub, GitLab, and future providers should follow one binding model, not bespoke per-provider rituals.
- Host-owned routing boundary — binding and mapping resolution belong in the host control plane, not in prompt folklore or user memory.
- Extensibility — Azure DevOps and other trackers should fit the same discovery and binding contract without redefining the architecture.
Considered Options
- Option 1: Continue requiring manual provider metadata during bind
- Option 2: Implement separate bind contracts for each provider
- Option 3: Standardize on discovered binding context with host-resolved binding
Decision Outcome
Chosen option: Option 3, because the system already has the right routing model and now needs a single authoritative way to discover, preserve, and resolve tracker resource identity.
Core Decision
- Tracker discovery MUST return bindable resource descriptors that preserve:
- a stable resource reference,
- human display labels,
- provider-native connector parameters,
- provider-specific routing metadata.
spec-kitty-saasMUST be authoritative for:- installation inventory,
- resource inventory within an installation,
- resolution from local Spec Kitty project identity to an existing mapping or candidate bind target.
spec-kittyCLI MUST derive local project identity and bind through resolved host context rather than requiring manual raw provider metadata in the normal SaaS bind path.- Local tracker config SHOULD persist a stable binding reference returned by the host control plane. Human-readable slugs may be cached for display or backward compatibility, but they are not the primary binding primitive.
ServiceResourceMapping.routing_metadataor its successor MUST be treated as the canonical place for provider-specific routing metadata that is needed after binding.- When binding is ambiguous, the user MAY choose among discovered labeled resources. The system MUST NOT ask the user to type raw tracker-native machine metadata unless discovery is unavailable and the workflow is explicitly in a repair/admin fallback mode.
Provider Interpretation Rule
Different providers expose different routing units:
- Jira: project under site
- Linear: team or project-like routing unit under workspace
- GitHub: repository under organization/account installation
- GitLab: project under group/namespace
- Azure DevOps: project and possibly team under organization
This ADR does not force identical provider nouns. It forces a shared contract: every provider must expose a bindable resource descriptor with enough data to route correctly without asking the user for hidden machine identity.
Consequences
Positive
- Binding becomes a discovery and selection workflow instead of a memory test.
- Runtime connector construction can rely on stored provider metadata instead of reconstructing it from brittle assumptions.
- New providers can plug into one model.
- Existing SaaS mapping architecture becomes usable from the CLI without leaking provider internals to the user.
Negative
- Discovery contracts in
spec-kitty-trackerbecome richer and more opinionated. spec-kitty-saasmust expose new API surfaces for resource inventory and bind resolution.spec-kittymust support config migration or backward-compatible dual-read for olderproject_slug-only bindings.
Neutral
- Users may still need to choose among multiple discovered resources, but that choice is made from labeled options rather than typed metadata.
- Raw provider metadata still exists internally; it is simply moved behind discovery, mapping, and routing contracts.
Confirmation
This decision is validated when:
- a normal SaaS-backed
tracker bindflow can complete without the user typing a tracker-native key, prefix, repo path, or numeric ID, - each supported provider exposes enough discovered metadata to construct its hosted connector without secondary human input,
- existing mappings can be enumerated and selected before a local bind exists,
- the same binding contract can accommodate a newly added provider such as Azure DevOps without reopening the architectural question.
Pros and Cons of the Options
Option 1: Continue manual provider metadata
Keep the current model where bind-time CLI or dashboard flows ask for project keys, team identifiers, repo coordinates, or similar raw metadata.
Pros:
- Lowest short-term implementation cost.
- Minimal change to current contracts.
Cons:
- Makes the user do discovery work the system can already do.
- Produces provider-specific UX leakage.
- Does not scale cleanly to more providers.
Option 2: Separate bind contracts per provider
Create a custom bind flow for each tracker with its own payloads and local config shape.
Pros:
- Can optimize each provider independently.
- Easy to ship tactical fixes quickly.
Cons:
- Fragments the architecture.
- Forces repeated logic across CLI, SaaS, and tracker library layers.
- Makes future providers slower and riskier to add.
Option 3: Discovered binding context with host resolution
Use a shared discovery contract, preserve provider-native machine identity, and let the host resolve local project identity into mappings or bind candidates.
Pros:
- Aligns with existing installation/link/mapping architecture.
- Eliminates most raw metadata prompts.
- Creates one reusable seam for all current and future providers.
Cons:
- Requires coordinated changes across three repositories.
- Needs disciplined contract design so the generic model does not become vague.
More Information
Related ADRs:
2026-02-11-5-task-tracker-agnostic-connector-architecture.md2026-02-27-2-host-owned-tracker-persistence-boundary.md2026-02-27-3-saas-tracker-integration-via-existing-connectors-journey.mdarchitecture/adrs/2026-03-09-1-prompts-do-not-discover-context-commands-do.md
Current seams this ADR is intended to tighten:
spec-kitty-tracker/src/spec_kitty_tracker/resource_discovery.pyspec-kitty-tracker/src/spec_kitty_tracker/workspace_discovery.pyspec-kitty/src/specify_cli/tracker/config.pyspec-kitty/src/specify_cli/tracker/saas_client.pyspec-kitty/src/specify_cli/cli/commands/tracker.pyspec-kitty-saas/apps/connectors/models.pyspec-kitty-saas/apps/connectors/tracker_views.pyspec-kitty-saas/apps/connectors/runtime_policy.py