feat(web): merge Specs route into Planner page (UC-1) #262

Closed
opened 2026-04-21 20:31:17 +00:00 by code-lead · 0 comments
Collaborator

As an operator, I want to browse and edit specs/*.md from the Planner page, so that specs and the sessions that produce them live on one surface instead of forcing me to jump between tabs.

Acceptance criteria

Planner sidebar

  • Left pane of /app/planner grows a Specs section alongside the existing sessions list. It reuses the same collapsible container shape so the pane's visual language stays consistent.
  • Specs list renders one row per specs/*.md file with name (specs/foo.mdfoo), last-modified timestamp, and a small type:user-story badge when a tracking issue is linked in the file's front-matter or detected heuristically from the body.
  • "New spec" button opens the same modal today's /app/specs route owns (input + create-button flow) — lifted as a component so the Planner sidebar and the redirected route both reach it.

Editor surface

  • Selecting a spec row loads the existing SpecEditor component into the Planner's middle column, replacing the chat transcript while the spec is active. A Back to session control returns to the previously-active session without re-fetching it.
  • Editing + saving uses the current saveSpec mutation from lib/foreman.ts; no change to the server endpoint.
  • Two action buttons next to the editor: Draft with foreman seeds a new session pre-filled with @specs/<name>.md, Breakdown posts to /breakdown with { repo, spec_path, tracking_issue? } and drops the task id into a toast.

Route + redirect

  • /app/specs route file is removed; the file-based router resolves the path via a shared 301-equivalent redirect to /app/planner?spec=<name> that preserves the ?name= query param.
  • Planner's validateSearch learns the spec?: string param; when set, the spec editor mounts active on first render.

Nav

  • components/app-shell.tsx drops the Specs entry from both the top-nav and bottom-tab arrays. Tests that assert nav labels are updated in the same commit.

Tests

  • Vitest: the Planner route renders the Specs section and falls back to the sessions list when ?spec= is absent.
  • Vitest: clicking a spec row navigates with ?spec=<name> and mounts the editor.
  • Playwright: existing /app/specs?name=foo URL lands on /app/planner?spec=foo with the editor open.
  • Biome + bun run typecheck pass with no new warnings.

Out of scope

  • Any new spec-authoring capability (AI-assisted drafting, templates). This story is a pure merge; behaviour is unchanged.
  • Changes to the POST /breakdown or /foreman/* endpoints.
  • Deleting SpecEditor or its tests — the component is kept, only its route is moved.

References

  • Spec: specs/ui-consolidation.md § UC-1 (Merge Specs into Planner)
  • Tracking: #259
  • apps/web/src/routes/specs.tsx (deleted)
  • apps/web/src/routes/planner.tsx, planner.index.tsx (extended)
  • apps/web/src/components/app-shell.tsx (nav prune)
  • apps/web/src/components/spec-editor/ (moved, not changed)

Dependencies

  • Blocks: #263 (UC-2 reuses the redirect helper pattern established here)
  • None blocking this story.
As an operator, I want to browse and edit `specs/*.md` from the Planner page, so that specs and the sessions that produce them live on one surface instead of forcing me to jump between tabs. ## Acceptance criteria ### Planner sidebar - [ ] Left pane of `/app/planner` grows a **Specs** section alongside the existing sessions list. It reuses the same collapsible container shape so the pane's visual language stays consistent. - [ ] Specs list renders one row per `specs/*.md` file with name (`specs/foo.md` → `foo`), last-modified timestamp, and a small `type:user-story` badge when a tracking issue is linked in the file's front-matter or detected heuristically from the body. - [ ] "New spec" button opens the same modal today's `/app/specs` route owns (input + create-button flow) — lifted as a component so the Planner sidebar and the redirected route both reach it. ### Editor surface - [ ] Selecting a spec row loads the existing `SpecEditor` component into the Planner's middle column, replacing the chat transcript while the spec is active. A **Back to session** control returns to the previously-active session without re-fetching it. - [ ] Editing + saving uses the current `saveSpec` mutation from `lib/foreman.ts`; no change to the server endpoint. - [ ] Two action buttons next to the editor: **Draft with foreman** seeds a new session pre-filled with `@specs/<name>.md`, **Breakdown** posts to `/breakdown` with `{ repo, spec_path, tracking_issue? }` and drops the task id into a toast. ### Route + redirect - [ ] `/app/specs` route file is removed; the file-based router resolves the path via a shared 301-equivalent redirect to `/app/planner?spec=<name>` that preserves the `?name=` query param. - [ ] Planner's `validateSearch` learns the `spec?: string` param; when set, the spec editor mounts active on first render. ### Nav - [ ] `components/app-shell.tsx` drops the `Specs` entry from both the top-nav and bottom-tab arrays. Tests that assert nav labels are updated in the same commit. ### Tests - [ ] Vitest: the Planner route renders the Specs section and falls back to the sessions list when `?spec=` is absent. - [ ] Vitest: clicking a spec row navigates with `?spec=<name>` and mounts the editor. - [ ] Playwright: existing `/app/specs?name=foo` URL lands on `/app/planner?spec=foo` with the editor open. - [ ] Biome + `bun run typecheck` pass with no new warnings. ## Out of scope - Any new spec-authoring capability (AI-assisted drafting, templates). This story is a pure merge; behaviour is unchanged. - Changes to the `POST /breakdown` or `/foreman/*` endpoints. - Deleting `SpecEditor` or its tests — the component is kept, only its route is moved. ## References - Spec: `specs/ui-consolidation.md` § UC-1 (Merge Specs into Planner) - Tracking: #259 - `apps/web/src/routes/specs.tsx` (deleted) - `apps/web/src/routes/planner.tsx`, `planner.index.tsx` (extended) - `apps/web/src/components/app-shell.tsx` (nav prune) - `apps/web/src/components/spec-editor/` (moved, not changed) ## Dependencies - **Blocks:** #263 (UC-2 reuses the redirect helper pattern established here) - None blocking this story.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#262
No description provided.