Skip to content

T-PFC2-suspenders-draft-body-editor

State: planning/needs-definition · Impact: medium · Complexity: medium

Suspenders shows a managed skill’s draft body but cannot edit it: SkillClient has no body verb and suspenders-core has no body write. This task adds the updateBody port and an edit mode on MdSurface for managed drafts, saving as a swap write that leaves frontmatter untouched.

LocationRole today
solutions/ontological/experiences/suspenders/app/composables/useSkillClient.tsSkillClient interface: roster, detail, managed, adopt, publish, destinations; no body write
solutions/ontological/experiences/suspenders/app/components/SkillDetailPanel.vueRead-only body after T-UQCN-suspenders-skill-body-viewer
solutions/ontological/experiences/suspenders/app/pages/apps/suspenders/index.vueOwns the detail actions
solutions/ontological/experiences/suspenders/app/types/skill.tsManagedDetail with body: string
solutions/ontological/experiences/suspenders/tests/roster.test.tsUnit tests
solutions/ontological/desktop/src-nuxt/app/plugins/suspenders.client.tsSDF’s provideSkillClient adapter over the Rust service
solutions/ontological/crates/suspenders-core/src/store/Managed skill store; no body write
solutions/ontological/crates/suspenders-core/src/skill.rsSkill model

A backend op (its own task, not yet created) adds a draft-body write to suspenders-core (swap on the body with a content-hash precondition) and exposes it through the SDF Rust service and the standalone product’s service. SkillClient gains updateBody(skillId, body, etag): Promise<ManagedDetail>; ManagedDetail carries etag. The detail panel shows an Edit toggle for managed drafts that emits saveBody; the page calls the client and refreshes. The toggle mounts:

<MdSurface v-model="body" mode="live" :modes="['live','source']" toolbar="fixed" frontmatter-panel="hidden" @save>

Unmanaged on-disk skills stay read-only. A hash mismatch shows a conflict notice with reload and overwrite.

  1. Land the backend op task first; record its id in depends_on and clear definition_gap.
  2. useSkillClient.ts and the suspenders skill types (skill.ts): add updateBody and etag; extend the SDF adapter in suspenders.client.ts and the product’s adapter.
  3. SkillDetailPanel.vue: Edit toggle and MdSurface for managed.body; emit saveBody. index.vue: handle the emit, call the client, refresh, surface conflicts.
  4. Tests: a fake SkillClient in tests/ covering save and conflict.
  5. Verify: bun test tests in the experience; moon run sdf:check; edit a managed draft in SDF, save, reload; byte-diff an unedited save; moon run :check :test --affected.
AreaNote
solutions/ontological/experiences/suspenders/app/composables/useSkillClient.tsupdateBody on the port
solutions/ontological/experiences/suspenders/app/types/skill.tsetag on ManagedDetail
solutions/ontological/experiences/suspenders/app/components/SkillDetailPanel.vueEdit toggle; MdSurface; saveBody emit
solutions/ontological/experiences/suspenders/app/pages/apps/suspenders/index.vueSave handler and conflict notice
solutions/ontological/experiences/suspenders/tests/body-write.test.tsSave and conflict tests over a fake client
solutions/ontological/desktop/src-nuxt/app/plugins/suspenders.client.tsAdapter implements updateBody
  • AC-1: Editing a managed draft body in SDF, saving and reloading shows the new body, and the skill file’s frontmatter bytes are unchanged.
  • AC-2: Saving an unedited body leaves the file’s sha unchanged.
  • AC-3: An unmanaged skill shows no Edit toggle.
  • AC-4: A stale etag surfaces the conflict notice; reload and overwrite both work.
  • AC-5: bun test tests in the experience passes with the new save and conflict tests; moon run sdf:check passes.
  • The suspenders-core write and its service routes; that is the missing prerequisite task.
  • Editing frontmatter or skill resources.
  • Validation hints for skill bodies.

Member of milestone M-931L; wave 5 of D-K3EM-markdown-editor-chrome-and-plugin-environment.

T-UQCN-suspenders-skill-body-viewer


← Back to Tasks