repo-nexus 0.5.2 → 0.5.4
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/CHANGELOG.md +20 -0
- package/README.md +4 -1
- package/docs/CLI.md +16 -7
- package/docs/rnex.example.yaml +14 -0
- package/package.json +1 -1
- package/rnex +277 -46
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,26 @@ All notable changes to Repo Nexus (`rnex`) will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Explicit `git_hooks` Workspace Configuration (`rnex.yaml` & `.local.rnex.yaml`)**:
|
|
12
|
+
- Top-level `git_hooks: true|false` setting establishes the workspace configuration as the single source of truth for automated Git hooks.
|
|
13
|
+
- Two-level configuration support allowing per-workstation overrides in `.local.rnex.yaml` (e.g. keeping hooks globally enabled in `rnex.yaml` while disabling locally via `rnex hooks uninstall --local`).
|
|
14
|
+
- `rnex hooks install [--local]` and `rnex hooks uninstall [--local]` record preference directly to `rnex.yaml` or `.local.rnex.yaml`.
|
|
15
|
+
- `rnex fix` (and `rnex sync`) automatically reconciles Git's `core.hooksPath` against the resolved `git_hooks` configuration.
|
|
16
|
+
- Interactive `rnex init` determines and records `git_hooks` preference upfront in new workspaces.
|
|
17
|
+
- Workspace schema migration in `rnex update` and `rnex fix -y` non-destructively inserts `git_hooks` into older configurations.
|
|
18
|
+
- `rnex status` and `rnex hooks status` display configuration state alongside runtime Git hooks status.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- **Git Hooks Self-Rewrite & Wrapper Preservation**:
|
|
22
|
+
- Resolved self-rewrite bug where `rnex hooks run post-merge` invoked `cmd_fix`, which truncated and replaced `.rnex/hooks/post-merge` while the shell interpreter was actively executing it.
|
|
23
|
+
- Added in-hook execution guard (`_RNEX_INSIDE_HOOK=1`) preventing hook script regeneration during active hook dispatch.
|
|
24
|
+
- Preserved custom / repository-owned wrappers in `.rnex/hooks/` that are not auto-managed by `rnex`.
|
|
25
|
+
- Added `cmp -s` check before writing hook files to eliminate unnecessary file churn and in-place overwrites.
|
|
26
|
+
- Automatically chain to existing repository-owned `.githooks/` scripts if present.
|
|
27
|
+
|
|
8
28
|
## [0.5.1] - 2026-10-08
|
|
9
29
|
|
|
10
30
|
### Added
|
package/README.md
CHANGED
|
@@ -245,6 +245,9 @@ The `karpathy-llm` plugin packages Andrej Karpathy's verified LLM agent design p
|
|
|
245
245
|
# Directory for member repository clones
|
|
246
246
|
repos_dir: ./repos
|
|
247
247
|
|
|
248
|
+
# Automated workspace Git hooks (default: true)
|
|
249
|
+
git_hooks: true
|
|
250
|
+
|
|
248
251
|
# Workspace plugins
|
|
249
252
|
plugins:
|
|
250
253
|
karpathy-llm: {}
|
|
@@ -301,7 +304,7 @@ repos:
|
|
|
301
304
|
| `rnex rnex-dir <enable\|disable> <name>` | Toggle `.rnex/` directory integration for a member repository |
|
|
302
305
|
| `rnex fix [-y] [--quiet]` (or `sync`) | Reconcile workspace repositories, plugins, prompts, and member `.rnex/` directories |
|
|
303
306
|
| `rnex update [-y]` (or `upgrade`) | Safely upgrade workspace configuration schema and routing instructions |
|
|
304
|
-
| `rnex hooks <install\|uninstall\|status
|
|
307
|
+
| `rnex hooks <install\|uninstall\|status> [--local]` | Manage automated Git hooks (`.rnex/hooks` and `git_hooks: true\|false`) |
|
|
305
308
|
| `rnex plugin <list\|info\|enable\|disable>` | Manage workspace plugins |
|
|
306
309
|
| `rnex completion <bash\|zsh\|fish>` | Generate shell auto-completion script |
|
|
307
310
|
|
package/docs/CLI.md
CHANGED
|
@@ -316,26 +316,35 @@ rnex rnex-dir <enable|disable> <name>
|
|
|
316
316
|
|
|
317
317
|
## Git Hooks Automation Commands
|
|
318
318
|
|
|
319
|
-
Repo Nexus manages workspace-level Git hooks via `git config core.hooksPath .rnex/hooks
|
|
319
|
+
Repo Nexus manages workspace-level Git hooks via `git config core.hooksPath .rnex/hooks` and configuration in `rnex.yaml` (`git_hooks: true|false`). The hooks are native shell scripts that dynamically evaluate configuration triggers in `rnex.yaml` and `.local.rnex.yaml`.
|
|
320
320
|
|
|
321
321
|
```sh
|
|
322
|
-
rnex hooks <install|uninstall|status>
|
|
322
|
+
rnex hooks <install|uninstall|status> [--local]
|
|
323
323
|
```
|
|
324
324
|
|
|
325
|
+
### Configuration (`rnex.yaml` / `.local.rnex.yaml`)
|
|
326
|
+
```yaml
|
|
327
|
+
# Enable or disable automated Git hooks
|
|
328
|
+
git_hooks: true # default: true (when in a Git repository)
|
|
329
|
+
```
|
|
330
|
+
- When `git_hooks: true`, `rnex fix` ensures hooks are installed and up to date.
|
|
331
|
+
- When `git_hooks: false`, `rnex fix` disables and uninstalls hooks from Git.
|
|
332
|
+
- Overrides can be placed in `.local.rnex.yaml` to disable hooks locally without modifying team config.
|
|
333
|
+
|
|
325
334
|
### Subcommands
|
|
326
335
|
|
|
327
|
-
#### `rnex hooks install`
|
|
328
|
-
Installs native hook dispatchers into `.rnex/hooks
|
|
336
|
+
#### `rnex hooks install [--local]`
|
|
337
|
+
Installs native hook dispatchers into `.rnex/hooks/`, sets `core.hooksPath = .rnex/hooks`, and records `git_hooks: true` in `rnex.yaml` (or `.local.rnex.yaml` if `--local` is passed):
|
|
329
338
|
- **`post-merge`**: Automatically runs `rnex fix -y --quiet` whenever you run `git pull` or merge upstream changes, ensuring new repositories or plugin additions sync instantly.
|
|
330
339
|
- **`post-commit`**: Evaluates `lint_trigger: git-post-commit`. If `/raw/` or `/wiki/` files were committed, alerts the user to run maintenance workflows.
|
|
331
340
|
- **`pre-commit`**: Evaluates `lint_trigger: git-pre-commit`. Validates staged files before committing.
|
|
332
341
|
- **`pre-push`**: Evaluates `lint_trigger: git-pre-push`. Validates changes before pushing to remote.
|
|
333
342
|
|
|
334
343
|
#### `rnex hooks status`
|
|
335
|
-
Displays the active `core.hooksPath`, installed hook scripts, and plugin triggers detected in `rnex.yaml`.
|
|
344
|
+
Displays the configuration setting (`git_hooks: true/false`), active `core.hooksPath`, installed hook scripts, and plugin triggers detected in `rnex.yaml`.
|
|
336
345
|
|
|
337
|
-
#### `rnex hooks uninstall`
|
|
338
|
-
Unsets `core.hooksPath` in Git configuration
|
|
346
|
+
#### `rnex hooks uninstall [--local]`
|
|
347
|
+
Unsets `core.hooksPath` in Git configuration, removes `.rnex/hooks/`, and records `git_hooks: false` in `rnex.yaml` (or `.local.rnex.yaml` if `--local` is passed).
|
|
339
348
|
|
|
340
349
|
---
|
|
341
350
|
|
package/docs/rnex.example.yaml
CHANGED
|
@@ -59,6 +59,20 @@ ai_instructions: AGENTS.md
|
|
|
59
59
|
#
|
|
60
60
|
code_workspace: false
|
|
61
61
|
|
|
62
|
+
# ------------------------------------------------------------------------------
|
|
63
|
+
# git_hooks — Automated workspace Git hooks
|
|
64
|
+
# ------------------------------------------------------------------------------
|
|
65
|
+
# Enables automated Git hooks in `.rnex/hooks/` (post-merge auto-sync and
|
|
66
|
+
# optional plugin triggers like Karpathy wiki lint on commit/push).
|
|
67
|
+
#
|
|
68
|
+
# Default: true (when initialized in a Git repository)
|
|
69
|
+
#
|
|
70
|
+
# Examples:
|
|
71
|
+
# git_hooks: true # active (core.hooksPath = .rnex/hooks)
|
|
72
|
+
# git_hooks: false # disabled
|
|
73
|
+
#
|
|
74
|
+
git_hooks: true
|
|
75
|
+
|
|
62
76
|
# ------------------------------------------------------------------------------
|
|
63
77
|
# plugins — Workspace plugins and AI instruction packs
|
|
64
78
|
# ------------------------------------------------------------------------------
|
package/package.json
CHANGED
package/rnex
CHANGED
|
@@ -146,6 +146,7 @@ require_workspace() {
|
|
|
146
146
|
_load_repos_dir
|
|
147
147
|
_load_ai_instructions_file
|
|
148
148
|
_load_code_workspace
|
|
149
|
+
_load_git_hooks
|
|
149
150
|
log_info "Using workspace at ${_BOLD}$NEXUS_DIR${_NC} ${_DIM}(via config: $WORKSPACE_YAML)${_NC}"
|
|
150
151
|
return 0
|
|
151
152
|
fi
|
|
@@ -175,6 +176,7 @@ require_workspace() {
|
|
|
175
176
|
_load_repos_dir
|
|
176
177
|
_load_ai_instructions_file
|
|
177
178
|
_load_code_workspace
|
|
179
|
+
_load_git_hooks
|
|
178
180
|
|
|
179
181
|
log_info "Using workspace at ${_BOLD}$NEXUS_DIR${_NC} ${_DIM}($(basename "$WORKSPACE_YAML") found)${_NC}"
|
|
180
182
|
}
|
|
@@ -254,6 +256,18 @@ _load_code_workspace() {
|
|
|
254
256
|
esac
|
|
255
257
|
}
|
|
256
258
|
|
|
259
|
+
_load_git_hooks() {
|
|
260
|
+
_gh=""
|
|
261
|
+
if [ -f "$WORKSPACE_LOCAL_YAML" ]; then
|
|
262
|
+
_gh="$(awk '/^(git_hooks|hooks):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_LOCAL_YAML")"
|
|
263
|
+
fi
|
|
264
|
+
if [ -z "$_gh" ] && [ -f "$WORKSPACE_YAML" ]; then
|
|
265
|
+
_gh="$(awk '/^(git_hooks|hooks):/ { sub(/^[a-zA-Z0-9_]+:[ ]*/, ""); sub(/[ ]*#.*/, ""); val=$0 } END { if (val) print val }' "$WORKSPACE_YAML")"
|
|
266
|
+
fi
|
|
267
|
+
_gh="$(echo "$_gh" | tr -d " \t\r\n'\"")"
|
|
268
|
+
GIT_HOOKS_CONFIG="$_gh"
|
|
269
|
+
}
|
|
270
|
+
|
|
257
271
|
# ---- YAML Parser / Manipulator (for rnex.yaml & .local.rnex.yaml) ----------
|
|
258
272
|
|
|
259
273
|
_yaml_list_plugins_from_file() {
|
|
@@ -575,6 +589,60 @@ EOF
|
|
|
575
589
|
_yaml_set_in_file "$WORKSPACE_LOCAL_YAML" "$_repo" "$_field" "$_value"
|
|
576
590
|
}
|
|
577
591
|
|
|
592
|
+
_yaml_set_top_level_in_file() {
|
|
593
|
+
_file="$1"
|
|
594
|
+
_key="$2"
|
|
595
|
+
_val="$3"
|
|
596
|
+
[ -f "$_file" ] || return 0
|
|
597
|
+
_tmp="$(mktemp)"
|
|
598
|
+
if grep -q "^[ ]*${_key}:" "$_file" 2>/dev/null; then
|
|
599
|
+
awk -v key="$_key" -v val="$_val" '
|
|
600
|
+
$0 ~ ("^[ ]*" key ":") {
|
|
601
|
+
print key ": " val
|
|
602
|
+
next
|
|
603
|
+
}
|
|
604
|
+
{ print }
|
|
605
|
+
' "$_file" > "$_tmp" && mv "$_tmp" "$_file"
|
|
606
|
+
else
|
|
607
|
+
awk -v key="$_key" -v val="$_val" '
|
|
608
|
+
BEGIN { inserted=0 }
|
|
609
|
+
/^[ ]*(plugins|repos):/ && !inserted {
|
|
610
|
+
print key ": " val
|
|
611
|
+
print ""
|
|
612
|
+
inserted=1
|
|
613
|
+
}
|
|
614
|
+
{ print }
|
|
615
|
+
END {
|
|
616
|
+
if (!inserted) {
|
|
617
|
+
print ""
|
|
618
|
+
print key ": " val
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
' "$_file" > "$_tmp" && mv "$_tmp" "$_file"
|
|
622
|
+
fi
|
|
623
|
+
rm -f "$_tmp"
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
yaml_set_top_level() {
|
|
627
|
+
_key="$1"; _val="$2"
|
|
628
|
+
_yaml_set_top_level_in_file "$WORKSPACE_YAML" "$_key" "$_val"
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
yaml_set_top_level_local() {
|
|
632
|
+
_key="$1"; _val="$2"
|
|
633
|
+
if [ ! -f "$WORKSPACE_LOCAL_YAML" ]; then
|
|
634
|
+
cat <<'EOF' > "$WORKSPACE_LOCAL_YAML"
|
|
635
|
+
# ==============================================================================
|
|
636
|
+
# .local.rnex.yaml — Repo Nexus Local Configuration (Machine-Specific)
|
|
637
|
+
# ==============================================================================
|
|
638
|
+
# This file is gitignored. Use it to specify local repository paths, overrides,
|
|
639
|
+
# and enable/disable states for this workstation.
|
|
640
|
+
|
|
641
|
+
EOF
|
|
642
|
+
fi
|
|
643
|
+
_yaml_set_top_level_in_file "$WORKSPACE_LOCAL_YAML" "$_key" "$_val"
|
|
644
|
+
}
|
|
645
|
+
|
|
578
646
|
# ---- Physical Repository Path Resolution ----------------------------------
|
|
579
647
|
|
|
580
648
|
resolve_repo_path() {
|
|
@@ -1159,28 +1227,66 @@ upgrade_workspace_config() {
|
|
|
1159
1227
|
' "$_f" > "$_tmp" && mv "$_tmp" "$_f"
|
|
1160
1228
|
fi
|
|
1161
1229
|
|
|
1230
|
+
# 4. Add git_hooks if missing
|
|
1231
|
+
if ! grep -q '^[ ]*\(git_hooks\|hooks\):' "$_f" 2>/dev/null; then
|
|
1232
|
+
_def_gh="false"
|
|
1233
|
+
_cur_hp="$(git -C "$NEXUS_DIR" config --get core.hooksPath 2>/dev/null || true)"
|
|
1234
|
+
if [ "$_cur_hp" = ".rnex/hooks" ] || [ "$_cur_hp" = "$NEXUS_DIR/.rnex/hooks" ]; then
|
|
1235
|
+
_def_gh="true"
|
|
1236
|
+
fi
|
|
1237
|
+
awk -v def_gh="$_def_gh" '
|
|
1238
|
+
BEGIN { inserted=0 }
|
|
1239
|
+
/^[ ]*(plugins|repos):/ && !inserted {
|
|
1240
|
+
print "# Automated workspace Git hooks (default: true; e.g. post-merge auto-sync, plugin triggers)"
|
|
1241
|
+
print "git_hooks: " def_gh
|
|
1242
|
+
print ""
|
|
1243
|
+
inserted=1
|
|
1244
|
+
}
|
|
1245
|
+
{ print }
|
|
1246
|
+
END {
|
|
1247
|
+
if (!inserted) {
|
|
1248
|
+
print ""
|
|
1249
|
+
print "git_hooks: " def_gh
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
' "$_f" > "$_tmp" && mv "$_tmp" "$_f"
|
|
1253
|
+
fi
|
|
1254
|
+
|
|
1162
1255
|
rm -f "$_tmp"
|
|
1163
1256
|
}
|
|
1164
1257
|
|
|
1165
1258
|
_create_hook_script() {
|
|
1166
1259
|
_dst="$1"
|
|
1167
1260
|
_hook_type="$2"
|
|
1168
|
-
|
|
1261
|
+
|
|
1262
|
+
# Preserve custom / repository-owned wrappers that are not auto-managed by rnex
|
|
1263
|
+
if [ -f "$_dst" ] && ! grep -q "Managed automatically by rnex" "$_dst" 2>/dev/null; then
|
|
1264
|
+
return 0
|
|
1265
|
+
fi
|
|
1266
|
+
|
|
1267
|
+
_sub_tmp="$(mktemp)"
|
|
1268
|
+
cat > "$_sub_tmp" <<HOOK_EOF
|
|
1169
1269
|
#!/bin/sh
|
|
1170
|
-
# Repo Nexus Git Hook:
|
|
1270
|
+
# Repo Nexus Git Hook: $_hook_type
|
|
1171
1271
|
# Managed automatically by rnex. Do not edit manually.
|
|
1172
1272
|
|
|
1173
|
-
_dir="
|
|
1273
|
+
_dir="\$(cd "\$(dirname "\$0")/../.." 2>/dev/null && pwd -P)"
|
|
1174
1274
|
if command -v rnex >/dev/null 2>&1; then
|
|
1175
|
-
rnex hooks run
|
|
1176
|
-
elif [ -f "
|
|
1177
|
-
"
|
|
1275
|
+
rnex hooks run $_hook_type "\$@"
|
|
1276
|
+
elif [ -f "\$_dir/rnex" ]; then
|
|
1277
|
+
"\$_dir/rnex" hooks run $_hook_type "\$@"
|
|
1178
1278
|
fi
|
|
1179
1279
|
HOOK_EOF
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1280
|
+
|
|
1281
|
+
chmod +x "$_sub_tmp"
|
|
1282
|
+
|
|
1283
|
+
# Avoid rewriting / modifying file if already identical (prevents inode churn & self-rewrite)
|
|
1284
|
+
if [ -f "$_dst" ] && cmp -s "$_sub_tmp" "$_dst"; then
|
|
1285
|
+
rm -f "$_sub_tmp"
|
|
1286
|
+
return 0
|
|
1287
|
+
fi
|
|
1288
|
+
|
|
1289
|
+
mv "$_sub_tmp" "$_dst"
|
|
1184
1290
|
}
|
|
1185
1291
|
|
|
1186
1292
|
cmd_hooks_install_dir() {
|
|
@@ -1212,11 +1318,43 @@ cmd_hooks() {
|
|
|
1212
1318
|
case "${1:-status}" in
|
|
1213
1319
|
install)
|
|
1214
1320
|
require_workspace
|
|
1321
|
+
_local=0
|
|
1322
|
+
shift || true
|
|
1323
|
+
while [ $# -gt 0 ]; do
|
|
1324
|
+
case "$1" in
|
|
1325
|
+
--local) _local=1 ;;
|
|
1326
|
+
esac
|
|
1327
|
+
shift
|
|
1328
|
+
done
|
|
1215
1329
|
cmd_hooks_install_dir "$NEXUS_DIR"
|
|
1330
|
+
if [ "$_local" -eq 1 ]; then
|
|
1331
|
+
yaml_set_top_level_local "git_hooks" "true"
|
|
1332
|
+
log_dim "Recorded git_hooks: true in $RNEX_LOCAL_CONFIG_FILE"
|
|
1333
|
+
else
|
|
1334
|
+
yaml_set_top_level "git_hooks" "true"
|
|
1335
|
+
log_dim "Recorded git_hooks: true in $RNEX_CONFIG_FILE"
|
|
1336
|
+
fi
|
|
1337
|
+
_load_git_hooks
|
|
1216
1338
|
;;
|
|
1217
1339
|
uninstall)
|
|
1218
1340
|
require_workspace
|
|
1341
|
+
_local=0
|
|
1342
|
+
shift || true
|
|
1343
|
+
while [ $# -gt 0 ]; do
|
|
1344
|
+
case "$1" in
|
|
1345
|
+
--local) _local=1 ;;
|
|
1346
|
+
esac
|
|
1347
|
+
shift
|
|
1348
|
+
done
|
|
1219
1349
|
cmd_hooks_uninstall_dir "$NEXUS_DIR"
|
|
1350
|
+
if [ "$_local" -eq 1 ]; then
|
|
1351
|
+
yaml_set_top_level_local "git_hooks" "false"
|
|
1352
|
+
log_dim "Recorded git_hooks: false in $RNEX_LOCAL_CONFIG_FILE"
|
|
1353
|
+
else
|
|
1354
|
+
yaml_set_top_level "git_hooks" "false"
|
|
1355
|
+
log_dim "Recorded git_hooks: false in $RNEX_CONFIG_FILE"
|
|
1356
|
+
fi
|
|
1357
|
+
_load_git_hooks
|
|
1220
1358
|
;;
|
|
1221
1359
|
status)
|
|
1222
1360
|
require_workspace
|
|
@@ -1224,6 +1362,13 @@ cmd_hooks() {
|
|
|
1224
1362
|
printf '=%.0s' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
|
1225
1363
|
printf '\n\n'
|
|
1226
1364
|
|
|
1365
|
+
printf ' %b●%b Configuration: ' "$_DIM" "$_NC"
|
|
1366
|
+
case "$GIT_HOOKS_CONFIG" in
|
|
1367
|
+
true|yes|1) printf '%bgit_hooks: true%b %b(enabled in config)%b\n' "$_G" "$_NC" "$_DIM" "$_NC" ;;
|
|
1368
|
+
false|no|0) printf '%bgit_hooks: false%b %b(disabled in config)%b\n' "$_Y" "$_NC" "$_DIM" "$_NC" ;;
|
|
1369
|
+
*) printf '%bnot configured%b %b(defaults to active if git repo)%b\n' "$_DIM" "$_NC" "$_DIM" "$_NC" ;;
|
|
1370
|
+
esac
|
|
1371
|
+
|
|
1227
1372
|
_hp="$(git -C "$NEXUS_DIR" config --get core.hooksPath 2>/dev/null || true)"
|
|
1228
1373
|
if [ "$_hp" = ".rnex/hooks" ] || [ "$_hp" = "$NEXUS_DIR/.rnex/hooks" ]; then
|
|
1229
1374
|
printf ' %b●%b core.hooksPath: %s %b(active)%b\n' "$_G" "$_NC" "$_hp" "$_DIM" "$_NC"
|
|
@@ -1258,6 +1403,7 @@ cmd_hooks() {
|
|
|
1258
1403
|
shift
|
|
1259
1404
|
_hook_name="$1"
|
|
1260
1405
|
shift || true
|
|
1406
|
+
export _RNEX_INSIDE_HOOK=1
|
|
1261
1407
|
require_workspace
|
|
1262
1408
|
case "$_hook_name" in
|
|
1263
1409
|
post-merge)
|
|
@@ -1271,6 +1417,9 @@ cmd_hooks() {
|
|
|
1271
1417
|
fi
|
|
1272
1418
|
fi
|
|
1273
1419
|
fi
|
|
1420
|
+
if [ -x "$NEXUS_DIR/.githooks/post-merge" ]; then
|
|
1421
|
+
"$NEXUS_DIR/.githooks/post-merge" "$@" || true
|
|
1422
|
+
fi
|
|
1274
1423
|
return 0
|
|
1275
1424
|
;;
|
|
1276
1425
|
post-commit)
|
|
@@ -1284,6 +1433,9 @@ cmd_hooks() {
|
|
|
1284
1433
|
fi
|
|
1285
1434
|
fi
|
|
1286
1435
|
fi
|
|
1436
|
+
if [ -x "$NEXUS_DIR/.githooks/post-commit" ]; then
|
|
1437
|
+
"$NEXUS_DIR/.githooks/post-commit" "$@" || true
|
|
1438
|
+
fi
|
|
1287
1439
|
return 0
|
|
1288
1440
|
;;
|
|
1289
1441
|
pre-commit)
|
|
@@ -1297,6 +1449,9 @@ cmd_hooks() {
|
|
|
1297
1449
|
fi
|
|
1298
1450
|
fi
|
|
1299
1451
|
fi
|
|
1452
|
+
if [ -x "$NEXUS_DIR/.githooks/pre-commit" ]; then
|
|
1453
|
+
"$NEXUS_DIR/.githooks/pre-commit" "$@" || return $?
|
|
1454
|
+
fi
|
|
1300
1455
|
return 0
|
|
1301
1456
|
;;
|
|
1302
1457
|
pre-push)
|
|
@@ -1306,6 +1461,9 @@ cmd_hooks() {
|
|
|
1306
1461
|
printf '%b[WIKI]%b Pre-push trigger: verifying wiki changes.\n' "$_C" "$_NC"
|
|
1307
1462
|
fi
|
|
1308
1463
|
fi
|
|
1464
|
+
if [ -x "$NEXUS_DIR/.githooks/pre-push" ]; then
|
|
1465
|
+
"$NEXUS_DIR/.githooks/pre-push" "$@" || return $?
|
|
1466
|
+
fi
|
|
1309
1467
|
return 0
|
|
1310
1468
|
;;
|
|
1311
1469
|
esac
|
|
@@ -1373,6 +1531,29 @@ cmd_init() {
|
|
|
1373
1531
|
fi
|
|
1374
1532
|
mkdir -p "$_target_dir"
|
|
1375
1533
|
|
|
1534
|
+
_is_git_ws=0
|
|
1535
|
+
if git -C "$_target_dir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
1536
|
+
_is_git_ws=1
|
|
1537
|
+
fi
|
|
1538
|
+
|
|
1539
|
+
_init_git_hooks="false"
|
|
1540
|
+
if [ "$_is_git_ws" -eq 1 ]; then
|
|
1541
|
+
if [ "$_cli_no_hooks" -eq 1 ] || [ "$_cli_hooks" = "false" ]; then
|
|
1542
|
+
_init_git_hooks="false"
|
|
1543
|
+
elif [ "$_cli_hooks" = "true" ] || [ "$_non_interactive" -eq 1 ]; then
|
|
1544
|
+
_init_git_hooks="true"
|
|
1545
|
+
elif [ -t 0 ]; then
|
|
1546
|
+
printf '%bConfigure automated Git hooks (post-merge auto-sync & wiki triggers)? [Y/n]: %b' "$_BOLD" "$_NC"
|
|
1547
|
+
read -r _h_ans
|
|
1548
|
+
case "$_h_ans" in
|
|
1549
|
+
n*|N*) _init_git_hooks="false" ;;
|
|
1550
|
+
*) _init_git_hooks="true" ;;
|
|
1551
|
+
esac
|
|
1552
|
+
else
|
|
1553
|
+
_init_git_hooks="true"
|
|
1554
|
+
fi
|
|
1555
|
+
fi
|
|
1556
|
+
|
|
1376
1557
|
# ---- 1. Create config file if none exists ---------------------------------
|
|
1377
1558
|
_config_created=0
|
|
1378
1559
|
if [ -f "$_target_yaml" ]; then
|
|
@@ -1396,6 +1577,9 @@ ai_instructions: ${_cli_ai_instructions:-AGENTS.md}
|
|
|
1396
1577
|
# VS Code / Cursor multi-root workspace file (default: false; e.g. true or workspace.code-workspace)
|
|
1397
1578
|
code_workspace: ${_cli_code_workspace:-false}
|
|
1398
1579
|
|
|
1580
|
+
# Automated workspace Git hooks (default: true; e.g. post-merge auto-sync, plugin triggers)
|
|
1581
|
+
git_hooks: $_init_git_hooks
|
|
1582
|
+
|
|
1399
1583
|
# Workspace plugins
|
|
1400
1584
|
plugins:
|
|
1401
1585
|
|
|
@@ -1479,22 +1663,11 @@ YAML_EOF
|
|
|
1479
1663
|
fi
|
|
1480
1664
|
|
|
1481
1665
|
# ---- 7. Setup automated Git hooks if inside a Git repository ------------
|
|
1482
|
-
if
|
|
1483
|
-
if [ "$
|
|
1484
|
-
log_dim "Skipping Git hooks setup (--no-hooks specified)"
|
|
1485
|
-
elif [ "$_cli_hooks" = "true" ] || [ "$_non_interactive" -eq 1 ]; then
|
|
1666
|
+
if [ "$_is_git_ws" -eq 1 ]; then
|
|
1667
|
+
if [ "$_init_git_hooks" = "true" ]; then
|
|
1486
1668
|
cmd_hooks_install_dir "$_target_dir"
|
|
1487
1669
|
else
|
|
1488
|
-
|
|
1489
|
-
printf '%bConfigure automated Git hooks (post-merge auto-sync & wiki triggers)? [Y/n]: %b' "$_BOLD" "$_NC"
|
|
1490
|
-
read -r _h_ans
|
|
1491
|
-
case "$_h_ans" in
|
|
1492
|
-
n*|N*) log_dim "Skipping Git hooks setup (run 'rnex hooks install' later)" ;;
|
|
1493
|
-
*) cmd_hooks_install_dir "$_target_dir" ;;
|
|
1494
|
-
esac
|
|
1495
|
-
else
|
|
1496
|
-
cmd_hooks_install_dir "$_target_dir"
|
|
1497
|
-
fi
|
|
1670
|
+
log_dim "Skipping Git hooks setup (run 'rnex hooks install' later to enable)"
|
|
1498
1671
|
fi
|
|
1499
1672
|
fi
|
|
1500
1673
|
|
|
@@ -1820,19 +1993,50 @@ cmd_status() {
|
|
|
1820
1993
|
fi
|
|
1821
1994
|
|
|
1822
1995
|
_hooks_path="$(git -C "$NEXUS_DIR" config --get core.hooksPath 2>/dev/null || true)"
|
|
1996
|
+
_gh_active=0
|
|
1823
1997
|
if [ "$_hooks_path" = ".rnex/hooks" ] || [ "$_hooks_path" = "$NEXUS_DIR/.rnex/hooks" ]; then
|
|
1824
|
-
|
|
1825
|
-
if yaml_has_plugin "karpathy-llm"; then
|
|
1826
|
-
_active_trigger="$(yaml_plugin_get "karpathy-llm" "lint_trigger")"
|
|
1827
|
-
fi
|
|
1828
|
-
if [ -n "$_active_trigger" ]; then
|
|
1829
|
-
printf ' %b✓%b Git Hooks: active (.rnex/hooks — post-merge auto-sync, %s)\n' "$_G" "$_NC" "$_active_trigger"
|
|
1830
|
-
else
|
|
1831
|
-
printf ' %b✓%b Git Hooks: active (.rnex/hooks — post-merge auto-sync)\n' "$_G" "$_NC"
|
|
1832
|
-
fi
|
|
1833
|
-
else
|
|
1834
|
-
printf ' %b○%b Git Hooks: not configured (run "rnex hooks install" to enable)\n' "$_DIM" "$_NC"
|
|
1998
|
+
_gh_active=1
|
|
1835
1999
|
fi
|
|
2000
|
+
|
|
2001
|
+
case "$GIT_HOOKS_CONFIG" in
|
|
2002
|
+
false|no|0)
|
|
2003
|
+
if [ "$_gh_active" -eq 1 ]; then
|
|
2004
|
+
printf ' %b!%b Git Hooks: active in Git, but disabled in config (git_hooks: false; run "rnex fix" to reconcile)\n' "$_Y" "$_NC"
|
|
2005
|
+
else
|
|
2006
|
+
printf ' %b○%b Git Hooks: disabled in configuration (git_hooks: false)\n' "$_DIM" "$_NC"
|
|
2007
|
+
fi
|
|
2008
|
+
;;
|
|
2009
|
+
true|yes|1)
|
|
2010
|
+
if [ "$_gh_active" -eq 1 ]; then
|
|
2011
|
+
_active_trigger=""
|
|
2012
|
+
if yaml_has_plugin "karpathy-llm"; then
|
|
2013
|
+
_active_trigger="$(yaml_plugin_get "karpathy-llm" "lint_trigger")"
|
|
2014
|
+
fi
|
|
2015
|
+
if [ -n "$_active_trigger" ]; then
|
|
2016
|
+
printf ' %b✓%b Git Hooks: active (git_hooks: true, .rnex/hooks — %s)\n' "$_G" "$_NC" "$_active_trigger"
|
|
2017
|
+
else
|
|
2018
|
+
printf ' %b✓%b Git Hooks: active (git_hooks: true, .rnex/hooks — post-merge auto-sync)\n' "$_G" "$_NC"
|
|
2019
|
+
fi
|
|
2020
|
+
else
|
|
2021
|
+
printf ' %b!%b Git Hooks: enabled in config (git_hooks: true), but not active in Git (run "rnex fix")\n' "$_Y" "$_NC"
|
|
2022
|
+
fi
|
|
2023
|
+
;;
|
|
2024
|
+
*)
|
|
2025
|
+
if [ "$_gh_active" -eq 1 ]; then
|
|
2026
|
+
_active_trigger=""
|
|
2027
|
+
if yaml_has_plugin "karpathy-llm"; then
|
|
2028
|
+
_active_trigger="$(yaml_plugin_get "karpathy-llm" "lint_trigger")"
|
|
2029
|
+
fi
|
|
2030
|
+
if [ -n "$_active_trigger" ]; then
|
|
2031
|
+
printf ' %b✓%b Git Hooks: active (.rnex/hooks — post-merge auto-sync, %s)\n' "$_G" "$_NC" "$_active_trigger"
|
|
2032
|
+
else
|
|
2033
|
+
printf ' %b✓%b Git Hooks: active (.rnex/hooks — post-merge auto-sync)\n' "$_G" "$_NC"
|
|
2034
|
+
fi
|
|
2035
|
+
else
|
|
2036
|
+
printf ' %b○%b Git Hooks: not configured (run "rnex hooks install" to enable)\n' "$_DIM" "$_NC"
|
|
2037
|
+
fi
|
|
2038
|
+
;;
|
|
2039
|
+
esac
|
|
1836
2040
|
printf '\n'
|
|
1837
2041
|
|
|
1838
2042
|
printf '%bWorkspace AI Context (Routing):%b\n' "$_BOLD" "$_NC"
|
|
@@ -1969,6 +2173,7 @@ cmd_fix() {
|
|
|
1969
2173
|
_load_repos_dir
|
|
1970
2174
|
_load_ai_instructions_file
|
|
1971
2175
|
_load_code_workspace
|
|
2176
|
+
_load_git_hooks
|
|
1972
2177
|
[ "$_fix_quiet" -eq 0 ] && log_ok "Upgraded workspace configuration and routing instructions to v$RNEX_VERSION"
|
|
1973
2178
|
fi
|
|
1974
2179
|
fi
|
|
@@ -1985,15 +2190,41 @@ cmd_fix() {
|
|
|
1985
2190
|
# 3. Sync standard prompts to .rnex/prompts/
|
|
1986
2191
|
sync_prompts
|
|
1987
2192
|
|
|
1988
|
-
# 4.
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
2193
|
+
# 4. Reconcile Git hooks according to configuration
|
|
2194
|
+
case "$GIT_HOOKS_CONFIG" in
|
|
2195
|
+
false|no|0)
|
|
2196
|
+
_cur_hp="$(git -C "$NEXUS_DIR" config --get core.hooksPath 2>/dev/null || true)"
|
|
2197
|
+
if [ "$_cur_hp" = ".rnex/hooks" ] || [ "$_cur_hp" = "$NEXUS_DIR/.rnex/hooks" ]; then
|
|
2198
|
+
cmd_hooks_uninstall_dir "$NEXUS_DIR"
|
|
2199
|
+
fi
|
|
2200
|
+
;;
|
|
2201
|
+
true|yes|1)
|
|
2202
|
+
if git -C "$NEXUS_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
2203
|
+
_cur_hp="$(git -C "$NEXUS_DIR" config --get core.hooksPath 2>/dev/null || true)"
|
|
2204
|
+
if [ "$_cur_hp" != ".rnex/hooks" ] && [ "$_cur_hp" != "$NEXUS_DIR/.rnex/hooks" ]; then
|
|
2205
|
+
cmd_hooks_install_dir "$NEXUS_DIR"
|
|
2206
|
+
elif [ "${_RNEX_INSIDE_HOOK:-0}" -ne 1 ]; then
|
|
2207
|
+
_hooks_dir="$NEXUS_DIR/.rnex/hooks"
|
|
2208
|
+
_create_hook_script "$_hooks_dir/post-merge" "post-merge"
|
|
2209
|
+
_create_hook_script "$_hooks_dir/post-commit" "post-commit"
|
|
2210
|
+
_create_hook_script "$_hooks_dir/pre-commit" "pre-commit"
|
|
2211
|
+
_create_hook_script "$_hooks_dir/pre-push" "pre-push"
|
|
2212
|
+
fi
|
|
2213
|
+
fi
|
|
2214
|
+
;;
|
|
2215
|
+
*)
|
|
2216
|
+
_cur_hp="$(git -C "$NEXUS_DIR" config --get core.hooksPath 2>/dev/null || true)"
|
|
2217
|
+
if [ "$_cur_hp" = ".rnex/hooks" ] || [ "$_cur_hp" = "$NEXUS_DIR/.rnex/hooks" ]; then
|
|
2218
|
+
if [ "${_RNEX_INSIDE_HOOK:-0}" -ne 1 ]; then
|
|
2219
|
+
_hooks_dir="$NEXUS_DIR/.rnex/hooks"
|
|
2220
|
+
_create_hook_script "$_hooks_dir/post-merge" "post-merge"
|
|
2221
|
+
_create_hook_script "$_hooks_dir/post-commit" "post-commit"
|
|
2222
|
+
_create_hook_script "$_hooks_dir/pre-commit" "pre-commit"
|
|
2223
|
+
_create_hook_script "$_hooks_dir/pre-push" "pre-push"
|
|
2224
|
+
fi
|
|
2225
|
+
fi
|
|
2226
|
+
;;
|
|
2227
|
+
esac
|
|
1997
2228
|
|
|
1998
2229
|
# 5. Reconcile plugins
|
|
1999
2230
|
sync_plugins
|
|
@@ -2404,8 +2635,8 @@ cmd_help() {
|
|
|
2404
2635
|
install [dir] Install rnex & repo-nexus globally into ~/.local/bin (or custom dir)
|
|
2405
2636
|
fix [-y] [--quiet] Reconcile workspace, plugins, prompts & member .rnex/ (alias: sync)
|
|
2406
2637
|
update [-y] Upgrade workspace configuration and routing instructions (alias: upgrade)
|
|
2407
|
-
hooks <install|uninstall|status>
|
|
2408
|
-
Manage
|
|
2638
|
+
hooks <install|uninstall|status> [--local]
|
|
2639
|
+
Manage automated Git hooks (--local writes to .local.rnex.yaml)
|
|
2409
2640
|
completion <shell> Generate shell completion script (bash, zsh, fish)
|
|
2410
2641
|
|
|
2411
2642
|
REPO MANAGEMENT
|