Repository navigation
Regression: #2284 fix for auto-memory-hook workingDir reverted by dogfood-helper sync (a5f86ad0); still broken in 3.41.2 #3286
Description
Summary
The fix for #2284 (auto-memory-hook.mjs hardcodes workingDir: PROJECT_ROOT) landed in
facec4cc on 2026-06-04, was never propagated to the package-distributed copy, and was
then reverted on the root copy by a5f86ad0 on 2026-07-04. Both copies on main
today, and the published 3.41.2 tarball, carry the original buggy line again.
#2284 is closed as COMPLETED, so the regression is invisible.
Separately: the fix addressed only workingDir. The underlying PROJECT_ROOT definition
it derives from was never touched, so DATA_DIR / STORE_PATH stay wrong even with the
original fix applied. Details in "Scope" below.
Regression trail
| Date | Commit | Effect |
|---|---|---|
| 2026-06-04 | facec4cc |
Fixes #2284 on .claude/helpers/auto-memory-hook.mjs: -workingDir: PROJECT_ROOT / +workingDir: process.env.CLAUDE_FLOW_CWD || process.cwd() (two sites: doImport, doSync). |
| 2026-06-15 | e7783f2f |
"reconcile diverged CLI-package helper copies (FIX 2/4/5)" propagates FIX 2/3/4/5 to v3/@claude-flow/cli/.claude/helpers/, but not this one. The distributed copy still has the bug. |
| 2026-07-04 | a5f86ad0 |
"chore: sync repo dogfood helpers to 3.23.0" copies the installed package's helpers over the repo's root copy. Since the package copy never received the fix, this reverts it: -workingDir: process.env.CLAUDE_FLOW_CWD || process.cwd() / +workingDir: PROJECT_ROOT, twice. |
Verification on current main:
.claude/helpers/auto-memory-hook.mjs:20 const PROJECT_ROOT = join(__dirname, '../..');
.claude/helpers/auto-memory-hook.mjs:275 workingDir: PROJECT_ROOT,
.claude/helpers/auto-memory-hook.mjs:335 workingDir: PROJECT_ROOT,
v3/@claude-flow/cli/.claude/helpers/auto-memory-hook.mjs:20/275/335 (identical)
npm pack @claude-flow/cli@3.41.2 ships the same three lines. The three affected helper
files are byte-identical between 3.41.1 and 3.41.2, so upgrading does not help.
Scope: the fix was too narrow to begin with
workingDir is one of three consumers of the same bad root:
// auto-memory-hook.mjs:20
const PROJECT_ROOT = join(__dirname, '../..');
const DATA_DIR = join(PROJECT_ROOT, '.claude-flow', 'data'); // :21
const STORE_PATH = join(DATA_DIR, 'auto-memory-store.json'); // :22Restoring only the workingDir lines fixes where the bridge looks for memory files, but
the backend store is still written under the wrong root. Meanwhile intelligence.cjs
resolves its own root correctly:
// intelligence.cjs:20-36
function resolveProjectRoot(startDir) {
if (process.env.CLAUDE_PROJECT_DIR) return path.resolve(process.env.CLAUDE_PROJECT_DIR);
// ...walk up looking for .git / .claude-flow
}
const PROJECT_ROOT = resolveProjectRoot(process.cwd());
const STORE_PATH = path.join(PROJECT_ROOT, '.claude-flow', 'data', 'auto-memory-store.json');So the writer and the reader disagree on the store path. intelligence.consolidate()
returns {"entries":0,"edges":0,"message":"No store to consolidate"} forever, and
intelligence.init() returns {"nodes":0,...,"message":"No memory entries to index"} —
which the hook-handler prints only when nodes > 0 (hook-handler.cjs:510), so the user
sees nothing at all. The hooks appear dead while exiting 0.
metrics-db.mjs:15 and learning-service.mjs:29 have the identical join(__dirname, '../..')
definition.
Reproduction
Trigger condition is the $HOME fallback in the generated settings.json hooks:
sh -c 'D="${CLAUDE_PROJECT_DIR:-.}"; [ -f "$D/.claude/helpers/hook-handler.cjs" ] || D="${HOME}"; exec node "$D/.claude/helpers/hook-handler.cjs" route'
Any project without a local .claude/helpers/ takes D="$HOME", so the helper runs from
~/.claude/helpers/ and join(__dirname, '../..') resolves to $HOME rather than the
project. (#2284 reported the same shape via the plugin marketplace path; the $HOME
fallback is a second route to it.)
cd /path/to/a/project-without-local-helpers
CLAUDE_PROJECT_DIR=$PWD node ~/.claude/helpers/auto-memory-hook.mjs import
# [AutoMemory] ✓ Imported 0 entries (0 skipped)
ls ~/.claude-flow/data/auto-memory-store.json # exists, contains []
ls ./.claude-flow/data/auto-memory-store.json # ENOENT — what intelligence.cjs readsSuggested fix
Fix the root rather than the three call sites, in both copies of all three helpers:
const PROJECT_ROOT = process.env.CLAUDE_PROJECT_DIR || join(__dirname, '../..');Preferring CLAUDE_PROJECT_DIR (rather than re-applying CLAUDE_FLOW_CWD || process.cwd())
makes the .mjs helpers agree with intelligence.cjs's existing resolveProjectRoot()
precedence by construction, which is the actual invariant being violated. Verified locally:
Imported 2 entries → init: {"nodes":2,...} → consolidate: {"entries":2,...}, with all
artifacts landing under <project>/.claude-flow/data/.
Two process points worth considering, since this is the second time this file regresses:
a5f86ad0's dogfood-sync direction (installed package → repo) silently overwrites repo
fixes that have not yet shipped. A guard or a sync in the other direction would have
caught it.- The two committed copies of these helpers keep diverging (
e7783f2fexists solely to
reconcile them). A generated-from-single-source arrangement, or a CI check that diffs
.claude/helpers/againstv3/@claude-flow/cli/.claude/helpers/, would close the class.
Environment
- ruflo 3.41.1 (Homebrew global),
@claude-flow/cli3.41.1; verified identical in 3.41.2 - macOS (Darwin 25.6.0), node via Homebrew
- Project with no local
.claude/helpers/and nonode_modules(Go project), so both the
$HOMEhook fallback and the@claude-flow/memoryresolution path are exercised
Related
auto-memory-hook.mjshardcodesworkingDir: PROJECT_ROOT(plugin path) instead of user's project #2284 — the original bug, closed COMPLETED, regressed- Documented
npx ruflo initpath leaves self-learning silently non-functional:@claude-flow/memoryunresolvable by construction,daemon startabsent from quickstart #2545 —@claude-flow/memoryunresolvable; the Strategy 0 sidecar
(.claude-flow/memory-package.json) from that fix is still required for a project with no
node_modules, andruflo initdid not create one here - Durable state anchored to raw process.cwd(): agent cwd drift silently resets autopilot/neural/metrics/memory — repro + a complete tested fix design (ADR-0100/0137) #2633 — durable state anchored to raw
process.cwd(); same family of root-resolution drift
Activity
patrickitalo commentedon Sep 11, 2026
Additional finding while patching this locally: affected users have no durable workaround, because the version-stamped auto-refresh reverts the fix on the one file that matters.
Observed live
Patched
~/.claude/helpers/auto-memory-hook.mjsat 20:59. By 21:03 the file was byte-identical to the unpatched package copy again and.helpers-versionhad been stamped3.41.2. Noruflocommand was run knowingly —helper-refresh.jsis imported on every CLI startup, so any incidental CLI invocation re-copies the helpers whenever the stamp is stale.Why only one of the three files regresses
CRITICAL_HELPERSindist/src/init/helper-refresh.js:The same
const PROJECT_ROOT = join(__dirname, '../..');also lives inmetrics-db.mjs:15andlearning-service.mjs:29. Those are not on the list, so a local patch there is permanent — while the patch onauto-memory-hook.mjs, the file this issue is actually about, is not.Why patching the package source is not an option either
The natural workaround — patch the copy the refresh reads from, so it propagates the fix instead of reverting it — is closed off by the integrity gate, which hashes the source, not the destination:
A patched source fails its signed hash and the gate fails closed for all of
CRITICAL_HELPERS— so that workaround would silently freeze legitimate updates tohook-handler.cjs,intelligence.cjsandstatusline.cjsas well. Correct behaviour for a signing gate; it just means there is no clean local mitigation.So the options a user actually has are: re-apply after every version bump, or give the project a local
.claude/helpers/sojoin(__dirname, '../..')happens to resolve correctly and the$HOMEfallback is never taken. Across 26 ruflo-initialised projects here, that split is exactly what the data shows — every project with a local helpers dir has a populatedauto-memory-store.json, and nearly every project on the$HOMEfallback has none. Restoring the resolution fix recovered 233 memory entries that were being written to an unreachable path.Relevant to process point 2
The "multiple divergent copies of the same helper" pattern bit again, in a different place:
~/.claude/settings.json'sstatusLinepointed at~/.claude/plugins/marketplaces/ruflo/.claude/helpers/statusline.cjs, a clone pinned atclaude-flow 3.26.0, while the installed CLI was 3.41.1. That copy'sgetPkgVersion()probesmarketplaces/ruflo/package.jsonfirst, ahead of every global-install probe, so the statusline confidently reportedRuFlo V3.26.0for months — the marketplace clone reporting its own version as the user's. Different root cause, same shape: several copies of one helper, no single source of truth, and the stale one winning. Happy to file that separately if useful.fix(helpers): resolve modules from the helper root and keep session w…