claude/.claude/memory/blockers.md
Bastien Chanot da4e6b9590 feat(profile): add gstack on|off verb to lib/profile.sh
Centralize gstack toggling in the `profile` command without losing the
active-profile label.

  - `gstack on`  re-enables ALL parked gstack skills (moves
    skills-disabled/gstack__* back) but does NOT touch .active-profile,
    so the user layers full gstack on top of their current profile and
    the statusline label is preserved. Unlike `reset`, which clears the
    label to "none".
  - `gstack off` disables gstack skills not listed in the active profile;
    errors cleanly when no profile is active (needs one to know what to
    keep).

Refactor (behavior-preserving): extract three shared helpers
`enable_all_gstack`, `disable_gstack_not_in`, `parked_gstack_count` and
rewire `cmd_reset` + `cmd_set` to reuse them instead of duplicating the
symlink-toggle loops. Wire `gstack` into main() dispatch, usage(), and the
header usage block.

Docs: SKILL.md argument-hint, examples, and output-policy updated. The
generic `make profile cmd="gstack on"` target already covers Make usage.

Verified: shellcheck CLEAN, `bash -n` OK, 6-case test (help, bad-action,
off-with-no-profile, on, off-trim, on-cycle) with final assertion that the
live symlink state was restored exactly to its pre-test value.

Memory: capitalize BDR-018 (decision), LRN-024 (DRY helper-extraction
pattern), BLK-007 (6 gstack source skills ios-*/spec unlinked post
submodule bump — open follow-up), EVAL-002 (self-eval, false "full.profile
bug" flag corrected pre-edit). Backfill index drift: BDR-017, BLK-005/006.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 18:31:48 +02:00

10 KiB

type entry_prefix schema rules
blockers_registry BLK
id date friction real_cause solution status
BLK-XXX YYYY-MM-DD string (what was blocked) string (root cause, not symptom) string (workaround or fix)
open | resolved | upstream
Open blocker when friction > 15 min wasted. Close with real cause, not "moved on".
Link upstream issue / PR / commit when applicable.
Cause is bug in dependency → status upstream with pointer to tracker.

Blockers registry (BLK)

Index

ID Date Friction Status
BLK-001 2026-04-22 rtk curl breaks JSON pipelines upstream
BLK-002 2026-04-23 rmdir denied in sandbox on empty directory resolved
BLK-003 2026-05-12 scripts/screenshot.mjs hardcoded macOS path blocks PNG cards on Linux upstream
BLK-004 2026-05-20 /ship-feature wrapper at ~/.claude/commands/ points to deleted agent files post-refactor resolved
BLK-005 2026-05-21 gstack submodule rename (checkpoint→context-save) breaks profile entries resolved
BLK-006 2026-05-21 profile.sh current false-negative via ~/.claude symlink (cd not cd -P) resolved
BLK-007 2026-06-02 6 gstack source skills (ios-*, spec) unlinked post-bump — invisible to profiles + gstack on open

BLK-001 — rtk curl returns compressed schema in pipes

  • Date: 2026-04-22
  • Friction: pipelines like rtk curl ... | python -c "json.load(sys.stdin)" (or jq, awk) fail without clear error.
  • Real cause: rtk curl auto-compresses stdout regardless of TTY — documented in .claude/tasks/rtk-upstream-issue.md.
  • Solution:
    • Short-term workaround: exclude_commands=["curl"] in ~/.config/rtk/config.toml.
    • Alternative workaround: use rtk proxy.
    • Upstream fix: issue reported, see .claude/tasks/rtk-upstream-issue.md.
  • Status: upstream (rtk bug, workaround applied).

BLK-002 — rmdir denied in sandbox on empty directory

  • Date: 2026-04-23
  • Friction: couldn't delete ./tasks/ after emptying (post-migration to .claude/tasks/). rmdir tasks and rm -r tasks returned "Permission denied" even with empty dir and non-destructive intent.
  • Real cause: Claude Code sandbox blocks destructive commands (rm, rmdir, rm -rf) by default via harness permission gate, regardless of actual semantics. git rm through git passed (commit c721a36) — git treated as non-destructive tool.
  • Solution:
    • This session: git rm tasks/*.md handled files individually (via git rm, cleared gate). Git auto-detected renames to .claude/tasks/, so tasks/ directory removed implicitly at commit time.
    • If dir persists empty after git rm: ask user to run rmdir tasks manually.
  • Status: resolved (fixed via git rm + rename auto-detection; no rmdir needed in practice).

BLK-003 — scripts/screenshot.mjs hardcoded macOS path blocks PNG cards on Linux

  • Date: 2026-05-12
  • Friction: /darwin-skill Phase 3 generates result cards via node ~/.agents/skills/darwin-skill/scripts/screenshot.mjs <html> <png>. On Linux: script fails immediately — require('/Users/alchain/.npm-global/lib/node_modules/playwright/node_modules/playwright-core') resolves to a non-existent macOS user path. No PNG cards produced; Phase 3 falls back to markdown report only.
  • Real cause: upstream alchaincyf/darwin-skill author dev'd on macOS, shipped absolute path to their own homedir's global npm install of playwright. Zero portability layer (no PATH lookup, no playwright bare require, no fallback to npx).
  • Solution:
    • Workaround (used 2026-05-12): skip PNG generation, deliver markdown + HTML cards (HTML viewable in browser without playwright).
    • Local patch: npm i -g playwright then replace require('/Users/alchain/...') with require('playwright'). Two lines edit.
    • Spec-documented fallback: npx playwright screenshot "file:///path/to/card.html#<theme>" out.png --viewport-size=960,1280 --wait-for-timeout=2000 — works without modifying the file, costs ~150MB chromium download.
    • PR upstream to github.com/alchaincyf/darwin-skill once tested.
  • Status: upstream (third-party skill at ~/.agents/skills/darwin-skill/scripts/screenshot.mjs, not in any of our repos).

BLK-004 — /ship-feature wrapper references 6 deleted agent files

  • Date: 2026-05-20
  • Friction: /ship-feature invocation loads wrapper at ~/.claude/commands/ship-feature.md. Wrapper says Load and follow strictly: .claude/agents/{ship-feature,analyzer,designer,implementer,reviewer,tester}.md. 5 of 6 paths missing on disk (only analyzer.md survives). User hits blocker — wrapper without orchestrator.
  • Real cause: refactor commits 0241e1d ("extract skill logic into standalone agent files") + 21960e0 ("changed orchestrators into skills") migrated orchestrator from .claude/agents/ship-feature.md into ~/.claude/skills/ship-feature/SKILL.md and replaced custom sub-agents (designer/implementer/reviewer/tester) with superpowers skills (brainstorming, writing-plans, subagent-driven-development, requesting-code-review, finishing-a-development-branch). Wrapper at ~/.claude/commands/ship-feature.md never updated, never deleted. Untracked file — survived all refactor commits silently.
  • Solution: rm ~/.claude/commands/ship-feature.md. Skill ~/.claude/skills/ship-feature/SKILL.md (name: ship-feature, disable-model-invocation: true) becomes sole /ship-feature resolver. SKILL.md references only existing agents: plugin-advisor.md, analyzer.md, doc-syncer.md.
  • Status: resolved.

BLK-005 — /profile set full warns missing: checkpoint after gstack upstream rename

  • Date: 2026-05-21
  • Friction: /profile set full (and dev, backend, web, web-full) emits ⚠ missing: checkpoint — try: bash link.sh. Running bash link.sh reports ✅ All symlinks already up to date. Next: bash install-plugins.sh — dead-end loop. User cannot resolve the warning by following the suggested next step.
  • Real cause: gstack upstream renamed the checkpoint skill to context-save (Claude Code now treats /checkpoint as a native rewind alias, shadowing the gstack skill). New skill in skills-external/gstack/context-save/SKILL.md carries the description "Formerly /checkpoint — renamed because Claude Code treats /checkpoint as a native rewind alias". Five lib/profiles/*.profile files still listed the dead name. link.sh only symlinks repo dirs into ~/.claude/ — it cannot materialize a skill that no longer exists upstream, so its suggested action was misleading.
  • Solution: s/checkpoint/context-save/ in lib/profiles/{dev,backend,full,web,web-full}.profile (commit 69c5ded). CLAUDE.md:193 routing line Save progress, checkpoint, resume → invoke context-save updated locally, left uncommitted because the file holds unrelated in-progress graphify section work. Verify: bash lib/profile.sh set full now outputs ✓ enabled: context-save with no warning.
  • Status: resolved.
  • Date: 2026-05-21
  • Friction: bash "$HOME/.claude/lib/profile.sh" current returns none (all gstack skills enabled — no profile set) even when a profile IS applied + 14 gstack__* entries sit in the repo's skills-disabled/. User cannot detect active profile via the official command. Same script invoked from inside the repo directory (bash lib/profile.sh current) returns the correct answer — invocation-path-dependent behavior is the worst kind of bug to diagnose.
  • Real cause: lib/profile.sh:43 set REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)". Default bash cd preserves symlinks (logical pathname mode, set -P off). When the script is invoked via the ~/.claude/lib/profile.sh symlink (link.sh wires ~/.claude/lib -> <repo>/lib), $BASH_SOURCE[0] is the symlinked path, dirname returns ~/.claude/lib, cd .. lands at ~/.claude, and pwd returns the logical path /home/bchanot-ubuntu/.claude. $SKILLS_DIR="$REPO/skills" still works because ~/.claude/skills happens to be a symlink to the repo's skills/. But $DISABLED_DIR="$REPO/skills-disabled" resolves to ~/.claude/skills-disabled — a real sibling directory created at some earlier point containing only 2 stale npx-skill symlinks (darwin-skill, find-skills). cmd_current scans this near-empty dir, finds 0 gstack__* entries, returns the "none" sentinel.
  • Solution: REPO="$(cd -P "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" (commit a4558ee). -P forces physical-path resolution so $REPO is always the real repo path regardless of how the script is invoked. Verify: bash "$HOME/.claude/lib/profile.sh" current now returns full (100% match, 14 gstack skills disabled).
  • Status: resolved. Follow-up: ~/.claude/skills-disabled/ (real dir with only darwin-skill/find-skills symlinks) is orphaned — these npx skills are already symlinked into <repo>/skills/ by link.sh, so the disabled-side copies serve no purpose. Could be deleted to remove confusion, but harmless as-is.

BLK-007 — 6 gstack source skills (ios-*, spec) unlinked — invisible to profile system + gstack on

  • Date: 2026-06-02
  • Friction: skills-external/gstack/ has 53 source skills; 6 (ios-clean, ios-design-review, ios-fix, ios-qa, ios-sync, spec) exist ONLY as source — NOT symlinked into skills/ (enabled) nor skills-disabled/gstack__* (parked). So invisible to Claude AND untouched by reset/gstack on (both operate on parked gstack__* only). Surfaced while adding gstack on|off: comm of gstack source vs full.profile.
  • Real cause: gstack submodule bump added new skills; gstack's own ./setup (source of truth for per-skill symlinks per link.sh) not re-run → symlinks never created. Same lifecycle gap class as toggle-external-source-only-state (LRN-007). NOT a full.profile bug — full curated by design (BDR-017 caveat: "full excludes rarely-used gstack skills"). Initial "full omits ios = bug" flag was WRONG, self-corrected (see EVAL-002).
  • Solution: re-run gstack setup to link new skills, then reconcile profiles (decide if iOS skills belong in web/dev profiles — likely NOT). Per gstack-rename-profile-audit (LRN-022): diff skills-external/gstack/ vs lib/profiles/*.profile after every submodule bump. NOT auto-fixed — gstack installer domain + iOS-in-web judgment call.
  • Status: open. Low impact (skills unused today, never linked). Next: run gstack ./setup, audit profile membership.