Commit Graph
468 Commits
Author SHA1 Message Date
rUvandClaude 7387295568 dream(memory): #4549 wire ControllerRegistry.set() — MutationGuard/AttestationLog activation was permanently dead (evaluated, ACCEPT-scoped) (#4550)
* dream(memory): wire ControllerRegistry.set() so MutationGuard/AttestationLog activation stops being dead code

memory-bridge.ts's post-init controller-activation wiring (reasoningBank,
learningSystem, skills, semanticRouter, gnnService, rvfOptimizer,
mutationGuard, attestationLog, guardedVectorBackend) has always gated
registration on `typeof reg.set === 'function'`, falling back to an
unread `reg._controllers` property otherwise. ControllerRegistry never
implemented a public set() method, so every external activation silently
took the dead fallback: registry.get('mutationGuard')/get('attestationLog')
always returned null, permanently disabling write-mutation validation
(fail-open "no guard installed = allow") and audit logging (silent no-op)
on the real store/delete/purge paths. Same bug shape as the already-fixed
#3327 Finding A (reasoningBank.store never existed, so its own
typeof-guard was dead too).

Adds ControllerRegistry.set<T>(name, instance) mirroring the shape
initController() already produces internally. Zero changes needed at any
of the 9 memory-bridge.ts call sites.

5 new discriminating tests reproduce memory-bridge.ts's exact activation
pattern; stash-isolated baseline fails all 5 (TypeError: registry.set is
not a function), candidate passes all 5. Full @claude-flow/memory suite:
650/651 both ways (1 pre-existing environmental failure, byte-identical,
unrelated chmod/root-bypass test). tsc --noEmit: 0 errors.

Evaluated, pending independent adversarial critique.

* dream(memory): close prior instance on ControllerRegistry.set() (post-critique)

Independent adversarial critique of afe2cdd found set() silently dropped
a reference to any pre-existing resource-holding instance on overwrite,
reintroducing the exact leak class #2432 fixed for initController()'s own
replacement path (unclosed sql.js/WASM resources, ~36GB over 6 weeks in
production per that commit's own account). Not currently triggerable
through the shipped memory-bridge.ts wiring (every real call site guards
with `if (!reg.get(name))` first), but the set() API itself offered no
protection.

Fix: dispatch the existing closePriorIfAny(name) before overwriting the
map entry, same as initController() does. Intentionally not awaited, so
get(name) still reflects the new instance synchronously; the old
instance's close()/dispose() (best-effort, errors swallowed) runs in the
background — matches every other call site's synchronous-looking
registration contract.

1 new discriminating test added. Full @claude-flow/memory suite:
651/652 (1 pre-existing environmental failure, unchanged). tsc --noEmit:
0 errors.

Known, disclosed, not-fixed-tonight limitation (out of scope, needs a
human call on correct init ordering): `causalRecall` is the one
ControllerName absent from every INIT_LEVELS entry, so shutdown()'s
by-static-list lookup would never find/close a controller registered
under that name via set() — unexercised today (no call site uses it).
Flagged for a future night rather than guessed at here.

* dream(memory): add 2026-10-28 SOTA research gist (gist publishing unavailable, FALLBACK)

No gh CLI / gist-creation tool reachable this session — same disclosed
FALLBACK as every night since 2026-09-30. Full SOTA report committed to
docs/dream-cycle/ instead of a gist.github.com URL.

* dream(memory): #4549 update LEDGER for 2026-10-28

* dream(memory): bump @claude-flow/memory to 3.1.0 (CI: leaf-package-publish audit)

CI's "Plugin package install-safety" job (scripts/audit-leaf-package-publish.mjs,
guarding ruvnet/ruflo#3335 and #3390/#3327 Finding A) correctly failed: this PR's
source change to v3/@claude-flow/memory/src/controller-registry.ts is publishable
(adds a new public method) but @claude-flow/memory's own package.json version was
unchanged at 3.0.9 — @claude-flow/memory is not bundled into the release train, so
publishing cli/claude-flow/ruflo without also bumping+publishing this leaf would
ship the OLD copy and this fix would reach nobody.

Bumped @claude-flow/memory 3.0.9 -> 3.1.0 (MINOR: backward-compatible new public
method). Updated the two exact pins in v3/@claude-flow/cli/package.json
(dependencies + optionalDependencies) to match, and regenerated v3/pnpm-lock.yaml
via `pnpm install` (never hand-edited) so the lockfile's specifier stays in sync.

Verified locally: node scripts/audit-leaf-package-publish.mjs --base origin/main
now reports "ok: every non-bundled leaf is covered by the CLI range and carries a
bump if changed". Full @claude-flow/memory suite re-confirmed 651/652 (same
pre-existing environmental failure), tsc --noEmit 0 errors.

Note for a future release: per CLAUDE.md's publishing rules, @claude-flow/memory
must be published standalone alongside the next @claude-flow/cli release for this
fix to actually reach consumers — not done as part of this draft PR.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 12:46:23 -04:00
ee75b70201 dream(intelligence): #4531 wire real Fisher-information estimation into SONAManager's EWC++ path (evaluated, ACCEPT-scoped) (#4532)
* dream(intelligence): wire real Fisher-information estimation into SONAManager's EWC++ path

SONAManager's EWC++ catastrophic-forgetting mechanism was completely inert:
ewcState.fisher/.means were initialized empty and never written anywhere in
the core @claude-flow/neural package; consolidateEWC() (the only method
touching fisher post-init) only decayed an always-empty map and had zero
callers. Every computeEWCPenalty/computeEWCLoss call across all 5 learning
modes therefore always evaluated to exactly 0, in production (SONAManager
backs NeuralLearningSystem, loaded by @claude-flow/memory's learning-bridge).

Scoped fix (default 'balanced' mode only): BalancedMode now exposes
getConsolidationSnapshot(), deriving Fisher as squared-gradient and means as
the raw gradient from its existing gradientAccumulator (mirroring a working
reference pattern already in this monorepo's
plugins/cognitive-kernel/src/bridges/sona-bridge.ts). SONAManager's
triggerLearning() folds this into ewcState via the existing (unchanged)
consolidateEWC() decay step, then additive accumulation - online-EWC style.

Also removes 6 stale, never-gitignored .js files under
v3/@claude-flow/neural/src/modes/ that shadowed the current .ts sources for
any explicit .js-extension import (Vite/Vitest resolve a literal file on
disk over transforming a sibling .ts) and were themselves circularly broken
- this was blocking any vitest test of SONAManager/mode classes from ever
exercising real logic, confirmed via git-stash to reproduce identically on
the pre-candidate baseline and to be a necessary precondition for tonight's
evaluation, not part of the EWC logic change itself.

Disclosed scope limit: this makes the EWC *state* real and measurable; the
computed penalty is not yet wired into the gradient update itself (same gap
already disclosed as a stub in the reference plugin's own consolidate()).

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01ReiDH3LBmCGHLADvSaqWs2

* dream(intelligence): fix forward per independent adversarial critique

Round-2 fixes from an independent adversarial-critic pass on commit
2c5bcb177:

- getConsolidationSnapshot() now reports the CHANGE in gradientAccumulator
  since the last consolidation (a delta), not the raw lifetime-cumulative
  accumulator. Squaring the ever-growing cumulative value directly (the
  original candidate) made Fisher/means diverge without bound over a
  long-running session - confirmed empirically by the critic (25 cycles:
  0.00012 -> 0.68) and reproduced independently here (150 cycles). The
  delta-based version is a strict improvement (Fisher now reflects "what
  changed", the theoretically appropriate EWC quantity) but does NOT fully
  solve divergence by itself: traced the remaining growth to a separate,
  deeper, pre-existing behavior one layer up - triggerLearning() reprocesses
  every completed trajectory still held by the manager on every call (no
  "already learned from" tracking; only pruneTrajectories()'s 50%-capacity
  threshold ever removes one), so BalancedMode.learn()'s gradient movement
  per cycle grows with the historical backlog, not just what's new. Fixing
  that is a distinct, larger-blast-radius change (trajectory lifecycle, not
  EWC) - disclosed in the test file's docstring and carried forward as a
  priority candidate for a future night, explicitly ahead of ever wiring
  computeEWCPenalty() into a real gradient update.
- Rescoped the "Fisher == means^2" test to state plainly it's a
  single-cycle construction-time identity (true by the snapshot's own
  arithmetic when there's no prior snapshot to diff against), not an
  ongoing system invariant - confirmed by the critic to break after cycle 2.
- Finished the stale-build-artifact cleanup in src/modes/ that the prior
  commit started: removed the remaining tracked .d.ts/.d.ts.map/.js.map
  siblings (12 files) plus a stray tmp.json, same never-gitignored,
  out-of-sync-with-source bug class as the .js files removed in the prior
  commit. src/modes/ now contains only .ts sources.
- Fixed a path citation (plugins/... -> v3/plugins/...) in comments/tests.

143/143 tests pass, 0 tsc errors, build clean - re-verified after each
change in this commit.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01ReiDH3LBmCGHLADvSaqWs2

* dream(intelligence): add research gist for 2026-10-27

Full SOTA report: 5-role parallel research fan-out, 6-row graded 2026
external-research table, 5-row competitor comparison (genuine "None" across
LangGraph/AutoGen/CrewAI/OpenAI agent tooling, explained), the frozen
hypothesis with explicit scope disclosure, the evaluation receipt including
the independent adversarial critique's findings and this session's fix
forward, and 4 deferred/scored candidates plus 2 scan findings
(capabilities, memory) carried to a future night. Witness stamp computed
from the final file content.

No gh gist create / gist-equivalent MCP tool reachable this session (same
disclosed FALLBACK as every night since 2026-09-30) - committed here
instead, per established convention.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01ReiDH3LBmCGHLADvSaqWs2

* docs(dream-cycle): append 2026-10-27 ledger row

Issue #4531 / PR #4532 / witness 7b524483... — ACCEPT-scoped, post-critique.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01ReiDH3LBmCGHLADvSaqWs2

* fix(neural): bump @claude-flow/neural to 3.1.0 for the EWC fix

CI's audit-leaf-package-publish.mjs (ruvnet/ruflo#3335/#3390 guard) failed:
@claude-flow/neural is a non-bundled leaf that resolves from the npm
registry at release time, not from this PR's source. Its publishable
source changed (the EWC Fisher-wiring fix) but package.json's version was
still 3.0.0 - a release right now would ship the OLD, still-broken copy
and this fix would reach nobody.

Bumped neural 3.0.0 -> 3.1.0 (adds a new optional ModeImplementation
member, getConsolidationSnapshot, in addition to the bug fix - a
backward-compatible addition, MINOR per CLAUDE.md's versioning policy) and
the CLI's exact pin to match. Verified locally: audit script passes
(version bumped, CLI range satisfied), full neural suite 143/143, build
clean.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01ReiDH3LBmCGHLADvSaqWs2

* fix(deps): regenerate v3/pnpm-lock.yaml for the neural version bump

The 3.0.0 -> 3.1.0 bump to @claude-flow/cli's @claude-flow/neural dependency
spec (previous commit) was made by hand, without regenerating the lockfile
- CI's --frozen-lockfile installs correctly rejected it with
ERR_PNPM_OUTDATED_LOCKFILE across every job that runs one (Memory import
smoke, Windows hook execution smoke, statusline generator delegation smoke,
Smoke (no better-sqlite3), and others).

Regenerated via `pnpm install --no-frozen-lockfile` (the repo's own
tooling, not a hand edit) inside v3/. The only intended change is the
@claude-flow/neural specifier; the diff also picked up an incidental
@opentelemetry/api 1.9.0 -> 1.9.1 transitive bump across vitest's
resolution entries, which is pnpm's own resolver picking a newer
compatible published patch, not something this PR intentionally touches.
Verified locally: `pnpm install --frozen-lockfile` now succeeds, full
@claude-flow/neural suite still 143/143.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01ReiDH3LBmCGHLADvSaqWs2

* fix(cli): revert neural pin to the published 3.0.0, not an unpublished 3.1.0

My previous fix bumped @claude-flow/cli's @claude-flow/neural dependency
spec to 3.1.0 to satisfy the "Plugin package install-safety" leaf-publish
audit - but 3.1.0 has never been published to npm (confirmed: `npm view
@claude-flow/neural versions` lists only up to 3.0.0). That pin broke a
REAL, more severe check: "CLI npx-install smoke" packs the actual CLI
tarball and runs a real `npm install` against it, which failed with
`ETARGET: No matching version found for @claude-flow/neural@3.1.0` - i.e.
a real `npx @claude-flow/cli` user would hit this exact error today.

Publishing @claude-flow/neural@3.1.0 to npm is a human-gated release
action (signing keys, GCP secrets, WebAuthn - see CLAUDE.md's "Publishing
to npm"), not something this session does autonomously from an unreviewed
nightly research PR. Reverted the CLI's pin to 3.0.0 (the real published
version) and regenerated the lockfile to match.

This leaves one disclosed, expected finding in "Plugin package
install-safety": @claude-flow/neural's own package.json is now ahead of
the CLI's pin (3.1.0 source vs 3.0.0 pinned) - exactly the state CLAUDE.md
describes as needing a human to "publish @claude-flow/neural@3.1.0 and
raise the range" as part of an actual release, not a code fix. Noted on
the PR rather than resolved by further pushes.

@claude-flow/neural's own suite remains 143/143, build clean - unaffected,
since its tests exercise the local TS source directly.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01ReiDH3LBmCGHLADvSaqWs2

* fix(neural): drop the 3.1.0 bump and restore main's lockfile

The bump broke the umbrella's @claude-flow/neural range check and forced a
lockfile regen that flipped @claude-flow/memory to a registry copy. The EWC
change ships as the next neural release, bumped at release time.

Co-Authored-By: RuFlo <ruv@ruv.net>

* fix(neural): anchor EWC means on the parameters at consolidation

computeEWCPenalty() measures current - means against the cumulative
gradient accumulator, so means must be that accumulator at consolidation
(theta*). Storing the per-cycle delta made the penalty start at roughly the
previous parameter value instead of zero. New test fails on the delta and
passes on the fix; neural suite 144/144, tsc clean.

Co-Authored-By: RuFlo <ruv@ruv.net>

* chore(neural): bump to 3.0.1 for the EWC++ consolidation fix (#4531)

The CLI and root pins move with it so the release carries the fix.

Co-Authored-By: RuFlo <ruv@ruv.net>

* chore: lock @claude-flow/neural 3.0.1 from the registry

Co-Authored-By: RuFlo <ruv@ruv.net>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: r <r@x>
2026-10-27 14:37:17 -04:00
rUvandClaude 9d854ddb9c dream(security): #4503 http_fetch SSRF bypass via IPv4-mapped IPv6 literals (evaluated, ACCEPT) (#4504)
* dream(security): http_fetch SSRF bypass via IPv4-mapped IPv6 literals

isPrivateOrLoopback() (the SSRF guard behind the http_fetch MCP tool's
validateUrl()) never stripped the "[...]" brackets Node's URL parser keeps
in `.hostname` for IPv6 literals. Two consequences:

1. The existing fc00::/7 (ULA) and fe80::/10 (link-local) checks
   (`host.startsWith('fc'/'fe80:')`) never matched anything, since `host`
   always started with "[" first.
2. There was no handling at all for IPv4-mapped IPv6 literals
   (`::ffff:a.b.c.d`, normalized by Node to a canonical `::ffff:xxxx:yyyy`
   hex form), so wrapping a loopback/private/link-local/cloud-metadata
   IPv4 address in that form bypassed the guard entirely
   (e.g. http://[::ffff:127.0.0.1]/, http://[::ffff:169.254.169.254]/).

Strips brackets once up front, then decodes IPv4-mapped-IPv6 forms back to
dotted-decimal and recurses into the existing IPv4 rules instead of adding
a parallel copy. 13 new tests (8 discriminating, verified to fail on the
pre-fix source via a stash-isolated run; 5 non-discriminating controls).

Independent adversarial critique: CONFIRMED-WITH-CAVEATS. Two pre-existing,
out-of-scope gaps disclosed in-source (IPv6 "::" unspecified address and
multicast/NAT64 ranges remain unblocked).

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_013bqQefaQjXhYZX2Acr9Jop

* dream(security): add 2026-10-26 research gist

Full SOTA report for tonight's security deep-dive (http_fetch SSRF
bypass via IPv4-mapped IPv6 literals) plus intelligence/swarm scan
findings and competitor comparison. No gist-publishing tool reachable
this session (same disclosed FALLBACK as every night since 2026-09-30)
— committed to this branch instead.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_013bqQefaQjXhYZX2Acr9Jop

* dream(security): update ledger for 2026-10-26

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_013bqQefaQjXhYZX2Acr9Jop

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 09:58:56 -04:00
Lenin MookiahandLenin Mookiah 2be0b69d68 fix(ci): gate helper sync on import and manifest checks (#4507)
Co-authored-by: Lenin Mookiah <2639584+leninworld@users.noreply.github.com>
2026-10-26 09:56:35 -04:00
rUvandr 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>
2026-10-24 22:42:09 -04:00
rUvandr e00a82f2fa docs: ChatGPT plugin badge in the README and a plugin section in the user guide (#4438)
Co-authored-by: r <r@x>
2026-10-23 15:04:54 -04:00
c2069ed6f6 fix(metaharness): revive the cost dimension and single-source the verdict bands (ADR-152) (#3520)
Reconciling the shipped similarity code against docs/metaharness-user-guide.md
turned up three divergences between what ADR-152 specifies, what the code does,
and what the docs promise.

1. Cost normalization (vector index 8) was inert below $0.999.

   ADR-152 Table 1 specified `log10(usd + 0.001) / log10(10)` clamped to [0,1].
   `Math.log10(10)` is 1, so the division was a no-op and the expression reduced
   to `clamp(log10(usd + 0.001), 0, 1)`. Because log10 is negative for every
   usd < 0.999, the clamp flattened that entire range to a constant 0 — including
   the $0.048 baseline the plugin README records. Two harnesses differing only in
   cost scored `cosine === 1`; the documented 9-dim vector was effectively 8-dim.

   Replaced with an explicit log band: $0.001 -> 0, $10 -> 1, log-interpolated
   between, monotonic and non-finite-safe. Exported as `normalizeCost()` with the
   band in `COST_BAND_USD`.

2. The verdict bands had two encodings, and they disagreed.

   `audit-trend.mjs` inlined the bands with a 0.80 `minor-drift` floor while the
   user guide documented 0.85; `drift-from-history` prints that verdict, so the
   two diverged in the 0.80-0.85 band. The bands now live once as
   `VERDICT_THRESHOLDS` + `verdictFor()` in `_similarity.mjs`, `audit-trend.mjs`
   imports them, and `similarity()` returns `verdict` beside `overall`. The
   documented 0.85 floor is canonical.

   Deliberate user-visible change: structural similarity in [0.80, 0.85) now
   reports `moderate-drift` instead of `minor-drift`. `--threshold` comparison is
   unaffected (it tests `overall`), but consumers branching on the verdict string
   should be re-checked.

3. The user guide's weight table said 0.4/0.3/0.3; ADR-152 and the code both say
   0.6/0.25/0.15. Corrected the guide, which was the outlier.

The ADR gains a dated Revision section recording both fixes and the behaviour
change. The §Spike-result figures are unchanged (the LEGAL/SUPPORT fixtures are
near-identical on the cost axis), so test-similarity.mjs Phase 8 keeps pinning
the original anchors; new Phase 7b/7c/7d coverage pins the corrected semantics.

Note this does NOT address the coarse-cosine limitation ADR-152 itself flags
("numerical cosine alone is too coarse"): uniform quality degradation still
reads as high similarity. Drift gates that must catch absolute loss should pair
structural similarity with the absolute gates rather than rely on --threshold.

Verification:
  node plugins/ruflo-metaharness/scripts/test-similarity.mjs   -> 128 passed, 0 failed (was 102)
  node plugins/ruflo-metaharness/scripts/_spike-similarity.mjs -> both invariants hold

Co-authored-by: longxinjun-ai <longxinjun-ai@users.noreply.github.com>
Co-authored-by: rUv <ruv@ruv.net>
2026-10-20 06:50:00 -04:00
9cf2ad57ba dream(memory): #4137 wire delete-sync into AutoMemoryBridge.importFromAutoMemory() (evaluated, ACCEPT) (#4138)
* dream(memory): #4137 AutoMemoryBridge was additive-only, never delete-synced removed/vanished source content

importFromAutoMemory() diffed new content against AgentDB by content-hash
to insert/skip, but never detected or deleted an entry whose source
heading (or whole source file) was removed — deleted memory content
stayed retrievable via semantic search indefinitely. Adds a per-source-
file key diff (reusing the existing single bulk query, zero schema
change) plus a second pass for files removed entirely from disk, each
with a false-full-wipe guard. Evaluated: 7 new discriminating tests,
baseline-fails/candidate-passes via stash isolation; full suite and tsc
clean modulo pre-existing/unrelated flakes. Adversarial critique found
and this session fixed forward the whole-file-removed gap and a vacuous
test assertion before this commit.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

* dream(memory): #4137 append 2026-10-13 ledger row

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

* fix(memory): #4137 bump @claude-flow/memory to 3.0.5 for the delete-sync change

CI's leaf-package-publish audit caught this: @claude-flow/memory is a
non-bundled leaf that resolves from the registry for the release train,
so a publishable source change (auto-memory-bridge.ts) must bump the
leaf's own version or the fix silently never reaches a release. Bumps
the leaf's package.json, the CLI's exact pin (dependencies +
optionalDependencies), and the matching pnpm-lock.yaml specifier.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

* fix(memory): #4137 scope delete-sync to the writing memoryDir, avoid version collision with #4183

Review finding: the backend can be shared across multiple memory dirs
(e.g. the SessionStart hook's main dir vs. a worktree dir from
worktreeMemoryDir()). Without recording which memoryDir wrote an entry,
importing one dir could see another dir's same-named file/heading as
"gone" and delete it. Entries now carry metadata.memoryDir, and both
delete-sync passes (per-heading diff and whole-file-removed) only
consider entries whose memoryDir matches the importing bridge's own —
legacy entries written before this field existed (no memoryDir at all)
are therefore never delete-sync eligible. Two new discriminating tests
cover cross-dir isolation and the legacy-entry case; all 9 existing
delete-sync fixtures updated to carry memoryDir so they still exercise
the intended "same dir" path rather than being silently excluded.

Also bumps @claude-flow/memory to 3.0.6 (CLI pins + lockfile specifier)
since #4183 independently claimed 3.0.5 for the same leaf — whichever
of the two PRs lands second needs a version past the other's.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

* fix(memory): #4137 revert stray codex/security/shared lockfile drift

An earlier `pnpm install` run in this session (unrelated to this PR's
own change) left pnpm-lock.yaml recording codex/security/shared at
specifier 3.0.6 while v3/@claude-flow/cli/package.json still pins them
at 3.0.5 — a mismatch that got swept into a prior commit by staging the
whole lockfile file. `pnpm install --frozen-lockfile` (what CI runs)
fails on that drift regardless of this PR's actual content. Reverted
those three specifiers back to 3.0.5 to match package.json; the memory
specifier bump to 3.0.6 (this PR's real change) is untouched. Verified
locally: `pnpm install --frozen-lockfile` now succeeds.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

* chore(memory): untrack test-generated agentdb.rvf.idmap.json

Swept into the previous merge commit by running the test suite to
verify the merge; it's a fresh-run artifact (empty idToLabel/labelToId
maps), not source. Added to .gitignore alongside the other *.rvf
test-pollution exclusions in this package.

Co-Authored-By: RuFlo <ruv@ruv.net>

* fix(memory): bump @claude-flow/memory to 3.0.7 for the delete-sync fix

AutoMemoryBridge.importFromAutoMemory()'s delete-sync fix in this PR
changed v3/@claude-flow/memory/src/auto-memory-bridge.ts without
bumping the package version. @claude-flow/memory is not bundled into
the release tarballs — it resolves from the registry — so publishing
the three train packages without this bump would ship the old 3.0.6
copy and the fix would reach nobody (ruvnet/ruflo#3335, #3390).

Will publish @claude-flow/memory@3.0.7 standalone once this merges.

Co-Authored-By: RuFlo <ruv@ruv.net>

* fix(memory): #4137 bump CLI pins + lockfile specifier to match memory@3.0.7

761b8386 bumped the leaf's own package.json version to 3.0.7 but left
v3/@claude-flow/cli/package.json's exact pin (dependencies +
optionalDependencies) and the matching pnpm-lock.yaml specifier at
3.0.6 — the leaf-package-publish audit catches this: an exact pin of
"3.0.6" is not satisfied by workspace version 3.0.7, so a release would
resolve to an older published copy than the source in this repo.
Verified: audit script passes, `pnpm install --frozen-lockfile`
succeeds.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01UkpQrJUNdFzDJVnY2FzXh8

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: r <r@x>
2026-10-20 05:27:57 -04:00
16507b171a dream(swarm): #4173 TaskOrchestrator.getQueuePosition() priority-map key typo (evaluated, ACCEPT) (#4174)
* dream(swarm): #4173 TaskOrchestrator.getQueuePosition() priority-map key typo

getQueuePosition()'s local priorityOrder map used keys
critical/high/normal/low/background, but TaskPriority is
critical/high/medium/low. createTask() defaults unspecified priority
to 'medium', so the lookup always fell through to 0, ranking
default-priority tasks behind even 'low' in the taskQueuedEvent
position field. Real dispatch (getNextTask/getPriorityQueue) uses a
separate, already-correct map and was unaffected.

Fixed the map to Record<TaskPriority, number>, which also gives
compile-time exhaustiveness against this regression recurring.

Evaluated: ACCEPT. Stash-isolated baseline 278/280 (2 discriminating
failures) -> candidate 280/280, zero other regressions. tsc clean
both ways. Independent adversarial critique: CONFIRMED.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01FpoMprTZKfkjhytxvLpyTT

* dream(swarm): #4173 append 2026-10-14 ledger row

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01FpoMprTZKfkjhytxvLpyTT

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: r <r@x>
2026-10-20 04:52:38 -04:00
rUvandClaude df2dd4bfd6 dream(security): #4312 hooks_codemod path-containment bypass (CWE-22) (evaluated, ACCEPT) (#4313)
* dream(security): hooks_codemod path-containment bypass (CWE-22)

resolveTargets()'s containment check (hooks-tools.ts) used an unanchored
abs.startsWith(cwd) string-prefix comparison. An absolute path.resolve()
result is returned unchanged for an already-absolute input, so a sibling
directory whose name merely starts with the project directory's name
(e.g. cwd=/home/user/ruflo, target=/home/user/ruflo-staging/notes.ts)
passed containment and let this live, CLAUDE.md-recommended Tier-1 MCP
tool read+write outside the project root.

Anchors both call sites (file/files[] and glob-match branches) at a
path-separator boundary, matching the already-correct pattern used in
@claude-flow/security's isWithinPrefix(), @claude-flow/hooks/workers,
and @claude-flow/plugins/security elsewhere in this codebase.

4 new tests (2 discriminating, real temp-dir fs I/O; 2 non-discriminating
controls). Stash-isolated: both escape tests fail on baseline (file
genuinely written outside root), 4/4 pass on candidate. Related suites
(mcp-tools-deep, validate-input-*, codemod-engine/routing/corpus):
229/229 unchanged. tsc --noEmit byte-identical (9 pre-existing
environmental errors, unbuilt sibling packages).

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_0171ELk4aJ9SPhudJw3UnjgL

* dream(security): disclose symlink containment gap (follow-up)

Independent adversarial critique of 71a6c07d found a real, reachable,
distinct bypass of the same containment check: a symlink inside the
project root pointing outside it still escapes containment, since the
check compares the resolved-but-not-realpath'd path (CWE-59, broader
than the CWE-22 unanchored-prefix bug the prior commit fixed). Not
fixed here (separate hardening effort, would need fs.realpathSync-based
containment) — disclosed in-source per this repo's established
non-blocking-caveat convention.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_0171ELk4aJ9SPhudJw3UnjgL

* docs(dream-cycle): research gist for 2026-10-20

SOTA report for tonight's performance DEEP / security+hive-mind SCAN
cycle. Documents the implemented hooks_codemod path-containment fix,
deferred performance candidates (CacheManager.estimateSize redundant
stringify; AttentionCoordinator embedding-cache miss), the hive-mind
topology role/connection-wiring bug, and graded 2026 external research
+ competitor comparison.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_0171ELk4aJ9SPhudJw3UnjgL

* docs(dream-cycle): ledger row for 2026-10-20 (#4312/#4313)

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_0171ELk4aJ9SPhudJw3UnjgL

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-20 03:17:25 -04:00
ClaudeandRuFlo a02d8aca6d docs(dream-cycle): append 2026-10-19 swarm ledger row
Records tonight's #4285/#4286 (TopologyManager queen/coordinator
failover fix, ACCEPT) plus GitHub-verified fates for 10-16..10-18
(none transcribed as rows, none stale) and the trailing-7-night merge
status, per STEP 25 of the nightly Dream Cycle routine.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01Ch1XkuxbE8ALBoXqZyiA8A
2026-10-19 17:24:05 -04:00
ClaudeandRuFlo db71baa436 dream(swarm): #4285 TopologyManager never promotes a replacement queen/coordinator after death (evaluated, ACCEPT)
removeFromRoleIndex() nulled the cached queenNode/coordinatorNode on
removal with no replacement; electLeader()'s hierarchical/centralized
branches then silently fell through to generic mesh-style ranking,
electing a leader without ever promoting its role. failoverEnabled
(default true) was read nowhere in the package. After exactly one
queen/coordinator death, getQueen()/getCoordinator() returned undefined
forever, contradicting CLAUDE.md's "queen controls workers directly"
guarantee.

Adds TopologyManager.promoteToRole(), gated behind failoverEnabled,
called from electLeader()'s hierarchical/centralized branches before
the generic fallthrough. 3 new discriminating tests: 2/3 fail on stash-
isolated baseline exactly as predicted, 1/3 (failoverEnabled:false
preserves old behavior) is a correct non-discriminating control. Full
@claude-flow/swarm suite 335/335 both ways, tsc clean both ways.

Independent adversarial critique: CONFIRMED-WITH-CAVEATS, no blocking
issues. Caveats disclosed in-source (promotion doesn't rewire
connections/adjacency itself; self-healing under the default
autoRebalance: true) and in the issue/gist.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01Ch1XkuxbE8ALBoXqZyiA8A
2026-10-19 17:23:22 -04:00
ClaudeandRuFlo fa7846d19b docs: update dream-cycle ledger for 2026-10-18 (memory)
Appends the 2026-10-18 row (issue #4270, PR #4271) and a verified
trailing-fate note for 10-16/10-17 plus the now-confirmed 7/7 merge
rate across the last 7 nights.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_016nZstVChPSSNBwmMUJW8tE
2026-10-19 14:53:26 -04:00
ClaudeandRuFlo 7a50aabd1b dream(memory): #4270 ReasoningBank.consolidate() HNSW orphan leak
storePattern() adds every pattern to the HNSW index, but
consolidate()'s prune and dedup loops only removed entries from the
in-memory map and AgentDB — never from the HNSW index itself. In a
long-running process (HooksLearningDaemon calls consolidate() every
60s), orphaned points accumulate until maxElements is exhausted,
after which storePattern()'s unguarded addPoint() throws "Index is
full, cannot add more elements" permanently, even though the index
is full of logically-deleted ghosts.

Fixed with two additive hnswIndex.removePoint(id) calls alongside the
existing deleteFromStorage(id) calls. Two new discriminating tests
(prune path, dedup path) reproduce the exact failure on baseline and
pass on the candidate; independently re-verified by an adversarial
critic subagent. Full @claude-flow/hooks suite 147/147, tsc clean.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_016nZstVChPSSNBwmMUJW8tE
2026-10-19 14:52:40 -04:00
rUv 02dab389b2 Merge pull request #4265 from ruvnet/fix/codex-npx-package-name
docs(codex): fix stray npx invocation of @claude-flow/codex
2026-10-19 19:51:29 +01:00
rUv 0b57d7933b Merge pull request #4275 from PerryLink/docs/hooks-worker-command
Fix command examples in the user guide that fail when copied
2026-10-19 19:51:05 +01:00
rUvandClaude 6cdad1ae0e dream(security): #4229 DENYLISTED_ENV_NAMES gaps — git/perl/ruby/java hijack family (evaluated, ACCEPT) (#4230)
* dream(security): denylist gaps in validateEnv() for git/perl/ruby/java env-var hijack family

DENYLISTED_ENV_NAMES (v3/@claude-flow/cli-core/src/mcp-tools/validate-input.ts)
covered loader-hijack and the 2026-09-21 search-path-family fix, but missed
credential/arbitrary-command vars in the same git family (GIT_ASKPASS,
GIT_PROXY_COMMAND), interpreter-flag-injection vars for Perl/Ruby/Java
(PERL5OPT/RUBYOPT/JAVA_TOOL_OPTIONS/_JAVA_OPTIONS/JDK_JAVA_OPTIONS), two more
search-path vars (PYTHONHOME, CLASSPATH), and git's numbered
GIT_CONFIG_KEY_<n>/VALUE_<n>/COUNT runtime-config-injection family (added via
a new regex, not a fixed name — strictly broader than any single name).
PYTHONSTARTUP included for defense-in-depth with an honest caveat (interactive-
REPL-only, not live-exploitable through today's non-interactive execSync path).
Researched and explicitly rejected: PYTHONEXECUTABLE (cosmetic, macOS-only),
PSModulePath (single-source, Grade C evidence only).

18 new discriminating tests added to validate-input-env.test.ts, matching the
file's existing pattern. Stash-isolated: 18/18 fail against baseline, 51/51
pass on candidate. Full @claude-flow/cli suite: byte-identical 60-failure set
baseline vs candidate (zero regressions). tsc --noEmit: 0 errors.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01S1h1otMCeN5gSX8S5gC17H

* dream(security): fix-forward post-critique — correct test counts, document GIT_CONFIG_NOSYSTEM/PYTHONSTARTUP caveats

Independent adversarial critic caught: (1) an arithmetic error in this
session's own evaluation writeup (32 pre-existing tests, not 33; 19 new
tests of which 18 discriminate, not 18 flat); (2) GIT_CONFIG_NOSYSTEM's
denylist rationale was undocumented despite guidance/mod-sources.ts's git()
helper setting that same var defensively elsewhere in this repo; (3) the
PYTHONSTARTUP comment overclaimed that execSync's non-interactive child
"cannot enter" Python's interactive mode — a caller-supplied `python3 -i`
can still trigger it. All three addressed: gist corrected, source comments
now document the real rationale for both. Net security conclusion for
PYTHONSTARTUP unchanged (defense-in-depth, no new capability — the caller
already controls the full command string). Re-verified: 51/51 tests,
tsc --noEmit clean.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01S1h1otMCeN5gSX8S5gC17H

* dream(security): update LEDGER.md for 2026-10-16 (#4229/#4230)

Appends tonight's row, confirms #4053/#3977 merged via GitHub MCP tools,
confirms no run-gap for 10-12..10-15, and flags that 10-11's own PR cited
a CVE-2026-25725 that does not resolve in NVD/MITRE.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01S1h1otMCeN5gSX8S5gC17H

* dream(security): fix CI — bump @claude-flow/cli-core 3.7.3->3.7.4 (leaf-package-publish audit)

The "Plugin package install-safety" CI check's audit-leaf-package-publish.mjs
caught that this PR's source change to v3/@claude-flow/cli-core (not bundled
into the release tarballs, resolved from the registry at the version
v3/@claude-flow/cli/package.json pins) left the leaf's own package.json
version unchanged — per CLAUDE.md's "Publishing Rules" (ruvnet/ruflo#3335,
#3390), that means a release would ship the OLD registry copy and this
fix would reach nobody. PATCH bump per repo semver policy (bug fix, no API
change): 3.7.3 -> 3.7.4. Updated the three places that need to agree:
cli-core's own package.json, @claude-flow/cli's dependency pin, and
v3/pnpm-lock.yaml's specifier for that workspace link.

Re-verified: audit-leaf-package-publish.mjs clean, tsc --noEmit 0 errors,
51/51 tests pass.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01S1h1otMCeN5gSX8S5gC17H

* dream(security): fix CI — bump root claude-flow's @claude-flow/cli-core range 3.7.3->3.7.4

audit-wrapper-dep-ranges.mjs (ruvnet/ruflo#2127) caught that the root
claude-flow umbrella's own declared dependency range for the just-bumped
@claude-flow/cli-core leaf (3.7.3) no longer includes the workspace's actual
version (3.7.4) after the prior commit's bump. package-lock.json's resolved
node_modules/@claude-flow/cli-core record intentionally left untouched (still
3.7.3, with its real registry integrity hash) since 3.7.4 has not actually
been published yet — see the PR comment on the structural publish blocker.

Re-verified all 5 install-safety audit scripts locally: clean.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01S1h1otMCeN5gSX8S5gC17H

* Revert "dream(security): fix CI — bump root claude-flow's @claude-flow/cli-core range 3.7.3->3.7.4"

This reverts commit 9dae077cb3.

* dream(security): resolve CI blocker — @claude-flow/cli-core@3.7.4 is now published

A maintainer's 3.57.0 release (main advanced from 1882006a0 to b93144803
while this PR sat open) published @claude-flow/cli-core@3.7.4 to the real
npm registry, containing this exact fix (verified via `npm pack` + diff
against the source on this branch). That resolves the structural blocker
described in this PR's comment: the root claude-flow umbrella's own
dependency range can now safely bump to match, since 3.7.4 genuinely
exists — unlike three days ago, this no longer breaks root `npm ci`/
`npm install` for the rest of the CI matrix.

Re-verified for real this time (not just the static audits): ran
`node scripts/smoke-cli-npx-install.mjs` directly — packs the real CLI
tarball and does a genuine `npm install` into a scratch project — and it
now succeeds end-to-end (previously failed with ETARGET). All 5 install-
safety audit scripts clean. 51/51 tests, tsc --noEmit 0 errors.

Note: main's own source tree (v3/@claude-flow/cli-core/src/mcp-tools/
validate-input.ts) is still at the pre-fix 3.7.3 content as of this
commit — only the npm registry got the fix early, via whatever process
published 3.7.4. Merging this PR is what reconciles main's source with
what's already shipped to real users.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01S1h1otMCeN5gSX8S5gC17H

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-19 16:55:41 +01:00
PerryLink 9ee87ea49b docs: fix the issue-claims and route-explain examples 2026-10-18 15:29:00 +00:00
PerryLink 6726f0f46a docs: use `hooks worker' in the Background Workers examples
`worker' is not a top-level command in 3.57.0, so the two examples in
docs/USERGUIDE.md exit 1 with "Unknown command: worker" when copied.
The command lives under `hooks worker', which the same guide already uses
further down.
2026-10-18 14:46:33 +00:00
randRuFlo 617f1935fa docs(codex): fix stray npx invocation of @claude-flow/codex
The package.json bin for this CLI is registered as claude-flow-codex,
but the package itself publishes under the scoped name @claude-flow/codex.
Several usage examples told a reader to run 'npx claude-flow-codex ...',
which resolves to a different (nonexistent) unscoped package rather than
this one.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-17 22:58:16 -04:00
rUv 275aff65a1 docs: label download badge with validated statistics 2026-10-18 01:47:47 +01:00
rUv 75ab118a7f docs: give download badge an agentic revolution headline 2026-10-18 01:45:44 +01:00
rUv 2f83654474 docs: vary illustrative download counter increments 2026-10-18 01:44:57 +01:00
rUv 536086a04d docs: increase illustrative counter by 100 per second 2026-10-18 01:43:30 +01:00
rUv c0fd7109df docs: start illustrative counter at 98 million (#4263)
* docs: start illustrative download animation at 98 million

* docs: pin illustrative 98 million counter and preserve measured total
2026-10-18 01:42:44 +01:00
rUv 4a1a4e3177 docs: animate downloads with a 30 second count up loop (#4262)
* docs: count up download badge once per second in a 30 second loop

* docs: pin 30 second download counter in README
2026-10-18 01:41:10 +01:00
rUv 819c0aff7a docs: add 3D icons to origin and download badges (#4261)
* docs: animate origin and download badges with 3D icons

* docs: pin refreshed 3D badge assets for immediate display
2026-10-18 01:38:57 +01:00
rUv d1e80400bd docs: give Claude Code and Codex distinct 3D animated badges (#4260) 2026-10-18 01:34:27 +01:00
rUv ae202d60a4 docs: unify animated badge dimensions and visual style (#4259) 2026-10-18 01:29:11 +01:00
rUv a23c11c904 docs: refresh ecosystem download badge from verified maintainer cohort (#4258) 2026-10-18 01:25:21 +01:00
rUv 715da4690f docs: illustrate Ruflo origins with dated commit evidence (#4257) 2026-10-18 01:20:27 +01:00
bbansandbbans ca31fc52be feat(doctor): add versioned JSON health check output (#4228)
Co-authored-by: bbans <252185257+bryanbans@users.noreply.github.com>
2026-10-17 16:35:30 +01:00
rUvandClaude ce7e78ab01 dream(performance): #4214 RaftConsensus.awaitConsensus() busy-poll → event-driven (evaluated, ACCEPT) (#4215)
* dream(performance): #4214 RaftConsensus.awaitConsensus() busy-poll -> event-driven

RaftConsensus.awaitConsensus() polled this.proposals via setInterval(...,10)
even though checkConsensus() already emits 'consensus.achieved' on every
accept/reject transition. Raft is Ruflo's default hive-mind consensus
algorithm, reachable from production via UnifiedSwarmCoordinator.proposeConsensus().
Third instance of a busy-poll bug class already fixed twice (UnifiedSwarmCoordinator
#3378, MessageBus #3563).

4 new discriminating tests, stash-isolated baseline-fails/candidate-passes
(3/4, 1 correct non-discriminating control), independently reproduced by an
adversarial critic. Full @claude-flow/swarm suite 281/281 (277 existing + 4
new), tsc clean both ways. Standalone wall-clock probe: 3.639ms/30 poll-timers
-> 0.058ms/0 timers (N=30).

Also closes a 3-night research thread (10-09/10-10/10-14) on graph-analyzer.ts's
dead native-acceleration detection: direct inspection shows ruvector's real
minCut/louvainCommunities exports are plain JS, not native-accelerated, so
wiring them in would not be a performance win (REJECT, with evidence).

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01MFLiva2zVEXr2n9UTK5YgU

* dream(performance): #4214 record PR #4215 in LEDGER.md

Fill in the real PR number (was a placeholder pending PR creation) in
tonight's ledger row, and note the 10-12/10-13/10-14 ledger-transcription
gap per the established convention.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01MFLiva2zVEXr2n9UTK5YgU

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-17 14:59:19 +01:00
Mondweep Chakravorty 332f22eec8 docs: ABP-governed SGit memory checkpoints and Ruflo CLI recovery validation (#4239)
* Document external SGit memory checkpoint MCP example

* Document ABP compilation and enforced memory adapter operations

* Document passing Ruflo CLI recovery and unresolved embedding persistence
2026-10-17 14:59:00 +01:00
KET ⚡ 45fa848b1b docs: repair user guide links to v3 packages (#4223) 2026-10-17 14:58:46 +01:00
randRuFlo 9a9411c26c feat(tui): actions by name behind the console's confirm card (ADR-489 phase 6)
The go prompt (: or /) takes an action as well as a page. A name is matched
literally against the console's palette entries (id, or name containing the
typed words, or a text command keyword), never fuzzily. A read runs at once
through Host.run (ruflo CLI by argv only); a change raises the console's own
state.pending card, pinned under the page bar, and runs only on a lone y while
every row of the card is on screen (state.shownCard). Paste, Enter, "yes", a
card too tall for the window or a replaced card run nothing; n/Esc drops it.
The console's own verdict on the run is pinned for 20 s.

- tui/pinned.ts: the card and result rows
- session: palette(), answer(), pending(), cardShown(), pinned()
- parity table wording, ADR-489 phase 6, guide; key line says "ask first"
- tests/tui-actions.spec.ts with a CLI stand-in recording the argv

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-14 06:15:07 -04:00
randRuFlo e7c29326d4 feat(tui): every console view opens in ruflo tui, with a menu, a go prompt, Back and opt-in mouse (ADR-489 phase 5)
- tui/parity.ts: a recorded decision for each of the console's views
  (same / partial / equivalent / claude-only); tests/tui-parity.spec.ts fails
  when a view in VIEWS has no decision or no row in ADR-489
- 0 opens the main menu (its keys open entries), : or / goes to a page by
  name, Esc/Backspace is Back, --view takes any page; the console terminal
  opens the AI page and the Room says on one screen that it needs Claude Code
- terminal renderer: a Box's width is honoured (the board's two groups side by
  side) and the board's entry labels are drawn (they were blank)
- --mouse (opt-in, SGR): click a page chip, wheel scrolls; off by default,
  switched off on exit, report bytes ignored without the flag
- CLI: --view validates against the loaded bundle's page list, --mouse flag

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-14 06:09:23 -04:00
randRuFlo 1e8d37e03a feat(tui): ruflo tui draws the console's pictures, looks and motion (console 0.44.0, ADR-489 phase 4)
The standalone terminal UI now leads each page with the same title art and
pictures the console draws, as coloured cells (Raster in the terminal kit),
in the console's looks (Classic BBS default, Orbital, plain), moving at
--fps with only the changed rows redrawn.

- tui/ansi.ts: Raster; control/escape/invisible/wide code points become
  spaces, malformed or oversized cells draw nothing
- looks: --look, t key; --boot; --fps, --no-anim, --no-pictures
- focus reporting pauses the animation clock; NO_COLOR, dumb terminals,
  and widths under 44 fall back to the words
- guide: flags, looks, the t key; corrects the confirm-card sentence
- ADR-489: phase 4 recorded, parity table skeleton
- README/guide SVGs regenerated from real frames (leak-checked)

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-14 05:44:48 -04:00
randRuFlo 29714a9e4a fix(console,cli): ruflo tui page bar marks the AI page, help says 1-6, policy-trust path never relative to cwd (console 0.43.1)
- tui: the page bar was painted from session.state.view, which the AI page never sets, so on page 6 it kept the previous page lit; it now follows session.page (9 tests, 4 failed first)
- tui --help and the console README said keys 1-5; they are 1-6 and o c s e m a (test holds the help text)
- cli: policyTrustRoot() no longer joins an empty or relative $HOME, which put the anchor mirror and key under the working directory; falls back to the account home or refuses (2 tests, 1 failed first)
- docs: ruflo-tui-walkthrough.svg re-recorded from real frames with the AI page and its ask-first card, 6 AI marked

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-12 12:55:08 -04:00
rUv f2ae86269b Merge pull request #4103 from ruvnet/docs/readme-tui
docs: mention the optional standalone ruflo tui (README, user guide, animated SVGs)
2026-10-12 09:44:23 -07:00
rUv 740d17f71e Merge pull request #4097 from ruvnet/fix/oct12-verified-issues
fix: accurate coverage reports and reliable SPARC/TDD workflow instructions
2026-10-12 08:56:43 -07:00
randRuFlo 72c3905e4d docs: mention the optional standalone ruflo tui in the README, with a user-guide section and animated SVGs
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>
2026-10-12 11:41:11 -04:00
randRuFlo c0cc3484e7 docs(#4097): receipts note describes the first validated state
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-12 11:15:57 -04:00
RuFlo b4cbd4be9f review(#4097): CI test ratchet exclusion, coverage report size cap and count clamping, sparc 0.3.5 / testgen 0.3.3, sanitize receipts
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-12 11:15:50 -04:00
rUv 6fe5706dfb fix: correct coverage reporting and plugin workflow contracts
Fixes #4082, #4083, #4084, #4085, #4086, #4087, #4088.

Validated on ruOS with 68 focused tests, both plugin smoke suites,
strict coverage reader type checking, and source checksums.
2026-10-12 07:40:46 -07:00
rUv ea0ea3d7e7 docs: embed compact verified Orbital SVG demo
Reduce vector replay from 29.6 MB to 3.84 MB through shared glyphs and per-cell animation. Retain 456 frames; verify SMIL timelines and img animation in Chrome.
2026-10-12 07:13:53 -07:00
rUv 2214ba3203 Revert "docs: feature latest Orbital console SVG demo in main README"
Restores the previous README and removes the oversized demo asset.
2026-10-12 07:07:52 -07:00
rUv 8c6b85de15 docs: feature latest Orbital console SVG demo in main README 2026-10-12 07:03:36 -07:00
randRuFlo 7718a142b4 feat(tui): the AI page: ask Codex (read-only, pinned) or OpenRouter, each question after a card (ADR-489 phase 3)
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>
2026-10-11 16:54:16 -04:00
rUv 7fca18f86e Merge pull request #4068 from ruvnet/feat/e2e-host-matrix
feat(e2e): three-host integration loop (Claude Code, Codex, OpenRouter) + fixes + ADR-490/491
2026-10-11 11:56:45 -07:00