Repository navigation
feat(drafts): foundation — top-level Drafts page + draft entity (slice 0) - #219
Merged
Merged
Conversation
Drafts is a new top-level feature: a living markdown document a user co-authors with an agent. Slice 0 ships only the standalone entity and single-user CRUD; later slices add the annotation surface, the agent, Yjs co-editing, and graduation. Backend mirrors the project/task handler patterns: - migration 122: standalone `draft` table (workspace_id, owner_user_id, title, body, open `status` enum defaulting to 'draft', timestamps) + (workspace_id, owner_user_id, updated_at DESC) index - draft.sql: List/Get/Create/Update(COALESCE narg)/Delete, every query scoped to workspace_id + owner_user_id - draft.go: DraftResponse + CRUD handlers, loadDraftForUser loader (UUID-parsing convention), open-enum status downgrade with a default branch - /api/drafts routes next to /api/tasks (GET/POST collection; GET/PUT/ PATCH/DELETE item) behind RequireWorkspaceMember - draft:created/updated/deleted WS events - draft_test.go: CRUD round-trip, partial-patch preservation, bad-UUID guards (404 not silent no-op), enum-drift downgrade, cross-owner denial Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirrors the Tasks feature end-to-end. Slice 0 is single-user CRUD: a
top-level Drafts page where a user can create, list, open, edit (title +
markdown body with autosave), and delete a draft. No annotations, agent,
or co-editing yet — those land in later slices and slot into the editor
pane without changing this shell.
Core:
- types/draft.ts: Draft, DraftStatus (open enum), CreateDraftRequest,
UpdateDraftRequest, ListDraftsResponse
- api/schemas.ts: DraftSchema + ListDraftsResponseSchema + EMPTY fallbacks;
schemas.test.ts adds malformed-response coverage (missing field, wrong
type, null array, unknown status downgrade)
- api/client.ts: listDrafts/getDraft/createDraft/updateDraft/deleteDraft,
every read through parseWithFallback (no bare `as`)
- drafts/: draftListOptions/draftDetailOptions, useCreateDraft/
useUpdateDraft (optimistic, autosave-friendly)/useDeleteDraft, flat-list
cache helpers, and onDraft{Created,Updated,Deleted} WS updaters
- realtime/use-realtime-sync.ts: subscribe draft:created/updated/deleted →
invalidate via the updaters (never write stores)
- paths.ts: drafts() + draftDetail() (?draft=<id>, mirroring taskDetail)
Views:
- drafts/: DraftsPage master-detail (list left, editor right; selection on
?draft=<id>), DraftEditor (TitleEditor + ContentEditor autosave, 1s
debounce) — mirrors the memory artifact editor
- layout/app-sidebar.tsx: Drafts nav entry (NotebookPen) in personalNav
- i18n: drafts namespace (en + zh-Hans) registered in locales bundle +
resources types; layout nav.drafts label
- web + desktop /drafts routes; @multica/views/drafts + @multica/core/drafts
package exports
- drafts-page.test.tsx: render/select/create/empty-state coverage
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slice 0 of Drafts — the foundation. A new top-level Drafts page where a user creates, lists, opens, edits (title + markdown body, autosave), and deletes a
draft. No agent, annotations, or co-editing yet — those are slices 1–4; clean seams left for them.Drafts is the incubation home for Multica's flagship lead agent ("Jane") — a surface where you co-author a living plan with an agent by editing + annotating. This PR is just the skeleton everything hangs off.
What's here (mirrors the Tasks feature end-to-end)
122_draft(own table —workspace_id+owner_user_id[forward-compat naming for future multi-author],title,body, openstatusenum [defaultdraft, no CHECK so it survives enum drift], timestamps, compound index); sqlc CRUD;draft.gohandler (loadDraftForUserloader + the UUID-parsing convention; open-enumdefaultbranch);/api/draftsroutes;draft:*WS events.parseWithFallback+ 5 malformed-response tests) + client;packages/core/drafts/query/mutation/cache/ws hooks (optimistic, autosave-friendly,wsId-keyed);packages/views/drafts/DraftsPagemaster-detail (?draft=<id>search param, matching Tasks' live mechanism) +DraftEditor(ContentEditor + debounced autosave); sidebar nav (NotebookPen, personal nav); web + desktop routes;draftsi18n namespace (en + zh-Hans).Decisions (from the implementer, all reasonable)
?draft=<id>search param, no[id]route (Tasks'[id]is only a legacy redirect; Drafts has no legacy links to preserve).draftis its own table (modeled onproject), not piggybacked onissueliketask.personalNavnext to Tasks (drafts are owner-scoped).statusdowngrades unknown→draft(enum-drift rule); no DB CHECK.Test plan
make sqlcclean;go build/vet/go test -run Draftpass; typecheck all 6 packages; core 328 + views 804 vitest (incl. 5 new schema + 6 new DraftsPage tests); lint 0 errors. Independently re-verified./drafts— create, edit (autosave), switch, delete a Draft.🤖 Generated with Claude Code