repo-nexus 0.7.18 → 0.7.19

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.
@@ -131,8 +131,8 @@ cmd_plugin_info() {
131
131
  [ -n "$_item" ] || continue
132
132
  _s="${_item%%:*}"
133
133
  _d="${_item#*:}"
134
- _s="$(printf '%s' "$_s" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
135
- _d="$(printf '%s' "$_d" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
134
+ _s="$(printf '%s' "$_s" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/^["\047]//' -e 's/["\047]$//')"
135
+ _d="$(printf '%s' "$_d" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/^["\047]//' -e 's/["\047]$//')"
136
136
  _d="$(plugin_resolve_placeholders "$_name" "$_pdir" "$_d")"
137
137
  printf ' - %s → %s\n' "$_s" "$_d"
138
138
  done
package/lib/hooks.sh CHANGED
@@ -115,6 +115,11 @@ run_plugin_git_hooks() {
115
115
  RNEX_ARGS="$*"
116
116
  RNEX_QUIET="${_sync_quiet:-0}"
117
117
 
118
+ _stdin_data=""
119
+ if [ ! -t 0 ]; then
120
+ _stdin_data="$(cat)"
121
+ fi
122
+
118
123
  _plugins="$(yaml_list_plugins 2>/dev/null || true)"
119
124
  for _pname in $_plugins; do
120
125
  [ -n "$_pname" ] || continue
@@ -143,7 +148,11 @@ run_plugin_git_hooks() {
143
148
  chmod +x "$_h_cand" 2>/dev/null || true
144
149
  (
145
150
  export RNEX_ROOT RNEX_CONFIG_MERGED RNEX_PLUGIN_DIR RNEX_CMD RNEX_ARGS RNEX_QUIET
146
- "$_h_cand" "$@"
151
+ if [ -n "$_stdin_data" ]; then
152
+ printf '%s\n' "$_stdin_data" | "$_h_cand" "$@"
153
+ else
154
+ "$_h_cand" "$@"
155
+ fi
147
156
  ) || true
148
157
  fi
149
158
  done
@@ -377,11 +386,27 @@ cmd_hooks() {
377
386
  return 0
378
387
  ;;
379
388
  pre-push)
380
- run_plugin_git_hooks "pre-push" "$@"
389
+ _stdin_data=""
390
+ if [ ! -t 0 ]; then
391
+ _stdin_data="$(cat)"
392
+ fi
393
+ if [ -n "$_stdin_data" ]; then
394
+ printf '%s\n' "$_stdin_data" | run_plugin_git_hooks "pre-push" "$@"
395
+ else
396
+ run_plugin_git_hooks "pre-push" "$@"
397
+ fi
381
398
  if [ -x "$NEXUS_DIR/scripts/githooks/pre-push" ]; then
382
- "$NEXUS_DIR/scripts/githooks/pre-push" "$@" || return $?
399
+ if [ -n "$_stdin_data" ]; then
400
+ printf '%s\n' "$_stdin_data" | "$NEXUS_DIR/scripts/githooks/pre-push" "$@" || return $?
401
+ else
402
+ "$NEXUS_DIR/scripts/githooks/pre-push" "$@" || return $?
403
+ fi
383
404
  elif [ -x "$NEXUS_DIR/.githooks/pre-push" ]; then
384
- "$NEXUS_DIR/.githooks/pre-push" "$@" || return $?
405
+ if [ -n "$_stdin_data" ]; then
406
+ printf '%s\n' "$_stdin_data" | "$NEXUS_DIR/.githooks/pre-push" "$@" || return $?
407
+ else
408
+ "$NEXUS_DIR/.githooks/pre-push" "$@" || return $?
409
+ fi
385
410
  fi
386
411
  return 0
387
412
  ;;
package/lib/plugins.sh CHANGED
@@ -91,7 +91,7 @@ plugin_list_instructions() {
91
91
 
92
92
  plugin_resolve_placeholders() {
93
93
  _p="$1"; _pd="$2"; _str="$3"
94
- _res="$_str"
94
+ _res="$(printf '%s' "$_str" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/^["\047]//' -e 's/["\047]$//')"
95
95
 
96
96
  if [ -f "$_pd/plugin.yaml" ]; then
97
97
  _keys="$(awk '
@@ -142,6 +142,8 @@ plugin_resolve_placeholders() {
142
142
  -e "s|^wiki/|${_w_val}/|" \
143
143
  -e "s|^raw/|${_r_val}/|")"
144
144
 
145
+ _res="$(printf '%s' "$_res" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/^["\047]//' -e 's/["\047]$//')"
146
+
145
147
  printf '%s' "$_res"
146
148
  }
147
149
 
@@ -230,8 +232,8 @@ sync_plugins() {
230
232
  [ -n "$_item" ] || continue
231
233
  _s="${_item%%:*}"
232
234
  _d="${_item#*:}"
233
- _s="$(printf '%s' "$_s" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
234
- _d="$(printf '%s' "$_d" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
235
+ _s="$(printf '%s' "$_s" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/^["\047]//' -e 's/["\047]$//')"
236
+ _d="$(printf '%s' "$_d" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/^["\047]//' -e 's/["\047]$//')"
235
237
 
236
238
  _d="$(plugin_resolve_placeholders "$_pname" "$_pdir" "$_d")"
237
239
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repo-nexus",
3
- "version": "0.7.18",
3
+ "version": "0.7.19",
4
4
  "description": "Lightweight, zero-dependency Virtual Meta-Repo companion for multi-repo workspaces and shared AI context (no git submodules)",
5
5
  "bin": {
6
6
  "repo-nexus": "rnex",
@@ -103,3 +103,137 @@ rnex_unregister_user_skill() {
103
103
  fi
104
104
  done
105
105
  }
106
+
107
+ # Provider configuration check helper
108
+ if ! command -v provider_option_enabled >/dev/null 2>&1; then
109
+ provider_option_enabled() {
110
+ _p="$1"; _opt="$2"
111
+ _r="${NEXUS_DIR:-${RNEX_ROOT:-.}}"
112
+ _val=""
113
+ if [ -f "$_r/.local.rnex.yaml" ]; then
114
+ _val="$(awk -v p="$_p" -v o="$_opt" '
115
+ /^plugins:/ { in_p=1; next }
116
+ in_p && /^[^ #]/ { in_p=0; in_target=0 }
117
+ in_p && match($0, "^[ ]*" p ":[ ]*(#.*)?$") { in_target=1; next }
118
+ in_target && (/^[ ]{1,2}[^ #]/ || /^[^ #]/) { in_target=0 }
119
+ in_target && $0 ~ ("^[ ]*" o ":") {
120
+ sub("^[ ]*" o ":[ ]*", "")
121
+ sub(/[ ]*#.*/, "")
122
+ gsub(/["\047]/, "")
123
+ print
124
+ exit
125
+ }
126
+ ' "$_r/.local.rnex.yaml")"
127
+ fi
128
+ if [ -z "$_val" ] && [ -f "$_r/rnex.yaml" ]; then
129
+ _val="$(awk -v p="$_p" -v o="$_opt" '
130
+ /^plugins:/ { in_p=1; next }
131
+ in_p && /^[^ #]/ { in_p=0; in_target=0 }
132
+ in_p && match($0, "^[ ]*" p ":[ ]*(#.*)?$") { in_target=1; next }
133
+ in_target && (/^[ ]{1,2}[^ #]/ || /^[^ #]/) { in_target=0 }
134
+ in_target && $0 ~ ("^[ ]*" o ":") {
135
+ sub("^[ ]*" o ":[ ]*", "")
136
+ sub(/[ ]*#.*/, "")
137
+ gsub(/["\047]/, "")
138
+ print
139
+ exit
140
+ }
141
+ ' "$_r/rnex.yaml")"
142
+ fi
143
+ _val="$(printf '%s' "$_val" | tr '[:upper:]' '[:lower:]')"
144
+ case "$_val" in
145
+ false|no|0|disabled|off) return 1 ;;
146
+ *) return 0 ;;
147
+ esac
148
+ }
149
+ fi
150
+
151
+ # Instructions routing helpers
152
+ if ! command -v merge_rnex_instructions >/dev/null 2>&1; then
153
+ merge_rnex_instructions() {
154
+ _dst="$1"
155
+ _m_start="<!-- REPO-NEXUS:START -->"
156
+ _m_end="<!-- REPO-NEXUS:END -->"
157
+ _instr="CRITICAL: You MUST read and strictly follow all instructions in \`.rnex/ai-instructions.md\` before executing any task or answering any query in this workspace."
158
+ if [ ! -f "$_dst" ]; then
159
+ mkdir -p "$(dirname "$_dst")"
160
+ printf '%s\n%s\n%s\n' "$_m_start" "$_instr" "$_m_end" > "$_dst"
161
+ return 0
162
+ fi
163
+ if grep -qF "$_m_start" "$_dst" 2>/dev/null; then
164
+ _tmp="$(mktemp)"
165
+ awk -v s="$_m_start" -v e="$_m_end" -v msg="$_instr" '
166
+ $0 == s { in_b = 1; print s; print msg; next }
167
+ $0 == e { in_b = 0; print e; next }
168
+ !in_b { print }
169
+ ' "$_dst" > "$_tmp" && mv "$_tmp" "$_dst"
170
+ return 0
171
+ fi
172
+ _tmp="$(mktemp)"
173
+ cp "$_dst" "$_tmp"
174
+ if [ -s "$_tmp" ] && [ -n "$(tail -c 1 "$_tmp" 2>/dev/null)" ]; then
175
+ printf '\n' >> "$_tmp"
176
+ fi
177
+ printf '\n%s\n%s\n%s\n' "$_m_start" "$_instr" "$_m_end" >> "$_tmp"
178
+ mv "$_tmp" "$_dst"
179
+ }
180
+ fi
181
+
182
+ if ! command -v clean_rnex_instructions >/dev/null 2>&1; then
183
+ clean_rnex_instructions() {
184
+ _dst="$1"
185
+ [ -f "$_dst" ] || return 0
186
+ _m_start="<!-- REPO-NEXUS:START -->"
187
+ _m_end="<!-- REPO-NEXUS:END -->"
188
+ if grep -qF "$_m_start" "$_dst" 2>/dev/null; then
189
+ _non_rnex="$(awk -v s="$_m_start" -v e="$_m_end" '
190
+ $0 == s { skip=1; next }
191
+ $0 == e { skip=0; next }
192
+ !skip { print }
193
+ ' "$_dst" | tr -d " \t\r\n")"
194
+ if [ -z "$_non_rnex" ]; then
195
+ rm -f "$_dst"
196
+ else
197
+ _tmp="$(mktemp)"
198
+ awk -v s="$_m_start" -v e="$_m_end" '
199
+ $0 == s { skip=1; next }
200
+ $0 == e { skip=0; next }
201
+ !skip { print }
202
+ ' "$_dst" > "$_tmp" && mv "$_tmp" "$_dst"
203
+ fi
204
+ fi
205
+ }
206
+ fi
207
+
208
+ if ! command -v clean_provider_user_skills >/dev/null 2>&1; then
209
+ clean_provider_user_skills() {
210
+ _sk_dir="$1"
211
+ [ -d "$_sk_dir" ] || return 0
212
+ rm -f "$_sk_dir"/rnex-*.md 2>/dev/null || true
213
+ for _d in "$_sk_dir"/rnex-*; do
214
+ [ -d "$_d" ] || continue
215
+ rm -rf "$_d" 2>/dev/null || true
216
+ done
217
+ rmdir "$_sk_dir" 2>/dev/null || true
218
+ }
219
+ fi
220
+
221
+ if ! command -v clean_provider_agents >/dev/null 2>&1; then
222
+ clean_provider_agents() {
223
+ _ag_dir="$1"
224
+ _ext="${2:-.md}"
225
+ _r="${NEXUS_DIR:-${RNEX_ROOT:-.}}"
226
+ [ -d "$_ag_dir" ] || return 0
227
+ for _pdir in "$_r/toolkit/plugins"/* "$_r/.rnex/plugins"/*; do
228
+ [ -d "$_pdir" ] || continue
229
+ [ -d "$_pdir/agents" ] || continue
230
+ for _afile in "$_pdir/agents"/*.md; do
231
+ [ -f "$_afile" ] || continue
232
+ _aname="$(basename "$_afile" .agent.md)"
233
+ _aname="$(basename "$_aname" .md)"
234
+ rm -f "$_ag_dir/${_aname}${_ext}" 2>/dev/null || true
235
+ done
236
+ done
237
+ rmdir "$_ag_dir" 2>/dev/null || true
238
+ }
239
+ fi
@@ -1,22 +1,162 @@
1
1
  #!/bin/sh
2
2
  set -e
3
3
  _root="${RNEX_ROOT:-${NEXUS_DIR:-$PWD}}"
4
+ NEXUS_DIR="${NEXUS_DIR:-$_root}"
5
+ WORKSPACE_YAML="${WORKSPACE_YAML:-$_root/rnex.yaml}"
6
+ WORKSPACE_LOCAL_YAML="${WORKSPACE_LOCAL_YAML:-$_root/.local.rnex.yaml}"
7
+ export RNEX_ROOT NEXUS_DIR WORKSPACE_YAML WORKSPACE_LOCAL_YAML
4
8
 
5
- if ! command -v merge_rnex_instructions >/dev/null 2>&1; then
9
+ # Explicitly locate and source core helper library if functions not preloaded
10
+ if ! command -v merge_rnex_instructions >/dev/null 2>&1 || ! command -v provider_option_enabled >/dev/null 2>&1; then
11
+ if [ -z "${RNEX_LIB_DIR:-}" ]; then
12
+ for _cand in \
13
+ "$_root/lib" \
14
+ "$(dirname "$0")/../../../../lib" \
15
+ "$(dirname "$0")/../../../lib"; do
16
+ if [ -d "$_cand" ] && [ -f "$_cand/ai.sh" ]; then
17
+ RNEX_LIB_DIR="$(cd "$_cand" 2>/dev/null && pwd -P)"
18
+ break
19
+ fi
20
+ done
21
+ fi
22
+ if [ -n "${RNEX_LIB_DIR:-}" ] && [ -d "$RNEX_LIB_DIR" ]; then
23
+ [ -f "$RNEX_LIB_DIR/core.sh" ] && . "$RNEX_LIB_DIR/core.sh" 2>/dev/null || true
24
+ [ -f "$RNEX_LIB_DIR/workspace.sh" ] && . "$RNEX_LIB_DIR/workspace.sh" 2>/dev/null || true
25
+ [ -f "$RNEX_LIB_DIR/yaml.sh" ] && . "$RNEX_LIB_DIR/yaml.sh" 2>/dev/null || true
26
+ [ -f "$RNEX_LIB_DIR/ai.sh" ] && . "$RNEX_LIB_DIR/ai.sh" 2>/dev/null || true
27
+ fi
6
28
  if [ -f "$_root/.rnex/bin/rnex-env.sh" ]; then
7
29
  . "$_root/.rnex/bin/rnex-env.sh"
8
30
  fi
9
31
  fi
10
32
 
33
+ # Complete guarded fallback contract for standalone or restricted hook runners
34
+ if ! command -v provider_option_enabled >/dev/null 2>&1; then
35
+ provider_option_enabled() {
36
+ _p="$1"; _opt="$2"
37
+ _val=""
38
+ if [ -f "$_root/.local.rnex.yaml" ]; then
39
+ _val="$(awk -v p="$_p" -v o="$_opt" '
40
+ /^plugins:/ { in_p=1; next }
41
+ in_p && /^[^ #]/ { in_p=0; in_target=0 }
42
+ in_p && match($0, "^[ ]*" p ":[ ]*(#.*)?$") { in_target=1; next }
43
+ in_target && (/^[ ]{1,2}[^ #]/ || /^[^ #]/) { in_target=0 }
44
+ in_target && $0 ~ ("^[ ]*" o ":") {
45
+ sub("^[ ]*" o ":[ ]*", "")
46
+ sub(/[ ]*#.*/, "")
47
+ gsub(/["\047]/, "")
48
+ print
49
+ exit
50
+ }
51
+ ' "$_root/.local.rnex.yaml")"
52
+ fi
53
+ if [ -z "$_val" ] && [ -f "$_root/rnex.yaml" ]; then
54
+ _val="$(awk -v p="$_p" -v o="$_opt" '
55
+ /^plugins:/ { in_p=1; next }
56
+ in_p && /^[^ #]/ { in_p=0; in_target=0 }
57
+ in_p && match($0, "^[ ]*" p ":[ ]*(#.*)?$") { in_target=1; next }
58
+ in_target && (/^[ ]{1,2}[^ #]/ || /^[^ #]/) { in_target=0 }
59
+ in_target && $0 ~ ("^[ ]*" o ":") {
60
+ sub("^[ ]*" o ":[ ]*", "")
61
+ sub(/[ ]*#.*/, "")
62
+ gsub(/["\047]/, "")
63
+ print
64
+ exit
65
+ }
66
+ ' "$_root/rnex.yaml")"
67
+ fi
68
+ _val="$(printf '%s' "$_val" | tr '[:upper:]' '[:lower:]')"
69
+ case "$_val" in
70
+ false|no|0|disabled|off) return 1 ;;
71
+ *) return 0 ;;
72
+ esac
73
+ }
74
+ fi
75
+
76
+ if ! command -v merge_rnex_instructions >/dev/null 2>&1; then
77
+ merge_rnex_instructions() {
78
+ _dst="$1"
79
+ _m_start="<!-- REPO-NEXUS:START -->"
80
+ _m_end="<!-- REPO-NEXUS:END -->"
81
+ _instr="CRITICAL: You MUST read and strictly follow all instructions in \`.rnex/ai-instructions.md\` before executing any task or answering any query in this workspace."
82
+ if [ ! -f "$_dst" ]; then
83
+ mkdir -p "$(dirname "$_dst")"
84
+ printf '%s\n%s\n%s\n' "$_m_start" "$_instr" "$_m_end" > "$_dst"
85
+ return 0
86
+ fi
87
+ if grep -qF "$_m_start" "$_dst" 2>/dev/null; then
88
+ _tmp="$(mktemp)"
89
+ awk -v s="$_m_start" -v e="$_m_end" -v msg="$_instr" '
90
+ $0 == s { in_b = 1; print s; print msg; next }
91
+ $0 == e { in_b = 0; print e; next }
92
+ !in_b { print }
93
+ ' "$_dst" > "$_tmp" && mv "$_tmp" "$_dst"
94
+ return 0
95
+ fi
96
+ _tmp="$(mktemp)"
97
+ cp "$_dst" "$_tmp"
98
+ if [ -s "$_tmp" ] && [ -n "$(tail -c 1 "$_tmp" 2>/dev/null)" ]; then
99
+ printf '\n' >> "$_tmp"
100
+ fi
101
+ printf '\n%s\n%s\n%s\n' "$_m_start" "$_instr" "$_m_end" >> "$_tmp"
102
+ mv "$_tmp" "$_dst"
103
+ }
104
+ fi
105
+
106
+ if ! command -v clean_rnex_instructions >/dev/null 2>&1; then
107
+ clean_rnex_instructions() {
108
+ _dst="$1"
109
+ [ -f "$_dst" ] || return 0
110
+ _m_start="<!-- REPO-NEXUS:START -->"
111
+ _m_end="<!-- REPO-NEXUS:END -->"
112
+ if grep -qF "$_m_start" "$_dst" 2>/dev/null; then
113
+ _non_rnex="$(awk -v s="$_m_start" -v e="$_m_end" '
114
+ $0 == s { skip=1; next }
115
+ $0 == e { skip=0; next }
116
+ !skip { print }
117
+ ' "$_dst" | tr -d " \t\r\n")"
118
+ if [ -z "$_non_rnex" ]; then
119
+ rm -f "$_dst"
120
+ else
121
+ _tmp="$(mktemp)"
122
+ awk -v s="$_m_start" -v e="$_m_end" '
123
+ $0 == s { skip=1; next }
124
+ $0 == e { skip=0; next }
125
+ !skip { print }
126
+ ' "$_dst" > "$_tmp" && mv "$_tmp" "$_dst"
127
+ fi
128
+ fi
129
+ }
130
+ fi
131
+
132
+ if ! command -v clean_provider_user_skills >/dev/null 2>&1; then
133
+ clean_provider_user_skills() {
134
+ _sk_dir="$1"
135
+ [ -d "$_sk_dir" ] || return 0
136
+ rm -f "$_sk_dir"/rnex-*.md 2>/dev/null || true
137
+ for _d in "$_sk_dir"/rnex-*; do
138
+ [ -d "$_d" ] || continue
139
+ rm -rf "$_d" 2>/dev/null || true
140
+ done
141
+ rmdir "$_sk_dir" 2>/dev/null || true
142
+ }
143
+ fi
144
+
11
145
  _inst="$(provider_option_enabled "copilot" "instructions" 2>/dev/null && echo "true" || echo "false")"
12
146
  if [ "$_inst" = "true" ]; then
13
147
  mkdir -p "$_root/.github"
14
- merge_rnex_instructions "$_root/.github/copilot-instructions.md"
148
+ if command -v merge_rnex_instructions >/dev/null 2>&1; then
149
+ merge_rnex_instructions "$_root/.github/copilot-instructions.md"
150
+ fi
15
151
  else
16
- clean_rnex_instructions "$_root/.github/copilot-instructions.md"
152
+ if command -v clean_rnex_instructions >/dev/null 2>&1; then
153
+ clean_rnex_instructions "$_root/.github/copilot-instructions.md"
154
+ fi
17
155
  fi
18
156
 
19
157
  _sk="$(provider_option_enabled "copilot" "skills" 2>/dev/null && echo "true" || echo "false")"
20
158
  if [ "$_sk" != "true" ]; then
21
- clean_provider_user_skills "$_root/.github/skills"
159
+ if command -v clean_provider_user_skills >/dev/null 2>&1; then
160
+ clean_provider_user_skills "$_root/.github/skills"
161
+ fi
22
162
  fi
@@ -1,15 +1,111 @@
1
1
  #!/bin/sh
2
2
  set -e
3
3
  _root="${RNEX_ROOT:-${NEXUS_DIR:-$PWD}}"
4
+ NEXUS_DIR="${NEXUS_DIR:-$_root}"
5
+ WORKSPACE_YAML="${WORKSPACE_YAML:-$_root/rnex.yaml}"
6
+ WORKSPACE_LOCAL_YAML="${WORKSPACE_LOCAL_YAML:-$_root/.local.rnex.yaml}"
7
+ export RNEX_ROOT NEXUS_DIR WORKSPACE_YAML WORKSPACE_LOCAL_YAML
4
8
 
5
- if ! command -v clean_rnex_instructions >/dev/null 2>&1; then
9
+ # Explicitly locate and source core helper library if functions not preloaded
10
+ if ! command -v clean_rnex_instructions >/dev/null 2>&1 || ! command -v clean_provider_user_skills >/dev/null 2>&1 || ! command -v clean_provider_agents >/dev/null 2>&1; then
11
+ if [ -z "${RNEX_LIB_DIR:-}" ]; then
12
+ for _cand in \
13
+ "$_root/lib" \
14
+ "$(dirname "$0")/../../../../lib" \
15
+ "$(dirname "$0")/../../../lib"; do
16
+ if [ -d "$_cand" ] && [ -f "$_cand/ai.sh" ]; then
17
+ RNEX_LIB_DIR="$(cd "$_cand" 2>/dev/null && pwd -P)"
18
+ break
19
+ fi
20
+ done
21
+ fi
22
+ if [ -n "${RNEX_LIB_DIR:-}" ] && [ -d "$RNEX_LIB_DIR" ]; then
23
+ [ -f "$RNEX_LIB_DIR/core.sh" ] && . "$RNEX_LIB_DIR/core.sh" 2>/dev/null || true
24
+ [ -f "$RNEX_LIB_DIR/workspace.sh" ] && . "$RNEX_LIB_DIR/workspace.sh" 2>/dev/null || true
25
+ [ -f "$RNEX_LIB_DIR/yaml.sh" ] && . "$RNEX_LIB_DIR/yaml.sh" 2>/dev/null || true
26
+ [ -f "$RNEX_LIB_DIR/ai.sh" ] && . "$RNEX_LIB_DIR/ai.sh" 2>/dev/null || true
27
+ fi
6
28
  if [ -f "$_root/.rnex/bin/rnex-env.sh" ]; then
7
29
  . "$_root/.rnex/bin/rnex-env.sh"
8
30
  fi
9
31
  fi
10
32
 
11
- clean_rnex_instructions "$_root/.github/copilot-instructions.md"
12
- clean_provider_user_skills "$_root/.github/skills"
13
- clean_provider_agents "$_root/.github/agents" ".agent.md"
14
- rm -rf "$_root/.github/prompts" 2>/dev/null || true
33
+ # Complete guarded fallback contract for standalone or restricted hook runners
34
+ if ! command -v clean_rnex_instructions >/dev/null 2>&1; then
35
+ clean_rnex_instructions() {
36
+ _dst="$1"
37
+ [ -f "$_dst" ] || return 0
38
+ _m_start="<!-- REPO-NEXUS:START -->"
39
+ _m_end="<!-- REPO-NEXUS:END -->"
40
+ if grep -qF "$_m_start" "$_dst" 2>/dev/null; then
41
+ _non_rnex="$(awk -v s="$_m_start" -v e="$_m_end" '
42
+ $0 == s { skip=1; next }
43
+ $0 == e { skip=0; next }
44
+ !skip { print }
45
+ ' "$_dst" | tr -d " \t\r\n")"
46
+ if [ -z "$_non_rnex" ]; then
47
+ rm -f "$_dst"
48
+ else
49
+ _tmp="$(mktemp)"
50
+ awk -v s="$_m_start" -v e="$_m_end" '
51
+ $0 == s { skip=1; next }
52
+ $0 == e { skip=0; next }
53
+ !skip { print }
54
+ ' "$_dst" > "$_tmp" && mv "$_tmp" "$_dst"
55
+ fi
56
+ fi
57
+ }
58
+ fi
59
+
60
+ if ! command -v clean_provider_user_skills >/dev/null 2>&1; then
61
+ clean_provider_user_skills() {
62
+ _sk_dir="$1"
63
+ [ -d "$_sk_dir" ] || return 0
64
+ rm -f "$_sk_dir"/rnex-*.md 2>/dev/null || true
65
+ for _d in "$_sk_dir"/rnex-*; do
66
+ [ -d "$_d" ] || continue
67
+ rm -rf "$_d" 2>/dev/null || true
68
+ done
69
+ rmdir "$_sk_dir" 2>/dev/null || true
70
+ }
71
+ fi
72
+
73
+ if ! command -v clean_provider_agents >/dev/null 2>&1; then
74
+ clean_provider_agents() {
75
+ _ag_dir="$1"
76
+ _ext="${2:-.md}"
77
+ [ -d "$_ag_dir" ] || return 0
78
+ for _pdir in "$_root/toolkit/plugins"/* "$_root/.rnex/plugins"/*; do
79
+ [ -d "$_pdir" ] || continue
80
+ [ -d "$_pdir/agents" ] || continue
81
+ for _afile in "$_pdir/agents"/*.md; do
82
+ [ -f "$_afile" ] || continue
83
+ _aname="$(basename "$_afile" .agent.md)"
84
+ _aname="$(basename "$_aname" .md)"
85
+ rm -f "$_ag_dir/${_aname}${_ext}" 2>/dev/null || true
86
+ done
87
+ done
88
+ rmdir "$_ag_dir" 2>/dev/null || true
89
+ }
90
+ fi
91
+
92
+ if command -v clean_rnex_instructions >/dev/null 2>&1; then
93
+ clean_rnex_instructions "$_root/.github/copilot-instructions.md"
94
+ fi
95
+ if command -v clean_provider_user_skills >/dev/null 2>&1; then
96
+ clean_provider_user_skills "$_root/.github/skills"
97
+ fi
98
+ if command -v clean_provider_agents >/dev/null 2>&1; then
99
+ clean_provider_agents "$_root/.github/agents" ".agent.md"
100
+ fi
101
+
102
+ # Remove only files owned by this plugin in .github/prompts/ and delete directory only if empty
103
+ if [ -d "$_root/.github/prompts" ]; then
104
+ rm -f "$_root/.github/prompts"/rnex-*.prompt.md "$_root/.github/prompts"/rnex-*.md 2>/dev/null || true
105
+ for _p in "$_root/.github/prompts"/rnex-*; do
106
+ [ -e "$_p" ] || continue
107
+ rm -rf "$_p" 2>/dev/null || true
108
+ done
109
+ rmdir "$_root/.github/prompts" 2>/dev/null || true
110
+ fi
15
111
  rmdir "$_root/.github" 2>/dev/null || true
@@ -44,12 +44,54 @@ _raw="$(printf '%s' "$_raw" | sed -e 's#^\./##' -e 's#^/##' -e 's#/$##')"
44
44
 
45
45
  _trigger="$(get_cfg "lint_trigger" "manual")"
46
46
  if [ "$_trigger" = "git-pre-push" ] || [ "$_trigger" = "pre-push" ]; then
47
- _notify="$(get_cfg "notify_on_changes" "true")"
48
- if [ "$_notify" != "false" ]; then
49
- _wiki_path="$_root/$_wiki"
50
- if [ ! -f "$_wiki_path/index.md" ] || [ ! -f "$_wiki_path/hot.md" ]; then
51
- printf '[WIKI] Warning: Required wiki files (index.md or hot.md) missing in %s/.\n' "$_wiki"
47
+ _has_wiki_changes=0
48
+ _has_input=0
49
+ _z40="0000000000000000000000000000000000000000"
50
+
51
+ # 1. Inspect pushed revisions if provided on stdin (standard Git pre-push hook contract)
52
+ if [ ! -t 0 ]; then
53
+ while read -r _local_ref _local_sha _remote_ref _remote_sha; do
54
+ [ -z "$_local_sha" ] && continue
55
+ [ "$_local_sha" = "$_z40" ] && continue
56
+ _has_input=1
57
+
58
+ if [ -z "$_remote_sha" ] || [ "$_remote_sha" = "$_z40" ]; then
59
+ if git -C "$_root" diff-tree -r --name-only --root "$_local_sha" 2>/dev/null | grep -qE "(^|/)($_raw|$_wiki)/"; then
60
+ _has_wiki_changes=1
61
+ break
62
+ fi
63
+ else
64
+ if git -C "$_root" diff-tree -r --name-only "$_remote_sha" "$_local_sha" 2>/dev/null | grep -qE "(^|/)($_raw|$_wiki)/"; then
65
+ _has_wiki_changes=1
66
+ break
67
+ fi
68
+ fi
69
+ done
70
+ fi
71
+
72
+ # 2. Fallback when invoked without piped stdin (e.g. CLI direct execution or test runners)
73
+ if [ "$_has_input" -eq 0 ]; then
74
+ if [ -n "${1:-}" ] && [ -n "${2:-}" ] && git -C "$_root" cat-file -e "${1:-}" 2>/dev/null && git -C "$_root" cat-file -e "${2:-}" 2>/dev/null; then
75
+ if git -C "$_root" diff-tree -r --name-only "$1" "$2" 2>/dev/null | grep -qE "(^|/)($_raw|$_wiki)/"; then
76
+ _has_wiki_changes=1
77
+ fi
78
+ elif git -C "$_root" rev-parse --verify HEAD >/dev/null 2>&1; then
79
+ if git -C "$_root" diff-tree -r --name-only --root HEAD 2>/dev/null | grep -qE "(^|/)($_raw|$_wiki)/"; then
80
+ _has_wiki_changes=1
81
+ fi
82
+ elif git -C "$_root" status --porcelain 2>/dev/null | grep -qE "(^[A-Z? ]+[ ]+|/)($_raw|$_wiki)/"; then
83
+ _has_wiki_changes=1
84
+ fi
85
+ fi
86
+
87
+ if [ "$_has_wiki_changes" -eq 1 ]; then
88
+ _notify="$(get_cfg "notify_on_changes" "true")"
89
+ if [ "$_notify" != "false" ]; then
90
+ _wiki_path="$_root/$_wiki"
91
+ if [ ! -f "$_wiki_path/index.md" ] || [ ! -f "$_wiki_path/hot.md" ]; then
92
+ printf '[WIKI] Warning: Required wiki files (index.md or hot.md) missing in %s/.\n' "$_wiki"
93
+ fi
94
+ printf '[WIKI] Reminder: Wiki files changed. Run the rnex-karpathy-llm-wiki-lint skill to verify.\n'
52
95
  fi
53
- printf '[WIKI] Reminder: Wiki files changed. Run the rnex-karpathy-llm-wiki-lint skill to verify.\n'
54
96
  fi
55
97
  fi
@@ -34,7 +34,7 @@ Do not create arbitrary or speculative subdirectories during initialization. Sca
34
34
 
35
35
  ### 2. Index File Format
36
36
 
37
- `/wiki/index.md` uses its own frontmatter schema (it is the wiki navigation file, not an atomic content page):
37
+ `.rnex/wiki/index.md` uses its own frontmatter schema (it is the wiki navigation file, not an atomic content page):
38
38
 
39
39
  ```yaml
40
40
  ---
@@ -58,8 +58,8 @@ Every wiki page is a single atomic markdown file covering one concept, entity, s
58
58
  title: ""
59
59
  tags: []
60
60
  last_updated: YYYY-MM-DD
61
- # Typed relation fields — paths relative to /wiki/
62
- sources: [] # /raw/ files this page was derived from
61
+ # Typed relation fields — paths relative to .rnex/wiki/
62
+ sources: [] # ./docs/ files this page was derived from
63
63
  related: [] # thematically related wiki pages
64
64
  extends: [] # pages this one builds upon or specialises
65
65
  contradicts: [] # pages with conflicting information
@@ -26,9 +26,9 @@ skills:
26
26
  instructions:
27
27
  - instructions/rnex-wiki-architecture.md: .rnex/plugins/karpathy-llm/instructions/rnex-wiki-architecture.md
28
28
  templates:
29
- - templates/index.md: {wiki_dir}/index.md
30
- - templates/_log.md: {wiki_dir}/_log.md
31
- - templates/hot.md: {wiki_dir}/hot.md
32
- - templates/raw.gitkeep: {raw_dir}/.gitkeep
29
+ - templates/index.md: "{wiki_dir}/index.md"
30
+ - templates/_log.md: "{wiki_dir}/_log.md"
31
+ - templates/hot.md: "{wiki_dir}/hot.md"
32
+ - templates/raw.gitkeep: "{raw_dir}/.gitkeep"
33
33
  - templates/rnex-wiki-page.sample.md: .rnex/plugins/karpathy-llm/templates/rnex-wiki-page.template.md
34
34
  - templates/rnex-llm-wiki.sample.md: .rnex/plugins/karpathy-llm/templates/rnex-llm-wiki.sample.md