19 tasks · 2 phases · 2026-08-08

Single-Layer Copy Menu + Menu Bar Tray Removal

Two unrelated quick tasks batched into one plan: add a right-click “copy this layer” menu everywhere Foundation layers are listed, and delete the macOS menu bar tray along with the whole notification center behind it.

14Implementation
5Yours to test
2Phases
6Files deleted
The gist

Phase 1 is pure reach: the code to copy a single Foundation layer already exists, it is just unreachable from the surfaces where layers are actually listed. One reusable menu fragment, attached in five places. Phase 2 is a deletion: the menu bar tray goes, and so does the notification queue, the git polling timer, and the five services that fed them — because leaving those running with no surface would be write-only dead code.

The problem

Phase 1. Copying one layer’s content to the clipboard is only reachable from inside that layer’s own edit/preview page (LayerExportMenu / CompactExportButton). From the surfaces where layers are listed — dashboard widget, Foundation hub, Foundation Review — the only clipboard action is the full-foundation export, or a file-writing “Export as Markdown”. There is no right-click → copy this one layer.

Phase 2. The tray icon had stopped earning its place, but it was not just an icon: it hosted a whole notification center (MenuBarNotificationQueue, persisted to Application Support) fed by five services, plus a five-minute git polling timer.

Approach

One menu fragment, five attachment points

FoundationExportService.shared.export(layer:manager:format:projectName:) already returns markdown, a short overview, or JSON for any single layer. Only the UI entry points are missing — so the work is one reusable FoundationLayerCopyMenuItems plus a .foundationLayerCopyMenu(…) View extension, attached to every layer row rather than five bespoke menus that drift apart.

Full removal, not a hidden icon

Hiding the tray would leave the queue, the timer, and five posting services running with nothing to display. The plan verified each signal still has an in-app surface before deleting: the five standup sites all set reachedNaturalEnd + save, which drives the in-meeting banner, and MockupDeliveryService also calls NotificationService.notify.

Normalized JSON, consistent with the rest of the app

.json re-encodes the in-memory Codable model, not the raw .claude/context/<layer>.json file. For layers whose decoders drop unknown fields this is a normalized view rather than a byte-copy of disk. That matches existing “Copy as JSON” behavior elsewhere, so the plan keeps it rather than making one menu special.

Decisions made for you

Accepted loss

The commit nudge goes away entirely

Every other tray signal — mockup-ready, mockup-delivered, meeting-pending-response, guide tips — was confirmed to have another in-app surface. The commit nudge had none, and it is cut rather than rehomed. That is the intended trade, not an oversight.

Regression handled

Session Bar Show/Hide relocated to General Settings

The tray popover held the only Show/Hide control for the Session Identity Bar. Settings has an enable toggle, but once the bar was user-dismissed only the tray could bring it back — so removing the tray would have stranded it. A Show/Hide control moves into General Settings in the same phase.

The work

Phase 1 — Right-click copy for a single Foundation layer

5 tasks Additive; independent of Phase 2.
  • Add Code Raven/Views/Foundation/FoundationLayerCopyMenu.swift with FoundationLayerCopyMenuItems (Copy as Markdown / Copy Summary / Copy as JSON) and a .foundationLayerCopyMenu(...) View extension
  • Attach copy items to the existing per-layer context menu in CompactFoundationWidget.compactLayerCell
  • Add a context menu to LayerConfigCard (Foundation hub rows) when the layer has data
  • Add a context menu to LayerReviewSection header and fold JSON into its inline Share menu (FoundationReviewView)
  • Add a context menu to the LayerPreviewFullPage header title so the Features layer — which has no export button — is covered too

Phase 2 — Remove the macOS menu bar tray icon

9 tasks Deletions land together; the build gate is the last task.
  • Delete MenuBarController.swift, MenuBarNotificationQueue.swift, MenuBarCommitNudgeMonitor.swift, MenuBarDeepLinkRouter.swift, Models/MenuBarNotification.swift, Views/MenuBar/MenuBarNotificationPopover.swift
  • Move Notification.Name.navigateToProjectTab to Extensions/NotificationNames.swift (the AppMainView listener stays; it now has no poster)
  • Remove menuBarController and MenuBarCommitNudgeMonitor start/stop from Code_RavenApp.swift
  • Remove the five MenuBarNotificationQueue.post sites in StandupMeetingService.swift
  • Remove the post sites in MockupAIService.swift, MockupDeliveryService.swift, LivingGuideStore.swift
  • Remove markViewedByType calls in LivingGuideView, StandupMeetingView, MockupStudioContainerView
  • Remove the “Menu bar notifications” toggle from GeneralSettingsView and add a Session Bar Show/Hide control
  • Delete the MenuBarIcon.imageset asset
  • xcodebuild -scheme "Code Raven" -destination 'platform=macOS' build green

Manual testing

5 tasks Yours — excluded from progress.
  • Right-click a layer in the dashboard Foundation widget → Copy as Markdown / JSON, paste and confirm content is that layer onlyyou
  • Right-click a layer row in the Foundation hub and in Foundation Review → sameyou
  • Right-click the Features layer header in its preview page → copy works there tooyou
  • Confirm no Code Raven icon appears in the macOS menu bar after relaunchyou
  • Dismiss the Session Bar, then re-show it from General Settingsyou

Risks & edge cases

Edge case

Normalized JSON is not a byte-copy

If you copy a layer as JSON expecting to paste it back over .claude/context/<layer>.json, any field the decoder does not know about is silently gone. Fine for reading and for handing to another model; wrong for round-tripping a file.

One-way

Phase 2 is not reversible in place

Six files are deleted outright. Restoring the tray later means restoring the queue, the persistence, the deep-link router, and the five post sites — recoverable from git, but not a toggle.

Thin spot

A listener with no poster

navigateToProjectTab survives the deletion and moves to NotificationNames.swift, but nothing posts it any more. It is harmless and may well be wanted again — it is also exactly the kind of thing that reads as live wiring six months from now.

Final review

The two halves are well matched to their own logic. Phase 1 resists the obvious shortcut — five separate context menus — in favor of one fragment attached five times, which is the difference between a change that stays consistent and one that drifts. Phase 2’s strength is that it did the surface audit before deleting rather than discovering the gap afterward, and it caught the Session Bar regression, which is the non-obvious casualty of removing the tray.

Where it is weakest: batching two unrelated tasks into one plan means the Chronicle record and any checkin summary describe a change with no single theme, and the Manual Testing section mixes verification for both. That is a legibility cost, not a correctness one. The stranded navigateToProjectTab listener is the one loose thread worth a comment in the file.

88/100

High on approach: the shared-fragment choice and the pre-deletion surface audit are both the right calls, and the accepted losses are named rather than hidden. Held back from higher by the batching, which makes the plan harder to review as one thing than either half would have been alone.