Skip to content
Merged
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
101 changes: 101 additions & 0 deletions .specs/features/web-setup-redesign/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Web setup redesign

## Goal

Redesign `/setup` as a clear setup dashboard that uses the CodeDeck brand and the visual language of `/usage`.
The page must make current settings readable, explain edits as human changes, and preserve the setup controller and
API behavior.

## Out of scope

- Changes to the setup API envelope or its Portuguese keys.
- Changes to CLI `codedeck setup`, `src/config/*`, or `src/cli/*` except the `/setup` route wiring in `ui.ts`.
- Changes to `/usage`, Home, Review, or the web server.
- Removal or migration of legacy `profiles` data from a user's config.
- New runtime dependencies. The page remains one server-rendered string with inline CSS, SVG, and script.

## Requirements

### R1. Brand and chrome

- R1.1 The setup page SHALL include `BRAND_CSS` from `src/web/brand.ts`.
- R1.2 The setup page SHALL use `LOGO_FAVICON_HREF` as its favicon.
- R1.3 The setup page SHALL render its top bar with `renderTopBar` from `src/web/brand.ts`.
- R1.4 The top bar SHALL mark Setup as the active page.
- R1.5 The top bar SHALL link to every page registered with the UI route table, including Home, Review, Setup, and Usage.
- R1.6 WHEN `/setup` is rendered without options THEN the exported `SETUP_PAGE` constant SHALL remain usable by existing callers.
- R1.7 The `/setup` route SHALL pass the registered pages to `renderSetupPage`.
- R1.8 Cards, buttons, pills, inputs, and selects SHALL use the `/usage` palette and control styling.
- R1.9 Model identifiers SHALL use a monospace font.
- R1.10 No native control SHALL render with a light background.
- R1.11 WHEN the setup page is rendered without a supplied page list THEN its navigation SHALL contain only Setup.
- R1.12 WHEN the setup page is rendered without a supplied page list THEN its brand link SHALL target `/setup`.

### R2. Current state

- R2.1 Each role card SHALL show a current binding as a harness pill, model identifier, and effort value.
- R2.2 WHEN a role has no current binding THEN its card SHALL show `not set` as the current binding.
- R2.3 The current orchestrator SHALL show a matching `ORCHESTRATOR_PRESETS` preset name when it matches a preset.
- R2.4 WHEN the current orchestrator matches no preset THEN it SHALL show `custom` and readable field values.
- R2.5 Current orchestrator values SHALL NOT be rendered as JSON.
- R2.6 Current sandbox state SHALL use words instead of JSON.
- R2.7 Current autocompact state SHALL use words instead of JSON.
- R2.8 Current sandbox state SHALL show the literal configuration value in monospace.

### R3. Role editing

- R3.1 Each role card SHALL offer explicit `Keep current` and `Change` choices.
- R3.2 The role choice SHALL retain the `skip-<role>` checkbox ID and checked semantics.
- R3.3 WHEN the selected role binding uses the `opencode` harness THEN its effort select SHALL be hidden.
- R3.4 Each role SHALL start with its `skip-<role>` checkbox checked, including unbound roles.
- R3.5 WHEN a role is set to Keep current THEN its binding and effort controls SHALL be hidden.
- R3.6 WHEN a role is set to Change THEN its binding and effort controls SHALL be shown and prefilled from current state.
- R3.7 WHEN a current role's effort is the only edited field THEN its selection SHALL preserve the current harness and model.
- R3.8 WHEN a role has no current effort THEN its effort select SHALL default to Keep current.
- R3.9 Each role card SHALL show its title in a normal header inside the card.

### R4. Preview and result

- R4.1 WHEN a dry run or apply response contains `mudancas` THEN the page SHALL render one row for each change.
- R4.2 Each change row SHALL format paths such as `/agents/reviewer/effort` as `reviewer · effort`.
- R4.3 Each change row SHALL show the before value, an arrow, and the after value when both values are present.
- R4.4 WHEN `beforePresent` is false THEN the change row SHALL label the change as added.
- R4.5 WHEN `afterPresent` is false THEN the change row SHALL label the change as removed.
- R4.6 WHEN `mudancas` is empty THEN the preview SHALL say `No changes`.
- R4.7 A dry-run result SHALL show the status `Preview only, nothing written`.
- R4.8 An applied result SHALL show the status `Saved`.
- R4.9 An unchanged result SHALL show the unchanged status and any supplied message.
- R4.10 An error result SHALL show the error status and its supplied message.
- R4.11 The config, catalog, and binding validations SHALL render as compact status pills or rows.
- R4.12 A validation message SHALL render only when the response supplies one.
- R4.13 The default preview SHALL NOT print the complete proposed config.
- R4.14 The default preview SHALL NOT print legacy `profiles` or `activeProfile` values.
- R4.15 The full raw response MAY be available inside a collapsed `details` element named `Raw response`.
- R4.16 Values inserted into the preview with `innerHTML` SHALL be HTML-escaped.
- R4.17 Each change row SHALL group the before value, arrow, and after value together after its friendly path.

### R5. Actions

- R5.1 Preview and Apply SHALL appear in one action bar.
- R5.2 Apply SHALL be the primary blue action.
- R5.3 Preview and Apply SHALL be disabled while a request is in flight.
- R5.4 Preview and Apply SHALL be disabled until setup state is loaded.
- R5.5 The action bar SHALL stick to the viewport bottom and show selection, loading, in-flight, or error status on its left.
- R5.6 The sticky action bar SHALL NOT cover the last page content at 390px.

### R6. Layout

- R6.1 At 1440px, role cards SHALL use a four-column grid or a two-by-two grid when space is constrained.
- R6.2 At 390px, role cards SHALL stack in one column.
- R6.3 At 390px, `document.documentElement.scrollWidth` SHALL be no greater than 390.

### R7. Preserved behavior

- R7.1 `buildSetupSelection` SHALL retain its current selection semantics.
- R7.2 The setup controller SHALL retain its public `start`, `refreshCatalog`, `buildSelection`, `dryRun`, and `apply` methods.
- R7.3 Every existing element ID used by the controller SHALL remain in the rendered page.
- R7.4 Every existing element ID used by setup tests SHALL remain in the rendered page unless the test only asserts obsolete copy.
- R7.5 The off-catalog apply confirmation SHALL remain per role.
- R7.6 A protected action that returns 403 SHALL show the existing expired-session message.
- R7.7 Setup API request paths, methods, and body shapes SHALL remain unchanged.
- R7.8 Existing tests SHALL continue to pass, except markup-only assertions may change to match the new copy.
74 changes: 74 additions & 0 deletions .specs/features/web-setup-redesign/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Web setup redesign: tasks

Source of truth: `spec.md` in this folder.

## Design notes

- Keep `renderSetupPage(options)` as a self-contained HTML string. Export `SETUP_PAGE = renderSetupPage()` for
callers that need the default markup.
- Reuse `BRAND_CSS`, `LOGO_FAVICON_HREF`, and `renderTopBar`; copy only the setup-specific CSS into this page.
- Keep `buildSetupSelection` and the controller's public methods and request shapes unchanged.
- Browser-time helpers used by the controller must live inside `createSetupPageController`, because that function
is serialized into the page's inline script.
- Escape every dynamic value inserted into `innerHTML`, including preview fields and raw response content.
- Render a concise default preview from `resultado`, `mudancas`, and `validacoes`. Keep the full response behind
a collapsed disclosure if it is retained.
- Preserve the existing element IDs, including `skip-<role>`, even when their labels and styles change.

## T1. Specify the redesign

- Requirement: R1-R7.
- Files: `.specs/features/web-setup-redesign/spec.md`, `.specs/features/web-setup-redesign/tasks.md`.
- Produce one acceptance criterion per observable behavior and a coverage matrix at the end of this file.

## T2. Render the branded setup page

- Requirement: R1-R3, R6.
- Files: `src/web/setup-page.ts`, `src/web/setup-routes.ts`.
- Render the shared brand chrome and dark usage-style controls. Add `renderSetupPage(options)` and preserve the
`SETUP_PAGE` export. Pass registered pages from the UI route handler, and use a setup-only navigation default for
the standalone setup server.
- Show role bindings, effort, orchestrator preset or readable custom fields, sandbox, and autocompact as human text.
- Replace the role skip copy with explicit Keep current / Change affordance while retaining its ID and behavior.
Default each role to Keep current, collapse its fields, and prefill current binding and effort for Change.
- Keep opencode effort hidden and make the layout responsive.

## T3. Render readable preview and status

- Requirement: R4-R5, R7.
- Files: `src/web/setup-page.ts`, `tests/setup-page.test.ts`.
- Render a status banner, change rows, and compact validation state from the existing API envelope.
- Keep the raw response collapsed if shown. Escape all dynamic preview content.
- Put Preview and Apply in one sticky bottom action bar with a selection and request status on the left. Disable both
while loading or while an action is in flight.
- Add focused tests for current-state text, change rendering, validation states, escaping, and action availability.
- Update existing tests only when they pin old markup text, and record each changed assertion with its reason.

## T4. Wire registered page links

- Requirement: R1.3-R1.7.
- Files: `src/cli/commands/ui.ts`, `src/web/setup-routes.ts`, `tests/setup-web.test.ts`, `tests/web-cli.test.ts`.
- Pass the UI route table's page list into the setup renderer. Give standalone setup only its Setup link and point its
brand link back to `/setup`.
- Verify the UI route links to Home, Review, Setup, and Usage and standalone setup links only to Setup.

## T5. Verify behavior and browser layout

- Requirement: R1-R7.
- Commands: `npx vitest run tests/setup-page.test.ts tests/setup-web.test.ts tests/web-cli.test.ts`; `npx tsc --noEmit -p .`;
`npm run build`; scoped mutation probe; Chromium browser check at 1440x900 and 390x844.
- Record exact commands, pass/fail counts, mutation kills/survivors, console errors, scroll width, and screenshots in
`validation.md`.
- Dispatch a read-only CodeDeck reviewer on the final diff, read its artifact, and address its findings.

## Coverage matrix

| Layer | Test type | File | Command |
| --- | --- | --- | --- |
| Role selection and current-state formatting | unit | `tests/setup-page.test.ts` | `npx vitest run tests/setup-page.test.ts` |
| Preview, validations, escaping, and actions | unit | `tests/setup-page.test.ts` | `npx vitest run tests/setup-page.test.ts` |
| Setup route and registered-page navigation | route unit | `tests/setup-web.test.ts` | `npx vitest run tests/setup-web.test.ts` |
| UI route navigation | route unit | `tests/web-cli.test.ts` | `npx vitest run tests/web-cli.test.ts` |
| Setup page and API regression | focused tests | `tests/setup-page.test.ts`, `tests/setup-web.test.ts`, `tests/web-cli.test.ts` | `npx vitest run tests/setup-page.test.ts tests/setup-web.test.ts tests/web-cli.test.ts` |
| Type checking | compiler | TypeScript project | `npx tsc --noEmit -p .` |
| Browser output and responsive width | manual e2e | no committed test | `npm run build`, launch UI, Chromium at 1440x900 and 390x844 |
131 changes: 131 additions & 0 deletions .specs/features/web-setup-redesign/validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Web setup redesign validation

## Verification

- `npm install` completed earlier in this task. It changed the stale package version in `package-lock.json`; that
incidental change was restored. No dependency or lockfile change is part of this work.
- `npx vitest run tests/setup-page.test.ts tests/setup-web.test.ts tests/web-cli.test.ts` exited 1: 1 file passed,
2 files failed, 20 tests passed, and 22 failed. All 17 route tests in `tests/setup-web.test.ts` failed before
reaching their assertions because the environment returned `listen EPERM: operation not permitted 127.0.0.1`.
Five `tests/web-cli.test.ts` cases also failed after their server could not start. The output identified the same
`listen EPERM` restriction.
- `npx vitest run tests/setup-page.test.ts` passed: 1 file, 16 tests.
- A direct compiled route-handler check using `node --input-type=module` passed. It asserted UI setup links in order
Home, Review, Setup, Usage, and standalone setup links Setup only with its brand link pointing to `/setup`.
- `npx tsc --noEmit -p .` passed with exit code 0 and no diagnostics.
- `npm run build` passed. The script ran `tsc` and `npm run build:plugin`.
- `git diff --check` passed with no whitespace errors.

## Mutation probe

Temporarily changed the role prefill from `skip.checked = true` to `skip.checked = false`, then ran:

```text
npx vitest run tests/setup-page.test.ts -t 'keeps every role unchanged by default and prefills the current binding and effort'
```

The test failed at `expect(skip-reviewer.checked).toBe(true)`, showing the default-Keep-current behavior is covered.
The source was restored and the focused setup-page test passed afterward.

- Mutations killed: 1 of 1.
- Mutations survived: 0.

## Browser check

`/usr/bin/chromium --version` reported `Chromium 152.0.7977.82 Arch Linux`. A headless launch smoke test could not
start Chromium:

```text
/usr/bin/chromium --headless --no-sandbox --disable-gpu --disable-dev-shm-usage --user-data-dir=/tmp/setup-redesign/chromium-smoke-profile --dump-dom 'data:text/html,<html><title>smoke</title><body>ok</body></html>'
exit 133
[ERROR:third_party/crashpad/crashpad/util/linux/socket.cc:45] setsockopt: Operation not permitted (1)
```

After `npm run build`, the UI launch command also could not bind its local server:

```text
env RUN_AGENT_DIR=/tmp/setup-redesign/run-agent RUN_AGENT_CONFIG_DIR=/tmp/setup-redesign/config node dist/cli/index.js ui --no-open --port 3147
Failed to listen on 127.0.0.1:3147: listen EPERM: operation not permitted 127.0.0.1:3147
```

The real `/setup` browser interaction therefore did not run. Console errors and 390px `scrollWidth` could not be
measured. The requested screenshots were not refreshed:

- `/tmp/setup-redesign/desktop-before-preview.png`
- `/tmp/setup-redesign/desktop-after-preview.png`
- `/tmp/setup-redesign/mobile.png`

Those paths contain screenshots from the earlier implementation and are stale for this corrective round.

## Existing assertions

- `tests/setup-web.test.ts` now asserts Setup-only navigation for its standalone route. It replaces expectations for
Home, Review, and Usage links that are not served by standalone `codedeck setup`; the brand link now returns to
`/setup` too.
- `tests/setup-page.test.ts` changes the expected current sandbox text from `workspace write` to the literal
`workspace-write`, as requested. No existing test asserted that bound roles began with Change.
- `tests/web-cli.test.ts` adds assertions that the UI-served setup navigation includes Home, Review, Setup, and Usage.

## Reviewer findings

Both findings from reviewer session `205e` are addressed in the current diff:

- `src/cli/commands/ui.ts` rebuilds setup routes with the UI page list. The route-handler check confirmed Home,
Review, Setup, and Usage navigation.
- `src/web/setup-routes.ts` supplies Setup only when no page list is provided. The route-handler check confirmed
Setup-only navigation and a brand link to `/setup` for standalone setup.

A final reviewer dispatch was attempted with `codedeck run --role reviewer --no-worktree --bg --json`, but CodeDeck
could not start its daemon (`Failed to start daemon`). It was retried after the final alignment change with the same
result, so the required read-only final review artifact is unavailable.

## Final role-grid adjustment verification

After adding `align-items: start` to the role grid:

- `npx vitest run tests/setup-page.test.ts` passed: 1 file, 16 tests.
- `npx tsc --noEmit -p .` passed with exit code 0 and no diagnostics.
- `npm run build` passed, including `tsc` and `build:plugin`.

## Orchestrator-verified results

The orchestrator verified the prior implementation outside this sandbox in the session `2cfc` worktree on
2026-09-24:

- `npx vitest run tests/setup-page.test.ts tests/setup-web.test.ts tests/web-cli.test.ts`: 42 of 42 tests passed.
- TypeScript check: clean.
- Headless Chromium against `dist`: navigation showed Home, Review, Setup, and Usage; all roles defaulted to Keep
current; changing only reviewer effort produced exactly `reviewer · effort`, `low → high`; mobile
`document.documentElement.scrollWidth` was 390; console errors: zero.

This browser run predates the final `align-items: start` role-grid adjustment. After that adjustment, the local
focused setup-page test, TypeScript check, and build results are recorded above and below; the sandbox still prevents
local headless Chromium from starting.

## Review remediation

- `createSetupPageController` now records the last rendered envelope by reference and its preview error. Form updates
keep the existing `setup-result` DOM, while a new response renders a new preview.
- `createUiRoutes` creates the setup routes once with a shared page list. The setup and usage top bars include Home,
Review, Setup, and Usage. The home page receives the same list without its Home entry.
- Added assertions that the home page has no self-link and setup navigation still links Home. Added an innerHTML write
counter test for preview preservation and response replacement.
- Extended the manually resolved in-flight action test to assert `Preparing preview...` and `Saving setup...`.

Verification after the remediation:

- `npx vitest run tests/setup-page.test.ts`: passed, 1 file and 17 tests.
- `npx tsc --noEmit -p .`: passed with exit code 0 and no diagnostics.
- `npx vitest run tests/web-cli.test.ts tests/setup-web.test.ts`: passed, 2 files and 26 tests. Local HTTP listeners
worked in this run.
- `git diff --check`: passed with no whitespace errors.
- Read-only review: `codedeck run --role reviewer --no-worktree --bg --json` completed as session `3933`; the
reviewer reported no findings. The review also ran `npx vitest run tests/setup-page.test.ts tests/web-cli.test.ts`,
which passed with 2 files and 26 tests.

Mutation probe:

- Temporarily restored unconditional `setup-result.innerHTML` assignment and ran
`npx vitest run tests/setup-page.test.ts -t 'preserves the rendered raw preview on form updates and refreshes it for a new response'`.
The regression test failed as expected: it observed 7 writes instead of 6 after a binding input event. The guard was
restored, then the full setup-page test passed with 17 of 17 tests.
Loading
Loading