Product rethink: visibility over status, personal libraries, profiles, three surfaces#153
Conversation
…rchived_at - Plans are born published; visibility:draft is the opt-in private flag - Publishing is one-way; archive replaces abandon (opt-in visible, reversible) - PlanPolicy#show? is now THE visibility predicate (was: true); attachments controller's duplicated brainstorm gate collapsed into it - Legacy API compat: status accepted on writes, legacy_status emitted on reads - Workspace groups by published/drafts; archived opt-in via ?filter=archived - developing/live preserved as tags in the data migration Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…adcast helper Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Folders now live in libraries (polymorphic owner, auto-created per user), plans attach to folders via first-class placements (one shelf per library, many libraries per plan), and shelving is viewer-relative everywhere: the workspace, the move menu, and the API's folder_id / folder_path all speak in terms of the caller's own library. - Library.for(owner) materializes the per-owner library invariant - Plans::Place is the single write path for shelving (web + API), gated on the plan being listed for the actor - Drafts are unlisted, not locked: PlanPolicy#show? is open, discovery goes through PlanPolicy#listed? / Plan.visible_to only - Read-only library browsing at /libraries/:id with folder anchors; plan pages grew a "Shelved in" folder-jump strip - API: folders index accepts ?library_id= for read-only browsing, legacy status values now 422 with guidance instead of being ignored Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every person gets a page at /people/:username-or-id — the front door to their library: identity (enriched by the host's people directory via the new config.directory_profile hook, degrading to local columns when absent or failing), published plans recent-first, and their library shelves embedded read-only. Profiles are them-facing: only publicly listed work appears, never drafts or archived plans, not even your own (Plan.publicly_listed is the shared scope). Author names across the app — plan headers, workspace row avatars, library shelves, comments — now link to profiles. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Home (/home) is the new org-facing landing: a feed of publicly listed plan activity rolled up per plan per day (agent editing loops hit rev 29 in days; per-edit entries would drown it), built by CoPlan::HomeFeed from versions, publish events, and comments over a 14-day window. Drafts and archived plans never appear. Search now finds people too — a person result lands on their profile, which is the road to their library. The nav grew primary links (Home / Workspace / Library), the signed-in root redirect goes to Home, and your name in the nav links to your profile. "All plans" stays demoted to a workspace sidebar filter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
From the screenshot pass on all four surfaces (light + dark): breathing room between the brand and the primary nav links, no wrapping in the nav user block, and profile shelf metadata wraps under the plan title instead of ellipsizing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 91cd5816fa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| folder = resolve_folder_params | ||
| return if performed? # resolve_folder_params rendered an error | ||
| @plan.folder = folder | ||
| result = Plans::Place.call(plan: @plan, folder: folder, actor: current_user) |
There was a problem hiding this comment.
Allow folder-only API shelving by non-authors
This new placement path is still inside update, which returns 403 on !policy.update? before reaching Plans::Place. When a user tries to shelve someone else's published plan into their own library, the service would allow it via listed? and the web move_to_folder flow now supports it, but the API rejects the request just because the caller is not the plan author. Split folder-only updates from metadata authorization or let them reach Plans::Place while keeping title/visibility/tag edits author-only.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🤖 (replying on Hampton's behalf) Confirmed still valid — API update gates everything on PlanPolicy#update?, so a non-author can't shelve someone else's listed plan via the API even though the web move_to_folder flow (and Plans::Place itself) allows it. Deliberately deferring rather than special-casing folder-only PATCHes inside update: mixing two authorization regimes in one action is how policy bugs happen, and placements are viewer-relative anyway — they deserve their own endpoint (e.g. PUT /plans/:id/placement) that authorizes via Plans::Place's rules, mirroring the web route. Tracking as a follow-up after #153 lands.
| counts = PlanPlacement.where(library_id: library.id) | ||
| .visible_to(current_user) | ||
| .group(:folder_id) |
There was a problem hiding this comment.
Exclude archived plans from folder counts
Archived plans are excluded from /api/v1/plans by default, but these folder counts only apply visible_to and therefore still count archived placements. A folder containing only archived plans will report a positive plans_count while the default plan listing for that folder returns no plans, which also surfaces archived work on a default discovery endpoint. Apply the same active/non-archived predicate here (and in the single-folder serializer) so counts match the plans users can list.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🤖 (replying on Hampton's behalf) Already addressed — the full-review pass (2fcbcb5) applies .where(plan: Plan.active) in both places: the grouped index counts and the single-folder folder_json fallback count. Archived placements no longer inflate plans_count, so counts match what the default plan listing returns.
| .pluck(:plan_id, :created_at, :revision) | ||
| .each do |plan_id, at, revision| | ||
| rollup = note.call(plan_id, at) | ||
| revision == 1 ? rollup[:published] = true : rollup[:edits] += 1 |
There was a problem hiding this comment.
Do not report draft creation as a publish
When a plan is created as a draft and later published on a different day within the feed window, it is included in listed at build time, so this loop treats its revision-1 draft creation as a published activity; the PlanEvent query below then adds the real publish day too. Home can show a bogus publish entry (or two publish entries) for the same plan. Only plans actually born published should mark revision 1 this way.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🤖 (replying on Hampton's behalf) Valid — fixed in e8f355d. Revision 1 now counts as the publish moment only when the plan has no "published" event; born-draft plans get their publish day from the event alone, and their revision 1 (which predates being listed) no longer produces a feed item. Covered by new specs in spec/models/home_feed_spec.rb.
Provisioning raised RecordInvalid when the host-supplied username was already held by a different account, which turned one data collision into an error on every page for that user. A username is a nicety — profiles fall back to id — so keep the user's current username (nil for a new account) when the host sends one that collides. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Shelved-in strip is now Drive-style folder chips: icon + folder name, ownership in the tooltip; your own chips open the workspace folder. - Published is the unmarked normal state everywhere. Hidden states (draft, archived) get a quiet crossed-out eye instead of colored badges; Home says "new" instead of "published"; the workspace group is just "Plans". - Attachment upload: designed dropzone (click or drag, auto-submits) replacing the native file input + Upload button. - IA: Library merged into Workspace. Nav is Home/Workspace; the sidebar folder tree is "My library" with a "Public view" link; the library page stays as the read-only face others browse. "All plans"/"My plans" filters removed — org-wide discovery lives on Home, search, and profiles (?scope=all still resolves, shown as a clearable chip). - Owner actions: consistent icon buttons (publish/edit/title-tags/ archive), SVG tab icons instead of emoji, chip-based tag editor with datalist suggestions. - Liquid-glass visual refresh: gradient mesh backdrop, translucent blurred nav/cards/popovers/search, floating comment-toolbar pill, gradient primary buttons, softer radii — both themes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Workspace & IA (feedback round): - Workspace main pane groups by root folder (subtree rollup) + Unfiled, with per-group turbo-frame pagination and heading drop targets - "Since you last looked" recency strip driven by PlanViewer.last_seen_at (new-to-you / updated badges); own unvisited plans excluded - Nav is Workspace (landing) + Feed; single pen icon opens the unified editor (title + tags + content); comment navigator toolbar deleted (keyboard j/k/r/a/d/s retained) - Reusable add-modal (Popover API) for references + attachments - Inline folder creation in sidebar; folder-onto-folder drag reparenting via new PATCH /folders/:id (model-validated cycles/depth/library) - Plan types get per-install lucide icons (coplan_plan_types.icon) and lead every row/feed/header line as a chip - Mobile pass: nav collapse, popover clamping, workspace stacking Audit fixes (testing depth, dead code, Rails 8/Stimulus idioms): - Fix: needs-attention strip now routes through Plan.visible_to + active (stale notifications can no longer resurface archived plans or leak another user's draft title) - Extract Plans::ToggleCheckbox service (controller no longer reimplements the versioning pipeline inline) - comment_nav: single timeboxed MutationObserver (was stacking one per keypress, never cleaned up); text_selection: clear linked-thread retry timer on disconnect; mention picker: abort stale fetches, drop dead submitOnEnter action - Workspace index: one grouped COUNT for all folder groups; shared unread grouped query; .to_a pagination (no extra COUNT); SQL ordering for shelves; notifications index capped at 100 - params.expect across web controllers (malformed payloads 400, not 500) - New workspace_path helper replaces 15 params.permit(...).merge sites - Dead code deleted: line-selection feature (helper + controller), dropdown controller + CSS, 8 orphaned CSS blocks, unused Stimulus targets/values, brainstorm status tokens, Plan#to_param - A11y: add-modal aria-labelledby + autofocus, plan-group aria-controls + hidden toggle, inbox bell aria-expanded + hidden attr - normalizes for Tag/Folder names; atomic thread+first-comment create - New specs: PlanPolicy + visible_to/publicly_listed units, update_content metadata path (incl. conflict survival), recency-strip bounds, libraries redirects, settings theme, llms.txt, plan versions/diff, nav chrome system specs (search modal, inbox, theme), tag-chip editor, folder reparent drag, add-modal close paths, s-in-textarea guard - Suite: 1204 examples, 0 failures Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mobile sheets Workspace becomes one-level-at-a-time navigation like Drive: each level shows its subfolders (even empty ones) plus the docs filed right there, root shows unfiled docs, and breadcrumbs replace the "Folder:" filter chip. Filters (type on top, tags, updated windows, private/archived) switch to flat subtree results, and every sidebar count now answers "what does clicking this show" under the other active filters. - Since-you-last-looked: new Plans::ChangedSections service diffs markdown sections between the version you last saw and the current one; the plan page highlights those sections once (client slugs mirror the server), and the workspace index opts out of Turbo cache so back-nav can't resurrect a stale strip. Trailing-blank-line shifts from adding a section below no longer flag the section above. - Plan rows drag as a whole card (inner links draggable=false) onto sidebar folders, main-pane folder rows, and breadcrumb segments. - New-folder is a popover modal nested in the current folder; fixed scope: :folder silently binding @folder and prefilling its name. - Doc types render as colored file icons (CRC-stable tint, tooltip) in rows, headers, search, home, and profiles; text chip removed. - Draft is now a quiet "Private" visibility flag (crossed-eye), the publish button reads "Share with everyone", and the agent API frames visibility=draft as a rare escape hatch. - References/attachments: any signed-in user can add (contribute? policy), removal stays with the author; tab-bar "+" activates the panel before showing its popover (popovers can't open from hidden subtrees). - Mobile: workspace sidebar collapses behind a Filters & folders disclosure; comment composer and thread popovers become bottom sheets. The composer joins the popover top layer — the glass panel's backdrop-filter made it the containing block, so position:fixed pinned the sheet off-screen instead of to the viewport. - Workspace keyboard nav: j/k move, Enter opens, Backspace goes up a crumb, Escape clears filters. - System specs run at an explicit 1400px viewport (the Capybara- registered :selenium_chrome_headless driver ignores screen_size). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Visibility/authz: - API folder counts and reference typeahead now exclude archived plans, matching every other discovery surface (.active alongside visible_to). Correctness: - ChangedSections rewritten to section the *rendered* document (Commonmarker + Nokogiri walk), matching the client renderer exactly — fixes phantom changed-section highlights from fence toggles, setext/indented headings, CRLF content, HTML entities, and headings with no body. - Plans::Create normalizes CRLF like ReplaceContent already did. - Sidebar counts share the Hidden filter with the list they describe — a folder count under ?filter=archived now matches what clicking shows. - Plans::Place: unshelving is always allowed (moved above the listed? check) and the placement upsert retries once on RecordNotUnique. JS resilience: - folder DnD payloads carry folderId/parentId so a no-op drop (same folder) skips the PATCH + reload + toast instead of lying about a move. - workspace keys leave Enter/Backspace alone when a link/button/summary has focus. - mobile comment sheet closes before Turbo caches the page; changed-section note no longer duplicates on snapshot restore. - web folders create/reparent use params.expect (malformed payload → 400). Perf: - index rows preload a lean version stub (id + sha) instead of dragging MEDIUMTEXT content/diff/operations per row; preview body fetched only on cache miss. PlanVersion after_initialize guards has_attribute? for this. - search typeahead includes :plan_type (kills an N+1). - dead .dropdown CSS removed. Tests: Plans::Place guard rails (8), rendered-section edge cases (6 more), web references contribute policy, move_to_folder draft rejection (JSON+HTML), sidebar counts under Hidden filter, folder page-2 pagination, Escape key nav. Full suite: 1255 examples, 0 failures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ibility eye
- Saving is bookmarking: flat "Add to Folder" selects replaced everywhere by
a bookmark button opening a hierarchical folder-picker popover (tree view,
current folder marked, "Remove from my library"); placements are pointers,
never copies
- Plan page loses its tabs: References/Attachments become footnote sections
under the document (round icon-only "+" add buttons, TOC entries, [ / ]
section jumps); History is its own page behind a header clock icon, with
?tab=history redirecting; TOC toggle moves to t
- Visibility is a two-way author-only eye: click to arm (slash preview,
4s auto-revert), click again to commit over fetch — no reload; hide is
policy-gated (published, unarchived) and logged to history
- Sidebar folder tree gets a "My Plans" root node; sidebar "+ New folder"
removed (breadcrumb-bar button remains)
- Workspace arrows mirror j/k; Backspace on a plan page returns to where you
came from (workspace fallback)
- Updated 7d/30d filters gain combinatorial counts and drop out at zero;
covering/scale indexes added for 50k+ doc workspaces
- Rows show full-height two-line type icons, Drive-style; row menu replaced
by the hover bookmark
- ActiveAdmin PlanTypes form gains the curated icon select
- Sign-in no longer double-loads: host layout now tracks the same engine
stylesheet (Turbo stops force-reloading on sign-in/out crossings, which
also raced navigation in system specs); stale host CSS deleted
- System specs run Chrome for Testing (pinned 150) via selenium-manager —
managed-Chrome force-installed IT extensions were opening a background tab
in test profiles and wedging Capybara teardown ("failed to close window")
Suite: 1265 examples, 0 failures.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Saved bookmarks (row and plan header) no longer reopen the folder navigator — clicking them removes the placement with no dialog and no toast, exactly like a browser bookmark star; click again to re-add. The picker's "Remove from my library" button is gone (unreachable now), saved bookmarks tint toward danger on hover as the only removal hint, and triggers carry data-saved so the controller can tell the two gestures apart. Suite: 1265 examples, 0 failures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…resh Prefer this branch's visibility model while genuinely adopting main's new features: - LinkPreviews/Slack unfurls (#154): adopted; context now speaks the visibility language — Private/Archived flagged, published unmarked, never "Draft". plan_og_description delegates to the same builder. - Mermaid comment anchors (#148/#149/#151): adopted; mermaid-settled re-highlighting wired into our no-tabs plan page, anchors-updated re-anchoring wired into our headless comment nav. Clicking a comment mark inside a diagram now opens its thread popover instead of the lightbox (showModal force-hides popovers). - Landing refresh + agent-instructions view (#140): adopted; step copy and mock badge updated to the born-published model (type badge, no status badge). - Status badge menu (#146): superseded — visibility is the only state, toggled by the header eye; status_menu_controller removed. - Attachments dropzone (#147): superseded by our add-modal dropzone; spec selectors reconciled. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The version-diff spec asserted on raw HTML, but Diffy shells out to the platform diff binary and GNU vs BSD diff pair changed lines differently, splitting the phrase with inline word-highlight markup on Linux. Assert on the rendered text instead. Chrome on CI runners fills the small /dev/shm tmpfs and exits mid-suite; --disable-dev-shm-usage spills to /tmp. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hrome The runner image ships chromedriver 150 in PATH next to Chrome 151; a PATH driver takes precedence over selenium-manager, and the mismatched pair makes Chrome exit at session creation — failing whichever system spec runs first (the retry on the next spec falls back to managed downloads, which is why exactly one spec failed per run). Removing the PATH driver lets selenium-manager provision the matched Chrome for Testing 150 + driver pair, same as local runs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The CfT pin + forced browser download work around managed-machine policy extensions — a local problem. On CI they fight selenium-manager into mismatched browser/driver pairs (the runner's own Chrome + chromedriver pair is unmanaged and matched, and is what main's CI has always used). Also reverts the workflow's chromedriver removal from the previous attempt. --disable-dev-shm-usage stays: it is what CI Chrome needs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Typing Enter into the tag field before tag_input_controller connects
submits the form natively instead of committing a chip — on slow CI
boots the navigation detaches the field mid-send_keys ("Node with given
id does not belong to the document"). Waiting for the existing tag's
chip (rendered only on connect) closes the window.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Revision 1 marks the publish moment only for born-published plans. Plans with a "published" event were listed later — their publish day comes from the event, and their revision 1 predates being visible, so it isn't feed activity. (Codex review finding on #153.) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Implements the product rethink from the CoPlan Rethink PRD end to end, in four phases (one commit each, plus a migration commit and polish).
Note
This supersedes #146, which is now obsolete — the org-global folder design it built on was replaced by personal libraries in the PRD.
1. Status is dead
statuslifecycle is replaced byvisibility(draft/published) +archived_at. Migration maps brainstorm→draft, abandoned→published+archived, everything else→published (withdeveloping/livepreserved as tags)."visibility": "draft"on create), not the starting state.PlanPolicy#show?is open); discovery — lists, feeds, search, counts, shelves — goes through one predicate (PlanPolicy#listed?/Plan.visible_to), never inline checks.statusstill accepted (mapped) and emitted (legacy_status) for the deprecation window; unknown legacy values now 422 with guidance.2. Folders became personal libraries
CoPlan::Librarywith a polymorphic owner (users only in v1); every user always has one, materialized on first touch (Library.for, race-safe). Folders belong to their library; write access is the library's call (writable_by?).CoPlan::PlanPlacement(who placed it, when; unique per plan per library) — the same plan can sit on many people's shelves. Shelving someone else's published plan is a normal action.Plans::Placeis the single write path for shelving (web drag-and-drop, row menu, and API all use it).folder_id/folder_pathmean "where you shelved it", workspace rows show your shelf, and the sidebar tree is your library./libraries/:id), and plan pages grew a "Shelved in" folder-jump strip.3. Profiles + directory adapter
/people/:username-or-id— identity, published plans, and the library shelves embedded. Only publicly listed work appears, even on your own profile.config.directory_profile(People API adapter point): enriches name/avatar/title/team and adds a directory link-out; failures degrade to the local profile. Author names across the app link to profiles.4. Three surfaces
/home, the new signed-in root): activity feed over published work, rolled up per plan per day (CoPlan::HomeFeed), plus search that now finds people as well as plans./plans): your operating center — your plans (drafts included) + your placements, needs-attention strip, folder tree.One deliberate deviation from the PRD: the workspace main pane still groups by plans/drafts rather than by folder — the folder tree + drag-to-file in the sidebar covers folder organization, and the visibility groups are what make drafts-you-never-published visible. Easy to revisit.
Design round (post-review feedback)
Feedback round 2 (workspace as the landing surface)
PATCH /folders/:id, cycle/depth/library rules enforced by the model).coplan_plan_types.icon(curated lucide set, per-install branding) renders as a leading chip on every row, feed item, and plan header.Polish & audit round (design, testing depth, dead code, Rails 8/Stimulus idioms)
Three-agent audit (dead code, idioms, test gaps), findings triaged and applied:
Plan.visible_to+active— stale notifications can no longer resurface an archived plan or leak another user's draft title. Locked in with request specs.Plans::ToggleCheckboxservice instead of an inline copy of the versioning pipeline in the controller.submitOnEnteraction and unused targets/values removed.params.expectacross web controllers (malformed payloads 400 instead of 500),normalizesfor tag/folder names, atomic thread+first-comment create, newworkspace_pathhelper replacing 15 hand-rolledparams.permit(...).mergelink sites.aria-labelledby+ autofocus, plan groups getaria-controls+ truehiddenwhen collapsed, inbox bell reportsaria-expanded.PlanPolicy+visible_to/publicly_listedunit specs (the discovery predicate had none), the unified editor's metadata path incl. metadata surviving an edit conflict, recency-strip bounds, libraries/theme/llms/version-diff request specs, and browser specs for the search modal, inbox, theme switcher, tag chips, folder-drag reparenting, and modal close paths.Verification
🤖 Generated with Claude Code
Feedback round 3 (Drive-style workspace + the 17-item list)
My Plans › Payments › EBT) replace the "Folder:" chip and are drop targets, so dragging up a level is a thing.#kmp (2)inside an empty folder bug is gone (tags/types with no matches drop out).visibility: "draft"as a rare, explicit-request-only escape hatch.contribute?policy — the upload UI no longer vanishes on plans you didn't write); removal stays with the author. The tab bar grew a shared "+" next to References and Attachments that activates the panel and opens its add-modal in one click — this also fixes the dead add-reference popup (popovers can't open from inside a hidden tab panel).backdrop-filtermade it the containing block, pinning the "fixed" sheet off-screen), and the workspace sidebar collapses behind a "Filters & folders" disclosure.j/kwalk folders and docs,Enteropens,Backspacegoes up a level,Escclears filters.screen_size.)Full-review pass (2fcbcb5)
A four-lens review of the whole diff (visibility/authz, correctness, JS/CSS, perf/tests), findings verified before fixing:
.activelike everything else. Everything else checked clean: every list/search/feed/notification path routes throughvisible_to/listed?, and flash/toast output is escape-safe.?filter=, so their counts now count what the click will show.Plans::Placehardening: unshelving is always allowed even if the plan has since become unlisted; concurrent double-shelving retries instead of 500ing. The service's guard rails (the web move endpoint's whole security boundary) now have a dedicated spec.Feedback round 4 (bookmarks, footnotes, the two-way eye)
[/]jump between document and footnotes), listed at the bottom of the table of contents with counts. Each footnote header has a round icon-only + that opens the existing add-popovers. History moved to its own page behind a clock icon in the header — Backspace (or the back arrow) returns to the document; old?tab=historylinks redirect. The TOC toggle moved from]tot.j/kon the workspace; Backspace on a plan page takes you back to wherever you came from (falls back to the workspace when you arrived cold).(author, updated_at)/(visibility, updated_at)on plans — keep the workspace queries index-only at that scale, no non-ActiveRecord machinery needed.Merged main (post-#140), reconciled (7d10932)
Main moved while this branch was open — this merge adopts its new features and re-expresses their state language in this branch's visibility model:
LinkPreviews.for_plannow builds its context as state · type · author where published is the unmarked state — onlyPrivateandArchivedget a flag, and the word "Draft" never appears (matches the in-app language). OG descriptions and Slack unfurls share the one builder.mermaid-settledre-highlight hook is wired into this branch's no-tabs plan page, andanchors-updatedre-anchoring feeds the headless comment nav (the floating toolbar it targeted on main no longer exists). One behavior fix on top: clicking a comment mark inside a diagram now opens its thread popover instead of the lightbox —showModal()force-hides every open popover, so the lightbox was eating the popover the marks exist to open.status_menu_controlleris gone.Full suite after the merge: 1301 examples, 0 failures.