aidevops 3.5.455 → 3.5.456

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 (4) hide show
  1. package/VERSION +1 -1
  2. package/aidevops.sh +183 -12
  3. package/package.json +1 -1
  4. package/setup.sh +1 -1
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.5.455
1
+ 3.5.456
package/aidevops.sh CHANGED
@@ -3,7 +3,7 @@
3
3
  # AI DevOps Framework CLI
4
4
  # Usage: aidevops <command> [options]
5
5
  #
6
- # Version: 3.5.455
6
+ # Version: 3.5.456
7
7
 
8
8
  set -euo pipefail
9
9
 
@@ -166,6 +166,91 @@ get_repo_slug() {
166
166
  return 1
167
167
  }
168
168
 
169
+ # Check whether a repo name follows mission-control naming.
170
+ # Usage: _is_mission_control_repo_name <repo-name>
171
+ _is_mission_control_repo_name() {
172
+ local repo_name="$1"
173
+ case "$repo_name" in
174
+ mission-control | *-mission-control | mission-control-*)
175
+ return 0
176
+ ;;
177
+ *)
178
+ return 1
179
+ ;;
180
+ esac
181
+ }
182
+
183
+ # Resolve mission-control scope from slug and current actor.
184
+ # Usage: _resolve_mission_control_scope <owner/repo> <current-login>
185
+ # Prints: personal | org (or empty if not mission-control)
186
+ _resolve_mission_control_scope() {
187
+ local slug="$1"
188
+ local current_login="$2"
189
+
190
+ if [[ -z "$slug" ]] || [[ "$slug" != */* ]]; then
191
+ echo ""
192
+ return 1
193
+ fi
194
+
195
+ local owner repo
196
+ owner="${slug%%/*}"
197
+ repo="${slug##*/}"
198
+
199
+ if ! _is_mission_control_repo_name "$repo"; then
200
+ echo ""
201
+ return 1
202
+ fi
203
+
204
+ if [[ -n "$current_login" && "$owner" == "$current_login" ]]; then
205
+ echo "personal"
206
+ return 0
207
+ fi
208
+
209
+ echo "org"
210
+ return 0
211
+ }
212
+
213
+ # Compute default repos.json registration values.
214
+ # Usage: _compute_repo_registration_defaults <path> <slug> <local_only> <maintainer>
215
+ # Prints eval-safe key=value lines: DEFAULT_PULSE, DEFAULT_PRIORITY
216
+ _compute_repo_registration_defaults() {
217
+ local repo_path="$1"
218
+ local slug="$2"
219
+ local is_local_only="$3"
220
+ local maintainer="$4"
221
+
222
+ local default_pulse=false
223
+ local default_priority=""
224
+
225
+ if [[ "$is_local_only" == "true" ]]; then
226
+ default_pulse=false
227
+ else
228
+ default_pulse=true
229
+ fi
230
+
231
+ if [[ "$slug" == */* ]]; then
232
+ local owner repo
233
+ owner="${slug%%/*}"
234
+ repo="${slug##*/}"
235
+
236
+ if [[ "$repo" == "$owner" ]] && [[ "$repo_path" == "$HOME/Git/$owner" ]]; then
237
+ default_pulse=false
238
+ default_priority="profile"
239
+ elif _is_mission_control_repo_name "$repo"; then
240
+ default_pulse=true
241
+ if [[ "$owner" == "$maintainer" ]]; then
242
+ default_priority="product"
243
+ else
244
+ default_priority="tooling"
245
+ fi
246
+ fi
247
+ fi
248
+
249
+ printf 'DEFAULT_PULSE=%q\n' "$default_pulse"
250
+ printf 'DEFAULT_PRIORITY=%q\n' "$default_priority"
251
+ return 0
252
+ }
253
+
169
254
  # Register a repo in repos.json
170
255
  # Usage: register_repo <path> <version> <features>
171
256
  register_repo() {
@@ -204,34 +289,46 @@ register_repo() {
204
289
  maintainer=$(gh api user --jq '.login' 2>/dev/null) || maintainer=""
205
290
  fi
206
291
 
292
+ local DEFAULT_PULSE="false"
293
+ local DEFAULT_PRIORITY=""
294
+ eval "$(_compute_repo_registration_defaults "$repo_path" "$slug" "$is_local_only" "$maintainer")"
295
+
207
296
  # Check if repo already registered
208
297
  if jq -e --arg path "$repo_path" '.initialized_repos[] | select(.path == $path)' "$REPOS_FILE" &>/dev/null; then
209
298
  # Update existing entry, preserving pulse/priority/local_only/maintainer if already set
210
299
  local temp_file="${REPOS_FILE}.tmp"
211
300
  jq --arg path "$repo_path" --arg version "$version" --arg features "$features" \
212
301
  --arg slug "$slug" --argjson local_only "$is_local_only" --arg maintainer "$maintainer" \
302
+ --argjson pulse_default "$DEFAULT_PULSE" --arg priority_default "$DEFAULT_PRIORITY" \
213
303
  '(.initialized_repos[] | select(.path == $path)) |= (
214
304
  . + {path: $path, version: $version, features: ($features | split(",")), updated: (now | strftime("%Y-%m-%dT%H:%M:%SZ"))}
215
305
  | if $slug != "" then .slug = $slug else . end
216
306
  | if $local_only then .local_only = true else . end
307
+ | if .pulse == null then .pulse = (if $local_only then false else $pulse_default end) else . end
308
+ | if (.priority == null or .priority == "") and $priority_default != "" then .priority = $priority_default else . end
217
309
  | if (.maintainer == null or .maintainer == "") and $maintainer != "" then .maintainer = $maintainer else . end
218
310
  )' \
219
311
  "$REPOS_FILE" >"$temp_file" && mv "$temp_file" "$REPOS_FILE"
220
312
  else
221
- # Add new entry with slug and maintainer
313
+ # Add new entry with slug, defaults, and maintainer
222
314
  local temp_file="${REPOS_FILE}.tmp"
223
- local new_entry
224
- # shellcheck disable=SC2016 # jq expressions use $var syntax, not shell expansion
225
- if [[ -n "$slug" ]]; then
226
- new_entry='{path: $path, slug: $slug, maintainer: $maintainer, version: $version, features: ($features | split(",")), initialized: (now | strftime("%Y-%m-%dT%H:%M:%SZ"))}'
227
- elif [[ "$is_local_only" == "true" ]]; then
228
- new_entry='{path: $path, local_only: true, maintainer: $maintainer, version: $version, features: ($features | split(",")), initialized: (now | strftime("%Y-%m-%dT%H:%M:%SZ"))}'
229
- else
230
- new_entry='{path: $path, maintainer: $maintainer, version: $version, features: ($features | split(",")), initialized: (now | strftime("%Y-%m-%dT%H:%M:%SZ"))}'
231
- fi
232
315
  jq --arg path "$repo_path" --arg version "$version" --arg features "$features" \
233
316
  --arg slug "$slug" --arg maintainer "$maintainer" \
234
- ".initialized_repos += [$new_entry]" \
317
+ --argjson local_only "$is_local_only" --argjson pulse_default "$DEFAULT_PULSE" \
318
+ --arg priority_default "$DEFAULT_PRIORITY" \
319
+ '.initialized_repos += [(
320
+ {
321
+ path: $path,
322
+ maintainer: $maintainer,
323
+ version: $version,
324
+ features: ($features | split(",")),
325
+ pulse: $pulse_default,
326
+ initialized: (now | strftime("%Y-%m-%dT%H:%M:%SZ"))
327
+ }
328
+ | if $slug != "" then . + {slug: $slug} else . end
329
+ | if $local_only then . + {local_only: true, pulse: false} else . end
330
+ | if $priority_default != "" then . + {priority: $priority_default} else . end
331
+ )]' \
235
332
  "$REPOS_FILE" >"$temp_file" && mv "$temp_file" "$REPOS_FILE"
236
333
  fi
237
334
  return 0
@@ -1269,6 +1366,67 @@ _init_parse_features() {
1269
1366
  return 0
1270
1367
  }
1271
1368
 
1369
+ # Seed mission-control onboarding template when initializing a mission-control repo.
1370
+ # Usage: _seed_mission_control_template <project_root> <personal|org>
1371
+ _seed_mission_control_template() {
1372
+ local project_root="$1"
1373
+ local scope="$2"
1374
+ local seed_file="$project_root/todo/mission-control-seed.md"
1375
+
1376
+ if [[ -z "$scope" ]]; then
1377
+ return 0
1378
+ fi
1379
+
1380
+ if [[ -f "$seed_file" ]]; then
1381
+ return 0
1382
+ fi
1383
+
1384
+ mkdir -p "$project_root/todo"
1385
+
1386
+ if [[ "$scope" == "personal" ]]; then
1387
+ cat >"$seed_file" <<'EOF'
1388
+ # Mission Control Seed (Personal)
1389
+
1390
+ Starter checklist for a personal mission-control repo initialized with aidevops.
1391
+
1392
+ ## First-Day Setup
1393
+
1394
+ - [ ] Confirm `~/.config/aidevops/repos.json` has all active repos registered with correct `slug` and `path`
1395
+ - [ ] Set `pulse: true` only for repos you want actively supervised
1396
+ - [ ] Add `pulse_hours` windows to avoid dispatch during daytime manual development
1397
+ - [ ] Verify profile and archive repos are `pulse: false` and `priority: "profile"` where applicable
1398
+
1399
+ ## Operating Rhythm
1400
+
1401
+ - [ ] Define weekly review cadence for `aidevops pulse` health and backlog aging
1402
+ - [ ] Add hygiene tasks for stale branches, stale worktrees, and stale queued issues
1403
+ - [ ] Track cross-repo blockers in TODO with clear `blocked-by:` links
1404
+ EOF
1405
+ else
1406
+ cat >"$seed_file" <<'EOF'
1407
+ # Mission Control Seed (Organization)
1408
+
1409
+ Starter checklist for an organization mission-control repo initialized with aidevops.
1410
+
1411
+ ## First-Day Setup
1412
+
1413
+ - [ ] Register all managed org repos in `~/.config/aidevops/repos.json` with `slug`, `path`, `priority`, and `maintainer`
1414
+ - [ ] Set `pulse: true` only for repos approved for autonomous dispatch
1415
+ - [ ] Configure `pulse_hours` and optional `pulse_expires` windows for sprint-based focus
1416
+ - [ ] Keep sensitive/internal-only repos `pulse: false` until policy checks are complete
1417
+
1418
+ ## Governance
1419
+
1420
+ - [ ] Define maintainer response SLA for `needs-maintainer-review` triage
1421
+ - [ ] Document worker guardrails (release, merge, and security boundaries)
1422
+ - [ ] Add a weekly audit task for repo registration drift and label hygiene
1423
+ EOF
1424
+ fi
1425
+
1426
+ print_success "Seeded mission-control template: todo/mission-control-seed.md (${scope})"
1427
+ return 0
1428
+ }
1429
+
1272
1430
  # Init command - initialize aidevops in a project
1273
1431
  cmd_init() {
1274
1432
  local features="${1:-all}"
@@ -1373,6 +1531,10 @@ EOF
1373
1531
  local repo_name
1374
1532
  local remote_url
1375
1533
  remote_url=$(git -C "$project_root" remote get-url origin 2>/dev/null || true)
1534
+ local repo_slug=""
1535
+ if [[ -n "$remote_url" ]]; then
1536
+ repo_slug=$(echo "$remote_url" | sed 's|.*github\.com[:/]||;s|\.git$||')
1537
+ fi
1376
1538
  if [[ -n "$remote_url" ]]; then
1377
1539
  repo_name=$(basename "$remote_url" .git)
1378
1540
  else
@@ -1525,6 +1687,15 @@ EOF
1525
1687
 
1526
1688
  # Create .gitkeep in tasks
1527
1689
  touch "$project_root/todo/tasks/.gitkeep"
1690
+
1691
+ # Seed mission-control starter template for personal/org control repos
1692
+ local init_actor=""
1693
+ if command -v gh &>/dev/null; then
1694
+ init_actor=$(gh api user --jq '.login' 2>/dev/null || echo "")
1695
+ fi
1696
+ local mission_scope=""
1697
+ mission_scope=$(_resolve_mission_control_scope "$repo_slug" "$init_actor" 2>/dev/null || echo "")
1698
+ _seed_mission_control_template "$project_root" "$mission_scope"
1528
1699
  fi
1529
1700
 
1530
1701
  # Create database directories if enabled
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "3.5.455",
3
+ "version": "3.5.456",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "bin": {
package/setup.sh CHANGED
@@ -10,7 +10,7 @@ shopt -s inherit_errexit 2>/dev/null || true
10
10
  # AI Assistant Server Access Framework Setup Script
11
11
  # Helps developers set up the framework for their infrastructure
12
12
  #
13
- # Version: 3.5.455
13
+ # Version: 3.5.456
14
14
  #
15
15
  # Quick Install:
16
16
  # npm install -g aidevops && aidevops update (recommended)