Plan · Code Raven · 1 September 2026 · implemented, awaiting manual testing

Personal Workspace

A default workspace for light coding, loose ideas, and AI conversations that aren't attached to a project. Same object model as a project, different verbs on top of it.

69Tasks
7Phases
10→5Widgets
1New enum
13Yours to test
The gist

Personal is a real project on disk with a real .claude/ tree, seeded automatically, distinguished from other projects by one enum and a different dashboard composition. Phases 1–5 make it usable for capture and conversation. Phase 6 adds Pursuits — named personal interests that group notes the way a Claude Project does.

The problem

There is nowhere in CodeRaven for work that isn't a codebase. Ideas about a room redesign, a hobby, or a small script with no repo either get filed into an unrelated project or never get written down. The Project Overview grid also renders ten widgets, most of which mean nothing without a codebase: a plan pipeline with no plans, blueprints with no architecture.

Approach

A real project on disk, not a pathless special case

Project.path is a non-optional let, and projectPath appears in 1,548 places. Giving Personal a real folder at ~/Documents/Code Raven/Personal means every store, importer and bridge works untouched. Every bridge importer on the activate scan reads only under .claude/, so a folder with nothing but .claude/ and a CLAUDE.md is fully compatible.

It differs by verb, not by object

A Note in Personal is the same ScratchNote, in the same store, with the same Move to Project support. Only the action on it changes. Widgets whose sole verb is plan-shaped come out entirely, which takes the grid from ten widgets to five.

Personal lives inside ProjectOverviewView

The overview host owns the tab bar, context row, meeting sheets, deep-link handlers and per-project tab persistence. A sibling PersonalOverviewView would duplicate all of it. The grid function branches on project.kind; the host stays one file.

Profile is the Developer Dossier, finally surfaced

The Dossier is already app-global and portable, and its only compact surface today reads the legacy profile. Personal's Foundation slot gives the Dossier proper a home instead of asking the same questions twice.

Decisions made for you

Judgment call

Notes and Tasks are one list in Personal

QuickTask already carries sourceNoteId and convertedToNoteId — bidirectional conversion already exists, which is what gets built when two types are nearly the same thing. In a project the split holds because a Note becomes a plan and a Task gets dispatched. In Personal there are no plans. ScratchNote is the base so the widget keeps its name. Reversible by re-adding TasksWidget to the grid.

Correction to the outline

No new isDone flag

ScratchNote already has isCompleted and completedAt, toggled by the leading checkbox in NotesWidget.noteRow and consumed by noteStatus, ScratchpadStats and the widget's derived-notes pass. A second done flag would split completion across two fields. The Personal list uses the existing checkbox as-is.

Judgment call

No Workflow Pipeline, and no plans from Personal notes

The pipeline is seven stages built on plan → checkin → complete → align and would render permanently empty. Light coding is still served: a Personal note dispatches straight to Claude Code through a new NotePlanningPromptBuilder variant that asks for the work, presented with isPlanning: false so the plan guardrails and the plan monitor never arm.

Judgment call

Personal experts answer in meetings and through Mira, and nowhere else

Expert output has two writers into the triage queue: FindingsIngestor for in-app runs and AgentFindingsBridgeImporter for CLI runs. Both get a kind guard, plus MeetingFlagBridgeImporter. What remains is the meeting transcript and MiraService.brokerExpert, which already appends an attributed conversation turn and never touches FindingsStore.

Judgment call

Seed path is ~/Documents/Code Raven/Personal

Finder-visible and covered by iCloud Desktop & Documents sync, so a future phone-side capture Shortcut can reach it. The app is not sandboxed, so this is a one-time macOS Documents prompt rather than an entitlement problem, and agent_metadata.json already lives in ~/Documents. Reversible in setup step one.

Judgment call

Personal keeps the Mockups tab

A room redesign is a mockup use case, and Mockup Lab only needs a docs/mockups folder. Feature Lab and Reports are hidden because both are Foundation-shaped. Reversible in the tab filter.

Judgment call

Pursuits get no status enum

Active or archived, everything else inferred from last touch. Plan status already has six cases overlapping PipelineStage's seven and BannerPhase's eighteen. A fourth vocabulary would repeat that.

The work

Phase 1 — Model, seeding and manager accessors

9 tasks Landed 2026-09-01. One enum, one seeder, two accessors.
  • Add enum ProjectKind: String, Codable { case project, personal } in Code Raven/Models/Project.swift beside ProjectStatus, with displayName and isPersonal helpers
  • Add let kind: ProjectKind to Project, append kind to CodingKeys (Project.swift:460), and add a kind: ProjectKind = .project parameter to the memberwise init (Project.swift:407)
  • Decode kind inside Project's existing init(from:) using decodeIfPresent with a .project default (Project.swift:464)
  • Add personalProject and codeProjects computed accessors to ProjectManager, and make sidebarProjects return only code projects (Project.swift:579)
  • Extend addProject(name:path:bookmarkData:) with a kind: parameter that skips the NavigateToFoundation post and the getGitRemote lookup for .personal (Project.swift:633)
  • Add PersonalWorkspaceSeeder.runIfNeeded() in Code Raven/Services/ that creates ~/Documents/Code Raven/Personal, writes a starter CLAUDE.md describing the workspace, and registers it via addProject(kind: .personal)
  • Make the seeder idempotent: adopt an existing folder without error, and skip registration when personalProject already exists
  • Seed Personal once for the existing install behind a UserDefaults migration flag personalWorkspaceSeededV1, called first in the launch migration block (Code_RavenApp.swift:226)
  • Confirm ProjectCommandManager.templateCommands(for:) has no callers, so Personal receives no default xcodebuild commands and nothing needs skipping (ProjectCommandManager.swift:302)

Phase 2 — Sidebar and routing

5 tasks Landed 2026-09-01. Sidebar, row badges, tab filter.
  • Add a Workspace section above Projects in the sidebar and render Personal in it, reusing the inline header pattern at AppMainView.swift:441 and showing only when personalProject is non-nil
  • Suppress the foundation, plan-count, git and stale badges in ProjectSidebarRow when project.kind == .personal (AppMainView.swift:1347)
  • Hide the Remove action for Personal in ProjectSidebarRow's context menu; keep Reveal in Finder (AppMainView.swift:1398)
  • Filter ProjectTabBar tabs by kind: Personal shows Overview, Meetings, Chronicle, Mockups and Usage, hiding Feature Lab and Reports (ProjectTabBar.swift:13)
  • Route sidebar selection of Personal through the existing selectProject path so switchToProject and .projectOverview(project) work unchanged (AppMainView.swift:1042)

Phase 3 — Exclude Personal from git, build and code-analysis surfaces

8 tasks Landed 2026-09-01. Kind guards at existing chokepoints.
  • Guard GitCommitWatcher.registerProject and SmartTriggerService.registerProject to return early for .personal (GitCommitWatcher.swift:266, SmartTriggerService.swift:75)
  • Filter .personal out of ProjectGitCache.register(projects:) so the 60s poll never spawns git for it (ProjectGitCache.swift:57)
  • Guard the overview's 30s git timer, checkGitRepository() and gitStatusIndicator on kind in ProjectOverviewView (ProjectOverviewView.swift:684, :1237, :1929)
  • Pick the first code project instead of currentProject ?? projects.first for BlueprintMaintenanceAgent.triggerAfterBridgeImport (Code_RavenApp.swift:443)
  • Return nil drift from MiraDriftScanner for .personal so segment openings do not run git diff (MiraDriftScanner.swift:118)
  • Skip .personal in FindingsIngestor.ingestLatestReport, AgentFindingsBridgeImporter.scanAllProjects and MeetingFlagBridgeImporter so Personal expert output never reaches the triage queue (FindingsIngestor.swift:50, AgentFindingsBridgeImporter.swift:55)
  • Use codeProjects in MorningDashboard, the Portfolio views and SyncStatusIndicator so Personal does not appear in cross-project code metrics
  • Hide MilestonePopover in ProjectContextRow for .personal (ProjectContextRow.swift:107)

Phase 4 — Personal overview composition

10 tasks Landed 2026-09-01. The five-widget grid and the Profile widget.
  • Build the Personal overview with a five-widget grid: Notes, Profile, Experts, Documents, Chronicle — as a personalWidgetGrid(isCompact:) branch in ProjectOverviewView.widgetGrid (ProjectOverviewView.swift:876)
  • Hide JourneyRailView, ProjectOverviewBriefingBanner, DispatchHomeBanner and ReferenceDocsWidget on the Personal overview; keep UnifiedQuickCapture (ProjectOverviewView.swift:706)
  • Rename the Foundation widget to Profile in Personal and back it with the Developer Dossier — a new ProfileWidget in Code Raven/Views/Dashboard/ built on DashboardWidgetFrame and reading DossierStore.shared
  • Show contract approval state, working-rule count, creative-brief presence and the userIdentity name in ProfileWidget, with a nav HeaderIconButton to the Dossier
  • Add an onOpenDossier callback to ProjectOverviewView wired to selectedView = .dossier in AppMainView (AppMainView.swift:861)
  • Show a dismissible three-step setup card on the Personal overview — PersonalSetupCard modeled on JourneyRailView, dismissal key personalSetupCardDismissed (JourneyRailView.swift:91)
  • Wire setup step one to the workspace folder: Reveal in Finder plus a Move workspace… action backed by ProjectManager.relocatePersonalWorkspace(to:) that moves the folder and replaces the project entry with the same id
  • Wire setup step two to the existing Developer Dossier rather than a new questionnaire, marking it done when dossier.contract?.isApproved == true
  • Wire setup step three to Claude Setup, marking it done when ~/.claude/CLAUDE.md exists
  • Add a Claude Setup entry in the Personal header that opens ~/.claude — an action in ProjectDetailPanel shown only for .personal (ProjectDetailPanel.swift:45)

Phase 5 — Note verbs in Personal

9 tasks Landed 2026-09-01. The verbs on a Personal note.
  • Confirm the Personal Notes list uses the existing isCompleted checkbox in NotesWidget.noteRow and add no second done flag (ScratchNote.swift:376, NotesWidget.swift:475)
  • Make "Talk this through" the primary action on a Personal note — replace the Start RowActionButton in NotesWidget.noteRow for .personal (NotesWidget.swift:521)
  • Implement talkThrough(note) by posting .navigateToMiraRoom with the project id, then calling MiraService.shared.sendMessage with the note content and details as a user turn, following MiraPanelManager.engageWhisper and MiraRoomView.discuss (MiraPanelManager.swift:160, MiraRoomView.swift:773)
  • Add "Send to Claude Code" as the secondary action on a Personal note — a context-menu item and a secondary row button in NotesWidget
  • Add a dispatch variant to NotePlanningPromptBuilder that requests the work instead of a plan file — Variant.dispatch with requestsPlanFile = false, omitting the plan imperative and Format Requirements (NotePlanningPromptBuilder.swift:114)
  • Present the dispatch prompt through CopyPromptPreviewSheet with isPlanning: false and skip ScratchpadManager.startPlanning in onPromptCopied so no plan monitor is armed (NotesWidget.swift:141)
  • Hide plan-shaped note actions for .personal in NotesWidget: the Planning section, Start Planning, Mark as Planning, Link to Plan, Convert to Task and Convert to Potential Feature (NotesWidget.swift:546)
  • Exclude Personal as a destination for tasks, to-dos and plans — MoveToProjectSheet.excludePersonal set by TasksWidget and ToDosWidget, and a kind filter in PlanReassignmentSheet (TasksWidget.swift:204, PlanReassignmentSheet.swift:31)
  • Verify the build product with scripts/verify-build-product.sh

Phase 6 — Pursuits

7 tasks Landed 2026-09-01. Groups notes only; conversations deferred.
  • Add a Pursuit model with title, summary, isOngoing and isArchived, and no status enum, in Code Raven/Models/Pursuit.swift with lastTouchedAt for ordering
  • Persist pursuits to .claude/context/pursuits.json inside the Personal project via a PursuitStore singleton with decodeIfPresent defaults on every field
  • Add pursuitId: UUID? to ScratchNote across all four edit sites: CodingKeys, decode line, init parameter and assignment (ScratchNote.swift:483)
  • Add a Pursuits widget to the Personal grid listing active pursuits by last touch, with create and archive actions
  • Build a pursuit detail view listing that pursuit's notes with the same row verbs as the Notes widget
  • Add an "Add to pursuit" action on Personal notes and a pursuit filter in the Notes widget
  • Record lastTouchedAt on every note assignment so ordering stays inferred rather than declared

Phase 7 — First-review follow-ups

8 tasks Landed 2026-09-01. From the first look at the running build, plus Claude Setup in Documents.
  • Hide the Note/Task toggle in UnifiedQuickCapture for .personal and force the Note mode on submit (UnifiedQuickCapture.swift:56)
  • Add lockToNotes to FloatingNotepadPanel so the global capture popover offers only Note when the picked project is Personal, and build a dispatch prompt for its Session launch (FloatingNotepadPanel.swift:29, CaptureControl.swift:111)
  • Add a NoteRoute enum (Mira, Claude, Claude Code, ChatGPT) and PersonalNoteActions.route(_:note:project:presentPrompt:); claude.ai and chatgpt.com open with the note prefilled through the q query item and copied to the clipboard
  • Add PersonalNoteRouteButtons and PersonalNoteRouteMenuItems in Code Raven/Views/Scratchpad/ and use them in NotesWidget rows, the "Send to" context menu and PursuitDetailSheet
  • Make the DocumentsHubWidget segment bar a horizontal scroll with single-line labels, and show only Guides and Mockups for .personal with Mockups as the default segment (DocumentsHubWidget.swift:211)
  • Add ClaudeSetupInspector that surveys ~/.claude (instructions, commands, agents, skills, hooks, settings, project memory) and classifies each cr-* command as in sync, update available, drifted, not installed or global only using the installer stamp
  • Add ClaudeSetupSheet in Code Raven/Views/Personal/ with section list, item list and preview pane, an installed/bundled toggle plus Reinstall for drifted commands
  • Surface Claude Setup as a Claude segment in DocumentsHubWidget (default for Personal, last for code projects) with a five-row summary that opens the sheet, badge = cr-* commands needing attention; remove the header-disclosure entry (DocumentsHubWidget.swift:30)

Manual Testing

13 tasks Yours — relaunch first; the running app predates the build.
  • Confirm Personal appears above Projects after relaunch and that existing projects still loadyou
  • Confirm the first launch after seeding shows at most one macOS prompt for Documents access and the folder appears in Finder at ~/Documents/Code Raven/Personalyou
  • Confirm a note captured in Personal can be moved to a real projectyou
  • Confirm "Talk this through" on a Personal note opens Mira with the note as the first turn and a follow-up resumes the same sessionyou
  • Confirm "Send to Claude Code" opens a terminal in the Personal folder and the prompt asks for the work, not a plan fileyou
  • Confirm a custom expert authored in Personal answers without emitting file-anchored findingsyou
  • Confirm Activity Monitor shows no recurring git processes for the Personal folder after five minutes on the Personal overviewyou
  • Confirm the Profile widget reflects the Dossier contract state and the setup card dismisses and stays dismissedyou
  • Confirm the Build button is absent from the Personal tab baryou
  • Confirm Quick Capture in Personal shows no Note/Task toggle and the global capture popover offers only Note when Personal is pickedyou
  • Confirm the Claude and ChatGPT routes open the browser with the note prefilled and the note on the clipboardyou
  • Confirm the Documents widget in Personal shows Guides and Mockups without wrapped labelsyou
  • Confirm the Documents widget in Personal opens on the Claude segment, its rows open Claude Setup, and Reinstall on a drifted cr-* command brings it back to in syncyou

Risks & edge cases

Will bite

The decode trap on kind

A non-optional field with an inline default is still required under synthesized Codable. Project has a hand-written init(from:), so the decodeIfPresent line goes there. loadProjects falls back to per-item decode and silently skips undecodable entries, so a missed default would not crash; every project would vanish from the sidebar with only a console log.

Edge case

Two machines, one iCloud folder

cr-filesync mirrors Application Support between the iMac and the MacBook, and iCloud mirrors ~/Documents. Both machines will see the same projects.json entry and the same folder. The seeder must treat "folder exists" and "entry exists" as success and must never create a second entry with a new id.

Watch

iCloud churn on .claude/

Bridge dirs and agent sessions rewrite small JSON files often; under Desktop & Documents sync each write is an upload. Volume is small for a personal workspace, and Application Support would forfeit the phone-side reach. Watch for .icloud placeholders if the Mac evicts content.

Gap

Experts still have nothing to anchor to until Phase 6

Personal expert answers live in meeting transcripts and Mira turns. That is a real surface now, but a meeting about a hobby still runs the standup format built for codebases. If it reads wrong on first use, pull Phase 6 forward rather than patching the meeting format.

Untested

Chronicle rollups against a journal

Every Chronicle record currently anchors to work. The rollup itself reads only records and is safe; the AI pattern panel is manual-only and can simply not be run.

Scope choice

ProjectOverviewView grows

Already 3,256 lines. Branching the grid and banner stack on kind adds two functions and half a dozen guards. Extracting the grid first would be cleaner but touches a file under active Design Studio work.

Deferred consequence

Personal's notes are not git-tracked

ScratchpadManager persists to Application Support, so nothing in Personal is visible to Claude Code on the web. Fine now, and the blocker the moment mobile access comes back.

Out of scope

Final review

The strength is that almost nothing is new: one enum, one seeder, one widget, one prompt variant, and a set of kind guards at chokepoints that already exist. Every store, importer and bridge carries over because Personal is a real path.

The weakest part is still Experts. The guards make "conversational only" true, but the meeting experience itself was designed for code and has not been tried on a hobby topic. The second soft spot is that Phase 6 pursuits group notes only; a pursuit with a conversation attached is what would make it feel like a Claude Project, and that is deferred.

Adjustments worth considering. If the setup card becomes furniture after a week, drop it to a single "Profile not set up" chip on the Profile widget. If a personal to-do list turns out to want its own surface, re-add TasksWidget rather than inventing a third list.

84/100

High on Phases 1–5, which reuse existing machinery and have one clearly identified failure mode each. Phase 6 is now additive only. The Notes/Tasks collapse remains a bet.