mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-06 16:34:36 +00:00
fix(projects): restore project key as grouping identity
Random host-local project IDs had replaced the persisted cross-host value carried by projectKey. Keep projectId for routing while reconciliation owns and persists projectKey for grouping.
This commit is contained in:
+13
-13
@@ -4,13 +4,13 @@
|
||||
|
||||
Projects are allocated for the exact root selected by the caller, normalized lexically with `path.resolve` (never `realpath`). New project IDs are opaque `prj_<16 hex>` values. Existing remote-shaped or path-shaped IDs are retained as readable compatibility records and are never rekeyed. An active exact root is idempotent; archived-only matches do not resurrect an old project. Workspace `projectId` is stable membership: reconciliation may update git-derived kind and branch metadata, but never rehomes a workspace or changes a project's root, ID, or default name.
|
||||
|
||||
`projectGroupKey` is a persisted, opaque equivalence key used only to group the same logical project
|
||||
`projectKey` is a persisted, opaque equivalence key used only to group the same logical project
|
||||
across hosts. It is separate from the host-local `projectId`; today's producer prefers a normalized
|
||||
Git remote and otherwise uses the local project root. Consumers never derive it from live Git.
|
||||
Creation persists it with the project, and normal boot reconciliation fills or refreshes it for
|
||||
older records where the field is absent—there is no migration.
|
||||
|
||||
`kind` and `projectGroupKey` are mutable metadata, not identity. Workspace reconciliation watches active project roots and
|
||||
`kind` and `projectKey` are mutable metadata, not identity. Workspace reconciliation watches active project roots and
|
||||
updates those fields and `updatedAt` when Git facts change, preserving the project's ID, root path,
|
||||
names, and workspace foreign keys. Attached workspaces are independently refreshed
|
||||
from their own cwd, so an explicit project root never implies a workspace checkout. Empty projects
|
||||
@@ -454,17 +454,17 @@ Single file containing an array of all loop records. Writes are direct (not atom
|
||||
|
||||
Array of project records.
|
||||
|
||||
| Field | Type | Description |
|
||||
| ----------------- | --------------------------- | -------------------------------------------------------------------------------- |
|
||||
| `projectId` | `string` | Host-local primary key; new records use opaque `prj_<16 hex>` IDs |
|
||||
| `projectGroupKey` | `string \| null` | Persisted opaque cross-host grouping key; reconciliation backfills absent values |
|
||||
| `rootPath` | `string` | Exact lexically normalized selected root; never realpathed |
|
||||
| `kind` | `"git" \| "non_git"` | Mutable Git observation about `rootPath`, never a membership key |
|
||||
| `displayName` | `string` | Selected-root basename, stable across remote and Git changes |
|
||||
| `customName` | `string \| null` | User-set override layered over `displayName`. Null means "use the derived name". |
|
||||
| `createdAt` | `string` (ISO 8601) | |
|
||||
| `updatedAt` | `string` (ISO 8601) | |
|
||||
| `archivedAt` | `string \| null` (ISO 8601) | Soft-delete timestamp; required nullable |
|
||||
| Field | Type | Description |
|
||||
| ------------- | --------------------------- | -------------------------------------------------------------------------------- |
|
||||
| `projectId` | `string` | Host-local primary key; new records use opaque `prj_<16 hex>` IDs |
|
||||
| `projectKey` | `string \| null` | Persisted opaque cross-host grouping key; reconciliation backfills absent values |
|
||||
| `rootPath` | `string` | Exact lexically normalized selected root; never realpathed |
|
||||
| `kind` | `"git" \| "non_git"` | Mutable Git observation about `rootPath`, never a membership key |
|
||||
| `displayName` | `string` | Selected-root basename, stable across remote and Git changes |
|
||||
| `customName` | `string \| null` | User-set override layered over `displayName`. Null means "use the derived name". |
|
||||
| `createdAt` | `string` (ISO 8601) | |
|
||||
| `updatedAt` | `string` (ISO 8601) | |
|
||||
| `archivedAt` | `string \| null` (ISO 8601) | Soft-delete timestamp; required nullable |
|
||||
|
||||
Active exact roots are idempotent using lexical platform-equivalence semantics. Existing legacy
|
||||
remote-shaped and path-shaped IDs remain readable, including duplicate roots; reconciliation never
|
||||
|
||||
+1
-2
@@ -2,8 +2,7 @@
|
||||
|
||||
Authoritative terminology. UI label wins. Don't invent synonyms; use what's here.
|
||||
|
||||
- **Project** — A stable, exact selected-root record. Its host-local `projectId` is an opaque `prj_<16 hex>` value. Its separate persisted `projectGroupKey` is an opaque equivalence key that may group the logical project across hosts. Git facts can update mutable kind and grouping metadata but never the ID, root, or default display name. UI: "Project" / "Add project". Forbidden: "Repo", "Repository" as UI label.
|
||||
- **Project group key** — Persisted opaque equivalence key used to group projects across hosts. A normalized Git remote is the current producer, but the concept is wider than repository identity and consumers must not parse or rederive it. Code: `projectGroupKey`.
|
||||
- **Project** — A stable, exact selected-root record. Its host-local `projectId` is an opaque `prj_<16 hex>` value. Its persisted `projectKey` is an opaque equivalence key that may group the logical project across hosts. A normalized Git remote is the current key producer, but consumers must not parse or rederive it. Git facts can update mutable kind and grouping metadata but never the ID, root, or default display name. UI: "Project" / "Add project". Forbidden: "Repo", "Repository" as UI label.
|
||||
- **Workspace** — One concrete `cwd` on one daemon, with git state; belongs to exactly one project. Its `id` is opaque workspace identity; its `cwd` is the filesystem directory. UI: "Workspace". Code: `WorkspaceDescriptorPayload` (`packages/protocol/src/messages.ts:2178`). Don't confuse with: Branch (one branch can back many workspaces via worktrees). Forbidden: "Folder", "Directory" as UI label.
|
||||
- **Archive workspace** — Removes one workspace from active use and archives everything it owns. UI, CLI, and MCP always say "Archive workspace", regardless of backing. The daemon leaves ordinary directories intact and removes a Paseo-owned worktree only when no active workspace still references it.
|
||||
- **Workspace kind** — `"directory" | "local_checkout" | "worktree"`. The git-derived, persisted property of a workspace, used across its lifetime (archive safety, sidebar, grouping). Derived from the cwd's git reality by `deriveWorkspaceKind` in `workspace-registry-model.ts`, not stored from a user choice. Don't confuse with **Isolation** (the create-time intent).
|
||||
|
||||
Reference in New Issue
Block a user