import type { WorkOrder } from "./prompts.js"; import type { BackendWorkUnit, ChecklistItem, ContractAmendment, CoverageChecklist, DomainMoveCandidate, EventHandlerLocation, OpenApiChange, ScenarioSlice, TestRun, VerticalSlice } from "./types.js"; /** * The backend agent: work classification, B1 use-case loop, domain * distillation, event handlers, the persistence ripple's agent-side * steps, B2 equivalence tests, and controller wiring. Each * model-performing method receives its instructions as order.prompt; * methods without an order are executors. During the fan-out, any * method may throw ContractGapDiscovered. */ export interface BackendAgent { /** * Open a FRESH backend lane conversation for a new slice. The backend's * constructive steps within a slice share one (model-aware) persistent * session; resetLane clears it at each slice boundary. Called by the * orchestrator at the start of every slice's backend work. */ resetLane(): void; receiveRunInstructions(instructions: readonly string[]): Promise; /** * The AI decision that opens the backend fan-out: WHICH backend units * does this slice need, each classified as one of the four kinds * (command / query / event-built query / standalone event handler) * and assigned to its owning bounded context. Everything the * algorithm does with the answer is deterministic dispatch on kind * (see backend-work.ts). Ambiguity is decided (most defensible kind) * and reported as a loud DILEMMA — runs are unsupervised. */ classifyBackendWork(order: WorkOrder, slice: ScenarioSlice): Promise; /** Request-driven units only (command or query — order.kind tells which). */ findOrCreateUseCase(order: WorkOrder, slice: ScenarioSlice, unit: BackendWorkUnit, template: VerticalSlice): Promise; /** * The concrete B1 exit condition: business rules plus one * infrastructure-failure item per repository/projection method the * interactor calls. On re-entry after an amendment, items keep the * covered status applyContractChange left them with. */ buildUseCaseChecklist(order: WorkOrder, slice: ScenarioSlice, unit: BackendWorkUnit): Promise; /** * TDD mode: write JUST the item's unit test (revised if it passes * prematurely). Resolves to the EXACT title of the test written — the * loop records it on the item so execution filters by title, and a * test never actually added reads as "no tests found", not as a pass. */ writeUseCaseTest(order: WorkOrder, item: ChecklistItem): Promise; /** * TDD mode: the fresh test passed BEFORE any implementation step. * Judge which explanation holds — the behavior is already implemented * (returns true: the pass is legitimate, the item is covered) or the * test is vacuous (returns false: rewrite it). Shared by the use-case * and event-handler loops. */ judgeItemAlreadyImplemented(order: WorkOrder, item: ChecklistItem): Promise; /** TDD mode: the minimum code that turns the observed-red test green. */ writeCodeToPassUseCaseTest(order: WorkOrder, item: ChecklistItem): Promise; /** * Basic mode: the item's test and minimum code in one step. Resolves * to the written test's exact title (see writeUseCaseTest). */ writeUseCaseTestAndCodeTogether(order: WorkOrder, item: ChecklistItem): Promise; /** Execute one item's unit test (in-memory, always local). */ runUseCaseTest(item: ChecklistItem): Promise; /** Create the three-file anatomy at the location and register it in Application. */ findOrCreateEventHandler(order: WorkOrder, slice: ScenarioSlice, unit: BackendWorkUnit, location: EventHandlerLocation): Promise; /** * The handler loop's exit condition: the reaction's behaviors, one * unparseable-payload case per subscribed event, and ONE at-least-once * delivery case (same event twice — no duplicated effect, or the * documented accepted trade). */ buildEventHandlerChecklist(order: WorkOrder, slice: ScenarioSlice, unit: BackendWorkUnit): Promise; /** * TDD mode: write JUST the item's handler test (revised if it passes * prematurely). Resolves to the written test's exact title (see * writeUseCaseTest). */ writeEventHandlerTest(order: WorkOrder, item: ChecklistItem): Promise; /** TDD mode: the minimum handler code that turns the observed-red test green. */ writeCodeToPassEventHandlerTest(order: WorkOrder, item: ChecklistItem): Promise; /** * Basic mode: the item's test and minimum handler code in one step. * Resolves to the written test's exact title (see writeUseCaseTest). */ writeEventHandlerTestAndCodeTogether(order: WorkOrder, item: ChecklistItem): Promise; /** Execute one item's handler test (in-memory, always local). */ runEventHandlerTest(item: ChecklistItem): Promise; /** Distillation step 1: list the interactor's imperative domain-language logic. */ findDomainMoveCandidates(order: WorkOrder, slice: ScenarioSlice, unit: BackendWorkUnit): Promise; /** Distillation step 2: one behavior-preserving move into the domain. */ moveLogicIntoDomain(order: WorkOrder, candidate: DomainMoveCandidate): Promise; /** * The loop's exit condition: for each domain object the slice created * or extended, the object's OWN contract — validation rules, boundary * values, state-transition guards, events emitted — EXCLUDING * behaviors the use-case tests already prove. */ buildDomainUnitChecklist(order: WorkOrder, slice: ScenarioSlice, unit: BackendWorkUnit): Promise; /** * One cycle: write the item's test against the object's public API * (its front door — no mocks, no Application) and run it. A red run * exposed a real domain defect: the fix goes into the domain, never * into the test. */ nextDomainUnitTestCycle(order: WorkOrder, item: ChecklistItem): Promise; /** Absorb an amendment; un-cover every checklist item it invalidates. */ applyContractChange(order: WorkOrder, contract: OpenApiChange, amendments: readonly ContractAmendment[]): Promise; /** Step 1: read the touched aggregates' snapshots, extending minimally. */ reviewSnapshots(order: WorkOrder, slice: ScenarioSlice): Promise; /** Step 2: the repository/projection methods the use case needs (empty = none). */ determineRepositoryMethodsNeeded(order: WorkOrder, slice: ScenarioSlice): Promise; /** Step 3: does the persisted schema change for the final domain shape? */ determineSchemaChangeNeeded(order: WorkOrder, slice: ScenarioSlice): Promise; /** Step 4: the minimal schema-file change. */ updateSchema(order: WorkOrder): Promise; /** Step 7: write/update the SQL queries for exactly the step-2 methods. */ writeOrUpdateQueries(order: WorkOrder, methods: string[]): Promise; /** After generation: both repositories, each in-memory method WITH its error seam. */ implementRepositoryMethods(order: WorkOrder, methods: string[]): Promise; /** The concrete B2 exit condition: repository behaviors to prove equivalent. */ buildRepoEquivalenceChecklist(order: WorkOrder, slice: ScenarioSlice): Promise; /** One B2 cycle: a fake-vs-Postgres comparison test for the item. */ nextRepoEquivalenceTestCycle(order: WorkOrder, item: ChecklistItem): Promise; /** Request-driven units only — a standalone event handler has no route. */ wireEndpointToUseCase(order: WorkOrder, contract: OpenApiChange, unit: BackendWorkUnit): Promise; runUnitSuite(): Promise; runIntegrationSuite(): Promise; /** Localize and fix the actual cause of a red suite — never weaken a test. */ fixFailingSuite(order: WorkOrder, run: TestRun): Promise; }