474 lines
13 KiB
TypeScript
474 lines
13 KiB
TypeScript
export const PROFILE_ROLES = [
|
|
"discover",
|
|
"design",
|
|
"prototype",
|
|
"implement",
|
|
"verify",
|
|
"review",
|
|
] as const;
|
|
|
|
export type ProfileRole = (typeof PROFILE_ROLES)[number];
|
|
export type AssignmentStageKind = ProfileRole;
|
|
export type WorkflowStageKind =
|
|
| "initialize"
|
|
| AssignmentStageKind
|
|
| "remediate"
|
|
| "complete"
|
|
| `custom:${string}`;
|
|
|
|
export const REASONING_EFFORTS = [
|
|
"off",
|
|
"minimal",
|
|
"low",
|
|
"medium",
|
|
"high",
|
|
"xhigh",
|
|
"max",
|
|
] as const;
|
|
|
|
export type ReasoningEffort = (typeof REASONING_EFFORTS)[number];
|
|
|
|
export interface ProfileSelection {
|
|
stages: AssignmentStageKind[];
|
|
anyTags: string[];
|
|
allTags: string[];
|
|
pathGlobs: string[];
|
|
keywords: string[];
|
|
}
|
|
|
|
export interface AgentProfile {
|
|
name: string;
|
|
description: string;
|
|
roles: ProfileRole[];
|
|
model?: string;
|
|
provider?: string;
|
|
effort?: ReasoningEffort;
|
|
tools?: string[];
|
|
selection: ProfileSelection;
|
|
instructions: string;
|
|
source: "bundled" | "project";
|
|
sourcePath: string;
|
|
resolvedPath: string;
|
|
digest: string;
|
|
}
|
|
|
|
export interface ProfileDiagnostic {
|
|
sourcePath: string;
|
|
severity: "warning" | "error";
|
|
message: string;
|
|
}
|
|
|
|
export interface ProfileCatalog {
|
|
profiles: AgentProfile[];
|
|
diagnostics: ProfileDiagnostic[];
|
|
}
|
|
|
|
export interface WorkflowFacts {
|
|
stage: AssignmentStageKind;
|
|
taskKind: "feature" | "analysis";
|
|
requestTerms: string[];
|
|
candidatePaths: string[];
|
|
languages: string[];
|
|
tags: string[];
|
|
riskTags: string[];
|
|
}
|
|
|
|
export interface EligibilityResult {
|
|
profile: AgentProfile;
|
|
eligible: boolean;
|
|
reasons: string[];
|
|
specificity: number;
|
|
}
|
|
|
|
export type RunStatus =
|
|
| "running"
|
|
| "waiting"
|
|
| "completed"
|
|
| "failed"
|
|
| "aborted";
|
|
export type AssignmentStatus =
|
|
| "queued"
|
|
| "running"
|
|
| "succeeded"
|
|
| "failed"
|
|
| "interrupted";
|
|
export type StageStatus =
|
|
| "pending"
|
|
| "running"
|
|
| "waiting"
|
|
| "completed"
|
|
| "failed";
|
|
export type GateKind =
|
|
| "questions"
|
|
| "plan-approval"
|
|
| "prototype-acceptance"
|
|
| "implementation-context"
|
|
| "recovery";
|
|
export type UiImpact = "none" | "minor" | "non-trivial";
|
|
|
|
export type GateDecision =
|
|
| { kind: "answer-questions"; answers: Record<string, string> }
|
|
| {
|
|
kind: "approve-plan";
|
|
approved: true;
|
|
acceptedUiImpact: UiImpact;
|
|
comment?: string;
|
|
}
|
|
| { kind: "revise-plan"; feedback: string }
|
|
| {
|
|
kind: "accept-prototype";
|
|
candidateId: string;
|
|
candidateRevision: number;
|
|
browserReviewed: true;
|
|
feedback?: string;
|
|
}
|
|
| { kind: "refine-prototypes"; feedback: string }
|
|
| {
|
|
kind: "select-implementation-context";
|
|
strategy:
|
|
| "fresh-session"
|
|
| "smart-compact"
|
|
| "current-session";
|
|
}
|
|
| {
|
|
kind: "report-context-preparation";
|
|
preparationId: string;
|
|
planRevision: number;
|
|
method: "smart_compact";
|
|
outcome: "unavailable" | "succeeded" | "no-op";
|
|
}
|
|
| {
|
|
kind: "report-context-preparation";
|
|
preparationId: string;
|
|
planRevision: number;
|
|
method: "smart_compact";
|
|
outcome: "failed";
|
|
error: string;
|
|
}
|
|
| { kind: "recover"; resolution: "retry" | "inspect" | "abort" };
|
|
|
|
export interface RunLease {
|
|
processId: number;
|
|
activeParentSessionId: string;
|
|
heartbeatAt: number;
|
|
worktreeIdentity?: string;
|
|
}
|
|
|
|
export interface SourceChangeEvidence {
|
|
path: string;
|
|
status: string;
|
|
}
|
|
|
|
export interface WorkflowWorkspace {
|
|
state: "not-required" | "creating" | "ready" | "failed";
|
|
sourceRoot: string;
|
|
root?: string;
|
|
branch?: string;
|
|
baseHead?: string;
|
|
sourceChanges?: SourceChangeEvidence[];
|
|
sourceChangesOmitted?: number;
|
|
dirtySourceAllowed?: boolean;
|
|
error?: string;
|
|
}
|
|
|
|
export interface WorkflowStage {
|
|
id: string;
|
|
kind: WorkflowStageKind;
|
|
status: StageStatus;
|
|
startedAt?: number;
|
|
finishedAt?: number;
|
|
output?: unknown;
|
|
}
|
|
|
|
export interface WorkflowGate {
|
|
id: string;
|
|
kind: GateKind;
|
|
status: "open" | "satisfied" | "rejected";
|
|
revision: number;
|
|
openedAt: number;
|
|
payload?: unknown;
|
|
}
|
|
|
|
export interface WorkflowDecision {
|
|
gateId: string;
|
|
revision: number;
|
|
idempotencyKey: string;
|
|
decidedAt: number;
|
|
value: GateDecision;
|
|
}
|
|
|
|
export interface ProfileSelectionEvidence {
|
|
profileName: string;
|
|
profileDigest: string;
|
|
eligible: boolean;
|
|
reasons: string[];
|
|
specificity: number;
|
|
}
|
|
|
|
export interface AssignmentSelection {
|
|
eligibleProfiles: ProfileSelectionEvidence[];
|
|
selectedProfileName: string;
|
|
rationale: string;
|
|
}
|
|
|
|
export interface StageEligibilityEvidence {
|
|
role: ProfileRole;
|
|
candidates: ProfileSelectionEvidence[];
|
|
}
|
|
|
|
export interface AssignmentTranscriptArtifact {
|
|
path: string;
|
|
digest: string;
|
|
}
|
|
|
|
export interface AssignmentGitState {
|
|
root: string;
|
|
branch: string;
|
|
head: string;
|
|
commonDirectory: string;
|
|
gitDirectory: string;
|
|
worktreeListDigest: string;
|
|
worktreeMetadataDigest: string;
|
|
status: string;
|
|
changedPaths: string[];
|
|
pathStatuses: Record<string, string>;
|
|
pathDigests: Record<string, string>;
|
|
}
|
|
|
|
export interface VerificationCommand {
|
|
id: string;
|
|
executable: string;
|
|
args: string[];
|
|
ownedPaths: string[];
|
|
kind: "test" | "typecheck" | "lint" | "build" | "browser" | "generation";
|
|
status:
|
|
| "pending"
|
|
| "running"
|
|
| "succeeded"
|
|
| "failed"
|
|
| "interrupted"
|
|
| "superseded";
|
|
exitCode?: number;
|
|
stdout?: string;
|
|
stderr?: string;
|
|
error?: string;
|
|
}
|
|
|
|
export interface VerificationEvidence {
|
|
commands: VerificationCommand[];
|
|
focusedBehavioralTests: boolean;
|
|
verifierSucceeded: boolean;
|
|
}
|
|
|
|
export interface ReviewAxis {
|
|
verdict: "approved" | "changes_requested";
|
|
findings: Array<{ severity: string; message: string; path?: string }>;
|
|
}
|
|
|
|
export interface ReviewVerdict {
|
|
specification: ReviewAxis;
|
|
standards: ReviewAxis;
|
|
}
|
|
|
|
export interface WorkflowAssignment {
|
|
id: string;
|
|
stageId: string;
|
|
role: ProfileRole | "remediate";
|
|
profileName: string;
|
|
profileDigest: string;
|
|
selection: AssignmentSelection;
|
|
status: AssignmentStatus;
|
|
mutates: boolean;
|
|
ownedPaths: string[];
|
|
scriptRequestId?: number;
|
|
scriptRequestFingerprint?: string;
|
|
executionToken?: string;
|
|
childSessionId?: string;
|
|
effectiveProvider?: string;
|
|
effectiveModel?: string;
|
|
effectiveEffort?: string;
|
|
contextCapacity?: number;
|
|
transcriptArtifact?: AssignmentTranscriptArtifact;
|
|
gitBefore?: AssignmentGitState;
|
|
gitAfter?: AssignmentGitState;
|
|
result?: unknown;
|
|
error?: string;
|
|
}
|
|
|
|
export interface PrototypeCandidate {
|
|
id: string;
|
|
revision: number;
|
|
assignmentId: string;
|
|
profileName: string;
|
|
status: "succeeded";
|
|
path: string;
|
|
route: string;
|
|
structuralRationale: string;
|
|
responsiveChecks: string[];
|
|
browserEvidence: string[];
|
|
launchInstructions: string;
|
|
visualDigest: string;
|
|
artifactPath: string;
|
|
retainedArtifacts: string[];
|
|
}
|
|
|
|
export interface DeliveryRecord {
|
|
key: string;
|
|
state: "pending" | "sent";
|
|
createdAt: number;
|
|
sentAt?: number;
|
|
}
|
|
|
|
export interface WorkflowReportArtifact {
|
|
path: string;
|
|
digest: string;
|
|
revision: number;
|
|
}
|
|
|
|
export interface PlanArtifact {
|
|
path: string;
|
|
revision: number;
|
|
digest: string;
|
|
}
|
|
|
|
export interface ImplementationContextState {
|
|
gateId: string;
|
|
runRevision: number;
|
|
planRevision: number;
|
|
preparationId: string;
|
|
activeParentSessionId: string;
|
|
sourceParentSessionId?: string;
|
|
sourceSessionFile?: string;
|
|
targetSessionFile?: string;
|
|
claimedAt?: number;
|
|
intentCreatedAt?: number;
|
|
intentExpiresAt?: number;
|
|
strategy?: "fresh-session" | "smart-compact" | "current-session";
|
|
status:
|
|
| "waiting"
|
|
| "handoff-pending"
|
|
| "claimed-target-awaiting-withSession"
|
|
| "smart-compact-pending"
|
|
| "normal-compact-pending"
|
|
| "normal-compact-running"
|
|
| "ready"
|
|
| "failed";
|
|
method?:
|
|
| "fresh-session"
|
|
| "smart_compact"
|
|
| "normal-compact"
|
|
| "unchanged";
|
|
outcome?: "unavailable" | "succeeded" | "no-op" | "failed";
|
|
error?: string;
|
|
}
|
|
|
|
export interface WorkflowError {
|
|
code: string;
|
|
message: string;
|
|
stageId?: string;
|
|
assignmentId?: string;
|
|
}
|
|
|
|
export type CommandContinuation =
|
|
| "none"
|
|
| "design"
|
|
| "prototype"
|
|
| "implementation"
|
|
| "recovery";
|
|
|
|
export interface CommandReceipt {
|
|
key: string;
|
|
action: "decide" | "abort";
|
|
fingerprint: string;
|
|
status: "pending" | "completed";
|
|
acceptedRevision: number;
|
|
continuation?: CommandContinuation;
|
|
result?: unknown;
|
|
}
|
|
|
|
export type FeatureScriptInsertionPoint =
|
|
| "before-design"
|
|
| "after-design"
|
|
| "before-review";
|
|
|
|
export interface WorkflowScriptState {
|
|
source: string;
|
|
args?: unknown;
|
|
insertionPoint?: FeatureScriptInsertionPoint;
|
|
activeToolNames: string[];
|
|
status: "pending" | "running" | "completed" | "failed";
|
|
stages: string[];
|
|
executed: boolean;
|
|
result?: unknown;
|
|
error?: string;
|
|
}
|
|
|
|
export interface WorkflowRun {
|
|
runId: string;
|
|
revision: number;
|
|
mode: "feature" | "analysis";
|
|
script?: WorkflowScriptState;
|
|
status: RunStatus;
|
|
background: boolean;
|
|
request: string;
|
|
featureName?: string;
|
|
parentSessionIds: string[];
|
|
planArtifact?: PlanArtifact;
|
|
reportArtifact?: WorkflowReportArtifact;
|
|
implementationContext?: ImplementationContextState;
|
|
lease?: RunLease;
|
|
workspace: WorkflowWorkspace;
|
|
effectiveConfig: WorkflowConfig;
|
|
pinnedProfiles: AgentProfile[];
|
|
preflightEligibility: StageEligibilityEvidence[];
|
|
facts: WorkflowFacts;
|
|
stages: WorkflowStage[];
|
|
gates: WorkflowGate[];
|
|
decisions: WorkflowDecision[];
|
|
assignments: WorkflowAssignment[];
|
|
prototypeCandidates: PrototypeCandidate[];
|
|
prototypeCleanupCompleted: boolean;
|
|
deliveries: DeliveryRecord[];
|
|
commandReceipts: CommandReceipt[];
|
|
uiImpact?: UiImpact;
|
|
uiImpactEvidence: string[];
|
|
affectedUiSurfaces: string[];
|
|
mutatorProfileNames: string[];
|
|
reviewCycles: number;
|
|
verificationCycles: number;
|
|
verificationEvidence?: VerificationEvidence;
|
|
reviewVerdict?: ReviewVerdict;
|
|
error?: WorkflowError;
|
|
}
|
|
|
|
export const ANALYSIS_TOOL_ALLOWLIST = ["read", "grep", "find", "ls"] as const;
|
|
export const MAX_CONCURRENCY = 32;
|
|
export const MAX_ASSIGNMENTS_PER_RUN = 1_024;
|
|
export const MAX_REVIEW_CYCLES = 20;
|
|
|
|
export interface WorkflowConfig {
|
|
concurrency: {
|
|
default: number;
|
|
ceiling: number;
|
|
};
|
|
maxAssignmentsPerRun: number;
|
|
maxReviewCycles: number;
|
|
analysisTools: string[];
|
|
worktrees: {
|
|
root: string;
|
|
};
|
|
}
|
|
|
|
export const DEFAULT_WORKFLOW_CONFIG: WorkflowConfig = {
|
|
concurrency: {
|
|
default: 8,
|
|
ceiling: MAX_CONCURRENCY,
|
|
},
|
|
maxAssignmentsPerRun: 128,
|
|
maxReviewCycles: 3,
|
|
analysisTools: [...ANALYSIS_TOOL_ALLOWLIST],
|
|
worktrees: {
|
|
root: ".worktrees",
|
|
},
|
|
};
|