Skip to content

[per-component-executor] - executor parameter kind #1434

Description

@JoshuaRowePhantom

executor parameter kind

Part of design: #1432 — per-component-executor-binding
Design document: https://github.com/JoshuaRowePhantom/Phantom.Workspaces/blob/design/docs/design/per-component-executor-binding.md

Scope

Add an executor parameter kind to the manifest parameter model and its documentation, plus value recording/substitution. The parameter is how a user, at launch, picks which executor a parameter-strategy executor resource resolves to. It offers a choice among two selectable option kinds, and records a disambiguated selection in a dedicated typed parameter-selections map (string → JsonElement) — NOT as a JSON-encoded string in the string→string parameter-values map, which stays reserved for ${param} text templating. Make parameter kind read from the manifest parameter kind field rather than being inferred purely by name (see Contradictions). (NEW parameter kind.)

Files

the AgentManifest parameter model / substitutor (Phantom.Workspaces.Llm.Core/AgentDefinitionParameterSubstitutor.cs and the parameter property model); Phantom.Workspaces.Data.Core/JsonEntities/documentation/agent-options-parameters.md.

Detailed design

Requirement 5 — executor launch parameter. A new manifest parameter kind:"executor" lets the user pick, at launch, which executor a parameter-strategy executor resource resolves to. The parameter offers a choice among two selectable option kinds:

  • a trust-profile entity ("choose by trust policy") — resolves to that trust profile's DefaultExecutionTarget connection-descriptor;
  • a user-computer-profile entity — choosing one synthesizes an implicit trust profile (an in-memory TrustProfileDefinition whose DefaultExecutionTarget = {"type":"user-computer-profile","entity-id":<chosen uuid>} and whose HostingWorkspacesClientInstances = [<chosen uuid>]); no trust-profile entity needs to be pre-authored or persisted.

Both paths converge on the same thing: a trust profile (explicit or implicit) whose DefaultExecutionTarget is the connection-descriptor used as the executor binding. This unifies executor selection under trust profiles, which is exactly where DefaultExecutionTarget already lives (Phantom.Workspaces.Llm.Core/Trust/TrustProfile.cs:105,143; TrustProfileDefinition.DefaultExecutionTarget; ExecutionTargetResolver.Resolve(TrustProfile?) returns DefaultExecutionTarget or {"type":"local"}).

Disambiguated recorded selection — a typed entry in parameter-selections (M7)

The chosen selection is recorded in the session's dedicated typed parameter-selections map (string parameter name → JsonElement selection), identifying BOTH the kind and the id as a small JSON object — {"trust-profile":"<name-or-id>"} or {"user-computer-profile":"<entity-id>"} — kept lossless through PhantomAgentSchema round-trip.

Decoupling contract (M7 — separate text templating from structured selection). parameter-values is IReadOnlyDictionary<string,string> — a string→string map — in AgentSessionEntityFactory (Phantom.Workspaces.Data.Core/AgentSessionEntityFactory.cs:46, serialized at :77-85) and in the substitutor (AgentDefinitionParameterSubstitutor.Substitute(AgentManifest, IReadOnlyDictionary<string,string>?), AgentDefinitionParameterSubstitutor.cs:15-17,133-140). That map exists for ${param} text templating; an executor selection is not a text substitution, so it does NOT go there. Instead the executor parameter's disambiguated selection is recorded in a dedicated typed parameter-selections map (string → JsonElement) — a sibling root key of parameter-values and executor-bindings on the persisted agent-session entity (AgentSessionEntityFactory.CreateEntityData, Data.Core/AgentSessionEntityFactory.cs:39-93). The resolver (#1436) reads the JsonElement selection directly — no JSON-string parsing. Do NOT widen parameter-values to string→object and do NOT store a JSON-encoded string in it; parameter-values stays string→string for templating, avoiding a breaking change across its ~20 call sites. Text/directory parameters continue to use parameter-values exactly as today.

Modified files (applicable):

  • Phantom.Workspaces.Llm.Core/JsonSchemas/agent-manifest.json — document an executor parameter kind.
  • Phantom.Workspaces.Llm.Core/AgentDefinitionParameterSubstitutor.cs + the parameter property model — an executor parameter is a structured selection recorded in the typed parameter-selections map, NOT a ${}-substitutable string; parameter-values text substitution is unchanged for text/directory params.
  • Phantom.Workspaces.Data.Core/JsonEntities/documentation/agent-options-parameters.md — document parameters + executor kind + executor resources + executor-bindings round-trip, INCLUDING that the executor selection lives in the typed parameter-selections map (string→JsonElement), a sibling of the string→string parameter-values.

Contradictions with the initial brief (verified against the codebase):

  1. agent-manifest.json parameters is untyped. The schema declares parameters as type:object, additionalProperties:true (Phantom.Workspaces.Llm.Core/JsonSchemas/agent-manifest.json:36-40) — it is not a typed properties[] array. The {name,kind,description,required,default} shape lives in the AgentManifest model and in agent-options-parameters.md, not in the JSON schema. Adding the executor kind is primarily a model + documentation change (Commit 2).
  2. Launchpad infers parameter kind by NAME, not a kind field. AgentManifestLaunchpadViewModel.DetermineParameterKind returns Directory only for the exact name working-directory (AgentManifestLaunchpadViewModel.cs:291-296); AgentManifestParameterKind has only Text and Directory (AgentManifestParameterKind.cs). Commit 2/8 must switch the picker to honour the manifest parameter kind field and add an Executor kind (not UserComputerProfile).

Data flow (applicable): The Launchpad records the disambiguated executor selection as a typed JsonElement entry in parameter-selections. ExecutorResourceResolver.Resolve later reads that selection (M7) and routes the parameter strategy through the selected/implicit trust profile, returning that profile's DefaultExecutionTarget descriptor. Text/directory parameters still flow through the string→string parameter-values.

Tests

AgentManifestExecutorResourceTests (Phantom.Workspaces.Llm.Core.Tests)

  • Load_ExecutorParameter_Recognised
  • a substitutor test for the new kind, covering both disambiguated value shapes ({"trust-profile":...} and {"user-computer-profile":...}).
  • ExecutorParameterSelection_RecordedInParameterSelections(M7) the recorded selection is a typed JsonElement entry in the parameter-selections map (both {"trust-profile":…} and {"user-computer-profile":…} shapes), NOT a JSON-encoded string in parameter-values, and survives PhantomAgentSchema round-trip; the string→string parameter-values type and text-substitution behaviour are unchanged.

Testing strategy — Schema and model round-trip: A manifest carrying an executor parameter loads through PhantomAgentSchema and re-serialises losslessly (including the disambiguated selection recorded in the typed parameter-selections map), remaining compliant with the AgentSchema source-scan guard test. → AgentManifestExecutorResourceTests.

Considered / Background

An earlier framing made this a user-computer-profile-only parameter kind (kind:"user-computer-profile") that let the user pick a remote machine and recorded a bare profile entity-id. This was generalised to the executor parameter above so an executor can also be chosen by trust policy (a trust-profile entity) — with a user-computer-profile selection now handled as an implicit trust profile rather than a special case. The disambiguated recorded value replaces the bare entity-id so the two option kinds never collide.

Storing the disambiguated selection inside parameter-values — whether as a JSON-encoded string or by widening the map to string→object — was considered but rejected (M7): it conflates structured selection with ${param} text templating, and widening the string→string dictionary (and the session-entity writer / substitutor) to string→object is a breaking type change rippling through ~20 call sites (incl. Mongo/Web persistence DTOs). Decoupling into a dedicated typed parameter-selections map keeps parameter-values string-only with no blast radius. The general typed-value model is filed separately as #1444 (non-blocking); the executor feature does not depend on it, and #1444 would later let parameter-selections fold into a unified typed parameter-values.

Dependencies

None.

Consumed by: #1436ExecutorResourceResolver reads this typed executor selection from parameter-selections (M7) for the parameter strategy.
Consumed by: #1437 — the session writer persists this selection in the typed parameter-selections root key (M7), a sibling of parameter-values and executor-bindings.

Activity

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

Metadata

Metadata

Labels

bugSomething isn't workingverified-locallyImplementation has been verified locally

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions