@massu/core 1.9.3 → 1.10.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/dist/cli.js +561 -283
- package/dist/hooks/auto-learning-pipeline.js +30 -8
- package/dist/hooks/classify-failure.js +8 -1
- package/dist/hooks/cost-tracker.js +8 -1
- package/dist/hooks/fix-detector.js +3 -3
- package/dist/hooks/incident-pipeline.js +8 -1
- package/dist/hooks/post-edit-context.js +8 -1
- package/dist/hooks/post-tool-use.js +98 -1
- package/dist/hooks/pre-compact.js +8 -1
- package/dist/hooks/pre-delete-check.js +8 -1
- package/dist/hooks/quality-event.js +8 -1
- package/dist/hooks/session-end.js +18 -2
- package/dist/hooks/session-start.js +8 -1
- package/dist/hooks/user-prompt.js +8 -1
- package/package.json +2 -2
- package/src/backfill-sessions.ts +3 -2
- package/src/cli.ts +10 -0
- package/src/cloud-sync.ts +18 -0
- package/src/commands/doctor.ts +9 -14
- package/src/commands/hook-runner.ts +145 -0
- package/src/commands/init.ts +239 -29
- package/src/commands/install-commands.ts +10 -0
- package/src/commands/install-hooks.ts +2 -1
- package/src/commands/template-engine.ts +41 -0
- package/src/config.ts +2 -1
- package/src/hooks/auto-learning-pipeline.ts +43 -10
- package/src/hooks/fix-detector.ts +3 -3
- package/src/hooks/post-tool-use.ts +91 -1
- package/src/lib/hook-registry.ts +43 -0
- package/src/lib/memory-path.ts +49 -0
- package/src/security/registry-pubkey.generated.ts +1 -1
- package/src/tool-db-needs.ts +8 -2
- package/src/tools.ts +23 -7
package/dist/cli.js
CHANGED
|
@@ -39,6 +39,16 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
39
39
|
mod
|
|
40
40
|
));
|
|
41
41
|
|
|
42
|
+
// src/lib/memory-path.ts
|
|
43
|
+
function encodeMemoryDirName(projectRoot) {
|
|
44
|
+
return projectRoot.replace(/\//g, "-");
|
|
45
|
+
}
|
|
46
|
+
var init_memory_path = __esm({
|
|
47
|
+
"src/lib/memory-path.ts"() {
|
|
48
|
+
"use strict";
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
42
52
|
// src/config.ts
|
|
43
53
|
import { resolve, dirname } from "path";
|
|
44
54
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -193,7 +203,7 @@ function getResolvedPaths() {
|
|
|
193
203
|
plansDir: resolve(root, "docs/plans"),
|
|
194
204
|
docsDir: resolve(root, "docs"),
|
|
195
205
|
claudeDir: resolve(root, claudeDirName),
|
|
196
|
-
memoryDir: resolve(homedir(), claudeDirName, "projects", root
|
|
206
|
+
memoryDir: resolve(homedir(), claudeDirName, "projects", encodeMemoryDirName(root), "memory"),
|
|
197
207
|
sessionStatePath: resolve(root, config.conventions?.sessionStatePath ?? `${claudeDirName}/session-state/CURRENT.md`),
|
|
198
208
|
sessionArchivePath: resolve(root, config.conventions?.sessionArchivePath ?? `${claudeDirName}/session-state/archive`),
|
|
199
209
|
mcpJsonPath: resolve(root, ".mcp.json"),
|
|
@@ -208,6 +218,7 @@ var DomainConfigSchema, PatternRuleConfigSchema, CostModelSchema, AnalyticsConfi
|
|
|
208
218
|
var init_config = __esm({
|
|
209
219
|
"src/config.ts"() {
|
|
210
220
|
"use strict";
|
|
221
|
+
init_memory_path();
|
|
211
222
|
DomainConfigSchema = z.object({
|
|
212
223
|
name: z.string().default("Unknown"),
|
|
213
224
|
routers: z.array(z.string()).default([]),
|
|
@@ -1761,6 +1772,13 @@ function renderTemplate(template, vars) {
|
|
|
1761
1772
|
throw new TemplateParseError("unclosed `{{` (no matching `}}`)", tokenStart);
|
|
1762
1773
|
}
|
|
1763
1774
|
const inner = template.slice(i + 2, closeIdx);
|
|
1775
|
+
if (isJsxPassThrough(inner)) {
|
|
1776
|
+
out.push("{{");
|
|
1777
|
+
out.push(inner);
|
|
1778
|
+
out.push("}}");
|
|
1779
|
+
i = closeIdx + 2;
|
|
1780
|
+
continue;
|
|
1781
|
+
}
|
|
1764
1782
|
const rendered = renderToken(inner, vars, tokenStart);
|
|
1765
1783
|
out.push(rendered);
|
|
1766
1784
|
i = closeIdx + 2;
|
|
@@ -1802,6 +1820,9 @@ function findTokenClose(template, start) {
|
|
|
1802
1820
|
}
|
|
1803
1821
|
return -1;
|
|
1804
1822
|
}
|
|
1823
|
+
function isJsxPassThrough(inner) {
|
|
1824
|
+
return inner.includes("\n");
|
|
1825
|
+
}
|
|
1805
1826
|
function renderToken(inner, vars, tokenStart) {
|
|
1806
1827
|
const trimmed = inner.trim();
|
|
1807
1828
|
if (trimmed === "") {
|
|
@@ -2451,7 +2472,17 @@ function buildTemplateVars() {
|
|
|
2451
2472
|
framework: config.framework,
|
|
2452
2473
|
paths: config.paths,
|
|
2453
2474
|
detected: config.detected ?? {},
|
|
2454
|
-
config
|
|
2475
|
+
config,
|
|
2476
|
+
// P-H006 (plan-stage-c-high-batch): RESERVED CLAUDE CODE PLACEHOLDER.
|
|
2477
|
+
// Claude Code reads `{{ARGUMENTS}}` as a runtime placeholder inside
|
|
2478
|
+
// slash-command files. The Massu template engine has no native concept
|
|
2479
|
+
// of reserved literals; we model the placeholder as a variable whose
|
|
2480
|
+
// value IS the literal `{{ARGUMENTS}}` string. Because the engine never
|
|
2481
|
+
// re-renders output, this passes through verbatim. Closes the bug class
|
|
2482
|
+
// where `/massu-article-review`, `/massu-autoresearch`, etc. silently
|
|
2483
|
+
// failed to install because the engine threw MissingVariableError on
|
|
2484
|
+
// their {{ARGUMENTS}} usage.
|
|
2485
|
+
ARGUMENTS: "{{ARGUMENTS}}"
|
|
2455
2486
|
};
|
|
2456
2487
|
}
|
|
2457
2488
|
function installCommands(projectRoot, opts = {}) {
|
|
@@ -8045,41 +8076,41 @@ var require_queue = __commonJS({
|
|
|
8045
8076
|
queue.drained = drained;
|
|
8046
8077
|
return queue;
|
|
8047
8078
|
function push(value) {
|
|
8048
|
-
var p19 = new Promise(function(
|
|
8079
|
+
var p19 = new Promise(function(resolve41, reject) {
|
|
8049
8080
|
pushCb(value, function(err, result) {
|
|
8050
8081
|
if (err) {
|
|
8051
8082
|
reject(err);
|
|
8052
8083
|
return;
|
|
8053
8084
|
}
|
|
8054
|
-
|
|
8085
|
+
resolve41(result);
|
|
8055
8086
|
});
|
|
8056
8087
|
});
|
|
8057
8088
|
p19.catch(noop);
|
|
8058
8089
|
return p19;
|
|
8059
8090
|
}
|
|
8060
8091
|
function unshift(value) {
|
|
8061
|
-
var p19 = new Promise(function(
|
|
8092
|
+
var p19 = new Promise(function(resolve41, reject) {
|
|
8062
8093
|
unshiftCb(value, function(err, result) {
|
|
8063
8094
|
if (err) {
|
|
8064
8095
|
reject(err);
|
|
8065
8096
|
return;
|
|
8066
8097
|
}
|
|
8067
|
-
|
|
8098
|
+
resolve41(result);
|
|
8068
8099
|
});
|
|
8069
8100
|
});
|
|
8070
8101
|
p19.catch(noop);
|
|
8071
8102
|
return p19;
|
|
8072
8103
|
}
|
|
8073
8104
|
function drained() {
|
|
8074
|
-
var p19 = new Promise(function(
|
|
8105
|
+
var p19 = new Promise(function(resolve41) {
|
|
8075
8106
|
process.nextTick(function() {
|
|
8076
8107
|
if (queue.idle()) {
|
|
8077
|
-
|
|
8108
|
+
resolve41();
|
|
8078
8109
|
} else {
|
|
8079
8110
|
var previousDrain = queue.drain;
|
|
8080
8111
|
queue.drain = function() {
|
|
8081
8112
|
if (typeof previousDrain === "function") previousDrain();
|
|
8082
|
-
|
|
8113
|
+
resolve41();
|
|
8083
8114
|
queue.drain = previousDrain;
|
|
8084
8115
|
};
|
|
8085
8116
|
}
|
|
@@ -8565,9 +8596,9 @@ var require_stream3 = __commonJS({
|
|
|
8565
8596
|
});
|
|
8566
8597
|
}
|
|
8567
8598
|
_getStat(filepath) {
|
|
8568
|
-
return new Promise((
|
|
8599
|
+
return new Promise((resolve41, reject) => {
|
|
8569
8600
|
this._stat(filepath, this._fsStatSettings, (error, stats) => {
|
|
8570
|
-
return error === null ?
|
|
8601
|
+
return error === null ? resolve41(stats) : reject(error);
|
|
8571
8602
|
});
|
|
8572
8603
|
});
|
|
8573
8604
|
}
|
|
@@ -8591,10 +8622,10 @@ var require_async5 = __commonJS({
|
|
|
8591
8622
|
this._readerStream = new stream_1.default(this._settings);
|
|
8592
8623
|
}
|
|
8593
8624
|
dynamic(root, options) {
|
|
8594
|
-
return new Promise((
|
|
8625
|
+
return new Promise((resolve41, reject) => {
|
|
8595
8626
|
this._walkAsync(root, options, (error, entries) => {
|
|
8596
8627
|
if (error === null) {
|
|
8597
|
-
|
|
8628
|
+
resolve41(entries);
|
|
8598
8629
|
} else {
|
|
8599
8630
|
reject(error);
|
|
8600
8631
|
}
|
|
@@ -8604,10 +8635,10 @@ var require_async5 = __commonJS({
|
|
|
8604
8635
|
async static(patterns, options) {
|
|
8605
8636
|
const entries = [];
|
|
8606
8637
|
const stream = this._readerStream.static(patterns, options);
|
|
8607
|
-
return new Promise((
|
|
8638
|
+
return new Promise((resolve41, reject) => {
|
|
8608
8639
|
stream.once("error", reject);
|
|
8609
8640
|
stream.on("data", (entry) => entries.push(entry));
|
|
8610
|
-
stream.once("end", () =>
|
|
8641
|
+
stream.once("end", () => resolve41(entries));
|
|
8611
8642
|
});
|
|
8612
8643
|
}
|
|
8613
8644
|
};
|
|
@@ -12982,10 +13013,12 @@ __export(init_exports, {
|
|
|
12982
13013
|
detectFramework: () => detectFramework,
|
|
12983
13014
|
detectPython: () => detectPython,
|
|
12984
13015
|
generateConfig: () => generateConfig,
|
|
13016
|
+
getInstallerVersion: () => getInstallerVersion,
|
|
12985
13017
|
initMemoryDir: () => initMemoryDir,
|
|
12986
13018
|
installHooks: () => installHooks,
|
|
12987
13019
|
isTemplateName: () => isTemplateName,
|
|
12988
13020
|
listTemplates: () => listTemplates,
|
|
13021
|
+
mergeHooksConfig: () => mergeHooksConfig,
|
|
12989
13022
|
parseInitArgs: () => parseInitArgs,
|
|
12990
13023
|
printInitHelp: () => printInitHelp,
|
|
12991
13024
|
registerMcpServer: () => registerMcpServer,
|
|
@@ -13213,6 +13246,15 @@ function buildConfigFromDetection(opts) {
|
|
|
13213
13246
|
pathsSource = monorepoCommonRoot(detection.monorepo.packages);
|
|
13214
13247
|
}
|
|
13215
13248
|
}
|
|
13249
|
+
if (pathsSource === "src" && !existsSync11(resolve7(projectRoot, "src"))) {
|
|
13250
|
+
const fallbacks = ["app", "pages", "."];
|
|
13251
|
+
for (const fallback of fallbacks) {
|
|
13252
|
+
if (fallback === "." || existsSync11(resolve7(projectRoot, fallback))) {
|
|
13253
|
+
pathsSource = fallback;
|
|
13254
|
+
break;
|
|
13255
|
+
}
|
|
13256
|
+
}
|
|
13257
|
+
}
|
|
13216
13258
|
let monorepoRoots;
|
|
13217
13259
|
if (detection.monorepo.type !== "single") {
|
|
13218
13260
|
if (detection.monorepo.packages.length > 0) {
|
|
@@ -13529,6 +13571,26 @@ function copyTemplateConfig(templateName, targetPath, projectName) {
|
|
|
13529
13571
|
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
13530
13572
|
}
|
|
13531
13573
|
}
|
|
13574
|
+
function getInstallerVersion() {
|
|
13575
|
+
const candidates = [
|
|
13576
|
+
resolve7(__dirname2, "../package.json"),
|
|
13577
|
+
resolve7(__dirname2, "../../package.json")
|
|
13578
|
+
];
|
|
13579
|
+
for (const candidate of candidates) {
|
|
13580
|
+
if (existsSync11(candidate)) {
|
|
13581
|
+
try {
|
|
13582
|
+
const pkg = JSON.parse(readFileSync11(candidate, "utf-8"));
|
|
13583
|
+
if (typeof pkg.version === "string" && pkg.version.length > 0 && pkg.name === "@massu/core") {
|
|
13584
|
+
return pkg.version;
|
|
13585
|
+
}
|
|
13586
|
+
} catch {
|
|
13587
|
+
}
|
|
13588
|
+
}
|
|
13589
|
+
}
|
|
13590
|
+
throw new Error(
|
|
13591
|
+
"getInstallerVersion: could not resolve @massu/core package.json. This indicates a corrupt install. Re-install via `npx -y @massu/core init`."
|
|
13592
|
+
);
|
|
13593
|
+
}
|
|
13532
13594
|
function registerMcpServer(projectRoot) {
|
|
13533
13595
|
const mcpPath = resolve7(projectRoot, ".mcp.json");
|
|
13534
13596
|
let existing = {};
|
|
@@ -13543,10 +13605,11 @@ function registerMcpServer(projectRoot) {
|
|
|
13543
13605
|
if (servers.massu) {
|
|
13544
13606
|
return false;
|
|
13545
13607
|
}
|
|
13608
|
+
const version = getInstallerVersion();
|
|
13546
13609
|
servers.massu = {
|
|
13547
13610
|
type: "stdio",
|
|
13548
13611
|
command: "npx",
|
|
13549
|
-
args: ["-y",
|
|
13612
|
+
args: ["-y", `@massu/core@${version}`]
|
|
13550
13613
|
};
|
|
13551
13614
|
existing.mcpServers = servers;
|
|
13552
13615
|
writeFileSync2(mcpPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
|
|
@@ -13564,15 +13627,16 @@ function resolveHooksDir() {
|
|
|
13564
13627
|
}
|
|
13565
13628
|
return "node_modules/@massu/core/dist/hooks";
|
|
13566
13629
|
}
|
|
13567
|
-
function hookCmd(
|
|
13568
|
-
return `
|
|
13630
|
+
function hookCmd(version, hookName) {
|
|
13631
|
+
return `npx -y @massu/core@${version} hook-runner ${hookName}`;
|
|
13569
13632
|
}
|
|
13570
|
-
function buildHooksConfig(
|
|
13633
|
+
function buildHooksConfig(_hooksDir) {
|
|
13634
|
+
const version = getInstallerVersion();
|
|
13571
13635
|
return {
|
|
13572
13636
|
SessionStart: [
|
|
13573
13637
|
{
|
|
13574
13638
|
hooks: [
|
|
13575
|
-
{ type: "command", command: hookCmd(
|
|
13639
|
+
{ type: "command", command: hookCmd(version, "session-start"), timeout: 10 }
|
|
13576
13640
|
]
|
|
13577
13641
|
}
|
|
13578
13642
|
],
|
|
@@ -13580,32 +13644,32 @@ function buildHooksConfig(hooksDir) {
|
|
|
13580
13644
|
{
|
|
13581
13645
|
matcher: "Bash",
|
|
13582
13646
|
hooks: [
|
|
13583
|
-
{ type: "command", command: hookCmd(
|
|
13647
|
+
{ type: "command", command: hookCmd(version, "security-gate"), timeout: 5 }
|
|
13584
13648
|
]
|
|
13585
13649
|
},
|
|
13586
13650
|
{
|
|
13587
13651
|
matcher: "Bash|Write",
|
|
13588
13652
|
hooks: [
|
|
13589
|
-
{ type: "command", command: hookCmd(
|
|
13653
|
+
{ type: "command", command: hookCmd(version, "pre-delete-check"), timeout: 5 }
|
|
13590
13654
|
]
|
|
13591
13655
|
}
|
|
13592
13656
|
],
|
|
13593
13657
|
PostToolUse: [
|
|
13594
13658
|
{
|
|
13595
13659
|
hooks: [
|
|
13596
|
-
{ type: "command", command: hookCmd(
|
|
13597
|
-
{ type: "command", command: hookCmd(
|
|
13598
|
-
{ type: "command", command: hookCmd(
|
|
13660
|
+
{ type: "command", command: hookCmd(version, "post-tool-use"), timeout: 10 },
|
|
13661
|
+
{ type: "command", command: hookCmd(version, "quality-event"), timeout: 5 },
|
|
13662
|
+
{ type: "command", command: hookCmd(version, "cost-tracker"), timeout: 5 }
|
|
13599
13663
|
]
|
|
13600
13664
|
},
|
|
13601
13665
|
{
|
|
13602
13666
|
matcher: "Edit|Write",
|
|
13603
13667
|
hooks: [
|
|
13604
|
-
{ type: "command", command: hookCmd(
|
|
13668
|
+
{ type: "command", command: hookCmd(version, "post-edit-context"), timeout: 5 },
|
|
13605
13669
|
// Auto-learning pipeline — classifies failures and detects fixes on
|
|
13606
13670
|
// file changes. See Phase 5-6 of the autodetect plan.
|
|
13607
|
-
{ type: "command", command: hookCmd(
|
|
13608
|
-
{ type: "command", command: hookCmd(
|
|
13671
|
+
{ type: "command", command: hookCmd(version, "fix-detector"), timeout: 5 },
|
|
13672
|
+
{ type: "command", command: hookCmd(version, "classify-failure"), timeout: 5 }
|
|
13609
13673
|
]
|
|
13610
13674
|
},
|
|
13611
13675
|
{
|
|
@@ -13613,37 +13677,86 @@ function buildHooksConfig(hooksDir) {
|
|
|
13613
13677
|
hooks: [
|
|
13614
13678
|
// Incident + rule enforcement pipelines fire on Write-only (incidents
|
|
13615
13679
|
// are authored as .md files; rules are enforced after new-file drops).
|
|
13616
|
-
{ type: "command", command: hookCmd(
|
|
13617
|
-
{ type: "command", command: hookCmd(
|
|
13680
|
+
{ type: "command", command: hookCmd(version, "incident-pipeline"), timeout: 5 },
|
|
13681
|
+
{ type: "command", command: hookCmd(version, "rule-enforcement-pipeline"), timeout: 5 }
|
|
13618
13682
|
]
|
|
13619
13683
|
}
|
|
13620
13684
|
],
|
|
13621
13685
|
Stop: [
|
|
13622
13686
|
{
|
|
13623
13687
|
hooks: [
|
|
13624
|
-
{ type: "command", command: hookCmd(
|
|
13688
|
+
{ type: "command", command: hookCmd(version, "session-end"), timeout: 15 },
|
|
13625
13689
|
// Session-end auto-learning aggregation (failure-class roll-up).
|
|
13626
|
-
{ type: "command", command: hookCmd(
|
|
13690
|
+
{ type: "command", command: hookCmd(version, "auto-learning-pipeline"), timeout: 10 }
|
|
13627
13691
|
]
|
|
13628
13692
|
}
|
|
13629
13693
|
],
|
|
13630
13694
|
PreCompact: [
|
|
13631
13695
|
{
|
|
13632
13696
|
hooks: [
|
|
13633
|
-
{ type: "command", command: hookCmd(
|
|
13697
|
+
{ type: "command", command: hookCmd(version, "pre-compact"), timeout: 10 }
|
|
13634
13698
|
]
|
|
13635
13699
|
}
|
|
13636
13700
|
],
|
|
13637
13701
|
UserPromptSubmit: [
|
|
13638
13702
|
{
|
|
13639
13703
|
hooks: [
|
|
13640
|
-
{ type: "command", command: hookCmd(
|
|
13641
|
-
{ type: "command", command: hookCmd(
|
|
13704
|
+
{ type: "command", command: hookCmd(version, "user-prompt"), timeout: 5 },
|
|
13705
|
+
{ type: "command", command: hookCmd(version, "intent-suggester"), timeout: 5 }
|
|
13642
13706
|
]
|
|
13643
13707
|
}
|
|
13644
13708
|
]
|
|
13645
13709
|
};
|
|
13646
13710
|
}
|
|
13711
|
+
function mergeHooksConfig(existing, additions) {
|
|
13712
|
+
const eventNames = /* @__PURE__ */ new Set([
|
|
13713
|
+
...Object.keys(existing ?? {}),
|
|
13714
|
+
...Object.keys(additions ?? {})
|
|
13715
|
+
]);
|
|
13716
|
+
const merged = {};
|
|
13717
|
+
for (const event of eventNames) {
|
|
13718
|
+
const existingGroups = existing?.[event] ?? [];
|
|
13719
|
+
const additionGroups = additions?.[event] ?? [];
|
|
13720
|
+
const byMatcher = /* @__PURE__ */ new Map();
|
|
13721
|
+
for (const group of existingGroups) {
|
|
13722
|
+
const key = group.matcher ?? "";
|
|
13723
|
+
const existingGroup = byMatcher.get(key);
|
|
13724
|
+
if (existingGroup) {
|
|
13725
|
+
existingGroup.hooks = mergeHookEntries(existingGroup.hooks, group.hooks);
|
|
13726
|
+
} else {
|
|
13727
|
+
byMatcher.set(key, { ...group, hooks: [...group.hooks ?? []] });
|
|
13728
|
+
}
|
|
13729
|
+
}
|
|
13730
|
+
for (const group of additionGroups) {
|
|
13731
|
+
const key = group.matcher ?? "";
|
|
13732
|
+
const existingGroup = byMatcher.get(key);
|
|
13733
|
+
if (existingGroup) {
|
|
13734
|
+
existingGroup.hooks = mergeHookEntries(existingGroup.hooks, group.hooks);
|
|
13735
|
+
} else {
|
|
13736
|
+
byMatcher.set(key, { ...group, hooks: [...group.hooks ?? []] });
|
|
13737
|
+
}
|
|
13738
|
+
}
|
|
13739
|
+
merged[event] = Array.from(byMatcher.values());
|
|
13740
|
+
}
|
|
13741
|
+
return merged;
|
|
13742
|
+
}
|
|
13743
|
+
function mergeHookEntries(existing, additions) {
|
|
13744
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13745
|
+
const result = [];
|
|
13746
|
+
for (const entry of additions ?? []) {
|
|
13747
|
+
if (!entry || typeof entry.command !== "string") continue;
|
|
13748
|
+
if (seen.has(entry.command)) continue;
|
|
13749
|
+
seen.add(entry.command);
|
|
13750
|
+
result.push(entry);
|
|
13751
|
+
}
|
|
13752
|
+
for (const entry of existing ?? []) {
|
|
13753
|
+
if (!entry || typeof entry.command !== "string") continue;
|
|
13754
|
+
if (seen.has(entry.command)) continue;
|
|
13755
|
+
seen.add(entry.command);
|
|
13756
|
+
result.push(entry);
|
|
13757
|
+
}
|
|
13758
|
+
return result;
|
|
13759
|
+
}
|
|
13647
13760
|
function installHooks(projectRoot) {
|
|
13648
13761
|
let claudeDirName = ".claude";
|
|
13649
13762
|
try {
|
|
@@ -13656,21 +13769,39 @@ function installHooks(projectRoot) {
|
|
|
13656
13769
|
mkdirSync5(claudeDir, { recursive: true });
|
|
13657
13770
|
}
|
|
13658
13771
|
const settings = readSettingsLocal(claudeDir);
|
|
13659
|
-
const
|
|
13660
|
-
const
|
|
13772
|
+
const hooksConfig = buildHooksConfig(resolveHooksDir());
|
|
13773
|
+
const existingHooks = settings.hooks ?? {};
|
|
13774
|
+
const mergedHooks = mergeHooksConfig(existingHooks, hooksConfig);
|
|
13661
13775
|
let hookCount = 0;
|
|
13662
|
-
for (const groups of Object.values(
|
|
13776
|
+
for (const groups of Object.values(mergedHooks)) {
|
|
13663
13777
|
for (const group of groups) {
|
|
13664
13778
|
hookCount += group.hooks.length;
|
|
13665
13779
|
}
|
|
13666
13780
|
}
|
|
13667
|
-
settings.hooks =
|
|
13781
|
+
settings.hooks = mergedHooks;
|
|
13668
13782
|
writeSettingsLocalAtomic(claudeDir, settings);
|
|
13669
13783
|
return { installed: true, count: hookCount };
|
|
13670
13784
|
}
|
|
13671
13785
|
function initMemoryDir(projectRoot) {
|
|
13672
|
-
const encodedRoot =
|
|
13786
|
+
const encodedRoot = encodeMemoryDirName(projectRoot);
|
|
13673
13787
|
const memoryDir = resolve7(homedir4(), `.claude/projects/${encodedRoot}/memory`);
|
|
13788
|
+
let migratedFromLegacy = false;
|
|
13789
|
+
const legacyDir = resolve7(homedir4(), `.claude/projects/-${encodedRoot}/memory`);
|
|
13790
|
+
if (existsSync11(legacyDir) && !existsSync11(memoryDir)) {
|
|
13791
|
+
try {
|
|
13792
|
+
mkdirSync5(resolve7(memoryDir, ".."), { recursive: true });
|
|
13793
|
+
renameSync3(legacyDir, memoryDir);
|
|
13794
|
+
try {
|
|
13795
|
+
const legacyParent = resolve7(legacyDir, "..");
|
|
13796
|
+
if (existsSync11(legacyParent) && readdirSync10(legacyParent).length === 0) {
|
|
13797
|
+
rmSync2(legacyParent, { recursive: false });
|
|
13798
|
+
}
|
|
13799
|
+
} catch {
|
|
13800
|
+
}
|
|
13801
|
+
migratedFromLegacy = true;
|
|
13802
|
+
} catch {
|
|
13803
|
+
}
|
|
13804
|
+
}
|
|
13674
13805
|
let created = false;
|
|
13675
13806
|
if (!existsSync11(memoryDir)) {
|
|
13676
13807
|
mkdirSync5(memoryDir, { recursive: true });
|
|
@@ -13697,7 +13828,7 @@ function initMemoryDir(projectRoot) {
|
|
|
13697
13828
|
writeFileSync2(memoryMdPath, memoryContent, "utf-8");
|
|
13698
13829
|
memoryMdCreated = true;
|
|
13699
13830
|
}
|
|
13700
|
-
return { created, memoryMdCreated };
|
|
13831
|
+
return { created, memoryMdCreated, migratedFromLegacy };
|
|
13701
13832
|
}
|
|
13702
13833
|
function parseInitArgs(argv) {
|
|
13703
13834
|
const opts = {};
|
|
@@ -13956,16 +14087,19 @@ function installSideEffects(projectRoot, log, skipCommands = false, emptyStack =
|
|
|
13956
14087
|
} catch {
|
|
13957
14088
|
}
|
|
13958
14089
|
}
|
|
13959
|
-
const { created: memDirCreated, memoryMdCreated } = initMemoryDir(projectRoot);
|
|
14090
|
+
const { created: memDirCreated, memoryMdCreated, migratedFromLegacy } = initMemoryDir(projectRoot);
|
|
13960
14091
|
if (memDirCreated) {
|
|
13961
14092
|
log(" Created memory directory");
|
|
13962
14093
|
}
|
|
13963
14094
|
if (memoryMdCreated) {
|
|
13964
14095
|
log(" Created initial MEMORY.md");
|
|
13965
14096
|
}
|
|
14097
|
+
if (migratedFromLegacy) {
|
|
14098
|
+
log(" Migrated memory directory from legacy double-dash path (pre-1.9.4)");
|
|
14099
|
+
}
|
|
13966
14100
|
(async () => {
|
|
13967
14101
|
try {
|
|
13968
|
-
const encodedRoot = projectRoot
|
|
14102
|
+
const encodedRoot = encodeMemoryDirName(projectRoot);
|
|
13969
14103
|
const memoryDir = resolve7(homedir4(), ".claude", "projects", encodedRoot, "memory");
|
|
13970
14104
|
const memFiles = existsSync11(memoryDir) ? readdirSync10(memoryDir).filter((f2) => f2.endsWith(".md") && f2 !== "MEMORY.md") : [];
|
|
13971
14105
|
if (memFiles.length > 0) {
|
|
@@ -14025,6 +14159,7 @@ var init_init = __esm({
|
|
|
14025
14159
|
init_config();
|
|
14026
14160
|
init_install_commands();
|
|
14027
14161
|
init_settings_local();
|
|
14162
|
+
init_memory_path();
|
|
14028
14163
|
init_detect();
|
|
14029
14164
|
init_drift();
|
|
14030
14165
|
__filename2 = fileURLToPath2(import.meta.url);
|
|
@@ -14341,6 +14476,35 @@ var init_license = __esm({
|
|
|
14341
14476
|
}
|
|
14342
14477
|
});
|
|
14343
14478
|
|
|
14479
|
+
// src/lib/hook-registry.ts
|
|
14480
|
+
function getExpectedHookFiles() {
|
|
14481
|
+
return REGISTERED_HOOKS.map((name) => `${name}.js`);
|
|
14482
|
+
}
|
|
14483
|
+
var REGISTERED_HOOKS;
|
|
14484
|
+
var init_hook_registry = __esm({
|
|
14485
|
+
"src/lib/hook-registry.ts"() {
|
|
14486
|
+
"use strict";
|
|
14487
|
+
REGISTERED_HOOKS = [
|
|
14488
|
+
"auto-learning-pipeline",
|
|
14489
|
+
"classify-failure",
|
|
14490
|
+
"cost-tracker",
|
|
14491
|
+
"fix-detector",
|
|
14492
|
+
"incident-pipeline",
|
|
14493
|
+
"intent-suggester",
|
|
14494
|
+
"post-edit-context",
|
|
14495
|
+
"post-tool-use",
|
|
14496
|
+
"pre-compact",
|
|
14497
|
+
"pre-delete-check",
|
|
14498
|
+
"quality-event",
|
|
14499
|
+
"rule-enforcement-pipeline",
|
|
14500
|
+
"security-gate",
|
|
14501
|
+
"session-end",
|
|
14502
|
+
"session-start",
|
|
14503
|
+
"user-prompt"
|
|
14504
|
+
];
|
|
14505
|
+
}
|
|
14506
|
+
});
|
|
14507
|
+
|
|
14344
14508
|
// src/commands/doctor.ts
|
|
14345
14509
|
var doctor_exports = {};
|
|
14346
14510
|
__export(doctor_exports, {
|
|
@@ -14714,21 +14878,10 @@ var init_doctor = __esm({
|
|
|
14714
14878
|
init_config();
|
|
14715
14879
|
init_license();
|
|
14716
14880
|
init_settings_local();
|
|
14881
|
+
init_hook_registry();
|
|
14717
14882
|
__filename3 = fileURLToPath3(import.meta.url);
|
|
14718
14883
|
__dirname3 = dirname7(__filename3);
|
|
14719
|
-
EXPECTED_HOOKS =
|
|
14720
|
-
"session-start.js",
|
|
14721
|
-
"session-end.js",
|
|
14722
|
-
"post-tool-use.js",
|
|
14723
|
-
"user-prompt.js",
|
|
14724
|
-
"pre-compact.js",
|
|
14725
|
-
"pre-delete-check.js",
|
|
14726
|
-
"post-edit-context.js",
|
|
14727
|
-
"security-gate.js",
|
|
14728
|
-
"cost-tracker.js",
|
|
14729
|
-
"quality-event.js",
|
|
14730
|
-
"intent-suggester.js"
|
|
14731
|
-
];
|
|
14884
|
+
EXPECTED_HOOKS = getExpectedHookFiles();
|
|
14732
14885
|
}
|
|
14733
14886
|
});
|
|
14734
14887
|
|
|
@@ -14756,13 +14909,113 @@ var init_install_hooks = __esm({
|
|
|
14756
14909
|
}
|
|
14757
14910
|
});
|
|
14758
14911
|
|
|
14912
|
+
// src/commands/hook-runner.ts
|
|
14913
|
+
var hook_runner_exports = {};
|
|
14914
|
+
__export(hook_runner_exports, {
|
|
14915
|
+
HOOK_NAME_TO_FILE: () => HOOK_NAME_TO_FILE,
|
|
14916
|
+
resolveHookFile: () => resolveHookFile,
|
|
14917
|
+
runHookRunner: () => runHookRunner
|
|
14918
|
+
});
|
|
14919
|
+
import { existsSync as existsSync13 } from "fs";
|
|
14920
|
+
import { resolve as resolve9, dirname as dirname8 } from "path";
|
|
14921
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
14922
|
+
import { spawn } from "child_process";
|
|
14923
|
+
function resolveHookFile(hookName) {
|
|
14924
|
+
const file = HOOK_NAME_TO_FILE[hookName];
|
|
14925
|
+
if (!file) {
|
|
14926
|
+
throw new Error(
|
|
14927
|
+
`Unknown hook: "${hookName}". Recognized: ${Object.keys(HOOK_NAME_TO_FILE).join(", ")}`
|
|
14928
|
+
);
|
|
14929
|
+
}
|
|
14930
|
+
const candidates = [
|
|
14931
|
+
// Bundled compiled layout: dist/cli.js → ./hooks/<file>.js
|
|
14932
|
+
resolve9(__dirname4, "hooks", file),
|
|
14933
|
+
// TS-source dev / sibling layout: src/commands/ → ../hooks/<file>
|
|
14934
|
+
resolve9(__dirname4, "../hooks", file),
|
|
14935
|
+
// TS-source dev fallback: src/commands/ → ../../dist/hooks/<file>
|
|
14936
|
+
resolve9(__dirname4, "../../dist/hooks", file)
|
|
14937
|
+
];
|
|
14938
|
+
for (const candidate of candidates) {
|
|
14939
|
+
if (existsSync13(candidate)) {
|
|
14940
|
+
return candidate;
|
|
14941
|
+
}
|
|
14942
|
+
}
|
|
14943
|
+
throw new Error(
|
|
14944
|
+
`Hook file not found for "${hookName}". Searched: ${candidates.join(", ")}. This indicates a broken @massu/core install. Re-run \`npx -y @massu/core init\`.`
|
|
14945
|
+
);
|
|
14946
|
+
}
|
|
14947
|
+
async function runHookRunner(args2) {
|
|
14948
|
+
const hookName = args2[0];
|
|
14949
|
+
if (!hookName) {
|
|
14950
|
+
process.stderr.write(
|
|
14951
|
+
`massu hook-runner: missing hook name.
|
|
14952
|
+
Usage: massu hook-runner <hook-name>
|
|
14953
|
+
Recognized: ${Object.keys(HOOK_NAME_TO_FILE).join(", ")}
|
|
14954
|
+
`
|
|
14955
|
+
);
|
|
14956
|
+
return { exitCode: 2 };
|
|
14957
|
+
}
|
|
14958
|
+
let hookFile;
|
|
14959
|
+
try {
|
|
14960
|
+
hookFile = resolveHookFile(hookName);
|
|
14961
|
+
} catch (err) {
|
|
14962
|
+
process.stderr.write(`massu hook-runner: ${err instanceof Error ? err.message : String(err)}
|
|
14963
|
+
`);
|
|
14964
|
+
return { exitCode: 2 };
|
|
14965
|
+
}
|
|
14966
|
+
return new Promise((resolvePromise) => {
|
|
14967
|
+
const child = spawn(process.execPath, [hookFile], {
|
|
14968
|
+
stdio: ["inherit", "inherit", "inherit"],
|
|
14969
|
+
env: process.env
|
|
14970
|
+
});
|
|
14971
|
+
child.on("exit", (code, signal) => {
|
|
14972
|
+
if (signal) {
|
|
14973
|
+
resolvePromise({ exitCode: 128 });
|
|
14974
|
+
return;
|
|
14975
|
+
}
|
|
14976
|
+
resolvePromise({ exitCode: code ?? 0 });
|
|
14977
|
+
});
|
|
14978
|
+
child.on("error", (err) => {
|
|
14979
|
+
process.stderr.write(`massu hook-runner: failed to spawn hook "${hookName}": ${err.message}
|
|
14980
|
+
`);
|
|
14981
|
+
resolvePromise({ exitCode: 2 });
|
|
14982
|
+
});
|
|
14983
|
+
});
|
|
14984
|
+
}
|
|
14985
|
+
var __filename4, __dirname4, HOOK_NAME_TO_FILE;
|
|
14986
|
+
var init_hook_runner = __esm({
|
|
14987
|
+
"src/commands/hook-runner.ts"() {
|
|
14988
|
+
"use strict";
|
|
14989
|
+
__filename4 = fileURLToPath4(import.meta.url);
|
|
14990
|
+
__dirname4 = dirname8(__filename4);
|
|
14991
|
+
HOOK_NAME_TO_FILE = {
|
|
14992
|
+
"session-start": "session-start.js",
|
|
14993
|
+
"session-end": "session-end.js",
|
|
14994
|
+
"security-gate": "security-gate.js",
|
|
14995
|
+
"pre-delete-check": "pre-delete-check.js",
|
|
14996
|
+
"post-tool-use": "post-tool-use.js",
|
|
14997
|
+
"post-edit-context": "post-edit-context.js",
|
|
14998
|
+
"quality-event": "quality-event.js",
|
|
14999
|
+
"cost-tracker": "cost-tracker.js",
|
|
15000
|
+
"fix-detector": "fix-detector.js",
|
|
15001
|
+
"classify-failure": "classify-failure.js",
|
|
15002
|
+
"incident-pipeline": "incident-pipeline.js",
|
|
15003
|
+
"rule-enforcement-pipeline": "rule-enforcement-pipeline.js",
|
|
15004
|
+
"auto-learning-pipeline": "auto-learning-pipeline.js",
|
|
15005
|
+
"pre-compact": "pre-compact.js",
|
|
15006
|
+
"user-prompt": "user-prompt.js",
|
|
15007
|
+
"intent-suggester": "intent-suggester.js"
|
|
15008
|
+
};
|
|
15009
|
+
}
|
|
15010
|
+
});
|
|
15011
|
+
|
|
14759
15012
|
// src/commands/permissions.ts
|
|
14760
15013
|
var permissions_exports = {};
|
|
14761
15014
|
__export(permissions_exports, {
|
|
14762
15015
|
handlePermissionsSubcommand: () => handlePermissionsSubcommand,
|
|
14763
15016
|
printPermissionsHelp: () => printPermissionsHelp
|
|
14764
15017
|
});
|
|
14765
|
-
import { resolve as
|
|
15018
|
+
import { resolve as resolve10 } from "path";
|
|
14766
15019
|
function resolveClaudeDir2() {
|
|
14767
15020
|
let claudeDirName = ".claude";
|
|
14768
15021
|
try {
|
|
@@ -14770,7 +15023,7 @@ function resolveClaudeDir2() {
|
|
|
14770
15023
|
} catch {
|
|
14771
15024
|
claudeDirName = ".claude";
|
|
14772
15025
|
}
|
|
14773
|
-
return
|
|
15026
|
+
return resolve10(process.cwd(), claudeDirName);
|
|
14774
15027
|
}
|
|
14775
15028
|
async function handlePermissionsSubcommand(args2) {
|
|
14776
15029
|
const sub = args2[0];
|
|
@@ -14884,8 +15137,8 @@ var init_permissions2 = __esm({
|
|
|
14884
15137
|
});
|
|
14885
15138
|
|
|
14886
15139
|
// src/changelog-generator.ts
|
|
14887
|
-
import { existsSync as
|
|
14888
|
-
import { resolve as
|
|
15140
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, readdirSync as readdirSync12 } from "fs";
|
|
15141
|
+
import { resolve as resolve11 } from "path";
|
|
14889
15142
|
function parseCommitsForPlanTokens(subjects) {
|
|
14890
15143
|
const tokens = /* @__PURE__ */ new Set();
|
|
14891
15144
|
const maintenance = [];
|
|
@@ -14902,7 +15155,7 @@ function parseCommitsForPlanTokens(subjects) {
|
|
|
14902
15155
|
function loadPlanSummaries(tokens, planDir) {
|
|
14903
15156
|
const result = /* @__PURE__ */ new Map();
|
|
14904
15157
|
if (tokens.size === 0) return result;
|
|
14905
|
-
if (!
|
|
15158
|
+
if (!existsSync14(planDir)) {
|
|
14906
15159
|
throw new Error(`Plan directory does not exist: ${planDir}`);
|
|
14907
15160
|
}
|
|
14908
15161
|
const files = readdirSync12(planDir).filter((f2) => f2.endsWith(".md"));
|
|
@@ -14910,7 +15163,7 @@ function loadPlanSummaries(tokens, planDir) {
|
|
|
14910
15163
|
let matchedFile = null;
|
|
14911
15164
|
let content = "";
|
|
14912
15165
|
for (const file of files) {
|
|
14913
|
-
const path =
|
|
15166
|
+
const path = resolve11(planDir, file);
|
|
14914
15167
|
const text18 = readFileSync13(path, "utf-8");
|
|
14915
15168
|
const tokenRe = new RegExp(
|
|
14916
15169
|
`^\\*\\*Plan Token\\*\\*:\\s*\`?${token.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")}\`?(\\s|$)`,
|
|
@@ -14992,8 +15245,8 @@ __export(changelog_exports, {
|
|
|
14992
15245
|
printChangelogHelp: () => printChangelogHelp
|
|
14993
15246
|
});
|
|
14994
15247
|
import { execSync } from "child_process";
|
|
14995
|
-
import { existsSync as
|
|
14996
|
-
import { resolve as
|
|
15248
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14 } from "fs";
|
|
15249
|
+
import { resolve as resolve12 } from "path";
|
|
14997
15250
|
function resolveRepoRoot() {
|
|
14998
15251
|
try {
|
|
14999
15252
|
return execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
|
|
@@ -15017,8 +15270,8 @@ function getCommitSubjects(range) {
|
|
|
15017
15270
|
}
|
|
15018
15271
|
}
|
|
15019
15272
|
function getCurrentVersion(repoRoot) {
|
|
15020
|
-
const pkgPath =
|
|
15021
|
-
if (!
|
|
15273
|
+
const pkgPath = resolve12(repoRoot, "packages/core/package.json");
|
|
15274
|
+
if (!existsSync15(pkgPath)) return "0.0.0";
|
|
15022
15275
|
const pkg = JSON.parse(readFileSync14(pkgPath, "utf-8"));
|
|
15023
15276
|
return pkg.version || "0.0.0";
|
|
15024
15277
|
}
|
|
@@ -15026,8 +15279,8 @@ function todayDate() {
|
|
|
15026
15279
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
15027
15280
|
}
|
|
15028
15281
|
function getLatestChangelogEntryBody(repoRoot) {
|
|
15029
|
-
const path =
|
|
15030
|
-
if (!
|
|
15282
|
+
const path = resolve12(repoRoot, "CHANGELOG.md");
|
|
15283
|
+
if (!existsSync15(path)) return "";
|
|
15031
15284
|
const content = readFileSync14(path, "utf-8");
|
|
15032
15285
|
const m3 = content.match(/^## \[[\d.]+\][^\n]*\n([\s\S]*?)(?=\n## \[|$)/m);
|
|
15033
15286
|
return m3 ? m3[1] : "";
|
|
@@ -15035,7 +15288,7 @@ function getLatestChangelogEntryBody(repoRoot) {
|
|
|
15035
15288
|
async function handleChangelogSubcommand(args2) {
|
|
15036
15289
|
const sub = args2[0];
|
|
15037
15290
|
const repoRoot = resolveRepoRoot();
|
|
15038
|
-
const planDir =
|
|
15291
|
+
const planDir = resolve12(repoRoot, "docs/plans");
|
|
15039
15292
|
switch (sub) {
|
|
15040
15293
|
case "generate": {
|
|
15041
15294
|
const lastTag = getLastTag();
|
|
@@ -15127,8 +15380,8 @@ var show_template_exports = {};
|
|
|
15127
15380
|
__export(show_template_exports, {
|
|
15128
15381
|
runShowTemplate: () => runShowTemplate
|
|
15129
15382
|
});
|
|
15130
|
-
import { existsSync as
|
|
15131
|
-
import { resolve as
|
|
15383
|
+
import { existsSync as existsSync16, readFileSync as readFileSync15 } from "fs";
|
|
15384
|
+
import { resolve as resolve13 } from "path";
|
|
15132
15385
|
function normalizeBaseName(input) {
|
|
15133
15386
|
return input.endsWith(".md") ? input.slice(0, -".md".length) : input;
|
|
15134
15387
|
}
|
|
@@ -15156,8 +15409,8 @@ async function runShowTemplate(args2) {
|
|
|
15156
15409
|
return;
|
|
15157
15410
|
}
|
|
15158
15411
|
const suffix = choice.kind === "hit" ? choice.suffix : "";
|
|
15159
|
-
const file = suffix === "" ?
|
|
15160
|
-
if (!
|
|
15412
|
+
const file = suffix === "" ? resolve13(sourceDir, `${baseName}.md`) : resolve13(sourceDir, `${baseName}${suffix}.md`);
|
|
15413
|
+
if (!existsSync16(file)) {
|
|
15161
15414
|
process.stderr.write(`massu: resolved template "${file}" no longer exists
|
|
15162
15415
|
`);
|
|
15163
15416
|
process.exit(1);
|
|
@@ -15217,7 +15470,7 @@ var init_passthrough = __esm({
|
|
|
15217
15470
|
|
|
15218
15471
|
// src/lib/fileLock.ts
|
|
15219
15472
|
import { mkdirSync as mkdirSync6, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
15220
|
-
import { dirname as
|
|
15473
|
+
import { dirname as dirname9 } from "path";
|
|
15221
15474
|
import * as lockfile from "proper-lockfile";
|
|
15222
15475
|
function readLockHolderPid(lockPath) {
|
|
15223
15476
|
try {
|
|
@@ -15240,7 +15493,7 @@ function busyWaitSync(ms) {
|
|
|
15240
15493
|
Atomics.wait(view, 0, 0, ms);
|
|
15241
15494
|
}
|
|
15242
15495
|
function withFileLockSync(lockPath, fn, opts = {}) {
|
|
15243
|
-
mkdirSync6(
|
|
15496
|
+
mkdirSync6(dirname9(lockPath), { recursive: true });
|
|
15244
15497
|
const staleMs = opts.staleMs ?? 3e4;
|
|
15245
15498
|
const blockMs = opts.retries === 0 ? 0 : opts.blockMs ?? 3e4;
|
|
15246
15499
|
const pollIntervalMs = opts.pollIntervalMs ?? 100;
|
|
@@ -15308,9 +15561,9 @@ var init_fileLock = __esm({
|
|
|
15308
15561
|
});
|
|
15309
15562
|
|
|
15310
15563
|
// src/lib/installLock.ts
|
|
15311
|
-
import { resolve as
|
|
15564
|
+
import { resolve as resolve14 } from "path";
|
|
15312
15565
|
function withInstallLock(projectRoot, fn, opts = {}) {
|
|
15313
|
-
const lockPath =
|
|
15566
|
+
const lockPath = resolve14(projectRoot, ".massu", "installAll.lock");
|
|
15314
15567
|
return withFileLockSync(
|
|
15315
15568
|
lockPath,
|
|
15316
15569
|
fn,
|
|
@@ -15346,8 +15599,8 @@ __export(config_refresh_exports, {
|
|
|
15346
15599
|
mergeRefresh: () => mergeRefresh,
|
|
15347
15600
|
runConfigRefresh: () => runConfigRefresh
|
|
15348
15601
|
});
|
|
15349
|
-
import { existsSync as
|
|
15350
|
-
import { resolve as
|
|
15602
|
+
import { existsSync as existsSync17, readFileSync as readFileSync17, rmSync as rmSync4 } from "fs";
|
|
15603
|
+
import { resolve as resolve15 } from "path";
|
|
15351
15604
|
import { parse as parseYaml5 } from "yaml";
|
|
15352
15605
|
function flatten(obj, prefix3 = "") {
|
|
15353
15606
|
const out = {};
|
|
@@ -15475,10 +15728,10 @@ function renderDiff(diff) {
|
|
|
15475
15728
|
}
|
|
15476
15729
|
async function runConfigRefresh(opts = {}) {
|
|
15477
15730
|
const cwd = opts.cwd ?? process.cwd();
|
|
15478
|
-
const configPath =
|
|
15731
|
+
const configPath = resolve15(cwd, "massu.config.yaml");
|
|
15479
15732
|
const log = opts.silent ? () => {
|
|
15480
15733
|
} : (s) => process.stdout.write(s);
|
|
15481
|
-
if (!
|
|
15734
|
+
if (!existsSync17(configPath)) {
|
|
15482
15735
|
const message = "massu.config.yaml not found. Run: npx massu init";
|
|
15483
15736
|
if (!opts.silent) process.stderr.write(message + "\n");
|
|
15484
15737
|
return { exitCode: 1, applied: false, dryRun: !!opts.dryRun, diff: [], message };
|
|
@@ -15558,8 +15811,8 @@ async function runConfigRefresh(opts = {}) {
|
|
|
15558
15811
|
`);
|
|
15559
15812
|
const stackResolved = installResult.totalInstalled > 0 || installResult.totalUpdated > 0;
|
|
15560
15813
|
if (stackResolved) {
|
|
15561
|
-
const placeholderPath =
|
|
15562
|
-
if (
|
|
15814
|
+
const placeholderPath = resolve15(installResult.claudeDir, "commands", "_massu-needs-stack.md");
|
|
15815
|
+
if (existsSync17(placeholderPath)) {
|
|
15563
15816
|
try {
|
|
15564
15817
|
rmSync4(placeholderPath, { force: true });
|
|
15565
15818
|
log("Removed _massu-needs-stack.md (stack now declared).\n");
|
|
@@ -15668,12 +15921,12 @@ var init_gitToplevel = __esm({
|
|
|
15668
15921
|
});
|
|
15669
15922
|
|
|
15670
15923
|
// src/watch/lockfile-detector.ts
|
|
15671
|
-
import { existsSync as
|
|
15672
|
-
import { resolve as
|
|
15924
|
+
import { existsSync as existsSync18, statSync as statSync8 } from "fs";
|
|
15925
|
+
import { resolve as resolve16 } from "path";
|
|
15673
15926
|
function lockfileMidWrite(projectRoot, now = Date.now(), windowMs = LOCKFILE_WINDOW_MS) {
|
|
15674
15927
|
for (const lf of KNOWN_LOCKFILES) {
|
|
15675
|
-
const p19 =
|
|
15676
|
-
if (!
|
|
15928
|
+
const p19 = resolve16(projectRoot, lf);
|
|
15929
|
+
if (!existsSync18(p19)) continue;
|
|
15677
15930
|
try {
|
|
15678
15931
|
const stat = statSync8(p19);
|
|
15679
15932
|
const delta = now - stat.mtimeMs;
|
|
@@ -15686,7 +15939,7 @@ function lockfileMidWrite(projectRoot, now = Date.now(), windowMs = LOCKFILE_WIN
|
|
|
15686
15939
|
function gitMidOperation(projectRoot) {
|
|
15687
15940
|
const sentinels = ["MERGE_HEAD", "REBASE_HEAD", "CHERRY_PICK_HEAD", "rebase-apply", "rebase-merge"];
|
|
15688
15941
|
for (const s of sentinels) {
|
|
15689
|
-
if (
|
|
15942
|
+
if (existsSync18(resolve16(projectRoot, ".git", s))) return true;
|
|
15690
15943
|
}
|
|
15691
15944
|
return false;
|
|
15692
15945
|
}
|
|
@@ -15883,17 +16136,17 @@ var init_paths = __esm({
|
|
|
15883
16136
|
});
|
|
15884
16137
|
|
|
15885
16138
|
// src/watch/state.ts
|
|
15886
|
-
import { closeSync as closeSync3, existsSync as
|
|
15887
|
-
import { dirname as
|
|
16139
|
+
import { closeSync as closeSync3, existsSync as existsSync19, fsyncSync as fsyncSync3, mkdirSync as mkdirSync7, openSync as openSync3, readFileSync as readFileSync18, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync4, writeSync as writeSync3 } from "fs";
|
|
16140
|
+
import { dirname as dirname10, resolve as resolve17 } from "path";
|
|
15888
16141
|
function watchStatePath(projectRoot) {
|
|
15889
|
-
return
|
|
16142
|
+
return resolve17(projectRoot, ".massu", "watch-state.json");
|
|
15890
16143
|
}
|
|
15891
16144
|
function backupStatePath(projectRoot) {
|
|
15892
|
-
return
|
|
16145
|
+
return resolve17(projectRoot, ".massu", "watch-state.v0.bak.json");
|
|
15893
16146
|
}
|
|
15894
16147
|
function readState(projectRoot) {
|
|
15895
16148
|
const path = watchStatePath(projectRoot);
|
|
15896
|
-
if (!
|
|
16149
|
+
if (!existsSync19(path)) return { ...DEFAULT_STATE };
|
|
15897
16150
|
const content = readFileSync18(path, "utf-8");
|
|
15898
16151
|
let raw;
|
|
15899
16152
|
try {
|
|
@@ -15936,14 +16189,14 @@ function readState(projectRoot) {
|
|
|
15936
16189
|
}
|
|
15937
16190
|
function archiveCorrupt(projectRoot, content) {
|
|
15938
16191
|
const bak = backupStatePath(projectRoot);
|
|
15939
|
-
mkdirSync7(
|
|
16192
|
+
mkdirSync7(dirname10(bak), { recursive: true });
|
|
15940
16193
|
writeFileSync4(bak, content, "utf-8");
|
|
15941
16194
|
}
|
|
15942
16195
|
function writeStateAtomic(projectRoot, state) {
|
|
15943
16196
|
const path = watchStatePath(projectRoot);
|
|
15944
16197
|
writeStateAtomicCounter = writeStateAtomicCounter + 1 >>> 0;
|
|
15945
16198
|
const tmp = `${path}.${process.pid}.${writeStateAtomicCounter}.tmp`;
|
|
15946
|
-
mkdirSync7(
|
|
16199
|
+
mkdirSync7(dirname10(path), { recursive: true });
|
|
15947
16200
|
let renamed = false;
|
|
15948
16201
|
try {
|
|
15949
16202
|
const fd = openSync3(tmp, "w");
|
|
@@ -15957,7 +16210,7 @@ function writeStateAtomic(projectRoot, state) {
|
|
|
15957
16210
|
renameSync4(tmp, path);
|
|
15958
16211
|
renamed = true;
|
|
15959
16212
|
} finally {
|
|
15960
|
-
if (!renamed &&
|
|
16213
|
+
if (!renamed && existsSync19(tmp)) {
|
|
15961
16214
|
try {
|
|
15962
16215
|
rmSync5(tmp, { force: true });
|
|
15963
16216
|
} catch {
|
|
@@ -16237,8 +16490,8 @@ __export(watch_exports, {
|
|
|
16237
16490
|
runWatch: () => runWatch
|
|
16238
16491
|
});
|
|
16239
16492
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
16240
|
-
import { basename as basename5, dirname as
|
|
16241
|
-
import { appendFileSync, existsSync as
|
|
16493
|
+
import { basename as basename5, dirname as dirname11, resolve as resolve18 } from "path";
|
|
16494
|
+
import { appendFileSync, existsSync as existsSync20, mkdirSync as mkdirSync8, readFileSync as readFileSync19 } from "fs";
|
|
16242
16495
|
function parseFlags(args2) {
|
|
16243
16496
|
const out = {
|
|
16244
16497
|
foreground: false,
|
|
@@ -16263,8 +16516,8 @@ function parseFlags(args2) {
|
|
|
16263
16516
|
}
|
|
16264
16517
|
function findClaudeBg() {
|
|
16265
16518
|
const home = process.env.HOME ?? "";
|
|
16266
|
-
const fixed = home ?
|
|
16267
|
-
if (fixed &&
|
|
16519
|
+
const fixed = home ? resolve18(home, ".claude", "bin", "claude-bg") : null;
|
|
16520
|
+
if (fixed && existsSync20(fixed)) return fixed;
|
|
16268
16521
|
const which = spawnSync3("which", ["claude-bg"], { encoding: "utf-8" });
|
|
16269
16522
|
if (which.status === 0 && which.stdout) {
|
|
16270
16523
|
const p19 = which.stdout.trim();
|
|
@@ -16325,7 +16578,7 @@ async function runWatch(args2) {
|
|
|
16325
16578
|
}
|
|
16326
16579
|
function runStatus(root) {
|
|
16327
16580
|
const path = watchStatePath(root);
|
|
16328
|
-
if (!
|
|
16581
|
+
if (!existsSync20(path)) {
|
|
16329
16582
|
process.stdout.write("massu watch: not running (no state file)\n");
|
|
16330
16583
|
return { exitCode: 0 };
|
|
16331
16584
|
}
|
|
@@ -16407,7 +16660,7 @@ async function runForeground(root) {
|
|
|
16407
16660
|
}
|
|
16408
16661
|
throw err;
|
|
16409
16662
|
}
|
|
16410
|
-
return new Promise((
|
|
16663
|
+
return new Promise((resolve41) => {
|
|
16411
16664
|
const shutdown = async () => {
|
|
16412
16665
|
if (stopped) return;
|
|
16413
16666
|
stopped = true;
|
|
@@ -16417,7 +16670,7 @@ async function runForeground(root) {
|
|
|
16417
16670
|
process.chdir(priorCwd);
|
|
16418
16671
|
} catch {
|
|
16419
16672
|
}
|
|
16420
|
-
|
|
16673
|
+
resolve41({ exitCode: 0 });
|
|
16421
16674
|
};
|
|
16422
16675
|
process.on("SIGINT", () => {
|
|
16423
16676
|
void shutdown();
|
|
@@ -16478,19 +16731,19 @@ async function runOnQuiescent(projectRoot) {
|
|
|
16478
16731
|
);
|
|
16479
16732
|
}
|
|
16480
16733
|
function refreshLogPath(projectRoot) {
|
|
16481
|
-
return
|
|
16734
|
+
return resolve18(projectRoot, ".massu", "refresh-log.jsonl");
|
|
16482
16735
|
}
|
|
16483
16736
|
function appendRefreshLog(projectRoot, event) {
|
|
16484
16737
|
const path = refreshLogPath(projectRoot);
|
|
16485
16738
|
try {
|
|
16486
|
-
mkdirSync8(
|
|
16739
|
+
mkdirSync8(dirname11(path), { recursive: true });
|
|
16487
16740
|
appendFileSync(path, JSON.stringify(event) + "\n", "utf-8");
|
|
16488
16741
|
} catch {
|
|
16489
16742
|
}
|
|
16490
16743
|
}
|
|
16491
16744
|
function readRefreshLog(projectRoot, limit = 10, opts = {}) {
|
|
16492
16745
|
const path = refreshLogPath(projectRoot);
|
|
16493
|
-
if (!
|
|
16746
|
+
if (!existsSync20(path)) return [];
|
|
16494
16747
|
const warn = opts.warn ?? ((s) => {
|
|
16495
16748
|
process.stderr.write(s);
|
|
16496
16749
|
});
|
|
@@ -16567,7 +16820,7 @@ var init_refresh_log = __esm({
|
|
|
16567
16820
|
import {
|
|
16568
16821
|
chmodSync as chmodSync3,
|
|
16569
16822
|
closeSync as closeSync4,
|
|
16570
|
-
existsSync as
|
|
16823
|
+
existsSync as existsSync21,
|
|
16571
16824
|
fsyncSync as fsyncSync4,
|
|
16572
16825
|
mkdirSync as mkdirSync9,
|
|
16573
16826
|
openSync as openSync4,
|
|
@@ -16576,12 +16829,12 @@ import {
|
|
|
16576
16829
|
statSync as statSync9,
|
|
16577
16830
|
writeSync as writeSync4
|
|
16578
16831
|
} from "node:fs";
|
|
16579
|
-
import { dirname as
|
|
16832
|
+
import { dirname as dirname12 } from "node:path";
|
|
16580
16833
|
function atomicWrite(path, content, opts = {}) {
|
|
16581
16834
|
const tmpPath = `${path}.tmp`;
|
|
16582
|
-
const parentDir =
|
|
16835
|
+
const parentDir = dirname12(path);
|
|
16583
16836
|
try {
|
|
16584
|
-
if (!
|
|
16837
|
+
if (!existsSync21(parentDir)) {
|
|
16585
16838
|
const mkdirOpts = { recursive: true };
|
|
16586
16839
|
if (opts.ensureParentDirMode !== void 0) {
|
|
16587
16840
|
mkdirOpts.mode = opts.ensureParentDirMode;
|
|
@@ -16603,7 +16856,7 @@ function atomicWrite(path, content, opts = {}) {
|
|
|
16603
16856
|
renameSync5(tmpPath, path);
|
|
16604
16857
|
return { written: true };
|
|
16605
16858
|
} catch (err) {
|
|
16606
|
-
if (
|
|
16859
|
+
if (existsSync21(tmpPath)) {
|
|
16607
16860
|
try {
|
|
16608
16861
|
rmSync6(tmpPath, { force: true });
|
|
16609
16862
|
} catch {
|
|
@@ -16946,19 +17199,19 @@ var init_fetcher = __esm({
|
|
|
16946
17199
|
});
|
|
16947
17200
|
|
|
16948
17201
|
// src/security/manifest-cache.ts
|
|
16949
|
-
import { existsSync as
|
|
17202
|
+
import { existsSync as existsSync22, readFileSync as readFileSync20, statSync as statSync10 } from "node:fs";
|
|
16950
17203
|
import { homedir as homedir5 } from "node:os";
|
|
16951
|
-
import { resolve as
|
|
17204
|
+
import { resolve as resolve19 } from "node:path";
|
|
16952
17205
|
import { z as z4 } from "zod";
|
|
16953
17206
|
function defaultCachePaths() {
|
|
16954
|
-
const dir =
|
|
17207
|
+
const dir = resolve19(homedir5(), ".massu");
|
|
16955
17208
|
return {
|
|
16956
|
-
cachePath:
|
|
16957
|
-
lockPath:
|
|
17209
|
+
cachePath: resolve19(dir, "adapter-manifest.json"),
|
|
17210
|
+
lockPath: resolve19(dir, ".adapter-manifest.lock")
|
|
16958
17211
|
};
|
|
16959
17212
|
}
|
|
16960
17213
|
function loadCachedManifest(paths = defaultCachePaths()) {
|
|
16961
|
-
if (!
|
|
17214
|
+
if (!existsSync22(paths.cachePath)) {
|
|
16962
17215
|
return { kind: "absent" };
|
|
16963
17216
|
}
|
|
16964
17217
|
let raw;
|
|
@@ -17152,15 +17405,15 @@ var init_adapter_origin = __esm({
|
|
|
17152
17405
|
});
|
|
17153
17406
|
|
|
17154
17407
|
// src/security/local-fingerprint.ts
|
|
17155
|
-
import { existsSync as
|
|
17408
|
+
import { existsSync as existsSync23, readFileSync as readFileSync21, lstatSync as lstatSync5 } from "node:fs";
|
|
17156
17409
|
import { homedir as homedir6 } from "node:os";
|
|
17157
|
-
import { resolve as
|
|
17410
|
+
import { resolve as resolve20, isAbsolute } from "node:path";
|
|
17158
17411
|
import { createHash as createHash7 } from "node:crypto";
|
|
17159
17412
|
import { z as z5 } from "zod";
|
|
17160
17413
|
function computeLocalFingerprint(localPaths, projectRoot) {
|
|
17161
17414
|
const tuples = [];
|
|
17162
17415
|
for (const p19 of localPaths) {
|
|
17163
|
-
const abs = isAbsolute(p19) ? p19 :
|
|
17416
|
+
const abs = isAbsolute(p19) ? p19 : resolve20(projectRoot, p19);
|
|
17164
17417
|
let contentTag;
|
|
17165
17418
|
try {
|
|
17166
17419
|
const lst = lstatSync5(abs);
|
|
@@ -17181,7 +17434,7 @@ function computeLocalFingerprint(localPaths, projectRoot) {
|
|
|
17181
17434
|
return createHash7("sha256").update(canonical).digest("hex");
|
|
17182
17435
|
}
|
|
17183
17436
|
function readFingerprintSentinel(path = FINGERPRINT_PATH) {
|
|
17184
|
-
if (!
|
|
17437
|
+
if (!existsSync23(path)) return null;
|
|
17185
17438
|
let raw;
|
|
17186
17439
|
try {
|
|
17187
17440
|
raw = JSON.parse(readFileSync21(path, "utf-8"));
|
|
@@ -17232,7 +17485,7 @@ var init_local_fingerprint = __esm({
|
|
|
17232
17485
|
"use strict";
|
|
17233
17486
|
init_atomic_write();
|
|
17234
17487
|
init_manifest_schema();
|
|
17235
|
-
FINGERPRINT_PATH =
|
|
17488
|
+
FINGERPRINT_PATH = resolve20(homedir6(), ".massu", "adapters-local-fingerprint.json");
|
|
17236
17489
|
FingerprintSentinelSchema = z5.object({
|
|
17237
17490
|
fingerprint: z5.string().regex(/^[0-9a-f]{64}$/),
|
|
17238
17491
|
source: z5.enum(["cli", "cli-resync"]),
|
|
@@ -17248,15 +17501,15 @@ var init_local_fingerprint = __esm({
|
|
|
17248
17501
|
});
|
|
17249
17502
|
|
|
17250
17503
|
// src/security/install-tracking.ts
|
|
17251
|
-
import { readFileSync as readFileSync22, readdirSync as readdirSync13, lstatSync as lstatSync6, existsSync as
|
|
17504
|
+
import { readFileSync as readFileSync22, readdirSync as readdirSync13, lstatSync as lstatSync6, existsSync as existsSync24 } from "node:fs";
|
|
17252
17505
|
import { join as join11, relative as relative5, sep } from "node:path";
|
|
17253
17506
|
import { homedir as homedir7 } from "node:os";
|
|
17254
|
-
import { resolve as
|
|
17507
|
+
import { resolve as resolve21 } from "node:path";
|
|
17255
17508
|
import { createHash as createHash8 } from "node:crypto";
|
|
17256
17509
|
import { z as z6 } from "zod";
|
|
17257
17510
|
function containsHiddenDirs(packageDir) {
|
|
17258
17511
|
for (const hidden of EXCLUDED_DIR_NAMES) {
|
|
17259
|
-
if (
|
|
17512
|
+
if (existsSync24(`${packageDir}/${hidden}`)) {
|
|
17260
17513
|
return hidden;
|
|
17261
17514
|
}
|
|
17262
17515
|
}
|
|
@@ -17311,7 +17564,7 @@ function sha256OfDir(dir, opts = {}) {
|
|
|
17311
17564
|
return top.digest("hex");
|
|
17312
17565
|
}
|
|
17313
17566
|
function readInstalledManifest(path = INSTALLED_MANIFEST_PATH) {
|
|
17314
|
-
if (!
|
|
17567
|
+
if (!existsSync24(path)) return {};
|
|
17315
17568
|
let raw;
|
|
17316
17569
|
try {
|
|
17317
17570
|
raw = JSON.parse(readFileSync22(path, "utf-8"));
|
|
@@ -17378,7 +17631,7 @@ var init_install_tracking = __esm({
|
|
|
17378
17631
|
"src/security/install-tracking.ts"() {
|
|
17379
17632
|
"use strict";
|
|
17380
17633
|
init_atomic_write();
|
|
17381
|
-
INSTALLED_MANIFEST_PATH =
|
|
17634
|
+
INSTALLED_MANIFEST_PATH = resolve21(homedir7(), ".massu", "adapter-manifest-installed.json");
|
|
17382
17635
|
DEFAULT_MAX_FILE_BYTES = 64 * 1024 * 1024;
|
|
17383
17636
|
EXCLUDED_DIR_NAMES = /* @__PURE__ */ new Set([".git", "node_modules", ".cache", ".tmp"]);
|
|
17384
17637
|
InstallEntrySchema = z6.object({
|
|
@@ -17401,12 +17654,12 @@ var init_install_tracking = __esm({
|
|
|
17401
17654
|
});
|
|
17402
17655
|
|
|
17403
17656
|
// src/detect/adapters/discover.ts
|
|
17404
|
-
import { existsSync as
|
|
17405
|
-
import { resolve as
|
|
17657
|
+
import { existsSync as existsSync25, readdirSync as readdirSync14, readFileSync as readFileSync23, lstatSync as lstatSync7 } from "node:fs";
|
|
17658
|
+
import { resolve as resolve22, isAbsolute as isAbsolute2 } from "node:path";
|
|
17406
17659
|
import { z as z7 } from "zod";
|
|
17407
17660
|
function walkNodeModules(projectRoot, warnings) {
|
|
17408
|
-
const nodeModulesDir =
|
|
17409
|
-
if (!
|
|
17661
|
+
const nodeModulesDir = resolve22(projectRoot, "node_modules");
|
|
17662
|
+
if (!existsSync25(nodeModulesDir)) {
|
|
17410
17663
|
return [];
|
|
17411
17664
|
}
|
|
17412
17665
|
const candidates = [];
|
|
@@ -17419,7 +17672,7 @@ function walkNodeModules(projectRoot, warnings) {
|
|
|
17419
17672
|
}
|
|
17420
17673
|
for (const entry of topLevelEntries) {
|
|
17421
17674
|
if (entry.startsWith(".")) continue;
|
|
17422
|
-
const entryPath =
|
|
17675
|
+
const entryPath = resolve22(nodeModulesDir, entry);
|
|
17423
17676
|
let entryStat;
|
|
17424
17677
|
try {
|
|
17425
17678
|
entryStat = lstatSync7(entryPath);
|
|
@@ -17441,7 +17694,7 @@ function walkNodeModules(projectRoot, warnings) {
|
|
|
17441
17694
|
continue;
|
|
17442
17695
|
}
|
|
17443
17696
|
for (const sub of scopedEntries) {
|
|
17444
|
-
const subPath =
|
|
17697
|
+
const subPath = resolve22(entryPath, sub);
|
|
17445
17698
|
let subStat;
|
|
17446
17699
|
try {
|
|
17447
17700
|
subStat = lstatSync7(subPath);
|
|
@@ -17460,8 +17713,8 @@ function walkNodeModules(projectRoot, warnings) {
|
|
|
17460
17713
|
return candidates;
|
|
17461
17714
|
}
|
|
17462
17715
|
function tryReadAdapterPackage(packageDir, warnings) {
|
|
17463
|
-
const pkgJsonPath =
|
|
17464
|
-
if (!
|
|
17716
|
+
const pkgJsonPath = resolve22(packageDir, "package.json");
|
|
17717
|
+
if (!existsSync25(pkgJsonPath)) return null;
|
|
17465
17718
|
let raw;
|
|
17466
17719
|
try {
|
|
17467
17720
|
raw = JSON.parse(readFileSync23(pkgJsonPath, "utf-8"));
|
|
@@ -17598,8 +17851,8 @@ function discoverAdapters(opts) {
|
|
|
17598
17851
|
const localSet = new Set(opts.configLocalPaths);
|
|
17599
17852
|
for (const localPath of opts.configLocalPaths) {
|
|
17600
17853
|
if (seenIds.has(localPath)) continue;
|
|
17601
|
-
const absPath = isAbsolute2(localPath) ? localPath :
|
|
17602
|
-
if (!
|
|
17854
|
+
const absPath = isAbsolute2(localPath) ? localPath : resolve22(opts.projectRoot, localPath);
|
|
17855
|
+
if (!existsSync25(absPath)) {
|
|
17603
17856
|
warnings.push(
|
|
17604
17857
|
`local adapter file not found: ${localPath} (resolved to ${absPath}). Remove via: massu adapters remove-local ${localPath}`
|
|
17605
17858
|
);
|
|
@@ -17680,8 +17933,8 @@ __export(adapters_exports, {
|
|
|
17680
17933
|
runAdaptersResyncLocalFingerprint: () => runAdaptersResyncLocalFingerprint,
|
|
17681
17934
|
runAdaptersSearch: () => runAdaptersSearch
|
|
17682
17935
|
});
|
|
17683
|
-
import { existsSync as
|
|
17684
|
-
import { resolve as
|
|
17936
|
+
import { existsSync as existsSync26, readFileSync as readFileSync24 } from "node:fs";
|
|
17937
|
+
import { resolve as resolve23 } from "node:path";
|
|
17685
17938
|
import { parseDocument } from "yaml";
|
|
17686
17939
|
async function handleAdaptersSubcommand(args2) {
|
|
17687
17940
|
const sub = args2[0];
|
|
@@ -17948,8 +18201,8 @@ function mutateLocalArray(mutator, command) {
|
|
|
17948
18201
|
);
|
|
17949
18202
|
return { exitCode: 2 };
|
|
17950
18203
|
}
|
|
17951
|
-
const yamlPath =
|
|
17952
|
-
if (!
|
|
18204
|
+
const yamlPath = resolve23(projectRoot, "massu.config.yaml");
|
|
18205
|
+
if (!existsSync26(yamlPath)) {
|
|
17953
18206
|
process.stderr.write(
|
|
17954
18207
|
`${command}: massu.config.yaml not found at ${yamlPath}. Run \`massu init\` first.
|
|
17955
18208
|
`
|
|
@@ -17979,7 +18232,7 @@ function mutateLocalArray(mutator, command) {
|
|
|
17979
18232
|
if (next === null) {
|
|
17980
18233
|
return { exitCode: 0 };
|
|
17981
18234
|
}
|
|
17982
|
-
const lockPath =
|
|
18235
|
+
const lockPath = resolve23(projectRoot, ".massu", "adapters-local-mutate.lock");
|
|
17983
18236
|
return withFileLockSync(lockPath, () => {
|
|
17984
18237
|
doc.setIn(["adapters", "local"], next);
|
|
17985
18238
|
const newYaml = doc.toString();
|
|
@@ -18048,16 +18301,16 @@ async function runAdaptersInstall(args2) {
|
|
|
18048
18301
|
`);
|
|
18049
18302
|
return { exitCode: 1 };
|
|
18050
18303
|
}
|
|
18051
|
-
const packageDir =
|
|
18052
|
-
if (!
|
|
18304
|
+
const packageDir = resolve23(projectRoot, "node_modules", ...packageName.split("/"));
|
|
18305
|
+
if (!existsSync26(packageDir)) {
|
|
18053
18306
|
process.stderr.write(
|
|
18054
18307
|
`install: ${packageName} is not installed in node_modules. Run \`npm install ${packageName}\` first.
|
|
18055
18308
|
`
|
|
18056
18309
|
);
|
|
18057
18310
|
return { exitCode: 1 };
|
|
18058
18311
|
}
|
|
18059
|
-
const pkgJsonPath =
|
|
18060
|
-
if (!
|
|
18312
|
+
const pkgJsonPath = resolve23(packageDir, "package.json");
|
|
18313
|
+
if (!existsSync26(pkgJsonPath)) {
|
|
18061
18314
|
process.stderr.write(`install: ${packageName} has no package.json at ${pkgJsonPath}
|
|
18062
18315
|
`);
|
|
18063
18316
|
return { exitCode: 1 };
|
|
@@ -18183,8 +18436,8 @@ async function runAdaptersResign(_args) {
|
|
|
18183
18436
|
removeInstalledManifestEntry(name);
|
|
18184
18437
|
continue;
|
|
18185
18438
|
}
|
|
18186
|
-
const packageDir =
|
|
18187
|
-
if (!
|
|
18439
|
+
const packageDir = resolve23(projectRoot, "node_modules", ...name.split("/"));
|
|
18440
|
+
if (!existsSync26(packageDir)) {
|
|
18188
18441
|
removed++;
|
|
18189
18442
|
warnings.push(`${name}@${entry.version}: not present in node_modules \u2014 REMOVED from sidecar`);
|
|
18190
18443
|
removeInstalledManifestEntry(name);
|
|
@@ -18271,11 +18524,11 @@ var init_adapters2 = __esm({
|
|
|
18271
18524
|
|
|
18272
18525
|
// src/db.ts
|
|
18273
18526
|
import Database2 from "better-sqlite3";
|
|
18274
|
-
import { dirname as
|
|
18275
|
-
import { existsSync as
|
|
18527
|
+
import { dirname as dirname13, join as join12 } from "path";
|
|
18528
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync10, readdirSync as readdirSync15, statSync as statSync11 } from "fs";
|
|
18276
18529
|
function getCodeGraphDb() {
|
|
18277
18530
|
const dbPath = getResolvedPaths().codegraphDbPath;
|
|
18278
|
-
if (!
|
|
18531
|
+
if (!existsSync27(dbPath)) {
|
|
18279
18532
|
throw new CodegraphDbNotInitializedError(dbPath);
|
|
18280
18533
|
}
|
|
18281
18534
|
const db = new Database2(dbPath, { readonly: true });
|
|
@@ -18284,8 +18537,8 @@ function getCodeGraphDb() {
|
|
|
18284
18537
|
}
|
|
18285
18538
|
function getDataDb() {
|
|
18286
18539
|
const dbPath = getResolvedPaths().dataDbPath;
|
|
18287
|
-
const dir =
|
|
18288
|
-
if (!
|
|
18540
|
+
const dir = dirname13(dbPath);
|
|
18541
|
+
if (!existsSync27(dir)) {
|
|
18289
18542
|
mkdirSync10(dir, { recursive: true });
|
|
18290
18543
|
}
|
|
18291
18544
|
const db = new Database2(dbPath);
|
|
@@ -18592,10 +18845,10 @@ var init_db = __esm({
|
|
|
18592
18845
|
});
|
|
18593
18846
|
|
|
18594
18847
|
// src/security-utils.ts
|
|
18595
|
-
import { resolve as
|
|
18848
|
+
import { resolve as resolve24, normalize } from "path";
|
|
18596
18849
|
function ensureWithinRoot(filePath, projectRoot) {
|
|
18597
|
-
const resolvedRoot =
|
|
18598
|
-
const resolvedPath =
|
|
18850
|
+
const resolvedRoot = resolve24(projectRoot);
|
|
18851
|
+
const resolvedPath = resolve24(resolvedRoot, filePath);
|
|
18599
18852
|
const normalizedPath = normalize(resolvedPath);
|
|
18600
18853
|
const normalizedRoot = normalize(resolvedRoot);
|
|
18601
18854
|
if (!normalizedPath.startsWith(normalizedRoot + "/") && normalizedPath !== normalizedRoot) {
|
|
@@ -18668,8 +18921,8 @@ var init_rules = __esm({
|
|
|
18668
18921
|
});
|
|
18669
18922
|
|
|
18670
18923
|
// src/import-resolver.ts
|
|
18671
|
-
import { readFileSync as readFileSync25, existsSync as
|
|
18672
|
-
import { resolve as
|
|
18924
|
+
import { readFileSync as readFileSync25, existsSync as existsSync28, statSync as statSync12 } from "fs";
|
|
18925
|
+
import { resolve as resolve25, dirname as dirname14, join as join13 } from "path";
|
|
18673
18926
|
function parseImports(source) {
|
|
18674
18927
|
const imports = [];
|
|
18675
18928
|
const lines = source.split("\n");
|
|
@@ -18725,23 +18978,23 @@ function resolveImportPath(specifier, fromFile) {
|
|
|
18725
18978
|
let basePath;
|
|
18726
18979
|
if (specifier.startsWith("@/")) {
|
|
18727
18980
|
const paths = getResolvedPaths();
|
|
18728
|
-
basePath =
|
|
18981
|
+
basePath = resolve25(paths.pathAlias["@"] ?? paths.srcDir, specifier.slice(2));
|
|
18729
18982
|
} else {
|
|
18730
|
-
basePath =
|
|
18983
|
+
basePath = resolve25(dirname14(fromFile), specifier);
|
|
18731
18984
|
}
|
|
18732
|
-
if (
|
|
18985
|
+
if (existsSync28(basePath) && !isDirectory(basePath)) {
|
|
18733
18986
|
return toRelative(basePath);
|
|
18734
18987
|
}
|
|
18735
18988
|
const resolvedPaths = getResolvedPaths();
|
|
18736
18989
|
for (const ext of resolvedPaths.extensions) {
|
|
18737
18990
|
const withExt = basePath + ext;
|
|
18738
|
-
if (
|
|
18991
|
+
if (existsSync28(withExt)) {
|
|
18739
18992
|
return toRelative(withExt);
|
|
18740
18993
|
}
|
|
18741
18994
|
}
|
|
18742
18995
|
for (const indexFile of resolvedPaths.indexFiles) {
|
|
18743
18996
|
const indexPath = join13(basePath, indexFile);
|
|
18744
|
-
if (
|
|
18997
|
+
if (existsSync28(indexPath)) {
|
|
18745
18998
|
return toRelative(indexPath);
|
|
18746
18999
|
}
|
|
18747
19000
|
}
|
|
@@ -18777,8 +19030,8 @@ function buildImportIndex(dataDb, codegraphDb) {
|
|
|
18777
19030
|
const batchSize = 500;
|
|
18778
19031
|
let batch = [];
|
|
18779
19032
|
for (const file of files) {
|
|
18780
|
-
const absPath = ensureWithinRoot(
|
|
18781
|
-
if (!
|
|
19033
|
+
const absPath = ensureWithinRoot(resolve25(projectRoot, file.path), projectRoot);
|
|
19034
|
+
if (!existsSync28(absPath)) continue;
|
|
18782
19035
|
let source;
|
|
18783
19036
|
try {
|
|
18784
19037
|
source = readFileSync25(absPath, "utf-8");
|
|
@@ -18817,12 +19070,12 @@ var init_import_resolver = __esm({
|
|
|
18817
19070
|
});
|
|
18818
19071
|
|
|
18819
19072
|
// src/trpc-index.ts
|
|
18820
|
-
import { readFileSync as readFileSync26, existsSync as
|
|
18821
|
-
import { resolve as
|
|
19073
|
+
import { readFileSync as readFileSync26, existsSync as existsSync29, readdirSync as readdirSync16 } from "fs";
|
|
19074
|
+
import { resolve as resolve26, join as join14 } from "path";
|
|
18822
19075
|
function parseRootRouter() {
|
|
18823
19076
|
const paths = getResolvedPaths();
|
|
18824
19077
|
const rootPath = paths.rootRouterPath;
|
|
18825
|
-
if (!
|
|
19078
|
+
if (!existsSync29(rootPath)) {
|
|
18826
19079
|
throw new Error(`Root router not found at ${rootPath}`);
|
|
18827
19080
|
}
|
|
18828
19081
|
const source = readFileSync26(rootPath, "utf-8");
|
|
@@ -18833,16 +19086,16 @@ function parseRootRouter() {
|
|
|
18833
19086
|
while ((match = importRegex.exec(source)) !== null) {
|
|
18834
19087
|
const variable = match[1];
|
|
18835
19088
|
let filePath = match[2];
|
|
18836
|
-
const fullPath =
|
|
19089
|
+
const fullPath = resolve26(paths.routersDir, filePath);
|
|
18837
19090
|
for (const ext of [".ts", ".tsx", ""]) {
|
|
18838
19091
|
const candidate = fullPath + ext;
|
|
18839
19092
|
const routersRelPath = getConfig().paths.routers ?? "src/server/api/routers";
|
|
18840
|
-
if (
|
|
19093
|
+
if (existsSync29(candidate)) {
|
|
18841
19094
|
filePath = routersRelPath + "/" + filePath + ext;
|
|
18842
19095
|
break;
|
|
18843
19096
|
}
|
|
18844
19097
|
const indexCandidate = join14(fullPath, "index.ts");
|
|
18845
|
-
if (
|
|
19098
|
+
if (existsSync29(indexCandidate)) {
|
|
18846
19099
|
filePath = routersRelPath + "/" + filePath + "/index.ts";
|
|
18847
19100
|
break;
|
|
18848
19101
|
}
|
|
@@ -18861,8 +19114,8 @@ function parseRootRouter() {
|
|
|
18861
19114
|
return mappings;
|
|
18862
19115
|
}
|
|
18863
19116
|
function extractProcedures(routerFilePath) {
|
|
18864
|
-
const absPath =
|
|
18865
|
-
if (!
|
|
19117
|
+
const absPath = resolve26(getProjectRoot(), routerFilePath);
|
|
19118
|
+
if (!existsSync29(absPath)) return [];
|
|
18866
19119
|
const source = readFileSync26(absPath, "utf-8");
|
|
18867
19120
|
const procedures = [];
|
|
18868
19121
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -18886,13 +19139,13 @@ function findUICallSites(routerKey, procedureName) {
|
|
|
18886
19139
|
const root = getProjectRoot();
|
|
18887
19140
|
const src = config.paths.source;
|
|
18888
19141
|
const searchDirs = [
|
|
18889
|
-
|
|
18890
|
-
|
|
18891
|
-
|
|
19142
|
+
resolve26(root, config.paths.pages ?? src + "/app"),
|
|
19143
|
+
resolve26(root, config.paths.components ?? src + "/components"),
|
|
19144
|
+
resolve26(root, config.paths.hooks ?? src + "/hooks")
|
|
18892
19145
|
];
|
|
18893
19146
|
const searchPattern = `api.${routerKey}.${procedureName}`;
|
|
18894
19147
|
for (const dir of searchDirs) {
|
|
18895
|
-
if (!
|
|
19148
|
+
if (!existsSync29(dir)) continue;
|
|
18896
19149
|
searchDirectory(dir, searchPattern, callSites);
|
|
18897
19150
|
}
|
|
18898
19151
|
return callSites;
|
|
@@ -18969,8 +19222,8 @@ var init_trpc_index = __esm({
|
|
|
18969
19222
|
});
|
|
18970
19223
|
|
|
18971
19224
|
// src/page-deps.ts
|
|
18972
|
-
import { readFileSync as readFileSync27, existsSync as
|
|
18973
|
-
import { resolve as
|
|
19225
|
+
import { readFileSync as readFileSync27, existsSync as existsSync30 } from "fs";
|
|
19226
|
+
import { resolve as resolve27 } from "path";
|
|
18974
19227
|
function deriveRoute(pageFile) {
|
|
18975
19228
|
let route = pageFile.replace(/^src\/app/, "").replace(/\/page\.tsx?$/, "").replace(/\/page\.jsx?$/, "");
|
|
18976
19229
|
return route || "/";
|
|
@@ -19008,8 +19261,8 @@ function findRouterCalls(files) {
|
|
|
19008
19261
|
const routers = /* @__PURE__ */ new Set();
|
|
19009
19262
|
const projectRoot = getProjectRoot();
|
|
19010
19263
|
for (const file of files) {
|
|
19011
|
-
const absPath = ensureWithinRoot(
|
|
19012
|
-
if (!
|
|
19264
|
+
const absPath = ensureWithinRoot(resolve27(projectRoot, file), projectRoot);
|
|
19265
|
+
if (!existsSync30(absPath)) continue;
|
|
19013
19266
|
try {
|
|
19014
19267
|
const source = readFileSync27(absPath, "utf-8");
|
|
19015
19268
|
const apiCallRegex = /api\.(\w+)\.\w+/g;
|
|
@@ -19029,8 +19282,8 @@ function findTablesFromRouters(routerNames, dataDb) {
|
|
|
19029
19282
|
"SELECT DISTINCT router_file FROM massu_trpc_procedures WHERE router_name = ?"
|
|
19030
19283
|
).all(routerName);
|
|
19031
19284
|
for (const proc of procs) {
|
|
19032
|
-
const absPath = ensureWithinRoot(
|
|
19033
|
-
if (!
|
|
19285
|
+
const absPath = ensureWithinRoot(resolve27(getProjectRoot(), proc.router_file), getProjectRoot());
|
|
19286
|
+
if (!existsSync30(absPath)) continue;
|
|
19034
19287
|
try {
|
|
19035
19288
|
const source = readFileSync27(absPath, "utf-8");
|
|
19036
19289
|
const dbPattern = getConfig().dbAccessPattern ?? "ctx.db.{table}";
|
|
@@ -19301,11 +19554,11 @@ var init_domains = __esm({
|
|
|
19301
19554
|
});
|
|
19302
19555
|
|
|
19303
19556
|
// src/schema-mapper.ts
|
|
19304
|
-
import { readFileSync as readFileSync28, existsSync as
|
|
19557
|
+
import { readFileSync as readFileSync28, existsSync as existsSync31, readdirSync as readdirSync17 } from "fs";
|
|
19305
19558
|
import { join as join15 } from "path";
|
|
19306
19559
|
function parsePrismaSchema() {
|
|
19307
19560
|
const schemaPath = getResolvedPaths().prismaSchemaPath;
|
|
19308
|
-
if (!
|
|
19561
|
+
if (!existsSync31(schemaPath)) {
|
|
19309
19562
|
throw new Error(`Prisma schema not found at ${schemaPath}`);
|
|
19310
19563
|
}
|
|
19311
19564
|
const source = readFileSync28(schemaPath, "utf-8");
|
|
@@ -19366,7 +19619,7 @@ function toSnakeCase(str) {
|
|
|
19366
19619
|
function findColumnUsageInRouters(tableName) {
|
|
19367
19620
|
const usage = /* @__PURE__ */ new Map();
|
|
19368
19621
|
const routersDir = getResolvedPaths().routersDir;
|
|
19369
|
-
if (!
|
|
19622
|
+
if (!existsSync31(routersDir)) return usage;
|
|
19370
19623
|
scanDirectory(routersDir, tableName, usage);
|
|
19371
19624
|
return usage;
|
|
19372
19625
|
}
|
|
@@ -19428,7 +19681,7 @@ function detectMismatches(models) {
|
|
|
19428
19681
|
}
|
|
19429
19682
|
function findFilesUsingColumn(dir, column, tableName) {
|
|
19430
19683
|
const result = [];
|
|
19431
|
-
if (!
|
|
19684
|
+
if (!existsSync31(dir)) return result;
|
|
19432
19685
|
const entries = readdirSync17(dir, { withFileTypes: true });
|
|
19433
19686
|
for (const entry of entries) {
|
|
19434
19687
|
const fullPath = join15(dir, entry.name);
|
|
@@ -19581,14 +19834,14 @@ var init_import_parser = __esm({
|
|
|
19581
19834
|
});
|
|
19582
19835
|
|
|
19583
19836
|
// src/python/import-resolver.ts
|
|
19584
|
-
import { readFileSync as readFileSync29, existsSync as
|
|
19585
|
-
import { resolve as
|
|
19837
|
+
import { readFileSync as readFileSync29, existsSync as existsSync32, readdirSync as readdirSync18 } from "fs";
|
|
19838
|
+
import { resolve as resolve29, join as join16, relative as relative6, dirname as dirname15 } from "path";
|
|
19586
19839
|
function resolvePythonModulePath(module, fromFile, pythonRoot, level) {
|
|
19587
19840
|
const projectRoot = getProjectRoot();
|
|
19588
19841
|
if (level > 0) {
|
|
19589
|
-
let baseDir =
|
|
19842
|
+
let baseDir = dirname15(resolve29(projectRoot, fromFile));
|
|
19590
19843
|
for (let i = 1; i < level; i++) {
|
|
19591
|
-
baseDir =
|
|
19844
|
+
baseDir = dirname15(baseDir);
|
|
19592
19845
|
}
|
|
19593
19846
|
const modulePart = module.replace(/^\.+/, "");
|
|
19594
19847
|
if (modulePart) {
|
|
@@ -19598,17 +19851,17 @@ function resolvePythonModulePath(module, fromFile, pythonRoot, level) {
|
|
|
19598
19851
|
return tryResolvePythonPath(baseDir, projectRoot);
|
|
19599
19852
|
}
|
|
19600
19853
|
const parts = module.split(".");
|
|
19601
|
-
const candidate = join16(
|
|
19854
|
+
const candidate = join16(resolve29(projectRoot, pythonRoot), ...parts);
|
|
19602
19855
|
return tryResolvePythonPath(candidate, projectRoot);
|
|
19603
19856
|
}
|
|
19604
19857
|
function tryResolvePythonPath(basePath, projectRoot) {
|
|
19605
|
-
if (
|
|
19858
|
+
if (existsSync32(basePath + ".py")) {
|
|
19606
19859
|
return relative6(projectRoot, basePath + ".py");
|
|
19607
19860
|
}
|
|
19608
|
-
if (
|
|
19861
|
+
if (existsSync32(join16(basePath, "__init__.py"))) {
|
|
19609
19862
|
return relative6(projectRoot, join16(basePath, "__init__.py"));
|
|
19610
19863
|
}
|
|
19611
|
-
if (basePath.endsWith(".py") &&
|
|
19864
|
+
if (basePath.endsWith(".py") && existsSync32(basePath)) {
|
|
19612
19865
|
return relative6(projectRoot, basePath);
|
|
19613
19866
|
}
|
|
19614
19867
|
return null;
|
|
@@ -19631,7 +19884,7 @@ function walkPythonFiles(dir, excludeDirs) {
|
|
|
19631
19884
|
}
|
|
19632
19885
|
function buildPythonImportIndex(dataDb, pythonRoot, excludeDirs = ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"]) {
|
|
19633
19886
|
const projectRoot = getProjectRoot();
|
|
19634
|
-
const absRoot =
|
|
19887
|
+
const absRoot = resolve29(projectRoot, pythonRoot);
|
|
19635
19888
|
dataDb.exec("DELETE FROM massu_py_imports");
|
|
19636
19889
|
const insertStmt = dataDb.prepare(
|
|
19637
19890
|
"INSERT INTO massu_py_imports (source_file, target_file, import_type, imported_names, line) VALUES (?, ?, ?, ?, ?)"
|
|
@@ -20956,8 +21209,8 @@ var init_memory_tools = __esm({
|
|
|
20956
21209
|
});
|
|
20957
21210
|
|
|
20958
21211
|
// src/docs-tools.ts
|
|
20959
|
-
import { readFileSync as readFileSync34, existsSync as
|
|
20960
|
-
import { resolve as
|
|
21212
|
+
import { readFileSync as readFileSync34, existsSync as existsSync33 } from "fs";
|
|
21213
|
+
import { resolve as resolve30, basename as basename6 } from "path";
|
|
20961
21214
|
function p3(baseName) {
|
|
20962
21215
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
20963
21216
|
}
|
|
@@ -21012,7 +21265,7 @@ function handleDocsToolCall(name, args2) {
|
|
|
21012
21265
|
}
|
|
21013
21266
|
function loadDocsMap() {
|
|
21014
21267
|
const mapPath = getResolvedPaths().docsMapPath;
|
|
21015
|
-
if (!
|
|
21268
|
+
if (!existsSync33(mapPath)) {
|
|
21016
21269
|
throw new Error(`docs-map.json not found at ${mapPath}`);
|
|
21017
21270
|
}
|
|
21018
21271
|
return JSON.parse(readFileSync34(mapPath, "utf-8"));
|
|
@@ -21085,10 +21338,10 @@ function extractFrontmatter(content) {
|
|
|
21085
21338
|
}
|
|
21086
21339
|
function extractProcedureNames(routerPath) {
|
|
21087
21340
|
const root = getProjectRoot();
|
|
21088
|
-
const absPath = ensureWithinRoot(
|
|
21089
|
-
if (!
|
|
21090
|
-
const altPath = ensureWithinRoot(
|
|
21091
|
-
if (!
|
|
21341
|
+
const absPath = ensureWithinRoot(resolve30(getResolvedPaths().srcDir, "..", routerPath), root);
|
|
21342
|
+
if (!existsSync33(absPath)) {
|
|
21343
|
+
const altPath = ensureWithinRoot(resolve30(getResolvedPaths().srcDir, "../server/api/routers", basename6(routerPath)), root);
|
|
21344
|
+
if (!existsSync33(altPath)) return [];
|
|
21092
21345
|
return extractProcedureNamesFromContent(readFileSync34(altPath, "utf-8"));
|
|
21093
21346
|
}
|
|
21094
21347
|
return extractProcedureNamesFromContent(readFileSync34(absPath, "utf-8"));
|
|
@@ -21131,8 +21384,8 @@ function handleDocsAudit(args2) {
|
|
|
21131
21384
|
for (const [mappingId, triggeringFiles] of affectedMappings) {
|
|
21132
21385
|
const mapping = docsMap.mappings.find((m3) => m3.id === mappingId);
|
|
21133
21386
|
if (!mapping) continue;
|
|
21134
|
-
const helpPagePath = ensureWithinRoot(
|
|
21135
|
-
if (!
|
|
21387
|
+
const helpPagePath = ensureWithinRoot(resolve30(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
|
|
21388
|
+
if (!existsSync33(helpPagePath)) {
|
|
21136
21389
|
results.push({
|
|
21137
21390
|
helpPage: mapping.helpPage,
|
|
21138
21391
|
mappingId,
|
|
@@ -21184,8 +21437,8 @@ function handleDocsAudit(args2) {
|
|
|
21184
21437
|
});
|
|
21185
21438
|
for (const [guideName, parentId] of Object.entries(docsMap.userGuideInheritance.examples)) {
|
|
21186
21439
|
if (parentId === mappingId) {
|
|
21187
|
-
const guidePath = ensureWithinRoot(
|
|
21188
|
-
if (
|
|
21440
|
+
const guidePath = ensureWithinRoot(resolve30(getResolvedPaths().helpSitePath, `pages/user-guides/${guideName}/index.mdx`), getProjectRoot());
|
|
21441
|
+
if (existsSync33(guidePath)) {
|
|
21189
21442
|
const guideContent = readFileSync34(guidePath, "utf-8");
|
|
21190
21443
|
const guideFrontmatter = extractFrontmatter(guideContent);
|
|
21191
21444
|
if (!guideFrontmatter?.lastVerified || status === "STALE") {
|
|
@@ -21219,8 +21472,8 @@ function handleDocsCoverage(args2) {
|
|
|
21219
21472
|
const gaps = [];
|
|
21220
21473
|
const mappings = filterDomain ? docsMap.mappings.filter((m3) => m3.id === filterDomain) : docsMap.mappings;
|
|
21221
21474
|
for (const mapping of mappings) {
|
|
21222
|
-
const helpPagePath = ensureWithinRoot(
|
|
21223
|
-
const exists =
|
|
21475
|
+
const helpPagePath = ensureWithinRoot(resolve30(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
|
|
21476
|
+
const exists = existsSync33(helpPagePath);
|
|
21224
21477
|
let hasContent = false;
|
|
21225
21478
|
let lineCount = 0;
|
|
21226
21479
|
let lastVerified = null;
|
|
@@ -21567,8 +21820,8 @@ var init_observability_tools = __esm({
|
|
|
21567
21820
|
});
|
|
21568
21821
|
|
|
21569
21822
|
// src/sentinel-db.ts
|
|
21570
|
-
import { existsSync as
|
|
21571
|
-
import { resolve as
|
|
21823
|
+
import { existsSync as existsSync34 } from "fs";
|
|
21824
|
+
import { resolve as resolve31 } from "path";
|
|
21572
21825
|
function parsePortalScope(raw) {
|
|
21573
21826
|
if (!raw) return [];
|
|
21574
21827
|
try {
|
|
@@ -21804,23 +22057,23 @@ function validateFeatures(db, domainFilter) {
|
|
|
21804
22057
|
const missingProcedures = [];
|
|
21805
22058
|
const missingPages = [];
|
|
21806
22059
|
for (const comp of components) {
|
|
21807
|
-
const absPath =
|
|
21808
|
-
if (!
|
|
22060
|
+
const absPath = resolve31(PROJECT_ROOT, comp.component_file);
|
|
22061
|
+
if (!existsSync34(absPath)) {
|
|
21809
22062
|
missingComponents.push(comp.component_file);
|
|
21810
22063
|
}
|
|
21811
22064
|
}
|
|
21812
22065
|
for (const proc of procedures) {
|
|
21813
|
-
const routerPath =
|
|
21814
|
-
if (!
|
|
22066
|
+
const routerPath = resolve31(PROJECT_ROOT, `src/server/api/routers/${proc.router_name}.ts`);
|
|
22067
|
+
if (!existsSync34(routerPath)) {
|
|
21815
22068
|
missingProcedures.push({ router: proc.router_name, procedure: proc.procedure_name });
|
|
21816
22069
|
}
|
|
21817
22070
|
}
|
|
21818
22071
|
for (const page of pages) {
|
|
21819
22072
|
const routeToPath = page.page_route.replace(/^\/(portal-[^/]+\/)?/, "src/app/").replace(/\/$/, "") + "/page.tsx";
|
|
21820
|
-
const absPath =
|
|
21821
|
-
if (page.page_route.startsWith("/") && !
|
|
21822
|
-
const altPath =
|
|
21823
|
-
if (!
|
|
22073
|
+
const absPath = resolve31(PROJECT_ROOT, routeToPath);
|
|
22074
|
+
if (page.page_route.startsWith("/") && !existsSync34(absPath)) {
|
|
22075
|
+
const altPath = resolve31(PROJECT_ROOT, `src/app${page.page_route}/page.tsx`);
|
|
22076
|
+
if (!existsSync34(altPath)) {
|
|
21824
22077
|
missingPages.push(page.page_route);
|
|
21825
22078
|
}
|
|
21826
22079
|
}
|
|
@@ -22344,8 +22597,8 @@ var init_sentinel_tools = __esm({
|
|
|
22344
22597
|
});
|
|
22345
22598
|
|
|
22346
22599
|
// src/sentinel-scanner.ts
|
|
22347
|
-
import { readFileSync as readFileSync35, existsSync as
|
|
22348
|
-
import { resolve as
|
|
22600
|
+
import { readFileSync as readFileSync35, existsSync as existsSync35, readdirSync as readdirSync23, statSync as statSync13 } from "fs";
|
|
22601
|
+
import { resolve as resolve32, join as join21, basename as basename7, dirname as dirname16, relative as relative11 } from "path";
|
|
22349
22602
|
function inferDomain(filePath) {
|
|
22350
22603
|
const domains = getConfig().domains;
|
|
22351
22604
|
const path = filePath.toLowerCase();
|
|
@@ -22474,8 +22727,8 @@ function scanComponentExports(dataDb) {
|
|
|
22474
22727
|
const projectRoot = getProjectRoot();
|
|
22475
22728
|
const componentsBase = config.paths.components ?? config.paths.source + "/components";
|
|
22476
22729
|
const componentDirs = [];
|
|
22477
|
-
const basePath =
|
|
22478
|
-
if (
|
|
22730
|
+
const basePath = resolve32(projectRoot, componentsBase);
|
|
22731
|
+
if (existsSync35(basePath)) {
|
|
22479
22732
|
try {
|
|
22480
22733
|
const entries = readdirSync23(basePath, { withFileTypes: true });
|
|
22481
22734
|
for (const entry of entries) {
|
|
@@ -22487,8 +22740,8 @@ function scanComponentExports(dataDb) {
|
|
|
22487
22740
|
}
|
|
22488
22741
|
}
|
|
22489
22742
|
for (const dir of componentDirs) {
|
|
22490
|
-
const absDir =
|
|
22491
|
-
if (!
|
|
22743
|
+
const absDir = resolve32(projectRoot, dir);
|
|
22744
|
+
if (!existsSync35(absDir)) continue;
|
|
22492
22745
|
const files = walkDir2(absDir).filter((f2) => f2.endsWith(".tsx") || f2.endsWith(".ts"));
|
|
22493
22746
|
for (const file of files) {
|
|
22494
22747
|
const relPath = relative11(projectRoot, file);
|
|
@@ -22518,7 +22771,7 @@ function scanComponentExports(dataDb) {
|
|
|
22518
22771
|
if (hasHandlers && exportMatch) {
|
|
22519
22772
|
const componentName = exportMatch[1];
|
|
22520
22773
|
const domain = inferDomain(relPath);
|
|
22521
|
-
const subdomain = basename7(
|
|
22774
|
+
const subdomain = basename7(dirname16(relPath));
|
|
22522
22775
|
const featureKey = `component.${subdomain}.${componentName.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "")}`;
|
|
22523
22776
|
if (!annotations.some((a2) => a2.featureKey === featureKey)) {
|
|
22524
22777
|
features.push({
|
|
@@ -23531,7 +23784,7 @@ var init_audit_trail = __esm({
|
|
|
23531
23784
|
});
|
|
23532
23785
|
|
|
23533
23786
|
// src/validation-engine.ts
|
|
23534
|
-
import { existsSync as
|
|
23787
|
+
import { existsSync as existsSync36, readFileSync as readFileSync36 } from "fs";
|
|
23535
23788
|
function p10(baseName) {
|
|
23536
23789
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
23537
23790
|
}
|
|
@@ -23562,7 +23815,7 @@ function validateFile(filePath, projectRoot) {
|
|
|
23562
23815
|
});
|
|
23563
23816
|
return checks;
|
|
23564
23817
|
}
|
|
23565
|
-
if (!
|
|
23818
|
+
if (!existsSync36(absPath)) {
|
|
23566
23819
|
checks.push({
|
|
23567
23820
|
name: "file_exists",
|
|
23568
23821
|
severity: "error",
|
|
@@ -24016,7 +24269,7 @@ var init_adr_generator = __esm({
|
|
|
24016
24269
|
});
|
|
24017
24270
|
|
|
24018
24271
|
// src/security-scorer.ts
|
|
24019
|
-
import { existsSync as
|
|
24272
|
+
import { existsSync as existsSync37, readFileSync as readFileSync37 } from "fs";
|
|
24020
24273
|
function p12(baseName) {
|
|
24021
24274
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
24022
24275
|
}
|
|
@@ -24040,7 +24293,7 @@ function scoreFileSecurity(filePath, projectRoot) {
|
|
|
24040
24293
|
}]
|
|
24041
24294
|
};
|
|
24042
24295
|
}
|
|
24043
|
-
if (!
|
|
24296
|
+
if (!existsSync37(absPath)) {
|
|
24044
24297
|
return { riskScore: 0, findings: [] };
|
|
24045
24298
|
}
|
|
24046
24299
|
let source;
|
|
@@ -24334,8 +24587,8 @@ var init_security_scorer = __esm({
|
|
|
24334
24587
|
});
|
|
24335
24588
|
|
|
24336
24589
|
// src/dependency-scorer.ts
|
|
24337
|
-
import { existsSync as
|
|
24338
|
-
import { resolve as
|
|
24590
|
+
import { existsSync as existsSync38, readFileSync as readFileSync38 } from "fs";
|
|
24591
|
+
import { resolve as resolve33 } from "path";
|
|
24339
24592
|
function p13(baseName) {
|
|
24340
24593
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
24341
24594
|
}
|
|
@@ -24367,8 +24620,8 @@ function calculateDepRisk(factors) {
|
|
|
24367
24620
|
return Math.min(100, risk);
|
|
24368
24621
|
}
|
|
24369
24622
|
function getInstalledPackages(projectRoot) {
|
|
24370
|
-
const pkgPath =
|
|
24371
|
-
if (!
|
|
24623
|
+
const pkgPath = resolve33(projectRoot, "package.json");
|
|
24624
|
+
if (!existsSync38(pkgPath)) return /* @__PURE__ */ new Map();
|
|
24372
24625
|
try {
|
|
24373
24626
|
const pkg = JSON.parse(readFileSync38(pkgPath, "utf-8"));
|
|
24374
24627
|
const packages = /* @__PURE__ */ new Map();
|
|
@@ -24973,8 +25226,8 @@ var init_regression_detector = __esm({
|
|
|
24973
25226
|
|
|
24974
25227
|
// src/knowledge-indexer.ts
|
|
24975
25228
|
import { createHash as createHash9 } from "crypto";
|
|
24976
|
-
import { readFileSync as readFileSync39, readdirSync as readdirSync24, statSync as statSync14, existsSync as
|
|
24977
|
-
import { resolve as
|
|
25229
|
+
import { readFileSync as readFileSync39, readdirSync as readdirSync24, statSync as statSync14, existsSync as existsSync39 } from "fs";
|
|
25230
|
+
import { resolve as resolve34, relative as relative12, basename as basename8, extname as extname2 } from "path";
|
|
24978
25231
|
function getKnowledgePaths() {
|
|
24979
25232
|
const resolved = getResolvedPaths();
|
|
24980
25233
|
const config = getConfig();
|
|
@@ -25002,7 +25255,7 @@ function discoverMarkdownFiles(baseDir) {
|
|
|
25002
25255
|
try {
|
|
25003
25256
|
const entries = readdirSync24(dir, { withFileTypes: true });
|
|
25004
25257
|
for (const entry of entries) {
|
|
25005
|
-
const fullPath =
|
|
25258
|
+
const fullPath = resolve34(dir, entry.name);
|
|
25006
25259
|
if (entry.isDirectory()) {
|
|
25007
25260
|
if (entry.name === "archive" && dir.includes("session-state")) continue;
|
|
25008
25261
|
if (entry.name === "archive" && dir.includes("status")) continue;
|
|
@@ -25280,11 +25533,11 @@ function indexAllKnowledge(db) {
|
|
|
25280
25533
|
files.push(...memFiles);
|
|
25281
25534
|
} catch {
|
|
25282
25535
|
}
|
|
25283
|
-
if (
|
|
25536
|
+
if (existsSync39(paths.plansDir)) {
|
|
25284
25537
|
const planFiles = discoverMarkdownFiles(paths.plansDir);
|
|
25285
25538
|
files.push(...planFiles);
|
|
25286
25539
|
}
|
|
25287
|
-
if (
|
|
25540
|
+
if (existsSync39(paths.docsDir)) {
|
|
25288
25541
|
const excludePatterns = getConfig().conventions?.excludePatterns ?? ["/ARCHIVE/", "/SESSION-HISTORY/"];
|
|
25289
25542
|
const docsFiles = discoverMarkdownFiles(paths.docsDir).filter((f2) => !f2.includes("/plans/") && !excludePatterns.some((p19) => f2.includes(p19)));
|
|
25290
25543
|
files.push(...docsFiles);
|
|
@@ -25327,7 +25580,7 @@ function indexAllKnowledge(db) {
|
|
|
25327
25580
|
} catch {
|
|
25328
25581
|
}
|
|
25329
25582
|
for (const filePath of files) {
|
|
25330
|
-
if (!
|
|
25583
|
+
if (!existsSync39(filePath)) continue;
|
|
25331
25584
|
const content = readFileSync39(filePath, "utf-8");
|
|
25332
25585
|
const hash = hashContent2(content);
|
|
25333
25586
|
const relPath = filePath.startsWith(paths.claudeDir) ? relative12(paths.claudeDir, filePath) : filePath.startsWith(paths.plansDir) ? "plans/" + relative12(paths.plansDir, filePath) : filePath.startsWith(paths.docsDir) ? "docs/" + relative12(paths.docsDir, filePath) : filePath.startsWith(paths.memoryDir) ? `memory/${relative12(paths.memoryDir, filePath)}` : basename8(filePath);
|
|
@@ -25448,10 +25701,10 @@ function isKnowledgeStale(db) {
|
|
|
25448
25701
|
files.push(...discoverMarkdownFiles(paths.memoryDir));
|
|
25449
25702
|
} catch {
|
|
25450
25703
|
}
|
|
25451
|
-
if (
|
|
25704
|
+
if (existsSync39(paths.plansDir)) {
|
|
25452
25705
|
files.push(...discoverMarkdownFiles(paths.plansDir));
|
|
25453
25706
|
}
|
|
25454
|
-
if (
|
|
25707
|
+
if (existsSync39(paths.docsDir)) {
|
|
25455
25708
|
const excludePatterns = getConfig().conventions?.excludePatterns ?? ["/ARCHIVE/", "/SESSION-HISTORY/"];
|
|
25456
25709
|
const docsFiles = discoverMarkdownFiles(paths.docsDir).filter((f2) => !f2.includes("/plans/") && !excludePatterns.some((p19) => f2.includes(p19)));
|
|
25457
25710
|
files.push(...docsFiles);
|
|
@@ -25481,7 +25734,7 @@ var init_knowledge_indexer = __esm({
|
|
|
25481
25734
|
|
|
25482
25735
|
// src/knowledge-tools.ts
|
|
25483
25736
|
import { readFileSync as readFileSync40, writeFileSync as writeFileSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync25 } from "fs";
|
|
25484
|
-
import { resolve as
|
|
25737
|
+
import { resolve as resolve35, basename as basename9 } from "path";
|
|
25485
25738
|
function p16(baseName) {
|
|
25486
25739
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
25487
25740
|
}
|
|
@@ -26218,7 +26471,7 @@ function handleCorrect(db, args2) {
|
|
|
26218
26471
|
if (!wrong || !correction || !rule) {
|
|
26219
26472
|
return text15("Error: wrong, correction, and rule are all required.");
|
|
26220
26473
|
}
|
|
26221
|
-
const correctionsPath =
|
|
26474
|
+
const correctionsPath = resolve35(getResolvedPaths().memoryDir, "corrections.md");
|
|
26222
26475
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
26223
26476
|
const title = rule.slice(0, 60);
|
|
26224
26477
|
const entry = `
|
|
@@ -26569,12 +26822,12 @@ var init_knowledge_tools = __esm({
|
|
|
26569
26822
|
|
|
26570
26823
|
// src/knowledge-db.ts
|
|
26571
26824
|
import Database3 from "better-sqlite3";
|
|
26572
|
-
import { dirname as
|
|
26573
|
-
import { existsSync as
|
|
26825
|
+
import { dirname as dirname17 } from "path";
|
|
26826
|
+
import { existsSync as existsSync41, mkdirSync as mkdirSync11 } from "fs";
|
|
26574
26827
|
function getKnowledgeDb() {
|
|
26575
26828
|
const dbPath = getResolvedPaths().knowledgeDbPath;
|
|
26576
|
-
const dir =
|
|
26577
|
-
if (!
|
|
26829
|
+
const dir = dirname17(dbPath);
|
|
26830
|
+
if (!existsSync41(dir)) {
|
|
26578
26831
|
mkdirSync11(dir, { recursive: true });
|
|
26579
26832
|
}
|
|
26580
26833
|
const db = new Database3(dbPath);
|
|
@@ -27308,8 +27561,8 @@ var init_python_tools = __esm({
|
|
|
27308
27561
|
});
|
|
27309
27562
|
|
|
27310
27563
|
// src/tools.ts
|
|
27311
|
-
import { readFileSync as readFileSync41, existsSync as
|
|
27312
|
-
import { resolve as
|
|
27564
|
+
import { readFileSync as readFileSync41, existsSync as existsSync42 } from "fs";
|
|
27565
|
+
import { resolve as resolve36, basename as basename10 } from "path";
|
|
27313
27566
|
function prefix2() {
|
|
27314
27567
|
return getConfig().toolPrefix;
|
|
27315
27568
|
}
|
|
@@ -27344,7 +27597,7 @@ function ensureIndexes(dataDb, codegraphDb, force = false) {
|
|
|
27344
27597
|
if (config.python?.root) {
|
|
27345
27598
|
const pythonRoot = config.python.root;
|
|
27346
27599
|
const excludeDirs = config.python.exclude_dirs || ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"];
|
|
27347
|
-
if (force || isPythonDataStale(dataDb,
|
|
27600
|
+
if (force || isPythonDataStale(dataDb, resolve36(getProjectRoot(), pythonRoot))) {
|
|
27348
27601
|
const pyImports = buildPythonImportIndex(dataDb, pythonRoot, excludeDirs);
|
|
27349
27602
|
results.push(`Python imports: ${pyImports}`);
|
|
27350
27603
|
const pyRoutes = buildPythonRouteIndex(dataDb, pythonRoot, excludeDirs);
|
|
@@ -27779,8 +28032,8 @@ function handleContext(file, dataDb, codegraphDb) {
|
|
|
27779
28032
|
try {
|
|
27780
28033
|
const resolvedPaths = getResolvedPaths();
|
|
27781
28034
|
const root = getProjectRoot();
|
|
27782
|
-
const absFilePath = ensureWithinRoot(
|
|
27783
|
-
if (
|
|
28035
|
+
const absFilePath = ensureWithinRoot(resolve36(resolvedPaths.srcDir, "..", file), root);
|
|
28036
|
+
if (existsSync42(absFilePath)) {
|
|
27784
28037
|
const fileContent = readFileSync41(absFilePath, "utf-8").slice(0, 3e3);
|
|
27785
28038
|
const keywords = [];
|
|
27786
28039
|
if (fileContent.includes("ctx.db")) keywords.push("database", "schema");
|
|
@@ -27970,13 +28223,26 @@ function handleTrpcMap(args2, dataDb) {
|
|
|
27970
28223
|
const total = dataDb.prepare("SELECT COUNT(*) as count FROM massu_trpc_procedures").get();
|
|
27971
28224
|
const coupled = dataDb.prepare("SELECT COUNT(*) as count FROM massu_trpc_procedures WHERE has_ui_caller = 1").get();
|
|
27972
28225
|
const uncoupled = total.count - coupled.count;
|
|
27973
|
-
|
|
27974
|
-
|
|
27975
|
-
|
|
27976
|
-
|
|
27977
|
-
|
|
27978
|
-
|
|
27979
|
-
|
|
28226
|
+
if (total.count === 0) {
|
|
28227
|
+
lines.push("## tRPC Index Empty");
|
|
28228
|
+
lines.push("");
|
|
28229
|
+
lines.push("No tRPC procedures indexed yet. Either this repo has no tRPC");
|
|
28230
|
+
lines.push("routers, or the CodeGraph index has not been built. To rebuild:");
|
|
28231
|
+
lines.push("");
|
|
28232
|
+
lines.push(" npx massu sync");
|
|
28233
|
+
lines.push("");
|
|
28234
|
+
lines.push("If `massu sync` completes successfully but `trpc_map` still");
|
|
28235
|
+
lines.push("returns 0, the repo likely has no tRPC procedures (this is");
|
|
28236
|
+
lines.push("expected for non-tRPC stacks \u2014 try `schema` or `domains` tools).");
|
|
28237
|
+
} else {
|
|
28238
|
+
lines.push("## tRPC Procedure Summary");
|
|
28239
|
+
lines.push(`- Total procedures: ${total.count}`);
|
|
28240
|
+
lines.push(`- With UI callers: ${coupled.count}`);
|
|
28241
|
+
lines.push(`- Without UI callers: ${uncoupled}`);
|
|
28242
|
+
lines.push("");
|
|
28243
|
+
lines.push('Use { router: "name" } to see details for a specific router.');
|
|
28244
|
+
lines.push("Use { uncoupled: true } to see all procedures without UI callers.");
|
|
28245
|
+
}
|
|
27980
28246
|
}
|
|
27981
28247
|
return text17(lines.join("\n"));
|
|
27982
28248
|
}
|
|
@@ -28205,8 +28471,8 @@ function handleSchema(args2) {
|
|
|
28205
28471
|
lines.push("Checking all column references against Prisma schema...");
|
|
28206
28472
|
lines.push("");
|
|
28207
28473
|
const projectRoot = getProjectRoot();
|
|
28208
|
-
const absPath = ensureWithinRoot(
|
|
28209
|
-
if (!
|
|
28474
|
+
const absPath = ensureWithinRoot(resolve36(projectRoot, file), projectRoot);
|
|
28475
|
+
if (!existsSync42(absPath)) {
|
|
28210
28476
|
return text17(`File not found: ${file}`);
|
|
28211
28477
|
}
|
|
28212
28478
|
const source = readFileSync41(absPath, "utf-8");
|
|
@@ -28319,8 +28585,14 @@ var init_tool_db_needs = __esm({
|
|
|
28319
28585
|
coupling_check: ["codegraph", "data"],
|
|
28320
28586
|
impact: ["codegraph", "data"],
|
|
28321
28587
|
domains: ["codegraph", "data"],
|
|
28322
|
-
// `trpc_map`
|
|
28323
|
-
|
|
28588
|
+
// P-H009 (plan-stage-c-high-batch): `trpc_map` queries Data DB tables
|
|
28589
|
+
// populated by `ensureIndexes(d, codegraphDb)` — without CodeGraph the
|
|
28590
|
+
// index never builds and the flagship code-intel tool silently returns
|
|
28591
|
+
// "0 procedures" on fresh installs. Declaring `codegraph` here makes the
|
|
28592
|
+
// dispatcher open the CodeGraph DB so `buildTrpcIndex` can run; the
|
|
28593
|
+
// handler also surfaces an actionable hint when no procedures + no
|
|
28594
|
+
// codegraph (covered by `trpc-map-empty-codegraph-hint.test.ts`).
|
|
28595
|
+
trpc_map: ["codegraph", "data"],
|
|
28324
28596
|
// `schema` reads filesystem (Prisma schema files); no DB access at all.
|
|
28325
28597
|
schema: [],
|
|
28326
28598
|
// === Memory tools (memory-tools.ts) ===
|
|
@@ -28579,8 +28851,8 @@ var init_server_dispatch = __esm({
|
|
|
28579
28851
|
// src/server.ts
|
|
28580
28852
|
var server_exports = {};
|
|
28581
28853
|
import { readFileSync as readFileSync42 } from "fs";
|
|
28582
|
-
import { resolve as
|
|
28583
|
-
import { fileURLToPath as
|
|
28854
|
+
import { resolve as resolve37, dirname as dirname18 } from "path";
|
|
28855
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
28584
28856
|
function pruneMemoryOnStartup() {
|
|
28585
28857
|
try {
|
|
28586
28858
|
const memDb = getMemoryDb();
|
|
@@ -28604,17 +28876,17 @@ function pruneMemoryOnStartup() {
|
|
|
28604
28876
|
);
|
|
28605
28877
|
}
|
|
28606
28878
|
}
|
|
28607
|
-
var
|
|
28879
|
+
var __dirname5, PKG_VERSION, dispatcher, buffer;
|
|
28608
28880
|
var init_server = __esm({
|
|
28609
28881
|
"src/server.ts"() {
|
|
28610
28882
|
"use strict";
|
|
28611
28883
|
init_memory_db();
|
|
28612
28884
|
init_license();
|
|
28613
28885
|
init_server_dispatch();
|
|
28614
|
-
|
|
28886
|
+
__dirname5 = dirname18(fileURLToPath5(import.meta.url));
|
|
28615
28887
|
PKG_VERSION = (() => {
|
|
28616
28888
|
try {
|
|
28617
|
-
const pkg = JSON.parse(readFileSync42(
|
|
28889
|
+
const pkg = JSON.parse(readFileSync42(resolve37(__dirname5, "..", "package.json"), "utf-8"));
|
|
28618
28890
|
return pkg.version ?? "0.0.0";
|
|
28619
28891
|
} catch {
|
|
28620
28892
|
return "0.0.0";
|
|
@@ -28900,19 +29172,19 @@ var config_upgrade_exports = {};
|
|
|
28900
29172
|
__export(config_upgrade_exports, {
|
|
28901
29173
|
runConfigUpgrade: () => runConfigUpgrade
|
|
28902
29174
|
});
|
|
28903
|
-
import { existsSync as
|
|
28904
|
-
import { resolve as
|
|
29175
|
+
import { existsSync as existsSync43, readFileSync as readFileSync43, writeFileSync as writeFileSync6, copyFileSync, unlinkSync as unlinkSync2 } from "fs";
|
|
29176
|
+
import { resolve as resolve38 } from "path";
|
|
28905
29177
|
import { parse as parseYaml6 } from "yaml";
|
|
28906
29178
|
async function runConfigUpgrade(opts = {}) {
|
|
28907
29179
|
const cwd = opts.cwd ?? process.cwd();
|
|
28908
|
-
const configPath =
|
|
29180
|
+
const configPath = resolve38(cwd, "massu.config.yaml");
|
|
28909
29181
|
const bakPath = `${configPath}.bak`;
|
|
28910
29182
|
const log = opts.silent ? () => {
|
|
28911
29183
|
} : (s) => process.stdout.write(s);
|
|
28912
29184
|
const err = opts.silent ? () => {
|
|
28913
29185
|
} : (s) => process.stderr.write(s);
|
|
28914
29186
|
if (opts.rollback) {
|
|
28915
|
-
if (!
|
|
29187
|
+
if (!existsSync43(bakPath)) {
|
|
28916
29188
|
const message = `No backup found at ${bakPath}`;
|
|
28917
29189
|
err(message + "\n");
|
|
28918
29190
|
return { exitCode: 1, action: "none", message };
|
|
@@ -28928,7 +29200,7 @@ async function runConfigUpgrade(opts = {}) {
|
|
|
28928
29200
|
return { exitCode: 2, action: "none", message };
|
|
28929
29201
|
}
|
|
28930
29202
|
}
|
|
28931
|
-
if (!
|
|
29203
|
+
if (!existsSync43(configPath)) {
|
|
28932
29204
|
const message = "massu.config.yaml not found. Run: npx massu init";
|
|
28933
29205
|
err(message + "\n");
|
|
28934
29206
|
return { exitCode: 1, action: "none", message };
|
|
@@ -28992,8 +29264,8 @@ var config_check_drift_exports = {};
|
|
|
28992
29264
|
__export(config_check_drift_exports, {
|
|
28993
29265
|
runConfigCheckDrift: () => runConfigCheckDrift
|
|
28994
29266
|
});
|
|
28995
|
-
import { existsSync as
|
|
28996
|
-
import { resolve as
|
|
29267
|
+
import { existsSync as existsSync44, readFileSync as readFileSync44 } from "fs";
|
|
29268
|
+
import { resolve as resolve39 } from "path";
|
|
28997
29269
|
import { parse as parseYaml7 } from "yaml";
|
|
28998
29270
|
function renderChanges(changes) {
|
|
28999
29271
|
if (changes.length === 0) return "(none)\n";
|
|
@@ -29001,12 +29273,12 @@ function renderChanges(changes) {
|
|
|
29001
29273
|
}
|
|
29002
29274
|
async function runConfigCheckDrift(opts = {}) {
|
|
29003
29275
|
const cwd = opts.cwd ?? process.cwd();
|
|
29004
|
-
const configPath =
|
|
29276
|
+
const configPath = resolve39(cwd, "massu.config.yaml");
|
|
29005
29277
|
const log = opts.silent ? () => {
|
|
29006
29278
|
} : (s) => process.stdout.write(s);
|
|
29007
29279
|
const err = opts.silent ? () => {
|
|
29008
29280
|
} : (s) => process.stderr.write(s);
|
|
29009
|
-
if (!
|
|
29281
|
+
if (!existsSync44(configPath)) {
|
|
29010
29282
|
const message = "massu.config.yaml not found. Run: npx massu init";
|
|
29011
29283
|
err(message + "\n");
|
|
29012
29284
|
return {
|
|
@@ -29088,10 +29360,10 @@ var init_config_check_drift = __esm({
|
|
|
29088
29360
|
|
|
29089
29361
|
// src/cli.ts
|
|
29090
29362
|
import { readFileSync as readFileSync45 } from "fs";
|
|
29091
|
-
import { resolve as
|
|
29092
|
-
import { fileURLToPath as
|
|
29093
|
-
var
|
|
29094
|
-
var
|
|
29363
|
+
import { resolve as resolve40, dirname as dirname19 } from "path";
|
|
29364
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
29365
|
+
var __filename5 = fileURLToPath6(import.meta.url);
|
|
29366
|
+
var __dirname6 = dirname19(__filename5);
|
|
29095
29367
|
var args = process.argv.slice(2);
|
|
29096
29368
|
var subcommand = args[0];
|
|
29097
29369
|
async function main() {
|
|
@@ -29111,6 +29383,12 @@ async function main() {
|
|
|
29111
29383
|
await runInstallHooks2();
|
|
29112
29384
|
break;
|
|
29113
29385
|
}
|
|
29386
|
+
case "hook-runner": {
|
|
29387
|
+
const { runHookRunner: runHookRunner2 } = await Promise.resolve().then(() => (init_hook_runner(), hook_runner_exports));
|
|
29388
|
+
const result = await runHookRunner2(args.slice(1));
|
|
29389
|
+
process.exit(result.exitCode);
|
|
29390
|
+
return;
|
|
29391
|
+
}
|
|
29114
29392
|
case "install-commands": {
|
|
29115
29393
|
const { runInstallCommands: runInstallCommands2 } = await Promise.resolve().then(() => (init_install_commands(), install_commands_exports));
|
|
29116
29394
|
await runInstallCommands2();
|
|
@@ -29287,7 +29565,7 @@ Examples:
|
|
|
29287
29565
|
}
|
|
29288
29566
|
function printVersion() {
|
|
29289
29567
|
try {
|
|
29290
|
-
const pkg = JSON.parse(readFileSync45(
|
|
29568
|
+
const pkg = JSON.parse(readFileSync45(resolve40(__dirname6, "../package.json"), "utf-8"));
|
|
29291
29569
|
console.log(`massu v${pkg.version}`);
|
|
29292
29570
|
} catch {
|
|
29293
29571
|
console.log("massu v0.1.0");
|