AX-2205: Add SH support - #89
Merged
Merged
Conversation
Port of jfrog/claude-plugin#78. Self-hosted JPDs do not serve /ml/core off the platform root — the same APIs sit behind /bridge-client — so every probe 404s and the caller reports the feature as absent. Each /ml/core call site now retries once behind /bridge-client after a 404, and adopts that result only when it evidences a working endpoint, so no pre-existing failure changes its status, detail or exit code: - modules/core/agent-guard-check.mjs and its jfrog-mcp-management copy: the HTTP call is split into fetchSetting(), giving each attempt its own AbortController so the retry cannot inherit a spent timeout budget. Only an enabled/registry-off answer replaces the root verdict. - jfrog-detect-catalog-runtime.mjs: the fallback runs in both parts. Part A resolves the prefix anonymously; Part B retries independently for a JPD that answers 401 anonymously at the root but 404s the authenticated call. Part A adopts only a code that says the catalog is deployed, Part B only a 2xx of the catalog's shape or a 403. The two skill scripts are byte-identical to the claude-plugin versions. The modules/core copy here is one revision behind on an unrelated envLookup helper, so it was patched in place rather than copied; that drift is untouched and left for the next modules sync. Tests: unit coverage for the fallback plus an integration suite that spawns both skill scripts against a localhost JPD stub with a fake jf on PATH. The repo ran no unit tests in CI, so validate-template.yml now runs these and the two pre-existing cursor-*.test.mjs suites. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Closed
yanivt-jfrog
approved these changes
Sep 3, 2026
shmuelqwak
added a commit
that referenced
this pull request
Sep 7, 2026
…or the release (#91) Reapplies **#86**, which merged as `b2eba5f` and was reverted by **#87** for release scheduling — not for anything wrong with the change. Fixes [MLAI-1310](https://jfrog-int.atlassian.net/browse/MLAI-1310). This is a **revert of that revert**, so the restored content is byte-identical to what was already reviewed and approved. The only edit on top is the version: main has since moved to `0.6.7`, so both manifests go to `0.6.8`. ## What is broken on main right now Cursor skill governance is non-functional again, exactly as before #86. Cursor concatenates the hook command onto a pipeline it builds and leaves the hook's own `fd 0` as `/dev/null`: ```sh printf %s '<b64>' | base64 -d | _JFAG_NOW=$(date +%s 2>/dev/null); npm_config_… npx … --enforce-skill ``` That top-level `;` **terminates the pipeline**. `base64 -d` pipes into a bare assignment that reads nothing, and `npx` runs as a *separate* command inheriting the shell's stdin — `/dev/null`. agent-guard reads 0 bytes, cannot classify the event, and renders its no-opinion allow, which is byte-identical to "this prompt was not a skill invocation". **Both governed surfaces allow every skill, silently, at exit 0.** Verified on main as it stands: ``` beforeSubmitPrompt top-level ';': True preToolUse top-level ';': True ``` ## The fix, unchanged from #86 ```sh JF_AGENT_GUARD_ENFORCE_DEADLINE="$(_JFAG_NOW=$(date +%s 2>/dev/null); echo ${_JFAG_NOW:+$((_JFAG_NOW + 25))})" npx --yes … ``` Computing the deadline inside a command substitution scopes the `;` and keeps the hook **one simple command**, so it stays the tail of Cursor's pipeline. The defensive clock read is preserved, not reverted — an unreadable clock still yields an **empty** deadline, which agent-guard ignores in favour of its own budget, rather than the `25` (an instant in 1970) that the older inline form produced and that would floor the budget at 500 ms and block every skill. ## Verified on top of current main | | | |---|---| | skill-governance suite | **41/41** | | `validate-template` | pass | | unit tests | **53 pass, 0 fail** (including those added by #89) | And the regression cannot return unnoticed — run against main's current `hooks.json`, the suite fails **10 ways**: ``` FAIL beforeSubmitPrompt computes the deadline fresh, with no inheritable fallback FAIL preToolUse computes the deadline fresh, with no inheritable fallback FAIL no governed command has a top-level ';', '&&' or '||' (it is the tail of Cursor's pipeline) FAIL the payload survives Cursor's pipeline under every shell Cursor may pick FAIL beforeSubmitPrompt: forwards stdin verbatim and hands agent-guard the expected argv FAIL beforeSubmitPrompt: hands agent-guard a deadline in the future, computed at invocation FAIL beforeSubmitPrompt: with no date(1) on PATH, the deadline degrades to EMPTY and the payload still arrives FAIL preToolUse: forwards stdin verbatim and hands agent-guard the expected argv FAIL preToolUse: hands agent-guard a deadline in the future, computed at invocation FAIL preToolUse: with no date(1) on PATH, the deadline degrades to EMPTY and the payload still arrives ``` ## Interaction with what landed meanwhile `AX-2205 - Add SH support` (#89) touched neither `hooks.json` nor `scripts/validate-skill-governance.mjs`, so this reapply carries no interaction with it. The only merge conflict was the version manifests, resolved to `0.6.8`. Review feedback from #86 is already folded in: the manifest bump, the corrected `date(1)` sandbox comment, and the behavioural check that *executes* the empty-deadline degrade rather than asserting it in text.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Self-hosted JFrog Platform instances serve these APIs behind
/bridge-clientrather than off the platform root, so the Agent Guard and AI Catalog checks always 404 and report the feature as unavailable.Both checks now retry once behind
/bridge-clientafter a 404, and use that answer only when it comes from a working endpoint — every other outcome keeps its existing behaviour. SaaS is unaffected.Port of jfrog/claude-plugin#78. Tests:
node --test— 13 unit, 17 integration, plus the two pre-existing suites, all passing and now wired into CI.