Regression: #2284 fix for auto-memory-hook `workingDir` reverted by dogfood-helper sync (a5f86ad0); still broken in 3.41.2
- Dominant language
- TypeScript
- Stars
- 72.7k
- Forks
- 8.6k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 83
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:
```js
// 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'); // :22
```
Restoring 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:
```js
// 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.)
```bash
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 reads
```
## Suggested fix
Fix the root rather than the three call sites, in both copies of all three helpers:
```js
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 `/.claude-flow/data/`.
Two process points worth considering, since this is the second time this file regresses:
1. `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.
2. The two committed copies of these helpers keep diverging (`e7783f2f` exists solely to
reconcile them). A generated-from-single-source arrangement, or a CI check that diffs
`.claude/helpers/` against `v3/@claude-flow/cli/.claude/helpers/`, would close the class.
## Environment
- ruflo 3.41.1 (Homebrew global), `@claude-flow/cli` 3.41.1; verified identical in 3.41.2
- macOS (Darwin 25.6.0), node via Homebrew
- Project with no local `.claude/helpers/` and no `node_modules` (Go project), so both the
`$HOME` hook fallback and the `@claude-flow/memory` resolution path are exercised
## Related
- #2284 — the original bug, closed COMPLETED, regressed
- #2545 — `@claude-flow/memory` unresolvable; the Strategy 0 sidecar
(`.claude-flow/memory-package.json`) from that fix is still required for a project with no
`node_modules`, and `ruflo init` did not create one here
- #2633 — durable state anchored to raw `process.cwd()`; same family of root-resolution drift
Contributor guide
Research direction
Start with .claude/helpers/auto-memory-hook.mjs and its matching v3/@claude-flow/cli copy, then compare metrics-db.mjs and learning-service.mjs with intelligence.cjs's root-resolution logic. Reproduce from a project without local helpers using the documented import command and inspect hook-handler.cjs:510. Done means both helper copies resolve the project consistently and import, init, and consolidate use the project's .claude-flow/data store.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- cli, developer-experience, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100