The Atlas Lavern's documentation, bound to its code
111 documents

How the engine works

From the prescriptive architecture to the actual dispatch loop: the 4-stage pipeline as designed, then the code that runs engagements.

src/dispatch.ts121 lines · dispatch L51–120
Outline 2 symbols
1/**
2 * Dispatch — The top-level entry point for The Shem.
3 *
4 * Flow:
5 * 1. Create session
6 * 2. Route request (LLM or deterministic, or use forceWorkflow override)
7 * 3. Look up the workflow template from the registry
8 * 4. Run runGenericWorkflow() with the selected template
9 *
10 * v11: The legacy runTheShem() backward compat path is sunset.
11 * All workflows go through runGenericWorkflow(). Eight workflow templates:
12 * counsel, review, adversarial, roundtable, full-bench, legal-design,
13 * pre-engagement, verification.
14 */
15
16import { type SchemOptions } from './orchestrator.js';
17import { runGenericWorkflow } from './workflows/executor.js';
18import { routeRequest } from './router/router.js';
19import { workflowRegistry } from './workflows/registry.js';
20import { SessionState } from './session/session-state.js';
21import type { LegalRequest } from './types/index.js';
22import type { GateResolver } from './gates/gate-resolver.js';
23import { type IntensityLevel, effortForIntensity } from './types/engagement.js';
24
25// Ensure templates are registered
26import './workflows/index.js';
27
28export interface DispatchOptions extends SchemOptions {
29 /** Force a specific workflow template instead of routing */
30 forceWorkflow?: string;
31 /** Use LLM-based routing (default: true). Set to false for deterministic-only. */
32 useLlmRouter?: boolean;
33 /** Model to use for LLM routing (default: claude-sonnet-4-5) */
34 routerModel?: string;
35 /** v8: Skip pre-engagement workflow (for backward compat or when matter already exists) */
36 skipPreEngagement?: boolean;
37 /** v8: Matter ID — loads the matter's selected team into the session */
38 matterId?: string;
39 /** v9: Engagement intensity level — controls team size, gate frequency, budget */
40 intensity?: IntensityLevel;
41 /** v9: YOLO mode — auto-approve all gates, fully automated */
42 yoloMode?: boolean;
43}
44
45/**
46 * Dispatch a legal request through the appropriate workflow.
47 *
48 * This is the universal entry point. It routes the request,
49 * selects the workflow, and runs it.
50 */
51export async function dispatch(
52 request: LegalRequest,
53 options: DispatchOptions = {},
54): Promise<SessionState> {
55 // Clone options to avoid mutating the caller's object
56 const opts = { ...options };
57
58 // Create session
59 const session = opts.session ?? new SessionState(undefined, {
60 gateResolver: opts.gateResolver,
61 budgetUsd: opts.maxBudgetUsd,
62 });
63
64 // v18: Store provider on session for per-session override
65 if (opts.provider) {
66 session.provider = opts.provider;
67 }
68
69 // v8: Matter data (including selectedTeam) is pre-loaded on the session by
70 // the API layer when a matterId is provided. The executor reads session.selectedTeam.
71
72 // v10: Resolve effort — explicit effort wins, otherwise derive from intensity
73 if (!opts.effort && opts.intensity) {
74 opts.effort = effortForIntensity(opts.intensity);
75 }
76
77 // Route request (or use forced workflow)
78 let workflowId: string;
79
80 if (opts.forceWorkflow) {
81 // Forced workflow — skip routing
82 workflowId = opts.forceWorkflow;
83 request.routerClassification = {
84 requestType: 'full_pipeline',
85 complexity: 'medium',
86 riskLevel: 'medium',
87 selectedWorkflow: workflowId,
88 selectedSpecialists: [],
89 requiresDebate: false,
90 requiresEthicsFirst: false,
91 requiresConsistencyCheck: false,
92 reasoning: `Workflow forced by user: ${workflowId}`,
93 };
94 } else {
95 // Normal routing (LLM or deterministic)
96 const classification = await routeRequest(request, session, {
97 useLlm: opts.useLlmRouter ?? true,
98 model: opts.routerModel,
99 provider: opts.provider,
100 });
101 workflowId = classification.selectedWorkflow;
102 }
103
104 // v11: All patterns (including roundtable, formerly legal-design) run through
105 // runGenericWorkflow(). No special-case paths.
106
107 // Look up template from registry
108 const template = workflowRegistry.get(workflowId);
109 if (!template) {
110 throw new Error(`Unknown workflow template: ${workflowId}. Available: ${workflowRegistry.list().map(t => t.id).join(', ')}`);
111 }
112
113 const classification = request.routerClassification;
114 if (!classification) {
115 throw new Error('Router classification missing after routing — cannot dispatch workflow');
116 }
117 session.workflowTemplateId = template.id;
118
119 return runGenericWorkflow(request, template, classification, session, opts);
120}
121