Skip to content

fix(connectors): reconcile mail connector key — probe gmail → canonical email (#172) - #189

Merged
jordanrburger merged 1 commit into
mainfrom
claude/sleepy-vaughan-f74339
Jul 17, 2026
Merged

fix(connectors): reconcile mail connector key — probe gmail → canonical email (#172)#189
jordanrburger merged 1 commit into
mainfrom
claude/sleepy-vaughan-f74339

Conversation

@jordanrburger

Copy link
Copy Markdown
Collaborator

Standalone fix for the connector key-namespace bug identified in the connector-catalog spec §7 (#152) and confirmed in the 2026-06-30 design review — split out as recommended there, independent of the catalog work. Fixes #172.

The bug

The mail connector was named by two different keys across the namespaces that must agree:

  • probe/config key (templates/connector-probes.yaml, scout-config.yaml connectors.enabled): gmail
  • phase gate (phases/connectors/email.md): requires: email

select_sections keeps a section only when its requires: key is in enabled_connectors, so with Gmail enabled the assembler silently dropped every email section from assembled SKILL.md — no error, just missing behavior. Tests never caught it because the fixture (dummy-mixed.md) used requires: gmail, matching the probe key instead of the real phase key.

The fix (spec §7's recommended resolution)

Standardize on the provider-neutral email, keep gmail as a legacy alias:

  • templates/connector-probes.yaml — probe key renamed gmailemail (same Gmail probe tool). A future Outlook/IMAP probe maps to the same capability key: one phase, many providers.
  • connector_probes.py — new CONNECTOR_KEY_ALIASES = {"gmail": "email"} + normalize_connector_keys().
  • bootstrap.pyBootstrapConfig.__post_init__ normalizes enabled_connectors. Every entrypoint (install / upgrade / migrate-legacy / phases backport) constructs BootstrapConfig, so a pre-rename vault's gmail keeps working immediately, and the next /scout-update idempotently rewrites connectors.enabled to the canonical key — no manual migration.
  • Fixturedummy-mixed.md now uses the canonical email key.

Regression guard

New engine/tests/unit/test_connector_key_invariant.py:

  • every requires: key in shipped phases/ resolves to a shipped probe-registry key (a key with no probe entry is silently un-enableable — this is the CI check spec §7 calls for);
  • phases must gate on canonical keys, never alias keys;
  • aliases must map onto real probe keys without colliding with them;
  • end-to-end bug: email phase never assembles — requires: email but the connector is enabled/detected as gmail #172 reproduction: a legacy {"gmail"} config selects zero sections of the real email phase raw, and all sections once normalized;
  • BootstrapConfig normalization itself.

Also fixed in passing

The new invariant test immediately flagged a second instance of the same class: phases/connectors/fathom.md gates on requires: fathom, but no probe entry existed, so nothing could ever write fathom into connectors.enabled via setup. Added the missing probe (mcp__fathom__list_meetings, the same tool the phase itself uses). Happy to split this into its own PR if preferred.

Verification

  • ruff format / ruff check clean
  • full engine suite: 896 passed, 1 skipped (the vault-parity test that only runs with SCOUT_DATA_DIR set)

🤖 Generated with Claude Code

…al email (#172)

The probe/config key for the mail connector was `gmail`, but the email
phase gates on `requires: email`, so select_sections silently dropped
every email section from assembled SKILL.md whenever Gmail was enabled.
The mismatch was masked in tests because dummy-mixed.md used
`requires: gmail` instead of the real phase key.

Per the connector-catalog spec §7 resolution (PR #152, confirmed in the
2026-06-30 design review): standardize on the provider-neutral `email`.

- Rename the probe registry key `gmail` → `email` (same Gmail probe tool).
- Add CONNECTOR_KEY_ALIASES + normalize_connector_keys(); BootstrapConfig
  normalizes enabled_connectors at construction, so every entrypoint
  (install / upgrade / migrate-legacy / backport) accepts the legacy key
  and /scout-update idempotently persists the canonical one.
- Fix the masking fixture to use the canonical `email` key.
- Add test_connector_key_invariant.py: every phase `requires:` must
  resolve to a shipped probe key, phases must not use alias keys, and the
  legacy-config end-to-end path selects the real email phase.
- Add the missing `fathom` probe entry — same silently-un-enableable
  class: phases/connectors/fathom.md gates on `requires: fathom` but no
  probe could ever write that key to connectors.enabled.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jordanrburger
jordanrburger merged commit c592291 into main Jul 17, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: email phase never assembles — requires: email but the connector is enabled/detected as gmail

1 participant