> For the complete documentation index, see [llms.txt](https://faction-os.gitbook.io/faction-os-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/phases/phase_18/session_03_suggestion_routes_and_websocket_parity.md).

# Session 03: Suggestion Routes And WebSocket Parity

**Session ID**: `phase18-session03-suggestion-routes-and-websocket-parity` **Package**: apps/server **Status**: Not Started **Estimated Tasks**: \~12-25 **Estimated Duration**: 2-4 hours

***

## Objective

Ship the core `/suggestions/*` route family (accept, dismiss, summary, issue dismiss) and broadcast `suggestion_update` snapshots over WebSocket, including hydrate-on-connect.

***

## Scope

### In Scope (MVP)

* `POST /suggestions/:suggestionId/accept` with historical routing semantics: when targeting an internal hero, verify the hero exists and return a `send_prompt` action with the hero prompt endpoint; otherwise broadcast a `user_prompt` message and return `prompt_sent`
* `POST /suggestions/:suggestionId/dismiss` and `POST /issues/:issueId/dismiss` backed by manager dismissed-ID sets
* `GET /suggestions/summary` returning counts and severity buckets
* Zod request validation, rate limits, and body-size caps consistent with existing route conventions
* `suggestion_update` broadcast on every manager `emitUpdate`, plus snapshot hydrate for newly connected WebSocket clients
* Compatibility: keep emitting the existing string `idle_suggestion` event alongside snapshots for the current web store
* Remove shipped routes from `unsupportedRoutes.ts` (leave engine trigger routes listed until their sessions ship them)
* Route and WebSocket integration tests

### Out of Scope

* Scan/analyze/project-scan trigger and status routes (ship with their engines in Sessions 07-08)
* Web UI consumption (Sessions 09-10)

***

## Prerequisites

* [ ] Session 02 SuggestionManager available with emitUpdate path
* [ ] Existing hero/internal-hero prompt endpoint semantics reviewed

***

## Deliverables

1. Accept, dismiss, issue-dismiss, and summary routes with validation and rate limits
2. WebSocket `suggestion_update` broadcast and connect-time hydrate
3. Updated `unsupportedRoutes.ts` reflecting actually-shipped routes
4. Integration tests for routes, hydrate, and accept routing branches

***

## Success Criteria

* [ ] Accepting a suggestion routes to an existing hero or broadcasts a `user_prompt`, matching the documented contract
* [ ] Dismissals persist and dismissed items never reappear in snapshots
* [ ] New WebSocket clients receive a full snapshot on connect
* [ ] Server test suite passes with new coverage included

***

## Historical Evidence (EXAMPLES References)

Preserved from the 2026-06-07 parity audit (full audit in `PRD_phase_18.md` Appendix A). Evidence only; never import, copy, or transform historical code.

* `EXAMPLES/package-0.4.1/server/dist/index.js:1` - route family evidence:
  * `POST /suggestions/:suggestionId/accept` calls `acceptSuggestion`; when targeting an internal hero it verifies the hero exists and returns `action:"send_prompt"` with `endpoint:/internal-heroes/{heroId}/prompt`; otherwise it broadcasts a `user_prompt` websocket message and returns `action:"prompt_sent"`.
  * `POST /suggestions/:suggestionId/dismiss` and `POST /issues/:issueId/dismiss` backed by manager dismissed-ID sets.
  * `GET /suggestions/summary` backed by `getSummary`.
  * All `/suggestions` route registrations, including rate-limit middleware on `/suggestions/analyze`, `/suggestions/scan`, and `/suggestions/project-scan`.
* `EXAMPLES/package-0.4.1/server/dist/suggestionManager.js:1` - `acceptSuggestion` (idle suggestions, the shipped path) versus `acceptQuest` (returns `sourceType:"quest_board"` for codebase issues but is never called from `index.js`). Even in EXAMPLES, issue-accept was latent; parity target is accept for idle suggestions and dismiss-only for codebase issues.
* `EXAMPLES/findings/api-routes.txt:149` (route family), `:151` (accept), `:152` (dismiss), `:158` (summary).
* `EXAMPLES/findings/websocket-events.txt:53` and `:139` - `suggestion_update` snapshot carrying idle suggestions, codebase issues, session summaries, analysis result, and project scan.
* Excluded by phase decision (recorded, not ported):
  * `EXAMPLES/package-0.4.1/server/dist/featureGates.js:1` - `SUGGESTION_ENGINE:"suggestion_engine"` entitlement gate; HTTP 403 with `upgrade:true` and a `suggestion_engine_blocked` event, enforced in `index.js:1` at the `POST /suggestions/analyze` handler.
  * `EXAMPLES/package-0.4.1/server/dist/posthog.js:1` - `suggestion_generated`, `suggestion_accepted`, `suggestion_dismissed` events carrying `suggestion_id`; `index.js:1` calls `recordSuggestionAccepted()` inside the accept route.

## Current-Code Touchpoints (Audit Snapshot 2026-06-07)

* `apps/server/src/lib/unsupportedRoutes.ts:94` - historical `/suggestions` routes are currently listed as planned/unsupported; de-list only what this session actually ships.
* `apps/web/src/store/useGameStore.ts:850` - store consumes only `idle_suggestion` and keeps the latest twelve strings (compat emission must keep this working until Session 09).
* `apps/web/src/components/QuestBoard.tsx:26` - cards are non-clickable `<article>` elements today.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/phases/phase_18/session_03_suggestion_routes_and_websocket_parity.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
