repo-nexus 0.3.3 → 0.3.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/README.md +18 -10
- package/docs/rnex.example.yaml +8 -3
- package/package.json +1 -1
- package/rnex +404 -112
- package/toolkit/plugins/karpathy-llm/README.md +114 -27
- package/toolkit/plugins/karpathy-llm/instructions/karpathy-llm.md +1 -3
- package/toolkit/plugins/karpathy-llm/plugin.yaml +0 -1
- package/toolkit/plugins/karpathy-llm/rules/KARPATHY_RULES.md +1 -3
- package/toolkit/plugins/karpathy-llm/templates/_log.md +1 -1
- package/toolkit/plugins/karpathy-llm/templates/hot.md +1 -1
- package/toolkit/plugins/karpathy-llm/templates/index.md +0 -1
- package/toolkit/prompts/setup-karpathy-wiki.md +3 -31
- package/toolkit/plugins/karpathy-llm/scripts/wiki-lint-trigger.sh +0 -44
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ A **simple, lightweight companion tool** for multi-repo workflows. It links mult
|
|
|
54
54
|
|
|
55
55
|
```
|
|
56
56
|
┌─────────────────────────────────────────────────────────────┐
|
|
57
|
-
│ Repo Nexus Workspace Root
|
|
57
|
+
│ Repo Nexus Workspace Root │
|
|
58
58
|
│ │
|
|
59
59
|
│ my-workspace/ │
|
|
60
60
|
│ repos/ │
|
|
@@ -214,20 +214,22 @@ The `karpathy-llm` plugin packages Andrej Karpathy's verified LLM agent design p
|
|
|
214
214
|
* **Autonomous Karpathy LLM Wiki Knowledge Architecture:**
|
|
215
215
|
* **Intake (`/raw/`):** Append-only intake for unmodified source documents.
|
|
216
216
|
* **Curated Knowledge Base (`/wiki/`):** Interlinked atomic markdown pages with typed YAML frontmatter relations (`sources`, `related`, `extends`, `contradicts`, `mentioned_in`).
|
|
217
|
-
* **
|
|
217
|
+
* **Navigation Index (`/wiki/index.md`):** Master categorized navigation index.
|
|
218
218
|
* **Rolling Context (`/wiki/hot.md`):** ~500-word quick-orient context cache for AI agents.
|
|
219
219
|
* **Operation Log (`/wiki/_log.md`):** Append-only audit trail of ingest and lint operations.
|
|
220
|
-
* **Session Counter (`.rnex/.lint_trigger_counter`):** Machine-local state tracking session activity (gitignored).
|
|
221
|
-
* **Autonomous Lint Trigger (`.rnex/scripts/wiki-lint-trigger.sh`):** Session counter and maintenance alerts on session 1 and every 15 sessions.
|
|
222
220
|
* **Standardized Workflows (`.rnex/workflows/`):**
|
|
223
221
|
* `wiki-ingest.md`: 8-step protocol decomposing raw source documents into 5–25 atomic wiki pages.
|
|
224
222
|
* `wiki-lint.md`: 10-step protocol validating paths, recomputing `mentioned_in`, removing orphans, resolving contradictions, identifying gaps, suggesting source candidates, and rebuilding indexes.
|
|
225
223
|
|
|
226
224
|
---
|
|
227
225
|
|
|
228
|
-
##
|
|
226
|
+
## Two-Level Configuration
|
|
229
227
|
|
|
230
|
-
|
|
228
|
+
Repo Nexus supports a two-level configuration model:
|
|
229
|
+
1. **Repo Config (`rnex.yaml`):** Shared manifest committed to git. Tracks member repo names, default settings, and active plugins.
|
|
230
|
+
2. **Local Config (`.local.rnex.yaml`):** Machine-specific file ignored in `.gitignore`. Overrides or provides member repo paths on each developer's workstation.
|
|
231
|
+
|
|
232
|
+
### Repo Configuration (`rnex.yaml`)
|
|
231
233
|
|
|
232
234
|
```yaml
|
|
233
235
|
# Directory for repository symlinks (relative or absolute)
|
|
@@ -235,17 +237,15 @@ repos_dir: ./repos
|
|
|
235
237
|
|
|
236
238
|
# Workspace plugins
|
|
237
239
|
plugins:
|
|
238
|
-
karpathy-llm:
|
|
239
|
-
lint_trigger_enabled: true
|
|
240
|
+
karpathy-llm: {}
|
|
240
241
|
|
|
241
242
|
# Member repositories
|
|
242
243
|
repos:
|
|
243
244
|
backend:
|
|
244
|
-
path: /Users/dev/code/backend-api
|
|
245
245
|
scope: visible
|
|
246
246
|
rnex_dir: true # default: true (creates repos/backend/.rnex/)
|
|
247
247
|
frontend:
|
|
248
|
-
path: ../web-app
|
|
248
|
+
path: ../web-app # optional default relative path
|
|
249
249
|
scope: visible
|
|
250
250
|
rnex_dir: true
|
|
251
251
|
analytics:
|
|
@@ -254,6 +254,14 @@ repos:
|
|
|
254
254
|
rnex_dir: false # disabled: leaves analytics repo 100% untouched
|
|
255
255
|
```
|
|
256
256
|
|
|
257
|
+
### Local Configuration (`.local.rnex.yaml`)
|
|
258
|
+
|
|
259
|
+
```yaml
|
|
260
|
+
repos:
|
|
261
|
+
backend:
|
|
262
|
+
path: /Users/alice/projects/backend-api
|
|
263
|
+
```
|
|
264
|
+
|
|
257
265
|
> See [`docs/rnex.example.yaml`](docs/rnex.example.yaml) for a comprehensive example with all options.
|
|
258
266
|
> For common questions and architecture details, see the [Frequently Asked Questions (FAQ)](docs/FAQ.md).
|
|
259
267
|
|
package/docs/rnex.example.yaml
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
# ==============================================================================
|
|
2
2
|
# rnex.yaml — Repo Nexus Workspace Configuration (Full Example)
|
|
3
3
|
# ==============================================================================
|
|
4
|
-
# This file is the central manifest for a Repo Nexus workspace.
|
|
4
|
+
# This file is the central team manifest for a Repo Nexus workspace (committed to git).
|
|
5
|
+
#
|
|
6
|
+
# TWO-LEVEL CONFIGURATION:
|
|
7
|
+
# 1. Repo Config (rnex.yaml): Shared across team, tracks member repos, plugins.
|
|
8
|
+
# 2. Local Config (.local.rnex.yaml): Machine-specific (gitignored), overrides/provides
|
|
9
|
+
# local member repo paths and developer-specific plugin settings.
|
|
10
|
+
#
|
|
5
11
|
# Place it in your workspace root directory and run `rnex sync` to apply.
|
|
6
12
|
#
|
|
7
13
|
# For more information: https://github.com/nu-nenoi/repo-nexus
|
|
@@ -37,8 +43,7 @@ repos_dir: ./repos
|
|
|
37
43
|
# Local / custom plugins can also be placed in .rnex/plugins/<name>/
|
|
38
44
|
|
|
39
45
|
plugins:
|
|
40
|
-
# karpathy-llm:
|
|
41
|
-
# lint_trigger_enabled: true
|
|
46
|
+
# karpathy-llm: {}
|
|
42
47
|
|
|
43
48
|
# ------------------------------------------------------------------------------
|
|
44
49
|
# repos — Member repositories managed by Repo Nexus
|
package/package.json
CHANGED
package/rnex
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
set -e
|
|
9
9
|
|
|
10
10
|
RNEX_CONFIG_FILE="rnex.yaml"
|
|
11
|
+
RNEX_LOCAL_CONFIG_FILE=".local.rnex.yaml"
|
|
11
12
|
|
|
12
13
|
# ---- Terminal Colours (auto-detected) -------------------------------------
|
|
13
14
|
|
|
@@ -92,17 +93,17 @@ RNEX_VERSION="$(resolve_version)"
|
|
|
92
93
|
|
|
93
94
|
# ---- Workspace Detection (Context-Aware) ----------------------------------
|
|
94
95
|
|
|
95
|
-
# Search for rnex.yaml in current directory or parent directories
|
|
96
|
+
# Search for rnex.yaml or .rnex.yaml in current directory or parent directories
|
|
96
97
|
find_workspace_dir() {
|
|
97
98
|
_curr="$(pwd -P 2>/dev/null || pwd)"
|
|
98
99
|
while [ -n "$_curr" ] && [ "$_curr" != "/" ]; do
|
|
99
|
-
if [ -f "$_curr/$RNEX_CONFIG_FILE" ]; then
|
|
100
|
+
if [ -f "$_curr/$RNEX_CONFIG_FILE" ] || [ -f "$_curr/.rnex.yaml" ]; then
|
|
100
101
|
printf '%s' "$_curr"
|
|
101
102
|
return 0
|
|
102
103
|
fi
|
|
103
104
|
_curr="$(dirname "$_curr")"
|
|
104
105
|
done
|
|
105
|
-
if [ -f "/$RNEX_CONFIG_FILE" ]; then
|
|
106
|
+
if [ -f "/$RNEX_CONFIG_FILE" ] || [ -f "/.rnex.yaml" ]; then
|
|
106
107
|
printf '/'
|
|
107
108
|
return 0
|
|
108
109
|
fi
|
|
@@ -118,6 +119,7 @@ require_workspace() {
|
|
|
118
119
|
fi
|
|
119
120
|
NEXUS_DIR="$(cd -P "$(dirname "$_cfg_path")" 2>/dev/null && pwd -P)"
|
|
120
121
|
WORKSPACE_YAML="$_cfg_path"
|
|
122
|
+
_init_local_yaml
|
|
121
123
|
_load_repos_dir
|
|
122
124
|
log_info "Using workspace at ${_BOLD}$NEXUS_DIR${_NC} ${_DIM}(via config: $WORKSPACE_YAML)${_NC}"
|
|
123
125
|
return 0
|
|
@@ -136,16 +138,36 @@ require_workspace() {
|
|
|
136
138
|
fi
|
|
137
139
|
|
|
138
140
|
NEXUS_DIR="$_found_dir"
|
|
139
|
-
|
|
141
|
+
if [ -f "$NEXUS_DIR/$RNEX_CONFIG_FILE" ]; then
|
|
142
|
+
WORKSPACE_YAML="$NEXUS_DIR/$RNEX_CONFIG_FILE"
|
|
143
|
+
elif [ -f "$NEXUS_DIR/.rnex.yaml" ]; then
|
|
144
|
+
WORKSPACE_YAML="$NEXUS_DIR/.rnex.yaml"
|
|
145
|
+
else
|
|
146
|
+
WORKSPACE_YAML="$NEXUS_DIR/$RNEX_CONFIG_FILE"
|
|
147
|
+
fi
|
|
148
|
+
_init_local_yaml
|
|
140
149
|
_load_repos_dir
|
|
141
150
|
|
|
142
|
-
log_info "Using workspace at ${_BOLD}$NEXUS_DIR${_NC} ${_DIM}($
|
|
151
|
+
log_info "Using workspace at ${_BOLD}$NEXUS_DIR${_NC} ${_DIM}($(basename "$WORKSPACE_YAML") found)${_NC}"
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_init_local_yaml() {
|
|
155
|
+
if [ -f "$NEXUS_DIR/$RNEX_LOCAL_CONFIG_FILE" ]; then
|
|
156
|
+
WORKSPACE_LOCAL_YAML="$NEXUS_DIR/$RNEX_LOCAL_CONFIG_FILE"
|
|
157
|
+
elif [ -f "$NEXUS_DIR/.rnex.local.yaml" ]; then
|
|
158
|
+
WORKSPACE_LOCAL_YAML="$NEXUS_DIR/.rnex.local.yaml"
|
|
159
|
+
else
|
|
160
|
+
WORKSPACE_LOCAL_YAML="$NEXUS_DIR/$RNEX_LOCAL_CONFIG_FILE"
|
|
161
|
+
fi
|
|
143
162
|
}
|
|
144
163
|
|
|
145
|
-
# Parse repos_dir from config, default to ./repos
|
|
164
|
+
# Parse repos_dir from config, check local first then repo, default to ./repos
|
|
146
165
|
_load_repos_dir() {
|
|
147
166
|
_rd=""
|
|
148
|
-
if [ -f "$
|
|
167
|
+
if [ -f "$WORKSPACE_LOCAL_YAML" ]; then
|
|
168
|
+
_rd="$(awk '/^repos_dir:/ { sub(/^repos_dir:[ ]*/, ""); sub(/[ ]*#.*/, ""); print }' "$WORKSPACE_LOCAL_YAML")"
|
|
169
|
+
fi
|
|
170
|
+
if [ -z "$_rd" ] && [ -f "$WORKSPACE_YAML" ]; then
|
|
149
171
|
_rd="$(awk '/^repos_dir:/ { sub(/^repos_dir:[ ]*/, ""); sub(/[ ]*#.*/, ""); print }' "$WORKSPACE_YAML")"
|
|
150
172
|
fi
|
|
151
173
|
_rd="${_rd:-./repos}"
|
|
@@ -158,9 +180,10 @@ _load_repos_dir() {
|
|
|
158
180
|
# ---- YAML Parser / Manipulator (for rnex.yaml) ----------------------------
|
|
159
181
|
|
|
160
182
|
|
|
161
|
-
# Parse list of plugins from
|
|
162
|
-
|
|
163
|
-
|
|
183
|
+
# Parse list of plugins from a config file
|
|
184
|
+
_yaml_list_plugins_from_file() {
|
|
185
|
+
_f="$1"
|
|
186
|
+
[ -f "$_f" ] || return 0
|
|
164
187
|
awk '
|
|
165
188
|
/^plugins:[ ]*$/ || /^plugins:[ ]*#/ { p=1; next }
|
|
166
189
|
p && /^[^ #]/ { exit }
|
|
@@ -189,13 +212,21 @@ yaml_list_plugins() {
|
|
|
189
212
|
if (length(line) > 0) print line
|
|
190
213
|
next
|
|
191
214
|
}
|
|
192
|
-
' "$
|
|
215
|
+
' "$_f"
|
|
193
216
|
}
|
|
194
217
|
|
|
195
|
-
#
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
218
|
+
# Parse list of plugins merged from repo and local configs
|
|
219
|
+
yaml_list_plugins() {
|
|
220
|
+
{
|
|
221
|
+
_yaml_list_plugins_from_file "$WORKSPACE_YAML"
|
|
222
|
+
_yaml_list_plugins_from_file "$WORKSPACE_LOCAL_YAML"
|
|
223
|
+
} | awk '!seen[$0]++'
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
# Get a configuration field value for a plugin from a single file
|
|
227
|
+
_yaml_plugin_get_from_file() {
|
|
228
|
+
_f="$1"; _plugin="$2"; _field="$3"
|
|
229
|
+
[ -f "$_f" ] || return 0
|
|
199
230
|
awk -v plugin="$_plugin" -v field="$_field" '
|
|
200
231
|
/^plugins:[ ]*$/ || /^plugins:[ ]*#/ { in_plugins=1; next }
|
|
201
232
|
in_plugins && /^[^ #]/ { in_plugins=0 }
|
|
@@ -212,7 +243,53 @@ yaml_plugin_get() {
|
|
|
212
243
|
}
|
|
213
244
|
}
|
|
214
245
|
in_target && !/^ / && !/^[ ]*#/ { in_target=0 }
|
|
215
|
-
' "$
|
|
246
|
+
' "$_f"
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
# Get a configuration field value for a plugin (local overrides repo config)
|
|
250
|
+
yaml_plugin_get() {
|
|
251
|
+
_plugin="$1"; _field="$2"
|
|
252
|
+
_val="$(_yaml_plugin_get_from_file "$WORKSPACE_LOCAL_YAML" "$_plugin" "$_field")"
|
|
253
|
+
if [ -n "$_val" ]; then
|
|
254
|
+
printf '%s' "$_val"
|
|
255
|
+
return 0
|
|
256
|
+
fi
|
|
257
|
+
_yaml_plugin_get_from_file "$WORKSPACE_YAML" "$_plugin" "$_field"
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
# List all configuration fields for a plugin with their source annotation
|
|
261
|
+
yaml_plugin_list_config() {
|
|
262
|
+
_plugin="$1"
|
|
263
|
+
if [ -f "$WORKSPACE_LOCAL_YAML" ]; then
|
|
264
|
+
awk -v plugin="$_plugin" '
|
|
265
|
+
/^plugins:[ ]*$/ || /^plugins:[ ]*#/ { in_p=1; next }
|
|
266
|
+
in_p && /^[^ #]/ { in_p=0 }
|
|
267
|
+
in_p && match($0, "^ " plugin ":[ ]*") { in_target=1; next }
|
|
268
|
+
in_target && /^ [a-zA-Z0-9_.-]+:[ ]*/ {
|
|
269
|
+
line = $0
|
|
270
|
+
sub(/^[ ]*/, "", line)
|
|
271
|
+
sub(/[ ]*#.*$/, "", line)
|
|
272
|
+
print line " (from local config)"
|
|
273
|
+
next
|
|
274
|
+
}
|
|
275
|
+
in_target && !/^ / && !/^[ ]*#/ { in_target=0 }
|
|
276
|
+
' "$WORKSPACE_LOCAL_YAML"
|
|
277
|
+
fi
|
|
278
|
+
if [ -f "$WORKSPACE_YAML" ]; then
|
|
279
|
+
awk -v plugin="$_plugin" '
|
|
280
|
+
/^plugins:[ ]*$/ || /^plugins:[ ]*#/ { in_p=1; next }
|
|
281
|
+
in_p && /^[^ #]/ { in_p=0 }
|
|
282
|
+
in_p && match($0, "^ " plugin ":[ ]*") { in_target=1; next }
|
|
283
|
+
in_target && /^ [a-zA-Z0-9_.-]+:[ ]*/ {
|
|
284
|
+
line = $0
|
|
285
|
+
sub(/^[ ]*/, "", line)
|
|
286
|
+
sub(/[ ]*#.*$/, "", line)
|
|
287
|
+
print line
|
|
288
|
+
next
|
|
289
|
+
}
|
|
290
|
+
in_target && !/^ / && !/^[ ]*#/ { in_target=0 }
|
|
291
|
+
' "$WORKSPACE_YAML"
|
|
292
|
+
fi
|
|
216
293
|
}
|
|
217
294
|
|
|
218
295
|
yaml_has_plugin() {
|
|
@@ -226,31 +303,20 @@ yaml_enable_plugin() {
|
|
|
226
303
|
printf '\nplugins:\n' >> "$WORKSPACE_YAML"
|
|
227
304
|
fi
|
|
228
305
|
_tmp="$(mktemp)"
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
' "$WORKSPACE_YAML" > "$_tmp" && mv "$_tmp" "$WORKSPACE_YAML"
|
|
239
|
-
else
|
|
240
|
-
awk -v name="$_name" '
|
|
241
|
-
/^plugins:[ ]*$/ || /^plugins:[ ]*#/ {
|
|
242
|
-
print
|
|
243
|
-
printf " %s: {}\n", name
|
|
244
|
-
added=1
|
|
245
|
-
next
|
|
246
|
-
}
|
|
247
|
-
{ print }
|
|
248
|
-
' "$WORKSPACE_YAML" > "$_tmp" && mv "$_tmp" "$WORKSPACE_YAML"
|
|
249
|
-
fi
|
|
306
|
+
awk -v name="$_name" '
|
|
307
|
+
/^plugins:[ ]*$/ || /^plugins:[ ]*#/ {
|
|
308
|
+
print
|
|
309
|
+
printf " %s: {}\n", name
|
|
310
|
+
added=1
|
|
311
|
+
next
|
|
312
|
+
}
|
|
313
|
+
{ print }
|
|
314
|
+
' "$WORKSPACE_YAML" > "$_tmp" && mv "$_tmp" "$WORKSPACE_YAML"
|
|
250
315
|
}
|
|
251
316
|
|
|
252
|
-
|
|
253
|
-
|
|
317
|
+
_yaml_disable_plugin_in_file() {
|
|
318
|
+
_file="$1"; _name="$2"
|
|
319
|
+
[ -f "$_file" ] || return 0
|
|
254
320
|
_tmp="$(mktemp)"
|
|
255
321
|
awk -v name="$_name" '
|
|
256
322
|
/^plugins:[ ]*$/ || /^plugins:[ ]*#/ { in_plugins=1; print; next }
|
|
@@ -260,35 +326,85 @@ yaml_disable_plugin() {
|
|
|
260
326
|
in_target && !/^ / { in_target=0 }
|
|
261
327
|
in_plugins && $0 ~ ("^[ ]*-[ ]*" name "[ ]*($|#)") { next }
|
|
262
328
|
{ print }
|
|
263
|
-
' "$
|
|
329
|
+
' "$_file" > "$_tmp" && mv "$_tmp" "$_file"
|
|
264
330
|
}
|
|
265
331
|
|
|
332
|
+
yaml_disable_plugin() {
|
|
333
|
+
_name="$1"
|
|
334
|
+
_yaml_disable_plugin_in_file "$WORKSPACE_YAML" "$_name"
|
|
335
|
+
_yaml_disable_plugin_in_file "$WORKSPACE_LOCAL_YAML" "$_name"
|
|
336
|
+
}
|
|
266
337
|
|
|
267
|
-
# Parse list of repos from
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
338
|
+
# Parse list of repos from a single config file
|
|
339
|
+
_yaml_list_repos_from_file() {
|
|
340
|
+
_f="$1"
|
|
341
|
+
[ -f "$_f" ] || return 0
|
|
342
|
+
awk '
|
|
343
|
+
/^repos:[ ]*$/ || /^repos:[ ]*#/ { r=1; next }
|
|
272
344
|
r && /^[^ #]/ { exit }
|
|
273
|
-
r && /^ [a-zA-Z0-9_.-]+:[ ]
|
|
274
|
-
|
|
345
|
+
r && /^ [a-zA-Z0-9_.-]+:[ ]*(#.*)?$/ {
|
|
346
|
+
line = $0
|
|
347
|
+
sub(/^[ ]*/, "", line)
|
|
348
|
+
sub(/:.*/, "", line)
|
|
349
|
+
gsub(/[[:space:]]/, "", line)
|
|
350
|
+
if (length(line) > 0) print line
|
|
275
351
|
}
|
|
276
|
-
'
|
|
352
|
+
' "$_f"
|
|
277
353
|
}
|
|
278
354
|
|
|
279
|
-
#
|
|
355
|
+
# Parse list of repos merged from repo and local configs (order preserved, deduplicated)
|
|
356
|
+
yaml_list_repos() {
|
|
357
|
+
{
|
|
358
|
+
_yaml_list_repos_from_file "$WORKSPACE_YAML"
|
|
359
|
+
_yaml_list_repos_from_file "$WORKSPACE_LOCAL_YAML"
|
|
360
|
+
} | awk '!seen[$0]++'
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
# Get a field value for a repo from a specific config file
|
|
364
|
+
_yaml_get_from_file() {
|
|
365
|
+
_f="$1"; _repo="$2"; _field="$3"
|
|
366
|
+
[ -f "$_f" ] || return 0
|
|
367
|
+
awk -v repo="$_repo" -v field="$_field" '
|
|
368
|
+
/^repos:[ ]*$/ || /^repos:[ ]*#/ { r=1; next }
|
|
369
|
+
r && /^[^ #]/ { r=0 }
|
|
370
|
+
r && match($0, "^ " repo ":[ ]*(#.*)?$") { in_target=1; next }
|
|
371
|
+
in_target && /^ [^ #]/ { in_target=0 }
|
|
372
|
+
in_target && match($0, "^ " field ":[ ]*") {
|
|
373
|
+
line = $0
|
|
374
|
+
sub("^ " field ":[ ]*", "", line)
|
|
375
|
+
sub(/[ ]*#.*$/, "", line)
|
|
376
|
+
gsub(/^["\x27]|["\x27]$/, "", line)
|
|
377
|
+
print line
|
|
378
|
+
exit
|
|
379
|
+
}
|
|
380
|
+
' "$_f"
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
# Get a field value for a repo (local config overrides repo config)
|
|
280
384
|
yaml_get() {
|
|
281
385
|
_repo="$1"; _field="$2"
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
386
|
+
_val="$(_yaml_get_from_file "$WORKSPACE_LOCAL_YAML" "$_repo" "$_field")"
|
|
387
|
+
if [ -n "$_val" ]; then
|
|
388
|
+
printf '%s' "$_val"
|
|
389
|
+
return 0
|
|
390
|
+
fi
|
|
391
|
+
_yaml_get_from_file "$WORKSPACE_YAML" "$_repo" "$_field"
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
# Return where the repo path came from: "local", "repo", or "none"
|
|
395
|
+
yaml_repo_path_source() {
|
|
396
|
+
_repo="$1"
|
|
397
|
+
_lval="$(_yaml_get_from_file "$WORKSPACE_LOCAL_YAML" "$_repo" "path")"
|
|
398
|
+
if [ -n "$_lval" ]; then
|
|
399
|
+
printf 'local'
|
|
400
|
+
return 0
|
|
401
|
+
fi
|
|
402
|
+
_rval="$(_yaml_get_from_file "$WORKSPACE_YAML" "$_repo" "path")"
|
|
403
|
+
if [ -n "$_rval" ]; then
|
|
404
|
+
printf 'repo'
|
|
405
|
+
return 0
|
|
406
|
+
fi
|
|
407
|
+
printf 'none'
|
|
292
408
|
}
|
|
293
409
|
|
|
294
410
|
yaml_has_repo() {
|
|
@@ -297,7 +413,7 @@ yaml_has_repo() {
|
|
|
297
413
|
|
|
298
414
|
yaml_add_repo() {
|
|
299
415
|
_name="$1"; _path="$2"; _rnex_dir="${3:-true}"
|
|
300
|
-
if ! grep -q '^repos:' "$WORKSPACE_YAML"; then
|
|
416
|
+
if ! grep -q '^repos:' "$WORKSPACE_YAML" 2>/dev/null; then
|
|
301
417
|
printf '\nrepos:\n' >> "$WORKSPACE_YAML"
|
|
302
418
|
fi
|
|
303
419
|
_tmp="$(mktemp)"
|
|
@@ -312,8 +428,9 @@ yaml_add_repo() {
|
|
|
312
428
|
' "$WORKSPACE_YAML" > "$_tmp" && mv "$_tmp" "$WORKSPACE_YAML"
|
|
313
429
|
}
|
|
314
430
|
|
|
315
|
-
|
|
316
|
-
|
|
431
|
+
_yaml_remove_repo_from_file() {
|
|
432
|
+
_file="$1"; _name="$2"
|
|
433
|
+
[ -f "$_file" ] || return 0
|
|
317
434
|
_tmp="$(mktemp)"
|
|
318
435
|
awk -v name="$_name" '
|
|
319
436
|
/^repos:/ { r=1; print; next }
|
|
@@ -322,11 +439,48 @@ yaml_remove_repo() {
|
|
|
322
439
|
r && skip && /^ [^ #]/ { skip=0 }
|
|
323
440
|
skip && /^ / { next }
|
|
324
441
|
{ print }
|
|
325
|
-
' "$
|
|
442
|
+
' "$_file" > "$_tmp" && mv "$_tmp" "$_file"
|
|
326
443
|
}
|
|
327
444
|
|
|
328
|
-
|
|
329
|
-
|
|
445
|
+
yaml_remove_repo() {
|
|
446
|
+
_name="$1"
|
|
447
|
+
_yaml_remove_repo_from_file "$WORKSPACE_YAML" "$_name"
|
|
448
|
+
_yaml_remove_repo_from_file "$WORKSPACE_LOCAL_YAML" "$_name"
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
_yaml_set_in_file() {
|
|
452
|
+
_file="$1"; _repo="$2"; _field="$3"; _value="$4"
|
|
453
|
+
if [ ! -f "$_file" ]; then
|
|
454
|
+
mkdir -p "$(dirname "$_file")"
|
|
455
|
+
printf 'repos:\n' > "$_file"
|
|
456
|
+
elif ! grep -q '^repos:' "$_file" 2>/dev/null; then
|
|
457
|
+
printf '\nrepos:\n' >> "$_file"
|
|
458
|
+
fi
|
|
459
|
+
|
|
460
|
+
if ! awk -v repo="$_repo" '
|
|
461
|
+
/^repos:[ ]*$/ || /^repos:[ ]*#/ { in_r=1; next }
|
|
462
|
+
in_r && /^[^ #]/ { in_r=0 }
|
|
463
|
+
in_r && match($0, "^ " repo ":[ ]*(#.*)?$") { found=1; exit }
|
|
464
|
+
END { exit !found }
|
|
465
|
+
' "$_file" 2>/dev/null; then
|
|
466
|
+
_tmp="$(mktemp)"
|
|
467
|
+
awk -v repo="$_repo" -v field="$_field" -v value="$_value" '
|
|
468
|
+
/^repos:[ ]*$/ || /^repos:[ ]*#/ {
|
|
469
|
+
print
|
|
470
|
+
printf " %s:\n %s: %s\n", repo, field, value
|
|
471
|
+
added=1
|
|
472
|
+
next
|
|
473
|
+
}
|
|
474
|
+
{ print }
|
|
475
|
+
END {
|
|
476
|
+
if (!added) {
|
|
477
|
+
printf "repos:\n %s:\n %s: %s\n", repo, field, value
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
' "$_file" > "$_tmp" && mv "$_tmp" "$_file"
|
|
481
|
+
return 0
|
|
482
|
+
fi
|
|
483
|
+
|
|
330
484
|
_tmp="$(mktemp)"
|
|
331
485
|
awk -v repo="$_repo" -v field="$_field" -v value="$_value" '
|
|
332
486
|
/^repos:/ { in_repos=1; print; next }
|
|
@@ -337,11 +491,7 @@ yaml_set() {
|
|
|
337
491
|
}
|
|
338
492
|
in_repos=0; in_target=0
|
|
339
493
|
}
|
|
340
|
-
in_repos && match($0, "^ " repo ":[ ]
|
|
341
|
-
if (in_target && !field_set) {
|
|
342
|
-
printf " %s: %s\n", field, value
|
|
343
|
-
field_set=1
|
|
344
|
-
}
|
|
494
|
+
in_repos && match($0, "^ " repo ":[ ]*(#.*)?$") {
|
|
345
495
|
in_target=1; print; next
|
|
346
496
|
}
|
|
347
497
|
in_target && /^ [^ #]/ {
|
|
@@ -362,7 +512,28 @@ yaml_set() {
|
|
|
362
512
|
printf " %s: %s\n", field, value
|
|
363
513
|
}
|
|
364
514
|
}
|
|
365
|
-
' "$
|
|
515
|
+
' "$_file" > "$_tmp" && mv "$_tmp" "$_file"
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
yaml_set() {
|
|
519
|
+
_repo="$1"; _field="$2"; _value="$3"
|
|
520
|
+
_yaml_set_in_file "$WORKSPACE_YAML" "$_repo" "$_field" "$_value"
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
yaml_set_local() {
|
|
524
|
+
_repo="$1"; _field="$2"; _value="$3"
|
|
525
|
+
if [ ! -f "$WORKSPACE_LOCAL_YAML" ]; then
|
|
526
|
+
cat <<'EOF' > "$WORKSPACE_LOCAL_YAML"
|
|
527
|
+
# ==============================================================================
|
|
528
|
+
# .local.rnex.yaml — Repo Nexus Local Configuration (Machine-Specific)
|
|
529
|
+
# ==============================================================================
|
|
530
|
+
# This file is gitignored. Use it to specify local repository paths and
|
|
531
|
+
# custom local plugin overrides for this workstation.
|
|
532
|
+
|
|
533
|
+
repos:
|
|
534
|
+
EOF
|
|
535
|
+
fi
|
|
536
|
+
_yaml_set_in_file "$WORKSPACE_LOCAL_YAML" "$_repo" "$_field" "$_value"
|
|
366
537
|
}
|
|
367
538
|
|
|
368
539
|
# ---- Symlink & Member Repo Operations -------------------------------------
|
|
@@ -629,16 +800,6 @@ sync_plugins() {
|
|
|
629
800
|
log_ok "Initialized template: $_d"
|
|
630
801
|
fi
|
|
631
802
|
done
|
|
632
|
-
|
|
633
|
-
# Reconcile plugin configuration (e.g., lint_trigger_enabled for karpathy-llm)
|
|
634
|
-
if [ "$_pname" = "karpathy-llm" ] && [ -f "$NEXUS_DIR/wiki/index.md" ]; then
|
|
635
|
-
_lte="$(yaml_plugin_get "karpathy-llm" "lint_trigger_enabled")"
|
|
636
|
-
if [ "$_lte" = "false" ]; then
|
|
637
|
-
sed -i.bak 's/lint_trigger:[ ]*enabled/lint_trigger: disabled/' "$NEXUS_DIR/wiki/index.md" 2>/dev/null && rm -f "$NEXUS_DIR/wiki/index.md.bak"
|
|
638
|
-
elif [ "$_lte" = "true" ]; then
|
|
639
|
-
sed -i.bak 's/lint_trigger:[ ]*disabled/lint_trigger: enabled/' "$NEXUS_DIR/wiki/index.md" 2>/dev/null && rm -f "$NEXUS_DIR/wiki/index.md.bak"
|
|
640
|
-
fi
|
|
641
|
-
fi
|
|
642
803
|
done
|
|
643
804
|
}
|
|
644
805
|
|
|
@@ -791,6 +952,12 @@ YAML_EOF
|
|
|
791
952
|
mkdir -p "$_target_dir/.rnex/rules"
|
|
792
953
|
mkdir -p "$_target_dir/.rnex/instructions"
|
|
793
954
|
|
|
955
|
+
# ---- Ensure local config is gitignored -----------------------------------
|
|
956
|
+
_target_gi="$_target_dir/.gitignore"
|
|
957
|
+
if [ ! -f "$_target_gi" ] || ! grep -qF "$RNEX_LOCAL_CONFIG_FILE" "$_target_gi" 2>/dev/null; then
|
|
958
|
+
printf '\n# Local machine-specific configuration\n%s\n.rnex.local.yaml\n' "$RNEX_LOCAL_CONFIG_FILE" >> "$_target_gi"
|
|
959
|
+
fi
|
|
960
|
+
|
|
794
961
|
if [ "$_config_created" -eq 1 ]; then
|
|
795
962
|
printf '\n'
|
|
796
963
|
log_ok "Initialized Repo Nexus workspace at ${_BOLD}$_target_dir${_NC}"
|
|
@@ -808,9 +975,11 @@ cmd_add() {
|
|
|
808
975
|
_name=""
|
|
809
976
|
_path=""
|
|
810
977
|
_rnex_dir="true"
|
|
978
|
+
_is_local=0
|
|
811
979
|
|
|
812
980
|
while [ $# -gt 0 ]; do
|
|
813
981
|
case "$1" in
|
|
982
|
+
--local) _is_local=1 ;;
|
|
814
983
|
--no-rnex-dir|--rnex-dir=false) _rnex_dir="false" ;;
|
|
815
984
|
--rnex-dir|--rnex-dir=true) _rnex_dir="true" ;;
|
|
816
985
|
-y|--yes) _assume="y" ;;
|
|
@@ -828,15 +997,39 @@ cmd_add() {
|
|
|
828
997
|
shift
|
|
829
998
|
done
|
|
830
999
|
|
|
831
|
-
[ -n "$_name" ] || die "Usage: rnex add [--no-rnex-dir] <name> <path>"
|
|
832
|
-
[ -n "$_path" ] || die "Usage: rnex add [--no-rnex-dir] <name> <path>"
|
|
833
|
-
|
|
834
|
-
yaml_has_repo "$_name" && die "Repo '$_name' is already registered in $RNEX_CONFIG_FILE"
|
|
1000
|
+
[ -n "$_name" ] || die "Usage: rnex add [--local] [--no-rnex-dir] <name> <path>"
|
|
1001
|
+
[ -n "$_path" ] || die "Usage: rnex add [--local] [--no-rnex-dir] <name> <path>"
|
|
835
1002
|
|
|
836
1003
|
_path="$(resolve_path "$_path")"
|
|
837
1004
|
[ -d "$_path" ] || die "Directory does not exist: $_path"
|
|
838
1005
|
|
|
839
1006
|
ensure_repos_dir
|
|
1007
|
+
|
|
1008
|
+
if [ "$_is_local" -eq 1 ]; then
|
|
1009
|
+
yaml_set_local "$_name" "path" "$_path"
|
|
1010
|
+
[ "$_rnex_dir" = "false" ] && yaml_set_local "$_name" "rnex_dir" "false"
|
|
1011
|
+
create_scope_link "$_name"
|
|
1012
|
+
sync_repo_rnex "$_name"
|
|
1013
|
+
printf '\n'
|
|
1014
|
+
log_ok "Registered local path for repo '${_name}' in $(basename "$WORKSPACE_LOCAL_YAML")"
|
|
1015
|
+
return 0
|
|
1016
|
+
fi
|
|
1017
|
+
|
|
1018
|
+
if grep -q "^ $_name:" "$WORKSPACE_YAML" 2>/dev/null; then
|
|
1019
|
+
_existing_path="$(_yaml_get_from_file "$WORKSPACE_YAML" "$_name" "path")"
|
|
1020
|
+
if [ -n "$_existing_path" ]; then
|
|
1021
|
+
die "Repo '$_name' is already registered in $(basename "$WORKSPACE_YAML")"
|
|
1022
|
+
else
|
|
1023
|
+
yaml_set "$_name" "path" "$_path"
|
|
1024
|
+
[ "$_rnex_dir" = "false" ] && yaml_set "$_name" "rnex_dir" "false"
|
|
1025
|
+
create_scope_link "$_name"
|
|
1026
|
+
sync_repo_rnex "$_name"
|
|
1027
|
+
printf '\n'
|
|
1028
|
+
log_ok "Updated repo '${_name}' path in $(basename "$WORKSPACE_YAML")"
|
|
1029
|
+
return 0
|
|
1030
|
+
fi
|
|
1031
|
+
fi
|
|
1032
|
+
|
|
840
1033
|
yaml_add_repo "$_name" "$_path" "$_rnex_dir"
|
|
841
1034
|
create_scope_link "$_name"
|
|
842
1035
|
sync_repo_rnex "$_name"
|
|
@@ -879,18 +1072,20 @@ cmd_hide() {
|
|
|
879
1072
|
|
|
880
1073
|
cmd_list() {
|
|
881
1074
|
require_workspace
|
|
882
|
-
printf '%b%-22s %-10s %-12s %s%b\n' "$_B" "NAME" "SCOPE" "RNEX_DIR" "PATH" "$_NC"
|
|
883
|
-
printf '%-22s %-10s %-12s %s\n' "----" "-----" "--------" "----"
|
|
1075
|
+
printf '%b%-22s %-10s %-12s %-8s %s%b\n' "$_B" "NAME" "SCOPE" "RNEX_DIR" "CONFIG" "PATH" "$_NC"
|
|
1076
|
+
printf '%-22s %-10s %-12s %-8s %s\n' "----" "-----" "--------" "------" "----"
|
|
884
1077
|
yaml_list_repos | while read -r _name; do
|
|
1078
|
+
[ -n "$_name" ] || continue
|
|
885
1079
|
_scope="$(yaml_get "$_name" "scope")"
|
|
886
1080
|
_path="$(yaml_get "$_name" "path")"
|
|
1081
|
+
_src="$(yaml_repo_path_source "$_name")"
|
|
887
1082
|
if repo_rnex_dir_enabled "$_name"; then
|
|
888
1083
|
_rd_str="enabled"
|
|
889
1084
|
else
|
|
890
1085
|
_rd_str="disabled"
|
|
891
1086
|
fi
|
|
892
|
-
printf '%-22s %-10s %-12s %s\n' \
|
|
893
|
-
"$_name" "${_scope:-visible}" "$_rd_str" "$_path"
|
|
1087
|
+
printf '%-22s %-10s %-12s %-8s %s\n' \
|
|
1088
|
+
"$_name" "${_scope:-visible}" "$_rd_str" "${_src:-repo}" "${_path:-(not set)}"
|
|
894
1089
|
done
|
|
895
1090
|
}
|
|
896
1091
|
|
|
@@ -902,6 +1097,20 @@ cmd_status() {
|
|
|
902
1097
|
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
|
|
903
1098
|
printf '\n\n'
|
|
904
1099
|
|
|
1100
|
+
printf '%bConfiguration:%b\n' "$_BOLD" "$_NC"
|
|
1101
|
+
if [ -f "$WORKSPACE_YAML" ]; then
|
|
1102
|
+
printf ' %b●%b Repo Config: %s %b(loaded)%b\n' "$_G" "$_NC" "$WORKSPACE_YAML" "$_DIM" "$_NC"
|
|
1103
|
+
else
|
|
1104
|
+
printf ' %b✗%b Repo Config: %s %b(missing)%b\n' "$_R" "$_NC" "$WORKSPACE_YAML" "$_R" "$_NC"
|
|
1105
|
+
fi
|
|
1106
|
+
if [ -f "$WORKSPACE_LOCAL_YAML" ]; then
|
|
1107
|
+
printf ' %b●%b Local Config: %s %b(loaded, overrides repo config)%b\n' "$_G" "$_NC" "$WORKSPACE_LOCAL_YAML" "$_DIM" "$_NC"
|
|
1108
|
+
else
|
|
1109
|
+
printf ' %b○%b Local Config: %s %b(not found — using repo defaults)%b\n' "$_DIM" "$_NC" "$WORKSPACE_LOCAL_YAML" "$_DIM" "$_NC"
|
|
1110
|
+
fi
|
|
1111
|
+
printf ' %b●%b Repos Dir: %s\n' "$_DIM" "$_NC" "$REPOS_DIR"
|
|
1112
|
+
printf '\n'
|
|
1113
|
+
|
|
905
1114
|
printf '%bWorkspace AI Context:%b\n' "$_BOLD" "$_NC"
|
|
906
1115
|
if [ -e "$NEXUS_DIR/AGENTS.md" ]; then
|
|
907
1116
|
printf ' %b✓%b %s\n' "$_G" "$_NC" "AGENTS.md"
|
|
@@ -925,26 +1134,45 @@ cmd_status() {
|
|
|
925
1134
|
_ver="$(plugin_get_field "$_pdir" "version")"
|
|
926
1135
|
_desc="$(plugin_get_field "$_pdir" "description")"
|
|
927
1136
|
printf ' %b●%b %-18s %b(v%s)%b %s\n' "$_G" "$_NC" "$_pname" "$_DIM" "${_ver:-0.1.0}" "$_NC" "${_desc:+- $_desc}"
|
|
1137
|
+
_pcfg="$(yaml_plugin_list_config "$_pname")"
|
|
1138
|
+
if [ -n "$_pcfg" ]; then
|
|
1139
|
+
printf ' %bConfiguration:%b\n' "$_DIM" "$_NC"
|
|
1140
|
+
echo "$_pcfg" | while read -r _line; do
|
|
1141
|
+
[ -n "$_line" ] && printf ' %b- %s%b\n' "$_DIM" "$_line" "$_NC"
|
|
1142
|
+
done
|
|
1143
|
+
else
|
|
1144
|
+
printf ' %bConfiguration: (default)%b\n' "$_DIM" "$_NC"
|
|
1145
|
+
fi
|
|
928
1146
|
else
|
|
929
1147
|
printf ' %b✗%b %-18s %bMISSING%b\n' "$_R" "$_NC" "$_pname" "$_R" "$_NC"
|
|
1148
|
+
printf ' %b↳ [!] Issue: plugin declared in config but directory not found on disk%b\n' "$_R" "$_NC"
|
|
930
1149
|
fi
|
|
931
1150
|
done
|
|
932
1151
|
fi
|
|
933
1152
|
printf '\n'
|
|
934
1153
|
|
|
935
1154
|
printf '%b%s%b\n' "$_BOLD" "Member Repositories:" "$_NC"
|
|
936
|
-
|
|
1155
|
+
_all_repos="$(yaml_list_repos)"
|
|
1156
|
+
if [ -z "$_all_repos" ]; then
|
|
937
1157
|
printf ' %b%s%b\n' "$_DIM" "(No repositories registered yet. Use 'rnex add <name> <path>')" "$_NC"
|
|
938
1158
|
else
|
|
939
|
-
|
|
1159
|
+
echo "$_all_repos" | while read -r _name; do
|
|
1160
|
+
[ -n "$_name" ] || continue
|
|
940
1161
|
_scope="$(yaml_get "$_name" "scope")"
|
|
941
1162
|
_path="$(yaml_get "$_name" "path")"
|
|
1163
|
+
_src="$(yaml_repo_path_source "$_name")"
|
|
1164
|
+
_src_tag=""
|
|
1165
|
+
if [ "$_src" = "local" ]; then
|
|
1166
|
+
_src_tag=" ${_DIM}(via $(basename "$WORKSPACE_LOCAL_YAML"))${_NC}"
|
|
1167
|
+
elif [ "$_src" = "repo" ]; then
|
|
1168
|
+
_src_tag=" ${_DIM}(via $(basename "$WORKSPACE_YAML"))${_NC}"
|
|
1169
|
+
fi
|
|
1170
|
+
|
|
942
1171
|
_link="$REPOS_DIR/$_name"
|
|
943
|
-
_resolved_path="$(resolve_repo_path "$_path")"
|
|
944
1172
|
|
|
945
1173
|
_rnex_tag=""
|
|
946
1174
|
if repo_rnex_dir_enabled "$_name"; then
|
|
947
|
-
if [ -d "$
|
|
1175
|
+
if [ -n "$_path" ] && [ -d "$(resolve_repo_path "$_path")/.rnex" ]; then
|
|
948
1176
|
_rnex_tag=" ${_DIM}[.rnex ✓]${_NC}"
|
|
949
1177
|
else
|
|
950
1178
|
_rnex_tag=" ${_Y}[.rnex pending]${_NC}"
|
|
@@ -953,32 +1181,94 @@ cmd_status() {
|
|
|
953
1181
|
_rnex_tag=" ${_DIM}[.rnex disabled]${_NC}"
|
|
954
1182
|
fi
|
|
955
1183
|
|
|
1184
|
+
if [ -z "$_path" ]; then
|
|
1185
|
+
printf ' %b✗%b %-22s %bMISSING PATH%b%b\n' "$_R" "$_NC" "$_name" "$_R" "$_NC" "$_rnex_tag"
|
|
1186
|
+
printf ' %b↳ Suggestion: set path in %s or run '\''rnex add %s <path> --local'\''%b\n' \
|
|
1187
|
+
"$_Y" "$(basename "$WORKSPACE_LOCAL_YAML")" "$_name" "$_NC"
|
|
1188
|
+
continue
|
|
1189
|
+
fi
|
|
1190
|
+
|
|
1191
|
+
_resolved_path="$(resolve_repo_path "$_path")"
|
|
1192
|
+
|
|
1193
|
+
if [ ! -d "$_resolved_path" ]; then
|
|
1194
|
+
printf ' %b✗%b %-22s %bBROKEN PATH%b%b → %s%b\n' "$_R" "$_NC" "$_name" "$_R" "$_NC" "$_rnex_tag" "$_path" "$_src_tag"
|
|
1195
|
+
printf ' %b↳ Suggestion: update path in %s or run '\''rnex add %s <path> --local'\''%b\n' \
|
|
1196
|
+
"$_Y" "$(basename "$WORKSPACE_LOCAL_YAML")" "$_name" "$_NC"
|
|
1197
|
+
continue
|
|
1198
|
+
fi
|
|
1199
|
+
|
|
956
1200
|
if [ "$_scope" = "hidden" ]; then
|
|
957
|
-
printf ' %b○%b %-22s %bhidden%b%b\n' "$_Y" "$_NC" "$_name" "$_DIM" "$_NC" "$_rnex_tag"
|
|
1201
|
+
printf ' %b○%b %-22s %bhidden%b%b → %s%b\n' "$_Y" "$_NC" "$_name" "$_DIM" "$_NC" "$_rnex_tag" "$_path" "$_src_tag"
|
|
958
1202
|
elif [ -L "$_link" ] && [ -d "$_link" ]; then
|
|
959
|
-
printf ' %b●%b %-22s %bactive%b%b → %s\n' "$_G" "$_NC" "$_name" "$_G" "$_NC" "$_rnex_tag" "$_path"
|
|
1203
|
+
printf ' %b●%b %-22s %bactive%b%b → %s%b\n' "$_G" "$_NC" "$_name" "$_G" "$_NC" "$_rnex_tag" "$_path" "$_src_tag"
|
|
960
1204
|
elif [ -L "$_link" ]; then
|
|
961
|
-
printf ' %b✗%b %-22s %bBROKEN LINK%b%b → %s\n' "$_R" "$_NC" "$_name" "$_R" "$_NC" "$_rnex_tag" "$_path"
|
|
1205
|
+
printf ' %b✗%b %-22s %bBROKEN LINK%b%b → %s%b\n' "$_R" "$_NC" "$_name" "$_R" "$_NC" "$_rnex_tag" "$_path" "$_src_tag"
|
|
1206
|
+
printf ' %b↳ Suggestion: run '\''rnex sync'\'' to recreate scope link%b\n' "$_Y" "$_NC"
|
|
962
1207
|
else
|
|
963
|
-
printf ' %b✗%b %-22s %bMISSING LINK%b%b %s\n' "$_R" "$_NC" "$_name" "$_R" "$_NC" "$_rnex_tag" "
|
|
1208
|
+
printf ' %b✗%b %-22s %bMISSING LINK%b%b → %s%b\n' "$_R" "$_NC" "$_name" "$_R" "$_NC" "$_rnex_tag" "$_path" "$_src_tag"
|
|
1209
|
+
printf ' %b↳ Suggestion: run '\''rnex sync'\'' to create scope link%b\n' "$_Y" "$_NC"
|
|
964
1210
|
fi
|
|
965
1211
|
done
|
|
966
1212
|
fi
|
|
967
1213
|
|
|
968
1214
|
printf '\n%bWorkspace: %s%b\n' "$_DIM" "$NEXUS_DIR" "$_NC"
|
|
969
1215
|
printf '%bRepos Dir: %s%b\n' "$_DIM" "$REPOS_DIR" "$_NC"
|
|
970
|
-
printf '%
|
|
1216
|
+
printf '%bRepo Config: %s%b\n' "$_DIM" "$WORKSPACE_YAML" "$_NC"
|
|
1217
|
+
[ -f "$WORKSPACE_LOCAL_YAML" ] && printf '%bLocal Config:%s%b\n' "$_DIM" " $WORKSPACE_LOCAL_YAML" "$_NC"
|
|
1218
|
+
printf '\n'
|
|
971
1219
|
}
|
|
972
1220
|
|
|
973
1221
|
cmd_sync() {
|
|
974
1222
|
require_workspace
|
|
975
1223
|
ensure_repos_dir
|
|
976
1224
|
|
|
977
|
-
log_info "Synchronizing workspace from $
|
|
1225
|
+
log_info "Synchronizing workspace from $(basename "$WORKSPACE_YAML")..."
|
|
978
1226
|
sync_plugins
|
|
1227
|
+
|
|
979
1228
|
yaml_list_repos | while read -r _name; do
|
|
1229
|
+
[ -n "$_name" ] || continue
|
|
1230
|
+
_raw_path="$(yaml_get "$_name" "path")"
|
|
980
1231
|
_scope="$(yaml_get "$_name" "scope")"
|
|
981
1232
|
|
|
1233
|
+
if [ -z "$_raw_path" ]; then
|
|
1234
|
+
log_warn "Member repo '${_BOLD}$_name${_NC}' has NO path configured in $(basename "$WORKSPACE_YAML") or $(basename "$WORKSPACE_LOCAL_YAML")"
|
|
1235
|
+
_prompted_path=""
|
|
1236
|
+
if [ -t 0 ] && [ -t 1 ]; then
|
|
1237
|
+
printf '%b Enter local path for member repo %s%b (or press Enter to skip): ' "$_BOLD" "$_name" "$_NC"
|
|
1238
|
+
read -r _prompted_path || true
|
|
1239
|
+
fi
|
|
1240
|
+
if [ -n "$_prompted_path" ]; then
|
|
1241
|
+
_p_res="$(resolve_path "$_prompted_path")"
|
|
1242
|
+
if [ -d "$_p_res" ]; then
|
|
1243
|
+
yaml_set_local "$_name" "path" "$_prompted_path"
|
|
1244
|
+
log_ok "Saved local path for '$_name' to $(basename "$WORKSPACE_LOCAL_YAML")"
|
|
1245
|
+
_raw_path="$_prompted_path"
|
|
1246
|
+
else
|
|
1247
|
+
log_err "Directory does not exist: $_p_res"
|
|
1248
|
+
fi
|
|
1249
|
+
fi
|
|
1250
|
+
if [ -z "$_raw_path" ]; then
|
|
1251
|
+
log_dim "To provide your local path for '$_name', configure $(basename "$WORKSPACE_LOCAL_YAML"):"
|
|
1252
|
+
log_dim " repos:"
|
|
1253
|
+
log_dim " $_name:"
|
|
1254
|
+
log_dim " path: /path/to/$_name"
|
|
1255
|
+
log_dim "Or run: rnex add $_name /path/to/$_name --local"
|
|
1256
|
+
continue
|
|
1257
|
+
fi
|
|
1258
|
+
fi
|
|
1259
|
+
|
|
1260
|
+
_resolved_path="$(resolve_repo_path "$_raw_path")"
|
|
1261
|
+
if [ ! -d "$_resolved_path" ]; then
|
|
1262
|
+
log_warn "Member repo '${_BOLD}$_name${_NC}' path does not exist on disk: $_resolved_path"
|
|
1263
|
+
log_dim "To fix this path locally on your machine, configure $(basename "$WORKSPACE_LOCAL_YAML"):"
|
|
1264
|
+
log_dim " repos:"
|
|
1265
|
+
log_dim " $_name:"
|
|
1266
|
+
log_dim " path: /path/to/$_name"
|
|
1267
|
+
log_dim "Or run: rnex add $_name /correct/path/to/$_name --local"
|
|
1268
|
+
remove_scope_link "$_name" 2>/dev/null || true
|
|
1269
|
+
continue
|
|
1270
|
+
fi
|
|
1271
|
+
|
|
982
1272
|
if [ "$_scope" = "hidden" ]; then
|
|
983
1273
|
remove_scope_link "$_name"
|
|
984
1274
|
else
|
|
@@ -1048,9 +1338,12 @@ cmd_plugin_info() {
|
|
|
1048
1338
|
[ -n "$_home" ] && printf '%bHomepage:%b %s\n' "$_BOLD" "$_NC" "$_home"
|
|
1049
1339
|
printf '%bLocation:%b %s\n' "$_BOLD" "$_NC" "$_pdir"
|
|
1050
1340
|
if yaml_has_plugin "$_name"; then
|
|
1051
|
-
|
|
1052
|
-
if [ -n "$
|
|
1053
|
-
printf '%bConfiguration:%b
|
|
1341
|
+
_cfg="$(yaml_plugin_list_config "$_name")"
|
|
1342
|
+
if [ -n "$_cfg" ]; then
|
|
1343
|
+
printf '%bConfiguration:%b\n' "$_BOLD" "$_NC"
|
|
1344
|
+
echo "$_cfg" | while read -r _cline; do
|
|
1345
|
+
[ -n "$_cline" ] && printf ' %s\n' "$_cline"
|
|
1346
|
+
done
|
|
1054
1347
|
fi
|
|
1055
1348
|
fi
|
|
1056
1349
|
|
|
@@ -1099,7 +1392,7 @@ cmd_plugin_enable() {
|
|
|
1099
1392
|
[ -n "$_name" ] || _name="$_pname"
|
|
1100
1393
|
|
|
1101
1394
|
yaml_enable_plugin "$_name"
|
|
1102
|
-
log_ok "Plugin '$_name' enabled in $
|
|
1395
|
+
log_ok "Plugin '$_name' enabled in $(basename "$WORKSPACE_YAML")"
|
|
1103
1396
|
|
|
1104
1397
|
# Link rules and workflows into workspace root
|
|
1105
1398
|
plugin_list_rules "$_pdir" | while read -r _item; do
|
|
@@ -1137,13 +1430,11 @@ cmd_plugin_enable() {
|
|
|
1137
1430
|
fi
|
|
1138
1431
|
done
|
|
1139
1432
|
|
|
1140
|
-
# Ensure machine-
|
|
1433
|
+
# Ensure local machine-specific config is gitignored
|
|
1141
1434
|
_gi="$NEXUS_DIR/.gitignore"
|
|
1142
|
-
if [ -f "$
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
log_dim "Added '.rnex/.lint_trigger_counter' to .gitignore"
|
|
1146
|
-
fi
|
|
1435
|
+
if [ ! -f "$_gi" ] || ! grep -qF "$RNEX_LOCAL_CONFIG_FILE" "$_gi" 2>/dev/null; then
|
|
1436
|
+
printf '\n# Local machine-specific configuration\n%s\n.rnex.local.yaml\n' "$RNEX_LOCAL_CONFIG_FILE" >> "$_gi"
|
|
1437
|
+
log_dim "Added '$RNEX_LOCAL_CONFIG_FILE' to .gitignore"
|
|
1147
1438
|
fi
|
|
1148
1439
|
|
|
1149
1440
|
cmd_sync
|
|
@@ -1321,7 +1612,7 @@ cmd_help() {
|
|
|
1321
1612
|
sync Reconcile scope links, plugins & member .rnex/ directories
|
|
1322
1613
|
|
|
1323
1614
|
REPO MANAGEMENT
|
|
1324
|
-
add [--no-rnex-dir] <name> <path> Register
|
|
1615
|
+
add [--local] [--no-rnex-dir] <name> <path> Register member repo (--local writes to .local.rnex.yaml)
|
|
1325
1616
|
remove <name> Unregister repo and unlink scope
|
|
1326
1617
|
list List all registered member repos with scope & .rnex status
|
|
1327
1618
|
status Inspect workspace health, active repos, and plugins
|
|
@@ -1340,7 +1631,8 @@ cmd_help() {
|
|
|
1340
1631
|
EXAMPLES
|
|
1341
1632
|
rnex init # Initialize workspace in current folder
|
|
1342
1633
|
rnex install # Install rnex CLI globally to ~/.local/bin
|
|
1343
|
-
rnex add my-app ~/code/my-app # Register repo
|
|
1634
|
+
rnex add my-app ~/code/my-app # Register repo in rnex.yaml (team-visible)
|
|
1635
|
+
rnex add my-app ~/code/my-app --local # Register local path in .local.rnex.yaml
|
|
1344
1636
|
rnex add --no-rnex-dir my-app ~/code/my-app # Register repo with .rnex/ disabled
|
|
1345
1637
|
rnex rnex-dir disable my-app # Disable .rnex directory for a repo
|
|
1346
1638
|
rnex rnex-dir enable my-app # Re-enable .rnex directory for a repo
|
|
@@ -1349,7 +1641,7 @@ cmd_help() {
|
|
|
1349
1641
|
rnex plugin enable karpathy-llm # Enable Karpathy LLM plugin
|
|
1350
1642
|
rnex hide my-app # Temporarily hide from active indexing
|
|
1351
1643
|
rnex show my-app # Bring back into active scope
|
|
1352
|
-
rnex sync # Reconcile all links from
|
|
1644
|
+
rnex sync # Reconcile all links from config
|
|
1353
1645
|
|
|
1354
1646
|
EOF
|
|
1355
1647
|
}
|
|
@@ -22,16 +22,11 @@ Reference specification: [setup-karpathy-wiki.md](https://github.com/nu-nenoi/ai
|
|
|
22
22
|
### 3. Complete Karpathy LLM Wiki Architecture
|
|
23
23
|
* **`/raw/` Intake Directory:** Append-only directory where unmodified source material (articles, transcripts, docs, meeting notes) is deposited. Includes `.gitkeep`.
|
|
24
24
|
* **`/wiki/` Curated Knowledge Base:** Interlinked atomic markdown pages, each with typed frontmatter relations (`sources`, `related`, `extends`, `contradicts`, `mentioned_in`).
|
|
25
|
-
* **`/wiki/index.md`
|
|
25
|
+
* **`/wiki/index.md` Navigation Index:** Master categorized catalog organizing atomic concepts, architecture decisions, and cross-project knowledge.
|
|
26
26
|
* **`/wiki/hot.md` Rolling Context Cache:** High-density ~500-word orientation summary for rapid agent onboarding without full wiki scans (especially for codebase knowledge and second-brain wikis).
|
|
27
27
|
* **`/wiki/_log.md` Audit Trail:** Append-only log recording every ingest and lint operation with timestamped details.
|
|
28
|
-
* **`/wiki/.lint_trigger_counter` Session Counter:** Machine-local state tracking session activity (ignored in `.gitignore`).
|
|
29
28
|
|
|
30
|
-
### 4.
|
|
31
|
-
* Lightweight POSIX script checking `lint_trigger: enabled` and incrementing `wiki/.lint_trigger_counter`.
|
|
32
|
-
* Alerts agents with `[WIKI MAINTENANCE DUE]: Pending /raw/ files or wiki health checks detected. Run wiki-lint.` on session 1 and every 15 sessions.
|
|
33
|
-
|
|
34
|
-
### 5. Standardized Agent Workflows (`workflows/`)
|
|
29
|
+
### 4. Standardized Agent Workflows (`workflows/`)
|
|
35
30
|
* **`wiki-ingest.md` (8 Steps):** Decomposes raw source documents into 5–25 atomic wiki pages with frontmatter relations.
|
|
36
31
|
* **`wiki-lint.md` (10 Steps):** Integrity audit protocol to validate paths, recompute `mentioned_in`, eliminate orphans, merge duplicates, audit inconsistencies, identify gaps, suggest source candidates, and rebuild indexes.
|
|
37
32
|
|
|
@@ -69,10 +64,6 @@ When an AI agent or developer sets up the Karpathy LLM Wiki in a repository or w
|
|
|
69
64
|
- Codebase → `architecture/`, `decisions/`, `runbooks/`, `people/`
|
|
70
65
|
- **Agent decides** — infer structure from the first batch of ingested content
|
|
71
66
|
|
|
72
|
-
4. **[Q4] Enable wiki automation now?**
|
|
73
|
-
- **Yes** — set `lint_trigger: enabled` in `/wiki/index.md` frontmatter
|
|
74
|
-
- **No** — set `lint_trigger: disabled` (can be changed anytime)
|
|
75
|
-
|
|
76
67
|
---
|
|
77
68
|
|
|
78
69
|
## Directory Layout Scaffolding
|
|
@@ -84,7 +75,7 @@ my-workspace/
|
|
|
84
75
|
├── raw/
|
|
85
76
|
│ └── .gitkeep # Intake for unmodified source documents
|
|
86
77
|
├── wiki/
|
|
87
|
-
│ ├── index.md # Master catalog
|
|
78
|
+
│ ├── index.md # Master catalog
|
|
88
79
|
│ ├── hot.md # Rolling ~500-word quick-orient context
|
|
89
80
|
│ └── _log.md # Ingestion & lint audit history
|
|
90
81
|
├── .rnex/
|
|
@@ -95,12 +86,9 @@ my-workspace/
|
|
|
95
86
|
│ ├── workflows/
|
|
96
87
|
│ │ ├── wiki-ingest.md # 8-step decomposition & ingestion workflow
|
|
97
88
|
│ │ └── wiki-lint.md # 10-step graph validation & maintenance workflow
|
|
98
|
-
│
|
|
99
|
-
│
|
|
100
|
-
│
|
|
101
|
-
│ │ ├── wiki-page.template.md # Atomic page template with typed relations
|
|
102
|
-
│ │ └── LLM_WIKI.sample.md # Sample wiki walkthrough
|
|
103
|
-
│ └── .lint_trigger_counter # Session counter (gitignored)
|
|
89
|
+
│ └── templates/
|
|
90
|
+
│ ├── wiki-page.template.md # Atomic page template with typed relations
|
|
91
|
+
│ └── LLM_WIKI.sample.md # Sample wiki walkthrough
|
|
104
92
|
└── rnex.yaml # Plugin configuration
|
|
105
93
|
```
|
|
106
94
|
|
|
@@ -115,11 +103,10 @@ rnex plugin enable karpathy-llm
|
|
|
115
103
|
```
|
|
116
104
|
|
|
117
105
|
This command:
|
|
118
|
-
1. Adds `karpathy-llm` to `plugins:` in `rnex.yaml
|
|
119
|
-
2. Copies initial templates (`wiki/index.md`, `wiki/_log.md`, `wiki/hot.md`, `raw/.gitkeep`, `.rnex/templates/wiki-page.template.md`, `.rnex/templates/LLM_WIKI.sample.md
|
|
106
|
+
1. Adds `karpathy-llm` to `plugins:` in `rnex.yaml`.
|
|
107
|
+
2. Copies initial templates (`wiki/index.md`, `wiki/_log.md`, `wiki/hot.md`, `raw/.gitkeep`, `.rnex/templates/wiki-page.template.md`, `.rnex/templates/LLM_WIKI.sample.md`).
|
|
120
108
|
3. Links `KARPATHY_RULES.md` and workflows into `.rnex/rules/` and `.rnex/workflows/`.
|
|
121
|
-
4.
|
|
122
|
-
5. Syncs scope links and AI context files across all registered member repositories via `rnex sync`.
|
|
109
|
+
4. Syncs scope links and AI context files across all registered member repositories via `rnex sync`.
|
|
123
110
|
|
|
124
111
|
### Option 2: Declarative in `rnex.yaml`
|
|
125
112
|
|
|
@@ -127,8 +114,7 @@ Configure `karpathy-llm` under `plugins:` in `rnex.yaml`:
|
|
|
127
114
|
|
|
128
115
|
```yaml
|
|
129
116
|
plugins:
|
|
130
|
-
karpathy-llm:
|
|
131
|
-
lint_trigger_enabled: true
|
|
117
|
+
karpathy-llm: {}
|
|
132
118
|
```
|
|
133
119
|
|
|
134
120
|
Then synchronize:
|
|
@@ -139,13 +125,114 @@ rnex sync
|
|
|
139
125
|
|
|
140
126
|
---
|
|
141
127
|
|
|
128
|
+
## Configuration Reference
|
|
129
|
+
|
|
130
|
+
The plugin supports two levels of configuration:
|
|
131
|
+
1. **Repo Config (`rnex.yaml`)**: Shared across your team and version-controlled. Configures repository-level structure, file paths, and indexing rules.
|
|
132
|
+
2. **Local Config (`.local.rnex.yaml`)**: Machine-specific and gitignored. Configures git hook triggers, deterministic checks, and your preferred local AI runner command.
|
|
133
|
+
|
|
134
|
+
### 1. Shared Repo Configuration (`rnex.yaml`)
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
plugins:
|
|
138
|
+
karpathy-llm:
|
|
139
|
+
# Directory paths relative to workspace root (defaults shown)
|
|
140
|
+
wiki_dir: wiki # Directory for curated atomic markdown pages
|
|
141
|
+
raw_dir: raw # Append-only directory for unmodified intake documents
|
|
142
|
+
|
|
143
|
+
# Master catalog auto-indexing (default: true)
|
|
144
|
+
# Automatically rebuilds categorized links in wiki/index.md when pages change
|
|
145
|
+
auto_index: true
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 2. Local Machine Configuration (`.local.rnex.yaml`)
|
|
149
|
+
|
|
150
|
+
Use this file to customize how your local workstation executes wiki maintenance (e.g., via git hooks, deterministic scripts, or provider-agnostic AI CLI runners):
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
plugins:
|
|
154
|
+
karpathy-llm:
|
|
155
|
+
# Optional automated git hook trigger (default: unset / manual only):
|
|
156
|
+
# "git-post-commit" - Runs immediately after a successful commit (Recommended: non-blocking)
|
|
157
|
+
# "git-pre-push" - Runs before pushing changes to remote
|
|
158
|
+
# "git-post-merge" - Runs after pulling upstream updates from teammates
|
|
159
|
+
# Omit or leave unset for purely manual maintenance (default).
|
|
160
|
+
lint_trigger: git-post-commit
|
|
161
|
+
|
|
162
|
+
# Stage 1: Deterministic graph maintenance (default: true)
|
|
163
|
+
# Executes zero-token AST/regex checks to validate broken links, recompute mentioned_in,
|
|
164
|
+
# and find orphaned pages without calling an LLM (<50ms, free, offline).
|
|
165
|
+
run_deterministic_checks: true
|
|
166
|
+
|
|
167
|
+
# Stage 2: Provider-agnostic AI command runner (default: "")
|
|
168
|
+
# Executed ONLY when semantic synthesis is required (e.g. decomposing /raw/ docs via wiki-ingest).
|
|
169
|
+
# The trigger pipes the workflow markdown instructions to this command via standard input (stdin).
|
|
170
|
+
ai_cmd: "llm -m openrouter/auto"
|
|
171
|
+
|
|
172
|
+
# Examples for popular CLI tools:
|
|
173
|
+
# ai_cmd: "gemini run" # Google Gemini / Antigravity CLI
|
|
174
|
+
# ai_cmd: "claude -p" # Claude Code CLI
|
|
175
|
+
# ai_cmd: "ollama run llama3" # Local offline model
|
|
176
|
+
# ai_cmd: "aider --message" # Aider CLI
|
|
177
|
+
# ai_cmd: "" # Empty: Prompt-only mode (prints terminal notification)
|
|
178
|
+
|
|
179
|
+
# Terminal notifications on commit (default: true)
|
|
180
|
+
# Displays non-blocking alerts in your terminal right after git commit completes.
|
|
181
|
+
notify_on_changes: true
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Detailed Option Descriptions
|
|
185
|
+
|
|
186
|
+
#### `auto_index` (Repo Config)
|
|
187
|
+
* **What it does:** Automatically keeps `/wiki/index.md` (the master catalog) synchronized with all atomic pages in `/wiki/`.
|
|
188
|
+
* **How it works:** During `wiki-ingest` and `wiki-lint`, the tool inspects each page's frontmatter (`title`, `tags`, directory category) and updates the categorized link sections in `index.md`.
|
|
189
|
+
* **Why you need it:** AI coding assistants read `wiki/index.md` first as a high-level "navigation map" to locate relevant concepts without scanning hundreds of individual markdown files (saving massive amounts of context tokens). If disabled (`false`), you must manually maintain links in `index.md`.
|
|
190
|
+
|
|
191
|
+
#### `lint_trigger` (Local Config)
|
|
192
|
+
* **What it does:** Optional git hook trigger to automate wiki graph audits and maintenance workflows (`wiki-lint` and `wiki-ingest`).
|
|
193
|
+
* **Default:** Unset / omitted. Automated triggers are **disabled by default**; wiki maintenance is purely manual unless you explicitly opt into a Git hook here.
|
|
194
|
+
* **Supported opt-in values:**
|
|
195
|
+
* `git-post-commit` *(Recommended)*: Fires immediately after a `git commit` succeeds. It is completely non-blocking and checks `git diff-tree` to see if files in `/raw/` or `/wiki/` were added or modified.
|
|
196
|
+
* `git-pre-push`: Fires before pushing changes upstream, catching dead links or unparsed notes before publishing to the team.
|
|
197
|
+
* `git-post-merge`: Fires after `git pull` when teammates have added new wiki notes or intake documents.
|
|
198
|
+
* **Why you need it:** Lets you optionally bind wiki maintenance to a specific Git lifecycle event without nagging prompts or timer counters. If you prefer running workflows manually on demand, leave this field omitted.
|
|
199
|
+
|
|
200
|
+
#### `notify_on_changes` (Local Config)
|
|
201
|
+
* **What it does:** Controls whether helpful status messages and action reminders are printed to your terminal stdout.
|
|
202
|
+
* **When is it triggered?** Triggered **immediately after a git operation completes** (e.g., right after `git commit` finishes writing the commit object, or during `git push`).
|
|
203
|
+
* If new documents were committed into `/raw/`: prints an alert (e.g. `[WIKI] 2 new intake documents in /raw/. Run wiki-ingest with your AI assistant.`).
|
|
204
|
+
* If broken links or orphans were detected: prints a summary notice highlighting the pages that need attention.
|
|
205
|
+
* **Why you need it:** Provides immediate visibility into pending wiki operations without blocking or slowing down your Git workflow. Set to `false` for silent background execution.
|
|
206
|
+
|
|
207
|
+
#### `run_deterministic_checks` (Local Config)
|
|
208
|
+
* **What it does:** Enables fast, offline graph analysis before invoking any LLM.
|
|
209
|
+
* **How it works:** Runs a local script that parses Markdown link targets and frontmatter relations (`sources`, `related`, `extends`, `contradicts`). It validates that target files exist, recomputes reciprocal `mentioned_in: []` backlinks, and identifies orphan pages.
|
|
210
|
+
* **Why you need it:** Resolves 90% of routine wiki maintenance in <50ms without spending API tokens, hitting rate limits, or risking LLM path hallucinations.
|
|
211
|
+
|
|
212
|
+
#### `ai_cmd` (Local Config)
|
|
213
|
+
* **What it does:** A provider-agnostic shell command template used to execute semantic LLM tasks (such as decomposing an intake document via `wiki-ingest` or resolving factual contradictions).
|
|
214
|
+
* **How it works:** When semantic work is needed, the trigger pipes the task prompt and workflow file into this shell command via standard input (`stdin`).
|
|
215
|
+
* **Why you need it:** Decouples your wiki workflow from any single vendor. Works with Simon Willison's `llm`, Google Gemini / Antigravity CLI, Anthropic Claude Code, Ollama, Aider, or custom shell scripts. If left blank (`""`), the system operates in prompt-only mode, reminding you to run the workflow in your interactive chat assistant.
|
|
216
|
+
|
|
217
|
+
### Summary Reference Table
|
|
218
|
+
|
|
219
|
+
| Field | Scope / File | Type | Default | Values / Behavior |
|
|
220
|
+
|:---|:---|:---|:---|:---|
|
|
221
|
+
| `auto_index` | Repo (`rnex.yaml`) | `boolean` | `true` | Auto-rebuilds categorized links in `wiki/index.md`. Set to `false` for manual curation. |
|
|
222
|
+
| `wiki_dir` | Repo (`rnex.yaml`) | `string` | `wiki` | Directory containing atomic domain pages. |
|
|
223
|
+
| `raw_dir` | Repo (`rnex.yaml`) | `string` | `raw` | Append-only directory for unmodified source materials. |
|
|
224
|
+
| `lint_trigger` | Local (`.local.rnex.yaml`) | `string` | *(unset)* | Optional opt-in Git hook: `git-post-commit`, `git-pre-push`, `git-post-merge`. Unset = purely manual. |
|
|
225
|
+
| `run_deterministic_checks` | Local (`.local.rnex.yaml`) | `boolean` | `true` | Offline zero-token validation of broken links, `mentioned_in`, and orphans. |
|
|
226
|
+
| `ai_cmd` | Local (`.local.rnex.yaml`) | `string` | `""` | Command template for semantic tasks. If unset, operates in prompt-only mode. |
|
|
227
|
+
| `notify_on_changes` | Local (`.local.rnex.yaml`) | `boolean` | `true` | Terminal alerts printed right after git commit/push when `/raw/` or wiki needs attention. |
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
142
231
|
## Everyday Operation & Cadence
|
|
143
232
|
|
|
144
233
|
1. **Intake:** Drop raw research papers, meeting notes, PRDs, or architecture specs into `/raw/` unmodified.
|
|
145
234
|
2. **Ingest:** Instruct your AI assistant: *"Run wiki-ingest on raw/source-document.md"*.
|
|
146
|
-
3. **
|
|
147
|
-
4. **Maintenance:** If prompted by `[WIKI MAINTENANCE DUE]`, instruct the assistant: *"Run wiki-lint"*.
|
|
148
|
-
5. **Toggle Automation:** Edit `lint_trigger: enabled` or `lint_trigger: disabled` in `/wiki/index.md` anytime.
|
|
235
|
+
3. **Maintenance:** Run the `wiki-lint` workflow to validate relations, prune orphans, and update `mentioned_in` links.
|
|
149
236
|
|
|
150
237
|
---
|
|
151
238
|
|
|
@@ -56,9 +56,7 @@ When working in a repository with an active Karpathy LLM Wiki (`/wiki/` and `/ra
|
|
|
56
56
|
- **Intake**: All source material (articles, transcripts, docs, notes) goes to `/raw/` unmodified. Never write directly to `/wiki/` without ingesting.
|
|
57
57
|
- **Orientation**: Before answering domain questions, read `/wiki/index.md` to find relevant pages, then read only those pages. If `hot.md` exists, read it first as a quick-orient step.
|
|
58
58
|
- **Ingestion**: When files appear in `/raw/`, run the `wiki-ingest` workflow (`.rnex/workflows/wiki-ingest.md`). One source document typically produces many atomic pages (commonly 5–25 pages) — do not collapse a source into a single file.
|
|
59
|
-
- **
|
|
60
|
-
- **No-op sessions**: Do not run the trigger after read-only or purely conversational sessions where no files changed.
|
|
61
|
-
- **Enable/disable**: Wiki automation is controlled by `lint_trigger_enabled: true|false` in `rnex.yaml` (and `lint_trigger: enabled|disabled` in `/wiki/index.md` frontmatter). Edit either field to toggle.
|
|
59
|
+
- **Maintenance**: Run the `wiki-lint` workflow (`.rnex/workflows/wiki-lint.md`) to validate paths, update `mentioned_in`, and preserve graph integrity.
|
|
62
60
|
|
|
63
61
|
---
|
|
64
62
|
|
|
@@ -56,9 +56,7 @@ When working in a repository with an active Karpathy LLM Wiki (`/wiki/` and `/ra
|
|
|
56
56
|
- **Intake**: All source material (articles, transcripts, docs, notes) goes to `/raw/` unmodified. Never write directly to `/wiki/` without ingesting.
|
|
57
57
|
- **Orientation**: Before answering domain questions, read `/wiki/index.md` to find relevant pages, then read only those pages. If `hot.md` exists, read it first as a quick-orient step.
|
|
58
58
|
- **Ingestion**: When files appear in `/raw/`, run the `wiki-ingest` workflow (`.rnex/workflows/wiki-ingest.md`). One source document typically produces many atomic pages (commonly 5–25 pages) — do not collapse a source into a single file.
|
|
59
|
-
- **
|
|
60
|
-
- **No-op sessions**: Do not run the trigger after read-only or purely conversational sessions where no files changed.
|
|
61
|
-
- **Enable/disable**: Wiki automation is controlled by `lint_trigger_enabled: true|false` in `rnex.yaml` (and `lint_trigger: enabled|disabled` in `/wiki/index.md` frontmatter). Edit either field to toggle.
|
|
59
|
+
- **Maintenance**: Run the `wiki-lint` workflow (`.rnex/workflows/wiki-lint.md`) to validate paths, update `mentioned_in`, and preserve graph integrity.
|
|
62
60
|
|
|
63
61
|
---
|
|
64
62
|
|
|
@@ -6,4 +6,4 @@ Append-only audit trail recording all ingest (`wiki-ingest`) and maintenance (`w
|
|
|
6
6
|
|
|
7
7
|
### Initial Setup — YYYY-MM-DD
|
|
8
8
|
* **Action:** Initialized Karpathy LLM Wiki architecture via `karpathy-llm` plugin.
|
|
9
|
-
* **
|
|
9
|
+
* **Intake:** Intake directory `/raw/` created.
|
|
@@ -8,4 +8,4 @@
|
|
|
8
8
|
* **Key Directives:**
|
|
9
9
|
1. Maintain atomic pages with typed frontmatter relations.
|
|
10
10
|
2. Update `/wiki/index.md` and this hot cache upon new ingests.
|
|
11
|
-
3. Run `
|
|
11
|
+
3. Run `wiki-lint` workflow to audit and maintain graph integrity.
|
|
@@ -40,10 +40,6 @@ Ask ALL of the following questions and wait for answers:
|
|
|
40
40
|
- Structured — subfolders by category, chosen based on Q2 answer
|
|
41
41
|
- Agent decides — infer structure from the first batch of ingested content
|
|
42
42
|
|
|
43
|
-
[Q4] Enable wiki automation now?
|
|
44
|
-
- Yes — set `lint_trigger: enabled` in `/wiki/index.md` frontmatter
|
|
45
|
-
- No — set `lint_trigger: disabled` (can be changed at any time by editing that field)
|
|
46
|
-
|
|
47
43
|
---
|
|
48
44
|
|
|
49
45
|
### 1. Directories and Files
|
|
@@ -58,27 +54,23 @@ Ask ALL of the following questions and wait for answers:
|
|
|
58
54
|
- Content archive → `sources/`, `people/`, `tools/`, `concepts/`
|
|
59
55
|
- Codebase → `architecture/`, `decisions/`, `runbooks/`, `people/`
|
|
60
56
|
|
|
61
|
-
**`/wiki/index.md`** — Master navigation index
|
|
62
|
-
- YAML frontmatter with `lint_trigger: enabled|disabled` — controls whether the autonomous trigger runs. Committed to version control; toggling is a team-visible decision.
|
|
57
|
+
**`/wiki/index.md`** — Master navigation index. Contains:
|
|
63
58
|
- Categorized links to every wiki page. Auto-maintained after every ingest and lint run.
|
|
64
59
|
|
|
65
60
|
**`/wiki/_log.md`** — Append-only operation log. Every ingest and lint run appends a timestamped entry.
|
|
66
61
|
|
|
67
62
|
**`/wiki/hot.md`** *(create only for second brain or codebase wiki)* — Rolling ~500-word cache of the most recently relevant context. Lets an agent orient without reading the full wiki.
|
|
68
63
|
|
|
69
|
-
**`/wiki/.lint_trigger_counter`** — Session counter used by the lint trigger script. Machine-local state. Add to `.gitignore`.
|
|
70
|
-
|
|
71
64
|
---
|
|
72
65
|
|
|
73
66
|
### 2. Index File Format
|
|
74
67
|
|
|
75
|
-
`/wiki/index.md` uses its own frontmatter schema (it is the wiki
|
|
68
|
+
`/wiki/index.md` uses its own frontmatter schema (it is the wiki navigation file, not an atomic content page):
|
|
76
69
|
|
|
77
70
|
```yaml
|
|
78
71
|
---
|
|
79
72
|
title: Wiki Index
|
|
80
73
|
last_updated: YYYY-MM-DD
|
|
81
|
-
lint_trigger: enabled # set to "disabled" to pause all wiki automation
|
|
82
74
|
---
|
|
83
75
|
```
|
|
84
76
|
|
|
@@ -122,9 +114,7 @@ In the file chosen in Q1, append:
|
|
|
122
114
|
- **Intake**: All source material (articles, transcripts, docs, notes) goes to `/raw/` unmodified. Never write directly to `/wiki/` without ingesting.
|
|
123
115
|
- **Orientation**: Before answering domain questions, read `/wiki/index.md` to find relevant pages, then read only those pages. If `hot.md` exists, read it first as a quick-orient step.
|
|
124
116
|
- **Ingestion**: When files appear in `/raw/`, run the `wiki-ingest` workflow. One source document typically produces many atomic pages — do not collapse a source into a single file.
|
|
125
|
-
- **
|
|
126
|
-
- **No-op sessions**: Do not run the trigger after read-only or purely conversational sessions where no files changed.
|
|
127
|
-
- **Enable/disable**: Wiki automation is controlled by `lint_trigger: enabled|disabled` in `/wiki/index.md` frontmatter. Edit that field to toggle — the change is committed and visible to the whole team.
|
|
117
|
+
- **Maintenance**: Run the `wiki-lint` workflow to validate paths, update `mentioned_in`, and preserve graph integrity.
|
|
128
118
|
```
|
|
129
119
|
|
|
130
120
|
---
|
|
@@ -157,23 +147,5 @@ Create workflow instruction files at `.agent/workflows/` (or `.agent/skills/` de
|
|
|
157
147
|
|
|
158
148
|
---
|
|
159
149
|
|
|
160
|
-
### 6. Autonomous Lint Trigger
|
|
161
|
-
|
|
162
|
-
Create `scripts/wiki-lint-trigger.sh` (POSIX shell):
|
|
163
|
-
- Check if `wiki/index.md` exists and contains `lint_trigger: enabled`. If not, exit silently with code `0`.
|
|
164
|
-
```sh
|
|
165
|
-
grep -q "lint_trigger: enabled" wiki/index.md 2>/dev/null || exit 0
|
|
166
|
-
```
|
|
167
|
-
- Read and increment a counter stored in `wiki/.lint_trigger_counter`.
|
|
168
|
-
- If counter is `1` or a multiple of `15`, print:
|
|
169
|
-
`[WIKI MAINTENANCE DUE]: Pending /raw/ files or wiki health checks detected. Run wiki-lint.`
|
|
170
|
-
- Otherwise exit silently with code `0`.
|
|
171
|
-
- Make executable: `chmod +x scripts/wiki-lint-trigger.sh`.
|
|
172
|
-
|
|
173
|
-
To disable: set `lint_trigger: disabled` in `/wiki/index.md` frontmatter.
|
|
174
|
-
To re-enable: set `lint_trigger: enabled`.
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
150
|
All files must be self-contained with no external dependencies.
|
|
179
151
|
```
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
# ============================================================================
|
|
3
|
-
# .rnex/scripts/wiki-lint-trigger.sh — Autonomous Karpathy Wiki Lint Trigger
|
|
4
|
-
# ============================================================================
|
|
5
|
-
|
|
6
|
-
# 1. Check rnex.yaml configuration if present
|
|
7
|
-
if [ -f "rnex.yaml" ]; then
|
|
8
|
-
_disabled=$(awk '
|
|
9
|
-
/^plugins:/ { in_p=1; next }
|
|
10
|
-
in_p && /^[^ #]/ { exit }
|
|
11
|
-
in_p && /^ karpathy-llm:[ ]*$/ { in_k=1; next }
|
|
12
|
-
in_k && /^ lint_trigger_enabled:[ ]*false/ { print "yes"; exit }
|
|
13
|
-
in_k && !/^ / && !/^[ ]*#/ { in_k=0 }
|
|
14
|
-
' rnex.yaml)
|
|
15
|
-
if [ "$_disabled" = "yes" ]; then
|
|
16
|
-
exit 0
|
|
17
|
-
fi
|
|
18
|
-
fi
|
|
19
|
-
|
|
20
|
-
# 2. Check if wiki/index.md exists and contains lint_trigger: enabled
|
|
21
|
-
grep -q "lint_trigger: enabled" wiki/index.md 2>/dev/null || exit 0
|
|
22
|
-
|
|
23
|
-
COUNTER_DIR=".rnex"
|
|
24
|
-
[ -d "$COUNTER_DIR" ] || COUNTER_DIR="wiki"
|
|
25
|
-
COUNTER_FILE="$COUNTER_DIR/.lint_trigger_counter"
|
|
26
|
-
|
|
27
|
-
# Read and increment session counter
|
|
28
|
-
count=0
|
|
29
|
-
if [ -f "$COUNTER_FILE" ]; then
|
|
30
|
-
count=$(cat "$COUNTER_FILE" 2>/dev/null || echo 0)
|
|
31
|
-
fi
|
|
32
|
-
case "$count" in
|
|
33
|
-
''|*[!0-9]*) count=0 ;;
|
|
34
|
-
esac
|
|
35
|
-
|
|
36
|
-
count=$((count + 1))
|
|
37
|
-
printf '%s\n' "$count" > "$COUNTER_FILE" 2>/dev/null || true
|
|
38
|
-
|
|
39
|
-
# If counter is 1 or a multiple of 15, print maintenance due notice
|
|
40
|
-
if [ "$count" -eq 1 ] || [ $((count % 15)) -eq 0 ]; then
|
|
41
|
-
printf '[WIKI MAINTENANCE DUE]: Pending /raw/ files or wiki health checks detected. Run wiki-lint.\n'
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
exit 0
|