Files
projectbrain-Public/backend/prisma/seed.ts
T

829 lines
30 KiB
TypeScript

import {
ApprovalState,
EvidenceStrength,
FeatureLifecycle,
FeatureStatus,
ReviewStatus,
PrismaClient,
VerificationState,
type Prisma,
} from "@prisma/client";
import {
findProject,
getWorkspaceRead,
} from "../src/fixtures/projectFixtures.js";
import { contextPackFixtures } from "../src/fixtures/contextPackFixtures.js";
import { knowledgeFixtures } from "../src/fixtures/knowledgeFixtures.js";
import { memoryRuleFixtures } from "../src/fixtures/memoryRuleFixtures.js";
import { captureFixtures } from "../src/fixtures/captureFixtures.js";
import { reviewQueueFixtures } from "../src/fixtures/reviewQueueFixtures.js";
import {
evidenceFixtures,
featureFixtures,
featureGroupFixtures,
} from "../src/fixtures/featureFixtures.js";
const prisma = new PrismaClient();
const widefrog = findProject("widefrog");
const toJson = (value: unknown): Prisma.InputJsonValue =>
JSON.parse(JSON.stringify(value)) as Prisma.InputJsonValue;
const main = async () => {
if (!widefrog) {
throw new Error("WideFrog fixture is missing; cannot seed P2 database.");
}
const project = await prisma.project.upsert({
where: { slug: widefrog.id },
create: {
slug: widefrog.id,
readableId: widefrog.id,
name: widefrog.name,
description: widefrog.description,
domain: widefrog.domain,
status: widefrog.status,
health: widefrog.health,
healthStatus: widefrog.healthStatus,
activeContextPackId: widefrog.activeContextPackId,
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
createdAt: new Date(widefrog.createdAt),
},
update: {
readableId: widefrog.id,
name: widefrog.name,
description: widefrog.description,
domain: widefrog.domain,
status: widefrog.status,
health: widefrog.health,
healthStatus: widefrog.healthStatus,
activeContextPackId: widefrog.activeContextPackId,
updatedBy: "seed",
sourceType: "fixture_seed",
deletedAt: null,
archivedAt: null,
},
});
await prisma.projectDNA.upsert({
where: { projectId: project.id },
create: {
projectId: project.id,
vision: widefrog.dna.vision,
goalsJson: toJson(widefrog.dna.goals),
nonGoalsJson: toJson(widefrog.dna.nonGoals),
targetAudience: widefrog.dna.targetAudience,
principlesJson: toJson(widefrog.dna.principles),
metricsJson: toJson(widefrog.dna.successMetrics),
maturityStage: widefrog.dna.maturityStage,
revision: widefrog.dna.revision,
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
},
update: {
vision: widefrog.dna.vision,
goalsJson: toJson(widefrog.dna.goals),
nonGoalsJson: toJson(widefrog.dna.nonGoals),
targetAudience: widefrog.dna.targetAudience,
principlesJson: toJson(widefrog.dna.principles),
metricsJson: toJson(widefrog.dna.successMetrics),
maturityStage: widefrog.dna.maturityStage,
revision: widefrog.dna.revision,
updatedBy: "seed",
sourceType: "fixture_seed",
},
});
const workspaceRead = getWorkspaceRead(widefrog);
const workspaceState = widefrog.workspaceState;
if (workspaceState) {
await prisma.workspaceState.upsert({
where: { projectId: project.id },
create: {
projectId: project.id,
activeContextPackId: workspaceState.activeContextPackId,
primaryObjective: workspaceState.primaryObjective,
activeSection: workspaceState.activeSection,
notesJson: toJson({
workspaceState,
focusAreas: workspaceRead.focusAreas,
activeFocusAreaId: workspaceRead.activeFocusAreaId,
currentStateSummary: workspaceRead.currentStateSummary,
healthSummary: workspaceRead.healthSummary,
}),
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
},
update: {
activeContextPackId: workspaceState.activeContextPackId,
primaryObjective: workspaceState.primaryObjective,
activeSection: workspaceState.activeSection,
notesJson: toJson({
workspaceState,
focusAreas: workspaceRead.focusAreas,
activeFocusAreaId: workspaceRead.activeFocusAreaId,
currentStateSummary: workspaceRead.currentStateSummary,
healthSummary: workspaceRead.healthSummary,
}),
updatedBy: "seed",
sourceType: "fixture_seed",
},
});
}
const seededProjects = new Map([[widefrog.id, project.id]]);
for (const group of featureGroupFixtures.filter((item) => seededProjects.has(item.projectId))) {
const projectId = seededProjects.get(group.projectId)!;
await prisma.featureGroup.upsert({
where: {
projectId_slug: {
projectId,
slug: group.id,
},
},
create: {
projectId,
slug: group.id,
readableId: group.id,
name: group.name,
description: group.description,
focusArea: group.focusArea,
},
update: {
readableId: group.id,
name: group.name,
description: group.description,
focusArea: group.focusArea,
deletedAt: null,
archivedAt: null,
},
});
}
const mapFeatureStatus = (status: string): FeatureStatus => {
if (status === "Done") return FeatureStatus.done;
if (status === "In Progress") return FeatureStatus.in_progress;
return FeatureStatus.todo;
};
const mapFeatureLifecycle = (feature: { lifecycle?: string; status: string }): FeatureLifecycle => {
if (feature.lifecycle && feature.lifecycle in FeatureLifecycle) {
return FeatureLifecycle[feature.lifecycle as keyof typeof FeatureLifecycle];
}
if (feature.status === "Done") return FeatureLifecycle.verified;
if (feature.status === "In Progress") return FeatureLifecycle.active;
return FeatureLifecycle.planned;
};
const mapVerificationState = (status: string): VerificationState => {
if (status === "Done") return VerificationState.verified;
if (status === "In Progress") return VerificationState.needs_evidence;
return VerificationState.unverified;
};
const mapEvidenceStrength = (confidence: number): EvidenceStrength => {
if (confidence >= 95) return EvidenceStrength.verified;
if (confidence >= 85) return EvidenceStrength.strong;
if (confidence >= 70) return EvidenceStrength.medium;
return EvidenceStrength.weak;
};
const mapApprovalState = (approvalState: string): ApprovalState => {
if (approvalState === "approved") return ApprovalState.approved;
if (approvalState === "rejected") return ApprovalState.rejected;
if (approvalState === "blocked") return ApprovalState.blocked;
return ApprovalState.pending;
};
const mapFixtureEvidenceStrength = (strength: string | undefined, confidence: number): EvidenceStrength => {
if (strength && strength in EvidenceStrength) {
return EvidenceStrength[strength as keyof typeof EvidenceStrength];
}
return mapEvidenceStrength(confidence);
};
for (const feature of featureFixtures.filter((item) => seededProjects.has(item.projectId))) {
const projectId = seededProjects.get(feature.projectId)!;
const group = await prisma.featureGroup.findFirst({
where: {
projectId,
slug: feature.groupId,
deletedAt: null,
},
});
if (!group) {
throw new Error(`Feature group '${feature.groupId}' is missing for feature '${feature.id}'.`);
}
await prisma.feature.upsert({
where: {
projectId_slug: {
projectId,
slug: feature.id,
},
},
create: {
projectId,
featureGroupId: group.id,
slug: feature.id,
readableId: feature.id,
name: feature.name,
description: feature.description,
status: mapFeatureStatus(feature.status),
lifecycle: mapFeatureLifecycle(feature),
intent: feature.intent,
confidence: feature.confidence,
health: feature.health,
approvalState: feature.status === "Done" ? ApprovalState.approved : ApprovalState.pending,
evidenceStrength: mapFixtureEvidenceStrength(feature.evidenceStrength, feature.confidence),
verificationState: mapVerificationState(feature.status),
trustJson: toJson({
bugCount: feature.bugCount,
taskCount: feature.taskCount,
decisionCount: feature.decisionCount,
codeEvidence: feature.codeEvidence,
aiSuggestionCount: feature.aiSuggestionCount,
evidenceIds: feature.evidenceIds,
initiativeId: feature.initiativeId,
}),
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/featureFixtures.ts",
fixtureId: feature.id,
}),
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
},
update: {
featureGroupId: group.id,
readableId: feature.id,
name: feature.name,
description: feature.description,
status: mapFeatureStatus(feature.status),
lifecycle: mapFeatureLifecycle(feature),
intent: feature.intent,
confidence: feature.confidence,
health: feature.health,
approvalState: feature.status === "Done" ? ApprovalState.approved : ApprovalState.pending,
evidenceStrength: mapFixtureEvidenceStrength(feature.evidenceStrength, feature.confidence),
verificationState: mapVerificationState(feature.status),
trustJson: toJson({
bugCount: feature.bugCount,
taskCount: feature.taskCount,
decisionCount: feature.decisionCount,
codeEvidence: feature.codeEvidence,
aiSuggestionCount: feature.aiSuggestionCount,
evidenceIds: feature.evidenceIds,
initiativeId: feature.initiativeId,
}),
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/featureFixtures.ts",
fixtureId: feature.id,
}),
updatedBy: "seed",
sourceType: "fixture_seed",
deletedAt: null,
archivedAt: null,
},
});
}
for (const evidence of evidenceFixtures.filter((item) => seededProjects.has(item.projectId))) {
const projectId = seededProjects.get(evidence.projectId)!;
await prisma.evidence.upsert({
where: {
projectId_slug: {
projectId,
slug: evidence.id,
},
},
create: {
projectId,
slug: evidence.id,
readableId: evidence.id,
type: evidence.type,
source: evidence.source,
confidence: evidence.confidence,
approvalState: mapApprovalState(evidence.approvalState),
evidenceStrength: mapEvidenceStrength(evidence.confidence),
verificationState: evidence.approvalState === "approved" ? VerificationState.verified : VerificationState.unverified,
reason: evidence.reason,
metadataJson: toJson({
linkedEntity: evidence.linkedEntity,
featureIds: evidence.featureIds,
route: evidence.route,
}),
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/featureFixtures.ts",
fixtureId: evidence.id,
}),
lastSeen: new Date(evidence.lastSeen),
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
},
update: {
readableId: evidence.id,
type: evidence.type,
source: evidence.source,
confidence: evidence.confidence,
approvalState: mapApprovalState(evidence.approvalState),
evidenceStrength: mapEvidenceStrength(evidence.confidence),
verificationState: evidence.approvalState === "approved" ? VerificationState.verified : VerificationState.unverified,
reason: evidence.reason,
metadataJson: toJson({
linkedEntity: evidence.linkedEntity,
featureIds: evidence.featureIds,
route: evidence.route,
}),
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/featureFixtures.ts",
fixtureId: evidence.id,
}),
lastSeen: new Date(evidence.lastSeen),
updatedBy: "seed",
sourceType: "fixture_seed",
deletedAt: null,
archivedAt: null,
},
});
}
for (const contextPack of contextPackFixtures.filter((item) => seededProjects.has(item.projectId))) {
const projectId = seededProjects.get(contextPack.projectId)!;
await prisma.contextPack.upsert({
where: {
projectId_slug: {
projectId,
slug: contextPack.id,
},
},
create: {
projectId,
slug: contextPack.id,
readableId: contextPack.id,
title: contextPack.title,
category: contextPack.category,
summary: contextPack.summary,
generatedBy: contextPack.generatedBy,
confidence: contextPack.trust.confidence,
approvalState: mapApprovalState(contextPack.trust.approvalState),
qualityJson: toJson(contextPack.quality ?? {}),
trustJson: toJson(contextPack.trust),
metadataJson: toJson({
dna: contextPack.dna,
assumptions: contextPack.assumptions,
constraints: contextPack.constraints,
evidence: contextPack.evidence,
signals: contextPack.signals,
featureIds: contextPack.featureIds,
bugIds: contextPack.bugIds,
taskIds: contextPack.taskIds,
decisionIds: contextPack.decisionIds,
memoryRuleIds: contextPack.memoryRuleIds,
architectureNotes: contextPack.architectureNotes,
regressions: contextPack.regressions,
risks: contextPack.risks,
currentFocus: contextPack.currentFocus,
}),
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/contextPackFixtures.ts",
fixtureId: contextPack.id,
}),
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
createdAt: new Date(contextPack.createdAt),
sections: {
create: [
{
projectId,
slug: "dna",
title: "Project DNA",
sectionType: "dna",
orderIndex: 1,
contentJson: toJson(contextPack.dna),
},
{
projectId,
slug: "features",
title: "Relevant features",
sectionType: "features",
orderIndex: 2,
contentJson: toJson(contextPack.featureIds ?? []),
},
{
projectId,
slug: "evidence",
title: "Evidence references",
sectionType: "evidence",
orderIndex: 3,
contentJson: toJson(contextPack.evidence),
},
{
projectId,
slug: "risks",
title: "Risks",
sectionType: "risks",
orderIndex: 4,
contentJson: toJson(contextPack.risks ?? []),
},
],
},
},
update: {
readableId: contextPack.id,
title: contextPack.title,
category: contextPack.category,
summary: contextPack.summary,
generatedBy: contextPack.generatedBy,
confidence: contextPack.trust.confidence,
approvalState: mapApprovalState(contextPack.trust.approvalState),
qualityJson: toJson(contextPack.quality ?? {}),
trustJson: toJson(contextPack.trust),
metadataJson: toJson({
dna: contextPack.dna,
assumptions: contextPack.assumptions,
constraints: contextPack.constraints,
evidence: contextPack.evidence,
signals: contextPack.signals,
featureIds: contextPack.featureIds,
bugIds: contextPack.bugIds,
taskIds: contextPack.taskIds,
decisionIds: contextPack.decisionIds,
memoryRuleIds: contextPack.memoryRuleIds,
architectureNotes: contextPack.architectureNotes,
regressions: contextPack.regressions,
risks: contextPack.risks,
currentFocus: contextPack.currentFocus,
}),
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/contextPackFixtures.ts",
fixtureId: contextPack.id,
}),
updatedBy: "seed",
sourceType: "fixture_seed",
deletedAt: null,
archivedAt: null,
},
});
const seededContextPack = await prisma.contextPack.findFirstOrThrow({
where: { projectId, slug: contextPack.id },
});
await prisma.contextPackSection.deleteMany({ where: { contextPackId: seededContextPack.id } });
await prisma.contextPackSection.createMany({
data: [
{
projectId,
contextPackId: seededContextPack.id,
slug: "dna",
title: "Project DNA",
sectionType: "dna",
orderIndex: 1,
contentJson: toJson(contextPack.dna),
},
{
projectId,
contextPackId: seededContextPack.id,
slug: "features",
title: "Relevant features",
sectionType: "features",
orderIndex: 2,
contentJson: toJson(contextPack.featureIds ?? []),
},
{
projectId,
contextPackId: seededContextPack.id,
slug: "evidence",
title: "Evidence references",
sectionType: "evidence",
orderIndex: 3,
contentJson: toJson(contextPack.evidence),
},
{
projectId,
contextPackId: seededContextPack.id,
slug: "risks",
title: "Risks",
sectionType: "risks",
orderIndex: 4,
contentJson: toJson(contextPack.risks ?? []),
},
],
});
}
for (const capture of captureFixtures.filter((item) => seededProjects.has(item.projectId))) {
const projectId = seededProjects.get(capture.projectId)!;
await prisma.captureItem.upsert({
where: {
projectId_slug: {
projectId,
slug: capture.id,
},
},
create: {
projectId,
slug: capture.id,
readableId: capture.id,
type: capture.type,
title: capture.title,
content: capture.content,
source: capture.source,
status: capture.status,
classificationType: capture.classificationType,
confidence: capture.confidence,
evidenceStrength: capture.evidenceStrength
? mapFixtureEvidenceStrength(capture.evidenceStrength, capture.confidence ?? 0)
: undefined,
suggestedAction: capture.suggestedAction,
linkedReviewItemId: capture.linkedReviewItemId,
metadataJson: toJson({}),
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/captureFixtures.ts",
fixtureId: capture.id,
}),
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
createdAt: new Date(capture.createdAt),
},
update: {
readableId: capture.id,
type: capture.type,
title: capture.title,
content: capture.content,
source: capture.source,
status: capture.status,
classificationType: capture.classificationType,
confidence: capture.confidence,
evidenceStrength: capture.evidenceStrength
? mapFixtureEvidenceStrength(capture.evidenceStrength, capture.confidence ?? 0)
: undefined,
suggestedAction: capture.suggestedAction,
linkedReviewItemId: capture.linkedReviewItemId,
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/captureFixtures.ts",
fixtureId: capture.id,
}),
updatedBy: "seed",
sourceType: "fixture_seed",
deletedAt: null,
archivedAt: null,
},
});
}
const mapReviewStatus = (status: string): ReviewStatus => {
if (status === "accepted") return ReviewStatus.accepted;
if (status === "rejected") return ReviewStatus.rejected;
if (status === "merged") return ReviewStatus.merged;
if (status === "converted") return ReviewStatus.converted;
return ReviewStatus.pending;
};
const mapReviewVerificationState = (state: string): VerificationState => {
if (state === "verified") return VerificationState.verified;
if (state === "blocked") return VerificationState.blocked;
if (state === "needs evidence") return VerificationState.needs_evidence;
return VerificationState.unverified;
};
for (const review of reviewQueueFixtures.filter((item) => seededProjects.has(item.projectId))) {
const projectId = seededProjects.get(review.projectId)!;
await prisma.reviewQueueItem.upsert({
where: {
projectId_slug: {
projectId,
slug: review.id,
},
},
create: {
projectId,
slug: review.id,
readableId: review.id,
type: review.type,
title: review.title,
description: review.description,
priority: review.priority,
status: mapReviewStatus(review.status),
source: review.source,
confidence: review.confidence,
approvalState: review.status === "accepted" || review.status === "converted" || review.status === "merged"
? ApprovalState.approved
: review.status === "rejected"
? ApprovalState.rejected
: ApprovalState.pending,
evidenceStrength: mapFixtureEvidenceStrength(review.evidenceStrength, review.confidence),
verificationState: mapReviewVerificationState(review.verificationState),
suggestedAction: review.suggestedAction,
notes: review.notes,
targetEntityId: review.targetEntityId,
createdEntityId: review.createdEntityId,
payloadJson: toJson({ convertedTarget: review.convertedTarget }),
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/reviewQueueFixtures.ts",
fixtureId: review.id,
}),
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
createdAt: new Date(review.createdAt),
},
update: {
readableId: review.id,
type: review.type,
title: review.title,
description: review.description,
priority: review.priority,
status: mapReviewStatus(review.status),
source: review.source,
confidence: review.confidence,
approvalState: review.status === "accepted" || review.status === "converted" || review.status === "merged"
? ApprovalState.approved
: review.status === "rejected"
? ApprovalState.rejected
: ApprovalState.pending,
evidenceStrength: mapFixtureEvidenceStrength(review.evidenceStrength, review.confidence),
verificationState: mapReviewVerificationState(review.verificationState),
suggestedAction: review.suggestedAction,
notes: review.notes,
targetEntityId: review.targetEntityId,
createdEntityId: review.createdEntityId,
payloadJson: toJson({ convertedTarget: review.convertedTarget }),
provenanceJson: toJson({
seededFrom: "backend/src/fixtures/reviewQueueFixtures.ts",
fixtureId: review.id,
}),
updatedBy: "seed",
sourceType: "fixture_seed",
deletedAt: null,
archivedAt: null,
},
});
}
for (const knowledge of knowledgeFixtures.filter((item) => seededProjects.has(item.projectId))) {
const projectId = seededProjects.get(knowledge.projectId)!;
await prisma.knowledgeItem.upsert({
where: { projectId_slug: { projectId, slug: knowledge.id } },
create: {
projectId,
slug: knowledge.id,
readableId: knowledge.id,
title: knowledge.title,
category: knowledge.category,
content: knowledge.content,
source: knowledge.source,
confidence: knowledge.confidence,
includeInContextPacks: knowledge.includeInContextPacks.length > 0,
approvalState: mapApprovalState(knowledge.trust.approvalState),
evidenceStrength: mapEvidenceStrength(knowledge.confidence),
verificationState: knowledge.trust.approvalState === "approved" ? VerificationState.verified : VerificationState.unverified,
metadataJson: toJson({ linkedFeatureIds: knowledge.linkedFeatureIds, includeInContextPacks: knowledge.includeInContextPacks }),
trustJson: toJson(knowledge.trust),
provenanceJson: toJson({ seededFrom: "backend/src/fixtures/knowledgeFixtures.ts", fixtureId: knowledge.id }),
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
createdAt: new Date(knowledge.createdAt),
},
update: {
readableId: knowledge.id,
title: knowledge.title,
category: knowledge.category,
content: knowledge.content,
source: knowledge.source,
confidence: knowledge.confidence,
includeInContextPacks: knowledge.includeInContextPacks.length > 0,
approvalState: mapApprovalState(knowledge.trust.approvalState),
evidenceStrength: mapEvidenceStrength(knowledge.confidence),
verificationState: knowledge.trust.approvalState === "approved" ? VerificationState.verified : VerificationState.unverified,
metadataJson: toJson({ linkedFeatureIds: knowledge.linkedFeatureIds, includeInContextPacks: knowledge.includeInContextPacks }),
trustJson: toJson(knowledge.trust),
provenanceJson: toJson({ seededFrom: "backend/src/fixtures/knowledgeFixtures.ts", fixtureId: knowledge.id }),
updatedBy: "seed",
sourceType: "fixture_seed",
deletedAt: null,
archivedAt: null,
},
});
}
for (const rule of memoryRuleFixtures.filter((item) => seededProjects.has(item.projectId))) {
const projectId = seededProjects.get(rule.projectId)!;
await prisma.memoryRule.upsert({
where: { projectId_slug: { projectId, slug: rule.id } },
create: {
projectId,
slug: rule.id,
readableId: rule.id,
title: rule.title,
rule: rule.rule,
scope: rule.scope,
category: rule.category,
severity: rule.severity,
includeInContextPacks: rule.includeInContextPacksDefault,
confidence: rule.trust.confidence,
approvalState: mapApprovalState(rule.trust.approvalState),
evidenceStrength: mapEvidenceStrength(rule.trust.confidence),
verificationState: rule.trust.approvalState === "approved" ? VerificationState.verified : VerificationState.unverified,
trustJson: toJson(rule.trust),
provenanceJson: toJson({ linkedFeatureIds: rule.linkedFeatureIds, includeInContextPacks: rule.includeInContextPacks, seededFrom: "backend/src/fixtures/memoryRuleFixtures.ts", fixtureId: rule.id }),
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
createdAt: new Date(rule.createdAt),
},
update: {
readableId: rule.id,
title: rule.title,
rule: rule.rule,
scope: rule.scope,
category: rule.category,
severity: rule.severity,
includeInContextPacks: rule.includeInContextPacksDefault,
confidence: rule.trust.confidence,
approvalState: mapApprovalState(rule.trust.approvalState),
evidenceStrength: mapEvidenceStrength(rule.trust.confidence),
verificationState: rule.trust.approvalState === "approved" ? VerificationState.verified : VerificationState.unverified,
trustJson: toJson(rule.trust),
provenanceJson: toJson({ linkedFeatureIds: rule.linkedFeatureIds, includeInContextPacks: rule.includeInContextPacks, seededFrom: "backend/src/fixtures/memoryRuleFixtures.ts", fixtureId: rule.id }),
updatedBy: "seed",
sourceType: "fixture_seed",
deletedAt: null,
archivedAt: null,
},
});
}
const documentationSeed = [
{ id: "doc-wide-readme", title: "README summary", kind: "README summary", status: "outdated", linkedFeatureIds: [], approvalState: ApprovalState.pending, content: "Project README summary needs an approved refresh after runtime persistence work." },
{ id: "doc-wide-operating-model", title: "ProjectBrain Operating Model", kind: "architecture docs", status: "AI-generated", linkedFeatureIds: ["f-auth-mfa", "f-auth-social"], approvalState: ApprovalState.pending, content: "Operating model generated from existing project memory and runtime workflow." },
{ id: "doc-wide-codex", title: "Codex instructions", kind: "Codex instructions", status: "needs verification", linkedFeatureIds: [], approvalState: ApprovalState.pending, content: "Codex instructions must preserve review-before-truth boundaries." },
{ id: "doc-wide-decision-log", title: "Decision log", kind: "decision log", status: "approved", linkedFeatureIds: ["f-auth-mfa"], approvalState: ApprovalState.approved, content: "Decision log is approved and can feed context packs." },
];
for (const doc of documentationSeed) {
await prisma.documentationItem.upsert({
where: { projectId_slug: { projectId: project.id, slug: doc.id } },
create: {
projectId: project.id,
slug: doc.id,
readableId: doc.id,
title: doc.title,
kind: doc.kind,
status: doc.status,
approvalState: doc.approvalState,
content: doc.content,
metadataJson: toJson({ linkedFeatureIds: doc.linkedFeatureIds, lastUpdated: new Date().toISOString() }),
trustJson: toJson({ source: "documentation seed", confidence: doc.approvalState === ApprovalState.approved ? 90 : 70, evidence: [], lastChecked: new Date().toISOString(), approvalState: doc.approvalState }),
provenanceJson: toJson({ seededFrom: "backend/prisma/seed.ts", fixtureId: doc.id }),
createdBy: "seed",
updatedBy: "seed",
sourceType: "fixture_seed",
},
update: {
readableId: doc.id,
title: doc.title,
kind: doc.kind,
status: doc.status,
approvalState: doc.approvalState,
content: doc.content,
metadataJson: toJson({ linkedFeatureIds: doc.linkedFeatureIds, lastUpdated: new Date().toISOString() }),
trustJson: toJson({ source: "documentation seed", confidence: doc.approvalState === ApprovalState.approved ? 90 : 70, evidence: [], lastChecked: new Date().toISOString(), approvalState: doc.approvalState }),
provenanceJson: toJson({ seededFrom: "backend/prisma/seed.ts", fixtureId: doc.id }),
updatedBy: "seed",
sourceType: "fixture_seed",
deletedAt: null,
archivedAt: null,
},
});
}
console.log(`Seeded P2-P8 ProjectBrain persistence data for ${widefrog.id}.`);
};
try {
await main();
} finally {
await prisma.$disconnect();
}