diff --git a/docs/superpowers/plans/2026-09-30-higgsfield-pack.md b/docs/superpowers/plans/2026-09-30-higgsfield-pack.md new file mode 100644 index 0000000..a046d7a --- /dev/null +++ b/docs/superpowers/plans/2026-09-30-higgsfield-pack.md @@ -0,0 +1,1342 @@ +# Higgsfield Pack Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use subagent-driven-development to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** `make plugin` installs the Higgsfield CLI and its eight skills, off by default, with two toggles to turn them on. + +**Architecture:** A sourced helper (`lib/higgsfield-skills.sh`) clones the upstream skills into gitignored `skills-external/higgsfield-*`; both installers call it. `lib/toggle-external.sh` links the skills on demand through two tools, `higgsfield` (media pack) and `higgsfield-websites` (single skill). Nothing is listed in `link.sh` or in a profile, which is what keeps the pack off across re-runs. + +**Tech Stack:** bash, git, npm (run by the user only), shellcheck, hermetic suites under `lib/tests/` run through `make test`. + +**Spec:** `docs/superpowers/specs/2026-09-30-higgsfield-pack-design.md` +**Contract:** `.claude/tasks/contracts/2026-09-30-higgsfield-pack-1412.md` (14 criteria, binding) + +## How this plan is packaged + +Every edit below was dry-run in a scratch copy: the final suite prints 14 +PASS, shellcheck is clean, and each patch applies to the branch. The exact +bytes live in `docs/superpowers/plans/2026-09-30-higgsfield-pack.patches/`. Each task shows its code inline for reading and names +the file to apply. Apply the file, never a retyped copy. + +Apply a patch with `git apply `. If `git apply` refuses (the target +moved), stop and report `BLOCKED` with the error. Do not hand-merge. + +## Global Constraints + +- Executors never run `install-plugins.sh`, `update-all.sh`, `link.sh`, `doctor.sh`, `npm install`, `npx`, `lib/toggle-external.sh` against the real repo, or `higgsfield_sync_skills` against the network (BDR-095). The suite is the only thing that runs. +- Tests run through `make test suite=lib/tests/` only. Never call a suite with `bash` directly, never prefix the command with env variables. +- Nothing about Higgsfield goes in `link.sh`, `lib/profile.sh`, `lib/profiles/*.profile` or `lib/effort-pins.txt` (BDR-093, BDR-079, BDR-105, BDR-107). The suite locks this. +- The skill sync sits before the last `apply_effort_pins "$REPO"` in `install-plugins.sh` and `update-all.sh` (BDR-108, BLK-024). +- `lib/toggle-external.sh` takes no new top-level `source` (LRN-178). +- The CLI token never reaches a terminal or a log: every `higgsfield auth token` call redirects to `/dev/null`. +- House limits for new code: functions of 25 logic lines at most, 80 columns, 5 parameters, 5 locals; shellcheck clean; comments state intent. +- Commits: explicit paths only (`git add `), never `git add -A`, never `--no-verify`, no attribution trailer. The hooks push each commit. +- `CLAUDE.global.md` and `settings.json` are hand-curated (BDR-028): only the orchestrator touches them. + +## Review Focus + +1. A refresh while the pack is enabled: the live `skills/` link must keep resolving. Pinned by `live-reads` in `SYNC_KEEPS_PARKED` (Task 2). +2. Upstream changes its layout (no `higgsfield-*/SKILL.md`): the sync must return non-zero and keep the existing copies. Pinned by `no-skills` in `SYNC_FAIL_KEEPS_COPY` (Task 2). +3. `enable higgsfield` on a machine with no CLI on PATH: links are created, one warning, exit 0. Pinned by `absent-*` in `SIGNED_OUT_WARNS` (Task 3). +4. npm holds back the package's postinstall script, so the shim exists but the binary does not: the installer must print the `--allow-scripts=` remedy. Pinned by `remedy` in `INSTALL_WIRING` (Task 4). +5. The generalised pack arms must not change what `21st` prints or does. Pinned by `PACK_21ST_UNCHANGED` (Task 3). + +--- + +### Task 1: Lock entry and gitignore + +**Files:** +- Modify: `plugins.lock.json` (new `higgsfield` entry before `graphifyy`) +- Modify: `.gitignore` (link side after `skills/21st-*`, source side after `skills-external/21st-*/`) + +**Interfaces:** +- Consumes: nothing. +- Produces: lock key `higgsfield` with `version` (read by Tasks 4 and 5); ignore rules `skills/higgsfield-*` and `skills-external/higgsfield-*/` (LRN-025: both states of a toggleable artifact). + +- [ ] **Step 1: Apply the lock patch** + +Run: `git apply docs/superpowers/plans/2026-09-30-higgsfield-pack.patches/01-lock.patch` + +````diff +--- a/plugins.lock.json ++++ b/plugins.lock.json +@@ -25,6 +25,11 @@ + "version": "latest", + "note": "21st.dev CLI (bin `21st`) — standalone CLI + a pack of 7 skills, no MCP, no API key: auth is `21st login` (browser token in ~/.config/21st). Install: npm install -g @21st-dev/cli. The skill pack is staged-installed into skills-external/21st-* by install-plugins.sh Step 8.7 — `21st skills install` refuses to write through the ~/.claude/skills symlink." + }, ++ "higgsfield": { ++ "source": "npm:@higgsfield/cli", ++ "version": "latest", ++ "note": "Higgsfield CLI (bins `higgsfield`, `higgs`) — image, video, audio and brand media generation, metered credits; auth is `higgsfield auth login` (browser). Install: npm install -g @higgsfield/cli. The package vendors its binary in a postinstall script; if npm holds it back, add --allow-scripts=@higgsfield/cli. The 8 skills are git-cloned from https://github.com/higgsfield-ai/skills (tracks main, no pin) into skills-external/higgsfield-* by lib/higgsfield-skills.sh (install-plugins.sh Step 8.6, refreshed by update-all.sh). OFF by default and in no profile: `lib/toggle-external.sh enable higgsfield` links the 7 media skills, `enable higgsfield-websites` the landing-page aid." ++ }, + "graphifyy": { + "source": "pypi:graphifyy", + "version": "latest", +```` + +- [ ] **Step 2: Apply the gitignore patch** + +Run: `git apply docs/superpowers/plans/2026-09-30-higgsfield-pack.patches/01-gitignore.patch` + +````diff +--- a/.gitignore ++++ b/.gitignore +@@ -101,6 +101,12 @@ + # membership, so the pack can gain a skill with no edit here. + skills/21st-* + ++# Higgsfield skill pack symlinks — created on demand by toggle-external.sh ++# (`enable higgsfield` / `enable higgsfield-websites`). The pack is OFF by ++# default and in no profile, so these usually don't exist. A glob: the ++# upstream repo owns the membership. ++skills/higgsfield-* ++ + # Context7 docs-lookup skill — installed by `ctx7 setup --claude --cli` + # (install-plugins.sh Step 6, when absent) into ~/.claude/skills (a symlink to + # this repo's skills/). ctx7-managed and re-created on demand — not vendored here. +@@ -236,6 +242,11 @@ + # layout and the content is sha256-verified against 21st.dev's manifest. + skills-external/21st-*/ + ++# Higgsfield skill pack — machine-owned: a git clone of higgsfield-ai/skills, ++# staged by lib/higgsfield-skills.sh (install-plugins.sh Step 8.6) and moved ++# here, refreshed by update-all.sh. Not vendored: it tracks upstream main. ++skills-external/higgsfield-*/ ++ + # npx `skills add` project-scope artifacts — darwin-skill copies itself into + # the repo's .agents/ and writes skills-lock.json at root. Our own agents live + # in agents/ (no dot) and stay tracked. Anchored to root so only the dotted +```` + +- [ ] **Step 3: Verify** + +Run: +```bash +python3 -c "import json;d=json.load(open('plugins.lock.json'))['higgsfield'];assert d['version']=='latest' and 'managed_by' not in d;print('LOCK_OK')" +git check-ignore -q skills/higgsfield-generate && git check-ignore -q skills-external/higgsfield-generate/SKILL.md && echo IGNORED_BOTH +git check-ignore -q skills/feat/SKILL.md || echo CONTROL_OK +``` +Expected: `LOCK_OK`, `IGNORED_BOTH`, `CONTROL_OK` (a tracked skill is not ignored). + +- [ ] **Step 4: Commit** + +```bash +git add plugins.lock.json .gitignore +git commit -m "chore(higgsfield): lock entry and gitignore for the skill pack" +``` + +--- + +### Task 2: Sync helper and its suite + +**Files:** +- Create: `lib/tests/higgsfield.test.sh` (from `docs/superpowers/plans/2026-09-30-higgsfield-pack.patches/02-higgsfield.test.sh`) +- Create: `lib/higgsfield-skills.sh` (from `docs/superpowers/plans/2026-09-30-higgsfield-pack.patches/02-higgsfield-skills.sh`) + +**Interfaces:** +- Consumes: nothing. +- Produces: + - `HIGGSFIELD_SKILLS_URL` (env value wins over the upstream default). + - `higgsfield_sync_skills `: prints the number of skills synced on stdout; returns 0 when at least one skill was synced, 1 otherwise (existing copies untouched). + - `higgsfield_signed_in`: returns 0 when `higgsfield auth token` succeeds; prints nothing. + - Suite helpers later tasks reuse: `expect`, `expect_has`, `expect_not`, `verdict`, `yn`, `entries`, `git_q`, `$WORK`, `$ROOT`; the file ends with a `# ── tally ──` block that must stay last. + +- [ ] **Step 1: Write the failing suite** + +Run: `cp docs/superpowers/plans/2026-09-30-higgsfield-pack.patches/02-higgsfield.test.sh lib/tests/higgsfield.test.sh` + +````bash +#!/usr/bin/env bash +# lib/tests/higgsfield.test.sh — hermetic suite for the Higgsfield pack. +# sync lib/higgsfield-skills.sh against a local git repo shaped like +# upstream (no network) +# toggle lib/toggle-external.sh `higgsfield` / `higgsfield-websites` +# against a fixture tree, fake CLIs first on PATH +# wiring static locks on the installers (order, off by default) +# Each named case prints one `PASS ` or `FAIL :
` line. +set -u +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +pass=0; fail=0; errs="" + +# expect