Skip to content

T-W8BH-kind-conversion-action

State: planning/proposed · Impact: high · Complexity: medium

ap-kind is a plain select in the fields form, so changing what a note is writes one frontmatter key and nothing else: the note stays in the folder its old kind put it in, keeps fields its new kind does not carry, and gets no container scaffolded for it. Conversion becomes a discrete action with a preview and a consent step, on the same shape rename and move already use. That also removes the phantom-container symptom, where a note claiming a plugin nothing declares mints an empty group in the tree.

LocationRole today
solutions/determined/experiences/agent-pants/app/components/SkillFieldsForm.vueThe ap-kind DSelect over kindItems/KIND_UNSET writes the key straight into the model — no move, no preview, no consent
solutions/determined/experiences/agent-pants/app/utils/fieldSpec.ts#fieldAppliesToKindSays which fields a kind carries; the source for the kept/dropped list
solutions/determined/crates/determined-agent-skills/src/lib.rs#move_destinationComputes where a move puts a note
solutions/determined/crates/determined-agent-skills/src/lib.rs#rename_destinationThe same computation for a rename
solutions/determined/crates/determined-agent-skills/src/lib.rs#new_note_dirMaps a placement onto its kind directory when a note is created
solutions/determined/crates/determined-agent-skills/src/lib.rs#group_componentsGroups the tree; or_insert_with mints a group with note: None for a plugin name no note declares — the phantom container
solutions/determined/crates/determined-agent-skills/src/lib.rs#get_rename_component_previewPreview half of the plan/apply pair, returning refusal, peers and expect etags
solutions/determined/crates/determined-agent-skills/src/lib.rs#rename_componentApply half: move the note, then rewrite frontmatter
solutions/determined/experiences/agent-pants/app/components/ApRenameDialog.vueThe consent dialog shape: live preview, inline refusal, “don’t show this again”, classifyOpRefusal handoff
solutions/determined/experiences/agent-pants/app/components/ApMoveDialog.vueThe same shape for a move, with a picker instead of a text field
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/notes/[...path].vueThe overflow menu — Rename…, Move…, Delete… — plus the undo toasts each apply raises
solutions/determined/experiences/agent-pants/app/composables/useAgentSkillComponentOps.tsThe transport wrappers for each plan/apply pair
solutions/determined/crates/determined-platform/src/api/v1/agent_skills.rsThe op seam; ontogen generates the IPC and HTTP transports from it
solutions/determined/experiences/agent-pants/app/plugins/register.tscontributes.commands — three commands today

“Convert kind…” is an entry in the note overflow menu and a registered command. It opens a dialog that previews, before anything is written:

  • the destination path, from the kind directory the new kind belongs in;
  • the fields kept and the fields dropped, derived from fieldAppliesToKind;
  • the container scaffold that would be created, when converting to plugin or marketplace;
  • collisions and any other refusal, rendered inline with the submit button disabled.

Applying calls one backend op, convert_kind, which moves the note, rewrites ap-kind and the fields the new kind drops, and rewrites the wikilinks that pointed at the old path — as one unit, with the same etag expect guard and preview-then-apply consent as rename. The ap-kind DSelect is gone from SkillFieldsForm.vue; the form shows the resolved kind as read-only text with a link to the action.

  1. determined-agent-skills: add convert_kind_destination, the kind-directory sibling of move_destination, and cover it with unit tests over each kind pair.
  2. Add get_convert_kind_preview returning a plan — destination, kept fields, dropped fields, scaffold, peers, expect, refusal — modelled on get_rename_component_preview. Writes nothing.
  3. Add convert_kind: move, frontmatter rewrite, link rewrite, in that order, through the same VaultNotesPort calls rename uses. Decision inside this step: converting to a container kind scaffolds its member folders; converting away from one refuses while the container still holds members, rather than orphaning them.
  4. Wire types in determined-core: AgentSkillConvertKindPlan, AgentSkillConvertKindRequest, AgentSkillConvertKindResult.
  5. Expose both ops in determined-platform/src/api/v1/agent_skills.rs and regenerate the transports.
  6. ApConvertKindDialog.vue, built on ApRenameDialog.vue’s structure: kind picker, live preview, inline refusal, “don’t show this again” hiding only the review, classifyOpRefusal handoff at apply time.
  7. Add the transport wrappers to useAgentSkillComponentOps.ts, the menu item and undo toast to notes/[...path].vue, and an agent-pants.convert-kind command to register.ts.
  8. Remove the ap-kind DSelect, kindItems and KIND_UNSET from SkillFieldsForm.vue; render the resolved kind read-only.
  9. Fix group_components so a plugin name that no plugin note declares does not mint a group. The members still show — under the marketplace’s shared group — and the tree stops advertising a container that does not exist.
AreaNote
solutions/determined/crates/determined-agent-skills/src/lib.rsconvert_kind_destination, get_convert_kind_preview, convert_kind; group_components stops minting phantom groups
solutions/determined/crates/determined-core/src/wire/mod.rsPlan, request and result types for the new op
solutions/determined/crates/determined-platform/src/api/v1/agent_skills.rsThe two op functions; ontogen regenerates the IPC and HTTP transports
solutions/determined/experiences/agent-pants/app/components/ApConvertKindDialog.vueThe preview-then-apply consent dialog
solutions/determined/experiences/agent-pants/app/components/SkillFieldsForm.vueDrop the ap-kind DSelect, kindItems and KIND_UNSET; show the resolved kind read-only
solutions/determined/experiences/agent-pants/app/composables/useAgentSkillComponentOps.tsTransport wrappers for preview and apply
solutions/determined/experiences/agent-pants/app/pages/apps/agent-pants/notes/[...path].vue”Convert kind…” in the overflow menu, dialog mount, undo toast
solutions/determined/experiences/agent-pants/app/plugins/register.tsagent-pants.convert-kind command
solutions/determined/experiences/agent-pants/docs/authoring.mdDocument conversion as an action, not a field
solutions/determined/products/agent-pants/tests/e2e/walkthrough-dialogs.e2e.tsWalk the convert dialog beside rename, move and delete
  • AC-1: SkillFieldsForm.vue carries no ap-kind DSelect, and neither kindItems nor KIND_UNSET remains in the file.
  • AC-2: The note overflow menu offers “Convert kind…”, and agent-pants.convert-kind is a registered command.
  • AC-3: The dialog shows destination path, kept fields, dropped fields and — for plugin and marketplace — the scaffold, before anything is written.
  • AC-4: Converting a skill in skills/ to command leaves the note at the commands/ destination with ap-kind: command, and the wikilinks that pointed at the old path resolve.
  • AC-5: A conversion whose destination already exists refuses inline, with the submit button disabled and nothing written.
  • AC-6: Converting a plugin that still holds members refuses, naming the members.
  • AC-7: A note declaring ap-plugin for a plugin no note declares no longer produces an empty group in the component tree, covered by a group_components unit test.
  • AC-8: The dialogs e2e project passes with the convert flow added.
  • none

Member of milestone M-BMFD, from the user’s planning request of 2026-09-07 on the data model. The assessment solutions/agent-pants/docs/vault/design/workflow-and-ux-assessment.md records the kind select as a field that silently disagrees with the folder it sits in, and the phantom container is the tree symptom of the same gap. ApRenameDialog.vue and ApMoveDialog.vue set the consent shape this action copies.


← Back to Tasks