summaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* chore: remove LLM module + all dependent surfacesremove-llmsoryu3 days37-14281/+58
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Wholesale removal of the LLM integration layer. ~14,200 LOC deleted across backend and frontend. All chat-driven UIs go with it. ## Backend - Delete `src/llm/` (7,400 LOC): claude/groq clients, contract_tools, contract_evaluator, discuss_tools, mesh_tools, phase_guidance, task_output, templates, markdown round-trip, tools, transcript_analyzer. - Delete handlers wholly dependent on LLM: - `chat.rs` (file-level LLM chat at /files/{id}/chat) - `mesh_chat.rs` (mesh & task LLM chat + history) - `templates.rs` (/contract-types listing) - Strip LLM uses from `mesh_daemon.rs`: - `compute_action_directive` (used phase_guidance::check_deliverables_met to nudge supervisors with "all tasks done" messages). The auto-PR path below still fires when all tasks finish, so no behaviour lost. - `crate::llm::markdown_to_body` → inline 1-line replacement that wraps markdown content in a single BodyElement::Markdown. The editor re-parses on display, so round-trip is preserved. - Drop routes: /files/{id}/chat, /mesh/chat, /mesh/chat/history, /mesh/tasks/{id}/chat, /contract-types. - Drop the matching openapi registrations. ## Frontend - Delete components that were LLM-only: - `mesh/UnifiedMeshChatInput.tsx` - `listen/DiscussContractModal.tsx` - `listen/TranscriptAnalysisPanel.tsx` - `listen/ContractPickerModal.tsx` - `files/CliInput.tsx` - Delete the entire /listen page (its primary value-add was voice → LLM analysis → contract creation; without LLM the page is just a transcript display with no obvious user purpose). - Delete `hooks/useMeshChatHistory.ts` and `lib/listenApi.ts` (transcript-analysis API client to the already-Phase-5-removed listen handlers). - Strip api.ts of LLM exports: LlmModel, ChatMessage/Request/Response, UserQuestion/Answer, chatWithFile, MeshChat* types & functions, getMeshChatHistory, clearMeshChatHistory, chatWithMeshContext, ContractTypeTemplate, listContractTypes, chatWithContract, getContractChatHistory, clearContractChatHistory, discussContract, PhaseDefinition, DeliverableDefinition. - mesh.tsx: drop UnifiedMeshChatInput render + the chatContext memo + handleTaskUpdatedFromCli (only consumer was the input). - files.tsx: drop CliInput render + handleGenerateFromElement + handleBodyUpdate + handleClearFocus + suggestedPrompt state (all CliInput-only). - NavStrip: drop the /listen link. - main.tsx: drop the /listen route. ## Net diff: 37 files changed, 58 insertions, 14,281 deletions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(directives): strict orchestration flow + sidebar overhaul + task page ↵soryu4 days14-993/+1366
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | rewrite (#134) 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>
* fix(directives): tasks folder visibility, circular auto-save timer, ↵soryu4 days3-55/+283
| | | | | | | | | unlock-to-edit (#133) * feat: soryu - makima: Fix tasks/ folder visibility and rename for multi-contract directives * feat: soryu - makima: Replace auto-save countdown text/bar with a circular timer * feat: soryu - makima: Require Unlock before editing a locked contract body
* feat(directives): drop directives.goal — orchestration reads contract body ↵soryu12 days17-1766/+198
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (#132) Hard cut. The unified contracts surface owns spec text now; the directive itself is just a folder. The orchestrator daemon reads the active contract's body when it spawns, replans, or runs completion. Schema (migration 20260510000000): - DROP TABLE directive_goal_history - ALTER TABLE directives DROP COLUMN goal - ALTER TABLE directives DROP COLUMN goal_updated_at New repo helper: - get_active_contract_body(directive_id) — picks the active|queued|draft contract (in that order), most-recent first. Backend cuts: - Directive / DirectiveSummary / CreateDirectiveRequest / UpdateDirectiveRequest lose goal & goalUpdatedAt. - CreateDirectiveRequest gains optional `contractBody` — when provided, create_directive_for_owner auto-creates a first contract with that body in the same transaction. - Removed: update_directive_goal, update_directive_goal_keep_orchestrator, save_directive_goal_history, get_directive_goal_history, DirectiveGoalHistory model, UpdateGoalRequest. - Removed handlers::directives::update_goal + the /directives/{id}/goal route. - orchestration::directive::build_planning_prompt / build_completion_prompt / build_order_pickup_prompt now take a `contract_body: &str` instead of `goal_history`. classify_goal_change + try_interrupt_planner_with_goal_edit + GoalChangeKind + GoalEditInterruptResult removed (they were only useful for the small-vs-large goal-edit interrupt cycle). CLI: - `makima directive update-goal` removed (UpdateGoalArgs deleted, Commands enum trimmed, ApiClient::directive_update_goal + UpdateGoalRequest deleted). Frontend: - Directive / DirectiveSummary / CreateDirectiveRequest types lose goal & goalUpdatedAt; CreateDirectiveRequest gains `contractBody`. - useDirective drops updateGoal helper. - api.ts updateDirectiveGoal removed. - Legacy DirectiveList + DirectiveDetail components deleted; the /directives route now always renders the document-mode page. The user-settings documentModeEnabled flag is no longer consulted at the route level. - NewContractModal passes body via contractBody. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(frontend): DocumentEditor takes explicit body/title/documentId ↵soryu12 days2-71/+97
| | | | | | | | | | | | | | | | | | | | | | | props (#131) Stops shadowing directive.goal with the contract body via a synthesised directive object. DocumentEditor now accepts: * documentId — scopes the localStorage draft key per contract so switching contracts under the same directive doesn't clobber the other's unsaved edits. * title — the contract title rendered as the H1. * body — the contract body, used to seed the editor. * onUpdateBody (was onUpdateGoal) The `directive` prop stays for orchestrator state + embedded steps panel. document-directives.tsx drops the directiveAsDocument synthesis hack and passes body/title from the contract directly. This is the prep-work for dropping `directives.goal` from the schema — once nothing reads it, the column can be dropped in a follow-up without touching the editor. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(contracts): drag-to-reorder active contract rows in sidebar (#130)soryu13 days1-1/+85
| | | | | | | | | | | | | | | | | HTML5 drag/drop on active contract rows. Dragging a row over another in the same directive folder shows a green top-border drop indicator; dropping calls reorderDirectiveContract(id, targetPosition) and refreshes the folder. Shipped/archived rows aren't draggable (historical, ordering is fixed). Implementation: - DocumentRow gains optional draggable + drag event props. - DirectiveFolder owns the drag/over state and handleReorder callback; computes target position from the drop-target row's current position. - Repository's reorder endpoint already exists from the backbone PR and handles sibling shift in a transaction. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(contracts): lifecycle — Lock/Start/Pause/Complete/Unlock + queue ↵soryu13 days10-36/+841
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | scheduler (#129) Adds the contract lifecycle layer on top of the unified-contracts backbone (#128). State machine: draft → queued → active → shipped → archived At most one contract per directive sits in `active` at any time — the queue is serialised because each directive owns a single shared worktree. Repository helpers handle the transition checks AND auto-promote the next-up `queued` contract whenever the active slot frees (pause / complete / unlock-from-active / archive-from-active). Endpoints (all under /api/v1/contracts/{id}): POST /start draft → queued | active (depending on slot) POST /pause active → queued; promotes next queued POST /complete active → shipped; optional pr_url + pr_branch POST /unlock queued | active → draft; promotes if was active Frontend wiring: * `DirectiveContractStatus` now includes `queued`. * Migration adds `queued` to the CHECK constraint on directive_documents.status. * `ContractHeader` component renders breadcrumb + status pill + status-driven action buttons + a merge-mode (shared / own_pr) radio. Merge mode is editable only while draft / queued so a running flow's branch target can't change mid-stream. * RepositoryError gains a `Validation(String)` arm; the three existing exhaustive matches (files, mesh, versions) get a 400 BAD_REQUEST response for it. Drag-to-reorder UI deferred to a small follow-up — the backend endpoint already exists from the backbone PR. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(directives): unified contracts surface — backbone (#128)soryu13 days8-108/+396
| | | | | | | | | | | | | | | | | | | | | | | | | | This is the backbone PR for the unified directive workflow. A directive holds a sequence of contracts; each contract is a spec body whose execution drives tasks in the directive's shared worktree. Lifecycle (Lock & Start, queue scheduler, drag-reorder) lands in follow-ups. What's in this PR: - Migration adds `position` (queue order) and `merge_mode` (shared|own_pr) columns to directive_documents. The actual table rename is deferred — the legacy `contracts` table from the old contracts system still exists, and the rename collision waits for Phase 5 to drop legacy contracts. - Repository: list orders by position; create assigns next-position; update accepts merge_mode; new reorder_directive_document_position shifts siblings inside a transaction. - HTTP: endpoints aliased under /api/v1/directives/{id}/contracts and /api/v1/contracts/{id}/... with a new /contracts/{id}/reorder. - Frontend: api types renamed `DirectiveContract*` (avoiding the legacy `Contract` type collision); document-directives.tsx imports via aliases so the rest of the file is untouched. Internal struct + table names stay `DirectiveDocument` / `directive_documents` until the legacy contracts cleanup. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Replace PC-98 landing aesthetic with Heisei Twilight theme (#127)soryu14 days19-19/+1296
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Replace PC-98 landing aesthetic with Heisei Twilight theme Layered new heisei.css (loaded after pc98.css) over the public landing page so the late-2000s/early-2010s anime cue lands subtly without a ground-up rewrite. Internal VN/contracts/daemons screens are untouched. What changed - Twilight gradient backdrop (deep night → dusk plum → horizon rose + amber) replaces the chunky animated GIF background. - Soft bokeh plates and a faint scanline overlay sit behind the content for atmosphere. - Floating header is now frosted glass with a 1px hairline; the system status pills use Inter-tracked uppercase labels with desaturated cyan/magenta indicators. - Vertical kanji masthead becomes a quiet Noto Serif JP column rather than an arcade box; English subtitle picks up a warm amber tone. - Issue badge is a flat pill; LED heart still pulses but in muted rose. - Empty hero state shows a faint tactical reticle (corner brackets) and bilingual JP/EN tagline — Ghost-in-the-Shell SAC HUD vibe. - Mission and MAKIMA panels render as Heisei magazine columns with a Noto Serif JP headline, accent rule (amber for Mission, magenta for MAKIMA), and Inter body copy. - Buttons are flat with hairline borders and a left-edge amber accent sweep on hover; the Login CTA keeps a warm gradient as the primary action. - Bottom Velocity/Energy strip becomes a small HUD pill with corner bracket detailing. - Mobile breakpoint tightens header, padding, headline size, and stacks the secondary CTAs back to a column. - prefers-reduced-motion respected for the heart pulse and image pan. How to verify - cd frontend && npm install && npm run dev - Compare http://localhost:5173 with the live soryu.co (PC-98 build) - Toggle the Mission and MAKIMA panels; resize to 390x844 for mobile. Implementation notes - Single new file: frontend/src/styles/heisei.css (~16 KB). - main.tsx imports heisei.css after pc98.css so the override wins. - No JSX/component changes — design lives entirely in CSS, easy to revert by removing the import line. - npm run build passes (vite v5.4, 91 kB CSS gzipped to 17.8 kB). * Attach before/after screenshots for review Six viewport/state combinations captured at 2x DPR with Playwright (desktop 1440x900, mobile 390x844). before-* show the live soryu.co PC-98 build; after-* show the heisei-twilight branch served by vite dev. Drop this commit before merge if you'd rather not carry the assets in tree. * Move CTA row into a top navbar below the floating header Per review feedback, lift Mission / MAKIMA / Login from the bottom of the cover into a fixed navbar that sits flush beneath the floating header — standard site pattern. - .cta-area is now position: fixed, top: 72px, height 52px (top: 56px, height 48px on mobile), with the same frosted-glass + hairline treatment as the header so they read as one stacked nav block. - Buttons become ghost-link items inside the bar with an animated underline-from-center on hover; Login keeps its warm amber→rose primary treatment but compact. - cover-content top padding bumped to 156px (desktop) / 124px (mobile) so the masthead and hero clear both stripes. - bottom-stats no longer needs to dodge a fixed-bottom CTA — pulled back to bottom: 24px (desktop) and ~20px + safe-area (mobile). - npm run build passes (CSS 91.6 kB / 17.9 kB gzip). Screenshots in docs/heisei-screenshots/after-*.jpg refreshed against the new navbar layout (1440x900 desktop, 390x844 mobile, 2x DPR). * Center mobile navbar buttons (kill leftover pc98 margin-top) The bottom-CTA layout in pc98.css had a mobile-specific margin-top: 20px on .taisho-cta, which carried over into the new top navbar and pushed every button 20px below the navbar's vertical center on mobile (visible misalignment at 390x844 — the Mission/MAKIMA/Login pills were sitting near the bottom edge of the bar). - Add margin: 0 !important to .taisho-cta in heisei.css (and to the mobile-block override) so the legacy column-layout margin is wiped on both breakpoints. - Switch buttons to height: 32px + line-height: 32px for stable vertical centering inside the 48px (mobile) / 52px (desktop) navbar. - Force align-self: center on .cta-left/.cta-right so they don't inherit any stretched height from previously-applied rules. Verified via Playwright DOM probe at 390x844: navbar y=56–104 (centerY 80) · buttons y=64–96 (centerY 80) ✓ And at 1280x720: navbar y=72–124 (centerY 98) · buttons y=83–113 (centerY 98) ✓ Screenshots in docs/heisei-screenshots/after-*.jpg refreshed. * Tighten mission/makima top space and use highlighted nav state The CTA row is now a top navbar, so the old 'Close' label on the active panel button is redundant — the button itself should look like the current page. Two fixes here: 1. Replace 'Close' with a persistent active highlight. - LandingPage.tsx: button keeps its label ('Mission' / 'MAKIMA') and gains an is-active class + aria-current="page" when its panel is open. heisei.css renders the active state as a solid amber underline + amber text — same visual language as the hover indicator, just persistent. - The button still toggles the panel closed when clicked again, so the interaction is unchanged; only the labelling moved. 2. Remove the white-space band above mission content. - The legacy .modern-landing-page wrapper from pc98.css pinned itself at top: 120px and height: calc(100vh - 120px), matching the original 120px-tall floating header. The new header is 72px (56px on mobile), which left ~50px of dead space below the navbar before the mission/makima content started. - Override the wrapper to top: 72px / height: calc(100vh - 72px) on desktop and 56px on mobile so it sits flush under the header. - Cover-content padding-top retuned for the new wrapper origin: desktop default 84px, mission-mode 72px (navbar 52 + 20 gap). Mobile default 76px, mission-mode 64px (navbar 48 + 16 gap). Verified at 1280x720: navbar y=72-124 · mission headline starts y=144 · 20px gap ✓ active Mission button: 'taisho-cta is-active', aria-current=page ✓ npm run build passes (CSS 92.6 kB / 18.1 kB gzip). Screenshots in docs/heisei-screenshots/after-*.jpg refreshed against the tightened layout. * Align mission/makima body, fix mobile bg, add typewriter hero rotator Three fixes coming out of QA on staging (soryu.eirin.xyz): 1. Mission / MAKIMA body alignment - The amber/magenta accent rule + 18px indent used to live on .mission-headline only, so paragraphs (and the mission image) started 18px to the LEFT of the headline. - Move the rule + padding-left onto the .mission-screen wrapper itself. Headline, image, and all paragraph(s) now share one consistent column edge. - Tighten the makima-badge so it doesn't stretch the grid column (justify-self: start + width: max-content). Image gets explicit width: 100%; display: block to behave inside the column. 2. Mobile background coverage - pc98.css mobile-block override ('@media max-width:768px') reset .modern-landing-page to position: relative + margin-top: 100px, leaving a 100-156px band at the top where only the body color showed and pushing the wrapper bottom past the viewport. - Force position: fixed on the wrapper at every breakpoint with !important. Use 100dvh (dynamic viewport height) so the gradient follows iOS Safari's collapsing URL bar rather than getting clipped. - Mirror the dusk gradient onto <body> as a fallback so any sub-pixel rounding gap shows the same colour, not white. 3. Typewriter hero rotator - New <TypewriterRotator/> component (frontend/src/components/ TypewriterRotator.tsx) — types, holds, deletes, gaps, advances. Honours prefers-reduced-motion (renders the first phrase static). - LandingPage.tsx renders it inside a new .hero-tagline wrapper where the old static CSS ::after lived. Five phrases, all bilingual JP/EN in the same Heisei tactical voice: * 低遅延ストリーミング · LOW-LATENCY OBSERVABILITY * リアルタイム監視 · REAL-TIME SURVEILLANCE * ミッションクリティカル · MISSION-CRITICAL INFRASTRUCTURE * エンドツーエンド可視化 · END-TO-END VISIBILITY * 安全な意思決定 · SECURE DECISIONS AT THE EDGE - Hide the old .hero::after pseudo-tagline; .hero-tagline keeps the same centred position, amber colour, and tracking. - Caret blink animation (steps(1), 1s) — separate from the typing timing so it always blinks at human speed. npm run build passes (CSS 94 kB / 18.2 kB gzip, JS 238 kB / 75 kB gzip — +1.5 kB net for the rotator + new phrases). Verified at 1280x720 / 390x844 via Playwright DOM probe: - mission/makima: headline.x === paragraph.x === image.x ✓ - mobile: wrapper y=56, h=788, bottom=844 (full coverage) ✓ - typewriter: types, holds, deletes, advances to phrase 2 ✓ Screenshots in docs/heisei-screenshots/after-*.jpg refreshed. Staging at soryu.eirin.xyz updated via rsync. * Center hero on homepage, image-left text-right on mission/makima - Default homepage now uses single-column grid; the SORYU masthead is absolutely positioned in the upper-left of the cover frame, so the hero typewriter is genuinely centered on the page (verified taglineCenterX === pageCenter at 1280px). - Mission/MAKIMA on desktop (>=1025px) switch to a flex layout with the image absolutely positioned in a 360px left gutter and all body text (badge -> headline -> paragraphs) flowing on the right. - Mobile and tablet (<=1024px) keep the stacked layout; masthead returns to inline flow under the navbar. - MAKIMA badge uses flex `order: -1` so it appears above the headline visually, even though the JSX renders headline first. * Replace PC-98 character image with tactical observability mesh SVG - New /public/mission-tactical.svg (~9KB, license-clean, hand-crafted): amber wireframe globe + magenta mesh links, GitS:SAC-style HUD chrome (corner brackets, scanlines, telemetry strip, NODE-001 TYO label, pulsing origin node), kanji watermark. - Uses CSS palette vars (amber #e8b87a / magenta #d96a8a / cyan #9ad7e0). - .mission-image switched to object-fit:contain with a dark fill so the vector renders fully and never crops; pc98 mission-pan animation is killed for the SVG path. * Animate mission tactical SVG: flowing data along mesh links - Each of 6 mesh arcs now has an id (#arc1..#arc6) with two layered animations: a flowing stroke-dashoffset (so the lines themselves appear to ripple), and a separate breathing opacity cycle. - 8 packet circles ride the arcs via <animateMotion> + <mpath>, with staggered begin times (0s..2.0s) and varied durations (2.6s..4.0s) so traffic feels asynchronous, not metronomic. - Amber arcs carry amber packets, magenta arcs carry magenta packets. - Hub nodes now have layered radial pulses (filled core + expanding ring) on independent timings; cyan relay dots blink gently. - REC indicator pulses 1.4s. All animations are SVG-native (no JS, no external library); browsers respect prefers-reduced-motion via UA defaults on <animate>. * chore: gitignore tsconfig.tsbuildinfo (auto-generated incremental build cache) * Drop mission-image ring border; reskin Login hover (no glow) - The animated SVG already draws its own hairline frame + corner brackets at the viewBox edge. Remove the `box-shadow: 0 0 0 1px` ring (in both the base `.mission-image` rule and the desktop-min-1025px `.mission-screen .mission-image` override) so the image isn't double-framed. Drop-shadow for elevation kept. - Replace the Login button hover effect. The amber drop-shadow halo used the same visual language as the active Mission/MAKIMA nav buttons (which also glow amber underneath); on hover Login now inverts to a deep-night background with amber ink and a hairline ::after rule that slides in from the left along the top edge — reads as 'armed' rather than 'glowing'. Letter-spacing widens slightly on hover (0.18em → 0.22em) for a subtle ink-spread. Added :active and :focus-visible states for keyboard a11y. * Remove vertical accent rule from Mission/MAKIMA text columns The 2px amber/magenta border-left + 18px indent on the right-column text was reading as another border running parallel to the SVG image on the left. The animated SVG already supplies all the framing the panels need, so the rule is now redundant noise. Removed in three places: - .mission-screen wrapper (base + .makima-screen variant) - desktop (>=1025px) per-block rule on headline + paragraph - mobile (<=768px) leftover padding-left: 14px on headline Verified: borderLeft = 0 on wrapper, headline, and paragraph(s) on both Mission and MAKIMA. Headline + body now sit flush with the badge at the same column edge (x=680 at 1280px). * Mission/MAKIMA backdrop: solid dark plate (no horizon bleed) The panel backdrop was rgba(11,17,36,0.62→0.85) — semi-transparent — so the page's dusk-pink horizon at the bottom of the gradient bled through behind the panel content, drawing the eye to the page edge and making the background gradient stand out instead of disappearing. Switched to a near-opaque #0a1024 → #0b1530 vertical gradient (slight slope kept for depth) and bumped backdrop-filter to blur(20px) saturate(80%) so any residual ambient is fully diffused. The panel now reads as its own surface rather than a tinted overlay. Verified: bottom-center pixel is rgb(10,20,47) — uniform deep night across the whole panel, no pink bleed at the page bottom. * Drop dark rounded plate behind Mission/MAKIMA images The .mission-image and .makima-logo had a semi-opaque dark fill (rgba(11,17,36,0.55-0.6)) plus border-radius: 2px. Combined with object-fit: contain (which letterboxes the SVG inside the larger 360px box), the dark fill was visible as a rounded rectangle 'frame' around the artwork — most noticeable on MAKIMA where the small circular logo sits in a much larger box. Switched both to transparent background + border-radius: 0 so the artwork floats directly on the panel backdrop. Drop-shadow kept on both for elevation; .makima-logo's amber halo + hairline ring removed too (it was painting the same noise). Verified by sampling pixels at the four image corners + inner mid: all read as the same uniform deep-night as the panel backdrop (rgb(10, 14-18, 30-42)). No plate, no rounded edge. * Remove box-shadow halo around Mission/MAKIMA image bounding boxes * Mission/MAKIMA backdrop: slightly translucent (alpha 0.72→0.84, blur 28px) --------- Co-authored-by: soryu-co <bot@soryu.co>
* fix(doc-mode): make task rows clickable and render live transcript (#125)soryu2026-05-051-11/+149
| | | | | | | | | | | | | | Task rows in the directive sidebar's `tasks/` subfolder were rendered as inert `<div>` elements with no click handler, and EditorShell had no branch for `selection.taskId` — so clicking a task did nothing visible. - StepRow and TaskRow are now `<button>` elements that call `onSelect(directiveId, taskId)` and navigate to `/directives/<dirId>?task=<taskId>`. - EditorShell renders DocumentTaskStream with a breadcrumb when `selection.taskId` is set (winning over the document path). - Step rows whose backing task hasn't been spawned yet stay disabled. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(doc-mode): flatten sidebar list + restore right-click context menu (#124)soryu2026-05-021-89/+183
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Two regressions reported by the user: 1. The sidebar was grouping contracts under per-status sub-folders (active/idle/archived). The user explicitly does not want that — they want a flat list with status indicated by a colored dot on the right of each row. 2. The right-click context menu on contract rows was missing — start/pause/archive/delete/create-PR/update-PR are no longer reachable through the UI. Fixes: * Drop the SidebarGroup/bucketOf/GROUP_LABEL helpers; replace the grouped render with a flat sort by status precedence (active → paused → idle → draft → inactive → archived) then alpha by title within the same status. The existing dot-color palette is unchanged; the dot just moved from the LEFT of the contract title to the RIGHT (after the orchestrator-running pulse, when present). * Wire `onContextMenu` through SidebarProps → DirectiveFolderProps → the folder header `<button>`. Page-level state captures the click position and the targeted directive; the existing DirectiveContextMenu component (start/pause/archive/delete/PR/ Advance/Cleanup/PickUpOrders) renders on top. * runAction helper centralises error handling: dispatches the API call, refreshes the sidebar list + bumps the document-folder refresh nonce on success, surfaces an alert on failure. * Delete confirms via window.confirm and clears the URL when the deleted contract was the one selected. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(frontend): regenerate pnpm-lock.yaml as v6 format + pin packageManager ↵soryu2026-05-022-1741/+1499
| | | | | | | | | | | | | | | | | | | | | | | | | | | (#123) Build env's pnpm warned "Ignoring not compatible lockfile" against the v9 lockfile produced by my last regen — older pnpm (8.x and below, which some build images still ship) only understands v6 lockfiles, and falls back to "no lockfile" mode which then errors under --frozen-lockfile: WARN Ignoring not compatible lockfile at /app/pnpm-lock.yaml ERR_PNPM_NO_LOCKFILE Cannot install with "frozen-lockfile" because pnpm-lock.yaml is absent Two-pronged fix: 1. Regenerate the lockfile in v6 format using pnpm 8.15.4 via corepack (`corepack pnpm@8.15.4 install`). The lockfile now starts with `lockfileVersion: '6.0'` again — readable by both old and new pnpm. 2. Pin `packageManager: "pnpm@8.15.4"` in package.json so build envs that respect corepack/Volta install the right version automatically instead of falling back to whatever's globally installed. Verified locally with `corepack pnpm@8.15.4 install --frozen-lockfile` (the CI command). \`tsc --noEmit\` passes. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(frontend): regenerate corrupted pnpm-lock.yaml (#122)soryu2026-05-021-1604/+544
| | | | | | | | | | | | | | | | | | | | The committed lockfile was a manual frankenstein of pnpm v6 metadata (`lockfileVersion: '6.0'` + `resolution:` blocks at the top) and v9-style snapshot entries appended below. pnpm 9 read it as a single packages: map and tripped on duplicate mapping keys (\`@floating-ui/core@1.7.5\` appeared twice; same for \`@floating-ui/utils@0.2.11\`, plus dozens of \`@lexical/*\` and \`@babel/*\` entries duplicated across the v6/v9 sections). This blew up Docker / Caddy builds: ERR_PNPM_BROKEN_LOCKFILE The lockfile at "/app/pnpm-lock.yaml" is broken: duplicated mapping key (688:3) Regenerated with \`pnpm install --no-frozen-lockfile\` against the existing package.json — net -1605 / +545 lines. \`pnpm install --frozen-lockfile\` now succeeds (the CI check), \`tsc --noEmit\` passes, \`vite build\` produces a clean bundle. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(doc-mode): + New contract sidebar header + + New ephemeral task per ↵soryu2026-05-021-5/+330
| | | | | | | | | | | | | | | | | | | | | | | | | | folder (#121) The unified surface didn't expose any way to create a new contract or a new ephemeral task — the only paths were `/directives/<id>?document=...` or right-click context menus that no longer existed in the documents-per- directive sidebar restructure. Two new affordances: * **Sidebar header gains a "+ New" button** that opens NewContractModal (title + goal + optional repository_url). On submit calls `useDirectives.create` and navigates the user into the new directive. Header label updated from "Documents" to "Contracts" so the button's intent reads naturally. * **Each open directive folder gets a "+ New ephemeral task" button** alongside the existing "+ New document" affordance. Opens NewEphemeralTaskModal (name + plan), calls the existing `createDirectiveTask` API, navigates the user into the new task's transcript at `?task=<id>`. NewContractModal and NewEphemeralTaskModal are local to the page — mirror the styling of the older NewTaskModal that lived here pre- restructure. ⌘/Ctrl+Enter submits. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* build(server): split Dockerfiles, make ML model paths optional (#120)soryu2026-05-025-79/+181
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Existing Dockerfile (with LLM/STT/TTS model download) is now `Dockerfile.full`. The new top-level `Dockerfile` builds a slim image without python, without huggingface_hub, without the model download step. The slim image is the new default for users who only want the orchestration surface — the directive folder UI, the mesh/task system, the API. ## Slim Dockerfile * No python / huggingface_hub / model downloads. * Same runtime tooling as `k8s/daemon/Dockerfile` (git, gh CLI, ssh, jq, curl, ca-certs, libssl3). * Embeds the daemon binary at /app/daemon-binaries/makima-linux-x86_64 for the in-server download endpoint. * PARAKEET_MODEL_DIR / SORTFORMER_MODEL_PATH / CHATTERBOX_MODEL_DIR are intentionally NOT set — Listen and Speak return "ML models not configured" if a client tries to use them. ## ML model paths now optional `ServerArgs.parakeet_model_dir`, `parakeet_eou_dir`, `sortformer_model_path`, `chatterbox_model_dir` are now `Option<String>` (no defaults). The bin constructor inspects them: if all four are present, configures `AppState::new`; if all four are absent, uses the new `AppState::new_slim()` which leaves `model_config = None`. The lazy load path in `get_ml_models` already returned a clean error for None. Speak (TTS) was already optional via `model_config.as_ref()` — still works. Mixed configurations log a warning and degrade to slim mode. ## Ops note The old `Dockerfile.full` retains the original behaviour for anyone who needs STT/diarization/TTS in production. CI still builds the daemon image from `k8s/daemon/Dockerfile` (untouched). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: multi-document directives with ephemeral task lifecycle (#119)soryu2026-05-0213-1798/+3816
| | | | | | | | | | | | | | | | | | | | | * feat: soryu-co/soryu - makima: Fix folder/file naming and breadcrumb hash bugs * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Frontend: render multiple documents per directive folder * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * Fix DirectiveRevision import in openapi.rs after merge * Fix document-directives.tsx merge artifacts and add inactive status
* chore(cleanup): Phase 5 contracts removal + tmp directive + 30-day expiry + ↵soryu2026-05-0136-14593/+275
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | scroll fix (#118) Sweeping cleanup across the surface and the wire. Net: -14k LOC of legacy contracts code, plus the tmp/scroll/UX fixes the user asked for. ## Sidebar/editor independent scroll Replace `height: calc(100vh - 80px)` (which assumed an 80px masthead and quietly clipped or pushed the whole page below the fold when the masthead was taller) with `h-screen + overflow-hidden` on the page root and proper `flex-1 min-h-0` sizing on `<main>`. Sidebar and editor pane now manage their own scroll independently; the page itself never scrolls. Same fix in /tmp/:taskId. ## tmp directive — real backing for orphans/ephemerals New migration `20260501100000_tmp_directive_and_clear_orphans.sql`: * Adds `directives.is_tmp` BOOLEAN NOT NULL DEFAULT false. * Partial unique index `(owner_id) WHERE is_tmp` — at most ONE tmp directive per owner. * Hard-deletes every existing orphan task (`directive_id IS NULL`). Per the user spec: "ALSO there are TOO MANY old tasks in tmp, we need to remove all of them as well." New repository helpers: * `get_or_create_tmp_directive(pool, owner_id) -> Directive` INSERT ON CONFLICT DO NOTHING + fallback SELECT, race-safe. * `list_all_tmp_directives` — drives the expiry sweep. * `delete_expired_tmp_tasks(tmp_directive_id) -> u64`. * `list_tmp_tasks_for_owner` (replaces `list_orphan_tasks_for_owner`). `mesh::create_task`: every top-level task must have a directive. If a caller doesn't supply `directive_id` and isn't a subtask, attach to the caller's tmp directive (auto-creating it on first use). `list_directives_for_owner` filters out `is_tmp=true` so the scratchpad directive doesn't pollute the contract list — surfaced via the sidebar's `tmp/` folder instead. ## 30-day expiry on tmp tasks New `phase_tmp_expiry` in the directive reconciler. Throttled to once per hour: enumerates every tmp directive, calls `delete_expired_tmp_tasks`, logs the count. The actual delete is `WHERE created_at < NOW() - INTERVAL '30 days'` and is fast on the existing index. Subtasks die via FK cascade. ## Phase 5 — contracts removed ### Frontend Deleted entire `/contracts` surface: * routes: `contracts.tsx`, `contract-file.tsx` * components/contracts: ContractList, ContractDetail, ContractCliInput, ContractContextMenu, CommandModePanel, PhaseBadge, PhaseHint, PhaseDeliverablesPanel, PhaseProgressBar, QuickActionButtons, RepositoryPanel, TaskDerivationPreview * (Kept `PhaseConfirmationModal` — used outside the contracts surface by `TaskOutput` and `PhaseConfirmationNotification`.) * Routes deregistered from `main.tsx`; nav entry removed from `NavStrip`. ### Backend handlers Deleted: `contracts.rs` (2.4k LOC), `contract_chat.rs` (3.2k LOC), `contract_daemon.rs` (~940 LOC), `contract_discuss.rs` (~590 LOC), `transcript_analysis.rs` (~690 LOC). All `/api/v1/contracts/*` routes deregistered. OpenAPI entries dropped. Module declarations removed from `server/handlers/mod.rs`. ### CLI Removed `makima contract` and `makima supervisor` subcommands. Deleted `daemon/cli/contract.rs` and `daemon/cli/supervisor.rs`. Bin dispatch trimmed (~377 LOC). ### Orchestrator Removed the contract-spawn path from `phase_execution` (`spawn_step_contract` and its caller). `directive_steps.contract_type` now logs a warning and falls through to standalone-task spawn. Column itself stays — old data still reads, just no longer triggers a contract+supervisor spawn. ### TUI `Action::PerformCreateContract` is now a no-op that surfaces a status message: "Contracts have been removed. Use directives instead." The TUI form is dead code pending a wider refresh. ## Out of scope (deliberately left) * Contracts DB tables (`contracts`, `contract_repositories`, `contract_chat_history`, `contract_events`, `contract_templates`) are retained for historical data + because some peripheral code still joins to them in TaskSummary queries. * `mesh_supervisor` handlers are retained — they aren't only used by contracts (some mesh-level supervisor behaviour persists), and the cross-cutting cleanup is bigger than this PR. * `directive_steps.contract_type` column itself isn't dropped; just no longer functional. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(doc-mode): unified surface — ephemeral tasks, tmp/, /exec redirect, ↵soryu2026-05-0114-91/+1705
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* fix(doc-mode): root-walk goal serializer + roundtrip-confirmed draft drop, ↵soryu2026-04-305-43/+276
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | plus richer context menus (#114) ## The data-loss bug User reported "even after clicking Save now I have lost my doc". Two causes: 1. **GoalChangePlugin only read children[1]** — it captured edits to the single goal paragraph but silently dropped any typing that landed in the trailing paragraph below the StepsBlock (or in extra paragraphs the user had inserted). pendingGoalRef stayed at the persisted value, Save now fired empty/stale content, the doc was overwritten. 2. **fireSave dropped localStorage immediately on save success.** If the save persisted the wrong/empty content, the draft (which had the real content) was already gone — no recovery path. ## Fixes ### Capture all body content New `serializeGoalFromRoot` walks the entire root, skips only the H1 title and the StepsBlock decorator, and emits multi-paragraph markdown joined by blank lines. `GoalChangePlugin` and `fireSave` both call it now. Seed code splits an existing multi-paragraph goal back into ParagraphNodes on load. ### Read directly from the editor at save time `fireSave` now reads pendingGoalRef AND consults the live editor state via `editor.getEditorState().read()`. If anything went wrong with OnChangePlugin (which is rare, but possible — and was eating typing for many users), the save still picks up the actual document body. ### Defensive pre-save flush Before talking to the backend, `fireSave` writes the value to localStorage. If the network fails, the page closes mid-flight, or anything else goes sideways, the draft survives. ### Roundtrip-confirmed draft cleanup We no longer drop the localStorage draft inside `fireSave`. Instead a new effect watches `directive.goal` and clears the draft only when: lastSavedValueRef === directive.goal === pendingGoalRef.current i.e. only when the polled state confirms our save persisted AND the user hasn't typed anything new in the meantime. ## Question notifications respect document mode `SupervisorQuestionNotification` and `PhaseConfirmationToast` now route to `/directives/<id>?task=<taskId>` (the doc-mode surface) when the user has documentMode on AND the question carries a directiveId. Falls back to the old `/exec/:taskId` route for non-doc-mode users. ## Richer directive folder context menu In addition to start/pause/archive/delete/go-to-PR/new-draft we now expose: - Advance DAG - Plan orders - Clean up - Create / Update PR All optional callbacks; the legacy tabular UI is unaffected. ## Richer task row context menu In addition to interrupt/complete/fail/skip we now expose: - Send message — browser prompt → sendTaskMessage (same wire as the inline comment box) - Open in task page — navigates to /exec/:taskId for the full task UI (worktree diff viewer, checkpoint controls, etc.) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(directives): amendment lifecycle — inactive status, new draft, ↵soryu2026-04-3010-10/+249
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | before/after diff (#113) Stage 4 of the doc-mode revamp. Closes the loop on living-spec contracts: once a contract ships (PR raised) it becomes 'inactive', editing it kicks off an amendment cycle, the planner sees the previously-merged content as context, and "New draft" lets users abandon amendment and start the next contract on a clean slate. ## inactive lifecycle - New status `'inactive'`. Set automatically when `update_directive` detects a `pr_url` transition None → Some, alongside the revision snapshot (set_directive_inactive: idempotent, only flips active/idle/paused). - `update_directive_goal` extends its CASE flip to include 'inactive', so editing a shipped contract's goal reactivates it for the planner. - Frontend: `DirectiveStatus` gains 'inactive'; STATUS_DOT and the legacy STATUS_BADGEs (DirectiveDetail, DirectiveList) get color/label entries. Sidebar sort puts inactive after draft / before archived. ## Amendment diff to the orchestrator `build_planning_prompt` takes a new `previous_merged_revision` parameter. When set, it prepends an "AMENDMENT TO A PREVIOUSLY-MERGED CONTRACT" header that shows the merged content and the amended content explicitly, with guidance to plan a delta rather than a from-scratch rebuild. Both the planning and replanning phases call `get_latest_merged_revision` and pass it through. ## "New draft" affordance - New `repository::reset_directive_for_new_draft`: clears goal to '', status → 'draft', detaches pr_url / pr_branch / orchestrator linkage. Past revisions stay in directive_revisions as history. - New `POST /api/v1/directives/{id}/new-draft` handler. - DirectiveContextMenu surfaces "New draft" only when status === 'inactive', via an optional onNewDraft callback (legacy tabular UI doesn't have to wire it up). After reset, the page navigates to the contract so the user starts typing the next iteration immediately. ## PR-state-aware updates The user's spec — "open ⇒ update, merged ⇒ new PR, closed ⇒ new PR" — is already implemented in `build_completion_prompt`'s `gh pr view` runtime check, so no code change was needed here. The amendment cycle naturally flows through it: inactive → goal save → status flips to active → phase_replanning spawns a planner → completion task picks up the existing pr_url, sees the GitHub state, and decides update vs new PR accordingly. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(directives): per-PR revision snapshots + sidebar history (#112)soryu2026-04-308-11/+514
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Stage 3 of the doc-mode revamp. Builds the foundation for treating contracts as living specifications by freezing their content into a revision every time a PR is raised. ## directive_revisions table (new migration) (id, directive_id, content, pr_url, pr_branch, pr_state, version, frozen_at) with UNIQUE(directive_id, version) and a partial index on pr_state='open' so the next reconciler iteration can poll only what's still in flight. pr_state is constrained to 'open' | 'merged' | 'closed' to mirror GitHub's PR lifecycle. For Stage 3 we only freeze on PR creation; pr_state poll is deferred to a follow-up. ## Repository helpers - create_directive_revision: idempotent on (directive_id, pr_url) so a re-run of the orchestrator's completion task can't double-snapshot. Auto-assigns version = MAX(existing) + 1 per directive. - list_directive_revisions_for_owner: scoped through the directive join so users can only read their own contract history. - update_directive_revision_pr_state: stub for the upcoming poller. - get_latest_merged_revision: returns the most recent merged revision — this is what Stage 4 will diff against on amendments. ## Snapshot trigger update_directive handler now reads the BEFORE pr_url before the update. If pr_url transitions None → Some, it snapshots the directive's current goal as a revision tied to the new pr_url. Failures log and continue — the directive update itself is unaffected. ## API + OpenAPI GET /api/v1/directives/{id}/revisions returns DirectiveRevisionListResponse (revisions newest-first). Schemas registered in OpenAPI. ## Frontend: revisions/ subfolder + read-only viewer Each contract folder now has a third subfolder ("revisions/") that lazily fetches and lists past revisions when the parent directive folder is open. Empty contracts skip the subfolder entirely so brand-new ones aren't cluttered. Each row shows v<N>.md plus a small pill ('open'/'merged'/ 'closed'). Selecting a revision encodes itself into the existing ?task= param as "revision:<id>", so EditorShell can route between the live task stream (realTaskId), the read-only RevisionViewer (revisionId), or the editor itself (neither). The viewer renders the frozen markdown verbatim with a deep-link to the PR — these are immutable historical records, not edit surfaces. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(doc-mode): rename surfaced label "Directive" → "Contract" (#109)soryu2026-04-303-30/+37
| | | | | | | | | | | | | | | | | | Stage 2: cosmetic UI rename only. Database tables, API paths, hook names, and CLI commands all stay as 'directive' for now — we'll phase out the existing standalone /contracts table later. Surface changes: - Sidebar header "Documents" → "Contracts"; root folder "directives/" → "contracts/"; empty state "No directives yet" → "No contracts yet". - Editor placeholders, breadcrumb header, "back to document" → "back to contract", right-click menu header. - NavStrip: when documentModeEnabled is on, the "Directives" link renders as "Contracts" (href stays /directives so links don't break). - Save bar message "saving will replan the directive" → "the contract". No backend changes — directive.goal etc. all still work the same. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(doc-mode): autosave robustness, draft→active flip, save-now, sidebar ↵soryu2026-04-304-40/+435
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | context menus (#108) Stage 1 of the planned doc-mode revamp — bug fixes + UX polish ahead of the larger contract-revisioning architecture work. ## Backend: 'draft' included in goal-update status flip repository::update_directive_goal previously flipped only idle/paused → active on a goal save, leaving 'draft' alone. That meant brand-new directives got their goal persisted on save but never spawned a planner — exactly the "orchestrator never runs" report. Extended the CASE clause so 'draft' also flips to 'active' on save. The status remains visible to users; this just makes the implicit "first goal save = start" behaviour work end-to-end. ## Autosave robustness (DocumentEditor.tsx) The synchronous-write fix from the previous PR was correct in principle but not visible enough for users to confirm it was working, and could still drop the very last edit on an abrupt tab close. This change: - Adds beforeunload / pagehide / visibilitychange handlers that synchronously flush pendingGoalRef → localStorage (skipping if it matches the persisted value). Backed by a persistedGoalRef that tracks directive.goal in real time so the handler doesn't capture a stale closure. - Tracks the timestamp of every successful draft write (draftSavedAt) and surfaces it as a "Draft saved Ns ago" stamp in the bar — refreshed on a 1Hz ticker so users can SEE the autosave is alive. - Logs a console.warn on localStorage write failure (was silently swallowed) so quota / storage-disabled environments are diagnosable. ## Always-visible save bar + Save now button The bar now renders in every state (was hiding when idle/pending-with-time- remaining). Idle shows a quiet "Up to date." Pending outside the last 10s shows "Unsaved changes — auto-save soon." Save now is always present; disabled only when truly idle. ## EXEC and CONTRACTS hidden in document mode NavStrip filters Contracts and Exec links when settings.documentModeEnabled is true. Those areas are subsumed by the directive-document interface; the nav strip stops surfacing them so document mode users have one canonical place to work. ## Right-click context menus on sidebar Right-clicking a directive folder header opens DirectiveContextMenu with start / pause / archive / delete / Go-to-PR — same component the legacy list page uses. Right-clicking a task row inside the tasks/ subfolder opens a smaller TaskContextMenu with Interrupt (for orchestrator/completion/ running steps) and Mark complete / failed / skipped (for step rows). Step lifecycle calls require the directive_step.id, so FolderTaskRow now carries stepId alongside taskId. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(document-mode): folder layout v2, glow on pending, inline formatting, ↵soryu2026-04-302-96/+479
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | autosave fix (#107) ## Autosave bug fix (top priority) The 250ms debounce on the localStorage draft write was racing the unmount cleanup: typing then navigating within 250ms cleared the pending timer *before* it flushed, which is exactly when we needed the draft saved. Drafts are now written synchronously on every keystroke. localStorage .setItem on a small string is sub-millisecond — the debounce was a premature optimisation. ## Sidebar v2 (document-directives.tsx) - Tasks now live in a `tasks/` subfolder inside each directive folder (orchestrator, completion, and started step tasks). The pinned `.md` document remains at the top of the directive folder. - Status circles moved to the RIGHT side only (previously rendered on both sides, which the user found noisy). - New `StatusDot` component composes the status colour with two optional modifiers: a "live" pulse when the orchestrator is running, and a GLOW (amber ring + pulse) when there is a pending user question for that directive or task. The glow is sourced from the existing SupervisorQuestionsContext, indexed by `directiveId` and `taskId`. - New `TaskIcon` (terminal) and `CompletionIcon` (PR-bracket) so orchestrator/step/completion entries look distinct from the .md file. ## Inline formatting in the editor (DocumentEditor.tsx) - New `MarkdownShortcutPlugin` (scoped to TEXT_FORMAT_TRANSFORMERS only) so typing `**foo**`, `*foo*`, `` `foo` ``, `~~foo~~` auto-formats inline. Block-level shortcuts (# heading, - list) are intentionally excluded so the document shape (H1 / goal / StepsBlock / trailing para) stays intact. - New `FloatingFormatToolbar` appears above any non-collapsed selection inside the goal paragraph, with B / I / U / S / </> buttons that dispatch FORMAT_TEXT_COMMAND. Buttons highlight when the corresponding format is active. Standard ⌘B / ⌘I / ⌘U keyboard shortcuts also work via the existing RichTextPlugin. - Round-trip via a small inline-only markdown serializer/parser so formatting persists across saves. Supported markers: `\``code\``, `***bold-italic***`, `**bold**`, `*italic* / _italic_`, `~~strike~~`. Underline survives within the editor session (toolbar / shortcut) but has no markdown syntax so it does not round-trip — by design. - No backend schema change: `directive.goal` is still a TEXT column, it just contains inline markdown now. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(directive): cancel orphaned planner and kick reconciler on goal update ↵soryu2026-04-304-12/+149
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (#104) Resolves the user-visible bug where editing a directive's goal mid-flight shows "saved" but does not actually replan: the running planner kept emitting add-step calls based on the OLD goal while a fresh planner was supposed to take over, and the user had to wait up to 15s for the next reconciler tick before any replanning even started. ## What was happening PUT /api/v1/directives/{id}/goal already had two paths: - Small change + planner running → SendMessage interrupt + KEEP orchestrator. - Everything else → clear orchestrator_task_id and let phase_replanning spawn a new planner on the next 15s tick. The "everything else" path cleared the directive's pointer to the planner task but never cancelled the task itself. The task kept executing and could race the new planner by adding more steps from the stale plan. Worse, those new steps could push MAX(steps.created_at) past the just-bumped goal_updated_at, suppressing phase_replanning entirely. ## Fix 1. New helper `try_cancel_running_planner()` (orchestration/directive.rs): sends `InterruptTask { graceful: true }` to the daemon owning the orchestrator task and marks the task `interrupted` in the DB. All errors are logged and swallowed so the goal update still completes. 2. update_goal handler calls the helper whenever it is about to take the "clear orchestrator_task_id" branch, so the orphaned planner stops producing stale-plan steps before its DB linkage is cut. 3. New `AppState::directive_kick` (tokio::sync::Notify) lets the handler signal the reconciler to run a tick immediately. The reconciler loop in server/mod.rs now selects between its 15s interval and the notify, so the user no longer waits up to 15s after editing a goal before replanning actually starts. update_goal calls `kick_directive_reconciler()` after the goal is persisted (both paths). ## Why not also loosen `get_directives_needing_replanning` The query already covers the common cases once the orphan-cancel lands — without a still-running orphan adding fresh steps, goal_updated_at reliably exceeds MAX(steps.created_at) after a goal edit. Loosening the predicate risked spurious replans for directives that legitimately have no steps yet (those are handled by `phase_planning`). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(document-mode): longer goal save countdown, per-directive folders, live ↵soryu2026-04-303-185/+939
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>
* fix(ci): regenerate pnpm-lock.yaml for lexical deps added by #101 (#102)soryu2026-04-301-1623/+1711
| | | | | | | | | | | PR #101 added @lexical/* and lexical to makima/frontend/package.json but did not refresh the lockfile, breaking CI installs that run with the default --frozen-lockfile setting. Regenerated via `pnpm install --no-frozen-lockfile` and verified `pnpm install --frozen-lockfile` now resolves cleanly. `npx tsc --noEmit` also passes. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: document-mode directive UI proof of concept (Lexical) (#101)soryu2026-04-2917-21/+2626
| | | | | | | | | | | * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Backend: feature flag + goal-edit interrupt messaging * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Frontend: Lexical document editor with step blocks, context menu, countdown
* revert PRs #93-#98; enforce strict-linear-DAG + mandatory directive verify ↵soryu2026-04-2825-1784/+514
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (#100) * revert: roll back PRs #93-#98 to pre-Lexical baseline Reverts the entire chain of directive document UI work and the homepage redesign, restoring the working tree to the state at 3679ceb (before c8b169d / PR #93). PRs reverted: - #93 c8b169d feat: Document UI for directive orchestration with Lexical editor - #94 d6f01a6 fix: compilation error and warnings already merged via PR #93 - #95 5aa3faf fix: resolve compilation error and warnings in Rust backend - #97 d513f93 feat: document UI with contract blocks, expandable logs, and interaction controls - #96 6366941 feat: Redesign homepage with professional PC-98 styling - #98 d1fdfb1 feat: revert broken directive PRs, re-implement Lexical document orchestrator The directive Document UI experiments produced fragile output and merge artifacts; follow-up commits in this PR change orchestration to favor strictly linear DAGs and add goal/conflict verification so future runs do not require this kind of cleanup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(directive): strict-linear-DAG planning + mandatory `directive verify` Tightens directive orchestration so the final PR almost never needs a hand-merge: 1. Planning prompts now strongly bias toward strictly linear DAGs. Parallel steps are reserved for genuinely independent work (e.g. disjoint modules); the default for "in doubt" is sequential. Linear chains inherit each previous step's worktree, so the final merge is typically just a rebase against the base branch. 2. New CLI command `makima directive verify` does a local in-memory `git merge-tree` of HEAD against `<remote>/<base>` and exits non-zero with a list of conflicting files if the PR would not merge cleanly. Pure-local — no API call, no working-tree mutation. 3. Completion / PR-creation prompts now mandate three pre-push checks: a. build (`cargo check` and/or `tsc --noEmit`), b. `makima directive verify --base <base_branch>` must exit 0, and c. an explicit goal-alignment self-check against the diff. The orchestrator is told NOT to push, create the PR, or call `makima directive update` until all three pass. Skipping any of them is documented as a directive failure. The combination means that with a linear DAG the final PR-creation task should almost never see a real conflict — when it does, that is treated as a planning bug to escalate rather than something to paper over with `-X theirs`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(frontend): TS errors pre-existing on master - TaskSlideOutPanel: declare missing `selectedFileDiff` / `selectedFilePath` state hooks that were referenced everywhere but never created, and re-balance the JSX so the `<>...</>` fragment in the non-diff branch is closed (the previous indentation/braces would not parse). - api.ts: add a `getWorktreeDiff` thin wrapper around `getTaskDiff` so TaskDetail's per-file click handler type-checks (the per-file slice is a future improvement; today both return the full task diff). - WorktreeFilesPanel: remove unused `isClickable` local; the gating already reads `onFileClick` directly inline. Run after revert: `npx tsc --noEmit` exits 0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: revert broken directive PRs, re-implement Lexical document ↵soryu2026-04-2849-4430/+385
| | | | | | | | | | | | | | | orchestrator (#98) * feat: soryu-co/soryu - makima: Revert broken directive PRs and verify clean build * feat: soryu-co/soryu - makima: Re-implement frontend: Lexical document editor with feature flag and base components * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Add contract blocks, expandable log rows, and interaction controls * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: End-to-end build verification and integration polish
* feat: Redesign homepage with professional PC-98 styling (#96)soryu2026-04-284-170/+525
| | | | | | | * feat: soryu-co/soryu - soryu: Redesign landing page layout and header for professional style * feat: soryu-co/soryu - soryu: Restyle CSS for professional landing page * feat: soryu-co/soryu - soryu: Integrate and polish landing page styles with component
* feat: document UI with contract blocks, expandable logs, and interaction ↵soryu2026-04-2818-60/+1819
| | | | | | | | | | | | | | | | | | | | | controls (#97) * feat: soryu-co/soryu - makima: Rename tasks to contracts in directive API and types * feat: soryu-co/soryu - makima: Add contract interaction panel with comment and interrupt * feat: soryu-co/soryu - makima: Build expandable contract log feed in StepsDiagram * feat: soryu-co/soryu - makima: Rename tasks to contracts throughout document UI and add contract block support * feat: soryu-co/soryu - makima: Add comment and interrupt controls to expanded step log feed * feat: soryu-co/soryu - makima: Audit and fix Document UI feature flag visibility and missing implementations * feat: soryu-co/soryu - makima: Add expandable step rows with live log feed in StepsDiagram * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Integrate all document UI components and final polish
* fix: resolve compilation error and warnings in Rust backend (#95)soryu2026-04-2813-62/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | | * fix: resolve compilation error and warnings in Rust backend - Fix syntax error in directive.rs phase_replanning (bad merge created duplicate code blocks with broken `.await {` syntax) - Remove unused imports: WorktreeError, DaemonReauthStatus, ratatui::prelude - Prefix unused variables with underscore: claude_command, content, owner_id - Suppress unused_assignments warning on final_exit_code - Add #[allow(unused_imports)] for cfg(unix) CommandExt imports Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * WIP: heartbeat checkpoint * fix: suppress remaining compiler warnings for clean build - Add #[allow(dead_code)] for unused but intentionally kept functions - Remove useless self-assignments in listen handler - Fixes: truncate_string, checkout_commit, handle_get_worktree_diff, default_max_retries, STREAM_CHUNK_MS, listen(), MessageResponse.role Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: compilation error and warnings already merged via PR #93 (#94)soryu2026-04-280-0/+0
| | | | | | The step branch fixes were already merged into master. This PR tracks the directive for deploy verification. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: Document UI for directive orchestration with Lexical editor (#93)soryu2026-04-2831-16/+3539
| | | | | | | | | | | | | | | * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Save previous goal on update and include history in re-planning prompt * feat: soryu-co/soryu - makima: Install Lexical and create base document editor component * feat: soryu-co/soryu - makima: Create directive file system sidebar and document layout * feat: soryu-co/soryu - makima: Create custom Lexical step diagram block * feat: soryu-co/soryu - makima: Add context menu and goal auto-update integration * WIP: heartbeat checkpoint
* feat: soryu-co/soryu - makima: Fix build errors in daemon protocol and task ↵v0.5.0soryu2026-03-104-0/+62
| | | | manager (#89)
* feat: worktree diff/commit endpoints and frontend diff viewing (#88)soryu2026-03-0912-60/+955
| | | | | | | | | | | | | * feat: soryu-co/soryu - makima: Fix worktree info failing when origin ref is missing * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Add worktree commit endpoint and diff endpoint for regular users * feat: soryu-co/soryu - makima: Add frontend diff viewing with clickable worktree files
* Merge pull request #87 from ↵soryu2026-03-098-58/+535
|\ | | | | | | | | soryu-co/makima/directive-soryu-co-soryu---makima-19fd3e1d-v1772943648 feat: compact order header & add context menus to orders/directives
| * fix: resolve merge conflicts with master (integrate DOG features into ↵makima/soryu-co-soryu---makima--resolve-merge-conflicts-i-f750d00dsoryu2026-03-0918-26/+1603
| |\ | |/ |/| | | | | | | | | | | | | | | | | | | | | compact header) - Resolved conflict in OrderDetail.tsx: kept PR compact header layout with inline badges while adding DOG badge from master - DOG selector in Actions section preserved from master - orders.tsx correctly passes dogs prop to OrderDetail (auto-merged correctly) - directives.tsx auto-merged correctly with DOG props for DirectiveDetail - Frontend builds successfully with no TypeScript errors Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* | Merge pull request #86 from ↵soryu2026-03-0717-25/+1609
|\ \ | | | | | | | | | | | | soryu-co/makima/directive-soryu-co-soryu---makima-19fd3e1d-v1772803139 feat: filter contract phase orbs by type & add DOGs (directive order groups)
| * | WIP: heartbeat checkpointmakima/directive-soryu-co-soryu---makima-19fd3e1d-v1772803139soryu2026-03-075-13/+542
| | |
| * | feat: soryu-co/soryu - makima: Add DOG frontend types, API client, and hookssoryu2026-03-072-0/+196
| | |
| * | feat: soryu-co/soryu - makima: Add DOG database schema and backend CRUDsoryu2026-03-074-2/+597
| | |
| * | WIP: heartbeat checkpointsoryu2026-03-074-3/+259
| | |
| * | feat: soryu-co/soryu - makima: Filter phase orbs by contract type in ↵soryu2026-03-073-7/+15
|/ / | | | | | | PhaseProgressBar
| * Merge remote-tracking branch ↵soryu2026-03-083-4/+245
| |\ | | | | | | | | | 'origin/makima/soryu-co-soryu---makima--add-right-click-context-m-6bf81c58' into makima/directive-soryu-co-soryu---makima-19fd3e1d-v1772943648
| | * feat: soryu-co/soryu - makima: Add right-click context menu to directives pagemakima/soryu-co-soryu---makima--add-right-click-context-m-6bf81c58soryu2026-03-073-4/+245
| |/ |/|
| * Merge remote-tracking branch ↵soryu2026-03-083-1/+247
| |\ | | | | | | | | | 'origin/makima/soryu-co-soryu---makima--add-right-click-context-m-f42926a8' into makima/directive-soryu-co-soryu---makima-19fd3e1d-v1772943648
| | * feat: soryu-co/soryu - makima: Add right-click context menu to orders pagemakima/soryu-co-soryu---makima--add-right-click-context-m-f42926a8soryu2026-03-073-1/+247
| |/ |/|
| * feat: soryu-co/soryu - makima: Compact the order page header displaymakima/soryu-co-soryu---makima--compact-the-order-page-he-b2c2cc2csoryu2026-03-071-40/+37
|/