* fix(ruflo-agentdb): stop the secret screen treating a hyphen-named memory key as a credential field
assignmentSecret() ran the KEY_NAME key-assignment check on every match, so
any entry whose name starts with auth (auth-flow-notes) plus up to 40 name
characters looked like a config field, and keyedSecret()/plausibleSecret()
then judged the entry's value as a credential: a write of
{ key: 'auth-flow-notes', value: 'getUser-not-getSession' } was refused
(#4202). A key that is itself a multi-word hyphenated name is an entry's
name, not a field, so the keyed check now skips it; the secret shapes still
screen the whole text, and single-word credential keys (auth, api_key,
token) keep blocking keyed literals.
Synced to the 39 plugin copies with scripts/sync-mod-screen.mjs.
Fixes#4202
Assisted-by: AI (automated contributor session, disclosed on the issue)
* chore(ci): exclude plugins/ruflo-agentdb/tests/guard-keys.test.ts from the root vitest run
The new test imports claude-code/testing like its six siblings, so the root
ratchet run (scripts/ci-test-ratchet.mjs) cannot collect it outside Claude
Code; list it in scripts/ci-test-excluded.txt per the documented convention
so ci.yml stays green until 'claude plugin test plugins/ruflo-agentdb' runs
it in all-plugins-smoke.
Follow-up to #4202
Assisted-by: AI (automated contributor session, disclosed on the issue)
- #4127: PostToolUseFailure registered for Bash and Write|Edit|MultiEdit and forwarded with -s false and the real exit code (builds on #4170 by @rudycelekli; payload shape verified against Claude Code 2.1.289)
- #4176: the hook shim starts the CLI from CLAUDE_PROJECT_DIR; the CLI only adopts a proven config in a directory that carries ruflo init's markers, not a bare .claude/ that Claude Code created
- #4128: the shim starts the CLI detached and returns at once (about 25 ms instead of 0.2-4 s per hook), bounded to 4 concurrent telemetry CLIs per project, Stop never dropped, RUFLO_HOOK_SYNC=1 for the old path
- ruflo-core 0.2.9
Co-Authored-By: RuFlo <ruv@ruv.net>
On Claude Code Desktop every picture was missing: no banner, no title
art, no topology, map, gauge or chart, and not even the text lines meant
to stand in for them. The host completes every resolved table with every
element name, and on the desktop its Raster draws an empty fragment, so
`kit.Raster !== undefined` always held and the console drew empty boxes.
- kitForSurface(): the terminal gets its Raster and no Svg; every other
surface (desktop, vscode, mobile) gets Svg and no Raster. Applied to the
Pane and the band. On the terminal nothing changes: the same Rasters,
keys, text and fallbacks.
- gfx/svg.ts: the same Grid as one SVG document. Every Block Elements
glyph (U+2580 to U+259F) and every braille glyph is drawn as
rectangles; other glyphs are placed cell by cell (a control character,
a value past Unicode or a character XML cannot hold is a blank cell);
colours are kept, the default background stays transparent, text is
escaped. A picture that would pass the host's 131,072-character Svg
limit is not sent, so one large picture cannot invalidate the whole
tree; it then falls back as on a surface with no pictures (its text line
where it has one).
- A surface that draws Svg gets still frames, since nothing blits an Svg:
nothing strikes in and the motion stops, as with fps 0, and the
decorative light (the header's sweep, the title's shimmer, the palette's
sweep) is off instead of caught mid-way. The boot keeps its real time so
its progress shows, and a picture of data is drawn as of the render. The
terminal keeps its moving light, with fps 0 too.
- art(): one helper for every picture site (header, title art, boot,
Orbital art, picture(), learning, memmap, palette). An Svg's alt is the
picture's fallback line without "needs a terminal".
- The frame loop runs while the view has pictures, as before, so the
menu entry and the Learning pulse still move on the desktop; it only
rebuilds and blits when a Raster is mounted, so the desktop no longer
rebuilds every picture per frame and blits keys that were never mounted.
The band's mark animates on the terminal only.
- tests: svg-pictures.spec.ts (vitest) for the writer, the kit, the still
frames (on every page in every look: header, title and palette the same
at any moment, every other picture equal to fps 0's) and the frame loop
by surface; surface-pictures.test.ts mounts the 33 main views and the
agent drill-down of a fixture agent in the bbs, plain and orbital looks
on terminal and desktop (7 tests, all fail on the parent commit). It
imports claude-code/testing, so it is listed in
scripts/ci-test-excluded.txt with the console's other kit tests. The old desktop test only asserted "no Raster",
which held while every picture was gone; it now asserts the Svgs arrive.
Fixes#4111
Co-Authored-By: Ruflo & AQE
README gets a short optional pointer (npx ruflo tui, --plain) and one small animated SVG. docs/USERGUIDE.md gets a
Terminal UI (optional) section: requirements, commands, keys, exit codes, what each page shows, the AI page's ask-first
card and its Codex/OpenRouter rules, the honest limits and a pointer to the Orbital theme. Both SVGs are built from real
frames of ruflo-tui 3.56.7 in a throwaway sample project; scripts/render-tui-svg.mjs rebuilds them (CSS animation only,
no scripts or external references, prefers-reduced-motion shows the first frame).
Co-Authored-By: RuFlo <ruv@ruv.net>
Carries #4031 (rudycelekli) and #4091 (proffesor-for-testing); oversized-tail and permission-safe
recovery per rUv's review and martinvlad's fresh-consumer finding. Adds scripts/smoke-shared-fresh-consumer.mjs
(packed tarball, plain Node) and a CI step for it.
Co-Authored-By: RuFlo <ruv@ruv.net>
Page 6. Reuses harness.send and the conversation bridge's sendTo, not a second harness. Host.spawn runs only the pinned Codex 0.162.0
release (never current or PATH), read-only, from a fixed argument allow-list; Host.httpSend sends only https POST to openrouter.ai or a
convoTargets host, never follows a redirect, and a key is read by variable name and never drawn. Enter shows a card of exactly what would be
sent; a lone y answers it only while it was drawn in full (#3983); spend cap from the provider-reported cost. e2e host matrix gets a tui leg
(keyless in CI, live gated). Not in this PR: the workspace-write toggle.
Co-Authored-By: RuFlo <ruv@ruv.net>
ADR-490 (loop), ADR-491 (mods host integration, Proposed). The loop's first run found two defects, fixed test-first:
- ruflo mcp start advertised resources but answered resources/* with -32601 (3 stdio servers).
- init --dual's marketplace clone ran under a 20 s budget (17.5 s measured), swallowing the real error.
Co-Authored-By: RuFlo <ruv@ruv.net>
Checked every CLI command, flag and MCP tool the skills tell the model to use
against ruflo 3.56.5 and the tool registry. Fixed what was false:
- workflows 0.6.6: MCP tool names with underscores that do not exist; gaia-bench
has no --dry-run/--task-id (unknown flags are ignored, so the documented cost
estimate started a billed run); opt-in guard for native workflows; stale smoke
- security-audit 0.3.4: non-existent `security report`, wrong `audit` usage,
scan depth table that described phases the scanner lacks; --fix gated
- swarm 0.3.7: `swarm watch/health/shutdown` do not exist; swarm-watch.mjs poller
- rag-memory 0.3.5: `ruflo recall`/`memory bridge` do not exist; shell-quoting
of user text in /recall
- testgen 0.3.2: tdd-repair now enforces that the test is not edited; shell
quoting; invalid --limit
- rvf 0.3.6: export went through the public IPFS marketplace; now memory export
- ruvllm 0.3.4: provider claims and persistence claims corrected
- observability 0.3.4: no invented traces when nothing wrote spans
- plugin-creator 0.4.3: required plugin.json fields and tool existence check
Co-Authored-By: RuFlo <ruv@ruv.net>
Under Git Bash MSYS rewrote the /c of the generated cmd /c IF EXIST hook, so cmd
started interactively, executed the hook's stdin JSON and created zero-byte files
from text after a >. The Windows hook is now a single node -e with no cmd, no
%VAR%, and none of < > | & $ or inner double quotes. It keeps the project-first
then user-profile fallback (#1943), user scope never reads the project, and the
helper runs as a child with inherited stdio so stdin and the exit status pass
through. pinToUserHelpers recognises the new form (exact match only) as well as
the old ones.
Co-Authored-By: RuFlo <ruv@ruv.net>
The statusline now builds shell command lines from HELPER_ROOT (the checkout's
directory, chosen by whoever made it). A directory named p$(...) was expanded
inside the double-quoted command; shell-active paths are now skipped.
The statusline-generator delegation smoke ran the generated helper from tmpdir,
so with CLI resolution moved to the helper root it fell through to the registry's
published CLI (intelligencePct null). It now writes the helper into a throwaway
helper root whose v3/@claude-flow/cli is the repo's built CLI.
Co-Authored-By: RuFlo <ruv@ruv.net>