gator-command 1.0.0__py3-none-any.whl

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 (110) hide show
  1. gator_command/__init__.py +2 -0
  2. gator_command/cli.py +137 -0
  3. gator_command/scripts/crawler.py +633 -0
  4. gator_command/scripts/dashboard/dashboard.css +982 -0
  5. gator_command/scripts/dashboard/dashboard.html +84 -0
  6. gator_command/scripts/dashboard/dashboard.js +419 -0
  7. gator_command/scripts/dashboard/views/audit.js +270 -0
  8. gator_command/scripts/dashboard/views/fleet.js +307 -0
  9. gator_command/scripts/dashboard/views/repo.js +599 -0
  10. gator_command/scripts/dashboard/views/settings.js +173 -0
  11. gator_command/scripts/dashboard/views/updates.js +308 -0
  12. gator_command/scripts/enforcer-prompt.md +22 -0
  13. gator_command/scripts/extract-claude-sessions.py +489 -0
  14. gator_command/scripts/extract-codex-sessions.py +477 -0
  15. gator_command/scripts/extract-gemini-sessions.py +410 -0
  16. gator_command/scripts/gator-audit.py +956 -0
  17. gator_command/scripts/gator-charter-draft.py +919 -0
  18. gator_command/scripts/gator-charter-lint.py +427 -0
  19. gator_command/scripts/gator-charter-verify.py +606 -0
  20. gator_command/scripts/gator-dashboard.py +1271 -0
  21. gator_command/scripts/gator-deploy.py +916 -0
  22. gator_command/scripts/gator-drift.py +569 -0
  23. gator_command/scripts/gator-enforce.py +82 -0
  24. gator_command/scripts/gator-fleet-intel.py +460 -0
  25. gator_command/scripts/gator-fleet-report.py +615 -0
  26. gator_command/scripts/gator-init-command-post.py +315 -0
  27. gator_command/scripts/gator-init.py +434 -0
  28. gator_command/scripts/gator-machine-id.py +153 -0
  29. gator_command/scripts/gator-policy-status.py +631 -0
  30. gator_command/scripts/gator-pulse.py +459 -0
  31. gator_command/scripts/gator-repo-status.py +649 -0
  32. gator_command/scripts/gator-session-common.py +372 -0
  33. gator_command/scripts/gator-session-sink.py +831 -0
  34. gator_command/scripts/gator-sessions.py +1244 -0
  35. gator_command/scripts/gator-update.py +615 -0
  36. gator_command/scripts/gator-version.py +38 -0
  37. gator_command/scripts/gator_core.py +489 -0
  38. gator_command/scripts/gator_remote.py +381 -0
  39. gator_command/scripts/gator_runtime.py +142 -0
  40. gator_command/scripts/gatorize-actions.sh +989 -0
  41. gator_command/scripts/gatorize-lib.sh +166 -0
  42. gator_command/scripts/gatorize-post.sh +394 -0
  43. gator_command/scripts/gatorize.py +1163 -0
  44. gator_command/scripts/gatorize.sh +185 -0
  45. gator_command/scripts/generate_markdown.py +212 -0
  46. gator_command/scripts/generate_wiki.py +424 -0
  47. gator_command/scripts/graph_health.py +780 -0
  48. gator_command/scripts/memex-lint.py +286 -0
  49. gator_command/scripts/memex-lint.sh +205 -0
  50. gator_command/scripts/memex.py +1472 -0
  51. gator_command/scripts/memex_formatters.py +191 -0
  52. gator_command/scripts/memex_state.py +236 -0
  53. gator_command/scripts/spawn.py +650 -0
  54. gator_command/templates/gator-starter/blueprints/README.md +32 -0
  55. gator_command/templates/gator-starter/charterignore +53 -0
  56. gator_command/templates/gator-starter/charters/README.md +178 -0
  57. gator_command/templates/gator-starter/charters/_template.md +31 -0
  58. gator_command/templates/gator-starter/commands/commit.md +33 -0
  59. gator_command/templates/gator-starter/commands/init.md +11 -0
  60. gator_command/templates/gator-starter/commands/update.md +5 -0
  61. gator_command/templates/gator-starter/constitution.md +165 -0
  62. gator_command/templates/gator-starter/field-guides/README.md +25 -0
  63. gator_command/templates/gator-starter/gator-start-up.md +119 -0
  64. gator_command/templates/gator-starter/procedures/charter-alignment.md +83 -0
  65. gator_command/templates/gator-starter/procedures/enforcer-review.md +317 -0
  66. gator_command/templates/gator-starter/procedures/field-guide-generation.md +176 -0
  67. gator_command/templates/gator-starter/procedures/knowledge-capture.md +57 -0
  68. gator_command/templates/gator-starter/procedures/significance-check.md +69 -0
  69. gator_command/templates/gator-starter/reference-notes/concierge-responses.md +535 -0
  70. gator_command/templates/gator-starter/reference-notes/dangerous-patterns.md +91 -0
  71. gator_command/templates/gator-starter/reference-notes/dashboard-operations.md +22 -0
  72. gator_command/templates/gator-starter/reference-notes/enforcer-configuration.md +232 -0
  73. gator_command/templates/gator-starter/reference-notes/example-project.md +289 -0
  74. gator_command/templates/gator-starter/reference-notes/failure-modes-and-self-correction.md +72 -0
  75. gator_command/templates/gator-starter/reference-notes/git-workflow.md +60 -0
  76. gator_command/templates/gator-starter/reference-notes/identity-and-ownership.md +37 -0
  77. gator_command/templates/gator-starter/reference-notes/refactor-approach.md +155 -0
  78. gator_command/templates/gator-starter/reference-notes/what-gator-requires-from-a-model.md +108 -0
  79. gator_command/templates/gator-starter/reference-notes/why-navigation-coding-feels-different.md +99 -0
  80. gator_command/templates/gator-starter/reference-notes/workflow-profiles.md +155 -0
  81. gator_command/templates/gator-starter/scripts/__pycache__/enforcer-review.cpython-313.pyc +0 -0
  82. gator_command/templates/gator-starter/scripts/__pycache__/gator-approve.cpython-313.pyc +0 -0
  83. gator_command/templates/gator-starter/scripts/__pycache__/gator-init.cpython-313.pyc +0 -0
  84. gator_command/templates/gator-starter/scripts/__pycache__/gator-pre-commit.cpython-313.pyc +0 -0
  85. gator_command/templates/gator-starter/scripts/__pycache__/gator-update.cpython-313.pyc +0 -0
  86. gator_command/templates/gator-starter/scripts/enforcer-prompt.md +55 -0
  87. gator_command/templates/gator-starter/scripts/enforcer-review.py +1551 -0
  88. gator_command/templates/gator-starter/scripts/gator-approve.py +139 -0
  89. gator_command/templates/gator-starter/scripts/gator-enforce.py +82 -0
  90. gator_command/templates/gator-starter/scripts/gator-init.py +434 -0
  91. gator_command/templates/gator-starter/scripts/gator-pre-commit.py +2670 -0
  92. gator_command/templates/gator-starter/scripts/gator-pulse.py +459 -0
  93. gator_command/templates/gator-starter/scripts/gator-update.py +615 -0
  94. gator_command/templates/gator-starter/scripts/gator-version.py +38 -0
  95. gator_command/templates/gator-starter/scripts/gator_core.py +487 -0
  96. gator_command/templates/gator-starter/scripts/hooks/__pycache__/commit-msgcpython-313.pyc +0 -0
  97. gator_command/templates/gator-starter/scripts/hooks/__pycache__/post-commitcpython-313.pyc +0 -0
  98. gator_command/templates/gator-starter/scripts/hooks/__pycache__/pre-commitcpython-313.pyc +0 -0
  99. gator_command/templates/gator-starter/scripts/hooks/commit-msg +5 -0
  100. gator_command/templates/gator-starter/scripts/hooks/post-commit +7 -0
  101. gator_command/templates/gator-starter/scripts/hooks/pre-commit +5 -0
  102. gator_command/templates/gator-starter/sessions/.gitignore +7 -0
  103. gator_command/templates/gator-starter/vault/.gitkeep +0 -0
  104. gator_command/templates/gator-starter/whiteboard.md +5 -0
  105. gator_command-1.0.0.dist-info/METADATA +122 -0
  106. gator_command-1.0.0.dist-info/RECORD +110 -0
  107. gator_command-1.0.0.dist-info/WHEEL +5 -0
  108. gator_command-1.0.0.dist-info/entry_points.txt +2 -0
  109. gator_command-1.0.0.dist-info/licenses/LICENSE +21 -0
  110. gator_command-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,989 @@
1
+ #!/usr/bin/env bash
2
+ # gatorize-actions.sh — Scenario action functions for gatorize.sh
3
+ #
4
+ # Sourced by gatorize.sh. Not a standalone script.
5
+ # Requires: gatorize-lib.sh (for log_step, confirm, detect_*, write_gator_version, etc.)
6
+ # Requires: TEMPLATES, GATOR_BRANCH, GATOR_GEN, TODAY (set by gatorize.sh)
7
+ #
8
+ # Contains: git init, feature branch, hook installation, fresh install,
9
+ # stub writing, upgrade, morph, dual-structure handling.
10
+
11
+ # =============================================================================
12
+ # Action: Git Init (Scenario 1)
13
+ # =============================================================================
14
+
15
+ action_git_init() {
16
+ local target="$1"
17
+ log_blank
18
+ echo " No git repository found in $target."
19
+ echo " Gator requires git — the entire governance model depends on commit history,"
20
+ echo " branching, and audit trails. Gator cannot function without it."
21
+ log_blank
22
+
23
+ if ! confirm "Initialize a git repo now?" "Y"; then
24
+ echo " Aborted. Initialize a git repo in $target and re-run gatorize.sh."
25
+ exit 1
26
+ fi
27
+
28
+ # Preflight: check git identity
29
+ local git_user git_email
30
+ git_user=$(git config user.name 2>/dev/null || true)
31
+ git_email=$(git config user.email 2>/dev/null || true)
32
+ if [ -z "$git_user" ] || [ -z "$git_email" ]; then
33
+ log_blank
34
+ echo " Git identity not configured. Git requires user.name and user.email to commit."
35
+ echo " Run these commands first, then re-run gatorize.sh:"
36
+ log_blank
37
+ echo " git config --global user.name \"Your Name\""
38
+ echo " git config --global user.email \"you@example.com\""
39
+ log_blank
40
+ exit 1
41
+ fi
42
+
43
+ (
44
+ cd "$target"
45
+ git init
46
+ local default_branch
47
+ default_branch=$(git branch --show-current 2>/dev/null || echo "master")
48
+ if [ "$default_branch" != "main" ]; then
49
+ git branch -M main 2>/dev/null || true
50
+ fi
51
+ # Check for files beyond .git itself
52
+ if [ -n "$(ls -A 2>/dev/null | grep -v '^\.git$')" ]; then
53
+ git add -A
54
+ git commit -m "Initial commit (pre-Gator)"
55
+ else
56
+ git commit --allow-empty -m "Initial commit (pre-Gator)"
57
+ fi
58
+ git branch dev
59
+ git checkout -b "$GATOR_BRANCH"
60
+ )
61
+ log_blank
62
+ log_step "Git initialized. Branches: main, dev, $GATOR_BRANCH (current)."
63
+ }
64
+
65
+ # =============================================================================
66
+ # Action: Feature Branch (mandatory for all git scenarios)
67
+ # =============================================================================
68
+
69
+ action_feature_branch() {
70
+ local target="$1"
71
+
72
+ # Check for uncommitted changes
73
+ local dirty current_branch
74
+ dirty=$(cd "$target" && git status --porcelain 2>/dev/null | head -1)
75
+ current_branch=$(cd "$target" && git branch --show-current 2>/dev/null)
76
+
77
+ if [ -n "$dirty" ]; then
78
+ log_blank
79
+ echo " Warning: uncommitted changes detected in $target."
80
+ echo " Strongly recommend committing or stashing before gatorizing."
81
+ log_blank
82
+ echo " Options:"
83
+ echo " [c] Continue anyway (changes will mix with Gator install)"
84
+ echo " [a] Abort — commit your changes first, then re-run"
85
+ log_blank
86
+ read -rp " Choice [c/a]: " dirty_choice
87
+ if [[ "$dirty_choice" =~ ^[Aa]$ ]]; then
88
+ echo " Aborted. Commit your changes and re-run gatorize.sh."
89
+ exit 0
90
+ fi
91
+ fi
92
+
93
+ # Handle existing gator-install branch BEFORE branch selection
94
+ if (cd "$target" && git rev-parse --verify "$GATOR_BRANCH" >/dev/null 2>&1); then
95
+ log_blank
96
+ echo " Branch '$GATOR_BRANCH' already exists (prior install attempt?)."
97
+ log_blank
98
+ echo " [1] Delete and start fresh (recommended)"
99
+ echo " [2] Continue on existing branch"
100
+ echo " [x] Cancel installation"
101
+ log_blank
102
+ read -rp " Choice [1/2/x]: " branch_choice
103
+ case "$branch_choice" in
104
+ 1)
105
+ (cd "$target" && git checkout dev 2>/dev/null || git checkout main 2>/dev/null)
106
+ (cd "$target" && git branch -D "$GATOR_BRANCH" 2>/dev/null)
107
+ log_step "Deleted old '$GATOR_BRANCH' branch."
108
+ ;;
109
+ [xX])
110
+ echo " Installation cancelled."
111
+ exit 0
112
+ ;;
113
+ *)
114
+ log_step "Continuing on existing '$GATOR_BRANCH' branch."
115
+ ;;
116
+ esac
117
+ fi
118
+
119
+ log_blank
120
+ echo " Gator installs on a feature branch ('$GATOR_BRANCH') for safety."
121
+ echo " This keeps the install reversible — delete the branch if anything goes wrong,"
122
+ echo " merge to dev when you're happy."
123
+ log_blank
124
+
125
+ # Get list of local branches (excluding gator-install itself)
126
+ local branches=()
127
+ while IFS= read -r branch; do
128
+ branch="${branch#\* }" # strip the * from current branch
129
+ branch="${branch#"${branch%%[! ]*}"}" # strip ALL leading spaces
130
+ [ "$branch" = "$GATOR_BRANCH" ] && continue # don't list gator-install as a source
131
+ branches+=("$branch")
132
+ done < <(cd "$target" && git branch 2>/dev/null)
133
+
134
+ if [ ${#branches[@]} -eq 0 ]; then
135
+ log_step "No branches found (empty repo?). Installing on current state."
136
+ (
137
+ cd "$target"
138
+ git checkout -b "$GATOR_BRANCH" 2>/dev/null || git checkout "$GATOR_BRANCH"
139
+ )
140
+ return
141
+ fi
142
+
143
+ local source_branch=""
144
+
145
+ if [ ${#branches[@]} -eq 1 ]; then
146
+ source_branch="${branches[0]}"
147
+ echo " Only one branch available: $source_branch"
148
+ echo " '$GATOR_BRANCH' will branch from '$source_branch'."
149
+ log_blank
150
+ if ! confirm "Proceed?" "Y"; then
151
+ echo " Aborted."
152
+ exit 0
153
+ fi
154
+ else
155
+ echo " Available branches:"
156
+ log_blank
157
+ for i in "${!branches[@]}"; do
158
+ local marker=" "
159
+ if [ "${branches[$i]}" = "$current_branch" ]; then
160
+ marker="* "
161
+ fi
162
+ echo " [$((i+1))] ${marker}${branches[$i]}"
163
+ done
164
+ log_blank
165
+ read -rp " Which branch should '$GATOR_BRANCH' branch from? [1-${#branches[@]}]: " source_choice
166
+
167
+ if [[ "$source_choice" =~ ^[0-9]+$ ]] && [ "$source_choice" -ge 1 ] && [ "$source_choice" -le ${#branches[@]} ]; then
168
+ source_branch="${branches[$((source_choice-1))]}"
169
+ else
170
+ source_branch="$current_branch"
171
+ echo " Invalid choice. Branching from '$current_branch'."
172
+ fi
173
+ fi
174
+
175
+ (
176
+ cd "$target"
177
+ git checkout "$source_branch" 2>/dev/null
178
+ # Ensure dev exists
179
+ if ! git rev-parse --verify dev >/dev/null 2>&1; then
180
+ git branch dev 2>/dev/null || true
181
+ log_step "Created 'dev' branch."
182
+ fi
183
+ # Create or switch to gator-install (already handled above if it existed)
184
+ if git rev-parse --verify "$GATOR_BRANCH" >/dev/null 2>&1; then
185
+ git checkout "$GATOR_BRANCH"
186
+ else
187
+ git checkout -b "$GATOR_BRANCH"
188
+ fi
189
+ )
190
+ log_step "On '$GATOR_BRANCH' (from '$source_branch')."
191
+ }
192
+
193
+ # =============================================================================
194
+ # Action: Install git hooks (pre-commit + commit-msg)
195
+ # =============================================================================
196
+
197
+ is_windows_shell() {
198
+ case "$(uname -s 2>/dev/null)" in
199
+ MINGW*|MSYS*|CYGWIN*)
200
+ return 0
201
+ ;;
202
+ *)
203
+ return 1
204
+ ;;
205
+ esac
206
+ }
207
+
208
+ write_windows_hook() {
209
+ local dest="$1"
210
+ local hook_name="$2"
211
+ local py_path
212
+ py_path=$(python -c "import sys; print(sys.executable.replace('\\\\', '/'))" 2>/dev/null)
213
+ [ -n "$py_path" ] || return 1
214
+
215
+ case "$hook_name" in
216
+ pre-commit)
217
+ cat > "$dest" <<EOF
218
+ #!$py_path
219
+ import subprocess
220
+ import sys
221
+
222
+ raise SystemExit(
223
+ subprocess.call(["python", ".gator/scripts/gator-pre-commit.py", "--phase", "validate"])
224
+ )
225
+ EOF
226
+ ;;
227
+ commit-msg)
228
+ cat > "$dest" <<EOF
229
+ #!$py_path
230
+ import subprocess
231
+ import sys
232
+
233
+ raise SystemExit(
234
+ subprocess.call(["python", ".gator/scripts/gator-pre-commit.py", "--phase", "trailers", *sys.argv[1:]])
235
+ )
236
+ EOF
237
+ ;;
238
+ post-commit)
239
+ cat > "$dest" <<EOF
240
+ #!$py_path
241
+ import subprocess
242
+
243
+ raise SystemExit(
244
+ subprocess.call(["python", ".gator/scripts/gator-pre-commit.py", "--phase", "cleanup"])
245
+ )
246
+ EOF
247
+ ;;
248
+ *)
249
+ return 1
250
+ ;;
251
+ esac
252
+
253
+ chmod +x "$dest"
254
+ }
255
+
256
+ install_hooks() {
257
+ local target="$1"
258
+ local hooks_dir="$target/.git/hooks"
259
+
260
+ # Only install if .git exists (it should — we're on a branch)
261
+ if [ ! -d "$target/.git" ]; then
262
+ return
263
+ fi
264
+
265
+ mkdir -p "$hooks_dir"
266
+
267
+ local installed=0
268
+ local backed_up=0
269
+
270
+ for hook_name in pre-commit commit-msg post-commit; do
271
+ local src="$TEMPLATES/scripts/hooks/$hook_name"
272
+ local dest="$hooks_dir/$hook_name"
273
+
274
+ [ -f "$src" ] || continue
275
+
276
+ if [ -f "$dest" ]; then
277
+ # Check if it's already a Gator hook (idempotent)
278
+ if grep -q "Gator" "$dest" 2>/dev/null; then
279
+ cp "$src" "$dest"
280
+ chmod +x "$dest"
281
+ installed=$((installed + 1))
282
+ continue
283
+ fi
284
+
285
+ # Existing non-Gator hook — back up and replace
286
+ local backup="$dest.pre-gator"
287
+ if [ ! -f "$backup" ]; then
288
+ cp "$dest" "$backup"
289
+ backed_up=$((backed_up + 1))
290
+ log_step "Backed up existing $hook_name hook → $hook_name.pre-gator"
291
+ fi
292
+ fi
293
+
294
+ if is_windows_shell && write_windows_hook "$dest" "$hook_name"; then
295
+ :
296
+ else
297
+ cp "$src" "$dest"
298
+ chmod +x "$dest"
299
+ fi
300
+ installed=$((installed + 1))
301
+ done
302
+
303
+ if [ "$backed_up" -gt 0 ]; then
304
+ log_step "Git hooks: $installed installed, $backed_up existing hooks backed up"
305
+ log_step "Your original hooks are preserved as .pre-gator files in .git/hooks/"
306
+ else
307
+ log_step "Git hooks installed (pre-commit + commit-msg + post-commit)"
308
+ fi
309
+ }
310
+
311
+ # =============================================================================
312
+ # Action: Install .gator/ (fresh, from templates)
313
+ # =============================================================================
314
+
315
+ action_install_gator() {
316
+ local target="$1"
317
+
318
+ log_step "Installing .gator/ into $target ..."
319
+
320
+ # Create directory structure
321
+ mkdir -p "$target/.gator/charters" "$target/.gator/blueprints" \
322
+ "$target/.gator/reference-notes" \
323
+ "$target/.gator/procedures" "$target/.gator/scripts" \
324
+ "$target/.gator/threads" "$target/.gator/artifacts" \
325
+ "$target/.gator/vault" "$target/.gator/policies" \
326
+ "$target/.gator/sessions"
327
+
328
+ # Copy constitution, startup guide
329
+ cp "$TEMPLATES/constitution.md" "$target/.gator/"
330
+ cp "$TEMPLATES/gator-start-up.md" "$target/.gator/"
331
+
332
+ # Copy charters scaffolding
333
+ cp "$TEMPLATES/charters/README.md" "$target/.gator/charters/"
334
+ cp "$TEMPLATES/charters/_template.md" "$target/.gator/charters/"
335
+
336
+ # Copy blueprints scaffolding
337
+ cp "$TEMPLATES/blueprints/README.md" "$target/.gator/blueprints/" 2>/dev/null || true
338
+
339
+ # Copy reference notes
340
+ cp "$TEMPLATES/reference-notes/"*.md "$target/.gator/reference-notes/"
341
+
342
+ # Copy procedures
343
+ cp "$TEMPLATES/procedures/"*.md "$target/.gator/procedures/"
344
+
345
+ # Copy sessions gitignore (keeps _active/ out of git)
346
+ if [ -f "$TEMPLATES/sessions/.gitignore" ]; then
347
+ cp "$TEMPLATES/sessions/.gitignore" "$target/.gator/sessions/"
348
+ fi
349
+
350
+ # Copy scripts (top-level files)
351
+ cp "$TEMPLATES/scripts/"* "$target/.gator/scripts/" 2>/dev/null || true
352
+
353
+ # Copy nested script directories (e.g., scripts/hooks/)
354
+ for subdir in "$TEMPLATES/scripts/"*/; do
355
+ [ -d "$subdir" ] || continue
356
+ local dirname
357
+ dirname=$(basename "$subdir")
358
+ mkdir -p "$target/.gator/scripts/$dirname"
359
+ cp "$subdir"* "$target/.gator/scripts/$dirname/" 2>/dev/null || true
360
+ done
361
+
362
+ # Install slash commands (vendor-neutral source, Claude Code destination)
363
+ if [ -d "$TEMPLATES/commands" ]; then
364
+ mkdir -p "$target/.claude/commands"
365
+ for cmd_file in "$TEMPLATES/commands/"*.md; do
366
+ [ -f "$cmd_file" ] || continue
367
+ local cmd_name
368
+ cmd_name=$(basename "$cmd_file")
369
+ local cmd_dest="$target/.claude/commands/$cmd_name"
370
+
371
+ if [ -f "$cmd_dest" ]; then
372
+ # Check if it's already a Gator command (idempotent)
373
+ if grep -qi "gator\|constitution\|charter" "$cmd_dest" 2>/dev/null; then
374
+ cp "$cmd_file" "$cmd_dest"
375
+ continue
376
+ fi
377
+ # Existing non-Gator command — back up
378
+ local cmd_backup="$cmd_dest.pre-gator"
379
+ if [ ! -f "$cmd_backup" ]; then
380
+ cp "$cmd_dest" "$cmd_backup"
381
+ log_step "Backed up existing slash command $cmd_name → $cmd_name.pre-gator"
382
+ fi
383
+ fi
384
+
385
+ cp "$cmd_file" "$cmd_dest"
386
+ done
387
+ fi
388
+
389
+ # .gitkeep for empty dirs
390
+ touch "$target/.gator/threads/.gitkeep"
391
+ touch "$target/.gator/artifacts/.gitkeep"
392
+ touch "$target/.gator/vault/.gitkeep"
393
+
394
+ # Install git hooks (pre-commit + commit-msg)
395
+ install_hooks "$target"
396
+
397
+ # Write stubs for content files
398
+ write_stubs "$target"
399
+
400
+ # Write version marker
401
+ write_gator_version "$target" "install"
402
+ }
403
+
404
+ write_stubs() {
405
+ local target="$1"
406
+
407
+ cat > "$target/.gator/mission.md" << 'STUB'
408
+ # Mission
409
+
410
+ ## What We're Building
411
+
412
+ [What is this project? One paragraph.]
413
+
414
+ ## Why It Exists
415
+
416
+ [What problem does it solve? Who is it for?]
417
+
418
+ ## What Success Looks Like
419
+
420
+ [How do you know when it's working?]
421
+ STUB
422
+
423
+ cat > "$target/.gator/roadmap.md" << 'STUB'
424
+ # Roadmap
425
+
426
+ [Priority-ordered. Updated as items complete or priorities shift.]
427
+
428
+ [Status key: Done · Building · Designed · Considering · Deferred]
429
+
430
+ | # | Feature | Status | Next step |
431
+ |---|---------|--------|-----------|
432
+ | 1 | | | |
433
+ | 2 | | | |
434
+ | 3 | | | |
435
+ STUB
436
+
437
+ cat > "$target/.gator/inbox.md" << 'STUB'
438
+ # Inbox
439
+
440
+ [Drop anything here. No formatting needed. The agent triages at session open.]
441
+
442
+ ---
443
+
444
+ STUB
445
+
446
+ cat > "$target/.gator/commit_draft.md" << 'STUB'
447
+ ---
448
+ message: ""
449
+ change-type:
450
+ significance:
451
+ decision-tags: []
452
+ agent:
453
+ architect:
454
+ ---
455
+
456
+ # Session Change Log
457
+
458
+ STUB
459
+
460
+ cat > "$target/.gator/whiteboard.md" << 'STUB'
461
+ # Whiteboard
462
+
463
+ Review log. Enforcer findings land here with timestamps. The Architect and agent review together, then act.
464
+
465
+ When this file exceeds 100 lines, archive older reviews to `artifacts/review-log.md` and keep the most recent 2–3.
466
+
467
+ ---
468
+
469
+ STUB
470
+
471
+ # Lint allowlist and commit issues — empty by default
472
+ echo '[]' > "$target/.gator/lint-allow.json"
473
+ printf "# Commit Issues\n\nNo findings.\n" > "$target/.gator/commit_issues.md"
474
+
475
+ # Enforcement config — strict by default
476
+ if [ ! -f "$target/.gator/config.json" ]; then
477
+ printf '{\n "enforcement_level": "strict"\n}\n' > "$target/.gator/config.json"
478
+ fi
479
+
480
+ cat > "$target/.gator/patterns.md" << 'STUB'
481
+ # Patterns
482
+
483
+ Recurring rhythms, obligations, schedules. Updated as patterns emerge.
484
+
485
+ ---
486
+
487
+ STUB
488
+
489
+ cat > "$target/.gator/charters/INDEX.md" << 'STUB'
490
+ # Charter Index
491
+
492
+ **Always read first:** [Cross-Cutting](cross-cutting.md) (when it exists)
493
+
494
+ | If you're changing... | Read these charters |
495
+ |---|---|
496
+ | | |
497
+ STUB
498
+
499
+ cat > "$target/.gator/issues.md" << 'STUB'
500
+ # Issues
501
+
502
+ Active bugs, blockers, and known fragilities. Checked at session open.
503
+
504
+ **Status key**: Open · Working · Resolved
505
+
506
+ ---
507
+
508
+ STUB
509
+ }
510
+
511
+ # =============================================================================
512
+ # Template overlay (used by upgrade and morph)
513
+ # =============================================================================
514
+
515
+ # Overlay template files into a directory WITHOUT deleting existing extras.
516
+ # Template files overwrite same-named files; files that exist only in the
517
+ # target directory are left untouched.
518
+ overlay_templates() {
519
+ local src_dir="$1" dest_dir="$2"
520
+ [ -d "$src_dir" ] || return 0
521
+ mkdir -p "$dest_dir"
522
+ local count=0
523
+ for f in "$src_dir"/*; do
524
+ [ -f "$f" ] || continue
525
+ cp "$f" "$dest_dir/"
526
+ count=$((count + 1))
527
+ done
528
+ echo "$count"
529
+ }
530
+
531
+ # =============================================================================
532
+ # Action: Upgrade existing .gator/ (Scenario 3)
533
+ # =============================================================================
534
+
535
+ action_upgrade_gator() {
536
+ local target="$1"
537
+
538
+ # --- Detect generation ---
539
+ local gen
540
+ gen=$(detect_gator_generation "$target")
541
+
542
+ local subcase
543
+ if [ "$gen" -eq 0 ]; then
544
+ subcase="3a"
545
+ elif [ "$gen" -lt "$GATOR_GEN" ]; then
546
+ subcase="3b"
547
+ else
548
+ subcase="3c"
549
+ fi
550
+
551
+ log_blank
552
+ case "$subcase" in
553
+ 3a)
554
+ echo " Pre-gatorize.sh install detected (generation 0)."
555
+ echo " No thin link, no registry entry, no outbox."
556
+ echo " Upgrade will add these and refresh templates while preserving all"
557
+ echo " your content — charters, mission, threads, reference-notes, scripts."
558
+ echo ""
559
+ echo " Note: your existing reference-notes and scripts may include files"
560
+ echo " not in the current template. These will be kept intact."
561
+ ;;
562
+ 3b)
563
+ echo " Earlier gatorize.sh install detected (generation $gen → $GATOR_GEN)."
564
+ echo " Upgrade will refresh templates while preserving all your content."
565
+ ;;
566
+ 3c)
567
+ echo " Current generation ($gen). Refreshing templates to latest versions."
568
+ ;;
569
+ esac
570
+ log_blank
571
+
572
+ if has_gator_knowledge "$target"; then
573
+ echo " Existing .gator/ has project knowledge (charters, threads, mission, etc.)."
574
+ echo " All content will be preserved."
575
+ log_blank
576
+ if ! confirm "Proceed with upgrade?" "Y"; then
577
+ echo " Aborted."
578
+ exit 0
579
+ fi
580
+ fi
581
+
582
+ # --- Ensure all directories exist (older versions may be missing some) ---
583
+ mkdir -p "$target/.gator/charters" "$target/.gator/blueprints" \
584
+ "$target/.gator/reference-notes" \
585
+ "$target/.gator/procedures" "$target/.gator/scripts" \
586
+ "$target/.gator/threads" "$target/.gator/artifacts" \
587
+ "$target/.gator/vault" "$target/.gator/policies" \
588
+ "$target/.gator/sessions"
589
+
590
+ # --- Refresh template-derived files ---
591
+ # Sessions gitignore (keeps _active/ out of git)
592
+ if [ -f "$TEMPLATES/sessions/.gitignore" ]; then
593
+ cp "$TEMPLATES/sessions/.gitignore" "$target/.gator/sessions/"
594
+ fi
595
+
596
+ # Constitution and startup guide: always overwrite (these are authoritative)
597
+ cp "$TEMPLATES/constitution.md" "$target/.gator/"
598
+ cp "$TEMPLATES/gator-start-up.md" "$target/.gator/"
599
+ log_step "Refreshed constitution.md, gator-start-up.md"
600
+
601
+ # Charter scaffolding: overwrite templates, preserve user charters
602
+ cp "$TEMPLATES/charters/README.md" "$target/.gator/charters/"
603
+ cp "$TEMPLATES/charters/_template.md" "$target/.gator/charters/"
604
+ cp "$TEMPLATES/blueprints/README.md" "$target/.gator/blueprints/" 2>/dev/null || true
605
+ log_step "Refreshed charter and blueprint templates"
606
+
607
+ # Reference-notes: OVERLAY
608
+ local rn_refreshed
609
+ rn_refreshed=$(overlay_templates "$TEMPLATES/reference-notes" "$target/.gator/reference-notes")
610
+ local rn_total
611
+ rn_total=$(find "$target/.gator/reference-notes" -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
612
+ log_step "Reference-notes: $rn_refreshed template files refreshed, $rn_total total (extras preserved)"
613
+
614
+ # Procedures: OVERLAY
615
+ local proc_refreshed
616
+ proc_refreshed=$(overlay_templates "$TEMPLATES/procedures" "$target/.gator/procedures")
617
+ local proc_total
618
+ proc_total=$(find "$target/.gator/procedures" -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
619
+ log_step "Procedures: $proc_refreshed template files refreshed, $proc_total total (extras preserved)"
620
+
621
+ # Scripts: OVERLAY (top-level files)
622
+ local script_refreshed=0
623
+ for f in "$TEMPLATES/scripts/"*; do
624
+ [ -f "$f" ] || continue
625
+ cp "$f" "$target/.gator/scripts/"
626
+ script_refreshed=$((script_refreshed + 1))
627
+ done 2>/dev/null || true
628
+
629
+ # Scripts: nested directories (e.g., scripts/hooks/)
630
+ for subdir in "$TEMPLATES/scripts/"*/; do
631
+ [ -d "$subdir" ] || continue
632
+ local dirname
633
+ dirname=$(basename "$subdir")
634
+ mkdir -p "$target/.gator/scripts/$dirname"
635
+ for f in "$subdir"*; do
636
+ [ -f "$f" ] || continue
637
+ cp "$f" "$target/.gator/scripts/$dirname/"
638
+ script_refreshed=$((script_refreshed + 1))
639
+ done
640
+ done 2>/dev/null || true
641
+
642
+ local script_total
643
+ script_total=$(find "$target/.gator/scripts" -type f 2>/dev/null | wc -l | tr -d ' ')
644
+ log_step "Scripts: $script_refreshed template files refreshed, $script_total total (extras preserved)"
645
+
646
+ # --- Content files: create stubs only if missing ---
647
+ for stub_file in mission.md roadmap.md inbox.md commit_draft.md whiteboard.md \
648
+ patterns.md issues.md; do
649
+ if [ ! -f "$target/.gator/$stub_file" ]; then
650
+ case "$stub_file" in
651
+ mission.md) echo "# Mission" > "$target/.gator/$stub_file" ;;
652
+ roadmap.md) echo "# Roadmap" > "$target/.gator/$stub_file" ;;
653
+ inbox.md) printf "# Inbox\n\n---\n\n" > "$target/.gator/$stub_file" ;;
654
+ commit_draft.md) cat > "$target/.gator/$stub_file" << 'CDSTUB'
655
+ ---
656
+ message: ""
657
+ change-type:
658
+ significance:
659
+ decision-tags: []
660
+ agent:
661
+ architect:
662
+ ---
663
+
664
+ # Session Change Log
665
+
666
+ CDSTUB
667
+ ;;
668
+ whiteboard.md) echo "# Whiteboard" > "$target/.gator/$stub_file" ;;
669
+ patterns.md) printf "# Patterns\n\n---\n\n" > "$target/.gator/$stub_file" ;;
670
+ issues.md) printf "# Issues\n\n---\n\n" > "$target/.gator/$stub_file" ;;
671
+ esac
672
+ log_step "Created missing stub: $stub_file"
673
+ fi
674
+ done
675
+
676
+ # Identity: create only if missing
677
+ if [ ! -f "$target/.gator/identity.md" ]; then
678
+ echo "# Identity" > "$target/.gator/identity.md"
679
+ log_step "Created missing stub: identity.md"
680
+ fi
681
+
682
+ # Charter INDEX: create only if missing
683
+ if [ ! -f "$target/.gator/charters/INDEX.md" ]; then
684
+ cat > "$target/.gator/charters/INDEX.md" << 'STUB'
685
+ # Charter Index
686
+
687
+ **Always read first:** [Cross-Cutting](cross-cutting.md) (when it exists)
688
+
689
+ | If you're changing... | Read these charters |
690
+ |---|---|
691
+ | | |
692
+ STUB
693
+ log_step "Created missing charters/INDEX.md"
694
+ fi
695
+
696
+ # Enforcement config: create only if missing (preserves user changes)
697
+ if [ ! -f "$target/.gator/config.json" ]; then
698
+ printf '{\n "enforcement_level": "strict"\n}\n' > "$target/.gator/config.json"
699
+ log_step "Created config.json (enforcement: strict)"
700
+ fi
701
+
702
+ # --- .gitkeep for empty dirs ---
703
+ [ -z "$(ls -A "$target/.gator/threads" 2>/dev/null)" ] && \
704
+ touch "$target/.gator/threads/.gitkeep"
705
+ [ -z "$(ls -A "$target/.gator/artifacts" 2>/dev/null)" ] && \
706
+ touch "$target/.gator/artifacts/.gitkeep"
707
+
708
+ # --- Install/refresh git hooks ---
709
+ install_hooks "$target"
710
+
711
+ # --- Write version marker ---
712
+ write_gator_version "$target" "upgrade"
713
+
714
+ log_blank
715
+ log_step "Upgraded .gator/ (gen $gen → $GATOR_GEN) — templates refreshed, content preserved."
716
+ }
717
+
718
+ # =============================================================================
719
+ # Action: Morph memex → gator (Scenario 4)
720
+ # =============================================================================
721
+
722
+ action_morph_memex() {
723
+ local target="$1"
724
+
725
+ detect_legacy_memex "$target"
726
+
727
+ log_blank
728
+ echo " Legacy memex structure detected:"
729
+ $HAS_MEMEX_DIR && echo " memex/ (content layer)"
730
+ $HAS_DOT_MEMEX_DIR && echo " .memex/ (system layer)"
731
+ $HAS_ROOT_CONSTITUTION && echo " constitution.md (root)"
732
+ $HAS_ROOT_CONSTITUTION_CORE && echo " constitution-core.md (root)"
733
+ log_blank
734
+ echo " Gatorize will morph this into .gator/ structure:"
735
+ echo " 1. Rename legacy dirs to *.pre-gator/ (preserves history, easy rollback)"
736
+ echo " 2. Install fresh .gator/ from templates"
737
+ echo " 3. Copy your content (mission, threads, artifacts, etc.) into .gator/"
738
+ echo " 4. Archive root constitution files"
739
+ echo " 5. Leave pre-gator dirs on this branch for review"
740
+ log_blank
741
+ if ! confirm "Proceed with morph?" "Y"; then
742
+ echo " Aborted."
743
+ exit 0
744
+ fi
745
+
746
+ # --- Step 1: Rename legacy dirs using git mv where possible ---
747
+
748
+ (
749
+ cd "$target"
750
+ if $HAS_MEMEX_DIR; then
751
+ if [ -d "memex.pre-gator" ]; then
752
+ echo " memex.pre-gator/ already exists — skipping rename"
753
+ else
754
+ git mv "memex" "memex.pre-gator" 2>/dev/null || \
755
+ mv "memex" "memex.pre-gator"
756
+ log_step "Renamed memex/ → memex.pre-gator/"
757
+ fi
758
+ fi
759
+ if $HAS_DOT_MEMEX_DIR; then
760
+ if [ -d ".memex.pre-gator" ]; then
761
+ echo " .memex.pre-gator/ already exists — skipping rename"
762
+ else
763
+ git mv ".memex" ".memex.pre-gator" 2>/dev/null || \
764
+ mv ".memex" ".memex.pre-gator"
765
+ log_step "Renamed .memex/ → .memex.pre-gator/"
766
+ fi
767
+ fi
768
+ )
769
+
770
+ # --- Step 2: Install .gator/ skeleton (or upgrade existing) ---
771
+
772
+ if [ -d "$target/.gator" ]; then
773
+ log_step "Existing .gator/ found — upgrading templates, preserving content."
774
+ action_upgrade_gator "$target"
775
+ else
776
+ action_install_gator "$target"
777
+ fi
778
+
779
+ # --- Step 3: Overlay content from memex.pre-gator/ ---
780
+
781
+ local src="$target/memex.pre-gator"
782
+
783
+ if [ -d "$src" ]; then
784
+ log_step "Migrating content from memex.pre-gator/ into .gator/ ..."
785
+
786
+ # Direct-copy content files (overwrite stubs)
787
+ for f in mission.md roadmap.md identity.md inbox.md issues.md \
788
+ commit_draft.md whiteboard.md friction.md audit-tracker.md; do
789
+ if [ -f "$src/$f" ]; then
790
+ cp "$src/$f" "$target/.gator/$f"
791
+ log_step " Migrated $f"
792
+ fi
793
+ done
794
+
795
+ # patterns — could be a file or a directory
796
+ if [ -d "$src/patterns" ]; then
797
+ mkdir -p "$target/.gator/patterns"
798
+ cp -r "$src/patterns/"* "$target/.gator/patterns/" 2>/dev/null || true
799
+ log_step " Migrated patterns/"
800
+ elif [ -f "$src/patterns.md" ]; then
801
+ cp "$src/patterns.md" "$target/.gator/patterns.md"
802
+ log_step " Migrated patterns.md"
803
+ fi
804
+
805
+ # active-threads → .gator/threads/ (demoted to reference tier)
806
+ if [ -d "$src/active-threads" ]; then
807
+ local at_count=0
808
+ for f in "$src/active-threads/"*.md; do
809
+ [ -f "$f" ] || continue
810
+ local basename_f
811
+ basename_f=$(basename "$f")
812
+ [ "$basename_f" = "_TEMPLATE.md" ] && continue
813
+ [ "$basename_f" = "_template.md" ] && continue
814
+ if [ -f "$target/.gator/threads/$basename_f" ]; then
815
+ cp "$f" "$target/.gator/threads/${basename_f%.md}-legacy.md"
816
+ else
817
+ cp "$f" "$target/.gator/threads/$basename_f"
818
+ fi
819
+ at_count=$((at_count + 1))
820
+ done
821
+ [ "$at_count" -gt 0 ] && log_step " Migrated $at_count active threads → threads/ (demoted)"
822
+ fi
823
+
824
+ # threads → .gator/threads/ (merge)
825
+ if [ -d "$src/threads" ]; then
826
+ local t_count=0
827
+ for f in "$src/threads/"*.md; do
828
+ [ -f "$f" ] || continue
829
+ local basename_f
830
+ basename_f=$(basename "$f")
831
+ if [ -f "$target/.gator/threads/$basename_f" ]; then
832
+ cp "$f" "$target/.gator/threads/${basename_f%.md}-legacy.md"
833
+ else
834
+ cp "$f" "$target/.gator/threads/$basename_f"
835
+ fi
836
+ t_count=$((t_count + 1))
837
+ done
838
+ [ "$t_count" -gt 0 ] && log_step " Migrated $t_count threads"
839
+ fi
840
+
841
+ # artifacts
842
+ if [ -d "$src/artifacts" ]; then
843
+ local a_count=0
844
+ for f in "$src/artifacts/"*.md; do
845
+ [ -f "$f" ] || continue
846
+ cp "$f" "$target/.gator/artifacts/"
847
+ a_count=$((a_count + 1))
848
+ done
849
+ [ "$a_count" -gt 0 ] && log_step " Migrated $a_count artifacts"
850
+ fi
851
+
852
+ # charters — preserve user charters, gator templates already installed
853
+ if [ -d "$src/charters" ]; then
854
+ local c_count=0
855
+ for f in "$src/charters/"*.md; do
856
+ [ -f "$f" ] || continue
857
+ local basename_f
858
+ basename_f=$(basename "$f")
859
+ case "$basename_f" in
860
+ _template.md|README.md) continue ;;
861
+ esac
862
+ cp "$f" "$target/.gator/charters/$basename_f"
863
+ c_count=$((c_count + 1))
864
+ done
865
+ [ "$c_count" -gt 0 ] && log_step " Migrated $c_count charters"
866
+ fi
867
+
868
+ # vault
869
+ if [ -d "$src/vault" ] && [ -n "$(ls -A "$src/vault" 2>/dev/null)" ]; then
870
+ cp -r "$src/vault/"* "$target/.gator/vault/" 2>/dev/null || true
871
+ log_step " Migrated vault/"
872
+ fi
873
+
874
+ # reference-notes — legacy notes may conflict with template notes
875
+ if [ -d "$src/reference-notes" ]; then
876
+ local rn_count=0 rn_conflict=0
877
+ for f in "$src/reference-notes/"*.md; do
878
+ [ -f "$f" ] || continue
879
+ local basename_f
880
+ basename_f=$(basename "$f")
881
+ if [ -f "$target/.gator/reference-notes/$basename_f" ]; then
882
+ if ! diff -q "$f" "$target/.gator/reference-notes/$basename_f" >/dev/null 2>&1; then
883
+ cp "$f" "$target/.gator/reference-notes/${basename_f%.md}-project.md"
884
+ rn_conflict=$((rn_conflict + 1))
885
+ fi
886
+ else
887
+ cp "$f" "$target/.gator/reference-notes/$basename_f"
888
+ rn_count=$((rn_count + 1))
889
+ fi
890
+ done
891
+ [ "$rn_count" -gt 0 ] && log_step " Migrated $rn_count reference notes"
892
+ [ "$rn_conflict" -gt 0 ] && log_step " Preserved $rn_conflict conflicting notes with -project suffix"
893
+ fi
894
+ fi
895
+
896
+ # --- Step 4: Overlay from .memex.pre-gator/ ---
897
+
898
+ local dotsrc="$target/.memex.pre-gator"
899
+
900
+ if [ -d "$dotsrc" ]; then
901
+ log_step "Migrating system layer from .memex.pre-gator/ ..."
902
+
903
+ if [ -f "$dotsrc/roles.yaml" ]; then
904
+ cp "$dotsrc/roles.yaml" "$target/.gator/roles.yaml"
905
+ log_step " Migrated roles.yaml"
906
+ fi
907
+
908
+ if [ -d "$dotsrc/policies" ]; then
909
+ mkdir -p "$target/.gator/policies"
910
+ cp "$dotsrc/policies/"*.md "$target/.gator/policies/" 2>/dev/null || true
911
+ log_step " Migrated policies/"
912
+ fi
913
+
914
+ log_step " Skipped .memex/scripts/ (gator provides its own)"
915
+ fi
916
+
917
+ # --- Step 5: Archive root constitution files ---
918
+
919
+ (
920
+ cd "$target"
921
+ if $HAS_ROOT_CONSTITUTION && [ -f "constitution.md" ]; then
922
+ git mv "constitution.md" ".gator/legacy-constitution.md" 2>/dev/null || \
923
+ mv "constitution.md" ".gator/legacy-constitution.md"
924
+ log_step "Archived constitution.md → .gator/legacy-constitution.md"
925
+ fi
926
+ if $HAS_ROOT_CONSTITUTION_CORE && [ -f "constitution-core.md" ]; then
927
+ git mv "constitution-core.md" ".gator/legacy-constitution-core.md" 2>/dev/null || \
928
+ mv "constitution-core.md" ".gator/legacy-constitution-core.md"
929
+ log_step "Archived constitution-core.md → .gator/legacy-constitution-core.md"
930
+ fi
931
+ )
932
+
933
+ # Remove .gitkeep from dirs that now have content
934
+ [ -n "$(find "$target/.gator/threads" -name "*.md" 2>/dev/null)" ] && \
935
+ rm -f "$target/.gator/threads/.gitkeep"
936
+ [ -n "$(find "$target/.gator/artifacts" -name "*.md" 2>/dev/null)" ] && \
937
+ rm -f "$target/.gator/artifacts/.gitkeep"
938
+
939
+ # Write version marker
940
+ write_gator_version "$target" "morph"
941
+
942
+ log_blank
943
+ log_step "Morph complete. Pre-gator directories preserved for review:"
944
+ $HAS_MEMEX_DIR && log_step " memex.pre-gator/ — your original content"
945
+ $HAS_DOT_MEMEX_DIR && log_step " .memex.pre-gator/ — your original system layer"
946
+ log_step "Review .gator/, then delete pre-gator dirs when satisfied."
947
+ }
948
+
949
+ # =============================================================================
950
+ # Action: Handle dual memex + gator (Scenario 5)
951
+ # =============================================================================
952
+
953
+ action_warn_dual() {
954
+ local target="$1"
955
+
956
+ detect_legacy_memex "$target"
957
+
958
+ log_blank
959
+ echo " Both memex and gator structures found in $target."
960
+ echo " This is ambiguous — could be a partial migration or manual setup."
961
+ log_blank
962
+ echo " Legacy memex:"
963
+ $HAS_MEMEX_DIR && echo " memex/"
964
+ $HAS_DOT_MEMEX_DIR && echo " .memex/"
965
+ $HAS_ROOT_CONSTITUTION && echo " constitution.md (root)"
966
+ $HAS_ROOT_CONSTITUTION_CORE && echo " constitution-core.md (root)"
967
+ echo " Gator:"
968
+ echo " .gator/"
969
+ log_blank
970
+ echo " Options:"
971
+ echo " [m] Morph — fold memex content into existing .gator/ (recommended)"
972
+ echo " [u] Upgrade — refresh .gator/ templates, ignore memex dirs"
973
+ echo " [a] Abort — inspect manually first"
974
+ log_blank
975
+ read -rp " Choice [m/u/a]: " dual_choice
976
+
977
+ case "$dual_choice" in
978
+ [Mm])
979
+ action_morph_memex "$target"
980
+ ;;
981
+ [Uu])
982
+ action_upgrade_gator "$target"
983
+ ;;
984
+ *)
985
+ echo " Aborted. Inspect the repo manually and re-run when ready."
986
+ exit 0
987
+ ;;
988
+ esac
989
+ }