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.
| Location | Role today |
|---|---|
solutions/ontological/experiences/suspenders/app/composables/useSkillClient.ts | SkillClient interface: roster, detail, managed, adopt, publish, destinations; no body write |
solutions/ontological/experiences/suspenders/app/components/SkillDetailPanel.vue | Read-only body after T-UQCN-suspenders-skill-body-viewer |
solutions/ontological/experiences/suspenders/app/pages/apps/suspenders/index.vue | Owns the detail actions |
solutions/ontological/experiences/suspenders/app/types/skill.ts | ManagedDetail with body: string |
solutions/ontological/experiences/suspenders/tests/roster.test.ts | Unit tests |
solutions/ontological/desktop/src-nuxt/app/plugins/suspenders.client.ts | SDF’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.rs | Skill model |
Proposed
Section titled “Proposed”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.
Approach
Section titled “Approach”- Land the backend op task first; record its id in
depends_onand cleardefinition_gap. useSkillClient.tsand the suspenders skill types (skill.ts): addupdateBodyandetag; extend the SDF adapter insuspenders.client.tsand the product’s adapter.SkillDetailPanel.vue: Edit toggle andMdSurfaceformanaged.body; emitsaveBody.index.vue: handle the emit, call the client, refresh, surface conflicts.- Tests: a fake
SkillClientintests/covering save and conflict. - Verify:
bun test testsin the experience;moon run sdf:check; edit a managed draft in SDF, save, reload; byte-diff an unedited save;moon run :check :test --affected.
| Area | Note |
|---|---|
solutions/ontological/experiences/suspenders/app/composables/useSkillClient.ts | updateBody on the port |
solutions/ontological/experiences/suspenders/app/types/skill.ts | etag on ManagedDetail |
solutions/ontological/experiences/suspenders/app/components/SkillDetailPanel.vue | Edit toggle; MdSurface; saveBody emit |
solutions/ontological/experiences/suspenders/app/pages/apps/suspenders/index.vue | Save handler and conflict notice |
solutions/ontological/experiences/suspenders/tests/body-write.test.ts | Save and conflict tests over a fake client |
solutions/ontological/desktop/src-nuxt/app/plugins/suspenders.client.ts | Adapter implements updateBody |
Acceptance criteria
Section titled “Acceptance criteria”- 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
etagsurfaces the conflict notice; reload and overwrite both work. - AC-5:
bun test testsin the experience passes with the new save and conflict tests;moon run sdf:checkpasses.
Out of scope
Section titled “Out of scope”- The
suspenders-corewrite and its service routes; that is the missing prerequisite task. - Editing frontmatter or skill resources.
- Validation hints for skill bodies.
Dependencies
Section titled “Dependencies”- T-UQCN-suspenders-skill-body-viewer: the viewer and layer wiring.
- The backend draft-body write: no task or backlog item exists for it yet, so
depends_oncannot name it. Create it and link it before this task is picked up. - D-A27T-suspenders-skill-experience-module: the experience reaches its backend only through
the injected
SkillClientport. D-7VMX-markdown-ecosystem-strategyd.4:swapwrite with advisory validation.- D-4QGN-markdown-dialect-and-compatibility-profile: body-only editing.
Discovery context
Section titled “Discovery context”Member of milestone M-931L; wave 5 of D-K3EM-markdown-editor-chrome-and-plugin-environment.
Depends on
Section titled “Depends on”T-UQCN-suspenders-skill-body-viewer