| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
rewrite
End-to-end rewrite addressing the issues from the user's UX review.
The system now feels like a daemon-orchestration tool: lock a contract
and the orchestrator just goes; PR raised → auto-ship → reopen for
amendments. The sidebar tree shows real entities only (no duplicates,
no inline action buttons polluting the file list), and every entity
gets a right-click context menu. Task page matches the old /exec
layout (diff on the left, feed + composer on the right).
## Backend — strict lifecycle (the orchestrator-never-spawned bug)
Root cause: `phase_planning()` gates on `directive.status='active'`, but
`start_contract()` only flipped the contract row — the parent directive
stayed in whatever state it was. So locking a contract did nothing
visible.
Fix: contract lifecycle now drives directive status in the same
transaction.
start_contract → if contract becomes active, flip directive
draft|paused|idle|inactive → active
pause_contract → after promote, if no active contract left,
directive → paused
complete_contract→ after promote, if no active left, directive →
inactive (also fires on auto-ship from PR detect)
unlock_contract → if was active and no active left, directive →
paused
reopen_contract → NEW. shipped → active. Directive → active,
orchestrator_task_id/pr_url/pr_branch cleared so
the reconciler spawns a fresh planner. The
planner reads get_latest_merged_revision and
frames the new plan as an amendment.
handlers::directive_documents lifts state.kick_directive_reconciler()
into run_contract_transition so every successful transition wakes the
reconciler immediately (no 15s wait).
handlers::directives `update_directive` (PR-detection branch) calls
`complete_contract(active_contract_id, pr_url, pr_branch)` instead of
`set_directive_inactive`. The contract auto-ships; the directive
follows via the sync above. No more manual "Mark complete" click.
POST /api/v1/contracts/{id}/reopen added + wired through openapi.
Spawn task names dropped the directive-title prefix that looked
redundant in the sidebar:
"Plan: <title>" → "orchestrator"
"Re-plan: <title>" → "orchestrator (re-plan)"
"PR: <title>" → "completion"
"Update PR: <title>" → "completion (update)"
## Frontend — sidebar
* De-dupe: DocumentTasksFolder filters tasks[] to exclude any task
whose id already appears in steps[].taskId. Single row per task,
single highlight on click.
* Generic SidebarContextMenu (new) replaces the directive-only
DirectiveContextMenu (deleted). Per-entity item arrays built at the
page level — directive, contract, step, task each have their own
contextual actions.
* Right-click works on every sidebar entity now (was directive-only).
* `+ New document` / `+ New ephemeral task` inline buttons removed.
Reachable via the directive folder right-click OR the hover-only
`+` button on the directive folder row.
* ContractHeader: dropped "Mark complete" button (auto-fires on PR).
Added "Reopen for amendment" button when contract is shipped.
## Frontend — task page rewrite
TaskPage.tsx replaces DocumentTaskStream.tsx (deleted). Two-column
layout matches the old /exec page that the user preferred:
┌────────────────────────┬──────────────────────────────────┐
│ Changed files (~30%) │ Transcript feed (scrollable) │
│ ────────────────── │ ────────────────────── │
│ src/foo.rs │ [user] do thing │
│ src/bar.rs │ [tool] Read foo.rs │
│ │ │
│ Diff (selected file) │ │
│ ├──────────────────────────────────┤
│ │ Composer (sticky bottom) │
└────────────────────────┴──────────────────────────────────┘
Diff comes from getTaskDiff(); parseDiff + DiffFileView exported from
OverlayDiffViewer for reuse (no duplication). Diff auto-refreshes
when the task transitions to a terminal state. Transcript styling +
sticky composer keep the parts the user liked. "Open in task page"
button removed — the right pane IS the task page.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
palette, SWR (#117)
Phases 1-3 of the unified-surface plan, bundled per the user's request.
The directive document/folder UI is now the canonical place to interact
with makima; legacy /exec is subsumed by routing redirects, /contracts is
already hidden in nav, and orphan tasks surface under a top-level tmp/
pseudo-folder. Phase 4 (porting contract-only features) was confirmed
out of scope; Phase 5 (deleting the contracts code) is a follow-up.
## Backend
- New migration `20260501000000_archive_existing_contracts.sql` flips
every legacy contract to `archived` so /contracts is read-only history.
- New endpoint `POST /api/v1/directives/{id}/tasks` creates an ephemeral
task — `directive_id` set, `directive_step_id` NULL, repo/branch
inherited from the directive. Reuses `create_task_for_owner`.
- New endpoint `GET /api/v1/directives/{id}/tasks` lists ephemeral tasks
attached to a directive (drives the per-folder ephemeral group).
- `GET /api/v1/mesh/tasks?orphan=true` returns top-level tasks with no
`directive_id` AND no `parent_task_id` — backs the sidebar's tmp/.
- New repo helpers `list_ephemeral_directive_tasks_for_owner` and
`list_orphan_tasks_for_owner`.
- The existing `mesh_merge` endpoints are reused as-is for ephemeral
task merge (no new merge logic needed).
## Frontend
### Sticky composer + auto-scroll fix (`DocumentTaskStream.tsx`)
- Sticky comment composer pinned to viewport bottom; padding compensates
so the last entry isn't hidden behind it.
- `autoScroll` now resumes when the user scrolls back within 80px of
the bottom (previously stuck off forever after a single scroll-up).
- Floating "↓ Jump to latest" chip when the user has scrolled away.
- Action header strip: explicit Stop / Send / Open-in-task-page +
conditional "Merge to base ↗" button on ephemeral terminal tasks.
- Module-level cache of historical entries by taskId so re-selecting a
task you've viewed renders instantly while a fresh fetch runs.
### Sidebar (`document-directives.tsx`)
- Top-level `tmp/` folder: orphan tasks, polled every 5s.
- Per-directive `tasks/` subfolder now also surfaces ephemeral tasks
(lazily fetched on folder open) with a distinct asterisk-on-terminal
icon (`EphemeralTaskIcon`).
- Inline hover-action chips on each directive folder header: Start /
Pause / PR / +New task. Right-click menu still works as a power-user
fallback.
- "Now executing" amber strip in the editor pane: surfaces the live
orchestrator/completion/running-step task with a one-click jump.
- Inline `+ New task` modal (name + plan); on submit calls
`createDirectiveTask` and navigates into the freshly-spawned task.
- New `EphemeralAwareTaskStream` wrapper passes `ephemeral` and
`status` to `DocumentTaskStream` so the merge button only shows when
the selected task is genuinely an ephemeral spinoff in a terminal
state. Step-spawned tasks merge via the directive's PR completion.
### SWR cache (`useDirectives.ts`)
- Module-level `listCache` and per-id `detailCache` (mirrors the pattern
in `useUserSettings.ts`). Mounting the hook renders the cache value
immediately if present and kicks a background refresh; subscribers see
the new value when it lands. Cuts perceived navigation latency to
near-zero on warm cache hits.
### QuickSwitcher (`QuickSwitcher.tsx`, new)
- IntelliJ-style double-Shift command palette mounted at app root.
- Listens at the document level for two `Shift` keydowns within 300ms
with no other key in between; ignores while focus is in an
input/textarea so capitalising letters doesn't pop the palette.
- Searches across directives + their tasks (orchestrator/completion/
steps/ephemerals) + orphan tmp tasks. Fuzzy matches on title.
- Eagerly loads task details for the first 20 directives on open so
searches don't block on per-directive fetches.
### Routing (`main.tsx` + `exec-redirect.tsx` + `tmp.tsx`)
- New `ExecRedirect` wrapper at `/exec/:id`: when documentMode is on
AND the task has a `directiveId`, replaces the URL with
`/directives/<directiveId>?task=<taskId>`. Otherwise renders the
legacy `MeshPage` as before.
- New `/tmp/:taskId` route renders `DocumentTaskStream` standalone for
orphan tasks, with the masthead and a `tmp / <slug>` breadcrumb.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
|
task stream (#103)
Three connected UX changes for the document-mode directive UI.
## Goal save UX (DocumentEditor.tsx)
- Replace the old 3-second countdown with 60s when no orchestrator is running
and 10s when one is, so editing a goal mid-flight does not feel rushed.
- The countdown bar is hidden until the last 10 seconds; users see "Saved" /
"Unsaved changes" indicators rather than a constantly-ticking clock.
- Continuously persist work-in-progress to localStorage on every keystroke
(debounced 250ms). On mount, if a draft for the directive exists in
localStorage and differs from the persisted goal, restore it and put the
editor in dirty/pending state — leaving the page no longer loses work.
- localStorage-backed "Live start" toggle in the bar. When off, the editor
stays in "dirty" instead of auto-firing; user clicks "Save now" to commit.
- Discard button reverts the editor to the persisted goal and clears the draft.
## Sidebar restructure (document-directives.tsx)
- Drop the active/idle/archived top-level grouping; show one folder per
directive instead. Folders sort by lifecycle (active, paused, idle, draft,
archived) then alphabetically.
- Each folder header shows a colored status dot on BOTH sides (left as the
primary status icon, right as a mirror plus a pulse when the orchestrator
is live), replacing the previous "/active", "/idle" text labels.
- Inside each open folder: the directive's document is pinned at the top
(with a small star icon), then the orchestrator task (if running), then
the completion task, then any step tasks that have started.
- The currently-selected directive's folder is auto-opened so deep links
always land somewhere visible.
## Live document task stream (DocumentTaskStream.tsx, new)
- Selecting a task in a folder navigates to ?task=<id> and replaces the
Lexical editor with a document-styled live transcript: assistant prose as
flowing paragraphs, tool calls as marginalia, results as a closing block.
No log/code box.
- Comment textarea at the bottom calls sendTaskMessage on submit, the same
wire the existing TaskOutput input bar uses for interrupts. ⌘/Ctrl-Enter
submits.
- Header breadcrumb gains a "back to document" affordance to return to the
pinned doc view without reopening the sidebar.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|