mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-11-03 10:37:24 +09:00
main
1292
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5f3dacc54b |
feat(mods): automatic context delegation (ruflo-mods 0.15.0, ADR-522) + release 3.71.0 (#4652)
* feat(mods): automatic context delegation (ruflo-mods 0.15.0, ADR-522) + release 3.71.0 New contextDelegation option (off | observe | enforce, default off). A main-loop whole-file Read of a 14-120 KB file for an analysis prompt is answered by a no-tools haiku $.model.complete on the session's own credentials. Every quote is checked against the file and the model sees only the cited passages (the file's own lines) plus how to read the rest. The real Read always runs first, so a later Edit works (spike: answering the Read without next(e) breaks Edit); any failure shows the whole file. Live A/B (real binary, haiku main, 6 repo files 17-83 KB): 6/6 correct both ways, 6/6 delegated, total cost -22.5% incl. worker, main input -21.5%, wall +6.5%. First run delegated 0/6: haiku drops indentation in quotes; the verifier now trims per-line whitespace and relocates up to 3 lines, showing the file's own lines. Tests: 8 plugin tests, 3 real-binary e2e (extract + Edit, forged quote, off), CLI parity test vs DEFAULT_CONTEXT_LIMITS and core verdicts. Smoke step 4 now allows exactly one gated $.model.complete. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01MfPHVHXWyvDvDtYMTsA6MP * ci: keep the claude-code test-kit plugin test out of the vitest ratchet Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01MfPHVHXWyvDvDtYMTsA6MP |
||
|
|
36a1575eaf |
fix(ruflo-core): say why a stale local CLI build failed and fall back to npx (0.2.13) (#4607)
mcp-launch picked v3/@claude-flow/cli inside a ruflo checkout because bin/cli.js and dist/src/index.js existed, then died on a bare ERR_MODULE_NOT_FOUND when dist/ predated src/. Claude Code hides stderr behind 'Skipping connection', so the cause was invisible. Catch the missing-module import failure, print the rebuild command and the run-outside-the-repo option, and fall back to npx @latest. RUFLO_MCP_CLI_OVERRIDE, RUFLO_MCP_SKIP_NPX=1 and other error types still exit 1. Co-authored-by: RuFlo <ruv@ruv.net> |
||
|
|
66df9b95e1 |
feat(marketplace): agentdb and agentic-flow external plugins (ADR-518) (#4629)
* feat(marketplace): list agentdb and agentic-flow as external plugins (ADR-518) Adds both upstream Claude Code plugins to the ruflo marketplace as git-subdir entries pinned to their plugin-v3.1.0 merge commits (agentdb 401fcb68, agentic-flow 2c86073b). Each runs its own MCP server pinned to the 3.1.0 package plus a mod guard command. A real-binary e2e checks out the pinned commit and asserts the mod answers its own command with zero model requests, with a negative control the loader refuses. README rows and ADR-518 added. Co-Authored-By: RuFlo <ruv@ruv.net> * chore(marketplace): keep \u escapes so the diff only adds the two entries Co-Authored-By: RuFlo <ruv@ruv.net> * fix(console): give agentdb and agentic-flow a home section (plugin coverage) Co-Authored-By: RuFlo <ruv@ruv.net> * test: run the external-plugin e2e only in the real-binary tier Co-Authored-By: RuFlo <ruv@ruv.net> * chore(console): 0.49.8 — plugin map covers agentdb and agentic-flow Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
bd77bced5f |
fix(security): bearer parsing, verification-code bias, protocol stripping; release 3.66.2 (#4624)
* fix(security): linear bearer parsing, unbiased verification codes, nested-protocol stripping - @claude-flow/mcp: HTTP and WebSocket transports parse Authorization: Bearer with a prefix compare instead of /^Bearer\s+(.+)$/i, which backtracked quadratically on long whitespace runs (CodeQL js/polynomial-redos). - ruflo-chatgpt-federation: same parser fix in authContext. - @claude-flow/security: generateVerificationCode draws digits with randomInt(10); byte % 10 favoured 0-5 (js/biased-cryptographic-random). - @claude-flow/security: sanitizeString strips javascript:/vbscript:/data: until stable, so javajavascript:script: no longer reassembles javascript: (js/incomplete-url-scheme-check). - cli terminal_create: session ids from crypto randomBytes, not Math.random. Co-Authored-By: RuFlo <ruv@ruv.net> * chore(release): 3.66.2 — mcp 3.1.5, security 3.0.6 Co-Authored-By: RuFlo <ruv@ruv.net> * chore(ruflo-chatgpt-federation): 0.2.5 for the bearer parser fix Co-Authored-By: RuFlo <ruv@ruv.net> * test(ruflo-chatgpt-federation): smoke expects 0.2.5 Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
189aceca1d |
feat(learning): the verified-outcome learning loop on classic hooks, for every ruflo project (ADR-512) (#4604)
* feat(learning): run the verified-outcome learning loop on classic hooks for every ruflo project (ADR-512) Until now only the opt-in ruflo-mods plugin recorded verified turns and showed lessons. Classic hooks (every `ruflo init` project) now do the same. They replay the session transcript (`transcript_path`) through the mod's own record and lesson code, bundled into .claude/helpers/learning-loop.cjs: - route: records the turns that finished, then prints the lessons that fit the new prompt - session-end: records the rest (PreCompact leaves the open turn open). This runs before the session-id dedup, which otherwise dropped SessionEnd after a PreCompact. It also starts a detached `ruflo hooks verified-ingest --quiet` - one implementation: plugins/ruflo-mods/scripts/build-learning-loop-helper.mjs bundles hooks/loop/transcript.ts; the bundle is committed, checked in mod-guidance CI, and is a signed critical helper that helper-refresh installs (manifest re-signed) - never twice: with its loop on, the mod adds `learning-loop` to RUFLO_MODS_OWNS - opt-out: .claude-flow/config.json learningLoop.enabled=false, or RUFLO_LEARNING_LOOP=0 Tests: mods-learning-loop-classic (replay matches the mod's records, offsets, the hook-handler run as a process, end to end classic record -> real ingest -> lesson in route output) and real-binary contract 6 (pinned claude, mock model, no plugin). ruflo-mods 0.14.0. Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-512 cites PR #4604 Co-Authored-By: RuFlo <ruv@ruv.net> * ci: sign and exclude the classic-loop helper and real-binary test where the other helpers are (ADR-512) smoke-helper-signing-security copies the critical helpers into its fixture; it now copies learning-loop.cjs too. The ratchet's default run skips real-binary files, which need the claude binary (mods-real-binary runs them). Co-Authored-By: RuFlo <ruv@ruv.net> * test(mods): give the built-CLI tests the time their children get vitest's 5s default timed out mods-cli-bin on a loaded CI runner and reported only STACK_TRACE_ERROR (the timeout error carries the stack of the it() call). Each test runs the built CLI several times with a 120s child timeout. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
243bc57f0b |
feat(learning): lessons say where the fix goes; reworded tasks learn together (ADR-511) (#4603)
* feat(learning): lessons say where the fix goes; reworded tasks learn together (ADR-511) The §7 evaluation (#4581) showed three limits on what the verified-outcome loop can learn: - a lesson named an agent, nothing the model can act on; - tasks naming different files merged into one lesson; - the same task worded differently never learned (15 reworded verified successes left 15 patterns at one success each, zero lessons). Changes: - mods: a verified turn records its screened edited source files; a lesson names the three its passing fixes edited most and leads with them; pick() weighs rare keywords (IDF) and drops matches far below the best. ruflo-mods 0.13.0. - cli: files are counted per pattern (successes only) into learned-lessons.json; SONA takes them as pattern anchors (never keywords), so reworded tasks that fixed the same file reinforce one pattern; tasks naming disjoint paths never merge. Lesson building moves to verified-lessons.ts. - eval: the harness gains --ablate, --test-index, --concurrency, --lessons, --save-lessons, --eval-sample, --calibrate and --max-turns; scripts/eval-learning-loop-corpus.mjs writes a validated 15+30-task corpus. Proved offline (tests): 15 reworded prompts form 5 lessons, up from 0; the first run's prompts form 5 lessons, up from 1; the right lesson ranks first for 30 of 30 eval prompts, with 1.07 lessons shown per prompt. Paid pilots (haiku, about $6.80) are directional and did not reach the gate: - 8-turn cap: off 2/10, on 4/10, lessons without files 1/10; - uncapped: 6/6 vs 6/6, cost within 1%. ADR-511 §5 has the details. Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-511 cites PR #4603 Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
e9248a170e |
feat(security): plugin signing, scan before install, refuse risky project auto-approve keys (ADR-509) (#4593)
* feat(plugins): ADR-509 plugin trust — signing, scan before install, refuse project auto-approve keys - scripts/sign-plugins.mjs signs every marketplace plugin (signature.json: sorted path+sha256 list, version, Ed25519 over canonical JSON) with the existing helpers key (same key resolution as sign-helpers.mjs; never printed). Nothing is signed with the real key here; release step in ADR. - `ruflo plugins verify [name]` and `ruflo mods doctor` check the clone and install cache: verified / modified / unsigned / bad-signature, and write ~/.claude-flow/mods/plugin-verify.json per config dir. - ruflo-mods plugin.register gate: under modTrust refuse-risky, a <name>@ruflo module whose clone is modified or bad-signature is refused (allow-list does not exempt it). Live-validated on Claude Code 2.1.289. - Static scan of .mcp.json, hooks/hooks.json and hook modules before `claude plugin install` (mods install / init mods path) and before a local `plugins install`; a high finding blocks that plugin unless --accept-risk <plugin>, which is recorded in .claude-flow/mods/install.json. - settings-risk-scanner covers enableAllProjectMcpServers, enabledMcpjsonServers, bypassPermissions, blanket Bash/* allows and non-ruflo hooks; `ruflo init` / `init hooks` / `init upgrade --settings` stop before writing anything (--keep-risky-settings / --drop-risky-settings); `ruflo doctor` warns on them in settings.json and settings.local.json. Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-509 status names PR #4593 Co-Authored-By: RuFlo <ruv@ruv.net> * fix(init): ADR-509 classify ruflo hooks by exact command; gate project-shipped helpers isRufloHelperCommand no longer reuses pinToUserHelpers as a classifier: it matches the closed set of commands ruflo generates or has generated (each helper, subcommand, scope, platform, plus the legacy forms) by string equality. node -e with extra code, -r/--require, --import, NODE_OPTIONS= and a helper path in a comment are now findings. A project .claude/helpers/<critical helper> that is neither ruflo's shipped copy nor in a ruflo-signed manifest stops init too; --drop-risky-settings replaces it. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(mods): ADR-509 a scan-blocked plugin is never left enabled applyMods scans an existing marketplace clone before enabling anything and does not enable what it blocks; a plugin the post-refresh scan blocks has its enabledPlugins key removed and is dropped from the install record. The --no-plugin-install, test/CI and no-claude paths are covered by the pre-enable scan, and say when there is no clone to scan yet. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(plugins): ADR-509 scan the modules hooks.json loads and their imports The pre-install scan now resolves hooks.json `modules` against hooks.json and follows every relative import/export-from/import()/require they reach, with none of the walk's name, directory or size skips. A loaded file that is missing, unreadable, over the size limit, outside the plugin, or loads a computed module name is a high finding instead of being skipped. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(mods): ADR-509 signature gate works on Windows and checks the loaded copy The status file key is normalized the same way on both sides (forward slashes, no trailing slash, Windows drive paths lower-cased), and the mod finds the home the CLI used (USERPROFILE on Windows, else HOME). plugins/.gitattributes turns off line-ending conversion so a Windows clone hashes as signed. Every writer now records the install-cache copies too: per plugin the worst of all copies, and each copy by its directory; the mod looks up the plugin.register root first, so a tampered install cache next to a clean clone is refused. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(mods): ADR-509 match status path keys normalized; fix-pass notes The mod compares the status file's per-copy path keys normalized, so a key another writer spelled differently still matches the plugin.register root. ADR-509 gains the review fix-pass implementation notes and live validation. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(mods): ADR-509 report each blocked plugin once per run Co-Authored-By: RuFlo <ruv@ruv.net> * fix(cli): no env values in sign-plugins errors; RSA-2048 in the rejection test (CodeQL, ADR-509) Co-Authored-By: RuFlo <ruv@ruv.net> * chore(ruflo-mods): 0.12.0 for ADR-509 Co-Authored-By: RuFlo <ruv@ruv.net> * test(mods): make mods-cli-bin failures readable (no more opaque STACK_TRACE_ERROR) execFileSync's error holds Buffers and a process handle that vitest cannot serialize, so a CI failure only said STACK_TRACE_ERROR. Rethrow a plain Error with exit status, signal and the child's stdout/stderr tail. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
5d2be9374a |
feat(cost): budget file, LiteLLM gateway export, per-agent/tool attribution (ADR-508) (#4592)
* feat(cost): ADR-508 budget file, LiteLLM budget export, per-agent/tool attribution - .claude-flow/cost/budget.json (v1): `ruflo cost budget set --daily/--weekly/--monthly` writes it; the ruflo-mods ladder uses its smallest window when costBudgetUsd is 0. Hostile files (negative usd, unknown periods, oversized arrays) are no budget. Validator in both the mod and the CLI with a parity test. - `ruflo cost budget export --gateway litellm` prints budget_limits (and, with --model, model_max_budget + budget_fallbacks) as YAML or the /key/generate body; --apply posts it to https or loopback only, key from --key-env, redirects refused. --gateway meta-llm fails with a pointer to ADR-508 (no documented budget API). - ruflo-mods costLedger option (default on, ruflo projects only): session.measure deltas charged to subagent type and preceding tool, one line per session in .claude-flow/cost/attribution.jsonl, read by `ruflo cost report`; a gateway budget refusal is toasted once and counted. - Live-validated on Claude Code 2.1.289 (fake LiteLLM on loopback + one haiku run). Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-508 status names PR #4592 Co-Authored-By: RuFlo <ruv@ruv.net> * docs(ruflo-mods): ADR-508 costLedger transcript read, open budget-file and default-on notes Co-Authored-By: RuFlo <ruv@ruv.net> * fix(cost): ADR-508 review — --apply host escape via // path, per-call attribution split - keyGenerateUrl: a base path starting with // (or /\) resolved as a protocol-relative URL and sent the LiteLLM master key to another host (http://localhost//evil.example/ -> http://evil.example/key/generate). Refuse such paths, set the path on a copy of the parsed URL, and require the result to keep the given scheme and host. - Attribution: session.measure fires once per main-thread turn, and a foreground subagent runs inside the main Agent call, so last-tool charging put subagent spend on main/Agent. Split each measured delta evenly across the tool calls completed since the last measurement. - Tests in host event order and for the path escape; both fail on the previous code. ADR, README, cost report header state the estimate rule. Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-508 live run of the per-call attribution split Co-Authored-By: RuFlo <ruv@ruv.net> * chore(plugins): ruflo-mods 0.11.0, cost-tracker 0.31.0 for ADR-508 Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
828a8d78d9 |
feat(plugins): cut per-turn footprint — user-invoked operational skills, description ceiling, footprint report (ADR-507) (#4588)
* feat(plugins): ADR-507 cut the per-turn plugin footprint - scripts/measure-plugin-footprint.mjs: per-plugin skills/commands/agents, listing characters and estimated tokens, from the tree or a git ref; before/after reports in v3/docs/validation/. - 27 operational skills get disable-model-invocation: true (cost-tracker sub-reports reached by /ruflo-cost, metaharness bench/learn/evolve/mint/ oia-audit, GAIA submission + comparison, init-project, ruflo-status, vector-setup, federation-init, agntcy-status). Each is listed in a "User-invoked skills" table in its plugin README; the choosing rule is in plugins/README.md. - 20 skill descriptions over 300 characters cut to one sentence plus "Use when". - audit-skill-frontmatter: 300-char ceiling on skill and command descriptions (measured unfolded) and a README check for every user-invoked skill. - skillTrim (§2.4) not built: the engine has no skill-listing hook. Listing with every plugin enabled: 47,743 -> 39,402 chars (about 11,936 -> 9,851 tokens per turn). Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-507 status names PR #4588 Co-Authored-By: RuFlo <ruv@ruv.net> * docs(plugins): ADR-507 cost-analyst points users at /ruflo-cost for user-invoked reports The engine's refusal for a disable-model-invocation skill says not to replicate its workflow by other means, so the agent names the subcommand instead of running the report script. After-report now cites the pushed commit. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(scripts): ADR-507 audit runs through symlinked paths; test the gate's wiring The import guard compared argv[1] with import.meta.url, which Node realpaths for the entry module. Run through a symlinked path, main() was skipped and the audit exited 0 having checked nothing. Both scripts now compare realpaths. audit-skill-frontmatter takes --plugins-dir so tests can run the real CLI on a fixture: a 304-char folded description, an unlisted user-invoked skill and a 311-char literal command description must exit 1 with those findings, and adding the README row must clear only the user-invoked one. The repo-wide test now also asserts skillsScanned > 100. Disabling any of the three checks, or restoring either old guard, fails a test. Co-Authored-By: RuFlo <ruv@ruv.net> * chore(plugins): version bumps for ADR-507 footprint changes Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
49fe0b362b |
feat(mods): compactSnapshot — pre-compaction snapshot + post-compaction reload (ADR-505) (#4591)
* feat(mods): compactSnapshot — pre-compaction transcript snapshot + one-shot reload block (ADR-505) New ruflo-mods option compactSnapshot (default on). On a main-loop manual/auto/plugin session.compact it writes the transcript about to be summarized to .claude-flow/sessions/compactions/snapshot-<n>.jsonl (role, text <= 2000 chars, tool names/ids only; each line screened; 400 messages / 2 MiB; ten rotating slots), beside the compaction so it is never blocked, delayed or rewritten. The next non-slash prompt after a compaction that stood gets one [RUFLO_AFTER_COMPACT] context block (<= 2000 chars) from lessons shown this session, the last 5 loop outcomes, open swarm/claim ids and the snapshot path. ruflo doctor warns when snapshots exist and git would commit them. Co-Authored-By: RuFlo <ruv@ruv.net> * test(mods): isolate the ADR-505 doctor test from global git excludes; note precompute inference Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-505 status names PR #4591 Co-Authored-By: RuFlo <ruv@ruv.net> * fix(mods): compactSnapshot screens raw message text before JSON encoding (ADR-505) JSON escaping put a backslash before quotes and encoded newlines, so the key-assignment rule missed "api_key": "..." / password="..." and the line-start role-tag rule missed a \nsystem: line; those were written to the snapshot in plaintext. messageLine now screens the raw cut text and the tool names, plus the encoded line as before. Negative-control test added. Co-Authored-By: RuFlo <ruv@ruv.net> * chore(ruflo-mods): 0.10.0 for ADR-505 --------- Co-authored-by: r <r@x> |
||
|
|
658f0e33bf |
feat(plugins): sensitive userConfig secrets + readSecret + secrets audit (ADR-506) (#4587)
* feat(plugins): sensitive userConfig secrets, readSecret helper, plugin secrets audit (ADR-506) - ruflo-cost-tracker, ruflo-metaharness: `openrouterApiKey`; ruflo-x-gateway: `adminToken`. Each is type string, sensitive, optional, no default. - readSecret(name, envFallbacks): CLAUDE_PLUGIN_OPTION_<NAME> first, then the variables the plugin always read. Copied per plugin (x-gateway in src/, the only folder its Docker image ships); a test keeps the copies identical. - Consumers: openrouter.mjs key/generation, x-gateway checkAdmin (call time, fail closed), redblue child env (OPENROUTER_API_KEY, never argv). - scripts/audit-plugin-secrets.mjs: credential-named option without sensitive: true, or a literal secret (the mods' COMMON_SECRETS, parsed from screen.ts) in plugin.json/hooks.json, fails. Wired into plugin-package-audit. Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-506 status points at PR #4587 Co-Authored-By: RuFlo <ruv@ruv.net> * fix(plugins): deliver the ADR-506 secret option, harden the plugin secrets audit Review fixes for #4587: - Delivery: Claude Code gives a plugin option only to the plugin's own hooks and MCP servers, never to the Bash tool that runs openrouter.mjs and the redblue skill path. ruflo-cost-tracker and ruflo-metaharness now carry a SessionStart hook (scripts/_secret-env.cjs) that writes the sensitive openrouterApiKey option to CLAUDE_ENV_FILE as OPENROUTER_API_KEY, only when that variable is unset. Live-verified with Claude Code 2.1.289 (probe plugin and the real cost-tracker): a Bash tool command resolved the key. - ruflo-x-gateway adminToken removed: the gateway is a deployed server that no Claude Code process of the plugin runs, so the option could never arrive. - Audit: a secret used as a JSON key is shown as <redacted-key> and never printed; .mcp.json and .lsp.json are scanned; OpenRouter key shape added; credential-named env/headers entries holding a 16+ char literal fail; ${user_config.*} in command/headersHelper/args fails. - ADR-506 updated with the delivery trade-off and what the bridge does not reach (the metaharness_redblue MCP tool in ruflo-core's server). Co-Authored-By: RuFlo <ruv@ruv.net> * test(plugins): skip the bash-only ADR-506 bridge tests on Windows; hedge env-file mode wording Co-Authored-By: RuFlo <ruv@ruv.net> * chore(plugins): cost-tracker 0.29.0, metaharness 0.3.0 for ADR-506 Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
76845f22d3 |
feat(cli): load ruflo plugins in headless claude -p workers (ADR-510) (#4586)
* feat(mods): load ruflo plugins in headless claude -p workers (ADR-510) claude -p on a fresh config loads no marketplace plugins, so ruflo's own headless workers ran without ruflo-mods' guard, routing and learning loop. - resolvePluginPaths: --source local checkout, then the marketplace clone, then the install cache; a folder without .claude-plugin/plugin.json is reported missing, never returned; honours CLAUDE_CONFIG_DIR. - The daemon's HeadlessWorkerExecutor and `hive-mind work` add --plugin-dir <ruflo-mods> and CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 (unless set), never duplicate a caller's own --plugin-dir, and record a missing plugin (logged once) as missingPlugins on the result. - `ruflo plugins paths [--json]` for Agent SDK callers; README section. - `ruflo doctor --component headless-plugins` runs a real claude -p and checks the init event, plugin_errors and the mod heartbeat (runner injectable; skipped without a model credential). Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-510 status names PR #4586 Co-Authored-By: RuFlo <ruv@ruv.net> * fix(mods): headless plugin paths never come from project settings; stage hive-mind spawn -p (ADR-510) - resolvePluginPaths no longer reads extraKnownMarketplaces from the project's .claude/settings.json or settings.local.json. A cloned repo could point every daemon worker and `hive-mind work` at its own folder, loaded via --plugin-dir with function hooks on and no trust prompt, in place of the user's ruflo-mods. "Local" is now only a directory marketplace in Claude Code's user-level known_marketplaces.json, and a relative path is rejected. - `hive-mind spawn --claude --non-interactive` builds a `claude -p` worker too: it now goes through withHeadlessPlugins (staged before the prompt) and reports missingPlugins on data.claude. Interactive launch unchanged. - Tests: project-scope settings (absolute or ./x) resolve to clone/cache, never the repo; relative path rejected; spawn-mocked hive-mind spawn test. All four new assertions fail on the previous commit. Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-510 trust-boundary note records the live resolver check Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
38112e0042 |
feat(mods): learning-loop gaming defences — taints, re-verify, anomaly gate (ADR-503) (#4590)
* feat(learning-loop): gaming defences for verified outcomes (ADR-503) The verified-outcome loop (ADR-502) trusts a verifier's exit status, but the model chooses what that verifier checks. Four downgrade-only layers: - mod: a verified-success record carries taints when the turn edited a test file (edited-tests), a verifier config (edited-verifier-config), or decided on a weakened/narrowed command (narrowed-verifier); a per-process session token is written on every record. The outcome word never changes. - CLI: a success with a taint not listed in .claude-flow/config.json learningLoop.allowTaint is counted under `tainted` and never reaches SONA. - CLI: opt-in re-verify (learningLoop.reverify, off by default) re-runs a rotating allowlisted manifest check in a temp detached git worktree at HEAD with a timeout; failure, timeout or error downgrades to unknown. Only an explicit verified-ingest re-verifies; hot callers defer. - CLI: anomaly gate holds would-be lessons that are perfect-and-tainted, only-narrowed, or from one session, listed as `held: <id> (<reason>)`. Adds scripts/eval-learning-loop.mjs (manual, plan-only unless --run). Co-Authored-By: RuFlo <ruv@ruv.net> * docs(adr): ADR-503 status names PR #4590 Co-Authored-By: RuFlo <ruv@ruv.net> * fix(learning-loop): shell edits of tests taint; test the real re-verify runner (ADR-503) - A Bash command that writes, moves or deletes a test file or verifier config (rm, mv, cp, tee, truncate, sed -i/perl -i, output redirection, git rm/checkout/restore/...) now sets edited-tests / edited-verifier-config like an Edit of that file. Before this change, Edit src/a.ts + `sed -i 's/it(/it.skip(/' src/a.test.ts` + `npm test` produced an untainted verified-success. Downgrade-only: reads and test runs earn nothing. - gitWorktreeRunner is now tested against a throwaway git repo: pass, fail, missing script, timeout (hung script's process verified dead), non-repo error. After each run only the main worktree remains and no ruflo-reverify-* dir is left. A negative control (kill only the direct child) makes the timeout test fail. - ADR-503 implementation notes record both, plus the interpreter-write gap. Co-Authored-By: RuFlo <ruv@ruv.net> * test(learning-loop): give the hung-check re-verify test an 8s budget for cold CI runners Co-Authored-By: RuFlo <ruv@ruv.net> * chore(ruflo-mods): 0.9.0 for ADR-503 Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
375e846c66 |
feat(mods): verified-outcome learning loop, on by default (learningLoop, #4581, ADR-502) (#4583)
* feat(mods): verified-outcome learning loop (learningLoop, #4581, ADR-502) ruflo-mods 0.8.0 adds the learningLoop option (default off). Each main-loop turn becomes a trajectory whose outcome is verified-success/verified-failure only when a recognised test/build/typecheck/lint command ran after the turn's last edit and the shell's exit status said so; otherwise unknown. A masked status (|| true, pipes, ;, background, substitution) verifies nothing, and the model's own words are never read. The CLI ingests the records (ruflo hooks verified-ingest, the hooks_intelligence_verified-ingest MCP tool, and automatically from hooks_route and hooks_session-end): only verified records train SONA, unknown ones are counted; each id once; PII-redacted. It writes learned-lessons.json, and the mod adds at most three cited lessons at or above the 0.6 gate to a matching prompt. doctor --component learning-loop reports whether outcomes reach SONA. Stages 5-7 of #4581 (pane, autonomous /loop-run, GEPA self-tuning) are deferred; the on-by-default evaluation has not been run. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(mods): learning loop needs an edit to verify; redact e-mails before writing (#4581) A turn that edited nothing is unknown (a verifier verifies a change). The mod replaces e-mail addresses in the stored task; ADR-502 states the privacy limit (broader PII redaction runs at CLI ingest). Co-Authored-By: RuFlo <ruv@ruv.net> * feat(mods): learningLoop on by default (#4581) Maintainer decision: ship the learning loop on by default. Set the learningLoop option to false to turn it off. ADR-502 records that the issue's 30-task evaluation has not been run yet. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(cli): ADR-112 guidance on hooks_intelligence_verified-ingest (#4581) Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
8c0ad74e50 |
chore(marketplace): pin agentic-qe-fleet to v3.15.17 (#4574)
Move the external agentic-qe-fleet entry from v3.15.16 (4edfa469) to v3.15.17 (b177b2315521376b83f2eed40e4994fd7581d067), so its MCP server runs agentic-qe@3.15.17. The plugin folder changed only its version and MCP pin. Updates the README links, the external-plugins test fixture and the ADR-484 evidence section with the re-run install results. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
49f9a313ea |
chore(marketplace): pin agentic-qe-fleet to v3.15.16 (#4560)
Move the external agentic-qe-fleet entry from v3.15.15 (1d0cc766) to v3.15.16 (4edfa469d8f957b45bc0ea25424eb831b134f129), so its MCP server runs agentic-qe@3.15.16. The plugin folder changed only its version and MCP pin. Updates the README links, the external-plugins test fixture and the ADR-484 evidence section with the re-run install results. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
7d679ab425 |
fix(console): let Claude ack Project Anatole alerts via console_run (0.49.7) (#4545)
* fix(console): let Claude ack Project Anatole alerts via console_run console_run anatole-ack-<id> failed with "command.run: called from a tool.call hook, it would wait on the turn this hook is holding": the console sent /protector and awaited its answer inside Claude's tool call, and the host refuses a slash command while that call holds the turn. A clock tick and immediate:true do not avoid it (probed against Claude Code 2.1.289); a command started after the hook returns runs. The Anatole specs now send /protector without waiting, retry for about a minute while the host reports the turn as held, and say Queued until the mod answers. Acks still pass the console confirm and Claude-control level. ruflo-console 0.49.7. Co-Authored-By: RuFlo <ruv@ruv.net> * docs(console): link #4545 in the 0.49.7 changelog Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
065089344d |
fix(ruflo-console): offer to create a mission for a new goal once the active mission is over (0.49.6) (#4537)
* fix(ruflo-console): offer to create a mission for a new goal once the active mission is over The active mission stayed active for ever, so after it finished (every task done in the ruflo task store) or was cancelled, a goal planned after it showed "Create the mission and its tasks" as done with the old id and no create button. missionOfGoal() now says the goal has no mission yet when the active one is over, so the create step is the next step with its mc-create button. A mission still going keeps the re-plan in place; a finished mission's own goal is not offered a second time; a cancelled mission's goal can be created again. The create itself is unchanged and still asks first. Co-Authored-By: RuFlo <ruv@ruv.net> * chore(ruflo-console): 0.49.6 Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: RuFlo <ruv@ruv.net> |
||
|
|
551428e39a |
chore(marketplace): pin agentic-qe-fleet to v3.15.15 (#4533)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
dafd38a4fe |
feat(ai-team): semantic memory via Cognitum embeddings, ordered listing, funnel logging, anon rate limit (0.4.0) (#4527)
* feat(ai-team): semantic memory via Cognitum embeddings, ordered listing, funnel logging, anon rate limit (0.4.0) - memory_search ranks by meaning through /v1/embeddings (cognitum-embed, 384-dim) when a key is set; vectors persisted only for unchanged text, never returned; outage or no key falls back to the labelled lexical index - listMemories reads newest first (composite index teamId+createdAt), falling back to the unordered read when the index is absent - one structured ai_team_activation log line per workflow stage, hashed tenant, no content - per-client limit on unauthenticated requests (last X-Forwarded-For entry; OAuth and /health exempt) Co-Authored-By: claude-flow <ruv@ruv.net> * fix(ai-team): keep plain mcp.tool registration sites; wrap registration for funnel logging The repo-wide guard-tool-names check scans for .tool('name'; a local tool() helper hid them. Co-Authored-By: claude-flow <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
60e951415b |
fix(ruflo-console): keep a project copy of the mission ledger (0.49.5) (#4524)
* fix(ruflo-console): keep a project copy of the mission ledger (0.49.5) The ledger lives in the plugin's host store, a separate file per plugin source. A console loaded inline in one session and from the marketplace install in the next saw an empty store, so the project's mission disappeared from Mission Control after a restart. Each save now also writes .claude-flow/console/mission-ledger.json (git-ignored), and a load that finds no ledger for the project in the store restores this project's missions from it. A store that already has a ledger is left alone. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix(ruflo-console): offer, never adopt, missions from the project copy The copy is a file a cloned repository can ship. Missions read from it are now only offered (same path as pre-per-project missions, one yes adopts each); nothing is adopted, stored or made active unasked, `active` in the copy is ignored, and an empty ledger no longer overwrites it. Addresses review on #4524. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix(ruflo-console): word the project-folder offer as what it is Missions offered from .claude-flow/console/mission-ledger.json were shown under "from before per-project storage, with no project recorded", which is wrong for them. They now get their own heading that says where they were found and that a cloned repo can ship the file; the old heading is kept for missions that name no project. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
64b4fb9768 |
fix(ruflo-console): submit the mission plan from a file (Windows "command line is too long") (#4506)
* fix(ruflo-console): submit the mission plan from a file so create works on Windows mission_plan passed the ~7 KB plan as one `mcp exec -p` argument. With about 750 quotes, Windows argv quoting pushed the line past cmd.exe's 8191 characters: "The command line is too long." The plan is now written to .claude-flow/missions/console-plan-<id>.json and submitted with `ruflo mission plan --plan-file`, on every platform. Bumps to 0.49.4. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * test(ruflo-console): smoke contract expects 0.49.4 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
ed2dd638bd |
fix(ruflo-console): entryFor no longer returns another project's install record (#4496) (#4497)
* fix(ruflo-console): entryFor no longer returns another project's install record (#4496) No applying record and no user record now yields null; among applying project/local records the longest projectPath wins. Co-Authored-By: RuFlo <ruv@ruv.net> * chore(ruflo-console): bump to 0.49.3 for the entryFor fix (#4496) Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
264b346479 |
fix(ruflo-console): close Windows autopilot guard gaps and binary-planting paths (#4491) (#4494)
* fix(ruflo-console): close Windows autopilot guard gaps and binary-planting paths (#4491) - ap-guard: extract Windows paths with spaces in folder names, extended namespaces (\\?\), UNC forward slashes (//srv/share), and capture drive-relative/device paths into relative paths. - ap-envelope: match envelope-edit deny pattern under both / and \ separators. - ap-envelope: normalize before root test and reject extended device namespace prefixes (\\?\, \\.\). - ap-envelope: refuse .bat/.cmd targets in verifyProblem, and strip Windows executable suffixes repeatedly. - paths: reject NTFS alternate data streams (colon after drive) and segments resolving to parent traversals in hasParentSegment. - wf-control & wf-convo-live: resolve powershell.exe and where.exe via System32 to prevent local directory binary-planting. - Add focused regression tests in ap-windows-guard, ap-envelope-windows-paths, wf-control-windows, and wf-convo-finder. Fixes #4491 * chore(ruflo-console): bump version to 0.49.2 (#4491) |
||
|
|
3a650ce747 |
fix(ruflo-console): Windows fixes from running every view on a real Windows machine (console 0.49.1, cost-tracker 0.28.3) (#4490)
* fix(ruflo-console): Plugin Catalog reads a Windows marketplace clone (0.47.1)
Claude Code records the ruflo marketplace clone's installLocation as a drive
path (C:\Users\...\marketplaces\ruflo). readCatalog refused any location not
starting with "/", so the catalog showed "the clone's marketplace.json is not
readable" with the file in place.
- readCatalog uses isAbsolutePath / hasParentSegment from paths.ts.
- The catalog's plugin folders, manifests, skill/agent/command reads and the
snapshot's marketplace.json read (freshness row) build paths with joinPath
instead of a hardcoded "/".
- tests/windows-drive-path-sites.spec.ts: a Windows clone lists its plugins,
reads a skill file, and still refuses a relative or climbing location. The
new tests fail without the fix.
- Version 0.47.0 -> 0.47.1 in plugin.json, hooks/version.ts, scripts/smoke.sh
and CHANGELOG.md.
The other ruflo-console specs fail the same 12 tests with and without this
change on this machine (mission-cost, menu-entry, tui-ai-page, write-argv).
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruflo-console): forget-history actions and TUI colour work on Windows
- Events "forget history" and Workflows "forget saved views" ran `rm -f`, which
Windows does not have (write-flavor.ts: no delete on host-fs). On host-fs they
now empty the file(s) through the host file API (new emptyFiles in
write-via.ts; forgetSpec carries a `write` op like event-export does). The
saved-views file is rewritten as a valid empty document, and the forget is
verified by what the file holds. Linux/macOS keep the rm argv.
- depthOf returned "none" whenever TERM was unset. Windows Terminal, PowerShell
and cmd leave TERM unset (COLORTERM=truecolor, OS=Windows_NT), so the
standalone TUI drew without colour. On Windows only an explicit TERM=dumb or
NO_COLOR turns colour off.
Tests: both forget actions in host-fs flavor (files emptied, no rm run, refusal
reported, missing file left alone), forgetSpec verification, depthOf on Windows.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruflo-console): ADR status edits on CRLF records, and codex detection, on Windows
- withStatus / withSupersedes compared whole lines ("---") and checked
startsWith("---\n"), so a MADR record checked out with CRLF (git autocrlf is on
by default on Windows) failed with "the front matter is not closed", and other
formats got mixed line endings. Records with CRLF are now edited as LF text and
written back with CRLF.
- The Conversation board looked for codex with `which`, which Windows lacks, so
codex was never offered there. A Windows home (drive path or share) uses
`where`.
Tests: CRLF records for all three ADR formats (same edit as LF, CRLF kept, MADR
front matter found, supersede link), and the finder per platform. The ADR tests
fail without the fix.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruflo-console): keep the Windows fixes under the size rule, skip POSIX-only specs on Windows (0.47.2)
- Move the forget-history spec out of events-ui.ts into events-forget.ts: the
Windows branch had taken events-ui.ts to 521 lines (smoke step 11 caps files at
500). Move the codex-finder test out of wf-control-views.spec.ts (514 lines)
into wf-convo-finder.spec.ts.
- wf-replay-views: the Forget button asks one tick later now that it awaits the
write flavor; the spec waits for it.
- write-argv.spec.ts: the real-disk POSIX script specs check Unix mode bits and
FIFOs, which NTFS has not; Windows writes through the host file API. Skipped
there. tui-ai-page.spec.ts: the --plain spec needs a runnable fake codex (a
shebang script), which Windows cannot run; it asserts the codex line exists.
- Version 0.47.1 -> 0.47.2 in plugin.json, hooks/version.ts, scripts/smoke.sh and
CHANGELOG.md (the entry lists every Windows fix of this branch).
Verified: the specs of the changed areas pass; the remaining failures in a full
run are menu-entry (a circular import, not Windows-specific, fails on the
baseline), the *.test.ts kit files (need claude-code/testing), and two
timing-sensitive specs that pass alone.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruflo-cost-tracker): the ledger scripts run on Windows (0.28.3)
ledger.mjs, advise.mjs and local-cost.mjs ran only when
import.meta.url === `file://${process.argv[1]}`. On Windows that is
file:///C:/... against C:\..., never equal, so every call exited 0 with no
output and the plugin's own test-ledger.mjs failed 7 tests. They compare against
pathToFileURL(process.argv[1]).href now.
Two more breaks sat behind it for the ruflo console's mission spend:
- ledger.mjs --project required a leading "/", so a Windows project exited 2.
- inProject matched with "/" and exact case; transcripts record C:\Users\x\proj.
A drive-lettered path now compares with either separator and any letter case;
POSIX matching is unchanged (exact, directory boundary).
Tests: test-ledger.mjs gains Windows rows and cases (drive path in both
separator styles and letter cases, relative or climbing drive paths still exit 2,
POSIX rule stays exact). Version 0.28.2 -> 0.28.3 in plugin.json, smoke.sh and
CHANGELOG.md. smoke.sh still fails 5 steps on a Windows Git Bash for a reason
that predates this (it hands /c/... paths to a Windows node), unchanged here.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruflo-console): the autopilot's text checks know Windows paths, commands and shells
Groundwork for the Windows-aware path checks that ap-windows-gate.spec.ts names as
the follow-up (an autopilot start is still refused on Windows). Each rule only
parks or refuses more; none allows anything that was refused before.
- classifyTask read only POSIX paths from a task's text, so a task naming
C:\Windows\..., \\srv\share\..., ..\..\x, ~\x, %USERPROFILE%\x or
$env:USERPROFILE\x was not checked against the envelope folders. It is now.
- delete-outside-worktree knew the POSIX recursive-delete forms but not the
Windows ones: rmdir /s, del on a drive, the drive-format command,
Remove-Item -Recurse, or a recursive rm on a drive or a variable.
- verifyProblem took the program name by splitting on "/" only, so
C:\Windows\System32\cmd.exe, bash.exe or powershell passed the banned-program
check. It uses either separator, drops .exe/.cmd/.bat/.ps1, and a second set
bans the Windows shells, script hosts and destructive or system tools.
Tests (ap-windows-guard.spec.ts): path extraction and the envelope check, the deny
forms and ordinary text that must not match, verify programs allowed and refused.
Four of them fail without the change; the POSIX behaviour is asserted unchanged.
CHANGELOG: added to the unreleased 0.47.2 entry.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruflo-console): the Overview heading shortens a Windows project path
"ruflo state in <last two folders>" split the cwd on "/" only, so a Windows cwd
(C:\Users\x\proj) printed whole. tailOf in paths.ts splits on either separator;
the overview uses it. Test in paths.spec.ts. CHANGELOG: added to the unreleased
0.47.2 entry.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ruflo-console): transcript search, model keys and peer sends on Windows; smoke under Git Bash
The last Windows gaps of the sweep, each tested.
- Stopping or messaging a workflow run reads the run's task id from the session
transcript; over 2 MB that was `grep -o`, which Windows lacks. Windows now runs
PowerShell's Select-String (windowsSearchArgv in data/wf-control.ts). The path
and the pattern ride inside the script as base64, so a path with a space, a
quote, $, & or ; is only data and the script holds no double quote. Tested
against a real PowerShell on a 5 MB-class file through such a path.
- taskIdOf returned the FIRST launch when a search printed two launches of one
run (a resume), because the pattern's `[^}]` ran across both matches (nothing
prints a closing brace between them). It takes the last task id in the match.
This also affected `grep -o` on Linux and macOS.
- A model key for an HTTP endpoint was read with `printenv`, which Windows lacks.
Host gains an optional `env` (register.ts: $.env.get, already used for other
names) and SendDeps an optional `readEnv`, set only for a Windows home; elsewhere
`printenv` is unchanged.
- A send to a federation peer runs `bash <helper>`. On a Windows PATH `bash` is
the WSL launcher (System32\bash.exe), which cannot open a C:\ script path, so
the send failed obscurely. On a Windows home it now refuses, running nothing,
and says why.
- ruflo-cost-tracker scripts/smoke.sh builds ROOT with `pwd -W` under Git Bash:
a Windows node could not open /c/... paths, which failed 5 steps (now 66/0).
Checked and left alone: the npx launcher. The installed Claude Code (a native
binary with the host code inside it) runs $.process.run through a bundled execa
on cross-spawn, which finds `npx` as npx.cmd through PATHEXT and runs it via
cmd.exe /d /s /c with its own argument escaping, so ['npx', ...] works on
Windows. The same lookup is why `bash` there is the first bash.exe on the PATH
(the WSL launcher on this machine), which the peer refusal above relies on.
CHANGELOG: both plugins' unreleased entries (0.47.2, 0.28.3) list these.
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01C9t8G7o2vTPAxSFNb8rP4n
* fix(ruflo-console): what running every view on a real Windows machine turned up
The previous commits came from pattern scans. This one comes from running the
console's own readers against a real Windows machine (every view through the
standalone terminal; the plugin catalog, ADR loader and workflow reader called
directly), plus a complete triage of the path-handling patterns in hooks/.
Found by the real run:
- The standalone terminal left state.configDir null when CLAUDE_CONFIG_DIR was
unset (the usual case), so the installed plugins, the marketplaces and the
workflow runs were all "unreadable". It now falls back to <home>/.claude, as
register.ts does in the engine. Not Windows-specific.
- research.ts kept its own POSIX-only safeInstallPath, so ruflo-goals was never
found on Windows. It uses the Windows-aware one in cost-ledger.ts (same
character set on POSIX); on this machine goalsOf now answers ready with the
real C:\ root.
Found by triaging every `split('/')`, `lastIndexOf('/')` and `startsWith('/')`:
- isRunPath, isRunFile and isUnder checked for ".." only between slashes, so a
segment written with a backslash passed on Windows; a config folder ending in
a backslash did not match. They use hasParentSegment / trimTrailing, as does
under().
- The menu and the boot screen named the project by splitting cwd on "/", which
printed a whole C:\ path. baseOf in paths.ts.
Test-suite and cycle fixes so the smoke's own command passes here:
- views/pane built BODIES = { menu: menuView, ... } at load time, but
views/menu reaches pane through mission-control > mission-claude > model-tools,
so loading menu first left menuView undefined under the test runner (native
ESM hoists the function; the app loads pane first). It is read at call time.
- tui-actions waited a fixed 1.2 s for a 1 s retry plus a redraw, and failed
under CPU contention in a full run (also on the baseline). It waits for the
outcome it asserts, up to 10 s.
Verified: the smoke's exact command (every spec, 30 s timeout) is 239 files
passed, 0 failed, 3486 tests; the console smoke is 20 passed, 0 failed; all 34
views render with exit 0 and no stderr; an ADR project with a space in its path
and CRLF records loads and plans a status change keeping its CRLF.
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01C9t8G7o2vTPAxSFNb8rP4n
* fix(ruflo-console): the install record of a plugin that applies to this project, compared the Windows way
installed_plugins.json holds one record per install of a plugin, and a project-scope
record names the project it was made for. The snapshot took entries[0], so a plugin
installed for several projects showed another project's version and install folder.
On a real Windows machine ruflo-console@ruflo has five records (four project, one
user) and the first is a different project's 0.44.7; everything derived from it,
the version shown and the installPath used to find a plugin's scripts, could point
at the wrong copy.
- parseInstalled(text, cwd) picks the project or local record whose projectPath is
the session folder or holds it, else the user record, else the first.
- insideOrSame in paths.ts is that comparison, Windows-aware (case, either
separator, a folder inside the project); hooks/updates.ts decides which installs
to update with it too. It compared with === and startsWith(path + "/"), so on
Windows a session in a subfolder of the project, or with a different drive-letter
case, did not count the project's own install and left it stale.
tui-actions: "a read runs at once" waited a fixed 500 ms for a stand-in CLI process
to start; it waits for the run it asserts, and its neighbour, which failed only
because that run landed late in the shared log, no longer does.
Tests (windows-path-guards.spec.ts): the record chosen for the project under both
separators, other letter case, a subfolder, a sibling sharing the prefix, no match,
no user record, no cwd; the updater's rule; insideOrSame. Verified: the smoke's
exact command (every spec, 30 s timeout) is 239 files passed, 0 failed, 3491 tests.
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01C9t8G7o2vTPAxSFNb8rP4n
* test(ruflo-console): the focus-lost spec waits for the output to go quiet before it asserts silence
"stops drawing while the terminal reports focus lost" marked the output length 60 ms
after the focus-lost report and then expected no growth. A frame already in flight
when focus was lost lands after that mark on a busy machine, which reads as the page
still drawing; the smoke's first vitest pass failed on it and only the retry passed.
It now waits until the output stops changing before it marks, still asserts 500 ms of
silence after that, and waits for the redraw on focus regained instead of a fixed
300 ms. Passes 4 of 4 isolated runs.
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01C9t8G7o2vTPAxSFNb8rP4n
* test(ruflo-console): the hostile-regex spec bounds the scan's CPU time, not the wall clock
"a slow pattern over ten thousand 200-character events stops at its budget" asserted
that the scan finished in under 2500 ms of wall-clock time. The scan is CPU-bound, and
the wall clock also counts every other worker of a parallel run, so the spec passed
alone (all 12 specs of the file in 316 ms) and failed in full runs, including both
tries of the smoke's step 14 on the previous HEAD. It now bounds the scan's CPU time
(process.cpuUsage) at the same 2500 ms and keeps a 30 s wall-clock bound as a guard
against a hang. The product code is untouched.
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01C9t8G7o2vTPAxSFNb8rP4n
* test(ruflo-console): the host-boundary spec does not scan the mutation specs' temporary files
tui-boundary.spec.ts reads every .ts under hooks/ when it loads. adr-mutation and
mission-advisor-mutation make temporary .mut-N-*.ts copies of hooks modules inside
hooks/ and delete them, in other workers of the same run. Two ways that disturbs this
spec: a copy that is still there is checked as if it were a hooks module (shown with a
throwaway .mut- file that imports a Node module: the spec failed before this change,
passes after), and a copy listed and then deleted can throw at load, which fails the
whole file (the smoke's step 14 showed one such file-level failure that did not repeat;
six runs of the three specs together did not reproduce it, so that part is the likely
cause, not a demonstrated one).
The walk skips .mut- names and tolerates a file that vanishes. A real violation in
hooks/ is still caught (checked with a throwaway file).
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01C9t8G7o2vTPAxSFNb8rP4n
* fix(ruflo-console): the mod loads again: $.env.get takes a literal name
An earlier commit on this branch (
|
||
|
|
d7fcaf3b25 |
fix(ruflo-mods): load again: the ruRE offer no longer registers a second bare session.start, tool.call and turn.complete (0.7.1, #4485) (#4487)
Co-authored-by: r <r@x> |
||
|
|
c365d37280 |
chore(marketplace): pin agentic-qe-fleet to v3.15.13 (#4484)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
f02989a78c |
fix(managed): refuse . and .. resource ids; guard reads common argument wrappers (ruflo-agent 0.4.1) (#4478)
Follow-up to the 3.63.0 security review (low severity #6 and #9); documents #7 and #8 as known limits. Co-authored-by: r <r@x> |
||
|
|
db141ba70e |
feat: managed workflows, unified console runs and verified advisory learning (#4471)
* feat(agent): add bounded managed dynamic workflows and verified lifecycle observation * feat(plugins): integrate managed workflows with mod policy and capability discovery * feat(managed): unify console runs and verified advisory learning * fix(managed): hydrate native recall receipts validated on ruOS * docs(managed): record authenticated console host blocker * docs(managed): qualify installed console and compatible native host * feat(managed): integrate verified cycles and isolate native memory * fix(managed): enforce offline native models and qualify feedback E2E * fix(managed): independent security and correctness review findings - gate managed_agent_interrupt through the managed_agent_control policy; terminate obeys the allowlist and deletes only its own environment when RUFLO_MANAGED_CONTROL=1 - track only events from the acknowledged message so a later poll cannot report the previous turn as finished - require the canonical base64 verifier signature so one receipt cannot fill the ledger - register RUFLO_MANAGED_AGENTS_BASE_URL as a trust-boundary env var (env-precedence audit) and key the credential scope marker with a per-process HMAC (CodeQL) - best-effort local snapshot writes; report messageId when a prompt fails after it was sent - console: rescheduling is running, budget/action-blocked sessions are active, not finished - document the remaining known limits in ADR 0004 Co-Authored-By: RuFlo <ruv@ruv.net> * docs: user guide section for managed cloud agents; correct ruflo-agent README counts Co-Authored-By: RuFlo <ruv@ruv.net> * fix(managed): scope marker is a generation number, never a hash of the API key (CodeQL) Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
8ec06c0ee8 |
feat(ai-team): guard team_create/team_update, skill handoffs, ruflo agent linkage, /team-remember and /team-board (0.3.5) (#4475)
The guard already covered task_update results (it screens the whole call), but team_create/team_update carry shared free text too and were unscreened. Skills now end with the skill to use next, the three agents say how ruflo agents do the work the service only records, and two commands cover memory and the board. Co-authored-by: r <r@x> |
||
|
|
979cce0ab5 |
fix(x-gateway): argument-less tools/call, bare-host POST, reject diagnostics (0.9.1) (#4468)
* fix(x-gateway): argument-less tools/call, bare-host POST, and reject diagnostics (0.9.1) Co-Authored-By: RuFlo <ruv@ruv.net> * ci: baseline the x-gateway registration-compat spec with its node:test siblings Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
d3948da2d5 |
fix(ai-team): newest-first lists, complete evidence audit, honest version (0.3.4) (#4467)
Firestore reads without orderBy return document-id order, so capped reads kept an arbitrary slice: the board showed an arbitrary 100 runs once a tenant had more, and evidence exports read the first 1000 audit records then filtered, dropping a run's events on busy tenants. Lists now order newest first; evidence queries audit by target (30-value in-chunks). package.json still said 0.1.6 so /health could not identify a deployment. Adds Firestore store tests with a limit-after-order double. Co-authored-by: r <r@x> |
||
|
|
24450bf9f7 |
feat(rure): rure_cuda_launch_plan — static occupancy plan for CUDA kernels (ADR-501) (#4464)
New read-only tool: per kernel and architecture, theoretical occupancy at several block sizes, what limits it, the best sizes and flags; optionally the text of a driver-API harness the person can build to check it on their own GPU. Nothing is compiled, loaded or run by ruRE. The model equals NVIDIA's cuda_occupancy.h on 1,770,216 combinations (8 archs, limiting sets included; fingerprints committed so CI repeats it) and the CUDA driver on real GPUs: RTX 5080, RTX 3090, RTX 4090, A100, H100. Found on hardware: from sm_90 the cubin's shared size already includes the driver's 1 KiB reservation. Also fixes the reader reporting sm_5 for standalone cubins from CUDA 12 (ELF OS ABI 51 keeps the SM number in the low byte of e_flags); real CUDA 12.8 cubins added. ruflo-rure 0.6.0. Co-authored-by: r <r@x> |
||
|
|
7c37957f55 |
Fix browser doctor path from unrelated working directories (#4454)
Resolve the structural smoke script through CLAUDE_PLUGIN_ROOT. Bump the browser plugin patch version and align its smoke assertion to make the fix visible to installed copies. |
||
|
|
d36d72a9ff |
feat(ruflo-console): ruRE can read an outside folder the person allows (ADR-499, console 0.48.0) (#4452)
New option rureFolders (name=/folder pairs); a sample names one as @name/sub/file. The preflight resolves the alias after checking the folder and every part below it for links, and swaps the absolute path into the row's -p JSON. Option writes stay install-class and always ask. Runner stays at 500 lines (preflight now gets options). Co-authored-by: r <r@x> |
||
|
|
cac404c54c |
feat(ruflo-mods): rureOffer — offer ruRE when the model reads a binary (ADR-498) (#4446)
Off by default. Observes Read/Write/Edit/MultiEdit file_path, and at the end of a main-loop turn appends one fixed-wording line naming up to three validated project-relative binary/library/asar/CUDA files (12 per session, each once). Offer only: never runs ruRE, never denies or edits a call. Inert without a ruRE MCP tool. Harness gains World.tools and $.tool.list. Co-authored-by: r <r@x> |
||
|
|
2bc73c0994 |
fix(deps): zod 4.6.7 in graph-intelligence and browser, time-boxed accepted entries for nested zod 3 (#4442) (#4444)
* fix(deps): zod 4.6.7 in graph-intelligence and browser; time-boxed accepted entries for nested zod 3 (#4442) GHSA-mrhx-c7xc-m3w5 (zod <4.6.6) turned the supply-chain audit red for every PR. Both projects' own zod dependency moves ^3.22.4 -> ^4.6.7; the only code change zod 4 needs is a key schema on z.record (7 calls). The regenerated locks are now consistent with package.json (npm ci works). The audit still names zod because other packages (@claude-flow/cli|hooks|security|plugin-gastown-bridge, agentic-flow) keep nested zod 3.25.76 copies; two time-boxed accepted entries (expire 2026-11-23, tracked in #4442) cover those. Needs CODEOWNER review (policy file). Co-Authored-By: RuFlo <ruv@ruv.net> * fix(deps): pnpm lock follows the browser package's zod 4.6.7 The first commit changed v3/@claude-flow/browser/package.json but not v3/pnpm-lock.yaml, so every 'pnpm install --frozen-lockfile' job failed with ERR_PNPM_OUTDATED_LOCKFILE. Minimal edit: the browser importer's zod specifier/version and the /zod@4.6.7 package block (registry integrity). Proved with a clean 'pnpm install --frozen-lockfile', then pnpm -r build, browser tsc --noEmit and its tests (231 passed). Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
7564f7cefa |
feat(ruflo-console): CUDA row on the ruRE page, DETECT routes and a hint from the native reader (ADR-497) (#4443)
* feat(ruflo-console): CUDA row on the ruRE page, DETECT routes and a hint from the native reader (ADR-497) dt-re-cuda calls rure_analyze_cuda; cudaLines shows fatbin entries, kernels with registers/code/constant/shared memory, and PTX, from real captured CLI answers. DETECT sends .cubin/.fatbin/.ptx to it, and the native reader points a CUDA host binary at it. Console 0.47.0. Needs a CLI with the tool (after 3.60.1). Co-Authored-By: RuFlo <ruv@ruv.net> * test(ruflo-console): CUDA e2e must handle a Node without zstd CI's Test Suite job runs Node 20.20.2, which has no zstd, so the CLI correctly reported the CUDA 13 PTX as unread and the test that expected it to be read failed. The test now expects the read where zstd exists and the explicit 'this Node cannot read zstd' note where it does not. Run under both Node 22.23.2 and 20.20.2. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
dd5d66cdb4 |
feat(rure): rure_analyze_cuda — CUDA fatbin, cubin and PTX static analysis (ADR-0006) (#4441)
* feat(rure): rure_analyze_cuda — CUDA fatbin, cubin and PTX static analysis (ADR-0006) New read-only MCP tool and an original pure-TypeScript reader: fatbin containers and entries (kind, sm_NN, zstd/LZ4 under size caps), cubin kernels from the symbol table with registers (EIATTR_REGCOUNT), code size and constant/shared/local memory, and PTX version/target/kernel names. Parses, never executes; strings screened by AIDefence; decompression budget charged per attempt. Checked against real nvcc 12.8 and 13.0 output (sm_75/80/90) and cuobjdump: committed fixtures with recorded ground truth, plus a live test that compiles with a local nvcc. ruflo-rure 0.5.0. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(rure): rure_analyze_cuda description carries the ADR-112 'Use when' guidance The tool-description audit (ADR-112) failed the PR: one tool without guidance. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(rure): linear-time PTX sniff and scan (CodeQL js/redos, plus a quadratic one it did not flag) looksLikePtx used a lazy comment pattern inside a repeated group, which backtracks exponentially (CodeQL js/redos); it is now a forward scan. The directive regexes in scanPtx matched with ^\s*, which rescans a whole run of blank lines at every line start: 80000 blank lines took 4.6 s and 320000 took 71 s. They now match space and tab only and bound the rest. Tests: pathological comment structure, and long blank-line and whitespace runs, all under 500 ms. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
bb9ab9eee3 |
feat(ruflo-console): ruRE DETECT, long lists, and a structured view for Claude (ADR-496) (#4440)
* feat(ruflo-console): ruRE DETECT, long lists, and a structured view for Claude (ADR-496) DETECT picks the reader from the folder/file kind and extension (never the writing one). Long lists wrap onto their own lines (60 items, 120 lines in all). console_run answers with a ruRE run's lines and console_state carries a rure block, every string through the model path. preflight may now return replacement args/label/lab/note/lines. Console 0.46.0. Co-Authored-By: RuFlo <ruv@ruv.net> * test(ruflo-console): DETECT e2e must not assume the format line is first Without AIDefence (CI) the reader puts a 'not screened' caveat first, so the ELF/PE assertions at index 0 failed on the Ubuntu runner. Look for the format line anywhere in the result. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
39f5942c02 |
fix(ruflo-console): ruRE refuses a sample that is a link (ADR-495) (#4439)
The sample rule was textual (relative, no ..); a link inside the project that points outside it passed and the rure_* tools opened it. Every ruRE row now walks the sample on disk before it runs (new ActionSpec.preflight, awaited by the runner), for the page and for console_run alike. Console 0.45.2. Also fixes ruRE comments citing ADR-492 (it is ADR-494). Co-authored-by: r <r@x> |
||
|
|
43a3954350 |
fix(ruflo-console): accept Windows paths in the autopilot envelope (follow-up to #4434 R1) (#4436)
* fix(console): accept Windows paths in the autopilot envelope #4434 added Windows path parity across the console, but the autopilot envelope's own path validator still rejected any `\`, and the downstream `isProtectedPath` and `pathAllowed` guards compared with POSIX-only string ops. The code is unreachable today because autopilot start is still gated off on Windows (ap-windows-gate.spec.ts), but it is the next thing a Windows user will trip on when that gate is lifted — the natural `C:\work\app` form, and every UNC path, is refused with the opaque "is not an absolute folder below the root with no .." error. Four narrow fixes in `hooks/data/ap-envelope.ts`, driven by the separator-aware helpers already in `hooks/data/paths.ts`: - `isProtectedPath`: fold `\` to `/` on a drive-lettered or UNC path before the protected-dir compare. - `validateEnvelope` path check: drop the unconditional `path.includes('\')` reject (it contradicted `isAbsolutePath` which already accepts `C:\x` and `\srv\share`), and tighten the drive-root regex `/^[A-Za-z]:\/?$/` → `/^[A-Za-z]:[\/]?$/` so `C:\` is still refused explicitly (was previously caught by the backslash reject). - `validateEnvelope` output canonicalisation: use `trimTrailing` instead of `/\/+$/` replace, so a trailing `\` on a Windows path is stripped the way `/` already is on POSIX. - `pathAllowed`: use `hasParentSegment`, `samePath` and `below` from paths.ts. A file at `C:\work\app\file.ts` is now inside envelope path `C:\work\app` (and `c:\WORK\app\file.ts` is too), while `C:\work\application\file.ts` still is not. Semantics on a POSIX envelope are unchanged — the new helpers degrade exactly to their old string ops when neither side is a Windows path. New `tests/ap-envelope-windows-paths.spec.ts` pins what should and should not be accepted (13 cases: backslash drive, forward-slash drive, UNC, trailing-separator strip, `..`, bare-drive-root, protected-folder, pathAllowed under case + separator variation, prefix-match rejection). Verified on Windows 11: new spec 13/13, ap-core.spec.ts 31/31 (no POSIX regression), 5 envelope-adjacent specs 64/64 combined, full console suite 3444 total · 3399 pass · 13 fail — same pre-existing baseline as #4434's own run, zero regressions. Follow-up to #4434 R1 (https://github.com/ruvnet/ruflo/pull/4434#issuecomment-6371423874). Co-Authored-By: RuFlo <ruv@ruv.net> * fix: keep the backslash reject for POSIX-rooted envelope paths #4436 review (@ruvnet): dropping `path.includes('\')` outright also dropped the refusal for a POSIX-rooted path with backslashes smuggled in. `/work/app\..\..\other` passes `isAbsolutePath` (POSIX form), and `hasParentSegment` splits POSIX-only when `isWindowsPath` says the path is not Windows, so the `..` segments are invisible to it. On a Windows host, that leading-`/` path then resolves to `\other`, outside the folder the user named. Unreachable today because autopilot is still gated off on Windows, but it is the guard that gate's removal depends on. Keep the backslash reject, but only for non-Windows paths (POSIX should never have `\` in its path). The native Windows forms `C:\work\app` and `\srv\share\app` continue to pass; the mixed `/work/app\..\..\other` form is refused as before. Added case to tests/ap-envelope-windows-paths.spec.ts. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: RuFlo <ruv@ruv.net> |
||
|
|
ea25a05abe |
fix(ruflo-console): Windows writes go through the host filesystem (#4433) (#4434)
* test(console): fixture file system accepts Windows drive paths
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): Windows project folders are project folders (ADRs, export, catalog, mission cost)
Guards that accepted only a path starting with "/" treated a Windows session
folder (C:\Users\x\proj) as "no project folder is known". Adds hooks/data/paths.ts
(pure string helpers: isAbsolutePath, joinPath, samePath, plus hasParentSegment,
normalizePath, below, trimTrailing, isWindowsPath) and uses it at the absolute-path
guards in adr, event-export, wf-file, plugin-catalog, mission-cost (and the ledger
install path), wf-worktrees, skills-lab, wf-drill-io, facts, ap-envelope and
register. Each caller keeps its own ".." refusal; POSIX paths take the same code
path as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): protected autopilot folders match ignoring case on Windows paths
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): find the home folder on Windows (sessions, plugin health, What's new)
Implements homeOf function that checks HOME → USERPROFILE → HOMEDRIVE+HOMEPATH
with comprehensive test coverage. Fixes state.home initialization on Windows
where HOME is unset.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): disk writes work on Windows through the host file API
Windows has none of uname, dd, sh, install, mkdir or cp in Claude Code's process
environment, so every console write (Events, Timeline, autopilot journal, ADRs,
exports, .gitignore) failed there. New write flavor host-fs, chosen on win32 (no
uname is run), carries the enumerated writes through $.fs.read/write/exists via
writeVia. Linux GNU and macOS/BSD argv are unchanged (pinned by test).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): autopilot kill flag can be cleared on Windows; document host-fs create window
Windows has no delete, so clearKill rewrites the KILL flag with a fixed marker and
killSeen treats exactly that content as not set (host-fs only); stopNow rewrites
the flag empty so a second stop is seen. POSIX rm/stat behaviour is unchanged.
write-via and wf-file now say host-fs creates are check-then-write (no O_EXCL).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): no Linux-only process probe on Windows; clear probe timers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): a hive started from the console shows at once
When a start's CLI run exited 0 but its verify fails (the CLI can return
before its state file lands), wait 1 s via host.after, read fresh and verify
once more before reporting the "expected ..." text. No retry when the run
failed; exactly one retry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(console): pin Windows containment, parent-segment and UNC rules in paths.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): workspace keys equal across drive-letter case and trailing separator
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): autopilot start is refused on Windows until atomic appends and Windows-aware path checks exist
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore(console): 0.42.2 changelog and version
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(console): read home variables by literal name so the module loads
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* post-merge cleanup: finish #4036 integration
The Option B merge commit (
|
||
|
|
e8c98eb916 |
feat(ruflo-console): ruRE page in TOOLS — static reverse engineering from the console (ADR-494) (#4430)
* feat(ruflo-console): ruRE page in TOOLS — static reverse engineering from the console (ADR-494) A TOOLS page for the six rure_* tools of ruflo-rure, built the way the Sandbox page is: six Dev Tools entries (dt-re-*) drawn on a page of their own, so they share the confirm gate, palette ids and result panel. Five rows are $0 reads; UNPACK .ASAR writes outside the project and asks first. A new 'sample' field takes only a project-relative path. Results are the analyzed file's own text and pass plain() so a hostile binary cannot put an escape on the terminal; a number that is not a measurement reads n/a. A CLI without the tools says to update. Enter in a ruRE field runs that page's row. Tests: rure-page.spec.ts (catalog vs real schemas, readers vs real captured CLI output, hostile answers, page, guide, palette, Enter routing) and rure-e2e.spec.ts (every row's argv through the built CLI on real files, including a hostile ELF; fails with plain() removed). Console 0.44.7 -> 0.45.0; ruflo-rure 0.4.1 -> 0.4.2 (docs only). Co-Authored-By: RuFlo <ruv@ruv.net> * test(ruflo-console): ruRE e2e accepts either AIDefence outcome (CI has no AIDefence) The .NET e2e asserted a string literal was 'hidden by AIDefence', true only where the optional package is installed. In CI the tool reports screened:false and the page says 'not screened: AIDefence was unavailable'. Both are honest; the test now pins that the screening state is always on screen. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(ruflo-console): ruRE EVM result no longer shows a doubled ellipsis plain() already marks a clipped value; the reader added a second one to the event topic and the IPFS hash. Test pins it. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: r <r@x> |
||
|
|
7d18ee7a03 |
chore(marketplace): pin agentic-qe-fleet to v3.15.12 (#4419)
Move the external agentic-qe-fleet entry from v3.15.11 (221d6de1) to v3.15.12 (90a91fe3), the current npm latest, and update the README links, the external-plugins test fixture and ADR-484. Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
a2465d80ba |
fix(cost-tracker): run memory store in CLAUDE_FLOW_CWD (#4397 part 2) (#4407)
The Stop hook spawned the CLI with no cwd, so it created a stray .swarm/memory.db in the session project instead of the MCP data root. Pass cwd: CLAUDE_FLOW_CWD || process.cwd(). Co-authored-by: r <r@x> |
||
|
|
92731bc6bf |
fix(ruflo-rure): security review fixes — gate coverage, symlinks, ReDoS, parser budgets (#4403)
Closes the findings from an independent review of ruRE 0.1.0-0.4.0: screen every attacker-derived string and report screened/skippedFiles, walk without following symlinks under a total-byte budget, linear EVM file sniffing, an iteration budget for ELF/PE table walks, guarded ELF e_entry, and single-descriptor reads. Each fix has a test that fails without it. Co-authored-by: r <r@x> |
||
|
|
e6ec9cd687 |
feat(ruflo-rure): Phase 4 — EVM bytecode static inventory (#4402)
Adds rure_analyze_evm per ADR-0005: aligned disassembly and pattern scan for dispatcher selectors, hazardous opcodes, embedded addresses, event topics, EIP-1167 minimal proxies, solc metadata and embedded strings. No interpreter, RPC or network; PUSH data is never read as opcodes; input capped at 256 KiB; embedded strings pass the AIDefence gate. Co-authored-by: r <r@x> |
||
|
|
d835597e0b |
feat(ruflo-rure): Phase 3 — .NET assembly metadata inspection (#4401)
Adds rure_analyze_dotnet per ADR-0004: an original pure-TypeScript ECMA-335 metadata reader (assembly identity and references, types, method count, P/Invoke imports, user-string literals, entry point). No dependency, no IL decoding, never loads or runs the assembly. Table extents are validated against the stream before any row is read, and all extracted text passes through the AIDefence gate. Co-authored-by: r <r@x> |
||
|
|
b31d2b0471 |
feat(ruflo-rure): Phase 2 — native binary static analysis (ELF/PE/Mach-O) (#4400)
Adds rure_analyze_binary per ADR-0003: an original pure-TypeScript container parser (format, arch, entry, sections, linked libraries, imported/exported symbols, optional strings). No disassembler, no new dependency, never loads or executes the target. Reads are bounds-checked, tables and strings are capped, files over 128 MiB are refused, and all extracted text passes through the AIDefence gate. Co-authored-by: r <r@x> |