Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
branch: vlad/cosmic-worktopics
bound_by: init.behavior skill
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
emit your response to the feedback into
- .behavior/v2026_04_11.cosmic-worktopics/$BEHAVIOR_REF_NAME.[feedback].v$FEEDBACK_VERSION.[taken].by_robot.md

1. emit your response checklist
2. exec your response plan
3. emit your response checkoffs into the checklist

---

first, bootup your mechanics briefs again

npx rhachet roles boot --repo ehmpathy --role mechanic

---
---
---


# blocker.1

---

# nitpick.2

---

# blocker.3
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
branch: vlad/cosmic-worktopics
bound_by: route.bind skill
11 changes: 11 additions & 0 deletions .behavior/v2026_04_11.cosmic-worktopics/.route/.bouncer.cache.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"protections": [
{
"glob": "src/**/*",
"stone": "3.3.1.blueprint.product.v1",
"guard": ".behavior/v2026_04_11.cosmic-worktopics/3.3.1.blueprint.product.v1.guard",
"route": ".behavior/v2026_04_11.cosmic-worktopics",
"passed": false
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"count": 4,
"stone": "3.3.1.blueprint.product.v1"
}
5 changes: 5 additions & 0 deletions .behavior/v2026_04_11.cosmic-worktopics/.route/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# ignore all except passage.jsonl and .bind flags
*
!.gitignore
!passage.jsonl
!.bind.*
29 changes: 29 additions & 0 deletions .behavior/v2026_04_11.cosmic-worktopics/.route/passage.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{"stone":"1.vision","status":"blocked","blocker":"review.self","reason":"review.self required: has-questioned-requirements"}
{"stone":"1.vision","status":"blocked","blocker":"approval","reason":"wait for human approval"}
{"stone":"1.vision","status":"approved"}
{"stone":"1.vision","status":"passed"}
{"stone":"2.1.criteria.blackbox","status":"passed"}
{"stone":"2.2.criteria.blackbox.matrix","status":"passed"}
{"stone":"2.3.criteria.blueprint","status":"passed"}
{"stone":"3.1.1.research.external.product.access._.v1","status":"passed"}
{"stone":"3.1.1.research.external.product.claims._.v1","status":"passed"}
{"stone":"3.1.1.research.external.product.domain._.v1","status":"passed"}
{"stone":"3.1.1.research.external.product.domain.terms.v1","status":"passed"}
{"stone":"3.1.1.research.external.product.references._.v1","status":"passed"}
{"stone":"3.1.2.research.external.factory.oss.levers._.v1","status":"passed"}
{"stone":"3.1.2.research.external.factory.templates._.v1","status":"passed"}
{"stone":"3.1.2.research.external.factory.testloops._.v1","status":"passed"}
{"stone":"3.1.3.research.internal.product.code.prod._.v1","status":"passed"}
{"stone":"3.1.3.research.internal.product.code.test._.v1","status":"passed"}
{"stone":"3.1.4.research.internal.factory.blockers._.v1","status":"passed"}
{"stone":"3.1.4.research.internal.factory.opports._.v1","status":"passed"}
{"stone":"3.1.5.research.reflection.product.audience._.v1","status":"passed"}
{"stone":"3.1.5.research.reflection.product.premortem._.v1","status":"passed"}
{"stone":"3.1.5.research.reflection.product.rootcause._.v1","status":"passed"}
{"stone":"3.2.distill.domain._.v1","status":"passed"}
{"stone":"3.2.distill.factory.upgrades._.v1","status":"passed"}
{"stone":"3.2.distill.repros.experience._.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-critical-paths-identified"}
{"stone":"3.2.distill.repros.experience._.v1","status":"passed"}
{"stone":"3.3.0.blueprint.factory.v1","status":"passed"}
{"stone":"3.3.1.blueprint.product.v1","status":"blocked","blocker":"review.self","reason":"review.self required: has-questioned-deletables"}
{"stone":"3.3.1.blueprint.product.v1","status":"malfunction"}
292 changes: 292 additions & 0 deletions .behavior/v2026_04_11.cosmic-worktopics/0.wish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
wish =

---

our work flow is as follows


1. workspace w/ 2-3 windows per workzone (workzone = one worktree)
- 1 window w/ terminal w/ claude
- 1 window w/ terminal w/ nvim
- misc

2. N workspaces, 1 per workzone
- typically, we have 10+ workzones (worktrees) open at a time; each w/ 2-3 windows


to pros of this is that each workzone is independent and easy to navigate to (super+/ search the name, boom, open)

the cons of this is that the workzones are intermixed across different domains; different topics
- some to develop rhachet
- some to develop rhight
- some to develop ahbode
- some for personal errands
- etc

it sucks, because for each domain (workgroup? workorg?) there's a bunch of workzones and they're intermixed, which means the context is scaterred. cant just focus on workgroup=ahbode because to get to the next ahbode workgroup, i cross the others. makes it way harder atleast

so, ideally, cosmic-comp would support workgroups/worktopics/workdomains (kde calls them "activities")

where we can group workspaces together, and use super-tab for example to rotate through them

e.g., up-and-down = workspaces within a workgroup, left-and-right = toggle across workgroups

---

we basically want 2d workspace control, where up and down moves workspaces within within the workgroup and left-and-right moves workgroups within the workgrid

the ideal bonus would be to name the workgroups so we can search into them, but thats not a requirement. just the 2d organization is the real unlock

---

here's a handoff a peer had proposed

# Worktopic: Workspace Groups for Cosmic DE

## Concept

A **Worktopic** is a named collection of workspaces representing a single domain/context (e.g., "client-A", "oss-projects", "personal").

**Navigation model:**
- `Super+Tab` — switch between worktopics (left/right axis)
- `Super+Ctrl+↑↓` — switch workspaces within current worktopic (up/down axis)
- `Super+Shift+Tab` — move current window to next worktopic

**User workflow:**
```
Worktopic: "work" Worktopic: "personal" Worktopic: "client-x"
├── workspace 1 (2 win) ├── workspace 1 ├── workspace 1
├── workspace 2 (2 win) ├── workspace 2 ├── workspace 2
├── workspace 3 (2 win) └── workspace 3 ├── workspace 3
├── workspace 4 (2 win) ├── workspace 4
└── workspace 5 (2 win) └── workspace 5

<── Super+Tab ──>
```

Switching worktopic = entire desktop context switches. All monitors show the new worktopic's workspaces.

---

## Why This Is Feasible

Cosmic's Wayland protocol (`cosmic-workspace-unstable-v2`) already supports:
- N-dimensional workspace coordinates via `coordinates` event
- Axis-based movement via `move_before(axis)` / `move_after(axis)`
- Workspace groups via `zcosmic_workspace_group_handle_v2`

The protocol is ready. The compositor and UI just need to use the second dimension.

---

## Repositories

| Repo | Purpose | Changes Needed |
|------|---------|----------------|
| [cosmic-comp](https://github.com/pop-os/cosmic-comp) | Compositor (workspace state, navigation) | Core implementation |
| [cosmic-protocols](https://github.com/pop-os/cosmic-protocols) | Wayland protocol definitions | Minor: add worktopic name field |
| [cosmic-workspaces-epoch](https://github.com/pop-os/cosmic-workspaces-epoch) | Workspace switcher applet | UI for 2D grid + worktopic labels |
| [cosmic-settings](https://github.com/pop-os/cosmic-settings) | Settings app | Worktopic configuration UI |

---

## Implementation Outline

### Phase 1: Data Model (cosmic-comp)

**File:** `src/shell/workspace.rs` (or similar)

```rust
// New struct
pub struct Worktopic {
pub id: WorktopicId,
pub name: String,
pub workspaces: Vec<WorkspaceHandle>,
pub active_workspace: usize,
}

// Extend Shell or WorkspaceSet
pub struct Shell {
// Change from flat workspace list to:
pub worktopics: Vec<Worktopic>,
pub active_worktopic: usize,
// ...
}
```

**Key changes:**
- Workspaces belong to a worktopic
- Navigation tracks (worktopic_index, workspace_index)
- Coordinates become `[worktopic_idx, workspace_idx]`

### Phase 2: Navigation Logic (cosmic-comp)

**File:** `src/input/mod.rs` or keybinding handler

```rust
// Pseudo-code for navigation
fn handle_worktopic_switch(&mut self, direction: Direction) {
match direction {
Direction::Next => {
self.active_worktopic = (self.active_worktopic + 1) % self.worktopics.len();
}
Direction::Prev => {
self.active_worktopic = self.active_worktopic.saturating_sub(1);
}
}
// Activate the worktopic's last-active workspace
let worktopic = &self.worktopics[self.active_worktopic];
self.activate_workspace(worktopic.workspaces[worktopic.active_workspace]);
}
```

**Keybindings to add:**
- `Super+Tab` → `worktopic_next`
- `Super+Shift+Tab` → `worktopic_prev` (or move window)
- Existing `Super+Ctrl+↑↓` continues to work within worktopic

### Phase 3: Protocol Events (cosmic-comp → clients)

Emit updated coordinates when worktopic changes:
```rust
// workspace coordinates = [worktopic_index, workspace_index]
workspace_handle.coordinates(&[self.active_worktopic as i32, workspace_idx as i32]);
```

Consider adding a new event for worktopic name:
```rust
workspace_handle.worktopic_name(&worktopic.name);
```

### Phase 4: UI (cosmic-workspaces-epoch)

**Current:** Flat horizontal workspace list
**New:** 2D grid or grouped list

```
┌─────────────────────────────────────────────┐
│ [work] [personal] [client-x] │ ← worktopic tabs
├─────────────────────────────────────────────┤
│ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │
│ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ 5 │ │ ← workspaces in active worktopic
│ └───┘ └───┘ └───┘ └───┘ └───┘ │
└─────────────────────────────────────────────┘
```

Or vertical stack per worktopic in overview mode.

---

## Testing Strategy

### 1. Build Cosmic from source

```bash
# Clone repos
git clone https://github.com/pop-os/cosmic-comp
git clone https://github.com/pop-os/cosmic-workspaces-epoch
git clone https://github.com/pop-os/cosmic-epoch # meta repo

# Build cosmic-comp
cd cosmic-comp
cargo build --release

# Run nested (Wayland-in-Wayland)
WAYLAND_DISPLAY=wayland-99 ./target/release/cosmic-comp --nested
```

### 2. Nested compositor testing

You can run `cosmic-comp --nested` inside your existing Cosmic session. This gives you a sandboxed compositor window to test changes without affecting your main desktop.

### 3. TTY testing

For full testing:
```bash
# Switch to TTY2 (Ctrl+Alt+F2)
# Stop existing cosmic session if running
# Run your modified compositor
./target/release/cosmic-comp
```

### 4. Incremental approach

1. **First PR:** Add Worktopic data structure + basic keybind (no UI)
- Test with `Super+Tab` cycling through hardcoded worktopics

2. **Second PR:** Wire up protocol coordinates
- Verify clients receive 2D coordinates

3. **Third PR:** Update cosmic-workspaces-epoch UI
- Show worktopic grouping in switcher

---

## Configuration (Future)

```json
// ~/.config/cosmic/worktopics.json (or similar)
{
"worktopics": [
{ "name": "work", "workspaces": 5 },
{ "name": "personal", "workspaces": 3 },
{ "name": "client-x", "workspaces": 5 }
],
"default_worktopic": "work",
"keybinds": {
"switch_worktopic": "Super+Tab",
"move_to_worktopic": "Super+Shift+Tab"
}
}
```

---

## Entry Points in Code

### cosmic-comp

| Area | File (approximate) | What to look for |
|------|-------------------|------------------|
| Workspace state | `src/shell/mod.rs`, `src/shell/workspace.rs` | `Workspace`, `WorkspaceSet` structs |
| Keybindings | `src/input/mod.rs` | `KeyboardInput` handling |
| Workspace switching | `src/shell/mod.rs` | `activate_workspace`, `switch_workspace` |
| Protocol emission | `src/wayland/protocols/workspace.rs` | `zcosmic_workspace_*` implementations |

### cosmic-workspaces-epoch

| Area | File | What to look for |
|------|------|------------------|
| Layout | `src/lib.rs`, `src/view.rs` | Workspace grid rendering |
| Protocol handling | `src/workspace.rs` | Workspace state from compositor |

---

## Questions to Resolve

1. **Worktopic persistence** — Save/restore worktopic assignments on logout/login?
2. **Window rules** — Auto-assign windows to worktopics based on app class?
3. **Per-monitor behavior** — Should worktopics span all monitors (proposed) or be per-monitor?
4. **Empty worktopics** — Allow 0 workspaces? Auto-delete when empty?

---

## Next Steps

1. Clone `cosmic-comp`, get it building
2. Find the workspace switching code path
3. Add a hardcoded second worktopic
4. Wire `Super+Tab` to toggle between them
5. Test in nested mode
6. Iterate from there

---

## Resources

- [Cosmic workspace v2 protocol](https://wayland.app/protocols/cosmic-workspace-unstable-v2)
- [cosmic-comp DeepWiki](https://deepwiki.com/pop-os/cosmic-comp)
- [System76 blog: Tiling redesign](https://blog.system76.com/post/cosmic-de-tiling-redesign-and-libcosmic-rebasing/)
- [Issue #78: Workspace grid option](https://github.com/pop-os/cosmic-workspaces/issues/78)


Loading