# perk provider-selection supported set — the THIRD parsed cross-plane contract
# (sibling of registry.yaml and bindings.yaml).
#
# Authored once here, bundled into each build artifact (wheel -> perk/_shared/,
# npm tarball -> shared/), and parsed directly by both planes at runtime: the
# Python reader is perk/substrate/providers.py, the TS reader is extension/substrate/providers.ts. No
# codegen step — both planes read this same file.
#
# This is the SUPPORTED SET (the full catalog of providers perk knows how to wire),
# distinct from the per-repo SELECTION (the flat `[providers]` table in .pi/perk.toml,
# which is just a pointer into this catalog). Because both planes read this with their
# full YAML readers, it can carry nested structure — notably the Pi `package_filter`
# object — that the narrow-TOML config reader cannot.
#
# Vocabulary — each provider entry:
#   id      — the stable provider id. NOT the cache.plan-ref `provider` string:
#             that field is the ISSUE BACKEND (the stamped `backend_id`, e.g.
#             "github"), not the seam id — see contracts.md §8.10 / §8.21.
#   seam    — `plan` | `footer` | `web` (the three seams; see
#             pluggability-taxonomy.md for the scope fence).
#   package — the foreign Pi package spec added to .pi/settings.json `packages`
#             (e.g. "npm:@tombell/pi-plan"); `null` for perk's own bundled reference
#             provider (nothing to add — perk produces the contract natively). NOT
#             universal: the `web` seam's reference provider (`pi-web-access`) is itself
#             a FOREIGN package because perk owns no native web implementation — its
#             `default: true` entry carries a non-null `package` (the documented exception).
#   adapter — the perk-owned shim module that bridges the foreign surface to the
#             artifact boundary (cache.plan-ref); `null` for the
#             reference provider.
#   default — exactly ONE `true` per seam: the behavior-preserving no-config pick.
#   package_filter — optional Pi object-form filter (extensions/skills/… arrays)
#             merged into the foreign package's `packages` entry to enable only the
#             conflicting surface. perk's own package is NEVER filtered (it defers at
#             runtime instead — adapter-architecture.md Invariant 2).
#
# Validation split (mirrors bindings.yaml): the shape-only loaders (perk/substrate/providers.py,
# extension/substrate/providers.ts) check schema_version, id uniqueness, seam membership, and
# exactly-one-default-per-seam. Cross-checks — does the repo's `[providers]` selection
# name a provider that exists / has the right seam? — are `doctor`'s job, NOT the
# loaders. The Python plane is the authoritative validator.
#
# Status: this file ships the substrate (the reference entries + foreign entries per seam), and
# every seam has a REAL foreign provider. The PLAN adapter: `tombell-plan` is a REAL, selectable
# plan provider — `planAdapterTombell` bridges `@tombell/pi-plan`'s free-form prose surface to
# perk's canonical `plan_save` → `cache.plan-ref` contract, and perk VACATES the plan surface at
# REGISTRATION time (not just handler-time) under a foreign plan selection so the foreign
# `/plan`/`Ctrl+Alt+P`/`--plan` are the sole registrants (Pi suffixes duplicate command
# names). The DEFAULT path (the reference providers) is the hard guarantee.
#
# The FOOTER seam is one of the TWO INTERFACE seams (with web; no durable artifact to bridge),
# vacated at the INSTALL SITE (runtime) rather than registration time: perk installs
# its own footer (`installPerkFooter`) inside the `session_start` event handler, so under a foreign
# `[providers] footer` selection perk simply does NOT call `installPerkFooter` (a runtime guard at
# that single install site, keyed off `ctx.cwd`), leaving the foreign footer (`pi-powerline-footer`,
# `pi-bar`, or `@tombell/pi-status`) as the sole footer surface. `adapter: null`, no shim: for
# `pi-powerline-footer`/`pi-bar` perk's objective progress reaches the foreign footer
# automatically via the already-publishing single-value `perk` `setStatus` slot (both render
# extension statuses), so the bridge is automatic; `@tombell/pi-status` is the exception (it does NOT render
# extension statuses — see the `pi-status-footer` note below).
# Fail-safe: any config-read error resolves to the reference id → perk installs its footer (the
# default path is the hard zero-change guarantee).
#
# Two more footer outcomes round out the catalog so the footer is governed EXCLUSIVELY by
# `[providers] footer` (no footer outcome ever needs a manual `packages` edit):
#   - `pi-status-footer` (`npm:@tombell/pi-status`) is vacate-only like the two above, BUT — unlike
#     `powerline-footer`/`pi-bar-footer` — pi-status does NOT render extension statuses, so perk's
#     objective progress is NOT shown in the footer when it is selected. This is an
#     accepted limitation (it matches what pi-status already does today); perk does not build a
#     status-bridge adapter for it (it is a genuine interface seam).
#   - `pi-default` (`package: null`) is the "install nothing / leave pi's stock built-in footer"
#     option: perk vacates (gate false), convergence adds no package, so pi's own footer stands.
#
# The WEB seam is the OTHER INTERFACE seam (no durable artifact to bridge), but with a genuine
# novelty: it is the ONLY seam whose `default: true` provider has a NON-NULL `package`. perk owns
# no native web-research implementation, so the behavior-preserving reference (`pi-web-access`,
# zero-config Exa search + content fetch + the bundled `librarian` skill) is itself a foreign npm
# package. Selection simply SWAPS which web package the provider-convergence installs — `adapter:
# null`, no shim, and there is NO perk surface to vacate at registration time because perk registers
# NO web tools of its own. The read-only allowlist statically carries the UNION of all known web
# tool names (inert when absent); perk does NOT normalize tool names across providers. `librarian`
# is pi-web-access-specific (it depends on `fetch_content`'s GitHub-clone path) and is accepted as
# lost under a foreign web selection. Fail-safe: any config-read error resolves to `pi-web-access`,
# keeping today's behavior exactly.
#
# There is NO review seam: the two surface-named review doors (`/pr-review-terminal` — the hunk
# terminal TUI; `/pr-review-browser` — the plannotator browser UI) are the selection (the command
# IS the surface pick). The hunk CLI converges unconditionally (init/doctor's best-effort
# `review-cli` install/verify); the plannotator package rides the plan seam's `plannotator-plan`
# entry.
#
# There is NO askuser seam anymore: it is RETIRED to a REQUIRED BORROW. After perk's first-party
# `ask_user_question` tool was deleted the seam had exactly one selectable provider — nothing to
# select (the borrow-vs-seam criterion) — so `ask_user_question` is now the borrowed
# `@juicesharp/rpiv-ask-user-question` questionnaire, installed for every repo via
# `BORROWED_PACKAGES` (convergence/init/settings.py).
#
# There is NO todo seam anymore: it is RETIRED to a REQUIRED BORROW. After the seam had exactly
# one selectable provider — nothing to select (the borrow-vs-seam criterion) — the checklist
# overlay became the borrowed `@juicesharp/rpiv-todo`, installed for every repo via
# `BORROWED_PACKAGES` (convergence/init/settings.py).

schema_version: 1

providers:
  - id: perk-plan            # perk's own planMode/planSave over toolGating
    seam: plan
    package: null            # null ⇒ perk's bundled reference provider (no foreign package)
    adapter: null            # null ⇒ no shim needed; perk produces the contract natively
    default: true            # the behavior-preserving no-config pick for the plan seam

  # --- foreign entries ---
  - id: tombell-plan         # REAL plan provider (Node 2.3) — planAdapterTombell bridges it
    seam: plan
    package: "npm:@tombell/pi-plan"   # the foreign Pi package to add to `packages`
    adapter: "planAdapterTombell"     # the perk-owned shim bridging surface → cache.plan-ref
    default: false
    # No `package_filter`: `@tombell/pi-plan`'s sole extension is its root `index.ts` (not under
    # `extensions/`), so omitting the filter ("load all of that type") loads exactly that one
    # extension. The `package_filter` field stays in the vocabulary for future providers.
  - id: plannotator-plan   # REAL plan provider — planAdapterPlannotator bridges its browser review
    seam: plan
    package: "npm:@plannotator/pi-extension"   # the foreign Pi package to add to `packages`
    adapter: "planAdapterPlannotator"          # the perk-owned shim bridging plan_review → its event API
    default: false
    # AUGMENT posture (contrast with tombell-plan's REPLACE posture): plannotator does not replace
    # perk's plan surface — perk's `/plan` command, authoring injection, and read-only gate STAY
    # registered; perk skips only the two real registration collisions (`--plan` flag and the
    # `Ctrl+Alt+P` shortcut, both of which plannotator also registers — duplicate flag/shortcut
    # registration is the known potentially-fatal Pi behavior). The bridge is the model-callable
    # `plan_review` tool (planAdapterPlannotator) → plannotator's `plannotator:request` plan-review
    # event flow (its browser review UI). Saving stays the human-run `/plan-save`.
    # No `package_filter`: `@plannotator/pi-extension`'s `pi.extensions` is `["./"]` (the sole
    # extension is the package root), so omitting the filter loads exactly that one extension.
  - id: perk-footer          # perk's own footer (extension/surfaces/surfaces.ts installPerkFooter)
    seam: footer
    package: null
    adapter: null
    default: true            # the behavior-preserving no-config pick for the footer seam
  - id: powerline-footer     # REAL footer provider — VACATE-ONLY (interface seam, no adapter)
    seam: footer
    package: "npm:pi-powerline-footer"   # the foreign Pi package to add to `packages`
    adapter: null            # VACATE-ONLY: the footer produces no durable artifact (interface seam),
                             # and pi-powerline-footer already renders perk's `perk` setStatus slot in
                             # its extension_statuses segment, so the bridge is automatic (no shim).
    default: false
    # No `package_filter`: load the package's sole footer extension ("load all of that type").
  - id: pi-bar-footer        # REAL footer provider — VACATE-ONLY (interface seam, no adapter)
    seam: footer
    package: "npm:pi-bar"   # the foreign Pi package to add to `packages`
    adapter: null            # VACATE-ONLY: pi-bar replaces pi's footer and "keeps extension statuses
                             # visible", so perk's `perk` setStatus slot appears automatically — no shim.
    default: false
    # No `package_filter`: load the package's sole footer extension ("load all of that type").
  - id: pi-status-footer     # REAL footer provider — VACATE-ONLY (interface seam, no adapter)
    seam: footer
    package: "npm:@tombell/pi-status"   # the foreign Pi package to add to `packages`
    adapter: null            # VACATE-ONLY: the footer produces no durable artifact (interface seam).
                             # UNLIKE powerline/pi-bar, pi-status does NOT render extension statuses,
                             # so perk's objective progress is NOT shown in the footer
                             # under this selection (an accepted limitation — matches pi-status today;
                             # no status-bridge adapter is built).
    default: false
    # No `package_filter`: load the package's sole footer extension ("load all of that type").
  - id: pi-default           # "install nothing" footer provider — leaves pi's stock built-in footer
    seam: footer
    package: null            # null ⇒ perk adds NO package; pi's own built-in footer stands.
    adapter: null            # VACATE-ONLY: perk's footer-install gate is false (resolved id ≠
                             # perk-footer), so perk skips installPerkFooter; nothing else to add.
    default: false
  - id: pi-web-access        # web seam DEFAULT — the FOREIGN reference provider (perk owns no native web impl)
    seam: web
    package: "npm:pi-web-access"   # NON-NULL default package: the novelty — perk has no native web provider
    adapter: null            # VACATE-ONLY interface seam: no durable artifact, and perk registers NO web
                             # tools, so there is no perk surface to vacate. Selection just swaps the package.
    default: true            # the behavior-preserving no-config pick (zero-config Exa search + `librarian`)
    # No `package_filter`: `pi-web-access`'s sole extension is its root `./index.ts` (verified via
    # `npm view pi-web-access pi`), so omitting the filter loads exactly that one extension.
  - id: ollama-web-search    # REAL web provider — VACATE-ONLY (interface seam, no adapter)
    seam: web
    package: "npm:@ollama/pi-web-search"   # the foreign Pi package to add to `packages`
    adapter: null            # VACATE-ONLY: web is an interface seam (no artifact); perk registers no web
                             # tools, so nothing to vacate. Tools: `ollama_web_search`/`ollama_web_fetch`
                             # (needs a local Ollama daemon). Divergent names — perk allowlists the union.
    default: false
    # No `package_filter`: verified manifest is `{"extensions": ["./index.ts"]}`, so omitting the
    # filter loads exactly that one extension.
  - id: juicesharp-web-tools # REAL web provider — VACATE-ONLY (interface seam, no adapter)
    seam: web
    package: "npm:@juicesharp/rpiv-web-tools"   # the foreign Pi package to add to `packages`
    adapter: null            # VACATE-ONLY: interface seam, no artifact; perk registers no web tools.
                             # Tools: `web_search`/`web_fetch` (needs an API key; default provider Brave;
                             # registers a `/web-tools` command — no perk collision).
    default: false
    # No `package_filter`: verified manifest is `{"extensions": ["./index.ts"]}`, so omitting the
    # filter loads exactly that one extension (the juicesharp single-extension convention).
