Skip to content

Commit 39aecae

Browse files
wow-mileyclaude
andauthored
Replace escalation lookup with enum in TicketOrchestrator (#7)
* Refactor escalation lookup to use EscalationKeyword enum Replace string-based keyword matching in TicketOrchestrator's blockerNeedsMeeting and blockerNeedsHuman with type-safe enum. This improves maintainability and allows keywords to specify both meeting and human involvement requirements. * Replace EscalationKeyword with Escalation sealed class hierarchy Introduce a proper domain model for escalation types: - EscalationProcess: Defines resolution mechanisms (AgentMeeting, HumanApproval, HumanMeeting, ExternalDependency) - Escalation: Sealed class hierarchy with Discussion, Decision, Budget, Priorities, Scope, and External categories Each escalation type defines its process, making the model suitable for LLM classification instead of keyword matching. The TicketOrchestrator now accepts an optional Escalation type to determine meeting and participant requirements. * Fix TicketMeetingIntegrationTest to use Escalation types Update tests to pass explicit Escalation types instead of relying on keyword matching, which was removed in the previous commit. * Refactor orchestrator dependencies with EnvironmentOrchestrator (#5) Remove direct MeetingOrchestrator dependency from TicketOrchestrator to enable bidirectional communication between orchestrators. - Add MeetingSchedulingService functional interface for decoupling - Create EnvironmentOrchestrator to manage Meeting/Ticket/Event orchestrators - Update TicketOrchestrator to use MeetingSchedulingService - Update tests to use new architecture This allows orchestrators to call each other through the parent EnvironmentOrchestrator without circular dependencies. Co-authored-by: Claude <noreply@anthropic.com> * Finish renaming to Ampere, add basic CLI (#9) * Refactor escalation lookup to use EscalationKeyword enum Replace string-based keyword matching in TicketOrchestrator's blockerNeedsMeeting and blockerNeedsHuman with type-safe enum. This improves maintainability and allows keywords to specify both meeting and human involvement requirements. * Replace EscalationKeyword with Escalation sealed class hierarchy Introduce a proper domain model for escalation types: - EscalationProcess: Defines resolution mechanisms (AgentMeeting, HumanApproval, HumanMeeting, ExternalDependency) - Escalation: Sealed class hierarchy with Discussion, Decision, Budget, Priorities, Scope, and External categories Each escalation type defines its process, making the model suitable for LLM classification instead of keyword matching. The TicketOrchestrator now accepts an optional Escalation type to determine meeting and participant requirements. * Fix typo * Replace EscalationKeyword with Agent-based classification using AgentDescribable interface * Refactor escalation lookup to use EscalationKeyword enum Replace string-based keyword matching in TicketOrchestrator's blockerNeedsMeeting and blockerNeedsHuman with type-safe enum. This improves maintainability and allows keywords to specify both meeting and human involvement requirements. * Replace EscalationKeyword with Escalation sealed class hierarchy Introduce a proper domain model for escalation types: - EscalationProcess: Defines resolution mechanisms (AgentMeeting, HumanApproval, HumanMeeting, ExternalDependency) - Escalation: Sealed class hierarchy with Discussion, Decision, Budget, Priorities, Scope, and External categories Each escalation type defines its process, making the model suitable for LLM classification instead of keyword matching. The TicketOrchestrator now accepts an optional Escalation type to determine meeting and participant requirements. * Fix TicketMeetingIntegrationTest to use Escalation types Update tests to pass explicit Escalation types instead of relying on keyword matching, which was removed in the previous commit. * Finish renaming to Ampere, add basic CLI (#9) --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 279e3cd commit 39aecae

11 files changed

Lines changed: 1096 additions & 63 deletions

File tree

ampere-cli/src/jvmMain/kotlin/link/socket/ampere/Main.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class AmpereCommand : CliktCommand(
1212
help = """
1313
Animated Multi-Agent (Prompting Technique) -> AniMA
1414
AniMA Model Protocol -> AMP
15-
AMP Environment Runtime Example -> AMPERE
15+
AMP Example Runtime Environment -> AMPERE
1616
1717
AMPERE is a tool for running AniMA simulations in a real-time, observable environment.
1818
""".trimIndent()

ampere-cli/src/jvmMain/kotlin/link/socket/ampere/WatchCommand.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import com.github.ajalt.clikt.core.CliktCommand
44
import com.github.ajalt.clikt.parameters.options.default
55
import com.github.ajalt.clikt.parameters.options.option
66
import com.github.ajalt.clikt.parameters.types.int
7-
import com.github.ajalt.mordant.rendering.TextColors.*
8-
import com.github.ajalt.mordant.rendering.TextStyles.*
7+
import com.github.ajalt.mordant.rendering.TextColors.cyan
8+
import com.github.ajalt.mordant.rendering.TextColors.yellow
9+
import com.github.ajalt.mordant.rendering.TextStyles.bold
10+
import com.github.ajalt.mordant.rendering.TextStyles.dim
911
import com.github.ajalt.mordant.terminal.Terminal
1012

1113
class WatchCommand : CliktCommand(
@@ -51,7 +53,7 @@ class WatchCommand : CliktCommand(
5153

5254
override fun run() {
5355
terminal.println(
54-
bold(cyan("AMPERE")) + " - AniMA Perception & Relay Environment"
56+
bold(cyan("AMPERE")) + " - AniMA Model Protocol Example Runtime Environment"
5557
)
5658
terminal.println(dim("Connecting to event stream..."))
5759
terminal.println()
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
package link.socket.ampere.agents.events.tickets
2+
3+
import link.socket.ampere.domain.agent.AgentDescribable
4+
import link.socket.ampere.domain.agent.AgentTypeDescriber
5+
6+
/**
7+
* Represents the type of escalation needed for a blocker.
8+
* Each escalation type defines what kind of issue it is and how it should be resolved.
9+
*
10+
* This hierarchy is designed to be used with LLM classification - an LLM analyzes
11+
* a blocker scenario and categorizes it into the appropriate escalation type.
12+
*/
13+
sealed class Escalation : AgentDescribable {
14+
15+
/**
16+
* The process mechanism used to resolve this type of escalation.
17+
*/
18+
abstract val escalationProcess: EscalationProcess
19+
20+
/**
21+
* Human-readable description of this escalation type for LLM context.
22+
*/
23+
abstract override val description: String
24+
25+
override fun describeProperties(): Map<String, String> = mapOf(
26+
"escalationProcess" to escalationProcess.typeName
27+
)
28+
29+
// ==================== Discussion Escalations ====================
30+
31+
/**
32+
* Escalations that require collaborative discussion to resolve.
33+
* These typically involve technical topics where multiple perspectives
34+
* help reach a better solution.
35+
*/
36+
sealed class Discussion : Escalation() {
37+
38+
/**
39+
* Code needs review before proceeding.
40+
* Includes pull requests, implementation approaches, and code quality concerns.
41+
*/
42+
data object CodeReview : Discussion() {
43+
override val escalationProcess = EscalationProcess.AgentMeeting
44+
override val description = "Code needs review - includes PRs, implementation approaches, and quality concerns"
45+
}
46+
47+
/**
48+
* Design decisions need discussion.
49+
* Includes UI/UX design, API design, and system design choices.
50+
*/
51+
data object Design : Discussion() {
52+
override val escalationProcess = EscalationProcess.AgentMeeting
53+
override val description = "Design decisions needed - UI/UX, API design, or system design choices"
54+
}
55+
56+
/**
57+
* Architecture questions need clarification.
58+
* Includes system structure, component relationships, and technical patterns.
59+
*/
60+
data object Architecture : Discussion() {
61+
override val escalationProcess = EscalationProcess.AgentMeeting
62+
override val description = "Architecture clarification needed - system structure, components, or patterns"
63+
}
64+
65+
/**
66+
* Requirements need clarification or refinement.
67+
* Includes unclear specifications, missing details, or conflicting requirements.
68+
*/
69+
data object Requirements : Discussion() {
70+
override val escalationProcess = EscalationProcess.HumanMeeting
71+
override val description = "Requirements clarification needed - unclear specs, missing details, or conflicts"
72+
}
73+
}
74+
75+
// ==================== Decision Escalations ====================
76+
77+
/**
78+
* Escalations that require a decision to be made.
79+
* These block progress until someone with authority makes a choice.
80+
*/
81+
sealed class Decision : Escalation() {
82+
83+
/**
84+
* Technical decision needed between alternatives.
85+
* Includes technology choices, library selection, and implementation strategies.
86+
*/
87+
data object Technical : Decision() {
88+
override val escalationProcess = EscalationProcess.AgentMeeting
89+
override val description = "Technical decision needed - technology choices, libraries, or implementation strategies"
90+
}
91+
92+
/**
93+
* Product decision needed from stakeholders.
94+
* Includes feature direction, user experience choices, and business logic decisions.
95+
*/
96+
data object Product : Decision() {
97+
override val escalationProcess = EscalationProcess.HumanMeeting
98+
override val description = "Product decision needed - feature direction, UX choices, or business logic"
99+
}
100+
101+
/**
102+
* Authorization or approval needed to proceed.
103+
* Includes security approvals, compliance sign-offs, and access grants.
104+
*/
105+
data object Authorization : Decision() {
106+
override val escalationProcess = EscalationProcess.HumanApproval
107+
override val description = "Authorization needed - security approvals, compliance, or access grants"
108+
}
109+
}
110+
111+
// ==================== Budget Escalations ====================
112+
113+
/**
114+
* Escalations related to budget, resources, or costs.
115+
* These typically require human approval due to financial implications.
116+
*/
117+
sealed class Budget : Escalation() {
118+
119+
/**
120+
* Resource allocation decision needed.
121+
* Includes team capacity, infrastructure resources, and tool licenses.
122+
*/
123+
data object ResourceAllocation : Budget() {
124+
override val escalationProcess = EscalationProcess.HumanMeeting
125+
override val description = "Resource allocation needed - team capacity, infrastructure, or licenses"
126+
}
127+
128+
/**
129+
* Cost approval needed for expenditure.
130+
* Includes service costs, tool purchases, and infrastructure expenses.
131+
*/
132+
data object CostApproval : Budget() {
133+
override val escalationProcess = EscalationProcess.HumanApproval
134+
override val description = "Cost approval needed - service costs, purchases, or infrastructure expenses"
135+
}
136+
137+
/**
138+
* Timeline or deadline negotiation needed.
139+
* Includes scope-timeline tradeoffs and delivery date discussions.
140+
*/
141+
data object Timeline : Budget() {
142+
override val escalationProcess = EscalationProcess.HumanMeeting
143+
override val description = "Timeline negotiation needed - scope-timeline tradeoffs or delivery dates"
144+
}
145+
}
146+
147+
// ==================== Priorities Escalations ====================
148+
149+
/**
150+
* Escalations related to prioritization and scheduling.
151+
* These involve deciding what to work on and in what order.
152+
*/
153+
sealed class Priorities : Escalation() {
154+
155+
/**
156+
* Conflicting priorities need resolution.
157+
* Includes competing deadlines, resource conflicts, and dependency ordering.
158+
*/
159+
data object Conflict : Priorities() {
160+
override val escalationProcess = EscalationProcess.HumanMeeting
161+
override val description = "Priority conflict - competing deadlines, resource conflicts, or dependency ordering"
162+
}
163+
164+
/**
165+
* Reprioritization request for existing work.
166+
* Includes urgent requests, changed business needs, and blocking issues.
167+
*/
168+
data object Reprioritization : Priorities() {
169+
override val escalationProcess = EscalationProcess.HumanApproval
170+
override val description = "Reprioritization request - urgent requests, changed needs, or blocking issues"
171+
}
172+
173+
/**
174+
* Dependency on another team or project.
175+
* Includes cross-team coordination and external project dependencies.
176+
*/
177+
data object Dependency : Priorities() {
178+
override val escalationProcess = EscalationProcess.AgentMeeting
179+
override val description = "Cross-team dependency - coordination with other teams or projects"
180+
}
181+
}
182+
183+
// ==================== Scope Escalations ====================
184+
185+
/**
186+
* Escalations related to project scope and boundaries.
187+
* These affect what is and isn't included in the work.
188+
*/
189+
sealed class Scope : Escalation() {
190+
191+
/**
192+
* Scope expansion or feature creep detected.
193+
* Includes additional requirements, expanded functionality, and new use cases.
194+
*/
195+
data object Expansion : Scope() {
196+
override val escalationProcess = EscalationProcess.HumanMeeting
197+
override val description = "Scope expansion detected - additional requirements or new use cases"
198+
}
199+
200+
/**
201+
* Scope reduction or feature cut needed.
202+
* Includes timeline pressure, technical limitations, and resource constraints.
203+
*/
204+
data object Reduction : Scope() {
205+
override val escalationProcess = EscalationProcess.HumanMeeting
206+
override val description = "Scope reduction needed - timeline pressure or resource constraints"
207+
}
208+
209+
/**
210+
* Scope boundaries unclear or undefined.
211+
* Includes ambiguous requirements and undefined edge cases.
212+
*/
213+
data object Clarification : Scope() {
214+
override val escalationProcess = EscalationProcess.HumanMeeting
215+
override val description = "Scope clarification needed - ambiguous requirements or undefined boundaries"
216+
}
217+
}
218+
219+
// ==================== External Escalations ====================
220+
221+
/**
222+
* Escalations caused by external factors outside the team's control.
223+
*/
224+
sealed class External : Escalation() {
225+
226+
/**
227+
* Waiting for third-party vendor or service.
228+
* Includes API availability, support responses, and service provisioning.
229+
*/
230+
data object Vendor : External() {
231+
override val escalationProcess = EscalationProcess.ExternalDependency
232+
override val description = "Waiting for vendor - API availability, support, or service provisioning"
233+
}
234+
235+
/**
236+
* Waiting for customer or end-user input.
237+
* Includes user testing feedback, customer requirements, and stakeholder input.
238+
*/
239+
data object Customer : External() {
240+
override val escalationProcess = EscalationProcess.HumanApproval
241+
override val description = "Waiting for customer - user feedback, requirements, or stakeholder input"
242+
}
243+
}
244+
245+
companion object {
246+
/**
247+
* Returns all possible escalation types for LLM classification context.
248+
* The LLM uses these descriptions to categorize blocker scenarios.
249+
*/
250+
fun allTypes(): List<Escalation> = listOf(
251+
// Discussion
252+
Discussion.CodeReview,
253+
Discussion.Design,
254+
Discussion.Architecture,
255+
Discussion.Requirements,
256+
// Decision
257+
Decision.Technical,
258+
Decision.Product,
259+
Decision.Authorization,
260+
// Budget
261+
Budget.ResourceAllocation,
262+
Budget.CostApproval,
263+
Budget.Timeline,
264+
// Priorities
265+
Priorities.Conflict,
266+
Priorities.Reprioritization,
267+
Priorities.Dependency,
268+
// Scope
269+
Scope.Expansion,
270+
Scope.Reduction,
271+
Scope.Clarification,
272+
// External
273+
External.Vendor,
274+
External.Customer,
275+
)
276+
277+
/**
278+
* Returns a formatted string of all escalation types and their descriptions
279+
* suitable for use in LLM prompts.
280+
*/
281+
fun allTypesForPrompt(): String = AgentTypeDescriber.formatGroupedByHierarchy(
282+
types = allTypes(),
283+
title = "Available escalation types:"
284+
)
285+
}
286+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package link.socket.ampere.agents.events.tickets
2+
3+
import link.socket.ampere.domain.agent.AgentDescribable
4+
5+
/**
6+
* Defines the mechanism by which an escalation is resolved.
7+
* Each process type specifies the participants and format needed
8+
* to address the escalation.
9+
*/
10+
sealed class EscalationProcess : AgentDescribable {
11+
12+
/**
13+
* Whether this process requires scheduling a meeting.
14+
*/
15+
abstract val requiresMeeting: Boolean
16+
17+
/**
18+
* Whether this process requires human involvement.
19+
*/
20+
abstract val requiresHuman: Boolean
21+
22+
override fun describeProperties(): Map<String, String> = mapOf(
23+
"requiresMeeting" to requiresMeeting.toString(),
24+
"requiresHuman" to requiresHuman.toString()
25+
)
26+
27+
/**
28+
* Escalation resolved through a meeting between agents.
29+
* Used for technical discussions, code reviews, and design decisions
30+
* that can be resolved by AI agents collaborating.
31+
*/
32+
data object AgentMeeting : EscalationProcess() {
33+
override val requiresMeeting: Boolean = true
34+
override val requiresHuman: Boolean = false
35+
override val description: String = "Resolved through agent meeting - technical discussions and decisions handled by AI agents"
36+
}
37+
38+
/**
39+
* Escalation resolved through human approval without a formal meeting.
40+
* Used for straightforward approvals, sign-offs, and permissions
41+
* that don't require discussion.
42+
*/
43+
data object HumanApproval : EscalationProcess() {
44+
override val requiresMeeting: Boolean = false
45+
override val requiresHuman: Boolean = true
46+
override val description: String = "Resolved through human approval - straightforward sign-offs and permissions without discussion"
47+
}
48+
49+
/**
50+
* Escalation resolved through a meeting that includes human participants.
51+
* Used for strategic decisions, budget approvals, and scope changes
52+
* that require both discussion and human authority.
53+
*/
54+
data object HumanMeeting : EscalationProcess() {
55+
override val requiresMeeting: Boolean = true
56+
override val requiresHuman: Boolean = true
57+
override val description: String = "Resolved through human meeting - strategic decisions requiring both discussion and human authority"
58+
}
59+
60+
/**
61+
* Escalation resolved by waiting for an external dependency.
62+
* Used when blocked by third-party APIs, vendor responses, or
63+
* other external factors outside the team's control.
64+
*/
65+
data object ExternalDependency : EscalationProcess() {
66+
override val requiresMeeting: Boolean = false
67+
override val requiresHuman: Boolean = false
68+
override val description: String = "Waiting for external dependency - third-party APIs, vendor responses, or other external factors"
69+
}
70+
}

0 commit comments

Comments
 (0)