feat(ruflo): rolling support window, 3.46.x adoptions and running backups - #247
Merged
Merged
Conversation
The Ruflo dependency policy now carries supportWindow (newest 6 minors, never fewer than those first published in the last 30 days). The loader validates the optional field: positive integer newestMinors and minDays and a string basis; anything else invalidates the policy.
…st 30 days) ak status adds a Ruflo support-window row computed from release dates remembered in kit.json (versionCheck.rufloMinors): inside the window is info, below it is a fail row that sync repairs by upgrading, and with no remembered dates the row says the window is not yet known and names ak sync. A plain read never calls the network. A non-dry, upgrading sync records each minor's first stable npm publish right after its forced drift lookup; a failed lookup keeps the old dates. The versions section gains drift/loadConfig/now seams and sync.run a releaseDatesRunner seam.
…uflo has the fix The watch computes the Ruflo support-window floor from the npm release dates it reads (reusing a gate's fetch) and the registry's supportWindow. A released Ruflo entry whose fix version is above the floor moves from the act-now groups to 'Released, waiting for the support window' with no dispatch; its 'released' ledger line carries no branch. With no floor (offline, npm unreadable, no window) nothing is held. The upstream-status skill names the new group.
Ruflo fixed its fabricated CVE count (ruvnet/ruflo#2694) in 3.32.2, below the support window's floor. ak no longer injects the getStatuslineData wrapper, the footer drops rufloLocalSecurity and rufloHonestInsight, and status and sync drop the statusline/cve subsystem. SEC_WRAP_STRIP stays for one release so a statusline an older ak patched is cleaned on the next sync. The registry marks ruvnet/ruflo#2694 adopted with its removal proof.
Ruflo shipped `migrate fix --agents` in 3.38.2, below the support window. The scaffold-agents info row now says the installed Ruflo predates it and points to ak sync. The section gains gaps/fixAvailable seams for a hermetic test. The registry marks ruvnet/ruflo#2986 and ruvnet/ruflo#2985 (the same ak change) adopted.
ADR-0041 §7 records the rule, where it lives (supportWindow on the Ruflo dependency policy), the remembered evidence (kit.json versionCheck.rufloMinors, written only by an upgrading ak sync) and the watch's hold. The hook-assurance DDD context gains SupportWindow. UPGRADING, UPSTREAM-WATCH and TROUBLESHOOTING describe the window, the waiting-for-window group and the retired statusline overlay; ak sync --help says when release dates are read.
A live daemon that deferred backup or distillation (CPU load or low free memory, read from .claude-flow/logs/daemon.log after the last daemon start) now gets a daemons warning until the job's own metrics are newer. On macOS a low-memory deferral names ruvnet/ruflo#2935 and is a sync repair; elsewhere it names the flat threshold key. With no daemon and start-on-use on, the row says Ruflo starts it on the next ruflo command.
…ettings ak setup no longer turns claudeFlow.daemon.autoStart to false. It writes flat keys in .claude-flow/config.json before starting the daemon: daemon.idleSecs 0 below 3.46.0 (ruvnet/ruflo#3194) and, on macOS, daemon.resourceThresholds.minFreeMemoryPercent 0 (ruvnet/ruflo#2935), never through ruflo config set (ruvnet/ruflo#3449). It turns init's autoStart false to true unless kit.json rufloDaemon.autoStart is false, with receipts in kit.json that ak uninstall uses to restore. A malformed file or a user value is left alone. ak status reports drift in a Ruflo repository and ak sync applies it, removing keys a newer Ruflo no longer needs and restarting a live daemon so it reads them. Setup discloses both writes.
SETUP and TROUBLESHOOTING describe what ak writes in .claude-flow/config.json and .claude/settings.json, the new daemons rows, and the kit.json opt-out. ADR-0016 and the ubiquitous language record the managed daemon settings; the audit record's Addendum 3 Item 1 gets the 3.46.1 implementation note and the disposable-project proof. ak setup --help and ak sync --help mention the daemon step.
The macOS deferral row promised a sync repair in any project with a live daemon, but sync manages daemon settings only in a Ruflo repository, so elsewhere the planned fix could never converge. Outside one it is now the manual step. Sync also no longer restarts a daemon whose deferred job has run since: status and sync share one pendingDeferral check.
…ps the built-in engine Ruflo 3.32.2+ falls back to security/builtin-aidefence.js when @claude-flow/aidefence is missing (ruvnet/ruflo#2670), so a missing aidefence now costs only adaptive learning and the aidefence_* MCP tools. - natives: rufloBuiltinDefence() probes the CLI's built-in engine. - status: warn (sync repair kept) instead of fail when the engine exists. - verify: run defend with -o json and read the verdict (parseDefendVerdict); the text-mode post-detection crash (ruvnet/ruflo#3473, still in 3.46.1) is reported as a crash. - footer: a fourth, silent "builtin" state; no alarm. - about and healAidefence detail describe what aidefence adds. - registry: #2670 adopted; #3473 re-checked on 3.46.1.
Ruflo 3.46.0 honours --no-codex-detect and --no-skills-sh (ruvnet/ruflo#3167, PR #3434). rufloProjectInitInvocation(version) passes the flags alone from 3.46.0; below it (and for an unknown version) it keeps --format json and RUFLO_NO_SKILLS_SH=1, since 3.39 to 3.45 are inside the support window. The registry's affected ranges now accept <major>.<minor>.x, the suppression constraint covers 3.38.21 to 3.45.x, and #3167 is adopted with the removal proof run on 3.46.1.
Ruflo 3.46.0 wires the MCP policy enforcer into both stdio entry points (ruvnet/ruflo#3415, PR #3423); 3.45.0 has no evaluateToolCall there. The not-wired explanation now applies below 3.46.0 (it stopped at 3.44.0), and the catalogue no longer calls the policy inert. Live proof on 3.46.1 with ak's policy capped at 2: two memory_stats calls allowed, the third refused, all three audited. From a subfolder with no .harness/ every call is refused; that exposure stays open until the launcher's Claude mode (plan Task 4.1).
A committed .harness/mcp-policy.json has no receipt on a teammate's machine, so reconcilePolicy reports it user-managed there and stops managing it. Other tools (Agentic QE) commit their own policy file on purpose, so ak excludes only its own file, never .harness/ as a whole, and never touches .gitignore. excludeFromGit adds one anchored line under a "# agentic-kit" comment to the repository's info/exclude, resolved without spawning git (a linked worktree's .git file and commondir lead to the main repository's file, the only one git reads). It runs whenever ak's file is written or already converged; removing the policy removes only that line and its comment. Sync reports the change and the trust manifest discloses it.
…er since 3.46.0) PR #3441 shipped in Ruflo 3.46.0: ruflo doctor reports the agent-browser CLI (ADR-122) against a 0.27.0 minimum, confirmed in the @claude-flow/cli 3.46.0 tarball and the installed 3.46.1. ak never carried a workaround.
PR #3420 (3.46.0) makes the daemon parse .claude-flow/config.yaml, but the memory root still reads JSON only (memory-initializer.js, rechecked on 3.46.1), so ak keeps its memory pin and the entry stays watching. The entry now names the ak files that cite it.
The note said "open as of 2026-08-13". It now cites the Aug 31 triage and the 2026-09-27 hosted probe on Ruflo 3.46.1 (run 36333572972): 10/10 aborts by default and 10/10 with single-threaded ONNX Runtime sessions. The step stays continue-on-error. The registry records the comment.
…058) ADR-0058 Updated 2026-09-27: Ruflo 3.46.0 enforces the policy on stdio (#3415); ak's boundary corrected from 3.44.0 to below 3.46.0; ak excludes its policy file from git (section 5, the section 7 table row, Consequences and Implementation status). User-facing docs describe the current state: the security rows in TROUBLESHOOTING (built-in engine, the #3473 crash message), the version- gated init flags in SETUP and HOST-SUPPORT, the 3.46.0 governance boundary and git exclusion in MANAGED-TOOLS and DASHBOARD, and the footer's alarm in README. The audit record gets the slice 3 implementation note.
GIT_CONFIG_GLOBAL=/dev/null has no Windows equivalent path, so the tests set it only off Windows; -c user.name/user.email already give git what the tests need.
Sync and project setup now add a line to the repository's .git/info/exclude where MCP governance is on; the upgrade note says what is written, what is never touched, and how to untrack an already committed copy.
ak x ruflo-mcp --host claude starts Ruflo at the repository root (else the folder, else the user-level store) like Codex's mode, but keeps Claude Code's settings env: no componentEnv and no governance deletion (ADR-0058 §3). ak's agent-browser config stays. An unknown --host exits 2. Started from a subfolder, Ruflo now reads <repo>/.harness/mcp-policy.json, which closes the 3.46.x stdio-governance exposure for Claude sessions opened in a subfolder (B3-D1).
register() now adds claude-flow at user scope as `ak x ruflo-mcp --host claude` (with ak's AGENT_BROWSER_CONFIG). ak's earlier `ruflo mcp start` entry and the launcher entry are both ak's to replace; any other command, scope or env key stays the user's. When `ak` is not on PATH, register() changes nothing and returns reason 'ak-not-on-path', which setup, sync and ak x mcp pick report. Status warns on ak's old entry (a sync repair when registration is managed) and, for the launcher, names the store it picks from the current folder. Hermetic Claude seats use the Claude mode too, and the memory rows now say the launcher serves Claude Code and Codex (B3-D1).
…utside projects
Harvest takes rufloMemoryLocation(cwd) directly: from a repository it
still runs at <repo> with <repo>/.swarm/memory.db; from the home folder,
a temporary root or a tool's own folder it runs in the flat user-level
store with CLAUDE_FLOW_DB_PATH and CLAUDE_FLOW_MEMORY_PATH pinned and
distils that store. An explicit root (ak x verify harvest) is unchanged.
Project setup from such a folder now refuses before spawning anything
("this folder is <reason>; run ak setup from a project folder").
memoryProjectRoot is unchanged for the daemons row and projectMemoryEnv
(B3-D1).
…receipt Older ak setup runs left `_setup/verify-<pid>-<ms>` rows (content setup-verify, namespace _setup) in project and user-level stores; Ruflo mirrors them into agentdb-memory.db and its own delete leaves the mirror (ruvnet/ruflo#3450, re-checked on 3.46.1). Status now warns with the count per store folder, and a new memory-probe-cleanup sync step backs each affected file up with VACUUM INTO, deletes exactly the matched ids from both files, and writes a receipt under the state folder. kit.json cleanups.setupProbeRows records each cleaned file so it is cleaned at most once. Scope: the current project's store and the user-level store (B3-D2).
The audit record gains the four Branch 3 decisions (B3-D1 to B3-D4) in its decision format, with the implementing commits and the disposable proofs. ADR-0058 §3 and ADR-0016 record that Claude Code reaches Ruflo through ak x ruflo-mcp --host claude. SETUP, HOST-SUPPORT, UPGRADING, TROUBLESHOOTING and the DDD glossary describe the launcher for both hosts, the ak-on-PATH requirement and the one-time probe-row cleanup.
…odex registration
The launcher that Claude Code and Codex register spawned a bare `ruflo`. On Windows that is an npm .cmd shim CreateProcess cannot start, so every launch failed with ENOENT while readiness (have/run, which resolve the shim) passed. It now resolves the command through exec.mjs resolveShim against the launch env's PATH and refuses with a message when no safe invocation exists.
A malformed .claude-flow/config.json, or one holding the user's own value for a key ak wants, is left untouched and never counts as drift, so ak status said nothing about it. The dry-run reconcile now names the held keys (reconcileRufloDaemon `held`, daemonConfigHeld), and status adds a manual row that names the file, the user's value and the flat key to set.
When .claude-flow/config.json was malformed or held the user's own minFreeMemoryPercent, status still offered the macOS deferral as a sync repair. Sync then changed nothing and only restarted the daemon, which hid the row until the next deferral and repeated on every sync. Status now makes that deferral a manual step naming the key, sync skips the restart when the floor is held by the user, and its warning says the daemon was not restarted for that key.
register() refuses with 'ak-not-on-path' when it would write a registration that starts `ak`, so the mcp sync step failed on every run while status kept offering it as a sync repair. When ak manages the registration, status now looks ak up and, when it does not resolve, makes the three rows whose fix goes through register() manual: the registration that does not start through the launcher, the missing agent-browser config and the missing registration. Each names "put ak on PATH, then run ak sync". The legacy-migration row stays a sync fix: it does not need a new registration when claude-flow is already right. The offline status fixture has an empty PATH, so the golden snapshot now records the manual row. The two sync plan tests that expect the mcp heal run with a fake ak on PATH, and a new test pins that the heal is not planned without it.
SETUP, TROUBLESHOOTING and ADR-0016 say a .claude-flow/config.json that is unreadable or holds the user's own value is left alone, ak status names the key to set, and sync does not restart the daemon for it. UPGRADING says status lists "put ak on PATH, then run ak sync" when the launcher registration cannot be written.
After the rebase onto #245, the guarded unit run failed on two rules that the branch's own tests broke. The git-exclude test built git's environment from process.env, and the spawn-env guard now refuses that. It now runs git through spawnEnv with its own throwaway home. Three test files left their sandbox homes behind, and the leftover check reported ak-about-security-home, ak-probe-cleanup-home and ak-security-status-home. Each file now removes its home when it finishes.
Claude Code starts whatever `ak` it finds on PATH. That can be an older install than the kit writing the registration. ak 4.0.0-alpha.56 rejects `--host` (exit 2, "Unknown option"). So a sync run by a newer kit re-registered claude-flow to a command that cannot start, and every Claude session lost Ruflo. register() now asks the PATH `ak` for `ak x ruflo-mcp --help` before it writes anything. `--help` is answered before the command runs. When the help does not name `--host`, it returns the new reason 'ak-launcher-outdated' and leaves the working registration in place. The status mcp section asks the same question, but only when sync would re-register. It then makes those rows manual, with the fix "update the `ak` on PATH ..., then run `ak sync`". Setup, sync and `ak x mcp pick` name the new reason. `ak` joins exec.mjs's Windows shim list, so the check resolves its npm shim. The hermetic Claude seat of `ak run` and qe-court now starts Ruflo through the running kit itself (node plus this kit's bin/agentic-kit.mjs), never a PATH `ak`.
"fresh dual-host Codex provisioning and repeated refresh retain one canonical connection" went stale when claude-flow moved onto `ak x ruflo-mcp --host claude`. It had two faults. It injected no launcher check, so on the sandbox's empty PATH register() refused before the runner ran (false !== true). It also still expected `ruflo mcp start`. It now injects a ready launcher and expects the launcher arguments with ak's AGENT_BROWSER_CONFIG. The fake ~/.claude.json gets the launcher entry with that env, so later refreshes find it already in place and claude-flow is added once.
…er entry Codex's Claude config import copies Claude Code's MCP servers by name. Since B3-D1, Claude Code's claude-flow is `ak x ruflo-mcp --host claude`. On a machine without the disabled placeholder, Codex therefore gained a second Ruflo transport. ak recognised only `ruflo mcp start` under that name, so both tables had no repair kind, the repair plan was empty, and every sync reported an unrepairable duplicate and exited 1. A Codex claude-flow table in ak's Claude launcher form now counts as the same alias. It needs exactly command and args, with at most ak's AGENT_BROWSER_CONFIG child. Sync disables it in place with the existing placeholder, after the usual backup and confirmation. Consent is remembered for that form as well. The Codex-mode launcher under the claude-flow name stays the user's. The repair reason names the imported copy instead of calling it a deprecated transport.
…ject rufloProjectRoot accepts any Git repository root with a .claude-flow/ folder. Ruflo 3.46.1 does not count a bare folder as a project (services/daemon-autostart.js:90-123, isRufloProject), because its startup migration can create one on its own (ruvnet/ruflo#2852). It does count .claude-flow/config.json. On macOS ak always wants the free-memory floor, so sync wrote that file in such a repository and made it a Ruflo project. The next ruflo command there then started a detached daemon. applyRufloDaemon and the status drift, held and deferral rows now use rufloDaemonProjectRoot. It requires the same gate plus one of Ruflo's durable markers: .claude-flow/config.{yaml,yml,json}, claude-flow.config.json, .swarm/memory.db, a claudeFlow block in .claude/settings.json, or a ruflo/claude-flow server in .mcp.json. rufloProjectRoot keeps its ADR-0058 role for the policy file.
The Open items still listed three things this branch resolved. Each is now marked resolved with its commits: - Claude-side memory outside a project (B3-D1): 518b4be, 8c91658 and 8966a18. - The one-time _setup/verify-* cleanup (B3-D2): ec6c936. - setup turning daemon start-on-use off (Addendum 3 Item 1): a9d59cd. The Branch 3 decision notes now cite the SHAs after the rebase onto main. B3-D1 records the launcher check and the disabled Codex import copy. The daemon note records the durable-marker gate.
The launcher note said the PATH `ak` "must be this version or newer". But the released 4.0.0-alpha.56 has the same version number as this build and still lacks `--host`. The note now names the capability ak checks (`ak x ruflo-mcp --help` must list `--host`), as SETUP.md does.
…uflo bundles them Decision B3-D5: an AgentDB fix delivered through Ruflo (doneWhen.release.bundledBy) counts as released for ak only when the oldest Ruflo inside the support window bundles a fixed agentdb, the same rule Ruflo's own fixes follow. - fetch: bundled() takes an optional carrier version, so the floor Ruflo's dependency chain resolves exactly like the newest one's. - watch: once the floor is known, resolve what the floor Ruflo bundles for the entries the newest carrier was checked for and for bundled entries recorded as released with a first fixed version. - classify: such an entry waits for the window until the floor bundles the fix; a floor bundle that could not be resolved is "Could not check". The held ledger line carries no branch and a newer Ruflo never changes it. - render: the held line names what the floor Ruflo bundles.
…ed range The registry schema now describes a dependency policy's optional supportWindow (newestMinors, minDays, basis, unsupported) and the affected-range grammar upstream.mjs applies: an exact version, <major>.x or <major>.<minor>.x. A package-qualified affected item is noted as reader-only. bundledBy's description names the support-window floor (decision B3-D5).
Branch 3's fifth decision: an AgentDB fix delivered through Ruflo counts as released for ak only when the oldest supported Ruflo bundles a fixed agentdb (choice A, oldest supported Ruflo; B was the newest Ruflo). The audit records it with its limit (npm resolves each range to its highest match, so the answer is a fresh install of the floor Ruflo). UPSTREAM-WATCH.md describes the floor check and the held group; ADR-0041 section 7 and its Updated line note it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adopts a rolling Ruflo support window and Ruflo 3.46.x's fixes, turns Ruflo's backups and distillation on, and implements the maintainer's Branch 3 decisions (B3-D1–D5, recorded in the audit record).
ak statussays the Ruflo is unsupported and points toak sync. The upstream watch holds a workaround removal until the oldest supported Ruflo contains the fix. AgentDB fixes wait until that Ruflo bundles a fixed agentdb (B3-D5).ak setup/syncturn Ruflo's daemon auto-start on, under a receipt..claude-flow/config.json, and only in a durable Ruflo project:daemon.idleSecs: 0below 3.46.0 (daemon: idle-shutdown check uses restored lastRun/lastStartedAt, so a daemon with old persisted state self-kills before its first worker ever runs ruvnet/ruflo#3194), and the macOS memory gate relaxed until macOS: daemon memory gate uses os.freemem(), deferring ~70% of workers and causing a KeepAlive restart loop ruvnet/ruflo#2935.ruflo config setis never used (config set cannot configure the daemon: wrong file, nested keys, and a value of 0 rejected ruvnet/ruflo#3449).security defendis reported as working on the built-in engine (security defend non-functional on 3.28.0: @claude-flow/aidefence dropped from the dependency tree but still imported — banner-only output, error silently swallowed ruvnet/ruflo#2670). Verify reads the-o jsonverdict, so the security defend crashes on every detected threat; exit 1 comes from the error handler ruvnet/ruflo#3473 crash is reported as a crash, not a detection.totalCves = 3+cvesFixedcounted from scan FILES, not findings ruvnet/ruflo#2694);SEC_WRAP_STRIPis kept for one release.ak x ruflo-mcp --host claude, so Claude sessions outside a project follow the same store rule as Codex (B3-D1). This happens only when theakon PATH supports--host; otherwise sync reports a manual step. Codex's imported copy of that entry is recognized and handled.ak synccleanup removes old_setup/verify-*probe rows from both memory stores, with preview, backup and receipt (B3-D2)..harness/mcp-policy.jsonis kept out of git via.git/info/exclude; no tracked file changes.supportWindowand the affected-range grammar.Verification
scripts/run-tests.mjs), Node 26.4: 5,324 pass / 0 fail. Node 22.22.3: green. UI: 495/0. Coverage: about 93.96 / 82.76 / 93.19.--host claude;.claude-flow/becoming a Ruflo project marker.ak.cmd/ak.ps1capability probe, shim resolution) are proven only by this CI run.Refs #239, #213 · remediation program Branch 3
🤖 Generated with Claude Code