Publish curated projectbrain source from 88fab8df1542019289e947f092c2b387e0825c60
This commit is contained in:
1 parent
48e72d07e0
commit
eca2891b07
45 files changed
+2697
-328
No files matched your search
@@ -8,123 +8,42 @@ import { getFeatureDelivery } from "./featureDeliveryRepository.js";
|
||||
import { createBrainstormForProject } from "./brainstormRepository.js";
|
||||
import { parseRoadmapMarkdown } from "../services/autonomyRoadmap.js";
|
||||
import { decideRecovery } from "../services/recoveryPolicy.js";
|
||||
import { applyAutonomyQueueOrder, clearAutonomyQueueOrder, nextManualOrderForAutonomyState } from "../services/autonomyQueueOrdering.js";
|
||||
import { hasGiteaAutonomyCompletionEvidence, type AutonomyExecutionTarget } from "./autonomyExecutionEvidence.js";
|
||||
import type {
|
||||
AutonomyCompletedLease,
|
||||
AutonomyEvent,
|
||||
AutonomyLease,
|
||||
AutonomyRoadmap,
|
||||
AutonomyRoadmapItem,
|
||||
AutonomyRoadmapPhase,
|
||||
AutonomyRun,
|
||||
AutonomyState,
|
||||
AutonomyStatus,
|
||||
AutonomyWorkKind,
|
||||
AutonomyWorkOutcome,
|
||||
RoadmapItemStatus,
|
||||
RoadmapPhaseStatus,
|
||||
} from "./autonomyTypes.js";
|
||||
export { parseRoadmapMarkdown };
|
||||
export { autonomyRetryDelayMinutes, classifyAutonomyBlocker };
|
||||
export { hasGiteaAutonomyCompletionEvidence };
|
||||
export type { AutonomyExecutionTarget };
|
||||
export type AutonomyStatus = "off" | "waiting_roadmap" | "running" | "blocked" | "completed";
|
||||
export type AutonomyWorkKind = "brainstorm" | "implement" | "validate_phase";
|
||||
export type AutonomyWorkOutcome = "success" | "failed" | "blocked";
|
||||
export type RoadmapItemStatus = "pending" | "in_progress" | "completed" | "blocked";
|
||||
export type RoadmapPhaseStatus = "pending" | "active" | "brainstorming" | "executing" | "validating" | "completed" | "blocked";
|
||||
|
||||
export type AutonomyRoadmapItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
instruction?: string;
|
||||
source?: "roadmap" | "user_assignment" | "brainstorm" | "recovery" | "finding" | "delivery" | "release" | "remediation" | "feature" | "bug";
|
||||
createdAt?: string;
|
||||
status: RoadmapItemStatus;
|
||||
attempts: number;
|
||||
priority?: number;
|
||||
scope?: "required" | "committed" | "stretch" | "future";
|
||||
risk?: "low" | "normal" | "medium" | "high" | "critical";
|
||||
estimatedScope?: number;
|
||||
releaseBlocking?: boolean;
|
||||
waitingExternal?: boolean;
|
||||
touchedPaths?: string[];
|
||||
domain?: string;
|
||||
deliveryId?: string;
|
||||
dependsOn?: string[];
|
||||
lastResult?: string;
|
||||
lastError?: string;
|
||||
completionEvidence?: string[];
|
||||
supersededBy?: string;
|
||||
};
|
||||
|
||||
export type AutonomyRoadmapPhase = {
|
||||
id: string;
|
||||
title: string;
|
||||
objective: string;
|
||||
status: RoadmapPhaseStatus;
|
||||
brainstormIterations: number;
|
||||
brainstormConverged: boolean;
|
||||
validationFailures: number;
|
||||
items: AutonomyRoadmapItem[];
|
||||
};
|
||||
|
||||
export type AutonomyRoadmap = {
|
||||
id: string;
|
||||
title: string;
|
||||
sourceMarkdown: string;
|
||||
status: "active" | "completed" | "blocked";
|
||||
currentPhaseIndex: number;
|
||||
phases: AutonomyRoadmapPhase[];
|
||||
importedAt: string;
|
||||
completedAt?: string;
|
||||
};
|
||||
|
||||
export type AutonomyLease = {
|
||||
token: string;
|
||||
kind: AutonomyWorkKind;
|
||||
actor: string;
|
||||
runId?: string;
|
||||
roadmapId: string;
|
||||
phaseId: string;
|
||||
itemId?: string;
|
||||
createdAt: string;
|
||||
expiresAt: string;
|
||||
};
|
||||
|
||||
export type AutonomyCompletedLease = {
|
||||
token: string;
|
||||
outcome: AutonomyWorkOutcome;
|
||||
summary: string;
|
||||
addedTasks: string[];
|
||||
completedAt: string;
|
||||
};
|
||||
|
||||
export type AutonomyRun = {
|
||||
id: string;
|
||||
actor: string;
|
||||
startedAt: string;
|
||||
reportedWorkItems: number;
|
||||
};
|
||||
|
||||
export type AutonomyEvent = {
|
||||
id: string;
|
||||
at: string;
|
||||
type: string;
|
||||
actor: string;
|
||||
summary: string;
|
||||
};
|
||||
|
||||
export type AutonomyState = {
|
||||
version: 1;
|
||||
profile: AutonomyProfile;
|
||||
enabled: boolean;
|
||||
status: AutonomyStatus;
|
||||
autoBrainstorm: boolean;
|
||||
maxBrainstormIterations: number;
|
||||
maxConsecutiveFailures: number;
|
||||
leaseMinutes: number;
|
||||
maxWorkItemsPerRun: number;
|
||||
maxRunMinutes: number;
|
||||
pauseAfterCurrent: boolean;
|
||||
schedulingPolicy: "balanced" | "downstream-impact";
|
||||
roadmap?: AutonomyRoadmap;
|
||||
activeLease?: AutonomyLease;
|
||||
blocker?: { at: string; phaseId?: string; itemId?: string; reason: string; kind: "human" | "retryable"; retryAt?: string; recoveryStage?: "retry" | "cooldown" | "alternate_recovery" | "escalated"; recoveryAttempts?: number; recoveryStartedAt?: string };
|
||||
recoveryStartedAt?: string;
|
||||
recoveryAttempts?: number;
|
||||
maxRecoveryMinutes?: number;
|
||||
runs: AutonomyRun[];
|
||||
completedLeases: AutonomyCompletedLease[];
|
||||
events: AutonomyEvent[];
|
||||
updatedAt: string;
|
||||
updatedBy: string;
|
||||
};
|
||||
export type {
|
||||
AutonomyCompletedLease,
|
||||
AutonomyEvent,
|
||||
AutonomyLease,
|
||||
AutonomyRoadmap,
|
||||
AutonomyRoadmapItem,
|
||||
AutonomyRoadmapPhase,
|
||||
AutonomyRun,
|
||||
AutonomyState,
|
||||
AutonomyStatus,
|
||||
AutonomyWorkKind,
|
||||
AutonomyWorkOutcome,
|
||||
RoadmapItemStatus,
|
||||
RoadmapPhaseStatus,
|
||||
} from "./autonomyTypes.js";
|
||||
|
||||
export type AutonomyWork = {
|
||||
token: string;
|
||||
@@ -220,6 +139,7 @@ const normalizeItem = (value: unknown): AutonomyRoadmapItem | undefined => {
|
||||
...(asString(row.createdAt) ? { createdAt: asString(row.createdAt) } : {}),
|
||||
...(asString(row.deliveryId) ? { deliveryId: asString(row.deliveryId) } : {}),
|
||||
...(typeof row.priority === "number" ? { priority: asInt(row.priority, 50, 0, 100) } : {}),
|
||||
...(typeof row.manualOrder === "number" ? { manualOrder: asInt(row.manualOrder, 0, 0, 10_000) } : {}),
|
||||
...(["required", "committed", "stretch", "future"].includes(asString(row.scope)) ? { scope: asString(row.scope) as AutonomyRoadmapItem["scope"] } : {}),
|
||||
...(["low", "normal", "medium", "high", "critical"].includes(asString(row.risk)) ? { risk: asString(row.risk) as AutonomyRoadmapItem["risk"] } : {}),
|
||||
...(typeof row.estimatedScope === "number" ? { estimatedScope: asInt(row.estimatedScope, 0, 0, 10) } : {}),
|
||||
@@ -430,6 +350,7 @@ const assignmentTitle = (input: EnqueueAutonomyTaskInput) => {
|
||||
export const enqueueAutonomyTaskInState = (current: AutonomyState, input: EnqueueAutonomyTaskInput, actor = "owner") => {
|
||||
const next = structuredClone(current) as AutonomyState;
|
||||
const createdAt = nowIso();
|
||||
const nextManualOrder = nextManualOrderForAutonomyState(current);
|
||||
const task: AutonomyRoadmapItem = {
|
||||
id: `assignment-${randomUUID()}`,
|
||||
title: assignmentTitle(input),
|
||||
@@ -438,6 +359,7 @@ export const enqueueAutonomyTaskInState = (current: AutonomyState, input: Enqueu
|
||||
createdAt,
|
||||
status: "pending",
|
||||
attempts: 0,
|
||||
...(nextManualOrder !== undefined ? { manualOrder: nextManualOrder } : {}),
|
||||
};
|
||||
const createAssignmentPhase = (): AutonomyRoadmapPhase => ({
|
||||
id: `projectbrain-opdrachten-${randomUUID()}`,
|
||||
@@ -480,6 +402,28 @@ export const enqueueAutonomyTaskInState = (current: AutonomyState, input: Enqueu
|
||||
return { state, task };
|
||||
};
|
||||
|
||||
export const reorderAutonomyQueueInState = (current: AutonomyState, orderedItemIds: string[], actor = "owner") => {
|
||||
const next = applyAutonomyQueueOrder(current, orderedItemIds);
|
||||
return appendEvent(next, event("autonomy.queue.reordered", actor, `Reordered ${orderedItemIds.length} pending Auto Mode work item(s).`));
|
||||
};
|
||||
|
||||
export const reorderAutonomyQueue = async (projectIdOrSlug: string, orderedItemIds: string[], actor = "owner") => {
|
||||
const project = await getProjectRow(projectIdOrSlug);
|
||||
const current = retryAutonomyBlockerIfDue(expireLeaseIfNeeded(readState(project, actor)));
|
||||
return saveState(project, reorderAutonomyQueueInState(current, orderedItemIds, actor), actor);
|
||||
};
|
||||
|
||||
export const resetAutonomyQueueOrderInState = (current: AutonomyState, actor = "owner") => {
|
||||
const next = clearAutonomyQueueOrder(current);
|
||||
return appendEvent(next, event("autonomy.queue.order_reset", actor, "Restored automatic Auto Mode scheduling order."));
|
||||
};
|
||||
|
||||
export const resetAutonomyQueueOrder = async (projectIdOrSlug: string, actor = "owner") => {
|
||||
const project = await getProjectRow(projectIdOrSlug);
|
||||
const current = retryAutonomyBlockerIfDue(expireLeaseIfNeeded(readState(project, actor)));
|
||||
return saveState(project, resetAutonomyQueueOrderInState(current, actor), actor);
|
||||
};
|
||||
|
||||
const expireLeaseIfNeeded = (state: AutonomyState) => {
|
||||
if (!state.activeLease || new Date(state.activeLease.expiresAt).getTime() > Date.now()) return state;
|
||||
const next = structuredClone(state) as AutonomyState;
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
import type { AutonomyProfile } from "@projectbrain/contracts";
|
||||
|
||||
export type AutonomyStatus = "off" | "waiting_roadmap" | "running" | "blocked" | "completed";
|
||||
export type AutonomyWorkKind = "brainstorm" | "implement" | "validate_phase";
|
||||
export type AutonomyWorkOutcome = "success" | "failed" | "blocked";
|
||||
export type RoadmapItemStatus = "pending" | "in_progress" | "completed" | "blocked";
|
||||
export type RoadmapPhaseStatus = "pending" | "active" | "brainstorming" | "executing" | "validating" | "completed" | "blocked";
|
||||
|
||||
export type AutonomyRoadmapItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
instruction?: string;
|
||||
source?: "roadmap" | "user_assignment" | "brainstorm" | "recovery" | "finding" | "delivery" | "release" | "remediation" | "feature" | "bug";
|
||||
createdAt?: string;
|
||||
status: RoadmapItemStatus;
|
||||
attempts: number;
|
||||
priority?: number;
|
||||
manualOrder?: number;
|
||||
scope?: "required" | "committed" | "stretch" | "future";
|
||||
risk?: "low" | "normal" | "medium" | "high" | "critical";
|
||||
estimatedScope?: number;
|
||||
releaseBlocking?: boolean;
|
||||
waitingExternal?: boolean;
|
||||
touchedPaths?: string[];
|
||||
domain?: string;
|
||||
deliveryId?: string;
|
||||
dependsOn?: string[];
|
||||
lastResult?: string;
|
||||
lastError?: string;
|
||||
completionEvidence?: string[];
|
||||
supersededBy?: string;
|
||||
};
|
||||
|
||||
export type AutonomyRoadmapPhase = {
|
||||
id: string;
|
||||
title: string;
|
||||
objective: string;
|
||||
status: RoadmapPhaseStatus;
|
||||
brainstormIterations: number;
|
||||
brainstormConverged: boolean;
|
||||
validationFailures: number;
|
||||
items: AutonomyRoadmapItem[];
|
||||
};
|
||||
|
||||
export type AutonomyRoadmap = {
|
||||
id: string;
|
||||
title: string;
|
||||
sourceMarkdown: string;
|
||||
status: "active" | "completed" | "blocked";
|
||||
currentPhaseIndex: number;
|
||||
phases: AutonomyRoadmapPhase[];
|
||||
importedAt: string;
|
||||
completedAt?: string;
|
||||
};
|
||||
|
||||
export type AutonomyLease = {
|
||||
token: string;
|
||||
kind: AutonomyWorkKind;
|
||||
actor: string;
|
||||
runId?: string;
|
||||
roadmapId: string;
|
||||
phaseId: string;
|
||||
itemId?: string;
|
||||
createdAt: string;
|
||||
expiresAt: string;
|
||||
};
|
||||
|
||||
export type AutonomyCompletedLease = {
|
||||
token: string;
|
||||
outcome: AutonomyWorkOutcome;
|
||||
summary: string;
|
||||
addedTasks: string[];
|
||||
completedAt: string;
|
||||
};
|
||||
|
||||
export type AutonomyRun = {
|
||||
id: string;
|
||||
actor: string;
|
||||
startedAt: string;
|
||||
reportedWorkItems: number;
|
||||
};
|
||||
|
||||
export type AutonomyEvent = {
|
||||
id: string;
|
||||
at: string;
|
||||
type: string;
|
||||
actor: string;
|
||||
summary: string;
|
||||
};
|
||||
|
||||
export type AutonomyState = {
|
||||
version: 1;
|
||||
profile: AutonomyProfile;
|
||||
enabled: boolean;
|
||||
status: AutonomyStatus;
|
||||
autoBrainstorm: boolean;
|
||||
maxBrainstormIterations: number;
|
||||
maxConsecutiveFailures: number;
|
||||
leaseMinutes: number;
|
||||
maxWorkItemsPerRun: number;
|
||||
maxRunMinutes: number;
|
||||
pauseAfterCurrent: boolean;
|
||||
schedulingPolicy: "balanced" | "downstream-impact";
|
||||
roadmap?: AutonomyRoadmap;
|
||||
activeLease?: AutonomyLease;
|
||||
blocker?: { at: string; phaseId?: string; itemId?: string; reason: string; kind: "human" | "retryable"; retryAt?: string; recoveryStage?: "retry" | "cooldown" | "alternate_recovery" | "escalated"; recoveryAttempts?: number; recoveryStartedAt?: string };
|
||||
recoveryStartedAt?: string;
|
||||
recoveryAttempts?: number;
|
||||
maxRecoveryMinutes?: number;
|
||||
runs: AutonomyRun[];
|
||||
completedLeases: AutonomyCompletedLease[];
|
||||
events: AutonomyEvent[];
|
||||
updatedAt: string;
|
||||
updatedBy: string;
|
||||
};
|
||||
Reference in new issue
Block a user