> 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-session05-session-summary-engine-and-noise-filtering/spec.md).

# Session Specification

**Session ID**: `phase18-session05-session-summary-engine-and-noise-filtering` **Phase**: 18 - Quest Board Suggestion Parity **Status**: Complete **Created**: 2026-06-10 **Package**: apps/server **Package Stack**: TypeScript

***

## 1. Session Overview

This session adds the second server-side generation path for the Phase 18 Quest Board: session summaries with follow-up tasks. Sessions 01-04 already provided shared suggestion contracts, server-owned suggestion persistence, REST and WebSocket mutation paths, and automatic idle suggestions from hero-idle transitions. The remaining gap is a dedicated summary engine that records concise follow-up tasks when a session ends instead of overloading the idle suggestion engine.

The work also adds the shared analysis noise filter required by later scan and analysis sessions. The filter rejects model self-talk about unreadable or truncated context before those items reach `SuggestionManager` state, and it also cleans persisted analysis state during load so stale noisy items do not survive a restart.

This is a server-only session. It does not implement codebase scanners, on-demand analysis engines, project scans, typed web rendering, Quest Board actions, keyboard shortcuts, or documentation closeout for the whole phase.

***

## 2. Objectives

1. Generate at most two typed session follow-up tasks when an event-ingested session ends.
2. Store session summaries through `SuggestionManager.setSessionSummary` and emit the existing canonical `suggestion_update` snapshot path.
3. Add lifecycle guards for summary generation: in-flight suppression, about 15-second timeout, abort handling, and shutdown cleanup.
4. Add a shared analysis noise filter and apply it at analysis store time and load time.
5. Cover parsing, fallback, lifecycle, manager filtering, and route integration with focused server tests.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase18-session01-protocol-suggestion-contract-parity` - provides `SessionSummary`, follow-up task categories, `AnalysisResult`, and `suggestion_update` contracts.
* [x] `phase18-session02-server-suggestion-manager-and-persistence` - provides server-owned persisted Quest Board state and `setSessionSummary`.
* [x] `phase18-session03-suggestion-routes-and-websocket-parity` - provides the shared `emitSuggestionMutationUpdate` broadcast path.
* [x] `phase18-session04-idle-lifecycle-engine-parity` - provides the bounded context and modified-file extraction patterns this session reuses.

### Required Tools/Knowledge

* Node 26.2.0 or newer with npm workspaces.
* TypeScript server package conventions and Vitest tests.
* Existing `llmClient`, `llmPrivacy`, `SuggestionManager`, event ingest, and lifecycle coordinator patterns.
* Phase 18 PRD Appendix A as traceability evidence only; do not import, copy, or transform historical code.

### 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)

* Server can trigger summary generation from the existing session-end signal in `/event` after a mission is completed.
* Summary generation uses bounded mission prompt, mission summary, safe tool paths, sanitized recent activity, and modified-file hints from Session 04 context helpers.
* A dedicated summary engine returns a typed `SessionSummary` candidate with 1-2 follow-up tasks categorized as `test`, `documentation`, `refactor`, or `validation`.
* Summary generation has an in-flight guard, about 15-second timeout, abort handling, compact warning behavior, and cleanup on server shutdown.
* LLM calls use `llmClient` and the existing two-level provider transfer rules; missing provider transfer, timeout, malformed output, or empty output falls back to deterministic schema-valid summary output when context is sufficient.
* Summary writes go through `SuggestionManager.setSessionSummary` and the existing `emitSuggestionMutationUpdate` helper.
* Shared analysis noise filter rejects items containing model self-talk about incomplete files, truncated input, unreadable context, missing context, or partial files.
* Noise filtering applies in `SuggestionManager.setAnalysisResult` and during manager load/normalization so persisted noisy analysis items are cleaned.
* Focused tests cover parser, fallback, lifecycle, timeout, in-flight guard, manager filtering, load filtering, and route integration.

### Out of Scope (Deferred)

* Codebase issue scanners - *Reason: Session 06 owns scanner logic.*
* Scan orchestration and quest ignore patterns - *Reason: Session 07 owns orchestration and ignore behavior.*
* On-demand analysis and project scan engines - *Reason: Session 08 owns engine behavior and trigger/status routes.*
* Web rendering of session follow-ups - *Reason: Session 09 owns typed card rendering.*
* Quest Board actions, hero assignment, and keyboard shortcuts - *Reason: Session 10 owns interactions.*
* Full phase documentation and privacy inventory closeout - *Reason: Session 11 owns validation documentation and handoff.*
* Historical telemetry and entitlement gates - *Reason: Phase 18 explicitly excludes analytics capture and entitlement gating.*

***

## 5. Technical Approach

### Architecture

Create `apps/server/src/llm/engines/sessionSummaryEngine.ts` as the dedicated summary generation boundary. It should accept bounded session context, call `llmClient.complete` with a new auditable prompt, parse direct JSON arrays, fenced JSON, extracted arrays, or object-shaped responses, and normalize output to the protocol `SessionSummary` shape. It should cap follow-up tasks at two generated items, validate follow-up categories, and produce deterministic fallback output when provider output is unavailable or invalid.

Create `apps/server/src/lib/sessionSummaryLifecycle.ts` as the lifecycle coordinator. It should mirror the proven Session 04 pattern: injectable clock, generation function, timeout, abort controller, in-flight session map, destroy cleanup, compact warning logs, manager write through `SuggestionManager.setSessionSummary`, and broadcast through `emitSuggestionMutationUpdate`.

Reuse `apps/server/src/lib/idleSuggestionContext.ts` instead of duplicating path extraction and context bounding. If small exports are needed from that module, expose them deliberately rather than copying logic. The event route should trigger summary generation after a mission has been completed and should not block the HTTP response path on model work.

Create `apps/server/src/lib/analysisNoiseFilter.ts` with pure predicates and filter helpers. `SuggestionManager.setAnalysisResult` should filter new analysis items before parsing/persistence. The manager load path should filter persisted analysis results during `normalizeStore` so old noisy entries are removed on startup without corrupting the rest of the store.

### Design Patterns

* Dedicated engine: parsing, category validation, and fallback generation stay testable without server startup.
* Lifecycle coordinator boundary: async timers, in-flight state, abort resources, manager writes, and cleanup live in one injectable class.
* Pure filtering before mutation: noise rejection happens before store state changes and again during load normalization.
* Manager-owned state: summaries and filtered analysis results only enter persisted Quest Board state through `SuggestionManager`.
* Single broadcast path: summary writes reuse the same snapshot helper as route mutations and idle generation.
* Local fallback first: provider calls remain governed by the existing two-level LLM provider transfer rules.

### Technology Stack

* TypeScript in `apps/server`.
* Existing Express 5 event ingest route.
* Existing `@factionos/protocol` suggestion summary and analysis types.
* Existing `llmClient`, `llmPrivacy`, `SuggestionManager`, and `emitSuggestionMutationUpdate`.
* Vitest server tests with fake timers and temporary state directories.

***

## 6. Deliverables

### Files to Create

| File                                                    | Purpose                                                                                              | Est. Lines |
| ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ---------- |
| `apps/server/src/llm/engines/sessionSummaryEngine.ts`   | Dedicated parser, normalizer, fallback, and generator for typed session summaries                    | \~260      |
| `apps/server/src/lib/sessionSummaryLifecycle.ts`        | Async lifecycle coordinator for summary generation, timeout, manager writes, broadcasts, and cleanup | \~260      |
| `apps/server/src/lib/analysisNoiseFilter.ts`            | Pure noise predicate and filter helpers for analysis-shaped Quest Board items                        | \~140      |
| `apps/server/src/llm/prompts/session-summary-engine.md` | Auditable system prompt for summary follow-up generation                                             | \~90       |
| `apps/server/tests/sessionSummaryEngine.test.ts`        | Unit tests for parsing, categories, caps, fallback, and provider failure paths                       | \~220      |
| `apps/server/tests/sessionSummaryLifecycle.test.ts`     | Unit tests for trigger, in-flight guard, timeout, cleanup, manager writes, and broadcasts            | \~280      |
| `apps/server/tests/analysisNoiseFilter.test.ts`         | Unit tests for accepted and rejected noise-filter fixtures                                           | \~160      |

### Files to Modify

| File                                            | Changes                                                                               | Est. Lines |
| ----------------------------------------------- | ------------------------------------------------------------------------------------- | ---------- |
| `apps/server/src/llm/prompts/index.ts`          | Register the session summary prompt in the maintained prompt registry                 | \~5        |
| `apps/server/src/managers/suggestionManager.ts` | Filter analysis results before store-time parsing and load-time normalization         | \~45       |
| `apps/server/src/routes/event.ts`               | Trigger session summary generation on session end without blocking `/event` responses | \~45       |
| `apps/server/src/server.ts`                     | Instantiate summary lifecycle coordinator and destroy it during shutdown              | \~25       |
| `apps/server/tests/suggestionManager.test.ts`   | Add store-time and load-time noise-filter coverage                                    | \~90       |
| `apps/server/tests/routes.test.ts`              | Add integration coverage for session-end summary generation reaching manager state    | \~80       |
| `apps/server/README_server.md`                  | Document session summaries, noise filtering, fallback behavior, and server-only scope | \~40       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] A completed session in `/event` starts one asynchronous summary generation attempt for the resolved session.
* [ ] Repeated session-end handling for the same session is suppressed while summary generation is in flight.
* [ ] Summary generation times out after about 15 seconds, aborts pending work, and leaves no orphaned in-flight state.
* [ ] Generated summaries are stored as typed `SessionSummary` entries with session ID, title, summary, created timestamp, and 1-2 follow-up tasks.
* [ ] Summary manager mutations emit a canonical `suggestion_update` snapshot.
* [ ] Missing provider transfer, LLM failure, malformed output, and empty output fall back to schema-valid deterministic summary output when context is sufficient.
* [ ] Analysis noise fixtures never reach stored analysis state through `setAnalysisResult`.
* [ ] Persisted noisy analysis items are removed during manager load while valid items are preserved.

### Testing Requirements

* [ ] Session summary engine tests are written and passing.
* [ ] Session summary lifecycle tests are written and passing.
* [ ] Analysis noise filter tests are written and passing.
* [ ] SuggestionManager filtering tests are updated and passing.
* [ ] Route integration tests are updated and passing.
* [ ] `npm --workspace apps/server run typecheck` passes.

### Non-Functional Requirements

* [ ] No raw prompts, terminal output, provider payloads, secrets, or absolute paths are persisted in generated summary state.
* [ ] Provider transfer remains disabled unless both provider credentials and `FACTIONOS_ALLOW_LLM_PROVIDER_TRANSFER=true` are configured.
* [ ] Summary generation does not block HTTP ingest responses.
* [ ] No new hosted storage, telemetry, entitlement, or real executor behavior is introduced.

### Quality Gates

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

***

## 8. Implementation Notes

### Key Considerations

* `SuggestionManager.setSessionSummary` already exists and should be reused rather than adding a second persistence path.
* `idleSuggestionContext.ts` already performs bounded text and safe relative file extraction; reuse that pattern for summary context.
* `emitSuggestionMutationUpdate` is the canonical server broadcast helper for Quest Board state mutations.
* The old `onDemandAnalysis.ts` route path currently returns an older issue shape; noise filtering in this session should focus on protocol `AnalysisResult` storage because the analysis engines land later.

### Potential Challenges

* Event-route duplication: The same `Stop`/hero-idle flow now triggers idle suggestions and session summaries. Keep each coordinator independent and non-blocking.
* Fallback quality: The fallback must be specific enough to be useful while still avoiding raw paths, prompts, patches, transcripts, and provider payloads.
* Persisted-state cleanup: Filtering during load must not reject the entire suggestion store when only analysis items are noisy.
* Category drift: Follow-up task categories must stay within the protocol enum: `test`, `documentation`, `refactor`, `validation`.

### Relevant Considerations

* \[P17-apps/server] **Manager-owned persistence and cleanup**: Keep summary storage and filtering at the manager boundary so test isolation and lifecycle cleanup stay predictable.
* \[P01-apps/server] **Anthropic transfer is two-level opt-in**: Summary generation must not send prompts or file-derived context to a provider without both provider credentials and explicit transfer opt-in.
* \[P03-apps/server] **Local server boundary must stay conservative**: Event-ingest changes must preserve request validation, rate limits, body-size caps, and compact failure behavior.
* \[P07] **Redaction is boundary-specific**: Summary text and analysis filtering must minimize prompts, paths, transcripts, terminal output, and provider payloads before persistence or broadcast.
* \[P03] **Stable docs are the current contract**: Historical `EXAMPLES/` material is evidence only; do not import, copy, or transform it.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* Duplicate session-end events could produce repeated summaries unless in-flight guards and idempotent manager writes are explicit.
* Timeout or shutdown could leave pending async work unless abort and cleanup paths are tested.
* Model self-talk could persist into Quest Board state unless filtering runs before mutation and during load.
* Event ingest could block on model work unless summary generation is scheduled asynchronously with compact failure handling.

***

## 9. Testing Strategy

### Unit Tests

* Summary parser accepts direct arrays, fenced JSON, extracted JSON, and object-shaped outputs.
* Summary parser rejects invalid categories and caps follow-up tasks at two.
* Deterministic fallback creates schema-valid summaries from safe mission context and modified-file hints.
* Analysis noise filter rejects the documented self-talk phrases and accepts concrete analysis items.

### Integration Tests

* Lifecycle coordinator writes one summary through `SuggestionManager` and emits `suggestion_update`.
* In-flight and timeout behavior suppress duplicate writes and clean up resources.
* SuggestionManager filters noisy analysis results at store time and load time.
* `/event` session-end flow returns promptly while summary generation reaches manager state asynchronously.

### Manual Testing

* Run a local server, ingest a session start, mission start, tool event, and stop event, then confirm `/suggestions/summary` counts the session summary and WebSocket clients receive `suggestion_update`.

### Edge Cases

* Missing session ID uses a safe hero/session fallback or produces no summary.
* Empty mission summary still creates a fallback only when there is enough safe context.
* Malformed provider JSON falls back without logging raw payloads.
* Persisted analysis state containing only noise is normalized to an empty analysis result or cleared without corrupting the store.

***

## 10. Dependencies

### External Libraries

* No new runtime dependencies.

### Other Sessions

* **Depends on**: `phase18-session01-protocol-suggestion-contract-parity`, `phase18-session02-server-suggestion-manager-and-persistence`, `phase18-session03-suggestion-routes-and-websocket-parity`, `phase18-session04-idle-lifecycle-engine-parity`
* **Depended by**: `phase18-session08-on-demand-analysis-and-project-scan-engines`, `phase18-session09-web-quest-board-typed-cards`, `phase18-session11-validation-documentation-and-handoff`

***

## Next Steps

Run the implement workflow step 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-session05-session-summary-engine-and-noise-filtering/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.
