You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: apps/penpal/ERD.md
+11-8Lines changed: 11 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,8 +82,8 @@ see-also:
82
82
- <aid="E-PENPAL-SRC-CLAUDE-PLANS"></a>**E-PENPAL-SRC-CLAUDE-PLANS**: The `claude-plans` source type classifies all files as `plan`. No custom grouping. Injected via `DiscoverClaudePlans()` which creates a synthetic standalone project or injects a tree source into an existing manually-added project.
- <aid="E-PENPAL-SRC-MANUAL"></a>**E-PENPAL-SRC-MANUAL**: The `manual` source type is used for user-added sources (via `penpal open`CLI or the add-workspace/project modal). Directory sources create "tree" type entries; individual file sources create "files" type entries. `GroupFiles()` generates directory headings (`Dir`, `ShowDir` fields on `FileInfo`) for subdirectory boundaries. Configuration is persisted in `config.json` under `ProjectSources` (workspace projects) or inline with the `ProjectConfig` entry (standalone projects).
- <aid="E-PENPAL-SRC-MANUAL"></a>**E-PENPAL-SRC-MANUAL**: The `manual` source type is used for explicit user-added paths, including CLI/opened paths and persisted favorites. Directory sources create `tree`entries; individual file sources create `files`entries. `GroupFiles()` generates directory headings (`Dir`, `ShowDir` fields on `FileInfo`) for subdirectory boundaries. Configuration is persisted in `config.json` under `ProjectSources` (workspace projects) or inline with the `ProjectConfig` entry (standalone projects). When building the regular project source list, manual groups are filtered out so they can be surfaced separately through Favorites.
- <aid="E-PENPAL-SRC-ALL-MD"></a>**E-PENPAL-SRC-ALL-MD**: An "All Markdown" source is always present in every project. Registered as a `SourceType` with `GroupFiles` returning a single "All Markdown" group, `ShowDirHeadings: true`, and `SkipDirs` for `node_modules`, `.hg`, `.svn`. Always appended by `DetectSources()` after the detection loop — not conditionally detected. The `Auto` field is `true` — the frontend uses this to prevent removal. During scanning, `__all_markdown__` bypasses the per-source dedup (`seen` map) so it claims every `.md` file regardless of other sources. `AllFiles()` deduplicates by project+path, preferring typed-source entries over `__all_markdown__`, so the recent-files list and activity seeding see each file exactly once. The `handleAddSource` conflict check skips `__all_markdown__` so it doesn't block manual file additions.
- <aid="E-PENPAL-WORKTREE-DROPDOWN"></a>**E-PENPAL-WORKTREE-DROPDOWN**: Rendered in `Layout.tsx` as a full-width `.worktree-selector-row` below the breadcrumb bar (outside the `.breadcrumb-bar` container) with `worktreeDropdownRef` for click-outside dismiss (via `mousedown` document listener). The `::after` pseudo-element renders a `▾` indicator. The `.worktree-dropdown-menu` is absolutely positioned. Each worktree button shows `active` class for the current selection; selecting a worktree navigates to `/project/{qn}@{worktreeName}`. Single-worktree projects render a static `.worktree-selector-row.deemphasized` div with "no worktrees" text (no ref, no click handler). State: `showWorktreeDropdown` boolean, toggled on click.
- <aid="E-PENPAL-SOURCE-SECTIONS"></a>**E-PENPAL-SOURCE-SECTIONS**: The project sidebar shows collapsible source sections populated from `projectFiles` state (via `api.getProjectFiles()`), a collapsible "In Review" section (from `projectReviews` via `api.getReviews()`), and a collapsible "Recent" section. Each source header shows its badge and file count. Virtual sources with zero files show alternate labels ("No Markdown Found", "Nothing in Review", "Nothing Recent") with `deemphasized` class and are not expandable. State: `expandedSources``Set<string>`. SSE `files` and `comments` events refresh the data.
- <aid="E-PENPAL-SOURCE-SECTIONS"></a>**E-PENPAL-SOURCE-SECTIONS**: The project sidebar shows a collapsible Favorites section populated from `favorites` state (via `api.getFavorites()`), collapsible detected-source sections populated from `projectFiles` state (via `api.getProjectFiles()`), a collapsible "In Review" section (from `projectReviews` via `api.getReviews()`), and a collapsible "Recent" section. Each header shows its count. Empty sections render alternate labels ("No Favorites", "No Markdown Found", "Nothing in Review", "Nothing Recent") with `deemphasized` class and are not expandable. State: `expandedSources``Set<string>`. When favorites load as non-empty for a project/worktree, the frontend auto-expands the Favorites section once for that view. SSE `files` and `comments` events refresh the data.
- <aid="E-PENPAL-FAVORITES"></a>**E-PENPAL-FAVORITES**: `GET /api/favorites` returns `APIFavoriteEntry[]` for the active project/worktree by projecting persisted manual source config into either `kind: "file"` or `kind: "tree"` entries. `POST /api/favorites` validates a project-relative path; directories are stored as manual `tree` sources and markdown files as manual `files` sources. `DELETE /api/favorites` removes the matching manual source entry. Favorite tree population prefers richer metadata from non-manual entries (typed sources or `__all_markdown__`) when the same file is known through multiple sources, but falls back to any known markdown file under the subtree so populated favorites do not depend on an All Markdown row being visible.
- <aid="E-PENPAL-FE-SRC-DISAMBIG"></a>**E-PENPAL-FE-SRC-DISAMBIG**: When rendering source sections in the sidebar, the frontend computes which `badgeText` values appear on more than one group. For groups with duplicated badges, the group `name` (module path) is rendered as a `<span class="source-disambig">` to the right of the badge with `text-overflow: ellipsis`, deemphasized color (`var(--text-disabled)`), and a `title` attribute showing the full path. Groups with unique badges show no disambiguation text.
- <aid="E-PENPAL-PROJECT-WELCOME"></a>**E-PENPAL-PROJECT-WELCOME**: `ProjectPage.tsx` is a simple welcome screen. Extracts the project name from the URL path via `parseProjectWorktree()` and shows the project name with a hint to expand a source in the sidebar. Data-testid `project-page`.
- <aid="E-PENPAL-SOURCE-ACTIONS"></a>**E-PENPAL-SOURCE-ACTIONS**: Source section headers in the sidebar support right-click context menus with: "Copy relative paths" (joins `@` + path with newlines), "Copy absolute paths", "Publish" (parallel `api.publish()` calls), "Remove from Penpal" (only for non-auto sources; `group.auto` controls visibility), and "Delete from disk". No "(auto)" badge is displayed. File tree items support right-click with: "Copy markdown", "Copy relative path", "Copy absolute path", "Add to Favorites"/"Remove from Favorites", "Publish", "Remove from Penpal" (files source only), and "Delete from disk". Directory tree items support right-click with: "Copy relative path", "Copy absolute path", and "Add to Favorites"/"Remove from Favorites". No inline star affordance is rendered.
- <aid="E-PENPAL-BATCH-OPS"></a>**E-PENPAL-BATCH-OPS**: `Layout.tsx` maintains a `Set<string>` selection state for the project sidebar. Shift-click on a file extends the selection from the last-clicked file to the shift-clicked file within the same source group. A floating selection bar at the bottom of the sidebar appears when `selected.size > 0` with actions: "Copy markdown" (`Promise.all` of `api.getRawFile()` joined with `\n\n---\n\n`), "Copy paths" (joins `@` + path), "Publish" (parallel), "Delete" (triggers delete confirmation modal), and "Clear".
- <aid="E-PENPAL-CONTEXT-MENU"></a>**E-PENPAL-CONTEXT-MENU**: A shared `ContextMenu` component renders an absolutely-positioned menu at mouse coordinates on `contextmenu` events. Items are `{ label, className?, onClick }`. The menu auto-dismisses on click-outside or item selection. Used for workspace items (remove), standalone projects (close), source headers (copy/publish/remove/delete), and file items (copy/publish/remove/delete).
- <aid="E-PENPAL-CONTEXT-MENU"></a>**E-PENPAL-CONTEXT-MENU**: A shared `ContextMenu` component renders an absolutely-positioned menu at mouse coordinates on `contextmenu` events. Items are `{ label, className?, onClick }`. The menu auto-dismisses on click-outside or item selection. Used for workspace items (remove), standalone projects (close), source headers (copy/publish/remove/delete), file items (copy/favorite/publish/remove/delete), and directory items (copy/favorite).
- <aid="E-PENPAL-NO-SELECT-CHROME"></a>**E-PENPAL-NO-SELECT-CHROME**: CSS `user-select: none` is applied to all application chrome: `.sidebar`, `.tab-bar`, `.topbar`, `.breadcrumb-bar`, and context menus. Only `.main-content` (the markdown viewer area) allows text selection.
Copy file name to clipboardExpand all lines: apps/penpal/PRODUCT.md
+6-2Lines changed: 6 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -148,7 +148,9 @@ The project view shows the contents of a single project in the sidebar, organize
148
148
149
149
- <aid="P-PENPAL-PROJECT-WORKTREE-DROPDOWN"></a>**P-PENPAL-PROJECT-WORKTREE-DROPDOWN**: When a project has multiple worktrees, a worktree selector row spans the full width of the sidebar below the breadcrumb bar. It shows the current worktree: "main repo" when viewing the main worktree, or the worktree icon and worktree name when viewing a non-main worktree. Content is left-aligned. Clicking the selector shows all available worktrees; each item shows its name with a worktree icon (non-main only), matching the home tree format. Selecting a worktree switches to that worktree's view. For single-worktree projects (no additional worktrees), the row shows dimmed static text "no worktrees" (no dropdown).
150
150
151
-
- <aid="P-PENPAL-PROJECT-SOURCES"></a>**P-PENPAL-PROJECT-SOURCES**: The project sidebar shows each detected source type as a collapsible top-level section with its badge and file count. Sources appear in this order: typed sources (RPI, RP1, ANCHORS), then All Markdown, then In Review, then Recent. Each source expands to show its files in a tree view. Virtual sources with no files are shown with an alternate label and dimmed styling: "All Markdown" becomes "No Markdown Found", "In Review" becomes "Nothing in Review", "Recent" becomes "Nothing Recent". These empty virtual sources are not expandable.
151
+
- <aid="P-PENPAL-PROJECT-SOURCES"></a>**P-PENPAL-PROJECT-SOURCES**: The project sidebar shows top-level collapsible sections with counts. Sections appear in this order: Favorites, typed sources (RPI, RP1, ANCHORS), All Markdown, In Review, then Recent. Each expandable section shows its files in a tree view. Empty sections are shown with alternate dimmed labels: "Favorites" becomes "No Favorites", "All Markdown" becomes "No Markdown Found", "In Review" becomes "Nothing in Review", and "Recent" becomes "Nothing Recent". Empty sections are not expandable.
152
+
153
+
- <aid="P-PENPAL-FAVORITES"></a>**P-PENPAL-FAVORITES**: Each project view includes a collapsible Favorites section above detected sources. Favorites are user-curated rather than auto-detected. A favorite can target either a single markdown file or a directory. File favorites render as normal file rows. Directory favorites render as collapsible directory rows with a nested tree of markdown files under that subtree, using paths relative to the favorite root. The Favorites header count reflects the number of favorite entries; a directory favorite row also shows the number of files contained within that favorite.
152
154
153
155
- <aid="P-PENPAL-PROJECT-FILE-TREE"></a>**P-PENPAL-PROJECT-FILE-TREE**: Within each source section, files are organized in a tree view that mirrors the directory structure. Directories are collapsible. Single-child directory chains are compacted into one tree item with a combined path (e.g., `a/b/c/` instead of three nested levels), similar to IntelliJ's "compact middle packages" behavior. Files show their name (or H1 heading when available), type badge, and an "in review" badge when they have open threads.
154
156
@@ -192,7 +194,9 @@ Global views aggregate content across all projects. They appear as top-level ite
192
194
193
195
- <aid="P-PENPAL-FILE-TYPES"></a>**P-PENPAL-FILE-TYPES**: Files are classified by type (research, plan, knowledge, prd, design, task, etc.) based on their path within a source. Type badges appear next to the filename in the sidebar tree and file viewer.
194
196
195
-
- <aid="P-PENPAL-FILE-ACTIONS"></a>**P-PENPAL-FILE-ACTIONS**: Each file has a right-click context menu (in the sidebar tree or file viewer toolbar) with: copy markdown, copy relative path (with `@` prefix), copy absolute path, publish to Blockcell, remove from Penpal, and delete from disk. In the file viewer toolbar, "copy file" places the file on the clipboard as a file reference, so pasting in Finder or other apps inserts the file itself (macOS only).
197
+
- <aid="P-PENPAL-FILE-ACTIONS"></a>**P-PENPAL-FILE-ACTIONS**: Each file has a right-click context menu (in the sidebar tree or file viewer toolbar) with: copy markdown, copy relative path (with `@` prefix), copy absolute path, add to Favorites or remove from Favorites, publish to Blockcell, remove from Penpal when the row comes from an explicit file source, and delete from disk. In the file viewer toolbar, "copy file" places the file on the clipboard as a file reference, so pasting in Finder or other apps inserts the file itself (macOS only).
198
+
199
+
- <aid="P-PENPAL-FAVORITE-ACTIONS"></a>**P-PENPAL-FAVORITE-ACTIONS**: Add to Favorites / Remove from Favorites is available from right-click context menus on file rows across the project sidebar, including detected sources, the Favorites section itself, and the project In Review section. Directory rows in project trees also expose add/remove favorites from their context menu. No inline star buttons are shown next to file or directory rows.
196
200
197
201
- <aid="P-PENPAL-SOURCE-ACTIONS"></a>**P-PENPAL-SOURCE-ACTIONS**: Each source section header in the sidebar has a right-click context menu with: copy relative paths, copy absolute paths, publish all files, remove source from Penpal (non-auto sources only), and delete from disk.
0 commit comments