docs: design Codex publishing and routine execution workflows

This commit is contained in:
2026-09-28 21:43:13 +09:00
parent 8985ef9fff
commit b0458c4b91
12 changed files with 579 additions and 0 deletions
+386
View File
@@ -0,0 +1,386 @@
# External Codex publishing into the workspace
Proposal, 2026-09-28. No endpoints, timers, or inference jobs in this document
have been implemented. This supersedes the earlier proposal for app-managed
inference and an application-owned life filesystem adapter.
## Responsibility
External Codex reads Beeper and the life filesystem, reasons about them, and
maintains life under its existing Rensheng conventions. life remains the CRM
source of truth. The workspace accepts structured results, persists and displays
them, and records user decisions and requests. It does not need a new LLM loop,
CRM compiler, or Markdown editing engine.
```mermaid
flowchart LR
T[Host timer or manual invocation] --> C[External Codex job]
B[Beeper API / CLI] --> C
C <-->|Read and maintain CRM| L[Rensheng / life files]
C -->|Publish structured results| P[Application write API]
P --> D[SQLite projections and user decisions]
D --> U[Home / Messages / CRM]
U -->|Requests and corrections| Q[Durable request inbox]
Q --> C
```
The existing Research chat can remain as-is. This design does not require
removing that feature or putting its runtime in charge of CRM automation.
Deterministic Beeper reads, live UI updates, and confirmed sends are ordinary
application integration code; they do not imply app-owned inference.
## What gbrain actually does
Inspected revision: `e78f1c38b947b053f3a46881340f74f316be855a`.
- Its [cron convention](https://github.com/garrytan/gbrain/blob/e78f1c38b947b053f3a46881340f74f316be855a/skills/conventions/cron-via-minions.md)
assigns scheduling to the host. It explicitly describes a native cron
scheduler inside `jobs work` as not yet shipped.
- [Minions workers](https://github.com/garrytan/gbrain/blob/e78f1c38b947b053f3a46881340f74f316be855a/src/core/minions/worker.ts)
handle durable execution, leases and retries. Job idempotency and prevention
of overlapping runs are separate concerns.
- [Autopilot](https://github.com/garrytan/gbrain/blob/e78f1c38b947b053f3a46881340f74f316be855a/src/commands/autopilot.ts)
is a maintenance daemon, not a ready-made external Codex scheduler. The
built-in [subagent handler](https://github.com/garrytan/gbrain/blob/e78f1c38b947b053f3a46881340f74f316be855a/src/core/minions/handlers/subagent.ts)
uses gbrain's own model/tool execution.
- Its [page write operation](https://github.com/garrytan/gbrain/blob/e78f1c38b947b053f3a46881340f74f316be855a/src/core/ops/pages.ts)
uses request receipts, expected revisions and transactional writes. These are
useful patterns for publishing into this app without importing its entire stack.
## Scheduling proposal
Use one external systemd timer and oneshot service, or the existing host scheduler
if one already owns this workflow. Do not create schedules during research.
Start with a morning brief and periodic daytime refresh; exact cadence and job
timeout are deployment choices, not established product requirements.
The runner sets an explicit working directory and `CODEX_HOME`, prevents
concurrent runs, reads the app context revision, then invokes Codex to inspect
sources and prepare a result. It publishes through the application API and keeps
a private result file until acknowledgment so a network retry need not repeat
inference. Do not put credentials in prompts or command arguments.
Use separate identifiers for the scheduled occurrence and publish attempt. A
retry of an unchanged result keeps its `runId`; regeneration after a conflict
uses a new `runId`. Host logs expose started, finished and failed runs without
dumping messages. The UI can show the last successful publication and source
freshness; it should retain the previous good result when a new run fails.
Beeper events can later mark work dirty and coalesce a wake-up. Do not start one
Codex process per message. Natural-language requests can use the same external
worker path; a future wake-up signal should only notify that worker, not execute
browser-supplied shell text.
## Write interface
Start with HTTP and a small CLI wrapper that accepts JSON from a file/stdin.
Add an MCP wrapper only if useful for tool discovery; it must call the same
validated service. HTTP, CLI and MCP are access methods, not three state stores.
Avoid direct SQLite writes and an arbitrary SQL, shell or filesystem tool.
Proposed first contract, keeping the repository's camelCase JSON convention:
| Method and path | Caller | Purpose | Success |
| -------------------------- | --------------------- | ----------------------------------------------------------------------- | ------------------------- |
| `GET /api/agent-context` | Agent credential | Read revision, current projections, user decisions and pending requests | `200` |
| `POST /api/agent-results` | Agent credential | Atomically publish a validated result and complete referenced requests | `201`; exact replay `200` |
| `POST /api/agent-requests` | Owner browser session | Persist a natural-language request or a requested life correction | `201`; exact replay `200` |
Browser snapshot reads use the same application service under owner session
authentication. An optional `GET /api/agent-results/{runId}` receipt endpoint can
be added if exact POST replay is insufficient. No public API version prefix is
needed for this first coordinated client/server contract.
The agent credential is limited to context reads and result publication. It must
not approve a send, change login settings, or mark user decisions on the user's
behalf. The existing session, Tailscale and Origin middleware does not accept
this authentication flow today. Implement a narrowly scoped agent route branch
that verifies its own credential; do not add these paths as unauthenticated
exceptions or spoof a Tailscale identity. Use loopback locally, TLS remotely.
### Result shape
Illustrative payload, with fictional data:
```json
{
"runId": "morning-2026-09-29-attempt-1",
"jobKey": "daily-brief",
"expectedRevision": 42,
"generatedAt": "2026-09-28T23:00:00Z",
"sourceRefs": [
{
"id": "life-person-example",
"kind": "life",
"path": "people/example.md",
"contentHash": "sha256:example",
"observedAt": "2026-09-28T22:59:00Z"
}
],
"brief": {
"date": "2026-09-29",
"timeZone": "Asia/Tokyo",
"text": "Start with the meeting reply.",
"evidenceIds": ["life-person-example"]
},
"people": [
{
"id": "person-example",
"name": "Example Person",
"context": "Discussing the next meeting.",
"evidenceIds": ["life-person-example"]
}
],
"activities": [],
"replyDrafts": [],
"retractions": [],
"completedRequests": []
}
```
`runId` and `jobKey` are required bounded strings; `expectedRevision` is a
nonnegative integer from the last context read. All timestamps are RFC 3339.
The server stamps `receivedAt` and authenticated publisher identity itself.
Dates used for the home brief include an explicit timezone.
People/activities/drafts are upserts with stable IDs, not position-based IDs or
display names. People are projections of life, not independently maintained CRM
facts. Activities use the typed contract below, with a title, references and
evidence IDs. Drafts include canonical target/account/chat IDs, reply target,
source message revision and candidate bodies/styles. Beeper evidence includes
target/account/chat/message IDs and observation time; life evidence includes a
relative path and content hash. A Git revision alone does not describe uncommitted
life edits. Source references are data, never filesystem access instructions.
The app validates structure, references, bounds and permissions; it does not
infer whether a CRM fact is true. Publisher-supplied evidence is provenance, not
proof that the app independently verified the original file or conversation.
Omitted `brief` leaves the brief unchanged; empty arrays perform no upserts.
Omission never deletes an existing item. Explicit typed retractions can withdraw
agent suggestions but cannot delete user-owned decisions. Reject unsupported
fields and nulls in this coordinated first version. Agree payload size, per-array
limits and bounded context pagination when implementing; do not accept unbounded
history or attachments through this endpoint.
### Atomic publication and conflicts
1. Scope receipts to authenticated publisher plus `runId`. Store a canonical
payload hash. A replay with the same payload returns the original receipt;
the same key with different content returns `409 idempotency_conflict`.
2. Check replay before checking the expected revision. A successful retry must
still work after unrelated later UI changes.
3. Validate the full result, check `expectedRevision`, write projections and the
receipt, and increment the context revision in one SQLite transaction.
A concurrent publish or user edit yields `409 revision_conflict` and no writes.
4. User edits, dismissals, completions and selections live separately from agent
suggestions. A new proposal cannot revive a dismissed action or replace a
user-edited draft. Context reads expose those decisions to Codex.
5. Emit a browser update only after commit. On reconnect, fetch a snapshot;
notifications are not the source of truth. A failed publication leaves the
previous brief intact.
Return `{runId, revision, receivedAt}` as the receipt. Keep deduplication receipts
for the MVP's lifetime; any future pruning must define a retry horizon first.
Retry transient transport failures with the exact payload and key. Conflicts
require a fresh context read and reconciliation, not blind retry.
Use a small stable error envelope such as
`{code, message, details, requestId}`: `400` malformed JSON, `401` invalid agent
credential, `403` forbidden operation, `409` conflicts, `413` oversized payload,
`422` invalid result structure, `429` throttling, and `5xx` transient server faults.
No partial successes. This is a new machine API; it need not refactor unrelated
existing UI error contracts.
## Returning user intent to Codex
The app must also expose what the user did. Otherwise the next scheduled run
cannot distinguish a stale suggestion from a deliberate dismissal or correction.
`POST /api/agent-requests` accepts a stable client `requestId`, a kind such as
`refresh`, `reply-draft`, or `crm-edit`, an optional entity ID/source revision,
and the user's text or requested edit. Persist before acknowledging. Repeated
IDs with identical bodies return the same request; mismatches return `409`.
A result links each completed request using
`completedRequests: [{requestId, sourceRefIds}]`. All source references must exist
in the publication; a `crm-edit` completion requires a life reference with the
resulting content hash. Reject completion of unknown or already cancelled
requests. This validates the claimed provenance link, not the file contents
independently.
A person-note edit appears as pending while external Codex applies it to life.
It becomes confirmed only after publication references that request and supplies
the resulting source revision. Failures keep the previous confirmed projection
and the pending request visible. Do not label an app-only edit as already saved
to life. Single-worker execution avoids requiring a job lease API for this MVP.
life changes and app publication are not one transaction. If the process stops
between them, the next run re-reads life and checks the request's outcome before
applying it again. Prefer desired-state edits over blind append operations and
preserve request provenance where the life workflow permits it.
Actual message sending remains a separate, revision-bound user command. Publishing
a draft or marking an agent request complete cannot send a message. Send results
can be exposed in the next agent context for Codex to update life.
## First useful slice
Implement context read and result publish, persist them, and render a published
brief plus a mixed activity list: weight entry, a simple optional task, routine
steps and a reply linked to published life context. Prove duplicate replay,
conflict handling, reload persistence and preservation
of user decisions with fixture data. Then run one external Codex job manually
before installing a timer. Add the request inbox when introducing on-demand
generation or CRM editing. This order gives the agent somewhere to write before
building automation around it.
The [Beeper Copilot captures](references/beeper-copilot/README.md) provide the UI
reference for those published results: conversation list, conversation body,
person context, evidence chips, reply candidates and explicit review.
## One activity list, different execution surfaces
Home should unify what the user needs to do, while preserving the right controls
for each activity. A shared task abstraction does not imply a universal checkbox
or a universal chat card. Activity ordering, deferral and visibility are shared;
execution and completion are domain-specific.
| Activity kind | Inline or expanded Home UI | Completion evidence |
| ------------- | --------------------------------------------------------------------- | ----------------------------------------------------------- |
| `task` | Concise title, optional detail, completion control | User marks it complete |
| `measurement` | Weight number field, unit, last recorded value/time, Save | A measurement record is saved |
| `reply` | Person, latest relevant message, reason to reply, draft editor/review | Send is confirmed; a larger exchange may remain waiting |
| `routine` | Ordered child activities and progress | Required children complete, or an explicit skip is recorded |
Use common fields such as `id`, `title`, `kind`, `evidenceIds`, `personId`,
`parentId`, `occurrenceKey`, and optional recommendation/order metadata. User
state (available, in progress, waiting, deferred, completed or skipped) is stored
separately from Codex's recommendation. Each kind has a validated payload and a
fixed application renderer; do not accept agent-generated executable UI or HTML.
`routine` and `optional` in the current Home sections are grouping/priority
choices, not exclusive UI types. A weight activity can be a morning routine step;
a reply can be optional today. A routine groups child activities rather than
duplicating their records. Home and Messages refer to the same reply activity ID,
so editing or finishing it in either surface is immediately consistent.
For example, an illustrative measurement activity published by Codex:
```json
{
"id": "weight-2026-09-29",
"kind": "measurement",
"title": "Log weight",
"parentId": "morning-2026-09-29",
"occurrenceKey": "2026-09-29@Asia/Tokyo",
"payload": { "metric": "weight", "unit": "kg" },
"evidenceIds": []
}
```
Codex chooses or recommends the activity; the user supplies the measured number.
The app saves the observation and its occurrence time without invoking inference.
Corrections preserve the observation history. Completion must reflect that save,
not merely a checked box. The agent can read this execution evidence on its next
run and maintain life accordingly; the app does not need to infer health advice.
Recurring activities need stable per-occurrence IDs: publishing tomorrow's
routine must not reopen today's completed one. Missing time slots are valid;
the user explicitly wants flexible daily ordering rather than a strict calendar.
A real appointment can still retain its explicit date/time.
Reply completion follows the confirmed send state, not draft generation, review
or merely pressing Send. A conversation can contain multiple distinct commitments;
Codex determines those relationships from sources. The application stores explicit
links and user choices without deciding that one reply resolves every commitment.
The resulting Home can place a weight input, a routine's next step, a reply
preview and a simple task together. Use a compact shared outer row and expand
the relevant controls in place; detailed conversation/CRM views remain available.
Natural-language entry creates an external-agent request, while direct numeric
entry, checkboxes and draft edits remain immediate deterministic UI operations.
## Routine execution and workstyle learning
The user wants to import ideal routines from life, track their execution in this
app, and use external Codex analysis to develop a workable personal workstyle.
This adds explicit execution analytics to the earlier reference-only routine
concept; it does not imply that all ideals are already practiced or due daily.
Keep three levels distinct:
1. **Routine definition:** life source, stable ID, definition revision, purpose,
trigger, steps, and completion rule. Codex publishes a structured projection.
2. **Trial/activation:** which version is currently being tried, applicable days
or situations, and the chosen scope. Importing an ideal into the catalog does
not silently activate every step as a daily obligation.
3. **Occurrence and observations:** the actual applicable occasion, its frozen
definition revision, user actions, recorded values, skips, and corrections.
The application is the source for execution history; life links to it rather
than maintaining a second completion ledger.
An approved routine definition can be instantiated deterministically by the app
on its recurrence or a user action such as starting/ending work. Codex need not
run every time a routine appears. Situational occurrences should come from an
explicit trigger or confirmed source, not an assumed event inferred by the UI.
Keep occurrence identity stable across delayed cron runs and retries. Do not
turn unfinished instances into an ever-growing daily backlog automatically.
Proposed operating loop:
- **Import:** Codex reads life and publishes a routine catalog with sources and
revisions. Show what is already active and what remains an ideal/candidate.
- **Try:** choose a small set and a review window, for example one or two weeks.
These durations and counts are starting suggestions, not fixed app rules.
- **Execute:** Home presents due/applicable occurrences with kind-specific UI.
Save completion evidence as part of the natural action: entering a value,
sending a reply, writing a resumption note, or completing a task. Optional
friction feedback can be one tap; reporting a reason is not required.
- **Review:** the application calculates counts from recorded events. External
Codex reads the counts and underlying evidence, relates them to life context,
and publishes a short review with observations, uncertainties and proposals.
- **Adjust:** the user adopts, modifies or rejects a proposal. Codex updates the
ideal/working procedure in life and publishes a new definition revision.
Historical occurrences retain their previous revision and completion rule.
A scheduled daily job can refresh the overview, while a weekly job reviews the
experiment. Neither creates additional inference inside the app. The publishing
contract will need versioned routine definitions and review artifacts alongside
activities; context reads must expose execution observations and aggregate counts.
Those are deterministic data contracts, not a new agent runtime.
### Metrics that preserve meaning
Show counts and denominators next to percentages. For each routine revision and
review window, report completed, partially completed, explicitly skipped,
deferred, not applicable, and unrecorded occurrences separately. A past due item
without an observation remains unrecorded, not verified non-execution.
A useful default is **recorded attainment = completed / applicable planned
occurrences**, accompanied by observation coverage. For example, 5 completed,
1 explicitly skipped and 1 unrecorded out of 7 applicable occasions yields 5/7
recorded attainment and 6/7 observed outcomes. It does not prove that the person
failed to act on the unrecorded occasion. If a resolved-outcome rate is also
shown, label its different denominator explicitly. Keep skipped occasions in
the planned denominator; exclude not-applicable ones with a recorded reason and
retain plan revisions so exclusions cannot silently rewrite prior performance.
Do not count a routine parent and every child as independent equivalent successes
in a global percentage. Analyze routines and steps at separate levels. Optional
ideas that were never scheduled/adopted do not belong in the planned denominator.
Explicitly record reduced/partial completion without silently calling it full
completion. Measurement adherence is about saving a measurement, not moving the
number in a preferred direction; reply counts do not measure relationship quality.
Attainment alone cannot establish usefulness. Add lightweight, optional feedback
on effort and whether a routine helped, plus domain-specific evidence such as a
resumption note being available next time. Compare versions over named periods
and show sample sizes. Codex can suggest one change to try next, but sparse
observations or coincident changes do not establish a causal improvement.
The review should answer: what was practical, where execution stopped, what was
useful, and what small change is worth trying next. Good outcomes can include
shortening, reducing frequency, changing the trigger, or retiring a routine.
Do not optimize a single global completion score at the expense of the purpose
of the work or the user's freedom to change the plan.
+143
View File
@@ -0,0 +1,143 @@
# Beeper integration research
Researched 2026-09-28. Proposal only; no integration was installed during research.
## Current direction
External Codex performs inference, reads Beeper, and reads/writes life under
Rensheng conventions. life is the CRM source of truth, serving the role Scrapbox
plays in Beeper Copilot. This application accepts structured publications and
provides the UI, persistent execution state, and user feedback. It does not need
a new CRM inference runtime or life filesystem editing engine.
Home combines routines, optional tasks, measurements and communication as
activities, with different controls for each kind. A weight entry, reply editor,
routine checklist and simple completion control belong in one daily overview.
See [external agent publishing](agent-publishing-design.md) for the concrete
contract and gbrain cron findings, and the
[Beeper Copilot screenshot gallery](references/beeper-copilot/README.md) for UI
references. This supersedes earlier proposals for app-managed inference and
direct app-to-life editing.
## Verified locally
- Beeper CLI 0.6.2 and Server run on UM790-Pro.
- Public `GET http://127.0.0.1:23373/v1/info` returned Beeper 4.3.149 on Linux,
running, remote access disabled and MCP enabled.
- Discovery exposes `/v0/mcp`, `/v1/ws`, and `/v1/spec`. The live OpenAPI
reports API version 5.0.0, distinct from the application/SDK version domains.
- The existing CLI target `um790` successfully retrieved server info using
`--read-only`. This is discovery verification, not proof of complete account
synchronization or successful message delivery.
- No private conversation bodies were fetched, and no Beeper configuration or
messages were changed. The screenshots contain public LP demonstrations.
The [official CLI](https://github.com/beeper/cli) supports headless Server as
well as Desktop. No additional GUI machine or remote tunnel is needed here.
## HTTP, WebSocket, MCP and CLI
| Interface | Role |
| -------------------------------------------- | -------------------------------------------------------------- |
| Beeper HTTP / CLI / SDK | Read messages, reconcile changes, perform approved sends |
| Beeper WebSocket | Live UI changes or a coalesced signal for the external worker |
| App write API, optionally wrapped as CLI/MCP | Receive Codex results without inference |
| App context/request API | Expose user decisions, pending requests and revisions |
| Browser HTTP + SSE | Persisted views, direct UI operations and update notifications |
Existing CLI authentication can be reused with bounded, fixed-argument
`api get` calls and `watch --target um790 --read-only --json`. Do not expose
arbitrary CLI/RPC command strings as agent tools. The
[official TypeScript SDK](https://github.com/beeper/desktop-api-js) is an alternative
after explicitly provisioning an application credential. Choose one transport
inside the adapter; automatic CLI/SDK fallback is unnecessary.
The [MCP guide](https://developers.beeper.com/desktop-api/mcp/) uses Streamable
HTTP. The [changelog](https://developers.beeper.com/desktop-api/changelog/) removes
the old Beeper MCP SSE transport; our own browser SSE can remain.
## Synchronization findings
The running server's `/v1/spec` explicitly states that WebSocket delivery is
at-most-once, has no replay after reconnect, and uses per-connection sequence
numbers. The [WebSocket guide](https://developers.beeper.com/desktop-api/websocket-experimental/)
also describes experimental status and best-effort payloads. HTTP reconciliation
is required after disconnects and periodically. Do not start Codex per message.
Subscribe before initial reconciliation, track changed chats during it, then
refetch those chats. Commit progress only after persistence. Use canonical
target/account/chat/message IDs and revisions or content hashes. Edited/deleted
evidence invalidates affected drafts. One missing list result does not prove
deletion. CLI watch webhooks are best-effort and can drop on queue overflow;
a same-machine worker avoids needing a webhook receiver, not the need to reconcile.
The [message API](https://developers.beeper.com/desktop-api-reference/resources/messages/methods/list/)
returns opaque cursors. life's backfill guide records missed/duplicated pages
when CLI message IDs were used as cursors, plus API order differing from timestamp
order. Do not stop pagination merely because a date boundary was crossed.
## Reference findings
### life
`life/briefs/2026-09-25-executive-support-design.md` describes source-backed reply
assistance, explicit review and durable personal context. Existing
`life/docs/beeper-backfill.md` and `life/scripts/beeper_backfill.py` implement
reviewed, resumable CLI backfill on this machine.
That helper is not a continuous inbox worker: discovery covers 100 recent chats,
pages require review/acknowledgment, and some quotes, forwarded messages and
attachments are deliberately excluded. Its output is not a complete conversation
view. Reuse its identity/provenance rules. Its guide warns that CLI 0.6.2 raw
`status --json` can expose credentials.
Codex should maintain existing life domain pages. The app displays published
CRM projections; user corrections return as durable requests to Codex. It must
distinguish pending corrections from confirmed life changes.
### gbrain
Inspected revision `e78f1c38b947b053f3a46881340f74f316be855a`. No Beeper-specific
connector was found. Its [open-loop design](https://github.com/garrytan/gbrain/blob/e78f1c38b947b053f3a46881340f74f316be855a/docs/guides/open-loops.md)
informs requests, commitments, waiting and source freshness. Its
[sync implementation](https://github.com/garrytan/gbrain/blob/e78f1c38b947b053f3a46881340f74f316be855a/src/core/connectors/sync.ts)
advances progress after successful ingestion. Apply those principles in the
external Codex workflow. The [publishing proposal](agent-publishing-design.md)
covers its host scheduler, job execution and transactional write patterns.
### Rensheng / OpenBrief
Inspected local revision `c06c4e3f290800752a0c252c84fbca0eed61e45d`.
Rensheng's [setup](https://github.com/yutakobayashidev/rensheng/blob/c06c4e3f290800752a0c252c84fbca0eed61e45d/docs/setup.md)
reuses existing source tools. OpenBrief's
[proposal-only MCP](https://github.com/yutakobayashidev/rensheng/blob/c06c4e3f290800752a0c252c84fbca0eed61e45d/crates/openbrief-app/src/mcp.rs)
and [snapshot transport design](https://github.com/yutakobayashidev/rensheng/blob/c06c4e3f290800752a0c252c84fbca0eed61e45d/docs/adr/0004-separate-acp-local-and-remote-transports.md)
are useful boundaries. Neither requires adopting its Rust application or
duplicating its filesystem workflow in this app.
### Beeper Copilot
The [LP](https://beeper-copilot-lp.vercel.app/) was inspected in Chromium at
desktop/mobile sizes. The three-pane view, person context, evidence chips and
reply review are concrete UI references, documented in the
[capture gallery](references/beeper-copilot/README.md). Its linked source repository
returned 404 to unauthenticated access; screenshots verify the LP presentation,
not backend behavior. Use life in the Scrapbox role. EventKit, macOS deployment
and the demo's relationship scoring are not requirements here.
## Sending
The [send API](https://developers.beeper.com/desktop-api-reference/resources/messages/methods/send/)
returns a pending ID, not delivery confirmation. Bind approval to exact draft
revision, recipient and reply target, then resolve pending IDs before marking
sent. The inspected schema does not document a client idempotency key, so local
deduplication cannot guarantee exactly-once delivery after an ambiguous failure.
Disable automatic send retries and reconcile uncertain results. The
[SDK defaults](https://github.com/beeper/desktop-api-js#retries) include retries on
transport errors and timeouts. Publishing a draft/activity must not send a message.
The current [execution support](execution-support.md) is still fictional and
in-memory. Establish the external agent's write interface and persistent typed
activities before installing scheduled automation.
+50
View File
@@ -0,0 +1,50 @@
# Beeper Copilot UI reference captures
Source: <https://beeper-copilot-lp.vercel.app/>
Captured on 2026-09-28 with Chromium through agent-browser. These are screenshots
of the public landing page and its animated UI demonstrations, not screenshots
of a logged-in production application. Displayed people and conversations come
from that page, not this user's Beeper account. Animations can show different
stages between captures. No page contents were modified to create the images.
| Capture | Contents |
| ---------------------------------------------- | ---------------------------------------------------------------------------------- |
| [Desktop three-pane](desktop-three-pane.png) | Conversation list, conversation body/composer, person context; 1440 × 720 viewport |
| [Reply review](desktop-reply-review.png) | Three reply styles, selected candidate, approval button; 1440 × 1080 |
| [CRM and evidence](desktop-crm.png) | Person panel, evidence-backed fields, people board; 1440 × 1080 |
| [Features](desktop-features.png) | Unified inbox, ghost completion, review and reply suggestions; 1440 × 1080 |
| [Feedback](desktop-feedback.png) | Candidate comparison and writing-rule feedback; 1440 × 1080 |
| [Desktop hero](desktop-hero.png) | Landing-page introduction and part of the demo; 1440 × 1080 |
| [Desktop full page](desktop-full.png) | Entire landing page at 1440px wide |
| [Mobile hero](mobile-hero.png) | Landing-page layout at 390 × 844 |
| [Mobile conversation](mobile-conversation.png) | The demo's compressed conversation layout at 390 × 844 |
## Patterns to reuse
- Three coordinated panes: compact list, a dominant conversation, and persistent
person context. In this app the right pane should show Codex-published life
context, source references and pending user corrections.
- Compact network badges on identities and messages. Keep original conversation
identity available even when presenting a person across networks.
- A reply review sits near the conversation and composer. Candidate selection,
editing and confirmation remain visible steps; approval is distinct from
generating or inserting a suggestion.
- Evidence chips next to contextual statements provide a path back to messages
or the published life source reference.
- Suggested actions include their reason and can populate the appropriate
editor. The app can render externally produced suggestions without inference.
The LP's dense right panel and desktop three-pane arrangement are useful
references. Its mobile demo squeezes the columns and is not a good mobile
navigation model for this app: use list → conversation with an accessible context
panel instead. The LP's relationship-phase labels, coverage scores and confidence
percentages are demo product choices, not requirements for this personal CRM.
For Home, borrow the contextual presentation inside a reply activity rather than
embedding the full inbox. Weight logging needs a numeric input; a routine needs
steps; an optional task needs a simple completion control. These can coexist in
one activity list without forcing every activity into a chat layout.
See [external agent publishing](../../agent-publishing-design.md) for the proposed
producer/consumer boundary and typed activity contract.
Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB