TODO
Owner-visible future work for Personal Context Protocol. Keep this list focused on versioned product work, not per-round scratch notes.
v0.1 Completed
[x] Core schema and API
[x] App instance and UI auth tables
[x] Topic, session, session token, message, event, and migration tables
[x] Setup, auth check, topic, session, token, message, event, and export routes
[x] API route handlers served from
src/app/api/v1[x] API routes marked dynamic so builds do not execute runtime database handlers
[x] Setup and authentication
[x] Deploy initialization creates schema, app instance, and the first admin credential
[x] One-time fallback setup token returned in the browser setup response
[x] Admin login page prompts for the UI token before dashboard access
[x] Admin login page prompts for fallback initialization when the database is not initialized
[x]
/api/v1/auth/checkvalidates the UI token before saving it in browser storage[x] Direct
/dashboardaccess withoutui_tokenredirects to/login?next=/dashboard[x] Automatic Postgres schema bootstrap when setup status/init runs with
DATABASE_URL
[x] Session workspace UI
[x] Topic creation and selection
[x] Session creation, editing, moving, archiving, and restoring
[x] Session token generation with copy-to-clipboard
[x] Message and event review views
[x] Dashboard split into focused topic, session, and workspace components
[x] Frontend shell
[x] Public introduction page
[x] Light, dark, and system theme toggle
[x] Published documentation links use GitHub Pages
[x] Footer links for documentation, API reference, deployment, and future work
[x] Diagnostics and docs
[x] Error messages include consequence, module/process, and cause
[x] Build/runtime diagnostics identify missing required env vars without printing secrets
[x] Build/start deploy initialization prints PCP-generated first-login admin tokens when
PCP_ADMIN_TOKENis absent[x] Sphinx documentation build root fixed
[x] README and protocol docs updated for implemented routes
v0.1.3 Completed — Agent recording URL
Shipped within the v0.1 line. The agent recording-URL surface and token expiration land here as part of v0.1; the move to v0.2.0 is gated on completing v0.1 Remaining Hardening below, not on shipping this feature.
[x] Recording URL + token model
[x]
GET /r/:sessionIdpublic recording-URL entry point[x]
GET /api/v1/agent/resolve?url=andGET /api/v1/agent/sessions/:id/protocol[x] Self-describing protocol (auth, routes, allowed_actions, limits)
[x] Copyable Recording URL + Access Token pair in the session UI
[x] Agent ingestion
[x]
POST /api/v1/agent/sessions/:id/messagesappend (append-only)[x]
POST /api/v1/agent/sessions/:id/compactdurable summaries (additional records)[x]
POST /api/v1/agent/sessions/:id/ingestforgiving parser (JSON, PCP tags, ChatML, transcript)[x] Structured
{ ok, code, retryable, message, next_steps }agent errors
[x] Token expiration
[x]
expires_inchoices (1h/24h/7d/30d/never), default 7d, NULL = never expire[x] Reject expired tokens; show active/expired/revoked + last used in UI
[x] Naming
[x] One-click topic/session creation with generated default names
[x] Duplicate title auto-suffixing; AI-suggested title normalization
v0.1.4–v0.1.10 Completed — Operability & correction
Shipped within the v0.1 line (still gated on v0.1 Remaining Hardening before v0.2).
[x] Admin token rotation (v0.1.4–v0.1.6): per-deploy rotation unless set in Settings (
user) orPCP_ADMIN_TOKEN(env); recovery guidance + dashboard warning[x] Public sessions (v0.1.7):
sessions.public, read-only/s/:id+ public API; 404 for private[x] Token management (v0.1.7, v0.1.9): revoke + rename via PATCH; auto-distinct token names; dashboard modal
[x] Recording URL origin fix (v0.1.7): UI builds from
window.location.origin; server ignores non-absolutePCP_APP_URL[x] Front-page polish (v0.1.7): load animations; footer shows deployed version
[x] Uncategorized sessions + ChatGPT-style nav (v0.1.5): nullable
topic_id; collapsible groups; right-click/long-press menu[x] Human fallback import (v0.1.8): paste agent fallback block; dedup-merge already-recorded messages
[x] Recording modes (v0.1.9):
sessions.modewild/exact surfaced to the agent[x] Message correction (v0.1.10): human admin edit/delete (append-only still enforced for AI); multi-select with select-all + shift-range; long messages fold to 5 lines in select mode
v0.1 Remaining Hardening
[x] Startup validation
[x] Add shared configuration validator for
DATABASE_URL,PCP_INSTANCE_SECRET, andPCP_APP_URL[x] Validate malformed values, not only missing values
[x] Surface deployment configuration errors in the setup UI without exposing secrets
[ ] Setup integration tests
[ ] Missing
DATABASE_URL[ ] Unreachable Neon database
[ ] Empty database schema bootstrap
[ ] Duplicate initialization
[ ] Invalid admin token login attempt
[ ] Security audit
[ ] Resolve current
npm auditfindings, including the Next.js 14.2.5 warning[ ] Add CI security scanning
[ ] Add automated checks that logs never include plaintext admin or session tokens
[ ] API docs sync
[x] Generate or validate docs against
src/app/api/v1(drift test)[ ] Add CI route/doc drift check
[ ] Keep README endpoint list in sync with protocol docs
[x] Agent import visibility and compaction rendering
Context: A user pasted a valid
PCP_COMPACTblock into the import flow. The UI reportedImported a compaction block, but the session message view showed no readable conversation content.Trigger: Import a
PCP_COMPACTpayload that containssummary,timeline,decisions, orrequirements, but nomessagesarray.Missing behavior: The app stores the compaction but does not make it visible in the session workspace as first-class readable content.
Expected UI output:
The session workspace has a
Compactionstab or section next toMessagesandEvents.If the session has compactions but no messages, the Messages pane shows:
No raw messages recorded. This session has compact summaries.The Compactions pane shows cards with
summary,timeline,decisions,requirements,open_questions,artifacts, andwarningswhen present.
Expected API/import response:
{ "ok": true, "imported": { "messages": 0, "compactions": 1, "events": 1 }, "session_id": "ses_...", "notice": "Imported a compact summary. No raw messages were included." }
Implementation tasks:
[x] Add or verify a
compactionstable/model.[x] Render compactions in the session workspace.
[x] Make
PCP_COMPACTwith no messages store a compaction, not fake message rows.[x] Make
PCP_COMPACT(andPCP_INGEST) with amessagesarray import both messages and the compaction.[x] Add an audit event for compact import (compaction.recorded).
[x] Add tests for compact-only import and compact-with-messages import.
[ ] Canonical agent fallback format
Context: Different agents are returning incompatible fallback formats. Some return generic JSON, some return
PCP_COMPACT, and some omit fields required for message recording.Trigger: Give an agent a Recording URL and Access Token, then ask it to record a session when direct upload is unavailable.
Missing behavior: The generated prompt does not force a single canonical fallback shape for message-level recording.
Expected output from agents when API upload fails but messages are reconstructable:
<PCP_INGEST> { "schema_version": 1, "session_id": "ses_...", "session_title": "optional suggested title or null", "messages": [ { "role": "user | assistant | system | tool | unknown", "content": "", "content_type": "text/markdown", "created_at": null, "observed_at": "ISO timestamp", "provider": "chatgpt | claude | gemini | cursor | codex | unknown", "agent_name": "unknown", "base_model": "unknown", "attachments": [ { "title": "", "media_type": "", "download_url": "", "description": "" } ], "metadata": {} } ], "compaction": null } </PCP_INGEST>Expected output from agents only when message-level reconstruction is impossible:
<PCP_COMPACT> { "schema_version": 1, "session_id": "ses_...", "session_title": "optional suggested title or null", "summary": "", "timeline": [], "decisions": [], "requirements": [], "open_questions": [], "artifacts": [ { "title": "", "media_type": "", "download_url": "", "description": "" } ], "warnings": [], "provider": "unknown", "agent_name": "unknown", "base_model": "unknown", "created_at": "ISO timestamp" } </PCP_COMPACT>Implementation tasks:
[ ] Update the generated agent instruction to prefer direct upload first,
PCP_INGESTsecond, andPCP_COMPACTonly as last resort.[ ] Update
/api/v1/agent/sessions/:id/ingestto preferPCP_INGEST.[ ] Keep backward compatibility with
PCP_APPEND.[ ] Return structured errors when payloads omit required message fields.
[ ] Add parser tests for
PCP_INGEST, legacyPCP_APPEND, andPCP_COMPACT.
[ ] Agent upload diagnostics and MCP connection guidance
Context: Some agents can discover
record_messages,record_compact, andingest_any, but cannot complete upload because their execution environment cannot resolvepcp.trance-0.comor cannot sendAuthorization: Bearer ...POST requests.Trigger: An agent replies that it discovered the protocol but cannot claim recording success because upload failed.
Missing behavior: The app does not give the user a precise diagnosis or a next operational path.
Expected UI output:
In the Token / Agent Instruction panel, show a
Connectivity testbutton.The test checks:
recording URL resolves
protocol endpoint responds
authenticated
reviewendpoint worksauthenticated dry-run ingest works if implemented
On failure, show one of:
DNS resolution failedTLS connection failedProtocol endpoint unreachableToken rejectedUpload route rejectedPayload schema rejected
Expected API response for diagnostics:
{ "ok": false, "stage": "dns | tls | protocol | auth | upload | schema", "code": "DNS_RESOLUTION_FAILED", "retryable": false, "message": "The recording host could not be resolved from this environment.", "next_steps": [ "Verify public DNS for pcp.trance-0.com.", "Try upload from a local relay or MCP-enabled agent." ] }
Implementation tasks:
[ ] Add documentation for connecting
https://pcp.trance-0.com/mcpas an MCP server where supported.[ ] Add sample Codex MCP config using
bearer_token_env_var.[ ] Add sample local relay script that posts
PCP_INGESTfrom a file.[ ] Document that prompt-only ChatGPT cannot be forced to send custom authenticated POST requests unless connected through MCP/tools/actions.
[ ] Do not describe CORS or trusted origins as a solution for model-side POST capability.
[ ] Message viewport containment
Context: Current message panes can overflow the browser window and push other widgets out of view.
Trigger: Open a session with long messages, long code blocks, or many events.
Missing behavior: The app shell does not constrain message/event/session panels to the viewport.
Expected UI output:
Header, sidebar, session workspace, message list, event list, and token widgets remain inside the browser viewport.
Message list scrolls internally with
overflow-y: auto.Event list scrolls internally with
overflow-y: auto.Session/sidebar list scrolls internally with
overflow-y: auto.Long code blocks scroll horizontally inside the message bubble instead of widening the page.
Implementation tasks:
[ ] Convert the dashboard/workspace shell to a viewport-height layout.
[ ] Add internal scroll containers for message, event, and session lists.
[ ] Prevent page-level overflow except on narrow screens where intentional.
[ ] Add regression test or visual check using a long message and a long code block.
[ ] ChatGPT-like message alignment
Context: Message alignment is currently wrong. System, user, and assistant messages are not visually differentiated in a readable chat flow.
Trigger: Open any recorded session with user and assistant messages.
Missing behavior: Message role is not mapped to consistent layout.
Expected UI output:
system: full-width horizontal card.user: right-aligned bubble.assistantoragent: left-aligned bubble.toolorunknown: neutral full-width or left-aligned card with visible role label.All bubbles wrap long text.
Code blocks scroll horizontally inside the bubble.
Implementation tasks:
[ ] Add role-to-layout mapping.
[ ] Add role labels for non-user/non-assistant messages.
[ ] Add CSS tests/snapshots or component tests for role alignment classes.
[ ] Verify markdown and code rendering do not break layout.
[ ] Session movement between topics
Context: Users need to reorganize sessions after creation. Topic management is human-only, but the UI should allow a session to be reassigned to another topic/folder.
Trigger: User drags a session from one topic group to another in the sidebar.
Missing behavior: Sidebar does not support drag-to-reassign or does not persist the session��s new topic.
Expected UI output:
Dragging a session over a topic highlights the target topic.
Dropping the session moves it under the target topic.
A toast appears:
Moved session to <topic title>.The session ID remains unchanged.
The message list remains unchanged.
Expected database/API behavior:
Update only
sessions.topic_id.Append an event with kind
session_moved_topic.Reject this operation for AI session tokens.
Implementation tasks:
[ ] Add admin-only API route or server action for moving a session to another topic.
[ ] Add drag-and-drop in the sidebar.
[ ] Add audit event for the move.
[ ] Add tests that UI/admin auth can move sessions.
[ ] Add tests that AI tokens cannot move sessions.
[ ] Sidebar scaling and lazy session rendering
Context: Topics with many sessions make the sidebar hard to scan and may render too many items at once.
Trigger: Create or import many sessions under one topic.
Missing behavior: The sidebar renders too many sessions and lacks progressive disclosure.
Expected UI output:
Each topic initially shows the 5 most recently updated sessions.
A
Show morebutton appears when more sessions exist.Clicking
Show morereveals the next batch.Sessions are sorted by
last_message_atfirst, thenupdated_at, descending.Sidebar scrolls internally and does not push the page height.
Implementation tasks:
[ ] Limit initial session render to 5 per topic.
[ ] Add per-topic
Show more.[ ] Use server-side limit/pagination where practical.
[ ] Add tests for initial 5-session render and expansion.
[ ] Precise topic and session default naming
Context: Topic/session creation can produce blank, duplicate, or confusing names. User wants one-click creation without being forced to name the object first.
Trigger: User clicks
New TopicorNew Sessionrepeatedly.Missing behavior: Name generation is not deterministic and duplicate-safe enough.
Expected UI output:
Topic defaults:
New TopicNew Topic 2New Topic 3
Session defaults within a topic:
New SessionNew Session 2New Session 3
If a human enters duplicate topic title
Research, create or suggestResearch 2instead of blocking.If an AI suggests duplicate session title
Route B Build Prompt, normalize toRoute B Build Prompt 2.
Implementation tasks:
[ ] Implement
normalizeTitle(input).[ ] Implement
dedupeTitle(baseTitle, existingTitles).[ ] Implement
generateUniqueTopicTitle(baseTitle).[ ] Implement
generateUniqueTopicSlug(baseTitle).[ ] Implement
generateUniqueSessionTitle(topicId, baseTitle).[ ] Add tests for blank titles, repeated default titles, and duplicate AI-suggested titles.
[ ] Session content search
Context: Current search is insufficient if it only searches session title. Users need to find sessions by message content and compact summaries.
Trigger: Search for a keyword that appears inside a recorded message or compaction but not in the session title.
Missing behavior: Search does not inspect message content or compaction content.
Expected UI output:
Add independent
Search Sessionsmodal or page.Results include session title, topic title, match type, and snippet.
Snippet includes roughly 20 words before and after the match.
Matched terms are highlighted.
Clicking a result opens the session and scrolls/highlights the target message or compaction when possible.
Expected API:
GET /api/v1/search/sessions?q=<query>&limit=20&offset=0{ "results": [ { "session_id": "ses_...", "session_title": "...", "topic_id": "topic_...", "topic_title": "...", "match_type": "message | compaction | title", "message_id": null, "compaction_id": null, "snippet": "...", "highlight_ranges": [ { "start": 10, "end": 18 } ], "updated_at": "ISO timestamp" } ], "next_offset": null }
Authorization:
UI/admin token can search all sessions.
AI session token cannot search all sessions.
Implementation tasks:
[ ] Search session titles.
[ ] Search message content.
[ ] Search compaction summary, timeline, decisions, requirements, and open questions.
[ ] Add keyword highlighting.
[ ] Add result navigation to target session/message/compaction.
[ ] Use Postgres full-text search if low-risk; otherwise use safe
ILIKEfor v0.1 and keep the API upgradeable.[ ] Add tests for message-content search, compaction search, snippets, highlights, and authorization.
[ ] Structured agent error contract
Context: Agents recover poorly from vague server errors and may reply with inconsistent fallback blocks.
Trigger: Send malformed
PCP_INGEST, expired token, forbidden topic mutation, or oversized payload.Missing behavior: Errors are not consistently actionable for an AI agent.
Expected API error shape:
{ "ok": false, "code": "INVALID_INGEST_SCHEMA", "retryable": true, "message": "The payload did not match PCP_INGEST or PCP_COMPACT.", "next_steps": [ "Retry with PCP_INGEST if you can reconstruct messages.", "Retry with PCP_COMPACT if only a summary is available." ] }
Required error cases:
TOKEN_EXPIREDTOKEN_REVOKEDTOKEN_SCOPE_FORBIDS_ACTIONTOPIC_MANAGEMENT_FORBIDDENINVALID_INGEST_SCHEMAPAYLOAD_TOO_LARGEMESSAGE_TOO_LARGEUNSUPPORTED_CONTENT_TYPE
Implementation tasks:
[ ] Normalize all agent-facing route errors to this shape.
[ ] Ensure errors never echo the access token.
[ ] Add tests for each required error case.
[ ] Acceptance checks for this hardening batch
[ ]
npm run typecheckpasses.[ ]
npm run testpasses.[ ]
npm run buildpasses.[ ] Importing compact-only content makes a visible compaction card.
[ ] Importing message-shaped fallback content creates visible chat messages.
[ ] Long messages and events scroll inside the viewport.
[ ] User, assistant, system, tool, and unknown roles render with the expected alignment.
[ ] Recording URL + Access Token flow still works.
[ ] AI tokens cannot manage topics, move sessions, or search all sessions.
[ ] User can drag sessions between topics.
[ ] Sidebar only shows the first 5 recent sessions per topic until
Show more.[ ] Search finds keywords inside message content and compactions.
[ ] Structured errors are returned for malformed agent uploads.
v0.2 Protocol Features
[ ] Token management
[ ] Token revocation UI
[ ] Token revocation API flow
[ ] Audit events for token revocation
[x] Manual custom admin token from the settings page
[x] Recovery path for lost UI token through
PCP_ADMIN_TOKENwithout printing tokens to logs[x] Missing admin credential repair during setup/init
[ ] Full UI token rotation flow with audit event history
[ ] Admin features
[ ] Replace browser-local token storage if stronger admin unlock semantics are needed
[ ] Direct topic detail endpoint
[ ] Direct message read endpoint
[ ] Export download controls in the admin UI
[ ] Import/export
[ ] Import endpoint for PCP JSON
[ ] Import endpoint for PCP JSONL
[ ] Import endpoint for generic transcripts
[ ] Richer transcript export formats
[ ] Query improvements
[ ] Pagination for topics
[ ] Pagination for sessions
[ ] Pagination for messages
[ ] Pagination for event logs
[ ] Cross-session search
[ ] Advanced context features
[ ] Bulk operations
[ ] Attachment support
[ ] Semantic search after the core append-only workflow is stable
[ ] Summaries and context compression
[ ] Auto-tagging
v0.3 Operations
[ ] Deployment diagnostics
[ ] Vercel diagnostics page
[ ] Neon diagnostics page
[ ] Schema version reporting
[ ] Migration state checks
[ ] Connection health checks without exposing secrets
[ ] Audit logging
[ ] Structured audit-log views
[ ] Token creation events
[ ] Token revocation events
[ ] Message append events
[ ] Session rename events
[ ] Archive events
[ ] Backup and restore
[ ] Neon branch backup documentation
[ ] JSON export restore process
[ ] Automated backup scripts
[ ] Rate limiting and observability
[ ] AI-facing append endpoint rate limiting
[ ] Admin token creation rate limiting
[ ] Production log guidance with secret redaction requirements
[ ] Metrics collection setup
[ ] Alerting configuration
[ ] Scaling
[ ] Custom domain documentation
[ ] Preview environment setup
[ ] Monitoring setup guide
[ ] Backup and disaster recovery procedures
[ ] Horizontal scaling guide
Later Candidates
[ ] Multiple admin users without external auth
[ ] Per-user data isolation
[ ] Role-based access control
[ ] OAuth/SSO after the single-admin model is no longer sufficient
[ ] MFA support
[ ] IP allowlisting
[ ] Optional app-level encryption
[ ] Read-only session sharing with topic fields hidden from AI-facing surfaces
[ ] Import prior AI conversations while preserving immutable message ordinals
[ ] Richer correction workflows that link correction messages to original message IDs
[ ] Local SQLite development profile
[ ] Signed messages
[ ] Advanced threat detection
Status Legend
[x] Completed and tested
[ ] Planned or not started