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/check validates the UI token before saving it in browser storage

    • [x] Direct /dashboard access without ui_token redirects 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_TOKEN is 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/:sessionId public recording-URL entry point

    • [x] GET /api/v1/agent/resolve?url= and GET /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/messages append (append-only)

    • [x] POST /api/v1/agent/sessions/:id/compact durable summaries (additional records)

    • [x] POST /api/v1/agent/sessions/:id/ingest forgiving parser (JSON, PCP tags, ChatML, transcript)

    • [x] Structured { ok, code, retryable, message, next_steps } agent errors

  • [x] Token expiration

    • [x] expires_in choices (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) or PCP_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-absolute PCP_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.mode wild/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, and PCP_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 audit findings, 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_COMPACT block into the import flow. The UI reported Imported a compaction block, but the session message view showed no readable conversation content.

    • Trigger: Import a PCP_COMPACT payload that contains summary, timeline, decisions, or requirements, but no messages array.

    • 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 Compactions tab or section next to Messages and Events.

      • 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, and warnings when 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 compactions table/model.

      • [x] Render compactions in the session workspace.

      • [x] Make PCP_COMPACT with no messages store a compaction, not fake message rows.

      • [x] Make PCP_COMPACT (and PCP_INGEST) with a messages array 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_INGEST second, and PCP_COMPACT only as last resort.

      • [ ] Update /api/v1/agent/sessions/:id/ingest to prefer PCP_INGEST.

      • [ ] Keep backward compatibility with PCP_APPEND.

      • [ ] Return structured errors when payloads omit required message fields.

      • [ ] Add parser tests for PCP_INGEST, legacy PCP_APPEND, and PCP_COMPACT.

  • [ ] Agent upload diagnostics and MCP connection guidance

    • Context: Some agents can discover record_messages, record_compact, and ingest_any, but cannot complete upload because their execution environment cannot resolve pcp.trance-0.com or cannot send Authorization: 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 test button.

      • The test checks:

        • recording URL resolves

        • protocol endpoint responds

        • authenticated review endpoint works

        • authenticated dry-run ingest works if implemented

      • On failure, show one of:

        • DNS resolution failed

        • TLS connection failed

        • Protocol endpoint unreachable

        • Token rejected

        • Upload route rejected

        • Payload 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/mcp as an MCP server where supported.

      • [ ] Add sample Codex MCP config using bearer_token_env_var.

      • [ ] Add sample local relay script that posts PCP_INGEST from 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.

      • assistant or agent: left-aligned bubble.

      • tool or unknown: 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 more button appears when more sessions exist.

      • Clicking Show more reveals the next batch.

      • Sessions are sorted by last_message_at first, then updated_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 Topic or New Session repeatedly.

    • Missing behavior: Name generation is not deterministic and duplicate-safe enough.

    • Expected UI output:

      • Topic defaults:

        • New Topic

        • New Topic 2

        • New Topic 3

      • Session defaults within a topic:

        • New Session

        • New Session 2

        • New Session 3

      • If a human enters duplicate topic title Research, create or suggest Research 2 instead of blocking.

      • If an AI suggests duplicate session title Route B Build Prompt, normalize to Route 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 Sessions modal 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 ILIKE for 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_EXPIRED

      • TOKEN_REVOKED

      • TOKEN_SCOPE_FORBIDS_ACTION

      • TOPIC_MANAGEMENT_FORBIDDEN

      • INVALID_INGEST_SCHEMA

      • PAYLOAD_TOO_LARGE

      • MESSAGE_TOO_LARGE

      • UNSUPPORTED_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 typecheck passes.

    • [ ] npm run test passes.

    • [ ] npm run build passes.

    • [ ] 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_TOKEN without 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