OpenWolf 2.0.1 — four hook defects (one silently disables write tracking)
Observed on v2.0.1 (latest published). Defect 1 is also present in v2.0.0 —
its post-write.js carries the same import while init.js omits the file from
the copy list — so the whole v2 line is affected, on every platform.
Defects 1-3 are platform-independent; defect 4 is Windows-only.
Environment: Windows 11, Node v22.17.0, Claude Code.
Line numbers refer to the published build under dist/src/.
1. symbol-extractor.js is never installed — post-write.js dies on every write
Severity: high. Silently disables write tracking, memory.md logging and
anatomy.md updates in every project, on every write, from install onward.
src/hooks/post-write.js:6 imports ./symbol-extractor.js, but that filename is
absent from all three hook file lists:
| File |
Line |
List |
src/cli/init.js |
~550 |
hookFiles — install |
src/cli/update.js |
~413 |
hookFiles — update |
src/cli/status.js |
~32 |
hookFiles — health check |
The package ships the file (dist/hooks/ and dist/src/hooks/); only the copy
lists omit it. Result:
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '.../.wolf/hooks/symbol-extractor.js'
imported from .../.wolf/hooks/post-write.js
Two things make this hard to notice:
- A missing ESM import fails at module load, before
post-write.js's own
try/catch blocks and before main().catch(() => process.exit(0)). The hook
exits 1 and the agent harness surfaces nothing.
post-write.js is the only hook importing it, so reads keep being tracked
and only writes go quiet — which reads as "idle", not "broken".
Because it is also missing from status.js, openwolf status reports healthy
hooks on a fully broken install (✓ All 7 hook scripts present).
Fix: add "symbol-extractor.js" to all three lists. After the fix
openwolf status reports 8 and detects the failure.
2. countSemanticEntries can never match — reminder fires unconditionally
Severity: medium. Stop hook emits ACTION REQUIRED: N files were modified this session but no semantic summary was written to memory.md on every turn,
regardless of what the user writes.
src/hooks/shared.js:~620:
const today = new Date().toISOString().slice(0, 10);
const todayPrefix = `| ${today}`; // "| 2026-08-05"
if (line.startsWith(todayPrefix) && !mechanical.test(line)) count++;
But memory.md rows use | HH:MM | — the format mandated by the project
template and by the reminder string in stop.js:~211 itself. Measured on one
real project: 543 rows in HH:MM format, 0 matching todayPrefix,
countSemanticEntries() → 0.
The hook therefore demands a format its own checker rejects. Note the
mechanical regex one line above (^\|\s*[\d:]+) does anticipate HH:MM, so
only the todayPrefix filter is inconsistent.
Fix: scope to the newest ## Session: <today> heading and count
non-mechanical rows beneath it; fall back to date-prefixed rows when no heading
for today exists, so older history is not miscounted.
3. Buglog reminder checks a list the file can never appear in
Severity: medium. ACTION REQUIRED: ... buglog.json was not updated fires
even immediately after buglog.json is updated.
src/cli/../hooks/stop.js:~153:
const buglogWritten = session.files_written.some(w => w.file.includes("buglog.json"));
buglog.json lives under .wolf/, and post-write.js:39-44 returns early for
every .wolf/ path before the session-tracker step. It can never be present
in files_written, so buglogWritten is always false.
Fix: compare buglog.json's mtime against session start. This also catches
updates made outside the Write/Edit tools (scripts, editors).
4. Out-of-project guard fails across Windows drives
Severity: low-medium. Pollutes anatomy-index.json with files outside the
project.
src/hooks/post-write.js:48:
const relPath = normalizePath(path.relative(projectRoot, absolutePath));
if (relPath.startsWith("..")) { process.exit(0); }
On Windows, path.relative() between different drives cannot produce a
relative path and returns the target as an absolute path:
path.relative('D:/projects/app', 'C:/Users/<user>/notes.md')
// → 'C:\\Users\\me\\notes.md' .startsWith('..') → false
The guard passes and the out-of-tree file is indexed — exactly what the comment
above it says it prevents. Reproducible only when project and target are on
different drives, which is likely why it shipped.
Fix: if (relPath.startsWith("..") || path.isAbsolute(relPath)).
Suggested regression tests
- Install into a scratch project, assert every file imported by a hook exists
in .wolf/hooks/ — this catches defect 1 generically, not just this filename.
countSemanticEntries against a fixture using the documented HH:MM format
→ expect non-zero; mechanical-rows-only → expect zero.
stop.js after touching buglog.json → expect no reminder.
post-write.js with a file_path on a different drive letter → assert no
anatomy-index.json entry. (Windows-only; skip elsewhere.)
Notes
All four were verified fixed locally by patching the installed package and
running a real openwolf update, which then distributed the corrected hooks to
all 7 registered projects with user data (buglog.json, cerebrum.md,
memory.md) intact.
OpenWolf 2.0.1 — four hook defects (one silently disables write tracking)
Observed on v2.0.1 (latest published). Defect 1 is also present in v2.0.0 —
its
post-write.jscarries the same import whileinit.jsomits the file fromthe copy list — so the whole v2 line is affected, on every platform.
Defects 1-3 are platform-independent; defect 4 is Windows-only.
Environment: Windows 11, Node v22.17.0, Claude Code.
Line numbers refer to the published build under
dist/src/.1.
symbol-extractor.jsis never installed —post-write.jsdies on every writeSeverity: high. Silently disables write tracking,
memory.mdlogging andanatomy.mdupdates in every project, on every write, from install onward.src/hooks/post-write.js:6imports./symbol-extractor.js, but that filename isabsent from all three hook file lists:
src/cli/init.jshookFiles— installsrc/cli/update.jshookFiles— updatesrc/cli/status.jshookFiles— health checkThe package ships the file (
dist/hooks/anddist/src/hooks/); only the copylists omit it. Result:
Two things make this hard to notice:
post-write.js's owntry/catchblocks and beforemain().catch(() => process.exit(0)). The hookexits 1 and the agent harness surfaces nothing.
post-write.jsis the only hook importing it, so reads keep being trackedand only writes go quiet — which reads as "idle", not "broken".
Because it is also missing from
status.js,openwolf statusreports healthyhooks on a fully broken install (
✓ All 7 hook scripts present).Fix: add
"symbol-extractor.js"to all three lists. After the fixopenwolf statusreports 8 and detects the failure.2.
countSemanticEntriescan never match — reminder fires unconditionallySeverity: medium.
Stophook emitsACTION REQUIRED: N files were modified this session but no semantic summary was written to memory.mdon every turn,regardless of what the user writes.
src/hooks/shared.js:~620:But
memory.mdrows use| HH:MM |— the format mandated by the projecttemplate and by the reminder string in
stop.js:~211itself. Measured on onereal project: 543 rows in
HH:MMformat, 0 matchingtodayPrefix,countSemanticEntries()→0.The hook therefore demands a format its own checker rejects. Note the
mechanicalregex one line above (^\|\s*[\d:]+) does anticipateHH:MM, soonly the
todayPrefixfilter is inconsistent.Fix: scope to the newest
## Session: <today>heading and countnon-mechanical rows beneath it; fall back to date-prefixed rows when no heading
for today exists, so older history is not miscounted.
3. Buglog reminder checks a list the file can never appear in
Severity: medium.
ACTION REQUIRED: ... buglog.json was not updatedfireseven immediately after
buglog.jsonis updated.src/cli/../hooks/stop.js:~153:buglog.jsonlives under.wolf/, andpost-write.js:39-44returns early forevery
.wolf/path before the session-tracker step. It can never be presentin
files_written, sobuglogWrittenis alwaysfalse.Fix: compare
buglog.json's mtime against session start. This also catchesupdates made outside the Write/Edit tools (scripts, editors).
4. Out-of-project guard fails across Windows drives
Severity: low-medium. Pollutes
anatomy-index.jsonwith files outside theproject.
src/hooks/post-write.js:48:On Windows,
path.relative()between different drives cannot produce arelative path and returns the target as an absolute path:
The guard passes and the out-of-tree file is indexed — exactly what the comment
above it says it prevents. Reproducible only when project and target are on
different drives, which is likely why it shipped.
Fix:
if (relPath.startsWith("..") || path.isAbsolute(relPath)).Suggested regression tests
in
.wolf/hooks/— this catches defect 1 generically, not just this filename.countSemanticEntriesagainst a fixture using the documentedHH:MMformat→ expect non-zero; mechanical-rows-only → expect zero.
stop.jsafter touchingbuglog.json→ expect no reminder.post-write.jswith afile_pathon a different drive letter → assert noanatomy-index.jsonentry. (Windows-only; skip elsewhere.)Notes
All four were verified fixed locally by patching the installed package and
running a real
openwolf update, which then distributed the corrected hooks toall 7 registered projects with user data (
buglog.json,cerebrum.md,memory.md) intact.