v0.9.1
Fixed
-
install.sh/bootstrap.shAPI rate-limit fallback — Both scripts calledapi.github.com/repos/$REPO/releases/latestto resolve the latest release. The unauthenticated GitHub REST endpoint allows only 60 requests/hour/IP, so on shared IPs (corporate proxies, VPNs, NAT pools) the call returned HTTP 403 even when releases existed. The previous fallback path treated empty API responses as "no releases at all" and then re-hit the same rate-limited endpoint frominstall.sh, producing a contradictoryError: Could not determine version. Use bootstrap.sh to install:message to users who had already usedbootstrap.sh. Added a two-stage resolver in both scripts:api.github.com(canonical) →raw.githubusercontent.com/$REPO/main/VERSION(CDN fallback, not subject to API rate limits, kept in sync by every/release-ispartorun) → install-from-main-unverified (last resort). Affected users on rate-limited IPs now see the upgrade succeed transparently. -
install.sh:48version_lt()BSD sort portability — The semver comparator usedsort -V, a feature only available in BSDsortfrom macOS Big Sur (11.0, 2020) onward. Replaced with pure-bash field-by-field MAJOR.MINOR.PATCH numeric comparison plus lexicographic pre-release tail; preserves the existing semver-regression guard (e.g.0.10.0 > 0.9.0) without depending onsortfeature levels. Closes Backlog FR-51. -
lib/patch-settings.pyportable hook command + equivalence-based dedup —install.shexpanded$HOMEat install time when composing the Bash hook command written to~/.claude/settings.json, baking the installer's user-specific absolute path (/Users/<install-time-user>/.isparto/...) into the registered command string. When the settings file was shared across Macs (iCloud Drive symlink, scp, Migration Assistant), the absolute path was broken on the receiving Mac and producedNo such file or directoryhook noise on every Bash tool invocation. Compounded bylib/patch-settings.py's string-exactcommand == hook_cmddedup (different absolute paths looked distinct → both kept) and its cleanup-only-for-WORKFLOW_MATCHERSscope (theBashmatcher's stale entries were never audited), causing accumulation across reinstalls. Three-layer fix:install.sh:667now writes a single-quoted literal'if [ -f "$HOME/.isparto/..." ]; then bash "$HOME/.isparto/..."; fi'that resolves$HOMEat hook-execution time rather than install time;lib/patch-settings.pyadds an_is_pre_tool_check_hook(cmd)substring helper and rewritespatch_user'sBash-matcher dedup to be semantic-equivalence based (any command containingpre-tool-check.shis treated as a Process Observer hook registration);patch_usernow strips all stale entries and installs exactly one canonical conditional form, preserving non-pre-tool-check.shhooks unchanged. Idempotent — repeatedpatch-userinvocations after migration produce no file change. Cross-machine deployment note: users whose~/.claude/settings.jsonis shared across multiple Macs (iCloud / Dropbox / symlinks) must run~/.isparto/install.sh --upgradeon EACH Mac before the file converges to a single canonical entry; otherwise the second machine's oldinstall.shwould re-introduce a broken absolute-path entry on its next upgrade and sync it back. Closes Backlog FR-52. -
Process Observer git-push guard no longer spans compound-command segments —
git push -u origin <feature-branch> && git checkout main ...is now allowed as a feature-branch push followed by a separate branch switch, while real direct pushes such asgit push -u origin mainandgit push origin HEAD:mainremain blocked. Added a--self-testflag tohooks/process-observer/scripts/pre-tool-check.shwith 6 fixtures (3 should-match + 3 should-not-match) covering compound commands, quoted PR-body mentions, and force pushes.