Repository navigation
fix(ui-plugin): consumer-safe pre-push gate — repo scoping, collision resolution, MIT license - #514
Conversation
The SessionStart installer ran in whatever repo a session started in, so a globally installed plugin installed (and chained aside) a real pre-push hook in every consumer repo, even ones without libs/ui. Likewise the PreToolUse guard blocked `git push --no-verify` everywhere. Both hooks now first check the repo actually contains guarded paths — a libs/ui/ directory with anything besides the plugin bundle itself. In any other repo the installer installs nothing and the guard allows everything. The installer also self-heals repos polluted by earlier versions: it removes its stale hook and restores any original hook it had chained aside. Also resolve a relative core.hooksPath against the worktree root (as git does) instead of the process cwd, and fix the README claim that pre-existing hooks are "left alone" — they are chained and run first. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013vUG3XqkXS4qovoemSuxRD
The plugin is distributed via marketplace but all three manifests said UNLICENSED, formally forbidding the redistribution the marketplace does. Add the MIT license text, switch the license field in package.json and both plugin manifests, ship LICENSE in the npm files list, and note in the README that the bundled skills are covered too. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013vUG3XqkXS4qovoemSuxRD
Two collision paths remained even after scoping the installer to the ui-kit source repo: - A hook tracked in the repo (committed .husky/pre-push, lefthook output) was renamed aside, dirtying the worktree and inviting an agent to commit our copy. Tracked hooks are now never touched — the installer warns and skips instead. - When a stale pre-push.pre-ui-kit backup existed and a NEW foreign hook had appeared since, the installer silently overwrote the foreign hook without any backup. Now it leaves both files untouched and warns. Only an untracked foreign hook is chained, as before. README documents the collision rules (agent-level hooks.json hooks are additive by design and cannot collide with Codex/Claude defaults or other plugins). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013vUG3XqkXS4qovoemSuxRD
Previously the installer refused to install the gate when acting safely was impossible (tracked hook, stale backup + new foreign hook). Now both collisions are resolved so existing hooks keep running: - Tracked hooks dir (committed .husky/pre-push, lefthook, a default hooks dir committed by another tool): core.hooksPath (repo-local config, nothing in the worktree) is pointed at a shim inside .git/ that forwards every git hook type to the original dir and adds the gate only to pre-push — the original hook runs first and its exit code is honoured. - Multiple foreign hooks over time: moved-aside hooks accumulate in numbered pre-push.pre-ui-kit[.N] slots and the gate runs all of them, oldest first, before its own check. The consumer-repo self-heal understands both: it restores the original core.hooksPath and removes the shim, or restores the most recently moved-aside hook. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013vUG3XqkXS4qovoemSuxRD
Changed Files
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR makes the ui-kit Git push gate safe for consumer repositories. The main changes are:
Confidence Score: 5/5The updated hook and target-resolution paths look safe to merge.
Important Files Changed
Reviews (9): Last reviewed commit: "fix(ui-plugin): resolve GIT_DIR env assi..." | Re-trigger Greptile |
|
Warning Review limit reached
Next review available in: 42 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe plugin now uses MIT licensing, bundles the licence text, and limits its pre-push gate to the ui-kit source repository. Installation preserves existing hooks through redirects or backups, while chained hooks receive the same push input and retain exit-status handling. ChangesPlugin licensing and hook lifecycle
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Installer as install-git-hook.mjs
participant Repository as ui-kit source repository
participant GitHooks as Git hooks configuration
participant ChainedHook as hooks/pre-push
participant ValidationGate as pre-push-validate-gate.mjs
Installer->>Repository: Detect repository identity
Installer->>GitHooks: Install gate, shim hooks, or backup foreign pre-push
GitHooks->>ChainedHook: Invoke pre-push with push input
ChainedHook->>ChainedHook: Replay input to original and moved-aside hooks
ChainedHook->>ValidationGate: Run scoped validation gate
ValidationGate-->>ChainedHook: Return validation status
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@libs/ui/agent-plugin/scripts/install-git-hook.mjs`:
- Around line 62-68: Extract the canonical isUiKitSourceRepo implementation from
libs/ui/agent-plugin/scripts/install-git-hook.mjs lines 62-68 into a shared
helper under libs/ui/agent-plugin/scripts/lib, preserving its current detection
and fallback behavior. Update
libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs lines 33-53 to remove
its duplicate isUiKitSourceRepo(cwd) logic and import the shared helper, passing
cwd through as needed; the install-git-hook site should use the shared helper
after extraction.
- Around line 190-213: Update removeRedirect() so rmSync(shimDir, { recursive:
true, force: true }) runs only after successfully restoring or unsetting
core.hooksPath. Track whether the git configuration operation failed in the
existing catch, preserve the note about the error, and return without deleting
the shim when restoration fails.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 36669fcc-2e59-495c-b147-42deda01e290
📒 Files selected for processing (8)
libs/ui/agent-plugin/.claude-plugin/plugin.jsonlibs/ui/agent-plugin/.codex-plugin/plugin.jsonlibs/ui/agent-plugin/LICENSElibs/ui/agent-plugin/README.mdlibs/ui/agent-plugin/hooks/pre-pushlibs/ui/agent-plugin/package.jsonlibs/ui/agent-plugin/scripts/install-git-hook.mjslibs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs
📜 Review details
⚠️ CI failures not shown inline (1)
GitHub Check: Kilo Code Review: Kilo Code Review failed
Conclusion: failure
Review failed: The message could not be delivered
🧰 Additional context used
📓 Path-based instructions (2)
libs/**
📄 CodeRabbit inference engine (AGENTS.md)
Use RSLib for building libraries in the monorepo
Files:
libs/ui/agent-plugin/LICENSElibs/ui/agent-plugin/package.jsonlibs/ui/agent-plugin/scripts/pre-push-validate-gate.mjslibs/ui/agent-plugin/scripts/install-git-hook.mjslibs/ui/agent-plugin/hooks/pre-pushlibs/ui/agent-plugin/README.md
**/package.json
📄 CodeRabbit inference engine (CLAUDE.md)
Use pnpm CLI to add dependencies; never edit package.json directly
Files:
libs/ui/agent-plugin/package.json
🧠 Learnings (3)
📚 Learning: 2026-02-05T14:43:17.404Z
Learnt from: KaiUweCZE
Repo: NMIT-WR/new-engine PR: 324
File: apps/medusa-be/package.json:0-0
Timestamp: 2026-02-05T14:43:17.404Z
Learning: Validate and enforce React 19 compatibility across monorepo workspaces. Since Medusa UI supports React 19 via root package.json overrides and Medusa Cloud prerequisites show React 19 overrides for npm workspaces, ensure workspace root and all relevant package.json files align with React 19 (18+ requirement is satisfied). When reviewing, verify that overrides exist in the root package.json and that dependent packages in apps or packages directories declare React 19 (or compatible) in their peerDependencies or dependencies as appropriate for workspace usage.
Applied to files:
libs/ui/agent-plugin/package.json
📚 Learning: 2026-05-07T19:05:58.339Z
Learnt from: redeyecz
Repo: TechsioCZ/new-engine PR: 390
File: apps/medusa-be/package.json:78-81
Timestamp: 2026-05-07T19:05:58.339Z
Learning: When reviewing changes to `package.json`, do not automatically flag dependency additions/removals as "manually edited" or as "bypassing the pnpm lockfile" just because the `package.json` diff shows only that file changed. First verify whether `pnpm-lock.yaml` is missing the corresponding entries. Since `pnpm add` updates both `package.json` and `pnpm-lock.yaml` together, legitimate changes can appear in the `package.json` diff while still being properly tracked in the lockfile.
Applied to files:
libs/ui/agent-plugin/package.json
📚 Learning: 2026-07-13T10:43:17.745Z
Learnt from: Luko248
Repo: TechsioCZ/new-engine PR: 510
File: libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs:0-0
Timestamp: 2026-07-13T10:43:17.745Z
Learning: In Node scripts, treat command strings built with `child_process.execSync(...)` as a potential shell-injection risk when any part of the command comes from untrusted or agent/LLM/remote input (e.g., ref/branch names like `tool_input.command`). Do not interpolate untrusted values into an `execSync` shell command string (and avoid relying on `shellQuote` workarounds). Instead, execute the program directly with argv arrays (e.g., `execFileSync('git', ['rev-parse', ref, ...], { stdio: ... })` or `spawn/execFile` with `args`), passing each argument as a separate array element at every call site so no shell parsing is involved.
Applied to files:
libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjslibs/ui/agent-plugin/scripts/install-git-hook.mjs
🪛 LanguageTool
libs/ui/agent-plugin/README.md
[style] ~121-~121: Consider placing the discourse marker ‘first’ at the beginning of the sentence for more clarity.
Context: ..., so sessions start in arbitrary repos. Both hooks first check whether the repo actually contain...
(SENT_START_FIRST_PREMIUM)
[uncategorized] ~122-~122: Possible missing comma found.
Context: ... the plugin bundle itself. In any other repo the installer installs nothing and the ...
(AI_HYDRA_LEO_MISSING_COMMA)
[misspelling] ~153-~153: This word is normally spelled as one.
Context: ...orce: - an untracked foreign hook (hand-written, .git/hooks) is moved aside to a `p...
(EN_COMPOUNDS_HAND_WRITTEN)
[uncategorized] ~157-~157: It seems likely that a singular genitive (’s) apostrophe is missing.
Context: ...pre-push`, lefthook output, a default hooks dir committed by another tool) is never...
(AI_HYDRA_LEO_APOSTROPHE_S_XS)
[uncategorized] ~157-~157: A comma may be missing after the conjunctive/linking adverb ‘Instead’.
Context: ... tool) is never renamed or overwritten. Instead core.hooksPath (repo-local config —...
(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)
[locale-violation] ~181-~181: License must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...idate-gate.mjs, sync-skills.mjs ``` ## License MIT — including the bundl...
(LICENCE_LICENSE_NOUN_SINGULAR)
[locale-violation] ~183-~183: LICENSE must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...s, sync-skills.mjs ``` ## License MIT — including the bundled skills.
(LICENCE_LICENSE_NOUN_SINGULAR)
🔇 Additional comments (8)
libs/ui/agent-plugin/.claude-plugin/plugin.json (1)
12-12: LGTM!libs/ui/agent-plugin/.codex-plugin/plugin.json (1)
12-12: LGTM!libs/ui/agent-plugin/LICENSE (1)
1-22: LGTM!libs/ui/agent-plugin/package.json (1)
15-15: LGTM!Also applies to: 25-32
libs/ui/agent-plugin/README.md (1)
23-23: LGTM!Also applies to: 120-126, 144-162, 180-183
libs/ui/agent-plugin/scripts/install-git-hook.mjs (1)
8-61: LGTM!Also applies to: 70-144, 166-188, 215-265, 275-275
libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs (1)
20-21: LGTM!Also applies to: 131-136
libs/ui/agent-plugin/hooks/pre-push (1)
23-24: LGTM!Also applies to: 36-42, 43-72, 74-84, 86-91
…files, safe shim removal Applies the four review findings on PR #514, all scoped to the plugin's hook scripts: - Greptile P1 (install-git-hook.mjs): a consumer repo with its own libs/ui package tripped the "libs/ui has something besides agent-plugin" scope check, so the gate wrongly activated. Identify THE ui-kit source repo by a specific tracked marker — libs/ui is the @techsio/ui-kit package — instead of any extra entry under libs/ui. - Greptile P1 (install-git-hook.mjs): isTrackedInRepo passed an absolute path to `git ls-files`, which matches worktree-relative pathspecs; a committed .husky/pre-push could be misread as untracked and renamed instead of shimmed. Pass a repo-relative path. - CodeRabbit Major (install-git-hook.mjs): removeRedirect() deleted the shim even when restoring core.hooksPath threw, leaving config pointing at a missing dir and silencing every hook. Return early on restore failure, leaving the shim in place for a retry. - CodeRabbit (both scripts): the source-repo detection was duplicated. Extract it to scripts/lib/is-ui-kit-source-repo.mjs so the installer and the guard can't diverge. Verified: consumer-scoping unit cases (own libs/ui → not gated) and an end-to-end tracked-hook run (committed .husky/pre-push left untouched, worktree clean, core.hooksPath routed through the shim). Plugin keeps its own formatting; no unrelated style churn. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e check Greptile P1 on the scoping added earlier in this PR: the guard tested the shell tool's cwd, so `git -C /path/to/ui-kit push --no-verify` issued from a consumer cwd resolved to "not the ui-kit repo", the guard allowed it, and `--no-verify` then skipped the ui-kit worktree's installed pre-push hook. Resolve the command's effective directory — walking repeatable, cumulative `-C <dir>` before the subcommand — and run both the source-repo scope check and the alias lookup against it. Verified: `git -C <uikit> push --no-verify` from a consumer cwd (and its relative `-C ../uikit` form) is now blocked, while a genuine consumer `git push --no-verify` is still allowed and a normal ui-kit push is untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs`:
- Around line 43-44: Update command tokenization near `tokens` to preserve
quoted arguments, including paths containing spaces, while still splitting
unquoted whitespace. Update the `gitIdx` executable match to recognize Unix and
Windows paths and both `git` and `git.exe` names, including backslash-separated
paths, so `effectiveGitCwd` receives the correct command context.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d3543159-218e-4acf-809e-9059a4020098
📒 Files selected for processing (1)
libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs
📜 Review details
⚠️ CI failures not shown inline (1)
GitHub Check: Kilo Code Review: Kilo Code Review failed
Conclusion: failure
Review failed: The message could not be delivered
🧰 Additional context used
📓 Path-based instructions (1)
libs/**
📄 CodeRabbit inference engine (AGENTS.md)
Use RSLib for building libraries in the monorepo
Files:
libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs
🧠 Learnings (2)
📚 Learning: 2026-07-13T10:43:17.745Z
Learnt from: Luko248
Repo: TechsioCZ/new-engine PR: 510
File: libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs:0-0
Timestamp: 2026-07-13T10:43:17.745Z
Learning: In Node scripts, treat command strings built with `child_process.execSync(...)` as a potential shell-injection risk when any part of the command comes from untrusted or agent/LLM/remote input (e.g., ref/branch names like `tool_input.command`). Do not interpolate untrusted values into an `execSync` shell command string (and avoid relying on `shellQuote` workarounds). Instead, execute the program directly with argv arrays (e.g., `execFileSync('git', ['rev-parse', ref, ...], { stdio: ... })` or `spawn/execFile` with `args`), passing each argument as a separate array element at every call site so no shell parsing is involved.
Applied to files:
libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs
📚 Learning: 2026-07-20T17:19:36.961Z
Learnt from: Luko248
Repo: TechsioCZ/new-engine PR: 514
File: libs/ui/agent-plugin/scripts/install-git-hook.mjs:0-0
Timestamp: 2026-07-20T17:19:36.961Z
Learning: In `libs/ui/agent-plugin/scripts`, keep ui-kit source-repository detection centralized in `scripts/lib/is-ui-kit-source-repo.mjs`. Ensure any git-hook/validation scripts (e.g., `install-git-hook.mjs`, `pre-push-validate-gate.mjs`) reuse this shared detector rather than duplicating logic. The shared detection must include the `techsio/ui-kit` marker (or equivalent required marker) so the code can reliably distinguish the real ui-kit source repository from consumer repositories.
Applied to files:
libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs
🔇 Additional comments (1)
libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs (1)
20-21: LGTM!Also applies to: 140-148
…re shell expansion Greptile P1 (security) follow-up to the -C handling: the hook receives the command verbatim, before the shell expands it, so `git -C "$UI_KIT_DIR" push --no-verify` from a consumer cwd made resolve() point at a literal `$UI_KIT_DIR` dir that does not exist, the source-repo check returned "not ui-kit", and the guard allowed it — then the shell expanded the variable, git targeted the ui-kit worktree, and --no-verify skipped its pre-push gate. effectiveGitCwd now reports trusted=false when a -C value contains shell-expansion syntax ($VAR, $(...), ~, globs). The scope check only exits early when it can PROVE the target is a non-ui-kit repo (trusted && resolvable); otherwise it falls through and fails closed — the guard blocks the command iff it is push + --no-verify. Normal pushes and non-push commands with an unresolvable -C are still allowed, so consumers are not over-blocked. Verified: $VAR / ~ / $(...) -C targets with --no-verify now blocked; the same with a normal push allowed; plain consumer push --no-verify allowed; trusted literal -C cases unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…vable `-C` Greptile P1 follow-up: when `-C` is unresolvable (shell expansion), the guard expanded aliases from the CALLER's config, not the target repo's. So `git -C "$UI_KIT_DIR" publish` — where the ui-kit repo defines `alias.publish = push --no-verify` — showed neither "push" nor "--no-verify" at the call site, the caller's config had no such alias, and the command was allowed; the shell then expanded the path, git ran in ui-kit, resolved the alias, and skipped the pre-push gate. The target repo's aliases are unknowable when its path isn't resolved yet, so on the unresolvable `-C` path we now fail closed: block a literal `push --no-verify`, and block any NON-built-in subcommand that could be an alias expanding to it. Git forbids an alias from shadowing a built-in, so every built-in subcommand is provably safe — a bare `push` (its pre-push hook still runs), `status`, `commit`, `fetch`, etc. stay allowed; only shell-variable `-C` + a custom alias over-blocks, which is rare and never a bypass. Verified: `git -C "$UI_KIT_DIR" publish|deploy` and `-C "$D" push --no-verify` blocked; bare push, status, commit, fetch via a shell-variable `-C` allowed; all trusted/literal paths unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…verify guard The guard resolved only `git -C <dir>` when deciding whether a command targets the ui-kit repo. `--git-dir`/`--work-tree` were skipped as value-taking flags but never changed the scoped directory, so from a consumer checkout `git --git-dir /path/to/ui-kit/.git push --no-verify` passed the non-ui-kit scope check while git pushed the ui-kit worktree and `--no-verify` skipped its gate. `effectiveGitCwd` now also extracts `--git-dir` (the only other selector that retargets a push; `--work-tree` merely relocates the tree and is intentionally not treated as a selector, to avoid over-blocking a legit consumer `--work-tree` push). `resolveTargetWorktree` derives the real worktree from the git dir via `rev-parse --absolute-git-dir` — cwd can't be trusted here, since git reports the cwd as top level when only `--git-dir` is set. Shell-expansion values and un-derivable worktrees (bare/linked) fail closed through the existing path. Verified end-to-end against throwaway repos: `--git-dir`/`-C` at ui-kit (incl. alias.publish and shell-var forms) blocked; `--work-tree`-alone, consumer own-repo, bare push, and non-push subcommands allowed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…kups Two follow-ups to the collision/scope work, from review: - Guard: the `--git-dir` scope resolution only matched the space form (`--git-dir <dir>`); the attached form `--git-dir=/path/to/ui-kit/.git` fell through as a generic flag, leaving the target at the consumer cwd so `git --git-dir=<ui-kit>/.git push --no-verify` slipped past the scope check. effectiveGitCwd now handles both forms (short `-C` stays space-only, per git). - pre-push shim: chainedHooks() only scanned its own directory. A foreign hook backed up as `.git/hooks/pre-push.pre-ui-kit` during an earlier untracked-path install is then invisible once the repo grows a tracked hooks dir and the installer switches to the core.hooksPath shim — its checks and non-zero exit were silently dropped on every push. It now also scans git's default `.git/hooks` when running as the shim (guarded so a normal install never double-runs a backup). Verified end-to-end: `--git-dir=` (incl. alias + shell-var forms) blocked for ui-kit and allowed for consumers; the default-dir foreign backup now runs and its failure propagates, while a direct install runs each backup exactly once. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`effectiveGitCwd` only inspected tokens after the git executable, so a leading environment assignment — `GIT_DIR=/path/to/ui-kit/.git git push --no-verify` (also via `env`, or after other `NAME=value` prefixes) — left the target at the consumer cwd and slipped past the scope check while git pushed the ui-kit repo with its pre-push hook skipped. The scan now also reads a leading `GIT_DIR=` assignment and feeds it through the same resolution as `--git-dir` (GIT_WORK_TREE is intentionally ignored — like --work-tree it only relocates the tree, not the repo). A command-line --git-dir still overrides the env var, matching git's own precedence. Verified: `GIT_DIR=<uikit>/.git git push --no-verify` (and its `env …`, alias, and `$VAR` forms) blocked; GIT_DIR at a consumer repo, GIT_WORK_TREE-only, bare push, non-push subcommands, and a consumer `--git-dir` overriding a ui-kit GIT_DIR all allowed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
🎉 This PR is included in version 0.27.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Summary
Fixes the consumer-safety issue reported when installing the
techsio-ui-kit-aiplugin in other repositories: theSessionStarthook installed (and moved aside) a real gitpre-pushhook in every repo a session started in, even repos withoutlibs/ui, and thePreToolUseguard blockedgit push --no-verifyeverywhere.Scope the gate to the ui-kit source repo (
9f552b0)libs/ui/directory with anything besides the plugin bundle itself. Anywhere else the installer installs nothing and the--no-verifyguard allows everything.core.hooksPathis now resolved against the worktree root (as git does), not the process cwd.Resolve collisions with existing/default hooks (
febf1f4,527f550)Collisions are resolved so existing hooks keep running — never won by force:
.husky/pre-push, lefthook output, a default hooks dir committed by another tool) is never renamed or overwritten. Insteadcore.hooksPath(repo-local config — nothing in the worktree changes) points at a shim dir inside.git/that forwards every git hook type to the original dir and adds the gate only topre-push— the original hook runs first and its exit code is honoured.pre-push.pre-ui-kit[.N]slots; the gate runs all of them, oldest first, before its own check. This also fixes a destructive bug where a stale backup plus a new foreign hook led to the foreign hook being overwritten without backup.core.hooksPath+ removes the shim, or restores the most recently moved-aside hook).License (
28fca40)UNLICENSED. Now MIT:LICENSEfile added, license field switched inpackage.json+ both plugin manifests, README notes the bundled skills are covered too.README documents the scoping and collision-resolution rules and fixes the previously inaccurate claim that pre-existing hooks are "left alone".
Testing
pre-pushruns first and its exit code propagates, other hook types forwarded, numbered backups all run oldest-first and a failing one still blocks the push,--no-verifyguard allows in consumer repos and blocks in the ui-kit repo, idempotent re-runs.bunx biome checkon the touched scripts.🤖 Generated with Claude Code
https://claude.ai/code/session_013vUG3XqkXS4qovoemSuxRD
Generated by Claude Code
Summary by CodeRabbit
pre-pushvalidation and hook compatibility by chaining existing hooks safely.pre-pushvalidation and installation to the ui-kit source repository only.