import type { ParityRow } from "./matrix.types"; export const parityMatrix: ParityRow[] = [ { id: "sidebar.document-tree-crud", surface: "sidebar", label: "Create, delete, move, favorite, list, search, and open pages", uiEntrypoints: [ "app/components/sidebar/DocumentSidebar.tsx", "app/components/sidebar/DocumentTreeItem.tsx", "app/hooks/use-documents.ts", ], durableEffect: "Document tree rows and document metadata are created, updated, deleted, moved, searched, or read.", uiImplementation: "Sidebar and hooks call document actions with optimistic cache updates for visible responsiveness.", status: "action-backed", actions: [ "create-document", "clone-creative-context-document", "delete-document", "get-document", "list-trashed-documents", "list-documents", "move-document", "permanently-delete-document", "restore-document", "search-documents", "update-document", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: [ "actions/content-database-lifecycle.db.test.ts", "actions/_local-file-documents.test.ts", ], evalScenarioIds: ["document-search-edit"], }, { id: "workspace.spaces-and-files-catalog", surface: "workspace", label: "Provision, navigate, and delete Content spaces through Files and Workspaces with personal expansion state", uiEntrypoints: [ "app/components/sidebar/DocumentSidebar.tsx", "app/hooks/use-content-spaces.ts", ], durableEffect: "Personal and organization spaces, user-created workspaces, their canonical Files databases, the personal Workspaces catalog, and each user's sidebar expansion state are stored and reconciled in SQL; deleting a user-created workspace atomically removes its catalog row and contents.", uiImplementation: "The app sidebar calls the shared space actions and renders the selected Files database through a saved sidebar view.", status: "action-backed", actions: [ "backfill-content-files", "create-content-space", "delete-content-space", "ensure-content-spaces", "get-content-sidebar-state", "list-content-spaces", "update-content-sidebar-state", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: [ "actions/content-spaces.db.test.ts", "actions/content-files.db.test.ts", "actions/content-sidebar-state.test.ts", ], }, { id: "sidebar.navigation-and-screen-context", surface: "sidebar", label: "Navigate between documents and expose current screen context", uiEntrypoints: [ "app/components/sidebar/DocumentSidebar.tsx", "actions/navigate.ts", "actions/view-screen.ts", ], durableEffect: "Application navigation state is updated or read so the agent can reason about the user's current page/view.", uiImplementation: "The UI uses React Router and application-state writes; agents use navigation and screen-context actions.", status: "action-equivalent", actions: ["navigate", "view-screen"], exception: "Human navigation is router-local, while agent navigation/screen inspection uses application-state actions to produce the same workspace orientation effect.", reliabilityRisk: "none", spinePriority: "P1", testCoverage: "seeded", followUpPR: null, }, { id: "sidebar.chrome-state", surface: "sidebar", label: "Collapse sections and resize the sidebar", uiEntrypoints: [ "app/components/sidebar/DocumentSidebar.tsx", "app/components/layout/Layout.tsx", ], durableEffect: null, uiImplementation: "Sidebar expansion, section collapse, and width are client-local UI state.", status: "client-only-ephemeral", actions: [], exception: null, reliabilityRisk: "none", spinePriority: "P2", testCoverage: "none", followUpPR: null, }, { id: "editor.document-body-and-title", surface: "editor", label: "Edit document title, body, icon, image alt text, and precise text", uiEntrypoints: [ "app/components/editor/DocumentEditor.tsx", "app/components/editor/DocumentDatabase.tsx", "app/components/editor/extensions/ImageBlock.tsx", "app/components/editor/SlashCommandMenu.tsx", ], durableEffect: "Document content, title, icon, image metadata, and text replacements are saved to the same document source.", uiImplementation: "The editor autosaves through update-document; agents can use update-document, edit-document, pull-document, and media-specific helpers.", status: "action-backed", actions: [ "edit-document", "pull-document", "set-image-alt-text", "transcribe-media", "update-document", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: [ "actions/content-database-lifecycle.db.test.ts", "actions/_local-file-documents.test.ts", ], evalScenarioIds: ["document-search-edit"], }, { id: "editor.client-formatting-and-insertions", surface: "editor", label: "Rich text formatting, selection state, slash block insertion, and copy actions", uiEntrypoints: [ "app/components/editor/BubbleToolbar.tsx", "app/components/editor/SlashCommandMenu.tsx", "app/components/editor/DocumentToolbar.tsx", ], durableEffect: null, uiImplementation: "Formatting and insertion controls mutate the local editor transaction; persistence is covered by the document save row.", status: "client-only-ephemeral", actions: [], exception: null, reliabilityRisk: "none", spinePriority: "P1", testCoverage: "none", followUpPR: null, }, { id: "editor.agent-assist-prompts", surface: "editor", label: "Ask AI from slash generation or comment context", uiEntrypoints: [ "app/components/editor/SlashCommandMenu.tsx", "app/components/editor/CommentsSidebar.tsx", ], durableEffect: "No direct durable mutation; the prompt asks the agent to use document actions when it decides to write.", uiImplementation: "Client composes context and sends it to agent chat rather than directly calling an LLM or mutating data.", status: "client-assist", actions: [], exception: null, reliabilityRisk: "none", spinePriority: "P1", testCoverage: "none", followUpPR: null, }, { id: "sharing.document-discoverability-and-export", surface: "sharing", label: "Share, hide from search, export, and reveal documents", uiEntrypoints: [ "app/components/editor/DocumentToolbar.tsx", "app/hooks/use-documents.ts", ], durableEffect: "Search discoverability, shareable copies, exports, and OS reveal requests are managed through Content actions.", uiImplementation: "Toolbar actions call sharing/export/discoverability actions; local source reveal is host-only and hidden from model tools.", status: "action-backed", actions: [ "export-document", "reveal-local-source-file", "set-document-discoverability", "share-local-file-document", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: ["actions/_local-file-documents.test.ts"], evalScenarioIds: ["local-file-source-truth"], }, { id: "sharing.os-reveal-local-source", surface: "sharing", label: "Reveal a local source file in the system file manager", uiEntrypoints: [ "app/components/editor/DocumentToolbar.tsx", "actions/reveal-local-source-file.ts", ], durableEffect: null, uiImplementation: "A trusted host opens the OS file manager for a local file path; the action is intentionally hidden from the model with agentTool: false.", status: "host-only", actions: ["reveal-local-source-file"], exception: "OS reveal depends on trusted local host capabilities and should not spend agent tool surface or imply portable hosted behavior.", reliabilityRisk: "none", spinePriority: "P2", testCoverage: "seeded", followUpPR: "Local folder exception/docs PR", }, { id: "database.lifecycle-and-trash", surface: "database", label: "Create, soft-delete, restore, list, and inspect content databases", uiEntrypoints: [ "app/components/editor/SlashCommandMenu.tsx", "app/hooks/use-content-database.ts", "app/hooks/use-documents.ts", ], durableEffect: "Database pages and database records are created, read, soft-deleted, restored, and listed.", uiImplementation: "Database creation and lifecycle controls call content database actions.", status: "action-backed", actions: [ "create-content-database", "create-inline-content-database", "delete-content-database", "get-content-database", "list-content-databases", "list-trashed-content-databases", "restore-content-database", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: ["actions/content-database-lifecycle.db.test.ts"], evalScenarioIds: ["database-source-scope"], }, { id: "database.form-submissions", surface: "database", label: "Submit public database forms as new rows", uiEntrypoints: ["app/components/editor/database/FormView.tsx"], durableEffect: "A validated form submission atomically creates a database row document and its editable property values.", uiImplementation: "The public form view calls the same submission action exposed to agents and rolls back the row if a property write fails.", status: "action-backed", actions: ["submit-content-database-form"], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: ["actions/submit-content-database-form.db.test.ts"], }, { id: "database.rows", surface: "database", label: "Add, duplicate, move, open, and delete database rows", uiEntrypoints: [ "app/components/editor/DocumentDatabase.tsx", "app/components/editor/database/DatabaseView.tsx", ], durableEffect: "Database row backing documents and row ordering are created, duplicated, moved, edited, and deleted.", uiImplementation: "Row controls call row actions; selected-row duplicate/delete call bounded batch actions, while bulk property edits remain a later reliability slice.", status: "action-backed", actions: [ "add-database-item", "delete-database-items", "delete-document", "duplicate-database-items", "duplicate-database-item", "move-database-item", "set-document-property", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: [ "actions/database-row-batch-actions.db.test.ts", "parity/__tests__/database-row-batch-reliability.test.ts", ], evalScenarioIds: ["database-bulk-row-reliability"], }, { id: "database.private-preview-drafts", surface: "database", label: "Persist and reconcile a user's private database-page preview draft", uiEntrypoints: [ "app/components/editor/database/DatabaseView.tsx", "app/hooks/use-documents.ts", ], durableEffect: "A user's private preview draft is read, saved, conflict-checked, or deleted without changing the shared database page until the normal save flow applies it.", uiImplementation: "The database preview uses the shared draft actions to preserve in-progress body edits across hydration and conflict states.", status: "action-backed", actions: ["get-preview-document-draft", "update-preview-document-draft"], exception: "These per-user editor-state actions are intentionally hidden from agent tools because preview drafts are a private UI recovery mechanism.", reliabilityRisk: "none", spinePriority: "P1", testCoverage: "covered", followUpPR: null, coverageRefs: ["actions/preview-document-draft.db.test.ts"], }, { id: "database.properties-and-view-config", surface: "database", label: "Configure properties, values, ordering, and saved views", uiEntrypoints: [ "app/components/editor/DocumentProperties.tsx", "app/components/editor/DocumentDatabase.tsx", "app/components/editor/database/DatabaseView.tsx", "app/hooks/use-document-properties.ts", ], durableEffect: "Property schemas, property values, property order, filters, sorts, grouping, hidden columns, view type, and view settings are stored.", uiImplementation: "Property popovers and database view controls call document property and view actions.", status: "action-backed", actions: [ "configure-document-property", "delete-document-property", "duplicate-document-property", "get-content-database-personal-view", "list-document-properties", "reorder-document-property", "set-document-property", "update-content-database-personal-view", "update-content-database-view", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: [ "actions/bind-content-database-source-field.db.test.ts", "actions/content-database-source-actions.test.ts", "actions/resync-content-database-source.db.test.ts", ], evalScenarioIds: ["database-source-scope"], }, { id: "source-sync.database-source-bindings", surface: "source-sync", label: "Attach, inspect, refresh, disconnect, join, and bind database sources", uiEntrypoints: [ "app/components/editor/DocumentDatabase.tsx", "app/components/editor/DocumentProperties.tsx", "app/components/editor/database/DatabaseView.tsx", "app/hooks/use-content-database.ts", ], durableEffect: "Mounted database source metadata, fields, source role, join keys, and source-field/property bindings are stored and refreshed.", uiImplementation: "Database settings and property UI call source actions through Content database hooks.", status: "action-backed", actions: [ "add-content-database-source-field-property", "attach-content-database-source", "bind-content-database-source-field", "change-content-database-source-role", "disconnect-content-database-source", "get-content-database-source", "list-builder-cms-models", "list-notion-database-sources", "refresh-content-database-source", "suggest-source-join-key", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: [ "actions/bind-content-database-source-field.db.test.ts", "actions/content-database-source-actions.test.ts", "actions/resync-content-database-source.db.test.ts", ], evalScenarioIds: ["database-source-scope"], }, { id: "source-sync.builder-cms-review-and-write-gates", surface: "source-sync", label: "Review, stage, validate, cancel, and execute Builder CMS source writes", uiEntrypoints: [ "app/components/editor/DocumentDatabase.tsx", "app/components/editor/database/DatabaseView.tsx", "app/components/editor/database-sources/BuilderSourceReviewDialog.tsx", ], durableEffect: "Builder source write mode, staged reviews, pre-dispatch cancellations, validation records, and bounded execution records are created through guarded actions.", uiImplementation: "Builder source dialogs call review, write-mode, validation, staging, and execution actions.", status: "action-backed", actions: [ "cancel-prepared-builder-source-update", "execute-builder-source-batch", "execute-builder-source-execution", "prepare-builder-source-execution", "prepare-builder-source-review", "preview-builder-source-review", "review-content-database-source-change-set", "set-content-database-source-write-mode", "stage-builder-source-bulk-update", "stage-builder-revision", "validate-builder-source-execution", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: [ "actions/builder-source-review-gates.db.test.ts", "actions/cancel-prepared-builder-source-update.db.test.ts", "actions/execute-builder-source-execution.test.ts", "actions/stage-builder-source-bulk-update.db.test.ts", ], evalScenarioIds: ["builder-source-review-readonly"], }, { id: "source-sync.builder-body-hydration-worker", surface: "source-sync", label: "Process queued Builder CMS body hydration work", uiEntrypoints: [ "app/components/editor/DocumentEditor.tsx", "app/components/editor/database/DatabaseView.tsx", "app/hooks/use-content-database.ts", ], durableEffect: "Queued Builder body hydration entries are processed into readable Content document/database body state.", uiImplementation: "Editor and database views trigger bounded queue processing through the shared action surface after source sync exposes hydration work.", status: "action-backed", actions: ["process-builder-body-hydration"], exception: "This action is intentionally hidden from the model with agentTool: false because it is an internal bounded queue worker; agents should use source refresh, review, and execution actions rather than manually driving hydration internals.", reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: ["actions/_database-source-utils.test.ts"], }, { id: "source-sync.builder-required-field-materialization", surface: "source-sync", label: "Add required Builder publishing fields to a connected collection", uiEntrypoints: [ "app/components/editor/database/DatabaseView.tsx", "app/hooks/use-content-database.ts", ], durableEffect: "Required Builder fields are materialized as editable Content properties in one local mutation.", uiImplementation: "Connected-source settings call the shared materialization action and refresh the database cache.", status: "action-backed", actions: ["materialize-builder-required-fields"], exception: "This bounded safe-model setup action is intentionally hidden from the agent tool list; the visible source settings surface invokes it.", reliabilityRisk: "none", spinePriority: "P1", testCoverage: "covered", followUpPR: null, coverageRefs: ["actions/materialize-builder-required-fields.test.ts"], }, { id: "source-sync.builder-documents", surface: "source-sync", label: "List, pull, check, and push Builder docs/blog MDX documents", uiEntrypoints: [ "actions/list-builder-docs.ts", "actions/pull-builder-doc.ts", "actions/check-builder-doc.ts", "actions/push-builder-doc.ts", ], durableEffect: "Builder docs/blog entries can be read into Content, checked locally, and pushed through guarded Builder document actions.", uiImplementation: "Currently agent/action-facing rather than a primary visible UI surface.", status: "action-backed", actions: [ "check-builder-doc", "list-builder-docs", "pull-builder-doc", "push-builder-doc", ], exception: null, reliabilityRisk: "none", spinePriority: "P1", testCoverage: "seeded", followUpPR: null, }, { id: "source-sync.provider-api-and-staged-datasets", surface: "source-sync", label: "Inspect provider APIs and stage/query/delete large provider datasets", uiEntrypoints: [ "actions/provider-api-catalog.ts", "actions/provider-api-docs.ts", "actions/provider-api-request.ts", "actions/query-staged-dataset.ts", ], durableEffect: "Provider API metadata and staged dataset scratch storage support scoped agent/source analysis.", uiImplementation: "Agent-facing provider API substrate; UI parity is capability parity rather than a visible button-by-button mapping.", status: "action-backed", actions: [ "delete-staged-dataset", "list-staged-datasets", "provider-api-catalog", "provider-api-docs", "provider-api-request", "query-staged-dataset", ], exception: null, reliabilityRisk: "none", spinePriority: "P1", testCoverage: "seeded", followUpPR: null, }, { id: "local-files.import-export-mounted-folder", surface: "local-files", label: "Import, check, export, push, and remove local folder source files", uiEntrypoints: [ "app/routes/_app.local-files.tsx", "actions/import-content-source.ts", "actions/export-content-source.ts", ], durableEffect: "Local Markdown/MDX source files are imported into Content documents, editable Content documents are exported back to source-friendly files, and imported source entries can be removed without deleting files on disk.", uiImplementation: "UI reads/writes browser or Desktop folder handles around import/export actions.", status: "action-backed", actions: [ "connect-local-folder-source", "disconnect-local-folder-source", "export-content-source", "import-content-source", "remove-local-file-source", "resolve-local-folder-conflict", "sync-local-folder-source", "sync-manifest-local-folder-source", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: [ "actions/_local-file-documents.test.ts", "actions/local-folder-source.db.test.ts", ], evalScenarioIds: ["local-file-source-truth"], }, { id: "local-files.host-folder-handles", surface: "local-files", label: "Choose, persist, remove, and write trusted local folder handles", uiEntrypoints: ["app/routes/_app.local-files.tsx"], durableEffect: "Host directory handles and browser/Desktop write permissions are managed outside SQL action state.", uiImplementation: "Browser File System Access and Desktop bridge APIs own the physical folder handles and writes.", status: "host-only", actions: [], exception: "Mounted local folders require browser/Desktop host handles that agents cannot safely or portably hold as normal tools.", reliabilityRisk: "none", spinePriority: "P0", testCoverage: "none", followUpPR: "Local folder exception/docs PR", }, { id: "local-files.components-workspace", surface: "local-files", label: "Register, list, and write local MDX component workspaces", uiEntrypoints: [ "app/routes/_app.local-files.tsx", "actions/register-local-component-workspace.ts", "actions/list-local-component-files.ts", "actions/write-local-component-file.ts", ], durableEffect: "Trusted local component workspace registration and component file reads/writes support local MDX previews.", uiImplementation: "Desktop-host workspace registration is hidden from model tools; listed/written files use Content actions once registered.", status: "host-only", actions: [ "list-local-component-files", "register-local-component-workspace", "write-local-component-file", ], exception: "Workspace registration depends on a trusted Desktop folder path and is intentionally hidden with agentTool: false.", reliabilityRisk: "none", spinePriority: "P1", testCoverage: "seeded", followUpPR: "Local folder exception/docs PR", }, { id: "notion.route-backed-document-sync", surface: "source-sync", label: "Notion document sync status, link, unlink, pull, push, resolve, create, search, and disconnect", uiEntrypoints: [ "app/hooks/use-notion.ts", "app/components/editor/DocumentToolbar.tsx", "app/components/editor/NotionSyncBar.tsx", "app/components/editor/DocumentEditor.tsx", ], durableEffect: "Notion connection state, page search, link metadata, and local/remote document body sync state are read or mutated through Content actions.", uiImplementation: "Notion document sync hooks call the shared action surface; OAuth auth-url/callback routes remain route-shaped because they depend on browser redirects.", status: "action-backed", actions: [ "connect-notion-status", "create-and-link-notion-page", "disconnect-notion", "link-notion-page", "list-notion-links", "pull-notion-page", "push-notion-page", "refresh-notion-sync-status", "resolve-notion-sync-conflict", "search-notion-pages", "sync-notion-comments", "unlink-notion-page", ], exception: "Notion OAuth auth-url and callback routes remain route-shaped because they initiate and receive browser redirects rather than normal app data mutations.", reliabilityRisk: "none", spinePriority: "P0", testCoverage: "covered", followUpPR: null, coverageRefs: ["parity/__tests__/matrix-route-gap-classify.test.ts"], routePatterns: ["/api/notion/auth-url", "/api/notion/callback"], }, { id: "comments.threads", surface: "comments", label: "List, add, reply, resolve, reopen, and delete comment threads", uiEntrypoints: [ "app/components/editor/CommentsSidebar.tsx", "app/hooks/use-comments.ts", ], durableEffect: "Comment threads, replies, anchors, mentions, resolution state, and deletion are stored through comment actions.", uiImplementation: "Comment hooks call comment actions; comment positioning is client-only editor geometry.", status: "action-backed", actions: [ "add-comment", "delete-comment", "list-comments", "update-comment", ], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "seeded", followUpPR: null, }, { id: "versions.history-and-restore", surface: "versions", label: "Open version history and restore a previous document version", uiEntrypoints: [ "app/components/editor/VersionHistoryPanel.tsx", "app/hooks/use-document-versions.ts", ], durableEffect: "Document versions are listed and selected versions can restore the document while snapshotting current state.", uiImplementation: "Version panel reads and restores through document version actions.", status: "action-backed", actions: ["list-document-versions", "restore-document-version"], exception: null, reliabilityRisk: "none", spinePriority: "P0", testCoverage: "seeded", followUpPR: null, }, ];