@massu/core 1.2.1 → 1.3.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.
- package/README.md +40 -0
- package/commands/README.md +122 -0
- package/commands/massu-deploy.python.md +200 -0
- package/commands/massu-scaffold-page.md +172 -59
- package/commands/massu-scaffold-page.swift.md +121 -0
- package/commands/massu-scaffold-router.python.md +143 -0
- package/dist/cli.js +482 -223
- package/dist/hooks/auto-learning-pipeline.js +7 -4
- package/dist/hooks/classify-failure.js +7 -4
- package/dist/hooks/cost-tracker.js +7 -4
- package/dist/hooks/fix-detector.js +7 -4
- package/dist/hooks/incident-pipeline.js +7 -4
- package/dist/hooks/post-edit-context.js +7 -4
- package/dist/hooks/post-tool-use.js +7 -4
- package/dist/hooks/pre-compact.js +7 -4
- package/dist/hooks/pre-delete-check.js +7 -4
- package/dist/hooks/quality-event.js +7 -4
- package/dist/hooks/rule-enforcement-pipeline.js +7 -4
- package/dist/hooks/session-end.js +7 -4
- package/dist/hooks/session-start.js +7 -4
- package/dist/hooks/user-prompt.js +7 -4
- package/package.json +1 -1
- package/src/cli.ts +6 -0
- package/src/commands/install-commands.ts +366 -42
- package/src/commands/show-template.ts +65 -0
- package/src/config.ts +6 -3
package/dist/cli.js
CHANGED
|
@@ -118,13 +118,16 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
118
118
|
name: parsed.project.name,
|
|
119
119
|
root: projectRoot
|
|
120
120
|
},
|
|
121
|
+
// Spread `fw` first so zod-`.passthrough()` extras (e.g., `framework.swift`,
|
|
122
|
+
// `framework.python`) survive into the consumer-visible Config. Then override
|
|
123
|
+
// the v2-backcompat-mirrored router/orm/ui values. Without the spread, the
|
|
124
|
+
// variant-resolution `pickVariant` (install-commands.ts) cannot see the
|
|
125
|
+
// top-level passthrough language blocks.
|
|
121
126
|
framework: {
|
|
122
|
-
|
|
127
|
+
...fw,
|
|
123
128
|
router,
|
|
124
129
|
orm,
|
|
125
|
-
ui
|
|
126
|
-
primary: fw.primary,
|
|
127
|
-
languages: fw.languages
|
|
130
|
+
ui
|
|
128
131
|
},
|
|
129
132
|
paths: parsed.paths,
|
|
130
133
|
toolPrefix: parsed.toolPrefix,
|
|
@@ -1681,15 +1684,30 @@ var init_memory_file_ingest = __esm({
|
|
|
1681
1684
|
// src/commands/install-commands.ts
|
|
1682
1685
|
var install_commands_exports = {};
|
|
1683
1686
|
__export(install_commands_exports, {
|
|
1687
|
+
hashContent: () => hashContent,
|
|
1684
1688
|
installAll: () => installAll,
|
|
1685
1689
|
installCommands: () => installCommands,
|
|
1690
|
+
loadManifest: () => loadManifest,
|
|
1691
|
+
pickVariant: () => pickVariant,
|
|
1686
1692
|
resolveAssetDir: () => resolveAssetDir,
|
|
1687
1693
|
resolveCommandsDir: () => resolveCommandsDir,
|
|
1688
|
-
runInstallCommands: () => runInstallCommands
|
|
1694
|
+
runInstallCommands: () => runInstallCommands,
|
|
1695
|
+
runWithManifest: () => runWithManifest,
|
|
1696
|
+
saveManifest: () => saveManifest,
|
|
1697
|
+
syncDirectory: () => syncDirectory
|
|
1689
1698
|
});
|
|
1690
|
-
import {
|
|
1691
|
-
|
|
1699
|
+
import {
|
|
1700
|
+
existsSync as existsSync4,
|
|
1701
|
+
readFileSync as readFileSync3,
|
|
1702
|
+
writeFileSync,
|
|
1703
|
+
mkdirSync as mkdirSync2,
|
|
1704
|
+
readdirSync as readdirSync2,
|
|
1705
|
+
statSync,
|
|
1706
|
+
renameSync
|
|
1707
|
+
} from "fs";
|
|
1708
|
+
import { resolve as resolve3, dirname as dirname3, join as join2 } from "path";
|
|
1692
1709
|
import { fileURLToPath } from "url";
|
|
1710
|
+
import { createHash } from "crypto";
|
|
1693
1711
|
function resolveAssetDir(assetName) {
|
|
1694
1712
|
const cwd = process.cwd();
|
|
1695
1713
|
const nodeModulesPath = resolve3(cwd, "node_modules/@massu/core", assetName);
|
|
@@ -1709,42 +1727,189 @@ function resolveAssetDir(assetName) {
|
|
|
1709
1727
|
function resolveCommandsDir() {
|
|
1710
1728
|
return resolveAssetDir("commands");
|
|
1711
1729
|
}
|
|
1712
|
-
function
|
|
1713
|
-
|
|
1730
|
+
function hashContent(content) {
|
|
1731
|
+
return createHash("sha256").update(content, "utf-8").digest("hex");
|
|
1732
|
+
}
|
|
1733
|
+
function loadManifest(claudeDir) {
|
|
1734
|
+
const path = resolve3(claudeDir, MANIFEST_RELPATH);
|
|
1735
|
+
if (!existsSync4(path)) {
|
|
1736
|
+
return emptyManifest();
|
|
1737
|
+
}
|
|
1738
|
+
try {
|
|
1739
|
+
const raw = readFileSync3(path, "utf-8");
|
|
1740
|
+
const parsed = JSON.parse(raw);
|
|
1741
|
+
if (!parsed || typeof parsed !== "object" || !parsed.entries) {
|
|
1742
|
+
return emptyManifest();
|
|
1743
|
+
}
|
|
1744
|
+
return parsed;
|
|
1745
|
+
} catch {
|
|
1746
|
+
return emptyManifest();
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
function saveManifest(claudeDir, manifest) {
|
|
1750
|
+
const dir = resolve3(claudeDir, ".massu");
|
|
1751
|
+
if (!existsSync4(dir)) {
|
|
1752
|
+
mkdirSync2(dir, { recursive: true });
|
|
1753
|
+
}
|
|
1754
|
+
const finalPath = resolve3(dir, "install-manifest.json");
|
|
1755
|
+
const tempPath = finalPath + ".tmp";
|
|
1756
|
+
manifest.generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1757
|
+
writeFileSync(tempPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
1758
|
+
renameSync(tempPath, finalPath);
|
|
1759
|
+
}
|
|
1760
|
+
function emptyManifest() {
|
|
1761
|
+
return {
|
|
1762
|
+
version: MANIFEST_VERSION,
|
|
1763
|
+
generatedBy: "@massu/core",
|
|
1764
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1765
|
+
entries: {}
|
|
1766
|
+
};
|
|
1767
|
+
}
|
|
1768
|
+
function runWithManifest(claudeDir, fn) {
|
|
1769
|
+
const manifest = loadManifest(claudeDir);
|
|
1770
|
+
const result = fn(manifest);
|
|
1771
|
+
saveManifest(claudeDir, manifest);
|
|
1772
|
+
return result;
|
|
1773
|
+
}
|
|
1774
|
+
function pickVariant(baseName, sourceDir, framework) {
|
|
1775
|
+
const candidates = [];
|
|
1776
|
+
const primary = framework.primary ?? framework.type;
|
|
1777
|
+
if (primary && primary !== "multi") {
|
|
1778
|
+
candidates.push(primary);
|
|
1779
|
+
}
|
|
1780
|
+
if (framework.languages) {
|
|
1781
|
+
for (const lang of Object.keys(framework.languages)) {
|
|
1782
|
+
const entry = framework.languages[lang];
|
|
1783
|
+
if (entry && typeof entry.framework === "string" && entry.framework.length > 0) {
|
|
1784
|
+
if (!candidates.includes(lang)) {
|
|
1785
|
+
candidates.push(lang);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
const passthrough = framework;
|
|
1791
|
+
for (const lang of PASSTHROUGH_LANG_KEYS) {
|
|
1792
|
+
if (candidates.includes(lang)) continue;
|
|
1793
|
+
const block = passthrough[lang];
|
|
1794
|
+
if (block && typeof block === "object") {
|
|
1795
|
+
const fw = block.framework;
|
|
1796
|
+
if (typeof fw === "string" && fw.length > 0) {
|
|
1797
|
+
candidates.push(lang);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
for (const cand of candidates) {
|
|
1802
|
+
const path = resolve3(sourceDir, `${baseName}.${cand}.md`);
|
|
1803
|
+
if (existsSync4(path)) {
|
|
1804
|
+
return { kind: "hit", suffix: `.${cand}` };
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
const defaultPath = resolve3(sourceDir, `${baseName}.md`);
|
|
1808
|
+
if (existsSync4(defaultPath)) {
|
|
1809
|
+
return { kind: "hit", suffix: "" };
|
|
1810
|
+
}
|
|
1811
|
+
if (framework.type === "multi" && !framework.primary) {
|
|
1812
|
+
process.stderr.write(
|
|
1813
|
+
"massu: warning - framework.type=multi but framework.primary is undefined; falling back to default templates\n"
|
|
1814
|
+
);
|
|
1815
|
+
return { kind: "fallback", reason: "multi-without-primary" };
|
|
1816
|
+
}
|
|
1817
|
+
return { kind: "miss" };
|
|
1818
|
+
}
|
|
1819
|
+
function isVariantFilename(entry) {
|
|
1820
|
+
return /^[^.]+\.[^.]+\.md$/.test(entry);
|
|
1821
|
+
}
|
|
1822
|
+
function syncDirectory(sourceDir, targetDir, framework, manifest, manifestKeyPrefix, topLevel = true) {
|
|
1823
|
+
const stats = { installed: 0, updated: 0, skipped: 0, kept: 0 };
|
|
1714
1824
|
if (!existsSync4(targetDir)) {
|
|
1715
1825
|
mkdirSync2(targetDir, { recursive: true });
|
|
1716
1826
|
}
|
|
1717
1827
|
const entries = readdirSync2(sourceDir);
|
|
1718
1828
|
for (const entry of entries) {
|
|
1719
1829
|
const sourcePath = resolve3(sourceDir, entry);
|
|
1720
|
-
const targetPath = resolve3(targetDir, entry);
|
|
1721
1830
|
const entryStat = statSync(sourcePath);
|
|
1722
1831
|
if (entryStat.isDirectory()) {
|
|
1723
|
-
const
|
|
1832
|
+
const subTargetDir = resolve3(targetDir, entry);
|
|
1833
|
+
const subPrefix = manifestKeyPrefix === "" ? entry : `${manifestKeyPrefix}/${entry}`;
|
|
1834
|
+
const subStats = syncDirectory(
|
|
1835
|
+
sourcePath,
|
|
1836
|
+
subTargetDir,
|
|
1837
|
+
framework,
|
|
1838
|
+
manifest,
|
|
1839
|
+
subPrefix,
|
|
1840
|
+
false
|
|
1841
|
+
);
|
|
1724
1842
|
stats.installed += subStats.installed;
|
|
1725
1843
|
stats.updated += subStats.updated;
|
|
1726
1844
|
stats.skipped += subStats.skipped;
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
writeFileSync(targetPath, sourceContent, "utf-8");
|
|
1739
|
-
stats.installed++;
|
|
1845
|
+
stats.kept += subStats.kept;
|
|
1846
|
+
continue;
|
|
1847
|
+
}
|
|
1848
|
+
if (!entry.endsWith(".md")) continue;
|
|
1849
|
+
let sourceFilename = entry;
|
|
1850
|
+
let baseName = entry.slice(0, -".md".length);
|
|
1851
|
+
if (topLevel) {
|
|
1852
|
+
if (isVariantFilename(entry)) continue;
|
|
1853
|
+
const choice = pickVariant(baseName, sourceDir, framework);
|
|
1854
|
+
if (choice.kind === "miss") {
|
|
1855
|
+
continue;
|
|
1740
1856
|
}
|
|
1857
|
+
const suffix = choice.kind === "hit" ? choice.suffix : "";
|
|
1858
|
+
sourceFilename = suffix === "" ? `${baseName}.md` : `${baseName}${suffix}.md`;
|
|
1859
|
+
}
|
|
1860
|
+
const resolvedSourcePath = resolve3(sourceDir, sourceFilename);
|
|
1861
|
+
if (!existsSync4(resolvedSourcePath)) {
|
|
1862
|
+
continue;
|
|
1863
|
+
}
|
|
1864
|
+
const targetFilename = topLevel ? `${baseName}.md` : entry;
|
|
1865
|
+
const targetPath = resolve3(targetDir, targetFilename);
|
|
1866
|
+
const sourceContent = readFileSync3(resolvedSourcePath, "utf-8");
|
|
1867
|
+
const sourceHash = hashContent(sourceContent);
|
|
1868
|
+
const manifestKey = manifestKeyPrefix === "" ? targetFilename : `${manifestKeyPrefix}/${targetFilename}`;
|
|
1869
|
+
const lastInstalledHash = manifest.entries[manifestKey];
|
|
1870
|
+
if (existsSync4(targetPath)) {
|
|
1871
|
+
const existingContent = readFileSync3(targetPath, "utf-8");
|
|
1872
|
+
const existingHash = hashContent(existingContent);
|
|
1873
|
+
if (existingHash === sourceHash) {
|
|
1874
|
+
manifest.entries[manifestKey] = sourceHash;
|
|
1875
|
+
stats.skipped++;
|
|
1876
|
+
continue;
|
|
1877
|
+
}
|
|
1878
|
+
if (lastInstalledHash === void 0) {
|
|
1879
|
+
manifest.entries[manifestKey] = existingHash;
|
|
1880
|
+
process.stderr.write(
|
|
1881
|
+
`First-install heuristic: keeping existing ${targetPath} (differs from upstream).
|
|
1882
|
+
To accept upstream: rm ${targetPath} && npx massu install-commands
|
|
1883
|
+
`
|
|
1884
|
+
);
|
|
1885
|
+
stats.kept++;
|
|
1886
|
+
continue;
|
|
1887
|
+
}
|
|
1888
|
+
if (existingHash !== lastInstalledHash) {
|
|
1889
|
+
process.stderr.write(
|
|
1890
|
+
`${targetFilename} has local edits - kept your version.
|
|
1891
|
+
To accept upstream: rm ${targetPath} && npx massu install-commands
|
|
1892
|
+
To diff: diff ${targetPath} <(npx massu show-template ${baseName})
|
|
1893
|
+
`
|
|
1894
|
+
);
|
|
1895
|
+
stats.kept++;
|
|
1896
|
+
continue;
|
|
1897
|
+
}
|
|
1898
|
+
writeFileSync(targetPath, sourceContent, "utf-8");
|
|
1899
|
+
manifest.entries[manifestKey] = sourceHash;
|
|
1900
|
+
stats.updated++;
|
|
1901
|
+
} else {
|
|
1902
|
+
writeFileSync(targetPath, sourceContent, "utf-8");
|
|
1903
|
+
manifest.entries[manifestKey] = sourceHash;
|
|
1904
|
+
stats.installed++;
|
|
1741
1905
|
}
|
|
1742
1906
|
}
|
|
1743
1907
|
return stats;
|
|
1744
1908
|
}
|
|
1745
1909
|
function installCommands(projectRoot) {
|
|
1746
1910
|
const claudeDirName = getConfig().conventions?.claudeDirName ?? ".claude";
|
|
1747
|
-
const
|
|
1911
|
+
const claudeDir = resolve3(projectRoot, claudeDirName);
|
|
1912
|
+
const targetDir = resolve3(claudeDir, "commands");
|
|
1748
1913
|
if (!existsSync4(targetDir)) {
|
|
1749
1914
|
mkdirSync2(targetDir, { recursive: true });
|
|
1750
1915
|
}
|
|
@@ -1752,9 +1917,13 @@ function installCommands(projectRoot) {
|
|
|
1752
1917
|
if (!sourceDir) {
|
|
1753
1918
|
console.error(" ERROR: Could not find massu commands directory.");
|
|
1754
1919
|
console.error(" Try reinstalling: npm install @massu/core");
|
|
1755
|
-
return { installed: 0, updated: 0, skipped: 0, commandsDir: targetDir };
|
|
1920
|
+
return { installed: 0, updated: 0, skipped: 0, kept: 0, commandsDir: targetDir };
|
|
1756
1921
|
}
|
|
1757
|
-
const
|
|
1922
|
+
const framework = getConfig().framework;
|
|
1923
|
+
const stats = runWithManifest(
|
|
1924
|
+
claudeDir,
|
|
1925
|
+
(manifest) => syncDirectory(sourceDir, targetDir, framework, manifest, "commands", true)
|
|
1926
|
+
);
|
|
1758
1927
|
return { ...stats, commandsDir: targetDir };
|
|
1759
1928
|
}
|
|
1760
1929
|
function installAll(projectRoot) {
|
|
@@ -1764,19 +1933,36 @@ function installAll(projectRoot) {
|
|
|
1764
1933
|
let totalInstalled = 0;
|
|
1765
1934
|
let totalUpdated = 0;
|
|
1766
1935
|
let totalSkipped = 0;
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1936
|
+
let totalKept = 0;
|
|
1937
|
+
const framework = getConfig().framework;
|
|
1938
|
+
runWithManifest(claudeDir, (manifest) => {
|
|
1939
|
+
for (const assetType of ASSET_TYPES) {
|
|
1940
|
+
const sourceDir = resolveAssetDir(assetType.name);
|
|
1941
|
+
if (!sourceDir) continue;
|
|
1942
|
+
const targetDir = resolve3(claudeDir, assetType.targetSubdir);
|
|
1943
|
+
const stats = syncDirectory(
|
|
1944
|
+
sourceDir,
|
|
1945
|
+
targetDir,
|
|
1946
|
+
framework,
|
|
1947
|
+
manifest,
|
|
1948
|
+
assetType.targetSubdir,
|
|
1949
|
+
true
|
|
1950
|
+
);
|
|
1951
|
+
assets[assetType.name] = stats;
|
|
1952
|
+
totalInstalled += stats.installed;
|
|
1953
|
+
totalUpdated += stats.updated;
|
|
1954
|
+
totalSkipped += stats.skipped;
|
|
1955
|
+
totalKept += stats.kept;
|
|
1771
1956
|
}
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
assets
|
|
1775
|
-
totalInstalled
|
|
1776
|
-
totalUpdated
|
|
1777
|
-
totalSkipped
|
|
1778
|
-
|
|
1779
|
-
|
|
1957
|
+
});
|
|
1958
|
+
return {
|
|
1959
|
+
assets,
|
|
1960
|
+
totalInstalled,
|
|
1961
|
+
totalUpdated,
|
|
1962
|
+
totalSkipped,
|
|
1963
|
+
totalKept,
|
|
1964
|
+
claudeDir
|
|
1965
|
+
};
|
|
1780
1966
|
}
|
|
1781
1967
|
async function runInstallCommands() {
|
|
1782
1968
|
const projectRoot = process.cwd();
|
|
@@ -1790,23 +1976,29 @@ async function runInstallCommands() {
|
|
|
1790
1976
|
if (!stats) {
|
|
1791
1977
|
continue;
|
|
1792
1978
|
}
|
|
1793
|
-
const total = stats.installed + stats.updated + stats.skipped;
|
|
1979
|
+
const total = stats.installed + stats.updated + stats.skipped + stats.kept;
|
|
1794
1980
|
if (total === 0) continue;
|
|
1795
1981
|
const parts = [];
|
|
1796
1982
|
if (stats.installed > 0) parts.push(`${stats.installed} new`);
|
|
1797
1983
|
if (stats.updated > 0) parts.push(`${stats.updated} updated`);
|
|
1798
1984
|
if (stats.skipped > 0) parts.push(`${stats.skipped} current`);
|
|
1985
|
+
if (stats.kept > 0) parts.push(`${stats.kept} kept (local edits)`);
|
|
1799
1986
|
const description = assetType.description;
|
|
1800
1987
|
console.log(` ${description}: ${parts.join(", ")} (${total} total)`);
|
|
1801
1988
|
}
|
|
1802
|
-
const grandTotal = result.totalInstalled + result.totalUpdated + result.totalSkipped;
|
|
1989
|
+
const grandTotal = result.totalInstalled + result.totalUpdated + result.totalSkipped + result.totalKept;
|
|
1803
1990
|
console.log("");
|
|
1804
1991
|
console.log(` ${grandTotal} total files synced to ${result.claudeDir}`);
|
|
1992
|
+
if (result.totalKept > 0) {
|
|
1993
|
+
console.log(
|
|
1994
|
+
` ${result.totalKept} file(s) had local edits and were preserved (see stderr above).`
|
|
1995
|
+
);
|
|
1996
|
+
}
|
|
1805
1997
|
console.log("");
|
|
1806
1998
|
console.log(" Restart your Claude Code session to use them.");
|
|
1807
1999
|
console.log("");
|
|
1808
2000
|
}
|
|
1809
|
-
var __filename, __dirname, ASSET_TYPES;
|
|
2001
|
+
var __filename, __dirname, ASSET_TYPES, MANIFEST_VERSION, MANIFEST_RELPATH, PASSTHROUGH_LANG_KEYS;
|
|
1810
2002
|
var init_install_commands = __esm({
|
|
1811
2003
|
"src/commands/install-commands.ts"() {
|
|
1812
2004
|
"use strict";
|
|
@@ -1820,6 +2012,16 @@ var init_install_commands = __esm({
|
|
|
1820
2012
|
{ name: "protocols", targetSubdir: "protocols", description: "protocol files" },
|
|
1821
2013
|
{ name: "reference", targetSubdir: "reference", description: "reference files" }
|
|
1822
2014
|
];
|
|
2015
|
+
MANIFEST_VERSION = 1;
|
|
2016
|
+
MANIFEST_RELPATH = join2(".massu", "install-manifest.json");
|
|
2017
|
+
PASSTHROUGH_LANG_KEYS = [
|
|
2018
|
+
"typescript",
|
|
2019
|
+
"javascript",
|
|
2020
|
+
"python",
|
|
2021
|
+
"swift",
|
|
2022
|
+
"rust",
|
|
2023
|
+
"go"
|
|
2024
|
+
];
|
|
1823
2025
|
}
|
|
1824
2026
|
});
|
|
1825
2027
|
|
|
@@ -7798,41 +8000,41 @@ var require_queue = __commonJS({
|
|
|
7798
8000
|
queue.drained = drained;
|
|
7799
8001
|
return queue;
|
|
7800
8002
|
function push(value) {
|
|
7801
|
-
var p19 = new Promise(function(
|
|
8003
|
+
var p19 = new Promise(function(resolve26, reject) {
|
|
7802
8004
|
pushCb(value, function(err, result) {
|
|
7803
8005
|
if (err) {
|
|
7804
8006
|
reject(err);
|
|
7805
8007
|
return;
|
|
7806
8008
|
}
|
|
7807
|
-
|
|
8009
|
+
resolve26(result);
|
|
7808
8010
|
});
|
|
7809
8011
|
});
|
|
7810
8012
|
p19.catch(noop);
|
|
7811
8013
|
return p19;
|
|
7812
8014
|
}
|
|
7813
8015
|
function unshift(value) {
|
|
7814
|
-
var p19 = new Promise(function(
|
|
8016
|
+
var p19 = new Promise(function(resolve26, reject) {
|
|
7815
8017
|
unshiftCb(value, function(err, result) {
|
|
7816
8018
|
if (err) {
|
|
7817
8019
|
reject(err);
|
|
7818
8020
|
return;
|
|
7819
8021
|
}
|
|
7820
|
-
|
|
8022
|
+
resolve26(result);
|
|
7821
8023
|
});
|
|
7822
8024
|
});
|
|
7823
8025
|
p19.catch(noop);
|
|
7824
8026
|
return p19;
|
|
7825
8027
|
}
|
|
7826
8028
|
function drained() {
|
|
7827
|
-
var p19 = new Promise(function(
|
|
8029
|
+
var p19 = new Promise(function(resolve26) {
|
|
7828
8030
|
process.nextTick(function() {
|
|
7829
8031
|
if (queue.idle()) {
|
|
7830
|
-
|
|
8032
|
+
resolve26();
|
|
7831
8033
|
} else {
|
|
7832
8034
|
var previousDrain = queue.drain;
|
|
7833
8035
|
queue.drain = function() {
|
|
7834
8036
|
if (typeof previousDrain === "function") previousDrain();
|
|
7835
|
-
|
|
8037
|
+
resolve26();
|
|
7836
8038
|
queue.drain = previousDrain;
|
|
7837
8039
|
};
|
|
7838
8040
|
}
|
|
@@ -8318,9 +8520,9 @@ var require_stream3 = __commonJS({
|
|
|
8318
8520
|
});
|
|
8319
8521
|
}
|
|
8320
8522
|
_getStat(filepath) {
|
|
8321
|
-
return new Promise((
|
|
8523
|
+
return new Promise((resolve26, reject) => {
|
|
8322
8524
|
this._stat(filepath, this._fsStatSettings, (error, stats) => {
|
|
8323
|
-
return error === null ?
|
|
8525
|
+
return error === null ? resolve26(stats) : reject(error);
|
|
8324
8526
|
});
|
|
8325
8527
|
});
|
|
8326
8528
|
}
|
|
@@ -8344,10 +8546,10 @@ var require_async5 = __commonJS({
|
|
|
8344
8546
|
this._readerStream = new stream_1.default(this._settings);
|
|
8345
8547
|
}
|
|
8346
8548
|
dynamic(root, options) {
|
|
8347
|
-
return new Promise((
|
|
8549
|
+
return new Promise((resolve26, reject) => {
|
|
8348
8550
|
this._walkAsync(root, options, (error, entries) => {
|
|
8349
8551
|
if (error === null) {
|
|
8350
|
-
|
|
8552
|
+
resolve26(entries);
|
|
8351
8553
|
} else {
|
|
8352
8554
|
reject(error);
|
|
8353
8555
|
}
|
|
@@ -8357,10 +8559,10 @@ var require_async5 = __commonJS({
|
|
|
8357
8559
|
async static(patterns, options) {
|
|
8358
8560
|
const entries = [];
|
|
8359
8561
|
const stream = this._readerStream.static(patterns, options);
|
|
8360
|
-
return new Promise((
|
|
8562
|
+
return new Promise((resolve26, reject) => {
|
|
8361
8563
|
stream.once("error", reject);
|
|
8362
8564
|
stream.on("data", (entry) => entries.push(entry));
|
|
8363
|
-
stream.once("end", () =>
|
|
8565
|
+
stream.once("end", () => resolve26(entries));
|
|
8364
8566
|
});
|
|
8365
8567
|
}
|
|
8366
8568
|
};
|
|
@@ -9697,7 +9899,7 @@ var init_detect = __esm({
|
|
|
9697
9899
|
});
|
|
9698
9900
|
|
|
9699
9901
|
// src/detect/drift.ts
|
|
9700
|
-
import { createHash } from "crypto";
|
|
9902
|
+
import { createHash as createHash2 } from "crypto";
|
|
9701
9903
|
function summarizeDetection(det) {
|
|
9702
9904
|
const languages = Array.from(new Set(det.manifests.map((m3) => m3.language))).sort();
|
|
9703
9905
|
const frameworks = {};
|
|
@@ -9728,7 +9930,7 @@ function summarizeDetection(det) {
|
|
|
9728
9930
|
function computeFingerprint(det) {
|
|
9729
9931
|
const data = summarizeDetection(det);
|
|
9730
9932
|
const stable = JSON.stringify(data, Object.keys(data).sort());
|
|
9731
|
-
return
|
|
9933
|
+
return createHash2("sha256").update(stable).digest("hex");
|
|
9732
9934
|
}
|
|
9733
9935
|
function stringOf(v3) {
|
|
9734
9936
|
if (typeof v3 === "string") return v3;
|
|
@@ -10886,7 +11088,7 @@ __export(init_exports, {
|
|
|
10886
11088
|
validateWrittenConfig: () => validateWrittenConfig,
|
|
10887
11089
|
writeConfigAtomic: () => writeConfigAtomic
|
|
10888
11090
|
});
|
|
10889
|
-
import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync6, renameSync, rmSync, statSync as statSync4, chmodSync } from "fs";
|
|
11091
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync6, renameSync as renameSync2, rmSync, statSync as statSync4, chmodSync } from "fs";
|
|
10890
11092
|
import { resolve as resolve5, basename as basename2, dirname as dirname4 } from "path";
|
|
10891
11093
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
10892
11094
|
import { homedir as homedir2 } from "os";
|
|
@@ -11208,7 +11410,7 @@ function writeConfigAtomic(configPath, content) {
|
|
|
11208
11410
|
if (parsed === null || typeof parsed !== "object") {
|
|
11209
11411
|
throw new Error("Generated config is not a valid YAML object");
|
|
11210
11412
|
}
|
|
11211
|
-
|
|
11413
|
+
renameSync2(tmpPath, configPath);
|
|
11212
11414
|
if (existingMode !== void 0) {
|
|
11213
11415
|
try {
|
|
11214
11416
|
chmodSync(configPath, existingMode);
|
|
@@ -11786,7 +11988,7 @@ var init_init = __esm({
|
|
|
11786
11988
|
});
|
|
11787
11989
|
|
|
11788
11990
|
// src/license.ts
|
|
11789
|
-
import { createHash as
|
|
11991
|
+
import { createHash as createHash3 } from "crypto";
|
|
11790
11992
|
function tierLevel(tier) {
|
|
11791
11993
|
return TIER_LEVELS[tier] ?? 0;
|
|
11792
11994
|
}
|
|
@@ -11811,7 +12013,7 @@ function annotateToolDefinitions(defs) {
|
|
|
11811
12013
|
});
|
|
11812
12014
|
}
|
|
11813
12015
|
async function validateLicense(apiKey) {
|
|
11814
|
-
const keyHash =
|
|
12016
|
+
const keyHash = createHash3("sha256").update(apiKey).digest("hex");
|
|
11815
12017
|
const memDb = getMemoryDb();
|
|
11816
12018
|
try {
|
|
11817
12019
|
const cached = memDb.prepare(
|
|
@@ -11872,7 +12074,7 @@ async function validateLicense(apiKey) {
|
|
|
11872
12074
|
}
|
|
11873
12075
|
}
|
|
11874
12076
|
function updateLicenseCache(apiKey, tier, validUntil, features = []) {
|
|
11875
|
-
const keyHash =
|
|
12077
|
+
const keyHash = createHash3("sha256").update(apiKey).digest("hex");
|
|
11876
12078
|
const memDb = getMemoryDb();
|
|
11877
12079
|
try {
|
|
11878
12080
|
memDb.prepare(`
|
|
@@ -12488,13 +12690,64 @@ var init_install_hooks = __esm({
|
|
|
12488
12690
|
}
|
|
12489
12691
|
});
|
|
12490
12692
|
|
|
12693
|
+
// src/commands/show-template.ts
|
|
12694
|
+
var show_template_exports = {};
|
|
12695
|
+
__export(show_template_exports, {
|
|
12696
|
+
runShowTemplate: () => runShowTemplate
|
|
12697
|
+
});
|
|
12698
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
12699
|
+
import { resolve as resolve7 } from "path";
|
|
12700
|
+
function normalizeBaseName(input) {
|
|
12701
|
+
return input.endsWith(".md") ? input.slice(0, -".md".length) : input;
|
|
12702
|
+
}
|
|
12703
|
+
async function runShowTemplate(args2) {
|
|
12704
|
+
const rawName = args2[0];
|
|
12705
|
+
if (!rawName) {
|
|
12706
|
+
process.stderr.write("massu: show-template requires a template name\n");
|
|
12707
|
+
process.stderr.write(" usage: massu show-template <name>\n");
|
|
12708
|
+
process.exit(1);
|
|
12709
|
+
return;
|
|
12710
|
+
}
|
|
12711
|
+
const baseName = normalizeBaseName(rawName);
|
|
12712
|
+
const sourceDir = resolveAssetDir("commands");
|
|
12713
|
+
if (!sourceDir) {
|
|
12714
|
+
process.stderr.write("massu: could not locate the bundled commands directory\n");
|
|
12715
|
+
process.exit(1);
|
|
12716
|
+
return;
|
|
12717
|
+
}
|
|
12718
|
+
const framework = getConfig().framework;
|
|
12719
|
+
const choice = pickVariant(baseName, sourceDir, framework);
|
|
12720
|
+
if (choice.kind === "miss") {
|
|
12721
|
+
process.stderr.write(`massu: no template named "${baseName}" found
|
|
12722
|
+
`);
|
|
12723
|
+
process.exit(1);
|
|
12724
|
+
return;
|
|
12725
|
+
}
|
|
12726
|
+
const suffix = choice.kind === "hit" ? choice.suffix : "";
|
|
12727
|
+
const file = suffix === "" ? resolve7(sourceDir, `${baseName}.md`) : resolve7(sourceDir, `${baseName}${suffix}.md`);
|
|
12728
|
+
if (!existsSync10(file)) {
|
|
12729
|
+
process.stderr.write(`massu: resolved template "${file}" no longer exists
|
|
12730
|
+
`);
|
|
12731
|
+
process.exit(1);
|
|
12732
|
+
return;
|
|
12733
|
+
}
|
|
12734
|
+
process.stdout.write(readFileSync8(file, "utf-8"));
|
|
12735
|
+
}
|
|
12736
|
+
var init_show_template = __esm({
|
|
12737
|
+
"src/commands/show-template.ts"() {
|
|
12738
|
+
"use strict";
|
|
12739
|
+
init_config();
|
|
12740
|
+
init_install_commands();
|
|
12741
|
+
}
|
|
12742
|
+
});
|
|
12743
|
+
|
|
12491
12744
|
// src/db.ts
|
|
12492
12745
|
import Database2 from "better-sqlite3";
|
|
12493
12746
|
import { dirname as dirname6, join as join6 } from "path";
|
|
12494
|
-
import { existsSync as
|
|
12747
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync4, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
|
|
12495
12748
|
function getCodeGraphDb() {
|
|
12496
12749
|
const dbPath = getResolvedPaths().codegraphDbPath;
|
|
12497
|
-
if (!
|
|
12750
|
+
if (!existsSync11(dbPath)) {
|
|
12498
12751
|
throw new Error(`CodeGraph database not found at ${dbPath}. Run 'npx @colbymchenry/codegraph sync' first.`);
|
|
12499
12752
|
}
|
|
12500
12753
|
const db = new Database2(dbPath, { readonly: true });
|
|
@@ -12504,7 +12757,7 @@ function getCodeGraphDb() {
|
|
|
12504
12757
|
function getDataDb() {
|
|
12505
12758
|
const dbPath = getResolvedPaths().dataDbPath;
|
|
12506
12759
|
const dir = dirname6(dbPath);
|
|
12507
|
-
if (!
|
|
12760
|
+
if (!existsSync11(dir)) {
|
|
12508
12761
|
mkdirSync4(dir, { recursive: true });
|
|
12509
12762
|
}
|
|
12510
12763
|
const db = new Database2(dbPath);
|
|
@@ -12802,10 +13055,10 @@ var init_db = __esm({
|
|
|
12802
13055
|
});
|
|
12803
13056
|
|
|
12804
13057
|
// src/security-utils.ts
|
|
12805
|
-
import { resolve as
|
|
13058
|
+
import { resolve as resolve8, normalize } from "path";
|
|
12806
13059
|
function ensureWithinRoot(filePath, projectRoot) {
|
|
12807
|
-
const resolvedRoot =
|
|
12808
|
-
const resolvedPath =
|
|
13060
|
+
const resolvedRoot = resolve8(projectRoot);
|
|
13061
|
+
const resolvedPath = resolve8(resolvedRoot, filePath);
|
|
12809
13062
|
const normalizedPath = normalize(resolvedPath);
|
|
12810
13063
|
const normalizedRoot = normalize(resolvedRoot);
|
|
12811
13064
|
if (!normalizedPath.startsWith(normalizedRoot + "/") && normalizedPath !== normalizedRoot) {
|
|
@@ -12878,8 +13131,8 @@ var init_rules = __esm({
|
|
|
12878
13131
|
});
|
|
12879
13132
|
|
|
12880
13133
|
// src/import-resolver.ts
|
|
12881
|
-
import { readFileSync as
|
|
12882
|
-
import { resolve as
|
|
13134
|
+
import { readFileSync as readFileSync9, existsSync as existsSync12, statSync as statSync6 } from "fs";
|
|
13135
|
+
import { resolve as resolve9, dirname as dirname7, join as join7 } from "path";
|
|
12883
13136
|
function parseImports(source) {
|
|
12884
13137
|
const imports = [];
|
|
12885
13138
|
const lines = source.split("\n");
|
|
@@ -12935,23 +13188,23 @@ function resolveImportPath(specifier, fromFile) {
|
|
|
12935
13188
|
let basePath;
|
|
12936
13189
|
if (specifier.startsWith("@/")) {
|
|
12937
13190
|
const paths = getResolvedPaths();
|
|
12938
|
-
basePath =
|
|
13191
|
+
basePath = resolve9(paths.pathAlias["@"] ?? paths.srcDir, specifier.slice(2));
|
|
12939
13192
|
} else {
|
|
12940
|
-
basePath =
|
|
13193
|
+
basePath = resolve9(dirname7(fromFile), specifier);
|
|
12941
13194
|
}
|
|
12942
|
-
if (
|
|
13195
|
+
if (existsSync12(basePath) && !isDirectory(basePath)) {
|
|
12943
13196
|
return toRelative(basePath);
|
|
12944
13197
|
}
|
|
12945
13198
|
const resolvedPaths = getResolvedPaths();
|
|
12946
13199
|
for (const ext of resolvedPaths.extensions) {
|
|
12947
13200
|
const withExt = basePath + ext;
|
|
12948
|
-
if (
|
|
13201
|
+
if (existsSync12(withExt)) {
|
|
12949
13202
|
return toRelative(withExt);
|
|
12950
13203
|
}
|
|
12951
13204
|
}
|
|
12952
13205
|
for (const indexFile of resolvedPaths.indexFiles) {
|
|
12953
13206
|
const indexPath = join7(basePath, indexFile);
|
|
12954
|
-
if (
|
|
13207
|
+
if (existsSync12(indexPath)) {
|
|
12955
13208
|
return toRelative(indexPath);
|
|
12956
13209
|
}
|
|
12957
13210
|
}
|
|
@@ -12987,11 +13240,11 @@ function buildImportIndex(dataDb2, codegraphDb2) {
|
|
|
12987
13240
|
const batchSize = 500;
|
|
12988
13241
|
let batch = [];
|
|
12989
13242
|
for (const file of files) {
|
|
12990
|
-
const absPath = ensureWithinRoot(
|
|
12991
|
-
if (!
|
|
13243
|
+
const absPath = ensureWithinRoot(resolve9(projectRoot, file.path), projectRoot);
|
|
13244
|
+
if (!existsSync12(absPath)) continue;
|
|
12992
13245
|
let source;
|
|
12993
13246
|
try {
|
|
12994
|
-
source =
|
|
13247
|
+
source = readFileSync9(absPath, "utf-8");
|
|
12995
13248
|
} catch {
|
|
12996
13249
|
continue;
|
|
12997
13250
|
}
|
|
@@ -13027,15 +13280,15 @@ var init_import_resolver = __esm({
|
|
|
13027
13280
|
});
|
|
13028
13281
|
|
|
13029
13282
|
// src/trpc-index.ts
|
|
13030
|
-
import { readFileSync as
|
|
13031
|
-
import { resolve as
|
|
13283
|
+
import { readFileSync as readFileSync10, existsSync as existsSync13, readdirSync as readdirSync9 } from "fs";
|
|
13284
|
+
import { resolve as resolve10, join as join8 } from "path";
|
|
13032
13285
|
function parseRootRouter() {
|
|
13033
13286
|
const paths = getResolvedPaths();
|
|
13034
13287
|
const rootPath = paths.rootRouterPath;
|
|
13035
|
-
if (!
|
|
13288
|
+
if (!existsSync13(rootPath)) {
|
|
13036
13289
|
throw new Error(`Root router not found at ${rootPath}`);
|
|
13037
13290
|
}
|
|
13038
|
-
const source =
|
|
13291
|
+
const source = readFileSync10(rootPath, "utf-8");
|
|
13039
13292
|
const mappings = [];
|
|
13040
13293
|
const importMap = /* @__PURE__ */ new Map();
|
|
13041
13294
|
const importRegex = /import\s+\{[^}]*?(\w+Router)[^}]*\}\s+from\s+['"]\.\/routers\/([^'"]+)['"]/g;
|
|
@@ -13043,16 +13296,16 @@ function parseRootRouter() {
|
|
|
13043
13296
|
while ((match = importRegex.exec(source)) !== null) {
|
|
13044
13297
|
const variable = match[1];
|
|
13045
13298
|
let filePath = match[2];
|
|
13046
|
-
const fullPath =
|
|
13299
|
+
const fullPath = resolve10(paths.routersDir, filePath);
|
|
13047
13300
|
for (const ext of [".ts", ".tsx", ""]) {
|
|
13048
13301
|
const candidate = fullPath + ext;
|
|
13049
13302
|
const routersRelPath = getConfig().paths.routers ?? "src/server/api/routers";
|
|
13050
|
-
if (
|
|
13303
|
+
if (existsSync13(candidate)) {
|
|
13051
13304
|
filePath = routersRelPath + "/" + filePath + ext;
|
|
13052
13305
|
break;
|
|
13053
13306
|
}
|
|
13054
13307
|
const indexCandidate = join8(fullPath, "index.ts");
|
|
13055
|
-
if (
|
|
13308
|
+
if (existsSync13(indexCandidate)) {
|
|
13056
13309
|
filePath = routersRelPath + "/" + filePath + "/index.ts";
|
|
13057
13310
|
break;
|
|
13058
13311
|
}
|
|
@@ -13071,9 +13324,9 @@ function parseRootRouter() {
|
|
|
13071
13324
|
return mappings;
|
|
13072
13325
|
}
|
|
13073
13326
|
function extractProcedures(routerFilePath) {
|
|
13074
|
-
const absPath =
|
|
13075
|
-
if (!
|
|
13076
|
-
const source =
|
|
13327
|
+
const absPath = resolve10(getProjectRoot(), routerFilePath);
|
|
13328
|
+
if (!existsSync13(absPath)) return [];
|
|
13329
|
+
const source = readFileSync10(absPath, "utf-8");
|
|
13077
13330
|
const procedures = [];
|
|
13078
13331
|
const seen = /* @__PURE__ */ new Set();
|
|
13079
13332
|
const procRegex = /(\w+)\s*:\s*(protected|public)Procedure/g;
|
|
@@ -13096,13 +13349,13 @@ function findUICallSites(routerKey, procedureName) {
|
|
|
13096
13349
|
const root = getProjectRoot();
|
|
13097
13350
|
const src = config.paths.source;
|
|
13098
13351
|
const searchDirs = [
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13352
|
+
resolve10(root, config.paths.pages ?? src + "/app"),
|
|
13353
|
+
resolve10(root, config.paths.components ?? src + "/components"),
|
|
13354
|
+
resolve10(root, config.paths.hooks ?? src + "/hooks")
|
|
13102
13355
|
];
|
|
13103
13356
|
const searchPattern = `api.${routerKey}.${procedureName}`;
|
|
13104
13357
|
for (const dir of searchDirs) {
|
|
13105
|
-
if (!
|
|
13358
|
+
if (!existsSync13(dir)) continue;
|
|
13106
13359
|
searchDirectory(dir, searchPattern, callSites);
|
|
13107
13360
|
}
|
|
13108
13361
|
return callSites;
|
|
@@ -13116,7 +13369,7 @@ function searchDirectory(dir, pattern, results) {
|
|
|
13116
13369
|
searchDirectory(fullPath, pattern, results);
|
|
13117
13370
|
} else if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) {
|
|
13118
13371
|
try {
|
|
13119
|
-
const source =
|
|
13372
|
+
const source = readFileSync10(fullPath, "utf-8");
|
|
13120
13373
|
const lines = source.split("\n");
|
|
13121
13374
|
for (let i = 0; i < lines.length; i++) {
|
|
13122
13375
|
if (lines[i].includes(pattern)) {
|
|
@@ -13179,8 +13432,8 @@ var init_trpc_index = __esm({
|
|
|
13179
13432
|
});
|
|
13180
13433
|
|
|
13181
13434
|
// src/page-deps.ts
|
|
13182
|
-
import { readFileSync as
|
|
13183
|
-
import { resolve as
|
|
13435
|
+
import { readFileSync as readFileSync11, existsSync as existsSync14 } from "fs";
|
|
13436
|
+
import { resolve as resolve11 } from "path";
|
|
13184
13437
|
function deriveRoute(pageFile) {
|
|
13185
13438
|
let route = pageFile.replace(/^src\/app/, "").replace(/\/page\.tsx?$/, "").replace(/\/page\.jsx?$/, "");
|
|
13186
13439
|
return route || "/";
|
|
@@ -13218,10 +13471,10 @@ function findRouterCalls(files) {
|
|
|
13218
13471
|
const routers = /* @__PURE__ */ new Set();
|
|
13219
13472
|
const projectRoot = getProjectRoot();
|
|
13220
13473
|
for (const file of files) {
|
|
13221
|
-
const absPath = ensureWithinRoot(
|
|
13222
|
-
if (!
|
|
13474
|
+
const absPath = ensureWithinRoot(resolve11(projectRoot, file), projectRoot);
|
|
13475
|
+
if (!existsSync14(absPath)) continue;
|
|
13223
13476
|
try {
|
|
13224
|
-
const source =
|
|
13477
|
+
const source = readFileSync11(absPath, "utf-8");
|
|
13225
13478
|
const apiCallRegex = /api\.(\w+)\.\w+/g;
|
|
13226
13479
|
let match;
|
|
13227
13480
|
while ((match = apiCallRegex.exec(source)) !== null) {
|
|
@@ -13239,10 +13492,10 @@ function findTablesFromRouters(routerNames, dataDb2) {
|
|
|
13239
13492
|
"SELECT DISTINCT router_file FROM massu_trpc_procedures WHERE router_name = ?"
|
|
13240
13493
|
).all(routerName);
|
|
13241
13494
|
for (const proc of procs) {
|
|
13242
|
-
const absPath = ensureWithinRoot(
|
|
13243
|
-
if (!
|
|
13495
|
+
const absPath = ensureWithinRoot(resolve11(getProjectRoot(), proc.router_file), getProjectRoot());
|
|
13496
|
+
if (!existsSync14(absPath)) continue;
|
|
13244
13497
|
try {
|
|
13245
|
-
const source =
|
|
13498
|
+
const source = readFileSync11(absPath, "utf-8");
|
|
13246
13499
|
const dbPattern = getConfig().dbAccessPattern ?? "ctx.db.{table}";
|
|
13247
13500
|
const regexStr = dbPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace("\\{table\\}", "(\\w+)");
|
|
13248
13501
|
const tableRegex = new RegExp(regexStr + "\\.", "g");
|
|
@@ -13511,14 +13764,14 @@ var init_domains = __esm({
|
|
|
13511
13764
|
});
|
|
13512
13765
|
|
|
13513
13766
|
// src/schema-mapper.ts
|
|
13514
|
-
import { readFileSync as
|
|
13767
|
+
import { readFileSync as readFileSync12, existsSync as existsSync15, readdirSync as readdirSync10 } from "fs";
|
|
13515
13768
|
import { join as join9 } from "path";
|
|
13516
13769
|
function parsePrismaSchema() {
|
|
13517
13770
|
const schemaPath = getResolvedPaths().prismaSchemaPath;
|
|
13518
|
-
if (!
|
|
13771
|
+
if (!existsSync15(schemaPath)) {
|
|
13519
13772
|
throw new Error(`Prisma schema not found at ${schemaPath}`);
|
|
13520
13773
|
}
|
|
13521
|
-
const source =
|
|
13774
|
+
const source = readFileSync12(schemaPath, "utf-8");
|
|
13522
13775
|
const models = [];
|
|
13523
13776
|
const sourceLines = source.split("\n");
|
|
13524
13777
|
let i = 0;
|
|
@@ -13576,7 +13829,7 @@ function toSnakeCase(str) {
|
|
|
13576
13829
|
function findColumnUsageInRouters(tableName) {
|
|
13577
13830
|
const usage = /* @__PURE__ */ new Map();
|
|
13578
13831
|
const routersDir = getResolvedPaths().routersDir;
|
|
13579
|
-
if (!
|
|
13832
|
+
if (!existsSync15(routersDir)) return usage;
|
|
13580
13833
|
scanDirectory(routersDir, tableName, usage);
|
|
13581
13834
|
return usage;
|
|
13582
13835
|
}
|
|
@@ -13593,7 +13846,7 @@ function scanDirectory(dir, tableName, usage) {
|
|
|
13593
13846
|
}
|
|
13594
13847
|
function scanFile(absPath, tableName, usage) {
|
|
13595
13848
|
try {
|
|
13596
|
-
const source =
|
|
13849
|
+
const source = readFileSync12(absPath, "utf-8");
|
|
13597
13850
|
if (!source.includes(tableName)) return;
|
|
13598
13851
|
const relPath = absPath.slice(getProjectRoot().length + 1);
|
|
13599
13852
|
const lines = source.split("\n");
|
|
@@ -13638,7 +13891,7 @@ function detectMismatches(models) {
|
|
|
13638
13891
|
}
|
|
13639
13892
|
function findFilesUsingColumn(dir, column, tableName) {
|
|
13640
13893
|
const result = [];
|
|
13641
|
-
if (!
|
|
13894
|
+
if (!existsSync15(dir)) return result;
|
|
13642
13895
|
const entries = readdirSync10(dir, { withFileTypes: true });
|
|
13643
13896
|
for (const entry of entries) {
|
|
13644
13897
|
const fullPath = join9(dir, entry.name);
|
|
@@ -13646,7 +13899,7 @@ function findFilesUsingColumn(dir, column, tableName) {
|
|
|
13646
13899
|
result.push(...findFilesUsingColumn(fullPath, column, tableName));
|
|
13647
13900
|
} else if (entry.name.endsWith(".ts")) {
|
|
13648
13901
|
try {
|
|
13649
|
-
const source =
|
|
13902
|
+
const source = readFileSync12(fullPath, "utf-8");
|
|
13650
13903
|
if (source.includes(tableName) && source.includes(column)) {
|
|
13651
13904
|
result.push(fullPath.slice(getProjectRoot().length + 1));
|
|
13652
13905
|
}
|
|
@@ -13791,12 +14044,12 @@ var init_import_parser = __esm({
|
|
|
13791
14044
|
});
|
|
13792
14045
|
|
|
13793
14046
|
// src/python/import-resolver.ts
|
|
13794
|
-
import { readFileSync as
|
|
13795
|
-
import { resolve as
|
|
14047
|
+
import { readFileSync as readFileSync13, existsSync as existsSync16, readdirSync as readdirSync11 } from "fs";
|
|
14048
|
+
import { resolve as resolve13, join as join10, relative as relative4, dirname as dirname8 } from "path";
|
|
13796
14049
|
function resolvePythonModulePath(module, fromFile, pythonRoot, level) {
|
|
13797
14050
|
const projectRoot = getProjectRoot();
|
|
13798
14051
|
if (level > 0) {
|
|
13799
|
-
let baseDir = dirname8(
|
|
14052
|
+
let baseDir = dirname8(resolve13(projectRoot, fromFile));
|
|
13800
14053
|
for (let i = 1; i < level; i++) {
|
|
13801
14054
|
baseDir = dirname8(baseDir);
|
|
13802
14055
|
}
|
|
@@ -13808,17 +14061,17 @@ function resolvePythonModulePath(module, fromFile, pythonRoot, level) {
|
|
|
13808
14061
|
return tryResolvePythonPath(baseDir, projectRoot);
|
|
13809
14062
|
}
|
|
13810
14063
|
const parts = module.split(".");
|
|
13811
|
-
const candidate = join10(
|
|
14064
|
+
const candidate = join10(resolve13(projectRoot, pythonRoot), ...parts);
|
|
13812
14065
|
return tryResolvePythonPath(candidate, projectRoot);
|
|
13813
14066
|
}
|
|
13814
14067
|
function tryResolvePythonPath(basePath, projectRoot) {
|
|
13815
|
-
if (
|
|
14068
|
+
if (existsSync16(basePath + ".py")) {
|
|
13816
14069
|
return relative4(projectRoot, basePath + ".py");
|
|
13817
14070
|
}
|
|
13818
|
-
if (
|
|
14071
|
+
if (existsSync16(join10(basePath, "__init__.py"))) {
|
|
13819
14072
|
return relative4(projectRoot, join10(basePath, "__init__.py"));
|
|
13820
14073
|
}
|
|
13821
|
-
if (basePath.endsWith(".py") &&
|
|
14074
|
+
if (basePath.endsWith(".py") && existsSync16(basePath)) {
|
|
13822
14075
|
return relative4(projectRoot, basePath);
|
|
13823
14076
|
}
|
|
13824
14077
|
return null;
|
|
@@ -13841,7 +14094,7 @@ function walkPythonFiles(dir, excludeDirs) {
|
|
|
13841
14094
|
}
|
|
13842
14095
|
function buildPythonImportIndex(dataDb2, pythonRoot, excludeDirs = ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"]) {
|
|
13843
14096
|
const projectRoot = getProjectRoot();
|
|
13844
|
-
const absRoot =
|
|
14097
|
+
const absRoot = resolve13(projectRoot, pythonRoot);
|
|
13845
14098
|
dataDb2.exec("DELETE FROM massu_py_imports");
|
|
13846
14099
|
const insertStmt = dataDb2.prepare(
|
|
13847
14100
|
"INSERT INTO massu_py_imports (source_file, target_file, import_type, imported_names, line) VALUES (?, ?, ?, ?, ?)"
|
|
@@ -13858,7 +14111,7 @@ function buildPythonImportIndex(dataDb2, pythonRoot, excludeDirs = ["__pycache__
|
|
|
13858
14111
|
const relFile = relative4(projectRoot, absFile);
|
|
13859
14112
|
let source;
|
|
13860
14113
|
try {
|
|
13861
|
-
source =
|
|
14114
|
+
source = readFileSync13(absFile, "utf-8");
|
|
13862
14115
|
} catch {
|
|
13863
14116
|
continue;
|
|
13864
14117
|
}
|
|
@@ -14124,7 +14377,7 @@ var init_route_parser = __esm({
|
|
|
14124
14377
|
});
|
|
14125
14378
|
|
|
14126
14379
|
// src/python/route-indexer.ts
|
|
14127
|
-
import { readFileSync as
|
|
14380
|
+
import { readFileSync as readFileSync14, readdirSync as readdirSync12 } from "fs";
|
|
14128
14381
|
import { join as join11, relative as relative5 } from "path";
|
|
14129
14382
|
function walkPyFiles(dir, excludeDirs) {
|
|
14130
14383
|
const files = [];
|
|
@@ -14157,7 +14410,7 @@ function buildPythonRouteIndex(dataDb2, pythonRoot, excludeDirs = ["__pycache__"
|
|
|
14157
14410
|
const relFile = relative5(projectRoot, absFile);
|
|
14158
14411
|
let source;
|
|
14159
14412
|
try {
|
|
14160
|
-
source =
|
|
14413
|
+
source = readFileSync14(absFile, "utf-8");
|
|
14161
14414
|
} catch {
|
|
14162
14415
|
continue;
|
|
14163
14416
|
}
|
|
@@ -14368,7 +14621,7 @@ var init_model_parser = __esm({
|
|
|
14368
14621
|
});
|
|
14369
14622
|
|
|
14370
14623
|
// src/python/model-indexer.ts
|
|
14371
|
-
import { readFileSync as
|
|
14624
|
+
import { readFileSync as readFileSync15, readdirSync as readdirSync13 } from "fs";
|
|
14372
14625
|
import { join as join12, relative as relative6 } from "path";
|
|
14373
14626
|
function walkPyFiles2(dir, excludeDirs) {
|
|
14374
14627
|
const files = [];
|
|
@@ -14404,7 +14657,7 @@ function buildPythonModelIndex(dataDb2, pythonRoot, excludeDirs = ["__pycache__"
|
|
|
14404
14657
|
const relFile = relative6(projectRoot, absFile);
|
|
14405
14658
|
let source;
|
|
14406
14659
|
try {
|
|
14407
|
-
source =
|
|
14660
|
+
source = readFileSync15(absFile, "utf-8");
|
|
14408
14661
|
} catch {
|
|
14409
14662
|
continue;
|
|
14410
14663
|
}
|
|
@@ -14664,7 +14917,7 @@ var init_migration_parser = __esm({
|
|
|
14664
14917
|
});
|
|
14665
14918
|
|
|
14666
14919
|
// src/python/migration-indexer.ts
|
|
14667
|
-
import { readFileSync as
|
|
14920
|
+
import { readFileSync as readFileSync16, readdirSync as readdirSync14 } from "fs";
|
|
14668
14921
|
import { join as join13, relative as relative7 } from "path";
|
|
14669
14922
|
function buildPythonMigrationIndex(dataDb2, alembicDir) {
|
|
14670
14923
|
const projectRoot = getProjectRoot();
|
|
@@ -14690,7 +14943,7 @@ function buildPythonMigrationIndex(dataDb2, alembicDir) {
|
|
|
14690
14943
|
for (const absFile of files) {
|
|
14691
14944
|
let source;
|
|
14692
14945
|
try {
|
|
14693
|
-
source =
|
|
14946
|
+
source = readFileSync16(absFile, "utf-8");
|
|
14694
14947
|
} catch {
|
|
14695
14948
|
continue;
|
|
14696
14949
|
}
|
|
@@ -14724,7 +14977,7 @@ var init_migration_indexer = __esm({
|
|
|
14724
14977
|
});
|
|
14725
14978
|
|
|
14726
14979
|
// src/python/coupling-detector.ts
|
|
14727
|
-
import { readFileSync as
|
|
14980
|
+
import { readFileSync as readFileSync17, readdirSync as readdirSync15 } from "fs";
|
|
14728
14981
|
import { join as join14, relative as relative8 } from "path";
|
|
14729
14982
|
function buildPythonCouplingIndex(dataDb2) {
|
|
14730
14983
|
const projectRoot = getProjectRoot();
|
|
@@ -14761,7 +15014,7 @@ function buildPythonCouplingIndex(dataDb2) {
|
|
|
14761
15014
|
const relFile = relative8(projectRoot, absFile);
|
|
14762
15015
|
let source;
|
|
14763
15016
|
try {
|
|
14764
|
-
source =
|
|
15017
|
+
source = readFileSync17(absFile, "utf-8");
|
|
14765
15018
|
} catch {
|
|
14766
15019
|
continue;
|
|
14767
15020
|
}
|
|
@@ -15166,8 +15419,8 @@ var init_memory_tools = __esm({
|
|
|
15166
15419
|
});
|
|
15167
15420
|
|
|
15168
15421
|
// src/docs-tools.ts
|
|
15169
|
-
import { readFileSync as
|
|
15170
|
-
import { resolve as
|
|
15422
|
+
import { readFileSync as readFileSync18, existsSync as existsSync17 } from "fs";
|
|
15423
|
+
import { resolve as resolve14, basename as basename3 } from "path";
|
|
15171
15424
|
function p3(baseName) {
|
|
15172
15425
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
15173
15426
|
}
|
|
@@ -15222,10 +15475,10 @@ function handleDocsToolCall(name, args2) {
|
|
|
15222
15475
|
}
|
|
15223
15476
|
function loadDocsMap() {
|
|
15224
15477
|
const mapPath = getResolvedPaths().docsMapPath;
|
|
15225
|
-
if (!
|
|
15478
|
+
if (!existsSync17(mapPath)) {
|
|
15226
15479
|
throw new Error(`docs-map.json not found at ${mapPath}`);
|
|
15227
15480
|
}
|
|
15228
|
-
return JSON.parse(
|
|
15481
|
+
return JSON.parse(readFileSync18(mapPath, "utf-8"));
|
|
15229
15482
|
}
|
|
15230
15483
|
function matchesPattern(filePath, pattern) {
|
|
15231
15484
|
const regexStr = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
@@ -15295,13 +15548,13 @@ function extractFrontmatter(content) {
|
|
|
15295
15548
|
}
|
|
15296
15549
|
function extractProcedureNames(routerPath) {
|
|
15297
15550
|
const root = getProjectRoot();
|
|
15298
|
-
const absPath = ensureWithinRoot(
|
|
15299
|
-
if (!
|
|
15300
|
-
const altPath = ensureWithinRoot(
|
|
15301
|
-
if (!
|
|
15302
|
-
return extractProcedureNamesFromContent(
|
|
15551
|
+
const absPath = ensureWithinRoot(resolve14(getResolvedPaths().srcDir, "..", routerPath), root);
|
|
15552
|
+
if (!existsSync17(absPath)) {
|
|
15553
|
+
const altPath = ensureWithinRoot(resolve14(getResolvedPaths().srcDir, "../server/api/routers", basename3(routerPath)), root);
|
|
15554
|
+
if (!existsSync17(altPath)) return [];
|
|
15555
|
+
return extractProcedureNamesFromContent(readFileSync18(altPath, "utf-8"));
|
|
15303
15556
|
}
|
|
15304
|
-
return extractProcedureNamesFromContent(
|
|
15557
|
+
return extractProcedureNamesFromContent(readFileSync18(absPath, "utf-8"));
|
|
15305
15558
|
}
|
|
15306
15559
|
function extractProcedureNamesFromContent(content) {
|
|
15307
15560
|
const procRegex = /\.(?:query|mutation)\s*\(/g;
|
|
@@ -15341,8 +15594,8 @@ function handleDocsAudit(args2) {
|
|
|
15341
15594
|
for (const [mappingId, triggeringFiles] of affectedMappings) {
|
|
15342
15595
|
const mapping = docsMap.mappings.find((m3) => m3.id === mappingId);
|
|
15343
15596
|
if (!mapping) continue;
|
|
15344
|
-
const helpPagePath = ensureWithinRoot(
|
|
15345
|
-
if (!
|
|
15597
|
+
const helpPagePath = ensureWithinRoot(resolve14(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
|
|
15598
|
+
if (!existsSync17(helpPagePath)) {
|
|
15346
15599
|
results.push({
|
|
15347
15600
|
helpPage: mapping.helpPage,
|
|
15348
15601
|
mappingId,
|
|
@@ -15354,7 +15607,7 @@ function handleDocsAudit(args2) {
|
|
|
15354
15607
|
});
|
|
15355
15608
|
continue;
|
|
15356
15609
|
}
|
|
15357
|
-
const content =
|
|
15610
|
+
const content = readFileSync18(helpPagePath, "utf-8");
|
|
15358
15611
|
const sections = extractSections(content);
|
|
15359
15612
|
const frontmatter = extractFrontmatter(content);
|
|
15360
15613
|
const staleReasons = [];
|
|
@@ -15394,9 +15647,9 @@ function handleDocsAudit(args2) {
|
|
|
15394
15647
|
});
|
|
15395
15648
|
for (const [guideName, parentId] of Object.entries(docsMap.userGuideInheritance.examples)) {
|
|
15396
15649
|
if (parentId === mappingId) {
|
|
15397
|
-
const guidePath = ensureWithinRoot(
|
|
15398
|
-
if (
|
|
15399
|
-
const guideContent =
|
|
15650
|
+
const guidePath = ensureWithinRoot(resolve14(getResolvedPaths().helpSitePath, `pages/user-guides/${guideName}/index.mdx`), getProjectRoot());
|
|
15651
|
+
if (existsSync17(guidePath)) {
|
|
15652
|
+
const guideContent = readFileSync18(guidePath, "utf-8");
|
|
15400
15653
|
const guideFrontmatter = extractFrontmatter(guideContent);
|
|
15401
15654
|
if (!guideFrontmatter?.lastVerified || status === "STALE") {
|
|
15402
15655
|
results.push({
|
|
@@ -15429,14 +15682,14 @@ function handleDocsCoverage(args2) {
|
|
|
15429
15682
|
const gaps = [];
|
|
15430
15683
|
const mappings = filterDomain ? docsMap.mappings.filter((m3) => m3.id === filterDomain) : docsMap.mappings;
|
|
15431
15684
|
for (const mapping of mappings) {
|
|
15432
|
-
const helpPagePath = ensureWithinRoot(
|
|
15433
|
-
const exists =
|
|
15685
|
+
const helpPagePath = ensureWithinRoot(resolve14(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
|
|
15686
|
+
const exists = existsSync17(helpPagePath);
|
|
15434
15687
|
let hasContent = false;
|
|
15435
15688
|
let lineCount = 0;
|
|
15436
15689
|
let lastVerified = null;
|
|
15437
15690
|
let status = null;
|
|
15438
15691
|
if (exists) {
|
|
15439
|
-
const content =
|
|
15692
|
+
const content = readFileSync18(helpPagePath, "utf-8");
|
|
15440
15693
|
lineCount = content.split("\n").length;
|
|
15441
15694
|
hasContent = lineCount > 10;
|
|
15442
15695
|
const frontmatter = extractFrontmatter(content);
|
|
@@ -15777,8 +16030,8 @@ var init_observability_tools = __esm({
|
|
|
15777
16030
|
});
|
|
15778
16031
|
|
|
15779
16032
|
// src/sentinel-db.ts
|
|
15780
|
-
import { existsSync as
|
|
15781
|
-
import { resolve as
|
|
16033
|
+
import { existsSync as existsSync18 } from "fs";
|
|
16034
|
+
import { resolve as resolve15 } from "path";
|
|
15782
16035
|
function parsePortalScope(raw) {
|
|
15783
16036
|
if (!raw) return [];
|
|
15784
16037
|
try {
|
|
@@ -16014,23 +16267,23 @@ function validateFeatures(db, domainFilter) {
|
|
|
16014
16267
|
const missingProcedures = [];
|
|
16015
16268
|
const missingPages = [];
|
|
16016
16269
|
for (const comp of components) {
|
|
16017
|
-
const absPath =
|
|
16018
|
-
if (!
|
|
16270
|
+
const absPath = resolve15(PROJECT_ROOT, comp.component_file);
|
|
16271
|
+
if (!existsSync18(absPath)) {
|
|
16019
16272
|
missingComponents.push(comp.component_file);
|
|
16020
16273
|
}
|
|
16021
16274
|
}
|
|
16022
16275
|
for (const proc of procedures) {
|
|
16023
|
-
const routerPath =
|
|
16024
|
-
if (!
|
|
16276
|
+
const routerPath = resolve15(PROJECT_ROOT, `src/server/api/routers/${proc.router_name}.ts`);
|
|
16277
|
+
if (!existsSync18(routerPath)) {
|
|
16025
16278
|
missingProcedures.push({ router: proc.router_name, procedure: proc.procedure_name });
|
|
16026
16279
|
}
|
|
16027
16280
|
}
|
|
16028
16281
|
for (const page of pages) {
|
|
16029
16282
|
const routeToPath = page.page_route.replace(/^\/(portal-[^/]+\/)?/, "src/app/").replace(/\/$/, "") + "/page.tsx";
|
|
16030
|
-
const absPath =
|
|
16031
|
-
if (page.page_route.startsWith("/") && !
|
|
16032
|
-
const altPath =
|
|
16033
|
-
if (!
|
|
16283
|
+
const absPath = resolve15(PROJECT_ROOT, routeToPath);
|
|
16284
|
+
if (page.page_route.startsWith("/") && !existsSync18(absPath)) {
|
|
16285
|
+
const altPath = resolve15(PROJECT_ROOT, `src/app${page.page_route}/page.tsx`);
|
|
16286
|
+
if (!existsSync18(altPath)) {
|
|
16034
16287
|
missingPages.push(page.page_route);
|
|
16035
16288
|
}
|
|
16036
16289
|
}
|
|
@@ -16554,8 +16807,8 @@ var init_sentinel_tools = __esm({
|
|
|
16554
16807
|
});
|
|
16555
16808
|
|
|
16556
16809
|
// src/sentinel-scanner.ts
|
|
16557
|
-
import { readFileSync as
|
|
16558
|
-
import { resolve as
|
|
16810
|
+
import { readFileSync as readFileSync19, existsSync as existsSync19, readdirSync as readdirSync16, statSync as statSync7 } from "fs";
|
|
16811
|
+
import { resolve as resolve16, join as join15, basename as basename4, dirname as dirname9, relative as relative9 } from "path";
|
|
16559
16812
|
function inferDomain(filePath) {
|
|
16560
16813
|
const domains = getConfig().domains;
|
|
16561
16814
|
const path = filePath.toLowerCase();
|
|
@@ -16684,8 +16937,8 @@ function scanComponentExports(dataDb2) {
|
|
|
16684
16937
|
const projectRoot = getProjectRoot();
|
|
16685
16938
|
const componentsBase = config.paths.components ?? config.paths.source + "/components";
|
|
16686
16939
|
const componentDirs = [];
|
|
16687
|
-
const basePath =
|
|
16688
|
-
if (
|
|
16940
|
+
const basePath = resolve16(projectRoot, componentsBase);
|
|
16941
|
+
if (existsSync19(basePath)) {
|
|
16689
16942
|
try {
|
|
16690
16943
|
const entries = readdirSync16(basePath, { withFileTypes: true });
|
|
16691
16944
|
for (const entry of entries) {
|
|
@@ -16697,12 +16950,12 @@ function scanComponentExports(dataDb2) {
|
|
|
16697
16950
|
}
|
|
16698
16951
|
}
|
|
16699
16952
|
for (const dir of componentDirs) {
|
|
16700
|
-
const absDir =
|
|
16701
|
-
if (!
|
|
16953
|
+
const absDir = resolve16(projectRoot, dir);
|
|
16954
|
+
if (!existsSync19(absDir)) continue;
|
|
16702
16955
|
const files = walkDir(absDir).filter((f2) => f2.endsWith(".tsx") || f2.endsWith(".ts"));
|
|
16703
16956
|
for (const file of files) {
|
|
16704
16957
|
const relPath = relative9(projectRoot, file);
|
|
16705
|
-
const source =
|
|
16958
|
+
const source = readFileSync19(file, "utf-8");
|
|
16706
16959
|
const annotations = parseFeatureAnnotations(source);
|
|
16707
16960
|
if (annotations.length > 0) {
|
|
16708
16961
|
for (const ann of annotations) {
|
|
@@ -17741,7 +17994,7 @@ var init_audit_trail = __esm({
|
|
|
17741
17994
|
});
|
|
17742
17995
|
|
|
17743
17996
|
// src/validation-engine.ts
|
|
17744
|
-
import { existsSync as
|
|
17997
|
+
import { existsSync as existsSync20, readFileSync as readFileSync20 } from "fs";
|
|
17745
17998
|
function p10(baseName) {
|
|
17746
17999
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
17747
18000
|
}
|
|
@@ -17772,7 +18025,7 @@ function validateFile(filePath, projectRoot) {
|
|
|
17772
18025
|
});
|
|
17773
18026
|
return checks;
|
|
17774
18027
|
}
|
|
17775
|
-
if (!
|
|
18028
|
+
if (!existsSync20(absPath)) {
|
|
17776
18029
|
checks.push({
|
|
17777
18030
|
name: "file_exists",
|
|
17778
18031
|
severity: "error",
|
|
@@ -17781,7 +18034,7 @@ function validateFile(filePath, projectRoot) {
|
|
|
17781
18034
|
});
|
|
17782
18035
|
return checks;
|
|
17783
18036
|
}
|
|
17784
|
-
const source =
|
|
18037
|
+
const source = readFileSync20(absPath, "utf-8");
|
|
17785
18038
|
const lines = source.split("\n");
|
|
17786
18039
|
if (activeChecks.rule_compliance !== false) {
|
|
17787
18040
|
for (const ruleSet of config.rules) {
|
|
@@ -18226,7 +18479,7 @@ var init_adr_generator = __esm({
|
|
|
18226
18479
|
});
|
|
18227
18480
|
|
|
18228
18481
|
// src/security-scorer.ts
|
|
18229
|
-
import { existsSync as
|
|
18482
|
+
import { existsSync as existsSync21, readFileSync as readFileSync21 } from "fs";
|
|
18230
18483
|
function p12(baseName) {
|
|
18231
18484
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
18232
18485
|
}
|
|
@@ -18250,12 +18503,12 @@ function scoreFileSecurity(filePath, projectRoot) {
|
|
|
18250
18503
|
}]
|
|
18251
18504
|
};
|
|
18252
18505
|
}
|
|
18253
|
-
if (!
|
|
18506
|
+
if (!existsSync21(absPath)) {
|
|
18254
18507
|
return { riskScore: 0, findings: [] };
|
|
18255
18508
|
}
|
|
18256
18509
|
let source;
|
|
18257
18510
|
try {
|
|
18258
|
-
source =
|
|
18511
|
+
source = readFileSync21(absPath, "utf-8");
|
|
18259
18512
|
} catch {
|
|
18260
18513
|
return { riskScore: 0, findings: [] };
|
|
18261
18514
|
}
|
|
@@ -18544,8 +18797,8 @@ var init_security_scorer = __esm({
|
|
|
18544
18797
|
});
|
|
18545
18798
|
|
|
18546
18799
|
// src/dependency-scorer.ts
|
|
18547
|
-
import { existsSync as
|
|
18548
|
-
import { resolve as
|
|
18800
|
+
import { existsSync as existsSync22, readFileSync as readFileSync22 } from "fs";
|
|
18801
|
+
import { resolve as resolve17 } from "path";
|
|
18549
18802
|
function p13(baseName) {
|
|
18550
18803
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
18551
18804
|
}
|
|
@@ -18577,10 +18830,10 @@ function calculateDepRisk(factors) {
|
|
|
18577
18830
|
return Math.min(100, risk);
|
|
18578
18831
|
}
|
|
18579
18832
|
function getInstalledPackages(projectRoot) {
|
|
18580
|
-
const pkgPath =
|
|
18581
|
-
if (!
|
|
18833
|
+
const pkgPath = resolve17(projectRoot, "package.json");
|
|
18834
|
+
if (!existsSync22(pkgPath)) return /* @__PURE__ */ new Map();
|
|
18582
18835
|
try {
|
|
18583
|
-
const pkg = JSON.parse(
|
|
18836
|
+
const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
|
|
18584
18837
|
const packages = /* @__PURE__ */ new Map();
|
|
18585
18838
|
for (const [name, version] of Object.entries(pkg.dependencies ?? {})) {
|
|
18586
18839
|
packages.set(name, version);
|
|
@@ -19182,9 +19435,9 @@ var init_regression_detector = __esm({
|
|
|
19182
19435
|
});
|
|
19183
19436
|
|
|
19184
19437
|
// src/knowledge-indexer.ts
|
|
19185
|
-
import { createHash as
|
|
19186
|
-
import { readFileSync as
|
|
19187
|
-
import { resolve as
|
|
19438
|
+
import { createHash as createHash4 } from "crypto";
|
|
19439
|
+
import { readFileSync as readFileSync23, readdirSync as readdirSync17, statSync as statSync8, existsSync as existsSync23 } from "fs";
|
|
19440
|
+
import { resolve as resolve18, relative as relative10, basename as basename5, extname } from "path";
|
|
19188
19441
|
function getKnowledgePaths() {
|
|
19189
19442
|
const resolved = getResolvedPaths();
|
|
19190
19443
|
const config = getConfig();
|
|
@@ -19212,7 +19465,7 @@ function discoverMarkdownFiles(baseDir) {
|
|
|
19212
19465
|
try {
|
|
19213
19466
|
const entries = readdirSync17(dir, { withFileTypes: true });
|
|
19214
19467
|
for (const entry of entries) {
|
|
19215
|
-
const fullPath =
|
|
19468
|
+
const fullPath = resolve18(dir, entry.name);
|
|
19216
19469
|
if (entry.isDirectory()) {
|
|
19217
19470
|
if (entry.name === "archive" && dir.includes("session-state")) continue;
|
|
19218
19471
|
if (entry.name === "archive" && dir.includes("status")) continue;
|
|
@@ -19269,8 +19522,8 @@ function categorizeFile(filePath) {
|
|
|
19269
19522
|
if (knownCategories.includes(firstDir)) return firstDir;
|
|
19270
19523
|
return "root";
|
|
19271
19524
|
}
|
|
19272
|
-
function
|
|
19273
|
-
return
|
|
19525
|
+
function hashContent2(content) {
|
|
19526
|
+
return createHash4("sha256").update(content).digest("hex");
|
|
19274
19527
|
}
|
|
19275
19528
|
function parseCRTable(content) {
|
|
19276
19529
|
const rules = [];
|
|
@@ -19490,11 +19743,11 @@ function indexAllKnowledge(db) {
|
|
|
19490
19743
|
files.push(...memFiles);
|
|
19491
19744
|
} catch {
|
|
19492
19745
|
}
|
|
19493
|
-
if (
|
|
19746
|
+
if (existsSync23(paths.plansDir)) {
|
|
19494
19747
|
const planFiles = discoverMarkdownFiles(paths.plansDir);
|
|
19495
19748
|
files.push(...planFiles);
|
|
19496
19749
|
}
|
|
19497
|
-
if (
|
|
19750
|
+
if (existsSync23(paths.docsDir)) {
|
|
19498
19751
|
const excludePatterns = getConfig().conventions?.excludePatterns ?? ["/ARCHIVE/", "/SESSION-HISTORY/"];
|
|
19499
19752
|
const docsFiles = discoverMarkdownFiles(paths.docsDir).filter((f2) => !f2.includes("/plans/") && !excludePatterns.some((p19) => f2.includes(p19)));
|
|
19500
19753
|
files.push(...docsFiles);
|
|
@@ -19537,9 +19790,9 @@ function indexAllKnowledge(db) {
|
|
|
19537
19790
|
} catch {
|
|
19538
19791
|
}
|
|
19539
19792
|
for (const filePath of files) {
|
|
19540
|
-
if (!
|
|
19541
|
-
const content =
|
|
19542
|
-
const hash =
|
|
19793
|
+
if (!existsSync23(filePath)) continue;
|
|
19794
|
+
const content = readFileSync23(filePath, "utf-8");
|
|
19795
|
+
const hash = hashContent2(content);
|
|
19543
19796
|
const relPath = filePath.startsWith(paths.claudeDir) ? relative10(paths.claudeDir, filePath) : filePath.startsWith(paths.plansDir) ? "plans/" + relative10(paths.plansDir, filePath) : filePath.startsWith(paths.docsDir) ? "docs/" + relative10(paths.docsDir, filePath) : filePath.startsWith(paths.memoryDir) ? `memory/${relative10(paths.memoryDir, filePath)}` : basename5(filePath);
|
|
19544
19797
|
const category = categorizeFile(filePath);
|
|
19545
19798
|
const title = extractTitle(content, filePath);
|
|
@@ -19658,10 +19911,10 @@ function isKnowledgeStale(db) {
|
|
|
19658
19911
|
files.push(...discoverMarkdownFiles(paths.memoryDir));
|
|
19659
19912
|
} catch {
|
|
19660
19913
|
}
|
|
19661
|
-
if (
|
|
19914
|
+
if (existsSync23(paths.plansDir)) {
|
|
19662
19915
|
files.push(...discoverMarkdownFiles(paths.plansDir));
|
|
19663
19916
|
}
|
|
19664
|
-
if (
|
|
19917
|
+
if (existsSync23(paths.docsDir)) {
|
|
19665
19918
|
const excludePatterns = getConfig().conventions?.excludePatterns ?? ["/ARCHIVE/", "/SESSION-HISTORY/"];
|
|
19666
19919
|
const docsFiles = discoverMarkdownFiles(paths.docsDir).filter((f2) => !f2.includes("/plans/") && !excludePatterns.some((p19) => f2.includes(p19)));
|
|
19667
19920
|
files.push(...docsFiles);
|
|
@@ -19690,8 +19943,8 @@ var init_knowledge_indexer = __esm({
|
|
|
19690
19943
|
});
|
|
19691
19944
|
|
|
19692
19945
|
// src/knowledge-tools.ts
|
|
19693
|
-
import { readFileSync as
|
|
19694
|
-
import { resolve as
|
|
19946
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync3, appendFileSync, readdirSync as readdirSync18 } from "fs";
|
|
19947
|
+
import { resolve as resolve19, basename as basename6 } from "path";
|
|
19695
19948
|
function p16(baseName) {
|
|
19696
19949
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
19697
19950
|
}
|
|
@@ -20428,7 +20681,7 @@ function handleCorrect(db, args2) {
|
|
|
20428
20681
|
if (!wrong || !correction || !rule) {
|
|
20429
20682
|
return text15("Error: wrong, correction, and rule are all required.");
|
|
20430
20683
|
}
|
|
20431
|
-
const correctionsPath =
|
|
20684
|
+
const correctionsPath = resolve19(getResolvedPaths().memoryDir, "corrections.md");
|
|
20432
20685
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
20433
20686
|
const title = rule.slice(0, 60);
|
|
20434
20687
|
const entry = `
|
|
@@ -20441,7 +20694,7 @@ ${crRule ? `- **CR**: ${crRule}
|
|
|
20441
20694
|
`;
|
|
20442
20695
|
let existing = "";
|
|
20443
20696
|
try {
|
|
20444
|
-
existing =
|
|
20697
|
+
existing = readFileSync24(correctionsPath, "utf-8");
|
|
20445
20698
|
} catch {
|
|
20446
20699
|
}
|
|
20447
20700
|
const archiveIdx = existing.indexOf("## Archived");
|
|
@@ -20780,11 +21033,11 @@ var init_knowledge_tools = __esm({
|
|
|
20780
21033
|
// src/knowledge-db.ts
|
|
20781
21034
|
import Database3 from "better-sqlite3";
|
|
20782
21035
|
import { dirname as dirname10 } from "path";
|
|
20783
|
-
import { existsSync as
|
|
21036
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync5 } from "fs";
|
|
20784
21037
|
function getKnowledgeDb() {
|
|
20785
21038
|
const dbPath = getResolvedPaths().knowledgeDbPath;
|
|
20786
21039
|
const dir = dirname10(dbPath);
|
|
20787
|
-
if (!
|
|
21040
|
+
if (!existsSync25(dir)) {
|
|
20788
21041
|
mkdirSync5(dir, { recursive: true });
|
|
20789
21042
|
}
|
|
20790
21043
|
const db = new Database3(dbPath);
|
|
@@ -21518,8 +21771,8 @@ var init_python_tools = __esm({
|
|
|
21518
21771
|
});
|
|
21519
21772
|
|
|
21520
21773
|
// src/tools.ts
|
|
21521
|
-
import { readFileSync as
|
|
21522
|
-
import { resolve as
|
|
21774
|
+
import { readFileSync as readFileSync25, existsSync as existsSync26 } from "fs";
|
|
21775
|
+
import { resolve as resolve20, basename as basename7 } from "path";
|
|
21523
21776
|
function prefix2() {
|
|
21524
21777
|
return getConfig().toolPrefix;
|
|
21525
21778
|
}
|
|
@@ -21554,7 +21807,7 @@ function ensureIndexes(dataDb2, codegraphDb2, force = false) {
|
|
|
21554
21807
|
if (config.python?.root) {
|
|
21555
21808
|
const pythonRoot = config.python.root;
|
|
21556
21809
|
const excludeDirs = config.python.exclude_dirs || ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"];
|
|
21557
|
-
if (force || isPythonDataStale(dataDb2,
|
|
21810
|
+
if (force || isPythonDataStale(dataDb2, resolve20(getProjectRoot(), pythonRoot))) {
|
|
21558
21811
|
const pyImports = buildPythonImportIndex(dataDb2, pythonRoot, excludeDirs);
|
|
21559
21812
|
results.push(`Python imports: ${pyImports}`);
|
|
21560
21813
|
const pyRoutes = buildPythonRouteIndex(dataDb2, pythonRoot, excludeDirs);
|
|
@@ -21953,9 +22206,9 @@ function handleContext(file, dataDb2, codegraphDb2) {
|
|
|
21953
22206
|
try {
|
|
21954
22207
|
const resolvedPaths = getResolvedPaths();
|
|
21955
22208
|
const root = getProjectRoot();
|
|
21956
|
-
const absFilePath = ensureWithinRoot(
|
|
21957
|
-
if (
|
|
21958
|
-
const fileContent =
|
|
22209
|
+
const absFilePath = ensureWithinRoot(resolve20(resolvedPaths.srcDir, "..", file), root);
|
|
22210
|
+
if (existsSync26(absFilePath)) {
|
|
22211
|
+
const fileContent = readFileSync25(absFilePath, "utf-8").slice(0, 3e3);
|
|
21959
22212
|
const keywords = [];
|
|
21960
22213
|
if (fileContent.includes("ctx.db")) keywords.push("database", "schema");
|
|
21961
22214
|
if (fileContent.includes("BigInt") || fileContent.includes("Decimal")) keywords.push("BigInt", "serialization");
|
|
@@ -22379,11 +22632,11 @@ function handleSchema(args2) {
|
|
|
22379
22632
|
lines.push("Checking all column references against Prisma schema...");
|
|
22380
22633
|
lines.push("");
|
|
22381
22634
|
const projectRoot = getProjectRoot();
|
|
22382
|
-
const absPath = ensureWithinRoot(
|
|
22383
|
-
if (!
|
|
22635
|
+
const absPath = ensureWithinRoot(resolve20(projectRoot, file), projectRoot);
|
|
22636
|
+
if (!existsSync26(absPath)) {
|
|
22384
22637
|
return text17(`File not found: ${file}`);
|
|
22385
22638
|
}
|
|
22386
|
-
const source =
|
|
22639
|
+
const source = readFileSync25(absPath, "utf-8");
|
|
22387
22640
|
const config = getConfig();
|
|
22388
22641
|
const dbPattern = config.dbAccessPattern ?? "ctx.db.{table}";
|
|
22389
22642
|
const regexStr = dbPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace("\\{table\\}", "(\\w+)");
|
|
@@ -22461,8 +22714,8 @@ var init_tools = __esm({
|
|
|
22461
22714
|
|
|
22462
22715
|
// src/server.ts
|
|
22463
22716
|
var server_exports = {};
|
|
22464
|
-
import { readFileSync as
|
|
22465
|
-
import { resolve as
|
|
22717
|
+
import { readFileSync as readFileSync26 } from "fs";
|
|
22718
|
+
import { resolve as resolve21, dirname as dirname11 } from "path";
|
|
22466
22719
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
22467
22720
|
function getDb() {
|
|
22468
22721
|
if (!codegraphDb) codegraphDb = getCodeGraphDb();
|
|
@@ -22557,7 +22810,7 @@ var init_server = __esm({
|
|
|
22557
22810
|
__dirname4 = dirname11(fileURLToPath4(import.meta.url));
|
|
22558
22811
|
PKG_VERSION = (() => {
|
|
22559
22812
|
try {
|
|
22560
|
-
const pkg = JSON.parse(
|
|
22813
|
+
const pkg = JSON.parse(readFileSync26(resolve21(__dirname4, "..", "package.json"), "utf-8"));
|
|
22561
22814
|
return pkg.version ?? "0.0.0";
|
|
22562
22815
|
} catch {
|
|
22563
22816
|
return "0.0.0";
|
|
@@ -22669,8 +22922,8 @@ __export(config_refresh_exports, {
|
|
|
22669
22922
|
mergeRefresh: () => mergeRefresh,
|
|
22670
22923
|
runConfigRefresh: () => runConfigRefresh
|
|
22671
22924
|
});
|
|
22672
|
-
import { existsSync as
|
|
22673
|
-
import { resolve as
|
|
22925
|
+
import { existsSync as existsSync27, readFileSync as readFileSync27 } from "fs";
|
|
22926
|
+
import { resolve as resolve22 } from "path";
|
|
22674
22927
|
import { parse as parseYaml5 } from "yaml";
|
|
22675
22928
|
function flatten(obj, prefix3 = "") {
|
|
22676
22929
|
const out = {};
|
|
@@ -22798,17 +23051,17 @@ function renderDiff(diff) {
|
|
|
22798
23051
|
}
|
|
22799
23052
|
async function runConfigRefresh(opts = {}) {
|
|
22800
23053
|
const cwd = opts.cwd ?? process.cwd();
|
|
22801
|
-
const configPath =
|
|
23054
|
+
const configPath = resolve22(cwd, "massu.config.yaml");
|
|
22802
23055
|
const log = opts.silent ? () => {
|
|
22803
23056
|
} : (s) => process.stdout.write(s);
|
|
22804
|
-
if (!
|
|
23057
|
+
if (!existsSync27(configPath)) {
|
|
22805
23058
|
const message = "massu.config.yaml not found. Run: npx massu init";
|
|
22806
23059
|
if (!opts.silent) process.stderr.write(message + "\n");
|
|
22807
23060
|
return { exitCode: 1, applied: false, dryRun: !!opts.dryRun, diff: [], message };
|
|
22808
23061
|
}
|
|
22809
23062
|
let existing;
|
|
22810
23063
|
try {
|
|
22811
|
-
const content =
|
|
23064
|
+
const content = readFileSync27(configPath, "utf-8");
|
|
22812
23065
|
const parsed = parseYaml5(content);
|
|
22813
23066
|
if (!parsed || typeof parsed !== "object") {
|
|
22814
23067
|
throw new Error("config is not a YAML object");
|
|
@@ -23138,19 +23391,19 @@ var config_upgrade_exports = {};
|
|
|
23138
23391
|
__export(config_upgrade_exports, {
|
|
23139
23392
|
runConfigUpgrade: () => runConfigUpgrade
|
|
23140
23393
|
});
|
|
23141
|
-
import { existsSync as
|
|
23142
|
-
import { resolve as
|
|
23394
|
+
import { existsSync as existsSync28, readFileSync as readFileSync28, writeFileSync as writeFileSync4, copyFileSync, unlinkSync } from "fs";
|
|
23395
|
+
import { resolve as resolve23 } from "path";
|
|
23143
23396
|
import { parse as parseYaml6 } from "yaml";
|
|
23144
23397
|
async function runConfigUpgrade(opts = {}) {
|
|
23145
23398
|
const cwd = opts.cwd ?? process.cwd();
|
|
23146
|
-
const configPath =
|
|
23399
|
+
const configPath = resolve23(cwd, "massu.config.yaml");
|
|
23147
23400
|
const bakPath = `${configPath}.bak`;
|
|
23148
23401
|
const log = opts.silent ? () => {
|
|
23149
23402
|
} : (s) => process.stdout.write(s);
|
|
23150
23403
|
const err = opts.silent ? () => {
|
|
23151
23404
|
} : (s) => process.stderr.write(s);
|
|
23152
23405
|
if (opts.rollback) {
|
|
23153
|
-
if (!
|
|
23406
|
+
if (!existsSync28(bakPath)) {
|
|
23154
23407
|
const message = `No backup found at ${bakPath}`;
|
|
23155
23408
|
err(message + "\n");
|
|
23156
23409
|
return { exitCode: 1, action: "none", message };
|
|
@@ -23166,14 +23419,14 @@ async function runConfigUpgrade(opts = {}) {
|
|
|
23166
23419
|
return { exitCode: 2, action: "none", message };
|
|
23167
23420
|
}
|
|
23168
23421
|
}
|
|
23169
|
-
if (!
|
|
23422
|
+
if (!existsSync28(configPath)) {
|
|
23170
23423
|
const message = "massu.config.yaml not found. Run: npx massu init";
|
|
23171
23424
|
err(message + "\n");
|
|
23172
23425
|
return { exitCode: 1, action: "none", message };
|
|
23173
23426
|
}
|
|
23174
23427
|
let existing;
|
|
23175
23428
|
try {
|
|
23176
|
-
const content =
|
|
23429
|
+
const content = readFileSync28(configPath, "utf-8");
|
|
23177
23430
|
const parsed = parseYaml6(content);
|
|
23178
23431
|
if (!parsed || typeof parsed !== "object") {
|
|
23179
23432
|
throw new Error("config is not a YAML object");
|
|
@@ -23196,7 +23449,7 @@ async function runConfigUpgrade(opts = {}) {
|
|
|
23196
23449
|
fingerprint: computeFingerprint(detection)
|
|
23197
23450
|
};
|
|
23198
23451
|
try {
|
|
23199
|
-
const original =
|
|
23452
|
+
const original = readFileSync28(configPath, "utf-8");
|
|
23200
23453
|
writeFileSync4(bakPath, original, "utf-8");
|
|
23201
23454
|
} catch (e2) {
|
|
23202
23455
|
const message = `Failed to write backup: ${e2 instanceof Error ? e2.message : String(e2)}`;
|
|
@@ -23230,8 +23483,8 @@ var config_check_drift_exports = {};
|
|
|
23230
23483
|
__export(config_check_drift_exports, {
|
|
23231
23484
|
runConfigCheckDrift: () => runConfigCheckDrift
|
|
23232
23485
|
});
|
|
23233
|
-
import { existsSync as
|
|
23234
|
-
import { resolve as
|
|
23486
|
+
import { existsSync as existsSync29, readFileSync as readFileSync29 } from "fs";
|
|
23487
|
+
import { resolve as resolve24 } from "path";
|
|
23235
23488
|
import { parse as parseYaml7 } from "yaml";
|
|
23236
23489
|
function renderChanges(changes) {
|
|
23237
23490
|
if (changes.length === 0) return "(none)\n";
|
|
@@ -23239,12 +23492,12 @@ function renderChanges(changes) {
|
|
|
23239
23492
|
}
|
|
23240
23493
|
async function runConfigCheckDrift(opts = {}) {
|
|
23241
23494
|
const cwd = opts.cwd ?? process.cwd();
|
|
23242
|
-
const configPath =
|
|
23495
|
+
const configPath = resolve24(cwd, "massu.config.yaml");
|
|
23243
23496
|
const log = opts.silent ? () => {
|
|
23244
23497
|
} : (s) => process.stdout.write(s);
|
|
23245
23498
|
const err = opts.silent ? () => {
|
|
23246
23499
|
} : (s) => process.stderr.write(s);
|
|
23247
|
-
if (!
|
|
23500
|
+
if (!existsSync29(configPath)) {
|
|
23248
23501
|
const message = "massu.config.yaml not found. Run: npx massu init";
|
|
23249
23502
|
err(message + "\n");
|
|
23250
23503
|
return {
|
|
@@ -23258,7 +23511,7 @@ async function runConfigCheckDrift(opts = {}) {
|
|
|
23258
23511
|
}
|
|
23259
23512
|
let config;
|
|
23260
23513
|
try {
|
|
23261
|
-
const content =
|
|
23514
|
+
const content = readFileSync29(configPath, "utf-8");
|
|
23262
23515
|
const parsed = parseYaml7(content);
|
|
23263
23516
|
if (!parsed || typeof parsed !== "object") {
|
|
23264
23517
|
throw new Error("config is not a YAML object");
|
|
@@ -23325,8 +23578,8 @@ var init_config_check_drift = __esm({
|
|
|
23325
23578
|
});
|
|
23326
23579
|
|
|
23327
23580
|
// src/cli.ts
|
|
23328
|
-
import { readFileSync as
|
|
23329
|
-
import { resolve as
|
|
23581
|
+
import { readFileSync as readFileSync30 } from "fs";
|
|
23582
|
+
import { resolve as resolve25, dirname as dirname12 } from "path";
|
|
23330
23583
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
23331
23584
|
var __filename4 = fileURLToPath5(import.meta.url);
|
|
23332
23585
|
var __dirname5 = dirname12(__filename4);
|
|
@@ -23354,6 +23607,11 @@ async function main() {
|
|
|
23354
23607
|
await runInstallCommands2();
|
|
23355
23608
|
break;
|
|
23356
23609
|
}
|
|
23610
|
+
case "show-template": {
|
|
23611
|
+
const { runShowTemplate: runShowTemplate2 } = await Promise.resolve().then(() => (init_show_template(), show_template_exports));
|
|
23612
|
+
await runShowTemplate2(args.slice(1));
|
|
23613
|
+
break;
|
|
23614
|
+
}
|
|
23357
23615
|
case "validate-config": {
|
|
23358
23616
|
const { runValidateConfig: runValidateConfig2 } = await Promise.resolve().then(() => (init_doctor(), doctor_exports));
|
|
23359
23617
|
await runValidateConfig2();
|
|
@@ -23440,6 +23698,7 @@ Commands:
|
|
|
23440
23698
|
doctor Check installation health
|
|
23441
23699
|
install-hooks Install/update Claude Code hooks
|
|
23442
23700
|
install-commands Install/update slash commands
|
|
23701
|
+
show-template Print the resolved variant of a bundled template (e.g. for diffs)
|
|
23443
23702
|
validate-config Validate massu.config.yaml (alias: config validate)
|
|
23444
23703
|
config <sub> Config lifecycle: refresh | validate | upgrade | doctor | check-drift
|
|
23445
23704
|
|
|
@@ -23478,7 +23737,7 @@ Examples:
|
|
|
23478
23737
|
}
|
|
23479
23738
|
function printVersion() {
|
|
23480
23739
|
try {
|
|
23481
|
-
const pkg = JSON.parse(
|
|
23740
|
+
const pkg = JSON.parse(readFileSync30(resolve25(__dirname5, "../package.json"), "utf-8"));
|
|
23482
23741
|
console.log(`massu v${pkg.version}`);
|
|
23483
23742
|
} catch {
|
|
23484
23743
|
console.log("massu v0.1.0");
|