Commit Graph
74 Commits
Author SHA1 Message Date
randRuFlo c53bed71e3 feat(console,mods): session workspace on the Room: attention queue, session browser, preview (ADR-486)
Needs-you queue (approvals, questions, failures, finished-unread) across Claude Code, Codex and Ruflo
sessions, a browser grouped by repository and worktree, and a preview of the selected session. Local,
read-only discovery (no model call, no process); ambiguous identity goes to an unassigned bucket;
finished work clears only after its preview was drawn; transcript text never reaches a model, the
state, the disk or a text answer. ruflo-mods gains an optional counts-only attention row.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-09 17:18:27 -04:00
ruv 7670a02849 docs(plugins): CHANGELOG.md for every plugin in the ADR-478 format, derived from git history
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 14:37:29 -04:00
ruv 04ff98bb32 fix(mods): a toast needs no engine.create (bind at session.start too), a throwing clock falls back to the wall clock; update the cost ladder expectation in the v3 mods contract
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 13:08:53 -04:00
ruv 146febd999 feat(mods): shared toast system with levels, dedupe, persistence and Settings (ADR-477)
One dependency-free policy (canonical in ruflo-mods, byte-identical copies in console,
swarm and protector, checked by scripts/sync-toast-policy.mjs and each smoke.sh): level
prefixes, one washed line of at most 120 characters, 60 s de-duplication, four toasts a
minute per source with errors held and counted, the person's all/important/off setting and
per-source mute (console Settings, mirrored to a file the others read), and a digest of
every toast kept for the console's Events page. All call sites migrated; new toasts for a
mission that finishes or fails and a swarm subagent that fails or a loop that is stuck.

Versions: console 0.37.0, swarm 0.3.4, protector 0.1.1, mods 0.3.16.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 12:50:30 -04:00
ruv a65be10ed4 feat(mods): shared toast policy and its call sites (ADR-477), work in progress
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 12:40:10 -04:00
ruv 38c30b1120 chore(mods): ruflo-mods 0.3.15 so marketplace users receive the #3791-#3805 fixes
The fixes merged in #3873 without a version bump, so 'claude plugin update'
saw no new version.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 03:51:38 -04:00
ruv e5d887af43 test(ruflo-mods): the /clear rollup record keeps the ending session's rung, the next starts at OK (#3795)
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 00:58:38 -04:00
ruv 6258d60127 fix(guard): decode $'...' escapes as bash does; adversarial and benign tables for the root-delete guard (#3791)
$'\x2f' and $'\x72m' name the root and rm without any expansion, and a
\' inside $'...' does not close the string. The scanner now decodes ANSI-C
escapes (octal, \x, \u/\U, \c, the single-letter set, NUL ends the string)
in all four copies, and the parity table gains wrapper, flag-spelling,
benign look-alike and documented-limit rows.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 00:58:38 -04:00
ruv 93b6870a1d fix(ruflo-mods): trust gate judges a glob or a negation by what it selects (#3801)
The scan reports hook patterns as written, so tool.*, prompt.*, agent.* or
!tool.describe hooked every risky event without matching a RISKY_EVENTS key.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 72c84437d4 fix(ruflo-mods): trust gate treats process.spawn, mcp.call/connect, session.send, config.set, prompt.submit and agent.spawn as risky; names a reload that gains risk (#3787, #3801)
refuse-risky admitted a user-tier mod that ran host commands through
$.process.spawn (process.run was listed) or through any MCP tool via
$.mcp.call, and one that steered every prompt (prompt.submit) or every
subagent (agent.spawn). Observe told the person "no risky calls or hooks".

The risk sets now cover every call in the engine's $ API that reaches
outside the session, and the two hooks from #3787. Observe-mode logging is
keyed on provenance plus the risk set, so a hot reload that gains a risky
call or hook is named again ("and every reload"), and the same risk is not
repeated.

(cherry picked from commit 566bfdc8a20409f763d312e1ae34bcd0fc6c0515)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 810fb0de48 test(ruflo-mods): pin registeredEvents to what register() hooks across every option combination (#3805)
Adversarial review follow-up: the list test only covered the conditions it
named, and the doc comment claimed smoke.sh guarded drift (it checks names,
not conditions). The matrix test calls register() with a recording on() for
256 option combinations and compares.

(cherry picked from commit d857b4d136)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov fff705bb3a fix(ruflo-mods): capabilityProbe counts session.measure, agent.spawn and plugin.register only where the options hook them (#3805)
registeredEvents() listed them as always registered, so with default options
the probe counted session.measure as "fired" with no ruflo hook running and
listed agent.spawn as "never fired" although the mod never hooked it (and
plugin.register under modTrust: off).

(cherry picked from commit 3a146c08dc)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 8613d5bdfe fix(ruflo-mods): stand down for legacy CLI hooks route|post-edit settings and check the %USERPROFILE% helper (#3803)
Projects initialised before hook-handler.cjs (e.g. settings-generator at
d7212d25b wrote `npx claude-flow@v3alpha hooks route --task "$PROMPT"`) run
the CLI's own hooks command, which never reads RUFLO_MODS_OWNS. The mod saw
no classic route/post-edit there, owned both, and every prompt was routed
twice (the CLI still prints its block with the handshake set, verified on
3.52.0). A settings hook running claude-flow / @claude-flow/cli / ruflo
`hooks route|post-edit` now makes the mod stand down for that event.

On Windows the generated hook falls back to
%USERPROFILE%\.claude\helpers\hook-handler.cjs; helperHonours now checks it
beside the project root and $HOME.

(cherry picked from commit 4dec48e9f5)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov c79f66e89f fix(ruflo-mods): keep main's Google-key and JWT matches when glued to a dash; no ^ at mid-line window starts (#3798)
Fourth review (differential vs main over 154k inputs): two secret shapes
main caught were missed after the earlier tightening - a Google key glued to
"-suffix" (the trailing lookahead rejected it; \b now also ends it) and a
JWT after a '-' (the new lookbehind; the rule now starts at the first eyJ
after a '-' or the run start, still once per run and linear). A later window
that starts mid-line gets a lead character so ^ cannot treat a benign
"system:" there as a role tag. Inbound and outbound now build the windows
once and pass them to scanWindows(). Two tests (each fails on the previous
head); corpus unchanged.

(cherry picked from commit 5e9cec209c)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 0e505ffcef fix(ruflo-mods): screen three readings so stripping or folding never glues a phrase to the word before it (#3798)
Third review: stripping every default-ignorable character and NFKC folding
joined what followed to the word before it, so a leading \b or lookbehind
failed: "x" + soft hyphen + "Ignore all previous instructions", a circled
digit before AKIA..., and a zero-width space before an SSN all passed, where
main caught them (129 of 1,093 sampled inputs).

windows() now screens three readings: the folded one, main's literal one
(only its original invisible set removed) and a spaced one (invisible
characters become spaces), each whitespace-collapsed and windowed, so cost
stays linear. The role-tag rule is back to main's \s* (linear after the
collapse; it caught "system\n:"), and the key rule accepts doubled or mixed
separators again (my--token=). One test pins seven of these cases; it fails
on the previous head.

(cherry picked from commit 000f677c36)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 6f88e5e9ae fix(ruflo-mods): screens stay linear on blank lines and repeated token starts; whitespace padding cannot straddle a window (#3798)
Second review: once the whole text is screened, two older rules that were
only ever run on a 20k prefix became the cost: `fake role tags` (^\s* with
m) is quadratic on runs of newlines (1 MB of "\n": 16.8 s) and `jwt` (\beyJ)
restarts at every '-' ("-eyJ" x 1 MB: 8.2 s). Unbounded \s in shell pipe,
key assignment and bearer also let padding carry a match across a window.

- bare() collapses each whitespace run to one space or newline before
  windowing (linear; screening only tests text, never returns it).
- jwt starts once per token run; the anchored role-tag half uses [ \t].
- key assignment accepts a CLI flag prefix again (--password=, --token=),
  which main caught.
Three tests pin these (1 MB of blank lines and "-eyJ" under 1.5 s, a pipe
padded with 1.1k-25k spaces at window boundaries, CLI flags); each fails on
the previous head.

(cherry picked from commit 2ffd534404)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov e281da31a4 fix(ruflo-mods): key-assignment rule is linear and ends at the credential name; windows start at whitespace (#3798)
Adversarial review of the previous commit:
- the suffix group after the keyword backtracked against it: 1 MB of
  'token_' took 6.4 s through scan() (10 MB: 71 s), and with the 20k cap gone
  a peer controlled the input. The keyword must now end the name, optionally
  followed by _key / _access_key; 1 MB of 'token_' screens in milliseconds.
- the same group flagged config names that only start with a keyword
  (TOKEN_URL=, MAX_TOKENS=, session_token_ttl=, CREDENTIALS_FILE=); those
  pass again, and an all-digit value is no longer a credential.
- a later window began mid-word, so its lookbehind, \b and ^ saw a false
  start of text ('q' * 18976 + 'secret=...' was refused, unpadded it passes).
  Later windows now start after whitespace within 256 characters; the 1,024
  overlap still covers every rule.
Three tests pin these; each fails on the previous head.

(cherry picked from commit 60a5f05340)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 3a3f8c3a61 fix(ruflo-mods): screen the whole text, strip every default-ignorable character, catch more secret shapes (#3798)
The shared screen behind deliveryScreen, compactCarry and guidance safeText:

- scanned only the first 20,000 characters, so padding pushed an injection
  or a secret past it. It now scans the whole text in overlapping 20k
  windows (1k overlap, far longer than any rule spans): still linear.
- stripped a fixed list of invisible characters. It now strips every
  default-ignorable code point (soft hyphen, CGJ, Mongolian VS, variation
  selectors, bidi isolates, tags) plus C0/C1 and line/paragraph separators,
  then NFKC-folds fullwidth forms.
- missed GITHUB_TOKEN= / aws_secret_access_key = / "client_secret": (the
  keyword inside an _ or - separated name), PGP armored private keys, Google
  keys ending in '-', and Slack xapp- tokens.

delivery/screen.ts reuses the shared windows instead of its own copy of the
invisible set and the 20k slice. The 50/50 acceptance corpus is unchanged
(50/50 caught, 1/50 benign flagged, as before).

(cherry picked from commit b1cc41c887)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 42424201c6 fix(ruflo-mods): /resume also gives the next session its own rollup record; redraw after the budget reset (#3795)
Re-review follow-ups: the engine contract says the process also goes on
under another session after a resume (no session.start), so the rollup
resets on reason resume as on clear (new test). The cost reset stays on
clear only until /resume cost behaviour is measured live. The cost reset
now redraws the status line, which otherwise showed the old rung until the
next prompt.

(cherry picked from commit 927799ae24)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov c486e0ec26 fix(ruflo-mods): reset per-session state on session.end(reason: clear), not session.start (#3795)
Adversarial review: the engine contract (2.1.289 types) says session.start
fires once per process or fresh load, "never /clear"; /clear is seen as
session.end with reason clear and no session.start follows. The previous
commit reset on session.start, so it never ran on a real /clear, and its
tests faked one with an `as never` cast.

- rollup: after writing the ending session's record, a clear resets the
  counters and the written flag, so the next session gets its own record.
- cost: a session.end matcher on reason clear restarts the ladder and the
  hard stop. Registered after the rollup, which records the rung first. Any
  other end reason keeps the hard stop (new test).
- tests replay the real sequence: session.end(clear), work, session.end.

Live (2.1.289, --plugin-dir, tmux): prompt, /clear, prompt, /exit now writes
two ledger records; main writes one.

(cherry picked from commit 3630744aea)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov ffd882365e fix(ruflo-mods): rollup and budget start over at each session.start, so /clear gets its own session (#3795)
/clear ends a session and starts the next in the same process without
re-running register, so the process-scoped state carried over:

- sessionRollup set `written` once and never reset it, so every session after
  the first /clear went unrecorded (measured live on 2.1.289), and its
  counters accumulated. The rollup now resets on session.start and records
  routed/tightened as this session's share.
- the cost ladder kept the previous session's announced rung and HARD_STOP
  level, though the engine counts the new session's cost from zero
  ($0.07 -> $0.06 across /clear, measured live). The ladder and the hard stop
  now start over at session.start; within a session a rung is still told once.

The engine refuses a second matcher-less session.start, so the cost hook uses
the same match-everything surface matcher as the rollup hook.

(cherry picked from commit 0f9f1b99f2)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 061efa3b40 fix(ruflo-mods): the observation queue and a quoted path no longer read as "missing" (#3793)
Adversarial review follow-ups in the same class:
- flushObservations read and parsed in one try and applied isMissing to the
  parse error, so a corrupt queue quoting ENOENT was overwritten, against its
  own "corrupt bytes are never replaced". Read and parse are separate now.
- isMissing matched ENOENT anywhere in the message, including the quoted
  path (a project under .../ENOENT-x/). It now takes the path and ignores
  it; cachedFile and the queue pass theirs.

(cherry picked from commit 5044d007f3)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov f661b83585 fix(ruflo-mods): a parse error that quotes "ENOENT" no longer reads as an absent projection (#3793)
cachedFile applied isMissing() to parse() exceptions as well as to the
fs.read rejection. JSON.parse and parseProjection both put the file's own
text in their message, so an enforced policy projection containing "ENOENT"
(torn JSON, a stray log line, version: "ENOENT") read as "no policy" and the
guard allowed what the rule denies. Only the read may say absent now; every
parse failure is an error, so the guard fails closed as ADR-450 T10 says.

(cherry picked from commit 5a0a5a4cf9)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 5ae95050c7 fix(guard): a quoted empty substitution leaves the word as bash does; # after it stays in the word (#3791)
Real-bash oracle (bwrap, read-only root, logging fake rm; positive controls
detected) over a 63,696-command differential between main and this branch:
- a substitution inside double quotes is now dropped from the word, as its
  empty output is, so "`true`"-rf reads as -rf; a placeholder is kept only
  when a # follows, so bash -c "`true`#x; rm -rf /" is still read as one
  word and caught;
- 1,260 commands main denies and this branch allows: 0 really delete
  (bash parses each differently than main assumed);
- of 1,500 sampled commands this branch allows with a root operand, the
  201 that really delete are all $(...) substitutions (stated follow-up, 189)
  or $- expansions inside sh -c (12); main misses every one too.
Three parity rows added (309 pass). All four copies alike; the generator's
String.raw source keeps no backtick in comments.

(cherry picked from commit 4f2ac8ba28)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 94238f06ef fix(guard): a substitution starts its word, and an unterminated backtick is text (#3791)
Third review (by reading; its oracle run was cut short): the unquoted
backtick branch did not mark the word as started, so a # right after an
empty substitution was read as a comment and the rest of the line skipped,
`true`#x; rm -rf / among it; bash keeps # inside the word. main denied this
(the backtick was a word character there). Confirmed: the new parity row
fails on the previous head and passes now.

An unterminated backtick (quoted or not) is now literal text, as main read
it, instead of a substitution that swallows the rest of the input. Five rows
added (306 pass); all four copies alike.

(cherry picked from commit 6f515a37a2)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov b880b825ff fix(guard): unescape a substitution body as bash does, scan backticks inside double quotes, rescan any word with a separator (#3791)
Second review, against a real-bash oracle (sandboxed, logging fake rm) over
12k generated commands:
- the backtick body dropped every backslash; bash removes one only before
  $, a backtick or a backslash (and " inside double quotes) and drops
  backslash-newline, so escaped operands and line continuations inside a
  substitution slipped through;
- a backtick inside "..." was kept as text, not scanned, so an empty
  substitution inside a quoted operand hid the delete;
- a word was rescanned only if it contained "rm", so a nested shell whose
  rm was split by a substitution or a backslash was never read.

One substitution helper now serves both contexts, and any word with a
separator or a backtick is rescanned (still bounded at four levels). All
four copies alike. The reviewer's oracle: misses 632 -> 26 (24 are the $(...)
follow-up, 2 real expansions), 0 regressions vs main. Five deny rows and one
allow row added to the parity table (301 pass; on the previous head exactly
the five new deny rows fail).

(cherry picked from commit feb0df1e73)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 54d49ea898 fix(guard): scan a backtick substitution as a nested command instead of ending the rm being parsed (#3791)
Adversarial review: making the backtick a command separator reset the rm
state, so an empty substitution among rm's operands hid the delete. Four
commands main denied were allowed (rm -rf `true` /, rm `` -rf /,
rm -rf /tmp/x `:` /, rm -r `:` -f /); the shell drops the empty word, so
each runs as a root delete.

The backtick is no longer a separator. Its body is scanned as its own
command (bounded at four levels, as other rescans), and the enclosing word
and rm state are left alone. All four copies changed alike; the parity
table gains those four rows plus two safe look-alikes (295 pass; on the
previous head exactly the four new deny rows fail).

(cherry picked from commit d4b0b739c3)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 574e5dd6da fix(guard): root-delete scanner catches backticks, $'…' quoting and abbreviated long options (#3791)
The #3698 scanner kept `$` in front of a quote, did not separate on a
backtick, and accepted only the exact `--recursive`/`--force`. So
``echo `rm -rf /` ``, `$'rm' -rf /`, `bash -c $'rm -rf /'` and
`rm --r --f /*` passed the mod and both classic pre-bash helpers. GNU rm
runs each of them as a root delete.

- A backtick separates words and ends a command, as `(` and `)` already do,
  and a quoted word that contains one is rescanned.
- A `$` immediately before `'` or `"` is ANSI-C/locale quoting, not part of the word.
- Any unambiguous `--` prefix of --recursive / --force counts as that flag,
  as getopt_long does.

The same change is applied to all four copies: the mod, the generator
fallback and both shipped hook-handler.cjs. Fifteen cases are added to the
#3698 parity table (10 deny, 5 safe look-alikes).

(cherry picked from commit ad44701617)
2026-10-07 00:58:38 -04:00
ruv 06d38d059a feat(ruflo-protector): Project Anatole plugin, tests, corpus gate, bench, fleet registration
ruflo-mods 0.3.14: /ruflo-mods shows one protector row from .claude-flow/protector-mod/status.json.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 15:06:42 -04:00
ruv 408c3e502a fix(ruflo-mods): trust gate counts prompt.submit and agent.spawn as risky; ranked context drops control and bidi characters (0.3.13)
#3787: under modTrust=refuse-risky a user-tier mod whose only hook was prompt.submit (the documented injection path at that tier) or
agent.spawn loaded, because neither was in the risk sets. Both are now named and refused; observe still only names them.

#3790: the [INTELLIGENCE] block put remembered entries into the prompt cut to 80 characters but otherwise as they were. They now pass
through the same control and bidi cleaning the research guard uses.

Both new tests fail without the change.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 11:54:51 -04:00
ruv ecb0c0bfa6 fix(ruflo-mods): reject a legacy or unknown-mode policy projection as unreadable; report shows the mode (ADR-450 T10), 0.3.12
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 05:44:23 -04:00
ruv ffe15550de Merge origin/main into loop/readme-options
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 05:02:29 -04:00
ruv 981757f12d docs(ruflo-mods): README rows cite the live options run and the source of the 76% figure
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 04:55:43 -04:00
ruv 5f717842b4 docs(ruflo-mods): complete the option table, one row per userConfig key, with a smoke guard (0.3.11)
Adds the missing toolHints, agentTrim and agentTrimKeep rows, evidence pointers, drops the stale console 'pending' line, and adds smoke step 13. 0.3.11 chosen because loop/probe-label (0.3.10) is not merged yet.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 04:47:20 -04:00
ruv ff66586247 fix(ruflo-mods): print the probe label once in the /ruflo-mods report (0.3.10)
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 04:41:04 -04:00
ruv f32b1f6db6 Merge origin/main into loop/adr451-compact
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 04:20:15 -04:00
ruv e1589e5d86 feat(ruflo-mods): compactCarry option carries swarm and claims state through compaction (ADR-451 item 7, 0.3.9)
session.compact appends one bounded (600 char) block of validated words and ids to the
compaction instructions: live swarm id/topology/agent count, open claim ids with status,
last route agent, budget and policy words. Default off, framed as data, screened for
secret shapes and injection phrases, skipped for subagent compactions, fails open.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 04:11:43 -04:00
ruv 349f7245be feat(ruflo-mods): sessionRollup ledger, one bounded counters record per session (ADR-451 item 6), 0.3.8
Default off. Counters and fixed-vocabulary fields only, capped at 50 records /
512 bytes each / 32 KB, pruned on write; corrupt ledger reads as empty; shown as
a sessions: line in /ruflo-mods. Observability only, fails open.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 03:45:51 -04:00
ruv 477622b97d chore(ruflo-mods): 0.3.7 for the capability probe (0.3.6 went to the wording fix)
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 03:22:31 -04:00
ruv 11e5c89e78 Merge remote-tracking branch 'origin/main' into loop/adr451-probe 2026-10-05 03:20:48 -04:00
ruv 32b6c33008 feat(ruflo-mods): capabilityProbe option records engine version and events fired (default off), ADR-451 item 5; 0.3.6
Observability only: one pass-through hook on every event counts which of the
events the mod registered fired; /ruflo-mods gains a bounded probe line and
the heartbeat lists the engine version and registered events. Never denies,
rewrites or delays; fails open.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 03:13:05 -04:00
ruv 8e87229606 fix(ruflo-mods): correct the agentTrim wording after the live measurement (0.3.6)
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 02:58:58 -04:00
ruv 6029b0aa2c chore(mods): drop provably unused hasSecret/tidy, swarm PLUGIN_NAME, ruos parseProbe; fix guidance screen header
Review 2026-10 #13. Patch bumps: ruflo-mods 0.3.5, ruflo-swarm 0.3.3, ruflo-ruos 0.1.1.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 02:28:30 -04:00
ruv c259ce9575 fix(ruflo-mods): keep guidance observations independent of route ownership (the e2e contract); keep rung and dropped-id fixes
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 02:09:19 -04:00
ruv 576672ea44 fix(ruflo-mods): 0.3.4 budget rung once per session, no guidance observations without route ownership, report dropped tool ids
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 01:46:59 -04:00
ruv cd01a4aea3 feat(ruflo-mods): deliveryScreen option hooks session.receive/send (default off), ADR-451 item 3; 0.3.3
Drops peer/relay deliveries with injection phrasing and refuses outgoing
messages carrying a secret shape or SSN. In-process, tighten-only, fail
open; the person's own Remote Control prompts are never screened.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 01:13:51 -04:00
ruv ebe2f82146 ruflo-mods 0.3.2: live validation of toolHints/agentTrim/status, correct the agentTrim option text
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-05 00:25:30 -04:00
ruv 33a60c715f feat(ruflo-mods): agentTrim option hooks agent.offer (default off), ADR-451 item 2; 0.3.1
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-04 23:28:44 -04:00
ruv a0ef670ed9 test(ruflo-mods): allow-comment the deliberate standalone-prefix tool name in describe.test.ts (fleet MCP namespace audit)
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-04 21:51:20 -04:00
ruv 549f66b0dc chore(ruflo-mods): 0.3.0 (toolHints option)
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-04 21:38:27 -04:00