mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-09-14 14:01:28 +08:00
docs/x-gateway-github-style-metadata
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fabcc9261a |
fix(hooks): Codex hooks.json schema + PreToolUse verdict compat (#2857)
Codex's plugin hook-manifest loader accepts only `description` and
`hooks` at the top level and hard-rejects the rest of the manifest on
anything else. plugins/ruflo-core/hooks/hooks.json and
plugins/ruflo-cost-tracker/hooks/hooks.json carried `_note` /
`_platform_note` documentation fields, so a fresh Codex install of
ruflo-core@ruflo (still true as of the currently-published 3.32.38 /
ruflo-core 0.2.5) fails to load the plugin at all with:
failed to parse plugin hooks config .../hooks.json:
unknown field `_note`, expected `description` or `hooks`
Fold the doc content into `description` (content preserved, no hook
commands changed) for both marketplace-listed manifests, and add a
strict top-level-key check to
scripts/audit-plugin-hooks-cross-platform.mjs so this class of
regression fails CI going forward. `.claude-plugin/hooks/hooks.json`
is POSIX-only and not marketplace-distributed (not what Codex fetches
for ruflo-core@ruflo); its doc fields are folded too but its
audit-script flags (`_platform`, `_legacy_unaudited_shim`) are kept.
Second, deeper bug once the manifest loads at all: `modify-bash`/
`modify-file` PreToolUse hooks always echo Cursor's
`{"permission":"allow"}` verdict. Codex's own strict output schema
(additionalProperties: false) rejects that shape outright and reports
"hook returned invalid pre-tool-use JSON output" on every single tool
call — verified directly against the real parser
(codex-rs/hooks/src/engine/output_parser.rs,
codex-rs/hooks/src/events/pre_tool_use.rs) and its generated JSON
schema. Empty stdout is the one input Codex's parser treats as
no-opinion/implicit-allow with no error. `isCodexPluginHost()` (added
for #2816, ruflo-core 0.2.5) already detects Codex via its
PLUGIN_ROOT/PLUGIN_DATA env vars and correctly suppresses the verdict
in that case — harden it with a `turn_id`-based fallback (a documented
Codex-only field always present in Codex's PreToolUse input JSON, per
codex-rs/hooks/schema/generated/pre-tool-use.command.input.schema.json)
so detection doesn't depend solely on those env vars being set.
Bump ruflo-core 0.2.5 -> 0.2.6 and ruflo-cost-tracker 0.26.2 -> 0.26.3
so Codex's per-version plugin cache invalidates and re-fetches the
fixed manifest instead of serving a stale cached copy indefinitely.
Fixes #2855, #2856.
|
||
|
|
67ff9898c0 |
fix: resolve current runtime and verification defects for v3.32.36 (#2850)
* fix(cli): make runtime status and learning signals truthful * fix(metaharness): accept padded scan severities * fix(codex): make core hooks and status skill native * fix(security): make witness verification hermetic * fix(metrics): expose grounded learning outcomes * fix(hooks): deduplicate project and plugin events * fix(verification): preserve security audit payloads * fix(runtime): stabilize dual memory skills and MCP schemas * fix(cli): harden helper signing and reflexion health * test(release): align helper and container invariants * chore(release): prepare v3.32.36 * test(funnel): align gates with cold-start seed pool * fix(ci): document MCP environment precedence |
||
|
|
b08246b04a |
chore(release): bump to 3.32.27 (#2823)
* chore(release): bump to 3.32.27 * chore(release): publish policy security dependency * chore(release): sign 3.32.27 helper manifest * ci: harden policy release gates |
||
|
|
b68ad4ccba |
fix(plugins): make ruflo-core/ruflo-cost-tracker hooks Windows-native (#2721)
Both plugins' hooks.json wrapped every command in `/bin/bash -c '...'`,
which fails outright on native Windows (no such path) -- Codex/Claude
Code report "PreToolUse hook (failed) -- exit code 1" on every tool
call. The `_platform: posix` / "ruflo init overrides this on Windows"
claim in both files was never actually true: Claude Code merges
plugin-declared hooks additively with any init-generated
.claude/settings.json, it doesn't replace them, and there's no `ruflo
init` step at all in the reported Codex marketplace install flow.
Fix: every hook command is now a `node -e` bootstrap that resolves
plugins/*/scripts/ruflo-hook.cjs from process.env.CLAUDE_PLUGIN_ROOT
inside Node -- no shell env-var expansion (${VAR} vs %VAR%), so the
exact same command string runs unchanged on Windows/macOS/Linux.
ruflo-core's ruflo-hook.cjs (previously a full port of ruflo-hook.sh
that existed on disk but was never referenced by hooks.json) gained:
- JSON parsing of the hook event from stdin (replaces jq) for
post-command/post-edit, deriving the same CLI flags the bash
version computed
- the PreToolUse permission-allow stdout echo Cursor's stricter
contract requires (previously only the bash wrapper's trailing
printf did this)
- precompact-manual/precompact-auto guidance text (previously plain
bash echoes, no CLI call)
- a real Windows shell-quoting fix: shell:true with an args array
does NOT quote array elements, so "echo hi" silently truncated to
"echo" and a heredoc's `<<` errored as unexpected -- skip the
shell entirely for `node` invocations (never a .cmd shim, so
CreateProcess gets the argv array byte-for-byte)
cost-tracker's existing ruflo-hook.cjs (already correct, just
orphaned) needed no logic changes, only wiring.
Also:
- corrected the false "_platform_note" claims about ruflo init
overriding plugin hooks
- hardened scripts/audit-plugin-hooks-cross-platform.mjs: a
POSIX-exempt hooks.json now must actually reference its sibling
.cjs shim, not just have one sitting on disk unreferenced (which
is exactly the shape cost-tracker shipped in undetected)
- added windows-latest to the plugin-hooks-smoke CI matrix (it was
ubuntu/macos-only because the old bash-based hooks.json couldn't
run on Windows at all) and rewrote test-hooks.mjs to drive hooks.json's
literal command strings via `shell: true` -- exactly how Claude
Code/Codex invoke them -- instead of wrapping everything in an
explicit `bash -c` that could never have caught this bug
- flagged (not fixed) a separate, currently-published, actively
maintained plugin package (.claude-plugin/ + plugin/, the older
"claude-flow" plugin, not listed in the ruflo marketplace) with
the same underlying bug via jq/xargs pipes instead of bash --
explicitly marked _legacy_unaudited_shim so the hardened audit
doesn't silently regress on out-of-scope work
Verified locally on native Windows (this fix's actual target
platform): all 17 ruflo-core hook cases pass, all 3 cost-tracker
cases pass, the existing 12-case smoke-ruflo-hook-cjs.mjs passes
unchanged, both hook-command audits pass clean.
Fixes #2721
|
||
|
|
f0ee0f9688 |
fix(#1921): plugin hooks use a resilient shim, not bare npx @alpha per fire (#1923)
* fix(#1921): plugin hooks invoke a resilient shim, not bare `npx @alpha` per fire Every PreToolUse/PostToolUse/Stop hook ran `npx <pkg>@alpha hooks …`, which (a) re-resolves the @alpha dist-tag from the registry on every fire and (b) re-installs from cold cache — and when that install crashes (an arborist `Invalid Version` on npm 10.8.x, deep in a transitive OTEL/grpc subtree) the user sees a hook error in Claude Code after every assistant turn, plus ~7s of wasted registry traffic per turn. Fix: each plugin (`.claude-plugin/`, `plugin/`, `plugins/ruflo-core/`) ships `scripts/ruflo-hook.sh` — prefers an already-installed `ruflo`/`claude-flow` binary, falls back to `npx --prefer-offline --yes ruflo@alpha`, and ALWAYS exits 0. hooks.json invokes `"${CLAUDE_PLUGIN_ROOT}/scripts/ruflo-hook.sh" … || true` (the `|| true` covers the unset-$CLAUDE_PLUGIN_ROOT case). stdin (the hook event JSON) passes through unchanged; the stdin-jq-xargs shell-injection-safety pattern in plugin/hooks/hooks.json is preserved. This does NOT fix the underlying arborist crash (which needs the offending empty-`version` package pinned via `overrides` once it's identified on npm 10.8.2 — see the issue thread) — it makes a CLI/install failure invisible and cheap instead of a visible error every turn. CI guard: scripts/audit-hook-commands.mjs — fails CI if any hook `command` uses `npx` without `--prefer-offline`, or invokes the CLI without a non-fatal guard. Wired into v3-ci.yml as `hook-command-audit` (also bash-lints each ruflo-hook.sh and asserts it exits 0 with no CLI on PATH) + added to witness-verify needs[]. Path triggers updated to fire on `**/hooks/hooks.json`, `**/scripts/ruflo-hook.sh`, and `scripts/**`. Witness markers for #1921 + Co-Authored-By: RuFlo <ruv@ruv.net> * fix(#1921): make test-hooks.mjs shim-aware; fix shim-lint CI step; regen witness Rebasing #1921 onto main surfaced 3 CI failures: - plugin-hooks-smoke (ubuntu + macos): test-hooks.mjs substituted only `npx ruflo@alpha` → the local CLI, but the hooks.json now invokes `${CLAUDE_PLUGIN_ROOT}/scripts/ruflo-hook.sh <args>`. It now also substitutes the shim path → `<cli> hooks <args>` (bypassing the shim, so the test exercises the real CLI flag wiring) and strips the shim's trailing `|| true` so exit codes are still asserted. 7/7 pass. - hook-command-audit shim-lint step: `PATH="/nonexistent" bash "$sh"` set PATH to a dir with no `bash`, so `bash: command not found`. Now invokes bash by full path with `PATH=` empty: `PATH= "$BASH" "$sh"` — the shim's `command -v` is a builtin (works with empty PATH) and the npx fallback fails cleanly under `|| true` → exit 0. (resolved in v3-ci.yml during the rebase.) Witness manifest regenerated; #1862's marker refreshed to match the shim-relocated `post-edit -f "$FILE" -s true` (the documented-flag form is preserved). `ruflo verify` 0 regressed. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
0114951502 |
fix(#1899): ruflo-core hooks call npx ruflo@alpha not npx claude-flow@alpha
The ruflo-core plugin's hooks.json referenced the legacy package name `claude-flow@alpha` in all 5 hook commands (PreToolUse/Bash, PreToolUse/file, PostToolUse/Bash, PostToolUse/file, Stop/session-end). On every session end + every tool call, `npx` re-resolves the old `claude-flow` package, producing visible `ETIMEDOUT` errors on any brief network blip (VPN reconnect, etc.) even though it's non-blocking. Per the ruflo rebranding, all 5 now use `npx ruflo@alpha`. Updated test-hooks.mjs's substitution regex to match. Bumped ruflo-core plugin version 0.2.1 → 0.2.2. 7/7 hooks smoke still passes after the rename. NOTE: the marketplace plugin distributes via IPFS, not npm — users won't get this until ruflo-core@0.2.2 is republished to the marketplace (separate step, same pattern as #1862). Closes #1899 Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
8d06e427ca |
fix: #1859 #1862 ruflo-core hooks + CLI flag priority
Two distinct bugs converged on the same user symptom (every Write/Edit/Bash fired in Claude Code logged a parser error or recorded "true" as the file path). ## CLI parser bug (root of #1859 "records true as filename") In v3/@claude-flow/cli/src/commands/hooks.ts every handler resolved the primary value with: const x = ctx.args[0] || ctx.flags.X as string Because boolean-typed flags don't consume their next token, writing `--success true` (which the help text and project examples explicitly recommend) leaves the literal string "true" in `ctx.args[0]`, which then beats the named flag. Result: post-edit logs "Recording outcome for: true" instead of the path passed via --file. Fixed by swapping priority — flag value first, positional fallback — across all 14 sites: const x = (ctx.flags.X as string) || ctx.args[0] Backward compatible for legacy positional-only callers; surgical to a single regexed bulk swap. ## Plugin hooks bug (#1862 + part of #1859) plugins/ruflo-core/hooks/hooks.json passed flags the CLI doesn't accept: `--format true`, `--update-memory true`, `--track-metrics true`, `--store-results true`. The CLI's global `--format` flag rejects "true" because it's restricted to text|json|table — every Write/Edit hook crashed with "Invalid value for --format: true" before the handler ran. Also: the Bash hook's `tr '\n' '\0' | xargs -0 -I {}` mangled multi-line heredoc commands by splitting them at newlines, occasionally producing empty `--command ''` calls that the CLI rejected with "Required option missing". Replaced with a `bash -c` wrapper that: - Reads stdin once, extracts via jq into env vars (multi-line safe). - No-ops cleanly when the relevant field is absent. - Calls only flags the CLI documents: -c/-s/-e for post-command, -f/-s for post-edit. ## CI regression guard plugins/ruflo-core/scripts/test-hooks.mjs drives each PostToolUse hook with synthetic Claude-Code JSON against a CLI binary (local or published), asserting both exit code 0 *and* that the recorded value is the intended one (not a stray boolean). Verified empirically: fixed CLI: 7/7 pass broken @3.7.0-alpha.17: 5/7 fail with the exact #1859/#1862 symptoms Wired into .github/workflows/v3-ci.yml as `plugin-hooks-smoke` (Node 20 + 22), gating publish on green. Refs #1859 #1862 Co-Authored-By: RuFlo <ruv@ruv.net> |