From 5dae0946eb2eb9b26bab42d830fe16ca7f3652c7 Mon Sep 17 00:00:00 2001 From: Dave Date: Thu, 17 Sep 2026 10:42:46 +0200 Subject: [PATCH] feat(projects): add kind field (project | prototype) --- scripts/setup-remote.ts | 46 +++++++++++++++++++++++++++++++++++++++++ src/lib/pb/types.ts | 2 ++ 2 files changed, 48 insertions(+) diff --git a/scripts/setup-remote.ts b/scripts/setup-remote.ts index 41a87ee..22fc7b8 100644 --- a/scripts/setup-remote.ts +++ b/scripts/setup-remote.ts @@ -363,6 +363,49 @@ async function ensureCardNumbers(pb: PocketBase): Promise { } } +/** + * Add the `kind` field to projects, for Phase 6's project/prototype + * distinction — a prototype is a full project (board, dashboard, same + * permissions), just tagged as not yet a committed piece of work. + * + * Backfilled to "project" for every existing row. Nothing already in + * production should read as a prototype just because the field is new. + * + * Re-runs are safe: the field is not duplicated, and backfill only touches + * rows where kind is still unset. + */ +async function ensureProjectKindField(pb: PocketBase): Promise { + const projects = await pb.collections.getOne("projects"); + const have = new Set(projects.fields.map((f: { name: string }) => f.name)); + + if (!have.has("kind")) { + const fields = [...(projects.fields as unknown[])]; + fields.push({ + name: "kind", + type: "select", + required: false, + maxSelect: 1, + values: ["project", "prototype"], + presentable: false, + hidden: false, + system: false, + }); + await pb.collections.update(projects.id, { fields }); + console.log(" + projects field: kind"); + } else { + console.log(" = projects.kind already present"); + } + + const unset = await pb.collection("projects").getFullList({ + filter: 'kind = ""', + fields: "id", + }); + for (const project of unset) { + await pb.collection("projects").update(project.id, { kind: "project" }); + } + console.log(` = project kind backfilled (${unset.length} row(s))`); +} + async function main(): Promise { const pb = new PocketBase(PB_URL); await authAdmin(pb); @@ -897,6 +940,9 @@ async function main(): Promise { // collection already exists from earlier migrations). await ensureProjectIngestFields(pb); + // Add the project/prototype kind field for Phase 6. + await ensureProjectKindField(pb); + // Add the per-commit summary fields used by Phase 3b's AI one-liner job. await ensureCommitSummaryFields(pb); diff --git a/src/lib/pb/types.ts b/src/lib/pb/types.ts index 19d8384..b49d09b 100644 --- a/src/lib/pb/types.ts +++ b/src/lib/pb/types.ts @@ -3,6 +3,7 @@ export type Role = "owner" | "client_manager"; export type Priority = "critical" | "high" | "medium" | "low"; export type ProjectStatus = "active" | "paused" | "completed" | "archived"; +export type ProjectKind = "project" | "prototype"; export type CreatedByRole = "owner" | "client"; export type ActivityAction = @@ -45,6 +46,7 @@ export interface ProjectRecord extends BaseRecord { slug: string; description: string; status: ProjectStatus; + kind: ProjectKind; color: string; repo_owner: string; repo_name: string;