@massu/core 1.15.0 → 1.15.2
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/CHANGELOG.md +30 -0
- package/commands/massu-loop/references/loop-controller.md +54 -7
- package/dist/cli.js +930 -575
- package/dist/hooks/auto-learning-pipeline.js +90 -19
- package/dist/hooks/classify-failure.js +112 -43
- package/dist/hooks/cost-tracker.js +108 -39
- package/dist/hooks/fix-detector.js +95 -24
- package/dist/hooks/incident-pipeline.js +114 -45
- package/dist/hooks/post-edit-context.js +105 -36
- package/dist/hooks/post-tool-use.js +137 -68
- package/dist/hooks/pre-compact.js +108 -39
- package/dist/hooks/pre-delete-check.js +107 -38
- package/dist/hooks/pre-tool-use-gate.js +113 -44
- package/dist/hooks/quality-event.js +108 -39
- package/dist/hooks/rule-enforcement-pipeline.js +92 -21
- package/dist/hooks/session-end.js +126 -57
- package/dist/hooks/session-start.js +177 -99
- package/dist/hooks/user-prompt.js +124 -55
- package/package.json +7 -6
|
@@ -12,11 +12,20 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
12
12
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
13
13
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
14
14
|
});
|
|
15
|
-
var __esm = (fn, res) => function __init() {
|
|
16
|
-
|
|
15
|
+
var __esm = (fn, res, err) => function __init() {
|
|
16
|
+
if (err) throw err[0];
|
|
17
|
+
try {
|
|
18
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
throw err = [e], e;
|
|
21
|
+
}
|
|
17
22
|
};
|
|
18
23
|
var __commonJS = (cb, mod) => function __require2() {
|
|
19
|
-
|
|
24
|
+
try {
|
|
25
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
26
|
+
} catch (e) {
|
|
27
|
+
throw mod = 0, e;
|
|
28
|
+
}
|
|
20
29
|
};
|
|
21
30
|
var __export = (target, all) => {
|
|
22
31
|
for (var name in all)
|
|
@@ -201,17 +210,17 @@ var init_manifest_registry = __esm({
|
|
|
201
210
|
});
|
|
202
211
|
|
|
203
212
|
// src/detect/package-detector.ts
|
|
204
|
-
import { readFileSync as
|
|
213
|
+
import { readFileSync as readFileSync4, existsSync as existsSync5, statSync, lstatSync, readdirSync } from "fs";
|
|
205
214
|
import { join as join2, relative } from "path";
|
|
206
215
|
import { parse as parseToml } from "smol-toml";
|
|
207
216
|
function safeRead(path) {
|
|
208
217
|
try {
|
|
209
|
-
if (!
|
|
218
|
+
if (!existsSync5(path)) return null;
|
|
210
219
|
const ls = lstatSync(path);
|
|
211
220
|
if (ls.isSymbolicLink()) return null;
|
|
212
221
|
const st = statSync(path);
|
|
213
222
|
if (!st.isFile()) return null;
|
|
214
|
-
return
|
|
223
|
+
return readFileSync4(path, "utf-8");
|
|
215
224
|
} catch {
|
|
216
225
|
return null;
|
|
217
226
|
}
|
|
@@ -242,7 +251,7 @@ function parsePackageJson(path, directory, root, warnings) {
|
|
|
242
251
|
const peer = Object.keys(
|
|
243
252
|
pkg.peerDependencies ?? {}
|
|
244
253
|
);
|
|
245
|
-
const hasTs = deps.includes("typescript") || devDeps.includes("typescript") ||
|
|
254
|
+
const hasTs = deps.includes("typescript") || devDeps.includes("typescript") || existsSync5(join2(directory, "tsconfig.json"));
|
|
246
255
|
const language = hasTs ? "typescript" : "javascript";
|
|
247
256
|
const scripts = Object.keys(
|
|
248
257
|
pkg.scripts ?? {}
|
|
@@ -669,7 +678,7 @@ function detectManifestsInDir(dir, root, warnings) {
|
|
|
669
678
|
for (const entry of getManifestRegistry2()) {
|
|
670
679
|
if (!entry.pattern.startsWith("*")) {
|
|
671
680
|
const path = join2(dir, entry.pattern);
|
|
672
|
-
if (!
|
|
681
|
+
if (!existsSync5(path)) continue;
|
|
673
682
|
const m = entry.parse(path, dir, root, warnings);
|
|
674
683
|
if (m !== null) out.push(m);
|
|
675
684
|
} else {
|
|
@@ -683,7 +692,7 @@ function detectManifestsInDir(dir, root, warnings) {
|
|
|
683
692
|
for (const fname of dirEntries) {
|
|
684
693
|
if (!matchManifestPattern2(fname, entry.pattern)) continue;
|
|
685
694
|
const path = join2(dir, fname);
|
|
686
|
-
if (!
|
|
695
|
+
if (!existsSync5(path)) continue;
|
|
687
696
|
const m = entry.parse(path, dir, root, warnings);
|
|
688
697
|
if (m !== null) out.push(m);
|
|
689
698
|
}
|
|
@@ -704,7 +713,7 @@ function detectPackageManifests(projectRoot) {
|
|
|
704
713
|
manifests.push(...detectManifestsInDir(projectRoot, projectRoot, warnings));
|
|
705
714
|
for (const ws of WORKSPACE_DIRS) {
|
|
706
715
|
const wsRoot = join2(projectRoot, ws);
|
|
707
|
-
if (!
|
|
716
|
+
if (!existsSync5(wsRoot)) continue;
|
|
708
717
|
for (const sub of listSubdirs(wsRoot)) {
|
|
709
718
|
manifests.push(...detectManifestsInDir(sub, projectRoot, warnings));
|
|
710
719
|
for (const sub2 of listSubdirs(sub)) {
|
|
@@ -5475,41 +5484,41 @@ var require_queue = __commonJS({
|
|
|
5475
5484
|
queue.drained = drained;
|
|
5476
5485
|
return queue;
|
|
5477
5486
|
function push(value) {
|
|
5478
|
-
var p = new Promise(function(
|
|
5487
|
+
var p = new Promise(function(resolve7, reject) {
|
|
5479
5488
|
pushCb(value, function(err, result) {
|
|
5480
5489
|
if (err) {
|
|
5481
5490
|
reject(err);
|
|
5482
5491
|
return;
|
|
5483
5492
|
}
|
|
5484
|
-
|
|
5493
|
+
resolve7(result);
|
|
5485
5494
|
});
|
|
5486
5495
|
});
|
|
5487
5496
|
p.catch(noop);
|
|
5488
5497
|
return p;
|
|
5489
5498
|
}
|
|
5490
5499
|
function unshift(value) {
|
|
5491
|
-
var p = new Promise(function(
|
|
5500
|
+
var p = new Promise(function(resolve7, reject) {
|
|
5492
5501
|
unshiftCb(value, function(err, result) {
|
|
5493
5502
|
if (err) {
|
|
5494
5503
|
reject(err);
|
|
5495
5504
|
return;
|
|
5496
5505
|
}
|
|
5497
|
-
|
|
5506
|
+
resolve7(result);
|
|
5498
5507
|
});
|
|
5499
5508
|
});
|
|
5500
5509
|
p.catch(noop);
|
|
5501
5510
|
return p;
|
|
5502
5511
|
}
|
|
5503
5512
|
function drained() {
|
|
5504
|
-
var p = new Promise(function(
|
|
5513
|
+
var p = new Promise(function(resolve7) {
|
|
5505
5514
|
process.nextTick(function() {
|
|
5506
5515
|
if (queue.idle()) {
|
|
5507
|
-
|
|
5516
|
+
resolve7();
|
|
5508
5517
|
} else {
|
|
5509
5518
|
var previousDrain = queue.drain;
|
|
5510
5519
|
queue.drain = function() {
|
|
5511
5520
|
if (typeof previousDrain === "function") previousDrain();
|
|
5512
|
-
|
|
5521
|
+
resolve7();
|
|
5513
5522
|
queue.drain = previousDrain;
|
|
5514
5523
|
};
|
|
5515
5524
|
}
|
|
@@ -5995,9 +6004,9 @@ var require_stream3 = __commonJS({
|
|
|
5995
6004
|
});
|
|
5996
6005
|
}
|
|
5997
6006
|
_getStat(filepath) {
|
|
5998
|
-
return new Promise((
|
|
6007
|
+
return new Promise((resolve7, reject) => {
|
|
5999
6008
|
this._stat(filepath, this._fsStatSettings, (error, stats) => {
|
|
6000
|
-
return error === null ?
|
|
6009
|
+
return error === null ? resolve7(stats) : reject(error);
|
|
6001
6010
|
});
|
|
6002
6011
|
});
|
|
6003
6012
|
}
|
|
@@ -6021,10 +6030,10 @@ var require_async5 = __commonJS({
|
|
|
6021
6030
|
this._readerStream = new stream_1.default(this._settings);
|
|
6022
6031
|
}
|
|
6023
6032
|
dynamic(root, options) {
|
|
6024
|
-
return new Promise((
|
|
6033
|
+
return new Promise((resolve7, reject) => {
|
|
6025
6034
|
this._walkAsync(root, options, (error, entries) => {
|
|
6026
6035
|
if (error === null) {
|
|
6027
|
-
|
|
6036
|
+
resolve7(entries);
|
|
6028
6037
|
} else {
|
|
6029
6038
|
reject(error);
|
|
6030
6039
|
}
|
|
@@ -6034,10 +6043,10 @@ var require_async5 = __commonJS({
|
|
|
6034
6043
|
async static(patterns, options) {
|
|
6035
6044
|
const entries = [];
|
|
6036
6045
|
const stream = this._readerStream.static(patterns, options);
|
|
6037
|
-
return new Promise((
|
|
6046
|
+
return new Promise((resolve7, reject) => {
|
|
6038
6047
|
stream.once("error", reject);
|
|
6039
6048
|
stream.on("data", (entry) => entries.push(entry));
|
|
6040
|
-
stream.once("end", () =>
|
|
6049
|
+
stream.once("end", () => resolve7(entries));
|
|
6041
6050
|
});
|
|
6042
6051
|
}
|
|
6043
6052
|
};
|
|
@@ -6696,7 +6705,7 @@ var require_out4 = __commonJS({
|
|
|
6696
6705
|
|
|
6697
6706
|
// src/detect/source-dir-detector.ts
|
|
6698
6707
|
import { realpathSync } from "fs";
|
|
6699
|
-
import { resolve as
|
|
6708
|
+
import { resolve as resolve4 } from "path";
|
|
6700
6709
|
function extsFor(language) {
|
|
6701
6710
|
return EXTENSIONS[language] ?? [];
|
|
6702
6711
|
}
|
|
@@ -6722,7 +6731,7 @@ function topSegment(rel) {
|
|
|
6722
6731
|
function isInsideRoot(root, candidate) {
|
|
6723
6732
|
try {
|
|
6724
6733
|
const realRoot = realpathSync(root);
|
|
6725
|
-
const realCand = realpathSync(
|
|
6734
|
+
const realCand = realpathSync(resolve4(root, candidate));
|
|
6726
6735
|
return realCand === realRoot || realCand.startsWith(realRoot + "/");
|
|
6727
6736
|
} catch {
|
|
6728
6737
|
return false;
|
|
@@ -6890,25 +6899,25 @@ var init_source_dir_detector = __esm({
|
|
|
6890
6899
|
});
|
|
6891
6900
|
|
|
6892
6901
|
// src/detect/monorepo-detector.ts
|
|
6893
|
-
import { readFileSync as
|
|
6902
|
+
import { readFileSync as readFileSync5, existsSync as existsSync6, statSync as statSync2, lstatSync as lstatSync2, readdirSync as readdirSync2 } from "fs";
|
|
6894
6903
|
import { join as join3, relative as relative2 } from "path";
|
|
6895
6904
|
import { parse as parseYaml2 } from "yaml";
|
|
6896
6905
|
import { parse as parseToml2 } from "smol-toml";
|
|
6897
6906
|
function safeReadText(path) {
|
|
6898
6907
|
try {
|
|
6899
|
-
if (!
|
|
6908
|
+
if (!existsSync6(path)) return null;
|
|
6900
6909
|
const ls = lstatSync2(path);
|
|
6901
6910
|
if (ls.isSymbolicLink()) return null;
|
|
6902
6911
|
const st = statSync2(path);
|
|
6903
6912
|
if (!st.isFile()) return null;
|
|
6904
|
-
return
|
|
6913
|
+
return readFileSync5(path, "utf-8");
|
|
6905
6914
|
} catch {
|
|
6906
6915
|
return null;
|
|
6907
6916
|
}
|
|
6908
6917
|
}
|
|
6909
6918
|
function firstManifestIn(dir) {
|
|
6910
6919
|
for (const m of MANIFEST_PRIORITY) {
|
|
6911
|
-
if (
|
|
6920
|
+
if (existsSync6(join3(dir, m))) return m;
|
|
6912
6921
|
}
|
|
6913
6922
|
return null;
|
|
6914
6923
|
}
|
|
@@ -6973,7 +6982,7 @@ function genericWorkspaces(root) {
|
|
|
6973
6982
|
const out = [];
|
|
6974
6983
|
for (const parent of CONVENTIONAL_WORKSPACE_PARENTS) {
|
|
6975
6984
|
const p = join3(root, parent);
|
|
6976
|
-
if (!
|
|
6985
|
+
if (!existsSync6(p)) continue;
|
|
6977
6986
|
for (const sub of listSubdirs2(p)) {
|
|
6978
6987
|
const pkg = pkgFromDir(root, sub);
|
|
6979
6988
|
if (pkg) out.push(pkg);
|
|
@@ -7014,7 +7023,7 @@ function expandWorkspaceGlobs(root, globs) {
|
|
|
7014
7023
|
const parts = pattern.split("/");
|
|
7015
7024
|
if (parts.length === 2 && (parts[1] === "*" || parts[1] === "**")) {
|
|
7016
7025
|
const parent = join3(root, parts[0]);
|
|
7017
|
-
if (!
|
|
7026
|
+
if (!existsSync6(parent)) continue;
|
|
7018
7027
|
for (const sub of listSubdirs2(parent)) {
|
|
7019
7028
|
const pkg = pkgFromDir(root, sub);
|
|
7020
7029
|
if (pkg && !seen.has(pkg.path)) {
|
|
@@ -7025,7 +7034,7 @@ function expandWorkspaceGlobs(root, globs) {
|
|
|
7025
7034
|
continue;
|
|
7026
7035
|
}
|
|
7027
7036
|
const direct = join3(root, pattern);
|
|
7028
|
-
if (
|
|
7037
|
+
if (existsSync6(direct)) {
|
|
7029
7038
|
const pkg = pkgFromDir(root, direct);
|
|
7030
7039
|
if (pkg && !seen.has(pkg.path)) {
|
|
7031
7040
|
seen.add(pkg.path);
|
|
@@ -7036,16 +7045,16 @@ function expandWorkspaceGlobs(root, globs) {
|
|
|
7036
7045
|
return out;
|
|
7037
7046
|
}
|
|
7038
7047
|
function hasTurbo(root) {
|
|
7039
|
-
return
|
|
7048
|
+
return existsSync6(join3(root, "turbo.json"));
|
|
7040
7049
|
}
|
|
7041
7050
|
function hasNx(root) {
|
|
7042
|
-
return
|
|
7051
|
+
return existsSync6(join3(root, "nx.json"));
|
|
7043
7052
|
}
|
|
7044
7053
|
function hasLerna(root) {
|
|
7045
|
-
return
|
|
7054
|
+
return existsSync6(join3(root, "lerna.json"));
|
|
7046
7055
|
}
|
|
7047
7056
|
function hasBazel(root) {
|
|
7048
|
-
return
|
|
7057
|
+
return existsSync6(join3(root, "WORKSPACE")) || existsSync6(join3(root, "WORKSPACE.bazel")) || existsSync6(join3(root, "MODULE.bazel"));
|
|
7049
7058
|
}
|
|
7050
7059
|
function detectMonorepo(projectRoot) {
|
|
7051
7060
|
const nested = [];
|
|
@@ -7236,7 +7245,7 @@ var init_vr_command_map = __esm({
|
|
|
7236
7245
|
});
|
|
7237
7246
|
|
|
7238
7247
|
// src/detect/domain-inferrer.ts
|
|
7239
|
-
import { existsSync as
|
|
7248
|
+
import { existsSync as existsSync7, readdirSync as readdirSync3 } from "fs";
|
|
7240
7249
|
import { join as join4 } from "path";
|
|
7241
7250
|
function titleCase(s) {
|
|
7242
7251
|
if (!s) return s;
|
|
@@ -7258,7 +7267,7 @@ function topLevelSrcSubdirs(root, sourceDirs) {
|
|
|
7258
7267
|
const seen = /* @__PURE__ */ new Set();
|
|
7259
7268
|
for (const rel of effective) {
|
|
7260
7269
|
const abs = join4(root, rel);
|
|
7261
|
-
if (!
|
|
7270
|
+
if (!existsSync7(abs)) continue;
|
|
7262
7271
|
try {
|
|
7263
7272
|
for (const e of readdirSync3(abs, { withFileTypes: true })) {
|
|
7264
7273
|
if (!e.isDirectory()) continue;
|
|
@@ -7345,8 +7354,8 @@ var init_domain_inferrer = __esm({
|
|
|
7345
7354
|
});
|
|
7346
7355
|
|
|
7347
7356
|
// src/detect/regex-fallback.ts
|
|
7348
|
-
import { existsSync as
|
|
7349
|
-
import { resolve as
|
|
7357
|
+
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync3 } from "fs";
|
|
7358
|
+
import { resolve as resolve5, join as join5, basename as basename2 } from "path";
|
|
7350
7359
|
function introspectPython(detection, projectRoot) {
|
|
7351
7360
|
const sourceDir = resolveSourceDir(detection, "python", projectRoot);
|
|
7352
7361
|
if (!sourceDir) return null;
|
|
@@ -7512,10 +7521,10 @@ function resolveSourceDir(detection, lang, projectRoot) {
|
|
|
7512
7521
|
const list = info?.source_dirs ?? [];
|
|
7513
7522
|
if (list.length > 0) {
|
|
7514
7523
|
const first = list[0];
|
|
7515
|
-
const abs =
|
|
7516
|
-
return
|
|
7524
|
+
const abs = resolve5(projectRoot, first);
|
|
7525
|
+
return existsSync8(abs) ? abs : null;
|
|
7517
7526
|
}
|
|
7518
|
-
return
|
|
7527
|
+
return existsSync8(projectRoot) ? projectRoot : null;
|
|
7519
7528
|
}
|
|
7520
7529
|
function sampleFiles(dir, nameRegex, pathFilter) {
|
|
7521
7530
|
const out = [];
|
|
@@ -7560,7 +7569,7 @@ function readSafe(path) {
|
|
|
7560
7569
|
try {
|
|
7561
7570
|
const st = statSync3(path);
|
|
7562
7571
|
if (st.size > MAX_FILE_BYTES) return null;
|
|
7563
|
-
return
|
|
7572
|
+
return readFileSync6(path, "utf-8");
|
|
7564
7573
|
} catch {
|
|
7565
7574
|
return null;
|
|
7566
7575
|
}
|
|
@@ -7937,12 +7946,12 @@ var init_drift = __esm({
|
|
|
7937
7946
|
// src/memory-db.ts
|
|
7938
7947
|
import Database from "better-sqlite3";
|
|
7939
7948
|
import { dirname as dirname2, basename } from "path";
|
|
7940
|
-
import { existsSync as
|
|
7949
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
7941
7950
|
|
|
7942
7951
|
// src/config.ts
|
|
7943
|
-
import { resolve, dirname } from "path";
|
|
7944
|
-
import { existsSync, readFileSync } from "fs";
|
|
7945
|
-
import { homedir } from "os";
|
|
7952
|
+
import { resolve as resolve2, dirname } from "path";
|
|
7953
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
7954
|
+
import { homedir as homedir2 } from "os";
|
|
7946
7955
|
import { parse as parseYaml } from "yaml";
|
|
7947
7956
|
import { z } from "zod";
|
|
7948
7957
|
|
|
@@ -7951,6 +7960,68 @@ function encodeMemoryDirName(projectRoot) {
|
|
|
7951
7960
|
return projectRoot.replace(/\//g, "-");
|
|
7952
7961
|
}
|
|
7953
7962
|
|
|
7963
|
+
// src/credentials.ts
|
|
7964
|
+
import { homedir } from "os";
|
|
7965
|
+
import { resolve } from "path";
|
|
7966
|
+
import {
|
|
7967
|
+
existsSync,
|
|
7968
|
+
readFileSync,
|
|
7969
|
+
writeFileSync,
|
|
7970
|
+
mkdirSync,
|
|
7971
|
+
rmSync,
|
|
7972
|
+
chmodSync
|
|
7973
|
+
} from "fs";
|
|
7974
|
+
var MASSU_ENV_API_KEY = "MASSU_API_KEY";
|
|
7975
|
+
var MASSU_ENV_CLOUD_ENDPOINT = "MASSU_CLOUD_ENDPOINT";
|
|
7976
|
+
var DEFAULT_CLOUD_ENDPOINT = "https://api.massu.ai/v1";
|
|
7977
|
+
function credentialsDir(home = homedir()) {
|
|
7978
|
+
return resolve(home, ".massu");
|
|
7979
|
+
}
|
|
7980
|
+
function credentialsPath(home = homedir()) {
|
|
7981
|
+
return resolve(credentialsDir(home), "credentials");
|
|
7982
|
+
}
|
|
7983
|
+
function readUserCredentials(home = homedir()) {
|
|
7984
|
+
try {
|
|
7985
|
+
const p = credentialsPath(home);
|
|
7986
|
+
if (!existsSync(p)) return void 0;
|
|
7987
|
+
const parsed = JSON.parse(readFileSync(p, "utf-8"));
|
|
7988
|
+
const key = typeof parsed?.apiKey === "string" ? parsed.apiKey.trim() : "";
|
|
7989
|
+
return key.length > 0 ? key : void 0;
|
|
7990
|
+
} catch {
|
|
7991
|
+
return void 0;
|
|
7992
|
+
}
|
|
7993
|
+
}
|
|
7994
|
+
function isUnresolvedLiteral(v) {
|
|
7995
|
+
return /^\$\{[^}]+\}$/.test(v);
|
|
7996
|
+
}
|
|
7997
|
+
function resolveApiKey(opts = {}) {
|
|
7998
|
+
const env = opts.env ?? process.env;
|
|
7999
|
+
const home = opts.home ?? homedir();
|
|
8000
|
+
const cfg = typeof opts.configApiKey === "string" ? opts.configApiKey.trim() : "";
|
|
8001
|
+
if (cfg.length > 0 && !isUnresolvedLiteral(cfg)) {
|
|
8002
|
+
return { apiKey: cfg, source: "config" };
|
|
8003
|
+
}
|
|
8004
|
+
const envRaw = env[MASSU_ENV_API_KEY];
|
|
8005
|
+
const envKey = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
8006
|
+
if (envKey.length > 0) {
|
|
8007
|
+
return { apiKey: envKey, source: "env" };
|
|
8008
|
+
}
|
|
8009
|
+
const fileKey = readUserCredentials(home);
|
|
8010
|
+
if (fileKey) {
|
|
8011
|
+
return { apiKey: fileKey, source: "user-file" };
|
|
8012
|
+
}
|
|
8013
|
+
return { source: "none" };
|
|
8014
|
+
}
|
|
8015
|
+
function resolveEndpoint(opts = {}) {
|
|
8016
|
+
const env = opts.env ?? process.env;
|
|
8017
|
+
const cfg = typeof opts.configEndpoint === "string" ? opts.configEndpoint.trim() : "";
|
|
8018
|
+
if (cfg.length > 0) return cfg;
|
|
8019
|
+
const envRaw = env[MASSU_ENV_CLOUD_ENDPOINT];
|
|
8020
|
+
const envEp = typeof envRaw === "string" ? envRaw.trim() : "";
|
|
8021
|
+
if (envEp.length > 0) return envEp;
|
|
8022
|
+
return DEFAULT_CLOUD_ENDPOINT;
|
|
8023
|
+
}
|
|
8024
|
+
|
|
7954
8025
|
// src/config.ts
|
|
7955
8026
|
var DomainConfigSchema = z.object({
|
|
7956
8027
|
name: z.string().default("Unknown"),
|
|
@@ -8333,12 +8404,13 @@ var RawConfigSchema = z.object({
|
|
|
8333
8404
|
lsp: LSPConfigSchema.optional()
|
|
8334
8405
|
}).passthrough();
|
|
8335
8406
|
var _config = null;
|
|
8407
|
+
var _resolvedApiKeySource = "none";
|
|
8336
8408
|
var _projectRoot = null;
|
|
8337
8409
|
function findProjectRoot() {
|
|
8338
8410
|
const cwd = process.cwd();
|
|
8339
8411
|
let dir = cwd;
|
|
8340
8412
|
while (true) {
|
|
8341
|
-
if (
|
|
8413
|
+
if (existsSync2(resolve2(dir, "massu.config.yaml"))) {
|
|
8342
8414
|
return dir;
|
|
8343
8415
|
}
|
|
8344
8416
|
const parent = dirname(dir);
|
|
@@ -8347,10 +8419,10 @@ function findProjectRoot() {
|
|
|
8347
8419
|
}
|
|
8348
8420
|
dir = cwd;
|
|
8349
8421
|
while (true) {
|
|
8350
|
-
if (
|
|
8422
|
+
if (existsSync2(resolve2(dir, "package.json"))) {
|
|
8351
8423
|
return dir;
|
|
8352
8424
|
}
|
|
8353
|
-
if (
|
|
8425
|
+
if (existsSync2(resolve2(dir, ".git"))) {
|
|
8354
8426
|
return dir;
|
|
8355
8427
|
}
|
|
8356
8428
|
const parent = dirname(dir);
|
|
@@ -8368,10 +8440,10 @@ function getProjectRoot() {
|
|
|
8368
8440
|
function getConfig() {
|
|
8369
8441
|
if (_config) return _config;
|
|
8370
8442
|
const root = getProjectRoot();
|
|
8371
|
-
const configPath =
|
|
8443
|
+
const configPath = resolve2(root, "massu.config.yaml");
|
|
8372
8444
|
let rawYaml = {};
|
|
8373
|
-
if (
|
|
8374
|
-
const content =
|
|
8445
|
+
if (existsSync2(configPath)) {
|
|
8446
|
+
const content = readFileSync2(configPath, "utf-8");
|
|
8375
8447
|
rawYaml = parseYaml(content) ?? {};
|
|
8376
8448
|
}
|
|
8377
8449
|
const result = RawConfigSchema.safeParse(rawYaml);
|
|
@@ -8388,7 +8460,7 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
8388
8460
|
);
|
|
8389
8461
|
}
|
|
8390
8462
|
const parsed = result.data;
|
|
8391
|
-
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root :
|
|
8463
|
+
const projectRoot = parsed.project.root === "auto" || !parsed.project.root ? root : resolve2(root, parsed.project.root);
|
|
8392
8464
|
const fw = parsed.framework;
|
|
8393
8465
|
let router = fw.router;
|
|
8394
8466
|
let orm = fw.orm;
|
|
@@ -8446,13 +8518,19 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
|
|
|
8446
8518
|
telemetry: parsed.telemetry,
|
|
8447
8519
|
lsp: parsed.lsp
|
|
8448
8520
|
};
|
|
8449
|
-
|
|
8521
|
+
const resolvedKey = resolveApiKey({ configApiKey: _config.cloud?.apiKey });
|
|
8522
|
+
_resolvedApiKeySource = resolvedKey.source;
|
|
8523
|
+
const resolvedEndpoint = resolveEndpoint({ configEndpoint: _config.cloud?.endpoint });
|
|
8524
|
+
if (resolvedKey.apiKey) {
|
|
8450
8525
|
_config.cloud = {
|
|
8451
8526
|
enabled: true,
|
|
8452
8527
|
sync: { memory: true, analytics: true, audit: true },
|
|
8453
8528
|
..._config.cloud,
|
|
8454
|
-
apiKey:
|
|
8529
|
+
apiKey: resolvedKey.apiKey,
|
|
8530
|
+
endpoint: resolvedEndpoint
|
|
8455
8531
|
};
|
|
8532
|
+
} else if (_config.cloud) {
|
|
8533
|
+
_config.cloud = { ..._config.cloud, endpoint: _config.cloud.endpoint ?? resolvedEndpoint };
|
|
8456
8534
|
}
|
|
8457
8535
|
return _config;
|
|
8458
8536
|
}
|
|
@@ -8461,34 +8539,34 @@ function getResolvedPaths() {
|
|
|
8461
8539
|
const root = getProjectRoot();
|
|
8462
8540
|
const claudeDirName = config.conventions?.claudeDirName ?? ".claude";
|
|
8463
8541
|
return {
|
|
8464
|
-
codegraphDbPath:
|
|
8465
|
-
dataDbPath:
|
|
8466
|
-
prismaSchemaPath:
|
|
8467
|
-
rootRouterPath:
|
|
8468
|
-
routersDir:
|
|
8469
|
-
srcDir:
|
|
8542
|
+
codegraphDbPath: resolve2(root, ".codegraph/codegraph.db"),
|
|
8543
|
+
dataDbPath: resolve2(root, ".massu/data.db"),
|
|
8544
|
+
prismaSchemaPath: resolve2(root, config.paths.schema ?? "prisma/schema.prisma"),
|
|
8545
|
+
rootRouterPath: resolve2(root, config.paths.routerRoot ?? "src/server/api/root.ts"),
|
|
8546
|
+
routersDir: resolve2(root, config.paths.routers ?? "src/server/api/routers"),
|
|
8547
|
+
srcDir: resolve2(root, config.paths.source),
|
|
8470
8548
|
pathAlias: Object.fromEntries(
|
|
8471
8549
|
Object.entries(config.paths.aliases).map(([alias, target]) => [
|
|
8472
8550
|
alias,
|
|
8473
|
-
|
|
8551
|
+
resolve2(root, target)
|
|
8474
8552
|
])
|
|
8475
8553
|
),
|
|
8476
8554
|
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
|
8477
8555
|
indexFiles: ["index.ts", "index.tsx", "index.js", "index.jsx"],
|
|
8478
|
-
patternsDir:
|
|
8479
|
-
claudeMdPath:
|
|
8480
|
-
docsMapPath:
|
|
8481
|
-
helpSitePath:
|
|
8482
|
-
memoryDbPath:
|
|
8483
|
-
knowledgeDbPath:
|
|
8484
|
-
plansDir:
|
|
8485
|
-
docsDir:
|
|
8486
|
-
claudeDir:
|
|
8487
|
-
memoryDir:
|
|
8488
|
-
sessionStatePath:
|
|
8489
|
-
sessionArchivePath:
|
|
8490
|
-
mcpJsonPath:
|
|
8491
|
-
settingsLocalPath:
|
|
8556
|
+
patternsDir: resolve2(root, claudeDirName, "patterns"),
|
|
8557
|
+
claudeMdPath: resolve2(root, claudeDirName, "CLAUDE.md"),
|
|
8558
|
+
docsMapPath: resolve2(root, ".massu/docs-map.json"),
|
|
8559
|
+
helpSitePath: resolve2(root, "../" + config.project.name + "-help"),
|
|
8560
|
+
memoryDbPath: resolve2(root, ".massu/memory.db"),
|
|
8561
|
+
knowledgeDbPath: resolve2(root, ".massu/knowledge.db"),
|
|
8562
|
+
plansDir: resolve2(root, "docs/plans"),
|
|
8563
|
+
docsDir: resolve2(root, "docs"),
|
|
8564
|
+
claudeDir: resolve2(root, claudeDirName),
|
|
8565
|
+
memoryDir: resolve2(homedir2(), claudeDirName, "projects", encodeMemoryDirName(root), "memory"),
|
|
8566
|
+
sessionStatePath: resolve2(root, config.conventions?.sessionStatePath ?? `${claudeDirName}/session-state/CURRENT.md`),
|
|
8567
|
+
sessionArchivePath: resolve2(root, config.conventions?.sessionArchivePath ?? `${claudeDirName}/session-state/archive`),
|
|
8568
|
+
mcpJsonPath: resolve2(root, ".mcp.json"),
|
|
8569
|
+
settingsLocalPath: resolve2(root, claudeDirName, "settings.local.json")
|
|
8492
8570
|
};
|
|
8493
8571
|
}
|
|
8494
8572
|
|
|
@@ -8502,8 +8580,8 @@ function sanitizeFts5Query(raw) {
|
|
|
8502
8580
|
function getMemoryDb() {
|
|
8503
8581
|
const dbPath = getResolvedPaths().memoryDbPath;
|
|
8504
8582
|
const dir = dirname2(dbPath);
|
|
8505
|
-
if (!
|
|
8506
|
-
|
|
8583
|
+
if (!existsSync3(dir)) {
|
|
8584
|
+
mkdirSync2(dir, { recursive: true });
|
|
8507
8585
|
}
|
|
8508
8586
|
const db = new Database(dbPath);
|
|
8509
8587
|
db.pragma("journal_mode = WAL");
|
|
@@ -9228,7 +9306,7 @@ function linkSessionToTask(db, sessionId, taskId) {
|
|
|
9228
9306
|
}
|
|
9229
9307
|
|
|
9230
9308
|
// src/team-rule-sync.ts
|
|
9231
|
-
import { existsSync as
|
|
9309
|
+
import { existsSync as existsSync4, writeFileSync as writeFileSync2, unlinkSync, mkdirSync as mkdirSync3 } from "fs";
|
|
9232
9310
|
import { join, dirname as dirname3 } from "path";
|
|
9233
9311
|
|
|
9234
9312
|
// src/license.ts
|
|
@@ -9574,7 +9652,7 @@ async function pullTeamPromotions(db, opts = {}) {
|
|
|
9574
9652
|
result.revoked_handled += 1;
|
|
9575
9653
|
continue;
|
|
9576
9654
|
}
|
|
9577
|
-
if (
|
|
9655
|
+
if (existsSync4(candidatePath) || alreadyApplied(db, p.prompt_hash)) {
|
|
9578
9656
|
result.skipped += 1;
|
|
9579
9657
|
continue;
|
|
9580
9658
|
}
|
|
@@ -9624,7 +9702,7 @@ function alreadyApplied(db, promptHash) {
|
|
|
9624
9702
|
}
|
|
9625
9703
|
}
|
|
9626
9704
|
function handleRevocation(db, projectRoot, candidatePath, promptHash) {
|
|
9627
|
-
if (
|
|
9705
|
+
if (existsSync4(candidatePath)) {
|
|
9628
9706
|
try {
|
|
9629
9707
|
unlinkSync(candidatePath);
|
|
9630
9708
|
} catch {
|
|
@@ -9673,8 +9751,8 @@ function materializeCandidate(db, projectRoot, candidatePath, p, orgId) {
|
|
|
9673
9751
|
...p.review_attestation !== void 0 ? { publisher_review_attestation: p.review_attestation } : {}
|
|
9674
9752
|
};
|
|
9675
9753
|
const dir = dirname3(candidatePath);
|
|
9676
|
-
if (!
|
|
9677
|
-
|
|
9754
|
+
if (!existsSync4(dir)) mkdirSync3(dir, { recursive: true });
|
|
9755
|
+
writeFileSync2(candidatePath, JSON.stringify(sidecar, null, 2), "utf-8");
|
|
9678
9756
|
try {
|
|
9679
9757
|
shareObservation(db, p.promoted_by, getProjectName(), "rule_promotion", promptText, {
|
|
9680
9758
|
filePath: void 0,
|
|
@@ -9718,8 +9796,8 @@ function emitDropTelemetry(db, eventType, data) {
|
|
|
9718
9796
|
}
|
|
9719
9797
|
|
|
9720
9798
|
// src/hooks/session-start.ts
|
|
9721
|
-
import { readFileSync as
|
|
9722
|
-
import { join as join6, resolve as
|
|
9799
|
+
import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
|
|
9800
|
+
import { join as join6, resolve as resolve6 } from "path";
|
|
9723
9801
|
import { parse as parseYaml3 } from "yaml";
|
|
9724
9802
|
|
|
9725
9803
|
// src/lib/pidLiveness.ts
|
|
@@ -9891,7 +9969,7 @@ async function buildContext(db, sessionId, source, tokenBudget, taskId) {
|
|
|
9891
9969
|
}
|
|
9892
9970
|
try {
|
|
9893
9971
|
const knowledgeDbPath = getResolvedPaths().knowledgeDbPath;
|
|
9894
|
-
if (
|
|
9972
|
+
if (existsSync9(knowledgeDbPath)) {
|
|
9895
9973
|
const Database2 = (await import("better-sqlite3")).default;
|
|
9896
9974
|
const kdb = new Database2(knowledgeDbPath, { readonly: true });
|
|
9897
9975
|
try {
|
|
@@ -9967,23 +10045,23 @@ async function getGitBranch() {
|
|
|
9967
10045
|
}
|
|
9968
10046
|
}
|
|
9969
10047
|
function readStdin() {
|
|
9970
|
-
return new Promise((
|
|
10048
|
+
return new Promise((resolve7) => {
|
|
9971
10049
|
let data = "";
|
|
9972
10050
|
process.stdin.setEncoding("utf-8");
|
|
9973
10051
|
process.stdin.on("data", (chunk) => {
|
|
9974
10052
|
data += chunk;
|
|
9975
10053
|
});
|
|
9976
|
-
process.stdin.on("end", () =>
|
|
9977
|
-
setTimeout(() =>
|
|
10054
|
+
process.stdin.on("end", () => resolve7(data));
|
|
10055
|
+
setTimeout(() => resolve7(data), 3e3);
|
|
9978
10056
|
});
|
|
9979
10057
|
}
|
|
9980
10058
|
async function buildDriftBanner() {
|
|
9981
10059
|
try {
|
|
9982
10060
|
if (process.env.MASSU_DRIFT_QUIET === "1") return "";
|
|
9983
10061
|
if (watcherIsLiveAndFresh()) return "";
|
|
9984
|
-
const configPath =
|
|
9985
|
-
if (!
|
|
9986
|
-
const content =
|
|
10062
|
+
const configPath = resolve6(process.cwd(), "massu.config.yaml");
|
|
10063
|
+
if (!existsSync9(configPath)) return "";
|
|
10064
|
+
const content = readFileSync7(configPath, "utf-8");
|
|
9987
10065
|
const parsed = parseYaml3(content);
|
|
9988
10066
|
if (!parsed || typeof parsed !== "object") return "";
|
|
9989
10067
|
const det = parsed.detection;
|
|
@@ -10024,8 +10102,8 @@ function loadCorrectionsPreventionRules() {
|
|
|
10024
10102
|
const claudeDirName = config.conventions?.claudeDirName ?? ".claude";
|
|
10025
10103
|
const projectDirName = cwd.replace(/[/\\]/g, "-").replace(/^-/, "");
|
|
10026
10104
|
const correctionsPath = join6(homeDir, claudeDirName, "projects", projectDirName, "memory", "corrections.md");
|
|
10027
|
-
if (!
|
|
10028
|
-
const content =
|
|
10105
|
+
if (!existsSync9(correctionsPath)) return [];
|
|
10106
|
+
const content = readFileSync7(correctionsPath, "utf-8");
|
|
10029
10107
|
const lines = content.split("\n");
|
|
10030
10108
|
const rules = [];
|
|
10031
10109
|
for (const line of lines) {
|
|
@@ -10046,9 +10124,9 @@ function loadCorrectionsPreventionRules() {
|
|
|
10046
10124
|
}
|
|
10047
10125
|
function readWatchStateRaw(cwd) {
|
|
10048
10126
|
try {
|
|
10049
|
-
const path =
|
|
10050
|
-
if (!
|
|
10051
|
-
const obj = JSON.parse(
|
|
10127
|
+
const path = resolve6(cwd, ".massu", "watch-state.json");
|
|
10128
|
+
if (!existsSync9(path)) return null;
|
|
10129
|
+
const obj = JSON.parse(readFileSync7(path, "utf-8"));
|
|
10052
10130
|
if (!obj || typeof obj !== "object") return null;
|
|
10053
10131
|
return obj;
|
|
10054
10132
|
} catch {
|