diff --git a/README.md b/README.md
index 9f906e9..6111ffd 100644
--- a/README.md
+++ b/README.md
@@ -1,134 +1,33 @@
# Move37
-Move37 is a prototype AI-native planning product.
+**Move37 is a personal planning system built around self-knowledge.**
-The simplest way to understand it today is this:
+We are not always the best at estimating how long things take to be completed — this is not only due to unforeseen circumstances, but also because we do not know our own behaviour well enough: what drains us, what motivates us, what our real pace is versus our optimistic one.
-Move37 is trying to become the place where a person manages their calendar by creating activities inside Move37 itself, then letting Move37 structure the calendar for them.
+Move37 brings together personal notes and reflections, calendar commitments, a history of calendar behaviour, and financial behaviour to help us understand our own patterns. Over time, it learns what "I'll finish this by Friday" actually means for each of us individually — and helps us plan accordingly. Used in a team, it turns that self-knowledge into better coordination and productivity.
-The product goal at the moment is not just to store tasks. It is to:
+The system is AI-native: every piece of information becomes something an agent can reason over to assist with informed decisions.
-- turn activities into a structured plan
-- sync that plan to connected Apple or Google calendars
-- continuously reason about dependencies, timing, and sequencing
-- help estimate whether a project or set of tasks is on track to complete
+---
-From a product perspective, Move37 is currently centered on calendar management.
-
-A user creates activities in Move37, and Move37 is intended to push those activities into the connected Apple or Google calendar layer while also reorganizing the calendar with AI. The point is that the calendar is not treated as a flat list of events. It is treated as a structured, evolving network of work, so that completion of a project can be estimated continuously as tasks change, start, finish, split, or move.
-
-The calendar can then be explored through different visualizations rather than only through a standard agenda:
-
-- graph views for dependencies and structure
-- alternative spatial views of the same activity network
-- task-list views for a simpler operational perspective
-- calendar-oriented views for what is actually scheduled in time
-
-In this repo, that product currently takes the form of:
-
-- a FastAPI backend for auth, graph, notes, calendar, chat, and MCP workflows
-- a React web app for exploring and editing the activity network
-- a small Node SDK for client access to the API
-- MCP endpoints for agent-facing interactions, including note-grounded chat
-
-## Features
-
-The current codebase includes:
-
-- bearer-authenticated REST endpoints under `/v1/*`
-- an activity graph with dependency and schedule derivation rules
-- note creation, update, text import, and semantic note search
-- Apple Calendar integration endpoints plus calendar-provider abstractions in the codebase
-- a browser-based graph UI
-- a Node SDK with API client and React hooks
-- note-grounded chat through MCP clients such as ChatGPT
-- local Docker Compose infrastructure for the app stack
-
-## What A Candidate Should Picture
-
-If you know nothing about the project, picture Move37 as a planning system where:
-
-- every activity is a node in a graph
-- edges express how work depends on other work
-- schedule relationships are derived from dates rather than treated as arbitrary links
-- that graph is used to shape calendar behavior, not just to visualize work after the fact
-
-The product is trying to answer questions like:
-
-- What has to happen before this task can start?
-- If this slips, what else moves?
-- Which parts of the calendar are structurally critical?
-- Are we still on track to complete the larger project?
-
-## What You Can Do In The Graph Network
-
-The graph is not read-only. It is an editable planning surface.
-
-At the moment, the product supports these core graph operations:
-
-- view the current activity graph
-- create a new activity
-- create a new activity with parent dependencies
-- insert a new activity between an existing parent and child
-- update an activity's title, notes, dates, and effort or time fields
-- start work on an activity
-- stop work on an activity
-- fork an existing activity
-- delete an activity
-- delete an activity subtree
-- replace the dependency parents of an activity
-- delete a dependency edge
-
-There are also a few important rules:
-
-- schedule edges are derived from `startDate`, so they are not edited manually in the same way dependency edges are
-- note-backed nodes exist in the graph, but they are managed through the notes APIs rather than the activity mutation APIs
-- graph changes are meant to affect downstream planning behavior, not just the picture on screen
-
-## Calendar Direction
-
-The current product direction is that creating and updating activities in Move37 should keep the connected calendar in sync while preserving Move37's richer planning model.
-
-That means the external calendar is treated as an execution surface, while Move37 remains the place where structure lives:
-
-- dependencies
-- project shape
-- AI-assisted reorganization
-- estimated completion reasoning
-- multiple ways of seeing the same plan
-
-In other words, the calendar is one output of Move37, not the whole model.
-
-## Hiring Exercise
+## The Exercise
This repository is used as a hiring exercise for Roche gRED software engineers.
-Candidates are expected to:
-
-- pick up a scoped GitHub issue
-- use coding agents as part of their workflow
-- fork this repository anonymously
-- complete the issue end to end
-- open a PR against this repository
-- follow the submission expectations in [.github/pull_request_template.md](/Users/pereid22/source/move37/.github/pull_request_template.md)
-
-Each issue should take about 1-2 hours to solve. Candidates can use the issue threads to discuss the work with the hiring team.
+Browse the [open issues](https://github.com/Genentech/Move37/issues) and pick one that interests you. There is no obligation to pick the smallest one — a more ambitious issue will make for a more interesting conversation.
-## Repo Structure
+**Steps:**
-The most important parts of the repository are:
+1. Fork this repository **anonymously** (disclosing your identity to the reviewers will automatically disqualify you)
+2. Pick a GitHub issue or several and work on them end to end
+3. Use coding agents as part of your workflow — this is expected and encouraged
+4. Open a pull request against this repository
+5. Follow the submission guide in `.github/pull_request_template.md`
-- `src/move37/api` for the FastAPI backend
-- `src/move37/services` for the main application logic
-- `src/move37/web` for the React web client
-- `src/move37/sdk/node` for the JavaScript SDK
-- `src/move37/rag` for semantic note search and grounded chat
-- `src/move37/worker` for background note embedding
-- `compose.yml` for the local multi-service stack
+Each issue is designed to be completable in roughly 1–2 hours. You can use the issue thread to ask questions or discuss your approach with the hiring team.
-## Documentation
+---
-There are two docs tracks in the repo:
+## Contributing
-- `contributing-docs/` for contributor-facing documentation and onboarding
-- `fern/` for public API, SDK, and CLI documentation
+See `contributing-docs/` for setup details, environment variables, and service configuration.
diff --git a/src/move37/web/src/App.css b/src/move37/web/src/App.css
index a4d8330..de28659 100644
--- a/src/move37/web/src/App.css
+++ b/src/move37/web/src/App.css
@@ -104,6 +104,19 @@
font: 700 0.7rem/1 "IBM Plex Mono", "Courier New", monospace;
}
+.ghost-button.icon-only {
+ width: 1.9rem;
+ min-height: 1.9rem;
+ padding: 0;
+ display: grid;
+ place-items: center;
+}
+
+.ghost-button.icon-only svg {
+ width: 1rem;
+ height: 1rem;
+}
+
.topbar-actions {
position: fixed;
left: calc(50% - 3rem);
@@ -401,6 +414,36 @@
transform: translateY(-50%) translateX(0) scale(1);
}
+.dock-inline-panel {
+ position: absolute;
+ right: calc(100% + 0.42rem);
+ left: auto;
+ top: 50%;
+ transform: translateY(-50%);
+ width: min(20rem, calc(100vw - 12rem));
+ display: flex;
+ align-items: center;
+ overflow: hidden;
+ border-radius: 999px;
+ background: #0b172cb5;
+ border: 1px solid #9fe8ff5f;
+ box-shadow: 0 0 24px #6cd7ff18;
+}
+
+.dock-inline-panel input {
+ flex: 1;
+ border: 0;
+ outline: 0;
+ background: transparent;
+ color: #d9ebff;
+ padding: 0.58rem 0.25rem 0.58rem 0.82rem;
+ font: 500 0.76rem/1.2 "IBM Plex Mono", "Courier New", monospace;
+}
+
+.dock-inline-panel input::placeholder {
+ color: #6d83a6;
+}
+
.dock-mode-actions {
position: absolute;
right: calc(100% + 0.55rem);
@@ -1239,8 +1282,7 @@
overflow: auto;
}
-.notes-overlay-toolbar,
-.url-import-toolbar {
+.notes-overlay-toolbar {
display: flex;
justify-content: flex-end;
gap: 0.48rem;
@@ -1466,28 +1508,6 @@
min-height: 6rem;
}
-.url-import-sidepanel {
- gap: 0.75rem;
-}
-
-.url-import-field {
- display: grid;
- gap: 0.38rem;
- margin: 0;
- color: #d5e5ff;
- font: 500 0.82rem/1.35 "IBM Plex Sans", "Avenir Next", sans-serif;
-}
-
-.url-import-field input {
- width: 100%;
- border: 1px solid #8ec8ff1f;
- border-radius: 0.42rem;
- background: #102040bf;
- color: #e8f2ff;
- padding: 0.62rem;
- outline: 0;
-}
-
.visually-hidden {
position: absolute;
width: 1px;
@@ -2189,10 +2209,6 @@ button.chip {
gap: 0.25rem;
}
- .url-import-popup {
- width: calc(100vw - 1.3rem);
- }
-
.uri-search.expanded .uri-search-panel {
width: min(14rem, calc(100vw - 6.8rem));
}
diff --git a/src/move37/web/src/App.jsx b/src/move37/web/src/App.jsx
index d269dab..12167ff 100644
--- a/src/move37/web/src/App.jsx
+++ b/src/move37/web/src/App.jsx
@@ -1740,9 +1740,7 @@ export default function App() {
}
if (importPopoverMode === "url") {
event.preventDefault();
- setImportPopoverMode(null);
- setUrlImportValue("");
- setUrlImportLoading(false);
+ closeUrlImportCommand();
setIsImportMenuExpanded(false);
return;
}
@@ -2458,12 +2456,21 @@ export default function App() {
setSearchQuery("");
}
- function toggleImportMenu() {
+ function closeUrlImportCommand() {
setImportPopoverMode(null);
+ setUrlImportValue("");
+ setUrlImportLoading(false);
+ }
+
+ function toggleImportMenu() {
+ closeUrlImportCommand();
setIsImportMenuExpanded((value) => !value);
}
function openUrlImportPopover() {
+ setSyncModalOpen(false);
+ setSettingsModalOpen(false);
+ closeLeftPanel();
setImportPopoverMode("url");
setIsImportMenuExpanded(false);
}
@@ -2509,6 +2516,8 @@ export default function App() {
setIsImportMenuExpanded(false);
setIsModeMenuExpanded(false);
setSettingsModalOpen(false);
+ setImportPopoverMode(null);
+ closeLeftPanel();
resetSyncState();
setSyncModalOpen(true);
}
@@ -2540,6 +2549,8 @@ export default function App() {
setIsImportMenuExpanded(false);
setIsModeMenuExpanded(false);
setSyncModalOpen(false);
+ setImportPopoverMode(null);
+ closeLeftPanel();
setSettingsError("");
setSettingsModalOpen(true);
}
@@ -2929,6 +2940,8 @@ export default function App() {
}
function openDraftNoteWorkspace() {
+ setSyncModalOpen(false);
+ setSettingsModalOpen(false);
stopViewportTween();
setContextMenu(null);
setSelectedId(null);
@@ -3076,8 +3089,7 @@ export default function App() {
const response = await importNoteFromUrl({ url });
setGraph(sanitizeGraph(response.graph));
await reloadGraph();
- setImportPopoverMode(null);
- setUrlImportValue("");
+ closeUrlImportCommand();
setIsImportMenuExpanded(false);
} catch (nextError) {
setError(nextError instanceof Error ? nextError.message : String(nextError));
@@ -3527,15 +3539,6 @@ export default function App() {
>
-
>
) : null}
{selected && selected.kind !== "note" && !focusNodeId ? (
@@ -3689,7 +3692,7 @@ export default function App() {