aidevops 3.8.71 → 3.8.72
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/VERSION +1 -1
- package/aidevops.sh +101 -9
- package/package.json +1 -1
- package/setup-modules/migrations.sh +56 -0
- package/setup.sh +4 -3
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.8.
|
|
1
|
+
3.8.72
|
package/aidevops.sh
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# AI DevOps Framework CLI
|
|
6
6
|
# Usage: aidevops <command> [options]
|
|
7
7
|
#
|
|
8
|
-
# Version: 3.8.
|
|
8
|
+
# Version: 3.8.72
|
|
9
9
|
|
|
10
10
|
set -euo pipefail
|
|
11
11
|
|
|
@@ -61,11 +61,31 @@ _timeout_cmd() {
|
|
|
61
61
|
fi
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
print_info() {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
print_info() {
|
|
65
|
+
local msg="$1"
|
|
66
|
+
echo -e "${BLUE}[INFO]${NC} $msg"
|
|
67
|
+
return 0
|
|
68
|
+
}
|
|
69
|
+
print_success() {
|
|
70
|
+
local msg="$1"
|
|
71
|
+
echo -e "${GREEN}[OK]${NC} $msg"
|
|
72
|
+
return 0
|
|
73
|
+
}
|
|
74
|
+
print_warning() {
|
|
75
|
+
local msg="$1"
|
|
76
|
+
echo -e "${YELLOW}[WARN]${NC} $msg"
|
|
77
|
+
return 0
|
|
78
|
+
}
|
|
79
|
+
print_error() {
|
|
80
|
+
local msg="$1"
|
|
81
|
+
echo -e "${RED}[ERROR]${NC} $msg"
|
|
82
|
+
return 0
|
|
83
|
+
}
|
|
84
|
+
print_header() {
|
|
85
|
+
local msg="$1"
|
|
86
|
+
echo -e "${BOLD}${CYAN}$msg${NC}"
|
|
87
|
+
return 0
|
|
88
|
+
}
|
|
69
89
|
|
|
70
90
|
# Get current version
|
|
71
91
|
get_version() {
|
|
@@ -106,17 +126,20 @@ get_public_release_tag() {
|
|
|
106
126
|
|
|
107
127
|
# Check if a command exists
|
|
108
128
|
check_cmd() {
|
|
109
|
-
|
|
129
|
+
local cmd="$1"
|
|
130
|
+
command -v "$cmd" >/dev/null 2>&1
|
|
110
131
|
}
|
|
111
132
|
|
|
112
133
|
# Check if a directory exists
|
|
113
134
|
check_dir() {
|
|
114
|
-
|
|
135
|
+
local dir="$1"
|
|
136
|
+
[[ -d "$dir" ]]
|
|
115
137
|
}
|
|
116
138
|
|
|
117
139
|
# Check if a file exists
|
|
118
140
|
check_file() {
|
|
119
|
-
|
|
141
|
+
local file="$1"
|
|
142
|
+
[[ -f "$file" ]]
|
|
120
143
|
}
|
|
121
144
|
|
|
122
145
|
# Ensure file ends with a trailing newline (prevents malformed appends)
|
|
@@ -268,6 +291,61 @@ _compute_repo_registration_defaults() {
|
|
|
268
291
|
return 0
|
|
269
292
|
}
|
|
270
293
|
|
|
294
|
+
# Resolve a worktree path to its canonical main-worktree path, if applicable.
|
|
295
|
+
# Usage: resolve_canonical_repo_path <path>
|
|
296
|
+
# Prints the canonical path to stdout. If the input is already the main
|
|
297
|
+
# worktree, a non-git path, or git is unavailable, prints the input unchanged.
|
|
298
|
+
#
|
|
299
|
+
# Why this exists: `find ~/Git -name .aidevops.json` in auto-discovery and
|
|
300
|
+
# similar scans pick up .aidevops.json files that exist in linked worktrees
|
|
301
|
+
# (because worktrees inherit the working tree contents), and without this
|
|
302
|
+
# guard each worktree gets registered as a separate repo. That's what caused
|
|
303
|
+
# tabby-profile-sync to emit a profile for a worktree directory.
|
|
304
|
+
resolve_canonical_repo_path() {
|
|
305
|
+
local input_path="$1"
|
|
306
|
+
local common_dir
|
|
307
|
+
common_dir=$(git -C "$input_path" rev-parse --git-common-dir 2>/dev/null) || {
|
|
308
|
+
printf '%s\n' "$input_path"
|
|
309
|
+
return 0
|
|
310
|
+
}
|
|
311
|
+
local own_git_dir
|
|
312
|
+
own_git_dir=$(git -C "$input_path" rev-parse --git-dir 2>/dev/null) || {
|
|
313
|
+
printf '%s\n' "$input_path"
|
|
314
|
+
return 0
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
# Resolve both to absolute paths for a reliable comparison.
|
|
318
|
+
# git -C <path> returns paths relative to <path> when they are relative.
|
|
319
|
+
local common_abs own_abs
|
|
320
|
+
if [[ "$common_dir" = /* ]]; then
|
|
321
|
+
common_abs=$(cd "$common_dir" 2>/dev/null && pwd -P)
|
|
322
|
+
else
|
|
323
|
+
common_abs=$(cd "$input_path/$common_dir" 2>/dev/null && pwd -P)
|
|
324
|
+
fi
|
|
325
|
+
if [[ "$own_git_dir" = /* ]]; then
|
|
326
|
+
own_abs=$(cd "$own_git_dir" 2>/dev/null && pwd -P)
|
|
327
|
+
else
|
|
328
|
+
own_abs=$(cd "$input_path/$own_git_dir" 2>/dev/null && pwd -P)
|
|
329
|
+
fi
|
|
330
|
+
|
|
331
|
+
if [[ -z "$common_abs" || -z "$own_abs" || "$common_abs" == "$own_abs" ]]; then
|
|
332
|
+
# Main worktree or degraded resolution — pass through.
|
|
333
|
+
printf '%s\n' "$input_path"
|
|
334
|
+
return 0
|
|
335
|
+
fi
|
|
336
|
+
|
|
337
|
+
# Linked worktree — ask git for the main worktree's working tree path.
|
|
338
|
+
local main_path
|
|
339
|
+
main_path=$(git -C "$input_path" worktree list --porcelain 2>/dev/null | awk '/^worktree /{print $2; exit}')
|
|
340
|
+
if [[ -n "$main_path" && "$main_path" != "$input_path" && -d "$main_path" ]]; then
|
|
341
|
+
printf '%s\n' "$main_path"
|
|
342
|
+
return 0
|
|
343
|
+
fi
|
|
344
|
+
|
|
345
|
+
printf '%s\n' "$input_path"
|
|
346
|
+
return 0
|
|
347
|
+
}
|
|
348
|
+
|
|
271
349
|
# Register a repo in repos.json
|
|
272
350
|
# Usage: register_repo <path> <version> <features>
|
|
273
351
|
register_repo() {
|
|
@@ -283,6 +361,20 @@ register_repo() {
|
|
|
283
361
|
return 1
|
|
284
362
|
fi
|
|
285
363
|
|
|
364
|
+
# Resolve linked worktrees to their canonical main-worktree path.
|
|
365
|
+
# Every registration path (cmd_init, auto-discovery, scan) runs through
|
|
366
|
+
# register_repo, so the guard here catches all of them — not just the
|
|
367
|
+
# cmd_init path that previously checked only when WORKTREE_PATH was set.
|
|
368
|
+
local canonical_path
|
|
369
|
+
canonical_path=$(resolve_canonical_repo_path "$repo_path")
|
|
370
|
+
if [[ -n "$canonical_path" && "$canonical_path" != "$repo_path" ]]; then
|
|
371
|
+
print_info "Resolved worktree to canonical repo: $repo_path → $canonical_path"
|
|
372
|
+
if ! repo_path=$(cd "$canonical_path" 2>/dev/null && pwd -P); then
|
|
373
|
+
print_warning "Cannot access canonical path: $canonical_path"
|
|
374
|
+
return 1
|
|
375
|
+
fi
|
|
376
|
+
fi
|
|
377
|
+
|
|
286
378
|
if ! command -v jq &>/dev/null; then
|
|
287
379
|
print_warning "jq not installed - repo tracking disabled"
|
|
288
380
|
return 0
|
package/package.json
CHANGED
|
@@ -308,6 +308,62 @@ cleanup_stale_bun_opencode() {
|
|
|
308
308
|
# by the 4-layer role resolution in stats-functions.sh.
|
|
309
309
|
#
|
|
310
310
|
# Gated by a flag file so it runs exactly once per install.
|
|
311
|
+
cleanup_worktree_entries_in_repos_json() {
|
|
312
|
+
# t2250: `find ~/Git -name .aidevops.json` during auto-discovery picks up
|
|
313
|
+
# files that exist inside linked worktrees (because worktrees inherit the
|
|
314
|
+
# working tree). Before the register_repo guard, each worktree ended up as
|
|
315
|
+
# a separate entry in repos.json — confusing tabby-profile-sync, pulse,
|
|
316
|
+
# cross-repo tooling, and anything that enumerates `initialized_repos`.
|
|
317
|
+
#
|
|
318
|
+
# One-shot migration: scan `initialized_repos[].path`, detect entries that
|
|
319
|
+
# are linked worktrees (git rev-parse --git-dir != --git-common-dir), and
|
|
320
|
+
# remove them. Safe to re-run; a flag file suppresses re-execution once
|
|
321
|
+
# the cleanup has been done on this machine.
|
|
322
|
+
local flag_file="${HOME}/.aidevops/logs/.migrated-worktree-repos-json-t2250"
|
|
323
|
+
[[ -f "$flag_file" ]] && return 0
|
|
324
|
+
|
|
325
|
+
local repos_json="${HOME}/.config/aidevops/repos.json"
|
|
326
|
+
[[ -f "$repos_json" ]] || return 0
|
|
327
|
+
|
|
328
|
+
command -v jq &>/dev/null || return 0
|
|
329
|
+
command -v git &>/dev/null || return 0
|
|
330
|
+
|
|
331
|
+
local stale_paths=()
|
|
332
|
+
local path git_dir common_dir
|
|
333
|
+
|
|
334
|
+
while IFS= read -r path; do
|
|
335
|
+
[[ -n "$path" && -d "$path" ]] || continue
|
|
336
|
+
git_dir=$(git -C "$path" rev-parse --git-dir 2>/dev/null) || continue
|
|
337
|
+
common_dir=$(git -C "$path" rev-parse --git-common-dir 2>/dev/null) || continue
|
|
338
|
+
# Normalise to absolute paths for comparison.
|
|
339
|
+
[[ "$git_dir" = /* ]] || git_dir="$path/$git_dir"
|
|
340
|
+
[[ "$common_dir" = /* ]] || common_dir="$path/$common_dir"
|
|
341
|
+
git_dir=$(cd "$git_dir" 2>/dev/null && pwd -P) || git_dir=""
|
|
342
|
+
common_dir=$(cd "$common_dir" 2>/dev/null && pwd -P) || common_dir=""
|
|
343
|
+
if [[ -n "$git_dir" && -n "$common_dir" && "$git_dir" != "$common_dir" ]]; then
|
|
344
|
+
stale_paths+=("$path")
|
|
345
|
+
fi
|
|
346
|
+
done < <(jq -r '.initialized_repos[].path // empty' "$repos_json" 2>/dev/null)
|
|
347
|
+
|
|
348
|
+
if [[ ${#stale_paths[@]} -gt 0 ]]; then
|
|
349
|
+
local temp_file="${repos_json}.tmp"
|
|
350
|
+
local paths_json
|
|
351
|
+
paths_json=$(printf '%s\n' "${stale_paths[@]}" | jq -R . | jq -s .)
|
|
352
|
+
jq --argjson stale "$paths_json" \
|
|
353
|
+
'.initialized_repos |= map(select(.path as $p | ($stale | index($p)) | not))' \
|
|
354
|
+
"$repos_json" >"$temp_file" && mv "$temp_file" "$repos_json"
|
|
355
|
+
print_info "Removed ${#stale_paths[@]} worktree entry/entries from repos.json (t2250):"
|
|
356
|
+
local p
|
|
357
|
+
for p in "${stale_paths[@]}"; do
|
|
358
|
+
print_info " - $p"
|
|
359
|
+
done
|
|
360
|
+
fi
|
|
361
|
+
|
|
362
|
+
mkdir -p "$(dirname "$flag_file")"
|
|
363
|
+
date -u +"%Y-%m-%dT%H:%M:%SZ" >"$flag_file"
|
|
364
|
+
return 0
|
|
365
|
+
}
|
|
366
|
+
|
|
311
367
|
cleanup_stale_health_issue_caches() {
|
|
312
368
|
local flag_file="${HOME}/.aidevops/logs/.migrated-health-issue-caches-t1929"
|
|
313
369
|
[[ -f "$flag_file" ]] && return 0
|
package/setup.sh
CHANGED
|
@@ -12,7 +12,7 @@ shopt -s inherit_errexit 2>/dev/null || true
|
|
|
12
12
|
# AI Assistant Server Access Framework Setup Script
|
|
13
13
|
# Helps developers set up the framework for their infrastructure
|
|
14
14
|
#
|
|
15
|
-
# Version: 3.8.
|
|
15
|
+
# Version: 3.8.72
|
|
16
16
|
#
|
|
17
17
|
# Quick Install:
|
|
18
18
|
# npm install -g aidevops && aidevops update (recommended)
|
|
@@ -915,6 +915,7 @@ _setup_run_non_interactive() {
|
|
|
915
915
|
cleanup_deprecated_mcps
|
|
916
916
|
cleanup_stale_bun_opencode
|
|
917
917
|
cleanup_stale_health_issue_caches
|
|
918
|
+
cleanup_worktree_entries_in_repos_json
|
|
918
919
|
_cleanup_legacy_model_config
|
|
919
920
|
validate_opencode_config
|
|
920
921
|
deploy_aidevops_agents
|
|
@@ -1030,8 +1031,8 @@ _setup_run_interactive() {
|
|
|
1030
1031
|
confirm_step "Backfill GitHub issue relationships (blocked-by, sub-issues)" && backfill_issue_relationships
|
|
1031
1032
|
confirm_step "Cleanup deprecated MCP entries (hetzner, serper, etc.)" && cleanup_deprecated_mcps
|
|
1032
1033
|
confirm_step "Cleanup stale bun opencode install" && cleanup_stale_bun_opencode
|
|
1033
|
-
|
|
1034
|
-
_cleanup_legacy_model_config
|
|
1034
|
+
# Silent one-shot migrations (idempotent, flag-guarded — no prompt needed).
|
|
1035
|
+
cleanup_stale_health_issue_caches; cleanup_worktree_entries_in_repos_json; _cleanup_legacy_model_config
|
|
1035
1036
|
confirm_step "Validate and repair OpenCode config schema" && validate_opencode_config
|
|
1036
1037
|
confirm_step "Extract OpenCode prompts" && extract_opencode_prompts
|
|
1037
1038
|
confirm_step "Check OpenCode prompt drift" && check_opencode_prompt_drift
|