Skip to content

Feature: expand one custom harness definition into per-profile catalog entries #7781

Description

@majieddd

Summary

A custom harness definition (<app-data>/custom_harnesses/<id>.json) describes exactly one runtime entry. When a runtime has a profile-per-directory layout (one command, several isolated homes), the only way to offer each home as a pickable runtime today is one hand-written definition file per profile, kept in sync by hand: add or rename a profile and the runtime dropdown is stale until someone regenerates those files.

This proposes letting one definition declare a variants block, so Buzz derives one catalog entry per detected profile directory from it.

Proposed shape

{
  "id": "hermes-profiles",
  "label": "Hermes Agent",
  "command": "hermes-acp",
  "modelSelection": "harness",
  "variants": {
    "dir": "~/.hermes/profiles",
    "marker": "profile.yaml",
    "idTemplate": "{id}-{slug}",
    "labelTemplate": "{label} [{meta}] ({name})",
    "labelFrom": { "file": "profile.yaml", "key": "ui_meta.hermes-bots.title" },
    "env": { "HERMES_HOME": "{dir}" }
  }
}
  • dir + marker: which directories count, by marker file, so a directory that is not a profile of that runtime is skipped.
  • idTemplate / labelTemplate: {id}, {label}, {name} (directory name), {slug} (id-safe directory name), and {meta} from labelFrom.
  • labelFrom: read one dotted key out of a file in the profile directory (a persona title, for example), so the entry can read Hermes Agent [Generalist] (generalist) rather than just the folder name.
  • args / env placeholders: {name}, {slug}, {dir} (the profile directory), {root} (the scanned directory), so the spawned process is pointed at its own profile.
  • Expansion is capped, and a definition with no variants returns exactly itself as one entry, so nothing changes for existing definitions.

Two things go with it:

  1. Generated entries are read-only. They carry generated + generated_from, render without an edit affordance, and name the definition file the user should edit instead. Editing a derived entry would otherwise be silently overwritten by the next scan.
  2. modelSelection: "harness". Optional, on any definition. When a runtime owns model choice, the agent config renderer omits the model field with the named reason ownedByHarnessSelection instead of showing a picker whose value the harness ignores.

The primitive is deliberately not tied to any one runtime. It covers a profile root, a per-project agent config dir, or any future profile-per-directory layout, and needs no runtime-specific code in the desktop shell.

Related existing reports

Searched open and closed PRs and issues for "harness profile", "custom harness variants", "harness definition profiles", "definitionVariants", "generated_from harness", "variants block harness": no existing work on this primitive.

Closest adjacent reports:

Status

Implementation is written, tested, and on a branch, with 12 Rust unit tests driven through the existing load_custom_harnesses / save_custom_harness_to_dir seam, a browser spec that asserts the read-only row and the omitted model picker, and two proof frames. PR to follow and cross-link here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions