Capitalizes the macOS port and the gstack Chromium deadlock, plus an
append-only correction to BLK-008 / LRN-038: their "ubuntu24.04 fallback
build" cause is refuted — macOS arm64 has a native Playwright 1.58.2 build,
no fallback, and the same hang reproduces. The real variable was the Node
version, and that wrong record misdirected this investigation for an hour.
EVAL-029 records two process failures worth keeping: the first fix
recommendation (pin node@22) was reversed only because the user asked
whether the browser was current — staleness had gone unpriced; and the grep
sweep returned empty twice while defects were present, once to `set -e`,
once to a pattern that could not match `${1,,}`.
Index rows added for all four registries. Pre-existing index drift
(BLK-018..020, LRN-144..149) left alone — backfilling means summarising
entries someone else wrote.
48 KiB
type, entry_prefix, schema, rules
| type | entry_prefix | schema | rules | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| blockers_registry | BLK |
|
|
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 |
resolved |
| BLK-008 | 2026-06-23 | gstack ./setup on Ubuntu 26.04: Playwright chromium unsupported → gstack browser (/browse, /qa, screenshots) silently dead | resolved (211c7d4) |
| BLK-009 | 2026-06-25 | user-level path-scoped rules (paths: frontmatter in ~/.claude/rules/) never inject — broken in CC 2.1.190 (#21858) |
resolved (2026-07-06) |
| BLK-010 | 2026-06-27 | init-project: scaffold (STEP 5) + bootstrap README (5b) have no deterministic commit owner; worktree add -b on unborn HEAD |
resolved (uncommitted) |
| BLK-011 | 2026-06-27 | init-project STEP 13 GSD post-FINISH creates ROADMAP.md → stranded doc (3rd post-FINISH artifact) | resolved (STEP 12 removed) |
| BLK-012 | 2026-06-29 | gitflow_init half-applied: socle-commit failure swallowed → hook activated on partial run → re-run self-blocks | resolved |
| BLK-013 | 2026-06-30 | make plugin Error 127 — npm absent on apt-nodejs host (Step 4 gsd-pi aborts, Steps 5-10 + residual cleanup never run) |
resolved (env) |
| BLK-014 | 2026-07-01 | make install aborts npm EEXIST on ~/.local/bin/claude when claude already installed via native installer — no presence guard |
resolved |
| BLK-015 | 2026-07-03 | gitflow_finish ignored its <type> <name> args → merged the CHECKED-OUT branch not the one named → wrong-branch merge (audit LOT3) |
resolved |
| BLK-016 | 2026-07-04 | rtk compression PATH-dead 30 days — 6/5070 Bash commands compressed (~460K tokens missed); installer sources cargo env so its own check passes, Claude tool shell never gets ~/.cargo/bin | resolved |
| BLK-017 | 2026-07-17 | Bing Webmaster API unusable for a multi-client agency: OAuth swamp (localhost redirect refused, rotated single-use refresh tokens race our parallel dispatch), API key = wrong model (client-owned sites) | open/deferred |
| BLK-021 | 2026-09-13 | gstack Chromium install hangs forever on macOS: Playwright 1.58.2 deadlocks on Node 26 mid-extraction (39/333 files, all threads idle) | resolved |
| BLK-022 | 2026-09-13 | macOS bash 3.2 + BSD userland: six silent defects, most fail-OPEN (SSRF guard, commit scope guards, gate criteria) | resolved |
BLK-001 — rtk curl returns compressed schema in pipes
- Date: 2026-04-22
- Friction: pipelines like
rtk curl ... | python -c "json.load(sys.stdin)"(orjq,awk) fail without clear error. - Real cause:
rtk curlauto-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.
- Short-term workaround:
- Status: upstream (
rtkbug, 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 tasksandrm -r tasksreturned "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 rmthroughgitpassed (commitc721a36) — git treated as non-destructive tool. - Solution:
- This session:
git rm tasks/*.mdhandled files individually (viagit rm, cleared gate). Git auto-detected renames to.claude/tasks/, sotasks/directory removed implicitly at commit time. - If dir persists empty after
git rm: ask user to runrmdir tasksmanually.
- This session:
- Status: resolved (fixed via
git rm+ rename auto-detection; normdirneeded in practice).
BLK-003 — scripts/screenshot.mjs hardcoded macOS path blocks PNG cards on Linux
- Date: 2026-05-12
- Friction:
/darwin-skillPhase 3 generates result cards vianode ~/.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-skillauthor dev'd on macOS, shipped absolute path to their own homedir's global npm install of playwright. Zero portability layer (no PATH lookup, noplaywrightbare require, no fallback tonpx). - Solution:
- Workaround (used 2026-05-12): skip PNG generation, deliver markdown + HTML cards (HTML viewable in browser without playwright).
- Local patch:
npm i -g playwrightthen replacerequire('/Users/alchain/...')withrequire('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-skillonce 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-featureinvocation loads wrapper at~/.claude/commands/ship-feature.md. Wrapper saysLoad and follow strictly: .claude/agents/{ship-feature,analyzer,designer,implementer,reviewer,tester}.md. 5 of 6 paths missing on disk (onlyanalyzer.mdsurvives). 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.mdinto~/.claude/skills/ship-feature/SKILL.mdand 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.mdnever 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-featureresolver. 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. Runningbash link.shreports✅ 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
checkpointskill tocontext-save(Claude Code now treats/checkpointas a native rewind alias, shadowing the gstack skill). New skill inskills-external/gstack/context-save/SKILL.mdcarries the description"Formerly /checkpoint — renamed because Claude Code treats /checkpoint as a native rewind alias". Fivelib/profiles/*.profilefiles still listed the dead name.link.shonly 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/inlib/profiles/{dev,backend,full,web,web-full}.profile(commit69c5ded).CLAUDE.md:193routing lineSave progress, checkpoint, resume → invoke context-saveupdated locally, left uncommitted because the file holds unrelated in-progress graphify section work. Verify:bash lib/profile.sh set fullnow outputs✓ enabled: context-savewith no warning. - Status: resolved.
BLK-006 — bash lib/profile.sh current false-negative when invoked via ~/.claude/lib/ symlink
- Date: 2026-05-21
- Friction:
bash "$HOME/.claude/lib/profile.sh" currentreturnsnone (all gstack skills enabled — no profile set)even when a profile IS applied + 14gstack__*entries sit in the repo'sskills-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:43setREPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)". Default bashcdpreserves symlinks (logical pathname mode,set -Poff). When the script is invoked via the~/.claude/lib/profile.shsymlink (link.sh wires~/.claude/lib -> <repo>/lib),$BASH_SOURCE[0]is the symlinked path,dirnamereturns~/.claude/lib,cd ..lands at~/.claude, andpwdreturns the logical path/home/bchanot-ubuntu/.claude.$SKILLS_DIR="$REPO/skills"still works because~/.claude/skillshappens to be a symlink to the repo'sskills/. 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_currentscans this near-empty dir, finds 0gstack__*entries, returns the "none" sentinel. - Solution:
REPO="$(cd -P "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"(commita4558ee).-Pforces physical-path resolution so$REPOis always the real repo path regardless of how the script is invoked. Verify:bash "$HOME/.claude/lib/profile.sh" currentnow returnsfull (100% match, 14 gstack skills disabled). - Status: resolved. Follow-up:
~/.claude/skills-disabled/(real dir with onlydarwin-skill/find-skillssymlinks) 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 intoskills/(enabled) norskills-disabled/gstack__*(parked). So invisible to Claude AND untouched byreset/gstack on(both operate on parkedgstack__*only). Surfaced while addinggstack on|off:commof gstack source vsfull.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 afull.profilebug — 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 applied (NOT full
./setup— surgical, no side effects): (1) Linkedspeconly —mkdir skills/spec+ln -snf <abs>/skills-external/gstack/spec/SKILL.md skills/spec/SKILL.md, matching gstack setup:440-476 (per-skill real dir + SKILL.md symlink, name from frontmatter). (2) Addedspectofull.profile+web-full.profileplanning sections (must be in active profilefullelseset fullre-disables it). (3) iOS 5 skills deliberately NOT linked — Linux host, device-farm needs Mac daemon + Tailscale + iOS devices = dead skills + token cost. (4) Completed.gitignoregstack allowlist: added all 12 missing (spec, 5ios-*, 6 parkeddocument-generate/landing-report/scrape/setup-gbrain/skillify/sync-gbrain), removed stalecheckpoint(BLK-005 rename). Reason:gstack on(BDR-018) moves parked skills intoskills/— any gstack skill missing from allowlist = untracked git noise on enable. - Verified:
profile show full+web-full→ spec enabled; allowlist drift recheck EMPTY; spec skill now visible to Claude. - Status: resolved. iOS = intentional exclusion (re-linkable via gstack
./setupon a Mac). See gstack-gitignore-allowlist-completeness (LRN-025).
BLK-008 — gstack ./setup fails on Ubuntu 26.04 — Playwright chromium unsupported
-
Date: 2026-06-23
-
Friction: fresh Ubuntu 26.04,
make install/make plugin→ "Failed to install browsers / ERROR: Playwright does not support chromium on ubuntu26.04-x64" → "GStack ./setup failed". Non-fatal in our wrapper (warn only) but gstack's browser (/browse,/qa, design screenshots) is silently dead once gstack is enabled. -
Real cause: Playwright 1.58.2 (pinned in the gstack submodule) registry lists
ubuntu20.04/22.04/24.04only; 26.04 released later → not in list →getHostPlatformerrors. Pure OS-newness, not an install bug. -
Solution: gated
export PLAYWRIGHT_HOST_PLATFORM_OVERRIDE=ubuntu24.04-x64(ubuntu >24.04 only) before gstack setup + persisted to.bashrcfor runtime. Playwright then pulls a Chrome-for-Testing fallback build for ubuntu24.04. Verified on 26.04:lddresolves all libs + real headless render OK. -
Status: resolved (commit
211c7d4). Residual: exact rev 1208 launch not in-session-tested (sandbox download hung at extraction); proved via sibling rev 1228 same-platform CfT build. Confirm on next realmake plugin. Proper upstream fix = gstack bumps Playwright to a version that lists ubuntu26.04. See LRN-038. -
2026-06-23 UPDATE — Solution REVERTED, status downgraded to UPSTREAM/open (commit
b9c3937): thePLAYWRIGHT_HOST_PLATFORM_OVERRIDEsolution above does NOT work on 26.04. The fallback build downloads to 100% then HANGS at extraction (chrome binary never appears, no headless-shell download starts; reproduced on real machine + sandbox) → turned a 0.5s fast-fail into an install-blocking hang (user Ctrl+C). Reverted to the fast-fail (non-fatal; gstack OFF by default, browser only for /browse,/qa,screenshots). The earlier "verified ldd + headless render" was an isolated test on a sibling already-extracted build (rev 1228) — it masked the rev-1208 install-path hang. Real fix = upstream: gstack bumps Playwright to a version that lists ubuntu26.04. Until then gstack's browser is unavailable on 26.04, install completes cleanly. See LRN-038 correction. -
2026-06-23 FINAL — RESOLVED (commit
3b8ffb1): gstack browser now works on Ubuntu 26.04. Two layers fixed: (1) bumped gstack's pinned Playwright 1.58.2 → 1.61 (bun add playwright@latestin the submodule; 1.61 ships a native ubuntu26.04 build — chromium rev 1228), automated in the installer (gstack_bump_playwright_if_unsupported, idempotent, OS-gated); (2)GSTACK_CHROMIUM_NO_SANDBOX=1to work around the AppArmor userns restriction (sysctl kernel.apparmor_restrict_unprivileged_userns=1), persisted to.bashrc+ installer Step 9 (sysctl-gated). Verified end-to-end:browse goto https://example.com→ "Navigated (200)". Caveat: the Playwright bump is a local submodule edit, reset bygit submodule update, re-applied by the next install. See BDR-029, LRN-040. -
2026-09-13 CORRECTION — the diagnosis above is wrong, the fix was right: the rev-1208 "downloads 100% then HANGS at extraction" was imputed to the
ubuntu24.04FALLBACK build. REFUTED on macOS arm64, where Playwright 1.58.2 has a NATIVE build and no fallback exists: the SAME hang reproduces with the SAME signature (39/333 files, every thread idle). The real variable is the NODE version — 1.58.2 deadlocks on a runtime newer than itself, platform-independently. The 1.58.2→1.61 bump did resolve 26.04, but for a reason not recorded here: it also cleared that Node incompatibility. See BLK-021 / LRN-150.
BLK-009 — user-level path-scoped rules don't load (#21858) — still broken in CC 2.1.190
- Date: 2026-06-25
- Friction: tried to scope a global rule to matching files via
paths:frontmatter in~/.claude/rules/<name>.md— the rule never injects, even when a matching file (*.probe) is read in a fresh session. Blocks any "load this guidance only for matching files" strategy at the user level. - Real cause: GitHub issue #21858 — user-level (
~/.claude/rules/) rules carryingpaths:frontmatter are not evaluated/injected; still unfixed in 2.1.190. (Project-level path-scoped rules not tested here.) - Probe method: 3-file probe —
_probe.md(paths: ["**/*.probe"], sentinelSENTINEL_USER_RULE_LOADED),_probe_ctl.md(NOpaths, control sentinelCONTROL_NOPATHS_LOADED),_probe_target.probe(target, read in a fresh session). Result: control sentinel PRESENT in session context, path-scoped sentinel ABSENT → the path-scoped rule did not load. Probe files removed after. - Status: upstream, open. Workaround: don't rely on user-level path-scoping → keep global guidance unconditional + COMPRESSED (BDR-031). Side-note: native auto-memory = "on" but writes nothing yet (fresh machine). Re-test on CC upgrades.
- 2026-07-06 UPDATE — RESOLVED: re-probed
paths:frontmatter lazy-load with fresh 3-file probe (**/*.blkprobeglob) — confirmed loading works at BOTH project-level AND user-level (~/.claude/rules/) rule dirs. #21858 no longer reproduces on current CC version. Status → resolved. Prior workaround (unconditional + compressed global CLAUDE.md, BDR-031) no longer forced by this bug — see LRN-103. - Reference: GitHub #21858. Linked to BDR-031, LRN-044, LRN-103.
BLK-010 — init-project scaffold + bootstrap README have no deterministic commit owner; worktree on unborn HEAD
-
Date: 2026-06-27
-
Friction: init-project scaffold (STEP 5 — CLAUDE.md, settings, config, entry points,
.gitignore,.env.example,.claude/) + bootstrap README (STEP 5b) never get an explicit commit. Pipeline's only commits = STEP 10b memory (helper) + STEP 8 per-task implementer commits. Whether scaffold/README land in a commit = emergent: implementer-prompt.md says only "4. Commit your work", scope undefined. Greenfield deeper: STEP 8subagent-driven-developmentrequiresusing-git-worktrees→git worktree add -bbranches from HEAD, but post-git initHEAD is UNBORN → add fails; the worktree skill has no unborn-HEAD path. -
Real cause: no deterministic commit step between
git init(STEP 5) and FINISH (STEP 11). scaffolder + doc-syncer both write-only (zerogit commit). implementer commit scope unspecified.using-git-worktreesassumes a born HEAD. -
Solution: open — own chantier (real technical weight: unborn HEAD + worktree). Candidate: explicit initial scaffold commit after STEP 5/5b before STEP 8, OR handle unborn HEAD in the worktree step. NOT cured by the doc-sync coupled chantier — that commits ONLY doc-sync's patched files and (correctly) excludes scaffold. Consequence: after doc-sync coupled, ship-feature fully fixed, init-project PARTIAL (doc-sync ok, scaffold/bootstrap still open).
-
Status: resolved (2026-06-29; working tree uncommitted — durable only at the claude repo commit, cf BLK-012). Was "open"; closed by the gitflow chantier — see note below.
-
Reference: discovered in doc-sync-coupled analysis (2026-06-27). Distinct from the doc-sync twin BDR-034. Sibling BLK-011. Surfaces via analyze-before-plan bookend on any init-project commit-flow work.
-
2026-06-29 — RESOLVED by the gitflow chantier:
gitflow_initfresh path (_gitflow_init_fresh: unborn HEAD →git symbolic-ref HEAD refs/heads/main→git add -A→ deterministic root commit →git branch develop) wired at init-project STEP 5f (after scaffold STEP 5 + README STEP 5b, before STEP 8 implement). Closes all 3 components: (a) scaffold+README get a deterministic commit owner = the root commit (git add -Astages whole tree; SKILL.md STEP 5f + lines 141/249-250 "scaffold commit owner … BLK-010 closed"); (b) root commit + develop make HEAD BORN before STEP 8 →gitflow start feature/worktree add -bnever hits unborn HEAD; (c) STEP 5f IS the deterministic commit step betweengit initand FINISH. Tested: gitflow-test.sh T2 "init fresh (BLK-010 root commit)" (root commit on main, socle IN root commit, hook tracked, tree clean). Residual (non-blocking): the genericusing-git-worktreesskill still has no unborn-HEAD path — now MOOT (HEAD always born by STEP 5f, never reached), not patched in the skill itself.
BLK-011 — init-project STEP 13 GSD post-FINISH creates ROADMAP.md → stranded doc
- Date: 2026-06-27
- Friction: init-project STEP 13 (GSD v2 init) runs post-FINISH (STEP 11).
gsd initcreates.gsd/+ROADMAP.md(a public doc). Created AFTER FINISH integrates → ROADMAP never in the merge/PR. Same PR-stranding class as the doc-sync twin, 3rd post-FINISH artifact. - Real cause: artifact-producing step ordered after FINISH (= BDR-034 class).
gsd initis a CLI mechanism distinct from doc-syncer; ROADMAP is sync-only for doc-syncer (never created by it, BDR-022 rules), so the doc-sync coupled chantier does not touch it. - Solution: open — separate thread. Candidate: reorder GSD before FINISH, or commit ROADMAP after
gsd init. Out of scope for doc-sync coupled (different mechanism). [historical candidates — NOT the route taken] - Resolution: RESOLVED 2026-06-29 — by REMOVAL, not by committing the orphan. init-project STEP 12 (speculative gsd auto-bootstrap) DELETED → ROADMAP/.gsd never created post-FINISH → orphan dissolves, no commit helper built. TRUE reason: auto-bootstrapping a heavy multi-session ENGINE the sole user doesn't use, AT project-creation, is bad on its own terms. NOT the initial framing "ROADMAP redundant with TODO" — that was wrong and would have aged badly: gsd ≫ roadmap (state machine / crash-recovery / cost / parallel / worktree), and TODO ≠ gsd ROADMAP (different altitude + consumer). Reasoning trace: BOTH initial premises (gsd=only-roadmap; TODO-redundant) REFUTED on read, yet conclusion A (remove STEP 12) held for the STRONGER reason — right answer, reason corrected before engraving. Deliberate gsd use KEPT (onboarder PHASE 6
/onboard add gsd, plugin-advisor reco, status-reporter.gsd/read, USAGEgsd init). Removed STEP 12 + header 12→11-step + 10c note + 4 USAGE refs; coherence sweep = zero dangling refs. LRN-072 - Status: resolved (init-project STEP 12 removed —
skills/init-project/SKILL.md; branch bugfix/blk-011-gsd-roadmap). Title says "STEP 13" — stale (was STEP 12 at removal per BDR-036 renumber); left per append-only. - Reference: discovered in doc-sync-coupled analysis (2026-06-27). Sibling BLK-010 + twin BDR-034.
BLK-012 — gitflow_init non-transactional: socle-commit failure swallowed → hook activated on partial run → re-run self-blocks
- Date: 2026-06-29
- Friction: migrating faunosteo,
migrate_local→gitflow_inithalf-applied TWICE. Run 1: master→main renamed, develop created, socle staged, but the socle commit died —Author identity unknown ... unable to auto-detect email address (got 'bchanot@bchanot-server.(none)')→ tree DIRTY, exit 1. Run 2 (recovery): socle commit BLOCKED by the gitflow hook itself (gitflow pre-commit: BLOCKED — direct commit on 'main'), yetinitreportedexit=0(a lie); main still at the old tip, socle uncommitted. - Real cause:
_gitflow_init_existingSWALLOWED the socle-commit failure —git diff --cached --quiet || git commitwith no propagation, and the function's last stmt (git branch develop) returned 0, masking the dead commit. Init CONTINUED past the failed commit → rangitflow_activate_hookthough the socle was never committed → re-run then self-blocks (commit on main blocked by the now-active hook). Design's "idempotent" + "never self-blocked" claims hold ONLY for a clean single run; a partial run breaks both. Fresh-repo path already propagated its failure (_gitflow_init_fresh); existing-repo path did not — the asymmetry was the bug. Trigger upstream of it: git identity UNSET (global unset; faunosteo had no local identity, though its own history usesBastien Chanot <git@bchanot.fr>). - Solution: (1) socle commit FATAL in
_gitflow_init_existing—if ! git diff --cached --quiet; then git commit … || { echo …; return 1; }; fi→ aborts BEFORE develop/hook-activation; (2) identity precheck at top ofgitflow_init(fail loud, no half-apply); (3) identity guard ingitflow-migrate.sh:migrate_local. Recovery: set faunosteo local identity → deactivate hook → delete premature develop → reinit (socle commits with hook inactive, as designed) → main==develop @ socle, tree clean, master renamed. Verified: shellcheck clean, 57/57 tests pass, hardened init on an identity-less repo aborts rc1 with ZERO mutation. - Status: resolved (
lib/gitflow.sh+lib/gitflow-migrate.sh, uncommitted working tree as of the gitflow chantier). - Reference: LRN-068 (transactional-bootstrap principle). Discovered mid gitflow-migration 2026-06-29. Sibling chantier learning LRN-067.
BLK-013 — make plugin Error 127: npm absent on apt-nodejs host
- Date: 2026-06-30
- Friction:
make plugin(→install-plugins.sh) aborts at Step 4 (gsd-pi):install-plugins.sh: line 425: npm: command not found→make: *** [Makefile:10: plugin] Error 127. Steps 5-10 never run, AND the post-Step-4 stray-dir cleanup (Step 8.5) never reached → the BDR-030/LRN-042 residual (stray$REPO/.agents/skills+$REPO/.claude/skills, promised "auto-cleaned nextmake plugin") silently persists run after run. SessionStart banner already showedgsd v2 ✗. - Real cause: Debian/apt
nodejspackage shipsnodeWITHOUTnpm(npm = separate apt pkg)./usr/bin/nodepresent (v22.22.1); its bindir has acorn/corepack/semver but NO npm/npx — npm genuinely uninstalled, not a PATH miss. install-plugins.sh Step 1 checksnode >=22but NEVER verifies npm — assumes npm ships with node (true for nodesource/brew/dnf paths, FALSE for plain apt). - Solution: corepack (ships with node) over apt npm (apt npm could pull a divergent 2nd node).
corepack enable --install-directory "$HOME/.local/bin" npm→ npm 11.18.0 shim, no sudo,~/.local/binalready on PATH. Thennpm config set prefix "$HOME/.local"— default prefix/usris root-owned →npm install -gwould EACCES;~/.localwritable + bins land on PATH. Persisted in~/.npmrc. Re-run → EXIT=0, Step 4 ✓ (gsd-pi@2.64.0), Step 8.5 ran (Removed stray repo-local skills dir: .agents/skills+.claude/skills). Caveat: gsd-pi DEPRECATED + postinstall scripts SKIPPED (npm 11allow-scripts) —gsd --version/--helpok, full provisioning would neednpm install -g --allow-scripts=gsd-pi,… gsd-pi. - Fix-forward: install-plugins.sh Step 1 should GUARANTEE npm on apt-
nodejshosts — detect missing npm +corepack enable npm(not just check node) → stops Error 127 recurring on any fresh apt machine. - Status: resolved (env-level: corepack shim + npm prefix; zero repo change). Fix-forward (script hardening) NOT built.
- Reference: discovered fixing
make plugin2026-06-30. Distinct from BLK-003 (macOS playwright hardcoded path) + the Playwright-chromiummake pluginfailure. Blocked residual = BDR-030/LRN-042. - Update 2026-07-01: fix-forward BUILT. install-plugins.sh Step 1 gained unconditional npm guard (
corepack enable npm→ distroinstall npmfallback → fatalexit 1), placed AFTER theNODE_OKshort-circuit so a node>=22-present-but-npm-absent host no longer skips it. Now fully resolved (env-level + script). shellcheck/bash -nclean; fresh-apt live validation still pending. Commit1f2c1cc, branchbugfix/install-plugins-npm-guard.
BLK-014 — make install aborts npm EEXIST when claude already present
- Date: 2026-07-01
- Friction:
make install→ install.sh Step 2npm install -g @anthropic-ai/claude-code@latestfails EEXIST on~/.local/bin/claudewhen claude already installed →else err→exit 1. Bootstrap not idempotent on Claude Code step; rest (auth, symlinks, plugins) never runs. - Real cause: claude installed via NATIVE installer, not npm —
~/.local/bin/claude= symlink →~/.local/share/claude/versions/<v>(npm ls -g @anthropic-ai/claude-code= empty;claude --version= 2.1.197). npm prefix~/.local(set by BLK-013) targets same~/.local/bin/claude→ npm won't clobber a bin it doesn't own → EEXIST. Channel conflict, not double-install. Step had NO presence guard, unlike RTK (install-plugins.sh:388) / GSD (:419) / claude check (:252). - Solution: install.sh — skip-if-present guard
command -v claude(mirror RTK/GSD), npm only fresh machine (elif). update-all.sh — channel-aware updater:npm ls -g→ npm-managed uses npm, else native usesclaude update(self-update). Nevernpm --force(would clobber native, break self-update). - Status: resolved. Fix
8dc4027, branchbugfix/install-claude-idempotent, pending merge validation. - Reference: BLK-013 npm prefix
~/.local= contributing factor (npm bin over native bin). install-plugins.sh already pointed to code.claude.com (native) — install.sh was the npm outlier. Fresh-machineelif npmbranch channel-consistency = open design question (potential BDR). Pattern → LRN-085. - Update 2026-07-01: MERGED
2393ca5(bugfix/install-claude-idempotent → develop), pushed — supersedes "pending merge validation". The open channel-consistency question is RESOLVED by BDR-046 (fresh install → native installer, npm dropped for claude); install.sh has noelif npmbranch → nothing left to trancher.
BLK-015 — gitflow_finish ignored its args, merged the CURRENT branch not the one asked
- Date: 2026-07-03
- Friction: audit 2026-07-02 —
gitflow.sh finish bugfix audit-bugsrun while checked out onfeature/audit-tokensmerged audit-tokens (LOT3), NOT audit-bugs. Final develop state identical (disjoint hunks) so no data damage, but the merge order was silently wrong. UX trap: the command LOOKS like it targetsbugfix/audit-bugs. - Real cause: CLI dispatch (
lib/gitflow.sh:257finish) gitflow_finish "$@") forwards args, but the function derived its source fromHEAD(git symbolic-ref) and NEVER read$1/$2→ the<type> <name>were silently dropped. Merge source = ambient state (checked-out branch), not the named target. Design intended finish to always operate on HEAD (human gate = "be on the branch"), but nothing enforced that passed args, if any, MATCH the branch you're on. - Solution:
gitflow_finish [<type> <name>]— args now an optional safety ASSERTION: present AND"$req_type/$req_name" != "$br"→ erroroperates on the current branch 'X', but you asked 'Y' — checkout 'Y' first, rc 2. No args = behavior unchanged (only real callerskills/gitflow/SKILL.md:36+ every test pass none → zero regression). +7 regression assertions (gitflow-test.shT12, numbered to dodge collision with reconcile's own T6c). - Status: resolved. Commit
d9fdd4c, branchbugfix/gitflow-finish-args. - Reference: journal 2026-07-02 (trap noted, not fixed) → fixed 2026-07-03. Pattern → LRN-089 (pass-through wrapper deriving target from ambient state = silent contract violation).
BLK-016 — rtk compression PATH-dead for 30 days: installer's own check can't see the tool shell
- Date: 2026-07-04
- Friction: user asked "is rtk installed + used right?". Measured (
rtk discover): 6 of 5070 Bash commands compressed over 30 days, ~460K tokens missed (grep ~144K, git status ~112K, ls ~92K…). Hook registered, integrity pin OK, registry broad — yet near-zero real usage. Nobody noticed: degradation was silent (LRN-047 class). - Real cause: two-layer. (1) cargo installs rtk into
~/.cargo/bin; hand-managed profile lost the PATH line (LRN-036 class) → Claude's TOOL shell can't resolvertk. (2) install-plugins.sh sources~/.cargo/envfor itself, so itscommand -v rtkcheck PASSES in the installer shell — validating an env the runtime never has. Hook survived via absolute-path substitution, but ONLY at string head (f0b7e89guard): every COMPOUND rewrite (dominant Claude style — echo separators,&&) was dropped by design. - Solution: bridge symlink
~/.cargo/bin/rtk→~/.local/bin/rtk(standard PATH). Immediate: created live, compound rewrites revived, proven in-session (bare grep →rtk grepoutput). Durable: install-plugins.sh STEP 3 idempotent self-repairing bridge, flip-tested 4/4 sandboxed HOME (LRN-096). Commite58037c(RC fix on release/1.0.0). - Status: resolved.
- Reference: lesson: a PATH-dependent hook must be verified in the TARGET shell, not the installer's (installer sourcing envs lies to its own checks); usage is MEASURED (
rtk discover), never assumed. Corroborates LRN-047 (silent degradation → measure) + LRN-036 (hand-managed profile drift); guard interplay LRN-089-adjacent (ambient-state assumptions). - backmerge: entry from release/1.0.0 (2b4e7401); the fix
e58037cwas ALSO missing from develop (rtk was live-broken on develop) — ported to develop 2026-07-08 (review remediation A3, commit follows) so this "resolved" is now true on develop too.
BLK-017 — Bing Webmaster API unusable for a multi-client agency (W2 deferred) — 2026-07-17
- Friction: W2 (
bingverb — free Bing query stats + index status + first-party backlinks) abandoned after 4 challenge rounds. User's model = client sites live on CLIENT Bing accounts. - Real cause: two viable-looking paths, both dead. (API KEY) is per-user not per-site (docs), but IS the account identity → one key per client account, exactly what the user feared; non-scoped, no expiry, passed in query string. (OAuth) is the right delegation model (like GSC) but a swamp: Redirect URI rejects ALL local forms (http/https/127.0.0.1 — user-tested); refresh tokens are ROTATED + single-use, self-described non-compliant with OAuth 2.0 → store rewrite every call, AND our parallel seo‖geo dispatch would race the rotation →
invalid_grant+ dead token; undocumented "Could not extract expected anti-forgery token" on refresh, unanswered on MS Q&A; docs contradict themselves on grant_type + token endpoint; no library. MS's own advisor recommends falling back to the API key. - Verified live: the Webmaster API itself is ALIVE (
GetUserSites?apikey=INVALID→ HTTP 400{"ErrorCode":3,"Message":"InvalidApiKey"}, 0.4s) — distinct from Bing SEARCH API (retired 2025-08-11). So the block is auth/model, not availability. - Status: open/deferred. REVIVAL: a client already on Bing adds the user as Read-Only → test in ~10 min whether one API key sees DELEGATED sites (undocumented, nobody knows). If yes → W2 is cheap+clean (one key, client-owned verification, revocable, read-only, zero OAuth). Value RAISED by BDR-071: GetUrlLinks is now the only free viable backlink source (first-party only).
BLK-018 — release-executor finish span blocked by permission classifier (human signal invisible to subagent) — 2026-07-20
- Friction: v1.3.1 release —
SPAN: finishdispatch denied at tool-permission layer: classifier flagged "Merge Without Review" (gitflow.sh finishin subagent transcript carries no explicit human merge signal). Executor correctly refused workaround, reported BLOCKED. v1.2.0/v1.3.0 same span passed → classifier behavior change, not skill regression. - Real cause: gitflow doctrine "finish only on explicit human signal" lives in DISPATCHER transcript (user ask + STEP 4 AskUserQuestion go); subagent transcript starts fresh → classifier sees consequential merge with zero authorization evidence. Structural: any human-gated action dispatched to a subagent loses its gate evidence.
- Solution (workaround): dispatcher ran
gitflow.sh finish+ tag inline after its own human gate — where the signal is real. Release completed clean (main648bc6e, tag v1.3.1). - Status: open. Candidate fixes: (a) quote gate evidence verbatim in span prompt — untested vs classifier; (b) move finish+tag span permanently inline in /release-candidate — keeps prep span dispatched, costs the sonnet pin on ~5 mechanical commands, cheap; (c) permission rule allowing subagent
gitflow.sh finish— weakens the guard, refused. Decide at next release. - Reference: skill
release-candidateSTEP 5. Pattern adjacent LRN-089 (ambient-state/context assumptions across boundaries). Journal 2026-07-20.
BLK-019 — notify-attention bell silent, toast OK (VS Code client default) — 2026-09-01
- Friction: hook fired, Windows toast arrived, native bell never audible. User heard only Windows toast sound. Looked like half-broken hook.
- Real cause: not hook. Toast proves full
terminalSequencereached terminal,\a\asits at head of that same string → BEL emitted. VS Code defaultsaccessibility.signals.terminalBellto"auto"= sound OFF unless screen reader active. - Solution:
"accessibility.signals.terminalBell": { "sound": "on" }in CLIENT-side user settings.json (c:/Users/<u>/AppData/Roaming/Code/User/). Unreachable from remote: real SSH remote, not WSL (no/mnt/c,/proc/versionno Microsoft). User applied, retest → both channels OK. - Status: resolved (per-client-machine, not repo-portable).
- Reference:
~/.claude/hooks/notify-attention.shheader already documented the setting; never applied. New client machine → bell mute again while toast works. Silent-degradation class LRN-047.
BLK-020 — notify-attention: both channels dead on one VS Code client — 2026-09-02
- Friction: client-side prereqs applied on Windows box (ext
wenbopan.vscode-terminal-osc-notifier+accessibility.signals.terminalBellsound:on), window reloaded. AskUserQuestion → nothing.idle_prompt90s wait → nothing. Direct write\a\a+ OSC 777 to claude own pty (/dev/pts/2) → nothing. Second client machine, same SSH server, same hook, same registries → both channels OK. - Server side cleared: hook dry-run emits
BELx2 + OSC 777 + STcorrectly,jqpresent, matcher coversidle_prompt, ext NOT wrongly installed remote-side. Not a hook bug — same class as BLK-019 (client default silently degrades). - Real cause: unresolved. Facts: claude runs under
dtach -c ~/.dtach/claude-190012; claude fd1 =/dev/pts/2(inner pty, dtach master side), REAL VS Code terminal =/dev/pts/1held by dtach client pid 742794.VSCODE_SHELL_INTEGRATIONunset this terminal; ext marketplace doc requires shell integration ON. BUT other working session (claude-154323) also runs under dtach → dtach alone insufficient explanation, weight shifts back to client-side. - Probes run: direct write to
/dev/pts/1(real VS Code pty, chain alive: bash pts/1 → dtach client 742794 S+ → master → claude pts/2) → no bell, no toast. Visible-marker injection both paths → user saw neither, BUT inconclusive: claude TUI repaints, injected text clobbered next frame. Only BEL is repaint-proof, and BEL stays silent. - Client settings verified by user: settings.json path correct (no VS Code profile indirection),
terminalBellsound on, ext installed + enabled local side. VS Code recent (server dirs 2026-08), so ≥ 1.93 ext requirement met. - Next probe: user opens FRESH VS Code integrated terminal (no dtach, no claude TUI) and runs
printf '\a\a\033]777;notify;Test;hello\033\\'. Isolates client renderer from claude/dtach path. Beep+toast there → fault in claude/dtach path; nothing → client-side, diff against working machine. - Fresh-terminal probe (decisive): user ran
printf '\a\a\033]777;notify;Test;hello\033\\'in NEW VS Code terminal → toast OK, bell still silent. Splits one symptom into TWO independent faults. - Fault A (toast in claude session): ext parses only terminals created AFTER its activation. Claude terminal pts/1 born 19:00, ext installed later same day → that terminal never hooked. Fix: restart claude in fresh terminal, or re-attach existing dtach session from one (
dtach -a ~/.dtach/<sess>; dtach broadcasts to multiple clients, no session loss). NOT a dtach filtering bug — earlier hypothesis wrong. - Fault B (bell): silent even in fresh terminal where toast works → not terminal path, VS Code audio side. Toast sound = Windows notification (works); bell = VS Code process audio (mute). Suspects: signal volume option, Windows volume mixer entry for Code, output device. Probe: palette
Help: List Signal Sounds→ Terminal Bell plays preview or not. - Fault A RESOLVED (verified 2026-09-02): re-attached session from fresh terminal (
dtach -a ~/.dtach/claude-190012, new client pts/3). Both sends toasted — one through session path (pts/2, dtach broadcast), one direct. Rule: ext hooks only terminals born AFTER its activation → install ext, THEN start/re-attach claude session. dtach broadcast means zero session loss. - Fault B still open: bell silent on every path. New signal: toasts arrive but user reports NO sound at all, while BLK-019 machine got audible Windows toast sound. Both audio channels dead + both visual channels fine → common factor is client audio output, not terminal stream. Suspects ranked: Windows per-app notification sound off for Code, system/app volume mixer mute, wrong output device,
accessibility.signalOptions.volume0. - Fault B ROOT CAUSE ISOLATED (2026-09-02): palette
Help: List Signal Sounds→ Terminal Bell preview plays NO sound, while Windows toast sound IS audible. Preview bypasses terminal, BEL, hook, dtach, ext entirely → VS Code renderer audio itself mute on this box. Toast sound emitted by Windows shell, not by Code → explains why one audio channel works and other does not. - Fix candidates (client, ranked): (1) Windows per-app volume mixer — Code muted/0, or per-app OUTPUT DEVICE pointing at disconnected device (mixer only lists app after it attempts playback → hit preview first, then open mixer); (2) VS Code
accessibility.signalOptions.volume= 0 kills all signals; (3) compare both against working machine. - Pragmatic out: toast already carries audible Windows sound → attention signal functional without bell. Bell is redundant channel, not blocker.
- Fault B RESOLVED (2026-09-03): cause = Windows per-app volume mixer, Code entry at 0. Toast audible throughout because Windows shell emits that sound, not Code → masked a plain app-volume mute. User set volume up → bell audible.
- Status: resolved (A: ext hooks only terminals born after activation → install ext THEN start/re-attach session; B: Code app volume 0 in Windows mixer).
- Lesson: two independent client faults presented as one symptom ("nothing works"). Splitting probe = run signal in FRESH terminal + play VS Code's own sound preview. Preview bypasses terminal/BEL/hook/dtach/ext → isolates renderer audio in one step. Do that FIRST next time, before any server-side archaeology.
- Reference: BLK-019 bell-only variant (resolved differently — setting alone insufficient here), LRN-145 terminalSequence-not-/dev/tty pattern. Silent-degradation class LRN-047.
BLK-021 — gstack Chromium install hangs forever on macOS (Playwright 1.58.2 x Node 26) — 2026-09-13
- Friction:
make pluginfroze at step 2/10. Log ends mid-Chromium install: 100% of 162.3 MiB downloaded, then nothing — no error, no timeout, no progress. Steps 3-10 (RTK, GSD, marketplace plugins, link.sh, shell profile) never ran. - Real cause: gstack's lockfile froze Playwright 1.58.2 (published 2026-02-06) → chromium rev 1208. Its extraction DEADLOCKS under Node 26.5.0: both processes (
playwright install+ childoopDownloadBrowserMain.js) fully idle — main thread inkevent, V8 AND libuv workers in__psynch_cvwait, 0% CPU, 2.5s CPU total — stuck at exactly 39/333 files. Zip fully downloaded and intact (170206961 B). NOT network, disk (396Gi free), Gatekeeper, quarantine (none set), nor Intego VirusBarrier — an AV block parks a thread inwrite; none was. PW 1.58.2 declaresengines: node >=18, so Node 26 is formally SUPPORTED: the incompatibility is undeclared upstream. - Proof (3-way, one variable moved): Node 26 x PW 1.58.2 = hang (2/2 reproductions); Node 22.23.1 x PW 1.58.2, same command + same rev = OK (336 files); Node 26 x PW 1.63.0 = OK (347 files, 360MB, Chrome 153.0.8010.12).
- Solution: bump gstack Playwright 1.58.2 → 1.63.0 (rev 1243). In-range, not a pin break —
package.jsondeclares"playwright": "^1.58.2"; onlybun.lockfroze it. Installer now pre-installs the browser under a deadline with bump-retry (BDR-088). The submodule edit stays LOCAL (reset bygit submodule update, re-applied by the next install — the BDR-029 pattern). - Status: resolved. Gate verified:
chromium.launch()→LAUNCH OK — Chromium 153.0.8010.12, rc 0. - Corrects upstream record: BLK-008 / LRN-038 imputed this exact signature on Ubuntu to the
ubuntu24.04FALLBACK build. REFUTED: macOS arm64 has a NATIVE 1.58.2 build, no fallback exists there, and the same hang reproduces with the same signature. The real variable is the NODE version. The 1.58.2→1.61 bump did fix 26.04, but for a reason not recorded there — it also cleared the Node incompatibility. - Cost of the wrong record: it sent the 2026-09-13 investigation hunting fallback builds first. A fix that WORKS can freeze a WRONG cause.
BLK-022 — macOS bash 3.2 + BSD userland: six fail-OPEN or silent-no-op defects — 2026-09-13
- Friction: repo moved to macOS (Darwin 25.6, arm64).
make testred across 5 suites, and several guards PASSED while doing nothing at all. - Real cause:
/bin/bashis 3.2.57 and#!/usr/bin/env bashresolves to it (no Homebrew bash on PATH). Every failure is silent:${1,,}(bash 4.0+) inlib/url-guard.sh→ "bad substitution", subshell exits 1 = "not local" → the SSRF guard returned rc 0 for localhost, 127.x, 10.x, 192.168.x, 172.16-31.x, 169.254.169.254 and metadata.google.internal. FAIL-OPEN on every Mac;url-guard.test.shrecorded it as 13x "got[0] want[2]".mapfilein the 3 surgical-commit helpers → empty arrays → scope guards fail-OPEN, commits degrade to "nothing pending — no-op" while reporting success.declare -Ainhooks/session-start.sh→ every plugin cost read 0 → the >50%-budget warning could never fire.timeout(coreutils, absent from a stock macOS) inlib/gates.sh→ exit 127 → EVERY criterion recorded NOT-MET whatever the check did.- GNU
sed -ix3 ininstall-plugins.sh→ BSD sed errors → aborts the installer underset -euo pipefail. - Test-side GNU-isms:
touch -d, BSDwc -lpadding (got[ 48] want[48]),/bin/grep(does not exist on macOS),stat -c,sed -i+\nin the replacement.
- Solution:
_read_lines_into(portable mapfile),shopt -s nocasematch(bash 3.1+, keeps the no-fork property),casefor plugin costs, resolved timeout binary + pure-bash fallback,_sed_inplace+ awk. Split over 5 branches. - Status: resolved. Every suite 0 failures except
gitflow-test.sh(13 failures, PRE-EXISTING and unattributed: 92/14 on pristine develop vs 93/13 after — nothing worsened, one case better). shellcheck 1 finding before and after (pre-existing SC2016). - Bonus found while porting: the orphan-comment cleanup
{N; /^\n$/d;}ininstall-plugins.shwas a no-op on EVERY platform — afterNthe pattern space starts with '#', so the^\n$anchor pair never applied. Rewritten in awk and tested.