|
| 1 | +import { Schema } from "effect"; |
| 2 | +import { |
| 3 | + IsoDateTime, |
| 4 | + NonNegativeInt, |
| 5 | + ProjectId, |
| 6 | + ThreadId, |
| 7 | + TrimmedNonEmptyString, |
| 8 | +} from "./baseSchemas"; |
| 9 | +import { OrchestrationThread, ProviderUserInputAnswers } from "./orchestration"; |
| 10 | +import { |
| 11 | + PrConflictAnalysis, |
| 12 | + PrConflictApplyResult, |
| 13 | + PrReviewConfig, |
| 14 | + PrReviewDashboardResult, |
| 15 | + PrReviewPatchResult, |
| 16 | + PrReviewSummary, |
| 17 | + PrWorkflowStepResolution, |
| 18 | +} from "./prReview"; |
| 19 | + |
| 20 | +export const DECISION_WS_METHODS = { |
| 21 | + listCases: "decision.listCases", |
| 22 | + getWorkspace: "decision.getWorkspace", |
| 23 | + reanalyze: "decision.reanalyze", |
| 24 | + requestConsultation: "decision.requestConsultation", |
| 25 | + respondConsultation: "decision.respondConsultation", |
| 26 | + executeRecommendation: "decision.executeRecommendation", |
| 27 | +} as const; |
| 28 | + |
| 29 | +export const DECISION_WS_CHANNELS = { |
| 30 | + updated: "decision.updated", |
| 31 | +} as const; |
| 32 | + |
| 33 | +export const DecisionCaseId = TrimmedNonEmptyString; |
| 34 | +export type DecisionCaseId = typeof DecisionCaseId.Type; |
| 35 | + |
| 36 | +export const DecisionConsultationId = TrimmedNonEmptyString; |
| 37 | +export type DecisionConsultationId = typeof DecisionConsultationId.Type; |
| 38 | + |
| 39 | +export const DecisionRecommendationId = TrimmedNonEmptyString; |
| 40 | +export type DecisionRecommendationId = typeof DecisionRecommendationId.Type; |
| 41 | + |
| 42 | +export const DecisionSource = Schema.Literals(["pr", "thread", "manual_brief"]); |
| 43 | +export type DecisionSource = typeof DecisionSource.Type; |
| 44 | + |
| 45 | +export const DecisionConflictKind = Schema.Literals([ |
| 46 | + "merge_conflict", |
| 47 | + "workflow_blocker", |
| 48 | + "review_conflict", |
| 49 | + "intent_ambiguity", |
| 50 | + "policy_conflict", |
| 51 | +]); |
| 52 | +export type DecisionConflictKind = typeof DecisionConflictKind.Type; |
| 53 | + |
| 54 | +export const DecisionConsultationTarget = Schema.Literals(["operator", "orchestrator"]); |
| 55 | +export type DecisionConsultationTarget = typeof DecisionConsultationTarget.Type; |
| 56 | + |
| 57 | +export const DecisionConsultationStatus = Schema.Literals([ |
| 58 | + "not_requested", |
| 59 | + "awaiting_operator", |
| 60 | + "awaiting_orchestrator", |
| 61 | + "resolved", |
| 62 | + "superseded", |
| 63 | +]); |
| 64 | +export type DecisionConsultationStatus = typeof DecisionConsultationStatus.Type; |
| 65 | + |
| 66 | +export const DecisionRiskTier = Schema.Literals(["low", "medium", "high"]); |
| 67 | +export type DecisionRiskTier = typeof DecisionRiskTier.Type; |
| 68 | + |
| 69 | +export const DecisionFactorId = Schema.Literals([ |
| 70 | + "contextCompleteness", |
| 71 | + "evidenceQuality", |
| 72 | + "sourceAgreement", |
| 73 | + "policyAlignment", |
| 74 | + "safetyAndReversibility", |
| 75 | + "executionReadiness", |
| 76 | +]); |
| 77 | +export type DecisionFactorId = typeof DecisionFactorId.Type; |
| 78 | + |
| 79 | +export const DecisionEvidenceSource = Schema.Struct({ |
| 80 | + id: TrimmedNonEmptyString, |
| 81 | + label: TrimmedNonEmptyString, |
| 82 | + source: DecisionSource, |
| 83 | + kind: TrimmedNonEmptyString, |
| 84 | + capturedAt: IsoDateTime, |
| 85 | + freshness: Schema.Literals(["fresh", "stale", "derived"]), |
| 86 | + usedInDecision: Schema.Boolean, |
| 87 | +}); |
| 88 | +export type DecisionEvidenceSource = typeof DecisionEvidenceSource.Type; |
| 89 | + |
| 90 | +export const DecisionContextRequirement = Schema.Struct({ |
| 91 | + id: TrimmedNonEmptyString, |
| 92 | + label: TrimmedNonEmptyString, |
| 93 | + satisfied: Schema.Boolean, |
| 94 | + whyItMatters: TrimmedNonEmptyString, |
| 95 | + howToProvideIt: TrimmedNonEmptyString, |
| 96 | + evidenceIds: Schema.Array(TrimmedNonEmptyString), |
| 97 | +}); |
| 98 | +export type DecisionContextRequirement = typeof DecisionContextRequirement.Type; |
| 99 | + |
| 100 | +export const DecisionPrincipleResult = Schema.Struct({ |
| 101 | + id: TrimmedNonEmptyString, |
| 102 | + label: TrimmedNonEmptyString, |
| 103 | + passed: Schema.Boolean, |
| 104 | + blocking: Schema.Boolean, |
| 105 | + rationale: TrimmedNonEmptyString, |
| 106 | + evidenceIds: Schema.Array(TrimmedNonEmptyString), |
| 107 | +}); |
| 108 | +export type DecisionPrincipleResult = typeof DecisionPrincipleResult.Type; |
| 109 | + |
| 110 | +export const DecisionConfidenceFactor = Schema.Struct({ |
| 111 | + id: DecisionFactorId, |
| 112 | + label: TrimmedNonEmptyString, |
| 113 | + score: NonNegativeInt.pipe(Schema.clamp(0, 100)), |
| 114 | + weight: Schema.Number, |
| 115 | + weightedPoints: Schema.Number, |
| 116 | + why: TrimmedNonEmptyString, |
| 117 | + missingInputs: Schema.Array(TrimmedNonEmptyString), |
| 118 | + evidenceIds: Schema.Array(TrimmedNonEmptyString), |
| 119 | +}); |
| 120 | +export type DecisionConfidenceFactor = typeof DecisionConfidenceFactor.Type; |
| 121 | + |
| 122 | +export const DecisionNextContextHint = Schema.Struct({ |
| 123 | + label: TrimmedNonEmptyString, |
| 124 | + whyItMatters: TrimmedNonEmptyString, |
| 125 | + howToProvideIt: TrimmedNonEmptyString, |
| 126 | + estimatedScoreGain: NonNegativeInt, |
| 127 | + appliesTo: Schema.Array(DecisionFactorId), |
| 128 | +}); |
| 129 | +export type DecisionNextContextHint = typeof DecisionNextContextHint.Type; |
| 130 | + |
| 131 | +export const DecisionConfidenceAnalysis = Schema.Struct({ |
| 132 | + score: NonNegativeInt.pipe(Schema.clamp(0, 100)), |
| 133 | + riskTier: DecisionRiskTier, |
| 134 | + autoExecuteEligible: Schema.Boolean, |
| 135 | + scoreDelta: Schema.Int, |
| 136 | + contextCoverageNumerator: NonNegativeInt, |
| 137 | + contextCoverageDenominator: NonNegativeInt, |
| 138 | + sourceAgreementNumerator: NonNegativeInt, |
| 139 | + sourceAgreementDenominator: NonNegativeInt, |
| 140 | + policyPassNumerator: NonNegativeInt, |
| 141 | + policyPassDenominator: NonNegativeInt, |
| 142 | + factors: Schema.Array(DecisionConfidenceFactor), |
| 143 | + nextContextHints: Schema.Array(DecisionNextContextHint), |
| 144 | +}); |
| 145 | +export type DecisionConfidenceAnalysis = typeof DecisionConfidenceAnalysis.Type; |
| 146 | + |
| 147 | +export const DecisionRecommendation = Schema.Struct({ |
| 148 | + id: DecisionRecommendationId, |
| 149 | + label: TrimmedNonEmptyString, |
| 150 | + rationale: TrimmedNonEmptyString, |
| 151 | + executable: Schema.Boolean, |
| 152 | + blockedReason: Schema.NullOr(TrimmedNonEmptyString), |
| 153 | + preview: Schema.String, |
| 154 | + source: DecisionSource, |
| 155 | +}); |
| 156 | +export type DecisionRecommendation = typeof DecisionRecommendation.Type; |
| 157 | + |
| 158 | +export const DecisionConsultationQuestionOption = Schema.Struct({ |
| 159 | + label: TrimmedNonEmptyString, |
| 160 | + description: TrimmedNonEmptyString, |
| 161 | +}); |
| 162 | +export type DecisionConsultationQuestionOption = typeof DecisionConsultationQuestionOption.Type; |
| 163 | + |
| 164 | +export const DecisionConsultationQuestion = Schema.Struct({ |
| 165 | + id: TrimmedNonEmptyString, |
| 166 | + header: TrimmedNonEmptyString, |
| 167 | + question: TrimmedNonEmptyString, |
| 168 | + options: Schema.Array(DecisionConsultationQuestionOption), |
| 169 | +}); |
| 170 | +export type DecisionConsultationQuestion = typeof DecisionConsultationQuestion.Type; |
| 171 | + |
| 172 | +export const DecisionConsultation = Schema.Struct({ |
| 173 | + id: DecisionConsultationId, |
| 174 | + caseId: DecisionCaseId, |
| 175 | + target: DecisionConsultationTarget, |
| 176 | + status: DecisionConsultationStatus, |
| 177 | + reason: TrimmedNonEmptyString, |
| 178 | + questions: Schema.Array(DecisionConsultationQuestion), |
| 179 | + responseSummary: Schema.NullOr(Schema.String), |
| 180 | + linkedThreadId: Schema.NullOr(ThreadId), |
| 181 | + createdAt: IsoDateTime, |
| 182 | + updatedAt: IsoDateTime, |
| 183 | + resolvedAt: Schema.NullOr(IsoDateTime), |
| 184 | +}); |
| 185 | +export type DecisionConsultation = typeof DecisionConsultation.Type; |
| 186 | + |
| 187 | +export const DecisionCaseSummary = Schema.Struct({ |
| 188 | + id: DecisionCaseId, |
| 189 | + projectId: ProjectId, |
| 190 | + cwd: TrimmedNonEmptyString, |
| 191 | + sourceKind: DecisionSource, |
| 192 | + sourceId: TrimmedNonEmptyString, |
| 193 | + title: TrimmedNonEmptyString, |
| 194 | + subtitle: Schema.String, |
| 195 | + conflictKind: DecisionConflictKind, |
| 196 | + score: NonNegativeInt.pipe(Schema.clamp(0, 100)), |
| 197 | + riskTier: DecisionRiskTier, |
| 198 | + consultationStatus: DecisionConsultationStatus, |
| 199 | + updatedAt: IsoDateTime, |
| 200 | +}); |
| 201 | +export type DecisionCaseSummary = typeof DecisionCaseSummary.Type; |
| 202 | + |
| 203 | +export const DecisionContextPack = Schema.Struct({ |
| 204 | + sourceKind: DecisionSource, |
| 205 | + sourceId: TrimmedNonEmptyString, |
| 206 | + prSummary: Schema.optional(PrReviewSummary), |
| 207 | + prDashboard: Schema.optional(PrReviewDashboardResult), |
| 208 | + prPatch: Schema.optional(PrReviewPatchResult), |
| 209 | + prConfig: Schema.optional(PrReviewConfig), |
| 210 | + prConflicts: Schema.optional(PrConflictAnalysis), |
| 211 | + workflowSteps: Schema.optional(Schema.Array(PrWorkflowStepResolution)), |
| 212 | + thread: Schema.optional(OrchestrationThread), |
| 213 | + manualBrief: Schema.optional(Schema.String), |
| 214 | + evidence: Schema.Array(DecisionEvidenceSource), |
| 215 | + contextRequirements: Schema.Array(DecisionContextRequirement), |
| 216 | + linkedThreadId: Schema.NullOr(ThreadId), |
| 217 | +}); |
| 218 | +export type DecisionContextPack = typeof DecisionContextPack.Type; |
| 219 | + |
| 220 | +export const DecisionCase = Schema.Struct({ |
| 221 | + id: DecisionCaseId, |
| 222 | + projectId: ProjectId, |
| 223 | + cwd: TrimmedNonEmptyString, |
| 224 | + sourceKind: DecisionSource, |
| 225 | + sourceId: TrimmedNonEmptyString, |
| 226 | + title: TrimmedNonEmptyString, |
| 227 | + conflictKind: DecisionConflictKind, |
| 228 | + linkedThreadId: Schema.NullOr(ThreadId), |
| 229 | + createdAt: IsoDateTime, |
| 230 | + updatedAt: IsoDateTime, |
| 231 | +}); |
| 232 | +export type DecisionCase = typeof DecisionCase.Type; |
| 233 | + |
| 234 | +export const DecisionWorkspace = Schema.Struct({ |
| 235 | + case: DecisionCase, |
| 236 | + summary: DecisionCaseSummary, |
| 237 | + contextPack: DecisionContextPack, |
| 238 | + principles: Schema.Array(DecisionPrincipleResult), |
| 239 | + confidence: DecisionConfidenceAnalysis, |
| 240 | + recommendations: Schema.Array(DecisionRecommendation), |
| 241 | + consultations: Schema.Array(DecisionConsultation), |
| 242 | +}); |
| 243 | +export type DecisionWorkspace = typeof DecisionWorkspace.Type; |
| 244 | + |
| 245 | +export const DecisionExecutionResult = Schema.Struct({ |
| 246 | + caseId: DecisionCaseId, |
| 247 | + recommendationId: DecisionRecommendationId, |
| 248 | + executed: Schema.Boolean, |
| 249 | + summary: TrimmedNonEmptyString, |
| 250 | + appliedConflictResult: Schema.optional(PrConflictApplyResult), |
| 251 | + updatedAt: IsoDateTime, |
| 252 | +}); |
| 253 | +export type DecisionExecutionResult = typeof DecisionExecutionResult.Type; |
| 254 | + |
| 255 | +export const DecisionListCasesInput = Schema.Struct({ |
| 256 | + cwd: TrimmedNonEmptyString, |
| 257 | + sourceKind: Schema.optional(DecisionSource), |
| 258 | + sourceId: Schema.optional(TrimmedNonEmptyString), |
| 259 | +}); |
| 260 | +export type DecisionListCasesInput = typeof DecisionListCasesInput.Type; |
| 261 | + |
| 262 | +export const DecisionGetWorkspaceInput = Schema.Struct({ |
| 263 | + cwd: TrimmedNonEmptyString, |
| 264 | + caseId: DecisionCaseId, |
| 265 | +}); |
| 266 | +export type DecisionGetWorkspaceInput = typeof DecisionGetWorkspaceInput.Type; |
| 267 | + |
| 268 | +export const DecisionReanalyzeInput = DecisionGetWorkspaceInput; |
| 269 | +export type DecisionReanalyzeInput = typeof DecisionReanalyzeInput.Type; |
| 270 | + |
| 271 | +export const DecisionRequestConsultationInput = Schema.Struct({ |
| 272 | + cwd: TrimmedNonEmptyString, |
| 273 | + caseId: DecisionCaseId, |
| 274 | + target: DecisionConsultationTarget, |
| 275 | + reason: TrimmedNonEmptyString, |
| 276 | + questions: Schema.optional(Schema.Array(DecisionConsultationQuestion)), |
| 277 | +}); |
| 278 | +export type DecisionRequestConsultationInput = typeof DecisionRequestConsultationInput.Type; |
| 279 | + |
| 280 | +export const DecisionRespondConsultationInput = Schema.Struct({ |
| 281 | + cwd: TrimmedNonEmptyString, |
| 282 | + consultationId: DecisionConsultationId, |
| 283 | + answers: ProviderUserInputAnswers, |
| 284 | + resolution: TrimmedNonEmptyString, |
| 285 | +}); |
| 286 | +export type DecisionRespondConsultationInput = typeof DecisionRespondConsultationInput.Type; |
| 287 | + |
| 288 | +export const DecisionExecuteRecommendationInput = Schema.Struct({ |
| 289 | + cwd: TrimmedNonEmptyString, |
| 290 | + caseId: DecisionCaseId, |
| 291 | + recommendationId: DecisionRecommendationId, |
| 292 | +}); |
| 293 | +export type DecisionExecuteRecommendationInput = typeof DecisionExecuteRecommendationInput.Type; |
| 294 | + |
| 295 | +export const DecisionUpdatedPayload = Schema.Struct({ |
| 296 | + cwd: TrimmedNonEmptyString, |
| 297 | + caseId: DecisionCaseId, |
| 298 | + updatedAt: IsoDateTime, |
| 299 | +}); |
| 300 | +export type DecisionUpdatedPayload = typeof DecisionUpdatedPayload.Type; |
0 commit comments