Spaces:
Paused
Paused
| /** | |
| * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| * β APPROVAL GATE - Claude as Delegate β | |
| * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| * β Claude har fΓ₯et delegeret godkendelsesautoritet fra CLAK β | |
| * β β | |
| * β APPROVAL FLOW: β | |
| * β Gemini/DeepSeek β Claude (auto-review) β Execute β | |
| * β β | |
| * β ESCALATE TO CLAK ONLY FOR: β | |
| * β β’ Production deployments β | |
| * β β’ API key/credential changes β | |
| * β β’ Budget/cost decisions β | |
| * β β’ Security-sensitive operations β | |
| * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| */ | |
| import { AgentId } from './types.js'; | |
| export type ApprovalDecision = 'approved' | 'rejected' | 'escalate_to_clak'; | |
| export interface ApprovalResult { | |
| decision: ApprovalDecision; | |
| reason: string; | |
| approvedBy: AgentId; | |
| timestamp: string; | |
| modifications?: string[]; // Claude kan modificere requests | |
| } | |
| // Only these require CLAK personally | |
| const ESCALATE_TO_CLAK = [ | |
| 'production_deploy', | |
| 'api_key_create', | |
| 'credential_change', | |
| 'budget_decision', | |
| 'security_config', | |
| 'delete_data', | |
| 'external_integration' | |
| ]; | |
| class ApprovalGate { | |
| private static instance: ApprovalGate; | |
| public static getInstance(): ApprovalGate { | |
| if (!ApprovalGate.instance) { | |
| ApprovalGate.instance = new ApprovalGate(); | |
| } | |
| return ApprovalGate.instance; | |
| } | |
| /** | |
| * Claude reviews and decides on behalf of CLAK | |
| * Returns immediately - no waiting for human | |
| */ | |
| review(params: { | |
| fromAgent: AgentId; | |
| action: string; | |
| description: string; | |
| context?: Record<string, any>; | |
| }): ApprovalResult { | |
| const { fromAgent, action, description } = params; | |
| const timestamp = new Date().toISOString(); | |
| // CLAK's own requests are auto-approved | |
| if (fromAgent === 'clak') { | |
| return { | |
| decision: 'approved', | |
| reason: 'CLAK authority - auto-approved', | |
| approvedBy: 'clak', | |
| timestamp | |
| }; | |
| } | |
| // Check if needs escalation to CLAK | |
| const needsEscalation = ESCALATE_TO_CLAK.some(e => | |
| action.toLowerCase().includes(e) || | |
| description.toLowerCase().includes(e) | |
| ); | |
| if (needsEscalation) { | |
| return { | |
| decision: 'escalate_to_clak', | |
| reason: `Action "${action}" requires CLAK's personal approval`, | |
| approvedBy: 'claude', | |
| timestamp | |
| }; | |
| } | |
| // Claude reviews based on reasonableness | |
| const review = this.evaluateRequest(params); | |
| return { | |
| decision: review.approved ? 'approved' : 'rejected', | |
| reason: review.reason, | |
| approvedBy: 'claude', | |
| timestamp, | |
| modifications: review.modifications | |
| }; | |
| } | |
| /** | |
| * Claude's evaluation logic | |
| */ | |
| private evaluateRequest(params: { | |
| fromAgent: AgentId; | |
| action: string; | |
| description: string; | |
| context?: Record<string, any>; | |
| }): { approved: boolean; reason: string; modifications?: string[] } { | |
| const { fromAgent, action, description } = params; | |
| // ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // APPROVAL RULES (Claude's delegated authority) | |
| // ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| // 1. Research requests - always approved | |
| if (action.includes('research') || action.includes('search') || action.includes('analyze')) { | |
| return { | |
| approved: true, | |
| reason: 'Research/analysis tasks are pre-approved' | |
| }; | |
| } | |
| // 2. Code review/suggestions - approved | |
| if (action.includes('review') || action.includes('suggest') || action.includes('recommend')) { | |
| return { | |
| approved: true, | |
| reason: 'Review and recommendations are welcome' | |
| }; | |
| } | |
| // 3. Documentation - approved | |
| if (action.includes('document') || action.includes('readme') || action.includes('comment')) { | |
| return { | |
| approved: true, | |
| reason: 'Documentation improvements are pre-approved' | |
| }; | |
| } | |
| // 4. Questions/clarifications - approved | |
| if (action.includes('question') || action.includes('clarify') || action.includes('ask')) { | |
| return { | |
| approved: true, | |
| reason: 'Questions and clarifications are encouraged' | |
| }; | |
| } | |
| // 5. Status updates - approved | |
| if (action.includes('status') || action.includes('update') || action.includes('report')) { | |
| return { | |
| approved: true, | |
| reason: 'Status updates are pre-approved' | |
| }; | |
| } | |
| // 6. Code generation for review - approved with note | |
| if (action.includes('generate') || action.includes('create') || action.includes('implement')) { | |
| return { | |
| approved: true, | |
| reason: 'Code generation approved - will be reviewed before merge', | |
| modifications: ['Output requires Claude code review before integration'] | |
| }; | |
| } | |
| // 7. Test generation - always approved | |
| if (action.includes('test')) { | |
| return { | |
| approved: true, | |
| reason: 'Test creation is always welcome' | |
| }; | |
| } | |
| // Default: Approve with logging | |
| console.log(`β οΈ [ApprovalGate] New action type from ${fromAgent}: ${action}`); | |
| return { | |
| approved: true, | |
| reason: `Approved by Claude (delegated authority) - action: ${action}`, | |
| modifications: ['New action type - logged for pattern review'] | |
| }; | |
| } | |
| /** | |
| * Quick check without full review | |
| */ | |
| canProceed(fromAgent: AgentId, action: string): boolean { | |
| if (fromAgent === 'clak' || fromAgent === 'claude') return true; | |
| const needsEscalation = ESCALATE_TO_CLAK.some(e => | |
| action.toLowerCase().includes(e) | |
| ); | |
| return !needsEscalation; | |
| } | |
| } | |
| export const approvalGate = ApprovalGate.getInstance(); | |