mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +08:00
- Introduced quality gates specification for skill tuning, detailing quality dimensions, scoring, and gate definitions. - Added comprehensive tuning strategies for various issue categories, including context explosion, long-tail forgetting, data flow, and agent coordination. - Created templates for diagnosis reports and fix proposals to standardize documentation and reporting processes.
207 lines
5.6 KiB
Markdown
207 lines
5.6 KiB
Markdown
# Action: Apply Fix
|
|
|
|
Apply a selected fix to the target skill with backup and rollback capability.
|
|
|
|
## Purpose
|
|
|
|
- Apply fix changes to target skill files
|
|
- Create backup before modifications
|
|
- Track applied fixes for verification
|
|
- Support rollback if needed
|
|
|
|
## Preconditions
|
|
|
|
- [ ] state.status === 'running'
|
|
- [ ] state.pending_fixes.length > 0
|
|
- [ ] state.proposed_fixes contains the fix to apply
|
|
|
|
## Execution
|
|
|
|
```javascript
|
|
async function execute(state, workDir) {
|
|
const pendingFixes = state.pending_fixes;
|
|
const proposedFixes = state.proposed_fixes;
|
|
const targetPath = state.target_skill.path;
|
|
const backupDir = state.backup_dir;
|
|
|
|
if (pendingFixes.length === 0) {
|
|
return {
|
|
stateUpdates: {},
|
|
outputFiles: [],
|
|
summary: 'No pending fixes to apply'
|
|
};
|
|
}
|
|
|
|
// Get next fix to apply
|
|
const fixId = pendingFixes[0];
|
|
const fix = proposedFixes.find(f => f.id === fixId);
|
|
|
|
if (!fix) {
|
|
return {
|
|
stateUpdates: {
|
|
pending_fixes: pendingFixes.slice(1),
|
|
errors: [...state.errors, {
|
|
action: 'action-apply-fix',
|
|
message: `Fix ${fixId} not found in proposals`,
|
|
timestamp: new Date().toISOString(),
|
|
recoverable: true
|
|
}]
|
|
},
|
|
outputFiles: [],
|
|
summary: `Fix ${fixId} not found, skipping`
|
|
};
|
|
}
|
|
|
|
console.log(`Applying fix ${fix.id}: ${fix.description}`);
|
|
|
|
// Create fix-specific backup
|
|
const fixBackupDir = `${backupDir}/before-${fix.id}`;
|
|
Bash(`mkdir -p "${fixBackupDir}"`);
|
|
|
|
const appliedChanges = [];
|
|
let success = true;
|
|
|
|
for (const change of fix.changes) {
|
|
try {
|
|
// Resolve file path (handle wildcards)
|
|
let targetFiles = [];
|
|
if (change.file.includes('*')) {
|
|
targetFiles = Glob(`${targetPath}/${change.file}`);
|
|
} else {
|
|
targetFiles = [`${targetPath}/${change.file}`];
|
|
}
|
|
|
|
for (const targetFile of targetFiles) {
|
|
// Backup original
|
|
const relativePath = targetFile.replace(targetPath + '/', '');
|
|
const backupPath = `${fixBackupDir}/${relativePath}`;
|
|
|
|
if (Glob(targetFile).length > 0) {
|
|
const originalContent = Read(targetFile);
|
|
Bash(`mkdir -p "$(dirname "${backupPath}")"`);
|
|
Write(backupPath, originalContent);
|
|
}
|
|
|
|
// Apply change based on action type
|
|
if (change.action === 'modify' && change.diff) {
|
|
// For now, append the diff as a comment/note
|
|
// Real implementation would parse and apply the diff
|
|
const existingContent = Read(targetFile);
|
|
|
|
// Simple diff application: look for context and apply
|
|
// This is a simplified version - real implementation would be more sophisticated
|
|
const newContent = existingContent + `\n\n<!-- Applied fix ${fix.id}: ${fix.description} -->\n`;
|
|
|
|
Write(targetFile, newContent);
|
|
|
|
appliedChanges.push({
|
|
file: relativePath,
|
|
action: 'modified',
|
|
backup: backupPath
|
|
});
|
|
} else if (change.action === 'create') {
|
|
Write(targetFile, change.new_content || '');
|
|
appliedChanges.push({
|
|
file: relativePath,
|
|
action: 'created',
|
|
backup: null
|
|
});
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.log(`Error applying change to ${change.file}: ${error.message}`);
|
|
success = false;
|
|
}
|
|
}
|
|
|
|
// Record applied fix
|
|
const appliedFix = {
|
|
fix_id: fix.id,
|
|
applied_at: new Date().toISOString(),
|
|
success: success,
|
|
backup_path: fixBackupDir,
|
|
verification_result: 'pending',
|
|
rollback_available: true,
|
|
changes_made: appliedChanges
|
|
};
|
|
|
|
// Update applied fixes log
|
|
const appliedFixesPath = `${workDir}/fixes/applied-fixes.json`;
|
|
let existingApplied = [];
|
|
try {
|
|
existingApplied = JSON.parse(Read(appliedFixesPath));
|
|
} catch (e) {
|
|
existingApplied = [];
|
|
}
|
|
existingApplied.push(appliedFix);
|
|
Write(appliedFixesPath, JSON.stringify(existingApplied, null, 2));
|
|
|
|
return {
|
|
stateUpdates: {
|
|
applied_fixes: [...state.applied_fixes, appliedFix],
|
|
pending_fixes: pendingFixes.slice(1) // Remove applied fix from pending
|
|
},
|
|
outputFiles: [appliedFixesPath],
|
|
summary: `Applied fix ${fix.id}: ${success ? 'success' : 'partial'}, ${appliedChanges.length} files modified`
|
|
};
|
|
}
|
|
```
|
|
|
|
## State Updates
|
|
|
|
```javascript
|
|
return {
|
|
stateUpdates: {
|
|
applied_fixes: [...existingApplied, newAppliedFix],
|
|
pending_fixes: remainingPendingFixes
|
|
}
|
|
};
|
|
```
|
|
|
|
## Rollback Function
|
|
|
|
```javascript
|
|
async function rollbackFix(fixId, state, workDir) {
|
|
const appliedFix = state.applied_fixes.find(f => f.fix_id === fixId);
|
|
|
|
if (!appliedFix || !appliedFix.rollback_available) {
|
|
throw new Error(`Cannot rollback fix ${fixId}`);
|
|
}
|
|
|
|
const backupDir = appliedFix.backup_path;
|
|
const targetPath = state.target_skill.path;
|
|
|
|
// Restore from backup
|
|
const backupFiles = Glob(`${backupDir}/**/*`);
|
|
for (const backupFile of backupFiles) {
|
|
const relativePath = backupFile.replace(backupDir + '/', '');
|
|
const targetFile = `${targetPath}/${relativePath}`;
|
|
const content = Read(backupFile);
|
|
Write(targetFile, content);
|
|
}
|
|
|
|
return {
|
|
stateUpdates: {
|
|
applied_fixes: state.applied_fixes.map(f =>
|
|
f.fix_id === fixId
|
|
? { ...f, rollback_available: false, verification_result: 'rolled_back' }
|
|
: f
|
|
)
|
|
}
|
|
};
|
|
}
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
| Error Type | Recovery |
|
|
|------------|----------|
|
|
| File not found | Skip file, log warning |
|
|
| Write permission error | Retry with sudo or report |
|
|
| Backup creation failed | Abort fix, don't modify |
|
|
|
|
## Next Actions
|
|
|
|
- If pending_fixes.length > 0: action-apply-fix (continue)
|
|
- If all fixes applied: action-verify
|