docs(plan): revise the higgsfield plan and spec after the three-lens challenge

This commit is contained in:
bastien
2026-09-30 15:06:43 +02:00
parent 64d094f93a
commit 1f4bd4a75a
16 changed files with 738 additions and 437 deletions
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# ============================================================
# lib/higgsfield-skills.sh — Higgsfield skill pack sync + session probe
# lib/higgsfield-skills.sh — Higgsfield skill pack sync + CLI probes
#
# Sourced by install-plugins.sh (Step 8.6), update-all.sh (7.3b) and
# doctor.sh. The pack is machine-owned: cloned from upstream and moved
@@ -14,40 +14,63 @@
HIGGSFIELD_SKILLS_URL="${HIGGSFIELD_SKILLS_URL:-\
https://github.com/higgsfield-ai/skills.git}"
# _higgsfield_adopt <clone> <dest>
# Move every real higgsfield-*/ directory of the clone that holds a SKILL.md
# over its copy in <dest>; prints how many landed. A symlinked entry is
# skipped: only upstream's own directories are adopted. A skill counts only
# once its move succeeded.
_higgsfield_adopt() {
local clone="$1" dest="$2" dir name count=0
for dir in "$clone"/higgsfield-*/; do
dir="${dir%/}"
{ [ -f "$dir/SKILL.md" ] && [ ! -L "$dir" ]; } || continue
name="$(basename "$dir")"
rm -rf "${dest:?}/${name:?}" && mv "$dir" "$dest/$name" \
&& count=$((count + 1))
done
echo "$count"
}
# higgsfield_sync_skills <repo>
# Clone upstream into a throwaway stage and replace each
# Clone upstream into a stage and replace each
# <repo>/skills-external/higgsfield-* with the fresh copy; upstream's own
# machinery (setup, scripts/, plugin manifests, .git) is left in the stage.
# Prints the number of skills synced. Returns 1, existing copies untouched,
# when the clone fails or upstream holds no higgsfield-*/SKILL.md. A parked
# skill (skills-disabled/<name>, a symlink to the source path) stays parked.
# machinery (setup, scripts/, plugin manifests, .git) stays in the stage.
# The stage sits next to the destination, on the same filesystem, so each
# replacement is a rename. Prints the number of skills synced. Returns 1,
# existing copies untouched, when the clone fails or upstream holds no
# higgsfield-*/SKILL.md. A parked skill (skills-disabled/<name>, a symlink
# to the source path) stays parked. Known limit: a skill that upstream
# removes or renames keeps its last local copy.
higgsfield_sync_skills() {
local repo="$1" stage dir name count=0
stage="$(mktemp -d)" || return 1
if git clone --quiet --depth 1 "$HIGGSFIELD_SKILLS_URL" "$stage/src" \
>/dev/null 2>&1; then
mkdir -p "$repo/skills-external"
for dir in "$stage"/src/higgsfield-*/; do
[ -f "${dir}SKILL.md" ] || continue
name="$(basename "$dir")"
rm -rf "${repo:?}/skills-external/${name:?}"
mv "$dir" "$repo/skills-external/$name"
count=$((count + 1))
done
local dest="$1/skills-external" stage count=0
mkdir -p "$dest" || return 1
stage="$(mktemp -d "$dest/.higgsfield-stage.XXXXXX")" || return 1
# No credential prompt: a private or deleted upstream must fail, not hang.
if GIT_TERMINAL_PROMPT=0 git clone --quiet --depth 1 \
"$HIGGSFIELD_SKILLS_URL" "$stage/src" >/dev/null 2>&1; then
count="$(_higgsfield_adopt "$stage/src" "$dest")"
fi
rm -rf "${stage:?}"
echo "$count"
[ "$count" -gt 0 ]
}
# higgsfield_signed_in — 0 when the CLI holds a session. The CLI is closed
# source, so whether `auth token` stays local is unverified: bound it when
# `timeout` exists, feed it no stdin, and never let the token reach a
# terminal or a log.
higgsfield_signed_in() {
# _higgsfield_probe <args...>
# Run `higgsfield <args>` silently, 15 s at most when `timeout` exists. The
# CLI is closed source: a probe must never hang an installer, and what it
# prints (a token, for `auth token`) must never reach a terminal or a log.
_higgsfield_probe() {
if command -v timeout >/dev/null 2>&1; then
timeout 15 higgsfield auth token </dev/null >/dev/null 2>&1
timeout 15 higgsfield "$@" </dev/null >/dev/null 2>&1
else
higgsfield auth token </dev/null >/dev/null 2>&1
higgsfield "$@" </dev/null >/dev/null 2>&1
fi
}
# higgsfield_cli_ok — 0 when the binary answers. `command -v` alone only
# proves the npm shim: the binary is vendored by a postinstall script that
# npm may hold back, on a first install or on any later update.
higgsfield_cli_ok() { _higgsfield_probe version; }
# higgsfield_signed_in — 0 when the CLI holds a session.
higgsfield_signed_in() { _higgsfield_probe auth token; }