openwolf-enhanced 1.26.0 → 1.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +175 -0
  2. package/dist/dashboard/assets/{AISuggestions-DZmzksSA.js → AISuggestions-DBUq3WQW.js} +1 -1
  3. package/dist/dashboard/assets/{ActivityLog-BJ0omuzu.js → ActivityLog-DzvER0xw.js} +1 -1
  4. package/dist/dashboard/assets/{ActivityTimeline-BWhxretI.js → ActivityTimeline-DVx1o9Of.js} +1 -1
  5. package/dist/dashboard/assets/{AnatomyBrowser-DNVp6-_r.js → AnatomyBrowser-CQGTp2MR.js} +1 -1
  6. package/dist/dashboard/assets/{BugLog-DMJTuU9p.js → BugLog-Ka23MuzX.js} +1 -1
  7. package/dist/dashboard/assets/{CerebrumViewer-BwcGr6pu.js → CerebrumViewer-2SO_QPQn.js} +1 -1
  8. package/dist/dashboard/assets/{CronStatus-Dwf_M4-S.js → CronStatus-BSJ7o-Xc.js} +1 -1
  9. package/dist/dashboard/assets/{DesignQC-DzHkh94I.js → DesignQC-D7Btjv4l.js} +1 -1
  10. package/dist/dashboard/assets/{LinkGraph-kqQD--Yj.js → LinkGraph-Cj0m-9HI.js} +1 -1
  11. package/dist/dashboard/assets/{MemoryViewer-BCn9Fr-w.js → MemoryViewer-DQ_OGTaW.js} +1 -1
  12. package/dist/dashboard/assets/{NativeMemory-DPMZaP5E.js → NativeMemory-BLa2fOaz.js} +1 -1
  13. package/dist/dashboard/assets/{ProjectOverview-PWENJiC4.js → ProjectOverview-DK4qaJsJ.js} +1 -1
  14. package/dist/dashboard/assets/{ProjectsAggregate-Baj44DVk.js → ProjectsAggregate-DW8TBuH2.js} +1 -1
  15. package/dist/dashboard/assets/{StatusBadge-Db61D51H.js → StatusBadge-Bclc5R-9.js} +1 -1
  16. package/dist/dashboard/assets/{TokenUsage-UefDh9w4.js → TokenUsage-BwhsNFH4.js} +1 -1
  17. package/dist/dashboard/assets/index-BNi8lsJE.css +2 -0
  18. package/dist/dashboard/assets/{index-e2PfOI0b.js → index-DsimHkSD.js} +5 -5
  19. package/dist/dashboard/index.html +2 -2
  20. package/dist/hooks/post-bash.js +6 -1
  21. package/dist/hooks/post-read.js +20 -20
  22. package/dist/hooks/post-write.js +22 -18
  23. package/dist/hooks/pre-read.js +39 -30
  24. package/dist/hooks/session-start.js +5 -3
  25. package/dist/hooks/shared.js +83 -2
  26. package/dist/hooks/stop.js +25 -5
  27. package/dist/src/cli/daemon-cmd.js +9 -7
  28. package/dist/src/cli/daemon-cmd.js.map +1 -1
  29. package/dist/src/cli/doctor-cmd.js +2 -1
  30. package/dist/src/cli/doctor-cmd.js.map +1 -1
  31. package/dist/src/cli/export-cmd.js +8 -0
  32. package/dist/src/cli/export-cmd.js.map +1 -1
  33. package/dist/src/cli/init.js +25 -6
  34. package/dist/src/cli/init.js.map +1 -1
  35. package/dist/src/cli/update.js +10 -2
  36. package/dist/src/cli/update.js.map +1 -1
  37. package/dist/src/daemon/cron-engine.js +47 -3
  38. package/dist/src/daemon/cron-engine.js.map +1 -1
  39. package/dist/src/daemon/llm-provider.js +9 -6
  40. package/dist/src/daemon/llm-provider.js.map +1 -1
  41. package/dist/src/daemon/wolf-daemon.js +52 -12
  42. package/dist/src/daemon/wolf-daemon.js.map +1 -1
  43. package/dist/src/designqc/designqc-capture.js +116 -6
  44. package/dist/src/designqc/designqc-capture.js.map +1 -1
  45. package/dist/src/designqc/designqc-engine.js +9 -3
  46. package/dist/src/designqc/designqc-engine.js.map +1 -1
  47. package/dist/src/hooks/post-bash.js +6 -1
  48. package/dist/src/hooks/post-bash.js.map +1 -1
  49. package/dist/src/hooks/post-read.js +20 -20
  50. package/dist/src/hooks/post-read.js.map +1 -1
  51. package/dist/src/hooks/post-write.js +22 -18
  52. package/dist/src/hooks/post-write.js.map +1 -1
  53. package/dist/src/hooks/pre-read.js +39 -30
  54. package/dist/src/hooks/pre-read.js.map +1 -1
  55. package/dist/src/hooks/session-start.js +5 -3
  56. package/dist/src/hooks/session-start.js.map +1 -1
  57. package/dist/src/hooks/shared.js +83 -2
  58. package/dist/src/hooks/shared.js.map +1 -1
  59. package/dist/src/hooks/stop.js +25 -5
  60. package/dist/src/hooks/stop.js.map +1 -1
  61. package/dist/src/utils/embeddings.js +9 -1
  62. package/dist/src/utils/embeddings.js.map +1 -1
  63. package/dist/src/utils/fs-safe.js +15 -1
  64. package/dist/src/utils/fs-safe.js.map +1 -1
  65. package/dist/src/utils/logger.js +21 -6
  66. package/dist/src/utils/logger.js.map +1 -1
  67. package/dist/src/utils/maintenance.js +44 -1
  68. package/dist/src/utils/maintenance.js.map +1 -1
  69. package/dist/src/utils/platform.js +39 -0
  70. package/dist/src/utils/platform.js.map +1 -1
  71. package/package.json +1 -1
  72. package/src/templates/config.json +2 -1
  73. package/dist/dashboard/assets/index-CVfvTpSA.css +0 -2
@@ -7,8 +7,8 @@
7
7
  <link rel="preconnect" href="https://fonts.googleapis.com" />
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
9
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
10
- <script type="module" crossorigin src="./assets/index-e2PfOI0b.js"></script>
11
- <link rel="stylesheet" crossorigin href="./assets/index-CVfvTpSA.css">
10
+ <script type="module" crossorigin src="./assets/index-DsimHkSD.js"></script>
11
+ <link rel="stylesheet" crossorigin href="./assets/index-BNi8lsJE.css">
12
12
  </head>
13
13
  <body>
14
14
  <div id="root"></div>
@@ -66,7 +66,12 @@ async function main() {
66
66
  // COMMAND position of each shell segment, not the whole string — the old `\bopenwolf\b` skipped
67
67
  // every command that merely mentioned an openwolf PATH, which made the write counter blind for
68
68
  // exactly the sessions that work on an openwolf checkout.
69
- const invokesOpenwolf = cmd.split(/&&|\|\||[;|]/).some(segmentInvokesOpenwolf);
69
+ // Newlines separate commands exactly like `;` does, and they were missing from this split: a
70
+ // two-line Bash block whose second line ran `openwolf push` was tested as ONE segment starting
71
+ // with the first line's command, so the filter saw no openwolf invocation and captured the whole
72
+ // thing. Multi-line blocks are the normal shape of an agent's shell call, so this was the common
73
+ // case, not the edge one.
74
+ const invokesOpenwolf = cmd.split(/&&|\|\||[;|\n\r]/).some(segmentInvokesOpenwolf);
70
75
  if (invokesOpenwolf) {
71
76
  process.exit(0);
72
77
  return;
@@ -1,5 +1,5 @@
1
1
  import * as path from "node:path";
2
- import { getWolfDir, ensureWolfDir, readJSON, writeJSON, readMarkdown, parseAnatomy, estimateFileTokens, getTokenRatios, readStdin, normalizePath, loadIgnore, isSecretFile } from "./shared.js";
2
+ import { getWolfDir, ensureWolfDir, updateSession, readMarkdown, parseAnatomy, estimateFileTokens, getTokenRatios, readStdin, normalizePath, loadIgnore, isSecretFile, matchesAnatomyEntry } from "./shared.js";
3
3
  async function main() {
4
4
  ensureWolfDir();
5
5
  const wolfDir = getWolfDir();
@@ -57,7 +57,7 @@ async function main() {
57
57
  for (const [sectionKey, entries] of sections) {
58
58
  for (const entry of entries) {
59
59
  const entryRelPath = normalizePath(path.join(sectionKey, entry.file));
60
- if (normalizedFile.endsWith(entryRelPath) || normalizedFile.endsWith("/" + entryRelPath)) {
60
+ if (matchesAnatomyEntry(normalizedFile, entryRelPath)) {
61
61
  tokens = entry.tokens;
62
62
  break;
63
63
  }
@@ -66,24 +66,24 @@ async function main() {
66
66
  break;
67
67
  }
68
68
  }
69
- const session = readJSON(sessionFile, { files_read: {} });
70
- if (session.files_read[normalizedFile]) {
71
- // Never let a re-read shrink the estimate to zero. A repeat read often arrives with an
72
- // empty tool_output.content, and if the file has no anatomy entry the fallback above
73
- // cannot recover a number — overwriting unconditionally would wipe the good first-read
74
- // estimate. That deflates inputTokens in stop.ts and, because savedFromRepeats multiplies
75
- // by (count - 1), silently zeroes the repeat-savings metric too.
76
- const prev = session.files_read[normalizedFile].tokens ?? 0;
77
- session.files_read[normalizedFile].tokens = Math.max(prev, tokens);
78
- }
79
- else {
80
- session.files_read[normalizedFile] = {
81
- count: 1,
82
- tokens,
83
- first_read: new Date().toISOString(),
84
- };
85
- }
86
- writeJSON(sessionFile, session);
69
+ updateSession(sessionFile, { files_read: {} }, (session) => {
70
+ if (session.files_read[normalizedFile]) {
71
+ // Never let a re-read shrink the estimate to zero. A repeat read often arrives with an
72
+ // empty tool_output.content, and if the file has no anatomy entry the fallback above
73
+ // cannot recover a number — overwriting unconditionally would wipe the good first-read
74
+ // estimate. That deflates inputTokens in stop.ts and, because savedFromRepeats multiplies
75
+ // by (count - 1), silently zeroes the repeat-savings metric too.
76
+ const prev = session.files_read[normalizedFile].tokens ?? 0;
77
+ session.files_read[normalizedFile].tokens = Math.max(prev, tokens);
78
+ }
79
+ else {
80
+ session.files_read[normalizedFile] = {
81
+ count: 1,
82
+ tokens,
83
+ first_read: new Date().toISOString(),
84
+ };
85
+ }
86
+ });
87
87
  process.exit(0);
88
88
  }
89
89
  main().catch(() => process.exit(0));
@@ -1,6 +1,6 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
- import { getWolfDir, ensureWolfDir, readJSON, writeJSON, writeAtomic, parseAnatomy, serializeAnatomy, extractDescription, estimateFileTokens, getTokenRatios, appendMarkdown, timeShort, readStdin, normalizePath, getRetention, loadIgnore, readBugLog, isSecretFile } from "./shared.js";
3
+ import { getWolfDir, ensureWolfDir, writeJSON, writeAtomic, parseAnatomy, serializeAnatomy, extractDescription, estimateFileTokens, getTokenRatios, appendMarkdown, timeShort, readStdin, normalizePath, getRetention, loadIgnore, readBugLog, isSecretFile, updateSession, isOutsideProject } from "./shared.js";
4
4
  async function main() {
5
5
  ensureWolfDir();
6
6
  const wolfDir = getWolfDir();
@@ -37,10 +37,10 @@ async function main() {
37
37
  // nothing happened, and the STATUS.md reminder never fires. That is exactly how a handoff doc goes
38
38
  // stale for eleven slices without anyone noticing. The counter is a number only: no path, no name,
39
39
  // so #56 still holds.
40
- if (relPath === "" || relPath.startsWith("..")) {
41
- const session = readJSON(sessionFile, { files_written: [], edit_counts: {} });
42
- session.external_writes = (session.external_writes ?? 0) + 1;
43
- writeJSON(sessionFile, session);
40
+ if (isOutsideProject(relPath)) {
41
+ updateSession(sessionFile, { files_written: [], edit_counts: {} }, (session) => {
42
+ session.external_writes = (session.external_writes ?? 0) + 1;
43
+ });
44
44
  process.exit(0);
45
45
  return;
46
46
  }
@@ -133,24 +133,28 @@ async function main() {
133
133
  catch { }
134
134
  // 3. Record in session tracker + track edit counts
135
135
  try {
136
- const session = readJSON(sessionFile, { files_written: [], edit_counts: {} });
137
- if (!session.edit_counts)
138
- session.edit_counts = {};
139
136
  const normalizedFile = normalizePath(filePath);
140
137
  const action = toolName === "Write" ? "create" : "edit";
141
138
  const fileContent = input.tool_input?.content ?? "";
142
139
  const tokens = estimateFileTokens(fileContent || writtenText, absolutePath, getTokenRatios(wolfDir));
143
- session.files_written.push({
144
- file: normalizedFile,
145
- action,
146
- tokens,
147
- at: new Date().toISOString(),
148
- });
149
140
  const editKey = normalizePath(path.relative(projectRoot, absolutePath));
150
- session.edit_counts[editKey] = (session.edit_counts[editKey] || 0) + 1;
151
- writeJSON(sessionFile, session);
152
- if (session.edit_counts[editKey] >= 3) {
153
- process.stderr.write(`⚠️ OpenWolf: ${baseName} has been edited ${session.edit_counts[editKey]} times this session. If you're fixing a bug, remember to log it to .wolf/buglog.json.\n`);
141
+ let edits = 0;
142
+ updateSession(sessionFile, { files_written: [], edit_counts: {} }, (session) => {
143
+ if (!session.files_written)
144
+ session.files_written = [];
145
+ if (!session.edit_counts)
146
+ session.edit_counts = {};
147
+ session.files_written.push({
148
+ file: normalizedFile,
149
+ action,
150
+ tokens,
151
+ at: new Date().toISOString(),
152
+ });
153
+ session.edit_counts[editKey] = (session.edit_counts[editKey] || 0) + 1;
154
+ edits = session.edit_counts[editKey];
155
+ });
156
+ if (edits >= 3) {
157
+ process.stderr.write(`⚠️ OpenWolf: ${baseName} has been edited ${edits} times this session. If you're fixing a bug, remember to log it to .wolf/buglog.json.\n`);
154
158
  }
155
159
  }
156
160
  catch { }
@@ -1,6 +1,9 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
- import { getWolfDir, ensureWolfDir, readJSON, writeJSON, readMarkdown, parseAnatomy, readStdin, normalizePath, loadIgnore, isSecretFile } from "./shared.js";
3
+ import { getWolfDir, ensureWolfDir, readJSON, updateSession, readMarkdown, parseAnatomy, readStdin, normalizePath, loadIgnore, isSecretFile, matchesAnatomyEntry } from "./shared.js";
4
+ const SESSION_FALLBACK = {
5
+ session_id: "", files_read: {}, anatomy_hits: 0, anatomy_misses: 0, repeated_reads_warned: 0,
6
+ };
4
7
  async function main() {
5
8
  ensureWolfDir();
6
9
  const wolfDir = getWolfDir();
@@ -56,27 +59,34 @@ async function main() {
56
59
  process.exit(0);
57
60
  return;
58
61
  }
59
- const session = readJSON(sessionFile, {
60
- session_id: "", files_read: {}, anatomy_hits: 0, anatomy_misses: 0,
61
- repeated_reads_warned: 0,
62
- });
62
+ // Snapshot read, used only to DECIDE what to print. Every mutation below re-reads under the lock
63
+ // and applies a delta, so a concurrent hook's update is never overwritten with this snapshot.
64
+ const session = readJSON(sessionFile, SESSION_FALLBACK);
63
65
  // Check if already read this session
64
66
  if (session.files_read[normalizedFile]) {
65
67
  const prev = session.files_read[normalizedFile];
66
68
  // If the file changed since we last read it (e.g. it was edited during the session),
67
69
  // a re-read is legitimate — refresh state and don't warn about a repeated read (upstream #41).
68
70
  if (fileMtime !== undefined && prev.mtime !== undefined && fileMtime !== prev.mtime) {
69
- prev.count++;
70
- prev.mtime = fileMtime;
71
- writeJSON(sessionFile, session);
71
+ updateSession(sessionFile, SESSION_FALLBACK, (s) => {
72
+ const e = s.files_read[normalizedFile];
73
+ if (e) {
74
+ e.count++;
75
+ e.mtime = fileMtime;
76
+ }
77
+ });
72
78
  process.exit(0);
73
79
  return;
74
80
  }
75
81
  process.stderr.write(`⚡ OpenWolf: ${path.basename(normalizedFile)} was already read this session (~${prev.tokens} tokens). Consider using your existing knowledge of this file.\n`);
76
- prev.count++;
77
- prev.mtime = fileMtime ?? prev.mtime;
78
- session.repeated_reads_warned++;
79
- writeJSON(sessionFile, session);
82
+ updateSession(sessionFile, SESSION_FALLBACK, (s) => {
83
+ const e = s.files_read[normalizedFile];
84
+ if (e) {
85
+ e.count++;
86
+ e.mtime = fileMtime ?? e.mtime;
87
+ }
88
+ s.repeated_reads_warned++;
89
+ });
80
90
  process.exit(0);
81
91
  return;
82
92
  }
@@ -90,7 +100,7 @@ async function main() {
90
100
  for (const entry of entries) {
91
101
  // Build the full relative path from the section key + filename for accurate matching
92
102
  const entryRelPath = normalizePath(path.join(sectionKey, entry.file));
93
- if (normalizedFile.endsWith(entryRelPath) || normalizedFile.endsWith("/" + entryRelPath)) {
103
+ if (matchesAnatomyEntry(normalizedFile, entryRelPath)) {
94
104
  process.stderr.write(`📋 OpenWolf anatomy: ${entry.file} — ${entry.description} (~${entry.tokens} tok)\n`);
95
105
  // If we indexed this big file's symbols, offer line ranges so the agent can read one
96
106
  // function with offset/limit instead of the whole file.
@@ -107,23 +117,22 @@ async function main() {
107
117
  if (found)
108
118
  break;
109
119
  }
110
- if (found) {
111
- session.anatomy_hits++;
112
- }
113
- else {
114
- session.anatomy_misses++;
115
- }
116
- // Record initial read entry (tokens will be updated in post-read)
117
- session.files_read[normalizedFile] = {
118
- count: 1,
119
- tokens: 0,
120
- first_read: new Date().toISOString(),
121
- // Whether anatomy.md already described this file. The ledger used to hardcode this as
122
- // false, which made the waste detector's "anatomy would have sufficed" pattern unreachable.
123
- anatomy_had_description: found,
124
- mtime: fileMtime,
125
- };
126
- writeJSON(sessionFile, session);
120
+ updateSession(sessionFile, SESSION_FALLBACK, (s) => {
121
+ if (found)
122
+ s.anatomy_hits++;
123
+ else
124
+ s.anatomy_misses++;
125
+ // Record initial read entry (tokens will be updated in post-read)
126
+ s.files_read[normalizedFile] = {
127
+ count: 1,
128
+ tokens: 0,
129
+ first_read: new Date().toISOString(),
130
+ // Whether anatomy.md already described this file. The ledger used to hardcode this as
131
+ // false, which made the waste detector's "anatomy would have sufficed" pattern unreachable.
132
+ anatomy_had_description: found,
133
+ mtime: fileMtime,
134
+ };
135
+ });
127
136
  process.exit(0);
128
137
  }
129
138
  main().catch(() => process.exit(0));
@@ -35,8 +35,10 @@ async function main() {
35
35
  catch { }
36
36
  const continuing = (source === "compact" || source === "resume") && fs.existsSync(sessionFile);
37
37
  if (!continuing) {
38
- // Create fresh session state
39
- writeJSON(sessionFile, {
38
+ // Create fresh session state. Under the lock like every other writer of this file: the reset is
39
+ // a whole-file replacement, so an unlocked write here could land in the middle of another
40
+ // hook's read-modify-write and hand it a half-written file to parse.
41
+ withLock(sessionFile, () => writeJSON(sessionFile, {
40
42
  session_id: sessionId,
41
43
  started: timestamp(),
42
44
  files_read: {},
@@ -47,7 +49,7 @@ async function main() {
47
49
  repeated_reads_warned: 0,
48
50
  cerebrum_warnings: 0,
49
51
  stop_count: 0,
50
- });
52
+ }));
51
53
  // Append session header to memory.md
52
54
  const memoryPath = path.join(wolfDir, "memory.md");
53
55
  const header = `\n## Session: ${now.toISOString().slice(0, 10)} ${timeShort()}\n\n${SESSION_SUMMARY_SCAFFOLD}\n\n| Time | Action | File(s) | Outcome | ~Tokens |\n|------|--------|---------|---------|--------|\n`;
@@ -126,6 +126,26 @@ export function withLock(targetPath, fn) {
126
126
  }
127
127
  }
128
128
  }
129
+ /**
130
+ * Read-modify-write `_session.json` under the lock, in one place.
131
+ *
132
+ * Every hook in a session mutates this one file, and until now only two of the seven writers took
133
+ * the lock at all: the rest did `readJSON` … `writeJSON` around unrelated work, so a PostToolUse
134
+ * hook finishing while PreToolUse was mid-cycle silently dropped one of the two updates. Reads and
135
+ * writes get counted for the token ledger, so a lost update is a wrong number in a report nobody
136
+ * can audit afterwards.
137
+ *
138
+ * The mutator receives the state as it is ON DISK at the moment the lock is held — not a snapshot
139
+ * taken earlier — and must apply a DELTA (increment, add a key), never assign a whole object it
140
+ * captured before. That is what makes the update safe against a concurrent writer.
141
+ */
142
+ export function updateSession(sessionFile, fallback, mutate) {
143
+ withLock(sessionFile, () => {
144
+ const session = readJSON(sessionFile, fallback);
145
+ mutate(session);
146
+ writeJSON(sessionFile, session);
147
+ });
148
+ }
129
149
  // A missing file is normal (first run) and silently yields the fallback. An EXISTING file that
130
150
  // fails to parse is a different situation: whatever it held is about to be treated as empty, and
131
151
  // a read-modify-write caller would then overwrite it with defaults. That must at least be visible.
@@ -201,10 +221,24 @@ export function readJSON(filePath, fallback) {
201
221
  return JSON.parse(raw);
202
222
  }
203
223
  catch (e) {
204
- process.stderr.write(`[openwolf] ${path.basename(filePath)} exists but is not valid JSON — using defaults (${e.message})\n`);
224
+ // The caller is about to treat this file as empty and, in a read-modify-write, overwrite it
225
+ // with defaults — so a corrupt token-ledger.json meant months of usage history vanished on the
226
+ // next Stop hook, with one line on stderr as the only trace. Move it aside first. Recovery is
227
+ // then a possibility rather than a hope, and because the path no longer exists, the next read
228
+ // takes the ordinary "missing file" branch instead of warning forever.
229
+ quarantineCorrupt(filePath);
230
+ process.stderr.write(`[openwolf] ${path.basename(filePath)} was not valid JSON — moved aside, using defaults (${e.message})\n`);
205
231
  return fallback;
206
232
  }
207
233
  }
234
+ /** Rename a corrupt file to <name>.corrupt-<stamp>. Best-effort: never throws, never blocks a read. */
235
+ function quarantineCorrupt(filePath) {
236
+ try {
237
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
238
+ fs.renameSync(filePath, `${filePath}.corrupt-${stamp}`);
239
+ }
240
+ catch { /* unwritable directory, race with another process — defaults still apply */ }
241
+ }
208
242
  // Duplicated from utils/fs-safe.ts (separate build roots). Never throws — a hook must not kill a
209
243
  // session over a failed journal write — but a total failure is reported on stderr instead of
210
244
  // vanishing: a silently dropped write once hid a completely broken persistence path (bug-183).
@@ -298,12 +332,17 @@ export function makeIgnoreMatcher(patterns) {
298
332
  if (pat.startsWith("*.") && norm.endsWith(pat.slice(1)))
299
333
  return true;
300
334
  }
301
- if (pat.includes("*")) {
335
+ // `?` is a gitignore wildcard for exactly one character, and it also has to be handled BEFORE
336
+ // this becomes a regex — it used to be neither escaped nor translated, so it survived into the
337
+ // pattern as a regex quantifier and made the preceding character OPTIONAL. `build?/*.js` then
338
+ // matched `buil/x.js` and missed `build2/x.js`: the rule silently covered the wrong files.
339
+ if (pat.includes("*") || pat.includes("?")) {
302
340
  const re = new RegExp("^" +
303
341
  pat
304
342
  .replace(/[.+^${}()|[\]\\]/g, "\\$&")
305
343
  .replace(/\*\*/g, "\u0000")
306
344
  .replace(/\*/g, "[^/]*")
345
+ .replace(/\?/g, "[^/]")
307
346
  .replace(/\u0000/g, ".*") +
308
347
  "$");
309
348
  if (re.test(norm) || (!anchored && re.test(base)))
@@ -1054,6 +1093,48 @@ export function readStdin() {
1054
1093
  export function normalizePath(p) {
1055
1094
  return p.replace(/\\/g, "/");
1056
1095
  }
1096
+ /**
1097
+ * Does an absolute (forward-slashed) file path correspond to this anatomy.md entry?
1098
+ *
1099
+ * anatomy entries are project-relative ("src/api/client.ts"); the hooks see an absolute path. The
1100
+ * old test was `abs.endsWith(rel) || abs.endsWith("/" + rel)`, and the first half of that had no
1101
+ * path-segment boundary: `/home/me/vendor/src/api/client.ts` and `/tmp/other-src/api/client.ts`
1102
+ * both "matched" an entry for `src/api/client.ts`, so the hook printed another file's description
1103
+ * and token estimate and booked an anatomy HIT for a file anatomy.md had never seen. The second
1104
+ * half of the old expression was already correct, so this keeps that and drops the loose one — an
1105
+ * exact equality covers the case where the path is already relative.
1106
+ */
1107
+ export function matchesAnatomyEntry(filePath, entryRelPath) {
1108
+ return filePath === entryRelPath || filePath.endsWith("/" + entryRelPath);
1109
+ }
1110
+ /**
1111
+ * Does this project-relative path point OUTSIDE the project root?
1112
+ *
1113
+ * Input is the output of `normalizePath(path.relative(root, file))`. The obvious test —
1114
+ * "does it start with `..`" — is complete on POSIX and wrong on Windows, because `path.relative`
1115
+ * cannot express a route between two drives and gives up by returning the target ABSOLUTE:
1116
+ *
1117
+ * path.win32.relative("C:\\proj", "F:\\secrets\\x") === "F:\\secrets\\x"
1118
+ *
1119
+ * That has no leading `..`, so the guard passed it and the full foreign path was written into
1120
+ * anatomy.md and memory.md — precisely the leak (upstream #56) the guard exists to prevent, on the
1121
+ * one platform nobody tested it on. An absolute result means "no relative route exists", i.e. the
1122
+ * strongest possible outside-the-root signal.
1123
+ *
1124
+ * The `..` test is also anchored to a whole segment now: a file genuinely named `..config` in the
1125
+ * root is inside the project, and used to be counted as external.
1126
+ */
1127
+ export function isOutsideProject(relPath) {
1128
+ if (relPath === "")
1129
+ return true; // the path IS the root, not a file in it
1130
+ if (relPath === ".." || relPath.startsWith("../"))
1131
+ return true;
1132
+ if (path.isAbsolute(relPath))
1133
+ return true; // win32 cross-drive ("F:/secrets/x")
1134
+ if (/^[a-zA-Z]:/.test(relPath))
1135
+ return true; // drive-relative ("F:x"), also not ours
1136
+ return false;
1137
+ }
1057
1138
  // Count non-mechanical (semantic) entries written to memory.md today. Mechanical rows
1058
1139
  // (auto file-op / session-end lines) don't count. Used by the stop hook to detect whether
1059
1140
  // a meaningful session summary was written. (upstream #55)
@@ -1,6 +1,6 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
- import { getWolfDir, ensureWolfDir, readJSON, writeJSON, appendMarkdown, timeShort, getRetention, compactMemoryIfLarge, countSemanticEntries, withLock, readStdin, readTranscriptUsage, detectAgent, bookInjection } from "./shared.js";
3
+ import { getWolfDir, ensureWolfDir, readJSON, writeJSON, appendMarkdown, timeShort, getRetention, compactMemoryIfLarge, countSemanticEntries, withLock, updateSession, readStdin, readTranscriptUsage, detectAgent, bookInjection } from "./shared.js";
4
4
  import { estimateTokens, getTokenRatios } from "./token-estimator.js";
5
5
  const NOTHING_BOOKED = {
6
6
  reads: 0, writes: 0, tokens: 0, anatomy_hits: 0, anatomy_misses: 0, repeated_reads_blocked: 0,
@@ -49,7 +49,11 @@ async function main() {
49
49
  const unnamedWrites = externalWrites + bashWrites;
50
50
  const totalWrites = writeCount + unnamedWrites;
51
51
  if (readCount === 0 && totalWrites === 0) {
52
- writeJSON(sessionFile, session);
52
+ // Only stop_count moved; apply it as a delta so an idle turn cannot overwrite a sibling
53
+ // hook's concurrent update with this hook's stale snapshot.
54
+ updateSession(sessionFile, session, (s) => {
55
+ s.stop_count = Math.max(s.stop_count ?? 0, session.stop_count);
56
+ });
53
57
  process.exit(0);
54
58
  return;
55
59
  }
@@ -180,8 +184,15 @@ async function main() {
180
184
  lt.real_cache_creation_tokens = (lt.real_cache_creation_tokens ?? 0) + delta(realUsage.cache_creation_input_tokens, booked.real_cache_creation);
181
185
  lt.real_api_calls = (lt.real_api_calls ?? 0) + delta(realUsage.api_calls, booked.real_api_calls);
182
186
  }
183
- // Mark what is now booked. Set inside the lock, right after the numbers went in, so a crash
184
- // between the two writes cannot leave the ledger credited and the session unmarked.
187
+ // Mark what is now booked.
188
+ //
189
+ // [fix] Setting this field inside the lock was never the point — PERSISTING it was. The write to
190
+ // _session.json used to sit ~30 lines further down, past two memory.md appends and a memory
191
+ // compaction, outside this lock. Anything that ended the process in that window (a hook timeout,
192
+ // the user quitting, a full disk during compactMemoryIfLarge) left the ledger credited and the
193
+ // session file still carrying the OLD booked values, so the next Stop re-booked every delta on
194
+ // top. The comment claimed that could not happen. It is now written under the same lock, one
195
+ // statement after the ledger, which is what the comment always described.
185
196
  session.booked = {
186
197
  reads: Math.max(readCount, booked.reads),
187
198
  writes: Math.max(totalWritesNow, booked.writes),
@@ -197,6 +208,16 @@ async function main() {
197
208
  real_api_calls: Math.max(realUsage?.api_calls ?? 0, booked.real_api_calls),
198
209
  };
199
210
  writeJSON(ledgerPath, ledger);
211
+ // Persist the session's own bookkeeping here, still holding the ledger lock. The deltas are
212
+ // re-applied to whatever is on disk right now, so a PostToolUse hook that wrote between this
213
+ // hook's initial read and this line does not lose its update.
214
+ const bookedNow = session.booked;
215
+ const remindersNow = session.reminders_shown;
216
+ updateSession(sessionFile, session, (s) => {
217
+ s.booked = bookedNow;
218
+ s.reminders_shown = remindersNow;
219
+ s.stop_count = Math.max(s.stop_count ?? 0, session.stop_count);
220
+ });
200
221
  });
201
222
  // Write a session summary line to memory.md if there was meaningful activity
202
223
  const memoryPath = path.join(wolfDir, "memory.md");
@@ -227,7 +248,6 @@ async function main() {
227
248
  compactMemoryIfLarge(wolfDir, ret.memory_max_bytes);
228
249
  }
229
250
  catch { }
230
- writeJSON(sessionFile, session);
231
251
  // Surface reminders into Claude's next context window (Stop hooks can inject via stdout JSON).
232
252
  if (reminders.length > 0) {
233
253
  const additionalContext = `⚠️ OpenWolf end-of-turn reminders:\n${reminders.map((r) => `• ${r}`).join("\n")}`;
@@ -6,7 +6,7 @@ import { findProjectRoot } from "../scanner/project-root.js";
6
6
  import { readJSON, writeJSON, withLock } from "../utils/fs-safe.js";
7
7
  import { readDashboardToken } from "../utils/dashboard-auth.js";
8
8
  import { isPortFree } from "../utils/ports.js";
9
- import { isWindows } from "../utils/platform.js";
9
+ import { isWindows, execShim } from "../utils/platform.js";
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const __dirname = path.dirname(__filename);
12
12
  function getDashboardPort() {
@@ -15,7 +15,9 @@ function getDashboardPort() {
15
15
  const config = readJSON(path.join(wolfDir, "config.json"), { openwolf: { dashboard: { port: 18791 } } });
16
16
  return config.openwolf.dashboard.port;
17
17
  }
18
- // On Windows the pm2 shim is pm2.cmd; execFileSync needs the exact name (no shell).
18
+ // On Windows the pm2 shim is pm2.cmd. Node cannot spawn a .cmd without a shell (CVE-2024-27980
19
+ // hardening), so every call goes through execShim(), which routes it via cmd.exe with the
20
+ // arguments still quoted individually rather than joined into a parseable string.
19
21
  const PM2 = isWindows() ? "pm2.cmd" : "pm2";
20
22
  function getPm2Name() {
21
23
  const projectRoot = findProjectRoot();
@@ -157,11 +159,11 @@ export function daemonStart() {
157
159
  // Resolve daemon script relative to openwolf's install dir, not the target project
158
160
  const daemonScript = path.resolve(__dirname, "..", "daemon", "wolf-daemon.js");
159
161
  try {
160
- execFileSync(PM2, ["start", daemonScript, "--name", name, "--cwd", projectRoot, "--", "--env", `OPENWOLF_PROJECT_ROOT=${projectRoot}`], {
162
+ execShim(PM2, ["start", daemonScript, "--name", name, "--cwd", projectRoot, "--", "--env", `OPENWOLF_PROJECT_ROOT=${projectRoot}`], {
161
163
  stdio: "inherit",
162
164
  env: { ...process.env, OPENWOLF_PROJECT_ROOT: projectRoot },
163
165
  });
164
- execFileSync(PM2, ["save"], { stdio: "ignore" });
166
+ execShim(PM2, ["save"], { stdio: "ignore" });
165
167
  console.log(`\n ✓ Daemon started: ${name}`);
166
168
  if (isWindows()) {
167
169
  console.log(" Tip: Run 'pm2-windows-startup' for boot persistence.");
@@ -185,7 +187,7 @@ export async function daemonStop() {
185
187
  if (hasPm2()) {
186
188
  const name = getPm2Name();
187
189
  try {
188
- execFileSync(PM2, ["stop", name], { stdio: "ignore" });
190
+ execShim(PM2, ["stop", name], { stdio: "ignore" });
189
191
  markDaemonStopped(wolfDir);
190
192
  console.log(` ✓ Daemon stopped (PM2): ${name}`);
191
193
  return;
@@ -227,7 +229,7 @@ export async function daemonRestart() {
227
229
  if (hasPm2()) {
228
230
  const name = getPm2Name();
229
231
  try {
230
- execFileSync(PM2, ["restart", name], { stdio: "ignore" });
232
+ execShim(PM2, ["restart", name], { stdio: "ignore" });
231
233
  console.log(` ✓ Daemon restarted (PM2): ${name}`);
232
234
  return;
233
235
  }
@@ -264,7 +266,7 @@ export function daemonLogs() {
264
266
  }
265
267
  const name = getPm2Name();
266
268
  try {
267
- execFileSync(PM2, ["logs", name, "--lines", "50", "--nostream"], { stdio: "inherit" });
269
+ execShim(PM2, ["logs", name, "--lines", "50", "--nostream"], { stdio: "inherit" });
268
270
  }
269
271
  catch {
270
272
  console.error("Failed to get daemon logs.");
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-cmd.js","sourceRoot":"","sources":["../../../src/cli/daemon-cmd.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemon-cmd.js","sourceRoot":"","sources":["../../../src/cli/daemon-cmd.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ import { isWindows } from "../utils/platform.js";
7
7
  import { dashboardTokenPath } from "../utils/dashboard-auth.js";
8
8
  import { remoteTokenPath } from "../utils/remote.js";
9
9
  import { readRegistry } from "./registry.js";
10
- import { getRetention, footprint, humanBytes, compactLedger, consolidateMemory, dedupeAndCapBuglog, pruneBackups, cleanTmp, rotateDaemonLog, dirSize, suggestIgnores, nativeMemoryHealth, findDuplicateEntries, repairNativeMemoryIndex, } from "../utils/maintenance.js";
10
+ import { getRetention, footprint, humanBytes, compactLedger, consolidateMemory, dedupeAndCapBuglog, pruneBackups, pruneProposals, cleanTmp, rotateDaemonLog, dirSize, suggestIgnores, nativeMemoryHealth, findDuplicateEntries, repairNativeMemoryIndex, } from "../utils/maintenance.js";
11
11
  import { nativeMemoryDir } from "../hooks/shared.js";
12
12
  // Does this file carry permissions of its own, or does it just inherit the folder's?
13
13
  //
@@ -226,6 +226,7 @@ export async function doctorCommand(opts) {
226
226
  consolidateMemory(wolfDir, ret.memory_consolidate_after_days),
227
227
  dedupeAndCapBuglog(wolfDir, ret.buglog_max_entries),
228
228
  pruneBackups(wolfDir, ret.backups_keep),
229
+ pruneProposals(wolfDir, ret.proposals_keep),
229
230
  rotateDaemonLog(wolfDir, ret.daemon_log_max_bytes),
230
231
  cleanTmp(wolfDir),
231
232
  ];