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.
| Location | Role today |
|---|---|
solutions/ontological/lib/services/dashboard/server.ts | Hono routes: GET /api/entities/:type, GET /api/entities/:type/:id, POST /api/refresh; no write |
packages/ts/dashboard-client/src/index.ts | Generated-style client: GET wrappers for entities |
packages/ts/dashboard-client/src/types.ts | Entity detail with body: string |
solutions/ontological/desktop/src-nuxt/app/components/entities/MarkdownBody.vue | Read-only viewer after T-I4V6-sdf-entity-body-viewer |
solutions/ontological/desktop/src-nuxt/app/components/entities/EntityDetailPanel.vue | Mounts the viewer |
solutions/ontological/desktop/src-nuxt/app/pages/model/tasks/[id].vue | Mounts the viewer |
solutions/ontological/desktop/src-nuxt/nuxt.config.ts | Dev proxy: /api to the dashboard server on 6174 |
Proposed
Section titled “Proposed”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.
Approach
Section titled “Approach”- Land the backend op task first; record its id in
depends_onand cleardefinition_gap. dashboard-client: addupdateEntityBodyand theetagfield; unit tests against a mocked fetch.- SDF: new
EntityBodyEditor.vuewrappingMdSurfacewith save, dirty and conflict state in auseEntityBodyWrite.tscomposable; mount it behind an Edit toggle at both call sites. - Verify:
moon run sdf:check sdf:test; against a runningsdlc 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.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
packages/ts/dashboard-client/src/index.ts | modify | updateEntityBody |
packages/ts/dashboard-client/src/types.ts | modify | etag on the detail type |
solutions/ontological/desktop/src-nuxt/app/components/entities/EntityBodyEditor.vue | new | MdSurface wrapper with save and conflict UI |
solutions/ontological/desktop/src-nuxt/app/composables/useEntityBodyWrite.ts | new | Write, dirty and conflict state |
solutions/ontological/desktop/src-nuxt/app/components/entities/EntityDetailPanel.vue | modify | Edit toggle |
solutions/ontological/desktop/src-nuxt/app/pages/model/tasks/[id].vue | modify | Edit toggle |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Editing a task body in SDF, saving and reloading shows the new body, and the file’s
frontmatter bytes are unchanged (
git difftouches 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-clienttests cover a200and a412response ofupdateEntityBody. - AC-6:
moon run sdf:check sdf:testpass.
Out of scope
Section titled “Out of scope”- The backend op itself and its
sdlcCLI verb; that is the missing prerequisite task. - Editing frontmatter from the dashboard.
- The validation hint plugin (T-Q38X-editor-contract-validation-hint).
Dependencies
Section titled “Dependencies”- T-I4V6-sdf-entity-body-viewer: the layer is wired into SDF.
- The backend body-write op: 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. - S-0008-apps-consume-substrate-through-published-surfaces: SDF writes through
@sdlc/dashboard-client, never the file system. - D-0013-dashboard-app: the dashboard server owns the entity read and write surface.
D-7VMX-markdown-ecosystem-strategyd.4: an interactive editor is aswapwriter 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.