Skip to content

feat: per-surface operations across CLI, HTTP API, and MCP#165

Closed
benvinegar wants to merge 2 commits into
mainfrom
feat/per-surface-operations
Closed

feat: per-surface operations across CLI, HTTP API, and MCP#165
benvinegar wants to merge 2 commits into
mainfrom
feat/per-surface-operations

Conversation

@benvinegar

Copy link
Copy Markdown
Member

What

Surfaces now carry stable server-assigned ids, enabling targeted operations (append, edit, remove, reorder) on individual surfaces within a post — across all three integration tiers (CLI, HTTP, MCP). Also fixes #158 (CLI publish flag order).

Why

Issue #158 flagged that sideshow publish ignored flag order, but the investigation revealed a broader gap: every tier treated a post's surfaces as an opaque whole-array blob. There was no surface identity, no index targeting, and no per-surface operation primitive anywhere — CLI, HTTP, or MCP. Any per-surface operation required a client-side read-modify-write (GET the post, mutate locally, PUT the whole thing back). The server's own comment at app.ts:924 flagged "multi-surface needs --surface N" as never-built future work.

Changes

Phase 1 — Fix #158: CLI flag order

  • publish walks parseArgs tokens to honor flag appearance order instead of a hardcoded if-ladder

Phase 2a — Surface identity

  • Surface type includes id?: string, assigned server-side via normalizeSurfaceIds()
  • Both stores normalize on create/update; one-time migration for existing data (SqlStore gated on settings sentinel, JsonFileStore on load)

Phase 2b — HTTP API per-surface endpoints

  • POST /api/posts/:id/surfaces — append (optional before/after for position)
  • PATCH /api/posts/:id/surfaces/:target — replace (full or content-only)
  • DELETE /api/posts/:id/surfaces/:target — remove (400 if last)
  • PATCH /api/posts/:id/surfaces — reorder
  • PATCH /api/posts/:id extended with surface param for multi-surface targeting

Phase 2c — MCP per-surface tools

  • add_surface, edit_surface, remove_surface, reorder_surfaces (both stdio and HTTP transports)

Phase 3a — CLI surface subcommand

  • sideshow surface add|remove|edit|move
  • sideshow update --surface N

Phase 3b — Viewer key-by-id

  • <Index><For> keyed by surface identity; reconcile({ key: "id" })

Validation

npm test          → 372 pass, 0 fail
npm run typecheck → 3 programs clean
npm run lint      → 0 warnings, 0 errors
npm run format:check → clean

Back-compat

  • Legacy routes (/api/surfaces, /api/snippets) and keys (parts) unchanged
  • update_post full-replace stays; new MCP tools are additive
  • sideshow update without --surface keeps single-surface behavior
  • Store contract tests pass on both JsonFileStore and SqlStore

Plan

Full design plan in docs/plans/per-surface-operations.md.

Surfaces now carry stable server-assigned ids, enabling targeted
operations (append, edit, remove, reorder) on individual surfaces
within a post — across all three integration tiers.

CLI:
- publish honors flag order instead of a fixed if-ladder (#158)
- update --surface N targets a surface in multi-surface posts
- new surface subcommand: add, remove, edit, move

HTTP API:
- POST /api/posts/:id/surfaces (append)
- PATCH /api/posts/:id/surfaces/:target (replace/content-only)
- DELETE /api/posts/:id/surfaces/:target (remove)
- PATCH /api/posts/:id/surfaces (reorder)
- PATCH /api/posts/:id extended with surface param

MCP:
- new tools: add_surface, edit_surface, remove_surface, reorder_surfaces

Viewer:
- surfaces keyed by stable id (For + reconcile key=id)

Data model:
- Surface.id assigned server-side via normalizeSurfaceIds
- one-time migration for existing data in both stores
…tml replacement

- surface add: add --layout flag and propagate layout:'split' to diff
  surfaces (matches publish behavior)
- replaceSurface: merge kits into a full html surface replacement so
  edit_surface no longer silently drops kits
@benvinegar

Copy link
Copy Markdown
Member Author

Closing — these changes landed on main via #166 (which was branched from this PR and merged first). Nothing lost; main has all of this PR's commits plus the get_post/show additions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI publish: surface order is fixed by flag identity, not command-line flag order

1 participant