# PRD Action → Implementation Map

Generated by W1-1 sub-agent on 2026-05-11.

Source PRD: `packages/docs/prd-lifeops-executive-assistant.md` (`Action Catalog` section).
Implementation sources cross-referenced:

- `plugins/app-lifeops/src/actions/` — LifeOps umbrella actions.
- `plugins/app-lifeops/src/followup/actions/` — standalone follow-up actions.
- `packages/core/src/features/advanced-capabilities/actions/message.ts` — MESSAGE umbrella.
- `packages/benchmarks/lifeops-bench/manifests/actions.manifest.json` and `actions.summary.md` — canonical action registry (91 actions, including promoted subactions).

The PRD enumerates **49 action names** across 6 domains. Several of these are aliases for verbs that the implementation exposes via umbrella `subaction` parameters, not as standalone action names. The runtime promotes umbrella subactions into discoverable top-level names like `CALENDAR_FEED`, `CALENDAR_CREATE_EVENT`, `MESSAGE_SEND`, etc. via `promoteSubactionsToActions` in `plugins/app-lifeops/src/plugin.ts`. Where a PRD name maps cleanly onto a promoted name or a subaction value, this map shows that mapping.

## Status legend

- ✅ Implemented — there's an umbrella + subaction (or a standalone action) that does this exact thing today.
- 🟡 Partial — close coverage exists but is a subset or superset; would need a new subaction or scenario asserter.
- ❌ Missing — no implementation. Proposed implementation route is in the "Missing actions" section.

## Coverage by domain

| Domain | Total | ✅ Implemented | 🟡 Partial | ❌ Missing |
|---|---:|---:|---:|---:|
| Calendar & Scheduling | 12 | 8 | 3 | 1 |
| Inbox & Messaging | 10 | 7 | 2 | 1 |
| Follow-Ups | 6 | 3 | 2 | 1 |
| Travel & Events | 9 | 4 | 3 | 2 |
| Docs & Portals | 6 | 6 | 0 | 0 |
| Push & Escalation | 6 | 2 | 2 | 2 |
| **Total** | **49** | **30** | **12** | **7** |

## Full action map

| PRD action | Domain | Implemented as | Status |
|---|---|---|---|
| CALENDAR_LIST_UPCOMING | Calendar | `CALENDAR.feed` (promoted to `CALENDAR_FEED`) | ✅ |
| CALENDAR_FIND_AVAILABILITY | Calendar | `CALENDAR.check_availability` (promoted to `CALENDAR_CHECK_AVAILABILITY`) | ✅ |
| CALENDAR_CREATE_EVENT | Calendar | `CALENDAR.create_event` (promoted to `CALENDAR_CREATE_EVENT`) | ✅ |
| CALENDAR_CREATE_RECURRING_BLOCK | Calendar | `CALENDAR.create_event` with recurrence in `details` | 🟡 — RRULE pass-through exists, but no executable test asserts cadence + relationship link (audit gap #21) |
| CALENDAR_RESCHEDULE_EVENT | Calendar | `CALENDAR.update_event` (promoted to `CALENDAR_UPDATE_EVENT`); bulk via `CALENDAR.bulk_reschedule` (`CALENDAR_BULK_RESCHEDULE`) | ✅ |
| CALENDAR_CANCEL_EVENT | Calendar | `CALENDAR.delete_event` (promoted to `CALENDAR_DELETE_EVENT`) | ✅ |
| CALENDAR_PROPOSE_TIMES | Calendar | `CALENDAR.propose_times` (promoted to `CALENDAR_PROPOSE_TIMES`); multi-turn via `SCHEDULING_NEGOTIATION` | ✅ |
| CALENDAR_PROTECT_WINDOW | Calendar | `CALENDAR.update_preferences` (blackout windows) | 🟡 — preferences storage exists; no end-to-end test asserts agent rejects 7am calls against a protected window (audit gap #12) |
| CALENDAR_BUNDLE_MEETINGS | Calendar | none directly; partial coverage in `test/bundle-meetings.e2e.test.ts` via `CALENDAR.feed` + read-only surfacer | 🟡 — read surfacer exists; no commit-bundle write path |
| CALENDAR_ADD_PREP_BUFFER | Calendar | `CALENDAR.create_event` (caller composes prep block) | 🟡 — possible via raw create, but no dedicated prep-buffer subaction with attendee-aware buffer math |
| CALENDAR_ADD_TRAVEL_BUFFER | Calendar | `CALENDAR.trip_window` (promoted to `CALENDAR_TRIP_WINDOW`) | ✅ |
| CALENDAR_BUILD_DOSSIER | Calendar | none directly; can be composed via `BRIEF.compose_morning` with `include={calendar:true}` for a calendar-focused brief | 🟡 — landed by W2-5 (2026-05-11) as a partial composer; dedicated per-meeting dossier action still missing |
| INBOX_LIST_UNREAD | Inbox | `MESSAGE.list_inbox`; also `INBOX_UNIFIED.list` for cross-platform fan-out | ✅ |
| INBOX_TRIAGE_PRIORITY | Inbox | `MESSAGE.triage` (delegates to `triageMessagesAction`); also `INBOX_UNIFIED` simile | ✅ |
| INBOX_SUMMARIZE_CHANNEL | Inbox | `MESSAGE.read_channel` + `MESSAGE.search_inbox` (composes summary in prompt); also `INBOX_UNIFIED.summarize` for cross-platform aggregation | 🟡 — cross-platform summarize landed by W2-5 (2026-05-11); per-channel deterministic summary action still missing |
| MESSAGE_DRAFT_REPLY | Inbox | `MESSAGE.draft_reply` (delegates to `draftReplyAction`) | ✅ |
| MESSAGE_SEND_APPROVAL_REQUEST | Inbox | `MESSAGE.send` (drafts route to approval queue automatically per role gate) + `RESOLVE_REQUEST` | ✅ |
| MESSAGE_SEND_CONFIRMED | Inbox | `MESSAGE.send` / `MESSAGE.send_draft` post-approval | ✅ |
| MESSAGE_ARCHIVE_OR_DEFER | Inbox | `MESSAGE.manage` (delegates to `manageMessageAction`) | ✅ |
| MESSAGE_CREATE_GROUP_HANDOFF | Inbox | `WORK_THREAD.create` + `WORK_THREAD.attach_source` (covered by `test/group-chat-handoff.e2e.test.ts`) | ✅ |
| MESSAGE_REPAIR_AFTER_MISS | Inbox | composed: `MESSAGE.draft_reply` + `CALENDAR.update_event` + `RESOLVE_REQUEST` (covered by `test/assistant-user-journeys.followup-repair.e2e.test.ts`) | 🟡 — composition is exercised end-to-end but no single named action; recovery is implicit |
| THREAD_LINK_CONTACT | Inbox | `ENTITY.set_identity` | ❌ — `ENTITY.set_identity` ties a handle to a person, but does not link a `Thread` object to a contact. No `Thread` domain object exists yet. |
| FOLLOWUP_CREATE_RULE | Follow-Ups | `SET_FOLLOWUP_THRESHOLD` (`plugins/app-lifeops/src/followup/actions/setFollowupThreshold.ts`) | ✅ |
| FOLLOWUP_LIST_OVERDUE | Follow-Ups | `LIST_OVERDUE_FOLLOWUPS` (`plugins/app-lifeops/src/followup/actions/listOverdueFollowups.ts`) | ✅ |
| FOLLOWUP_CREATE_DRAFT | Follow-Ups | `MESSAGE.draft_followup` (delegates to `draftFollowupAction`) | ✅ |
| FOLLOWUP_SEND_CONFIRMED | Follow-Ups | `MESSAGE.send_draft` after `RESOLVE_REQUEST.approve` | 🟡 — works via composition; no dedicated `FOLLOWUP_SEND_CONFIRMED` aliased path |
| FOLLOWUP_GENERATE_DIGEST | Follow-Ups | partially via `MORNING_BRIEF_PACK_KEY` default pack (renders overdue follow-ups inside daily brief) | 🟡 — digest is rendered as part of the morning-brief pack; no standalone digest action callable on demand |
| FOLLOWUP_ESCALATE | Follow-Ups | `SCHEDULED_TASK.create` with escalation policy + `DEVICE_INTENT.broadcast` (catalog references PRD but `audit gap #42` shows no executable test) | ❌ — no dedicated escalation action; ladder is assembled implicitly via SCHEDULED_TASK + DEVICE_INTENT, not exercised |
| TRAVEL_CAPTURE_PREFERENCES | Travel | `PROFILE.save` (free-form prefs) + `BOOK_TRAVEL` first-turn preference capture | ✅ |
| TRAVEL_BOOK_FLIGHT | Travel | `BOOK_TRAVEL` with kind=flight | ✅ |
| TRAVEL_BOOK_HOTEL | Travel | `BOOK_TRAVEL` (hotel kind not yet implemented in handler) | 🟡 — Duffel adapter is flights-only; hotel adapter not wired |
| TRAVEL_SYNC_ITINERARY_TO_CALENDAR | Travel | `BOOK_TRAVEL.calendarSync` parameter (covered by `test/book-travel.approval.integration.test.ts`) | ✅ |
| TRAVEL_REBOOK_AFTER_CONFLICT | Travel | `BOOK_TRAVEL` conflict path (covered by `test/flight-rebook.e2e.test.ts`) | 🟡 — covered but weak rubric (audit gap #37) |
| EVENT_CREATE_OPPORTUNITY | Events | `CALENDAR.create_event` + `ENTITY.add` | 🟡 — possible via composition; no `EventOpportunity` domain object or dedicated action |
| EVENT_SET_DECISION_DEADLINE | Events | `SCHEDULED_TASK.create` with priority=high + `DEVICE_INTENT.broadcast` | ✅ |
| EVENT_BUILD_ITINERARY_BRIEF | Events | none | ❌ — no action assembles per-event itinerary briefs (slides + lodging + transit + checklist) |
| EVENT_TRACK_ASSET_DEADLINES | Events | `SCHEDULED_TASK.create` with subjectKind=document | ✅ |
| DOC_REQUEST_SIGNATURE | Docs | `DOC.request_signature` (`plugins/app-lifeops/src/actions/document.ts`); `DocumentRequest` type at `plugins/app-lifeops/src/types/document-request.ts` | ✅ — landed by W1-8 (2026-05-11) |
| DOC_REQUEST_APPROVAL | Docs | `DOC.request_approval` (`plugins/app-lifeops/src/actions/document.ts`) | ✅ — landed by W1-8 (2026-05-11) |
| DOC_TRACK_DEADLINE | Docs | `DOC.track_deadline` (`plugins/app-lifeops/src/actions/document.ts`); composes `SCHEDULED_TASK.create` with `subjectKind=document` | ✅ — landed by W1-8 (2026-05-11) |
| DOC_UPLOAD_ASSET | Docs | `DOC.upload_asset` (`plugins/app-lifeops/src/actions/document.ts`); leaves browser routing as Wave-2 follow-up | ✅ — landed by W1-8 (2026-05-11) |
| DOC_COLLECT_ID_OR_FORM | Docs | `DOC.collect_id` (`plugins/app-lifeops/src/actions/document.ts`) | ✅ — landed by W1-8 (2026-05-11) |
| DOC_CLOSE_REQUEST | Docs | `DOC.close_request` (`plugins/app-lifeops/src/actions/document.ts`) | ✅ — landed by W1-8 (2026-05-11) |
| NOTIFICATION_CREATE_INTENT | Push | `SCHEDULED_TASK.create` (the `NotificationIntent` PRD object is folded into `ScheduledTask` with escalation policy) | ✅ |
| NOTIFICATION_RESOLVE_ENDPOINTS | Push | `CONNECTOR.list` + `CONNECTOR.status` (returns registered endpoints) | 🟡 — connector list exists; no dedicated endpoint-resolver that maps a NotificationIntent to a target device set |
| NOTIFICATION_DISPATCH | Push | `DEVICE_INTENT.broadcast` | ✅ |
| NOTIFICATION_ACKNOWLEDGE | Push | `SCHEDULED_TASK.acknowledge` | 🟡 — ack on scheduled tasks exists, but does not suppress duplicates on other device endpoints (PRD `DeviceEndpoint` not modeled) |
| NOTIFICATION_ESCALATE | Push | `VOICE_CALL.dial` + `MESSAGE.send` (composed by SCHEDULED_TASK escalation policy) | 🟡 — Twilio voice + SMS exist (covered by `test/eow-escalation.e2e.test.ts`); phone-call + Discord escalations are `it.todo` (audit gap #47) |
| REMOTE_REQUEST_HELP | Push | `REMOTE_DESKTOP.start` | ❌ — `REMOTE_DESKTOP.start` opens a session, but no action fires the "agent stuck → ask human" handoff signal (audit gap #71, scenario catalog only) |

## Missing actions — atomic decomposition

For each ❌ entry, the recommended implementation route is:

### 1. `CALENDAR_BUILD_DOSSIER`

- **Recommended:** new `CALENDAR.build_dossier` subaction.
- **Behavior:** given a `calendar_event` id, return a structured dossier: attendees + linked entities, last-N inbox threads with each attendee, relevant docs, prior meeting notes, prep buffer status, and travel buffer status.
- **Why new:** crosses entity, message, and calendar domains and emits a typed output schema; `CALENDAR.feed` returns events, not dossiers.

### 2. `THREAD_LINK_CONTACT`

- **Recommended:** new `MESSAGE.link_thread` subaction (or extend `ENTITY.set_identity` to accept `threadId`).
- **Behavior:** associate a `Thread.id` with a `Contact.id`, optionally creating the contact, and update follow-up state.
- **Why new:** `ENTITY.set_identity` works at the handle level; thread-level linkage is the missing seam.

### 3. `FOLLOWUP_ESCALATE`

- **Recommended:** new `FOLLOWUP_ESCALATE` standalone action (or `FOLLOWUP_ESCALATE` subaction on a new `FOLLOWUP` umbrella).
- **Behavior:** advance a relationship/thread up the escalation ladder (chat → DM → SMS → call), respecting cool-down and ack suppression.
- **Why new:** ladder logic currently lives inside the `SCHEDULED_TASK` runner; no callable surface that hand-fires the escalation.

### 4. `EVENT_BUILD_ITINERARY_BRIEF`

- **Recommended:** new `BOOK_TRAVEL.build_itinerary_brief` subaction or new `EVENT_BUILD_ITINERARY_BRIEF` action.
- **Behavior:** given an event/trip id, assemble a brief with flights, lodging, ground transit, asset deadlines, and dress code.
- **Why new:** no current action composes itinerary state into a typed brief.

### 5. `DOC_REQUEST_SIGNATURE`

- **Recommended:** new `DOC` umbrella with `request_signature` subaction.
- **Behavior:** create a `DocumentRequest`, attach signer + deadline, surface to approval queue, dispatch reminder ladder via `SCHEDULED_TASK`.
- **Why new:** PRD requires a `DocumentRequest` domain object; current code has signature-deadline scenarios but no typed request.

### 6. `DOC_REQUEST_APPROVAL`

- **Recommended:** new `DOC.request_approval` subaction on the same `DOC` umbrella.
- **Behavior:** similar to signature but for review/approve workflow; binds to a doc id + approver + deadline.
- **Why new:** `RESOLVE_REQUEST.approve` resolves a queued action, but the PRD's `DocumentRequest` object — with status, approver, deadline, deep link — is not modeled.

### 7. `DOC_TRACK_DEADLINE`

- **Recommended:** `DOC.track_deadline` subaction.
- **Behavior:** create a `SCHEDULED_TASK` with `subjectKind=document` and a doc reference, automatically wiring escalation policy from `DocumentRequest.priority`.
- **Why new:** the substrate exists in `SCHEDULED_TASK`, but the doc-bound shape (status, signer, escalation) does not.

### 8. `DOC_UPLOAD_ASSET`

- **Recommended:** new `DOC.upload_asset` subaction that dispatches a browser workflow + approval gate.
- **Behavior:** upload a file to a configured portal URL, wait for completion, store result deep link.
- **Why new:** current `test/portal-upload.e2e.test.ts` only verifies `navigate`/`eval` ran; full form-fill+submit is `it.todo` per audit gap #48.

### 9. `DOC_COLLECT_ID_OR_FORM`

- **Recommended:** new `DOC.collect_id` subaction.
- **Behavior:** create a `DocumentRequest` of `kind=id_form`, dispatch reminder ladder, route uploads through `CREDENTIALS` redaction.
- **Why new:** referenced by catalog `ea.docs.collect-id-copy-for-workflow` with no impl (audit gap #49).

### 10. `DOC_CLOSE_REQUEST`

- **Recommended:** `DOC.close_request` subaction.
- **Behavior:** mark a `DocumentRequest` as complete or cancelled, update follow-up timers, archive deep link.
- **Why new:** no document state machine exists yet.

### 11. `NOTIFICATION_ESCALATE` (full ladder)

- **Recommended:** extend `SCHEDULED_TASK` escalation policy + add `DEVICE_INTENT.broadcast` per-channel routing; OR introduce a `NOTIFICATION.escalate` umbrella.
- **Status:** currently 🟡 not ❌ — counted in coverage table as 🟡. Listed here because PRD demands phone-call + Discord paths that are `it.todo`.

### 12. `REMOTE_REQUEST_HELP`

- **Recommended:** new `REMOTE_DESKTOP.request_help` subaction (separate from `start`).
- **Behavior:** fire a stuck-agent signal: dispatch high-priority `DEVICE_INTENT`, queue a `RESOLVE_REQUEST` for the user, optionally open a `REMOTE_DESKTOP.start` session once approved.
- **Why new:** `REMOTE_DESKTOP.start` opens a session unconditionally; PRD wants a request-for-help gate first.

## Wave-2 atomic actions (W2-5, landed 2026-05-11)

Four new umbrella actions landed alongside the PRD action map to give the
planner targets it can call for cross-domain operations the PRD names imply
but no single existing umbrella covers cleanly. None of these replace
existing umbrellas — they compose them.

| New action | Subactions | Composes | PRD names partially covered |
|---|---|---|---|
| `BRIEF` (`plugins/app-lifeops/src/actions/brief.ts`) | `compose_morning`, `compose_evening`, `compose_weekly` | calendar feed, inbox triage, life-domain due items, money recurring charges; LLM narrative pass via `ModelType.TEXT_LARGE` | `FOLLOWUP_GENERATE_DIGEST` (partial), `CALENDAR_BUILD_DOSSIER` (partial, calendar-focused brief) |
| `PRIORITIZE` (`plugins/app-lifeops/src/actions/prioritize.ts`) | `rank_todos`, `rank_threads`, `rank_decisions` | todos store, inbox threads, approval queue; LLM ranking by urgency × importance via `ModelType.TEXT_LARGE` | none directly; supports `INBOX_TRIAGE_PRIORITY`-style triage |
| `CONFLICT_DETECT` (`plugins/app-lifeops/src/actions/conflict-detect.ts`) | `scan_today`, `scan_week`, `scan_event_proposal` | calendar feed loader (Wave-2 wires `CALENDAR.feed`); attendee-aware severity | `CALENDAR_PROTECT_WINDOW` (partial proactive scanning) |
| `INBOX_UNIFIED` (`plugins/app-lifeops/src/actions/inbox-unified.ts`) | `list`, `search`, `summarize` | Gmail, Slack, Discord, Telegram, Signal, iMessage, WhatsApp adapters; dedupe by id + thread topic | `INBOX_LIST_UNREAD`, `INBOX_TRIAGE_PRIORITY`, `INBOX_SUMMARIZE_CHANNEL` (cross-platform variants) |

Wave-1 (W2-5) scaffolding: handlers are skeletons that COMPOSE existing
surfaces. Loaders are injectable (`setBriefComposers`, `setPrioritizeLoaders`,
`setConflictDetectLoader`, `setInboxUnifiedFetchers`) so unit tests inject
scenario data without standing up the full connector graph. Wave-2 wires
those loaders to the real underlying services.

## Spot-checks performed

| PRD action | Map says | Verified by reading |
|---|---|---|
| `CALENDAR_FIND_AVAILABILITY` | `CALENDAR.check_availability` | `plugins/app-lifeops/src/actions/calendar.ts:73` confirms `check_availability` subaction; `actions.summary.md:46` shows promoted `CALENDAR_CHECK_AVAILABILITY` |
| `CALENDAR_LIST_UPCOMING` | `CALENDAR.feed` | `plugins/app-lifeops/src/actions/calendar.ts:73` lists `feed`; `actions.summary.md:49` shows `CALENDAR_FEED` |
| `CALENDAR_RESCHEDULE_EVENT` | `CALENDAR.update_event` + `CALENDAR.bulk_reschedule` | `plugins/app-lifeops/src/actions/calendar.ts:67-68`; `actions.summary.md:45` shows `CALENDAR_BULK_RESCHEDULE` |
| `MESSAGE_DRAFT_REPLY` | `MESSAGE.draft_reply` | `packages/core/src/features/advanced-capabilities/actions/message.ts:75` confirms `draft_reply` in `MESSAGE_OPS` |
| `MESSAGE_ARCHIVE_OR_DEFER` | `MESSAGE.manage` | `packages/core/src/features/advanced-capabilities/actions/message.ts:80`; delegates to `manageMessageAction` |
| `FOLLOWUP_LIST_OVERDUE` | `LIST_OVERDUE_FOLLOWUPS` | `plugins/app-lifeops/src/followup/actions/listOverdueFollowups.ts:24` |
| `TRAVEL_BOOK_FLIGHT` | `BOOK_TRAVEL` | `plugins/app-lifeops/src/actions/book-travel.ts` defines BOOK_TRAVEL; `actions.summary.md:174` confirms |
| `NOTIFICATION_DISPATCH` | `DEVICE_INTENT.broadcast` | `actions.manifest.json:5218` confirms DEVICE_INTENT with `broadcast` enum |
| `MESSAGE_CREATE_GROUP_HANDOFF` | `WORK_THREAD.*` | `plugins/app-lifeops/src/actions/work-thread.ts:291` confirms name + lifecycle ops |
| `EVENT_SET_DECISION_DEADLINE` | `SCHEDULED_TASK.create` | `plugins/app-lifeops/src/actions/scheduled-task.ts:57-70` confirms subactions; subject kinds include `calendar_event` (`scheduled-task/types.ts:158`) |

## PRD-name aliases (Wave-1 W1-7)

PRD action names listed in `prd-lifeops-executive-assistant.md` resolve at runtime
via `similes` on existing umbrella actions. A planner asking for, e.g.,
`INBOX_LIST_UNREAD` lands on the `MESSAGE` umbrella, which then narrows by
subaction args (`list_inbox` in this case).

Similes are at the **action** level, not the subaction level — they steer the
planner to the right umbrella, after which the umbrella's `subaction` parameter
selects the verb. PRD names attached this way:

| Target umbrella | PRD action name(s) added as similes |
|---|---|
| `MESSAGE` (`packages/core/src/features/advanced-capabilities/actions/message.ts`) | `INBOX_LIST_UNREAD`, `INBOX_TRIAGE_PRIORITY`, `INBOX_SUMMARIZE_CHANNEL`, `MESSAGE_DRAFT_REPLY`, `MESSAGE_SEND_APPROVAL_REQUEST`, `MESSAGE_SEND_CONFIRMED`, `MESSAGE_ARCHIVE_OR_DEFER`, `MESSAGE_REPAIR_AFTER_MISS`, `FOLLOWUP_CREATE_DRAFT`, `FOLLOWUP_SEND_CONFIRMED` |
| `CALENDAR` (`plugins/app-lifeops/src/actions/calendar.ts`) | `CALENDAR_LIST_UPCOMING`, `CALENDAR_FIND_AVAILABILITY`, `CALENDAR_CREATE_EVENT`, `CALENDAR_CREATE_RECURRING_BLOCK`, `CALENDAR_RESCHEDULE_EVENT`, `CALENDAR_CANCEL_EVENT`, `CALENDAR_PROPOSE_TIMES`, `CALENDAR_PROTECT_WINDOW`, `CALENDAR_BUNDLE_MEETINGS`, `CALENDAR_ADD_PREP_BUFFER`, `CALENDAR_ADD_TRAVEL_BUFFER` |
| `WORK_THREAD` (`plugins/app-lifeops/src/actions/work-thread.ts`) | `MESSAGE_CREATE_GROUP_HANDOFF` |
| `SCHEDULED_TASKS` (`plugins/app-lifeops/src/actions/scheduled-task.ts`) | `EVENT_SET_DECISION_DEADLINE`, `EVENT_TRACK_ASSET_DEADLINES`, `NOTIFICATION_CREATE_INTENT`, `NOTIFICATION_ACKNOWLEDGE`, `NOTIFICATION_ESCALATE` |
| `PERSONAL_ASSISTANT` (`plugins/app-lifeops/src/actions/owner-surfaces.ts`, owns `BOOK_TRAVEL`) | `TRAVEL_CAPTURE_PREFERENCES`, `TRAVEL_BOOK_FLIGHT`, `TRAVEL_BOOK_HOTEL`, `TRAVEL_SYNC_ITINERARY_TO_CALENDAR`, `TRAVEL_REBOOK_AFTER_CONFLICT` |
| `CONNECTOR` (`plugins/app-lifeops/src/actions/connector.ts`) | `NOTIFICATION_RESOLVE_ENDPOINTS` |
| `SET_FOLLOWUP_THRESHOLD` (`plugins/app-lifeops/src/followup/actions/setFollowupThreshold.ts`) | `FOLLOWUP_CREATE_RULE` |
| `LIST_OVERDUE_FOLLOWUPS` (`plugins/app-lifeops/src/followup/actions/listOverdueFollowups.ts`) | `FOLLOWUP_LIST_OVERDUE` |

**PRD names deliberately NOT aliased (Wave-2 territory):**

- `CALENDAR_BUILD_DOSSIER`, `THREAD_LINK_CONTACT`, `FOLLOWUP_ESCALATE`, `EVENT_BUILD_ITINERARY_BRIEF`, all `DOC_*` actions, and `REMOTE_REQUEST_HELP` — these are ❌ rows above. There is no umbrella to alias onto; they require real implementation (the `DOC` umbrella is being scaffolded separately).
- `FOLLOWUP_GENERATE_DIGEST` (🟡) — currently produced by the morning-brief pack, not by a callable action; no single umbrella to alias.
- `EVENT_CREATE_OPPORTUNITY` (🟡) — composition of `CALENDAR.create_event` + `ENTITY.add`; no single umbrella owns the verb.
- `NOTIFICATION_DISPATCH` (✅ in map, but the `DEVICE_INTENT` action it points to is retired from the planner). Flagged for Wave-2 re-mapping; the map currently references a dead action.

## Renaming proposals (surprises)

A handful of PRD names disguise actions that already exist under wildly different names. These are worth either renaming or adding as `similes` so planner extraction matches both:

| PRD action | Actually implemented as | Suggested fix |
|---|---|---|
| `INBOX_LIST_UNREAD` | `MESSAGE.list_inbox` | add `INBOX_LIST_UNREAD` as a simile on `MESSAGE` |
| `INBOX_TRIAGE_PRIORITY` | `MESSAGE.triage` | add `INBOX_TRIAGE` simile |
| `MESSAGE_CREATE_GROUP_HANDOFF` | `WORK_THREAD.create` | the PRD's "group handoff" maps to thread lifecycle, not message-domain action; rename in PRD or alias `WORK_THREAD` |
| `FOLLOWUP_CREATE_RULE` | `SET_FOLLOWUP_THRESHOLD` | rename for consistency: `FOLLOWUP_SET_THRESHOLD` or alias |
| `FOLLOWUP_LIST_OVERDUE` | `LIST_OVERDUE_FOLLOWUPS` | reorder convention: `FOLLOWUP_LIST_OVERDUE` would match PRD; alias accordingly |
| `CALENDAR_ADD_TRAVEL_BUFFER` | `CALENDAR.trip_window` | rename PRD or subaction so they match |
| `NOTIFICATION_CREATE_INTENT` | `SCHEDULED_TASK.create` | the PRD's `NotificationIntent` is conflated with `ScheduledTask`; either fork the domain object or rename PRD section |
| `EVENT_SET_DECISION_DEADLINE` | `SCHEDULED_TASK.create` (priority=high) | same fork-or-rename consideration |

These are flagged for Wave-2 product/naming discussion — not implementation tasks for this wave.

## How to refresh this map

1. Re-read the `Action Catalog` section of `packages/docs/prd-lifeops-executive-assistant.md`.
2. Re-read `plugins/app-lifeops/src/actions/*.ts` subaction type definitions.
3. Cross-check `packages/benchmarks/lifeops-bench/manifests/actions.summary.md` for promoted top-level names.
4. Update the table above and the coverage counts.
