Skip to content

T-WUVP-sdf-entity-body-swap-write

State: closed/done · Impact: medium · Complexity: large

SDF shows entity and task bodies but cannot change them: the dashboard API is read-only. This task adds an edit mode to the entity detail panel and task page on MdSurface, saving through a swap body write behind @sdlc/dashboard-client, with conflict detection and advisory validation that never blocks a save.

LocationRole today
solutions/ontological/lib/services/dashboard/server.tsHono routes: GET /api/entities/:type, GET /api/entities/:type/:id, POST /api/refresh; no write
packages/ts/dashboard-client/src/index.tsGenerated-style client: GET wrappers for entities
packages/ts/dashboard-client/src/types.tsEntity detail with body: string
solutions/ontological/desktop/src-nuxt/app/components/entities/MarkdownBody.vueRead-only viewer after T-I4V6-sdf-entity-body-viewer
solutions/ontological/desktop/src-nuxt/app/components/entities/EntityDetailPanel.vueMounts the viewer
solutions/ontological/desktop/src-nuxt/app/pages/model/tasks/[id].vueMounts the viewer
solutions/ontological/desktop/src-nuxt/nuxt.config.tsDev proxy: /api to the dashboard server on 6174

A backend op (its own task, not yet created) exposes PUT /api/entities/:type/:id/body taking the new body and an If-Match content hash from the last read; it composes body and untouched frontmatter through markdown-util and answers 412 on hash mismatch. @sdlc/dashboard-client gains updateEntityBody(type, id, body, etag) and the detail read returns the hash. In SDF, EntityDetailPanel.vue and tasks/[id].vue get an Edit toggle that swaps MarkdownBody for:

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

Save calls the client, refreshes the entity, and on 412 shows a conflict notice with reload and overwrite. Validation hints (T-Q38X-editor-contract-validation-hint) are advisory.

  1. Land the backend op task first; record its id in depends_on and clear definition_gap.
  2. dashboard-client: add updateEntityBody and the etag field; unit tests against a mocked fetch.
  3. SDF: new EntityBodyEditor.vue wrapping MdSurface with save, dirty and conflict state in a useEntityBodyWrite.ts composable; mount it behind an Edit toggle at both call sites.
  4. Verify: moon run sdf:check sdf:test; against a running sdlc dashboard start, edit a task body, save, reload and see the change; edit the file on disk between read and save and see the conflict notice; byte-diff an unedited save; moon run :check :test --affected.
LocationKindChange
packages/ts/dashboard-client/src/index.tsmodifyupdateEntityBody
packages/ts/dashboard-client/src/types.tsmodifyetag on the detail type
solutions/ontological/desktop/src-nuxt/app/components/entities/EntityBodyEditor.vuenewMdSurface wrapper with save and conflict UI
solutions/ontological/desktop/src-nuxt/app/composables/useEntityBodyWrite.tsnewWrite, dirty and conflict state
solutions/ontological/desktop/src-nuxt/app/components/entities/EntityDetailPanel.vuemodifyEdit toggle
solutions/ontological/desktop/src-nuxt/app/pages/model/tasks/[id].vuemodifyEdit toggle
  • AC-1: Editing a task body in SDF, saving and reloading shows the new body, and the file’s frontmatter bytes are unchanged (git diff touches body lines only).
  • AC-2: Saving an unedited body leaves the file’s sha unchanged.
  • AC-3: Changing the file on disk between read and save surfaces the conflict notice; reload shows the disk version; overwrite writes the editor version.
  • AC-4: A body with a validation finding still saves.
  • AC-5: dashboard-client tests cover a 200 and a 412 response of updateEntityBody.
  • AC-6: moon run sdf:check sdf:test pass.
  • The backend op itself and its sdlc CLI verb; that is the missing prerequisite task.
  • Editing frontmatter from the dashboard.
  • The validation hint plugin (T-Q38X-editor-contract-validation-hint).

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

T-I4V6-sdf-entity-body-viewer


← Back to Tasks