feat(#166): Implement Stitcher module structure

Created the mosaic-stitcher module - the workflow orchestration layer
that wraps OpenClaw.

Responsibilities:
- Receive webhooks from @mosaic bot
- Apply Guard Rails (capability permissions)
- Apply Quality Rails (mandatory gates)
- Track all job steps and events
- Dispatch work to OpenClaw with constraints

Implementation:
- StitcherModule: Module definition with PrismaModule and BullMqModule
- StitcherService: Core orchestration logic
  - handleWebhook(): Process webhooks from @mosaic bot
  - dispatchJob(): Create RunnerJob and dispatch to BullMQ queue
  - applyGuardRails(): Check capability permissions for agent profiles
  - applyQualityRails(): Determine mandatory gates for job types
  - trackJobEvent(): Log events to database for audit trail
- StitcherController: HTTP endpoints
  - POST /stitcher/webhook: Webhook receiver
  - POST /stitcher/dispatch: Manual job dispatch
- DTOs and interfaces for type safety

TDD Process:
1. RED: Created failing tests (12 tests)
2. GREEN: Implemented minimal code to pass tests
3. REFACTOR: Fixed TypeScript strict mode issues

Quality Gates: ALL PASS
- Typecheck: PASS
- Lint: PASS
- Build: PASS
- Tests: PASS (12/12)

Token estimate: ~56,000 tokens

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-01 21:08:32 -06:00
parent 65b1dad64f
commit a2cd614e87
12 changed files with 741 additions and 0 deletions

View File

@@ -0,0 +1 @@
export * from "./job-dispatch.interface";

View File

@@ -0,0 +1,39 @@
/**
* Result of job dispatch operation
*/
export interface JobDispatchResult {
jobId: string;
queueName: string;
status: string;
estimatedStartTime?: Date;
}
/**
* Guard Rails result - capability permission check
*/
export interface GuardRailsResult {
allowed: boolean;
reason?: string;
requiredCapability?: string;
}
/**
* Quality Rails result - mandatory gate check
*/
export interface QualityRailsResult {
required: boolean;
gates: string[];
skipReason?: string;
}
/**
* Job dispatch context
*/
export interface JobDispatchContext {
workspaceId: string;
type: string;
priority?: number;
guardRails?: GuardRailsResult;
qualityRails?: QualityRailsResult;
metadata?: Record<string, unknown>;
}