From e76033b3c907b9b95c1ca6e49b8f69a27e5101d7 Mon Sep 17 00:00:00 2001 From: Bruno Azoulay Date: Mon, 12 Oct 2026 21:39:09 +0200 Subject: [PATCH 1/2] fix(installer): keep the shared harness on latest - installer refreshes @fusengine/harness on every run (bun update, falling back to bun install) via new services/harness-vendor.ts, fail-open - hook.sh wrappers (21 plugins + plugin-runtime): comment no longer claims auto-upgrade and names the upgrade path (re-run the installer) - 6 tests for harness vendoring; installation docs updated --- .cursor-plugin/plugin-runtime/hook.sh | 10 +- .../plugins/core-guards/scripts/hook.sh | 10 +- .../plugins/fuse-ai-pilot/scripts/hook.sh | 10 +- .../plugins/fuse-cartographer/scripts/hook.sh | 10 +- .../plugins/fuse-changelog/scripts/hook.sh | 10 +- .../plugins/fuse-design/scripts/hook.sh | 10 +- .../plugins/fuse-go/scripts/hook.sh | 10 +- .../plugins/fuse-laravel/scripts/hook.sh | 10 +- .../plugins/fuse-lessons/scripts/hook.sh | 10 +- .../plugins/fuse-nextjs/scripts/hook.sh | 10 +- .../plugins/fuse-php/scripts/hook.sh | 10 +- .../plugins/fuse-react/scripts/hook.sh | 10 +- .../plugins/fuse-rules/scripts/hook.sh | 10 +- .../plugins/fuse-rust/scripts/hook.sh | 10 +- .../plugins/fuse-security/scripts/hook.sh | 10 +- .../plugins/fuse-seo/scripts/hook.sh | 10 +- .../plugins/fuse-shadcn-ui/scripts/hook.sh | 10 +- .../plugins/fuse-solid/scripts/hook.sh | 10 +- .../fuse-swift-apple-expert/scripts/hook.sh | 10 +- .../plugins/fuse-tailwindcss/scripts/hook.sh | 10 +- .../fuse-tanstack-start/scripts/hook.sh | 10 +- .../plugins/fuse-typescript/scripts/hook.sh | 10 +- .cursor-plugin/scripts/install-hooks.ts | 1 + .../src/__tests__/harness-vendor.test.ts | 96 +++++++++++++++++++ .../scripts/src/interfaces/harness-vendor.ts | 20 ++++ .../scripts/src/interfaces/setup.ts | 6 ++ .../scripts/src/services/harness-vendor.ts | 51 ++++++++++ .../scripts/src/services/setup-runner.ts | 15 +++ .../scripts/src/utils/bun-install-runner.ts | 28 ++++-- docs/getting-started/installation.md | 15 ++- 30 files changed, 378 insertions(+), 74 deletions(-) create mode 100644 .cursor-plugin/scripts/src/__tests__/harness-vendor.test.ts create mode 100644 .cursor-plugin/scripts/src/interfaces/harness-vendor.ts create mode 100644 .cursor-plugin/scripts/src/services/harness-vendor.ts diff --git a/.cursor-plugin/plugin-runtime/hook.sh b/.cursor-plugin/plugin-runtime/hook.sh index cff4a47..3c88b14 100644 --- a/.cursor-plugin/plugin-runtime/hook.sh +++ b/.cursor-plugin/plugin-runtime/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/core-guards/scripts/hook.sh b/.cursor-plugin/plugins/core-guards/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/core-guards/scripts/hook.sh +++ b/.cursor-plugin/plugins/core-guards/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-ai-pilot/scripts/hook.sh b/.cursor-plugin/plugins/fuse-ai-pilot/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-ai-pilot/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-ai-pilot/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-cartographer/scripts/hook.sh b/.cursor-plugin/plugins/fuse-cartographer/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-cartographer/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-cartographer/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-changelog/scripts/hook.sh b/.cursor-plugin/plugins/fuse-changelog/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-changelog/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-changelog/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-design/scripts/hook.sh b/.cursor-plugin/plugins/fuse-design/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-design/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-design/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-go/scripts/hook.sh b/.cursor-plugin/plugins/fuse-go/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-go/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-go/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-laravel/scripts/hook.sh b/.cursor-plugin/plugins/fuse-laravel/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-laravel/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-laravel/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-lessons/scripts/hook.sh b/.cursor-plugin/plugins/fuse-lessons/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-lessons/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-lessons/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-nextjs/scripts/hook.sh b/.cursor-plugin/plugins/fuse-nextjs/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-nextjs/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-nextjs/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-php/scripts/hook.sh b/.cursor-plugin/plugins/fuse-php/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-php/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-php/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-react/scripts/hook.sh b/.cursor-plugin/plugins/fuse-react/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-react/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-react/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-rules/scripts/hook.sh b/.cursor-plugin/plugins/fuse-rules/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-rules/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-rules/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-rust/scripts/hook.sh b/.cursor-plugin/plugins/fuse-rust/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-rust/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-rust/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-security/scripts/hook.sh b/.cursor-plugin/plugins/fuse-security/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-security/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-security/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-seo/scripts/hook.sh b/.cursor-plugin/plugins/fuse-seo/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-seo/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-seo/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-shadcn-ui/scripts/hook.sh b/.cursor-plugin/plugins/fuse-shadcn-ui/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-shadcn-ui/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-shadcn-ui/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-solid/scripts/hook.sh b/.cursor-plugin/plugins/fuse-solid/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-solid/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-solid/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-swift-apple-expert/scripts/hook.sh b/.cursor-plugin/plugins/fuse-swift-apple-expert/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-swift-apple-expert/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-swift-apple-expert/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-tailwindcss/scripts/hook.sh b/.cursor-plugin/plugins/fuse-tailwindcss/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-tailwindcss/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-tailwindcss/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-tanstack-start/scripts/hook.sh b/.cursor-plugin/plugins/fuse-tanstack-start/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-tanstack-start/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-tanstack-start/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/plugins/fuse-typescript/scripts/hook.sh b/.cursor-plugin/plugins/fuse-typescript/scripts/hook.sh index cff4a47..3c88b14 100755 --- a/.cursor-plugin/plugins/fuse-typescript/scripts/hook.sh +++ b/.cursor-plugin/plugins/fuse-typescript/scripts/hook.sh @@ -7,9 +7,13 @@ # 2. a self-heal `bun install` of that same shared directory, once # 3. `npx` on latest (last resort, network) # -# Always tracks the LATEST published harness: the vendored manifest uses the -# `latest` dist-tag and the npx fallback resolves it too, so a new release is -# picked up without editing 21 wrappers. +# Installs the LATEST published harness the first time (the manifest uses the +# `latest` dist-tag, and so does the npx fallback), so no wrapper needs editing +# per release. It does NOT upgrade an existing install: the fast path runs the +# vendored bin as is, and rewriting it in place while up to 62 hooks load it +# could crash a guard mid-run (hooks fail open). The upgrade path is the +# installer (`install.sh` runs `bun update @fusengine/harness` on every run) or, +# by hand: `cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. # # Resolution is relative to THIS file, never to the caller's cwd. Always exits 0 # on its own failures: Cursor fails hooks open, and a broken guard must never diff --git a/.cursor-plugin/scripts/install-hooks.ts b/.cursor-plugin/scripts/install-hooks.ts index f574f93..35ac3a0 100755 --- a/.cursor-plugin/scripts/install-hooks.ts +++ b/.cursor-plugin/scripts/install-hooks.ts @@ -26,6 +26,7 @@ const PATHS = { marketplace: join(HOME, ".cursor"), pluginsDir: join(HOME, ".cursor/plugins/local"), loaderSrc: join(SCRIPT_DIR, "hooks-loader.ts"), + harnessManifestSrc: join(PROJECT_ROOT, "harness/package.json"), cursorMdSrc: join( PROJECT_ROOT, "plugins/fuse-rules/templates/CLAUDE.md.template", diff --git a/.cursor-plugin/scripts/src/__tests__/harness-vendor.test.ts b/.cursor-plugin/scripts/src/__tests__/harness-vendor.test.ts new file mode 100644 index 0000000..339e326 --- /dev/null +++ b/.cursor-plugin/scripts/src/__tests__/harness-vendor.test.ts @@ -0,0 +1,96 @@ +/** + * Tests for vendorHarness: the installer must always refresh the shared + * `@fusengine/harness` to the latest release, never leave a pinned spec, and + * never throw. The real `bun` is never invoked — every test injects a fake. + */ +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import type { BunRunFn } from "../interfaces/harness-vendor"; +import { vendorHarness } from "../services/harness-vendor"; + +const MANIFEST = `${JSON.stringify({ + name: "@fusengine/cursor-harness", + private: true, + dependencies: { "@fusengine/harness": "latest" }, +})}\n`; +const BIN = "node_modules/@fusengine/harness/dist/cli/bin.mjs"; + +let root: string; +let manifestSrc: string; +let controlRoot: string; + +/** Fake runner recording every call and answering with scripted exit codes. */ +function fakeRun(codes: number[]): { run: BunRunFn; calls: string[][] } { + const calls: string[][] = []; + const run: BunRunFn = async (_cwd, args) => { + calls.push(args); + return codes[calls.length - 1] ?? 0; + }; + return { run, calls }; +} + +/** Simulate an earlier install: pinned manifest, lockfile and vendored bin. */ +function seedPinnedInstall(): void { + mkdirSync(join(controlRoot, "node_modules/@fusengine/harness/dist/cli"), { recursive: true }); + writeFileSync(join(controlRoot, BIN), "// old bin"); + writeFileSync(join(controlRoot, "bun.lock"), "{}"); + writeFileSync( + join(controlRoot, "package.json"), + '{"dependencies":{"@fusengine/harness":"0.1.100"}}', + ); +} + +beforeEach(() => { + root = mkdtempSync(join(tmpdir(), "fusengine-vendor-")); + manifestSrc = join(root, "manifest.json"); + controlRoot = join(root, ".fusengine-global"); + writeFileSync(manifestSrc, MANIFEST); +}); + +afterEach(() => rmSync(root, { recursive: true, force: true })); + +describe("vendorHarness", () => { + test("fresh machine: writes the `latest` manifest and runs bun install", async () => { + const { run, calls } = fakeRun([0]); + expect(await vendorHarness({ manifestSrc, controlRoot, run })).toBe("installed"); + expect(readFileSync(join(controlRoot, "package.json"), "utf8")).toBe(MANIFEST); + expect(calls).toEqual([["install", "--silent"]]); + }); + + test("pinned earlier install: manifest reset to `latest`, then bun update of the harness only", async () => { + seedPinnedInstall(); + const { run, calls } = fakeRun([0]); + expect(await vendorHarness({ manifestSrc, controlRoot, run })).toBe("updated"); + expect(readFileSync(join(controlRoot, "package.json"), "utf8")).toBe(MANIFEST); + expect(calls).toEqual([["update", "@fusengine/harness", "--silent"]]); + }); + + test("update fails (package absent from the lock): falls back to bun install", async () => { + seedPinnedInstall(); + const { run, calls } = fakeRun([1, 0]); + expect(await vendorHarness({ manifestSrc, controlRoot, run })).toBe("installed"); + expect(calls.map((c) => c[0])).toEqual(["update", "install"]); + }); + + test("every bun run fails: reports failed, does not throw", async () => { + seedPinnedInstall(); + const { run } = fakeRun([1, 1]); + expect(await vendorHarness({ manifestSrc, controlRoot, run })).toBe("failed"); + }); + + test("runner throws: fail-open, reports failed", async () => { + const run: BunRunFn = async () => { + throw new Error("spawn failed"); + }; + expect(await vendorHarness({ manifestSrc, controlRoot, run })).toBe("failed"); + }); + + test("missing repo manifest: skipped, bun never called, nothing written", async () => { + rmSync(manifestSrc); + const { run, calls } = fakeRun([0]); + expect(await vendorHarness({ manifestSrc, controlRoot, run })).toBe("skipped"); + expect(calls).toEqual([]); + }); +}); diff --git a/.cursor-plugin/scripts/src/interfaces/harness-vendor.ts b/.cursor-plugin/scripts/src/interfaces/harness-vendor.ts new file mode 100644 index 0000000..27a15df --- /dev/null +++ b/.cursor-plugin/scripts/src/interfaces/harness-vendor.ts @@ -0,0 +1,20 @@ +/** + * Shared-harness vendoring interfaces. + * @description SRP: types for the installer's `@fusengine/harness` refresh only. + */ + +/** Outcome of one vendoring run. `failed` is fail-open: the installer keeps going. */ +export type HarnessVendorStatus = "installed" | "updated" | "skipped" | "failed"; + +/** Injectable `bun` runner — returns the exit code; tests fake it (no network). */ +export type BunRunFn = (cwd: string, args: string[], timeoutMs: number) => Promise; + +/** Inputs of {@link vendorHarness}. */ +export interface HarnessVendorOptions { + /** Absolute path of the repo manifest (`.cursor-plugin/harness/package.json`). */ + manifestSrc: string; + /** Absolute shared install dir (`~/.cursor/.fusengine-global`). */ + controlRoot: string; + /** Bun runner; defaults to the real `bun` binary. */ + run?: BunRunFn; +} diff --git a/.cursor-plugin/scripts/src/interfaces/setup.ts b/.cursor-plugin/scripts/src/interfaces/setup.ts index 919a4bd..e6ece33 100644 --- a/.cursor-plugin/scripts/src/interfaces/setup.ts +++ b/.cursor-plugin/scripts/src/interfaces/setup.ts @@ -15,4 +15,10 @@ export interface SetupPaths { * with no intermediate `plugins/` level like Claude Code's marketplace. */ pluginsDir: string; + /** + * Repo manifest of the shared harness (`.cursor-plugin/harness/package.json`, + * spec `latest`). Copied to `~/.cursor/.fusengine-global/package.json` and + * refreshed on every install run. + */ + harnessManifestSrc: string; } diff --git a/.cursor-plugin/scripts/src/services/harness-vendor.ts b/.cursor-plugin/scripts/src/services/harness-vendor.ts new file mode 100644 index 0000000..8ef7570 --- /dev/null +++ b/.cursor-plugin/scripts/src/services/harness-vendor.ts @@ -0,0 +1,51 @@ +/** + * Shared-harness vendoring: keep `~/.cursor/.fusengine-global/node_modules` + * on the latest published `@fusengine/harness` on every installer run. + * @description SRP: sync the repo manifest into the control root, then move the + * install to the newest release. The spec is always the manifest's dist-tag + * (`latest`), never a pinned version; `bun update` keeps a dist-tag as written + * and only advances `bun.lock` (https://bun.sh/docs/pm/cli/update). + */ +import { copyFileSync, existsSync, mkdirSync } from "node:fs"; +import { join } from "node:path"; +import type { + HarnessVendorOptions, + HarnessVendorStatus, +} from "../interfaces/harness-vendor"; +import { runBun } from "../utils/bun-install-runner"; + +const HARNESS_PACKAGE = "@fusengine/harness"; +const HARNESS_BIN = `node_modules/${HARNESS_PACKAGE}/dist/cli/bin.mjs`; +const VENDOR_TIMEOUT_MS = 120_000; + +/** + * Write the repo manifest to the control root and refresh the harness to the + * latest release. Fail-open: never throws, a failure only returns `"failed"` + * so the rest of the install proceeds (the hook wrappers self-heal). + * + * - lockfile + vendored bin present → `bun update @fusengine/harness` + * (a pinned lock from an earlier installer moves to the newest release); + * if that errors (package absent from the lock) it falls back to a full install + * - otherwise → `bun install` + * + * @param options - Manifest source, control root and optional bun runner + * @returns `installed`, `updated`, `skipped` (no manifest) or `failed` + */ +export async function vendorHarness(options: HarnessVendorOptions): Promise { + const { manifestSrc, controlRoot, run = runBun } = options; + if (!existsSync(manifestSrc)) return "skipped"; + try { + mkdirSync(controlRoot, { recursive: true }); + copyFileSync(manifestSrc, join(controlRoot, "package.json")); + const vendored = + existsSync(join(controlRoot, "bun.lock")) && existsSync(join(controlRoot, HARNESS_BIN)); + if (vendored) { + const updateArgs = ["update", HARNESS_PACKAGE, "--silent"]; + if ((await run(controlRoot, updateArgs, VENDOR_TIMEOUT_MS)) === 0) return "updated"; + } + const code = await run(controlRoot, ["install", "--silent"], VENDOR_TIMEOUT_MS); + return code === 0 ? "installed" : "failed"; + } catch { + return "failed"; + } +} diff --git a/.cursor-plugin/scripts/src/services/setup-runner.ts b/.cursor-plugin/scripts/src/services/setup-runner.ts index e9462fb..346c0da 100644 --- a/.cursor-plugin/scripts/src/services/setup-runner.ts +++ b/.cursor-plugin/scripts/src/services/setup-runner.ts @@ -10,6 +10,7 @@ import { installBrowserBinary } from "./browser-binary"; import { setHarnessRefs } from "./harness-env"; import { resolveHomeInHooks } from "./harness-path-resolver"; import { promptHarnessGates } from "./harness-gates"; +import { vendorHarness } from "./harness-vendor"; import { promptHarnessTuning } from "./harness-tuning"; import { promptEnforceTtl } from "./enforce-ttl"; import { promptSolidMaxLines } from "./solid-lines"; @@ -60,6 +61,20 @@ export async function runSetup( // `installClaudeMd` stays available for the project scope. await installDeps(pluginsDir); + // Shared harness: the hook.sh wrappers run whatever is vendored and never + // upgrade it, so THIS is the upgrade path — every run moves it to the latest + // published release (spec `latest`, never a pinned version). Fail-open. + const vendorSpinner = p.spinner(); + vendorSpinner.start("Refreshing shared @fusengine/harness to latest..."); + const vendored = await vendorHarness({ + manifestSrc: paths.harnessManifestSrc, + controlRoot: join(paths.marketplace, ".fusengine-global"), + }); + vendorSpinner.stop(`Shared harness: ${vendored}`); + if (vendored === "failed") { + p.log.warn("Harness refresh failed — the hook wrappers keep the vendored copy (or self-heal)."); + } + const homeSpinner = p.spinner(); homeSpinner.start("Resolving $HOME in hook paths..."); const resolved = await resolveHomeInHooks(pluginsDir); diff --git a/.cursor-plugin/scripts/src/utils/bun-install-runner.ts b/.cursor-plugin/scripts/src/utils/bun-install-runner.ts index 182901c..e9ae5b5 100644 --- a/.cursor-plugin/scripts/src/utils/bun-install-runner.ts +++ b/.cursor-plugin/scripts/src/utils/bun-install-runner.ts @@ -3,22 +3,36 @@ * no node_modules import), so it works even when node_modules is entirely gone. */ import type { InstallFn } from "../interfaces/ensure-deps"; +import type { BunRunFn } from "../interfaces/harness-vendor"; /** - * Run `bun install --silent` in `cwd`, hard-killing it after `timeoutMs`. - * Never throws on timeout/non-zero exit: a failed or slow install just leaves - * the caller's presence marker missing, and the next hook invocation retries. + * Run the current `bun` binary with `args` in `cwd`, hard-killing it after + * `timeoutMs`. Never throws on timeout/non-zero exit: the exit code is returned. * - * @param cwd - Directory holding the package.json to install + * @param cwd - Directory the command runs in + * @param args - Arguments passed to bun (e.g. `["install", "--silent"]`) * @param timeoutMs - Hard kill timeout in milliseconds + * @returns The process exit code (non-zero when killed) */ -export const runBunInstall: InstallFn = async (cwd, timeoutMs) => { - const proc = Bun.spawn([process.execPath, "install", "--silent"], { +export const runBun: BunRunFn = async (cwd, args, timeoutMs) => { + const proc = Bun.spawn([process.execPath, ...args], { cwd, stdout: "ignore", stderr: "ignore", timeout: timeoutMs, killSignal: "SIGKILL", }); - await proc.exited; + return proc.exited; +}; + +/** + * Run `bun install --silent` in `cwd`, hard-killing it after `timeoutMs`. + * Never throws on timeout/non-zero exit: a failed or slow install just leaves + * the caller's presence marker missing, and the next hook invocation retries. + * + * @param cwd - Directory holding the package.json to install + * @param timeoutMs - Hard kill timeout in milliseconds + */ +export const runBunInstall: InstallFn = async (cwd, timeoutMs) => { + await runBun(cwd, ["install", "--silent"], timeoutMs); }; diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index e50d2d0..9684c06 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -70,7 +70,10 @@ runtime-unverified until executed on Windows. ├── rules/fuse-global.mdc └── .fusengine-global/ ├── .managed-by-fusengine - └── receipt.json + ├── receipt.json + ├── package.json # spec "latest", copied from .cursor-plugin/harness + ├── bun.lock + └── node_modules/@fusengine/harness ``` The bundled installer copies each repository plugin as an immediate child of @@ -78,6 +81,16 @@ The bundled installer copies each repository plugin as an immediate child of Existing foreign plugin directories are preserved. Reinstall refreshes only intact installer-owned copies and refuses modified or colliding targets. +### Shared harness upgrades + +Every `install.sh` run rewrites `.fusengine-global/package.json` from the repo +manifest (`"@fusengine/harness": "latest"`, never a pinned version) and runs +`bun update @fusengine/harness`, which keeps the dist-tag and advances +`bun.lock` to the newest release. The `hook.sh` wrappers only install the +harness when it is missing; they never upgrade it. Without re-running the +installer, upgrade by hand with +`cd ~/.cursor/.fusengine-global && bun update @fusengine/harness`. + ## Project installation layout ```text From 6e2de98c8b81c24bc2e18fe2768f7d7d5c291e6d Mon Sep 17 00:00:00 2001 From: Bruno Azoulay Date: Mon, 12 Oct 2026 21:40:20 +0200 Subject: [PATCH 2/2] chore: bump marketplace and CHANGELOG to 0.1.8 --- .cursor-plugin/marketplace.json | 44 +++++++++---------- .../core-guards/.cursor-plugin/plugin.json | 2 +- .../fuse-ai-pilot/.cursor-plugin/plugin.json | 2 +- .../.cursor-plugin/plugin.json | 2 +- .../fuse-changelog/.cursor-plugin/plugin.json | 2 +- .../fuse-design/.cursor-plugin/plugin.json | 2 +- .../fuse-go/.cursor-plugin/plugin.json | 2 +- .../fuse-laravel/.cursor-plugin/plugin.json | 2 +- .../fuse-lessons/.cursor-plugin/plugin.json | 2 +- .../fuse-nextjs/.cursor-plugin/plugin.json | 2 +- .../fuse-php/.cursor-plugin/plugin.json | 2 +- .../fuse-react/.cursor-plugin/plugin.json | 2 +- .../fuse-rules/.cursor-plugin/plugin.json | 2 +- .../fuse-rust/.cursor-plugin/plugin.json | 2 +- .../fuse-security/.cursor-plugin/plugin.json | 2 +- .../fuse-seo/.cursor-plugin/plugin.json | 2 +- .../fuse-shadcn-ui/.cursor-plugin/plugin.json | 2 +- .../fuse-solid/.cursor-plugin/plugin.json | 2 +- .../.cursor-plugin/plugin.json | 2 +- .../.cursor-plugin/plugin.json | 2 +- .../.cursor-plugin/plugin.json | 2 +- .../.cursor-plugin/plugin.json | 2 +- CHANGELOG.md | 17 +++++++ README.md | 2 +- 24 files changed, 61 insertions(+), 44 deletions(-) diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 5b75c29..41cf5e0 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -6,14 +6,14 @@ }, "metadata": { "description": "Professional Cursor plugins with APEX workflow, SOLID principles, and expert development agents for Next.js, Laravel, Swift, Tailwind CSS, and more", - "version": "0.1.7" + "version": "0.1.8" }, "plugins": [ { "name": "core-guards", "source": ".cursor-plugin/plugins/core-guards", "description": "Core security guards (git, install, security) and SOLID enforcement hooks", - "version": "1.1.38", + "version": "1.1.39", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -36,7 +36,7 @@ "name": "fuse-ai-pilot", "source": ".cursor-plugin/plugins/fuse-ai-pilot", "description": "AI Pilot workflow agents: sniper (code quality), research-expert, explore-codebase, websearch", - "version": "1.2.43", + "version": "1.2.44", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -81,7 +81,7 @@ "name": "fuse-cartographer", "source": ".cursor-plugin/plugins/fuse-cartographer", "description": "Generates indented markdown maps of the plugin ecosystem for agent navigation", - "version": "1.0.13", + "version": "1.0.14", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -102,7 +102,7 @@ "name": "fuse-changelog", "source": ".cursor-plugin/plugins/fuse-changelog", "description": "Claude Code update watcher: changelog tracking, breaking changes detection, community pulse via Exa, plugin compatibility analysis", - "version": "1.0.15", + "version": "1.0.16", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -145,7 +145,7 @@ "name": "fuse-design", "source": ".cursor-plugin/plugins/fuse-design", "description": "Design Director for websites, web apps, iOS, and Android. Generates HTML/CSS directly (Gemini Design MCP, Magic/21st.dev, and shadcn MCP are optional). iOS/Android produce tokens + a device-framed mockup + a handoff spec, never SwiftUI/Compose. Design method, design system tokens, motion, UX copy, and a deterministic design-review gate. Anti-AI-Slop, WCAG 2.2.", - "version": "2.2.10", + "version": "2.2.11", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -181,7 +181,7 @@ "name": "fuse-go", "source": ".cursor-plugin/plugins/fuse-go", "description": "Expert Go 1.26+ — idioms, concurrency, backend services, cargo-grade tooling (golangci-lint v2, govulncheck), with SOLID principles", - "version": "1.0.7", + "version": "1.0.8", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -207,7 +207,7 @@ "name": "fuse-laravel", "source": ".cursor-plugin/plugins/fuse-laravel", "description": "Expert Laravel 13 + PHP 8.3+ with SOLID principles, first-class PHP Attributes, Laravel AI SDK, JSON:API Resources, native vector search (pgvector), Eloquent, Livewire, queues with routing, and comprehensive documentation", - "version": "1.2.8", + "version": "1.2.9", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -229,7 +229,7 @@ "name": "fuse-lessons", "source": ".cursor-plugin/plugins/fuse-lessons", "description": "Project memory: writes compact 'never reproduce' lessons to MEMORY/LESSON.md on finish, force-reads them at session/subagent start.", - "version": "1.0.7", + "version": "1.0.8", "author": { "name": "Fusengine" }, @@ -247,7 +247,7 @@ "name": "fuse-nextjs", "source": ".cursor-plugin/plugins/fuse-nextjs", "description": "Expert Next.js 16 + React 19 with App Router, Server Components, Prisma 7, and Better Auth", - "version": "1.1.24", + "version": "1.1.25", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -269,7 +269,7 @@ "name": "fuse-php", "source": ".cursor-plugin/plugins/fuse-php", "description": "Expert modern PHP 8.5/8.4 for non-Laravel projects — libraries, standalone Symfony components, Slim, API-first apps, and CLI tools, with PER Coding Style 3.0, PHPStan, and SOLID principles", - "version": "1.0.7", + "version": "1.0.8", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -322,7 +322,7 @@ "name": "fuse-react", "source": ".cursor-plugin/plugins/fuse-react", "description": "Expert React 19 with hooks, TanStack Router, Zustand, React Hook Form, Testing Library, shadcn/ui, and SOLID principles", - "version": "1.0.21", + "version": "1.0.22", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -346,7 +346,7 @@ "name": "fuse-rules", "source": ".cursor-plugin/plugins/fuse-rules", "description": "Global rules for all sessions: APEX workflow, SOLID/DRY enforcement, project detection, agent delegation, frontend/git standards", - "version": "1.0.23", + "version": "1.0.24", "author": { "name": "Fusengine" }, @@ -359,7 +359,7 @@ "name": "fuse-rust", "source": ".cursor-plugin/plugins/fuse-rust", "description": "Expert Rust 1.96+ (2024 edition) — ownership, error handling, async/tokio, axum backends, cargo tooling, with SOLID principles", - "version": "1.0.7", + "version": "1.0.8", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -385,7 +385,7 @@ "name": "fuse-security", "source": ".cursor-plugin/plugins/fuse-security", "description": "Security vulnerability detection and remediation: OWASP Top 10, SAST scanning, CVE research, dependency audit, secrets detection", - "version": "1.0.17", + "version": "1.0.18", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -408,7 +408,7 @@ "name": "fuse-seo", "source": ".cursor-plugin/plugins/fuse-seo", "description": "SEO/GEO 2026 plugin. Local-first, framework-aware, zero third-party APIs. Covers technical SEO, schema markup, E-E-A-T, AI Overviews optimization, local SEO, sitemaps, hreflang, internal linking, content briefs, semantic clustering, and search experience optimization.", - "version": "1.0.12", + "version": "1.0.13", "author": { "name": "Fusengine" }, @@ -438,7 +438,7 @@ "name": "fuse-shadcn-ui", "source": ".cursor-plugin/plugins/fuse-shadcn-ui", "description": "Expert shadcn/ui with Radix UI and Base UI detection, component patterns, registries, theming, and migration", - "version": "1.0.18", + "version": "1.0.19", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -462,7 +462,7 @@ "name": "fuse-solid", "source": ".cursor-plugin/plugins/fuse-solid", "description": "SOLID principles enforcement with automatic project detection and validation for all languages", - "version": "1.0.19", + "version": "1.0.20", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -483,7 +483,7 @@ "name": "fuse-swift-apple-expert", "source": ".cursor-plugin/plugins/fuse-swift-apple-expert", "description": "Expert Swift 6.2 + SwiftUI for iOS 26, macOS 26, iPadOS 26, watchOS 26, visionOS 26, tvOS 26 with Liquid Glass, @Observable, actors, SwiftData inheritance", - "version": "1.1.20", + "version": "1.1.21", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -510,7 +510,7 @@ "name": "fuse-tailwindcss", "source": ".cursor-plugin/plugins/fuse-tailwindcss", "description": "Expert Tailwind CSS v4.1 - CSS-first configuration, @theme, @utility, @variant, Oxide engine 5x faster, OKLCH colors, container queries, 15 specialized skills", - "version": "1.1.11", + "version": "1.1.12", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -542,7 +542,7 @@ "name": "fuse-tanstack-start", "source": ".cursor-plugin/plugins/fuse-tanstack-start", "description": "Expert TanStack Start (React, RC) full-stack framework with file-based routing, createServerFn server functions, selective SSR, and Nitro deployment", - "version": "1.0.5", + "version": "1.0.6", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" @@ -567,7 +567,7 @@ "name": "fuse-typescript", "source": ".cursor-plugin/plugins/fuse-typescript", "description": "Expert TypeScript 6.0 for pure TS projects — CLI tools, libraries, scripts, and backends on Node 24 LTS or Bun 1.3, with SOLID principles", - "version": "1.0.7", + "version": "1.0.8", "author": { "name": "Fusengine", "email": "hello@fusengine.ch" diff --git a/.cursor-plugin/plugins/core-guards/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/core-guards/.cursor-plugin/plugin.json index 532fdbe..3312ead 100644 --- a/.cursor-plugin/plugins/core-guards/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/core-guards/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "core-guards", - "version": "1.1.38", + "version": "1.1.39", "description": "Core security guards (git, install, security) and SOLID enforcement hooks", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-ai-pilot/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-ai-pilot/.cursor-plugin/plugin.json index a10280d..43e53ce 100644 --- a/.cursor-plugin/plugins/fuse-ai-pilot/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-ai-pilot/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-ai-pilot", - "version": "1.2.43", + "version": "1.2.44", "description": "AI Pilot workflow agents: sniper (code quality), research-expert, explore-codebase, websearch", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-cartographer/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-cartographer/.cursor-plugin/plugin.json index 10932cf..ba309e8 100644 --- a/.cursor-plugin/plugins/fuse-cartographer/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-cartographer/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-cartographer", - "version": "1.0.13", + "version": "1.0.14", "description": "Generates indented markdown maps of the plugin ecosystem for agent navigation", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-changelog/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-changelog/.cursor-plugin/plugin.json index 1ad7628..7cdc842 100644 --- a/.cursor-plugin/plugins/fuse-changelog/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-changelog/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-changelog", - "version": "1.0.15", + "version": "1.0.16", "description": "Claude Code update watcher: changelog tracking, breaking changes detection, community pulse via Exa, plugin compatibility analysis", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-design/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-design/.cursor-plugin/plugin.json index 4956cf2..5842879 100644 --- a/.cursor-plugin/plugins/fuse-design/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-design/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-design", - "version": "2.2.10", + "version": "2.2.11", "description": "Design Director for websites, web apps, iOS, and Android. Generates HTML/CSS directly (Gemini Design MCP, Magic/21st.dev, and shadcn MCP are optional). iOS/Android produce tokens + a device-framed mockup + a handoff spec, never SwiftUI/Compose. Design method, design system tokens, motion, UX copy, and a deterministic design-review gate. Anti-AI-Slop, WCAG 2.2.", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-go/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-go/.cursor-plugin/plugin.json index 2ab115e..32f49ab 100644 --- a/.cursor-plugin/plugins/fuse-go/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-go/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-go", - "version": "1.0.7", + "version": "1.0.8", "description": "Expert Go 1.26+ — idioms, concurrency, backend services, cargo-grade tooling (golangci-lint v2, govulncheck), with SOLID principles", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-laravel/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-laravel/.cursor-plugin/plugin.json index 7a7d208..57d9ac9 100644 --- a/.cursor-plugin/plugins/fuse-laravel/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-laravel/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-laravel", - "version": "1.2.8", + "version": "1.2.9", "description": "Expert Laravel 13 + PHP 8.3+ with SOLID principles, first-class PHP Attributes, Laravel AI SDK, JSON:API Resources, native vector search (pgvector), Eloquent, Livewire, queues with routing, and comprehensive documentation", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-lessons/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-lessons/.cursor-plugin/plugin.json index 265a871..05a4e4b 100644 --- a/.cursor-plugin/plugins/fuse-lessons/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-lessons/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-lessons", - "version": "1.0.7", + "version": "1.0.8", "description": "Project memory: writes compact 'never reproduce' lessons to MEMORY/LESSON.md on finish, force-reads them at session/subagent start.", "author": { "name": "Fusengine" diff --git a/.cursor-plugin/plugins/fuse-nextjs/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-nextjs/.cursor-plugin/plugin.json index 2bac1dd..4edb4ce 100644 --- a/.cursor-plugin/plugins/fuse-nextjs/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-nextjs/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-nextjs", - "version": "1.1.24", + "version": "1.1.25", "description": "Expert Next.js 16 + React 19 with App Router, Server Components, Prisma 7, and Better Auth", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-php/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-php/.cursor-plugin/plugin.json index 43fde1d..f9c6548 100644 --- a/.cursor-plugin/plugins/fuse-php/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-php/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-php", - "version": "1.0.7", + "version": "1.0.8", "description": "Expert modern PHP 8.5/8.4 for non-Laravel projects — libraries, standalone Symfony components, Slim, API-first apps, and CLI tools, with PER Coding Style 3.0, PHPStan, and SOLID principles", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-react/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-react/.cursor-plugin/plugin.json index 58edd5f..9d43ec5 100644 --- a/.cursor-plugin/plugins/fuse-react/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-react/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-react", - "version": "1.0.21", + "version": "1.0.22", "description": "Expert React 19 with hooks, TanStack Router, Zustand, React Hook Form, Testing Library, shadcn/ui, and SOLID principles", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-rules/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-rules/.cursor-plugin/plugin.json index 02a7d17..c2e1a61 100644 --- a/.cursor-plugin/plugins/fuse-rules/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-rules/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-rules", - "version": "1.0.23", + "version": "1.0.24", "description": "Global rules for all agent sessions: APEX workflow, SOLID/DRY enforcement, project detection, agent delegation, frontend/git standards", "author": { "name": "Fusengine" diff --git a/.cursor-plugin/plugins/fuse-rust/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-rust/.cursor-plugin/plugin.json index 9683fa0..a1fd28f 100644 --- a/.cursor-plugin/plugins/fuse-rust/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-rust/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-rust", - "version": "1.0.7", + "version": "1.0.8", "description": "Expert Rust 1.96+ (2024 edition) — ownership, error handling, async/tokio, axum backends, cargo tooling, with SOLID principles", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-security/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-security/.cursor-plugin/plugin.json index 33ea075..69c4cf9 100644 --- a/.cursor-plugin/plugins/fuse-security/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-security/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-security", - "version": "1.0.17", + "version": "1.0.18", "description": "Security vulnerability detection and remediation: OWASP Top 10, SAST scanning, CVE research, dependency audit, secrets detection", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-seo/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-seo/.cursor-plugin/plugin.json index 16ac2ff..41baa64 100644 --- a/.cursor-plugin/plugins/fuse-seo/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-seo/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-seo", - "version": "1.0.12", + "version": "1.0.13", "description": "SEO/GEO 2026 plugin. Local-first, framework-aware, zero third-party APIs. Covers technical SEO, schema markup, E-E-A-T, AI Overviews optimization, local SEO, sitemaps, hreflang, internal linking, content briefs, semantic clustering, and search experience optimization.", "author": { "name": "Fusengine" diff --git a/.cursor-plugin/plugins/fuse-shadcn-ui/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-shadcn-ui/.cursor-plugin/plugin.json index c82be31..0c7d30c 100644 --- a/.cursor-plugin/plugins/fuse-shadcn-ui/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-shadcn-ui/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-shadcn-ui", - "version": "1.0.18", + "version": "1.0.19", "description": "Expert shadcn/ui with Radix UI and Base UI detection, component patterns, registries, theming, and migration", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-solid/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-solid/.cursor-plugin/plugin.json index f1ae358..d9b217a 100644 --- a/.cursor-plugin/plugins/fuse-solid/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-solid/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-solid", - "version": "1.0.19", + "version": "1.0.20", "description": "SOLID principles enforcement with automatic project detection and validation for all languages", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-swift-apple-expert/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-swift-apple-expert/.cursor-plugin/plugin.json index 83c1486..4ef1c9c 100644 --- a/.cursor-plugin/plugins/fuse-swift-apple-expert/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-swift-apple-expert/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-swift-apple-expert", - "version": "1.1.20", + "version": "1.1.21", "description": "Expert Swift 6.2 + SwiftUI for iOS 26, macOS 26, iPadOS 26, watchOS 26, visionOS 26, tvOS 26 with Liquid Glass, @Observable, actors, SwiftData inheritance", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-tailwindcss/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-tailwindcss/.cursor-plugin/plugin.json index 288485f..eddac5a 100644 --- a/.cursor-plugin/plugins/fuse-tailwindcss/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-tailwindcss/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-tailwindcss", - "version": "1.1.11", + "version": "1.1.12", "description": "Expert Tailwind CSS v4.1 - CSS-first configuration, @theme, @utility, @variant, Oxide engine 5x faster, OKLCH colors, container queries, 15 specialized skills", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-tanstack-start/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-tanstack-start/.cursor-plugin/plugin.json index f5c752a..ef9bf40 100644 --- a/.cursor-plugin/plugins/fuse-tanstack-start/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-tanstack-start/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-tanstack-start", - "version": "1.0.5", + "version": "1.0.6", "description": "Expert TanStack Start (React, RC) full-stack framework with file-based routing, createServerFn server functions, selective SSR, and Nitro deployment", "author": { "name": "Fusengine", diff --git a/.cursor-plugin/plugins/fuse-typescript/.cursor-plugin/plugin.json b/.cursor-plugin/plugins/fuse-typescript/.cursor-plugin/plugin.json index cf2e051..953e25b 100644 --- a/.cursor-plugin/plugins/fuse-typescript/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugins/fuse-typescript/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "fuse-typescript", - "version": "1.0.7", + "version": "1.0.8", "description": "Expert TypeScript 6.0 for pure TS projects — CLI tools, libraries, scripts, and backends on Node 24 LTS or Bun 1.3, with SOLID principles", "author": { "name": "Fusengine", diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a7eb8c..41570c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [0.1.8] - 12-10-2026 + +- fix(installer): keep the shared harness on latest — every installer run + refreshes `@fusengine/harness` in the shared control root (`bun update`, + falling back to `bun install`; fail-open) via new + `scripts/src/services/harness-vendor.ts` (+ interface, 6 tests); the + `hook.sh` wrapper comment (21 plugins + `plugin-runtime`) no longer claims + auto-upgrade and names the upgrade path; installation docs updated +- chore(plugins): PATCH bump, mirrored in `.cursor-plugin/marketplace.json` — + core-guards 1.1.39, fuse-ai-pilot 1.2.44, fuse-cartographer 1.0.14, + fuse-changelog 1.0.16, fuse-design 2.2.11, fuse-go 1.0.8, fuse-laravel 1.2.9, + fuse-lessons 1.0.8, fuse-nextjs 1.1.25, fuse-php 1.0.8, fuse-react 1.0.22, + fuse-rules 1.0.24, fuse-rust 1.0.8, fuse-security 1.0.18, fuse-seo 1.0.13, + fuse-shadcn-ui 1.0.19, fuse-solid 1.0.20, fuse-swift-apple-expert 1.1.21, + fuse-tailwindcss 1.1.12, fuse-tanstack-start 1.0.6, fuse-typescript 1.0.8 +- chore(marketplace): suite `metadata.version` 0.1.7 → 0.1.8, README version badge updated + ## [0.1.7] - 12-10-2026 - fix(rules): "always delegate" made consistent — Scope Ladder first row is diff --git a/README.md b/README.md index cf65cd8..cce3ed5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Fusengine Cursor Plugins -![version](https://img.shields.io/badge/version-0.1.7-blue?style=flat-square) +![version](https://img.shields.io/badge/version-0.1.8-blue?style=flat-square) ![plugins](https://img.shields.io/badge/plugins-24-brightgreen?style=flat-square) ![runtime](https://img.shields.io/badge/runtime-Cursor%20CLI-black?style=flat-square) ![License: MIT](https://img.shields.io/badge/License-MIT-yellow?style=flat-square)