> 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/sessions/phase18-session01-protocol-suggestion-contract-parity/spec.md).

# Session Specification

**Session ID**: `phase18-session01-protocol-suggestion-contract-parity` **Phase**: 18 - Quest Board Suggestion Parity **Status**: Not Started **Created**: 2026-06-09 **Package**: packages/protocol **Package Stack**: TypeScript

***

## 1. Session Overview

This session defines the canonical typed Quest Board contracts in `packages/protocol` so every later Phase 18 server and web session builds on shared shapes instead of ad hoc strings. The current contract surface is minimal: `idle_suggestion` carries plain string prompts, the `quest_board` event is defined but unused by any server or client flow, and the web store models suggestions as `{ heroId, text }` only. Phase 18 requires the recovered multi-source model: typed idle suggestions, codebase issues, on-demand analysis results, project scan items, and session summaries, all carried by a `suggestion_update` snapshot event plus accept/dismiss, scan, and summary route contracts.

The work stays in `packages/protocol` and its focused tests. It does not add the server SuggestionManager, Express routes, engines, persistence, or web store changes; those belong to Sessions 02 through 10 and depend on this contract being clear and compile-safe first. The session follows the proven Phase 17 notice pattern: exported `as const` vocabularies, pure fail-closed guards and parsers, bounded normalization helpers, and compatibility aliases so existing consumers keep compiling.

`EXAMPLES/` material referenced by the Phase 18 PRD Appendix A is traceability evidence only. Behavior may be studied and represented in current source, but no historical code, bundles, or assets are imported, copied, or transformed directly, and no new contract may weaken local-first privacy boundaries.

***

## 2. Objectives

1. Define typed card shapes for all five Quest Board sources: idle suggestions, codebase issues, session summaries with follow-up tasks, on-demand analysis results, and project scan results, including parity constants (item caps, dismissed-ID cap, freshness windows).
2. Define the `suggestion_update` snapshot event plus accept/dismiss, scan trigger/status, and summary (counts plus severity buckets) request and response contracts, including hero-routed accept (`send_prompt`) versus broadcast (`prompt_sent`) results.
3. Add pure fail-closed validation and bounded normalization helpers for every vocabulary, card shape, file-path field, and the full mixed-source snapshot payload.
4. Reconcile the existing events: keep `idle_suggestion` as a typed compatibility emission and formally retire the unused `quest_board` event with a documented decision.
5. Prove the contracts with focused protocol tests covering parsing, validation, bounds, and rejection of malformed payloads.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase17-session10-validation-documentation-and-handoff` - closes Phase 17 and establishes the contract-first, manager-owned persistence, and snapshot-event patterns this phase reuses.

### Required Tools/Knowledge

* Node 26.2.0 or newer with npm workspaces.
* TypeScript contract editing in `packages/protocol`.
* Vitest test style used by existing protocol tests (root Vitest projects).
* Phase 18 PRD Appendix A card-shape inventory and the Session 01 stub.
* The `notices.ts` validator pattern (vocab arrays, guards, parse helpers, bounded normalization, validation-result shape).

### Environment Requirements

* Work from the repository root.
* Use package-relative monorepo paths from the repo root.
* Keep all generated and edited files ASCII-only with Unix LF line endings.

***

## 4. Scope

### In Scope (MVP)

* Protocol consumers can import a typed idle suggestion shape - id, session and hero linkage, title, text, category, priority, created-at timestamp.
* Protocol consumers can import a typed codebase issue shape - id, issue type (todo-family markers, git\_status, lint, build, test), severity, repo-relative file path, line, message/title, suggested prompt, suggested agent type.
* Protocol consumers can import a typed on-demand analysis result - item types (potential\_bug, error\_handling, code\_style, refactoring, performance, feature\_idea, enhancement), validated priority, generated-at and freshness metadata.
* Protocol consumers can import a typed project scan result - title, description, prompt, category (architecture, dependencies, performance, security, testing, feature\_idea), effort (small, medium, large), priority, capped at 4 items.
* Protocol consumers can import a typed session summary - follow-up tasks with categories test, documentation, refactor, validation.
* WebSocket consumers can type the `suggestion_update` snapshot - idle suggestions, codebase issues, session summaries, analysis result, project scan, and scan status in one event payload.
* Server and web packages can type accept/dismiss flows - accept request and response shapes including hero-routed `send_prompt` versus broadcast `prompt_sent` results, suggestion dismiss, and issue dismiss contracts.
* Server and web packages can type scan and summary flows - scan trigger/status shapes and a summary contract with counts plus severity buckets.
* Later packages can fail closed on invalid values - pure guards, parsers, and bounded normalization helpers for every vocabulary and card shape, including parity caps (4 project scan items, 50 issues per category, 100 dismissed IDs FIFO) and freshness windows (analysis 30 minutes, project and codebase scan 24 hours) as exported constants.
* Existing consumers keep compiling - `idle_suggestion` stays as a typed compatibility emission; the unused `quest_board` event is formally retired with the decision documented.

### Out of Scope (Deferred)

* Server SuggestionManager, persistence, and dismissed-ID runtime tracking - *Reason: Session 02 owns manager state, debounced atomic persistence, and shutdown flush.*
* Express `/suggestions/*` routes, WebSocket emission, and rate limits - *Reason: Session 03 owns runtime route validation and handlers.*
* Idle lifecycle, session summary, scan, analysis, and project scan engines - *Reason: Sessions 04 through 08 own engine behavior, orchestration, and ignore patterns.*
* Web store, typed cards, actions, and keyboard shortcuts - *Reason: Sessions 09 and 10 own UI and store behavior.*
* Suggestion telemetry and entitlement gating shapes - *Reason: excluded for this phase by PRD decision (hosted-services guardrails, local-first).*
* Codebase-issue quest-accept contract (`sourceType: "quest_board"`) - *Reason: latent and unwired even in EXAMPLES; parity target is accept for idle suggestions and dismiss-only for codebase issues.*

***

## 5. Technical Approach

### Architecture

Keep `packages/protocol` as the source of truth for cross-package Quest Board contracts. A new `suggestions.ts` module owns the vocabularies, parity constants, card interfaces, snapshot shape, REST request/response contracts, pure guards, parsers, and bounded normalization helpers. `events.ts` consumes those types to define the `suggestion_update` event, keeps `idle_suggestion` as a compatibility emission, and retires the unused `quest_board` interface. `rest.ts` aliases the accept/dismiss, scan, and summary REST contracts the same way it does for notices, and `index.ts` exports the new module from the barrel.

The helper surface must stay pure and deterministic so server, web, CLI, hooks, and Worker code can reuse it without runtime dependencies. Validation fails closed for unknown enum values; arrays are capped to the parity constants; file-path fields reject absolute paths, traversal, and URL-like values following the established `notices.ts` related-file rules. Runtime request validation with Zod remains a server concern for Session 03; the protocol package keeps the hand-rolled pure-validator style used everywhere else in `packages/protocol`.

### Design Patterns

* Protocol-first contracts: shared shapes land before package-specific runtime behavior (Phase 17 lesson, P03).
* Canonical contract plus compatibility aliases: `suggestion_update` is canonical; `idle_suggestion` remains a typed compat emission until the web store migrates (Session 09).
* Explicit enum vocabularies: exported `as const` arrays keep tests and consumers synchronized and make enum handling exhaustive.
* Fail-closed validation: unknown types, categories, efforts, priorities, severities, and statuses are rejected, never coerced into trusted cards.
* Bounded everything: exported caps and length limits prevent unbounded arrays and oversized text from entering snapshots or persistence.

### Technology Stack

* TypeScript in `packages/protocol`.
* Vitest for focused root test runs (protocol project).
* Package typecheck through `npm --workspace packages/protocol run typecheck`.
* Biome formatting and linting through root workspace commands.

***

## 6. Deliverables

### Files to Create

| File                                          | Purpose                                                                                    | Est. Lines |
| --------------------------------------------- | ------------------------------------------------------------------------------------------ | ---------- |
| `packages/protocol/src/suggestions.ts`        | Vocabularies, parity constants, card interfaces, snapshot, REST contracts, guards, helpers | \~420      |
| `packages/protocol/tests/suggestions.test.ts` | Card shape, guard, helper, and snapshot fixture coverage                                   | \~280      |

### Files to Modify

| File                                     | Changes                                                                                                     | Est. Lines |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------- |
| `packages/protocol/src/events.ts`        | Add `suggestion_update` event, type `idle_suggestion` compat note, retire `quest_board`, update event union | \~45       |
| `packages/protocol/src/index.ts`         | Barrel export for `suggestions.js`                                                                          | \~1        |
| `packages/protocol/src/rest.ts`          | Accept/dismiss, scan trigger/status, and summary REST aliases                                               | \~30       |
| `packages/protocol/tests/events.test.ts` | `suggestion_update` payload, `idle_suggestion` compat, `quest_board` retirement coverage                    | \~40       |
| `packages/protocol/tests/rest.test.ts`   | REST contract type tests for the suggestion route family                                                    | \~35       |
| `packages/protocol/README_protocol.md`   | Quest Board contract ownership, compat decision, privacy boundary notes                                     | \~30       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] All shapes named in the parity audit card-metadata rows exist as exported protocol types with runtime validation, including `suggestedAgentType` on codebase issues.
* [ ] Analysis item types are exactly `potential_bug`, `error_handling`, `code_style`, `refactoring`, `performance`, `feature_idea`, `enhancement`.
* [ ] Project scan categories are exactly `architecture`, `dependencies`, `performance`, `security`, `testing`, `feature_idea` with effort `small`, `medium`, `large` and a 4-item cap.
* [ ] Follow-up task categories are exactly `test`, `documentation`, `refactor`, `validation`.
* [ ] The `suggestion_update` snapshot schema validates a full mixed-source fixture (idle suggestions, issues, summaries, analysis, project scan, scan status) and rejects malformed payloads.
* [ ] Accept response contract distinguishes hero-routed `send_prompt` from broadcast `prompt_sent`; dismiss contracts exist for suggestions and issues.
* [ ] Parity constants are exported: project scan cap 4, issues per category cap 50, dismissed-ID cap 100, analysis freshness 30 minutes, project and codebase scan freshness 24 hours.
* [ ] `idle_suggestion` remains typed and compiling for existing consumers; `quest_board` is retired with the decision documented.

### Testing Requirements

* [ ] Focused suggestion contract tests written and passing.
* [ ] Existing events and REST protocol tests updated and passing.
* [ ] Package typecheck passing.

### Non-Functional Requirements

* [ ] No contract implies hosted identity, entitlement gating, telemetry capture, trusted erasure, or real executors.
* [ ] File-path fields accept repo-relative paths only and fail closed on absolute paths, traversal segments, and URL-like values.
* [ ] Protocol helpers remain dependency-free and reusable by server, web, CLI, hooks, and Worker packages.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.

***

## 8. Implementation Notes

### Key Considerations

* Follow the `notices.ts` module pattern exactly: vocab `as const` arrays, `is*` guards, `parse*` fail-closed helpers returning the shared validation-result shape, `normalize*` bounded helpers, and exported length and count constants.
* `packages/protocol/src/index.ts` needs one new barrel line for `suggestions.js`; events and rest are already exported.
* The protocol package has only a `typecheck` script; focused runtime tests run through the root Vitest command.
* `quest_board` (`packages/protocol/src/events.ts:386`) has no consumers outside `events.ts`, so formal retirement is the recommended reconciliation; record the decision in the README and the events test.
* Freshness predicates should take an explicit `now` argument so they stay deterministic and testable; no internal clock reads.
* Path safety rules for issue `filePath` should mirror the notice related-files helper (no absolute, no traversal, no URL-like, bounded length); full repository-boundary checks stay with the server sessions.

### Potential Challenges

* Vocabulary drift against Appendix A: copy the enum inventories directly from the PRD rows and assert them verbatim in tests so later engine sessions cannot diverge silently.
* Over-validating in protocol: keep helpers pure and bounded; runtime ownership (manager state, route limits, scan execution) belongs to later sessions.
* Compatibility breakage: `IdleSuggestionEvent` consumers (server route, web store, mock generator) must keep compiling unchanged; do not alter its payload shape this session.
* Snapshot shape churn: Sessions 02-10 all consume `SuggestionSnapshot`; reject the temptation to leave fields loosely typed "for later" - unknown keys and partial snapshots should fail closed now.

### Relevant Considerations

* \[P03-packages/protocol] **Protocol leads cross-package work**: every shared suggestion, issue, analysis, project-scan, session-summary, snapshot-event, and route shape lands here before server or web sessions begin.
* \[P17] **Notice Board parity is a shared contract**: the same coordinated cross-package discipline applies to suggestion shapes; one-package changes will drift parity, so contracts ship complete in this session.
* \[P07] **Redaction is boundary-specific**: suggestion text, issue messages, and snapshot payloads must avoid raw prompts, secrets, and broad absolute paths; bounded lengths and path rejection are contract-level enforcement.
* \[P03] **Stable docs are the current contract**: `EXAMPLES/` and PRD Appendix A are traceability evidence only; no historical code is imported.
* \[P17-packages/protocol] **Canonical contract plus compatibility aliases** (lesson): recover the authoritative shape without forcing a hard cutover; `idle_suggestion` stays as the compat emission until Session 09.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* Invalid enum values (issue type, analysis type, category, effort, priority, severity, scan status, follow-up category) accepted and later interpreted as trusted Quest Board cards.
* File-path fields in issue cards leaking absolute paths, traversal, or URL-like values into snapshots that later persist to disk and emit over WebSocket.
* Unbounded arrays (issues, project scan items, dismissed IDs, follow-ups) compiling fine but enabling oversized snapshots downstream.
* Compatibility emission (`idle_suggestion`) and canonical snapshot (`suggestion_update`) drifting apart because the compat shape was modified instead of frozen.

***

## 9. Testing Strategy

### Unit Tests

* Assert exported vocabularies match the PRD Appendix A inventories verbatim (issue types, severities, analysis item types, project scan categories, efforts, follow-up categories, scan statuses).
* Test card interfaces via parse helpers: valid idle suggestion, codebase issue (including `suggestedAgentType`), analysis result, project scan item, and session summary fixtures round-trip.
* Test guards and parsers fail closed for unknown enum values, wrong types, and missing required fields.
* Test bounded helpers: text and prompt length caps, project scan 4-item cap, 50-issues-per-category cap, dismissed-ID 100 cap with FIFO order, file-path rejection (absolute, traversal, URL-like, over-length).
* Test freshness predicates at, inside, and outside the 30-minute and 24-hour windows with explicit `now` values.

### Integration Tests

* Validate a full mixed-source `suggestion_update` snapshot fixture and reject partial or malformed snapshots.
* Update event tests: `suggestion_update` payload typing, `idle_suggestion` unchanged compat shape, `quest_board` retirement.
* Update REST contract tests for accept (both result actions), dismiss (suggestion and issue), scan trigger/status, and summary shapes.

### Manual Testing

* Review generated contracts against PRD Appendix A card-metadata rows and the Session 01 stub inventory.
* Confirm no Session 02-10 runtime behavior (manager, routes, engines, store) was implemented in this session.

### Edge Cases

* Unknown issue type, analysis type, category, effort, priority, severity, scan status, or follow-up category.
* Empty, non-array, or over-cap card arrays in a snapshot.
* Issue with absolute Windows path (`C:\...`), POSIX absolute path, `../` traversal, or `file://` URL-like `filePath`.
* Negative, zero, fractional, or non-numeric issue line numbers.
* Accept response missing `action` or carrying an unknown action value.
* Snapshot timestamps that are non-numeric or in the future relative to the freshness `now` argument.
* Dismissed-ID list exactly at, and one over, the 100-entry cap.

***

## 10. Dependencies

### External Libraries

* None expected (protocol stays dependency-free).

### Other Sessions

* **Depends on**: `phase17-session10-validation-documentation-and-handoff`
* **Depended by**: `phase18-session02-server-suggestion-manager-and-persistence`, `phase18-session03-suggestion-routes-and-websocket-parity`, `phase18-session04-idle-lifecycle-engine-parity`, `phase18-session05-session-summary-engine-and-noise-filtering`, `phase18-session06-codebase-issue-scanners`, `phase18-session07-scan-orchestration-and-quest-ignore-patterns`, `phase18-session08-on-demand-analysis-and-project-scan-engines`, `phase18-session09-web-quest-board-typed-cards`, `phase18-session10-quest-actions-and-keyboard-shortcuts`, and `phase18-session11-validation-documentation-and-handoff`.

***

## Next Steps

Run `/implement` to begin AI-led implementation.


---

# 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/sessions/phase18-session01-protocol-suggestion-contract-parity/spec.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.
