@zerwiz/ymir 0.1.5 → 0.1.8
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/.agents/agents/huginn-researcher.md +1 -1
- package/.agents/agents/kvasir-scout.md +1 -1
- package/.agents/agents/sindri-developer.md +1 -1
- package/.agents/backend/README.md +74 -0
- package/.agents/backend/model-bridge.py +74 -4
- package/.agents/config/cron.yaml +2 -0
- package/.agents/config/eindri-dispatch.json +6 -6
- package/.agents/migrations/0003-private-data-separation.sh +11 -1
- package/.agents/migrations/0005-roots-out-of-tree.sh +158 -0
- package/.agents/skills/README.md +1 -1
- package/.agents/skills/galdr-ymirsystem/SKILL.md +2 -1
- package/.agents/skills/galdr-ymirsystem/assets/harness-integration/README.md +73 -10
- package/.agents/skills/galdr-ymirsystem/assets/hlidskjalf-ui.md +44 -1
- package/.agents/skills/galdr-ymirsystem/assets/installation.md +290 -24
- package/.agents/skills/galdr-ymirsystem/assets/memory-well.md +3 -1
- package/.agents/skills/galdr-ymirsystem/assets/nornir-jobs.md +39 -1
- package/.agents/skills/galdr-ymirsystem/assets/odrerir-hall.md +4 -0
- package/.agents/skills/galdr-ymirsystem/assets/pi-boot/pi-profile.yml +7 -2
- package/.agents/skills/galdr-ymirsystem/assets/registry.md +1 -1
- package/.agents/skills/galdr-ymirsystem/assets/runtime-compliance.md +2 -2
- package/.agents/skills/galdr-ymirsystem/assets/smidja.md +16 -11
- package/.agents/skills/galdr-ymirsystem/scripts/compliance-check.sh +147 -4
- package/.agents/skills/groa-update/SKILL.md +20 -0
- package/.agents/skills/hamr-adapters/SKILL.md +2 -2
- package/.agents/skills/lifecycle/smoke_test.sh +7 -2
- package/.agents/skills/ymir-host/SKILL.md +2 -1
- package/.agents/skills/ymir-host/assets/install.md +69 -0
- package/AGENTS.md +78 -34
- package/CHANGELOG.md +1362 -1
- package/README.md +1 -1
- package/RULES/02-agents.md +2 -2
- package/RULES/04-hoard.md +32 -0
- package/RULES/06-append-only.md +50 -0
- package/RULES/07-config.md +56 -0
- package/RULES/09-electron.md +58 -0
- package/RULES/README.md +2 -0
- package/bin/a2a-mcp.sh +42 -7
- package/bin/agents-config.sh +30 -7
- package/bin/apodex-smoke-test.sh +14 -1
- package/bin/bifrost-bridge.sh +25 -6
- package/bin/bootstrap-macos.sh +6 -1
- package/bin/brokk-send.sh +14 -1
- package/bin/changelog-assemble.sh +154 -0
- package/bin/changelog-guard.sh +39 -7
- package/bin/crash-sense.sh +14 -1
- package/bin/design-check.sh +80 -0
- package/bin/design-icon.sh +156 -0
- package/bin/docs-guard.sh +2 -2
- package/bin/editor-place.sh +33 -15
- package/bin/eindri-acclaim.sh +14 -1
- package/bin/eindri-seat.sh +83 -0
- package/bin/eindri-seen.sh +14 -1
- package/bin/eindri-start.sh +14 -1
- package/bin/einherjar-spawn.sh +9 -3
- package/bin/eir-doctor.sh +89 -1
- package/bin/electron-lib.sh +34 -0
- package/bin/feature-inventory.sh +73 -0
- package/bin/fleet-apply.sh +15 -2
- package/bin/github-deploy.sh +14 -1
- package/bin/gjallarhorn-expose.sh +43 -9
- package/bin/gjallarhorn-notify.sh +14 -1
- package/bin/gjallarhorn-purge.sh +14 -1
- package/bin/gjallarhorn-tunnel.sh +16 -3
- package/bin/groa-update.sh +9 -1
- package/bin/hall-snapshot.sh +21 -2
- package/bin/herdr-run.sh +23 -2
- package/bin/hlidskjalf-agents.sh +172 -0
- package/bin/hlidskjalf-usage.sh +196 -0
- package/bin/hoard-guard.sh +135 -0
- package/bin/hoard-lib.sh +91 -11
- package/bin/hodd.sh +28 -4
- package/bin/huginn-research-worker.sh +14 -1
- package/bin/local-model-lock.sh +22 -3
- package/bin/mimir-bridge.py +33 -0
- package/bin/mimir-bridge.sh +14 -1
- package/bin/mimir-reflect.sh +27 -0
- package/bin/mjollnir-webhook.sh +14 -1
- package/bin/mjollnir.sh +22 -3
- package/bin/model-hardware.sh +17 -3
- package/bin/model-resolve.sh +14 -1
- package/bin/nornir-job-hall-snapshot.sh +28 -0
- package/bin/nornir-job-nsr-compliance.sh +54 -0
- package/bin/npm-publish.sh +136 -0
- package/bin/omarchy-install.sh +18 -5
- package/bin/omarchy-plugins.sh +15 -2
- package/bin/omarchy-sense.sh +14 -1
- package/bin/pi-model-agnostic.sh +71 -0
- package/bin/private-guard.sh +20 -0
- package/bin/project-git.sh +18 -4
- package/bin/public-guard.sh +3 -2
- package/bin/sessrumnir-ensure.sh +1 -1
- package/bin/sessrumnir.sh +16 -3
- package/bin/smidja-board.sh +136 -0
- package/bin/smidja-bootstrap.sh +5 -1
- package/bin/smidja-lib.sh +49 -0
- package/bin/syn-asset-pretool-check.sh +14 -1
- package/bin/syn-spawn-pretool-check.sh +58 -0
- package/bin/tailscale-sync.sh +15 -2
- package/bin/telegram-bot.sh +14 -1
- package/bin/ui-truth-check.sh +75 -0
- package/bin/valknut-load.sh +42 -4
- package/bin/wedge-notify.sh +14 -1
- package/bin/workspace-rag.sh +14 -1
- package/bin/ymir-install.sh +257 -57
- package/bin/ymir-plan.sh +390 -0
- package/bin/ymir-say.sh +14 -1
- package/bin/ymir-setup-auth.sh +12 -1
- package/bin/ymir-style.sh +108 -0
- package/bin/ymir-validate.sh +64 -11
- package/bin/ymir.js +82 -34
- package/docs/design.md +2 -2
- package/docs/lore.md +5 -1
- package/docs/runbooks/agents.md +1 -1
- package/package.json +13 -3
- package/scripts/electron.sh +74 -15
- package/scripts/lower.sh +34 -0
- package/scripts/raise.sh +42 -0
- package/scripts/start.sh +65 -3
- package/.agents/config/agents.yaml +0 -50
- package/.agents/config/tailscale-sync.yaml +0 -27
- package/.agents/memory/kaia.engram +0 -0
- package/.agents/memory/kaia.engram-shm +0 -0
- package/.agents/memory/kaia.engram-wal +0 -0
- package/.agents/memory/well/episodes.jsonl +0 -367
- package/.agents/memory/well/workspace.jsonl +0 -27
package/bin/eir-doctor.sh
CHANGED
|
@@ -18,6 +18,11 @@ ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
18
18
|
YMIR_HOME="${YMIR_HOME:-$HOME/Documents/Ymir}"
|
|
19
19
|
STATE="${BROKK_STATE_OVERRIDE:-$YMIR_HOME/state}"
|
|
20
20
|
|
|
21
|
+
# The cloth: colour and marks for the human reading this report; the TOON rows on
|
|
22
|
+
# stdout stay the data (bin/ymir-style.sh).
|
|
23
|
+
if [ -z "${YMIR_STYLE_LOADED:-}" ]; then . "$SCRIPT_DIR/ymir-style.sh"; YMIR_STYLE_LOADED=1; fi
|
|
24
|
+
style_init
|
|
25
|
+
|
|
21
26
|
case "${1-}" in -v|-V|--version) printf '%s\n' "$VERSION"; exit 0 ;; -h|--help|"") sed -n '2,15p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; esac
|
|
22
27
|
ACTION="${1:-check}"; shift || true
|
|
23
28
|
|
|
@@ -25,7 +30,7 @@ have() { command -v "$1" >/dev/null 2>&1; }
|
|
|
25
30
|
say_ok() { return 0; }
|
|
26
31
|
|
|
27
32
|
# Each surface: `s_<name>` = healthy? (exit 0), `f_<name>` = the repair.
|
|
28
|
-
SURFACES=(floors herdr a2abridge hermes sessrumnir well mcp lock migrations)
|
|
33
|
+
SURFACES=(floors herdr a2abridge hermes sessrumnir shells well mcp lock migrations hoard)
|
|
29
34
|
|
|
30
35
|
s_floors() { [ -x "$SCRIPT_DIR/prereq-ensure.sh" ] && "$SCRIPT_DIR/prereq-ensure.sh" status >/dev/null 2>&1; }
|
|
31
36
|
f_floors() { "$SCRIPT_DIR/prereq-ensure.sh" ensure --install >/dev/null 2>&1; }
|
|
@@ -37,6 +42,34 @@ s_hermes() { [ -x "$SCRIPT_DIR/hermes-ensure.sh" ] && "$SCRIPT_DIR/hermes-ens
|
|
|
37
42
|
f_hermes() { "$SCRIPT_DIR/hermes-ensure.sh" ensure --install >/dev/null 2>&1; }
|
|
38
43
|
s_sessrumnir(){ [ -x "$SCRIPT_DIR/sessrumnir-ensure.sh" ] && "$SCRIPT_DIR/sessrumnir-ensure.sh" status >/dev/null 2>&1; }
|
|
39
44
|
f_sessrumnir(){ "$SCRIPT_DIR/sessrumnir-ensure.sh" ensure --install >/dev/null 2>&1; }
|
|
45
|
+
# The desktop shells: absent is healthy (the web surfaces stand alone), PARTIAL is
|
|
46
|
+
# not — npm gated the Electron postinstall, so the window cannot open while every
|
|
47
|
+
# build still passes (bin/electron-lib.sh).
|
|
48
|
+
shell_dirs() {
|
|
49
|
+
local a d
|
|
50
|
+
for a in hlidskjalf odrerir sessrumnir; do
|
|
51
|
+
for d in "$ROOT/apps/$a" "$ROOT/node_modules/@zerwiz/$a"; do
|
|
52
|
+
[ -d "$d" ] && { printf '%s\n' "$d"; break; }
|
|
53
|
+
done
|
|
54
|
+
done
|
|
55
|
+
}
|
|
56
|
+
s_shells() {
|
|
57
|
+
local d state
|
|
58
|
+
while IFS= read -r d; do
|
|
59
|
+
state="$(electron_runtime_state "$d" 2>/dev/null || true)"
|
|
60
|
+
[ "$state" = partial ] && return 1
|
|
61
|
+
done < <(shell_dirs)
|
|
62
|
+
return 0
|
|
63
|
+
}
|
|
64
|
+
f_shells() {
|
|
65
|
+
printf 'eir: the shells need YOUR hand — npm gated the runtime download:\n' >&2
|
|
66
|
+
electron_remedy >&2
|
|
67
|
+
return 1
|
|
68
|
+
}
|
|
69
|
+
if [ -z "${YMIR_ELECTRON_LIB_LOADED:-}" ] && [ -r "$SCRIPT_DIR/electron-lib.sh" ]; then
|
|
70
|
+
. "$SCRIPT_DIR/electron-lib.sh"; YMIR_ELECTRON_LIB_LOADED=1
|
|
71
|
+
fi
|
|
72
|
+
|
|
40
73
|
s_well() { [ -x "$SCRIPT_DIR/mimir.sh" ] && "$SCRIPT_DIR/mimir.sh" health >/dev/null 2>&1; }
|
|
41
74
|
f_well() { "$SCRIPT_DIR/mimir.sh" start >/dev/null 2>&1; }
|
|
42
75
|
# MCP: both A2A servers wired into opencode + pi.
|
|
@@ -69,6 +102,51 @@ f_lock() {
|
|
|
69
102
|
}
|
|
70
103
|
s_migrations(){ [ ! -x "$SCRIPT_DIR/ymir-migrate.sh" ] || "$SCRIPT_DIR/ymir-migrate.sh" status >/dev/null 2>&1; }
|
|
71
104
|
f_migrations(){ [ -x "$SCRIPT_DIR/ymir-migrate.sh" ] && "$SCRIPT_DIR/ymir-migrate.sh" apply >/dev/null 2>&1; }
|
|
105
|
+
# Hoard: private data sits under the hoard, and .ymir-layout.yaml tells the truth.
|
|
106
|
+
# Two failures this catches: (1) a declared layout path that does not exist — a
|
|
107
|
+
# stale map is what lets private work land outside the hoard; (2) a flat
|
|
108
|
+
# $YMIR_HOME/{identity,data,docs,secrets,tenants} duplicate beside hodd/ — the
|
|
109
|
+
# drift that RULES/04-hoard.md (correction 2026-09-17) forbids.
|
|
110
|
+
_hoard_root() { local r; if [ -x "$SCRIPT_DIR/hoard-lib.sh" ]; then . "$SCRIPT_DIR/hoard-lib.sh"; hoard_root r; printf '%s' "$r"; else printf '%s' "${YMIR_HOARD:-$YMIR_HOME/hodd}"; fi; }
|
|
111
|
+
s_hoard() {
|
|
112
|
+
local h; h="$(_hoard_root)"
|
|
113
|
+
[ -d "$h" ] || return 1
|
|
114
|
+
local lay="$YMIR_HOME/.ymir-layout.yaml" k p
|
|
115
|
+
if [ -f "$lay" ]; then
|
|
116
|
+
for k in config secrets identity workspaces memory smidja state data; do
|
|
117
|
+
p="$(sed -nE "s/^ $k: \"([^\"]+)\".*/\1/p" "$lay" | head -1)"
|
|
118
|
+
[ -n "$p" ] && [ ! -d "$p" ] && return 1
|
|
119
|
+
done
|
|
120
|
+
fi
|
|
121
|
+
for k in identity data docs secrets tenants; do
|
|
122
|
+
[ -d "$YMIR_HOME/$k" ] && return 1
|
|
123
|
+
done
|
|
124
|
+
return 0
|
|
125
|
+
}
|
|
126
|
+
f_hoard() {
|
|
127
|
+
local h; h="$(_hoard_root)"
|
|
128
|
+
mkdir -p "$h" 2>/dev/null || return 1
|
|
129
|
+
# A flat duplicate beside hodd/ is the drift: merge it in, never clobber.
|
|
130
|
+
local k
|
|
131
|
+
for k in identity data docs secrets tenants; do
|
|
132
|
+
local src="$YMIR_HOME/$k"
|
|
133
|
+
[ -d "$src" ] || continue
|
|
134
|
+
mkdir -p "$h/$k" 2>/dev/null || continue
|
|
135
|
+
cp -an "$src/." "$h/$k/" 2>/dev/null || true
|
|
136
|
+
rm -rf "$src" 2>/dev/null || true
|
|
137
|
+
done
|
|
138
|
+
# A layout entry naming a nonexistent dir is repointed at the hoard.
|
|
139
|
+
local lay="$YMIR_HOME/.ymir-layout.yaml" k2 p
|
|
140
|
+
if [ -f "$lay" ] && [ -d "$h" ]; then
|
|
141
|
+
for k2 in identity data secrets docs tenants; do
|
|
142
|
+
p="$(sed -nE "s/^ $k2: \"([^\"]+)\".*/\1/p" "$lay" | head -1)"
|
|
143
|
+
if [ -n "$p" ] && [ ! -d "$p" ]; then
|
|
144
|
+
sed -i "s|^ $k2: .*| $k2: \"$h/$k2\"|" "$lay"
|
|
145
|
+
fi
|
|
146
|
+
done
|
|
147
|
+
fi
|
|
148
|
+
s_hoard
|
|
149
|
+
}
|
|
72
150
|
|
|
73
151
|
detail() { # <name> -> one short fact
|
|
74
152
|
case "$1" in
|
|
@@ -81,6 +159,8 @@ detail() { # <name> -> one short fact
|
|
|
81
159
|
mcp) "echo 'a2abridge + engram'" ;;
|
|
82
160
|
lock) "cat $STATE/.lock 2>/dev/null | tr -d '[:space:]' | sed 's/^/pid /' || echo none" ;;
|
|
83
161
|
migrations)"echo 'structure'" ;;
|
|
162
|
+
shells) 'shell_dirs | while IFS= read -r d; do printf "%s %s; " "$(basename "$d")" "$(electron_runtime_state "$d" 2>/dev/null || true)"; done' ;;
|
|
163
|
+
hoard) "printf 'hoard %s' \"$(_hoard_root)\" ; [ -d \"$YMIR_HOME/identity\" ] && printf ' +flat-duplicate' ; printf '\\n'" ;;
|
|
84
164
|
esac
|
|
85
165
|
}
|
|
86
166
|
|
|
@@ -105,6 +185,14 @@ done
|
|
|
105
185
|
printf 'eir[1]{action,root,broken}:\n "%s","%s",%s\n' "$ACTION" "$ROOT" "$broken"
|
|
106
186
|
printf 'health[%d]{surface,state,detail}:\n' "$count"
|
|
107
187
|
printf '%b' "$rows"
|
|
188
|
+
# For the eye, on stderr: marks and colour; for the pipe, the TOON above.
|
|
189
|
+
if [ -t 2 ]; then
|
|
190
|
+
printf '\n' >&2
|
|
191
|
+
while IFS='|' read -r surface state detail; do
|
|
192
|
+
[ -n "$surface" ] || continue
|
|
193
|
+
style_line "$state" "$surface" "$detail"
|
|
194
|
+
done <<<"$(printf '%b' "$rows" | sed 's/^ //; s/"//g; s/,/|/; s/,/|/')"
|
|
195
|
+
fi
|
|
108
196
|
if [ "$broken" != 0 ]; then
|
|
109
197
|
printf 'eir: %s surface(s) need mending — run: bin/eir-doctor.sh fix\n' "$broken"
|
|
110
198
|
exit 1
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# electron-lib.sh — is a desktop shell's runtime actually there?
|
|
3
|
+
#
|
|
4
|
+
# The trap this exists for: npm blocks a package's install scripts by default
|
|
5
|
+
# (npm 11.16+ warns, npm 12 refuses), and Electron's postinstall is what downloads
|
|
6
|
+
# its ~100 MB runtime. Without it the install still reports SUCCESS and the web app
|
|
7
|
+
# still builds — `node_modules/electron/dist/` is simply partial and `path.txt` is
|
|
8
|
+
# never written. So the shell fails to launch while every check says healthy, and
|
|
9
|
+
# nobody is told.
|
|
10
|
+
#
|
|
11
|
+
# Ymir refuses that silence: a shell is only "ready" when the runtime verifies.
|
|
12
|
+
# Source-safe, functions only.
|
|
13
|
+
#
|
|
14
|
+
# electron_runtime_state <app-dir> ok | partial | absent (exit 0 only for ok)
|
|
15
|
+
# electron_remedy the exact command that mends a partial one
|
|
16
|
+
set -u
|
|
17
|
+
|
|
18
|
+
electron_runtime_state() { # <app-dir>
|
|
19
|
+
local dir="${1-}"
|
|
20
|
+
[ -n "$dir" ] && [ -d "$dir" ] || { printf 'absent'; return 1; }
|
|
21
|
+
[ -d "$dir/node_modules/electron" ] || { printf 'absent'; return 1; }
|
|
22
|
+
# path.txt is written by the postinstall; dist/electron is what it points at.
|
|
23
|
+
if [ -f "$dir/node_modules/electron/path.txt" ] \
|
|
24
|
+
&& [ -x "$dir/node_modules/electron/dist/electron" ]; then
|
|
25
|
+
printf 'ok'; return 0
|
|
26
|
+
fi
|
|
27
|
+
printf 'partial'; return 1
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
electron_remedy() {
|
|
31
|
+
printf 'the runtime download was skipped by npm — approve and rebuild:\n'
|
|
32
|
+
printf ' npm install-scripts approve electron && npm rebuild electron\n'
|
|
33
|
+
printf 'yonder: bin/ymir-install.sh --no-desktop if the web surfaces are enough'
|
|
34
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# feature-inventory.sh — every feature the system CLAIMS, in one checklist.
|
|
3
|
+
#
|
|
4
|
+
# "Every single feature must work" is a hope until there is a list. This builds
|
|
5
|
+
# the list from the tree itself rather than from anyone's memory: every tool, job,
|
|
6
|
+
# skill, agent, app, workflow, service and registered project. It asserts nothing
|
|
7
|
+
# about whether they work — that is the verification pass, and it needs this
|
|
8
|
+
# inventory to exist first.
|
|
9
|
+
#
|
|
10
|
+
# bin/feature-inventory.sh # the inventory, as TOON
|
|
11
|
+
# bin/feature-inventory.sh --counts # just the tallies
|
|
12
|
+
# bin/feature-inventory.sh --verify-plan # the inventory as a checklist to fill in
|
|
13
|
+
set -u
|
|
14
|
+
|
|
15
|
+
VERSION="1.0.0"
|
|
16
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
17
|
+
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
18
|
+
HOARD="${YMIR_HOARD:-${YMIR_HOME:-$HOME/Documents/Ymir}/hodd}"
|
|
19
|
+
|
|
20
|
+
case "${1-}" in
|
|
21
|
+
-v|-V|--version) printf '%s\n' "$VERSION"; exit 0 ;;
|
|
22
|
+
-h|--help|"") sed -n '2,14p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
|
23
|
+
esac
|
|
24
|
+
MODE="${1:-all}"
|
|
25
|
+
|
|
26
|
+
n_tools=$(find "$ROOT/bin" -maxdepth 1 -type f \( -name '*.sh' -o -name '*.py' -o -name '*.js' \) 2>/dev/null | wc -l | tr -d ' ')
|
|
27
|
+
n_jobs=$(ls "$ROOT"/bin/nornir-job-*.sh 2>/dev/null | wc -l | tr -d ' ')
|
|
28
|
+
n_skills=$(find -L "$ROOT/.agents/skills" -mindepth 2 -maxdepth 2 -name SKILL.md 2>/dev/null | wc -l | tr -d ' ')
|
|
29
|
+
n_agents=$(ls "$ROOT"/.agents/agents/*.md 2>/dev/null | wc -l | tr -d ' ')
|
|
30
|
+
n_workflows=$(ls "$ROOT"/.github/workflows/*.yml 2>/dev/null | wc -l | tr -d ' ')
|
|
31
|
+
n_apps=$(find "$ROOT/apps" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l | tr -d ' ')
|
|
32
|
+
n_migrations=$(ls "$ROOT"/.agents/migrations/*.sh 2>/dev/null | wc -l | tr -d ' ')
|
|
33
|
+
n_projects=0
|
|
34
|
+
[ -r "$HOARD/identity/projects.yaml" ] && n_projects=$(grep -c '^ - id:' "$HOARD/identity/projects.yaml" 2>/dev/null | tr -d ' ')
|
|
35
|
+
|
|
36
|
+
if [ "$MODE" = "--counts" ]; then
|
|
37
|
+
printf 'features[8]{kind,count}:\n'
|
|
38
|
+
printf ' "tools (bin/)",%s\n' "$n_tools"
|
|
39
|
+
printf ' "nornir jobs",%s\n' "$n_jobs"
|
|
40
|
+
printf ' "skills",%s\n' "$n_skills"
|
|
41
|
+
printf ' "agents",%s\n' "$n_agents"
|
|
42
|
+
printf ' "workflows (CI)",%s\n' "$n_workflows"
|
|
43
|
+
printf ' "apps",%s\n' "$n_apps"
|
|
44
|
+
printf ' "migrations",%s\n' "$n_migrations"
|
|
45
|
+
printf ' "registered projects",%s\n' "$n_projects"
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# The checklist: one row per thing that must be proven.
|
|
50
|
+
printf 'inventory[8]{kind,count,how_proven}:\n'
|
|
51
|
+
printf ' "tools (bin/)",%s,"bash -n + --version/--help runs, exit 0"\n' "$n_tools"
|
|
52
|
+
printf ' "nornir jobs",%s,"one run each, --check or dry-run, writes as documented"\n' "$n_jobs"
|
|
53
|
+
printf ' "skills",%s,"its scripts run; its asset paths resolve (skillindex gate)"\n' "$n_skills"
|
|
54
|
+
printf ' "agents",%s,"bound into all five harnesses (harnesses gate) + a dispatch"\n' "$n_agents"
|
|
55
|
+
printf ' "workflows (CI)",%s,"YAML parses + the job runs green on the branch"\n' "$n_workflows"
|
|
56
|
+
printf ' "apps",%s,"builds, serves, wears its rune, installs its entry, opens in Electron"\n' "$n_apps"
|
|
57
|
+
printf ' "migrations",%s,"idempotent; re-run leaves the home unchanged"\n' "$n_migrations"
|
|
58
|
+
printf ' "registered projects",%s,"gh resolves the repo; PR ledger reports its PRs"\n' "$n_projects"
|
|
59
|
+
|
|
60
|
+
printf 'tools[%s]{tool}:\n' "$n_tools"
|
|
61
|
+
for f in "$ROOT"/bin/*; do
|
|
62
|
+
[ -f "$f" ] || continue
|
|
63
|
+
case "$f" in *.sh|*.py|*.js) printf ' "%s"\n' "$(basename "$f")" ;; esac
|
|
64
|
+
done
|
|
65
|
+
|
|
66
|
+
printf 'jobs[%s]{job}:\n' "$n_jobs"
|
|
67
|
+
for f in "$ROOT"/bin/nornir-job-*.sh; do [ -f "$f" ] && printf ' "%s"\n' "$(basename "$f")"; done
|
|
68
|
+
|
|
69
|
+
printf 'apps[%s]{app}:\n' "$n_apps"
|
|
70
|
+
for d in "$ROOT"/apps/*/; do [ -d "$d" ] && printf ' "%s"\n' "$(basename "$d")"; done
|
|
71
|
+
|
|
72
|
+
printf 'skills[%s]{skill,owner}:\n' "$n_skills"
|
|
73
|
+
grep -oE '^ "[a-z0-9-]+","[^"]*","[a-z]+"' "$ROOT/.agents/skills/README.md" 2>/dev/null | sed 's/^ //' || true
|
package/bin/fleet-apply.sh
CHANGED
|
@@ -14,8 +14,21 @@ set -u
|
|
|
14
14
|
VERSION="1.0.0"
|
|
15
15
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
16
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
|
|
18
|
+
# The roots that live OUTSIDE the code tree: this machine's records and the
|
|
19
|
+
# runtime state belong to the home the operator chose at installation, never in
|
|
20
|
+
# the tree — a packaged install replaces its tree on upgrade (Rule 04).
|
|
21
|
+
if [ -z "${YMIR_HOARD_LIB_LOADED:-}" ]; then
|
|
22
|
+
_yr="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
for _yc in "$_yr/hoard-lib.sh" "$(dirname "$_yr")/bin/hoard-lib.sh"; do
|
|
24
|
+
[ -r "$_yc" ] && { . "$_yc"; YMIR_HOARD_LIB_LOADED=1; break; }
|
|
25
|
+
done
|
|
26
|
+
unset _yr _yc
|
|
27
|
+
fi
|
|
28
|
+
hoard_state_dir YMIR_STATE_DIR
|
|
29
|
+
hoard_data_dir YMIR_DATA_DIR
|
|
30
|
+
REG="${BROKK_EINDRI_HOMES:-$YMIR_DATA_DIR/eindri-homes.md}"
|
|
31
|
+
PREFS="${BROKK_FLEET_PREFS:-$YMIR_DATA_DIR/fleet.md}"
|
|
19
32
|
CHECK=0
|
|
20
33
|
|
|
21
34
|
case "${1-}" in -v|-V|--version) printf '%s\n' "$VERSION"; exit 0 ;; -h|--help) sed -n '2,12p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; esac
|
package/bin/github-deploy.sh
CHANGED
|
@@ -16,7 +16,20 @@ set -u
|
|
|
16
16
|
VERSION="1.0.0"
|
|
17
17
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
18
18
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
# The operator's settings and secrets live in the home they chose, never in the
|
|
21
|
+
# code tree — a packaged install replaces its tree on upgrade, and a credential
|
|
22
|
+
# must never sit in a tree that ships (Rule 04).
|
|
23
|
+
if [ -z "${YMIR_HOARD_LIB_LOADED:-}" ]; then
|
|
24
|
+
_yr="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
25
|
+
for _yc in "$_yr/hoard-lib.sh" "$(dirname "$_yr")/bin/hoard-lib.sh"; do
|
|
26
|
+
[ -r "$_yc" ] && { . "$_yc"; YMIR_HOARD_LIB_LOADED=1; break; }
|
|
27
|
+
done
|
|
28
|
+
unset _yr _yc
|
|
29
|
+
fi
|
|
30
|
+
hoard_settings_dir YMIR_SETTINGS_DIR
|
|
31
|
+
hoard_local_env YMIR_ENV_FILE
|
|
32
|
+
ENV_FILE="${BROKK_ENV_FILE:-$YMIR_ENV_FILE}"
|
|
20
33
|
SECRETS="NETLIFY_AUTH_TOKEN NETLIFY_SITE_ID VERCEL_TOKEN GITHUB_TOKEN TELEGRAM_BOT_TOKEN"
|
|
21
34
|
|
|
22
35
|
case "${1-}" in
|
|
@@ -17,6 +17,19 @@ set -u
|
|
|
17
17
|
VERSION="1.0.0"
|
|
18
18
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
19
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
20
|
+
|
|
21
|
+
# The roots that live OUTSIDE the code tree: this machine's records and the
|
|
22
|
+
# runtime state belong to the home the operator chose at installation, never in
|
|
23
|
+
# the tree — a packaged install replaces its tree on upgrade (Rule 04).
|
|
24
|
+
if [ -z "${YMIR_HOARD_LIB_LOADED:-}" ]; then
|
|
25
|
+
_yr="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
|
+
for _yc in "$_yr/hoard-lib.sh" "$(dirname "$_yr")/bin/hoard-lib.sh"; do
|
|
27
|
+
[ -r "$_yc" ] && { . "$_yc"; YMIR_HOARD_LIB_LOADED=1; break; }
|
|
28
|
+
done
|
|
29
|
+
unset _yr _yc
|
|
30
|
+
fi
|
|
31
|
+
hoard_state_dir YMIR_STATE_DIR
|
|
32
|
+
hoard_data_dir YMIR_DATA_DIR
|
|
20
33
|
TUNNEL="${YMIR_TUNNEL_NAME:-ymir}"
|
|
21
34
|
DOMAIN="${YMIR_TUNNEL_DOMAIN:-zerwiz.org}"
|
|
22
35
|
SUFFIX="${YMIR_TUNNEL_SUFFIX:-dell}"
|
|
@@ -31,13 +44,16 @@ case "${1:-plan}" in
|
|
|
31
44
|
esac
|
|
32
45
|
ACTION="${1:-plan}"
|
|
33
46
|
|
|
34
|
-
#
|
|
47
|
+
# Every public hostname points at the GATE (:3889), never at an app's own port:
|
|
48
|
+
# the gate holds the login and proxies on by host, so the web door is locked for
|
|
49
|
+
# every app. An app port here would be a hole straight past the login.
|
|
50
|
+
GATE_PORT="${HLIDSKJALF_API_PORT:-3889}"
|
|
35
51
|
APPS=(
|
|
36
|
-
"ymir:$
|
|
37
|
-
"hlidskjalf
|
|
38
|
-
"odrerir
|
|
39
|
-
"smidja
|
|
40
|
-
"smidjafactory
|
|
52
|
+
"ymir:$GATE_PORT"
|
|
53
|
+
"hlidskjalf:$GATE_PORT"
|
|
54
|
+
"odrerir:$GATE_PORT"
|
|
55
|
+
"smidja:$GATE_PORT"
|
|
56
|
+
"smidjafactory:$GATE_PORT"
|
|
41
57
|
)
|
|
42
58
|
|
|
43
59
|
if [ -z "$SUFFIX" ]; then
|
|
@@ -71,7 +87,9 @@ mkdir -p "$(dirname "$CONFIG")"
|
|
|
71
87
|
{
|
|
72
88
|
printf '# Gjallarhorn — this machine (%s). Generated by bin/gjallarhorn-expose.sh.\n' "$SUFFIX"
|
|
73
89
|
printf 'tunnel: %s\n' "$TUNNEL"
|
|
74
|
-
|
|
90
|
+
# No credentials-file line: cloudflared resolves <UUID>.json for a named
|
|
91
|
+
# tunnel itself. Guessing the filename (ymir.json) is what made it refuse to
|
|
92
|
+
# start, and a tunnel that will not start answers 530 to the world.
|
|
75
93
|
printf 'ingress:\n'
|
|
76
94
|
for row in "${APPS[@]}"; do
|
|
77
95
|
app="${row%%:*}"; port="${row##*:}"
|
|
@@ -81,16 +99,31 @@ mkdir -p "$(dirname "$CONFIG")"
|
|
|
81
99
|
} >"$CONFIG"
|
|
82
100
|
|
|
83
101
|
# 2. the routes (idempotent: an existing record is left alone)
|
|
102
|
+
# Route by the tunnel's own UUID, never by its name. `route dns <name> <host>`
|
|
103
|
+
# resolves the name through the account certificate, which can point at a
|
|
104
|
+
# DIFFERENT (even deleted) tunnel: every hostname then answers 530 while the
|
|
105
|
+
# named tunnel runs happily beside it. Resolve the UUID first, then route.
|
|
106
|
+
TUNNEL_ID="$(cloudflared tunnel info "$TUNNEL" 2>/dev/null | grep -m1 -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')"
|
|
107
|
+
[ -n "$TUNNEL_ID" ] || TUNNEL_ID="$TUNNEL"
|
|
84
108
|
made=0
|
|
85
109
|
for row in "${APPS[@]}"; do
|
|
86
110
|
app="${row%%:*}"
|
|
87
|
-
cloudflared tunnel route dns "$
|
|
111
|
+
cloudflared tunnel route dns --overwrite-dns "$TUNNEL_ID" "$app$SUFFIX.$DOMAIN" >/dev/null 2>&1 && made=$((made+1))
|
|
88
112
|
done
|
|
89
113
|
|
|
114
|
+
# 2b. the gate must know which host belongs to which app (it routes by host)
|
|
115
|
+
HOSTMAP="$YMIR_STATE_DIR/gjallarhorn-hosts.env"
|
|
116
|
+
{
|
|
117
|
+
printf '# Written by bin/gjallarhorn-expose.sh — the gate routes these hosts.\n'
|
|
118
|
+
printf 'YMIR_PRIMARY_HOST=ymir%s.%s\n' "$SUFFIX" "$DOMAIN"
|
|
119
|
+
printf 'SMIDJA_HOST=smidja%s.%s\n' "$SUFFIX" "$DOMAIN"
|
|
120
|
+
printf 'ODRERIR_HOST=odrerir%s.%s\n' "$SUFFIX" "$DOMAIN"
|
|
121
|
+
} >"$HOSTMAP"
|
|
122
|
+
|
|
90
123
|
# 3. raise it
|
|
91
124
|
started="already"
|
|
92
125
|
if ! pgrep -f "cloudflared.*tunnel.*--config $CONFIG" >/dev/null 2>&1; then
|
|
93
|
-
nohup cloudflared tunnel --config "$CONFIG" run "$TUNNEL" >"$
|
|
126
|
+
nohup cloudflared tunnel --config "$CONFIG" run "$TUNNEL" >"$YMIR_STATE_DIR/gjallarhorn.log" 2>&1 &
|
|
94
127
|
started="pid $!"
|
|
95
128
|
sleep 4
|
|
96
129
|
fi
|
|
@@ -98,5 +131,6 @@ fi
|
|
|
98
131
|
printf 'gjallarhorn_apply[3]{what,detail,count}:\n'
|
|
99
132
|
printf ' "config","%s","%s"\n' "${CONFIG#"$HOME"/}" "${#APPS[@]}"
|
|
100
133
|
printf ' "routes","%s%s.%s","%s"\n' "" "$SUFFIX" "$DOMAIN" "$made"
|
|
134
|
+
printf ' "hostmap","%s","the gate routes by host"\n' "${HOSTMAP#"$ROOT"/}"
|
|
101
135
|
printf ' "tunnel","%s","%s"\n' "$started" "$TUNNEL"
|
|
102
136
|
plan
|
|
@@ -13,7 +13,20 @@ set -u
|
|
|
13
13
|
VERSION="1.0.0"
|
|
14
14
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
15
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
# The operator's settings and secrets live in the home they chose, never in the
|
|
18
|
+
# code tree — a packaged install replaces its tree on upgrade, and a credential
|
|
19
|
+
# must never sit in a tree that ships (Rule 04).
|
|
20
|
+
if [ -z "${YMIR_HOARD_LIB_LOADED:-}" ]; then
|
|
21
|
+
_yr="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
22
|
+
for _yc in "$_yr/hoard-lib.sh" "$(dirname "$_yr")/bin/hoard-lib.sh"; do
|
|
23
|
+
[ -r "$_yc" ] && { . "$_yc"; YMIR_HOARD_LIB_LOADED=1; break; }
|
|
24
|
+
done
|
|
25
|
+
unset _yr _yc
|
|
26
|
+
fi
|
|
27
|
+
hoard_settings_dir YMIR_SETTINGS_DIR
|
|
28
|
+
hoard_local_env YMIR_ENV_FILE
|
|
29
|
+
ENV_FILE="${BROKK_ENV_FILE:-$YMIR_ENV_FILE}"
|
|
17
30
|
|
|
18
31
|
usage() { sed -n '2,11p' "$0" | sed 's/^# \{0,1\}//'; }
|
|
19
32
|
|
package/bin/gjallarhorn-purge.sh
CHANGED
|
@@ -11,7 +11,20 @@ set -u
|
|
|
11
11
|
VERSION="1.0.0"
|
|
12
12
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
13
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
# The operator's settings and secrets live in the home they chose, never in the
|
|
16
|
+
# code tree — a packaged install replaces its tree on upgrade, and a credential
|
|
17
|
+
# must never sit in a tree that ships (Rule 04).
|
|
18
|
+
if [ -z "${YMIR_HOARD_LIB_LOADED:-}" ]; then
|
|
19
|
+
_yr="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
20
|
+
for _yc in "$_yr/hoard-lib.sh" "$(dirname "$_yr")/bin/hoard-lib.sh"; do
|
|
21
|
+
[ -r "$_yc" ] && { . "$_yc"; YMIR_HOARD_LIB_LOADED=1; break; }
|
|
22
|
+
done
|
|
23
|
+
unset _yr _yc
|
|
24
|
+
fi
|
|
25
|
+
hoard_settings_dir YMIR_SETTINGS_DIR
|
|
26
|
+
hoard_local_env YMIR_ENV_FILE
|
|
27
|
+
ENV_FILE="${BROKK_ENV_FILE:-$YMIR_ENV_FILE}"
|
|
15
28
|
DOMAIN="${YMIR_DOMAIN:-${YMIR_TUNNEL_HOST:-}}"
|
|
16
29
|
[ -n "$DOMAIN" ] || { printf 'gjallarhorn-purge: set YMIR_DOMAIN (or YMIR_TUNNEL_HOST)\n' >&2; exit 2; }
|
|
17
30
|
ZONE_NAME="${CLOUDFLARE_ZONE_NAME:-}"
|
|
@@ -19,10 +19,23 @@ fi
|
|
|
19
19
|
VERSION="1.0.0"
|
|
20
20
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
21
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
22
|
+
|
|
23
|
+
# The roots that live OUTSIDE the code tree: this machine's records and the
|
|
24
|
+
# runtime state belong to the home the operator chose at installation, never in
|
|
25
|
+
# the tree — a packaged install replaces its tree on upgrade (Rule 04).
|
|
26
|
+
if [ -z "${YMIR_HOARD_LIB_LOADED:-}" ]; then
|
|
27
|
+
_yr="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
28
|
+
for _yc in "$_yr/hoard-lib.sh" "$(dirname "$_yr")/bin/hoard-lib.sh"; do
|
|
29
|
+
[ -r "$_yc" ] && { . "$_yc"; YMIR_HOARD_LIB_LOADED=1; break; }
|
|
30
|
+
done
|
|
31
|
+
unset _yr _yc
|
|
32
|
+
fi
|
|
33
|
+
hoard_state_dir YMIR_STATE_DIR
|
|
34
|
+
hoard_data_dir YMIR_DATA_DIR
|
|
22
35
|
CONFIG="${YMIR_TUNNEL_CONFIG:-$HOME/.cloudflared/config-ymir.yml}"
|
|
23
36
|
TUNNEL="${YMIR_TUNNEL_NAME:-ymir}"
|
|
24
|
-
PID_FILE="$
|
|
25
|
-
LOG_FILE="$
|
|
37
|
+
PID_FILE="$YMIR_STATE_DIR/gjallarhorn.pid"
|
|
38
|
+
LOG_FILE="$YMIR_STATE_DIR/gjallarhorn.log"
|
|
26
39
|
|
|
27
40
|
case "${1-}" in -v|-V|--version) printf '%s\n' "$VERSION"; exit 0 ;; -h|--help|"") sed -n '2,10p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; esac
|
|
28
41
|
ACTION="${1:-status}"; shift || true
|
|
@@ -59,7 +72,7 @@ esac
|
|
|
59
72
|
|
|
60
73
|
command -v cloudflared >/dev/null 2>&1 || { printf 'error: cloudflared not found\nhelp: install cloudflared\n' >&2; exit 1; }
|
|
61
74
|
[ -r "$CONFIG" ] || { printf 'error: tunnel config not found: %s\nhelp: cp midgard/infrastructure/ingress/cloudflared-ymir.yml ~/.cloudflared/config-ymir.yml\n' "$CONFIG" >&2; exit 1; }
|
|
62
|
-
mkdir -p "$
|
|
75
|
+
mkdir -p "$YMIR_STATE_DIR"
|
|
63
76
|
if running; then printf 'gjallarhorn[1]{state,host}:\n "already up","%s"\n' "$HOST"; exit 0; fi
|
|
64
77
|
|
|
65
78
|
nohup cloudflared tunnel --config "$CONFIG" run "$TUNNEL" >"$LOG_FILE" 2>&1 &
|
package/bin/groa-update.sh
CHANGED
|
@@ -25,7 +25,15 @@ VERSION="2.0.0"
|
|
|
25
25
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
26
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
27
27
|
YMIR_HOME="${YMIR_HOME:-$HOME/Documents/Ymir}"
|
|
28
|
-
|
|
28
|
+
# The registry lives in the hoard (RULES/04-hoard.md; correction 2026-09-17).
|
|
29
|
+
# Resolve through hoard-lib so the path can never drift again.
|
|
30
|
+
if [ -r "$SCRIPT_DIR/hoard-lib.sh" ]; then
|
|
31
|
+
# shellcheck source=bin/hoard-lib.sh
|
|
32
|
+
. "$SCRIPT_DIR/hoard-lib.sh"; hoard_root _hoard
|
|
33
|
+
else
|
|
34
|
+
_hoard="${YMIR_HOARD:-$YMIR_HOME/hodd}"
|
|
35
|
+
fi
|
|
36
|
+
REG="${BROKK_EINDRI_HOMES:-$_hoard/data/eindri-homes.md}"
|
|
29
37
|
REMOTE=""; BRANCH=""; CHECK=0
|
|
30
38
|
|
|
31
39
|
case "${1-}" in -v|-V|--version) printf '%s\n' "$VERSION"; exit 0 ;; -h|--help) sed -n '2,21p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; esac
|
package/bin/hall-snapshot.sh
CHANGED
|
@@ -17,13 +17,32 @@
|
|
|
17
17
|
set -u
|
|
18
18
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
19
|
ROOT="${BROKK_ROOT_OVERRIDE:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
# The operator's settings and secrets live in the home they chose, never in the
|
|
22
|
+
# code tree — a packaged install replaces its tree on upgrade, and a credential
|
|
23
|
+
# must never sit in a tree that ships (Rule 04).
|
|
24
|
+
if [ -z "${YMIR_HOARD_LIB_LOADED:-}" ]; then
|
|
25
|
+
_yr="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
|
+
for _yc in "$_yr/hoard-lib.sh" "$(dirname "$_yr")/bin/hoard-lib.sh"; do
|
|
27
|
+
[ -r "$_yc" ] && { . "$_yc"; YMIR_HOARD_LIB_LOADED=1; break; }
|
|
28
|
+
done
|
|
29
|
+
unset _yr _yc
|
|
30
|
+
fi
|
|
31
|
+
hoard_settings_dir YMIR_SETTINGS_DIR
|
|
32
|
+
hoard_local_env YMIR_ENV_FILE
|
|
33
|
+
hoard_state_dir YMIR_STATE_DIR
|
|
34
|
+
hoard_data_dir YMIR_DATA_DIR
|
|
35
|
+
|
|
36
|
+
# The roots that live OUTSIDE the code tree: this machine's records and the
|
|
37
|
+
# runtime state belong to the home the operator chose at installation, never in
|
|
38
|
+
# the tree — a packaged install replaces its tree on upgrade (Rule 04).
|
|
39
|
+
STATE="${BROKK_STATE_OVERRIDE:-$YMIR_STATE_DIR}"
|
|
21
40
|
OUT="${1:-$ROOT/apps/odrerir/public/livehall.json}"
|
|
22
41
|
|
|
23
42
|
runes_file="${BROKK_RUNES_FILE:-${YMIR_HOME:-$HOME/Documents/Ymir}/hodd/memory/runes_audit.md}"
|
|
24
43
|
PROJECTS_FILE="${YMIR_HOME:-$HOME/Documents/Ymir}/hodd/identity/projects.yaml"
|
|
25
44
|
projects_file="$PROJECTS_FILE"
|
|
26
|
-
cron_file="$
|
|
45
|
+
cron_file="$YMIR_SETTINGS_DIR/cron.yaml"
|
|
27
46
|
|
|
28
47
|
# --- tally the pieces ---
|
|
29
48
|
runes=$(grep -c '^{' "$runes_file" 2>/dev/null || echo 0)
|
package/bin/herdr-run.sh
CHANGED
|
@@ -37,7 +37,20 @@ set -u
|
|
|
37
37
|
VERSION="2.0.0"
|
|
38
38
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
39
39
|
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
40
|
-
|
|
40
|
+
|
|
41
|
+
# The roots that live OUTSIDE the code tree: this machine's records and the
|
|
42
|
+
# runtime state belong to the home the operator chose at installation, never in
|
|
43
|
+
# the tree — a packaged install replaces its tree on upgrade (Rule 04).
|
|
44
|
+
if [ -z "${YMIR_HOARD_LIB_LOADED:-}" ]; then
|
|
45
|
+
_yr="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
46
|
+
for _yc in "$_yr/hoard-lib.sh" "$(dirname "$_yr")/bin/hoard-lib.sh"; do
|
|
47
|
+
[ -r "$_yc" ] && { . "$_yc"; YMIR_HOARD_LIB_LOADED=1; break; }
|
|
48
|
+
done
|
|
49
|
+
unset _yr _yc
|
|
50
|
+
fi
|
|
51
|
+
hoard_state_dir YMIR_STATE_DIR
|
|
52
|
+
hoard_data_dir YMIR_DATA_DIR
|
|
53
|
+
STATE_DIR="${BROKK_STATE_OVERRIDE:-$YMIR_STATE_DIR}"
|
|
41
54
|
TAB_LOG="$STATE_DIR/herdr-seats"
|
|
42
55
|
SETTLE="${YMIR_HERDR_SETTLE:-300}"
|
|
43
56
|
|
|
@@ -302,7 +315,15 @@ case "$ACTION" in
|
|
|
302
315
|
h="$(printf '%s' "$r" | cut -d'"' -f6)"
|
|
303
316
|
pv="$(printf '%s' "$r" | cut -d'"' -f8)"
|
|
304
317
|
md="$(printf '%s' "$r" | cut -d'"' -f10)"
|
|
305
|
-
|
|
318
|
+
# The harness FOLLOWS the model: a local provider is pi's work, an
|
|
319
|
+
# online one is opencode's. Trusting a field position here seated
|
|
320
|
+
# pi with an online model id, so the worker started and sat IDLE -
|
|
321
|
+
# "sent but never started" - while the dispatch row reported success.
|
|
322
|
+
case "${md:-}:${pv:-}:${h:-}" in
|
|
323
|
+
*llama*|*lmstudio*|*ollama*) KIND=pi ;;
|
|
324
|
+
"") KIND=pi ;; # nothing resolved: stay local
|
|
325
|
+
*) KIND=opencode ;;
|
|
326
|
+
esac
|
|
306
327
|
[ -n "$md" ] && MODEL_ARGS=(-- --model "$pv/$md")
|
|
307
328
|
printf 'herdr-run[1]{model,harness,provider,model_id}:\n "%s","%s","%s","%s"\n' "$MODEL_REQ" "$h" "$pv" "$md" >&2 ;;
|
|
308
329
|
esac
|