> 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/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md).

# Implementation Notes

**Session ID**: `phase17-session04-web-store-and-cockpit-notice-board` **Package**: apps/web, packages/protocol **Started**: 2026-06-05 20:55 **Last Updated**: 2026-06-05 21:18

***

## Session Progress

| Metric              | Value   |
| ------------------- | ------- |
| Tasks Completed     | 24 / 24 |
| Estimated Remaining | 0 hours |
| Blockers            | 0       |

***

### Task T024 - Run focused validation

**Started**: 2026-06-05 21:16 **Completed**: 2026-06-05 21:18 **Duration**: 2 minutes

**Notes**:

* Ran focused Notice Board and shell tests after formatting.
* Ran web typecheck under the local Node 26.2.0 runtime.
* Ran targeted Biome formatting and linting on touched source and test files.
* Ran ASCII/LF validation for touched source/tests and session artifacts.
* Ran `git diff --check`.

**Files Changed**:

* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T024 and completion checklist complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded final validation.

**Validation Commands**:

* `npx vitest run apps/web/tests/noticeBoardStore.test.ts apps/web/tests/NoticeBoard.test.tsx apps/web/tests/cockpitShell.test.ts apps/web/tests/CockpitShell.test.tsx`
* `npm --workspace apps/web run typecheck`
* `npx biome format --write apps/web/src/lib/noticeBoard.ts apps/web/src/store/useGameStore.ts apps/web/src/components/NoticeBoard.tsx apps/web/src/lib/cockpitShell.ts apps/web/tests/noticeBoardStore.test.ts apps/web/tests/NoticeBoard.test.tsx apps/web/tests/cockpitShell.test.ts apps/web/tests/CockpitShell.test.tsx`
* `npx biome lint apps/web/src/lib/noticeBoard.ts apps/web/src/store/useGameStore.ts apps/web/src/components/NoticeBoard.tsx apps/web/src/lib/cockpitShell.ts apps/web/tests/noticeBoardStore.test.ts apps/web/tests/NoticeBoard.test.tsx apps/web/tests/cockpitShell.test.ts apps/web/tests/CockpitShell.test.tsx`
* `node -e "...ASCII and LF validation..."`
* `git diff --check`

**BQC Fixes**:

* Contract alignment: focused tests validate canonical/compatibility Notice Board payloads end-to-end through the store and component.
* Accessibility and platform compliance: focused tests validate status regions and expansion ARIA behavior.
* Failure path completeness: focused tests validate empty, filtered, offline, disconnected, and local stream metadata states.

***

### Task T023 - Update cockpit shell tests

**Started**: 2026-06-05 21:14 **Completed**: 2026-06-05 21:16 **Duration**: 2 minutes

**Notes**:

* Added pure metadata expectations for Notice Board loading, offline, and disconnected active-room copy.
* Added App shell expectations for notice-board surface notes in no-server, disconnected, and connecting states.
* Ran `npx vitest run apps/web/tests/cockpitShell.test.ts apps/web/tests/CockpitShell.test.tsx`.

**Files Changed**:

* `apps/web/tests/cockpitShell.test.ts` - added Notice Board metadata expectations.
* `apps/web/tests/CockpitShell.test.tsx` - added Notice Board shell state render expectations.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T023 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T023 tests.

**BQC Fixes**:

* Failure path completeness: tests pin loading, offline, and disconnected state copy for the Notice Board wrapper (`apps/web/tests/cockpitShell.test.ts`, `apps/web/tests/CockpitShell.test.tsx`).

***

### Task T022 - Add Notice Board component tests

**Started**: 2026-06-05 21:13 **Completed**: 2026-06-05 21:14 **Duration**: 1 minute

**Notes**:

* Added component coverage for compact row metadata, type and priority labels, related files, resolved state, empty state, disconnected state, offline state, filtered-out state, severity filter behavior, and expansion accessibility.
* Tests assert the six-row compact cap and native button expansion ARIA state.
* Ran `npx vitest run apps/web/tests/NoticeBoard.test.tsx`.

**Files Changed**:

* `apps/web/tests/NoticeBoard.test.tsx` - expanded focused component coverage.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T022 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T022 tests.

**BQC Fixes**:

* Accessibility and platform compliance: tests assert `role="status"` states and expansion ARIA behavior (`apps/web/tests/NoticeBoard.test.tsx`).
* Contract alignment: tests assert workflow type labels remain visible independently of severity filtering (`apps/web/tests/NoticeBoard.test.tsx`).

***

### Task T021 - Add store Notice Board tests

**Started**: 2026-06-05 21:11 **Completed**: 2026-06-05 21:13 **Duration**: 2 minutes

**Notes**:

* Added store reducer tests for canonical hydrate, compatibility hydrate, canonical message preference, compatibility message fallback, dedupe, sorting, history cap, resolve handling, target visibility, fail-open behavior, and compatibility aliases.
* Used deterministic Notice, Hero, and Mission fixtures to keep ordering and identity-context assertions stable.
* Ran `npx vitest run apps/web/tests/noticeBoardStore.test.ts`.

**Files Changed**:

* `apps/web/tests/noticeBoardStore.test.ts` - added focused reducer coverage for Notice Board store behavior.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T021 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T021 tests.

**BQC Fixes**:

* Contract alignment: tests assert canonical and compatibility event aliases produce the same normalized store shape (`apps/web/tests/noticeBoardStore.test.ts`).
* Duplicate action prevention: tests assert repeated ids do not create duplicate rows (`apps/web/tests/noticeBoardStore.test.ts`).
* Trust boundary enforcement: tests assert target visibility is enforced when local identity context exists and fails open only without identity context (`apps/web/tests/noticeBoardStore.test.ts`).

***

### Task T020 - Update cockpit Notice Board metadata

**Started**: 2026-06-05 21:09 **Completed**: 2026-06-05 21:11 **Duration**: 2 minutes

**Notes**:

* Updated Notice Board surface loading, offline, and closed-stream copy to describe active-room coordination behavior.
* Kept the copy local-server-scoped and avoided hosted identity, public collaboration, or production audit claims.
* Ran shell metadata tests and web typecheck after the copy update.

**Files Changed**:

* `apps/web/src/lib/cockpitShell.ts` - updated Notice Board shell state metadata copy.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T020 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T020 implementation.

**BQC Fixes**:

* Error information boundaries: wrapper copy describes local active-room coordination without implying hosted safety or production auditability (`apps/web/src/lib/cockpitShell.ts`).

***

### Task T019 - Preserve severity filters as tint filters

**Started**: 2026-06-05 21:07 **Completed**: 2026-06-05 21:09 **Duration**: 2 minutes

**Notes**:

* Settings filtering remains mapped from Notice Board severity/tint only.
* Recovered workflow `type` values render as labels and are not used as filter keys.
* Filtered-out copy now explicitly points users to severity Settings, not workflow type filtering.

**Files Changed**:

* `apps/web/src/components/NoticeBoard.tsx` - preserved severity-based filtering and separate workflow type labels.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T019 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T019 implementation.

**BQC Fixes**:

* Contract alignment: workflow type and severity tint stay separate in rendering and filtering behavior (`apps/web/src/components/NoticeBoard.tsx`).

***

### Task T018 - Keep compact list and add accessible expansion

**Started**: 2026-06-05 21:07 **Completed**: 2026-06-05 21:09 **Duration**: 2 minutes

**Notes**:

* The board renders six visible notices by default using `NOTICE_BOARD_COMPACT_LIMIT`.
* Added an in-board expansion button for older visible notices with `aria-expanded`, `aria-controls`, and explicit accessible labels.
* Expansion keeps the list inside the existing bounded scroll region.

**Files Changed**:

* `apps/web/src/components/NoticeBoard.tsx` - added six-row cap and accessible expansion control.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T018 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T018 implementation.

**BQC Fixes**:

* Accessibility and platform compliance: expansion is a native button with keyboard support and ARIA state (`apps/web/src/components/NoticeBoard.tsx`).
* State freshness on re-entry: expansion state only affects display count and recomputes from the current filtered notice list on render (`apps/web/src/components/NoticeBoard.tsx`).

***

### Task T017 - Implement distinct board states

**Started**: 2026-06-05 21:07 **Completed**: 2026-06-05 21:09 **Duration**: 2 minutes

**Notes**:

* Added distinct in-board copy for empty, tint-filtered, connecting, offline, and disconnected states.
* Header status now reflects active-room, connecting, offline, disconnected, or local state without implying hosted behavior.

**Files Changed**:

* `apps/web/src/components/NoticeBoard.tsx` - added explicit Notice Board state copy and status labels.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T017 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T017 implementation.

**BQC Fixes**:

* Failure path completeness: empty, filtered, offline, loading, and disconnected states no longer collapse into one generic empty message (`apps/web/src/components/NoticeBoard.tsx`).

***

### Task T016 - Render compact row details

**Started**: 2026-06-05 21:06 **Completed**: 2026-06-05 21:09 **Duration**: 3 minutes

**Notes**:

* Rows now render author, relative age, target state, related files, normalized content, and resolved state.
* Target display uses state/count copy instead of raw target ids.
* Related files use protocol-normalized safe relative file values.

**Files Changed**:

* `apps/web/src/components/NoticeBoard.tsx` - added compact row detail rendering for author, age, target, related file, content, and resolved state fields.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T016 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T016 implementation.

**BQC Fixes**:

* Error information boundaries: target ids are summarized and related files are normalized safe relative values before rendering (`apps/web/src/components/NoticeBoard.tsx`).

***

### Task T015 - Render workflow type, severity tint, and priority metadata

**Started**: 2026-06-05 21:06 **Completed**: 2026-06-05 21:09 **Duration**: 3 minutes

**Notes**:

* Added compact row metadata chips for Notice Board workflow type and priority.
* Preserved severity as tint and label metadata separate from workflow type.
* Critical priority receives a distinct compact visual state without changing severity filtering semantics.

**Files Changed**:

* `apps/web/src/components/NoticeBoard.tsx` - added compact type, priority, and severity metadata rendering.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T015 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T015 implementation.

**BQC Fixes**:

* Accessibility and platform compliance: metadata is rendered as text labels, not color-only state (`apps/web/src/components/NoticeBoard.tsx`).

***

### Task T014 - Update Notice Board data mapping

**Started**: 2026-06-05 21:05 **Completed**: 2026-06-05 21:09 **Duration**: 4 minutes

**Notes**:

* The component now normalizes store notices before rendering, so canonical and compatibility notice shapes share one display path.
* Rows render canonical `type`, `priority`, `content`, and `authorName`, with legacy aliases supplied by the normalization helper.
* Type, priority, and severity labels use exhaustive switch handling for the current protocol enum values.
* Ran web typecheck and the focused Notice Board component scaffold after the update.

**Files Changed**:

* `apps/web/src/components/NoticeBoard.tsx` - mapped normalized notice fields into compact row content.
* `apps/web/tests/NoticeBoard.test.tsx` - updated scaffold empty-state expectation for the new real Notice Board copy.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T014 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T014 implementation.

**BQC Fixes**:

* Contract alignment: component rendering consumes normalized protocol Notice Board fields with compatibility aliases preserved (`apps/web/src/components/NoticeBoard.tsx`).
* Error information boundaries: rows render safe normalized notice fields only, not raw event payloads (`apps/web/src/components/NoticeBoard.tsx`).

***

### Task T013 - Preserve seed reset and compatibility notice behavior

**Started**: 2026-06-05 21:04 **Completed**: 2026-06-05 21:05 **Duration**: 1 minute

**Notes**:

* Kept `resetToSeed` behavior intact so existing seed notices continue to restore legacy `body`, `severity`, `targets`, and `postedAt` fields.
* Added normalization paths that preserve `body`, `severity`, `targets`, `postedAt`, and `resolvedAt` aliases for incoming hydrate/message/resolve events.
* Ran web typecheck and focused store scaffold after the reducer update.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - integrated compatibility-preserving Notice Board helpers without changing seed reset semantics.
* `apps/web/src/lib/noticeBoard.ts` - compatibility alias normalization supports legacy field shapes consumed by the store.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T013 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T013 implementation.

**BQC Fixes**:

* Contract alignment: legacy and canonical Notice Board fields normalize into one store shape without dropping seed or compatibility notices (`apps/web/src/store/useGameStore.ts`, `apps/web/src/lib/noticeBoard.ts`).

***

### Task T012 - Apply web target visibility filtering

**Started**: 2026-06-05 21:04 **Completed**: 2026-06-05 21:05 **Duration**: 1 minute

**Notes**:

* Notice writes now pass through visibility filtering using current hero, mission, selected hero, and selected mission context.
* Roster, hero, mission, and selected-context state changes re-filter existing notices so visibility does not remain stale after local identity changes.
* Visibility still fails open when no meaningful local identity context exists.
* Ran web typecheck and focused store scaffold after the reducer update.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - added store-side visibility filtering for notice events and identity-context updates.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T012 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T012 implementation.

**BQC Fixes**:

* State freshness on re-entry: local identity changes re-apply visibility filtering to current notices (`apps/web/src/store/useGameStore.ts`).
* Trust boundary enforcement: targeted notices are filtered at the store boundary when local context can decide visibility (`apps/web/src/store/useGameStore.ts`).

***

### Task T011 - Add notice\_resolved reducer handling

**Started**: 2026-06-05 21:04 **Completed**: 2026-06-05 21:05 **Duration**: 1 minute

**Notes**:

* Added `notice_resolved` event handling for `noticeId`, `messageId`, embedded `notice`, and embedded `message`.
* Resolve events update matching notices in place and can merge embedded resolved notice payloads without adding duplicate rows.
* Invalid or unmatched resolve payloads preserve the current normalized board state.
* Ran web typecheck and focused store scaffold after the reducer update.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - added `notice_resolved` reducer handling through the resolve merge helper.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T011 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T011 implementation.

**BQC Fixes**:

* Duplicate action prevention: repeated resolve events keep a single resolved row (`apps/web/src/store/useGameStore.ts`).
* Failure path completeness: malformed resolve events preserve current board state rather than partially mutating it (`apps/web/src/store/useGameStore.ts`).

***

### Task T010 - Update notice\_board\_message reducer

**Started**: 2026-06-05 21:04 **Completed**: 2026-06-05 21:05 **Duration**: 1 minute

**Notes**:

* Updated message handling to accept canonical `message` and compatibility `notice` payload keys.
* Normalized aliases before writing to store state, deduped by id, sorted newest first, and retained the existing 50-notice history cap.
* Ran web typecheck and focused store scaffold after the reducer update.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - wired `notice_board_message` through normalized merge helper and visibility filtering.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T010 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T010 implementation.

**BQC Fixes**:

* Duplicate action prevention: repeated message ids overwrite existing rows instead of duplicating them (`apps/web/src/store/useGameStore.ts`).
* Contract alignment: message handling accepts canonical and compatibility payload keys (`apps/web/src/store/useGameStore.ts`).

***

### Task T009 - Update notice\_board\_hydrate reducer

**Started**: 2026-06-05 21:03 **Completed**: 2026-06-05 21:05 **Duration**: 2 minutes

**Notes**:

* Updated hydrate handling to prefer canonical `messages` when present and fall back to compatibility `notices`.
* Malformed hydrate events preserve the current normalized board rather than replacing it with unsafe empty state.
* Hydrated notices pass through current web visibility filtering before entering store state.
* Ran web typecheck and focused store scaffold after the reducer update.

**Files Changed**:

* `apps/web/src/store/useGameStore.ts` - wired `notice_board_hydrate` through normalized hydrate helper and visibility filtering.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T009 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T009 implementation.

**BQC Fixes**:

* Failure path completeness: malformed hydrate payloads no longer wipe the existing board (`apps/web/src/store/useGameStore.ts`).
* Contract alignment: hydrate handles canonical `messages` and compatibility `notices` (`apps/web/src/store/useGameStore.ts`).

***

### Task T008 - Add Notice Board component test scaffold

**Started**: 2026-06-05 21:02 **Completed**: 2026-06-05 21:03 **Duration**: 1 minute

**Notes**:

* Added controlled component render helper for the Notice Board with explicit game and Settings store setup.
* Added deterministic component Notice fixture factory for later compact rendering and state tests.
* Ran focused scaffold tests with Vitest.

**Files Changed**:

* `apps/web/tests/NoticeBoard.test.tsx` - added component test scaffold and controlled render helper.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T008 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T008 implementation.

**BQC Fixes**:

* State freshness on re-entry: component tests reset game and Settings stores before each render (`apps/web/tests/NoticeBoard.test.tsx`).
* Accessibility and platform compliance: scaffold already asserts the empty board exposes a `status` role (`apps/web/tests/NoticeBoard.test.tsx`).

***

### Task T007 - Add store reducer test scaffold

**Started**: 2026-06-05 21:01 **Completed**: 2026-06-05 21:03 **Duration**: 2 minutes

**Notes**:

* Added focused store test scaffold with deterministic Notice, Hero, and Mission fixture factories.
* Added store reset helper that starts from seed and then applies a controlled local identity context.
* Ran focused scaffold tests with Vitest.

**Files Changed**:

* `apps/web/tests/noticeBoardStore.test.ts` - added store reducer test scaffold and reusable Notice fixture factory.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T007 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T007 implementation.

**BQC Fixes**:

* State freshness on re-entry: scaffold reset helper clears notices, event log, replay state, and selected identity before each test (`apps/web/tests/noticeBoardStore.test.ts`).

***

### Task T006 - Implement merge, dedupe, sort, and resolve helpers

**Started**: 2026-06-05 21:01 **Completed**: 2026-06-05 21:01 **Duration**: 1 minute

**Notes**:

* Added deterministic newest-first sorting by `createdAt`, `postedAt`, and id.
* Added id-based dedupe and capped Notice Board history merging.
* Added resolve merging for `noticeId`, `messageId`, embedded `notice`, and embedded `message` payloads.

**Files Changed**:

* `apps/web/src/lib/noticeBoard.ts` - added merge, sort, dedupe, cap, and resolve helpers.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T006 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T006 implementation.

**BQC Fixes**:

* Duplicate action prevention: notice merges overwrite by id and resolve updates are idempotent (`apps/web/src/lib/noticeBoard.ts`).
* Contract alignment: resolve handling accepts canonical and compatibility identifiers and embedded payload keys (`apps/web/src/lib/noticeBoard.ts`).
* Concurrency safety: helper functions are pure and return new arrays instead of mutating shared store arrays (`apps/web/src/lib/noticeBoard.ts`).

***

### Task T005 - Implement target visibility helper

**Started**: 2026-06-05 21:00 **Completed**: 2026-06-05 21:01 **Duration**: 1 minute

**Notes**:

* Added visibility context collection from selected hero, selected mission, active missions, known hero ids, and known hero session ids.
* Added fail-open behavior only when no meaningful local identity context exists.
* Added defensive denied/restricted/revoked target handling so those target-only notices do not render as visible local notices.

**Files Changed**:

* `apps/web/src/lib/noticeBoard.ts` - added Notice Board visibility context and filtering helpers.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T005 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T005 implementation.

**BQC Fixes**:

* Trust boundary enforcement: visibility decisions use normalized target ids and explicit local identity context, not raw upstream assumptions (`apps/web/src/lib/noticeBoard.ts`).
* State freshness on re-entry: visibility helpers rebuild context from current selected hero, selected mission, active mission, and roster state on each call (`apps/web/src/lib/noticeBoard.ts`).

***

### Task T004 - Create Notice Board normalization helper

**Started**: 2026-06-05 20:57 **Completed**: 2026-06-05 21:00 **Duration**: 3 minutes

**Notes**:

* Added a pure web Notice Board helper module that normalizes canonical `message`/`messages` and compatibility `notice`/`notices` payloads.
* Reused protocol Notice Board validation through `parseNoticeLike` and derived severity from protocol type/priority rules.
* Preserved canonical and compatibility aliases for `content`, `body`, `targetSessionIds`, `targets`, `postedAt`, `createdAt`, `relatedFiles`, `resolved`, `resolvedAt`, and `resolution`.
* Ran `npm --workspace apps/web run typecheck` with local Node 26.2.0 after adding the helper.

**Files Changed**:

* `apps/web/src/lib/noticeBoard.ts` - added normalization, extraction, sorting, merge, resolve, and visibility scaffolding helpers.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T004 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T004 implementation.

**BQC Fixes**:

* Trust boundary enforcement: invalid notice payloads are parsed through protocol validation and discarded instead of trusted blindly (`apps/web/src/lib/noticeBoard.ts`).
* Contract alignment: canonical and compatibility aliases normalize into one web notice shape using protocol Notice Board contracts (`apps/web/src/lib/noticeBoard.ts`).
* Failure path completeness: malformed hydrate/message/resolve payloads preserve current normalized state rather than wiping the board (`apps/web/src/lib/noticeBoard.ts`).

***

### Task T003 - Audit existing web test reset and render patterns

**Started**: 2026-06-05 20:57 **Completed**: 2026-06-05 20:57 **Duration**: 1 minute

**Notes**:

* Confirmed focused component tests use React Testing Library with `cleanup()` in `afterEach`.
* Confirmed store-dependent tests reset state through `useGameStore.setState()` or `resetToSeed()` and Settings through `DEFAULT_SETTINGS`.
* Confirmed component tests can mount isolated surfaces without starting the WebSocket client.

**Files Changed**:

* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T003 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T003 audit.

**BQC Fixes**:

* None; audit-only task.

***

### Task T002 - Audit current Notice Board component and shell metadata

**Started**: 2026-06-05 20:56 **Completed**: 2026-06-05 20:57 **Duration**: 1 minute

**Notes**:

* Confirmed `NoticeBoard` currently renders only author, legacy body, severity tint, posted age, and resolved alias data.
* Confirmed Settings `severityFilter` is the existing tint/noise filter shared with toasts and must remain severity-based rather than workflow-type-based.
* Confirmed cockpit shell metadata already distinguishes loading, offline, and closed-stream states, but copy still describes legacy server notices rather than active-room coordination.

**Files Changed**:

* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T002 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T002 audit.

**BQC Fixes**:

* None; audit-only task.

***

### Task T001 - Verify Session 01-03 Notice Board prerequisites

**Started**: 2026-06-05 20:55 **Completed**: 2026-06-05 20:56 **Duration**: 1 minute

**Notes**:

* Confirmed protocol contracts include `notice_board_hydrate.messages`, `notice_board_message.message`, and `notice_resolved`.
* Confirmed server WebSocket hydration and routes emit canonical and compatibility payload keys.
* Confirmed current web reducer only reads legacy `e.notices` and `e.notice`, so this session must add canonical payload and resolve handling.

**Files Changed**:

* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/tasks.md` - marked T001 complete.
* `.spec_system/specs/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.md` - recorded T001 audit.

**BQC Fixes**:

* None; audit-only task.

***

## Task Log

### 2026-06-05 - Session Start

**Environment verified**:

* [x] Prerequisites confirmed for `apps/web`
* [x] Prerequisites confirmed for `packages/protocol`
* [x] Tools available with local Node 26.2.0 runtime
* [x] Directory structure ready

***


---

# 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/phase17-session04-web-store-and-cockpit-notice-board/implementation-notes.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.
