monomind 1.18.11 → 1.18.12
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "monomind",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.12",
|
|
4
4
|
"description": "Monomind - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -1809,6 +1809,207 @@ const monographSuggestAutoTool = {
|
|
|
1809
1809
|
},
|
|
1810
1810
|
};
|
|
1811
1811
|
// ── Export all tools ──────────────────────────────────────────────────────────
|
|
1812
|
+
// ── monograph_dead_code ──────────────────────────────────────────────────────
|
|
1813
|
+
const monographDeadCodeTool = {
|
|
1814
|
+
name: 'monograph_dead_code',
|
|
1815
|
+
description: 'Detect dead code: exported functions with zero inbound references, files with no importers, and stale dist build artifacts. Returns structured JSON with candidates grouped by category. Always verify candidates with grep before deleting.',
|
|
1816
|
+
inputSchema: {
|
|
1817
|
+
type: 'object',
|
|
1818
|
+
properties: {
|
|
1819
|
+
path: { type: 'string', description: 'Absolute path to the repo (defaults to project cwd)' },
|
|
1820
|
+
categories: {
|
|
1821
|
+
type: 'array',
|
|
1822
|
+
items: { type: 'string', enum: ['dead-functions', 'orphan-files', 'stale-dist'] },
|
|
1823
|
+
description: 'Which categories to check (default: all three)',
|
|
1824
|
+
},
|
|
1825
|
+
},
|
|
1826
|
+
},
|
|
1827
|
+
handler: async (input) => {
|
|
1828
|
+
const { openDb } = await import('@monoes/monograph');
|
|
1829
|
+
const repoPath = input.path ?? getProjectCwd();
|
|
1830
|
+
const cats = input.categories ?? ['dead-functions', 'orphan-files', 'stale-dist'];
|
|
1831
|
+
const result = {};
|
|
1832
|
+
const dbPath = join(repoPath, '.monomind', 'monograph.db');
|
|
1833
|
+
let db = null;
|
|
1834
|
+
try {
|
|
1835
|
+
db = openDb(dbPath);
|
|
1836
|
+
}
|
|
1837
|
+
catch {
|
|
1838
|
+
return text(JSON.stringify({ error: 'No monograph index found. Run monograph_build first.' }));
|
|
1839
|
+
}
|
|
1840
|
+
try {
|
|
1841
|
+
if (cats.includes('dead-functions')) {
|
|
1842
|
+
const { detectDeadCodeNodes } = await import('@monoes/monograph');
|
|
1843
|
+
const { readFileSync } = await import('fs');
|
|
1844
|
+
const nodes = detectDeadCodeNodes(db);
|
|
1845
|
+
// Filter out stale graph nodes: verify the function name actually appears in the source file
|
|
1846
|
+
const verified = nodes.filter(n => {
|
|
1847
|
+
if (!n.filePath)
|
|
1848
|
+
return false;
|
|
1849
|
+
try {
|
|
1850
|
+
const content = readFileSync(join(repoPath, n.filePath), 'utf-8');
|
|
1851
|
+
return content.includes(n.name);
|
|
1852
|
+
}
|
|
1853
|
+
catch {
|
|
1854
|
+
return false;
|
|
1855
|
+
}
|
|
1856
|
+
});
|
|
1857
|
+
const staleCount = nodes.length - verified.length;
|
|
1858
|
+
result['dead-functions'] = {
|
|
1859
|
+
count: verified.length,
|
|
1860
|
+
candidates: verified.map(n => ({
|
|
1861
|
+
name: n.name,
|
|
1862
|
+
location: n.filePath ? (n.startLine ? `${n.filePath}:${n.startLine}` : n.filePath) : null,
|
|
1863
|
+
})),
|
|
1864
|
+
...(staleCount > 0 ? { staleIndexEntries: staleCount, note: 'Some graph entries reference deleted functions. Rebuild the index with monograph_build to clean up.' } : {}),
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
if (cats.includes('orphan-files')) {
|
|
1868
|
+
const rows = db.prepare(`
|
|
1869
|
+
SELECT n.name, n.file_path,
|
|
1870
|
+
(SELECT COUNT(*) FROM edges e WHERE e.source_id = n.id AND e.relation = 'IMPORTS') as imports_out,
|
|
1871
|
+
(SELECT COUNT(*) FROM edges e WHERE e.target_id = n.id AND e.relation = 'IMPORTS') as imported_by
|
|
1872
|
+
FROM nodes n
|
|
1873
|
+
WHERE n.label = 'File'
|
|
1874
|
+
AND (SELECT COUNT(*) FROM edges e WHERE e.target_id = n.id AND e.relation = 'IMPORTS') = 0
|
|
1875
|
+
AND n.file_path NOT LIKE '%test%'
|
|
1876
|
+
AND n.file_path NOT LIKE '%__tests__%'
|
|
1877
|
+
AND n.file_path NOT LIKE '%spec%'
|
|
1878
|
+
AND n.file_path NOT LIKE '%/index.%'
|
|
1879
|
+
AND n.file_path NOT LIKE 'bin/%'
|
|
1880
|
+
AND n.file_path NOT LIKE 'scripts/%'
|
|
1881
|
+
AND n.file_path NOT LIKE '%/cli.ts'
|
|
1882
|
+
AND n.file_path NOT LIKE '%/cli.js'
|
|
1883
|
+
AND n.file_path NOT LIKE '%/main.ts'
|
|
1884
|
+
AND n.file_path NOT LIKE '%/main.js'
|
|
1885
|
+
AND n.file_path NOT LIKE '%/dist/%'
|
|
1886
|
+
AND n.file_path NOT LIKE '%node_modules%'
|
|
1887
|
+
ORDER BY n.file_path
|
|
1888
|
+
`).all();
|
|
1889
|
+
const withOutbound = rows.filter((r) => r.imports_out > 0);
|
|
1890
|
+
const isolated = rows.filter((r) => r.imports_out === 0);
|
|
1891
|
+
result['orphan-files'] = {
|
|
1892
|
+
count: withOutbound.length,
|
|
1893
|
+
note: 'Files that import other modules but nothing imports them. May be lazy-loaded or dynamically imported — verify with grep.',
|
|
1894
|
+
candidates: withOutbound.map((r) => ({ file: r.file_path, outboundImports: r.imports_out })),
|
|
1895
|
+
...(isolated.length > 0 ? {
|
|
1896
|
+
isolated: {
|
|
1897
|
+
count: isolated.length,
|
|
1898
|
+
note: 'Files with zero edges in either direction — likely standalone scripts or entry points.',
|
|
1899
|
+
files: isolated.map((r) => r.file_path),
|
|
1900
|
+
},
|
|
1901
|
+
} : {}),
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
if (cats.includes('stale-dist')) {
|
|
1905
|
+
result['stale-dist'] = findStaleDist(repoPath);
|
|
1906
|
+
}
|
|
1907
|
+
return text(JSON.stringify(result, null, 2));
|
|
1908
|
+
}
|
|
1909
|
+
finally {
|
|
1910
|
+
db.close();
|
|
1911
|
+
}
|
|
1912
|
+
},
|
|
1913
|
+
};
|
|
1914
|
+
function findStaleDist(repoPath) {
|
|
1915
|
+
const { readdirSync, existsSync } = require('fs');
|
|
1916
|
+
const distSrc = join(repoPath, 'dist', 'src');
|
|
1917
|
+
const src = join(repoPath, 'src');
|
|
1918
|
+
// Scan a single package for stale dist artifacts
|
|
1919
|
+
const scanPkg = (pkgPath, pkgName) => {
|
|
1920
|
+
const pkgDistSrc = join(pkgPath, 'dist', 'src');
|
|
1921
|
+
const pkgSrc = join(pkgPath, 'src');
|
|
1922
|
+
if (!existsSync(pkgDistSrc) || !existsSync(pkgSrc))
|
|
1923
|
+
return null;
|
|
1924
|
+
const staleDirs = [];
|
|
1925
|
+
const staleFiles = [];
|
|
1926
|
+
let resourceForks = 0;
|
|
1927
|
+
try {
|
|
1928
|
+
const distDirs = readdirSync(pkgDistSrc, { withFileTypes: true })
|
|
1929
|
+
.filter(d => d.isDirectory() && !d.name.startsWith('.') && !d.name.startsWith('._'));
|
|
1930
|
+
const srcDirs = new Set(readdirSync(pkgSrc, { withFileTypes: true })
|
|
1931
|
+
.filter(d => d.isDirectory() && !d.name.startsWith('.'))
|
|
1932
|
+
.map(d => d.name));
|
|
1933
|
+
for (const d of distDirs) {
|
|
1934
|
+
if (!srcDirs.has(d.name))
|
|
1935
|
+
staleDirs.push(d.name);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
catch { /* skip */ }
|
|
1939
|
+
try {
|
|
1940
|
+
const distFiles = readdirSync(pkgDistSrc)
|
|
1941
|
+
.filter(f => f.endsWith('.js') && !f.startsWith('.') && !f.startsWith('._'));
|
|
1942
|
+
for (const f of distFiles) {
|
|
1943
|
+
const tsName = f.replace(/\.js$/, '.ts');
|
|
1944
|
+
if (!existsSync(join(pkgSrc, tsName)))
|
|
1945
|
+
staleFiles.push(f);
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
catch { /* skip */ }
|
|
1949
|
+
// Count macOS resource fork files
|
|
1950
|
+
const countRF = (dir) => {
|
|
1951
|
+
try {
|
|
1952
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
1953
|
+
if (entry.name.startsWith('._'))
|
|
1954
|
+
resourceForks++;
|
|
1955
|
+
else if (entry.isDirectory())
|
|
1956
|
+
countRF(join(dir, entry.name));
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
catch { /* skip */ }
|
|
1960
|
+
};
|
|
1961
|
+
countRF(pkgDistSrc);
|
|
1962
|
+
if (staleDirs.length === 0 && staleFiles.length === 0 && resourceForks === 0)
|
|
1963
|
+
return null;
|
|
1964
|
+
return {
|
|
1965
|
+
package: pkgName,
|
|
1966
|
+
staleDirs,
|
|
1967
|
+
staleFiles,
|
|
1968
|
+
...(resourceForks > 0 ? { macosResourceForks: resourceForks } : {}),
|
|
1969
|
+
};
|
|
1970
|
+
};
|
|
1971
|
+
// Single-package repo
|
|
1972
|
+
if (existsSync(distSrc) && existsSync(src)) {
|
|
1973
|
+
const finding = scanPkg(repoPath, '.');
|
|
1974
|
+
return {
|
|
1975
|
+
count: finding ? finding.staleDirs.length + finding.staleFiles.length : 0,
|
|
1976
|
+
note: 'Directories/files in dist/src/ with no corresponding source. Fix: rm -rf dist && npm run build.',
|
|
1977
|
+
...(finding ? { findings: [finding] } : {}),
|
|
1978
|
+
};
|
|
1979
|
+
}
|
|
1980
|
+
// Monorepo: scan all packages
|
|
1981
|
+
const packagesDir = join(repoPath, 'packages');
|
|
1982
|
+
if (!existsSync(packagesDir))
|
|
1983
|
+
return { count: 0, note: 'No dist/src or packages/ found' };
|
|
1984
|
+
const findings = [];
|
|
1985
|
+
try {
|
|
1986
|
+
for (const scope of readdirSync(packagesDir, { withFileTypes: true })) {
|
|
1987
|
+
if (!scope.isDirectory())
|
|
1988
|
+
continue;
|
|
1989
|
+
const scopeDir = join(packagesDir, scope.name);
|
|
1990
|
+
if (scope.name.startsWith('@')) {
|
|
1991
|
+
for (const pkg of readdirSync(scopeDir, { withFileTypes: true })) {
|
|
1992
|
+
if (!pkg.isDirectory())
|
|
1993
|
+
continue;
|
|
1994
|
+
const f = scanPkg(join(scopeDir, pkg.name), `${scope.name}/${pkg.name}`);
|
|
1995
|
+
if (f)
|
|
1996
|
+
findings.push(f);
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
else {
|
|
2000
|
+
const f = scanPkg(scopeDir, scope.name);
|
|
2001
|
+
if (f)
|
|
2002
|
+
findings.push(f);
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
catch { /* skip */ }
|
|
2007
|
+
return {
|
|
2008
|
+
count: findings.reduce((s, f) => s + (f.staleDirs?.length ?? 0) + (f.staleFiles?.length ?? 0), 0),
|
|
2009
|
+
note: 'Directories/files in dist/src/ with no corresponding source. Fix: rm -rf dist && npm run build.',
|
|
2010
|
+
findings,
|
|
2011
|
+
};
|
|
2012
|
+
}
|
|
1812
2013
|
export const monographTools = [
|
|
1813
2014
|
monographBuildTool,
|
|
1814
2015
|
monographQueryTool,
|
|
@@ -1854,5 +2055,6 @@ export const monographTools = [
|
|
|
1854
2055
|
monographListReposTool,
|
|
1855
2056
|
monographGroupContractsTool,
|
|
1856
2057
|
monographGroupStatusTool,
|
|
2058
|
+
monographDeadCodeTool,
|
|
1857
2059
|
];
|
|
1858
2060
|
//# sourceMappingURL=monograph-tools.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monoes/monomindcli",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Monomind CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|