The previous expression used `if ($r | type) == "!!str" then ... end`
which produces a lexer error in yq v4.50–v4.53. This caused every
parse_reference call to return empty output, silently skipping all
references — the root cause of the missing [INFO] messages and tree.
Replace with a single-line expression using only the // alternative
operator and select(), which work across all tested yq v4 versions:
.references[N] | (.url // .) + "|" + (.into // "") + "|" +
(.ref // "") + "|" +
((.env | select(tag == "!!seq") | join(",")) // .env // "")
.url // . handles both string refs (no .url key) and object refs.
env arrays are joined; null env falls back to "".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two issues on IONOS shared hosting (very low ulimit -u):
1. bash 4.4+ propagates the exit code of command substitutions through
`local var=$(cmd)`. When yq crashes (exit 2) the assignment itself
returns 2, and set -e kills the script before any log message appears.
Fixed by adding `|| return 0` to the yq wrapper so it always exits 0.
2. All ref_count comparisons checked for "null"/"0" but not for empty
string. A yq call that produces no stdout (crashed but returned 0)
leaves ref_count="", which neither guard caught — the arithmetic loop
`i < ref_count` silently treated "" as 0 and skipped all references.
Fixed by adding `[[ -z "$ref_count" ]]` to every ref_count guard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
parse_reference was calling yq 5-7 times per reference. With 8 refs
that's ~48 fork+exec calls in rapid succession, saturating IONOS's
ulimit -u and causing intermittent empty 'into' fields — libraries then
installed to the wrong .arty/libs/ location instead of their configured
path.
Collapse all field reads into a single yq expression per reference.
Also add 2>/dev/null to git fetch/pull so the "getaddrinfo() thread
failed to start" message (another ulimit hit, in git's DNS resolver)
doesn't spam the output — the warn message still fires on failure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
IONOS shared hosting enforces a strict process limit. yq (a Go binary)
tries to spawn several OS threads at startup and crashes with
"failed to create new OS thread (errno=11 EAGAIN)" when the limit is
hit, returning empty stdout. This silently skips all references.
Wrap yq with GOMAXPROCS=1 GOGC=off so the Go runtime uses a single
goroutine-running thread and skips GC goroutines, staying within the
host's ulimit -u.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FORCE_COLOR defaulted to 1, emitting ANSI codes unconditionally. On SSH
sessions without a proper TTY or with TERM=dumb this caused color codes
to render text invisible. Now colors are enabled only when stdout is an
interactive terminal; FORCE_COLOR=1 can still override when needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All log_* functions were writing to stderr, causing output to be
invisible in SSH sessions where stderr is not forwarded or captured.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace broken control characters and U+FFFD replacement characters in
log function labels with ASCII equivalents ([ok], [!], [x]).
Drop the hardcoded "main" default for git_ref so arty deps no longer
fails with "pathspec 'main' did not match" on repos whose default branch
is not named main — git clone already checks out the remote default branch.
A ref: value in arty.yml is still honoured when explicitly set.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>