@massu/core 2.3.1 → 2.5.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/CHANGELOG.md +131 -0
- package/dist/cli.js +175 -41
- package/dist/hooks/auto-learning-pipeline.js +16 -2
- package/dist/hooks/classify-failure.js +13 -2
- package/dist/hooks/cost-tracker.js +13 -2
- package/dist/hooks/fix-detector.js +13 -2
- package/dist/hooks/incident-pipeline.js +13 -2
- package/dist/hooks/intent-suggester.js +13 -2
- package/dist/hooks/memory-recall.js +13 -2
- package/dist/hooks/post-edit-context.js +13 -2
- package/dist/hooks/post-tool-use.js +13 -2
- package/dist/hooks/pre-compact.js +13 -2
- package/dist/hooks/pre-delete-check.js +13 -2
- package/dist/hooks/pre-tool-use-gate.js +13 -2
- package/dist/hooks/quality-event.js +13 -2
- package/dist/hooks/rule-enforcement-pipeline.js +13 -2
- package/dist/hooks/security-gate.js +13 -2
- package/dist/hooks/session-end.js +13 -2
- package/dist/hooks/session-start.js +22 -7
- package/dist/hooks/user-prompt.js +13 -2
- package/package.json +3 -3
|
@@ -454,6 +454,12 @@ import { join as join2 } from "path";
|
|
|
454
454
|
function resolveDbEngine() {
|
|
455
455
|
return process.env[DB_ENGINE_ENV] === "better-sqlite3" ? "better-sqlite3" : DEFAULT_DB_ENGINE;
|
|
456
456
|
}
|
|
457
|
+
function resolveBusyTimeoutMs() {
|
|
458
|
+
const raw = process.env[DB_BUSY_TIMEOUT_ENV];
|
|
459
|
+
if (raw === void 0 || raw === "") return DEFAULT_BUSY_TIMEOUT_MS;
|
|
460
|
+
const n = Number(raw);
|
|
461
|
+
return Number.isFinite(n) && n >= 0 ? Math.floor(n) : DEFAULT_BUSY_TIMEOUT_MS;
|
|
462
|
+
}
|
|
457
463
|
function nodeSqliteCtor() {
|
|
458
464
|
if (!_nodeCtor) _nodeCtor = req2("node:sqlite").DatabaseSync;
|
|
459
465
|
return _nodeCtor;
|
|
@@ -475,6 +481,7 @@ function openNodeSqlite(dbPath, opts) {
|
|
|
475
481
|
enableForeignKeyConstraints: true,
|
|
476
482
|
allowExtension: false
|
|
477
483
|
});
|
|
484
|
+
raw.exec(`PRAGMA busy_timeout = ${resolveBusyTimeoutMs()}`);
|
|
478
485
|
let savepointSeq = 0;
|
|
479
486
|
const wrapStmt = (sql) => {
|
|
480
487
|
const st = raw.prepare(sql);
|
|
@@ -558,12 +565,14 @@ function openNodeSqlite(dbPath, opts) {
|
|
|
558
565
|
return handle;
|
|
559
566
|
}
|
|
560
567
|
function openBetterSqlite3(dbPath, opts) {
|
|
561
|
-
|
|
568
|
+
const db = openDatabase(dbPath, opts);
|
|
569
|
+
db.exec(`PRAGMA busy_timeout = ${resolveBusyTimeoutMs()}`);
|
|
570
|
+
return db;
|
|
562
571
|
}
|
|
563
572
|
function openDatabase2(dbPath, opts = {}) {
|
|
564
573
|
return resolveDbEngine() === "better-sqlite3" ? openBetterSqlite3(dbPath, opts) : openNodeSqlite(dbPath, opts);
|
|
565
574
|
}
|
|
566
|
-
var req2, DEFAULT_DB_ENGINE, DB_ENGINE_ENV, _nodeCtor;
|
|
575
|
+
var req2, DEFAULT_DB_ENGINE, DB_ENGINE_ENV, DEFAULT_BUSY_TIMEOUT_MS, DB_BUSY_TIMEOUT_ENV, _nodeCtor;
|
|
567
576
|
var init_db_driver = __esm({
|
|
568
577
|
"src/db-driver.ts"() {
|
|
569
578
|
"use strict";
|
|
@@ -572,6 +581,8 @@ var init_db_driver = __esm({
|
|
|
572
581
|
req2 = createRequire2(import.meta.url);
|
|
573
582
|
DEFAULT_DB_ENGINE = "node-sqlite";
|
|
574
583
|
DB_ENGINE_ENV = "MASSU_DB_ENGINE";
|
|
584
|
+
DEFAULT_BUSY_TIMEOUT_MS = 5e3;
|
|
585
|
+
DB_BUSY_TIMEOUT_ENV = "MASSU_DB_BUSY_TIMEOUT_MS";
|
|
575
586
|
_nodeCtor = null;
|
|
576
587
|
}
|
|
577
588
|
});
|
|
@@ -12646,23 +12657,23 @@ function introspectPython(detection, projectRoot) {
|
|
|
12646
12657
|
for (const path of candidates) {
|
|
12647
12658
|
const body = readSafe(path);
|
|
12648
12659
|
if (body === null) continue;
|
|
12649
|
-
const authRegex =
|
|
12660
|
+
const authRegex = new RegExp(PY_AUTH_DEP_PATTERN, "gu");
|
|
12650
12661
|
forEachMatch(authRegex, body, (m) => {
|
|
12651
12662
|
const name = m[1];
|
|
12652
12663
|
if (!authDeps.has(name)) authDeps.set(name, path);
|
|
12653
12664
|
});
|
|
12654
|
-
const djangoAuthRegex =
|
|
12665
|
+
const djangoAuthRegex = new RegExp(PY_DJANGO_AUTH_PATTERN, "gmu");
|
|
12655
12666
|
forEachMatch(djangoAuthRegex, body, (m) => {
|
|
12656
12667
|
const name = m[1];
|
|
12657
12668
|
if (!authDeps.has(name)) authDeps.set(name, path);
|
|
12658
12669
|
});
|
|
12659
|
-
const prefixRegex =
|
|
12670
|
+
const prefixRegex = new RegExp(PY_API_PREFIX_PATTERN, "gu");
|
|
12660
12671
|
forEachMatch(prefixRegex, body, (m) => {
|
|
12661
12672
|
const fullPrefix = m[1];
|
|
12662
12673
|
const base = extractPrefixBase(fullPrefix);
|
|
12663
12674
|
if (base && !prefixBases.has(base)) prefixBases.set(base, path);
|
|
12664
12675
|
});
|
|
12665
|
-
const asyncRegex =
|
|
12676
|
+
const asyncRegex = new RegExp(PY_TEST_ASYNC_PATTERN, "gmu");
|
|
12666
12677
|
forEachMatch(asyncRegex, body, (m) => {
|
|
12667
12678
|
const pat = m[1].trim();
|
|
12668
12679
|
if (!testAsyncPatterns.has(pat)) testAsyncPatterns.set(pat, path);
|
|
@@ -12867,10 +12878,14 @@ function relativeTo(projectRoot, absPath) {
|
|
|
12867
12878
|
}
|
|
12868
12879
|
return basename4(absPath);
|
|
12869
12880
|
}
|
|
12870
|
-
var MAX_FILE_BYTES, MAX_SAMPLES_PER_ADAPTER, MAX_DIR_DEPTH;
|
|
12881
|
+
var PY_AUTH_DEP_PATTERN, PY_DJANGO_AUTH_PATTERN, PY_API_PREFIX_PATTERN, PY_TEST_ASYNC_PATTERN, MAX_FILE_BYTES, MAX_SAMPLES_PER_ADAPTER, MAX_DIR_DEPTH;
|
|
12871
12882
|
var init_regex_fallback = __esm({
|
|
12872
12883
|
"src/detect/regex-fallback.ts"() {
|
|
12873
12884
|
"use strict";
|
|
12885
|
+
PY_AUTH_DEP_PATTERN = String.raw`\bDepends\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)`;
|
|
12886
|
+
PY_DJANGO_AUTH_PATTERN = String.raw`^@\s*([a-z_][a-z0-9_]*(?:_required|_login))\b`;
|
|
12887
|
+
PY_API_PREFIX_PATTERN = String.raw`\bAPIRouter\s*\(\s*[^)]*?prefix\s*=\s*["']([^"']+)["']`;
|
|
12888
|
+
PY_TEST_ASYNC_PATTERN = String.raw`^(@pytest\.mark\.asyncio(?:\s*\([^)]*\))?)`;
|
|
12874
12889
|
MAX_FILE_BYTES = 256 * 1024;
|
|
12875
12890
|
MAX_SAMPLES_PER_ADAPTER = 3;
|
|
12876
12891
|
MAX_DIR_DEPTH = 6;
|
|
@@ -431,6 +431,12 @@ import { join as join2 } from "path";
|
|
|
431
431
|
function resolveDbEngine() {
|
|
432
432
|
return process.env[DB_ENGINE_ENV] === "better-sqlite3" ? "better-sqlite3" : DEFAULT_DB_ENGINE;
|
|
433
433
|
}
|
|
434
|
+
function resolveBusyTimeoutMs() {
|
|
435
|
+
const raw = process.env[DB_BUSY_TIMEOUT_ENV];
|
|
436
|
+
if (raw === void 0 || raw === "") return DEFAULT_BUSY_TIMEOUT_MS;
|
|
437
|
+
const n = Number(raw);
|
|
438
|
+
return Number.isFinite(n) && n >= 0 ? Math.floor(n) : DEFAULT_BUSY_TIMEOUT_MS;
|
|
439
|
+
}
|
|
434
440
|
function nodeSqliteCtor() {
|
|
435
441
|
if (!_nodeCtor) _nodeCtor = req2("node:sqlite").DatabaseSync;
|
|
436
442
|
return _nodeCtor;
|
|
@@ -452,6 +458,7 @@ function openNodeSqlite(dbPath, opts) {
|
|
|
452
458
|
enableForeignKeyConstraints: true,
|
|
453
459
|
allowExtension: false
|
|
454
460
|
});
|
|
461
|
+
raw.exec(`PRAGMA busy_timeout = ${resolveBusyTimeoutMs()}`);
|
|
455
462
|
let savepointSeq = 0;
|
|
456
463
|
const wrapStmt = (sql) => {
|
|
457
464
|
const st = raw.prepare(sql);
|
|
@@ -535,12 +542,14 @@ function openNodeSqlite(dbPath, opts) {
|
|
|
535
542
|
return handle;
|
|
536
543
|
}
|
|
537
544
|
function openBetterSqlite3(dbPath, opts) {
|
|
538
|
-
|
|
545
|
+
const db = openDatabase(dbPath, opts);
|
|
546
|
+
db.exec(`PRAGMA busy_timeout = ${resolveBusyTimeoutMs()}`);
|
|
547
|
+
return db;
|
|
539
548
|
}
|
|
540
549
|
function openDatabase2(dbPath, opts = {}) {
|
|
541
550
|
return resolveDbEngine() === "better-sqlite3" ? openBetterSqlite3(dbPath, opts) : openNodeSqlite(dbPath, opts);
|
|
542
551
|
}
|
|
543
|
-
var req2, DEFAULT_DB_ENGINE, DB_ENGINE_ENV, _nodeCtor;
|
|
552
|
+
var req2, DEFAULT_DB_ENGINE, DB_ENGINE_ENV, DEFAULT_BUSY_TIMEOUT_MS, DB_BUSY_TIMEOUT_ENV, _nodeCtor;
|
|
544
553
|
var init_db_driver = __esm({
|
|
545
554
|
"src/db-driver.ts"() {
|
|
546
555
|
"use strict";
|
|
@@ -549,6 +558,8 @@ var init_db_driver = __esm({
|
|
|
549
558
|
req2 = createRequire2(import.meta.url);
|
|
550
559
|
DEFAULT_DB_ENGINE = "node-sqlite";
|
|
551
560
|
DB_ENGINE_ENV = "MASSU_DB_ENGINE";
|
|
561
|
+
DEFAULT_BUSY_TIMEOUT_MS = 5e3;
|
|
562
|
+
DB_BUSY_TIMEOUT_ENV = "MASSU_DB_BUSY_TIMEOUT_MS";
|
|
552
563
|
_nodeCtor = null;
|
|
553
564
|
}
|
|
554
565
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@massu/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AI Engineering Governance MCP Server - Session memory, knowledge system, feature registry, code intelligence, rule enforcement, tiered tooling (12 free / 73 total), 56 workflow commands, 11 agents, 20+ patterns",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"build:adapter-types": "tsc -p tsconfig.adapter-types.json",
|
|
29
29
|
"build:adapter-subpath": "tsx scripts/bundle-adapters.ts --subpath-only",
|
|
30
30
|
"build:bundle-adapters": "tsx scripts/bundle-adapters.ts",
|
|
31
|
-
"build:cli": "
|
|
32
|
-
"build:hooks": "
|
|
31
|
+
"build:cli": "node scripts/build-bundles.mjs --cli",
|
|
32
|
+
"build:hooks": "node scripts/build-bundles.mjs --hooks",
|
|
33
33
|
"prepublishOnly": "bash ../../scripts/prepublish-check.sh && node ../../scripts/bundle-pubkey.mjs && node ../../scripts/bundle-license-pubkey.mjs && node ../../scripts/bundle-promotion-pubkey.mjs && node ../../scripts/bundle-audit-export-pubkey.mjs && cp ../../CHANGELOG.md ./CHANGELOG.md && npm run build && bash ../../scripts/npm-publish-guard.sh",
|
|
34
34
|
"bench:watch": "tsx test/perf/watch-benchmark.ts",
|
|
35
35
|
"build:owned-sidecars": "node scripts/gen-owned-sidecars.mjs"
|