Skip to content

Externalize target architectures so a new one can be added via configuration #20

Description

@adilei

Summary

Externalize the definition of target architectures into a single declarative registry/config so adding a new target (e.g. the proposed "generic agent" in #19, or Copilot Studio) is a one-place change — no scattered edits across an enum, a UI array, a catalogue switch, and an automation lookup.

Problem — a new target touches 4+ places today

Adding or enabling an architecture currently requires hand-editing several disconnected spots:

  • common/skill.ts — extend the SkillArchitecture zod enum and add an entry to the ARCHITECTURES selector array.
  • electron/skillbuilder/<name>-catalog.ts — author a new capability-catalogue module (+ a *_CATALOGUE_VERSION).
  • electron/skillbuilder/scout-catalog.ts — add a case to the catalogueFor(architecture) switch.
  • electron/automationbuilder/scout-automation-catalog.ts — add a branch to automationCatalogueFor(architecture).

These are easy to miss and keep in sync (e.g. an architecture can be in the enum but fall through catalogueFor to null, which the builder surfaces as "That target architecture isn't available yet.").

Proposed approach

Introduce one architecture registry — a single source of truth that carries everything about a target:

interface ArchitectureDefinition {
  id: string;              // "scout" | "cowork" | ...
  label: string;
  enabled: boolean;
  note: string;            // shown under the selector option
  catalogueVersion: string;
  skillCatalogue: () => string;        // capability catalogue text (main-only)
  automationCatalogue?: () => string;  // optional; automations are Scout-only today
}

Then derive the existing surfaces from it instead of maintaining them by hand:

  • SkillArchitecture (the union type / enum) is derived from the registry's ids.
  • ARCHITECTURES (UI metadata) is a projection of the registry.
  • catalogueFor / automationCatalogueFor become simple registry lookups (no per-target switch).

Adding a target = add one registry entry (+ author its catalogue content). #19's "generic agent" would just be one more entry with a neutral catalogue.

Constraints to preserve

  • Ship catalogues with the app, no runtime fetch. Catalogues are static, versioned snapshots embedded in the system prompt (end users don't have the Scout repo checked out) — keep them bundled and keep the "built-ins only" authoring rule.
  • Keep the main/renderer split. UI metadata (id/label/enabled/note) is safe for the renderer and lives in common/; the catalogue payload is main-process only. The registry should expose the public metadata without leaking catalogue text to the renderer.
  • Don't lose type safety. Prefer a single as const source array so the SkillArchitecture union is still inferred at compile time; otherwise widen to string + runtime validation (zod) at the boundaries.

Acceptance criteria

  • Adding/enabling a target architecture requires editing one registry location (plus authoring its catalogue content) — no manual edits to catalogueFor, automationCatalogueFor, the enum, or ARCHITECTURES.
  • Existing scout / cowork / copilot-studio behavior and catalogues are unchanged.
  • The renderer still receives only UI metadata, never catalogue text.
  • It's impossible to have an "enabled" target with no catalogue wired (registry makes the pairing explicit).

Open questions

  • Config format: a TS module registry (keeps type inference, loaders, and bundling) vs. external JSON/YAML data (more literally "configuration", but needs a load/validate + bundling strategy and loses inline TS).
  • Should catalogue content stay in separate files referenced by the registry entry (they're large), or move inline?
  • Is per-target automation support worth modeling now (optional field) or deferred until a second automation-capable target exists?

Related: #19 (add a "generic agent" target) — that target becomes a trivial registry entry once this lands.

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions