Initial curated projectbrain source from 8a7b1e0651dbdab97d744cbd2e653ab3970ac6c5
This commit is contained in:
commit
5aa3e8d685
700 files changed
+132801
No files matched your search
@@ -0,0 +1,406 @@
|
||||
import { ApprovalState, EntityType, EvidenceStrength, FeatureLifecycle, FeatureStatus, ReviewStatus, VerificationState } from "@prisma/client";
|
||||
import { prisma } from "../db/prisma.js";
|
||||
import type { Initiative, Prisma } from "@prisma/client";
|
||||
|
||||
export type InitiativeDto = {
|
||||
id: string;
|
||||
projectId: string;
|
||||
title: string;
|
||||
intent: string;
|
||||
status: "proposed" | "planned" | "active" | "complete" | "paused";
|
||||
featureIds: string[];
|
||||
priority: "critical" | "important" | "normal" | "low";
|
||||
confidence?: number;
|
||||
approvalState?: string;
|
||||
sourceBrainstormId?: string;
|
||||
reviewItemId?: string;
|
||||
sourceType?: string;
|
||||
metadata?: unknown;
|
||||
provenance?: unknown;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
};
|
||||
|
||||
|
||||
const slugify = (value: string) =>
|
||||
value.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 56) || "initiative";
|
||||
|
||||
const toJson = (value: unknown): Prisma.InputJsonValue => JSON.parse(JSON.stringify(value)) as Prisma.InputJsonValue;
|
||||
|
||||
export type CreateInitiativeInput = {
|
||||
title: string;
|
||||
intent: string;
|
||||
priority?: InitiativeDto["priority"];
|
||||
status?: InitiativeDto["status"];
|
||||
confidence?: number;
|
||||
featureIds?: string[];
|
||||
sourceType?: string;
|
||||
};
|
||||
|
||||
export type UpdateInitiativeInput = Partial<CreateInitiativeInput> & {
|
||||
approvalState?: string;
|
||||
};
|
||||
|
||||
const toStringArray = (value: unknown): string[] => Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : [];
|
||||
const toStatus = (value: string): InitiativeDto["status"] => ["proposed", "planned", "active", "complete", "paused"].includes(value) ? value as InitiativeDto["status"] : "proposed";
|
||||
const toPriority = (value: string): InitiativeDto["priority"] => ["critical", "important", "normal", "low"].includes(value) ? value as InitiativeDto["priority"] : "normal";
|
||||
|
||||
const getProject = async (projectIdOrSlug: string) => {
|
||||
const project = await prisma.project.findFirst({ where: { OR: [{ id: projectIdOrSlug }, { slug: projectIdOrSlug }, { readableId: projectIdOrSlug }], deletedAt: null }});
|
||||
if (!project) throw new Error(`Project '${projectIdOrSlug}' not found`);
|
||||
return project;
|
||||
};
|
||||
|
||||
const toDto = (projectSlug: string, initiative: Initiative): InitiativeDto => ({
|
||||
id: initiative.slug ?? initiative.id,
|
||||
projectId: projectSlug,
|
||||
title: initiative.title,
|
||||
intent: initiative.intent,
|
||||
status: toStatus(initiative.status),
|
||||
featureIds: toStringArray(initiative.featureIdsJson),
|
||||
priority: toPriority(initiative.priority),
|
||||
confidence: initiative.confidence,
|
||||
approvalState: initiative.approvalState,
|
||||
sourceBrainstormId: initiative.sourceBrainstormId ?? undefined,
|
||||
reviewItemId: initiative.reviewItemId ?? undefined,
|
||||
sourceType: initiative.sourceType,
|
||||
metadata: initiative.metadataJson ?? undefined,
|
||||
provenance: initiative.provenanceJson ?? undefined,
|
||||
createdAt: initiative.createdAt.toISOString(),
|
||||
updatedAt: initiative.updatedAt.toISOString(),
|
||||
});
|
||||
|
||||
export const listInitiativesForProject = async (projectIdOrSlug: string): Promise<InitiativeDto[]> => {
|
||||
const project = await getProject(projectIdOrSlug);
|
||||
const items = await prisma.initiative.findMany({
|
||||
where: { projectId: project.id, deletedAt: null },
|
||||
orderBy: [{ status: "asc" }, { updatedAt: "desc" }],
|
||||
});
|
||||
return items.map((item) => toDto(project.slug, item));
|
||||
};
|
||||
|
||||
export const markInitiativePlannedFromReview = async (projectId: string, initiativeId: string, reviewItemId: string): Promise<string | undefined> => {
|
||||
const existing = await prisma.initiative.findFirst({
|
||||
where: { projectId, deletedAt: null, OR: [{ id: initiativeId }, { slug: initiativeId }, { readableId: initiativeId }] },
|
||||
});
|
||||
if (!existing) return undefined;
|
||||
const updated = await prisma.initiative.update({
|
||||
where: { id: existing.id },
|
||||
data: {
|
||||
status: "planned",
|
||||
approvalState: ApprovalState.approved,
|
||||
reviewItemId,
|
||||
updatedBy: "review_queue",
|
||||
},
|
||||
});
|
||||
return updated.slug ?? updated.id;
|
||||
};
|
||||
|
||||
|
||||
export const getInitiativeForProject = async (projectIdOrSlug: string, initiativeId: string): Promise<InitiativeDto | undefined> => {
|
||||
const project = await getProject(projectIdOrSlug);
|
||||
const item = await prisma.initiative.findFirst({
|
||||
where: { projectId: project.id, deletedAt: null, OR: [{ id: initiativeId }, { slug: initiativeId }, { readableId: initiativeId }] },
|
||||
});
|
||||
return item ? toDto(project.slug, item) : undefined;
|
||||
};
|
||||
|
||||
export const createInitiativeForProject = async (projectIdOrSlug: string, input: CreateInitiativeInput): Promise<InitiativeDto> => {
|
||||
const project = await getProject(projectIdOrSlug);
|
||||
const slug = `${slugify(input.title)}-${Date.now().toString(36)}`;
|
||||
const item = await prisma.initiative.create({
|
||||
data: {
|
||||
projectId: project.id,
|
||||
slug,
|
||||
readableId: slug,
|
||||
title: input.title,
|
||||
intent: input.intent,
|
||||
priority: input.priority ?? "normal",
|
||||
status: input.status ?? "proposed",
|
||||
confidence: input.confidence ?? 72,
|
||||
featureIdsJson: toJson(input.featureIds ?? []),
|
||||
approvalState: ApprovalState.pending,
|
||||
sourceType: input.sourceType ?? "manual_initiative",
|
||||
metadataJson: toJson({ reviewBeforeTruth: true, createdFrom: "initiative_endpoint" }),
|
||||
provenanceJson: toJson({ source: input.sourceType ?? "manual_initiative" }),
|
||||
},
|
||||
});
|
||||
await prisma.operatingLogEntry.create({
|
||||
data: {
|
||||
projectId: project.id,
|
||||
slug: `log-initiative-created-${slug}`,
|
||||
readableId: `log-initiative-created-${slug}`,
|
||||
type: "initiative created",
|
||||
title: `Initiative created: ${input.title}`,
|
||||
summary: "A roadmap initiative was created as a review-gated planning object.",
|
||||
linkedEntityIdsJson: toJson([item.slug ?? item.id]),
|
||||
source: "initiative_center",
|
||||
importance: input.priority === "critical" ? "critical" : input.priority === "important" ? "important" : "normal",
|
||||
payloadJson: toJson({ initiativeId: item.slug ?? item.id, status: item.status }),
|
||||
provenanceJson: toJson({ source: input.sourceType ?? "manual_initiative" }),
|
||||
},
|
||||
});
|
||||
return toDto(project.slug, item);
|
||||
};
|
||||
|
||||
export const updateInitiativeForProject = async (projectIdOrSlug: string, initiativeId: string, input: UpdateInitiativeInput): Promise<InitiativeDto | undefined> => {
|
||||
const project = await getProject(projectIdOrSlug);
|
||||
const existing = await prisma.initiative.findFirst({
|
||||
where: { projectId: project.id, deletedAt: null, OR: [{ id: initiativeId }, { slug: initiativeId }, { readableId: initiativeId }] },
|
||||
});
|
||||
if (!existing) return undefined;
|
||||
const updated = await prisma.initiative.update({
|
||||
where: { id: existing.id },
|
||||
data: {
|
||||
title: input.title,
|
||||
intent: input.intent,
|
||||
priority: input.priority,
|
||||
status: input.status,
|
||||
confidence: input.confidence,
|
||||
featureIdsJson: input.featureIds ? toJson(input.featureIds) : undefined,
|
||||
approvalState: input.approvalState === "approved" ? ApprovalState.approved : input.approvalState === "rejected" ? ApprovalState.rejected : undefined,
|
||||
updatedBy: "initiative_endpoint",
|
||||
},
|
||||
});
|
||||
return toDto(project.slug, updated);
|
||||
};
|
||||
|
||||
const suggestedFeatureTitlesFor = (initiative: InitiativeDto): string[] => {
|
||||
const text = `${initiative.title} ${initiative.intent}`.toLowerCase();
|
||||
if (text.includes("brainstorm")) return ["Brainstorm review detail", "Outcome conversion guardrails", "Idea graph comparison panel"];
|
||||
if (text.includes("blueprint") || text.includes("documentation")) return ["Blueprint acceptance workflow", "Documentation export audit", "Stale document regeneration queue"];
|
||||
if (text.includes("database") || text.includes("backend")) return ["Database smoke evidence panel", "API contract regression pack", "Persistence recovery checklist"];
|
||||
if (text.includes("ux") || text.includes("usability")) return ["Guided empty-state actions", "Workflow-based navigation polish", "Mobile action rail refinement"];
|
||||
return ["Initiative scope brief", "Feature candidate breakdown", "Acceptance criteria draft"];
|
||||
};
|
||||
|
||||
export type InitiativeFeatureCandidateDto = {
|
||||
id: string;
|
||||
title: string;
|
||||
confidence: number;
|
||||
reviewItemId: string;
|
||||
targetRoute: string;
|
||||
materializedFeatureId?: string;
|
||||
};
|
||||
|
||||
export type InitiativeReviewSyncResultDto = {
|
||||
applied: boolean;
|
||||
action: "accept" | "reject";
|
||||
reviewItemId: string;
|
||||
initiativeId?: string;
|
||||
featureId?: string;
|
||||
acceptedTruthId?: string;
|
||||
affectedEntities: string[];
|
||||
message: string;
|
||||
};
|
||||
|
||||
export const createFeatureCandidatesForInitiative = async (projectIdOrSlug: string, initiativeId: string): Promise<{ initiative: InitiativeDto; candidates: InitiativeFeatureCandidateDto[] } | undefined> => {
|
||||
const project = await getProject(projectIdOrSlug);
|
||||
const initiative = await getInitiativeForProject(projectIdOrSlug, initiativeId);
|
||||
if (!initiative) return undefined;
|
||||
const titles = suggestedFeatureTitlesFor(initiative);
|
||||
const candidates: InitiativeFeatureCandidateDto[] = [];
|
||||
|
||||
for (const [index, title] of titles.entries()) {
|
||||
const slug = `rq-initiative-feature-${slugify(initiative.title)}-${index}-${Date.now().toString(36)}`;
|
||||
const review = await prisma.reviewQueueItem.create({
|
||||
data: {
|
||||
projectId: project.id,
|
||||
slug,
|
||||
readableId: slug,
|
||||
type: "feature",
|
||||
title: `Feature candidate: ${title}`,
|
||||
description: `Initiative '${initiative.title}' proposes this feature candidate.\n\nIntent: ${initiative.intent}`,
|
||||
priority: initiative.priority === "critical" ? "critical" : initiative.priority === "important" ? "important" : "normal",
|
||||
status: ReviewStatus.pending,
|
||||
source: "initiative_center",
|
||||
confidence: Math.max(62, (initiative.confidence ?? 72) - index * 6),
|
||||
approvalState: ApprovalState.pending,
|
||||
evidenceStrength: EvidenceStrength.medium,
|
||||
verificationState: VerificationState.needs_evidence,
|
||||
suggestedAction: "Review whether this feature should be promoted into the Feature Map.",
|
||||
createdBy: "api",
|
||||
updatedBy: "api",
|
||||
sourceType: "initiative_feature_candidate",
|
||||
targetEntityType: undefined,
|
||||
targetEntityId: initiative.id,
|
||||
payloadJson: toJson({ initiativeId: initiative.id, candidateTitle: title, candidateIndex: index }),
|
||||
provenanceJson: toJson({ createdFrom: "Initiative feature generation", initiativeId: initiative.id }),
|
||||
},
|
||||
});
|
||||
candidates.push({ id: `${initiative.id}-candidate-${index}`, title, confidence: Math.max(62, (initiative.confidence ?? 72) - index * 6), reviewItemId: review.slug ?? review.id, targetRoute: `/projects/${project.slug}/review-queue` });
|
||||
}
|
||||
|
||||
await prisma.operatingLogEntry.create({
|
||||
data: {
|
||||
projectId: project.id,
|
||||
slug: `log-initiative-feature-candidates-${slugify(initiative.title)}-${Date.now().toString(36)}`,
|
||||
readableId: `log-initiative-feature-candidates-${slugify(initiative.title)}-${Date.now().toString(36)}`,
|
||||
type: "initiative planning",
|
||||
title: `Feature candidates generated for ${initiative.title}`,
|
||||
summary: `${candidates.length} feature candidates were generated and queued for review.`,
|
||||
linkedEntityIdsJson: toJson([initiative.id, ...candidates.map((item) => item.reviewItemId)]),
|
||||
source: "initiative_center",
|
||||
importance: initiative.priority === "critical" ? "critical" : initiative.priority === "important" ? "important" : "normal",
|
||||
payloadJson: toJson({ initiativeId: initiative.id, candidateCount: candidates.length }),
|
||||
provenanceJson: toJson({ source: "initiative_feature_generation" }),
|
||||
},
|
||||
});
|
||||
|
||||
return { initiative, candidates };
|
||||
};
|
||||
|
||||
|
||||
const safeRecord = (value: unknown): Record<string, unknown> =>
|
||||
typeof value === "object" && value !== null ? value as Record<string, unknown> : {};
|
||||
|
||||
const getString = (value: unknown, fallback = ""): string => typeof value === "string" && value.trim() ? value : fallback;
|
||||
|
||||
const acceptedTruthKindForInitiativeReview = (reviewType: string) =>
|
||||
reviewType === "feature" ? "feature" : reviewType;
|
||||
|
||||
const ensureInitiativeFeatureGroup = async (projectId: string) =>
|
||||
prisma.featureGroup.upsert({
|
||||
where: { projectId_slug: { projectId, slug: "initiative-roadmap" } },
|
||||
create: {
|
||||
projectId,
|
||||
slug: "initiative-roadmap",
|
||||
readableId: "initiative-roadmap",
|
||||
name: "Initiative Roadmap",
|
||||
description: "Features materialized from accepted roadmap initiative candidates.",
|
||||
focusArea: "Roadmap",
|
||||
},
|
||||
update: {},
|
||||
});
|
||||
|
||||
export const syncInitiativeReviewAction = async (
|
||||
projectIdOrSlug: string,
|
||||
reviewItemId: string,
|
||||
action: "accept" | "reject",
|
||||
): Promise<InitiativeReviewSyncResultDto | undefined> => {
|
||||
const project = await getProject(projectIdOrSlug);
|
||||
const review = await prisma.reviewQueueItem.findFirst({
|
||||
where: {
|
||||
projectId: project.id,
|
||||
deletedAt: null,
|
||||
OR: [{ id: reviewItemId }, { slug: reviewItemId }, { readableId: reviewItemId }],
|
||||
},
|
||||
});
|
||||
if (!review || review.sourceType !== "initiative_feature_candidate") return undefined;
|
||||
|
||||
const payload = safeRecord(review.payloadJson);
|
||||
const initiativeId = getString(payload.initiativeId, review.targetEntityId ?? "");
|
||||
const candidateTitle = getString(payload.candidateTitle, review.title.replace(/^Feature candidate:\s*/i, ""));
|
||||
const affectedEntities = [review.slug ?? review.id];
|
||||
|
||||
let featureId: string | undefined;
|
||||
let acceptedTruthId: string | undefined;
|
||||
|
||||
if (initiativeId) affectedEntities.push(initiativeId);
|
||||
|
||||
if (action === "accept") {
|
||||
const group = await ensureInitiativeFeatureGroup(project.id);
|
||||
const featureSlug = `initiative-feature-${slugify(candidateTitle)}-${Date.now().toString(36)}`;
|
||||
const feature = await prisma.feature.create({
|
||||
data: {
|
||||
projectId: project.id,
|
||||
featureGroupId: group.id,
|
||||
slug: featureSlug,
|
||||
readableId: featureSlug,
|
||||
name: candidateTitle,
|
||||
description: review.description,
|
||||
status: FeatureStatus.todo,
|
||||
lifecycle: FeatureLifecycle.planned,
|
||||
intent: `Materialized from accepted roadmap initiative candidate. Initiative: ${initiativeId || "unknown"}.`,
|
||||
confidence: review.confidence,
|
||||
health: 65,
|
||||
approvalState: ApprovalState.approved,
|
||||
evidenceStrength: review.evidenceStrength,
|
||||
verificationState: VerificationState.needs_evidence,
|
||||
trustJson: toJson({ initiativeId, reviewItemId: review.slug ?? review.id, materializedFrom: "initiative_feature_candidate" }),
|
||||
provenanceJson: toJson({ source: "initiative_review_accept", initiativeId, reviewItemId: review.id, candidateTitle }),
|
||||
sourceType: "initiative_review_accept",
|
||||
createdBy: "review_queue",
|
||||
updatedBy: "review_queue",
|
||||
},
|
||||
});
|
||||
featureId = feature.slug ?? feature.id;
|
||||
affectedEntities.push(featureId);
|
||||
|
||||
if (initiativeId) {
|
||||
const initiative = await prisma.initiative.findFirst({
|
||||
where: { projectId: project.id, deletedAt: null, OR: [{ id: initiativeId }, { slug: initiativeId }, { readableId: initiativeId }] },
|
||||
});
|
||||
if (initiative) {
|
||||
const existingFeatureIds = toStringArray(initiative.featureIdsJson);
|
||||
await prisma.initiative.update({
|
||||
where: { id: initiative.id },
|
||||
data: {
|
||||
status: initiative.status === "proposed" ? "planned" : initiative.status,
|
||||
approvalState: ApprovalState.approved,
|
||||
featureIdsJson: toJson(Array.from(new Set([...existingFeatureIds, featureId]))),
|
||||
updatedBy: "review_queue",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const existingTruth = await prisma.acceptedTruthItem.findFirst({ where: { projectId: project.id, sourceReviewItemId: review.id, deletedAt: null } });
|
||||
if (existingTruth) acceptedTruthId = existingTruth.slug ?? existingTruth.id;
|
||||
else {
|
||||
const slug = `truth-initiative-feature-${slugify(candidateTitle)}-${Date.now().toString(36)}`;
|
||||
const truth = await prisma.acceptedTruthItem.create({
|
||||
data: {
|
||||
projectId: project.id,
|
||||
slug,
|
||||
readableId: slug,
|
||||
sourceReviewItemId: review.id,
|
||||
kind: acceptedTruthKindForInitiativeReview(review.type),
|
||||
title: `Accepted initiative feature: ${candidateTitle}`,
|
||||
summary: review.description,
|
||||
status: "accepted",
|
||||
source: "initiative_center",
|
||||
confidence: review.confidence,
|
||||
approvalState: ApprovalState.approved,
|
||||
evidenceStrength: review.evidenceStrength,
|
||||
verificationState: VerificationState.verified,
|
||||
payloadJson: toJson({ initiativeId, featureId, reviewItemId: review.slug ?? review.id, candidateTitle, targetRoute: `/projects/${project.slug}/features/${featureId}` }),
|
||||
provenanceJson: toJson({ createdFrom: "Initiative feature candidate review acceptance", sourceType: review.sourceType }),
|
||||
verifiedAt: new Date(),
|
||||
verifiedBy: "api",
|
||||
},
|
||||
});
|
||||
acceptedTruthId = truth.slug ?? truth.id;
|
||||
}
|
||||
if (acceptedTruthId) affectedEntities.push(acceptedTruthId);
|
||||
}
|
||||
|
||||
await prisma.operatingLogEntry.create({
|
||||
data: {
|
||||
projectId: project.id,
|
||||
slug: `log-initiative-review-${slugify(candidateTitle)}-${Date.now().toString(36)}`,
|
||||
readableId: `log-initiative-review-${slugify(candidateTitle)}-${Date.now().toString(36)}`,
|
||||
type: "initiative review sync",
|
||||
title: action === "accept" ? `Initiative feature accepted: ${candidateTitle}` : `Initiative feature rejected: ${candidateTitle}`,
|
||||
summary: action === "accept" ? "Accepted initiative feature candidate was materialized into the Feature Map and Accepted Truth." : "Rejected initiative feature candidate was left out of the Feature Map.",
|
||||
linkedEntityIdsJson: toJson(affectedEntities),
|
||||
source: "initiative_center",
|
||||
importance: action === "accept" ? "important" : "normal",
|
||||
payloadJson: toJson({ action, initiativeId, featureId, acceptedTruthId }),
|
||||
provenanceJson: toJson({ reviewItemId: review.id, sourceType: review.sourceType }),
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
applied: true,
|
||||
action,
|
||||
reviewItemId: review.slug ?? review.id,
|
||||
initiativeId,
|
||||
featureId,
|
||||
acceptedTruthId,
|
||||
affectedEntities,
|
||||
message: action === "accept"
|
||||
? "Initiative feature candidate accepted and materialized into Feature Map."
|
||||
: "Initiative feature candidate rejected without materializing a feature.",
|
||||
};
|
||||
};
|
||||
Reference in new issue
Block a user