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,182 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { ApprovalState, DeliveryStatus, DeliveryValidationStatus } from "@prisma/client";
|
||||
|
||||
const mocks = vi.hoisted(() => {
|
||||
const tx = {
|
||||
deliveryPlan: { create: vi.fn(), update: vi.fn() },
|
||||
initiative: { update: vi.fn() },
|
||||
outboxEvent: { create: vi.fn() },
|
||||
deliveryRun: { create: vi.fn(), update: vi.fn() },
|
||||
deliveryValidation: { create: vi.fn(), deleteMany: vi.fn() },
|
||||
findingInvestigation: { findUnique: vi.fn(), update: vi.fn() },
|
||||
repositoryFinding: { update: vi.fn() },
|
||||
};
|
||||
const prisma = {
|
||||
project: { findFirst: vi.fn() },
|
||||
initiative: { findFirstOrThrow: vi.fn() },
|
||||
deliveryPlan: { findFirst: vi.fn(), findMany: vi.fn() },
|
||||
giteaRepositoryLink: { findFirst: vi.fn() },
|
||||
deliveryRun: { findFirst: vi.fn() },
|
||||
$transaction: vi.fn(async (callback: (client: typeof tx) => unknown) => callback(tx)),
|
||||
};
|
||||
return {
|
||||
prisma,
|
||||
tx,
|
||||
createInitiativeForProject: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../src/db/prisma.js", () => ({ prisma: mocks.prisma }));
|
||||
vi.mock("../src/repositories/initiativesRepository.js", () => ({ createInitiativeForProject: mocks.createInitiativeForProject }));
|
||||
|
||||
import { createFeatureDelivery, startFeatureDelivery, recordFeatureDeliveryActionValidation, reportedValidationResult, type FeatureDeliveryInput } from "../src/repositories/featureDeliveryRepository.js";
|
||||
|
||||
const baseInput = (riskLevel: FeatureDeliveryInput["riskLevel"]): FeatureDeliveryInput => ({
|
||||
title: "Intent-first onboarding",
|
||||
intent: "Make onboarding understandable for nontechnical users.",
|
||||
priority: "normal",
|
||||
problem: "The current onboarding exposes too many technical concepts.",
|
||||
desiredOutcome: "A short intent-first onboarding flow.",
|
||||
users: ["new users"],
|
||||
goals: ["reduce cognitive load"],
|
||||
nonGoals: ["remove technical capabilities"],
|
||||
acceptanceCriteria: ["normal users can create a project without understanding MCP or Git internals"],
|
||||
implementationPlan: ["simplify the primary flow", "preserve technical drill-downs"],
|
||||
risks: ["navigation changes can affect deep links"],
|
||||
validationCommands: ["pnpm test"],
|
||||
riskLevel,
|
||||
});
|
||||
|
||||
const plan = (approvalState: ApprovalState, status: DeliveryStatus) => ({
|
||||
id: "delivery-db-1",
|
||||
slug: "delivery-1",
|
||||
projectId: "project-db-1",
|
||||
initiativeId: "initiative-db-1",
|
||||
title: "Intent-first onboarding",
|
||||
intent: "Make onboarding understandable for nontechnical users.",
|
||||
priority: "normal",
|
||||
problem: "The current onboarding exposes too many technical concepts.",
|
||||
desiredOutcome: "A short intent-first onboarding flow.",
|
||||
usersJson: ["new users"],
|
||||
goalsJson: ["reduce cognitive load"],
|
||||
nonGoalsJson: [],
|
||||
acceptanceCriteriaJson: ["normal users understand the flow"],
|
||||
implementationPlanJson: ["simplify the primary flow"],
|
||||
risksJson: ["navigation changes"],
|
||||
validationCommandsJson: ["pnpm test"],
|
||||
status,
|
||||
approvalState,
|
||||
approvedAt: approvalState === ApprovalState.approved ? new Date("2026-08-31T20:00:00.000Z") : null,
|
||||
approvedBy: approvalState === ApprovalState.approved ? "chatgpt" : null,
|
||||
reviewFeedback: null,
|
||||
version: 1,
|
||||
createdBy: "chatgpt",
|
||||
updatedBy: "chatgpt",
|
||||
createdAt: new Date("2026-08-31T20:00:00.000Z"),
|
||||
updatedAt: new Date("2026-08-31T20:00:00.000Z"),
|
||||
initiative: null,
|
||||
runs: [],
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mocks.prisma.project.findFirst.mockResolvedValue({ id: "project-db-1", slug: "projectbrain" });
|
||||
mocks.createInitiativeForProject.mockResolvedValue({ id: "initiative-1" });
|
||||
mocks.prisma.initiative.findFirstOrThrow.mockResolvedValue({ id: "initiative-db-1", slug: "initiative-1" });
|
||||
mocks.tx.initiative.update.mockResolvedValue({});
|
||||
mocks.tx.outboxEvent.create.mockResolvedValue({});
|
||||
mocks.tx.findingInvestigation.findUnique.mockResolvedValue(null);
|
||||
});
|
||||
|
||||
describe("feature delivery risk authorization", () => {
|
||||
it.each([
|
||||
["low", "AUTO_ALLOWED"],
|
||||
["medium", "AUTO_ALLOWED_WITH_AUDIT"],
|
||||
] as const)("auto-authorizes %s reversible work", async (riskLevel, policyDecision) => {
|
||||
const created = plan(ApprovalState.approved, DeliveryStatus.approved);
|
||||
mocks.tx.deliveryPlan.create.mockResolvedValue(created);
|
||||
|
||||
const result = await createFeatureDelivery("projectbrain", baseInput(riskLevel), "chatgpt");
|
||||
|
||||
expect(result.approvalState).toBe(ApprovalState.approved);
|
||||
expect(result.spec.status).toBe(DeliveryStatus.approved);
|
||||
expect(mocks.tx.deliveryPlan.create).toHaveBeenCalledWith(expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
approvalState: ApprovalState.approved,
|
||||
status: DeliveryStatus.approved,
|
||||
}),
|
||||
}));
|
||||
expect(mocks.tx.outboxEvent.create).toHaveBeenCalledWith(expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
eventType: "delivery.plan.auto_authorized",
|
||||
payloadJson: expect.objectContaining({ riskLevel, policyDecision }),
|
||||
}),
|
||||
}));
|
||||
});
|
||||
|
||||
it.each(["high", "destructive"] as const)("requires a human decision for %s work", async (riskLevel) => {
|
||||
const created = plan(ApprovalState.pending, DeliveryStatus.awaiting_approval);
|
||||
mocks.tx.deliveryPlan.create.mockResolvedValue(created);
|
||||
|
||||
const result = await createFeatureDelivery("projectbrain", baseInput(riskLevel), "chatgpt");
|
||||
|
||||
expect(result.approvalState).toBe(ApprovalState.pending);
|
||||
expect(result.spec.status).toBe(DeliveryStatus.awaiting_approval);
|
||||
expect(mocks.tx.deliveryPlan.create).toHaveBeenCalledWith(expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
approvalState: ApprovalState.pending,
|
||||
status: DeliveryStatus.awaiting_approval,
|
||||
approvedAt: null,
|
||||
approvedBy: null,
|
||||
}),
|
||||
}));
|
||||
expect(mocks.tx.outboxEvent.create).toHaveBeenCalledWith(expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
eventType: "delivery.plan.user_decision_required",
|
||||
payloadJson: expect.objectContaining({ riskLevel, policyDecision: "USER_DECISION_REQUIRED" }),
|
||||
}),
|
||||
}));
|
||||
});
|
||||
|
||||
it("fails closed when a pending high-risk delivery tries to start repository execution", async () => {
|
||||
mocks.prisma.deliveryPlan.findFirst.mockResolvedValue(plan(ApprovalState.pending, DeliveryStatus.awaiting_approval));
|
||||
|
||||
await expect(startFeatureDelivery("projectbrain", "delivery-1", "chatgpt/high-risk-change"))
|
||||
.rejects.toThrow("FEATURE_DELIVERY_APPROVAL_REQUIRED");
|
||||
|
||||
expect(mocks.prisma.giteaRepositoryLink.findFirst).not.toHaveBeenCalled();
|
||||
expect(mocks.tx.deliveryRun.create).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Actions evidence scope", () => {
|
||||
it("records only the observed workflow, preserving separately reported checks", async () => {
|
||||
const current = { ...plan(ApprovalState.approved, DeliveryStatus.validating),
|
||||
validationCommandsJson: ["dotnet test", "CI / build-test (pull_request)", "Live disposable provider smoke"],
|
||||
runs: [{ id: "run-1", validations: [], changes: [] }] };
|
||||
mocks.prisma.deliveryPlan.findFirst.mockResolvedValue(current);
|
||||
mocks.tx.deliveryPlan.update.mockResolvedValue(current);
|
||||
await recordFeatureDeliveryActionValidation("projectbrain", "delivery-1", {
|
||||
provider: "gitea_actions", runId: 9205, runNumber: 500, url: "https://example.test/actions/runs/9205",
|
||||
workflowPath: "managed-validation.yml@refs/heads/chatgpt/work", headSha: "a".repeat(40),
|
||||
conclusion: "success", verifiedAt: "2026-09-08T00:00:00Z",
|
||||
});
|
||||
expect(mocks.tx.deliveryValidation.create).toHaveBeenCalledTimes(1);
|
||||
expect(mocks.tx.deliveryValidation.create).toHaveBeenCalledWith({ data: expect.objectContaining({
|
||||
command: "Gitea Actions: managed-validation.yml@refs/heads/chatgpt/work", status: "passed", headSha: "a".repeat(40),
|
||||
}) });
|
||||
expect(mocks.tx.deliveryValidation.deleteMany).toHaveBeenCalledWith({ where: { deliveryRunId: "run-1", provider: "gitea_actions" } });
|
||||
});
|
||||
|
||||
it.each(["CI / build-test (pull_request)", "Live provider smoke", "dotnet test"])("does not present legacy inferred %s as execution", (command) => {
|
||||
expect(reportedValidationResult({ command, status: DeliveryValidationStatus.passed, provider: "gitea_actions", summary: "managed-validation.yml" }))
|
||||
.toEqual({ command, status: "not_run", summary: expect.stringContaining("Legacy inferred result") });
|
||||
});
|
||||
|
||||
it("preserves explicit reports and directly observed workflow results", () => {
|
||||
expect(reportedValidationResult({ command: "Live provider smoke", status: DeliveryValidationStatus.skipped, provider: null, summary: "Credentials unavailable" }).status).toBe("not_run");
|
||||
expect(reportedValidationResult({ command: "Local contract suite", status: DeliveryValidationStatus.failed, provider: null, summary: "Failed" }).status).toBe("failed");
|
||||
expect(reportedValidationResult({ command: "CI / build-test (pull_request)", status: DeliveryValidationStatus.failed, provider: "gitea_actions", summary: "ci.yml" }).status).toBe("failed");
|
||||
expect(reportedValidationResult({ command: "Gitea Actions: ci.yml", status: DeliveryValidationStatus.passed, provider: "gitea_actions", summary: "ci.yml" }).status).toBe("passed");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user