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.
- package/.claude/commands/CFN_LOOP_TASK_MODE.md +7 -51
- package/.claude/commands/cfn-loop-cli.md +50 -125
- package/.claude/skills/cfn-agent-selector/SKILL.md +2 -2
- package/.claude/skills/cfn-agent-selector/select-agents.sh +0 -45
- package/.claude/skills/cfn-loop-orchestration/helpers/context-injection.sh +6 -69
- package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +0 -17
- package/README.md +2 -2
- package/claude-assets/agents/cfn-dev-team/CLAUDE.md +3 -3
- package/claude-assets/agents/cfn-dev-team/README.md +1 -1
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +2 -2
- package/claude-assets/agents/cfn-dev-team/developers/README.md +3 -3
- package/claude-assets/agents/cfn-dev-team/documentation/agent-type-guidelines.md +1 -1
- package/claude-assets/agents/cfn-dev-team/test-agent.md +2 -2
- package/claude-assets/commands/CFN_LOOP_TASK_MODE.md +7 -51
- package/claude-assets/commands/cfn-loop-cli.md +50 -125
- package/claude-assets/skills/cfn-agent-selector/SKILL.md +2 -2
- package/claude-assets/skills/cfn-agent-selector/select-agents.sh +0 -45
- package/claude-assets/skills/cfn-loop-orchestration/helpers/context-injection.sh +6 -69
- package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +0 -17
- package/claude-assets/skills/cfn-multi-coordinator-planning/README.md +256 -0
- package/claude-assets/skills/cfn-multi-coordinator-planning/SKILL.md +62 -0
- package/claude-assets/skills/cfn-multi-coordinator-planning/map-dependencies-conflicts.sh +376 -0
- package/claude-assets/skills/cfn-multi-coordinator-planning/plan-coordinator-resources.sh +258 -0
- package/claude-assets/skills/cfn-multi-coordinator-planning/plan-multi-coordinator-work.sh +267 -0
- package/claude-assets/skills/cfn-multi-coordinator-planning/plan-risk-rollout.sh +350 -0
- package/claude-assets/skills/cfn-multi-coordinator-planning/test-multi-coordinator-planning.sh +338 -0
- package/claude-assets/skills/cfn-multi-coordinator-planning/validate-task-planning.sh +189 -0
- package/dist/agents/agent-loader.js +165 -146
- package/dist/agents/agent-loader.js.map +1 -1
- package/package.json +1 -1
- package/.claude/skills/cfn-agent-selector/SKILL.md.backup_before_replace +0 -91
- package/.claude/skills/cfn-loop-orchestration/helpers/validate-task-context.sh +0 -241
- package/.claude/skills/pre-edit-backup/backup.sh +0 -130
- package/.claude/skills/pre-edit-backup/cleanup.sh +0 -155
- package/.claude/skills/pre-edit-backup/restore.sh +0 -128
- package/.claude/skills/pre-edit-backup/revert-file.sh +0 -168
- package/claude-assets/agents/cfn-dev-team/CLAUDE.md.backup_before_replace +0 -1086
- package/claude-assets/agents/cfn-dev-team/README.md.backup_before_replace +0 -116
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md.backup_before_replace +0 -451
- package/claude-assets/agents/cfn-dev-team/developers/README.md.backup_before_replace +0 -69
- package/claude-assets/agents/cfn-dev-team/documentation/agent-type-guidelines.md.backup_before_replace +0 -465
- package/claude-assets/agents/cfn-dev-team/test-agent.md.backup_before_replace +0 -141
- package/claude-assets/skills/CFN-LOOP-VALIDATION.md +0 -202
- package/claude-assets/skills/REDIS-COORDINATION.md +0 -187
- package/claude-assets/skills/SKILL.md +0 -229
- package/claude-assets/skills/agent-discovery/agents-registry.json +0 -484
- package/claude-assets/skills/agent-name-validation/README.md +0 -28
- package/claude-assets/skills/agent-name-validation/SKILL.md +0 -168
- package/claude-assets/skills/agent-name-validation/validate-agent-names.sh +0 -47
- package/claude-assets/skills/cfn-agent-selector/SKILL.md.backup_before_replace +0 -91
- package/claude-assets/skills/cfn-loop-orchestration/helpers/validate-task-context.sh +0 -241
- package/claude-assets/skills/consensus-calculator.js +0 -45
- package/claude-assets/skills/evidence-chain.sql +0 -66
- package/claude-assets/skills/hook-pipeline/bash-dependency-checker.sh +0 -89
- package/claude-assets/skills/hook-pipeline/bash-pipe-safety.sh +0 -69
- package/claude-assets/skills/hook-pipeline/enforce-lf.sh +0 -36
- package/claude-assets/skills/hook-pipeline/js-promise-safety.sh +0 -110
- package/claude-assets/skills/hook-pipeline/python-async-safety.py +0 -124
- package/claude-assets/skills/hook-pipeline/python-import-checker.py +0 -114
- package/claude-assets/skills/hook-pipeline/python-subprocess-safety.py +0 -77
- package/claude-assets/skills/hook-pipeline/rust-command-safety.sh +0 -38
- package/claude-assets/skills/hook-pipeline/rust-dependency-checker.sh +0 -50
- package/claude-assets/skills/hook-pipeline/rust-future-safety.sh +0 -50
- package/claude-assets/skills/pre-edit-backup/backup.sh +0 -130
- package/claude-assets/skills/pre-edit-backup/cleanup.sh +0 -155
- package/claude-assets/skills/pre-edit-backup/restore.sh +0 -128
- package/claude-assets/skills/pre-edit-backup/revert-file.sh +0 -168
- package/claude-assets/skills/run-all-skill-tests.sh +0 -124
- package/claude-assets/skills/seo-orchestration/SKILL.md +0 -292
- package/claude-assets/skills/seo-orchestration/orchestrate-seo.sh +0 -566
- package/claude-assets/skills/seo-orchestration/orchestrate-seo.sh.backup +0 -755
- package/claude-assets/skills/seo-orchestration/validate-consensus.sh +0 -270
- package/claude-assets/skills/team-provider-routing/execute-agent.sh +0 -76
- 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
|