Quickstart: Tracker Binding Context Discovery

Feature: 062-tracker-binding-context-discovery

What Changed

The tracker bind flow for SaaS providers no longer requires --project-slug. Instead, the CLI discovers bindable resources from the SaaS host and lets you select one.

New Commands

tracker discover

Browse all bindable resources under your installation:

spec-kitty tracker discover --provider linear

Output:

  #  Resource                      Provider  Workspace     Status
  1  My Project (LINEAR-123)       linear    Acme Corp     ● bound
  2  Backend API (LINEAR-456)      linear    Acme Corp     ○ available
  3  Mobile App (LINEAR-789)       linear    Acme Corp     ○ available

JSON output for scripting:

spec-kitty tracker discover --provider linear --json

tracker bind (updated)

Bind with auto-discovery:

spec-kitty tracker bind --provider linear
# → resolves identity, auto-binds or shows candidates

Non-interactive (CI/automation):

# By bind-ref (validated against host):
spec-kitty tracker bind --provider linear --bind-ref srm_01HXYZ

# By selection number:
spec-kitty tracker bind --provider linear --select 1

tracker status --all

Installation-wide status:

spec-kitty tracker status --all

Config Changes

Before (pre-062)

tracker:
  provider: linear
  project_slug: my-project

After (post-062)

tracker:
  provider: linear
  binding_ref: srm_01HXYZ...
  project_slug: my-project          # kept for legacy compat
  display_label: "My Project (LINEAR-123)"
  provider_context:
    team_name: Engineering
    workspace_name: Acme Corp

Backward compatibility: Existing configs with only project_slug continue to work. The CLI opportunistically writes binding_ref on successful SaaS calls.

Key Concepts

ConceptDescription
candidate_tokenPre-bind opaque token from discovery. Passed to bind-confirm. Never persisted.
binding_refPost-bind stable reference from host. Primary routing key. Persisted in config.
Opportunistic upgradeSuccessful SaaS calls silently write binding_ref to legacy configs.
Stale bindingHost-side deletion/disable of mapping. CLI errors with re-bind instructions.

Testing

Run the full tracker test suite:

python -m pytest tests/sync/tracker/ tests/agent/cli/commands/test_tracker.py -x -q

Run only the new discovery tests:

python -m pytest tests/sync/tracker/test_discovery.py tests/sync/tracker/test_saas_client_discovery.py -x -q

Files Changed

FileWhat
src/specify_cli/tracker/config.py+binding_ref, +display_label, +provider_context, +unknown field passthrough
src/specify_cli/tracker/discovery.pyNEW: dataclasses (BindableResource, BindCandidate, etc.) + pure data helpers
src/specify_cli/tracker/saas_client.py+resources(), +bind_resolve(), +bind_confirm(), +bind_validate(); enriched SaaSTrackerClientError; existing methods gain binding_ref param
src/specify_cli/tracker/saas_service.py+discover(), +resolve_and_bind(), +_maybe_upgrade_binding_ref(), +_resolve_routing_params(), stale-binding detection
src/specify_cli/tracker/service.pyTrackerService facade: +discover(), updated bind(), +status(all=)
src/specify_cli/cli/commands/tracker.py+discover command, updated bind, +status --all