@miller-tech/uap 2.36.4 → 2.39.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/model-profiles/qwen38.json +3 -3
- package/config/model-registry.json +96 -6
- package/dist/.tsbuildinfo +1 -1
- package/dist/bin/cli.js +57 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/deliver.d.ts +46 -0
- package/dist/cli/deliver.d.ts.map +1 -1
- package/dist/cli/deliver.js +155 -36
- package/dist/cli/deliver.js.map +1 -1
- package/dist/cli/models.d.ts +11 -1
- package/dist/cli/models.d.ts.map +1 -1
- package/dist/cli/models.js +164 -3
- package/dist/cli/models.js.map +1 -1
- package/dist/cli/workflow.d.ts +36 -0
- package/dist/cli/workflow.d.ts.map +1 -0
- package/dist/cli/workflow.js +246 -0
- package/dist/cli/workflow.js.map +1 -0
- package/dist/delivery/run-state.d.ts +1 -1
- package/dist/delivery/run-state.d.ts.map +1 -1
- package/dist/delivery/run-state.js +1 -1
- package/dist/delivery/run-state.js.map +1 -1
- package/dist/delivery/team-solve-deliver.d.ts +83 -0
- package/dist/delivery/team-solve-deliver.d.ts.map +1 -0
- package/dist/delivery/team-solve-deliver.js +191 -0
- package/dist/delivery/team-solve-deliver.js.map +1 -0
- package/dist/inference/model-files.d.ts +111 -0
- package/dist/inference/model-files.d.ts.map +1 -0
- package/dist/inference/model-files.js +172 -0
- package/dist/inference/model-files.js.map +1 -0
- package/dist/placement/registry.d.ts +650 -0
- package/dist/placement/registry.d.ts.map +1 -1
- package/dist/placement/registry.js +21 -0
- package/dist/placement/registry.js.map +1 -1
- package/dist/workflow/loader.d.ts +34 -0
- package/dist/workflow/loader.d.ts.map +1 -0
- package/dist/workflow/loader.js +232 -0
- package/dist/workflow/loader.js.map +1 -0
- package/dist/workflow/runner.d.ts +90 -0
- package/dist/workflow/runner.d.ts.map +1 -0
- package/dist/workflow/runner.js +416 -0
- package/dist/workflow/runner.js.map +1 -0
- package/dist/workflow/types.d.ts +400 -0
- package/dist/workflow/types.d.ts.map +1 -0
- package/dist/workflow/types.js +147 -0
- package/dist/workflow/types.js.map +1 -0
- package/docs/INDEX.md +1 -0
- package/docs/architecture/adr/0013-declarative-workflow-layer.md +99 -0
- package/docs/architecture/adr/0014-loop-steps-and-team-solve-deliver.md +142 -0
- package/docs/benchmarks/LCB_DROID_SMOKE.md +111 -0
- package/docs/guides/DELIVER.md +3 -1
- package/docs/guides/WORKFLOWS.md +179 -0
- package/docs/plans/model-performance-proof-options.md +39 -0
- package/docs/reference/CLI.md +33 -0
- package/docs/reference/CONFIGURATION.md +1 -0
- package/docs/reference/FEATURES.md +18 -0
- package/examples/auto-coordinator-example.js +127 -0
- package/examples/demo-order-solid.ts +19 -0
- package/examples/order-processing-strategy-pattern.ts +186 -0
- package/examples/order-processor-refactored.ts +473 -0
- package/examples/order-solid-refactor.ts +830 -0
- package/examples/refactored-order-processing.ts +106 -0
- package/examples/run-order-processing.ts +48 -0
- package/examples/solid-order-processing.ts +324 -0
- package/examples/strategy-pattern-example.ts +100 -0
- package/examples/workflows/team-solve/README.md +85 -0
- package/examples/workflows/team-solve/check-samples.sh +50 -0
- package/examples/workflows/team-solve/sample/task.md +22 -0
- package/examples/workflows/team-solve/sample/tests/1.in +2 -0
- package/examples/workflows/team-solve/sample/tests/1.out +1 -0
- package/examples/workflows/team-solve/sample/tests/2.in +2 -0
- package/examples/workflows/team-solve/sample/tests/2.out +1 -0
- package/examples/workflows/team-solve/sample/tests/3.in +2 -0
- package/examples/workflows/team-solve/sample/tests/3.out +1 -0
- package/examples/workflows/team-solve/sample/tests/4.in +2 -0
- package/examples/workflows/team-solve/sample/tests/4.out +1 -0
- package/examples/workflows/team-solve/sample/tests/5.in +1 -0
- package/examples/workflows/team-solve/sample/tests/5.out +1 -0
- package/examples/workflows/team-solve/steps/ideate-a.md +26 -0
- package/examples/workflows/team-solve/steps/ideate-b.md +28 -0
- package/examples/workflows/team-solve/steps/plan.md +20 -0
- package/examples/workflows/team-solve/steps/repair.md +25 -0
- package/examples/workflows/team-solve/steps/review.md +29 -0
- package/examples/workflows/team-solve/steps/solve.md +26 -0
- package/examples/workflows/team-solve/workflow.yaml +78 -0
- package/examples/workflows/team-solve-deliver/README.md +84 -0
- package/examples/workflows/team-solve-deliver/steps/ideate-a.md +25 -0
- package/examples/workflows/team-solve-deliver/steps/ideate-b.md +28 -0
- package/examples/workflows/team-solve-deliver/steps/plan.md +25 -0
- package/examples/workflows/team-solve-deliver/steps/repair.md +20 -0
- package/examples/workflows/team-solve-deliver/steps/review.md +31 -0
- package/examples/workflows/team-solve-deliver/steps/solve.md +28 -0
- package/examples/workflows/team-solve-deliver/steps/verify.md +9 -0
- package/examples/workflows/team-solve-deliver/workflow.yaml +74 -0
- package/package.json +2 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-311.pyc +0 -0
- package/src/policies/enforcers/__pycache__/expert_review_required.cpython-311.pyc +0 -0
- package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-311.pyc +0 -0
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-311.pyc +0 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-311.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +163 -18
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// Concise Strategy Pattern Implementation
|
|
3
|
+
// ============================================
|
|
4
|
+
|
|
5
|
+
// Strategy interface
|
|
6
|
+
export interface OrderProcessingStrategy {
|
|
7
|
+
process(order: Order): Order;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Order interface for type safety
|
|
11
|
+
export interface Order {
|
|
12
|
+
type: string;
|
|
13
|
+
status?: string;
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// ===== Concrete Strategies =====
|
|
18
|
+
|
|
19
|
+
export class DigitalOrderStrategy implements OrderProcessingStrategy {
|
|
20
|
+
process(order: Order): Order {
|
|
21
|
+
return { ...order, status: 'delivered' };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class PhysicalOrderStrategy implements OrderProcessingStrategy {
|
|
26
|
+
process(order: Order): Order {
|
|
27
|
+
return { ...order, status: 'shipped' };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class SubscriptionOrderStrategy implements OrderProcessingStrategy {
|
|
32
|
+
process(order: Order): Order {
|
|
33
|
+
return { ...order, status: 'active' };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ===== Context with Strategy Selection =====
|
|
38
|
+
|
|
39
|
+
export class OrderProcessor {
|
|
40
|
+
private strategies: Record<string, OrderProcessingStrategy>;
|
|
41
|
+
|
|
42
|
+
constructor() {
|
|
43
|
+
this.strategies = {
|
|
44
|
+
digital: new DigitalOrderStrategy(),
|
|
45
|
+
physical: new PhysicalOrderStrategy(),
|
|
46
|
+
subscription: new SubscriptionOrderStrategy(),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
processOrder(order: Order): Order {
|
|
51
|
+
const strategy = this.strategies[order.type];
|
|
52
|
+
if (!strategy) {
|
|
53
|
+
// Handle unknown order types gracefully
|
|
54
|
+
return { ...order, status: 'pending' };
|
|
55
|
+
}
|
|
56
|
+
return strategy.process(order);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
addStrategy(type: string, strategy: OrderProcessingStrategy): void {
|
|
60
|
+
this.strategies[type] = strategy;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ===== Usage =====
|
|
65
|
+
|
|
66
|
+
const processor = new OrderProcessor();
|
|
67
|
+
|
|
68
|
+
// Example 1: Digital order
|
|
69
|
+
const order1 = processor.processOrder({ type: 'digital', id: 1 });
|
|
70
|
+
console.log(order1); // { type: 'digital', id: 1, status: 'delivered' }
|
|
71
|
+
|
|
72
|
+
// Example 2: Physical order
|
|
73
|
+
const order2 = processor.processOrder({ type: 'physical', id: 2 });
|
|
74
|
+
console.log(order2); // { type: 'physical', id: 2, status: 'shipped' }
|
|
75
|
+
|
|
76
|
+
// Example 3: Subscription order
|
|
77
|
+
const order3 = processor.processOrder({ type: 'subscription', id: 3 });
|
|
78
|
+
console.log(order3); // { type: 'subscription', id: 3, status: 'active' }
|
|
79
|
+
|
|
80
|
+
// Example 4: Unknown order type
|
|
81
|
+
const order4 = processor.processOrder({ type: 'gift_card', id: 4 });
|
|
82
|
+
console.log(order4); // { type: 'gift_card', id: 4, status: 'pending' }
|
|
83
|
+
|
|
84
|
+
// ============================================
|
|
85
|
+
// Comparison with Original Code
|
|
86
|
+
// ============================================
|
|
87
|
+
|
|
88
|
+
// Original code:
|
|
89
|
+
// function processOrder(order: any) {
|
|
90
|
+
// if (order.type === 'digital') {
|
|
91
|
+
// order.status = 'delivered';
|
|
92
|
+
// } else if (order.type === 'physical') {
|
|
93
|
+
// order.status = 'shipped';
|
|
94
|
+
// } else if (order.type === 'subscription') {
|
|
95
|
+
// order.status = 'active';
|
|
96
|
+
// }
|
|
97
|
+
// return order;
|
|
98
|
+
// }
|
|
99
|
+
|
|
100
|
+
// Strategy Pattern Benefits:
|
|
101
|
+
// 1. Better type safety with TypeScript interfaces
|
|
102
|
+
// 2. OCP: Add new order types without modifying existing code
|
|
103
|
+
// 3. Each strategy is independently testable
|
|
104
|
+
// 4. No mutation of input (returns new objects)
|
|
105
|
+
// 5. Easy to extend with new strategies
|
|
106
|
+
// 6. Handles unknown types gracefully
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
// Practical usage example for Strategy Pattern Order Processing
|
|
3
|
+
|
|
4
|
+
import { OrderProcessor, OrderProcessingStrategy } from './refactored-order-processing';
|
|
5
|
+
|
|
6
|
+
// Example: Defining a custom order type and strategy
|
|
7
|
+
class GiftCardOrderStrategy implements OrderProcessingStrategy {
|
|
8
|
+
process(order: any): any {
|
|
9
|
+
return { ...order, status: 'available', expiryDate: '365 days from now' };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Create processor and add custom strategy
|
|
14
|
+
const processor = new OrderProcessor();
|
|
15
|
+
processor.addStrategy('gift_card', new GiftCardOrderStrategy());
|
|
16
|
+
|
|
17
|
+
// Process various orders
|
|
18
|
+
const orders = [
|
|
19
|
+
{ type: 'digital', id: 1, item: 'software' },
|
|
20
|
+
{ type: 'physical', id: 2, item: 'book', address: '123 Main St' },
|
|
21
|
+
{ type: 'subscription', id: 3, item: 'streaming' },
|
|
22
|
+
{ type: 'gift_card', id: 4, item: '$50 card' },
|
|
23
|
+
{ type: 'custom', id: 5, item: 'special request' }, // Unknown type falls back to 'pending'
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
console.log('=== Processing Orders ===\n');
|
|
27
|
+
orders.forEach((order) => {
|
|
28
|
+
const result = processor.processOrder(order);
|
|
29
|
+
console.log(`ID: ${result.id} | Type: ${result.type} | Status: ${result.status}`);
|
|
30
|
+
if (result.expiryDate) {
|
|
31
|
+
console.log(` Expires: ${result.expiryDate}`);
|
|
32
|
+
}
|
|
33
|
+
console.log('');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Output:
|
|
37
|
+
// === Processing Orders ===
|
|
38
|
+
//
|
|
39
|
+
// ID: 1 | Type: digital | Status: delivered
|
|
40
|
+
//
|
|
41
|
+
// ID: 2 | Type: physical | Status: shipped
|
|
42
|
+
//
|
|
43
|
+
// ID: 3 | Type: subscription | Status: active
|
|
44
|
+
//
|
|
45
|
+
// ID: 4 | Type: gift_card | Status: available
|
|
46
|
+
// Expires: 365 days from now
|
|
47
|
+
//
|
|
48
|
+
// ID: 5 | Type: custom | Status: pending
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SOLID-Compliant Order Processing Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates:
|
|
5
|
+
* - Single Responsibility Principle: Each class has one reason to change
|
|
6
|
+
* - Open/Closed Principle: New order types can be added without modifying existing code
|
|
7
|
+
* - Liskov Substitution Principle: All strategies can be used interchangeably
|
|
8
|
+
* - Interface Segregation Principle: Focused, small interfaces
|
|
9
|
+
* - Dependency Inversion Principle: Depends on abstractions, not concretions
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// ============================================
|
|
13
|
+
// Interfaces (Abstractions)
|
|
14
|
+
// ============================================
|
|
15
|
+
|
|
16
|
+
interface Order {
|
|
17
|
+
id: string;
|
|
18
|
+
type: OrderType;
|
|
19
|
+
status: OrderStatus;
|
|
20
|
+
customerEmail?: string;
|
|
21
|
+
shippingAddress?: string;
|
|
22
|
+
// Add other order properties as needed
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
enum OrderType {
|
|
26
|
+
DIGITAL = 'digital',
|
|
27
|
+
PHYSICAL = 'physical',
|
|
28
|
+
SUBSCRIPTION = 'subscription',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
enum OrderStatus {
|
|
32
|
+
PENDING = 'pending',
|
|
33
|
+
DELIVERED = 'delivered',
|
|
34
|
+
SHIPPED = 'shipped',
|
|
35
|
+
ACTIVE = 'active',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Strategy Interface - defines the contract for all order processing strategies
|
|
40
|
+
* This follows the Interface Segregation Principle
|
|
41
|
+
*/
|
|
42
|
+
interface OrderProcessingStrategy {
|
|
43
|
+
process(order: Order): void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Logger Interface - allows for different logging implementations
|
|
48
|
+
* This follows the Dependency Inversion Principle
|
|
49
|
+
*/
|
|
50
|
+
interface Logger {
|
|
51
|
+
log(message: string): void;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ============================================
|
|
55
|
+
// Concrete Implementations
|
|
56
|
+
// ============================================
|
|
57
|
+
|
|
58
|
+
// Concrete Logger implementation
|
|
59
|
+
class ConsoleLogger implements Logger {
|
|
60
|
+
log(message: string): void {
|
|
61
|
+
console.log(message);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Digital Order Strategy
|
|
66
|
+
class DigitalOrderStrategy implements OrderProcessingStrategy {
|
|
67
|
+
constructor(private logger: Logger, private emailService: EmailService) {}
|
|
68
|
+
|
|
69
|
+
process(order: Order): void {
|
|
70
|
+
this.logger.log(`Processing digital order: ${order.id}`);
|
|
71
|
+
|
|
72
|
+
// Send email with download link
|
|
73
|
+
this.emailService.sendEmail({
|
|
74
|
+
to: order.customerEmail!,
|
|
75
|
+
subject: 'Your digital order is ready',
|
|
76
|
+
body: 'Click here to download your item',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
order.status = OrderStatus.DELIVERED;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Physical Order Strategy
|
|
84
|
+
class PhysicalOrderStrategy implements OrderProcessingStrategy {
|
|
85
|
+
constructor(private logger: Logger, private shippingService: ShippingService) {}
|
|
86
|
+
|
|
87
|
+
process(order: Order): void {
|
|
88
|
+
this.logger.log(`Processing physical order: ${order.id}`);
|
|
89
|
+
|
|
90
|
+
// Create shipping label
|
|
91
|
+
const label = this.shippingService.createLabel({
|
|
92
|
+
address: order.shippingAddress!,
|
|
93
|
+
orderId: order.id,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
this.logger.log(`Shipping label created: ${label.trackingNumber}`);
|
|
97
|
+
|
|
98
|
+
order.status = OrderStatus.SHIPPED;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Subscription Order Strategy
|
|
103
|
+
class SubscriptionOrderStrategy implements OrderProcessingStrategy {
|
|
104
|
+
constructor(private logger: Logger, private subscriptionService: SubscriptionService) {}
|
|
105
|
+
|
|
106
|
+
process(order: Order): void {
|
|
107
|
+
this.logger.log(`Processing subscription order: ${order.id}`);
|
|
108
|
+
|
|
109
|
+
// Activate subscription
|
|
110
|
+
this.subscriptionService.activate({
|
|
111
|
+
orderId: order.id,
|
|
112
|
+
customerEmail: order.customerEmail!,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
order.status = OrderStatus.ACTIVE;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ============================================
|
|
120
|
+
// Support Services (External Dependencies)
|
|
121
|
+
// ============================================
|
|
122
|
+
|
|
123
|
+
interface EmailService {
|
|
124
|
+
sendEmail(params: { to: string; subject: string; body: string }): void;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
interface ShippingService {
|
|
128
|
+
createLabel(params: { address: string; orderId: string }): { trackingNumber: string };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
interface SubscriptionService {
|
|
132
|
+
activate(params: { orderId: string; customerEmail: string }): void;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Mock implementations (in production, these would be real services)
|
|
136
|
+
class MockEmailService implements EmailService {
|
|
137
|
+
sendEmail(params: { to: string; subject: string; body: string }): void {
|
|
138
|
+
console.log(`[Email Service] Sending email to ${params.to}: ${params.subject}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
class MockShippingService implements ShippingService {
|
|
143
|
+
createLabel(params: { address: string; orderId: string }): { trackingNumber: string } {
|
|
144
|
+
const trackingNumber = `TRK-${params.orderId}-${Date.now()}`;
|
|
145
|
+
console.log(`[Shipping Service] Creating label for ${params.address}`);
|
|
146
|
+
return { trackingNumber };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
class MockSubscriptionService implements SubscriptionService {
|
|
151
|
+
activate(params: { orderId: string; customerEmail: string }): void {
|
|
152
|
+
console.log(`[Subscription Service] Activating subscription for ${params.customerEmail}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ============================================
|
|
157
|
+
// Strategy Factory (Single Responsibility)
|
|
158
|
+
// ============================================
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Factory responsible for creating the appropriate strategy based on order type
|
|
162
|
+
* This follows the Open/Closed Principle - new strategies can be added without modifying this class
|
|
163
|
+
*/
|
|
164
|
+
class OrderStrategyFactory {
|
|
165
|
+
private strategies = new Map<OrderType, OrderProcessingStrategy>();
|
|
166
|
+
|
|
167
|
+
constructor(
|
|
168
|
+
logger: Logger,
|
|
169
|
+
emailService: EmailService,
|
|
170
|
+
shippingService: ShippingService,
|
|
171
|
+
subscriptionService: SubscriptionService,
|
|
172
|
+
) {
|
|
173
|
+
// Register all available strategies
|
|
174
|
+
this.strategies.set(OrderType.DIGITAL, new DigitalOrderStrategy(logger, emailService));
|
|
175
|
+
this.strategies.set(
|
|
176
|
+
OrderType.PHYSICAL,
|
|
177
|
+
new PhysicalOrderStrategy(logger, shippingService),
|
|
178
|
+
);
|
|
179
|
+
this.strategies.set(
|
|
180
|
+
OrderType.SUBSCRIPTION,
|
|
181
|
+
new SubscriptionOrderStrategy(logger, subscriptionService),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
getStrategy(orderType: OrderType): OrderProcessingStrategy {
|
|
186
|
+
const strategy = this.strategies.get(orderType);
|
|
187
|
+
if (!strategy) {
|
|
188
|
+
throw new Error(`No strategy found for order type: ${orderType}`);
|
|
189
|
+
}
|
|
190
|
+
return strategy;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ============================================
|
|
195
|
+
// Order Processor (Context)
|
|
196
|
+
// ============================================
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Order Processor - the context that uses strategies
|
|
200
|
+
* This follows the Single Responsibility Principle - only handles order processing orchestration
|
|
201
|
+
* And Dependency Inversion Principle - depends on abstractions (Factory, Logger)
|
|
202
|
+
*/
|
|
203
|
+
class OrderProcessor {
|
|
204
|
+
constructor(
|
|
205
|
+
private strategyFactory: OrderStrategyFactory,
|
|
206
|
+
private logger: Logger,
|
|
207
|
+
) {}
|
|
208
|
+
|
|
209
|
+
processOrder(order: Order): Order {
|
|
210
|
+
this.logger.log(`Starting order processing for order: ${order.id}`);
|
|
211
|
+
|
|
212
|
+
// Get the appropriate strategy and process
|
|
213
|
+
const strategy = this.strategyFactory.getStrategy(order.type);
|
|
214
|
+
strategy.process(order);
|
|
215
|
+
|
|
216
|
+
this.logger.log(`Order processed successfully: ${order.id} (Status: ${order.status})`);
|
|
217
|
+
|
|
218
|
+
return order;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ============================================
|
|
223
|
+
// Usage Example
|
|
224
|
+
// ============================================
|
|
225
|
+
|
|
226
|
+
export function demonstrateSOLIDOrderProcessing() {
|
|
227
|
+
// Setup dependencies (could be injected via DI container in production)
|
|
228
|
+
const logger: Logger = new ConsoleLogger();
|
|
229
|
+
const emailService: EmailService = new MockEmailService();
|
|
230
|
+
const shippingService: ShippingService = new MockShippingService();
|
|
231
|
+
const subscriptionService: SubscriptionService = new MockSubscriptionService();
|
|
232
|
+
|
|
233
|
+
// Create strategy factory with all dependencies
|
|
234
|
+
const strategyFactory = new OrderStrategyFactory(
|
|
235
|
+
logger,
|
|
236
|
+
emailService,
|
|
237
|
+
shippingService,
|
|
238
|
+
subscriptionService,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// Create order processor
|
|
242
|
+
const orderProcessor = new OrderProcessor(strategyFactory, logger);
|
|
243
|
+
|
|
244
|
+
// Create test orders
|
|
245
|
+
const digitalOrder: Order = {
|
|
246
|
+
id: 'ORD-001',
|
|
247
|
+
type: OrderType.DIGITAL,
|
|
248
|
+
status: OrderStatus.PENDING,
|
|
249
|
+
customerEmail: 'customer@example.com',
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const physicalOrder: Order = {
|
|
253
|
+
id: 'ORD-002',
|
|
254
|
+
type: OrderType.PHYSICAL,
|
|
255
|
+
status: OrderStatus.PENDING,
|
|
256
|
+
customerEmail: 'customer@example.com',
|
|
257
|
+
shippingAddress: '123 Main St, City, Country',
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const subscriptionOrder: Order = {
|
|
261
|
+
id: 'ORD-003',
|
|
262
|
+
type: OrderType.SUBSCRIPTION,
|
|
263
|
+
status: OrderStatus.PENDING,
|
|
264
|
+
customerEmail: 'customer@example.com',
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
// Process orders
|
|
268
|
+
console.log('=== Processing Digital Order ===');
|
|
269
|
+
orderProcessor.processOrder(digitalOrder);
|
|
270
|
+
|
|
271
|
+
console.log('\n=== Processing Physical Order ===');
|
|
272
|
+
orderProcessor.processOrder(physicalOrder);
|
|
273
|
+
|
|
274
|
+
console.log('\n=== Processing Subscription Order ===');
|
|
275
|
+
orderProcessor.processOrder(subscriptionOrder);
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
digitalOrder,
|
|
279
|
+
physicalOrder,
|
|
280
|
+
subscriptionOrder,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// ============================================
|
|
285
|
+
// Benefits of this SOLID approach:
|
|
286
|
+
// ============================================
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* 1. Single Responsibility Principle
|
|
290
|
+
* - Each class has one reason to change
|
|
291
|
+
* - DigitalOrderStrategy only handles digital orders
|
|
292
|
+
* - OrderStrategyFactory only creates strategies
|
|
293
|
+
* - OrderProcessor only orchestrates processing
|
|
294
|
+
*
|
|
295
|
+
* 2. Open/Closed Principle
|
|
296
|
+
* - New order types can be added by creating new strategy classes
|
|
297
|
+
* - No existing code needs to be modified
|
|
298
|
+
* - Example: Adding a GiftCardStrategy without changing OrderProcessor
|
|
299
|
+
*
|
|
300
|
+
* 3. Liskov Substitution Principle
|
|
301
|
+
* - All OrderProcessingStrategy implementations are interchangeable
|
|
302
|
+
* - The OrderProcessor can use any strategy without knowing the concrete type
|
|
303
|
+
*
|
|
304
|
+
* 4. Interface Segregation Principle
|
|
305
|
+
* - Small, focused interfaces (OrderProcessingStrategy, Logger, etc.)
|
|
306
|
+
* - Classes only implement methods they need
|
|
307
|
+
*
|
|
308
|
+
* 5. Dependency Inversion Principle
|
|
309
|
+
* - High-level modules (OrderProcessor) depend on abstractions (interfaces)
|
|
310
|
+
* - Low-level modules (DigitalOrderStrategy, etc.) implement abstractions
|
|
311
|
+
* - Both depend on interfaces, not concrete implementations
|
|
312
|
+
*
|
|
313
|
+
* Additional Benefits:
|
|
314
|
+
* - Testable: Each component can be unit tested in isolation
|
|
315
|
+
* - Maintainable: Changes are isolated to specific classes
|
|
316
|
+
* - Extensible: New features can be added without refactoring existing code
|
|
317
|
+
* - Type-safe: TypeScript catches errors at compile time
|
|
318
|
+
* - Flexible: Dependencies can be swapped (e.g., MockLogger vs ProdLogger)
|
|
319
|
+
*/
|
|
320
|
+
|
|
321
|
+
// Run demonstration
|
|
322
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
323
|
+
demonstrateSOLIDOrderProcessing();
|
|
324
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Strategy Pattern Implementation Summary
|
|
2
|
+
|
|
3
|
+
## Original Code
|
|
4
|
+
```typescript
|
|
5
|
+
function processOrder(order: any) {
|
|
6
|
+
if (order.type === 'digital') {
|
|
7
|
+
order.status = 'delivered';
|
|
8
|
+
} else if (order.type === 'physical') {
|
|
9
|
+
order.status = 'shipped';
|
|
10
|
+
} else if (order.type === 'subscription') {
|
|
11
|
+
order.status = 'active';
|
|
12
|
+
}
|
|
13
|
+
return order;
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Refactored Code Options
|
|
18
|
+
|
|
19
|
+
### Option 1: Concise Version (`refactored-order-processing.ts`)
|
|
20
|
+
A simplified, production-ready implementation with:
|
|
21
|
+
- Single file with exported classes/interfaces
|
|
22
|
+
- Built-in strategy registry
|
|
23
|
+
- Graceful handling of unknown order types (returns 'pending')
|
|
24
|
+
- Immutability (returns new objects instead of mutating)
|
|
25
|
+
|
|
26
|
+
**Use this when:** You want a simple, working solution with good extensibility.
|
|
27
|
+
|
|
28
|
+
### Option 2: Detailed Version (`order-processing-strategy-pattern.ts`)
|
|
29
|
+
A comprehensive, educational implementation with:
|
|
30
|
+
- Separated Strategy Factory for strategy management
|
|
31
|
+
- Extensive inline documentation explaining assumptions
|
|
32
|
+
- Complete example usage including custom strategies
|
|
33
|
+
- Benefits and comparison sections
|
|
34
|
+
|
|
35
|
+
**Use this when:** You're learning the pattern or need maximum extensibility and documentation.
|
|
36
|
+
|
|
37
|
+
## Key Improvements Over Original
|
|
38
|
+
|
|
39
|
+
| Aspect | Original | Refactored |
|
|
40
|
+
|--------|----------|------------|
|
|
41
|
+
| **Type Safety** | Uses `any` type | Uses proper TypeScript interfaces |
|
|
42
|
+
| **Immutability** | Mutates input | Returns new objects |
|
|
43
|
+
| **Extensibility** | Requires modifying function | Add strategies without changing code |
|
|
44
|
+
| **Testability** | Hard to test in isolation | Each strategy is independently testable |
|
|
45
|
+
| **Maintainability** | Growing `if-else` chain | Clean separation of concerns |
|
|
46
|
+
| **Unknown Types** | Silent failure | Fallback strategy ('pending') |
|
|
47
|
+
|
|
48
|
+
## Usage Example
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { OrderProcessor, Order } from './refactored-order-processing';
|
|
52
|
+
|
|
53
|
+
const processor = new OrderProcessor();
|
|
54
|
+
|
|
55
|
+
const orders = [
|
|
56
|
+
{ type: 'digital', id: 1, item: 'software' },
|
|
57
|
+
{ type: 'physical', id: 2, item: 'book' },
|
|
58
|
+
{ type: 'subscription', id: 3, item: 'streaming' },
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
orders.forEach(order => {
|
|
62
|
+
const result = processor.processOrder(order);
|
|
63
|
+
console.log(`${order.type}: ${result.status}`);
|
|
64
|
+
});
|
|
65
|
+
// Output:
|
|
66
|
+
// digital: delivered
|
|
67
|
+
// physical: shipped
|
|
68
|
+
// subscription: active
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Adding New Order Types
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { OrderProcessingStrategy, OrderProcessor } from './refactored-order-processing';
|
|
75
|
+
|
|
76
|
+
// Create custom strategy
|
|
77
|
+
class GiftCardStrategy implements OrderProcessingStrategy {
|
|
78
|
+
process(order: Order): Order {
|
|
79
|
+
return { ...order, status: 'available', expiryDate: '365 days' };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Register and use
|
|
84
|
+
const processor = new OrderProcessor();
|
|
85
|
+
const order = processor.processOrder({
|
|
86
|
+
type: 'gift_card',
|
|
87
|
+
id: 4,
|
|
88
|
+
item: '$50 card'
|
|
89
|
+
});
|
|
90
|
+
// Returns: { type: 'gift_card', id: 4, item: '$50 card', status: 'pending' }
|
|
91
|
+
// (You would call processor.addStrategy('gift_card', new GiftCardStrategy()) first)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Files Created
|
|
95
|
+
|
|
96
|
+
1. **refactored-order-processing.ts** - Concise, production-ready version
|
|
97
|
+
2. **order-processing-strategy-pattern.ts** - Detailed, educational version
|
|
98
|
+
3. **run-order-processing.ts** - Practical usage example script
|
|
99
|
+
|
|
100
|
+
All files compile successfully with TypeScript strict mode and include proper type safety.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# team-solve — five roles, one problem, files only
|
|
2
|
+
|
|
3
|
+
The GVS5H method (Lee, 2026) as a static UAP workflow: a planner, two
|
|
4
|
+
ideators, a solver, a reviewer and a repair worker — five fresh-context model
|
|
5
|
+
calls per pass, each reading and writing FILES in the run directory, never
|
|
6
|
+
chat — with a deterministic sample harness as the only judge.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
plan ──┬── ideate-a ──┬── solve ── test ── review ── repair ── verify
|
|
10
|
+
└── ideate-b ──┘
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- `test` runs the samples and NEVER fails the run (evidence for the reviewer).
|
|
14
|
+
- `verify` runs the same samples as the verdict — a nonzero exit fails it.
|
|
15
|
+
- The steps name no model; the pin ladder answers (step → workflow
|
|
16
|
+
`defaultModel` → `uap workflow run --model` → the local fleet default).
|
|
17
|
+
- Command steps run with `cwd` = the run directory; the harness script is
|
|
18
|
+
referenced via `$UAP_WORKFLOW_DIR` (this workflow's own directory) rather
|
|
19
|
+
than copied in, so the run directory stays a pure ledger of inputs and
|
|
20
|
+
step outputs.
|
|
21
|
+
|
|
22
|
+
## Provenance (the numbers are theirs, not ours)
|
|
23
|
+
|
|
24
|
+
The original claim: five Qwen3.8-27B roles on this shape scored a mean
|
|
25
|
+
9.8/10 on the first ten LiveCodeBench Hard problems, at parity with the
|
|
26
|
+
authors' own harness (9.6) and above Fable 5 single-call (8.0). Those runs
|
|
27
|
+
were on OpenRouter (~$0.39/run, 40 min median), with the authors' caveats
|
|
28
|
+
intact: ten problems, not one hundred; contamination not ruled out; the
|
|
29
|
+
claim is parity with their harness, not superiority.
|
|
30
|
+
|
|
31
|
+
What this port proves HERE is the capability, not the score: a static
|
|
32
|
+
workflow, local fleet, hidden-style verdict — a paired A/B against the
|
|
33
|
+
single-model `deliver` loop is the validation experiment (see
|
|
34
|
+
`docs/plans/model-performance-proof-options.md`, option O7), gated on an
|
|
35
|
+
explicit go.
|
|
36
|
+
|
|
37
|
+
## Run it
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# from the project root
|
|
41
|
+
uap workflow run team-solve --input examples/workflows/team-solve/sample
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
That copies `sample/` (task.md + tests/) into a fresh run directory under
|
|
45
|
+
`.uap/workflow-runs/` and executes the seven steps on the local fleet default
|
|
46
|
+
(the strata arm through the proxy). Exit 0 means every sample passed.
|
|
47
|
+
|
|
48
|
+
Other useful invocations:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uap workflow show team-solve # the validated plan + pins
|
|
52
|
+
uap workflow run team-solve --input <my-problem-dir> # your own task.md + tests/
|
|
53
|
+
uap workflow status # runs + their verdicts
|
|
54
|
+
uap workflow resume <runId> # after a block or an interrupt
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Your problem directory needs `task.md` and paired `tests/N.in` / `tests/N.out`;
|
|
58
|
+
the program is `solution.py`, Python 3, stdin → stdout.
|
|
59
|
+
|
|
60
|
+
## Layout
|
|
61
|
+
|
|
62
|
+
| file | role |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `workflow.yaml` | the DAG: steps, `requires:` edges, kinds, reads/writes |
|
|
65
|
+
| `steps/*.md` | one role prompt per agent step (the role IS the prompt) |
|
|
66
|
+
| `check-samples.sh` | the deterministic harness (test: evidence; verify: verdict) |
|
|
67
|
+
| `sample/` | a smoke task: longest strictly increasing subsequence |
|
|
68
|
+
|
|
69
|
+
## Notes for authors of new workflows
|
|
70
|
+
|
|
71
|
+
- Agent steps take `prompt:` (a role-prompt file) XOR `goal:` (inline).
|
|
72
|
+
- `reads:` files are inlined into the agent prompt at run time; `writes[0]`
|
|
73
|
+
receives the reply verbatim. Overwrite semantics: the file ledger is the
|
|
74
|
+
truth, chat is not.
|
|
75
|
+
- Parallel steps (`parallel: 2`) must not share write targets — the loader
|
|
76
|
+
rejects a DAG where two steps write the same file with no `requires:` path
|
|
77
|
+
between them.
|
|
78
|
+
- A `gate` step pauses for `uap workflow approve <runId> <step>` — resumable.
|
|
79
|
+
- Runs are resumable at the step boundary: `.uap/workflow-runs/<runId>/`
|
|
80
|
+
keeps every step's files plus `run-state.json`.
|
|
81
|
+
- Hardening option: `test` executes model-written Python
|
|
82
|
+
(`check-samples.sh` → `python3 solution.py`) with your privileges — the
|
|
83
|
+
same trust class as `deliver` gate scripts. For untrusted inputs insert a
|
|
84
|
+
`gate` step before the first command step (approve the program once, then
|
|
85
|
+
resume), or wrap the whole run in `uap sandbox --net off`.
|