Spaces:
Paused
Paused
File size: 7,676 Bytes
529090e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | /**
* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
* β 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();
|