Skip to content

Commit e95b5d3

Browse files
feat: improved workspace ux baseline.
1 parent 92310ee commit e95b5d3

19 files changed

Lines changed: 321 additions & 682 deletions

docs/idb-workspace-state.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Each workspace record may include:
2323
- `head`
2424
- `prTitle`
2525
- `prNumber`
26-
- `prContextState` (`inactive` | `active` | `disconnected` | `closed`)
26+
- `prContextState` (`inactive` | `active` | `closed`)
2727
- Runtime/editor state:
2828
- `renderMode`
2929
- `activeTabId`
@@ -37,7 +37,7 @@ IDB supports that by storing:
3737

3838
- Full workspace snapshots
3939
- Repo-scoped context records
40-
- Historical transitions such as disconnected or closed PR context
40+
- Historical transitions such as closed PR context
4141

4242
## Design Rule
4343

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Issue #99 + Workspaces Drawer UX Plan
2+
3+
## Goal
4+
5+
Simplify PR/workspace lifecycle and the Workspaces drawer UX by:
6+
7+
- removing disconnected state and Disconnect action paths
8+
- using workspace terminology in the drawer (not context)
9+
- separating new workspace initialization from workspace selection
10+
- preserving strict explicit intent semantics (no implicit apply/mutation from select changes)
11+
12+
## Decisions
13+
14+
- New workspace is an explicit direct action via a `New workspace` button.
15+
- `New workspace` must work for both repository scopes and `Local`.
16+
- `Open` remains the explicit action for applying an existing stored workspace.
17+
- If the selected repository has no stored workspaces, hide the workspace select and show the new-workspace path.
18+
19+
## Implementation Steps
20+
21+
1. Remove disconnected model paths (Issue #99)
22+
23+
- Remove Disconnect control from UI.
24+
- Remove disconnected event wiring and runtime callbacks.
25+
- Remove disconnected public action paths.
26+
- Normalize legacy `disconnected` records to `inactive` during restore/normalization.
27+
28+
2. Redesign drawer flow
29+
30+
- Replace starter option-in-select behavior with a dedicated `New workspace` button adjacent to repository select.
31+
- Keep workspace select for stored workspaces only.
32+
- Hide workspace select when no stored workspaces exist for the selected scope.
33+
- Keep strict explicit selection semantics (no auto-apply from select/filter changes).
34+
35+
3. Update copy and accessibility
36+
37+
- Replace "Stored contexts" and related "context" wording with "Workspace" wording.
38+
- Update status and aria labels consistently.
39+
40+
4. Remove obsolete code paths
41+
42+
- Remove starter prefix constants and parsing.
43+
- Remove disconnected-only logic and stale styling/branches.
44+
45+
5. Update tests
46+
47+
- Remove/replace disconnected-focused scenarios.
48+
- Update helpers/selectors to new workspace labels and `New workspace` action.
49+
- Add/adjust scenarios for empty repository scope (select hidden) and explicit Open behavior for existing workspaces.
50+
51+
6. Update docs
52+
53+
- Update storage/state docs to remove disconnected semantics.
54+
- Update drawer UX docs to reflect repository row + new workspace action flow.
55+
56+
## Verification
57+
58+
1. `npm run lint`
59+
2. Targeted Playwright (Chromium first):
60+
61+
- `playwright/github-pr-drawer/active-context-switch.spec.ts`
62+
- `playwright/github-pr-drawer/open-pr-create.spec.ts`
63+
64+
3. Broader Playwright run for workspace/PR drawer flows.
65+
4. Manual verification in dev server for:
66+
67+
- repository + new workspace row
68+
- local new workspace creation
69+
- hidden workspace select when no stored entries
70+
- explicit Open required for existing entries
71+
- no Disconnect control

docs/localstorage-state.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Do not store pull request context in `localStorage`.
1919
Examples that must stay out of `localStorage`:
2020

2121
- Selected repository preference (`owner/repo`)
22-
- PR context state (`active`, `disconnected`, `closed`, `inactive`)
22+
- PR context state (`active`, `closed`, `inactive`)
2323
- PR number and URL
2424
- PR base/head/title/body
2525
- PR drawer repository-scoped workflow state

docs/pr-context-storage-matrix.md

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ See the full storage ownership docs for non-PR keys:
2020
- Database: `knighted-develop-workspaces`
2121
- Object store: `prWorkspaces`
2222
- Relevant fields in each workspace record:
23-
- `prContextState`: `inactive` | `active` | `disconnected` | `closed`
23+
- `prContextState`: `inactive` | `active` | `closed`
2424
- `prNumber`: `number | null`
2525
- `prTitle`, `base`, `head`
2626
- `repo`
@@ -34,12 +34,11 @@ See the full storage ownership docs for non-PR keys:
3434

3535
Use this matrix as the source of truth when debugging UI/storage mismatch.
3636

37-
| Scenario | IDB `prContextState` | IDB `prNumber` | localStorage PR fields | Notes |
38-
| --------------------------------------------- | -------------------- | --------------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------- |
39-
| A. Local workspace only, no PR context | `inactive` | `null` | none | No connected PR context. |
40-
| B. Workspace is for an active, open PR | `active` | PR number | none | Push mode in PR controls. |
41-
| C. Workspace is for a disconnected PR context | `disconnected` | last known PR number if available | none | Opening this workspace from Workspaces restores PR runtime context and verifies open/closed state with GitHub. |
42-
| D. Workspace is for a PR closed on GitHub | `closed` | closed PR number | none | Historical context retained for debugging/reference. |
37+
| Scenario | IDB `prContextState` | IDB `prNumber` | localStorage PR fields | Notes |
38+
| ----------------------------------------- | -------------------- | ---------------- | ---------------------- | ---------------------------------------------------- |
39+
| A. Local workspace only, no PR context | `inactive` | `null` | none | No connected PR context. |
40+
| B. Workspace is for an active, open PR | `active` | PR number | none | Push mode in PR controls. |
41+
| C. Workspace is for a PR closed on GitHub | `closed` | closed PR number | none | Historical context retained for debugging/reference. |
4342

4443
## Current Workspace Selection On Load
4544

@@ -82,9 +81,8 @@ When the UI does not match expected PR state:
8281
- `prNumber`
8382
- `repo`, `head`, `prTitle`
8483
2. Compare against the matrix above.
85-
3. If scenario C is expected, open that workspace from Workspaces to restore runtime PR context.
86-
4. If the PR is still open on GitHub, expect PR controls to return to Push mode and the workspace record to transition back to `active`.
87-
5. If the PR is no longer open, expect Open PR mode to remain and status messaging to explain verification results.
84+
3. If the PR is still open on GitHub, expect PR controls to return to Push mode and the workspace record to transition back to `active`.
85+
4. If the PR is no longer open, expect Open PR mode to remain and status messaging to explain verification results.
8886

8987
## Console Snippets
9088

@@ -99,19 +97,13 @@ indexedDB.open('knighted-develop-workspaces').onsuccess = event => {
9997
}
10098
```
10199

102-
## Reconnect Behavior
103-
104-
Reconnect behavior from the Workspaces drawer is implemented.
105-
106-
Opening a `disconnected` workspace record restores active PR runtime context for that repository and reinitializes editor state from the selected workspace record.
107-
108100
## End-Of-Session Behavior
109101

110-
`Disconnect` and `Close` are treated as end-of-session actions for PR-linked workspaces.
102+
`Close` is the end-of-session action for PR-linked workspaces.
111103

112-
When either action is confirmed:
104+
When close is confirmed:
113105

114-
1. The current workspace is archived as historical (`disconnected` or `closed`).
106+
1. The current workspace is archived as historical (`closed`).
115107
2. The app immediately switches to a fresh local workspace (`inactive`) with a single empty entry tab.
116108
3. Status messaging guides the user to continue locally or reopen a stored workspace from Workspaces.
117109

playwright/github-byot-ai.spec.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -768,21 +768,16 @@ test('BYOT remembers selected repository across reloads', async ({ page }) => {
768768

769769
await page.getByRole('button', { name: 'Workspaces' }).click()
770770
const workspaceRepositoryFilter = page.getByLabel('Workspace repository filter')
771-
const storedContextsSelect = page.getByLabel('Stored local editor contexts')
772-
const openStoredContextButton = page.getByRole('button', {
773-
name: 'Open',
771+
const newWorkspaceButton = page.getByRole('button', {
772+
name: 'New workspace',
774773
exact: true,
775774
})
776775
await expect(workspaceRepositoryFilter).toBeVisible()
777776
await workspaceRepositoryFilter.selectOption('knightedcodemonkey/develop')
778777
await expect(workspaceRepositoryFilter).toHaveValue('knightedcodemonkey/develop')
779778

780-
await expect(storedContextsSelect).toBeVisible()
781-
await storedContextsSelect.selectOption({
782-
label: 'Start new context for knightedcodemonkey/develop',
783-
})
784-
await expect(openStoredContextButton).toBeEnabled()
785-
await openStoredContextButton.click()
779+
await expect(newWorkspaceButton).toBeVisible()
780+
await newWorkspaceButton.click()
786781
await page.getByRole('button', { name: 'Close workspaces drawer' }).click()
787782

788783
await ensureOpenPrDrawerOpen(page)

0 commit comments

Comments
 (0)