@monoes/monomindcli 2.16.12 → 2.16.13

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 (217) hide show
  1. package/.claude/agents/core/coder.md +1 -1
  2. package/.claude/agents/engineering/engineering-devops-automator.md +1 -1
  3. package/.claude/agents/github/repo-architect.md +1 -1
  4. package/.claude/agents/testing/production-validator.md +1 -1
  5. package/.claude/agents/testing/testing-tool-evaluator.md +1 -1
  6. package/.claude/commands/github/pr-manager.md +1 -1
  7. package/.claude/helpers/pick-rank.cjs +34 -4
  8. package/.claude/skills/monolean-audit/SKILL.md +1 -1
  9. package/dist/src/commands/cleanup-data.d.ts +30 -0
  10. package/dist/src/commands/cleanup-data.d.ts.map +1 -0
  11. package/dist/src/commands/cleanup-data.js +138 -0
  12. package/dist/src/commands/cleanup-data.js.map +1 -0
  13. package/dist/src/commands/cleanup-scratch.d.ts +43 -0
  14. package/dist/src/commands/cleanup-scratch.d.ts.map +1 -0
  15. package/dist/src/commands/cleanup-scratch.js +125 -0
  16. package/dist/src/commands/cleanup-scratch.js.map +1 -0
  17. package/dist/src/commands/cleanup.d.ts +2 -39
  18. package/dist/src/commands/cleanup.d.ts.map +1 -1
  19. package/dist/src/commands/cleanup.js +5 -247
  20. package/dist/src/commands/cleanup.js.map +1 -1
  21. package/dist/src/commands/doctor-gitignore-checks.d.ts +10 -0
  22. package/dist/src/commands/doctor-gitignore-checks.d.ts.map +1 -0
  23. package/dist/src/commands/doctor-gitignore-checks.js +141 -0
  24. package/dist/src/commands/doctor-gitignore-checks.js.map +1 -0
  25. package/dist/src/commands/doctor-helpers-checks.d.ts +10 -0
  26. package/dist/src/commands/doctor-helpers-checks.d.ts.map +1 -0
  27. package/dist/src/commands/doctor-helpers-checks.js +292 -0
  28. package/dist/src/commands/doctor-helpers-checks.js.map +1 -0
  29. package/dist/src/commands/doctor-memory-checks.d.ts +47 -0
  30. package/dist/src/commands/doctor-memory-checks.d.ts.map +1 -0
  31. package/dist/src/commands/doctor-memory-checks.js +298 -0
  32. package/dist/src/commands/doctor-memory-checks.js.map +1 -0
  33. package/dist/src/commands/doctor-monograph-checks.d.ts +9 -0
  34. package/dist/src/commands/doctor-monograph-checks.d.ts.map +1 -0
  35. package/dist/src/commands/doctor-monograph-checks.js +331 -0
  36. package/dist/src/commands/doctor-monograph-checks.js.map +1 -0
  37. package/dist/src/commands/doctor-project-checks.d.ts +7 -66
  38. package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
  39. package/dist/src/commands/doctor-project-checks.js +10 -1331
  40. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  41. package/dist/src/commands/doctor-routing-checks.d.ts +10 -0
  42. package/dist/src/commands/doctor-routing-checks.d.ts.map +1 -0
  43. package/dist/src/commands/doctor-routing-checks.js +194 -0
  44. package/dist/src/commands/doctor-routing-checks.js.map +1 -0
  45. package/dist/src/commands/doctor-worker-checks.d.ts +17 -0
  46. package/dist/src/commands/doctor-worker-checks.d.ts.map +1 -0
  47. package/dist/src/commands/doctor-worker-checks.js +122 -0
  48. package/dist/src/commands/doctor-worker-checks.js.map +1 -0
  49. package/dist/src/commands/hooks-routing-commands.js +1 -1
  50. package/dist/src/commands/hooks-routing-commands.js.map +1 -1
  51. package/dist/src/commands/init.d.ts.map +1 -1
  52. package/dist/src/commands/init.js +6 -15
  53. package/dist/src/commands/init.js.map +1 -1
  54. package/dist/src/index.js +2 -2
  55. package/dist/src/index.js.map +1 -1
  56. package/dist/src/init/never-commit.d.ts +3 -3
  57. package/dist/src/init/types.d.ts +1 -1
  58. package/dist/src/init/types.js +1 -1
  59. package/dist/src/knowledge/document-store.js +1 -1
  60. package/dist/src/knowledge/document-store.js.map +1 -1
  61. package/dist/src/mcp-tools/hooks-edit-command.d.ts +10 -0
  62. package/dist/src/mcp-tools/hooks-edit-command.d.ts.map +1 -0
  63. package/dist/src/mcp-tools/hooks-edit-command.js +247 -0
  64. package/dist/src/mcp-tools/hooks-edit-command.js.map +1 -0
  65. package/dist/src/mcp-tools/hooks-learning.d.ts +9 -0
  66. package/dist/src/mcp-tools/hooks-learning.d.ts.map +1 -0
  67. package/dist/src/mcp-tools/hooks-learning.js +408 -0
  68. package/dist/src/mcp-tools/hooks-learning.js.map +1 -0
  69. package/dist/src/mcp-tools/hooks-metrics-list.d.ts +8 -0
  70. package/dist/src/mcp-tools/hooks-metrics-list.d.ts.map +1 -0
  71. package/dist/src/mcp-tools/hooks-metrics-list.js +205 -0
  72. package/dist/src/mcp-tools/hooks-metrics-list.js.map +1 -0
  73. package/dist/src/mcp-tools/hooks-route.d.ts +12 -0
  74. package/dist/src/mcp-tools/hooks-route.d.ts.map +1 -0
  75. package/dist/src/mcp-tools/hooks-route.js +251 -0
  76. package/dist/src/mcp-tools/hooks-route.js.map +1 -0
  77. package/dist/src/mcp-tools/hooks-routing.d.ts +6 -27
  78. package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
  79. package/dist/src/mcp-tools/hooks-routing.js +6 -1727
  80. package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
  81. package/dist/src/mcp-tools/hooks-session.d.ts +9 -0
  82. package/dist/src/mcp-tools/hooks-session.d.ts.map +1 -0
  83. package/dist/src/mcp-tools/hooks-session.js +243 -0
  84. package/dist/src/mcp-tools/hooks-session.js.map +1 -0
  85. package/dist/src/mcp-tools/hooks-task.d.ts +17 -0
  86. package/dist/src/mcp-tools/hooks-task.d.ts.map +1 -0
  87. package/dist/src/mcp-tools/hooks-task.js +427 -0
  88. package/dist/src/mcp-tools/hooks-task.js.map +1 -0
  89. package/dist/src/mcp-tools/hooks-tools.d.ts +2 -1
  90. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
  91. package/dist/src/mcp-tools/hooks-tools.js +2 -1
  92. package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
  93. package/dist/src/mcp-tools/memory-tools.js +1 -1
  94. package/dist/src/mcp-tools/memory-tools.js.map +1 -1
  95. package/dist/src/memory/bm25-index.d.ts +2 -2
  96. package/dist/src/memory/bm25-index.js +2 -2
  97. package/dist/src/memory/embedding-operations.js +2 -2
  98. package/dist/src/memory/embedding-operations.js.map +1 -1
  99. package/dist/src/memory/entity-name-key.d.ts +1 -1
  100. package/dist/src/memory/entity-name-key.js +1 -1
  101. package/dist/src/memory/hnsw-operations.d.ts +1 -1
  102. package/dist/src/memory/hnsw-operations.js +1 -1
  103. package/dist/src/memory/memory-bridge-backend.d.ts +43 -0
  104. package/dist/src/memory/memory-bridge-backend.d.ts.map +1 -0
  105. package/dist/src/memory/memory-bridge-backend.js +363 -0
  106. package/dist/src/memory/memory-bridge-backend.js.map +1 -0
  107. package/dist/src/memory/memory-bridge-core.d.ts +42 -0
  108. package/dist/src/memory/memory-bridge-core.d.ts.map +1 -0
  109. package/dist/src/memory/memory-bridge-core.js +126 -0
  110. package/dist/src/memory/memory-bridge-core.js.map +1 -0
  111. package/dist/src/memory/memory-bridge-entries.d.ts +131 -0
  112. package/dist/src/memory/memory-bridge-entries.d.ts.map +1 -0
  113. package/dist/src/memory/memory-bridge-entries.js +227 -0
  114. package/dist/src/memory/memory-bridge-entries.js.map +1 -0
  115. package/dist/src/memory/memory-bridge-feedback.d.ts +60 -0
  116. package/dist/src/memory/memory-bridge-feedback.d.ts.map +1 -0
  117. package/dist/src/memory/memory-bridge-feedback.js +118 -0
  118. package/dist/src/memory/memory-bridge-feedback.js.map +1 -0
  119. package/dist/src/memory/memory-bridge-paths.d.ts +123 -0
  120. package/dist/src/memory/memory-bridge-paths.d.ts.map +1 -0
  121. package/dist/src/memory/memory-bridge-paths.js +335 -0
  122. package/dist/src/memory/memory-bridge-paths.js.map +1 -0
  123. package/dist/src/memory/memory-bridge-search.d.ts +48 -0
  124. package/dist/src/memory/memory-bridge-search.d.ts.map +1 -0
  125. package/dist/src/memory/memory-bridge-search.js +383 -0
  126. package/dist/src/memory/memory-bridge-search.js.map +1 -0
  127. package/dist/src/memory/memory-bridge-sessions.d.ts +38 -0
  128. package/dist/src/memory/memory-bridge-sessions.d.ts.map +1 -0
  129. package/dist/src/memory/memory-bridge-sessions.js +109 -0
  130. package/dist/src/memory/memory-bridge-sessions.js.map +1 -0
  131. package/dist/src/memory/memory-bridge-store.d.ts +58 -0
  132. package/dist/src/memory/memory-bridge-store.d.ts.map +1 -0
  133. package/dist/src/memory/memory-bridge-store.js +201 -0
  134. package/dist/src/memory/memory-bridge-store.js.map +1 -0
  135. package/dist/src/memory/memory-bridge.d.ts +10 -438
  136. package/dist/src/memory/memory-bridge.d.ts.map +1 -1
  137. package/dist/src/memory/memory-bridge.js +14 -1787
  138. package/dist/src/memory/memory-bridge.js.map +1 -1
  139. package/dist/src/memory/memory-kg-claims.d.ts +52 -0
  140. package/dist/src/memory/memory-kg-claims.d.ts.map +1 -0
  141. package/dist/src/memory/memory-kg-claims.js +99 -0
  142. package/dist/src/memory/memory-kg-claims.js.map +1 -0
  143. package/dist/src/memory/memory-kg-index.d.ts +86 -0
  144. package/dist/src/memory/memory-kg-index.d.ts.map +1 -0
  145. package/dist/src/memory/memory-kg-index.js +256 -0
  146. package/dist/src/memory/memory-kg-index.js.map +1 -0
  147. package/dist/src/memory/memory-kg-ingest.d.ts +44 -0
  148. package/dist/src/memory/memory-kg-ingest.d.ts.map +1 -0
  149. package/dist/src/memory/memory-kg-ingest.js +361 -0
  150. package/dist/src/memory/memory-kg-ingest.js.map +1 -0
  151. package/dist/src/memory/memory-kg-model.d.ts +168 -0
  152. package/dist/src/memory/memory-kg-model.d.ts.map +1 -0
  153. package/dist/src/memory/memory-kg-model.js +158 -0
  154. package/dist/src/memory/memory-kg-model.js.map +1 -0
  155. package/dist/src/memory/memory-kg-names.d.ts +64 -0
  156. package/dist/src/memory/memory-kg-names.d.ts.map +1 -0
  157. package/dist/src/memory/memory-kg-names.js +187 -0
  158. package/dist/src/memory/memory-kg-names.js.map +1 -0
  159. package/dist/src/memory/memory-kg-promote.d.ts +79 -0
  160. package/dist/src/memory/memory-kg-promote.d.ts.map +1 -0
  161. package/dist/src/memory/memory-kg-promote.js +248 -0
  162. package/dist/src/memory/memory-kg-promote.js.map +1 -0
  163. package/dist/src/memory/memory-kg-rebuild.d.ts +77 -0
  164. package/dist/src/memory/memory-kg-rebuild.d.ts.map +1 -0
  165. package/dist/src/memory/memory-kg-rebuild.js +299 -0
  166. package/dist/src/memory/memory-kg-rebuild.js.map +1 -0
  167. package/dist/src/memory/memory-kg-rollback.d.ts +47 -0
  168. package/dist/src/memory/memory-kg-rollback.d.ts.map +1 -0
  169. package/dist/src/memory/memory-kg-rollback.js +193 -0
  170. package/dist/src/memory/memory-kg-rollback.js.map +1 -0
  171. package/dist/src/memory/memory-kg-rules.d.ts +64 -0
  172. package/dist/src/memory/memory-kg-rules.d.ts.map +1 -0
  173. package/dist/src/memory/memory-kg-rules.js +251 -0
  174. package/dist/src/memory/memory-kg-rules.js.map +1 -0
  175. package/dist/src/memory/memory-kg-scan.d.ts +118 -0
  176. package/dist/src/memory/memory-kg-scan.d.ts.map +1 -0
  177. package/dist/src/memory/memory-kg-scan.js +209 -0
  178. package/dist/src/memory/memory-kg-scan.js.map +1 -0
  179. package/dist/src/memory/memory-kg-search.d.ts +80 -0
  180. package/dist/src/memory/memory-kg-search.d.ts.map +1 -0
  181. package/dist/src/memory/memory-kg-search.js +239 -0
  182. package/dist/src/memory/memory-kg-search.js.map +1 -0
  183. package/dist/src/memory/memory-kg.d.ts +19 -547
  184. package/dist/src/memory/memory-kg.d.ts.map +1 -1
  185. package/dist/src/memory/memory-kg.js +10 -2389
  186. package/dist/src/memory/memory-kg.js.map +1 -1
  187. package/dist/src/ui/org-hil.mjs +1 -1
  188. package/dist/src/ui/routes-org-agents.mjs +318 -0
  189. package/dist/src/ui/routes-org-approvals.mjs +133 -0
  190. package/dist/src/ui/routes-org-config.mjs +459 -0
  191. package/dist/src/ui/routes-org-control.mjs +300 -0
  192. package/dist/src/ui/routes-org-files.mjs +172 -0
  193. package/dist/src/ui/routes-org-helpers.mjs +84 -0
  194. package/dist/src/ui/routes-org-knowledge.mjs +262 -0
  195. package/dist/src/ui/routes-org-lifecycle.mjs +224 -0
  196. package/dist/src/ui/routes-org-live.mjs +278 -0
  197. package/dist/src/ui/routes-org-mastermind.mjs +346 -0
  198. package/dist/src/ui/routes-org-planning.mjs +398 -0
  199. package/dist/src/ui/routes-org-runs.mjs +430 -0
  200. package/dist/src/ui/routes-org-status.mjs +342 -0
  201. package/dist/src/ui/routes-org-workflows.mjs +212 -0
  202. package/dist/src/ui/routes-org.mjs +26 -3847
  203. package/dist/src/ui/server.mjs +1 -1
  204. package/dist/src/utils/native-error.d.ts +1 -1
  205. package/dist/src/utils/native-error.js +1 -1
  206. package/dist/src/utils/paths.d.ts +2 -1
  207. package/dist/src/utils/paths.d.ts.map +1 -1
  208. package/dist/src/utils/paths.js +2 -1
  209. package/dist/src/utils/paths.js.map +1 -1
  210. package/dist/tsconfig.tsbuildinfo +1 -1
  211. package/org-skills/adversarial-reviewer/SKILL.md +1 -1
  212. package/org-skills/board-deck-builder/SKILL.md +1 -1
  213. package/org-skills/code-reviewer/SKILL.md +1 -1
  214. package/org-skills/debugging-wizard/SKILL.md +1 -1
  215. package/org-skills/scientific-thinking-literature-review/SKILL.md +1 -1
  216. package/org-skills/scientific-thinking-scholar-evaluation/SKILL.md +1 -1
  217. package/package.json +8 -8
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Doctor — hook helper checks: installed helpers vs the bundled copies
3
+ * (freshness and --fix) and guidance gate wiring.
4
+ * Extracted from doctor-project-checks.ts.
5
+ */
6
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync } from 'node:fs';
7
+ import { dirname, join, sep } from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { isKeptUserEdit } from '../init/file-guard.js';
10
+ import { DOCTOR_TRACKED_HELPERS, OBSOLETE_HELPER_NAMES } from '../init/helpers-generator.js';
11
+ import { MAX_DOCTOR_CONFIG_BYTES, MAX_DOCTOR_HELPER_BYTES, MAX_DOCTOR_PKG_BYTES, } from './doctor-env-checks.js';
12
+ function _resolveBundledHelper(relativePath) {
13
+ try {
14
+ const thisFile = fileURLToPath(import.meta.url);
15
+ let dir = dirname(thisFile);
16
+ for (;;) {
17
+ const candidate = join(dir, 'package.json');
18
+ if (existsSync(candidate) && statSync(candidate).size <= MAX_DOCTOR_PKG_BYTES) {
19
+ try {
20
+ const pkg = JSON.parse(readFileSync(candidate, 'utf8'));
21
+ if (pkg.name === '@monomind/cli' ||
22
+ pkg.name === 'monomind' ||
23
+ pkg.name === '@monoes/monomindcli') {
24
+ const helperPath = join(dir, relativePath);
25
+ return existsSync(helperPath) ? helperPath : null;
26
+ }
27
+ }
28
+ catch {
29
+ /* keep walking */
30
+ }
31
+ }
32
+ const parent = dirname(dir);
33
+ if (parent === dir)
34
+ return null;
35
+ dir = parent;
36
+ }
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ // Top-level critical helpers, plus every file bundled under handlers/ and utils/
43
+ // (capture-handler.cjs, gates-handler.cjs, route-handler.cjs, session-handler.cjs,
44
+ // etc. — where most actual hook-behavior fixes live). Subdir membership is
45
+ // discovered from the bundled package itself, not hardcoded, so a helper added
46
+ // upstream is picked up automatically instead of silently never syncing.
47
+ function _allTrackedHelperNames() {
48
+ const names = [...DOCTOR_TRACKED_HELPERS];
49
+ for (const sub of ['handlers', 'utils']) {
50
+ const bundledSubDir = _resolveBundledHelper(join('.claude', 'helpers', sub));
51
+ if (!bundledSubDir)
52
+ continue;
53
+ try {
54
+ for (const f of readdirSync(bundledSubDir)) {
55
+ if (f.startsWith('._'))
56
+ continue;
57
+ if (statSync(join(bundledSubDir, f)).isDirectory())
58
+ continue;
59
+ names.push(join(sub, f));
60
+ }
61
+ }
62
+ catch {
63
+ /* skip */
64
+ }
65
+ }
66
+ return names;
67
+ }
68
+ // Top-level helpers the bundle ships. Their mere ABSENCE is a defect no
69
+ // matter which one it is — handlers/ scripts require() some of them at module
70
+ // load, and a missing one fails the hook closed (issue #225: doctor reported
71
+ // "helpers match bundled version" while audit-log-writer.cjs was absent and
72
+ // every PreToolUse hook was crashing). Existence is checked for all of them;
73
+ // content is still only hash-compared for _allTrackedHelperNames(), because
74
+ // the rest are user-editable scaffolds (memory.cjs, session.cjs) whose local
75
+ // edits are legitimate and must not be reported as staleness.
76
+ function _bundledTopLevelHelperNames() {
77
+ const bundledDir = _resolveBundledHelper(join('.claude', 'helpers'));
78
+ if (!bundledDir)
79
+ return [];
80
+ try {
81
+ return readdirSync(bundledDir, { withFileTypes: true })
82
+ .filter((e) => e.isFile() && !e.name.startsWith('._'))
83
+ .map((e) => e.name);
84
+ }
85
+ catch {
86
+ return [];
87
+ }
88
+ }
89
+ // The installed helper copies doctor compares against the bundle: the Claude
90
+ // Code tree, plus the copy init writes to .gemini/helpers (Antigravity's status
91
+ // bar runs .gemini/helpers/statusline.cjs), which is only checked when present.
92
+ const CLAUDE_HELPERS = join('.claude', 'helpers');
93
+ const GEMINI_HELPERS = join('.gemini', 'helpers');
94
+ async function _detectStaleHelpers(helpersDir = CLAUDE_HELPERS) {
95
+ const stale = [];
96
+ const missing = [];
97
+ // Helpers this product shipped under a name it has since renamed away from
98
+ // (e.g. graphify-freshen.cjs -> monograph-freshen.cjs). Reported separately
99
+ // from `stale`/`missing`: unlike those, doctor --fix does not delete these
100
+ // on its own — settings.json may still have a hook command pointing at one,
101
+ // and only `init --force` (which also refreshes settings.json in the same
102
+ // pass) can safely remove it. See writeHelpers/writeSettings.
103
+ const orphaned = OBSOLETE_HELPER_NAMES.filter((name) => existsSync(join(process.cwd(), '.claude', 'helpers', name)));
104
+ const crypto = await import('node:crypto');
105
+ const hashChecked = new Set(_allTrackedHelperNames());
106
+ for (const name of new Set([..._allTrackedHelperNames(), ..._bundledTopLevelHelperNames()])) {
107
+ const bundled = _resolveBundledHelper(join('.claude', 'helpers', name));
108
+ // Oversized-bundled is reported the same as missing-bundled: doctor can't
109
+ // verify freshness either way, and silently excluding it from both `stale`
110
+ // and `missing` would let checkHelpersFresh() report "pass" without ever
111
+ // having actually compared this file.
112
+ if (!bundled || statSync(bundled).size > MAX_DOCTOR_HELPER_BYTES) {
113
+ missing.push(name);
114
+ continue;
115
+ }
116
+ const local = join(process.cwd(), helpersDir, name);
117
+ if (!existsSync(local)) {
118
+ stale.push(name);
119
+ continue;
120
+ } // bundled has it, project doesn't — needs creating
121
+ if (!hashChecked.has(name))
122
+ continue; // existence-only (see above)
123
+ if (statSync(local).size > MAX_DOCTOR_HELPER_BYTES)
124
+ continue;
125
+ try {
126
+ const hashLocal = crypto.createHash('sha256').update(readFileSync(local)).digest('hex');
127
+ const hashBundled = crypto.createHash('sha256').update(readFileSync(bundled)).digest('hex');
128
+ if (hashLocal !== hashBundled)
129
+ stale.push(name);
130
+ }
131
+ catch {
132
+ /* skip */
133
+ }
134
+ }
135
+ return { stale, missing, orphaned };
136
+ }
137
+ /** Stale helpers in the Gemini copy, as `.gemini/helpers/<name>`; none if not installed. */
138
+ async function _detectStaleGeminiHelpers() {
139
+ if (!existsSync(join(process.cwd(), GEMINI_HELPERS)))
140
+ return [];
141
+ const { stale } = await _detectStaleHelpers(GEMINI_HELPERS);
142
+ return stale.map((name) => `.gemini/helpers/${name.split(sep).join('/')}`);
143
+ }
144
+ export async function fixStaleHelpers() {
145
+ const { stale } = await _detectStaleHelpers();
146
+ const targets = stale.map((name) => ({ name, local: join(process.cwd(), CLAUDE_HELPERS, name) }));
147
+ if (existsSync(join(process.cwd(), GEMINI_HELPERS))) {
148
+ for (const name of (await _detectStaleHelpers(GEMINI_HELPERS)).stale) {
149
+ targets.push({ name, local: join(process.cwd(), GEMINI_HELPERS, name) });
150
+ }
151
+ }
152
+ let fixed = 0;
153
+ for (const { name, local } of targets) {
154
+ // A helper `monomind init` kept because the user edited it is theirs.
155
+ if (isKeptUserEdit(process.cwd(), local))
156
+ continue;
157
+ const bundled = _resolveBundledHelper(join('.claude', 'helpers', name));
158
+ if (bundled) {
159
+ try {
160
+ mkdirSync(dirname(local), { recursive: true });
161
+ copyFileSync(bundled, local);
162
+ fixed++;
163
+ }
164
+ catch (e) {
165
+ if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
166
+ console.error(`[fixStaleHelpers] failed to copy ${name}:`, e);
167
+ }
168
+ }
169
+ }
170
+ return fixed > 0;
171
+ }
172
+ export async function checkHelpersFresh() {
173
+ try {
174
+ const { stale: claudeStale, missing, orphaned } = await _detectStaleHelpers();
175
+ const stale = [...claudeStale, ...(await _detectStaleGeminiHelpers())];
176
+ if (orphaned.length > 0) {
177
+ return {
178
+ name: 'Helper Files',
179
+ status: 'warn',
180
+ message: `Found ${orphaned.length} hook(s) from before a rename, still on disk: ${orphaned.join(', ')}. Run \`monomind init --force\` to update your hooks and rebuild the Monograph graph.`,
181
+ fix: 'monomind init --force',
182
+ // `--fix` only copies stale helpers; it never removes these.
183
+ fixSafety: 'manual',
184
+ };
185
+ }
186
+ if (stale.length === 0 && missing.length === 0) {
187
+ return {
188
+ name: 'Helper Files',
189
+ status: 'pass',
190
+ message: 'Project helpers match bundled version',
191
+ };
192
+ }
193
+ if (stale.length > 0) {
194
+ return {
195
+ name: 'Helper Files',
196
+ status: 'warn',
197
+ message: `${stale.length} stale helper(s): ${stale.join(', ')}`,
198
+ fix: 'monomind init upgrade',
199
+ fixSafety: 'auto',
200
+ };
201
+ }
202
+ return {
203
+ name: 'Helper Files',
204
+ status: 'warn',
205
+ message: `Could not locate bundled copies of: ${missing.join(', ')}`,
206
+ fix: 'Reinstall monomind or run `monomind init upgrade`',
207
+ fixSafety: 'manual',
208
+ };
209
+ }
210
+ catch (e) {
211
+ return {
212
+ name: 'Helper Files',
213
+ status: 'warn',
214
+ message: `check failed: ${e instanceof Error ? e.message : 'unknown'}`,
215
+ };
216
+ }
217
+ }
218
+ export async function checkGuidanceGates() {
219
+ const settingsPath = join(process.cwd(), '.claude', 'settings.json');
220
+ const gatesHandlerPath = join(process.cwd(), '.claude', 'helpers', 'handlers', 'gates-handler.cjs');
221
+ if (!existsSync(gatesHandlerPath)) {
222
+ return {
223
+ name: 'Guidance Gates',
224
+ status: 'warn',
225
+ message: 'gates-handler.cjs not found — enforcement gates not installed',
226
+ fix: 'monomind init (then monomind guidance setup)',
227
+ };
228
+ }
229
+ if (!existsSync(settingsPath)) {
230
+ return {
231
+ name: 'Guidance Gates',
232
+ status: 'warn',
233
+ message: 'gates-handler.cjs present but .claude/settings.json missing',
234
+ fix: 'monomind guidance setup',
235
+ };
236
+ }
237
+ try {
238
+ if (statSync(settingsPath).size > MAX_DOCTOR_CONFIG_BYTES) {
239
+ return {
240
+ name: 'Guidance Gates',
241
+ status: 'warn',
242
+ message: 'settings.json too large to parse',
243
+ };
244
+ }
245
+ const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
246
+ const preToolUse = settings?.hooks?.PreToolUse ?? [];
247
+ // Match on capability, not on an exact matcher string. The matcher is a
248
+ // regex alternation that legitimately changes as tools are added — it
249
+ // gained `|NotebookEdit` when that tool turned out to bypass the secret
250
+ // gate — and an `=== 'Write|Edit|MultiEdit'` test reported the gate as
251
+ // INACTIVE the moment it did, telling users their secrets gate was off
252
+ // while it was demonstrably blocking secrets, and sending them to
253
+ // `guidance setup`, which would then add a duplicate entry.
254
+ const hasPreWrite = preToolUse.some((e) => /\bWrite\b/.test(e.matcher ?? '') && e.hooks.some((h) => h.command?.includes('pre-write')));
255
+ const hasPreBash = preToolUse.some((e) => e.matcher === 'Bash' && e.hooks.some((h) => h.command?.includes('pre-bash')));
256
+ if (!hasPreWrite && !hasPreBash)
257
+ return {
258
+ name: 'Guidance Gates',
259
+ status: 'warn',
260
+ message: 'gates-handler.cjs present but no gates registered',
261
+ fix: 'monomind guidance setup',
262
+ };
263
+ if (!hasPreWrite)
264
+ return {
265
+ name: 'Guidance Gates',
266
+ status: 'warn',
267
+ message: 'pre-write hook not registered — secrets gate inactive',
268
+ fix: 'monomind guidance setup',
269
+ };
270
+ if (!hasPreBash)
271
+ return {
272
+ name: 'Guidance Gates',
273
+ status: 'warn',
274
+ message: 'pre-bash hook not registered — destructive-ops gate inactive',
275
+ fix: 'monomind guidance setup',
276
+ };
277
+ return {
278
+ name: 'Guidance Gates',
279
+ status: 'pass',
280
+ message: 'destructive-ops (pre-bash) + secrets (pre-write) gates active',
281
+ };
282
+ }
283
+ catch {
284
+ return {
285
+ name: 'Guidance Gates',
286
+ status: 'warn',
287
+ message: 'Could not parse .claude/settings.json',
288
+ fix: 'monomind guidance setup --force',
289
+ };
290
+ }
291
+ }
292
+ //# sourceMappingURL=doctor-helpers-checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-helpers-checks.js","sourceRoot":"","sources":["../../../src/commands/doctor-helpers-checks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnG,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC7F,OAAO,EAEL,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,SAAS,qBAAqB,CAAC,YAAoB;IACjD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC5B,SAAS,CAAC;YACR,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YAC5C,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,oBAAoB,EAAE,CAAC;gBAC9E,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;oBACxD,IACE,GAAG,CAAC,IAAI,KAAK,eAAe;wBAC5B,GAAG,CAAC,IAAI,KAAK,UAAU;wBACvB,GAAG,CAAC,IAAI,KAAK,qBAAqB,EAClC,CAAC;wBACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;wBAC3C,OAAO,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;oBACpD,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,kBAAkB;gBACpB,CAAC;YACH,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,IAAI,CAAC;YAChC,GAAG,GAAG,MAAM,CAAC;QACf,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,iFAAiF;AACjF,mFAAmF;AACnF,2EAA2E;AAC3E,+EAA+E;AAC/E,yEAAyE;AACzE,SAAS,sBAAsB;IAC7B,MAAM,KAAK,GAAG,CAAC,GAAG,sBAAsB,CAAC,CAAC;IAC1C,KAAK,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,aAAa,GAAG,qBAAqB,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,aAAa;YAAE,SAAS;QAC7B,IAAI,CAAC;YACH,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACjC,IAAI,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;oBAAE,SAAS;gBAC7D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,UAAU;QACZ,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wEAAwE;AACxE,8EAA8E;AAC9E,6EAA6E;AAC7E,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,6EAA6E;AAC7E,8DAA8D;AAC9D,SAAS,2BAA2B;IAClC,MAAM,UAAU,GAAG,qBAAqB,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IACrE,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;aACpD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;aACrD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,gFAAgF;AAChF,gFAAgF;AAChF,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAClD,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAElD,KAAK,UAAU,mBAAmB,CAAC,UAAU,GAAW,cAAc;IAKpE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,4EAA4E;IAC5E,0EAA0E;IAC1E,8DAA8D;IAC9D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACrD,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAC5D,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,sBAAsB,EAAE,CAAC,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,GAAG,sBAAsB,EAAE,EAAE,GAAG,2BAA2B,EAAE,CAAC,CAAC,EAAE,CAAC;QAC5F,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QACxE,0EAA0E;QAC1E,2EAA2E;QAC3E,yEAAyE;QACzE,sCAAsC;QACtC,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,GAAG,uBAAuB,EAAE,CAAC;YACjE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QACpD,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,SAAS;QACX,CAAC,CAAC,mDAAmD;QACrD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,6BAA6B;QACnE,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,uBAAuB;YAAE,SAAS;QAC7D,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxF,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5F,IAAI,SAAS,KAAK,WAAW;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,UAAU;QACZ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtC,CAAC;AAED,4FAA4F;AAC5F,KAAK,UAAU,yBAAyB;IACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAChE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,mBAAmB,CAAC,cAAc,CAAC,CAAC;IAC5D,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAClG,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;QACpD,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,mBAAmB,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;YACrE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,OAAO,EAAE,CAAC;QACtC,sEAAsE;QACtE,IAAI,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC;YAAE,SAAS;QACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QACxE,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/C,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBAC7B,KAAK,EAAE,CAAC;YACV,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;oBACjD,OAAO,CAAC,KAAK,CAAC,oCAAoC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,GAAG,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;QAC9E,MAAM,KAAK,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,CAAC,MAAM,yBAAyB,EAAE,CAAC,CAAC,CAAC;QACvE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO;gBACL,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,SAAS,QAAQ,CAAC,MAAM,iDAAiD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,uFAAuF;gBAC5L,GAAG,EAAE,uBAAuB;gBAC5B,6DAA6D;gBAC7D,SAAS,EAAE,QAAQ;aACpB,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO;gBACL,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,uCAAuC;aACjD,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,OAAO;gBACL,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,qBAAqB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC/D,GAAG,EAAE,uBAAuB;gBAC5B,SAAS,EAAE,MAAM;aAClB,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,uCAAuC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACpE,GAAG,EAAE,mDAAmD;YACxD,SAAS,EAAE,QAAQ;SACpB,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO;YACL,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,iBAAiB,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE;SACvE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IACrE,MAAM,gBAAgB,GAAG,IAAI,CAC3B,OAAO,CAAC,GAAG,EAAE,EACb,SAAS,EACT,SAAS,EACT,UAAU,EACV,mBAAmB,CACpB,CAAC;IACF,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,+DAA+D;YACxE,GAAG,EAAE,+CAA+C;SACrD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,6DAA6D;YACtE,GAAG,EAAE,yBAAyB;SAC/B,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC,IAAI,GAAG,uBAAuB,EAAE,CAAC;YAC1D,OAAO;gBACL,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,kCAAkC;aAC5C,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;QACjE,MAAM,UAAU,GACd,QAAQ,EAAE,KAAK,EAAE,UAAU,IAAI,EAAE,CAAC;QACpC,wEAAwE;QACxE,sEAAsE;QACtE,wEAAwE;QACxE,uEAAuE;QACvE,uEAAuE;QACvE,kEAAkE;QAClE,4DAA4D;QAC5D,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,EAAE,CACJ,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC,CAC7F,CAAC;QACF,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CACpF,CAAC;QACF,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU;YAC7B,OAAO;gBACL,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,mDAAmD;gBAC5D,GAAG,EAAE,yBAAyB;aAC/B,CAAC;QACJ,IAAI,CAAC,WAAW;YACd,OAAO;gBACL,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,uDAAuD;gBAChE,GAAG,EAAE,yBAAyB;aAC/B,CAAC;QACJ,IAAI,CAAC,UAAU;YACb,OAAO;gBACL,IAAI,EAAE,gBAAgB;gBACtB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,8DAA8D;gBACvE,GAAG,EAAE,yBAAyB;aAC/B,CAAC;QACJ,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,+DAA+D;SACzE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,uCAAuC;YAChD,GAAG,EAAE,iCAAiC;SACvC,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Doctor — memory checks: project root resolution, memory database, knowledge
3
+ * graph, Second Brain model and document extractors, memory proficiency.
4
+ * Extracted from doctor-project-checks.ts.
5
+ */
6
+ import type { HealthCheck } from './doctor-env-checks.js';
7
+ /** o-16 (AC-6): the marker walk that resolves "this project" for the Memory
8
+ * & Knowledge store can silently adopt a wrong ancestor — the incident that
9
+ * motivated this check was a shared scratch parent's bare `.monomind`
10
+ * capturing an unrelated fixture, with no visible symptom until a search
11
+ * came back empty. Disclose the resolved root and why it was chosen, so a
12
+ * user can see which directory their brain is keyed to without reading code
13
+ * or debug logs. Always 'info': the resolution itself is never a health
14
+ * problem, only the failure to see it was.
15
+ *
16
+ * Named/scoped to "Memory Project Root", not a bare "Project Root" (o-16
17
+ * revision 1, reviewer MAJOR 2): `MONOMIND_PROJECT_ROOT` has a SECOND,
18
+ * independent consumer — `mcp-tools/guidance-tools.ts:findProjectRoot()`,
19
+ * which uses a different marker (`.claude`) and can legitimately resolve a
20
+ * different directory (see the divergence explained at
21
+ * `memory-bridge.ts`'s `getProjectRoot()` doc comment). A generic "Project
22
+ * Root" label would claim there is one true answer when this commit is
23
+ * what creates a state where two resolvers can disagree — this check must
24
+ * not be the thing that misleads about that. */
25
+ export declare function checkProjectRoot(): Promise<HealthCheck>;
26
+ export declare function checkMemoryDatabase(): Promise<HealthCheck>;
27
+ /** Memory knowledge graph (cognee port): entities/relations/rules distilled
28
+ * from sessions and org runs. Informational — an empty graph on a fresh
29
+ * project is normal, so it never fails. */
30
+ export declare function checkMemoryKnowledgeGraph(): Promise<HealthCheck>;
31
+ /** Second Brain: when there is any indexed knowledge — ingested docs in this
32
+ * project, the personal global brain, or the monograph god-node chunk —
33
+ * semantic search needs the local embedding model. Its absence is silent
34
+ * (search degrades to keyword matching), so surface it here instead. */
35
+ export declare function checkSecondBrainModel(): Promise<HealthCheck>;
36
+ /**
37
+ * AutoMem proficiency check — reports memory learning health
38
+ */
39
+ export declare function checkMemoryProficiency(): Promise<HealthCheck>;
40
+ /** Per-extractor health for Second Brain document ingestion (MEM-8/MEM-9):
41
+ * one check per format family (PDF, DOCX, XLSX/XLS/ODS, PPTX/ODT/ODP/EPUB,
42
+ * legacy DOC/PPT/Pages) instead of a single blanket "documents" check, so
43
+ * `doctor` can report exactly which formats are functional vs broken.
44
+ * No-op (empty array) when the documents capability isn't active — nothing
45
+ * to report if this project doesn't ingest documents. */
46
+ export declare function checkDocumentExtractors(): Promise<HealthCheck[]>;
47
+ //# sourceMappingURL=doctor-memory-checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-memory-checks.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor-memory-checks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D;;;;;;;;;;;;;;;;;iDAiBiD;AACjD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,WAAW,CAAC,CA2B7D;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC,CAkBhE;AAED;;2CAE2C;AAC3C,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,WAAW,CAAC,CAqDtE;AAeD;;;wEAGwE;AACxE,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,WAAW,CAAC,CAuElE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,WAAW,CAAC,CA6BnE;AAiBD;;;;;yDAKyD;AACzD,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAoBtE"}
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Doctor — memory checks: project root resolution, memory database, knowledge
3
+ * graph, Second Brain model and document extractors, memory proficiency.
4
+ * Extracted from doctor-project-checks.ts.
5
+ */
6
+ import { existsSync, readFileSync, statSync } from 'node:fs';
7
+ import { dirname, join } from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { MEMORY_DB_CANDIDATE_PATHS } from '../utils/paths.js';
10
+ /** o-16 (AC-6): the marker walk that resolves "this project" for the Memory
11
+ * & Knowledge store can silently adopt a wrong ancestor — the incident that
12
+ * motivated this check was a shared scratch parent's bare `.monomind`
13
+ * capturing an unrelated fixture, with no visible symptom until a search
14
+ * came back empty. Disclose the resolved root and why it was chosen, so a
15
+ * user can see which directory their brain is keyed to without reading code
16
+ * or debug logs. Always 'info': the resolution itself is never a health
17
+ * problem, only the failure to see it was.
18
+ *
19
+ * Named/scoped to "Memory Project Root", not a bare "Project Root" (o-16
20
+ * revision 1, reviewer MAJOR 2): `MONOMIND_PROJECT_ROOT` has a SECOND,
21
+ * independent consumer — `mcp-tools/guidance-tools.ts:findProjectRoot()`,
22
+ * which uses a different marker (`.claude`) and can legitimately resolve a
23
+ * different directory (see the divergence explained at
24
+ * `memory-bridge.ts`'s `getProjectRoot()` doc comment). A generic "Project
25
+ * Root" label would claim there is one true answer when this commit is
26
+ * what creates a state where two resolvers can disagree — this check must
27
+ * not be the thing that misleads about that. */
28
+ export async function checkProjectRoot() {
29
+ const name = 'Memory Project Root';
30
+ const { getProjectRootResolution } = await import('../memory/memory-bridge.js');
31
+ const { root, reason, ignoredBareMonomind, invalidAnchor } = getProjectRootResolution();
32
+ const reasonText = {
33
+ 'explicit-anchor': 'MONOMIND_PROJECT_ROOT anchor',
34
+ git: 'nearest .git ancestor',
35
+ 'monomind-at-start': 'starting directory carries .monomind',
36
+ 'monomind-with-marker': '.monomind ancestor confirmed by a project manifest',
37
+ 'start-fallback': 'no adoptable marker found — using the current directory',
38
+ };
39
+ // o-16 revision 1 (dev-lead Addition 1): the anchor's own disclosure must
40
+ // cover the ambiguous case it exists to resolve — a SET-but-INVALID
41
+ // anchor — not just the happy path, or a typo'd MONOMIND_PROJECT_ROOT
42
+ // silently does nothing and the user has no way to find out why. Appended
43
+ // regardless of which `reason` the walk ultimately fell back to.
44
+ const invalidAnchorNote = invalidAnchor
45
+ ? ` [MONOMIND_PROJECT_ROOT="${invalidAnchor.value}" ignored — ${invalidAnchor.problem}]`
46
+ : '';
47
+ if (reason === 'start-fallback' && ignoredBareMonomind) {
48
+ return {
49
+ name,
50
+ status: 'info',
51
+ message: `${root} (${reasonText[reason]}; ignored bare .monomind at ${ignoredBareMonomind} — add a project marker there, or set MONOMIND_PROJECT_ROOT, to adopt it)${invalidAnchorNote}`,
52
+ };
53
+ }
54
+ return { name, status: 'info', message: `${root} (${reasonText[reason]})${invalidAnchorNote}` };
55
+ }
56
+ export async function checkMemoryDatabase() {
57
+ const dbPaths = MEMORY_DB_CANDIDATE_PATHS;
58
+ for (const dbPath of dbPaths) {
59
+ if (existsSync(dbPath)) {
60
+ try {
61
+ const sizeMB = (statSync(dbPath).size / 1024 / 1024).toFixed(2);
62
+ return { name: 'Memory Database', status: 'pass', message: `${dbPath} (${sizeMB} MB)` };
63
+ }
64
+ catch {
65
+ return { name: 'Memory Database', status: 'warn', message: `${dbPath} (unable to stat)` };
66
+ }
67
+ }
68
+ }
69
+ return {
70
+ name: 'Memory Database',
71
+ status: 'warn',
72
+ message: 'Not initialized',
73
+ fix: 'monomind memory init',
74
+ };
75
+ }
76
+ /** Memory knowledge graph (cognee port): entities/relations/rules distilled
77
+ * from sessions and org runs. Informational — an empty graph on a fresh
78
+ * project is normal, so it never fails. */
79
+ export async function checkMemoryKnowledgeGraph() {
80
+ const name = 'Memory Knowledge Graph';
81
+ try {
82
+ const kg = await import('../memory/memory-kg.js');
83
+ const bridge = await import('../memory/memory-bridge.js');
84
+ const project = await kg.kgStats();
85
+ // Org KG facts are namespaced per org (kg:nodes:org:<name> etc.), so an
86
+ // unscoped kgStats against the org store reads the now-unused flat
87
+ // namespaces and reports zero for every org. Sum each org's own scope
88
+ // instead — the org store holds all of them, keyed by scope.
89
+ const orgDb = join(process.cwd(), '.monomind', 'org-memory');
90
+ let org = null;
91
+ if (existsSync(orgDb)) {
92
+ const { orgKgScope } = await import('../orgrt/org-memory.js');
93
+ const { listOrgConfigFiles } = await import('./org.js');
94
+ const orgsDir = join(process.cwd(), '.monomind', 'orgs');
95
+ const orgNames = existsSync(orgsDir)
96
+ ? listOrgConfigFiles(orgsDir).map((f) => f.replace(/\.json$/, ''))
97
+ : [];
98
+ org = { nodes: 0, edges: 0, rules: 0 };
99
+ for (const orgName of orgNames) {
100
+ const s = await kg.kgStats({ dbPath: orgDb, scope: orgKgScope(orgName) });
101
+ org.nodes += s.nodes;
102
+ org.edges += s.edges;
103
+ org.rules += s.rules;
104
+ }
105
+ }
106
+ await bridge.shutdownBridge().catch(() => {
107
+ /* best effort */
108
+ });
109
+ const total = project.nodes + (org?.nodes ?? 0);
110
+ const fmt = (s) => `${s.nodes}n/${s.edges}e/${s.rules}r`;
111
+ if (total === 0) {
112
+ return {
113
+ name,
114
+ status: 'warn',
115
+ message: 'Empty — sessions/org runs have not distilled knowledge yet',
116
+ fix: 'org runs call org_learn automatically; sessions use memory_kg_ingest',
117
+ };
118
+ }
119
+ return {
120
+ name,
121
+ status: 'pass',
122
+ message: `project ${fmt(project)}${org ? ` · org ${fmt(org)}` : ''}`,
123
+ };
124
+ }
125
+ catch (err) {
126
+ return {
127
+ name,
128
+ status: 'warn',
129
+ message: `Check failed: ${err instanceof Error ? err.message : String(err)}`,
130
+ };
131
+ }
132
+ }
133
+ /** Count live (non-tombstoned) ingested documents under a brain root, without
134
+ * creating the directory — `listDocuments` mkdir's its metadata dir, which
135
+ * would materialize an empty global brain just by running doctor. */
136
+ async function countBrainDocs(root) {
137
+ if (!existsSync(join(root, '.monomind', 'knowledge', 'doc-metadata.jsonl')))
138
+ return 0;
139
+ try {
140
+ const { listDocuments } = await import('../knowledge/document-pipeline.js');
141
+ return listDocuments(root).length;
142
+ }
143
+ catch {
144
+ return 0;
145
+ }
146
+ }
147
+ /** Second Brain: when there is any indexed knowledge — ingested docs in this
148
+ * project, the personal global brain, or the monograph god-node chunk —
149
+ * semantic search needs the local embedding model. Its absence is silent
150
+ * (search degrades to keyword matching), so surface it here instead. */
151
+ export async function checkSecondBrainModel() {
152
+ const name = 'Second Brain Model';
153
+ const { BRIDGE_EMBEDDING_MODEL, getGlobalBrainDir, getProjectRoot } = await import('../memory/memory-bridge.js');
154
+ const projectDocs = await countBrainDocs(getProjectRoot());
155
+ const globalDocs = await countBrainDocs(getGlobalBrainDir());
156
+ // chunks.jsonl holds the monograph god-node chunk — knowledge with no doc
157
+ // ingest. Unlike the document store it is written per-CWD by the session
158
+ // hook, not at the project root, so check both rather than assuming.
159
+ const chunksIn = (root) => existsSync(join(root, '.monomind', 'knowledge', 'chunks.jsonl'));
160
+ const hasChunks = chunksIn(getProjectRoot()) || chunksIn(process.cwd());
161
+ if (!projectDocs && !globalDocs && !hasChunks) {
162
+ return { name, status: 'pass', message: 'No knowledge indexed (nothing to check)' };
163
+ }
164
+ const indexed = [
165
+ projectDocs ? `${projectDocs} project doc${projectDocs === 1 ? '' : 's'}` : null,
166
+ globalDocs ? `${globalDocs} global doc${globalDocs === 1 ? '' : 's'}` : null,
167
+ !projectDocs && !globalDocs ? 'monograph god-nodes' : null,
168
+ ]
169
+ .filter(Boolean)
170
+ .join(' · ');
171
+ let entryPath = null;
172
+ try {
173
+ // exports map blocks package.json — resolve the entry file, then walk UP
174
+ // with path ops (no separator-sensitive regex: '/dist/'.replace broke on
175
+ // Windows paths, and any install layout without a dist segment).
176
+ // import.meta.resolve is missing on Node 20.0–20.5; fall back to CJS resolve.
177
+ const viaEsm = import.meta.resolve?.('@huggingface/transformers');
178
+ if (viaEsm)
179
+ entryPath = fileURLToPath(await viaEsm);
180
+ }
181
+ catch {
182
+ /* try CJS below */
183
+ }
184
+ if (!entryPath) {
185
+ try {
186
+ const { createRequire } = await import('node:module');
187
+ entryPath = createRequire(import.meta.url).resolve('@huggingface/transformers');
188
+ }
189
+ catch {
190
+ return {
191
+ name,
192
+ status: 'warn',
193
+ message: '@huggingface/transformers not installed — semantic search degraded to keyword matching',
194
+ fix: 'reinstall monomind (the model dependency is optional and may have failed to build)',
195
+ };
196
+ }
197
+ }
198
+ // Walk up from the entry file to the package root (the dir named 'transformers').
199
+ let pkgDir = dirname(entryPath);
200
+ while (pkgDir !== dirname(pkgDir) && !pkgDir.endsWith('transformers'))
201
+ pkgDir = dirname(pkgDir);
202
+ // The cached model is whichever one the bridge actually loads. This used to
203
+ // look for '.cache/Xenova', a model the bridge stopped using — so the check
204
+ // reported "not downloaded" with a fully provisioned cache sitting on disk.
205
+ const modelCache = join(pkgDir, '.cache', ...BRIDGE_EMBEDDING_MODEL.split('/'));
206
+ if (pkgDir.endsWith('transformers') && existsSync(modelCache)) {
207
+ return {
208
+ name,
209
+ status: 'pass',
210
+ message: `Local embedding model cached — semantic search active (${indexed})`,
211
+ };
212
+ }
213
+ return {
214
+ name,
215
+ status: 'warn',
216
+ message: 'Embedding model not downloaded yet — searches use keyword matching until it is',
217
+ // Query-time paths all pass local_files_only and never fetch; this is the
218
+ // one command that downloads the weights.
219
+ fix: 'run once while online: monomind doc eval --provision-model (downloads ~270MB locally, one time)',
220
+ };
221
+ }
222
+ /**
223
+ * AutoMem proficiency check — reports memory learning health
224
+ */
225
+ export async function checkMemoryProficiency() {
226
+ try {
227
+ const intelligenceMod = await import('../memory/intelligence.js');
228
+ const stats = intelligenceMod.getMemoryProficiencyStats();
229
+ const bankStats = intelligenceMod.getIntelligenceStats();
230
+ if (stats.totalDecisions === 0) {
231
+ return {
232
+ name: 'Memory Proficiency',
233
+ status: 'pass',
234
+ message: 'AutoMem active — no decisions recorded yet (builds up over sessions)',
235
+ };
236
+ }
237
+ const successPct = Math.round(stats.successRate * 100);
238
+ const hitPct = Math.round(stats.patternHitRate * 100);
239
+ const msg = `${stats.totalDecisions} decisions, ${successPct}% success, ${stats.proficiencyPatterns} patterns, ${hitPct}% hit rate (bank: ${bankStats.patternsLearned} total)`;
240
+ if (stats.successRate < 0.5) {
241
+ return { name: 'Memory Proficiency', status: 'warn', message: msg };
242
+ }
243
+ return { name: 'Memory Proficiency', status: 'pass', message: msg };
244
+ }
245
+ catch {
246
+ return {
247
+ name: 'Memory Proficiency',
248
+ status: 'warn',
249
+ message: 'Could not load intelligence module',
250
+ };
251
+ }
252
+ }
253
+ /** Second Brain document ingestion: whether the "documents" capability is
254
+ * active for this project. Read directly from capabilities.json rather than
255
+ * re-running the directory scan — doctor should report on what's actually
256
+ * activated, not re-detect. */
257
+ function isDocumentsCapabilityActive(cwd) {
258
+ try {
259
+ const capsPath = join(cwd, '.monomind', 'capabilities.json');
260
+ if (!existsSync(capsPath))
261
+ return false;
262
+ const parsed = JSON.parse(readFileSync(capsPath, 'utf8'));
263
+ return Array.isArray(parsed.active) && parsed.active.includes('documents');
264
+ }
265
+ catch {
266
+ return false;
267
+ }
268
+ }
269
+ /** Per-extractor health for Second Brain document ingestion (MEM-8/MEM-9):
270
+ * one check per format family (PDF, DOCX, XLSX/XLS/ODS, PPTX/ODT/ODP/EPUB,
271
+ * legacy DOC/PPT/Pages) instead of a single blanket "documents" check, so
272
+ * `doctor` can report exactly which formats are functional vs broken.
273
+ * No-op (empty array) when the documents capability isn't active — nothing
274
+ * to report if this project doesn't ingest documents. */
275
+ export async function checkDocumentExtractors() {
276
+ if (!isDocumentsCapabilityActive(process.cwd()))
277
+ return [];
278
+ try {
279
+ const { documentsCapability } = await import('../capabilities/cap-documents.js');
280
+ const checks = (await documentsCapability.healthChecks?.()) ?? [];
281
+ return checks.map((c) => ({
282
+ name: c.name,
283
+ status: c.status,
284
+ message: c.message,
285
+ fix: c.hint ?? c.fix,
286
+ }));
287
+ }
288
+ catch (err) {
289
+ return [
290
+ {
291
+ name: 'Document Extractors',
292
+ status: 'warn',
293
+ message: `Check failed: ${err instanceof Error ? err.message : String(err)}`,
294
+ },
295
+ ];
296
+ }
297
+ }
298
+ //# sourceMappingURL=doctor-memory-checks.js.map