claude-flow-novice 2.14.13 → 2.14.15

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.
Files changed (74) hide show
  1. package/.claude/commands/CFN_LOOP_TASK_MODE.md +7 -51
  2. package/.claude/commands/cfn-loop-cli.md +50 -125
  3. package/.claude/skills/cfn-agent-selector/SKILL.md +2 -2
  4. package/.claude/skills/cfn-agent-selector/select-agents.sh +0 -45
  5. package/.claude/skills/cfn-loop-orchestration/helpers/context-injection.sh +6 -69
  6. package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +0 -17
  7. package/README.md +2 -2
  8. package/claude-assets/agents/cfn-dev-team/CLAUDE.md +3 -3
  9. package/claude-assets/agents/cfn-dev-team/README.md +1 -1
  10. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +2 -2
  11. package/claude-assets/agents/cfn-dev-team/developers/README.md +3 -3
  12. package/claude-assets/agents/cfn-dev-team/documentation/agent-type-guidelines.md +1 -1
  13. package/claude-assets/agents/cfn-dev-team/test-agent.md +2 -2
  14. package/claude-assets/commands/CFN_LOOP_TASK_MODE.md +7 -51
  15. package/claude-assets/commands/cfn-loop-cli.md +50 -125
  16. package/claude-assets/skills/cfn-agent-selector/SKILL.md +2 -2
  17. package/claude-assets/skills/cfn-agent-selector/select-agents.sh +0 -45
  18. package/claude-assets/skills/cfn-loop-orchestration/helpers/context-injection.sh +6 -69
  19. package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +0 -17
  20. package/claude-assets/skills/cfn-multi-coordinator-planning/README.md +256 -0
  21. package/claude-assets/skills/cfn-multi-coordinator-planning/SKILL.md +62 -0
  22. package/claude-assets/skills/cfn-multi-coordinator-planning/map-dependencies-conflicts.sh +376 -0
  23. package/claude-assets/skills/cfn-multi-coordinator-planning/plan-coordinator-resources.sh +258 -0
  24. package/claude-assets/skills/cfn-multi-coordinator-planning/plan-multi-coordinator-work.sh +267 -0
  25. package/claude-assets/skills/cfn-multi-coordinator-planning/plan-risk-rollout.sh +350 -0
  26. package/claude-assets/skills/cfn-multi-coordinator-planning/test-multi-coordinator-planning.sh +338 -0
  27. package/claude-assets/skills/cfn-multi-coordinator-planning/validate-task-planning.sh +189 -0
  28. package/dist/agents/agent-loader.js +165 -146
  29. package/dist/agents/agent-loader.js.map +1 -1
  30. package/package.json +1 -1
  31. package/.claude/skills/cfn-agent-selector/SKILL.md.backup_before_replace +0 -91
  32. package/.claude/skills/cfn-loop-orchestration/helpers/validate-task-context.sh +0 -241
  33. package/.claude/skills/pre-edit-backup/backup.sh +0 -130
  34. package/.claude/skills/pre-edit-backup/cleanup.sh +0 -155
  35. package/.claude/skills/pre-edit-backup/restore.sh +0 -128
  36. package/.claude/skills/pre-edit-backup/revert-file.sh +0 -168
  37. package/claude-assets/agents/cfn-dev-team/CLAUDE.md.backup_before_replace +0 -1086
  38. package/claude-assets/agents/cfn-dev-team/README.md.backup_before_replace +0 -116
  39. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md.backup_before_replace +0 -451
  40. package/claude-assets/agents/cfn-dev-team/developers/README.md.backup_before_replace +0 -69
  41. package/claude-assets/agents/cfn-dev-team/documentation/agent-type-guidelines.md.backup_before_replace +0 -465
  42. package/claude-assets/agents/cfn-dev-team/test-agent.md.backup_before_replace +0 -141
  43. package/claude-assets/skills/CFN-LOOP-VALIDATION.md +0 -202
  44. package/claude-assets/skills/REDIS-COORDINATION.md +0 -187
  45. package/claude-assets/skills/SKILL.md +0 -229
  46. package/claude-assets/skills/agent-discovery/agents-registry.json +0 -484
  47. package/claude-assets/skills/agent-name-validation/README.md +0 -28
  48. package/claude-assets/skills/agent-name-validation/SKILL.md +0 -168
  49. package/claude-assets/skills/agent-name-validation/validate-agent-names.sh +0 -47
  50. package/claude-assets/skills/cfn-agent-selector/SKILL.md.backup_before_replace +0 -91
  51. package/claude-assets/skills/cfn-loop-orchestration/helpers/validate-task-context.sh +0 -241
  52. package/claude-assets/skills/consensus-calculator.js +0 -45
  53. package/claude-assets/skills/evidence-chain.sql +0 -66
  54. package/claude-assets/skills/hook-pipeline/bash-dependency-checker.sh +0 -89
  55. package/claude-assets/skills/hook-pipeline/bash-pipe-safety.sh +0 -69
  56. package/claude-assets/skills/hook-pipeline/enforce-lf.sh +0 -36
  57. package/claude-assets/skills/hook-pipeline/js-promise-safety.sh +0 -110
  58. package/claude-assets/skills/hook-pipeline/python-async-safety.py +0 -124
  59. package/claude-assets/skills/hook-pipeline/python-import-checker.py +0 -114
  60. package/claude-assets/skills/hook-pipeline/python-subprocess-safety.py +0 -77
  61. package/claude-assets/skills/hook-pipeline/rust-command-safety.sh +0 -38
  62. package/claude-assets/skills/hook-pipeline/rust-dependency-checker.sh +0 -50
  63. package/claude-assets/skills/hook-pipeline/rust-future-safety.sh +0 -50
  64. package/claude-assets/skills/pre-edit-backup/backup.sh +0 -130
  65. package/claude-assets/skills/pre-edit-backup/cleanup.sh +0 -155
  66. package/claude-assets/skills/pre-edit-backup/restore.sh +0 -128
  67. package/claude-assets/skills/pre-edit-backup/revert-file.sh +0 -168
  68. package/claude-assets/skills/run-all-skill-tests.sh +0 -124
  69. package/claude-assets/skills/seo-orchestration/SKILL.md +0 -292
  70. package/claude-assets/skills/seo-orchestration/orchestrate-seo.sh +0 -566
  71. package/claude-assets/skills/seo-orchestration/orchestrate-seo.sh.backup +0 -755
  72. package/claude-assets/skills/seo-orchestration/validate-consensus.sh +0 -270
  73. package/claude-assets/skills/team-provider-routing/execute-agent.sh +0 -76
  74. package/claude-assets/skills/test-execution-coordinator-pattern.md +0 -228
@@ -1,50 +0,0 @@
1
- #!/bin/bash
2
- # Rust Dependency Checker
3
- set -o pipefail
4
-
5
- # Exit codes:
6
- # 0 - No issues found
7
- # 1 - Cargo.toml not found or cannot be read
8
- # 2 - Dependency warnings found
9
-
10
- if [ $# -eq 0 ]; then
11
- echo "Usage: $0 <rust_file>"
12
- exit 1
13
- fi
14
-
15
- file_path="$1"
16
- project_dir=$(dirname "$file_path")
17
- cargo_toml="${project_dir}/Cargo.toml"
18
-
19
- if [ ! -f "$cargo_toml" ]; then
20
- echo "Cargo.toml not found in project directory"
21
- exit 1
22
- fi
23
-
24
- # Skip list for built-in/standard libraries
25
- skip_modules="std|core|alloc|proc_macro"
26
-
27
- # Find local crate dependencies in the file
28
- local_deps=$(grep -o "use crate::[a-zA-Z_][a-zA-Z0-9_:]*" "$file_path" |
29
- sed 's/use crate:://g' |
30
- cut -d':' -f1 |
31
- sort -u |
32
- grep -vE "^(${skip_modules})$")
33
-
34
- # Check dependencies in Cargo.toml
35
- if [ -n "$local_deps" ]; then
36
- warnings=$(echo "$local_deps" | while read -r dep; do
37
- if ! grep -q "path = \".*${dep}\"" "$cargo_toml"; then
38
- echo "Undeclared local crate dependency: ${dep}"
39
- fi
40
- done)
41
-
42
- if [ -n "$warnings" ]; then
43
- echo "Dependency warnings:"
44
- echo "$warnings"
45
- echo "Recommendation: Declare local crate dependencies in Cargo.toml"
46
- exit 2
47
- fi
48
- fi
49
-
50
- exit 0
@@ -1,50 +0,0 @@
1
- #!/bin/bash
2
- # Rust Future Safety Validator
3
- set -o pipefail
4
-
5
- # Exit codes:
6
- # 0 - No issues found
7
- # 1 - File not found or cannot be read
8
- # 2 - Future safety warnings found
9
-
10
- if [ $# -eq 0 ]; then
11
- echo "Usage: $0 <rust_file>"
12
- exit 1
13
- fi
14
-
15
- file_path="$1"
16
-
17
- if [ ! -f "$file_path" ]; then
18
- echo "File not found: $file_path"
19
- exit 1
20
- fi
21
-
22
- # Find async function definitions
23
- async_functions=$(grep -n "async fn" "$file_path")
24
-
25
- if [ -n "$async_functions" ]; then
26
- warnings=$(echo "$async_functions" | while read -r async_line; do
27
- line_num=$(echo "$async_line" | cut -d':' -f1)
28
- func_name=$(echo "$async_line" | sed -n 's/.*async fn \([a-zA-Z_][a-zA-Z0-9_]*\).*/\1/p')
29
-
30
- # Search for function calls without .await
31
- calls_without_await=$(grep -n "\\b${func_name}(" "$file_path" |
32
- grep -v ".await" |
33
- grep -v "async fn" |
34
- grep -v "fn ${func_name}")
35
-
36
- if [ -n "$calls_without_await" ]; then
37
- echo "Lines related to async function '${func_name}':"
38
- echo "$calls_without_await"
39
- echo "Recommendation: Use .await for async function calls. Run cargo clippy for more details."
40
- fi
41
- done)
42
-
43
- if [ -n "$warnings" ]; then
44
- echo "Future safety warnings:"
45
- echo "$warnings"
46
- exit 2
47
- fi
48
- fi
49
-
50
- exit 0
@@ -1,130 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Pre-Edit Backup Script
4
- # Creates timestamped backup with SHA-256 hash and JSON metadata
5
- #
6
- # Usage: backup.sh FILE_PATH AGENT_ID
7
- #
8
- # Arguments:
9
- # FILE_PATH - Absolute path to file to backup
10
- # AGENT_ID - Unique identifier for the agent creating the backup
11
- #
12
- # Returns:
13
- # Backup directory path on success
14
- # Exit code 1 on failure
15
- #
16
- # Example:
17
- # ./.claude/skills/pre-edit-backup/backup.sh "/path/to/file.txt" "backend-dev-1"
18
-
19
- set -euo pipefail
20
-
21
- # === Input Validation ===
22
-
23
- FILE_PATH="$1"
24
- AGENT_ID="$2"
25
-
26
- if [[ -z "$FILE_PATH" ]]; then
27
- echo "Error: No file path provided" >&2
28
- echo "Usage: backup.sh FILE_PATH AGENT_ID" >&2
29
- exit 1
30
- fi
31
-
32
- if [[ -z "$AGENT_ID" ]]; then
33
- echo "Error: No agent ID provided" >&2
34
- echo "Usage: backup.sh FILE_PATH AGENT_ID" >&2
35
- exit 1
36
- fi
37
-
38
- if [[ ! -f "$FILE_PATH" ]]; then
39
- echo "Error: File does not exist: $FILE_PATH" >&2
40
- exit 1
41
- fi
42
-
43
- # === Configuration ===
44
-
45
- BACKUP_BASE_DIR=".backups"
46
- DEFAULT_TTL=86400 # 24 hours in seconds
47
-
48
- # === Tool Availability Checks ===
49
-
50
- # Check for sha256sum (with fallback to shasum on macOS)
51
- if command -v sha256sum &>/dev/null; then
52
- HASH_TOOL="sha256sum"
53
- elif command -v shasum &>/dev/null; then
54
- HASH_TOOL="shasum -a 256"
55
- else
56
- echo "Error: Neither sha256sum nor shasum found. Cannot generate file hash." >&2
57
- exit 1
58
- fi
59
-
60
- # Check for jq (graceful degradation)
61
- if ! command -v jq &>/dev/null; then
62
- echo "Warning: jq not found. Metadata will be created using basic shell." >&2
63
- USE_JQ=false
64
- else
65
- USE_JQ=true
66
- fi
67
-
68
- # === Generate Backup Metadata ===
69
-
70
- TIMESTAMP=$(date +%s%3N 2>/dev/null || date +%s) # Milliseconds if supported, else seconds
71
- FILE_HASH=$($HASH_TOOL "$FILE_PATH" | cut -d' ' -f1)
72
-
73
- # === Create Backup Directory ===
74
-
75
- BACKUP_DIR="${BACKUP_BASE_DIR}/${AGENT_ID}/${TIMESTAMP}_${FILE_HASH}"
76
-
77
- if ! mkdir -p "$BACKUP_DIR" 2>/dev/null; then
78
- echo "Error: Failed to create backup directory: $BACKUP_DIR" >&2
79
- exit 1
80
- fi
81
-
82
- # Set secure permissions (owner read/write/execute only)
83
- chmod 700 "$BACKUP_DIR" 2>/dev/null || true
84
-
85
- # === Copy Original File ===
86
-
87
- if ! cp "$FILE_PATH" "${BACKUP_DIR}/original_file" 2>/dev/null; then
88
- echo "Error: Failed to copy file to backup directory" >&2
89
- rm -rf "$BACKUP_DIR"
90
- exit 1
91
- fi
92
-
93
- # === Generate Metadata ===
94
-
95
- METADATA_FILE="${BACKUP_DIR}/backup_metadata.json"
96
-
97
- if [[ "$USE_JQ" == true ]]; then
98
- # Use jq for structured JSON generation
99
- jq -n \
100
- --arg agent_id "$AGENT_ID" \
101
- --arg original_path "$FILE_PATH" \
102
- --arg timestamp "$TIMESTAMP" \
103
- --arg file_hash "$FILE_HASH" \
104
- --arg ttl "$DEFAULT_TTL" \
105
- '{
106
- agent_id: $agent_id,
107
- original_path: $original_path,
108
- backup_timestamp: ($timestamp | tonumber),
109
- file_hash: $file_hash,
110
- backup_ttl: ($ttl | tonumber),
111
- backup_status: "active"
112
- }' > "$METADATA_FILE"
113
- else
114
- # Fallback: Manual JSON generation
115
- cat > "$METADATA_FILE" <<EOF
116
- {
117
- "agent_id": "$AGENT_ID",
118
- "original_path": "$FILE_PATH",
119
- "backup_timestamp": $TIMESTAMP,
120
- "file_hash": "$FILE_HASH",
121
- "backup_ttl": $DEFAULT_TTL,
122
- "backup_status": "active"
123
- }
124
- EOF
125
- fi
126
-
127
- # === Return Backup Path ===
128
-
129
- echo "$BACKUP_DIR"
130
- exit 0
@@ -1,155 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Pre-Edit Backup Cleanup Script
4
- # Removes expired backups based on TTL configuration
5
- # Runs as background process or cron-style with flock for concurrency control
6
- #
7
- # Usage: cleanup.sh [--dry-run] [--log-file FILE]
8
- #
9
- # Options:
10
- # --dry-run - Show what would be deleted without actually deleting
11
- # --log-file - Path to log file (default: none, outputs to stdout)
12
- #
13
- # Returns:
14
- # Exit code 0 on success
15
- # Exit code 1 if cleanup already in progress
16
- #
17
- # Example:
18
- # ./.claude/skills/pre-edit-backup/cleanup.sh
19
- # ./.claude/skills/pre-edit-backup/cleanup.sh --dry-run
20
- # ./.claude/skills/pre-edit-backup/cleanup.sh --log-file /tmp/backup-cleanup.log
21
-
22
- set -euo pipefail
23
-
24
- # === Configuration ===
25
-
26
- BACKUP_BASE_DIR=".backups"
27
- CURRENT_TIME=$(date +%s)
28
- DRY_RUN=false
29
- LOG_FILE=""
30
-
31
- # === Parse Options ===
32
-
33
- while [[ "$#" -gt 0 ]]; do
34
- case $1 in
35
- --dry-run)
36
- DRY_RUN=true
37
- shift
38
- ;;
39
- --log-file)
40
- LOG_FILE="$2"
41
- shift 2
42
- ;;
43
- *)
44
- echo "Error: Unknown option: $1" >&2
45
- echo "Usage: cleanup.sh [--dry-run] [--log-file FILE]" >&2
46
- exit 1
47
- ;;
48
- esac
49
- done
50
-
51
- # === Logging Function ===
52
-
53
- log() {
54
- local message="$1"
55
- local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
56
- local log_line="[$timestamp] $message"
57
-
58
- if [[ -n "$LOG_FILE" ]]; then
59
- echo "$log_line" >> "$LOG_FILE"
60
- else
61
- echo "$log_line"
62
- fi
63
- }
64
-
65
- # === Prevent Concurrent Cleanup ===
66
-
67
- if [[ ! -d "$BACKUP_BASE_DIR" ]]; then
68
- log "Backup directory does not exist: $BACKUP_BASE_DIR"
69
- exit 0
70
- fi
71
-
72
- LOCKFILE="${BACKUP_BASE_DIR}/cleanup.lock"
73
-
74
- # Ensure lock file directory exists
75
- mkdir -p "$(dirname "$LOCKFILE")" 2>/dev/null || true
76
-
77
- # Acquire lock (non-blocking)
78
- exec 9>"$LOCKFILE"
79
- if ! flock -n 9; then
80
- log "Cleanup already in progress (lock held)"
81
- exit 1
82
- fi
83
-
84
- log "Cleanup started (dry-run: $DRY_RUN)"
85
-
86
- # === Cleanup Logic ===
87
-
88
- REMOVED_COUNT=0
89
- SKIPPED_COUNT=0
90
- ERROR_COUNT=0
91
-
92
- # Check for jq availability
93
- if ! command -v jq &>/dev/null; then
94
- log "Error: jq is required for cleanup operations"
95
- exit 1
96
- fi
97
-
98
- # Iterate through agent directories
99
- for agent_dir in "$BACKUP_BASE_DIR"/*; do
100
- # Skip if not a directory or if it's the lockfile
101
- [[ -d "$agent_dir" ]] || continue
102
- [[ "$(basename "$agent_dir")" == "cleanup.lock" ]] && continue
103
-
104
- # Iterate through backup directories for this agent
105
- for backup_dir in "$agent_dir"/*; do
106
- [[ -d "$backup_dir" ]] || continue
107
-
108
- metadata_file="${backup_dir}/backup_metadata.json"
109
-
110
- if [[ ! -f "$metadata_file" ]]; then
111
- log "Warning: Metadata missing for backup: ${backup_dir}"
112
- SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
113
- continue
114
- fi
115
-
116
- # Extract backup timestamp and TTL
117
- backup_timestamp=$(jq -r '.backup_timestamp' "$metadata_file" 2>/dev/null || echo "")
118
- backup_ttl=$(jq -r '.backup_ttl' "$metadata_file" 2>/dev/null || echo "")
119
-
120
- if [[ -z "$backup_timestamp" ]] || [[ "$backup_timestamp" == "null" ]] || \
121
- [[ -z "$backup_ttl" ]] || [[ "$backup_ttl" == "null" ]]; then
122
- log "Warning: Invalid metadata in: ${metadata_file}"
123
- SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
124
- continue
125
- fi
126
-
127
- # Convert milliseconds to seconds if needed (timestamp > 10 digits = milliseconds)
128
- if [[ ${#backup_timestamp} -gt 10 ]]; then
129
- backup_timestamp=$((backup_timestamp / 1000))
130
- fi
131
-
132
- # Check if backup has expired
133
- age=$((CURRENT_TIME - backup_timestamp))
134
- if (( age > backup_ttl )); then
135
- if [[ "$DRY_RUN" == true ]]; then
136
- log "Would remove expired backup (age: ${age}s, ttl: ${backup_ttl}s): ${backup_dir}"
137
- REMOVED_COUNT=$((REMOVED_COUNT + 1))
138
- else
139
- if rm -rf "$backup_dir" 2>/dev/null; then
140
- log "Removed expired backup (age: ${age}s, ttl: ${backup_ttl}s): ${backup_dir}"
141
- REMOVED_COUNT=$((REMOVED_COUNT + 1))
142
- else
143
- log "Error: Failed to remove backup: ${backup_dir}"
144
- ERROR_COUNT=$((ERROR_COUNT + 1))
145
- fi
146
- fi
147
- fi
148
- done
149
- done
150
-
151
- # === Summary ===
152
-
153
- log "Cleanup completed: removed=$REMOVED_COUNT, skipped=$SKIPPED_COUNT, errors=$ERROR_COUNT"
154
-
155
- exit 0
@@ -1,128 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Pre-Edit Restore Script
4
- # Restores file from backup and updates metadata
5
- #
6
- # Usage: restore.sh BACKUP_DIR [--list FILE_PATH AGENT_ID]
7
- #
8
- # Arguments:
9
- # BACKUP_DIR - Path to backup directory containing backup_metadata.json
10
- # --list - List available backups for a file (requires FILE_PATH and AGENT_ID)
11
- #
12
- # Returns:
13
- # Exit code 0 on success
14
- # Exit code 1 on failure
15
- #
16
- # Example:
17
- # ./.claude/skills/pre-edit-backup/restore.sh ".backups/backend-dev-1/1698764800000_abc123"
18
- # ./.claude/skills/pre-edit-backup/restore.sh --list "/path/to/file.txt" "backend-dev-1"
19
-
20
- set -euo pipefail
21
-
22
- # === Handle --list Mode ===
23
-
24
- if [[ "${1:-}" == "--list" ]]; then
25
- FILE_PATH="$2"
26
- AGENT_ID="$3"
27
-
28
- if [[ -z "$FILE_PATH" ]] || [[ -z "$AGENT_ID" ]]; then
29
- echo "Error: --list requires FILE_PATH and AGENT_ID" >&2
30
- exit 1
31
- fi
32
-
33
- BACKUP_BASE_DIR=".backups"
34
- AGENT_BACKUP_DIR="${BACKUP_BASE_DIR}/${AGENT_ID}"
35
-
36
- if [[ ! -d "$AGENT_BACKUP_DIR" ]]; then
37
- echo "No backups found for agent: $AGENT_ID" >&2
38
- exit 1
39
- fi
40
-
41
- echo "Available backups for $FILE_PATH (agent: $AGENT_ID):"
42
- echo "---"
43
-
44
- FOUND_BACKUPS=0
45
- for backup_dir in "$AGENT_BACKUP_DIR"/*; do
46
- if [[ -f "${backup_dir}/backup_metadata.json" ]]; then
47
- ORIGINAL=$(jq -r '.original_path' "${backup_dir}/backup_metadata.json" 2>/dev/null || echo "")
48
- if [[ "$ORIGINAL" == "$FILE_PATH" ]]; then
49
- TIMESTAMP=$(jq -r '.backup_timestamp' "${backup_dir}/backup_metadata.json" 2>/dev/null || echo "unknown")
50
- STATUS=$(jq -r '.backup_status' "${backup_dir}/backup_metadata.json" 2>/dev/null || echo "unknown")
51
- echo "Backup: $(basename "$backup_dir")"
52
- echo " Timestamp: $TIMESTAMP"
53
- echo " Status: $STATUS"
54
- echo " Path: $backup_dir"
55
- echo "---"
56
- FOUND_BACKUPS=$((FOUND_BACKUPS + 1))
57
- fi
58
- fi
59
- done
60
-
61
- if [[ $FOUND_BACKUPS -eq 0 ]]; then
62
- echo "No backups found for this file."
63
- exit 1
64
- fi
65
-
66
- exit 0
67
- fi
68
-
69
- # === Restore Mode ===
70
-
71
- BACKUP_DIR="$1"
72
-
73
- if [[ -z "$BACKUP_DIR" ]]; then
74
- echo "Error: No backup directory provided" >&2
75
- echo "Usage: restore.sh BACKUP_DIR" >&2
76
- exit 1
77
- fi
78
-
79
- if [[ ! -d "$BACKUP_DIR" ]]; then
80
- echo "Error: Backup directory does not exist: $BACKUP_DIR" >&2
81
- exit 1
82
- fi
83
-
84
- METADATA_FILE="${BACKUP_DIR}/backup_metadata.json"
85
- BACKUP_FILE="${BACKUP_DIR}/original_file"
86
-
87
- if [[ ! -f "$METADATA_FILE" ]]; then
88
- echo "Error: Backup metadata not found: $METADATA_FILE" >&2
89
- exit 1
90
- fi
91
-
92
- if [[ ! -f "$BACKUP_FILE" ]]; then
93
- echo "Error: Backup file not found: $BACKUP_FILE" >&2
94
- exit 1
95
- fi
96
-
97
- # Check for jq availability
98
- if ! command -v jq &>/dev/null; then
99
- echo "Error: jq is required for restore operations" >&2
100
- exit 1
101
- fi
102
-
103
- # Extract original path
104
- ORIGINAL_PATH=$(jq -r '.original_path' "$METADATA_FILE" 2>/dev/null)
105
-
106
- if [[ -z "$ORIGINAL_PATH" ]] || [[ "$ORIGINAL_PATH" == "null" ]]; then
107
- echo "Error: Failed to read original path from metadata" >&2
108
- exit 1
109
- fi
110
-
111
- # Restore file
112
- if ! cp "$BACKUP_FILE" "$ORIGINAL_PATH" 2>/dev/null; then
113
- echo "Error: Failed to restore file to: $ORIGINAL_PATH" >&2
114
- exit 1
115
- fi
116
-
117
- # Update backup status
118
- TEMP_FILE=$(mktemp)
119
- if jq '.backup_status = "restored"' "$METADATA_FILE" > "$TEMP_FILE" 2>/dev/null; then
120
- mv "$TEMP_FILE" "$METADATA_FILE"
121
- else
122
- echo "Warning: Failed to update backup status in metadata" >&2
123
- rm -f "$TEMP_FILE"
124
- fi
125
-
126
- echo "File restored from backup: ${BACKUP_DIR}"
127
- echo "Restored to: ${ORIGINAL_PATH}"
128
- exit 0
@@ -1,168 +0,0 @@
1
- #!/bin/bash
2
- #
3
- # Revert File Utility
4
- # High-level revert interface for agents to use instead of git operations
5
- #
6
- # Usage:
7
- # ./.claude/skills/pre-edit-backup/revert-file.sh <file_path> [--agent-id <id>] [--interactive]
8
- #
9
- # Examples:
10
- # # Revert to most recent backup (auto-select)
11
- # ./.claude/skills/pre-edit-backup/revert-file.sh src/file.ts --agent-id "coder-1"
12
- #
13
- # # Interactive mode (shows list of backups)
14
- # ./.claude/skills/pre-edit-backup/revert-file.sh src/file.ts --agent-id "coder-1" --interactive
15
- #
16
- # # List available backups without reverting
17
- # ./.claude/skills/pre-edit-backup/revert-file.sh src/file.ts --agent-id "coder-1" --list-only
18
-
19
- set -euo pipefail
20
-
21
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
22
- BACKUP_BASE_DIR=".backups"
23
-
24
- # Parse arguments
25
- FILE_PATH=""
26
- AGENT_ID="${AGENT_ID:-unknown}"
27
- INTERACTIVE=false
28
- LIST_ONLY=false
29
-
30
- while [[ $# -gt 0 ]]; do
31
- case $1 in
32
- --agent-id)
33
- AGENT_ID="$2"
34
- shift 2
35
- ;;
36
- --interactive)
37
- INTERACTIVE=true
38
- shift
39
- ;;
40
- --list-only)
41
- LIST_ONLY=true
42
- shift
43
- ;;
44
- *)
45
- FILE_PATH="$1"
46
- shift
47
- ;;
48
- esac
49
- done
50
-
51
- # Validate inputs
52
- if [ -z "$FILE_PATH" ]; then
53
- echo "Error: File path required"
54
- echo "Usage: $0 <file_path> [--agent-id <id>] [--interactive] [--list-only]"
55
- exit 1
56
- fi
57
-
58
- # Normalize file path
59
- FILE_PATH=$(realpath "$FILE_PATH" 2>/dev/null || echo "$FILE_PATH")
60
-
61
- # Find backups for this file
62
- AGENT_BACKUP_DIR="$BACKUP_BASE_DIR/$AGENT_ID"
63
-
64
- if [ ! -d "$AGENT_BACKUP_DIR" ]; then
65
- echo "❌ No backups found for agent: $AGENT_ID"
66
- exit 1
67
- fi
68
-
69
- # Search for backups matching this file
70
- MATCHING_BACKUPS=()
71
- while IFS= read -r backup_dir; do
72
- metadata_file="$backup_dir/backup_metadata.json"
73
-
74
- if [ -f "$metadata_file" ]; then
75
- original_path=$(jq -r '.original_path' "$metadata_file" 2>/dev/null || echo "")
76
-
77
- # Normalize original path for comparison
78
- original_path=$(realpath "$original_path" 2>/dev/null || echo "$original_path")
79
-
80
- if [ "$original_path" = "$FILE_PATH" ]; then
81
- MATCHING_BACKUPS+=("$backup_dir")
82
- fi
83
- fi
84
- done < <(find "$AGENT_BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d | sort -r)
85
-
86
- # Check if any backups found
87
- if [ ${#MATCHING_BACKUPS[@]} -eq 0 ]; then
88
- echo "❌ No backups found for file: $FILE_PATH"
89
- exit 1
90
- fi
91
-
92
- # List backups function
93
- list_backups() {
94
- echo "Available backups for: $FILE_PATH"
95
- echo "----------------------------------------"
96
-
97
- local index=1
98
- for backup_dir in "${MATCHING_BACKUPS[@]}"; do
99
- metadata_file="$backup_dir/backup_metadata.json"
100
-
101
- timestamp=$(jq -r '.backup_timestamp' "$metadata_file")
102
- status=$(jq -r '.backup_status' "$metadata_file")
103
-
104
- # Convert timestamp to readable date
105
- if command -v date >/dev/null 2>&1; then
106
- # Handle millisecond timestamps
107
- timestamp_seconds=$((timestamp / 1000))
108
- date_str=$(date -d "@$timestamp_seconds" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || date -r "$timestamp_seconds" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "Unknown")
109
- else
110
- date_str="$timestamp"
111
- fi
112
-
113
- echo "[$index] $date_str (Status: $status)"
114
- echo " Path: $backup_dir"
115
-
116
- ((index++))
117
- done
118
- echo "----------------------------------------"
119
- }
120
-
121
- # List-only mode
122
- if [ "$LIST_ONLY" = true ]; then
123
- list_backups
124
- exit 0
125
- fi
126
-
127
- # Interactive mode
128
- if [ "$INTERACTIVE" = true ]; then
129
- list_backups
130
- echo ""
131
- echo -n "Select backup to restore [1-${#MATCHING_BACKUPS[@]}] (or 0 to cancel): "
132
- read -r selection
133
-
134
- if [ "$selection" = "0" ]; then
135
- echo "❌ Revert cancelled"
136
- exit 0
137
- fi
138
-
139
- if ! [[ "$selection" =~ ^[0-9]+$ ]] || [ "$selection" -lt 1 ] || [ "$selection" -gt ${#MATCHING_BACKUPS[@]} ]; then
140
- echo "❌ Invalid selection: $selection"
141
- exit 1
142
- fi
143
-
144
- SELECTED_BACKUP="${MATCHING_BACKUPS[$((selection - 1))]}"
145
- else
146
- # Auto-select most recent backup (first in sorted list)
147
- SELECTED_BACKUP="${MATCHING_BACKUPS[0]}"
148
-
149
- metadata_file="$SELECTED_BACKUP/backup_metadata.json"
150
- timestamp=$(jq -r '.backup_timestamp' "$metadata_file")
151
- timestamp_seconds=$((timestamp / 1000))
152
- date_str=$(date -d "@$timestamp_seconds" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || date -r "$timestamp_seconds" '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "timestamp: $timestamp")
153
-
154
- echo "🔄 Auto-selecting most recent backup: $date_str"
155
- fi
156
-
157
- # Restore using restore.sh
158
- echo "🔄 Restoring file from backup..."
159
- "$SCRIPT_DIR/restore.sh" "$SELECTED_BACKUP"
160
-
161
- if [ $? -eq 0 ]; then
162
- echo "✅ File successfully reverted to backup"
163
- echo " Backup: $SELECTED_BACKUP"
164
- exit 0
165
- else
166
- echo "❌ Failed to revert file"
167
- exit 1
168
- fi